diff --exclude=CVS --exclude=obj.evbsh3 --exclude=compile --exclude='makeBuild*.log' -uNr src.orig/sys/arch/evbsh3/conf/RENESAS7785LCR src-sh4a.orig/sys/arch/evbsh3/conf/RENESAS7785LCR --- src.orig/sys/arch/evbsh3/conf/RENESAS7785LCR 1970-01-01 09:00:00.000000000 +0900 +++ src-sh4a.orig/sys/arch/evbsh3/conf/RENESAS7785LCR 2010-04-07 15:54:23.000000000 +0900 @@ -0,0 +1,62 @@ +# $NetBSD$ +# +# RENESAS7785LCR -- renesas evaluation board R0P7785LC0011RL +# + +machine evbsh3 sh3 +include "conf/std" # MI standard options +include "arch/sh3/conf/std.sh3el" # arch standard options +include "arch/evbsh3/conf/std.renesas7785lcr" + +maxusers 32 # estimated number of users + +#options INCLUDE_CONFIG_FILE # embed config file in kernel binary + +# Enable the hooks used for initializing the root memory-disk. +options MEMORY_DISK_HOOKS +options MEMORY_DISK_IS_ROOT # force root on memory disk +options MEMORY_DISK_SERVER=0 # no userspace memory disk support +options MEMORY_DISK_ROOT_SIZE=8192 # size of memory disk, in blocks +options MEMORY_DISK_RBFLAGS=RB_SINGLE # boot in single-user mode + +# CPU support. +options SH4A_EXT_ADDR32 # 32bit physical address mode. XXXnotyet +#options SH4A_EXT_MMU # TLB-extended mode. XXXnotyet. + +options DEBUG +options DDB # in-kernel debugger +options DIAGNOSTIC # cheap kernel consistency checks +options POOL_DIAGNOSTIC +options LOCKDEBUG # expensive locking checks/support +#options UVMHIST +#options UVMHIST_PRINT +options PGALLOC_VERBOSE + +#options USERCONF # userconf(4) support +#options SYSCTL_INCLUDE_DESCR # Include sysctl descriptions in kernel + +# Compatibility options +options COMPAT_43 # and 4.3BSD +options COMPAT_BSDPTY # /dev/[pt]ty?? ptys. + +# File systems +file-system FFS # UFS +options FFS_NO_SNAPSHOT # No FFS snapshot support +options WAPBL # File system journaling support - Experimental + +# Kernel root file system and dump configuration. +config netbsd root on ? type ? + +# +# Device configuration +# +mainbus0 at root +cpu* at mainbus? +shb* at mainbus? +options SCIFCONSOLE,SCIFCN_SPEED=115200 +scif0 at shb? + +# Pseudo-Devices +pseudo-device md 1 # memory disk device (ramdisk) +pseudo-device pty # pseudo-terminals +pseudo-device clockctl # user control of clock subsystem diff --exclude=CVS --exclude=obj.evbsh3 --exclude=compile --exclude='makeBuild*.log' -uNr src.orig/sys/arch/evbsh3/conf/files.evbsh3 src-sh4a.orig/sys/arch/evbsh3/conf/files.evbsh3 --- src.orig/sys/arch/evbsh3/conf/files.evbsh3 2010-04-07 01:07:22.000000000 +0900 +++ src-sh4a.orig/sys/arch/evbsh3/conf/files.evbsh3 2010-04-07 17:44:00.000000000 +0900 @@ -11,7 +11,7 @@ file arch/evbsh3/evbsh3/autoconf.c file arch/evbsh3/evbsh3/bus_dma.c file arch/evbsh3/evbsh3/conf.c -file arch/evbsh3/evbsh3/machdep.c +file arch/evbsh3/evbsh3/machdep.c sh3 | sh4 file arch/sh3/sh3/disksubr.c disk defparam opt_memsize.h IOM_ROM_BEGIN IOM_ROM_SIZE IOM_RAM_BEGIN IOM_RAM_SIZE diff --exclude=CVS --exclude=obj.evbsh3 --exclude=compile --exclude='makeBuild*.log' -uNr src.orig/sys/arch/evbsh3/conf/files.renesas7785lcr src-sh4a.orig/sys/arch/evbsh3/conf/files.renesas7785lcr --- src.orig/sys/arch/evbsh3/conf/files.renesas7785lcr 1970-01-01 09:00:00.000000000 +0900 +++ src-sh4a.orig/sys/arch/evbsh3/conf/files.renesas7785lcr 2010-04-07 16:01:22.000000000 +0900 @@ -0,0 +1,6 @@ +# $NetBSD$ +# +# RENESAS7785LCR + +file arch/evbsh3/renesas7785lcr/clock_machdep.c +file arch/evbsh3/renesas7785lcr/machdep.c diff --exclude=CVS --exclude=obj.evbsh3 --exclude=compile --exclude='makeBuild*.log' -uNr src.orig/sys/arch/evbsh3/conf/majors.evbsh3 src-sh4a.orig/sys/arch/evbsh3/conf/majors.evbsh3 --- src.orig/sys/arch/evbsh3/conf/majors.evbsh3 2010-04-07 01:07:22.000000000 +0900 +++ src-sh4a.orig/sys/arch/evbsh3/conf/majors.evbsh3 2010-04-07 15:38:45.000000000 +0900 @@ -1,52 +1,49 @@ -# $NetBSD: majors.evbsh3,v 1.19 2010/04/06 15:54:30 nonaka Exp $ +# $NetBSD: majors.hpcsh,v 1.22 2008/11/12 12:36:01 ad Exp $ # -# Device majors for evbsh3 +# Device majors for hpcsh # -device-major cons char 0 -device-major ctty char 1 -device-major mem char 2 -device-major wd char 3 block 0 wd -device-major swap char 4 block 1 vmswap -device-major pts char 5 pty +device-major mem char 0 +device-major swap char 1 block 0 vmswap +device-major cons char 2 +device-major ctty char 3 +device-major filedesc char 4 +device-major log char 5 device-major ptc char 6 pty -device-major log char 7 +device-major pts char 7 pty device-major com char 8 com -device-major scif char 10 scif -device-major sci char 11 sci +device-major wd char 10 block 1 wd -device-major sd char 13 block 4 sd -device-major st char 14 block 5 st -device-major cd char 15 block 6 cd - -device-major ch char 17 ch -device-major ccd char 18 block 16 ccd -device-major ss char 19 ss -device-major uk char 20 uk - -device-major filedesc char 22 -device-major bpf char 23 bpfilter -device-major md char 24 block 17 md - -device-major tun char 40 tun -device-major vnd char 41 block 14 vnd +device-major md char 12 block 6 md +device-major ccd char 13 block 7 ccd +device-major vnd char 14 block 8 vnd +device-major raid char 15 block 9 raid +device-major scsibus char 16 scsibus +device-major sd char 17 block 3 sd +device-major st char 18 block 4 st +device-major cd char 19 block 5 cd +device-major ch char 20 ch +device-major uk char 21 uk +device-major ss char 22 ss +device-major ipl char 23 ipfilter +device-major tun char 24 tun +device-major bpf char 25 bpfilter +device-major wsdisplay char 26 wsdisplay +device-major wskbd char 27 wskbd +device-major wsmouse char 28 wsmouse +device-major wsmux char 29 wsmux +device-major rnd char 30 rnd +device-major scif char 31 scif +device-major sci char 32 sci +device-major biconsdev char 33 biconsdev +device-major clockctl char 34 clockctl +device-major cgd char 36 block 10 cgd +device-major ksyms char 37 ksyms +device-major wsfont char 39 wsfont +device-major apmdev char 40 apmdev device-major audio char 42 audio -device-major ipl char 44 ipfilter - -device-major rnd char 46 rnd -device-major vcoda char 47 vcoda -device-major scsibus char 48 scsibus -device-major raid char 49 block 18 raid -device-major esh char 50 esh -device-major wdog char 51 wdog -device-major clockctl char 52 clockctl -device-major cgd char 54 block 19 cgd -device-major ksyms char 55 ksyms - -device-major ld char 69 block 20 ld - device-major nsmb char 98 nsmb # Majors up to 143 are reserved for machine-dependant drivers. diff --exclude=CVS --exclude=obj.evbsh3 --exclude=compile --exclude='makeBuild*.log' -uNr src.orig/sys/arch/evbsh3/conf/mk.renesas7785lcr src-sh4a.orig/sys/arch/evbsh3/conf/mk.renesas7785lcr --- src.orig/sys/arch/evbsh3/conf/mk.renesas7785lcr 1970-01-01 09:00:00.000000000 +0900 +++ src-sh4a.orig/sys/arch/evbsh3/conf/mk.renesas7785lcr 2010-04-07 15:47:13.000000000 +0900 @@ -0,0 +1,9 @@ +# $NetBSD$ + +DEFTEXTADDR="0x89000000" # u-boot load here. + +SYSTEM_LD_TAIL_EXTRA+=; \ + echo ${OBJCOPY} -S -O binary $@ $@.bin; \ + ${OBJCOPY} -S -O binary $@ $@.bin + +EXTRA_KERNELS+= ${KERNELS:@.KERNEL.@${.KERNEL.}.bin@} diff --exclude=CVS --exclude=obj.evbsh3 --exclude=compile --exclude='makeBuild*.log' -uNr src.orig/sys/arch/evbsh3/conf/std.renesas7785lcr src-sh4a.orig/sys/arch/evbsh3/conf/std.renesas7785lcr --- src.orig/sys/arch/evbsh3/conf/std.renesas7785lcr 1970-01-01 09:00:00.000000000 +0900 +++ src-sh4a.orig/sys/arch/evbsh3/conf/std.renesas7785lcr 2010-04-07 15:50:40.000000000 +0900 @@ -0,0 +1,22 @@ +# $NetBSD$ +# +# standard NetBSD/evbsh3 for RENESAS7785LCR options + +# Pull in RENESAS7785LCR config definitions. +include "arch/evbsh3/conf/files.renesas7785lcr" + +# Executable format options +options EXEC_COFF # 32-bit COFF executables (sh-compiler) + +# CPU support. +options SH4A +options SH7785 +options SH4A_CPUMODE=16 +options SH4A_INPUT_CLOCK=33333333 # 33.333MHz (not PCLOCK) + +# 0x09000000 - 0x1000 +options IOM_RAM_BEGIN=0x08fff000 # Specify VBR address only. + +options EVBSH3_BOARDTYPE=renesas7785lcr +makeoptions BOARDTYPE="renesas7785lcr" +makeoptions BOARDMKFRAG="${THISSH3}/conf/mk.renesas7785lcr" diff --exclude=CVS --exclude=obj.evbsh3 --exclude=compile --exclude='makeBuild*.log' -uNr src.orig/sys/arch/evbsh3/evbsh3/locore.S src-sh4a.orig/sys/arch/evbsh3/evbsh3/locore.S --- src.orig/sys/arch/evbsh3/evbsh3/locore.S 2006-10-07 10:21:47.000000000 +0900 +++ src-sh4a.orig/sys/arch/evbsh3/evbsh3/locore.S 2010-04-07 16:05:15.000000000 +0900 @@ -1,279 +1,11 @@ -/* $NetBSD: locore.S,v 1.11 2006/10/07 01:21:47 tsutsui 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. - * - * @(#)locore.s 7.3 (Berkeley) 5/13/91 - */ - -/*- - * Copyright (c) 1993, 1994, 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. - * - * @(#)locore.s 7.3 (Berkeley) 5/13/91 - */ +/* $NetBSD$ */ #include "opt_cputype.h" -#include "opt_memsize.h" -#include "assym.h" - -#if defined(SH3) && defined(SH4) -#error "evbsh3 port don't support SH3,SH4 common kernel." +#include "opt_evbsh3_boardtype.h" +#if defined SH3 || defined SH4 +#include "locore_sh3_sh4.S" +#elif EVBSH3_BOARDTYPE == renesas7785lcr +#include "../renesas7785lcr/locore.S" +#else +#error #endif - -#include -#include -#include -#include -#include -#include -#include - -#define INIT_STACK \ - ((IOM_RAM_BEGIN + IOM_RAM_SIZE - 0x00001000) | 0x80000000) - -NENTRY(start) -ALTENTRY(kernel_text) - /* Set SP to initial position */ - mov.l XLtmpstk, r15 - - /* Mask all interrupt */ - __INTR_MASK(r0, r1) - - /* Set Register Bank to Bank 0 */ - mov.l SR_init, r0 - ldc r0, sr - - /* MMU off */ - xor r0, r0 - MOV (MMUCR, r2) - mov.l r0, @r2 - - bra start1 - nop - .align 2 -SR_init: .long 0x500000F0 -REG_SYMBOL(MMUCR) -start1: - -#ifdef ROMIMAGE - /* Initialize BUS State Control Regs. */ - mov.l _ROM_START, r3 - mov.l XL_ram_start, r4 - mov.l @r4, r4 - sub r3, r4 - /* Set Bus State Controller */ - mov.l XLInitializeBsc, r0 - sub r4, r0 - jsr @r0 - nop - - /* Move kernel image from ROM area to RAM area */ - mov.l ___end, r0 - mov.l ___start, r1 - mov.l _KERNBASE, r2 - sub r2, r0 - sub r2, r1 - sub r1, r0 - add #4, r0 /* size of bytes to be copied */ - shlr2 r0 /* number of long word */ - mov.l _ROM_START, r3 - add r3, r1 /* src address */ - mov.l ___start, r3 - sub r2, r3 - mov.l XL_ram_start, r4 - mov.l @r4, r4 - add r4, r3 /* dest address */ -1: - mov.l @r1+, r4 - mov.l r4, @r3 - add #4, r3 - dt r0 /* decrement and Test */ - bf 1b - /* kernel image copy end */ - - mov.l LXstart_in_RAM, r0 - jmp @r0 /* jump to RAM area */ - nop - - .align 2 -LXstart_in_RAM: - .long start_in_RAM -XL_ram_start: - .long _C_LABEL(ram_start) -#else /* ROMIMAGE */ -#ifndef DONT_INIT_BSC - /* Set Bus State Controller */ - mov.l XLInitializeBsc, r0 - jsr @r0 - nop -#endif /* !DONT_INIT_BSC */ -#endif /* ROMIMAGE */ - -start_in_RAM: - mova 1f, r0 - mov r0, r4 - mov.l XLinitSH3, r0 - jsr @r0 /* call initSH3() */ - nop - - .align 2 -1: - -#ifdef SH4 - /* CCR must be accessed from P2 area */ - mova cache_on, r0 - mov r0, r5 - mov.l XLtoP2, r1 - add r1, r5 - mova main_label, r0 - mov r0, r2 - MOV (CCR, r3) - mov.l XL_CCRVAL, r4 - jmp @r5 - nop - - .align 2 -cache_on: - mov.l r4, @r3 /* Write to CCR */ - nop - nop - nop - nop - nop - nop - nop - nop - jmp @r2 - nop - - .align 2 -main_label: -#endif /* SH4 */ - mov.l XLmain, r0 - jsr @r0 /* call main() */ - nop - - .align 2 - -#ifndef DONT_INIT_BSC -XLInitializeBsc:.long _C_LABEL(InitializeBsc) -#endif /* DONT_INIT_BSC */ -___start: .long start -___etext: .long _C_LABEL(etext) -___end: .long _C_LABEL(end) -XLtmpstk: .long INIT_STACK -_KERNBASE: .long 0x8c000000 -_ROM_START: .long IOM_ROM_BEGIN -XLinitSH3: .long _C_LABEL(initSH3) -XLmain: .long _C_LABEL(main) -XLtoP2: .long 0x20000000 -REG_SYMBOL(CCR) -#ifdef SH4 -XL_CCRVAL: .long 0x0909 /* Operand cache ON */ -#endif /* SH4 */ - -load_and_reset: - mov.l XL_start_address, r0 - mov r0, r8 - mov.l @r4+, r1 /* r1 = osimage size */ - mov.l @r4+, r2 /* r2 = check sum */ - shlr2 r1 /* r1 = osimage size in dword */ -1: - mov.l @r4+, r3 - mov.l r3, @r0 - add #4, r0 - dt r1 - bf 1b - - jmp @r8 /* jump to start address */ - nop - - .align 2 -XL_start_address: - .long IOM_RAM_BEGIN + 0x00010000 -load_and_reset_end: - -ENTRY(XLoadAndReset) - __INTR_MASK(r0, r1) - /* copy trampoline code to RAM area top */ - mov.l XL_load_and_reset, r0 - mov.l XL_load_and_reset_end, r1 - mov.l XL_load_trampoline_addr, r2 - mov r2, r8 - sub r0, r1 /* r1 = bytes to be copied */ -1: mov.b @r0+, r3 - mov.b r3, @r2 - add #1, r2 - dt r1 - bf 1b - - jmp @r8 /* jump to trampoline code */ - nop - - .align 2 -XL_load_trampoline_addr: - .long IOM_RAM_BEGIN + 0x00008000 -XL_load_and_reset: - .long load_and_reset -XL_load_and_reset_end: - .long load_and_reset_end diff --exclude=CVS --exclude=obj.evbsh3 --exclude=compile --exclude='makeBuild*.log' -uNr src.orig/sys/arch/evbsh3/evbsh3/locore_sh3_sh4.S src-sh4a.orig/sys/arch/evbsh3/evbsh3/locore_sh3_sh4.S --- src.orig/sys/arch/evbsh3/evbsh3/locore_sh3_sh4.S 1970-01-01 09:00:00.000000000 +0900 +++ src-sh4a.orig/sys/arch/evbsh3/evbsh3/locore_sh3_sh4.S 2010-01-06 19:11:51.000000000 +0900 @@ -0,0 +1,279 @@ +/* $NetBSD: locore.S,v 1.11 2006/10/07 01:21:47 tsutsui 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. + * + * @(#)locore.s 7.3 (Berkeley) 5/13/91 + */ + +/*- + * Copyright (c) 1993, 1994, 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. + * + * @(#)locore.s 7.3 (Berkeley) 5/13/91 + */ + +#include "opt_cputype.h" +#include "opt_memsize.h" +#include "assym.h" + +#if defined(SH3) && defined(SH4) +#error "evbsh3 port don't support SH3,SH4 common kernel." +#endif + +#include +#include +#include +#include +#include +#include +#include + +#define INIT_STACK \ + ((IOM_RAM_BEGIN + IOM_RAM_SIZE - 0x00001000) | 0x80000000) + +NENTRY(start) +ALTENTRY(kernel_text) + /* Set SP to initial position */ + mov.l XLtmpstk, r15 + + /* Mask all interrupt */ + __INTR_MASK(r0, r1) + + /* Set Register Bank to Bank 0 */ + mov.l SR_init, r0 + ldc r0, sr + + /* MMU off */ + xor r0, r0 + MOV (MMUCR, r2) + mov.l r0, @r2 + + bra start1 + nop + .align 2 +SR_init: .long 0x500000F0 +REG_SYMBOL(MMUCR) +start1: + +#ifdef ROMIMAGE + /* Initialize BUS State Control Regs. */ + mov.l _ROM_START, r3 + mov.l XL_ram_start, r4 + mov.l @r4, r4 + sub r3, r4 + /* Set Bus State Controller */ + mov.l XLInitializeBsc, r0 + sub r4, r0 + jsr @r0 + nop + + /* Move kernel image from ROM area to RAM area */ + mov.l ___end, r0 + mov.l ___start, r1 + mov.l _KERNBASE, r2 + sub r2, r0 + sub r2, r1 + sub r1, r0 + add #4, r0 /* size of bytes to be copied */ + shlr2 r0 /* number of long word */ + mov.l _ROM_START, r3 + add r3, r1 /* src address */ + mov.l ___start, r3 + sub r2, r3 + mov.l XL_ram_start, r4 + mov.l @r4, r4 + add r4, r3 /* dest address */ +1: + mov.l @r1+, r4 + mov.l r4, @r3 + add #4, r3 + dt r0 /* decrement and Test */ + bf 1b + /* kernel image copy end */ + + mov.l LXstart_in_RAM, r0 + jmp @r0 /* jump to RAM area */ + nop + + .align 2 +LXstart_in_RAM: + .long start_in_RAM +XL_ram_start: + .long _C_LABEL(ram_start) +#else /* ROMIMAGE */ +#ifndef DONT_INIT_BSC + /* Set Bus State Controller */ + mov.l XLInitializeBsc, r0 + jsr @r0 + nop +#endif /* !DONT_INIT_BSC */ +#endif /* ROMIMAGE */ + +start_in_RAM: + mova 1f, r0 + mov r0, r4 + mov.l XLinitSH3, r0 + jsr @r0 /* call initSH3() */ + nop + + .align 2 +1: + +#ifdef SH4 + /* CCR must be accessed from P2 area */ + mova cache_on, r0 + mov r0, r5 + mov.l XLtoP2, r1 + add r1, r5 + mova main_label, r0 + mov r0, r2 + MOV (CCR, r3) + mov.l XL_CCRVAL, r4 + jmp @r5 + nop + + .align 2 +cache_on: + mov.l r4, @r3 /* Write to CCR */ + nop + nop + nop + nop + nop + nop + nop + nop + jmp @r2 + nop + + .align 2 +main_label: +#endif /* SH4 */ + mov.l XLmain, r0 + jsr @r0 /* call main() */ + nop + + .align 2 + +#ifndef DONT_INIT_BSC +XLInitializeBsc:.long _C_LABEL(InitializeBsc) +#endif /* DONT_INIT_BSC */ +___start: .long start +___etext: .long _C_LABEL(etext) +___end: .long _C_LABEL(end) +XLtmpstk: .long INIT_STACK +_KERNBASE: .long 0x8c000000 +_ROM_START: .long IOM_ROM_BEGIN +XLinitSH3: .long _C_LABEL(initSH3) +XLmain: .long _C_LABEL(main) +XLtoP2: .long 0x20000000 +REG_SYMBOL(CCR) +#ifdef SH4 +XL_CCRVAL: .long 0x0909 /* Operand cache ON */ +#endif /* SH4 */ + +load_and_reset: + mov.l XL_start_address, r0 + mov r0, r8 + mov.l @r4+, r1 /* r1 = osimage size */ + mov.l @r4+, r2 /* r2 = check sum */ + shlr2 r1 /* r1 = osimage size in dword */ +1: + mov.l @r4+, r3 + mov.l r3, @r0 + add #4, r0 + dt r1 + bf 1b + + jmp @r8 /* jump to start address */ + nop + + .align 2 +XL_start_address: + .long IOM_RAM_BEGIN + 0x00010000 +load_and_reset_end: + +ENTRY(XLoadAndReset) + __INTR_MASK(r0, r1) + /* copy trampoline code to RAM area top */ + mov.l XL_load_and_reset, r0 + mov.l XL_load_and_reset_end, r1 + mov.l XL_load_trampoline_addr, r2 + mov r2, r8 + sub r0, r1 /* r1 = bytes to be copied */ +1: mov.b @r0+, r3 + mov.b r3, @r2 + add #1, r2 + dt r1 + bf 1b + + jmp @r8 /* jump to trampoline code */ + nop + + .align 2 +XL_load_trampoline_addr: + .long IOM_RAM_BEGIN + 0x00008000 +XL_load_and_reset: + .long load_and_reset +XL_load_and_reset_end: + .long load_and_reset_end diff --exclude=CVS --exclude=obj.evbsh3 --exclude=compile --exclude='makeBuild*.log' -uNr src.orig/sys/arch/evbsh3/include/vmparam.h src-sh4a.orig/sys/arch/evbsh3/include/vmparam.h --- src.orig/sys/arch/evbsh3/include/vmparam.h 2001-02-07 23:53:09.000000000 +0900 +++ src-sh4a.orig/sys/arch/evbsh3/include/vmparam.h 2010-01-06 19:11:51.000000000 +0900 @@ -4,9 +4,14 @@ #include -#define VM_PHYSSEG_MAX 1 - +#ifdef SH4A_EXT_ADDR32 +#define VM_PHYSSEG_MAX 4 +#define VM_NFREELIST 2 +#define VM_FREELIST_P1ACCESS 1 +#else +#define VM_PHYSSEG_MAX 2 #define VM_NFREELIST 1 +#endif #define VM_FREELIST_DEFAULT 0 #endif /* _EVBSH3_VMPARAM_H_ */ diff --exclude=CVS --exclude=obj.evbsh3 --exclude=compile --exclude='makeBuild*.log' -uNr src.orig/sys/arch/evbsh3/renesas7785lcr/clock_machdep.c src-sh4a.orig/sys/arch/evbsh3/renesas7785lcr/clock_machdep.c --- src.orig/sys/arch/evbsh3/renesas7785lcr/clock_machdep.c 1970-01-01 09:00:00.000000000 +0900 +++ src-sh4a.orig/sys/arch/evbsh3/renesas7785lcr/clock_machdep.c 2010-04-07 15:52:15.000000000 +0900 @@ -0,0 +1,42 @@ +/* $NetBSD$ */ + +/*- + * 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. + * + * 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 +__KERNEL_RCSID(0, "$NetBSD$"); + +#include +#include + +#include + +void +machine_clock_init(void) +{ + + sh_clock_init(0); +} diff --exclude=CVS --exclude=obj.evbsh3 --exclude=compile --exclude='makeBuild*.log' -uNr src.orig/sys/arch/evbsh3/renesas7785lcr/locore.S src-sh4a.orig/sys/arch/evbsh3/renesas7785lcr/locore.S --- src.orig/sys/arch/evbsh3/renesas7785lcr/locore.S 1970-01-01 09:00:00.000000000 +0900 +++ src-sh4a.orig/sys/arch/evbsh3/renesas7785lcr/locore.S 2010-01-06 19:11:51.000000000 +0900 @@ -0,0 +1,79 @@ +/* $NetBSD$ */ +/*- + * Copyright (c) 2009 UCHIYAMA Yasushi. 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 + +__KERNEL_RCSID(0, "$NetBSD$") + + .align 2 + .section .text + .globl start +start: +1: mov.l .L_led, r0 + mov #0x4, r1 + mov.l r1, @r0 +/* + bra 1b + nop +*/ + /* Change BANK0 */ + stc sr, r1 + mov.l .L_SR_RB0, r0 + and r0, r1 + ldc r1, sr + + mov.l .L_machine_startup, r0 + mov.l .L_stack_start, r15 + jmp @r0 + nop + /* NOTREACHED */ + .align 2 +.L_led: + .long 0xa4000008 +.L_machine_startup: + .long machine_startup +.L_stack_start: + .long 0x89000000 +.L_SR_RB0: + .long 0xdfffffff + +/*XXX*/ +NENTRY (_cpu_run_P2) + sts pr, r0 + mov.l .L_P2, r1 + or r1, r0 + lds r0, pr + rts + nop +.L_P2: .long 0x20000000 + +NENTRY (_cpu_run_P1) + sts pr, r0 + mov.l .L_P1, r1 + and r1, r0 + lds r0, pr + rts + nop +.L_P1: .long 0xdfffffff + diff --exclude=CVS --exclude=obj.evbsh3 --exclude=compile --exclude='makeBuild*.log' -uNr src.orig/sys/arch/evbsh3/renesas7785lcr/machdep.c src-sh4a.orig/sys/arch/evbsh3/renesas7785lcr/machdep.c --- src.orig/sys/arch/evbsh3/renesas7785lcr/machdep.c 1970-01-01 09:00:00.000000000 +0900 +++ src-sh4a.orig/sys/arch/evbsh3/renesas7785lcr/machdep.c 2010-01-06 19:11:51.000000000 +0900 @@ -0,0 +1,197 @@ +/* $NetBSD$ */ +/*- + * Copyright (c) 2009 UCHIYAMA Yasushi. 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 +__KERNEL_RCSID(0, "$NetBSD$"); + +#include "opt_ddb.h" +#include "opt_kgdb.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +char machine[] = MACHINE; +char machine_arch[] = MACHINE_ARCH; + +void led(uint8_t); +uint8_t dip_switch(void); + +void machine_startup(void) __attribute__((noreturn)); +void main(void) __attribute__((__noreturn__)); + +void +machine_startup() +{ + extern char edata[], end[]; + + // Clear bss. + memset(edata, 0, end - edata); + consinit(); + + // Initialize Cache, MMU, Exception handler. + sh_cpu_init(CPU_ARCH_SH4A, CPU_PRODUCT_7785); + + // Load memory to UVM + struct { + int kernel; + paddr_t addr; + psize_t size; + int list; + } ram_region [] = { +#ifdef SH4A_EXT_ADDR32 + // Load all memory. + { FALSE, 0x08000000, 0x1000000 - 0x1000, + VM_FREELIST_P1ACCESS },//SKIP VBR area 0x08fff000 + { TRUE, 0x09000000, 0x07000000, VM_FREELIST_P1ACCESS }, +#if 1 +#if 1 + { FALSE, 0x40000000, 0x08000000, VM_FREELIST_DEFAULT }, + { FALSE, 0x50000000, 0x10000000, VM_FREELIST_DEFAULT }, +#else + { FALSE, 0x40000000, 0x01000000, VM_FREELIST_DEFAULT }, + { FALSE, 0x50000000, 0x0b007000, VM_FREELIST_DEFAULT }, +#endif +#endif +#else + // Load memory mapped P1/P2. + { FALSE, 0x08000000, 0x1000000 - 0x1000, + VM_FREELIST_DEFAULT },//SKIP VBR XXX see sh3_machdep.c + { TRUE, 0x09000000, 0x07000000, VM_FREELIST_DEFAULT }, +#endif + }, *p; + vaddr_t kernend = atop(round_page(SH3_P1SEG_TO_PHYS(end))); + + physmem = 0; + int i; + for (i = 0, p = ram_region; + i < sizeof ram_region / sizeof(ram_region[0]); i++, p++) { + uvm_page_physload(atop(p->addr), atop(p->addr + p->size), + p->kernel ? kernend : atop(p->addr), atop(p->addr + p->size), + p->list); + physmem += atop(p->size); + printf ("load %lx-%lx\n", p->addr, p->addr + p->size); + } + + // Initialize lwp0 u-area. (construct the 1st switch frame). + sh_proc0_init(); + + /* Initialize pmap and start to address translation */ + pmap_bootstrap(); + +// pmap_growkernel(VM_MAX_KERNEL_ADDRESS);//XXX + + // Jump to main(). use lwp0 kernel stack. + __asm volatile ( + "jmp @%0;" + "mov %1, r15" + :: "r"(main),"r"(lwp0.l_md.md_pcb->pcb_sf.sf_r7_bank)); + // NOTREACHED +} + +void +consinit() +{ + static int initted; + + if (initted++) + return; + + cninit(); +} + +void +cpu_startup() +{ + + sh_startup(); + printf("Renesas evaluation board R0P7785LC0011RL\n"); +} + +void +cpu_reboot (int howto, char *bootstr) +{ + if (howto & RB_HALT) { + *POFCR = 1; // Shutdown board. + } else { + // Reset board peripherals. + *LOCALCR = 1; + delay(100); // at least 10us. + cpu_reset(); + } + while (/*CONSTCOND*/1) + ; + // NOTREACHED +} + +// Called from sh_vector_interrupt() +void +intc_intr(int ssr, int spc, int ssp) +{ + static uint8_t heartbeat; + uint32_t intevc = *INTEVT; + struct intr_table *handler = intr_table + (intevc >> 3); + +// printf ("%d<=\n", handler->level); + if (intevc == 0x580) { //TMU0 TUNI0 + struct clockframe cf; + cf.spc = spc; + cf.ssr = ssr; + cf.ssp = ssp; + handler->func(&cf); + } else { + +// printf("device\n"); + handler->func(handler->arg); +// printf("device done\n"); + } + + led(heartbeat ^= 1); +} + +// Renesas evaluation board R0P7785LC0011RL specific functions. +uint8_t +dip_switch() +{ + + return *SWSR; +} + +void +led(uint8_t r) +{ + + *LEDCR = r; +} + diff --exclude=CVS --exclude=obj.evbsh3 --exclude=compile --exclude='makeBuild*.log' -uNr src.orig/sys/arch/evbsh3/renesas7785lcr/reg.h src-sh4a.orig/sys/arch/evbsh3/renesas7785lcr/reg.h --- src.orig/sys/arch/evbsh3/renesas7785lcr/reg.h 1970-01-01 09:00:00.000000000 +0900 +++ src-sh4a.orig/sys/arch/evbsh3/renesas7785lcr/reg.h 2010-01-06 19:11:51.000000000 +0900 @@ -0,0 +1,40 @@ +/* $NetBSD$ */ +/*- + * Copyright (c) 2009 UCHIYAMA Yasushi. 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. + */ +// Renesas evaluation board R0P7785LC0011RL + +#ifndef _RENESAS_7785LCR_REG_H_ +#define _RENESAS_7785LCR_REG_H_ + +//R0P7786LC0011RL PLD internal register +// LED +#define LEDCR ((volatile uint8_t *)0xa4000008) +// Dip switch +#define SWSR ((volatile uint8_t *)0xa400000a) +// Shutdown +#define POFCR ((volatile uint8_t *)0xa4000006) +// Peripheral reset +#define LOCALCR ((volatile uint8_t *)0xa4000004) + +#endif diff --exclude=CVS --exclude=obj.evbsh3 --exclude=compile --exclude='makeBuild*.log' -uNr src.orig/sys/arch/sh3/7785/clock.c src-sh4a.orig/sys/arch/sh3/7785/clock.c --- src.orig/sys/arch/sh3/7785/clock.c 1970-01-01 09:00:00.000000000 +0900 +++ src-sh4a.orig/sys/arch/sh3/7785/clock.c 2010-01-06 19:11:51.000000000 +0900 @@ -0,0 +1,243 @@ +/* $NetBSD$ */ +/*- + * Copyright (c) 2009 UCHIYAMA Yasushi. 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. + */ + +// SH7785 clock module. SH7785 don't have RTC module. + +#include +__KERNEL_RCSID(0, "$NetBSD$"); + +#include + +#include + +#include +#include +#include +#include +#include + +#ifndef HZ +#define HZ 64 +#endif + +static vaddr_t timer_base[] = { T0_BASE, T1_BASE, T2_BASE, + T3_BASE, T4_BASE, T5_BASE }; +enum timer_counter_match { + COUNTER_STOP, + COUNTER_RESET, +}; + +enum timer_counter_unit { + COUNTER_USEC, + COUNTER_MSEC, + COUNTER_RAW, +}; + +enum timer_channel { + TIMER0, + TIMER1, + TIMER2, + TIMER3, + TIMER4, + TIMER5, +}; + +enum timer_cmd { + TIMER_START, + TIMER_STOP, + TIMER_BUSY, +}; + +static bool timer_start(int, uint32_t, enum timer_counter_unit, + enum timer_counter_match, bool); +static bool tmu_start(int, enum timer_cmd); +static intr_handler_t tmu0_intr; + +static u_int sh_timecounter_get(struct timecounter *); +static uint32_t udelay_param; + +void +sh_clock_init(int flags) +{ + + udelay_param = cpg_pck () / 1000000 / 4; +} + + +int +sh_clock_get_pclock() +{ + + return cpg_pck (); +} + +int +sh_clock_get_cpuclock() +{ + + return cpg_ick (); +} + +u_int +sh_timecounter_get(struct timecounter *tc) +{ + + return 0xffffffff - *TCNT1; +} + +void +setstatclockrate(int newhz) +{ +} + + +void +cpu_initclocks() +{ + static struct timecounter __tc; // don't allocate stack. + + // Hard clock. + timer_start(TIMER0, 1000000 / HZ, COUNTER_USEC, COUNTER_RESET, TRUE); +//XXX timer_start(TIMER0, 1000, COUNTER_MSEC, COUNTER_RESET, TRUE); + intc_intr_establish(0x580, IST_LEVEL, IPL_CLOCK, tmu0_intr, 0); +// intc_intr_enable(0x580); + + // Freerunning counter timercounter(9) + timer_start(TIMER1, 0xffffffff, COUNTER_RAW, COUNTER_RESET, FALSE); + + __tc.tc_get_timecount = sh_timecounter_get; + __tc.tc_frequency = cpg_pck() / 4; + __tc.tc_name = "tmu0_pclock_4"; + __tc.tc_quality = 0; + __tc.tc_counter_mask = 0xffffffff; + tc_init(&__tc); +} + +void +delay(int n) +{ + int s = _cpu_intr_suspend(); + + *TSTR1 &= ~TSTR_STR5; // Stop TMU5 + *TCNT5 = n * udelay_param; + *TCOR5 = 0; + *TCR5 = TPSC_PCK_4; + *TSTR1 |= TSTR_STR5; // Start TMU5 + while ((*TCR5 & TCR_UNF) == 0) + ; + *TSTR1 &= ~TSTR_STR5; // Stop TMU5 + + _cpu_intr_resume(s); +} + +int +tmu0_intr(void *arg) +{ +// printf("tmu0_intr\n"); + *TCR0 &= ~TCR_UNF; // Clear underflow. + hardclock(arg); + + return 0; +} + +static inline void +__reg_write_4(enum timer_channel ch, uint32_t offset, uint32_t val) +{ + *(volatile uint32_t *)(timer_base[ch] + offset) = val; +} + +static inline uint32_t +__reg_read_4(enum timer_channel ch, uint32_t offset) +{ + return *(volatile uint32_t *)(timer_base[ch] + offset); +} + +static inline void +__reg_write_2(enum timer_channel ch, uint32_t offset, uint32_t val) +{ + *(volatile uint16_t *)(timer_base[ch] + offset) = val; +} + +static inline uint16_t +__reg_read_2(enum timer_channel ch, uint32_t offset) +{ + return *(volatile uint16_t *)(timer_base[ch] + offset); +} + +bool +timer_start(int channel, uint32_t interval, + enum timer_counter_unit counter_unit, + enum timer_counter_match counter_conf, bool interrupt) +{ + extern uint32_t udelay_param; + uint16_t r; + + tmu_start(channel, TIMER_STOP); + + if (counter_unit != COUNTER_RAW) { + if (counter_unit == COUNTER_MSEC) + interval *= 1000; + interval *= udelay_param; + } + __reg_write_4(channel, T_CNT, interval); + __reg_write_4(channel, T_COR, + counter_conf == COUNTER_STOP ? 0 : interval); + + r = TPSC_PCK_4; + if (interrupt) + r |= TCR_UNIE; // Underflow interrupt. + __reg_write_2(channel, T_CR, r); + + return tmu_start(channel, TIMER_START); +} + +bool +tmu_start (int channel, enum timer_cmd cmd) +{ + volatile uint8_t *start_reg; + uint8_t bit; + + if (channel < 3) { + start_reg = TSTR0; + bit = 1 << channel; + } else { + start_reg = TSTR1; + bit = 1 << (channel - 3); + } + + switch (cmd) + { + case TIMER_START: + *start_reg |= bit; + return TRUE; + case TIMER_STOP: + *start_reg &= ~bit; + return TRUE; + case TIMER_BUSY: + return *start_reg & bit; + } + + return FALSE; +} diff --exclude=CVS --exclude=obj.evbsh3 --exclude=compile --exclude='makeBuild*.log' -uNr src.orig/sys/arch/sh3/7785/cpg.c src-sh4a.orig/sys/arch/sh3/7785/cpg.c --- src.orig/sys/arch/sh3/7785/cpg.c 1970-01-01 09:00:00.000000000 +0900 +++ src-sh4a.orig/sys/arch/sh3/7785/cpg.c 2010-01-06 19:11:51.000000000 +0900 @@ -0,0 +1,82 @@ +/* $NetBSD$ */ +/*- + * Copyright (c) 2009 UCHIYAMA Yasushi. 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 "opt_sh4a_cpumode.h" +#include "opt_sh4a_input_clock.h" + +#include +__KERNEL_RCSID(0, "$NetBSD: cache_sh4.c,v 1.20 2008/04/28 20:23:35 martin Exp $"); + +#include +#include + + +static int cpg_freq[] = { 0, 18 * 8, 9 * 8, 6 * 8, 9 * 4, + 3 * 8, 9 * 2, 2 * 8, 3 * 4, 9, 8, 3 * 2 }; + +#define CPG_FREQ_SCALE (SH4A_CPUMODE >= 16 ? 8/*mode 16-19*/ : 4/*mode 0-3*/) + +void +cpg_dump() +{ + const char *clk [] = { "P", "DU", "GDTA", "DDR", "B", "SH", "U", "I" }; + int div[] ={ 0, 2, 4, 6, 8, 12, 16, 18, + 24, 32, 36, 48, -1, -1, -1, -1 }; + uint32_t r = *FRQMR1; + int i; + + for (i = 0; i < 8; i++) { + int j = (r >> (i * 4)) & 0xf; + printf("%sck 1/%d ", clk[i], div[j]); + if (div[j] > 0) + printf("%dMHz\n", + SH4A_INPUT_CLOCK / CPG_FREQ_SCALE * + cpg_freq[j]/ 1000000 + 1); + else + printf("Disabled.\n"); + } +} + +uint32_t +cpg_pck() +{ + uint32_t r = *FRQMR1; + + uint32_t hz = SH4A_INPUT_CLOCK / + CPG_FREQ_SCALE * cpg_freq[(r >> PFC_SHIFT) & 0xf]; + + return hz; +} + +uint32_t +cpg_ick() +{ + uint32_t r = *FRQMR1; + + uint32_t hz = SH4A_INPUT_CLOCK / + CPG_FREQ_SCALE * cpg_freq[(r >> IFC_SHIFT) & 0xf]; + + return hz; +} diff --exclude=CVS --exclude=obj.evbsh3 --exclude=compile --exclude='makeBuild*.log' -uNr src.orig/sys/arch/sh3/7785/cpg.h src-sh4a.orig/sys/arch/sh3/7785/cpg.h --- src.orig/sys/arch/sh3/7785/cpg.h 1970-01-01 09:00:00.000000000 +0900 +++ src-sh4a.orig/sys/arch/sh3/7785/cpg.h 2010-01-06 19:11:51.000000000 +0900 @@ -0,0 +1,134 @@ +/* $NetBSD$ */ +/*- + * Copyright (c) 2009 UCHIYAMA Yasushi. 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. + */ +// SH7785 Clock Pulse Generator + +#ifndef _CPG_H_ +#define _CPG_H_ +// Frequency Control Register +#define FRQCR0 ((volatile uint32_t *)0xffc80000) +#define FRQCR0_CODE 0xcf000000 +#define FRQCR0_FRQE 0x1 // Frequency change sequence enable + +#define FRQCR1 ((volatile uint32_t *)0xffc80004) +// CPU (Ick) +#define IFC_SHIFT 28 +#define IFC3 0x80000000 +#define IFC2 0x40000000 +#define IFC1 0x20000000 +#define IFC0 0x10000000 +#define IFC_2 IFC0 // 1/2 +#define IFC_4 IFC1 // 1/4 +#define IFC_6 (IFC0 | IFC1) // 1/6 +// RAM (Uck) +#define UFC_SHIFT 24 +#define UFC3 0x08000000 +#define UFC2 0x04000000 +#define UFC1 0x02000000 +#define UFC0 0x01000000 +#define UFC_4 UFC1 // 1/4 +#define UFC_6 (UFC0 | UFC1) // 1/6 +// SuperHyway (SHck) +#define SFC_SHIFT 20 +#define SFC3 0x00800000 +#define SFC2 0x00400000 +#define SFC1 0x00200000 +#define SFC0 0x00100000 +#define SFC_4 SFC1 // 1/4 +#define SFC_6 (SFC0 | SFC1) // 1/6 +// Bus (Bck) +#define BFC_SHIFT 16 +#define BFC3 0x00080000 +#define BFC2 0x00040000 +#define BFC1 0x00020000 +#define BFC0 0x00010000 +#define BFC_12 (BFC2 | BFC0) +#define BFC_16 (BFC2 | BFC1) +#define BFC_18 (BFC2 | BFC1 | BFC0) +#define BFC_24 BFC3 +#define BFC_32 (BFC3 | BFC0) +#define BFC_36 (BFC3 | BFC1) +#define BFC_48 (BFC3 | BFC1 | BFC0) +// DDR (DDRck) +#define MFC_SHIFT 12 +#define MFC3 0x00008000 +#define MFC2 0x00004000 +#define MFC1 0x00002000 +#define MFC0 0x00001000 +#define MFC_4 MFC1 +#define MFC_6 (MFC1 | MFC0) +// GDTA (GAck) +#define S2FC_SHIFT 8 +#define S2FC3 0x00000800 +#define S2FC2 0x00000400 +#define S2FC1 0x00000200 +#define S2FC0 0x00000100 +#define S2FC_8 S2FC2 +#define S2FC_12 (S2FC2 | S2FC0) +// DU (DUck) +#define S3FC_SHIFT 4 +#define S3FC3 0x00000080 +#define S3FC2 0x00000040 +#define S3FC1 0x00000020 +#define S3FC0 0x00000010 +#define S3FC_8 S3FC2 +#define S3FC_12 (S3FC2 | S3FC0) +#define S3FC_16 (S3FC2 | S3FC1) +#define S3FC_18 (S3FC2 | S3FC1 | S3FC0) +#define S3FC_24 S3FC3 +#define S3FC_32 (S3FC3 | S3FC0) +#define S3FC_36 (S3FC3 | S3FC1) +#define S3FC_48 (S3FC3 | S3FC1 | S3FC0) +// Peripheral (Pck) +#define PFC_SHIFT 0 +#define PFC3 0x00000008 +#define PFC2 0x00000004 +#define PFC1 0x00000002 +#define PFC0 0x00000001 +#define PFC_8 PFC2 +#define PFC_24 PFC3 +#define PFC_32 (PFC3 | PFC0) +#define PFC_36 (PFC3 | PFC1) +#define PFC_48 (PFC3 | PFC1 | PFC0) + +// Frequency Display Register +#define FRQMR1 ((volatile uint32_t *)0xffc80014) +// Sleep Control Register +#define SLPCR ((volatile uint32_t *)0xffc80020) +// PLL Control Register +#define PLLCR ((volatile uint32_t *)0xffc80024) +#define PLLCR_CKOFF 0x2 // CLKOUT output enable. + +// Stanby Control Regsiter +#define MSTPCR0 ((volatile uint32_t *)0xffc80030) +#define MSTPCR1 ((volatile uint32_t *)0xffc80034) +// Stanby Display Register +#define MSTPMR ((volatile uint32_t *)0xffc80044) + +__BEGIN_DECLS +uint32_t cpg_pck(void); +uint32_t cpg_ick(void); +void cpg_dump(void); +__END_DECLS +#endif diff --exclude=CVS --exclude=obj.evbsh3 --exclude=compile --exclude='makeBuild*.log' -uNr src.orig/sys/arch/sh3/7785/intc.h src-sh4a.orig/sys/arch/sh3/7785/intc.h --- src.orig/sys/arch/sh3/7785/intc.h 1970-01-01 09:00:00.000000000 +0900 +++ src-sh4a.orig/sys/arch/sh3/7785/intc.h 2010-01-06 19:11:51.000000000 +0900 @@ -0,0 +1,53 @@ +/* $NetBSD$ */ +/*- + * Copyright (c) 2009 UCHIYAMA Yasushi. 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. + */ + +// SH7785 INTC + +#ifndef _INTC_H_ +#define _INTC_H_ + +#define INT2MSKR ((volatile uint32_t *)0xffd40038) +#define INT2MSKCR ((volatile uint32_t *)0xffd4003c) +#define INT2PRI0 ((volatile uint32_t *)0xffd40000) +#define INT2PRI1 ((volatile uint32_t *)0xffd40004) +#define INT2PRI2 ((volatile uint32_t *)0xffd40008) + +#define INT2B0 ((volatile uint32_t *)0xffd40040) +#define INT2A0 ((volatile uint32_t *)0xffd40030) +#define INT2A1 ((volatile uint32_t *)0xffd40034) + +#define EXPEVT ((volatile uint32_t *)0xff000024) +#define INTEVT ((volatile uint32_t *)0xff000028) + +__BEGIN_DECLS +typedef int (intr_handler_t)(void *); +struct intr_table { + intr_handler_t *func; + void *arg; + int level; +}; +extern struct intr_table intr_table[]; +__END_DECLS +#endif diff --exclude=CVS --exclude=obj.evbsh3 --exclude=compile --exclude='makeBuild*.log' -uNr src.orig/sys/arch/sh3/7785/interrupt.c src-sh4a.orig/sys/arch/sh3/7785/interrupt.c --- src.orig/sys/arch/sh3/7785/interrupt.c 1970-01-01 09:00:00.000000000 +0900 +++ src-sh4a.orig/sys/arch/sh3/7785/interrupt.c 2010-01-06 19:11:51.000000000 +0900 @@ -0,0 +1,143 @@ +/* $NetBSD$ */ +/*- + * Copyright (c) 2009 UCHIYAMA Yasushi. 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. + */ + +// SH7785 INTC module. + +#include +__KERNEL_RCSID(0, "$NetBSD$"); + +#include +#include +#include + +#include +#include + +intr_handler_t null_intr; + +struct intr_table intr_table[512]; // INTEVT: 0x1c0-0xfe0 -> 56-508 + +void +intc_init(void) +{ + size_t i; + + for (i = 0; i < sizeof intr_table / sizeof (intr_table[0]); i++) + intr_table[i].func = null_intr; +} + +void * +intc_intr_establish(int intevt, int trigger, int level, int (*ih_func)(void *), + void *ih_arg) +{ + struct intr_table *p = intr_table + (intevt >> 3); + + p->func = ih_func; + p->arg = ih_arg; + p->level = level; + intc_intr_enable(intevt); + + return p; +} + +void +intc_intr_disestablish(void *arg) +{ + struct intr_table *p = (struct intr_table *)arg; + + p->func = null_intr; + p->arg = NULL; +} + +void +intc_intr_enable(int intevt) +{ + + switch (intevt) { + case 0x580: // TMU0 TUNI0 + *INT2MSKCR = 1; // unmask TMU0-2 + // Set priority. + *INT2PRI0 |= 0x1f000000; + break; + case 0x5a0: // TMU1 TUNI1 + *INT2MSKCR = 1; // unmask TMU0-2 + *INT2PRI0 |= 0x001f0000; + break; + case 0x5c0: // TMU2 TUNI2 + *INT2MSKCR = 1; // unmask TMU0-2 + *INT2PRI0 |= 0x00001f00; + break; + case 0x780: + *INT2MSKCR = 1 << 3; + *INT2PRI2 |= 0x000f0000; + break; + case 0x7a0: + *INT2MSKCR = 1 << 3; + *INT2PRI2 |= 0x000f0000; + break; + case 0x7c0: + *INT2MSKCR = 1 << 3; + *INT2PRI2 |= 0x000f0000; + break; + case 0x7e0: + *INT2MSKCR = 1 << 3; + *INT2PRI2 |= 0x000f0000; + break; + } +} + +void +intc_intr_disable(int intevt) +{ + + switch (intevt) { + case 0x580: // TMU0 TUNI0 + *INT2PRI0 &= ~0x1f000000; + break; + case 0x5a0: // TMU1 TUNI1 + *INT2PRI0 &= ~0x001f0000; + break; + case 0x5c0: // TMU2 TUNI2 + *INT2PRI0 &= ~0x00001f00; + break; + } +} + +bool +cpu_intr_p(void) +{ + + return curcpu()->ci_idepth >= 0; +} + +int +null_intr (void *ctx) +{ + uint32_t intevt = *INTEVT; + + printf("%x %x\n", intevt, intevt >> 3); + panic("interrupt handler missing"); + return 0; +} diff --exclude=CVS --exclude=obj.evbsh3 --exclude=compile --exclude='makeBuild*.log' -uNr src.orig/sys/arch/sh3/7785/scif.c src-sh4a.orig/sys/arch/sh3/7785/scif.c --- src.orig/sys/arch/sh3/7785/scif.c 1970-01-01 09:00:00.000000000 +0900 +++ src-sh4a.orig/sys/arch/sh3/7785/scif.c 2010-01-06 19:11:51.000000000 +0900 @@ -0,0 +1,1567 @@ +/* $NetBSD: scif.c,v 1.59 2009/04/05 00:22:53 uwe 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. + * + * 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 +__KERNEL_RCSID(0, "$NetBSD: scif.c,v 1.59 2009/04/05 00:22:53 uwe Exp $"); + +#include "opt_kgdb.h" +#include "opt_scif.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include + +#include "locators.h" + + +struct scif_softc { + device_t sc_dev; + + struct tty *sc_tty; + void *sc_si; + + callout_t sc_diag_ch; + +#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; +}; + + +static int scif_match(device_t, cfdata_t, void *); +static void scif_attach(device_t, device_t, void *); + +CFATTACH_DECL_NEW(scif, sizeof(struct scif_softc), + scif_match, scif_attach, NULL, NULL); + +static int scif_attached = 0; /* XXX: FIXME: don't limit to just one! */ + +extern struct cfdriver scif_cd; + +#define SCIFUNIT_MASK 0x7ffff +#define SCIFDIALOUT_MASK 0x80000 + +#define SCIFUNIT(x) (minor(x) & SCIFUNIT_MASK) +#define SCIFDIALOUT(x) (minor(x) & SCIFDIALOUT_MASK) + + +/* console */ +dev_type_cnprobe(scifcnprobe); +dev_type_cninit(scifcninit); +dev_type_cngetc(scifcngetc); +dev_type_cnputc(scifcnputc); + + +/* cdevsw */ +dev_type_open(scifopen); +dev_type_close(scifclose); +dev_type_read(scifread); +dev_type_write(scifwrite); +dev_type_ioctl(scifioctl); +dev_type_stop(scifstop); +dev_type_tty(sciftty); +dev_type_poll(scifpoll); + +const struct cdevsw scif_cdevsw = { + scifopen, scifclose, scifread, scifwrite, scifioctl, + scifstop, sciftty, scifpoll, nommap, ttykqfilter, D_TTY +}; + + +/* struct tty */ +static void scifstart(struct tty *); +static int scifparam(struct tty *, struct termios *); + + +void InitializeScif (unsigned int); +int ScifErrCheck(void); +void scif_putc(unsigned char); +unsigned char scif_getc(void); + +static int scifintr(void *); +static void scifsoft(void *); +static void scif_rxsoft(struct scif_softc *, struct tty *); +static void scif_txsoft(struct scif_softc *, struct tty *); +#if 0 +static void scif_stsoft(struct scif_softc *, struct tty *); +#endif +static void scif_schedrx(struct scif_softc *); +static void scifdiag(void *); + +static void scif_break(struct scif_softc *, int); +static void scif_iflush(struct scif_softc *); + + +/* Hardware flag masks (sc_hwflags) */ +#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 +#define SCIF_HW_KGDB 0x80 + + +/* Buffer size for character buffer */ +#define SCIF_RING_SIZE 2048 +static unsigned int scif_rbuf_size = SCIF_RING_SIZE; + +/* Stop input when 3/4 of the ring is full; restart when only 1/4 is full. */ +static unsigned int scif_rbuf_hiwat = (SCIF_RING_SIZE * 1) / 4; +static unsigned int scif_rbuf_lowat = (SCIF_RING_SIZE * 3) / 4; + +#ifdef SCIFCN_SPEED +unsigned int scifcn_speed = SCIFCN_SPEED; +#else +unsigned int scifcn_speed = 9600; +#endif + +#define CONMODE ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8) /* 8N1 */ +int scifconscflag = CONMODE; + +static int scifisconsole = 0; + +#ifdef KGDB +static int kgdb_attached = 0; +#endif + + +#define divrnd(n, q) (((n)*2/(q)+1)/2) /* divide and round off */ + + +/* 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)) +#ifndef SH7785 +#define scif_fdr_read() SHREG_SCFDR2 +#endif +#if defined SH4 || defined SH4A /* 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 */ + +#ifdef SH7785 +#define SCSMR1 ((volatile uint16_t *)0xffeb0000) +#define SCBRR1 ((volatile uint8_t *) 0xffeb0004) +#define SCSCR1 ((volatile uint16_t *)0xffeb0008) +#define SCFTDR1 ((volatile uint8_t *) 0xffeb000c) +#define SCFSR1 ((volatile uint16_t *)0xffeb0010) +#define SCFRDR1 ((volatile uint8_t *) 0xffeb0014) +#define SCFCR1 ((volatile uint16_t *)0xffeb0018) + +#define SCTFDR ((volatile uint16_t *)0xffeb001c)// TX FIFO cnt. +#define SCRFDR ((volatile uint16_t *)0xffeb0020)// RX FIFO cnt. +#define SCSPTR ((volatile uint16_t *)0xffeb0024)// serial port +#define SCLSR ((volatile uint16_t *)0xffeb0028)// line status +#define SCRER ((volatile uint16_t *)0xffeb002c)// error +#endif + +void +InitializeScif(unsigned int bps) +{ +#ifdef SH7785 + *SCSCR1 = 0x2; /*CKE1 external clock */ + *SCSCR1 |= (1 << 5)/*TE*/ | (1 << 4)/*RE*/; + *SCSMR1 = 1/*CKS0*/; + *SCBRR1 = 0; + *SCFCR1 = 0; + +#else + /* 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 */ +#endif +} + +int +ScifErrCheck(void) +{ + + return (scif_ssr_read() & (SCSSR2_ER | SCSSR2_FER | SCSSR2_PER)); +} + +void +scif_putc(unsigned char c) +{ +#ifdef SH7785 + while ((*SCFSR1 & (1 << 5)/*TDFE*/) == 0) + ; + *SCFTDR1 = c; + *SCFSR1 &= ~((1 << 5)/*TDFE*/ | (1 << 6)/*TEND*/); + while ((*SCFSR1 & (1 << 6)/*TEND*/) == 0) + ; +#else + /* 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)); +#endif +} + +unsigned char +scif_getc(void) +{ +#ifdef SH7785 + uint8_t c; + + while (((c = *SCFSR1) & 0x2/*RDF*/) == 0) + ; + + c = *SCFRDR1; + *SCFSR1 &= ~0x2/*RDF*/; + return c; +#else + unsigned char c, err_c; +#if defined SH4 || defined SH4A + 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)); +#if defined SH4 || defined SH4A + 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) + { +#if defined SH4 || defined SH4A + if ((CPU_IS_SH4 || CPU_IS_SH4A) && ((err_c2 & SCLSR2_ORER) == 0)) +#endif + return(c); + } + } +#endif +} + +static int +scif_match(device_t parent, cfdata_t cfp, void *aux) +{ + + if (scif_attached) + return 0; + + if (strcmp(cfp->cf_name, "scif") != 0) + return 0; + + return 1; +} + +static void +scif_attach(device_t parent, device_t self, void *aux) +{ + struct scif_softc *sc; + struct tty *tp; + + sc = device_private(self); + sc->sc_dev = self; + + scif_attached = 1; + + sc->sc_hwflags = 0; /* XXX */ + sc->sc_swflags = 0; /* XXX */ + sc->sc_fifolen = 16; + + aprint_normal("\n"); + if (scifisconsole) { + aprint_naive(" (console)\n"); + aprint_normal_dev(self, "console\n"); + SET(sc->sc_hwflags, SCIF_HW_CONSOLE); + SET(sc->sc_swflags, TIOCFLAG_SOFTCAR); + } +#ifdef KGDB + else if (kgdb_attached) { + aprint_naive(" (kgdb)\n"); + aprint_normal_dev(self, "kgdb\n"); + SET(sc->sc_hwflags, SCIF_HW_KGDB); + SET(sc->sc_swflags, TIOCFLAG_SOFTCAR); + } +#endif + else { + aprint_naive("\n"); + InitializeScif(9600); /* XXX */ + } + + callout_init(&sc->sc_diag_ch, 0); +#ifdef SH4 + intc_intr_establish(SH4_INTEVT_SCIF_ERI, IST_LEVEL, IPL_SERIAL, + scifintr, sc); + intc_intr_establish(SH4_INTEVT_SCIF_RXI, IST_LEVEL, IPL_SERIAL, + scifintr, sc); + intc_intr_establish(SH4_INTEVT_SCIF_BRI, IST_LEVEL, IPL_SERIAL, + scifintr, sc); + intc_intr_establish(SH4_INTEVT_SCIF_TXI, IST_LEVEL, IPL_SERIAL, + scifintr, sc); +#endif +#ifdef SH4A + intc_intr_establish(0x780, IST_LEVEL, IPL_SERIAL, + scifintr, sc); + intc_intr_establish(0x7a0, IST_LEVEL, IPL_SERIAL, + scifintr, sc); + intc_intr_establish(0x7c0, IST_LEVEL, IPL_SERIAL, + scifintr, sc); + intc_intr_establish(0x7e0, IST_LEVEL, IPL_SERIAL, + scifintr, sc); +#endif +#ifdef SH3 + intc_intr_establish(SH7709_INTEVT2_SCIF_ERI, IST_LEVEL, IPL_SERIAL, + scifintr, sc); + intc_intr_establish(SH7709_INTEVT2_SCIF_RXI, IST_LEVEL, IPL_SERIAL, + scifintr, sc); + intc_intr_establish(SH7709_INTEVT2_SCIF_BRI, IST_LEVEL, IPL_SERIAL, + scifintr, sc); + intc_intr_establish(SH7709_INTEVT2_SCIF_TXI, IST_LEVEL, IPL_SERIAL, + scifintr, sc); +#endif + + sc->sc_si = softint_establish(SOFTINT_SERIAL, 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) { + aprint_error_dev(self, "unable to allocate ring buffer\n"); + return; + } + sc->sc_ebuf = sc->sc_rbuf + (scif_rbuf_size << 1); + + tty_attach(tp); + + /* XXX: TODO */ + if (!pmf_device_register(self, NULL, NULL)) + aprint_error_dev(self, "unable to establish power handler\n"); +} + +/* + * Start or restart transmission. + */ +static void +scifstart(struct tty *tp) +{ + struct scif_softc *sc; + int s; + + sc = device_lookup_private(&scif_cd, SCIFUNIT(tp->t_dev)); + + s = spltty(); + if (ISSET(tp->t_state, TS_BUSY | TS_TIMEOUT | TS_TTSTOP)) + goto out; + if (sc->sc_tx_stopped) + goto out; + if (!ttypull(tp)) + 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; +#ifdef SH7785 + maxchars = sc->sc_fifolen - *SCTFDR; +#else + maxchars = sc->sc_fifolen + - ((scif_fdr_read() & SCFDR2_TXCNT) >> 8); +#endif + 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. + */ +static int +scifparam(struct tty *tp, struct termios *t) +{ + struct scif_softc *sc; + int ospeed = t->c_ospeed; + int s; + + sc = device_lookup_private(&scif_cd, SCIFUNIT(tp->t_dev)); + if (!device_is_active(sc->sc_dev)) + return (EIO); + + /* 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)) { + /* + * !DANGER! SH7709 SCIF module has CTS bug. + * RTSCTS flow control causes data lost. + */ + 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); +} + +static void +scif_iflush(struct scif_softc *sc) +{ + int i; + unsigned char c; +#ifdef SH7785 + i = *SCRFDR; +#else + i = scif_fdr_read() & SCFDR2_RECVCNT; +#endif + 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 lwp *l) +{ + struct scif_softc *sc; + struct tty *tp; + int s, s2; + int error; + + sc = device_lookup_private(&scif_cd, SCIFUNIT(dev)); + if (sc == 0 || !ISSET(sc->sc_hwflags, SCIF_HW_DEV_OK) || + sc->sc_rbuf == NULL) + return (ENXIO); + + if (!device_is_active(sc->sc_dev)) + return (ENXIO); + +#ifdef KGDB + /* + * If this is the kgdb port, no other use is permitted. + */ + if (ISSET(sc->sc_hwflags, SCIF_HW_KGDB)) + return (EBUSY); +#endif /* KGDB */ + + tp = sc->sc_tty; + + if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp)) + return (EBUSY); + + s = spltty(); + + /* + * Do the following iff this is a first open. + */ + if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) { + 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(tp, SCIFDIALOUT(dev), ISSET(flag, O_NONBLOCK)); + if (error) + goto bad; + + error = (*tp->t_linesw->l_open)(dev, tp); + if (error) + goto bad; + + (void) (*tp->t_linesw->l_modem)(tp, 1);//XXX force to carrier -uch + + + return (0); + +bad: + + return (error); +} + +int +scifclose(dev_t dev, int flag, int mode, struct lwp *l) +{ + struct scif_softc *sc; + struct tty *tp; + + sc = device_lookup_private(&scif_cd, SCIFUNIT(dev)); + tp = sc->sc_tty; + + /* XXX This is for cons.c. */ + if (!ISSET(tp->t_state, TS_ISOPEN)) + return (0); + + (*tp->t_linesw->l_close)(tp, flag); + ttyclose(tp); + + if (!device_is_active(sc->sc_dev)) + return (0); + + return (0); +} + +int +scifread(dev_t dev, struct uio *uio, int flag) +{ + struct scif_softc *sc; + struct tty *tp; + + sc = device_lookup_private(&scif_cd, SCIFUNIT(dev)); + tp = sc->sc_tty; + + return ((*tp->t_linesw->l_read)(tp, uio, flag)); +} + +int +scifwrite(dev_t dev, struct uio *uio, int flag) +{ + struct scif_softc *sc; + struct tty *tp; + + sc = device_lookup_private(&scif_cd, SCIFUNIT(dev)); + tp = sc->sc_tty; + + return ((*tp->t_linesw->l_write)(tp, uio, flag)); +} + +int +scifpoll(dev_t dev, int events, struct lwp *l) +{ + struct scif_softc *sc; + struct tty *tp; + + sc = device_lookup_private(&scif_cd, SCIFUNIT(dev)); + tp = sc->sc_tty; + + return ((*tp->t_linesw->l_poll)(tp, events, l)); +} + +struct tty * +sciftty(dev_t dev) +{ + struct scif_softc *sc; + struct tty *tp; + + sc = device_lookup_private(&scif_cd, SCIFUNIT(dev)); + tp = sc->sc_tty; + + return (tp); +} + +int +scifioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) +{ + struct scif_softc *sc; + struct tty *tp; + int error; + int s; + + sc = device_lookup_private(&scif_cd, SCIFUNIT(dev)); + if (!device_is_active(sc->sc_dev)) + return (EIO); + + tp = sc->sc_tty; + error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, l); + if (error != EPASSTHROUGH) + return (error); + + error = ttioctl(tp, cmd, data, flag, l); + if (error != EPASSTHROUGH) + 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 = kauth_authorize_device_tty(l->l_cred, + KAUTH_DEVICE_TTY_PRIVSET, tp); + if (error) + break; + sc->sc_swflags = *(int *)data; + break; + + default: + error = EPASSTHROUGH; + break; + } + + splx(s); + + return (error); +} + +static void +scif_schedrx(struct scif_softc *sc) +{ + + sc->sc_rx_ready = 1; + + /* Wake up the poller. */ + softint_schedule(sc->sc_si); +} + +static 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. + */ +void +scifstop(struct tty *tp, int flag) +{ + struct scif_softc *sc; + int s; + + sc = device_lookup_private(&scif_cd, SCIFUNIT(tp->t_dev)); + + 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); +} + +static 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", + device_xname(sc->sc_dev), + overflows, overflows == 1 ? "" : "s", + floods, floods == 1 ? "" : "s"); +} + +static void +scif_rxsoft(struct scif_softc *sc, struct tty *tp) +{ + int (*rint)(int, struct tty *) = tp->t_linesw->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) + callout_reset(&sc->sc_diag_ch, 60 * hz, scifdiag, sc); + } + + 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); + } +} + +static 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)); + (*tp->t_linesw->l_start)(tp); +} + +#if 0 /* XXX (msaitoh) */ +static void +scif_stsoft(struct scif_softc *sc, struct tty *tp) +{ + 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) (*tp->t_linesw->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; + (*tp->t_linesw->l_start)(tp); + } else { + sc->sc_tx_stopped = 1; + } + } + +#ifdef SCIF_DEBUG + if (scif_debug) + scifstatus(sc, "scif_stsoft"); +#endif +} +#endif /* 0 */ + +static void +scifsoft(void *arg) +{ + struct scif_softc *sc = arg; + struct tty *tp; + + if (!device_is_active(sc->sc_dev)) + return; + + 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); + } +} + +static int +scifintr(void *arg) +{ + struct scif_softc *sc = arg; + u_char *put, *end; + u_int cc; + u_short ssr2; + int count; + + + if (!device_is_active(sc->sc_dev)) { + + panic ("scif"); + return (0); + } + 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)) { + console_debugger(); + } +#endif /* DDB */ + +#ifdef KGDB + if (ISSET(sc->sc_hwflags, SCIF_HW_KGDB)) { + kgdb_connect(1); + } +#endif /* KGDB */ + } +#ifdef SH7785 + count = *SCRFDR; +#else + count = scif_fdr_read() & SCFDR2_RECVCNT; +#endif + 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)); +#if defined SH4 || defined SH4A + if (CPU_IS_SH4 || CPU_IS_SH4A) + 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. + */ +#ifdef SH7785 + if (*SCTFDR != 16) { /* XXX (msaitoh) */ +#else + if (((scif_fdr_read() & SCFDR2_TXCNT) >> 8) != 16) { /* XXX (msaitoh) */ +#endif + /* + * 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; +#ifdef SH7785 + maxchars = sc->sc_fifolen - *SCTFDR; +#else + maxchars = sc->sc_fifolen - + ((scif_fdr_read() & SCFDR2_TXCNT) >> 8); +#endif + 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. */ + softint_schedule(sc->sc_si); + +#if NRND > 0 && defined(RND_SCIF) + rnd_add_uint32(&sc->rnd_source, iir | lsr); +#endif + return (1); +} + +void +scifcnprobe(struct consdev *cp) +{ + int maj; + + /* locate the major number */ + maj = cdevsw_lookup_major(&scif_cdevsw); + + /* Initialize required fields. */ + 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); +} + +#ifdef KGDB +int +scif_kgdb_init(void) +{ + + if (strcmp(kgdb_devname, "scif") != 0) + return (1); + + if (scifisconsole) + return (1); /* can't share with console */ + + InitializeScif(kgdb_rate); + + kgdb_attach((int (*)(void *))scifcngetc, + (void (*)(void *, int))scifcnputc, NULL); + kgdb_dev = 123; /* unneeded, only to satisfy some tests */ + kgdb_attached = 1; + + return (0); +} +#endif /* KGDB */ diff --exclude=CVS --exclude=obj.evbsh3 --exclude=compile --exclude='makeBuild*.log' -uNr src.orig/sys/arch/sh3/7785/tmu.h src-sh4a.orig/sys/arch/sh3/7785/tmu.h --- src.orig/sys/arch/sh3/7785/tmu.h 1970-01-01 09:00:00.000000000 +0900 +++ src-sh4a.orig/sys/arch/sh3/7785/tmu.h 2010-01-06 19:11:51.000000000 +0900 @@ -0,0 +1,107 @@ +/* $NetBSD$ */ +/*- + * Copyright (c) 2009 UCHIYAMA Yasushi. 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. + */ +// SH7785 Timer Unit. + +#ifndef _TMU_H_ +#define _TMU_H_ +// Timer Start Register (0,1,2 common) +#define TSTR0 ((volatile uint8_t *)0xffd80004) +#define TSTR_STR0 0x1 +#define TSTR_STR1 0x2 +#define TSTR_STR2 0x4 + +// Channel 0 +// Timer Constant Register +#define TCOR0 ((volatile uint32_t *)0xffd80008) +// Timer Counter +#define TCNT0 ((volatile uint32_t *)0xffd8000c) +// Timer Control Register +#define TCR0 ((volatile uint16_t *)0xffd80010) +#define TCR2_ICPF 0x200 // Input Captuer Interrupt Flag +#define TCR_UNF 0x100 // Under flow flag. +#define TCR2_ICPE1 0x80 // Input Captuer Control +#define TCR2_ICPE0 0x40 +#define TCPE_DISABLE 0 +#define TCPE_ENABLE TCR2_ICPE1 +#define TCPE_INTR (TCR2_ICPE0 | TCR2_ICPE1) +#define TCR_UNIE 0x20 // Undef flow Interrupt Enable +#define TCR_CKEG1 0x10 // Clock Edge Select +#define TCR_CKEG0 0x8 +#define CKEG_RISING_EDGE 0 +#define CKEG_FALLING_EDGE TCR_CKEG0 +#define CKEG_BOTH_EDGE TCR_CKEG1 +#define TCR_TPSC2 0x4 // Timer Prescaler +#define TCR_TPSC1 0x2 +#define TCR_TPSC0 0x1 +#define TPSC_PCK_4 0 +#define TPSC_PCK_16 TCR_TPSC0 +#define TPSC_PCK_64 TCR_TPSC1 +#define TPSC_PCK_256 (TCR_TPSC0 | TCR_TPSC1) +#define TPSC_PCK_1024 TCR_TPSC2 +// External clock (Channel 0,1,2 only) +#define TPSC_PCK_EXT (TCR_TPSC0 | TCR_TPSC1 | TCR_TPSC2) + +// Channel 1 +#define TCOR1 ((volatile uint32_t *)0xffd80014) +#define TCNT1 ((volatile uint32_t *)0xffd80018) +#define TCR1 ((volatile uint16_t *)0xffd8001c) +// Channel 2 +#define TCOR2 ((volatile uint32_t *)0xffd80020) +#define TCNT2 ((volatile uint32_t *)0xffd80024) +#define TCR2 ((volatile uint16_t *)0xffd80028) +// Input Capture Register +#define TCPR2 ((volatile uint32_t *)0xffd8002c) //RO + +// Timer Start Register (3,4,5 common) +#define TSTR1 ((volatile uint8_t *)0xffdc0004) +#define TSTR_STR3 0x1 +#define TSTR_STR4 0x2 +#define TSTR_STR5 0x4 + +// Channel 3 +#define TCOR3 ((volatile uint32_t *)0xffdc0008) +#define TCNT3 ((volatile uint32_t *)0xffdc000c) +#define TCR3 ((volatile uint16_t *)0xffdc0010) +// Channel 4 +#define TCOR4 ((volatile uint32_t *)0xffdc0014) +#define TCNT4 ((volatile uint32_t *)0xffdc0018) +#define TCR4 ((volatile uint16_t *)0xffdc001c) +// Channel 5 +#define TCOR5 ((volatile uint32_t *)0xffdc0020) +#define TCNT5 ((volatile uint32_t *)0xffdc0024) +#define TCR5 ((volatile uint16_t *)0xffdc0028) + +#define T0_BASE 0xffd80008 +#define T1_BASE 0xffd80014 +#define T2_BASE 0xffd80020 +#define T3_BASE 0xffdc0008 +#define T4_BASE 0xffdc0014 +#define T5_BASE 0xffdc0020 + +#define T_COR 0 +#define T_CNT 4 +#define T_CR 8 + +#endif diff --exclude=CVS --exclude=obj.evbsh3 --exclude=compile --exclude='makeBuild*.log' -uNr src.orig/sys/arch/sh3/conf/files.sh3 src-sh4a.orig/sys/arch/sh3/conf/files.sh3 --- src.orig/sys/arch/sh3/conf/files.sh3 2008-11-22 15:00:26.000000000 +0900 +++ src-sh4a.orig/sys/arch/sh3/conf/files.sh3 2010-01-06 19:11:51.000000000 +0900 @@ -1,9 +1,11 @@ # $NetBSD: files.sh3,v 1.43 2008/11/22 02:12:45 uwe Exp $ # -defflag opt_cputype.h SH3 SH4 +defflag opt_cputype.h SH3 SH4 SH4A defparam PCLOCK +defparam SH4A_CPUMODE +defparam SH4A_INPUT_CLOCK defflag opt_kstack_debug.h KSTACK_DEBUG @@ -17,7 +19,8 @@ file arch/sh3/sh3/cache.c file arch/sh3/sh3/cache_sh3.c sh3 file arch/sh3/sh3/cache_sh4.c sh4 -file arch/sh3/sh3/clock.c +file arch/sh3/sh3/cache_sh4a.c sh4a +file arch/sh3/sh3/clock.c sh3 | sh4 file arch/sh3/sh3/coff_exec.c exec_coff file arch/sh3/sh3/compat_16_machdep.c compat_16 file arch/sh3/sh3/core_machdep.c coredump @@ -29,7 +32,7 @@ file arch/sh3/sh3/devreg.c sh3 & sh4 file arch/sh3/sh3/exception.c file arch/sh3/sh3/exception_vector.S -file arch/sh3/sh3/interrupt.c +file arch/sh3/sh3/interrupt.c sh3 | sh4 file arch/sh3/sh3/kgdb_machdep.c kgdb file arch/sh3/sh3/kobj_machdep.c modular file arch/sh3/sh3/lock_stubs.S @@ -39,7 +42,11 @@ file arch/sh3/sh3/mmu.c file arch/sh3/sh3/mmu_sh3.c sh3 file arch/sh3/sh3/mmu_sh4.c sh4 +file arch/sh3/sh3/mmu_sh4a.c sh4a +file arch/sh3/sh3/pmb.c sh4a +file arch/sh3/sh3/pmb_subr.S sh4a file arch/sh3/sh3/pmap.c +file arch/sh3/sh3/pmap_cache_ops.c file arch/sh3/sh3/process_machdep.c file arch/sh3/sh3/procfs_machdep.c procfs file arch/sh3/sh3/sh3_machdep.c @@ -47,5 +54,10 @@ file arch/sh3/sh3/syscall.c file arch/sh3/sh3/vm_machdep.c +# Product dependent drivers. +file arch/sh3/7785/cpg.c sh7785 +file arch/sh3/7785/clock.c sh7785 +file arch/sh3/7785/interrupt.c sh7785 + file dev/cninit.c file dev/cons.c diff --exclude=CVS --exclude=obj.evbsh3 --exclude=compile --exclude='makeBuild*.log' -uNr src.orig/sys/arch/sh3/conf/files.shb src-sh4a.orig/sys/arch/sh3/conf/files.shb --- src.orig/sys/arch/sh3/conf/files.shb 2006-09-20 09:41:11.000000000 +0900 +++ src-sh4a.orig/sys/arch/sh3/conf/files.shb 2010-01-06 19:11:51.000000000 +0900 @@ -25,7 +25,8 @@ defparam opt_scif.h SCIFCN_SPEED device scif: tty attach scif at shb -file arch/sh3/dev/scif.c scif needs-flag +file arch/sh3/dev/scif.c scif & (sh3 | sh4) needs-flag +file arch/sh3/7785/scif.c scif & sh7785 needs-flag device adc {} attach adc at shb diff --exclude=CVS --exclude=obj.evbsh3 --exclude=compile --exclude='makeBuild*.log' -uNr src.orig/sys/arch/sh3/dev/scif.c src-sh4a.orig/sys/arch/sh3/dev/scif.c --- src.orig/sys/arch/sh3/dev/scif.c 2011-04-27 21:26:33.000000000 +0900 +++ src-sh4a.orig/sys/arch/sh3/dev/scif.c 2011-04-27 21:28:38.000000000 +0900 @@ -303,7 +303,7 @@ #define scif_fdr_read() SHREG_SCFDR2 -#ifdef SH4 /* additional registers in sh4 */ +#if defined SH4 || defined SH4A /* additional registers in sh4 */ #define scif_sptr_read() SHREG_SCSPTR2 #define scif_sptr_write(v) (SHREG_SCSPTR2 = (v)) @@ -313,11 +313,27 @@ #endif /* SH4 */ +#ifdef SH7785 +#define SCSMR1 ((volatile uint16_t *)0xffeb0000) +#define SCBRR1 ((volatile uint8_t *) 0xffeb0004) +#define SCSCR1 ((volatile uint16_t *)0xffeb0008) +#define SCFTDR1 ((volatile uint8_t *) 0xffeb000c) +#define SCFSR1 ((volatile uint16_t *)0xffeb0010) +#define SCFRDR1 ((volatile uint8_t *) 0xffeb0014) +#define SCFCR1 ((volatile uint16_t *)0xffeb0018) +#endif void InitializeScif(unsigned int bps) { +#ifdef SH7785 + *SCSCR1 = 0x2; /*CKE1 external clock */ + *SCSCR1 |= (1 << 5)/*TE*/ | (1 << 4)/*RE*/; + *SCSMR1 = 1/*CKS0*/; + *SCBRR1 = 0; + *SCFCR1 = 0; +#else /* Initialize SCR */ scif_scr_write(0x00); @@ -349,6 +365,7 @@ /* Serial Status Register */ scif_ssr_write(scif_ssr_read() & SCSSR2_TDFE); /* Clear Status */ +#endif } int @@ -361,7 +378,14 @@ void scif_putc(unsigned char c) { - +#ifdef SH7785 + while ((*SCFSR1 & (1 << 5)/*TDFE*/) == 0) + ; + *SCFTDR1 = c; + *SCFSR1 &= ~((1 << 5)/*TDFE*/ | (1 << 6)/*TEND*/); + while ((*SCFSR1 & (1 << 6)/*TEND*/) == 0) + ; +#else /* wait for ready */ while ((scif_fdr_read() & SCFDR2_TXCNT) == SCFDR2_TXF_FULL) continue; @@ -371,13 +395,24 @@ /* clear ready flag */ scif_ssr_write(scif_ssr_read() & ~(SCSSR2_TDFE | SCSSR2_TEND)); +#endif } unsigned char scif_getc(void) { +#ifdef SH7785 + uint8_t c; + + while (((c = *SCFSR1) & 0x2/*RDF*/) == 0) + ; + + c = *SCFRDR1; + *SCFSR1 &= ~0x2/*RDF*/; + return c; +#else unsigned char c, err_c; -#ifdef SH4 +#if defined SH4 || defined SH4A unsigned short err_c2 = 0; /* XXXGCC: -Wuninitialized */ #endif @@ -390,7 +425,7 @@ err_c = scif_ssr_read(); scif_ssr_write(scif_ssr_read() & ~(SCSSR2_ER | SCSSR2_BRK | SCSSR2_RDF | SCSSR2_DR)); -#ifdef SH4 +#if defined SH4 || defined SH4A if (CPU_IS_SH4) { err_c2 = scif_lsr_read(); scif_lsr_write(scif_lsr_read() & ~SCLSR2_ORER); @@ -399,13 +434,13 @@ if ((err_c & (SCSSR2_ER | SCSSR2_BRK | SCSSR2_FER | SCSSR2_PER)) == 0) { -#ifdef SH4 +#if defined SH4 || defined SH4A if (CPU_IS_SH4 && ((err_c2 & SCLSR2_ORER) == 0)) #endif return(c); } } - +#endif } static int @@ -457,7 +492,7 @@ } callout_init(&sc->sc_diag_ch, 0); -#ifdef SH4 +#if defined SH4 || defined SH4A intc_intr_establish(SH4_INTEVT_SCIF_ERI, IST_LEVEL, IPL_SERIAL, scifintr, sc); intc_intr_establish(SH4_INTEVT_SCIF_RXI, IST_LEVEL, IPL_SERIAL, @@ -615,6 +650,10 @@ * mode. */ if (ISSET(t->c_cflag, CRTSCTS)) { + /* + * !DANGER! SH7709 SCIF module has CTS bug. + * RTSCTS flow control causes data lost. + */ scif_fcr_write(scif_fcr_read() | SCFCR2_MCE); } else { scif_fcr_write(scif_fcr_read() & ~SCFCR2_MCE); @@ -809,6 +848,9 @@ if (error) goto bad; + (void) (*tp->t_linesw->l_modem)(tp, 1);//XXX force to carrier -uch + + return (0); bad: @@ -1218,7 +1260,7 @@ scif_ssr_write(scif_ssr_read() & ~(SCSSR2_ER | SCSSR2_RDF | SCSSR2_DR)); -#ifdef SH4 +#if defined SH4 || defined SH4A if (CPU_IS_SH4) scif_lsr_write(scif_lsr_read() & ~SCLSR2_ORER); diff --exclude=CVS --exclude=obj.evbsh3 --exclude=compile --exclude='makeBuild*.log' -uNr src.orig/sys/arch/sh3/include/cache.h src-sh4a.orig/sys/arch/sh3/include/cache.h --- src.orig/sys/arch/sh3/include/cache.h 2008-04-29 11:39:26.000000000 +0900 +++ src-sh4a.orig/sys/arch/sh3/include/cache.h 2010-01-06 19:11:51.000000000 +0900 @@ -183,7 +183,8 @@ void sh_cache_information(void); #define SH_HAS_UNIFIED_CACHE CPU_IS_SH3 -#define SH_HAS_VIRTUAL_ALIAS CPU_IS_SH4 +//XXX-uch bogus define. some SH3 variants has virtual alias. +#define SH_HAS_VIRTUAL_ALIAS (CPU_IS_SH4 || CPU_IS_SH4A) #define SH_HAS_WRITEBACK_CACHE (!sh_cache_write_through) #endif /* _KERNEL */ diff --exclude=CVS --exclude=obj.evbsh3 --exclude=compile --exclude='makeBuild*.log' -uNr src.orig/sys/arch/sh3/include/cache_sh4a.h src-sh4a.orig/sys/arch/sh3/include/cache_sh4a.h --- src.orig/sys/arch/sh3/include/cache_sh4a.h 1970-01-01 09:00:00.000000000 +0900 +++ src-sh4a.orig/sys/arch/sh3/include/cache_sh4a.h 2010-01-06 19:11:51.000000000 +0900 @@ -0,0 +1,162 @@ + +/*- + * Copyright (c) 2009 UCHIYAMA Yasushi. 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. + */ + +// SH4A: SH7780, SH7785 +#ifndef _SH4A_CACHE_H_ +#define _SH4A_CACHE_H_ + +#define SH4A_ICACHE_SIZE 32768 +#define SH4A_DCACHE_SIZE 32768 + +#define SH4A_CACHE_LINESZ 32 +#define SH4A_CACHE_WAY 4 + +// SH4A_DCACHE_SIZE / SH4A_CACHE_LINESZ / SH4A_CACHE_WAY = 256 +#define SH4A_CACHE_ENTRY 256 + +#define ROUND_CACHELINE_32(x) (((x) + 31) & ~31) +#define TRUNC_CACHELINE_32(x) ((x) & ~31) + +// Cache control register +#define SH4A_CCR ((volatile uint32_t *)0xff00001c) +// Instruction Cache Invalidate (all entry) +#define CCR_ICI 0x800 +// Instruction Cache Enable +#define CCR_ICE 0x100 +// Operand Cache Invalidate (all entry) +#define CCR_OCI 0x8 +// P1-area Copy Back mode (1:write-back, 0:write-thru) +#ifndef SH4A_EXT_ADDR32 // PMB->WT bit. +#define CCR_CB 0x4 +#endif +// P0,U0,P3-area Write Thru (1:write-thru, 0:write-back) +#define CCR_WT 0x2 +// Operand Cache Enable +#define CCR_OCE 0x1 + +#define SH4A_QACR0 ((volatile uint32_t *)0xff000038) +// When MMU disable, set physical address 28:26 +#define QACR_AREA_MASK 0x7 +#define QACR_AREA_SHIFT 2 +#define SH4A_QACR1 ((volatile uint32_t *)0xff00003c) + +// RAM Control Register +#define SH4A_RAMCR ((volatile uint32_t *)0xff000074) +// Internal Memmory Access mode. (L-memory) +#define RAMCR_RMD 0x200 +// Internal Memmory Protection. (L-memory) +#define RAMCR_RP 0x100 +// I-cache 2way mode (default 4way) +#define RAMCR_IC2W 0x80 +// D-cache 2way mode (default 4way) +#define RAMCR_OC2W 0x40 +// I-cache way-prediction (SH7785) +#define RAMCR_ICWPD 0x20 + + +// +// Memory-Maped Cache Configuratiion +// + +// I-cache address array +#define SH4A_CCIA 0xf0000000 +// address-field +#define CCIA_A 0x8 // Associative bit. +#define CCIA_ENTRY_MASK 0xff +#define CCIA_ENTRY_SHIFT 5 +#define CCIA_WAY_MASK 0x3 +#define CCIA_WAY_SHIFT 13 +// data-field (physical tag) +#define CCIA_V 0x1 // Valid bit +#define CCIA_TAG_MASK 0x3fffff +#define CCIA_TAG_SHIFT 10 + +// I-cache data array +#define SH4A_CCID 0xf1000000 +// address-filed +#define CCID_LINE_MASK 0x3 // line size is 32B +#define CCID_LINE_SHIFT 2 +#define CCID_ENTRY_MASK 0xff // 256 entry +#define CCID_ENTRY_SHIFT 5 +#define CCID_WAY_MASK 0x3 // 4way +#define CCID_WAY_SHIFT 13 +// data-filed (cached data) +// + + +// D-cache address array +#define SH4A_CCDA 0xf4000000 +// address-field +#define CCDA_A 0x8 // Associative bit. +#define CCDA_ENTRY_MASK 0xff +#define CCDA_ENTRY_SHIFT 5 +#define CCDA_WAY_MASK 0x3 +#define CCDA_WAY_SHIFT 13 +// data-field (physical tag) +#define CCDA_V 0x1 // Valid bit +#define CCDA_U 0x2 // Dirty bit +#define CCDA_TAG_MASK 0x3fffff +#define CCDA_TAG_SHIFT 10 + +// D-cache data array +#define SH4A_CCDD 0xf5000000 +// address-filed +#define CCDD_LINE_MASK 0x3 // line size is 32B +#define CCDD_LINE_SHIFT 2 +#define CCDD_ENTRY_MASK 0xff // 256 entry +#define CCDD_ENTRY_SHIFT 5 +#define CCDD_WAY_MASK 0x3 // 4way +#define CCDD_WAY_SHIFT 13 +// data-field (cached data) +// + +// Store Queue +#define SH4A_SQ 0xe0000000 +#define SQ_BANK 0x20 +#define SQ_LW_MASK 0x7 +#define SQ_LW_SHIFT 2 + +__BEGIN_DECLS +void sh4a_cache_config (void); + +void sh4a_cache_enable (bool); +void sh4a_cache_disable (void); + +void sh4a_icache_sync_all (void); +void sh4a_icache_sync_range (vaddr_t, vsize_t); +void sh4a_icache_sync_range_index (vaddr_t, vsize_t); + +void sh4a_dcache_wbinv_all (void); +void sh4a_dcache_wbinv_range (vaddr_t, vsize_t); +void sh4a_dcache_inv_range (vaddr_t, vsize_t); +void sh4a_dcache_wb_range (vaddr_t, vsize_t); +void sh4a_dcache_wbinv_range_index (vaddr_t, vsize_t); +#ifdef DEBUG +void sh4a_dcache_array_dump (vaddr_t, vsize_t); +#endif + +__END_DECLS + +#endif diff --exclude=CVS --exclude=obj.evbsh3 --exclude=compile --exclude='makeBuild*.log' -uNr src.orig/sys/arch/sh3/include/cputypes.h src-sh4a.orig/sys/arch/sh3/include/cputypes.h --- src.orig/sys/arch/sh3/include/cputypes.h 2009-04-22 07:16:35.000000000 +0900 +++ src-sh4a.orig/sys/arch/sh3/include/cputypes.h 2010-01-06 19:11:51.000000000 +0900 @@ -41,6 +41,7 @@ #define CPU_ARCH_SH3 3 #define CPU_ARCH_SH4 4 +#define CPU_ARCH_SH4A 5 /* SH3 series */ #define CPU_PRODUCT_7708 1 @@ -57,6 +58,9 @@ #define CPU_PRODUCT_7751 10 #define CPU_PRODUCT_7751R 11 +/* SH4A series */ +#define CPU_PRODUCT_7780 12 +#define CPU_PRODUCT_7785 13 #ifndef _LOCORE extern int cpu_arch; @@ -67,11 +71,17 @@ #elif defined(SH3) #define CPU_IS_SH3 (/* CONSTCOND */1) #define CPU_IS_SH4 (/* CONSTCOND */0) +#define CPU_IS_SH4A (/* CONSTCOND */0) #elif defined(SH4) #define CPU_IS_SH3 (/* CONSTCOND */0) #define CPU_IS_SH4 (/* CONSTCOND */1) +#define CPU_IS_SH4A (/* CONSTCOND */0) +#elif defined(SH4A) +#define CPU_IS_SH3 (/* CONSTCOND */0) +#define CPU_IS_SH4 (/* CONSTCOND */0) +#define CPU_IS_SH4A (/* CONSTCOND */1) #else -#error "define SH3 and/or SH4" +#error "define SH3 and/or SH4 or SH4A" #endif #endif /* !_LOCORE */ diff --exclude=CVS --exclude=obj.evbsh3 --exclude=compile --exclude='makeBuild*.log' -uNr src.orig/sys/arch/sh3/include/devreg.h src-sh4a.orig/sys/arch/sh3/include/devreg.h --- src.orig/sys/arch/sh3/include/devreg.h 2008-04-29 11:39:26.000000000 +0900 +++ src-sh4a.orig/sys/arch/sh3/include/devreg.h 2010-01-06 19:11:51.000000000 +0900 @@ -64,7 +64,7 @@ #define SH_(x) __sh_ ## x #elif defined(SH3) #define SH_(x) SH3_ ## x -#elif defined(SH4) +#elif defined(SH4) || defined(SH4A) /*XXX for now.*/ #define SH_(x) SH4_ ## x #endif diff --exclude=CVS --exclude=obj.evbsh3 --exclude=compile --exclude='makeBuild*.log' -uNr src.orig/sys/arch/sh3/include/locore.h src-sh4a.orig/sys/arch/sh3/include/locore.h --- src.orig/sys/arch/sh3/include/locore.h 2011-02-05 00:09:49.000000000 +0900 +++ src-sh4a.orig/sys/arch/sh3/include/locore.h 2011-02-05 00:11:24.000000000 +0900 @@ -51,7 +51,7 @@ #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) +#elif defined(SH4) || defined (SH4A) /*XXX for now.*/ #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) diff --exclude=CVS --exclude=obj.evbsh3 --exclude=compile --exclude='makeBuild*.log' -uNr src.orig/sys/arch/sh3/include/mmu.h src-sh4a.orig/sys/arch/sh3/include/mmu.h --- src.orig/sys/arch/sh3/include/mmu.h 2008-04-29 11:39:26.000000000 +0900 +++ src-sh4a.orig/sys/arch/sh3/include/mmu.h 2010-01-06 19:11:51.000000000 +0900 @@ -53,6 +53,7 @@ void sh_mmu_init(void); void sh_mmu_information(void); void sh_tlb_set_asid(int); +int sh_tlb_get_asid(void); #ifdef SH3 void sh3_mmu_start(void); @@ -70,6 +71,14 @@ void sh4_tlb_update(int, vaddr_t, uint32_t); #endif +#ifdef SH4A +void sh4a_mmu_start(void); +void sh4a_tlb_invalidate_addr(int, vaddr_t); +void sh4a_tlb_invalidate_asid(int); +void sh4a_tlb_invalidate_all(void); +void sh4a_tlb_update(int, vaddr_t, uint32_t); +#endif + #if defined(SH3) && defined(SH4) extern uint32_t __sh_PTEH; @@ -102,6 +111,16 @@ #define sh_tlb_invalidate_all() sh4_tlb_invalidate_all() #define sh_tlb_update(a, va, pte) sh4_tlb_update(a, va, pte) +#elif defined(SH4A) +#define sh_mmu_start() sh4a_mmu_start() +#define sh_tlb_invalidate_addr(a, va) sh4a_tlb_invalidate_addr(a, va) +#define sh_tlb_invalidate_asid(a) sh4a_tlb_invalidate_asid(a) +#define sh_tlb_invalidate_all() sh4a_tlb_invalidate_all() +#define sh_tlb_update(a, va, pte) sh4a_tlb_update(a, va, pte) +int sh4a_wired_counter_alloc (vaddr_t); +void sh4a_wired_counter_dealloc (vaddr_t); +void sh4a_tlb_update_wired(int, vaddr_t, uint32_t); + #endif #endif /* !_SH3_MMU_H_ */ diff --exclude=CVS --exclude=obj.evbsh3 --exclude=compile --exclude='makeBuild*.log' -uNr src.orig/sys/arch/sh3/include/mmu_sh4a.h src-sh4a.orig/sys/arch/sh3/include/mmu_sh4a.h --- src.orig/sys/arch/sh3/include/mmu_sh4a.h 1970-01-01 09:00:00.000000000 +0900 +++ src-sh4a.orig/sys/arch/sh3/include/mmu_sh4a.h 2010-01-06 19:11:51.000000000 +0900 @@ -0,0 +1,415 @@ + +/*- + * Copyright (c) 2009 UCHIYAMA Yasushi. 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. + */ + +// SH4A: SH7785 +// 64entry full-assciative +#ifndef _SH7785_MMU_H_ +#define _SH7785_MMU_H_ +// SH7780 don't have TLB-extended mode. + +// Page Table Entry Hi Register +#define SH4A_PTEH ((volatile uint32_t *)0xff000000) +#define PTEH_VPN 0xfffffc00 // Virtual Page Number +#define PTEH_ASID 0x000000ff // Address Space ID +#define PTEH_VALID_BITS (PTEH_VPN | PTEH_ASID) + +// Page Table Entry Lo Register (LDTLB) +#define SH4A_PTEL ((volatile uint32_t *)0xff000004) +#define PTEL_V 0x100 // Valid +#ifdef SH4A_EXT_ADDR32 +#define PTEL_PPN 0xfffffc00 // Pysical Page Number +#define PTEL_UB 0x200 // Unbuffered write. +#else +#define PTEL_PPN 0x1ffffc00 // 29bit +#endif + +#ifndef SH4A_EXT_MMU // Extended Mode, use Data Array 2. +#define PTEL_SZ1 0x80 // Page size +#define PTEL_PR1 0x40 // Protection key +#define PTEL_PR0 0x20 +#define PTEL_SZ0 0x10 +#define PTEL_SZ_1K 0 +#define PTEL_SZ_4K PTEL_SZ0 +#define PTEL_SZ_64K PTEL_SZ1 +#define PTEL_SZ_1M (PTEL_SZ0 | PTEL_SZ1) +#define PTEL_PR_P_RDONLY 0 +#define PTEL_PR_P_RW PTEL_PR0 +#define PTEL_PR_U_RDONLY PTEL_PR1 +#define PTEL_PR_U_RW (PTEL_PR0 | PTEL_PR1) +#endif //SH4A_EXT_MMU +#define PTEL_C 0x8 // Cacheable +#define PTEL_D 0x4 // Dirty +#define PTEL_SH 0x2 // Shared page (igonre ASID) +#define PTEL_WT 0x1 // Write-thru. (0: Write-back) + +#ifdef SH4A_EXT_ADDR32 // UB bit is added. +#ifdef SH4A_EXT_MMU // page size and protection is setted by PTEA. +#define PTEL_VALID_BITS (PTEL_PPN|PTEL_V|PTEL_UB|PTEL_C|PTEL_D|PTEL_SH|PTEL_WT) +#else +#define PTEL_VALID_BITS (PTEL_PPN|PTEL_V|PTEL_UB|PTEL_C|PTEL_D|PTEL_SH|PTEL_WT | PTEL_SZ1|PTEL_SZ0|PTEL_PR1|PTEL_PR0) +#endif +#else //!SH4A_EXT_ADDR32 +#ifdef SH4A_EXT_MMU +#define PTEL_VALID_BITS (PTEL_PPN|PTEL_V|PTEL_C|PTEL_D|PTEL_SH|PTEL_WT) +#else +#define PTEL_VALID_BITS (PTEL_PPN|PTEL_V|PTEL_C|PTEL_D|PTEL_SH|PTEL_WT | PTEL_SZ1|PTEL_SZ0|PTEL_PR1|PTEL_PR0) +#endif +#endif + +// Translation Table Base Register. (user register) +#define SH4A_TTB ((volatile uint32_t *)0xff000008) + +// TLB Exception Address Register. +#define SH4A_TEA ((volatile uint32_t *)0xff00000c) + +// MMU Control Register. +#define SH4A_MMUCR ((volatile uint32_t *)0xff000010) +#define MMUCR_LRUI_MASK 0x3f // ITLB LRU +#define MMUCR_LRUT_SHIFT 26 +#define MMUCR_URB_MASK 0x3f // UTLB Replace Boundary. +#define MMUCR_URB_SHIFT 18 +#define MMUCR_URC_MASK 0x3f // UTLB Replace Counter. +#define MMUCR_URC_SHIFT 10 +#define MMUCR_SQMD 0x200 // Store Queue Mode. (1: priv only) +// Single Virtual Memory/ Multiple Virtual Memory mode switch +#define MMUCR_SV 0x100 // 1: Single virtual +#define MMUCR_ME 0x80 // TLB Extended mode (SH7785) +#define MMUCR_TI 0x4 // TLB Invalidate bit +#define MMUCR_AT 0x1 // Address Translation Enable bit. + +#ifdef SH4A_EXT_MMU +// Page Table Entry Assistance Register. (SH7785) +// SH7780 don't have this register. +#define SH4A_PTEA ((volatile uint32_t *)0xff000034) +// Page Control Infomation. for TLB Extended mode; MMUCR.ME = 1 +#define PTEA_EPR (0x3f << 8) +#define PTEA_EPR_SHIFT 8 +#define PTEA_ESZ (0xf << 4) +#define PTEA_ESZ_SHIFT 4 +#define PTEA_EPR_P_R 0x2000 +#define PTEA_EPR_P_W 0x1000 +#define PTEA_EPR_P_X 0x800 +#define PTEA_EPR_U_R 0x400 +#define PTEA_EPR_U_W 0x200 +#define PTEA_EPR_U_X 0x100 + +#define PTEA_ESZ_1K 0 +#define PTEA_ESZ_4K 0x10 +#define PTEA_ESZ_8K 0x20 +#define PTEA_ESZ_64K 0x40 +#define PTEA_ESZ_256K 0x50 +#define PTEA_ESZ_1M 0x70 +#define PTEA_ESZ_4M 0x80 +#define PTEA_ESZ_64M 0xc0 +#endif // SH4A_EXT_MMU + +////////////////////////////////////////////////////////////////////// +// Physical Address Space Control Register. (reset 0x0) +#define PASCR ((volatile uint32_t *)0xff000070) +#ifdef SH4A_EXT_ADDR32 +// 16entry Privilege-area Mapping Buffer. +#define PMB_ENTRY 16 + +#define PMB_AA 0xf6100000 +#define PMB_AA_E_MASK 0xf +#define PMB_AA_E_SHIFT 8 +#define PMB_AA_V 0x100 +#define PMB_AA_VPN 0xff000000 +#define PMB_AA_VPN_MASK 0xff +#define PMB_AA_VPN_SHIFT 24 + +#define PMB_AA_VALID_BIT (PMB_AA_VPN|PMB_AA_V) + +#define PMB_DA 0xf7100000 +#define PMB_DA_E_MASK 0xf +#define PMB_DA_E_SHIFT 8 + +#define PMB_DA_PPN 0xff000000 +#define PMB_DA_PPN_MASK 0xff +#define PMB_DA_PPN_SHIFT 24 + +#define PMB_DA_SZ_MASK 0x3 // Page size + +#define PMB_DA_WT 0x1 // Write-thru. +#define PMB_DA_C 0x8 // Cacheable. +#define PMB_DA_V 0x100 // Valid +#define PMB_DA_UB 0x200 // Buffered write. +#define PMB_DA_SZ0 0x10 +#define PMB_DA_SZ1 0x80 +#define PMB_DA_SZ_16M 0 +#define PMB_DA_SZ_64M PMB_DA_SZ0 +#define PMB_DA_SZ_128M PMB_DA_SZ1 +#define PMB_DA_SZ_512M (PMB_DA_SZ0 | PMB_DA_SZ1) +#define _PMB_SZ_INDEX(x) (((da & PMB_DA_SZ0) >> 4) | \ + ((da & PMB_DA_SZ1) >> 6)) + +#define PMB_DA_VALID_BIT (PMB_DA_PPN|PMB_DA_WT|PMB_DA_C|PMB_DA_V| \ + PMB_DA_SZ0|PMB_DA_SZ1|PMB_DA_UB) + + +// 0: 29bit physical address, 1: 32bit physical address. +#define PASCR_SE 0x80000000 +#else // 29bit address. +// 0: Buffered write, 1: Unbuffered write. +// When 32bit address exetended mode, these bits disabled. +#define PASCR_UB0 0x01 +#define PASCR_UB1 0x02 +#define PASCR_UB2 0x04 +#define PASCR_UB3 0x08 +#define PASCR_UB4 0x10 +#define PASCR_UB5 0x20 +#define PASCR_UB6 0x40 +#endif // SH4A_EXT_ADDR32 +#define PASCR_UB7 0x80 + + +////////////////////////////////////////////////////////////////////// +// Instruction Re-Fetch Inhibit Control Register. +#define IRMCR ((volatile uint32_t *)0xff000078) +// MMUCR, PACCR, CCR, RAMCR, PTEH +#define IRMCR_R2 0x10 +// 0xff200000-0xff2fffff +#define IRMCR_R1 0x08 +// LDTLB +#define IRMCR_LT 0x04 +// Memory-maped TLB +#define IRMCR_MT 0x02 +// Memory-maped CACHE +#define IRMCR_MC 0x01 + +////////////////////////////////////////////////////////////////////// +// Memory mapped TLB +// ITLB 4entry +// UTLB 64entry +// +// ITLB Address Array +#define SH4A_ITLB_AA 0xf2000000 +#define SH4A_ITLB_ENTRY 4 +#define ITLB_AA_E_MASK 0x3 // Entry +#define ITLB_AA_E_SHIFT 8 +#define ITLB_AA_VPN 0xfffffc00 +#define ITLB_AA_V 0x100 // Valid +#define ITLB_AA_ASID 0xff +// ITLB Data Array +#define SH4A_ITLB_DA1 0xf3000000 +#define ITLB_DA1_E_MASK 0x3 // Entry +#define ITLB_DA1_E_SHIFT 8 +#ifdef SH4A_EXT_ADDR32 +#define ITLB_DA1_PPN 0xfffffc00 // 32bit +#else +#define ITLB_DA1_PPN 0x1ffffc00 // 29bit +#endif +#define ITLB_DA1_V 0x100 // Valid. +#define ITLB_DA1_C 0x8 // Cacheable. +#define ITLB_DA1_SH 0x2 // Shared page. +#ifndef SH4A_EXT_MMU // TLB Extended mode uses 'ITLB Data Array 2' +#define ITLB_PR 0x40 // User/Privilege +#define ITLB_SZ0 0x10 +#define ITLB_SZ1 0x80 +#define ITLB_SZ_1K 0 +#define ITLB_SZ_4K ITLB_SZ0 +#define ITLB_SZ_64K ITLB_SZ1 +#define ITLB_SZ_1M (ITLB_SZ0 | ITLB_SZ1) +#endif //!SH4A_EXT_MMU + +// UTLB Address Array +#define SH4A_UTLB_AA 0xf6000000 +#define SH4A_UTLB_ENTRY 64 +#define UTLB_AA_E_MASK 0x3f // Entry +#define UTLB_AA_E_SHIFT 8 +#define UTLB_AA_A 0x80 // Associate bit +#define UTLB_AA_VPN 0xfffffc00 +#define UTLB_AA_D 0x200 // Dirty +#define UTLB_AA_V 0x100 // Valid +#define UTLB_AA_ASID 0xff // Address Space ID. + +// UTLB Data Array +#define SH4A_UTLB_DA1 0xf7000000 +#define UTLB_DA1_E_MASK 0x3f // Entry +#define UTLB_DA1_E_SHIFT 8 +#define UTLB_DA1_V 0x100 // Valid +#ifdef SH4A_EXT_ADDR32 +#define UTLB_DA1_PPN 0xfffffc00 // 32bit +#define UTLB_DA1_UB 0x200 // UnBuffered write. +#else +#define UTLB_DA1_PPN 0x1ffffc00 // 29bit +#endif +#ifndef SH4A_EXT_MMU +#define UTLB_PR0 0x20 +#define UTLB_PR1 0x40 +#define UTLB_SZ0 0x10 +#define UTLB_SZ1 0x80 +#define UTLB_SZ_1K 0 +#define UTLB_SZ_4K UTLB_SZ0 +#define UTLB_SZ_64K UTLB_SZ1 +#define UTLB_SZ_1M (UTLB_SZ0 | UTLB_SZ1) +#define UTLB_PR_P_RDONLY 0 +#define UTLB_PR_P_RW UTLB_PR0 +#define UTLB_PR_U_RDONLY UTLB_PR1 +#define UTLB_PR_U_RW (UTLB_PR0 | UTLB_PR1) +#endif //!SH4A_EXT_MMU +#define UTLB_DA1_C 0x8 // Cacheable. +#define UTLB_DA1_D 0x4 +#define UTLB_DA1_SH 0x2 // Shared page. +#define UTLB_DA1_WT 0x1 // Write Thru. + +#ifdef SH4A_EXT_MMU +#define SH4A_ITLB_DA2 0xf3800000 +#define ITLB_DA2_E_MASK 0x3 // Entry +#define ITLB_DA2_E_SHIFT 8 + +#define ITLB_DA2_VALID_MASK 0x2df0 +#define ITLB_DA2_EPR_P_R 0x2000 +#define ITLB_DA2_EPR_P_X 0x800 +#define ITLB_DA2_EPR_U_R 0x400 +#define ITLB_DA2_EPR_U_X 0x100 +#define ITLB_DA2_ESZ_1K 0 +#define ITLB_DA2_ESZ_4K 0x10 +#define ITLB_DA2_ESZ_8K 0x20 +#define ITLB_DA2_ESZ_64K 0x40 +#define ITLB_DA2_ESZ_256K 0x50 +#define ITLB_DA2_ESZ_1M 0x70 +#define ITLB_DA2_ESZ_4M 0x80 +#define ITLB_DA2_ESZ_64M 0xc0 + +#define SH4A_UTLB_DA2 0xf7800000 +#define UTLB_DA2_E_MASK 0x3f // Entry +#define UTLB_DA2_E_SHIFT 8 + +#define UTLB_DA2_VALID_MASK 0x3ff0 +#define UTLB_DA2_EPR_P_R 0x2000 +#define UTLB_DA2_EPR_P_W 0x1000 +#define UTLB_DA2_EPR_P_X 0x800 +#define UTLB_DA2_EPR_U_R 0x400 +#define UTLB_DA2_EPR_U_W 0x200 +#define UTLB_DA2_EPR_U_X 0x100 +#define UTLB_DA2_ESZ_1K 0 +#define UTLB_DA2_ESZ_4K 0x10 +#define UTLB_DA2_ESZ_8K 0x20 +#define UTLB_DA2_ESZ_64K 0x40 +#define UTLB_DA2_ESZ_256K 0x50 +#define UTLB_DA2_ESZ_1M 0x70 +#define UTLB_DA2_ESZ_4M 0x80 +#define UTLB_DA2_ESZ_64M 0xc0 +#endif + +__BEGIN_DECLS +enum mmu_cache +{ + UNCACHED, + WRITEBACK, + WRITETHRU, +}; +enum mmu_page_size + { + SH4A_PG_1K, + SH4A_PG_4K, + SH4A_PG_64K, + SH4A_PG_1M, +#ifdef SH4A_EXT_MMU + SH4A_PG_8K, + SH4A_PG_256K, + SH4A_PG_4M, + SH4A_PG_64M, +#endif + }; +enum mmu_protect + { + P_RDONLY, + P_RW, + U_RDONLY, + U_RW, + }; + +struct tlb_entry +{ + + vaddr_t vpn; + paddr_t ppn; + int asid; + enum mmu_cache cache; + enum mmu_page_size size; + enum mmu_protect protect; + bool shared; +}; + +void sh4a_mmu_information (void); + +#ifdef SH4A_EXT_ADDR32 +void sh4a_pmb_setup (void); +bool sh4a_pmb_region_write_thru (int); +void sh4a_pmb_dump (void); +void sh4a_pmb_entry_get (int, uint32_t *, uint32_t *); +void sh4a_pmb_entry_set (int, uint32_t, uint32_t); +void sh4a_pmb_entry_set_self (uint32_t, uint32_t, uint32_t, uint32_t); +bool sh4a_pmb_align_check (uint32_t, uint32_t); +#endif + +#ifdef DEBUG +void sh4a_mmu_itlb_dump (void); +void sh4a_mmu_utlb_dump (void); +void sh4a_mmu_dump (void); +#endif + +void sh4a_mmu_start (void); +void sh4a_tlb_clear_all (void); +void sh4a_tlb_wired_entry (struct tlb_entry *); +// TLB entry helper functions. +void sh4a_tlb_entry_pagesize (int, uint32_t *, uint32_t *); +void sh4a_tlb_entry_protect (int, uint32_t *, uint32_t *); +void sh4a_tlb_entry_cache (int, uint32_t *, uint32_t *); + + +// ASID +void sh4a_mmu_asid_set (uint32_t); +uint32_t sh4a_mmu_asid_get (void); +// Wired entry. +void sh4a_mmu_wired_set (int); +uint32_t sh4a_mmu_wired_get (void); + +// TLB entry couter. +void sh4a_tlb_counter_incr (void); +void sh4a_tlb_counter_set (uint32_t); +uint32_t sh4a_tlb_counter_get (void); + +// Software bits. +void sh4a_mmu_decode_swbits (uint32_t, uint32_t *, uint32_t *); +uint32_t sh4a_mmu_encode_swbits (enum mmu_page_size, enum mmu_protect, uint32_t); + +void sh4a_tlb_invalidate_addr (int, vaddr_t); +void sh4a_tlb_invalidate_asid (int); +void sh4a_tlb_invalidate_all (void); +void sh4a_tlb_update(int, vaddr_t, uint32_t); + + +int sh4a_wired_counter_alloc (vaddr_t); +void sh4a_wired_counter_dealloc (vaddr_t); +void sh4a_tlb_update_wired(int, vaddr_t, uint32_t); + + +__END_DECLS + +#define CPU_SYNC_RESOURCE() __asm volatile ("icbi @%0" :: "r"(0x89000000)) +#endif diff --exclude=CVS --exclude=obj.evbsh3 --exclude=compile --exclude='makeBuild*.log' -uNr src.orig/sys/arch/sh3/include/param.h src-sh4a.orig/sys/arch/sh3/include/param.h --- src.orig/sys/arch/sh3/include/param.h 2010-02-20 18:37:12.000000000 +0900 +++ src-sh4a.orig/sys/arch/sh3/include/param.h 2010-02-20 18:40:10.000000000 +0900 @@ -108,7 +108,12 @@ * Minimum and maximum sizes of the kernel malloc arena in PAGE_SIZE-sized * logical pages. */ +#ifdef SH4A_EXT_ADDR32 +#define NKMEMPAGES_MIN_DEFAULT ((6 * 1024 * 1024) >> PAGE_SHIFT) +#define NKMEMPAGES_MAX_DEFAULT ((16 * 1024 * 1024) >> PAGE_SHIFT) +#else #define NKMEMPAGES_MIN_DEFAULT ((6 * 1024 * 1024) >> PAGE_SHIFT) #define NKMEMPAGES_MAX_DEFAULT ((6 * 1024 * 1024) >> PAGE_SHIFT) +#endif #endif /* !_SH3_PARAM_H_ */ diff --exclude=CVS --exclude=obj.evbsh3 --exclude=compile --exclude='makeBuild*.log' -uNr src.orig/sys/arch/sh3/include/pmap.h src-sh4a.orig/sys/arch/sh3/include/pmap.h --- src.orig/sys/arch/sh3/include/pmap.h 2010-12-11 17:59:34.000000000 +0900 +++ src-sh4a.orig/sys/arch/sh3/include/pmap.h 2010-12-11 18:01:01.000000000 +0900 @@ -39,6 +39,7 @@ #ifndef _SH3_PMAP_H_ #define _SH3_PMAP_H_ #include +#include // virtual alias information. #include #define PMAP_NEED_PROCWR @@ -53,6 +54,13 @@ struct pmap_statistics pm_stats; /* pmap statistics */ }; +/* pv_entry ops. */ +struct pv_entry { + struct pmap *pv_pmap; + vaddr_t pv_va; + SLIST_ENTRY(pv_entry) pv_link; +}; + void pmap_bootstrap(void); void pmap_procwr(struct proc *, vaddr_t, size_t); #define pmap_update(pmap) ((void)0) @@ -71,14 +79,22 @@ * pmap_prefer() helps to avoid virtual cache aliases on SH4 CPUs * which have the virtually-indexed cache. */ -#ifdef SH4 +#if defined SH4 || defined SH4A //XXX should be SH_HAS_VIRTUAL_ALIAS #define PMAP_PREFER(pa, va, sz, td) pmap_prefer((pa), (va)) void pmap_prefer(vaddr_t, vaddr_t *); -#endif /* SH4 */ +#endif /* SH_HAS_VIRTUAL_ALIAS */ +//#ifndef SH4A_EXT_ADDR32 // 32bit address mode. +#if 0 +vaddr_t pmap_map_poolpage(paddr_t); +paddr_t pmap_unmap_poolpage(vaddr_t); +#define PMAP_MAP_POOLPAGE(pa) pmap_map_poolpage(pa) +#define PMAP_UNMAP_POOLPAGE(va) pmap_unmap_poolpage(va) +#else #define PMAP_MAP_POOLPAGE(pa) SH3_PHYS_TO_P1SEG((pa)) #define PMAP_UNMAP_POOLPAGE(va) SH3_P1SEG_TO_PHYS((va)) - +#endif +//#endif /* MD pmap utils. */ pt_entry_t *__pmap_pte_lookup(pmap_t, vaddr_t); pt_entry_t *__pmap_kpte_lookup(vaddr_t); diff --exclude=CVS --exclude=obj.evbsh3 --exclude=compile --exclude='makeBuild*.log' -uNr src.orig/sys/arch/sh3/include/pmap_cache_ops.h src-sh4a.orig/sys/arch/sh3/include/pmap_cache_ops.h --- src.orig/sys/arch/sh3/include/pmap_cache_ops.h 1970-01-01 09:00:00.000000000 +0900 +++ src-sh4a.orig/sys/arch/sh3/include/pmap_cache_ops.h 2010-01-06 19:11:51.000000000 +0900 @@ -0,0 +1,43 @@ + +/*- + * Copyright (c) 2009 UCHIYAMA Yasushi. 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. + */ + +#ifndef _SH3_PMAP_CACHE_OPS_H_ +#define _SH3_PMAP_CACHE_OPS_H_ +__BEGIN_DECLS + +typedef void (cache_func_t)(vaddr_t, vsize_t); +void __pmap_cache_ops_init(void); +void __pmap_icache_inv_va(struct pmap*, vaddr_t); + +void __pmap_dcache_inv_pg(struct vm_page *); +void __pmap_dcache_wb_pg(struct vm_page *); +void __pmap_dcache_wbinv_pg(struct vm_page *); +void __pmap_dcache_inv_va(struct pmap*, vaddr_t); +void __pmap_dcache_wb_va(struct pmap*, vaddr_t); +void __pmap_dcache_wbinv_va(struct pmap*, vaddr_t); + +void __pmap_pg_dump(struct vm_page *); +__END_DECLS +#endif diff --exclude=CVS --exclude=obj.evbsh3 --exclude=compile --exclude='makeBuild*.log' -uNr src.orig/sys/arch/sh3/include/pte.h src-sh4a.orig/sys/arch/sh3/include/pte.h --- src.orig/sys/arch/sh3/include/pte.h 2008-04-29 11:39:26.000000000 +0900 +++ src-sh4a.orig/sys/arch/sh3/include/pte.h 2010-01-06 19:11:51.000000000 +0900 @@ -43,16 +43,44 @@ * SH4 * V SZ PR SZ C D SH WT * [28:10][8][7][6:5][4][3][2][1][0] + * SH4 PCMCIA + * V SZ PR SZ C D SH WT + * [28:10] [8][7][6:5][4][3][2][1][0] + * [11:9] * * [Software bit] * [31] - PMAP_WIRED bit (not hardware wired entry) * [11:9] - SH4 PCMCIA Assistant bit. (space attribute bit only) + * + *---------------------------------------------------------------------- + * SH4A 32bit physical address mode. tlb compatible mode. + * PPN UB V SZ PR SZ C D SH WT + * [31:10][9][8][7][6:5][4][3][2][1][0] + * + * SH4A 32bit physical address mode. tlb extended mode. + * PPN UB V C D SH WT + * [31:10][9][8] [3][2][1][0] + * page size and protection set to PTEA + * + * 32bit physical address mode : SH4A_EXT_ADDR32 + * TLB extended mode : SH4A_EXT_MMU + * + * [Software bit] + * [10] - PMAP_WIRED bit (not hardware wired entry) + * XXX SH4A_EXT_MMU is not implemented now. XXX + * */ /* * Hardware bits */ +#ifdef SH4A_EXT_ADDR32 +#define PG_PPN 0xfffff000 /* Physical page number mask */ +#define PG_UB 0x00000200 /* Unbuffered write */ +#else #define PG_PPN 0x1ffff000 /* Physical page number mask */ +#endif + #define PG_V 0x00000100 /* Valid */ #define PG_PR_MASK 0x00000060 /* Page protection mask */ #define PG_PR_URW 0x00000060 /* kernel/user read/write */ @@ -65,12 +93,28 @@ #define PG_SH 0x00000002 /* Share status */ #define PG_WT 0x00000001 /* Write-through (SH4 only) */ +#ifdef SH4A_EXT_ADDR32 /* 32bit physical address mode */ +#ifdef SH4A_EXT_MMU +#define PG_HW_BITS 0xfffff30e /* [31:12][9:8][3:1] */ +#else +#define PG_HW_BITS 0xfffff37e /* [31:12][9:8][6:1] */ +#endif +#else /* 29bit physical address mode */ +#ifdef SH4A_EXT_MMU +#define PG_HW_BITS 0x1ffff30e /* [28:12][9:8][3:1] */ +#else #define PG_HW_BITS 0x1ffff17e /* [28:12][8][6:1] */ +#endif +#endif /* * Software bits */ +#ifdef SH4A_EXT_ADDR32 +#define _PG_WIRED 0x00000800 +#else #define _PG_WIRED 0x80000000 +#endif /* SH4 PCMCIA MMU support bits */ /* PTEA SA (Space Attribute bit) */ diff --exclude=CVS --exclude=obj.evbsh3 --exclude=compile --exclude='makeBuild*.log' -uNr src.orig/sys/arch/sh3/include/scifreg.h src-sh4a.orig/sys/arch/sh3/include/scifreg.h --- src.orig/sys/arch/sh3/include/scifreg.h 2006-02-18 09:41:32.000000000 +0900 +++ src-sh4a.orig/sys/arch/sh3/include/scifreg.h 2010-01-06 19:11:51.000000000 +0900 @@ -36,12 +36,15 @@ #define SH3_SCIF0_BASE 0xa4000150 #define SH3_SCIF1_BASE 0xa4000140 +#ifdef SH7785 +#define SH4_SCIF_BASE 0xffeb0000 //XXX-uch SH7785 SCIF1 +#else #define SH4_SCIF_BASE 0xffe80000 +#endif #ifdef SH3 /* SH3 definitions */ - #define SCIF_SMR 0x0 /* serial mode */ #define SCIF_BRR 0x2 /* bit rate */ #define SCIF_SCR 0x4 /* serial control */ @@ -71,11 +74,16 @@ #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 */ +#ifdef SH7785 +#define SCIF_FDR 0x20 /* fifo data count set RX*/ +#define SCIF_SPTR 0x24 /* seial port */ +#define SCIF_LSR 0x28 /* line status */ +#else +#define SCIF_FDR 0x1c /* fifo data count set */ #define SCIF_SPTR 0x20 /* seial port */ #define SCIF_LSR 0x24 /* line status */ - +#endif #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)) diff --exclude=CVS --exclude=obj.evbsh3 --exclude=compile --exclude='makeBuild*.log' -uNr src.orig/sys/arch/sh3/sh3/cache.c src-sh4a.orig/sys/arch/sh3/sh3/cache.c --- src.orig/sys/arch/sh3/sh3/cache.c 2009-03-21 18:58:59.000000000 +0900 +++ src-sh4a.orig/sys/arch/sh3/sh3/cache.c 2010-01-06 19:11:51.000000000 +0900 @@ -39,8 +39,15 @@ #include #include +#ifdef SH3 #include +#endif +#ifdef SH4 #include +#endif +#ifdef SH4A +#include +#endif /* * __cache_flush is used before sh_cache_config() is called. @@ -89,6 +96,10 @@ if (CPU_IS_SH4) sh4_cache_config(); #endif +#ifdef SH4A + if (CPU_IS_SH4A) + sh4a_cache_config(); +#endif } void diff --exclude=CVS --exclude=obj.evbsh3 --exclude=compile --exclude='makeBuild*.log' -uNr src.orig/sys/arch/sh3/sh3/cache_sh4a.c src-sh4a.orig/sys/arch/sh3/sh3/cache_sh4a.c --- src.orig/sys/arch/sh3/sh3/cache_sh4a.c 1970-01-01 09:00:00.000000000 +0900 +++ src-sh4a.orig/sys/arch/sh3/sh3/cache_sh4a.c 2010-01-06 19:11:51.000000000 +0900 @@ -0,0 +1,370 @@ + +/*- + * Copyright (c) 2009 UCHIYAMA Yasushi. 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 +__KERNEL_RCSID(0, "$NetBSD$"); + +#include "opt_cache.h" + +#include +#include + +#include +#include +#ifdef SH4A_EXT_ADDR32 +#include //PMB +#endif +#include + +#ifndef CPU_SYNC_RESOURCE //XXX +#define CPU_SYNC_RESOURCE() __asm volatile ("icbi @%0" :: "r"(0x89000000)) +#endif + +void +sh4a_cache_config () +{ + sh4a_cache_disable (); + sh4a_cache_enable (TRUE); // write-back +// sh4a_cache_enable (FALSE); // write-thru + uint32_t r = *SH4A_CCR; + + sh_cache_unified = FALSE; + sh_cache_enable_icache = r & CCR_ICE; + sh_cache_enable_dcache = r & CCR_OCE; + sh_cache_ways = SH4A_CACHE_WAY; + sh_cache_line_size = SH4A_CACHE_LINESZ; + sh_cache_alias_mask = + (SH4A_DCACHE_SIZE / SH4A_CACHE_WAY - 1) & ~PAGE_MASK; + sh_cache_prefer_mask = SH4A_DCACHE_SIZE / SH4A_CACHE_WAY - 1; + sh_cache_write_through_p0_u0_p3 = r & CCR_WT; +#ifdef SH4A_EXT_ADDR32 + sh_cache_write_through_p1 = sh4a_pmb_region_write_thru (0); +#else + sh_cache_write_through_p1 = !(r & CCR_CB); +#endif + sh_cache_write_through = FALSE;//XXX + sh_cache_ram_mode = FALSE; + sh_cache_index_mode_icache = FALSE; + sh_cache_index_mode_dcache = FALSE; + + sh_cache_size_dcache = SH4A_DCACHE_SIZE; + sh_cache_size_icache = SH4A_ICACHE_SIZE; + + sh_cache_ops._icache_sync_all = sh4a_icache_sync_all; + sh_cache_ops._icache_sync_range = sh4a_icache_sync_range; + sh_cache_ops._icache_sync_range_index = sh4a_icache_sync_range_index; + + sh_cache_ops._dcache_wbinv_all = sh4a_dcache_wbinv_all; + sh_cache_ops._dcache_wbinv_range = sh4a_dcache_wbinv_range; + sh_cache_ops._dcache_wbinv_range_index = sh4a_dcache_wbinv_range_index; + sh_cache_ops._dcache_inv_range = sh4a_dcache_inv_range; + sh_cache_ops._dcache_wb_range = sh4a_dcache_wb_range; +} + +void _cpu_run_P2(void); +void _cpu_run_P1(void); + +void +sh4a_cache_enable (bool write_back) +{ + // CCR modifications must only be made by program in the P2(uncached) area. + _cpu_run_P2(); + + // Reset cache. invalidate all. CACHED DATA IS NOT WRITE-BACKED. + *SH4A_CCR |= (CCR_ICI | CCR_OCI); + + // I/D-cache 4way, use I-cache way-prediction. + *SH4A_RAMCR = 0; + + // Enable I/D cache + *SH4A_CCR = CCR_ICE | CCR_OCE; +#ifndef SH4A_EXT_ADDR32 // SH4A_EXT_ADDR32 uses PMB entry WT,C bit. + // P0,U0,P3 write-back, P1 write-back. + if (write_back) + *SH4A_CCR |= CCR_CB; + else + *SH4A_CCR |= CCR_WT; +#endif + // After CCR has been updated, execute the ICBI instruction for any address. + CPU_SYNC_RESOURCE (); + // Return to P1(cacheable) again. + _cpu_run_P1(); +} + +void +sh4a_cache_disable () +{ + // CCR modifications must only be made by program in the P2(uncached) area. + _cpu_run_P2(); + + // Before invalidate, write-back all. + sh4a_dcache_wbinv_all (); + + // Reset cache. invalidate all. + *SH4A_CCR |= (CCR_ICI | CCR_OCI); + + // Disable I/D cache + *SH4A_CCR &= ~(CCR_ICE | CCR_OCE); + + // After CCR has been updated, execute the ICBI instruction for any address. + CPU_SYNC_RESOURCE (); + // Return to P1(cacheable) again. + _cpu_run_P1(); +} + +void +sh4a_icache_sync_all () +{ +// printf("%s\n", __FUNCTION__); + + // Memory-mapped cache array must be accessed in the P2 area program. + _cpu_run_P2(); + int entry; + uint32_t addr; + + // D-cache writeback invalidate. + sh4a_dcache_wbinv_all (); // Index ops. + + // I-cache invalidate + for (entry = 0; entry < SH4A_CACHE_ENTRY; entry++) + { + addr = SH4A_CCIA | (entry << CCDA_ENTRY_SHIFT); + // non-associate. clear valid bit. + *(volatile uint32_t *)(addr | 0) &= ~CCIA_V; + *(volatile uint32_t *)(addr | (1 << CCIA_WAY_SHIFT)) &= ~CCIA_V; + *(volatile uint32_t *)(addr | (2 << CCIA_WAY_SHIFT)) &= ~CCIA_V; + *(volatile uint32_t *)(addr | (3 << CCIA_WAY_SHIFT)) &= ~CCIA_V; + } + CPU_SYNC_RESOURCE (); + _cpu_run_P1(); +} + +void +sh4a_icache_sync_range (vaddr_t va, vsize_t sz) +{ +// printf("%s\n", __FUNCTION__); + + // round/truncate with cache line. + vsize_t eva = ROUND_CACHELINE_32 (va + sz); + va = TRUNC_CACHELINE_32 (va); + + sh4a_dcache_wbinv_range (va, sz); + + while (va < eva) + { + // Hit invalidate. this may occur TLB miss. + __asm volatile ("icbi @%0" :: "r"(va)); + va += SH4A_CACHE_LINESZ; // next cache line. + } +} + +void +sh4a_icache_sync_range_index (vaddr_t va, vsize_t sz) +{ +// printf("%s\n", __FUNCTION__); + + _cpu_run_P2(); + vsize_t eva = ROUND_CACHELINE_32 (va + sz); + va = TRUNC_CACHELINE_32 (va); + + if (sz > SH4A_ICACHE_SIZE) + { + sh4a_icache_sync_all (); + return; + } + + sh4a_dcache_wbinv_range_index (va, sz); + + while (va < eva) + { + uint32_t addr = SH4A_CCIA | (va & (CCIA_ENTRY_MASK << CCIA_ENTRY_SHIFT)); + *(volatile uint32_t *)(addr | 0) &= ~CCIA_V; + *(volatile uint32_t *)(addr | (1 << CCIA_WAY_SHIFT)) &= ~CCIA_V; + *(volatile uint32_t *)(addr | (2 << CCIA_WAY_SHIFT)) &= ~CCIA_V; + *(volatile uint32_t *)(addr | (3 << CCIA_WAY_SHIFT)) &= ~CCIA_V; + va += SH4A_CACHE_LINESZ; + } + CPU_SYNC_RESOURCE (); + _cpu_run_P1(); +} + +void +sh4a_dcache_wbinv_all () +{ +// printf("%s\n", __FUNCTION__); + + _cpu_run_P2(); + int entry; + uint32_t addr; + + // D-cache writeback invalidate. + for (entry = 0; entry < SH4A_CACHE_ENTRY; entry++) + { + // non-associate. clear valid, dirty bit. + addr = SH4A_CCDA | (entry << CCDA_ENTRY_SHIFT); + // flush all way. + *(volatile uint32_t *)(addr | 0) &= ~(CCDA_U | CCDA_V); + *(volatile uint32_t *)(addr | (1 << CCDA_WAY_SHIFT)) &= ~(CCDA_U | CCDA_V); + *(volatile uint32_t *)(addr | (2 << CCDA_WAY_SHIFT)) &= ~(CCDA_U | CCDA_V); + *(volatile uint32_t *)(addr | (3 << CCDA_WAY_SHIFT)) &= ~(CCDA_U | CCDA_V); + } + CPU_SYNC_RESOURCE (); + _cpu_run_P1(); +} + +void +sh4a_dcache_wbinv_range (vaddr_t va, vsize_t sz) +{ +// printf("%s\n", __FUNCTION__); + + if (sz > SH4A_DCACHE_SIZE) + { + sh4a_dcache_wbinv_all (); // Index ops. + return; + } + + vsize_t eva = ROUND_CACHELINE_32 (va + sz); + va = TRUNC_CACHELINE_32 (va); + + while (va < eva) + { + // Hit write-back-invalidate. this may occur TLB miss. + __asm volatile ("ocbp @%0" :: "r"(va)); + va += SH4A_CACHE_LINESZ; // next cache line. + } + __asm volatile ("synco"); +} + +void +sh4a_dcache_inv_range (vaddr_t va, vsize_t sz) +{ + vsize_t eva = ROUND_CACHELINE_32 (va + sz); + va = TRUNC_CACHELINE_32 (va); + + while (va < eva) + { + // Hit invalidate. this may occur TLB miss. +#if 0 + __asm volatile ("ocbi @%0" :: "r"(va)); //XXX SH4A bug +#else + __asm volatile ("ocbp @%0" :: "r"(va)); +#endif + va += SH4A_CACHE_LINESZ; // next cache line. + } + __asm volatile ("synco"); +} + +void +sh4a_dcache_wb_range (vaddr_t va, vsize_t sz) +{ +// printf("%s\n", __FUNCTION__); + + vsize_t eva = ROUND_CACHELINE_32 (va + sz); + va = TRUNC_CACHELINE_32 (va); + + while (va < eva) + { + // Hit write-back. this may occur TLB miss. + __asm volatile ("ocbwb @%0" :: "r"(va)); + va += SH4A_CACHE_LINESZ; // next cache line. + } + __asm volatile ("synco"); +} + +void +sh4a_dcache_wbinv_range_index (vaddr_t va, vsize_t sz) +{ +// printf("%s\n", __FUNCTION__); + + _cpu_run_P2(); + vsize_t eva = ROUND_CACHELINE_32 (va + sz); + va = TRUNC_CACHELINE_32 (va); + + if (sz > SH4A_DCACHE_SIZE) + { + sh4a_dcache_wbinv_all (); // Index ops. + return; + } + + while (va < eva) + { + uint32_t addr = SH4A_CCDA | (va & (CCIA_ENTRY_MASK << CCIA_ENTRY_SHIFT)); + *(volatile uint32_t *)(addr | 0) &= ~(CCDA_U | CCDA_V); + *(volatile uint32_t *)(addr | (1 << CCIA_WAY_SHIFT)) &= ~(CCDA_U | CCDA_V); + *(volatile uint32_t *)(addr | (2 << CCIA_WAY_SHIFT)) &= ~(CCDA_U | CCDA_V); + *(volatile uint32_t *)(addr | (3 << CCIA_WAY_SHIFT)) &= ~(CCDA_U | CCDA_V); + va += SH4A_CACHE_LINESZ; + } + CPU_SYNC_RESOURCE (); + _cpu_run_P1(); +} + +#include "opt_ddb.h" +#include +#ifdef DDB +#define printf db_printf +void +sh4a_dcache_array_dump (vaddr_t va, vsize_t sz) +{ + _cpu_run_P2(); + vsize_t eva = ROUND_CACHELINE_32 (va + sz); + va = TRUNC_CACHELINE_32 (va); + + size_t j, k; + + while (va < eva) + { + uint32_t entry = va & (CCDD_ENTRY_MASK << CCDD_ENTRY_SHIFT); + uint32_t d0 = SH4A_CCDD | entry; + uint32_t a0 = SH4A_CCDA | entry; + printf ("[Entry %lx](%x)----------------------------------------------\n", + (va >> CCDD_ENTRY_SHIFT) & CCDD_ENTRY_MASK, entry); + for (k = 0; k < SH4A_CACHE_WAY; k++) + { + uint32_t way = k << CCDD_WAY_SHIFT; + uint32_t d1 = d0 | way; + uint32_t bit = *(volatile uint32_t *)(a0 | way); + printf ("way %d tag=%x (%c|%c)\n", k, + bit & (CCDA_TAG_MASK << CCDA_TAG_SHIFT), + bit & CCDA_U ? 'D' : '-', + bit & CCDA_V ? 'V' : '-'); + + // Dump cache line. + for (j = 0; j < SH4A_CACHE_LINESZ / sizeof (int32_t); j++) + { + uint32_t line = j << CCDD_LINE_SHIFT; + printf ("%x ", *(volatile uint32_t *)(d1 | line)); + } + printf ("\n"); + } + va += SH4A_CACHE_LINESZ; + } + + CPU_SYNC_RESOURCE (); + _cpu_run_P1(); +} + + +#endif diff --exclude=CVS --exclude=obj.evbsh3 --exclude=compile --exclude='makeBuild*.log' -uNr src.orig/sys/arch/sh3/sh3/cpu.c src-sh4a.orig/sys/arch/sh3/sh3/cpu.c --- src.orig/sys/arch/sh3/sh3/cpu.c 2009-04-05 11:38:41.000000000 +0900 +++ src-sh4a.orig/sys/arch/sh3/sh3/cpu.c 2010-01-06 19:11:51.000000000 +0900 @@ -68,11 +68,10 @@ #define MHZ(x) ((x) / 1000000), (((x) % 1000000) / 1000) aprint_naive("\n"); - aprint_normal(": 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())); - + aprint_normal(": SH%d%c %d.%02d MHz PCLOCK %d.%02d MHz\n", + CPU_IS_SH3 ? 3 : 4, CPU_IS_SH4A ? 'A' : ' ', + MHZ(sh_clock_get_cpuclock()), + MHZ(sh_clock_get_pclock())); #undef MHZ sh_cache_information(); diff --exclude=CVS --exclude=obj.evbsh3 --exclude=compile --exclude='makeBuild*.log' -uNr src.orig/sys/arch/sh3/sh3/db_interface.c src-sh4a.orig/sys/arch/sh3/sh3/db_interface.c --- src.orig/sys/arch/sh3/sh3/db_interface.c 2011-02-05 00:09:49.000000000 +0900 +++ src-sh4a.orig/sys/arch/sh3/sh3/db_interface.c 2011-02-05 00:11:24.000000000 +0900 @@ -52,11 +52,17 @@ #ifndef KGDB #include -#include -#include #include +#if defined SH3 || defined SH4 +#include #include +#include #include +#endif +#ifdef SH4A +#include +#include +#endif #include #include @@ -64,10 +70,11 @@ #include static void kdb_printtrap(u_int, int); - static void db_tlbdump_cmd(db_expr_t, bool, db_expr_t, const char *); +#if defined SH3 || defined SH4 static char *__db_procname_by_asid(int); static void __db_tlbdump_pfn(uint32_t); +#endif #ifdef SH4 static void __db_tlbdump_page_size_sh4(uint32_t); #endif @@ -79,6 +86,9 @@ #ifdef SH4 static void __db_cachedump_sh4(vaddr_t); #endif +#ifdef SH4A +static void __db_cachedump_sh4a(vaddr_t); +#endif static void db_frame_cmd(db_expr_t, bool, db_expr_t, const char *); static void __db_print_symbol(db_expr_t); @@ -262,6 +272,7 @@ db_tlbdump_cmd(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif) { +#if defined SH3 || defined SH4 static const char *pr[] = { "_r", "_w", "rr", "ww" }; static const char title[] = " VPN ASID PFN AREA VDCGWtPR SZ"; @@ -269,6 +280,7 @@ " U/K U/K"; uint32_t r, e; int i; +#endif #ifdef SH3 if (CPU_IS_SH3) { /* MMU configuration. */ @@ -395,8 +407,12 @@ } } #endif /* SH4 */ +#ifdef SH4A + sh4a_mmu_dump(); +#endif } +#if defined SH3 || defined SH4 static void __db_tlbdump_pfn(uint32_t r) { @@ -418,6 +434,7 @@ return (notfound); } +#endif // SH3 || SH4 #ifdef SH4 static void @@ -455,6 +472,10 @@ if (CPU_IS_SH4) __db_cachedump_sh4(have_addr ? addr : 0); #endif +#ifdef SH4A + if (CPU_IS_SH4A) + __db_cachedump_sh4a(have_addr ? addr : 0); +#endif } #ifdef SH3 @@ -553,6 +574,17 @@ } #endif /* SH4 */ +#ifdef SH4A +static void +__db_cachedump_sh4a(vaddr_t va) +{ + if (va) + sh4a_dcache_array_dump (va, 4); + else + sh4a_dcache_array_dump (0, SH4A_DCACHE_SIZE); +} +#endif // SH4A + #undef ON static void diff --exclude=CVS --exclude=obj.evbsh3 --exclude=compile --exclude='makeBuild*.log' -uNr src.orig/sys/arch/sh3/sh3/exception.c src-sh4a.orig/sys/arch/sh3/sh3/exception.c --- src.orig/sys/arch/sh3/sh3/exception.c 2011-02-05 00:09:49.000000000 +0900 +++ src-sh4a.orig/sys/arch/sh3/sh3/exception.c 2011-02-05 00:11:24.000000000 +0900 @@ -272,9 +272,15 @@ * tf ... full user context. * va ... fault address. */ +int __tlb_exception_cnt; +int __tlb_exception_debug; void tlb_exception(struct lwp *l, struct trapframe *tf, uint32_t va) { + if (__tlb_exception_debug) + printf ("%s from %s va=%x EXPEVT=%x\n", __FUNCTION__, + KERNELMODE(tf->tf_ssr) ? "kernel" : "user", va, tf->tf_expevt); + __tlb_exception_cnt++; struct vm_map *map; struct pcb *pcb; pmap_t pmap; @@ -358,8 +364,10 @@ map = kernel_map; pmap = pmap_kernel(); } else { +#if 0// allow user-space access from kernel mode -uch TLB_ASSERT(l != NULL && onfault != NULL, "invalid user-space access from kernel mode"); +#endif if (va == 0) { tf->tf_spc = (int)onfault; tf->tf_r0 = EFAULT; @@ -367,6 +375,9 @@ } map = &l->l_proc->p_vmspace->vm_map; pmap = map->pmap; +#if 1 + printf("%s: ASID%d\n", __FUNCTION__,pmap->pm_asid); +#endif } } @@ -422,9 +433,21 @@ else { ksi.ksi_signo = SIGSEGV; ksi.ksi_code = SEGV_MAPERR; + void sh4a_mmu_dump (void); + sh4a_mmu_dump (); + panic(__FUNCTION__); } goto user_fault; } else { +#if 1 + void sh4a_mmu_dump (void); + uint32_t r; + __asm volatile ("stc spc, %0" : "=r"(r)); + printf ("%x\n", tf->tf_r8); + printf("!!!!%s %x %x!!!!\n", __FUNCTION__, va, r); + sh4a_mmu_dump (); +#endif + TLB_ASSERT(onfault, "no copyin/out fault handler (page not found)"); tf->tf_spc = (int)onfault; diff --exclude=CVS --exclude=obj.evbsh3 --exclude=compile --exclude='makeBuild*.log' -uNr src.orig/sys/arch/sh3/sh3/exception_vector.S src-sh4a.orig/sys/arch/sh3/sh3/exception_vector.S --- src.orig/sys/arch/sh3/sh3/exception_vector.S 2011-02-05 00:09:49.000000000 +0900 +++ src-sh4a.orig/sys/arch/sh3/sh3/exception_vector.S 2011-02-05 00:11:24.000000000 +0900 @@ -297,7 +297,7 @@ #endif /* SH3 */ -#ifdef SH4 +#if defined SH4 || defined SH4A /* SH4A TLB-compatible mode */ /* * LINTSTUB: Var: char sh4_vector_tlbmiss[1]; * @@ -314,6 +314,7 @@ * and maximum 512 bytes long (== 0x600 - 0x400). */ NENTRY(sh4_vector_tlbmiss) +#if 0 mov.l .L4_SH4_PTEH, r4 mov.l .L4_VPN_cleanup, r0 mov.l @r4, r5 @@ -382,13 +383,20 @@ mov.l .L4_PG_HW_BITS, r1 shlr8 r0 and r1, r3 ! pte &= PG_HW_BITS +#ifndef SH4A shlr r0 ! pte >> _PG_PCMCIA_SHIFT +#endif cmp/pz r5 ! user space address? +#ifndef SH4A and #SH4_PTEA_SA_MASK, r0 +#endif mov.l r3, @(0x04, r4) ! *SH4_PTEL = pte bf/s .L4_load_kernel +#ifdef SH4A + nop +#else mov.l r0, @(0x34, r4) ! *SH4_PTEA = PCMCIA space attrs - +#endif !! load mapping for a user space page !! we reload PTEH to enter VPN aligned to 4K page boundary .L4_load_user: @@ -413,6 +421,7 @@ !! if we haven't found a valid mapping in the fast path !! tlb_exception(curlwp, trapframe, tea) .L4_call_tlb_exception: +#endif /*0*/ __EXCEPTION_ENTRY mov.l .L4_SH4_PTEH, r0 mov.l .L4_curlwp, r1 diff --exclude=CVS --exclude=obj.evbsh3 --exclude=compile --exclude='makeBuild*.log' -uNr src.orig/sys/arch/sh3/sh3/locore_c.c src-sh4a.orig/sys/arch/sh3/sh3/locore_c.c --- src.orig/sys/arch/sh3/sh3/locore_c.c 2009-11-28 21:50:08.000000000 +0900 +++ src-sh4a.orig/sys/arch/sh3/sh3/locore_c.c 2010-01-06 19:11:51.000000000 +0900 @@ -171,7 +171,7 @@ #endif /* SH3 */ -#ifdef SH4 +#if defined SH4 || defined SH4A /* * Prepare kernel stack PTE table. sh4_switch_resume wires these PTEs. */ @@ -206,7 +206,7 @@ ++e; } } -#endif /* SH4 */ +#endif /* SH4 || SH4A */ #endif /* !P1_STACK */ diff --exclude=CVS --exclude=obj.evbsh3 --exclude=compile --exclude='makeBuild*.log' -uNr src.orig/sys/arch/sh3/sh3/locore_subr.S src-sh4a.orig/sys/arch/sh3/sh3/locore_subr.S --- src.orig/sys/arch/sh3/sh3/locore_subr.S 2011-02-05 00:09:49.000000000 +0900 +++ src-sh4a.orig/sys/arch/sh3/sh3/locore_subr.S 2011-02-05 00:11:24.000000000 +0900 @@ -129,7 +129,7 @@ ldc r2, r6_bank mov r3, r15 -#if !defined(P1_STACK) && defined(SH4) +#if !defined(P1_STACK) && (defined(SH4) || defined SH4A) !! wire u-area in TLB MOV (switch_resume, r0) jsr @r0 @@ -158,7 +158,7 @@ .L_curlwp: .long _C_LABEL(curlwp) .L_curpcb: .long _C_LABEL(curpcb) .L_cpu_switch_prepare: .long _C_LABEL(cpu_switch_prepare) -#ifdef SH4 +#if defined SH4 || defined SH4A FUNC_SYMBOL(switch_resume) #endif SET_ENTRY_SIZE(cpu_switchto) @@ -176,7 +176,7 @@ #endif /* SH3 */ -#ifdef SH4 +#if defined SH4 || defined SH4A /* * LINTSTUB: Func: void sh4_switch_resume(struct lwp *l) * Wire u-area. invalidate TLB entry for kernel stack to prevent @@ -197,7 +197,7 @@ mov.l .L_VPN_MASK, r6 mov.l .L_4_UTLB_AA_A, r5 - +/*-uch SH4A don't have this constraint.*/ /* TLB address array must be accessed via P2. Setup jump address. */ mova 1f, r0 mov.l .L_P2BASE, r1 @@ -236,7 +236,7 @@ .L_VPN_MASK: .long 0xfffff000 .L_P2BASE: .long 0xa0000000 SET_ENTRY_SIZE(sh4_switch_resume) -#endif /* SH4 */ +#endif /* SH4 || SH4A */ /* diff --exclude=CVS --exclude=obj.evbsh3 --exclude=compile --exclude='makeBuild*.log' -uNr src.orig/sys/arch/sh3/sh3/mmu.c src-sh4a.orig/sys/arch/sh3/sh3/mmu.c --- src.orig/sys/arch/sh3/sh3/mmu.c 2008-04-29 11:39:28.000000000 +0900 +++ src-sh4a.orig/sys/arch/sh3/sh3/mmu.c 2010-01-06 19:11:51.000000000 +0900 @@ -38,6 +38,7 @@ #include #include #include +#include #if defined(SH3) && defined(SH4) void (*__sh_mmu_start)(void); @@ -87,8 +88,8 @@ r & SH3_MMUCR_SV ? "single" : "multiple"); } #endif -#ifdef SH4 - if (CPU_IS_SH4) { +#if defined SH4 || defined SH4A + if (CPU_IS_SH4 || CPU_IS_SH4A) { unsigned int urb; aprint_normal("cpu0: full-associative" " 4 ITLB, 64 UTLB entries\n"); @@ -102,6 +103,9 @@ urb ? 64 - urb : 0); } #endif +#ifdef SH4A + sh4a_mmu_information(); +#endif } void @@ -110,3 +114,10 @@ _reg_write_4(SH_(PTEH), asid); } + +int +sh_tlb_get_asid() +{ + + return _reg_read_4(SH_(PTEH)) & 0xff; +} diff --exclude=CVS --exclude=obj.evbsh3 --exclude=compile --exclude='makeBuild*.log' -uNr src.orig/sys/arch/sh3/sh3/mmu_sh4a.c src-sh4a.orig/sys/arch/sh3/sh3/mmu_sh4a.c --- src.orig/sys/arch/sh3/sh3/mmu_sh4a.c 1970-01-01 09:00:00.000000000 +0900 +++ src-sh4a.orig/sys/arch/sh3/sh3/mmu_sh4a.c 2010-01-06 19:11:51.000000000 +0900 @@ -0,0 +1,701 @@ + +/*- + * Copyright (c) 2009 UCHIYAMA Yasushi. 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. + */ + +// Memory Management Unit + +#include +__KERNEL_RCSID(0, "$NetBSD$"); + +#include +#include + +#include /* NetBSD/sh3 specific PTE */ +#include +#include +#include +#include // PAGE_SIZE + +#define STATIC static +#ifdef DEBUG +STATIC void tlb_entry_print (uint32_t, uint32_t, uint32_t, int); +#endif +void sh4a_mmu_utlb_check (void); +paddr_t sh4a_mmu_utlb_lookup_by_va (vaddr_t); + + +static int mmu_paddr; +static int mmu_mode; +#define SPECIAL_WIRED 4 + +void +sh4a_mmu_start () +{ + uint32_t r; + + sh4a_mmu_dump (); + sh4a_tlb_clear_all (); + sh4a_mmu_dump (); +#ifdef SH4A_EXT_ADDR32 + *PASCR = PASCR_SE; + mmu_paddr = 32; +#else + // CPU doesn't wait for the end of writing bus access and starts + // next bus access + *PASCR = 0; + mmu_paddr = 29; +#endif + + // Don't re-fetch all. +// *IRMCR = IRMCR_R2 | IRMCR_R1 | IRMCR_LT | IRMCR_MT | IRMCR_MC; + // re-fetch. (slow) + *IRMCR = 0; + + // Set ASID + *SH4A_PTEH = 0; + + // Invalidate all entries. and start Address translation. + r = MMUCR_TI | MMUCR_AT; +#ifdef SH4A_EXT_MMU + r |= MMUCR_ME; + mmu_mode = 1; +#endif + r |= MMUCR_SQMD; // Store queue + + *SH4A_MMUCR = r; + +#ifdef NetBSD + sh4a_mmu_wired_set (UPAGES + SPECIAL_WIRED); +#endif + + CPU_SYNC_RESOURCE (); +} + +void +sh4a_mmu_information () +{ + printf ("cpu0: %dbit physical address mode. ", mmu_paddr); + printf ("TLB-%s mode.\n", mmu_mode ? "extended" : "compatible"); +#ifdef SH4A_EXT_ADDR32 + sh4a_pmb_dump (); +#endif +} + + +void +sh4a_mmu_asid_set (uint32_t acid) +{ + + *SH4A_PTEH = acid & PTEH_ASID; +} + +uint32_t +sh4a_mmu_asid_get () +{ + + return *SH4A_PTEH & PTEH_ASID; +} + +void +sh4a_tlb_counter_set (uint32_t n) +{ + + *SH4A_MMUCR &= ~(MMUCR_URC_MASK << MMUCR_URC_SHIFT); + *SH4A_MMUCR |= (n << MMUCR_URC_SHIFT); +} + +uint32_t +sh4a_tlb_counter_get () +{ + + return (*SH4A_MMUCR >> MMUCR_URC_SHIFT) & MMUCR_URC_MASK; +} + +void +sh4a_mmu_wired_set (int n) +{ + uint32_t limit = (SH4A_UTLB_ENTRY - n) & MMUCR_URB_MASK; + + // If current counter is wired area, reset. + if (sh4a_tlb_counter_get () >= limit) + sh4a_tlb_counter_set (0); + // Set coutner limit. + *SH4A_MMUCR &= ~(MMUCR_URB_MASK << MMUCR_URB_SHIFT); + *SH4A_MMUCR |= (limit << MMUCR_URB_SHIFT); + + printf ("wired entry: %d-%d\n", limit, SH4A_UTLB_ENTRY - 1); +} + +uint32_t +sh4a_mmu_wired_get () +{ + // return # of wired entry. if URC == URB, URC is setted 0. + uint32_t urb = (*SH4A_MMUCR >> MMUCR_URB_SHIFT) & MMUCR_URB_MASK; + + return urb == 0 ? 0 : SH4A_UTLB_ENTRY - urb; // urb == 0: no wired entry. +} + +void +sh4a_tlb_clear_all () +{ + uint32_t entry, e; + + for (entry = 0; entry < SH4A_ITLB_ENTRY; entry++) + { + e = entry << ITLB_AA_E_SHIFT; + *(volatile uint32_t *)(SH4A_ITLB_AA | e) = 0; + *(volatile uint32_t *)(SH4A_ITLB_DA1 | e) = 0; +#ifdef SH4A_EXT_MMU + *(volatile uint32_t *)(SH4A_ITLB_DA2 | e) = 0; +#endif + } + for (entry = 0; entry < SH4A_UTLB_ENTRY; entry++) + { + e = entry << UTLB_AA_E_SHIFT; + *(volatile uint32_t *)(SH4A_UTLB_AA | e) = 0; + *(volatile uint32_t *)(SH4A_UTLB_DA1 | e) = 0; +#ifdef SH4A_EXT_MMU + *(volatile uint32_t *)(SH4A_UTLB_DA2 | e) = 0; +#endif + } +} + +void +sh4a_tlb_wired_entry (struct tlb_entry *e) +{ + uint32_t pteh, ptel, ptea; +#ifdef DEBUG + uint32_t pgsz_table[] = { 0x400, 0x1000, 0x1000, 0x100000, 0x2000, 0x40000, + 0x400000, 0x4000000 }; + uint32_t pgsz_mask = pgsz_table[e->size] -1; + assert (!(e->vpn & pgsz_mask) && !(e->ppn & pgsz_mask)); +#endif + // Set Physical addr - Virtual addr. + ptel = e->ppn & PTEL_PPN; + pteh = e->vpn & PTEH_VPN; + ptea = 0; + + // Shared page don't bother ASID. + if (e->shared) + ptel |= PTEL_SH; + else + pteh |= e->asid; + // Setup Protect, Cache, Pagesize. + sh4a_tlb_entry_pagesize (e->size, &ptel, &ptea); + sh4a_tlb_entry_protect (e->protect, &ptel, &ptea); + sh4a_tlb_entry_cache (e->cache, &ptel, &ptea); + + // Enable this entry. + ptel |= (PTEL_V | PTEL_D); + // Prepare new wired entry. + uint32_t n = sh4a_mmu_wired_get () + 1; + + // Set URC for LDTLB + sh4a_tlb_counter_set (SH4A_UTLB_ENTRY - n); + *SH4A_PTEH = pteh; + *SH4A_PTEL = ptel; +#ifdef SH4A_EXT_MMU + *SH4A_PTEA = ptea; +#endif + __asm volatile ("ldtlb"); + // Make this wired entry. + sh4a_mmu_wired_set (n); + CPU_SYNC_RESOURCE (); +#ifdef DEBUG + // Valid bit is maped to both address array and data array, but + // tlb_entry_print check address array only. XXX + tlb_entry_print (pteh | UTLB_AA_V, ptel, ptea, 0); +#endif +} + +// Invalidate TLB entry by address. +void +sh4a_tlb_invalidate_addr (int asid, vaddr_t va) +{ + int s = _cpu_intr_suspend(); + // Save current ASID + uint32_t oasid = sh4a_mmu_asid_get (); + bool save_asid = asid != oasid; + + // Set ASID for associative write + if (save_asid) + sh4a_mmu_asid_set (asid); + + // Associative write UTLB. ITLB is also invalidated. + // SH4A can access by a program in the P1/P2. no need to change P2. + *(volatile uint32_t *)(SH4A_UTLB_AA | UTLB_AA_A) = va & PTEH_VPN; + + // Restore ASID + if (save_asid) + sh4a_mmu_asid_set (oasid); + _cpu_intr_resume (s); +} + + +// Invalidate TLB entry by ASID. +void +sh4a_tlb_invalidate_asid (int asid) +{ + int s = _cpu_intr_suspend(); // don't thread switch here. + volatile uint32_t *a; + uint32_t entry; + // I assume asid is not 0. so wired entry is not matched. + assert (asid != 0); + for (entry = 0; entry < SH4A_UTLB_ENTRY; entry++) + { + a = (volatile uint32_t *)(SH4A_UTLB_AA | (entry << UTLB_AA_E_SHIFT)); + if ((*a & UTLB_AA_ASID) == (uint32_t)asid) + *a = 0; + } + + for (entry = 0; entry < SH4A_ITLB_ENTRY; entry++) + { + a = (volatile uint32_t *)(SH4A_ITLB_AA | (entry << ITLB_AA_E_SHIFT)); + if ((*a & ITLB_AA_ASID) == (uint32_t)asid) + *a = 0; // Drop valid bit. + } + + _cpu_intr_resume (s); +} + +// Invalidate TLB entry exclude wired entry. +void +sh4a_tlb_invalidate_all () +{ + int s = _cpu_intr_suspend(); + volatile uint32_t *a; + uint32_t limit, entry; + + limit = SH4A_UTLB_ENTRY - sh4a_mmu_wired_get (); + for (entry = 0; entry < limit; entry++) + { + *(volatile uint32_t *)(SH4A_UTLB_AA | (entry << UTLB_AA_E_SHIFT)) = 0; + } + + for (entry = 0; entry < SH4A_ITLB_ENTRY; entry++) + { + a = (volatile uint32_t *)(SH4A_ITLB_AA | (entry << ITLB_AA_E_SHIFT)); + *a = 0; + } + + _cpu_intr_resume (s); +} + +void +sh4a_tlb_entry_pagesize (int szidx, uint32_t *ptel __attribute__((unused)), + uint32_t *ptea __attribute__((unused))) +{ +#ifdef SH4A_EXT_MMU + uint32_t pgsz_bits[] = { PTEA_ESZ_1K, PTEA_ESZ_4K, PTEA_ESZ_64K, + PTEA_ESZ_1M, PTEA_ESZ_8K, PTEA_ESZ_256K, + PTEA_ESZ_4M, PTEA_ESZ_64M }; + *ptea |= pgsz_bits[szidx]; +#else + uint32_t pgsz_bits[] = { PTEL_SZ_1K, PTEL_SZ_4K, PTEL_SZ_64K, PTEL_SZ_1M }; + *ptel |= pgsz_bits[szidx]; +#endif +} + +void +sh4a_tlb_entry_protect (int pridx, uint32_t *ptel __attribute__((unused)), + uint32_t *ptea __attribute__((unused))) +{ +#ifdef SH4A_EXT_MMU + uint32_t pr_bits [] = { PTEA_EPR_P_R | PTEA_EPR_P_X, + PTEA_EPR_P_R | PTEA_EPR_P_W | PTEA_EPR_P_X, + PTEA_EPR_P_R | PTEA_EPR_P_W | PTEA_EPR_P_X | + PTEA_EPR_U_R | PTEA_EPR_U_X, + PTEA_EPR_P_R | PTEA_EPR_P_W | PTEA_EPR_P_X | + PTEA_EPR_U_R | PTEA_EPR_U_W | PTEA_EPR_U_X }; + *ptea |= pr_bits[pridx]; +#else + uint32_t pr_bits[] = { PTEL_PR_P_RDONLY, PTEL_PR_P_RW, PTEL_PR_U_RDONLY, + PTEL_PR_U_RW }; + + *ptel |= pr_bits[pridx]; +#endif +} + +void +sh4a_tlb_entry_cache (int cidx, uint32_t *ptel, + uint32_t *ptea __attribute__((unused))) +{ + uint32_t cache_bits[] = { 0, PTEL_C, PTEL_C | PTEL_WT }; + + *ptel |= cache_bits[cidx]; +} + + +uint32_t +sh4a_mmu_encode_swbits (enum mmu_page_size sz, // 8types. 3bit + enum mmu_protect pr, // 4types. 2bit + uint32_t opt __attribute__((unused))) +{ + uint32_t pte = 0; + + pte |= (sz & 1) << 4; + pte |= (sz & 2) << 6; +#ifdef SH4A_EXT_MMU + pte |= (sz & 4) << 6; +#endif + pte |= pr << 5; + + return pte; +} + + +struct { + int inuse; + vaddr_t va; +} wired_map[1024]; + +int +sh4a_wired_counter_alloc (vaddr_t va) +{ + + int i; + for (i = 0; i < 1024; i++) { + if (!wired_map[i].inuse) { + wired_map[i].inuse = TRUE; + wired_map[i].va = va; + printf ("%s wired %d alloc\n", __FUNCTION__, i); + return 0; +// return SH4A_UTLB_ENTRY - UPAGES - SPECIAL_WIRED + i; + } + } + + return 0; +} + +void +sh4a_wired_counter_dealloc (vaddr_t va) +{ + + int i, j; + for (i = j = 0; i < 1024; i++) { + bool wired = wired_map[i].inuse; + if (wired) { + j++; + if (wired_map[i].va == va) { + wired_map[i].inuse = FALSE; + printf ("%s wired %d dealloc\n", __FUNCTION__, i); + } + } + } + printf ("tolal %d wired page\n", j); +} + +// Load new TLB entry. +void +sh4a_tlb_update_wired(int asid, vaddr_t va, uint32_t pte) +{ +// printf ("%s %d %lx %x\n", __FUNCTION__, asid, va, pte); + + int s = _cpu_intr_suspend (); + va &= ~PGOFSET; + + // Save current ASID + uint32_t oasid = sh4a_mmu_asid_get (); + bool save_asid = asid != oasid; + + // Load new entry. + uint32_t vpn = va & PTEH_VPN; + + uint32_t pteh = (vpn | asid) & PTEH_VALID_BITS; + *SH4A_PTEH = pteh; + uint32_t ptel = pte & PG_HW_BITS; // Remove software bits + *SH4A_PTEL = ptel; + + int cnt = sh4a_tlb_counter_get (); + // Set wired entry. + sh4a_tlb_counter_set (sh4a_wired_counter_alloc(va)); + __asm volatile ("ldtlb"); + CPU_SYNC_RESOURCE (); + // Restore counter. + sh4a_tlb_counter_set (cnt); + + // Restore ASID + if (save_asid) + sh4a_mmu_asid_set (oasid); +// sh4a_mmu_dump (); + _cpu_intr_resume (s); +} + +// Load new TLB entry. +void +sh4a_tlb_update(int asid, vaddr_t va, uint32_t pte) +{ +// printf ("%s %d %lx %x\n", __FUNCTION__, asid, va, pte); + + int s = _cpu_intr_suspend (); + va &= ~PGOFSET; + + // Save current ASID + uint32_t oasid = sh4a_mmu_asid_get (); + bool save_asid = asid != oasid; + if (save_asid) + sh4a_mmu_asid_set (asid); + + // Invalidate old entry. + sh4a_tlb_invalidate_addr (asid, va); + + // Load new entry. + uint32_t vpn = va & PTEH_VPN; + + uint32_t pteh = (vpn | asid) & PTEH_VALID_BITS; + *SH4A_PTEH = pteh; +#ifdef SH4A_EXT_MMU +#error notyet + uint32_t ptel, ptea; + pte = pte; ptel = 0; ptea=0; + // sh4a_mmu_decode_swbits (pte, &ptel, &ptea); + *SH4A_PTEL = ptel; + *SH4A_PTEA = ptea; +#else +#ifdef NetBSD + uint32_t ptel = pte & PG_HW_BITS; // Remove software bits +#else + uint32_t ptel = pte & PTEL_VALID_BITS; +#endif + *SH4A_PTEL = ptel; +#endif + + int cnt = sh4a_tlb_counter_get () + 1; + if (cnt > (60 - SPECIAL_WIRED)) + cnt = 0; + sh4a_tlb_counter_set (cnt); + + __asm volatile ("ldtlb"); + CPU_SYNC_RESOURCE (); + + // Restore ASID + if (save_asid) + sh4a_mmu_asid_set (oasid); + sh4a_mmu_utlb_check (); +// sh4a_mmu_dump (); + _cpu_intr_resume (s); +} + +#include "opt_ddb.h" +#ifdef DDB +#include +#define printf db_printf +void +sh4a_mmu_dump () +{ + + printf ("MMUCR: %x ", *SH4A_MMUCR); + printf ("PTEH: %x ", *SH4A_PTEH); + printf ("PTEL: %x ", *SH4A_PTEL); + printf ("TTB: %x ", *SH4A_TTB); + printf ("TEA: %x ", *SH4A_TEA); +#ifdef SH4A_EXT_MMU + printf ("PTEA: %x", *SH4A_TEA); +#endif + printf ("\n"); + printf ("wired entry:%d\n", sh4a_mmu_wired_get ()); + + sh4a_mmu_itlb_dump (); + sh4a_mmu_utlb_dump (); +#ifdef SH4A_EXT_ADDR32 + printf ("--------------------PMB--------------------\n"); + uint32_t r = *PASCR; + printf ("paddr %dbit mode.\n", r & PASCR_SE ? 32 : 29); + sh4a_pmb_dump (); +#endif +} + +void +sh4a_mmu_itlb_dump () +{ + uint32_t entry, e, aa, da1, da2; + + printf ("--------------------ITLB--------------------\n"); + for (entry = 0; entry < SH4A_ITLB_ENTRY; entry++) + { + e = entry << ITLB_AA_E_SHIFT; + aa = *(volatile uint32_t *)(SH4A_ITLB_AA | e); + da1 = *(volatile uint32_t *)(SH4A_ITLB_DA1 | e); +#ifdef SH4A_EXT_MMU + da2 = *(volatile uint32_t *)(SH4A_ITLB_DA2 | e); +#else + da2 = 0; +#endif + tlb_entry_print (aa, da1, da2, entry); + } +} + +void +sh4a_mmu_utlb_dump () +{ + uint32_t entry, e, aa, da1, da2; + + printf ("--------------------UTLB--------------------\n"); + for (entry = 0; entry < SH4A_UTLB_ENTRY; entry++) + { + e = entry << UTLB_AA_E_SHIFT; + aa = *(volatile uint32_t *)(SH4A_UTLB_AA | e); + da1 = *(volatile uint32_t *)(SH4A_UTLB_DA1 | e); +#ifdef SH4A_EXT_MMU + da2 = *(volatile uint32_t *)(SH4A_UTLB_DA2 | e); +#else + da2 = 0; +#endif + tlb_entry_print (aa, da1, da2, entry); + } +} + + + +vaddr_t utlb_vaddr[SH4A_UTLB_ENTRY]; + +paddr_t +sh4a_mmu_utlb_lookup_by_va (vaddr_t va) +{ + uint32_t entry, e, aa, da1; + paddr_t pa = 0; + va &= UTLB_AA_VPN; + + for (entry = 0; entry < SH4A_UTLB_ENTRY; entry++) + { + e = entry << UTLB_AA_E_SHIFT; + aa = *(volatile uint32_t *)(SH4A_UTLB_AA | e); + if ((aa & UTLB_AA_VPN) == va) { + da1 = *(volatile uint32_t *)(SH4A_UTLB_DA1 | e); + pa = da1 & UTLB_DA1_PPN; + tlb_entry_print (aa, da1, 0, entry); + return pa; + } + } + printf("no mapping\n"); + + return pa; +} + + +void +sh4a_mmu_utlb_check () +{ + uint32_t entry, e, aa; + + for (entry = 0; entry < SH4A_UTLB_ENTRY; entry++) + { + e = entry << UTLB_AA_E_SHIFT; + aa = *(volatile uint32_t *)(SH4A_UTLB_AA | e); + utlb_vaddr[entry] = aa & UTLB_AA_V ? (aa & (UTLB_AA_VPN | UTLB_AA_ASID)) + : 0xffffffff; + } + + int i, j; + uint32_t a0, a1; + for (i = 0; i < SH4A_UTLB_ENTRY; i++) { + a0 = utlb_vaddr[i]; + if (a0 == 0xffffffff) + continue; + for (j = 0; j < i; j++) { + a1 = utlb_vaddr[j]; + if (a1 == 0xffffffff) + continue; + if (a0 == a1) { + printf("TLB double hit %x\n", a0); + sh4a_mmu_utlb_dump(); + while (/*CONSTCOND*/1) + ; + } + } + } + +} + +void +tlb_entry_print (uint32_t aa, uint32_t da1, uint32_t da2, int n) +{ + uint32_t vpn = aa & UTLB_AA_VPN; + bool pmb = (vpn & 0xc0000000) == 0x80000000; + int sz; + int valid = aa & UTLB_AA_V; + + if (!valid) + return; + + printf ("(%c|%c) ", aa & UTLB_AA_D ? 'D' : '-', valid ? 'V' : '-'); + const char *pmb_pgsz[] = { " 16M", " 64M", "128M", "512M" }; +#ifdef SH4A_EXT_MMU + const char *pgsz[] = { " 1K", " 4K", " 8K", "-XX-", + " 64K", "256K", "-XX-", " 1M", + " 4M", "-XX-", "-XX-", "-XX-", + " 64M", "-XX-", "-XX-", "-XX-" }; + if (pmb) + sz = ((da1 & PMB_DA_SZ0) >> 4) | ((da1 & PMB_DA_SZ1) >> 6); + else + sz = (da2 >> 4) & 0xf; + if (!pmb) + { + printf ("[%c%c%c][%c%c%c] ", + da2 & UTLB_DA2_EPR_P_R ? 'r' : '-', + da2 & UTLB_DA2_EPR_P_W ? 'w' : '-', + da2 & UTLB_DA2_EPR_P_X ? 'x' : '-', + da2 & UTLB_DA2_EPR_U_R ? 'r' : '-', + da2 & UTLB_DA2_EPR_U_W ? 'w' : '-', + da2 & UTLB_DA2_EPR_U_X ? 'x' : '-'); + } +#else + const char *pgsz[] = { " 1K", " 4K", " 64K", " 1M" }; + sz = ((da1 & UTLB_SZ0) >> 4) | ((da1 & UTLB_SZ1) >> 6); + + if (!pmb) + { + int pr = (da1 >> 5) & 0x3; + const char *pr_pat[] = { "[r-][--]", + "[rw][--]", + "[rw][r-]", + "[rw][rw]" }; + printf ("%s ", pr_pat[pr]); + } +#endif + printf ("%s ", pmb ? pmb_pgsz[sz] : pgsz[sz]); + +#ifdef SH4A_EXT_ADDR32 + printf ("%s ", da1 & UTLB_DA1_UB ? "UB" : "--"); +#endif + if (da1 & UTLB_DA1_C) + { + printf ("W%c ", da1 & UTLB_DA1_WT ? 'T' : 'B'); + } + else + { + printf ("-- "); + } + bool shared_page = da1 & UTLB_DA1_SH; + if (!pmb) + printf ("%s ", shared_page ? "SH" : "--"); + printf ("VPN:%x PPN:%x ", aa & UTLB_AA_VPN, da1 & UTLB_DA1_PPN); + if (pmb) + printf ("PMB "); + else if (!shared_page) + printf ("ASID:%x ", aa & UTLB_AA_ASID); + + printf ("[%d]\n", n); +} +#endif // DEBUG diff --exclude=CVS --exclude=obj.evbsh3 --exclude=compile --exclude='makeBuild*.log' -uNr src.orig/sys/arch/sh3/sh3/pmap.c src-sh4a.orig/sys/arch/sh3/sh3/pmap.c --- src.orig/sys/arch/sh3/sh3/pmap.c 2010-12-11 17:59:34.000000000 +0900 +++ src-sh4a.orig/sys/arch/sh3/sh3/pmap.c 2010-12-11 18:24:15.000000000 +0900 @@ -42,6 +42,7 @@ #include #include +#include #ifdef DEBUG #define STATIC @@ -59,6 +60,7 @@ struct pmap __pmap_kernel; struct pmap *const kernel_pmap_ptr = &__pmap_kernel; STATIC vaddr_t __pmap_kve; /* VA of last kernel virtual */ +// kloader uses avail_start and avail_end. paddr_t avail_start; /* PA of first available physical page */ paddr_t avail_end; /* PA of last available physical page */ @@ -68,12 +70,6 @@ /* 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); @@ -103,7 +99,6 @@ void pmap_bootstrap(void) { - /* Steal msgbuf area */ initmsgbuf((void *)uvm_pageboot_alloc(MSGBUFSIZE), MSGBUFSIZE); @@ -126,6 +121,7 @@ vaddr_t pmap_steal_memory(vsize_t size, vaddr_t *vstart, vaddr_t *vend) { +// printf("%s\n", __FUNCTION__); struct vm_physseg *bank; int i, j, npage; paddr_t pa; @@ -136,12 +132,20 @@ size = round_page(size); npage = atop(size); +#ifdef SH4A_EXT_ADDR32 + // To assure uvm_pageboot_alloc allocates P1/P2 mapped area. + for (i = 0, bank = &vm_physmem[i]; i < vm_nphysseg; i++, bank++) + if ((npage <= bank->avail_end - bank->avail_start) && + (bank->free_list == VM_FREELIST_P1ACCESS)) + break; +#else bank = NULL; for (i = 0; i < vm_nphysseg; i++) { bank = VM_PHYSMEM_PTR(i); if (npage <= bank->avail_end - bank->avail_start) break; } +#endif KDASSERT(i != vm_nphysseg); KDASSERT(bank != NULL); @@ -160,6 +164,9 @@ } va = SH3_PHYS_TO_P1SEG(pa); +#ifdef SH4A_EXT_ADDR32 + assert(pa < 0x20000000); +#endif memset((void *)va, 0, size); return (va); @@ -168,6 +175,7 @@ vaddr_t pmap_growkernel(vaddr_t maxkvaddr) { +// printf("%s %d\n", __FUNCTION__, uvm.page_init_done); int i, n; if (maxkvaddr <= __pmap_kve) @@ -183,12 +191,21 @@ continue; if (uvm.page_init_done) { +#ifdef SH4A_EXT_ADDR32 + struct vm_page *pg = uvm_pagealloc_strat(NULL, 0, NULL, + UVM_PGA_USERESERVE | UVM_PGA_ZERO, + UVM_PGA_STRAT_ONLY, VM_FREELIST_P1ACCESS); + assert(VM_PAGE_TO_PHYS(pg) < 0x20000000); +#else struct vm_page *pg = uvm_pagealloc(NULL, 0, NULL, UVM_PGA_USERESERVE | UVM_PGA_ZERO); +#endif if (pg == NULL) goto error; __pmap_kernel.pm_ptp[i] = (pt_entry_t *) SH3_PHYS_TO_P1SEG(VM_PAGE_TO_PHYS(pg)); + printf("%s: %lx for %d\n", __FUNCTION__, VM_PAGE_TO_PHYS(pg), i); + } else { pt_entry_t *ptp = (pt_entry_t *) uvm_pageboot_alloc(PAGE_SIZE); @@ -208,7 +225,7 @@ void pmap_virtual_space(vaddr_t *start, vaddr_t *end) { - +// printf("%s\n", __FUNCTION__); *start = VM_MIN_KERNEL_ADDRESS; *end = VM_MAX_KERNEL_ADDRESS; } @@ -216,15 +233,20 @@ void pmap_init(void) { - +// printf("%s\n", __FUNCTION__); /* Initialize pmap module */ +#if 0//def PMAP_MAP_POOLPAGE pool_init(&__pmap_pmap_pool, sizeof(struct pmap), 0, 0, 0, "pmappl", &pool_allocator_nointr, IPL_NONE); +#else + // allocate pmap to P1. + pool_init(&__pmap_pmap_pool, sizeof(struct pmap), 0, 0, 0, "pmappl", + &pmap_pv_page_allocator, IPL_NONE); +#endif pool_init(&__pmap_pv_pool, sizeof(struct pv_entry), 0, 0, 0, "pvpl", &pmap_pv_page_allocator, IPL_NONE); pool_setlowat(&__pmap_pv_pool, 16); - -#ifdef SH4 +#if defined SH4 || defined SH4A //XXX should be SH_HAS_VIRTUAL_ALIAS if (SH_HAS_VIRTUAL_ALIAS) { /* * XXX @@ -240,22 +262,30 @@ sock_loan_thresh = -1; } #endif -} + __pmap_cache_ops_init(); +} pmap_t pmap_create(void) { +// printf("%s\n", __FUNCTION__); pmap_t pmap; + struct vm_page *pg; 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))); +#ifdef SH4A_EXT_ADDR32 + pg = uvm_pagealloc_strat(NULL, 0, NULL, + UVM_PGA_USERESERVE | UVM_PGA_ZERO, + UVM_PGA_STRAT_ONLY, VM_FREELIST_P1ACCESS); + assert(VM_PAGE_TO_PHYS(pg) < 0x20000000); +#else + pg = uvm_pagealloc(NULL, 0, NULL, UVM_PGA_USERESERVE | UVM_PGA_ZERO); +#endif + pmap->pm_ptp = (pt_entry_t **)SH3_PHYS_TO_P1SEG(VM_PAGE_TO_PHYS(pg)); return (pmap); } @@ -263,6 +293,8 @@ void pmap_destroy(pmap_t pmap) { +// printf("%s\n", __FUNCTION__); + vaddr_t va; int i; if (--pmap->pm_refcnt > 0) @@ -270,7 +302,7 @@ /* Deallocate all page table page */ for (i = 0; i < __PMAP_PTP_N; i++) { - vaddr_t va = (vaddr_t)pmap->pm_ptp[i]; + va = (vaddr_t)pmap->pm_ptp[i]; if (va == 0) continue; #ifdef DEBUG /* Check no mapping exists. */ @@ -281,16 +313,15 @@ 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))); + /* Purge cache entry for next use of this page. */ + __pmap_dcache_inv_va(pmap_kernel(), 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))); + va = (vaddr_t)pmap->pm_ptp; // P1 + uvm_pagefree(PHYS_TO_VM_PAGE(SH3_P1SEG_TO_PHYS(va))); + __pmap_dcache_inv_va(pmap_kernel(), va); /* Free ASID */ __pmap_asid_free(pmap->pm_asid); @@ -301,15 +332,18 @@ void pmap_reference(pmap_t pmap) { - +// printf("%s\n", __FUNCTION__); pmap->pm_refcnt++; } void pmap_activate(struct lwp *l) { - pmap_t pmap = l->l_proc->p_vmspace->vm_map.pmap; +// void sh4a_tlb_invalidate_all (void); +// sh4a_tlb_invalidate_all(); + pmap_t pmap = l->l_proc->p_vmspace->vm_map.pmap; +// printf("%s %d\n", __FUNCTION__, pmap->pm_asid); if (pmap->pm_asid == -1) pmap->pm_asid = __pmap_asid_alloc(); @@ -322,13 +356,14 @@ void pmap_deactivate(struct lwp *l) { - +// printf("%s\n", __FUNCTION__); /* Nothing to do */ } int pmap_enter(pmap_t pmap, vaddr_t va, paddr_t pa, vm_prot_t prot, u_int flags) { +// printf("%s pa=%lx va=%lx\n", __FUNCTION__, pa, va); struct vm_page *pg; struct vm_page_md *pvh; pt_entry_t entry, *pte; @@ -405,9 +440,9 @@ 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 (prot == (VM_PROT_READ | VM_PROT_EXECUTE)) { + __pmap_icache_inv_va(pmap, va); + } if (entry & _PG_WIRED) pmap->pm_stats.wired_count++; @@ -427,6 +462,7 @@ __pmap_map_change(pmap_t pmap, vaddr_t va, paddr_t pa, vm_prot_t prot, pt_entry_t entry) { +// printf("%s\n", __FUNCTION__); pt_entry_t *pte, oentry; vaddr_t eva = va + PAGE_SIZE; @@ -454,10 +490,12 @@ /* "wired" is software bits. no need to update TLB */ pmap->pm_stats.wired_count--; } +#if 1//XXXnoneed } else if (entry & _PG_WIRED) { /* unwired -> wired. make sure to reflect "flags" */ pmap_remove(pmap, va, eva); return (false); +#endif } return (true); /* mapping was changed. */ @@ -471,6 +509,7 @@ void __pmap_pv_enter(pmap_t pmap, struct vm_page *pg, vaddr_t va) { +// printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%s pa=%lx, va=%lx\n", __FUNCTION__, pa, va); struct vm_page_md *pvh; struct pv_entry *pv; int s; @@ -493,6 +532,7 @@ sh_cache_indexof(pv->pv_va)) { pmap_remove(pv->pv_pmap, pv->pv_va, pv->pv_va + PAGE_SIZE); + printf("VIRTUAL ALIAS FOUND\n"); goto again; } } @@ -511,6 +551,7 @@ void pmap_remove(pmap_t pmap, vaddr_t sva, vaddr_t eva) { + printf("%s: asid%d %lx-%lx\n", __FUNCTION__, pmap->pm_asid, sva, eva); struct vm_page *pg; pt_entry_t *pte, entry; vaddr_t va; @@ -546,6 +587,7 @@ void __pmap_pv_remove(pmap_t pmap, struct vm_page *pg, vaddr_t vaddr) { +// printf("%s\n", __FUNCTION__); struct vm_page_md *pvh; struct pv_entry *pv; int s; @@ -570,10 +612,14 @@ break; } } + __pmap_icache_inv_va(pmap, vaddr); + #ifdef DEBUG /* Check duplicated map. */ - SLIST_FOREACH(pv, &pvh->pvh_head, pv_link) + SLIST_FOREACH(pv, &pvh->pvh_head, pv_link) { +// printf("%s: pmap %p va %lx\n", __FUNCTION__, pv->pv_pmap, pv->pv_va); KDASSERT(!(pv->pv_pmap == pmap && pv->pv_va == vaddr)); + } #endif splx(s); } @@ -581,11 +627,12 @@ void pmap_kenter_pa(vaddr_t va, paddr_t pa, vm_prot_t prot, u_int flags) { +// printf("%s va=%lx pa=%lx ptpslot=%ld\n", __FUNCTION__, va, pa, +// __PMAP_PTP_INDEX(va-VM_MIN_KERNEL_ADDRESS)); 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); @@ -595,7 +642,10 @@ if (PHYS_TO_VM_PAGE(pa)) entry |= PG_C; - pte = __pmap_kpte_lookup(va); + if ((pte = __pmap_kpte_lookup(va)) == NULL) { + printf ("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$%s no pte\n", + __FUNCTION__); + } KDASSERT(*pte == 0); *pte = entry; @@ -606,6 +656,7 @@ void pmap_kremove(vaddr_t va, vsize_t len) { +// printf("%s va=%lx len=%lx\n", __FUNCTION__, va, len); pt_entry_t *pte; vaddr_t eva = va + len; @@ -619,8 +670,8 @@ if (*pte == 0) continue; - if (SH_HAS_VIRTUAL_ALIAS && PHYS_TO_VM_PAGE(*pte & PG_PPN)) - sh_dcache_wbinv_range(va, PAGE_SIZE); + if (PHYS_TO_VM_PAGE(*pte & PG_PPN)) // Memory. + __pmap_dcache_wbinv_va(pmap_kernel(), va);//XXXinv?? *pte = 0; sh_tlb_invalidate_addr(0, va); @@ -630,18 +681,22 @@ bool pmap_extract(pmap_t pmap, vaddr_t va, paddr_t *pap) { +// printf("%s\n", __FUNCTION__); 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) + if (pte == NULL || *pte == 0) { +// printf("%s va=%lx failed\n", __FUNCTION__, va); return (false); + } if (pap != NULL) *pap = (*pte & PG_PPN) | (va & PGOFSET); @@ -652,6 +707,7 @@ void pmap_protect(pmap_t pmap, vaddr_t sva, vaddr_t eva, vm_prot_t prot) { +// printf("%s\n", __FUNCTION__); bool kernel = pmap == pmap_kernel(); pt_entry_t *pte, entry, protbits; vaddr_t va; @@ -685,12 +741,10 @@ (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); - } + if (prot & VM_PROT_EXECUTE) + __pmap_icache_inv_va(pmap, va);// also dcache_wbinv + else + __pmap_dcache_wbinv_va(pmap, va); entry = (entry & ~PG_PR_MASK) | protbits; *pte = entry; @@ -703,6 +757,7 @@ void pmap_page_protect(struct vm_page *pg, vm_prot_t prot) { +// printf("%s\n", __FUNCTION__); struct vm_page_md *pvh = VM_PAGE_TO_MD(pg); struct pv_entry *pv; struct pmap *pmap; @@ -743,6 +798,7 @@ void pmap_unwire(pmap_t pmap, vaddr_t va) { +// printf("%s\n", __FUNCTION__); pt_entry_t *pte, entry; if ((pte = __pmap_pte_lookup(pmap, va)) == NULL || @@ -757,18 +813,64 @@ void pmap_procwr(struct proc *p, vaddr_t va, size_t len) { - +// printf("%s\n", __FUNCTION__); +#if 0 if (!SH_HAS_UNIFIED_CACHE) sh_icache_sync_range_index(va, len); +#else + if (SH_HAS_UNIFIED_CACHE) + return; + struct pmap *pmap = p->p_vmspace->vm_map.pmap; + int current_asid = sh_tlb_get_asid(); + + if (pmap->pm_asid == current_asid) + sh_icache_sync_range(va, len); + else + sh_icache_sync_range_index(va, len); +#endif } void pmap_zero_page(paddr_t phys) { +// printf("%s pa=%lx\n", __FUNCTION__, phys); +#ifdef SH4A_EXT_ADDR32 + if (phys < 0x20000000) + goto maped_area; + struct vm_page *pg; + struct vm_page_md *pvh; + struct pv_entry *pv; + bool vm_mapped = FALSE; + if ((pg = PHYS_TO_VM_PAGE(phys)) != NULL) { + pvh = &pg->mdpage; + // For each vm page which maps this physical page. + SLIST_FOREACH(pv, &pvh->pvh_head, pv_link) { + sh_tlb_set_asid(pv->pv_pmap->pm_asid); + memset ((void *)pv->pv_va, 0, PAGE_SIZE); + sh_tlb_set_asid(0); + vm_mapped = TRUE; + } + } + if (!vm_mapped) { + // Mapped to P0 area + vaddr_t va = 0; + sh_tlb_update (0, va, + (phys & PG_PPN) | PG_PR_KRW | PG_V | PG_D | PG_4K); + int asid = sh_tlb_get_asid(); + sh_tlb_set_asid(0); + memset ((void *)va, 0, PAGE_SIZE); + sh_tlb_set_asid(asid); + sh_tlb_invalidate_addr (0, 0); + } + return; +maped_area: +#endif if (SH_HAS_VIRTUAL_ALIAS) { /* don't polute cache */ /* sync cache since we access via P2. */ - sh_dcache_wbinv_all(); + if ((pg = PHYS_TO_VM_PAGE(phys))) { + __pmap_dcache_inv_pg(pg); //OK inv + } memset((void *)SH3_PHYS_TO_P2SEG(phys), 0, PAGE_SIZE); } else { memset((void *)SH3_PHYS_TO_P1SEG(phys), 0, PAGE_SIZE); @@ -778,21 +880,58 @@ void pmap_copy_page(paddr_t src, paddr_t dst) { - - if (SH_HAS_VIRTUAL_ALIAS) { /* don't polute cache */ + printf("%s src:%lx, dst:%lx\n", __FUNCTION__, src, dst); + struct vm_page *pg; +#ifdef SH4A_EXT_ADDR32 + if (src < 0x20000000 && dst < 0x20000000) + goto maped_area; + struct vm_page *pg_src, *pg_dst; + vaddr_t dst_va; + vaddr_t src_va; + int s = _cpu_intr_suspend(); + // If mapped to virtual address, sync cache. + if ((pg_src = PHYS_TO_VM_PAGE(src)) != NULL) + __pmap_dcache_wb_pg(pg_src); + + if ((pg_dst = PHYS_TO_VM_PAGE(dst)) != NULL) + __pmap_dcache_inv_pg(pg_src);//XXXinv + + src_va = 0; + dst_va = PAGE_SIZE; + sh_tlb_update(0, src_va, + (src & PG_PPN) | PG_PR_KRW | PG_V | PG_D | PG_4K); + sh_tlb_update(0, dst_va, + (dst & PG_PPN) | PG_PR_KRW | PG_V | PG_D | PG_4K); + int asid = sh_tlb_get_asid(); + sh_tlb_set_asid(0); + memcpy((void *)dst_va, (void *)src_va, PAGE_SIZE); + sh_tlb_set_asid(asid); + sh_tlb_invalidate_addr (0, src_va); + sh_tlb_invalidate_addr (0, dst_va); + _cpu_intr_resume (s); + return; +maped_area: +#endif + if (SH_HAS_VIRTUAL_ALIAS) { /* sync cache since we access via P2. */ - sh_dcache_wbinv_all(); + printf("%s P2\n", __FUNCTION__); + if ((pg = PHYS_TO_VM_PAGE(dst))) + __pmap_dcache_inv_pg(pg); + if ((pg = PHYS_TO_VM_PAGE(src))) + __pmap_dcache_wb_pg(pg); 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); } +// printf("DONE***************************************%s\n", __FUNCTION__); } bool pmap_is_referenced(struct vm_page *pg) { +// printf("%s\n", __FUNCTION__); struct vm_page_md *pvh = VM_PAGE_TO_MD(pg); return ((pvh->pvh_flags & PVH_REFERENCED) ? true : false); @@ -801,6 +940,7 @@ bool pmap_clear_reference(struct vm_page *pg) { +// printf("%s\n", __FUNCTION__); struct vm_page_md *pvh = VM_PAGE_TO_MD(pg); struct pv_entry *pv; pt_entry_t *pte; @@ -836,6 +976,7 @@ bool pmap_is_modified(struct vm_page *pg) { +// printf("%s\n", __FUNCTION__); struct vm_page_md *pvh = VM_PAGE_TO_MD(pg); return ((pvh->pvh_flags & PVH_MODIFIED) ? true : false); @@ -844,6 +985,7 @@ bool pmap_clear_modify(struct vm_page *pg) { +// printf("%s\n", __FUNCTION__); struct vm_page_md *pvh = VM_PAGE_TO_MD(pg); struct pv_entry *pv; struct pmap *pmap; @@ -865,8 +1007,11 @@ } /* Write-back and invalidate TLB entry */ - if (!SH_HAS_VIRTUAL_ALIAS && SH_HAS_WRITEBACK_CACHE) - sh_dcache_wbinv_all(); +#if 0 + if (!SH_HAS_VIRTUAL_ALIAS && SH_HAS_WRITEBACK_CACHE)//XXX + sh_dcache_wbinv_all();//XXX +#endif +// __pmap_dcache_wbinv_pg(pg); SLIST_FOREACH(pv, &pvh->pvh_head, pv_link) { pmap = pv->pv_pmap; @@ -877,8 +1022,7 @@ if ((entry & PG_D) == 0) continue; - if (SH_HAS_VIRTUAL_ALIAS) - sh_dcache_wbinv_range_index(va, PAGE_SIZE); + __pmap_dcache_wbinv_va(pmap, va); *pte = entry & ~PG_D; if (pmap->pm_asid != -1) @@ -892,11 +1036,11 @@ paddr_t pmap_phys_address(paddr_t cookie) { - +// printf("%s\n", __FUNCTION__); return (sh3_ptob(cookie)); } -#ifdef SH4 +#if defined SH4 || defined SH4A //XXX should be SH_HAS_VIRTUAL_ALIAS /* * pmap_prefer(vaddr_t foff, vaddr_t *vap) * @@ -906,15 +1050,26 @@ void pmap_prefer(vaddr_t foff, vaddr_t *vap) { +// printf("%s\n", __FUNCTION__); vaddr_t va; + if (*vap & 0x1f) + printf("%s %lx\n", __FUNCTION__, *vap); + assert (!(foff & 0x1f)); if (SH_HAS_VIRTUAL_ALIAS) { +#if 0 va = *vap; - *vap = va + ((foff - va) & sh_cache_prefer_mask); +#else + va = *vap; + uint32_t ci0 = foff & (0xff << 5); + uint32_t ci1 = va & (0xff << 5); + *vap = va + (ci0 - ci1); +#endif + } } -#endif /* SH4 */ +#endif /* SH_HAS_VIRTUAL_ALIAS */ /* * pv_entry pool allocator: @@ -924,9 +1079,15 @@ void * __pmap_pv_page_alloc(struct pool *pool, int flags) { +// printf("%s\n", __FUNCTION__); struct vm_page *pg; - +#ifdef SH4A_EXT_ADDR32 + pg = uvm_pagealloc_strat(NULL, 0, NULL, UVM_PGA_USERESERVE, + UVM_PGA_STRAT_ONLY, VM_FREELIST_P1ACCESS); + assert(VM_PAGE_TO_PHYS(pg) < 0x20000000); +#else pg = uvm_pagealloc(NULL, 0, NULL, UVM_PGA_USERESERVE); +#endif if (pg == NULL) return (NULL); @@ -936,11 +1097,12 @@ void __pmap_pv_page_free(struct pool *pool, void *v) { +// printf("%s\n", __FUNCTION__); 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); + __pmap_dcache_inv_va(pmap_kernel(), va); + uvm_pagefree(PHYS_TO_VM_PAGE(SH3_P1SEG_TO_PHYS(va))); } @@ -952,6 +1114,7 @@ pt_entry_t * __pmap_pte_alloc(pmap_t pmap, vaddr_t va) { +// printf("%s\n", __FUNCTION__); struct vm_page *pg; pt_entry_t *ptp, *pte; @@ -959,7 +1122,14 @@ return (pte); /* Allocate page table (not managed page) */ +#ifdef SH4A_EXT_ADDR32 + pg = uvm_pagealloc_strat(NULL, 0, NULL, + UVM_PGA_USERESERVE | UVM_PGA_ZERO, + UVM_PGA_STRAT_ONLY, VM_FREELIST_P1ACCESS); + assert(VM_PAGE_TO_PHYS(pg) < 0x20000000); +#else pg = uvm_pagealloc(NULL, 0, NULL, UVM_PGA_USERESERVE | UVM_PGA_ZERO); +#endif if (pg == NULL) return NULL; @@ -976,6 +1146,7 @@ pt_entry_t * __pmap_pte_lookup(pmap_t pmap, vaddr_t va) { +//// printf("%s\n", __FUNCTION__); pt_entry_t *ptp; if (pmap == pmap_kernel()) @@ -989,6 +1160,7 @@ return (ptp + __PMAP_PTP_OFSET(va)); } + /* * pt_entry_t *__pmap_kpte_lookup(vaddr_t va): * kernel virtual only version of __pmap_pte_lookup(). @@ -997,11 +1169,12 @@ __pmap_kpte_lookup(vaddr_t va) { pt_entry_t *ptp; - +// printf("%s va=%lx, %lx\n", __FUNCTION__, va, __PMAP_PTP_INDEX(va-VM_MIN_KERNEL_ADDRESS)); ptp = __pmap_kernel.pm_ptp[__PMAP_PTP_INDEX(va-VM_MIN_KERNEL_ADDRESS)]; if (ptp == NULL) return NULL; +// printf("%s found %p\n", __FUNCTION__, ptp + __PMAP_PTP_OFSET(va)); return (ptp + __PMAP_PTP_OFSET(va)); } @@ -1013,6 +1186,7 @@ bool __pmap_pte_load(pmap_t pmap, vaddr_t va, int flags) { +// printf("%s\n", __FUNCTION__); struct vm_page *pg; pt_entry_t *pte; pt_entry_t entry; @@ -1056,6 +1230,7 @@ int __pmap_asid_alloc(void) { +// printf("%s\n", __FUNCTION__); struct proc *p; int i, j, k, n, map, asid; @@ -1069,6 +1244,8 @@ if ((map & (1 << j)) == 0 && (k + j) != 0) { __pmap_asid.map[k] |= (1 << j); __pmap_asid.hint = (k << 5) + j; + printf("%s: %d\n", __FUNCTION__, + __pmap_asid.hint); return (__pmap_asid.hint); } } @@ -1102,8 +1279,11 @@ if (asid < 1) /* Don't invalidate kernel ASID 0 */ return; - + printf("%s:%d\n", __FUNCTION__, asid); sh_tlb_invalidate_asid(asid); +// void sh4a_dcache_array_dump (vaddr_t va, vsize_t sz); +// sh4a_dcache_array_dump(0, 32*1024); + i = asid >> 5; __pmap_asid.map[i] &= ~(1 << (asid - (i << 5))); diff --exclude=CVS --exclude=obj.evbsh3 --exclude=compile --exclude='makeBuild*.log' -uNr src.orig/sys/arch/sh3/sh3/pmap_cache_ops.c src-sh4a.orig/sys/arch/sh3/sh3/pmap_cache_ops.c --- src.orig/sys/arch/sh3/sh3/pmap_cache_ops.c 1970-01-01 09:00:00.000000000 +0900 +++ src-sh4a.orig/sys/arch/sh3/sh3/pmap_cache_ops.c 2010-01-06 19:11:51.000000000 +0900 @@ -0,0 +1,256 @@ +/* $NetBSD$ */ + +/*- + * Copyright (c) 2009 UCHIYAMA Yasushi. 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 +__KERNEL_RCSID(0, "$NetBSD$"); + +#include +#include +#include +#include + +#include + +#include +#include +#include + +#ifdef DEBUG +#define STATIC +#else +#define STATIC static +#endif + +cache_func_t *current_dcache_inv; +cache_func_t *noncurrent_dcache_inv; +cache_func_t *current_dcache_wb; +cache_func_t *noncurrent_dcache_wb; +cache_func_t *current_dcache_wbinv; +cache_func_t *noncurrent_dcache_wbinv; + +cache_func_t *current_icache_inv; +cache_func_t *noncurrent_icache_inv; + +STATIC void cache_nop(vaddr_t va, vsize_t sz); + +void +cache_nop(vaddr_t va, vsize_t sz) +{ +} + +void +__pmap_cache_ops_init () +{ + // I-cache + if (SH_HAS_UNIFIED_CACHE) { + current_icache_inv = cache_nop; + noncurrent_icache_inv = cache_nop; + } else { + current_icache_inv = sh_cache_ops._icache_sync_range; + noncurrent_icache_inv = + sh_cache_ops._icache_sync_range_index; + } + + // D-cache + + // Invalidate + if (SH_HAS_WRITEBACK_CACHE) { + printf ("writeback "); + if (SH_HAS_VIRTUAL_ALIAS) { + printf ("virtual alias "); + current_dcache_inv = sh_cache_ops._dcache_inv_range; + if (sh_cache_ways > 1) { + printf("way=%d\n", sh_cache_ways); + noncurrent_dcache_inv = + sh_cache_ops._dcache_wbinv_range_index; + } else { + printf ("direct map"); +#if 0 + noncurrent_dcache_inv = + sh_cache_ops._dcache_inv_range_index; +#else + noncurrent_dcache_inv = + sh_cache_ops._dcache_wbinv_range_index; +#endif + } + } else { + current_dcache_inv = cache_nop; + noncurrent_dcache_inv = cache_nop; + } + } else { + current_dcache_inv = cache_nop; + noncurrent_dcache_inv = cache_nop; + } + + // Writeback + if (SH_HAS_WRITEBACK_CACHE) { + current_dcache_wb = sh_cache_ops._dcache_wb_range; +#if 0 + noncurrent_dcache_wb = sh_cache_ops._dcache_wb_range_index; +#else + noncurrent_dcache_wb = sh_cache_ops._dcache_wbinv_range_index; +#endif + } else { + current_dcache_wb = cache_nop; + noncurrent_dcache_wb = cache_nop; + } + + // Writeback Invalidate + if (SH_HAS_WRITEBACK_CACHE) { + current_dcache_wbinv = sh_cache_ops._dcache_wbinv_range; + noncurrent_dcache_wbinv = sh_cache_ops._dcache_wbinv_range_index; + } else { + current_dcache_wbinv = sh_cache_ops._dcache_inv_range; +#if 0 + noncurrent_dcache_wbinv = sh_cache_ops._dcache_inv_range_index; +#else + noncurrent_dcache_wbinv = sh_cache_ops._dcache_wbinv_range_index; +#endif + } + printf("\n"); +} + +void __pmap_pg_dump(struct vm_page *pg) +{ + struct vm_page_md *pvh; + struct pv_entry *pv; +// int current_asid = sh_tlb_get_asid(); + printf("%s: %p\n", __FUNCTION__, pg); + pvh = &pg->mdpage; + SLIST_FOREACH(pv, &pvh->pvh_head, pv_link) { + printf ("%p: %p-%lx\n", pg, pv->pv_pmap, pv->pv_va); + } +} + +void __pmap_icache_inv_va(struct pmap *pmap, vaddr_t va) +{ + int current_asid = sh_tlb_get_asid(); + + if (pmap == pmap_kernel() || pmap->pm_asid == current_asid) + current_icache_inv(va, PAGE_SIZE); + else + noncurrent_icache_inv(va, PAGE_SIZE); +} + + +void __pmap_dcache_inv_va(struct pmap *pmap, vaddr_t va) +{ + int current_asid = sh_tlb_get_asid(); + + if (pmap == pmap_kernel() || pmap->pm_asid == current_asid) + current_dcache_inv(va, PAGE_SIZE); + else + noncurrent_dcache_inv(va, PAGE_SIZE); +} + +void __pmap_dcache_wb_va(struct pmap *pmap, vaddr_t va) +{ + int current_asid = sh_tlb_get_asid(); + + if (pmap == pmap_kernel() || pmap->pm_asid == current_asid) + current_dcache_wb(va, PAGE_SIZE); + else + noncurrent_dcache_wb(va, PAGE_SIZE); +} + +void __pmap_dcache_wbinv_va(struct pmap *pmap, vaddr_t va) +{ + int current_asid = sh_tlb_get_asid(); + + if (pmap == pmap_kernel() || pmap->pm_asid == current_asid) + current_dcache_wbinv(va, PAGE_SIZE); + else + noncurrent_dcache_wbinv(va, PAGE_SIZE); +} + +extern int __tlb_exception_cnt; +extern int __tlb_exception_debug; +paddr_t sh4a_mmu_utlb_lookup_by_va (vaddr_t); +void sh4a_dcache_array_dump (vaddr_t, vsize_t); + +void __pmap_dcache_inv_pg(struct vm_page *pg) +{ + struct vm_page_md *pvh; + struct pv_entry *pv; + struct pmap *pmap; + int current_asid = sh_tlb_get_asid(); + pvh = &pg->mdpage; +// int s = splvm(); + SLIST_FOREACH(pv, &pvh->pvh_head, pv_link) { + pmap = pv->pv_pmap; + paddr_t pa = sh4a_mmu_utlb_lookup_by_va (pv->pv_va); +// sh4a_dcache_array_dump (pv->pv_va, PAGE_SIZE); + printf("%s: ASID%d<->%d %p,va:%lx pa:%lx ", __FUNCTION__, current_asid, pmap->pm_asid, pmap, pv->pv_va, pa); + if (pmap == pmap_kernel() || pmap->pm_asid == current_asid) { + printf("ohayo0 %d\n", __tlb_exception_cnt); + __tlb_exception_debug = 1; + current_dcache_inv(pv->pv_va, PAGE_SIZE); + printf("ohayo1 %d\n", __tlb_exception_cnt); + __tlb_exception_debug = 0; + } else { + noncurrent_dcache_inv(pv->pv_va, PAGE_SIZE); + } + } +// splx(s); +} + +void __pmap_dcache_wb_pg(struct vm_page *pg) +{ + struct vm_page_md *pvh; + struct pv_entry *pv; + struct pmap *pmap; + int current_asid = sh_tlb_get_asid(); + + pvh = &pg->mdpage; + SLIST_FOREACH(pv, &pvh->pvh_head, pv_link) { + pmap = pv->pv_pmap; + if (pmap == pmap_kernel() || pmap->pm_asid == current_asid) + current_dcache_wb(pv->pv_va, PAGE_SIZE); + else + noncurrent_dcache_wb(pv->pv_va, PAGE_SIZE); + } +} + +void __pmap_dcache_wbinv_pg(struct vm_page *pg) +{ + struct vm_page_md *pvh; + struct pv_entry *pv; + struct pmap *pmap; + int current_asid = sh_tlb_get_asid(); + + pvh = &pg->mdpage; + SLIST_FOREACH(pv, &pvh->pvh_head, pv_link) { + pmap = pv->pv_pmap; + printf("%s: ASID%d<->%d %p,va:%lx pa:%lx ", __FUNCTION__, current_asid, pmap->pm_asid, pmap, pv->pv_va, sh4a_mmu_utlb_lookup_by_va (pv->pv_va)); + if (pmap == pmap_kernel() || pmap->pm_asid == current_asid) { +// printf("ohayo-0 %d\n", __tlb_exception_cnt); + current_dcache_wbinv(pv->pv_va, PAGE_SIZE); +// printf("ohayo-1 %d\n", __tlb_exception_cnt); + } else { + noncurrent_dcache_wbinv(pv->pv_va, PAGE_SIZE); + } + } +} diff --exclude=CVS --exclude=obj.evbsh3 --exclude=compile --exclude='makeBuild*.log' -uNr src.orig/sys/arch/sh3/sh3/pmap_map_poolpage.c src-sh4a.orig/sys/arch/sh3/sh3/pmap_map_poolpage.c --- src.orig/sys/arch/sh3/sh3/pmap_map_poolpage.c 1970-01-01 09:00:00.000000000 +0900 +++ src-sh4a.orig/sys/arch/sh3/sh3/pmap_map_poolpage.c 2010-01-06 19:11:51.000000000 +0900 @@ -0,0 +1,46 @@ +#if 0 +vaddr_t +pmap_map_poolpage(paddr_t pa) +{ + struct vm_page *pg; + struct vm_page_md *pvh; + struct pv_entry *pv; + + if (pa < 0x20000000) { + return SH3_PHYS_TO_P1SEG(pa); + } + pg = PHYS_TO_VM_PAGE(pa); + assert(pg); + pvh = &pg->mdpage; + if ((pv = SLIST_FIRST(&pvh->pvh_head)) != 0) + return pv->pv_va; + panic(__FUNCTION__); + assert(kernel_map); + uvm_flag_t mapflags = UVM_MAPFLAG(UVM_PROT_ALL, UVM_PROT_ALL, + UVM_INH_NONE, UVM_ADV_RANDOM, UVM_FLAG_NOMERGE); + struct uvm_map_args args; + uvm_map_prepare(kernel_map, 0, PAGE_SIZE, NULL, + UVM_UNKNOWN_OFFSET, 0, mapflags, &args); + + vaddr_t va = args.uma_start; + printf ("%s pa=%lx va=%lx\n", __FUNCTION__, pa, va); + + pmap_kenter_pa(va, VM_PAGE_TO_PHYS(pg), + VM_PROT_READ|VM_PROT_WRITE|PMAP_KMPAGE); + + vm_map_unlock(kernel_map); + return va; +} + +paddr_t +pmap_unmap_poolpage(vaddr_t va) +{ + paddr_t pa; + + pmap_extract(&__pmap_kernel, va, &pa); + if (pa < 0x20000000) + return SH3_P1SEG_TO_PHYS(va); + panic(__FUNCTION__); + return pa; +} +#endif diff --exclude=CVS --exclude=obj.evbsh3 --exclude=compile --exclude='makeBuild*.log' -uNr src.orig/sys/arch/sh3/sh3/pmb.c src-sh4a.orig/sys/arch/sh3/sh3/pmb.c --- src.orig/sys/arch/sh3/sh3/pmb.c 1970-01-01 09:00:00.000000000 +0900 +++ src-sh4a.orig/sys/arch/sh3/sh3/pmb.c 2010-01-06 19:11:51.000000000 +0900 @@ -0,0 +1,166 @@ + +/*- + * Copyright (c) 2009 UCHIYAMA Yasushi. 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. + */ + +// Physical Address Space. (SH4A_EXT_ADDR32) + +#ifdef SH4A_EXT_ADDR32 //32bit physical addrres mode. +#include +__KERNEL_RCSID(0, "$NetBSD$"); + +#include +#include +#include + +static int pmb_page_size[] = { 16, 64, 128, 512 }; + +struct { + uint32_t aa; + uint32_t da; +} pmb [] = { + // P1 + { 0x80000000 | PMB_AA_V, +#if 1 + 0x00000000 | PMB_DA_V | PMB_DA_C | PMB_DA_SZ_512M }, +#else + 0x00000000 | PMB_DA_V | PMB_DA_C | PMB_DA_WT | PMB_DA_SZ_512M },// write-thru test. +#endif + // P2 + { 0xa0000000 | PMB_AA_V, + 0x00000000 | PMB_DA_V | PMB_DA_SZ_512M }, +}; + +void +sh4a_pmb_setup() +{ + // Change PMB setting P1/P2 + sh4a_pmb_entry_set_self (pmb[0].aa, pmb[0].da, pmb[1].aa, pmb[1].da); + + // Additional PMB. + size_t i; + for (i = 2; i < sizeof pmb / sizeof (pmb[0]); i++) + { + if (!sh4a_pmb_align_check (pmb[i].aa, pmb[i].da)) + continue; + sh4a_pmb_entry_set (i, pmb[i].aa, pmb[i].da); + *SH4A_MMUCR |= MMUCR_TI; // Invalidate TLB + CPU_SYNC_RESOURCE (); // For MMUCR + } +} + +bool +sh4a_pmb_region_write_thru (int region) +{ + + return pmb[region].da & PMB_DA_WT; +} + +bool +sh4a_pmb_align_check (uint32_t aa, uint32_t da) +{ + int pgmb = pmb_page_size[_PMB_SZ_INDEX (da)]; + uint32_t mask = pgmb * 1024 * 1024 - 1; + uint32_t vpn = aa & PMB_AA_VPN; + uint32_t ppn = da & PMB_DA_PPN; + bool vpn_ok = !(vpn & mask); + bool ppn_ok = !(ppn & mask); + + printf ("PMB page size %dMB mask=%x VPN:%x%s PPN:%x%s\n", pgmb, mask, + vpn, vpn_ok ? "" : "***NG***", ppn, ppn_ok ? "" : "***NG***"); + + return vpn_ok && ppn_ok; +} + +void +sh4a_pmb_entry_get (int entry, uint32_t *aa, uint32_t *da) +{ + uint32_t e = entry << PMB_AA_E_SHIFT; + + *aa = *(volatile uint32_t *)(PMB_AA | e); + *da = *(volatile uint32_t *)(PMB_DA | e); +} + +void +sh4a_pmb_entry_set (int entry, uint32_t aa, uint32_t da) +{ + uint32_t e = entry << PMB_AA_E_SHIFT; + + aa &= PMB_AA_VALID_BIT; + da &= PMB_DA_VALID_BIT; + // Valid bit is mapped to both AA and DA. + aa |= PMB_AA_V; + da &= ~PMB_DA_V; + *(volatile uint32_t *)(PMB_DA | e) = da; + *(volatile uint32_t *)(PMB_AA | e) = aa; +} + +#include "opt_ddb.h" +#ifdef DDB +#include +#define printf db_printf +void sh4a_pmb_entry_dump (uint32_t, uint32_t); + +void +sh4a_pmb_entry_dump (uint32_t aa, uint32_t da) +{ + + if (!(aa & PMB_AA_V)) + return; + + printf ("VPN:%x (%c) ", aa & PMB_AA_VPN, aa & PMB_AA_V ? 'V' : '-'); + printf ("PPN:%x (%c) ", da & PMB_DA_PPN, da & PMB_DA_V ? 'V' : '-'); + printf ("%dMB, ", pmb_page_size[_PMB_SZ_INDEX (da)]); + printf ("%sbufferd write, ", da & PMB_DA_UB ? "un" : ""); + printf ("%scacheable, ", da & PMB_DA_C ? "" : "un"); + printf ("write-%s, ", da & PMB_DA_WT ? "thru" : "back"); + + printf ("\n"); +} + +void +sh4a_pmb_dump () +{ + uint32_t r; + int entry; + int i; + + r = *PASCR; + if (!(r & PASCR_SE)) + { + // These are effectable for 29bit mode. + printf ("Buffered write setting: |"); + for (i = 0; i < 8; i++) + printf ("%c", r & (1 << i) ? 'x' : '-'); + printf ("| x:unbuffered write.\n"); + } + + for (entry = 0; entry < PMB_ENTRY; entry++) + { + uint32_t aa, da; + sh4a_pmb_entry_get (entry, &aa, &da); + sh4a_pmb_entry_dump (aa, da); + } +} +#endif +#endif // SH4A_EXT_ADDR32 diff --exclude=CVS --exclude=obj.evbsh3 --exclude=compile --exclude='makeBuild*.log' -uNr src.orig/sys/arch/sh3/sh3/pmb_subr.S src-sh4a.orig/sys/arch/sh3/sh3/pmb_subr.S --- src.orig/sys/arch/sh3/sh3/pmb_subr.S 1970-01-01 09:00:00.000000000 +0900 +++ src-sh4a.orig/sys/arch/sh3/sh3/pmb_subr.S 2010-01-06 19:11:51.000000000 +0900 @@ -0,0 +1,68 @@ + +/*- + * Copyright (c) 2009 UCHIYAMA Yasushi. 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 + +__KERNEL_RCSID(0, "$NetBSD$") + +/* + void sh4a_pmb_entry_set_self (uint32_t aa0, uint32_t da0, uint32_t aa1, + uint32_t da1) +*/ +NENTRY (sh4a_pmb_entry_set_self) + mov.l r8, @-r15 + mov.l r9, @-r15 + mov.l r10, @-r15 + mov.l .L_MMUCR, r8 + mov #4, r9 /* MMUCR.TI*/ + mov.l .L_PMB_AA0, r0 + mov.l .L_PMB_DA0, r1 + mov.l .L_PMB_AA1, r2 + mov.l .L_PMB_DA1, r3 + mov.l r4, @r0 + mov.l r5, @r1 + mov.l r6, @r2 + mov.l r7, @r3 + /* MMUCR.TI = 1*/ + mov.l @r8, r10 + or r9, r10 + mov.l r10, @r8 + /* Sync resrouce.*/ + icbi @r0 + mov.l @r15+, r10 + mov.l @r15+, r9 + rts + mov.l @r15+, r8 + .align 2 +.L_MMUCR: + .long 0xff000010 +.L_PMB_AA0: + .long 0xf6100000 +.L_PMB_AA1: + .long 0xf6100100 +.L_PMB_DA0: + .long 0xf7100000 +.L_PMB_DA1: + .long 0xf7100100 diff --exclude=CVS --exclude=obj.evbsh3 --exclude=compile --exclude='makeBuild*.log' -uNr src.orig/sys/arch/sh3/sh3/sh3_machdep.c src-sh4a.orig/sys/arch/sh3/sh3/sh3_machdep.c --- src.orig/sys/arch/sh3/sh3/sh3_machdep.c 2011-03-07 19:54:26.000000000 +0900 +++ src-sh4a.orig/sys/arch/sh3/sh3/sh3_machdep.c 2011-03-07 19:59:17.000000000 +0900 @@ -90,6 +90,8 @@ #include #include +#include //for mb_map + #ifdef KGDB #include #ifndef KGDB_DEVNAME @@ -109,6 +111,10 @@ #include #include +#ifdef SH4A_EXT_ADDR32 +#include //PMB +#endif + /* Our exported CPU info; we can have only one. */ struct cpu_info cpu_info_store; int cpu_arch; @@ -126,14 +132,14 @@ #endif #define VBR (uint8_t *)SH3_PHYS_TO_P1SEG(IOM_RAM_BEGIN) -vaddr_t ram_start = SH3_PHYS_TO_P1SEG(IOM_RAM_BEGIN); +vaddr_t ram_start = SH3_PHYS_TO_P1SEG(IOM_RAM_BEGIN);// who use this ? /* exception handler holder (sh3/sh3/exception_vector.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 +#if defined SH4 || defined SH4A extern char sh4_vector_tlbmiss[], sh4_vector_tlbmiss_end[]; #endif /* @@ -151,6 +157,11 @@ cpu_arch = arch; cpu_product = product; +#ifdef SH4A_EXT_ADDR32 + // P1 cache configuration is PMB. not CCR_CB bit. + sh4a_pmb_setup(); // Setup P1/P2 +#endif + #if defined(SH3) && defined(SH4) /* Set register addresses */ sh_devreg_init(); @@ -176,8 +187,8 @@ memcpy(VBR + 0x400, sh3_vector_tlbmiss, sh3_vector_tlbmiss_end - sh3_vector_tlbmiss); #endif -#ifdef SH4 - if (CPU_IS_SH4) +#if defined SH4 || defined SH4A + if (CPU_IS_SH4 || CPU_IS_SH4A) memcpy(VBR + 0x400, sh4_vector_tlbmiss, sh4_vector_tlbmiss_end - sh4_vector_tlbmiss); #endif @@ -288,7 +299,7 @@ sh4_vector_tlbmiss_end - sh4_vector_tlbmiss #elif defined(SH3) sh3_vector_tlbmiss_end - sh3_vector_tlbmiss -#elif defined(SH4) +#elif defined(SH4) || defined (SH4A) sh4_vector_tlbmiss_end - sh4_vector_tlbmiss #endif ); @@ -307,6 +318,9 @@ phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, VM_PHYS_SIZE, 0, false, NULL); + mb_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, + nmbclusters * mclbytes, VM_MAP_INTRSAFE, false, NULL); + format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free)); printf("avail memory = %s\n", pbuf); } diff --exclude=CVS --exclude=obj.evbsh3 --exclude=compile --exclude='makeBuild*.log' -uNr src.orig/sys/arch/sh3/sh3/vm_machdep.c src-sh4a.orig/sys/arch/sh3/sh3/vm_machdep.c --- src.orig/sys/arch/sh3/sh3/vm_machdep.c 2011-02-14 08:46:13.000000000 +0900 +++ src-sh4a.orig/sys/arch/sh3/sh3/vm_machdep.c 2011-02-14 08:47:58.000000000 +0900 @@ -222,9 +222,9 @@ sh_dcache_wbinv_range(uv, USPACE); spbase = P1ADDR(spbase); #else /* !P1_STACK */ -#ifdef SH4 +#if defined SH4 || defined SH4A /* Prepare u-area PTEs */ - if (CPU_IS_SH4) + if (CPU_IS_SH4 || CPU_IS_SH4A) sh4_switch_setup(l); #endif #endif /* !P1_STACK */ @@ -357,7 +357,9 @@ upmap = vm_map_pmap(&bp->b_proc->p_vmspace->vm_map); kpmap = vm_map_pmap(phys_map); while (len) { - pmap_extract(upmap, faddr, &fpa); + if (!pmap_extract(upmap, faddr, &fpa)) { + panic("vmapbuf pmap_extract failed."); + } pmap_enter(kpmap, taddr, fpa, VM_PROT_READ | VM_PROT_WRITE, PMAP_WIRED); faddr += PAGE_SIZE; diff --exclude=CVS --exclude=obj.evbsh3 --exclude=compile --exclude='makeBuild*.log' -uNr src.orig/sys/uvm/uvm_km.c src-sh4a.orig/sys/uvm/uvm_km.c --- src.orig/sys/uvm/uvm_km.c 2011-02-05 00:10:01.000000000 +0900 +++ src-sh4a.orig/sys/uvm/uvm_km.c 2011-02-05 00:11:35.000000000 +0900 @@ -529,6 +529,13 @@ struct uvm_object *obj; int pgaflags; vm_prot_t prot; + if (!map) { + uint32_t r; + __asm volatile ("sts pr, %0" : "=r"(r)); + printf ("PR=%x\n", r); + assert (0); + } + UVMHIST_FUNC(__func__); UVMHIST_CALLED(maphist); KASSERT(vm_map_pmap(map) == pmap_kernel()); @@ -594,6 +601,10 @@ while (loopsize) { KASSERT(!pmap_extract(pmap_kernel(), loopva, NULL)); +#ifdef SH4A_EXT_ADDR32 + pg = uvm_pagealloc_strat(NULL, offset, NULL, pgaflags, + UVM_PGA_STRAT_ONLY, VM_FREELIST_P1ACCESS); +#else pg = uvm_pagealloc_strat(NULL, offset, NULL, pgaflags, #ifdef UVM_KM_VMFREELIST UVM_PGA_STRAT_ONLY, UVM_KM_VMFREELIST @@ -602,6 +613,7 @@ #endif ); +#endif /* * out of memory? */ @@ -692,6 +704,7 @@ struct vm_page *pg; struct pool *pp = &vm_map_to_kernel(map)->vmk_vacache; vaddr_t va; + assert(map); if ((map->flags & VM_MAP_VACACHE) == 0) return uvm_km_alloc_poolpage(map, waitok); @@ -701,7 +714,12 @@ return 0; KASSERT(!pmap_extract(pmap_kernel(), va, NULL)); again: +#ifdef SH4A_EXT_ADDR32 + pg = uvm_pagealloc_strat(NULL, 0, NULL, waitok ? 0 : UVM_PGA_USERESERVE, + UVM_PGA_STRAT_ONLY, VM_FREELIST_P1ACCESS); +#else pg = uvm_pagealloc(NULL, 0, NULL, waitok ? 0 : UVM_PGA_USERESERVE); +#endif if (__predict_false(pg == NULL)) { if (waitok) { uvm_wait("plpg"); @@ -722,17 +740,26 @@ vaddr_t uvm_km_alloc_poolpage(struct vm_map *map, bool waitok) { + uint32_t r; + __asm volatile ("sts pr, %0" : "=r"(r)); + // printf ("PR=%x\n", r); + #if defined(PMAP_MAP_POOLPAGE) struct vm_page *pg; vaddr_t va; again: +#ifdef SH4A_EXT_ADDR32 + pg = uvm_pagealloc_strat(NULL, 0, NULL, waitok ? 0 : UVM_PGA_USERESERVE, + UVM_PGA_STRAT_ONLY, VM_FREELIST_P1ACCESS); +#else #ifdef PMAP_ALLOC_POOLPAGE pg = PMAP_ALLOC_POOLPAGE(waitok ? 0 : UVM_PGA_USERESERVE); #else pg = uvm_pagealloc(NULL, 0, NULL, waitok ? 0 : UVM_PGA_USERESERVE); #endif +#endif if (__predict_false(pg == NULL)) { if (waitok) { uvm_wait("plpg"); diff --exclude=CVS --exclude=obj.evbsh3 --exclude=compile --exclude='makeBuild*.log' -uNr src.orig/sys/uvm/uvm_map.c src-sh4a.orig/sys/uvm/uvm_map.c --- src.orig/sys/uvm/uvm_map.c 2011-04-15 22:03:17.000000000 +0900 +++ src-sh4a.orig/sys/uvm/uvm_map.c 2011-04-15 22:05:13.000000000 +0900 @@ -4720,8 +4720,14 @@ * for simplicity, always allocate one page chunk of them at once. */ +#ifdef SH4A_EXT_ADDR32 + pg = uvm_pagealloc_strat(NULL, 0, NULL, + (flags & UVM_KMF_NOWAIT) != 0 ? UVM_PGA_USERESERVE : 0, + UVM_PGA_STRAT_ONLY, VM_FREELIST_P1ACCESS); +#else pg = uvm_pagealloc(NULL, 0, NULL, (flags & UVM_KMF_NOWAIT) != 0 ? UVM_PGA_USERESERVE : 0); +#endif if (__predict_false(pg == NULL)) { if (flags & UVM_FLAG_NOWAIT) return NULL; @@ -4746,6 +4752,8 @@ VM_PROT_READ|VM_PROT_WRITE, PMAP_KMPAGE); pmap_update(vm_map_pmap(map)); +// void sh4a_mmu_dump (void); +// sh4a_mmu_dump (); #endif ukh = (void *)va;