diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2006-10-06 21:02:56 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2006-10-06 21:02:56 +0000 |
commit | f2984aabfd358ae2731013df5d571a596cb9a5eb (patch) | |
tree | 0b36a098a4b5fcb0d202c68c5a85123e7d95f419 /sys | |
parent | b50063e7723d8a96f3eaeb641e59f7f161dcd917 (diff) |
Preliminary bits for SuperH-based ports, based on NetBSD/sh3 codebase with
minor changes.
Diffstat (limited to 'sys')
86 files changed, 18570 insertions, 0 deletions
diff --git a/sys/arch/sh/conf/files.sh b/sys/arch/sh/conf/files.sh new file mode 100644 index 00000000000..3c45db7852b --- /dev/null +++ b/sys/arch/sh/conf/files.sh @@ -0,0 +1,31 @@ +# $OpenBSD: files.sh,v 1.1 2006/10/06 21:02:55 miod Exp $ +# $NetBSD: files.sh3,v 1.32 2005/12/11 12:18:58 christos Exp $ + +file arch/sh/sh/cache.c +file arch/sh/sh/cache_sh3.c sh3 +file arch/sh/sh/cache_sh4.c sh4 +file arch/sh/sh/clock.c +file arch/sh/sh/db_disasm.c ddb +file arch/sh/sh/db_interface.c ddb +file arch/sh/sh/db_memrw.c ddb +file arch/sh/sh/db_trace.c ddb +file arch/sh/sh/devreg.c sh3 & sh4 +file arch/sh/sh/interrupt.c +file arch/sh/sh/locore_c.c +file arch/sh/sh/locore_subr.S +file arch/sh/sh/mem.c +file arch/sh/sh/mmu.c +file arch/sh/sh/mmu_sh3.c sh3 +file arch/sh/sh/mmu_sh4.c sh4 +file arch/sh/sh/pmap.c +file arch/sh/sh/process_machdep.c +file arch/sh/sh/sh_machdep.c +file arch/sh/sh/sys_machdep.c +file arch/sh/sh/trap.c +file arch/sh/sh/vectors.S +file arch/sh/sh/vm_machdep.c + +file arch/sh/sh/in_cksum.S inet +file netinet/in4_cksum.c inet + +file dev/cninit.c diff --git a/sys/arch/sh/conf/files.shb b/sys/arch/sh/conf/files.shb new file mode 100644 index 00000000000..13537c21ccc --- /dev/null +++ b/sys/arch/sh/conf/files.shb @@ -0,0 +1,13 @@ +# $OpenBSD: files.shb,v 1.1.1.1 2006/10/06 21:02:55 miod Exp $ +# $NetBSD: files.shb,v 1.4 2005/12/11 12:18:58 christos Exp $ +# +# SuperH internal devices. +# +device shb { } +attach shb at mainbus + +file arch/sh/dev/shb.c shb + +device scif: tty +attach scif at shb +file arch/sh/dev/scif.c scif needs-flag diff --git a/sys/arch/sh/conf/files.shpcic b/sys/arch/sh/conf/files.shpcic new file mode 100644 index 00000000000..054f7d9b611 --- /dev/null +++ b/sys/arch/sh/conf/files.shpcic @@ -0,0 +1,10 @@ +# $OpenBSD: files.shpcic,v 1.1 2006/10/06 21:02:55 miod Exp $ +# $NetBSD: files.shpcic,v 1.2 2005/12/11 12:18:58 christos Exp $ + +# +# SH7751{,R} integrated PCI controller +# +device shpcic: pcibus +attach shpcic at mainbus + +file arch/sh/dev/shpcic.c sh4 & shpcic diff --git a/sys/arch/sh/dev/pcicreg.h b/sys/arch/sh/dev/pcicreg.h new file mode 100644 index 00000000000..f4ed0e3c75d --- /dev/null +++ b/sys/arch/sh/dev/pcicreg.h @@ -0,0 +1,141 @@ +/* $OpenBSD: pcicreg.h,v 1.1.1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: pcicreg.h,v 1.2 2005/12/11 12:18:58 christos Exp $ */ + +/*- + * Copyright (c) 2005 NONAKA Kimihiro + * 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. + * + * 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. + */ + +#include <sh/devreg.h> + +/* + * PCI Controller + */ + +#define SH4_PCIC 0xfe200000 + +#define SH4_PCIC_IO 0xfe240000 +#define SH4_PCIC_IO_SIZE 0x00040000 +#define SH4_PCIC_IO_MASK (SH4_PCIC_IO_SIZE-1) +#define SH4_PCIC_MEM 0xfd000000 +#define SH4_PCIC_MEM_SIZE 0x01000000 +#define SH4_PCIC_MEM_MASK (SH4_PCIC_MEM_SIZE-1) + +#define SH4_PCICONF (SH4_PCIC+0x000) /* 32bit */ +#define SH4_PCICONF0 (SH4_PCICONF+0x00) /* 32bit */ +#define SH4_PCICONF1 (SH4_PCICONF+0x04) /* 32bit */ +#define SH4_PCICONF2 (SH4_PCICONF+0x08) /* 32bit */ +#define SH4_PCICONF3 (SH4_PCICONF+0x0c) /* 32bit */ +#define SH4_PCICONF4 (SH4_PCICONF+0x10) /* 32bit */ +#define SH4_PCICONF5 (SH4_PCICONF+0x14) /* 32bit */ +#define SH4_PCICONF6 (SH4_PCICONF+0x18) /* 32bit */ +#define SH4_PCICONF7 (SH4_PCICONF+0x1c) /* 32bit */ +#define SH4_PCICONF8 (SH4_PCICONF+0x20) /* 32bit */ +#define SH4_PCICONF9 (SH4_PCICONF+0x24) /* 32bit */ +#define SH4_PCICONF10 (SH4_PCICONF+0x28) /* 32bit */ +#define SH4_PCICONF11 (SH4_PCICONF+0x2c) /* 32bit */ +#define SH4_PCICONF12 (SH4_PCICONF+0x30) /* 32bit */ +#define SH4_PCICONF13 (SH4_PCICONF+0x34) /* 32bit */ +#define SH4_PCICONF14 (SH4_PCICONF+0x38) /* 32bit */ +#define SH4_PCICONF15 (SH4_PCICONF+0x3c) /* 32bit */ +#define SH4_PCICONF16 (SH4_PCICONF+0x40) /* 32bit */ +#define SH4_PCICONF17 (SH4_PCICONF+0x44) /* 32bit */ +#define SH4_PCICR (SH4_PCIC+0x100) /* 32bit */ +#define SH4_PCILSR0 (SH4_PCIC+0x104) /* 32bit */ +#define SH4_PCILSR1 (SH4_PCIC+0x108) /* 32bit */ +#define SH4_PCILAR0 (SH4_PCIC+0x10c) /* 32bit */ +#define SH4_PCILAR1 (SH4_PCIC+0x110) /* 32bit */ +#define SH4_PCIINT (SH4_PCIC+0x114) /* 32bit */ +#define SH4_PCIINTM (SH4_PCIC+0x118) /* 32bit */ +#define SH4_PCIALR (SH4_PCIC+0x11c) /* 32bit */ +#define SH4_PCICLR (SH4_PCIC+0x120) /* 32bit */ +#define SH4_PCIAINT (SH4_PCIC+0x130) /* 32bit */ +#define SH4_PCIAINTM (SH4_PCIC+0x134) /* 32bit */ +#define SH4_PCIDMABT (SH4_PCIC+0x140) /* 32bit */ +#define SH4_PCIDPA0 (SH4_PCIC+0x180) /* 32bit */ +#define SH4_PCIDLA0 (SH4_PCIC+0x184) /* 32bit */ +#define SH4_PCIDTC0 (SH4_PCIC+0x188) /* 32bit */ +#define SH4_PCIDCR0 (SH4_PCIC+0x18c) /* 32bit */ +#define SH4_PCIDPA1 (SH4_PCIC+0x190) /* 32bit */ +#define SH4_PCIDLA1 (SH4_PCIC+0x194) /* 32bit */ +#define SH4_PCIDTC1 (SH4_PCIC+0x198) /* 32bit */ +#define SH4_PCIDCR1 (SH4_PCIC+0x19c) /* 32bit */ +#define SH4_PCIDPA2 (SH4_PCIC+0x1a0) /* 32bit */ +#define SH4_PCIDLA2 (SH4_PCIC+0x1a4) /* 32bit */ +#define SH4_PCIDTC2 (SH4_PCIC+0x1a8) /* 32bit */ +#define SH4_PCIDCR2 (SH4_PCIC+0x1ac) /* 32bit */ +#define SH4_PCIDPA3 (SH4_PCIC+0x1b0) /* 32bit */ +#define SH4_PCIDLA3 (SH4_PCIC+0x1b4) /* 32bit */ +#define SH4_PCIDTC3 (SH4_PCIC+0x1b8) /* 32bit */ +#define SH4_PCIDCR3 (SH4_PCIC+0x1bc) /* 32bit */ +#define SH4_PCIPAR (SH4_PCIC+0x1c0) /* 32bit */ +#define SH4_PCIMBR (SH4_PCIC+0x1c4) /* 32bit */ +#define SH4_PCIIOBR (SH4_PCIC+0x1c8) /* 32bit */ +#define SH4_PCIPINT (SH4_PCIC+0x1cc) /* 32bit */ +#define SH4_PCIPINTM (SH4_PCIC+0x1d0) /* 32bit */ +#define SH4_PCICLKR (SH4_PCIC+0x1d4) /* 32bit */ +#define SH4_PCIBCR1 (SH4_PCIC+0x1e0) /* 32bit */ +#define SH4_PCIBCR2 (SH4_PCIC+0x1e4) /* 32bit */ +#define SH4_PCIWCR1 (SH4_PCIC+0x1e8) /* 32bit */ +#define SH4_PCIWCR2 (SH4_PCIC+0x1ec) /* 32bit */ +#define SH4_PCIWCR3 (SH4_PCIC+0x1f0) /* 32bit */ +#define SH4_PCIMCR (SH4_PCIC+0x1f4) /* 32bit */ +#define SH4_PCIBCR3 (SH4_PCIC+0x1f8) /* 32bit: SH7751R */ +#define SH4_PCIPCTR (SH4_PCIC+0x200) /* 32bit */ +#define SH4_PCIPDTR (SH4_PCIC+0x204) /* 32bit */ +#define SH4_PCIPDR (SH4_PCIC+0x220) /* 32bit */ + +#define PCICR_BASE 0xa5000000 +#define PCICR_TRDSGL 0x00000200 +#define PCICR_BYTESWAP 0x00000100 +#define PCICR_PCIPUP 0x00000080 +#define PCICR_BMABT 0x00000040 +#define PCICR_MD10 0x00000020 +#define PCICR_MD9 0x00000010 +#define PCICR_SERR 0x00000008 +#define PCICR_INTA 0x00000004 +#define PCICR_RSTCTL 0x00000002 +#define PCICR_CFINIT 0x00000001 + +#define PCIINT_M_LOCKON 0x00008000 +#define PCIINT_T_TGT_ABORT 0x00004000 +#define PCIINT_TGT_RETRY 0x00000200 +#define PCIINT_MST_DIS 0x00000100 +#define PCIINT_ADRPERR 0x00000080 +#define PCIINT_SERR_DET 0x00000040 +#define PCIINT_T_DPERR_WT 0x00000020 +#define PCIINT_T_PERR_DET 0x00000010 +#define PCIINT_M_TGT_ABORT 0x00000008 +#define PCIINT_M_MST_ABORT 0x00000004 +#define PCIINT_M_DPERR_WT 0x00000002 +#define PCIINT_M_DPERR_RD 0x00000001 +#define PCIINT_ALL 0x0000c3ff +#define PCIINT_CLEAR_ALL PCIINT_ALL + +#define PCIINTM_MASK_ALL 0x00000000 +#define PCIINTM_UNMASK_ALL PCIINT_ALL + +#define PCIMBR_MASK 0xff000000 + +#define PCIIOBR_MASK 0xffc00000 diff --git a/sys/arch/sh/dev/scif.c b/sys/arch/sh/dev/scif.c new file mode 100644 index 00000000000..c2449a8cbd4 --- /dev/null +++ b/sys/arch/sh/dev/scif.c @@ -0,0 +1,1398 @@ +/* $OpenBSD: scif.c,v 1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: scif.c,v 1.47 2006/07/23 22:06:06 ad Exp $ */ + +/*- + * Copyright (C) 1999 T.Horiuchi and SAITOH Masanobu. 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. 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. + */ + +/*- + * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Charles M. Hannum. + * + * 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) 1991 The Regents of the University of California. + * 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. 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. + * + * @(#)com.c 7.5 (Berkeley) 5/16/91 + */ + +/* + * SH internal serial driver + * + * This code is derived from both z8530tty.c and com.c + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/tty.h> +#include <sys/proc.h> +#include <sys/conf.h> +#include <sys/file.h> +#include <sys/syslog.h> +#include <sys/kernel.h> +#include <sys/device.h> +#include <sys/malloc.h> +#include <sys/timeout.h> + +#include <dev/cons.h> + +#include <sh/clock.h> +#include <sh/trap.h> +#include <machine/intr.h> + +#include <sh/dev/scifreg.h> + +#ifdef DDB +#include <ddb/db_var.h> +#endif + +void scifstart(struct tty *); +int scifparam(struct tty *, struct termios *); + +void scifcnprobe(struct consdev *); +void scifcninit(struct consdev *); +void scifcnputc(dev_t, int); +int scifcngetc(dev_t); +void scifcnpoolc(dev_t, int); +void scif_intr_init(void); +int scifintr(void *); + +struct scif_softc { + struct device sc_dev; /* boilerplate */ + struct tty *sc_tty; + void *sc_si; + + struct timeout sc_diag_tmo; + +#if 0 + bus_space_tag_t sc_iot; /* ISA i/o space identifier */ + bus_space_handle_t sc_ioh; /* ISA io handle */ + + int sc_drq; + + int sc_frequency; +#endif + + u_int sc_overflows, + sc_floods, + sc_errors; /* number of retries so far */ + u_char sc_status[7]; /* copy of registers */ + + int sc_hwflags; + int sc_swflags; + u_int sc_fifolen; + + u_int sc_r_hiwat, + sc_r_lowat; + u_char *volatile sc_rbget, + *volatile sc_rbput; + volatile u_int sc_rbavail; + u_char *sc_rbuf, + *sc_ebuf; + + u_char *sc_tba; /* transmit buffer address */ + u_int sc_tbc, /* transmit byte count */ + sc_heldtbc; + + volatile u_char sc_rx_flags, +#define RX_TTY_BLOCKED 0x01 +#define RX_TTY_OVERFLOWED 0x02 +#define RX_IBUF_BLOCKED 0x04 +#define RX_IBUF_OVERFLOWED 0x08 +#define RX_ANY_BLOCK 0x0f + sc_tx_busy, /* working on an output chunk */ + sc_tx_done, /* done with one output chunk */ + sc_tx_stopped, /* H/W level stop (lost CTS) */ + sc_st_check, /* got a status interrupt */ + sc_rx_ready; + + volatile u_char sc_heldchange; +}; + +/* controller driver configuration */ +int scif_match(struct device *, void *, void *); +void scif_attach(struct device *, struct device *, void *); + +void scif_break(struct scif_softc *, int); +void scif_iflush(struct scif_softc *); + +void scifsoft(void *); +void scif_rxsoft(struct scif_softc *, struct tty *); +void scif_txsoft(struct scif_softc *, struct tty *); +void scif_stsoft(struct scif_softc *, struct tty *); +void scif_schedrx(struct scif_softc *); +void scifdiag(void *); + + +#define SCIFUNIT_MASK 0x7ffff +#define SCIFDIALOUT_MASK 0x80000 + +#define SCIFUNIT(x) (minor(x) & SCIFUNIT_MASK) +#define SCIFDIALOUT(x) (minor(x) & SCIFDIALOUT_MASK) + +/* Hardware flag masks */ +#define SCIF_HW_NOIEN 0x01 +#define SCIF_HW_FIFO 0x02 +#define SCIF_HW_FLOW 0x08 +#define SCIF_HW_DEV_OK 0x20 +#define SCIF_HW_CONSOLE 0x40 + +/* Buffer size for character buffer */ +#define SCIF_RING_SIZE 2048 + +/* Stop input when 3/4 of the ring is full; restart when only 1/4 is full. */ +u_int scif_rbuf_hiwat = (SCIF_RING_SIZE * 1) / 4; +u_int scif_rbuf_lowat = (SCIF_RING_SIZE * 3) / 4; + +#define CONMODE ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8) /* 8N1 */ +int scifconscflag = CONMODE; +int scifisconsole = 0; + +#ifdef SCIFCN_SPEED +unsigned int scifcn_speed = SCIFCN_SPEED; +#else +unsigned int scifcn_speed = 9600; +#endif + +#define divrnd(n, q) (((n)*2/(q)+1)/2) /* divide and round off */ + +u_int scif_rbuf_size = SCIF_RING_SIZE; + +struct cfattach scif_ca = { + sizeof(struct scif_softc), scif_match, scif_attach +}; + +struct cfdriver scif_cd = { + 0, "scif", DV_DULL +}; + +static int scif_attached; + +cdev_decl(scif); + +void InitializeScif(unsigned int); + +/* + * following functions are debugging prupose only + */ +#define CR 0x0D +#define USART_ON (unsigned int)~0x08 + +void scif_putc(unsigned char); +unsigned char scif_getc(void); +int ScifErrCheck(void); + + +/* XXX: uwe + * Prepare for bus_spacification. The difference in access widths is + * still handled by the magic definitions in scifreg.h + */ +#define scif_smr_read() SHREG_SCSMR2 +#define scif_smr_write(v) (SHREG_SCSMR2 = (v)) + +#define scif_brr_read() SHREG_SCBRR2 +#define scif_brr_write(v) (SHREG_SCBRR2 = (v)) + +#define scif_scr_read() SHREG_SCSCR2 +#define scif_scr_write(v) (SHREG_SCSCR2 = (v)) + +#define scif_ftdr_write(v) (SHREG_SCFTDR2 = (v)) + +#define scif_ssr_read() SHREG_SCSSR2 +#define scif_ssr_write(v) (SHREG_SCSSR2 = (v)) + +#define scif_frdr_read() SHREG_SCFRDR2 + +#define scif_fcr_read() SHREG_SCFCR2 +#define scif_fcr_write(v) (SHREG_SCFCR2 = (v)) + +#define scif_fdr_read() SHREG_SCFDR2 + +#ifdef SH4 /* additional registers in sh4 */ + +#define scif_sptr_read() SHREG_SCSPTR2 +#define scif_sptr_write(v) (SHREG_SCSPTR2 = (v)) + +#define scif_lsr_read() SHREG_SCLSR2 +#define scif_lsr_write(v) (SHREG_SCLSR2 = (v)) + +#endif /* SH4 */ + + +/* + * InitializeScif + * : unsigned int bps; + * : SCIF(Serial Communication Interface) + */ + +void +InitializeScif(unsigned int bps) +{ + /* Initialize SCR */ + scif_scr_write(0x00); + +#if 0 + scif_fcr_write(SCFCR2_TFRST | SCFCR2_RFRST | SCFCR2_MCE); +#else + scif_fcr_write(SCFCR2_TFRST | SCFCR2_RFRST); +#endif + /* Serial Mode Register */ + scif_smr_write(0x00); /* 8bit,NonParity,Even,1Stop */ + + /* Bit Rate Register */ + scif_brr_write(divrnd(sh_clock_get_pclock(), 32 * bps) - 1); + + /* + * wait 2m Sec, because Send/Recv must begin 1 bit period after + * BRR is set. + */ + delay(2000); + +#if 0 + scif_fcr_write(FIFO_RCV_TRIGGER_14 | FIFO_XMT_TRIGGER_1 | SCFCR2_MCE); +#else + scif_fcr_write(FIFO_RCV_TRIGGER_14 | FIFO_XMT_TRIGGER_1); +#endif + + /* Send permission, Receive permission ON */ + scif_scr_write(SCSCR2_TE | SCSCR2_RE); + + /* Serial Status Register */ + scif_ssr_write(scif_ssr_read() & SCSSR2_TDFE); /* Clear Status */ +} + + +/* + * scif_putc + * : unsigned char c; + */ + +void +scif_putc(unsigned char c) +{ + /* wait for ready */ + while ((scif_fdr_read() & SCFDR2_TXCNT) == SCFDR2_TXF_FULL) + continue; + + /* write send data to send register */ + scif_ftdr_write(c); + + /* clear ready flag */ + scif_ssr_write(scif_ssr_read() & ~(SCSSR2_TDFE | SCSSR2_TEND)); +} + +/* + * : ScifErrCheck + * 0x80 = error + * 0x08 = frame error + * 0x04 = parity error + */ +int +ScifErrCheck(void) +{ + return (scif_ssr_read() & (SCSSR2_ER | SCSSR2_FER | SCSSR2_PER)); +} + +/* + * scif_getc + */ +unsigned char +scif_getc(void) +{ + unsigned char c, err_c; +#ifdef SH4 + unsigned short err_c2 = 0; /* XXXGCC: -Wuninitialized */ +#endif + + for (;;) { + /* wait for ready */ + while ((scif_fdr_read() & SCFDR2_RECVCNT) == 0) + continue; + + c = scif_frdr_read(); + err_c = scif_ssr_read(); + scif_ssr_write(scif_ssr_read() + & ~(SCSSR2_ER | SCSSR2_BRK | SCSSR2_RDF | SCSSR2_DR)); +#ifdef SH4 + if (CPU_IS_SH4) { + err_c2 = scif_lsr_read(); + scif_lsr_write(scif_lsr_read() & ~SCLSR2_ORER); + } +#endif + if ((err_c & (SCSSR2_ER | SCSSR2_BRK | SCSSR2_FER + | SCSSR2_PER)) == 0) { +#ifdef SH4 + if (CPU_IS_SH4 && ((err_c2 & SCLSR2_ORER) == 0)) +#endif + return(c); + } + } + +} + +int +scif_match(struct device *parent, void *vcf, void *aux) +{ + if (scif_attached != 0) + return 0; + + return 1; +} + +void +scif_attach(struct device *parent, struct device *self, void *aux) +{ + struct scif_softc *sc = (struct scif_softc *)self; + struct tty *tp; + + scif_attached = 1; + + sc->sc_hwflags = 0; /* XXX */ + sc->sc_swflags = 0; /* XXX */ + sc->sc_fifolen = 16; + + if (scifisconsole) { + /* InitializeScif(scifcn_speed); */ + SET(sc->sc_hwflags, SCIF_HW_CONSOLE); + SET(sc->sc_swflags, TIOCFLAG_SOFTCAR); + printf("\n%s: console\n", sc->sc_dev.dv_xname); + } else { + InitializeScif(9600); + printf("\n"); + } + + timeout_set(&sc->sc_diag_tmo, scifdiag, sc); +#ifdef SH4 + intc_intr_establish(SH4_INTEVT_SCIF_ERI, IST_LEVEL, IPL_SERIAL, + scifintr, sc, self->dv_xname); + intc_intr_establish(SH4_INTEVT_SCIF_RXI, IST_LEVEL, IPL_SERIAL, + scifintr, sc, self->dv_xname); + intc_intr_establish(SH4_INTEVT_SCIF_BRI, IST_LEVEL, IPL_SERIAL, + scifintr, sc, self->dv_xname); + intc_intr_establish(SH4_INTEVT_SCIF_TXI, IST_LEVEL, IPL_SERIAL, + scifintr, sc, self->dv_xname); +#else + intc_intr_establish(SH7709_INTEVT2_SCIF_ERI, IST_LEVEL, IPL_SERIAL, + scifintr, sc, self->dv_xname); + intc_intr_establish(SH7709_INTEVT2_SCIF_RXI, IST_LEVEL, IPL_SERIAL, + scifintr, sc, self->dv_xname); + intc_intr_establish(SH7709_INTEVT2_SCIF_BRI, IST_LEVEL, IPL_SERIAL, + scifintr, sc, self->dv_xname); + intc_intr_establish(SH7709_INTEVT2_SCIF_TXI, IST_LEVEL, IPL_SERIAL, + scifintr, sc, self->dv_xname); +#endif + + sc->sc_si = softintr_establish(IPL_SOFTSERIAL, scifsoft, sc); + SET(sc->sc_hwflags, SCIF_HW_DEV_OK); + + tp = ttymalloc(); + tp->t_oproc = scifstart; + tp->t_param = scifparam; + tp->t_hwiflow = NULL; + + sc->sc_tty = tp; + sc->sc_rbuf = malloc(scif_rbuf_size << 1, M_DEVBUF, M_NOWAIT); + if (sc->sc_rbuf == NULL) { + printf("%s: unable to allocate ring buffer\n", + sc->sc_dev.dv_xname); + return; + } + sc->sc_ebuf = sc->sc_rbuf + (scif_rbuf_size << 1); +} + +/* + * Start or restart transmission. + */ +void +scifstart(struct tty *tp) +{ + struct scif_softc *sc = scif_cd.cd_devs[SCIFUNIT(tp->t_dev)]; + int s; + + s = spltty(); + if (ISSET(tp->t_state, TS_BUSY | TS_TIMEOUT | TS_TTSTOP)) + goto out; + if (sc->sc_tx_stopped) + goto out; + + if (tp->t_outq.c_cc <= tp->t_lowat) { + if (ISSET(tp->t_state, TS_ASLEEP)) { + CLR(tp->t_state, TS_ASLEEP); + wakeup(&tp->t_outq); + } + selwakeup(&tp->t_wsel); + if (tp->t_outq.c_cc == 0) + goto out; + } + + /* Grab the first contiguous region of buffer space. */ + { + u_char *tba; + int tbc; + + tba = tp->t_outq.c_cf; + tbc = ndqb(&tp->t_outq, 0); + + (void)splserial(); + + sc->sc_tba = tba; + sc->sc_tbc = tbc; + } + + SET(tp->t_state, TS_BUSY); + sc->sc_tx_busy = 1; + + /* Enable transmit completion interrupts if necessary. */ + scif_scr_write(scif_scr_read() | SCSCR2_TIE | SCSCR2_RIE); + + /* Output the first chunk of the contiguous buffer. */ + { + int n; + int maxchars; + int i; + + n = sc->sc_tbc; + maxchars = sc->sc_fifolen + - ((scif_fdr_read() & SCFDR2_TXCNT) >> 8); + if (n > maxchars) + n = maxchars; + + for (i = 0; i < n; i++) { + scif_putc(*(sc->sc_tba)); + sc->sc_tba++; + } + sc->sc_tbc -= n; + } +out: + splx(s); + return; +} + +/* + * Set SCIF tty parameters from termios. + * XXX - Should just copy the whole termios after + * making sure all the changes could be done. + */ +int +scifparam(struct tty *tp, struct termios *t) +{ + struct scif_softc *sc = scif_cd.cd_devs[SCIFUNIT(tp->t_dev)]; + int ospeed = t->c_ospeed; + int s; + + /* Check requested parameters. */ + if (ospeed < 0) + return (EINVAL); + if (t->c_ispeed && t->c_ispeed != t->c_ospeed) + return (EINVAL); + + /* + * For the console, always force CLOCAL and !HUPCL, so that the port + * is always active. + */ + if (ISSET(sc->sc_swflags, TIOCFLAG_SOFTCAR) || + ISSET(sc->sc_hwflags, SCIF_HW_CONSOLE)) { + SET(t->c_cflag, CLOCAL); + CLR(t->c_cflag, HUPCL); + } + + /* + * If there were no changes, don't do anything. This avoids dropping + * input and improves performance when all we did was frob things like + * VMIN and VTIME. + */ + if (tp->t_ospeed == t->c_ospeed && + tp->t_cflag == t->c_cflag) + return (0); + +#if 0 +/* XXX (msaitoh) */ + lcr = ISSET(sc->sc_lcr, LCR_SBREAK) | cflag2lcr(t->c_cflag); +#endif + + s = splserial(); + + /* + * Set the flow control pins depending on the current flow control + * mode. + */ + if (ISSET(t->c_cflag, CRTSCTS)) { + scif_fcr_write(scif_fcr_read() | SCFCR2_MCE); + } else { + scif_fcr_write(scif_fcr_read() & ~SCFCR2_MCE); + } + + scif_brr_write(divrnd(sh_clock_get_pclock(), 32 * ospeed) -1); + + /* + * Set the FIFO threshold based on the receive speed. + * + * * If it's a low speed, it's probably a mouse or some other + * interactive device, so set the threshold low. + * * If it's a high speed, trim the trigger level down to prevent + * overflows. + * * Otherwise set it a bit higher. + */ +#if 0 +/* XXX (msaitoh) */ + if (ISSET(sc->sc_hwflags, SCIF_HW_HAYESP)) + sc->sc_fifo = FIFO_DMA_MODE | FIFO_ENABLE | FIFO_TRIGGER_8; + else if (ISSET(sc->sc_hwflags, SCIF_HW_FIFO)) + sc->sc_fifo = FIFO_ENABLE | + (t->c_ospeed <= 1200 ? FIFO_TRIGGER_1 : + t->c_ospeed <= 38400 ? FIFO_TRIGGER_8 : FIFO_TRIGGER_4); + else + sc->sc_fifo = 0; +#endif + + /* And copy to tty. */ + tp->t_ispeed = 0; + tp->t_ospeed = t->c_ospeed; + tp->t_cflag = t->c_cflag; + + if (!sc->sc_heldchange) { + if (sc->sc_tx_busy) { + sc->sc_heldtbc = sc->sc_tbc; + sc->sc_tbc = 0; + sc->sc_heldchange = 1; + } +#if 0 +/* XXX (msaitoh) */ + else + scif_loadchannelregs(sc); +#endif + } + + if (!ISSET(t->c_cflag, CHWFLOW)) { + /* Disable the high water mark. */ + sc->sc_r_hiwat = 0; + sc->sc_r_lowat = 0; + if (ISSET(sc->sc_rx_flags, RX_TTY_OVERFLOWED)) { + CLR(sc->sc_rx_flags, RX_TTY_OVERFLOWED); + scif_schedrx(sc); + } + } else { + sc->sc_r_hiwat = scif_rbuf_hiwat; + sc->sc_r_lowat = scif_rbuf_lowat; + } + + splx(s); + +#ifdef SCIF_DEBUG + if (scif_debug) + scifstatus(sc, "scifparam "); +#endif + + if (!ISSET(t->c_cflag, CHWFLOW)) { + if (sc->sc_tx_stopped) { + sc->sc_tx_stopped = 0; + scifstart(tp); + } + } + + return (0); +} + +void +scif_iflush(struct scif_softc *sc) +{ + int i; + unsigned char c; + + i = scif_fdr_read() & SCFDR2_RECVCNT; + + while (i > 0) { + c = scif_frdr_read(); + scif_ssr_write(scif_ssr_read() & ~(SCSSR2_RDF | SCSSR2_DR)); + i--; + } +} + +int +scifopen(dev_t dev, int flag, int mode, struct proc *p) +{ + int unit = SCIFUNIT(dev); + struct scif_softc *sc; + struct tty *tp; + int s, s2; + int error; + + if (unit >= scif_cd.cd_ndevs) + return (ENXIO); + sc = scif_cd.cd_devs[unit]; + if (sc == 0 || !ISSET(sc->sc_hwflags, SCIF_HW_DEV_OK) || + sc->sc_rbuf == NULL) + return (ENXIO); + + tp = sc->sc_tty; + + if (ISSET(tp->t_state, TS_ISOPEN) && + ISSET(tp->t_state, TS_XCLUDE) && + p->p_ucred->cr_uid != 0) + return (EBUSY); + + s = spltty(); + + /* + * Do the following iff this is a first open. + */ + if (!ISSET(tp->t_state, TS_ISOPEN)) { + struct termios t; + + tp->t_dev = dev; + + s2 = splserial(); + + /* Turn on interrupts. */ + scif_scr_write(scif_scr_read() | SCSCR2_TIE | SCSCR2_RIE); + + splx(s2); + + /* + * Initialize the termios status to the defaults. Add in the + * sticky bits from TIOCSFLAGS. + */ + t.c_ispeed = 0; + if (ISSET(sc->sc_hwflags, SCIF_HW_CONSOLE)) { + t.c_ospeed = scifcn_speed; /* XXX (msaitoh) */ + t.c_cflag = scifconscflag; + } else { + t.c_ospeed = TTYDEF_SPEED; + t.c_cflag = TTYDEF_CFLAG; + } + if (ISSET(sc->sc_swflags, TIOCFLAG_CLOCAL)) + SET(t.c_cflag, CLOCAL); + if (ISSET(sc->sc_swflags, TIOCFLAG_CRTSCTS)) + SET(t.c_cflag, CRTSCTS); + if (ISSET(sc->sc_swflags, TIOCFLAG_MDMBUF)) + SET(t.c_cflag, MDMBUF); + /* Make sure scifparam() will do something. */ + tp->t_ospeed = 0; + (void) scifparam(tp, &t); + tp->t_iflag = TTYDEF_IFLAG; + tp->t_oflag = TTYDEF_OFLAG; + tp->t_lflag = TTYDEF_LFLAG; + ttychars(tp); + ttsetwater(tp); + + s2 = splserial(); + + /* Clear the input ring, and unblock. */ + sc->sc_rbput = sc->sc_rbget = sc->sc_rbuf; + sc->sc_rbavail = scif_rbuf_size; + scif_iflush(sc); + CLR(sc->sc_rx_flags, RX_ANY_BLOCK); +#if 0 +/* XXX (msaitoh) */ + scif_hwiflow(sc); +#endif + +#ifdef SCIF_DEBUG + if (scif_debug) + scifstatus(sc, "scifopen "); +#endif + + splx(s2); + } + + splx(s); + + error = ttyopen(dev, tp); + if (error) + goto bad; + + error = (*linesw[tp->t_line].l_open)(dev, tp); + if (error) + goto bad; + + return (0); + +bad: + + return (error); +} + +int +scifclose(dev_t dev, int flag, int mode, struct proc *p) +{ + struct scif_softc *sc = scif_cd.cd_devs[SCIFUNIT(dev)]; + struct tty *tp = sc->sc_tty; + + /* XXX This is for cons.c. */ + if (!ISSET(tp->t_state, TS_ISOPEN)) + return (0); + + (*linesw[tp->t_line].l_close)(tp, flag); + ttyclose(tp); + + return (0); +} + +int +scifread(dev_t dev, struct uio *uio, int flag) +{ + struct scif_softc *sc = scif_cd.cd_devs[SCIFUNIT(dev)]; + struct tty *tp = sc->sc_tty; + + return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); +} + +int +scifwrite(dev_t dev, struct uio *uio, int flag) +{ + struct scif_softc *sc = scif_cd.cd_devs[SCIFUNIT(dev)]; + struct tty *tp = sc->sc_tty; + + return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); +} + +#if 0 +int +scifpoll(dev_t dev, int events, struct proc *p) +{ + struct scif_softc *sc = scif_cd.cd_devs[SCIFUNIT(dev)]; + struct tty *tp = sc->sc_tty; + + return ((*linesw[tp->t_line].l_poll)(tp, events, p)); +} +#endif + +struct tty * +sciftty(dev_t dev) +{ + struct scif_softc *sc = scif_cd.cd_devs[SCIFUNIT(dev)]; + struct tty *tp = sc->sc_tty; + + return (tp); +} + +int +scifioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) +{ + struct scif_softc *sc = scif_cd.cd_devs[SCIFUNIT(dev)]; + struct tty *tp = sc->sc_tty; + int error; + int s; + + error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); + if (error != -1) + return (error); + + error = ttioctl(tp, cmd, data, flag, p); + if (error != -1) + return (error); + + error = 0; + + s = splserial(); + + switch (cmd) { + case TIOCSBRK: + scif_break(sc, 1); + break; + + case TIOCCBRK: + scif_break(sc, 0); + break; + + case TIOCGFLAGS: + *(int *)data = sc->sc_swflags; + break; + + case TIOCSFLAGS: + error = suser(p, 0); + if (error) + break; + sc->sc_swflags = *(int *)data; + break; + + default: + error = -1; + break; + } + + splx(s); + + return (error); +} + +void +scif_schedrx(struct scif_softc *sc) +{ + sc->sc_rx_ready = 1; + + /* Wake up the poller. */ + softintr_schedule(sc->sc_si); +} + +void +scif_break(struct scif_softc *sc, int onoff) +{ + if (onoff) + scif_ssr_write(scif_ssr_read() & ~SCSSR2_TDFE); + else + scif_ssr_write(scif_ssr_read() | SCSSR2_TDFE); + +#if 0 /* XXX */ + if (!sc->sc_heldchange) { + if (sc->sc_tx_busy) { + sc->sc_heldtbc = sc->sc_tbc; + sc->sc_tbc = 0; + sc->sc_heldchange = 1; + } else + scif_loadchannelregs(sc); + } +#endif +} + +/* + * Stop output, e.g., for ^S or output flush. + */ +int +scifstop(struct tty *tp, int flag) +{ + struct scif_softc *sc = scif_cd.cd_devs[SCIFUNIT(tp->t_dev)]; + int s; + + s = splserial(); + if (ISSET(tp->t_state, TS_BUSY)) { + /* Stop transmitting at the next chunk. */ + sc->sc_tbc = 0; + sc->sc_heldtbc = 0; + if (!ISSET(tp->t_state, TS_TTSTOP)) + SET(tp->t_state, TS_FLUSH); + } + splx(s); + return (0); +} + +void +scif_intr_init() +{ + /* XXX */ +} + +void +scifdiag(void *arg) +{ + struct scif_softc *sc = arg; + int overflows, floods; + int s; + + s = splserial(); + overflows = sc->sc_overflows; + sc->sc_overflows = 0; + floods = sc->sc_floods; + sc->sc_floods = 0; + sc->sc_errors = 0; + splx(s); + + log(LOG_WARNING, "%s: %d silo overflow%s, %d ibuf flood%s\n", + sc->sc_dev.dv_xname, + overflows, overflows == 1 ? "" : "s", + floods, floods == 1 ? "" : "s"); +} + +void +scif_rxsoft(struct scif_softc *sc, struct tty *tp) +{ + int (*rint)(int, struct tty *) = *linesw[tp->t_line].l_rint; + u_char *get, *end; + u_int cc, scc; + u_char ssr2; + int code; + int s; + + end = sc->sc_ebuf; + get = sc->sc_rbget; + scc = cc = scif_rbuf_size - sc->sc_rbavail; + + if (cc == scif_rbuf_size) { + sc->sc_floods++; + if (sc->sc_errors++ == 0) + timeout_add(&sc->sc_diag_tmo, 60 * hz); + } + + while (cc) { + code = get[0]; + ssr2 = get[1]; + if (ISSET(ssr2, SCSSR2_BRK | SCSSR2_FER | SCSSR2_PER)) { + if (ISSET(ssr2, SCSSR2_BRK | SCSSR2_FER)) + SET(code, TTY_FE); + if (ISSET(ssr2, SCSSR2_PER)) + SET(code, TTY_PE); + } + if ((*rint)(code, tp) == -1) { + /* + * The line discipline's buffer is out of space. + */ + if (!ISSET(sc->sc_rx_flags, RX_TTY_BLOCKED)) { + /* + * We're either not using flow control, or the + * line discipline didn't tell us to block for + * some reason. Either way, we have no way to + * know when there's more space available, so + * just drop the rest of the data. + */ + get += cc << 1; + if (get >= end) + get -= scif_rbuf_size << 1; + cc = 0; + } else { + /* + * Don't schedule any more receive processing + * until the line discipline tells us there's + * space available (through scifhwiflow()). + * Leave the rest of the data in the input + * buffer. + */ + SET(sc->sc_rx_flags, RX_TTY_OVERFLOWED); + } + break; + } + get += 2; + if (get >= end) + get = sc->sc_rbuf; + cc--; + } + + if (cc != scc) { + sc->sc_rbget = get; + s = splserial(); + cc = sc->sc_rbavail += scc - cc; + /* Buffers should be ok again, release possible block. */ + if (cc >= sc->sc_r_lowat) { + if (ISSET(sc->sc_rx_flags, RX_IBUF_OVERFLOWED)) { + CLR(sc->sc_rx_flags, RX_IBUF_OVERFLOWED); + scif_scr_write(scif_scr_read() | SCSCR2_RIE); + } +#if 0 + if (ISSET(sc->sc_rx_flags, RX_IBUF_BLOCKED)) { + CLR(sc->sc_rx_flags, RX_IBUF_BLOCKED); + scif_hwiflow(sc); + } +#endif + } + splx(s); + } +} + +void +scif_txsoft(struct scif_softc *sc, struct tty *tp) +{ + CLR(tp->t_state, TS_BUSY); + if (ISSET(tp->t_state, TS_FLUSH)) + CLR(tp->t_state, TS_FLUSH); + else + ndflush(&tp->t_outq, (int)(sc->sc_tba - tp->t_outq.c_cf)); + (*linesw[tp->t_line].l_start)(tp); +} + +void +scif_stsoft(struct scif_softc *sc, struct tty *tp) +{ +#if 0 +/* XXX (msaitoh) */ + u_char msr, delta; + int s; + + s = splserial(); + msr = sc->sc_msr; + delta = sc->sc_msr_delta; + sc->sc_msr_delta = 0; + splx(s); + + if (ISSET(delta, sc->sc_msr_dcd)) { + /* + * Inform the tty layer that carrier detect changed. + */ + (void) (*linesw[tp->t_line].l_modem)(tp, ISSET(msr, MSR_DCD)); + } + + if (ISSET(delta, sc->sc_msr_cts)) { + /* Block or unblock output according to flow control. */ + if (ISSET(msr, sc->sc_msr_cts)) { + sc->sc_tx_stopped = 0; + (*linesw[tp->t_line].l_start)(tp); + } else { + sc->sc_tx_stopped = 1; + } + } + +#ifdef SCIF_DEBUG + if (scif_debug) + scifstatus(sc, "scif_stsoft"); +#endif +#endif +} + +void +scifsoft(void *arg) +{ + struct scif_softc *sc = arg; + struct tty *tp; + + tp = sc->sc_tty; + + if (sc->sc_rx_ready) { + sc->sc_rx_ready = 0; + scif_rxsoft(sc, tp); + } + +#if 0 + if (sc->sc_st_check) { + sc->sc_st_check = 0; + scif_stsoft(sc, tp); + } +#endif + + if (sc->sc_tx_done) { + sc->sc_tx_done = 0; + scif_txsoft(sc, tp); + } +} + +int +scifintr(void *arg) +{ + struct scif_softc *sc = arg; + u_char *put, *end; + u_int cc; + u_short ssr2; + int count; + + end = sc->sc_ebuf; + put = sc->sc_rbput; + cc = sc->sc_rbavail; + + do { + ssr2 = scif_ssr_read(); + if (ISSET(ssr2, SCSSR2_BRK)) { + scif_ssr_write(scif_ssr_read() + & ~(SCSSR2_ER | SCSSR2_BRK | SCSSR2_DR)); +#ifdef DDB + if (ISSET(sc->sc_hwflags, SCIF_HW_CONSOLE) && + db_console != 0) { + Debugger(); + } +#endif /* DDB */ + } + count = scif_fdr_read() & SCFDR2_RECVCNT; + if (count != 0) { + for (;;) { + u_char c = scif_frdr_read(); + u_char err = (u_char)(scif_ssr_read() & 0x00ff); + + scif_ssr_write(scif_ssr_read() + & ~(SCSSR2_ER | SCSSR2_RDF | SCSSR2_DR)); +#ifdef SH4 + if (CPU_IS_SH4) + scif_lsr_write(scif_lsr_read() + & ~SCLSR2_ORER); +#endif + if ((cc > 0) && (count > 0)) { + put[0] = c; + put[1] = err; + put += 2; + if (put >= end) + put = sc->sc_rbuf; + cc--; + count--; + } else + break; + } + + /* + * Current string of incoming characters ended because + * no more data was available or we ran out of space. + * Schedule a receive event if any data was received. + * If we're out of space, turn off receive interrupts. + */ + sc->sc_rbput = put; + sc->sc_rbavail = cc; + if (!ISSET(sc->sc_rx_flags, RX_TTY_OVERFLOWED)) + sc->sc_rx_ready = 1; + + /* + * See if we are in danger of overflowing a buffer. If + * so, use hardware flow control to ease the pressure. + */ + if (!ISSET(sc->sc_rx_flags, RX_IBUF_BLOCKED) && + cc < sc->sc_r_hiwat) { + SET(sc->sc_rx_flags, RX_IBUF_BLOCKED); +#if 0 + scif_hwiflow(sc); +#endif + } + + /* + * If we're out of space, disable receive interrupts + * until the queue has drained a bit. + */ + if (!cc) { + SET(sc->sc_rx_flags, RX_IBUF_OVERFLOWED); + scif_scr_write(scif_scr_read() & ~SCSCR2_RIE); + } + } else { + if (scif_ssr_read() & (SCSSR2_RDF | SCSSR2_DR)) { + scif_scr_write(scif_scr_read() + & ~(SCSCR2_TIE | SCSCR2_RIE)); + delay(10); + scif_scr_write(scif_scr_read() + | SCSCR2_TIE | SCSCR2_RIE); + continue; + } + } + } while (scif_ssr_read() & (SCSSR2_RDF | SCSSR2_DR)); + +#if 0 + msr = bus_space_read_1(iot, ioh, scif_msr); + delta = msr ^ sc->sc_msr; + sc->sc_msr = msr; + if (ISSET(delta, sc->sc_msr_mask)) { + SET(sc->sc_msr_delta, delta); + + /* + * Pulse-per-second clock signal on edge of DCD? + */ + if (ISSET(delta, sc->sc_ppsmask)) { + struct timeval tv; + if (ISSET(msr, sc->sc_ppsmask) == + sc->sc_ppsassert) { + /* XXX nanotime() */ + microtime(&tv); + TIMEVAL_TO_TIMESPEC(&tv, + &sc->ppsinfo.assert_timestamp); + if (sc->ppsparam.mode & PPS_OFFSETASSERT) { + timespecadd(&sc->ppsinfo.assert_timestamp, + &sc->ppsparam.assert_offset, + &sc->ppsinfo.assert_timestamp); + TIMESPEC_TO_TIMEVAL(&tv, &sc->ppsinfo.assert_timestamp); + } + +#ifdef PPS_SYNC + if (sc->ppsparam.mode & PPS_HARDPPSONASSERT) + hardpps(&tv, tv.tv_usec); +#endif + sc->ppsinfo.assert_sequence++; + sc->ppsinfo.current_mode = + sc->ppsparam.mode; + + } else if (ISSET(msr, sc->sc_ppsmask) == + sc->sc_ppsclear) { + /* XXX nanotime() */ + microtime(&tv); + TIMEVAL_TO_TIMESPEC(&tv, + &sc->ppsinfo.clear_timestamp); + if (sc->ppsparam.mode & PPS_OFFSETCLEAR) { + timespecadd(&sc->ppsinfo.clear_timestamp, + &sc->ppsparam.clear_offset, + &sc->ppsinfo.clear_timestamp); + TIMESPEC_TO_TIMEVAL(&tv, &sc->ppsinfo.clear_timestamp); + } + +#ifdef PPS_SYNC + if (sc->ppsparam.mode & PPS_HARDPPSONCLEAR) + hardpps(&tv, tv.tv_usec); +#endif + sc->ppsinfo.clear_sequence++; + sc->ppsinfo.current_mode = + sc->ppsparam.mode; + } + } + + /* + * Stop output immediately if we lose the output + * flow control signal or carrier detect. + */ + if (ISSET(~msr, sc->sc_msr_mask)) { + sc->sc_tbc = 0; + sc->sc_heldtbc = 0; +#ifdef SCIF_DEBUG + if (scif_debug) + scifstatus(sc, "scifintr "); +#endif + } + + sc->sc_st_check = 1; + } +#endif + + /* + * Done handling any receive interrupts. See if data can be + * transmitted as well. Schedule tx done event if no data left + * and tty was marked busy. + */ + if (((scif_fdr_read() & SCFDR2_TXCNT) >> 8) != 16) { /* XXX (msaitoh) */ + /* + * If we've delayed a parameter change, do it now, and restart + * output. + */ + if (sc->sc_heldchange) { + sc->sc_heldchange = 0; + sc->sc_tbc = sc->sc_heldtbc; + sc->sc_heldtbc = 0; + } + + /* Output the next chunk of the contiguous buffer, if any. */ + if (sc->sc_tbc > 0) { + int n; + int maxchars; + int i; + + n = sc->sc_tbc; + maxchars = sc->sc_fifolen - + ((scif_fdr_read() & SCFDR2_TXCNT) >> 8); + if (n > maxchars) + n = maxchars; + + for (i = 0; i < n; i++) { + scif_putc(*(sc->sc_tba)); + sc->sc_tba++; + } + sc->sc_tbc -= n; + } else { + /* Disable transmit completion interrupts if necessary. */ +#if 0 + if (ISSET(sc->sc_ier, IER_ETXRDY)) +#endif + scif_scr_write(scif_scr_read() & ~SCSCR2_TIE); + + if (sc->sc_tx_busy) { + sc->sc_tx_busy = 0; + sc->sc_tx_done = 1; + } + } + } + + /* Wake up the poller. */ + softintr_schedule(sc->sc_si); + + return (1); +} + +void +scifcnprobe(struct consdev *cp) +{ + int maj; + + /* locate the major number */ + for (maj = 0; maj < nchrdev; maj++) + if (cdevsw[maj].d_open == scifopen) + break; + + cp->cn_dev = makedev(maj, 0); +#ifdef SCIFCONSOLE + cp->cn_pri = CN_REMOTE; +#else + cp->cn_pri = CN_NORMAL; +#endif +} + +void +scifcninit(struct consdev *cp) +{ + InitializeScif(scifcn_speed); + scifisconsole = 1; +} + +int +scifcngetc(dev_t dev) +{ + int c; + int s; + + s = splserial(); + c = scif_getc(); + splx(s); + + return (c); +} + +void +scifcnputc(dev_t dev, int c) +{ + int s; + + s = splserial(); + scif_putc((u_char)c); + splx(s); +} diff --git a/sys/arch/sh/dev/scifreg.h b/sys/arch/sh/dev/scifreg.h new file mode 100644 index 00000000000..3baf31f7f90 --- /dev/null +++ b/sys/arch/sh/dev/scifreg.h @@ -0,0 +1,164 @@ +/* $OpenBSD: scifreg.h,v 1.1.1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: scifreg.h,v 1.10 2006/02/18 00:41:32 uwe Exp $ */ + +/*- + * Copyright (C) 1999 SAITOH Masanobu. 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. 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. + */ + +/* + * Serial Communication Interface with FIFO (SCIF) + */ + +#define SH3_SCIF0_BASE 0xa4000150 +#define SH3_SCIF1_BASE 0xa4000140 + +#define SH4_SCIF_BASE 0xffe80000 + +#ifdef SH3 + +/* SH3 definitions */ + +#define SCIF_SMR 0x0 /* serial mode */ +#define SCIF_BRR 0x2 /* bit rate */ +#define SCIF_SCR 0x4 /* serial control */ +#define SCIF_FTDR 0x6 /* transmit fifo data */ +#define SCIF_SSR 0x8 /* serial status */ +#define SCIF_FRDR 0xa /* receive fifo data */ +#define SCIF_FCR 0xc /* fifo control */ +#define SCIF_FDR 0xe /* fifo data count set */ + +#define SHREG_SCSMR2 (*(volatile uint8_t *)(SH3_SCIF0_BASE + SCIF_SMR)) +#define SHREG_SCBRR2 (*(volatile uint8_t *)(SH3_SCIF0_BASE + SCIF_BRR)) +#define SHREG_SCSCR2 (*(volatile uint8_t *)(SH3_SCIF0_BASE + SCIF_SCR)) +#define SHREG_SCFTDR2 (*(volatile uint8_t *)(SH3_SCIF0_BASE + SCIF_FTDR)) +#define SHREG_SCSSR2 (*(volatile uint16_t *)(SH3_SCIF0_BASE + SCIF_SSR)) +#define SHREG_SCFRDR2 (*(volatile uint8_t *)(SH3_SCIF0_BASE + SCIF_FRDR)) +#define SHREG_SCFCR2 (*(volatile uint8_t *)(SH3_SCIF0_BASE + SCIF_FCR)) +#define SHREG_SCFDR2 (*(volatile uint16_t *)(SH3_SCIF0_BASE + SCIF_FDR)) + +#else /* !SH3 */ + +/* SH4 definitions */ + +#define SCIF_SMR 0x00 /* serial mode */ +#define SCIF_BRR 0x04 /* bit rate */ +#define SCIF_SCR 0x08 /* serial control */ +#define SCIF_FTDR 0x0c /* transmit fifo data */ +#define SCIF_SSR 0x10 /* serial status */ +#define SCIF_FRDR 0x14 /* receive fifo data */ +#define SCIF_FCR 0x18 /* fifo control */ +#define SCIF_FDR 0x1c /* fifo data count set */ + +#define SCIF_SPTR 0x20 /* seial port */ +#define SCIF_LSR 0x24 /* line status */ + +#define SHREG_SCSMR2 (*(volatile uint16_t *)(SH4_SCIF_BASE + SCIF_SMR)) +#define SHREG_SCBRR2 (*(volatile uint8_t *)(SH4_SCIF_BASE + SCIF_BRR)) +#define SHREG_SCSCR2 (*(volatile uint16_t *)(SH4_SCIF_BASE + SCIF_SCR)) +#define SHREG_SCFTDR2 (*(volatile uint8_t *)(SH4_SCIF_BASE + SCIF_FTDR)) +#define SHREG_SCSSR2 (*(volatile uint16_t *)(SH4_SCIF_BASE + SCIF_SSR)) +#define SHREG_SCFRDR2 (*(volatile uint8_t *)(SH4_SCIF_BASE + SCIF_FRDR)) +#define SHREG_SCFCR2 (*(volatile uint16_t *)(SH4_SCIF_BASE + SCIF_FCR)) +#define SHREG_SCFDR2 (*(volatile uint16_t *)(SH4_SCIF_BASE + SCIF_FDR)) + +#define SHREG_SCSPTR2 (*(volatile uint16_t *)(SH4_SCIF_BASE + SCIF_SPTR)) +#define SHREG_SCLSR2 (*(volatile uint16_t *)(SH4_SCIF_BASE + SCIF_LSR)) + +/* alias */ +#define SHREG_SCSFDR2 SHREG_SCFTDR2 +#define SHREG_SCFSR2 SHREG_SCSSR2 + +#define SCSPTR2_RTSIO 0x0080 +#define SCSPTR2_RTSDT 0x0040 +#define SCSPTR2_CTSIO 0x0020 +#define SCSPTR2_CTSDT 0x0010 +#define SCSPTR2_SCKIO 0x0008 +#define SCSPTR2_SCKDT 0x0004 +#define SCSPTR2_SPB2IO 0x0002 +#define SCSPTR2_SPB2DT 0x0001 + +#define SCLSR2_ORER 0x0001 /* overrun error */ + +#endif /* !SH3 */ + +/* SMR: serial mode */ +#define SCSMR2_CHR 0x40 /* character width (set = 7bit) */ +#define SCSMR2_PE 0x20 /* Parity Enable */ +#define SCSMR2_O 0x10 /* parity mode Odd */ +#define SCSMR2_STOP 0x08 /* STOP bit (set = 2 stop bits) */ +#define SCSMR2_CKS1 0x02 /* ClocK Select 1 */ +#define SCSMR2_CKS0 0x01 /* ClocK Select 0 */ + +/* SMR: serial mode (for IrDA) */ +#define SCSMR2_IRMOD 0x80 /* IrDA mode */ +#define SCSMR2_ICK3 0x40 +#define SCSMR2_ICK2 0x20 +#define SCSMR2_ICK1 0x10 +#define SCSMR2_ICK0 0x08 +#define SCSMR2_PSEL 0x04 /* Pulse width SELelect */ + +/* SCR: serial control */ +#define SCSCR2_TIE 0x80 /* Transmit Interrupt Enable */ +#define SCSCR2_RIE 0x40 /* Recieve Interrupt Enable */ +#define SCSCR2_TE 0x20 /* Transmit Enable */ +#define SCSCR2_RE 0x10 /* Receive Enable */ +#define SCSCR2_CKE1 0x02 /* ClocK Enable 1 */ +#define SCSCR2_CKE0 0x01 /* ClocK Enable 0 (not in sh4) */ + +/* SSR: serial status */ +#define SCSSR2_ER 0x0080 /* ERror */ +#define SCSSR2_TEND 0x0040 /* Transmit END */ +#define SCSSR2_TDFE 0x0020 /* Transmit Data Fifo Empty */ +#define SCSSR2_BRK 0x0010 /* BReaK detection */ +#define SCSSR2_FER 0x0008 /* Framing ERror */ +#define SCSSR2_PER 0x0004 /* Parity ERror */ +#define SCSSR2_RDF 0x0002 /* Recieve fifo Data Full */ +#define SCSSR2_DR 0x0001 /* Data Ready */ + +/* FCR: fifo control */ +#define SCFCR2_RTRG1 0x80 /* Receive TRiGger 1 */ +#define SCFCR2_RTRG0 0x40 /* Receive TRiGger 0 */ +#define SCFCR2_TTRG1 0x20 /* Transmit TRiGger 1 */ +#define SCFCR2_TTRG0 0x10 /* Transmit TRiGger 0 */ +#define SCFCR2_MCE 0x08 /* Modem Control Enable */ +#define SCFCR2_TFRST 0x04 /* Transmit Fifo register ReSeT */ +#define SCFCR2_RFRST 0x02 /* Receive Fifo register ReSeT */ +#define SCFCR2_LOOP 0x01 /* LOOP back test */ + +#define FIFO_RCV_TRIGGER_1 0x00 +#define FIFO_RCV_TRIGGER_4 0x40 +#define FIFO_RCV_TRIGGER_8 0x80 +#define FIFO_RCV_TRIGGER_14 0xc0 + +#define FIFO_XMT_TRIGGER_8 0x00 +#define FIFO_XMT_TRIGGER_4 0x10 +#define FIFO_XMT_TRIGGER_2 0x20 +#define FIFO_XMT_TRIGGER_1 0x30 + +/* FDR: fifo data count set */ +#define SCFDR2_TXCNT 0xff00 /* Tx CouNT */ +#define SCFDR2_RECVCNT 0x00ff /* Rx CouNT */ +#define SCFDR2_TXF_FULL 0x1000 /* Tx FULL */ +#define SCFDR2_RXF_EPTY 0x0000 /* Rx EMPTY */ diff --git a/sys/arch/sh/dev/scireg.h b/sys/arch/sh/dev/scireg.h new file mode 100644 index 00000000000..bd3d2529c4e --- /dev/null +++ b/sys/arch/sh/dev/scireg.h @@ -0,0 +1,82 @@ +/* $OpenBSD: scireg.h,v 1.1.1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: scireg.h,v 1.8 2003/07/01 11:49:37 uwe Exp $ */ + +/*- + * Copyright (C) 1999 SAITOH Masanobu. 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. 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. + */ + +/* + * Serial Communication Interface (SCI) + */ + +#if !defined(SH4) + +/* SH3 definitions */ + +#define SHREG_SCSMR (*(volatile unsigned char *) 0xFFFFFE80) +#define SHREG_SCBRR (*(volatile unsigned char *) 0xFFFFFE82) +#define SHREG_SCSCR (*(volatile unsigned char *) 0xFFFFFE84) +#define SHREG_SCTDR (*(volatile unsigned char *) 0xFFFFFE86) +#define SHREG_SCSSR (*(volatile unsigned char *) 0xFFFFFE88) +#define SHREG_SCRDR (*(volatile unsigned char *) 0xFFFFFE8A) +#define SHREG_SCSPDR (*(volatile unsigned char *) 0xf4000136) + +#else + +/* SH4 definitions */ + +#define SHREG_SCSMR (*(volatile unsigned char *) 0xffe00000) +#define SHREG_SCBRR (*(volatile unsigned char *) 0xffe00004) +#define SHREG_SCSCR (*(volatile unsigned char *) 0xffe00008) +#define SHREG_SCTDR (*(volatile unsigned char *) 0xffe0000c) +#define SHREG_SCSSR (*(volatile unsigned char *) 0xffe00010) +#define SHREG_SCRDR (*(volatile unsigned char *) 0xffe00014) +#define SHREG_SCSPTR (*(volatile unsigned char *) 0xffe0001c) + +#endif + +#define SCSCR_TIE 0x80 /* Transmit Interrupt Enable */ +#define SCSCR_RIE 0x40 /* Receive Interrupt Enable */ +#define SCSCR_TE 0x20 /* Transmit Enable */ +#define SCSCR_RE 0x10 /* Receive Enable */ +#define SCSCR_MPIE 0x08 /* Multi Processor Interrupt Enable */ +#define SCSCR_TEIE 0x04 /* Transmit End Interrupt Enable */ +#define SCSCR_CKE1 0x02 /* ClocK Enable 1 */ +#define SCSCR_CKE0 0x01 /* ClocK Enable 0 */ + +#define SCSSR_TDRE 0x80 +#define SCSSR_RDRF 0x40 +#define SCSSR_ORER 0x20 +#define SCSSR_FER 0x10 +#define SCSSR_PER 0x08 + +#define SCSPTR_SPB1IO 0x08 +#define SCSPTR_SPB1DT 0x04 +#define SCSPTR_SPB0IO 0x02 +#define SCSPTR_SPB0DT 0x01 + +#if defined(SH3) +#define SCSPDR_SCP0DT 0x01 +#endif diff --git a/sys/arch/sh/dev/shb.c b/sys/arch/sh/dev/shb.c new file mode 100644 index 00000000000..2880a647b0b --- /dev/null +++ b/sys/arch/sh/dev/shb.c @@ -0,0 +1,91 @@ +/* $OpenBSD: shb.c,v 1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: shb.c,v 1.10 2005/12/11 12:18:58 christos Exp $ */ + +/*- + * Copyright (c) 2002 The NetBSD Foundation, Inc. + * 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 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. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> + +#include <machine/autoconf.h> + +int shb_match(struct device *, void *, void *); +void shb_attach(struct device *, struct device *, void *); +int shb_print(void *, const char *); +int shb_search(struct device *, void *, void *); + +struct cfattach shb_ca = { + sizeof(struct device), shb_match, shb_attach +}; + +struct cfdriver shb_cd = { + 0, "shb", DV_DULL +}; + +int +shb_match(struct device *parent, void *vcf, void *aux) +{ + extern struct cfdriver shb_cd; + struct mainbus_attach_args *ma = aux; + + if (strcmp(ma->ma_name, shb_cd.cd_name) != 0) + return (0); + + return (1); +} + +void +shb_attach(struct device *parent, struct device *self, void *aux) +{ + printf("\n"); + + config_search(shb_search, self, aux); +} + +int +shb_search(struct device *parent, void *vcf, void *aux) +{ + struct cfdata *cf = vcf; + + if ((*cf->cf_attach->ca_match)(parent, cf, NULL) == 0) + return (0); + config_attach(parent, cf, NULL, shb_print); + return (1); +} + +int +shb_print(void *aux, const char *pnp) +{ + return (UNCONF); +} diff --git a/sys/arch/sh/dev/shpcic.c b/sys/arch/sh/dev/shpcic.c new file mode 100644 index 00000000000..c1357e2d708 --- /dev/null +++ b/sys/arch/sh/dev/shpcic.c @@ -0,0 +1,1182 @@ +/* $OpenBSD: shpcic.c,v 1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: shpcic.c,v 1.10 2005/12/24 20:07:32 perry Exp $ */ + +/* + * Copyright (c) 2005 NONAKA Kimihiro + * 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. + * + * 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. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/device.h> +#include <sys/extent.h> +#include <sys/malloc.h> + +#include <dev/pci/pcireg.h> +#include <dev/pci/pcivar.h> +#include <dev/pci/pcidevs.h> + +#include <sh/bscreg.h> +#include <sh/cache.h> +#include <sh/trap.h> +#include <sh/dev/pcicreg.h> + +#include <machine/bus.h> +#include <machine/intr.h> + +#if defined(SHPCIC_DEBUG) +int shpcic_debug = 0; +#define DPRINTF(arg) if (shpcic_debug) printf arg +#else +#define DPRINTF(arg) +#endif + +#define PCI_MODE1_ENABLE 0x80000000UL + +static const struct shpcic_product { + uint32_t sp_product; + const char *sp_name; +} shpcic_products[] = { + { PCI_PRODUCT_HITACHI_SH7751, "SH7751" }, + { PCI_PRODUCT_HITACHI_SH7751R, "SH7751R" }, + + { 0, NULL }, +}; + +int shpcic_match(struct device *, void *, void *); +void shpcic_attach(struct device *, struct device *, void *); + +struct cfattach shpcic_ca = { + sizeof(struct device), shpcic_match, shpcic_attach +}; + +struct cfdriver shpcic_cd = { + 0, "shpcic", DV_DULL +}; + +/* There can be only one. */ +int shpcic_found = 0; + +/* PCIC intr priotiry */ +static int shpcic_intr_priority[2] = { IPL_BIO, IPL_BIO }; + +static const struct shpcic_product *shpcic_lookup(void); + +static const struct shpcic_product * +shpcic_lookup(void) +{ + const struct shpcic_product *spp; + pcireg_t id; + + id = _reg_read_4(SH4_PCICONF0); + switch (PCI_VENDOR(id)) { + case PCI_VENDOR_HITACHI: + break; + + default: + return (NULL); + } + + for (spp = shpcic_products; spp->sp_name != NULL; spp++) { + if (PCI_PRODUCT(id) == spp->sp_product) { + return (spp); + } + } + return (NULL); +} + +int +shpcic_match(struct device *parent, void *vcf, void *aux) +{ + if (!CPU_IS_SH4) + return (0); + + switch (cpu_product) { + default: + return (0); + + case CPU_PRODUCT_7751: + case CPU_PRODUCT_7751R: + break; + } + + if (shpcic_found) + return (0); + + if (shpcic_lookup() == NULL) + return (0); + + if (_reg_read_2(SH4_BCR2) & BCR2_PORTEN) + return (0); + + return (1); +} + +void +shpcic_attach(struct device *parent, struct device *self, void *aux) +{ + const struct shpcic_product *spp; + struct pcibus_attach_args pba; + + shpcic_found = 1; + + spp = shpcic_lookup(); + if (spp == NULL) { + printf("\n"); + panic("shpcic_attach: impossible"); + } + + if (_reg_read_2(SH4_BCR2) & BCR2_PORTEN) { + printf("\n"); + panic("shpcic_attach: port enabled"); + } + + printf(": HITACHI %s\n", spp->sp_name); + + /* allow PCIC request */ + _reg_write_4(SH4_BCR1, _reg_read_4(SH4_BCR1) | BCR1_BREQEN); + + /* Initialize PCIC */ + _reg_write_4(SH4_PCICR, PCICR_BASE | PCICR_RSTCTL); + delay(10 * 1000); + _reg_write_4(SH4_PCICR, PCICR_BASE); + + /* Class: Host-Bridge */ + _reg_write_4(SH4_PCICONF2, + (PCI_CLASS_BRIDGE << PCI_CLASS_SHIFT) | + (PCI_SUBCLASS_BRIDGE_HOST << PCI_SUBCLASS_SHIFT)); + +#if !defined(DONT_INIT_PCIBSC) +#if defined(PCIBCR_BCR1_VAL) + _reg_write_4(SH4_PCIBCR1, PCIBCR_BCR1_VAL); +#else + _reg_write_4(SH4_PCIBCR1, _reg_read_4(SH4_BCR1) | BCR1_MASTER); +#endif +#if defined(PCIBCR_BCR2_VAL) + _reg_write_4(SH4_PCIBCR2, PCIBCR_BCR2_VAL); +#else + _reg_write_4(SH4_PCIBCR2, _reg_read_2(SH4_BCR2)); +#endif +#if defined(SH4) && defined(SH7751R) + if (cpu_product == CPU_PRODUCT_7751R) { +#if defined(PCIBCR_BCR3_VAL) + _reg_write_4(SH4_PCIBCR3, PCIBCR_BCR3_VAL); +#else + _reg_write_4(SH4_PCIBCR3, _reg_read_2(SH4_BCR3)); +#endif + } +#endif /* SH4 && SH7751R && PCIBCR_BCR3_VAL */ +#if defined(PCIBCR_WCR1_VAL) + _reg_write_4(SH4_PCIWCR1, PCIBCR_WCR1_VAL); +#else + _reg_write_4(SH4_PCIWCR1, _reg_read_4(SH4_WCR1)); +#endif +#if defined(PCIBCR_WCR2_VAL) + _reg_write_4(SH4_PCIWCR2, PCIBCR_WCR2_VAL); +#else + _reg_write_4(SH4_PCIWCR2, _reg_read_4(SH4_WCR2)); +#endif +#if defined(PCIBCR_WCR3_VAL) + _reg_write_4(SH4_PCIWCR3, PCIBCR_WCR3_VAL); +#else + _reg_write_4(SH4_PCIWCR3, _reg_read_4(SH4_WCR3)); +#endif +#if defined(PCIBCR_MCR_VAL) + _reg_write_4(SH4_PCIMCR, PCIBCR_MCR_VAL); +#else + _reg_write_4(SH4_PCIMCR, _reg_read_4(SH4_MCR)); +#endif +#endif /* !DONT_INIT_PCIBSC */ + + /* set PCI I/O, memory base address */ + _reg_write_4(SH4_PCIIOBR, SH4_PCIC_IO); + _reg_write_4(SH4_PCIMBR, SH4_PCIC_MEM); + + /* set PCI local address 0 */ + _reg_write_4(SH4_PCILSR0, (64 - 1) << 20); + _reg_write_4(SH4_PCILAR0, 0xac000000); + _reg_write_4(SH4_PCICONF5, 0xac000000); + + /* set PCI local address 1 */ + _reg_write_4(SH4_PCILSR1, (64 - 1) << 20); + _reg_write_4(SH4_PCILAR1, 0xac000000); + _reg_write_4(SH4_PCICONF6, 0x8c000000); + + /* Enable I/O, memory, bus-master */ + _reg_write_4(SH4_PCICONF1, PCI_COMMAND_IO_ENABLE + | PCI_COMMAND_MEM_ENABLE + | PCI_COMMAND_MASTER_ENABLE + | PCI_COMMAND_STEPPING_ENABLE + | PCI_STATUS_DEVSEL_MEDIUM); + + /* Initialize done. */ + _reg_write_4(SH4_PCICR, PCICR_BASE | PCICR_CFINIT); + + /* set PCI controller interrupt priority */ + intpri_intr_priority(SH4_INTEVT_PCIERR, shpcic_intr_priority[0]); + intpri_intr_priority(SH4_INTEVT_PCISERR, shpcic_intr_priority[1]); + + /* PCI bus */ + memset(&pba, 0, sizeof(pba)); + pba.pba_iot = shpcic_get_bus_io_tag(); + pba.pba_memt = shpcic_get_bus_mem_tag(); + pba.pba_dmat = shpcic_get_bus_dma_tag(); + pba.pba_pc = NULL; + pba.pba_bus = 0; + pba.pba_bridgetag = NULL; + config_found(self, &pba, NULL); +} + +int +shpcic_bus_maxdevs(void *v, int busno) +{ + /* + * Bus number is irrelevant. Configuration Mechanism 1 is in + * use, can have devices 0-32 (i.e. the `normal' range). + */ + return (32); +} + +pcitag_t +shpcic_make_tag(void *v, int bus, int device, int function) +{ + pcitag_t tag; + + if (bus >= 256 || device >= 32 || function >= 8) + panic("pci_make_tag: bad request"); + + tag = PCI_MODE1_ENABLE | + (bus << 16) | (device << 11) | (function << 8); + + return (tag); +} + +void +shpcic_decompose_tag(void *v, pcitag_t tag, int *bp, int *dp, int *fp) +{ + if (bp != NULL) + *bp = (tag >> 16) & 0xff; + if (dp != NULL) + *dp = (tag >> 11) & 0x1f; + if (fp != NULL) + *fp = (tag >> 8) & 0x7; +} + +pcireg_t +shpcic_conf_read(void *v, pcitag_t tag, int reg) +{ + pcireg_t data; + int s; + + s = splhigh(); + _reg_write_4(SH4_PCIPAR, tag | reg); + data = _reg_read_4(SH4_PCIPDR); + _reg_write_4(SH4_PCIPAR, 0); + splx(s); + + return data; +} + +void +shpcic_conf_write(void *v, pcitag_t tag, int reg, pcireg_t data) +{ + int s; + + s = splhigh(); + _reg_write_4(SH4_PCIPAR, tag | reg); + _reg_write_4(SH4_PCIPDR, data); + _reg_write_4(SH4_PCIPAR, 0); + splx(s); +} + +int +shpcic_set_intr_priority(int intr, int level) +{ + int evtcode; + + if ((intr != 0) && (intr != 1)) { + return (-1); + } + if ((level < IPL_NONE) || (level > IPL_HIGH)) { + return (-1); + } + + if (intr == 0) { + evtcode = SH4_INTEVT_PCIERR; + } else { + evtcode = SH4_INTEVT_PCISERR; + } + + intpri_intr_priority(evtcode, shpcic_intr_priority[intr]); + shpcic_intr_priority[intr] = level; + + return (0); +} + +void * +shpcic_intr_establish(int evtcode, int (*ih_func)(void *), void *ih_arg, + const char *ih_name) +{ + int level; + + switch (evtcode) { + case SH4_INTEVT_PCISERR: + level = shpcic_intr_priority[1]; + break; + + case SH4_INTEVT_PCIDMA3: + case SH4_INTEVT_PCIDMA2: + case SH4_INTEVT_PCIDMA1: + case SH4_INTEVT_PCIDMA0: + case SH4_INTEVT_PCIPWON: + case SH4_INTEVT_PCIPWDWN: + case SH4_INTEVT_PCIERR: + level = shpcic_intr_priority[0]; + break; + + default: + printf("shpcic_intr_establish: unknown evtcode = 0x%08x\n", + evtcode); + return NULL; + } + + return intc_intr_establish(evtcode, IST_LEVEL, level, ih_func, ih_arg, + ih_name); +} + +void +shpcic_intr_disestablish(void *ih) +{ + intc_intr_disestablish(ih); +} + +/* + * shpcic bus space + */ +int +shpcic_iomem_map(void *v, bus_addr_t bpa, bus_size_t size, + int flags, bus_space_handle_t *bshp) +{ + *bshp = (bus_space_handle_t)bpa; + + return (0); +} + +void +shpcic_iomem_unmap(void *v, bus_space_handle_t bsh, bus_size_t size) +{ + /* Nothing to do */ +} + +int +shpcic_iomem_subregion(void *v, bus_space_handle_t bsh, + bus_size_t offset, bus_size_t size, bus_space_handle_t *nbshp) +{ + *nbshp = bsh + offset; + + return (0); +} + +int +shpcic_iomem_alloc(void *v, bus_addr_t rstart, bus_addr_t rend, + bus_size_t size, bus_size_t alignment, bus_size_t boundary, int flags, + bus_addr_t *bpap, bus_space_handle_t *bshp) +{ + *bshp = *bpap = rstart; + + return (0); +} + +void +shpcic_iomem_free(void *v, bus_space_handle_t bsh, bus_size_t size) +{ + /* Nothing to do */ +} + +/* + * shpcic bus space io/mem read/write + */ +/* read */ +static inline uint8_t __shpcic_io_read_1(bus_space_handle_t bsh, + bus_size_t offset); +static inline uint16_t __shpcic_io_read_2(bus_space_handle_t bsh, + bus_size_t offset); +static inline uint32_t __shpcic_io_read_4(bus_space_handle_t bsh, + bus_size_t offset); +static inline uint8_t __shpcic_mem_read_1(bus_space_handle_t bsh, + bus_size_t offset); +static inline uint16_t __shpcic_mem_read_2(bus_space_handle_t bsh, + bus_size_t offset); +static inline uint32_t __shpcic_mem_read_4(bus_space_handle_t bsh, + bus_size_t offset); + +static inline uint8_t +__shpcic_io_read_1(bus_space_handle_t bsh, bus_size_t offset) +{ + u_long adr = (u_long)(bsh + offset) & SH4_PCIC_IO_MASK; + + return *(volatile uint8_t *)(SH4_PCIC_IO + adr); +} + +static inline uint16_t +__shpcic_io_read_2(bus_space_handle_t bsh, bus_size_t offset) +{ + u_long adr = (u_long)(bsh + offset) & SH4_PCIC_IO_MASK; + + return *(volatile uint16_t *)(SH4_PCIC_IO + adr); +} + +static inline uint32_t +__shpcic_io_read_4(bus_space_handle_t bsh, bus_size_t offset) +{ + u_long adr = (u_long)(bsh + offset) & SH4_PCIC_IO_MASK; + + return *(volatile uint32_t *)(SH4_PCIC_IO + adr); +} + +static inline uint8_t +__shpcic_mem_read_1(bus_space_handle_t bsh, bus_size_t offset) +{ + u_long adr = (u_long)(bsh + offset) & SH4_PCIC_MEM_MASK; + + return *(volatile uint8_t *)(SH4_PCIC_MEM + adr); +} + +static inline uint16_t +__shpcic_mem_read_2(bus_space_handle_t bsh, bus_size_t offset) +{ + u_long adr = (u_long)(bsh + offset) & SH4_PCIC_MEM_MASK; + + return *(volatile uint16_t *)(SH4_PCIC_MEM + adr); +} + +static inline uint32_t +__shpcic_mem_read_4(bus_space_handle_t bsh, bus_size_t offset) +{ + u_long adr = (u_long)(bsh + offset) & SH4_PCIC_MEM_MASK; + + return *(volatile uint32_t *)(SH4_PCIC_MEM + adr); +} + +/* + * read single + */ +uint8_t +shpcic_io_read_1(void *v, bus_space_handle_t bsh, bus_size_t offset) +{ + uint8_t value; + + value = __shpcic_io_read_1(bsh, offset); + + return value; +} + +uint16_t +shpcic_io_read_2(void *v, bus_space_handle_t bsh, bus_size_t offset) +{ + uint16_t value; + + value = __shpcic_io_read_2(bsh, offset); + + return value; +} + +uint32_t +shpcic_io_read_4(void *v, bus_space_handle_t bsh, bus_size_t offset) +{ + uint32_t value; + + value = __shpcic_io_read_4(bsh, offset); + + return value; +} + +uint8_t +shpcic_mem_read_1(void *v, bus_space_handle_t bsh, bus_size_t offset) +{ + uint8_t value; + + value = __shpcic_mem_read_1(bsh, offset); + + return value; +} + +uint16_t +shpcic_mem_read_2(void *v, bus_space_handle_t bsh, bus_size_t offset) +{ + uint16_t value; + + value = __shpcic_mem_read_2(bsh, offset); + + return value; +} + +uint32_t +shpcic_mem_read_4(void *v, bus_space_handle_t bsh, bus_size_t offset) +{ + uint32_t value; + + value = __shpcic_mem_read_4(bsh, offset); + + return value; +} + +/* + * read multi + */ +void +shpcic_io_read_multi_1(void *v, bus_space_handle_t bsh, + bus_size_t offset, uint8_t *addr, bus_size_t count) +{ + while (count--) { + *addr++ = __shpcic_io_read_1(bsh, offset); + } +} + +void +shpcic_io_read_multi_2(void *v, bus_space_handle_t bsh, + bus_size_t offset, uint16_t *addr, bus_size_t count) +{ + while (count--) { + *addr++ = __shpcic_io_read_2(bsh, offset); + } +} + +void +shpcic_io_read_multi_4(void *v, bus_space_handle_t bsh, + bus_size_t offset, uint32_t *addr, bus_size_t count) +{ + while (count--) { + *addr++ = __shpcic_io_read_4(bsh, offset); + } +} + +void +shpcic_mem_read_multi_1(void *v, bus_space_handle_t bsh, + bus_size_t offset, uint8_t *addr, bus_size_t count) +{ + while (count--) { + *addr++ = __shpcic_mem_read_1(bsh, offset); + } +} + +void +shpcic_mem_read_multi_2(void *v, bus_space_handle_t bsh, + bus_size_t offset, uint16_t *addr, bus_size_t count) +{ + while (count--) { + *addr++ = __shpcic_mem_read_2(bsh, offset); + } +} + +void +shpcic_mem_read_multi_4(void *v, bus_space_handle_t bsh, + bus_size_t offset, uint32_t *addr, bus_size_t count) +{ + while (count--) { + *addr++ = __shpcic_mem_read_4(bsh, offset); + } +} + +/* + * + * read region + */ +void +shpcic_io_read_region_1(void *v, bus_space_handle_t bsh, + bus_size_t offset, uint8_t *addr, bus_size_t count) +{ + while (count--) { + *addr++ = __shpcic_io_read_1(bsh, offset); + offset += 1; + } +} + +void +shpcic_io_read_region_2(void *v, bus_space_handle_t bsh, + bus_size_t offset, uint16_t *addr, bus_size_t count) +{ + while (count--) { + *addr++ = __shpcic_io_read_2(bsh, offset); + offset += 2; + } +} + +void +shpcic_io_read_region_4(void *v, bus_space_handle_t bsh, + bus_size_t offset, uint32_t *addr, bus_size_t count) +{ + while (count--) { + *addr++ = __shpcic_io_read_4(bsh, offset); + offset += 4; + } +} + +void +shpcic_mem_read_region_1(void *v, bus_space_handle_t bsh, + bus_size_t offset, uint8_t *addr, bus_size_t count) +{ + while (count--) { + *addr++ = __shpcic_mem_read_1(bsh, offset); + offset += 1; + } +} + +void +shpcic_mem_read_region_2(void *v, bus_space_handle_t bsh, + bus_size_t offset, uint16_t *addr, bus_size_t count) +{ + while (count--) { + *addr++ = __shpcic_mem_read_2(bsh, offset); + offset += 2; + } +} + +void +shpcic_mem_read_region_4(void *v, bus_space_handle_t bsh, + bus_size_t offset, uint32_t *addr, bus_size_t count) +{ + while (count--) { + *addr++ = __shpcic_mem_read_4(bsh, offset); + offset += 4; + } +} + +/* write */ +static inline void __shpcic_io_write_1(bus_space_handle_t bsh, + bus_size_t offset, uint8_t value); +static inline void __shpcic_io_write_2(bus_space_handle_t bsh, + bus_size_t offset, uint16_t value); +static inline void __shpcic_io_write_4(bus_space_handle_t bsh, + bus_size_t offset, uint32_t value); +static inline void __shpcic_mem_write_1(bus_space_handle_t bsh, + bus_size_t offset, uint8_t value); +static inline void __shpcic_mem_write_2(bus_space_handle_t bsh, + bus_size_t offset, uint16_t value); +static inline void __shpcic_mem_write_4(bus_space_handle_t bsh, + bus_size_t offset, uint32_t value); + +static inline void +__shpcic_io_write_1(bus_space_handle_t bsh, bus_size_t offset, + uint8_t value) +{ + u_long adr = (u_long)(bsh + offset) & SH4_PCIC_IO_MASK; + + *(volatile uint8_t *)(SH4_PCIC_IO + adr) = value; +} + +static inline void +__shpcic_io_write_2(bus_space_handle_t bsh, bus_size_t offset, + uint16_t value) +{ + u_long adr = (u_long)(bsh + offset) & SH4_PCIC_IO_MASK; + + *(volatile uint16_t *)(SH4_PCIC_IO + adr) = value; +} + +static inline void +__shpcic_io_write_4(bus_space_handle_t bsh, bus_size_t offset, + uint32_t value) +{ + u_long adr = (u_long)(bsh + offset) & SH4_PCIC_IO_MASK; + + *(volatile uint32_t *)(SH4_PCIC_IO + adr) = value; +} + +static inline void +__shpcic_mem_write_1(bus_space_handle_t bsh, bus_size_t offset, + uint8_t value) +{ + u_long adr = (u_long)(bsh + offset) & SH4_PCIC_MEM_MASK; + + *(volatile uint8_t *)(SH4_PCIC_MEM + adr) = value; +} + +static inline void +__shpcic_mem_write_2(bus_space_handle_t bsh, bus_size_t offset, + uint16_t value) +{ + u_long adr = (u_long)(bsh + offset) & SH4_PCIC_MEM_MASK; + + *(volatile uint16_t *)(SH4_PCIC_MEM + adr) = value; +} + +static inline void +__shpcic_mem_write_4(bus_space_handle_t bsh, bus_size_t offset, + uint32_t value) +{ + u_long adr = (u_long)(bsh + offset) & SH4_PCIC_MEM_MASK; + + *(volatile uint32_t *)(SH4_PCIC_MEM + adr) = value; +} + +/* + * write single + */ +void +shpcic_io_write_1(void *v, bus_space_handle_t bsh, + bus_size_t offset, uint8_t value) +{ + __shpcic_io_write_1(bsh, offset, value); +} + +void +shpcic_io_write_2(void *v, bus_space_handle_t bsh, + bus_size_t offset, uint16_t value) +{ + __shpcic_io_write_2(bsh, offset, value); +} + +void +shpcic_io_write_4(void *v, bus_space_handle_t bsh, + bus_size_t offset, uint32_t value) +{ + __shpcic_io_write_4(bsh, offset, value); +} + +void +shpcic_mem_write_1(void *v, bus_space_handle_t bsh, + bus_size_t offset, uint8_t value) +{ + __shpcic_mem_write_1(bsh, offset, value); +} + +void +shpcic_mem_write_2(void *v, bus_space_handle_t bsh, + bus_size_t offset, uint16_t value) +{ + __shpcic_mem_write_2(bsh, offset, value); +} + +void +shpcic_mem_write_4(void *v, bus_space_handle_t bsh, + bus_size_t offset, uint32_t value) +{ + __shpcic_mem_write_4(bsh, offset, value); +} + +/* + * write multi + */ +void +shpcic_io_write_multi_1(void *v, bus_space_handle_t bsh, + bus_size_t offset, const uint8_t *addr, bus_size_t count) +{ + while (count--) { + __shpcic_io_write_1(bsh, offset, *addr++); + } +} + +void +shpcic_io_write_multi_2(void *v, bus_space_handle_t bsh, + bus_size_t offset, const uint16_t *addr, bus_size_t count) +{ + while (count--) { + __shpcic_io_write_2(bsh, offset, *addr++); + } +} + +void +shpcic_io_write_multi_4(void *v, bus_space_handle_t bsh, + bus_size_t offset, const uint32_t *addr, bus_size_t count) +{ + while (count--) { + __shpcic_io_write_4(bsh, offset, *addr++); + } +} + +void +shpcic_mem_write_multi_1(void *v, bus_space_handle_t bsh, + bus_size_t offset, const uint8_t *addr, bus_size_t count) +{ + while (count--) { + __shpcic_mem_write_1(bsh, offset, *addr++); + } +} + +void +shpcic_mem_write_multi_2(void *v, bus_space_handle_t bsh, + bus_size_t offset, const uint16_t *addr, bus_size_t count) +{ + while (count--) { + __shpcic_mem_write_2(bsh, offset, *addr++); + } +} + +void +shpcic_mem_write_multi_4(void *v, bus_space_handle_t bsh, + bus_size_t offset, const uint32_t *addr, bus_size_t count) +{ + while (count--) { + __shpcic_mem_write_4(bsh, offset, *addr++); + } +} + +/* + * write region + */ +void +shpcic_io_write_region_1(void *v, bus_space_handle_t bsh, + bus_size_t offset, const uint8_t *addr, bus_size_t count) +{ + while (count--) { + __shpcic_io_write_1(bsh, offset, *addr++); + offset += 1; + } +} + +void +shpcic_io_write_region_2(void *v, bus_space_handle_t bsh, + bus_size_t offset, const uint16_t *addr, bus_size_t count) +{ + while (count--) { + __shpcic_io_write_2(bsh, offset, *addr++); + offset += 2; + } +} + +void +shpcic_io_write_region_4(void *v, bus_space_handle_t bsh, + bus_size_t offset, const uint32_t *addr, bus_size_t count) +{ + while (count--) { + __shpcic_io_write_4(bsh, offset, *addr++); + offset += 4; + } +} + +void +shpcic_mem_write_region_1(void *v, bus_space_handle_t bsh, + bus_size_t offset, const uint8_t *addr, bus_size_t count) +{ + while (count--) { + __shpcic_mem_write_1(bsh, offset, *addr++); + offset += 1; + } +} + +void +shpcic_mem_write_region_2(void *v, bus_space_handle_t bsh, + bus_size_t offset, const uint16_t *addr, bus_size_t count) +{ + while (count--) { + __shpcic_mem_write_2(bsh, offset, *addr++); + offset += 2; + } +} + +void +shpcic_mem_write_region_4(void *v, bus_space_handle_t bsh, + bus_size_t offset, const uint32_t *addr, bus_size_t count) +{ + while (count--) { + __shpcic_mem_write_4(bsh, offset, *addr++); + offset += 4; + } +} + +/* + * set multi + */ +void +shpcic_io_set_multi_1(void *v, bus_space_handle_t bsh, + bus_size_t offset, uint8_t value, bus_size_t count) +{ + while (count--) { + __shpcic_io_write_1(bsh, offset, value); + } +} + +void +shpcic_io_set_multi_2(void *v, bus_space_handle_t bsh, + bus_size_t offset, uint16_t value, bus_size_t count) +{ + while (count--) { + __shpcic_io_write_2(bsh, offset, value); + } +} + +void +shpcic_io_set_multi_4(void *v, bus_space_handle_t bsh, + bus_size_t offset, uint32_t value, bus_size_t count) +{ + while (count--) { + __shpcic_io_write_4(bsh, offset, value); + } +} + +void +shpcic_mem_set_multi_1(void *v, bus_space_handle_t bsh, + bus_size_t offset, uint8_t value, bus_size_t count) +{ + while (count--) { + __shpcic_mem_write_1(bsh, offset, value); + } +} + +void +shpcic_mem_set_multi_2(void *v, bus_space_handle_t bsh, + bus_size_t offset, uint16_t value, bus_size_t count) +{ + while (count--) { + __shpcic_mem_write_2(bsh, offset, value); + } +} + +void +shpcic_mem_set_multi_4(void *v, bus_space_handle_t bsh, + bus_size_t offset, uint32_t value, bus_size_t count) +{ + while (count--) { + __shpcic_mem_write_4(bsh, offset, value); + } +} + +/* + * set region + */ +void +shpcic_io_set_region_1(void *v, bus_space_handle_t bsh, + bus_size_t offset, uint8_t value, bus_size_t count) +{ + while (count--) { + __shpcic_io_write_1(bsh, offset, value); + offset += 1; + } +} + +void +shpcic_io_set_region_2(void *v, bus_space_handle_t bsh, + bus_size_t offset, uint16_t value, bus_size_t count) +{ + while (count--) { + __shpcic_io_write_2(bsh, offset, value); + offset += 2; + } +} + +void +shpcic_io_set_region_4(void *v, bus_space_handle_t bsh, + bus_size_t offset, uint32_t value, bus_size_t count) +{ + while (count--) { + __shpcic_io_write_4(bsh, offset, value); + offset += 4; + } +} + +void +shpcic_mem_set_region_1(void *v, bus_space_handle_t bsh, + bus_size_t offset, uint8_t value, bus_size_t count) +{ + while (count--) { + __shpcic_mem_write_1(bsh, offset, value); + offset += 1; + } +} + +void +shpcic_mem_set_region_2(void *v, bus_space_handle_t bsh, + bus_size_t offset, uint16_t value, bus_size_t count) +{ + while (count--) { + __shpcic_mem_write_2(bsh, offset, value); + offset += 2; + } +} + +void +shpcic_mem_set_region_4(void *v, bus_space_handle_t bsh, + bus_size_t offset, uint32_t value, bus_size_t count) +{ + while (count--) { + __shpcic_mem_write_4(bsh, offset, value); + offset += 4; + } +} + +/* + * copy region + */ +void +shpcic_io_copy_region_1(void *v, bus_space_handle_t bsh1, + bus_size_t off1, bus_space_handle_t bsh2, bus_size_t off2, bus_size_t count) +{ + u_long addr1 = bsh1 + off1; + u_long addr2 = bsh2 + off2; + uint8_t value; + + if (addr1 >= addr2) { /* src after dest: copy forward */ + while (count--) { + value = __shpcic_io_read_1(bsh1, off1); + __shpcic_io_write_1(bsh2, off2, value); + off1 += 1; + off2 += 1; + } + } else { /* dest after src: copy backwards */ + off1 += (count - 1) * 1; + off2 += (count - 1) * 1; + while (count--) { + value = __shpcic_io_read_1(bsh1, off1); + __shpcic_io_write_1(bsh2, off2, value); + off1 -= 1; + off2 -= 1; + } + } +} + +void +shpcic_io_copy_region_2(void *v, bus_space_handle_t bsh1, + bus_size_t off1, bus_space_handle_t bsh2, bus_size_t off2, bus_size_t count) +{ + u_long addr1 = bsh1 + off1; + u_long addr2 = bsh2 + off2; + uint16_t value; + + if (addr1 >= addr2) { /* src after dest: copy forward */ + while (count--) { + value = __shpcic_io_read_2(bsh1, off1); + __shpcic_io_write_2(bsh2, off2, value); + off1 += 2; + off2 += 2; + } + } else { /* dest after src: copy backwards */ + off1 += (count - 1) * 2; + off2 += (count - 1) * 2; + while (count--) { + value = __shpcic_io_read_2(bsh1, off1); + __shpcic_io_write_2(bsh2, off2, value); + off1 -= 2; + off2 -= 2; + } + } +} + +void +shpcic_io_copy_region_4(void *v, bus_space_handle_t bsh1, + bus_size_t off1, bus_space_handle_t bsh2, bus_size_t off2, bus_size_t count) +{ + u_long addr1 = bsh1 + off1; + u_long addr2 = bsh2 + off2; + uint32_t value; + + if (addr1 >= addr2) { /* src after dest: copy forward */ + while (count--) { + value = __shpcic_io_read_4(bsh1, off1); + __shpcic_io_write_4(bsh2, off2, value); + off1 += 4; + off2 += 4; + } + } else { /* dest after src: copy backwards */ + off1 += (count - 1) * 4; + off2 += (count - 1) * 4; + while (count--) { + value = __shpcic_io_read_4(bsh1, off1); + __shpcic_io_write_4(bsh2, off2, value); + off1 -= 4; + off2 -= 4; + } + } +} + +void +shpcic_mem_copy_region_1(void *v, bus_space_handle_t bsh1, + bus_size_t off1, bus_space_handle_t bsh2, bus_size_t off2, bus_size_t count) +{ + u_long addr1 = bsh1 + off1; + u_long addr2 = bsh2 + off2; + uint8_t value; + + if (addr1 >= addr2) { /* src after dest: copy forward */ + while (count--) { + value = __shpcic_mem_read_1(bsh1, off1); + __shpcic_mem_write_1(bsh2, off2, value); + off1 += 1; + off2 += 1; + } + } else { /* dest after src: copy backwards */ + off1 += (count - 1) * 1; + off2 += (count - 1) * 1; + while (count--) { + value = __shpcic_mem_read_1(bsh1, off1); + __shpcic_mem_write_1(bsh2, off2, value); + off1 -= 1; + off2 -= 1; + } + } +} + +void +shpcic_mem_copy_region_2(void *v, bus_space_handle_t bsh1, + bus_size_t off1, bus_space_handle_t bsh2, bus_size_t off2, bus_size_t count) +{ + u_long addr1 = bsh1 + off1; + u_long addr2 = bsh2 + off2; + uint16_t value; + + if (addr1 >= addr2) { /* src after dest: copy forward */ + while (count--) { + value = __shpcic_mem_read_2(bsh1, off1); + __shpcic_mem_write_2(bsh2, off2, value); + off1 += 2; + off2 += 2; + } + } else { /* dest after src: copy backwards */ + off1 += (count - 1) * 2; + off2 += (count - 1) * 2; + while (count--) { + value = __shpcic_mem_read_2(bsh1, off1); + __shpcic_mem_write_2(bsh2, off2, value); + off1 -= 2; + off2 -= 2; + } + } +} + +void +shpcic_mem_copy_region_4(void *v, bus_space_handle_t bsh1, + bus_size_t off1, bus_space_handle_t bsh2, bus_size_t off2, bus_size_t count) +{ + u_long addr1 = bsh1 + off1; + u_long addr2 = bsh2 + off2; + uint32_t value; + + if (addr1 >= addr2) { /* src after dest: copy forward */ + while (count--) { + value = __shpcic_mem_read_4(bsh1, off1); + __shpcic_mem_write_4(bsh2, off2, value); + off1 += 4; + off2 += 4; + } + } else { /* dest after src: copy backwards */ + off1 += (count - 1) * 4; + off2 += (count - 1) * 4; + while (count--) { + value = __shpcic_mem_read_4(bsh1, off1); + __shpcic_mem_write_4(bsh2, off2, value); + off1 -= 4; + off2 -= 4; + } + } +} diff --git a/sys/arch/sh/dev/shpcicvar.h b/sys/arch/sh/dev/shpcicvar.h new file mode 100644 index 00000000000..f000fec3084 --- /dev/null +++ b/sys/arch/sh/dev/shpcicvar.h @@ -0,0 +1,184 @@ +/* $OpenBSD: shpcicvar.h,v 1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: shpcicvar.h,v 1.6 2005/12/11 12:18:58 christos Exp $ */ + +/*- + * Copyright (c) 2005 NONAKA Kimihiro + * 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. + * + * 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. + */ + +#include <machine/bus.h> + +bus_space_tag_t shpcic_get_bus_io_tag(void); +bus_space_tag_t shpcic_get_bus_mem_tag(void); +bus_dma_tag_t shpcic_get_bus_dma_tag(void); + +int shpcic_bus_maxdevs(void *v, int busno); +pcitag_t shpcic_make_tag(void *v, int bus, int device, int function); +void shpcic_decompose_tag(void *v, pcitag_t tag, int *bp, int *dp, int *fp); +pcireg_t shpcic_conf_read(void *v, pcitag_t tag, int reg); +void shpcic_conf_write(void *v, pcitag_t tag, int reg, pcireg_t data); + +int shpcic_set_intr_priority(int intr, int level); +void *shpcic_intr_establish(int evtcode, int (*ih_func)(void *), void *ih_arg, + const char *ih_name); +void shpcic_intr_disestablish(void *ih); + +/* + * shpcic io/mem bus space + */ +int shpcic_iomem_map(void *v, bus_addr_t bpa, bus_size_t size, int flags, + bus_space_handle_t *bshp); +void shpcic_iomem_unmap(void *v, bus_space_handle_t bsh, bus_size_t size); +int shpcic_iomem_subregion(void *v, bus_space_handle_t bsh, bus_size_t offset, + bus_size_t size, bus_space_handle_t *nbshp); +int shpcic_iomem_alloc(void *v, bus_addr_t rstart, bus_addr_t rend, + bus_size_t size, bus_size_t alignment, bus_size_t boundary, int flags, + bus_addr_t *bpap, bus_space_handle_t *bshp); +void shpcic_iomem_free(void *v, bus_space_handle_t bsh, bus_size_t size); + +/* read single */ +uint8_t shpcic_io_read_1(void *v, bus_space_handle_t bsh, bus_size_t offset); +uint16_t shpcic_io_read_2(void *v, bus_space_handle_t bsh, bus_size_t offset); +uint32_t shpcic_io_read_4(void *v, bus_space_handle_t bsh, bus_size_t offset); +uint8_t shpcic_mem_read_1(void *v, bus_space_handle_t bsh, bus_size_t offset); +uint16_t shpcic_mem_read_2(void *v, bus_space_handle_t bsh, bus_size_t offset); +uint32_t shpcic_mem_read_4(void *v, bus_space_handle_t bsh, bus_size_t offset); + +/* read multi */ +void shpcic_io_read_multi_1(void *v, bus_space_handle_t bsh, + bus_size_t offset, uint8_t *addr, bus_size_t count); +void shpcic_io_read_multi_2(void *v, bus_space_handle_t bsh, + bus_size_t offset, uint16_t *addr, bus_size_t count); +void shpcic_io_read_multi_4(void *v, bus_space_handle_t bsh, + bus_size_t offset, uint32_t *addr, bus_size_t count); +void shpcic_mem_read_multi_1(void *v, bus_space_handle_t bsh, + bus_size_t offset, uint8_t *addr, bus_size_t count); +void shpcic_mem_read_multi_2(void *v, bus_space_handle_t bsh, + bus_size_t offset, uint16_t *addr, bus_size_t count); +void shpcic_mem_read_multi_4(void *v, bus_space_handle_t bsh, + bus_size_t offset, uint32_t *addr, bus_size_t count); + +/* read region */ +void shpcic_io_read_region_1(void *v, bus_space_handle_t bsh, + bus_size_t offset, uint8_t *addr, bus_size_t count); +void shpcic_io_read_region_2(void *v, bus_space_handle_t bsh, + bus_size_t offset, uint16_t *addr, bus_size_t count); +void shpcic_io_read_region_4(void *v, bus_space_handle_t bsh, + bus_size_t offset, uint32_t *addr, bus_size_t count); +void shpcic_mem_read_region_1(void *v, bus_space_handle_t bsh, + bus_size_t offset, uint8_t *addr, bus_size_t count); +void shpcic_mem_read_region_2(void *v, bus_space_handle_t bsh, + bus_size_t offset, uint16_t *addr, bus_size_t count); +void shpcic_mem_read_region_4(void *v, bus_space_handle_t bsh, + bus_size_t offset, uint32_t *addr, bus_size_t count); + +/* write single */ +void shpcic_io_write_1(void *v, bus_space_handle_t bsh, + bus_size_t offset, uint8_t data); +void shpcic_io_write_2(void *v, bus_space_handle_t bsh, + bus_size_t offset, uint16_t data); +void shpcic_io_write_4(void *v, bus_space_handle_t bsh, + bus_size_t offset, uint32_t data); +void shpcic_mem_write_1(void *v, bus_space_handle_t bsh, + bus_size_t offset, uint8_t data); +void shpcic_mem_write_2(void *v, bus_space_handle_t bsh, + bus_size_t offset, uint16_t data); +void shpcic_mem_write_4(void *v, bus_space_handle_t bsh, + bus_size_t offset, uint32_t data); + +/* write multi */ +void shpcic_io_write_multi_1(void *v, bus_space_handle_t bsh, + bus_size_t offset, const uint8_t *addr, bus_size_t count); +void shpcic_io_write_multi_2(void *v, bus_space_handle_t bsh, + bus_size_t offset, const uint16_t *addr, bus_size_t count); +void shpcic_io_write_multi_4(void *v, bus_space_handle_t bsh, + bus_size_t offset, const uint32_t *addr, bus_size_t count); +void shpcic_mem_write_multi_1(void *v, bus_space_handle_t bsh, + bus_size_t offset, const uint8_t *addr, bus_size_t count); +void shpcic_mem_write_multi_2(void *v, bus_space_handle_t bsh, + bus_size_t offset, const uint16_t *addr, bus_size_t count); +void shpcic_mem_write_multi_4(void *v, bus_space_handle_t bsh, + bus_size_t offset, const uint32_t *addr, bus_size_t count); + +/* write region */ +void shpcic_io_write_region_1(void *v, bus_space_handle_t bsh, + bus_size_t offset, const uint8_t *addr, bus_size_t count); +void shpcic_io_write_region_2(void *v, bus_space_handle_t bsh, + bus_size_t offset, const uint16_t *addr, bus_size_t count); +void shpcic_io_write_region_4(void *v, bus_space_handle_t bsh, + bus_size_t offset, const uint32_t *addr, bus_size_t count); +void shpcic_mem_write_region_1(void *v, bus_space_handle_t bsh, + bus_size_t offset, const uint8_t *addr, bus_size_t count); +void shpcic_mem_write_region_2(void *v, bus_space_handle_t bsh, + bus_size_t offset, const uint16_t *addr, bus_size_t count); +void shpcic_mem_write_region_4(void *v, bus_space_handle_t bsh, + bus_size_t offset, const uint32_t *addr, bus_size_t count); + +/* set multi */ +void shpcic_io_set_multi_1(void *v, bus_space_handle_t bsh, + bus_size_t offset, uint8_t val, bus_size_t count); +void shpcic_io_set_multi_2(void *v, bus_space_handle_t bsh, + bus_size_t offset, uint16_t val, bus_size_t count); +void shpcic_io_set_multi_4(void *v, bus_space_handle_t bsh, + bus_size_t offset, uint32_t val, bus_size_t count); +void shpcic_mem_set_multi_1(void *v, bus_space_handle_t bsh, + bus_size_t offset, uint8_t val, bus_size_t count); +void shpcic_mem_set_multi_2(void *v, bus_space_handle_t bsh, + bus_size_t offset, uint16_t val, bus_size_t count); +void shpcic_mem_set_multi_4(void *v, bus_space_handle_t bsh, + bus_size_t offset, uint32_t val, bus_size_t count); + +/* set region */ +void shpcic_io_set_region_1(void *v, bus_space_handle_t bsh, + bus_size_t offset, uint8_t val, bus_size_t count); +void shpcic_io_set_region_2(void *v, bus_space_handle_t bsh, + bus_size_t offset, uint16_t val, bus_size_t count); +void shpcic_io_set_region_4(void *v, bus_space_handle_t bsh, + bus_size_t offset, uint32_t val, bus_size_t count); +void shpcic_mem_set_region_1(void *v, bus_space_handle_t bsh, + bus_size_t offset, uint8_t val, bus_size_t count); +void shpcic_mem_set_region_2(void *v, bus_space_handle_t bsh, + bus_size_t offset, uint16_t val, bus_size_t count); +void shpcic_mem_set_region_4(void *v, bus_space_handle_t bsh, + bus_size_t offset, uint32_t val, bus_size_t count); + +/* copy region */ +void shpcic_io_copy_region_1(void *v, bus_space_handle_t bsh1, + bus_size_t off1, bus_space_handle_t bsh2, bus_size_t off2, + bus_size_t count); +void shpcic_io_copy_region_2(void *v, bus_space_handle_t bsh1, + bus_size_t off1, bus_space_handle_t bsh2, bus_size_t off2, + bus_size_t count); +void shpcic_io_copy_region_4(void *v, bus_space_handle_t bsh1, + bus_size_t off1, bus_space_handle_t bsh2, bus_size_t off2, + bus_size_t count); +void shpcic_mem_copy_region_1(void *v, bus_space_handle_t bsh1, + bus_size_t off1, bus_space_handle_t bsh2, bus_size_t off2, + bus_size_t count); +void shpcic_mem_copy_region_2(void *v, bus_space_handle_t bsh1, + bus_size_t off1, bus_space_handle_t bsh2, bus_size_t off2, + bus_size_t count); +void shpcic_mem_copy_region_4(void *v, bus_space_handle_t bsh1, + bus_size_t off1, bus_space_handle_t bsh2, bus_size_t off2, + bus_size_t count); diff --git a/sys/arch/sh/include/_types.h b/sys/arch/sh/include/_types.h new file mode 100644 index 00000000000..8b528bbf524 --- /dev/null +++ b/sys/arch/sh/include/_types.h @@ -0,0 +1,121 @@ +/* $OpenBSD: _types.h,v 1.1 2006/10/06 21:02:55 miod Exp $ */ + +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. 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. 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. + * + * @(#)types.h 8.3 (Berkeley) 1/5/94 + * @(#)ansi.h 8.2 (Berkeley) 1/4/94 + */ + +#ifndef _SH__TYPES_H_ +#define _SH__TYPES_H_ + +#if defined(_KERNEL) +typedef struct label_t { + int val[9]; +} label_t; +#endif + +/* 7.18.1.1 Exact-width integer types */ +typedef __signed char __int8_t; +typedef unsigned char __uint8_t; +typedef short __int16_t; +typedef unsigned short __uint16_t; +typedef int __int32_t; +typedef unsigned int __uint32_t; +/* LONGLONG */ +typedef long long __int64_t; +/* LONGLONG */ +typedef unsigned long long __uint64_t; + +/* 7.18.1.2 Minimum-width integer types */ +typedef __int8_t __int_least8_t; +typedef __uint8_t __uint_least8_t; +typedef __int16_t __int_least16_t; +typedef __uint16_t __uint_least16_t; +typedef __int32_t __int_least32_t; +typedef __uint32_t __uint_least32_t; +typedef __int64_t __int_least64_t; +typedef __uint64_t __uint_least64_t; + +/* 7.18.1.3 Fastest minimum-width integer types */ +typedef __int32_t __int_fast8_t; +typedef __uint32_t __uint_fast8_t; +typedef __int32_t __int_fast16_t; +typedef __uint32_t __uint_fast16_t; +typedef __int32_t __int_fast32_t; +typedef __uint32_t __uint_fast32_t; +typedef __int64_t __int_fast64_t; +typedef __uint64_t __uint_fast64_t; + +/* 7.18.1.4 Integer types capable of holding object pointers */ +typedef long __intptr_t; +typedef unsigned long __uintptr_t; + +/* 7.18.1.5 Greatest-width integer types */ +typedef __int64_t __intmax_t; +typedef __uint64_t __uintmax_t; + +/* Register size */ +typedef __uint32_t __register_t; + +/* VM system types */ +typedef unsigned long __vaddr_t; +typedef unsigned long __paddr_t; +typedef unsigned long __vsize_t; +typedef unsigned long __psize_t; + +/* Standard system types */ +typedef int __clock_t; +typedef int __clockid_t; +typedef long long __off_t; +typedef long __ptrdiff_t; +typedef unsigned long __size_t; +typedef long __ssize_t; +typedef int __time_t; +typedef int __timer_t; +#if defined(__GNUC__) && __GNUC__ >= 3 +typedef __builtin_va_list __va_list; +#else +struct __va_list_tag; +typedef struct __va_list_tag * __va_list; +#endif + +/* Wide character support types */ +#ifndef __cplusplus +typedef int __wchar_t; +#endif +typedef int __wint_t; +typedef int __rune_t; +typedef void * __wctrans_t; +typedef void * __wctype_t; + +/* Feature test macros */ +#define __HAVE_GENERIC_SOFT_INTERRUPTS + +#endif /* _SH__TYPES_H_ */ diff --git a/sys/arch/sh/include/asm.h b/sys/arch/sh/include/asm.h new file mode 100644 index 00000000000..052d5a1748a --- /dev/null +++ b/sys/arch/sh/include/asm.h @@ -0,0 +1,217 @@ +/* $OpenBSD: asm.h,v 1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: asm.h,v 1.25 2006/01/20 22:02:40 christos Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * 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. 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. + * + * @(#)asm.h 5.5 (Berkeley) 5/7/91 + */ + +#ifndef _SH_ASM_H_ +#define _SH_ASM_H_ + +#ifdef __ELF__ +# define _C_LABEL(x) x +#else +#ifdef __STDC__ +# define _C_LABEL(x) _ ## x +#else +# define _C_LABEL(x) _/**/x +#endif +#endif +#define _ASM_LABEL(x) x + +#ifdef __STDC__ +# define __CONCAT(x,y) x ## y +# define __STRING(x) #x +#else +# define __CONCAT(x,y) x/**/y +# define __STRING(x) "x" +#endif + +/* let kernels and others override entrypoint alignment */ +#ifndef _ALIGN_TEXT +# define _ALIGN_TEXT .align 2 +#endif + +#ifdef __ELF__ +#define _ENTRY(x) \ + .text ;\ + _ALIGN_TEXT ;\ + .globl x ;\ + .type x,@function ;\ + x: +#else /* !__ELF__ */ +#define _ENTRY(x) \ + .text ;\ + _ALIGN_TEXT ;\ + .globl x ;\ + x: +#endif /* !__ELF__ */ + +#ifdef GPROF +#define _PROF_PROLOGUE \ + mov.l 1f,r1 ; \ + mova 2f,r0 ; \ + jmp @r1 ; \ + nop ; \ + .align 2 ; \ +1: .long __mcount ; \ +2: +#else /* !GPROF */ +#define _PROF_PROLOGUE +#endif /* !GPROF */ + +#define ENTRY(y) _ENTRY(_C_LABEL(y)) _PROF_PROLOGUE +#define NENTRY(y) _ENTRY(_C_LABEL(y)) +#define ASENTRY(y) _ENTRY(_ASM_LABEL(y)) _PROF_PROLOGUE + +#define SET_ENTRY_SIZE(y) \ + .size _C_LABEL(y), . - _C_LABEL(y) + +#define SET_ASENTRY_SIZE(y) \ + .size _ASM_LABEL(y), . - _ASM_LABEL(y) + +#ifdef __ELF__ +#define ALTENTRY(name) \ + .globl _C_LABEL(name) ;\ + .type _C_LABEL(name),@function ;\ + _C_LABEL(name): +#else +#define ALTENTRY(name) \ + .globl _C_LABEL(name) ;\ + _C_LABEL(name): +#endif + + +/* + * Hide the gory details of PIC calls vs. normal calls. Use as in the + * following example: + * + * sts.l pr, @-sp + * PIC_PROLOGUE(.L_got, r0) ! saves old r12 on stack + * ... + * mov.l .L_function_1, r0 + * 1: CALL r0 ! each call site needs a label + * nop + * ... + * mov.l .L_function_2, r0 + * 2: CALL r0 + * nop + * ... + * PIC_EPILOGUE ! restores r12 from stack + * lds.l @sp+, pr ! so call in right order + * rts + * nop + * + * .align 2 + * .L_got: + * PIC_GOT_DATUM + * .L_function_1: ! if you call the same function twice + * CALL_DATUM(function, 1b) ! provide call datum for each call + * .L_function_2: + * CALL_DATUM(function, 2b) + */ + +#ifdef PIC + +#define PIC_PLT(x) x@PLT +#define PIC_GOT(x) x@GOT +#define PIC_GOTOFF(x) x@GOTOFF + +#define PIC_PROLOGUE(got) \ + mov.l r12, @-sp; \ + PIC_PROLOGUE_NOSAVE(got) + +/* + * Functions that do non local jumps don't need to preserve r12, + * so we can shave off two instructions to save/restore it. + */ +#define PIC_PROLOGUE_NOSAVE(got) \ + mov.l got, r12; \ + mova got, r0; \ + add r0, r12 + +#define PIC_EPILOGUE \ + mov.l @sp+, r12 + +#define PIC_EPILOGUE_SLOT \ + PIC_EPILOGUE + +#define PIC_GOT_DATUM \ + .long _GLOBAL_OFFSET_TABLE_ + +#define CALL bsrf +#define JUMP braf + +#define CALL_DATUM(function, lpcs) \ + .long PIC_PLT(function) - ((lpcs) + 4 - (.)) + +/* + * This will result in text relocations in the shared library, + * unless the function is local or has hidden or protected visibility. + * Does not require PIC prologue. + */ +#define CALL_DATUM_LOCAL(function, lpcs) \ + .long function - ((lpcs) + 4) + +#else /* !PIC */ + +#define PIC_PROLOGUE(label) +#define PIC_PROLOGUE_NOSAVE(label) +#define PIC_EPILOGUE +#define PIC_EPILOGUE_SLOT nop +#define PIC_GOT_DATUM + +#define CALL jsr @ +#define JUMP jmp @ + +#define CALL_DATUM(function, lpcs) \ + .long function + +#define CALL_DATUM_LOCAL(function, lpcs) \ + .long function + +#endif /* !PIC */ + + +#define ASMSTR .asciz + +#ifdef __ELF__ +#define WEAK_ALIAS(alias,sym) \ + .weak _C_LABEL(alias); \ + _C_LABEL(alias) = _C_LABEL(sym) +#endif + +#define WARN_REFERENCES(_sym,_msg) \ + .section .gnu.warning._sym; .ascii _msg; .previous + +#endif /* !_SH_ASM_H_ */ diff --git a/sys/arch/sh/include/bscreg.h b/sys/arch/sh/include/bscreg.h new file mode 100644 index 00000000000..86ea687978d --- /dev/null +++ b/sys/arch/sh/include/bscreg.h @@ -0,0 +1,70 @@ +/* $OpenBSD: bscreg.h,v 1.1.1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: bscreg.h,v 1.6 2005/12/11 12:18:58 christos Exp $ */ + +/*- + * Copyright (C) 1999 SAITOH Masanobu. 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. 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 _SH_BSCREG_H_ +#define _SH_BSCREG_H_ +#include <sh/devreg.h> + +/* + * Bus State Controller + */ + +#define SH3_BCR1 0xffffff60 /* 16bit */ +#define SH3_BCR2 0xffffff62 /* 16bit */ +#define SH3_WCR1 0xffffff64 /* 16bit */ +#define SH3_WCR2 0xffffff66 /* 16bit */ +#define SH3_MCR 0xffffff68 /* 16bit */ +#define SH3_DCR 0xffffff6a /* 16bit */ +#define SH3_PCR 0xffffff6c /* 16bit */ +#define SH3_RTCSR 0xffffff6e /* 16bit */ +#define SH3_RTCNT 0xffffff70 /* 16bit */ +#define SH3_RTCOR 0xffffff72 /* 16bit */ +#define SH3_RFCR 0xffffff74 /* 16bit */ +#define SH3_BCR3 0xffffff7e /* 16bit */ + +#define SH4_BCR1 0xff800000 /* 32bit */ +#define SH4_BCR2 0xff800004 /* 16bit */ +#define SH4_WCR1 0xff800008 /* 32bit */ +#define SH4_WCR2 0xff80000c /* 32bit */ +#define SH4_WCR3 0xff800010 /* 32bit */ +#define SH4_MCR 0xff800014 /* 32bit */ +#define SH4_PCR 0xff800018 /* 16bit */ +#define SH4_RTCSR 0xff80001c /* 16bit */ +#define SH4_RTCNT 0xff800020 /* 16bit */ +#define SH4_RTCOR 0xff800024 /* 16bit */ +#define SH4_RFCR 0xff800028 /* 16bit */ +#define SH4_BCR3 0xff800050 /* 16bit: SH7751R */ +#define SH4_BCR4 0xfe0a00f0 /* 32bit: SH7751R */ + +#define BCR1_MASTER (1 << 30) +#define BCR1_BREQEN (1 << 19) + +#define BCR2_PORTEN (1 << 0) + +#endif /* !_SH_BSCREG_H_ */ diff --git a/sys/arch/sh/include/cache.h b/sys/arch/sh/include/cache.h new file mode 100644 index 00000000000..2e4fa50249a --- /dev/null +++ b/sys/arch/sh/include/cache.h @@ -0,0 +1,194 @@ +/* $OpenBSD: cache.h,v 1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: cache.h,v 1.7 2006/01/21 00:46:36 uwe Exp $ */ + +/*- + * Copyright (c) 2002 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by UCHIYAMA Yasushi. + * + * 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. + */ + +/* + * Cache configurations. + * + * SH3 I/D unified virtual-index physical-tag cache. + * SH4 I/D separated virtual-index physical-tag cache. + * + * + * size line-size entry way type + * SH7708 4/8K 16B 128 2/4 P0,P2,U0 [1] + * P1 [2] + * SH7709 4/8K 16B 128 2/4 [1] + * SH7709A 16K 16B 256 4 [1] + * + * SH7750 I$ D$ line-size entry way + * 8K 8/16K 32B 256 1 [1] + * SH7750 + * SH7750S + * SH7751 I$ D$ line-size entry way + * 8K 8/16K 32B 256 1 [1] + * + * SH7750R + * SH7751R I$ D$ line-size entry way + * 16K 16/32K 32B 512 2 [1] + * + * [1] write-through/back selectable + * [2] write-through only + * + * Cache operations. + * + * There are some rules that must be followed: + * + * I-cache Sync (all or range): + * The goal is to synchronize the instruction stream, + * so you may need to write-back dirty data cache + * blocks first. If a range is requested, and you + * can't synchronize just a range, you have to hit + * the whole thing. + * + * D-cache Write-back Invalidate range: + * If you can't WB-Inv a range, you must WB-Inv the + * entire D-cache. + * + * D-cache Invalidate: + * If you can't Inv the D-cache without doing a + * Write-back, YOU MUST PANIC. This is to catch + * errors in calling code. Callers must be aware + * of this scenario, and must handle it appropriately + * (consider the bus_dma(9) operations). + * + * D-cache Write-back: + * If you can't Write-back without doing an invalidate, + * that's fine. Then treat this as a WB-Inv. Skipping + * the invalidate is merely an optimization. + * + * All operations: + * Valid virtual addresses must be passed to the + * cache operation. + * + * + * sh_icache_sync_all Synchronize I-cache + * + * sh_icache_sync_range Synchronize I-cache range + * + * sh_icache_sync_range_index (index ops) + * + * sh_dcache_wbinv_all Write-back Invalidate D-cache + * + * sh_dcache_wbinv_range Write-back Invalidate D-cache range + * + * sh_dcache_wbinv_range_index (index ops) + * + * sh_dcache_inv_range Invalidate D-cache range + * + * sh_dcache_wb_range Write-back D-cache range + * + * If I/D unified cache (SH3), I-cache ops are writeback invalidate + * operation. + * If write-through mode, sh_dcache_wb_range is no-operation. + * + */ + +#ifndef _SH_CACHE_H_ +#define _SH_CACHE_H_ + +#ifdef _KERNEL +struct sh_cache_ops { + void (*_icache_sync_all)(void); + void (*_icache_sync_range)(vaddr_t, vsize_t); + void (*_icache_sync_range_index)(vaddr_t, vsize_t); + + void (*_dcache_wbinv_all)(void); + void (*_dcache_wbinv_range)(vaddr_t, vsize_t); + void (*_dcache_wbinv_range_index)(vaddr_t, vsize_t); + void (*_dcache_inv_range)(vaddr_t, vsize_t); + void (*_dcache_wb_range)(vaddr_t, vsize_t); +}; + +/* Cache configurations */ +#define sh_cache_enable_unified sh_cache_enable_icache +extern int sh_cache_enable_icache; +extern int sh_cache_enable_dcache; +extern int sh_cache_write_through; +extern int sh_cache_write_through_p0_u0_p3; +extern int sh_cache_write_through_p1; +extern int sh_cache_ways; +extern int sh_cache_unified; +#define sh_cache_size_unified sh_cache_size_icache +extern int sh_cache_size_icache; +extern int sh_cache_size_dcache; +extern int sh_cache_line_size; +/* for n-way set associative cache */ +extern int sh_cache_way_size; +extern int sh_cache_way_shift; +extern int sh_cache_entry_mask; + +/* Special mode */ +extern int sh_cache_ram_mode; +extern int sh_cache_index_mode_icache; +extern int sh_cache_index_mode_dcache; + +extern struct sh_cache_ops sh_cache_ops; + +#define sh_icache_sync_all() \ + (*sh_cache_ops._icache_sync_all)() + +#define sh_icache_sync_range(v, s) \ + (*sh_cache_ops._icache_sync_range)((v), (s)) + +#define sh_icache_sync_range_index(v, s) \ + (*sh_cache_ops._icache_sync_range_index)((v), (s)) + +#define sh_dcache_wbinv_all() \ + (*sh_cache_ops._dcache_wbinv_all)() + +#define sh_dcache_wbinv_range(v, s) \ + (*sh_cache_ops._dcache_wbinv_range)((v), (s)) + +#define sh_dcache_wbinv_range_index(v, s) \ + (*sh_cache_ops._dcache_wbinv_range_index)((v), (s)) + +#define sh_dcache_inv_range(v, s) \ + (*sh_cache_ops._dcache_inv_range)((v), (s)) + +#define sh_dcache_wb_range(v, s) \ + (*sh_cache_ops._dcache_wb_range)((v), (s)) + +void sh_cache_init(void); +void sh_cache_information(void); + +#define SH_HAS_UNIFIED_CACHE CPU_IS_SH3 +#define SH_HAS_VIRTUAL_ALIAS CPU_IS_SH4 +#define SH_HAS_WRITEBACK_CACHE (!sh_cache_write_through) + +#endif /* _KERNEL */ +#endif /* _SH_CACHE_H_ */ diff --git a/sys/arch/sh/include/cache_sh3.h b/sys/arch/sh/include/cache_sh3.h new file mode 100644 index 00000000000..b51e1c469b5 --- /dev/null +++ b/sys/arch/sh/include/cache_sh3.h @@ -0,0 +1,159 @@ +/* $OpenBSD: cache_sh3.h,v 1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: cache_sh3.h,v 1.8 2006/03/04 01:55:03 uwe Exp $ */ + +/*- + * Copyright (c) 2002 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by UCHIYAMA Yasushi. + * + * 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. + */ + +/* + * SH3: SH7708, SH7708S, SH7708R, SH7709, SH7709A + */ +#ifndef _SH_CACHE_SH3_H_ +#define _SH_CACHE_SH3_H_ +#include <sh/devreg.h> +#ifdef _KERNEL + +#define SH3_CCR 0xffffffec +#define SH3_CCR_CE 0x00000001 +#define SH3_CCR_WT 0x00000002 +/* SH7708 don't have CB bit */ +#define SH3_CCR_CB 0x00000004 +#define SH3_CCR_CF 0x00000008 +/* SH7709A don't have RA bit */ +#define SH3_CCR_RA 0x00000020 + +/* SH7709A specific cache-lock control register */ +#define SH7709A_CCR2 0xa40000b0 +#define SH7709A_CCR2_W2LOCK 0x00000001 +#define SH7709A_CCR2_W2LOAD 0x00000002 +#define SH7709A_CCR2_W3LOCK 0x00000100 +#define SH7709A_CCR2_W3LOAD 0x00000200 + +#define SH3_CCA 0xf0000000 +/* Address specification */ +#define CCA_A 0x00000008 +#define CCA_ENTRY_SHIFT 4 +/* 8KB cache (SH7708, SH7708S, SH7708R, SH7709) */ +#define CCA_8K_ENTRY 128 +#define CCA_8K_ENTRY_MASK 0x000007f0 /* [10:4] */ +#define CCA_8K_WAY_SHIFT 11 +#define CCA_8K_WAY_MASK 0x00001800 /* [12:11] */ +/* 16KB cache (SH7709A) */ +#define CCA_16K_ENTRY 256 +#define CCA_16K_ENTRY_MASK 0x00000ff0 /* [11:4] */ +#define CCA_16K_WAY_SHIFT 12 +#define CCA_16K_WAY_MASK 0x00003000 /* [13:12] */ + +/* Data specification */ +#define CCA_V 0x00000001 +#define CCA_U 0x00000002 +#define CCA_LRU_SHIFT 4 +#define CCA_LRU_MASK 0x000003f0 /* [9:4] */ +#define CCA_TAGADDR_SHIFT 10 +#define CCA_TAGADDR_MASK 0xfffffc00 /* [31:10] */ + +#define SH3_CCD 0xf1000000 +/* Address specification */ +#define CCD_L_SHIFT 2 +#define CCD_L_MASK 0x0000000c /* [3:2] */ +#define CCD_E_SHIFT 4 +#define CCD_8K_E_MASK 0x000007f0 /* [10:4] */ +#define CCD_16K_E_MASK 0x00000ff0 /* [11:4] */ +#define CCD_8K_W_SHIFT 11 +#define CCD_8K_W_MASK 0x00001800 /* [12:11] */ +#define CCD_16K_W_SHIFT 12 +#define CCD_16K_W_MASK 0x00003000 /* [13:12] */ +/* Data specification */ + +/* + * Configuration + */ +#define SH3_CACHE_LINESZ 16 +#define SH3_CACHE_NORMAL_WAY 4 +#define SH3_CACHE_RAMMODE_WAY 2 + +#define SH3_CACHE_8K_ENTRY 128 +#define SH3_CACHE_8K_WAY_NORMAL 4 +#define SH3_CACHE_8K_WAY_RAMMODE 2 + +#define SH3_CACHE_16K_ENTRY 256 +#define SH3_CACHE_16K_WAY 4 + +/* + * cache flush macro for locore level code. + */ +#define SH3_CACHE_8K_FLUSH(maxway) \ +do { \ + uint32_t __e, __w, __wa, __a; \ + \ + for (__w = 0; __w < maxway; __w++) { \ + __wa = SH3_CCA | __w << CCA_8K_WAY_SHIFT; \ + for (__e = 0; __e < CCA_8K_ENTRY; __e++) { \ + __a = __wa |(__e << CCA_ENTRY_SHIFT); \ + (*(volatile uint32_t *)__a) &= \ + ~(CCA_U | CCA_V); \ + } \ + } \ +} while (/*CONSTCOND*/0) + +#define SH3_CACHE_16K_FLUSH() \ +do { \ + uint32_t __e, __w, __wa, __a; \ + \ + for (__w = 0; __w < SH3_CACHE_16K_WAY; __w++) { \ + __wa = SH3_CCA | __w << CCA_16K_WAY_SHIFT; \ + for (__e = 0; __e < CCA_16K_ENTRY; __e++) { \ + __a = __wa |(__e << CCA_ENTRY_SHIFT); \ + (*(volatile uint32_t *)__a) &= \ + ~(CCA_U | CCA_V); \ + } \ + } \ +} while (/*CONSTCOND*/0) + +#define SH7708_CACHE_FLUSH() SH3_CACHE_8K_FLUSH(4) +#define SH7708_CACHE_FLUSH_RAMMODE() SH3_CACHE_8K_FLUSH(2) +#define SH7708S_CACHE_FLUSH() SH3_CACHE_8K_FLUSH(4) +#define SH7708S_CACHE_FLUSH_RAMMODE() SH3_CACHE_8K_FLUSH(2) +#define SH7708R_CACHE_FLUSH() SH3_CACHE_8K_FLUSH(4) +#define SH7708R_CACHE_FLUSH_RAMMODE() SH3_CACHE_8K_FLUSH(2) +#define SH7709_CACHE_FLUSH() SH3_CACHE_8K_FLUSH(4) +#define SH7709_CACHE_FLUSH_RAMMODE() SH3_CACHE_8K_FLUSH(2) +#define SH7709A_CACHE_FLUSH() SH3_CACHE_16K_FLUSH() + +#ifndef _LOCORE +extern void sh3_cache_config(void); +#endif +#endif /* _KERNEL */ +#endif /* !_SH_CACHE_SH3_H_ */ diff --git a/sys/arch/sh/include/cache_sh4.h b/sys/arch/sh/include/cache_sh4.h new file mode 100644 index 00000000000..dfc5ff14434 --- /dev/null +++ b/sys/arch/sh/include/cache_sh4.h @@ -0,0 +1,155 @@ +/* $OpenBSD: cache_sh4.h,v 1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: cache_sh4.h,v 1.11 2006/03/04 01:55:03 uwe Exp $ */ + +/*- + * Copyright (c) 2002 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by UCHIYAMA Yasushi. + * + * 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. + */ + +/* + * SH4: SH7750 SH7750S SH7750R SH7751 SH7751R + */ + +#ifndef _SH_CACHE_SH4_H_ +#define _SH_CACHE_SH4_H_ +#include <sh/devreg.h> +#ifdef _KERNEL + +#define SH4_ICACHE_SIZE 8192 +#define SH4_DCACHE_SIZE 16384 +#define SH4_EMODE_ICACHE_SIZE 16384 +#define SH4_EMODE_DCACHE_SIZE 32768 +#define SH4_CACHE_LINESZ 32 + +#define SH4_CCR 0xff00001c +#define SH4_CCR_EMODE 0x80000000 +#define SH4_CCR_IIX 0x00008000 +#define SH4_CCR_ICI 0x00000800 +#define SH4_CCR_ICE 0x00000100 +#define SH4_CCR_OIX 0x00000080 +#define SH4_CCR_ORA 0x00000020 +#define SH4_CCR_OCI 0x00000008 +#define SH4_CCR_CB 0x00000004 +#define SH4_CCR_WT 0x00000002 +#define SH4_CCR_OCE 0x00000001 + +#define SH4_QACR0 0xff000038 +#define SH4_QACR1 0xff00003c +#define SH4_QACR_AREA_SHIFT 2 +#define SH4_QACR_AREA_MASK 0x0000001c + +/* I-cache address/data array */ +#define SH4_CCIA 0xf0000000 +/* address specification */ +#define CCIA_A 0x00000008 /* associate bit */ +#define CCIA_ENTRY_SHIFT 5 /* line size 32B */ +#define CCIA_ENTRY_MASK 0x00001fe0 /* [12:5] 256-entries */ +#define CCIA_EMODE_ENTRY_MASK 0x00003fe0 /* [13:5] 512-entries */ +/* data specification */ +#define CCIA_V 0x00000001 +#define CCIA_TAGADDR_MASK 0xfffffc00 /* [31:10] */ + +#define SH4_CCID 0xf1000000 +/* address specification */ +#define CCID_L_SHIFT 2 +#define CCID_L_MASK 0x1c /* line-size is 32B */ +#define CCID_ENTRY_MASK 0x00001fe0 /* [12:5] 256-entries */ + +/* D-cache address/data array */ +#define SH4_CCDA 0xf4000000 +/* address specification */ +#define CCDA_A 0x00000008 /* associate bit */ +#define CCDA_ENTRY_SHIFT 5 /* line size 32B */ +#define CCDA_ENTRY_MASK 0x00003fe0 /* [13:5] 512-entries */ +/* data specification */ +#define CCDA_V 0x00000001 +#define CCDA_U 0x00000002 +#define CCDA_TAGADDR_MASK 0xfffffc00 /* [31:10] */ + +#define SH4_CCDD 0xf5000000 + +/* Store Queue */ +#define SH4_SQ 0xe0000000 + +/* + * cache flush macro for locore level code. + */ +#define SH4_CACHE_FLUSH() \ +do { \ + uint32_t __e, __a; \ + \ + /* D-cache */ \ + for (__e = 0; __e < (SH4_DCACHE_SIZE / SH4_CACHE_LINESZ); __e++) {\ + __a = SH4_CCDA | (__e << CCDA_ENTRY_SHIFT); \ + (*(volatile uint32_t *)__a) &= ~(CCDA_U | CCDA_V); \ + } \ + /* I-cache */ \ + for (__e = 0; __e < (SH4_ICACHE_SIZE / SH4_CACHE_LINESZ); __e++) {\ + __a = SH4_CCIA | (__e << CCIA_ENTRY_SHIFT); \ + (*(volatile uint32_t *)__a) &= ~(CCIA_V); \ + } \ +} while(/*CONSTCOND*/0) + +#define SH4_EMODE_CACHE_FLUSH() \ +do { \ + uint32_t __e, __a; \ + \ + /* D-cache */ \ + for (__e = 0;__e < (SH4_EMODE_DCACHE_SIZE / SH4_CACHE_LINESZ);__e++) {\ + __a = SH4_CCDA | (__e << CCDA_ENTRY_SHIFT); \ + (*(volatile uint32_t *)__a) &= ~(CCDA_U | CCDA_V); \ + } \ + /* I-cache */ \ + for (__e = 0;__e < (SH4_EMODE_ICACHE_SIZE / SH4_CACHE_LINESZ);__e++) {\ + __a = SH4_CCIA | (__e << CCIA_ENTRY_SHIFT); \ + (*(volatile uint32_t *)__a) &= ~(CCIA_V); \ + } \ +} while(/*CONSTCOND*/0) + +#define SH7750_CACHE_FLUSH() SH4_CACHE_FLUSH() +#define SH7750S_CACHE_FLUSH() SH4_CACHE_FLUSH() +#define SH7751_CACHE_FLUSH() SH4_CACHE_FLUSH() +#if defined(SH4_CACHE_DISABLE_EMODE) +#define SH7750R_CACHE_FLUSH() SH4_CACHE_FLUSH() +#define SH7751R_CACHE_FLUSH() SH4_CACHE_FLUSH() +#else +#define SH7750R_CACHE_FLUSH() SH4_EMODE_CACHE_FLUSH() +#define SH7751R_CACHE_FLUSH() SH4_EMODE_CACHE_FLUSH() +#endif + +#ifndef _LOCORE +extern void sh4_cache_config(void); +#endif +#endif /* _KERNEL */ +#endif /* !_SH_CACHE_SH4_H_ */ diff --git a/sys/arch/sh/include/cdefs.h b/sys/arch/sh/include/cdefs.h new file mode 100644 index 00000000000..eb7c7eb3761 --- /dev/null +++ b/sys/arch/sh/include/cdefs.h @@ -0,0 +1,19 @@ +/* $OpenBSD: cdefs.h,v 1.1.1.1 2006/10/06 21:02:55 miod Exp $ */ + +#ifndef _SH_CDEFS_H_ +#define _SH_CDEFS_H_ + +#if defined(lint) +#define __indr_reference(sym,alias) __lint_equal__(sym,alias) +#define __warn_references(sym,msg) +#define __weak_alias(alias,sym) __lint_equal__(sym,alias) +#elif defined(__GNUC__) && defined(__STDC__) +#define __weak_alias(alias,sym) \ + __asm__(".weak " __STRING(alias) " ; " __STRING(alias) \ + " = " __STRING(sym)) +#define __warn_references(sym,msg) \ + __asm__(".section .gnu.warning." __STRING(sym) \ + " ; .ascii \"" msg "\" ; .text") +#endif + +#endif /* !_SH_CDEFS_H_ */ diff --git a/sys/arch/sh/include/clock.h b/sys/arch/sh/include/clock.h new file mode 100644 index 00000000000..80a3167b639 --- /dev/null +++ b/sys/arch/sh/include/clock.h @@ -0,0 +1,90 @@ +/* $OpenBSD: clock.h,v 1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: clock.h,v 1.2 2002/04/28 17:10:33 uch Exp $ */ + +/*- + * Copyright (c) 2002 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by UCHIYAMA Yasushi. + * + * 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. + */ + +/* + * void sh_clock_init(int flags, struct rtc_ops *): + * flags: + * SH_CLOCK_NORTC ... If SH RTC module is disabled, set this. + * internal module don't use RTCCLK. + * SH_CLOCK_NOINITTODR ... Don't initialize RTC time. + * rtc_ops: + * Machine dependent RTC ops pointer. If NULL is specified, use SH + * internal RTC. + * + * void machine_clock_init(void): + * Implement machine specific part of clock routines. + * must call sh_clock_init() at exit. + * + * int sh_clock_get_cpuclock(void): + * returns CPU clock estimated by sh_clock_init(). + * + * int sh_clock_get_pclock(void): + * returns PCLOCK. when PCLOCK is not specified by kernel configuration + * file, this value is estimated by sh_clock_init(). + * + */ +struct rtc_ops; +struct clock_ymdhms; + +void sh_clock_init(int, struct rtc_ops *); +#define SH_CLOCK_NORTC 0x00000001 +#define SH_CLOCK_NOINITTODR 0x00000002 +void machine_clock_init(void); + +int sh_clock_get_cpuclock(void); +int sh_clock_get_pclock(void); + +/* + * SH RTC module interface. + */ +void sh_rtc_init(void *); +void sh_rtc_get(void *, time_t, struct clock_ymdhms *); +void sh_rtc_set(void *, struct clock_ymdhms *); + +/* + * machine specific RTC ops + */ +struct clock_ymdhms; +struct rtc_ops { + void *_cookie; + void (*init)(void *); + void (*get)(void *, time_t, struct clock_ymdhms *); + void (*set)(void *, struct clock_ymdhms *); +}; + diff --git a/sys/arch/sh/include/cpgreg.h b/sys/arch/sh/include/cpgreg.h new file mode 100644 index 00000000000..2e7d5694295 --- /dev/null +++ b/sys/arch/sh/include/cpgreg.h @@ -0,0 +1,48 @@ +/* $OpenBSD: cpgreg.h,v 1.1.1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: cpgreg.h,v 1.5 2002/04/28 17:10:34 uch Exp $ */ + +/*- + * Copyright (C) 1999 SAITOH Masanobu. 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. 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 _SH_CPGREG_H_ +#define _SH_CPGREG_H_ + +/* + * Clock Pulse Generator + */ +#define SH3_FRQCR 0xffffff80 /* 16bit */ +#define SH4_FRQCR 0xffc00000 /* 16bit */ + +/* + * Standby Control + */ +#define SH3_STBCR 0xffffff82 /* 8bit */ +#define SH7709_STBCR2 0xffffff88 /* 8bit */ + +#define SH4_STBCR 0xffc00004 /* 8bit */ +#define SH4_STBCR2 0xffc00010 /* 8bit */ + +#endif /* !_SH_CPGREG_H_ */ diff --git a/sys/arch/sh/include/cpu.h b/sys/arch/sh/include/cpu.h new file mode 100644 index 00000000000..682ab233eaa --- /dev/null +++ b/sys/arch/sh/include/cpu.h @@ -0,0 +1,213 @@ +/* $OpenBSD: cpu.h,v 1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: cpu.h,v 1.41 2006/01/21 04:24:12 uwe Exp $ */ + +/*- + * Copyright (c) 2002 The NetBSD Foundation, Inc. All rights reserved. + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * 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. 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. + * + * @(#)cpu.h 5.4 (Berkeley) 5/9/91 + */ + +/* + * SH3/SH4 support. + * + * T.Horiuchi Brains Corp. 5/22/98 + */ + +#ifndef _SH_CPU_H_ +#define _SH_CPU_H_ + +#include <sh/psl.h> +#include <sh/frame.h> + +#ifdef _KERNEL + +/* + * Can't swapout u-area, (__SWAP_BROKEN) + * since we use P1 converted address for trapframe. + */ +#define cpu_swapin(p) /* nothing */ +#define cpu_swapout(p) /* nothing */ + +/* + * Arguments to hardclock and gatherstats encapsulate the previous + * machine state in an opaque clockframe. + */ +struct clockframe { + int spc; /* program counter at time of interrupt */ + int ssr; /* status register at time of interrupt */ + int ssp; /* stack pointer at time of interrupt */ +}; + +#define CLKF_USERMODE(cf) (!KERNELMODE((cf)->ssr)) +#define CLKF_BASEPRI(cf) (((cf)->ssr & 0xf0) == 0) +#define CLKF_PC(cf) ((cf)->spc) +#define CLKF_INTR(cf) 0 /* XXX */ + +/* + * This is used during profiling to integrate system time. It can safely + * assume that the process is resident. + */ +#define PROC_PC(p) \ + (((struct trapframe *)(p)->p_md.md_regs)->tf_spc) + +/* + * Preempt the current process if in interrupt from user mode, + * or after the current trap/syscall if in system mode. + */ +#define need_resched(ci) \ +do { \ + want_resched = 1; \ + if (curproc != NULL) \ + aston(curproc); \ +} while (/*CONSTCOND*/0) + +/* + * Give a profiling tick to the current process when the user profiling + * buffer pages are invalid. On the MIPS, request an ast to send us + * through trap, marking the proc as needing a profiling tick. + */ +#define need_proftick(p) \ +do { \ + (p)->p_flag |= P_OWEUPC; \ + aston(p); \ +} while (/*CONSTCOND*/0) + +/* + * Notify the current process (p) that it has a signal pending, + * process as soon as possible. + */ +#define signotify(p) aston(p) + +#define aston(p) ((p)->p_md.md_astpending = 1) + +extern int want_resched; /* need_resched() was called */ + +/* + * We need a machine-independent name for this. + */ +#define DELAY(x) delay(x) +#endif /* _KERNEL */ + +/* + * Logical address space of SH3/SH4 CPU. + */ +#define SH3_PHYS_MASK 0x1fffffff + +#define SH3_P0SEG_BASE 0x00000000 /* TLB mapped, also U0SEG */ +#define SH3_P0SEG_END 0x7fffffff +#define SH3_P1SEG_BASE 0x80000000 /* pa == va */ +#define SH3_P1SEG_END 0x9fffffff +#define SH3_P2SEG_BASE 0xa0000000 /* pa == va, non-cacheable */ +#define SH3_P2SEG_END 0xbfffffff +#define SH3_P3SEG_BASE 0xc0000000 /* TLB mapped, kernel mode */ +#define SH3_P3SEG_END 0xdfffffff +#define SH3_P4SEG_BASE 0xe0000000 /* peripheral space */ +#define SH3_P4SEG_END 0xffffffff + +#define SH3_P1SEG_TO_PHYS(x) ((uint32_t)(x) & SH3_PHYS_MASK) +#define SH3_P2SEG_TO_PHYS(x) ((uint32_t)(x) & SH3_PHYS_MASK) +#define SH3_PHYS_TO_P1SEG(x) ((uint32_t)(x) | SH3_P1SEG_BASE) +#define SH3_PHYS_TO_P2SEG(x) ((uint32_t)(x) | SH3_P2SEG_BASE) +#define SH3_P1SEG_TO_P2SEG(x) ((uint32_t)(x) | 0x20000000) +#define SH3_P2SEG_TO_P1SEG(x) ((uint32_t)(x) & ~0x20000000) + +#ifdef _KERNEL +#ifndef __lint__ + +/* switch from P1 to P2 */ +#define RUN_P2 do { \ + void *p; \ + p = &&P2; \ + goto *(void *)SH3_P1SEG_TO_P2SEG(p); \ + P2: (void)0; \ + } while (0) + +/* switch from P2 to P1 */ +#define RUN_P1 do { \ + void *p; \ + p = &&P1; \ + __asm volatile("nop;nop;nop;nop;nop;nop;nop;nop"); \ + goto *(void *)SH3_P2SEG_TO_P1SEG(p); \ + P1: (void)0; \ + } while (0) + +#else /* __lint__ */ +#define RUN_P2 do {} while (/* CONSTCOND */ 0) +#define RUN_P1 do {} while (/* CONSTCOND */ 0) +#endif +#endif + +#if defined(SH4) +/* SH4 Processor Version Register */ +#define SH4_PVR_ADDR 0xff000030 /* P4 address */ +#define SH4_PVR (*(volatile uint32_t *) SH4_PVR_ADDR) +#define SH4_PRR_ADDR 0xff000044 /* P4 address */ +#define SH4_PRR (*(volatile uint32_t *) SH4_PRR_ADDR) + +#define SH4_PVR_MASK 0xffffff00 +#define SH4_PVR_SH7750 0x04020500 /* SH7750 */ +#define SH4_PVR_SH7750S 0x04020600 /* SH7750S */ +#define SH4_PVR_SH775xR 0x04050000 /* SH775xR */ +#define SH4_PVR_SH7751 0x04110000 /* SH7751 */ + +#define SH4_PRR_MASK 0xfffffff0 +#define SH4_PRR_7750R 0x00000100 /* SH7750R */ +#define SH4_PRR_7751R 0x00000110 /* SH7751R */ +#endif + +/* + * pull in #defines for kinds of processors + */ +#include <machine/cputypes.h> + +/* + * CTL_MACHDEP definitions. + */ +#define CPU_CONSDEV 1 /* dev_t: console terminal device */ +#define CPU_MAXID 2 /* number of valid machdep ids */ + +#define CTL_MACHDEP_NAMES { \ + { 0, 0 }, \ + { "console_device", CTLTYPE_STRUCT }, \ +} + +#ifdef _KERNEL +void sh_cpu_init(int, int); +void sh_startup(void); +__dead void cpu_reset(void); /* soft reset */ +void _cpu_spin(uint32_t); /* for delay loop. */ +void delay(int); +struct pcb; +void savectx(struct pcb *); +void dumpsys(void); +#endif /* _KERNEL */ +#endif /* !_SH_CPU_H_ */ diff --git a/sys/arch/sh/include/cputypes.h b/sys/arch/sh/include/cputypes.h new file mode 100644 index 00000000000..5befc6321c6 --- /dev/null +++ b/sys/arch/sh/include/cputypes.h @@ -0,0 +1,79 @@ +/* $OpenBSD: cputypes.h,v 1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: cputypes.h,v 1.10 2006/01/21 00:40:36 uwe Exp $ */ + +/*- + * Copyright (c) 2002 The NetBSD Foundation, Inc. + * 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 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. + */ + +#ifndef _SH_CPUTYPES_H_ +#define _SH_CPUTYPES_H_ + +#ifdef _KERNEL + +#define CPU_ARCH_SH3 3 +#define CPU_ARCH_SH4 4 + +/* SH3 series */ +#define CPU_PRODUCT_7708 1 +#define CPU_PRODUCT_7708S 2 +#define CPU_PRODUCT_7708R 3 +#define CPU_PRODUCT_7709 4 +#define CPU_PRODUCT_7709A 5 + +/* SH4 series */ +#define CPU_PRODUCT_7750 6 +#define CPU_PRODUCT_7750S 7 +#define CPU_PRODUCT_7750R 8 +#define CPU_PRODUCT_7751 9 +#define CPU_PRODUCT_7751R 10 + + +#ifndef _LOCORE +extern int cpu_arch; +extern int cpu_product; +#if defined(SH3) && defined(SH4) +#define CPU_IS_SH3 (cpu_arch == CPU_ARCH_SH3) +#define CPU_IS_SH4 (cpu_arch == CPU_ARCH_SH4) +#elif defined(SH3) +#define CPU_IS_SH3 (/* CONSTCOND */1) +#define CPU_IS_SH4 (/* CONSTCOND */0) +#elif defined(SH4) +#define CPU_IS_SH3 (/* CONSTCOND */0) +#define CPU_IS_SH4 (/* CONSTCOND */1) +#else +#error "define SH3 and/or SH4" +#endif +#endif /* !_LOCORE */ + +#endif /* _KERNEL */ + +#endif /* !_SH_CPUTYPES_H_ */ diff --git a/sys/arch/sh/include/db_machdep.h b/sys/arch/sh/include/db_machdep.h new file mode 100644 index 00000000000..10afa9cf335 --- /dev/null +++ b/sys/arch/sh/include/db_machdep.h @@ -0,0 +1,83 @@ +/* $OpenBSD: db_machdep.h,v 1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: db_machdep.h,v 1.12 2006/05/10 06:24:03 skrll Exp $ */ + +/* + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ + +#ifndef _SH_DB_MACHDEP_H_ +#define _SH_DB_MACHDEP_H_ + +/* + * Machine-dependent defines for the kernel debugger. + */ + +#include <sys/param.h> +#include <uvm/uvm_extern.h> +#include <sh/trap.h> + +typedef vaddr_t db_addr_t; /* address - unsigned */ +typedef long db_expr_t; /* expression - signed */ + +typedef struct trapframe db_regs_t; +extern db_regs_t ddb_regs; /* register state */ +#define DDB_REGS (&ddb_regs) + +#define PC_REGS(regs) ((db_addr_t)(regs)->tf_spc) +#define PC_ADVANCE(regs) ((regs)->tf_spc += BKPT_SIZE) + +#define BKPT_INST 0xc3c3 /* breakpoint instruction */ +#define BKPT_SIZE 2 /* size of breakpoint inst */ +#define BKPT_SET(inst) BKPT_INST + +#define FIXUP_PC_AFTER_BREAK(regs) ((regs)->tf_spc -= BKPT_SIZE) + +#define IS_BREAKPOINT_TRAP(type, code) ((type) == EXPEVT_BREAK) +#define IS_WATCHPOINT_TRAP(type, code) (0) /* XXX (msaitoh) */ + +#define inst_load(ins) 0 +#define inst_store(ins) 0 + +/* macro for checking if a thread has used floating-point */ +#define db_thread_fp_used(thread) ((thread)->pcb->ims.ifps != 0) + +int kdb_trap(int, int, db_regs_t *); +boolean_t inst_call(int); +boolean_t inst_return(int); +boolean_t inst_trap_return(int); + +/* + * We use ELF symbols in DDB. + * + */ +#define DB_ELF_SYMBOLS +#define DB_ELFSIZE 32 + +/* + * We have machine-dependent commands. + */ +#define DB_MACHINE_COMMANDS + +#endif /* !_SH_DB_MACHDEP_H_ */ diff --git a/sys/arch/sh/include/devreg.h b/sys/arch/sh/include/devreg.h new file mode 100644 index 00000000000..37886f04a7b --- /dev/null +++ b/sys/arch/sh/include/devreg.h @@ -0,0 +1,83 @@ +/* $OpenBSD: devreg.h,v 1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: devreg.h,v 1.5 2006/01/21 04:57:07 uwe Exp $ */ + +/*- + * Copyright (c) 2002 The NetBSD Foundation, Inc. + * 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 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. + */ + +#ifndef _SH_DEVREG_H_ +#define _SH_DEVREG_H_ +/* + * SH embeded device register defines. + */ + +/* + * Access method + */ +#define _reg_read_1(a) (*(volatile uint8_t *)((vaddr_t)(a))) +#define _reg_read_2(a) (*(volatile uint16_t *)((vaddr_t)(a))) +#define _reg_read_4(a) (*(volatile uint32_t *)((vaddr_t)(a))) +#define _reg_write_1(a, v) \ + (*(volatile uint8_t *)(a) = (uint8_t)(v)) +#define _reg_write_2(a, v) \ + (*(volatile uint16_t *)(a) = (uint16_t)(v)) +#define _reg_write_4(a, v) \ + (*(volatile uint32_t *)(a) = (uint32_t)(v)) +#define _reg_bset_1(a, v) \ + (*(volatile uint8_t *)(a) |= (uint8_t)(v)) +#define _reg_bset_2(a, v) \ + (*(volatile uint16_t *)(a) |= (uint16_t)(v)) +#define _reg_bset_4(a, v) \ + (*(volatile uint32_t *)(a) |= (uint32_t)(v)) +#define _reg_bclr_1(a, v) \ + (*(volatile uint8_t *)(a) &= ~(uint8_t)(v)) +#define _reg_bclr_2(a, v) \ + (*(volatile uint16_t *)(a) &= ~(uint16_t)(v)) +#define _reg_bclr_4(a, v) \ + (*(volatile uint32_t *)(a) &= ~(uint32_t)(v)) + +/* + * Register address. + */ +#if defined(SH3) && defined(SH4) +#define SH_(x) __sh_ ## x +#elif defined(SH3) +#define SH_(x) SH3_ ## x +#elif defined(SH4) +#define SH_(x) SH4_ ## x +#endif + +#ifndef _LOCORE +/* Initialize register address for SH3 && SH4 kernel. */ +void sh_devreg_init(void); +#endif +#endif /* !_SH_DEVREG_H_ */ diff --git a/sys/arch/sh/include/disklabel.h b/sys/arch/sh/include/disklabel.h new file mode 100644 index 00000000000..0b61abbc41a --- /dev/null +++ b/sys/arch/sh/include/disklabel.h @@ -0,0 +1,112 @@ +/* $OpenBSD: disklabel.h,v 1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: disklabel.h,v 1.2 2001/11/25 19:02:03 thorpej Exp $ */ + +/* + * Copyright (c) 1994 Mark Brinicombe. + * Copyright (c) 1994 Brini. + * All rights reserved. + * + * This code is derived from software written for Brini by Mark Brinicombe + * + * 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 Brini. + * 4. The name of the company nor the name of the author may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY BRINI ``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 BRINI 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. + * + * RiscBSD kernel project + * + * disklabel.h + * + * machine specific disk label info + * + * Created : 04/10/94 + */ + +#ifndef _ARM_DISKLABEL_H_ +#define _ARM_DISKLABEL_H_ + +#define LABELSECTOR 1 /* sector containing label */ +#define LABELOFFSET 0 /* offset of label in sector */ +#define MAXPARTITIONS 16 /* number of partitions */ +#define RAW_PART 2 /* raw partition: XX?c */ + +#include <sys/dkbad.h> +#if 0 +#include <arm/disklabel_acorn.h> +#include <sys/disklabel_mbr.h> +#endif + +/* MBR partition table */ +#define DOSBBSECTOR 0 /* MBR sector number */ +#define DOSPARTOFF 446 /* Offset of MBR partition table */ +#define NDOSPART 4 /* # of partitions in MBR */ +#define DOSMAGICOFF 510 /* Offset of magic number */ +#define DOSMAGIC 0xaa55 /* Actual magic number */ +#define MBRMAGIC DOSMAGIC +#define DOSMBR_SIGNATURE MBRMAGIC +#define DOSMBR_SIGNATURE_OFF DOSMAGICOFF +#define DOSACTIVE 0x80 + + +struct dos_partition { + u_int8_t dp_flag; /* bootstrap flags */ + u_int8_t dp_shd; /* starting head */ + u_int8_t dp_ssect; /* starting sector */ + u_int8_t dp_scyl; /* starting cylinder */ + u_int8_t dp_typ; /* partition type (see below) */ + u_int8_t dp_ehd; /* end head */ + u_int8_t dp_esect; /* end sector */ + u_int8_t dp_ecyl; /* end cylinder */ + u_int32_t dp_start; /* absolute starting sector number */ + u_int32_t dp_size; /* partition size in sectors */ +}; + +/* Known DOS partition types. */ +#define DOSPTYP_UNUSED 0x00 /* Unused partition */ +#define DOSPTYP_FAT12 0x01 /* 12-bit FAT */ +#define DOSPTYP_FAT16S 0x04 /* 16-bit FAT, less than 32M */ +#define DOSPTYP_EXTEND 0x05 /* Extended; contains sub-partitions */ +#define DOSPTYP_FAT16B 0x06 /* 16-bit FAT, more than 32M */ +#define DOSPTYP_FAT32 0x0b /* 32-bit FAT */ +#define DOSPTYP_FAT32L 0x0c /* 32-bit FAT, LBA-mapped */ +#define DOSPTYP_FAT16L 0x0e /* 16-bit FAT, LBA-mapped */ +#define DOSPTYP_EXTENDL 0x0f /* Extended, LBA-mapped; contains sub-partitions */ +#define DOSPTYP_ONTRACK 0x54 +#define DOSPTYP_LINUX 0x83 /* That other thing */ +#define DOSPTYP_FREEBSD 0xa5 /* FreeBSD partition type */ +#define DOSPTYP_OPENBSD 0xa6 /* OpenBSD partition type */ +#define DOSPTYP_NETBSD 0xa9 /* NetBSD partition type */ + +/* Isolate the relevant bits to get sector and cylinder. */ +#define DPSECT(s) ((s) & 0x3f) +#define DPCYL(c, s) ((c) + (((s) & 0xc0) << 2)) + + +struct cpu_disklabel { + struct dos_partition dosparts[NDOSPART]; + struct dkbad bad; +}; + +#endif /* _ARM_DISKLABEL_H_ */ diff --git a/sys/arch/sh/include/endian.h b/sys/arch/sh/include/endian.h new file mode 100644 index 00000000000..9615f567cd1 --- /dev/null +++ b/sys/arch/sh/include/endian.h @@ -0,0 +1,43 @@ +/* $OpenBSD: endian.h,v 1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: endian.h,v 1.4 2000/03/17 00:09:25 mycroft Exp $ */ + +/* Written by Manuel Bouyer. Public domain */ + +#ifndef _SH_ENDIAN_H_ +#define _SH_ENDIAN_H_ + +#ifdef __GNUC__ + +#define __swap64md __swap64gen + +#define __swap16md(x) ({ \ + uint16_t rval; \ + \ + __asm volatile ("swap.b %1,%0" : "=r"(rval) : "r"(x)); \ + \ + rval; \ +}) + +#define __swap32md(x) ({ \ + uint32_t rval; \ + \ + __asm volatile ("swap.b %1,%0; swap.w %0,%0; swap.b %0,%0" \ + : "=r"(rval) : "r"(x)); \ + \ + rval; \ +}) + +#define MD_SWAP + +#endif /* __GNUC_ */ + +#ifdef __LITTLE_ENDIAN__ +#define _BYTE_ORDER _LITTLE_ENDIAN +#else +#define _BYTE_ORDER _BIG_ENDIAN +#endif +#include <sys/endian.h> + +#define __STRICT_ALIGNMENT + +#endif /* !_SH_ENDIAN_H_ */ diff --git a/sys/arch/sh/include/exec.h b/sys/arch/sh/include/exec.h new file mode 100644 index 00000000000..2bf1c48d8ae --- /dev/null +++ b/sys/arch/sh/include/exec.h @@ -0,0 +1,70 @@ +/* $OpenBSD: exec.h,v 1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: elf_machdep.h,v 1.8 2002/04/28 17:10:34 uch Exp $ */ + +#define __LDPGSZ 4096 + +#define NATIVE_EXEC_ELF + +#define ARCH_ELFSIZE 32 /* MD native binary size */ +#define ELF_TARG_CLASS ELFCLASS32 +#ifdef __LITTLE_ENDIAN__ +#define ELF_TARG_DATA ELFDATA2LSB +#else +#define ELF_TARG_DATA ELFDATA2MSB +#endif +#define ELF_TARG_MACH EM_SH + +#define _KERN_DO_ELF +#define _NLIST_DO_ELF + +/* + * SuperH ELF header flags. + */ +#define EF_SH_MACH_MASK 0x1f + +#define EF_SH_UNKNOWN 0x00 +#define EF_SH_SH1 0x01 +#define EF_SH_SH2 0x02 +#define EF_SH_SH3 0x03 +#define EF_SH_DSP 0x04 +#define EF_SH_SH3_DSP 0x05 +#define EF_SH_SH3E 0x08 +#define EF_SH_SH4 0x09 + +#define EF_SH_HAS_DSP(x) ((x) & EF_SH_DSP) +#define EF_SH_HAS_FP(x) ((x) & EF_SH_SH3E) + + +#define R_SH_NONE 0 +#define R_SH_DIR32 1 +#define R_SH_REL32 2 +#define R_SH_DIR8WPN 3 +#define R_SH_IND12W 4 +#define R_SH_DIR8WPL 5 +#define R_SH_DIR8WPZ 6 +#define R_SH_DIR8BP 7 +#define R_SH_DIR8W 8 +#define R_SH_DIR8L 9 +#define R_SH_SWITCH16 25 +#define R_SH_SWITCH32 26 +#define R_SH_USES 27 +#define R_SH_COUNT 28 +#define R_SH_ALIGN 29 +#define R_SH_CODE 30 +#define R_SH_DATA 31 +#define R_SH_LABEL 32 +#define R_SH_SWITCH8 33 +#define R_SH_GNU_VTINHERIT 34 +#define R_SH_GNU_VTENTRY 35 +#define R_SH_LOOP_START 36 +#define R_SH_LOOP_END 37 +#define R_SH_GOT32 160 +#define R_SH_PLT32 161 +#define R_SH_COPY 162 +#define R_SH_GLOB_DAT 163 +#define R_SH_JMP_SLOT 164 +#define R_SH_RELATIVE 165 +#define R_SH_GOTOFF 166 +#define R_SH_GOTPC 167 + +#define R_TYPE(name) __CONCAT(R_SH_,name) diff --git a/sys/arch/sh/include/float.h b/sys/arch/sh/include/float.h new file mode 100644 index 00000000000..b39dd8fe6ff --- /dev/null +++ b/sys/arch/sh/include/float.h @@ -0,0 +1,76 @@ +/* $OpenBSD: float.h,v 1.1 2006/10/06 21:02:55 miod Exp $ */ + +/* + * Copyright (c) 1989 Regents of the University of California. + * 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. 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. + * + * @(#)float.h 7.1 (Berkeley) 5/8/90 + */ + +#ifndef _SH_FLOAT_H_ +#define _SH_FLOAT_H_ + +#include <sys/cdefs.h> + +__BEGIN_DECLS +int __flt_rounds(void); +__END_DECLS + +#define FLT_RADIX 2 /* b */ +#define FLT_ROUNDS __flt_rounds() + +#define FLT_MANT_DIG 24 /* p */ +#define FLT_EPSILON 1.19209290E-07F /* b**(1-p) */ +#define FLT_DIG 6 /* floor((p-1)*log10(b))+(b == 10) */ +#define FLT_MIN_EXP (-125) /* emin */ +#define FLT_MIN 1.17549435E-38F /* b**(emin-1) */ +#define FLT_MIN_10_EXP (-37) /* ceil(log10(b**(emin-1))) */ +#define FLT_MAX_EXP 128 /* emax */ +#define FLT_MAX 3.40282347E+38F /* (1-b**(-p))*b**emax */ +#define FLT_MAX_10_EXP 38 /* floor(log10((1-b**(-p))*b**emax)) */ + +#define DBL_MANT_DIG 53 +#define DBL_EPSILON 2.2204460492503131E-16 +#define DBL_DIG 15 +#define DBL_MIN_EXP (-1021) +#define DBL_MIN 2.2250738585072014E-308 +#define DBL_MIN_10_EXP (-307) +#define DBL_MAX_EXP 1024 +#define DBL_MAX 1.7976931348623157E+308 +#define DBL_MAX_10_EXP 308 + +#define LDBL_MANT_DIG DBL_MANT_DIG +#define LDBL_EPSILON DBL_EPSILON +#define LDBL_DIG DBL_DIG +#define LDBL_MIN_EXP DBL_MIN_EXP +#define LDBL_MIN DBL_MIN +#define LDBL_MIN_10_EXP DBL_MIN_10_EXP +#define LDBL_MAX_EXP DBL_MAX_EXP +#define LDBL_MAX DBL_MAX +#define LDBL_MAX_10_EXP DBL_MAX_10_EXP + +#endif /* _SH_FLOAT_H_ */ diff --git a/sys/arch/sh/include/frame.h b/sys/arch/sh/include/frame.h new file mode 100644 index 00000000000..fd7176d829a --- /dev/null +++ b/sys/arch/sh/include/frame.h @@ -0,0 +1,130 @@ +/* $OpenBSD: frame.h,v 1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: frame.h,v 1.14 2005/12/11 12:18:58 christos Exp $ */ + +/*- + * Copyright (c) 2002 The NetBSD Foundation, Inc. All rights reserved. + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * 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. 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 5.2 (Berkeley) 1/18/91 + */ + +/*- + * Copyright (c) 1995 Charles M. Hannum. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * 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 5.2 (Berkeley) 1/18/91 + */ + +#ifndef _SH_FRAME_H_ +#define _SH_FRAME_H_ + +#include <sys/signal.h> + +/* + * Exception Stack Frame + */ +struct trapframe { + /* software member */ + int tf_expevt; + int tf_ubc; + /* hardware registers */ + int tf_spc; + int tf_ssr; + int tf_macl; + int tf_mach; + int tf_pr; + int tf_r13; + int tf_r12; + int tf_r11; + int tf_r10; + int tf_r9; + int tf_r8; + int tf_r7; + int tf_r6; + int tf_r5; + int tf_r4; + int tf_r3; + int tf_r2; + int tf_r1; + int tf_r0; + int tf_r15; + int tf_r14; +}; + +/* + * Stack frame inside cpu_switch() + */ +struct switchframe { + int sf_r15; + int sf_r14; + int sf_r13; + int sf_r12; + int sf_r11; + int sf_r10; + int sf_r9; + int sf_r8; + int sf_pr; + int sf_r6_bank; + int sf_sr; + int sf_r7_bank; +}; + +#endif /* !_SH_FRAME_H_ */ diff --git a/sys/arch/sh/include/ieee.h b/sys/arch/sh/include/ieee.h new file mode 100644 index 00000000000..7ee46d82db4 --- /dev/null +++ b/sys/arch/sh/include/ieee.h @@ -0,0 +1,132 @@ +/* $OpenBSD: ieee.h,v 1.1 2006/10/06 21:02:55 miod 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. 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. + * + * @(#)ieee.h 8.1 (Berkeley) 6/11/93 + */ + +/* + * ieee.h defines the machine-dependent layout of the machine's IEEE + * floating point. It does *not* define (yet?) any of the rounding + * mode bits, exceptions, and so forth. + */ + +/* + * Define the number of bits in each fraction and exponent. + * + * k k+1 + * Note that 1.0 x 2 == 0.1 x 2 and that denorms are represented + * + * (-exp_bias+1) + * as fractions that look like 0.fffff x 2 . This means that + * + * -126 + * the number 0.10000 x 2 , for instance, is the same as the normalized + * + * -127 -128 + * float 1.0 x 2 . Thus, to represent 2 , we need one leading zero + * + * -129 + * in the fraction; to represent 2 , we need two, and so on. This + * + * (-exp_bias-fracbits+1) + * implies that the smallest denormalized number is 2 + * + * for whichever format we are talking about: for single precision, for + * + * -126 -149 + * instance, we get .00000000000000000000001 x 2 , or 1.0 x 2 , and + * + * -149 == -127 - 23 + 1. + */ +#define SNG_EXPBITS 8 +#define SNG_FRACBITS 23 + +#define DBL_EXPBITS 11 +#define DBL_FRACBITS 52 + +#define EXT_EXPBITS 15 +#define EXT_FRACBITS 112 + +struct ieee_single { + u_int sng_sign:1; + u_int sng_exp:8; + u_int sng_frac:23; +}; + +struct ieee_double { + u_int dbl_sign:1; + u_int dbl_exp:11; + u_int dbl_frach:20; + u_int dbl_fracl; +}; + +struct ieee_ext { + u_int ext_sign:1; + u_int ext_exp:15; + u_int ext_frach:16; + u_int ext_frachm; + u_int ext_fraclm; + u_int ext_fracl; +}; + +/* + * Floats whose exponent is in [1..INFNAN) (of whatever type) are + * `normal'. Floats whose exponent is INFNAN are either Inf or NaN. + * Floats whose exponent is zero are either zero (iff all fraction + * bits are zero) or subnormal values. + * + * A NaN is a `signalling NaN' if its QUIETNAN bit is clear in its + * high fraction; if the bit is set, it is a `quiet NaN'. + */ +#define SNG_EXP_INFNAN 255 +#define DBL_EXP_INFNAN 2047 +#define EXT_EXP_INFNAN 32767 + +#if 0 +#define SNG_QUIETNAN (1 << 22) +#define DBL_QUIETNAN (1 << 19) +#define EXT_QUIETNAN (1 << 15) +#endif + +/* + * Exponent biases. + */ +#define SNG_EXP_BIAS 127 +#define DBL_EXP_BIAS 1023 +#define EXT_EXP_BIAS 16383 diff --git a/sys/arch/sh/include/ieeefp.h b/sys/arch/sh/include/ieeefp.h new file mode 100644 index 00000000000..141048038ad --- /dev/null +++ b/sys/arch/sh/include/ieeefp.h @@ -0,0 +1,27 @@ +/* $OpenBSD: ieeefp.h,v 1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: ieeefp.h,v 1.3 2002/04/28 17:10:34 uch Exp $ */ + +/* + * Written by J.T. Conklin, Apr 6, 1995 + * Public domain. + */ + +#ifndef _SH_IEEEFP_H_ +#define _SH_IEEEFP_H_ + +typedef int fp_except; +#define FP_X_INV 0x01 /* invalid operation exception */ +#define FP_X_DNML 0x02 /* denormalization exception */ +#define FP_X_DZ 0x04 /* divide-by-zero exception */ +#define FP_X_OFL 0x08 /* overflow exception */ +#define FP_X_UFL 0x10 /* underflow exception */ +#define FP_X_IMP 0x20 /* imprecise (loss of precision) */ + +typedef enum { + FP_RN=0, /* round to nearest representable number */ + FP_RM=1, /* round toward negative infinity */ + FP_RP=2, /* round toward positive infinity */ + FP_RZ=3 /* round to zero (truncate) */ +} fp_rnd; + +#endif /* !_SH_IEEEFP_H_ */ diff --git a/sys/arch/sh/include/intcreg.h b/sys/arch/sh/include/intcreg.h new file mode 100644 index 00000000000..e69f31db7aa --- /dev/null +++ b/sys/arch/sh/include/intcreg.h @@ -0,0 +1,127 @@ +/* $OpenBSD: intcreg.h,v 1.1.1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: intcreg.h,v 1.10 2005/12/11 12:18:58 christos Exp $ */ + +/*- + * Copyright (C) 1999 SAITOH Masanobu. 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. 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 _SH_INTCREG_H_ +#define _SH_INTCREG_H_ +#include <sh/devreg.h> + +/* + * INTC + */ +/* SH3 SH7708*, SH7709* common */ +#define SH3_ICR0 0xfffffee0 /* 16bit */ +#define SH3_IPRA 0xfffffee2 /* 16bit */ +#define SH3_IPRB 0xfffffee4 /* 16bit */ + +/* SH7709, SH7709A only */ +#define SH7709_ICR1 0xa4000010 /* 16bit */ +#define SH7709_ICR2 0xa4000012 /* 16bit */ +#define SH7709_PINTER 0xa4000014 /* 16bit */ +#define SH7709_IPRC 0xa4000016 /* 16bit */ +#define SH7709_IPRD 0xa4000018 /* 16bit */ +#define SH7709_IPRE 0xa400001a /* 16bit */ +#define SH7709_IRR0 0xa4000004 /* 8bit */ +#define SH7709_IRR1 0xa4000006 /* 8bit */ +#define SH7709_IRR2 0xa4000008 /* 8bit */ + +#define IPRC_IRQ3_MASK 0xf000 +#define IPRC_IRQ2_MASK 0x0f00 +#define IPRC_IRQ1_MASK 0x00f0 +#define IPRC_IRQ0_MASK 0x000f + +#define IPRD_PINT07_MASK 0xf000 +#define IPRD_PINT8F_MASK 0x0f00 +#define IPRD_IRQ5_MASK 0x00f0 +#define IPRD_IRQ4_MASK 0x000f + +#define IPRE_DMAC_MASK 0xf000 +#define IPRE_IRDA_MASK 0x0f00 +#define IPRE_SCIF_MASK 0x00f0 +#define IPRE_ADC_MASK 0x000f + +#define IRR0_PINT8F 0x80 +#define IRR0_PINT07 0x40 +#define IRR0_IRQ5 0x20 +#define IRR0_IRQ4 0x10 +#define IRR0_IRQ3 0x08 +#define IRR0_IRQ2 0x04 +#define IRR0_IRQ1 0x02 +#define IRR0_IRQ0 0x01 + + +/* SH4 */ +#define SH4_ICR 0xffd00000 /* 16bit */ +#define SH4_IPRA 0xffd00004 /* 16bit */ +#define SH4_IPRB 0xffd00008 /* 16bit */ +#define SH4_IPRC 0xffd0000c /* 16bit */ +#define SH4_IPRD 0xffd00010 /* 16bit */ +#define SH4_INTPRI00 0xfe080000 /* 32bit */ +#define SH4_INTREQ00 0xfe080020 /* 32bit */ +#define SH4_INTMSK00 0xfe080040 /* 32bit */ +#define SH4_INTMSKCLR00 0xfe080060 /* 32bit */ + +#define IPRC_GPIO_MASK 0xf000 +#define IPRC_DMAC_MASK 0x0f00 +#define IPRC_SCIF_MASK 0x00f0 +#define IPRC_HUDI_MASK 0x000f + +#define IPRD_IRL0_MASK 0xf000 +#define IPRD_IRL1_MASK 0x0f00 +#define IPRD_IRL2_MASK 0x00f0 +#define IPRD_IRL3_MASK 0x000f + +#define IPRA_TMU0_MASK 0xf000 +#define IPRA_TMU1_MASK 0x0f00 +#define IPRA_TMU2_MASK 0x00f0 +#define IPRA_RTC_MASK 0x000f + +#define IPRB_WDT_MASK 0xf000 +#define IPRB_REF_MASK 0x0f00 +#define IPRB_SCI_MASK 0x00f0 + +#define INTPRI00_PCI0_MASK 0x0000000f +#define INTPRI00_PCI1_MASK 0x000000f0 +#define INTPRI00_TMU3_MASK 0x00000f00 +#define INTPRI00_TMU4_MASK 0x0000f000 + +/* INTREQ/INTMSK/INTMSKCLR */ +#define INTREQ00_PCISERR 0x00000001 +#define INTREQ00_PCIDMA3 0x00000002 +#define INTREQ00_PCIDMA2 0x00000004 +#define INTREQ00_PCIDMA1 0x00000008 +#define INTREQ00_PCIDMA0 0x00000010 +#define INTREQ00_PCIPWON 0x00000020 +#define INTREQ00_PCIPWDWN 0x00000040 +#define INTREQ00_PCIERR 0x00000080 +#define INTREQ00_TUNI3 0x00000100 +#define INTREQ00_TUNI4 0x00000200 + +#define INTMSK00_MASK_ALL 0x000003ff + +#endif /* !_SH_INTCREG_H_ */ diff --git a/sys/arch/sh/include/internal_types.h b/sys/arch/sh/include/internal_types.h new file mode 100644 index 00000000000..1c6d5a40911 --- /dev/null +++ b/sys/arch/sh/include/internal_types.h @@ -0,0 +1,6 @@ +/* $OpenBSD: internal_types.h,v 1.1 2006/10/06 21:02:55 miod Exp $ */ +/* Public domain */ +#ifndef _SH_INTERNAL_TYPES_H_ +#define _SH_INTERNAL_TYPES_H_ + +#endif diff --git a/sys/arch/sh/include/intr.h b/sys/arch/sh/include/intr.h new file mode 100644 index 00000000000..eabf78662ad --- /dev/null +++ b/sys/arch/sh/include/intr.h @@ -0,0 +1,145 @@ +/* $OpenBSD: intr.h,v 1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: intr.h,v 1.22 2006/01/24 23:51:42 uwe Exp $ */ + +/*- + * Copyright (c) 2002 The NetBSD Foundation, Inc. + * 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 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. + */ + +#ifndef _SH_INTR_H_ +#define _SH_INTR_H_ + +#ifdef _KERNEL + +#include <sys/device.h> +#include <sys/evcount.h> +#include <sys/lock.h> +#include <sys/queue.h> +#include <sh/psl.h> + +/* Interrupt sharing types. */ +#define IST_NONE 0 /* none */ +#define IST_PULSE 1 /* pulsed */ +#define IST_EDGE 2 /* edge-triggered */ +#define IST_LEVEL 3 /* level-triggered */ + +/* Interrupt priority levels */ +#define _IPL_N 15 +#define _IPL_NSOFT 4 + +#define IPL_NONE 0 /* nothing */ +#define IPL_SOFT 1 +#define IPL_SOFTCLOCK 2 /* timeouts */ +#define IPL_SOFTNET 3 /* protocol stacks */ +#define IPL_SOFTSERIAL 4 /* serial */ + +#define IPL_SOFTNAMES { \ + "misc", \ + "clock", \ + "net", \ + "serial", \ +} + +struct intc_intrhand { + int (*ih_func)(void *); + void *ih_arg; + int ih_level; /* SR.I[0:3] value */ + int ih_evtcode; /* INTEVT or INTEVT2(SH7709/SH7709A) */ + int ih_idx; /* evtcode -> intrhand mapping */ + struct evcount ih_count; +}; + +/* from 0x200 by 0x20 -> from 0 by 1 */ +#define EVTCODE_TO_MAP_INDEX(x) (((x) >> 5) - 0x10) +#define EVTCODE_TO_IH_INDEX(x) \ + __intc_evtcode_to_ih[EVTCODE_TO_MAP_INDEX(x)] +#define EVTCODE_IH(x) (&__intc_intrhand[EVTCODE_TO_IH_INDEX(x)]) +extern int8_t __intc_evtcode_to_ih[]; +extern struct intc_intrhand __intc_intrhand[]; + +void intc_init(void); +void *intc_intr_establish(int, int, int, int (*)(void *), void *, const char *); +void intc_intr_disestablish(void *); +void intc_intr_enable(int); +void intc_intr_disable(int); +void intc_intr(int, int, int); + +void intpri_intr_priority(int evtcode, int level); + +/* + * software simulated interrupt + */ +struct sh_soft_intrhand { + TAILQ_ENTRY(sh_soft_intrhand) sih_q; + struct sh_soft_intr *sih_intrhead; + void (*sih_fn)(void *); + void *sih_arg; + int sih_pending; +}; + +struct sh_soft_intr { + TAILQ_HEAD(, sh_soft_intrhand) softintr_q; + struct evcnt softintr_evcnt; + struct simplelock softintr_slock; + unsigned long softintr_ipl; +}; + +#define softintr_schedule(arg) \ +do { \ + struct sh_soft_intrhand *__sih = (arg); \ + struct sh_soft_intr *__si = __sih->sih_intrhead; \ + int __s; \ + \ + __s = _cpu_intr_suspend(); \ + simple_lock(&__si->softintr_slock); \ + if (__sih->sih_pending == 0) { \ + TAILQ_INSERT_TAIL(&__si->softintr_q, __sih, sih_q); \ + __sih->sih_pending = 1; \ + setsoft(__si->softintr_ipl); \ + } \ + simple_unlock(&__si->softintr_slock); \ + _cpu_intr_resume(__s); \ +} while (/*CONSTCOND*/0) + +void softintr_init(void); +void *softintr_establish(int, void (*)(void *), void *); +void softintr_disestablish(void *); +void softintr_dispatch(int); +void setsoft(int); + +/* XXX For legacy software interrupts. */ +extern struct sh_soft_intrhand *softnet_intrhand; + +#define setsoftnet() softintr_schedule(softnet_intrhand) + +#endif /* _KERNEL */ + +#endif /* !_SH_INTR_H_ */ diff --git a/sys/arch/sh/include/limits.h b/sys/arch/sh/include/limits.h new file mode 100644 index 00000000000..e8ceb6d29f5 --- /dev/null +++ b/sys/arch/sh/include/limits.h @@ -0,0 +1,57 @@ +/* $OpenBSD: limits.h,v 1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: limits.h,v 1.1 1996/09/30 16:34:28 ws Exp $ */ + +/*- + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * 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 TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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 _SH_LIMITS_H_ +#define _SH_LIMITS_H_ + +#include <sys/cdefs.h> + +#define MB_LEN_MAX 1 /* no multibyte characters */ + +#if __POSIX_VISIBLE || __XPG_VISIBLE +#ifndef SIZE_MAX +#define SIZE_MAX UINT_MAX /* max value for a size_t */ +#endif +#define SSIZE_MAX INT_MAX /* max value for a ssize_t */ +#endif + +#if __BSD_VISIBLE +#define SIZE_T_MAX UINT_MAX /* max value for a size_t (historic) */ + +#define UQUAD_MAX 0xffffffffffffffffULL /* max unsigned quad */ +#define QUAD_MAX 0x7fffffffffffffffLL /* max signed quad */ +#define QUAD_MIN (-0x7fffffffffffffffLL-1) /* min signed quad */ +#endif /* __BSD_VISIBLE */ + +#endif /* _SH_LIMITS_H_ */ diff --git a/sys/arch/sh/include/lock.h b/sys/arch/sh/include/lock.h new file mode 100644 index 00000000000..017e083c7dc --- /dev/null +++ b/sys/arch/sh/include/lock.h @@ -0,0 +1,87 @@ +/* $OpenBSD: lock.h,v 1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: lock.h,v 1.10 2006/01/03 01:29:46 uwe Exp $ */ + +/*- + * Copyright (c) 2002 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Gregory McGarry. + * + * 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. + */ + +/* + * Machine-dependent spin lock operations. + */ + +#ifndef _SH_LOCK_H_ +#define _SH_LOCK_H_ + +typedef volatile u_int8_t __cpu_simple_lock_t; + +#define __SIMPLELOCK_LOCKED 0x80 +#define __SIMPLELOCK_UNLOCKED 0x00 + +static __inline void +__cpu_simple_lock_init(__cpu_simple_lock_t *alp) +{ + *alp = __SIMPLELOCK_UNLOCKED; +} + +static __inline void +__cpu_simple_lock(__cpu_simple_lock_t *alp) +{ + __asm volatile( + "1: tas.b %0 \n" + " bf 1b \n" + : "=m" (*alp)); +} + +static __inline int +__cpu_simple_lock_try(__cpu_simple_lock_t *alp) +{ + int __rv; + + __asm volatile( + " tas.b %0 \n" + " mov #0, %1 \n" + " rotcl %1 \n" + : "=m" (*alp), "=r" (__rv)); + + return (__rv); +} + +static __inline void +__cpu_simple_unlock(__cpu_simple_lock_t *alp) +{ + *alp = __SIMPLELOCK_UNLOCKED; +} + +#endif /* !_SH_LOCK_H_ */ diff --git a/sys/arch/sh/include/locore.h b/sys/arch/sh/include/locore.h new file mode 100644 index 00000000000..40fc0839f84 --- /dev/null +++ b/sys/arch/sh/include/locore.h @@ -0,0 +1,207 @@ +/* $OpenBSD: locore.h,v 1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: locore.h,v 1.11 2006/01/23 22:32:50 uwe Exp $ */ + +/*- + * Copyright (c) 2002 The NetBSD Foundation, Inc. + * 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 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. + */ + +#if defined(SH3) && defined(SH4) +#define MOV(x, r) mov.l .L_/**/x, r; mov.l @r, r +#define REG_SYMBOL(x) .L_/**/x: .long _C_LABEL(__sh_/**/x) +#define FUNC_SYMBOL(x) .L_/**/x: .long _C_LABEL(__sh_/**/x) +#elif defined(SH3) +#define MOV(x, r) mov.l .L_/**/x, r +#define REG_SYMBOL(x) .L_/**/x: .long SH3_/**/x +#define FUNC_SYMBOL(x) .L_/**/x: .long _C_LABEL(sh3_/**/x) +#elif defined(SH4) +#define MOV(x, r) mov.l .L_/**/x, r +#define REG_SYMBOL(x) .L_/**/x: .long SH4_/**/x +#define FUNC_SYMBOL(x) .L_/**/x: .long _C_LABEL(sh4_/**/x) +#endif /* SH3 && SH4 */ + +/* + * BANK1 r7 contains kernel stack top address. + * BANK1 r6 conatins current frame pointer. (per process) + */ +/* + * __EXCEPTION_ENTRY: + * + setup stack pointer + * + save all register to frame. (struct trapframe) + * + setup kernel stack. + * + change bank from 1 to 0 + * + set BANK0 (r4, r5, r6) = (ssr, spc, ssp) + */ +#define __EXCEPTION_ENTRY ;\ + /* Check kernel/user mode. */ ;\ + mov #0x40, r3 ;\ + swap.b r3, r3 ;\ + stc ssr, r2 ;\ + swap.w r3, r3 /* r3 = 0x40000000 */ ;\ + mov r2, r0 /* r2 = r0 = SSR */ ;\ + and r3, r0 ;\ + tst r0, r0 /* if (SSR.MD == 0) T = 1 */ ;\ + mov r14, r1 ;\ + mov r6, r14 /* frame pointer */ ;\ + bf/s 1f /* T==0 ...Exception from kernel mode */;\ + mov r15, r0 ;\ + /* Exception from user mode */ ;\ + mov r7, r15 /* change to kernel stack */ ;\ +1: ;\ + /* Save registers */ ;\ + mov.l r1, @-r14 /* tf_r14 */ ;\ + mov.l r0, @-r14 /* tf_r15 */ ;\ + stc.l r0_bank,@-r14 /* tf_r0 */ ;\ + stc.l r1_bank,@-r14 /* tf_r1 */ ;\ + stc.l r2_bank,@-r14 /* tf_r2 */ ;\ + stc.l r3_bank,@-r14 /* tf_r3 */ ;\ + stc.l r4_bank,@-r14 /* tf_r4 */ ;\ + stc.l r5_bank,@-r14 /* tf_r5 */ ;\ + stc.l r6_bank,@-r14 /* tf_r6 */ ;\ + stc.l r7_bank,@-r14 /* tf_r7 */ ;\ + mov.l r8, @-r14 /* tf_r8 */ ;\ + mov.l r9, @-r14 /* tf_r9 */ ;\ + mov.l r10, @-r14 /* tf_r10 */ ;\ + mov.l r11, @-r14 /* tf_r11 */ ;\ + mov.l r12, @-r14 /* tf_r12 */ ;\ + mov.l r13, @-r14 /* tf_r13 */ ;\ + sts.l pr, @-r14 /* tf_pr */ ;\ + sts.l mach, @-r14 /* tf_mach*/ ;\ + sts.l macl, @-r14 /* tf_macl*/ ;\ + mov.l r2, @-r14 /* tf_ssr */ ;\ + stc.l spc, @-r14 /* tf_spc */ ;\ + add #-8, r14 /* skip tf_ubc, tf_expevt */ ;\ + mov r14, r6 /* store frame pointer */ ;\ + /* Change register bank to 0 */ ;\ + shlr r3 /* r3 = 0x20000000 */ ;\ + stc sr, r1 /* r1 = SR */ ;\ + not r3, r3 ;\ + and r1, r3 ;\ + ldc r3, sr /* SR.RB = 0 */ ;\ + /* Set up argument. r4 = ssr, r5 = spc */ ;\ + stc r2_bank,r4 ;\ + stc spc, r5 + +/* + * __EXCEPTION_RETURN: + * + block exception + * + restore all register from stack. + * + rte. + */ +#define __EXCEPTION_RETURN ;\ + mov #0x10, r0 ;\ + swap.b r0, r0 ;\ + swap.w r0, r0 /* r0 = 0x10000000 */ ;\ + stc sr, r1 ;\ + or r0, r1 ;\ + ldc r1, sr /* SR.BL = 1 */ ;\ + stc r6_bank,r0 ;\ + mov r0, r14 ;\ + add #TF_SIZE, r0 ;\ + ldc r0, r6_bank /* roll up frame pointer */ ;\ + add #8, r14 /* skip tf_expevt, tf_ubc */ ;\ + mov.l @r14+, r0 /* tf_spc */ ;\ + ldc r0, spc ;\ + mov.l @r14+, r0 /* tf_ssr */ ;\ + ldc r0, ssr ;\ + lds.l @r14+, macl /* tf_macl*/ ;\ + lds.l @r14+, mach /* tf_mach*/ ;\ + lds.l @r14+, pr /* tf_pr */ ;\ + mov.l @r14+, r13 /* tf_r13 */ ;\ + mov.l @r14+, r12 /* tf_r12 */ ;\ + mov.l @r14+, r11 /* tf_r11 */ ;\ + mov.l @r14+, r10 /* tf_r10 */ ;\ + mov.l @r14+, r9 /* tf_r9 */ ;\ + mov.l @r14+, r8 /* tf_r8 */ ;\ + mov.l @r14+, r7 /* tf_r7 */ ;\ + mov.l @r14+, r6 /* tf_r6 */ ;\ + mov.l @r14+, r5 /* tf_r5 */ ;\ + mov.l @r14+, r4 /* tf_r4 */ ;\ + mov.l @r14+, r3 /* tf_r3 */ ;\ + mov.l @r14+, r2 /* tf_r2 */ ;\ + mov.l @r14+, r1 /* tf_r1 */ ;\ + mov.l @r14+, r0 /* tf_r0 */ ;\ + mov.l @r14+ r15 /* tf_r15 */ ;\ + mov.l @r14+, r14 /* tf_r14 */ ;\ + rte ;\ + nop + + +/* + * Macros to disable and enable exceptions (including interrupts). + * This modifies SR.BL + */ +#define __0x10 #0x10 +#define __0x78 #0x78 + +#define __EXCEPTION_BLOCK(Rn, Rm) ;\ + mov __0x10, Rn ;\ + swap.b Rn, Rn ;\ + swap.w Rn, Rn /* Rn = 0x10000000 */ ;\ + stc sr, Rm ;\ + or Rn, Rm ;\ + ldc Rm, sr /* block exceptions */ + +#define __EXCEPTION_UNBLOCK(Rn, Rm) ;\ + mov __0x10, Rn ;\ + swap.b Rn, Rn ;\ + swap.w Rn, Rn /* Rn = 0x10000000 */ ;\ + not Rn, Rn ;\ + stc sr, Rm ;\ + and Rn, Rm ;\ + ldc Rm, sr /* unblock exceptions */ + +/* + * Macros to disable and enable interrupts. + * This modifies SR.I[0-3] + */ +#define __INTR_MASK(Rn, Rm) ;\ + mov __0x78, Rn ;\ + shll Rn /* Rn = 0x000000f0 */ ;\ + stc sr, Rm ;\ + or Rn, Rm ;\ + ldc Rm, sr /* mask all interrupt */ + +#define __INTR_UNMASK(Rn, Rm) ;\ + mov __0x78, Rn ;\ + shll Rn /* Rn = 0x000000f0 */ ;\ + not Rn, Rn ;\ + stc sr, Rm ;\ + and Rn, Rm ;\ + ldc Rm, sr /* unmask all interrupt */ + +#ifndef _LOCORE +void sh3_switch_setup(struct proc *); +void sh4_switch_setup(struct proc *); +void sh3_switch_resume(struct proc *); +void sh4_switch_resume(struct proc *); +extern void (*__sh_switch_resume)(struct proc *); +#endif /* !_LOCORE */ diff --git a/sys/arch/sh/include/mmu.h b/sys/arch/sh/include/mmu.h new file mode 100644 index 00000000000..da1cdc501cb --- /dev/null +++ b/sys/arch/sh/include/mmu.h @@ -0,0 +1,115 @@ +/* $OpenBSD: mmu.h,v 1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: mmu.h,v 1.9 2006/03/04 01:55:03 uwe Exp $ */ + +/*- + * Copyright (c) 2002 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by UCHIYAMA Yasushi. + * + * 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. + */ + +#ifndef _SH_MMU_H_ +#define _SH_MMU_H_ + +/* + * Initialize routines. + * sh_mmu_init Assign function vector. Don't access hardware. + * Call as early as possible. + * sh_mmu_start Reset TLB entry, set default ASID, and start to + * translate addresses. + * Call after exception vector was installed. + * + * TLB access ops. + * sh_tlb_invalidate_addr invalidate TLB entris for given + * virtual addr with ASID. + * sh_tlb_invalidate_asid invalidate TLB entries for given ASID. + * sh_tlb_invalidate_all invalidate all non-wired TLB entries. + * sh_tlb_set_asid set ASID. + * sh_tlb_update load new PTE to TLB. + * + */ + +void sh_mmu_init(void); +void sh_mmu_information(void); +void sh_tlb_set_asid(int); + +#ifdef SH3 +void sh3_mmu_start(void); +void sh3_tlb_invalidate_addr(int, vaddr_t); +void sh3_tlb_invalidate_asid(int); +void sh3_tlb_invalidate_all(void); +void sh3_tlb_update(int, vaddr_t, uint32_t); +#endif + +#ifdef SH4 +void sh4_mmu_start(void); +void sh4_tlb_invalidate_addr(int, vaddr_t); +void sh4_tlb_invalidate_asid(int); +void sh4_tlb_invalidate_all(void); +void sh4_tlb_update(int, vaddr_t, uint32_t); +#endif + + +#if defined(SH3) && defined(SH4) +extern uint32_t __sh_PTEH; + +extern void (*__sh_mmu_start)(void); +extern void (*__sh_tlb_invalidate_addr)(int, vaddr_t); +extern void (*__sh_tlb_invalidate_asid)(int); +extern void (*__sh_tlb_invalidate_all)(void); +extern void (*__sh_tlb_update)(int, vaddr_t, uint32_t); + +#define sh_mmu_start() (*__sh_mmu_start)() +#define sh_tlb_invalidate_addr(a, va) (*__sh_tlb_invalidate_addr)(a, va) +#define sh_tlb_invalidate_asid(a) (*__sh_tlb_invalidate_asid)(a) +#define sh_tlb_invalidate_all() (*__sh_tlb_invalidate_all)() +#define sh_tlb_update(a, va, pte) (*__sh_tlb_update)(a, va, pte) + +#elif defined(SH3) + +#define sh_mmu_start() sh3_mmu_start() +#define sh_tlb_invalidate_addr(a, va) sh3_tlb_invalidate_addr(a, va) +#define sh_tlb_invalidate_asid(a) sh3_tlb_invalidate_asid(a) +#define sh_tlb_invalidate_all() sh3_tlb_invalidate_all() +#define sh_tlb_update(a, va, pte) sh3_tlb_update(a, va, pte) + +#elif defined(SH4) + +#define sh_mmu_start() sh4_mmu_start() +#define sh_tlb_invalidate_addr(a, va) sh4_tlb_invalidate_addr(a, va) +#define sh_tlb_invalidate_asid(a) sh4_tlb_invalidate_asid(a) +#define sh_tlb_invalidate_all() sh4_tlb_invalidate_all() +#define sh_tlb_update(a, va, pte) sh4_tlb_update(a, va, pte) + +#endif + +#endif /* !_SH_MMU_H_ */ diff --git a/sys/arch/sh/include/mmu_sh3.h b/sys/arch/sh/include/mmu_sh3.h new file mode 100644 index 00000000000..a8f5139e8ca --- /dev/null +++ b/sys/arch/sh/include/mmu_sh3.h @@ -0,0 +1,90 @@ +/* $OpenBSD: mmu_sh3.h,v 1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: mmu_sh3.h,v 1.6 2006/03/04 01:55:03 uwe Exp $ */ + +/*- + * Copyright (c) 2002 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by UCHIYAMA Yasushi. + * + * 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. + */ + +#ifndef _SH_MMU_SH3_H_ +#define _SH_MMU_SH3_H_ +#include <sh/devreg.h> + +/* 128-entry 4-way set-associative */ +#define SH3_MMU_WAY 4 +#define SH3_MMU_ENTRY 32 + +#define SH3_PTEH 0xfffffff0 +#define SH3_PTEH_ASID_MASK 0x000000ff +#define SH3_PTEH_VPN_MASK 0xfffffc00 +#define SH3_PTEL 0xfffffff4 +#define SH3_PTEL_HWBITS 0x1ffff17e /* [28:12][8][6:1] */ +#define SH3_TTB 0xfffffff8 +#define SH3_TEA 0xfffffffc +#define SH3_MMUCR 0xffffffe0 +#define SH3_MMUCR_AT 0x00000001 +#define SH3_MMUCR_IX 0x00000002 +#define SH3_MMUCR_TF 0x00000004 +#define SH3_MMUCR_RC 0x00000030 +#define SH3_MMUCR_SV 0x00000100 + +/* + * memory-mapped TLB + */ +/* Address array */ +#define SH3_MMUAA 0xf2000000 +/* address specification */ +#define SH3_MMU_VPN_SHIFT 12 +#define SH3_MMU_VPN_MASK 0x0001f000 /* [16:12] */ +#define SH3_MMU_WAY_SHIFT 8 +#define SH3_MMU_WAY_MASK 0x00000300 /* [9:8] */ +/* data specification */ +#define SH3_MMU_D_VALID 0x00000100 +#define SH3_MMUAA_D_VPN_MASK_1K 0xfffe0c00 /* [31:17][11:10] */ +#define SH3_MMUAA_D_VPN_MASK_4K 0xfffe0000 /* [31:17] */ +#define SH3_MMUAA_D_ASID_MASK 0x000000ff + +/* Data array */ +#define SH3_MMUDA 0xf3000000 +#define SH3_MMUDA_D_PPN_MASK 0xfffffc00 +#define SH3_MMUDA_D_V 0x00000100 +#define SH3_MMUDA_D_PR_SHIFT 5 +#define SH3_MMUDA_D_PR_MASK 0x00000060 /* [6:5] */ +#define SH3_MMUDA_D_SZ 0x00000010 +#define SH3_MMUDA_D_C 0x00000008 +#define SH3_MMUDA_D_D 0x00000004 +#define SH3_MMUDA_D_SH 0x00000002 + +#define SH3_TLB_DISABLE *(volatile uint32_t *)SH3_MMUCR = SH3_MMUCR_TF +#endif /* !_SH_MMU_SH3_H_ */ diff --git a/sys/arch/sh/include/mmu_sh4.h b/sys/arch/sh/include/mmu_sh4.h new file mode 100644 index 00000000000..c25a48c4748 --- /dev/null +++ b/sys/arch/sh/include/mmu_sh4.h @@ -0,0 +1,154 @@ +/* $OpenBSD: mmu_sh4.h,v 1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: mmu_sh4.h,v 1.6 2006/03/04 01:55:03 uwe Exp $ */ + +/*- + * Copyright (c) 2002 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by UCHIYAMA Yasushi. + * + * 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. + */ + +#ifndef _SH_MMU_SH4_H_ +#define _SH_MMU_SH4_H_ +#include <sh/devreg.h> + +/* ITLB 4-entry full-associative UTLB 64-entry full-associative */ +#define SH4_PTEH 0xff000000 +#define SH4_PTEH_VPN_MASK 0xfffffc00 +#define SH4_PTEH_ASID_MASK 0x000000ff +#define SH4_PTEL 0xff000004 +#define SH4_PTEL_WT 0x00000001 +#define SH4_PTEL_SH 0x00000002 +#define SH4_PTEL_D 0x00000004 +#define SH4_PTEL_C 0x00000008 +#define SH4_PTEL_PR_SHIFT 5 +#define SH4_PTEL_PR_MASK 0x00000060 /* [5:6] */ +#define SH4_PTEL_SZ_MASK 0x00000090 /* [4][7] */ +#define SH4_PTEL_SZ_1K 0x00000000 +#define SH4_PTEL_SZ_4K 0x00000010 +#define SH4_PTEL_SZ_64K 0x00000080 +#define SH4_PTEL_SZ_1M 0x00000090 +#define SH4_PTEL_V 0x00000100 +#define SH4_PTEL_HWBITS 0x1ffff1ff /* [28:12]PFN [8:0]attr. */ + +#define SH4_PTEA 0xff000034 +#define SH4_PTEA_SA_MASK 0x00000007 +#define SH4_PTEA_SA_TC 0x00000008 +#define SH4_TTB 0xff000008 +#define SH4_TEA 0xff00000c +#define SH4_MMUCR 0xff000010 +#define SH4_MMUCR_AT 0x00000001 +#define SH4_MMUCR_TI 0x00000004 +#define SH4_MMUCR_SV 0x00000100 +#define SH4_MMUCR_SQMD 0x00000200 +#define SH4_MMUCR_URC_SHIFT 10 +#define SH4_MMUCR_URC_MASK 0x0000fc00 /* [10:15] */ +#define SH4_MMUCR_URB_SHIFT 18 +#define SH4_MMUCR_URB_MASK 0x00fc0000 /* [18:23] */ +#define SH4_MMUCR_LRUI_SHIFT 26 +#define SH4_MMUCR_LRUT_MASK 0xfc000000 /* [26:31] */ + +#define SH4_MMUCR_MASK (SH4_MMUCR_LRUT_MASK | SH4_MMUCR_URB_MASK | \ + SH4_MMUCR_URC_MASK | SH4_MMUCR_SQMD | SH4_MMUCR_SV | SH4_MMUCR_AT) +/* + * memory-mapped TLB + * must be access from P2-area program. + * branch to the other area must be maed at least 8 instruction + * after access. + */ +#define SH4_ITLB_ENTRY 4 +#define SH4_UTLB_ENTRY 64 + +/* ITLB */ +#define SH4_ITLB_AA 0xf2000000 +/* address specification (common for address and data array(0,1)) */ +#define SH4_ITLB_E_SHIFT 8 +#define SH4_ITLB_E_MASK 0x00000300 /* [9:8] */ +/* data specification */ +/* address-array */ +#define SH4_ITLB_AA_ASID_MASK 0x000000ff /* [7:0] */ +#define SH4_ITLB_AA_V 0x00000100 +#define SH4_ITLB_AA_VPN_SHIFT 10 +#define SH4_ITLB_AA_VPN_MASK 0xfffffc00 /* [31:10] */ +/* data-array 1 */ +#define SH4_ITLB_DA1 0xf3000000 +#define SH4_ITLB_DA1_SH 0x00000002 +#define SH4_ITLB_DA1_C 0x00000008 +#define SH4_ITLB_DA1_SZ_MASK 0x00000090 /* [7][4] */ +#define SH4_ITLB_DA1_SZ_1K 0x00000000 +#define SH4_ITLB_DA1_SZ_4K 0x00000010 +#define SH4_ITLB_DA1_SZ_64K 0x00000080 +#define SH4_ITLB_DA1_SZ_1M 0x00000090 +#define SH4_ITLB_DA1_PR 0x00000040 +#define SH4_ITLB_DA1_V 0x00000100 +#define SH4_ITLB_DA1_PPN_SHIFT 11 +#define SH4_ITLB_DA1_PPN_MASK 0x1ffffc00 /* [28:10] */ +/* data-array 2 */ +#define SH4_ITLB_DA2 0xf3800000 +#define SH4_ITLB_DA2_SA_MASK 0x00000003 +#define SH4_ITLB_DA2_TC 0x00000004 + +/* UTLB */ +#define SH4_UTLB_AA 0xf6000000 +/* address specification (common for address and data array(0,1)) */ +#define SH4_UTLB_E_SHIFT 8 +#define SH4_UTLB_E_MASK 0x00003f00 +#define SH4_UTLB_A 0x00000080 +/* data specification */ +/* address-array */ +#define SH4_UTLB_AA_VPN_MASK 0xfffffc00 /* [31:10] */ +#define SH4_UTLB_AA_D 0x00000200 +#define SH4_UTLB_AA_V 0x00000100 +#define SH4_UTLB_AA_ASID_MASK 0x000000ff /* [7:0] */ +/* data-array 1 */ +#define SH4_UTLB_DA1 0xf7000000 +#define SH4_UTLB_DA1_WT 0x00000001 +#define SH4_UTLB_DA1_SH 0x00000002 +#define SH4_UTLB_DA1_D 0x00000004 +#define SH4_UTLB_DA1_C 0x00000008 +#define SH4_UTLB_DA1_SZ_MASK 0x00000090 /* [7][4] */ +#define SH4_UTLB_DA1_SZ_1K 0x00000000 +#define SH4_UTLB_DA1_SZ_4K 0x00000010 +#define SH4_UTLB_DA1_SZ_64K 0x00000080 +#define SH4_UTLB_DA1_SZ_1M 0x00000090 +#define SH4_UTLB_DA1_PR_SHIFT 5 +#define SH4_UTLB_DA1_PR_MASK 0x00000060 +#define SH4_UTLB_DA1_V 0x00000100 +#define SH4_UTLB_DA1_PPN_SHIFT 11 +#define SH4_UTLB_DA1_PPN_MASK 0x1ffffc00 /* [28:10] */ +/* data-array 2 */ +#define SH4_UTLB_DA2 0xf7800000 +#define SH4_UTLB_DA2_SA_MASK 0x00000003 +#define SH4_UTLB_DA2_TC 0x00000004 + +#define SH4_TLB_DISABLE *(volatile uint32_t *)SH4_MMUCR = SH4_MMUCR_TI +#endif /* !_SH_MMU_SH4_H_ */ diff --git a/sys/arch/sh/include/param.h b/sys/arch/sh/include/param.h new file mode 100644 index 00000000000..9a4493af3ee --- /dev/null +++ b/sys/arch/sh/include/param.h @@ -0,0 +1,137 @@ +/* $OpenBSD: param.h,v 1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: param.h,v 1.15 2006/08/28 13:43:35 yamt Exp $ */ + +/*- + * Copyright (c) 2002 The NetBSD Foundation, Inc. All rights reserved. + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * 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. 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. + * + * @(#)param.h 5.8 (Berkeley) 6/28/91 + */ + +/* + * SuperH dependent constants. + */ + +#ifndef _SH_PARAM_H_ +#define _SH_PARAM_H_ + +#define _MACHINE_ARCH sh +#define MACHINE_ARCH "sh" + +#ifndef MID_MACHINE +#define MID_MACHINE MID_SH3 +#endif + +#if defined(_KERNEL) && !defined(_LOCORE) +#include <sh/cpu.h> +#endif + +/* + * We use 4K pages on the sh3/sh4. Override the PAGE_* definitions + * to be compile-time constants. + */ +#define PAGE_SHIFT 12 +#define PAGE_SIZE (1 << PAGE_SHIFT) +#define PAGE_MASK (PAGE_SIZE - 1) + +#define PGSHIFT PAGE_SHIFT +#define NBPG PAGE_SIZE +#define PGOFSET PAGE_MASK + +/* + * Round p (pointer or byte index) up to a correctly-aligned value + * for all data types (int, long, ...). The result is u_int and + * must be cast to any desired pointer type. + * + * ALIGNED_POINTER is a boolean macro that checks whether an address + * is valid to fetch data elements of type t from on this architecture. + * This does not reflect the optimal alignment, just the possibility + * (within reasonable limits). + * + */ +#define ALIGNBYTES (sizeof(int) - 1) +#define ALIGN(p) (((u_int)(p) + ALIGNBYTES) & ~ALIGNBYTES) +#define ALIGNED_POINTER(p, t) ((((u_long)(p)) & (sizeof(t) - 1)) == 0) + +#define DEV_BSHIFT 9 /* log2(DEV_BSIZE) */ +#define DEV_BSIZE (1 << DEV_BSHIFT) +#define BLKDEV_IOSIZE 2048 +#define MAXPHYS (64 * 1024) /* max raw I/O transfer size */ + +/* + * u-space. + */ +#define UPAGES 2 /* pages of u-area */ +#define USPACE (UPAGES * NBPG) /* total size of u-area */ +#define USPACE_ALIGN (0) +#if UPAGES == 1 +#error "too small u-area" +#elif UPAGES == 2 +#define P1_STACK /* kernel stack is P1-area */ +#else +#undef P1_STACK /* kernel stack is P3-area */ +#endif + +#ifndef MSGBUFSIZE +#define MSGBUFSIZE NBPG /* default message buffer size */ +#endif + +#define btoc(x) (((x) + PAGE_MASK) >> PAGE_SHIFT) +#define ctob(x) ((x) << PAGE_SHIFT) + +#define btodb(bytes) /* calculates (bytes / DEV_BSIZE) */ \ + ((bytes) >> DEV_BSHIFT) +#define dbtob(db) /* calculates (db * DEV_BSIZE) */ \ + ((db) << DEV_BSHIFT) + +/* + * Constants related to network buffer management. + * MCLBYTES must be no larger than NBPG (the software page size), and, + * on machines that exchange pages of input or output buffers with mbuf + * clusters (MAPPED_MBUFS), MCLBYTES must also be an integral multiple + * of the hardware page size. + */ +#define MSIZE 256 /* size of an mbuf */ + +#define MCLSHIFT 11 /* convert bytes to m_buf clusters */ + /* 2K cluster can hold Ether frame */ +#define MCLBYTES (1 << MCLSHIFT) /* size of a m_buf cluster */ + +#define NMBCLUSTERS 4096 /* map size, max cluster allocation */ + +/* + * Minimum and maximum sizes of the kernel malloc arena in PAGE_SIZE-sized + * logical pages. + */ +#define NKMEMPAGES_MIN_DEFAULT ((4 * 1024 * 1024) >> PAGE_SHIFT) +#define NKMEMPAGES_MAX_DEFAULT ((64 * 1024 * 1024) >> PAGE_SHIFT) + +#endif /* !_SH3_PARAM_H_ */ diff --git a/sys/arch/sh/include/pcb.h b/sys/arch/sh/include/pcb.h new file mode 100644 index 00000000000..2dbc63c7cfa --- /dev/null +++ b/sys/arch/sh/include/pcb.h @@ -0,0 +1,55 @@ +/* $OpenBSD: pcb.h,v 1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: pcb.h,v 1.7 2002/05/09 12:28:08 uch Exp $ */ + +/*- + * Copyright (c) 2002 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by UCHIYAMA Yasushi. + * + * 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. + */ + +#ifndef _SH_PCB_H_ +#define _SH_PCB_H_ + +#include <sh/frame.h> + +struct pcb { + struct switchframe pcb_sf; /* kernel context for resume */ + caddr_t pcb_onfault; /* for copyin/out fault */ + int pcb_faultbail; /* bail out before call uvm_fault. */ +}; + +struct md_coredump { +}; + +extern struct pcb *curpcb; +#endif /* !_SH_PCB_H_ */ diff --git a/sys/arch/sh/include/pmap.h b/sys/arch/sh/include/pmap.h new file mode 100644 index 00000000000..b26dd562137 --- /dev/null +++ b/sys/arch/sh/include/pmap.h @@ -0,0 +1,91 @@ +/* $OpenBSD: pmap.h,v 1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: pmap.h,v 1.28 2006/04/10 23:12:11 uwe Exp $ */ + +/*- + * Copyright (c) 2002 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by UCHIYAMA Yasushi. + * + * 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. + */ + +/* + * OpenBSD/sh pmap: + * pmap.pm_ptp[512] ... 512 slot of page table page + * page table page contains 1024 PTEs. (PAGE_SIZE / sizeof(pt_entry_t)) + * | PTP 11bit | PTOFSET 10bit | PGOFSET 12bit | + */ + +#ifndef _SH_PMAP_H_ +#define _SH_PMAP_H_ +#include <sys/queue.h> +#include <sh/pte.h> + +#define PMAP_STEAL_MEMORY +#define PMAP_GROWKERNEL + +#define __PMAP_PTP_N 512 /* # of page table page maps 2GB. */ +typedef struct pmap { + pt_entry_t **pm_ptp; + int pm_asid; + int pm_refcnt; + struct pmap_statistics pm_stats; /* pmap statistics */ +} *pmap_t; +extern struct pmap __pmap_kernel; + +void pmap_bootstrap(void); +void pmap_proc_iflush(struct proc *, vaddr_t, size_t); +#define pmap_unuse_final(p) do { /* nothing */ } while (0) +#define pmap_kernel() (&__pmap_kernel) +#define pmap_deactivate(pmap) do { /* nothing */ } while (0) +#define pmap_update(pmap) do { /* nothing */ } while (0) +#define pmap_copy(dp,sp,d,l,s) do { /* nothing */ } while (0) +#define pmap_collect(pmap) do { /* nothing */ } while (0) +#define pmap_wired_count(pmap) ((pmap)->pm_stats.wired_count) +#define pmap_resident_count(pmap) ((pmap)->pm_stats.resident_count) +#define pmap_phys_address(frame) ((paddr_t)(ptoa(frame))) + +/* ARGSUSED */ +static __inline void +pmap_remove_all(struct pmap *pmap) +{ + /* Nothing. */ +} + +#define __HAVE_PMAP_DIRECT +#define pmap_map_direct(pg) SH3_PHYS_TO_P1SEG(VM_PAGE_TO_PHYS(pg)) +#define pmap_unmap_direct(va) PHYS_TO_VM_PAGE(SH3_P1SEG_TO_PHYS((va))) + +/* MD pmap utils. */ +pt_entry_t *__pmap_pte_lookup(pmap_t, vaddr_t); +pt_entry_t *__pmap_kpte_lookup(vaddr_t); +boolean_t __pmap_pte_load(pmap_t, vaddr_t, int); +#endif /* !_SH_PMAP_H_ */ diff --git a/sys/arch/sh/include/proc.h b/sys/arch/sh/include/proc.h new file mode 100644 index 00000000000..a308274bf3e --- /dev/null +++ b/sys/arch/sh/include/proc.h @@ -0,0 +1,69 @@ +/* $OpenBSD: proc.h,v 1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: proc.h,v 1.10 2005/12/11 12:18:58 christos Exp $ */ + +/* + * Copyright (c) 2002 The NetBSD Foundation, Inc. All rights reserved. + * Copyright (c) 1991 Regents of the University of California. + * 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. 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. + * + * @(#)proc.h 7.1 (Berkeley) 5/15/91 + */ + +#ifndef _SH_PROC_H_ +#define _SH_PROC_H_ + +/* + * Machine-dependent part of the proc structure for sh. + */ + +#include <machine/param.h> + +/* Kernel stack PTE */ +struct md_upte { + uint32_t addr; + uint32_t data; +}; + +struct mdproc { + struct trapframe *md_regs; /* user context */ + struct pcb *md_pcb; /* pcb access address */ + volatile int md_astpending; /* AST pending on return to userland */ + int md_flags; /* machine-dependent flags */ + /* u-area PTE: *2 .. SH4 data/address data array access */ + struct md_upte md_upte[UPAGES * 2]; +}; + +/* md_flags */ +#define MDP_USEDFPU 0x0001 /* has used the FPU */ + +#ifdef _KERNEL +#ifndef _LOCORE +extern void sh_proc0_init(void); +extern struct md_upte *curupte; /* SH3 wired u-area hack */ +#endif /* _LOCORE */ +#endif /* _KERNEL */ +#endif /* !_SH_PROC_H_ */ diff --git a/sys/arch/sh/include/profile.h b/sys/arch/sh/include/profile.h new file mode 100644 index 00000000000..2b2caf62119 --- /dev/null +++ b/sys/arch/sh/include/profile.h @@ -0,0 +1,74 @@ +/* $OpenBSD: profile.h,v 1.1.1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: profile.h,v 1.4 2002/04/28 17:10:36 uch Exp $ */ + +/*- + * Copyright (c) 2000 Tsubai Masanari. 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. 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. + */ + +#if defined(__ELF__) +#define _MCOUNT_DECL static void _mcount +#else +#define _MCOUNT_DECL static void mcount +#endif + +#define MCOUNT __asm (" \n\ + .text \n\ + .align 2 \n\ + .globl __mcount \n\ +__mcount: \n\ + mov.l r0,@-r15 \n\ + mov.l r4,@-r15 \n\ + mov.l r5,@-r15 \n\ + mov.l r6,@-r15 \n\ + mov.l r7,@-r15 \n\ + mov.l r14,@-r15 \n\ + sts.l pr,@-r15 \n\ + mov r15,r14 \n\ + \n\ + mov.l 1f,r1 ! _mcount \n\ + sts pr,r4 ! frompc \n\ + mov r0,r5 ! selfpc \n\ + jsr @r1 \n\ + nop \n\ + \n\ + mov r14,r15 \n\ + lds.l @r15+,pr \n\ + mov.l @r15+,r14 \n\ + mov.l @r15+,r7 \n\ + mov.l @r15+,r6 \n\ + mov.l @r15+,r5 \n\ + mov.l @r15+,r4 \n\ + mov.l @r15+,r0 \n\ + \n\ + jmp @r0 ! return \n\ + nop \n\ + \n\ + .align 2 \n\ +1: .long _mcount "); + +#ifdef _KERNEL +#define MCOUNT_ENTER s = splhigh() +#define MCOUNT_EXIT splx(s) +#endif diff --git a/sys/arch/sh/include/psl.h b/sys/arch/sh/include/psl.h new file mode 100644 index 00000000000..8a45a23a3fd --- /dev/null +++ b/sys/arch/sh/include/psl.h @@ -0,0 +1,76 @@ +/* $OpenBSD: psl.h,v 1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: psl.h,v 1.8 2005/12/11 12:18:58 christos Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * 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. 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. + * + * @(#)psl.h 5.2 (Berkeley) 1/18/91 + */ + +#ifndef _SH_PSL_H_ +#define _SH_PSL_H_ + +/* + * SuperH Processer Status Register. + */ +#define PSL_TBIT 0x00000001 /* T bit */ +#define PSL_SBIT 0x00000002 /* S bit */ +#define PSL_IMASK 0x000000f0 /* Interrupt Mask bit */ +#define PSL_QBIT 0x00000100 /* Q bit */ +#define PSL_MBIT 0x00000200 /* M bit */ +#define PSL_BL 0x10000000 /* Exception Block bit */ +#define PSL_RB 0x20000000 /* Register Bank bit */ +#define PSL_MD 0x40000000 /* Processor Mode bit */ + /* 1 = kernel, 0 = user */ + +#define PSL_MBO 0x00000000 /* must be one bits */ +#define PSL_MBZ 0x8ffffc0c /* must be zero bits */ + +#define PSL_USERSET 0 +#define PSL_USERSTATIC (PSL_BL|PSL_RB|PSL_MD|PSL_IMASK|PSL_MBO|PSL_MBZ) + +#define KERNELMODE(sr) ((sr) & PSL_MD) + +#ifdef _KERNEL +#ifndef _LOCORE +/* SR.IMASK */ +int _cpu_intr_raise(int); +int _cpu_intr_suspend(void); +int _cpu_intr_resume(int); +/* SR.BL */ +int _cpu_exception_suspend(void); +void _cpu_exception_resume(int); +#endif /* !_LOCORE */ + +#include <machine/intr.h> +#endif /* _KERNEL */ + +#endif /* !_SH_PSL_H_ */ diff --git a/sys/arch/sh/include/pte.h b/sys/arch/sh/include/pte.h new file mode 100644 index 00000000000..b3034504cb9 --- /dev/null +++ b/sys/arch/sh/include/pte.h @@ -0,0 +1,99 @@ +/* $OpenBSD: pte.h,v 1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: pte.h,v 1.11 2006/03/04 01:55:03 uwe Exp $ */ + +/*- + * Copyright (c) 2002 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by UCHIYAMA Yasushi. + * + * 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. + */ + +#ifndef _SH_PTE_H_ +#define _SH_PTE_H_ + +/* + * OpenBSD/sh PTE format. + * + * [Hardware bit] + * SH3 + * PPN V PR SZ C D SH + * [28:10][8][6:5][4][3][2][1] + * + * SH4 + * V SZ PR SZ C D SH WT + * [28:10][8][7][6:5][4][3][2][1][0] + * + * [Software bit] + * [31] - PMAP_WIRED bit (not hardware wired entry) + * [11:9] - SH4 PCMCIA Assistant bit. (space attribute bit only) + */ + +/* + * Hardware bits + */ +#define PG_PPN 0x1ffff000 /* Physical page number mask */ +#define PG_V 0x00000100 /* Valid */ +#define PG_PR_MASK 0x00000060 /* Page protection mask */ +#define PG_PR_URW 0x00000060 /* kernel/user read/write */ +#define PG_PR_URO 0x00000040 /* kernel/user read only */ +#define PG_PR_KRW 0x00000020 /* kernel read/write */ +#define PG_PR_KRO 0x00000000 /* kernel read only */ +#define PG_4K 0x00000010 /* page size 4KB */ +#define PG_C 0x00000008 /* Cacheable */ +#define PG_D 0x00000004 /* Dirty */ +#define PG_SH 0x00000002 /* Share status */ +#define PG_WT 0x00000001 /* Write-through (SH4 only) */ + +#define PG_HW_BITS 0x1ffff17e /* [28:12][8][6:1] */ + +/* + * Software bits + */ +#define _PG_WIRED 0x80000000 + +/* SH4 PCMCIA MMU support bits */ +/* PTEA SA (Space Attribute bit) */ +#define _PG_PCMCIA 0x00000e00 /* [11:9] */ +#define _PG_PCMCIA_SHIFT 9 +#define _PG_PCMCIA_NONE 0x00000000 /* Non PCMCIA space */ +#define _PG_PCMCIA_IO 0x00000200 /* IOIS16 signal */ +#define _PG_PCMCIA_IO8 0x00000400 /* 8 bit I/O */ +#define _PG_PCMCIA_IO16 0x00000600 /* 16 bit I/O */ +#define _PG_PCMCIA_MEM8 0x00000800 /* 8 bit common memory */ +#define _PG_PCMCIA_MEM16 0x00000a00 /* 16 bit common memory */ +#define _PG_PCMCIA_ATTR8 0x00000c00 /* 8 bit attribute */ +#define _PG_PCMCIA_ATTR16 0x00000e00 /* 16 bit attribute */ + +#ifndef _LOCORE +typedef uint32_t pt_entry_t; +#endif /* _LOCORE */ +#endif /* !_SH_PTE_H_ */ diff --git a/sys/arch/sh/include/ptrace.h b/sys/arch/sh/include/ptrace.h new file mode 100644 index 00000000000..3c25fb88b73 --- /dev/null +++ b/sys/arch/sh/include/ptrace.h @@ -0,0 +1,40 @@ +/* $OpenBSD: ptrace.h,v 1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: ptrace.h,v 1.3 2002/02/28 01:58:53 uch Exp $ */ + +/* + * Copyright (c) 1993 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. + * 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. + */ + +/* + * SuperH ptrace definitions + */ + +#define PT_GETREGS (PT_FIRSTMACH + 1) +#define PT_SETREGS (PT_FIRSTMACH + 2) + diff --git a/sys/arch/sh/include/reg.h b/sys/arch/sh/include/reg.h new file mode 100644 index 00000000000..ec499656bb1 --- /dev/null +++ b/sys/arch/sh/include/reg.h @@ -0,0 +1,103 @@ +/* $OpenBSD: reg.h,v 1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: reg.h,v 1.5 2005/12/11 12:18:58 christos Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * 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. 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. + * + * @(#)reg.h 5.5 (Berkeley) 1/18/91 + */ + +#ifndef _SH_REG_H_ +#define _SH_REG_H_ + +/* + * Location of the users' stored + * registers within appropriate frame of 'trap' and 'syscall', relative to + * base of stack frame. + * + * XXX + * The #defines aren't used in the kernel, but some user-level code still + * expects them. + */ + +/* When referenced during a trap/exception, registers are at these offsets */ + +#define tSPC (0) +#define tSSR (1) +#define tPR (2) +#define tR14 (3) +#define tR13 (4) +#define tR12 (5) +#define tR11 (6) +#define tR10 (7) +#define tR9 (8) + +#define tR8 (11) +#define tR7 (12) +#define tR6 (13) +#define tR5 (14) +#define tR4 (15) +#define tR3 (16) +#define tR2 (17) +#define tR1 (18) +#define tR0 (19) + +/* + * Registers accessible to ptrace(2) syscall for debugger + * The machine-dependent code for PT_{SET,GET}REGS needs to + * use whichver order, defined above, is correct, so that it + * is all invisible to the user. + */ +struct reg { + int r_spc; + int r_ssr; + int r_pr; + int r_mach; + int r_macl; + int r_r15; + int r_r14; + int r_r13; + int r_r12; + int r_r11; + int r_r10; + int r_r9; + int r_r8; + int r_r7; + int r_r6; + int r_r5; + int r_r4; + int r_r3; + int r_r2; + int r_r1; + int r_r0; +}; + +#endif /* !_SH_REG_H_ */ diff --git a/sys/arch/sh/include/rtcreg.h b/sys/arch/sh/include/rtcreg.h new file mode 100644 index 00000000000..7ebd9274e38 --- /dev/null +++ b/sys/arch/sh/include/rtcreg.h @@ -0,0 +1,106 @@ +/* $OpenBSD: rtcreg.h,v 1.1.1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: rtcreg.h,v 1.10 2006/09/03 12:38:34 uwe Exp $ */ + +/*- + * Copyright (C) 1999 SAITOH Masanobu. 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. 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 _SH_RTCREG_H_ +#define _SH_RTCREG_H_ +#include <sh/devreg.h> + +/* + * RTC + */ +#define SH3_R64CNT 0xfffffec0 +#define SH3_RSECCNT 0xfffffec2 +#define SH3_RMINCNT 0xfffffec4 +#define SH3_RHRCNT 0xfffffec6 +#define SH3_RWKCNT 0xfffffec8 +#define SH3_RDAYCNT 0xfffffeca +#define SH3_RMONCNT 0xfffffecc +#define SH3_RYRCNT 0xfffffece +#define SH3_RSECAR 0xfffffed0 +#define SH3_RMINAR 0xfffffed2 +#define SH3_RHRAR 0xfffffed4 +#define SH3_RWKAR 0xfffffed6 +#define SH3_RDAYAR 0xfffffed8 +#define SH3_RMONAR 0xfffffeda +#define SH3_RCR1 0xfffffedc +#define SH3_RCR2 0xfffffede + +#define SH4_R64CNT 0xffc80000 +#define SH4_RSECCNT 0xffc80004 +#define SH4_RMINCNT 0xffc80008 +#define SH4_RHRCNT 0xffc8000c +#define SH4_RWKCNT 0xffc80010 +#define SH4_RDAYCNT 0xffc80014 +#define SH4_RMONCNT 0xffc80018 +#define SH4_RYRCNT 0xffc8001c /* 16 bit */ +#define SH4_RSECAR 0xffc80020 +#define SH4_RMINAR 0xffc80024 +#define SH4_RHRAR 0xffc80028 +#define SH4_RWKAR 0xffc8002c +#define SH4_RDAYAR 0xffc80030 +#define SH4_RMONAR 0xffc80034 +#define SH4_RCR1 0xffc80038 +#define SH4_RCR2 0xffc8003c + +#define SH_RCR1_CF 0x80 /* carry flag */ +#define SH_RCR1_CIE 0x10 /* carry interrupt enable */ +#define SH_RCR1_AIE 0x08 /* alarm interrupt enable */ +#define SH_RCR1_AF 0x01 /* alarm flag */ + +#define SH_RCR2_PEF 0x80 /* periodic interrupt flag */ +#define SH_RCR2_PES2 0x40 /* periodic interrupt freq */ +#define SH_RCR2_PES1 0x20 /* -//- */ +#define SH_RCR2_PES0 0x10 /* -//- */ +#define SH_RCR2_ENABLE 0x08 +#define SH_RCR2_ADJ 0x04 /* second adjustment */ +#define SH_RCR2_RESET 0x02 +#define SH_RCR2_START 0x01 + +#ifndef _LOCORE +#if defined(SH3) && defined(SH4) +extern uint32_t __sh_R64CNT; +extern uint32_t __sh_RSECCNT; +extern uint32_t __sh_RMINCNT; +extern uint32_t __sh_RHRCNT; +extern uint32_t __sh_RWKCNT; +extern uint32_t __sh_RDAYCNT; +extern uint32_t __sh_RMONCNT; +extern uint32_t __sh_RYRCNT; +extern uint32_t __sh_RSECAR; +extern uint32_t __sh_RMINAR; +extern uint32_t __sh_RHRAR; +extern uint32_t __sh_RWKAR; +extern uint32_t __sh_RDAYAR; +extern uint32_t __sh_RMONAR; +extern uint32_t __sh_RCR1; +extern uint32_t __sh_RCR2; +#endif /* SH3 && SH4 */ +#endif /* !_LOCORE */ + +#endif /* !_SH_RTCREG_H_ */ diff --git a/sys/arch/sh/include/setjmp.h b/sys/arch/sh/include/setjmp.h new file mode 100644 index 00000000000..fb8887ca147 --- /dev/null +++ b/sys/arch/sh/include/setjmp.h @@ -0,0 +1,23 @@ +/* $OpenBSD: setjmp.h,v 1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: setjmp.h,v 1.3 2006/01/05 00:50:23 uwe Exp $ */ + +/* + * machine/setjmp.h: machine dependent setjmp-related information. + */ + +#define _JBLEN 14 /* size, in longs, of a jmp_buf */ + +#define _JB_REG_PR 0 +#define _JB_REG_R8 1 +#define _JB_REG_R9 2 +#define _JB_REG_R10 3 +#define _JB_REG_R11 4 +#define _JB_REG_R12 5 +#define _JB_REG_R13 6 +#define _JB_REG_R14 7 +#define _JB_REG_R15 8 + +#define _JB_HAS_MASK 9 +#define _JB_SIGMASK 10 /* occupies sizeof(sigset_t) = 4 slots */ + +#define _JB_REG_SP _JB_REG_R15 diff --git a/sys/arch/sh/include/sh_opcode.h b/sys/arch/sh/include/sh_opcode.h new file mode 100644 index 00000000000..3fad67a443c --- /dev/null +++ b/sys/arch/sh/include/sh_opcode.h @@ -0,0 +1,163 @@ +/* $OpenBSD: sh_opcode.h,v 1.1.1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: sh_opcode.h,v 1.3 2002/04/28 17:10:36 uch Exp $ */ + +typedef union { + unsigned word; + +#if _BYTE_ORDER == BIG_ENDIAN + struct { + unsigned op: 16; + } oType; + + struct { + unsigned op1: 4; + unsigned n: 4; + unsigned op2: 8; + } nType; + + struct { + unsigned op1: 4; + unsigned m: 4; + unsigned op2: 8; + } mType; + + struct { + unsigned op1: 4; + unsigned n: 4; + unsigned m: 4; + unsigned op2: 4; + } nmType; + + struct { + unsigned op: 8; + unsigned m: 4; + unsigned d: 4; + } mdType; + + struct { + unsigned op: 8; + unsigned n: 4; + unsigned d: 4; + } nd4Type; + + struct { + unsigned op: 4; + unsigned n: 4; + unsigned m: 4; + unsigned d: 4; + } nmdType; + + struct { + unsigned op: 8; + unsigned d: 8; + } dType; + + struct { + unsigned op: 4; + unsigned d: 12; + } d12Type; + + struct { + unsigned op: 4; + unsigned n: 4; + unsigned d: 8; + } nd8Type; + + struct { + unsigned op: 8; + unsigned i: 8; + } iType; + + struct { + unsigned op: 4; + unsigned n: 4; + unsigned i: 8; + } niType; +#endif +#if _BYTE_ORDER == LITTLE_ENDIAN +struct { + unsigned op: 16; + } oType; + + struct { + unsigned op2: 8; + unsigned n: 4; + unsigned op1: 4; + } nType; + + struct { + unsigned op2: 8; + unsigned m: 4; + unsigned op1: 4; + } mType; + + struct { + unsigned op2: 4; + unsigned m: 4; + unsigned n: 4; + unsigned op1: 4; + } nmType; + + struct { + unsigned d: 4; + unsigned m: 4; + unsigned op: 8; + } mdType; + + struct { + unsigned d: 4; + unsigned n: 4; + unsigned op: 8; + } nd4Type; + + struct { + unsigned d: 4; + unsigned m: 4; + unsigned n: 4; + unsigned op: 4; + } nmdType; + + struct { + unsigned d: 8; + unsigned op: 8; + } dType; + + struct { + unsigned d: 12; + unsigned op: 4; + } d12Type; + + struct { + unsigned d: 8; + unsigned n: 4; + unsigned op: 4; + } nd8Type; + + struct { + unsigned i: 8; + unsigned op: 8; + } iType; + + struct { + unsigned i: 8; + unsigned n: 4; + unsigned op: 4; + } niType; +#endif +} InstFmt; + +#define OP_BF 0x8b +#define OP_BFS 0x8f +#define OP_BT 0x89 +#define OP_BTS 0x8d +#define OP_BRA 0xa +#define OP_BSR 0xb +#define OP1_BRAF 0x0 +#define OP2_BRAF 0x23 +#define OP1_BSRF 0x0 +#define OP2_BSRF 0x03 +#define OP1_JMP 0x4 +#define OP2_JMP 0x2b +#define OP1_JSR 0x4 +#define OP2_JSR 0x0b +#define OP_RTS 0xffff diff --git a/sys/arch/sh/include/signal.h b/sys/arch/sh/include/signal.h new file mode 100644 index 00000000000..b742e598ef5 --- /dev/null +++ b/sys/arch/sh/include/signal.h @@ -0,0 +1,80 @@ +/* $OpenBSD: signal.h,v 1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: signal.h,v 1.12 2005/12/11 12:18:58 christos Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1989, 1991 Regents of the University of California. + * 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. 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. + * + * @(#)signal.h 7.16 (Berkeley) 3/17/91 + */ + +#ifndef _SH_SIGNAL_H_ +#define _SH_SIGNAL_H_ + +#include <sys/cdefs.h> + +typedef int sig_atomic_t; + +#if __BSD_VISIBLE || __XPG_VISIBLE >= 420 +/* + * Information pushed on stack when a signal is delivered. + * This is used by the kernel to restore state following + * execution of the signal handler. It is also made available + * to the handler to allow it to restore state properly if + * a non-standard exit is performed. + */ +struct sigcontext { + int sc_spc; + int sc_ssr; + int sc_pr; + int sc_r14; + int sc_r13; + int sc_r12; + int sc_r11; + int sc_r10; + int sc_r9; + int sc_r8; + int sc_r7; + int sc_r6; + int sc_r5; + int sc_r4; + int sc_r3; + int sc_r2; + int sc_r1; + int sc_r0; + int sc_r15; + + int sc_onstack; /* sigstack state to restore */ + + int sc_expevt; /* XXX should be above */ + int sc_err; + + unsigned int sc_mask; /* signal mask to restore */ +}; + +#endif /* __BSD_VISIBLE || __XPG_VISIBLE >= 420 */ +#endif /* !_SH_SIGNAL_H_ */ diff --git a/sys/arch/sh/include/spinlock.h b/sys/arch/sh/include/spinlock.h new file mode 100644 index 00000000000..6fc31bec819 --- /dev/null +++ b/sys/arch/sh/include/spinlock.h @@ -0,0 +1,52 @@ +/* $OpenBSD: spinlock.h,v 1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: lock.h,v 1.10 2006/01/03 01:29:46 uwe Exp $ */ + +/*- + * Copyright (c) 2002 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Gregory McGarry. + * + * 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. + */ + +/* + * Machine-dependent spin lock operations. + */ + +#ifndef _SH_SPINLOCK_H_ +#define _SH_SPINLOCK_H_ + +typedef volatile u_int8_t _spinlock_lock_t; + +#define _SPINLOCK_LOCKED 0x80 +#define _SPINLOCK_UNLOCKED 0x00 + +#endif /* !_SH_SPINLOCK_H_ */ diff --git a/sys/arch/sh/include/stdarg.h b/sys/arch/sh/include/stdarg.h new file mode 100644 index 00000000000..b6a7a3f7f88 --- /dev/null +++ b/sys/arch/sh/include/stdarg.h @@ -0,0 +1,60 @@ +/* $OpenBSD: stdarg.h,v 1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: stdarg.h,v 1.9 2006/05/21 22:39:04 uwe Exp $ */ + +/* + * Copyright (c) 1991, 1993 + * The Regents of the University of California. 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. 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. + * + * from: @(#)stdarg.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _SH_STDARG_H_ +#define _SH_STDARG_H_ + +#include <sys/cdefs.h> +#include <machine/_types.h> + +typedef __va_list va_list; + +#ifdef __lint__ +#define __builtin_next_arg(t) ((t) ? 0 : 0) +#define __builtin_stdarg_start(a, l) ((a) = ((l) ? 0 : 0)) +#define __builtin_va_arg(a, t) ((t)((a) ? 0 : 0)) +#define __builtin_va_end /* nothing */ +#define __builtin_va_copy(d, s) ((d) = (s)) +#endif + +#define va_start(ap, last) __builtin_stdarg_start((ap), (last)) +#define va_arg __builtin_va_arg +#define va_end __builtin_va_end +#define __va_copy(dest, src) __builtin_va_copy((dest), (src)) + +#if __ISO_C_VISIBLE >= 1999 +#define va_copy(dest, src) __va_copy((dest), (src)) +#endif + +#endif /* !_SH_STDARG_H_ */ diff --git a/sys/arch/sh/include/tmureg.h b/sys/arch/sh/include/tmureg.h new file mode 100644 index 00000000000..959957bd8f2 --- /dev/null +++ b/sys/arch/sh/include/tmureg.h @@ -0,0 +1,115 @@ +/* $OpenBSD: tmureg.h,v 1.1.1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: tmureg.h,v 1.11 2006/03/04 01:55:03 uwe Exp $ */ + +/*- + * Copyright (C) 1999 SAITOH Masanobu. 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. 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 _SH_TMUREG_H_ +#define _SH_TMUREG_H_ +#include <sh/devreg.h> + +/* + * TMU + */ +#define SH3_TOCR 0xfffffe90 +#define SH3_TSTR 0xfffffe92 +#define SH3_TCOR0 0xfffffe94 +#define SH3_TCNT0 0xfffffe98 +#define SH3_TCR0 0xfffffe9c +#define SH3_TCOR1 0xfffffea0 +#define SH3_TCNT1 0xfffffea4 +#define SH3_TCR1 0xfffffea8 +#define SH3_TCOR2 0xfffffeac +#define SH3_TCNT2 0xfffffeb0 +#define SH3_TCR2 0xfffffeb4 +#define SH3_TCPR2 0xfffffeb8 + +#define SH4_TOCR 0xffd80000 +#define SH4_TSTR 0xffd80004 +#define SH4_TCOR0 0xffd80008 +#define SH4_TCNT0 0xffd8000c +#define SH4_TCR0 0xffd80010 +#define SH4_TCOR1 0xffd80014 +#define SH4_TCNT1 0xffd80018 +#define SH4_TCR1 0xffd8001c +#define SH4_TCOR2 0xffd80020 +#define SH4_TCNT2 0xffd80024 +#define SH4_TCR2 0xffd80028 +#define SH4_TCPR2 0xffd8002c +#define SH4_TSTR2 0xfe100004 +#define SH4_TCOR3 0xfe100008 +#define SH4_TCNT3 0xfe10000c +#define SH4_TCR3 0xfe100010 +#define SH4_TCOR4 0xfe100014 +#define SH4_TCNT4 0xfe100018 +#define SH4_TCR4 0xfe10001c + + +#define TOCR_TCOE 0x01 +#define TSTR_STR2 0x04 +#define TSTR_STR1 0x02 +#define TSTR_STR0 0x01 +#define TCR_ICPF 0x0200 +#define TCR_UNF 0x0100 +#define TCR_ICPE1 0x0080 +#define TCR_ICPE0 0x0040 +#define TCR_UNIE 0x0020 +#define TCR_CKEG1 0x0010 +#define TCR_CKEG0 0x0008 +#define TCR_TPSC2 0x0004 +#define TCR_TPSC1 0x0002 +#define TCR_TPSC0 0x0001 +#define TCR_TPSC_P4 0x0000 +#define TCR_TPSC_P16 0x0001 +#define TCR_TPSC_P64 0x0002 +#define TCR_TPSC_P256 0x0003 +#define SH3_TCR_TPSC_RTC 0x0004 +#define SH3_TCR_TPSC_TCLK 0x0005 +#define SH4_TCR_TPSC_P1024 0x0004 +#define SH4_TCR_TPSC_RTC 0x0006 +#define SH4_TCR_TPSC_TCLK 0x0007 +#define SH4_TSTR2_STR4 0x02 +#define SH4_TSTR2_STR3 0x01 + + +#ifndef _LOCORE +#if defined(SH3) && defined(SH4) +extern uint32_t __sh_TOCR; +extern uint32_t __sh_TSTR; +extern uint32_t __sh_TCOR0; +extern uint32_t __sh_TCNT0; +extern uint32_t __sh_TCR0; +extern uint32_t __sh_TCOR1; +extern uint32_t __sh_TCNT1; +extern uint32_t __sh_TCR1; +extern uint32_t __sh_TCOR2; +extern uint32_t __sh_TCNT2; +extern uint32_t __sh_TCR2; +extern uint32_t __sh_TCPR2; +#endif /* SH3 && SH4 */ +#endif /* !_LOCORE */ + +#endif /* !_SH_TMUREG_H_ */ diff --git a/sys/arch/sh/include/trap.h b/sys/arch/sh/include/trap.h new file mode 100644 index 00000000000..b3a4bca347b --- /dev/null +++ b/sys/arch/sh/include/trap.h @@ -0,0 +1,187 @@ +/* $OpenBSD: trap.h,v 1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: exception.h,v 1.9 2006/07/22 21:58:29 uwe Exp $ */ + +/*- + * Copyright (c) 2002 The NetBSD Foundation, Inc. + * 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 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. + */ + +#ifndef _SH_EXCEPTION_H_ +#define _SH_EXCEPTION_H_ +/* + * SH3/SH4 Exception handling. + */ +#include <sh/devreg.h> + +#ifdef _KERNEL +#define SH3_TRA 0xffffffd0 /* 32bit */ +#define SH3_EXPEVT 0xffffffd4 /* 32bit */ +#define SH3_INTEVT 0xffffffd8 /* 32bit */ +#define SH7709_INTEVT2 0xa4000000 /* 32bit */ + +#define SH4_TRA 0xff000020 /* 32bit */ +#define SH4_EXPEVT 0xff000024 /* 32bit */ +#define SH4_INTEVT 0xff000028 /* 32bit */ + +/* + * EXPEVT + */ +/* Reset exception */ +#define EXPEVT_RESET_POWER 0x000 /* Power-On reset */ +#define EXPEVT_RESET_MANUAL 0x020 /* Manual reset */ +#define EXPEVT_RESET_TLB_MULTI_HIT 0x140 /* SH4 only */ + +/* General exception */ +#define EXPEVT_TLB_MISS_LD 0x040 /* TLB miss (load) */ +#define EXPEVT_TLB_MISS_ST 0x060 /* TLB miss (store) */ +#define EXPEVT_TLB_MOD 0x080 /* Initial page write */ +#define EXPEVT_TLB_PROT_LD 0x0a0 /* Protection violation (load) */ +#define EXPEVT_TLB_PROT_ST 0x0c0 /* Protection violation (store)*/ +#define EXPEVT_ADDR_ERR_LD 0x0e0 /* Address error (load) */ +#define EXPEVT_ADDR_ERR_ST 0x100 /* Address error (store) */ +#define EXPEVT_FPU 0x120 /* FPU exception */ +#define EXPEVT_TRAPA 0x160 /* Unconditional trap (TRAPA) */ +#define EXPEVT_RES_INST 0x180 /* Illegal instruction */ +#define EXPEVT_SLOT_INST 0x1a0 /* Illegal slot instruction */ +#define EXPEVT_BREAK 0x1e0 /* User break */ +#define EXPEVT_FPU_DISABLE 0x800 /* FPU disabled */ +#define EXPEVT_FPU_SLOT_DISABLE 0x820 /* Slot FPU disabled */ + +/* Software bit */ +#define EXP_USER 0x001 /* exception from user-mode */ + +#define _SH_TRA_SYSCALL 0x80 /* syscall trapa number */ +#define _SH_TRA_BREAK 0xc3 /* magic number for debugger */ + +/* + * INTEVT/INTEVT2 + */ +/* External interrupt */ +#define SH_INTEVT_NMI 0x1c0 + +#define SH_INTEVT_TMU0_TUNI0 0x400 +#define SH_INTEVT_TMU1_TUNI1 0x420 +#define SH_INTEVT_TMU2_TUNI2 0x440 +#define SH_INTEVT_TMU2_TICPI2 0x460 + +#define SH_INTEVT_SCI_ERI 0x4e0 +#define SH_INTEVT_SCI_RXI 0x500 +#define SH_INTEVT_SCI_TXI 0x520 +#define SH_INTEVT_SCI_TEI 0x540 + +#define SH_INTEVT_WDT_ITI 0x560 + +#define SH_INTEVT_IRL9 0x320 +#define SH_INTEVT_IRL11 0x360 +#define SH_INTEVT_IRL13 0x3a0 + +#define SH4_INTEVT_SCIF_ERI 0x700 +#define SH4_INTEVT_SCIF_RXI 0x720 +#define SH4_INTEVT_SCIF_BRI 0x740 +#define SH4_INTEVT_SCIF_TXI 0x760 + +#define SH7709_INTEVT2_IRQ0 0x600 +#define SH7709_INTEVT2_IRQ1 0x620 +#define SH7709_INTEVT2_IRQ2 0x640 +#define SH7709_INTEVT2_IRQ3 0x660 +#define SH7709_INTEVT2_IRQ4 0x680 +#define SH7709_INTEVT2_IRQ5 0x6a0 + +#define SH7709_INTEVT2_PINT07 0x700 +#define SH7709_INTEVT2_PINT8F 0x720 + +#define SH7709_INTEVT2_DEI0 0x800 +#define SH7709_INTEVT2_DEI1 0x820 +#define SH7709_INTEVT2_DEI2 0x840 +#define SH7709_INTEVT2_DEI3 0x860 + +#define SH7709_INTEVT2_IRDA_ERI 0x880 +#define SH7709_INTEVT2_IRDA_RXI 0x8a0 +#define SH7709_INTEVT2_IRDA_BRI 0x8c0 +#define SH7709_INTEVT2_IRDA_TXI 0x8e0 + +#define SH7709_INTEVT2_SCIF_ERI 0x900 +#define SH7709_INTEVT2_SCIF_RXI 0x920 +#define SH7709_INTEVT2_SCIF_BRI 0x940 +#define SH7709_INTEVT2_SCIF_TXI 0x960 + +#define SH7709_INTEVT2_ADC 0x980 + +/* SH7750R, SH7751, SH7751R */ +#define SH4_INTEVT_IRL0 0x240 +#define SH4_INTEVT_IRL1 0x2a0 +#define SH4_INTEVT_IRL2 0x300 +#define SH4_INTEVT_IRL3 0x360 + +#define SH4_INTEVT_IRQ0 0x200 +#define SH4_INTEVT_IRQ1 0x220 +#define SH4_INTEVT_IRQ2 0x240 +#define SH4_INTEVT_IRQ3 0x260 +#define SH4_INTEVT_IRQ4 0x280 +#define SH4_INTEVT_IRQ5 0x2a0 +#define SH4_INTEVT_IRQ6 0x2c0 +#define SH4_INTEVT_IRQ7 0x2e0 +#define SH4_INTEVT_IRQ8 0x300 +#define SH4_INTEVT_IRQ9 0x320 +#define SH4_INTEVT_IRQ10 0x340 +#define SH4_INTEVT_IRQ11 0x360 +#define SH4_INTEVT_IRQ12 0x380 +#define SH4_INTEVT_IRQ13 0x3a0 +#define SH4_INTEVT_IRQ14 0x3c0 +#define SH4_INTEVT_IRQ15 0x3e0 + +#define SH4_INTEVT_TMU3 0xb00 +#define SH4_INTEVT_TMU4 0xb80 + +#define SH4_INTEVT_PCISERR 0xa00 +#define SH4_INTEVT_PCIERR 0xae0 +#define SH4_INTEVT_PCIPWDWN 0xac0 +#define SH4_INTEVT_PCIPWON 0xaa0 +#define SH4_INTEVT_PCIDMA0 0xa80 +#define SH4_INTEVT_PCIDMA1 0xa60 +#define SH4_INTEVT_PCIDMA2 0xa40 +#define SH4_INTEVT_PCIDMA3 0xa20 + +#ifndef _LOCORE + +#if defined(SH3) && defined(SH4) +extern uint32_t __sh_TRA; +extern uint32_t __sh_EXPEVT; +extern uint32_t __sh_INTEVT; +#endif /* SH3 && SH4 */ + +extern const char * const exp_type[]; +extern const int exp_types; + +#endif /* !_LOCORE */ + +#endif /* _KERNEL */ +#endif /* !_SH_EXCEPTION_H_ */ diff --git a/sys/arch/sh/include/ubcreg.h b/sys/arch/sh/include/ubcreg.h new file mode 100644 index 00000000000..dacbfa52f1d --- /dev/null +++ b/sys/arch/sh/include/ubcreg.h @@ -0,0 +1,86 @@ +/* $OpenBSD: ubcreg.h,v 1.1.1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: ubcreg.h,v 1.4 2006/03/04 01:55:03 uwe Exp $ */ + +/*- + * Copyright (C) 1999 SAITOH Masanobu. 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. 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 _SH_UBCREG_H_ +#define _SH_UBCREG_H_ +#include <sh/devreg.h> + +/* + * User Break Controller + */ + +/* ch-A */ +#define SH3_BARA 0xffffffb0 +#define SH3_BAMRA 0xffffffb4 +#define SH3_BASRA 0xffffffe4 +#define SH3_BBRA 0xffffffb8 +/* ch-B */ +#define SH3_BARB 0xffffffa0 +#define SH3_BAMRB 0xffffffa4 +#define SH3_BASRB 0xffffffe8 +#define SH3_BBRB 0xffffffa8 +#define SH3_BDRB 0xffffff90 +#define SH3_BDMRB 0xffffff94 +/* common */ +#define SH3_BRCR 0xffffff98 + + +/* ch-A */ +#define SH4_BARA 0xff200000 +#define SH4_BAMRA 0xff200004 +#define SH4_BASRA 0xff000014 +#define SH4_BBRA 0xff200008 + +/* ch-B */ +#define SH4_BARB 0xff20000c +#define SH4_BAMRB 0xff200010 +#define SH4_BASRB 0xff000018 +#define SH4_BBRB 0xff200014 +#define SH4_BDRB 0xff200018 +#define SH4_BDMRB 0xff20001c +/* common */ +#define SH4_BRCR 0xff200020 + +#ifndef _LOCORE +#if defined(SH3) && defined(SH4) +extern uint32_t __sh_BARA; +extern uint32_t __sh_BAMRA; +extern uint32_t __sh_BASRA; +extern uint32_t __sh_BBRA; +extern uint32_t __sh_BARB; +extern uint32_t __sh_BAMRB; +extern uint32_t __sh_BASRB; +extern uint32_t __sh_BBRB; +extern uint32_t __sh_BDRB; +extern uint32_t __sh_BDMRB; +extern uint32_t __sh_BRCR; +#endif /* SH3 && SH4 */ +#endif /* !_LOCORE */ + +#endif /* !_SH_UBCREG_H_ */ diff --git a/sys/arch/sh/include/userret.h b/sys/arch/sh/include/userret.h new file mode 100644 index 00000000000..07db83959a2 --- /dev/null +++ b/sys/arch/sh/include/userret.h @@ -0,0 +1,94 @@ +/* $OpenBSD: userret.h,v 1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: userret.h,v 1.9 2006/02/16 20:17:15 perry Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the Systems Programming Group of the University of Utah Computer + * Science Department and Ralph Campbell. + * + * 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. 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. + * + * from: Utah Hdr: trap.c 1.32 91/04/06 + * + * @(#)trap.c 8.5 (Berkeley) 1/11/94 + */ +/* + * Copyright (c) 1988 University of Utah. + * + * This code is derived from software contributed to Berkeley by + * the Systems Programming Group of the University of Utah Computer + * Science Department and Ralph Campbell. + * + * 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. + * + * from: Utah Hdr: trap.c 1.32 91/04/06 + * + * @(#)trap.c 8.5 (Berkeley) 1/11/94 + */ + +#include <sys/signalvar.h> +#include <machine/cpu.h> + +static __inline void userret(struct proc *); + +static __inline void +userret(struct proc *p) +{ + int sig; + + while ((sig = CURSIG(p)) != 0) + postsig(sig); + + curpriority = p->p_priority = p->p_usrpri; +} diff --git a/sys/arch/sh/include/varargs.h b/sys/arch/sh/include/varargs.h new file mode 100644 index 00000000000..6fae10957e0 --- /dev/null +++ b/sys/arch/sh/include/varargs.h @@ -0,0 +1,57 @@ +/* $OpenBSD: varargs.h,v 1.1.1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: varargs.h,v 1.7 2006/05/21 22:39:04 uwe Exp $ */ + +/* + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * 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. 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. + * + * from: @(#)varargs.h 8.2 (Berkeley) 3/22/94 + */ + +#ifndef _SH_VARARGS_H_ +#define _SH_VARARGS_H_ + +#include <machine/stdarg.h> + +#if __GNUC__ == 1 +#define __va_ellipsis +#else +#define __va_ellipsis ... +#endif + +#define va_alist __builtin_va_alist +#define va_dcl __builtin_va_alist_t __builtin_va_alist; __va_ellipsis + +#undef va_start +#define va_start(ap) __builtin_varargs_start((ap)) + +#endif /* !_SH_VARARGS_H_ */ diff --git a/sys/arch/sh/include/vmparam.h b/sys/arch/sh/include/vmparam.h new file mode 100644 index 00000000000..c9bf886ac4d --- /dev/null +++ b/sys/arch/sh/include/vmparam.h @@ -0,0 +1,107 @@ +/* $OpenBSD: vmparam.h,v 1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: vmparam.h,v 1.17 2006/03/04 01:55:03 uwe Exp $ */ + +/*- + * Copyright (c) 2002 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by UCHIYAMA Yasushi. + * + * 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. + */ + +#ifndef _SH_VMPARAM_H_ +#define _SH_VMPARAM_H_ +#include <sys/queue.h> + +/* Virtual address map. */ +#define VM_MIN_ADDRESS ((vaddr_t)0) +#define VM_MAXUSER_ADDRESS ((vaddr_t)0x7ffff000) +#define VM_MAX_ADDRESS ((vaddr_t)0x7ffff000) +#define VM_MIN_KERNEL_ADDRESS ((vaddr_t)0xc0000000) +#define VM_MAX_KERNEL_ADDRESS ((vaddr_t)0xe0000000) + +/* top of stack */ +#define USRSTACK VM_MAXUSER_ADDRESS + +/* Virtual memory resoruce limit. */ +#define MAXTSIZ (64 * 1024 * 1024) /* max text size */ +#ifndef MAXDSIZ +#define MAXDSIZ (512 * 1024 * 1024) /* max data size */ +#endif +#ifndef MAXSSIZ +#define MAXSSIZ (32 * 1024 * 1024) /* max stack size */ +#endif + +/* initial data size limit */ +#ifndef DFLDSIZ +#define DFLDSIZ (128 * 1024 * 1024) +#endif +/* initial stack size limit */ +#ifndef DFLSSIZ +#define DFLSSIZ (2 * 1024 * 1024) +#endif + +#define STACKGAP_RANDOM (256 * 1024) + +/* + * Size of shared memory map + */ +#ifndef SHMMAXPGS +#define SHMMAXPGS 1024 +#endif + +/* Size of user raw I/O map */ +#ifndef USRIOSIZE +#define USRIOSIZE (MAXBSIZE / PAGE_SIZE * 8) +#endif + +#define VM_PHYS_SIZE (USRIOSIZE * PAGE_SIZE) + +/* pmap-specific data store in the vm_page structure. */ +#define __HAVE_VM_PAGE_MD +#define PVH_REFERENCED 1 +#define PVH_MODIFIED 2 + +#ifndef _LOCORE +struct pv_entry; +struct vm_page_md { + SLIST_HEAD(, pv_entry) pvh_head; + int pvh_flags; +}; + +#define VM_MDPAGE_INIT(pg) \ +do { \ + struct vm_page_md *pvh = &(pg)->mdpage; \ + SLIST_INIT(&pvh->pvh_head); \ + pvh->pvh_flags = 0; \ +} while (/*CONSTCOND*/0) +#endif /* _LOCORE */ +#endif /* !_SH_VMPARAM_H_ */ diff --git a/sys/arch/sh/sh/cache.c b/sys/arch/sh/sh/cache.c new file mode 100644 index 00000000000..53939b37376 --- /dev/null +++ b/sys/arch/sh/sh/cache.c @@ -0,0 +1,173 @@ +/* $OpenBSD: cache.c,v 1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: cache.c,v 1.11 2006/01/02 23:37:34 uwe Exp $ */ + +/*- + * Copyright (c) 2002 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by UCHIYAMA Yasushi. + * + * 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. + */ + +#include <sys/param.h> +#include <sys/systm.h> + +#include <sh/cache.h> +#include <sh/cache_sh3.h> +#include <sh/cache_sh4.h> + +/* + * __cache_flush is used before sh_cache_config() is called. + */ +static void __cache_flush(void); + +struct sh_cache_ops sh_cache_ops = { + ._icache_sync_all = (void (*)(void))__cache_flush, + ._icache_sync_range = (void (*)(vaddr_t, vsize_t))__cache_flush, + ._icache_sync_range_index = (void (*)(vaddr_t, vsize_t))__cache_flush, + ._dcache_wbinv_all = (void (*)(void))__cache_flush, + ._dcache_wbinv_range = (void (*)(vaddr_t, vsize_t))__cache_flush, + ._dcache_wbinv_range_index = (void (*)(vaddr_t, vsize_t))__cache_flush, + ._dcache_inv_range = (void (*)(vaddr_t, vsize_t))__cache_flush, + ._dcache_wb_range = (void (*)(vaddr_t, vsize_t))__cache_flush +}; + +int sh_cache_enable_icache; +int sh_cache_enable_dcache; +int sh_cache_write_through; +int sh_cache_write_through_p0_u0_p3; +int sh_cache_write_through_p1; +int sh_cache_unified; +int sh_cache_ways; +int sh_cache_size_icache; +int sh_cache_size_dcache; +int sh_cache_line_size; +int sh_cache_ram_mode; +int sh_cache_index_mode_icache; +int sh_cache_index_mode_dcache; + +void +sh_cache_init() +{ +#ifdef CACHE_DEBUG + return; +#endif +#ifdef SH3 + if (CPU_IS_SH3) + sh3_cache_config(); +#endif +#ifdef SH4 + if (CPU_IS_SH4) + sh4_cache_config(); +#endif +} + +void +sh_cache_information() +{ +#ifdef CACHE_DEBUG + printf("*** USE CPU INDEPENDENT CACHE OPS. ***\n"); + return; +#endif + + /* I-cache or I/D-unified cache */ + printf("cpu0: %dKB/%dB", + sh_cache_size_icache >> 10, sh_cache_line_size); + if (sh_cache_ways > 1) + printf(" %d-way set-associative", sh_cache_ways); + else + printf(" direct-mapped"); + if (sh_cache_unified) + printf(" I/D-unified"); + else + printf(" Instruction"); + printf(" cache."); + if (!sh_cache_enable_icache) + printf(" DISABLED"); + if (sh_cache_unified && sh_cache_ram_mode) + printf(" RAM-mode"); + if (sh_cache_index_mode_icache) + printf(" INDEX-mode"); + printf("\n"); + + /* D-cache */ + if (!sh_cache_unified) { + printf("cpu0: %dKB/%dB", sh_cache_size_dcache >> 10, + sh_cache_line_size); + if (sh_cache_ways > 1) + printf(" %d-way set-associative", sh_cache_ways); + else + printf(" direct-mapped"); + printf(" Data cache."); + if (!sh_cache_enable_dcache) + printf(" DISABLED"); + if (sh_cache_ram_mode) + printf(" RAM-mode"); + if (sh_cache_index_mode_dcache) + printf(" INDEX-mode"); + printf("\n"); + } + + /* Write-through/back */ + printf("cpu0: P0, U0, P3 write-%s; P1 write-%s\n", + sh_cache_write_through_p0_u0_p3 ? "through" : "back", + sh_cache_write_through_p1 ? "through" : "back"); +} + +/* + * CPU-independent cache flush. + */ +void +__cache_flush() +{ + volatile int *p = (int *)SH3_PHYS_TO_P1SEG(IOM_RAM_BEGIN); + int i; + int d; + + /* Flush D-Cache */ + /* + * Access address range [13:4]. + * max: + * 16KB line-size 16B 4-way ... [11:4] * 4 + * 16KB line-size 32B 1-way ... [13:5] + */ + for (i = 0; i < 256/*entry*/ * 4/*way*/; i++) { + d = *p; + p += 4; /* next line index (16B) */ + } + + /* Flush I-Cache */ + /* + * this code flush I-cache. but can't compile.. + * __asm volatile(".space 8192"); + * + */ +} diff --git a/sys/arch/sh/sh/cache_sh3.c b/sys/arch/sh/sh/cache_sh3.c new file mode 100644 index 00000000000..af31deb58a7 --- /dev/null +++ b/sys/arch/sh/sh/cache_sh3.c @@ -0,0 +1,246 @@ +/* $OpenBSD: cache_sh3.c,v 1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: cache_sh3.c,v 1.12 2006/03/04 01:13:35 uwe Exp $ */ + +/*- + * Copyright (c) 2002 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by UCHIYAMA Yasushi. + * + * 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. + */ + +#include <sys/param.h> +#include <sys/systm.h> + +#include <sh/cache.h> +#include <sh/cache_sh3.h> + +#define round_line(x) (((x) + 15) & ~15) +#define trunc_line(x) ((x) & ~15) + +void sh3_cache_wbinv_all(void); +void sh3_cache_wbinv_range(vaddr_t, vsize_t); +void sh3_cache_wbinv_range_index(vaddr_t, vsize_t); +void sh3_cache_panic(vaddr_t, vsize_t); +void sh3_cache_nop(vaddr_t, vsize_t); + +int sh_cache_way_size; +int sh_cache_way_shift; +int sh_cache_entry_mask; + +static inline void cache_sh3_op_line_16_nway(int, vaddr_t, uint32_t); +static inline void cache_sh3_op_8lines_16_nway(int, vaddr_t, uint32_t); + +void +sh3_cache_config() +{ + size_t cache_size; + uint32_t r; + + /* Determine cache size */ + switch (cpu_product) { + default: + /* FALLTHROUGH */ + case CPU_PRODUCT_7708: + /* FALLTHROUGH */ + case CPU_PRODUCT_7708S: + /* FALLTHROUGH */ + case CPU_PRODUCT_7708R: + cache_size = 8 * 1024; + break; + case CPU_PRODUCT_7709: + cache_size = 8 * 1024; + break; + case CPU_PRODUCT_7709A: + cache_size = 16 * 1024; + break; + } + + r = _reg_read_4(SH3_CCR); + + sh_cache_unified = 1; + sh_cache_enable_unified = (r & SH3_CCR_CE); + sh_cache_line_size = 16; + sh_cache_write_through_p0_u0_p3 = r & SH3_CCR_WT; + sh_cache_write_through_p1 = !(r & SH3_CCR_CB); + sh_cache_write_through = sh_cache_write_through_p0_u0_p3 && + sh_cache_write_through_p1; + + sh_cache_ram_mode = r & SH3_CCR_RA; + if (sh_cache_ram_mode) { + /* + * In RAM-mode, way 2 and 3 are used as RAM. + */ + sh_cache_ways = 2; + sh_cache_size_unified = cache_size / 2; + } else { + sh_cache_ways = 4; + sh_cache_size_unified = cache_size; + } + + /* size enough to access foreach entries */ + sh_cache_way_size = sh_cache_size_unified / 4/*way*/; + /* mask for extracting entry select */ + sh_cache_entry_mask = (sh_cache_way_size - 1) & ~15/*line-mask*/; + /* shift for way selection (16KB/8KB) */ + sh_cache_way_shift = + /* entry bits */ + ffs(sh_cache_size_unified / (4/*way*/ * 16/*line-size*/)) - 1 + /* line bits */ + + 4; + + sh_cache_ops._icache_sync_all = sh3_cache_wbinv_all; + sh_cache_ops._icache_sync_range = sh3_cache_wbinv_range; + sh_cache_ops._icache_sync_range_index = sh3_cache_wbinv_range_index; + sh_cache_ops._dcache_wbinv_all = sh3_cache_wbinv_all; + sh_cache_ops._dcache_wbinv_range = sh3_cache_wbinv_range; + sh_cache_ops._dcache_wbinv_range_index = sh3_cache_wbinv_range_index; + /* SH3 can't invalidate without write-back */ + sh_cache_ops._dcache_inv_range = sh3_cache_panic; + if (sh_cache_write_through) { + sh_cache_ops._dcache_wb_range = sh3_cache_nop; + } else { + /* SH3 can't write-back without invalidate */ + sh_cache_ops._dcache_wb_range = sh3_cache_wbinv_range; + } +} + +/* + * cache_sh3_op_line_16_nway: (index-operation) + * + * Clear the specified bits on single 16-byte cache line. n-ways. + * + */ +static inline void +cache_sh3_op_line_16_nway(int n, vaddr_t va, uint32_t bits) +{ + vaddr_t cca; + int way; + + /* extract entry # */ + va &= sh_cache_entry_mask; + + /* operate for each way */ + for (way = 0; way < n; way++) { + cca = (SH3_CCA | way << sh_cache_way_shift | va); + _reg_bclr_4(cca, bits); + } +} + +/* + * cache_sh3_op_8lines_16_nway: (index-operation) + * + * Clear the specified bits on 8 16-byte cache lines, n-ways. + * + */ +static inline void +cache_sh3_op_8lines_16_nway(int n, vaddr_t va, uint32_t bits) +{ + volatile uint32_t *cca; + int way; + + /* extract entry # */ + va &= sh_cache_entry_mask; + + /* operate for each way */ + for (way = 0; way < n; way++) { + cca = (volatile uint32_t *) + (SH3_CCA | way << sh_cache_way_shift | va); + cca[ 0] &= ~bits; + cca[ 4] &= ~bits; + cca[ 8] &= ~bits; + cca[12] &= ~bits; + cca[16] &= ~bits; + cca[20] &= ~bits; + cca[24] &= ~bits; + cca[28] &= ~bits; + } +} + +void +sh3_cache_wbinv_all() +{ + vaddr_t va; + + for (va = 0; va < sh_cache_way_size; va += 16 * 8) + cache_sh3_op_8lines_16_nway(sh_cache_ways, va, CCA_U | CCA_V); +} + +void +sh3_cache_wbinv_range_index(vaddr_t va, vsize_t sz) +{ + vaddr_t eva = round_line(va + sz); + + va = trunc_line(va); + + while ((eva - va) >= (8 * 16)) { + cache_sh3_op_8lines_16_nway(sh_cache_ways, va, CCA_U | CCA_V); + va += 16 * 8; + } + + while (va < eva) { + cache_sh3_op_line_16_nway(sh_cache_ways, va, CCA_U | CCA_V); + va += 16; + } +} + +void +sh3_cache_wbinv_range(vaddr_t va, vsize_t sz) +{ + vaddr_t eva = round_line(va + sz); + vaddr_t cca; + + va = trunc_line(va); + + while (va < eva) { + cca = SH3_CCA | CCA_A | (va & sh_cache_entry_mask); + /* + * extract virtual tag-address. + * MMU translates it to physical address tag, + * and write to address-array. + * implicitly specified U = 0, V = 0. + */ + _reg_write_4(cca, va & CCA_TAGADDR_MASK); + va += 16; + } +} + +void +sh3_cache_panic(vaddr_t va, vsize_t size) +{ + panic("SH3 can't invalidate without write-back"); +} + +void +sh3_cache_nop(vaddr_t va, vsize_t sz) +{ + /* NO-OP */ +} diff --git a/sys/arch/sh/sh/cache_sh4.c b/sys/arch/sh/sh/cache_sh4.c new file mode 100644 index 00000000000..2f0a0fc9453 --- /dev/null +++ b/sys/arch/sh/sh/cache_sh4.c @@ -0,0 +1,470 @@ +/* $OpenBSD: cache_sh4.c,v 1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: cache_sh4.c,v 1.15 2005/12/24 23:24:02 perry Exp $ */ + +/*- + * Copyright (c) 2002 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by UCHIYAMA Yasushi. + * + * 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. + */ + +#include <sys/param.h> +#include <sys/systm.h> + +#include <sh/cache.h> +#include <sh/cache_sh4.h> + +#define round_line(x) (((x) + 31) & ~31) +#define trunc_line(x) ((x) & ~31) + +void sh4_icache_sync_all(void); +void sh4_icache_sync_range(vaddr_t, vsize_t); +void sh4_icache_sync_range_index(vaddr_t, vsize_t); +void sh4_dcache_wbinv_all(void); +void sh4_dcache_wbinv_range(vaddr_t, vsize_t); +void sh4_dcache_wbinv_range_index(vaddr_t, vsize_t); +void sh4_dcache_inv_range(vaddr_t, vsize_t); +void sh4_dcache_wb_range(vaddr_t, vsize_t); + +/* EMODE */ +void sh4_emode_icache_sync_all(void); +void sh4_emode_icache_sync_range_index(vaddr_t, vsize_t); +void sh4_emode_dcache_wbinv_all(void); +void sh4_emode_dcache_wbinv_range_index(vaddr_t, vsize_t); + +/* must be inlined. */ +static inline void cache_sh4_op_line_32(vaddr_t, vaddr_t, uint32_t, + uint32_t); +static inline void cache_sh4_op_8lines_32(vaddr_t, vaddr_t, uint32_t, + uint32_t); +static inline void cache_sh4_emode_op_line_32(vaddr_t, vaddr_t, + uint32_t, uint32_t, uint32_t); +static inline void cache_sh4_emode_op_8lines_32(vaddr_t, vaddr_t, + uint32_t, uint32_t, uint32_t); + +void +sh4_cache_config(void) +{ + int icache_size; + int dcache_size; + int ways; + uint32_t r; + + /* Determine cache size */ + switch (cpu_product) { + default: + /* FALLTHROUGH */ + case CPU_PRODUCT_7750: + case CPU_PRODUCT_7750S: + case CPU_PRODUCT_7751: +#if defined(SH4_CACHE_DISABLE_EMODE) + case CPU_PRODUCT_7750R: + case CPU_PRODUCT_7751R: +#endif + icache_size = SH4_ICACHE_SIZE; + dcache_size = SH4_DCACHE_SIZE; + ways = 1; + r = SH4_CCR_ICE|SH4_CCR_OCE|SH4_CCR_WT; + break; + +#if !defined(SH4_CACHE_DISABLE_EMODE) + case CPU_PRODUCT_7750R: + case CPU_PRODUCT_7751R: + icache_size = SH4_EMODE_ICACHE_SIZE; + dcache_size = SH4_EMODE_DCACHE_SIZE; + ways = 2; + r = SH4_CCR_EMODE|SH4_CCR_ICE|SH4_CCR_OCE|SH4_CCR_WT; + break; +#endif + } +#if defined(SH4_CACHE_DISABLE_ICACHE) + r &= ~SH4_CCR_ICE; +#endif +#if defined(SH4_CACHE_DISABLE_DCACHE) + r &= ~SH4_CCR_OCE; +#endif +#if defined(SH4_CACHE_WB_U0_P0_P3) + r &= ~SH4_CCR_WT; +#endif +#if defined(SH4_CACHE_WB_P1) + r |= SH4_CCR_CB; +#endif + + sh4_icache_sync_all(); + RUN_P2; + _reg_write_4(SH4_CCR, SH4_CCR_ICI|SH4_CCR_OCI); + _reg_write_4(SH4_CCR, r); + RUN_P1; + + r = _reg_read_4(SH4_CCR); + + sh_cache_unified = 0; + sh_cache_enable_icache = (r & SH4_CCR_ICE); + sh_cache_enable_dcache = (r & SH4_CCR_OCE); + sh_cache_ways = ways; + sh_cache_line_size = SH4_CACHE_LINESZ; + sh_cache_write_through_p0_u0_p3 = (r & SH4_CCR_WT); + sh_cache_write_through_p1 = !(r & SH4_CCR_CB); + sh_cache_write_through = sh_cache_write_through_p0_u0_p3 && + sh_cache_write_through_p1; + sh_cache_ram_mode = (r & SH4_CCR_ORA); + sh_cache_index_mode_icache = (r & SH4_CCR_IIX); + sh_cache_index_mode_dcache = (r & SH4_CCR_OIX); + + sh_cache_size_dcache = dcache_size; + if (sh_cache_ram_mode) + sh_cache_size_dcache /= 2; + sh_cache_size_icache = icache_size; + + sh_cache_ops._icache_sync_all = sh4_icache_sync_all; + sh_cache_ops._icache_sync_range = sh4_icache_sync_range; + sh_cache_ops._icache_sync_range_index = sh4_icache_sync_range_index; + + sh_cache_ops._dcache_wbinv_all = sh4_dcache_wbinv_all; + sh_cache_ops._dcache_wbinv_range = sh4_dcache_wbinv_range; + sh_cache_ops._dcache_wbinv_range_index = sh4_dcache_wbinv_range_index; + sh_cache_ops._dcache_inv_range = sh4_dcache_inv_range; + sh_cache_ops._dcache_wb_range = sh4_dcache_wb_range; + + switch (cpu_product) { + case CPU_PRODUCT_7750R: + case CPU_PRODUCT_7751R: + if (!(r & SH4_CCR_EMODE)) { + break; + } + sh_cache_ops._icache_sync_all = sh4_emode_icache_sync_all; + sh_cache_ops._icache_sync_range_index = sh4_emode_icache_sync_range_index; + sh_cache_ops._dcache_wbinv_all = sh4_emode_dcache_wbinv_all; + sh_cache_ops._dcache_wbinv_range_index = sh4_emode_dcache_wbinv_range_index; + break; + } +} + +/* + * cache_sh4_op_line_32: (index-operation) + * + * Clear the specified bits on single 32-byte cache line. + */ +static inline void +cache_sh4_op_line_32(vaddr_t va, vaddr_t base, uint32_t mask, uint32_t bits) +{ + vaddr_t cca; + + cca = base | (va & mask); + _reg_bclr_4(cca, bits); +} + +/* + * cache_sh4_op_8lines_32: (index-operation) + * + * Clear the specified bits on 8 32-byte cache lines. + */ +static inline void +cache_sh4_op_8lines_32(vaddr_t va, vaddr_t base, uint32_t mask, uint32_t bits) +{ + volatile uint32_t *cca = (volatile uint32_t *) + (base | (va & mask)); + + cca[ 0] &= ~bits; + cca[ 8] &= ~bits; + cca[16] &= ~bits; + cca[24] &= ~bits; + cca[32] &= ~bits; + cca[40] &= ~bits; + cca[48] &= ~bits; + cca[56] &= ~bits; +} + +void +sh4_icache_sync_all(void) +{ + vaddr_t va = 0; + vaddr_t eva = SH4_ICACHE_SIZE; + + sh4_dcache_wbinv_all(); + + RUN_P2; + while (va < eva) { + cache_sh4_op_8lines_32(va, SH4_CCIA, CCIA_ENTRY_MASK, CCIA_V); + va += 32 * 8; + } + RUN_P1; +} + +void +sh4_icache_sync_range(vaddr_t va, vsize_t sz) +{ + vaddr_t ccia; + vaddr_t eva = round_line(va + sz); + va = trunc_line(va); + + sh4_dcache_wbinv_range(va, (eva - va)); + + RUN_P2; + while (va < eva) { + /* CCR.IIX has no effect on this entry specification */ + ccia = SH4_CCIA | CCIA_A | (va & CCIA_ENTRY_MASK); + _reg_write_4(ccia, va & CCIA_TAGADDR_MASK); /* V = 0 */ + va += 32; + } + RUN_P1; +} + +void +sh4_icache_sync_range_index(vaddr_t va, vsize_t sz) +{ + vaddr_t eva = round_line(va + sz); + va = trunc_line(va); + + sh4_dcache_wbinv_range_index(va, eva - va); + + RUN_P2; + while ((eva - va) >= (8 * 32)) { + cache_sh4_op_8lines_32(va, SH4_CCIA, CCIA_ENTRY_MASK, CCIA_V); + va += 32 * 8; + } + + while (va < eva) { + cache_sh4_op_line_32(va, SH4_CCIA, CCIA_ENTRY_MASK, CCIA_V); + va += 32; + } + RUN_P1; +} + +void +sh4_dcache_wbinv_all(void) +{ + vaddr_t va = 0; + vaddr_t eva = SH4_DCACHE_SIZE; + + RUN_P2; + while (va < eva) { + cache_sh4_op_8lines_32(va, SH4_CCDA, CCDA_ENTRY_MASK, + (CCDA_U | CCDA_V)); + va += 32 * 8; + } + RUN_P1; +} + +void +sh4_dcache_wbinv_range(vaddr_t va, vsize_t sz) +{ + vaddr_t eva = round_line(va + sz); + va = trunc_line(va); + + while (va < eva) { + __asm volatile("ocbp @%0" : : "r"(va)); + va += 32; + } +} + +void +sh4_dcache_wbinv_range_index(vaddr_t va, vsize_t sz) +{ + vaddr_t eva = round_line(va + sz); + va = trunc_line(va); + + RUN_P2; + while ((eva - va) >= (8 * 32)) { + cache_sh4_op_8lines_32(va, SH4_CCDA, CCDA_ENTRY_MASK, + (CCDA_U | CCDA_V)); + va += 32 * 8; + } + + while (va < eva) { + cache_sh4_op_line_32(va, SH4_CCDA, CCDA_ENTRY_MASK, + (CCDA_U | CCDA_V)); + va += 32; + } + RUN_P1; +} + +void +sh4_dcache_inv_range(vaddr_t va, vsize_t sz) +{ + vaddr_t eva = round_line(va + sz); + va = trunc_line(va); + + while (va < eva) { + __asm volatile("ocbi @%0" : : "r"(va)); + va += 32; + } +} + +void +sh4_dcache_wb_range(vaddr_t va, vsize_t sz) +{ + vaddr_t eva = round_line(va + sz); + va = trunc_line(va); + + while (va < eva) { + __asm volatile("ocbwb @%0" : : "r"(va)); + va += 32; + } +} + +/* + * EMODE operation + */ +/* + * cache_sh4_emode_op_line_32: (index-operation) + * + * Clear the specified bits on single 32-byte cache line. 2-ways. + */ +static inline void +cache_sh4_emode_op_line_32(vaddr_t va, vaddr_t base, uint32_t mask, + uint32_t bits, uint32_t way_shift) +{ + vaddr_t cca; + + /* extract entry # */ + va &= mask; + + /* operate for each way */ + cca = base | (0 << way_shift) | va; + _reg_bclr_4(cca, bits); + + cca = base | (1 << way_shift) | va; + _reg_bclr_4(cca, bits); +} + +/* + * cache_sh4_emode_op_8lines_32: (index-operation) + * + * Clear the specified bits on 8 32-byte cache lines. 2-ways. + */ +static inline void +cache_sh4_emode_op_8lines_32(vaddr_t va, vaddr_t base, uint32_t mask, + uint32_t bits, uint32_t way_shift) +{ + volatile uint32_t *cca; + + /* extract entry # */ + va &= mask; + + /* operate for each way */ + cca = (volatile uint32_t *)(base | (0 << way_shift) | va); + cca[ 0] &= ~bits; + cca[ 8] &= ~bits; + cca[16] &= ~bits; + cca[24] &= ~bits; + cca[32] &= ~bits; + cca[40] &= ~bits; + cca[48] &= ~bits; + cca[56] &= ~bits; + + cca = (volatile uint32_t *)(base | (1 << way_shift) | va); + cca[ 0] &= ~bits; + cca[ 8] &= ~bits; + cca[16] &= ~bits; + cca[24] &= ~bits; + cca[32] &= ~bits; + cca[40] &= ~bits; + cca[48] &= ~bits; + cca[56] &= ~bits; +} + +void +sh4_emode_icache_sync_all(void) +{ + vaddr_t va = 0; + vaddr_t eva = SH4_EMODE_ICACHE_SIZE; + + sh4_emode_dcache_wbinv_all(); + + RUN_P2; + while (va < eva) { + cache_sh4_emode_op_8lines_32(va, SH4_CCIA, CCIA_ENTRY_MASK, + CCIA_V, 13); + va += 32 * 8; + } + RUN_P1; +} + +void +sh4_emode_icache_sync_range_index(vaddr_t va, vsize_t sz) +{ + vaddr_t eva = round_line(va + sz); + va = trunc_line(va); + + sh4_emode_dcache_wbinv_range_index(va, eva - va); + + RUN_P2; + while ((eva - va) >= (8 * 32)) { + cache_sh4_emode_op_8lines_32(va, SH4_CCIA, CCIA_ENTRY_MASK, + CCIA_V, 13); + va += 32 * 8; + } + + while (va < eva) { + cache_sh4_emode_op_line_32(va, SH4_CCIA, CCIA_ENTRY_MASK, + CCIA_V, 13); + va += 32; + } + RUN_P1; +} + +void +sh4_emode_dcache_wbinv_all(void) +{ + vaddr_t va = 0; + vaddr_t eva = SH4_EMODE_DCACHE_SIZE; + + RUN_P2; + while (va < eva) { + cache_sh4_emode_op_8lines_32(va, SH4_CCDA, CCDA_ENTRY_MASK, + (CCDA_U | CCDA_V), 14); + va += 32 * 8; + } + RUN_P1; +} + +void +sh4_emode_dcache_wbinv_range_index(vaddr_t va, vsize_t sz) +{ + vaddr_t eva = round_line(va + sz); + va = trunc_line(va); + + RUN_P2; + while ((eva - va) >= (8 * 32)) { + cache_sh4_emode_op_8lines_32(va, SH4_CCDA, CCDA_ENTRY_MASK, + (CCDA_U | CCDA_V), 14); + va += 32 * 8; + } + + while (va < eva) { + cache_sh4_emode_op_line_32(va, SH4_CCDA, CCDA_ENTRY_MASK, + (CCDA_U | CCDA_V), 14); + va += 32; + } + RUN_P1; +} diff --git a/sys/arch/sh/sh/clock.c b/sys/arch/sh/sh/clock.c new file mode 100644 index 00000000000..5db3106de69 --- /dev/null +++ b/sys/arch/sh/sh/clock.c @@ -0,0 +1,478 @@ +/* $NetBSD: clock.c,v 1.32 2006/09/05 11:09:36 uwe Exp $ */ + +/*- + * Copyright (c) 2002 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by UCHIYAMA Yasushi. + * + * 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. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/device.h> + +#include <dev/clock_subr.h> + +#include <sh/clock.h> +#include <sh/trap.h> +#include <sh/rtcreg.h> +#include <sh/tmureg.h> + +#include <machine/intr.h> + +#define NWDOG 0 + +#ifndef HZ +#define HZ 64 +#endif +#define MINYEAR 2002 /* "today" */ +#define SH_RTC_CLOCK 16384 /* Hz */ + +/* + * OpenBSD/sh clock module + * + default 64Hz + * + use TMU channel 0 as clock interrupt source. + * + use TMU channel 1 and 2 as emulated software interrupt soruce. + * + If RTC module is active, TMU channel 0 input source is RTC output. + * (1.6384kHz) + */ +struct { + /* Hard clock */ + uint32_t hz_cnt; /* clock interrupt interval count */ + uint32_t cpucycle_1us; /* calibrated loop variable (1 us) */ + uint32_t tmuclk; /* source clock of TMU0 (Hz) */ + + /* RTC ops holder. default SH RTC module */ + struct rtc_ops rtc; + int rtc_initialized; + + uint32_t pclock; /* PCLOCK */ + uint32_t cpuclock; /* CPU clock */ + int flags; +} sh_clock = { +#ifdef PCLOCK + .pclock = PCLOCK, +#endif + .rtc = { + /* SH RTC module to default RTC */ + .init = sh_rtc_init, + .get = sh_rtc_get, + .set = sh_rtc_set + } +}; + +uint32_t maxwdog; + +/* TMU */ +/* interrupt handler is timing critical. prepared for each. */ +int sh3_clock_intr(void *); +int sh4_clock_intr(void *); + +/* + * Estimate CPU and Peripheral clock. + */ +#define TMU_START(x) \ +do { \ + _reg_bclr_1(SH_(TSTR), TSTR_STR##x); \ + _reg_write_4(SH_(TCNT ## x), 0xffffffff); \ + _reg_bset_1(SH_(TSTR), TSTR_STR##x); \ +} while (/*CONSTCOND*/0) +#define TMU_ELAPSED(x) \ + (0xffffffff - _reg_read_4(SH_(TCNT ## x))) +void +sh_clock_init(int flags, struct rtc_ops *rtc) +{ + uint32_t s, t0, t1 __attribute__((__unused__)); + + sh_clock.flags = flags; + if (rtc != NULL) + sh_clock.rtc = *rtc; /* structure copy */ + + /* Initialize TMU */ + _reg_write_2(SH_(TCR0), 0); + _reg_write_2(SH_(TCR1), 0); + _reg_write_2(SH_(TCR2), 0); + + /* Reset RTC alarm and interrupt */ + _reg_write_1(SH_(RCR1), 0); + + /* Stop all counter */ + _reg_write_1(SH_(TSTR), 0); + + /* + * Estimate CPU clock. + */ + if (sh_clock.flags & SH_CLOCK_NORTC) { + /* Set TMU channel 0 source to PCLOCK / 16 */ + _reg_write_2(SH_(TCR0), TCR_TPSC_P16); + sh_clock.tmuclk = sh_clock.pclock / 16; + } else { + /* Set TMU channel 0 source to RTC counter clock (16.384kHz) */ + _reg_write_2(SH_(TCR0), + CPU_IS_SH3 ? SH3_TCR_TPSC_RTC : SH4_TCR_TPSC_RTC); + sh_clock.tmuclk = SH_RTC_CLOCK; + } + + s = _cpu_exception_suspend(); + _cpu_spin(1); /* load function on cache. */ + TMU_START(0); + _cpu_spin(10000000); + t0 = TMU_ELAPSED(0); + _cpu_exception_resume(s); + + sh_clock.cpuclock = ((10000000 * 10) / t0) * sh_clock.tmuclk; + sh_clock.cpucycle_1us = (sh_clock.tmuclk * 10) / t0; + + if (CPU_IS_SH4) + sh_clock.cpuclock >>= 1; /* two-issue */ + + /* + * Estimate PCLOCK + */ + if (sh_clock.pclock == 0) { + /* set TMU channel 1 source to PCLOCK / 4 */ + _reg_write_2(SH_(TCR1), TCR_TPSC_P4); + s = _cpu_exception_suspend(); + _cpu_spin(1); /* load function on cache. */ + TMU_START(0); + TMU_START(1); + _cpu_spin(sh_clock.cpucycle_1us * 1000000); /* 1 sec. */ + t0 = TMU_ELAPSED(0); + t1 = TMU_ELAPSED(1); + _cpu_exception_resume(s); + + sh_clock.pclock = ((t1 * 4)/ t0) * SH_RTC_CLOCK; + } + + /* Stop all counter */ + _reg_write_1(SH_(TSTR), 0); + +#undef TMU_START +#undef TMU_ELAPSED +} + +int +sh_clock_get_cpuclock() +{ + return (sh_clock.cpuclock); +} + +int +sh_clock_get_pclock() +{ + return (sh_clock.pclock); +} + +void +setstatclockrate(int newhz) +{ + /* XXX not yet */ +} + +/* + * Return the best possible estimate of the time in the timeval to + * which tv points. + */ +void +microtime(struct timeval *tv) +{ + static struct timeval lasttime; + int s; + + s = splclock(); + *tv = time; + splx(s); + + tv->tv_usec += ((sh_clock.hz_cnt - _reg_read_4(SH_(TCNT0))) + * 1000000) / sh_clock.tmuclk; + while (tv->tv_usec >= 1000000) { + tv->tv_usec -= 1000000; + tv->tv_sec++; + } + + if (tv->tv_sec == lasttime.tv_sec && + tv->tv_usec <= lasttime.tv_usec && + (tv->tv_usec = lasttime.tv_usec + 1) >= 1000000) { + tv->tv_usec -= 1000000; + tv->tv_sec++; + } + lasttime = *tv; +} + +/* + * Wait at least `n' usec. + */ +void +delay(int n) +{ + _cpu_spin(sh_clock.cpucycle_1us * n); +} + +/* + * Start the clock interrupt. + */ +void +cpu_initclocks() +{ + if (sh_clock.pclock == 0) + panic("No PCLOCK information."); + + /* Set global variables. */ + hz = HZ; + tick = 1000000 / hz; + + /* + * Use TMU channel 0 as hard clock + */ + _reg_bclr_1(SH_(TSTR), TSTR_STR0); + + if (sh_clock.flags & SH_CLOCK_NORTC) { + /* use PCLOCK/16 as TMU0 source */ + _reg_write_2(SH_(TCR0), TCR_UNIE | TCR_TPSC_P16); + } else { + /* use RTC clock as TMU0 source */ + _reg_write_2(SH_(TCR0), TCR_UNIE | + (CPU_IS_SH3 ? SH3_TCR_TPSC_RTC : SH4_TCR_TPSC_RTC)); + } + sh_clock.hz_cnt = sh_clock.tmuclk / hz - 1; + + _reg_write_4(SH_(TCOR0), sh_clock.hz_cnt); + _reg_write_4(SH_(TCNT0), sh_clock.hz_cnt); + + intc_intr_establish(SH_INTEVT_TMU0_TUNI0, IST_LEVEL, IPL_CLOCK, + CPU_IS_SH3 ? sh3_clock_intr : sh4_clock_intr, NULL, "clock"); + /* start hardclock */ + _reg_bset_1(SH_(TSTR), TSTR_STR0); + + /* + * TMU channel 1, 2 are one shot timer. + */ + _reg_write_2(SH_(TCR1), TCR_UNIE | TCR_TPSC_P4); + _reg_write_4(SH_(TCOR1), 0xffffffff); + _reg_write_2(SH_(TCR2), TCR_UNIE | TCR_TPSC_P4); + _reg_write_4(SH_(TCOR2), 0xffffffff); + + /* Make sure to start RTC */ + sh_clock.rtc.init(sh_clock.rtc._cookie); +} + +void +inittodr(time_t base) +{ + struct clock_ymdhms dt; + time_t rtc; + int s; + + if (!sh_clock.rtc_initialized) + sh_clock.rtc_initialized = 1; + + sh_clock.rtc.get(sh_clock.rtc._cookie, base, &dt); + rtc = clock_ymdhms_to_secs(&dt); + +#ifdef DEBUG + printf("inittodr: %d/%d/%d/%d/%d/%d(%d)\n", dt.dt_year, + dt.dt_mon, dt.dt_day, dt.dt_hour, dt.dt_min, dt.dt_sec, + dt.dt_wday); +#endif + + if (!(sh_clock.flags & SH_CLOCK_NOINITTODR) && + (rtc < base || + dt.dt_year < MINYEAR || dt.dt_year > 2037 || + dt.dt_mon < 1 || dt.dt_mon > 12 || + dt.dt_wday > 6 || + dt.dt_day < 1 || dt.dt_day > 31 || + dt.dt_hour > 23 || dt.dt_min > 59 || dt.dt_sec > 59)) { + /* + * Believe the time in the file system for lack of + * anything better, resetting the RTC. + */ + s = splclock(); + time.tv_sec = base; + time.tv_usec = 0; + splx(s); + printf("WARNING: preposterous clock chip time\n"); + resettodr(); + printf(" -- CHECK AND RESET THE DATE!\n"); + return; + } + + s = splclock(); + time.tv_sec = rtc; + time.tv_usec = 0; + splx(s); + + return; +} + +void +resettodr() +{ + struct clock_ymdhms dt; + int s; + + if (!sh_clock.rtc_initialized) + return; + + s = splclock(); + clock_secs_to_ymdhms(time.tv_sec, &dt); + splx(s); + + sh_clock.rtc.set(sh_clock.rtc._cookie, &dt); +#ifdef DEBUG + printf("%s: %d/%d/%d/%d/%d/%d(%d) rtc_offset %d\n", __FUNCTION__, + dt.dt_year, dt.dt_mon, dt.dt_day, dt.dt_hour, dt.dt_min, dt.dt_sec, + dt.dt_wday, rtc_offset); +#endif +} + +#ifdef SH3 +int +sh3_clock_intr(void *arg) /* trap frame */ +{ +#if (NWDOG > 0) + uint32_t i; + + i = (uint32_t)SHREG_WTCNT_R; + if (i > maxwdog) + maxwdog = i; + wdog_wr_cnt(0); /* reset to zero */ +#endif + /* clear underflow status */ + _reg_bclr_2(SH3_TCR0, TCR_UNF); + + hardclock(arg); + + return (1); +} +#endif /* SH3 */ + +#ifdef SH4 +int +sh4_clock_intr(void *arg) /* trap frame */ +{ +#if (NWDOG > 0) + uint32_t i; + + i = (uint32_t)SHREG_WTCNT_R; + if (i > maxwdog) + maxwdog = i; + wdog_wr_cnt(0); /* reset to zero */ +#endif + /* clear underflow status */ + _reg_bclr_2(SH4_TCR0, TCR_UNF); + + hardclock(arg); + + return (1); +} +#endif /* SH4 */ + +/* + * SH3 RTC module ops. + */ + +void +sh_rtc_init(void *cookie) +{ + /* Make sure to start RTC */ + _reg_write_1(SH_(RCR2), SH_RCR2_ENABLE | SH_RCR2_START); +} + +void +sh_rtc_get(void *cookie, time_t base, struct clock_ymdhms *dt) +{ + int retry = 8; + + /* disable carry interrupt */ + _reg_bclr_1(SH_(RCR1), SH_RCR1_CIE); + + do { + uint8_t r = _reg_read_1(SH_(RCR1)); + r &= ~SH_RCR1_CF; + r |= SH_RCR1_AF; /* don't clear alarm flag */ + _reg_write_1(SH_(RCR1), r); + + if (CPU_IS_SH3) + dt->dt_year = FROMBCD(_reg_read_1(SH3_RYRCNT)); + else + dt->dt_year = FROMBCD(_reg_read_2(SH4_RYRCNT) & 0x00ff); + + /* read counter */ +#define RTCGET(x, y) dt->dt_ ## x = FROMBCD(_reg_read_1(SH_(R ## y ## CNT))) + RTCGET(mon, MON); + RTCGET(wday, WK); + RTCGET(day, DAY); + RTCGET(hour, HR); + RTCGET(min, MIN); + RTCGET(sec, SEC); +#undef RTCGET + } while ((_reg_read_1(SH_(RCR1)) & SH_RCR1_CF) && --retry > 0); + + if (retry == 0) { + printf("rtc_gettime: couldn't read RTC register.\n"); + memset(dt, 0, sizeof(*dt)); + return; + } + + dt->dt_year = (dt->dt_year % 100) + 1900; + if (dt->dt_year < 1970) + dt->dt_year += 100; +} + +void +sh_rtc_set(void *cookie, struct clock_ymdhms *dt) +{ + uint8_t r; + + /* stop clock */ + r = _reg_read_1(SH_(RCR2)); + r |= SH_RCR2_RESET; + r &= ~SH_RCR2_START; + _reg_write_1(SH_(RCR2), r); + + /* set time */ + if (CPU_IS_SH3) + _reg_write_1(SH3_RYRCNT, TOBCD(dt->dt_year % 100)); + else + _reg_write_2(SH4_RYRCNT, TOBCD(dt->dt_year % 100)); +#define RTCSET(x, y) _reg_write_1(SH_(R ## x ## CNT), TOBCD(dt->dt_ ## y)) + RTCSET(MON, mon); + RTCSET(WK, wday); + RTCSET(DAY, day); + RTCSET(HR, hour); + RTCSET(MIN, min); + RTCSET(SEC, sec); +#undef RTCSET + /* start clock */ + _reg_write_1(SH_(RCR2), r | SH_RCR2_START); +} diff --git a/sys/arch/sh/sh/cpu.c b/sys/arch/sh/sh/cpu.c new file mode 100644 index 00000000000..a3c5b98f83f --- /dev/null +++ b/sys/arch/sh/sh/cpu.c @@ -0,0 +1,79 @@ +/* $OpenBSD: cpu.c,v 1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: cpu.c,v 1.8 2006/01/02 23:16:20 uwe Exp $ */ + +/*- + * Copyright (c) 2002 The NetBSD Foundation, Inc. + * 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 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. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> + +#include <sh/clock.h> +#include <sh/cache.h> +#include <sh/mmu.h> + +#include <machine/autoconf.h> + +int cpu_match(struct device *, void *, void *); +void cpu_attach(struct device *, struct device *, void *); + +struct cfattach cpu_ca = { + sizeof(struct device), cpu_match, cpu_attach +}; + +struct cfdriver cpu_cd = { + 0, "cpu", DV_DULL +}; + +int +cpu_match(struct device *parent, void *vcf, void *aux) +{ + struct mainbus_attach_args *ma = aux; + + if (strcmp(ma->ma_name, cpu_cd.cd_name) != 0) + return (0); + + return (1); +} + +void +cpu_attach(struct device *parent, struct device *self, void *aux) +{ +#define MHZ(x) ((x) / 1000000), (((x) % 1000000) / 1000) + printf(": HITACHI SH%d %d.%02d MHz PCLOCK %d.%02d MHz\n", + CPU_IS_SH3 ? 3 : 4, MHZ(sh_clock_get_cpuclock()), + MHZ(sh_clock_get_pclock())); +#undef MHZ + sh_cache_information(); + sh_mmu_information(); +} diff --git a/sys/arch/sh/sh/db_disasm.c b/sys/arch/sh/sh/db_disasm.c new file mode 100644 index 00000000000..a309151d677 --- /dev/null +++ b/sys/arch/sh/sh/db_disasm.c @@ -0,0 +1,1671 @@ +/* $OpenBSD: db_disasm.c,v 1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: db_disasm.c,v 1.13 2006/01/21 02:09:06 uwe Exp $ */ + +/* + * Copyright (c) 1998-2000 Internet Initiative Japan Inc. + * All rights reserved. + * + * Author: Akinori Koketsu + * + * 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. Redistribution with functional modification must include + * prominent notice stating how and when and by whom it is + * modified. + * 3. Redistributions in binary form have to be along with the source + * code or documentation which include above copyright notice, this + * list of conditions and the following disclaimer. + * 4. All commercial advertising materials mentioning features or use + * of this software must display the following acknowledgement: + * This product includes software developed by Internet + * Initiative Japan Inc. + * + * THIS SOFTWARE IS PROVIDED BY ``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. + */ + +#include <sys/param.h> +#include <sys/systm.h> + +#include <machine/db_machdep.h> + +#include <ddb/db_interface.h> +#include <ddb/db_output.h> + +static void get_opcode(uint16_t *, char *, size_t); +static void get_ascii(unsigned char *, char *); +static void f_02(uint16_t *, char *, size_t); +static void f_03(uint16_t *, char *, size_t); +static void f_04(uint16_t *, char *, size_t); +static void f_08(uint16_t *, char *, size_t); +static void f_09(uint16_t *, char *, size_t); +static void f_0a(uint16_t *, char *, size_t); +static void f_0b(uint16_t *, char *, size_t); +static void f_0c(uint16_t *, char *, size_t); +static void f_10(uint16_t *, char *, size_t); +static void f_20(uint16_t *, char *, size_t); +static void f_24(uint16_t *, char *, size_t); +static void f_28(uint16_t *, char *, size_t); +static void f_2c(uint16_t *, char *, size_t); +static void f_30(uint16_t *, char *, size_t); +static void f_34(uint16_t *, char *, size_t); +static void f_38(uint16_t *, char *, size_t); +static void f_3c(uint16_t *, char *, size_t); +static void f_40(uint16_t *, char *, size_t); +static void f_41(uint16_t *, char *, size_t); +static void f_42(uint16_t *, char *, size_t); +static void f_43(uint16_t *, char *, size_t); +static void f_44(uint16_t *, char *, size_t); +static void f_45(uint16_t *, char *, size_t); +static void f_46(uint16_t *, char *, size_t); +static void f_47(uint16_t *, char *, size_t); +static void f_48(uint16_t *, char *, size_t); +static void f_49(uint16_t *, char *, size_t); +static void f_4a(uint16_t *, char *, size_t); +static void f_4b(uint16_t *, char *, size_t); +static void f_4c(uint16_t *, char *, size_t); +static void f_4d(uint16_t *, char *, size_t); +static void f_4e(uint16_t *, char *, size_t); +static void f_4f(uint16_t *, char *, size_t); +static void f_50(uint16_t *, char *, size_t); +static void f_60(uint16_t *, char *, size_t); +static void f_64(uint16_t *, char *, size_t); +static void f_68(uint16_t *, char *, size_t); +static void f_6c(uint16_t *, char *, size_t); +static void f_70(uint16_t *, char *, size_t); +static void f_80(uint16_t *, char *, size_t); +static void f_90(uint16_t *, char *, size_t); +static void f_a0(uint16_t *, char *, size_t); +static void f_b0(uint16_t *, char *, size_t); +static void f_c0(uint16_t *, char *, size_t); +static void f_d0(uint16_t *, char *, size_t); +static void f_e0(uint16_t *, char *, size_t); +static void f_f0(uint16_t *, char *, size_t); +static void f_f4(uint16_t *, char *, size_t); +static void f_f8(uint16_t *, char *, size_t); +static void f_fc(uint16_t *, char *, size_t); +static void f_fd(uint16_t *, char *, size_t); +static void f_fe(uint16_t *, char *, size_t); + +typedef void (*rasm_t)(uint16_t *, char *, size_t); +static rasm_t f[16][16] = { + { /* [0][0-7] */ NULL, NULL, f_02, f_03, f_04, f_04, f_04, f_04, + /* [0][8-f] */ f_08, f_09, f_0a, f_0b, f_0c, f_0c, f_0c, f_0c }, + { /* [1][0-7] */ f_10, f_10, f_10, f_10, f_10, f_10, f_10, f_10, + /* [1][8-f] */ f_10, f_10, f_10, f_10, f_10, f_10, f_10, f_10 }, + { /* [2][0-7] */ f_20, f_20, f_20, f_20, f_24, f_24, f_24, f_24, + /* [2][8-f] */ f_28, f_28, f_28, f_28, f_2c, f_2c, f_2c, f_2c }, + { /* [3][0-7] */ f_30, f_30, f_30, f_30, f_34, f_34, f_34, f_34, + /* [3][8-f] */ f_38, f_38, f_38, f_38, f_3c, f_3c, f_3c, f_3c }, + { /* [4][0-7] */ f_40, f_41, f_42, f_43, f_44, f_45, f_46, f_47, + /* [4][8-f] */ f_48, f_49, f_4a, f_4b, f_4c, f_4d, f_4e, f_4f }, + { /* [5][0-7] */ f_50, f_50, f_50, f_50, f_50, f_50, f_50, f_50, + /* [5][8-f] */ f_50, f_50, f_50, f_50, f_50, f_50, f_50, f_50 }, + { /* [6][0-7] */ f_60, f_60, f_60, f_60, f_64, f_64, f_64, f_64, + /* [6][8-f] */ f_68, f_68, f_68, f_68, f_6c, f_6c, f_6c, f_6c }, + { /* [7][0-7] */ f_70, f_70, f_70, f_70, f_70, f_70, f_70, f_70, + /* [7][8-f] */ f_70, f_70, f_70, f_70, f_70, f_70, f_70, f_70 }, + { /* [8][0-7] */ f_80, f_80, f_80, f_80, f_80, f_80, f_80, f_80, + /* [8][8-f] */ f_80, f_80, f_80, f_80, f_80, f_80, f_80, f_80 }, + { /* [9][0-7] */ f_90, f_90, f_90, f_90, f_90, f_90, f_90, f_90, + /* [9][8-f] */ f_90, f_90, f_90, f_90, f_90, f_90, f_90, f_90 }, + { /* [a][0-7] */ f_a0, f_a0, f_a0, f_a0, f_a0, f_a0, f_a0, f_a0, + /* [a][8-f] */ f_a0, f_a0, f_a0, f_a0, f_a0, f_a0, f_a0, f_a0 }, + { /* [b][0-7] */ f_b0, f_b0, f_b0, f_b0, f_b0, f_b0, f_b0, f_b0, + /* [b][8-f] */ f_b0, f_b0, f_b0, f_b0, f_b0, f_b0, f_b0, f_b0 }, + { /* [c][0-7] */ f_c0, f_c0, f_c0, f_c0, f_c0, f_c0, f_c0, f_c0, + /* [c][8-f] */ f_c0, f_c0, f_c0, f_c0, f_c0, f_c0, f_c0, f_c0 }, + { /* [d][0-7] */ f_d0, f_d0, f_d0, f_d0, f_d0, f_d0, f_d0, f_d0, + /* [d][8-f] */ f_d0, f_d0, f_d0, f_d0, f_d0, f_d0, f_d0, f_d0 }, + { /* [e][0-7] */ f_e0, f_e0, f_e0, f_e0, f_e0, f_e0, f_e0, f_e0, + /* [e][8-f] */ f_e0, f_e0, f_e0, f_e0, f_e0, f_e0, f_e0, f_e0 }, + { /* [f][0-7] */ f_f0, f_f0, f_f0, f_f0, f_f4, f_f4, f_f4, f_f4, + /* [f][8-f] */ f_f8, f_f8, f_f8, f_f8, f_fc, f_fd, f_fe, NULL } +}; + +db_addr_t +db_disasm(db_addr_t loc, boolean_t altfmt) +{ + char line[40], ascii[4]; + void *pc = (void *)loc; + + get_opcode(pc, line, sizeof line); + if (altfmt) { + get_ascii(pc, ascii); + db_printf("%-32s ! %s\n", line, ascii); + } else + db_printf("%s\n", line); + + return (loc + 2); +} + +static void +get_ascii(unsigned char *cp, char *str) +{ + + *str++ = (0x20 <= *cp && *cp < 0x7f) ? *cp : '.'; + cp++; + *str++ = (0x20 <= *cp && *cp < 0x7f) ? *cp : '.'; + *str = '\0'; +} + +static void +get_opcode(uint16_t *sp, char *buf, size_t bufsiz) +{ + int n0, n3; + + strlcpy(buf, "unknown opcode", bufsiz); + + n0 = (*sp & 0xf000) >> 12; + n3 = (*sp & 0x000f); + + if (f[n0][n3] != NULL) { + (*f[n0][n3])(sp, buf, bufsiz); + } +} + +static void +f_02(uint16_t *code, char *buf, size_t bufsiz) +{ + int rn, type, md; + + rn = (*code & 0x0f00) >> 8; + type = (*code & 0x00c0) >> 6; + md = (*code & 0x0030) >> 4; + + switch (type) { + case 0: + switch (md) { + case 0: + snprintf(buf, bufsiz, "stc sr, r%d", rn); + break; + + case 1: + snprintf(buf, bufsiz, "stc gbr, r%d", rn); + break; + + case 2: + snprintf(buf, bufsiz, "stc vbr, r%d", rn); + break; + + case 3: + snprintf(buf, bufsiz, "stc ssr, r%d", rn); + break; + + } + break; + + case 1: + switch (md) { + case 0: + snprintf(buf, bufsiz, "stc spc, r%d", rn); + break; + } + break; + + case 2: + snprintf(buf, bufsiz, "stc r%d_bank, r%d", md, rn); + break; + + case 3: + snprintf(buf, bufsiz, "stc r%d_bank, r%d", md+4, rn); + break; + } /* end of switch (type) */ +} + +static void +f_03(uint16_t *code, char *buf, size_t bufsiz) +{ + int rn, type, md; + + rn = (*code & 0x0f00) >> 8; + type = (*code & 0x00c0) >> 6; + md = (*code & 0x0030) >> 4; + + switch (type) { + case 0: + switch (md) { + case 0: + snprintf(buf, bufsiz, "bsrf r%d", rn); + break; + + case 2: + snprintf(buf, bufsiz, "braf r%d", rn); + break; + } + break; + + case 2: + switch (md) { + case 0: + snprintf(buf, bufsiz, "pref @r%d", rn); + break; + } + break; + } /* end of switch (type) */ +} + + +static void +f_04(uint16_t *code, char *buf, size_t bufsiz) +{ + int rn, rm, md; + + rn = (*code & 0x0f00) >> 8; + rm = (*code & 0x00f0) >> 4; + md = (*code & 0x0003); + + switch (md) { + case 0: + snprintf(buf, bufsiz, "mov.b r%d, @(r0, r%d)", rm, rn); + break; + + case 1: + snprintf(buf, bufsiz, "mov.w r%d, @(r0, r%d)", rm, rn); + break; + + case 2: + snprintf(buf, bufsiz, "mov.l r%d, @(r0, r%d)", rm, rn); + break; + + case 3: + snprintf(buf, bufsiz, "mul.l r%d, r%d)", rm, rn); + break; + } /* end of switch (md) */ +} + +static void +f_08(uint16_t *code, char *buf, size_t bufsiz) +{ + int n1, type, md; + + n1 = (*code & 0x0f00) >> 8; + type = (*code & 0x00c0) >> 6; + md = (*code & 0x0030) >> 4; + + if (n1 != 0) + return; + + switch (type) { + case 0: + switch (md) { + case 0: + strlcpy(buf, "clrt", bufsiz); + break; + + case 1: + strlcpy(buf, "sett", bufsiz); + break; + + case 2: + strlcpy(buf, "clrmac", bufsiz); + break; + + case 3: + strlcpy(buf, "ldtlb", bufsiz); + break; + } + break; + + case 1: + switch (md) { + case 0: + strlcpy(buf, "clrs", bufsiz); + break; + + case 1: + strlcpy(buf, "sets", bufsiz); + break; + } + break; + } /* end of switch (type) */ +} + +static void +f_09(uint16_t *code, char *buf, size_t bufsiz) +{ + int rn, fx; + + rn = (*code & 0x0f00) >> 8; + fx = (*code & 0x00f0) >> 4; + + switch (fx) { + case 0: + if (rn != 0) + return; + strlcpy(buf, "nop", bufsiz); + break; + + case 1: + if (rn != 0) + return; + strlcpy(buf, "div0u", bufsiz); + break; + + case 2: + snprintf(buf, bufsiz, "movt r%d", rn); + break; + } /* end of switch (fx) */ +} + +static void +f_0a(uint16_t *code, char *buf, size_t bufsiz) +{ + int rn, type, md; + + rn = (*code & 0x0f00) >> 8; + type = (*code & 0x00c0) >> 6; + md = (*code & 0x0030) >> 4; + + switch (type) { + case 0: + switch (md) { + case 0: + snprintf(buf, bufsiz, "sts mach, r%d", rn); + break; + + case 1: + snprintf(buf, bufsiz, "sts macl, r%d", rn); + break; + + case 2: + snprintf(buf, bufsiz, "sts pr, r%d", rn); + break; + } + break; + + case 1: + switch (md) { + case 1: + snprintf(buf, bufsiz, "sts fpul, r%d", rn); + break; + + case 2: + snprintf(buf, bufsiz, "sts fpscr, r%d", rn); + break; + } + break; + } /* end of switch (type) */ +} + +static void +f_0b(uint16_t *code, char *buf, size_t bufsiz) +{ + int n1, fx; + + n1 = (*code & 0x0f00) >> 8; + if (n1 != 0) + return; + + fx = (*code & 0x00f0) >> 4; + switch (fx) { + case 0: + strlcpy(buf, "rts", bufsiz); + break; + + case 1: + strlcpy(buf, "sleep", bufsiz); + break; + + case 2: + strlcpy(buf, "rte", bufsiz); + break; + } /* end of switch (fx) */ +} + +static void +f_0c(uint16_t *code, char *buf, size_t bufsiz) +{ + int rn, rm, md; + + rn = (*code & 0x0f00) >> 8; + rm = (*code & 0x00f0) >> 4; + md = (*code & 0x0003); + + switch (md) { + case 0: + snprintf(buf, bufsiz, "mov.b @(r0, r%d), r%d", rm, rn); + break; + + case 1: + snprintf(buf, bufsiz, "mov.w @(r0, r%d), r%d", rm, rn); + break; + + case 2: + snprintf(buf, bufsiz, "mov.l @(r0, r%d), r%d", rm, rn); + break; + + case 3: + snprintf(buf, bufsiz, "mac.l @r%d+, r%d+", rm, rn); + break; + } /* end of switch (md) */ +} + +static void +f_10(uint16_t *code, char *buf, size_t bufsiz) +{ + int rn, rm, disp; + + rn = (*code & 0x0f00) >> 8; + rm = (*code & 0x00f0) >> 4; + disp = (*code & 0x000f); + disp *= 4; + + snprintf(buf, bufsiz, "mov.l r%d, @(%d, r%d)", rm, disp, rn); +} + +static void +f_20(uint16_t *code, char *buf, size_t bufsiz) +{ + int rn, rm, md; + + rn = (*code & 0x0f00) >> 8; + rm = (*code & 0x00f0) >> 4; + md = (*code & 0x0003); + + switch (md) { + case 0: + snprintf(buf, bufsiz, "mov.b r%d, @r%d", rm, rn); + break; + + case 1: + snprintf(buf, bufsiz, "mov.w r%d, @r%d", rm, rn); + break; + + case 2: + snprintf(buf, bufsiz, "mov.l r%d, @r%d", rm, rn); + break; + } /* end of switch (md) */ +} + + +static void +f_24(uint16_t *code, char *buf, size_t bufsiz) +{ + int rn, rm, md; + + rn = (*code & 0x0f00) >> 8; + rm = (*code & 0x00f0) >> 4; + md = (*code & 0x0003); + + switch (md) { + case 0: + snprintf(buf, bufsiz, "mov.b r%d, @-r%d", rm, rn); + break; + + case 1: + snprintf(buf, bufsiz, "mov.w r%d, @-r%d", rm, rn); + break; + + case 2: + snprintf(buf, bufsiz, "mov.l r%d, @-r%d", rm, rn); + break; + + case 3: + snprintf(buf, bufsiz, "div0s r%d, r%d)", rm, rn); + break; + } /* end of switch (md) */ +} + +static void +f_28(uint16_t *code, char *buf, size_t bufsiz) +{ + int rn, rm, md; + + rn = (*code & 0x0f00) >> 8; + rm = (*code & 0x00f0) >> 4; + md = (*code & 0x0003); + + switch (md) { + case 0: + snprintf(buf, bufsiz, "tst r%d, r%d", rm, rn); + break; + + case 1: + snprintf(buf, bufsiz, "and r%d, r%d", rm, rn); + break; + + case 2: + snprintf(buf, bufsiz, "xor r%d, r%d", rm, rn); + break; + + case 3: + snprintf(buf, bufsiz, "or r%d, r%d", rm, rn); + break; + } /* end of switch (md) */ +} + + +static void +f_2c(uint16_t *code, char *buf, size_t bufsiz) +{ + int rn, rm, md; + + rn = (*code & 0x0f00) >> 8; + rm = (*code & 0x00f0) >> 4; + md = (*code & 0x0003); + + switch (md) { + case 0: + snprintf(buf, bufsiz, "cmp/str r%d, r%d", rm, rn); + break; + + case 1: + snprintf(buf, bufsiz, "xtrct r%d, r%d", rm, rn); + break; + + case 2: + snprintf(buf, bufsiz, "mulu.w r%d, r%d", rm, rn); + break; + + case 3: + snprintf(buf, bufsiz, "muls.w r%d, r%d", rm, rn); + break; + } /* end of switch (md) */ +} + +static void +f_30(uint16_t *code, char *buf, size_t bufsiz) +{ + int rn, rm, md; + + rn = (*code & 0x0f00) >> 8; + rm = (*code & 0x00f0) >> 4; + md = (*code & 0x0003); + + switch (md) { + case 0: + snprintf(buf, bufsiz, "cmp/eq r%d, r%d", rm, rn); + break; + + case 2: + snprintf(buf, bufsiz, "cmp/hs r%d, r%d", rm, rn); + break; + + case 3: + snprintf(buf, bufsiz, "cmp/ge r%d, r%d", rm, rn); + break; + } /* end of switch (md) */ +} + + +static void +f_34(uint16_t *code, char *buf, size_t bufsiz) +{ + int rn, rm, md; + + rn = (*code & 0x0f00) >> 8; + rm = (*code & 0x00f0) >> 4; + md = (*code & 0x0003); + + switch (md) { + case 0: + snprintf(buf, bufsiz, "div1 r%d, r%d", rm, rn); + break; + + case 1: + snprintf(buf, bufsiz, "dmulu.l r%d, r%d", rm, rn); + break; + + case 2: + snprintf(buf, bufsiz, "cmp/hi r%d, r%d", rm, rn); + break; + + case 3: + snprintf(buf, bufsiz, "cmp/gt r%d, r%d", rm, rn); + break; + } /* end of switch (md) */ +} + +static void +f_38(uint16_t *code, char *buf, size_t bufsiz) +{ + int rn, rm, md; + + rn = (*code & 0x0f00) >> 8; + rm = (*code & 0x00f0) >> 4; + md = (*code & 0x0003); + + switch (md) { + case 0: + snprintf(buf, bufsiz, "sub r%d, r%d", rm, rn); + break; + + case 2: + snprintf(buf, bufsiz, "subc r%d, r%d", rm, rn); + break; + + case 3: + snprintf(buf, bufsiz, "subv r%d, r%d", rm, rn); + break; + } /* end of switch (md) */ +} + + +static void +f_3c(uint16_t *code, char *buf, size_t bufsiz) +{ + int rn, rm, md; + + rn = (*code & 0x0f00) >> 8; + rm = (*code & 0x00f0) >> 4; + md = (*code & 0x0003); + + switch (md) { + case 0: + snprintf(buf, bufsiz, "add r%d, r%d", rm, rn); + break; + + case 1: + snprintf(buf, bufsiz, "dmulu.l r%d, r%d", rm, rn); + break; + + case 2: + snprintf(buf, bufsiz, "addc r%d, r%d", rm, rn); + break; + + case 3: + snprintf(buf, bufsiz, "addv r%d, r%d", rm, rn); + break; + } /* end of switch (md) */ +} + + +static void +f_40(uint16_t *code, char *buf, size_t bufsiz) +{ + int rn, fx; + + rn = (*code & 0x0f00) >> 8; + fx = (*code & 0x00f0) >> 4; + + switch (fx) { + case 0: + snprintf(buf, bufsiz, "shll r%d", rn); + break; + + case 1: + snprintf(buf, bufsiz, "dt r%d", rn); + break; + + case 2: + snprintf(buf, bufsiz, "shal r%d", rn); + break; + } /* end of switch (fx) */ +} + +static void +f_41(uint16_t *code, char *buf, size_t bufsiz) +{ + int rn, fx; + + rn = (*code & 0x0f00) >> 8; + fx = (*code & 0x00f0) >> 4; + + switch (fx) { + case 0: + snprintf(buf, bufsiz, "shlr r%d", rn); + break; + + case 1: + snprintf(buf, bufsiz, "cmp/pz r%d", rn); + break; + + case 2: + snprintf(buf, bufsiz, "shar r%d", rn); + break; + } /* end of switch (fx) */ +} + + +static void +f_42(uint16_t *code, char *buf, size_t bufsiz) +{ + int rn, type, md; + + rn = (*code & 0x0f00) >> 8; + type = (*code & 0x00c0) >> 6; + md = (*code & 0x0030) >> 4; + + switch (type) { + case 0: + switch (md) { + case 0: + snprintf(buf, bufsiz, "sts.l mach, @-r%d", rn); + break; + + case 1: + snprintf(buf, bufsiz, "sts.l macl, @-r%d", rn); + break; + + case 2: + snprintf(buf, bufsiz, "sts.l pr, @-r%d", rn); + break; + } + break; + + case 1: + switch (md) { + case 1: + snprintf(buf, bufsiz, "sts.l fpul, @-r%d", rn); + break; + + case 2: + snprintf(buf, bufsiz, "sts.l fpscr, @-r%d", rn); + break; + } + break; + } /* end of switch (type) */ +} + +static void +f_43(uint16_t *code, char *buf, size_t bufsiz) +{ + int rn, type, md; + + rn = (*code & 0x0f00) >> 8; + type = (*code & 0x00c0) >> 6; + md = (*code & 0x0030) >> 4; + + switch (type) { + case 0: + switch (md) { + case 0: + snprintf(buf, bufsiz, "stc.l sr, @-r%d", rn); + break; + + case 1: + snprintf(buf, bufsiz, "stc.l gbr, @-r%d", rn); + break; + + case 2: + snprintf(buf, bufsiz, "stc.l vbr, @-r%d", rn); + break; + + case 3: + snprintf(buf, bufsiz, "stc.l ssr, @-r%d", rn); + break; + } + break; + + case 1: + switch (md) { + case 0: + snprintf(buf, bufsiz, "stc.l spc, @-r%d", rn); + break; + } + break; + + case 2: + snprintf(buf, bufsiz, "stc.l r%d_bank, @-r%d", md, rn); + break; + + case 3: + snprintf(buf, bufsiz, "stc.l r%d_bank, @-r%d", md+4, rn); + break; + } /* end of switch (type) */ +} + +static void +f_44(uint16_t *code, char *buf, size_t bufsiz) +{ + int rn, fx; + + rn = (*code & 0x0f00) >> 8; + fx = (*code & 0x00f0) >> 4; + + switch (fx) { + case 0: + snprintf(buf, bufsiz, "rotl r%d", rn); + break; + + case 2: + snprintf(buf, bufsiz, "rotcl r%d", rn); + break; + } /* end of switch (fx) */ +} + +static void +f_45(uint16_t *code, char *buf, size_t bufsiz) +{ + int rn, fx; + + rn = (*code & 0x0f00) >> 8; + fx = (*code & 0x00f0) >> 4; + + switch (fx) { + case 0: + snprintf(buf, bufsiz, "rotr r%d", rn); + break; + + case 1: + snprintf(buf, bufsiz, "cmp/pl r%d", rn); + break; + + case 2: + snprintf(buf, bufsiz, "rotcr r%d", rn); + break; + } /* end of switch (fx) */ +} + +static void +f_46(uint16_t *code, char *buf, size_t bufsiz) +{ + int rm, type, md; + + rm = (*code & 0x0f00) >> 8; + type = (*code & 0x00c0) >> 6; + md = (*code & 0x0030) >> 4; + + switch (type) { + case 0: + switch (md) { + case 0: + snprintf(buf, bufsiz, "lds.l @r%d+, mach", rm); + break; + + case 1: + snprintf(buf, bufsiz, "lds.l @r%d+, macl", rm); + break; + + case 2: + snprintf(buf, bufsiz, "lds.l @r%d+, pr", rm); + break; + } + break; + + case 1: + switch (md) { + case 1: + snprintf(buf, bufsiz, "lds.l @r%d+, fpul", rm); + break; + + case 2: + snprintf(buf, bufsiz, "lds.l @r%d+, fpscr", rm); + break; + } + break; + } /* end of switch (type) */ +} + +static void +f_47(uint16_t *code, char *buf, size_t bufsiz) +{ + int rm, type, md; + + rm = (*code & 0x0f00) >> 8; + type = (*code & 0x00c0) >> 6; + md = (*code & 0x0030) >> 4; + + switch (type) { + case 0: + switch (md) { + case 0: + snprintf(buf, bufsiz, "ldc.l @r%d+, sr", rm); + break; + + case 1: + snprintf(buf, bufsiz, "ldc.l @r%d+, gbr", rm); + break; + + case 2: + snprintf(buf, bufsiz, "ldc.l @r%d+, vbr", rm); + break; + + case 3: + snprintf(buf, bufsiz, "ldc.l @r%d+, ssr", rm); + break; + } + break; + + case 1: + switch (md) { + case 0: + snprintf(buf, bufsiz, "ldc.l @r%d+, spc", rm); + break; + } + break; + + case 2: + snprintf(buf, bufsiz, "ldc.l @r%d+, r%d_bank", rm, md); + break; + + case 3: + snprintf(buf, bufsiz, "ldc.l @r%d+, r%d_bank", rm, md+4); + break; + } /* end of switch (type) */ +} + +static void +f_48(uint16_t *code, char *buf, size_t bufsiz) +{ + int rn, fx; + + rn = (*code & 0x0f00) >> 8; + fx = (*code & 0x00f0) >> 4; + + switch (fx) { + case 0: + snprintf(buf, bufsiz, "shll2 r%d", rn); + break; + + case 1: + snprintf(buf, bufsiz, "shll8 r%d", rn); + break; + + case 2: + snprintf(buf, bufsiz, "shll16 r%d", rn); + break; + } /* end of switch (fx) */ +} + +static void +f_49(uint16_t *code, char *buf, size_t bufsiz) +{ + int rn, fx; + + rn = (*code & 0x0f00) >> 8; + fx = (*code & 0x00f0) >> 4; + + switch (fx) { + case 0: + snprintf(buf, bufsiz, "shlr2 r%d", rn); + break; + + case 1: + snprintf(buf, bufsiz, "shlr8 r%d", rn); + break; + + case 2: + snprintf(buf, bufsiz, "shlr16 r%d", rn); + break; + } /* end of switch (fx) */ +} + +static void +f_4a(uint16_t *code, char *buf, size_t bufsiz) +{ + int rm, type, md; + + rm = (*code & 0x0f00) >> 8; + type = (*code & 0x00c0) >> 6; + md = (*code & 0x0030) >> 4; + + switch (type) { + case 0: + switch (md) { + case 0: + snprintf(buf, bufsiz, "lds r%d, mach", rm); + break; + + case 1: + snprintf(buf, bufsiz, "lds r%d, macl", rm); + break; + + case 2: + snprintf(buf, bufsiz, "lds r%d, pr", rm); + break; + } + break; + + case 1: + switch (md) { + case 1: + snprintf(buf, bufsiz, "lds r%d, fpul", rm); + break; + + case 2: + snprintf(buf, bufsiz, "lds r%d, fpscr", rm); + break; + } + break; + } /* end of switch (type) */ +} + +static void +f_4b(uint16_t *code, char *buf, size_t bufsiz) +{ + int rm, fx; + + rm = (*code & 0x0f00) >> 8; + fx = (*code & 0x00f0) >> 4; + + switch (fx) { + case 0: + snprintf(buf, bufsiz, "jsr @r%d", rm); + break; + + case 1: + snprintf(buf, bufsiz, "tas.b @r%d", rm); + break; + + case 2: + snprintf(buf, bufsiz, "jmp @r%d", rm); + break; + } /* end of switch (fx) */ +} + +static void +f_4c(uint16_t *code, char *buf, size_t bufsiz) +{ + int rn, rm; + + rn = (*code & 0x0f00) >> 8; + rm = (*code & 0x00f0) >> 4; + snprintf(buf, bufsiz, "shad r%d, r%d", rm, rn); +} + +static void +f_4d(uint16_t *code, char *buf, size_t bufsiz) +{ + int rn, rm; + + rn = (*code & 0x0f00) >> 8; + rm = (*code & 0x00f0) >> 4; + snprintf(buf, bufsiz, "shld r%d, r%d", rm, rn); +} + +static void +f_4e(uint16_t *code, char *buf, size_t bufsiz) +{ + int rm, type, md; + + rm = (*code & 0x0f00) >> 8; + type = (*code & 0x00c0) >> 6; + md = (*code & 0x0030) >> 4; + + switch (type) { + case 0: + switch (md) { + case 0: + snprintf(buf, bufsiz, "ldc r%d, sr", rm); + break; + + case 1: + snprintf(buf, bufsiz, "ldc r%d, gbr", rm); + break; + + case 2: + snprintf(buf, bufsiz, "ldc r%d, vbr", rm); + break; + + case 3: + snprintf(buf, bufsiz, "ldc r%d, ssr", rm); + break; + } + break; + + case 1: + switch (md) { + case 0: + snprintf(buf, bufsiz, "ldc r%d, spc", rm); + break; + } + break; + + case 2: + snprintf(buf, bufsiz, "ldc r%d, r%d_bank", rm, md); + break; + + case 3: + snprintf(buf, bufsiz, "ldc r%d, r%d_bank", rm, md+4); + break; + } /* end of switch (type) */ +} + +static void +f_4f(uint16_t *code, char *buf, size_t bufsiz) +{ + int rn, rm; + + rn = (*code & 0x0f00) >> 8; + rm = (*code & 0x00f0) >> 4; + snprintf(buf, bufsiz, "mac.w @r%d+, @r%d+", rm, rn); +} + +static void +f_50(uint16_t *code, char *buf, size_t bufsiz) +{ + int rn, rm, disp; + + rn = (*code & 0x0f00) >> 8; + rm = (*code & 0x00f0) >> 4; + disp = (*code & 0x000f); + disp *= 4; + + snprintf(buf, bufsiz, "mov.l @(%d, r%d), r%d", disp, rm, rn); +} + +static void +f_60(uint16_t *code, char *buf, size_t bufsiz) +{ + int rn, rm, md; + + rn = (*code & 0x0f00) >> 8; + rm = (*code & 0x00f0) >> 4; + md = (*code & 0x0003); + + switch (md) { + case 0: + snprintf(buf, bufsiz, "mov.b @r%d, r%d", rm, rn); + break; + + case 1: + snprintf(buf, bufsiz, "mov.w @r%d, r%d", rm, rn); + break; + + case 2: + snprintf(buf, bufsiz, "mov.l @r%d, r%d", rm, rn); + break; + + case 3: + snprintf(buf, bufsiz, "mov r%d, r%d", rm, rn); + break; + } /* end of switch (md) */ +} + +static void +f_64(uint16_t *code, char *buf, size_t bufsiz) +{ + int rn, rm, md; + + rn = (*code & 0x0f00) >> 8; + rm = (*code & 0x00f0) >> 4; + md = (*code & 0x0003); + + switch (md) { + case 0: + snprintf(buf, bufsiz, "mov.b @r%d+, r%d", rm, rn); + break; + + case 1: + snprintf(buf, bufsiz, "mov.w @r%d+, r%d", rm, rn); + break; + + case 2: + snprintf(buf, bufsiz, "mov.l @r%d+, r%d", rm, rn); + break; + + case 3: + snprintf(buf, bufsiz, "not r%d, r%d", rm, rn); + break; + } /* end of switch (md) */ +} + +static void +f_68(uint16_t *code, char *buf, size_t bufsiz) +{ + int rn, rm, md; + + rn = (*code & 0x0f00) >> 8; + rm = (*code & 0x00f0) >> 4; + md = (*code & 0x0003); + + switch (md) { + case 0: + snprintf(buf, bufsiz, "swap.b r%d, r%d", rm, rn); + break; + + case 1: + snprintf(buf, bufsiz, "swap.w r%d, r%d", rm, rn); + break; + + case 2: + snprintf(buf, bufsiz, "negc r%d, r%d", rm, rn); + break; + + case 3: + snprintf(buf, bufsiz, "neg r%d, r%d", rm, rn); + break; + } /* end of switch (md) */ +} + +static void +f_6c(uint16_t *code, char *buf, size_t bufsiz) +{ + int rn, rm, md; + + rn = (*code & 0x0f00) >> 8; + rm = (*code & 0x00f0) >> 4; + md = (*code & 0x0003); + + switch (md) { + case 0: + snprintf(buf, bufsiz, "extu.b r%d, r%d", rm, rn); + break; + + case 1: + snprintf(buf, bufsiz, "extu.w r%d, r%d", rm, rn); + break; + + case 2: + snprintf(buf, bufsiz, "exts.b r%d, r%d", rm, rn); + break; + + case 3: + snprintf(buf, bufsiz, "exts.w r%d, r%d", rm, rn); + break; + } /* end of switch (md) */ +} + +static void +f_70(uint16_t *code, char *buf, size_t bufsiz) +{ + int rn, imm; + + rn = (*code & 0x0f00) >> 8; + imm = (int) ((char) (*code & 0x00ff)); + + snprintf(buf, bufsiz, "add #0x%x, r%d", imm, rn); +} + +static void +f_80(uint16_t *code, char *buf, size_t bufsiz) +{ + int type, md, rn, disp; + + type = (*code & 0x0c00) >> 10; + md = (*code & 0x0300) >> 8; + + switch (type) { + case 0: + rn = (*code & 0x00f0) >> 4; + disp = (*code & 0x000f); + + switch (md) { + case 0: + snprintf(buf, bufsiz, "mov.b r0, @(%d, r%d)", + disp, rn); + break; + + case 1: + disp *= 2; + snprintf(buf, bufsiz, "mov.w r0, @(%d, r%d)", + disp, rn); + break; + } + break; + + case 1: + rn = (*code & 0x00f0) >> 4; + disp = (*code & 0x000f); + + switch (md) { + case 0: + snprintf(buf, bufsiz, "mov.b @(%d, r%d), r0", + disp, rn); + break; + + case 1: + disp *= 2; + snprintf(buf, bufsiz, "mov.w @(%d, r%d), r0", + disp, rn); + break; + } + break; + + case 2: + disp = (*code & 0x00ff); + + switch (md) { + case 0: + snprintf(buf, bufsiz, "cmp/eq #%d, r0", disp); + break; + + case 1: + disp = (int) ((char) disp); + disp *= 2; + snprintf(buf, bufsiz, "bt 0x%x", disp); + break; + + case 3: + disp = (int) ((char) disp); + disp *= 2; + snprintf(buf, bufsiz, "bf 0x%x", disp); + break; + } + break; + + case 3: + disp = (int) ((char) (*code & 0x00ff)); + disp *= 2; + + switch (md) { + case 1: + snprintf(buf, bufsiz, "bt/s 0x%x", disp); + break; + + case 3: + snprintf(buf, bufsiz, "bf/s 0x%x", disp); + break; + } + break; + } /* end of switch (type) */ +} + +static void +f_90(uint16_t *code, char *buf, size_t bufsiz) +{ + int rn, disp; + + rn = (*code & 0x0f00) >> 8; + disp = (*code & 0x00ff); + disp *= 2; + + snprintf(buf, bufsiz, "mov.w @(%d, pc), r%d", disp, rn); +} + +static void +f_a0(uint16_t *code, char *buf, size_t bufsiz) +{ + int disp; + + disp = (*code & 0x0fff); + if (disp & 0x0800) /* negative displacement? */ + disp |= 0xfffff000; /* sign extend */ + disp *= 2; + + snprintf(buf, bufsiz, "bra %d(0x%x)", disp, disp); +} + +static void +f_b0(uint16_t *code, char *buf, size_t bufsiz) +{ + int disp; + + disp = (*code & 0x0fff); + if (disp & 0x0800) /* negative displacement? */ + disp |= 0xfffff000; /* sign extend */ + disp *= 2; + + snprintf(buf, bufsiz, "bsr %d(0x%x)", disp, disp); +} + +static void +f_c0(uint16_t *code, char *buf, size_t bufsiz) +{ + int type, md, imm; + + type = (*code & 0x0c00) >> 10; + md = (*code & 0x0300) >> 8; + imm = (*code & 0x00ff); + + switch (type) { + case 0: + switch (md) { + case 0: + snprintf(buf, bufsiz, "mov.b r0, @(%d, gbr)", imm); + break; + + case 1: + imm *= 2; + snprintf(buf, bufsiz, "mov.w r0, @(%d, gbr)", imm); + break; + + case 2: + imm *= 4; + snprintf(buf, bufsiz, "mov.l r0, @(%d, gbr)", imm); + break; + + case 3: + snprintf(buf, bufsiz, "trapa #%d", imm); + break; + } + break; + + case 1: + switch (md) { + case 0: + snprintf(buf, bufsiz, "mov.b @(%d, gbr), r0", imm); + break; + + case 1: + imm *= 2; + snprintf(buf, bufsiz, "mov.w @(%d, gbr), r0", imm); + break; + + case 2: + imm *= 4; + snprintf(buf, bufsiz, "mov.l @(%d, gbr), r0", imm); + break; + + case 3: + imm *= 4; + snprintf(buf, bufsiz, "mova @(%d, pc), r0", imm); + break; + } + break; + + case 2: + switch (md) { + case 0: + snprintf(buf, bufsiz, "tst #%d, r0", imm); + break; + + case 1: + snprintf(buf, bufsiz, "and #%d, r0", imm); + break; + + case 2: + snprintf(buf, bufsiz, "xor #%d, r0", imm); + break; + + case 3: + snprintf(buf, bufsiz, "or #%d, r0", imm); + break; + } + break; + + case 3: + switch (md) { + case 0: + snprintf(buf, bufsiz, "tst.b #%d, @(r0, gbr)", imm); + break; + + case 1: + snprintf(buf, bufsiz, "and.b #%d, @(r0, gbr)", imm); + break; + + case 2: + snprintf(buf, bufsiz, "xor.b #%d, @(r0, gbr)", imm); + break; + + case 3: + snprintf(buf, bufsiz, "or.b #%d, @(r0, gbr)", imm); + break; + } + break; + } /* end of switch (type) */ +} + + +static void +f_d0(uint16_t *code, char *buf, size_t bufsiz) +{ + int rn, disp; + + rn = (*code & 0x0f00) >> 8; + disp = (*code & 0x00ff); + disp *= 4; + + snprintf(buf, bufsiz, "mov.l @(%d, pc), r%d", disp, rn); +} + +static void +f_e0(uint16_t *code, char *buf, size_t bufsiz) +{ + int rn, imm; + + rn = (*code & 0x0f00) >> 8; + imm = (int) ((char) (*code & 0x00ff)); + + snprintf(buf, bufsiz, "mov #0x%x, r%d", imm, rn); +} + +static void +f_f0(uint16_t *code, char *buf, size_t bufsiz) +{ + int rn, rm, md; + + rn = (*code & 0x0f00) >> 8; + rm = (*code & 0x00f0) >> 4; + md = (*code & 0x0003); + + switch (md) { + case 0: + snprintf(buf, bufsiz, "fadd fr%d, fr%d", rm, rn); + break; + + case 1: + snprintf(buf, bufsiz, "fsub fr%d, fr%d", rm, rn); + break; + + case 2: + snprintf(buf, bufsiz, "fmul fr%d, fr%d", rm, rn); + break; + + case 3: + snprintf(buf, bufsiz, "fdiv fr%d, fr%d", rm, rn); + break; + } /* end of switch (md) */ +} + +static void +f_f4(uint16_t *code, char *buf, size_t bufsiz) +{ + int rn, rm, md; + + rn = (*code & 0x0f00) >> 8; + rm = (*code & 0x00f0) >> 4; + md = (*code & 0x0003); + + switch (md) { + case 0: + snprintf(buf, bufsiz, "fcmp/eq fr%d, fr%d", rm, rn); + break; + + case 1: + snprintf(buf, bufsiz, "fcmp/gt fr%d, fr%d", rm, rn); + break; + + case 2: + snprintf(buf, bufsiz, "fmov.s @(r0, r%d), fr%d", rm, rn); + break; + + case 3: + snprintf(buf, bufsiz, "fmov.s fr%d, @(r0, r%d)", rm, rn); + break; + } /* end of switch (md) */ +} + +static void +f_f8(uint16_t *code, char *buf, size_t bufsiz) +{ + int rn, rm, md; + + rn = (*code & 0x0f00) >> 8; + rm = (*code & 0x00f0) >> 4; + md = (*code & 0x0003); + + switch (md) { + case 0: + snprintf(buf, bufsiz, "fmov.s @r%d, fr%d", rm, rn); + break; + + case 1: + snprintf(buf, bufsiz, "fmov.s @r%d+, fr%d", rm, rn); + break; + + case 2: + snprintf(buf, bufsiz, "fmov.s fr%d, @r%d", rm, rn); + break; + + case 3: + snprintf(buf, bufsiz, "fmov.s fr%d, @-r%d", rm, rn); + break; + } /* end of switch (md) */ +} + +static void +f_fc(uint16_t *code, char *buf, size_t bufsiz) +{ + int rn, rm; + + rn = (*code & 0x0f00) >> 8; + rm = (*code & 0x00f0) >> 4; + + snprintf(buf, bufsiz, "fmov fr%d, fr%d", rm, rn); +} + +static void +f_fd(uint16_t *code, char *buf, size_t bufsiz) +{ + int rn, type, md; + + rn = (*code & 0x0f00) >> 8; + type = (*code & 0x00c0) >> 6; + md = (*code & 0x0030) >> 4; + + switch (type) { + case 0: + switch (md) { + case 0: + snprintf(buf, bufsiz, "fsts fpul, fr%d", rn); + break; + + case 1: + snprintf(buf, bufsiz, "flds fr%d, fpul", rn); + break; + + case 2: + snprintf(buf, bufsiz, "float fpul, fr%d", rn); + break; + + case 3: + snprintf(buf, bufsiz, "ftrc fr%d, fpul", rn); + break; + } + break; + + case 1: + switch (md) { + case 0: + snprintf(buf, bufsiz, "fneg fr%d", rn); + break; + + case 1: + snprintf(buf, bufsiz, "fabs fr%d", rn); + break; + + case 2: + snprintf(buf, bufsiz, "fsqrt fr%d", rn); + break; + } + break; + + case 2: + switch (md) { + case 0: + case 1: + snprintf(buf, bufsiz, "fldi%d fr%d", md, rn); + break; + } + break; + } /* end of switch (type) */ +} + +static void +f_fe(uint16_t *code, char *buf, size_t bufsiz) +{ + int rn, rm; + + rn = (*code & 0x0f00) >> 8; + rm = (*code & 0x00f0) >> 4; + + snprintf(buf, bufsiz, "fmac fr0, fr%d, fr%d", rm, rn); +} diff --git a/sys/arch/sh/sh/db_interface.c b/sys/arch/sh/sh/db_interface.c new file mode 100644 index 00000000000..2fc8f75241d --- /dev/null +++ b/sys/arch/sh/sh/db_interface.c @@ -0,0 +1,641 @@ +/* $OpenBSD: db_interface.c,v 1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: db_interface.c,v 1.37 2006/09/06 00:11:49 uwe Exp $ */ + +/*- + * Copyright (C) 2002 UCHIYAMA Yasushi. All rights reserved. + * Copyright (c) 2000 Tsubai Masanari. 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. 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. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/user.h> + +#include <uvm/uvm_extern.h> + +#include <dev/cons.h> + +#include <machine/db_machdep.h> +#include <ddb/db_run.h> +#include <ddb/db_sym.h> + +#include <sh/ubcreg.h> + +db_regs_t ddb_regs; /* register state */ + + +#include <sh/cache.h> +#include <sh/cache_sh3.h> +#include <sh/cache_sh4.h> +#include <sh/mmu.h> +#include <sh/mmu_sh3.h> +#include <sh/mmu_sh4.h> + +#include <ddb/db_command.h> +#include <ddb/db_extern.h> +#include <ddb/db_output.h> +#include <ddb/db_run.h> +#include <ddb/db_var.h> + +void kdb_printtrap(u_int, int); + +void db_tlbdump_cmd(db_expr_t, int, db_expr_t, char *); +void __db_tlbdump_page_size_sh4(uint32_t); +void __db_tlbdump_pfn(uint32_t); +void db_cachedump_cmd(db_expr_t, int, db_expr_t, char *); + +void __db_cachedump_sh3(vaddr_t); +void __db_cachedump_sh4(vaddr_t); + +void db_stackcheck_cmd(db_expr_t, int, db_expr_t, char *); +void db_frame_cmd(db_expr_t, int, db_expr_t, char *); +void __db_print_symbol(db_expr_t); +char *__db_procname_by_asid(int); + +const struct db_command db_machine_command_table[] = { + { "tlb", db_tlbdump_cmd, 0, NULL }, + { "cache", db_cachedump_cmd, 0, NULL }, + { "frame", db_frame_cmd, 0, NULL }, +#ifdef KSTACK_DEBUG + { "stack", db_stackcheck_cmd, 0, NULL }, +#endif + { NULL } +}; + +int db_active; + +void +kdb_printtrap(u_int type, int code) +{ + int i; + i = type >> 5; + + db_printf("%s mode trap: ", type & 1 ? "user" : "kernel"); + if (i >= exp_types) + db_printf("type 0x%03x", type & ~1); + else + db_printf("%s", exp_type[i]); + + db_printf(" code = 0x%x\n", code); +} + +int +kdb_trap(int type, int code, db_regs_t *regs) +{ + extern label_t *db_recover; + int s; + + switch (type) { + case EXPEVT_TRAPA: /* trapa instruction */ + case EXPEVT_BREAK: /* UBC */ + case -1: /* keyboard interrupt */ + break; + default: + if (!db_panic && db_recover == NULL) + return 0; + + kdb_printtrap(type, code); + if (db_recover != NULL) { + db_error("Faulted in DDB; continuing...\n"); + /*NOTREACHED*/ + } + } + + /* XXX Should switch to kdb's own stack here. */ + + ddb_regs = *regs; + + s = splhigh(); + db_active++; + cnpollc(TRUE); + db_trap(type, code); + cnpollc(FALSE); + db_active--; + splx(s); + + *regs = ddb_regs; + + return 1; +} + +#if 0 +void +Debugger() +{ + + __asm volatile("trapa %0" :: "i"(_SH_TRA_BREAK)); +} +#endif + +#define M_BSR 0xf000 +#define I_BSR 0xb000 +#define M_BSRF 0xf0ff +#define I_BSRF 0x0003 +#define M_JSR 0xf0ff +#define I_JSR 0x400b +#define M_RTS 0xffff +#define I_RTS 0x000b +#define M_RTE 0xffff +#define I_RTE 0x002b + +boolean_t +inst_call(int inst) +{ +#if _BYTE_ORDER == BIG_ENDIAN + inst >>= 16; +#endif + return (inst & M_BSR) == I_BSR || (inst & M_BSRF) == I_BSRF || + (inst & M_JSR) == I_JSR; +} + +boolean_t +inst_return(int inst) +{ +#if _BYTE_ORDER == BIG_ENDIAN + inst >>= 16; +#endif + return (inst & M_RTS) == I_RTS; +} + +boolean_t +inst_trap_return(int inst) +{ +#if _BYTE_ORDER == BIG_ENDIAN + inst >>= 16; +#endif + return (inst & M_RTE) == I_RTE; +} + +void +db_set_single_step(db_regs_t *regs) +{ + + _reg_write_2(SH_(BBRA), 0); /* disable break */ + _reg_write_4(SH_(BARA), 0); /* break address */ + _reg_write_1(SH_(BASRA), 0); /* break ASID */ + _reg_write_1(SH_(BAMRA), 0x07); /* break always */ + _reg_write_2(SH_(BRCR), 0x400); /* break after each execution */ + + regs->tf_ubc = 0x0014; /* will be written to BBRA */ +} + +void +db_clear_single_step(db_regs_t *regs) +{ + + regs->tf_ubc = 0; +} + +#define ON(x, c) ((x) & (c) ? '|' : '.') + +/* + * MMU + */ +void +db_tlbdump_cmd(db_expr_t addr, int have_addr, db_expr_t count, + char *modif) +{ + static const char *pr[] = { "_r", "_w", "rr", "ww" }; + static const char title[] = + " VPN ASID PFN AREA VDCGWtPR SZ"; + static const char title2[] = + " U/K U/K"; + uint32_t r, e; + int i; +#ifdef SH3 + if (CPU_IS_SH3) { + /* MMU configuration. */ + r = _reg_read_4(SH3_MMUCR); + db_printf("%s-mode, %s virtual storage mode\n", + r & SH3_MMUCR_IX + ? "ASID + VPN" : "VPN only", + r & SH3_MMUCR_SV ? "single" : "multiple"); + i = _reg_read_4(SH3_PTEH) & SH3_PTEH_ASID_MASK; + db_printf("ASID=%d (%s)", i, __db_procname_by_asid(i)); + + db_printf("---TLB DUMP---\n%s\n%s\n", title, title2); + for (i = 0; i < SH3_MMU_WAY; i++) { + db_printf(" [way %d]\n", i); + for (e = 0; e < SH3_MMU_ENTRY; e++) { + uint32_t a; + /* address/data array common offset. */ + a = (e << SH3_MMU_VPN_SHIFT) | + (i << SH3_MMU_WAY_SHIFT); + + r = _reg_read_4(SH3_MMUAA | a); + if (r == 0) { + db_printf("---------- - --- ----------" + " - ----x -- --\n"); + } else { + vaddr_t va; + int asid; + asid = r & SH3_MMUAA_D_ASID_MASK; + r &= SH3_MMUAA_D_VPN_MASK_1K; + va = r | (e << SH3_MMU_VPN_SHIFT); + db_printf("0x%08lx %c %3d", va, + (int)va < 0 ? 'K' : 'U', asid); + + r = _reg_read_4(SH3_MMUDA | a); + __db_tlbdump_pfn(r); + + db_printf(" %c%c%c%cx %s %2dK\n", + ON(r, SH3_MMUDA_D_V), + ON(r, SH3_MMUDA_D_D), + ON(r, SH3_MMUDA_D_C), + ON(r, SH3_MMUDA_D_SH), + pr[(r & SH3_MMUDA_D_PR_MASK) >> + SH3_MMUDA_D_PR_SHIFT], + r & SH3_MMUDA_D_SZ ? 4 : 1); + } + } + } + } +#endif /* SH3 */ +#ifdef SH4 + if (CPU_IS_SH4) { + /* MMU configuration */ + r = _reg_read_4(SH4_MMUCR); + db_printf("%s virtual storage mode, SQ access: (kernel%s)\n", + r & SH3_MMUCR_SV ? "single" : "multiple", + r & SH4_MMUCR_SQMD ? "" : "/user"); + db_printf("random counter limit=%d\n", + (r & SH4_MMUCR_URB_MASK) >> SH4_MMUCR_URB_SHIFT); + + i = _reg_read_4(SH4_PTEH) & SH4_PTEH_ASID_MASK; + db_printf("ASID=%d (%s)", i, __db_procname_by_asid(i)); + + /* Dump ITLB */ + db_printf("---ITLB DUMP ---\n%s TC SA\n%s\n", title, title2); + for (i = 0; i < 4; i++) { + e = i << SH4_ITLB_E_SHIFT; + + r = _reg_read_4(SH4_ITLB_AA | e); + db_printf("0x%08x %3d", + r & SH4_ITLB_AA_VPN_MASK, + r & SH4_ITLB_AA_ASID_MASK); + + r = _reg_read_4(SH4_ITLB_DA1 | e); + __db_tlbdump_pfn(r); + db_printf(" %c_%c%c_ %s ", + ON(r, SH4_ITLB_DA1_V), + ON(r, SH4_ITLB_DA1_C), + ON(r, SH4_ITLB_DA1_SH), + pr[(r & SH4_ITLB_DA1_PR) >> + SH4_UTLB_DA1_PR_SHIFT]); + __db_tlbdump_page_size_sh4(r); + +#if 0 /* XXX: causes weird effects on landisk */ + r = _reg_read_4(SH4_ITLB_DA2 | e); + db_printf(" %c %d\n", + ON(r, SH4_ITLB_DA2_TC), + r & SH4_ITLB_DA2_SA_MASK); +#else + db_printf("\n"); +#endif + } + + /* Dump UTLB */ + db_printf("---UTLB DUMP---\n%s TC SA\n%s\n", title, title2); + for (i = 0; i < 64; i++) { + e = i << SH4_UTLB_E_SHIFT; + + r = _reg_read_4(SH4_UTLB_AA | e); + db_printf("0x%08x %3d", + r & SH4_UTLB_AA_VPN_MASK, + r & SH4_UTLB_AA_ASID_MASK); + + r = _reg_read_4(SH4_UTLB_DA1 | e); + __db_tlbdump_pfn(r); + db_printf(" %c%c%c%c%c %s ", + ON(r, SH4_UTLB_DA1_V), + ON(r, SH4_UTLB_DA1_D), + ON(r, SH4_UTLB_DA1_C), + ON(r, SH4_UTLB_DA1_SH), + ON(r, SH4_UTLB_DA1_WT), + pr[(r & SH4_UTLB_DA1_PR_MASK) >> + SH4_UTLB_DA1_PR_SHIFT] + ); + __db_tlbdump_page_size_sh4(r); + +#if 0 /* XXX: causes weird effects on landisk */ + r = _reg_read_4(SH4_UTLB_DA2 | e); + db_printf(" %c %d\n", + ON(r, SH4_UTLB_DA2_TC), + r & SH4_UTLB_DA2_SA_MASK); +#else + db_printf("\n"); +#endif + } + } +#endif /* SH4 */ +} + +void +__db_tlbdump_pfn(uint32_t r) +{ + uint32_t pa = (r & SH3_MMUDA_D_PPN_MASK); + + db_printf(" 0x%08x %d", pa, (pa >> 26) & 7); +} + +char * +__db_procname_by_asid(int asid) +{ + static char notfound[] = "---"; + struct proc *p; + + LIST_FOREACH(p, &allproc, p_list) { + if (p->p_vmspace->vm_map.pmap->pm_asid == asid) + return (p->p_comm); + } + + return (notfound); +} + +#ifdef SH4 +void +__db_tlbdump_page_size_sh4(uint32_t r) +{ + switch (r & SH4_PTEL_SZ_MASK) { + case SH4_PTEL_SZ_1K: + db_printf(" 1K"); + break; + case SH4_PTEL_SZ_4K: + db_printf(" 4K"); + break; + case SH4_PTEL_SZ_64K: + db_printf("64K"); + break; + case SH4_PTEL_SZ_1M: + db_printf(" 1M"); + break; + } +} +#endif /* SH4 */ + +/* + * CACHE + */ +void +db_cachedump_cmd(db_expr_t addr, int have_addr, db_expr_t count, + char *modif) +{ +#ifdef SH3 + if (CPU_IS_SH3) + __db_cachedump_sh3(have_addr ? addr : 0); +#endif +#ifdef SH4 + if (CPU_IS_SH4) + __db_cachedump_sh4(have_addr ? addr : 0); +#endif +} + +#ifdef SH3 +void +__db_cachedump_sh3(vaddr_t va_start) +{ + uint32_t r; + vaddr_t va, va_end, cca; + int entry, way; + + RUN_P2; + /* disable cache */ + _reg_write_4(SH3_CCR, + _reg_read_4(SH3_CCR) & ~SH3_CCR_CE); + + if (va_start) { + va = va_start & ~(sh_cache_line_size - 1); + va_end = va + sh_cache_line_size; + } else { + va = 0; + va_end = sh_cache_way_size; + } + + db_printf("%d-way, way-size=%dB, way-shift=%d, entry-mask=%08x, " + "line-size=%dB \n", sh_cache_ways, sh_cache_way_size, + sh_cache_way_shift, sh_cache_entry_mask, sh_cache_line_size); + db_printf("Entry Way 0 UV Way 1 UV Way 2 UV Way 3 UV\n"); + for (; va < va_end; va += sh_cache_line_size) { + entry = va & sh_cache_entry_mask; + cca = SH3_CCA | entry; + db_printf(" %3d ", entry >> CCA_ENTRY_SHIFT); + for (way = 0; way < sh_cache_ways; way++) { + r = _reg_read_4(cca | (way << sh_cache_way_shift)); + db_printf("%08x %c%c ", r & CCA_TAGADDR_MASK, + ON(r, CCA_U), ON(r, CCA_V)); + } + db_printf("\n"); + } + + /* enable cache */ + _reg_bset_4(SH3_CCR, SH3_CCR_CE); + sh_icache_sync_all(); + + RUN_P1; +} +#endif /* SH3 */ + +#ifdef SH4 +void +__db_cachedump_sh4(vaddr_t va) +{ + uint32_t r, e; + int i, istart, iend; + + RUN_P2; /* must access from P2 */ + + /* disable I/D-cache */ + _reg_write_4(SH4_CCR, + _reg_read_4(SH4_CCR) & ~(SH4_CCR_ICE | SH4_CCR_OCE)); + + if (va) { + istart = ((va & CCIA_ENTRY_MASK) >> CCIA_ENTRY_SHIFT) & ~3; + iend = istart + 4; + } else { + istart = 0; + iend = SH4_ICACHE_SIZE / SH4_CACHE_LINESZ; + } + + db_printf("[I-cache]\n"); + db_printf(" Entry V V V V\n"); + for (i = istart; i < iend; i++) { + if ((i & 3) == 0) + db_printf("\n[%3d-%3d] ", i, i + 3); + r = _reg_read_4(SH4_CCIA | (i << CCIA_ENTRY_SHIFT)); + db_printf("%08x _%c ", r & CCIA_TAGADDR_MASK, ON(r, CCIA_V)); + } + + db_printf("\n[D-cache]\n"); + db_printf(" Entry UV UV UV UV\n"); + for (i = istart; i < iend; i++) { + if ((i & 3) == 0) + db_printf("\n[%3d-%3d] ", i, i + 3); + e = (i << CCDA_ENTRY_SHIFT); + r = _reg_read_4(SH4_CCDA | e); + db_printf("%08x %c%c ", r & CCDA_TAGADDR_MASK, ON(r, CCDA_U), + ON(r, CCDA_V)); + + } + db_printf("\n"); + + _reg_write_4(SH4_CCR, + _reg_read_4(SH4_CCR) | SH4_CCR_ICE | SH4_CCR_OCE); + sh_icache_sync_all(); + + RUN_P1; +} +#endif /* SH4 */ + +#undef ON + +void +db_frame_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif) +{ + struct switchframe *sf = &curpcb->pcb_sf; + struct trapframe *tf, *tftop; + + /* Print switch frame */ + db_printf("[switch frame]\n"); + +#define SF(x) db_printf("sf_" #x "\t\t0x%08x\t", sf->sf_ ## x); \ + __db_print_symbol(sf->sf_ ## x) + + SF(sr); + SF(r15); + SF(r14); + SF(r13); + SF(r12); + SF(r11); + SF(r10); + SF(r9); + SF(r8); + SF(pr); + db_printf("sf_r6_bank\t0x%08x\n", sf->sf_r6_bank); + db_printf("sf_r7_bank\t0x%08x\n", sf->sf_r7_bank); + + + /* Print trap frame stack */ + db_printf("[trap frame]\n"); + + __asm("stc r6_bank, %0" : "=r"(tf)); + tftop = (struct trapframe *)((vaddr_t)curpcb + PAGE_SIZE); + + for (; tf != tftop; tf++) { + db_printf("-- %p-%p --\n", tf, tf + 1); + db_printf("tf_expevt\t0x%08x\n", tf->tf_expevt); + +#define TF(x) db_printf("tf_" #x "\t\t0x%08x\t", tf->tf_ ## x); \ + __db_print_symbol(tf->tf_ ## x) + + TF(ubc); + TF(spc); + TF(ssr); + TF(macl); + TF(mach); + TF(pr); + TF(r13); + TF(r12); + TF(r11); + TF(r10); + TF(r9); + TF(r8); + TF(r7); + TF(r6); + TF(r5); + TF(r4); + TF(r3); + TF(r2); + TF(r1); + TF(r0); + TF(r15); + TF(r14); + } +#undef SF +#undef TF +} + +void +__db_print_symbol(db_expr_t value) +{ + char *name; + db_expr_t offset; + + db_find_sym_and_offset((db_addr_t)value, &name, &offset); + if (name != NULL && offset <= db_maxoff && offset != value) + db_printsym(value, DB_STGY_ANY, db_printf); + + db_printf("\n"); +} + +#ifdef KSTACK_DEBUG +/* + * Stack overflow check + */ +void +db_stackcheck_cmd(db_expr_t addr, int have_addr, db_expr_t count, + char *modif) +{ + struct proc *p; + struct user *u; + struct pcb *pcb; + uint32_t *t32; + uint8_t *t8; + int i, j; + +#define MAX_STACK (USPACE - PAGE_SIZE) +#define MAX_FRAME (PAGE_SIZE - sizeof(struct user)) + + db_printf("stack max: %d byte, frame max %d byte," + " sizeof(struct trapframe) %d byte\n", MAX_STACK, MAX_FRAME, + sizeof(struct trapframe)); + db_printf(" PID.LID " + "stack top max used frame top max used" + " nest\n"); + + LIST_FOREACH(p, &allproc, p_list) { + u = p->p_addr; + pcb = &u->u_pcb; + /* stack */ + t32 = (uint32_t *)(pcb->pcb_sf.sf_r7_bank - MAX_STACK); + for (i = 0; *t32++ == 0xa5a5a5a5; i++) + continue; + i = MAX_STACK - i * sizeof(int); + + /* frame */ + t8 = (uint8_t *)((vaddr_t)pcb + PAGE_SIZE - MAX_FRAME); + for (j = 0; *t8++ == 0x5a; j++) + continue; + j = MAX_FRAME - j; + + db_printf("%6d 0x%08x %6d (%3d%%) 0x%08lx %6d (%3d%%) %d %s\n", + p->p_lid, + pcb->pcb_sf.sf_r7_bank, i, i * 100 / MAX_STACK, + (vaddr_t)pcb + PAGE_SIZE, j, j * 100 / MAX_FRAME, + j / sizeof(struct trapframe), + p->p_comm); + } +#undef MAX_STACK +#undef MAX_FRAME +} +#endif /* KSTACK_DEBUG */ diff --git a/sys/arch/sh/sh/db_memrw.c b/sys/arch/sh/sh/db_memrw.c new file mode 100644 index 00000000000..978c8c37005 --- /dev/null +++ b/sys/arch/sh/sh/db_memrw.c @@ -0,0 +1,94 @@ +/* $OpenBSD: db_memrw.c,v 1.1.1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: db_memrw.c,v 1.8 2006/02/24 00:57:19 uwe Exp $ */ + +/* + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + * + * db_interface.c,v 2.4 1991/02/05 17:11:13 mrt (CMU) + */ + +/* + * Routines to read and write memory on behalf of the debugger, used + * by DDB. + */ + +#include <sys/param.h> +#include <sys/proc.h> +#include <sys/systm.h> +#include <sys/stdint.h> + +#include <uvm/uvm_extern.h> + +#include <machine/db_machdep.h> + +#include <ddb/db_access.h> + +/* + * Read bytes from kernel address space for debugger. + */ +void +db_read_bytes(vaddr_t addr, size_t size, char *data) +{ + char *src = (char *)addr; + + /* properly aligned 4-byte */ + if (size == 4 && ((addr & 3) == 0) && (((uintptr_t)data & 3) == 0)) { + *(uint32_t *)data = *(uint32_t *)src; + return; + } + + /* properly aligned 2-byte */ + if (size == 2 && ((addr & 1) == 0) && (((uintptr_t)data & 1) == 0)) { + *(uint16_t *)data = *(uint16_t *)src; + return; + } + + while (size-- > 0) + *data++ = *src++; +} + +/* + * Write bytes to kernel address space for debugger. + */ +void +db_write_bytes(vaddr_t addr, size_t size, char *data) +{ + char *dst = (char *)addr; + + /* properly aligned 4-byte */ + if (size == 4 && ((addr & 3) == 0) && (((uintptr_t)data & 3) == 0)) { + *(uint32_t *)dst = *(const uint32_t *)data; + return; + } + + /* properly aligned 2-byte */ + if (size == 2 && ((addr & 1) == 0) && (((uintptr_t)data & 1) == 0)) { + *(uint16_t *)dst = *(const uint16_t *)data; + return; + } + + while (size-- > 0) + *dst++ = *data++; +} diff --git a/sys/arch/sh/sh/db_trace.c b/sys/arch/sh/sh/db_trace.c new file mode 100644 index 00000000000..8228c26bf46 --- /dev/null +++ b/sys/arch/sh/sh/db_trace.c @@ -0,0 +1,225 @@ +/* $OpenBSD: db_trace.c,v 1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: db_trace.c,v 1.19 2006/01/21 22:10:59 uwe Exp $ */ + +/*- + * Copyright (c) 2000 Tsubai Masanari. 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. 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. + */ + +#include <sys/param.h> +#include <sys/systm.h> + +#include <machine/db_machdep.h> + +#include <ddb/db_access.h> +#include <ddb/db_interface.h> +#include <ddb/db_output.h> +#include <ddb/db_sym.h> +#include <ddb/db_variables.h> + +#ifdef TRACE_DEBUG +# define DPRINTF printf +#else +# define DPRINTF while (/* CONSTCOND */ 0) printf +#endif + +extern char start[], etext[]; +void db_nextframe(db_addr_t, db_addr_t *, db_addr_t *); + +struct db_variable db_regs[] = { + { "r0", (long *)&ddb_regs.tf_r0, FCN_NULL }, + { "r1", (long *)&ddb_regs.tf_r1, FCN_NULL }, + { "r2", (long *)&ddb_regs.tf_r2, FCN_NULL }, + { "r3", (long *)&ddb_regs.tf_r3, FCN_NULL }, + { "r4", (long *)&ddb_regs.tf_r4, FCN_NULL }, + { "r5", (long *)&ddb_regs.tf_r5, FCN_NULL }, + { "r6", (long *)&ddb_regs.tf_r6, FCN_NULL }, + { "r7", (long *)&ddb_regs.tf_r7, FCN_NULL }, + { "r8", (long *)&ddb_regs.tf_r8, FCN_NULL }, + { "r9", (long *)&ddb_regs.tf_r9, FCN_NULL }, + { "r10", (long *)&ddb_regs.tf_r10, FCN_NULL }, + { "r11", (long *)&ddb_regs.tf_r11, FCN_NULL }, + { "r12", (long *)&ddb_regs.tf_r12, FCN_NULL }, + { "r13", (long *)&ddb_regs.tf_r13, FCN_NULL }, + { "r14", (long *)&ddb_regs.tf_r14, FCN_NULL }, + { "r15", (long *)&ddb_regs.tf_r15, FCN_NULL }, + { "pr", (long *)&ddb_regs.tf_pr, FCN_NULL }, + { "spc", (long *)&ddb_regs.tf_spc, FCN_NULL }, + { "ssr", (long *)&ddb_regs.tf_ssr, FCN_NULL }, + { "mach", (long *)&ddb_regs.tf_mach, FCN_NULL }, + { "macl", (long *)&ddb_regs.tf_macl, FCN_NULL }, +}; + +struct db_variable *db_eregs = + db_regs + sizeof(db_regs)/sizeof(db_regs[0]); + +void +db_stack_trace_print(db_expr_t addr, int have_addr, db_expr_t count, + char *modif, int (*print)(const char *, ...)) +{ + db_addr_t callpc, frame, lastframe; + uint32_t vbr; + + __asm volatile("stc vbr, %0" : "=r"(vbr)); + + frame = ddb_regs.tf_r14; + callpc = ddb_regs.tf_spc; + + lastframe = 0; + while (count > 0 && frame != 0) { + /* Are we crossing a trap frame? */ + if ((callpc & ~PAGE_MASK) == vbr) { + struct trapframe *tf = (void *)frame; + + frame = tf->tf_r14; + callpc = tf->tf_spc; + + (*print)("<EXPEVT %03x; SSR=%08x> at ", + tf->tf_expevt, tf->tf_ssr); + db_printsym(callpc, DB_STGY_PROC, print); + (*print)("\n"); + + /* XXX: don't venture into the userland yet */ + if ((tf->tf_ssr & PSL_MD) == 0) + break; + } else { + char *name; + db_expr_t offset; + db_sym_t sym; + + + DPRINTF(" (1)newpc 0x%lx, newfp 0x%lx\n", + callpc, frame); + + sym = db_search_symbol(callpc, DB_STGY_ANY, &offset); + db_symbol_values(sym, &name, NULL); + + if (lastframe == 0 && sym == 0) { + printf("symbol not found\n"); + break; + } + + db_nextframe(callpc - offset, &frame, &callpc); + DPRINTF(" (2)newpc 0x%lx, newfp 0x%lx\n", + callpc, frame); + + if (callpc == 0 && lastframe == 0) + callpc = (db_addr_t)ddb_regs.tf_pr; + DPRINTF(" (3)newpc 0x%lx, newfp 0x%lx\n", + callpc, frame); + + (*print)("%s() at ", name ? name : ""); + db_printsym(callpc, DB_STGY_PROC, print); + (*print)("\n"); + } + + count--; + lastframe = frame; + } +} + +void +db_nextframe( + db_addr_t pc, /* in: entry address of current function */ + db_addr_t *fp, /* in: current fp, out: parent fp */ + db_addr_t *pr) /* out: parent pr */ +{ + int *frame = (void *)*fp; + int i, inst; + int depth, prdepth, fpdepth; + + depth = 0; + prdepth = fpdepth = -1; + + if (pc < (db_addr_t)start || pc > (db_addr_t)etext) + goto out; + + for (i = 0; i < 30; i++) { + inst = db_get_value(pc, 2, FALSE); + pc += 2; + + if (inst == 0x6ef3) /* mov r15,r14 -- end of prologue */ + break; + + if (inst == 0x4f22) { /* sts.l pr,@-r15 */ + prdepth = depth; + depth++; + continue; + } + if (inst == 0x2fe6) { /* mov.l r14,@-r15 */ + fpdepth = depth; + depth++; + continue; + } + if ((inst & 0xff0f) == 0x2f06) { /* mov.l r?,@-r15 */ + depth++; + continue; + } + if ((inst & 0xff00) == 0x7f00) { /* add #n,r15 */ + int8_t n = inst & 0xff; + + if (n >= 0) { + printf("add #n,r15 (n > 0)\n"); + break; + } + + depth += -n/4; + continue; + } + if ((inst & 0xf000) == 0x9000) { + if (db_get_value(pc, 2, FALSE) == 0x3f38) { + /* "mov #n,r3; sub r3,r15" */ + unsigned int disp = (int)(inst & 0xff); + int r3; + + r3 = (int)*(unsigned short *)(pc + (4 - 2) + + (disp << 1)); + if ((r3 & 0x00008000) == 0) + r3 &= 0x0000ffff; + else + r3 |= 0xffff0000; + depth += (r3 / 4); + + pc += 2; + continue; + } + } + +#ifdef TRACE_DEBUG + printf("unknown instruction in prologue\n"); + db_disasm(pc - 2, 0); +#endif + } + + out: + if (fpdepth != -1) + *fp = frame[depth - fpdepth - 1]; + else + *fp = 0; + + if (prdepth != -1) + *pr = frame[depth - prdepth - 1]; + else + *pr = 0; +} diff --git a/sys/arch/sh/sh/devreg.c b/sys/arch/sh/sh/devreg.c new file mode 100644 index 00000000000..ec1df3bbbe1 --- /dev/null +++ b/sys/arch/sh/sh/devreg.c @@ -0,0 +1,167 @@ +/* $OpenBSD: devreg.c,v 1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: devreg.c,v 1.6 2006/03/04 01:13:35 uwe Exp $ */ + +/*- + * Copyright (c) 2002 The NetBSD Foundation, Inc. + * 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 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. + */ + +#include <sys/param.h> + +#include <sh/cache_sh3.h> +#include <sh/cache_sh4.h> +#include <sh/mmu_sh3.h> +#include <sh/mmu_sh4.h> +#include <sh/trap.h> + +#include <sh/ubcreg.h> +#include <sh/rtcreg.h> +#include <sh/tmureg.h> + +/* MMU */ +uint32_t __sh_PTEH; +uint32_t __sh_TTB; +uint32_t __sh_TEA; +uint32_t __sh_TRA; +uint32_t __sh_EXPEVT; +uint32_t __sh_INTEVT; + +/* UBC */ +uint32_t __sh_BARA; +uint32_t __sh_BAMRA; +uint32_t __sh_BASRA; +uint32_t __sh_BBRA; +uint32_t __sh_BARB; +uint32_t __sh_BAMRB; +uint32_t __sh_BASRB; +uint32_t __sh_BBRB; +uint32_t __sh_BDRB; +uint32_t __sh_BDMRB; +uint32_t __sh_BRCR; + +/* RTC */ +uint32_t __sh_R64CNT; +uint32_t __sh_RSECCNT; +uint32_t __sh_RMINCNT; +uint32_t __sh_RHRCNT; +uint32_t __sh_RWKCNT; +uint32_t __sh_RDAYCNT; +uint32_t __sh_RMONCNT; +uint32_t __sh_RYRCNT; +uint32_t __sh_RSECAR; +uint32_t __sh_RMINAR; +uint32_t __sh_RHRAR; +uint32_t __sh_RWKAR; +uint32_t __sh_RDAYAR; +uint32_t __sh_RMONAR; +uint32_t __sh_RCR1; +uint32_t __sh_RCR2; + +/* TMU */ +uint32_t __sh_TOCR; +uint32_t __sh_TSTR; +uint32_t __sh_TCOR0; +uint32_t __sh_TCNT0; +uint32_t __sh_TCR0; +uint32_t __sh_TCOR1; +uint32_t __sh_TCNT1; +uint32_t __sh_TCR1; +uint32_t __sh_TCOR2; +uint32_t __sh_TCNT2; +uint32_t __sh_TCR2; +uint32_t __sh_TCPR2; + +#define SH3REG(x) __sh_ ## x = SH3_ ## x +#define SH4REG(x) __sh_ ## x = SH4_ ## x + +#define SHREG(x) \ +do { \ +/* Exception */ \ +SH ## x ## REG(TRA); \ +SH ## x ## REG(EXPEVT); \ +SH ## x ## REG(INTEVT); \ +/* UBC */ \ +SH ## x ## REG(BARA); \ +SH ## x ## REG(BAMRA); \ +SH ## x ## REG(BASRA); \ +SH ## x ## REG(BBRA); \ +SH ## x ## REG(BARB); \ +SH ## x ## REG(BAMRB); \ +SH ## x ## REG(BASRB); \ +SH ## x ## REG(BBRB); \ +SH ## x ## REG(BDRB); \ +SH ## x ## REG(BDMRB); \ +SH ## x ## REG(BRCR); \ +/* MMU */ \ +SH ## x ## REG(PTEH); \ +SH ## x ## REG(TEA); \ +SH ## x ## REG(TTB); \ +/* RTC */ \ +SH ## x ## REG(R64CNT); \ +SH ## x ## REG(RSECCNT); \ +SH ## x ## REG(RMINCNT); \ +SH ## x ## REG(RHRCNT); \ +SH ## x ## REG(RWKCNT); \ +SH ## x ## REG(RDAYCNT); \ +SH ## x ## REG(RMONCNT); \ +SH ## x ## REG(RYRCNT); \ +SH ## x ## REG(RSECAR); \ +SH ## x ## REG(RMINAR); \ +SH ## x ## REG(RHRAR); \ +SH ## x ## REG(RWKAR); \ +SH ## x ## REG(RDAYAR); \ +SH ## x ## REG(RMONAR); \ +SH ## x ## REG(RCR1); \ +SH ## x ## REG(RCR2); \ +/* TMU */ \ +SH ## x ## REG(TOCR); \ +SH ## x ## REG(TSTR); \ +SH ## x ## REG(TCOR0); \ +SH ## x ## REG(TCNT0); \ +SH ## x ## REG(TCR0); \ +SH ## x ## REG(TCOR1); \ +SH ## x ## REG(TCNT1); \ +SH ## x ## REG(TCR1); \ +SH ## x ## REG(TCOR2); \ +SH ## x ## REG(TCNT2); \ +SH ## x ## REG(TCR2); \ +SH ## x ## REG(TCPR2); \ +} while (/*CONSTCOND*/0) + +void +sh_devreg_init() +{ + if (CPU_IS_SH3) + SHREG(3); + + if (CPU_IS_SH4) + SHREG(4); +} diff --git a/sys/arch/sh/sh/genassym.cf b/sys/arch/sh/sh/genassym.cf new file mode 100644 index 00000000000..52c6fb4a19f --- /dev/null +++ b/sys/arch/sh/sh/genassym.cf @@ -0,0 +1,120 @@ +# $OpenBSD: genassym.cf,v 1.1 2006/10/06 21:02:55 miod Exp $ +# $NetBSD: genassym.cf,v 1.10 2005/12/11 12:19:00 christos Exp $ + +#- +# Copyright (c) 2002 The NetBSD Foundation, Inc. +# 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 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. +# + +include <sys/param.h> +include <sys/proc.h> +include <sys/signal.h> +include <sys/mbuf.h> +include <sys/user.h> +include <sys/errno.h> +include <uvm/uvm_extern.h> +include <sh/locore.h> +include <sh/vmparam.h> + +struct trapframe +define TF_SIZE sizeof(struct trapframe) +member tf_expevt +member tf_ubc +member tf_spc +member tf_ssr +member tf_macl +member tf_mach +member tf_pr +member tf_r14 +member tf_r13 +member tf_r12 +member tf_r11 +member tf_r10 +member tf_r9 +member tf_r8 +member tf_r7 +member tf_r6 +member tf_r5 +member tf_r4 +member tf_r3 +member tf_r2 +member tf_r1 +member tf_r0 +member tf_r15 + +struct proc +member p_addr +member p_back +member p_forw +member p_stat +member p_wchan +member P_MD_UPTE p_md.md_upte +member P_MD_PCB p_md.md_pcb + +struct switchframe +define SF_SIZE sizeof(struct switchframe) +member sf_sr +member sf_r15 +member sf_r14 +member sf_r13 +member sf_r12 +member sf_r10 +member sf_r9 +member sf_r8 +member sf_pr +member sf_r6_bank +member sf_r7_bank + +struct sigcontext +member SC_EFLAGS sc_ssr + +struct pcb +member pcb_onfault +member pcb_faultbail + +export SONPROC +export SRUN + +struct uvmexp UVMEXP_ +member intrs + +export VM_MAXUSER_ADDRESS + +export EFAULT +export ENAMETOOLONG + +# +# in_cksum.S +# +struct mbuf +member m_data +member m_len +member m_next diff --git a/sys/arch/sh/sh/in_cksum.S b/sys/arch/sh/sh/in_cksum.S new file mode 100644 index 00000000000..f03ddb3bf96 --- /dev/null +++ b/sys/arch/sh/sh/in_cksum.S @@ -0,0 +1,279 @@ +/* $OpenBSD: in_cksum.S,v 1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: in_cksum.S,v 1.10 2006/04/11 23:45:13 uwe Exp $ */ + +/*- + * Copyright (c) 2000 SHIMIZU Ryo <ryo@misakimix.org> + * 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. 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. + */ + +#include <machine/asm.h> +#include "assym.h" + + +#define reg_tmp0 r0 +#define reg_byte_swapped r1 +#define reg_mlen r2 +#define reg_tmp3 r3 +#define reg_m r4 +#define reg_len r5 +#define reg_sum r6 +#define reg_w r7 + + +#define REDUCE \ + swap.w reg_sum,reg_tmp0 ; \ + extu.w reg_sum,reg_sum ; \ + extu.w reg_tmp0,reg_tmp0 ; \ + add reg_tmp0,reg_sum + +#define ROL \ + shll8 reg_sum + +#ifndef __LITTLE_ENDIAN__ +#define ADDB \ + mov.b @reg_w+,reg_tmp0 ; \ + ROL ; \ + extu.b reg_tmp0,reg_tmp0 ; \ + add reg_tmp0,reg_sum ; \ + not reg_byte_swapped,reg_byte_swapped +#else +#define ADDB \ + mov.b @reg_w+,reg_tmp0 ; \ + extu.b reg_tmp0,reg_tmp0 ; \ + add reg_tmp0,reg_sum ; \ + ROL ; \ + not reg_byte_swapped,reg_byte_swapped +#endif + + +#define ADDS \ + mov.w @reg_w+,reg_tmp0 ; \ + extu.w reg_tmp0,reg_tmp0 ; \ + add reg_tmp0,reg_sum + +#define ADDCL \ + mov.l @reg_w+,reg_tmp0 ; \ + addc reg_tmp0,reg_sum + +#define FORWARD1 \ + add #-1,reg_mlen + +#define FORWARD2 \ + add #-2,reg_mlen + + +/* + * LINTSTUB: include <sys/param.h> + * LINTSTUB: include <sys/mbuf.h> + * + * LINTSTUB: Func: int in_cksum(struct mbuf *m, int len); + */ +ENTRY(in_cksum) + sts.l pr,@-sp + + + mov #0,reg_sum + mov #0,reg_byte_swapped + + + tst reg_len,reg_len + bt/s mbuf_loop_done +mbuf_loop: + tst reg_m,reg_m + bt out_of_mbufs + + mov.l @(M_LEN,reg_m),reg_mlen + tst reg_mlen,reg_mlen + bt/s mbuf_loop_continue + mov.l @(M_DATA,reg_m),reg_w + + + cmp/ge reg_mlen,reg_len + bt 1f + mov reg_len,reg_mlen +1: + sub reg_mlen,reg_len + + + mov reg_w,reg_tmp0 + tst #1,reg_tmp0 + bt/s 1f + REDUCE /* 1st instruction break only reg_tmp0(r0) */ + ADDB + FORWARD1 +1: + + + mov #1,reg_tmp0 + cmp/gt reg_tmp0,reg_mlen + bf/s 1f + mov reg_w,reg_tmp0 + tst #2,reg_tmp0 + bt/s 1f + REDUCE /* 1st instruction break only reg_tmp0(r0) */ + ADDS + FORWARD2 +1: + + + + mov #127,reg_tmp0 + cmp/hi reg_tmp0,reg_mlen + bf 1f + +do_cksum128: + bsr cksum128 + nop + + mov #127,reg_tmp0 + cmp/hi reg_tmp0,reg_mlen + bt do_cksum128 +1: + + + bsr cksum128mod + nop + + REDUCE + + mov #1,reg_tmp0 + cmp/gt reg_tmp0,reg_mlen + bf 1f + ADDS + FORWARD2 +1: + + mov reg_mlen,r0 + tst #1,r0 + bt 1f + ADDB +1: + + +mbuf_loop_continue: + mov.l @(M_NEXT,reg_m),reg_m + + tst reg_len,reg_len + bf/s mbuf_loop +mbuf_loop_done: + + + tst reg_byte_swapped,reg_byte_swapped + bt/s 1f + REDUCE /* 1st instruction break only reg_tmp0(r0) */ + ROL +1: + + REDUCE + REDUCE + +in_cksum_return: + not reg_sum,r0 + lds.l @sp+,pr + rts + extu.w r0,r0 + + +out_of_mbufs: + mova .L_message_out_of_data,reg_tmp0 + mov.l .L_printf,reg_tmp3 + + mov.l reg_sum,@-sp /* save: call clobbered register */ + + jsr @reg_tmp3 + mov reg_tmp0,r4 + + bra in_cksum_return + mov.l @sp+,reg_sum /* restore */ + + .align 2 +.L_printf: + .long _C_LABEL(printf) + + .align 2 /* mova target */ +.L_message_out_of_data: + .asciz "cksum: out of data (%d byte short)\n" + + SET_ENTRY_SIZE(in_cksum) + + + .align 2 +cksum128mod: + mov reg_mlen,reg_tmp0 + and #124,reg_tmp0 + sub reg_tmp0,reg_mlen + + mov.l .L_cksum128_tail_p,reg_tmp3 + sub reg_tmp0,reg_tmp3 + jmp @reg_tmp3 + clrt + + .align 2 +.L_cksum128_tail_p: + .long cksum128_tail + + + .align 2 +cksum128: + add #-128,reg_mlen + clrt + +cksum128_unroll: + ADDCL + ADDCL + ADDCL + ADDCL + ADDCL + ADDCL + ADDCL + ADDCL + ADDCL + ADDCL + ADDCL + ADDCL + ADDCL + ADDCL + ADDCL + ADDCL + ADDCL + ADDCL + ADDCL + ADDCL + ADDCL + ADDCL + ADDCL + ADDCL + ADDCL + ADDCL + ADDCL + ADDCL + ADDCL + ADDCL + ADDCL + ADDCL +cksum128_tail: + mov #0,reg_tmp0 + rts + addc reg_tmp0,reg_sum diff --git a/sys/arch/sh/sh/interrupt.c b/sys/arch/sh/sh/interrupt.c new file mode 100644 index 00000000000..8a32d9ac7e1 --- /dev/null +++ b/sys/arch/sh/sh/interrupt.c @@ -0,0 +1,752 @@ +/* $OpenBSD: interrupt.c,v 1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: interrupt.c,v 1.18 2006/01/25 00:02:57 uwe Exp $ */ + +/*- + * Copyright (c) 2002 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by UCHIYAMA Yasushi. + * + * 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. + */ + +#include <sys/param.h> +#include <sys/malloc.h> + +#include <uvm/uvm_extern.h> /* uvmexp.intrs */ + +#include <net/netisr.h> + +#include <sh/clock.h> +#include <sh/trap.h> +#include <sh/intcreg.h> +#include <sh/tmureg.h> +#include <machine/intr.h> + +void intc_intr_priority(int, int); +struct intc_intrhand *intc_alloc_ih(void); +void intc_free_ih(struct intc_intrhand *); +int intc_unknown_intr(void *); + +#ifdef SH4 +void intpri_intr_enable(int); +void intpri_intr_disable(int); +#endif + +void netintr(void); +void tmu1_oneshot(void); +int tmu1_intr(void *); +void tmu2_oneshot(void); +int tmu2_intr(void *); + +/* + * EVTCODE to intc_intrhand mapper. + * max #76 is SH4_INTEVT_TMU4 (0xb80) + */ +int8_t __intc_evtcode_to_ih[128]; + +struct intc_intrhand __intc_intrhand[_INTR_N + 1] = { + /* Place holder interrupt handler for unregistered interrupt. */ + [0] = { .ih_func = intc_unknown_intr, .ih_level = 0xf0 } +}; + +struct sh_soft_intr sh_soft_intrs[_IPL_NSOFT]; +struct sh_soft_intrhand *softnet_intrhand; + +/* + * SH INTC support. + */ +void +intc_init(void) +{ + + switch (cpu_product) { +#ifdef SH3 + case CPU_PRODUCT_7709: + case CPU_PRODUCT_7709A: + _reg_write_2(SH7709_IPRC, 0); + _reg_write_2(SH7709_IPRD, 0); + _reg_write_2(SH7709_IPRE, 0); + /* FALLTHROUGH */ + case CPU_PRODUCT_7708: + case CPU_PRODUCT_7708S: + case CPU_PRODUCT_7708R: + _reg_write_2(SH3_IPRA, 0); + _reg_write_2(SH3_IPRB, 0); + break; +#endif /* SH3 */ + +#ifdef SH4 + case CPU_PRODUCT_7751: + case CPU_PRODUCT_7751R: + _reg_write_4(SH4_INTPRI00, 0); + _reg_write_4(SH4_INTMSK00, INTMSK00_MASK_ALL); + /* FALLTHROUGH */ + case CPU_PRODUCT_7750S: + case CPU_PRODUCT_7750R: + _reg_write_2(SH4_IPRD, 0); + /* FALLTHROUGH */ + case CPU_PRODUCT_7750: + _reg_write_2(SH4_IPRA, 0); + _reg_write_2(SH4_IPRB, 0); + _reg_write_2(SH4_IPRC, 0); + break; +#endif /* SH4 */ + } +} + +void * +intc_intr_establish(int evtcode, int trigger, int level, + int (*ih_func)(void *), void *ih_arg, const char *name) +{ + struct intc_intrhand *ih; + + KDASSERT(evtcode >= 0x200 && level > 0); + + ih = intc_alloc_ih(); + ih->ih_func = ih_func; + ih->ih_arg = ih_arg; + ih->ih_level = level << 4; /* convert to SR.IMASK format. */ + ih->ih_evtcode = evtcode; + + /* Map interrupt handler */ + EVTCODE_TO_IH_INDEX(evtcode) = ih->ih_idx; + + /* Priority */ + intc_intr_priority(evtcode, level); + + /* Sense select (SH7709, SH7709A only) XXX notyet */ + + return (ih); +} + +void +intc_intr_disestablish(void *arg) +{ + struct intc_intrhand *ih = arg; + int evtcode = ih->ih_evtcode; + + /* Mask interrupt if IPR can manage it. if not, cascaded ICU will do */ + intc_intr_priority(evtcode, 0); + + /* Unmap interrupt handler */ + EVTCODE_TO_IH_INDEX(evtcode) = 0; + + intc_free_ih(ih); +} + +void +intc_intr_disable(int evtcode) +{ + int s; + + s = _cpu_intr_suspend(); + KASSERT(EVTCODE_TO_IH_INDEX(evtcode) != 0); /* there is a handler */ + switch (evtcode) { + default: + intc_intr_priority(evtcode, 0); + break; + +#ifdef SH4 + case SH4_INTEVT_PCISERR: + case SH4_INTEVT_PCIDMA3: + case SH4_INTEVT_PCIDMA2: + case SH4_INTEVT_PCIDMA1: + case SH4_INTEVT_PCIDMA0: + case SH4_INTEVT_PCIPWON: + case SH4_INTEVT_PCIPWDWN: + case SH4_INTEVT_PCIERR: + intpri_intr_disable(evtcode); + break; +#endif + } + _cpu_intr_resume(s); +} + +void +intc_intr_enable(int evtcode) +{ + struct intc_intrhand *ih; + int s; + + s = _cpu_intr_suspend(); + KASSERT(EVTCODE_TO_IH_INDEX(evtcode) != 0); /* there is a handler */ + switch (evtcode) { + default: + ih = EVTCODE_IH(evtcode); + /* ih_level is in the SR.IMASK format */ + intc_intr_priority(evtcode, (ih->ih_level >> 4)); + break; + +#ifdef SH4 + case SH4_INTEVT_PCISERR: + case SH4_INTEVT_PCIDMA3: + case SH4_INTEVT_PCIDMA2: + case SH4_INTEVT_PCIDMA1: + case SH4_INTEVT_PCIDMA0: + case SH4_INTEVT_PCIPWON: + case SH4_INTEVT_PCIPWDWN: + case SH4_INTEVT_PCIERR: + intpri_intr_enable(evtcode); + break; +#endif + } + _cpu_intr_resume(s); +} + + +/* + * int intc_intr_priority(int evtcode, int level) + * Setup interrupt priority register. + * SH7708, SH7708S, SH7708R, SH7750, SH7750S ... evtcode is INTEVT + * SH7709, SH7709A ... evtcode is INTEVT2 + */ +void +intc_intr_priority(int evtcode, int level) +{ + volatile uint16_t *iprreg; + int pos; + uint16_t r; + +#define __SH_IPR(_sh, _ipr, _pos) \ + do { \ + iprreg = (volatile uint16_t *)(SH ## _sh ## _IPR ## _ipr); \ + pos = (_pos); \ + } while (/*CONSTCOND*/0) + +#define SH3_IPR(_ipr, _pos) __SH_IPR(3, _ipr, _pos) +#define SH4_IPR(_ipr, _pos) __SH_IPR(4, _ipr, _pos) +#define SH7709_IPR(_ipr, _pos) __SH_IPR(7709, _ipr, _pos) + +#define SH_IPR(_ipr, _pos) \ + do { \ + if (CPU_IS_SH3) \ + SH3_IPR(_ipr, _pos); \ + else \ + SH4_IPR(_ipr, _pos); \ + } while (/*CONSTCOND*/0) + + iprreg = 0; + pos = -1; + + switch (evtcode) { + case SH_INTEVT_TMU0_TUNI0: + SH_IPR(A, 12); + break; + case SH_INTEVT_TMU1_TUNI1: + SH_IPR(A, 8); + break; + case SH_INTEVT_TMU2_TUNI2: + SH_IPR(A, 4); + break; + case SH_INTEVT_WDT_ITI: + SH_IPR(B, 12); + break; + case SH_INTEVT_SCI_ERI: + case SH_INTEVT_SCI_RXI: + case SH_INTEVT_SCI_TXI: + case SH_INTEVT_SCI_TEI: + SH_IPR(B, 4); + break; + } + +#ifdef SH3 + if (CPU_IS_SH3) { + switch (evtcode) { + case SH7709_INTEVT2_IRQ3: + SH7709_IPR(C, 12); + break; + case SH7709_INTEVT2_IRQ2: + SH7709_IPR(C, 8); + break; + case SH7709_INTEVT2_IRQ1: + SH7709_IPR(C, 4); + break; + case SH7709_INTEVT2_IRQ0: + SH7709_IPR(C, 0); + break; + case SH7709_INTEVT2_PINT07: + SH7709_IPR(D, 12); + break; + case SH7709_INTEVT2_PINT8F: + SH7709_IPR(D, 8); + break; + case SH7709_INTEVT2_IRQ5: + SH7709_IPR(D, 4); + break; + case SH7709_INTEVT2_IRQ4: + SH7709_IPR(D, 0); + break; + case SH7709_INTEVT2_DEI0: + case SH7709_INTEVT2_DEI1: + case SH7709_INTEVT2_DEI2: + case SH7709_INTEVT2_DEI3: + SH7709_IPR(E, 12); + break; + case SH7709_INTEVT2_IRDA_ERI: + case SH7709_INTEVT2_IRDA_RXI: + case SH7709_INTEVT2_IRDA_BRI: + case SH7709_INTEVT2_IRDA_TXI: + SH7709_IPR(E, 8); + break; + case SH7709_INTEVT2_SCIF_ERI: + case SH7709_INTEVT2_SCIF_RXI: + case SH7709_INTEVT2_SCIF_BRI: + case SH7709_INTEVT2_SCIF_TXI: + SH7709_IPR(E, 4); + break; + case SH7709_INTEVT2_ADC: + SH7709_IPR(E, 0); + break; + } + } +#endif /* SH3 */ + +#ifdef SH4 + if (CPU_IS_SH4) { + switch (evtcode) { + case SH4_INTEVT_SCIF_ERI: + case SH4_INTEVT_SCIF_RXI: + case SH4_INTEVT_SCIF_BRI: + case SH4_INTEVT_SCIF_TXI: + SH4_IPR(C, 4); + break; + +#if 0 + case SH4_INTEVT_PCISERR: + case SH4_INTEVT_PCIDMA3: + case SH4_INTEVT_PCIDMA2: + case SH4_INTEVT_PCIDMA1: + case SH4_INTEVT_PCIDMA0: + case SH4_INTEVT_PCIPWON: + case SH4_INTEVT_PCIPWDWN: + case SH4_INTEVT_PCIERR: +#endif + case SH4_INTEVT_TMU3: + case SH4_INTEVT_TMU4: + intpri_intr_priority(evtcode, level); + break; + } + } +#endif /* SH4 */ + + /* + * XXX: This function gets called even for interrupts that + * don't have their priority defined by IPR registers. + */ + if (pos < 0) + return; + + r = _reg_read_2(iprreg); + r = (r & ~(0xf << (pos))) | (level << (pos)); + _reg_write_2(iprreg, r); +} + +/* + * Interrupt handler holder allocater. + */ +struct intc_intrhand * +intc_alloc_ih(void) +{ + /* #0 is reserved for unregistered interrupt. */ + struct intc_intrhand *ih = &__intc_intrhand[1]; + int i; + + for (i = 1; i <= _INTR_N; i++, ih++) + if (ih->ih_idx == 0) { /* no driver uses this. */ + ih->ih_idx = i; /* register myself */ + return (ih); + } + + panic("increase _INTR_N greater than %d", _INTR_N); + return (NULL); +} + +void +intc_free_ih(struct intc_intrhand *ih) +{ + memset(ih, 0, sizeof(*ih)); +} + +/* Place-holder for debugging */ +int +intc_unknown_intr(void *arg) +{ + printf("INTEVT=0x%x", _reg_read_4(SH_(INTEVT))); + if (cpu_product == CPU_PRODUCT_7709 || cpu_product == CPU_PRODUCT_7709A) + printf(" INTEVT2=0x%x", _reg_read_4(SH7709_INTEVT2)); + printf("\n"); + + panic("unknown interrupt"); + /* NOTREACHED */ + return (0); +} + +#ifdef SH4 /* SH7751 support */ + +/* + * INTPRIxx + */ +void +intpri_intr_priority(int evtcode, int level) +{ + volatile uint32_t *iprreg; + uint32_t r; + int pos; + + if (!CPU_IS_SH4) + return; + + switch (cpu_product) { + default: + return; + + case CPU_PRODUCT_7751: + case CPU_PRODUCT_7751R: + break; + } + + iprreg = (volatile uint32_t *)SH4_INTPRI00; + pos = -1; + + switch (evtcode) { + case SH4_INTEVT_PCIDMA3: + case SH4_INTEVT_PCIDMA2: + case SH4_INTEVT_PCIDMA1: + case SH4_INTEVT_PCIDMA0: + case SH4_INTEVT_PCIPWDWN: + case SH4_INTEVT_PCIPWON: + case SH4_INTEVT_PCIERR: + pos = 0; + break; + + case SH4_INTEVT_PCISERR: + pos = 4; + break; + + case SH4_INTEVT_TMU3: + pos = 8; + break; + + case SH4_INTEVT_TMU4: + pos = 12; + break; + } + + if (pos < 0) { + return; + } + + r = _reg_read_4(iprreg); + r = (r & ~(0xf << pos)) | (level << pos); + _reg_write_4(iprreg, r); +} + +void +intpri_intr_enable(int evtcode) +{ + volatile uint32_t *iprreg; + uint32_t bit; + + if (!CPU_IS_SH4) + return; + + switch (cpu_product) { + default: + return; + + case CPU_PRODUCT_7751: + case CPU_PRODUCT_7751R: + break; + } + + iprreg = (volatile uint32_t *)SH4_INTMSKCLR00; + bit = 0; + + switch (evtcode) { + case SH4_INTEVT_PCISERR: + case SH4_INTEVT_PCIDMA3: + case SH4_INTEVT_PCIDMA2: + case SH4_INTEVT_PCIDMA1: + case SH4_INTEVT_PCIDMA0: + case SH4_INTEVT_PCIPWON: + case SH4_INTEVT_PCIPWDWN: + case SH4_INTEVT_PCIERR: + bit = (1 << ((evtcode - SH4_INTEVT_PCISERR) >> 5)); + break; + + case SH4_INTEVT_TMU3: + bit = INTREQ00_TUNI3; + break; + + case SH4_INTEVT_TMU4: + bit = INTREQ00_TUNI4; + break; + } + + if ((bit == 0) || (iprreg == NULL)) { + return; + } + + _reg_write_4(iprreg, bit); +} + +void +intpri_intr_disable(int evtcode) +{ + volatile uint32_t *iprreg; + uint32_t bit; + + if (!CPU_IS_SH4) + return; + + switch (cpu_product) { + default: + return; + + case CPU_PRODUCT_7751: + case CPU_PRODUCT_7751R: + break; + } + + iprreg = (volatile uint32_t *)SH4_INTMSK00; + bit = 0; + + switch (evtcode) { + case SH4_INTEVT_PCISERR: + case SH4_INTEVT_PCIDMA3: + case SH4_INTEVT_PCIDMA2: + case SH4_INTEVT_PCIDMA1: + case SH4_INTEVT_PCIDMA0: + case SH4_INTEVT_PCIPWON: + case SH4_INTEVT_PCIPWDWN: + case SH4_INTEVT_PCIERR: + bit = (1 << ((evtcode - SH4_INTEVT_PCISERR) >> 5)); + break; + + case SH4_INTEVT_TMU3: + bit = INTREQ00_TUNI3; + break; + + case SH4_INTEVT_TMU4: + bit = INTREQ00_TUNI4; + break; + } + + if ((bit == 0) || (iprreg == NULL)) { + return; + } + + _reg_write_4(iprreg, bit); +} +#endif /* SH4 */ + +/* + * Software interrupt support + */ +void +softintr_init(void) +{ +#if 0 + static const char *softintr_names[] = IPL_SOFTNAMES; +#endif + struct sh_soft_intr *asi; + int i; + + for (i = 0; i < _IPL_NSOFT; i++) { + asi = &sh_soft_intrs[i]; + TAILQ_INIT(&asi->softintr_q); + + asi->softintr_ipl = IPL_SOFT + i; + simple_lock_init(&asi->softintr_slock); +#if 0 + evcnt_attach_dynamic(&asi->softintr_evcnt, EVCNT_TYPE_INTR, + NULL, "soft", softintr_names[i]); +#endif + } + + /* XXX Establish legacy soft interrupt handlers. */ + softnet_intrhand = softintr_establish(IPL_SOFTNET, + (void (*)(void *))netintr, NULL); + KDASSERT(softnet_intrhand != NULL); + + intc_intr_establish(SH_INTEVT_TMU1_TUNI1, IST_LEVEL, IPL_SOFT, + tmu1_intr, NULL, "tmu1"); + intc_intr_establish(SH_INTEVT_TMU2_TUNI2, IST_LEVEL, IPL_SOFTNET, + tmu2_intr, NULL, "tmu2"); +} + +void +softintr_dispatch(int ipl) +{ + struct sh_soft_intr *asi; + struct sh_soft_intrhand *sih; + int s; + + s = _cpu_intr_suspend(); + + asi = &sh_soft_intrs[ipl - IPL_SOFT]; + + if (TAILQ_FIRST(&asi->softintr_q) != NULL) + asi->softintr_evcnt.ev_count++; + + while ((sih = TAILQ_FIRST(&asi->softintr_q)) != NULL) { + TAILQ_REMOVE(&asi->softintr_q, sih, sih_q); + sih->sih_pending = 0; + + uvmexp.softs++; + + _cpu_intr_resume(s); + (*sih->sih_fn)(sih->sih_arg); + s = _cpu_intr_suspend(); + } + + _cpu_intr_resume(s); +} + +void +setsoft(int ipl) +{ + if (ipl < IPL_SOFTNET) + tmu1_oneshot(); + else + tmu2_oneshot(); +} + +/* Register a software interrupt handler. */ +void * +softintr_establish(int ipl, void (*func)(void *), void *arg) +{ + struct sh_soft_intr *asi; + struct sh_soft_intrhand *sih; + int s; + + if (__predict_false(ipl >= (IPL_SOFT + _IPL_NSOFT) || + ipl < IPL_SOFT)) + panic("softintr_establish"); + + sih = malloc(sizeof(*sih), M_DEVBUF, M_NOWAIT); + + s = _cpu_intr_suspend(); + asi = &sh_soft_intrs[ipl - IPL_SOFT]; + if (__predict_true(sih != NULL)) { + sih->sih_intrhead = asi; + sih->sih_fn = func; + sih->sih_arg = arg; + sih->sih_pending = 0; + } + _cpu_intr_resume(s); + + return (sih); +} + +/* Unregister a software interrupt handler. */ +void +softintr_disestablish(void *arg) +{ + struct sh_soft_intrhand *sih = arg; + struct sh_soft_intr *asi = sih->sih_intrhead; + int s; + + s = _cpu_intr_suspend(); + if (sih->sih_pending) { + TAILQ_REMOVE(&asi->softintr_q, sih, sih_q); + sih->sih_pending = 0; + } + _cpu_intr_resume(s); + + free(sih, M_DEVBUF); +} + +/* + * Software (low priority) network interrupt. i.e. softnet(). + */ +void +netintr(void) +{ +#define DONETISR(bit, fn) \ + do { \ + if (n & (1 << bit)) \ + fn(); \ + } while (/*CONSTCOND*/0) + + int s, n; + + s = splnet(); + n = netisr; + netisr = 0; + splx(s); +#include <net/netisr_dispatch.h> + +#undef DONETISR +} + +/* + * Software interrupt is simulated with TMU one-shot timer. + */ +void +tmu1_oneshot(void) +{ + _reg_bclr_1(SH_(TSTR), TSTR_STR1); + _reg_write_4(SH_(TCNT1), 0); + _reg_bset_1(SH_(TSTR), TSTR_STR1); +} + +int +tmu1_intr(void *arg) +{ + _reg_bclr_1(SH_(TSTR), TSTR_STR1); + _reg_bclr_2(SH_(TCR1), TCR_UNF); + + softintr_dispatch(IPL_SOFTCLOCK); + softintr_dispatch(IPL_SOFT); + + return (0); +} + +void +tmu2_oneshot(void) +{ + _reg_bclr_1(SH_(TSTR), TSTR_STR2); + _reg_write_4(SH_(TCNT2), 0); + _reg_bset_1(SH_(TSTR), TSTR_STR2); +} + +int +tmu2_intr(void *arg) +{ + _reg_bclr_1(SH_(TSTR), TSTR_STR2); + _reg_bclr_2(SH_(TCR2), TCR_UNF); + + softintr_dispatch(IPL_SOFTSERIAL); + softintr_dispatch(IPL_SOFTNET); + + return (0); +} diff --git a/sys/arch/sh/sh/locore_c.c b/sys/arch/sh/sh/locore_c.c new file mode 100644 index 00000000000..f034e45846c --- /dev/null +++ b/sys/arch/sh/sh/locore_c.c @@ -0,0 +1,286 @@ +/* $OpenBSD: locore_c.c,v 1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: locore_c.c,v 1.13 2006/03/04 01:13:35 uwe Exp $ */ + +/*- + * Copyright (c) 1996, 1997, 2002 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) 1982, 1987, 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * 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. 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. + * + * @(#)Locore.c + */ + +/*- + * Copyright (c) 1993, 1994, 1995, 1996, 1997 + * Charles M. Hannum. All rights reserved. + * Copyright (c) 1992 Terrence R. Lambert. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * 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. + * + * @(#)Locore.c + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/user.h> +#include <sys/sched.h> +#include <sys/proc.h> + +#include <uvm/uvm_extern.h> + +#include <sh/locore.h> +#include <sh/cpu.h> +#include <sh/pmap.h> +#include <sh/mmu_sh3.h> +#include <sh/mmu_sh4.h> + +void (*__sh_switch_resume)(struct proc *); +struct proc *cpu_switch_search(struct proc *); +struct proc *cpu_switch_prepare(struct proc *, struct proc *); +void idle(void); +int want_resched; + +#ifdef LOCKDEBUG +#define SCHED_LOCK_IDLE() sched_lock_idle() +#define SCHED_UNLOCK_IDLE() sched_unlock_idle() +#else +#define SCHED_LOCK_IDLE() do {} while (/* CONSTCOND */ 0) +#define SCHED_UNLOCK_IDLE() do {} while (/* CONSTCOND */ 0) +#endif + + +/* + * Prepare context switch from oproc to nproc. + * This code is shared by cpu_switch and cpu_switchto. + */ +struct proc * +cpu_switch_prepare(struct proc *oproc, struct proc *nproc) +{ + nproc->p_stat = SONPROC; + + if (nproc != oproc) { + curpcb = nproc->p_md.md_pcb; + pmap_activate(nproc); + } + + curproc = nproc; + return (nproc); +} + +/* + * Find the highest priority proc and prepare to switching to it. + */ +struct proc * +cpu_switch_search(struct proc *oproc) +{ + struct prochd *q; + struct proc *p; + + curproc = NULL; + + SCHED_LOCK_IDLE(); + while (whichqs == 0) { + SCHED_UNLOCK_IDLE(); + idle(); + SCHED_LOCK_IDLE(); + } + + q = &qs[ffs(whichqs) - 1]; + p = q->ph_link; + remrunqueue(p); + want_resched = 0; + SCHED_UNLOCK_IDLE(); + + return (cpu_switch_prepare(oproc, p)); +} + +/* + * void idle(void): + * When no processes are on the run queue, wait for something to come + * ready. Separated function for profiling. + */ +void +idle() +{ + spl0(); + uvm_pageidlezero(); + __asm volatile("sleep"); + splsched(); +} + +#ifndef P1_STACK +#ifdef SH3 +/* + * void sh3_switch_setup(struct proc *p): + * prepare kernel stack PTE table. TLB miss handler check these. + */ +void +sh3_switch_setup(struct proc *p) +{ + pt_entry_t *pte; + struct md_upte *md_upte = p->p_md.md_upte; + uint32_t vpn; + int i; + + vpn = (uint32_t)p->p_addr; + vpn &= ~PGOFSET; + for (i = 0; i < UPAGES; i++, vpn += PAGE_SIZE, md_upte++) { + pte = __pmap_kpte_lookup(vpn); + KDASSERT(pte && *pte != 0); + + md_upte->addr = vpn; + md_upte->data = (*pte & PG_HW_BITS) | PG_D | PG_V; + } +} +#endif /* SH3 */ + +#ifdef SH4 +/* + * void sh4_switch_setup(struct proc *p): + * prepare kernel stack PTE table. sh4_switch_resume wired this PTE. + */ +void +sh4_switch_setup(struct proc *p) +{ + pt_entry_t *pte; + struct md_upte *md_upte = p->p_md.md_upte; + uint32_t vpn; + int i, e; + + vpn = (uint32_t)p->p_addr; + vpn &= ~PGOFSET; + e = SH4_UTLB_ENTRY - UPAGES; + for (i = 0; i < UPAGES; i++, e++, vpn += PAGE_SIZE) { + pte = __pmap_kpte_lookup(vpn); + KDASSERT(pte && *pte != 0); + /* Address array */ + md_upte->addr = SH4_UTLB_AA | (e << SH4_UTLB_E_SHIFT); + md_upte->data = vpn | SH4_UTLB_AA_D | SH4_UTLB_AA_V; + md_upte++; + /* Data array */ + md_upte->addr = SH4_UTLB_DA1 | (e << SH4_UTLB_E_SHIFT); + md_upte->data = (*pte & PG_HW_BITS) | + SH4_UTLB_DA1_D | SH4_UTLB_DA1_V; + md_upte++; + } +} +#endif /* SH4 */ +#endif /* !P1_STACK */ + +/* + * copystr(caddr_t from, caddr_t to, size_t maxlen, size_t *lencopied); + * Copy a NUL-terminated string, at most maxlen characters long. Return the + * number of characters copied (including the NUL) in *lencopied. If the + * string is too long, return ENAMETOOLONG; else return 0. + */ +int +copystr(const void *kfaddr, void *kdaddr, size_t maxlen, size_t *lencopied) +{ + const char *from = kfaddr; + char *to = kdaddr; + int i; + + for (i = 0; maxlen-- > 0; i++) { + if ((*to++ = *from++) == '\0') { + if (lencopied) + *lencopied = i + 1; + return (0); + } + } + + if (lencopied) + *lencopied = i; + + return (ENAMETOOLONG); +} diff --git a/sys/arch/sh/sh/locore_subr.S b/sys/arch/sh/sh/locore_subr.S new file mode 100644 index 00000000000..1f45dd721c7 --- /dev/null +++ b/sys/arch/sh/sh/locore_subr.S @@ -0,0 +1,866 @@ +/* $OpenBSD: locore_subr.S,v 1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: locore_subr.S,v 1.28 2006/01/23 22:52:09 uwe Exp $ */ + +/*- + * Copyright (c) 2002 The NetBSD Foundation, Inc. + * 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 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. + */ + +#include "assym.h" + +#include <sys/syscall.h> /* SYS_sigreturn, SYS_exit */ +#include <sh/asm.h> +#include <sh/locore.h> +#include <sh/param.h> /* UPAGES */ +#include <sh/mmu_sh3.h> +#include <sh/mmu_sh4.h> + +/* + * LINTSTUB: include <sys/types.h> + * LINTSTUB: include <sys/proc.h> + * LINTSTUB: include <sh/locore.h> + */ + + .text + .align 5 /* align cache line size (32B) */ +/* + * LINTSTUB: Func: int cpu_switch(struct proc *p, struct proc *XXX_IGNORED) + * Find a runnable proc and switch to it. Wait if necessary. + */ +ENTRY(cpu_switch) + /* Save current proc's context to switchframe */ + mov.l .L_SF, r0 + mov.l @(r0, r4), r1 + add #SF_SIZE, r1 + stc.l r7_bank,@-r1 + stc.l sr, @-r1 + stc.l r6_bank,@-r1 + sts.l pr, @-r1 + mov.l r8, @-r1 + mov.l r9, @-r1 + mov.l r10, @-r1 + mov.l r11, @-r1 + mov.l r12, @-r1 + mov.l r13, @-r1 + mov.l r14, @-r1 + mov.l r15, @-r1 + +.L_find_and_switch: + /* Search next proc. cpu_switch_search may or may not sleep. */ + mov.l .L_cpu_switch_search, r0 + jsr @r0 + mov r4, r8 /* save old proc */ + + /* Skip context switch if same proc. */ + cmp/eq r8, r0 + bt/s 1f + mov r0, r4 /* new proc */ + +.L_doswitch: + /* Setup kernel stack */ + mov.l .L_SF, r0 + mov.l @(r0, r4), r1 /* switch frame */ + mov.l @(SF_R7_BANK, r1), r0 /* stack top */ + mov.l @(SF_R6_BANK, r1), r2 /* current frame */ + mov.l @(SF_R15, r1), r3 /* current stack */ + /* During kernel stack switching, all interrupts are disabled. */ + __EXCEPTION_BLOCK(r1, r5) + /* switch to new kernel stack */ + ldc r0, r7_bank + ldc r2, r6_bank + mov r3, r15 + + /* Wire u-area */ + MOV (switch_resume, r0) + jsr @r0 + mov r4, r8 /* save new proc */ + mov r8, r4 + __EXCEPTION_UNBLOCK(r0, r1) + /* Now OK to use kernel stack. */ + + /* Return 1 indicating "we switched". */ + bra 2f + mov #1, r2 + +1: /* Return 0 indicating "didn't switch". */ + mov #0, r2 + + /* Restore new proc's context from switchframe */ + /* NOTE: r2 has return value! */ +2: mov.l .L_SF, r0 + mov.l @(r0, r4), r1 + add #4, r1 /* r15 already restored */ + mov.l @r1+, r14 + mov.l @r1+, r13 + mov.l @r1+, r12 + mov.l @r1+, r11 + mov.l @r1+, r10 + mov.l @r1+, r9 + mov.l @r1+, r8 + lds.l @r1+, pr + add #4, r1 /* r6_bank already restored */ + ldc.l @r1+, sr + + /* r2 has the return value; stuff it into r0 now. */ + rts + mov r2, r0 + .align 2 +.L_SF: .long (P_MD_PCB) +.L_cpu_switch_search: .long _C_LABEL(cpu_switch_search) +FUNC_SYMBOL(switch_resume) + + + +/* + * LINTSTUB: Func: void cpu_switchto(struct proc *current, struct proc *next) + * Switch to the specified next LWP. + */ +ENTRY(cpu_switchto) + /* Save current proc's context to switchframe. */ + mov.l .L_SFp, r0 + mov.l @(r0, r4), r1 + add #SF_SIZE, r1 + stc.l r7_bank,@-r1 + stc.l sr, @-r1 + stc.l r6_bank,@-r1 + sts.l pr, @-r1 + mov.l r8, @-r1 + mov.l r9, @-r1 + mov.l r10, @-r1 + mov.l r11, @-r1 + mov.l r12, @-r1 + mov.l r13, @-r1 + mov.l r14, @-r1 + mov.l r15, @-r1 + + /* + * curproc = NULL; + * XXX Is this necessary? We know we won't go idle. + */ + mov.l .L_curproc, r0 + mov #0, r1 + mov.l r1, @r0 + + /* old and new procs are already in r4, r5 */ + mov.l .L_cpu_switch_prepare, r0 + jsr @r0 + nop + + /* + * Put the incoming LWP in r4 and jump into the middle + * of cpu_switch(), and let it do the work to restore the + * incoming LWP's context. + */ + bra .L_doswitch + mov r0, r4 + + .align 2 +.L_SFp: .long (P_MD_PCB) +.L_curproc: .long _C_LABEL(curproc) +.L_cpu_switch_prepare: .long _C_LABEL(cpu_switch_prepare) + + +/* + * LINTSTUB: Func: void cpu_exit(struct proc *p) + * Just fall-through to the switch_exit below. + */ +ENTRY(cpu_exit) + mov.l .L_switch_exit_proc_exit2, r5 /* exit_func to call */ + /* FALLTHROUGH */ + +/* + * LINTSTUB: Func: void switch_exit(struct proc *p, void (*exit_func)(struct proc *)) + * Called only from cpu_exit(p). Before we call exit_func to + * free proc's resources (including kernel stack) we need to + * switch to the proc0's kernel stack. Then we jump into the + * middle of cpu_switch to find and switch to a new proc. + */ +ALTENTRY(switch_exit) + mov.l .L_switch_exit_proc0_pcb, r1 + mov.l .L_switch_exit_curpcb, r0 + mov.l @r1, r1 + mov.l r1, @r0 /* curpcb = proc0.p_md.md_pcb */ + + mov.l @(SF_R7_BANK, r1), r0 /* stack top */ + mov.l @(SF_R6_BANK, r1), r2 /* current frame */ + mov.l @(SF_R15, r1), r3 /* current stack */ + + /* switch to proc0's kernel stack */ + __EXCEPTION_BLOCK(r1, r6) + ldc r0, r7_bank + ldc r2, r6_bank + mov r3, r15 + __EXCEPTION_UNBLOCK(r0, r1) + + /* safe to call (*exit_func)(p); now */ + jsr @r5 + nop /* proc is already in r4 */ + + /* proceed to cpu_switch */ + bra .L_find_and_switch + mov #0, r4 /* no "previous" proc */ + + .align 2 +.L_switch_exit_proc_exit2: + .long _C_LABEL(proc_exit2) +.L_switch_exit_proc0_pcb: + .long _C_LABEL(proc0) + P_MD_PCB +.L_switch_exit_curpcb: + .long _C_LABEL(curpcb) + + +#ifdef SH3 +/* + * LINTSTUB: Func: void sh3_switch_resume(struct proc *p) + * Set current u-area PTE array to curupte. + * No need to flush any entries. it is depended on u-area mapping is + * wired, and its mapping never cause modified/reference fault. + * u-area TLB fault is only covered by TLB miss exception. + * When the situation that "VPN match but not Valid" occur, SH3 jump to + * "generic exception" handler instead of TLB miss exception. + * But OpenBSD/sh code doesn't handle it. As the result, it causes + * hard reset. (never can access kernel stack). + */ +NENTRY(sh3_switch_resume) + mov.l .L_UPTE, r0 + mov.l .L_curupte, r1 + add r4, r0 /* p->p_md.md_upte */ + rts + mov.l r0, @r1 + .align 2 +.L_UPTE: .long P_MD_UPTE +.L_curupte: .long _C_LABEL(curupte) + SET_ENTRY_SIZE(sh3_switch_resume) +#endif /* SH3 */ + + +#ifdef SH4 +/* + * LINTSTUB: Func: void sh4_switch_resume(struct proc *p) + * Wire u-area. invalidate TLB entry for kernel stack to prevent + * TLB multiple hit. + */ +NENTRY(sh4_switch_resume) + mov.l .L_UPTE__sh4, r0 + add r0, r4 /* p->p_md.md_upte */ + mov #UPAGES,r3 + mov #1, r2 + mov.l @r4, r0 /* if (p->p_md.md_upte[0].addr == 0) return; */ + tst r0, r0 + bt 2f + + /* Save old ASID and set ASID to zero */ + xor r0, r0 + mov.l .L_4_PTEH, r1 + mov.l @r1, r7 + mov.l r0, @r1 + + mov.l .L_VPN_MASK, r6 + mov.l .L_4_UTLB_AA_A, r5 + + /* TLB address array must be accessed via P2. Setup jump address. */ + mova 1f, r0 + mov.l .L_P2BASE, r1 + or r1, r0 + jmp @r0 /* run P2 */ + nop + + /* Probe VPN match TLB entry and invalidate it. */ + .align 2 /* mova target must be 4byte alignment */ +1: mov.l @(4, r4), r0 + and r6, r0 + mov.l r0, @r5 /* clear D, V */ + + /* Wire u-area TLB entry */ + /* Address array */ + mov.l @r4+, r0 /* addr */ + mov.l @r4+, r1 /* data */ + mov.l r1, @r0 /* *addr = data */ + + /* Data array */ + mov.l @r4+, r0 /* addr */ + mov.l @r4+, r1 /* data */ + mov.l r1, @r0 /* *addr = data */ + cmp/eq r2, r3 + bf/s 1b + add #1, r2 + + /* restore ASID */ + mov.l .L_4_PTEH, r0 + mov.l r7, @r0 + mova 2f, r0 + jmp @r0 /* run P1 */ + nop + .align 2 +2: rts /* mova target must be 4byte alignment */ + nop + .align 2 +.L_UPTE__sh4: .long P_MD_UPTE +.L_4_PTEH: .long SH4_PTEH +.L_4_UTLB_AA_A: .long (SH4_UTLB_AA | SH4_UTLB_A) +.L_4_ITLB_AA: .long SH4_ITLB_AA +.L_VPN_MASK: .long 0xfffff000 +.L_P2BASE: .long 0xa0000000 + SET_ENTRY_SIZE(sh4_switch_resume) +#endif /* SH4 */ + + +/* + * LINTSTUB: Func: int _cpu_intr_raise(int s) + * raise SR.IMASK to 's'. if current SR.IMASK is greater equal 's', + * nothing to do. returns previous SR.IMASK. + */ +NENTRY(_cpu_intr_raise) + stc sr, r2 + mov #0x78, r1 + mov r2, r0 + shll r1 /* r1 = 0xf0 */ + and r1, r0 /* r0 = SR & 0xf0 */ + cmp/ge r4, r0 /* r0 >= r4 ? T = 1 */ + bt/s 1f + not r1, r1 /* r1 = 0xffffff0f */ + and r1, r2 /* r2 = SR & ~0xf0 */ + or r2, r4 /* r4 = (SR & ~0xf0) | s */ + ldc r4, sr /* SR = r4 (don't move to delay slot) */ +1: rts + nop /* return (SR & 0xf0) */ + SET_ENTRY_SIZE(_cpu_intr_raise) + + +/* + * LINTSTUB: Func: int _cpu_intr_suspend(void) + * Mask all external interrupt. Returns previous SR.IMASK. + */ +NENTRY(_cpu_intr_suspend) + stc sr, r0 /* r0 = SR */ + mov #0x78, r1 + shll r1 /* r1 = 0x000000f0 */ + mov r0, r2 /* r2 = SR */ + or r1, r2 /* r2 |= 0x000000f0 */ + ldc r2, sr /* SR = r2 */ + rts + and r1, r0 /* r0 = SR & 0x000000f0 */ + SET_ENTRY_SIZE(_cpu_intr_suspend) + + + +/* + * LINTSTUB: Func: int _cpu_intr_resume(int s) + * Set 's' to SR.IMASK. Returns previous SR.IMASK. + */ +NENTRY(_cpu_intr_resume) + stc sr, r0 /* r0 = SR */ + mov #0x78, r2 + shll r2 /* r2 = 0x000000f0 */ + not r2, r1 /* r1 = 0xffffff0f */ + and r0, r1 /* r1 = (SR & ~0xf0) */ + or r1, r4 /* r4 = (SR & ~0xf0) | level */ + ldc r4, sr /* SR = r0 (don't move to delay slot) */ + rts + and r2, r0 /* return (SR & 0xf0) */ + SET_ENTRY_SIZE(_cpu_intr_resume) + + +/* + * LINTSTUB: Func: int _cpu_exception_suspend(void) + * Block exception (SR.BL). if external interrupt raise, pending interrupt. + * if exception occur, jump to 0xa0000000 (hard reset). + */ +NENTRY(_cpu_exception_suspend) + stc sr, r0 /* r0 = SR */ + mov #0x10, r1 + swap.b r1, r1 + mov r0, r2 /* r2 = r0 */ + swap.w r1, r1 /* r1 = 0x10000000 */ + or r1, r2 /* r2 |= 0x10000000 */ + ldc r2, sr /* SR = r2 */ + rts + and r1, r0 /* r0 &= 0x10000000 */ + SET_ENTRY_SIZE(_cpu_exception_suspend) + + +/* + * LINTSTUB: Func: void _cpu_exception_resume(int s) + * restore 's' exception mask. (SR.BL) + */ +NENTRY(_cpu_exception_resume) + stc sr, r0 /* r0 = SR */ + mov #0x10, r1 + swap.b r1, r1 + swap.w r1, r1 + not r1, r1 /* r1 = ~0x10000000 */ + and r1, r0 /* r0 &= ~0x10000000 */ + or r4, r0 /* r0 |= old SR.BL */ + ldc r0, sr /* SR = r0 (don't move to delay slot) */ + rts + nop + SET_ENTRY_SIZE(_cpu_exception_resume) + + +/* + * LINTSTUB: Func: void _cpu_spin(uint32_t count) + * Loop for 'count' * 10 cycles. + * [...] + * add IF ID EX MA WB + * nop IF ID EX MA WB + * cmp/pl IF ID EX MA WB - - + * nop IF ID EX MA - - WB + * bt IF ID EX . . MA WB + * nop IF ID - - EX MA WB + * nop IF - - ID EX MA WB + * nop - - - IF ID EX MA WB + * add IF ID EX MA WB + * nop IF ID EX MA WB + * cmp/pl IF ID EX MA WB - - + * nop IF ID EX MA - - WB + * bt IF ID EX . . MA + * [...] + */ + .align 5 /* align cache line size (32B) */ +NENTRY(_cpu_spin) +1: nop /* 1 */ + nop /* 2 */ + nop /* 3 */ + add #-1, r4 /* 4 */ + nop /* 5 */ + cmp/pl r4 /* 6 */ + nop /* 7 */ + bt 1b /* 8, 9, 10 */ + rts + nop + SET_ENTRY_SIZE(_cpu_spin) + + +/* + * proc_trapmpoline: + * Call the service function with one argument specified by the r12 and r11 + * respectively. set by cpu_fork(). + */ +NENTRY(proc_trampoline) + jsr @r12 + mov r11, r4 + __EXCEPTION_RETURN + /* NOTREACHED */ + SET_ENTRY_SIZE(proc_trampoline) + + +/* + * LINTSTUB: Var: char sigcode[1] + * Signal trampoline. + * + * The kernel arranges for the signal handler to be invoked directly. + * This trampoline is used only to perform the return. + * + * On entry, the stack looks like this: + * + * sp-> sigcontext structure + */ +NENTRY(sigcode) + mov r15, r4 /* get pointer to sigcontext */ + mov.l .L_SYS_sigreturn, r0 + trapa #0x80 /* and call sigreturn() */ + mov.l .L_SYS_exit, r0 + trapa #0x80 /* exit if sigreturn fails */ + /* NOTREACHED */ + + .align 2 +.L_SYS_sigreturn: .long SYS_sigreturn +.L_SYS_exit: .long SYS_exit + +/* LINTSTUB: Var: char esigcode[1] */ +.globl _C_LABEL(esigcode) +_C_LABEL(esigcode): + SET_ENTRY_SIZE(sigcode) + +/* + * LINTSTUB: Func: void savectx(struct pcb *pcb) + * save struct switchframe. + */ +ENTRY(savectx) + add #SF_SIZE, r4 + stc.l r7_bank,@-r4 + stc.l sr, @-r4 + stc.l r6_bank,@-r4 + sts.l pr, @-r4 + mov.l r8, @-r4 + mov.l r9, @-r4 + mov.l r10, @-r4 + mov.l r11, @-r4 + mov.l r12, @-r4 + mov.l r13, @-r4 + mov.l r14, @-r4 + rts + mov.l r15, @-r4 + SET_ENTRY_SIZE(savectx) + + +/* + * LINTSTUB: Func: int copyout(const void *ksrc, void *udst, size_t len) + * Copy len bytes into the user address space. + */ +ENTRY(copyout) + mov.l r14, @-r15 + sts.l pr, @-r15 + mov r15, r14 + + mov #EFAULT, r0 /* assume there was a problem */ + mov r4, r3 + mov r5, r2 + mov r5, r4 + add r6, r2 + cmp/hs r5, r2 /* bomb if uaddr+len wraps */ + bf 2f + mov.l .L_copyout_VM_MAXUSER_ADDRESS, r1 + cmp/hi r1, r2 /* bomb if uaddr isn't in user space */ + bt 2f + + mov.l .L_copyout_curpcb, r1 /* set fault hander */ + mov.l @r1, r2 + mov.l .L_copyout_onfault, r1 + mov.l r1, @(PCB_ONFAULT,r2) + mov.l .L_copyout_memcpy, r1 + jsr @r1 /* memcpy(uaddr, kaddr, len) */ + mov r3, r5 + + mov #0, r0 +1: + mov.l .L_copyout_curpcb, r1 /* clear fault handler */ + mov.l @r1, r2 + mov #0, r1 + mov.l r1, @(PCB_ONFAULT,r2) +2: + mov r14, r15 + lds.l @r15+, pr + rts + mov.l @r15+, r14 + +3: + bra 1b + mov #EFAULT, r0 + + .align 2 +.L_copyout_onfault: + .long 3b +.L_copyout_VM_MAXUSER_ADDRESS: + .long VM_MAXUSER_ADDRESS +.L_copyout_curpcb: + .long _C_LABEL(curpcb) +.L_copyout_memcpy: + .long _C_LABEL(memcpy) + SET_ENTRY_SIZE(copyout) + + +/* + * LINTSTUB: Func: int copyin(const void *usrc, void *kdst, size_t len) + * Copy len bytes from the user address space. + */ +ENTRY(copyin) + mov.l r14, @-r15 + sts.l pr, @-r15 + mov r15, r14 + + mov #EFAULT, r0 /* assume there was a problem */ + mov r4, r3 + mov r5, r4 + mov r3, r2 + add r6, r2 + cmp/hs r3, r2 /* bomb if uaddr+len wraps */ + bf 2f + mov.l .L_copyin_VM_MAXUSER_ADDRESS, r1 + cmp/hi r1, r2 /* bomb if uaddr isn't in user space */ + bt 2f + + mov.l .L_copyin_curpcb, r1 /* set fault hander */ + mov.l @r1, r2 + mov.l .L_copyin_onfault, r1 + mov.l r1, @(PCB_ONFAULT,r2) + mov.l .L_copyin_memcpy, r1 + jsr @r1 /* memcpy(kaddr, uaddr, len) */ + mov r3, r5 + + mov #0, r0 +1: + mov.l .L_copyin_curpcb, r1 /* clear fault hander */ + mov.l @r1, r2 + mov #0, r1 + mov.l r1, @(PCB_ONFAULT,r2) +2: + mov r14, r15 + lds.l @r15+, pr + rts + mov.l @r15+, r14 + +3: + bra 1b + mov #EFAULT, r0 + + .align 2 +.L_copyin_onfault: + .long 3b +.L_copyin_VM_MAXUSER_ADDRESS: + .long VM_MAXUSER_ADDRESS +.L_copyin_curpcb: + .long _C_LABEL(curpcb) +.L_copyin_memcpy: + .long _C_LABEL(memcpy) + SET_ENTRY_SIZE(copyin) + + +/* + * LINTSTUB: Func: int copyoutstr(const void *ksrc, void *udst, size_t maxlen, size_t *lencopied) + * Copy a NUL-terminated string, at most maxlen characters long, + * into the user address space. Return the number of characters + * copied (including the NUL) in *lencopied. If the string is + * too long, return ENAMETOOLONG; else return 0 or EFAULT. + */ +ENTRY(copyoutstr) + mov.l r8, @-r15 + + mov #EFAULT, r3 /* assume there was a problem */ + mov r4, r8 + mov.l .L_copyoutstr_curpcb, r1 /* set fault handler */ + mov.l @r1, r2 + mov.l .L_copyoutstr_onfault, r1 + mov.l r1, @(PCB_ONFAULT,r2) + mov.l .L_copyoutstr_VM_MAXUSER_ADDRESS, r1 + mov r1, r0 + sub r5, r0 + cmp/hi r6, r0 /* don't beyond user space */ + bf 2f + bra 2f + mov r6, r0 + + .align 2 +1: + mov.b @r4+, r1 /* copy str */ + mov.b r1, @r5 + extu.b r1, r1 + add #1, r5 + tst r1, r1 + bf 2f + bra 3f + mov #0, r3 + .align 2 +2: + add #-1, r0 + cmp/eq #-1, r0 + bf 1b + mov.l .L_copyoutstr_VM_MAXUSER_ADDRESS, r1 + cmp/hs r1, r5 + bt 3f + mov #ENAMETOOLONG, r3 + +3: + tst r7, r7 /* set lencopied if needed */ + bt 4f + mov r4, r1 + sub r8, r1 + mov.l r1, @r7 +4: + mov.l .L_copyoutstr_curpcb, r1 /* clear fault handler */ + mov.l @r1, r2 + mov #0, r1 + mov.l r1, @(PCB_ONFAULT,r2) + + mov r3, r0 + rts + mov.l @r15+, r8 + +5: + bra 4b + mov #EFAULT, r3 + + .align 2 +.L_copyoutstr_onfault: + .long 5b +.L_copyoutstr_VM_MAXUSER_ADDRESS: + .long VM_MAXUSER_ADDRESS +.L_copyoutstr_curpcb: + .long _C_LABEL(curpcb) + SET_ENTRY_SIZE(copyoutstr) + + +/* + * LINTSTUB: Func: int copyinstr(const void *src, void *dst, size_t maxlen, size_t *lencopied) + * Copy a NUL-terminated string, at most maxlen characters long, + * from the user address space. Return the number of characters + * copied (including the NUL) in *lencopied. If the string is + * too long, return ENAMETOOLONG; else return 0 or EFAULT. + */ +ENTRY(copyinstr) + mov.l r8, @-r15 + mov #EFAULT, r3 /* assume there was a problem */ + mov r4, r8 + mov.l .L_copyinstr_curpcb, r1 /* set fault handler */ + mov.l @r1, r2 + mov.l .L_copyinstr_onfault, r1 + mov.l r1, @(PCB_ONFAULT,r2) + + mov.l .L_copyinstr_VM_MAXUSER_ADDRESS, r1 + mov r1, r0 + sub r5, r0 + cmp/hi r6, r0 /* don't beyond user space */ + bf 2f + bra 2f + mov r6, r0 + + .align 2 +1: + mov.b @r4+, r1 /* copy str */ + mov.b r1, @r5 + extu.b r1, r1 + add #1, r5 + tst r1, r1 + bf 2f + bra 3f + mov #0, r3 + .align 2 +2: + add #-1, r0 + cmp/eq #-1, r0 + bf 1b + mov.l .L_copyinstr_VM_MAXUSER_ADDRESS, r1 + cmp/hs r1, r5 + bt 3f + mov #ENAMETOOLONG, r3 + +3: + tst r7, r7 /* set lencopied if needed */ + bt 4f + mov r4, r1 + sub r8, r1 + mov.l r1, @r7 +4: + mov.l .L_copyinstr_curpcb, r1 /* clear fault handler */ + mov.l @r1, r2 + mov #0, r1 + mov.l r1, @(PCB_ONFAULT,r2) + + mov r3, r0 + rts + mov.l @r15+, r8 + +5: + bra 4b + mov #EFAULT, r3 + + .align 2 +.L_copyinstr_onfault: + .long 5b +.L_copyinstr_VM_MAXUSER_ADDRESS: + .long VM_MAXUSER_ADDRESS +.L_copyinstr_curpcb: + .long _C_LABEL(curpcb) + SET_ENTRY_SIZE(copyinstr) + +/* + * LINTSTUB: Func: int kcopy(const void *src, void *dst, size_t len) + */ +ENTRY(kcopy) + mov.l r8, @-r15 + mov.l r14, @-r15 + sts.l pr, @-r15 + mov r15, r14 + + mov r4, r3 + mov.l .L_kcopy_curpcb, r1 + mov.l @r1, r2 + mov.l @(PCB_ONFAULT,r2) ,r8 /* save old fault handler */ + mov.l .L_kcopy_onfault, r1 + mov.l r1, @(PCB_ONFAULT,r2) /* set fault handler */ + mov.l .L_kcopy_memcpy, r1 + mov r5, r4 + jsr @r1 /* memcpy(dst, src, len) */ + mov r3, r5 + mov #0, r0 +1: + mov.l .L_kcopy_curpcb, r1 /* restore fault handler */ + mov.l @r1, r2 + mov.l r8, @(PCB_ONFAULT,r2) + + mov r14, r15 + lds.l @r15+, pr + mov.l @r15+, r14 + rts + mov.l @r15+, r8 + +2: + bra 1b + mov #EFAULT, r0 + + .align 2 +.L_kcopy_onfault: + .long 2b +.L_kcopy_curpcb: + .long _C_LABEL(curpcb) +.L_kcopy_memcpy: + .long _C_LABEL(memcpy) + SET_ENTRY_SIZE(kcopy) + + +#if defined(DDB) + +/* + * LINTSTUB: Func: int setjmp(label_t *jmpbuf) + */ +ENTRY(setjmp) + add #4*9, r4 + mov.l r8, @-r4 + mov.l r9, @-r4 + mov.l r10, @-r4 + mov.l r11, @-r4 + mov.l r12, @-r4 + mov.l r13, @-r4 + mov.l r14, @-r4 + mov.l r15, @-r4 + sts.l pr, @-r4 + rts + xor r0, r0 + SET_ENTRY_SIZE(setjmp) + +/* + * LINTSTUB: Func: void longjmp(label_t *jmpbuf) + */ +ENTRY(longjmp) + lds.l @r4+, pr + mov.l @r4+, r15 + mov.l @r4+, r14 + mov.l @r4+, r13 + mov.l @r4+, r12 + mov.l @r4+, r11 + mov.l @r4+, r10 + mov.l @r4+, r9 + mov.l @r4+, r8 + rts + mov #1, r0 /* return 1 from setjmp */ + SET_ENTRY_SIZE(longjmp) + +#endif /* DDB */ diff --git a/sys/arch/sh/sh/mem.c b/sys/arch/sh/sh/mem.c new file mode 100644 index 00000000000..26055857312 --- /dev/null +++ b/sys/arch/sh/sh/mem.c @@ -0,0 +1,260 @@ +/* $OpenBSD: mem.c,v 1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: mem.c,v 1.21 2006/07/23 22:06:07 ad Exp $ */ + +/* + * Copyright (c) 2002 The NetBSD Foundation, Inc. + * All rights reserved. + * Copyright (c) 1982, 1986, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the Systems Programming Group of the University of Utah Computer + * Science Department. + * + * 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. 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. + * + * @(#)mem.c 8.3 (Berkeley) 1/12/94 + */ + +/* + * Copyright (c) 1988 University of Utah. + * + * This code is derived from software contributed to Berkeley by + * the Systems Programming Group of the University of Utah Computer + * Science Department. + * + * 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. + * + * @(#)mem.c 8.3 (Berkeley) 1/12/94 + */ + +/* + * Memory special file + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/buf.h> +#include <sys/uio.h> +#include <sys/malloc.h> +#include <sys/proc.h> +#include <sys/conf.h> + +#include <uvm/uvm_extern.h> + +caddr_t zeropage; +boolean_t __mm_mem_addr(paddr_t); + +#define mmread mmrw +#define mmwrite mmrw +cdev_decl(mm); + +#define DEV_MEM 0 +#define DEV_KMEM 1 +#define DEV_NULL 2 +#define DEV_ZERO 12 + +/* ARGSUSED */ +int +mmopen(dev_t dev, int flag, int mode, struct proc *p) +{ + switch (minor(dev)) { + case DEV_MEM: + case DEV_KMEM: + case DEV_NULL: + case DEV_ZERO: + break; + default: + return (ENXIO); + } + + return (0); +} + +/*ARGSUSED*/ +int +mmclose(dev_t dev, int flag, int mode, struct proc *p) +{ + return (0); +} + +/*ARGSUSED*/ +int +mmrw(dev_t dev, struct uio *uio, int flags) +{ + struct iovec *iov; + vaddr_t v, o; + int c; + int error = 0; + + while (uio->uio_resid > 0 && !error) { + iov = uio->uio_iov; + if (iov->iov_len == 0) { + uio->uio_iov++; + uio->uio_iovcnt--; + if (uio->uio_iovcnt < 0) + panic("mmrw"); + continue; + } + + v = uio->uio_offset; + + switch (minor(dev)) { +kmemphys: + case DEV_MEM: + /* Physical address */ + if (__mm_mem_addr(v)) { + o = v & PGOFSET; + c = min(uio->uio_resid, (int)(PAGE_SIZE - o)); + error = uiomove((caddr_t)SH3_PHYS_TO_P1SEG(v), + c, uio); + } else { + return (EFAULT); + } + break; + + case DEV_KMEM: + /* P0 */ + if (v < SH3_P1SEG_BASE) + return (EFAULT); + /* P1 */ + if (v < SH3_P2SEG_BASE) { + v = SH3_P1SEG_TO_PHYS(v); + goto kmemphys; + } + /* P2 */ + if (v < SH3_P3SEG_BASE) + return (EFAULT); + /* P3 */ + c = min(iov->iov_len, MAXPHYS); + if (!uvm_kernacc((void *)v, c, + uio->uio_rw == UIO_READ ? B_READ : B_WRITE)) + return (EFAULT); + error = uiomove((caddr_t)v, c, uio); + break; + + case DEV_NULL: + if (uio->uio_rw == UIO_WRITE) + uio->uio_resid = 0; + return (0); + + case DEV_ZERO: + if (uio->uio_rw == UIO_WRITE) { + uio->uio_resid = 0; + return (0); + } + if (zeropage == NULL) { + zeropage = malloc(PAGE_SIZE, M_TEMP, M_WAITOK); + memset(zeropage, 0, PAGE_SIZE); + } + c = min(iov->iov_len, PAGE_SIZE); + error = uiomove(zeropage, c, uio); + break; + + default: + return (ENXIO); + } + } + + return (error); +} + +/*ARGSUSED*/ +paddr_t +mmmmap(dev_t dev, off_t off, int prot) +{ + struct proc *p = curproc; + + if (minor(dev) != DEV_MEM) + return (-1); + + if (__mm_mem_addr((paddr_t)off) == FALSE && suser(p, 0) != 0) + return (-1); + return (atop((paddr_t)off)); +} + +/*ARGSUSED*/ +int +mmioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p) +{ + return (EOPNOTSUPP); +} + +/* + * boolean_t __mm_mem_addr(paddr_t pa): + * Check specified physical address is in physical memory, with the + * kernel image off-limits. + */ +boolean_t +__mm_mem_addr(paddr_t pa) +{ + extern vaddr_t kernend; /* from machdep.c */ + struct vm_physseg *seg; + unsigned int segno; + + for (segno = 0, seg = vm_physmem; segno < vm_nphysseg; segno++, seg++) { + if (pa < seg->start || pa >= seg->end) + continue; + + /* + * This assumes the kernel image occupies the beginning of a + * memory segment. + */ + if (kernend >= seg->start && kernend < seg->end) { + if (pa < kernend) + return (FALSE); + } + + return (TRUE); + } + + return (FALSE); +} diff --git a/sys/arch/sh/sh/mmu.c b/sys/arch/sh/sh/mmu.c new file mode 100644 index 00000000000..cd093d9b73c --- /dev/null +++ b/sys/arch/sh/sh/mmu.c @@ -0,0 +1,110 @@ +/* $OpenBSD: mmu.c,v 1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: mmu.c,v 1.15 2006/02/12 02:30:55 uwe Exp $ */ + +/*- + * Copyright (c) 2002 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by UCHIYAMA Yasushi. + * + * 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. + */ + +#include <sys/param.h> +#include <sys/systm.h> + +#include <sh/mmu.h> +#include <sh/mmu_sh3.h> +#include <sh/mmu_sh4.h> + +#if defined(SH3) && defined(SH4) +void (*__sh_mmu_start)(void); +void (*__sh_tlb_invalidate_addr)(int, vaddr_t); +void (*__sh_tlb_invalidate_asid)(int); +void (*__sh_tlb_invalidate_all)(void); +void (*__sh_tlb_update)(int, vaddr_t, uint32_t); +#endif /* SH3 && SH4 */ + +void +sh_mmu_init(void) +{ + /* + * Assign function hooks but only if both SH3 and SH4 are defined. + * They are called directly otherwise. See <sh3/mmu.h>. + */ +#if defined(SH3) && defined(SH4) + if (CPU_IS_SH3) { + __sh_mmu_start = sh3_mmu_start; + __sh_tlb_invalidate_addr = sh3_tlb_invalidate_addr; + __sh_tlb_invalidate_asid = sh3_tlb_invalidate_asid; + __sh_tlb_invalidate_all = sh3_tlb_invalidate_all; + __sh_tlb_update = sh3_tlb_update; + } + else if (CPU_IS_SH4) { + __sh_mmu_start = sh4_mmu_start; + __sh_tlb_invalidate_addr = sh4_tlb_invalidate_addr; + __sh_tlb_invalidate_asid = sh4_tlb_invalidate_asid; + __sh_tlb_invalidate_all = sh4_tlb_invalidate_all; + __sh_tlb_update = sh4_tlb_update; + } +#endif /* SH3 && SH4 */ +} + +void +sh_mmu_information(void) +{ + uint32_t r; +#ifdef SH3 + if (CPU_IS_SH3) { + printf("cpu0: 4-way set-associative 128 TLB entries\n"); + r = _reg_read_4(SH3_MMUCR); + printf("cpu0: %s mode, %s virtual storage mode\n", + r & SH3_MMUCR_IX ? "ASID+VPN" : "VPN", + r & SH3_MMUCR_SV ? "single" : "multiple"); + } +#endif +#ifdef SH4 + if (CPU_IS_SH4) { + printf("cpu0: full-associative 4 ITLB, 64 UTLB entries\n"); + r = _reg_read_4(SH4_MMUCR); + printf("cpu0: %s virtual storage mode, SQ access: kernel%s, ", + r & SH3_MMUCR_SV ? "single" : "multiple", + r & SH4_MMUCR_SQMD ? "" : "/user"); + printf("wired %d\n", + (r & SH4_MMUCR_URB_MASK) >> SH4_MMUCR_URB_SHIFT); + } +#endif +} + +void +sh_tlb_set_asid(int asid) +{ + _reg_write_4(SH_(PTEH), asid); +} diff --git a/sys/arch/sh/sh/mmu_sh3.c b/sys/arch/sh/sh/mmu_sh3.c new file mode 100644 index 00000000000..c5b9f814a8b --- /dev/null +++ b/sys/arch/sh/sh/mmu_sh3.c @@ -0,0 +1,136 @@ +/* $OpenBSD: mmu_sh3.c,v 1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: mmu_sh3.c,v 1.11 2006/03/04 01:13:35 uwe Exp $ */ + +/*- + * Copyright (c) 2002 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by UCHIYAMA Yasushi. + * + * 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. + */ + +#include <sys/param.h> +#include <sys/systm.h> + +#include <sh/pte.h> /* OpenBSD/sh specific PTE */ +#include <sh/mmu.h> +#include <sh/mmu_sh3.h> + +void +sh3_mmu_start() +{ + /* Zero clear all TLB entry */ + sh3_tlb_invalidate_all(); + + /* Set current ASID to 0 */ + sh_tlb_set_asid(0); + + _reg_write_4(SH3_MMUCR, SH3_MMUCR_AT | SH3_MMUCR_TF); +} + +void +sh3_tlb_invalidate_addr(int asid, vaddr_t va) +{ + uint32_t a, d; + int w; + + d = (va & SH3_MMUAA_D_VPN_MASK_4K) | asid; /* 4K page */ + va = va & SH3_MMU_VPN_MASK; /* [16:12] entry index */ + + /* Probe entry and invalidate it. */ + for (w = 0; w < SH3_MMU_WAY; w++) { + a = va | (w << SH3_MMU_WAY_SHIFT); /* way [9:8] */ + if ((_reg_read_4(SH3_MMUAA | a) & + (SH3_MMUAA_D_VPN_MASK_4K | SH3_MMUAA_D_ASID_MASK)) == d) { + _reg_write_4(SH3_MMUAA | a, 0); + break; + } + } +} + +void +sh3_tlb_invalidate_asid(int asid) +{ + uint32_t aw, a; + int e, w; + + /* Invalidate entry attribute to ASID */ + for (w = 0; w < SH3_MMU_WAY; w++) { + aw = (w << SH3_MMU_WAY_SHIFT); + for (e = 0; e < SH3_MMU_ENTRY; e++) { + a = aw | (e << SH3_MMU_VPN_SHIFT); + if ((_reg_read_4(SH3_MMUAA | a) & + SH3_MMUAA_D_ASID_MASK) == asid) { + _reg_write_4(SH3_MMUAA | a, 0); + } + } + } +} + +void +sh3_tlb_invalidate_all() +{ + uint32_t aw, a; + int e, w; + + /* Zero clear all TLB entry to avoid unexpected VPN match. */ + for (w = 0; w < SH3_MMU_WAY; w++) { + aw = (w << SH3_MMU_WAY_SHIFT); + for (e = 0; e < SH3_MMU_ENTRY; e++) { + a = aw | (e << SH3_MMU_VPN_SHIFT); + _reg_write_4(SH3_MMUAA | a, 0); + _reg_write_4(SH3_MMUDA | a, 0); + } + } +} + +void +sh3_tlb_update(int asid, vaddr_t va, uint32_t pte) +{ + uint32_t oasid; + + KDASSERT(asid < 0x100 && (pte & ~PGOFSET) != 0 && va != 0); + + /* Save old ASID */ + oasid = _reg_read_4(SH3_PTEH) & SH3_PTEH_ASID_MASK; + + /* Invalidate old entry (if any) */ + sh3_tlb_invalidate_addr(asid, va); + + /* Load new entry */ + _reg_write_4(SH3_PTEH, (va & ~PGOFSET) | asid); + _reg_write_4(SH3_PTEL, pte & PG_HW_BITS); + __asm volatile("ldtlb"); + + /* Restore old ASID */ + if (asid != oasid) + _reg_write_4(SH3_PTEH, oasid); +} diff --git a/sys/arch/sh/sh/mmu_sh4.c b/sys/arch/sh/sh/mmu_sh4.c new file mode 100644 index 00000000000..873534ff9d5 --- /dev/null +++ b/sys/arch/sh/sh/mmu_sh4.c @@ -0,0 +1,184 @@ +/* $OpenBSD: mmu_sh4.c,v 1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: mmu_sh4.c,v 1.11 2006/03/04 01:13:35 uwe Exp $ */ + +/*- + * Copyright (c) 2002 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by UCHIYAMA Yasushi. + * + * 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. + */ + +#include <sys/param.h> +#include <sys/systm.h> + +#include <sh/pte.h> /* OpenBSD/sh specific PTE */ +#include <sh/mmu.h> +#include <sh/mmu_sh4.h> + +#define SH4_MMU_HAZARD __asm volatile("nop;nop;nop;nop;nop;nop;nop;nop;") + +static inline void __sh4_itlb_invalidate_all(void); + +static inline void +__sh4_itlb_invalidate_all() +{ + _reg_write_4(SH4_ITLB_AA, 0); + _reg_write_4(SH4_ITLB_AA | (1 << SH4_ITLB_E_SHIFT), 0); + _reg_write_4(SH4_ITLB_AA | (2 << SH4_ITLB_E_SHIFT), 0); + _reg_write_4(SH4_ITLB_AA | (3 << SH4_ITLB_E_SHIFT), 0); +} + +void +sh4_mmu_start() +{ + /* Zero clear all TLB entry */ + _reg_write_4(SH4_MMUCR, 0); /* zero wired entry */ + sh_tlb_invalidate_all(); + + /* Set current ASID to 0 */ + sh_tlb_set_asid(0); + + /* + * User can't access store queue + * make wired entry for u-area. + */ + _reg_write_4(SH4_MMUCR, SH4_MMUCR_AT | SH4_MMUCR_TI | SH4_MMUCR_SQMD | + (SH4_UTLB_ENTRY - UPAGES) << SH4_MMUCR_URB_SHIFT); + + SH4_MMU_HAZARD; +} + +void +sh4_tlb_invalidate_addr(int asid, vaddr_t va) +{ + uint32_t pteh; + int s; + + va &= SH4_PTEH_VPN_MASK; + s = _cpu_exception_suspend(); + + /* Save current ASID */ + pteh = _reg_read_4(SH4_PTEH); + /* Set ASID for associative write */ + _reg_write_4(SH4_PTEH, asid); + + /* Associative write(UTLB/ITLB). not required ITLB invalidate. */ + RUN_P2; + _reg_write_4(SH4_UTLB_AA | SH4_UTLB_A, va); /* Clear D, V */ + RUN_P1; + /* Restore ASID */ + _reg_write_4(SH4_PTEH, pteh); + + _cpu_exception_resume(s); +} + +void +sh4_tlb_invalidate_asid(int asid) +{ + uint32_t a; + int e, s; + + s = _cpu_exception_suspend(); + /* Invalidate entry attribute to ASID */ + RUN_P2; + for (e = 0; e < SH4_UTLB_ENTRY; e++) { + a = SH4_UTLB_AA | (e << SH4_UTLB_E_SHIFT); + if ((_reg_read_4(a) & SH4_UTLB_AA_ASID_MASK) == asid) + _reg_write_4(a, 0); + } + + __sh4_itlb_invalidate_all(); + RUN_P1; + _cpu_exception_resume(s); +} + +void +sh4_tlb_invalidate_all() +{ + uint32_t a; + int e, eend, s; + + s = _cpu_exception_suspend(); + /* If non-wired entry limit is zero, clear all entry. */ + a = _reg_read_4(SH4_MMUCR) & SH4_MMUCR_URB_MASK; + eend = a ? (a >> SH4_MMUCR_URB_SHIFT) : SH4_UTLB_ENTRY; + + RUN_P2; + for (e = 0; e < eend; e++) { + a = SH4_UTLB_AA | (e << SH4_UTLB_E_SHIFT); + _reg_write_4(a, 0); + a = SH4_UTLB_DA1 | (e << SH4_UTLB_E_SHIFT); + _reg_write_4(a, 0); + } + __sh4_itlb_invalidate_all(); + _reg_write_4(SH4_ITLB_DA1, 0); + _reg_write_4(SH4_ITLB_DA1 | (1 << SH4_ITLB_E_SHIFT), 0); + _reg_write_4(SH4_ITLB_DA1 | (2 << SH4_ITLB_E_SHIFT), 0); + _reg_write_4(SH4_ITLB_DA1 | (3 << SH4_ITLB_E_SHIFT), 0); + RUN_P1; + _cpu_exception_resume(s); +} + +void +sh4_tlb_update(int asid, vaddr_t va, uint32_t pte) +{ + uint32_t oasid; + uint32_t ptel; + int s; + + KDASSERT(asid < 0x100 && (pte & ~PGOFSET) != 0 && va != 0); + + s = _cpu_exception_suspend(); + /* Save old ASID */ + oasid = _reg_read_4(SH4_PTEH) & SH4_PTEH_ASID_MASK; + + /* Invalidate old entry (if any) */ + sh4_tlb_invalidate_addr(asid, va); + + _reg_write_4(SH4_PTEH, asid); + /* Load new entry */ + _reg_write_4(SH4_PTEH, (va & ~PGOFSET) | asid); + ptel = pte & PG_HW_BITS; + if (pte & _PG_PCMCIA) { + _reg_write_4(SH4_PTEA, + (pte >> _PG_PCMCIA_SHIFT) & SH4_PTEA_SA_MASK); + } else { + _reg_write_4(SH4_PTEA, 0); + } + _reg_write_4(SH4_PTEL, ptel); + __asm volatile("ldtlb; nop"); + + /* Restore old ASID */ + if (asid != oasid) + _reg_write_4(SH4_PTEH, oasid); + _cpu_exception_resume(s); +} diff --git a/sys/arch/sh/sh/pmap.c b/sys/arch/sh/sh/pmap.c new file mode 100644 index 00000000000..3f432895bb7 --- /dev/null +++ b/sys/arch/sh/sh/pmap.c @@ -0,0 +1,1029 @@ +/* $OpenBSD: pmap.c,v 1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: pmap.c,v 1.55 2006/08/07 23:19:36 tsutsui Exp $ */ + +/*- + * Copyright (c) 2002 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by UCHIYAMA Yasushi. + * + * 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. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/pool.h> +#include <sys/msgbuf.h> + +#include <uvm/uvm.h> + +#include <sh/mmu.h> +#include <sh/cache.h> + +#ifdef DEBUG +#define STATIC +#else +#define STATIC static +#endif + +#define __PMAP_PTP_SHIFT 22 +#define __PMAP_PTP_TRUNC(va) \ + (((va) + (1 << __PMAP_PTP_SHIFT) - 1) & ~((1 << __PMAP_PTP_SHIFT) - 1)) +#define __PMAP_PTP_PG_N (PAGE_SIZE / sizeof(pt_entry_t)) +#define __PMAP_PTP_INDEX(va) (((va) >> __PMAP_PTP_SHIFT) & (__PMAP_PTP_N - 1)) +#define __PMAP_PTP_OFSET(va) ((va >> PGSHIFT) & (__PMAP_PTP_PG_N - 1)) + +struct pmap __pmap_kernel; +STATIC vaddr_t __pmap_kve; /* VA of last kernel virtual */ +paddr_t avail_start; /* PA of first available physical page */ +paddr_t avail_end; /* PA of last available physical page */ + +/* pmap pool */ +STATIC struct pool __pmap_pmap_pool; + +/* pv_entry ops. */ +struct pv_entry { + struct pmap *pv_pmap; + vaddr_t pv_va; + SLIST_ENTRY(pv_entry) pv_link; +}; +#define __pmap_pv_alloc() pool_get(&__pmap_pv_pool, PR_NOWAIT) +#define __pmap_pv_free(pv) pool_put(&__pmap_pv_pool, (pv)) +STATIC void __pmap_pv_enter(pmap_t, struct vm_page *, vaddr_t); +STATIC void __pmap_pv_remove(pmap_t, struct vm_page *, vaddr_t); +STATIC void *__pmap_pv_page_alloc(struct pool *, int); +STATIC void __pmap_pv_page_free(struct pool *, void *); +STATIC struct pool __pmap_pv_pool; +STATIC struct pool_allocator pmap_pv_page_allocator = { + __pmap_pv_page_alloc, __pmap_pv_page_free, 0, +}; + +/* ASID ops. */ +STATIC int __pmap_asid_alloc(void); +STATIC void __pmap_asid_free(int); +STATIC struct { + uint32_t map[8]; + int hint; /* hint for next allocation */ +} __pmap_asid; + +/* page table entry ops. */ +STATIC pt_entry_t *__pmap_pte_alloc(pmap_t, vaddr_t); + +/* pmap_enter util */ +STATIC boolean_t __pmap_map_change(pmap_t, vaddr_t, paddr_t, vm_prot_t, + pt_entry_t); + +void +pmap_bootstrap() +{ + /* Steal msgbuf area */ + initmsgbuf((caddr_t)uvm_pageboot_alloc(MSGBUFSIZE), MSGBUFSIZE); + + avail_start = ptoa(vm_physmem[0].start); + avail_end = ptoa(vm_physmem[vm_nphysseg - 1].end); + __pmap_kve = VM_MIN_KERNEL_ADDRESS; + + pmap_kernel()->pm_refcnt = 1; + pmap_kernel()->pm_ptp = (pt_entry_t **)uvm_pageboot_alloc(PAGE_SIZE); + memset(pmap_kernel()->pm_ptp, 0, PAGE_SIZE); + + /* Enable MMU */ + sh_mmu_start(); + /* Mask all interrupt */ + _cpu_intr_suspend(); + /* Enable exception for P3 access */ + _cpu_exception_resume(0); +} + +vaddr_t +pmap_steal_memory(vsize_t size, vaddr_t *vstart, vaddr_t *vend) +{ + struct vm_physseg *bank; + int i, j, npage; + paddr_t pa; + vaddr_t va; + + KDASSERT(!uvm.page_init_done); + + size = round_page(size); + npage = atop(size); + + for (i = 0, bank = &vm_physmem[i]; i < vm_nphysseg; i++, bank++) + if (npage <= bank->avail_end - bank->avail_start) + break; + KDASSERT(i != vm_nphysseg); + + /* Steal pages */ + pa = ptoa(bank->avail_start); + bank->avail_start += npage; + bank->start += npage; + + /* GC memory bank */ + if (bank->avail_start == bank->end) { + /* Remove this segment from the list. */ + vm_nphysseg--; + KDASSERT(vm_nphysseg > 0); + for (j = i; i < vm_nphysseg; j++) + vm_physmem[j] = vm_physmem[j + 1]; + } + + va = SH3_PHYS_TO_P1SEG(pa); + memset((caddr_t)va, 0, size); + + return (va); +} + +vaddr_t +pmap_growkernel(vaddr_t maxkvaddr) +{ + int i, n; + + if (maxkvaddr <= __pmap_kve) + return (__pmap_kve); + + i = __PMAP_PTP_INDEX(__pmap_kve - VM_MIN_KERNEL_ADDRESS); + __pmap_kve = __PMAP_PTP_TRUNC(maxkvaddr); + n = __PMAP_PTP_INDEX(__pmap_kve - VM_MIN_KERNEL_ADDRESS); + + /* Allocate page table pages */ + for (;i < n; i++) { + if (__pmap_kernel.pm_ptp[i] != NULL) + continue; + + if (uvm.page_init_done) { + struct vm_page *pg = uvm_pagealloc(NULL, 0, NULL, + UVM_PGA_USERESERVE | UVM_PGA_ZERO); + if (pg == NULL) + goto error; + __pmap_kernel.pm_ptp[i] = (pt_entry_t *) + SH3_PHYS_TO_P1SEG(VM_PAGE_TO_PHYS(pg)); + } else { + pt_entry_t *ptp = (pt_entry_t *) + uvm_pageboot_alloc(PAGE_SIZE); + if (ptp == NULL) + goto error; + __pmap_kernel.pm_ptp[i] = ptp; + memset(ptp, 0, PAGE_SIZE); + } + } + + return (__pmap_kve); + error: + panic("pmap_growkernel: out of memory."); + /* NOTREACHED */ +} + +void +pmap_virtual_space(vaddr_t *start, vaddr_t *end) +{ + *start = VM_MIN_KERNEL_ADDRESS; + *end = VM_MAX_KERNEL_ADDRESS; +} + +void +pmap_init() +{ + /* Initialize pmap module */ + pool_init(&__pmap_pmap_pool, sizeof(struct pmap), 0, 0, 0, "pmappl", + &pool_allocator_nointr); + pool_init(&__pmap_pv_pool, sizeof(struct pv_entry), 0, 0, 0, "pvpl", + &pmap_pv_page_allocator); + pool_setlowat(&__pmap_pv_pool, 16); +} + +pmap_t +pmap_create() +{ + pmap_t pmap; + + pmap = pool_get(&__pmap_pmap_pool, PR_WAITOK); + memset(pmap, 0, sizeof(struct pmap)); + pmap->pm_asid = -1; + pmap->pm_refcnt = 1; + /* Allocate page table page holder (512 slot) */ + pmap->pm_ptp = (pt_entry_t **) + SH3_PHYS_TO_P1SEG(VM_PAGE_TO_PHYS( + uvm_pagealloc(NULL, 0, NULL, + UVM_PGA_USERESERVE | UVM_PGA_ZERO))); + + return (pmap); +} + +void +pmap_destroy(pmap_t pmap) +{ + int i; + + if (--pmap->pm_refcnt > 0) + return; + + /* Deallocate all page table page */ + for (i = 0; i < __PMAP_PTP_N; i++) { + vaddr_t va = (vaddr_t)pmap->pm_ptp[i]; + if (va == 0) + continue; +#ifdef DEBUG /* Check no mapping exists. */ + { + int j; + pt_entry_t *pte = (pt_entry_t *)va; + for (j = 0; j < __PMAP_PTP_PG_N; j++, pte++) + KDASSERT(*pte == 0); + } +#endif /* DEBUG */ + /* Purge cache entry for next use of this page. */ + if (SH_HAS_VIRTUAL_ALIAS) + sh_dcache_inv_range(va, PAGE_SIZE); + /* Free page table */ + uvm_pagefree(PHYS_TO_VM_PAGE(SH3_P1SEG_TO_PHYS(va))); + } + /* Deallocate page table page holder */ + if (SH_HAS_VIRTUAL_ALIAS) + sh_dcache_inv_range((vaddr_t)pmap->pm_ptp, PAGE_SIZE); + uvm_pagefree(PHYS_TO_VM_PAGE(SH3_P1SEG_TO_PHYS((vaddr_t)pmap->pm_ptp))); + + /* Free ASID */ + __pmap_asid_free(pmap->pm_asid); + + pool_put(&__pmap_pmap_pool, pmap); +} + +void +pmap_reference(pmap_t pmap) +{ + pmap->pm_refcnt++; +} + +void +pmap_activate(struct proc *p) +{ + pmap_t pmap = p->p_vmspace->vm_map.pmap; + + if (pmap->pm_asid == -1) + pmap->pm_asid = __pmap_asid_alloc(); + + KDASSERT(pmap->pm_asid >=0 && pmap->pm_asid < 256); + sh_tlb_set_asid(pmap->pm_asid); +} + +int +pmap_enter(pmap_t pmap, vaddr_t va, paddr_t pa, vm_prot_t prot, int flags) +{ + struct vm_page *pg; + struct vm_page_md *pvh; + pt_entry_t entry, *pte; + boolean_t kva = (pmap == pmap_kernel()); + + /* "flags" never exceed "prot" */ + KDASSERT(prot != 0 && ((flags & VM_PROT_ALL) & ~prot) == 0); + + pg = PHYS_TO_VM_PAGE(pa); + entry = (pa & PG_PPN) | PG_4K; + if (flags & PMAP_WIRED) + entry |= _PG_WIRED; + + if (pg != NULL) { /* memory-space */ + pvh = &pg->mdpage; + entry |= PG_C; /* always cached */ + + /* Modified/reference tracking */ + if (flags & VM_PROT_WRITE) { + entry |= PG_V | PG_D; + pvh->pvh_flags |= PVH_MODIFIED | PVH_REFERENCED; + } else if (flags & VM_PROT_ALL) { + entry |= PG_V; + pvh->pvh_flags |= PVH_REFERENCED; + } + + /* Protection */ + if ((prot & VM_PROT_WRITE) && (pvh->pvh_flags & PVH_MODIFIED)) { + if (kva) + entry |= PG_PR_KRW | PG_SH; + else + entry |= PG_PR_URW; + } else { + /* RO, COW page */ + if (kva) + entry |= PG_PR_KRO | PG_SH; + else + entry |= PG_PR_URO; + } + + /* Check for existing mapping */ + if (__pmap_map_change(pmap, va, pa, prot, entry)) + return (0); + + /* Add to physical-virtual map list of this page */ + __pmap_pv_enter(pmap, pg, va); + + } else { /* bus-space (always uncached map) */ + if (kva) { + entry |= PG_V | PG_SH | + ((prot & VM_PROT_WRITE) ? + (PG_PR_KRW | PG_D) : PG_PR_KRO); + } else { + entry |= PG_V | + ((prot & VM_PROT_WRITE) ? + (PG_PR_URW | PG_D) : PG_PR_URO); + } + } + + /* Register to page table */ + if (kva) + pte = __pmap_kpte_lookup(va); + else { + pte = __pmap_pte_alloc(pmap, va); + if (pte == NULL) { + if (flags & PMAP_CANFAIL) + return ENOMEM; + panic("pmap_enter: cannot allocate pte"); + } + } + + *pte = entry; + + if (pmap->pm_asid != -1) + sh_tlb_update(pmap->pm_asid, va, entry); + + if (!SH_HAS_UNIFIED_CACHE && + (prot == (VM_PROT_READ | VM_PROT_EXECUTE))) + sh_icache_sync_range_index(va, PAGE_SIZE); + + if (entry & _PG_WIRED) + pmap->pm_stats.wired_count++; + pmap->pm_stats.resident_count++; + + return (0); +} + +/* + * boolean_t __pmap_map_change(pmap_t pmap, vaddr_t va, paddr_t pa, + * vm_prot_t prot, pt_entry_t entry): + * Handle the situation that pmap_enter() is called to enter a + * mapping at a virtual address for which a mapping already + * exists. + */ +boolean_t +__pmap_map_change(pmap_t pmap, vaddr_t va, paddr_t pa, vm_prot_t prot, + pt_entry_t entry) +{ + pt_entry_t *pte, oentry; + vaddr_t eva = va + PAGE_SIZE; + + if ((pte = __pmap_pte_lookup(pmap, va)) == NULL || + ((oentry = *pte) == 0)) + return (FALSE); /* no mapping exists. */ + + if (pa != (oentry & PG_PPN)) { + /* Enter a mapping at a mapping to another physical page. */ + pmap_remove(pmap, va, eva); + return (FALSE); + } + + /* Pre-existing mapping */ + + /* Protection change. */ + if ((oentry & PG_PR_MASK) != (entry & PG_PR_MASK)) + pmap_protect(pmap, va, eva, prot); + + /* Wired change */ + if (oentry & _PG_WIRED) { + if (!(entry & _PG_WIRED)) { + /* wired -> unwired */ + *pte = entry; + /* "wired" is software bits. no need to update TLB */ + pmap->pm_stats.wired_count--; + } + } else if (entry & _PG_WIRED) { + /* unwired -> wired. make sure to reflect "flags" */ + pmap_remove(pmap, va, eva); + return (FALSE); + } + + return (TRUE); /* mapping was changed. */ +} + +/* + * void __pmap_pv_enter(pmap_t pmap, struct vm_page *pg, vaddr_t vaddr): + * Insert physical-virtual map to vm_page. + * Assume pre-existed mapping is already removed. + */ +void +__pmap_pv_enter(pmap_t pmap, struct vm_page *pg, vaddr_t va) +{ + struct vm_page_md *pvh; + struct pv_entry *pv; + int s; + + s = splvm(); + if (SH_HAS_VIRTUAL_ALIAS) { + /* Remove all other mapping on this physical page */ + pvh = &pg->mdpage; + while ((pv = SLIST_FIRST(&pvh->pvh_head)) != NULL) { + pmap_remove(pv->pv_pmap, pv->pv_va, + pv->pv_va + PAGE_SIZE); + } + } + + /* Register pv map */ + pvh = &pg->mdpage; + pv = __pmap_pv_alloc(); + pv->pv_pmap = pmap; + pv->pv_va = va; + + SLIST_INSERT_HEAD(&pvh->pvh_head, pv, pv_link); + splx(s); +} + +void +pmap_remove(pmap_t pmap, vaddr_t sva, vaddr_t eva) +{ + struct vm_page *pg; + pt_entry_t *pte, entry; + vaddr_t va; + + KDASSERT((sva & PGOFSET) == 0); + + for (va = sva; va < eva; va += PAGE_SIZE) { + if ((pte = __pmap_pte_lookup(pmap, va)) == NULL || + (entry = *pte) == 0) + continue; + + if ((pg = PHYS_TO_VM_PAGE(entry & PG_PPN)) != NULL) + __pmap_pv_remove(pmap, pg, va); + + if (entry & _PG_WIRED) + pmap->pm_stats.wired_count--; + pmap->pm_stats.resident_count--; + *pte = 0; + + /* + * When pmap->pm_asid == -1 (invalid ASID), old entry attribute + * to this pmap is already removed by pmap_activate(). + */ + if (pmap->pm_asid != -1) + sh_tlb_invalidate_addr(pmap->pm_asid, va); + } +} + +/* + * void __pmap_pv_remove(pmap_t pmap, struct vm_page *pg, vaddr_t vaddr): + * Remove physical-virtual map from vm_page. + */ +void +__pmap_pv_remove(pmap_t pmap, struct vm_page *pg, vaddr_t vaddr) +{ + struct vm_page_md *pvh; + struct pv_entry *pv; + int s; + + s = splvm(); + pvh = &pg->mdpage; + SLIST_FOREACH(pv, &pvh->pvh_head, pv_link) { + if (pv->pv_pmap == pmap && pv->pv_va == vaddr) { + if (SH_HAS_VIRTUAL_ALIAS || + (SH_HAS_WRITEBACK_CACHE && + (pg->mdpage.pvh_flags & PVH_MODIFIED))) { + /* + * Always use index ops. since I don't want to + * worry about address space. + */ + sh_dcache_wbinv_range_index + (pv->pv_va, PAGE_SIZE); + } + + SLIST_REMOVE(&pvh->pvh_head, pv, pv_entry, pv_link); + __pmap_pv_free(pv); + break; + } + } +#ifdef DEBUG + /* Check duplicated map. */ + SLIST_FOREACH(pv, &pvh->pvh_head, pv_link) + KDASSERT(!(pv->pv_pmap == pmap && pv->pv_va == vaddr)); +#endif + splx(s); +} + +void +pmap_kenter_pa(vaddr_t va, paddr_t pa, vm_prot_t prot) +{ + pt_entry_t *pte, entry; + + KDASSERT((va & PGOFSET) == 0); + KDASSERT(va >= VM_MIN_KERNEL_ADDRESS && va < VM_MAX_KERNEL_ADDRESS); + + entry = (pa & PG_PPN) | PG_V | PG_SH | PG_4K; + if (prot & VM_PROT_WRITE) + entry |= (PG_PR_KRW | PG_D); + else + entry |= PG_PR_KRO; + + if (PHYS_TO_VM_PAGE(pa)) + entry |= PG_C; + + pte = __pmap_kpte_lookup(va); + + KDASSERT(*pte == 0); + *pte = entry; + + sh_tlb_update(0, va, entry); +} + +void +pmap_kremove(vaddr_t va, vsize_t len) +{ + pt_entry_t *pte; + vaddr_t eva = va + len; + + KDASSERT((va & PGOFSET) == 0); + KDASSERT((len & PGOFSET) == 0); + KDASSERT(va >= VM_MIN_KERNEL_ADDRESS && eva <= VM_MAX_KERNEL_ADDRESS); + + for (; va < eva; va += PAGE_SIZE) { + pte = __pmap_kpte_lookup(va); + KDASSERT(pte != NULL); + if (*pte == 0) + continue; + + if (SH_HAS_VIRTUAL_ALIAS && PHYS_TO_VM_PAGE(*pte & PG_PPN)) + sh_dcache_wbinv_range(va, PAGE_SIZE); + *pte = 0; + + sh_tlb_invalidate_addr(0, va); + } +} + +boolean_t +pmap_extract(pmap_t pmap, vaddr_t va, paddr_t *pap) +{ + pt_entry_t *pte; + + /* handle P1 and P2 specially: va == pa */ + if (pmap == pmap_kernel() && (va >> 30) == 2) { + if (pap != NULL) + *pap = va & SH3_PHYS_MASK; + return (TRUE); + } + + pte = __pmap_pte_lookup(pmap, va); + if (pte == NULL || *pte == 0) + return (FALSE); + + if (pap != NULL) + *pap = (*pte & PG_PPN) | (va & PGOFSET); + + return (TRUE); +} + +void +pmap_protect(pmap_t pmap, vaddr_t sva, vaddr_t eva, vm_prot_t prot) +{ + boolean_t kernel = pmap == pmap_kernel(); + pt_entry_t *pte, entry; + vaddr_t va; + + sva = trunc_page(sva); + + if ((prot & VM_PROT_READ) == VM_PROT_NONE) { + pmap_remove(pmap, sva, eva); + return; + } + + for (va = sva; va < eva; va += PAGE_SIZE) { + + if (((pte = __pmap_pte_lookup(pmap, va)) == NULL) || + (entry = *pte) == 0) + continue; + + if (SH_HAS_VIRTUAL_ALIAS && (entry & PG_D)) { + if (!SH_HAS_UNIFIED_CACHE && (prot & VM_PROT_EXECUTE)) + sh_icache_sync_range_index(va, PAGE_SIZE); + else + sh_dcache_wbinv_range_index(va, PAGE_SIZE); + } + + entry &= ~PG_PR_MASK; + switch (prot) { + default: + panic("pmap_protect: invalid protection mode %x", prot); + /* NOTREACHED */ + case VM_PROT_READ: + /* FALLTHROUGH */ + case VM_PROT_READ | VM_PROT_EXECUTE: + entry |= kernel ? PG_PR_KRO : PG_PR_URO; + break; + case VM_PROT_READ | VM_PROT_WRITE: + /* FALLTHROUGH */ + case VM_PROT_ALL: + entry |= kernel ? PG_PR_KRW : PG_PR_URW; + break; + } + *pte = entry; + + if (pmap->pm_asid != -1) + sh_tlb_update(pmap->pm_asid, va, entry); + } +} + +void +pmap_page_protect(struct vm_page *pg, vm_prot_t prot) +{ + struct vm_page_md *pvh = &pg->mdpage; + struct pv_entry *pv; + struct pmap *pmap; + vaddr_t va; + int s; + + switch (prot) { + case VM_PROT_READ | VM_PROT_WRITE: + /* FALLTHROUGH */ + case VM_PROT_ALL: + break; + + case VM_PROT_READ: + /* FALLTHROUGH */ + case VM_PROT_READ | VM_PROT_EXECUTE: + s = splvm(); + SLIST_FOREACH(pv, &pvh->pvh_head, pv_link) { + pmap = pv->pv_pmap; + va = pv->pv_va; + + KDASSERT(pmap); + pmap_protect(pmap, va, va + PAGE_SIZE, prot); + } + splx(s); + break; + + default: + /* Remove all */ + s = splvm(); + while ((pv = SLIST_FIRST(&pvh->pvh_head)) != NULL) { + va = pv->pv_va; + pmap_remove(pv->pv_pmap, va, va + PAGE_SIZE); + } + splx(s); + } +} + +void +pmap_unwire(pmap_t pmap, vaddr_t va) +{ + pt_entry_t *pte, entry; + + if ((pte = __pmap_pte_lookup(pmap, va)) == NULL || + (entry = *pte) == 0 || + (entry & _PG_WIRED) == 0) + return; + + *pte = entry & ~_PG_WIRED; + pmap->pm_stats.wired_count--; +} + +void +pmap_proc_iflush(struct proc *p, vaddr_t va, size_t len) +{ + if (!SH_HAS_UNIFIED_CACHE) + sh_icache_sync_range_index(va, len); +} + +void +pmap_zero_page(vm_page_t pg) +{ + paddr_t phys = VM_PAGE_TO_PHYS(pg); + + if (SH_HAS_VIRTUAL_ALIAS) { /* don't pollute cache */ + /* sync cache since we access via P2. */ + sh_dcache_wbinv_all(); + memset((void *)SH3_PHYS_TO_P2SEG(phys), 0, PAGE_SIZE); + } else { + memset((void *)SH3_PHYS_TO_P1SEG(phys), 0, PAGE_SIZE); + } +} + +void +pmap_copy_page(vm_page_t srcpg, vm_page_t dstpg) +{ + paddr_t src,dst; + + src = VM_PAGE_TO_PHYS(srcpg); + dst = VM_PAGE_TO_PHYS(dstpg); + + if (SH_HAS_VIRTUAL_ALIAS) { /* don't pollute cache */ + /* sync cache since we access via P2. */ + sh_dcache_wbinv_all(); + memcpy((void *)SH3_PHYS_TO_P2SEG(dst), + (void *)SH3_PHYS_TO_P2SEG(src), PAGE_SIZE); + } else { + memcpy((void *)SH3_PHYS_TO_P1SEG(dst), + (void *)SH3_PHYS_TO_P1SEG(src), PAGE_SIZE); + } +} + +boolean_t +pmap_is_referenced(struct vm_page *pg) +{ + return ((pg->mdpage.pvh_flags & PVH_REFERENCED) ? TRUE : FALSE); +} + +boolean_t +pmap_clear_reference(struct vm_page *pg) +{ + struct vm_page_md *pvh = &pg->mdpage; + struct pv_entry *pv; + pt_entry_t *pte; + pmap_t pmap; + vaddr_t va; + int s; + + if ((pg->mdpage.pvh_flags & PVH_REFERENCED) == 0) + return (FALSE); + + pg->mdpage.pvh_flags &= ~PVH_REFERENCED; + + s = splvm(); + /* Restart reference bit emulation */ + SLIST_FOREACH(pv, &pvh->pvh_head, pv_link) { + pmap = pv->pv_pmap; + va = pv->pv_va; + + if ((pte = __pmap_pte_lookup(pmap, va)) == NULL) + continue; + if ((*pte & PG_V) == 0) + continue; + *pte &= ~PG_V; + + if (pmap->pm_asid != -1) + sh_tlb_invalidate_addr(pmap->pm_asid, va); + } + splx(s); + + return (TRUE); +} + +boolean_t +pmap_is_modified(struct vm_page *pg) +{ + return ((pg->mdpage.pvh_flags & PVH_MODIFIED) ? TRUE : FALSE); +} + +boolean_t +pmap_clear_modify(struct vm_page *pg) +{ + struct vm_page_md *pvh = &pg->mdpage; + struct pv_entry *pv; + struct pmap *pmap; + pt_entry_t *pte, entry; + boolean_t modified; + vaddr_t va; + int s; + + modified = pvh->pvh_flags & PVH_MODIFIED; + if (!modified) + return (FALSE); + + pvh->pvh_flags &= ~PVH_MODIFIED; + + s = splvm(); + if (SLIST_EMPTY(&pvh->pvh_head)) {/* no map on this page */ + splx(s); + return (TRUE); + } + + /* Write-back and invalidate TLB entry */ + if (!SH_HAS_VIRTUAL_ALIAS && SH_HAS_WRITEBACK_CACHE) + sh_dcache_wbinv_all(); + + SLIST_FOREACH(pv, &pvh->pvh_head, pv_link) { + pmap = pv->pv_pmap; + va = pv->pv_va; + if ((pte = __pmap_pte_lookup(pmap, va)) == NULL) + continue; + entry = *pte; + if ((entry & PG_D) == 0) + continue; + + if (SH_HAS_VIRTUAL_ALIAS) + sh_dcache_wbinv_range_index(va, PAGE_SIZE); + + *pte = entry & ~PG_D; + if (pmap->pm_asid != -1) + sh_tlb_invalidate_addr(pmap->pm_asid, va); + } + splx(s); + + return (TRUE); +} + +/* + * pv_entry pool allocator: + * void *__pmap_pv_page_alloc(struct pool *pool, int flags): + * void __pmap_pv_page_free(struct pool *pool, void *v): + */ +void * +__pmap_pv_page_alloc(struct pool *pool, int flags) +{ + struct vm_page *pg; + + pg = uvm_pagealloc(NULL, 0, NULL, UVM_PGA_USERESERVE); + if (pg == NULL) + return (NULL); + + return ((void *)SH3_PHYS_TO_P1SEG(VM_PAGE_TO_PHYS(pg))); +} + +void +__pmap_pv_page_free(struct pool *pool, void *v) +{ + vaddr_t va = (vaddr_t)v; + + /* Invalidate cache for next use of this page */ + if (SH_HAS_VIRTUAL_ALIAS) + sh_icache_sync_range_index(va, PAGE_SIZE); + uvm_pagefree(PHYS_TO_VM_PAGE(SH3_P1SEG_TO_PHYS(va))); +} + +/* + * pt_entry_t __pmap_pte_alloc(pmap_t pmap, vaddr_t va): + * lookup page table entry. if found returns it, else allocate it. + * page table is accessed via P1. + */ +pt_entry_t * +__pmap_pte_alloc(pmap_t pmap, vaddr_t va) +{ + struct vm_page *pg; + pt_entry_t *ptp, *pte; + + if ((pte = __pmap_pte_lookup(pmap, va)) != NULL) + return (pte); + + /* Allocate page table (not managed page) */ + pg = uvm_pagealloc(NULL, 0, NULL, UVM_PGA_USERESERVE | UVM_PGA_ZERO); + if (pg == NULL) + return NULL; + + ptp = (pt_entry_t *)SH3_PHYS_TO_P1SEG(VM_PAGE_TO_PHYS(pg)); + pmap->pm_ptp[__PMAP_PTP_INDEX(va)] = ptp; + + return (ptp + __PMAP_PTP_OFSET(va)); +} + +/* + * pt_entry_t *__pmap_pte_lookup(pmap_t pmap, vaddr_t va): + * lookup page table entry, if not allocated, returns NULL. + */ +pt_entry_t * +__pmap_pte_lookup(pmap_t pmap, vaddr_t va) +{ + pt_entry_t *ptp; + + if (pmap == pmap_kernel()) + return (__pmap_kpte_lookup(va)); + + /* Lookup page table page */ + ptp = pmap->pm_ptp[__PMAP_PTP_INDEX(va)]; + if (ptp == NULL) + return (NULL); + + return (ptp + __PMAP_PTP_OFSET(va)); +} + +/* + * pt_entry_t *__pmap_kpte_lookup(vaddr_t va): + * kernel virtual only version of __pmap_pte_lookup(). + */ +pt_entry_t * +__pmap_kpte_lookup(vaddr_t va) +{ + return (__pmap_kernel.pm_ptp + [__PMAP_PTP_INDEX(va - VM_MIN_KERNEL_ADDRESS)] + + __PMAP_PTP_OFSET(va)); +} + +/* + * boolean_t __pmap_pte_load(pmap_t pmap, vaddr_t va, int flags): + * lookup page table entry, if found it, load to TLB. + * flags specify do emulate reference and/or modified bit or not. + */ +boolean_t +__pmap_pte_load(pmap_t pmap, vaddr_t va, int flags) +{ + struct vm_page *pg; + pt_entry_t *pte; + pt_entry_t entry; + + KDASSERT((((int)va < 0) && (pmap == pmap_kernel())) || + (((int)va >= 0) && (pmap != pmap_kernel()))); + + /* Lookup page table entry */ + if (((pte = __pmap_pte_lookup(pmap, va)) == NULL) || + ((entry = *pte) == 0)) + return (FALSE); + + KDASSERT(va != 0); + + /* Emulate reference/modified tracking for managed page. */ + if (flags != 0 && (pg = PHYS_TO_VM_PAGE(entry & PG_PPN)) != NULL) { + if (flags & PVH_REFERENCED) { + pg->mdpage.pvh_flags |= PVH_REFERENCED; + entry |= PG_V; + } + if (flags & PVH_MODIFIED) { + pg->mdpage.pvh_flags |= PVH_MODIFIED; + entry |= PG_D; + } + *pte = entry; + } + + /* When pmap has valid ASID, register to TLB */ + if (pmap->pm_asid != -1) + sh_tlb_update(pmap->pm_asid, va, entry); + + return (TRUE); +} + +/* + * int __pmap_asid_alloc(void): + * Allocate new ASID. if all ASID is used, steal from other process. + */ +int +__pmap_asid_alloc() +{ + struct proc *p; + int i, j, k, n, map, asid; + + /* Search free ASID */ + i = __pmap_asid.hint >> 5; + n = i + 8; + for (; i < n; i++) { + k = i & 0x7; + map = __pmap_asid.map[k]; + for (j = 0; j < 32; j++) { + if ((map & (1 << j)) == 0 && (k + j) != 0) { + __pmap_asid.map[k] |= (1 << j); + __pmap_asid.hint = (k << 5) + j; + return (__pmap_asid.hint); + } + } + } + + /* Steal ASID */ + LIST_FOREACH(p, &allproc, p_list) { + if ((asid = p->p_vmspace->vm_map.pmap->pm_asid) > 0) { + pmap_t pmap = p->p_vmspace->vm_map.pmap; + pmap->pm_asid = -1; + __pmap_asid.hint = asid; + /* Invalidate all old ASID entry */ + sh_tlb_invalidate_asid(pmap->pm_asid); + + return (__pmap_asid.hint); + } + } + + panic("No ASID allocated."); + /* NOTREACHED */ +} + +/* + * void __pmap_asid_free(int asid): + * Return unused ASID to pool. and remove all TLB entry of ASID. + */ +void +__pmap_asid_free(int asid) +{ + int i; + + if (asid < 1) /* Don't invalidate kernel ASID 0 */ + return; + + sh_tlb_invalidate_asid(asid); + + i = asid >> 5; + __pmap_asid.map[i] &= ~(1 << (asid - (i << 5))); +} diff --git a/sys/arch/sh/sh/process_machdep.c b/sys/arch/sh/sh/process_machdep.c new file mode 100644 index 00000000000..9f82c48527a --- /dev/null +++ b/sys/arch/sh/sh/process_machdep.c @@ -0,0 +1,210 @@ +/* $OpenBSD: process_machdep.c,v 1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: process_machdep.c,v 1.12 2006/01/21 04:12:22 uwe Exp $ */ + +/* + * Copyright (c) 1993 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Jan-Simon Pendry. + * + * 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. 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. + * + * From: + * Id: procfs_i386.c,v 4.1 1993/12/17 10:47:45 jsp Rel + */ + +/* + * Copyright (c) 1995, 1996, 1997 + * Charles M. Hannum. All rights reserved. + * Copyright (c) 1993 Jan-Simon Pendry + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Jan-Simon Pendry. + * + * 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. + * + * From: + * Id: procfs_i386.c,v 4.1 1993/12/17 10:47:45 jsp Rel + */ + +/* + * This file may seem a bit stylized, but that so that it's easier to port. + * Functions to be implemented here are: + * + * process_read_regs(proc, regs) + * Get the current user-visible register set from the process + * and copy it into the regs structure (<machine/reg.h>). + * The process is stopped at the time read_regs is called. + * + * process_write_regs(proc, regs) + * Update the current register set from the passed in regs + * structure. Take care to avoid clobbering special CPU + * registers or privileged bits in the PSL. + * The process is stopped at the time write_regs is called. + * + * process_sstep(proc) + * Arrange for the process to trap after executing a single instruction. + * + * process_set_pc(proc) + * Set the process's program counter. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/time.h> +#include <sys/kernel.h> +#include <sys/proc.h> +#include <sys/user.h> +#include <sys/vnode.h> +#include <sys/ptrace.h> + +#include <machine/psl.h> +#include <machine/reg.h> + +static inline struct trapframe * +process_frame(struct proc *p) +{ + + return (p->p_md.md_regs); +} + +int +process_read_regs(struct proc *p, struct reg *regs) +{ + struct trapframe *tf = process_frame(p); + + regs->r_spc = tf->tf_spc; + regs->r_ssr = tf->tf_ssr; + regs->r_macl = tf->tf_macl; + regs->r_mach = tf->tf_mach; + regs->r_pr = tf->tf_pr; + regs->r_r14 = tf->tf_r14; + regs->r_r13 = tf->tf_r13; + regs->r_r12 = tf->tf_r12; + regs->r_r11 = tf->tf_r11; + regs->r_r10 = tf->tf_r10; + regs->r_r9 = tf->tf_r9; + regs->r_r8 = tf->tf_r8; + regs->r_r7 = tf->tf_r7; + regs->r_r6 = tf->tf_r6; + regs->r_r5 = tf->tf_r5; + regs->r_r4 = tf->tf_r4; + regs->r_r3 = tf->tf_r3; + regs->r_r2 = tf->tf_r2; + regs->r_r1 = tf->tf_r1; + regs->r_r0 = tf->tf_r0; + regs->r_r15 = tf->tf_r15; + + return (0); +} + +#ifdef PTRACE + +int +process_write_regs(struct proc *p, struct reg *regs) +{ + struct trapframe *tf = process_frame(p); + + /* + * Check for security violations. + */ + if (((regs->r_ssr ^ tf->tf_ssr) & PSL_USERSTATIC) != 0) { + return (EINVAL); + } + + tf->tf_spc = regs->r_spc; + tf->tf_ssr = regs->r_ssr; + tf->tf_pr = regs->r_pr; + + tf->tf_mach = regs->r_mach; + tf->tf_macl = regs->r_macl; + tf->tf_r14 = regs->r_r14; + tf->tf_r13 = regs->r_r13; + tf->tf_r12 = regs->r_r12; + tf->tf_r11 = regs->r_r11; + tf->tf_r10 = regs->r_r10; + tf->tf_r9 = regs->r_r9; + tf->tf_r8 = regs->r_r8; + tf->tf_r7 = regs->r_r7; + tf->tf_r6 = regs->r_r6; + tf->tf_r5 = regs->r_r5; + tf->tf_r4 = regs->r_r4; + tf->tf_r3 = regs->r_r3; + tf->tf_r2 = regs->r_r2; + tf->tf_r1 = regs->r_r1; + tf->tf_r0 = regs->r_r0; + tf->tf_r15 = regs->r_r15; + + return (0); +} + +int +process_sstep(struct proc *p, int sstep) +{ + if (sstep) + return (EINVAL); + + return (0); +} + +int +process_set_pc(struct proc *p, caddr_t addr) +{ + struct trapframe *tf = process_frame(p); + + tf->tf_spc = (int)addr; + + return (0); +} + +#endif /* PTRACE */ diff --git a/sys/arch/sh/sh/sh_machdep.c b/sys/arch/sh/sh/sh_machdep.c new file mode 100644 index 00000000000..74ab7da4861 --- /dev/null +++ b/sys/arch/sh/sh/sh_machdep.c @@ -0,0 +1,471 @@ +/* $OpenBSD: sh_machdep.c,v 1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: sh3_machdep.c,v 1.59 2006/03/04 01:13:36 uwe Exp $ */ + +/*- + * Copyright (c) 1996, 1997, 1998, 2002 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Charles M. Hannum and 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) 1982, 1987, 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * 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. 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. + * + * @(#)machdep.c 7.4 (Berkeley) 6/3/91 + */ + +#include <sys/param.h> +#include <sys/systm.h> + +#include <sys/buf.h> +#include <sys/exec.h> +#include <sys/kernel.h> +#include <sys/malloc.h> +#include <sys/mount.h> +#include <sys/proc.h> +#include <sys/signalvar.h> +#include <sys/syscallargs.h> +#include <sys/user.h> + +#include <uvm/uvm_extern.h> + +#include <sh/cache.h> +#include <sh/clock.h> +#include <sh/locore.h> +#include <sh/mmu.h> +#include <sh/trap.h> +#include <sh/intr.h> + +/* Our exported CPU info; we can have only one. */ +int cpu_arch; +int cpu_product; +char cpu_model[120]; + +struct vm_map *exec_map; +struct vm_map *phys_map; + +int physmem; +struct user *proc0paddr; /* init_main.c use this. */ +struct pcb *curpcb; +struct md_upte *curupte; /* SH3 wired u-area hack */ + +#define VBR (uint8_t *)SH3_PHYS_TO_P1SEG(IOM_RAM_BEGIN) +vaddr_t ram_start = SH3_PHYS_TO_P1SEG(IOM_RAM_BEGIN); +/* exception handler holder (sh/sh/vectors.S) */ +extern char sh_vector_generic[], sh_vector_generic_end[]; +extern char sh_vector_interrupt[], sh_vector_interrupt_end[]; +#ifdef SH3 +extern char sh3_vector_tlbmiss[], sh3_vector_tlbmiss_end[]; +#endif +#ifdef SH4 +extern char sh4_vector_tlbmiss[], sh4_vector_tlbmiss_end[]; +#endif + +/* + * These variables are needed by /sbin/savecore + */ +uint32_t dumpmag = 0x8fca0101; /* magic number */ +int dumpsize; /* pages */ +long dumplo; /* blocks */ + +void +sh_cpu_init(int arch, int product) +{ + /* CPU type */ + cpu_arch = arch; + cpu_product = product; + +#if defined(SH3) && defined(SH4) + /* Set register addresses */ + sh_devreg_init(); +#endif + /* Cache access ops. */ + sh_cache_init(); + + /* MMU access ops. */ + sh_mmu_init(); + + /* Hardclock, RTC initialize. */ + machine_clock_init(); + + /* ICU initiailze. */ + intc_init(); + + /* Exception vector. */ + memcpy(VBR + 0x100, sh_vector_generic, + sh_vector_generic_end - sh_vector_generic); +#ifdef SH3 + if (CPU_IS_SH3) + memcpy(VBR + 0x400, sh3_vector_tlbmiss, + sh3_vector_tlbmiss_end - sh3_vector_tlbmiss); +#endif +#ifdef SH4 + if (CPU_IS_SH4) + memcpy(VBR + 0x400, sh4_vector_tlbmiss, + sh4_vector_tlbmiss_end - sh4_vector_tlbmiss); +#endif + memcpy(VBR + 0x600, sh_vector_interrupt, + sh_vector_interrupt_end - sh_vector_interrupt); + + if (!SH_HAS_UNIFIED_CACHE) + sh_icache_sync_all(); + + __asm volatile("ldc %0, vbr" :: "r"(VBR)); + + /* kernel stack setup */ + __sh_switch_resume = CPU_IS_SH3 ? sh3_switch_resume : sh4_switch_resume; + + /* Set page size (4KB) */ + uvm_setpagesize(); +} + +/* + * void sh_proc0_init(void): + * Setup proc0 u-area. + */ +void +sh_proc0_init() +{ + struct switchframe *sf; + vaddr_t u; + + /* Steal process0 u-area */ + u = uvm_pageboot_alloc(USPACE); + memset((void *)u, 0, USPACE); + + /* Setup proc0 */ + proc0paddr = (struct user *)u; + proc0.p_addr = proc0paddr; + /* + * u-area map: + * |user| .... | .................. | + * | PAGE_SIZE | USPACE - PAGE_SIZE | + * frame top stack top + * current frame ... r6_bank + * stack top ... r7_bank + * current stack ... r15 + */ + curpcb = proc0.p_md.md_pcb = &proc0.p_addr->u_pcb; + curupte = proc0.p_md.md_upte; + + sf = &curpcb->pcb_sf; + sf->sf_r6_bank = u + PAGE_SIZE; + sf->sf_r7_bank = sf->sf_r15 = u + USPACE; + __asm volatile("ldc %0, r6_bank" :: "r"(sf->sf_r6_bank)); + __asm volatile("ldc %0, r7_bank" :: "r"(sf->sf_r7_bank)); + + proc0.p_md.md_regs = (struct trapframe *)sf->sf_r6_bank - 1; +#ifdef KSTACK_DEBUG + memset((char *)(u + sizeof(struct user)), 0x5a, + PAGE_SIZE - sizeof(struct user)); + memset((char *)(u + PAGE_SIZE), 0xa5, USPACE - PAGE_SIZE); +#endif /* KSTACK_DEBUG */ +} + +void +sh_startup() +{ + vaddr_t minaddr, maxaddr; + + printf("%s", version); + if (*cpu_model != '\0') + printf("%s", cpu_model); +#ifdef DEBUG + printf("general exception handler:\t%d byte\n", + sh_vector_generic_end - sh_vector_generic); + printf("TLB miss exception handler:\t%d byte\n", +#if defined(SH3) && defined(SH4) + CPU_IS_SH3 ? sh3_vector_tlbmiss_end - sh3_vector_tlbmiss : + sh4_vector_tlbmiss_end - sh4_vector_tlbmiss +#elif defined(SH3) + sh3_vector_tlbmiss_end - sh3_vector_tlbmiss +#elif defined(SH4) + sh4_vector_tlbmiss_end - sh4_vector_tlbmiss +#endif + ); + printf("interrupt exception handler:\t%d byte\n", + sh_vector_interrupt_end - sh_vector_interrupt); +#endif /* DEBUG */ + + printf("real mem = %u (%uK)\n", ctob(physmem), ctob(physmem) / 1024); + + minaddr = 0; + /* + * Allocate a submap for exec arguments. This map effectively + * limits the number of processes exec'ing at any time. + */ + exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, + 16 * NCARGS, VM_MAP_PAGEABLE, FALSE, NULL); + + /* + * Allocate a submap for physio + */ + phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, + VM_PHYS_SIZE, 0, FALSE, NULL); + + printf("avail mem = %u (%uK)\n", ptoa(uvmexp.free), + ptoa(uvmexp.free) / 1024); +} + +/* + * Signal frame. + */ +struct sigframe { +#if 0 /* in registers on entry to signal trampoline */ + int sf_signum; /* r4 - "signum" argument for handler */ + siginfo_t *sf_sip; /* r5 - "sip" argument for handler */ + struct sigcontext *sf_ucp; /* r6 - "ucp" argument for handler */ +#endif + struct sigcontext sf_uc; /* actual context */ + siginfo_t sf_si; +}; + +/* + * Send an interrupt to process. + */ +void +sendsig(sig_t catcher, int sig, int mask, u_long code, int type, + union sigval val) +{ + struct proc *p = curproc; + struct sigframe *fp, frame; + struct trapframe *tf = p->p_md.md_regs; + struct sigacts *ps = p->p_sigacts; + siginfo_t *sip; + int onstack; + + onstack = ps->ps_sigstk.ss_flags & SS_ONSTACK; + if ((ps->ps_flags & SAS_ALTSTACK) && onstack == 0 && + (ps->ps_sigonstack & sigmask(sig))) { + fp = (struct sigframe *)((vaddr_t)ps->ps_sigstk.ss_sp + + ps->ps_sigstk.ss_size); + ps->ps_sigstk.ss_flags |= SS_ONSTACK; + } else + fp = (void *)p->p_md.md_regs->tf_r15; + --fp; + + + bzero(&frame, sizeof(frame)); + + if (ps->ps_siginfo & sigmask(sig)) { + initsiginfo(&frame.sf_si, sig, code, type, val); + sip = &fp->sf_si; + } else + sip = NULL; + + /* Save register context. */ + frame.sf_uc.sc_spc = tf->tf_spc; + frame.sf_uc.sc_ssr = tf->tf_ssr; + frame.sf_uc.sc_pr = tf->tf_pr; + frame.sf_uc.sc_r14 = tf->tf_r14; + frame.sf_uc.sc_r13 = tf->tf_r13; + frame.sf_uc.sc_r12 = tf->tf_r12; + frame.sf_uc.sc_r11 = tf->tf_r11; + frame.sf_uc.sc_r10 = tf->tf_r10; + frame.sf_uc.sc_r9 = tf->tf_r9; + frame.sf_uc.sc_r8 = tf->tf_r8; + frame.sf_uc.sc_r7 = tf->tf_r7; + frame.sf_uc.sc_r6 = tf->tf_r6; + frame.sf_uc.sc_r5 = tf->tf_r5; + frame.sf_uc.sc_r4 = tf->tf_r4; + frame.sf_uc.sc_r3 = tf->tf_r3; + frame.sf_uc.sc_r2 = tf->tf_r2; + frame.sf_uc.sc_r1 = tf->tf_r1; + frame.sf_uc.sc_r0 = tf->tf_r0; + frame.sf_uc.sc_r15 = tf->tf_r15; + frame.sf_uc.sc_onstack = onstack; + frame.sf_uc.sc_expevt = tf->tf_expevt; + /* frame.sf_uc.sc_err = 0; */ + frame.sf_uc.sc_mask = p->p_sigmask; + /* XXX tf_macl, tf_mach not saved */ + + if (copyout(&frame, fp, sizeof(frame)) != 0) { + /* + * Process has trashed its stack; give it an illegal + * instruction to halt it in its tracks. + */ + sigexit(p, SIGILL); + /* NOTREACHED */ + } + + tf->tf_r4 = sig; /* "signum" argument for handler */ + tf->tf_r5 = (int)sip; /* "sip" argument for handler */ + tf->tf_r6 = (int)&fp->sf_uc; /* "ucp" argument for handler */ + tf->tf_spc = (int)catcher; + tf->tf_r15 = (int)fp; + tf->tf_pr = (int)p->p_sigcode; +} + +/* + * System call to cleanup state after a signal + * has been taken. Reset signal mask and + * stack state from context left by sendsig (above). + * Return to previous pc and psl as specified by + * context left by sendsig. Check carefully to + * make sure that the user has not modified the + * psl to gain improper privileges or to cause + * a machine fault. + */ +int +sys_sigreturn(struct proc *p, void *v, register_t *retval) +{ + struct sys_sigreturn_args /* { + syscallarg(struct sigcontext *) sigcntxp; + } */ *uap = v; + struct sigcontext *scp, context; + struct trapframe *tf; + int error; + + /* + * The trampoline code hands us the context. + * It is unsafe to keep track of it ourselves, in the event that a + * program jumps out of a signal handler. + */ + scp = SCARG(uap, sigcntxp); + if ((error = copyin((caddr_t)scp, &context, sizeof(*scp))) != 0) + return (error); + + /* Restore signal context. */ + tf = p->p_md.md_regs; + + /* Check for security violations. */ + if (((context.sc_ssr ^ tf->tf_ssr) & PSL_USERSTATIC) != 0) + return (EINVAL); + + tf->tf_ssr = context.sc_ssr; + + tf->tf_r0 = context.sc_r0; + tf->tf_r1 = context.sc_r1; + tf->tf_r2 = context.sc_r2; + tf->tf_r3 = context.sc_r3; + tf->tf_r4 = context.sc_r4; + tf->tf_r5 = context.sc_r5; + tf->tf_r6 = context.sc_r6; + tf->tf_r7 = context.sc_r7; + tf->tf_r8 = context.sc_r8; + tf->tf_r9 = context.sc_r9; + tf->tf_r10 = context.sc_r10; + tf->tf_r11 = context.sc_r11; + tf->tf_r12 = context.sc_r12; + tf->tf_r13 = context.sc_r13; + tf->tf_r14 = context.sc_r14; + tf->tf_spc = context.sc_spc; + tf->tf_r15 = context.sc_r15; + tf->tf_pr = context.sc_pr; + + /* Restore signal stack. */ + if (context.sc_onstack) + p->p_sigacts->ps_sigstk.ss_flags |= SS_ONSTACK; + else + p->p_sigacts->ps_sigstk.ss_flags &= ~SS_ONSTACK; + /* Restore signal mask. */ + p->p_sigmask = context.sc_mask & ~sigcantmask; + + return (EJUSTRETURN); +} + +/* + * Clear registers on exec + */ +void +setregs(struct proc *p, struct exec_package *pack, u_long stack, + register_t rval[2]) +{ + struct trapframe *tf; + + p->p_md.md_flags &= ~MDP_USEDFPU; + + tf = p->p_md.md_regs; + + tf->tf_r0 = 0; + tf->tf_r1 = 0; + tf->tf_r2 = 0; + tf->tf_r3 = 0; + copyin((caddr_t)stack, &tf->tf_r4, sizeof(register_t)); /* argc */ + tf->tf_r5 = stack + 4; /* argv */ + tf->tf_r6 = stack + 4 * tf->tf_r4 + 8; /* envp */ + tf->tf_r7 = 0; + tf->tf_r8 = 0; + tf->tf_r9 = (int)PS_STRINGS; + tf->tf_r10 = 0; + tf->tf_r11 = 0; + tf->tf_r12 = 0; + tf->tf_r13 = 0; + tf->tf_r14 = 0; + tf->tf_spc = pack->ep_entry; + tf->tf_ssr = PSL_USERSET; + tf->tf_r15 = stack; +} + +/* + * Jump to reset vector. + */ +void +cpu_reset() +{ + _cpu_exception_suspend(); + _reg_write_4(SH_(EXPEVT), EXPEVT_RESET_MANUAL); + +#ifndef __lint__ + goto *(void *)0xa0000000; +#endif + /* NOTREACHED */ +} diff --git a/sys/arch/sh/sh/sys_machdep.c b/sys/arch/sh/sh/sys_machdep.c new file mode 100644 index 00000000000..3d78e981779 --- /dev/null +++ b/sys/arch/sh/sh/sys_machdep.c @@ -0,0 +1,87 @@ +/* $OpenBSD: sys_machdep.c,v 1.1.1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: sys_machdep.c,v 1.11 2005/12/11 12:19:00 christos Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * 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. 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. + * + * @(#)sys_machdep.c 5.5 (Berkeley) 1/19/91 + */ + +/*- + * Copyright (c) 1995, 1997 + * Charles M. Hannum. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * 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. + * + * @(#)sys_machdep.c 5.5 (Berkeley) 1/19/91 + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/mount.h> +#include <sys/syscallargs.h> + +int +sys_sysarch(struct proc *p, void *v, register_t *retval) +{ + struct sys_sysarch_args __attribute__((__unused__)) *uap = v; + + return (ENOSYS); +} diff --git a/sys/arch/sh/sh/trap.c b/sys/arch/sh/sh/trap.c new file mode 100644 index 00000000000..c4da3df5a89 --- /dev/null +++ b/sys/arch/sh/sh/trap.c @@ -0,0 +1,618 @@ +/* $OpenBSD: trap.c,v 1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: exception.c,v 1.32 2006/09/04 23:57:52 uwe Exp $ */ +/* $NetBSD: syscall.c,v 1.6 2006/03/07 07:21:50 thorpej Exp $ */ + +/*- + * Copyright (c) 2002 The NetBSD Foundation, Inc. All rights reserved. + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the University of Utah, and William Jolitz. + * + * 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. 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. + * + * @(#)trap.c 7.4 (Berkeley) 5/13/91 + */ + +/*- + * Copyright (c) 1995 Charles M. Hannum. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the University of Utah, and William Jolitz. + * + * 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. + * + * @(#)trap.c 7.4 (Berkeley) 5/13/91 + */ + +/* + * SH3 Trap and System call handling + * + * T.Horiuchi 1998.06.8 + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/proc.h> +#include <sys/pool.h> +#include <sys/user.h> +#include <sys/kernel.h> +#include <sys/signal.h> +#include <sys/syscall.h> + +#ifdef KTRACE +#include <sys/ktrace.h> +#endif + +#include "systrace.h" +#if NSYSTRACE > 0 +#include <dev/systrace.h> +#endif + +#include <uvm/uvm_extern.h> + +#include <sh/cpu.h> +#include <sh/mmu.h> +#include <sh/trap.h> +#include <sh/userret.h> + +#ifdef DDB +#include <machine/db_machdep.h> +#endif + +const char * const exp_type[] = { + "--", /* 0x000 (reset vector) */ + "--", /* 0x020 (reset vector) */ + "TLB miss/invalid (load)", /* 0x040 EXPEVT_TLB_MISS_LD */ + "TLB miss/invalid (store)", /* 0x060 EXPEVT_TLB_MISS_ST */ + "initial page write", /* 0x080 EXPEVT_TLB_MOD */ + "TLB protection violation (load)", /* 0x0a0 EXPEVT_TLB_PROT_LD */ + "TLB protection violation (store)", /* 0x0c0 EXPEVT_TLB_PROT_ST */ + "address error (load)", /* 0x0e0 EXPEVT_ADDR_ERR_LD */ + "address error (store)", /* 0x100 EXPEVT_ADDR_ERR_ST */ + "FPU", /* 0x120 EXPEVT_FPU */ + "--", /* 0x140 (reset vector) */ + "unconditional trap (TRAPA)", /* 0x160 EXPEVT_TRAPA */ + "reserved instruction code exception", /* 0x180 EXPEVT_RES_INST */ + "illegal slot instruction exception", /* 0x1a0 EXPEVT_SLOT_INST */ + "--", /* 0x1c0 (external interrupt) */ + "user break point trap", /* 0x1e0 EXPEVT_BREAK */ +}; +const int exp_types = sizeof exp_type / sizeof exp_type[0]; + +void general_exception(struct proc *, struct trapframe *, uint32_t); +void tlb_exception(struct proc *, struct trapframe *, uint32_t); +void ast(struct proc *, struct trapframe *); +void syscall(struct proc *, struct trapframe *); + +/* + * void general_exception(struct proc *p, struct trapframe *tf): + * p ... curproc when exception occured. + * tf ... full user context. + * va ... fault va for user mode EXPEVT_ADDR_ERR_{LD,ST} + */ +void +general_exception(struct proc *p, struct trapframe *tf, uint32_t va) +{ + int expevt = tf->tf_expevt; + int tra; + boolean_t usermode = !KERNELMODE(tf->tf_ssr); + union sigval sv; + + uvmexp.traps++; + + if (p == NULL) + goto do_panic; + + if (usermode) { + KDASSERT(p->p_md.md_regs == tf); /* check exception depth */ + expevt |= EXP_USER; + } + + switch (expevt) { + case EXPEVT_TRAPA: + /* Check for ddb request */ + tra = _reg_read_4(SH_(TRA)); + if (tra == (_SH_TRA_BREAK << 2)) { + kdb_trap(expevt, tra, tf); + goto out; + } else + goto do_panic; + case EXPEVT_TRAPA | EXP_USER: + /* Check for debugger break */ + tra = _reg_read_4(SH_(TRA)); + switch (tra) { + case _SH_TRA_BREAK << 2: + tf->tf_spc -= 2; /* back to the breakpoint address */ + sv.sival_ptr = (void *)tf->tf_spc; + trapsignal(p, SIGTRAP, expevt & ~EXP_USER, TRAP_BRKPT, + sv); + goto out; + case _SH_TRA_SYSCALL << 2: + syscall(p, tf); + return; + default: + sv.sival_ptr = (void *)tf->tf_spc; + trapsignal(p, SIGILL, expevt & ~EXP_USER, ILL_ILLTRP, + sv); + goto out; + } + break; + + case EXPEVT_ADDR_ERR_LD: /* FALLTHROUGH */ + case EXPEVT_ADDR_ERR_ST: + KDASSERT(p->p_md.md_pcb->pcb_onfault != NULL); + tf->tf_spc = (int)p->p_md.md_pcb->pcb_onfault; + if (tf->tf_spc == 0) + goto do_panic; + break; + + case EXPEVT_ADDR_ERR_LD | EXP_USER: /* FALLTHROUGH */ + case EXPEVT_ADDR_ERR_ST | EXP_USER: + sv.sival_ptr = (void *)va; + if (((int)va) < 0) + trapsignal(p, SIGSEGV, expevt & ~EXP_USER, SEGV_ACCERR, + sv); + else + trapsignal(p, SIGBUS, expevt & ~EXP_USER, BUS_ADRALN, + sv); + goto out; + + case EXPEVT_RES_INST | EXP_USER: /* FALLTHROUGH */ + case EXPEVT_SLOT_INST | EXP_USER: + sv.sival_ptr = (void *)tf->tf_spc; + trapsignal(p, SIGILL, expevt & ~EXP_USER, ILL_ILLOPC, sv); + goto out; + + case EXPEVT_BREAK | EXP_USER: + sv.sival_ptr = (void *)tf->tf_spc; + trapsignal(p, SIGTRAP, expevt & ~EXP_USER, TRAP_TRACE, sv); + goto out; + + default: + goto do_panic; + } + + if (!usermode) + return; +out: + userret(p); + return; + +do_panic: + if ((expevt >> 5) < exp_types) + printf("fatal %s", exp_type[expevt >> 5]); + else + printf("EXPEVT 0x%03x", expevt); + printf(" in %s mode\n", expevt & EXP_USER ? "user" : "kernel"); + printf(" spc %x ssr %x \n", tf->tf_spc, tf->tf_ssr); + + panic("general_exception"); + /* NOTREACHED */ +} + + +/* + * void tlb_exception(struct proc *p, struct trapframe *tf, uint32_t va): + * p ... curproc when exception occured. + * tf ... full user context. + * va ... fault address. + */ +void +tlb_exception(struct proc *p, struct trapframe *tf, uint32_t va) +{ + struct vm_map *map; + pmap_t pmap; + union sigval sv; + boolean_t usermode; + int err, track, ftype; + const char *panic_msg; + +#define TLB_ASSERT(assert, msg) \ + do { \ + if (!(assert)) { \ + panic_msg = msg; \ + goto tlb_panic; \ + } \ + } while(/*CONSTCOND*/0) + + + usermode = !KERNELMODE(tf->tf_ssr); + if (usermode) { + KDASSERT(p->p_md.md_regs == tf); + } else { + KDASSERT(p == NULL || /* idle */ + p == &proc0 || /* kthread */ + p->p_md.md_regs != tf); /* other */ + } + + switch (tf->tf_expevt) { + case EXPEVT_TLB_MISS_LD: + track = PVH_REFERENCED; + ftype = VM_PROT_READ; + break; + case EXPEVT_TLB_MISS_ST: + track = PVH_REFERENCED; + ftype = VM_PROT_WRITE; + break; + case EXPEVT_TLB_MOD: + track = PVH_REFERENCED | PVH_MODIFIED; + ftype = VM_PROT_WRITE; + break; + case EXPEVT_TLB_PROT_LD: + TLB_ASSERT((int)va > 0, + "kernel virtual protection fault (load)"); + if (usermode) { + sv.sival_ptr = (void *)va; + trapsignal(p, SIGSEGV, tf->tf_expevt, SEGV_ACCERR, sv); + goto user_fault; + } else { + TLB_ASSERT(p->p_md.md_pcb->pcb_onfault != NULL, + "no copyin/out fault handler (load protection)"); + tf->tf_spc = (int)p->p_md.md_pcb->pcb_onfault; + } + return; + + case EXPEVT_TLB_PROT_ST: + track = 0; /* call uvm_fault first. (COW) */ + ftype = VM_PROT_WRITE; + break; + + default: + TLB_ASSERT(0, "impossible expevt"); + } + + /* Select address space */ + if (usermode) { + TLB_ASSERT(p != NULL, "no curproc"); + map = &p->p_vmspace->vm_map; + pmap = map->pmap; + } else { + if ((int)va < 0) { + map = kernel_map; + pmap = pmap_kernel(); + } else { + TLB_ASSERT(p != NULL && + p->p_md.md_pcb->pcb_onfault != NULL, + "invalid user-space access from kernel mode"); + if (va == 0) { + tf->tf_spc = (int)p->p_md.md_pcb->pcb_onfault; + return; + } + map = &p->p_vmspace->vm_map; + pmap = map->pmap; + } + } + + /* Lookup page table. if entry found, load it. */ + if (track && __pmap_pte_load(pmap, va, track)) { + if (usermode) + userret(p); + return; + } + + /* Page not found. call fault handler */ + if (!usermode && pmap != pmap_kernel() && + p->p_md.md_pcb->pcb_faultbail) { + TLB_ASSERT(p->p_md.md_pcb->pcb_onfault != NULL, + "no copyin/out fault handler (interrupt context)"); + tf->tf_spc = (int)p->p_md.md_pcb->pcb_onfault; + return; + } + + err = uvm_fault(map, va, 0, ftype); + + /* User stack extension */ + if (map != kernel_map && + (va >= (vaddr_t)p->p_vmspace->vm_maxsaddr) && + (va < USRSTACK)) { + if (err == 0) { + struct vmspace *vm = p->p_vmspace; + uint32_t nss; + nss = btoc(USRSTACK - va); + if (nss > vm->vm_ssize) + vm->vm_ssize = nss; + } else if (err == EACCES) { + err = EFAULT; + } + } + + /* Page in. load PTE to TLB. */ + if (err == 0) { + boolean_t loaded = __pmap_pte_load(pmap, va, track); + TLB_ASSERT(loaded, "page table entry not found"); + if (usermode) + userret(p); + return; + } + + /* Page not found. */ + if (usermode) { + sv.sival_ptr = (void *)va; + if (err == ENOMEM) { + printf("UVM: pid %d (%s), uid %d killed: out of swap\n", + p->p_pid, p->p_comm, + p->p_cred && p->p_ucred ? + (int)p->p_ucred->cr_uid : -1); + trapsignal(p, SIGKILL, tf->tf_expevt, SEGV_MAPERR, sv); + } else + trapsignal(p, SIGSEGV, tf->tf_expevt, SEGV_MAPERR, sv); + goto user_fault; + } else { + TLB_ASSERT(p->p_md.md_pcb->pcb_onfault, + "no copyin/out fault handler (page not found)"); + tf->tf_spc = (int)p->p_md.md_pcb->pcb_onfault; + } + return; + +user_fault: + userret(p); + ast(p, tf); + return; + +tlb_panic: + panic("tlb_exception: %s\n" + "expevt=%x va=%08x ssr=%08x spc=%08x proc=%p onfault=%p", + panic_msg, tf->tf_expevt, va, tf->tf_ssr, tf->tf_spc, + p, p ? p->p_md.md_pcb->pcb_onfault : NULL); +#undef TLB_ASSERT +} + + +/* + * void ast(struct proc *p, struct trapframe *tf): + * p ... curproc when exception occured. + * tf ... full user context. + * This is called upon exception return. if return from kernel to user, + * handle asynchronous software traps and context switch if needed. + */ +void +ast(struct proc *p, struct trapframe *tf) +{ + if (KERNELMODE(tf->tf_ssr)) + return; + KDASSERT(p != NULL); + KDASSERT(p->p_md.md_regs == tf); + + while (p->p_md.md_astpending) { + uvmexp.softs++; + p->p_md.md_astpending = 0; + + if (p->p_flag & P_OWEUPC) { + p->p_flag &= ~P_OWEUPC; + ADDUPROF(p); + } + + if (want_resched) { + /* We are being preempted. */ + preempt(NULL); + } + + userret(p); + } +} + +void +syscall(struct proc *p, struct trapframe *tf) +{ + caddr_t params; + const struct sysent *callp; + int error, oerror, opc, nsys; + size_t argsize; + register_t code, args[8], rval[2], ocode; + + uvmexp.syscalls++; + + opc = tf->tf_spc; + ocode = code = tf->tf_r0; + + nsys = p->p_emul->e_nsysent; + callp = p->p_emul->e_sysent; + + params = (caddr_t)tf->tf_r15; + + switch (code) { + case SYS_syscall: + /* + * Code is first argument, followed by actual args. + */ + code = tf->tf_r4; + break; + case SYS___syscall: + /* + * Like syscall, but code is a quad, so as to maintain + * quad alignment for the rest of the arguments. + */ + if (callp != sysent) + break; +#if _BYTE_ORDER == BIG_ENDIAN + code = tf->tf_r5; +#else + code = tf->tf_r4; +#endif + break; + default: + break; + } + if (code < 0 || code >= nsys) + callp += p->p_emul->e_nosys; /* illegal */ + else + callp += code; + argsize = callp->sy_argsize; +#ifdef DIAGNOSTIC + if (argsize > sizeof args) { + callp += p->p_emul->e_nosys - code; + goto bad; + } +#endif + + switch (ocode) { + case SYS_syscall: + if (argsize) { + args[0] = tf->tf_r5; + args[1] = tf->tf_r6; + args[2] = tf->tf_r7; + if (argsize > 3 * sizeof(int)) { + argsize -= 3 * sizeof(int); + error = copyin(params, (caddr_t)&args[3], + argsize); + } else + error = 0; + } else + error = 0; + break; + case SYS___syscall: + if (argsize) { + args[0] = tf->tf_r6; + args[1] = tf->tf_r7; + if (argsize > 2 * sizeof(int)) { + argsize -= 2 * sizeof(int); + error = copyin(params, (caddr_t)&args[2], + argsize); + } else + error = 0; + } else + error = 0; + break; + default: + if (argsize) { + args[0] = tf->tf_r4; + args[1] = tf->tf_r5; + args[2] = tf->tf_r6; + args[3] = tf->tf_r7; + if (argsize > 4 * sizeof(int)) { + argsize -= 4 * sizeof(int); + error = copyin(params, (caddr_t)&args[4], + argsize); + } else + error = 0; + } else + error = 0; + break; + } + + if (error) + goto bad; + +#ifdef SYSCALL_DEBUG + scdebug_call(p, code, args); +#endif +#ifdef KTRACE + if (KTRPOINT(p, KTR_SYSCALL)) + ktrsyscall(p, code, callp->sy_argsize, args); +#endif + + rval[0] = 0; + rval[1] = tf->tf_r1; +#if NSYSTRACE > 0 + if (ISSET(p->p_flag, P_SYSTRACE)) + error = systrace_redirect(code, p, args, rval); + else +#endif + error = (*callp->sy_call)(p, args, rval); + + switch (oerror = error) { + case 0: + tf->tf_r0 = rval[0]; + tf->tf_r1 = rval[1]; + tf->tf_ssr |= PSL_TBIT; /* T bit */ + break; + case ERESTART: + /* 2 = TRAPA instruction size */ + tf->tf_spc = opc - 2; + break; + case EJUSTRETURN: + /* nothing to do */ + break; + default: +bad: + if (p->p_emul->e_errno) + error = p->p_emul->e_errno[error]; + tf->tf_r0 = error; + tf->tf_ssr &= ~PSL_TBIT; /* T bit */ + break; + } + +#ifdef SYSCALL_DEBUG + scdebug_ret(p, code, oerror, rval); +#endif + userret(p); +#ifdef KTRACE + if (KTRPOINT(p, KTR_SYSRET)) + ktrsysret(p, code, oerror, rval[0]); +#endif +} + +/* + * void child_return(void *arg): + * + * uvm_fork sets this routine to proc_trampoline's service function. + * when returning from here, jump to userland. + */ +void +child_return(void *arg) +{ + struct proc *p = arg; + struct trapframe *tf = p->p_md.md_regs; + + tf->tf_r0 = 0; + tf->tf_ssr |= PSL_TBIT; /* This indicates no error. */ + + userret(p); + +#ifdef KTRACE + if (KTRPOINT(p, KTR_SYSRET)) + ktrsysret(p, + (p->p_flag & P_PPWAIT) ? SYS_vfork : SYS_fork, 0, 0); +#endif +} + diff --git a/sys/arch/sh/sh/vectors.S b/sys/arch/sh/sh/vectors.S new file mode 100644 index 00000000000..26c7d1d235e --- /dev/null +++ b/sys/arch/sh/sh/vectors.S @@ -0,0 +1,275 @@ +/* $OpenBSD: vectors.S,v 1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: exception_vector.S,v 1.19 2006/08/22 21:47:57 uwe Exp $ */ + +/*- + * Copyright (c) 2002 The NetBSD Foundation, Inc. + * 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 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. + */ + +#include "assym.h" + +#include <sh/param.h> +#include <sh/asm.h> +#include <sh/locore.h> +#include <sh/trap.h> +#include <sh/ubcreg.h> +#include <sh/mmu_sh3.h> +#include <sh/mmu_sh4.h> + +/* + * Exception vectors. The following routines are copied to vector addreses. + * sh_vector_generic: VBR + 0x100 + * sh_vector_tlbmiss: VBR + 0x400 + * sh_vector_interrupt: VBR + 0x600 + */ + +#define VECTOR_END_MARKER(sym) \ + .globl _C_LABEL(sym); \ + _C_LABEL(sym): + + +/* + * LINTSTUB: Var: char sh_vector_generic[1]; + * + * void sh_vector_generic(void) __attribute__((__noreturn__)) + * Copied to VBR+0x100. This code should be position independent + * and no more than 786 bytes long (== 0x400 - 0x100). + */ +NENTRY(sh_vector_generic) + __EXCEPTION_ENTRY + __INTR_MASK(r0, r1) + /* Identify exception cause */ + MOV (EXPEVT, r0) + mov.l @r0, r0 + mov.l r0, @(TF_EXPEVT, r14) /* trapframe->tf_expevt = EXPEVT */ + /* Get curproc */ + mov.l _L.curproc, r1 + mov.l @r1, r4 /* 1st arg */ + /* Get TEA */ + MOV (TEA, r1) + mov.l @r1, r6 /* 3rd arg */ + /* Check TLB exception or not */ + mov.l _L.TLB_PROT_ST, r1 + cmp/hi r1, r0 + bt 1f + + /* tlb_exception(curproc, trapframe, trunc_page(TEA)); */ + mov.l _L.VPN_MASK, r1 + and r1, r6 /* va = trunc_page(va) */ + __EXCEPTION_UNBLOCK(r0, r1) + mov.l _L.tlb, r0 + jsr @r0 + mov r14, r5 /* 2nd arg */ + bra 2f + nop + + /* general_exception(curproc, trapframe, TEA); */ +1: mov r4, r8 +#ifdef DDB + mov #0, r2 + MOV (BBRA, r1) + mov.w r2, @r1 /* disable UBC */ + mov.l r2, @(TF_UBC, r14) /* clear trapframe->tf_ubc */ +#endif /* DDB */ + __EXCEPTION_UNBLOCK(r0, r1) + mov.l _L.general, r0 + jsr @r0 + mov r14, r5 /* 2nd arg */ + + /* Check for ASTs on exit to user mode. */ + mov r8, r4 + mov.l _L.ast, r0 + jsr @r0 + mov r14, r5 +#ifdef DDB /* BBRA = trapframe->tf_ubc */ + __EXCEPTION_BLOCK(r0, r1) + mov.l @(TF_UBC, r14), r0 + MOV (BBRA, r1) + mov.w r0, @r1 +#endif /* DDB */ +2: __EXCEPTION_RETURN + /* NOTREACHED */ + .align 2 +_L.curproc: .long _C_LABEL(curproc) +REG_SYMBOL(EXPEVT) +REG_SYMBOL(BBRA) +REG_SYMBOL(TEA) +_L.tlb: .long _C_LABEL(tlb_exception) +_L.general: .long _C_LABEL(general_exception) +_L.ast: .long _C_LABEL(ast) +_L.TLB_PROT_ST: .long 0xc0 +_L.VPN_MASK: .long 0xfffff000 + +/* LINTSTUB: Var: char sh_vector_generic_end[1]; */ +VECTOR_END_MARKER(sh_vector_generic_end) + SET_ENTRY_SIZE(sh_vector_generic) + + +#ifdef SH3 +/* + * LINTSTUB: Var: char sh3_vector_tlbmiss[1]; + * + * void sh3_vector_tlbmiss(void) __attribute__((__noreturn__)) + * Copied to VBR+0x400. This code should be position independent + * and no more than 512 bytes long (== 0x600 - 0x400). + */ +NENTRY(sh3_vector_tlbmiss) + __EXCEPTION_ENTRY + mov #(SH3_TEA & 0xff), r0 + mov.l @r0, r6 /* 3rd arg: va = TEA */ +#if !defined(P1_STACK) + /* Load kernel stack */ + mov.l __L.VPN_MASK, r0 + and r6, r0 + tst r0, r0 /* check VPN == 0 */ + bt 6f + mov.l _L.CURUPTE, r1 + mov.l @r1, r1 + mov #UPAGES,r3 + mov #1, r2 +4: mov.l @r1+, r7 + cmp/eq r7, r0 /* md_upte.addr: u-area VPN */ + bt 5f + add #4, r1 /* skip md_upte.data */ + cmp/eq r2, r3 + bf/s 4b + add #1, r2 + bra 7f /* pull insn at 6f into delay slot */ + mov #(SH3_EXPEVT & 0xff), r0 +5: mov.l @r1, r2 /* md_upte.data: u-area PTE */ + mov #(SH3_PTEL & 0xff), r1 + mov.l r2, @r1 + mov #(SH3_PTEH & 0xff), r1 + mov.l @r1, r2 + mov.l __L.VPN_MASK, r0 + and r2, r0 + mov.l r0, @r1 /* ASID 0 */ + ldtlb + bra 3f + mov.l r2, @r1 /* restore ASID */ +#endif /* !P1_STACK */ +6: mov #(SH3_EXPEVT & 0xff), r0 +7: mov.l @r0, r0 + mov.l r0, @(TF_EXPEVT, r14) /* trapframe->tf_expevt = EXPEVT */ + mov.l 2f, r0 + mov.l @r0, r4 /* 1st arg */ + __INTR_MASK(r0, r1) + __EXCEPTION_UNBLOCK(r0, r1) + mov.l 1f, r0 + jsr @r0 + mov r14, r5 /* 2nd arg */ +3: __EXCEPTION_RETURN + .align 2 +2: .long _C_LABEL(curproc) +1: .long _C_LABEL(tlb_exception) +__L.VPN_MASK: .long 0xfffff000 +_L.CURUPTE: .long _C_LABEL(curupte) + +/* LINTSTUB: Var: char sh3_vector_tlbmiss_end[1]; */ +VECTOR_END_MARKER(sh3_vector_tlbmiss_end) + SET_ENTRY_SIZE(sh3_vector_tlbmiss) +#endif /* SH3 */ + + +#ifdef SH4 +/* + * LINTSTUB: Var: char sh4_vector_tlbmiss[1]; + * + * void sh4_vector_tlbmiss(void) __attribute__((__noreturn__)) + * Copied to VBR+0x400. This code should be position independent + * and no more than 512 bytes long (== 0x600 - 0x400). + */ +NENTRY(sh4_vector_tlbmiss) + __EXCEPTION_ENTRY + mov.l _L.TEA4, r0 + mov.l @r0, r6 + mov.l _L.EXPEVT4, r0 + mov.l @r0, r0 + mov.l r0, @(TF_EXPEVT, r14) /* trapframe->tf_expevt = EXPEVT */ + mov.l 2f, r0 + mov.l @r0, r4 /* 1st arg */ + __INTR_MASK(r0, r1) + __EXCEPTION_UNBLOCK(r0, r1) + mov.l 1f, r0 + jsr @r0 + mov r14, r5 /* 2nd arg */ + __EXCEPTION_RETURN + .align 2 +1: .long _C_LABEL(tlb_exception) +2: .long _C_LABEL(curproc) +_L.EXPEVT4: .long SH4_EXPEVT +_L.TEA4: .long SH4_TEA + +/* LINTSTUB: Var: char sh4_vector_tlbmiss_end[1]; */ +VECTOR_END_MARKER(sh4_vector_tlbmiss_end) + SET_ENTRY_SIZE(sh4_vector_tlbmiss) +#endif /* SH4 */ + + +/* + * LINTSTUB: Var: char sh_vector_interrupt[1]; + * + * void sh_vector_interrupt(void) __attribute__((__noreturn__)): + * copied to VBR+0x600. This code should be relocatable. + */ +NENTRY(sh_vector_interrupt) + __EXCEPTION_ENTRY + xor r0, r0 + mov.l r0, @(TF_EXPEVT, r14) /* (for debug) */ + stc r0_bank,r6 /* ssp */ + /* Enable exception for P3 access */ + __INTR_MASK(r0, r1) + __EXCEPTION_UNBLOCK(r0, r1) + /* uvmexp.intrs++ */ + mov.l __L.uvmexp.intrs, r0 + mov.l @r0, r1 + add #1 r1 + mov.l r1, @r0 + /* Dispatch interrupt handler */ + mov.l __L.intc_intr, r0 + jsr @r0 /* intc_intr(ssr, spc, ssp) */ + nop + /* Check for ASTs on exit to user mode. */ + mov.l 1f, r0 + mov.l @r0, r4 /* 1st arg */ + mov.l __L.ast, r0 + jsr @r0 + mov r14, r5 /* 2nd arg */ + __EXCEPTION_RETURN + .align 2 +1: .long _C_LABEL(curproc) +__L.intc_intr: .long _C_LABEL(intc_intr) +__L.ast: .long _C_LABEL(ast) +__L.uvmexp.intrs: .long _C_LABEL(uvmexp) + UVMEXP_INTRS + +/* LINTSTUB: Var: char sh_vector_interrupt_end[1]; */ +VECTOR_END_MARKER(sh_vector_interrupt_end) + SET_ENTRY_SIZE(sh_vector_interrupt) diff --git a/sys/arch/sh/sh/vm_machdep.c b/sys/arch/sh/sh/vm_machdep.c new file mode 100644 index 00000000000..20bb7adc942 --- /dev/null +++ b/sys/arch/sh/sh/vm_machdep.c @@ -0,0 +1,364 @@ +/* $OpenBSD: vm_machdep.c,v 1.1 2006/10/06 21:02:55 miod Exp $ */ +/* $NetBSD: vm_machdep.c,v 1.53 2006/08/31 16:49:21 matt Exp $ */ + +/*- + * Copyright (c) 2002 The NetBSD Foundation, Inc. All rights reserved. + * Copyright (c) 1982, 1986 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the Systems Programming Group of the University of Utah Computer + * Science Department, and William Jolitz. + * + * 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. 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. + * + * @(#)vm_machdep.c 7.3 (Berkeley) 5/13/91 + */ + +/*- + * Copyright (c) 1995 Charles M. Hannum. All rights reserved. + * Copyright (c) 1989, 1990 William Jolitz + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the Systems Programming Group of the University of Utah Computer + * Science Department, and William Jolitz. + * + * 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. + * + * @(#)vm_machdep.c 7.3 (Berkeley) 5/13/91 + */ + +/* + * Utah $Hdr: vm_machdep.c 1.16.1.1 89/06/23$ + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/proc.h> +#include <sys/malloc.h> +#include <sys/vnode.h> +#include <sys/buf.h> +#include <sys/user.h> +#include <sys/core.h> +#include <sys/exec.h> +#include <sys/ptrace.h> +#include <sys/signalvar.h> + +#include <uvm/uvm_extern.h> + +#include <sh/locore.h> +#include <sh/cpu.h> +#include <sh/reg.h> +#include <sh/mmu.h> +#include <sh/cache.h> + +extern void proc_trampoline(void); + +/* + * Finish a fork operation, with process p2 nearly set up. + * Copy and update the pcb and trap frame, making the child ready to run. + * + * Rig the child's kernel stack so that it will start out in + * proc_trampoline() and call child_return() with p2 as an + * argument. This causes the newly-created child process to go + * directly to user level with an apparent return value of 0 from + * fork(), while the parent process returns normally. + * + * p1 is the process being forked; if p1 == &proc0, we are creating + * a kernel thread, and the return path and argument are specified with + * `func' and `arg'. + * + * If an alternate user-level stack is requested (with non-zero values + * in both the stack and stacksize args), set up the user stack pointer + * accordingly. + */ +void +cpu_fork(struct proc *p1, struct proc *p2, void *stack, size_t stacksize, + void (*func)(void *), void *arg) +{ + struct pcb *pcb; + struct trapframe *tf; + struct switchframe *sf; + vaddr_t spbase, fptop; +#define P1ADDR(x) (SH3_PHYS_TO_P1SEG(*__pmap_kpte_lookup(x) & PG_PPN)) + + KDASSERT(p1 == curproc || p1 == &proc0); + + /* Copy flags */ + p2->p_md.md_flags = p1->p_md.md_flags; + + pcb = NULL; /* XXXGCC: -Wuninitialized */ +#ifdef SH3 + /* + * Convert frame pointer top to P1. because SH3 can't make + * wired TLB entry, context store space accessing must not cause + * exception. For SH3, we are 4K page, P3/P1 conversion don't + * cause virtual-aliasing. + */ + if (CPU_IS_SH3) + pcb = (struct pcb *)P1ADDR((vaddr_t)&p2->p_addr->u_pcb); +#endif /* SH3 */ +#ifdef SH4 + /* SH4 can make wired entry, no need to convert to P1. */ + if (CPU_IS_SH4) + pcb = &p2->p_addr->u_pcb; +#endif /* SH4 */ + + p2->p_md.md_pcb = pcb; + fptop = (vaddr_t)pcb + PAGE_SIZE; + + /* set up the kernel stack pointer */ + spbase = (vaddr_t)p2->p_addr + PAGE_SIZE; +#ifdef P1_STACK + /* Convert to P1 from P3 */ + /* + * wbinv u-area to avoid cache-aliasing, since kernel stack + * is accessed from P1 instead of P3. + */ + if (SH_HAS_VIRTUAL_ALIAS) + sh_dcache_wbinv_range((vaddr_t)p2->p_addr, USPACE); + spbase = P1ADDR(spbase); +#else /* !P1_STACK */ + /* Prepare u-area PTEs */ +#ifdef SH3 + if (CPU_IS_SH3) + sh3_switch_setup(p2); +#endif +#ifdef SH4 + if (CPU_IS_SH4) + sh4_switch_setup(p2); +#endif +#endif /* !P1_STACK */ + +#ifdef KSTACK_DEBUG + /* Fill magic number for tracking */ + memset((char *)fptop - PAGE_SIZE + sizeof(struct user), 0x5a, + PAGE_SIZE - sizeof(struct user)); + memset((char *)spbase, 0xa5, (USPACE - PAGE_SIZE)); + memset(&pcb->pcb_sf, 0xb4, sizeof(struct switchframe)); +#endif /* KSTACK_DEBUG */ + + /* + * Copy the user context. + */ + p2->p_md.md_regs = tf = (struct trapframe *)fptop - 1; + memcpy(tf, p1->p_md.md_regs, sizeof(struct trapframe)); + + /* + * If specified, give the child a different stack. + */ + if (stack != NULL) + tf->tf_r15 = (u_int)stack + stacksize; + + /* Setup switch frame */ + sf = &pcb->pcb_sf; + sf->sf_r11 = (int)arg; /* proc_trampoline hook func */ + sf->sf_r12 = (int)func; /* proc_trampoline hook func's arg */ + sf->sf_r15 = spbase + USPACE - PAGE_SIZE;/* current stack pointer */ + sf->sf_r7_bank = sf->sf_r15; /* stack top */ + sf->sf_r6_bank = (vaddr_t)tf; /* current frame pointer */ + /* when switch to me, jump to proc_trampoline */ + sf->sf_pr = (int)proc_trampoline; + /* + * Enable interrupt when switch frame is restored, since + * kernel thread begin to run without restoring trapframe. + */ + sf->sf_sr = PSL_MD; /* kernel mode, interrupt enable */ +} + +/* + * Dump the machine specific segment at the start of a core dump. + */ +struct md_core { + struct reg intreg; +}; + +int +cpu_coredump(struct proc *p, struct vnode *vp, struct ucred *cred, + struct core *chdr) +{ + struct md_core md_core; + struct coreseg cseg; + int error; + + CORE_SETMAGIC(*chdr, COREMAGIC, MID_MACHINE, 0); + chdr->c_hdrsize = ALIGN(sizeof(*chdr)); + chdr->c_seghdrsize = ALIGN(sizeof(cseg)); + chdr->c_cpusize = sizeof(md_core); + + /* Save integer registers. */ + error = process_read_regs(p, &md_core.intreg); + if (error) + return error; + + CORE_SETMAGIC(cseg, CORESEGMAGIC, MID_MACHINE, CORE_CPU); + cseg.c_addr = 0; + cseg.c_size = chdr->c_cpusize; + + error = vn_rdwr(UIO_WRITE, vp, (caddr_t)&cseg, chdr->c_seghdrsize, + (off_t)chdr->c_hdrsize, UIO_SYSSPACE, IO_NODELOCKED | IO_UNIT, cred, + NULL, p); + if (error) + return error; + + error = vn_rdwr(UIO_WRITE, vp, (caddr_t)&md_core, sizeof(md_core), + (off_t)(chdr->c_hdrsize + chdr->c_seghdrsize), UIO_SYSSPACE, + IO_NODELOCKED | IO_UNIT, cred, NULL, p); + if (error) + return error; + + chdr->c_nseg++; + return 0; +} + +/* + * Move pages from one kernel virtual address to another. + * Both addresses are assumed to reside in the Sysmap, + * and size must be a multiple of PAGE_SIZE. + */ + +void +pagemove(caddr_t from, caddr_t to, size_t size) +{ + paddr_t pa; + boolean_t rv; + +#ifdef DEBUG + if (size % PAGE_SIZE) + panic("pagemove: size=%08lx", (u_long) size); +#endif + + while (size > 0) { + rv = pmap_extract(pmap_kernel(), (vaddr_t) from, &pa); +#ifdef DEBUG + if (rv == FALSE) + panic("pagemove 2"); + if (pmap_extract(pmap_kernel(), (vaddr_t) to, NULL) == TRUE) + panic("pagemove 3"); +#endif + pmap_kremove((vaddr_t) from, PAGE_SIZE); + pmap_kenter_pa((vaddr_t) to, pa, VM_PROT_READ|VM_PROT_WRITE); + from += PAGE_SIZE; + to += PAGE_SIZE; + size -= PAGE_SIZE; + } + pmap_update(pmap_kernel()); +} + +/* + * Map an IO request into kernel virtual address space. + * All requests are (re)mapped into kernel VA space via the phys_map + * (a name with only slightly more meaning than "kernel_map") + */ + +void +vmapbuf(struct buf *bp, vsize_t len) +{ + vaddr_t faddr, taddr, off; + paddr_t fpa; + pmap_t kpmap, upmap; + + if ((bp->b_flags & B_PHYS) == 0) + panic("vmapbuf"); + bp->b_saveaddr = bp->b_data; + faddr = trunc_page((vaddr_t)bp->b_data); + off = (vaddr_t)bp->b_data - faddr; + len = round_page(off + len); + taddr = uvm_km_valloc_wait(phys_map, len); + bp->b_data = (caddr_t)(taddr + off); + /* + * The region is locked, so we expect that pmap_pte() will return + * non-NULL. + * XXX: unwise to expect this in a multithreaded environment. + * anything can happen to a pmap between the time we lock a + * region, release the pmap lock, and then relock it for + * the pmap_extract(). + * + * no need to flush TLB since we expect nothing to be mapped + * where we we just allocated (TLB will be flushed when our + * mapping is removed). + */ + upmap = vm_map_pmap(&bp->b_proc->p_vmspace->vm_map); + kpmap = vm_map_pmap(phys_map); + while (len) { + pmap_extract(upmap, faddr, &fpa); + pmap_enter(kpmap, taddr, fpa, + VM_PROT_READ | VM_PROT_WRITE, PMAP_WIRED); + faddr += PAGE_SIZE; + taddr += PAGE_SIZE; + len -= PAGE_SIZE; + } + pmap_update(kpmap); +} + +/* + * Free the io map PTEs associated with this IO operation. + * We also invalidate the TLB entries and restore the original b_addr. + */ +void +vunmapbuf(struct buf *bp, vsize_t len) +{ + vaddr_t addr, off; + pmap_t kpmap; + + if ((bp->b_flags & B_PHYS) == 0) + panic("vunmapbuf"); + addr = trunc_page((vaddr_t)bp->b_data); + off = (vaddr_t)bp->b_data - addr; + len = round_page(off + len); + kpmap = vm_map_pmap(phys_map); + pmap_remove(kpmap, addr, addr + len); + pmap_update(kpmap); + uvm_km_free_wakeup(phys_map, addr, len); + bp->b_data = bp->b_saveaddr; + bp->b_saveaddr = 0; +} |