From 191578f645ae4653ab5468715a748a9565b04069 Mon Sep 17 00:00:00 2001 From: Andrzej Flis Date: Thu, 27 Nov 2014 20:56:49 +0100 Subject: [PATCH] Initial commit - code buildable with rpi --- .settings | 8 + common/lib/libc/arch/arm/atomic/Makefile.inc | 1 - etc/Makefile | 2 +- .../binutils/lib/libbfd/arch/earmhf/config.h | 12 +- .../binutils/lib/libbfd/arch/earmhf/defs.mk | 7 +- .../lib/libiberty/arch/earmhf/config.h | 22 +- .../lib/libiberty/arch/earmhf/defs.mk | 2 +- .../lib/libopcodes/arch/earmhf/config.h | 2 +- .../usr.bin/common/arch/earmhf/config.h | 29 +- .../usr.bin/common/arch/earmhf/defs.mk | 24 +- .../binutils/usr.bin/gas/arch/earmhf/config.h | 27 +- .../usr.bin/gas/arch/earmhf/targ-env.h | 2 +- .../usr.bin/gprof/arch/earmhf/gconfig.h | 8 +- .../binutils/usr.bin/ld/arch/earmhf/config.h | 17 +- .../binutils/usr.bin/ld/arch/earmhf/defs.mk | 8 +- .../usr.bin/ld/arch/earmhf/ldemul-list.h | 8 +- .../gpl3/gcc/lib/crtstuff/arch/earmv6hf.mk | 5 +- external/gpl3/gcc/lib/libgcc/Makefile | 2 +- external/gpl3/gcc/lib/libgcc/arch/earmv6hf.mk | 5 +- .../gcc/lib/libgomp/arch/earmv6hf/config.h | 2 +- .../gcc/lib/libiberty/arch/earmv6hf/config.h | 6 +- .../gcc/lib/libobjc/arch/earmv6hf/config.h | 2 +- .../gcc/lib/libobjc/arch/earmv6hf/defs.mk | 7 +- .../libstdc++-v3/arch/earmv6hf/c++config.h | 14 +- .../lib/libstdc++-v3/arch/earmv6hf/config.h | 12 +- .../lib/libstdc++-v3/arch/earmv6hf/defs.mk | 17 +- .../gcc/usr.bin/gcc/arch/earmv6/auto-host.h | 16 +- .../gcc/usr.bin/gcc/arch/earmv6hf/auto-host.h | 16 +- .../usr.bin/gcc/arch/earmv6hf/configargs.h | 6 +- .../gcc/usr.bin/gcc/arch/earmv6hf/defs.mk | 12 +- .../usr.bin/gcc/arch/earmv6hf/gtyp-input.list | 10 +- .../gcc/usr.bin/gcc/arch/earmv6hf/multilib.h | 16 +- .../gpl3/gcc/usr.bin/gcc/arch/earmv6hf/tm.h | 18 +- .../gcc/usr.bin/libcpp/arch/earmv6hf/config.h | 2 +- lib/Makefile | 4 +- lib/libc/arch/arm/Makefile.inc | 2 +- minix/drivers/bus/Makefile | 2 +- .../bus/i2c/arch/earmv6hf/Makefile.inc | 7 + .../drivers/bus/i2c/arch/earmv6hf/omap_i2c.c | 876 +++++++++++++++++ .../drivers/bus/i2c/arch/earmv6hf/omap_i2c.h | 10 + .../i2c/arch/earmv6hf/omap_i2c_registers.h | 152 +++ .../readclock/arch/earmv6hf/Makefile.inc | 10 + .../readclock/arch/earmv6hf/arch_readclock.c | 45 + .../clock/readclock/arch/earmv6hf/omap_rtc.c | 419 ++++++++ .../clock/readclock/arch/earmv6hf/omap_rtc.h | 94 ++ minix/drivers/eeprom/Makefile | 2 +- minix/drivers/net/Makefile | 2 +- minix/drivers/power/Makefile | 2 +- minix/drivers/sensors/Makefile | 2 +- minix/drivers/storage/mmc/Makefile | 2 +- minix/drivers/storage/ramdisk/Makefile | 2 +- minix/drivers/system/Makefile | 2 +- .../tty/tty/arch/earmv6hf/Makefile.inc | 7 + minix/drivers/tty/tty/arch/earmv6hf/console.c | 30 + .../drivers/tty/tty/arch/earmv6hf/keyboard.c | 30 + .../tty/tty/arch/earmv6hf/omap_serial.h | 107 +++ minix/drivers/tty/tty/arch/earmv6hf/rs232.c | 848 +++++++++++++++++ minix/drivers/usb/Makefile | 2 +- minix/drivers/usb/usbd/Makefile | 2 +- minix/drivers/video/Makefile | 2 +- .../video/fb/arch/earmv6hf/Makefile.inc | 7 + minix/drivers/video/fb/arch/earmv6hf/dss.h | 65 ++ .../drivers/video/fb/arch/earmv6hf/fb_arch.c | 408 ++++++++ minix/include/arch/earmv6hf/Makefile | 4 + minix/include/arch/earmv6hf/include/Makefile | 8 + .../include/arch/earmv6hf/include/archconst.h | 6 + .../include/arch/earmv6hf/include/archtypes.h | 27 + .../include/arch/earmv6hf/include/diskparm.h | 20 + minix/include/arch/earmv6hf/include/elf.h | 42 + .../include/arch/earmv6hf/include/interrupt.h | 8 + .../include/arch/earmv6hf/include/ipcconst.h | 9 + minix/include/arch/earmv6hf/include/memory.h | 10 + .../include/arch/earmv6hf/include/multiboot.h | 351 +++++++ .../include/arch/earmv6hf/include/partition.h | 28 + .../arch/earmv6hf/include/stackframe.h | 28 + minix/include/arch/earmv6hf/include/vm.h | 196 ++++ minix/kernel/arch/earmv6hf/Makefile.inc | 98 ++ minix/kernel/arch/earmv6hf/arch_clock.c | 141 +++ minix/kernel/arch/earmv6hf/arch_do_vmctl.c | 56 ++ minix/kernel/arch/earmv6hf/arch_reset.c | 82 ++ minix/kernel/arch/earmv6hf/arch_system.c | 218 +++++ .../arch/earmv6hf/bsp/include/bsp_init.h | 7 + .../arch/earmv6hf/bsp/include/bsp_intr.h | 12 + .../arch/earmv6hf/bsp/include/bsp_padconf.h | 11 + .../arch/earmv6hf/bsp/include/bsp_reset.h | 9 + .../arch/earmv6hf/bsp/include/bsp_serial.h | 6 + .../arch/earmv6hf/bsp/include/bsp_timer.h | 13 + .../kernel/arch/earmv6hf/bsp/ti/Makefile.inc | 13 + minix/kernel/arch/earmv6hf/bsp/ti/omap_init.c | 21 + minix/kernel/arch/earmv6hf/bsp/ti/omap_intr.c | 72 ++ .../earmv6hf/bsp/ti/omap_intr_registers.h | 236 +++++ .../arch/earmv6hf/bsp/ti/omap_padconf.c | 83 ++ .../kernel/arch/earmv6hf/bsp/ti/omap_reset.c | 100 ++ minix/kernel/arch/earmv6hf/bsp/ti/omap_rtc.c | 58 ++ minix/kernel/arch/earmv6hf/bsp/ti/omap_rtc.h | 7 + .../kernel/arch/earmv6hf/bsp/ti/omap_serial.c | 84 ++ .../kernel/arch/earmv6hf/bsp/ti/omap_serial.h | 27 + .../kernel/arch/earmv6hf/bsp/ti/omap_timer.c | 397 ++++++++ .../earmv6hf/bsp/ti/omap_timer_registers.h | 157 +++ minix/kernel/arch/earmv6hf/direct_tty_utils.c | 30 + minix/kernel/arch/earmv6hf/do_padconf.c | 18 + minix/kernel/arch/earmv6hf/exc.S | 22 + minix/kernel/arch/earmv6hf/exception.c | 232 +++++ minix/kernel/arch/earmv6hf/glo.h | 9 + minix/kernel/arch/earmv6hf/head.S | 54 ++ minix/kernel/arch/earmv6hf/hw_intr.c | 16 + .../kernel/arch/earmv6hf/include/arch_clock.h | 6 + .../kernel/arch/earmv6hf/include/arch_proto.h | 125 +++ .../arch/earmv6hf/include/arch_watchdog.h | 6 + .../kernel/arch/earmv6hf/include/archconst.h | 41 + minix/kernel/arch/earmv6hf/include/ccnt.h | 22 + minix/kernel/arch/earmv6hf/include/cpufunc.h | 463 +++++++++ .../arch/earmv6hf/include/direct_utils.h | 11 + minix/kernel/arch/earmv6hf/include/hw_intr.h | 15 + minix/kernel/arch/earmv6hf/include/io.h | 16 + minix/kernel/arch/earmv6hf/kernel.lds | 50 + minix/kernel/arch/earmv6hf/klib.S | 107 +++ minix/kernel/arch/earmv6hf/memory.c | 899 ++++++++++++++++++ minix/kernel/arch/earmv6hf/mpx.S | 289 ++++++ minix/kernel/arch/earmv6hf/pg_utils.c | 317 ++++++ minix/kernel/arch/earmv6hf/phys_copy.S | 397 ++++++++ minix/kernel/arch/earmv6hf/phys_memset.S | 274 ++++++ minix/kernel/arch/earmv6hf/pre_init.c | 426 +++++++++ minix/kernel/arch/earmv6hf/procoffsets.cf | 24 + minix/kernel/arch/earmv6hf/protect.c | 183 ++++ minix/kernel/arch/earmv6hf/sconst.h | 7 + minix/kernel/arch/earmv6hf/timer.h | 7 + minix/lib/Makefile | 2 +- .../libminc/arch/earmv6hf/Makefile.libc.inc | 99 ++ minix/lib/libsys/arch/earmv6hf/Makefile.inc | 15 + minix/lib/libsys/arch/earmv6hf/frclock_util.c | 92 ++ minix/lib/libsys/arch/earmv6hf/spin.c | 98 ++ minix/lib/libsys/arch/earmv6hf/tsc_util.c | 35 + minix/servers/vm/Makefile | 2 +- minix/servers/vm/arch/earmv6hf/Makefile.inc | 4 + minix/servers/vm/arch/earmv6hf/pagetable.h | 52 + minix/servers/vm/arch/earmv6hf/vm.lds | 249 +++++ minix/share/Makefile | 5 +- minix/share/rpi/Makefile | 4 + minix/share/rpi/Makefile.inc | 1 + minix/share/rpi/weather/LICENSE | 27 + minix/share/rpi/weather/Makefile | 14 + minix/share/rpi/weather/README.txt | 53 ++ minix/share/rpi/weather/index.html | 97 ++ minix/share/rpi/weather/jquery.js | 6 + minix/share/rpi/weather/processing.js | 13 + minix/share/rpi/weather/spin.js | 355 +++++++ minix/share/rpi/weather/style.css | 17 + minix/share/rpi/weather/weatherstation.js | 302 ++++++ minix/share/rpi/weather/weatherstation.lua | 175 ++++ minix/usr.bin/Makefile | 2 +- releasetools/arm_sdimage.sh | 25 +- releasetools/fetch_u-boot.sh | 18 +- share/mk/bsd.lib.mk | 2 +- share/mk/bsd.own.mk | 2 +- share/mk/bsd.prog.mk | 2 +- share/mk/minix.service.mk | 2 +- 157 files changed, 11736 insertions(+), 235 deletions(-) create mode 100644 .settings create mode 100644 minix/drivers/bus/i2c/arch/earmv6hf/Makefile.inc create mode 100644 minix/drivers/bus/i2c/arch/earmv6hf/omap_i2c.c create mode 100644 minix/drivers/bus/i2c/arch/earmv6hf/omap_i2c.h create mode 100644 minix/drivers/bus/i2c/arch/earmv6hf/omap_i2c_registers.h create mode 100644 minix/drivers/clock/readclock/arch/earmv6hf/Makefile.inc create mode 100644 minix/drivers/clock/readclock/arch/earmv6hf/arch_readclock.c create mode 100644 minix/drivers/clock/readclock/arch/earmv6hf/omap_rtc.c create mode 100644 minix/drivers/clock/readclock/arch/earmv6hf/omap_rtc.h create mode 100644 minix/drivers/tty/tty/arch/earmv6hf/Makefile.inc create mode 100644 minix/drivers/tty/tty/arch/earmv6hf/console.c create mode 100644 minix/drivers/tty/tty/arch/earmv6hf/keyboard.c create mode 100644 minix/drivers/tty/tty/arch/earmv6hf/omap_serial.h create mode 100644 minix/drivers/tty/tty/arch/earmv6hf/rs232.c create mode 100644 minix/drivers/video/fb/arch/earmv6hf/Makefile.inc create mode 100644 minix/drivers/video/fb/arch/earmv6hf/dss.h create mode 100644 minix/drivers/video/fb/arch/earmv6hf/fb_arch.c create mode 100644 minix/include/arch/earmv6hf/Makefile create mode 100644 minix/include/arch/earmv6hf/include/Makefile create mode 100644 minix/include/arch/earmv6hf/include/archconst.h create mode 100644 minix/include/arch/earmv6hf/include/archtypes.h create mode 100644 minix/include/arch/earmv6hf/include/diskparm.h create mode 100644 minix/include/arch/earmv6hf/include/elf.h create mode 100644 minix/include/arch/earmv6hf/include/interrupt.h create mode 100644 minix/include/arch/earmv6hf/include/ipcconst.h create mode 100644 minix/include/arch/earmv6hf/include/memory.h create mode 100644 minix/include/arch/earmv6hf/include/multiboot.h create mode 100644 minix/include/arch/earmv6hf/include/partition.h create mode 100644 minix/include/arch/earmv6hf/include/stackframe.h create mode 100644 minix/include/arch/earmv6hf/include/vm.h create mode 100644 minix/kernel/arch/earmv6hf/Makefile.inc create mode 100644 minix/kernel/arch/earmv6hf/arch_clock.c create mode 100644 minix/kernel/arch/earmv6hf/arch_do_vmctl.c create mode 100644 minix/kernel/arch/earmv6hf/arch_reset.c create mode 100644 minix/kernel/arch/earmv6hf/arch_system.c create mode 100644 minix/kernel/arch/earmv6hf/bsp/include/bsp_init.h create mode 100644 minix/kernel/arch/earmv6hf/bsp/include/bsp_intr.h create mode 100644 minix/kernel/arch/earmv6hf/bsp/include/bsp_padconf.h create mode 100644 minix/kernel/arch/earmv6hf/bsp/include/bsp_reset.h create mode 100644 minix/kernel/arch/earmv6hf/bsp/include/bsp_serial.h create mode 100644 minix/kernel/arch/earmv6hf/bsp/include/bsp_timer.h create mode 100644 minix/kernel/arch/earmv6hf/bsp/ti/Makefile.inc create mode 100644 minix/kernel/arch/earmv6hf/bsp/ti/omap_init.c create mode 100644 minix/kernel/arch/earmv6hf/bsp/ti/omap_intr.c create mode 100644 minix/kernel/arch/earmv6hf/bsp/ti/omap_intr_registers.h create mode 100644 minix/kernel/arch/earmv6hf/bsp/ti/omap_padconf.c create mode 100644 minix/kernel/arch/earmv6hf/bsp/ti/omap_reset.c create mode 100644 minix/kernel/arch/earmv6hf/bsp/ti/omap_rtc.c create mode 100644 minix/kernel/arch/earmv6hf/bsp/ti/omap_rtc.h create mode 100644 minix/kernel/arch/earmv6hf/bsp/ti/omap_serial.c create mode 100644 minix/kernel/arch/earmv6hf/bsp/ti/omap_serial.h create mode 100644 minix/kernel/arch/earmv6hf/bsp/ti/omap_timer.c create mode 100644 minix/kernel/arch/earmv6hf/bsp/ti/omap_timer_registers.h create mode 100644 minix/kernel/arch/earmv6hf/direct_tty_utils.c create mode 100644 minix/kernel/arch/earmv6hf/do_padconf.c create mode 100644 minix/kernel/arch/earmv6hf/exc.S create mode 100644 minix/kernel/arch/earmv6hf/exception.c create mode 100644 minix/kernel/arch/earmv6hf/glo.h create mode 100644 minix/kernel/arch/earmv6hf/head.S create mode 100644 minix/kernel/arch/earmv6hf/hw_intr.c create mode 100644 minix/kernel/arch/earmv6hf/include/arch_clock.h create mode 100644 minix/kernel/arch/earmv6hf/include/arch_proto.h create mode 100644 minix/kernel/arch/earmv6hf/include/arch_watchdog.h create mode 100644 minix/kernel/arch/earmv6hf/include/archconst.h create mode 100644 minix/kernel/arch/earmv6hf/include/ccnt.h create mode 100644 minix/kernel/arch/earmv6hf/include/cpufunc.h create mode 100644 minix/kernel/arch/earmv6hf/include/direct_utils.h create mode 100644 minix/kernel/arch/earmv6hf/include/hw_intr.h create mode 100644 minix/kernel/arch/earmv6hf/include/io.h create mode 100644 minix/kernel/arch/earmv6hf/kernel.lds create mode 100644 minix/kernel/arch/earmv6hf/klib.S create mode 100644 minix/kernel/arch/earmv6hf/memory.c create mode 100644 minix/kernel/arch/earmv6hf/mpx.S create mode 100644 minix/kernel/arch/earmv6hf/pg_utils.c create mode 100644 minix/kernel/arch/earmv6hf/phys_copy.S create mode 100644 minix/kernel/arch/earmv6hf/phys_memset.S create mode 100644 minix/kernel/arch/earmv6hf/pre_init.c create mode 100644 minix/kernel/arch/earmv6hf/procoffsets.cf create mode 100644 minix/kernel/arch/earmv6hf/protect.c create mode 100644 minix/kernel/arch/earmv6hf/sconst.h create mode 100644 minix/kernel/arch/earmv6hf/timer.h create mode 100644 minix/lib/libminc/arch/earmv6hf/Makefile.libc.inc create mode 100644 minix/lib/libsys/arch/earmv6hf/Makefile.inc create mode 100644 minix/lib/libsys/arch/earmv6hf/frclock_util.c create mode 100644 minix/lib/libsys/arch/earmv6hf/spin.c create mode 100644 minix/lib/libsys/arch/earmv6hf/tsc_util.c create mode 100644 minix/servers/vm/arch/earmv6hf/Makefile.inc create mode 100644 minix/servers/vm/arch/earmv6hf/pagetable.h create mode 100644 minix/servers/vm/arch/earmv6hf/vm.lds create mode 100644 minix/share/rpi/Makefile create mode 100644 minix/share/rpi/Makefile.inc create mode 100644 minix/share/rpi/weather/LICENSE create mode 100644 minix/share/rpi/weather/Makefile create mode 100644 minix/share/rpi/weather/README.txt create mode 100644 minix/share/rpi/weather/index.html create mode 100644 minix/share/rpi/weather/jquery.js create mode 100644 minix/share/rpi/weather/processing.js create mode 100644 minix/share/rpi/weather/spin.js create mode 100644 minix/share/rpi/weather/style.css create mode 100644 minix/share/rpi/weather/weatherstation.js create mode 100755 minix/share/rpi/weather/weatherstation.lua diff --git a/.settings b/.settings new file mode 100644 index 000000000..afd9f29c9 --- /dev/null +++ b/.settings @@ -0,0 +1,8 @@ +# raspberry-pi +U_BOOT_BIN_DIR=build/rpi_b +CONSOLE=tty02 +U_BOOT_SOURCE=git://git.denx.de/u-boot-arm +U_BOOT_BRANCH=master +U_BOOT_GIT_VERSION=85bafb6da4dddfffa78479aa49a72ae48578a4ce +ARCH=evbearmv6hf-el +#ARCH=evbearm-el diff --git a/common/lib/libc/arch/arm/atomic/Makefile.inc b/common/lib/libc/arch/arm/atomic/Makefile.inc index ba9044e38..495a5e525 100644 --- a/common/lib/libc/arch/arm/atomic/Makefile.inc +++ b/common/lib/libc/arch/arm/atomic/Makefile.inc @@ -9,7 +9,6 @@ ARMV7+= ${CPPFLAGS:M-march=armv7*:} ${CPPFLAGS:M-mcpu=cortex*} .if empty(CFLAGS:M-march=*) && empty(CFLAGS:M-mcpu=*) \ && empty(CPPFLAGS:M-march=*) && empty(CPPFLAGS:M-mcpu=*) \ && empty(CPUFLAGS:M-march=*) && empty(CPUFLAGS:M-mcpu=*) -ARMV6+= ${MACHINE_ARCH:Mearmv6*} ARMV7+= ${MACHINE_ARCH:Mearmv7*} .endif diff --git a/etc/Makefile b/etc/Makefile index a4b4a47f3..8e52b03e8 100644 --- a/etc/Makefile +++ b/etc/Makefile @@ -445,7 +445,7 @@ install-etc-files-safe: .PHONY .MAKE check_DESTDIR MAKEDEV fi; \ ${INSTALL_FILE} -o ${owner} -g ${group} -m ${mode} ${sdir}${files} ${tdir}; .endfor -.if ${MACHINE_ARCH} == "earm" +.if ((${MACHINE_ARCH} == "earm") || (${MACHINE_ARCH} == "earmv6hf")) ${_MKMSG_INSTALL} ${DESTDIR}/etc/rc.capes ${INSTALL_DIR} ${DESTDIR}/etc/rc.capes ${INSTALL_FILE} -m ${BINMODE} -o ${BINOWN} -g ${BINGRP} ${NETBSDSRCDIR}/etc/rc.capes/* ${DESTDIR}/etc/rc.capes diff --git a/external/gpl3/binutils/lib/libbfd/arch/earmhf/config.h b/external/gpl3/binutils/lib/libbfd/arch/earmhf/config.h index 0927064f9..55f08a841 100644 --- a/external/gpl3/binutils/lib/libbfd/arch/earmhf/config.h +++ b/external/gpl3/binutils/lib/libbfd/arch/earmhf/config.h @@ -17,7 +17,7 @@ /* Define to 1 if translation of program messages to the user's native language is requested. */ -#define ENABLE_NLS 1 +/* #undef ENABLE_NLS */ /* Define to 1 if you have the header file. */ /* #undef HAVE_ALLOCA_H */ @@ -139,7 +139,7 @@ /* #undef HAVE_LWPXSTATUS_T */ /* Define to 1 if you have the `madvise' function. */ -#define HAVE_MADVISE 1 +/* #undef HAVE_MADVISE */ /* Define to 1 if you have the header file. */ #define HAVE_MEMORY_H 1 @@ -148,7 +148,7 @@ #define HAVE_MMAP 1 /* Define to 1 if you have the `mprotect' function. */ -#define HAVE_MPROTECT 1 +/* #undef HAVE_MPROTECT */ /* Define to 1 if you have the header file, and it defines `DIR'. */ /* #undef HAVE_NDIR_H */ @@ -368,11 +368,11 @@ /* #undef _LARGE_FILES */ /* Define to 1 if on MINIX. */ -/* #undef _MINIX */ +#define _MINIX 1 /* Define to 2 if the system does not provide POSIX.1 features except with this defined. */ -/* #undef _POSIX_1_SOURCE */ +#define _POSIX_1_SOURCE 2 /* Define to 1 if you need to in order for `stat' and other things to work. */ -/* #undef _POSIX_SOURCE */ +#define _POSIX_SOURCE 1 diff --git a/external/gpl3/binutils/lib/libbfd/arch/earmhf/defs.mk b/external/gpl3/binutils/lib/libbfd/arch/earmhf/defs.mk index 2b158e406..33d84221b 100644 --- a/external/gpl3/binutils/lib/libbfd/arch/earmhf/defs.mk +++ b/external/gpl3/binutils/lib/libbfd/arch/earmhf/defs.mk @@ -2,8 +2,9 @@ # Generated from: NetBSD: mknative-binutils,v 1.8 2011/09/25 04:00:58 christos Exp # Generated from: NetBSD: mknative.common,v 1.9 2007/02/05 18:26:01 apb Exp # -G_libbfd_la_DEPENDENCIES=elf32-arm.lo elf32.lo elf-nacl.lo elf-vxworks.lo elf.lo elflink.lo elf-attrs.lo elf-strtab.lo elf-eh-frame.lo dwarf1.lo armnetbsd.lo aout32.lo coff-arm.lo cofflink.lo elf32-gen.lo cpu-arm.lo netbsd-core.lo ofiles +G_libbfd_la_DEPENDENCIES=elf32-arm.lo elf32.lo elf-nacl.lo elf-vxworks.lo elf.lo elflink.lo elf-attrs.lo elf-strtab.lo elf-eh-frame.lo dwarf1.lo elf32-gen.lo cpu-arm.lo archive64.lo ofiles G_libbfd_la_OBJECTS=archive.lo archures.lo bfd.lo bfdio.lo bfdwin.lo cache.lo coffgen.lo corefile.lo format.lo init.lo libbfd.lo opncls.lo reloc.lo section.lo syms.lo targets.lo hash.lo linker.lo srec.lo binary.lo tekhex.lo ihex.lo stabs.lo stab-syms.lo merge.lo dwarf2.lo simple.lo compress.lo verilog.lo G_DEFS=-DHAVE_CONFIG_H -G_INCLUDES=-DNETBSD_CORE -I. -I${GNUHOSTDIST}/bfd -I${GNUHOSTDIST}/bfd/../include -DHAVE_bfd_elf32_littlearm_vec -DHAVE_bfd_elf32_bigarm_vec -DHAVE_armnetbsd_vec -DHAVE_armcoff_little_vec -DHAVE_armcoff_big_vec -DHAVE_bfd_elf32_little_generic_vec -DHAVE_bfd_elf32_big_generic_vec -I./../intl -G_TDEFAULTS=-DDEFAULT_VECTOR=bfd_elf32_littlearm_vec -DSELECT_VECS='&bfd_elf32_littlearm_vec,&bfd_elf32_bigarm_vec,&armnetbsd_vec,&armcoff_little_vec,&armcoff_big_vec,&bfd_elf32_little_generic_vec,&bfd_elf32_big_generic_vec' -DSELECT_ARCHITECTURES='&bfd_arm_arch' +G_INCLUDES=-I. -I${GNUHOSTDIST}/bfd -I${GNUHOSTDIST}/bfd/../include -DHAVE_bfd_elf32_littlearm_vec -DHAVE_bfd_elf32_bigarm_vec -DHAVE_bfd_elf32_little_generic_vec -DHAVE_bfd_elf32_big_generic_vec +G_TDEFAULTS=-DDEFAULT_VECTOR=bfd_elf32_littlearm_vec -DSELECT_VECS='&bfd_elf32_littlearm_vec,&bfd_elf32_bigarm_vec,&bfd_elf32_little_generic_vec,&bfd_elf32_big_generic_vec' -DSELECT_ARCHITECTURES='&bfd_arm_arch' + diff --git a/external/gpl3/binutils/lib/libiberty/arch/earmhf/config.h b/external/gpl3/binutils/lib/libiberty/arch/earmhf/config.h index ca7c59dcc..bd9a7175d 100644 --- a/external/gpl3/binutils/lib/libiberty/arch/earmhf/config.h +++ b/external/gpl3/binutils/lib/libiberty/arch/earmhf/config.h @@ -97,7 +97,7 @@ #define HAVE_DECL_VSNPRINTF 1 /* Define to 1 if you have the `dup3' function. */ -#define HAVE_DUP3 1 +/* #undef HAVE_DUP3 */ /* Define to 1 if you have the header file. */ #define HAVE_FCNTL_H 1 @@ -118,7 +118,7 @@ #define HAVE_GETRLIMIT 1 /* Define to 1 if you have the `getrusage' function. */ -#define HAVE_GETRUSAGE 1 +/* #undef HAVE_GETRUSAGE */ /* Define to 1 if you have the `getsysinfo' function. */ /* #undef HAVE_GETSYSINFO */ @@ -211,13 +211,13 @@ #define HAVE_SETENV 1 /* Define to 1 if you have the `setproctitle' function. */ -#define HAVE_SETPROCTITLE 1 +/* #undef HAVE_SETPROCTITLE */ /* Define to 1 if you have the `setrlimit' function. */ -#define HAVE_SETRLIMIT 1 +/* #undef HAVE_SETRLIMIT */ /* Define to 1 if you have the `sigsetmask' function. */ -#define HAVE_SIGSETMASK 1 +/* #undef HAVE_SIGSETMASK */ /* Define to 1 if you have the `snprintf' function. */ #define HAVE_SNPRINTF 1 @@ -292,13 +292,13 @@ #define HAVE_SYSCONF 1 /* Define to 1 if you have the `sysctl' function. */ -#define HAVE_SYSCTL 1 +/* #undef HAVE_SYSCTL */ /* Define to 1 if you have the `sysmp' function. */ /* #undef HAVE_SYSMP */ /* Define if you have the sys_errlist variable. */ -#define HAVE_SYS_ERRLIST 1 +/* #undef HAVE_SYS_ERRLIST */ /* Define to 1 if you have the header file. */ #define HAVE_SYS_FILE_H 1 @@ -307,7 +307,7 @@ #define HAVE_SYS_MMAN_H 1 /* Define if you have the sys_nerr variable. */ -#define HAVE_SYS_NERR 1 +/* #undef HAVE_SYS_NERR */ /* Define to 1 if you have the header file. */ #define HAVE_SYS_PARAM_H 1 @@ -322,7 +322,7 @@ #define HAVE_SYS_RESOURCE_H 1 /* Define if you have the sys_siglist variable. */ -#define HAVE_SYS_SIGLIST 1 +/* #undef HAVE_SYS_SIGLIST */ /* Define to 1 if you have the header file. */ #define HAVE_SYS_STAT_H 1 @@ -388,10 +388,10 @@ #define HAVE_VSPRINTF 1 /* Define to 1 if you have the `wait3' function. */ -#define HAVE_WAIT3 1 +/* #undef HAVE_WAIT3 */ /* Define to 1 if you have the `wait4' function. */ -#define HAVE_WAIT4 1 +/* #undef HAVE_WAIT4 */ /* Define to 1 if you have the `waitpid' function. */ #define HAVE_WAITPID 1 diff --git a/external/gpl3/binutils/lib/libiberty/arch/earmhf/defs.mk b/external/gpl3/binutils/lib/libiberty/arch/earmhf/defs.mk index 613d0e3a9..bda8a0d8c 100644 --- a/external/gpl3/binutils/lib/libiberty/arch/earmhf/defs.mk +++ b/external/gpl3/binutils/lib/libiberty/arch/earmhf/defs.mk @@ -4,5 +4,5 @@ # G_ALLOCA= G_EXTRA_OFILES= -G_LIBOBJS=mempcpy.o mkstemps.o strverscmp.o +G_LIBOBJS=mempcpy.o mkstemps.o strverscmp.o strncmp.o G_REQUIRED_OFILES=regex.o cplus-dem.o cp-demangle.o md5.o sha1.o alloca.o argv.o choose-temp.o concat.o cp-demint.o crc32.o dwarfnames.o dyn-string.o fdmatch.o fibheap.o filename_cmp.o floatformat.o fnmatch.o fopen_unlocked.o getopt.o getopt1.o getpwd.o getruntime.o hashtab.o hex.o lbasename.o lrealpath.o make-relative-prefix.o make-temp-file.o objalloc.o obstack.o partition.o pexecute.o physmem.o pex-common.o pex-one.o pex-unix.o safe-ctype.o simple-object.o simple-object-coff.o simple-object-elf.o simple-object-mach-o.o sort.o spaces.o splay-tree.o stack-limit.o strerror.o strsignal.o timeval-utils.o unlink-if-ordinary.o xatexit.o xexit.o xmalloc.o xmemdup.o xstrdup.o xstrerror.o xstrndup.o diff --git a/external/gpl3/binutils/lib/libopcodes/arch/earmhf/config.h b/external/gpl3/binutils/lib/libopcodes/arch/earmhf/config.h index beb23fa93..cc97fca9d 100644 --- a/external/gpl3/binutils/lib/libopcodes/arch/earmhf/config.h +++ b/external/gpl3/binutils/lib/libopcodes/arch/earmhf/config.h @@ -14,7 +14,7 @@ /* Define to 1 if translation of program messages to the user's native language is requested. */ -#define ENABLE_NLS 1 +/* #undef ENABLE_NLS */ /* Define to 1 if you have the declaration of `basename', and to 0 if you don't. */ diff --git a/external/gpl3/binutils/usr.bin/common/arch/earmhf/config.h b/external/gpl3/binutils/usr.bin/common/arch/earmhf/config.h index ee219d291..99c96dacb 100644 --- a/external/gpl3/binutils/usr.bin/common/arch/earmhf/config.h +++ b/external/gpl3/binutils/usr.bin/common/arch/earmhf/config.h @@ -25,13 +25,13 @@ /* Define to 1 if translation of program messages to the user's native language is requested. */ -#define ENABLE_NLS 1 +/* #undef ENABLE_NLS */ /* Suffix used for executables, if any. */ #define EXECUTABLE_SUFFIX "" /* Define to 1 if you have `alloca', as a function or macro. */ -#define HAVE_ALLOCA 1 +/* #undef HAVE_ALLOCA */ /* Define to 1 if you have and it should be used (not on Ultrix). */ @@ -97,18 +97,9 @@ /* Define to 1 if you have the header file. */ #define HAVE_INTTYPES_H 1 -/* Define if your file defines LC_MESSAGES. */ -#define HAVE_LC_MESSAGES 1 - /* Define to 1 if you have the header file. */ #define HAVE_LIMITS_H 1 -/* Define to 1 if you have the header file. */ -#define HAVE_LOCALE_H 1 - -/* Define if mbstate_t exists in wchar.h. */ -#define HAVE_MBSTATE_T 1 - /* Define to 1 if you have the header file. */ #define HAVE_MEMORY_H 1 @@ -121,9 +112,6 @@ /* Define to 1 if you have the `sbrk' function. */ #define HAVE_SBRK 1 -/* Define to 1 if you have the `setlocale' function. */ -#define HAVE_SETLOCALE 1 - /* Define to 1 if you have the `setmode' function. */ #define HAVE_SETMODE 1 @@ -167,10 +155,7 @@ #define HAVE_UNISTD_H 1 /* Define to 1 if you have the `utimes' function. */ -#define HAVE_UTIMES 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_WCHAR_H 1 +/* #undef HAVE_UTIMES */ /* Define to 1 if you have the header file. */ #define HAVE_ZLIB_H 1 @@ -218,7 +203,7 @@ #define STRING_WITH_STRINGS 1 /* Configured target name. */ -#define TARGET "arm--netbsdelf-eabihf" +#define TARGET "arm-elf32-minix" /* Define to 1 if user symbol names have a leading underscore, 0 if not. */ #define TARGET_PREPENDS_UNDERSCORE 0 @@ -262,11 +247,11 @@ /* #undef _LARGE_FILES */ /* Define to 1 if on MINIX. */ -/* #undef _MINIX */ +#define _MINIX 1 /* Define to 2 if the system does not provide POSIX.1 features except with this defined. */ -/* #undef _POSIX_1_SOURCE */ +#define _POSIX_1_SOURCE /* Define to 1 if you need to in order for `stat' and other things to work. */ -/* #undef _POSIX_SOURCE */ +#define _POSIX_SOURCE 1 diff --git a/external/gpl3/binutils/usr.bin/common/arch/earmhf/defs.mk b/external/gpl3/binutils/usr.bin/common/arch/earmhf/defs.mk index e7616a664..e76ae52c1 100644 --- a/external/gpl3/binutils/usr.bin/common/arch/earmhf/defs.mk +++ b/external/gpl3/binutils/usr.bin/common/arch/earmhf/defs.mk @@ -11,26 +11,26 @@ G_TEXINFOS=binutils.texi G_PKGVERSION=(NetBSD Binutils nb1) G_REPORT_BUGS_TEXI=@uref{http://www.NetBSD.org/support/send-pr.html} G_size_OBJECTS=size.o bucomm.o version.o filemode.o -G_size_DEPENDENCIES=./../intl/libintl.a ../libiberty/libiberty.a ../bfd/libbfd.la +G_size_DEPENDENCIES= ../libiberty/libiberty.a ../bfd/libbfd.la G_objdump_OBJECTS=objdump.o dwarf.o prdbg.o rddbg.o debug.o stabs.o ieee.o rdcoff.o bucomm.o version.o filemode.o elfcomm.o -G_objdump_DEPENDENCIES=./../intl/libintl.a ../libiberty/libiberty.a ../bfd/libbfd.la ../opcodes/libopcodes.la +G_objdump_DEPENDENCIES= ../libiberty/libiberty.a ../bfd/libbfd.la ../opcodes/libopcodes.la G_ar_OBJECTS=arparse.o arlex.o ar.o not-ranlib.o arsup.o rename.o binemul.o emul_vanilla.o bucomm.o version.o filemode.o -G_ar_DEPENDENCIES=./../intl/libintl.a ../libiberty/libiberty.a ../bfd/libbfd.la +G_ar_DEPENDENCIES= ../libiberty/libiberty.a ../bfd/libbfd.la G_strings_OBJECTS=strings.o bucomm.o version.o filemode.o -G_strings_DEPENDENCIES=./../intl/libintl.a ../libiberty/libiberty.a ../bfd/libbfd.la +G_strings_DEPENDENCIES= ../libiberty/libiberty.a ../bfd/libbfd.la G_ranlib_OBJECTS=ar.o is-ranlib.o arparse.o arlex.o arsup.o rename.o binemul.o emul_vanilla.o bucomm.o version.o filemode.o -G_ranlib_DEPENDENCIES=./../intl/libintl.a ../libiberty/libiberty.a ../bfd/libbfd.la +G_ranlib_DEPENDENCIES= ../libiberty/libiberty.a ../bfd/libbfd.la G_objcopy_OBJECTS=objcopy.o not-strip.o rename.o rddbg.o debug.o stabs.o ieee.o rdcoff.o wrstabs.o bucomm.o version.o filemode.o -G_objcopy_DEPENDENCIES=./../intl/libintl.a ../libiberty/libiberty.a ../bfd/libbfd.la +G_objcopy_DEPENDENCIES= ../libiberty/libiberty.a ../bfd/libbfd.la G_addr2line_OBJECTS=addr2line.o bucomm.o version.o filemode.o -G_addr2line_DEPENDENCIES=./../intl/libintl.a ../libiberty/libiberty.a ../bfd/libbfd.la +G_addr2line_DEPENDENCIES= ../libiberty/libiberty.a ../bfd/libbfd.la G_readelf_OBJECTS=readelf.o version.o unwind-ia64.o dwarf.o elfcomm.o -G_readelf_DEPENDENCIES=./../intl/libintl.a ../libiberty/libiberty.a +G_readelf_DEPENDENCIES= ../libiberty/libiberty.a G_elfedit_OBJECTS=elfedit.o version.o elfcomm.o -G_elfedit_DEPENDENCIES=./../intl/libintl.a ../libiberty/libiberty.a +G_elfedit_DEPENDENCIES= ../libiberty/libiberty.a G_nm_new_OBJECTS=nm.o bucomm.o version.o filemode.o -G_nm_new_DEPENDENCIES=./../intl/libintl.a ../libiberty/libiberty.a ../bfd/libbfd.la +G_nm_new_DEPENDENCIES= ../libiberty/libiberty.a ../bfd/libbfd.la G_strip_new_OBJECTS=objcopy.o is-strip.o rename.o rddbg.o debug.o stabs.o ieee.o rdcoff.o wrstabs.o bucomm.o version.o filemode.o -G_strip_new_DEPENDENCIES=./../intl/libintl.a ../libiberty/libiberty.a ../bfd/libbfd.la +G_strip_new_DEPENDENCIES= ../libiberty/libiberty.a ../bfd/libbfd.la G_cxxfilt_OBJECTS=cxxfilt.o bucomm.o version.o filemode.o -G_cxxfilt_DEPENDENCIES=./../intl/libintl.a ../libiberty/libiberty.a ../bfd/libbfd.la +G_cxxfilt_DEPENDENCIES= ../libiberty/libiberty.a ../bfd/libbfd.la diff --git a/external/gpl3/binutils/usr.bin/gas/arch/earmhf/config.h b/external/gpl3/binutils/usr.bin/gas/arch/earmhf/config.h index 1672cb51d..6081a5dfe 100644 --- a/external/gpl3/binutils/usr.bin/gas/arch/earmhf/config.h +++ b/external/gpl3/binutils/usr.bin/gas/arch/earmhf/config.h @@ -49,10 +49,10 @@ /* Define to 1 if translation of program messages to the user's native language is requested. */ -#define ENABLE_NLS 1 +/* #undef ENABLE_NLS */ /* Define to 1 if you have `alloca', as a function or macro. */ -#define HAVE_ALLOCA 1 +/* #undef HAVE_ALLOCA */ /* Define to 1 if you have and it should be used (not on Ultrix). */ @@ -102,15 +102,9 @@ /* Define to 1 if you have the header file. */ #define HAVE_INTTYPES_H 1 -/* Define if your file defines LC_MESSAGES. */ -#define HAVE_LC_MESSAGES 1 - /* Define to 1 if you have the header file. */ #define HAVE_LIMITS_H 1 -/* Define to 1 if you have the header file. */ -#define HAVE_LOCALE_H 1 - /* Define to 1 if you have the header file. */ #define HAVE_MEMORY_H 1 @@ -120,9 +114,6 @@ /* Define to 1 if you have the `sbrk' function. */ #define HAVE_SBRK 1 -/* Define to 1 if you have the `setlocale' function. */ -#define HAVE_SETLOCALE 1 - /* Define to 1 if you have the header file. */ #define HAVE_STDINT_H 1 @@ -268,19 +259,19 @@ #define STRING_WITH_STRINGS 1 /* Target alias. */ -#define TARGET_ALIAS "arm--netbsdelf-eabihf" +#define TARGET_ALIAS "arm-elf32-minix" /* Define as 1 if big endian. */ #define TARGET_BYTES_BIG_ENDIAN 0 /* Canonical target. */ -#define TARGET_CANONICAL "arm--netbsdelf-eabihf" +#define TARGET_CANONICAL "arm-elf32-minix" /* Target CPU. */ #define TARGET_CPU "arm" /* Target OS. */ -#define TARGET_OS "netbsdelf-eabihf" +#define TARGET_OS "minix" /* Define if default target is PowerPC Solaris. */ /* #undef TARGET_SOLARIS_COMMENT */ @@ -289,7 +280,7 @@ /* #undef TARGET_SYMBIAN */ /* Target vendor. */ -#define TARGET_VENDOR "" +#define TARGET_VENDOR "elf32" /* Use b modifier when opening binary files? */ /* #undef USE_BINARY_FOPEN */ @@ -351,14 +342,14 @@ /* #undef _LARGE_FILES */ /* Define to 1 if on MINIX. */ -/* #undef _MINIX */ +#define _MINIX 1 /* Define to 2 if the system does not provide POSIX.1 features except with this defined. */ -/* #undef _POSIX_1_SOURCE */ +#define _POSIX_1_SOURCE 2 /* Define to 1 if you need to in order for `stat' and other things to work. */ -/* #undef _POSIX_SOURCE */ +#define _POSIX_SOURCE 1 /* Define to `__inline__' or `__inline' if that's what the C compiler calls it, or to nothing if 'inline' is not supported under any name. */ diff --git a/external/gpl3/binutils/usr.bin/gas/arch/earmhf/targ-env.h b/external/gpl3/binutils/usr.bin/gas/arch/earmhf/targ-env.h index 75045d5bc..6411e55f0 100644 --- a/external/gpl3/binutils/usr.bin/gas/arch/earmhf/targ-env.h +++ b/external/gpl3/binutils/usr.bin/gas/arch/earmhf/targ-env.h @@ -2,4 +2,4 @@ /* Generated from: NetBSD: mknative-binutils,v 1.8 2011/09/25 04:00:58 christos Exp */ /* Generated from: NetBSD: mknative.common,v 1.9 2007/02/05 18:26:01 apb Exp */ -#include "te-armnbsdeabihf.h" +#include "te-armeabi.h" diff --git a/external/gpl3/binutils/usr.bin/gprof/arch/earmhf/gconfig.h b/external/gpl3/binutils/usr.bin/gprof/arch/earmhf/gconfig.h index 5711c7e4a..8bc2e3705 100644 --- a/external/gpl3/binutils/usr.bin/gprof/arch/earmhf/gconfig.h +++ b/external/gpl3/binutils/usr.bin/gprof/arch/earmhf/gconfig.h @@ -7,7 +7,7 @@ /* Define to 1 if translation of program messages to the user's native language is requested. */ -#define ENABLE_NLS 1 +/* #undef ENABLE_NLS */ /* Is the prototype for getopt in in the expected format? */ #define HAVE_DECL_GETOPT 1 @@ -108,11 +108,11 @@ /* #undef _LARGE_FILES */ /* Define to 1 if on MINIX. */ -/* #undef _MINIX */ +#define _MINIX 1 /* Define to 2 if the system does not provide POSIX.1 features except with this defined. */ -/* #undef _POSIX_1_SOURCE */ +#define _POSIX_1_SOURCE 2 /* Define to 1 if you need to in order for `stat' and other things to work. */ -/* #undef _POSIX_SOURCE */ +#define _POSIX_SOURCE 1 diff --git a/external/gpl3/binutils/usr.bin/ld/arch/earmhf/config.h b/external/gpl3/binutils/usr.bin/ld/arch/earmhf/config.h index ef2d2cafa..cf888dc23 100644 --- a/external/gpl3/binutils/usr.bin/ld/arch/earmhf/config.h +++ b/external/gpl3/binutils/usr.bin/ld/arch/earmhf/config.h @@ -14,7 +14,7 @@ /* Define to 1 if translation of program messages to the user's native language is requested. */ -#define ENABLE_NLS 1 +/* #undef ENABLE_NLS */ /* Additional extension a shared object might have. */ /* #undef EXTRA_SHLIB_EXTENSION */ @@ -79,15 +79,9 @@ /* Define to 1 if you have the header file. */ #define HAVE_INTTYPES_H 1 -/* Define if your file defines LC_MESSAGES. */ -#define HAVE_LC_MESSAGES 1 - /* Define to 1 if you have the header file. */ #define HAVE_LIMITS_H 1 -/* Define to 1 if you have the header file. */ -#define HAVE_LOCALE_H 1 - /* Define to 1 if you have the `lseek' function. */ #define HAVE_LSEEK 1 @@ -109,9 +103,6 @@ /* Define to 1 if you have the `sbrk' function. */ #define HAVE_SBRK 1 -/* Define to 1 if you have the `setlocale' function. */ -#define HAVE_SETLOCALE 1 - /* Define to 1 if you have the header file. */ #define HAVE_STDINT_H 1 @@ -232,11 +223,11 @@ /* #undef _LARGE_FILES */ /* Define to 1 if on MINIX. */ -/* #undef _MINIX */ +#define _MINIX 1 /* Define to 2 if the system does not provide POSIX.1 features except with this defined. */ -/* #undef _POSIX_1_SOURCE */ +#define _POSIX_1_SOURCE 2 /* Define to 1 if you need to in order for `stat' and other things to work. */ -/* #undef _POSIX_SOURCE */ +#define _POSIX_SOURCE 1 diff --git a/external/gpl3/binutils/usr.bin/ld/arch/earmhf/defs.mk b/external/gpl3/binutils/usr.bin/ld/arch/earmhf/defs.mk index 291f094ba..acad4e50e 100644 --- a/external/gpl3/binutils/usr.bin/ld/arch/earmhf/defs.mk +++ b/external/gpl3/binutils/usr.bin/ld/arch/earmhf/defs.mk @@ -3,11 +3,11 @@ # Generated from: NetBSD: mknative.common,v 1.9 2007/02/05 18:26:01 apb Exp # G_DEFS=-DHAVE_CONFIG_H -G_EMUL=armelf_nbsd_eabi -G_EMULATION_OFILES=earmelf_nbsd_eabi.o earmelfb_nbsd_eabi.o earmelf.o earmnbsd.o +G_EMUL=armelf_minix +G_EMULATION_OFILES=earmelf_minix.o earmelf.o G_INCLUDES= -G_OFILES=ldgram.o ldlex-wrapper.o lexsup.o ldlang.o mri.o ldctor.o ldmain.o plugin.o ldwrite.o ldexp.o ldemul.o ldver.o ldmisc.o ldfile.o ldcref.o earmelf_nbsd_eabi.o earmelfb_nbsd_eabi.o earmelf.o earmnbsd.o +G_OFILES=ldgram.o ldlex-wrapper.o lexsup.o ldlang.o mri.o ldctor.o ldmain.o plugin.o ldwrite.o ldexp.o ldemul.o ldver.o ldmisc.o ldfile.o ldcref.o earmelf_minix.o earmelf.o G_STRINGIFY=astring.sed G_TEXINFOS=ld.texinfo -G_target_alias=arm--netbsdelf-eabihf +G_target_alias=arm-elf32-minix G_enable_initfini_array=no diff --git a/external/gpl3/binutils/usr.bin/ld/arch/earmhf/ldemul-list.h b/external/gpl3/binutils/usr.bin/ld/arch/earmhf/ldemul-list.h index 59a6f9cbd..2344f001f 100644 --- a/external/gpl3/binutils/usr.bin/ld/arch/earmhf/ldemul-list.h +++ b/external/gpl3/binutils/usr.bin/ld/arch/earmhf/ldemul-list.h @@ -3,14 +3,10 @@ /* Generated from: NetBSD: mknative.common,v 1.9 2007/02/05 18:26:01 apb Exp */ /* This file is automatically generated. DO NOT EDIT! */ -extern ld_emulation_xfer_type ld_armelf_nbsd_eabi_emulation; -extern ld_emulation_xfer_type ld_armelfb_nbsd_eabi_emulation; +extern ld_emulation_xfer_type ld_armelf_minix_emulation; extern ld_emulation_xfer_type ld_armelf_emulation; -extern ld_emulation_xfer_type ld_armnbsd_emulation; #define EMULATION_LIST \ - &ld_armelf_nbsd_eabi_emulation, \ - &ld_armelfb_nbsd_eabi_emulation, \ + &ld_armelf_minix_emulation, \ &ld_armelf_emulation, \ - &ld_armnbsd_emulation, \ 0 diff --git a/external/gpl3/gcc/lib/crtstuff/arch/earmv6hf.mk b/external/gpl3/gcc/lib/crtstuff/arch/earmv6hf.mk index 58a3a350c..af71279f0 100644 --- a/external/gpl3/gcc/lib/crtstuff/arch/earmv6hf.mk +++ b/external/gpl3/gcc/lib/crtstuff/arch/earmv6hf.mk @@ -2,12 +2,11 @@ # Generated from: NetBSD: mknative-gcc,v 1.71 2013/06/28 08:30:10 mrg Exp # Generated from: NetBSD: mknative.common,v 1.9 2007/02/05 18:26:01 apb Exp # -nbgmake[1]: Entering directory `/u2/netbsd-HEAD/evbearmv6hf-el/obj/tools/gcc' G_INCLUDES=-I. -I. -I${GNUHOSTDIST}/gcc -I${GNUHOSTDIST}/gcc/. -I${GNUHOSTDIST}/gcc/../include -I./../intl -I${GNUHOSTDIST}/gcc/../libcpp/include -I${GNUHOSTDIST}/gcc/../libdecnumber -I${GNUHOSTDIST}/gcc/../libdecnumber/dpd -I../libdecnumber G_CRTSTUFF_CFLAGS=-O2 -DIN_GCC -W -Wall -Wwrite-strings -Wcast-qual -Wstrict-prototypes -Wmissing-prototypes -Wold-style-definition -isystem ./include -I. -I. -I${GNUHOSTDIST}/gcc -I${GNUHOSTDIST}/gcc/. -I${GNUHOSTDIST}/gcc/../include -I./../intl -I${GNUHOSTDIST}/gcc/../libcpp/include -I${GNUHOSTDIST}/gcc/../libdecnumber -I${GNUHOSTDIST}/gcc/../libdecnumber/dpd -I../libdecnumber -g0 -finhibit-size-directive -fno-inline -fno-exceptions -fno-zero-initialized-in-bss -fno-toplevel-reorder -fno-tree-vectorize G_CRTSTUFF_T_CFLAGS= G_CRTSTUFF_T_CFLAGS_S= -fPIC -G_tm_defines=NETBSD_ENABLE_PTHREADS TARGET_DEFAULT_FLOAT_ABI=ARM_FLOAT_ABI_HARD +G_tm_defines= G_xm_file= G_xm_defines= -nbgmake[1]: Leaving directory `/u2/netbsd-HEAD/evbearmv6hf-el/obj/tools/gcc' + diff --git a/external/gpl3/gcc/lib/libgcc/Makefile b/external/gpl3/gcc/lib/libgcc/Makefile index 20ed1643f..9f0433cb1 100644 --- a/external/gpl3/gcc/lib/libgcc/Makefile +++ b/external/gpl3/gcc/lib/libgcc/Makefile @@ -6,7 +6,7 @@ SUBDIR+= libgcc .if defined(__MINIX) && ${MKGCCCMDS} == "yes" -.if ${MKPIC} != "no" || ${MACHINE_ARCH} == "earm" +.if ((${MKPIC} != "no") || (${MACHINE_ARCH} == "earm") || (${MACHINE_ARCH} == "earmv6hf")) SUBDIR+= libgcc_eh .endif diff --git a/external/gpl3/gcc/lib/libgcc/arch/earmv6hf.mk b/external/gpl3/gcc/lib/libgcc/arch/earmv6hf.mk index 824f0c27e..52f5b4848 100644 --- a/external/gpl3/gcc/lib/libgcc/arch/earmv6hf.mk +++ b/external/gpl3/gcc/lib/libgcc/arch/earmv6hf.mk @@ -2,7 +2,6 @@ # Generated from: NetBSD: mknative-gcc,v 1.71 2013/06/28 08:30:10 mrg Exp # Generated from: NetBSD: mknative.common,v 1.9 2007/02/05 18:26:01 apb Exp # -nbgmake[1]: Entering directory `/u2/netbsd-HEAD/evbearmv6hf-el/obj/tools/gcc' G_INCLUDES=-I. -I. -I${GNUHOSTDIST}/gcc -I${GNUHOSTDIST}/gcc/. -I${GNUHOSTDIST}/gcc/../include -I./../intl -I${GNUHOSTDIST}/gcc/../libcpp/include -I${GNUHOSTDIST}/gcc/../libdecnumber -I${GNUHOSTDIST}/gcc/../libdecnumber/dpd -I../libdecnumber G_LIB2ADD=${GNUHOSTDIST}/gcc/config/arm/unaligned-funcs.c G_LIB2ADDEH=${GNUHOSTDIST}/gcc/config/arm/unwind-arm.c ${GNUHOSTDIST}/gcc/config/arm/libunwind.S ${GNUHOSTDIST}/gcc/config/arm/pr-support.c ${GNUHOSTDIST}/gcc/unwind-c.c @@ -19,8 +18,8 @@ G_SHLIB_MAPFILES=${GNUHOSTDIST}/gcc/libgcc-std.ver ${GNUHOSTDIST}/gcc/config/arm G_SHLIB_NM_FLAGS=-pg G_EXTRA_HEADERS=${GNUHOSTDIST}/gcc/config/arm/mmintrin.h ${GNUHOSTDIST}/gcc/config/arm/arm_neon.h ${GNUHOSTDIST}/gcc/ginclude/tgmath.h G_xm_defines= -G_tm_defines=NETBSD_ENABLE_PTHREADS TARGET_DEFAULT_FLOAT_ABI=ARM_FLOAT_ABI_HARD +G_tm_defines= G_COLLECT2=collect2 G_UNWIND_H=${GNUHOSTDIST}/gcc/config/arm/unwind-arm.h G_xm_include_list=auto-host.h ansidecl.h -nbgmake[1]: Leaving directory `/u2/netbsd-HEAD/evbearmv6hf-el/obj/tools/gcc' + diff --git a/external/gpl3/gcc/lib/libgomp/arch/earmv6hf/config.h b/external/gpl3/gcc/lib/libgomp/arch/earmv6hf/config.h index 56e3fde42..8d1e89b93 100644 --- a/external/gpl3/gcc/lib/libgomp/arch/earmv6hf/config.h +++ b/external/gpl3/gcc/lib/libgomp/arch/earmv6hf/config.h @@ -75,7 +75,7 @@ #define HAVE_SYS_TYPES_H 1 /* Define to 1 if the target supports thread-local storage. */ -#define HAVE_TLS 1 +/* #undef HAVE_TLS */ /* Define to 1 if you have the header file. */ #define HAVE_UNISTD_H 1 diff --git a/external/gpl3/gcc/lib/libiberty/arch/earmv6hf/config.h b/external/gpl3/gcc/lib/libiberty/arch/earmv6hf/config.h index ad4514b5f..bb0f71772 100644 --- a/external/gpl3/gcc/lib/libiberty/arch/earmv6hf/config.h +++ b/external/gpl3/gcc/lib/libiberty/arch/earmv6hf/config.h @@ -274,7 +274,7 @@ #define HAVE_SYSCONF 1 /* Define to 1 if you have the `sysctl' function. */ -#define HAVE_SYSCTL 1 +/* #undef HAVE_SYSCTL */ /* Define to 1 if you have the `sysmp' function. */ /* #undef HAVE_SYSMP */ @@ -370,10 +370,10 @@ #define HAVE_VSPRINTF 1 /* Define to 1 if you have the `wait3' function. */ -#define HAVE_WAIT3 1 +/* #undef HAVE_WAIT3 */ /* Define to 1 if you have the `wait4' function. */ -#define HAVE_WAIT4 1 +/* #undef HAVE_WAIT4 */ /* Define to 1 if you have the `waitpid' function. */ #define HAVE_WAITPID 1 diff --git a/external/gpl3/gcc/lib/libobjc/arch/earmv6hf/config.h b/external/gpl3/gcc/lib/libobjc/arch/earmv6hf/config.h index 3bcee757a..3c606c3e3 100644 --- a/external/gpl3/gcc/lib/libobjc/arch/earmv6hf/config.h +++ b/external/gpl3/gcc/lib/libobjc/arch/earmv6hf/config.h @@ -9,7 +9,7 @@ #define HAVE_DLFCN_H 1 /* Define if the compiler has a thread header that is non single. */ -#define HAVE_GTHR_DEFAULT 1 +/* #undef HAVE_GTHR_DEFAULT */ /* Define to 1 if you have the header file. */ #define HAVE_INTTYPES_H 1 diff --git a/external/gpl3/gcc/lib/libobjc/arch/earmv6hf/defs.mk b/external/gpl3/gcc/lib/libobjc/arch/earmv6hf/defs.mk index 2d598689f..76ae2dd43 100644 --- a/external/gpl3/gcc/lib/libobjc/arch/earmv6hf/defs.mk +++ b/external/gpl3/gcc/lib/libobjc/arch/earmv6hf/defs.mk @@ -2,15 +2,10 @@ # Generated from: NetBSD: mknative-gcc,v 1.71 2013/06/28 08:30:10 mrg Exp # Generated from: NetBSD: mknative.common,v 1.9 2007/02/05 18:26:01 apb Exp # -nbgmake[1]: Entering directory `/u2/netbsd-HEAD/evbearmv6hf-el/obj/tools/gcc' G_ALL_OPT_FILES=${GNUHOSTDIST}/gcc/lto/lang.opt ${GNUHOSTDIST}/gcc/c.opt ${GNUHOSTDIST}/gcc/common.opt ${GNUHOSTDIST}/gcc/config/arm/arm.opt -nbgmake[1]: Leaving directory `/u2/netbsd-HEAD/evbearmv6hf-el/obj/tools/gcc' -nbgmake[1]: Entering directory `/u2/netbsd-HEAD/evbearmv6hf-el/obj/tools/gcc' G_ALL_CFLAGS=-I. -I${GNUHOSTDIST}/libobjc -g -W -Wall -Wwrite-strings -Wstrict-prototypes -DIN_GCC -DIN_TARGET_LIBS -fno-strict-aliasing -fexceptions G_INCLUDES=-I${GNUHOSTDIST}/libobjc/objc -I${GNUHOSTDIST}/libobjc/../gcc -I${GNUHOSTDIST}/libobjc/../gcc/config -I../.././gcc -I${GNUHOSTDIST}/libobjc/../include G_OBJS=archive.lo class.lo encoding.lo gc.lo hash.lo init.lo linking.lo misc.lo nil_method.lo NXConstStr.lo Object.lo objects.lo Protocol.lo sarray.lo selector.lo sendmsg.lo thr.lo thr-objc.lo exception.lo G_OBJC_H=hash.h objc-list.h sarray.h objc.h objc-api.h NXConstStr.h Object.h Protocol.h encoding.h typedstream.h thr.h objc-decls.h -nbgmake[1]: Leaving directory `/u2/netbsd-HEAD/evbearmv6hf-el/obj/tools/gcc' -nbgmake[1]: Entering directory `/u2/netbsd-HEAD/evbearmv6hf-el/obj/tools/gcc' G_UNWIND_H=${GNUHOSTDIST}/gcc/config/arm/unwind-arm.h -nbgmake[1]: Leaving directory `/u2/netbsd-HEAD/evbearmv6hf-el/obj/tools/gcc' + diff --git a/external/gpl3/gcc/lib/libstdc++-v3/arch/earmv6hf/c++config.h b/external/gpl3/gcc/lib/libstdc++-v3/arch/earmv6hf/c++config.h index bc1a80edd..43a6fc5ed 100644 --- a/external/gpl3/gcc/lib/libstdc++-v3/arch/earmv6hf/c++config.h +++ b/external/gpl3/gcc/lib/libstdc++-v3/arch/earmv6hf/c++config.h @@ -542,7 +542,7 @@ _GLIBCXX_END_NAMESPACE /* Define if gthr-default.h exists (meaning that threading support is enabled). */ -#define _GLIBCXX_HAVE_GTHR_DEFAULT 1 +/* #undef _GLIBCXX_HAVE_GTHR_DEFAULT */ /* Define to 1 if you have the `hypot' function. */ /* #undef _GLIBCXX_HAVE_HYPOT */ @@ -662,7 +662,7 @@ _GLIBCXX_END_NAMESPACE /* #undef _GLIBCXX_HAVE_NAN_H */ /* Define if poll is available in . */ -#define _GLIBCXX_HAVE_POLL 1 +/* #undef _GLIBCXX_HAVE_POLL */ /* Define to 1 if you have the `powf' function. */ /* #undef _GLIBCXX_HAVE_POWF */ @@ -734,7 +734,7 @@ _GLIBCXX_END_NAMESPACE /* #undef _GLIBCXX_HAVE_STRXFRM_L */ /* Define to 1 if you have the header file. */ -#define _GLIBCXX_HAVE_SYS_FILIO_H 1 +/* #undef _GLIBCXX_HAVE_SYS_FILIO_H */ /* Define to 1 if you have the header file. */ #define _GLIBCXX_HAVE_SYS_IOCTL_H 1 @@ -773,7 +773,7 @@ _GLIBCXX_END_NAMESPACE /* #undef _GLIBCXX_HAVE_S_IFREG */ /* Define if S_IFREG is available in . */ -#define _GLIBCXX_HAVE_S_ISREG 1 +/* #undef _GLIBCXX_HAVE_S_ISREG */ /* Define to 1 if you have the `tanf' function. */ /* #undef _GLIBCXX_HAVE_TANF */ @@ -815,7 +815,7 @@ _GLIBCXX_END_NAMESPACE #define _GLIBCXX_HAVE_WCTYPE_H 1 /* Define if writev is available in . */ -#define _GLIBCXX_HAVE_WRITEV 1 +/* #undef _GLIBCXX_HAVE_WRITEV */ /* Define to 1 if you have the `_acosf' function. */ /* #undef _GLIBCXX_HAVE__ACOSF */ @@ -1119,7 +1119,7 @@ _GLIBCXX_END_NAMESPACE /* Define if C99 functions in should be used in . Using compiler builtins for these functions requires corresponding C99 library functions to be present. */ -#define _GLIBCXX_USE_C99_COMPLEX_TR1 1 +/* #undef _GLIBCXX_USE_C99_COMPLEX_TR1 */ /* Define if C99 functions in should be imported in in namespace std::tr1. */ @@ -1143,7 +1143,7 @@ _GLIBCXX_END_NAMESPACE /* Define if C99 functions or macros in should be imported in in namespace std::tr1. */ -#define _GLIBCXX_USE_C99_MATH_TR1 1 +/* #undef _GLIBCXX_USE_C99_MATH_TR1 */ /* Define if C99 types in should be imported in in namespace std::tr1. */ diff --git a/external/gpl3/gcc/lib/libstdc++-v3/arch/earmv6hf/config.h b/external/gpl3/gcc/lib/libstdc++-v3/arch/earmv6hf/config.h index 938409722..13c69664b 100644 --- a/external/gpl3/gcc/lib/libstdc++-v3/arch/earmv6hf/config.h +++ b/external/gpl3/gcc/lib/libstdc++-v3/arch/earmv6hf/config.h @@ -163,7 +163,7 @@ /* Define if gthr-default.h exists (meaning that threading support is enabled). */ -#define HAVE_GTHR_DEFAULT 1 +/* #undef HAVE_GTHR_DEFAULT */ /* Define to 1 if you have the `hypot' function. */ /* #undef HAVE_HYPOT */ @@ -283,7 +283,7 @@ /* #undef HAVE_NAN_H */ /* Define if poll is available in . */ -#define HAVE_POLL 1 +/* #undef HAVE_POLL */ /* Define to 1 if you have the `powf' function. */ /* #undef HAVE_POWF */ @@ -394,7 +394,7 @@ /* #undef HAVE_S_IFREG */ /* Define if S_IFREG is available in . */ -#define HAVE_S_ISREG 1 +/* #undef HAVE_S_ISREG */ /* Define to 1 if you have the `tanf' function. */ /* #undef HAVE_TANF */ @@ -436,7 +436,7 @@ #define HAVE_WCTYPE_H 1 /* Define if writev is available in . */ -#define HAVE_WRITEV 1 +/* #undef HAVE_WRITEV */ /* Define to 1 if you have the `_acosf' function. */ /* #undef HAVE__ACOSF */ @@ -741,7 +741,7 @@ /* Define if C99 functions in should be used in . Using compiler builtins for these functions requires corresponding C99 library functions to be present. */ -#define _GLIBCXX_USE_C99_COMPLEX_TR1 1 +/* #undef _GLIBCXX_USE_C99_COMPLEX_TR1 */ /* Define if C99 functions in should be imported in in namespace std::tr1. */ @@ -765,7 +765,7 @@ /* Define if C99 functions or macros in should be imported in in namespace std::tr1. */ -#define _GLIBCXX_USE_C99_MATH_TR1 1 +/* #undef _GLIBCXX_USE_C99_MATH_TR1 */ /* Define if C99 types in should be imported in in namespace std::tr1. */ diff --git a/external/gpl3/gcc/lib/libstdc++-v3/arch/earmv6hf/defs.mk b/external/gpl3/gcc/lib/libstdc++-v3/arch/earmv6hf/defs.mk index 6ad586bf0..f84753539 100644 --- a/external/gpl3/gcc/lib/libstdc++-v3/arch/earmv6hf/defs.mk +++ b/external/gpl3/gcc/lib/libstdc++-v3/arch/earmv6hf/defs.mk @@ -2,14 +2,9 @@ # Generated from: NetBSD: mknative-gcc,v 1.71 2013/06/28 08:30:10 mrg Exp # Generated from: NetBSD: mknative.common,v 1.9 2007/02/05 18:26:01 apb Exp # -nbgmake[1]: Entering directory `/u2/netbsd-HEAD/evbearmv6hf-el/obj/tools/gcc' G_LIBSUPCXX_SOURCES=array_type_info.cc atexit_arm.cc bad_cast.cc bad_typeid.cc class_type_info.cc del_op.cc del_opnt.cc del_opv.cc del_opvnt.cc dyncast.cc eh_alloc.cc eh_arm.cc eh_aux_runtime.cc eh_call.cc eh_catch.cc eh_exception.cc eh_globals.cc eh_personality.cc eh_ptr.cc eh_term_handler.cc eh_terminate.cc eh_throw.cc eh_type.cc eh_unex_handler.cc enum_type_info.cc function_type_info.cc fundamental_type_info.cc guard.cc new_handler.cc new_op.cc new_opnt.cc new_opv.cc new_opvnt.cc pbase_type_info.cc pmem_type_info.cc pointer_type_info.cc pure.cc si_class_type_info.cc tinfo.cc tinfo2.cc vec.cc vmi_class_type_info.cc vterminate.cc -nbgmake[1]: Leaving directory `/u2/netbsd-HEAD/evbearmv6hf-el/obj/tools/gcc' -nbgmake[1]: Entering directory `/u2/netbsd-HEAD/evbearmv6hf-el/obj/tools/gcc' G_LIBSUPCXX_C_SOURCES=cp-demangle.c -nbgmake[1]: Leaving directory `/u2/netbsd-HEAD/evbearmv6hf-el/obj/tools/gcc' -nbgmake[1]: Entering directory `/u2/netbsd-HEAD/evbearmv6hf-el/obj/tools/gcc' -G_SRC_SOURCES=atomic.cc bitmap_allocator.cc pool_allocator.cc mt_allocator.cc codecvt.cc compatibility.cc compatibility-c++0x.cc compatibility-debug_list.cc compatibility-list.cc complex_io.cc ctype.cc debug.cc functexcept.cc globals_io.cc hash_c++0x.cc hash_tr1.cc hashtable_c++0x.cc hashtable_tr1.cc ios.cc ios_failure.cc ios_init.cc ios_locale.cc limits.cc list.cc debug_list.cc locale.cc locale_init.cc locale_facets.cc localename.cc math_stubs_float.cc math_stubs_long_double.cc stdexcept.cc strstream.cc system_error.cc tree.cc allocator-inst.cc concept-inst.cc fstream-inst.cc ext-inst.cc ios-inst.cc iostream-inst.cc istream-inst.cc istream.cc locale-inst.cc misc-inst.cc ostream-inst.cc sstream-inst.cc streambuf-inst.cc streambuf.cc string-inst.cc valarray-inst.cc wlocale-inst.cc wstring-inst.cc mutex.cc condition_variable.cc chrono.cc thread.cc future.cc atomicity.cc codecvt_members.cc collate_members.cc ctype_members.cc messages_members.cc monetary_members.cc numeric_members.cc time_members.cc basic_file.cc c++locale.cc parallel_list.cc parallel_settings.cc compatibility-parallel_list.cc +G_SRC_SOURCES=atomic.cc bitmap_allocator.cc pool_allocator.cc mt_allocator.cc codecvt.cc compatibility.cc compatibility-c++0x.cc compatibility-debug_list.cc compatibility-list.cc complex_io.cc ctype.cc debug.cc functexcept.cc globals_io.cc hash_c++0x.cc hash_tr1.cc hashtable_c++0x.cc hashtable_tr1.cc ios.cc ios_failure.cc ios_init.cc ios_locale.cc limits.cc list.cc debug_list.cc locale.cc locale_init.cc locale_facets.cc localename.cc math_stubs_float.cc math_stubs_long_double.cc stdexcept.cc strstream.cc system_error.cc tree.cc allocator-inst.cc concept-inst.cc fstream-inst.cc ext-inst.cc ios-inst.cc iostream-inst.cc istream-inst.cc istream.cc locale-inst.cc misc-inst.cc ostream-inst.cc sstream-inst.cc streambuf-inst.cc streambuf.cc string-inst.cc valarray-inst.cc wlocale-inst.cc wstring-inst.cc mutex.cc condition_variable.cc chrono.cc thread.cc future.cc atomicity.cc codecvt_members.cc collate_members.cc ctype_members.cc messages_members.cc monetary_members.cc numeric_members.cc time_members.cc basic_file.cc c++locale.cc G_atomicity_file=${GNUHOSTDIST}/libstdc++-v3/config/cpu/generic/atomicity_mutex/atomicity.h G_CCODECVT_CC=config/locale/generic/codecvt_members.cc G_CCOLLATE_CC=config/locale/generic/collate_members.cc @@ -21,12 +16,8 @@ G_CTIME_CC=config/locale/generic/time_members.cc G_CLOCALE_CC=config/locale/generic/c_locale.cc G_BASIC_FILE_CC=config/io/basic_file_stdio.cc G_SECTION_FLAGS=-ffunction-sections -fdata-sections -nbgmake[1]: Leaving directory `/u2/netbsd-HEAD/evbearmv6hf-el/obj/tools/gcc' -nbgmake[1]: Entering directory `gcc' G_c_base_headers=cassert ccomplex cctype cerrno cfenv cfloat cinttypes ciso646 climits clocale cmath csetjmp csignal cstdarg cstdbool cstddef cstdint cstdio cstdlib cstring ctgmath ctime cwchar cwctype G_std_headers=algorithm array atomic bitset chrono complex condition_variable deque forward_list fstream functional future iomanip ios iosfwd iostream istream iterator limits list locale map memory mutex numeric ostream queue random ratio regex set sstream stack stdexcept streambuf string system_error thread tuple type_traits unordered_map unordered_set utility valarray vector -nbgmake[1]: Leaving directory `gcc' -nbgmake[1]: Entering directory `gcc' G_bits_headers=algorithmfwd.h allocator.h atomic_base.h atomicfwd_c.h atomicfwd_cxx.h atomic_0.h atomic_2.h basic_ios.h basic_ios.tcc basic_string.h basic_string.tcc boost_concept_check.h c++0x_warning.h char_traits.h codecvt.h concept_check.h cpp_type_traits.h deque.tcc forward_list.h forward_list.tcc fstream.tcc functexcept.h functional_hash.h gslice.h gslice_array.h hashtable.h hashtable_policy.h indirect_array.h ios_base.h istream.tcc list.tcc locale_classes.h locale_classes.tcc locale_facets.h locale_facets.tcc locale_facets_nonio.h locale_facets_nonio.tcc localefwd.h mask_array.h move.h ostream.tcc ostream_insert.h postypes.h random.h random.tcc stream_iterator.h streambuf_iterator.h shared_ptr.h shared_ptr_base.h slice_array.h sstream.tcc stl_algo.h stl_algobase.h stl_bvector.h stl_construct.h stl_deque.h stl_function.h stl_heap.h stl_iterator.h stl_iterator_base_funcs.h stl_iterator_base_types.h stl_list.h stl_map.h stl_multimap.h stl_multiset.h stl_numeric.h stl_pair.h stl_queue.h stl_raw_storage_iter.h stl_relops.h stl_set.h stl_stack.h stl_tempbuf.h stl_tree.h stl_uninitialized.h stl_vector.h streambuf.tcc stringfwd.h unique_ptr.h unordered_map.h unordered_set.h valarray_array.h valarray_array.tcc valarray_before.h valarray_after.h vector.tcc G_backward_headers=auto_ptr.h backward_warning.h binders.h hash_map hash_set hash_fun.h hashtable.h strstream G_ext_headers=algorithm atomicity.h array_allocator.h bitmap_allocator.h cast.h codecvt_specializations.h concurrence.h debug_allocator.h enc_filebuf.h extptr_allocator.h stdio_filebuf.h stdio_sync_filebuf.h functional iterator malloc_allocator.h memory mt_allocator.h new_allocator.h numeric numeric_traits.h pod_char_traits.h pointer.h pool_allocator.h rb_tree rope ropeimpl.h slist string_conversions.h throw_allocator.h typelist.h type_traits.h rc_string_base.h sso_string_base.h vstring.h vstring.tcc vstring_fwd.h vstring_util.h hash_set hash_map @@ -38,11 +29,7 @@ G_c_compatibility_headers_extra=complex.h fenv.h tgmath.h stdatomic.h G_tr1_impl_headers=array boost_sp_counted_base.h cctype cfenv cinttypes cmath complex cstdint cstdio cstdlib cwchar cwctype regex type_traits utility G_parallel_headers=algo.h algobase.h algorithm algorithmfwd.h balanced_quicksort.h base.h basic_iterator.h checkers.h compatibility.h compiletime_settings.h equally_split.h features.h find.h find_selectors.h for_each.h for_each_selectors.h iterator.h list_partition.h losertree.h merge.h multiseq_selection.h multiway_merge.h multiway_mergesort.h numeric numericfwd.h omp_loop.h omp_loop_static.h par_loop.h parallel.h partial_sum.h partition.h queue.h quicksort.h random_number.h random_shuffle.h search.h set_operations.h settings.h sort.h tags.h types.h unique_copy.h workstealing.h G_decimal_headers=decimal decimal.h -nbgmake[1]: Leaving directory `gcc' -nbgmake[1]: Entering directory `/u2/netbsd-HEAD/evbearmv6hf-el/obj/tools/gcc' G_thread_host_headers=gthr.h gthr-single.h gthr-posix.h gthr-tpf.h gthr-default.h G_host_headers_extra=basic_file.h c++config.h c++allocator.h c++io.h c++locale.h messages_members.h time_members.h -nbgmake[1]: Leaving directory `/u2/netbsd-HEAD/evbearmv6hf-el/obj/tools/gcc' -nbgmake[1]: Entering directory `/u2/netbsd-HEAD/evbearmv6hf-el/obj/tools/gcc' G_UNWIND_H=${GNUHOSTDIST}/gcc/config/arm/unwind-arm.h -nbgmake[1]: Leaving directory `/u2/netbsd-HEAD/evbearmv6hf-el/obj/tools/gcc' + diff --git a/external/gpl3/gcc/usr.bin/gcc/arch/earmv6/auto-host.h b/external/gpl3/gcc/usr.bin/gcc/arch/earmv6/auto-host.h index 4f253155d..01373d82c 100644 --- a/external/gpl3/gcc/usr.bin/gcc/arch/earmv6/auto-host.h +++ b/external/gpl3/gcc/usr.bin/gcc/arch/earmv6/auto-host.h @@ -127,7 +127,7 @@ /* Define to 1 if translation of program messages to the user's native language is requested. */ #ifndef USED_FOR_TARGET -#define ENABLE_NLS 1 +/* #undef ENABLE_NLS */ #endif @@ -504,7 +504,7 @@ /* Define 0/1 if your assembler and linker support COMDAT groups. */ #ifndef USED_FOR_TARGET -#define HAVE_COMDAT_GROUP 1 +#define HAVE_COMDAT_GROUP 0 #endif @@ -759,14 +759,14 @@ /* Define to 1 if we found a declaration for 'setrlimit', otherwise define to 0. */ #ifndef USED_FOR_TARGET -#define HAVE_DECL_SETRLIMIT 1 +#define HAVE_DECL_SETRLIMIT 0 #endif /* Define to 1 if we found a declaration for 'sigaltstack', otherwise define to 0. */ #ifndef USED_FOR_TARGET -#define HAVE_DECL_SIGALTSTACK 1 +#define HAVE_DECL_SIGALTSTACK 0 #endif @@ -1093,7 +1093,7 @@ /* Define .init_array/.fini_array sections are available and working. */ #ifndef USED_FOR_TARGET -/* #undef HAVE_INITFINI_ARRAY */ +#define HAVE_INITFINI_ARRAY 1 #endif @@ -1267,7 +1267,7 @@ /* Define to 1 if you have the `mincore' function. */ #ifndef USED_FOR_TARGET -#define HAVE_MINCORE 1 +/* #undef HAVE_MINCORE */ #endif @@ -1321,7 +1321,7 @@ /* Define to 1 if you have the `setrlimit' function. */ #ifndef USED_FOR_TARGET -#define HAVE_SETRLIMIT 1 +/* #undef HAVE_SETRLIMIT */ #endif @@ -1753,7 +1753,7 @@ /* Define to 1 if on MINIX. */ #ifndef USED_FOR_TARGET -/* #undef _MINIX */ +#define _MINIX 1 #endif diff --git a/external/gpl3/gcc/usr.bin/gcc/arch/earmv6hf/auto-host.h b/external/gpl3/gcc/usr.bin/gcc/arch/earmv6hf/auto-host.h index 4f253155d..01373d82c 100644 --- a/external/gpl3/gcc/usr.bin/gcc/arch/earmv6hf/auto-host.h +++ b/external/gpl3/gcc/usr.bin/gcc/arch/earmv6hf/auto-host.h @@ -127,7 +127,7 @@ /* Define to 1 if translation of program messages to the user's native language is requested. */ #ifndef USED_FOR_TARGET -#define ENABLE_NLS 1 +/* #undef ENABLE_NLS */ #endif @@ -504,7 +504,7 @@ /* Define 0/1 if your assembler and linker support COMDAT groups. */ #ifndef USED_FOR_TARGET -#define HAVE_COMDAT_GROUP 1 +#define HAVE_COMDAT_GROUP 0 #endif @@ -759,14 +759,14 @@ /* Define to 1 if we found a declaration for 'setrlimit', otherwise define to 0. */ #ifndef USED_FOR_TARGET -#define HAVE_DECL_SETRLIMIT 1 +#define HAVE_DECL_SETRLIMIT 0 #endif /* Define to 1 if we found a declaration for 'sigaltstack', otherwise define to 0. */ #ifndef USED_FOR_TARGET -#define HAVE_DECL_SIGALTSTACK 1 +#define HAVE_DECL_SIGALTSTACK 0 #endif @@ -1093,7 +1093,7 @@ /* Define .init_array/.fini_array sections are available and working. */ #ifndef USED_FOR_TARGET -/* #undef HAVE_INITFINI_ARRAY */ +#define HAVE_INITFINI_ARRAY 1 #endif @@ -1267,7 +1267,7 @@ /* Define to 1 if you have the `mincore' function. */ #ifndef USED_FOR_TARGET -#define HAVE_MINCORE 1 +/* #undef HAVE_MINCORE */ #endif @@ -1321,7 +1321,7 @@ /* Define to 1 if you have the `setrlimit' function. */ #ifndef USED_FOR_TARGET -#define HAVE_SETRLIMIT 1 +/* #undef HAVE_SETRLIMIT */ #endif @@ -1753,7 +1753,7 @@ /* Define to 1 if on MINIX. */ #ifndef USED_FOR_TARGET -/* #undef _MINIX */ +#define _MINIX 1 #endif diff --git a/external/gpl3/gcc/usr.bin/gcc/arch/earmv6hf/configargs.h b/external/gpl3/gcc/usr.bin/gcc/arch/earmv6hf/configargs.h index 53acbad72..b26b56e90 100644 --- a/external/gpl3/gcc/usr.bin/gcc/arch/earmv6hf/configargs.h +++ b/external/gpl3/gcc/usr.bin/gcc/arch/earmv6hf/configargs.h @@ -3,9 +3,9 @@ /* Generated from: NetBSD: mknative.common,v 1.9 2007/02/05 18:26:01 apb Exp */ /* Generated automatically. */ -static const char configuration_arguments[] = "/u1/netbsd-HEAD/src/tools/gcc/../../external/gpl3/gcc/dist/configure --target=armv6--netbsdelf-eabihf --enable-long-long --enable-threads --with-bugurl=http://www.NetBSD.org/Misc/send-pr.html --with-pkgversion='NetBSD nb1 20120916' --with-system-zlib --enable-__cxa_atexit --with-mpc-lib=/u2/netbsd-HEAD/evbearmv6hf-el/obj/external/lgpl2/mpc/lib/libmpc --with-mpfr-lib=/u2/netbsd-HEAD/evbearmv6hf-el/obj/external/lgpl3/mpfr/lib/libmpfr --with-gmp-lib=/u2/netbsd-HEAD/evbearmv6hf-el/obj/external/lgpl3/gmp/lib/libgmp --with-mpc-include=/u1/netbsd-HEAD/src/external/lgpl2/mpc/dist/src --with-mpfr-include=/u1/netbsd-HEAD/src/external/lgpl3/mpfr/dist --with-gmp-include=/u1/netbsd-HEAD/src/external/lgpl3/gmp/lib/libgmp/arch/earmv6hf --enable-tls --disable-multilib --disable-symvers --disable-libstdcxx-pch --build=x86_64-unknown-netbsd6.1. --host=armv6--netbsdelf-eabihf"; -static const char thread_model[] = "posix"; +static const char configuration_arguments[] = "/usr/src/tools/gcc/../../external/gpl3/gcc/dist/configure --target=arm-elf32-minix --disable-libssp --disable-threads --enable-long-long --enable-threads --with-bugurl=http://www.NetBSD.org/Misc/send-pr.html --with-pkgversion='NetBSD nb1 20120916' --with-system-zlib --enable-__cxa_atexit --with-arch=armv7-a --with-mpfr=/usr/objs/evbearm-el/tooldir.Minix-3.2.1-i686 --with-gmp=/usr/objs/evbearm-el/tooldir.Minix-3.2.1-i686 --with-mpc=/usr/objs/evbearm-el/tooldir.Minix-3.2.1-i686 --disable-nls --disable-multilib --disable-symvers --disable-libstdcxx-pch --program-transform-name=s,^,arm-elf32-minix-, --enable-languages='c c++ objc' --prefix=/usr/objs/evbearm-el/tooldir.Minix-3.2.1-i686"; +static const char thread_model[] = "single"; static const struct { const char *name, *value; -} configure_default_options[] = { { "cpu", "arm1176jzf-s" } }; +} configure_default_options[] = { { "arch", "arm1176jzf-s" } }; diff --git a/external/gpl3/gcc/usr.bin/gcc/arch/earmv6hf/defs.mk b/external/gpl3/gcc/usr.bin/gcc/arch/earmv6hf/defs.mk index 458618809..333c22d27 100644 --- a/external/gpl3/gcc/usr.bin/gcc/arch/earmv6hf/defs.mk +++ b/external/gpl3/gcc/usr.bin/gcc/arch/earmv6hf/defs.mk @@ -29,16 +29,16 @@ G_GCC_H=gcc.h version.h G_GTFILES_SRCDIR= G_GTFILES_FILES_FILES= G_GTFILES_FILES_LANGS= -G_GTFILES=${GNUHOSTDIST}/gcc/../libcpp/include/line-map.h ${GNUHOSTDIST}/gcc/../libcpp/include/cpplib.h ${GNUHOSTDIST}/gcc/../libcpp/include/cpp-id-data.h ${GNUHOSTDIST}/gcc/input.h ${GNUHOSTDIST}/gcc/coretypes.h auto-host.h ${GNUHOSTDIST}/gcc/../include/ansidecl.h options.h ${GNUHOSTDIST}/gcc/config/dbxelf.h ${GNUHOSTDIST}/gcc/config/elfos.h ${GNUHOSTDIST}/gcc/config/netbsd.h ${GNUHOSTDIST}/gcc/config/netbsd-elf.h ${GNUHOSTDIST}/gcc/config/arm/elf.h ${GNUHOSTDIST}/gcc/config/arm/aout.h ${GNUHOSTDIST}/gcc/config/arm/arm.h ${GNUHOSTDIST}/gcc/config/arm/bpabi.h ${GNUHOSTDIST}/gcc/config/arm/netbsd-elf.h ${GNUHOSTDIST}/gcc/config/arm/netbsd-eabi.h ${GNUHOSTDIST}/gcc/defaults.h ${GNUHOSTDIST}/gcc/../include/hashtab.h ${GNUHOSTDIST}/gcc/../include/splay-tree.h ${GNUHOSTDIST}/gcc/bitmap.h ${GNUHOSTDIST}/gcc/alias.h ${GNUHOSTDIST}/gcc/coverage.c ${GNUHOSTDIST}/gcc/rtl.h ${GNUHOSTDIST}/gcc/vecprim.h ${GNUHOSTDIST}/gcc/optabs.h ${GNUHOSTDIST}/gcc/tree.h ${GNUHOSTDIST}/gcc/varray.h ${GNUHOSTDIST}/gcc/libfuncs.h ${GNUHOSTDIST}/gcc/../libcpp/include/symtab.h ${GNUHOSTDIST}/gcc/../include/obstack.h ${GNUHOSTDIST}/gcc/real.h ${GNUHOSTDIST}/gcc/function.h ${GNUHOSTDIST}/gcc/insn-addr.h ${GNUHOSTDIST}/gcc/hwint.h ${GNUHOSTDIST}/gcc/fixed-value.h ${GNUHOSTDIST}/gcc/ipa-reference.h ${GNUHOSTDIST}/gcc/output.h ${GNUHOSTDIST}/gcc/cfgloop.h ${GNUHOSTDIST}/gcc/cselib.h ${GNUHOSTDIST}/gcc/basic-block.h ${GNUHOSTDIST}/gcc/cgraph.h ${GNUHOSTDIST}/gcc/reload.h ${GNUHOSTDIST}/gcc/caller-save.c ${GNUHOSTDIST}/gcc/alias.c ${GNUHOSTDIST}/gcc/bitmap.c ${GNUHOSTDIST}/gcc/cselib.c ${GNUHOSTDIST}/gcc/cgraph.c ${GNUHOSTDIST}/gcc/ipa-prop.c ${GNUHOSTDIST}/gcc/ipa-cp.c ${GNUHOSTDIST}/gcc/ipa-inline.c ${GNUHOSTDIST}/gcc/matrix-reorg.c ${GNUHOSTDIST}/gcc/dbxout.c ${GNUHOSTDIST}/gcc/ipa-struct-reorg.c ${GNUHOSTDIST}/gcc/dwarf2out.c ${GNUHOSTDIST}/gcc/dwarf2asm.c ${GNUHOSTDIST}/gcc/tree-vect-generic.c ${GNUHOSTDIST}/gcc/dojump.c ${GNUHOSTDIST}/gcc/emit-rtl.c ${GNUHOSTDIST}/gcc/except.h ${GNUHOSTDIST}/gcc/explow.c ${GNUHOSTDIST}/gcc/expr.c ${GNUHOSTDIST}/gcc/expr.h ${GNUHOSTDIST}/gcc/function.c ${GNUHOSTDIST}/gcc/except.c ${GNUHOSTDIST}/gcc/gcse.c ${GNUHOSTDIST}/gcc/integrate.c ${GNUHOSTDIST}/gcc/lists.c ${GNUHOSTDIST}/gcc/optabs.c ${GNUHOSTDIST}/gcc/profile.c ${GNUHOSTDIST}/gcc/reginfo.c ${GNUHOSTDIST}/gcc/mcf.c ${GNUHOSTDIST}/gcc/reg-stack.c ${GNUHOSTDIST}/gcc/cfglayout.c ${GNUHOSTDIST}/gcc/cfglayout.h ${GNUHOSTDIST}/gcc/sdbout.c ${GNUHOSTDIST}/gcc/stor-layout.c ${GNUHOSTDIST}/gcc/stringpool.c ${GNUHOSTDIST}/gcc/tree.c ${GNUHOSTDIST}/gcc/varasm.c ${GNUHOSTDIST}/gcc/gimple.h ${GNUHOSTDIST}/gcc/gimple.c ${GNUHOSTDIST}/gcc/tree-mudflap.c ${GNUHOSTDIST}/gcc/tree-flow.h ${GNUHOSTDIST}/gcc/tree-ssanames.c ${GNUHOSTDIST}/gcc/tree-eh.c ${GNUHOSTDIST}/gcc/tree-ssa-address.c ${GNUHOSTDIST}/gcc/tree-cfg.c ${GNUHOSTDIST}/gcc/tree-dfa.c ${GNUHOSTDIST}/gcc/tree-iterator.c ${GNUHOSTDIST}/gcc/gimplify.c ${GNUHOSTDIST}/gcc/tree-chrec.h ${GNUHOSTDIST}/gcc/tree-scalar-evolution.c ${GNUHOSTDIST}/gcc/tree-ssa-operands.h ${GNUHOSTDIST}/gcc/tree-profile.c ${GNUHOSTDIST}/gcc/tree-nested.c ${GNUHOSTDIST}/gcc/varpool.c ${GNUHOSTDIST}/gcc/tree-parloops.c ${GNUHOSTDIST}/gcc/omp-low.c ${GNUHOSTDIST}/gcc/targhooks.c ${GNUHOSTDIST}/gcc/config/arm/arm.c ${GNUHOSTDIST}/gcc/passes.c ${GNUHOSTDIST}/gcc/cgraphunit.c ${GNUHOSTDIST}/gcc/tree-ssa-propagate.c ${GNUHOSTDIST}/gcc/tree-phinodes.c ${GNUHOSTDIST}/gcc/ipa-reference.c ${GNUHOSTDIST}/gcc/tree-ssa-structalias.c ${GNUHOSTDIST}/gcc/lto-symtab.c ${GNUHOSTDIST}/gcc/tree-ssa-alias.h ${GNUHOSTDIST}/gcc/ipa-prop.h [cp] ${GNUHOSTDIST}/gcc/cp/rtti.c ${GNUHOSTDIST}/gcc/cp/mangle.c ${GNUHOSTDIST}/gcc/cp/name-lookup.h ${GNUHOSTDIST}/gcc/cp/name-lookup.c ${GNUHOSTDIST}/gcc/cp/cp-tree.h ${GNUHOSTDIST}/gcc/cp/decl.h ${GNUHOSTDIST}/gcc/cp/call.c ${GNUHOSTDIST}/gcc/cp/decl.c ${GNUHOSTDIST}/gcc/cp/decl2.c ${GNUHOSTDIST}/gcc/cp/pt.c ${GNUHOSTDIST}/gcc/cp/repo.c ${GNUHOSTDIST}/gcc/cp/semantics.c ${GNUHOSTDIST}/gcc/cp/tree.c ${GNUHOSTDIST}/gcc/cp/parser.c ${GNUHOSTDIST}/gcc/cp/method.c ${GNUHOSTDIST}/gcc/cp/typeck2.c ${GNUHOSTDIST}/gcc/c-common.c ${GNUHOSTDIST}/gcc/c-common.h ${GNUHOSTDIST}/gcc/c-lex.c ${GNUHOSTDIST}/gcc/c-pragma.h ${GNUHOSTDIST}/gcc/c-pragma.c ${GNUHOSTDIST}/gcc/cp/class.c ${GNUHOSTDIST}/gcc/cp/cp-objcp-common.c ${GNUHOSTDIST}/gcc/cp/cp-lang.c [lto] ${GNUHOSTDIST}/gcc/lto/lto-tree.h ${GNUHOSTDIST}/gcc/lto/lto-lang.c ${GNUHOSTDIST}/gcc/lto/lto.c [objc] ${GNUHOSTDIST}/gcc/objc/objc-act.h ${GNUHOSTDIST}/gcc/c-parser.c ${GNUHOSTDIST}/gcc/c-tree.h ${GNUHOSTDIST}/gcc/c-decl.c ${GNUHOSTDIST}/gcc/c-objc-common.c ${GNUHOSTDIST}/gcc/c-common.c ${GNUHOSTDIST}/gcc/c-common.h ${GNUHOSTDIST}/gcc/c-pragma.h ${GNUHOSTDIST}/gcc/c-pragma.c ${GNUHOSTDIST}/gcc/objc/objc-act.c [objcp] ${GNUHOSTDIST}/gcc/objcp/objcp-decl.c ${GNUHOSTDIST}/gcc/objc/objc-act.c ${GNUHOSTDIST}/gcc/objc/objc-act.h ${GNUHOSTDIST}/gcc/cp/rtti.c ${GNUHOSTDIST}/gcc/cp/mangle.c ${GNUHOSTDIST}/gcc/cp/name-lookup.h ${GNUHOSTDIST}/gcc/cp/name-lookup.c ${GNUHOSTDIST}/gcc/cp/cp-tree.h ${GNUHOSTDIST}/gcc/cp/decl.h ${GNUHOSTDIST}/gcc/cp/call.c ${GNUHOSTDIST}/gcc/cp/decl.c ${GNUHOSTDIST}/gcc/cp/decl2.c ${GNUHOSTDIST}/gcc/cp/pt.c ${GNUHOSTDIST}/gcc/cp/repo.c ${GNUHOSTDIST}/gcc/cp/semantics.c ${GNUHOSTDIST}/gcc/cp/tree.c ${GNUHOSTDIST}/gcc/cp/parser.c ${GNUHOSTDIST}/gcc/cp/method.c ${GNUHOSTDIST}/gcc/cp/typeck2.c ${GNUHOSTDIST}/gcc/c-common.c ${GNUHOSTDIST}/gcc/c-common.h ${GNUHOSTDIST}/gcc/c-lex.c ${GNUHOSTDIST}/gcc/c-pragma.h ${GNUHOSTDIST}/gcc/c-pragma.c ${GNUHOSTDIST}/gcc/cp/cp-objcp-common.c [c] ${GNUHOSTDIST}/gcc/c-lang.c ${GNUHOSTDIST}/gcc/c-tree.h ${GNUHOSTDIST}/gcc/c-decl.c ${GNUHOSTDIST}/gcc/c-common.c ${GNUHOSTDIST}/gcc/c-common.h ${GNUHOSTDIST}/gcc/c-pragma.h ${GNUHOSTDIST}/gcc/c-pragma.c ${GNUHOSTDIST}/gcc/c-objc-common.c ${GNUHOSTDIST}/gcc/c-parser.c ${GNUHOSTDIST}/gcc/c-lang.h +G_GTFILES=${GNUHOSTDIST}/gcc/../libcpp/include/line-map.h ${GNUHOSTDIST}/gcc/../libcpp/include/cpplib.h ${GNUHOSTDIST}/gcc/../libcpp/include/cpp-id-data.h ${GNUHOSTDIST}/gcc/input.h ${GNUHOSTDIST}/gcc/coretypes.h auto-host.h ${GNUHOSTDIST}/gcc/../include/ansidecl.h options.h ${GNUHOSTDIST}/gcc/config/dbxelf.h ${GNUHOSTDIST}/gcc/config/elfos.h ${GNUHOSTDIST}/gcc/config/arm/unknown-elf.h ${GNUHOSTDIST}/gcc/config/arm/elf.h ${GNUHOSTDIST}/gcc/config/arm/aout.h ${GNUHOSTDIST}/gcc/config/arm/arm.h ${GNUHOSTDIST}/gcc/config/arm/bpabi.h ${GNUHOSTDIST}/gcc/config/arm/eabi.h ${GNUHOSTDIST}/gcc/config/newlib-stdint.h ${GNUHOSTDIST}/gcc/config/minix-spec.h ${GNUHOSTDIST}/gcc/config/arm/minix.h ${GNUHOSTDIST}/gcc/config/minix.h ${GNUHOSTDIST}/gcc/defaults.h ${GNUHOSTDIST}/gcc/../include/hashtab.h ${GNUHOSTDIST}/gcc/../include/splay-tree.h ${GNUHOSTDIST}/gcc/bitmap.h ${GNUHOSTDIST}/gcc/alias.h ${GNUHOSTDIST}/gcc/coverage.c ${GNUHOSTDIST}/gcc/rtl.h ${GNUHOSTDIST}/gcc/vecprim.h ${GNUHOSTDIST}/gcc/optabs.h ${GNUHOSTDIST}/gcc/tree.h ${GNUHOSTDIST}/gcc/varray.h ${GNUHOSTDIST}/gcc/libfuncs.h ${GNUHOSTDIST}/gcc/../libcpp/include/symtab.h ${GNUHOSTDIST}/gcc/../include/obstack.h ${GNUHOSTDIST}/gcc/real.h ${GNUHOSTDIST}/gcc/function.h ${GNUHOSTDIST}/gcc/insn-addr.h ${GNUHOSTDIST}/gcc/hwint.h ${GNUHOSTDIST}/gcc/fixed-value.h ${GNUHOSTDIST}/gcc/ipa-reference.h ${GNUHOSTDIST}/gcc/output.h ${GNUHOSTDIST}/gcc/cfgloop.h ${GNUHOSTDIST}/gcc/cselib.h ${GNUHOSTDIST}/gcc/basic-block.h ${GNUHOSTDIST}/gcc/cgraph.h ${GNUHOSTDIST}/gcc/reload.h ${GNUHOSTDIST}/gcc/caller-save.c ${GNUHOSTDIST}/gcc/alias.c ${GNUHOSTDIST}/gcc/bitmap.c ${GNUHOSTDIST}/gcc/cselib.c ${GNUHOSTDIST}/gcc/cgraph.c ${GNUHOSTDIST}/gcc/ipa-prop.c ${GNUHOSTDIST}/gcc/ipa-cp.c ${GNUHOSTDIST}/gcc/ipa-inline.c ${GNUHOSTDIST}/gcc/matrix-reorg.c ${GNUHOSTDIST}/gcc/dbxout.c ${GNUHOSTDIST}/gcc/ipa-struct-reorg.c ${GNUHOSTDIST}/gcc/dwarf2out.c ${GNUHOSTDIST}/gcc/dwarf2asm.c ${GNUHOSTDIST}/gcc/tree-vect-generic.c ${GNUHOSTDIST}/gcc/dojump.c ${GNUHOSTDIST}/gcc/emit-rtl.c ${GNUHOSTDIST}/gcc/except.h ${GNUHOSTDIST}/gcc/explow.c ${GNUHOSTDIST}/gcc/expr.c ${GNUHOSTDIST}/gcc/expr.h ${GNUHOSTDIST}/gcc/function.c ${GNUHOSTDIST}/gcc/except.c ${GNUHOSTDIST}/gcc/gcse.c ${GNUHOSTDIST}/gcc/integrate.c ${GNUHOSTDIST}/gcc/lists.c ${GNUHOSTDIST}/gcc/optabs.c ${GNUHOSTDIST}/gcc/profile.c ${GNUHOSTDIST}/gcc/reginfo.c ${GNUHOSTDIST}/gcc/mcf.c ${GNUHOSTDIST}/gcc/reg-stack.c ${GNUHOSTDIST}/gcc/cfglayout.c ${GNUHOSTDIST}/gcc/cfglayout.h ${GNUHOSTDIST}/gcc/sdbout.c ${GNUHOSTDIST}/gcc/stor-layout.c ${GNUHOSTDIST}/gcc/stringpool.c ${GNUHOSTDIST}/gcc/tree.c ${GNUHOSTDIST}/gcc/varasm.c ${GNUHOSTDIST}/gcc/gimple.h ${GNUHOSTDIST}/gcc/gimple.c ${GNUHOSTDIST}/gcc/tree-mudflap.c ${GNUHOSTDIST}/gcc/tree-flow.h ${GNUHOSTDIST}/gcc/tree-ssanames.c ${GNUHOSTDIST}/gcc/tree-eh.c ${GNUHOSTDIST}/gcc/tree-ssa-address.c ${GNUHOSTDIST}/gcc/tree-cfg.c ${GNUHOSTDIST}/gcc/tree-dfa.c ${GNUHOSTDIST}/gcc/tree-iterator.c ${GNUHOSTDIST}/gcc/gimplify.c ${GNUHOSTDIST}/gcc/tree-chrec.h ${GNUHOSTDIST}/gcc/tree-scalar-evolution.c ${GNUHOSTDIST}/gcc/tree-ssa-operands.h ${GNUHOSTDIST}/gcc/tree-profile.c ${GNUHOSTDIST}/gcc/tree-nested.c ${GNUHOSTDIST}/gcc/varpool.c ${GNUHOSTDIST}/gcc/tree-parloops.c ${GNUHOSTDIST}/gcc/omp-low.c \ ${GNUHOSTDIST}/gcc/targhooks.c ${GNUHOSTDIST}/gcc/config/arm/arm.c ${GNUHOSTDIST}/gcc/passes.c ${GNUHOSTDIST}/gcc/cgraphunit.c ${GNUHOSTDIST}/gcc/tree-ssa-propagate.c ${GNUHOSTDIST}/gcc/tree-phinodes.c ${GNUHOSTDIST}/gcc/ipa-reference.c ${GNUHOSTDIST}/gcc/tree-ssa-structalias.c ${GNUHOSTDIST}/gcc/lto-symtab.c ${GNUHOSTDIST}/gcc/tree-ssa-alias.h ${GNUHOSTDIST}/gcc/ipa-prop.h [cp] ${GNUHOSTDIST}/gcc/cp/rtti.c ${GNUHOSTDIST}/gcc/cp/mangle.c ${GNUHOSTDIST}/gcc/cp/name-lookup.h ${GNUHOSTDIST}/gcc/cp/name-lookup.c ${GNUHOSTDIST}/gcc/cp/cp-tree.h ${GNUHOSTDIST}/gcc/cp/decl.h ${GNUHOSTDIST}/gcc/cp/call.c ${GNUHOSTDIST}/gcc/cp/decl.c ${GNUHOSTDIST}/gcc/cp/decl2.c ${GNUHOSTDIST}/gcc/cp/pt.c ${GNUHOSTDIST}/gcc/cp/repo.c ${GNUHOSTDIST}/gcc/cp/semantics.c ${GNUHOSTDIST}/gcc/cp/tree.c ${GNUHOSTDIST}/gcc/cp/parser.c ${GNUHOSTDIST}/gcc/cp/method.c ${GNUHOSTDIST}/gcc/cp/typeck2.c ${GNUHOSTDIST}/gcc/c-common.c ${GNUHOSTDIST}/gcc/c-common.h ${GNUHOSTDIST}/gcc/c-lex.c ${GNUHOSTDIST}/gcc/c-pragma.h ${GNUHOSTDIST}/gcc/c-pragma.c ${GNUHOSTDIST}/gcc/cp/class.c ${GNUHOSTDIST}/gcc/cp/cp-objcp-common.c ${GNUHOSTDIST}/gcc/cp/cp-lang.c [lto] ${GNUHOSTDIST}/gcc/lto/lto-tree.h ${GNUHOSTDIST}/gcc/lto/lto-lang.c ${GNUHOSTDIST}/gcc/lto/lto.c [objc] ${GNUHOSTDIST}/gcc/objc/objc-act.h ${GNUHOSTDIST}/gcc/c-parser.c ${GNUHOSTDIST}/gcc/c-tree.h ${GNUHOSTDIST}/gcc/c-decl.c ${GNUHOSTDIST}/gcc/c-objc-common.c ${GNUHOSTDIST}/gcc/c-common.c ${GNUHOSTDIST}/gcc/c-common.h ${GNUHOSTDIST}/gcc/c-pragma.h ${GNUHOSTDIST}/gcc/c-pragma.c ${GNUHOSTDIST}/gcc/objc/objc-act.c [objcp] ${GNUHOSTDIST}/gcc/objcp/objcp-decl.c ${GNUHOSTDIST}/gcc/objc/objc-act.c ${GNUHOSTDIST}/gcc/objc/objc-act.h ${GNUHOSTDIST}/gcc/cp/rtti.c ${GNUHOSTDIST}/gcc/cp/mangle.c ${GNUHOSTDIST}/gcc/cp/name-lookup.h ${GNUHOSTDIST}/gcc/cp/name-lookup.c ${GNUHOSTDIST}/gcc/cp/cp-tree.h ${GNUHOSTDIST}/gcc/cp/decl.h ${GNUHOSTDIST}/gcc/cp/call.c ${GNUHOSTDIST}/gcc/cp/decl.c ${GNUHOSTDIST}/gcc/cp/decl2.c ${GNUHOSTDIST}/gcc/cp/pt.c ${GNUHOSTDIST}/gcc/cp/repo.c ${GNUHOSTDIST}/gcc/cp/semantics.c ${GNUHOSTDIST}/gcc/cp/tree.c ${GNUHOSTDIST}/gcc/cp/parser.c ${GNUHOSTDIST}/gcc/cp/method.c ${GNUHOSTDIST}/gcc/cp/typeck2.c ${GNUHOSTDIST}/gcc/c-common.c ${GNUHOSTDIST}/gcc/c-common.h ${GNUHOSTDIST}/gcc/c-lex.c ${GNUHOSTDIST}/gcc/c-pragma.h ${GNUHOSTDIST}/gcc/c-pragma.c ${GNUHOSTDIST}/gcc/cp/cp-objcp-common.c [c] ${GNUHOSTDIST}/gcc/c-lang.c ${GNUHOSTDIST}/gcc/c-tree.h ${GNUHOSTDIST}/gcc/c-decl.c ${GNUHOSTDIST}/gcc/c-common.c ${GNUHOSTDIST}/gcc/c-common.h ${GNUHOSTDIST}/gcc/c-pragma.h ${GNUHOSTDIST}/gcc/c-pragma.c ${GNUHOSTDIST}/gcc/c-objc-common.c ${GNUHOSTDIST}/gcc/c-parser.c ${GNUHOSTDIST}/gcc/c-lang.h G_GTFILES_LANG_DIR_NAMES= -G_tm_defines=NETBSD_ENABLE_PTHREADS TARGET_DEFAULT_FLOAT_ABI=ARM_FLOAT_ABI_HARD +G_tm_defines= G_host_xm_file= G_host_xm_defines= G_tm_p_file= -G_target_cpu_default=TARGET_CPU_arm1176jzfs -G_TM_H=tm.h options.h ${GNUHOSTDIST}/gcc/config/dbxelf.h ${GNUHOSTDIST}/gcc/config/elfos.h ${GNUHOSTDIST}/gcc/config/netbsd.h ${GNUHOSTDIST}/gcc/config/netbsd-elf.h ${GNUHOSTDIST}/gcc/config/arm/elf.h ${GNUHOSTDIST}/gcc/config/arm/aout.h ${GNUHOSTDIST}/gcc/config/arm/arm.h ${GNUHOSTDIST}/gcc/config/arm/bpabi.h ${GNUHOSTDIST}/gcc/config/arm/netbsd-elf.h ${GNUHOSTDIST}/gcc/config/arm/netbsd-eabi.h ${GNUHOSTDIST}/gcc/defaults.h insn-constants.h insn-flags.h options.h -G_ALL_OPT_FILES=${GNUHOSTDIST}/gcc/lto/lang.opt ${GNUHOSTDIST}/gcc/c.opt ${GNUHOSTDIST}/gcc/common.opt ${GNUHOSTDIST}/gcc/config/arm/arm.opt -G_tm_file_list=options.h ${GNUHOSTDIST}/gcc/config/dbxelf.h ${GNUHOSTDIST}/gcc/config/elfos.h ${GNUHOSTDIST}/gcc/config/netbsd.h ${GNUHOSTDIST}/gcc/config/netbsd-elf.h ${GNUHOSTDIST}/gcc/config/arm/elf.h ${GNUHOSTDIST}/gcc/config/arm/aout.h ${GNUHOSTDIST}/gcc/config/arm/arm.h ${GNUHOSTDIST}/gcc/config/arm/bpabi.h ${GNUHOSTDIST}/gcc/config/arm/netbsd-elf.h ${GNUHOSTDIST}/gcc/config/arm/netbsd-eabi.h ${GNUHOSTDIST}/gcc/defaults.h +G_target_cpu_default=TARGET_CPU_generic +G_TM_H=tm.h options.h ${GNUHOSTDIST}/gcc/config/dbxelf.h ${GNUHOSTDIST}/gcc/config/elfos.h ${GNUHOSTDIST}/gcc/config/arm/unknown-elf.h ${GNUHOSTDIST}/gcc/config/arm/elf.h ${GNUHOSTDIST}/gcc/config/arm/aout.h ${GNUHOSTDIST}/gcc/config/arm/arm.h ${GNUHOSTDIST}/gcc/config/arm/bpabi.h ${GNUHOSTDIST}/gcc/config/arm/eabi.h ${GNUHOSTDIST}/gcc/config/newlib-stdint.h ${GNUHOSTDIST}/gcc/config/minix-spec.h ${GNUHOSTDIST}/gcc/config/arm/minix.h ${GNUHOSTDIST}/gcc/config/minix.h ${GNUHOSTDIST}/gcc/defaults.h insn-constants.h insn-flags.h options.h +G_ALL_OPT_FILES=${GNUHOSTDIST}/gcc/lto/lang.opt ${GNUHOSTDIST}/gcc/c.opt ${GNUHOSTDIST}/gcc/common.opt ${GNUHOSTDIST}/gcc/config/arm/arm.opt ${GNUHOSTDIST}/gcc/config/arm/eabi.opt +G_tm_file_list=options.h ${GNUHOSTDIST}/gcc/config/dbxelf.h ${GNUHOSTDIST}/gcc/config/elfos.h ${GNUHOSTDIST}/gcc/config/arm/unknown-elf.h ${GNUHOSTDIST}/gcc/config/arm/elf.h ${GNUHOSTDIST}/gcc/config/arm/aout.h ${GNUHOSTDIST}/gcc/config/arm/arm.h ${GNUHOSTDIST}/gcc/config/arm/bpabi.h ${GNUHOSTDIST}/gcc/config/arm/eabi.h ${GNUHOSTDIST}/gcc/config/newlib-stdint.h ${GNUHOSTDIST}/gcc/config/minix-spec.h ${GNUHOSTDIST}/gcc/config/arm/minix.h ${GNUHOSTDIST}/gcc/config/minix.h ${GNUHOSTDIST}/gcc/defaults.h G_build_xm_include_list=auto-build.h ansidecl.h G_lang_specs_files=${GNUHOSTDIST}/gcc/cp/lang-specs.h ${GNUHOSTDIST}/gcc/lto/lang-specs.h ${GNUHOSTDIST}/gcc/objc/lang-specs.h G_tm_p_include_list=config/arm/arm-protos.h tm-preds.h diff --git a/external/gpl3/gcc/usr.bin/gcc/arch/earmv6hf/gtyp-input.list b/external/gpl3/gcc/usr.bin/gcc/arch/earmv6hf/gtyp-input.list index 21f9cc4dc..4d6eb2f78 100644 --- a/external/gpl3/gcc/usr.bin/gcc/arch/earmv6hf/gtyp-input.list +++ b/external/gpl3/gcc/usr.bin/gcc/arch/earmv6hf/gtyp-input.list @@ -8,14 +8,16 @@ SRCDIR/gcc/../include/ansidecl.h options.h SRCDIR/gcc/config/dbxelf.h SRCDIR/gcc/config/elfos.h -SRCDIR/gcc/config/netbsd.h -SRCDIR/gcc/config/netbsd-elf.h +SRCDIR/gcc/config/arm/unknown-elf.h SRCDIR/gcc/config/arm/elf.h SRCDIR/gcc/config/arm/aout.h SRCDIR/gcc/config/arm/arm.h SRCDIR/gcc/config/arm/bpabi.h -SRCDIR/gcc/config/arm/netbsd-elf.h -SRCDIR/gcc/config/arm/netbsd-eabi.h +SRCDIR/gcc/config/arm/eabi.h +SRCDIR/gcc/config/newlib-stdint.h +SRCDIR/gcc/config/minix-spec.h +SRCDIR/gcc/config/arm/minix.h +SRCDIR/gcc/config/minix.h SRCDIR/gcc/defaults.h SRCDIR/gcc/../include/hashtab.h SRCDIR/gcc/../include/splay-tree.h diff --git a/external/gpl3/gcc/usr.bin/gcc/arch/earmv6hf/multilib.h b/external/gpl3/gcc/usr.bin/gcc/arch/earmv6hf/multilib.h index 6f4a51325..bb92819aa 100644 --- a/external/gpl3/gcc/usr.bin/gcc/arch/earmv6hf/multilib.h +++ b/external/gpl3/gcc/usr.bin/gcc/arch/earmv6hf/multilib.h @@ -3,21 +3,11 @@ /* Generated from: NetBSD: mknative.common,v 1.9 2007/02/05 18:26:01 apb Exp */ static const char *const multilib_raw[] = { -". !mabi=aapcs-linux !mabi=aapcs !mabi=atpcs !mabi=apcs-gnu !mabi=iwmmxt;", -".:. mabi=aapcs-linux !mabi=aapcs !mabi=atpcs !mabi=apcs-gnu !mabi=iwmmxt;", -".:../lib/aapcs !mabi=aapcs-linux mabi=aapcs !mabi=atpcs !mabi=apcs-gnu !mabi=iwmmxt;", -".:../lib/atpcs !mabi=aapcs-linux !mabi=aapcs mabi=atpcs !mabi=apcs-gnu !mabi=iwmmxt;", -".:../lib/oabi !mabi=aapcs-linux !mabi=aapcs !mabi=atpcs mabi=apcs-gnu !mabi=iwmmxt;", -".:../lib/iwmmxt !mabi=aapcs-linux !mabi=aapcs !mabi=atpcs !mabi=apcs-gnu mabi=iwmmxt;", +". ;", NULL }; static const char *const multilib_matches_raw[] = { -"mabi=aapcs-linux mabi=aapcs-linux;", -"mabi=aapcs mabi=aapcs;", -"mabi=atpcs mabi=atpcs;", -"mabi=apcs-gnu mabi=apcs-gnu;", -"mabi=iwmmxt mabi=iwmmxt;", NULL }; @@ -27,6 +17,4 @@ static const char *const multilib_exclusions_raw[] = { NULL }; -static const char *multilib_options = "mabi=aapcs-linux/mabi=aapcs/mabi=atpcs/mabi=apcs-gnu/mabi=iwmmxt"; - -#define DISABLE_MULTILIB 1 +static const char *multilib_options = ""; diff --git a/external/gpl3/gcc/usr.bin/gcc/arch/earmv6hf/tm.h b/external/gpl3/gcc/usr.bin/gcc/arch/earmv6hf/tm.h index 7c849d35d..b4ba71399 100644 --- a/external/gpl3/gcc/usr.bin/gcc/arch/earmv6hf/tm.h +++ b/external/gpl3/gcc/usr.bin/gcc/arch/earmv6hf/tm.h @@ -4,25 +4,21 @@ #ifndef GCC_TM_H #define GCC_TM_H -#define TARGET_CPU_DEFAULT (TARGET_CPU_arm1176jzfs) -#ifndef NETBSD_ENABLE_PTHREADS -# define NETBSD_ENABLE_PTHREADS -#endif -#ifndef TARGET_DEFAULT_FLOAT_ABI -# define TARGET_DEFAULT_FLOAT_ABI ARM_FLOAT_ABI_HARD -#endif +#define TARGET_CPU_DEFAULT (TARGET_CPU_generic) #ifdef IN_GCC # include "options.h" # include "config/dbxelf.h" # include "config/elfos.h" -# include "config/netbsd.h" -# include "config/netbsd-elf.h" +# include "config/arm/unknown-elf.h" # include "config/arm/elf.h" # include "config/arm/aout.h" # include "config/arm/arm.h" # include "config/arm/bpabi.h" -# include "config/arm/netbsd-elf.h" -# include "config/arm/netbsd-eabi.h" +# include "config/arm/eabi.h" +# include "config/newlib-stdint.h" +# include "config/minix-spec.h" +# include "config/arm/minix.h" +# include "config/minix.h" # include "defaults.h" #endif #if defined IN_GCC && !defined GENERATOR_FILE && !defined USED_FOR_TARGET diff --git a/external/gpl3/gcc/usr.bin/libcpp/arch/earmv6hf/config.h b/external/gpl3/gcc/usr.bin/libcpp/arch/earmv6hf/config.h index 4c67a698c..02f76dda2 100644 --- a/external/gpl3/gcc/usr.bin/libcpp/arch/earmv6hf/config.h +++ b/external/gpl3/gcc/usr.bin/libcpp/arch/earmv6hf/config.h @@ -18,7 +18,7 @@ /* Define to 1 if translation of program messages to the user's native language is requested. */ -#define ENABLE_NLS 1 +/* #undef ENABLE_NLS */ /* Define to 1 if you have `alloca', as a function or macro. */ #define HAVE_ALLOCA 1 diff --git a/lib/Makefile b/lib/Makefile index aa3dce34e..012fec7bc 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -67,7 +67,7 @@ SUBDIR+= ../minix/lib/libhgfs \ ../minix/lib/libvirtio .endif -.if (${MACHINE_ARCH} == "earm") +.if ( (${MACHINE_ARCH} == "earm") || (${MACHINE_ARCH} == "earmv6hf") ) SUBDIR+= ../minix/lib/libclkconf \ ../minix/lib/libgpio \ ../minix/lib/libi2cdriver @@ -97,7 +97,7 @@ SUBDIR+= \ .if (${MACHINE_CPU} == "arm") LIBC_MACHINE_ARCH?=${MACHINE_ARCH} -.if empty(LIBC_MACHINE_ARCH:M*hf*) +.if ( (empty(LIBC_MACHINE_ARCH:M*hf*) ) || (${MACHINE_ARCH} == "earmv6hf")) SUBDIR+= libc_vfp .endif .endif diff --git a/lib/libc/arch/arm/Makefile.inc b/lib/libc/arch/arm/Makefile.inc index bef93afc4..5e44ceb66 100644 --- a/lib/libc/arch/arm/Makefile.inc +++ b/lib/libc/arch/arm/Makefile.inc @@ -6,7 +6,7 @@ SRCS+= __aeabi_read_tp.S __sigaction14_sigtramp.c __sigtramp2.S .endif -.if empty(LIBC_MACHINE_ARCH:Mearmv7*) +.if empty(LIBC_MACHINE_ARCH:Mearmv*) AFLAGS+= -marm .endif diff --git a/minix/drivers/bus/Makefile b/minix/drivers/bus/Makefile index e7c956d53..3989f1854 100644 --- a/minix/drivers/bus/Makefile +++ b/minix/drivers/bus/Makefile @@ -5,7 +5,7 @@ SUBDIR+= ti1225 . endif # ${MACHINE_ARCH} == "i386" -. if ${MACHINE_ARCH} == "earm" +. if ((${MACHINE_ARCH} == "earm") || (${MACHINE_ARCH} == "earmv6hf") ) SUBDIR+= i2c . endif # ${MACHINE_ARCH} == "earm" .endif # ${MKIMAGEONLY} == "no" diff --git a/minix/drivers/bus/i2c/arch/earmv6hf/Makefile.inc b/minix/drivers/bus/i2c/arch/earmv6hf/Makefile.inc new file mode 100644 index 000000000..497fd24c3 --- /dev/null +++ b/minix/drivers/bus/i2c/arch/earmv6hf/Makefile.inc @@ -0,0 +1,7 @@ +# Makefile for arch-dependent i2c code +.include + +HERE=${.CURDIR}/arch/${MACHINE_ARCH} +.PATH: ${HERE} + +SRCS += omap_i2c.c omap_i2c.h omap_i2c_registers.h diff --git a/minix/drivers/bus/i2c/arch/earmv6hf/omap_i2c.c b/minix/drivers/bus/i2c/arch/earmv6hf/omap_i2c.c new file mode 100644 index 000000000..cc571c509 --- /dev/null +++ b/minix/drivers/bus/i2c/arch/earmv6hf/omap_i2c.c @@ -0,0 +1,876 @@ +/* + * This file implements support for i2c on the BeagleBone and BeagleBoard-xM + */ + +/* kernel headers */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* device headers */ +#include + +/* system headers */ +#include +#include +#include + +/* usr headers */ +#include +#include +#include + +/* local headers */ +#include "omap_i2c.h" + +/* + * defines the set of register + * + * Warning: always use the 16-bit variants of read/write/set from mmio.h + * to access these registers. The DM37XX TRM Section 17.6 warns that 32-bit + * accesses can corrupt the register contents. + */ +typedef struct omap_i2c_registers +{ + vir_bytes I2C_REVNB_LO; /* AM335X Only */ + vir_bytes I2C_REVNB_HI; /* AM335X Only */ + vir_bytes I2C_REV; /* DM37XX Only */ + vir_bytes I2C_IE; /* DM37XX Only */ + vir_bytes I2C_STAT; /* DM37XX Only */ + vir_bytes I2C_SYSC; + vir_bytes I2C_IRQSTATUS_RAW; /* AM335X Only */ + vir_bytes I2C_IRQSTATUS; /* AM335X Only */ + vir_bytes I2C_IRQENABLE_SET; /* AM335X Only */ + vir_bytes I2C_IRQENABLE_CLR; /* AM335X Only */ + vir_bytes I2C_WE; + vir_bytes I2C_DMARXENABLE_SET; /* AM335X Only */ + vir_bytes I2C_DMATXENABLE_SET; /* AM335X Only */ + vir_bytes I2C_DMARXENABLE_CLR; /* AM335X Only */ + vir_bytes I2C_DMATXENABLE_CLR; /* AM335X Only */ + vir_bytes I2C_DMARXWAKE_EN; /* AM335X Only */ + vir_bytes I2C_DMATXWAKE_EN; /* AM335X Only */ + vir_bytes I2C_SYSS; + vir_bytes I2C_BUF; + vir_bytes I2C_CNT; + vir_bytes I2C_DATA; + vir_bytes I2C_CON; + vir_bytes I2C_OA; /* AM335X Only */ + vir_bytes I2C_OA0; /* DM37XX Only */ + vir_bytes I2C_SA; + vir_bytes I2C_PSC; + vir_bytes I2C_SCLL; + vir_bytes I2C_SCLH; + vir_bytes I2C_SYSTEST; + vir_bytes I2C_BUFSTAT; + vir_bytes I2C_OA1; + vir_bytes I2C_OA2; + vir_bytes I2C_OA3; + vir_bytes I2C_ACTOA; + vir_bytes I2C_SBLOCK; +} omap_i2c_regs_t; + +/* generic definition an i2c bus */ + +typedef struct omap_i2c_bus +{ + enum bus_types + { AM335X_I2C_BUS, DM37XX_I2C_BUS} bus_type; + phys_bytes mr_base; + phys_bytes mr_size; + vir_bytes mapped_addr; + omap_i2c_regs_t *regs; + uint32_t functional_clock; + uint32_t module_clock; + uint32_t bus_speed; + uint16_t major; + uint16_t minor; + int irq; + int irq_hook_id; + int irq_hook_kernel_id; +} omap_i2c_bus_t; + +/* Define the registers for each chip */ + +static omap_i2c_regs_t am335x_i2c_regs = { + .I2C_REVNB_LO = AM335X_I2C_REVNB_LO, + .I2C_REVNB_HI = AM335X_I2C_REVNB_HI, + .I2C_SYSC = AM335X_I2C_SYSC, + .I2C_IRQSTATUS_RAW = AM335X_I2C_IRQSTATUS_RAW, + .I2C_IRQSTATUS = AM335X_I2C_IRQSTATUS, + .I2C_IRQENABLE_SET = AM335X_I2C_IRQENABLE_SET, + .I2C_IRQENABLE_CLR = AM335X_I2C_IRQENABLE_CLR, + .I2C_WE = AM335X_I2C_WE, + .I2C_DMARXENABLE_SET = AM335X_I2C_DMARXENABLE_SET, + .I2C_DMATXENABLE_SET = AM335X_I2C_DMATXENABLE_SET, + .I2C_DMARXENABLE_CLR = AM335X_I2C_DMARXENABLE_CLR, + .I2C_DMATXENABLE_CLR = AM335X_I2C_DMATXENABLE_CLR, + .I2C_DMARXWAKE_EN = AM335X_I2C_DMARXWAKE_EN, + .I2C_DMATXWAKE_EN = AM335X_I2C_DMATXWAKE_EN, + .I2C_SYSS = AM335X_I2C_SYSS, + .I2C_BUF = AM335X_I2C_BUF, + .I2C_CNT = AM335X_I2C_CNT, + .I2C_DATA = AM335X_I2C_DATA, + .I2C_CON = AM335X_I2C_CON, + .I2C_OA = AM335X_I2C_OA, + .I2C_SA = AM335X_I2C_SA, + .I2C_PSC = AM335X_I2C_PSC, + .I2C_SCLL = AM335X_I2C_SCLL, + .I2C_SCLH = AM335X_I2C_SCLH, + .I2C_SYSTEST = AM335X_I2C_SYSTEST, + .I2C_BUFSTAT = AM335X_I2C_BUFSTAT, + .I2C_OA1 = AM335X_I2C_OA1, + .I2C_OA2 = AM335X_I2C_OA2, + .I2C_OA3 = AM335X_I2C_OA3, + .I2C_ACTOA = AM335X_I2C_ACTOA, + .I2C_SBLOCK = AM335X_I2C_SBLOCK +}; + +static omap_i2c_regs_t dm37xx_i2c_regs = { + .I2C_REV = DM37XX_I2C_REV, + .I2C_IE = DM37XX_I2C_IE, + .I2C_STAT = DM37XX_I2C_STAT, + .I2C_WE = DM37XX_I2C_WE, + .I2C_SYSS = DM37XX_I2C_SYSS, + .I2C_BUF = DM37XX_I2C_BUF, + .I2C_CNT = DM37XX_I2C_CNT, + .I2C_DATA = DM37XX_I2C_DATA, + .I2C_SYSC = DM37XX_I2C_SYSC, + .I2C_CON = DM37XX_I2C_CON, + .I2C_OA0 = DM37XX_I2C_OA0, + .I2C_SA = DM37XX_I2C_SA, + .I2C_PSC = DM37XX_I2C_PSC, + .I2C_SCLL = DM37XX_I2C_SCLL, + .I2C_SCLH = DM37XX_I2C_SCLH, + .I2C_SYSTEST = DM37XX_I2C_SYSTEST, + .I2C_BUFSTAT = DM37XX_I2C_BUFSTAT, + .I2C_OA1 = DM37XX_I2C_OA1, + .I2C_OA2 = DM37XX_I2C_OA2, + .I2C_OA3 = DM37XX_I2C_OA3, + .I2C_ACTOA = DM37XX_I2C_ACTOA, + .I2C_SBLOCK = DM37XX_I2C_SBLOCK +}; + +/* Define the buses available on each chip */ + +static omap_i2c_bus_t am335x_i2c_buses[] = { + {AM335X_I2C_BUS, AM335X_I2C0_BASE, AM335X_I2C0_SIZE, 0, &am335x_i2c_regs, + AM335X_FUNCTIONAL_CLOCK, AM335X_MODULE_CLOCK, + BUS_SPEED_400KHz, AM335X_REV_MAJOR, AM335X_REV_MINOR, + AM335X_I2C0_IRQ, 1, 1}, + {AM335X_I2C_BUS, AM335X_I2C1_BASE, AM335X_I2C1_SIZE, 0, &am335x_i2c_regs, + AM335X_FUNCTIONAL_CLOCK, AM335X_MODULE_CLOCK, + BUS_SPEED_100KHz, AM335X_REV_MAJOR, AM335X_REV_MINOR, + AM335X_I2C1_IRQ, 2, 3}, + {AM335X_I2C_BUS, AM335X_I2C2_BASE, AM335X_I2C2_SIZE, 0, &am335x_i2c_regs, + AM335X_FUNCTIONAL_CLOCK, AM335X_MODULE_CLOCK, + BUS_SPEED_100KHz, AM335X_REV_MAJOR, AM335X_REV_MINOR, + AM335X_I2C2_IRQ, 3, 3} +}; + +#define AM335X_OMAP_NBUSES (sizeof(am335x_i2c_buses) / sizeof(omap_i2c_bus_t)) + +static omap_i2c_bus_t dm37xx_i2c_buses[] = { + {DM37XX_I2C_BUS, DM37XX_I2C0_BASE, DM37XX_I2C0_SIZE, 0, &dm37xx_i2c_regs, + DM37XX_FUNCTIONAL_CLOCK, DM37XX_MODULE_CLOCK, + BUS_SPEED_100KHz, DM37XX_REV_MAJOR, DM37XX_REV_MINOR, + DM37XX_I2C0_IRQ, 1, 1}, + {DM37XX_I2C_BUS, DM37XX_I2C1_BASE, DM37XX_I2C1_SIZE, 0, &dm37xx_i2c_regs, + DM37XX_FUNCTIONAL_CLOCK, DM37XX_MODULE_CLOCK, + BUS_SPEED_100KHz, DM37XX_REV_MAJOR, DM37XX_REV_MINOR, + DM37XX_I2C1_IRQ, 2, 2}, + {DM37XX_I2C_BUS, DM37XX_I2C2_BASE, DM37XX_I2C2_SIZE, 0, &dm37xx_i2c_regs, + DM37XX_FUNCTIONAL_CLOCK, DM37XX_MODULE_CLOCK, + BUS_SPEED_100KHz, DM37XX_REV_MAJOR, DM37XX_REV_MINOR, + DM37XX_I2C2_IRQ, 3, 3} +}; + +#define DM37XX_OMAP_NBUSES (sizeof(dm37xx_i2c_buses) / sizeof(omap_i2c_bus_t)) + +/* Globals */ + +static omap_i2c_bus_t *omap_i2c_buses; /* all available buses for this SoC */ +static omap_i2c_bus_t *omap_i2c_bus; /* the bus selected at start-up */ +static int omap_i2c_nbuses; /* number of buses supported by SoC */ + +/* logging - use with log_warn(), log_info(), log_debug(), log_trace() */ +static struct log log = { + .name = "i2c", + .log_level = LEVEL_INFO, + .log_func = default_log +}; + +/* Local Function Prototypes */ + +/* Implementation of Generic I2C Interface using Bus Specific Code */ +static int omap_i2c_process(minix_i2c_ioctl_exec_t * m); + +/* Bus Specific Code */ +static void omap_i2c_flush(void); +static uint16_t omap_i2c_poll(uint16_t mask); +static int omap_i2c_bus_is_free(void); +static int omap_i2c_soft_reset(void); +static void omap_i2c_bus_init(void); +static void omap_i2c_padconf(int i2c_bus_id); +static void omap_i2c_clkconf(int i2c_bus_id); +static void omap_i2c_intr_enable(void); +static uint16_t omap_i2c_read_status(void); +static void omap_i2c_write_status(uint16_t mask); +static int omap_i2c_read(i2c_addr_t addr, uint8_t * buf, size_t buflen, + int dostop); +static int omap_i2c_write(i2c_addr_t addr, const uint8_t * buf, size_t buflen, + int dostop); + +/* + * Performs the action in minix_i2c_ioctl_exec_t. + */ +static int +omap_i2c_process(minix_i2c_ioctl_exec_t * ioctl_exec) +{ + int r; + + /* + * Zero data bytes transfers are not allowed. The controller treats + * I2C_CNT register value of 0x0 as 65536. This is true for both the + * am335x and dm37xx. Full details in the TRM on the I2C_CNT page. + */ + if (ioctl_exec->iie_buflen == 0) { + return EINVAL; + } + + omap_i2c_flush(); /* clear any garbage in the fifo */ + + /* Check bus busy flag before using the bus */ + r = omap_i2c_bus_is_free(); + if (r == 0) { + log_warn(&log, "Bus is busy\n"); + return EBUSY; + } + + if (ioctl_exec->iie_cmdlen > 0) { + r = omap_i2c_write(ioctl_exec->iie_addr, ioctl_exec->iie_cmd, + ioctl_exec->iie_cmdlen, + !(I2C_OP_READ_P(ioctl_exec->iie_op))); + if (r != OK) { + omap_i2c_soft_reset(); + omap_i2c_bus_init(); + return r; + } + } + + if (I2C_OP_READ_P(ioctl_exec->iie_op)) { + r = omap_i2c_read(ioctl_exec->iie_addr, ioctl_exec->iie_buf, + ioctl_exec->iie_buflen, I2C_OP_STOP_P(ioctl_exec->iie_op)); + } else { + r = omap_i2c_write(ioctl_exec->iie_addr, ioctl_exec->iie_buf, + ioctl_exec->iie_buflen, I2C_OP_STOP_P(ioctl_exec->iie_op)); + } + + if (r != OK) { + omap_i2c_soft_reset(); + omap_i2c_bus_init(); + return r; + } + + return OK; +} + +/* + * Drain the incoming FIFO. + * + * Usually called to clear any garbage that may be in the buffer before + * doing a read. + */ +static void +omap_i2c_flush(void) +{ + int tries; + int status; + + for (tries = 0; tries < 1000; tries++) { + status = omap_i2c_poll(1 << RRDY); + if ((status & (1 << RRDY)) != 0) { /* bytes available for reading */ + + /* consume the byte and throw it away */ + (void) read16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_DATA); + + /* clear the read ready flag */ + omap_i2c_write_status(1 << RRDY); + + } else { + break; /* buffer drained */ + } + } +} + +/* + * Poll the status register checking the bits set in 'mask'. + * Returns the status if any bits set or 0x0000 when the timeout is reached. + */ +static uint16_t +omap_i2c_poll(uint16_t mask) +{ + spin_t spin; + uint16_t status; + + /* poll for up to 1 s */ + spin_init(&spin, 1000000); + do { + status = omap_i2c_read_status(); + if ((status & mask) != 0) { /* any bits in mask set */ + return status; + } + + } while (spin_check(&spin)); + + return status; /* timeout reached, abort */ +} + +/* + * Poll Bus Busy Flag until the bus becomes free (return 1) or the timeout + * expires (return 0). + */ +static int +omap_i2c_bus_is_free(void) +{ + spin_t spin; + uint16_t status; + + /* wait for up to 1 second for the bus to become free */ + spin_init(&spin, 1000000); + do { + + status = omap_i2c_read_status(); + if ((status & (1 << BB)) == 0) { + return 1; /* bus is free */ + } + + } while (spin_check(&spin)); + + return 0; /* timeout expired */ +} + +static void +omap_i2c_clkconf(int i2c_bus_id) +{ + clkconf_init(); + + if (omap_i2c_bus->bus_type == DM37XX_I2C_BUS) { + + clkconf_set(CM_ICLKEN1_CORE, BIT((15 + i2c_bus_id)), + 0xffffffff); + clkconf_set(CM_FCLKEN1_CORE, BIT((15 + i2c_bus_id)), + 0xffffffff); + + } else if (omap_i2c_bus->bus_type == AM335X_I2C_BUS) { + + switch (i2c_bus_id) { + case 0: + clkconf_set(CM_WKUP_I2C0_CLKCTRL, BIT(1), 0xffffffff); + break; + case 1: + clkconf_set(CM_PER_I2C1_CLKCTRL, BIT(1), 0xffffffff); + break; + case 2: + clkconf_set(CM_PER_I2C2_CLKCTRL, BIT(1), 0xffffffff); + break; + default: + log_warn(&log, "Invalid i2c_bus_id\n"); + break; + } + } + + clkconf_release(); +} + +static void +omap_i2c_padconf(int i2c_bus_id) +{ + int r; + u32_t pinopts; + + if (omap_i2c_bus->bus_type == AM335X_I2C_BUS) { + + /* use the options suggested in starterware driver */ + pinopts = + CONTROL_CONF_SLEWCTRL | CONTROL_CONF_RXACTIVE | + CONTROL_CONF_PUTYPESEL; + + switch (i2c_bus_id) { + case 0: + pinopts |= CONTROL_CONF_MUXMODE(0); + + r = sys_padconf(CONTROL_CONF_I2C0_SDA, 0xffffffff, + pinopts); + if (r != OK) { + log_warn(&log, "padconf failed (r=%d)\n", r); + } + + r = sys_padconf(CONTROL_CONF_I2C0_SCL, 0xffffffff, + pinopts); + if (r != OK) { + log_warn(&log, "padconf failed (r=%d)\n", r); + } + + log_debug(&log, "pinopts=0x%x\n", pinopts); + break; + + case 1: + pinopts |= CONTROL_CONF_MUXMODE(2); + + r = sys_padconf(CONTROL_CONF_SPI0_CS0, 0xffffffff, + pinopts); + if (r != OK) { + log_warn(&log, "padconf failed (r=%d)\n", r); + } + + r = sys_padconf(CONTROL_CONF_SPI0_D1, 0xffffffff, + pinopts); + if (r != OK) { + log_warn(&log, "padconf failed (r=%d)\n", r); + } + log_debug(&log, "pinopts=0x%x\n", pinopts); + break; + + case 2: + pinopts |= CONTROL_CONF_MUXMODE(3); + + r = sys_padconf(CONTROL_CONF_UART1_CTSN, 0xffffffff, + pinopts); + if (r != OK) { + log_warn(&log, "padconf failed (r=%d)\n", r); + } + + r = sys_padconf(CONTROL_CONF_UART1_RTSN, + 0xffffffff, pinopts); + if (r != OK) { + log_warn(&log, "padconf failed (r=%d)\n", r); + } + + log_debug(&log, "pinopts=0x%x\n", pinopts); + break; + + default: + log_warn(&log, "Invalid i2c_bus_id\n"); + break; + } + } + + /* nothing to do for the DM37XX */ +} + +static int +omap_i2c_soft_reset(void) +{ + spin_t spin; + + /* Disable to do soft reset */ + write16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_CON, 0); + micro_delay(50000); + + /* Do a soft reset */ + write16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_SYSC, (1 << SRST)); + + /* Have to temporarily enable I2C to read RDONE */ + set16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_CON, (1<mapped_addr + omap_i2c_bus->regs->I2C_SYSS) & (1 << RDONE)) { + return OK; + } + + } while (spin_check(&spin)); + + log_warn(&log, "Tried soft reset, but bus never came back.\n"); + return EIO; +} + +static void +omap_i2c_intr_enable(void) +{ + int r; + uint16_t intmask; + static int policy_set = 0; + static int enabled = 0; + + if (!policy_set) { + r = sys_irqsetpolicy(omap_i2c_bus->irq, 0, + &omap_i2c_bus->irq_hook_kernel_id); + if (r == OK) { + policy_set = 1; + } else { + log_warn(&log, "Couldn't set irq policy\n"); + } + } + + if (policy_set && !enabled) { + r = sys_irqenable(&omap_i2c_bus->irq_hook_kernel_id); + if (r == OK) { + enabled = 1; + } else { + log_warn(&log, "Couldn't enable irq %d (hooked)\n", + omap_i2c_bus->irq); + } + } + + /* According to NetBSD driver and u-boot, these are needed even + * if just using polling (i.e. non-interrupt driver programming). + */ + intmask = 0; + intmask |= (1 << ROVR); + intmask |= (1 << AERR); + intmask |= (1 << XRDY); + intmask |= (1 << RRDY); + intmask |= (1 << ARDY); + intmask |= (1 << NACK); + intmask |= (1 << AL); + + if (omap_i2c_bus->bus_type == AM335X_I2C_BUS) { + write16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_IRQENABLE_SET, intmask); + } else if (omap_i2c_bus->bus_type == DM37XX_I2C_BUS) { + write16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_IE, intmask); + } else { + log_warn(&log, "Don't know how to enable interrupts.\n"); + } +} + +static void +omap_i2c_bus_init(void) +{ + + /* Ensure i2c module is disabled before setting prescalar & bus speed */ + write16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_CON, 0); + micro_delay(50000); + + /* Disable autoidle */ + set16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_SYSC, (1<mapped_addr + omap_i2c_bus->regs->I2C_PSC, + ((omap_i2c_bus->functional_clock / omap_i2c_bus->module_clock) - + 1)); + + /* Set the bus speed */ + write16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_SCLL, + ((omap_i2c_bus->module_clock / (2 * omap_i2c_bus->bus_speed)) - + 7)); + write16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_SCLH, + ((omap_i2c_bus->module_clock / (2 * omap_i2c_bus->bus_speed)) - + 5)); + + /* Set own I2C address */ + if (omap_i2c_bus->bus_type == AM335X_I2C_BUS) { + write16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_OA, I2C_OWN_ADDRESS); + } else if (omap_i2c_bus->bus_type == DM37XX_I2C_BUS) { + write16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_OA0, I2C_OWN_ADDRESS); + } else { + log_warn(&log, "Don't know how to set own address.\n"); + } + + /* Set TX/RX Threshold to 1 and disable I2C DMA */ + write16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_BUF, 0x0000); + + /* Bring the i2c module out of reset */ + set16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_CON, (1<bus_type == AM335X_I2C_BUS) { + /* TRM says to use RAW for polling for events */ + status = read16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_IRQSTATUS_RAW); + } else if (omap_i2c_bus->bus_type == DM37XX_I2C_BUS) { + status = read16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_STAT); + } else { + log_warn(&log, "Don't know how to read i2c bus status.\n"); + } + + return status; +} + +static void +omap_i2c_write_status(uint16_t mask) +{ + if (omap_i2c_bus->bus_type == AM335X_I2C_BUS) { + /* write 1's to IRQSTATUS (not RAW) to clear the bits */ + write16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_IRQSTATUS, mask); + } else if (omap_i2c_bus->bus_type == DM37XX_I2C_BUS) { + write16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_STAT, mask); + } else { + log_warn(&log, "Don't know how to clear i2c bus status.\n"); + } +} + +static int +omap_i2c_read(i2c_addr_t addr, uint8_t * buf, size_t buflen, int dostop) +{ + int r, i; + uint16_t conopts; + uint16_t pollmask; + uint16_t errmask; + + /* Set address of slave device */ + conopts = 0; + addr &= MAX_I2C_SA_MASK; /* sanitize address (10-bit max) */ + if (addr > 0x7f) { + /* 10-bit extended address in use, need to set XSA */ + conopts |= (1 << XSA); + } + + errmask = 0; + errmask |= (1 << ROVR); + errmask |= (1 << AERR); + errmask |= (1 << NACK); + errmask |= (1 << AL); + + pollmask = 0; + pollmask |= (1 << RRDY); + + /* Set bytes to read and slave address */ + write16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_CNT, buflen); + write16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_SA, addr); + + /* Set control register */ + conopts |= (1 << I2C_EN); /* enabled */ + conopts |= (1 << MST); /* master mode */ + conopts |= (1 << STT); /* start condition */ + + if (dostop != 0) { + conopts |= (1 << STP); /* stop condition */ + } + + write16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_CON, conopts); + + for (i = 0; i < buflen; i++) { + /* Data to read? */ + r = omap_i2c_poll(pollmask | errmask); + if ((r & errmask) != 0) { + /* only debug log level because i2cscan trigers this */ + log_debug(&log, "Read Error! Status=%x\n", r); + return EIO; + } else if ((r & pollmask) == 0) { + log_warn(&log, "No RRDY Interrupt. Status=%x\n", r); + log_warn(&log, + "Likely cause: bad pinmux or no devices on bus\n"); + return EBUSY; + } + + /* read a byte */ + buf[i] = read16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_DATA) & 0xff; + + /* clear the read ready flag */ + omap_i2c_write_status(pollmask); + } + + r = omap_i2c_read_status(); + if ((r & (1 << NACK)) != 0) { + log_warn(&log, "NACK\n"); + return EIO; + } + + /* Wait for operation to complete */ + pollmask = (1< 0x7f) { + /* 10-bit extended address in use, need to set XSA */ + conopts |= (1 << XSA); + } + + pollmask = 0; + pollmask |= (1 << XRDY); + + errmask = 0; + errmask |= (1 << ROVR); + errmask |= (1 << AERR); + errmask |= (1 << NACK); + errmask |= (1 << AL); + + write16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_CNT, buflen); + write16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_SA, addr); + + /* Set control register */ + conopts |= (1 << I2C_EN); /* enabled */ + conopts |= (1 << MST); /* master mode */ + conopts |= (1 << TRX); /* TRX mode */ + conopts |= (1 << STT); /* start condition */ + + if (dostop != 0) { + conopts |= (1 << STP); /* stop condition */ + } + + omap_i2c_write_status(0x7fff); + write16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_CON, conopts); + + for (i = 0; i < buflen; i++) { + + /* Ready to write? */ + r = omap_i2c_poll(pollmask | errmask); + if ((r & errmask) != 0) { + log_warn(&log, "Write Error! Status=%x\n", r); + return EIO; + } else if ((r & pollmask) == 0) { + log_warn(&log, "Not ready for write? Status=%x\n", r); + return EBUSY; + } + + write16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_DATA, buf[i]); + + /* clear the write ready flag */ + omap_i2c_write_status(pollmask); + } + + r = omap_i2c_read_status(); + if ((r & (1 << NACK)) != 0) { + log_warn(&log, "NACK\n"); + return EIO; + } + + /* Wait for operation to complete */ + pollmask = (1<= omap_i2c_nbuses) { + return EINVAL; + } + + /* select the bus to operate on */ + omap_i2c_bus = &omap_i2c_buses[i2c_bus_id]; + + /* Configure Pins */ + omap_i2c_padconf(i2c_bus_id); + + /* + * Map I2C Registers + */ + + /* Configure memory access */ + mr.mr_base = omap_i2c_bus->mr_base; /* start addr */ + mr.mr_limit = mr.mr_base + omap_i2c_bus->mr_size; /* end addr */ + + /* ask for privileges to access the I2C memory range */ + if (sys_privctl(SELF, SYS_PRIV_ADD_MEM, &mr) != OK) { + panic("Unable to obtain i2c memory range privileges"); + } + + /* map the memory into this process */ + omap_i2c_bus->mapped_addr = (vir_bytes) vm_map_phys(SELF, + (void *) omap_i2c_bus->mr_base, omap_i2c_bus->mr_size); + + if (omap_i2c_bus->mapped_addr == (vir_bytes) MAP_FAILED) { + panic("Unable to map i2c registers"); + } + + /* Enable Clocks */ + omap_i2c_clkconf(i2c_bus_id); + + /* Perform a soft reset of the I2C module to ensure a fresh start */ + r = omap_i2c_soft_reset(); + if (r != OK) { + /* module didn't come back up :( */ + return r; + } + + /* Bring up I2C module */ + omap_i2c_bus_init(); + + /* Get I2C Revision */ + if (omap_i2c_bus->bus_type == AM335X_I2C_BUS) { + /* I2C_REVLO revision: major (bits 10-8), minor (bits 5-0) */ + i2c_rev = read16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_REVNB_LO); + major = (i2c_rev >> 8) & 0x07; + minor = i2c_rev & 0x3f; + + } else if (omap_i2c_bus->bus_type == DM37XX_I2C_BUS) { + /* I2C_REV revision: major (bits 7-4), minor (bits 3-0) */ + i2c_rev = read16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_REV); + major = (i2c_rev >> 4) & 0x0f; + minor = i2c_rev & 0x0f; + } else { + panic("Don't know how to read i2c revision."); + } + + if (major != omap_i2c_bus->major || minor != omap_i2c_bus->minor) { + log_warn(&log, "Unrecognized value in I2C_REV register.\n"); + log_warn(&log, "Read: 0x%x.0x%x | Expected: 0x%x.0x%x\n", + major, minor, omap_i2c_bus->major, omap_i2c_bus->minor); + } + + /* display i2c revision information for debugging purposes */ + log_debug(&log, "i2c_%d: I2C rev 0x%x.0x%x\n", (i2c_bus_id + 1), + major, minor); + + return OK; +} diff --git a/minix/drivers/bus/i2c/arch/earmv6hf/omap_i2c.h b/minix/drivers/bus/i2c/arch/earmv6hf/omap_i2c.h new file mode 100644 index 000000000..014df2c83 --- /dev/null +++ b/minix/drivers/bus/i2c/arch/earmv6hf/omap_i2c.h @@ -0,0 +1,10 @@ +#ifndef _OMAP_I2C_H +#define _OMAP_I2C_H + +#include +#include +#include "omap_i2c_registers.h" + +int omap_interface_setup(int (**process)(minix_i2c_ioctl_exec_t *ioctl_exec), int i2c_bus_id); + +#endif /* _OMAP_I2C_H */ diff --git a/minix/drivers/bus/i2c/arch/earmv6hf/omap_i2c_registers.h b/minix/drivers/bus/i2c/arch/earmv6hf/omap_i2c_registers.h new file mode 100644 index 000000000..6563ca040 --- /dev/null +++ b/minix/drivers/bus/i2c/arch/earmv6hf/omap_i2c_registers.h @@ -0,0 +1,152 @@ +#ifndef _OMAP_I2C_REGISTERS_H +#define _OMAP_I2C_REGISTERS_H + +/* I2C Addresses for am335x (BeagleBone White / BeagleBone Black) */ + +/* IRQ Numbers */ +#define AM335X_I2C0_IRQ 70 +#define AM335X_I2C1_IRQ 71 +#define AM335X_I2C2_IRQ 30 + +/* Base Addresses */ +#define AM335X_I2C0_BASE 0x44e0b000 +#define AM335X_I2C1_BASE 0x4802a000 +#define AM335X_I2C2_BASE 0x4819c000 + +/* Size of I2C Register Address Range */ +#define AM335X_I2C0_SIZE 0x1000 +#define AM335X_I2C1_SIZE 0x1000 +#define AM335X_I2C2_SIZE 0x1000 + +/* Register Offsets */ +#define AM335X_I2C_REVNB_LO 0x00 +#define AM335X_I2C_REVNB_HI 0x04 +#define AM335X_I2C_SYSC 0x10 +#define AM335X_I2C_IRQSTATUS_RAW 0x24 +#define AM335X_I2C_IRQSTATUS 0x28 +#define AM335X_I2C_IRQENABLE_SET 0x2c +#define AM335X_I2C_IRQENABLE_CLR 0x30 +#define AM335X_I2C_WE 0x34 +#define AM335X_I2C_DMARXENABLE_SET 0x38 +#define AM335X_I2C_DMATXENABLE_SET 0x3c +#define AM335X_I2C_DMARXENABLE_CLR 0x40 +#define AM335X_I2C_DMATXENABLE_CLR 0x44 +#define AM335X_I2C_DMARXWAKE_EN 0x48 +#define AM335X_I2C_DMATXWAKE_EN 0x4c +#define AM335X_I2C_SYSS 0x90 +#define AM335X_I2C_BUF 0x94 +#define AM335X_I2C_CNT 0x98 +#define AM335X_I2C_DATA 0x9c +#define AM335X_I2C_CON 0xa4 +#define AM335X_I2C_OA 0xa8 +#define AM335X_I2C_SA 0xac +#define AM335X_I2C_PSC 0xb0 +#define AM335X_I2C_SCLL 0xb4 +#define AM335X_I2C_SCLH 0xb8 +#define AM335X_I2C_SYSTEST 0xbc +#define AM335X_I2C_BUFSTAT 0xc0 +#define AM335X_I2C_OA1 0xc4 +#define AM335X_I2C_OA2 0xc8 +#define AM335X_I2C_OA3 0xcc +#define AM335X_I2C_ACTOA 0xd0 +#define AM335X_I2C_SBLOCK 0xd4 + +/* Constants */ +#define AM335X_FUNCTIONAL_CLOCK 96000000 /* 96 MHz */ +#define AM335X_MODULE_CLOCK 12000000 /* 12 MHz */ + +/* I2C_REV value found on the BeagleBone / BeagleBone Black */ +#define AM335X_REV_MAJOR 0x00 +#define AM335X_REV_MINOR 0x0b + +/* I2C Addresses for dm37xx (BeagleBoard-xM) */ + +/* IRQ Numbers */ +#define DM37XX_I2C0_IRQ 56 +#define DM37XX_I2C1_IRQ 57 +#define DM37XX_I2C2_IRQ 61 + +/* Base Addresses */ +#define DM37XX_I2C0_BASE 0x48070000 +#define DM37XX_I2C1_BASE 0x48072000 +#define DM37XX_I2C2_BASE 0x48060000 + +/* Size of I2C Register Address Range */ +#define DM37XX_I2C0_SIZE 0x1000 +#define DM37XX_I2C1_SIZE 0x1000 +#define DM37XX_I2C2_SIZE 0x1000 + +/* Register Offsets */ +#define DM37XX_I2C_REV 0x00 +#define DM37XX_I2C_IE 0x04 +#define DM37XX_I2C_STAT 0x08 +#define DM37XX_I2C_WE 0x0C +#define DM37XX_I2C_SYSS 0x10 +#define DM37XX_I2C_BUF 0x14 +#define DM37XX_I2C_CNT 0x18 +#define DM37XX_I2C_DATA 0x1c +#define DM37XX_I2C_SYSC 0x20 +#define DM37XX_I2C_CON 0x24 +#define DM37XX_I2C_OA0 0x28 +#define DM37XX_I2C_SA 0x2c +#define DM37XX_I2C_PSC 0x30 +#define DM37XX_I2C_SCLL 0x34 +#define DM37XX_I2C_SCLH 0x38 +#define DM37XX_I2C_SYSTEST 0x3c +#define DM37XX_I2C_BUFSTAT 0x40 +#define DM37XX_I2C_OA1 0x44 +#define DM37XX_I2C_OA2 0x48 +#define DM37XX_I2C_OA3 0x4c +#define DM37XX_I2C_ACTOA 0x50 +#define DM37XX_I2C_SBLOCK 0x54 + +/* Constants */ +#define DM37XX_FUNCTIONAL_CLOCK 96000000 /* 96 MHz */ +#define DM37XX_MODULE_CLOCK 19200000 /* 19.2 MHz */ + +#define DM37XX_REV_MAJOR 0x04 +#define DM37XX_REV_MINOR 0x00 + +/* Shared Values */ + +#define BUS_SPEED_100KHz 100000 /* 100 KHz */ +#define BUS_SPEED_400KHz 400000 /* 400 KHz */ +#define I2C_OWN_ADDRESS 0x01 + +/* Masks */ + +#define MAX_I2C_SA_MASK (0x3ff) /* Highest 10 bit address -- 9..0 */ + +/* Bit Offsets within Registers (only those used are listed) */ + +/* Same offsets for both dm37xx and am335x */ + +#define I2C_EN 15 /* I2C_CON */ +#define MST 10 /* I2C_CON */ +#define TRX 9 /* I2C_CON */ +#define XSA 8 /* I2C_CON */ +#define STP 1 /* I2C_CON */ +#define STT 0 /* I2C_CON */ + +#define CLKACTIVITY_S 9 /* I2C_SYSC */ +#define CLKACTIVITY_I 8 /* I2C_SYSC */ +#define SMART_WAKE_UP 4 /* I2C_SYSC */ +#define NO_IDLE_MODE 3 /* I2C_SYSC */ +#define SRST 1 /* I2C_SYSC */ +#define AUTOIDLE 0 /* I2C_SYSC */ + +#define RDONE 0 /* I2C_SYSS */ + +#define RXFIFO_CLR 14 /* I2C_BUF */ +#define TXFIFO_CLR 6 /* I2C_BUF */ + +#define BB 12 /* I2C_IRQSTATUS / I2C_STAT / I2C_IRQENABLE_SET / I2C_IE */ +#define ROVR 11 /* I2C_IRQSTATUS / I2C_STAT / I2C_IRQENABLE_SET / I2C_IE */ +#define AERR 7 /* I2C_IRQSTATUS / I2C_STAT / I2C_IRQENABLE_SET / I2C_IE */ +#define XRDY 4 /* I2C_IRQSTATUS / I2C_STAT / I2C_IRQENABLE_SET / I2C_IE */ +#define RRDY 3 /* I2C_IRQSTATUS / I2C_STAT / I2C_IRQENABLE_SET / I2C_IE */ +#define ARDY 2 /* I2C_IRQSTATUS / I2C_STAT / I2C_IRQENABLE_SET / I2C_IE */ +#define NACK 1 /* I2C_IRQSTATUS / I2C_STAT / I2C_IRQENABLE_SET / I2C_IE */ +#define AL 0 /* I2C_IRQSTATUS / I2C_STAT / I2C_IRQENABLE_SET / I2C_IE */ + +#endif /* _OMAP_I2C_REGISTERS_H */ diff --git a/minix/drivers/clock/readclock/arch/earmv6hf/Makefile.inc b/minix/drivers/clock/readclock/arch/earmv6hf/Makefile.inc new file mode 100644 index 000000000..909a63b6e --- /dev/null +++ b/minix/drivers/clock/readclock/arch/earmv6hf/Makefile.inc @@ -0,0 +1,10 @@ +# Makefile for arch-dependent readclock code +.include + +HERE=${.CURDIR}/arch/${MACHINE_ARCH} +.PATH: ${HERE} + +SRCS += arch_readclock.c omap_rtc.c omap_rtc.h + +DPADD+= ${LIBCLKCONF} +LDADD+= -lclkconf diff --git a/minix/drivers/clock/readclock/arch/earmv6hf/arch_readclock.c b/minix/drivers/clock/readclock/arch/earmv6hf/arch_readclock.c new file mode 100644 index 000000000..bc535bd5b --- /dev/null +++ b/minix/drivers/clock/readclock/arch/earmv6hf/arch_readclock.c @@ -0,0 +1,45 @@ +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "omap_rtc.h" +#include "forward.h" +#include "readclock.h" + +int +arch_setup(struct rtc *r) +{ + struct machine machine ; + sys_getmachine(&machine); + + if (BOARD_IS_BBXM(machine.board_id)){ + fwd_set_label("tps65950.1.48"); + r->init = fwd_init; + r->get_time = fwd_get_time; + r->set_time = fwd_set_time; + r->pwr_off = fwd_pwr_off; + r->exit = fwd_exit; + return OK; + } else if ( BOARD_IS_BB(machine.board_id)){ + r->init = omap_rtc_init; + r->get_time = omap_rtc_get_time; + r->set_time = omap_rtc_set_time; + r->pwr_off = omap_rtc_pwr_off; + r->exit = omap_rtc_exit; + return OK; + } + return ENOSYS; +} diff --git a/minix/drivers/clock/readclock/arch/earmv6hf/omap_rtc.c b/minix/drivers/clock/readclock/arch/earmv6hf/omap_rtc.c new file mode 100644 index 000000000..8fb312275 --- /dev/null +++ b/minix/drivers/clock/readclock/arch/earmv6hf/omap_rtc.c @@ -0,0 +1,419 @@ +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "omap_rtc.h" +#include "readclock.h" + +/* defines the set of register */ + +typedef struct omap_rtc_registers +{ + vir_bytes RTC_SS_SECONDS_REG; + vir_bytes RTC_SS_MINUTES_REG; + vir_bytes RTC_SS_HOURS_REG; + vir_bytes RTC_SS_DAYS_REG; + vir_bytes RTC_SS_MONTHS_REG; + vir_bytes RTC_SS_YEARS_REG; + vir_bytes RTC_SS_WEEKS_REG; + vir_bytes RTC_SS_ALARM_SECONDS_REG; + vir_bytes RTC_SS_ALARM_MINUTES_REG; + vir_bytes RTC_SS_ALARM_HOURS_REG; + vir_bytes RTC_SS_ALARM_DAYS_REG; + vir_bytes RTC_SS_ALARM_MONTHS_REG; + vir_bytes RTC_SS_ALARM_YEARS_REG; + vir_bytes RTC_SS_RTC_CTRL_REG; + vir_bytes RTC_SS_RTC_STATUS_REG; + vir_bytes RTC_SS_RTC_INTERRUPTS_REG; + vir_bytes RTC_SS_RTC_COMP_LSB_REG; + vir_bytes RTC_SS_RTC_COMP_MSB_REG; + vir_bytes RTC_SS_RTC_OSC_REG; + vir_bytes RTC_SS_RTC_SCRATCH0_REG; + vir_bytes RTC_SS_RTC_SCRATCH1_REG; + vir_bytes RTC_SS_RTC_SCRATCH2_REG; + vir_bytes RTC_SS_KICK0R; + vir_bytes RTC_SS_KICK1R; + vir_bytes RTC_SS_RTC_REVISION; + vir_bytes RTC_SS_RTC_SYSCONFIG; + vir_bytes RTC_SS_RTC_IRQWAKEEN; + vir_bytes RTC_SS_ALARM2_SECONDS_REG; + vir_bytes RTC_SS_ALARM2_MINUTES_REG; + vir_bytes RTC_SS_ALARM2_HOURS_REG; + vir_bytes RTC_SS_ALARM2_DAYS_REG; + vir_bytes RTC_SS_ALARM2_MONTHS_REG; + vir_bytes RTC_SS_ALARM2_YEARS_REG; + vir_bytes RTC_SS_RTC_PMIC; + vir_bytes RTC_SS_RTC_DEBOUNCE; +} omap_rtc_registers_t; + +typedef struct omap_rtc_clock +{ + enum rtc_clock_type + { am335x } clock_type; + phys_bytes mr_base; + phys_bytes mr_size; + vir_bytes mapped_addr; + omap_rtc_registers_t *regs; +} omap_rtc_clock_t; + +/* Define the registers for each chip */ + +static omap_rtc_registers_t am335x_rtc_regs = { + .RTC_SS_SECONDS_REG = AM335X_RTC_SS_SECONDS_REG, + .RTC_SS_MINUTES_REG = AM335X_RTC_SS_MINUTES_REG, + .RTC_SS_HOURS_REG = AM335X_RTC_SS_HOURS_REG, + .RTC_SS_DAYS_REG = AM335X_RTC_SS_DAYS_REG, + .RTC_SS_MONTHS_REG = AM335X_RTC_SS_MONTHS_REG, + .RTC_SS_YEARS_REG = AM335X_RTC_SS_YEARS_REG, + .RTC_SS_WEEKS_REG = AM335X_RTC_SS_WEEKS_REG, + .RTC_SS_ALARM_SECONDS_REG = AM335X_RTC_SS_ALARM_SECONDS_REG, + .RTC_SS_ALARM_MINUTES_REG = AM335X_RTC_SS_ALARM_MINUTES_REG, + .RTC_SS_ALARM_HOURS_REG = AM335X_RTC_SS_ALARM_HOURS_REG, + .RTC_SS_ALARM_DAYS_REG = AM335X_RTC_SS_ALARM_DAYS_REG, + .RTC_SS_ALARM_MONTHS_REG = AM335X_RTC_SS_ALARM_MONTHS_REG, + .RTC_SS_ALARM_YEARS_REG = AM335X_RTC_SS_ALARM_YEARS_REG, + .RTC_SS_RTC_CTRL_REG = AM335X_RTC_SS_RTC_CTRL_REG, + .RTC_SS_RTC_STATUS_REG = AM335X_RTC_SS_RTC_STATUS_REG, + .RTC_SS_RTC_INTERRUPTS_REG = AM335X_RTC_SS_RTC_INTERRUPTS_REG, + .RTC_SS_RTC_COMP_LSB_REG = AM335X_RTC_SS_RTC_COMP_LSB_REG, + .RTC_SS_RTC_COMP_MSB_REG = AM335X_RTC_SS_RTC_COMP_MSB_REG, + .RTC_SS_RTC_OSC_REG = AM335X_RTC_SS_RTC_OSC_REG, + .RTC_SS_RTC_SCRATCH0_REG = AM335X_RTC_SS_RTC_SCRATCH0_REG, + .RTC_SS_RTC_SCRATCH1_REG = AM335X_RTC_SS_RTC_SCRATCH1_REG, + .RTC_SS_RTC_SCRATCH2_REG = AM335X_RTC_SS_RTC_SCRATCH2_REG, + .RTC_SS_KICK0R = AM335X_RTC_SS_KICK0R, + .RTC_SS_KICK1R = AM335X_RTC_SS_KICK1R, + .RTC_SS_RTC_REVISION = AM335X_RTC_SS_RTC_REVISION, + .RTC_SS_RTC_SYSCONFIG = AM335X_RTC_SS_RTC_SYSCONFIG, + .RTC_SS_RTC_IRQWAKEEN = AM335X_RTC_SS_RTC_IRQWAKEEN, + .RTC_SS_ALARM2_SECONDS_REG = AM335X_RTC_SS_ALARM2_SECONDS_REG, + .RTC_SS_ALARM2_MINUTES_REG = AM335X_RTC_SS_ALARM2_MINUTES_REG, + .RTC_SS_ALARM2_HOURS_REG = AM335X_RTC_SS_ALARM2_HOURS_REG, + .RTC_SS_ALARM2_DAYS_REG = AM335X_RTC_SS_ALARM2_DAYS_REG, + .RTC_SS_ALARM2_MONTHS_REG = AM335X_RTC_SS_ALARM2_MONTHS_REG, + .RTC_SS_ALARM2_YEARS_REG = AM335X_RTC_SS_ALARM2_YEARS_REG, + .RTC_SS_RTC_PMIC = AM335X_RTC_SS_RTC_PMIC, + .RTC_SS_RTC_DEBOUNCE = AM335X_RTC_SS_RTC_DEBOUNCE +}; + +static omap_rtc_clock_t rtc = { + am335x, AM335X_RTC_SS_BASE, AM335X_RTC_SS_SIZE, 0, &am335x_rtc_regs +}; + +/* used for logging */ +static struct log log = { + .name = "omap_rtc", + .log_level = LEVEL_INFO, + .log_func = default_log +}; + +static u32_t use_count = 0; +static u32_t pwr_off_in_progress = 0; + +static void omap_rtc_unlock(void); +static void omap_rtc_lock(void); +static int omap_rtc_clkconf(void); + +/* Helper Functions for Register Access */ +#define reg_read(a) (*(volatile uint32_t *)(rtc.mapped_addr + a)) +#define reg_write(a,v) (*(volatile uint32_t *)(rtc.mapped_addr + a) = (v)) +#define reg_set_bit(a,v) reg_write((a), reg_read((a)) | (1<RTC_SS_RTC_STATUS_REG) & (1<RTC_SS_KICK0R, AM335X_RTC_SS_KICK0R_UNLOCK_MASK); + reg_write(rtc.regs->RTC_SS_KICK1R, AM335X_RTC_SS_KICK1R_UNLOCK_MASK); +} + +static void +omap_rtc_lock(void) +{ + /* Write garbage to the KICK registers to enable write protect. */ + reg_write(rtc.regs->RTC_SS_KICK0R, AM335X_RTC_SS_KICK0R_LOCK_MASK); + reg_write(rtc.regs->RTC_SS_KICK1R, AM335X_RTC_SS_KICK1R_LOCK_MASK); +} + +static int +omap_rtc_clkconf(void) +{ + int r; + + /* Configure the clocks need to run the RTC */ + r = clkconf_init(); + if (r != OK) { + return r; + } + + r = clkconf_set(CM_RTC_RTC_CLKCTRL, 0xffffffff, + CM_RTC_RTC_CLKCTRL_MASK); + if (r != OK) { + return r; + } + + r = clkconf_set(CM_RTC_CLKSTCTRL, 0xffffffff, CM_RTC_CLKSTCTRL_MASK); + if (r != OK) { + return r; + } + + r = clkconf_release(); + if (r != OK) { + return r; + } + + return OK; +} + +int +omap_rtc_init(void) +{ + int r; + int rtc_rev, major, minor; + struct minix_mem_range mr; + + struct machine machine ; + sys_getmachine(&machine); + + if(! BOARD_IS_BB(machine.board_id)){ + /* Only the am335x (BeagleBone & BeagleBone Black) is supported ATM. + * The dm37xx (BeagleBoard-xM) doesn't have a real time clock + * built-in. Instead, it uses the RTC on the PMIC. A driver for + * the BeagleBoard-xM's PMIC still needs to be developed. + */ + log_warn(&log, "unsupported processor\n"); + return ENOSYS; + } + + if (pwr_off_in_progress) + return EINVAL; + + use_count++; + if (rtc.mapped_addr != 0) { + /* already intialized */ + return OK; + } + + /* Enable Clocks */ + r = omap_rtc_clkconf(); + if (r != OK) { + log_warn(&log, "Failed to enable clocks for RTC.\n"); + return r; + } + + /* + * Map RTC_SS Registers + */ + + /* Configure memory access */ + mr.mr_base = rtc.mr_base; /* start addr */ + mr.mr_limit = mr.mr_base + rtc.mr_size; /* end addr */ + + /* ask for privileges to access the RTC_SS memory range */ + if (sys_privctl(SELF, SYS_PRIV_ADD_MEM, &mr) != OK) { + log_warn(&log, + "Unable to obtain RTC memory range privileges."); + return EPERM; + } + + /* map the memory into this process */ + rtc.mapped_addr = (vir_bytes) vm_map_phys(SELF, + (void *) rtc.mr_base, rtc.mr_size); + if (rtc.mapped_addr == (vir_bytes) MAP_FAILED) { + log_warn(&log, "Unable to map RTC registers\n"); + return EPERM; + } + + rtc_rev = reg_read(rtc.regs->RTC_SS_RTC_REVISION); + major = (rtc_rev & 0x0700) >> 8; + minor = (rtc_rev & 0x001f); + log_debug(&log, "omap rtc rev %d.%d\n", major, minor); + + /* Disable register write protect */ + omap_rtc_unlock(); + + /* Set NOIDLE */ + reg_write(rtc.regs->RTC_SS_RTC_SYSCONFIG, (1 << NOIDLE_BIT)); + + /* Enable 32kHz clock */ + reg_set_bit(rtc.regs->RTC_SS_RTC_OSC_REG, EN_32KCLK_BIT); + + /* Setting the stop bit starts the RTC running */ + reg_set_bit(rtc.regs->RTC_SS_RTC_CTRL_REG, RTC_STOP_BIT); + + /* Re-enable Write Protection */ + omap_rtc_lock(); + + log_debug(&log, "OMAP RTC Initialized\n"); + + return OK; +} + +/* + * These are the ranges used by the real time clock and struct tm. + * + * Field OMAP RTC struct tm + * ----- -------- --------- + * seconds 0 to 59 (Mask 0x7f) 0 to 59 (60 for leap seconds) + * minutes 0 to 59 (Mask 0x7f) 0 to 59 + * hours 0 to 23 (Mask 0x3f) 0 to 23 + * day 1 to 31 (Mask 0x3f) 1 to 31 + * month 1 to 12 (Mask 0x1f) 0 to 11 + * year last 2 digits of year X + 1900 + */ + +int +omap_rtc_get_time(struct tm *t, int flags) +{ + int r; + + if (pwr_off_in_progress) + return EINVAL; + + memset(t, '\0', sizeof(struct tm)); + + /* Read and Convert BCD to binary (default RTC mode). */ + t->tm_sec = bcd_to_dec(reg_read(rtc.regs->RTC_SS_SECONDS_REG) & 0x7f); + t->tm_min = bcd_to_dec(reg_read(rtc.regs->RTC_SS_MINUTES_REG) & 0x7f); + t->tm_hour = bcd_to_dec(reg_read(rtc.regs->RTC_SS_HOURS_REG) & 0x3f); + t->tm_mday = bcd_to_dec(reg_read(rtc.regs->RTC_SS_DAYS_REG) & 0x3f); + t->tm_mon = + bcd_to_dec(reg_read(rtc.regs->RTC_SS_MONTHS_REG) & 0x1f) - 1; + t->tm_year = + bcd_to_dec(reg_read(rtc.regs->RTC_SS_YEARS_REG) & 0xff) + 100; + + if (t->tm_year == 100) { + /* Cold start - no date/time set - default to 2013-01-01 */ + t->tm_sec = 0; + t->tm_min = 0; + t->tm_hour = 0; + t->tm_mday = 1; + t->tm_mon = 0; + t->tm_year = 113; + + omap_rtc_set_time(t, RTCDEV_NOFLAGS); + } + + return OK; +} + +int +omap_rtc_set_time(struct tm *t, int flags) +{ + int r; + + if (pwr_off_in_progress) + return EINVAL; + + /* Disable Write Protection */ + omap_rtc_unlock(); + + /* Write the date/time to the RTC registers. */ + safe_reg_write(rtc.regs->RTC_SS_SECONDS_REG, + (dec_to_bcd(t->tm_sec) & 0x7f)); + safe_reg_write(rtc.regs->RTC_SS_MINUTES_REG, + (dec_to_bcd(t->tm_min) & 0x7f)); + safe_reg_write(rtc.regs->RTC_SS_HOURS_REG, + (dec_to_bcd(t->tm_hour) & 0x3f)); + safe_reg_write(rtc.regs->RTC_SS_DAYS_REG, + (dec_to_bcd(t->tm_mday) & 0x3f)); + safe_reg_write(rtc.regs->RTC_SS_MONTHS_REG, + (dec_to_bcd(t->tm_mon + 1) & 0x1f)); + safe_reg_write(rtc.regs->RTC_SS_YEARS_REG, + (dec_to_bcd(t->tm_year % 100) & 0xff)); + + /* Re-enable Write Protection */ + omap_rtc_lock(); + + return OK; +} + +int +omap_rtc_pwr_off(void) +{ + int r; + struct tm t; + + if (pwr_off_in_progress) + return EINVAL; + + /* wait until 3 seconds can be added without overflowing tm_sec */ + do { + omap_rtc_get_time(&t, RTCDEV_NOFLAGS); + micro_delay(250000); + } while (t.tm_sec >= 57); + + /* set the alarm for 3 seconds from now */ + t.tm_sec += 3; + + /* Disable register write protect */ + omap_rtc_unlock(); + + /* enable power-off via ALARM2 by setting the PWR_ENABLE_EN bit. */ + safe_reg_set_bit(rtc.regs->RTC_SS_RTC_PMIC, PWR_ENABLE_EN_BIT); + + /* Write the date/time to the RTC registers. */ + safe_reg_write(rtc.regs->RTC_SS_ALARM2_SECONDS_REG, + (dec_to_bcd(t.tm_sec) & 0x7f)); + safe_reg_write(rtc.regs->RTC_SS_ALARM2_MINUTES_REG, + (dec_to_bcd(t.tm_min) & 0x7f)); + safe_reg_write(rtc.regs->RTC_SS_ALARM2_HOURS_REG, + (dec_to_bcd(t.tm_hour) & 0x3f)); + safe_reg_write(rtc.regs->RTC_SS_ALARM2_DAYS_REG, + (dec_to_bcd(t.tm_mday) & 0x3f)); + safe_reg_write(rtc.regs->RTC_SS_ALARM2_MONTHS_REG, + (dec_to_bcd(t.tm_mon + 1) & 0x1f)); + safe_reg_write(rtc.regs->RTC_SS_ALARM2_YEARS_REG, + (dec_to_bcd(t.tm_year % 100) & 0xff)); + + /* enable interrupt to trigger POWER_EN to go low when alarm2 hits. */ + safe_reg_set_bit(rtc.regs->RTC_SS_RTC_INTERRUPTS_REG, IT_ALARM2_BIT); + + /* pause the realtime clock. the kernel will enable it when safe. */ + reg_clear_bit(rtc.regs->RTC_SS_RTC_CTRL_REG, RTC_STOP_BIT); + + /* Set this flag to block all other operations so that the clock isn't + * accidentally re-startered and so write protect isn't re-enabled. */ + pwr_off_in_progress = 1; + + /* Make the kernel's job easier by not re-enabling write protection */ + + return OK; +} + +void +omap_rtc_exit(void) +{ + use_count--; + if (use_count == 0) { + vm_unmap_phys(SELF, (void *) rtc.mapped_addr, rtc.mr_size); + rtc.mapped_addr = 0; + } + log_debug(&log, "Exiting\n"); +} diff --git a/minix/drivers/clock/readclock/arch/earmv6hf/omap_rtc.h b/minix/drivers/clock/readclock/arch/earmv6hf/omap_rtc.h new file mode 100644 index 000000000..28a5a1949 --- /dev/null +++ b/minix/drivers/clock/readclock/arch/earmv6hf/omap_rtc.h @@ -0,0 +1,94 @@ +#ifndef __OMAP_RTC_REGISTERS_H +#define __OMAP_RTC_REGISTERS_H + +/* RTC Addresses for am335x (BeagleBone White / BeagleBone Black) */ + +/* Base Addresses */ +#define AM335X_RTC_SS_BASE 0x44e3e000 + +/* Size of RTC Register Address Range */ +#define AM335X_RTC_SS_SIZE 0x1000 + +/* Register Offsets */ +#define AM335X_RTC_SS_SECONDS_REG 0x0 +#define AM335X_RTC_SS_MINUTES_REG 0x4 +#define AM335X_RTC_SS_HOURS_REG 0x8 +#define AM335X_RTC_SS_DAYS_REG 0xC +#define AM335X_RTC_SS_MONTHS_REG 0x10 +#define AM335X_RTC_SS_YEARS_REG 0x14 +#define AM335X_RTC_SS_WEEKS_REG 0x18 +#define AM335X_RTC_SS_ALARM_SECONDS_REG 0x20 +#define AM335X_RTC_SS_ALARM_MINUTES_REG 0x24 +#define AM335X_RTC_SS_ALARM_HOURS_REG 0x28 +#define AM335X_RTC_SS_ALARM_DAYS_REG 0x2C +#define AM335X_RTC_SS_ALARM_MONTHS_REG 0x30 +#define AM335X_RTC_SS_ALARM_YEARS_REG 0x34 +#define AM335X_RTC_SS_RTC_CTRL_REG 0x40 +#define AM335X_RTC_SS_RTC_STATUS_REG 0x44 +#define AM335X_RTC_SS_RTC_INTERRUPTS_REG 0x48 +#define AM335X_RTC_SS_RTC_COMP_LSB_REG 0x4C +#define AM335X_RTC_SS_RTC_COMP_MSB_REG 0x50 +#define AM335X_RTC_SS_RTC_OSC_REG 0x54 +#define AM335X_RTC_SS_RTC_SCRATCH0_REG 0x60 +#define AM335X_RTC_SS_RTC_SCRATCH1_REG 0x64 +#define AM335X_RTC_SS_RTC_SCRATCH2_REG 0x68 +#define AM335X_RTC_SS_KICK0R 0x6C +#define AM335X_RTC_SS_KICK1R 0x70 +#define AM335X_RTC_SS_RTC_REVISION 0x74 +#define AM335X_RTC_SS_RTC_SYSCONFIG 0x78 +#define AM335X_RTC_SS_RTC_IRQWAKEEN 0x7C +#define AM335X_RTC_SS_ALARM2_SECONDS_REG 0x80 +#define AM335X_RTC_SS_ALARM2_MINUTES_REG 0x84 +#define AM335X_RTC_SS_ALARM2_HOURS_REG 0x88 +#define AM335X_RTC_SS_ALARM2_DAYS_REG 0x8C +#define AM335X_RTC_SS_ALARM2_MONTHS_REG 0x90 +#define AM335X_RTC_SS_ALARM2_YEARS_REG 0x94 +#define AM335X_RTC_SS_RTC_PMIC 0x98 +#define AM335X_RTC_SS_RTC_DEBOUNCE 0x9C + +/* Constants */ +#define AM335X_RTC_SS_KICK0R_UNLOCK_MASK 0x83E70B13 +#define AM335X_RTC_SS_KICK1R_UNLOCK_MASK 0x95A4F1E0 + +#define AM335X_RTC_SS_KICK0R_LOCK_MASK 0x546f6d20 +#define AM335X_RTC_SS_KICK1R_LOCK_MASK 0x436f7274 + +/* Bits */ + +/* RTC_SS_RTC_STATUS_REG */ +#define RTC_BUSY_BIT 0 + +/* RTC_SS_RTC_CTRL_REG */ +#define RTC_STOP_BIT 0 + +/* RTC_SS_RTC_SYSCONFIG */ +#define NOIDLE_BIT 0 + +/* RTC_SS_RTC_OSC_REG */ +#define EN_32KCLK_BIT 6 + +/* RTC_SS_RTC_PMIC */ +#define PWR_ENABLE_EN_BIT 16 + +/* RTC_SS_RTC_INTERRUPTS_REG */ +#define IT_ALARM2_BIT 4 + +/* Clocks */ +#define CM_RTC_RTC_CLKCTRL 0x800 +#define CM_RTC_RTC_CLKCTRL_IDLEST ((0<<17)|(0<<16)) +#define CM_RTC_RTC_CLKCTRL_MODULEMODE ((1<<1)|(0<<0)) +#define CM_RTC_RTC_CLKCTRL_MASK (CM_RTC_RTC_CLKCTRL_IDLEST|CM_RTC_RTC_CLKCTRL_MODULEMODE) + +#define CM_RTC_CLKSTCTRL 0x804 +#define CLKACTIVITY_RTC_32KCLK (1<<9) +#define CLKACTIVITY_L4_RTC_GCLK (1<<8) +#define CLKTRCTRL ((0<<1)|(0<<0)) +#define CM_RTC_CLKSTCTRL_MASK (CLKACTIVITY_RTC_32KCLK|CLKACTIVITY_L4_RTC_GCLK|CLKTRCTRL) + +int omap_rtc_init(void); +int omap_rtc_get_time(struct tm *t, int flags); +int omap_rtc_set_time(struct tm *t, int flags); +int omap_rtc_pwr_off(void); +void omap_rtc_exit(void); + +#endif /* __OMAP_RTC_REGISTERS_H */ diff --git a/minix/drivers/eeprom/Makefile b/minix/drivers/eeprom/Makefile index 40ab6c53c..f5e60fc69 100644 --- a/minix/drivers/eeprom/Makefile +++ b/minix/drivers/eeprom/Makefile @@ -1,6 +1,6 @@ .include -.if ${MACHINE_ARCH} == "earm" +.if ( (${MACHINE_ARCH} == "earm") || (${MACHINE_ARCH} == "earmv6hf") ) SUBDIR+= cat24c256 .endif # ${MACHINE_ARCH} == "earm" diff --git a/minix/drivers/net/Makefile b/minix/drivers/net/Makefile index 069ab5c19..3b963cded 100644 --- a/minix/drivers/net/Makefile +++ b/minix/drivers/net/Makefile @@ -14,7 +14,7 @@ SUBDIR+= rtl8169 SUBDIR+= virtio_net .endif # ${MACHINE_ARCH} == "i386" -.if ${MACHINE_ARCH} == "earm" +.if ( (${MACHINE_ARCH} == "earm") || (${MACHINE_ARCH} == "earmv6hf") ) SUBDIR+= lan8710a .endif # ${MACHINE_ARCH} == "earm" diff --git a/minix/drivers/power/Makefile b/minix/drivers/power/Makefile index f33853130..964a21563 100644 --- a/minix/drivers/power/Makefile +++ b/minix/drivers/power/Makefile @@ -4,7 +4,7 @@ SUBDIR+= acpi .endif # ${MACHINE_ARCH} == "i386" -.if ${MACHINE_ARCH} == "earm" +.if ( (${MACHINE_ARCH} == "earm") || (${MACHINE_ARCH} == "earmv6hf") ) SUBDIR+= tps65217 SUBDIR+= tps65950 .endif # ${MACHINE_ARCH} == "earm" diff --git a/minix/drivers/sensors/Makefile b/minix/drivers/sensors/Makefile index 071d48cb9..7435111ea 100644 --- a/minix/drivers/sensors/Makefile +++ b/minix/drivers/sensors/Makefile @@ -1,6 +1,6 @@ .include -.if ${MACHINE_ARCH} == "earm" +.if ( (${MACHINE_ARCH} == "earm") || (${MACHINE_ARCH} == "earmv6hf") ) SUBDIR+= bmp085 SUBDIR+= sht21 SUBDIR+= tsl2550 diff --git a/minix/drivers/storage/mmc/Makefile b/minix/drivers/storage/mmc/Makefile index b21ab617e..79a9e971c 100644 --- a/minix/drivers/storage/mmc/Makefile +++ b/minix/drivers/storage/mmc/Makefile @@ -2,7 +2,7 @@ PROG= mmc SRCS= mmcblk.c mmchost_dummy.c sdhcreg.h sdmmcreg.h -.if ${MACHINE_ARCH} == "earm" +.if ( (${MACHINE_ARCH} == "earm") || (${MACHINE_ARCH} == "earmv6hf") ) SRCS += mmchost_mmchs.c .endif diff --git a/minix/drivers/storage/ramdisk/Makefile b/minix/drivers/storage/ramdisk/Makefile index c984aca63..1ef1a97eb 100644 --- a/minix/drivers/storage/ramdisk/Makefile +++ b/minix/drivers/storage/ramdisk/Makefile @@ -89,7 +89,7 @@ dir.acpi:= minix/drivers/power/acpi .endif .endif # ${MACHINE_ARCH} == "i386" -.if ${MACHINE_ARCH} == "earm" +.if ( (${MACHINE_ARCH} == "earm") || (${MACHINE_ARCH} == "earmv6hf") ) PROGRAMS+= mmc dir.mmc:= minix/drivers/storage/mmc .endif # ${MACHINE_ARCH} == "earm" diff --git a/minix/drivers/system/Makefile b/minix/drivers/system/Makefile index 00033c6be..e948bdcf7 100644 --- a/minix/drivers/system/Makefile +++ b/minix/drivers/system/Makefile @@ -1,6 +1,6 @@ .include -.if ${MACHINE_ARCH} == "earm" +.if ((${MACHINE_ARCH} == "earm") || (${MACHINE_ARCH} == "earmv6hf") ) SUBDIR+= gpio .endif # ${MACHINE_ARCH} == "earm" diff --git a/minix/drivers/tty/tty/arch/earmv6hf/Makefile.inc b/minix/drivers/tty/tty/arch/earmv6hf/Makefile.inc new file mode 100644 index 000000000..3ad697a9e --- /dev/null +++ b/minix/drivers/tty/tty/arch/earmv6hf/Makefile.inc @@ -0,0 +1,7 @@ +# Makefile for arch-dependent TTY code +.include + +HERE=${.CURDIR}/arch/${MACHINE_ARCH} +.PATH: ${HERE} + +SRCS += console.c keyboard.c rs232.c diff --git a/minix/drivers/tty/tty/arch/earmv6hf/console.c b/minix/drivers/tty/tty/arch/earmv6hf/console.c new file mode 100644 index 000000000..8eb588316 --- /dev/null +++ b/minix/drivers/tty/tty/arch/earmv6hf/console.c @@ -0,0 +1,30 @@ +/* Console unsupport for ARM. Just stubs. */ +#include +#include +#include "tty.h" + +void +do_video(message *m, int ipc_status) +{ +} + +void +scr_init(tty_t *tp) +{ +} + +void +cons_stop(void) +{ +} + +void +beep_x(unsigned int freq, clock_t dur) +{ +} + +int +con_loadfont(endpoint_t endpt, cp_grant_id_t grant) +{ + return 0; +} diff --git a/minix/drivers/tty/tty/arch/earmv6hf/keyboard.c b/minix/drivers/tty/tty/arch/earmv6hf/keyboard.c new file mode 100644 index 000000000..fd11bde51 --- /dev/null +++ b/minix/drivers/tty/tty/arch/earmv6hf/keyboard.c @@ -0,0 +1,30 @@ +/* Keyboard unsupport for ARM. Just stubs. */ +#include +#include +#include "tty.h" + +void +do_fkey_ctl(message *m) +{ +} + +void +do_input(message *m) +{ +} + +void +kb_init_once(void) +{ +} + +int +kbd_loadmap(endpoint_t endpt, cp_grant_id_t grant) +{ + return 0; +} + +void +kb_init(tty_t *tp) +{ +} diff --git a/minix/drivers/tty/tty/arch/earmv6hf/omap_serial.h b/minix/drivers/tty/tty/arch/earmv6hf/omap_serial.h new file mode 100644 index 000000000..765bfce63 --- /dev/null +++ b/minix/drivers/tty/tty/arch/earmv6hf/omap_serial.h @@ -0,0 +1,107 @@ +#ifndef _OMAP_SERIAL_H +#define _OMAP_SERIAL_H + +/* UART register map */ +#define OMAP3_UART1_BASE 0x4806A000 /* UART1 physical address */ +#define OMAP3_UART2_BASE 0x4806C000 /* UART2 physical address */ +#define OMAP3_UART3_BASE 0x49020000 /* UART3 physical address */ + +/* UART registers */ +#define OMAP3_THR 0 /* Transmit holding register */ +#define OMAP3_RHR 0 /* Receive holding register */ +#define OMAP3_DLL 0 /* Divisor latches low */ +#define OMAP3_DLH 1 /* Divisor latches high */ +#define OMAP3_IER 1 /* Interrupt enable register */ +#define OMAP3_IIR 2 /* Interrupt identification register */ +#define OMAP3_EFR 2 /* Extended features register */ +#define OMAP3_FCR 2 /* FIFO control register */ +#define OMAP3_LCR 3 /* Line control register */ +#define OMAP3_MCR 4 /* Modem control register */ +#define OMAP3_LSR 5 /* Line status register */ +#define OMAP3_MSR 6 /* Modem status register */ +#define OMAP3_TCR 6 +#define OMAP3_MDR1 0x08 /* Mode definition register 1 */ +#define OMAP3_MDR2 0x09 /* Mode definition register 2 */ +#define OMAP3_SCR 0x10 /* Supplementary control register */ +#define OMAP3_SSR 0x11 /* Supplementary status register */ +#define OMAP3_SYSC 0x15 /* System configuration register */ +#define OMAP3_SYSS 0x16 /* System status register */ + +/* Enhanced Features Register bits */ +#define UART_EFR_ECB (1 << 4)/* Enhanced control bit */ +#define UART_EFR_AUTO_CTS (1 << 6)/* auto cts enable */ +#define UART_EFR_AUTO_RTS (1 << 7)/* auto rts enable */ + +/* Interrupt Enable Register bits */ +#define UART_IER_MSI 0x08 /* Modem status interrupt */ +#define UART_IER_RLSI 0x04 /* Receiver line status interrupt */ +#define UART_IER_THRI 0x02 /* Transmitter holding register int. */ +#define UART_IER_RDI 0x01 /* Receiver data interrupt */ + +/* FIFO control register */ +#define OMAP_UART_FCR_RX_FIFO_TRIG_SHIFT 6 +#define OMAP_UART_FCR_RX_FIFO_TRIG_MASK (0x3 << 6) +#define OMAP_UART_FCR_TX_FIFO_TRIG_SHIFT 4 +#define OMAP_UART_FCR_TX_FIFO_TRIG_MASK (0x3 << 4) +#define UART_FCR_ENABLE_FIFO 0x01 /* Enable the fifo */ +#define UART_FCR_CLR_RCVR 0x02 /* Clear the RCVR FIFO */ +#define UART_FCR_CLR_XMIT 0x04 /* Clear the XMIT FIFO */ + +/* Interrupt Identification Register bits */ +#define UART_IIR_RDI 0x04 /* Data ready interrupt */ +#define UART_IIR_THRI 0x02 /* Transmitter holding register empty */ +#define UART_IIR_NO_INT 0x01 /* No interrupt is pending */ + +/* Line Control Register bits */ +#define UART_LCR_DLAB 0x80 /* Divisor latch access bit */ +#define UART_LCR_SBC 0x40 /* Set break control */ +#define UART_LCR_EPAR 0x10 /* Even parity select */ +#define UART_LCR_PARITY 0x08 /* Enable parity */ +#define UART_LCR_STOP 0x04 /* Stop bits; 0=1 bit, 1=2 bits */ +#define UART_LCR_WLEN5 0x00 /* Wordlength 5 bits */ +#define UART_LCR_WLEN6 0x01 /* Wordlength 6 bits */ +#define UART_LCR_WLEN7 0x02 /* Wordlength 7 bits */ +#define UART_LCR_WLEN8 0x03 /* Wordlength 8 bits */ + +#define UART_LCR_CONF_MODE_A UART_LCR_DLAB /* Configuration Mode A */ +#define UART_LCR_CONF_MODE_B 0xBF /* Configuration Mode B */ + +/* Line Status Register bits */ +#define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */ +#define UART_LSR_BI 0x10 /* Break condition */ +#define UART_LSR_DR 0x01 /* Data ready */ + +/* Modem Control Register bits */ +#define UART_MCR_TCRTLR 0x40 /* Access TCR/TLR */ +#define UART_MCR_OUT2 0x08 /* Out2 complement */ +#define UART_MCR_RTS 0x02 /* RTS complement */ +#define UART_MCR_DTR 0x01 /* DTR output low */ + +/* Mode Definition Register 1 bits */ +#define OMAP_MDR1_DISABLE 0x07 +#define OMAP_MDR1_MODE13X 0x03 +#define OMAP_MDR1_MODE16X 0x00 + +/* Modem Status Register bits */ +#define UART_MSR_DCD 0x80 /* Data Carrier Detect */ +#define UART_MSR_CTS 0x10 /* Clear to Send */ +#define UART_MSR_DDCD 0x08 /* Delta DCD */ + +/* Supplementary control Register bits */ +#define OMAP_UART_SCR_RX_TRIG_GRANU1_MASK (1 << 7) + +/* System Control Register bits */ +#define UART_SYSC_SOFTRESET 0x02 + +/* System Status Register bits */ +#define UART_SYSS_RESETDONE 0x01 + +/* Line status register fields */ +#define OMAP3_LSR_TX_FIFO_E (1 << 5) /* Transmit FIFO empty */ +#define OMAP3_LSR_RX_FIFO_E (1 << 0) /* Receive FIFO empty */ +#define OMAP3_LSR_RXOE (1 << 1) /* Overrun error.*/ + +/* Supplementary status register fields */ +#define OMAP3_SSR_TX_FIFO_FULL (1 << 0) /* Transmit FIFO full */ + +#endif /* _OMAP_SERIAL_H */ diff --git a/minix/drivers/tty/tty/arch/earmv6hf/rs232.c b/minix/drivers/tty/tty/arch/earmv6hf/rs232.c new file mode 100644 index 000000000..f9a9e8777 --- /dev/null +++ b/minix/drivers/tty/tty/arch/earmv6hf/rs232.c @@ -0,0 +1,848 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "omap_serial.h" +#include "tty.h" + +#if NR_RS_LINES > 0 + +#define UART_FREQ 48000000L /* timer frequency */ +#if 0 +#define DFLT_BAUD TSPEED_DEF /* default baud rate */ +#else +#define DFLT_BAUD B115200 /* default baud rate */ +#endif + + +#define RS_IBUFSIZE 40960 /* RS232 input buffer size */ +#define RS_OBUFSIZE 40960 /* RS232 output buffer size */ + +/* Input buffer watermarks. + * The external device is asked to stop sending when the buffer + * exactly reaches high water, or when TTY requests it. Sending restarts + * when the input buffer empties below the low watermark. + */ +#define RS_ILOWWATER (1 * RS_IBUFSIZE / 4) +#define RS_IHIGHWATER (3 * RS_IBUFSIZE / 4) + +/* Output buffer low watermark. + * TTY is notified when the output buffer empties below the low watermark, so + * it may continue filling the buffer if doing a large write. + */ +#define RS_OLOWWATER (1 * RS_OBUFSIZE / 4) + +/* Macros to handle flow control. + * Interrupts must be off when they are used. + * Time is critical - already the function call for outb() is annoying. + * If outb() can be done in-line, tests to avoid it can be dropped. + * istart() tells external device we are ready by raising RTS. + * istop() tells external device we are not ready by dropping RTS. + * DTR is kept high all the time (it probably should be raised by open and + * dropped by close of the device). + * OUT2 is also kept high all the time. + */ +#define istart(rs) \ + (serial_out((rs), OMAP3_MCR, UART_MCR_OUT2|UART_MCR_RTS|UART_MCR_DTR),\ + (rs)->idevready = TRUE) +#define istop(rs) \ + (serial_out((rs), OMAP3_MCR, UART_MCR_OUT2|UART_MCR_DTR), \ + (rs)->idevready = FALSE) + +/* Macro to tell if device is ready. The rs->cts field is set to UART_MSR_CTS + * if CLOCAL is in effect for a line without a CTS wire. + */ +#define devready(rs) ((serial_in(rs, OMAP3_MSR) | rs->cts) & UART_MSR_CTS) + +/* Macro to tell if transmitter is ready. */ +#define txready(rs) (serial_in(rs, OMAP3_LSR) & UART_LSR_THRE) + +/* RS232 device structure, one per device. */ +typedef struct rs232 { + tty_t *tty; /* associated TTY structure */ + + int icount; /* number of bytes in the input buffer */ + char *ihead; /* next free spot in input buffer */ + char *itail; /* first byte to give to TTY */ + char idevready; /* nonzero if we are ready to receive (RTS) */ + char cts; /* normally 0, but MS_CTS if CLOCAL is set */ + + unsigned char ostate; /* combination of flags: */ +#define ODONE 1 /* output completed (< output enable bits) */ +#define ORAW 2 /* raw mode for xoff disable (< enab. bits) */ +#define OWAKEUP 4 /* tty_wakeup() pending (asm code only) */ +#define ODEVREADY UART_MSR_CTS /* external device hardware ready (CTS) */ +#define OQUEUED 0x20 /* output buffer not empty */ +#define OSWREADY 0x40 /* external device software ready (no xoff) */ +#define ODEVHUP UART_MSR_DCD /* external device has dropped carrier */ +#define OSOFTBITS (ODONE | ORAW | OWAKEUP | OQUEUED | OSWREADY) + /* user-defined bits */ +#if (OSOFTBITS | ODEVREADY | ODEVHUP) == OSOFTBITS + /* a weak sanity check */ +#error /* bits are not unique */ +#endif + unsigned char oxoff; /* char to stop output */ + char inhibited; /* output inhibited? (follows tty_inhibited) */ + char drain; /* if set drain output and reconfigure line */ + int ocount; /* number of bytes in the output buffer */ + char *ohead; /* next free spot in output buffer */ + char *otail; /* next char to output */ + + phys_bytes phys_base; /* UART physical base address (I/O map) */ + unsigned int reg_offset; /* UART register offset */ + unsigned int ier; /* copy of ier register */ + unsigned int scr; /* copy of scr register */ + unsigned int fcr; /* copy of fcr register */ + unsigned int dll; /* copy of dll register */ + unsigned int dlh; /* copy of dlh register */ + unsigned int uartclk; /* UART clock rate */ + + unsigned char lstatus; /* last line status */ + int rx_overrun_events; + + int irq; /* irq for this line */ + int irq_hook_id; /* interrupt hook */ + int irq_hook_kernel_id; /* id as returned from sys_irqsetpolicy */ + + char ibuf[RS_IBUFSIZE]; /* input buffer */ + char obuf[RS_OBUFSIZE]; /* output buffer */ +} rs232_t; + +static rs232_t rs_lines[NR_RS_LINES]; + +typedef struct uart_port { + phys_bytes base_addr; + int irq; +} uart_port_t; + +/* OMAP3 UART base addresses. */ +static uart_port_t dm37xx_ports[] = { + { OMAP3_UART1_BASE, 72}, /* UART1 */ + { OMAP3_UART2_BASE, 73}, /* UART2 */ + { OMAP3_UART3_BASE, 74}, /* UART3 */ + { 0, 0 } +}; + +static uart_port_t am335x_ports[] = { + { 0x44E09000 , 72 }, /* UART0 */ + { 0, 0 }, + { 0, 0 }, + { 0, 0 } +}; + + +static int rs_write(tty_t *tp, int try); +static void rs_echo(tty_t *tp, int c); +static int rs_ioctl(tty_t *tp, int try); +static void rs_config(rs232_t *rs); +static int rs_read(tty_t *tp, int try); +static int rs_icancel(tty_t *tp, int try); +static int rs_ocancel(tty_t *tp, int try); +static void rs_ostart(rs232_t *rs); +static int rs_break_on(tty_t *tp, int try); +static int rs_break_off(tty_t *tp, int try); +static int rs_close(tty_t *tp, int try); +static int rs_open(tty_t *tp, int try); +static void rs232_handler(rs232_t *rs); +static void rs_reset(rs232_t *rs); +static unsigned int check_modem_status(rs232_t *rs); +static int termios_baud_rate(struct termios *term); + +static inline unsigned int readw(vir_bytes addr); +static inline unsigned int serial_in(rs232_t *rs, int offset); +static inline void serial_out(rs232_t *rs, int offset, int val); +static inline void writew(vir_bytes addr, int val); +static void write_chars(rs232_t *rs); +static void read_chars(rs232_t *rs, unsigned int status); + +static inline unsigned int +readw(vir_bytes addr) +{ + return *((volatile unsigned int *) addr); +} + +static inline void +writew(vir_bytes addr, int val) +{ + *((volatile unsigned int *) addr) = val; +} + +static inline unsigned int +serial_in(rs232_t *rs, int offset) +{ + offset <<= rs->reg_offset; + return readw(rs->phys_base + offset); +} + +static inline void +serial_out(rs232_t *rs, int offset, int val) +{ + offset <<= rs->reg_offset; + writew(rs->phys_base + offset, val); +} + +static void +rs_reset(rs232_t *rs) +{ + u32_t syss; + + serial_out(rs, OMAP3_SYSC, UART_SYSC_SOFTRESET); + + /* Poll until done */ + do { + syss = serial_in(rs, OMAP3_SYSS); + } while (!(syss & UART_SYSS_RESETDONE)); +} + +static int +rs_write(register tty_t *tp, int try) +{ +/* (*devwrite)() routine for RS232. */ + + rs232_t *rs = tp->tty_priv; + int r, count, ocount; + + if (rs->inhibited != tp->tty_inhibited) { + /* Inhibition state has changed. */ + rs->ostate |= OSWREADY; + if (tp->tty_inhibited) rs->ostate &= ~OSWREADY; + rs->inhibited = tp->tty_inhibited; + } + + if (rs->drain) { + /* Wait for the line to drain then reconfigure and continue + * output. */ + if (rs->ocount > 0) return 0; + rs->drain = FALSE; + rs_config(rs); + } + /* While there is something to do. */ + for (;;) { + ocount = buflen(rs->obuf) - rs->ocount; + count = bufend(rs->obuf) - rs->ohead; + if (count > ocount) count = ocount; + if (count > tp->tty_outleft) count = tp->tty_outleft; + if (count == 0 || tp->tty_inhibited) { + if (try) return 0; + break; + } + + if (try) return 1; + + /* Copy from user space to the RS232 output buffer. */ + if (tp->tty_outcaller == KERNEL) { + /* We're trying to print on kernel's behalf */ + memcpy(rs->ohead, + (char *) tp->tty_outgrant + tp->tty_outcum, + count); + } else { + if ((r = sys_safecopyfrom(tp->tty_outcaller, + tp->tty_outgrant, tp->tty_outcum, + (vir_bytes) rs->ohead, count)) != OK) { + return 0; + } + } + + /* Perform output processing on the output buffer. */ + out_process(tp, rs->obuf, rs->ohead, bufend(rs->obuf), &count, + &ocount); + if (count == 0) { + break; + } + + /* Assume echoing messed up by output. */ + tp->tty_reprint = TRUE; + + /* Bookkeeping. */ + rs->ocount += ocount; + rs_ostart(rs); + if ((rs->ohead += ocount) >= bufend(rs->obuf)) + rs->ohead -= buflen(rs->obuf); + tp->tty_outcum += count; + if ((tp->tty_outleft -= count) == 0) { + /* Output is finished, reply to the writer. */ + if (tp->tty_outcaller != KERNEL) + chardriver_reply_task(tp->tty_outcaller, + tp->tty_outid, tp->tty_outcum); + tp->tty_outcum = 0; + tp->tty_outcaller = NONE; + } + + } + if (tp->tty_outleft > 0 && tp->tty_termios.c_ospeed == B0) { + /* Oops, the line has hung up. */ + if (tp->tty_outcaller != KERNEL) + chardriver_reply_task(tp->tty_outcaller, tp->tty_outid, + EIO); + tp->tty_outleft = tp->tty_outcum = 0; + tp->tty_outcaller = NONE; + } + + return 1; +} + +static void +rs_echo(tty_t *tp, int character) +{ +/* Echo one character. (Like rs_write, but only one character, optionally.) */ + + rs232_t *rs = tp->tty_priv; + int count, ocount; + + ocount = buflen(rs->obuf) - rs->ocount; + if (ocount == 0) return; /* output buffer full */ + count = 1; + *rs->ohead = character; /* add one character */ + + out_process(tp, rs->obuf, rs->ohead, bufend(rs->obuf), &count, &ocount); + if (count == 0) return; + + rs->ocount += ocount; + rs_ostart(rs); + if ((rs->ohead += ocount) >= bufend(rs->obuf)) + rs->ohead -= buflen(rs->obuf); +} + +static int +rs_ioctl(tty_t *tp, int UNUSED(dummy)) +{ +/* Reconfigure the line as soon as the output has drained. */ + rs232_t *rs = tp->tty_priv; + + rs->drain = TRUE; + return 0; /* dummy */ +} + +static unsigned int +omap_get_divisor(rs232_t *rs, unsigned int baud) +{ +/* Calculate divisor value. The 16750 has two oversampling modes to reach + * high baud rates with little error rate (see table 17-1 in OMAP TRM). + * Baud rates 460800, 921600, 1843200, and 3686400 use 13x oversampling, + * the other rates 16x. The baud rate is calculated as follows: + * baud rate = (functional clock / oversampling) / divisor. + */ + + unsigned int oversampling; + assert(baud != 0); + + switch(baud) { + case B460800: /* Fall through */ + case B921600: /* Fall through */ +#if 0 + case B1843200: /* Fall through */ + case B3686400: +#endif + oversampling = 13; break; + default: oversampling = 16; + } + + return (rs->uartclk / oversampling) / baud; +} + +static int +termios_baud_rate(struct termios *term) +{ + int baud; + switch(term->c_ospeed) { + case B300: baud = 300; break; + case B600: baud = 600; break; + case B1200: baud = 1200; break; + case B2400: baud = 2400; break; + case B4800: baud = 4800; break; + case B9600: baud = 9600; break; + case B38400: baud = 38400; break; + case B57600: baud = 57600; break; + case B115200: baud = 115200; break; + case B0: + default: + /* Reset the speed to the default speed, then call ourselves + * to convert the default speed to a baudrate. This call will + * always return a value without inducing another recursive + * call. */ + term->c_ospeed = DFLT_BAUD; + baud = termios_baud_rate(term); + } + + return baud; +} +static void rs_config(rs232_t *rs) +{ +/* Set various line control parameters for RS232 I/O. */ + tty_t *tp = rs->tty; + unsigned int divisor, efr, lcr, mcr, baud; + + /* Fifo and DMA settings */ + /* See OMAP35x TRM 17.5.1.1.2 */ + lcr = serial_in(rs, OMAP3_LCR); /* 1a */ + serial_out(rs, OMAP3_LCR, UART_LCR_CONF_MODE_B); /* 1b */ + efr = serial_in(rs, OMAP3_EFR); /* 2a */ + serial_out(rs, OMAP3_EFR, efr | UART_EFR_ECB); /* 2b */ + serial_out(rs, OMAP3_LCR, UART_LCR_CONF_MODE_A); /* 3 */ + mcr = serial_in(rs, OMAP3_MCR); /* 4a */ + serial_out(rs, OMAP3_MCR, mcr | UART_MCR_TCRTLR); /* 4b */ + /* Set up FIFO */ + rs->fcr = 0; + /* Set FIFO interrupt trigger levels high */ + rs->fcr |= (0x3 << OMAP_UART_FCR_RX_FIFO_TRIG_SHIFT); + rs->fcr |= (0x3 << OMAP_UART_FCR_TX_FIFO_TRIG_SHIFT); + rs->fcr |= UART_FCR_ENABLE_FIFO; + serial_out(rs, OMAP3_FCR, rs->fcr); /* 5 */ + serial_out(rs, OMAP3_LCR, UART_LCR_CONF_MODE_B); /* 6 */ + /* DMA triggers, not supported by this driver */ /* 7 */ + rs->scr = OMAP_UART_SCR_RX_TRIG_GRANU1_MASK; + serial_out(rs, OMAP3_SCR, rs->scr); /* 8 */ + serial_out(rs, OMAP3_EFR, efr); /* 9 */ + serial_out(rs, OMAP3_LCR, UART_LCR_CONF_MODE_A); /* 10 */ + serial_out(rs, OMAP3_MCR, mcr); /* 11 */ + serial_out(rs, OMAP3_LCR, lcr); /* 12 */ + + /* RS232 needs to know the xoff character, and if CTS works. */ + rs->oxoff = tp->tty_termios.c_cc[VSTOP]; + rs->cts = (tp->tty_termios.c_cflag & CLOCAL) ? UART_MSR_CTS : 0; + baud = termios_baud_rate(&tp->tty_termios); + + /* Look up the 16750 rate divisor from the output speed. */ + divisor = omap_get_divisor(rs, baud); + rs->dll = divisor & 0xFF; + rs->dlh = divisor >> 8; + + /* Compute line control flag bits. */ + lcr = 0; + if (tp->tty_termios.c_cflag & PARENB) { + lcr |= UART_LCR_PARITY; + if (!(tp->tty_termios.c_cflag & PARODD)) lcr |= UART_LCR_EPAR; + } + if (tp->tty_termios.c_cflag & CSTOPB) lcr |= UART_LCR_STOP; + switch(tp->tty_termios.c_cflag & CSIZE) { + case CS5: + lcr |= UART_LCR_WLEN5; + break; + case CS6: + lcr |= UART_LCR_WLEN6; + break; + case CS7: + lcr |= UART_LCR_WLEN7; + break; + default: + case CS8: + lcr |= UART_LCR_WLEN8; + break; + } + + /* Lock out interrupts while setting the speed. The receiver register + * is going to be hidden by the div_low register, but the input + * interrupt handler relies on reading it to clear the interrupt and + * avoid looping forever. + */ + + if (sys_irqdisable(&rs->irq_hook_kernel_id) != OK) + panic("unable to disable interrupts"); + + /* Select the baud rate divisor registers and change the rate. */ + /* See OMAP35x TRM 17.5.1.1.3 */ + serial_out(rs, OMAP3_MDR1, OMAP_MDR1_DISABLE); /* 1 */ + serial_out(rs, OMAP3_LCR, UART_LCR_CONF_MODE_B); /* 2 */ + efr = serial_in(rs, OMAP3_EFR); /* 3a */ + serial_out(rs, OMAP3_EFR, efr | UART_EFR_ECB); /* 3b */ + serial_out(rs, OMAP3_LCR, 0); /* 4 */ + serial_out(rs, OMAP3_IER, 0); /* 5 */ + serial_out(rs, OMAP3_LCR, UART_LCR_CONF_MODE_B); /* 6 */ + serial_out(rs, OMAP3_DLL, rs->dll); /* 7 */ + serial_out(rs, OMAP3_DLH, rs->dlh); /* 7 */ + serial_out(rs, OMAP3_LCR, 0); /* 8 */ + serial_out(rs, OMAP3_IER, rs->ier); /* 9 */ + serial_out(rs, OMAP3_LCR, UART_LCR_CONF_MODE_B); /* 10 */ + serial_out(rs, OMAP3_EFR, efr); /* 11 */ + serial_out(rs, OMAP3_LCR, lcr); /* 12 */ + if (baud > 230400 && baud != 3000000) + serial_out(rs, OMAP3_MDR1, OMAP_MDR1_MODE13X); /* 13 */ + else + serial_out(rs, OMAP3_MDR1, OMAP_MDR1_MODE16X); + + rs->ostate = devready(rs) | ORAW | OSWREADY; /* reads MSR */ + if ((tp->tty_termios.c_lflag & IXON) && rs->oxoff != _POSIX_VDISABLE) + rs->ostate &= ~ORAW; + (void) serial_in(rs, OMAP3_IIR); + + if (sys_irqenable(&rs->irq_hook_kernel_id) != OK) + panic("unable to enable interrupts"); +} + +void +rs_init(tty_t *tp) +{ +/* Initialize RS232 for one line. */ + register rs232_t *rs; + int line; + uart_port_t this_omap3; + char l[10]; + struct minix_mem_range mr; + struct machine machine; + + /* Associate RS232 and TTY structures. */ + line = tp - &tty_table[NR_CONS]; + + /* See if kernel debugging is enabled; if so, don't initialize this + * serial line, making tty not look at the irq and returning ENXIO + * for all requests on it from userland. (The kernel will use it.) + */ + if(env_get_param(SERVARNAME, l, sizeof(l)-1) == OK && atoi(l) == line){ + printf("TTY: rs232 line %d not initialized (used by kernel)\n", + line); + return; + } + + rs = tp->tty_priv = &rs_lines[line]; + rs->tty = tp; + + /* Set up input queue. */ + rs->ihead = rs->itail = rs->ibuf; + + sys_getmachine(&machine); + + if (BOARD_IS_BBXM(machine.board_id)){ + this_omap3 = dm37xx_ports[line]; + } else if (BOARD_IS_BB(machine.board_id)){ + this_omap3 = am335x_ports[line]; + } else { + return; + } + if (this_omap3.base_addr == 0) return; + + /* Configure memory access */ + mr.mr_base = rs->phys_base; + mr.mr_limit = rs->phys_base + 0x100; + if (sys_privctl(SELF, SYS_PRIV_ADD_MEM, &mr) != OK) { + panic("Unable to request access to UART memory"); + } + rs->phys_base = (vir_bytes) vm_map_phys(SELF, + (void *) this_omap3.base_addr, 0x100); + + if (rs->phys_base == (vir_bytes) MAP_FAILED) { + panic("Unable to request access to UART memory"); + } + rs->reg_offset = 2; + + rs->uartclk = UART_FREQ; + rs->ohead = rs->otail = rs->obuf; + + /* Override system default baud rate. We do this because u-boot + * configures the UART for a baud rate of 115200 b/s and the kernel + * directly sends data over serial out upon boot up. If we then + * suddenly change the settings, the output will be garbled during + * booting. + */ + tp->tty_termios.c_ospeed = DFLT_BAUD; + + /* Configure IRQ */ + rs->irq = this_omap3.irq; + + /* callback with irq line number + 1 because using line number 0 + fails eslewhere */ + rs->irq_hook_kernel_id = rs->irq_hook_id = line + 1; + + /* sys_irqsetpolicy modifies irq_hook_kernel_id. this modified id + * needs to be used in sys_irqenable and similar calls. + */ + if (sys_irqsetpolicy(rs->irq, 0, &rs->irq_hook_kernel_id) != OK) { + printf("RS232: Couldn't obtain hook for irq %d\n", rs->irq); + } else { + if (sys_irqenable(&rs->irq_hook_kernel_id) != OK) { + printf("RS232: Couldn't enable irq %d (hooked)\n", + rs->irq); + } + } + + /* When we get called back we get called back using the original + * hook_id bit set. e.g. if we register with hook_id 5 the callback + * calls us with the 5 th bit set */ + rs_irq_set |= (1 << (rs->irq_hook_id )); + + /* Enable interrupts */ + rs_reset(rs); + rs->ier = UART_IER_RLSI | UART_IER_RDI | UART_IER_MSI; + rs_config(rs); + + /* Fill in TTY function hooks. */ + tp->tty_devread = rs_read; + tp->tty_devwrite = rs_write; + tp->tty_echo = rs_echo; + tp->tty_icancel = rs_icancel; + tp->tty_ocancel = rs_ocancel; + tp->tty_ioctl = rs_ioctl; + tp->tty_break_on = rs_break_on; + tp->tty_break_off = rs_break_off; + tp->tty_open = rs_open; + tp->tty_close = rs_close; + + /* Tell external device we are ready. */ + istart(rs); +} + +void +rs_interrupt(message *m) +{ + unsigned long irq_set; + int line; + rs232_t *rs; + + irq_set = m->m_notify.interrupts; + for (line = 0, rs = rs_lines; line < NR_RS_LINES; line++, rs++) { + if (irq_set & (1 << rs->irq_hook_id)) { + rs232_handler(rs); + if (sys_irqenable(&rs->irq_hook_kernel_id) != OK) + panic("unable to enable interrupts"); + } + } +} + +static int +rs_icancel(tty_t *tp, int UNUSED(dummy)) +{ +/* Cancel waiting input. */ + rs232_t *rs = tp->tty_priv; + + rs->icount = 0; + rs->itail = rs->ihead; + istart(rs); + return 0; /* dummy */ +} + +static int +rs_ocancel(tty_t *tp, int UNUSED(dummy)) +{ +/* Cancel pending output. */ + rs232_t *rs = tp->tty_priv; + + rs->ostate &= ~(ODONE | OQUEUED); + rs->ocount = 0; + rs->otail = rs->ohead; + + return 0; /* dummy */ +} + +static int +rs_read(tty_t *tp, int try) +{ +/* Process characters from the circular input buffer. */ + + rs232_t *rs = tp->tty_priv; + int icount, count, ostate; + + if (!(tp->tty_termios.c_cflag & CLOCAL)) { + if (try) return 1; + + /* Send a SIGHUP if hangup detected. */ + ostate = rs->ostate; + rs->ostate &= ~ODEVHUP; /* save ostate, clear DEVHUP */ + if (ostate & ODEVHUP) { + sigchar(tp, SIGHUP, 1); + tp->tty_termios.c_ospeed = B0;/* Disable further I/O.*/ + return 0; + } + } + + if (try) { + return(rs->icount > 0); + } + + while ((count = rs->icount) > 0) { + icount = bufend(rs->ibuf) - rs->itail; + if (count > icount) count = icount; + + /* Perform input processing on (part of) the input buffer. */ + if ((count = in_process(tp, rs->itail, count)) == 0) break; + rs->icount -= count; + if (!rs->idevready && rs->icount < RS_ILOWWATER) istart(rs); + if ((rs->itail += count) == bufend(rs->ibuf)) + rs->itail = rs->ibuf; + } + + return 0; +} + +static void +rs_ostart(rs232_t *rs) +{ +/* Tell RS232 there is something waiting in the output buffer. */ + + rs->ostate |= OQUEUED; + if (txready(rs)) write_chars(rs); +} + +static int +rs_break_on(tty_t *tp, int UNUSED(dummy)) +{ +/* Raise break condition */ + rs232_t *rs = tp->tty_priv; + unsigned int lsr; + + lsr = serial_in(rs, OMAP3_LSR); + serial_out(rs, OMAP3_LSR, lsr | UART_LSR_BI); + return 0; /* dummy */ +} + +static int +rs_break_off(tty_t *tp, int UNUSED(dummy)) +{ +/* Clear break condition */ + rs232_t *rs = tp->tty_priv; + unsigned int lsr; + + lsr = serial_in(rs, OMAP3_LSR); + serial_out(rs, OMAP3_LSR, lsr & ~UART_LSR_BI); + return 0; /* dummy */ +} + +static int +rs_open(tty_t *tp, int UNUSED(dummy)) +{ + /* Set the speed to 115200 by default */ + tp->tty_termios.c_ospeed = DFLT_BAUD; + return 0; +} + +static int +rs_close(tty_t *tp, int UNUSED(dummy)) +{ +/* The line is closed; optionally hang up. */ + rs232_t *rs = tp->tty_priv; + + if (tp->tty_termios.c_cflag & HUPCL) { + serial_out(rs, OMAP3_MCR, UART_MCR_OUT2|UART_MCR_RTS); + if (rs->ier & UART_IER_THRI) { + rs->ier &= ~UART_IER_THRI; + serial_out(rs, OMAP3_IER, rs->ier); + } + } + return 0; /* dummy */ +} + +/* Low level (interrupt) routines. */ + +static void +rs232_handler(struct rs232 *rs) +{ +/* Handle interrupt of a UART port */ + unsigned int iir, lsr; + + iir = serial_in(rs, OMAP3_IIR); + if (iir & UART_IIR_NO_INT) /* No interrupt */ + return; + + lsr = serial_in(rs, OMAP3_LSR); + if (iir & UART_IIR_RDI) { /* Data ready interrupt */ + if (lsr & UART_LSR_DR) { + read_chars(rs, lsr); + } + } + check_modem_status(rs); + if (iir & UART_IIR_THRI) { + if (lsr & UART_LSR_THRE) { + /* Ready to send and space available */ + write_chars(rs); + } + } +} + +static void +read_chars(rs232_t *rs, unsigned int status) +{ + unsigned char c; + + if(serial_in(rs,OMAP3_LSR) & OMAP3_LSR_RXOE) { + rs->rx_overrun_events++; + } + + /* check the line status to know if there are more chars */ + while (serial_in(rs, OMAP3_LSR) & UART_LSR_DR) { + c = serial_in(rs, OMAP3_RHR); + if (!(rs->ostate & ORAW)) { + if (c == rs->oxoff) { + rs->ostate &= ~OSWREADY; + } else if (!(rs->ostate & OSWREADY)) { + rs->ostate = OSWREADY; + } + } + + if (rs->icount == buflen(rs->ibuf)) { + /* no buffer space? keep reading */ + continue; + } + + if (++rs->icount == RS_IHIGHWATER && rs->idevready) { + istop(rs); + } + + *rs->ihead = c; + if (++rs->ihead == bufend(rs->ibuf)) { + rs->ihead = rs->ibuf; + } + + if (rs->icount == 1) { + rs->tty->tty_events = 1; + } + } +} + +static void +write_chars(rs232_t *rs) +{ +/* If there is output to do and everything is ready, do it (local device is + * known ready). + * Notify TTY when the buffer goes empty. + */ + + if (rs->ostate >= (ODEVREADY | OQUEUED | OSWREADY)) { + /* Bit test allows ORAW and requires the others. */ + serial_out(rs, OMAP3_THR, *rs->otail); + if (++rs->otail == bufend(rs->obuf)) + rs->otail = rs->obuf; + if (--rs->ocount == 0) { + /* Turn on ODONE flag, turn off OQUEUED */ + rs->ostate ^= (ODONE | OQUEUED); + rs->tty->tty_events = 1; + if (rs->ier & UART_IER_THRI) { + rs->ier &= ~UART_IER_THRI; + serial_out(rs, OMAP3_IER, rs->ier); + } + } else { + if (rs->icount == RS_OLOWWATER) + rs->tty->tty_events = 1; + if (!(rs->ier & UART_IER_THRI)) { + rs->ier |= UART_IER_THRI; + serial_out(rs, OMAP3_IER, rs->ier); + } + } + } +} + +static unsigned int +check_modem_status(rs232_t *rs) +{ +/* Check modem status */ + + unsigned int msr; + + msr = serial_in(rs, OMAP3_MSR); /* Resets modem interrupt */ + if ((msr & (UART_MSR_DCD|UART_MSR_DDCD)) == UART_MSR_DDCD) { + rs->ostate |= ODEVHUP; + rs->tty->tty_events = 1; + } + + if (!devready(rs)) + rs->ostate &= ~ODEVREADY; + else + rs->ostate |= ODEVREADY; + + return msr; +} + +#endif /* NR_RS_LINES > 0 */ + diff --git a/minix/drivers/usb/Makefile b/minix/drivers/usb/Makefile index 6ebeeb593..9375f9337 100644 --- a/minix/drivers/usb/Makefile +++ b/minix/drivers/usb/Makefile @@ -1,6 +1,6 @@ .include -.if ${MACHINE_ARCH} == "earm" +.if ((${MACHINE_ARCH} == "earm") || (${MACHINE_ARCH} == "earmv6hf") ) SUBDIR+= usbd .endif # ${MACHINE_ARCH} == "earm" diff --git a/minix/drivers/usb/usbd/Makefile b/minix/drivers/usb/usbd/Makefile index 739f2f56d..2acda52f2 100644 --- a/minix/drivers/usb/usbd/Makefile +++ b/minix/drivers/usb/usbd/Makefile @@ -1,7 +1,7 @@ # Makefile for usb host controllers .include -.if ${MACHINE_ARCH} == "earm" +.if ((${MACHINE_ARCH} == "earm") || (${MACHINE_ARCH} == "earmv6hf") ) SUBDIR= .WAIT base/earm .endif diff --git a/minix/drivers/video/Makefile b/minix/drivers/video/Makefile index 747857337..fd0781690 100644 --- a/minix/drivers/video/Makefile +++ b/minix/drivers/video/Makefile @@ -1,6 +1,6 @@ .include -.if ${MACHINE_ARCH} == "earm" +.if ((${MACHINE_ARCH} == "earm") || (${MACHINE_ARCH} == "earmv6hf") ) SUBDIR+= fb SUBDIR+= tda19988 .endif # ${MACHINE_ARCH} == "earm" diff --git a/minix/drivers/video/fb/arch/earmv6hf/Makefile.inc b/minix/drivers/video/fb/arch/earmv6hf/Makefile.inc new file mode 100644 index 000000000..2afe6fe56 --- /dev/null +++ b/minix/drivers/video/fb/arch/earmv6hf/Makefile.inc @@ -0,0 +1,7 @@ +# Makefile for arch-dependent framebuffer code +.include + +HERE=${.CURDIR}/arch/${MACHINE_ARCH} +.PATH: ${HERE} + +SRCS += fb_arch.c diff --git a/minix/drivers/video/fb/arch/earmv6hf/dss.h b/minix/drivers/video/fb/arch/earmv6hf/dss.h new file mode 100644 index 000000000..4e5a2aec6 --- /dev/null +++ b/minix/drivers/video/fb/arch/earmv6hf/dss.h @@ -0,0 +1,65 @@ +#ifndef __DSS_H__ +#define __DSS_H__ + +/* DSS Base Registers */ +#define OMAP3_DSS_BASE 0x48050000 +#define OMAP3_DISPC_BASE 0x48050400 +#define OMAP3_VENC_BASE 0x48050C00 + +#define OMAP3_DSS_SYSCONFIG(b) (b + 0x10) +#define OMAP3_DSS_SYSSTATUS(b) (b + 0x14) + +#define OMAP3_DISPC_IRQSTATUS(b) (b + 0x18) +#define OMAP3_DISPC_CONTROL(b) (b + 0x40) +#define OMAP3_DISPC_CONFIG(b) (b + 0x44) +#define OMAP3_DISPC_DEFAULT_COLOR0(b) (b + 0x4c) +#define OMAP3_DISPC_DEFAULT_COLOR1(b) (b + 0x50) +#define OMAP3_DISPC_TIMINGH(b) (b + 0x64) +#define OMAP3_DISPC_TIMINGV(b) (b + 0x68) +#define OMAP3_DISPC_POL_FREQ(b) (b + 0x6c) +#define OMAP3_DISPC_DIVISOR(b) (b + 0x70) +#define OMAP3_DISPC_SIZE_DIG(b) (b + 0x78) +#define OMAP3_DISPC_SIZE_LCD(b) (b + 0x7c) +#define OMAP3_DISPC_GFX_BA0(b) (b + 0x80) +#define OMAP3_DISPC_GFX_BA1(b) (b + 0x84) +#define OMAP3_DISPC_GFX_SIZE(b) (b + 0x8c) +#define OMAP3_DISPC_GFX_ATTRIBUTES(b) (b + 0xa0) +#define OMAP3_DISPC_GFX_ROW_INC(b) (b + 0xac) +#define OMAP3_DISPC_GFX_PIXEL_INC(b) (b + 0xb0) + +#define LOADMODE_SHIFT 1 +#define TFTSTN_SHIFT 3 +#define DATALINES_SHIFT 8 +#define GFXFORMAT_SHIFT 1 +#define GFXBURSTSIZE_SHIFT 6 + +#define DSS_SOFTRESET (1 << 1) +#define DSS_RESETDONE (1 << 0) + +#define DISPC_LCDENABLE (1 << 0) +#define DISPC_DIGITALENABLE (1 << 1) +#define DISPC_GOLCD (1 << 5) +#define DISPC_GODIGITAL (1 << 6) +#define DISPC_GPIN0 (1 << 13) +#define DISPC_GPIN1 (1 << 14) +#define DISPC_GPOUT0 (1 << 15) +#define DISPC_GPOUT1 (1 << 16) +#define DISPC_ENABLESIGNAL (1 << 28) +#define DISPC_FRAMEDONE (1 << 0) +#define DISPC_GFXENABLE (1 << 0) +#define DISPC_GFXFORMAT_BMP1 0x0 +#define DISPC_GFXFORMAT_BMP2 0x1 +#define DISPC_GFXFORMAT_BMP4 0x2 +#define DISPC_GFXFORMAT_BMP8 0x3 +#define DISPC_GFXFORMAT_RGB12 0x4 +#define DISPC_GFXFORMAT_ARGB16 0x5 +#define DISPC_GFXFORMAT_RGB16 0x6 +#define DISPC_GFXFORMAT_RGB24 0x8 +#define DISPC_GFXFORMAT_RGB24P 0x9 +#define DISPC_GFXFORMAT_ARGB32 0xC +#define DISPC_GFXFORMAT_RGBA32 0xD +#define DISPC_GFXFORMAT_RGBx 0xE +#define DISPC_GFXBURSTSIZE_4 0x0 +#define DISPC_GFXBURSTSIZE_8 0x1 +#define DISPC_GFXBURSTSIZE_16 0x2 +#endif /* __DSS_H__ */ diff --git a/minix/drivers/video/fb/arch/earmv6hf/fb_arch.c b/minix/drivers/video/fb/arch/earmv6hf/fb_arch.c new file mode 100644 index 000000000..6e3e58a1c --- /dev/null +++ b/minix/drivers/video/fb/arch/earmv6hf/fb_arch.c @@ -0,0 +1,408 @@ +/* Architecture dependent part for the framebuffer on the OMAP3. + * There's obvious room for improvement. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "dss.h" +#include "fb.h" + +/* default / fallback resolution if EDID reading fails */ +#define SCREEN_WIDTH 1024 +#define SCREEN_HEIGHT 600 +#define PAGES_NR 2 + +#define NSUPPORTED_MODES (4) + +/* List of valid modes from TRM 7.1 + * Other modes might work (like the default 1024x600), but no guarantees. + */ +struct supported_modes { + int hdisplay; + int vdisplay; +} omap_supported_modes[NSUPPORTED_MODES] = { + { .hdisplay = 1024, .vdisplay = 768 }, /* XGA */ + { .hdisplay = 1280, .vdisplay = 800 }, /* WXGA */ + { .hdisplay = 1400, .vdisplay = 1050 }, /* SXGA+ */ + { .hdisplay = 1280, .vdisplay = 720 } /* HD 720p */ +}; + +/* local function prototypes */ +static struct videomode *choose_mode(struct edid_info *info); +static void configure_with_defaults(int minor); +static int configure_with_edid(int minor, struct edid_info *info); + +/* globals */ +static vir_bytes dss_phys_base; /* Address of dss phys memory map */ +static vir_bytes dispc_phys_base; /* Address of dispc phys memory map */ +static vir_bytes fb_vir; +static phys_bytes fb_phys; +static size_t fb_size; +static int initialized = 0; + +struct panel_config { + u32_t timing_h; + u32_t timing_v; + u32_t pol_freq; + u32_t divisor; + u32_t lcd_size; + u32_t panel_type; + u32_t data_lines; + u32_t load_mode; + u32_t panel_color; +}; + +static const struct panel_config default_cfg = { + /* See OMAP TRM section 15.7 for the register values/encoding */ + .timing_h = 0x1a4024c9, /* Horizontal timing */ + .timing_v = 0x02c00509, /* Vertical timing */ + .pol_freq = 0x00007028, /* Pol Freq */ + .divisor = 0x00010001, /* 96MHz Pixel Clock */ + .lcd_size = ((SCREEN_HEIGHT - 1) << 16 | (SCREEN_WIDTH - 1)), + .panel_type = 0x01, /* TFT */ + .data_lines = 0x03, /* 24 Bit RGB */ + .load_mode = 0x02, /* Frame Mode */ + .panel_color = 0xFFFFFF /* WHITE */ +}; + +static struct panel_config omap_cfg[FB_DEV_NR]; + +static const struct fb_fix_screeninfo default_fbfs = { + .xpanstep = 0, + .ypanstep = 0, + .ywrapstep = 0, + .line_length = SCREEN_WIDTH * 4, + .mmio_start = 0, /* Not implemented for char. special, so */ + .mmio_len = 0 /* these are set to 0 */ +}; + +static struct fb_fix_screeninfo omap_fbfs[FB_DEV_NR]; + +static const struct fb_var_screeninfo default_fbvs = { + .xres = SCREEN_WIDTH, + .yres = SCREEN_HEIGHT, + .xres_virtual = SCREEN_WIDTH, + .yres_virtual = SCREEN_HEIGHT*2, + .xoffset = 0, + .yoffset = 0, + .bits_per_pixel = 32, + .red = { + .offset = 16, + .length = 8, + .msb_right = 0 + }, + .green = { + .offset = 8, + .length = 8, + .msb_right = 0 + }, + .blue = { + .offset = 0, + .length = 8, + .msb_right = 0 + }, + .transp = { + .offset = 24, + .length = 8, + .msb_right = 0 + } +}; + +static struct fb_var_screeninfo omap_fbvs[FB_DEV_NR]; + +/* logging - use with log_warn(), log_info(), log_debug(), log_trace() */ +static struct log log = { + .name = "fb", + .log_level = LEVEL_INFO, + .log_func = default_log +}; + +static inline u32_t +readw(vir_bytes addr) +{ + return *((volatile u32_t *) addr); +} + +static inline void +writew(vir_bytes addr, u32_t val) +{ + *((volatile u32_t *) addr) = val; +} + +static struct videomode * +choose_mode(struct edid_info *info) +{ + int i, j; + + /* choose the highest resolution supported by both the SoC and screen */ + for (i = info->edid_nmodes - 1; i >= 0; i--) { + for (j = NSUPPORTED_MODES - 1; j >= 0; j--) { + + if (info->edid_modes[i].hdisplay == + omap_supported_modes[j].hdisplay && + info->edid_modes[i].vdisplay == + omap_supported_modes[j].vdisplay) { + + return &(info->edid_modes[i]); + } + } + } + + return NULL; +} + +static int +configure_with_edid(int minor, struct edid_info *info) +{ + struct videomode *mode; + + if (info == NULL || minor < 0 || minor >= FB_DEV_NR) { + log_warn(&log, "Invalid minor #%d or info == NULL\n", minor); + return -1; + } + + /* If debugging or tracing, print the contents of info */ + if (log.log_level >= LEVEL_DEBUG) { + log_debug(&log, "--- EDID - START ---\n"); + edid_print(info); + log_debug(&log, "--- EDID - END ---\n"); + } + + /* Choose the preferred mode. */ + mode = choose_mode(info); + if (mode == NULL) { + log_warn(&log, "Couldn't find a supported resolution.\n"); + return -1; + } + + /* + * apply the default settings since we don't overwrite every field + */ + configure_with_defaults(minor); + + /* + * apply the settings corresponding to the given EDID + */ + + /* panel_config */ + omap_cfg[minor].lcd_size = ((mode->vdisplay - 1) << 16 | (mode->hdisplay - 1)); + + if (EDID_FEATURES_DISP_TYPE(info->edid_features) == + EDID_FEATURES_DISP_TYPE_MONO) { + omap_cfg[minor].panel_type = 0x00; /* Mono */ + } else { + omap_cfg[minor].panel_type = 0x01; /* RGB/Color */ + } + + /* fb_fix_screeninfo */ + omap_fbfs[minor].line_length = mode->hdisplay * 4; + + /* fb_var_screeninfo */ + omap_fbvs[minor].xres = mode->hdisplay; + omap_fbvs[minor].yres = mode->vdisplay; + omap_fbvs[minor].xres_virtual = mode->hdisplay; + omap_fbvs[minor].yres_virtual = mode->vdisplay*2; + + return OK; +} + +static void +configure_with_defaults(int minor) +{ + if (minor < 0 || minor >= FB_DEV_NR) { + log_warn(&log, "Invalid minor #%d\n", minor); + return; + } + + /* copy the default values into this minor's configuration */ + memcpy(&omap_cfg[minor], &default_cfg, sizeof(struct panel_config)); + memcpy(&omap_fbfs[minor], &default_fbfs, sizeof(struct fb_fix_screeninfo)); + memcpy(&omap_fbvs[minor], &default_fbvs, sizeof(struct fb_var_screeninfo)); +} + +static void +arch_configure_display(int minor) +{ +/* Tell hardware where frame buffer is and turn display on */ + u32_t off, rdispc; + + if (!initialized) return; + if (minor != 0) return; + + off = omap_fbvs[minor].yoffset * omap_fbvs[minor].xres_virtual * (omap_fbvs[minor].bits_per_pixel/8); + + writew((vir_bytes) OMAP3_DISPC_GFX_BA0(dispc_phys_base), + fb_phys + (phys_bytes) off); + rdispc = readw((vir_bytes) OMAP3_DISPC_CONTROL(dispc_phys_base)); + rdispc |= DISPC_LCDENABLE | DISPC_DIGITALENABLE | DISPC_GOLCD | + DISPC_GODIGITAL | DISPC_GPOUT0 | DISPC_GPOUT1; + writew((vir_bytes) OMAP3_DISPC_CONTROL(dispc_phys_base), rdispc); +} + +int +arch_get_device(int minor, struct device *dev) +{ + if (!initialized) return ENXIO; + if (minor != 0) return ENXIO; + dev->dv_base = fb_vir; + dev->dv_size = fb_size; + return OK; +} + +int +arch_get_varscreeninfo(int minor, struct fb_var_screeninfo *fbvsp) +{ + if (!initialized) return ENXIO; + if (minor != 0) return ENXIO; + + *fbvsp = omap_fbvs[minor]; + return OK; +} + +int +arch_put_varscreeninfo(int minor, struct fb_var_screeninfo *fbvsp) +{ + int r = OK; + + assert(fbvsp != NULL); + + if (!initialized) return ENXIO; + if (minor != 0) return ENXIO; + + /* For now we only allow to play with the yoffset setting */ + if (fbvsp->yoffset != omap_fbvs[minor].yoffset) { + if (fbvsp->yoffset < 0 || fbvsp->yoffset > omap_fbvs[minor].yres) { + return EINVAL; + } + + omap_fbvs[minor].yoffset = fbvsp->yoffset; + } + + /* Now update hardware with new settings */ + arch_configure_display(minor); + return OK; +} + +int +arch_get_fixscreeninfo(int minor, struct fb_fix_screeninfo *fbfsp) +{ + if (!initialized) return ENXIO; + if (minor != 0) return ENXIO; + + *fbfsp = omap_fbfs[minor]; + return OK; +} + +int +arch_pan_display(int minor, struct fb_var_screeninfo *fbvsp) +{ + return arch_put_varscreeninfo(minor, fbvsp); +} + +int +arch_fb_init(int minor, struct edid_info *info) +{ + int r; + u32_t rdispc; + struct minix_mem_range mr; + + const struct panel_config *panel_cfg = &omap_cfg[minor]; + + if (minor != 0) return ENXIO; /* We support only one minor */ + + if (initialized) { + return OK; + } else if (info != NULL) { + log_debug(&log, "Configuring Settings based on EDID...\n"); + r = configure_with_edid(minor, info); + if (r != OK) { + log_warn(&log, "EDID config failed. Using defaults.\n"); + configure_with_defaults(minor); + } + } else { + log_debug(&log, "Loading Default Settings...\n"); + configure_with_defaults(minor); + } + + initialized = 1; + + /* Configure DSS memory access */ + mr.mr_base = OMAP3_DSS_BASE; + mr.mr_limit = mr.mr_base + 0x60; + if (sys_privctl(SELF, SYS_PRIV_ADD_MEM, &mr) != OK) { + panic("Unable to request access to DSS(1) memory"); + } + + dss_phys_base = (vir_bytes) vm_map_phys(SELF, (void *) OMAP3_DSS_BASE, + 0x60); + + if (dss_phys_base == (vir_bytes) MAP_FAILED) { + panic("Unable to request access to DSS(2) memory"); + } + + /* Configure DISPC memory access */ + mr.mr_base = OMAP3_DISPC_BASE; + mr.mr_limit = mr.mr_base + 0x430; + if (sys_privctl(SELF, SYS_PRIV_ADD_MEM, &mr) != OK) { + panic("Unable to request access to DISPC(1) memory"); + } + dispc_phys_base = (vir_bytes) vm_map_phys(SELF, + (void *) OMAP3_DISPC_BASE, + 0x430); + + if (dispc_phys_base == (vir_bytes) MAP_FAILED) { + panic("Unable to request access to DISPC(2) memory"); + } + + /* Set timings, screen mode, screen size, etc. */ + writew(OMAP3_DISPC_TIMINGH(dispc_phys_base), panel_cfg->timing_h); + writew(OMAP3_DISPC_TIMINGV(dispc_phys_base), panel_cfg->timing_v); + writew(OMAP3_DISPC_POL_FREQ(dispc_phys_base), panel_cfg->pol_freq); + writew(OMAP3_DISPC_DIVISOR(dispc_phys_base), panel_cfg->divisor); + writew(OMAP3_DISPC_CONFIG(dispc_phys_base), + panel_cfg->load_mode << LOADMODE_SHIFT); + writew(OMAP3_DISPC_CONTROL(dispc_phys_base), + panel_cfg->panel_type << TFTSTN_SHIFT | + panel_cfg->data_lines << DATALINES_SHIFT); + + writew((vir_bytes) OMAP3_DISPC_SIZE_LCD(dispc_phys_base), + panel_cfg->lcd_size); + writew((vir_bytes) OMAP3_DISPC_GFX_SIZE(dispc_phys_base), + panel_cfg->lcd_size); + writew(OMAP3_DISPC_DEFAULT_COLOR0(dispc_phys_base), + panel_cfg->panel_color); + + /* Enable gfx engine */ + writew(OMAP3_DISPC_GFX_ATTRIBUTES(dispc_phys_base), + (DISPC_GFXBURSTSIZE_16 << GFXBURSTSIZE_SHIFT) | + (DISPC_GFXFORMAT_RGB24 << GFXFORMAT_SHIFT) | + (DISPC_GFXENABLE)); + writew(OMAP3_DISPC_GFX_ROW_INC(dispc_phys_base), 1); + writew(OMAP3_DISPC_GFX_PIXEL_INC(dispc_phys_base), 1); + + /* Allocate contiguous physical memory for the display buffer */ + fb_size = omap_fbvs[minor].yres_virtual * omap_fbvs[minor].xres_virtual * + (omap_fbvs[minor].bits_per_pixel / 8); + fb_vir = (vir_bytes) alloc_contig(fb_size, 0, &fb_phys); + if (fb_vir == (vir_bytes) MAP_FAILED) { + panic("Unable to allocate contiguous memory\n"); + } + + /* Configure buffer settings and turn on LCD/Digital */ + arch_configure_display(minor); + + return OK; +} + diff --git a/minix/include/arch/earmv6hf/Makefile b/minix/include/arch/earmv6hf/Makefile new file mode 100644 index 000000000..3d01d044e --- /dev/null +++ b/minix/include/arch/earmv6hf/Makefile @@ -0,0 +1,4 @@ + +SUBDIR= include + +.include diff --git a/minix/include/arch/earmv6hf/include/Makefile b/minix/include/arch/earmv6hf/include/Makefile new file mode 100644 index 000000000..eaf08d24e --- /dev/null +++ b/minix/include/arch/earmv6hf/include/Makefile @@ -0,0 +1,8 @@ + +INCSDIR= /usr/include/arm + +INCS= archconst.h archtypes.h diskparm.h elf.h interrupt.h \ + ipcconst.h memory.h multiboot.h partition.h \ + stackframe.h vm.h + +.include diff --git a/minix/include/arch/earmv6hf/include/archconst.h b/minix/include/arch/earmv6hf/include/archconst.h new file mode 100644 index 000000000..484436f68 --- /dev/null +++ b/minix/include/arch/earmv6hf/include/archconst.h @@ -0,0 +1,6 @@ +#ifndef _ARM_CONST_H +#define _ARM_CONST_H + +#define DEFAULT_HZ 1000 + +#endif /* #ifndef _ARM_CONST_H */ diff --git a/minix/include/arch/earmv6hf/include/archtypes.h b/minix/include/arch/earmv6hf/include/archtypes.h new file mode 100644 index 000000000..a5e32c432 --- /dev/null +++ b/minix/include/arch/earmv6hf/include/archtypes.h @@ -0,0 +1,27 @@ + +#ifndef _ARM_TYPES_H +#define _ARM_TYPES_H + +#include +#include +#include + +typedef struct segframe { + reg_t p_ttbr; /* page table root */ + u32_t *p_ttbr_v; + char *fpu_state; +} segframe_t; + +struct cpu_info { + u32_t arch; + u32_t implementer; + u32_t part; + u32_t variant; + u32_t freq; /* in MHz */ + u32_t revision; +}; + +typedef u32_t atomic_t; /* access to an aligned 32bit value is atomic on ARM */ + +#endif /* #ifndef _ARM_TYPES_H */ + diff --git a/minix/include/arch/earmv6hf/include/diskparm.h b/minix/include/arch/earmv6hf/include/diskparm.h new file mode 100644 index 000000000..fdf514916 --- /dev/null +++ b/minix/include/arch/earmv6hf/include/diskparm.h @@ -0,0 +1,20 @@ +/* PC (and AT) BIOS structure to hold disk parameters. Under Minix, it is + * used mainly for formatting. + */ + +#ifndef _DISKPARM_H +#define _DISKPARM_H +struct disk_parameter_s { + char spec1; + char spec2; + char motor_turnoff_sec; + char sector_size_code; + char sectors_per_cylinder; + char gap_length; + char dtl; + char gap_length_for_format; + char fill_byte_for_format; + char head_settle_msec; + char motor_start_eigth_sec; +}; +#endif /* _DISKPARM_H */ diff --git a/minix/include/arch/earmv6hf/include/elf.h b/minix/include/arch/earmv6hf/include/elf.h new file mode 100644 index 000000000..a77092bb0 --- /dev/null +++ b/minix/include/arch/earmv6hf/include/elf.h @@ -0,0 +1,42 @@ +/*- + * Copyright (c) 1996-1997 John D. Polstra. + * 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 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 AUTHOR 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. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_ELF_H_ +#define _MACHINE_ELF_H_ 1 + +/* + * ELF definitions for the ARM architecture. + */ + +/* Define "machine" characteristics */ +#define ELF_TARG_CLASS ELFCLASS32 +#define ELF_TARG_DATA ELFDATA2LSB +#define ELF_TARG_MACH EM_ARM +#define ELF_TARG_VER 1 + +#endif /* !_MACHINE_ELF_H_ */ diff --git a/minix/include/arch/earmv6hf/include/interrupt.h b/minix/include/arch/earmv6hf/include/interrupt.h new file mode 100644 index 000000000..0cc92491e --- /dev/null +++ b/minix/include/arch/earmv6hf/include/interrupt.h @@ -0,0 +1,8 @@ +/* Interrupt numbers and hardware vectors. */ + +#ifndef _INTERRUPT_H +#define _INTERRUPT_H + +#define NR_IRQ_VECTORS 125 + +#endif /* _INTERRUPT_H */ diff --git a/minix/include/arch/earmv6hf/include/ipcconst.h b/minix/include/arch/earmv6hf/include/ipcconst.h new file mode 100644 index 000000000..d181f5d4a --- /dev/null +++ b/minix/include/arch/earmv6hf/include/ipcconst.h @@ -0,0 +1,9 @@ +#ifndef _ARM_IPCCONST_H_ +#define _ARM_IPCCONST_H_ + +#define KERVEC_INTR 32 /* syscall trap to kernel */ +#define IPCVEC_INTR 33 /* ipc trap to kernel */ + +#define IPC_STATUS_REG r1 + +#endif /* _ARM_IPCCONST_H_ */ diff --git a/minix/include/arch/earmv6hf/include/memory.h b/minix/include/arch/earmv6hf/include/memory.h new file mode 100644 index 000000000..977d622bb --- /dev/null +++ b/minix/include/arch/earmv6hf/include/memory.h @@ -0,0 +1,10 @@ +/* Physical memory layout */ + +#ifndef _ARM_MEMORY_H +#define _ARM_MEMORY_H + +/* omap */ +#define PHYS_MEM_BEGIN 0x80000000 +#define PHYS_MEM_END 0xbfffffff + +#endif /* _ARM_MEMORY_H */ diff --git a/minix/include/arch/earmv6hf/include/multiboot.h b/minix/include/arch/earmv6hf/include/multiboot.h new file mode 100644 index 000000000..753d49365 --- /dev/null +++ b/minix/include/arch/earmv6hf/include/multiboot.h @@ -0,0 +1,351 @@ +/* $NetBSD: multiboot.h,v 1.8 2009/02/22 18:05:42 ahoka Exp $ */ + +/*- + * Copyright (c) 2005, 2006 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Julio M. Merino Vidal. + * + * 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. + */ +#ifndef __MULTIBOOT_H__ +#define __MULTIBOOT_H__ + +#if !defined(_KERNEL) && defined(_STANDALONE) + +/* --------------------------------------------------------------------- */ + +/* + * Multiboot header structure. + */ +#define MULTIBOOT_HEADER_MAGIC 0x1BADB002 +#define MULTIBOOT_HEADER_MODS_ALIGNED 0x00000001 +#define MULTIBOOT_HEADER_WANT_MEMORY 0x00000002 +#define MULTIBOOT_HEADER_HAS_VBE 0x00000004 +#define MULTIBOOT_HEADER_HAS_ADDR 0x00010000 + +#if !defined(_LOCORE) +struct multiboot_header { + uint32_t mh_magic; + uint32_t mh_flags; + uint32_t mh_checksum; + + /* Valid if mh_flags sets MULTIBOOT_HEADER_HAS_ADDR. */ + paddr_t mh_header_addr; + paddr_t mh_load_addr; + paddr_t mh_load_end_addr; + paddr_t mh_bss_end_addr; + paddr_t mh_entry_addr; + + /* Valid if mh_flags sets MULTIBOOT_HEADER_HAS_VBE. */ + uint32_t mh_mode_type; + uint32_t mh_width; + uint32_t mh_height; + uint32_t mh_depth; +}; +#endif /* !defined(_LOCORE) */ + +/* + * Symbols defined in locore.S. + */ +#if !defined(_LOCORE) && defined(_KERNEL) +extern struct multiboot_header *Multiboot_Header; +#endif /* !defined(_LOCORE) && defined(_KERNEL) */ + +/* --------------------------------------------------------------------- */ + +/* + * Multiboot information structure. + */ +#define MULTIBOOT_INFO_MAGIC 0x2BADB002 +#define MULTIBOOT_INFO_HAS_MEMORY 0x00000001 +#define MULTIBOOT_INFO_HAS_BOOT_DEVICE 0x00000002 +#define MULTIBOOT_INFO_HAS_CMDLINE 0x00000004 +#define MULTIBOOT_INFO_HAS_MODS 0x00000008 +#define MULTIBOOT_INFO_HAS_AOUT_SYMS 0x00000010 +#define MULTIBOOT_INFO_HAS_ELF_SYMS 0x00000020 +#define MULTIBOOT_INFO_HAS_MMAP 0x00000040 +#define MULTIBOOT_INFO_HAS_DRIVES 0x00000080 +#define MULTIBOOT_INFO_HAS_CONFIG_TABLE 0x00000100 +#define MULTIBOOT_INFO_HAS_LOADER_NAME 0x00000200 +#define MULTIBOOT_INFO_HAS_APM_TABLE 0x00000400 +#define MULTIBOOT_INFO_HAS_VBE 0x00000800 + +#if !defined(_LOCORE) +struct multiboot_info { + uint32_t mi_flags; + + /* Valid if mi_flags sets MULTIBOOT_INFO_HAS_MEMORY. */ + uint32_t mi_mem_lower; + uint32_t mi_mem_upper; + + /* Valid if mi_flags sets MULTIBOOT_INFO_HAS_BOOT_DEVICE. */ + uint8_t mi_boot_device_part3; + uint8_t mi_boot_device_part2; + uint8_t mi_boot_device_part1; + uint8_t mi_boot_device_drive; + + /* Valid if mi_flags sets MULTIBOOT_INFO_HAS_CMDLINE. */ + char * mi_cmdline; + + /* Valid if mi_flags sets MULTIBOOT_INFO_HAS_MODS. */ + uint32_t mi_mods_count; + vaddr_t mi_mods_addr; + + /* Valid if mi_flags sets MULTIBOOT_INFO_HAS_{AOUT,ELF}_SYMS. */ + uint32_t mi_elfshdr_num; + uint32_t mi_elfshdr_size; + vaddr_t mi_elfshdr_addr; + uint32_t mi_elfshdr_shndx; + + /* Valid if mi_flags sets MULTIBOOT_INFO_HAS_MMAP. */ + uint32_t mi_mmap_length; + vaddr_t mi_mmap_addr; + + /* Valid if mi_flags sets MULTIBOOT_INFO_HAS_DRIVES. */ + uint32_t mi_drives_length; + vaddr_t mi_drives_addr; + + /* Valid if mi_flags sets MULTIBOOT_INFO_HAS_CONFIG_TABLE. */ + void * unused_mi_config_table; + + /* Valid if mi_flags sets MULTIBOOT_INFO_HAS_LOADER_NAME. */ + char * mi_loader_name; + + /* Valid if mi_flags sets MULTIBOOT_INFO_HAS_APM. */ + void * unused_mi_apm_table; + + /* Valid if mi_flags sets MULTIBOOT_INFO_HAS_VBE. */ + void * unused_mi_vbe_control_info; + void * unused_mi_vbe_mode_info; + paddr_t unused_mi_vbe_interface_seg; + paddr_t unused_mi_vbe_interface_off; + uint32_t unused_mi_vbe_interface_len; +}; + +/* --------------------------------------------------------------------- */ + +/* + * Drive information. This describes an entry in the drives table as + * pointed to by mi_drives_addr. + */ +struct multiboot_drive { + uint32_t md_length; + uint8_t md_number; + uint8_t md_mode; + uint16_t md_cylinders; + uint8_t md_heads; + uint8_t md_sectors; + + /* The variable-sized 'ports' field comes here, so this structure + * can be longer. */ +}; + +/* --------------------------------------------------------------------- */ + +/* + * Memory mapping. This describes an entry in the memory mappings table + * as pointed to by mi_mmap_addr. + * + * Be aware that mm_size specifies the size of all other fields *except* + * for mm_size. In order to jump between two different entries, you + * have to count mm_size + 4 bytes. + */ +struct multiboot_mmap { + uint32_t mm_size; + uint64_t mm_base_addr; + uint64_t mm_length; + uint32_t mm_type; +}; + +/* + * Modules. This describes an entry in the modules table as pointed + * to by mi_mods_addr. + */ + +struct multiboot_module { + uint32_t mmo_start; + uint32_t mmo_end; + char * mmo_string; + uint32_t mmo_reserved; +}; + +#endif /* !defined(_LOCORE) */ + +/* --------------------------------------------------------------------- */ + +/* + * Prototypes for public functions defined in multiboot.c. + */ +#if !defined(_LOCORE) && defined(_KERNEL) +void multiboot_pre_reloc(struct multiboot_info *); +void multiboot_post_reloc(void); +void multiboot_print_info(void); +bool multiboot_ksyms_addsyms_elf(void); +#endif /* !defined(_LOCORE) */ + +/* --------------------------------------------------------------------- */ +#else /* !defined(_KERNEL) && defined(_STANDALONE) */ +/* LSC FIXME: OLD MINIX DEFINITION: should be removed and replace with + definition above... */ +#define MULTIBOOT_HEADER_MAGIC 0x1BADB002 + +#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002 + +/* Must pass memory information to OS. */ +#define MULTIBOOT_PAGE_ALIGN 0x00000001 + +#define MULTIBOOT_MEMORY_INFO 0x00000002 + +#define MULTIBOOT_VIDEO_MODE 0x00000004 + +#define MULTIBOOT_AOUT_KLUDGE 0x00010000 + +/* consts used for Multiboot pre-init */ + +#define MULTIBOOT_VIDEO_MODE_EGA 1 + +#define MULTIBOOT_VIDEO_BUFFER 0xB8000 + +/* Usable lower memory chunk has a upper bound */ +#define MULTIBOOT_LOWER_MEM_MAX 0x7f800 + +#define MULTIBOOT_CONSOLE_LINES 25 +#define MULTIBOOT_CONSOLE_COLS 80 + +#define MULTIBOOT_VIDEO_BUFFER_BYTES \ + (MULTIBOOT_CONSOLE_LINES*MULTIBOOT_CONSOLE_COLS*2) + +#define MULTIBOOT_STACK_SIZE 4096 +#define MULTIBOOT_PARAM_BUF_SIZE 1024 + +#define MULTIBOOT_MAX_MODS 20 + +/* Flags to be set in the ’flags’ member of the multiboot info structure. */ + +#define MULTIBOOT_INFO_MEMORY 0x00000001 +#define MULTIBOOT_INFO_MEM_MAP 0x00000040 + +/* Is there a boot device set? */ +#define MULTIBOOT_INFO_BOOTDEV 0x00000002 + +/* Is the command-line defined? */ +#define MULTIBOOT_INFO_CMDLINE 0x00000004 + +/* Are there modules to do something with? */ +#define MULTIBOOT_INFO_MODS 0x00000008 + +#define MULTIBOOT_HIGH_MEM_BASE 0x100000 + +#ifndef __ASSEMBLY__ + +#include +/* The symbol table for a.out. */ +struct multiboot_aout_symbol_table +{ + u32_t tabsize; + u32_t strsize; + u32_t addr; + u32_t reserved; +}; +/* The section header table for ELF. */ +struct multiboot_elf_section_header_table +{ + u32_t num; + u32_t size; + u32_t addr; + u32_t shndx; +}; + +typedef struct multiboot_elf_section_header_table multiboot_elf_section_header_table_t; +typedef struct multiboot_aout_symbol_table multiboot_aout_symbol_table_t; + +struct multiboot_info +{ + /* Multiboot info version number */ + u32_t flags; + /* Available memory from BIOS */ + u32_t mem_lower_unused; /* minix uses memmap instead */ + u32_t mem_upper_unused; + /* "root" partition */ + u32_t boot_device; + /* Kernel command line */ + u32_t cmdline; + /* Boot-Module list */ + u32_t mi_mods_count; + u32_t mods_addr; + union + { + multiboot_aout_symbol_table_t aout_sym; + multiboot_elf_section_header_table_t elf_sec; + } u; + /* Memory Mapping buffer */ + u32_t mmap_length; + u32_t mmap_addr; + /* Drive Info buffer */ + u32_t drives_length; + u32_t drives_addr; + /* ROM configuration table */ + u32_t config_table; + /* Boot Loader Name */ + u32_t boot_loader_name; + /* APM table */ + u32_t apm_table; + /* Video */ + u32_t vbe_control_info; + u32_t vbe_mode_info; + u16_t vbe_mode; + u16_t vbe_interface_seg; + u16_t vbe_interface_off; + u16_t vbe_interface_len; +}; +typedef struct multiboot_info multiboot_info_t; + +struct multiboot_mod_list +{ + /* Memory used goes from bytes 'mod_start' to 'mod_end-1' inclusive */ + u32_t mod_start; + u32_t mod_end; + /* Module command line */ + u32_t cmdline; + /* Pad struct to 16 bytes (must be zero) */ + u32_t pad; +}; +typedef struct multiboot_mod_list multiboot_module_t; + +#define MULTIBOOT_MEMORY_AVAILABLE 1 +#define MULTIBOOT_MEMORY_RESERVED 2 +struct multiboot_mmap_entry +{ + u32_t size; + u64_t mm_base_addr; + u64_t mm_length; +#define MULTIBOOT_MEMORY_AVAILABLE 1 +#define MULTIBOOT_MEMORY_RESERVED 2 + u32_t type; +} __attribute__((packed)); +typedef struct multiboot_mmap_entry multiboot_memory_map_t; + +#endif /* __ASSEMBLY__ */ +#endif /* !defined(_KERNEL) && defined(_STANDALONE) */ +#endif /* __MULTIBOOT_H__ */ diff --git a/minix/include/arch/earmv6hf/include/partition.h b/minix/include/arch/earmv6hf/include/partition.h new file mode 100644 index 000000000..0af0abf4e --- /dev/null +++ b/minix/include/arch/earmv6hf/include/partition.h @@ -0,0 +1,28 @@ +/* Description of entry in partition table. */ +#ifndef _PARTITION_H +#define _PARTITION_H + +#include + +struct part_entry { + uint8_t bootind; /* boot indicator 0/ACTIVE_FLAG */ + uint8_t start_head; /* head value for first sector */ + uint8_t start_sec; /* sector value + cyl bits for first sector */ + uint8_t start_cyl; /* track value for first sector */ + uint8_t sysind; /* system indicator */ + uint8_t last_head; /* head value for last sector */ + uint8_t last_sec; /* sector value + cyl bits for last sector */ + uint8_t last_cyl; /* track value for last sector */ + uint32_t lowsec; /* logical first sector */ + uint32_t size; /* size of partition in sectors */ +}; + +#define ACTIVE_FLAG 0x80 /* value for active in bootind field (hd0) */ +#define NR_PARTITIONS 4 /* number of entries in partition table */ +#define PART_TABLE_OFF 0x1BE /* offset of partition table in boot sector */ + +/* Partition types. */ +#define NO_PART 0x00 /* unused entry */ +#define MINIX_PART 0x81 /* Minix partition type */ + +#endif /* _PARTITION_H */ diff --git a/minix/include/arch/earmv6hf/include/stackframe.h b/minix/include/arch/earmv6hf/include/stackframe.h new file mode 100644 index 000000000..aec3da201 --- /dev/null +++ b/minix/include/arch/earmv6hf/include/stackframe.h @@ -0,0 +1,28 @@ +#ifndef _ARM_STACKFRAME_H +#define _ARM_STACKFRAME_H + +#include + +typedef u32_t reg_t; /* machine register */ + +struct stackframe_s { + reg_t retreg; /* r0 */ + reg_t r1; + reg_t r2; + reg_t r3; + reg_t r4; + reg_t r5; + reg_t r6; + reg_t r7; + reg_t r8; + reg_t r9; /* sb */ + reg_t r10; /* sl */ + reg_t fp; /* r11 */ + reg_t r12; /* ip */ + reg_t sp; /* r13 */ + reg_t lr; /* r14 */ + reg_t pc; /* r15 */ + reg_t psr; +}; + +#endif /* _ARM_STACKFRAME_H */ diff --git a/minix/include/arch/earmv6hf/include/vm.h b/minix/include/arch/earmv6hf/include/vm.h new file mode 100644 index 000000000..0d7cec642 --- /dev/null +++ b/minix/include/arch/earmv6hf/include/vm.h @@ -0,0 +1,196 @@ +#ifndef __SYS_VM_ARM_H__ +#define __SYS_VM_ARM_H__ +/* +arm/vm.h +*/ + + +/* + * We are using the following setup + * the system is configured to have the TRE (Tex remap enable bit) set to 0 + * The TEX[2:0] B and C bits are used to determins memory attributes. + * These bits together with the S Bit (Shareability Bit) determines the + * memory attributes. + * + * The S bit is ignored when the other attribute define the memory as + * "device" or "strongly ordered" + * + * We are setting the tex[2] bit to one to end up with the following + * encoding + * + * 00 00 Non cacheable + * 01 01 Write back, Write allocate + * 10 10 Write trough, No write allocate + * 11 11 Write back , Write alloc + */ +#define ARM_PAGE_SIZE 4096 /* small page on ARM */ +#define ARM_SECTION_SIZE (1024 * 1024) /* 1 MB section */ + +/* Second level page table entries */ +#define ARM_VM_PAGETABLE (1 << 1) /* Page table */ +#define ARM_VM_PTE_PRESENT (1 << 1) /* Page is present */ +#define ARM_VM_PTE_B (1 << 2) /* B bit */ +#define ARM_VM_PTE_C (1 << 3) /* C bit */ +#define ARM_VM_PTE_SUPER (0x1 << 4) /* Super access only AP[1:0] */ +#define ARM_VM_PTE_USER (0x3 << 4) /* Super/User access AP[1:0] */ +#define ARM_VM_PTE_TEX0 (1 << 6) /* TEX[0] */ +#define ARM_VM_PTE_TEX1 (1 << 7) /* TEX[1] */ +#define ARM_VM_PTE_TEX2 (1 << 8) /* TEX[2] */ +#define ARM_VM_PTE_RO (1 << 9) /* Read only access AP[2] */ +#define ARM_VM_PTE_RW (0 << 9) /* Read-write access AP[2] */ + +#define ARM_VM_PTE_S (1 << 10) /* "Shareable" */ + + +#define ARM_VM_PTE_NOTGLOBAL (1 << 11) /* Not Global */ + +/* inner and outer write-back, write-allocate */ +#define ARM_VM_PTE_WB (ARM_VM_PTE_TEX2 | ARM_VM_PTE_TEX0 | ARM_VM_PTE_B) +/* inner and outer write-through, no write-allocate */ +#define ARM_VM_PTE_WT (ARM_VM_PTE_TEX2 | ARM_VM_PTE_TEX1 | ARM_VM_PTE_C ) +/* Inner , Write through, No Write Allocate Outer - Write Back, Write Allocate */ +#define ARM_VM_PTE_WTWB (ARM_VM_PTE_TEX2 | ARM_VM_PTE_TEX0 | ARM_VM_PTE_C ) + +#define ARM_VM_PTE_CACHED ARM_VM_PTE_WTWB +/* shareable device */ +#define ARM_VM_PTE_DEVICE (ARM_VM_PTE_B) + +#define ARM_VM_ADDR_MASK 0xFFFFF000 /* physical address */ +#define ARM_VM_ADDR_MASK_1MB 0xFFF00000 /* physical address */ +#define ARM_VM_OFFSET_MASK_1MB 0x000FFFFF /* physical address */ + +/* Big page (1MB section) specific flags. */ +#define ARM_VM_SECTION (1 << 1) /* 1MB section */ +#define ARM_VM_SECTION_PRESENT (1 << 1) /* Section is present */ +#define ARM_VM_SECTION_B (1 << 2) /* B Bit */ +#define ARM_VM_SECTION_C (1 << 3) /* C Bit */ +#define ARM_VM_SECTION_DOMAIN (0xF << 5) /* Domain Number */ +#define ARM_VM_SECTION_SUPER (0x1 << 10) /* Super access only AP[1:0] */ +#define ARM_VM_SECTION_USER (0x3 << 10) /* Super/User access AP[1:0] */ +#define ARM_VM_SECTION_TEX0 (1 << 12) /* TEX[0] */ +#define ARM_VM_SECTION_TEX1 (1 << 13) /* TEX[1] */ +#define ARM_VM_SECTION_TEX2 (1 << 14) /* TEX[2] */ +#define ARM_VM_SECTION_RO (1 << 15) /* Read only access AP[2] */ +#define ARM_VM_SECTION_SHAREABLE (1 << 16) /* Shareable */ +#define ARM_VM_SECTION_NOTGLOBAL (1 << 17) /* Not Global */ + +/* inner and outer write-back, write-allocate */ +#define ARM_VM_SECTION_WB (ARM_VM_SECTION_TEX2 | ARM_VM_SECTION_TEX0 | ARM_VM_SECTION_B ) +/* inner and outer write-through, no write-allocate */ +#define ARM_VM_SECTION_WT (ARM_VM_SECTION_TEX2 | ARM_VM_SECTION_TEX1 | ARM_VM_SECTION_C ) +/* Inner , Write through, No Write Allocate Outer - Write Back, Write Allocate */ +#define ARM_VM_SECTION_WTWB (ARM_VM_SECTION_TEX2 | ARM_VM_SECTION_TEX0 | ARM_VM_SECTION_C ) +/* shareable device */ + +#define ARM_VM_SECTION_CACHED ARM_VM_SECTION_WTWB + +#define ARM_VM_SECTION_DEVICE (ARM_VM_SECTION_B) + +/* Page directory specific flags. */ +#define ARM_VM_PAGEDIR (1 << 0) /* Page directory */ +#define ARM_VM_PDE_PRESENT (1 << 0) /* Page directory is present */ +#define ARM_VM_PDE_DOMAIN (0xF << 5) /* Domain Number */ + +#define ARM_VM_PT_ENT_SIZE 4 /* Size of a page table entry */ +#define ARM_VM_DIR_ENT_SIZE 4 /* Size of a page dir entry */ +#define ARM_VM_DIR_ENTRIES 4096 /* Number of entries in a page dir */ +#define ARM_VM_DIR_ENT_SHIFT 20 /* Shift to get entry in page dir. */ +#define ARM_VM_PT_ENT_SHIFT 12 /* Shift to get entry in page table */ +#define ARM_VM_PT_ENT_MASK 0xFF /* Mask to get entry in page table */ +#define ARM_VM_PT_ENTRIES 256 /* Number of entries in a page table */ + + +#define ARM_VM_PTE(v) (((v) >> ARM_VM_PT_ENT_SHIFT) & ARM_VM_PT_ENT_MASK) +#define ARM_VM_PDE(v) ( (v) >> ARM_VM_DIR_ENT_SHIFT) +#define ARM_VM_PFA(e) ( (e) & ARM_VM_ADDR_MASK) + +/* Second level small pages entry(Page Table Entry) points to 4K */ +#define ARM_VM_PTE_SHIFT 12 +#define ARM_VM_PTE_MASK (~((1 << ARM_VM_PTE_SHIFT) - 1)) + +/* First level entry(Page Directory Entry) to a second level small page PTE */ +#define ARM_VM_PDE_SHIFT 10 +#define ARM_VM_PDE_MASK (~((1 << ARM_VM_PDE_SHIFT) - 1)) + +/* First level entry(Page Directory Entry) to a 1MB section */ +#define ARM_VM_SECTION_SHIFT 20 +#define ARM_VM_SECTION_MASK (~((1 << ARM_VM_SECTION_SHIFT) - 1)) + +#define ARM_VM_DIR_SIZE (ARM_VM_DIR_ENTRIES * ARM_VM_DIR_ENT_SIZE) +#define ARM_PAGEDIR_SIZE (ARM_VM_DIR_SIZE) +#define ARM_VM_PT_SIZE (ARM_VM_PT_ENTRIES * ARM_VM_PT_ENT_SIZE) +#define ARM_PAGETABLE_SIZE (ARM_VM_PT_SIZE) + +/* ARM pagefault status bits */ +#define ARM_VM_PFE_ALIGN 0x01 /* Pagefault caused by Alignment fault */ +#define ARM_VM_PFE_IMAINT 0x04 /* Caused by Instruction cache + maintenance fault */ +#define ARM_VM_PFE_TTWALK_L1ABORT 0x0c /* Caused by Synchronous external abort + * on translation table walk (Level 1) + */ +#define ARM_VM_PFE_TTWALK_L2ABORT 0x0e /* Caused by Synchronous external abort + * on translation table walk (Level 2) + */ +#define ARM_VM_PFE_TTWALK_L1PERR 0x1c /* Caused by Parity error + * on translation table walk (Level 1) + */ +#define ARM_VM_PFE_TTWALK_L2PERR 0x1e /* Caused by Parity error + * on translation table walk (Level 2) + */ +#define ARM_VM_PFE_L1TRANS 0x05 /* Caused by Translation fault (Level 1) + */ +#define ARM_VM_PFE_L2TRANS 0x07 /* Caused by Translation fault (Level 2) + */ +#define ARM_VM_PFE_L1ACCESS 0x03 /* Caused by Access flag fault (Level 1) + */ +#define ARM_VM_PFE_L2ACCESS 0x06 /* Caused by Access flag fault (Level 2) + */ +#define ARM_VM_PFE_L1DOMAIN 0x09 /* Caused by Domain fault (Level 1) + */ +#define ARM_VM_PFE_L2DOMAIN 0x0b /* Caused by Domain fault (Level 2) + */ +#define ARM_VM_PFE_L1PERM 0x0d /* Caused by Permission fault (Level 1) + */ +#define ARM_VM_PFE_L2PERM 0x0f /* Caused by Permission fault (Level 2) + */ +#define ARM_VM_PFE_DEBUG 0x02 /* Caused by Debug event */ +#define ARM_VM_PFE_ABORT 0x08 /* Caused by Synchronous external abort + */ +#define ARM_VM_PFE_TLB_CONFLICT 0x10 /* Caused by TLB conflict abort + */ + +#define ARM_VM_PFE_W (1<<11) /* Caused by write (otherwise read) */ +#define ARM_VM_PFE_FS4 (1<<10) /* Fault status (bit 4) */ +#define ARM_VM_PFE_FS3_0 0xf /* Fault status (bits 3:0) */ + + +/* Translation table base register specfic flags */ +#define ARM_TTBR_C (0x01) /* Cacheable bit. Indicates whether the translation table walk is to Inner Cacheable memory. */ + +/* RGN bits[4:3] indicates the Outer cacheability attributes + for the memory associated with the translation table walks */ +#define ARM_TTBR_OUTER_NC (0x0 << 3) /* Non-cacheable*/ +#define ARM_TTBR_OUTER_WBWA (0x1 << 3) /* Outer Write-Back Write-Allocate Cacheable. */ +#define ARM_TTBR_OUTER_WT (0x2 << 3) /* Outer Write-Through Cacheable. */ +#define ARM_TTBR_OUTER_WBNWA (0x3 << 3) /* Outer Write-Back no Write-Allocate Cacheable. */ + + +#define ARM_TTBR_ADDR_MASK (0xffffc000) /* only the 18 upper bits are to be used as address */ +#define ARM_TTBR_FLAGS_CACHED ARM_TTBR_OUTER_WBWA + +/* Fault status */ +#define ARM_VM_PFE_FS(s) \ + ((((s) & ARM_VM_PFE_FS4) >> 6) | ((s) & ARM_VM_PFE_FS3_0)) + +#ifndef __ASSEMBLY__ + +#include + +/* structure used by VM to pass data to the kernel while enabling paging */ +struct vm_ep_data { + struct mem_map * mem_map; + vir_bytes data_seg_limit; +}; +#endif + +#endif /* __SYS_VM_ARM_H__ */ diff --git a/minix/kernel/arch/earmv6hf/Makefile.inc b/minix/kernel/arch/earmv6hf/Makefile.inc new file mode 100644 index 000000000..eb56e80c5 --- /dev/null +++ b/minix/kernel/arch/earmv6hf/Makefile.inc @@ -0,0 +1,98 @@ +# Makefile for arch-dependent kernel code +.include + +HERE=${.CURDIR}/arch/${MACHINE_ARCH} +.PATH: ${HERE} + +# objects we want unpaged from -lc +MINLIB_OBJS_UNPAGED= get_bp.o +get_bp.o: ${NETBSDSRCDIR}/minix/lib/libc/arch/arm/get_bp.S + +# objects we want unpaged from -lsys +SYS_OBJS_UNPAGED=assert.o stacktrace.o +assert.o: ${NETBSDSRCDIR}/minix/lib/libsys/assert.c +stacktrace.o: ${NETBSDSRCDIR}/minix/lib/libsys/stacktrace.c + +# objects we want unpaged from -lminc +MINC_OBJS_UNPAGED= atoi.o \ + printf.o subr_prf.o \ + strcmp.o strcpy.o strlen.o strncmp.o \ + memcpy.o memmove.o memset.o \ + udivdi3.o umoddi3.o qdivrem.o +MINC_OBJS_UNPAGED+= __aeabi_ldiv0.o __aeabi_idiv0.o __aeabi_uldivmod.o divide.o divsi3.o udivsi3.o +atoi.o: ${NETBSDSRCDIR}/minix/lib/libminc/atoi.c +printf.o: ${NETBSDSRCDIR}/sys/lib/libsa/printf.c +subr_prf.o: ${NETBSDSRCDIR}/sys/lib/libsa/subr_prf.c +memcpy.o: ${NETBSDSRCDIR}/common/lib/libc/arch/arm/string/memcpy.S +memmove.o: ${NETBSDSRCDIR}/common/lib/libc/arch/arm/string/memmove.S +memset.o: ${NETBSDSRCDIR}/common/lib/libc/arch/arm/string/memset.S +strlen.o: ${NETBSDSRCDIR}/common/lib/libc/arch/arm/string/strlen.S +strcpy.o: ${NETBSDSRCDIR}/common/lib/libc/arch/arm/string/strcpy.S +strcmp.o: ${NETBSDSRCDIR}/common/lib/libc/arch/arm/string/strcmp.S + +#strcat.o: ${NETBSDSRCDIR}/common/lib/libc/string/strcat.c +__aeabi_idiv0.o: ${NETBSDSRCDIR}/common/lib/libc/arch/arm/gen/__aeabi_idiv0.c +__aeabi_ldiv0.o: ${NETBSDSRCDIR}/common/lib/libc/arch/arm/gen/__aeabi_ldiv0.c +__aeabi_uldivmod.o: ${NETBSDSRCDIR}/common/lib/libc/arch/arm/quad/__aeabi_uldivmod.S +divide.o: ${NETBSDSRCDIR}/common/lib/libc/arch/arm/gen/divide.S +divsi3.o: ${NETBSDSRCDIR}/common/lib/libc/arch/arm/gen/divsi3.S +udivsi3.o: ${NETBSDSRCDIR}/common/lib/libc/arch/arm/gen/udivsi3.S + +# the following is required by pre_init.c +strncmp.o: ${NETBSDSRCDIR}/common/lib/libc/string/strncmp.c + +# these are required by kprintn.o: +udivdi3.o: ${NETBSDSRCDIR}/common/lib/libc/quad/udivdi3.c +umoddi3.o: ${NETBSDSRCDIR}/common/lib/libc/quad/umoddi3.c +qdivrem.o: ${NETBSDSRCDIR}/common/lib/libc/quad/qdivrem.c + +CPPFLAGS.__aeabi_idiv0.c+= -D_STANDALONE +CPPFLAGS.__aeabi_ldiv0.c+= -D_STANDALONE + +# LSC: putchar and kputc have the same signature. A bit hackish. +CPPFLAGS.subr_prf.c+= -Dputchar=kputc + +# Activate optional support, may be deactivated. +CPPFLAGS.subr_prf.c+= -DLIBSA_PRINTF_LONGLONG_SUPPORT -DLIBSA_PRINTF_WIDTH_SUPPORT + +.include "bsp/ti/Makefile.inc" + +# some object files we give a symbol prefix (or namespace) of __k_unpaged_ +# that must live in their own unique namespace. +# +.for unpaged_obj in head.o pre_init.o direct_tty_utils.o \ + pg_utils.o klib.o utility.o arch_reset.o \ + ${MINLIB_OBJS_UNPAGED} ${MINC_OBJS_UNPAGED} ${SYS_OBJS_UNPAGED} ${BSP_OBJS_UNPAGED} +unpaged_${unpaged_obj}: ${unpaged_obj} + ${OBJCOPY} --prefix-symbols=__k_unpaged_ ${.OBJDIR}/${unpaged_obj} $@ +UNPAGED_OBJS += unpaged_${unpaged_obj} +ORIG_UNPAGED_OBJS += ${unpaged_obj} +.endfor + + +CLEANFILES+= ${ORIG_UNPAGED_OBJS} + +SRCS+= mpx.S arch_clock.c arch_do_vmctl.c arch_system.c do_padconf.c \ + exception.c hw_intr.c klib.S memory.c \ + protect.c direct_tty_utils.c arch_reset.c \ + pg_utils.c phys_copy.S phys_memset.S exc.S + +OBJS.kernel+= ${UNPAGED_OBJS} + +klib.o mpx.o head.o: procoffsets.h + +SRCS+= procoffsets.h + +PROCOFFSETSCF=procoffsets.cf + +.PATH: ${NETBSDSRCDIR}/minix/include/arch/${MACHINE_ARCH}/include + +procoffsets.h: ${PROCOFFSETSCF} kernel.h proc.h stackframe.h archtypes.h + ${_MKTARGET_CREATE} + ${TOOL_CAT} ${HERE}/${PROCOFFSETSCF} | \ + ${TOOL_GENASSYM} -- ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} >$@.tmp && \ + mv -f $@.tmp $@ + +sconst.h: procoffsets.h +apic_asm.o head.o klib.o mpx.o: sconst.h + diff --git a/minix/kernel/arch/earmv6hf/arch_clock.c b/minix/kernel/arch/earmv6hf/arch_clock.c new file mode 100644 index 000000000..8990890c4 --- /dev/null +++ b/minix/kernel/arch/earmv6hf/arch_clock.c @@ -0,0 +1,141 @@ +/* ARM-specific clock functions. */ + +#include "kernel/kernel.h" + +#include "kernel/clock.h" +#include "kernel/proc.h" +#include "kernel/interrupt.h" +#include +#include +#include "kernel/glo.h" +#include "kernel/profile.h" + +#include + + +#include "kernel/spinlock.h" + +#ifdef CONFIG_SMP +#include "kernel/smp.h" +#endif + +#include "bsp_timer.h" +#include "bsp_intr.h" + +static unsigned tsc_per_ms[CONFIG_MAX_CPUS]; + +int init_local_timer(unsigned freq) +{ + bsp_timer_init(freq); + + if (BOARD_IS_BBXM(machine.board_id)) { + tsc_per_ms[0] = 16250; + } else if (BOARD_IS_BB(machine.board_id)) { + tsc_per_ms[0] = 15000; + } else { + panic("Can not do the clock setup. machine (0x%08x) is unknown\n",machine.board_id); + }; + + return 0; +} + +void stop_local_timer(void) +{ + bsp_timer_stop(); +} + +void arch_timer_int_handler(void) +{ + bsp_timer_int_handler(); +} + +void cycles_accounting_init(void) +{ + read_tsc_64(get_cpu_var_ptr(cpu, tsc_ctr_switch)); + + get_cpu_var(cpu, cpu_last_tsc) = 0; + get_cpu_var(cpu, cpu_last_idle) = 0; +} + +void context_stop(struct proc * p) +{ + u64_t tsc; + u32_t tsc_delta; + u64_t * __tsc_ctr_switch = get_cpulocal_var_ptr(tsc_ctr_switch); + + read_tsc_64(&tsc); + assert(tsc >= *__tsc_ctr_switch); + tsc_delta = tsc - *__tsc_ctr_switch; + p->p_cycles += tsc_delta; + + if(kbill_ipc) { + kbill_ipc->p_kipc_cycles += tsc_delta; + kbill_ipc = NULL; + } + + if(kbill_kcall) { + kbill_kcall->p_kcall_cycles += tsc_delta; + kbill_kcall = NULL; + } + + /* + * deduct the just consumed cpu cycles from the cpu time left for this + * process during its current quantum. Skip IDLE and other pseudo kernel + * tasks + */ + if (p->p_endpoint >= 0) { +#if DEBUG_RACE + p->p_cpu_time_left = 0; +#else + if (tsc_delta < p->p_cpu_time_left) { + p->p_cpu_time_left -= tsc_delta; + } else p->p_cpu_time_left = 0; +#endif + } + + *__tsc_ctr_switch = tsc; +} + +void context_stop_idle(void) +{ + int is_idle; +#ifdef CONFIG_SMP + unsigned cpu = cpuid; +#endif + + is_idle = get_cpu_var(cpu, cpu_is_idle); + get_cpu_var(cpu, cpu_is_idle) = 0; + + context_stop(get_cpulocal_var_ptr(idle_proc)); + + if (is_idle) + restart_local_timer(); +#if SPROFILE + if (sprofiling) + get_cpulocal_var(idle_interrupted) = 1; +#endif +} + +void restart_local_timer(void) +{ +} + +int register_local_timer_handler(const irq_handler_t handler) +{ + return bsp_register_timer_handler(handler); +} + +u64_t ms_2_cpu_time(unsigned ms) +{ + return (u64_t)(tsc_per_ms[cpuid]) * ms; +} + +unsigned cpu_time_2_ms(u64_t cpu_time) +{ + return (unsigned long)(cpu_time / tsc_per_ms[cpuid]); +} + +short cpu_load(void) +{ + return 0; +} diff --git a/minix/kernel/arch/earmv6hf/arch_do_vmctl.c b/minix/kernel/arch/earmv6hf/arch_do_vmctl.c new file mode 100644 index 000000000..bb8d231e9 --- /dev/null +++ b/minix/kernel/arch/earmv6hf/arch_do_vmctl.c @@ -0,0 +1,56 @@ +/* The kernel call implemented in this file: + * m_type: SYS_VMCTL + * + * The parameters for this kernel call are: + * SVMCTL_WHO which process + * SVMCTL_PARAM set this setting (VMCTL_*) + * SVMCTL_VALUE to this value + */ + +#include "kernel/system.h" +#include +#include + +#include "arch_proto.h" + +static void set_ttbr(struct proc *p, u32_t ttbr, u32_t *v) +{ + /* Set process TTBR. */ + p->p_seg.p_ttbr = ttbr; + assert(p->p_seg.p_ttbr); + p->p_seg.p_ttbr_v = v; + if(p == get_cpulocal_var(ptproc)) { + write_ttbr0(p->p_seg.p_ttbr); + } + if(p->p_nr == VM_PROC_NR) { + if (arch_enable_paging(p) != OK) + panic("arch_enable_paging failed"); + } + RTS_UNSET(p, RTS_VMINHIBIT); +} + +/*===========================================================================* + * arch_do_vmctl * + *===========================================================================*/ +int arch_do_vmctl(m_ptr, p) +register message *m_ptr; /* pointer to request message */ +struct proc *p; +{ + switch(m_ptr->SVMCTL_PARAM) { + case VMCTL_GET_PDBR: + /* Get process page directory base reg (TTBR). */ + m_ptr->SVMCTL_VALUE = p->p_seg.p_ttbr; + return OK; + case VMCTL_SETADDRSPACE: + set_ttbr(p, m_ptr->SVMCTL_PTROOT, (u32_t *) m_ptr->SVMCTL_PTROOT_V); + return OK; + case VMCTL_FLUSHTLB: + { + reload_ttbr0(); + return OK; + } + } + + printf("arch_do_vmctl: strange param %d\n", m_ptr->SVMCTL_PARAM); + return EINVAL; +} diff --git a/minix/kernel/arch/earmv6hf/arch_reset.c b/minix/kernel/arch/earmv6hf/arch_reset.c new file mode 100644 index 000000000..7d5a872de --- /dev/null +++ b/minix/kernel/arch/earmv6hf/arch_reset.c @@ -0,0 +1,82 @@ +#include "kernel/kernel.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include "archconst.h" +#include "arch_proto.h" +#include "bsp_reset.h" +#include "bsp_serial.h" +#include "kernel/proc.h" +#include "kernel/debug.h" +#include "direct_utils.h" +#include + +void +halt_cpu(void) +{ + asm volatile("dsb"); + asm volatile("cpsie i"); + asm volatile("wfi"); + asm volatile("cpsid i"); +} + +void +reset(void) +{ + bsp_reset(); /* should not exit */ + direct_print("Reset not supported."); + while (1); +} + +void +poweroff(void) +{ + bsp_poweroff(); + /* fallback option: hang */ + direct_print("Unable to power-off this device."); + while (1); +} + +__dead void +arch_shutdown(int how) +{ + + if((how & RB_POWERDOWN) == RB_POWERDOWN) { + /* Power off if possible, hang otherwise */ + poweroff(); + NOT_REACHABLE; + } + + if(how & RB_HALT) { + /* Hang */ + for (; ; ) halt_cpu(); + NOT_REACHABLE; + } + + /* Reset the system */ + reset(); + NOT_REACHABLE; + + while (1); +} + +#ifdef DEBUG_SERIAL +void +ser_putc(char c) +{ + bsp_ser_putc(c); +} + +#endif diff --git a/minix/kernel/arch/earmv6hf/arch_system.c b/minix/kernel/arch/earmv6hf/arch_system.c new file mode 100644 index 000000000..9399c2e4c --- /dev/null +++ b/minix/kernel/arch/earmv6hf/arch_system.c @@ -0,0 +1,218 @@ +/* system dependent functions for use inside the whole kernel. */ + +#include "kernel/kernel.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "archconst.h" +#include "arch_proto.h" +#include "kernel/proc.h" +#include "kernel/debug.h" +#include "ccnt.h" +#include "bsp_init.h" +#include "bsp_serial.h" + +#include "glo.h" + +void * k_stacks; + + +void fpu_init(void) +{ +} + +void save_local_fpu(struct proc *pr, int retain) +{ +} + +void save_fpu(struct proc *pr) +{ +} + +void arch_proc_reset(struct proc *pr) +{ + assert(pr->p_nr < NR_PROCS); + + /* Clear process state. */ + memset(&pr->p_reg, 0, sizeof(pr->p_reg)); + if(iskerneln(pr->p_nr)) { + pr->p_reg.psr = INIT_TASK_PSR; + } else { + pr->p_reg.psr = INIT_PSR; + } +} + +void arch_proc_setcontext(struct proc *p, struct stackframe_s *state, + int isuser, int trapstyle) +{ + assert(sizeof(p->p_reg) == sizeof(*state)); + if(state != &p->p_reg) { + memcpy(&p->p_reg, state, sizeof(*state)); + } + + /* further code is instructed to not touch the context + * any more + */ + p->p_misc_flags |= MF_CONTEXT_SET; + + if(!(p->p_rts_flags)) { + printf("WARNINIG: setting full context of runnable process\n"); + print_proc(p); + util_stacktrace(); + } +} + +void arch_set_secondary_ipc_return(struct proc *p, u32_t val) +{ + p->p_reg.r1 = val; +} + +int restore_fpu(struct proc *pr) +{ + return 0; +} + +void cpu_identify(void) +{ + u32_t midr; + unsigned cpu = cpuid; + + asm volatile("mrc p15, 0, %[midr], c0, c0, 0 @ read MIDR\n\t" + : [midr] "=r" (midr)); + + cpu_info[cpu].implementer = midr >> 24; + cpu_info[cpu].variant = (midr >> 20) & 0xF; + cpu_info[cpu].arch = (midr >> 16) & 0xF; + cpu_info[cpu].part = (midr >> 4) & 0xFFF; + cpu_info[cpu].revision = midr & 0xF; + cpu_info[cpu].freq = 660; /* 660 Mhz hardcoded */ +} + +void arch_init(void) +{ + u32_t value; + + k_stacks = (void*) &k_stacks_start; + assert(!((vir_bytes) k_stacks % K_STACK_SIZE)); + +#ifndef CONFIG_SMP + /* + * use stack 0 and cpu id 0 on a single processor machine, SMP + * configuration does this in smp_init() for all cpus at once + */ + tss_init(0, get_k_stack_top(0)); +#endif + + + /* enable user space access to cycle counter */ + /* set cycle counter to 0: ARM ARM B4.1.113 and B4.1.117 */ + asm volatile ("MRC p15, 0, %0, c9, c12, 0\t\n": "=r" (value)); + value |= PMU_PMCR_C; /* Reset counter */ + value |= PMU_PMCR_E; /* Enable counter hardware */ + asm volatile ("MCR p15, 0, %0, c9, c12, 0\t\n": : "r" (value)); + + /* enable CCNT counting: ARM ARM B4.1.116 */ + value = PMU_PMCNTENSET_C; /* Enable PMCCNTR cycle counter */ + asm volatile ("MCR p15, 0, %0, c9, c12, 1\t\n": : "r" (value)); + + /* enable cycle counter in user mode: ARM ARM B4.1.124 */ + value = PMU_PMUSERENR_EN; + asm volatile ("MCR p15, 0, %0, c9, c14, 0\t\n": : "r" (value)); + bsp_init(); +} + +/*===========================================================================* + * do_ser_debug * + *===========================================================================*/ +void do_ser_debug() +{ +} + +void arch_do_syscall(struct proc *proc) +{ + /* do_ipc assumes that it's running because of the current process */ + assert(proc == get_cpulocal_var(proc_ptr)); + /* Make the system call, for real this time. */ + proc->p_reg.retreg = + do_ipc(proc->p_reg.retreg, proc->p_reg.r1, proc->p_reg.r2); +} + +reg_t svc_stack; + +struct proc * arch_finish_switch_to_user(void) +{ + char * stk; + struct proc * p; + +#ifdef CONFIG_SMP + stk = (char *)tss[cpuid].sp0; +#else + stk = (char *)tss[0].sp0; +#endif + svc_stack = (reg_t)stk; + /* set pointer to the process to run on the stack */ + p = get_cpulocal_var(proc_ptr); + *((reg_t *)stk) = (reg_t) p; + + /* turn interrupts on */ + p->p_reg.psr &= ~(PSR_I|PSR_F); + + return p; +} + +void fpu_sigcontext(struct proc *pr, struct sigframe_sigcontext *fr, struct sigcontext *sc) +{ +} + +reg_t arch_get_sp(struct proc *p) { return p->p_reg.sp; } + +void get_randomness(struct k_randomness *rand, int source) +{ +} + +void arch_ser_init(void) +{ + bsp_ser_init(); +} + +/*===========================================================================*/ +/* __switch_address_space */ +/*===========================================================================*/ +/* + * sets the ttbr register to the supplied value if it is not already set to the + * same value in which case it would only result in an extra TLB flush which is + * not desirable + */ +void __switch_address_space(struct proc *p, struct proc **__ptproc) +{ + reg_t orig_ttbr, new_ttbr; + + new_ttbr = p->p_seg.p_ttbr; + if (new_ttbr == 0) + return; + + orig_ttbr = read_ttbr0(); + + /* + * test if ttbr is loaded with the current value to avoid unnecessary + * TLB flushes + */ + if (new_ttbr == orig_ttbr) + return; + + write_ttbr0(new_ttbr); + + *__ptproc = p; + + return; +} diff --git a/minix/kernel/arch/earmv6hf/bsp/include/bsp_init.h b/minix/kernel/arch/earmv6hf/bsp/include/bsp_init.h new file mode 100644 index 000000000..36361243e --- /dev/null +++ b/minix/kernel/arch/earmv6hf/bsp/include/bsp_init.h @@ -0,0 +1,7 @@ +#ifndef _BSP_INIT_H_ +#define _BSP_INIT_H_ + +/* BSP init */ +void bsp_init(); + +#endif /* __BSP_INIT_H__ */ diff --git a/minix/kernel/arch/earmv6hf/bsp/include/bsp_intr.h b/minix/kernel/arch/earmv6hf/bsp/include/bsp_intr.h new file mode 100644 index 000000000..018c4796d --- /dev/null +++ b/minix/kernel/arch/earmv6hf/bsp/include/bsp_intr.h @@ -0,0 +1,12 @@ +#ifndef _BSP_INTR_H_ +#define _BSP_INTR_H_ + +#ifndef __ASSEMBLY__ + +void bsp_irq_unmask(int irq); +void bsp_irq_mask(int irq); +void bsp_irq_handle(void); + +#endif /* __ASSEMBLY__ */ + +#endif /* _BSP_INTR_H_ */ diff --git a/minix/kernel/arch/earmv6hf/bsp/include/bsp_padconf.h b/minix/kernel/arch/earmv6hf/bsp/include/bsp_padconf.h new file mode 100644 index 000000000..5aa9c5341 --- /dev/null +++ b/minix/kernel/arch/earmv6hf/bsp/include/bsp_padconf.h @@ -0,0 +1,11 @@ +#ifndef _BSP_PADCONF_H_ +#define _BSP_PADCONF_H_ + +#ifndef __ASSEMBLY__ + +void bsp_padconf_init(void); +int bsp_padconf_set(u32_t padconf, u32_t mask, u32_t value); + +#endif /* __ASSEMBLY__ */ + +#endif /* _BSP_PADCONF_H_ */ diff --git a/minix/kernel/arch/earmv6hf/bsp/include/bsp_reset.h b/minix/kernel/arch/earmv6hf/bsp/include/bsp_reset.h new file mode 100644 index 000000000..7f91da13c --- /dev/null +++ b/minix/kernel/arch/earmv6hf/bsp/include/bsp_reset.h @@ -0,0 +1,9 @@ +#ifndef _BSP_RESET_H_ +#define _BSP_RESET_H_ + +void bsp_reset_init(void); +void bsp_reset(void); +void bsp_poweroff(void); +void bsp_disable_watchdog(void); + +#endif /* _BSP_RESET_H_ */ diff --git a/minix/kernel/arch/earmv6hf/bsp/include/bsp_serial.h b/minix/kernel/arch/earmv6hf/bsp/include/bsp_serial.h new file mode 100644 index 000000000..4cd0ee4e7 --- /dev/null +++ b/minix/kernel/arch/earmv6hf/bsp/include/bsp_serial.h @@ -0,0 +1,6 @@ +#ifndef _BSP_SERIAL_H_ +#define _BSP_SERIAL_H_ + +void bsp_ser_init(); +void bsp_ser_putc(char c); +#endif /* _BSP_SERIAL_H_ */ diff --git a/minix/kernel/arch/earmv6hf/bsp/include/bsp_timer.h b/minix/kernel/arch/earmv6hf/bsp/include/bsp_timer.h new file mode 100644 index 000000000..d4ad85f8d --- /dev/null +++ b/minix/kernel/arch/earmv6hf/bsp/include/bsp_timer.h @@ -0,0 +1,13 @@ +#ifndef _BSP_TIMER_H_ +#define _BSP_TIMER_H_ + +#ifndef __ASSEMBLY__ + +void bsp_timer_init(unsigned freq); +void bsp_timer_stop(void); +int bsp_register_timer_handler(const irq_handler_t handler); +void bsp_timer_int_handler(void); + +#endif /* __ASSEMBLY__ */ + +#endif /* _BSP_TIMER_H_ */ diff --git a/minix/kernel/arch/earmv6hf/bsp/ti/Makefile.inc b/minix/kernel/arch/earmv6hf/bsp/ti/Makefile.inc new file mode 100644 index 000000000..a75a54e2c --- /dev/null +++ b/minix/kernel/arch/earmv6hf/bsp/ti/Makefile.inc @@ -0,0 +1,13 @@ +# +# BSP for TI hardware +# + +.PATH: ${.CURDIR}/arch/${MACHINE_ARCH}/bsp/ti + +.for unpaged_obj in omap_serial.o omap_rtc.o omap_reset.o +BSP_OBJS_UNPAGED += ${unpaged_obj} +.endfor + +SRCS+= omap_init.c omap_serial.c omap_timer.c omap_padconf.c omap_intr.c omap_rtc.c \ + omap_reset.c + diff --git a/minix/kernel/arch/earmv6hf/bsp/ti/omap_init.c b/minix/kernel/arch/earmv6hf/bsp/ti/omap_init.c new file mode 100644 index 000000000..99a47b765 --- /dev/null +++ b/minix/kernel/arch/earmv6hf/bsp/ti/omap_init.c @@ -0,0 +1,21 @@ +#include +#include "bsp_init.h" +#include "bsp_padconf.h" +#include "omap_rtc.h" +#include "bsp_reset.h" + +void +bsp_init() +{ + /* map memory for padconf */ + bsp_padconf_init(); + + /* map memory for rtc */ + omap3_rtc_init(); + + /* map memory for reset control */ + bsp_reset_init(); + + /* disable watchdog */ + bsp_disable_watchdog(); +} diff --git a/minix/kernel/arch/earmv6hf/bsp/ti/omap_intr.c b/minix/kernel/arch/earmv6hf/bsp/ti/omap_intr.c new file mode 100644 index 000000000..59bd4c2b9 --- /dev/null +++ b/minix/kernel/arch/earmv6hf/bsp/ti/omap_intr.c @@ -0,0 +1,72 @@ +#include +#include +#include +#include +#include + +#include "kernel/kernel.h" +#include "kernel/proc.h" +#include "kernel/vm.h" +#include "kernel/proto.h" +#include "arch_proto.h" +#include "hw_intr.h" + +#include "omap_intr_registers.h" +static struct omap_intr +{ + vir_bytes base; + int size; +} omap_intr; + +static kern_phys_map intr_phys_map; + +int +intr_init(const int auto_eoi) +{ + if (BOARD_IS_BBXM(machine.board_id)) { + omap_intr.base = OMAP3_DM37XX_INTR_BASE; + } else if (BOARD_IS_BB(machine.board_id)) { + omap_intr.base = OMAP3_AM335X_INTR_BASE; + } else { + panic + ("Can not do the interrupt setup. machine (0x%08x) is unknown\n", + machine.board_id); + }; + omap_intr.size = 0x1000; /* 4K */ + + kern_phys_map_ptr(omap_intr.base, omap_intr.size, + VMMF_UNCACHED | VMMF_WRITE, + &intr_phys_map, (vir_bytes) & omap_intr.base); + return 0; +} + +void +bsp_irq_handle(void) +{ + /* Function called from assembly to handle interrupts */ + + /* get irq */ + int irq = + mmio_read(omap_intr.base + + OMAP3_INTCPS_SIR_IRQ) & OMAP3_INTR_ACTIVEIRQ_MASK; + /* handle irq */ + irq_handle(irq); + /* re-enable. this should not trigger interrupts due to current cpsr + * state */ + mmio_write(omap_intr.base + OMAP3_INTCPS_CONTROL, + OMAP3_INTR_NEWIRQAGR); +} + +void +bsp_irq_unmask(int irq) +{ + mmio_write(OMAP3_INTR_MIR_CLEAR(omap_intr.base, irq >> 5), + 1 << (irq & 0x1f)); +} + +void +bsp_irq_mask(const int irq) +{ + mmio_write(OMAP3_INTR_MIR_SET(omap_intr.base, irq >> 5), + 1 << (irq & 0x1f)); +} diff --git a/minix/kernel/arch/earmv6hf/bsp/ti/omap_intr_registers.h b/minix/kernel/arch/earmv6hf/bsp/ti/omap_intr_registers.h new file mode 100644 index 000000000..a2a13046e --- /dev/null +++ b/minix/kernel/arch/earmv6hf/bsp/ti/omap_intr_registers.h @@ -0,0 +1,236 @@ +#ifndef _OMAP_INTR_H +#define _OMAP_INTR_H + +/* Interrupt controller memory map */ +#define OMAP3_DM37XX_INTR_BASE 0x48200000 /* INTCPS physical address */ + + +/* Interrupt controller memory map */ +#define OMAP3_AM335X_INTR_BASE 0x48200000 /* INTCPS physical address */ + +/* Interrupt controller registers */ +#define OMAP3_INTCPS_REVISION 0x000 /* IP revision code */ +#define OMAP3_INTCPS_SYSCONFIG 0x010 /* Controls params */ +#define OMAP3_INTCPS_SYSSTATUS 0x014 /* Status */ +#define OMAP3_INTCPS_SIR_IRQ 0x040 /* Active IRQ number */ +#define OMAP3_INTCPS_SIR_FIQ 0x044 /* Active FIQ number */ +#define OMAP3_INTCPS_CONTROL 0x048 /* New int agreement bits */ +#define OMAP3_INTCPS_PROTECTION 0x04C /* Protection for other regs */ +#define OMAP3_INTCPS_IDLE 0x050 /* Clock auto-idle/gating */ +#define OMAP3_INTCPS_IRQ_PRIORITY 0x060 /* Active IRQ priority level */ +#define OMAP3_INTCPS_FIQ_PRIORITY 0x064 /* Active FIQ priority level */ +#define OMAP3_INTCPS_THRESHOLD 0x068 /* Priority threshold */ +#define OMAP3_INTCPS_ITR0 0x080 /* Raw pre-masking interrupt status */ +#define OMAP3_INTCPS_MIR0 0x084 /* Interrupt mask */ +#define OMAP3_INTCPS_MIR_CLEAR0 0x088 /* Clear interrupt mask bits */ +#define OMAP3_INTCPS_MIR_SET0 0x08C /* Set interrupt mask bits */ +#define OMAP3_INTCPS_ISR_SET0 0x090 /* Set software int bits */ +#define OMAP3_INTCPS_ISR_CLEAR0 0x094 /* Clear software int bits */ +#define OMAP3_INTCPS_PENDING_IRQ0 0x098 /* IRQ status post-masking */ +#define OMAP3_INTCPS_PENDING_FIQ0 0x09C /* FIQ status post-masking */ +#define OMAP3_INTCPS_ILR0 0x100 /* Priority for interrupts */ + + +#define OMAP3_INTR_ITR(base,n) \ + (base + OMAP3_INTCPS_ITR0 + 0x20 * (n)) +#define OMAP3_INTR_MIR(base,n) \ + (base + OMAP3_INTCPS_MIR0 + 0x20 * (n)) +#define OMAP3_INTR_MIR_CLEAR(base,n) \ + (base + OMAP3_INTCPS_MIR_CLEAR0 + 0x20 * (n)) +#define OMAP3_INTR_MIR_SET(base,n) \ + (base + OMAP3_INTCPS_MIR_SET0 + 0x20 * (n)) +#define OMAP3_INTR_ISR_SET(base,n) \ + (base + OMAP3_INTCPS_ISR_SET0 + 0x20 * (n)) +#define OMAP3_INTR_ISR_CLEAR(base,n) \ + (base + OMAP3_INTCPS_ISR_CLEAR0 + 0x20 * (n)) +#define OMAP3_INTR_PENDING_IRQ(base,n) \ + (base + OMAP3_INTCPS_PENDING_IRQ0 + 0x20 * (n)) +#define OMAP3_INTR_PENDING_FIQ(base,n) \ + (base + OMAP3_INTCPS_PENDING_FIQ0 + 0x20 * (n)) +#define OMAP3_INTR_ILR(base,m) \ + (base + OMAP3_INTCPS_ILR0 + 0x4 * (m)) + +#define OMAP3_INTR_ACTIVEIRQ_MASK 0x7f /* Active IRQ mask for SIR_IRQ */ +#define OMAP3_INTR_NEWIRQAGR 0x1 /* New IRQ Generation */ + + + + +#define OMAP3_DM337X_NR_IRQ_VECTORS 96 + +/* Interrupt mappings */ +#define OMAP3_MCBSP2_ST_IRQ 4 /* Sidestone McBSP2 overflow */ +#define OMAP3_MCBSP3_ST_IRQ 5 /* Sidestone McBSP3 overflow */ +#define OMAP3_SYS_NIRQ 7 /* External source (active low) */ +#define OMAP3_SMX_DBG_IRQ 9 /* L3 interconnect error for debug */ +#define OMAP3_SMX_APP_IRQ 10 /* L3 interconnect error for application */ +#define OMAP3_PRCM_IRQ 11 /* PRCM module */ +#define OMAP3_SDMA0_IRQ 12 /* System DMA request 0 */ +#define OMAP3_SDMA1_IRQ 13 /* System DMA request 1 */ +#define OMAP3_SDMA2_IRQ 14 /* System DMA request 2 */ +#define OMAP3_SDMA3_IRQ 15 /* System DMA request 3 */ +#define OMAP3_MCBSP1_IRQ 16 /* McBSP module 1 */ +#define OMAP3_MCBSP2_IRQ 17 /* McBSP module 2 */ +#define OMAP3_GPMC_IRQ 20 /* General-purpose memory controller */ +#define OMAP3_SGX_IRQ 21 /* 2D/3D graphics module */ +#define OMAP3_MCBSP3_IRQ 22 /* McBSP module 3 */ +#define OMAP3_MCBSP4_IRQ 23 /* McBSP module 4 */ +#define OMAP3_CAM0_IRQ 24 /* Camera interface request 0 */ +#define OMAP3_DSS_IRQ 25 /* Display subsystem module */ +#define OMAP3_MAIL_U0_IRQ 26 /* Mailbox user 0 request */ +#define OMAP3_MCBSP5_IRQ 27 /* McBSP module 5 */ +#define OMAP3_IVA2_MMU_IRQ 28 /* IVA2 MMU */ +#define OMAP3_GPIO1_IRQ 29 /* GPIO module 1 */ +#define OMAP3_GPIO2_IRQ 30 /* GPIO module 2 */ +#define OMAP3_GPIO3_IRQ 31 /* GPIO module 3 */ +#define OMAP3_GPIO4_IRQ 32 /* GPIO module 4 */ +#define OMAP3_GPIO5_IRQ 33 /* GPIO module 5 */ +#define OMAP3_GPIO6_IRQ 34 /* GPIO module 6 */ +#define OMAP3_WDT3_IRQ 36 /* Watchdog timer module 3 overflow */ +#define OMAP3_GPT1_IRQ 37 /* General-purpose timer module 1 */ +#define OMAP3_GPT2_IRQ 38 /* General-purpose timer module 2 */ +#define OMAP3_GPT3_IRQ 39 /* General-purpose timer module 3 */ +#define OMAP3_GPT4_IRQ 40 /* General-purpose timer module 4 */ +#define OMAP3_GPT5_IRQ 41 /* General-purpose timer module 5 */ +#define OMAP3_GPT6_IRQ 42 /* General-purpose timer module 6 */ +#define OMAP3_GPT7_IRQ 43 /* General-purpose timer module 7 */ +#define OMAP3_GPT8_IRQ 44 /* General-purpose timer module 8 */ +#define OMAP3_GPT9_IRQ 45 /* General-purpose timer module 9 */ +#define OMAP3_GPT10_IRQ 46 /* General-purpose timer module 10 */ +#define OMAP3_GPT11_IRQ 47 /* General-purpose timer module 11 */ +#define OMAP3_SPI4_IRQ 48 /* McSPI module 4 */ +#define OMAP3_MCBSP4_TX_IRQ 54 /* McBSP module 4 transmit */ +#define OMAP3_MCBSP4_RX_IRQ 55 /* McBSP module 4 receive */ +#define OMAP3_I2C1_IRQ 56 /* I2C module 1 */ +#define OMAP3_I2C2_IRQ 57 /* I2C module 2 */ +#define OMAP3_HDQ_IRQ 58 /* HDQ/1-Wire */ +#define OMAP3_MCBSP1_TX_IRQ 59 /* McBSP module 1 transmit */ +#define OMAP3_MCBSP1_RX_IRQ 60 /* McBSP module 1 receive */ +#define OMAP3_I2C3_IRQ 61 /* I2C module 3 */ +#define OMAP3_MCBSP2_TX_IRQ 62 /* McBSP module 2 transmit */ +#define OMAP3_MCBSP2_RX_IRQ 63 /* McBSP module 2 receive */ +#define OMAP3_SPI1_IRQ 65 /* McSPI module 1 */ +#define OMAP3_SPI2_IRQ 66 /* McSPI module 2 */ +#define OMAP3_UART1_IRQ 72 /* UART module 1 */ +#define OMAP3_UART2_IRQ 73 /* UART module 2 */ +#define OMAP3_PBIAS_IRQ 75 /* Merged interrupt for PBIASlite 1/2 */ +#define OMAP3_OHCI_IRQ 76 /* OHCI HSUSB MP Host Interrupt */ +#define OMAP3_EHCI_IRQ 77 /* EHCI HSUSB MP Host Interrupt */ +#define OMAP3_TLL_IRQ 78 /* HSUSB MP TLL Interrupt */ +#define OMAP3_MCBSP5_TX_IRQ 81 /* McBSP module 5 transmit */ +#define OMAP3_MCBSP5_RX_IRQ 82 /* McBSP module 5 receive */ +#define OMAP3_MMC1_IRQ 83 /* MMC/SD module 1 */ +#define OMAP3_MMC2_IRQ 86 /* MMC/SD module 2 */ +#define OMAP3_ICR_IRQ 87 /* MPU ICR */ +#define OMAP3_D2DFRINT_IRQ 88 /* 3G coproc (in stacked modem config) */ +#define OMAP3_MCBSP3_TX_IRQ 89 /* McBSP module 3 transmit */ +#define OMAP3_MCBSP3_RX_IRQ 90 /* McBSP module 3 receive */ +#define OMAP3_SPI3_IRQ 91 /* McSPI module 3 */ +#define OMAP3_HSUSB_MC_IRQ 92 /* High-speed USB OTG */ +#define OMAP3_HSUSB_DMA_IRQ 93 /* High-speed USB OTG DMA */ +#define OMAP3_MMC3_IRQ 94 /* MMC/SD module 3 */ + + +#define AM335X_INT_EMUINT 0 /* Emulation interrupt (EMUICINTR) */ +#define AM335X_INT_COMMTX 1 /* CortexA8 COMMTX */ +#define AM335X_INT_COMMRX 2 /* CortexA8 COMMRX */ +#define AM335X_INT_BENCH 3 /* CortexA8 NPMUIRQ */ +#define AM335X_INT_ELM_IRQ 4 /* Sinterrupt (Error location process completion) */ +#define AM335X_INT_NMI 7 /* nmi_int */ +#define AM335X_INT_L3DEBUG 9 /* l3_FlagMux_top_FlagOut1 */ +#define AM335X_INT_L3APPINT 10 /* l3_FlagMux_top_FlagOut0 */ +#define AM335X_INT_PRCMINT 11 /* irq_mpu */ +#define AM335X_INT_EDMACOMPINT 12 /* tpcc_int_pend_po0 */ +#define AM335X_INT_EDMAMPERR 13 /* tpcc_mpint_pend_po */ +#define AM335X_INT_EDMAERRINT 14 /* tpcc_errint_pend_po */ +#define AM335X_INT_ADC_TSC_GENINT 16 /* gen_intr_pend */ +#define AM335X_INT_USBSSINT 17 /* usbss_intr_pend */ +#define AM335X_INT_USB0 18 /* usb0_intr_pend */ +#define AM335X_INT_USB1 19 /* usb1_intr_pend */ +#define AM335X_INT_PRUSS1_EVTOUT0 20 /* pr1_host_intr0_intr_pend */ +#define AM335X_INT_PRUSS1_EVTOUT1 21 /* pr1_host_intr1_intr_pend */ +#define AM335X_INT_PRUSS1_EVTOUT2 22 /* pr1_host_intr2_intr_pend */ +#define AM335X_INT_PRUSS1_EVTOUT3 23 /* pr1_host_intr3_intr_pend */ +#define AM335X_INT_PRUSS1_EVTOUT4 24 /* pr1_host_intr4_intr_pend */ +#define AM335X_INT_PRUSS1_EVTOUT5 25 /* pr1_host_intr5_intr_pend */ +#define AM335X_INT_PRUSS1_EVTOUT6 26 /* pr1_host_intr6_intr_pend */ +#define AM335X_INT_PRUSS1_EVTOUT7 27 /* pr1_host_intr7_intr_pend */ +#define AM335X_INT_MMCSD1INT 28 /* MMCSD1 SINTERRUPTN */ +#define AM335X_INT_MMCSD2INT 29 /* MMCSD2 SINTERRUPT */ +#define AM335X_INT_I2C2INT 30 /* I2C2 POINTRPEND */ +#define AM335X_INT_eCAP0INT 31 /* ecap_intr_intr_pend */ +#define AM335X_INT_GPIOINT2A 32 /* GPIO 2 POINTRPEND1 */ +#define AM335X_INT_GPIOINT2B 33 /* GPIO 2 POINTRPEND2 */ +#define AM335X_INT_USBWAKEUP 34 /* USBSS slv0p_Swakeup */ +#define AM335X_INT_LCDCINT 36 /* LCDC lcd_irq */ +#define AM335X_INT_GFXINT 37 /* SGX530 THALIAIRQ */ +#define AM335X_INT_ePWM2INT 39 /* (PWM Subsystem) epwm_intr_intr_pend */ +#define AM335X_INT_3PGSWRXTHR0 40 /* (Ethernet) c0_rx_thresh_pend (RX_THRESH_PULSE) */ +#define AM335X_INT_3PGSWRXINT0 41 /* CPSW (Ethernet) c0_rx_pend */ +#define AM335X_INT_3PGSWTXINT0 42 /* CPSW (Ethernet) c0_tx_pend */ +#define AM335X_INT_3PGSWMISC0 43 /* CPSW (Ethernet) c0_misc_pend */ +#define AM335X_INT_UART3INT 44 /* UART3 niq */ +#define AM335X_INT_UART4INT 45 /* UART4 niq */ +#define AM335X_INT_UART5INT 46 /* UART5 niq */ +#define AM335X_INT_eCAP1INT 47 /* (PWM Subsystem) ecap_intr_intr_pend */ +#define AM335X_INT_DCAN0_INT0 52 /* DCAN0 dcan_intr0_intr_pend */ +#define AM335X_INT_DCAN0_INT1 53 /* DCAN0 dcan_intr1_intr_pend */ +#define AM335X_INT_DCAN0_PARITY 54 /* DCAN0 dcan_uerr_intr_pend */ +#define AM335X_INT_DCAN1_INT0 55 /* DCAN1 dcan_intr0_intr_pend */ +#define AM335X_INT_DCAN1_INT1 56 /* DCAN1 dcan_intr1_intr_pend */ +#define AM335X_INT_DCAN1_PARITY 57 /* DCAN1 dcan_uerr_intr_pend */ +#define AM335X_INT_ePWM0_TZINT 58 /* eHRPWM0 TZ interrupt (PWM epwm_tz_intr_pend Subsystem) */ +#define AM335X_INT_ePWM1_TZINT 59 /* eHRPWM1 TZ interrupt (PWM epwm_tz_intr_pend Subsystem) */ +#define AM335X_INT_ePWM2_TZINT 60 /* eHRPWM2 TZ interrupt (PWM epwm_tz_intr_pend Subsystem) */ +#define AM335X_INT_eCAP2INT 61 /* eCAP2 (PWM Subsystem) ecap_intr_intr_pend */ +#define AM335X_INT_GPIOINT3A 62 /* GPIO 3 POINTRPEND1 */ +#define AM335X_INT_GPIOINT3B 63 /* GPIO 3 POINTRPEND2 */ +#define AM335X_INT_MMCSD0INT 64 /* MMCSD0 SINTERRUPTN */ +#define AM335X_INT_SPI0INT 65 /* McSPI0 SINTERRUPTN */ +#define AM335X_INT_TINT0 66 /* Timer0 POINTR_PEND */ +#define AM335X_INT_TINT1_1MS 67 /* DMTIMER_1ms POINTR_PEND */ +#define AM335X_INT_TINT2 68 /* DMTIMER2 POINTR_PEND */ +#define AM335X_INT_TINT3 69 /* DMTIMER3 POINTR_PEND */ +#define AM335X_INT_I2C0INT 70 /* I2C0 POINTRPEND */ +#define AM335X_INT_I2C1INT 71 /* I2C1 POINTRPEND */ +#define AM335X_INT_UART0INT 72 /* UART0 niq */ +#define AM335X_INT_UART1INT 73 /* UART1 niq */ +#define AM335X_INT_UART2INT 74 /* UART2 niq */ +#define AM335X_INT_RTCINT 75 /* RTC timer_intr_pend */ +#define AM335X_INT_RTCALARMINT 76 /* RTC alarm_intr_pend */ +#define AM335X_INT_MBINT0 77 /* Mailbox0 (mail_u0_irq) initiator_sinterrupt_q_n */ +#define AM335X_INT_M3_TXEV 78 /* Wake M3 Subsystem TXEV */ +#define AM335X_INT_eQEP0INT 79 /* eQEP0 (PWM Subsystem) eqep_intr_intr_pend */ +#define AM335X_INT_MCATXINT0 80 /* McASP0 mcasp_x_intr_pend */ +#define AM335X_INT_MCARXINT0 81 /* McASP0 mcasp_r_intr_pend */ +#define AM335X_INT_MCATXINT1 82 /* McASP1 mcasp_x_intr_pend */ +#define AM335X_INT_MCARXINT1 83 /* McASP1 mcasp_r_intr_pend */ +#define AM335X_INT_ePWM0INT 86 /* (PWM Subsystem) epwm_intr_intr_pend */ +#define AM335X_INT_ePWM1INT 87 /* (PWM Subsystem) epwm_intr_intr_pend */ +#define AM335X_INT_eQEP1INT 88 /* (PWM Subsystem) eqep_intr_intr_pend */ +#define AM335X_INT_eQEP2INT 89 /* (PWM Subsystem) eqep_intr_intr_pend */ +#define AM335X_INT_DMA_INTR_PIN2 90 /* External DMA/Interrupt Pin2 pi_x_dma_event_intr2 (xdma_event_intr2) */ +#define AM335X_INT_WDT1INT 91 /* (Public Watchdog) WDTIMER1 PO_INT_PEND */ +#define AM335X_INT_TINT4 92 /* DMTIMER4 POINTR_PEN */ +#define AM335X_INT_TINT5 93 /* DMTIMER5 POINTR_PEN */ +#define AM335X_INT_TINT6 94 /* DMTIMER6 POINTR_PEND */ +#define AM335X_INT_TINT7 95 /* DMTIMER7 POINTR_PEND */ +#define AM335X_INT_GPIOINT0A 96 /* GPIO 0 POINTRPEND1 */ +#define AM335X_INT_GPIOINT0B 97 /* GPIO 0 POINTRPEND2 */ +#define AM335X_INT_GPIOINT1A 98 /* GPIO 1 POINTRPEND1 */ +#define AM335X_INT_GPIOINT1B 99 /* GPIO 1 POINTRPEND2 */ +#define AM335X_INT_GPMCINT 100 /* GPMC gpmc_sinterrupt */ +#define AM335X_INT_DDRERR0 101 /* EMIF sys_err_intr_pend */ +#define AM335X_INT_TCERRINT0 112 /* TPTC0 tptc_erint_pend_po */ +#define AM335X_INT_TCERRINT1 113 /* TPTC1 tptc_erint_pend_po */ +#define AM335X_INT_TCERRINT2 114 /* TPTC2 tptc_erint_pend_po */ +#define AM335X_INT_ADC_TSC_PENINT 115 /* ADC_TSC pen_intr_pend */ +#define AM335X_INT_SMRFLX_Sabertooth 120 /* Smart Reflex 0 intrpen */ +#define AM335X_INT_SMRFLX_Core 121 /* Smart Reflex 1 intrpend */ +#define AM335X_INT_DMA_INTR_PIN0 123 /* pi_x_dma_event_intr0 (xdma_event_intr0) */ +#define AM335X_INT_DMA_INTR_PIN1 124 /* pi_x_dma_event_intr1 (xdma_event_intr1) */ +#define AM335X_INT_SPI1INT 125 /* McSPI1 SINTERRUPTN */ + +#define OMAP3_AM335X_NR_IRQ_VECTORS 125 + +#endif /* _OMAP_INTR_H */ diff --git a/minix/kernel/arch/earmv6hf/bsp/ti/omap_padconf.c b/minix/kernel/arch/earmv6hf/bsp/ti/omap_padconf.c new file mode 100644 index 000000000..318769bea --- /dev/null +++ b/minix/kernel/arch/earmv6hf/bsp/ti/omap_padconf.c @@ -0,0 +1,83 @@ +/* Implements sys_padconf() for the AM335X and DM37XX. */ + +#include "kernel/kernel.h" +#include "arch_proto.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "bsp_padconf.h" + +struct omap_padconf +{ + vir_bytes base; + vir_bytes offset; + vir_bytes size; + unsigned int board_filter_value; + unsigned int board_filter_mask; +}; + +static struct omap_padconf omap_padconfs[] = { + { + .base = PADCONF_DM37XX_REGISTERS_BASE, + .offset = PADCONF_DM37XX_REGISTERS_OFFSET, + .size = PADCONF_DM37XX_REGISTERS_SIZE, + .board_filter_value = BOARD_FILTER_BBXM_VALUE, + .board_filter_mask = BOARD_FILTER_BBXM_MASK, + }, + { + .base = PADCONF_AM335X_REGISTERS_BASE, + .offset = PADCONF_AM335X_REGISTERS_OFFSET, + .size = PADCONF_AM335X_REGISTERS_SIZE, + .board_filter_value = BOARD_FILTER_BB_VALUE, + .board_filter_mask = BOARD_FILTER_BB_MASK, + }, +}; + +/* initialized in init */ +static struct omap_padconf *omap_padconf; + +static kern_phys_map padconf_phys_map; + +int +bsp_padconf_set(u32_t padconf, u32_t mask, u32_t value) +{ + /* check that the value will be inside the padconf memory range */ + if (padconf >= (omap_padconf->size - omap_padconf->offset)) { + return EINVAL; /* outside of valid range */ + } + + set32(padconf + omap_padconf->base + omap_padconf->offset, mask, + value); + + return OK; +} + +void +bsp_padconf_init(void) +{ + int x; + omap_padconf = NULL; + /* find the correct padconf */ + for (x = 0; x < sizeof(omap_padconfs) / sizeof(omap_padconfs[0]); x++) { + if ((omap_padconfs[x].board_filter_mask & machine.board_id) == + omap_padconfs[x].board_filter_value) { + omap_padconf = &omap_padconfs[x]; + break; + } + } + assert(omap_padconf); + + kern_phys_map_ptr(omap_padconf->base, omap_padconf->size, + VMMF_UNCACHED | VMMF_WRITE, + &padconf_phys_map, (vir_bytes) & omap_padconf->base); + + return; +} diff --git a/minix/kernel/arch/earmv6hf/bsp/ti/omap_reset.c b/minix/kernel/arch/earmv6hf/bsp/ti/omap_reset.c new file mode 100644 index 000000000..db8562657 --- /dev/null +++ b/minix/kernel/arch/earmv6hf/bsp/ti/omap_reset.c @@ -0,0 +1,100 @@ +#include +#include +#include +#include +#include +#include + +#include "kernel/kernel.h" +#include "kernel/proc.h" +#include "kernel/vm.h" +#include "kernel/proto.h" +#include "arch_proto.h" +#include "bsp_reset.h" + +#include "omap_timer_registers.h" +#include "omap_rtc.h" + +#define AM335X_CM_BASE 0x44E00000 +#define AM335X_CM_SIZE 0x1000 + +#define AM335X_PRM_DEVICE_OFFSET 0xf00 +#define AM335X_PRM_RSTCTRL_REG 0x00 +#define AM335X_RST_GLOBAL_WARM_SW_BIT 0 + +#define DM37XX_CM_BASE 0x48307000 +#define DM37XX_CM_SIZE 0x1000 +#define DM37XX_PRM_RSTCTRL_REG 0x250 +#define DM37XX_RST_DPLL3_BIT 2 + +struct omap_reset +{ + vir_bytes base; + vir_bytes size; +}; + +static struct omap_reset omap_reset; + +static kern_phys_map reset_phys_map; + +void +bsp_reset_init(void) +{ + if (BOARD_IS_BBXM(machine.board_id)) { + omap_reset.base = DM37XX_CM_BASE; + omap_reset.size = DM37XX_CM_SIZE; + } else if (BOARD_IS_BB(machine.board_id)) { + omap_reset.base = AM335X_CM_BASE; + omap_reset.size = AM335X_CM_SIZE; + } + + kern_phys_map_ptr(omap_reset.base, omap_reset.size, + VMMF_UNCACHED | VMMF_WRITE, + &reset_phys_map, (vir_bytes) & omap_reset.base); +} + +void +bsp_reset(void) +{ + if (BOARD_IS_BBXM(machine.board_id)) { + mmio_set((omap_reset.base + DM37XX_PRM_RSTCTRL_REG), + (1 << DM37XX_RST_DPLL3_BIT)); + } else if (BOARD_IS_BB(machine.board_id)) { + mmio_set((omap_reset.base + AM335X_PRM_DEVICE_OFFSET + + AM335X_PRM_RSTCTRL_REG), + (1 << AM335X_RST_GLOBAL_WARM_SW_BIT)); + } +} + +void +bsp_poweroff(void) +{ + +/* + * The am335x can signal an external power management chip to cut the power + * by toggling the PMIC_POWER_EN pin. It might fail if there isn't an + * external PMIC or if the PMIC hasn't been configured to respond to toggles. + * The only way to pull the pin low is via ALARM2 (see TRM 20.3.3.8). + * At this point PM should have already signaled readclock to set the alarm. + */ + if (BOARD_IS_BB(machine.board_id)) { + /* rtc was frozen to prevent premature power-off, unfreeze it + * now */ + omap3_rtc_run(); + + /* wait for the alarm to go off and PMIC to disable power to + * SoC */ + while (1); + } +} + +void bsp_disable_watchdog(void) +{ + if(BOARD_IS_BB(machine.board_id)) { + mmio_write(AM335X_WDT_BASE+AM335X_WDT_WSPR, 0xAAAA); + while(mmio_read(AM335X_WDT_BASE+AM335X_WDT_WWPS) != 0) ; + mmio_write(AM335X_WDT_BASE+AM335X_WDT_WSPR, 0x5555); + while(mmio_read(AM335X_WDT_BASE+AM335X_WDT_WWPS) != 0) ; + } +} + diff --git a/minix/kernel/arch/earmv6hf/bsp/ti/omap_rtc.c b/minix/kernel/arch/earmv6hf/bsp/ti/omap_rtc.c new file mode 100644 index 000000000..4e2fdeb3f --- /dev/null +++ b/minix/kernel/arch/earmv6hf/bsp/ti/omap_rtc.c @@ -0,0 +1,58 @@ +/* + * This is a mini driver for the AM335X Real Time Clock. The majority of the + * work is done in user space in readclock, but for power-off the clock needs + * to be put into run mode at the last possible moment in arch_reset.c. This + * driver just implements mapping the memory and re-starting the clock. + */ + +#include +#include +#include +#include +#include +#include + +#include "kernel/kernel.h" +#include "kernel/proc.h" +#include "kernel/vm.h" +#include "kernel/proto.h" +#include "arch_proto.h" +#include "omap_rtc.h" + +#define RTC_SS_BASE 0x44e3e000 +#define RTC_SS_SIZE 0x1000 +#define RTC_CTRL_REG 0x40 +#define RTC_CTRL_RTC_STOP_BIT 0 + +struct omap_rtc +{ + vir_bytes base; + vir_bytes size; +}; + +static struct omap_rtc omap_rtc = { + .base = RTC_SS_BASE, + .size = RTC_SS_SIZE +}; + +static kern_phys_map rtc_phys_map; + +void +omap3_rtc_init(void) +{ + if (BOARD_IS_BB(machine.board_id)) { + kern_phys_map_ptr(omap_rtc.base, omap_rtc.size, + VMMF_UNCACHED | VMMF_WRITE, &rtc_phys_map, + (vir_bytes) & omap_rtc.base); + } +} + +void +omap3_rtc_run(void) +{ + if (BOARD_IS_BB(machine.board_id)) { + /* Setting the stop bit starts the RTC running */ + mmio_set((omap_rtc.base + RTC_CTRL_REG), + (1 << RTC_CTRL_RTC_STOP_BIT)); + } +} diff --git a/minix/kernel/arch/earmv6hf/bsp/ti/omap_rtc.h b/minix/kernel/arch/earmv6hf/bsp/ti/omap_rtc.h new file mode 100644 index 000000000..cbed3a561 --- /dev/null +++ b/minix/kernel/arch/earmv6hf/bsp/ti/omap_rtc.h @@ -0,0 +1,7 @@ +#ifndef __OMAP_RTC_H +#define __OMAP_RTC_H + +void omap3_rtc_init(void); +void omap3_rtc_run(void); + +#endif /* __OMAP_RTC_H */ diff --git a/minix/kernel/arch/earmv6hf/bsp/ti/omap_serial.c b/minix/kernel/arch/earmv6hf/bsp/ti/omap_serial.c new file mode 100644 index 000000000..9affc52ef --- /dev/null +++ b/minix/kernel/arch/earmv6hf/bsp/ti/omap_serial.c @@ -0,0 +1,84 @@ +#include +#include +#include +#include +#include +#include + +#include "kernel/kernel.h" +#include "kernel/proc.h" +#include "kernel/vm.h" +#include "kernel/proto.h" +#include "arch_proto.h" + +#include "omap_serial.h" + +struct omap_serial +{ + vir_bytes base; + vir_bytes size; +}; + +static struct omap_serial omap_serial = { + .base = 0, +}; + +static kern_phys_map serial_phys_map; + +/* + * In kernel serial for the omap. The serial driver like most other + * drivers needs to be started early and even before the MMU is turned on. + * We start by directly accessing the hardware memory address. Later on + * a when the MMU is turned on we still use a 1:1 mapping for these addresses. + * + * Pretty soon we are going to remap these addresses at later stage. And this + * requires us to use a dynamic base address. The idea is to receive a callback + * from VM with the new address to use. + * + * We also anticipate on the beaglebone port an try to keep the differences between + * the drivers to a minimum by initializing a struct here and not using (to much) + * constants in the code. + * + * The serial driver also gets used in the "pre_init" stage before the kernel is loaded + * in high memory so keep in mind there are two copies of this code in the kernel. + */ +void +bsp_ser_init() +{ + if (BOARD_IS_BBXM(machine.board_id)) { + omap_serial.base = OMAP3_DM37XX_DEBUG_UART_BASE; + } else if (BOARD_IS_BB(machine.board_id)) { + omap_serial.base = OMAP3_AM335X_DEBUG_UART_BASE; + } + omap_serial.size = 0x1000; /* 4k */ + + kern_phys_map_ptr(omap_serial.base, omap_serial.size, + VMMF_UNCACHED | VMMF_WRITE, &serial_phys_map, + (vir_bytes) & omap_serial.base); + assert(omap_serial.base); +} + +void +bsp_ser_putc(char c) +{ + int i; + assert(omap_serial.base); + + /* Wait until FIFO's empty */ + for (i = 0; i < 100000; i++) { + if (mmio_read(omap_serial.base + OMAP3_LSR) & OMAP3_LSR_THRE) { + break; + } + } + + /* Write character */ + mmio_write(omap_serial.base + OMAP3_THR, c); + + /* And wait again until FIFO's empty to prevent TTY from overwriting */ + for (i = 0; i < 100000; i++) { + if (mmio_read(omap_serial.base + + OMAP3_LSR) & (OMAP3_LSR_THRE | OMAP3_LSR_TEMT)) { + break; + } + } +} diff --git a/minix/kernel/arch/earmv6hf/bsp/ti/omap_serial.h b/minix/kernel/arch/earmv6hf/bsp/ti/omap_serial.h new file mode 100644 index 000000000..84272a2fa --- /dev/null +++ b/minix/kernel/arch/earmv6hf/bsp/ti/omap_serial.h @@ -0,0 +1,27 @@ +#ifndef _OMAP_SERIAL_H +#define _OMAP_SERIAL_H + +/* UART register map */ +#define OMAP3_DM37XX_DEBUG_UART_BASE 0x49020000 /* UART3 physical address */ +#define OMAP3_AM335X_DEBUG_UART_BASE 0x44E09000 /* UART0? physical address */ + +/* UART registers */ +#define OMAP3_THR 0x000 /* Transmit holding register */ +#define OMAP3_LSR 0x014 /* Line status register */ +#define OMAP3_SSR 0x044 /* Supplementary status register */ + +/* Line status register fields */ +#define OMAP3_LSR_TEMT 0x40 /* Transmitter empty */ +#define OMAP3_LSR_THRE 0x20 /* Transmit-hold-register empty */ + +/* Supplementary status register fields */ +#define OMAP3_SSR_TX_FIFO_FULL (1 << 0) /* Transmit FIFO full */ + +#ifndef __ASSEMBLY__ + +void omap3_ser_init(); +void omap3_ser_putc(char c); + +#endif /* __ASSEMBLY__ */ + +#endif /* _OMAP_SERIAL_H */ diff --git a/minix/kernel/arch/earmv6hf/bsp/ti/omap_timer.c b/minix/kernel/arch/earmv6hf/bsp/ti/omap_timer.c new file mode 100644 index 000000000..bb764b377 --- /dev/null +++ b/minix/kernel/arch/earmv6hf/bsp/ti/omap_timer.c @@ -0,0 +1,397 @@ +#include "kernel/kernel.h" +#include "kernel/clock.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include "arch_proto.h" +#include "bsp_timer.h" +#include "omap_timer_registers.h" +#include "omap_intr_registers.h" +#include "bsp_intr.h" + +/* interrupt handler hook */ +static irq_hook_t omap3_timer_hook; +static u64_t high_frc; + +struct omap_timer_registers; + +struct omap_timer +{ + vir_bytes base; + int irq_nr; + struct omap_timer_registers *regs; +}; + +struct omap_timer_registers +{ + vir_bytes TIDR; + vir_bytes TIOCP_CFG; + vir_bytes TISTAT; + vir_bytes TISR; + vir_bytes TIER; + vir_bytes TWER; + vir_bytes TCLR; + vir_bytes TCRR; + vir_bytes TLDR; + vir_bytes TTGR; + vir_bytes TWPS; + vir_bytes TMAR; + vir_bytes TCAR1; + vir_bytes TSICR; + vir_bytes TCAR2; + vir_bytes TPIR; + vir_bytes TNIR; + vir_bytes TCVR; + vir_bytes TOCR; + vir_bytes TOWR; + +}; + +static struct omap_timer_registers regs_v1 = { + .TIDR = OMAP3_TIMER_TIDR, + .TIOCP_CFG = OMAP3_TIMER_TIOCP_CFG, + .TISTAT = OMAP3_TIMER_TISTAT, + .TISR = OMAP3_TIMER_TISR, + .TIER = OMAP3_TIMER_TIER, + .TWER = OMAP3_TIMER_TWER, + .TCLR = OMAP3_TIMER_TCLR, + .TCRR = OMAP3_TIMER_TCRR, + .TLDR = OMAP3_TIMER_TLDR, + .TTGR = OMAP3_TIMER_TTGR, + .TWPS = OMAP3_TIMER_TWPS, + .TMAR = OMAP3_TIMER_TMAR, + .TCAR1 = OMAP3_TIMER_TCAR1, + .TSICR = OMAP3_TIMER_TSICR, + .TCAR2 = OMAP3_TIMER_TCAR2, + .TPIR = OMAP3_TIMER_TPIR, + .TNIR = OMAP3_TIMER_TNIR, + .TCVR = OMAP3_TIMER_TCVR, + .TOCR = OMAP3_TIMER_TOCR, + .TOWR = OMAP3_TIMER_TOWR, +}; + +/* AM335X has a different ip block for the non + 1ms timers */ +static struct omap_timer_registers regs_v2 = { + .TIDR = AM335X_TIMER_TIDR, + .TIOCP_CFG = AM335X_TIMER_TIOCP_CFG, + .TISTAT = AM335X_TIMER_IRQSTATUS_RAW, + .TISR = AM335X_TIMER_IRQSTATUS, + .TIER = AM335X_TIMER_IRQENABLE_SET, + .TWER = AM335X_TIMER_IRQWAKEEN, + .TCLR = AM335X_TIMER_TCLR, + .TCRR = AM335X_TIMER_TCRR, + .TLDR = AM335X_TIMER_TLDR, + .TTGR = AM335X_TIMER_TTGR, + .TWPS = AM335X_TIMER_TWPS, + .TMAR = AM335X_TIMER_TMAR, + .TCAR1 = AM335X_TIMER_TCAR1, + .TSICR = AM335X_TIMER_TSICR, + .TCAR2 = AM335X_TIMER_TCAR2, + .TPIR = -1, /* UNDEF */ + .TNIR = -1, /* UNDEF */ + .TCVR = -1, /* UNDEF */ + .TOCR = -1, /* UNDEF */ + .TOWR = -1 /* UNDEF */ +}; + +static struct omap_timer dm37xx_timer = { + .base = OMAP3_GPTIMER1_BASE, + .irq_nr = OMAP3_GPT1_IRQ, + .regs = ®s_v1 +}; + +/* free running timer */ +static struct omap_timer dm37xx_fr_timer = { + .base = OMAP3_GPTIMER10_BASE, + .irq_nr = OMAP3_GPT10_IRQ, + .regs = ®s_v1 +}; + +/* normal timer */ +static struct omap_timer am335x_timer = { + .base = AM335X_DMTIMER1_1MS_BASE, + .irq_nr = AM335X_INT_TINT1_1MS, + .regs = ®s_v1 +}; + +/* free running timer */ +static struct omap_timer am335x_fr_timer = { + .base = AM335X_DMTIMER7_BASE, + .irq_nr = AM335X_INT_TINT7, + .regs = ®s_v2 +}; + +static struct omap_timer *timer; +static struct omap_timer *fr_timer; + +static int done = 0; + +int +bsp_register_timer_handler(const irq_handler_t handler) +{ + /* Initialize the CLOCK's interrupt hook. */ + omap3_timer_hook.proc_nr_e = NONE; + omap3_timer_hook.irq = timer->irq_nr; + + put_irq_handler(&omap3_timer_hook, timer->irq_nr, handler); + /* only unmask interrupts after registering */ + bsp_irq_unmask(timer->irq_nr); + + return 0; +} + +/* meta data for remapping */ +static kern_phys_map timer_phys_map; +static kern_phys_map fr_timer_phys_map; +static kern_phys_map fr_timer_user_phys_map; /* struct for when the free */ + /* running timer is mapped to */ + /* userland */ + +/* callback for when the free running clock gets mapped */ +int +kern_phys_fr_user_mapped(vir_bytes id, phys_bytes address) +{ + /* the only thing we need to do at this stage is to set the address */ + /* in the kerninfo struct */ + if (BOARD_IS_BBXM(machine.board_id)) { + minix_kerninfo.minix_frclock_tcrr = address + OMAP3_TIMER_TCRR; + minix_kerninfo.minix_arm_frclock_hz = 1625000; + } else if (BOARD_IS_BB(machine.board_id)) { + minix_kerninfo.minix_frclock_tcrr = + address + AM335X_TIMER_TCRR; + minix_kerninfo.minix_arm_frclock_hz = 1500000; + } + return 0; +} + +void +omap3_frclock_init(void) +{ + u32_t tisr; + + /* enable the clock */ + if (BOARD_IS_BBXM(machine.board_id)) { + fr_timer = &dm37xx_fr_timer; + + kern_phys_map_ptr(fr_timer->base, ARM_PAGE_SIZE, + VMMF_UNCACHED | VMMF_WRITE, &fr_timer_phys_map, + (vir_bytes) & fr_timer->base); + + /* the timer is also mapped in user space hence the this */ + /* second mapping and callback to set kerninfo frclock_tcrr */ + kern_req_phys_map(fr_timer->base, ARM_PAGE_SIZE, + VMMF_UNCACHED | VMMF_USER, + &fr_timer_user_phys_map, kern_phys_fr_user_mapped, 0); + + /* Stop timer */ + mmio_clear(fr_timer->base + fr_timer->regs->TCLR, + OMAP3_TCLR_ST); + + /* Use functional clock source for GPTIMER10 */ + mmio_set(OMAP3_CM_CLKSEL_CORE, OMAP3_CLKSEL_GPT10); + + /* Scale timer down to 13/8 = 1.625 Mhz to roughly get + * microsecond ticks */ + /* The scale is computed as 2^(PTV+1). So if PTV == 2, we get + * 2^3 = 8. */ + mmio_set(fr_timer->base + fr_timer->regs->TCLR, + (2 << OMAP3_TCLR_PTV)); + } else if (BOARD_IS_BB(machine.board_id)) { + fr_timer = &am335x_fr_timer; + kern_phys_map_ptr(fr_timer->base, ARM_PAGE_SIZE, + VMMF_UNCACHED | VMMF_WRITE, + &fr_timer_phys_map, (vir_bytes) & fr_timer->base); + + /* the timer is also mapped in user space hence the this */ + /* second mapping and callback to set kerninfo frclock_tcrr */ + kern_req_phys_map(fr_timer->base, ARM_PAGE_SIZE, + VMMF_UNCACHED | VMMF_USER, + &fr_timer_user_phys_map, kern_phys_fr_user_mapped, 0); + /* Disable the module and wait for the module to be disabled */ + set32(CM_PER_TIMER7_CLKCTRL, CM_MODULEMODE_MASK, + CM_MODULEMODE_DISABLED); + while ((mmio_read(CM_PER_TIMER7_CLKCTRL) & CM_CLKCTRL_IDLEST) + != CM_CLKCTRL_IDLEST_DISABLE); + + set32(CLKSEL_TIMER7_CLK, CLKSEL_TIMER7_CLK_SEL_MASK, + CLKSEL_TIMER7_CLK_SEL_SEL2); + while ((read32(CLKSEL_TIMER7_CLK) & CLKSEL_TIMER7_CLK_SEL_MASK) + != CLKSEL_TIMER7_CLK_SEL_SEL2); + + /* enable the module and wait for the module to be ready */ + set32(CM_PER_TIMER7_CLKCTRL, CM_MODULEMODE_MASK, + CM_MODULEMODE_ENABLE); + while ((mmio_read(CM_PER_TIMER7_CLKCTRL) & CM_CLKCTRL_IDLEST) + != CM_CLKCTRL_IDLEST_FUNC); + + /* Stop timer */ + mmio_clear(fr_timer->base + fr_timer->regs->TCLR, + OMAP3_TCLR_ST); + + /* 24Mhz / 16 = 1.5 Mhz */ + mmio_set(fr_timer->base + fr_timer->regs->TCLR, + (3 << OMAP3_TCLR_PTV)); + } + + /* Start and auto-reload at 0 */ + mmio_write(fr_timer->base + fr_timer->regs->TLDR, 0x0); + mmio_write(fr_timer->base + fr_timer->regs->TCRR, 0x0); + + /* Set up overflow interrupt */ + tisr = OMAP3_TISR_MAT_IT_FLAG | OMAP3_TISR_OVF_IT_FLAG | + OMAP3_TISR_TCAR_IT_FLAG; + /* Clear interrupt status */ + mmio_write(fr_timer->base + fr_timer->regs->TISR, tisr); + mmio_write(fr_timer->base + fr_timer->regs->TIER, + OMAP3_TIER_OVF_IT_ENA); + + /* Start timer */ + mmio_set(fr_timer->base + fr_timer->regs->TCLR, + OMAP3_TCLR_OVF_TRG | OMAP3_TCLR_AR | OMAP3_TCLR_ST | + OMAP3_TCLR_PRE); + done = 1; +} + +void +omap3_frclock_stop() +{ + mmio_clear(fr_timer->base + fr_timer->regs->TCLR, OMAP3_TCLR_ST); +} + +void +bsp_timer_init(unsigned freq) +{ + /* we only support 1ms resolution */ + u32_t tisr; + if (BOARD_IS_BBXM(machine.board_id)) { + timer = &dm37xx_timer; + kern_phys_map_ptr(timer->base, ARM_PAGE_SIZE, + VMMF_UNCACHED | VMMF_WRITE, + &timer_phys_map, (vir_bytes) & timer->base); + /* Stop timer */ + mmio_clear(timer->base + timer->regs->TCLR, OMAP3_TCLR_ST); + + /* Use 32 KHz clock source for GPTIMER1 */ + mmio_clear(OMAP3_CM_CLKSEL_WKUP, OMAP3_CLKSEL_GPT1); + } else if (BOARD_IS_BB(machine.board_id)) { + timer = &am335x_timer; + kern_phys_map_ptr(timer->base, ARM_PAGE_SIZE, + VMMF_UNCACHED | VMMF_WRITE, + &timer_phys_map, (vir_bytes) & timer->base); + /* disable the module and wait for the module to be disabled */ + set32(CM_WKUP_TIMER1_CLKCTRL, CM_MODULEMODE_MASK, + CM_MODULEMODE_DISABLED); + while ((mmio_read(CM_WKUP_TIMER1_CLKCTRL) & CM_CLKCTRL_IDLEST) + != CM_CLKCTRL_IDLEST_DISABLE); + + set32(CLKSEL_TIMER1MS_CLK, CLKSEL_TIMER1MS_CLK_SEL_MASK, + CLKSEL_TIMER1MS_CLK_SEL_SEL2); + while ((read32(CLKSEL_TIMER1MS_CLK) & + CLKSEL_TIMER1MS_CLK_SEL_MASK) != + CLKSEL_TIMER1MS_CLK_SEL_SEL2); + + /* enable the module and wait for the module to be ready */ + set32(CM_WKUP_TIMER1_CLKCTRL, CM_MODULEMODE_MASK, + CM_MODULEMODE_ENABLE); + while ((mmio_read(CM_WKUP_TIMER1_CLKCTRL) & CM_CLKCTRL_IDLEST) + != CM_CLKCTRL_IDLEST_FUNC); + + /* Stop timer */ + mmio_clear(timer->base + timer->regs->TCLR, OMAP3_TCLR_ST); + } + + /* Use 1-ms tick mode for GPTIMER1 TRM 16.2.4.2.1 */ + mmio_write(timer->base + timer->regs->TPIR, 232000); + mmio_write(timer->base + timer->regs->TNIR, -768000); + mmio_write(timer->base + timer->regs->TLDR, + 0xffffffff - (32768 / freq) + 1); + mmio_write(timer->base + timer->regs->TCRR, + 0xffffffff - (32768 / freq) + 1); + + /* Set up overflow interrupt */ + tisr = OMAP3_TISR_MAT_IT_FLAG | OMAP3_TISR_OVF_IT_FLAG | + OMAP3_TISR_TCAR_IT_FLAG; + /* Clear interrupt status */ + mmio_write(timer->base + timer->regs->TISR, tisr); + mmio_write(timer->base + timer->regs->TIER, OMAP3_TIER_OVF_IT_ENA); + + /* Start timer */ + mmio_set(timer->base + timer->regs->TCLR, + OMAP3_TCLR_OVF_TRG | OMAP3_TCLR_AR | OMAP3_TCLR_ST); + /* also initilize the free runnning timer */ + omap3_frclock_init(); +} + +void +bsp_timer_stop() +{ + mmio_clear(timer->base + timer->regs->TCLR, OMAP3_TCLR_ST); +} + +static u32_t +read_frc(void) +{ + if (done == 0) { + return 0; + } + return mmio_read(fr_timer->base + fr_timer->regs->TCRR); +} + +/* + * Check if the free running clock has overflown and + * increase the high free running clock counter if + * so. This method takes the current timer value as + * parameter to ensure the overflow check is done + * on the current timer value. + * + * To compose the current timer value (64 bits) you + * need to follow the following sequence: + * read the current timer value. + * call the overflow check + * compose the 64 bits time based on the current timer value + * and high_frc. + */ +static void +frc_overflow_check(u32_t cur_frc) +{ + static int prev_frc_valid; + static u32_t prev_frc; + if (prev_frc_valid && prev_frc > cur_frc) { + high_frc++; + } + prev_frc = cur_frc; + prev_frc_valid = 1; +} + +void +bsp_timer_int_handler() +{ + /* Clear all interrupts */ + u32_t tisr, now; + + /* when the kernel itself is running interrupts are disabled. We + * should therefore also read the overflow counter to detect this as + * to not miss events. */ + tisr = OMAP3_TISR_MAT_IT_FLAG | OMAP3_TISR_OVF_IT_FLAG | + OMAP3_TISR_TCAR_IT_FLAG; + mmio_write(timer->base + timer->regs->TISR, tisr); + + now = read_frc(); + frc_overflow_check(now); +} + +/* Use the free running clock as TSC */ +void +read_tsc_64(u64_t * t) +{ + u32_t now; + now = read_frc(); + frc_overflow_check(now); + *t = (u64_t) now + (high_frc << 32); +} diff --git a/minix/kernel/arch/earmv6hf/bsp/ti/omap_timer_registers.h b/minix/kernel/arch/earmv6hf/bsp/ti/omap_timer_registers.h new file mode 100644 index 000000000..b127e48ed --- /dev/null +++ b/minix/kernel/arch/earmv6hf/bsp/ti/omap_timer_registers.h @@ -0,0 +1,157 @@ +#ifndef _OMAP_TIMER_REGISTERS_H +#define _OMAP_TIMER_REGISTERS_H + + +/* General-purpose timer register map */ +#define OMAP3_GPTIMER1_BASE 0x48318000 /* GPTIMER1 physical address */ +#define OMAP3_GPTIMER2_BASE 0x49032000 /* GPTIMER2 physical address */ +#define OMAP3_GPTIMER3_BASE 0x49034000 /* GPTIMER3 physical address */ +#define OMAP3_GPTIMER4_BASE 0x49036000 /* GPTIMER4 physical address */ +#define OMAP3_GPTIMER5_BASE 0x49038000 /* GPTIMER5 physical address */ +#define OMAP3_GPTIMER6_BASE 0x4903A000 /* GPTIMER6 physical address */ +#define OMAP3_GPTIMER7_BASE 0x4903C000 /* GPTIMER7 physical address */ +#define OMAP3_GPTIMER8_BASE 0x4903E000 /* GPTIMER8 physical address */ +#define OMAP3_GPTIMER9_BASE 0x49040000 /* GPTIMER9 physical address */ +#define OMAP3_GPTIMER10_BASE 0x48086000 /* GPTIMER10 physical address */ +#define OMAP3_GPTIMER11_BASE 0x48088000 /* GPTIMER11 physical address */ + + +/* General-purpose timer registers */ +#define OMAP3_TIMER_TIDR 0x000 /* IP revision code */ +#define OMAP3_TIMER_TIOCP_CFG 0x010 /* Controls params for GP timer L4 interface */ +#define OMAP3_TIMER_TISTAT 0x014 /* Status (excl. interrupt status) */ +#define OMAP3_TIMER_TISR 0x018 /* Pending interrupt status */ +#define OMAP3_TIMER_TIER 0x01C /* Interrupt enable */ +#define OMAP3_TIMER_TWER 0x020 /* Wakeup enable */ +#define OMAP3_TIMER_TCLR 0x024 /* Controls optional features */ +#define OMAP3_TIMER_TCRR 0x028 /* Internal counter value */ +#define OMAP3_TIMER_TLDR 0x02C /* Timer load value */ +#define OMAP3_TIMER_TTGR 0x030 /* Triggers counter reload */ +#define OMAP3_TIMER_TWPS 0x034 /* Indicates if Write-Posted pending */ +#define OMAP3_TIMER_TMAR 0x038 /* Value to be compared with counter */ +#define OMAP3_TIMER_TCAR1 0x03C /* First captured value of counter register */ +#define OMAP3_TIMER_TSICR 0x040 /* Control posted mode and functional SW reset */ +#define OMAP3_TIMER_TCAR2 0x044 /* Second captured value of counter register */ +#define OMAP3_TIMER_TPIR 0x048 /* Positive increment (1 ms tick) */ +#define OMAP3_TIMER_TNIR 0x04C /* Negative increment (1 ms tick) */ +#define OMAP3_TIMER_TCVR 0x050 /* Defines TCRR is sub/over-period (1 ms tick) */ +#define OMAP3_TIMER_TOCR 0x054 /* Masks tick interrupt */ +#define OMAP3_TIMER_TOWR 0x058 /* Number of masked overflow interrupts */ + +#define AM335X_DMTIMER0_BASE 0x44E05000 /* DMTimer0 Registers */ +#define AM335X_DMTIMER1_1MS_BASE 0x44E31000 /* DMTimer1 1ms Registers (Accurate 1ms timer) */ +#define AM335X_DMTIMER2_BASE 0x48040000 /* DMTimer2 Registers */ +#define AM335X_DMTIMER3_BASE 0x48042000 /* DMTimer3 Registers */ +#define AM335X_DMTIMER4_BASE 0x48044000 /* DMTimer4 Registers */ +#define AM335X_DMTIMER5_BASE 0x48046000 /* DMTimer5 Registers */ +#define AM335X_DMTIMER6_BASE 0x48048000 /* DMTimer6 Registers */ +#define AM335X_DMTIMER7_BASE 0x4804A000 /* DMTimer7 Registers */ + +/* General-purpose timer registers AM335x non 1MS timers have different offsets */ +#define AM335X_TIMER_TIDR 0x000 /* IP revision code */ +#define AM335X_TIMER_TIOCP_CFG 0x010 /* Controls params for GP timer L4 interface */ +#define AM335X_TIMER_IRQSTATUS_RAW 0x024 /* Timer IRQSTATUS Raw Register */ +#define AM335X_TIMER_IRQSTATUS 0x028 /* Timer IRQSTATUS Register */ +#define AM335X_TIMER_IRQENABLE_SET 0x02C /* Timer IRQENABLE Set Register */ +#define AM335X_TIMER_IRQENABLE_CLR 0x030 /* Timer IRQENABLE Clear Register */ +#define AM335X_TIMER_IRQWAKEEN 0x034 /* Timer IRQ Wakeup Enable Register */ +#define AM335X_TIMER_TCLR 0x038 /* Controls optional features */ +#define AM335X_TIMER_TCRR 0x03C /* Internal counter value */ +#define AM335X_TIMER_TLDR 0x040 /* Timer load value */ +#define AM335X_TIMER_TTGR 0x044 /* Triggers counter reload */ +#define AM335X_TIMER_TWPS 0x048 /* Indicates if Write-Posted pending */ +#define AM335X_TIMER_TMAR 0x04C /* Value to be compared with counter */ +#define AM335X_TIMER_TCAR1 0x050 /* First captured value of counter register */ +#define AM335X_TIMER_TSICR 0x054 /* Control posted mode and functional SW reset */ +#define AM335X_TIMER_TCAR2 0x058 /* Second captured value of counter register */ + +#define AM335X_WDT_BASE 0x44E35000 /* watchdog timer */ +#define AM335X_WDT_WWPS 0x34 /* command posted status */ +#define AM335X_WDT_WSPR 0x48 /* activate/deactivate sequence */ + +/* Interrupt status register fields */ +#define OMAP3_TISR_MAT_IT_FLAG (1 << 0) /* Pending match interrupt status */ +#define OMAP3_TISR_OVF_IT_FLAG (1 << 1) /* Pending overflow interrupt status */ +#define OMAP3_TISR_TCAR_IT_FLAG (1 << 2) /* Pending capture interrupt status */ + +/* Interrupt enable register fields */ +#define OMAP3_TIER_MAT_IT_ENA (1 << 0) /* Enable match interrupt */ +#define OMAP3_TIER_OVF_IT_ENA (1 << 1) /* Enable overflow interrupt */ +#define OMAP3_TIER_TCAR_IT_ENA (1 << 2) /* Enable capture interrupt */ + +/* Timer control fields */ +#define OMAP3_TCLR_ST (1 << 0) /* Start/stop timer */ +#define OMAP3_TCLR_AR (1 << 1) /* Autoreload or one-shot mode */ +#define OMAP3_TCLR_PRE (1 << 5) /* Prescaler on */ +#define OMAP3_TCLR_PTV 2 +#define OMAP3_TCLR_OVF_TRG (1 << 10) /* Overflow trigger */ + + +#define OMAP3_CM_CLKSEL_GFX 0x48004b40 +#define OMAP3_CM_CLKEN_PLL 0x48004d00 +#define OMAP3_CM_FCLKEN1_CORE 0x48004A00 +#define OMAP3_CM_CLKSEL_CORE 0x48004A40 /* GPT10 src clock sel. */ +#define OMAP3_CM_FCLKEN_PER 0x48005000 +#define OMAP3_CM_CLKSEL_PER 0x48005040 +#define OMAP3_CM_CLKSEL_WKUP 0x48004c40 /* GPT1 source clock selection */ + + +#define CM_MODULEMODE_MASK (0x3 << 0) +#define CM_MODULEMODE_ENABLE (0x2 << 0) +#define CM_MODULEMODE_DISABLED (0x0 << 0) + +#define CM_CLKCTRL_IDLEST (0x3 << 16) +#define CM_CLKCTRL_IDLEST_FUNC (0x0 << 16) +#define CM_CLKCTRL_IDLEST_TRANS (0x1 << 16) +#define CM_CLKCTRL_IDLEST_IDLE (0x2 << 16) +#define CM_CLKCTRL_IDLEST_DISABLE (0x3 << 16) + +#define CM_WKUP_BASE 0x44E00400 /* Clock Module Wakeup Registers */ + +#define CM_WKUP_TIMER1_CLKCTRL (CM_WKUP_BASE + 0xC4) /* This register manages the TIMER1 clocks. [Memory Mapped] */ + + +#define CM_PER_BASE 0x44E00000 /* Clock Module Peripheral Registers */ +#define CM_PER_TIMER7_CLKCTRL (CM_PER_BASE + 0x7C) /* This register manages the TIMER7 clocks. [Memory Mapped] */ + + + +/* CM_DPLL registers */ + + +#define CM_DPLL_BASE 0x44E00500 /* Clock Module PLL Registers */ + +#define CLKSEL_TIMER1MS_CLK (CM_DPLL_BASE + 0x28) + + +#define CLKSEL_TIMER1MS_CLK_SEL_MASK (0x7 << 0) +#define CLKSEL_TIMER1MS_CLK_SEL_SEL1 (0x0 << 0) /* Select CLK_M_OSC clock */ +#define CLKSEL_TIMER1MS_CLK_SEL_SEL2 (0x1 << 0) /* Select CLK_32KHZ clock */ +#define CLKSEL_TIMER1MS_CLK_SEL_SEL3 (0x2 << 0) /* Select TCLKIN clock */ +#define CLKSEL_TIMER1MS_CLK_SEL_SEL4 (0x3 << 0) /* Select CLK_RC32K clock */ +#define CLKSEL_TIMER1MS_CLK_SEL_SEL5 (0x4 << 0) /* Selects the CLK_32768 from 32KHz Crystal Osc */ + +#define CLKSEL_TIMER7_CLK (CM_DPLL_BASE + 0x04) +#define CLKSEL_TIMER7_CLK_SEL_MASK (0x3 << 0) +#define CLKSEL_TIMER7_CLK_SEL_SEL1 (0x0 << 0) /* Select TCLKIN clock */ +#define CLKSEL_TIMER7_CLK_SEL_SEL2 (0x1 << 0) /* Select CLK_M_OSC clock */ +#define CLKSEL_TIMER7_CLK_SEL_SEL3 (0x2 << 0) /* Select CLK_32KHZ clock */ +#define CLKSEL_TIMER7_CLK_SEL_SEL4 (0x3 << 0) /* Reserved */ + + + + +#define OMAP3_CLKSEL_GPT1 (1 << 0) /* Selects GPTIMER 1 source + * clock: + * + * 0: use 32KHz clock + * 1: sys clock) + */ +#define OMAP3_CLKSEL_GPT10 (1 << 6) +#define OMAP3_CLKSEL_GPT11 (1 << 7) + + +#define TIMER_FREQ 1000 /* clock frequency for OMAP timer (1ms) */ +#define TIMER_COUNT(freq) (TIMER_FREQ/(freq)) /* initial value for counter*/ + +#endif /* _OMAP_TIMER_REGISTERS_H */ diff --git a/minix/kernel/arch/earmv6hf/direct_tty_utils.c b/minix/kernel/arch/earmv6hf/direct_tty_utils.c new file mode 100644 index 000000000..46ee67498 --- /dev/null +++ b/minix/kernel/arch/earmv6hf/direct_tty_utils.c @@ -0,0 +1,30 @@ + +#include "kernel/kernel.h" +#include "direct_utils.h" +#include "bsp_serial.h" +#include "glo.h" + +void direct_cls(void) +{ + /* Do nothing */ +} + +void direct_print_char(char c) +{ + if(c == '\n') + bsp_ser_putc('\r'); + ser_putc(c); +} + +void direct_print(const char *str) +{ + while (*str) { + direct_print_char(*str); + str++; + } +} + +int direct_read_char(unsigned char *ch) +{ + return 0; +} diff --git a/minix/kernel/arch/earmv6hf/do_padconf.c b/minix/kernel/arch/earmv6hf/do_padconf.c new file mode 100644 index 000000000..89bbb9233 --- /dev/null +++ b/minix/kernel/arch/earmv6hf/do_padconf.c @@ -0,0 +1,18 @@ +#include "kernel/system.h" +#include + +#if USE_PADCONF + +/* get arch specific arch_padconf_set() */ +#include "bsp_padconf.h" + +/*===========================================================================* + * do_padconf * + *===========================================================================*/ +int do_padconf(struct proc *caller_ptr, message *m_ptr) +{ + return bsp_padconf_set(m_ptr->PADCONF_PADCONF, m_ptr->PADCONF_MASK, + m_ptr->PADCONF_VALUE); +} + +#endif /* USE_PADCONF */ diff --git a/minix/kernel/arch/earmv6hf/exc.S b/minix/kernel/arch/earmv6hf/exc.S new file mode 100644 index 000000000..743102cb2 --- /dev/null +++ b/minix/kernel/arch/earmv6hf/exc.S @@ -0,0 +1,22 @@ +#include + +IMPORT(undefined_inst_entry) +IMPORT(svc_entry) +IMPORT(prefetch_abort_entry) +IMPORT(data_abort_entry) +IMPORT(irq_entry) + +.text +.balign 4096 +LABEL(exc_vector_table) + ldr pc, =invalid_exc /* Reset */ + ldr pc, =undefined_inst_entry /* Undefined Instruction */ + ldr pc, =svc_entry /* Supervisor Call */ + ldr pc, =prefetch_abort_entry /* Prefetch Abort */ + ldr pc, =data_abort_entry /* Data Abort */ + ldr pc, =invalid_exc /* Hypervisor Call */ + ldr pc, =irq_entry /* Interrupt */ + ldr pc, =invalid_exc /* Fast Interrupt */ + +ENTRY(invalid_exc) + b . diff --git a/minix/kernel/arch/earmv6hf/exception.c b/minix/kernel/arch/earmv6hf/exception.c new file mode 100644 index 000000000..ee074a81e --- /dev/null +++ b/minix/kernel/arch/earmv6hf/exception.c @@ -0,0 +1,232 @@ +/* This file contains a simple exception handler. Exceptions in user + * processes are converted to signals. Exceptions in a kernel task cause + * a panic. + */ + +#include "kernel/kernel.h" +#include "arch_proto.h" +#include +#include +#include +#include "kernel/proc.h" +#include "kernel/proto.h" +#include + +struct ex_s { + char *msg; + int signum; +}; + +static struct ex_s ex_data[] = { + { "Reset", 0}, + { "Undefined instruction", SIGILL}, + { "Supervisor call", 0}, + { "Prefetch Abort", SIGILL}, + { "Data Abort", SIGSEGV}, + { "Hypervisor call", 0}, + { "Interrupt", 0}, + { "Fast Interrupt", 0}, +}; + +static void inkernel_disaster(struct proc *saved_proc, + reg_t *saved_lr, struct ex_s *ep, int is_nested); + +extern int catch_pagefaults; + +static void proc_stacktrace_execute(struct proc *whichproc, reg_t v_bp, reg_t pc); + +static void pagefault( struct proc *pr, + reg_t *saved_lr, + int is_nested, + u32_t pagefault_addr, + u32_t pagefault_status) +{ + int in_physcopy = 0, in_memset = 0; + + message m_pagefault; + int err; + + in_physcopy = (*saved_lr > (vir_bytes) phys_copy) && + (*saved_lr < (vir_bytes) phys_copy_fault); + + in_memset = (*saved_lr > (vir_bytes) phys_memset) && + (*saved_lr < (vir_bytes) memset_fault); + + if((is_nested || iskernelp(pr)) && + catch_pagefaults && (in_physcopy || in_memset)) { + if (is_nested) { + if(in_physcopy) { + assert(!in_memset); + *saved_lr = (reg_t) phys_copy_fault_in_kernel; + } else { + *saved_lr = (reg_t) memset_fault_in_kernel; + } + } + else { + pr->p_reg.pc = (reg_t) phys_copy_fault; + pr->p_reg.retreg = pagefault_addr; + } + + return; + } + + if(is_nested) { + printf("pagefault in kernel at pc 0x%lx address 0x%lx\n", + *saved_lr, pagefault_addr); + inkernel_disaster(pr, saved_lr, NULL, is_nested); + } + + /* VM can't handle page faults. */ + if(pr->p_endpoint == VM_PROC_NR) { + /* Page fault we can't / don't want to + * handle. + */ + printf("pagefault for VM on CPU %d, " + "pc = 0x%x, addr = 0x%x, flags = 0x%x, is_nested %d\n", + cpuid, pr->p_reg.pc, pagefault_addr, pagefault_status, + is_nested); + proc_stacktrace(pr); + printf("pc of pagefault: 0x%lx\n", pr->p_reg.pc); + panic("pagefault in VM"); + + return; + } + + /* Don't schedule this process until pagefault is handled. */ + RTS_SET(pr, RTS_PAGEFAULT); + + /* tell Vm about the pagefault */ + m_pagefault.m_source = pr->p_endpoint; + m_pagefault.m_type = VM_PAGEFAULT; + m_pagefault.VPF_ADDR = pagefault_addr; + m_pagefault.VPF_FLAGS = pagefault_status; + + if ((err = mini_send(pr, VM_PROC_NR, + &m_pagefault, FROM_KERNEL))) { + panic("WARNING: pagefault: mini_send returned %d\n", err); + } + + return; +} + +static void inkernel_disaster(struct proc *saved_proc, + reg_t *saved_lr, struct ex_s *ep, + int is_nested) +{ +#if USE_SYSDEBUG + if(ep) + printf("\n%s\n", ep->msg); + + printf("cpu %d is_nested = %d ", cpuid, is_nested); + + if (saved_proc) { + printf("scheduled was: process %d (%s), ", saved_proc->p_endpoint, saved_proc->p_name); + printf("pc = 0x%x\n", (unsigned) saved_proc->p_reg.pc); + proc_stacktrace(saved_proc); + + panic("Unhandled kernel exception"); + } + + /* in an early stage of boot process we don't have processes yet */ + panic("exception in kernel while booting, no saved_proc yet"); + +#endif /* USE_SYSDEBUG */ +} + +void exception_handler(int is_nested, reg_t *saved_lr, int vector) +{ +/* An exception or unexpected interrupt has occurred. */ + struct ex_s *ep; + struct proc *saved_proc; + + saved_proc = get_cpulocal_var(proc_ptr); + + ep = &ex_data[vector]; + + assert((vir_bytes) saved_lr >= kinfo.vir_kern_start); + + /* + * handle special cases for nested problems as they might be tricky or filter + * them out quickly if the traps are not nested + */ + if (is_nested) { + /* + * if a problem occurred while copying a message from userspace because + * of a wrong pointer supplied by userland, handle it the only way we + * can handle it ... + */ + if (((void*)*saved_lr >= (void*)copy_msg_to_user && + (void*)*saved_lr <= (void*)__copy_msg_to_user_end) || + ((void*)*saved_lr >= (void*)copy_msg_from_user && + (void*)*saved_lr <= (void*)__copy_msg_from_user_end)) { + switch(vector) { + /* these error are expected */ + case DATA_ABORT_VECTOR: + *saved_lr = (reg_t) __user_copy_msg_pointer_failure; + return; + default: + panic("Copy involving a user pointer failed unexpectedly!"); + } + } + } + + if (vector == DATA_ABORT_VECTOR) { + pagefault(saved_proc, saved_lr, is_nested, read_dfar(), read_dfsr()); + return; + } + + if (!is_nested && vector == PREFETCH_ABORT_VECTOR) { + reg_t ifar = read_ifar(), ifsr = read_ifsr(); + + /* The saved_lr is the instruction we're going to execute after + * the fault is handled; IFAR is the address that pagefaulted + * while fetching the instruction. As far as we know the two + * should be the same, if not this assumption will lead to very + * hard to debug problems (instruction executing being off by one) + * and this assumption needs re-examining, hence the assert. + */ + assert(*saved_lr == ifar); + pagefault(saved_proc, saved_lr, is_nested, ifar, ifsr); + return; + } + + /* If an exception occurs while running a process, the is_nested variable + * will be zero. Exceptions in interrupt handlers or system traps will make + * is_nested non-zero. + */ + if (is_nested == 0 && ! iskernelp(saved_proc)) { + cause_sig(proc_nr(saved_proc), ep->signum); + return; + } + + /* Exception in system code. This is not supposed to happen. */ + inkernel_disaster(saved_proc, saved_lr, ep, is_nested); + + panic("return from inkernel_disaster"); +} + +#if USE_SYSDEBUG +/*===========================================================================* + * proc_stacktrace_execute * + *===========================================================================*/ +static void proc_stacktrace_execute(struct proc *whichproc, reg_t v_bp, reg_t pc) +{ + printf("%-8.8s %6d 0x%lx \n", + whichproc->p_name, whichproc->p_endpoint, pc); +} +#endif + +void proc_stacktrace(struct proc *whichproc) +{ +#if USE_SYSDEBUG + proc_stacktrace_execute(whichproc, whichproc->p_reg.fp, whichproc->p_reg.pc); +#endif /* USE_SYSDEBUG */ +} + +void enable_fpu_exception(void) +{ +} + +void disable_fpu_exception(void) +{ +} diff --git a/minix/kernel/arch/earmv6hf/glo.h b/minix/kernel/arch/earmv6hf/glo.h new file mode 100644 index 000000000..d12da4259 --- /dev/null +++ b/minix/kernel/arch/earmv6hf/glo.h @@ -0,0 +1,9 @@ +#ifndef __GLO_ARM_H__ +#define __GLO_ARM_H__ + +#include "kernel/kernel.h" +#include "arch_proto.h" + +EXTERN struct tss_s tss[CONFIG_MAX_CPUS]; + +#endif /* __GLO_ARM_H__ */ diff --git a/minix/kernel/arch/earmv6hf/head.S b/minix/kernel/arch/earmv6hf/head.S new file mode 100644 index 000000000..03f9f97e0 --- /dev/null +++ b/minix/kernel/arch/earmv6hf/head.S @@ -0,0 +1,54 @@ +#include "kernel/kernel.h" /* configures the kernel */ + +/* sections */ + +#include +#include "kernel/kernel.h" +#include +#include +#include +#include +#include +#include "archconst.h" +#include "kernel/const.h" +#include "kernel/proc.h" +#include "sconst.h" +#include +#include + +#include "arch_proto.h" /* K_STACK_SIZE */ + +.text +/*===========================================================================*/ +/* MINIX */ +/*===========================================================================*/ +.global MINIX +MINIX: +/* this is the entry point for the MINIX kernel */ + b multiboot_init + +multiboot_init: + ldr sp, =load_stack_start /* make usable stack */ + mov fp, #0 + bl _C_LABEL(pre_init) + + /* Kernel is mapped high now and ready to go, with + * the boot info pointer returned by pre_init in r0. + * Set the highly mapped stack and initialize it. + * + * Afther that call kmain with r0 still pointing to boot info + */ + ldr sp, =k_initial_stktop + mov r1, #0 + push {r1} /* Terminate stack */ + ldr r2, =_C_LABEL(kmain) /* r0 holds kinfo_t ptr */ + bx r2 + + /* not reached */ +hang: + b hang + +.data +load_stack: + .space 4096 +load_stack_start: diff --git a/minix/kernel/arch/earmv6hf/hw_intr.c b/minix/kernel/arch/earmv6hf/hw_intr.c new file mode 100644 index 000000000..8e97a61f9 --- /dev/null +++ b/minix/kernel/arch/earmv6hf/hw_intr.c @@ -0,0 +1,16 @@ +/* hw_intr handles the hardware dependent part of the interrupts */ +#include "hw_intr.h" +#include "bsp_intr.h" + +int hw_intr_mask(int irq){ + bsp_irq_mask(irq); +} + +int hw_intr_unmask(int irq){ + bsp_irq_unmask(irq); +} + +int hw_intr_ack(int irq){}; +int hw_intr_used(int irq){}; +int hw_intr_not_used(int irq){}; +int hw_intr_disable_all(){}; diff --git a/minix/kernel/arch/earmv6hf/include/arch_clock.h b/minix/kernel/arch/earmv6hf/include/arch_clock.h new file mode 100644 index 000000000..21574aae5 --- /dev/null +++ b/minix/kernel/arch/earmv6hf/include/arch_clock.h @@ -0,0 +1,6 @@ +#ifndef __CLOCK_ARM_H__ +#define __CLOCK_ARM_H__ + +void arch_timer_int_handler(void); + +#endif /* __CLOCK_ARM_H__ */ diff --git a/minix/kernel/arch/earmv6hf/include/arch_proto.h b/minix/kernel/arch/earmv6hf/include/arch_proto.h new file mode 100644 index 000000000..2ec2ef16b --- /dev/null +++ b/minix/kernel/arch/earmv6hf/include/arch_proto.h @@ -0,0 +1,125 @@ + +#ifndef _ARM_PROTO_H +#define _ARM_PROTO_H + +#include + +#define K_STACK_SIZE ARM_PAGE_SIZE + + +#ifndef __ASSEMBLY__ + +#include "cpufunc.h" + +/* klib */ +__dead void reset(void); +phys_bytes vir2phys(void *); +vir_bytes phys_memset(phys_bytes ph, u32_t c, phys_bytes bytes); + +void __switch_address_space(struct proc *p, struct proc **__ptproc); +#define switch_address_space(proc) \ + __switch_address_space(proc, get_cpulocal_var_ptr(ptproc)) + +void __copy_msg_from_user_end(void); +void __copy_msg_to_user_end(void); +void __user_copy_msg_pointer_failure(void); + +/* multiboot.c */ +void multiboot_init(void); + +/* protect.c */ +struct tss_s { + reg_t sp0; /* stack pointer to use during interrupt */ +} __attribute__((packed)); +int tss_init(unsigned cpu, void * kernel_stack); + +void add_memmap(kinfo_t *cbi, u64_t addr, u64_t len); +phys_bytes alloc_lowest(kinfo_t *cbi, phys_bytes len); +void vm_enable_paging(void); +void cut_memmap(kinfo_t *cbi, phys_bytes start, phys_bytes end); +phys_bytes pg_roundup(phys_bytes b); +void pg_info(reg_t *, u32_t **); +void pg_clear(void); +void pg_identity(kinfo_t *); +phys_bytes pg_load(void); +void pg_map(phys_bytes phys, vir_bytes vaddr, vir_bytes vaddr_end, kinfo_t *cbi); +int pg_mapkernel(void); +void pg_mapproc(struct proc *p, struct boot_image *ip, kinfo_t *cbi); + +EXTERN void * k_stacks_start; +extern void * k_stacks; + +#define get_k_stack_top(cpu) ((void *)(((char*)(k_stacks)) \ + + 2 * ((cpu) + 1) * K_STACK_SIZE)) + + +/* + * Definition of a callback used when a memory map changed it's base address + */ +typedef int (*kern_phys_map_mapped)(vir_bytes id, vir_bytes new_addr ); + +/* + * struct used internally by memory.c to keep a list of + * items to map. These should be statically allocated + * in the individual files and passed as argument. + * The data doesn't need to be initialized. See omap_serial for + * and example usage. + */ +typedef struct kern_phys_map{ + phys_bytes addr; /* The physical address to map */ + vir_bytes size; /* The size of the mapping */ + vir_bytes id; /* an id passed to the callback */ + int vm_flags; /* flags to be passed to vm map */ + kern_phys_map_mapped cb; /* the callback itself */ + phys_bytes vir; /* The virtual address once remapped */ + int index; /* index */ + struct kern_phys_map *next; /* pointer to the next */ +} kern_phys_map ; + + +/* + * Request an in kernel physical mapping. + * + * On ARM many devices are memory mapped and some of these devices + * are used in the kernel. These device can be things like serial + * lines, interrupt controller and clocks. The kernel needs to be + * able to access these devices at the various stages of booting. + * During startup, until arch_enable_paging is called, it is the + * kernel whom is controlling the mappings and it often needs to + * access the memory using a 1:1 mapping between virtual and + * physical memory. + * + * Once processes start to run it is no longer desirable for the + * kernel to have devices mapped in the middle of the process + * address space. + * + * This method requests the memory manager to map base_address/size + * in the kernel address space and call back the kernel when this + * mapping takes effect (after enable_paging). + * + * Before the callback is called it is up to the kernel to use it's + * own addressing. The callback will happen *after* the kernel lost + * it's initial mapping. It it therefore not safe to use the initial + * mapping in the callback. It also is not possible to use printf for + * the same reason. + */ +int kern_req_phys_map( phys_bytes base_address, vir_bytes io_size, + int vm_flags, kern_phys_map * priv, + kern_phys_map_mapped cb, vir_bytes id); + +/* + * Request a physical mapping and put the result in the given prt + * Note that ptr will only be valid once the callback happened. + */ +int kern_phys_map_ptr( phys_bytes base_address, vir_bytes io_size, + int vm_flags, kern_phys_map * priv, + vir_bytes ptr); + +void arch_ser_init(); + +/* functions defined in architecture-independent kernel source. */ +#include "kernel/proto.h" + +#endif /* __ASSEMBLY__ */ + +#endif diff --git a/minix/kernel/arch/earmv6hf/include/arch_watchdog.h b/minix/kernel/arch/earmv6hf/include/arch_watchdog.h new file mode 100644 index 000000000..2e6f73346 --- /dev/null +++ b/minix/kernel/arch/earmv6hf/include/arch_watchdog.h @@ -0,0 +1,6 @@ +#ifndef __ARM_WATCHDOG_H__ +#define __ARM_WATCHDOG_H__ + +#include "kernel/kernel.h" + +#endif /* __ARM_WATCHDOG_H__ */ diff --git a/minix/kernel/arch/earmv6hf/include/archconst.h b/minix/kernel/arch/earmv6hf/include/archconst.h new file mode 100644 index 000000000..8d2edf967 --- /dev/null +++ b/minix/kernel/arch/earmv6hf/include/archconst.h @@ -0,0 +1,41 @@ + +#ifndef _ARM_ACONST_H +#define _ARM_ACONST_H + +#include +#include +#include +#include + +/* Program stack words and masks. */ +#define INIT_PSR (PSR_USR32_MODE | PSR_F) /* initial psr */ +#define INIT_TASK_PSR (PSR_SVC32_MODE | PSR_F) /* initial psr for tasks */ + +/* Exception vector numbers */ +#define RESET_VECTOR 0 +#define UNDEFINED_INST_VECTOR 1 +#define SUPERVISOR_CALL_VECTOR 2 +#define PREFETCH_ABORT_VECTOR 3 +#define DATA_ABORT_VECTOR 4 +#define HYPERVISOR_CALL_VECTOR 5 +#define INTERRUPT_VECTOR 6 +#define FAST_INTERRUPT_VECTOR 7 + +/* + * defines how many bytes are reserved at the top of the kernel stack for global + * information like currently scheduled process or current cpu id + */ +#define ARM_STACK_TOP_RESERVED (2 * sizeof(reg_t)) + +/* only selected bits are changeable by user e.g.[31:9] and skip the + * mode bits. It is probably is a better idea to look at the current + * status to determine if one is allowed to write these values. This + * might allow debugging of privileged processes + */ +#define SET_USR_PSR(rp, npsr) \ + rp->p_reg.psr = ( rp->p_reg.psr & 0x1F) | ( npsr & ~0x1F) + + +#define PG_ALLOCATEME ((phys_bytes)-1) + +#endif /* _ARM_ACONST_H */ diff --git a/minix/kernel/arch/earmv6hf/include/ccnt.h b/minix/kernel/arch/earmv6hf/include/ccnt.h new file mode 100644 index 000000000..a05568c1d --- /dev/null +++ b/minix/kernel/arch/earmv6hf/include/ccnt.h @@ -0,0 +1,22 @@ +#ifndef _CCNT_H +#define _CCNT_H + +/* ARMV7 PMU (performance monitors) */ +/* ARM ARM B4.1.116 */ +#define PMU_PMCNTENSET_C (1 << 31) /* Enable PMCCNTR cycle counter */ + +/* ARM ARM B4.1.117 PMCR */ +#define PMU_PMCR_DP (1 << 5) /* Disable when ev. cnt. prohibited */ +#define PMU_PMCR_X (1 << 4) /* Export enable */ +#define PMU_PMCR_D (1 << 3) /* Clock divider */ +#define PMU_PMCR_C (1 << 2) /* Cycle counter reset */ +#define PMU_PMCR_P (1 << 1) /* Event counter reset */ +#define PMU_PMCR_E (1 << 0) /* Enable event counters */ + +/* ARM ARM B4.1.119 PMINTENSET */ +#define PMU_PMINTENSET_C (1 << 31) /* PMCCNTR overflow int req. enable*/ + +/* ARM ARM B4.1.124 PMUSERENR */ +#define PMU_PMUSERENR_EN (1 << 0) /* User mode access enable bit */ + +#endif /* _CCNT_H */ diff --git a/minix/kernel/arch/earmv6hf/include/cpufunc.h b/minix/kernel/arch/earmv6hf/include/cpufunc.h new file mode 100644 index 000000000..c5606dbe4 --- /dev/null +++ b/minix/kernel/arch/earmv6hf/include/cpufunc.h @@ -0,0 +1,463 @@ +#ifndef _ARM_CPUFUNC_H +#define _ARM_CPUFUNC_H + +#if 0 +/* check interrupt state */ +static inline void check_int(unsigned int state, int line) +{ + unsigned int cpsr = 0; + + asm volatile("mrs %0, cpsr" : "=r" (cpsr)); + + if ((cpsr & PSR_F) != (state & PSR_F)) + printf("%d: FIQs are unexpectedly %s\n", line, (cpsr & PSR_F) ? "MASKED" : "UNMASKED"); + + if ((cpsr & PSR_I) != (state & PSR_I)) + printf("%d: IRQs are unexpectedly %s\n", line, (cpsr & PSR_I) ? "MASKED" : "UNMASKED"); + +} +#endif + +/* Data memory barrier */ +static inline void dmb(void) +{ + asm volatile("dmb" : : : "memory"); +} + +/* Data synchronization barrier */ +static inline void dsb(void) +{ + asm volatile("dsb" : : : "memory"); +} + +/* Instruction synchronization barrier */ +static inline void isb(void) +{ + asm volatile("isb" : : : "memory"); +} + +static inline void barrier(void) +{ + dsb(); + isb(); +} + + +/* Read CLIDR, Cache Level ID Register */ +static inline u32_t read_clidr(){ + u32_t clidr; + asm volatile("mrc p15, 1, %[clidr], c0, c0 , 1 @ READ CLIDR\n\t" + : [clidr] "=r" (clidr)); + return clidr; +} + + +/* Read CSSELR, Cache Size Selection Register */ +static inline u32_t read_csselr(){ + u32_t csselr; + asm volatile("mrc p15, 2, %[csselr], c0, c0 , 0 @ READ CSSELR\n\t" + : [csselr] "=r" (csselr)); + return csselr; +} + +/* Write CSSELR, Cache Size Selection Register */ +static inline void write_csselr(u32_t csselr){ + asm volatile("mcr p15, 2, %[csselr], c0, c0 , 0 @ WRITE CSSELR\n\t" + : : [csselr] "r" (csselr)); +} + +/* Read Cache Size ID Register */ +static inline u32_t read_ccsidr() +{ + u32_t ccsidr; + asm volatile("mrc p15, 1, %[ccsidr], c0, c0, 0 @ Read CCSIDR\n\t" + : [ccsidr] "=r" (ccsidr)); + return ccsidr; +} + +/* Read TLBTR, TLB Type Register */ +static inline u32_t read_tlbtr() +{ + u32_t tlbtr; + asm volatile("mrc p15, 0, %[tlbtr], c0, c0, 3 @ Read TLBTR\n\t" + : [tlbtr] "=r" (tlbtr)); + return tlbtr; +} + +/* keesj:move these out */ +static inline u32_t ilog2(u32_t t) +{ + u32_t counter =0; + while( (t = t >> 1) ) counter ++; + return counter; +} + +/* keesj:move these out */ +static inline u32_t ipow2(u32_t t) +{ + return 1 << t; +} + +/* + * type = 1 == CLEAN + * type = 2 == INVALIDATE + */ +static inline void dcache_maint(int type){ + u32_t cache_level ; + u32_t clidr; + u32_t ctype; + u32_t ccsidr; + u32_t line_size,line_length; + u32_t number_of_sets,number_of_ways; + u32_t set,way; + + clidr = read_clidr(); + u32_t loc = ( clidr >> 24) & 0x7; + u32_t louu = ( clidr >> 27) & 0x7; + u32_t louis = ( clidr >> 21) & 0x7; + for (cache_level =0 ; cache_level < loc; cache_level++){ + /* get current cache type */ + ctype = ( clidr >> cache_level*3) & 0x7; + /* select data or unified or cache level */ + write_csselr(cache_level << 1); + isb(); + ccsidr = read_ccsidr(); + line_size = ccsidr & 0x7; + line_length = 2 << (line_size + 1) ; /* 2**(line_size + 2) */ + number_of_sets = ((ccsidr >> 13) & 0x7fff) + 1; + number_of_ways = ((ccsidr >> 3) & 0x3ff) + 1; + + u32_t way_bits = ilog2(number_of_ways); + if(ipow2(ilog2(number_of_ways) < number_of_ways) ) { + way_bits++; + } + + u32_t l = ilog2(line_length); + for (way =0 ; way < number_of_ways; way++) { + for (set =0 ; set < number_of_sets; set++) { + u32_t val = ( way << (32 - way_bits) ) | (set << l) | (cache_level << 1 ); + if (type == 1) { + /* DCCISW, Data Cache Clean and Invalidate by Set/Way */ + asm volatile("mcr p15, 0, %[set], c7, c14, 2 @ DCCISW" + : : [set] "r" (val)); + } else if (type ==2 ){ + /* DCISW, Data Cache Invalidate by Set/Way */ + asm volatile("mcr p15, 0, %[set], c7, c6, 2" + : : [set] "r" (val)); + } + } + } + } + dsb(); + isb(); + +} +static inline void dcache_clean(){ + dcache_maint(1); +} +static inline void dcache_invalidate (){ + dcache_maint(2); +} + +static inline void refresh_tlb(void) +{ + dsb(); + + /* Invalidate entire unified TLB */ + asm volatile("mcr p15, 0, %[zero], c8, c7, 0 @ TLBIALL\n\t" : : [zero] "r" (0)); + +#if 0 + /* Invalidate entire data TLB */ + asm volatile("mcr p15, 0, %[zero], c8, c6, 0" : : [zero] "r" (0)); + + /* Invalidate entire instruction TLB */ + asm volatile("mcr p15, 0, %[zero], c8, c5, 0" : : [zero] "r" (0)); +#endif + + /* + * Invalidate all instruction caches to PoU. + * Also flushes branch target cache. + */ + asm volatile("mcr p15, 0, %[zero], c7, c5, 0" : : [zero] "r" (0)); + + /* Invalidate entire branch predictor array */ + asm volatile("mcr p15, 0, %[zero], c7, c5, 6" : : [zero] "r" (0)); /* flush BTB */ + + dsb(); + isb(); +} + + +/* Read System Control Register */ +static inline u32_t read_sctlr() +{ + u32_t ctl; + + asm volatile("mrc p15, 0, %[ctl], c1, c0, 0 @ Read SCTLR\n\t" + : [ctl] "=r" (ctl)); + + return ctl; +} + +/* Write System Control Register */ +static inline void write_sctlr(u32_t ctl) +{ + asm volatile("mcr p15, 0, %[ctl], c1, c0, 0 @ Write SCTLR\n\t" + : : [ctl] "r" (ctl)); + isb(); +} + +/* Read Translation Table Base Register 0 */ +static inline u32_t read_ttbr0() +{ + u32_t bar; + + asm volatile("mrc p15, 0, %[bar], c2, c0, 0 @ Read TTBR0\n\t" + : [bar] "=r" (bar)); + + return bar & ARM_TTBR_ADDR_MASK; +} + +/* Write Translation Table Base Register 0 */ +static inline void write_ttbr0(u32_t bar) +{ + barrier(); + /* In our setup TTBR contains the base address *and* the flags + but other pieces of the kernel code expect ttbr to be the + base address of the l1 page table. We therefore add the + flags here and remove them in the read_ttbr0 */ + u32_t v = (bar & ARM_TTBR_ADDR_MASK ) | ARM_TTBR_FLAGS_CACHED; + asm volatile("mcr p15, 0, %[bar], c2, c0, 0 @ Write TTBR0\n\t" + : : [bar] "r" (v)); + + refresh_tlb(); +} + +/* Reload Translation Table Base Register 0 */ +static inline void reload_ttbr0(void) +{ + reg_t ttbr = read_ttbr0(); + write_ttbr0(ttbr); +} + +/* Read Translation Table Base Register 1 */ +static inline u32_t read_ttbr1() +{ + u32_t bar; + + asm volatile("mrc p15, 0, %[bar], c2, c0, 1 @ Read TTBR1\n\t" + : [bar] "=r" (bar)); + + return bar; +} + +/* Write Translation Table Base Register 1 */ +static inline void write_ttbr1(u32_t bar) +{ + barrier(); + + asm volatile("mcr p15, 0, %[bar], c2, c0, 1 @ Write TTBR1\n\t" + : : [bar] "r" (bar)); + + refresh_tlb(); +} + +/* Reload Translation Table Base Register 1 */ +static inline void reload_ttbr1(void) +{ + reg_t ttbr = read_ttbr1(); + + write_ttbr1(ttbr); +} + +/* Read Translation Table Base Control Register */ +static inline u32_t read_ttbcr() +{ + u32_t bcr; + + asm volatile("mrc p15, 0, %[bcr], c2, c0, 2 @ Read TTBCR\n\t" + : [bcr] "=r" (bcr)); + + return bcr; +} + +/* Write Translation Table Base Control Register */ +static inline void write_ttbcr(u32_t bcr) +{ + asm volatile("mcr p15, 0, %[bcr], c2, c0, 2 @ Write TTBCR\n\t" + : : [bcr] "r" (bcr)); + + isb(); +} + +/* Read Domain Access Control Register */ +static inline u32_t read_dacr() +{ + u32_t dacr; + + asm volatile("mrc p15, 0, %[dacr], c3, c0, 0 @ Read DACR\n\t" + : [dacr] "=r" (dacr)); + + return dacr; +} + +/* Write Domain Access Control Register */ +static inline void write_dacr(u32_t dacr) +{ + asm volatile("mcr p15, 0, %[dacr], c3, c0, 0 @ Write DACR\n\t" + : : [dacr] "r" (dacr)); + + isb(); +} + +/* Read Data Fault Status Register */ +static inline u32_t read_dfsr() +{ + u32_t fsr; + + asm volatile("mrc p15, 0, %[fsr], c5, c0, 0 @ Read DFSR\n\t" + : [fsr] "=r" (fsr)); + + return fsr; +} + +/* Write Data Fault Status Register */ +static inline void write_dfsr(u32_t fsr) +{ + asm volatile("mcr p15, 0, %[fsr], c5, c0, 0 @ Write DFSR\n\t" + : : [fsr] "r" (fsr)); + + isb(); +} + +/* Read Instruction Fault Status Register */ +static inline u32_t read_ifsr() +{ + u32_t fsr; + + asm volatile("mrc p15, 0, %[fsr], c5, c0, 1 @ Read IFSR\n\t" + : [fsr] "=r" (fsr)); + + return fsr; +} + +/* Write Instruction Fault Status Register */ +static inline void write_ifsr(u32_t fsr) +{ + asm volatile("mcr p15, 0, %[fsr], c5, c0, 1 @ Write IFSR\n\t" + : : [fsr] "r" (fsr)); + + isb(); +} + +/* Read Data Fault Address Register */ +static inline u32_t read_dfar() +{ + u32_t far; + + asm volatile("mrc p15, 0, %[far], c6, c0, 0 @ Read DFAR\n\t" + : [far] "=r" (far)); + + return far; +} + +/* Write Data Fault Address Register */ +static inline void write_dfar(u32_t far) +{ + asm volatile("mcr p15, 0, %[far], c6, c0, 0 @ Write DFAR\n\t" + : : [far] "r" (far)); + + isb(); +} + +/* Read Instruction Fault Address Register */ +static inline u32_t read_ifar() +{ + u32_t far; + + asm volatile("mrc p15, 0, %[far], c6, c0, 2 @ Read IFAR\n\t" + : [far] "=r" (far)); + + return far; +} + +/* Write Instruction Fault Address Register */ +static inline void write_ifar(u32_t far) +{ + asm volatile("mcr p15, 0, %[far], c6, c0, 2 @ Write IFAR\n\t" + : : [far] "r" (far)); + + isb(); +} + +/* Read Vector Base Address Register */ +static inline u32_t read_vbar() +{ + u32_t vbar; + + asm volatile("mrc p15, 0, %[vbar], c12, c0, 0 @ Read VBAR\n\t" + : [vbar] "=r" (vbar)); + + return vbar; +} + +/* Write Vector Base Address Register */ +static inline void write_vbar(u32_t vbar) +{ + asm volatile("mcr p15, 0, %[vbar], c12, c0, 0 @ Write VBAR\n\t" + : : [vbar] "r" (vbar)); + + isb(); +} + +/* Read the Main ID Register */ +static inline u32_t read_midr() +{ + u32_t id; + + asm volatile("mrc p15, 0, %[id], c0, c0, 0 @ read MIDR\n\t" + : [id] "=r" (id)); + + return id; +} + +/* Read Auxiliary Control Register */ +static inline u32_t read_actlr() +{ + u32_t ctl; + + asm volatile("mrc p15, 0, %[ctl], c1, c0, 1 @ Read ACTLR\n\t" + : [ctl] "=r" (ctl)); + + return ctl; +} + +/* Write Auxiliary Control Register */ +static inline void write_actlr(u32_t ctl) +{ +//http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0344k/Babjbjbb.html + asm volatile("mcr p15, 0, %[ctl], c1, c0, 1 @ Write ACTLR\n\t" + : : [ctl] "r" (ctl)); + + isb(); +} + +/* Read Current Program Status Register */ +static inline u32_t read_cpsr() +{ + u32_t status; + + asm volatile("mrs %[status], cpsr @ read CPSR" + : [status] "=r" (status)); + + return status; +} + +/* Write Current Program Status Register */ +static inline void write_cpsr(u32_t status) +{ + asm volatile("msr cpsr_c, %[status] @ write CPSR" + : : [status] "r" (status)); +} + +#endif /* _ARM_CPUFUNC_H */ diff --git a/minix/kernel/arch/earmv6hf/include/direct_utils.h b/minix/kernel/arch/earmv6hf/include/direct_utils.h new file mode 100644 index 000000000..5b7943d74 --- /dev/null +++ b/minix/kernel/arch/earmv6hf/include/direct_utils.h @@ -0,0 +1,11 @@ +#ifndef MB_UTILS_H +#define MB_UTILS_H + +#include "kernel/kernel.h" + +void direct_cls(void); +void direct_print(const char*); +void direct_print_char(char); +int direct_read_char(unsigned char*); + +#endif diff --git a/minix/kernel/arch/earmv6hf/include/hw_intr.h b/minix/kernel/arch/earmv6hf/include/hw_intr.h new file mode 100644 index 000000000..f9eabc72f --- /dev/null +++ b/minix/kernel/arch/earmv6hf/include/hw_intr.h @@ -0,0 +1,15 @@ +#ifndef __HW_INTR_ARM_H__ +#define __HW_INTR_ARM_H__ + + +#include "kernel/kernel.h" +void irq_handle(int irq); + +int hw_intr_mask(int irq); +int hw_intr_unmask(int irq); +int hw_intr_ack(int irq); +int hw_intr_used(int irq); +int hw_intr_not_used(int irq); +int hw_intr_disable_all(); + +#endif /* __HW_INTR_ARM_H__ */ diff --git a/minix/kernel/arch/earmv6hf/include/io.h b/minix/kernel/arch/earmv6hf/include/io.h new file mode 100644 index 000000000..7678148e3 --- /dev/null +++ b/minix/kernel/arch/earmv6hf/include/io.h @@ -0,0 +1,16 @@ +#ifndef _ARM_IO_H_ +#define _ARM_IO_H_ + +#ifndef __ASSEMBLY__ + +#include + +/* Access memory-mapped I/O devices */ +#define mmio_read(a) (*(volatile u32_t *)(a)) +#define mmio_write(a,v) (*(volatile u32_t *)(a) = (v)) +#define mmio_set(a,v) mmio_write((a), mmio_read((a)) | (v)) +#define mmio_clear(a,v) mmio_write((a), mmio_read((a)) & ~(v)) + +#endif /* __ASSEMBLY__ */ + +#endif /* _ARM_IO_H_ */ diff --git a/minix/kernel/arch/earmv6hf/kernel.lds b/minix/kernel/arch/earmv6hf/kernel.lds new file mode 100644 index 000000000..b41fcad29 --- /dev/null +++ b/minix/kernel/arch/earmv6hf/kernel.lds @@ -0,0 +1,50 @@ +OUTPUT_ARCH("arm") +ENTRY(__k_unpaged_MINIX) + +_kern_phys_base = 0x80200000; /* phys 4MB aligned for convenient remapping */ +_kern_vir_base = 0xF0400000; /* map kernel high for max. user vir space */ +_kern_offset = (_kern_vir_base - _kern_phys_base); + +__k_unpaged__kern_offset = _kern_offset; +__k_unpaged__kern_vir_base = _kern_vir_base; +__k_unpaged__kern_phys_base = _kern_phys_base; + +SECTIONS +{ + . = _kern_phys_base; + __k_unpaged__kern_unpaged_start = .; + + .unpaged_text ALIGN(4096) : { unpaged_*.o(.text) } + .unpaged_data ALIGN(4096) : { unpaged_*.o(.data .rodata*) } + __k_unpaged__kern_unpaged_edata = .; + + .unpaged_bss ALIGN(4096) : { unpaged_*.o(.bss COMMON) } + __k_unpaged__kern_unpaged_end = .; + + . += _kern_offset; + + . = ALIGN(4096); usermapped_start = .; + .usermapped_glo : AT(ADDR(.usermapped_glo) - _kern_offset) { *(.usermapped_glo) } + . = ALIGN(4096); usermapped_nonglo_start = .; + .usermapped : AT(ADDR(.usermapped) - _kern_offset) { *(.usermapped) } + . = ALIGN(4096); usermapped_end = .; + .text : AT(ADDR(.text) - _kern_offset) { *(.text*) } + _etext = .; + .data ALIGN(4096) : AT(ADDR(.data) - _kern_offset) { *(.data .rodata* ) } + . = ALIGN(4096); + _edata = .; + __k_unpaged__edata = . - _kern_offset; + .bss ALIGN(4096) : AT(ADDR(.bss) - _kern_offset) { *(.bss* COMMON) + __k_unpaged__kern_size = . - _kern_vir_base; + _kern_size = __k_unpaged__kern_size; + + . += 4096; + } + _end = .; + __k_unpaged__end = . - _kern_offset; + + /DISCARD/ : + { + *(.ARM.exidx*) + } +} diff --git a/minix/kernel/arch/earmv6hf/klib.S b/minix/kernel/arch/earmv6hf/klib.S new file mode 100644 index 000000000..60b5046e3 --- /dev/null +++ b/minix/kernel/arch/earmv6hf/klib.S @@ -0,0 +1,107 @@ +/* sections */ + + +#include +#include +#include +#include +#include +#include "archconst.h" +#include "kernel/const.h" +#include "sconst.h" +#include + + +/*===========================================================================*/ +/* copy_msg_from_user */ +/*===========================================================================*/ +/* + * int copy_msg_from_user(message * user_mbuf, message * dst); + * + * Copies a message of 64 bytes from user process space to a kernel buffer. This + * function assumes that the process address space is installed (ttbr loaded). + * + * This function from the callers point of view either succeeds or returns an + * error which gives the caller a chance to respond accordingly. In fact it + * either succeeds or if it generates a pagefault, general protection or other + * exception, the trap handler has to redirect the execution to + * __user_copy_msg_pointer_failure where the error is reported to the caller + * without resolving the pagefault. It is not kernel's problem to deal with + * wrong pointers from userspace and the caller should return an error to + * userspace as if wrong values or request were passed to the kernel + */ +ENTRY(copy_msg_from_user) + push {r4-r10, lr} + /* load the source pointer */ + mov r9, r0 + /* load the destination pointer */ + mov r10, r1 + /* do the copy, first 32 bytes */ + ldm r9, {r0-r7} + stm r10, {r0-r7} + + /* next 32 bytes */ + add r9, r9, #32 + add r10, r10, #32 + ldm r9, {r0-r7} + stm r10, {r0-r7} + +LABEL(__copy_msg_from_user_end) + pop {r4-r10, lr} + mov r0, #0 + bx lr + +/*===========================================================================*/ +/* copy_msg_to_user */ +/*===========================================================================*/ +/* + * void copy_msg_to_user(message * src, message * user_mbuf); + * + * Copies a message of 64 bytes to user process space from a kernel buffer. + * + * All the other copy_msg_from_user() comments apply here as well! + */ +ENTRY(copy_msg_to_user) + push {r4-r10, lr} + /* load the source pointer */ + mov r9, r0 + /* load the destination pointer */ + mov r10, r1 + /* do the copy, first 32 bytes */ + ldm r9, {r0-r7} + stm r10, {r0-r7} + + /* next 32 bytes */ + add r9, r9, #32 + add r10, r10, #32 + ldm r9, {r0-r7} + stm r10, {r0-r7} + +LABEL(__copy_msg_to_user_end) + pop {r4-r10, lr} + mov r0, #0 + bx lr + +/* + * if a function from a selected set of copies from or to userspace fails, it is + * because of a wrong pointer supplied by the userspace. We have to clean up and + * and return -1 to indicated that something wrong has happend. The place it was + * called from has to handle this situation. The exception handler redirect us + * here to continue, clean up and report the error + */ +ENTRY(__user_copy_msg_pointer_failure) + pop {r4-r10, lr} + mov r0, #-1 + bx lr + +ENTRY(intr_enable) +ENTRY(interrupts_enable) + dsb + cpsie if + bx lr + +ENTRY(intr_disable) +ENTRY(interrupts_disable) + dsb + cpsid if + bx lr diff --git a/minix/kernel/arch/earmv6hf/memory.c b/minix/kernel/arch/earmv6hf/memory.c new file mode 100644 index 000000000..e8648897c --- /dev/null +++ b/minix/kernel/arch/earmv6hf/memory.c @@ -0,0 +1,899 @@ + +#include "kernel/kernel.h" +#include "kernel/proc.h" +#include "kernel/vm.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "arch_proto.h" +#include "kernel/proto.h" +#include "kernel/debug.h" +#include "bsp_timer.h" + + +#define HASPT(procptr) ((procptr)->p_seg.p_ttbr != 0) +static int nfreepdes = 0; +#define MAXFREEPDES 2 +static int freepdes[MAXFREEPDES]; + +static u32_t phys_get32(phys_bytes v); + +/* list of requested physical mapping */ +static kern_phys_map *kern_phys_map_head; + +void mem_clear_mapcache(void) +{ + int i; + for(i = 0; i < nfreepdes; i++) { + struct proc *ptproc = get_cpulocal_var(ptproc); + int pde = freepdes[i]; + u32_t *ptv; + assert(ptproc); + ptv = ptproc->p_seg.p_ttbr_v; + assert(ptv); + ptv[pde] = 0; + } +} + +/* This function sets up a mapping from within the kernel's address + * space to any other area of memory, either straight physical + * memory (pr == NULL) or a process view of memory, in 1MB windows. + * I.e., it maps in 1MB chunks of virtual (or physical) address space + * to 1MB chunks of kernel virtual address space. + * + * It recognizes pr already being in memory as a special case (no + * mapping required). + * + * The target (i.e. in-kernel) mapping area is one of the freepdes[] + * VM has earlier already told the kernel about that is available. It is + * identified as the 'pde' parameter. This value can be chosen freely + * by the caller, as long as it is in range (i.e. 0 or higher and corresponds + * to a known freepde slot). It is up to the caller to keep track of which + * freepde's are in use, and to determine which ones are free to use. + * + * The logical number supplied by the caller is translated into an actual + * pde number to be used, and a pointer to it (linear address) is returned + * for actual use by phys_copy or memset. + */ +static phys_bytes createpde( + const struct proc *pr, /* Requested process, NULL for physical. */ + const phys_bytes linaddr,/* Address after segment translation. */ + phys_bytes *bytes, /* Size of chunk, function may truncate it. */ + int free_pde_idx, /* index of the free slot to use */ + int *changed /* If mapping is made, this is set to 1. */ + ) +{ + u32_t pdeval; + phys_bytes offset; + int pde; + + assert(free_pde_idx >= 0 && free_pde_idx < nfreepdes); + pde = freepdes[free_pde_idx]; + assert(pde >= 0 && pde < 4096); + + if(pr && ((pr == get_cpulocal_var(ptproc)) || iskernelp(pr))) { + /* Process memory is requested, and + * it's a process that is already in current page table, or + * the kernel, which is always there. + * Therefore linaddr is valid directly, with the requested + * size. + */ + return linaddr; + } + + if(pr) { + /* Requested address is in a process that is not currently + * accessible directly. Grab the PDE entry of that process' + * page table that corresponds to the requested address. + */ + assert(pr->p_seg.p_ttbr_v); + pdeval = pr->p_seg.p_ttbr_v[ARM_VM_PDE(linaddr)]; + } else { + /* Requested address is physical. Make up the PDE entry. */ + assert (linaddr >= PHYS_MEM_BEGIN && linaddr <= PHYS_MEM_END); + + /* memory */ + pdeval = (linaddr & ARM_VM_SECTION_MASK) + | ARM_VM_SECTION + | ARM_VM_SECTION_DOMAIN + | ARM_VM_SECTION_CACHED + | ARM_VM_SECTION_USER; + } + + /* Write the pde value that we need into a pde that the kernel + * can access, into the currently loaded page table so it becomes + * visible. + */ + assert(get_cpulocal_var(ptproc)->p_seg.p_ttbr_v); + if(get_cpulocal_var(ptproc)->p_seg.p_ttbr_v[pde] != pdeval) { + get_cpulocal_var(ptproc)->p_seg.p_ttbr_v[pde] = pdeval; + *changed = 1; + } + + /* Memory is now available, but only the 1MB window of virtual + * address space that we have mapped; calculate how much of + * the requested range is visible and return that in *bytes, + * if that is less than the requested range. + */ + offset = linaddr & ARM_VM_OFFSET_MASK_1MB; /* Offset in 1MB window. */ + *bytes = MIN(*bytes, ARM_SECTION_SIZE - offset); + + /* Return the linear address of the start of the new mapping. */ + return ARM_SECTION_SIZE*pde + offset; +} + + +/*===========================================================================* + * check_resumed_caller * + *===========================================================================*/ +static int check_resumed_caller(struct proc *caller) +{ + /* Returns the result from VM if caller was resumed, otherwise OK. */ + if (caller && (caller->p_misc_flags & MF_KCALL_RESUME)) { + assert(caller->p_vmrequest.vmresult != VMSUSPEND); + return caller->p_vmrequest.vmresult; + } + + return OK; +} + +/*===========================================================================* + * lin_lin_copy * + *===========================================================================*/ +static int lin_lin_copy(struct proc *srcproc, vir_bytes srclinaddr, + struct proc *dstproc, vir_bytes dstlinaddr, vir_bytes bytes) +{ + u32_t addr; + proc_nr_t procslot; + + assert(get_cpulocal_var(ptproc)); + assert(get_cpulocal_var(proc_ptr)); + assert(read_ttbr0() == get_cpulocal_var(ptproc)->p_seg.p_ttbr); + + procslot = get_cpulocal_var(ptproc)->p_nr; + + assert(procslot >= 0 && procslot < ARM_VM_DIR_ENTRIES); + + if(srcproc) assert(!RTS_ISSET(srcproc, RTS_SLOT_FREE)); + if(dstproc) assert(!RTS_ISSET(dstproc, RTS_SLOT_FREE)); + assert(!RTS_ISSET(get_cpulocal_var(ptproc), RTS_SLOT_FREE)); + assert(get_cpulocal_var(ptproc)->p_seg.p_ttbr_v); + if(srcproc) assert(!RTS_ISSET(srcproc, RTS_VMINHIBIT)); + if(dstproc) assert(!RTS_ISSET(dstproc, RTS_VMINHIBIT)); + + while(bytes > 0) { + phys_bytes srcptr, dstptr; + vir_bytes chunk = bytes; + int changed = 0; + +#ifdef CONFIG_SMP + unsigned cpu = cpuid; + + if (srcproc && GET_BIT(srcproc->p_stale_tlb, cpu)) { + changed = 1; + UNSET_BIT(srcproc->p_stale_tlb, cpu); + } + if (dstproc && GET_BIT(dstproc->p_stale_tlb, cpu)) { + changed = 1; + UNSET_BIT(dstproc->p_stale_tlb, cpu); + } +#endif + + /* Set up 1MB ranges. */ + srcptr = createpde(srcproc, srclinaddr, &chunk, 0, &changed); + dstptr = createpde(dstproc, dstlinaddr, &chunk, 1, &changed); + if(changed) { + reload_ttbr0(); + } + /* Copy pages. */ + PHYS_COPY_CATCH(srcptr, dstptr, chunk, addr); + + if(addr) { + /* If addr is nonzero, a page fault was caught. + * + * phys_copy does all memory accesses word-aligned (rounded + * down), so pagefaults can occur at a lower address than + * the specified offsets. compute the lower bounds for sanity + * check use. + */ + vir_bytes src_aligned = srcptr & ~0x3, dst_aligned = dstptr & ~0x3; + + if(addr >= src_aligned && addr < (srcptr + chunk)) { + return EFAULT_SRC; + } + if(addr >= dst_aligned && addr < (dstptr + chunk)) { + return EFAULT_DST; + } + + panic("lin_lin_copy fault out of range"); + + /* Not reached. */ + return EFAULT; + } + + /* Update counter and addresses for next iteration, if any. */ + bytes -= chunk; + srclinaddr += chunk; + dstlinaddr += chunk; + } + + if(srcproc) assert(!RTS_ISSET(srcproc, RTS_SLOT_FREE)); + if(dstproc) assert(!RTS_ISSET(dstproc, RTS_SLOT_FREE)); + assert(!RTS_ISSET(get_cpulocal_var(ptproc), RTS_SLOT_FREE)); + assert(get_cpulocal_var(ptproc)->p_seg.p_ttbr_v); + + return OK; +} + +static u32_t phys_get32(phys_bytes addr) +{ + u32_t v; + int r; + + if((r=lin_lin_copy(NULL, addr, + proc_addr(SYSTEM), (phys_bytes) &v, sizeof(v))) != OK) { + panic("lin_lin_copy for phys_get32 failed: %d", r); + } + + return v; +} + +/*===========================================================================* + * umap_virtual * + *===========================================================================*/ +phys_bytes umap_virtual(rp, seg, vir_addr, bytes) +register struct proc *rp; /* pointer to proc table entry for process */ +int seg; /* T, D, or S segment */ +vir_bytes vir_addr; /* virtual address in bytes within the seg */ +vir_bytes bytes; /* # of bytes to be copied */ +{ + phys_bytes phys = 0; + + if(vm_lookup(rp, vir_addr, &phys, NULL) != OK) { + printf("SYSTEM:umap_virtual: vm_lookup of %s: seg 0x%x: 0x%lx failed\n", rp->p_name, seg, vir_addr); + phys = 0; + } else { + if(phys == 0) + panic("vm_lookup returned phys: 0x%lx", phys); + } + + if(phys == 0) { + printf("SYSTEM:umap_virtual: lookup failed\n"); + return 0; + } + + /* Now make sure addresses are contiguous in physical memory + * so that the umap makes sense. + */ + if(bytes > 0 && vm_lookup_range(rp, vir_addr, NULL, bytes) != bytes) { + printf("umap_virtual: %s: %lu at 0x%lx (vir 0x%lx) not contiguous\n", + rp->p_name, bytes, vir_addr, vir_addr); + return 0; + } + + /* phys must be larger than 0 (or the caller will think the call + * failed), and address must not cross a page boundary. + */ + assert(phys); + + return phys; +} + + +/*===========================================================================* + * vm_lookup * + *===========================================================================*/ +int vm_lookup(const struct proc *proc, const vir_bytes virtual, + phys_bytes *physical, u32_t *ptent) +{ + u32_t *root, *pt; + int pde, pte; + u32_t pde_v, pte_v; + + assert(proc); + assert(physical); + assert(!isemptyp(proc)); + assert(HASPT(proc)); + + /* Retrieve page directory entry. */ + root = (u32_t *) (proc->p_seg.p_ttbr & ARM_TTBR_ADDR_MASK); + assert(!((u32_t) root % ARM_PAGEDIR_SIZE)); + pde = ARM_VM_PDE(virtual); + assert(pde >= 0 && pde < ARM_VM_DIR_ENTRIES); + pde_v = phys_get32((u32_t) (root + pde)); + + if(! ((pde_v & ARM_VM_PDE_PRESENT) + || (pde_v & ARM_VM_SECTION_PRESENT) + )) { + return EFAULT; + } + + if(pde_v & ARM_VM_SECTION) { + *physical = pde_v & ARM_VM_SECTION_MASK; + if(ptent) *ptent = pde_v; + *physical += virtual & ARM_VM_OFFSET_MASK_1MB; + } else { + /* Retrieve page table entry. */ + pt = (u32_t *) (pde_v & ARM_VM_PDE_MASK); + assert(!((u32_t) pt % ARM_PAGETABLE_SIZE)); + pte = ARM_VM_PTE(virtual); + assert(pte >= 0 && pte < ARM_VM_PT_ENTRIES); + pte_v = phys_get32((u32_t) (pt + pte)); + if(!(pte_v & ARM_VM_PTE_PRESENT)) { + return EFAULT; + } + + if(ptent) *ptent = pte_v; + + /* Actual address now known; retrieve it and add page offset. */ + *physical = pte_v & ARM_VM_PTE_MASK; + *physical += virtual % ARM_PAGE_SIZE; + } + + return OK; +} + +/*===========================================================================* + * vm_lookup_range * + *===========================================================================*/ +size_t vm_lookup_range(const struct proc *proc, vir_bytes vir_addr, + phys_bytes *phys_addr, size_t bytes) +{ + /* Look up the physical address corresponding to linear virtual address + * 'vir_addr' for process 'proc'. Return the size of the range covered + * by contiguous physical memory starting from that address; this may + * be anywhere between 0 and 'bytes' inclusive. If the return value is + * nonzero, and 'phys_addr' is non-NULL, 'phys_addr' will be set to the + * base physical address of the range. 'vir_addr' and 'bytes' need not + * be page-aligned, but the caller must have verified that the given + * linear range is valid for the given process at all. + */ + phys_bytes phys, next_phys; + size_t len; + + assert(proc); + assert(bytes > 0); + assert(HASPT(proc)); + + /* Look up the first page. */ + if (vm_lookup(proc, vir_addr, &phys, NULL) != OK) + return 0; + + if (phys_addr != NULL) + *phys_addr = phys; + + len = ARM_PAGE_SIZE - (vir_addr % ARM_PAGE_SIZE); + vir_addr += len; + next_phys = phys + len; + + /* Look up any next pages and test physical contiguity. */ + while (len < bytes) { + if (vm_lookup(proc, vir_addr, &phys, NULL) != OK) + break; + + if (next_phys != phys) + break; + + len += ARM_PAGE_SIZE; + vir_addr += ARM_PAGE_SIZE; + next_phys += ARM_PAGE_SIZE; + } + + /* We might now have overshot the requested length somewhat. */ + return MIN(bytes, len); +} + +/*===========================================================================* + * vm_suspend * + *===========================================================================*/ +static void vm_suspend(struct proc *caller, const struct proc *target, + const vir_bytes linaddr, const vir_bytes len, const int type, + const int writeflag) +{ + /* This range is not OK for this process. Set parameters + * of the request and notify VM about the pending request. + */ + assert(!RTS_ISSET(caller, RTS_VMREQUEST)); + assert(!RTS_ISSET(target, RTS_VMREQUEST)); + + RTS_SET(caller, RTS_VMREQUEST); + + caller->p_vmrequest.req_type = VMPTYPE_CHECK; + caller->p_vmrequest.target = target->p_endpoint; + caller->p_vmrequest.params.check.start = linaddr; + caller->p_vmrequest.params.check.length = len; + caller->p_vmrequest.params.check.writeflag = writeflag; + caller->p_vmrequest.type = type; + + /* Connect caller on vmrequest wait queue. */ + if(!(caller->p_vmrequest.nextrequestor = vmrequest)) + if(OK != send_sig(VM_PROC_NR, SIGKMEM)) + panic("send_sig failed"); + vmrequest = caller; +} + +/*===========================================================================* + * vm_check_range * + *===========================================================================*/ +int vm_check_range(struct proc *caller, struct proc *target, + vir_bytes vir_addr, size_t bytes, int writeflag) +{ + /* Public interface to vm_suspend(), for use by kernel calls. On behalf + * of 'caller', call into VM to check linear virtual address range of + * process 'target', starting at 'vir_addr', for 'bytes' bytes. This + * function assumes that it will called twice if VM returned an error + * the first time (since nothing has changed in that case), and will + * then return the error code resulting from the first call. Upon the + * first call, a non-success error code is returned as well. + */ + int r; + + if ((caller->p_misc_flags & MF_KCALL_RESUME) && + (r = caller->p_vmrequest.vmresult) != OK) + return r; + + vm_suspend(caller, target, vir_addr, bytes, VMSTYPE_KERNELCALL, + writeflag); + + return VMSUSPEND; +} + +/*===========================================================================* + * delivermsg * + *===========================================================================*/ +void delivermsg(struct proc *rp) +{ + int r = OK; + + assert(rp->p_misc_flags & MF_DELIVERMSG); + assert(rp->p_delivermsg.m_source != NONE); + + if (copy_msg_to_user(&rp->p_delivermsg, + (message *) rp->p_delivermsg_vir)) { + printf("WARNING wrong user pointer 0x%08lx from " + "process %s / %d\n", + rp->p_delivermsg_vir, + rp->p_name, + rp->p_endpoint); + r = EFAULT; + } + + /* Indicate message has been delivered; address is 'used'. */ + rp->p_delivermsg.m_source = NONE; + rp->p_misc_flags &= ~MF_DELIVERMSG; + + if(!(rp->p_misc_flags & MF_CONTEXT_SET)) { + rp->p_reg.retreg = r; + } +} + +/*===========================================================================* + * vmmemset * + *===========================================================================*/ +int vm_memset(struct proc* caller, endpoint_t who, phys_bytes ph, int c, + phys_bytes count) +{ + u32_t pattern; + struct proc *whoptr = NULL; + phys_bytes cur_ph = ph; + phys_bytes left = count; + phys_bytes ptr, chunk, pfa = 0; + int new_ttbr, r = OK; + + if ((r = check_resumed_caller(caller)) != OK) + return r; + + /* NONE for physical, otherwise virtual */ + if (who != NONE && !(whoptr = endpoint_lookup(who))) + return ESRCH; + + c &= 0xFF; + pattern = c | (c << 8) | (c << 16) | (c << 24); + + assert(get_cpulocal_var(ptproc)->p_seg.p_ttbr_v); + assert(!catch_pagefaults); + catch_pagefaults = 1; + + /* We can memset as many bytes as we have remaining, + * or as many as remain in the 1MB chunk we mapped in. + */ + while (left > 0) { + new_ttbr = 0; + chunk = left; + ptr = createpde(whoptr, cur_ph, &chunk, 0, &new_ttbr); + + if (new_ttbr) { + reload_ttbr0(); + } + /* If a page fault happens, pfa is non-null */ + if ((pfa = phys_memset(ptr, pattern, chunk))) { + + /* If a process pagefaults, VM may help out */ + if (whoptr) { + vm_suspend(caller, whoptr, ph, count, + VMSTYPE_KERNELCALL, 1); + assert(catch_pagefaults); + catch_pagefaults = 0; + return VMSUSPEND; + } + + /* Pagefault when phys copying ?! */ + panic("vm_memset: pf %lx addr=%lx len=%lu\n", + pfa , ptr, chunk); + } + + cur_ph += chunk; + left -= chunk; + } + + assert(get_cpulocal_var(ptproc)->p_seg.p_ttbr_v); + assert(catch_pagefaults); + catch_pagefaults = 0; + + return OK; +} + +/*===========================================================================* + * virtual_copy_f * + *===========================================================================*/ +int virtual_copy_f(caller, src_addr, dst_addr, bytes, vmcheck) +struct proc * caller; +struct vir_addr *src_addr; /* source virtual address */ +struct vir_addr *dst_addr; /* destination virtual address */ +vir_bytes bytes; /* # of bytes to copy */ +int vmcheck; /* if nonzero, can return VMSUSPEND */ +{ +/* Copy bytes from virtual address src_addr to virtual address dst_addr. */ + struct vir_addr *vir_addr[2]; /* virtual source and destination address */ + int i, r; + struct proc *procs[2]; + + assert((vmcheck && caller) || (!vmcheck && !caller)); + + /* Check copy count. */ + if (bytes <= 0) return(EDOM); + + /* Do some more checks and map virtual addresses to physical addresses. */ + vir_addr[_SRC_] = src_addr; + vir_addr[_DST_] = dst_addr; + + for (i=_SRC_; i<=_DST_; i++) { + endpoint_t proc_e = vir_addr[i]->proc_nr_e; + int proc_nr; + struct proc *p; + + if(proc_e == NONE) { + p = NULL; + } else { + if(!isokendpt(proc_e, &proc_nr)) { + printf("virtual_copy: no reasonable endpoint\n"); + return ESRCH; + } + p = proc_addr(proc_nr); + } + + procs[i] = p; + } + + if ((r = check_resumed_caller(caller)) != OK) + return r; + + if((r=lin_lin_copy(procs[_SRC_], vir_addr[_SRC_]->offset, + procs[_DST_], vir_addr[_DST_]->offset, bytes)) != OK) { + int writeflag; + struct proc *target = NULL; + phys_bytes lin; + if(r != EFAULT_SRC && r != EFAULT_DST) + panic("lin_lin_copy failed: %d", r); + if(!vmcheck || !caller) { + return r; + } + + if(r == EFAULT_SRC) { + lin = vir_addr[_SRC_]->offset; + target = procs[_SRC_]; + writeflag = 0; + } else if(r == EFAULT_DST) { + lin = vir_addr[_DST_]->offset; + target = procs[_DST_]; + writeflag = 1; + } else { + panic("r strange: %d", r); + } + + assert(caller); + assert(target); + + vm_suspend(caller, target, lin, bytes, VMSTYPE_KERNELCALL, writeflag); + return VMSUSPEND; + } + + return OK; +} + +/*===========================================================================* + * data_copy * + *===========================================================================*/ +int data_copy(const endpoint_t from_proc, const vir_bytes from_addr, + const endpoint_t to_proc, const vir_bytes to_addr, + size_t bytes) +{ + struct vir_addr src, dst; + + src.offset = from_addr; + dst.offset = to_addr; + src.proc_nr_e = from_proc; + dst.proc_nr_e = to_proc; + assert(src.proc_nr_e != NONE); + assert(dst.proc_nr_e != NONE); + + return virtual_copy(&src, &dst, bytes); +} + +/*===========================================================================* + * data_copy_vmcheck * + *===========================================================================*/ +int data_copy_vmcheck(struct proc * caller, + const endpoint_t from_proc, const vir_bytes from_addr, + const endpoint_t to_proc, const vir_bytes to_addr, + size_t bytes) +{ + struct vir_addr src, dst; + + src.offset = from_addr; + dst.offset = to_addr; + src.proc_nr_e = from_proc; + dst.proc_nr_e = to_proc; + assert(src.proc_nr_e != NONE); + assert(dst.proc_nr_e != NONE); + + return virtual_copy_vmcheck(caller, &src, &dst, bytes); +} + +void memory_init(void) +{ + assert(nfreepdes == 0); + + freepdes[nfreepdes++] = kinfo.freepde_start++; + freepdes[nfreepdes++] = kinfo.freepde_start++; + + assert(kinfo.freepde_start < ARM_VM_DIR_ENTRIES); + assert(nfreepdes == 2); + assert(nfreepdes <= MAXFREEPDES); +} + +/*===========================================================================* + * arch_proc_init * + *===========================================================================*/ +void arch_proc_init(struct proc *pr, const u32_t ip, const u32_t sp, + const u32_t ps_str, char *name) +{ + arch_proc_reset(pr); + strcpy(pr->p_name, name); + + /* set custom state we know */ + pr->p_reg.pc = ip; + pr->p_reg.sp = sp; + pr->p_reg.retreg = ps_str; /* a.k.a r0*/ +} + +static int usermapped_glo_index = -1, + usermapped_index = -1, first_um_idx = -1; + + +/* defined in kernel.lds */ +extern char usermapped_start, usermapped_end, usermapped_nonglo_start; + +int arch_phys_map(const int index, + phys_bytes *addr, + phys_bytes *len, + int *flags) +{ + static int first = 1; + kern_phys_map *phys_maps; + + int freeidx = 0; + u32_t glo_len = (u32_t) &usermapped_nonglo_start - + (u32_t) &usermapped_start; + + if(first) { + memset(&minix_kerninfo, 0, sizeof(minix_kerninfo)); + if(glo_len > 0) { + usermapped_glo_index = freeidx++; + } + + usermapped_index = freeidx++; + first_um_idx = usermapped_index; + if(usermapped_glo_index != -1) + first_um_idx = usermapped_glo_index; + first = 0; + + /* list over the maps and index them */ + phys_maps = kern_phys_map_head; + while(phys_maps != NULL){ + phys_maps->index = freeidx++; + phys_maps = phys_maps->next; + } + + } + + if(index == usermapped_glo_index) { + *addr = vir2phys(&usermapped_start); + *len = glo_len; + *flags = VMMF_USER | VMMF_GLO; + return OK; + } + else if(index == usermapped_index) { + *addr = vir2phys(&usermapped_nonglo_start); + *len = (u32_t) &usermapped_end - + (u32_t) &usermapped_nonglo_start; + *flags = VMMF_USER; + return OK; + } + + /* if this all fails loop over the maps */ + phys_maps = kern_phys_map_head; + while(phys_maps != NULL){ + if(phys_maps->index == index){ + *addr = phys_maps->addr; + *len = phys_maps->size; + *flags = phys_maps->vm_flags; + return OK; + } + phys_maps = phys_maps->next; + } + + return EINVAL; +} + +int arch_phys_map_reply(const int index, const vir_bytes addr) +{ + kern_phys_map *phys_maps; + + if(index == first_um_idx) { + u32_t usermapped_offset; + assert(addr > (u32_t) &usermapped_start); + usermapped_offset = addr - (u32_t) &usermapped_start; +#define FIXEDPTR(ptr) (void *) ((u32_t)ptr + usermapped_offset) +#define FIXPTR(ptr) ptr = FIXEDPTR(ptr) +#define ASSIGN(minixstruct) minix_kerninfo.minixstruct = FIXEDPTR(&minixstruct) + ASSIGN(kinfo); + ASSIGN(machine); + ASSIGN(kmessages); + ASSIGN(loadinfo); + + /* adjust the pointers of the functions and the struct + * itself to the user-accessible mapping + */ + minix_kerninfo.kerninfo_magic = KERNINFO_MAGIC; + minix_kerninfo.minix_feature_flags = minix_feature_flags; + minix_kerninfo_user = (vir_bytes) FIXEDPTR(&minix_kerninfo); + return OK; + } + + if (index == usermapped_index) { + return OK; + } + + /* if this all fails loop over the maps */ + /* list over the maps and index them */ + phys_maps = kern_phys_map_head; + while(phys_maps != NULL){ + if(phys_maps->index == index){ + assert(phys_maps->cb != NULL); + /* only update the vir addr we are + going to call the callback in enable + paging + */ + phys_maps->vir = addr; + return OK; + } + phys_maps = phys_maps->next; + } + + return EINVAL; +} + +int arch_enable_paging(struct proc * caller) +{ + kern_phys_map *phys_maps; + assert(caller->p_seg.p_ttbr); + + + /* load caller's page table */ + switch_address_space(caller); + + /* We have now switched address spaces and the mappings are + valid. We can now remap previous mappings. This is not a + good time to do printf as the initial massing is gone and + the new mapping is not in place */ + phys_maps = kern_phys_map_head; + while(phys_maps != NULL){ + assert(phys_maps->cb != NULL); + phys_maps->cb(phys_maps->id, phys_maps->vir); + phys_maps = phys_maps->next; + } + + return OK; +} + +void release_address_space(struct proc *pr) +{ + pr->p_seg.p_ttbr_v = NULL; + barrier(); +} + + + +/* + * Request a physical mapping + */ +int kern_req_phys_map( phys_bytes base_address, vir_bytes io_size, + int vm_flags, kern_phys_map * priv, + kern_phys_map_mapped cb, vir_bytes id) +{ + /* Assign the values to the given struct and add priv + to the list */ + assert(base_address != 0); + assert(io_size % ARM_PAGE_SIZE == 0); + assert(cb != NULL); + + priv->addr = base_address; + priv->size = io_size; + priv->vm_flags = vm_flags; + priv->cb = cb; + priv->id = id; + priv->index = -1; + priv->next = NULL; + + + if (kern_phys_map_head == NULL){ + /* keep a list of items this is the first one */ + kern_phys_map_head = priv; + kern_phys_map_head->next = NULL; + } else { + /* insert the item head but first keep track + of the current by putting it in next */ + priv->next = kern_phys_map_head; + /* replace the head */ + kern_phys_map_head = priv; + } + return 0; +} + +/* + * Callback implementation where the id given to the + * kern_phys_map is a pointer to the io map base address. + * this implementation will just change that base address. + * once that area is remapped. + */ +int kern_phys_map_mapped_ptr(vir_bytes id, phys_bytes address){ + *((vir_bytes*)id) = address; + return 0; +} + +/* + * Request a physical mapping and put the result in the given prt + * Note that ptr will only be valid once the callback happened. + */ +int kern_phys_map_ptr( + phys_bytes base_address, + vir_bytes io_size, + int vm_flags, + kern_phys_map * priv, + vir_bytes ptr) +{ + return kern_req_phys_map(base_address,io_size,vm_flags,priv,kern_phys_map_mapped_ptr,ptr); +} + diff --git a/minix/kernel/arch/earmv6hf/mpx.S b/minix/kernel/arch/earmv6hf/mpx.S new file mode 100644 index 000000000..c7371e988 --- /dev/null +++ b/minix/kernel/arch/earmv6hf/mpx.S @@ -0,0 +1,289 @@ +/* This file is part of the lowest layer of the MINIX kernel. (The other part + * is "proc.c".) The lowest layer does process switching and message handling. + * + * Kernel is entered either because of kernel-calls, ipc-calls, interrupts or + * exceptions. TSS is set so that the kernel stack is loaded. The user context is + * saved to the proc table and the handler of the event is called. Once the + * handler is done, switch_to_user() function is called to pick a new process, + * finish what needs to be done for the next process to run, sets its context + * and switch to userspace. + */ + +#include "kernel/kernel.h" /* configures the kernel */ + +/* sections */ + +#include +#include "kernel/kernel.h" +#include +#include +#include +#include +#include +#include "archconst.h" +#include "kernel/const.h" +#include "kernel/proc.h" +#include "sconst.h" +#include +#include +#include +#include +#include "bsp_intr.h" + +#include "arch_proto.h" /* K_STACK_SIZE */ + +IMPORT(svc_stack) + +/* + * Adjust lr, push pc/psr when exception triggered and switch to SVC mode + * The 'lr_offset' argument holds the adjustment. + * + * When an instruction causes the ARM core to enter the exception handler + * the value of pc is stored in the link register (lr). By default on ARM + * the program counter is 3 instruction a head of the current instruction + * being executed (because of the 3 stage pipeline). Depending on where in + * the pipeline the exception happens lr will need to de adjusted to find + * the proper return address. + */ +.macro switch_to_svc lr_offset + sub lr, lr, #\lr_offset /* do the adjustment */ + srsdb sp!, #PSR_SVC32_MODE /* store the saved the return */ + /* address and program status */ + /* register onto the kernel stack */ + /* Also modify the stack pointer. */ + cps #PSR_SVC32_MODE /* do the switch to SVC. */ +.endm + +/* + * Test if the exception/interrupt occurred in the kernel. + * Jump to 'label' argument if it occurred in the kernel. + * + * NOTE: switch_to_svc must be called first */ +.macro test_int_in_kernel, label + push {r3} + ldr r3, [sp, #8] /* get spsr. */ + orr r3, r3, #(PSR_F | PSR_I) /* mask interrupts on return. */ + str r3, [sp, #8] /* store spsr. */ + and r3, r3, #PSR_MODE /* mask the ARM mode. */ + cmp r3, #PSR_USR32_MODE /* compare it to user mode. */ + pop {r3} + bne \label /* In-kernel handling. */ +.endm + +/* Save the register context to the proc structure */ +.macro save_process_ctx + add sp, sp, #8 /* We expect srsdb pushed cpsr and lr on */ + /* the stack. */ + ldr lr, [sp] /* lr = proc_ptr. */ + stm lr, {r0-r14}^ /* store the user mode registers */ + /* proc_ptr->p_reg.r0-r14 = r0-r14. */ + ldr r12, [sp, #-8] /* r12 = pc stored on the stack. */ + str r12, [lr, #PCREG] /* proc_ptr->p_reg.pc = r12. */ + ldr r12, [sp, #-4] /* r12 = cpsr stored on the stack. */ + str r12, [lr, #PSREG] /* proc_ptr->p_reg.psr = r12. */ +.endm + +.macro exception_handler exc_name, exc_num, lr_offset +ENTRY(\exc_name\()_entry) + switch_to_svc \lr_offset + test_int_in_kernel \exc_name\()_entry_nested + +\exc_name\()entry_from_user: + save_process_ctx + + ldr fp, [sp] /* save the pointer to the current process. */ + add r4, fp, #PCREG /* save the exception pc (saved lr_user) */ + /* r4-r9 are callee save. */ + + /* stop user process cycles */ + mov r0, fp /* first param: caller proc ptr. */ + mov fp, #0 /* for stack trace. */ + bl _C_LABEL(context_stop) + + /* + * push a pointer to the interrupt state pushed by the cpu and the + * vector number pushed by the vector handler just before calling + * exception_entry and call the exception handler. + */ + mov r0, #0 /* it is not a nested exception. */ + mov r1, r4 /* saved lr. */ + mov r2, #\exc_num /* vector number */ + bl _C_LABEL(exception_handler) + b _C_LABEL(switch_to_user) + +\exc_name\()_entry_nested: + push {r0-r12, lr} + mov r0, #1 /* it is a nested exception. */ + add r1, sp, #56 /* saved lr */ + mov r2, #\exc_num /* vector number */ + bl _C_LABEL(exception_handler) + pop {r0-r12, lr} + rfeia sp! +.endm + + +/* Exception handlers */ +exception_handler data_abort DATA_ABORT_VECTOR 8 +exception_handler prefetch_abort PREFETCH_ABORT_VECTOR 4 +exception_handler undefined_inst UNDEFINED_INST_VECTOR 4 + + +ENTRY(irq_entry) + switch_to_svc 4 + test_int_in_kernel irq_entry_from_kernel + +irq_entry_from_user: + save_process_ctx + + /* save the pointer to the current process */ + ldr fp, [sp] + + push {fp} /* save caller proc ptr. */ + sub sp, sp, #4 /* maintain stack alignment. */ + + /* stop user process cycles */ + mov r0, fp /* first param: caller proc ptr. */ + mov fp, #0 /* for stack trace. */ + bl _C_LABEL(context_stop) + + /* call handler */ + bl _C_LABEL(bsp_irq_handle) /* bsp_irq_handle(void) */ + + add sp, sp, #4 + pop {fp} /* caller proc ptr. */ + dsb /* data synchronization barrier. */ + + b _C_LABEL(switch_to_user) + +irq_entry_from_kernel: + push {r0-r12, lr} + bl _C_LABEL(context_stop_idle) + + /* call handler */ + bl _C_LABEL(bsp_irq_handle) /* bsp_irq_handle(void). */ + + /* data synchronization barrier */ dsb + pop {r0-r12, lr} + rfeia sp! + + +/* + * supervisor call (SVC) kernel entry point + */ +ENTRY(svc_entry) + /* Store the LR and the SPSR of the current mode onto the SVC stack */ + srsdb sp!, #PSR_SVC32_MODE + save_process_ctx + + /* save the pointer to the current process */ + ldr fp, [sp] + + cmp r3, #KERVEC_INTR + beq kernel_call_entry + cmp r3, #IPCVEC_INTR + beq ipc_entry + + /* return -1 to the current process as an invalid SWI was called .*/ + mov r0, #-1 + str r0, [fp, #REG0] + b _C_LABEL(switch_to_user) + +/* + * kernel call is only from a process to kernel + */ +ENTRY(kernel_call_entry) + /* + * pass the syscall arguments from userspace to the handler. + * save_process_ctx() does not clobber these registers, they are still + * set as the userspace has set them. + */ + push {fp} /* save caller proc ptr. */ + push {r0} /* save msg ptr so it's not clobbered. */ + + /* stop user process cycles */ + mov r0, fp /* first param: caller proc ptr */ + mov fp, #0 /* for stack trace */ + bl _C_LABEL(context_stop) + + pop {r0} /* first param: msg ptr. */ + pop {r1} /* second param: caller proc ptr. */ + bl _C_LABEL(kernel_call) + + b _C_LABEL(switch_to_user) + +/* + * IPC is only from a process to kernel + */ +ENTRY(ipc_entry) + /* + * pass the syscall arguments from userspace to the handler. + * save_process_ctx() does not clobber these registers, they are still + * set as the userspace have set them + */ + push {fp} /* save caller proc ptr. */ + push {r0-r2} /* save regs so they're not clobbered. */ + + /* stop user process cycles */ + mov r0, fp /* first param: caller proc ptr. */ + mov fp, #0 /* for stack trace. */ + bl _C_LABEL(context_stop) + + pop {r0-r2} /* restore regs */ + bl _C_LABEL(do_ipc) + + /* restore the current process pointer and save the return value */ + pop {fp} /* caller proc ptr. */ + str r0, [fp, #REG0] + + b _C_LABEL(switch_to_user) + +ENTRY(invalid_svc) + b . + +ENTRY(restore_user_context) + /* sp holds the proc ptr */ + mov sp, r0 + + /* Set SPSR and LR for return */ + ldr r0, [sp, #PSREG] + msr spsr_fsxc, r0 /* flags , status, extension control. */ + ldr lr, [sp, #PCREG] + + /* Restore user-mode registers from proc struct */ + ldm sp, {r0-r14}^ + + ldr sp, =_C_LABEL(svc_stack) + ldr sp, [sp] + + /* To user mode! */ + movs pc, lr /* preferred way of returning from svc */ + +/*===========================================================================*/ +/* data */ +/*===========================================================================*/ + +.data +.short 0x526F /* this must be the first data entry (magic #) */ +.bss +.data +.balign 4 +k_initial_stack: +.space K_STACK_SIZE +LABEL(__k_unpaged_k_initial_stktop) + +/* + * the kernel stack + */ +k_boot_stack: +.space K_STACK_SIZE /* kernel stack */ /* FIXME use macro here */ +LABEL(k_boot_stktop) /* top of kernel stack */ + +.balign K_STACK_SIZE +LABEL(k_stacks_start) + +/* two pages for each stack, one for data, other as a sandbox */ +.space 2 * (K_STACK_SIZE * CONFIG_MAX_CPUS) + +LABEL(k_stacks_end) + +/* top of kernel stack */ diff --git a/minix/kernel/arch/earmv6hf/pg_utils.c b/minix/kernel/arch/earmv6hf/pg_utils.c new file mode 100644 index 000000000..fe4c24d33 --- /dev/null +++ b/minix/kernel/arch/earmv6hf/pg_utils.c @@ -0,0 +1,317 @@ +#include + +#include +#include +#include "kernel/kernel.h" +#include "arch_proto.h" +#include +#include + +#include +#include + +/* These are set/computed in kernel.lds. */ +extern char _kern_vir_base, _kern_phys_base, _kern_size; + +/* Retrieve the absolute values to something we can use. */ +static phys_bytes kern_vir_start = (phys_bytes) &_kern_vir_base; +static phys_bytes kern_phys_start = (phys_bytes) &_kern_phys_base; +static phys_bytes kern_kernlen = (phys_bytes) &_kern_size; + +/* page directory we can use to map things */ +static u32_t pagedir[4096] __aligned(16384); + +void print_memmap(kinfo_t *cbi) +{ + int m; + assert(cbi->mmap_size < MAXMEMMAP); + for(m = 0; m < cbi->mmap_size; m++) { + phys_bytes addr = cbi->memmap[m].mm_base_addr, endit = cbi->memmap[m].mm_base_addr + cbi->memmap[m].mm_length; + printf("%08lx-%08lx ",addr, endit); + } + printf("\nsize %08lx\n", cbi->mmap_size); +} + +void cut_memmap(kinfo_t *cbi, phys_bytes start, phys_bytes end) +{ + int m; + phys_bytes o; + + if((o=start % ARM_PAGE_SIZE)) + start -= o; + if((o=end % ARM_PAGE_SIZE)) + end += ARM_PAGE_SIZE - o; + + assert(kernel_may_alloc); + + for(m = 0; m < cbi->mmap_size; m++) { + phys_bytes substart = start, subend = end; + phys_bytes memaddr = cbi->memmap[m].mm_base_addr, + memend = cbi->memmap[m].mm_base_addr + cbi->memmap[m].mm_length; + + /* adjust cut range to be a subset of the free memory */ + if(substart < memaddr) substart = memaddr; + if(subend > memend) subend = memend; + if(substart >= subend) continue; + + /* if there is any overlap, forget this one and add + * 1-2 subranges back + */ + cbi->memmap[m].mm_base_addr = cbi->memmap[m].mm_length = 0; + if(substart > memaddr) + add_memmap(cbi, memaddr, substart-memaddr); + if(subend < memend) + add_memmap(cbi, subend, memend-subend); + } +} + +void add_memmap(kinfo_t *cbi, u64_t addr, u64_t len) +{ + int m; +#define LIMIT 0xFFFFF000 + /* Truncate available memory at 4GB as the rest of minix + * currently can't deal with any bigger. + */ + if(addr > LIMIT) { + return; + } + + if(addr + len > LIMIT) { + len -= (addr + len - LIMIT); + } + + assert(cbi->mmap_size < MAXMEMMAP); + if(len == 0) { + return; + } + addr = roundup(addr, ARM_PAGE_SIZE); + len = rounddown(len, ARM_PAGE_SIZE); + + assert(kernel_may_alloc); + + for(m = 0; m < MAXMEMMAP; m++) { + phys_bytes highmark; + if(cbi->memmap[m].mm_length) { + continue; + } + cbi->memmap[m].mm_base_addr = addr; + cbi->memmap[m].mm_length = len; + cbi->memmap[m].type = MULTIBOOT_MEMORY_AVAILABLE; + if(m >= cbi->mmap_size) { + cbi->mmap_size = m+1; + } + highmark = addr + len; + if(highmark > cbi->mem_high_phys) { + cbi->mem_high_phys = highmark; + } + return; + } + + panic("no available memmap slot"); +} + +u32_t *alloc_pagetable(phys_bytes *ph) +{ + u32_t *ret; +#define PG_PAGETABLES 24 + static u32_t pagetables[PG_PAGETABLES][256] __aligned(1024); + static int pt_inuse = 0; + if(pt_inuse >= PG_PAGETABLES) { + panic("no more pagetables"); + } + assert(sizeof(pagetables[pt_inuse]) == 1024); + ret = pagetables[pt_inuse++]; + *ph = vir2phys(ret); + return ret; +} + +#define PAGE_KB (ARM_PAGE_SIZE / 1024) + +phys_bytes pg_alloc_page(kinfo_t *cbi) +{ + int m; + multiboot_memory_map_t *mmap; + + assert(kernel_may_alloc); + + for(m = 0; m < cbi->mmap_size; m++) { + mmap = &cbi->memmap[m]; + if(!mmap->mm_length) { + continue; + } + assert(mmap->mm_length > 0); + assert(!(mmap->mm_length % ARM_PAGE_SIZE)); + assert(!(mmap->mm_base_addr % ARM_PAGE_SIZE)); + + u32_t addr = mmap->mm_base_addr; + mmap->mm_base_addr += ARM_PAGE_SIZE; + mmap->mm_length -= ARM_PAGE_SIZE; + + cbi->kernel_allocated_bytes_dynamic += ARM_PAGE_SIZE; + + return addr; + } + + panic("can't find free memory"); +} + +void pg_identity(kinfo_t *cbi) +{ + int i; + phys_bytes phys; + + /* We map memory that does not correspond to physical memory + * as non-cacheable. Make sure we know what it is. + */ + assert(cbi->mem_high_phys); + + /* Set up an identity mapping page directory */ + for(i = 0; i < ARM_VM_DIR_ENTRIES; i++) { + u32_t flags = ARM_VM_SECTION + | ARM_VM_SECTION_USER + | ARM_VM_SECTION_DOMAIN; + + phys = i * ARM_SECTION_SIZE; + /* mark mormal memory as cacheable. TODO: fix hard coded values */ + if (phys >= PHYS_MEM_BEGIN && phys <= PHYS_MEM_END) { + pagedir[i] = phys | flags | ARM_VM_SECTION_CACHED; + } else { + pagedir[i] = phys | flags | ARM_VM_SECTION_DEVICE; + } + } +} + +int pg_mapkernel(void) +{ + int pde; + u32_t mapped = 0, kern_phys = kern_phys_start; + + assert(!(kern_vir_start % ARM_SECTION_SIZE)); + assert(!(kern_phys_start % ARM_SECTION_SIZE)); + pde = kern_vir_start / ARM_SECTION_SIZE; /* start pde */ + while(mapped < kern_kernlen) { + pagedir[pde] = (kern_phys & ARM_VM_SECTION_MASK) + | ARM_VM_SECTION + | ARM_VM_SECTION_SUPER + | ARM_VM_SECTION_DOMAIN + | ARM_VM_SECTION_CACHED; + mapped += ARM_SECTION_SIZE; + kern_phys += ARM_SECTION_SIZE; + pde++; + } + return pde; /* free pde */ +} + +void vm_enable_paging(void) +{ + u32_t sctlr; + u32_t actlr; + + write_ttbcr(0); + + /* Set all Domains to Client */ + write_dacr(0x55555555); + + sctlr = read_sctlr(); + + /* Enable MMU */ + sctlr |= CPU_CONTROL_MMU_ENABLE; + + /* TRE set to zero (default reset value): TEX[2:0] are used, plus C and B bits.*/ + sctlr &= ~CPU_CONTROL_TR_ENABLE; + + /* AFE set to zero (default reset value): not using simplified model. */ + sctlr &= ~CPU_CONTROL_AF_ENABLE; + + /* Enable instruction ,data cache and branch prediction */ + sctlr |= CPU_CONTROL_DC_ENABLE; + sctlr |= CPU_CONTROL_IC_ENABLE; + sctlr |= CPU_CONTROL_BPRD_ENABLE; + + /* Enable barriers */ + sctlr |= CPU_CONTROL_32BD_ENABLE; + + /* Enable L2 cache (cortex-a8) */ + #define CORTEX_A8_L2EN (0x02) + actlr = read_actlr(); + actlr |= CORTEX_A8_L2EN; + write_actlr(actlr); + + write_sctlr(sctlr); +} + +phys_bytes pg_load() +{ + phys_bytes phpagedir = vir2phys(pagedir); + write_ttbr0(phpagedir); + return phpagedir; +} + +void pg_clear(void) +{ + memset(pagedir, 0, sizeof(pagedir)); +} + +phys_bytes pg_rounddown(phys_bytes b) +{ + phys_bytes o; + if(!(o = b % ARM_PAGE_SIZE)) { + return b; + } + return b - o; +} + +void pg_map(phys_bytes phys, vir_bytes vaddr, vir_bytes vaddr_end, + kinfo_t *cbi) +{ + static int mapped_pde = -1; + static u32_t *pt = NULL; + int pde, pte; + + assert(kernel_may_alloc); + + if(phys == PG_ALLOCATEME) { + assert(!(vaddr % ARM_PAGE_SIZE)); + } else { + assert((vaddr % ARM_PAGE_SIZE) == (phys % ARM_PAGE_SIZE)); + vaddr = pg_rounddown(vaddr); + phys = pg_rounddown(phys); + } + assert(vaddr < kern_vir_start); + + while(vaddr < vaddr_end) { + phys_bytes source = phys; + assert(!(vaddr % ARM_PAGE_SIZE)); + if(phys == PG_ALLOCATEME) { + source = pg_alloc_page(cbi); + } else { + assert(!(phys % ARM_PAGE_SIZE)); + } + assert(!(source % ARM_PAGE_SIZE)); + pde = ARM_VM_PDE(vaddr); + pte = ARM_VM_PTE(vaddr); + if(mapped_pde < pde) { + phys_bytes ph; + pt = alloc_pagetable(&ph); + pagedir[pde] = (ph & ARM_VM_PDE_MASK) + | ARM_VM_PAGEDIR + | ARM_VM_PDE_DOMAIN; + mapped_pde = pde; + } + assert(pt); + pt[pte] = (source & ARM_VM_PTE_MASK) + | ARM_VM_PAGETABLE + | ARM_VM_PTE_CACHED + | ARM_VM_PTE_USER; + vaddr += ARM_PAGE_SIZE; + if(phys != PG_ALLOCATEME) { + phys += ARM_PAGE_SIZE; + } + } +} + +void pg_info(reg_t *pagedir_ph, u32_t **pagedir_v) +{ + *pagedir_ph = vir2phys(pagedir); + *pagedir_v = pagedir; +} diff --git a/minix/kernel/arch/earmv6hf/phys_copy.S b/minix/kernel/arch/earmv6hf/phys_copy.S new file mode 100644 index 000000000..8ee390ca6 --- /dev/null +++ b/minix/kernel/arch/earmv6hf/phys_copy.S @@ -0,0 +1,397 @@ +/* $NetBSD: memcpy_arm.S,v 1.4 2013/08/11 04:56:32 matt Exp $ */ + +/*- + * Copyright (c) 1997 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Neil A. Carson and Mark Brinicombe + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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 + +#if !defined(__minix) +#if defined(__ARM_EABI__) +STRONG_ALIAS(__aeabi_memcpy, memcpy) +#endif +#endif /* !defined(__minix) */ + +/* + * This is one fun bit of code ... + * Some easy listening music is suggested while trying to understand this + * code e.g. Iron Maiden + * + * For anyone attempting to understand it : + * + * The core code is implemented here with simple stubs for memcpy(). + * + * All local labels are prefixed with Lmemcpy_ + * Following the prefix a label starting f is used in the forward copy code + * while a label using b is used in the backwards copy code + * The source and destination addresses determine whether a forward or + * backward copy is performed. + * Separate bits of code are used to deal with the following situations + * for both the forward and backwards copy. + * unaligned source address + * unaligned destination address + * Separate copy routines are used to produce an optimised result for each + * of these cases. + * The copy code will use LDM/STM instructions to copy up to 32 bytes at + * a time where possible. + * + * Note: r12 (aka ip) can be trashed during the function along with + * r0-r3 although r0-r2 have defined uses i.e. src, dest, len through out. + * Additional registers are preserved prior to use i.e. r4, r5 & lr + * + * Apologies for the state of the comments ;-) + */ + +/* For MINIX, we always spill r0, r4, r5, and lr, so we can easily + * clean up the stack after a phys_copy fault. NetBSD, in contrast, + * spills the minimum number of registers for each path. + */ +#if defined(__minix) +/* LINTSTUB: Func: void *phys_copy(void *src, void *dst, size_t len) */ +ENTRY(phys_copy) + /* switch the source and destination registers */ + eor r0, r1, r0 + eor r1, r0, r1 + eor r0, r1, r0 +#else +/* LINTSTUB: Func: void *memcpy(void *dst, const void *src, size_t len) */ +ENTRY(memcpy) +#endif + /* save leaf functions having to store this away */ +#if defined(__minix) + push {r0, r4, r5, lr} /* memcpy() returns dest addr */ +#else + push {r0, lr} /* memcpy() returns dest addr */ +#endif + + subs r2, r2, #4 + blt .Lmemcpy_l4 /* less than 4 bytes */ + ands r12, r0, #3 + bne .Lmemcpy_destul /* oh unaligned destination addr */ + ands r12, r1, #3 + bne .Lmemcpy_srcul /* oh unaligned source addr */ + +.Lmemcpy_t8: + /* We have aligned source and destination */ + subs r2, r2, #8 + blt .Lmemcpy_l12 /* less than 12 bytes (4 from above) */ + subs r2, r2, #0x14 + blt .Lmemcpy_l32 /* less than 32 bytes (12 from above) */ +#if !defined(__minix) + push {r4} /* borrow r4 */ +#endif + + /* blat 32 bytes at a time */ + /* XXX for really big copies perhaps we should use more registers */ +.Lmemcpy_loop32: + ldmia r1!, {r3, r4, r12, lr} + stmia r0!, {r3, r4, r12, lr} + ldmia r1!, {r3, r4, r12, lr} + stmia r0!, {r3, r4, r12, lr} + subs r2, r2, #0x20 + bge .Lmemcpy_loop32 + + cmn r2, #0x10 + ldmiage r1!, {r3, r4, r12, lr} /* blat a remaining 16 bytes */ + stmiage r0!, {r3, r4, r12, lr} + subge r2, r2, #0x10 +#if !defined(__minix) + pop {r4} /* return r4 */ +#endif + +.Lmemcpy_l32: + adds r2, r2, #0x14 + + /* blat 12 bytes at a time */ +.Lmemcpy_loop12: + ldmiage r1!, {r3, r12, lr} + stmiage r0!, {r3, r12, lr} + subsge r2, r2, #0x0c + bge .Lmemcpy_loop12 + +.Lmemcpy_l12: + adds r2, r2, #8 + blt .Lmemcpy_l4 + + subs r2, r2, #4 + ldrlt r3, [r1], #4 + strlt r3, [r0], #4 + ldmiage r1!, {r3, r12} + stmiage r0!, {r3, r12} + subge r2, r2, #4 + +.Lmemcpy_l4: + /* less than 4 bytes to go */ + adds r2, r2, #4 +#if defined(__minix) + popeq {r0, r4, r5} + moveq r0, #0 + popeq {pc} +#else +#ifdef __APCS_26_ + ldmiaeq sp!, {r0, pc}^ /* done */ +#else + popeq {r0, pc} /* done */ +#endif +#endif + /* copy the crud byte at a time */ + cmp r2, #2 + ldrb r3, [r1], #1 + strb r3, [r0], #1 + ldrbge r3, [r1], #1 + strbge r3, [r0], #1 + ldrbgt r3, [r1], #1 + strbgt r3, [r0], #1 +#if defined(__minix) + pop {r0, r4, r5} + mov r0, #0 + pop {pc} +#else + pop {r0, pc} +#endif + + /* erg - unaligned destination */ +.Lmemcpy_destul: + rsb r12, r12, #4 + cmp r12, #2 + + /* align destination with byte copies */ + ldrb r3, [r1], #1 + strb r3, [r0], #1 + ldrbge r3, [r1], #1 + strbge r3, [r0], #1 + ldrbgt r3, [r1], #1 + strbgt r3, [r0], #1 + subs r2, r2, r12 + blt .Lmemcpy_l4 /* less the 4 bytes */ + + ands r12, r1, #3 + beq .Lmemcpy_t8 /* we have an aligned source */ + + /* erg - unaligned source */ + /* This is where it gets nasty ... */ +.Lmemcpy_srcul: + bic r1, r1, #3 + ldr lr, [r1], #4 + cmp r12, #2 + bgt .Lmemcpy_srcul3 + beq .Lmemcpy_srcul2 + cmp r2, #0x0c + blt .Lmemcpy_srcul1loop4 + sub r2, r2, #0x0c +#if !defined(__minix) + push {r4, r5} +#endif + +.Lmemcpy_srcul1loop16: +#ifdef __ARMEB__ + mov r3, lr, lsl #8 +#else + mov r3, lr, lsr #8 +#endif + ldmia r1!, {r4, r5, r12, lr} +#ifdef __ARMEB__ + orr r3, r3, r4, lsr #24 + mov r4, r4, lsl #8 + orr r4, r4, r5, lsr #24 + mov r5, r5, lsl #8 + orr r5, r5, r12, lsr #24 + mov r12, r12, lsl #8 + orr r12, r12, lr, lsr #24 +#else + orr r3, r3, r4, lsl #24 + mov r4, r4, lsr #8 + orr r4, r4, r5, lsl #24 + mov r5, r5, lsr #8 + orr r5, r5, r12, lsl #24 + mov r12, r12, lsr #8 + orr r12, r12, lr, lsl #24 +#endif + stmia r0!, {r3-r5, r12} + subs r2, r2, #0x10 + bge .Lmemcpy_srcul1loop16 +#if !defined(__minix) + pop {r4, r5} +#endif + adds r2, r2, #0x0c + blt .Lmemcpy_srcul1l4 + +.Lmemcpy_srcul1loop4: +#ifdef __ARMEB__ + mov r12, lr, lsl #8 +#else + mov r12, lr, lsr #8 +#endif + ldr lr, [r1], #4 +#ifdef __ARMEB__ + orr r12, r12, lr, lsr #24 +#else + orr r12, r12, lr, lsl #24 +#endif + str r12, [r0], #4 + subs r2, r2, #4 + bge .Lmemcpy_srcul1loop4 + +.Lmemcpy_srcul1l4: + sub r1, r1, #3 + b .Lmemcpy_l4 + +.Lmemcpy_srcul2: + cmp r2, #0x0c + blt .Lmemcpy_srcul2loop4 + sub r2, r2, #0x0c +#if !defined(__minix) + push {r4, r5} +#endif + +.Lmemcpy_srcul2loop16: +#ifdef __ARMEB__ + mov r3, lr, lsl #16 +#else + mov r3, lr, lsr #16 +#endif + ldmia r1!, {r4, r5, r12, lr} +#ifdef __ARMEB__ + orr r3, r3, r4, lsr #16 + mov r4, r4, lsl #16 + orr r4, r4, r5, lsr #16 + mov r5, r5, lsl #16 + orr r5, r5, r12, lsr #16 + mov r12, r12, lsl #16 + orr r12, r12, lr, lsr #16 +#else + orr r3, r3, r4, lsl #16 + mov r4, r4, lsr #16 + orr r4, r4, r5, lsl #16 + mov r5, r5, lsr #16 + orr r5, r5, r12, lsl #16 + mov r12, r12, lsr #16 + orr r12, r12, lr, lsl #16 +#endif + stmia r0!, {r3-r5, r12} + subs r2, r2, #0x10 + bge .Lmemcpy_srcul2loop16 +#if !defined(__minix) + pop {r4, r5} +#endif + adds r2, r2, #0x0c + blt .Lmemcpy_srcul2l4 + +.Lmemcpy_srcul2loop4: +#ifdef __ARMEB__ + mov r12, lr, lsl #16 +#else + mov r12, lr, lsr #16 +#endif + ldr lr, [r1], #4 +#ifdef __ARMEB__ + orr r12, r12, lr, lsr #16 +#else + orr r12, r12, lr, lsl #16 +#endif + str r12, [r0], #4 + subs r2, r2, #4 + bge .Lmemcpy_srcul2loop4 + +.Lmemcpy_srcul2l4: + sub r1, r1, #2 + b .Lmemcpy_l4 + +.Lmemcpy_srcul3: + cmp r2, #0x0c + blt .Lmemcpy_srcul3loop4 + sub r2, r2, #0x0c +#if !defined(__minix) + push {r4, r5} +#endif + +.Lmemcpy_srcul3loop16: +#ifdef __ARMEB__ + mov r3, lr, lsl #24 +#else + mov r3, lr, lsr #24 +#endif + ldmia r1!, {r4, r5, r12, lr} +#ifdef __ARMEB__ + orr r3, r3, r4, lsr #8 + mov r4, r4, lsl #24 + orr r4, r4, r5, lsr #8 + mov r5, r5, lsl #24 + orr r5, r5, r12, lsr #8 + mov r12, r12, lsl #24 + orr r12, r12, lr, lsr #8 +#else + orr r3, r3, r4, lsl #8 + mov r4, r4, lsr #24 + orr r4, r4, r5, lsl #8 + mov r5, r5, lsr #24 + orr r5, r5, r12, lsl #8 + mov r12, r12, lsr #24 + orr r12, r12, lr, lsl #8 +#endif + stmia r0!, {r3-r5, r12} + subs r2, r2, #0x10 + bge .Lmemcpy_srcul3loop16 +#if !defined(__minix) + pop {r4, r5} +#endif + adds r2, r2, #0x0c + blt .Lmemcpy_srcul3l4 + +.Lmemcpy_srcul3loop4: +#ifdef __ARMEB__ + mov r12, lr, lsl #24 +#else + mov r12, lr, lsr #24 +#endif + ldr lr, [r1], #4 +#ifdef __ARMEB__ + orr r12, r12, lr, lsr #8 +#else + orr r12, r12, lr, lsl #8 +#endif + str r12, [r0], #4 + subs r2, r2, #4 + bge .Lmemcpy_srcul3loop4 + +.Lmemcpy_srcul3l4: + sub r1, r1, #1 + b .Lmemcpy_l4 + +#if defined(__minix) +LABEL(phys_copy_fault) /* kernel can send us here */ + pop {r0, r4, r5} + pop {pc} + +LABEL(phys_copy_fault_in_kernel) /* kernel can send us here */ + pop {r0, r4, r5} + mrc p15, 0, r0, c6, c0, 0 /* Read DFAR */ + pop {pc} +#else +END(memcpy) +#endif diff --git a/minix/kernel/arch/earmv6hf/phys_memset.S b/minix/kernel/arch/earmv6hf/phys_memset.S new file mode 100644 index 000000000..c3200230e --- /dev/null +++ b/minix/kernel/arch/earmv6hf/phys_memset.S @@ -0,0 +1,274 @@ +/* $NetBSD: memset.S,v 1.1 2005/12/20 19:28:49 christos Exp $ */ + +/* + * Copyright 2003 Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Steve C. Woodford for Wasabi Systems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC + * 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) 1995 Mark Brinicombe. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Mark Brinicombe. + * 4. The name of the company nor the name of the author may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY 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 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 + +/* + * memset: Sets a block of memory to the specified value + * + * On entry: + * r0 - dest address + * r1 - byte to write + * r2 - number of bytes to write + * + * On exit: + * r0 - dest address + */ +#ifdef _BZERO +/* LINTSTUB: Func: void bzero(void *, size_t) */ +ENTRY(bzero) + mov r3, #0x00 +#else +#if defined(__minix) +/* LINTSTUB: Func: void *phys_memset(void *, int, size_t) */ +ENTRY(phys_memset) +#else +/* LINTSTUB: Func: void *memset(void *, int, size_t) */ +ENTRY(memset) +#endif + and r3, r1, #0xff /* We deal with bytes */ + mov r1, r2 +#endif + cmp r1, #0x04 /* Do we have less than 4 bytes */ + mov ip, r0 + blt .Lmemset_lessthanfour + + /* Ok first we will word align the address */ + ands r2, ip, #0x03 /* Get the bottom two bits */ + bne .Lmemset_wordunaligned /* The address is not word aligned */ + + /* We are now word aligned */ +.Lmemset_wordaligned: +#ifndef _BZERO + orr r3, r3, r3, lsl #8 /* Extend value to 16-bits */ +#endif +#ifdef __XSCALE__ + tst ip, #0x04 /* Quad-align for Xscale */ +#else + cmp r1, #0x10 +#endif +#ifndef _BZERO + orr r3, r3, r3, lsl #16 /* Extend value to 32-bits */ +#endif +#ifdef __XSCALE__ + subne r1, r1, #0x04 /* Quad-align if necessary */ + strne r3, [ip], #0x04 + cmp r1, #0x10 +#endif + blt .Lmemset_loop4 /* If less than 16 then use words */ + mov r2, r3 /* Duplicate data */ + cmp r1, #0x80 /* If < 128 then skip the big loop */ + blt .Lmemset_loop32 + + /* Do 128 bytes at a time */ +.Lmemset_loop128: + subs r1, r1, #0x80 +#ifdef __XSCALE__ + strged r2, [ip], #0x08 + strged r2, [ip], #0x08 + strged r2, [ip], #0x08 + strged r2, [ip], #0x08 + strged r2, [ip], #0x08 + strged r2, [ip], #0x08 + strged r2, [ip], #0x08 + strged r2, [ip], #0x08 + strged r2, [ip], #0x08 + strged r2, [ip], #0x08 + strged r2, [ip], #0x08 + strged r2, [ip], #0x08 + strged r2, [ip], #0x08 + strged r2, [ip], #0x08 + strged r2, [ip], #0x08 + strged r2, [ip], #0x08 +#else + stmgeia ip!, {r2-r3} + stmgeia ip!, {r2-r3} + stmgeia ip!, {r2-r3} + stmgeia ip!, {r2-r3} + stmgeia ip!, {r2-r3} + stmgeia ip!, {r2-r3} + stmgeia ip!, {r2-r3} + stmgeia ip!, {r2-r3} + stmgeia ip!, {r2-r3} + stmgeia ip!, {r2-r3} + stmgeia ip!, {r2-r3} + stmgeia ip!, {r2-r3} + stmgeia ip!, {r2-r3} + stmgeia ip!, {r2-r3} + stmgeia ip!, {r2-r3} + stmgeia ip!, {r2-r3} +#endif + bgt .Lmemset_loop128 +#if defined(__minix) + moveq r0, #0 +#endif + RETc(eq) /* Zero length so just exit */ + + add r1, r1, #0x80 /* Adjust for extra sub */ + + /* Do 32 bytes at a time */ +.Lmemset_loop32: + subs r1, r1, #0x20 +#ifdef __XSCALE__ + strged r2, [ip], #0x08 + strged r2, [ip], #0x08 + strged r2, [ip], #0x08 + strged r2, [ip], #0x08 +#else + stmgeia ip!, {r2-r3} + stmgeia ip!, {r2-r3} + stmgeia ip!, {r2-r3} + stmgeia ip!, {r2-r3} +#endif + bgt .Lmemset_loop32 +#if defined(__minix) + moveq r0, #0 +#endif + RETc(eq) /* Zero length so just exit */ + + adds r1, r1, #0x10 /* Partially adjust for extra sub */ + + /* Deal with 16 bytes or more */ +#ifdef __XSCALE__ + strged r2, [ip], #0x08 + strged r2, [ip], #0x08 +#else + stmgeia ip!, {r2-r3} + stmgeia ip!, {r2-r3} +#endif +#if defined(__minix) + moveq r0, #0 +#endif + RETc(eq) /* Zero length so just exit */ + + addlt r1, r1, #0x10 /* Possibly adjust for extra sub */ + + /* We have at least 4 bytes so copy as words */ +.Lmemset_loop4: + subs r1, r1, #0x04 + strge r3, [ip], #0x04 + bgt .Lmemset_loop4 +#if defined(__minix) + moveq r0, #0 +#endif + RETc(eq) /* Zero length so just exit */ + +#ifdef __XSCALE__ + /* Compensate for 64-bit alignment check */ + adds r1, r1, #0x04 +#if defined(__minix) + moveq r0, #0 +#endif + RETc(eq) + cmp r1, #2 +#else + cmp r1, #-2 +#endif + + strb r3, [ip], #0x01 /* Set 1 byte */ + strgeb r3, [ip], #0x01 /* Set another byte */ + strgtb r3, [ip] /* and a third */ +#if defined(__minix) + mov r0, #0 +#endif + RET /* Exit */ + +.Lmemset_wordunaligned: + rsb r2, r2, #0x004 + strb r3, [ip], #0x01 /* Set 1 byte */ + cmp r2, #0x02 + strgeb r3, [ip], #0x01 /* Set another byte */ + sub r1, r1, r2 + strgtb r3, [ip], #0x01 /* and a third */ + cmp r1, #0x04 /* More than 4 bytes left? */ + bge .Lmemset_wordaligned /* Yup */ + +.Lmemset_lessthanfour: + cmp r1, #0x00 +#if defined(__minix) + moveq r0, #0 +#endif + RETc(eq) /* Zero length so exit */ + strb r3, [ip], #0x01 /* Set 1 byte */ + cmp r1, #0x02 + strgeb r3, [ip], #0x01 /* Set another byte */ + strgtb r3, [ip] /* and a third */ +#if defined(__minix) + mov r0, #0 +#endif + RET /* Exit */ + +#if defined(__minix) +LABEL(memset_fault) /* kernel can send us here */ + mov r0, #0 + RET + +LABEL(memset_fault_in_kernel) /* kernel can send us here */ + mrc p15, 0, r0, c6, c0, 0 /* Read DFAR */ + RET +#endif diff --git a/minix/kernel/arch/earmv6hf/pre_init.c b/minix/kernel/arch/earmv6hf/pre_init.c new file mode 100644 index 000000000..a7c757b8f --- /dev/null +++ b/minix/kernel/arch/earmv6hf/pre_init.c @@ -0,0 +1,426 @@ +#define UNPAGED 1 /* for proper kmain() prototype */ + +#include "kernel/kernel.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "string.h" +#include "arch_proto.h" +#include "direct_utils.h" +#include "bsp_serial.h" +#include "glo.h" +#include + +#if USE_SYSDEBUG +#define MULTIBOOT_VERBOSE 1 +#endif + +/* to-be-built kinfo struct, diagnostics buffer */ +kinfo_t kinfo; +struct kmessages kmessages; + +/* pg_utils.c uses this; in this phase, there is a 1:1 mapping. */ +phys_bytes vir2phys(void *addr) { return (phys_bytes) addr; } + +static void setup_mbi(multiboot_info_t *mbi, char *bootargs); + +/* String length used for mb_itoa */ +#define ITOA_BUFFER_SIZE 20 + +/* Kernel may use memory */ +int kernel_may_alloc = 1; + +/* kernel bss */ +extern u32_t _edata; +extern u32_t _end; + +/* kernel unpaged bss */ +extern char _kern_unpaged_edata; +extern char _kern_unpaged_end; + +/** + * + * The following function combines a few things together + * that can well be done using standard libc like strlen/strstr + * and such but these are not available in pre_init stage. + * + * The function expects content to be in the form of space separated + * key value pairs. + * param content the contents to search in + * param key the key to find (this *should* include the key/value delimiter) + * param value a pointer to an initialized char * of at least value_max_len length + * param value_max_len the maximum length of the value to store in value including + * the end char + * +**/ +int find_value(char * content,char * key,char *value,int value_max_len){ + + char *iter,*keyp; + int key_len,content_len,match_len,value_len; + + /* return if the input is invalid */ + if (key == NULL || content == NULL || value == NULL) { + return 1; + } + + /* find the key and content length */ + key_len = content_len =0; + for(iter = key ; *iter != '\0'; iter++, key_len++); + for(iter = content ; *iter != '\0'; iter++, content_len++); + + /* return if key or content length invalid */ + if (key_len == 0 || content_len == 0) { + return 1; + } + + /* now find the key in the contents */ + match_len =0; + for (iter = content ,keyp=key; match_len < key_len && *iter != '\0' ; iter++) { + if (*iter == *keyp) { + match_len++; + keyp++; + continue; + } + /* The current key does not match the value , reset */ + match_len =0; + keyp=key; + } + + if (match_len == key_len) { + printf("key found at %d %s\n", match_len, &content[match_len]); + value_len = 0; + /* copy the content to the value char iter already points to the first + char value */ + while(*iter != '\0' && *iter != ' ' && value_len + 1< value_max_len) { + *value++ = *iter++; + value_len++; + } + *value='\0'; + return 0; + } + return 1; /* not found */ +} + +static int mb_set_param(char *bigbuf,char *name,char *value, kinfo_t *cbi) +{ + /* bigbuf contains a list of key=value pairs separated by \0 char. + * The list itself is ended by a second \0 terminator*/ + char *p = bigbuf; + char *bufend = bigbuf + MULTIBOOT_PARAM_BUF_SIZE; + char *q; + int namelen = strlen(name); + int valuelen = strlen(value); + + /* Some variables we recognize */ + if(!strcmp(name, SERVARNAME)) { cbi->do_serial_debug = 1; } + if(!strcmp(name, SERBAUDVARNAME)) { cbi->serial_debug_baud = atoi(value); } + + /* Delete the item if already exists */ + while (*p) { + if (strncmp(p, name, namelen) == 0 && p[namelen] == '=') { + q = p; + /* let q point to the end of the entry */ + while (*q) q++; + /* now copy the remained of the buffer */ + for (q++; q < bufend; q++, p++) + *p = *q; + break; + } + + /* find the end of the buffer */ + while (*p++); + p++; + } + + + /* find the first empty spot */ + for (p = bigbuf; p < bufend && (*p || *(p + 1)); p++); + + /* unless we are the first entry step over the delimiter */ + if (p > bigbuf) p++; + + /* Make sure there's enough space for the new parameter */ + if (p + namelen + valuelen + 3 > bufend) { + return -1; + } + + strcpy(p, name); + p[namelen] = '='; + strcpy(p + namelen + 1, value); + p[namelen + valuelen + 1] = 0; + p[namelen + valuelen + 2] = 0; /* end with a second delimiter */ + return 0; +} + +int overlaps(multiboot_module_t *mod, int n, int cmp_mod) +{ + multiboot_module_t *cmp = &mod[cmp_mod]; + int m; + +#define INRANGE(mod, v) ((v) >= mod->mod_start && (v) <= thismod->mod_end) +#define OVERLAP(mod1, mod2) (INRANGE(mod1, mod2->mod_start) || \ + INRANGE(mod1, mod2->mod_end)) + for(m = 0; m < n; m++) { + multiboot_module_t *thismod = &mod[m]; + if(m == cmp_mod) continue; + if(OVERLAP(thismod, cmp)) { + return 1; + } + } + return 0; +} + +/* XXX: hard-coded stuff for modules */ +#define MB_MODS_NR NR_BOOT_MODULES +#define MB_MODS_BASE 0x82000000 +#define MB_MODS_ALIGN 0x00800000 /* 8 MB */ +#define MB_MMAP_START 0x80000000 +#define MB_MMAP_SIZE 0x10000000 /* 256 MB */ + +multiboot_module_t mb_modlist[MB_MODS_NR]; +multiboot_memory_map_t mb_memmap; + +void setup_mbi(multiboot_info_t *mbi, char *bootargs) +{ + memset(mbi, 0, sizeof(*mbi)); + mbi->flags = MULTIBOOT_INFO_MODS | MULTIBOOT_INFO_MEM_MAP | + MULTIBOOT_INFO_CMDLINE; + mbi->mi_mods_count = MB_MODS_NR; + mbi->mods_addr = (u32_t)&mb_modlist; + + int i; + for (i = 0; i < MB_MODS_NR; ++i) { + mb_modlist[i].mod_start = MB_MODS_BASE + i * MB_MODS_ALIGN; + mb_modlist[i].mod_end = mb_modlist[i].mod_start + MB_MODS_ALIGN + - ARM_PAGE_SIZE; + mb_modlist[i].cmdline = 0; + } + + /* morph the bootargs into multiboot */ + mbi->cmdline = (u32_t) bootargs; + + mbi->mmap_addr =(u32_t)&mb_memmap; + mbi->mmap_length = sizeof(mb_memmap); + + mb_memmap.size = sizeof(multiboot_memory_map_t); + mb_memmap.mm_base_addr = MB_MMAP_START; + mb_memmap.mm_length = MB_MMAP_SIZE; + mb_memmap.type = MULTIBOOT_MEMORY_AVAILABLE; +} + +void get_parameters(kinfo_t *cbi, char *bootargs) +{ + multiboot_memory_map_t *mmap; + multiboot_info_t *mbi = &cbi->mbi; + int var_i,value_i, m, k; + char *p; + extern char _kern_phys_base, _kern_vir_base, _kern_size, + _kern_unpaged_start, _kern_unpaged_end; + phys_bytes kernbase = (phys_bytes) &_kern_phys_base, + kernsize = (phys_bytes) &_kern_size; +#define BUF 1024 + static char cmdline[BUF]; + + /* get our own copy of the multiboot info struct and module list */ + setup_mbi(mbi, bootargs); + + /* Set various bits of info for the higher-level kernel. */ + cbi->mem_high_phys = 0; + cbi->user_sp = (vir_bytes) &_kern_vir_base; + cbi->vir_kern_start = (vir_bytes) &_kern_vir_base; + cbi->bootstrap_start = (vir_bytes) &_kern_unpaged_start; + cbi->bootstrap_len = (vir_bytes) &_kern_unpaged_end - + cbi->bootstrap_start; + cbi->kmess = &kmess; + + /* set some configurable defaults */ + cbi->do_serial_debug = 1; + cbi->serial_debug_baud = 115200; + + /* parse boot command line */ + if (mbi->flags&MULTIBOOT_INFO_CMDLINE) { + static char var[BUF]; + static char value[BUF]; + + /* Override values with cmdline argument */ + memcpy(cmdline, (void *) mbi->cmdline, BUF); + p = cmdline; + while (*p) { + var_i = 0; + value_i = 0; + while (*p == ' ') p++; /* skip spaces */ + if (!*p) break; /* is this the end? */ + while (*p && *p != '=' && *p != ' ' && var_i < BUF - 1) + var[var_i++] = *p++ ; + var[var_i] = 0; + if (*p++ != '=') continue; /* skip if not name=value */ + while (*p && *p != ' ' && value_i < BUF - 1) { + value[value_i++] = *p++ ; + } + value[value_i] = 0; + + mb_set_param(cbi->param_buf, var, value, cbi); + } + } + + /* let higher levels know what we are booting on */ + mb_set_param(cbi->param_buf, ARCHVARNAME, (char *)get_board_arch_name(machine.board_id), cbi); + mb_set_param(cbi->param_buf, BOARDVARNAME,(char *)get_board_name(machine.board_id) , cbi); + + + /* round user stack down to leave a gap to catch kernel + * stack overflow; and to distinguish kernel and user addresses + * at a glance (0xf.. vs 0xe..) + */ + cbi->user_sp &= 0xF0000000; + cbi->user_end = cbi->user_sp; + + /* kernel bytes without bootstrap code/data that is currently + * still needed but will be freed after bootstrapping. + */ + kinfo.kernel_allocated_bytes = (phys_bytes) &_kern_size; + kinfo.kernel_allocated_bytes -= cbi->bootstrap_len; + + assert(!(cbi->bootstrap_start % ARM_PAGE_SIZE)); + cbi->bootstrap_len = rounddown(cbi->bootstrap_len, ARM_PAGE_SIZE); + assert(mbi->flags & MULTIBOOT_INFO_MODS); + assert(mbi->mi_mods_count < MULTIBOOT_MAX_MODS); + assert(mbi->mi_mods_count > 0); + memcpy(&cbi->module_list, (void *) mbi->mods_addr, + mbi->mi_mods_count * sizeof(multiboot_module_t)); + + memset(cbi->memmap, 0, sizeof(cbi->memmap)); + /* mem_map has a variable layout */ + if(mbi->flags & MULTIBOOT_INFO_MEM_MAP) { + cbi->mmap_size = 0; + for (mmap = (multiboot_memory_map_t *) mbi->mmap_addr; + (unsigned long) mmap < mbi->mmap_addr + mbi->mmap_length; + mmap = (multiboot_memory_map_t *) + ((unsigned long) mmap + mmap->size + sizeof(mmap->size))) { + if(mmap->type != MULTIBOOT_MEMORY_AVAILABLE) continue; + add_memmap(cbi, mmap->mm_base_addr, mmap->mm_length); + } + } else { + assert(mbi->flags & MULTIBOOT_INFO_MEMORY); + add_memmap(cbi, 0, mbi->mem_lower_unused*1024); + add_memmap(cbi, 0x100000, mbi->mem_upper_unused*1024); + } + + /* Sanity check: the kernel nor any of the modules may overlap + * with each other. Pretend the kernel is an extra module for a + * second. + */ + k = mbi->mi_mods_count; + assert(k < MULTIBOOT_MAX_MODS); + cbi->module_list[k].mod_start = kernbase; + cbi->module_list[k].mod_end = kernbase + kernsize; + cbi->mods_with_kernel = mbi->mi_mods_count+1; + cbi->kern_mod = k; + + for(m = 0; m < cbi->mods_with_kernel; m++) { +#if 0 + printf("checking overlap of module %08lx-%08lx\n", + cbi->module_list[m].mod_start, cbi->module_list[m].mod_end); +#endif + if(overlaps(cbi->module_list, cbi->mods_with_kernel, m)) + panic("overlapping boot modules/kernel"); + /* We cut out the bits of memory that we know are + * occupied by the kernel and boot modules. + */ + cut_memmap(cbi, + cbi->module_list[m].mod_start, + cbi->module_list[m].mod_end); + } +} + +/* + * During low level init many things are not supposed to work + * serial being one of them. We therefore can't rely on the + * serial to debug. POORMANS_FAILURE_NOTIFICATION can be used + * before we setup our own vector table and will result in calling + * the bootloader's debugging methods that will hopefully show some + * information like the currnet PC at on the serial. + */ +#define POORMANS_FAILURE_NOTIFICATION asm volatile("svc #00\n") + +/* use the passed cmdline argument to determine the machine id */ +void set_machine_id(char *cmdline) +{ + + char boardname[20]; + memset(boardname,'\0',20); + if (find_value(cmdline,"board_name=",boardname,20)){ + /* we expect the bootloader to pass a board_name as argument + * this however did not happen and given we still are in early + * boot we can't use the serial. We therefore generate an interrupt + * and hope the bootloader will do something nice with it */ + POORMANS_FAILURE_NOTIFICATION; + } + machine.board_id = get_board_id_by_short_name(boardname); + + if (machine.board_id ==0){ + /* same thing as above there is no safe escape */ + POORMANS_FAILURE_NOTIFICATION; + } +} + +kinfo_t *pre_init(int argc, char **argv) +{ + char *bootargs; + /* This is the main "c" entry point into the kernel. It gets called + from head.S */ + + /* Clear BSS */ + memset(&_edata, 0, (u32_t)&_end - (u32_t)&_edata); + memset(&_kern_unpaged_edata, 0, (u32_t)&_kern_unpaged_end - (u32_t)&_kern_unpaged_edata); + + /* we get called in a c like fashion where the first arg + * is the program name (load address) and the rest are + * arguments. by convention the second argument is the + * command line */ + if (argc != 2) { + POORMANS_FAILURE_NOTIFICATION; + } + + bootargs = argv[1]; + set_machine_id(bootargs); + bsp_ser_init(); + /* Get our own copy boot params pointed to by ebx. + * Here we find out whether we should do serial output. + */ + get_parameters(&kinfo, bootargs); + + /* Make and load a pagetable that will map the kernel + * to where it should be; but first a 1:1 mapping so + * this code stays where it should be. + */ + dcache_clean(); /* clean the caches */ + pg_clear(); + pg_identity(&kinfo); + kinfo.freepde_start = pg_mapkernel(); + pg_load(); + vm_enable_paging(); + + /* Done, return boot info so it can be passed to kmain(). */ + return &kinfo; +} + +/* pre_init gets executed at the memory location where the kernel was loaded by the boot loader. + * at that stage we only have a minimum set of functionality present (all symbols gets renamed to + * ensure this). The following methods are used in that context. Once we jump to kmain they are no + * longer used and the "real" implementations are visible + */ +void send_diag_sig(void) { } +void minix_shutdown(minix_timer_t *t) { arch_shutdown(0); } +void busy_delay_ms(int x) { } +int raise(int n) { panic("raise(%d)\n", n); } +int kern_phys_map_ptr( phys_bytes base_address, vir_bytes io_size, int vm_flags, +struct kern_phys_map * priv, vir_bytes ptr) {}; +struct machine machine; /* pre init stage machine */ diff --git a/minix/kernel/arch/earmv6hf/procoffsets.cf b/minix/kernel/arch/earmv6hf/procoffsets.cf new file mode 100644 index 000000000..c64213c78 --- /dev/null +++ b/minix/kernel/arch/earmv6hf/procoffsets.cf @@ -0,0 +1,24 @@ + +include "kernel/kernel.h" +include "kernel/proc.h" + +struct proc +member REG0 p_reg.retreg +member REG1 p_reg.r1 +member REG2 p_reg.r2 +member REG3 p_reg.r3 +member REG4 p_reg.r4 +member REG5 p_reg.r5 +member REG6 p_reg.r6 +member REG7 p_reg.r7 +member REG8 p_reg.r8 +member REG9 p_reg.r9 +member REG10 p_reg.r10 +member FPREG p_reg.fp +member REG12 p_reg.r12 +member SPREG p_reg.sp +member LRREG p_reg.lr +member PCREG p_reg.pc +member PSREG p_reg.psr +member P_TTBR p_seg.p_ttbr + diff --git a/minix/kernel/arch/earmv6hf/protect.c b/minix/kernel/arch/earmv6hf/protect.c new file mode 100644 index 000000000..b63b09ae3 --- /dev/null +++ b/minix/kernel/arch/earmv6hf/protect.c @@ -0,0 +1,183 @@ +/* This file contains code for initialization of protected mode, to initialize + * code and data segment descriptors, and to initialize global descriptors + * for local descriptors in the process table. + */ + +#include +#include + +#include + +#include "kernel/kernel.h" + +#include "archconst.h" +#include "arch_proto.h" + +#include +#include + +struct tss_s tss[CONFIG_MAX_CPUS]; +extern int exc_vector_table; + +int prot_init_done = 0; + +phys_bytes vir2phys(void *vir) +{ + /* defined in kernel.lds */ + extern char _kern_vir_base, _kern_phys_base; + u32_t offset = (vir_bytes) &_kern_vir_base - + (vir_bytes) &_kern_phys_base; + return (phys_bytes)vir - offset; +} + +int tss_init(unsigned cpu, void * kernel_stack) +{ + + struct tss_s * t = &tss[cpu]; + + /* + * make space for process pointer and cpu id and point to the first + * usable word + */ + t->sp0 = ((unsigned) kernel_stack) - ARM_STACK_TOP_RESERVED; + /* + * set the cpu id at the top of the stack so we know on which cpu is + * this stak in use when we trap to kernel + */ + *((reg_t *)(t->sp0 + 1 * sizeof(reg_t))) = cpu; + + return 0; +} + +multiboot_module_t *bootmod(int pnr) +{ + int i; + + assert(pnr >= 0); + + /* Search for desired process in boot process + * list. The first NR_TASKS ones do not correspond + * to a module, however, so we don't search those. + */ + for(i = NR_TASKS; i < NR_BOOT_PROCS; i++) { + int p; + p = i - NR_TASKS; + if(image[i].proc_nr == pnr) { + assert(p < MULTIBOOT_MAX_MODS); + assert(p < kinfo.mbi.mi_mods_count); + return &kinfo.module_list[p]; + } + } + + panic("boot module %d not found", pnr); +} + +int booting_cpu = 0; + +void prot_init() +{ + /* tell the HW where we stored our vector table */ + write_vbar((reg_t)&exc_vector_table); + + /* Set up a new post-relocate bootstrap pagetable so that + * we can map in VM, and we no longer rely on pre-relocated + * data. + */ + + pg_clear(); + pg_identity(&kinfo); /* Still need 1:1 for device memory . */ + pg_mapkernel(); + pg_load(); + + prot_init_done = 1; +} + +static int alloc_for_vm = 0; + +void arch_post_init(void) +{ + /* Let memory mapping code know what's going on at bootstrap time */ + struct proc *vm; + vm = proc_addr(VM_PROC_NR); + get_cpulocal_var(ptproc) = vm; + pg_info(&vm->p_seg.p_ttbr, &vm->p_seg.p_ttbr_v); +} + +static int libexec_pg_alloc(struct exec_info *execi, vir_bytes vaddr, size_t len) +{ + pg_map(PG_ALLOCATEME, vaddr, vaddr+len, &kinfo); + pg_load(); + memset((char *) vaddr, 0, len); + alloc_for_vm += len; + return OK; +} + +void arch_boot_proc(struct boot_image *ip, struct proc *rp) +{ + multiboot_module_t *mod; + struct ps_strings *psp; + char *sp; + + if(rp->p_nr < 0) return; + + mod = bootmod(rp->p_nr); + + /* Important special case: we put VM in the bootstrap pagetable + * so it can run. + */ + + if(rp->p_nr == VM_PROC_NR) { + struct exec_info execi; + + memset(&execi, 0, sizeof(execi)); + + /* exec parameters */ + execi.stack_high = kinfo.user_sp; + execi.stack_size = 64 * 1024; /* not too crazy as it must be preallocated */ + execi.proc_e = ip->endpoint; + execi.hdr = (char *) mod->mod_start; /* phys mem direct */ + execi.filesize = execi.hdr_len = mod->mod_end - mod->mod_start; + strlcpy(execi.progname, ip->proc_name, sizeof(execi.progname)); + execi.frame_len = 0; + + /* callbacks for use in the kernel */ + execi.copymem = libexec_copy_memcpy; + execi.clearmem = libexec_clear_memset; + execi.allocmem_prealloc_junk = libexec_pg_alloc; + execi.allocmem_prealloc_cleared = libexec_pg_alloc; + execi.allocmem_ondemand = libexec_pg_alloc; + execi.clearproc = NULL; + + /* parse VM ELF binary and alloc/map it into bootstrap pagetable */ + if(libexec_load_elf(&execi) != OK) + panic("VM loading failed"); + + /* Setup a ps_strings struct on the stack, pointing to the + * following argv, envp. */ + sp = (char *)execi.stack_high; + sp -= sizeof(struct ps_strings); + psp = (struct ps_strings *) sp; + + /* Take the stack pointer down three words to give startup code + * something to use as "argc", "argv" and "envp". + */ + sp -= (sizeof(void *) + sizeof(void *) + sizeof(int)); + + // linear address space, so it is available. + psp->ps_argvstr = (char **)(sp + sizeof(int)); + psp->ps_nargvstr = 0; + psp->ps_envstr = psp->ps_argvstr + sizeof(void *); + psp->ps_nenvstr = 0; + + arch_proc_init(rp, execi.pc, (vir_bytes)sp, + execi.stack_high - sizeof(struct ps_strings), + ip->proc_name); + + /* Free VM blob that was just copied into existence. */ + add_memmap(&kinfo, mod->mod_start, mod->mod_end-mod->mod_start); + mod->mod_end = mod->mod_start = 0; + + /* Remember them */ + kinfo.vm_allocated_bytes = alloc_for_vm; + } +} diff --git a/minix/kernel/arch/earmv6hf/sconst.h b/minix/kernel/arch/earmv6hf/sconst.h new file mode 100644 index 000000000..6282717ab --- /dev/null +++ b/minix/kernel/arch/earmv6hf/sconst.h @@ -0,0 +1,7 @@ +#ifndef __SCONST_H__ +#define __SCONST_H__ + +#include "kernel/const.h" +#include "kernel/procoffsets.h" + +#endif /* __SCONST_H__ */ diff --git a/minix/kernel/arch/earmv6hf/timer.h b/minix/kernel/arch/earmv6hf/timer.h new file mode 100644 index 000000000..df911b57b --- /dev/null +++ b/minix/kernel/arch/earmv6hf/timer.h @@ -0,0 +1,7 @@ + +#ifndef _KERN_TIMER_H +#define _KERN_TIMER_H + +#include "omap_timer.h" + +#endif diff --git a/minix/lib/Makefile b/minix/lib/Makefile index 752269a51..6adec86a6 100644 --- a/minix/lib/Makefile +++ b/minix/lib/Makefile @@ -39,7 +39,7 @@ SUBDIR+= libvboxfs SUBDIR+= libvirtio .endif -.if (${MACHINE_ARCH} == "earm") +.if ((${MACHINE_ARCH} == "earm") || (${MACHINE_ARCH} == "earmv6hf") ) SUBDIR+= libclkconf SUBDIR+= libgpio SUBDIR+= libi2cdriver diff --git a/minix/lib/libminc/arch/earmv6hf/Makefile.libc.inc b/minix/lib/libminc/arch/earmv6hf/Makefile.libc.inc new file mode 100644 index 000000000..2fd3cac48 --- /dev/null +++ b/minix/lib/libminc/arch/earmv6hf/Makefile.libc.inc @@ -0,0 +1,99 @@ +######################################################################## +# +# Shared libc with userspace (/common/lib/libc) +# + +.for f in \ + memchr.o +${f}: ${LIBCOMMONCDIR}/string/${f:C/\.o/.c/} +OBJS+= ${f} +CLEANFILES+= ${f} +.endfor + +.for f in \ + byte_swap_2.o byte_swap_4.o divsi3.o divide.o udivsi3.o +${f}: ${LIBCOMMONCARCHDIR}/gen/${f:C/\.o/.S/} +OBJS+= ${f} +CLEANFILES+= ${f} +.endfor + +CPPFLAGS.byte_swap_4.S+= -D_STANDALONE + +.for f in \ + __aeabi_idiv0.o __aeabi_ldiv0.o +${f}: ${LIBCOMMONCARCHDIR}/gen/${f:C/\.o/.c/} +OBJS+= ${f} +CLEANFILES+= ${f} +.endfor + +CPPFLAGS.__aeabi_idiv0.c+= -D_STANDALONE +CPPFLAGS.__aeabi_ldiv0.c+= -D_STANDALONE + +.for f in \ + __aeabi_ldivmod.o __aeabi_uldivmod.o +${f}: ${LIBCOMMONCARCHDIR}/quad/${f:C/\.o/.S/} +OBJS+= ${f} +CLEANFILES+= ${f} +.endfor + +.for f in \ + memcmp.o memcpy.o memmove.o memset.o \ + strcat.o strchr.o strcmp.o strcpy.o strlcpy.o strlen.o strncpy.o \ + strncmp.o strrchr.o strcpy_arm.o +${f}: ${LIBCOMMONCARCHDIR}/string/${f:C/\.o/.S/} +OBJS+= ${f} +CLEANFILES+= ${f} +.endfor + +CPPFLAGS.strcpy_arm.S+= -DSTRLCPY -D_LIBC + +######################################################################## +# +# Functions imported directly from libc. +# +.for f in \ + alloca.o +${f}: ${LIBCARCHDIR}/gen/${f:C/\.o/.S/} +OBJS+= ${f} +CLEANFILES+= ${f} +.endfor + +.for f in \ + __aeabi_dcmpeq.o __aeabi_fcmpeq.o \ + __aeabi_dcmpge.o __aeabi_fcmpge.o \ + __aeabi_dcmpgt.o __aeabi_fcmpgt.o \ + __aeabi_dcmple.o __aeabi_fcmple.o \ + __aeabi_dcmplt.o __aeabi_fcmplt.o \ + __aeabi_dcmpun.o __aeabi_fcmpun.o +CPPFLAGS.${f:C/\.o/.c/}+= -I${LIBCARCHDIR}/softfloat -I${LIBCDIR}/softfloat +CPPFLAGS.${f:C/\.o/.c/}+= -DSOFTFLOAT_FOR_GCC +${f}: ${LIBCARCHDIR}/softfloat/${f:C/\.o/.c/} +OBJS+= ${f} +CLEANFILES+= ${f} +.endfor + +.for f in \ + fpgetround.o fpsetround.o fpgetmask.o fpsetmask.o \ + fpgetsticky.o fpsetsticky.o +CPPFLAGS.${f:C/\.o/.c/}+= -I${LIBCARCHDIR}/softfloat -I${LIBCDIR}/softfloat +CPPFLAGS.${f:C/\.o/.c/}+= -DSOFTFLOAT_FOR_GCC +${f}: ${LIBCDIR}/softfloat/${f:C/\.o/.c/} +OBJS+= ${f} +CLEANFILES+= ${f} +.endfor + +SOFTFLOAT_BITS?=64 +.for f in \ + softfloat.o +CPPFLAGS.${f:C/\.o/.c/}+= -I${LIBCARCHDIR}/softfloat -I${LIBCDIR}/softfloat +CPPFLAGS.${f:C/\.o/.c/}+= -DSOFTFLOAT_FOR_GCC +${f}: ${LIBCDIR}/softfloat/bits${SOFTFLOAT_BITS}/${f:C/\.o/.c/} +OBJS+= ${f} +CLEANFILES+= ${f} +.endfor + +.if defined(HAVE_GCC) && ${HAVE_GCC} >= 45 +.if (${MACHINE_CPU} == "arm") +COPTS.softfloat.c+= -Wno-enum-compare -fno-tree-vrp +.endif +.endif diff --git a/minix/lib/libsys/arch/earmv6hf/Makefile.inc b/minix/lib/libsys/arch/earmv6hf/Makefile.inc new file mode 100644 index 000000000..55fd2bced --- /dev/null +++ b/minix/lib/libsys/arch/earmv6hf/Makefile.inc @@ -0,0 +1,15 @@ +# Makefile for arch-dependent libsys code +.include + +HERE=${.CURDIR}/arch/${MACHINE_ARCH} +.PATH: ${HERE} + +SRCS+= \ + frclock_util.c \ + spin.c \ + tsc_util.c + +CPPFLAGS+= -I${HERE}/../../ +CPPFLAGS+= -I${NETBSDSRCDIR} -I${NETBSDSRCDIR}/kernel/arch/${MACHINE_ARCH}/ + + diff --git a/minix/lib/libsys/arch/earmv6hf/frclock_util.c b/minix/lib/libsys/arch/earmv6hf/frclock_util.c new file mode 100644 index 000000000..086be43bc --- /dev/null +++ b/minix/lib/libsys/arch/earmv6hf/frclock_util.c @@ -0,0 +1,92 @@ +/* Some utility functions around the free running clock on ARM. The clock is + * 32-bits wide, but we provide 64-bit wrapper functions to make it look + * similar to the read_tsc functions. On hardware we could actually make use + * of the timer overflow counter, but emulator doesn't emulate it. */ + +#include +#include +#include +#include +#include +#include + +#define MICROHZ 1000000ULL /* number of micros per second */ +#define MICROSPERTICK(h) (MICROHZ/(h)) /* number of micros per HZ tick */ + +static u64_t Hz; + +extern struct minix_kerninfo *_minix_kerninfo; + +int +micro_delay(u32_t micros) +{ + u64_t start, delta, delta_end; + + Hz = sys_hz(); + + /* Start of delay. */ + read_frclock_64(&start); + assert(_minix_kerninfo->minix_arm_frclock_hz); + delta_end = (_minix_kerninfo->minix_arm_frclock_hz * micros) / MICROHZ; + + /* If we have to wait for at least one HZ tick, use the regular + * tickdelay first. Round downwards on purpose, so the average + * half-tick we wait short (depending on where in the current tick + * we call tickdelay). We can correct for both overhead of tickdelay + * itself and the short wait in the busywait later. + */ + if (micros >= MICROSPERTICK(Hz)) + tickdelay(micros*Hz/MICROHZ); + + /* Wait (the rest) of the delay time using busywait. */ + do { + read_frclock_64(&delta); + } while (delta_frclock_64(start, delta) < delta_end); + + + return 0; +} + +u32_t frclock_64_to_micros(u64_t tsc) +{ + return (u32_t) (tsc / (_minix_kerninfo->minix_arm_frclock_hz / MICROHZ)); +} + +void +read_frclock(u32_t *frclk) +{ + assert(frclk); + assert(_minix_kerninfo->minix_frclock_tcrr); + assert(_minix_kerninfo->minix_arm_frclock_hz); + *frclk = *(volatile u32_t *)((u8_t *) _minix_kerninfo->minix_frclock_tcrr); +} + +u32_t +delta_frclock(u32_t base, u32_t cur) +{ + u32_t delta; + + if (cur < base) { + /* We have wrapped around, so delta is base to wrapping point + * plus starting point (0) to cur. This supports wrapping once + * only. */ + delta = (UINT_MAX - base) + cur; + } else { + delta = cur - base; + } + + return delta; +} + +void +read_frclock_64(u64_t *frclk) +{ + read_frclock((u32_t *) frclk); +} + +u64_t +delta_frclock_64(u64_t base, u64_t cur) +{ + return (u64_t) delta_frclock((u32_t) base, (u32_t) cur); +} + diff --git a/minix/lib/libsys/arch/earmv6hf/spin.c b/minix/lib/libsys/arch/earmv6hf/spin.c new file mode 100644 index 000000000..967f2a68d --- /dev/null +++ b/minix/lib/libsys/arch/earmv6hf/spin.c @@ -0,0 +1,98 @@ +/* Helper functions that allow driver writers to easily busy-wait (spin) for a + * condition to become satisfied within a certain maximum time span. + */ +/* This implementation first spins without making any system calls for a + * while, and then starts using system calls (specifically, the system call to + * obtain the current time) while spinning. The reason for this is that in + * many cases, the condition to be checked will become satisfied rather + * quickly, and we want to avoid getting descheduled in that case. However, + * after a while, running out of scheduling quantum will cause our priority to + * be lowered, and we can avoid this by voluntarily giving up the CPU, by + * making a system call. + */ +#include "sysutil.h" +#include +#include + +/* Number of microseconds to keep spinning initially, without performing a + * system call. We pick a value somewhat smaller than a typical clock tick. + * Note that for the above reasons, we want to avoid using sys_hz() here. + */ +#define TSC_SPIN 1000 /* in microseconds */ + +/* Internal spin states. */ +enum { + STATE_INIT, /* simply check the condition (once) */ + STATE_BASE_TS, /* get the initial TSC value (once) */ + STATE_TS, /* use the TSC to spin (up to TSC_SPIN us) */ + STATE_UPTIME /* use the clock to spin */ +}; + +void spin_init(spin_t *s, u32_t usecs) +{ + /* Initialize the given spin state structure, set to spin at most the + * given number of microseconds. + */ + s->s_state = STATE_INIT; + s->s_usecs = usecs; + s->s_timeout = FALSE; +} + +int spin_check(spin_t *s) +{ + /* Check whether a timeout has taken place. Return TRUE if the caller + * should continue spinning, and FALSE if a timeout has occurred. The + * implementation assumes that it is okay to spin a little bit too long + * (up to a full clock tick extra). + */ + u64_t cur_tsc, tsc_delta; + clock_t now, micro_delta; + + switch (s->s_state) { + case STATE_INIT: + s->s_state = STATE_BASE_TS; + break; + + case STATE_BASE_TS: + s->s_state = STATE_TS; + read_frclock_64(&s->s_base_tsc); + break; + + case STATE_TS: + read_frclock_64(&cur_tsc); + tsc_delta = delta_frclock_64(s->s_base_tsc, cur_tsc); + micro_delta = frclock_64_to_micros(tsc_delta); + + if (micro_delta >= s->s_usecs) { + s->s_timeout = TRUE; + return FALSE; + } + + if (micro_delta >= TSC_SPIN) { + s->s_usecs -= micro_delta; + getticks(&s->s_base_uptime); + s->s_state = STATE_UPTIME; + } + + break; + + case STATE_UPTIME: + getticks(&now); + + /* We assume that sys_hz() caches its return value. */ + micro_delta = ((now - s->s_base_uptime) * 1000 / sys_hz()) * + 1000; + + if (micro_delta >= s->s_usecs) { + s->s_timeout = TRUE; + return FALSE; + } + + break; + + default: + panic("spin_check: invalid state %d", s->s_state); + } + + return TRUE; +} diff --git a/minix/lib/libsys/arch/earmv6hf/tsc_util.c b/minix/lib/libsys/arch/earmv6hf/tsc_util.c new file mode 100644 index 000000000..4f973e9a1 --- /dev/null +++ b/minix/lib/libsys/arch/earmv6hf/tsc_util.c @@ -0,0 +1,35 @@ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sysutil.h" + +#ifndef CONFIG_MAX_CPUS +#define CONFIG_MAX_CPUS 1 +#endif + +#define MICROHZ 1000000 /* number of micros per second */ +#define MICROSPERTICK(h) (MICROHZ/(h)) /* number of micros per HZ tick */ + +static u32_t calib_hz = 600000000; + +u32_t tsc_64_to_micros(u64_t tsc) +{ + u64_t tmp; + + tmp = tsc / calib_hz; + return (u32_t) tmp; +} + +u32_t tsc_to_micros(u32_t low, u32_t high) +{ + return tsc_64_to_micros(make64(low, high)); +} + diff --git a/minix/servers/vm/Makefile b/minix/servers/vm/Makefile index b79f21741..88d1c6590 100644 --- a/minix/servers/vm/Makefile +++ b/minix/servers/vm/Makefile @@ -8,7 +8,7 @@ SRCS= main.c alloc.c utility.c exit.c fork.c break.c \ mem_anon.c mem_directphys.c mem_anon_contig.c mem_shared.c \ mem_cache.c cache.c vfs.c mem_file.c fdref.c acl.c -.if ${MACHINE_ARCH} == "earm" +.if ((${MACHINE_ARCH} == "earm") || (${MACHINE_ARCH} == "earmv6hf") ) LDFLAGS+= -T ${.CURDIR}/arch/${MACHINE_ARCH}/vm.lds .endif diff --git a/minix/servers/vm/arch/earmv6hf/Makefile.inc b/minix/servers/vm/arch/earmv6hf/Makefile.inc new file mode 100644 index 000000000..27456c4b8 --- /dev/null +++ b/minix/servers/vm/arch/earmv6hf/Makefile.inc @@ -0,0 +1,4 @@ +.include + +#Arch-specific sources +.PATH: ${.CURDIR}/arch/${MACHINE_ARCH} diff --git a/minix/servers/vm/arch/earmv6hf/pagetable.h b/minix/servers/vm/arch/earmv6hf/pagetable.h new file mode 100644 index 000000000..ce22ab569 --- /dev/null +++ b/minix/servers/vm/arch/earmv6hf/pagetable.h @@ -0,0 +1,52 @@ + +#ifndef _PAGETABLE_H +#define _PAGETABLE_H 1 + +#include +#include + +#include "vm.h" + +/* Mapping flags. */ +#define PTF_WRITE ARM_VM_PTE_RW +#define PTF_READ ARM_VM_PTE_RO +#define PTF_PRESENT ARM_VM_PTE_PRESENT +#define PTF_SUPER ARM_VM_PTE_SUPER +#define PTF_USER ARM_VM_PTE_USER +#define PTF_NOCACHE ARM_VM_PTE_DEVICE +#define PTF_CACHEWB ARM_VM_PTE_WB +#define PTF_CACHEWT ARM_VM_PTE_WT +#define PTF_SHARE ARM_VM_PTE_S + +#define ARCH_VM_DIR_ENTRIES ARM_VM_DIR_ENTRIES +#define ARCH_BIG_PAGE_SIZE ARM_SECTION_SIZE +#define ARCH_VM_ADDR_MASK ARM_VM_ADDR_MASK +#define ARCH_VM_PDE_MASK ARM_VM_PDE_MASK +#define ARCH_VM_PDE_PRESENT ARM_VM_PDE_PRESENT +#define ARCH_VM_PTE_PRESENT ARM_VM_PTE_PRESENT +#define ARCH_VM_PTE_USER ARM_VM_PTE_USER +#define ARCH_PAGEDIR_SIZE ARM_PAGEDIR_SIZE +#define ARCH_VM_PTE_RW ARM_VM_PTE_RW +#define ARCH_VM_BIGPAGE ARM_VM_SECTION +#define ARCH_VM_PT_ENTRIES ARM_VM_PT_ENTRIES +#define ARCH_VM_PTE_RO ARM_VM_PTE_RO + +/* For arch-specific PT routines to check if no bits outside + * the regular flags are set. + */ +#define PTF_ALLFLAGS (PTF_READ|PTF_WRITE|PTF_PRESENT|PTF_SUPER|PTF_USER|PTF_NOCACHE|PTF_CACHEWB|PTF_CACHEWT|PTF_SHARE) + +#define PFERR_PROT(e) ((ARM_VM_PFE_FS(e) == ARM_VM_PFE_L1PERM) \ + || (ARM_VM_PFE_FS(e) == ARM_VM_PFE_L2PERM)) +#define PFERR_NOPAGE(e) (!PFERR_PROT(e)) +#define PFERR_WRITE(e) ((e) & ARM_VM_PFE_W) +#define PFERR_READ(e) (!((e) & ARM_VM_PFE_W)) + +#define VM_PAGE_SIZE ARM_PAGE_SIZE + +/* virtual address -> pde, pte macros */ +#define ARCH_VM_PTE(v) ARM_VM_PTE(v) +#define ARCH_VM_PDE(v) ARM_VM_PDE(v) + +#endif + diff --git a/minix/servers/vm/arch/earmv6hf/vm.lds b/minix/servers/vm/arch/earmv6hf/vm.lds new file mode 100644 index 000000000..0339c73ef --- /dev/null +++ b/minix/servers/vm/arch/earmv6hf/vm.lds @@ -0,0 +1,249 @@ +/* Script for -z combreloc: combine and sort reloc sections */ +OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", + "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SEARCH_DIR("=/usr/local/lib"); SEARCH_DIR("=/lib"); SEARCH_DIR("=/usr/lib"); +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x8000)); . = SEGMENT_START("text-segment", 0x8000); + .interp : { *(.interp) } + .note.gnu.build-id : { *(.note.gnu.build-id) } + .hash : { *(.hash) } + .gnu.hash : { *(.gnu.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .gnu.version : { *(.gnu.version) } + .gnu.version_d : { *(.gnu.version_d) } + .gnu.version_r : { *(.gnu.version_r) } + .rel.dyn : + { + *(.rel.init) + *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) + *(.rel.fini) + *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) + *(.rel.data.rel.ro* .rel.gnu.linkonce.d.rel.ro.*) + *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) + *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) + *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) + *(.rel.ctors) + *(.rel.dtors) + *(.rel.got) + *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) + PROVIDE_HIDDEN (__rel_iplt_start = .); + *(.rel.iplt) + PROVIDE_HIDDEN (__rel_iplt_end = .); + PROVIDE_HIDDEN (__rela_iplt_start = .); + PROVIDE_HIDDEN (__rela_iplt_end = .); + } + .rela.dyn : + { + *(.rela.init) + *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) + *(.rela.fini) + *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) + *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) + *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) + *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) + *(.rela.ctors) + *(.rela.dtors) + *(.rela.got) + *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) + PROVIDE_HIDDEN (__rel_iplt_start = .); + PROVIDE_HIDDEN (__rel_iplt_end = .); + PROVIDE_HIDDEN (__rela_iplt_start = .); + *(.rela.iplt) + PROVIDE_HIDDEN (__rela_iplt_end = .); + } + .rel.plt : + { + *(.rel.plt) + } + .rela.plt : + { + *(.rela.plt) + } + .init : + { + KEEP (*(.init)) + } =0 + .plt : { *(.plt) } + .iplt : { *(.iplt) } + .text : + { + *(.text.unlikely .text.*_unlikely) + *(.text.exit .text.exit.*) + *(.text.startup .text.startup.*) + *(.text.hot .text.hot.*) + *(.text .stub .text.* .gnu.linkonce.t.*) + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + *(.glue_7t) *(.glue_7) *(.vfp11_veneer) *(.v4_bx) + } =0 + .fini : + { + KEEP (*(.fini)) + } =0 + PROVIDE (__etext = .); + PROVIDE (_etext = .); + PROVIDE (etext = .); + .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } + .rodata1 : { *(.rodata1) } + .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } + PROVIDE_HIDDEN (__exidx_start = .); + .ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) } + PROVIDE_HIDDEN (__exidx_end = .); + .eh_frame_hdr : { *(.eh_frame_hdr) } + .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) } + .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table + .gcc_except_table.*) } + /* These sections are generated by the Sun/Oracle C++ compiler. */ + .exception_ranges : ONLY_IF_RO { *(.exception_ranges + .exception_ranges*) } + /* Adjust the address for the data segment. We want to adjust up to + the same address within the page on the next page up. */ +/* XXX: align on page boundary */ +/* . = ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1));*/ + . = ALIGN(4096); + /* Exception handling */ + .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) } + .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } + .exception_ranges : ONLY_IF_RW { *(.exception_ranges .exception_ranges*) } + /* Thread Local Storage sections */ + .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } + .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + } + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array)) + PROVIDE_HIDDEN (__fini_array_end = .); + } + .ctors : + { + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + /* We don't want to include the .ctor section from + the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } +/* XXX: no jcr, got, etc. + + .jcr : { KEEP (*(.jcr)) } + .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro* .gnu.linkonce.d.rel.ro.*) } + .dynamic : { *(.dynamic) } + .got : { *(.got.plt) *(.igot.plt) *(.got) *(.igot) } +*/ + .data : + { + __data_start = . ; + /* XXX: put pagetable data at beginning */ + pagetable.o(.data) + *(.data .data.* .gnu.linkonce.d.*) + SORT(CONSTRUCTORS) + /* XXX: 16KB align */ + . = ALIGN(16384); + } + .data1 : { *(.data1) } + _edata = .; PROVIDE (edata = .); + __bss_start = .; + __bss_start__ = .; + .bss : + { + /* XXX: put pagetable bss at beginning */ + pagetable.o(.bss) + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + /* Align here to ensure that the .bss section occupies space up to + _end. Align after .bss to ensure correct alignment even if the + .bss section disappears because there are no input sections. + FIXME: Why do we need it? When there is no .bss section, we don't + pad the .data section. */ + . = ALIGN(. != 0 ? 32 / 8 : 1); + } + _bss_end__ = . ; __bss_end__ = . ; + . = ALIGN(32 / 8); + . = ALIGN(32 / 8); + __end__ = . ; + _end = .; PROVIDE (end = .); + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /* DWARF 3 */ + .debug_pubtypes 0 : { *(.debug_pubtypes) } + .debug_ranges 0 : { *(.debug_ranges) } + .stack 0x80000 : + { + _stack = .; + *(.stack) + } + .ARM.attributes 0 : { KEEP (*(.ARM.attributes)) KEEP (*(.gnu.attributes)) } + .note.gnu.arm.ident 0 : { KEEP (*(.note.gnu.arm.ident)) } + /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) } +} diff --git a/minix/share/Makefile b/minix/share/Makefile index df43d38bb..1ccc3b09e 100644 --- a/minix/share/Makefile +++ b/minix/share/Makefile @@ -2,6 +2,9 @@ .if ${MACHINE_ARCH} == "earm" SUBDIR+= beaglebone -.endif # ${MACHINE_ARCH} == "earm" +.endif +.if ${MACHINE_ARCH} == "earmv6hf" +SUBDIR+= rpi +.endif # ${MACHINE_ARCH} == "earmv6hf" .include diff --git a/minix/share/rpi/Makefile b/minix/share/rpi/Makefile new file mode 100644 index 000000000..6f321a88f --- /dev/null +++ b/minix/share/rpi/Makefile @@ -0,0 +1,4 @@ + +SUBDIR+= weather + +.include diff --git a/minix/share/rpi/Makefile.inc b/minix/share/rpi/Makefile.inc new file mode 100644 index 000000000..01b5f2341 --- /dev/null +++ b/minix/share/rpi/Makefile.inc @@ -0,0 +1 @@ +.include "../Makefile.inc" diff --git a/minix/share/rpi/weather/LICENSE b/minix/share/rpi/weather/LICENSE new file mode 100644 index 000000000..89c1bf567 --- /dev/null +++ b/minix/share/rpi/weather/LICENSE @@ -0,0 +1,27 @@ +Original code is based on bonescript by Jason Kridner . +To see the original, checkout the bonescript repository on github +The license for the original code is below, between the dashes. Minix changes +Copyright (c) 2013 Thomas Cort (same license applies). +spin.js, jQuery and Processing.js are under MIT license. + +------------------------------------------------------------------------------- +Copyright (c) 2011 Jason Kridner + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------- diff --git a/minix/share/rpi/weather/Makefile b/minix/share/rpi/weather/Makefile new file mode 100644 index 000000000..19c530d81 --- /dev/null +++ b/minix/share/rpi/weather/Makefile @@ -0,0 +1,14 @@ +# BeagleBone Weather Cape Demo +.include + +NOOBJ= # defined + +FILES= LICENSE README.txt jquery.js style.css weatherstation.js \ + index.html processing.js spin.js weatherstation.lua + +# weatherstation.lua is an executable script run under tcpd and needs BINMODE +FILESMODE_weatherstation.lua=${BINMODE} + +FILESDIR=/usr/share/beaglebone/weather + +.include diff --git a/minix/share/rpi/weather/README.txt b/minix/share/rpi/weather/README.txt new file mode 100644 index 000000000..f9ab7ad1b --- /dev/null +++ b/minix/share/rpi/weather/README.txt @@ -0,0 +1,53 @@ + _ _ _ _ _ + __ _____ __ _| |_| |__ ___ _ __ ___| |_ __ _| |_(_) ___ _ __ + \ \ /\ / / _ \/ _` | __| '_ \ / _ \ '__/ __| __/ _` | __| |/ _ \| '_ \ + \ V V / __/ (_| | |_| | | | __/ | \__ \ || (_| | |_| | (_) | | | | + \_/\_/ \___|\__,_|\__|_| |_|\___|_| |___/\__\__,_|\__|_|\___/|_| |_| + + Minix Demo for the BeagleBone Weather Cape + Based on https://github.com/jadonk/bonescript + + +Overview +-------- + +This is a demo of the BeagleBone Weather Cape. It's a fork of the original +bonescript weatherstation demo, modified to work on the Minix operating +system. The main changes are conversion from nodejs to JSON and mbar to hPa. + +Requirements +------------ + +Hardware: + BeagleBone + BeagleBone Weather Cape + Network (doesn't have to be connected to the Internet) + +Software: + Web Browser with HTML5 support and JavaScript enabled. + + +Setup +----- + +This demo is meant to work 'out of the box'. It requires the BeagleBone be +connected to the network and have the BeagleBone Weather cape attached at +boot. + + 1) Attach the BeagleBone Weather Cape. + 2) Connect a network cable to the BeagleBone. + 3) Power on the BeagleBone. + 4) Configure the network by running these commands. + # netconf + # reboot + 5) Enter the BeagleBone's IP address into your web browser. + +Usage +----- + +This demo is a web application. You just need to point your web browser at +the BeagleBone's IP address to view a nice display of the sensor values. You +can get your BeagleBone's IP address by running `ifconfig` on the BeagleBone. +If the address is 192.168.12.138, you'd enter http://192.168.12.138/ into your +web browser. + diff --git a/minix/share/rpi/weather/index.html b/minix/share/rpi/weather/index.html new file mode 100644 index 000000000..c82e8fab6 --- /dev/null +++ b/minix/share/rpi/weather/index.html @@ -0,0 +1,97 @@ + + + + + + Weather Station - Powered by Minix and BeagleBone + + + + + + + + + + + + + + +
+ + +
+ + + +
+ + + + + diff --git a/minix/share/rpi/weather/jquery.js b/minix/share/rpi/weather/jquery.js new file mode 100644 index 000000000..da4170647 --- /dev/null +++ b/minix/share/rpi/weather/jquery.js @@ -0,0 +1,6 @@ +/*! jQuery v1.10.2 | (c) 2005, 2013 jQuery Foundation, Inc. | jquery.org/license +//@ sourceMappingURL=jquery-1.10.2.min.map +*/ +(function(e,t){var n,r,i=typeof t,o=e.location,a=e.document,s=a.documentElement,l=e.jQuery,u=e.$,c={},p=[],f="1.10.2",d=p.concat,h=p.push,g=p.slice,m=p.indexOf,y=c.toString,v=c.hasOwnProperty,b=f.trim,x=function(e,t){return new x.fn.init(e,t,r)},w=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,T=/\S+/g,C=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,N=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,k=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,E=/^[\],:{}\s]*$/,S=/(?:^|:|,)(?:\s*\[)+/g,A=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,j=/"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g,D=/^-ms-/,L=/-([\da-z])/gi,H=function(e,t){return t.toUpperCase()},q=function(e){(a.addEventListener||"load"===e.type||"complete"===a.readyState)&&(_(),x.ready())},_=function(){a.addEventListener?(a.removeEventListener("DOMContentLoaded",q,!1),e.removeEventListener("load",q,!1)):(a.detachEvent("onreadystatechange",q),e.detachEvent("onload",q))};x.fn=x.prototype={jquery:f,constructor:x,init:function(e,n,r){var i,o;if(!e)return this;if("string"==typeof e){if(i="<"===e.charAt(0)&&">"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:N.exec(e),!i||!i[1]&&n)return!n||n.jquery?(n||r).find(e):this.constructor(n).find(e);if(i[1]){if(n=n instanceof x?n[0]:n,x.merge(this,x.parseHTML(i[1],n&&n.nodeType?n.ownerDocument||n:a,!0)),k.test(i[1])&&x.isPlainObject(n))for(i in n)x.isFunction(this[i])?this[i](n[i]):this.attr(i,n[i]);return this}if(o=a.getElementById(i[2]),o&&o.parentNode){if(o.id!==i[2])return r.find(e);this.length=1,this[0]=o}return this.context=a,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):x.isFunction(e)?r.ready(e):(e.selector!==t&&(this.selector=e.selector,this.context=e.context),x.makeArray(e,this))},selector:"",length:0,toArray:function(){return g.call(this)},get:function(e){return null==e?this.toArray():0>e?this[this.length+e]:this[e]},pushStack:function(e){var t=x.merge(this.constructor(),e);return t.prevObject=this,t.context=this.context,t},each:function(e,t){return x.each(this,e,t)},ready:function(e){return x.ready.promise().done(e),this},slice:function(){return this.pushStack(g.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(0>e?t:0);return this.pushStack(n>=0&&t>n?[this[n]]:[])},map:function(e){return this.pushStack(x.map(this,function(t,n){return e.call(t,n,t)}))},end:function(){return this.prevObject||this.constructor(null)},push:h,sort:[].sort,splice:[].splice},x.fn.init.prototype=x.fn,x.extend=x.fn.extend=function(){var e,n,r,i,o,a,s=arguments[0]||{},l=1,u=arguments.length,c=!1;for("boolean"==typeof s&&(c=s,s=arguments[1]||{},l=2),"object"==typeof s||x.isFunction(s)||(s={}),u===l&&(s=this,--l);u>l;l++)if(null!=(o=arguments[l]))for(i in o)e=s[i],r=o[i],s!==r&&(c&&r&&(x.isPlainObject(r)||(n=x.isArray(r)))?(n?(n=!1,a=e&&x.isArray(e)?e:[]):a=e&&x.isPlainObject(e)?e:{},s[i]=x.extend(c,a,r)):r!==t&&(s[i]=r));return s},x.extend({expando:"jQuery"+(f+Math.random()).replace(/\D/g,""),noConflict:function(t){return e.$===x&&(e.$=u),t&&e.jQuery===x&&(e.jQuery=l),x},isReady:!1,readyWait:1,holdReady:function(e){e?x.readyWait++:x.ready(!0)},ready:function(e){if(e===!0?!--x.readyWait:!x.isReady){if(!a.body)return setTimeout(x.ready);x.isReady=!0,e!==!0&&--x.readyWait>0||(n.resolveWith(a,[x]),x.fn.trigger&&x(a).trigger("ready").off("ready"))}},isFunction:function(e){return"function"===x.type(e)},isArray:Array.isArray||function(e){return"array"===x.type(e)},isWindow:function(e){return null!=e&&e==e.window},isNumeric:function(e){return!isNaN(parseFloat(e))&&isFinite(e)},type:function(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?c[y.call(e)]||"object":typeof e},isPlainObject:function(e){var n;if(!e||"object"!==x.type(e)||e.nodeType||x.isWindow(e))return!1;try{if(e.constructor&&!v.call(e,"constructor")&&!v.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(r){return!1}if(x.support.ownLast)for(n in e)return v.call(e,n);for(n in e);return n===t||v.call(e,n)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},error:function(e){throw Error(e)},parseHTML:function(e,t,n){if(!e||"string"!=typeof e)return null;"boolean"==typeof t&&(n=t,t=!1),t=t||a;var r=k.exec(e),i=!n&&[];return r?[t.createElement(r[1])]:(r=x.buildFragment([e],t,i),i&&x(i).remove(),x.merge([],r.childNodes))},parseJSON:function(n){return e.JSON&&e.JSON.parse?e.JSON.parse(n):null===n?n:"string"==typeof n&&(n=x.trim(n),n&&E.test(n.replace(A,"@").replace(j,"]").replace(S,"")))?Function("return "+n)():(x.error("Invalid JSON: "+n),t)},parseXML:function(n){var r,i;if(!n||"string"!=typeof n)return null;try{e.DOMParser?(i=new DOMParser,r=i.parseFromString(n,"text/xml")):(r=new ActiveXObject("Microsoft.XMLDOM"),r.async="false",r.loadXML(n))}catch(o){r=t}return r&&r.documentElement&&!r.getElementsByTagName("parsererror").length||x.error("Invalid XML: "+n),r},noop:function(){},globalEval:function(t){t&&x.trim(t)&&(e.execScript||function(t){e.eval.call(e,t)})(t)},camelCase:function(e){return e.replace(D,"ms-").replace(L,H)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t,n){var r,i=0,o=e.length,a=M(e);if(n){if(a){for(;o>i;i++)if(r=t.apply(e[i],n),r===!1)break}else for(i in e)if(r=t.apply(e[i],n),r===!1)break}else if(a){for(;o>i;i++)if(r=t.call(e[i],i,e[i]),r===!1)break}else for(i in e)if(r=t.call(e[i],i,e[i]),r===!1)break;return e},trim:b&&!b.call("\ufeff\u00a0")?function(e){return null==e?"":b.call(e)}:function(e){return null==e?"":(e+"").replace(C,"")},makeArray:function(e,t){var n=t||[];return null!=e&&(M(Object(e))?x.merge(n,"string"==typeof e?[e]:e):h.call(n,e)),n},inArray:function(e,t,n){var r;if(t){if(m)return m.call(t,e,n);for(r=t.length,n=n?0>n?Math.max(0,r+n):n:0;r>n;n++)if(n in t&&t[n]===e)return n}return-1},merge:function(e,n){var r=n.length,i=e.length,o=0;if("number"==typeof r)for(;r>o;o++)e[i++]=n[o];else while(n[o]!==t)e[i++]=n[o++];return e.length=i,e},grep:function(e,t,n){var r,i=[],o=0,a=e.length;for(n=!!n;a>o;o++)r=!!t(e[o],o),n!==r&&i.push(e[o]);return i},map:function(e,t,n){var r,i=0,o=e.length,a=M(e),s=[];if(a)for(;o>i;i++)r=t(e[i],i,n),null!=r&&(s[s.length]=r);else for(i in e)r=t(e[i],i,n),null!=r&&(s[s.length]=r);return d.apply([],s)},guid:1,proxy:function(e,n){var r,i,o;return"string"==typeof n&&(o=e[n],n=e,e=o),x.isFunction(e)?(r=g.call(arguments,2),i=function(){return e.apply(n||this,r.concat(g.call(arguments)))},i.guid=e.guid=e.guid||x.guid++,i):t},access:function(e,n,r,i,o,a,s){var l=0,u=e.length,c=null==r;if("object"===x.type(r)){o=!0;for(l in r)x.access(e,n,l,r[l],!0,a,s)}else if(i!==t&&(o=!0,x.isFunction(i)||(s=!0),c&&(s?(n.call(e,i),n=null):(c=n,n=function(e,t,n){return c.call(x(e),n)})),n))for(;u>l;l++)n(e[l],r,s?i:i.call(e[l],l,n(e[l],r)));return o?e:c?n.call(e):u?n(e[0],r):a},now:function(){return(new Date).getTime()},swap:function(e,t,n,r){var i,o,a={};for(o in t)a[o]=e.style[o],e.style[o]=t[o];i=n.apply(e,r||[]);for(o in t)e.style[o]=a[o];return i}}),x.ready.promise=function(t){if(!n)if(n=x.Deferred(),"complete"===a.readyState)setTimeout(x.ready);else if(a.addEventListener)a.addEventListener("DOMContentLoaded",q,!1),e.addEventListener("load",q,!1);else{a.attachEvent("onreadystatechange",q),e.attachEvent("onload",q);var r=!1;try{r=null==e.frameElement&&a.documentElement}catch(i){}r&&r.doScroll&&function o(){if(!x.isReady){try{r.doScroll("left")}catch(e){return setTimeout(o,50)}_(),x.ready()}}()}return n.promise(t)},x.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(e,t){c["[object "+t+"]"]=t.toLowerCase()});function M(e){var t=e.length,n=x.type(e);return x.isWindow(e)?!1:1===e.nodeType&&t?!0:"array"===n||"function"!==n&&(0===t||"number"==typeof t&&t>0&&t-1 in e)}r=x(a),function(e,t){var n,r,i,o,a,s,l,u,c,p,f,d,h,g,m,y,v,b="sizzle"+-new Date,w=e.document,T=0,C=0,N=st(),k=st(),E=st(),S=!1,A=function(e,t){return e===t?(S=!0,0):0},j=typeof t,D=1<<31,L={}.hasOwnProperty,H=[],q=H.pop,_=H.push,M=H.push,O=H.slice,F=H.indexOf||function(e){var t=0,n=this.length;for(;n>t;t++)if(this[t]===e)return t;return-1},B="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",P="[\\x20\\t\\r\\n\\f]",R="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",W=R.replace("w","w#"),$="\\["+P+"*("+R+")"+P+"*(?:([*^$|!~]?=)"+P+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+W+")|)|)"+P+"*\\]",I=":("+R+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+$.replace(3,8)+")*)|.*)\\)|)",z=RegExp("^"+P+"+|((?:^|[^\\\\])(?:\\\\.)*)"+P+"+$","g"),X=RegExp("^"+P+"*,"+P+"*"),U=RegExp("^"+P+"*([>+~]|"+P+")"+P+"*"),V=RegExp(P+"*[+~]"),Y=RegExp("="+P+"*([^\\]'\"]*)"+P+"*\\]","g"),J=RegExp(I),G=RegExp("^"+W+"$"),Q={ID:RegExp("^#("+R+")"),CLASS:RegExp("^\\.("+R+")"),TAG:RegExp("^("+R.replace("w","w*")+")"),ATTR:RegExp("^"+$),PSEUDO:RegExp("^"+I),CHILD:RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+P+"*(even|odd|(([+-]|)(\\d*)n|)"+P+"*(?:([+-]|)"+P+"*(\\d+)|))"+P+"*\\)|)","i"),bool:RegExp("^(?:"+B+")$","i"),needsContext:RegExp("^"+P+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+P+"*((?:-\\d)?\\d*)"+P+"*\\)|)(?=[^-]|$)","i")},K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,et=/^(?:input|select|textarea|button)$/i,tt=/^h\d$/i,nt=/'|\\/g,rt=RegExp("\\\\([\\da-f]{1,6}"+P+"?|("+P+")|.)","ig"),it=function(e,t,n){var r="0x"+t-65536;return r!==r||n?t:0>r?String.fromCharCode(r+65536):String.fromCharCode(55296|r>>10,56320|1023&r)};try{M.apply(H=O.call(w.childNodes),w.childNodes),H[w.childNodes.length].nodeType}catch(ot){M={apply:H.length?function(e,t){_.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function at(e,t,n,i){var o,a,s,l,u,c,d,m,y,x;if((t?t.ownerDocument||t:w)!==f&&p(t),t=t||f,n=n||[],!e||"string"!=typeof e)return n;if(1!==(l=t.nodeType)&&9!==l)return[];if(h&&!i){if(o=Z.exec(e))if(s=o[1]){if(9===l){if(a=t.getElementById(s),!a||!a.parentNode)return n;if(a.id===s)return n.push(a),n}else if(t.ownerDocument&&(a=t.ownerDocument.getElementById(s))&&v(t,a)&&a.id===s)return n.push(a),n}else{if(o[2])return M.apply(n,t.getElementsByTagName(e)),n;if((s=o[3])&&r.getElementsByClassName&&t.getElementsByClassName)return M.apply(n,t.getElementsByClassName(s)),n}if(r.qsa&&(!g||!g.test(e))){if(m=d=b,y=t,x=9===l&&e,1===l&&"object"!==t.nodeName.toLowerCase()){c=mt(e),(d=t.getAttribute("id"))?m=d.replace(nt,"\\$&"):t.setAttribute("id",m),m="[id='"+m+"'] ",u=c.length;while(u--)c[u]=m+yt(c[u]);y=V.test(e)&&t.parentNode||t,x=c.join(",")}if(x)try{return M.apply(n,y.querySelectorAll(x)),n}catch(T){}finally{d||t.removeAttribute("id")}}}return kt(e.replace(z,"$1"),t,n,i)}function st(){var e=[];function t(n,r){return e.push(n+=" ")>o.cacheLength&&delete t[e.shift()],t[n]=r}return t}function lt(e){return e[b]=!0,e}function ut(e){var t=f.createElement("div");try{return!!e(t)}catch(n){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function ct(e,t){var n=e.split("|"),r=e.length;while(r--)o.attrHandle[n[r]]=t}function pt(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&(~t.sourceIndex||D)-(~e.sourceIndex||D);if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function ft(e){return function(t){var n=t.nodeName.toLowerCase();return"input"===n&&t.type===e}}function dt(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function ht(e){return lt(function(t){return t=+t,lt(function(n,r){var i,o=e([],n.length,t),a=o.length;while(a--)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}s=at.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?"HTML"!==t.nodeName:!1},r=at.support={},p=at.setDocument=function(e){var n=e?e.ownerDocument||e:w,i=n.defaultView;return n!==f&&9===n.nodeType&&n.documentElement?(f=n,d=n.documentElement,h=!s(n),i&&i.attachEvent&&i!==i.top&&i.attachEvent("onbeforeunload",function(){p()}),r.attributes=ut(function(e){return e.className="i",!e.getAttribute("className")}),r.getElementsByTagName=ut(function(e){return e.appendChild(n.createComment("")),!e.getElementsByTagName("*").length}),r.getElementsByClassName=ut(function(e){return e.innerHTML="
",e.firstChild.className="i",2===e.getElementsByClassName("i").length}),r.getById=ut(function(e){return d.appendChild(e).id=b,!n.getElementsByName||!n.getElementsByName(b).length}),r.getById?(o.find.ID=function(e,t){if(typeof t.getElementById!==j&&h){var n=t.getElementById(e);return n&&n.parentNode?[n]:[]}},o.filter.ID=function(e){var t=e.replace(rt,it);return function(e){return e.getAttribute("id")===t}}):(delete o.find.ID,o.filter.ID=function(e){var t=e.replace(rt,it);return function(e){var n=typeof e.getAttributeNode!==j&&e.getAttributeNode("id");return n&&n.value===t}}),o.find.TAG=r.getElementsByTagName?function(e,n){return typeof n.getElementsByTagName!==j?n.getElementsByTagName(e):t}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},o.find.CLASS=r.getElementsByClassName&&function(e,n){return typeof n.getElementsByClassName!==j&&h?n.getElementsByClassName(e):t},m=[],g=[],(r.qsa=K.test(n.querySelectorAll))&&(ut(function(e){e.innerHTML="",e.querySelectorAll("[selected]").length||g.push("\\["+P+"*(?:value|"+B+")"),e.querySelectorAll(":checked").length||g.push(":checked")}),ut(function(e){var t=n.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("t",""),e.querySelectorAll("[t^='']").length&&g.push("[*^$]="+P+"*(?:''|\"\")"),e.querySelectorAll(":enabled").length||g.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),g.push(",.*:")})),(r.matchesSelector=K.test(y=d.webkitMatchesSelector||d.mozMatchesSelector||d.oMatchesSelector||d.msMatchesSelector))&&ut(function(e){r.disconnectedMatch=y.call(e,"div"),y.call(e,"[s!='']:x"),m.push("!=",I)}),g=g.length&&RegExp(g.join("|")),m=m.length&&RegExp(m.join("|")),v=K.test(d.contains)||d.compareDocumentPosition?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},A=d.compareDocumentPosition?function(e,t){if(e===t)return S=!0,0;var i=t.compareDocumentPosition&&e.compareDocumentPosition&&e.compareDocumentPosition(t);return i?1&i||!r.sortDetached&&t.compareDocumentPosition(e)===i?e===n||v(w,e)?-1:t===n||v(w,t)?1:c?F.call(c,e)-F.call(c,t):0:4&i?-1:1:e.compareDocumentPosition?-1:1}:function(e,t){var r,i=0,o=e.parentNode,a=t.parentNode,s=[e],l=[t];if(e===t)return S=!0,0;if(!o||!a)return e===n?-1:t===n?1:o?-1:a?1:c?F.call(c,e)-F.call(c,t):0;if(o===a)return pt(e,t);r=e;while(r=r.parentNode)s.unshift(r);r=t;while(r=r.parentNode)l.unshift(r);while(s[i]===l[i])i++;return i?pt(s[i],l[i]):s[i]===w?-1:l[i]===w?1:0},n):f},at.matches=function(e,t){return at(e,null,null,t)},at.matchesSelector=function(e,t){if((e.ownerDocument||e)!==f&&p(e),t=t.replace(Y,"='$1']"),!(!r.matchesSelector||!h||m&&m.test(t)||g&&g.test(t)))try{var n=y.call(e,t);if(n||r.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(i){}return at(t,f,null,[e]).length>0},at.contains=function(e,t){return(e.ownerDocument||e)!==f&&p(e),v(e,t)},at.attr=function(e,n){(e.ownerDocument||e)!==f&&p(e);var i=o.attrHandle[n.toLowerCase()],a=i&&L.call(o.attrHandle,n.toLowerCase())?i(e,n,!h):t;return a===t?r.attributes||!h?e.getAttribute(n):(a=e.getAttributeNode(n))&&a.specified?a.value:null:a},at.error=function(e){throw Error("Syntax error, unrecognized expression: "+e)},at.uniqueSort=function(e){var t,n=[],i=0,o=0;if(S=!r.detectDuplicates,c=!r.sortStable&&e.slice(0),e.sort(A),S){while(t=e[o++])t===e[o]&&(i=n.push(o));while(i--)e.splice(n[i],1)}return e},a=at.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=a(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r];r++)n+=a(t);return n},o=at.selectors={cacheLength:50,createPseudo:lt,match:Q,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(rt,it),e[3]=(e[4]||e[5]||"").replace(rt,it),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||at.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&at.error(e[0]),e},PSEUDO:function(e){var n,r=!e[5]&&e[2];return Q.CHILD.test(e[0])?null:(e[3]&&e[4]!==t?e[2]=e[4]:r&&J.test(r)&&(n=mt(r,!0))&&(n=r.indexOf(")",r.length-n)-r.length)&&(e[0]=e[0].slice(0,n),e[2]=r.slice(0,n)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(rt,it).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=N[e+" "];return t||(t=RegExp("(^|"+P+")"+e+"("+P+"|$)"))&&N(e,function(e){return t.test("string"==typeof e.className&&e.className||typeof e.getAttribute!==j&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=at.attr(r,e);return null==i?"!="===t:t?(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i+" ").indexOf(n)>-1:"|="===t?i===n||i.slice(0,n.length+1)===n+"-":!1):!0}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),a="last"!==e.slice(-4),s="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,l){var u,c,p,f,d,h,g=o!==a?"nextSibling":"previousSibling",m=t.parentNode,y=s&&t.nodeName.toLowerCase(),v=!l&&!s;if(m){if(o){while(g){p=t;while(p=p[g])if(s?p.nodeName.toLowerCase()===y:1===p.nodeType)return!1;h=g="only"===e&&!h&&"nextSibling"}return!0}if(h=[a?m.firstChild:m.lastChild],a&&v){c=m[b]||(m[b]={}),u=c[e]||[],d=u[0]===T&&u[1],f=u[0]===T&&u[2],p=d&&m.childNodes[d];while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if(1===p.nodeType&&++f&&p===t){c[e]=[T,d,f];break}}else if(v&&(u=(t[b]||(t[b]={}))[e])&&u[0]===T)f=u[1];else while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if((s?p.nodeName.toLowerCase()===y:1===p.nodeType)&&++f&&(v&&((p[b]||(p[b]={}))[e]=[T,f]),p===t))break;return f-=i,f===r||0===f%r&&f/r>=0}}},PSEUDO:function(e,t){var n,r=o.pseudos[e]||o.setFilters[e.toLowerCase()]||at.error("unsupported pseudo: "+e);return r[b]?r(t):r.length>1?(n=[e,e,"",t],o.setFilters.hasOwnProperty(e.toLowerCase())?lt(function(e,n){var i,o=r(e,t),a=o.length;while(a--)i=F.call(e,o[a]),e[i]=!(n[i]=o[a])}):function(e){return r(e,0,n)}):r}},pseudos:{not:lt(function(e){var t=[],n=[],r=l(e.replace(z,"$1"));return r[b]?lt(function(e,t,n,i){var o,a=r(e,null,i,[]),s=e.length;while(s--)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),!n.pop()}}),has:lt(function(e){return function(t){return at(e,t).length>0}}),contains:lt(function(e){return function(t){return(t.textContent||t.innerText||a(t)).indexOf(e)>-1}}),lang:lt(function(e){return G.test(e||"")||at.error("unsupported lang: "+e),e=e.replace(rt,it).toLowerCase(),function(t){var n;do if(n=h?t.lang:t.getAttribute("xml:lang")||t.getAttribute("lang"))return n=n.toLowerCase(),n===e||0===n.indexOf(e+"-");while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===d},focus:function(e){return e===f.activeElement&&(!f.hasFocus||f.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeName>"@"||3===e.nodeType||4===e.nodeType)return!1;return!0},parent:function(e){return!o.pseudos.empty(e)},header:function(e){return tt.test(e.nodeName)},input:function(e){return et.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||t.toLowerCase()===e.type)},first:ht(function(){return[0]}),last:ht(function(e,t){return[t-1]}),eq:ht(function(e,t,n){return[0>n?n+t:n]}),even:ht(function(e,t){var n=0;for(;t>n;n+=2)e.push(n);return e}),odd:ht(function(e,t){var n=1;for(;t>n;n+=2)e.push(n);return e}),lt:ht(function(e,t,n){var r=0>n?n+t:n;for(;--r>=0;)e.push(r);return e}),gt:ht(function(e,t,n){var r=0>n?n+t:n;for(;t>++r;)e.push(r);return e})}},o.pseudos.nth=o.pseudos.eq;for(n in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})o.pseudos[n]=ft(n);for(n in{submit:!0,reset:!0})o.pseudos[n]=dt(n);function gt(){}gt.prototype=o.filters=o.pseudos,o.setFilters=new gt;function mt(e,t){var n,r,i,a,s,l,u,c=k[e+" "];if(c)return t?0:c.slice(0);s=e,l=[],u=o.preFilter;while(s){(!n||(r=X.exec(s)))&&(r&&(s=s.slice(r[0].length)||s),l.push(i=[])),n=!1,(r=U.exec(s))&&(n=r.shift(),i.push({value:n,type:r[0].replace(z," ")}),s=s.slice(n.length));for(a in o.filter)!(r=Q[a].exec(s))||u[a]&&!(r=u[a](r))||(n=r.shift(),i.push({value:n,type:a,matches:r}),s=s.slice(n.length));if(!n)break}return t?s.length:s?at.error(e):k(e,l).slice(0)}function yt(e){var t=0,n=e.length,r="";for(;n>t;t++)r+=e[t].value;return r}function vt(e,t,n){var r=t.dir,o=n&&"parentNode"===r,a=C++;return t.first?function(t,n,i){while(t=t[r])if(1===t.nodeType||o)return e(t,n,i)}:function(t,n,s){var l,u,c,p=T+" "+a;if(s){while(t=t[r])if((1===t.nodeType||o)&&e(t,n,s))return!0}else while(t=t[r])if(1===t.nodeType||o)if(c=t[b]||(t[b]={}),(u=c[r])&&u[0]===p){if((l=u[1])===!0||l===i)return l===!0}else if(u=c[r]=[p],u[1]=e(t,n,s)||i,u[1]===!0)return!0}}function bt(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function xt(e,t,n,r,i){var o,a=[],s=0,l=e.length,u=null!=t;for(;l>s;s++)(o=e[s])&&(!n||n(o,r,i))&&(a.push(o),u&&t.push(s));return a}function wt(e,t,n,r,i,o){return r&&!r[b]&&(r=wt(r)),i&&!i[b]&&(i=wt(i,o)),lt(function(o,a,s,l){var u,c,p,f=[],d=[],h=a.length,g=o||Nt(t||"*",s.nodeType?[s]:s,[]),m=!e||!o&&t?g:xt(g,f,e,s,l),y=n?i||(o?e:h||r)?[]:a:m;if(n&&n(m,y,s,l),r){u=xt(y,d),r(u,[],s,l),c=u.length;while(c--)(p=u[c])&&(y[d[c]]=!(m[d[c]]=p))}if(o){if(i||e){if(i){u=[],c=y.length;while(c--)(p=y[c])&&u.push(m[c]=p);i(null,y=[],u,l)}c=y.length;while(c--)(p=y[c])&&(u=i?F.call(o,p):f[c])>-1&&(o[u]=!(a[u]=p))}}else y=xt(y===a?y.splice(h,y.length):y),i?i(null,a,y,l):M.apply(a,y)})}function Tt(e){var t,n,r,i=e.length,a=o.relative[e[0].type],s=a||o.relative[" "],l=a?1:0,c=vt(function(e){return e===t},s,!0),p=vt(function(e){return F.call(t,e)>-1},s,!0),f=[function(e,n,r){return!a&&(r||n!==u)||((t=n).nodeType?c(e,n,r):p(e,n,r))}];for(;i>l;l++)if(n=o.relative[e[l].type])f=[vt(bt(f),n)];else{if(n=o.filter[e[l].type].apply(null,e[l].matches),n[b]){for(r=++l;i>r;r++)if(o.relative[e[r].type])break;return wt(l>1&&bt(f),l>1&&yt(e.slice(0,l-1).concat({value:" "===e[l-2].type?"*":""})).replace(z,"$1"),n,r>l&&Tt(e.slice(l,r)),i>r&&Tt(e=e.slice(r)),i>r&&yt(e))}f.push(n)}return bt(f)}function Ct(e,t){var n=0,r=t.length>0,a=e.length>0,s=function(s,l,c,p,d){var h,g,m,y=[],v=0,b="0",x=s&&[],w=null!=d,C=u,N=s||a&&o.find.TAG("*",d&&l.parentNode||l),k=T+=null==C?1:Math.random()||.1;for(w&&(u=l!==f&&l,i=n);null!=(h=N[b]);b++){if(a&&h){g=0;while(m=e[g++])if(m(h,l,c)){p.push(h);break}w&&(T=k,i=++n)}r&&((h=!m&&h)&&v--,s&&x.push(h))}if(v+=b,r&&b!==v){g=0;while(m=t[g++])m(x,y,l,c);if(s){if(v>0)while(b--)x[b]||y[b]||(y[b]=q.call(p));y=xt(y)}M.apply(p,y),w&&!s&&y.length>0&&v+t.length>1&&at.uniqueSort(p)}return w&&(T=k,u=C),x};return r?lt(s):s}l=at.compile=function(e,t){var n,r=[],i=[],o=E[e+" "];if(!o){t||(t=mt(e)),n=t.length;while(n--)o=Tt(t[n]),o[b]?r.push(o):i.push(o);o=E(e,Ct(i,r))}return o};function Nt(e,t,n){var r=0,i=t.length;for(;i>r;r++)at(e,t[r],n);return n}function kt(e,t,n,i){var a,s,u,c,p,f=mt(e);if(!i&&1===f.length){if(s=f[0]=f[0].slice(0),s.length>2&&"ID"===(u=s[0]).type&&r.getById&&9===t.nodeType&&h&&o.relative[s[1].type]){if(t=(o.find.ID(u.matches[0].replace(rt,it),t)||[])[0],!t)return n;e=e.slice(s.shift().value.length)}a=Q.needsContext.test(e)?0:s.length;while(a--){if(u=s[a],o.relative[c=u.type])break;if((p=o.find[c])&&(i=p(u.matches[0].replace(rt,it),V.test(s[0].type)&&t.parentNode||t))){if(s.splice(a,1),e=i.length&&yt(s),!e)return M.apply(n,i),n;break}}}return l(e,f)(i,t,!h,n,V.test(e)),n}r.sortStable=b.split("").sort(A).join("")===b,r.detectDuplicates=S,p(),r.sortDetached=ut(function(e){return 1&e.compareDocumentPosition(f.createElement("div"))}),ut(function(e){return e.innerHTML="","#"===e.firstChild.getAttribute("href")})||ct("type|href|height|width",function(e,n,r){return r?t:e.getAttribute(n,"type"===n.toLowerCase()?1:2)}),r.attributes&&ut(function(e){return e.innerHTML="",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||ct("value",function(e,n,r){return r||"input"!==e.nodeName.toLowerCase()?t:e.defaultValue}),ut(function(e){return null==e.getAttribute("disabled")})||ct(B,function(e,n,r){var i;return r?t:(i=e.getAttributeNode(n))&&i.specified?i.value:e[n]===!0?n.toLowerCase():null}),x.find=at,x.expr=at.selectors,x.expr[":"]=x.expr.pseudos,x.unique=at.uniqueSort,x.text=at.getText,x.isXMLDoc=at.isXML,x.contains=at.contains}(e);var O={};function F(e){var t=O[e]={};return x.each(e.match(T)||[],function(e,n){t[n]=!0}),t}x.Callbacks=function(e){e="string"==typeof e?O[e]||F(e):x.extend({},e);var n,r,i,o,a,s,l=[],u=!e.once&&[],c=function(t){for(r=e.memory&&t,i=!0,a=s||0,s=0,o=l.length,n=!0;l&&o>a;a++)if(l[a].apply(t[0],t[1])===!1&&e.stopOnFalse){r=!1;break}n=!1,l&&(u?u.length&&c(u.shift()):r?l=[]:p.disable())},p={add:function(){if(l){var t=l.length;(function i(t){x.each(t,function(t,n){var r=x.type(n);"function"===r?e.unique&&p.has(n)||l.push(n):n&&n.length&&"string"!==r&&i(n)})})(arguments),n?o=l.length:r&&(s=t,c(r))}return this},remove:function(){return l&&x.each(arguments,function(e,t){var r;while((r=x.inArray(t,l,r))>-1)l.splice(r,1),n&&(o>=r&&o--,a>=r&&a--)}),this},has:function(e){return e?x.inArray(e,l)>-1:!(!l||!l.length)},empty:function(){return l=[],o=0,this},disable:function(){return l=u=r=t,this},disabled:function(){return!l},lock:function(){return u=t,r||p.disable(),this},locked:function(){return!u},fireWith:function(e,t){return!l||i&&!u||(t=t||[],t=[e,t.slice?t.slice():t],n?u.push(t):c(t)),this},fire:function(){return p.fireWith(this,arguments),this},fired:function(){return!!i}};return p},x.extend({Deferred:function(e){var t=[["resolve","done",x.Callbacks("once memory"),"resolved"],["reject","fail",x.Callbacks("once memory"),"rejected"],["notify","progress",x.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return x.Deferred(function(n){x.each(t,function(t,o){var a=o[0],s=x.isFunction(e[t])&&e[t];i[o[1]](function(){var e=s&&s.apply(this,arguments);e&&x.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[a+"With"](this===r?n.promise():this,s?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?x.extend(e,r):r}},i={};return r.pipe=r.then,x.each(t,function(e,o){var a=o[2],s=o[3];r[o[1]]=a.add,s&&a.add(function(){n=s},t[1^e][2].disable,t[2][2].lock),i[o[0]]=function(){return i[o[0]+"With"](this===i?r:this,arguments),this},i[o[0]+"With"]=a.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t=0,n=g.call(arguments),r=n.length,i=1!==r||e&&x.isFunction(e.promise)?r:0,o=1===i?e:x.Deferred(),a=function(e,t,n){return function(r){t[e]=this,n[e]=arguments.length>1?g.call(arguments):r,n===s?o.notifyWith(t,n):--i||o.resolveWith(t,n)}},s,l,u;if(r>1)for(s=Array(r),l=Array(r),u=Array(r);r>t;t++)n[t]&&x.isFunction(n[t].promise)?n[t].promise().done(a(t,u,n)).fail(o.reject).progress(a(t,l,s)):--i;return i||o.resolveWith(u,n),o.promise()}}),x.support=function(t){var n,r,o,s,l,u,c,p,f,d=a.createElement("div");if(d.setAttribute("className","t"),d.innerHTML="
a",n=d.getElementsByTagName("*")||[],r=d.getElementsByTagName("a")[0],!r||!r.style||!n.length)return t;s=a.createElement("select"),u=s.appendChild(a.createElement("option")),o=d.getElementsByTagName("input")[0],r.style.cssText="top:1px;float:left;opacity:.5",t.getSetAttribute="t"!==d.className,t.leadingWhitespace=3===d.firstChild.nodeType,t.tbody=!d.getElementsByTagName("tbody").length,t.htmlSerialize=!!d.getElementsByTagName("link").length,t.style=/top/.test(r.getAttribute("style")),t.hrefNormalized="/a"===r.getAttribute("href"),t.opacity=/^0.5/.test(r.style.opacity),t.cssFloat=!!r.style.cssFloat,t.checkOn=!!o.value,t.optSelected=u.selected,t.enctype=!!a.createElement("form").enctype,t.html5Clone="<:nav>"!==a.createElement("nav").cloneNode(!0).outerHTML,t.inlineBlockNeedsLayout=!1,t.shrinkWrapBlocks=!1,t.pixelPosition=!1,t.deleteExpando=!0,t.noCloneEvent=!0,t.reliableMarginRight=!0,t.boxSizingReliable=!0,o.checked=!0,t.noCloneChecked=o.cloneNode(!0).checked,s.disabled=!0,t.optDisabled=!u.disabled;try{delete d.test}catch(h){t.deleteExpando=!1}o=a.createElement("input"),o.setAttribute("value",""),t.input=""===o.getAttribute("value"),o.value="t",o.setAttribute("type","radio"),t.radioValue="t"===o.value,o.setAttribute("checked","t"),o.setAttribute("name","t"),l=a.createDocumentFragment(),l.appendChild(o),t.appendChecked=o.checked,t.checkClone=l.cloneNode(!0).cloneNode(!0).lastChild.checked,d.attachEvent&&(d.attachEvent("onclick",function(){t.noCloneEvent=!1}),d.cloneNode(!0).click());for(f in{submit:!0,change:!0,focusin:!0})d.setAttribute(c="on"+f,"t"),t[f+"Bubbles"]=c in e||d.attributes[c].expando===!1;d.style.backgroundClip="content-box",d.cloneNode(!0).style.backgroundClip="",t.clearCloneStyle="content-box"===d.style.backgroundClip;for(f in x(t))break;return t.ownLast="0"!==f,x(function(){var n,r,o,s="padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;",l=a.getElementsByTagName("body")[0];l&&(n=a.createElement("div"),n.style.cssText="border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px",l.appendChild(n).appendChild(d),d.innerHTML="
t
",o=d.getElementsByTagName("td"),o[0].style.cssText="padding:0;margin:0;border:0;display:none",p=0===o[0].offsetHeight,o[0].style.display="",o[1].style.display="none",t.reliableHiddenOffsets=p&&0===o[0].offsetHeight,d.innerHTML="",d.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",x.swap(l,null!=l.style.zoom?{zoom:1}:{},function(){t.boxSizing=4===d.offsetWidth}),e.getComputedStyle&&(t.pixelPosition="1%"!==(e.getComputedStyle(d,null)||{}).top,t.boxSizingReliable="4px"===(e.getComputedStyle(d,null)||{width:"4px"}).width,r=d.appendChild(a.createElement("div")),r.style.cssText=d.style.cssText=s,r.style.marginRight=r.style.width="0",d.style.width="1px",t.reliableMarginRight=!parseFloat((e.getComputedStyle(r,null)||{}).marginRight)),typeof d.style.zoom!==i&&(d.innerHTML="",d.style.cssText=s+"width:1px;padding:1px;display:inline;zoom:1",t.inlineBlockNeedsLayout=3===d.offsetWidth,d.style.display="block",d.innerHTML="
",d.firstChild.style.width="5px",t.shrinkWrapBlocks=3!==d.offsetWidth,t.inlineBlockNeedsLayout&&(l.style.zoom=1)),l.removeChild(n),n=d=o=r=null)}),n=s=l=u=r=o=null,t +}({});var B=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,P=/([A-Z])/g;function R(e,n,r,i){if(x.acceptData(e)){var o,a,s=x.expando,l=e.nodeType,u=l?x.cache:e,c=l?e[s]:e[s]&&s;if(c&&u[c]&&(i||u[c].data)||r!==t||"string"!=typeof n)return c||(c=l?e[s]=p.pop()||x.guid++:s),u[c]||(u[c]=l?{}:{toJSON:x.noop}),("object"==typeof n||"function"==typeof n)&&(i?u[c]=x.extend(u[c],n):u[c].data=x.extend(u[c].data,n)),a=u[c],i||(a.data||(a.data={}),a=a.data),r!==t&&(a[x.camelCase(n)]=r),"string"==typeof n?(o=a[n],null==o&&(o=a[x.camelCase(n)])):o=a,o}}function W(e,t,n){if(x.acceptData(e)){var r,i,o=e.nodeType,a=o?x.cache:e,s=o?e[x.expando]:x.expando;if(a[s]){if(t&&(r=n?a[s]:a[s].data)){x.isArray(t)?t=t.concat(x.map(t,x.camelCase)):t in r?t=[t]:(t=x.camelCase(t),t=t in r?[t]:t.split(" ")),i=t.length;while(i--)delete r[t[i]];if(n?!I(r):!x.isEmptyObject(r))return}(n||(delete a[s].data,I(a[s])))&&(o?x.cleanData([e],!0):x.support.deleteExpando||a!=a.window?delete a[s]:a[s]=null)}}}x.extend({cache:{},noData:{applet:!0,embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(e){return e=e.nodeType?x.cache[e[x.expando]]:e[x.expando],!!e&&!I(e)},data:function(e,t,n){return R(e,t,n)},removeData:function(e,t){return W(e,t)},_data:function(e,t,n){return R(e,t,n,!0)},_removeData:function(e,t){return W(e,t,!0)},acceptData:function(e){if(e.nodeType&&1!==e.nodeType&&9!==e.nodeType)return!1;var t=e.nodeName&&x.noData[e.nodeName.toLowerCase()];return!t||t!==!0&&e.getAttribute("classid")===t}}),x.fn.extend({data:function(e,n){var r,i,o=null,a=0,s=this[0];if(e===t){if(this.length&&(o=x.data(s),1===s.nodeType&&!x._data(s,"parsedAttrs"))){for(r=s.attributes;r.length>a;a++)i=r[a].name,0===i.indexOf("data-")&&(i=x.camelCase(i.slice(5)),$(s,i,o[i]));x._data(s,"parsedAttrs",!0)}return o}return"object"==typeof e?this.each(function(){x.data(this,e)}):arguments.length>1?this.each(function(){x.data(this,e,n)}):s?$(s,e,x.data(s,e)):null},removeData:function(e){return this.each(function(){x.removeData(this,e)})}});function $(e,n,r){if(r===t&&1===e.nodeType){var i="data-"+n.replace(P,"-$1").toLowerCase();if(r=e.getAttribute(i),"string"==typeof r){try{r="true"===r?!0:"false"===r?!1:"null"===r?null:+r+""===r?+r:B.test(r)?x.parseJSON(r):r}catch(o){}x.data(e,n,r)}else r=t}return r}function I(e){var t;for(t in e)if(("data"!==t||!x.isEmptyObject(e[t]))&&"toJSON"!==t)return!1;return!0}x.extend({queue:function(e,n,r){var i;return e?(n=(n||"fx")+"queue",i=x._data(e,n),r&&(!i||x.isArray(r)?i=x._data(e,n,x.makeArray(r)):i.push(r)),i||[]):t},dequeue:function(e,t){t=t||"fx";var n=x.queue(e,t),r=n.length,i=n.shift(),o=x._queueHooks(e,t),a=function(){x.dequeue(e,t)};"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,a,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return x._data(e,n)||x._data(e,n,{empty:x.Callbacks("once memory").add(function(){x._removeData(e,t+"queue"),x._removeData(e,n)})})}}),x.fn.extend({queue:function(e,n){var r=2;return"string"!=typeof e&&(n=e,e="fx",r--),r>arguments.length?x.queue(this[0],e):n===t?this:this.each(function(){var t=x.queue(this,e,n);x._queueHooks(this,e),"fx"===e&&"inprogress"!==t[0]&&x.dequeue(this,e)})},dequeue:function(e){return this.each(function(){x.dequeue(this,e)})},delay:function(e,t){return e=x.fx?x.fx.speeds[e]||e:e,t=t||"fx",this.queue(t,function(t,n){var r=setTimeout(t,e);n.stop=function(){clearTimeout(r)}})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,n){var r,i=1,o=x.Deferred(),a=this,s=this.length,l=function(){--i||o.resolveWith(a,[a])};"string"!=typeof e&&(n=e,e=t),e=e||"fx";while(s--)r=x._data(a[s],e+"queueHooks"),r&&r.empty&&(i++,r.empty.add(l));return l(),o.promise(n)}});var z,X,U=/[\t\r\n\f]/g,V=/\r/g,Y=/^(?:input|select|textarea|button|object)$/i,J=/^(?:a|area)$/i,G=/^(?:checked|selected)$/i,Q=x.support.getSetAttribute,K=x.support.input;x.fn.extend({attr:function(e,t){return x.access(this,x.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){x.removeAttr(this,e)})},prop:function(e,t){return x.access(this,x.prop,e,t,arguments.length>1)},removeProp:function(e){return e=x.propFix[e]||e,this.each(function(){try{this[e]=t,delete this[e]}catch(n){}})},addClass:function(e){var t,n,r,i,o,a=0,s=this.length,l="string"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).addClass(e.call(this,t,this.className))});if(l)for(t=(e||"").match(T)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(U," "):" ")){o=0;while(i=t[o++])0>r.indexOf(" "+i+" ")&&(r+=i+" ");n.className=x.trim(r)}return this},removeClass:function(e){var t,n,r,i,o,a=0,s=this.length,l=0===arguments.length||"string"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).removeClass(e.call(this,t,this.className))});if(l)for(t=(e||"").match(T)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(U," "):"")){o=0;while(i=t[o++])while(r.indexOf(" "+i+" ")>=0)r=r.replace(" "+i+" "," ");n.className=e?x.trim(r):""}return this},toggleClass:function(e,t){var n=typeof e;return"boolean"==typeof t&&"string"===n?t?this.addClass(e):this.removeClass(e):x.isFunction(e)?this.each(function(n){x(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if("string"===n){var t,r=0,o=x(this),a=e.match(T)||[];while(t=a[r++])o.hasClass(t)?o.removeClass(t):o.addClass(t)}else(n===i||"boolean"===n)&&(this.className&&x._data(this,"__className__",this.className),this.className=this.className||e===!1?"":x._data(this,"__className__")||"")})},hasClass:function(e){var t=" "+e+" ",n=0,r=this.length;for(;r>n;n++)if(1===this[n].nodeType&&(" "+this[n].className+" ").replace(U," ").indexOf(t)>=0)return!0;return!1},val:function(e){var n,r,i,o=this[0];{if(arguments.length)return i=x.isFunction(e),this.each(function(n){var o;1===this.nodeType&&(o=i?e.call(this,n,x(this).val()):e,null==o?o="":"number"==typeof o?o+="":x.isArray(o)&&(o=x.map(o,function(e){return null==e?"":e+""})),r=x.valHooks[this.type]||x.valHooks[this.nodeName.toLowerCase()],r&&"set"in r&&r.set(this,o,"value")!==t||(this.value=o))});if(o)return r=x.valHooks[o.type]||x.valHooks[o.nodeName.toLowerCase()],r&&"get"in r&&(n=r.get(o,"value"))!==t?n:(n=o.value,"string"==typeof n?n.replace(V,""):null==n?"":n)}}}),x.extend({valHooks:{option:{get:function(e){var t=x.find.attr(e,"value");return null!=t?t:e.text}},select:{get:function(e){var t,n,r=e.options,i=e.selectedIndex,o="select-one"===e.type||0>i,a=o?null:[],s=o?i+1:r.length,l=0>i?s:o?i:0;for(;s>l;l++)if(n=r[l],!(!n.selected&&l!==i||(x.support.optDisabled?n.disabled:null!==n.getAttribute("disabled"))||n.parentNode.disabled&&x.nodeName(n.parentNode,"optgroup"))){if(t=x(n).val(),o)return t;a.push(t)}return a},set:function(e,t){var n,r,i=e.options,o=x.makeArray(t),a=i.length;while(a--)r=i[a],(r.selected=x.inArray(x(r).val(),o)>=0)&&(n=!0);return n||(e.selectedIndex=-1),o}}},attr:function(e,n,r){var o,a,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return typeof e.getAttribute===i?x.prop(e,n,r):(1===s&&x.isXMLDoc(e)||(n=n.toLowerCase(),o=x.attrHooks[n]||(x.expr.match.bool.test(n)?X:z)),r===t?o&&"get"in o&&null!==(a=o.get(e,n))?a:(a=x.find.attr(e,n),null==a?t:a):null!==r?o&&"set"in o&&(a=o.set(e,r,n))!==t?a:(e.setAttribute(n,r+""),r):(x.removeAttr(e,n),t))},removeAttr:function(e,t){var n,r,i=0,o=t&&t.match(T);if(o&&1===e.nodeType)while(n=o[i++])r=x.propFix[n]||n,x.expr.match.bool.test(n)?K&&Q||!G.test(n)?e[r]=!1:e[x.camelCase("default-"+n)]=e[r]=!1:x.attr(e,n,""),e.removeAttribute(Q?n:r)},attrHooks:{type:{set:function(e,t){if(!x.support.radioValue&&"radio"===t&&x.nodeName(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},propFix:{"for":"htmlFor","class":"className"},prop:function(e,n,r){var i,o,a,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return a=1!==s||!x.isXMLDoc(e),a&&(n=x.propFix[n]||n,o=x.propHooks[n]),r!==t?o&&"set"in o&&(i=o.set(e,r,n))!==t?i:e[n]=r:o&&"get"in o&&null!==(i=o.get(e,n))?i:e[n]},propHooks:{tabIndex:{get:function(e){var t=x.find.attr(e,"tabindex");return t?parseInt(t,10):Y.test(e.nodeName)||J.test(e.nodeName)&&e.href?0:-1}}}}),X={set:function(e,t,n){return t===!1?x.removeAttr(e,n):K&&Q||!G.test(n)?e.setAttribute(!Q&&x.propFix[n]||n,n):e[x.camelCase("default-"+n)]=e[n]=!0,n}},x.each(x.expr.match.bool.source.match(/\w+/g),function(e,n){var r=x.expr.attrHandle[n]||x.find.attr;x.expr.attrHandle[n]=K&&Q||!G.test(n)?function(e,n,i){var o=x.expr.attrHandle[n],a=i?t:(x.expr.attrHandle[n]=t)!=r(e,n,i)?n.toLowerCase():null;return x.expr.attrHandle[n]=o,a}:function(e,n,r){return r?t:e[x.camelCase("default-"+n)]?n.toLowerCase():null}}),K&&Q||(x.attrHooks.value={set:function(e,n,r){return x.nodeName(e,"input")?(e.defaultValue=n,t):z&&z.set(e,n,r)}}),Q||(z={set:function(e,n,r){var i=e.getAttributeNode(r);return i||e.setAttributeNode(i=e.ownerDocument.createAttribute(r)),i.value=n+="","value"===r||n===e.getAttribute(r)?n:t}},x.expr.attrHandle.id=x.expr.attrHandle.name=x.expr.attrHandle.coords=function(e,n,r){var i;return r?t:(i=e.getAttributeNode(n))&&""!==i.value?i.value:null},x.valHooks.button={get:function(e,n){var r=e.getAttributeNode(n);return r&&r.specified?r.value:t},set:z.set},x.attrHooks.contenteditable={set:function(e,t,n){z.set(e,""===t?!1:t,n)}},x.each(["width","height"],function(e,n){x.attrHooks[n]={set:function(e,r){return""===r?(e.setAttribute(n,"auto"),r):t}}})),x.support.hrefNormalized||x.each(["href","src"],function(e,t){x.propHooks[t]={get:function(e){return e.getAttribute(t,4)}}}),x.support.style||(x.attrHooks.style={get:function(e){return e.style.cssText||t},set:function(e,t){return e.style.cssText=t+""}}),x.support.optSelected||(x.propHooks.selected={get:function(e){var t=e.parentNode;return t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex),null}}),x.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){x.propFix[this.toLowerCase()]=this}),x.support.enctype||(x.propFix.enctype="encoding"),x.each(["radio","checkbox"],function(){x.valHooks[this]={set:function(e,n){return x.isArray(n)?e.checked=x.inArray(x(e).val(),n)>=0:t}},x.support.checkOn||(x.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})});var Z=/^(?:input|select|textarea)$/i,et=/^key/,tt=/^(?:mouse|contextmenu)|click/,nt=/^(?:focusinfocus|focusoutblur)$/,rt=/^([^.]*)(?:\.(.+)|)$/;function it(){return!0}function ot(){return!1}function at(){try{return a.activeElement}catch(e){}}x.event={global:{},add:function(e,n,r,o,a){var s,l,u,c,p,f,d,h,g,m,y,v=x._data(e);if(v){r.handler&&(c=r,r=c.handler,a=c.selector),r.guid||(r.guid=x.guid++),(l=v.events)||(l=v.events={}),(f=v.handle)||(f=v.handle=function(e){return typeof x===i||e&&x.event.triggered===e.type?t:x.event.dispatch.apply(f.elem,arguments)},f.elem=e),n=(n||"").match(T)||[""],u=n.length;while(u--)s=rt.exec(n[u])||[],g=y=s[1],m=(s[2]||"").split(".").sort(),g&&(p=x.event.special[g]||{},g=(a?p.delegateType:p.bindType)||g,p=x.event.special[g]||{},d=x.extend({type:g,origType:y,data:o,handler:r,guid:r.guid,selector:a,needsContext:a&&x.expr.match.needsContext.test(a),namespace:m.join(".")},c),(h=l[g])||(h=l[g]=[],h.delegateCount=0,p.setup&&p.setup.call(e,o,m,f)!==!1||(e.addEventListener?e.addEventListener(g,f,!1):e.attachEvent&&e.attachEvent("on"+g,f))),p.add&&(p.add.call(e,d),d.handler.guid||(d.handler.guid=r.guid)),a?h.splice(h.delegateCount++,0,d):h.push(d),x.event.global[g]=!0);e=null}},remove:function(e,t,n,r,i){var o,a,s,l,u,c,p,f,d,h,g,m=x.hasData(e)&&x._data(e);if(m&&(c=m.events)){t=(t||"").match(T)||[""],u=t.length;while(u--)if(s=rt.exec(t[u])||[],d=g=s[1],h=(s[2]||"").split(".").sort(),d){p=x.event.special[d]||{},d=(r?p.delegateType:p.bindType)||d,f=c[d]||[],s=s[2]&&RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),l=o=f.length;while(o--)a=f[o],!i&&g!==a.origType||n&&n.guid!==a.guid||s&&!s.test(a.namespace)||r&&r!==a.selector&&("**"!==r||!a.selector)||(f.splice(o,1),a.selector&&f.delegateCount--,p.remove&&p.remove.call(e,a));l&&!f.length&&(p.teardown&&p.teardown.call(e,h,m.handle)!==!1||x.removeEvent(e,d,m.handle),delete c[d])}else for(d in c)x.event.remove(e,d+t[u],n,r,!0);x.isEmptyObject(c)&&(delete m.handle,x._removeData(e,"events"))}},trigger:function(n,r,i,o){var s,l,u,c,p,f,d,h=[i||a],g=v.call(n,"type")?n.type:n,m=v.call(n,"namespace")?n.namespace.split("."):[];if(u=f=i=i||a,3!==i.nodeType&&8!==i.nodeType&&!nt.test(g+x.event.triggered)&&(g.indexOf(".")>=0&&(m=g.split("."),g=m.shift(),m.sort()),l=0>g.indexOf(":")&&"on"+g,n=n[x.expando]?n:new x.Event(g,"object"==typeof n&&n),n.isTrigger=o?2:3,n.namespace=m.join("."),n.namespace_re=n.namespace?RegExp("(^|\\.)"+m.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,n.result=t,n.target||(n.target=i),r=null==r?[n]:x.makeArray(r,[n]),p=x.event.special[g]||{},o||!p.trigger||p.trigger.apply(i,r)!==!1)){if(!o&&!p.noBubble&&!x.isWindow(i)){for(c=p.delegateType||g,nt.test(c+g)||(u=u.parentNode);u;u=u.parentNode)h.push(u),f=u;f===(i.ownerDocument||a)&&h.push(f.defaultView||f.parentWindow||e)}d=0;while((u=h[d++])&&!n.isPropagationStopped())n.type=d>1?c:p.bindType||g,s=(x._data(u,"events")||{})[n.type]&&x._data(u,"handle"),s&&s.apply(u,r),s=l&&u[l],s&&x.acceptData(u)&&s.apply&&s.apply(u,r)===!1&&n.preventDefault();if(n.type=g,!o&&!n.isDefaultPrevented()&&(!p._default||p._default.apply(h.pop(),r)===!1)&&x.acceptData(i)&&l&&i[g]&&!x.isWindow(i)){f=i[l],f&&(i[l]=null),x.event.triggered=g;try{i[g]()}catch(y){}x.event.triggered=t,f&&(i[l]=f)}return n.result}},dispatch:function(e){e=x.event.fix(e);var n,r,i,o,a,s=[],l=g.call(arguments),u=(x._data(this,"events")||{})[e.type]||[],c=x.event.special[e.type]||{};if(l[0]=e,e.delegateTarget=this,!c.preDispatch||c.preDispatch.call(this,e)!==!1){s=x.event.handlers.call(this,e,u),n=0;while((o=s[n++])&&!e.isPropagationStopped()){e.currentTarget=o.elem,a=0;while((i=o.handlers[a++])&&!e.isImmediatePropagationStopped())(!e.namespace_re||e.namespace_re.test(i.namespace))&&(e.handleObj=i,e.data=i.data,r=((x.event.special[i.origType]||{}).handle||i.handler).apply(o.elem,l),r!==t&&(e.result=r)===!1&&(e.preventDefault(),e.stopPropagation()))}return c.postDispatch&&c.postDispatch.call(this,e),e.result}},handlers:function(e,n){var r,i,o,a,s=[],l=n.delegateCount,u=e.target;if(l&&u.nodeType&&(!e.button||"click"!==e.type))for(;u!=this;u=u.parentNode||this)if(1===u.nodeType&&(u.disabled!==!0||"click"!==e.type)){for(o=[],a=0;l>a;a++)i=n[a],r=i.selector+" ",o[r]===t&&(o[r]=i.needsContext?x(r,this).index(u)>=0:x.find(r,this,null,[u]).length),o[r]&&o.push(i);o.length&&s.push({elem:u,handlers:o})}return n.length>l&&s.push({elem:this,handlers:n.slice(l)}),s},fix:function(e){if(e[x.expando])return e;var t,n,r,i=e.type,o=e,s=this.fixHooks[i];s||(this.fixHooks[i]=s=tt.test(i)?this.mouseHooks:et.test(i)?this.keyHooks:{}),r=s.props?this.props.concat(s.props):this.props,e=new x.Event(o),t=r.length;while(t--)n=r[t],e[n]=o[n];return e.target||(e.target=o.srcElement||a),3===e.target.nodeType&&(e.target=e.target.parentNode),e.metaKey=!!e.metaKey,s.filter?s.filter(e,o):e},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(e,t){return null==e.which&&(e.which=null!=t.charCode?t.charCode:t.keyCode),e}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(e,n){var r,i,o,s=n.button,l=n.fromElement;return null==e.pageX&&null!=n.clientX&&(i=e.target.ownerDocument||a,o=i.documentElement,r=i.body,e.pageX=n.clientX+(o&&o.scrollLeft||r&&r.scrollLeft||0)-(o&&o.clientLeft||r&&r.clientLeft||0),e.pageY=n.clientY+(o&&o.scrollTop||r&&r.scrollTop||0)-(o&&o.clientTop||r&&r.clientTop||0)),!e.relatedTarget&&l&&(e.relatedTarget=l===e.target?n.toElement:l),e.which||s===t||(e.which=1&s?1:2&s?3:4&s?2:0),e}},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==at()&&this.focus)try{return this.focus(),!1}catch(e){}},delegateType:"focusin"},blur:{trigger:function(){return this===at()&&this.blur?(this.blur(),!1):t},delegateType:"focusout"},click:{trigger:function(){return x.nodeName(this,"input")&&"checkbox"===this.type&&this.click?(this.click(),!1):t},_default:function(e){return x.nodeName(e.target,"a")}},beforeunload:{postDispatch:function(e){e.result!==t&&(e.originalEvent.returnValue=e.result)}}},simulate:function(e,t,n,r){var i=x.extend(new x.Event,n,{type:e,isSimulated:!0,originalEvent:{}});r?x.event.trigger(i,null,t):x.event.dispatch.call(t,i),i.isDefaultPrevented()&&n.preventDefault()}},x.removeEvent=a.removeEventListener?function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n,!1)}:function(e,t,n){var r="on"+t;e.detachEvent&&(typeof e[r]===i&&(e[r]=null),e.detachEvent(r,n))},x.Event=function(e,n){return this instanceof x.Event?(e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||e.returnValue===!1||e.getPreventDefault&&e.getPreventDefault()?it:ot):this.type=e,n&&x.extend(this,n),this.timeStamp=e&&e.timeStamp||x.now(),this[x.expando]=!0,t):new x.Event(e,n)},x.Event.prototype={isDefaultPrevented:ot,isPropagationStopped:ot,isImmediatePropagationStopped:ot,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=it,e&&(e.preventDefault?e.preventDefault():e.returnValue=!1)},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=it,e&&(e.stopPropagation&&e.stopPropagation(),e.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=it,this.stopPropagation()}},x.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(e,t){x.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj;return(!i||i!==r&&!x.contains(r,i))&&(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),x.support.submitBubbles||(x.event.special.submit={setup:function(){return x.nodeName(this,"form")?!1:(x.event.add(this,"click._submit keypress._submit",function(e){var n=e.target,r=x.nodeName(n,"input")||x.nodeName(n,"button")?n.form:t;r&&!x._data(r,"submitBubbles")&&(x.event.add(r,"submit._submit",function(e){e._submit_bubble=!0}),x._data(r,"submitBubbles",!0))}),t)},postDispatch:function(e){e._submit_bubble&&(delete e._submit_bubble,this.parentNode&&!e.isTrigger&&x.event.simulate("submit",this.parentNode,e,!0))},teardown:function(){return x.nodeName(this,"form")?!1:(x.event.remove(this,"._submit"),t)}}),x.support.changeBubbles||(x.event.special.change={setup:function(){return Z.test(this.nodeName)?(("checkbox"===this.type||"radio"===this.type)&&(x.event.add(this,"propertychange._change",function(e){"checked"===e.originalEvent.propertyName&&(this._just_changed=!0)}),x.event.add(this,"click._change",function(e){this._just_changed&&!e.isTrigger&&(this._just_changed=!1),x.event.simulate("change",this,e,!0)})),!1):(x.event.add(this,"beforeactivate._change",function(e){var t=e.target;Z.test(t.nodeName)&&!x._data(t,"changeBubbles")&&(x.event.add(t,"change._change",function(e){!this.parentNode||e.isSimulated||e.isTrigger||x.event.simulate("change",this.parentNode,e,!0)}),x._data(t,"changeBubbles",!0))}),t)},handle:function(e){var n=e.target;return this!==n||e.isSimulated||e.isTrigger||"radio"!==n.type&&"checkbox"!==n.type?e.handleObj.handler.apply(this,arguments):t},teardown:function(){return x.event.remove(this,"._change"),!Z.test(this.nodeName)}}),x.support.focusinBubbles||x.each({focus:"focusin",blur:"focusout"},function(e,t){var n=0,r=function(e){x.event.simulate(t,e.target,x.event.fix(e),!0)};x.event.special[t]={setup:function(){0===n++&&a.addEventListener(e,r,!0)},teardown:function(){0===--n&&a.removeEventListener(e,r,!0)}}}),x.fn.extend({on:function(e,n,r,i,o){var a,s;if("object"==typeof e){"string"!=typeof n&&(r=r||n,n=t);for(a in e)this.on(a,n,r,e[a],o);return this}if(null==r&&null==i?(i=n,r=n=t):null==i&&("string"==typeof n?(i=r,r=t):(i=r,r=n,n=t)),i===!1)i=ot;else if(!i)return this;return 1===o&&(s=i,i=function(e){return x().off(e),s.apply(this,arguments)},i.guid=s.guid||(s.guid=x.guid++)),this.each(function(){x.event.add(this,e,i,r,n)})},one:function(e,t,n,r){return this.on(e,t,n,r,1)},off:function(e,n,r){var i,o;if(e&&e.preventDefault&&e.handleObj)return i=e.handleObj,x(e.delegateTarget).off(i.namespace?i.origType+"."+i.namespace:i.origType,i.selector,i.handler),this;if("object"==typeof e){for(o in e)this.off(o,n,e[o]);return this}return(n===!1||"function"==typeof n)&&(r=n,n=t),r===!1&&(r=ot),this.each(function(){x.event.remove(this,e,r,n)})},trigger:function(e,t){return this.each(function(){x.event.trigger(e,t,this)})},triggerHandler:function(e,n){var r=this[0];return r?x.event.trigger(e,n,r,!0):t}});var st=/^.[^:#\[\.,]*$/,lt=/^(?:parents|prev(?:Until|All))/,ut=x.expr.match.needsContext,ct={children:!0,contents:!0,next:!0,prev:!0};x.fn.extend({find:function(e){var t,n=[],r=this,i=r.length;if("string"!=typeof e)return this.pushStack(x(e).filter(function(){for(t=0;i>t;t++)if(x.contains(r[t],this))return!0}));for(t=0;i>t;t++)x.find(e,r[t],n);return n=this.pushStack(i>1?x.unique(n):n),n.selector=this.selector?this.selector+" "+e:e,n},has:function(e){var t,n=x(e,this),r=n.length;return this.filter(function(){for(t=0;r>t;t++)if(x.contains(this,n[t]))return!0})},not:function(e){return this.pushStack(ft(this,e||[],!0))},filter:function(e){return this.pushStack(ft(this,e||[],!1))},is:function(e){return!!ft(this,"string"==typeof e&&ut.test(e)?x(e):e||[],!1).length},closest:function(e,t){var n,r=0,i=this.length,o=[],a=ut.test(e)||"string"!=typeof e?x(e,t||this.context):0;for(;i>r;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(11>n.nodeType&&(a?a.index(n)>-1:1===n.nodeType&&x.find.matchesSelector(n,e))){n=o.push(n);break}return this.pushStack(o.length>1?x.unique(o):o)},index:function(e){return e?"string"==typeof e?x.inArray(this[0],x(e)):x.inArray(e.jquery?e[0]:e,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){var n="string"==typeof e?x(e,t):x.makeArray(e&&e.nodeType?[e]:e),r=x.merge(this.get(),n);return this.pushStack(x.unique(r))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}});function pt(e,t){do e=e[t];while(e&&1!==e.nodeType);return e}x.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return x.dir(e,"parentNode")},parentsUntil:function(e,t,n){return x.dir(e,"parentNode",n)},next:function(e){return pt(e,"nextSibling")},prev:function(e){return pt(e,"previousSibling")},nextAll:function(e){return x.dir(e,"nextSibling")},prevAll:function(e){return x.dir(e,"previousSibling")},nextUntil:function(e,t,n){return x.dir(e,"nextSibling",n)},prevUntil:function(e,t,n){return x.dir(e,"previousSibling",n)},siblings:function(e){return x.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return x.sibling(e.firstChild)},contents:function(e){return x.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:x.merge([],e.childNodes)}},function(e,t){x.fn[e]=function(n,r){var i=x.map(this,t,n);return"Until"!==e.slice(-5)&&(r=n),r&&"string"==typeof r&&(i=x.filter(r,i)),this.length>1&&(ct[e]||(i=x.unique(i)),lt.test(e)&&(i=i.reverse())),this.pushStack(i)}}),x.extend({filter:function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?x.find.matchesSelector(r,e)?[r]:[]:x.find.matches(e,x.grep(t,function(e){return 1===e.nodeType}))},dir:function(e,n,r){var i=[],o=e[n];while(o&&9!==o.nodeType&&(r===t||1!==o.nodeType||!x(o).is(r)))1===o.nodeType&&i.push(o),o=o[n];return i},sibling:function(e,t){var n=[];for(;e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}});function ft(e,t,n){if(x.isFunction(t))return x.grep(e,function(e,r){return!!t.call(e,r,e)!==n});if(t.nodeType)return x.grep(e,function(e){return e===t!==n});if("string"==typeof t){if(st.test(t))return x.filter(t,e,n);t=x.filter(t,e)}return x.grep(e,function(e){return x.inArray(e,t)>=0!==n})}function dt(e){var t=ht.split("|"),n=e.createDocumentFragment();if(n.createElement)while(t.length)n.createElement(t.pop());return n}var ht="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",gt=/ jQuery\d+="(?:null|\d+)"/g,mt=RegExp("<(?:"+ht+")[\\s/>]","i"),yt=/^\s+/,vt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bt=/<([\w:]+)/,xt=/\s*$/g,At={option:[1,""],legend:[1,"
","
"],area:[1,"",""],param:[1,"",""],thead:[1,"","
"],tr:[2,"","
"],col:[2,"","
"],td:[3,"","
"],_default:x.support.htmlSerialize?[0,"",""]:[1,"X
","
"]},jt=dt(a),Dt=jt.appendChild(a.createElement("div"));At.optgroup=At.option,At.tbody=At.tfoot=At.colgroup=At.caption=At.thead,At.th=At.td,x.fn.extend({text:function(e){return x.access(this,function(e){return e===t?x.text(this):this.empty().append((this[0]&&this[0].ownerDocument||a).createTextNode(e))},null,e,arguments.length)},append:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Lt(this,e);t.appendChild(e)}})},prepend:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Lt(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},remove:function(e,t){var n,r=e?x.filter(e,this):this,i=0;for(;null!=(n=r[i]);i++)t||1!==n.nodeType||x.cleanData(Ft(n)),n.parentNode&&(t&&x.contains(n.ownerDocument,n)&&_t(Ft(n,"script")),n.parentNode.removeChild(n));return this},empty:function(){var e,t=0;for(;null!=(e=this[t]);t++){1===e.nodeType&&x.cleanData(Ft(e,!1));while(e.firstChild)e.removeChild(e.firstChild);e.options&&x.nodeName(e,"select")&&(e.options.length=0)}return this},clone:function(e,t){return e=null==e?!1:e,t=null==t?e:t,this.map(function(){return x.clone(this,e,t)})},html:function(e){return x.access(this,function(e){var n=this[0]||{},r=0,i=this.length;if(e===t)return 1===n.nodeType?n.innerHTML.replace(gt,""):t;if(!("string"!=typeof e||Tt.test(e)||!x.support.htmlSerialize&&mt.test(e)||!x.support.leadingWhitespace&&yt.test(e)||At[(bt.exec(e)||["",""])[1].toLowerCase()])){e=e.replace(vt,"<$1>");try{for(;i>r;r++)n=this[r]||{},1===n.nodeType&&(x.cleanData(Ft(n,!1)),n.innerHTML=e);n=0}catch(o){}}n&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var e=x.map(this,function(e){return[e.nextSibling,e.parentNode]}),t=0;return this.domManip(arguments,function(n){var r=e[t++],i=e[t++];i&&(r&&r.parentNode!==i&&(r=this.nextSibling),x(this).remove(),i.insertBefore(n,r))},!0),t?this:this.remove()},detach:function(e){return this.remove(e,!0)},domManip:function(e,t,n){e=d.apply([],e);var r,i,o,a,s,l,u=0,c=this.length,p=this,f=c-1,h=e[0],g=x.isFunction(h);if(g||!(1>=c||"string"!=typeof h||x.support.checkClone)&&Nt.test(h))return this.each(function(r){var i=p.eq(r);g&&(e[0]=h.call(this,r,i.html())),i.domManip(e,t,n)});if(c&&(l=x.buildFragment(e,this[0].ownerDocument,!1,!n&&this),r=l.firstChild,1===l.childNodes.length&&(l=r),r)){for(a=x.map(Ft(l,"script"),Ht),o=a.length;c>u;u++)i=l,u!==f&&(i=x.clone(i,!0,!0),o&&x.merge(a,Ft(i,"script"))),t.call(this[u],i,u);if(o)for(s=a[a.length-1].ownerDocument,x.map(a,qt),u=0;o>u;u++)i=a[u],kt.test(i.type||"")&&!x._data(i,"globalEval")&&x.contains(s,i)&&(i.src?x._evalUrl(i.src):x.globalEval((i.text||i.textContent||i.innerHTML||"").replace(St,"")));l=r=null}return this}});function Lt(e,t){return x.nodeName(e,"table")&&x.nodeName(1===t.nodeType?t:t.firstChild,"tr")?e.getElementsByTagName("tbody")[0]||e.appendChild(e.ownerDocument.createElement("tbody")):e}function Ht(e){return e.type=(null!==x.find.attr(e,"type"))+"/"+e.type,e}function qt(e){var t=Et.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function _t(e,t){var n,r=0;for(;null!=(n=e[r]);r++)x._data(n,"globalEval",!t||x._data(t[r],"globalEval"))}function Mt(e,t){if(1===t.nodeType&&x.hasData(e)){var n,r,i,o=x._data(e),a=x._data(t,o),s=o.events;if(s){delete a.handle,a.events={};for(n in s)for(r=0,i=s[n].length;i>r;r++)x.event.add(t,n,s[n][r])}a.data&&(a.data=x.extend({},a.data))}}function Ot(e,t){var n,r,i;if(1===t.nodeType){if(n=t.nodeName.toLowerCase(),!x.support.noCloneEvent&&t[x.expando]){i=x._data(t);for(r in i.events)x.removeEvent(t,r,i.handle);t.removeAttribute(x.expando)}"script"===n&&t.text!==e.text?(Ht(t).text=e.text,qt(t)):"object"===n?(t.parentNode&&(t.outerHTML=e.outerHTML),x.support.html5Clone&&e.innerHTML&&!x.trim(t.innerHTML)&&(t.innerHTML=e.innerHTML)):"input"===n&&Ct.test(e.type)?(t.defaultChecked=t.checked=e.checked,t.value!==e.value&&(t.value=e.value)):"option"===n?t.defaultSelected=t.selected=e.defaultSelected:("input"===n||"textarea"===n)&&(t.defaultValue=e.defaultValue)}}x.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){x.fn[e]=function(e){var n,r=0,i=[],o=x(e),a=o.length-1;for(;a>=r;r++)n=r===a?this:this.clone(!0),x(o[r])[t](n),h.apply(i,n.get());return this.pushStack(i)}});function Ft(e,n){var r,o,a=0,s=typeof e.getElementsByTagName!==i?e.getElementsByTagName(n||"*"):typeof e.querySelectorAll!==i?e.querySelectorAll(n||"*"):t;if(!s)for(s=[],r=e.childNodes||e;null!=(o=r[a]);a++)!n||x.nodeName(o,n)?s.push(o):x.merge(s,Ft(o,n));return n===t||n&&x.nodeName(e,n)?x.merge([e],s):s}function Bt(e){Ct.test(e.type)&&(e.defaultChecked=e.checked)}x.extend({clone:function(e,t,n){var r,i,o,a,s,l=x.contains(e.ownerDocument,e);if(x.support.html5Clone||x.isXMLDoc(e)||!mt.test("<"+e.nodeName+">")?o=e.cloneNode(!0):(Dt.innerHTML=e.outerHTML,Dt.removeChild(o=Dt.firstChild)),!(x.support.noCloneEvent&&x.support.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||x.isXMLDoc(e)))for(r=Ft(o),s=Ft(e),a=0;null!=(i=s[a]);++a)r[a]&&Ot(i,r[a]);if(t)if(n)for(s=s||Ft(e),r=r||Ft(o),a=0;null!=(i=s[a]);a++)Mt(i,r[a]);else Mt(e,o);return r=Ft(o,"script"),r.length>0&&_t(r,!l&&Ft(e,"script")),r=s=i=null,o},buildFragment:function(e,t,n,r){var i,o,a,s,l,u,c,p=e.length,f=dt(t),d=[],h=0;for(;p>h;h++)if(o=e[h],o||0===o)if("object"===x.type(o))x.merge(d,o.nodeType?[o]:o);else if(wt.test(o)){s=s||f.appendChild(t.createElement("div")),l=(bt.exec(o)||["",""])[1].toLowerCase(),c=At[l]||At._default,s.innerHTML=c[1]+o.replace(vt,"<$1>")+c[2],i=c[0];while(i--)s=s.lastChild;if(!x.support.leadingWhitespace&&yt.test(o)&&d.push(t.createTextNode(yt.exec(o)[0])),!x.support.tbody){o="table"!==l||xt.test(o)?""!==c[1]||xt.test(o)?0:s:s.firstChild,i=o&&o.childNodes.length;while(i--)x.nodeName(u=o.childNodes[i],"tbody")&&!u.childNodes.length&&o.removeChild(u)}x.merge(d,s.childNodes),s.textContent="";while(s.firstChild)s.removeChild(s.firstChild);s=f.lastChild}else d.push(t.createTextNode(o));s&&f.removeChild(s),x.support.appendChecked||x.grep(Ft(d,"input"),Bt),h=0;while(o=d[h++])if((!r||-1===x.inArray(o,r))&&(a=x.contains(o.ownerDocument,o),s=Ft(f.appendChild(o),"script"),a&&_t(s),n)){i=0;while(o=s[i++])kt.test(o.type||"")&&n.push(o)}return s=null,f},cleanData:function(e,t){var n,r,o,a,s=0,l=x.expando,u=x.cache,c=x.support.deleteExpando,f=x.event.special;for(;null!=(n=e[s]);s++)if((t||x.acceptData(n))&&(o=n[l],a=o&&u[o])){if(a.events)for(r in a.events)f[r]?x.event.remove(n,r):x.removeEvent(n,r,a.handle); +u[o]&&(delete u[o],c?delete n[l]:typeof n.removeAttribute!==i?n.removeAttribute(l):n[l]=null,p.push(o))}},_evalUrl:function(e){return x.ajax({url:e,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})}}),x.fn.extend({wrapAll:function(e){if(x.isFunction(e))return this.each(function(t){x(this).wrapAll(e.call(this,t))});if(this[0]){var t=x(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstChild&&1===e.firstChild.nodeType)e=e.firstChild;return e}).append(this)}return this},wrapInner:function(e){return x.isFunction(e)?this.each(function(t){x(this).wrapInner(e.call(this,t))}):this.each(function(){var t=x(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=x.isFunction(e);return this.each(function(n){x(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){x.nodeName(this,"body")||x(this).replaceWith(this.childNodes)}).end()}});var Pt,Rt,Wt,$t=/alpha\([^)]*\)/i,It=/opacity\s*=\s*([^)]*)/,zt=/^(top|right|bottom|left)$/,Xt=/^(none|table(?!-c[ea]).+)/,Ut=/^margin/,Vt=RegExp("^("+w+")(.*)$","i"),Yt=RegExp("^("+w+")(?!px)[a-z%]+$","i"),Jt=RegExp("^([+-])=("+w+")","i"),Gt={BODY:"block"},Qt={position:"absolute",visibility:"hidden",display:"block"},Kt={letterSpacing:0,fontWeight:400},Zt=["Top","Right","Bottom","Left"],en=["Webkit","O","Moz","ms"];function tn(e,t){if(t in e)return t;var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=en.length;while(i--)if(t=en[i]+n,t in e)return t;return r}function nn(e,t){return e=t||e,"none"===x.css(e,"display")||!x.contains(e.ownerDocument,e)}function rn(e,t){var n,r,i,o=[],a=0,s=e.length;for(;s>a;a++)r=e[a],r.style&&(o[a]=x._data(r,"olddisplay"),n=r.style.display,t?(o[a]||"none"!==n||(r.style.display=""),""===r.style.display&&nn(r)&&(o[a]=x._data(r,"olddisplay",ln(r.nodeName)))):o[a]||(i=nn(r),(n&&"none"!==n||!i)&&x._data(r,"olddisplay",i?n:x.css(r,"display"))));for(a=0;s>a;a++)r=e[a],r.style&&(t&&"none"!==r.style.display&&""!==r.style.display||(r.style.display=t?o[a]||"":"none"));return e}x.fn.extend({css:function(e,n){return x.access(this,function(e,n,r){var i,o,a={},s=0;if(x.isArray(n)){for(o=Rt(e),i=n.length;i>s;s++)a[n[s]]=x.css(e,n[s],!1,o);return a}return r!==t?x.style(e,n,r):x.css(e,n)},e,n,arguments.length>1)},show:function(){return rn(this,!0)},hide:function(){return rn(this)},toggle:function(e){return"boolean"==typeof e?e?this.show():this.hide():this.each(function(){nn(this)?x(this).show():x(this).hide()})}}),x.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Wt(e,"opacity");return""===n?"1":n}}}},cssNumber:{columnCount:!0,fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":x.support.cssFloat?"cssFloat":"styleFloat"},style:function(e,n,r,i){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var o,a,s,l=x.camelCase(n),u=e.style;if(n=x.cssProps[l]||(x.cssProps[l]=tn(u,l)),s=x.cssHooks[n]||x.cssHooks[l],r===t)return s&&"get"in s&&(o=s.get(e,!1,i))!==t?o:u[n];if(a=typeof r,"string"===a&&(o=Jt.exec(r))&&(r=(o[1]+1)*o[2]+parseFloat(x.css(e,n)),a="number"),!(null==r||"number"===a&&isNaN(r)||("number"!==a||x.cssNumber[l]||(r+="px"),x.support.clearCloneStyle||""!==r||0!==n.indexOf("background")||(u[n]="inherit"),s&&"set"in s&&(r=s.set(e,r,i))===t)))try{u[n]=r}catch(c){}}},css:function(e,n,r,i){var o,a,s,l=x.camelCase(n);return n=x.cssProps[l]||(x.cssProps[l]=tn(e.style,l)),s=x.cssHooks[n]||x.cssHooks[l],s&&"get"in s&&(a=s.get(e,!0,r)),a===t&&(a=Wt(e,n,i)),"normal"===a&&n in Kt&&(a=Kt[n]),""===r||r?(o=parseFloat(a),r===!0||x.isNumeric(o)?o||0:a):a}}),e.getComputedStyle?(Rt=function(t){return e.getComputedStyle(t,null)},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),l=s?s.getPropertyValue(n)||s[n]:t,u=e.style;return s&&(""!==l||x.contains(e.ownerDocument,e)||(l=x.style(e,n)),Yt.test(l)&&Ut.test(n)&&(i=u.width,o=u.minWidth,a=u.maxWidth,u.minWidth=u.maxWidth=u.width=l,l=s.width,u.width=i,u.minWidth=o,u.maxWidth=a)),l}):a.documentElement.currentStyle&&(Rt=function(e){return e.currentStyle},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),l=s?s[n]:t,u=e.style;return null==l&&u&&u[n]&&(l=u[n]),Yt.test(l)&&!zt.test(n)&&(i=u.left,o=e.runtimeStyle,a=o&&o.left,a&&(o.left=e.currentStyle.left),u.left="fontSize"===n?"1em":l,l=u.pixelLeft+"px",u.left=i,a&&(o.left=a)),""===l?"auto":l});function on(e,t,n){var r=Vt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function an(e,t,n,r,i){var o=n===(r?"border":"content")?4:"width"===t?1:0,a=0;for(;4>o;o+=2)"margin"===n&&(a+=x.css(e,n+Zt[o],!0,i)),r?("content"===n&&(a-=x.css(e,"padding"+Zt[o],!0,i)),"margin"!==n&&(a-=x.css(e,"border"+Zt[o]+"Width",!0,i))):(a+=x.css(e,"padding"+Zt[o],!0,i),"padding"!==n&&(a+=x.css(e,"border"+Zt[o]+"Width",!0,i)));return a}function sn(e,t,n){var r=!0,i="width"===t?e.offsetWidth:e.offsetHeight,o=Rt(e),a=x.support.boxSizing&&"border-box"===x.css(e,"boxSizing",!1,o);if(0>=i||null==i){if(i=Wt(e,t,o),(0>i||null==i)&&(i=e.style[t]),Yt.test(i))return i;r=a&&(x.support.boxSizingReliable||i===e.style[t]),i=parseFloat(i)||0}return i+an(e,t,n||(a?"border":"content"),r,o)+"px"}function ln(e){var t=a,n=Gt[e];return n||(n=un(e,t),"none"!==n&&n||(Pt=(Pt||x("