From 8ddf82cf70dc6f951ab477f325dee0efde3ec589 Mon Sep 17 00:00:00 2001 From: Inaky Perez-Gonzalez Date: Fri, 10 Apr 2015 16:44:37 -0700 Subject: [PATCH] First commit Signed-off-by: --- .gitattributes | 5 + .gitignore | 13 + .mailmap | 1 + arch/arc/bsp/fatal_error.c | 115 + arch/arc/bsp/prep_c.c | 108 + arch/arc/bsp/reset.s | 71 + arch/arc/bsp/vector_table.c | 89 + arch/arc/bsp/vector_table.h | 95 + arch/arc/core/atomic.s | 445 ++ arch/arc/core/context.c | 171 + arch/arc/core/context_wrapper.s | 64 + arch/arc/core/cpu_idle.s | 79 + arch/arc/core/fast_irq.s | 284 + arch/arc/core/fatal.c | 114 + arch/arc/core/fault.c | 109 + arch/arc/core/fault_s.s | 107 + arch/arc/core/ffs.s | 94 + arch/arc/core/irq_lock.s | 97 + arch/arc/core/irq_manage.c | 205 + arch/arc/core/isr_wrapper.s | 240 + arch/arc/core/offsets/offsets.c | 126 + arch/arc/core/regular_irq.s | 203 + arch/arc/core/swap.s | 202 + arch/arc/core/swap_macros.h | 176 + arch/arc/defs.objs | 61 + arch/arc/include/nanok.h | 287 + arch/arc/include/v2/cache.h | 66 + arch/arc/include/v2/irq.h | 77 + .../arc/interrupt_controller/arcv2_irq_unit.c | 103 + arch/arc/serial/nsim_uart.c | 81 + arch/arc/timer/arcv2_timer0.c | 247 + arch/arm/bsp/CortexM/nmi.c | 117 + arch/arm/bsp/CortexM/prep_c.c | 108 + arch/arm/bsp/CortexM/reset.s | 93 + arch/arm/bsp/CortexM/scb.c | 109 + arch/arm/bsp/CortexM/scs.c | 46 + arch/arm/bsp/CortexM/vector_table.h | 78 + arch/arm/bsp/CortexM/vector_table.s | 74 + arch/arm/bsp/rand32.c | 78 + arch/arm/bsp/sysFatalErrorHandler.c | 115 + arch/arm/core/atomic.s | 429 ++ arch/arm/core/basepri.s | 95 + arch/arm/core/cpu_idle.s | 198 + arch/arm/core/exc_exit.s | 128 + arch/arm/core/fault.c | 414 ++ arch/arm/core/fault_s.s | 101 + arch/arm/core/ffs.s | 93 + arch/arm/core/gdb_stub.s | 163 + arch/arm/core/gdb_stub_irq_vector_table.c | 52 + arch/arm/core/irq_init.c | 65 + arch/arm/core/irq_manage.c | 189 + arch/arm/core/isr_wrapper.s | 111 + arch/arm/core/nano_fiber_abort.c | 77 + arch/arm/core/nanocontext.c | 151 + arch/arm/core/nanofatal.c | 132 + arch/arm/core/offsets/offsets.c | 104 + arch/arm/core/swap.s | 223 + arch/arm/core/task_abort.c | 86 + arch/arm/defs.objs | 73 + arch/arm/fsl_frdm_k64f/board.h | 217 + arch/arm/fsl_frdm_k64f/defs.objs | 103 + arch/arm/fsl_frdm_k64f/irq_vector_table.c | 65 + arch/arm/fsl_frdm_k64f/linker.cmd | 60 + arch/arm/fsl_frdm_k64f/nmi_on_reset.s | 53 + arch/arm/fsl_frdm_k64f/sw_isr_table.c | 64 + arch/arm/fsl_frdm_k64f/system.c | 381 ++ arch/arm/fsl_frdm_k64f/wdog.s | 104 + arch/arm/include/CortexM/exc.h | 123 + arch/arm/include/CortexM/stack.h | 114 + arch/arm/include/nanok.h | 227 + arch/arm/include/start_task_arch.h | 56 + arch/arm/ti_lm3s6965/board.h | 149 + arch/arm/ti_lm3s6965/defs.objs | 102 + arch/arm/ti_lm3s6965/irq_vector_table.c | 67 + arch/arm/ti_lm3s6965/linker.cmd | 38 + arch/arm/ti_lm3s6965/nmi_on_reset.s | 53 + arch/arm/ti_lm3s6965/scp.c | 68 + arch/arm/ti_lm3s6965/scp.h | 179 + arch/arm/ti_lm3s6965/sw_isr_table.c | 66 + arch/arm/ti_lm3s6965/system.c | 135 + arch/arm/timer/systick.c | 726 +++ arch/arm/timer/systick_gdb.s | 57 + arch/x86/bsp/cache.c | 75 + arch/x86/bsp/cache_s.s | 64 + arch/x86/bsp/crt0.s | 662 +++ arch/x86/bsp/driver_static_irq_stubs.s | 145 + arch/x86/bsp/i8259Boi.s | 151 + arch/x86/bsp/rand32.c | 84 + arch/x86/bsp/sysFatalErrorHandler.c | 112 + arch/x86/bsp/systemApic.c | 252 + arch/x86/bsp/systemPic.c | 150 + arch/x86/core/cpuhalt.s | 169 + arch/x86/core/excconnect.c | 246 + arch/x86/core/excstub.s | 322 + arch/x86/core/ffs.s | 134 + arch/x86/core/gdt.c | 103 + arch/x86/core/intboiexit.s | 82 + arch/x86/core/intconnect.c | 600 ++ arch/x86/core/inthndlset.c | 146 + arch/x86/core/intstub.s | 525 ++ arch/x86/core/msr.s | 105 + arch/x86/core/nanoatomic.s | 499 ++ arch/x86/core/nanoatomic_nolock.c | 364 ++ arch/x86/core/nanocontext.c | 404 ++ arch/x86/core/nanofatal.c | 147 + arch/x86/core/nanofloat.c | 556 ++ arch/x86/core/offsets/offsets.c | 158 + arch/x86/core/swap.s | 391 ++ arch/x86/core/unaligned.s | 123 + arch/x86/defs.objs | 71 + arch/x86/generic_pc/board.h | 386 ++ arch/x86/generic_pc/defs.objs | 115 + arch/x86/generic_pc/linker.cmd | 75 + arch/x86/generic_pc/system.c | 167 + arch/x86/include/advidle.h | 91 + arch/x86/include/asmPrv.h | 103 + arch/x86/include/gdt.h | 84 + arch/x86/include/idtEnt.h | 1 + arch/x86/include/nanok.h | 967 +++ arch/x86/include/start_task_arch.h | 54 + arch/x86/include/swapstk.h | 62 + arch/x86/interrupt_controller/ioApicIntr.c | 608 ++ arch/x86/interrupt_controller/loApicIntr.c | 420 ++ arch/x86/quark/board.h | 477 ++ arch/x86/quark/defs.objs | 80 + arch/x86/quark/linker.cmd | 75 + arch/x86/quark/system.c | 176 + arch/x86/task/strtask.c | 96 + arch/x86/timer/hpet.c | 712 +++ arch/x86/timer/loApicTimer.c | 679 +++ config/fsl_frdm_k64f/bsp.kconf | 80 + config/fsl_frdm_k64f/defs.bsp | 39 + .../fsl_frdm_k64f/nkernel/bsp-nkernel.kconf | 34 + .../fsl_frdm_k64f/ukernel/bsp-ukernel.kconf | 34 + config/fsl_frdm_k64f/ukernel/config1p.vpf | 42 + config/generic_pc/bsp-atom_n28xx.kconf | 73 + config/generic_pc/bsp-minuteia.kconf | 67 + config/generic_pc/bsp-pentium4.kconf | 70 + config/generic_pc/defs.bsp | 41 + .../nkernel/bsp-nkernelatom_n28xx.kconf | 34 + .../nkernel/bsp-nkernelminuteia.kconf | 34 + .../nkernel/bsp-nkernelpentium4.kconf | 34 + .../ukernel/bsp-ukernelatom_n28xx.kconf | 34 + .../ukernel/bsp-ukernelminuteia.kconf | 34 + .../ukernel/bsp-ukernelpentium4.kconf | 34 + config/generic_pc/ukernel/config1p.vpf | 41 + config/quark/bsp.kconf | 92 + config/quark/defs.bsp | 38 + config/quark/nkernel/bsp-nkernel.kconf | 35 + config/quark/ukernel/bsp-ukernel.kconf | 35 + config/quark/ukernel/config1p.vpf | 41 + config/ti_lm3s6965/bsp.kconf | 79 + config/ti_lm3s6965/defs.bsp | 42 + config/ti_lm3s6965/nkernel/bsp-nkernel.kconf | 34 + config/ti_lm3s6965/ukernel/bsp-ukernel.kconf | 34 + config/ti_lm3s6965/ukernel/config1p.vpf | 42 + drivers/console/uart_console.c | 120 + drivers/console/uart_console.h | 48 + drivers/defs.objs | 40 + drivers/interrupt_controller/i8259.c | 333 ++ drivers/pci/pci.c | 397 ++ drivers/pci/pci.h | 70 + drivers/pci/pci_config.c | 303 + drivers/pci/pci_interface.c | 426 ++ drivers/pci/pci_mgr.h | 1649 ++++++ drivers/random/rand32-timer.c | 78 + drivers/serial/k20UartDrv.c | 408 ++ drivers/serial/ns16550.c | 540 ++ drivers/serial/stellarisUartDrv.c | 597 ++ drivers/timer/i8253.c | 660 +++ host/src/Makefile | 35 + host/src/dec2hex/Makefile | 35 + host/src/dec2hex/dec2hex.c | 56 + host/src/genIdt/Makefile | 34 + host/src/genIdt/genIdt.c | 339 ++ host/src/genIdt/idtEnt.h | 1 + host/src/genIdt/segselect.h | 1 + host/src/genOffsetHeader/Makefile | 33 + host/src/genOffsetHeader/elf.h | 389 ++ host/src/genOffsetHeader/genOffsetHeader.c | 716 +++ host/src/gen_config_abssym/Makefile | 33 + .../src/gen_config_abssym/gen_config_abssym.c | 261 + host/src/include/vxmicro.h | 35 + host/src/include/vxmicro/os.h | 59 + host/src/include/vxmicro/util.h | 46 + host/src/include/vxmicro/version.h | 40 + host/src/lib/Makefile | 33 + host/src/lib/os.c | 56 + host/src/lib/util.c | 49 + host/src/lib/version.c | 45 + host/src/mkEvents/Makefile | 35 + host/src/mkEvents/mkevents.c | 71 + host/src/wrsconfig/COPYING-GPL-2.0.txt | 340 ++ host/src/wrsconfig/Makefile | 37 + host/src/wrsconfig/conf.c | 695 +++ host/src/wrsconfig/confdata.c | 915 +++ host/src/wrsconfig/expr.c | 1100 ++++ host/src/wrsconfig/expr.h | 200 + host/src/wrsconfig/fixdep.c | 399 ++ host/src/wrsconfig/lex.zconf.c | 2266 +++++++ host/src/wrsconfig/lkc.h | 175 + host/src/wrsconfig/lkc_proto.h | 74 + host/src/wrsconfig/menu.c | 431 ++ host/src/wrsconfig/symbol.c | 887 +++ host/src/wrsconfig/test/h/config/auto.conf | 5 + .../src/wrsconfig/test/h/config/auto.conf.cmd | 7 + host/src/wrsconfig/test/h/config/autoconf.h | 6 + .../h/config/wrsconfig/config/nano/kernel.h | 0 .../h/config/wrsconfig/config/standalone.h | 0 host/src/wrsconfig/test/vsb.config | 8 + host/src/wrsconfig/test/vsb.config.old | 5 + host/src/wrsconfig/test/vxmicro.wrsconfig | 94 + host/src/wrsconfig/util.c | 111 + host/src/wrsconfig/vxmicro.wrsconfig | 94 + host/src/wrsconfig/zconf.hash.c | 242 + host/src/wrsconfig/zconf.tab.c | 2348 ++++++++ host/x86-linux2/bin/cat3files | 34 + host/x86-linux2/bin/dirlist | 52 + host/x86-linux2/bin/filelist | 43 + host/x86-linux2/bin/make-ll | 42 + host/x86-linux2/bin/truesize | 52 + host/x86-linux2/bin/truesize.awk | 209 + host/x86-linux2/lib/build_tools/.keep | 0 include/absSym.h | 99 + include/clock_vars.h | 70 + include/cputype.h | 54 + include/drivers/ioapic.h | 81 + include/drivers/k20Mcg.h | 221 + include/drivers/k20Pcr.h | 105 + include/drivers/k20Sim.h | 234 + include/drivers/k20Uart.h | 252 + include/drivers/k20Wdog.h | 152 + include/drivers/k6xMpu.h | 90 + include/drivers/k6xPmc.h | 71 + include/drivers/loapic.h | 84 + include/drivers/pic.h | 81 + include/drivers/rand32.h | 53 + include/drivers/system_timer.h | 69 + include/drivers/uart.h | 76 + include/kernel_version.h | 62 + include/linker-defs.h | 112 + include/linker-tool-gcc.h | 105 + include/linker-tool.h | 52 + include/microkernel.h | 136 + include/microkernel/chan.h | 141 + include/microkernel/cmdPkt.h | 93 + include/microkernel/entries.h | 130 + include/microkernel/event.h | 54 + include/microkernel/event_api_export.h | 40 + include/microkernel/fifo.h | 52 + include/microkernel/fifo_api_export.h | 54 + include/microkernel/k_boot.h | 76 + include/microkernel/k_chstr.h | 156 + include/microkernel/k_struct.h | 611 ++ include/microkernel/k_types.h | 123 + include/microkernel/mail.h | 68 + include/microkernel/mail_api_export.h | 47 + include/microkernel/memcpy.h | 52 + include/microkernel/mmap.h | 59 + include/microkernel/mutex.h | 49 + include/microkernel/mutex_api_export.h | 45 + include/microkernel/pool.h | 61 + include/microkernel/sema.h | 58 + include/microkernel/sema_api_export.h | 45 + include/microkernel/task.h | 102 + include/microkernel/task_api_export.h | 58 + include/microkernel/task_irq.h | 55 + include/microkernel/task_irq_api_export.h | 42 + include/microkernel/ticks.h | 118 + include/microkernel/util/mallocInit.h | 57 + include/misc/__assert.h | 137 + include/misc/dlist.h | 61 + include/misc/lists.h | 78 + include/misc/lists_c.h | 155 + include/misc/printk.h | 33 + include/misc/util.h | 102 + include/nanokernel.h | 246 + include/nanokernel/arc/arch.h | 67 + include/nanokernel/arc/arcprc.h | 69 + include/nanokernel/arc/v2/arcv2_irq_unit.h | 124 + include/nanokernel/arc/v2/aux_regs.h | 119 + include/nanokernel/arc/v2/error.h | 54 + include/nanokernel/arc/v2/exc.h | 52 + include/nanokernel/arc/v2/ffs.h | 109 + include/nanokernel/arc/v2/init.h | 46 + include/nanokernel/arc/v2/irq.h | 111 + include/nanokernel/arc/v2/misc.h | 47 + include/nanokernel/arm/ARMprc.h | 65 + include/nanokernel/arm/CortexM/error.h | 54 + include/nanokernel/arm/CortexM/exc.h | 62 + include/nanokernel/arm/CortexM/ffs.h | 120 + include/nanokernel/arm/CortexM/gdb_stub.h | 75 + include/nanokernel/arm/CortexM/init.h | 46 + include/nanokernel/arm/CortexM/irq.h | 161 + .../nanokernel/arm/CortexM/memory_map-m0.h | 53 + .../nanokernel/arm/CortexM/memory_map-m3.h | 67 + include/nanokernel/arm/CortexM/memory_map.h | 83 + include/nanokernel/arm/CortexM/misc.h | 45 + include/nanokernel/arm/CortexM/nvic.h | 237 + include/nanokernel/arm/CortexM/scb.h | 1232 ++++ .../nanokernel/arm/CortexM/scripts/linker.cmd | 220 + include/nanokernel/arm/CortexM/scs.h | 568 ++ include/nanokernel/arm/arch.h | 70 + include/nanokernel/cpu.h | 46 + include/nanokernel/private.h | 95 + include/nanokernel/x86/Intelprc.h | 71 + include/nanokernel/x86/addr_types.h | 43 + include/nanokernel/x86/arch.h | 687 +++ include/nanokernel/x86/asm.h | 52 + include/nanokernel/x86/k_mem-gcc.h | 75 + include/nanokernel/x86/k_mem-other.h | 91 + include/nanokernel/x86/k_mem.h | 67 + .../nanokernel/x86/linker-common-sections.h | 219 + include/nanokernel/x86/linker-defs-arch.h | 65 + include/nanokernel/x86/linker-epilog.h | 95 + include/nanokernel/x86/segselect.h | 1 + include/section_tags.h | 82 + include/sections.h | 96 + include/string_s.h | 101 + include/sw_isr_table.h | 57 + include/toolchain.h | 52 + include/toolchain/common.h | 131 + include/toolchain/gcc.h | 303 + include/toolchain/unsupported.h | 68 + kernel/common/bsp/ctors.c | 82 + kernel/common/bsp/init.c | 158 + kernel/common/string_s.c | 155 + kernel/common/util/defs.objs | 48 + kernel/common/version.c | 66 + kernel/defs.objs | 14 + kernel/microkernel/channel/InitChan.c | 55 + kernel/microkernel/channel/KS_ChGet.c | 96 + kernel/microkernel/channel/KS_ChPtA.c | 87 + kernel/microkernel/channel/KS_ChPut.c | 96 + kernel/microkernel/channel/KS_Chan.c | 309 + kernel/microkernel/channel/K_ChGAck.c | 56 + kernel/microkernel/channel/K_ChGReq.c | 233 + kernel/microkernel/channel/K_ChGRpl.c | 92 + kernel/microkernel/channel/K_ChGTmo.c | 56 + kernel/microkernel/channel/K_ChPAck.c | 84 + kernel/microkernel/channel/K_ChPReq.c | 260 + kernel/microkernel/channel/K_ChPRpl.c | 96 + kernel/microkernel/channel/K_ChPTmo.c | 56 + kernel/microkernel/channel/K_ChProc.c | 561 ++ kernel/microkernel/channel/K_Ch_Mvd.c | 371 ++ kernel/microkernel/channel/K_Ch_RO.c | 120 + kernel/microkernel/channel/K_Ch_WO.c | 122 + kernel/microkernel/channel/K_Ch_WR.c | 184 + kernel/microkernel/channel/ch_addit.c | 294 + kernel/microkernel/channel/ch_buff.c | 590 ++ kernel/microkernel/channel/ch_buffm.c | 217 + kernel/microkernel/core/cmdPkt.c | 87 + kernel/microkernel/core/flashboot.c | 48 + kernel/microkernel/core/global.c | 113 + kernel/microkernel/core/k_remrpl.c | 41 + kernel/microkernel/core/netload.c | 51 + kernel/microkernel/core/taskcall.c | 53 + kernel/microkernel/defs.objs | 55 + kernel/microkernel/idle.c | 318 + kernel/microkernel/include/ch_buff.h | 123 + kernel/microkernel/include/ch_buffm.h | 63 + kernel/microkernel/include/ch_cfg.h | 59 + kernel/microkernel/include/kchan.h | 102 + kernel/microkernel/include/kevent.h | 46 + kernel/microkernel/include/kfifo.h | 42 + kernel/microkernel/include/kmail.h | 62 + kernel/microkernel/include/kmemcpy.h | 45 + kernel/microkernel/include/kmemp.h | 41 + kernel/microkernel/include/kmmap.h | 40 + kernel/microkernel/include/kres.h | 40 + kernel/microkernel/include/ksema.h | 51 + kernel/microkernel/include/ktask.h | 48 + kernel/microkernel/include/kticks.h | 71 + kernel/microkernel/include/minik.h | 267 + kernel/microkernel/include/v1.h | 42 + kernel/microkernel/include/v3.h | 39 + kernel/microkernel/k_event.c | 299 + kernel/microkernel/k_irq.c | 282 + kernel/microkernel/k_mbox.c | 985 ++++ kernel/microkernel/k_memmap.c | 229 + kernel/microkernel/k_mempool.c | 708 +++ kernel/microkernel/k_mutex.c | 406 ++ kernel/microkernel/k_nop.c | 75 + kernel/microkernel/k_offload.c | 73 + kernel/microkernel/k_queue.c | 351 ++ kernel/microkernel/k_sema.c | 689 +++ kernel/microkernel/k_task.c | 473 ++ kernel/microkernel/k_timer.c | 557 ++ kernel/microkernel/movedata/K_cpyreq.c | 56 + kernel/microkernel/movedata/K_cpyrpl.c | 56 + kernel/microkernel/movedata/ks_moved.c | 64 + kernel/microkernel/movedata/movedata.c | 130 + kernel/microkernel/power.c | 138 + kernel/microkernel/task_monitor.c | 122 + kernel/microkernel/timer/ticker.c | 302 + kernel/microkernel/timer/ticks.c | 65 + .../nanokernel/core/compiler_stack_protect.c | 95 + kernel/nanokernel/core/idle.c | 63 + kernel/nanokernel/core/int_latency_bench.c | 265 + kernel/nanokernel/core/microk.c | 240 + kernel/nanokernel/core/nano_context_data.c | 74 + kernel/nanokernel/core/nano_lifo.c | 324 + kernel/nanokernel/core/nano_mwfifo.c | 362 ++ kernel/nanokernel/core/nano_sema.c | 281 + kernel/nanokernel/core/nano_stack.c | 322 + kernel/nanokernel/core/nano_timer.c | 299 + kernel/nanokernel/core/nanocontextentry.c | 165 + kernel/nanokernel/core/nanofiber.c | 344 ++ kernel/nanokernel/core/nanoinit.c | 193 + kernel/nanokernel/core/nanometrics.c | 44 + kernel/nanokernel/core/nanotime.c | 131 + kernel/nanokernel/include/genOffset.h | 153 + kernel/nanokernel/include/nanocontextentry.h | 60 + kernel/nanokernel/include/offsets/common.h | 71 + kernel/nanokernel/task/start_task.c | 91 + lib/libc/minimal/Makefile | 60 + lib/libc/minimal/include/errno.h | 153 + lib/libc/minimal/include/limits.h | 71 + lib/libc/minimal/include/stdbool.h | 42 + lib/libc/minimal/include/stddef.h | 52 + lib/libc/minimal/include/stdint.h | 73 + lib/libc/minimal/include/stdio.h | 82 + lib/libc/minimal/include/stdlib.h | 45 + lib/libc/minimal/include/string.h | 56 + lib/libc/minimal/source/stdout/fprintf.c | 81 + lib/libc/minimal/source/stdout/prf.c | 816 +++ lib/libc/minimal/source/stdout/sprintf.c | 134 + .../minimal/source/stdout/stdout_console.c | 106 + lib/libc/minimal/source/string/string.c | 230 + make/env/defs.base | 160 + make/env/defs.host | 48 + make/env/defs.host.linux2 | 45 + make/env/defs.host.x86-linux2 | 92 + make/env/defs.kver | 88 + make/env/rules.shared | 36 + make/env/rules.wb-helper | 43 + make/env/sanity_check | 33 + make/host/dir.rules | 65 + make/host/exe.build | 49 + make/host/exe.defs | 66 + make/host/exe.rules | 49 + make/host/lib.build | 45 + make/host/lib.defs | 50 + make/host/lib.rules | 48 + make/host/obj.defs | 66 + make/host/obj.rules | 89 + make/host/toolchain.defs | 40 + make/host/top.rules | 50 + make/target/arch/arc/defs.arch | 33 + make/target/arch/arc/rules.arch | 33 + make/target/arch/arm/defs.arch | 33 + make/target/arch/arm/rules.arch | 33 + make/target/arch/x86/defs.arch | 33 + make/target/arch/x86/rules.arch | 33 + make/target/arch/x86/rules.idt | 69 + make/target/env/defs.ext | 39 + make/target/env/defs.target | 43 + make/target/headers/defs.autoconf.check | 42 + make/target/headers/defs.autoconf.kernel | 63 + make/target/headers/defs.kver | 43 + make/target/headers/defs.offsets | 64 + make/target/headers/rules.autoconf | 86 + make/target/headers/rules.kver | 47 + make/target/headers/rules.offsets | 41 + make/target/kconfig/arch/arc/arc.kconf | 41 + make/target/kconfig/arch/arc/arc_em4.kconf | 44 + make/target/kconfig/arch/arc/arc_v2.kconf | 207 + make/target/kconfig/arch/arc/build.kconf | 39 + .../target/kconfig/arch/arc/kernel-core.kconf | 84 + make/target/kconfig/arch/arm/ARM.kconf | 134 + make/target/kconfig/arch/arm/ARM_Cortex.kconf | 44 + .../target/kconfig/arch/arm/ARM_CortexM.kconf | 128 + .../kconfig/arch/arm/ARM_CortexM3.kconf | 140 + .../kconfig/arch/arm/ARM_CortexM4.kconf | 67 + make/target/kconfig/arch/arm/build.kconf | 40 + .../target/kconfig/arch/arm/kernel-core.kconf | 84 + make/target/kconfig/arch/x86/Intel-core.kconf | 461 ++ make/target/kconfig/arch/x86/build.kconf | 58 + .../target/kconfig/arch/x86/kernel-core.kconf | 90 + make/target/kconfig/modules/apm.kconf | 92 + make/target/kconfig/modules/basic.kconf | 59 + make/target/kconfig/modules/build-base.kconf | 71 + make/target/kconfig/modules/debug.kconf | 67 + make/target/kconfig/modules/gdb.kconf | 45 + make/target/kconfig/modules/io.kconf | 53 + make/target/kconfig/modules/misc.kconf | 187 + make/target/kconfig/modules/monitor.kconf | 137 + make/target/kconfig/modules/nli.kconf | 85 + make/target/kconfig/modules/nli_RS232.kconf | 84 + .../kconfig/modules/security_basic.kconf | 62 + make/target/kconfig/nkernel.kconf | 63 + make/target/kconfig/product.kconf | 37 + make/target/kconfig/ukernel.kconf | 66 + make/target/kernel/arch/arc/defs.arch | 14 + make/target/kernel/arch/arm/defs.arch | 47 + make/target/kernel/check.kapp | 53 + make/target/kernel/check.klib | 35 + make/target/kernel/check.nkapp | 34 + make/target/kernel/check.nklib | 33 + make/target/kernel/check.ukapp | 36 + make/target/kernel/check.uklib | 33 + make/target/kernel/defs.kbuild | 324 + make/target/kernel/defs.nkbuild | 46 + make/target/kernel/defs.ukbuild | 102 + .../nli/rules.board.GENERIC_SERVERBOARD | 42 + .../kernel/nli/rules.board.GenericMTS_RS232 | 33 + .../kernel/nli/rules.board.Generic_RS232 | 49 + make/target/kernel/nli/rules.nodes | 99 + make/target/kernel/rules.kbuild | 123 + make/target/kernel/rules.kclean | 77 + make/target/kernel/rules.nkbuild | 48 + make/target/kernel/rules.ukbuild | 62 + make/target/kernel/rules.vpfgen | 58 + make/target/library/defs.library | 94 + make/target/library/defs.objects | 52 + make/target/library/rules.library | 57 + make/target/make.library | 41 + make/target/make.nkernel | 51 + make/target/make.nklib | 51 + make/target/make.ukernel | 51 + make/target/make.uklib | 51 + make/target/run/arch/defs.qemu.arc | 1 + make/target/run/arch/defs.qemu.arm | 47 + make/target/run/arch/defs.qemu.x86 | 56 + make/target/run/defs.emulation | 38 + make/target/run/defs.emulation.x86-linux2 | 34 + make/target/run/defs.qemu | 39 + make/target/run/defs.qemu.custom.vqemu | 1 + make/target/run/defs.qemu.default | 38 + make/target/run/defs.qemu.x86-linux2 | 50 + make/target/run/rules.emulation | 42 + make/target/run/rules.qemu | 53 + make/target/run/rules.qemu.x86-linux2 | 72 + make/target/stdlib/minimal/defs.kernel.stdlib | 33 + make/target/stdlib/minimal/defs.stdlib | 38 + make/target/toolchain/common/defs.objects | 130 + make/target/toolchain/common/rules.objects | 77 + make/target/toolchain/gcc/4.6/defs.flags | 35 + make/target/toolchain/gcc/4.6/rules.gcc | 31 + make/target/toolchain/gcc/4.8/defs.flags | 35 + make/target/toolchain/gcc/4.8/rules.gcc | 33 + make/target/toolchain/gcc/arch/arc/defs.exec | 42 + make/target/toolchain/gcc/arch/arc/defs.flags | 49 + make/target/toolchain/gcc/arch/arm/defs.exec | 48 + make/target/toolchain/gcc/arch/arm/defs.flags | 64 + make/target/toolchain/gcc/arch/x86/defs.exec | 40 + .../gcc/arch/x86/defs.exec.variant_ish | 32 + .../gcc/arch/x86/defs.exec.variant_otc | 37 + .../gcc/arch/x86/defs.exec.variant_xtools | 37 + make/target/toolchain/gcc/arch/x86/defs.flags | 50 + .../gcc/arch/x86/defs.flags.atom_n28xx | 43 + .../gcc/arch/x86/defs.flags.minuteia | 36 + .../gcc/arch/x86/defs.flags.pentium4 | 43 + make/target/toolchain/gcc/arch/x86/rules.idt | 45 + make/target/toolchain/gcc/defs.exec | 64 + make/target/toolchain/gcc/defs.ext | 50 + make/target/toolchain/gcc/defs.flags | 84 + make/target/toolchain/gcc/defs.flags.library | 40 + make/target/toolchain/gcc/defs.gcc | 80 + make/target/toolchain/gcc/defs.gcc.x86-linux2 | 46 + .../gcc/defs.gcc.x86-linux2.variant_ish | 32 + .../gcc/defs.gcc.x86-linux2.variant_otc | 38 + .../gcc/defs.gcc.x86-linux2.variant_xtools | 39 + make/target/toolchain/gcc/defs.kernel-bin | 42 + make/target/toolchain/gcc/defs.offsets | 34 + make/target/toolchain/gcc/rules.gcc | 34 + make/target/toolchain/gcc/rules.kernel-bin | 78 + make/target/wb-helper/README | 21 + make/vxmicro/make/env/defs.check-host | 43 + make/vxmicro/make/env/defs.host.win32 | 47 + make/vxmicro/make/env/defs.host.x86-win32 | 137 + make/vxmicro/make/host/exe_extra.defs | 50 + make/vxmicro/make/host/lib_extra.defs | 40 + make/vxmicro/make/host/obj_extra.defs | 43 + make/vxmicro/make/host/toolchain_extra.defs | 40 + .../vxmicro/make/iap/host/defs.host.x86-win32 | 10 + make/vxmicro/make/target/arch/x86/rules.idt | 96 + .../make/target/run/defs.emulation.x86-win32 | 71 + make/vxmicro/make/target/run/defs.extra | 35 + .../make/target/run/defs.qemu.custom.vqemu | 38 + .../vxmicro/make/target/run/defs.qemu.default | 40 + .../make/target/run/defs.qemu.x86-win32 | 72 + make/vxmicro/make/target/run/rules.extra | 35 + .../make/target/run/rules.qemu.x86-win32 | 53 + make/vxmicro/make/target/toolchain/Xcc/README | 4 + .../make/target/toolchain/Xcc/defs.Xcc | 37 + .../make/target/toolchain/Xcc/defs.kernel-bin | 20 + .../target/toolchain/Xcc/rules.kernel-bin | 56 + .../target/toolchain/diab/arch/arm/defs.exec | 14 + .../target/toolchain/diab/arch/arm/defs.flags | 43 + .../toolchain/diab/arch/arm/defs.target | 16 + .../target/toolchain/diab/arch/x86/defs.exec | 14 + .../target/toolchain/diab/arch/x86/defs.flags | 40 + .../toolchain/diab/arch/x86/defs.target | 19 + .../target/toolchain/diab/arch/x86/rules.idt | 50 + .../make/target/toolchain/diab/defs.diab | 59 + .../make/target/toolchain/diab/defs.diab.host | 25 + .../toolchain/diab/defs.diab.x86-linux2 | 15 + .../target/toolchain/diab/defs.diab.x86-win32 | 15 + .../make/target/toolchain/diab/defs.exec | 38 + .../make/target/toolchain/diab/defs.ext | 25 + .../make/target/toolchain/diab/defs.flags | 86 + .../target/toolchain/diab/defs.kernel-bin | 21 + .../make/target/toolchain/diab/defs.offsets | 13 + .../make/target/toolchain/diab/defs.target | 9 + .../make/target/toolchain/diab/rules.diab | 12 + .../target/toolchain/diab/rules.kernel-bin | 66 + .../target/toolchain/gcc/defs.gcc.x86-win32 | 34 + .../make/target/toolchain/icc/13.0/defs.flags | 81 + .../make/target/toolchain/icc/13.0/rules.icc | 9 + .../target/toolchain/icc/arch/x86/defs.exec | 14 + .../target/toolchain/icc/arch/x86/defs.flags | 26 + .../icc/arch/x86/defs.flags.atom_n28xx | 21 + .../icc/arch/x86/defs.flags.minuteia | 18 + .../icc/arch/x86/defs.flags.pentium4 | 21 + .../target/toolchain/icc/arch/x86/rules.idt | 37 + .../make/target/toolchain/icc/defs.exec | 50 + .../make/target/toolchain/icc/defs.ext | 28 + .../make/target/toolchain/icc/defs.flags | 68 + .../make/target/toolchain/icc/defs.icc | 46 + .../target/toolchain/icc/defs.icc.x86-linux2 | 30 + .../target/toolchain/icc/defs.icc.x86-win32 | 32 + .../make/target/toolchain/icc/defs.offsets | 13 + .../make/target/toolchain/icc/rules.icc | 12 + .../target/toolchain/icc/rules.kernel-bin | 9 + .../vxmicro/target/include/linker-tool-diab.h | 71 + misc/defs.objs | 47 + misc/dlist.c | 114 + misc/printk.c | 250 + samples/include/irq_test_common.h | 175 + samples/include/tc_util.h | 92 + samples/include/util_test_common.h | 47 + samples/libc/Makefile | 37 + samples/libc/README | 1 + samples/microkernel/apps/hello_world/Makefile | 44 + .../microkernel/apps/hello_world/README.txt | 38 + samples/microkernel/apps/hello_world/prj.vpf | 16 + .../microkernel/apps/hello_world/prj_arm.conf | 1 + .../microkernel/apps/hello_world/prj_x86.conf | 2 + .../microkernel/apps/hello_world/src/hello.c | 163 + .../microkernel/apps/philosophers/Makefile | 40 + .../microkernel/apps/philosophers/README.txt | 52 + samples/microkernel/apps/philosophers/prj.vpf | 29 + .../apps/philosophers/prj_arm.conf | 4 + .../apps/philosophers/prj_x86.conf | 3 + .../microkernel/apps/philosophers/src/phil.h | 51 + .../apps/philosophers/src/phil_fiber.c | 159 + .../apps/philosophers/src/phil_task.c | 121 + .../microkernel/benchmark/app_kernel/Makefile | 53 + .../benchmark/app_kernel/README.txt | 137 + .../microkernel/benchmark/app_kernel/prj.vpf | 50 + .../app_kernel/prj_console_float_generic.conf | 15 + .../app_kernel/prj_console_float_pc8253.conf | 17 + .../prj_console_nofloat_generic.conf | 9 + .../prj_console_nofloat_pc8253.conf | 11 + .../benchmark/app_kernel/src/config.h | 72 + .../benchmark/app_kernel/src/event_b.c | 212 + .../benchmark/app_kernel/src/fifo_b.c | 122 + .../benchmark/app_kernel/src/fifo_r.c | 63 + .../benchmark/app_kernel/src/mailbox_b.c | 179 + .../benchmark/app_kernel/src/mailbox_r.c | 124 + .../benchmark/app_kernel/src/master.c | 188 + .../benchmark/app_kernel/src/master.h | 179 + .../benchmark/app_kernel/src/memcfg.h | 39 + .../benchmark/app_kernel/src/memmap_b.c | 70 + .../benchmark/app_kernel/src/mempool_b.c | 67 + .../benchmark/app_kernel/src/mutex_b.c | 65 + .../benchmark/app_kernel/src/nop_b.c | 63 + .../benchmark/app_kernel/src/pipe_b.c | 289 + .../benchmark/app_kernel/src/pipe_r.c | 186 + .../benchmark/app_kernel/src/receiver.c | 82 + .../benchmark/app_kernel/src/receiver.h | 51 + .../benchmark/app_kernel/src/sema_b.c | 159 + .../benchmark/app_kernel/src/sema_r.c | 88 + .../microkernel/benchmark/boot_time/Makefile | 40 + .../benchmark/boot_time/README.txt | 60 + .../benchmark/boot_time/check_prj_conf.mk | 12 + .../benchmark/boot_time/generic_pc/prj.conf | 7 + .../boot_time/generic_pc/prj_expert_test.conf | 6 + .../generic_pc/prj_pentium4_best.conf | 41 + .../generic_pc/prj_pentium4_default.conf | 55 + .../generic_pc/prj_pentium4_worst.conf | 64 + .../benchmark/boot_time/get_prj_conf.mk | 17 + .../microkernel/benchmark/boot_time/prj.vpf | 10 + .../benchmark/boot_time/quark/prj.conf | 4 + .../benchmark/boot_time/src/boot_time.c | 143 + .../microkernel/benchmark/footprint/Makefile | 58 + .../benchmark/footprint/README.txt | 94 + .../benchmark/footprint/micro_max.vpf | 42 + .../benchmark/footprint/micro_min.vpf | 6 + .../benchmark/footprint/micro_reg.vpf | 26 + .../benchmark/footprint/prj_max_arm.conf | 15 + .../benchmark/footprint/prj_max_x86.conf | 20 + .../benchmark/footprint/prj_min_arm.conf | 9 + .../benchmark/footprint/prj_min_x86.conf | 11 + .../benchmark/footprint/prj_reg_arm.conf | 9 + .../benchmark/footprint/prj_reg_x86.conf | 9 + .../footprint/src/microkernel_footprint.c | 230 + .../benchmark/latency_measure/Makefile | 47 + .../benchmark/latency_measure/README.txt | 77 + .../benchmark/latency_measure/prj.vpf | 81 + .../latency_measure/prj_generic.conf | 8 + .../benchmark/latency_measure/prj_pc8253.conf | 10 + .../benchmark/latency_measure/src/main.c | 154 + .../latency_measure/src/micro_int_to_task.c | 116 + .../src/micro_int_to_task_evt.c | 113 + .../src/micro_sema_lock_release.c | 151 + .../src/micro_task_switch_yield.c | 143 + .../latency_measure/src/nano_ctx_switch.c | 150 + .../benchmark/latency_measure/src/nano_int.c | 106 + .../src/nano_int_lock_unlock.c | 112 + .../latency_measure/src/nano_int_to_fiber.c | 119 + .../src/nano_int_to_fiber_sem.c | 144 + .../benchmark/latency_measure/src/timemacro.h | 66 + .../benchmark/latency_measure/src/timestamp.h | 178 + .../benchmark/latency_measure/src/utils.c | 119 + .../benchmark/latency_measure/src/utils.h | 146 + .../microkernel/benchmark/sys_kernel/Makefile | 48 + .../benchmark/sys_kernel/README.txt | 122 + .../microkernel/benchmark/sys_kernel/prj.vpf | 11 + .../sys_kernel/prj_console_generic.conf | 10 + .../sys_kernel/prj_console_pc8253.conf | 12 + .../microkernel/klibs/klibs_events/Makefile | 39 + .../microkernel/klibs/klibs_events/README.txt | 41 + .../microkernel/klibs/klibs_events/prj.vpf | 20 + samples/microkernel/klibs/klibs_sema/Makefile | 39 + .../microkernel/klibs/klibs_sema/README.txt | 38 + samples/microkernel/klibs/klibs_sema/prj.vpf | 30 + .../microkernel/test/test_critical/Makefile | 39 + .../microkernel/test/test_critical/README.txt | 41 + .../microkernel/test/test_critical/prj.vpf | 16 + .../test/test_critical/prj_arm.conf | 3 + .../test/test_critical/prj_x86.conf | 3 + .../test/test_critical/src/critical.c | 190 + samples/microkernel/test/test_events/Makefile | 39 + .../microkernel/test/test_events/README.txt | 35 + samples/microkernel/test/test_events/prj.vpf | 20 + .../microkernel/test/test_events/prj_arm.conf | 3 + .../microkernel/test/test_events/prj_x86.conf | 3 + .../microkernel/test/test_events/src/events.c | 622 ++ .../test/test_events/src/test_fiber.c | 101 + samples/microkernel/test/test_fifo/Makefile | 39 + samples/microkernel/test/test_fifo/README.txt | 76 + samples/microkernel/test/test_fifo/prj.vpf | 20 + .../microkernel/test/test_fifo/prj_arm.conf | 3 + .../microkernel/test/test_fifo/prj_x86.conf | 3 + samples/microkernel/test/test_fifo/src/fifo.c | 647 ++ .../microkernel/test/test_fp_sharing/Makefile | 46 + .../test/test_fp_sharing/README.txt | 53 + .../microkernel/test/test_fp_sharing/prj.vpf | 13 + .../test/test_fp_sharing/prj_x86.conf | 11 + .../test/test_fp_sharing/src/float_context.h | 188 + .../test/test_fp_sharing/src/float_regs_x86.c | 326 + .../test/test_fp_sharing/src/main.c | 490 ++ .../microkernel/test/test_fp_sharing/src/pi.c | 181 + samples/microkernel/test/test_libs/Makefile | 39 + samples/microkernel/test/test_libs/README.txt | 39 + samples/microkernel/test/test_libs/prj.vpf | 16 + .../microkernel/test/test_libs/prj_arm.conf | 1 + .../microkernel/test/test_libs/prj_x86.conf | 3 + .../test/test_libs/src/libraries.c | 274 + samples/microkernel/test/test_libs/src/main.c | 127 + samples/microkernel/test/test_mail/Makefile | 39 + samples/microkernel/test/test_mail/README.txt | 51 + samples/microkernel/test/test_mail/prj.vpf | 29 + .../microkernel/test/test_mail/prj_arm.conf | 3 + .../microkernel/test/test_mail/prj_x86.conf | 3 + samples/microkernel/test/test_mail/src/mail.c | 685 +++ samples/microkernel/test/test_mail/src/main.c | 153 + samples/microkernel/test/test_map/Makefile | 39 + samples/microkernel/test/test_map/README.txt | 70 + samples/microkernel/test/test_map/prj.vpf | 20 + .../microkernel/test/test_map/prj_arm.conf | 3 + .../microkernel/test/test_map/prj_x86.conf | 3 + samples/microkernel/test/test_map/src/map.c | 411 ++ samples/microkernel/test/test_mutex/Makefile | 39 + .../microkernel/test/test_mutex/README.txt | 29 + samples/microkernel/test/test_mutex/prj.vpf | 23 + .../microkernel/test/test_mutex/prj_arm.conf | 3 + .../microkernel/test/test_mutex/prj_x86.conf | 3 + .../microkernel/test/test_mutex/src/mutex.c | 370 ++ samples/microkernel/test/test_pipe/Makefile | 39 + samples/microkernel/test/test_pipe/README.txt | 32 + samples/microkernel/test/test_pipe/prj.vpf | 24 + .../microkernel/test/test_pipe/prj_arm.conf | 3 + .../microkernel/test/test_pipe/prj_x86.conf | 3 + samples/microkernel/test/test_pipe/src/main.c | 147 + samples/microkernel/test/test_pipe/src/pipe.c | 1139 ++++ samples/microkernel/test/test_pool/Makefile | 39 + samples/microkernel/test/test_pool/README.txt | 32 + samples/microkernel/test/test_pool/prj.vpf | 25 + .../microkernel/test/test_pool/prj_arm.conf | 3 + .../microkernel/test/test_pool/prj_x86.conf | 3 + samples/microkernel/test/test_pool/src/pool.c | 643 ++ .../test/test_secure_string_api/Makefile | 39 + .../test/test_secure_string_api/README.txt | 38 + .../test/test_secure_string_api/prj.vpf | 17 + .../test/test_secure_string_api/prj_arm.conf | 7 + .../test/test_secure_string_api/prj_x86.conf | 3 + .../test/test_secure_string_api/src/secure.c | 162 + samples/microkernel/test/test_sema/Makefile | 39 + samples/microkernel/test/test_sema/README.txt | 32 + samples/microkernel/test/test_sema/prj.vpf | 30 + .../microkernel/test/test_sema/prj_arm.conf | 3 + .../microkernel/test/test_sema/prj_x86.conf | 3 + samples/microkernel/test/test_sema/src/README | 24 + samples/microkernel/test/test_sema/src/main.c | 277 + samples/microkernel/test/test_sema/src/sema.c | 725 +++ .../test/test_sema/src/test_fiber.c | 108 + .../microkernel/test/test_sprintf/Makefile | 39 + .../microkernel/test/test_sprintf/README.txt | 35 + samples/microkernel/test/test_sprintf/prj.vpf | 10 + .../test/test_sprintf/prj_arm.conf | 4 + .../test/test_sprintf/prj_x86.conf | 7 + .../test/test_sprintf/src/test_sprintf.c | 863 +++ .../microkernel/test/test_stackprot/Makefile | 43 + .../test/test_stackprot/README.txt | 42 + .../microkernel/test/test_stackprot/prj.vpf | 15 + .../test/test_stackprot/prj_arm.conf | 6 + .../test/test_stackprot/prj_x86.conf | 3 + .../test/test_stackprot/src/stackprot.c | 194 + .../microkernel/test/test_static_idt/Makefile | 40 + .../test/test_static_idt/README.txt | 35 + .../microkernel/test/test_static_idt/prj.vpf | 15 + .../test/test_static_idt/prj_x86.conf | 3 + .../test/test_static_idt/src/static_idt.c | 316 + .../test/test_static_idt/src/test_stubs.s | 84 + samples/microkernel/test/test_task/Makefile | 39 + samples/microkernel/test/test_task/README.txt | 35 + samples/microkernel/test/test_task/prj.vpf | 16 + .../microkernel/test/test_task/prj_arm.conf | 3 + .../microkernel/test/test_task/prj_x86.conf | 3 + samples/microkernel/test/test_task/src/task.c | 581 ++ .../microkernel/test/test_task_irq/Makefile | 44 + .../microkernel/test/test_task_irq/README.txt | 48 + .../microkernel/test/test_task_irq/prj.vpf | 19 + .../test/test_task_irq/prj_arm.conf | 8 + .../test/test_task_irq/prj_x86.conf | 5 + .../microkernel/test/test_task_irq/src/main.c | 166 + .../test/test_task_irq/src/raise_int.c | 1425 +++++ .../test/test_task_irq/src/test_device.c | 208 + .../microkernel/test/test_tickless/Makefile | 46 + .../microkernel/test/test_tickless/README.txt | 45 + .../microkernel/test/test_tickless/prj.vpf | 10 + .../test/test_tickless/prj_arm.conf | 3 + .../test/test_tickless/prj_x86.conf | 6 + .../test/test_tickless/src/test_tickless.c | 208 + .../test/test_tickless/src/timestamps.c | 286 + samples/microkernel/test/test_timer/Makefile | 39 + .../microkernel/test/test_timer/README.txt | 35 + samples/microkernel/test/test_timer/prj.vpf | 14 + .../microkernel/test/test_timer/prj_arm.conf | 4 + .../microkernel/test/test_timer/prj_x86.conf | 4 + .../microkernel/test/test_timer/src/timer.c | 333 ++ samples/microkernel/test/test_xip/Makefile | 37 + samples/microkernel/test/test_xip/README.txt | 27 + samples/microkernel/test/test_xip/prj.conf | 3 + samples/microkernel/test/test_xip/prj.vpf | 10 + samples/microkernel/test/test_xip/src/test.h | 49 + .../microkernel/test/test_xip/src/test_xip.c | 93 + .../test/test_xip/src/test_xip_helper.c | 49 + samples/nanokernel/apps/hello_world/Makefile | 41 + .../nanokernel/apps/hello_world/README.txt | 38 + samples/nanokernel/apps/hello_world/prj.conf | 2 + samples/nanokernel/apps/philosophers/Makefile | 43 + .../nanokernel/apps/philosophers/README.txt | 51 + .../nanokernel/apps/philosophers/prj_arc.conf | 4 + .../nanokernel/apps/philosophers/prj_arm.conf | 4 + .../nanokernel/apps/philosophers/prj_x86.conf | 3 + .../nanokernel/benchmark/boot_time/Makefile | 42 + .../nanokernel/benchmark/boot_time/README.txt | 58 + .../benchmark/boot_time/generic_pc/prj.conf | 7 + .../boot_time/generic_pc/prj_expert_test.conf | 6 + .../generic_pc/prj_pentium4_best.conf | 40 + .../generic_pc/prj_pentium4_default.conf | 55 + .../generic_pc/prj_pentium4_worst.conf | 53 + .../benchmark/boot_time/quark/prj.conf | 4 + .../nanokernel/benchmark/footprint/Makefile | 58 + .../nanokernel/benchmark/footprint/README.txt | 89 + .../benchmark/footprint/prj_max_arm.conf | 5 + .../benchmark/footprint/prj_max_x86.conf | 10 + .../benchmark/footprint/prj_min_arc.conf | 6 + .../benchmark/footprint/prj_min_arm.conf | 6 + .../benchmark/footprint/prj_min_x86.conf | 6 + .../benchmark/footprint/prj_reg_arm.conf | 6 + .../benchmark/footprint/prj_reg_x86.conf | 6 + .../footprint/src/nanokernel_footprint.c | 214 + .../benchmark/latency_measure/Makefile | 43 + .../benchmark/latency_measure/README.txt | 53 + .../benchmark/latency_measure/prj.conf | 5 + .../nanokernel/benchmark/sys_kernel/Makefile | 43 + .../benchmark/sys_kernel/README.txt | 122 + .../benchmark/sys_kernel/prj_console.conf | 8 + .../benchmark/sys_kernel/src/lifo.c | 273 + .../benchmark/sys_kernel/src/mwfifo.c | 271 + .../benchmark/sys_kernel/src/sema.c | 214 + .../benchmark/sys_kernel/src/stack.c | 251 + .../benchmark/sys_kernel/src/syskernel.c | 244 + .../benchmark/sys_kernel/src/syskernel.h | 84 + samples/nanokernel/klibs/klibs_lifo/Makefile | 39 + .../nanokernel/klibs/klibs_lifo/README.txt | 38 + samples/nanokernel/klibs/klibs_sema/Makefile | 39 + .../nanokernel/klibs/klibs_sema/README.txt | 39 + .../test_arm_m3_irq_vector_table/Makefile | 36 + .../test_arm_m3_irq_vector_table/README.txt | 28 + .../test_arm_m3_irq_vector_table/prj.conf | 5 + .../test_arm_m3_irq_vector_table/src/main.c | 136 + samples/nanokernel/test/test_context/Makefile | 47 + .../nanokernel/test/test_context/README.txt | 39 + .../nanokernel/test/test_context/prj_arm.conf | 4 + .../nanokernel/test/test_context/prj_x86.conf | 3 + .../nanokernel/test/test_context/src/README | 57 + .../test/test_context/src/context.c | 826 +++ samples/nanokernel/test/test_fifo/Makefile | 40 + samples/nanokernel/test/test_fifo/README.txt | 81 + .../nanokernel/test/test_fifo/prj_arm.conf | 3 + .../nanokernel/test/test_fifo/prj_x86.conf | 3 + samples/nanokernel/test/test_fifo/src/fifo.c | 756 +++ .../nanokernel/test/test_fp_sharing/Makefile | 44 + .../test/test_fp_sharing/README.txt | 39 + .../test/test_fp_sharing/prj_x86.conf | 9 + samples/nanokernel/test/test_lifo/Makefile | 40 + samples/nanokernel/test/test_lifo/README.txt | 32 + .../nanokernel/test/test_lifo/prj_arm.conf | 3 + .../nanokernel/test/test_lifo/prj_x86.conf | 3 + samples/nanokernel/test/test_lifo/src/README | 35 + samples/nanokernel/test/test_lifo/src/lifo.c | 529 ++ samples/nanokernel/test/test_sema/Makefile | 40 + samples/nanokernel/test/test_sema/README.txt | 33 + .../nanokernel/test/test_sema/prj_arm.conf | 3 + .../nanokernel/test/test_sema/prj_x86.conf | 3 + samples/nanokernel/test/test_sema/src/README | 33 + samples/nanokernel/test/test_sema/src/sema.c | 485 ++ samples/nanokernel/test/test_stack/Makefile | 40 + samples/nanokernel/test/test_stack/README.txt | 80 + .../nanokernel/test/test_stack/prj_arm.conf | 3 + .../nanokernel/test/test_stack/prj_x86.conf | 3 + .../nanokernel/test/test_stack/src/stack.c | 628 ++ .../nanokernel/test/test_stackprot/Makefile | 45 + .../nanokernel/test/test_stackprot/README.txt | 40 + .../test/test_stackprot/prj_arm.conf | 6 + .../test/test_stackprot/prj_x86.conf | 3 + .../nanokernel/test/test_static_idt/Makefile | 43 + .../test/test_static_idt/README.txt | 36 + .../test/test_static_idt/prj_x86.conf | 3 + samples/nanokernel/test/test_timer/Makefile | 40 + samples/nanokernel/test/test_timer/README.txt | 40 + .../nanokernel/test/test_timer/prj_arm.conf | 1 + .../nanokernel/test/test_timer/prj_x86.conf | 3 + samples/nanokernel/test/test_timer/src/README | 42 + .../nanokernel/test/test_timer/src/timer.c | 617 ++ samples/nanokernel/test/test_xip/Makefile | 42 + samples/nanokernel/test/test_xip/README.txt | 27 + samples/nanokernel/test/test_xip/prj_arm.conf | 3 + samples/nanokernel/test/test_xip/prj_x86.conf | 3 + scripts/Kbuild.include | 308 + scripts/Makefile | 24 + scripts/Makefile.asm-generic | 23 + scripts/Makefile.build | 426 ++ scripts/Makefile.clean | 94 + scripts/Makefile.dtbinst | 51 + scripts/Makefile.extrawarn | 68 + scripts/Makefile.fwinst | 70 + scripts/Makefile.headersinst | 139 + scripts/Makefile.help | 3 + scripts/Makefile.host | 128 + scripts/Makefile.lib | 379 ++ scripts/Makefile.modbuiltin | 60 + scripts/Makefile.modinst | 41 + scripts/Makefile.modpost | 152 + scripts/Makefile.modsign | 32 + scripts/basic/Makefile | 16 + scripts/basic/bin2c.c | 35 + scripts/basic/fixdep.c | 462 ++ scripts/check_known_checkpatch_issues.sh | 169 + scripts/checkpatch.pl | 5250 +++++++++++++++++ scripts/checkstack.pl | 176 + scripts/config | 225 + scripts/cross_compiler/arm.config | 461 ++ scripts/cross_compiler/x86.config | 473 ++ scripts/depmod.sh | 64 + scripts/diffconfig | 132 + scripts/do_checkpatch.sh | 19 + scripts/docproc.c | 580 ++ scripts/gcc-version.sh | 32 + scripts/genksyms/Makefile | 14 + scripts/genksyms/genksyms.c | 875 +++ scripts/genksyms/genksyms.h | 94 + scripts/genksyms/keywords.gperf | 60 + scripts/genksyms/keywords.hash.c_shipped | 229 + scripts/genksyms/lex.l | 482 ++ scripts/genksyms/lex.lex.c_shipped | 2292 +++++++ scripts/genksyms/parse.tab.c_shipped | 2407 ++++++++ scripts/genksyms/parse.tab.h_shipped | 96 + scripts/genksyms/parse.y | 504 ++ scripts/headerdep.pl | 192 + scripts/kconfig/Makefile | 312 + scripts/kconfig/POTFILES.in | 12 + scripts/kconfig/check.sh | 13 + scripts/kconfig/conf.c | 718 +++ scripts/kconfig/confdata.c | 1242 ++++ scripts/kconfig/expr.c | 1168 ++++ scripts/kconfig/expr.h | 241 + scripts/kconfig/gconf.c | 1542 +++++ scripts/kconfig/gconf.glade | 661 +++ scripts/kconfig/images.c | 326 + scripts/kconfig/kxgettext.c | 235 + scripts/kconfig/list.h | 131 + scripts/kconfig/lkc.h | 200 + scripts/kconfig/lkc_proto.h | 57 + scripts/kconfig/lxdialog/BIG.FAT.WARNING | 4 + scripts/kconfig/lxdialog/check-lxdialog.sh | 91 + scripts/kconfig/lxdialog/checklist.c | 332 ++ scripts/kconfig/lxdialog/dialog.h | 257 + scripts/kconfig/lxdialog/inputbox.c | 301 + scripts/kconfig/lxdialog/menubox.c | 437 ++ scripts/kconfig/lxdialog/textbox.c | 408 ++ scripts/kconfig/lxdialog/util.c | 713 +++ scripts/kconfig/lxdialog/yesno.c | 114 + scripts/kconfig/mconf.c | 1036 ++++ scripts/kconfig/menu.c | 697 +++ scripts/kconfig/merge_config.sh | 150 + scripts/kconfig/nconf.c | 1556 +++++ scripts/kconfig/nconf.gui.c | 656 ++ scripts/kconfig/nconf.h | 96 + scripts/kconfig/qconf.cc | 1795 ++++++ scripts/kconfig/qconf.h | 338 ++ scripts/kconfig/streamline_config.pl | 647 ++ scripts/kconfig/symbol.c | 1373 +++++ scripts/kconfig/util.c | 157 + scripts/kconfig/zconf.gperf | 48 + scripts/kconfig/zconf.hash.c_shipped | 289 + scripts/kconfig/zconf.l | 363 ++ scripts/kconfig/zconf.lex.c_shipped | 2420 ++++++++ scripts/kconfig/zconf.tab.c_shipped | 2538 ++++++++ scripts/kconfig/zconf.y | 733 +++ scripts/link-vmlinux.sh | 240 + scripts/maintainer-checkpatch.bash | 128 + scripts/mkmakefile | 52 + scripts/mksysmap | 44 + scripts/package/Makefile | 145 + scripts/package/builddeb | 375 ++ scripts/package/buildtar | 137 + scripts/package/mkspec | 163 + scripts/sanity_chk/QA/README.txt | 11 + scripts/sanity_chk/QA/chk_sanity.sh | 58 + .../sanity_chk/QA/patterns_sanity_x86_gcc.txt | 5 + scripts/sanity_chk/QA/reduce_sanity.sh | 25 + scripts/sanity_chk/common-klibs_chk | 275 + scripts/sanity_chk/common.defs | 542 ++ scripts/sanity_chk/footprint_chk | 262 + scripts/sanity_chk/out-of-tree_chk | 306 + scripts/sanity_chk/regression_chk | 361 ++ scripts/sanity_chk/sanity_chk | 246 + scripts/setlocalversion | 174 + scripts/spelling.txt | 1042 ++++ scripts/sysgen.py | 1086 ++++ scripts/tags.sh | 339 ++ scripts/timestamp | 99 + scripts/unifdef.c | 1225 ++++ shared/include/nanokernel/x86/idtEnt.h | 143 + shared/include/nanokernel/x86/segselect.h | 56 + vxmicro-env.bash | 34 + 1063 files changed, 163901 insertions(+) create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 .mailmap create mode 100644 arch/arc/bsp/fatal_error.c create mode 100644 arch/arc/bsp/prep_c.c create mode 100644 arch/arc/bsp/reset.s create mode 100644 arch/arc/bsp/vector_table.c create mode 100644 arch/arc/bsp/vector_table.h create mode 100644 arch/arc/core/atomic.s create mode 100644 arch/arc/core/context.c create mode 100644 arch/arc/core/context_wrapper.s create mode 100644 arch/arc/core/cpu_idle.s create mode 100644 arch/arc/core/fast_irq.s create mode 100644 arch/arc/core/fatal.c create mode 100644 arch/arc/core/fault.c create mode 100644 arch/arc/core/fault_s.s create mode 100644 arch/arc/core/ffs.s create mode 100644 arch/arc/core/irq_lock.s create mode 100644 arch/arc/core/irq_manage.c create mode 100644 arch/arc/core/isr_wrapper.s create mode 100644 arch/arc/core/offsets/offsets.c create mode 100644 arch/arc/core/regular_irq.s create mode 100644 arch/arc/core/swap.s create mode 100644 arch/arc/core/swap_macros.h create mode 100644 arch/arc/defs.objs create mode 100644 arch/arc/include/nanok.h create mode 100644 arch/arc/include/v2/cache.h create mode 100644 arch/arc/include/v2/irq.h create mode 100644 arch/arc/interrupt_controller/arcv2_irq_unit.c create mode 100644 arch/arc/serial/nsim_uart.c create mode 100644 arch/arc/timer/arcv2_timer0.c create mode 100644 arch/arm/bsp/CortexM/nmi.c create mode 100644 arch/arm/bsp/CortexM/prep_c.c create mode 100644 arch/arm/bsp/CortexM/reset.s create mode 100644 arch/arm/bsp/CortexM/scb.c create mode 100644 arch/arm/bsp/CortexM/scs.c create mode 100644 arch/arm/bsp/CortexM/vector_table.h create mode 100644 arch/arm/bsp/CortexM/vector_table.s create mode 100644 arch/arm/bsp/rand32.c create mode 100644 arch/arm/bsp/sysFatalErrorHandler.c create mode 100644 arch/arm/core/atomic.s create mode 100644 arch/arm/core/basepri.s create mode 100644 arch/arm/core/cpu_idle.s create mode 100644 arch/arm/core/exc_exit.s create mode 100644 arch/arm/core/fault.c create mode 100644 arch/arm/core/fault_s.s create mode 100644 arch/arm/core/ffs.s create mode 100644 arch/arm/core/gdb_stub.s create mode 100644 arch/arm/core/gdb_stub_irq_vector_table.c create mode 100644 arch/arm/core/irq_init.c create mode 100644 arch/arm/core/irq_manage.c create mode 100644 arch/arm/core/isr_wrapper.s create mode 100644 arch/arm/core/nano_fiber_abort.c create mode 100644 arch/arm/core/nanocontext.c create mode 100644 arch/arm/core/nanofatal.c create mode 100644 arch/arm/core/offsets/offsets.c create mode 100644 arch/arm/core/swap.s create mode 100644 arch/arm/core/task_abort.c create mode 100644 arch/arm/defs.objs create mode 100644 arch/arm/fsl_frdm_k64f/board.h create mode 100644 arch/arm/fsl_frdm_k64f/defs.objs create mode 100644 arch/arm/fsl_frdm_k64f/irq_vector_table.c create mode 100644 arch/arm/fsl_frdm_k64f/linker.cmd create mode 100644 arch/arm/fsl_frdm_k64f/nmi_on_reset.s create mode 100644 arch/arm/fsl_frdm_k64f/sw_isr_table.c create mode 100644 arch/arm/fsl_frdm_k64f/system.c create mode 100644 arch/arm/fsl_frdm_k64f/wdog.s create mode 100644 arch/arm/include/CortexM/exc.h create mode 100644 arch/arm/include/CortexM/stack.h create mode 100644 arch/arm/include/nanok.h create mode 100644 arch/arm/include/start_task_arch.h create mode 100644 arch/arm/ti_lm3s6965/board.h create mode 100644 arch/arm/ti_lm3s6965/defs.objs create mode 100644 arch/arm/ti_lm3s6965/irq_vector_table.c create mode 100644 arch/arm/ti_lm3s6965/linker.cmd create mode 100644 arch/arm/ti_lm3s6965/nmi_on_reset.s create mode 100644 arch/arm/ti_lm3s6965/scp.c create mode 100644 arch/arm/ti_lm3s6965/scp.h create mode 100644 arch/arm/ti_lm3s6965/sw_isr_table.c create mode 100644 arch/arm/ti_lm3s6965/system.c create mode 100644 arch/arm/timer/systick.c create mode 100644 arch/arm/timer/systick_gdb.s create mode 100644 arch/x86/bsp/cache.c create mode 100644 arch/x86/bsp/cache_s.s create mode 100644 arch/x86/bsp/crt0.s create mode 100644 arch/x86/bsp/driver_static_irq_stubs.s create mode 100644 arch/x86/bsp/i8259Boi.s create mode 100644 arch/x86/bsp/rand32.c create mode 100644 arch/x86/bsp/sysFatalErrorHandler.c create mode 100644 arch/x86/bsp/systemApic.c create mode 100644 arch/x86/bsp/systemPic.c create mode 100644 arch/x86/core/cpuhalt.s create mode 100644 arch/x86/core/excconnect.c create mode 100644 arch/x86/core/excstub.s create mode 100644 arch/x86/core/ffs.s create mode 100644 arch/x86/core/gdt.c create mode 100644 arch/x86/core/intboiexit.s create mode 100644 arch/x86/core/intconnect.c create mode 100644 arch/x86/core/inthndlset.c create mode 100644 arch/x86/core/intstub.s create mode 100644 arch/x86/core/msr.s create mode 100644 arch/x86/core/nanoatomic.s create mode 100644 arch/x86/core/nanoatomic_nolock.c create mode 100644 arch/x86/core/nanocontext.c create mode 100644 arch/x86/core/nanofatal.c create mode 100644 arch/x86/core/nanofloat.c create mode 100644 arch/x86/core/offsets/offsets.c create mode 100644 arch/x86/core/swap.s create mode 100644 arch/x86/core/unaligned.s create mode 100644 arch/x86/defs.objs create mode 100644 arch/x86/generic_pc/board.h create mode 100644 arch/x86/generic_pc/defs.objs create mode 100644 arch/x86/generic_pc/linker.cmd create mode 100644 arch/x86/generic_pc/system.c create mode 100644 arch/x86/include/advidle.h create mode 100644 arch/x86/include/asmPrv.h create mode 100644 arch/x86/include/gdt.h create mode 100644 arch/x86/include/idtEnt.h create mode 100644 arch/x86/include/nanok.h create mode 100644 arch/x86/include/start_task_arch.h create mode 100644 arch/x86/include/swapstk.h create mode 100644 arch/x86/interrupt_controller/ioApicIntr.c create mode 100644 arch/x86/interrupt_controller/loApicIntr.c create mode 100644 arch/x86/quark/board.h create mode 100644 arch/x86/quark/defs.objs create mode 100644 arch/x86/quark/linker.cmd create mode 100644 arch/x86/quark/system.c create mode 100644 arch/x86/task/strtask.c create mode 100644 arch/x86/timer/hpet.c create mode 100644 arch/x86/timer/loApicTimer.c create mode 100644 config/fsl_frdm_k64f/bsp.kconf create mode 100644 config/fsl_frdm_k64f/defs.bsp create mode 100644 config/fsl_frdm_k64f/nkernel/bsp-nkernel.kconf create mode 100644 config/fsl_frdm_k64f/ukernel/bsp-ukernel.kconf create mode 100644 config/fsl_frdm_k64f/ukernel/config1p.vpf create mode 100644 config/generic_pc/bsp-atom_n28xx.kconf create mode 100644 config/generic_pc/bsp-minuteia.kconf create mode 100644 config/generic_pc/bsp-pentium4.kconf create mode 100644 config/generic_pc/defs.bsp create mode 100644 config/generic_pc/nkernel/bsp-nkernelatom_n28xx.kconf create mode 100644 config/generic_pc/nkernel/bsp-nkernelminuteia.kconf create mode 100644 config/generic_pc/nkernel/bsp-nkernelpentium4.kconf create mode 100644 config/generic_pc/ukernel/bsp-ukernelatom_n28xx.kconf create mode 100644 config/generic_pc/ukernel/bsp-ukernelminuteia.kconf create mode 100644 config/generic_pc/ukernel/bsp-ukernelpentium4.kconf create mode 100644 config/generic_pc/ukernel/config1p.vpf create mode 100644 config/quark/bsp.kconf create mode 100644 config/quark/defs.bsp create mode 100644 config/quark/nkernel/bsp-nkernel.kconf create mode 100644 config/quark/ukernel/bsp-ukernel.kconf create mode 100644 config/quark/ukernel/config1p.vpf create mode 100644 config/ti_lm3s6965/bsp.kconf create mode 100644 config/ti_lm3s6965/defs.bsp create mode 100644 config/ti_lm3s6965/nkernel/bsp-nkernel.kconf create mode 100644 config/ti_lm3s6965/ukernel/bsp-ukernel.kconf create mode 100644 config/ti_lm3s6965/ukernel/config1p.vpf create mode 100644 drivers/console/uart_console.c create mode 100644 drivers/console/uart_console.h create mode 100644 drivers/defs.objs create mode 100644 drivers/interrupt_controller/i8259.c create mode 100644 drivers/pci/pci.c create mode 100644 drivers/pci/pci.h create mode 100644 drivers/pci/pci_config.c create mode 100644 drivers/pci/pci_interface.c create mode 100644 drivers/pci/pci_mgr.h create mode 100644 drivers/random/rand32-timer.c create mode 100644 drivers/serial/k20UartDrv.c create mode 100644 drivers/serial/ns16550.c create mode 100644 drivers/serial/stellarisUartDrv.c create mode 100644 drivers/timer/i8253.c create mode 100644 host/src/Makefile create mode 100644 host/src/dec2hex/Makefile create mode 100644 host/src/dec2hex/dec2hex.c create mode 100644 host/src/genIdt/Makefile create mode 100644 host/src/genIdt/genIdt.c create mode 120000 host/src/genIdt/idtEnt.h create mode 120000 host/src/genIdt/segselect.h create mode 100644 host/src/genOffsetHeader/Makefile create mode 100644 host/src/genOffsetHeader/elf.h create mode 100644 host/src/genOffsetHeader/genOffsetHeader.c create mode 100644 host/src/gen_config_abssym/Makefile create mode 100644 host/src/gen_config_abssym/gen_config_abssym.c create mode 100644 host/src/include/vxmicro.h create mode 100644 host/src/include/vxmicro/os.h create mode 100644 host/src/include/vxmicro/util.h create mode 100644 host/src/include/vxmicro/version.h create mode 100644 host/src/lib/Makefile create mode 100644 host/src/lib/os.c create mode 100644 host/src/lib/util.c create mode 100644 host/src/lib/version.c create mode 100644 host/src/mkEvents/Makefile create mode 100644 host/src/mkEvents/mkevents.c create mode 100755 host/src/wrsconfig/COPYING-GPL-2.0.txt create mode 100644 host/src/wrsconfig/Makefile create mode 100755 host/src/wrsconfig/conf.c create mode 100755 host/src/wrsconfig/confdata.c create mode 100755 host/src/wrsconfig/expr.c create mode 100755 host/src/wrsconfig/expr.h create mode 100755 host/src/wrsconfig/fixdep.c create mode 100755 host/src/wrsconfig/lex.zconf.c create mode 100755 host/src/wrsconfig/lkc.h create mode 100755 host/src/wrsconfig/lkc_proto.h create mode 100755 host/src/wrsconfig/menu.c create mode 100755 host/src/wrsconfig/symbol.c create mode 100644 host/src/wrsconfig/test/h/config/auto.conf create mode 100644 host/src/wrsconfig/test/h/config/auto.conf.cmd create mode 100644 host/src/wrsconfig/test/h/config/autoconf.h create mode 100644 host/src/wrsconfig/test/h/config/wrsconfig/config/nano/kernel.h create mode 100644 host/src/wrsconfig/test/h/config/wrsconfig/config/standalone.h create mode 100644 host/src/wrsconfig/test/vsb.config create mode 100644 host/src/wrsconfig/test/vsb.config.old create mode 100644 host/src/wrsconfig/test/vxmicro.wrsconfig create mode 100755 host/src/wrsconfig/util.c create mode 100644 host/src/wrsconfig/vxmicro.wrsconfig create mode 100755 host/src/wrsconfig/zconf.hash.c create mode 100755 host/src/wrsconfig/zconf.tab.c create mode 100755 host/x86-linux2/bin/cat3files create mode 100755 host/x86-linux2/bin/dirlist create mode 100755 host/x86-linux2/bin/filelist create mode 100755 host/x86-linux2/bin/make-ll create mode 100755 host/x86-linux2/bin/truesize create mode 100755 host/x86-linux2/bin/truesize.awk create mode 100644 host/x86-linux2/lib/build_tools/.keep create mode 100644 include/absSym.h create mode 100644 include/clock_vars.h create mode 100644 include/cputype.h create mode 100644 include/drivers/ioapic.h create mode 100644 include/drivers/k20Mcg.h create mode 100644 include/drivers/k20Pcr.h create mode 100644 include/drivers/k20Sim.h create mode 100644 include/drivers/k20Uart.h create mode 100644 include/drivers/k20Wdog.h create mode 100644 include/drivers/k6xMpu.h create mode 100644 include/drivers/k6xPmc.h create mode 100644 include/drivers/loapic.h create mode 100644 include/drivers/pic.h create mode 100644 include/drivers/rand32.h create mode 100644 include/drivers/system_timer.h create mode 100644 include/drivers/uart.h create mode 100644 include/kernel_version.h create mode 100644 include/linker-defs.h create mode 100644 include/linker-tool-gcc.h create mode 100644 include/linker-tool.h create mode 100644 include/microkernel.h create mode 100644 include/microkernel/chan.h create mode 100644 include/microkernel/cmdPkt.h create mode 100644 include/microkernel/entries.h create mode 100644 include/microkernel/event.h create mode 100644 include/microkernel/event_api_export.h create mode 100644 include/microkernel/fifo.h create mode 100644 include/microkernel/fifo_api_export.h create mode 100644 include/microkernel/k_boot.h create mode 100644 include/microkernel/k_chstr.h create mode 100644 include/microkernel/k_struct.h create mode 100644 include/microkernel/k_types.h create mode 100644 include/microkernel/mail.h create mode 100644 include/microkernel/mail_api_export.h create mode 100644 include/microkernel/memcpy.h create mode 100644 include/microkernel/mmap.h create mode 100644 include/microkernel/mutex.h create mode 100644 include/microkernel/mutex_api_export.h create mode 100644 include/microkernel/pool.h create mode 100644 include/microkernel/sema.h create mode 100644 include/microkernel/sema_api_export.h create mode 100644 include/microkernel/task.h create mode 100644 include/microkernel/task_api_export.h create mode 100644 include/microkernel/task_irq.h create mode 100644 include/microkernel/task_irq_api_export.h create mode 100644 include/microkernel/ticks.h create mode 100644 include/microkernel/util/mallocInit.h create mode 100644 include/misc/__assert.h create mode 100644 include/misc/dlist.h create mode 100644 include/misc/lists.h create mode 100644 include/misc/lists_c.h create mode 100644 include/misc/printk.h create mode 100644 include/misc/util.h create mode 100644 include/nanokernel.h create mode 100644 include/nanokernel/arc/arch.h create mode 100644 include/nanokernel/arc/arcprc.h create mode 100644 include/nanokernel/arc/v2/arcv2_irq_unit.h create mode 100644 include/nanokernel/arc/v2/aux_regs.h create mode 100644 include/nanokernel/arc/v2/error.h create mode 100644 include/nanokernel/arc/v2/exc.h create mode 100644 include/nanokernel/arc/v2/ffs.h create mode 100644 include/nanokernel/arc/v2/init.h create mode 100644 include/nanokernel/arc/v2/irq.h create mode 100644 include/nanokernel/arc/v2/misc.h create mode 100644 include/nanokernel/arm/ARMprc.h create mode 100644 include/nanokernel/arm/CortexM/error.h create mode 100644 include/nanokernel/arm/CortexM/exc.h create mode 100644 include/nanokernel/arm/CortexM/ffs.h create mode 100644 include/nanokernel/arm/CortexM/gdb_stub.h create mode 100644 include/nanokernel/arm/CortexM/init.h create mode 100644 include/nanokernel/arm/CortexM/irq.h create mode 100644 include/nanokernel/arm/CortexM/memory_map-m0.h create mode 100644 include/nanokernel/arm/CortexM/memory_map-m3.h create mode 100644 include/nanokernel/arm/CortexM/memory_map.h create mode 100644 include/nanokernel/arm/CortexM/misc.h create mode 100644 include/nanokernel/arm/CortexM/nvic.h create mode 100644 include/nanokernel/arm/CortexM/scb.h create mode 100644 include/nanokernel/arm/CortexM/scripts/linker.cmd create mode 100644 include/nanokernel/arm/CortexM/scs.h create mode 100644 include/nanokernel/arm/arch.h create mode 100644 include/nanokernel/cpu.h create mode 100644 include/nanokernel/private.h create mode 100644 include/nanokernel/x86/Intelprc.h create mode 100644 include/nanokernel/x86/addr_types.h create mode 100644 include/nanokernel/x86/arch.h create mode 100644 include/nanokernel/x86/asm.h create mode 100644 include/nanokernel/x86/k_mem-gcc.h create mode 100644 include/nanokernel/x86/k_mem-other.h create mode 100644 include/nanokernel/x86/k_mem.h create mode 100644 include/nanokernel/x86/linker-common-sections.h create mode 100644 include/nanokernel/x86/linker-defs-arch.h create mode 100644 include/nanokernel/x86/linker-epilog.h create mode 100644 include/nanokernel/x86/segselect.h create mode 100644 include/section_tags.h create mode 100644 include/sections.h create mode 100644 include/string_s.h create mode 100644 include/sw_isr_table.h create mode 100644 include/toolchain.h create mode 100644 include/toolchain/common.h create mode 100644 include/toolchain/gcc.h create mode 100644 include/toolchain/unsupported.h create mode 100644 kernel/common/bsp/ctors.c create mode 100644 kernel/common/bsp/init.c create mode 100644 kernel/common/string_s.c create mode 100644 kernel/common/util/defs.objs create mode 100644 kernel/common/version.c create mode 100644 kernel/defs.objs create mode 100644 kernel/microkernel/channel/InitChan.c create mode 100644 kernel/microkernel/channel/KS_ChGet.c create mode 100644 kernel/microkernel/channel/KS_ChPtA.c create mode 100644 kernel/microkernel/channel/KS_ChPut.c create mode 100644 kernel/microkernel/channel/KS_Chan.c create mode 100644 kernel/microkernel/channel/K_ChGAck.c create mode 100644 kernel/microkernel/channel/K_ChGReq.c create mode 100644 kernel/microkernel/channel/K_ChGRpl.c create mode 100644 kernel/microkernel/channel/K_ChGTmo.c create mode 100644 kernel/microkernel/channel/K_ChPAck.c create mode 100644 kernel/microkernel/channel/K_ChPReq.c create mode 100644 kernel/microkernel/channel/K_ChPRpl.c create mode 100644 kernel/microkernel/channel/K_ChPTmo.c create mode 100644 kernel/microkernel/channel/K_ChProc.c create mode 100644 kernel/microkernel/channel/K_Ch_Mvd.c create mode 100644 kernel/microkernel/channel/K_Ch_RO.c create mode 100644 kernel/microkernel/channel/K_Ch_WO.c create mode 100644 kernel/microkernel/channel/K_Ch_WR.c create mode 100644 kernel/microkernel/channel/ch_addit.c create mode 100644 kernel/microkernel/channel/ch_buff.c create mode 100644 kernel/microkernel/channel/ch_buffm.c create mode 100644 kernel/microkernel/core/cmdPkt.c create mode 100644 kernel/microkernel/core/flashboot.c create mode 100644 kernel/microkernel/core/global.c create mode 100644 kernel/microkernel/core/k_remrpl.c create mode 100644 kernel/microkernel/core/netload.c create mode 100644 kernel/microkernel/core/taskcall.c create mode 100644 kernel/microkernel/defs.objs create mode 100644 kernel/microkernel/idle.c create mode 100644 kernel/microkernel/include/ch_buff.h create mode 100644 kernel/microkernel/include/ch_buffm.h create mode 100644 kernel/microkernel/include/ch_cfg.h create mode 100644 kernel/microkernel/include/kchan.h create mode 100644 kernel/microkernel/include/kevent.h create mode 100644 kernel/microkernel/include/kfifo.h create mode 100644 kernel/microkernel/include/kmail.h create mode 100644 kernel/microkernel/include/kmemcpy.h create mode 100644 kernel/microkernel/include/kmemp.h create mode 100644 kernel/microkernel/include/kmmap.h create mode 100644 kernel/microkernel/include/kres.h create mode 100644 kernel/microkernel/include/ksema.h create mode 100644 kernel/microkernel/include/ktask.h create mode 100644 kernel/microkernel/include/kticks.h create mode 100644 kernel/microkernel/include/minik.h create mode 100644 kernel/microkernel/include/v1.h create mode 100644 kernel/microkernel/include/v3.h create mode 100644 kernel/microkernel/k_event.c create mode 100644 kernel/microkernel/k_irq.c create mode 100644 kernel/microkernel/k_mbox.c create mode 100644 kernel/microkernel/k_memmap.c create mode 100644 kernel/microkernel/k_mempool.c create mode 100644 kernel/microkernel/k_mutex.c create mode 100644 kernel/microkernel/k_nop.c create mode 100644 kernel/microkernel/k_offload.c create mode 100644 kernel/microkernel/k_queue.c create mode 100644 kernel/microkernel/k_sema.c create mode 100644 kernel/microkernel/k_task.c create mode 100644 kernel/microkernel/k_timer.c create mode 100644 kernel/microkernel/movedata/K_cpyreq.c create mode 100644 kernel/microkernel/movedata/K_cpyrpl.c create mode 100644 kernel/microkernel/movedata/ks_moved.c create mode 100644 kernel/microkernel/movedata/movedata.c create mode 100644 kernel/microkernel/power.c create mode 100644 kernel/microkernel/task_monitor.c create mode 100644 kernel/microkernel/timer/ticker.c create mode 100644 kernel/microkernel/timer/ticks.c create mode 100644 kernel/nanokernel/core/compiler_stack_protect.c create mode 100644 kernel/nanokernel/core/idle.c create mode 100644 kernel/nanokernel/core/int_latency_bench.c create mode 100644 kernel/nanokernel/core/microk.c create mode 100644 kernel/nanokernel/core/nano_context_data.c create mode 100644 kernel/nanokernel/core/nano_lifo.c create mode 100644 kernel/nanokernel/core/nano_mwfifo.c create mode 100644 kernel/nanokernel/core/nano_sema.c create mode 100644 kernel/nanokernel/core/nano_stack.c create mode 100644 kernel/nanokernel/core/nano_timer.c create mode 100644 kernel/nanokernel/core/nanocontextentry.c create mode 100644 kernel/nanokernel/core/nanofiber.c create mode 100644 kernel/nanokernel/core/nanoinit.c create mode 100644 kernel/nanokernel/core/nanometrics.c create mode 100644 kernel/nanokernel/core/nanotime.c create mode 100644 kernel/nanokernel/include/genOffset.h create mode 100644 kernel/nanokernel/include/nanocontextentry.h create mode 100644 kernel/nanokernel/include/offsets/common.h create mode 100644 kernel/nanokernel/task/start_task.c create mode 100644 lib/libc/minimal/Makefile create mode 100644 lib/libc/minimal/include/errno.h create mode 100644 lib/libc/minimal/include/limits.h create mode 100644 lib/libc/minimal/include/stdbool.h create mode 100644 lib/libc/minimal/include/stddef.h create mode 100644 lib/libc/minimal/include/stdint.h create mode 100644 lib/libc/minimal/include/stdio.h create mode 100644 lib/libc/minimal/include/stdlib.h create mode 100644 lib/libc/minimal/include/string.h create mode 100644 lib/libc/minimal/source/stdout/fprintf.c create mode 100644 lib/libc/minimal/source/stdout/prf.c create mode 100644 lib/libc/minimal/source/stdout/sprintf.c create mode 100644 lib/libc/minimal/source/stdout/stdout_console.c create mode 100644 lib/libc/minimal/source/string/string.c create mode 100644 make/env/defs.base create mode 100644 make/env/defs.host create mode 100644 make/env/defs.host.linux2 create mode 100644 make/env/defs.host.x86-linux2 create mode 100644 make/env/defs.kver create mode 100644 make/env/rules.shared create mode 100644 make/env/rules.wb-helper create mode 100644 make/env/sanity_check create mode 100644 make/host/dir.rules create mode 100644 make/host/exe.build create mode 100644 make/host/exe.defs create mode 100644 make/host/exe.rules create mode 100644 make/host/lib.build create mode 100644 make/host/lib.defs create mode 100644 make/host/lib.rules create mode 100644 make/host/obj.defs create mode 100644 make/host/obj.rules create mode 100644 make/host/toolchain.defs create mode 100644 make/host/top.rules create mode 100644 make/target/arch/arc/defs.arch create mode 100644 make/target/arch/arc/rules.arch create mode 100644 make/target/arch/arm/defs.arch create mode 100644 make/target/arch/arm/rules.arch create mode 100644 make/target/arch/x86/defs.arch create mode 100644 make/target/arch/x86/rules.arch create mode 100644 make/target/arch/x86/rules.idt create mode 100644 make/target/env/defs.ext create mode 100644 make/target/env/defs.target create mode 100644 make/target/headers/defs.autoconf.check create mode 100644 make/target/headers/defs.autoconf.kernel create mode 100644 make/target/headers/defs.kver create mode 100644 make/target/headers/defs.offsets create mode 100644 make/target/headers/rules.autoconf create mode 100644 make/target/headers/rules.kver create mode 100644 make/target/headers/rules.offsets create mode 100644 make/target/kconfig/arch/arc/arc.kconf create mode 100644 make/target/kconfig/arch/arc/arc_em4.kconf create mode 100644 make/target/kconfig/arch/arc/arc_v2.kconf create mode 100644 make/target/kconfig/arch/arc/build.kconf create mode 100644 make/target/kconfig/arch/arc/kernel-core.kconf create mode 100644 make/target/kconfig/arch/arm/ARM.kconf create mode 100644 make/target/kconfig/arch/arm/ARM_Cortex.kconf create mode 100644 make/target/kconfig/arch/arm/ARM_CortexM.kconf create mode 100644 make/target/kconfig/arch/arm/ARM_CortexM3.kconf create mode 100644 make/target/kconfig/arch/arm/ARM_CortexM4.kconf create mode 100644 make/target/kconfig/arch/arm/build.kconf create mode 100644 make/target/kconfig/arch/arm/kernel-core.kconf create mode 100644 make/target/kconfig/arch/x86/Intel-core.kconf create mode 100644 make/target/kconfig/arch/x86/build.kconf create mode 100644 make/target/kconfig/arch/x86/kernel-core.kconf create mode 100644 make/target/kconfig/modules/apm.kconf create mode 100644 make/target/kconfig/modules/basic.kconf create mode 100644 make/target/kconfig/modules/build-base.kconf create mode 100644 make/target/kconfig/modules/debug.kconf create mode 100644 make/target/kconfig/modules/gdb.kconf create mode 100644 make/target/kconfig/modules/io.kconf create mode 100644 make/target/kconfig/modules/misc.kconf create mode 100644 make/target/kconfig/modules/monitor.kconf create mode 100644 make/target/kconfig/modules/nli.kconf create mode 100644 make/target/kconfig/modules/nli_RS232.kconf create mode 100644 make/target/kconfig/modules/security_basic.kconf create mode 100644 make/target/kconfig/nkernel.kconf create mode 100644 make/target/kconfig/product.kconf create mode 100644 make/target/kconfig/ukernel.kconf create mode 100644 make/target/kernel/arch/arc/defs.arch create mode 100644 make/target/kernel/arch/arm/defs.arch create mode 100644 make/target/kernel/check.kapp create mode 100644 make/target/kernel/check.klib create mode 100644 make/target/kernel/check.nkapp create mode 100644 make/target/kernel/check.nklib create mode 100644 make/target/kernel/check.ukapp create mode 100644 make/target/kernel/check.uklib create mode 100644 make/target/kernel/defs.kbuild create mode 100644 make/target/kernel/defs.nkbuild create mode 100644 make/target/kernel/defs.ukbuild create mode 100644 make/target/kernel/nli/rules.board.GENERIC_SERVERBOARD create mode 100644 make/target/kernel/nli/rules.board.GenericMTS_RS232 create mode 100644 make/target/kernel/nli/rules.board.Generic_RS232 create mode 100644 make/target/kernel/nli/rules.nodes create mode 100644 make/target/kernel/rules.kbuild create mode 100644 make/target/kernel/rules.kclean create mode 100644 make/target/kernel/rules.nkbuild create mode 100644 make/target/kernel/rules.ukbuild create mode 100644 make/target/kernel/rules.vpfgen create mode 100644 make/target/library/defs.library create mode 100644 make/target/library/defs.objects create mode 100644 make/target/library/rules.library create mode 100644 make/target/make.library create mode 100644 make/target/make.nkernel create mode 100644 make/target/make.nklib create mode 100644 make/target/make.ukernel create mode 100644 make/target/make.uklib create mode 100644 make/target/run/arch/defs.qemu.arc create mode 100644 make/target/run/arch/defs.qemu.arm create mode 100644 make/target/run/arch/defs.qemu.x86 create mode 100644 make/target/run/defs.emulation create mode 100644 make/target/run/defs.emulation.x86-linux2 create mode 100644 make/target/run/defs.qemu create mode 120000 make/target/run/defs.qemu.custom.vqemu create mode 100644 make/target/run/defs.qemu.default create mode 100644 make/target/run/defs.qemu.x86-linux2 create mode 100644 make/target/run/rules.emulation create mode 100644 make/target/run/rules.qemu create mode 100644 make/target/run/rules.qemu.x86-linux2 create mode 100644 make/target/stdlib/minimal/defs.kernel.stdlib create mode 100644 make/target/stdlib/minimal/defs.stdlib create mode 100644 make/target/toolchain/common/defs.objects create mode 100644 make/target/toolchain/common/rules.objects create mode 100644 make/target/toolchain/gcc/4.6/defs.flags create mode 100644 make/target/toolchain/gcc/4.6/rules.gcc create mode 100644 make/target/toolchain/gcc/4.8/defs.flags create mode 100644 make/target/toolchain/gcc/4.8/rules.gcc create mode 100644 make/target/toolchain/gcc/arch/arc/defs.exec create mode 100644 make/target/toolchain/gcc/arch/arc/defs.flags create mode 100644 make/target/toolchain/gcc/arch/arm/defs.exec create mode 100644 make/target/toolchain/gcc/arch/arm/defs.flags create mode 100644 make/target/toolchain/gcc/arch/x86/defs.exec create mode 100644 make/target/toolchain/gcc/arch/x86/defs.exec.variant_ish create mode 100644 make/target/toolchain/gcc/arch/x86/defs.exec.variant_otc create mode 100644 make/target/toolchain/gcc/arch/x86/defs.exec.variant_xtools create mode 100644 make/target/toolchain/gcc/arch/x86/defs.flags create mode 100644 make/target/toolchain/gcc/arch/x86/defs.flags.atom_n28xx create mode 100644 make/target/toolchain/gcc/arch/x86/defs.flags.minuteia create mode 100644 make/target/toolchain/gcc/arch/x86/defs.flags.pentium4 create mode 100644 make/target/toolchain/gcc/arch/x86/rules.idt create mode 100644 make/target/toolchain/gcc/defs.exec create mode 100644 make/target/toolchain/gcc/defs.ext create mode 100644 make/target/toolchain/gcc/defs.flags create mode 100644 make/target/toolchain/gcc/defs.flags.library create mode 100644 make/target/toolchain/gcc/defs.gcc create mode 100644 make/target/toolchain/gcc/defs.gcc.x86-linux2 create mode 100644 make/target/toolchain/gcc/defs.gcc.x86-linux2.variant_ish create mode 100644 make/target/toolchain/gcc/defs.gcc.x86-linux2.variant_otc create mode 100644 make/target/toolchain/gcc/defs.gcc.x86-linux2.variant_xtools create mode 100644 make/target/toolchain/gcc/defs.kernel-bin create mode 100644 make/target/toolchain/gcc/defs.offsets create mode 100644 make/target/toolchain/gcc/rules.gcc create mode 100644 make/target/toolchain/gcc/rules.kernel-bin create mode 100644 make/target/wb-helper/README create mode 100644 make/vxmicro/make/env/defs.check-host create mode 100644 make/vxmicro/make/env/defs.host.win32 create mode 100644 make/vxmicro/make/env/defs.host.x86-win32 create mode 100644 make/vxmicro/make/host/exe_extra.defs create mode 100644 make/vxmicro/make/host/lib_extra.defs create mode 100644 make/vxmicro/make/host/obj_extra.defs create mode 100644 make/vxmicro/make/host/toolchain_extra.defs create mode 100644 make/vxmicro/make/iap/host/defs.host.x86-win32 create mode 100644 make/vxmicro/make/target/arch/x86/rules.idt create mode 100644 make/vxmicro/make/target/run/defs.emulation.x86-win32 create mode 100644 make/vxmicro/make/target/run/defs.extra create mode 100644 make/vxmicro/make/target/run/defs.qemu.custom.vqemu create mode 100644 make/vxmicro/make/target/run/defs.qemu.default create mode 100644 make/vxmicro/make/target/run/defs.qemu.x86-win32 create mode 100644 make/vxmicro/make/target/run/rules.extra create mode 100644 make/vxmicro/make/target/run/rules.qemu.x86-win32 create mode 100644 make/vxmicro/make/target/toolchain/Xcc/README create mode 100644 make/vxmicro/make/target/toolchain/Xcc/defs.Xcc create mode 100644 make/vxmicro/make/target/toolchain/Xcc/defs.kernel-bin create mode 100644 make/vxmicro/make/target/toolchain/Xcc/rules.kernel-bin create mode 100644 make/vxmicro/make/target/toolchain/diab/arch/arm/defs.exec create mode 100644 make/vxmicro/make/target/toolchain/diab/arch/arm/defs.flags create mode 100644 make/vxmicro/make/target/toolchain/diab/arch/arm/defs.target create mode 100644 make/vxmicro/make/target/toolchain/diab/arch/x86/defs.exec create mode 100644 make/vxmicro/make/target/toolchain/diab/arch/x86/defs.flags create mode 100644 make/vxmicro/make/target/toolchain/diab/arch/x86/defs.target create mode 100644 make/vxmicro/make/target/toolchain/diab/arch/x86/rules.idt create mode 100644 make/vxmicro/make/target/toolchain/diab/defs.diab create mode 100644 make/vxmicro/make/target/toolchain/diab/defs.diab.host create mode 100644 make/vxmicro/make/target/toolchain/diab/defs.diab.x86-linux2 create mode 100644 make/vxmicro/make/target/toolchain/diab/defs.diab.x86-win32 create mode 100644 make/vxmicro/make/target/toolchain/diab/defs.exec create mode 100644 make/vxmicro/make/target/toolchain/diab/defs.ext create mode 100644 make/vxmicro/make/target/toolchain/diab/defs.flags create mode 100644 make/vxmicro/make/target/toolchain/diab/defs.kernel-bin create mode 100644 make/vxmicro/make/target/toolchain/diab/defs.offsets create mode 100644 make/vxmicro/make/target/toolchain/diab/defs.target create mode 100644 make/vxmicro/make/target/toolchain/diab/rules.diab create mode 100644 make/vxmicro/make/target/toolchain/diab/rules.kernel-bin create mode 100644 make/vxmicro/make/target/toolchain/gcc/defs.gcc.x86-win32 create mode 100644 make/vxmicro/make/target/toolchain/icc/13.0/defs.flags create mode 100644 make/vxmicro/make/target/toolchain/icc/13.0/rules.icc create mode 100644 make/vxmicro/make/target/toolchain/icc/arch/x86/defs.exec create mode 100644 make/vxmicro/make/target/toolchain/icc/arch/x86/defs.flags create mode 100644 make/vxmicro/make/target/toolchain/icc/arch/x86/defs.flags.atom_n28xx create mode 100644 make/vxmicro/make/target/toolchain/icc/arch/x86/defs.flags.minuteia create mode 100644 make/vxmicro/make/target/toolchain/icc/arch/x86/defs.flags.pentium4 create mode 100644 make/vxmicro/make/target/toolchain/icc/arch/x86/rules.idt create mode 100644 make/vxmicro/make/target/toolchain/icc/defs.exec create mode 100644 make/vxmicro/make/target/toolchain/icc/defs.ext create mode 100644 make/vxmicro/make/target/toolchain/icc/defs.flags create mode 100644 make/vxmicro/make/target/toolchain/icc/defs.icc create mode 100644 make/vxmicro/make/target/toolchain/icc/defs.icc.x86-linux2 create mode 100644 make/vxmicro/make/target/toolchain/icc/defs.icc.x86-win32 create mode 100644 make/vxmicro/make/target/toolchain/icc/defs.offsets create mode 100644 make/vxmicro/make/target/toolchain/icc/rules.icc create mode 100644 make/vxmicro/make/target/toolchain/icc/rules.kernel-bin create mode 100644 make/vxmicro/target/include/linker-tool-diab.h create mode 100644 misc/defs.objs create mode 100644 misc/dlist.c create mode 100644 misc/printk.c create mode 100644 samples/include/irq_test_common.h create mode 100644 samples/include/tc_util.h create mode 100644 samples/include/util_test_common.h create mode 100644 samples/libc/Makefile create mode 100644 samples/libc/README create mode 100644 samples/microkernel/apps/hello_world/Makefile create mode 100644 samples/microkernel/apps/hello_world/README.txt create mode 100644 samples/microkernel/apps/hello_world/prj.vpf create mode 100644 samples/microkernel/apps/hello_world/prj_arm.conf create mode 100644 samples/microkernel/apps/hello_world/prj_x86.conf create mode 100644 samples/microkernel/apps/hello_world/src/hello.c create mode 100644 samples/microkernel/apps/philosophers/Makefile create mode 100644 samples/microkernel/apps/philosophers/README.txt create mode 100644 samples/microkernel/apps/philosophers/prj.vpf create mode 100644 samples/microkernel/apps/philosophers/prj_arm.conf create mode 100644 samples/microkernel/apps/philosophers/prj_x86.conf create mode 100644 samples/microkernel/apps/philosophers/src/phil.h create mode 100644 samples/microkernel/apps/philosophers/src/phil_fiber.c create mode 100644 samples/microkernel/apps/philosophers/src/phil_task.c create mode 100644 samples/microkernel/benchmark/app_kernel/Makefile create mode 100644 samples/microkernel/benchmark/app_kernel/README.txt create mode 100644 samples/microkernel/benchmark/app_kernel/prj.vpf create mode 100644 samples/microkernel/benchmark/app_kernel/prj_console_float_generic.conf create mode 100644 samples/microkernel/benchmark/app_kernel/prj_console_float_pc8253.conf create mode 100644 samples/microkernel/benchmark/app_kernel/prj_console_nofloat_generic.conf create mode 100644 samples/microkernel/benchmark/app_kernel/prj_console_nofloat_pc8253.conf create mode 100644 samples/microkernel/benchmark/app_kernel/src/config.h create mode 100644 samples/microkernel/benchmark/app_kernel/src/event_b.c create mode 100644 samples/microkernel/benchmark/app_kernel/src/fifo_b.c create mode 100644 samples/microkernel/benchmark/app_kernel/src/fifo_r.c create mode 100644 samples/microkernel/benchmark/app_kernel/src/mailbox_b.c create mode 100644 samples/microkernel/benchmark/app_kernel/src/mailbox_r.c create mode 100644 samples/microkernel/benchmark/app_kernel/src/master.c create mode 100644 samples/microkernel/benchmark/app_kernel/src/master.h create mode 100644 samples/microkernel/benchmark/app_kernel/src/memcfg.h create mode 100644 samples/microkernel/benchmark/app_kernel/src/memmap_b.c create mode 100644 samples/microkernel/benchmark/app_kernel/src/mempool_b.c create mode 100644 samples/microkernel/benchmark/app_kernel/src/mutex_b.c create mode 100644 samples/microkernel/benchmark/app_kernel/src/nop_b.c create mode 100644 samples/microkernel/benchmark/app_kernel/src/pipe_b.c create mode 100644 samples/microkernel/benchmark/app_kernel/src/pipe_r.c create mode 100644 samples/microkernel/benchmark/app_kernel/src/receiver.c create mode 100644 samples/microkernel/benchmark/app_kernel/src/receiver.h create mode 100644 samples/microkernel/benchmark/app_kernel/src/sema_b.c create mode 100644 samples/microkernel/benchmark/app_kernel/src/sema_r.c create mode 100644 samples/microkernel/benchmark/boot_time/Makefile create mode 100644 samples/microkernel/benchmark/boot_time/README.txt create mode 100644 samples/microkernel/benchmark/boot_time/check_prj_conf.mk create mode 100644 samples/microkernel/benchmark/boot_time/generic_pc/prj.conf create mode 100644 samples/microkernel/benchmark/boot_time/generic_pc/prj_expert_test.conf create mode 100644 samples/microkernel/benchmark/boot_time/generic_pc/prj_pentium4_best.conf create mode 100644 samples/microkernel/benchmark/boot_time/generic_pc/prj_pentium4_default.conf create mode 100644 samples/microkernel/benchmark/boot_time/generic_pc/prj_pentium4_worst.conf create mode 100644 samples/microkernel/benchmark/boot_time/get_prj_conf.mk create mode 100644 samples/microkernel/benchmark/boot_time/prj.vpf create mode 100644 samples/microkernel/benchmark/boot_time/quark/prj.conf create mode 100644 samples/microkernel/benchmark/boot_time/src/boot_time.c create mode 100644 samples/microkernel/benchmark/footprint/Makefile create mode 100644 samples/microkernel/benchmark/footprint/README.txt create mode 100644 samples/microkernel/benchmark/footprint/micro_max.vpf create mode 100644 samples/microkernel/benchmark/footprint/micro_min.vpf create mode 100644 samples/microkernel/benchmark/footprint/micro_reg.vpf create mode 100644 samples/microkernel/benchmark/footprint/prj_max_arm.conf create mode 100644 samples/microkernel/benchmark/footprint/prj_max_x86.conf create mode 100644 samples/microkernel/benchmark/footprint/prj_min_arm.conf create mode 100644 samples/microkernel/benchmark/footprint/prj_min_x86.conf create mode 100644 samples/microkernel/benchmark/footprint/prj_reg_arm.conf create mode 100644 samples/microkernel/benchmark/footprint/prj_reg_x86.conf create mode 100644 samples/microkernel/benchmark/footprint/src/microkernel_footprint.c create mode 100644 samples/microkernel/benchmark/latency_measure/Makefile create mode 100644 samples/microkernel/benchmark/latency_measure/README.txt create mode 100644 samples/microkernel/benchmark/latency_measure/prj.vpf create mode 100644 samples/microkernel/benchmark/latency_measure/prj_generic.conf create mode 100644 samples/microkernel/benchmark/latency_measure/prj_pc8253.conf create mode 100644 samples/microkernel/benchmark/latency_measure/src/main.c create mode 100644 samples/microkernel/benchmark/latency_measure/src/micro_int_to_task.c create mode 100644 samples/microkernel/benchmark/latency_measure/src/micro_int_to_task_evt.c create mode 100644 samples/microkernel/benchmark/latency_measure/src/micro_sema_lock_release.c create mode 100644 samples/microkernel/benchmark/latency_measure/src/micro_task_switch_yield.c create mode 100644 samples/microkernel/benchmark/latency_measure/src/nano_ctx_switch.c create mode 100644 samples/microkernel/benchmark/latency_measure/src/nano_int.c create mode 100644 samples/microkernel/benchmark/latency_measure/src/nano_int_lock_unlock.c create mode 100644 samples/microkernel/benchmark/latency_measure/src/nano_int_to_fiber.c create mode 100644 samples/microkernel/benchmark/latency_measure/src/nano_int_to_fiber_sem.c create mode 100644 samples/microkernel/benchmark/latency_measure/src/timemacro.h create mode 100644 samples/microkernel/benchmark/latency_measure/src/timestamp.h create mode 100644 samples/microkernel/benchmark/latency_measure/src/utils.c create mode 100644 samples/microkernel/benchmark/latency_measure/src/utils.h create mode 100644 samples/microkernel/benchmark/sys_kernel/Makefile create mode 100644 samples/microkernel/benchmark/sys_kernel/README.txt create mode 100644 samples/microkernel/benchmark/sys_kernel/prj.vpf create mode 100644 samples/microkernel/benchmark/sys_kernel/prj_console_generic.conf create mode 100644 samples/microkernel/benchmark/sys_kernel/prj_console_pc8253.conf create mode 100644 samples/microkernel/klibs/klibs_events/Makefile create mode 100644 samples/microkernel/klibs/klibs_events/README.txt create mode 100644 samples/microkernel/klibs/klibs_events/prj.vpf create mode 100644 samples/microkernel/klibs/klibs_sema/Makefile create mode 100644 samples/microkernel/klibs/klibs_sema/README.txt create mode 100644 samples/microkernel/klibs/klibs_sema/prj.vpf create mode 100644 samples/microkernel/test/test_critical/Makefile create mode 100644 samples/microkernel/test/test_critical/README.txt create mode 100644 samples/microkernel/test/test_critical/prj.vpf create mode 100644 samples/microkernel/test/test_critical/prj_arm.conf create mode 100644 samples/microkernel/test/test_critical/prj_x86.conf create mode 100644 samples/microkernel/test/test_critical/src/critical.c create mode 100644 samples/microkernel/test/test_events/Makefile create mode 100644 samples/microkernel/test/test_events/README.txt create mode 100644 samples/microkernel/test/test_events/prj.vpf create mode 100644 samples/microkernel/test/test_events/prj_arm.conf create mode 100644 samples/microkernel/test/test_events/prj_x86.conf create mode 100644 samples/microkernel/test/test_events/src/events.c create mode 100644 samples/microkernel/test/test_events/src/test_fiber.c create mode 100644 samples/microkernel/test/test_fifo/Makefile create mode 100644 samples/microkernel/test/test_fifo/README.txt create mode 100644 samples/microkernel/test/test_fifo/prj.vpf create mode 100644 samples/microkernel/test/test_fifo/prj_arm.conf create mode 100644 samples/microkernel/test/test_fifo/prj_x86.conf create mode 100644 samples/microkernel/test/test_fifo/src/fifo.c create mode 100644 samples/microkernel/test/test_fp_sharing/Makefile create mode 100644 samples/microkernel/test/test_fp_sharing/README.txt create mode 100644 samples/microkernel/test/test_fp_sharing/prj.vpf create mode 100644 samples/microkernel/test/test_fp_sharing/prj_x86.conf create mode 100644 samples/microkernel/test/test_fp_sharing/src/float_context.h create mode 100644 samples/microkernel/test/test_fp_sharing/src/float_regs_x86.c create mode 100644 samples/microkernel/test/test_fp_sharing/src/main.c create mode 100644 samples/microkernel/test/test_fp_sharing/src/pi.c create mode 100644 samples/microkernel/test/test_libs/Makefile create mode 100644 samples/microkernel/test/test_libs/README.txt create mode 100644 samples/microkernel/test/test_libs/prj.vpf create mode 100644 samples/microkernel/test/test_libs/prj_arm.conf create mode 100644 samples/microkernel/test/test_libs/prj_x86.conf create mode 100644 samples/microkernel/test/test_libs/src/libraries.c create mode 100644 samples/microkernel/test/test_libs/src/main.c create mode 100644 samples/microkernel/test/test_mail/Makefile create mode 100644 samples/microkernel/test/test_mail/README.txt create mode 100644 samples/microkernel/test/test_mail/prj.vpf create mode 100644 samples/microkernel/test/test_mail/prj_arm.conf create mode 100644 samples/microkernel/test/test_mail/prj_x86.conf create mode 100644 samples/microkernel/test/test_mail/src/mail.c create mode 100644 samples/microkernel/test/test_mail/src/main.c create mode 100644 samples/microkernel/test/test_map/Makefile create mode 100644 samples/microkernel/test/test_map/README.txt create mode 100644 samples/microkernel/test/test_map/prj.vpf create mode 100644 samples/microkernel/test/test_map/prj_arm.conf create mode 100644 samples/microkernel/test/test_map/prj_x86.conf create mode 100644 samples/microkernel/test/test_map/src/map.c create mode 100644 samples/microkernel/test/test_mutex/Makefile create mode 100644 samples/microkernel/test/test_mutex/README.txt create mode 100644 samples/microkernel/test/test_mutex/prj.vpf create mode 100644 samples/microkernel/test/test_mutex/prj_arm.conf create mode 100644 samples/microkernel/test/test_mutex/prj_x86.conf create mode 100644 samples/microkernel/test/test_mutex/src/mutex.c create mode 100644 samples/microkernel/test/test_pipe/Makefile create mode 100644 samples/microkernel/test/test_pipe/README.txt create mode 100644 samples/microkernel/test/test_pipe/prj.vpf create mode 100644 samples/microkernel/test/test_pipe/prj_arm.conf create mode 100644 samples/microkernel/test/test_pipe/prj_x86.conf create mode 100644 samples/microkernel/test/test_pipe/src/main.c create mode 100644 samples/microkernel/test/test_pipe/src/pipe.c create mode 100644 samples/microkernel/test/test_pool/Makefile create mode 100644 samples/microkernel/test/test_pool/README.txt create mode 100644 samples/microkernel/test/test_pool/prj.vpf create mode 100644 samples/microkernel/test/test_pool/prj_arm.conf create mode 100644 samples/microkernel/test/test_pool/prj_x86.conf create mode 100644 samples/microkernel/test/test_pool/src/pool.c create mode 100644 samples/microkernel/test/test_secure_string_api/Makefile create mode 100644 samples/microkernel/test/test_secure_string_api/README.txt create mode 100644 samples/microkernel/test/test_secure_string_api/prj.vpf create mode 100644 samples/microkernel/test/test_secure_string_api/prj_arm.conf create mode 100644 samples/microkernel/test/test_secure_string_api/prj_x86.conf create mode 100644 samples/microkernel/test/test_secure_string_api/src/secure.c create mode 100644 samples/microkernel/test/test_sema/Makefile create mode 100644 samples/microkernel/test/test_sema/README.txt create mode 100644 samples/microkernel/test/test_sema/prj.vpf create mode 100644 samples/microkernel/test/test_sema/prj_arm.conf create mode 100644 samples/microkernel/test/test_sema/prj_x86.conf create mode 100644 samples/microkernel/test/test_sema/src/README create mode 100644 samples/microkernel/test/test_sema/src/main.c create mode 100644 samples/microkernel/test/test_sema/src/sema.c create mode 100644 samples/microkernel/test/test_sema/src/test_fiber.c create mode 100644 samples/microkernel/test/test_sprintf/Makefile create mode 100644 samples/microkernel/test/test_sprintf/README.txt create mode 100644 samples/microkernel/test/test_sprintf/prj.vpf create mode 100644 samples/microkernel/test/test_sprintf/prj_arm.conf create mode 100644 samples/microkernel/test/test_sprintf/prj_x86.conf create mode 100644 samples/microkernel/test/test_sprintf/src/test_sprintf.c create mode 100644 samples/microkernel/test/test_stackprot/Makefile create mode 100644 samples/microkernel/test/test_stackprot/README.txt create mode 100644 samples/microkernel/test/test_stackprot/prj.vpf create mode 100644 samples/microkernel/test/test_stackprot/prj_arm.conf create mode 100644 samples/microkernel/test/test_stackprot/prj_x86.conf create mode 100644 samples/microkernel/test/test_stackprot/src/stackprot.c create mode 100644 samples/microkernel/test/test_static_idt/Makefile create mode 100644 samples/microkernel/test/test_static_idt/README.txt create mode 100644 samples/microkernel/test/test_static_idt/prj.vpf create mode 100644 samples/microkernel/test/test_static_idt/prj_x86.conf create mode 100644 samples/microkernel/test/test_static_idt/src/static_idt.c create mode 100644 samples/microkernel/test/test_static_idt/src/test_stubs.s create mode 100644 samples/microkernel/test/test_task/Makefile create mode 100644 samples/microkernel/test/test_task/README.txt create mode 100644 samples/microkernel/test/test_task/prj.vpf create mode 100644 samples/microkernel/test/test_task/prj_arm.conf create mode 100644 samples/microkernel/test/test_task/prj_x86.conf create mode 100644 samples/microkernel/test/test_task/src/task.c create mode 100644 samples/microkernel/test/test_task_irq/Makefile create mode 100644 samples/microkernel/test/test_task_irq/README.txt create mode 100644 samples/microkernel/test/test_task_irq/prj.vpf create mode 100644 samples/microkernel/test/test_task_irq/prj_arm.conf create mode 100644 samples/microkernel/test/test_task_irq/prj_x86.conf create mode 100644 samples/microkernel/test/test_task_irq/src/main.c create mode 100644 samples/microkernel/test/test_task_irq/src/raise_int.c create mode 100644 samples/microkernel/test/test_task_irq/src/test_device.c create mode 100644 samples/microkernel/test/test_tickless/Makefile create mode 100644 samples/microkernel/test/test_tickless/README.txt create mode 100644 samples/microkernel/test/test_tickless/prj.vpf create mode 100644 samples/microkernel/test/test_tickless/prj_arm.conf create mode 100644 samples/microkernel/test/test_tickless/prj_x86.conf create mode 100644 samples/microkernel/test/test_tickless/src/test_tickless.c create mode 100644 samples/microkernel/test/test_tickless/src/timestamps.c create mode 100644 samples/microkernel/test/test_timer/Makefile create mode 100644 samples/microkernel/test/test_timer/README.txt create mode 100644 samples/microkernel/test/test_timer/prj.vpf create mode 100644 samples/microkernel/test/test_timer/prj_arm.conf create mode 100644 samples/microkernel/test/test_timer/prj_x86.conf create mode 100644 samples/microkernel/test/test_timer/src/timer.c create mode 100644 samples/microkernel/test/test_xip/Makefile create mode 100644 samples/microkernel/test/test_xip/README.txt create mode 100644 samples/microkernel/test/test_xip/prj.conf create mode 100644 samples/microkernel/test/test_xip/prj.vpf create mode 100644 samples/microkernel/test/test_xip/src/test.h create mode 100644 samples/microkernel/test/test_xip/src/test_xip.c create mode 100644 samples/microkernel/test/test_xip/src/test_xip_helper.c create mode 100644 samples/nanokernel/apps/hello_world/Makefile create mode 100644 samples/nanokernel/apps/hello_world/README.txt create mode 100644 samples/nanokernel/apps/hello_world/prj.conf create mode 100644 samples/nanokernel/apps/philosophers/Makefile create mode 100644 samples/nanokernel/apps/philosophers/README.txt create mode 100644 samples/nanokernel/apps/philosophers/prj_arc.conf create mode 100644 samples/nanokernel/apps/philosophers/prj_arm.conf create mode 100644 samples/nanokernel/apps/philosophers/prj_x86.conf create mode 100644 samples/nanokernel/benchmark/boot_time/Makefile create mode 100644 samples/nanokernel/benchmark/boot_time/README.txt create mode 100644 samples/nanokernel/benchmark/boot_time/generic_pc/prj.conf create mode 100644 samples/nanokernel/benchmark/boot_time/generic_pc/prj_expert_test.conf create mode 100644 samples/nanokernel/benchmark/boot_time/generic_pc/prj_pentium4_best.conf create mode 100644 samples/nanokernel/benchmark/boot_time/generic_pc/prj_pentium4_default.conf create mode 100644 samples/nanokernel/benchmark/boot_time/generic_pc/prj_pentium4_worst.conf create mode 100644 samples/nanokernel/benchmark/boot_time/quark/prj.conf create mode 100644 samples/nanokernel/benchmark/footprint/Makefile create mode 100644 samples/nanokernel/benchmark/footprint/README.txt create mode 100644 samples/nanokernel/benchmark/footprint/prj_max_arm.conf create mode 100644 samples/nanokernel/benchmark/footprint/prj_max_x86.conf create mode 100644 samples/nanokernel/benchmark/footprint/prj_min_arc.conf create mode 100644 samples/nanokernel/benchmark/footprint/prj_min_arm.conf create mode 100644 samples/nanokernel/benchmark/footprint/prj_min_x86.conf create mode 100644 samples/nanokernel/benchmark/footprint/prj_reg_arm.conf create mode 100644 samples/nanokernel/benchmark/footprint/prj_reg_x86.conf create mode 100644 samples/nanokernel/benchmark/footprint/src/nanokernel_footprint.c create mode 100644 samples/nanokernel/benchmark/latency_measure/Makefile create mode 100644 samples/nanokernel/benchmark/latency_measure/README.txt create mode 100644 samples/nanokernel/benchmark/latency_measure/prj.conf create mode 100644 samples/nanokernel/benchmark/sys_kernel/Makefile create mode 100644 samples/nanokernel/benchmark/sys_kernel/README.txt create mode 100644 samples/nanokernel/benchmark/sys_kernel/prj_console.conf create mode 100644 samples/nanokernel/benchmark/sys_kernel/src/lifo.c create mode 100644 samples/nanokernel/benchmark/sys_kernel/src/mwfifo.c create mode 100644 samples/nanokernel/benchmark/sys_kernel/src/sema.c create mode 100644 samples/nanokernel/benchmark/sys_kernel/src/stack.c create mode 100644 samples/nanokernel/benchmark/sys_kernel/src/syskernel.c create mode 100644 samples/nanokernel/benchmark/sys_kernel/src/syskernel.h create mode 100644 samples/nanokernel/klibs/klibs_lifo/Makefile create mode 100644 samples/nanokernel/klibs/klibs_lifo/README.txt create mode 100644 samples/nanokernel/klibs/klibs_sema/Makefile create mode 100644 samples/nanokernel/klibs/klibs_sema/README.txt create mode 100644 samples/nanokernel/test/test_arm_m3_irq_vector_table/Makefile create mode 100644 samples/nanokernel/test/test_arm_m3_irq_vector_table/README.txt create mode 100644 samples/nanokernel/test/test_arm_m3_irq_vector_table/prj.conf create mode 100644 samples/nanokernel/test/test_arm_m3_irq_vector_table/src/main.c create mode 100644 samples/nanokernel/test/test_context/Makefile create mode 100644 samples/nanokernel/test/test_context/README.txt create mode 100644 samples/nanokernel/test/test_context/prj_arm.conf create mode 100644 samples/nanokernel/test/test_context/prj_x86.conf create mode 100644 samples/nanokernel/test/test_context/src/README create mode 100644 samples/nanokernel/test/test_context/src/context.c create mode 100644 samples/nanokernel/test/test_fifo/Makefile create mode 100644 samples/nanokernel/test/test_fifo/README.txt create mode 100644 samples/nanokernel/test/test_fifo/prj_arm.conf create mode 100644 samples/nanokernel/test/test_fifo/prj_x86.conf create mode 100644 samples/nanokernel/test/test_fifo/src/fifo.c create mode 100644 samples/nanokernel/test/test_fp_sharing/Makefile create mode 100644 samples/nanokernel/test/test_fp_sharing/README.txt create mode 100644 samples/nanokernel/test/test_fp_sharing/prj_x86.conf create mode 100644 samples/nanokernel/test/test_lifo/Makefile create mode 100644 samples/nanokernel/test/test_lifo/README.txt create mode 100644 samples/nanokernel/test/test_lifo/prj_arm.conf create mode 100644 samples/nanokernel/test/test_lifo/prj_x86.conf create mode 100644 samples/nanokernel/test/test_lifo/src/README create mode 100644 samples/nanokernel/test/test_lifo/src/lifo.c create mode 100644 samples/nanokernel/test/test_sema/Makefile create mode 100644 samples/nanokernel/test/test_sema/README.txt create mode 100644 samples/nanokernel/test/test_sema/prj_arm.conf create mode 100644 samples/nanokernel/test/test_sema/prj_x86.conf create mode 100644 samples/nanokernel/test/test_sema/src/README create mode 100644 samples/nanokernel/test/test_sema/src/sema.c create mode 100644 samples/nanokernel/test/test_stack/Makefile create mode 100644 samples/nanokernel/test/test_stack/README.txt create mode 100644 samples/nanokernel/test/test_stack/prj_arm.conf create mode 100644 samples/nanokernel/test/test_stack/prj_x86.conf create mode 100644 samples/nanokernel/test/test_stack/src/stack.c create mode 100644 samples/nanokernel/test/test_stackprot/Makefile create mode 100644 samples/nanokernel/test/test_stackprot/README.txt create mode 100644 samples/nanokernel/test/test_stackprot/prj_arm.conf create mode 100644 samples/nanokernel/test/test_stackprot/prj_x86.conf create mode 100644 samples/nanokernel/test/test_static_idt/Makefile create mode 100644 samples/nanokernel/test/test_static_idt/README.txt create mode 100644 samples/nanokernel/test/test_static_idt/prj_x86.conf create mode 100644 samples/nanokernel/test/test_timer/Makefile create mode 100644 samples/nanokernel/test/test_timer/README.txt create mode 100644 samples/nanokernel/test/test_timer/prj_arm.conf create mode 100644 samples/nanokernel/test/test_timer/prj_x86.conf create mode 100644 samples/nanokernel/test/test_timer/src/README create mode 100644 samples/nanokernel/test/test_timer/src/timer.c create mode 100644 samples/nanokernel/test/test_xip/Makefile create mode 100644 samples/nanokernel/test/test_xip/README.txt create mode 100644 samples/nanokernel/test/test_xip/prj_arm.conf create mode 100644 samples/nanokernel/test/test_xip/prj_x86.conf create mode 100644 scripts/Kbuild.include create mode 100644 scripts/Makefile create mode 100644 scripts/Makefile.asm-generic create mode 100644 scripts/Makefile.build create mode 100644 scripts/Makefile.clean create mode 100644 scripts/Makefile.dtbinst create mode 100644 scripts/Makefile.extrawarn create mode 100644 scripts/Makefile.fwinst create mode 100644 scripts/Makefile.headersinst create mode 100644 scripts/Makefile.help create mode 100644 scripts/Makefile.host create mode 100644 scripts/Makefile.lib create mode 100644 scripts/Makefile.modbuiltin create mode 100644 scripts/Makefile.modinst create mode 100644 scripts/Makefile.modpost create mode 100644 scripts/Makefile.modsign create mode 100644 scripts/basic/Makefile create mode 100644 scripts/basic/bin2c.c create mode 100644 scripts/basic/fixdep.c create mode 100755 scripts/check_known_checkpatch_issues.sh create mode 100755 scripts/checkpatch.pl create mode 100755 scripts/checkstack.pl create mode 100755 scripts/config create mode 100644 scripts/cross_compiler/arm.config create mode 100644 scripts/cross_compiler/x86.config create mode 100755 scripts/depmod.sh create mode 100755 scripts/diffconfig create mode 100755 scripts/do_checkpatch.sh create mode 100644 scripts/docproc.c create mode 100755 scripts/gcc-version.sh create mode 100644 scripts/genksyms/Makefile create mode 100644 scripts/genksyms/genksyms.c create mode 100644 scripts/genksyms/genksyms.h create mode 100644 scripts/genksyms/keywords.gperf create mode 100644 scripts/genksyms/keywords.hash.c_shipped create mode 100644 scripts/genksyms/lex.l create mode 100644 scripts/genksyms/lex.lex.c_shipped create mode 100644 scripts/genksyms/parse.tab.c_shipped create mode 100644 scripts/genksyms/parse.tab.h_shipped create mode 100644 scripts/genksyms/parse.y create mode 100755 scripts/headerdep.pl create mode 100644 scripts/kconfig/Makefile create mode 100644 scripts/kconfig/POTFILES.in create mode 100755 scripts/kconfig/check.sh create mode 100644 scripts/kconfig/conf.c create mode 100644 scripts/kconfig/confdata.c create mode 100644 scripts/kconfig/expr.c create mode 100644 scripts/kconfig/expr.h create mode 100644 scripts/kconfig/gconf.c create mode 100644 scripts/kconfig/gconf.glade create mode 100644 scripts/kconfig/images.c create mode 100644 scripts/kconfig/kxgettext.c create mode 100644 scripts/kconfig/list.h create mode 100644 scripts/kconfig/lkc.h create mode 100644 scripts/kconfig/lkc_proto.h create mode 100644 scripts/kconfig/lxdialog/BIG.FAT.WARNING create mode 100755 scripts/kconfig/lxdialog/check-lxdialog.sh create mode 100644 scripts/kconfig/lxdialog/checklist.c create mode 100644 scripts/kconfig/lxdialog/dialog.h create mode 100644 scripts/kconfig/lxdialog/inputbox.c create mode 100644 scripts/kconfig/lxdialog/menubox.c create mode 100644 scripts/kconfig/lxdialog/textbox.c create mode 100644 scripts/kconfig/lxdialog/util.c create mode 100644 scripts/kconfig/lxdialog/yesno.c create mode 100644 scripts/kconfig/mconf.c create mode 100644 scripts/kconfig/menu.c create mode 100755 scripts/kconfig/merge_config.sh create mode 100644 scripts/kconfig/nconf.c create mode 100644 scripts/kconfig/nconf.gui.c create mode 100644 scripts/kconfig/nconf.h create mode 100644 scripts/kconfig/qconf.cc create mode 100644 scripts/kconfig/qconf.h create mode 100755 scripts/kconfig/streamline_config.pl create mode 100644 scripts/kconfig/symbol.c create mode 100644 scripts/kconfig/util.c create mode 100644 scripts/kconfig/zconf.gperf create mode 100644 scripts/kconfig/zconf.hash.c_shipped create mode 100644 scripts/kconfig/zconf.l create mode 100644 scripts/kconfig/zconf.lex.c_shipped create mode 100644 scripts/kconfig/zconf.tab.c_shipped create mode 100644 scripts/kconfig/zconf.y create mode 100755 scripts/link-vmlinux.sh create mode 100755 scripts/maintainer-checkpatch.bash create mode 100755 scripts/mkmakefile create mode 100755 scripts/mksysmap create mode 100644 scripts/package/Makefile create mode 100755 scripts/package/builddeb create mode 100755 scripts/package/buildtar create mode 100755 scripts/package/mkspec create mode 100644 scripts/sanity_chk/QA/README.txt create mode 100644 scripts/sanity_chk/QA/chk_sanity.sh create mode 100644 scripts/sanity_chk/QA/patterns_sanity_x86_gcc.txt create mode 100644 scripts/sanity_chk/QA/reduce_sanity.sh create mode 100755 scripts/sanity_chk/common-klibs_chk create mode 100644 scripts/sanity_chk/common.defs create mode 100755 scripts/sanity_chk/footprint_chk create mode 100755 scripts/sanity_chk/out-of-tree_chk create mode 100755 scripts/sanity_chk/regression_chk create mode 100755 scripts/sanity_chk/sanity_chk create mode 100755 scripts/setlocalversion create mode 100644 scripts/spelling.txt create mode 100755 scripts/sysgen.py create mode 100755 scripts/tags.sh create mode 100755 scripts/timestamp create mode 100644 scripts/unifdef.c create mode 100644 shared/include/nanokernel/x86/idtEnt.h create mode 100644 shared/include/nanokernel/x86/segselect.h create mode 100644 vxmicro-env.bash diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000000..c739a43a82f --- /dev/null +++ b/.gitattributes @@ -0,0 +1,5 @@ +# used to remove files from deployment using `git archive` +# git files +.gitattributes export-ignore +.gitignore export-ignore +.mailmap export-ignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000000..cbdb7282c72 --- /dev/null +++ b/.gitignore @@ -0,0 +1,13 @@ +*.o +*.a +*.d +.dir + +outdir +samples/libc/minimal-*-O? +linux2/ +host/x86-linux2/bin/gen* +host/x86-linux2/bin/bin2hex +host/x86-linux2/bin/dec2hex +host/x86-linux2/bin/mkevents +host/x86-linux2/bin/sysgen diff --git a/.mailmap b/.mailmap new file mode 100644 index 00000000000..bd12a43e888 --- /dev/null +++ b/.mailmap @@ -0,0 +1 @@ +Dirk Brandewie diff --git a/arch/arc/bsp/fatal_error.c b/arch/arc/bsp/fatal_error.c new file mode 100644 index 00000000000..4590d8c369e --- /dev/null +++ b/arch/arc/bsp/fatal_error.c @@ -0,0 +1,115 @@ +/* fatal_error.c - ARCv2 system fatal error handler */ + +/* + * Copyright (c) 2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This module provides the _SysFatalErrorHandler() routine for ARCv2 BSPs. +*/ + +/* includes */ + +#include +#include +#include +#include +#include +#include "board.h" + +#ifdef CONFIG_PRINTK +#include +#define PRINTK(...) printk(__VA_ARGS__) +#else +#define PRINTK(...) +#endif + +#ifdef CONFIG_MICROKERNEL +extern void _TaskAbort(void); +static inline void nonEssentialTaskAbort(void) +{ + PRINTK("Fatal fault in task ! Aborting task.\n"); + _TaskAbort(); +} +#define NON_ESSENTIAL_TASK_ABORT() nonEssentialTaskAbort() +#else +#define NON_ESSENTIAL_TASK_ABORT() \ + do {/* nothing */ \ + } while ((0)) +#endif + +/******************************************************************************* +* +* _SysFatalErrorHandler - fatal error handler +* +* This routine implements the corrective action to be taken when the system +* detects a fatal error. +* +* This sample implementation attempts to abort the current context and allow +* the system to continue executing, which may permit the system to continue +* functioning with degraded capabilities. +* +* System designers may wish to enhance or substitute this sample +* implementation to take other actions, such as logging error (or debug) +* information to a persistent repository and/or rebooting the system. +* +* RETURNS: N/A +* +* \NOMANUAL +*/ + +void _SysFatalErrorHandler( + unsigned int reason, /* fatal error reason */ + const NANO_ESF *pEsf /* pointer to exception stack frame */ +) +{ + nano_context_type_t curCtx = context_type_get(); + + ARG_UNUSED(reason); + ARG_UNUSED(pEsf); + + if ((curCtx == NANO_CTX_ISR) || _context_essential_check(NULL)) { + PRINTK("Fatal fault in %s ! Spinning...\n", + NANO_CTX_ISR == curCtx + ? "ISR" + : NANO_CTX_FIBER == curCtx ? "essential fiber" + : "essential task"); + for (;;) + ; /* spin forever */ + } + + if (NANO_CTX_FIBER == curCtx) { + PRINTK("Fatal fault in fiber ! Aborting fiber.\n"); + fiber_abort(); + return; + } + + NON_ESSENTIAL_TASK_ABORT(); +} diff --git a/arch/arc/bsp/prep_c.c b/arch/arc/bsp/prep_c.c new file mode 100644 index 00000000000..468e08c1c84 --- /dev/null +++ b/arch/arc/bsp/prep_c.c @@ -0,0 +1,108 @@ +/* prep_c.c - full C support initialization */ + +/* + * Copyright (c) 2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION + +Initialization of full C support: zero the .bss, copy the .data if XIP, +call _Cstart(). + +Stack is available in this module, but not the global data/bss until their +initialization is performed. +*/ + +#include +#include +#include + +/******************************************************************************* +* +* bssZero - clear BSS +* +* This routine clears the BSS region, so all bytes are 0. +* +* RETURNS: N/A +*/ + +static void bssZero(void) +{ + volatile uint32_t *pBSS = (uint32_t *)&__bss_start; + unsigned int n; + + for (n = 0; n < (unsigned int)&__bss_num_words; n++) { + pBSS[n] = 0; + } +} + +/******************************************************************************* +* +* dataCopy - copy the data section from ROM to RAM +* +* This routine copies the data section from ROM to RAM. +* +* RETURNS: N/A +*/ + +#ifdef CONFIG_XIP +static void dataCopy(void) +{ + volatile uint32_t *pROM = (uint32_t *)&__data_rom_start; + volatile uint32_t *pRAM = (uint32_t *)&__data_ram_start; + unsigned int n; + + for (n = 0; n < (unsigned int)&__data_num_words; n++) { + pRAM[n] = pROM[n]; + } +} +#else +static void dataCopy(void) +{ +} +#endif + +extern FUNC_NORETURN void _Cstart(void); +/******************************************************************************* +* +* _PrepC - prepare to and run C code +* +* This routine prepares for the execution of and runs C code. +* +* RETURNS: N/A +*/ + +void _PrepC(void) +{ + bssZero(); + dataCopy(); + _Cstart(); + CODE_UNREACHABLE; +} diff --git a/arch/arc/bsp/reset.s b/arch/arc/bsp/reset.s new file mode 100644 index 00000000000..6f711a3d910 --- /dev/null +++ b/arch/arc/bsp/reset.s @@ -0,0 +1,71 @@ +/* reset.s - reset handler */ + +/* + * Copyright (c) 2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +Reset handler that prepares the system for running C code. +*/ + +#define _ASMLANGUAGE + +#include +#include +#include +#include + +#define _RAM_END (CONFIG_RAM_START + CONFIG_RAM_SIZE) + +GTEXT(__reset) + +/******************************************************************************* +* +* __reset - reset vector +* +* Ran when the system comes out of reset. The processor is at supervisor level. +* +* Locking interrupts prevents anything from interrupting the CPU. +* +* When these steps are completed, jump to _PrepC(), which will finish setting +* up the system for running C code. +* +* RETURNS: N/A +*/ + +SECTION_FUNC(TEXT,__reset) + + /* lock interrupts: will get unlocked when switch to main task */ + clri + + /* setup a stack at the end of the RAM */ + mov sp, _RAM_END + + j @_PrepC diff --git a/arch/arc/bsp/vector_table.c b/arch/arc/bsp/vector_table.c new file mode 100644 index 00000000000..1ac95c2f7a8 --- /dev/null +++ b/arch/arc/bsp/vector_table.c @@ -0,0 +1,89 @@ +/* vector_table.c - populated exception vector table */ + +/* + * Copyright (c) 2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +Vector table with exceptions filled in. The reset vector is the system entry +point, ie. the first instruction executed. + +The table is populated with all the system exception handlers. No exception +should not be triggered until the kernel is ready to handle them. + +We are using a C file instead of an assembly file (like the ARM vector table) +to work around an issue with the assembler where: + + .word + +statements would end up with the two half-words of the functions' addresses +swapped. +*/ + +#include +#include +#include "vector_table.h" + +struct vector_table { + uint32_t reset; + uint32_t memory_error; + uint32_t instruction_error; + uint32_t ev_machine_check; + uint32_t ev_tlb_miss_i; + uint32_t ev_tlb_miss_d; + uint32_t ev_prot_v; + uint32_t ev_privilege_v; + uint32_t ev_swi; + uint32_t ev_trap; + uint32_t ev_extension; + uint32_t ev_div_zero; + uint32_t ev_dc_error; + uint32_t ev_maligned; +}; + +struct vector_table _VectorTable _GENERIC_SECTION(.exc_vector_table) = { + (uint32_t)__reset, + (uint32_t)__memory_error, + (uint32_t)__instruction_error, + (uint32_t)__ev_machine_check, + (uint32_t)__ev_tlb_miss_i, + (uint32_t)__ev_tlb_miss_d, + (uint32_t)__ev_prot_v, + (uint32_t)__ev_privilege_v, + (uint32_t)__ev_swi, + (uint32_t)__ev_trap, + (uint32_t)__ev_extension, + (uint32_t)__ev_div_zero, + (uint32_t)__ev_dc_error, + (uint32_t)__ev_maligned, +}; + +extern struct vector_table _VxMicroStart _ALIAS_OF(_VectorTable); +extern struct vector_table _start _ALIAS_OF(_VectorTable); diff --git a/arch/arc/bsp/vector_table.h b/arch/arc/bsp/vector_table.h new file mode 100644 index 00000000000..8fa6c4ef814 --- /dev/null +++ b/arch/arc/bsp/vector_table.h @@ -0,0 +1,95 @@ +/* vector_table.h - definitions for the exception vector table */ + +/* + * Copyright (c) 2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION + +Definitions for the boot vector table. + +System exception handler names all have the same format: + + __ + +Refer to the ARCv2 manual for an explanation of the exceptions. +*/ + +#ifndef _VECTOR_TABLE__H_ +#define _VECTOR_TABLE__H_ + +#ifdef _ASMLANGUAGE + +#include +#include +#include + +GTEXT(__start) +GTEXT(_VxMicroStart) +GTEXT(_VectorTable) + +GTEXT(__reset) +GTEXT(__memory_error) +GTEXT(__instruction_error) +GTEXT(__ev_machine_check) +GTEXT(__ev_tlb_miss_i) +GTEXT(__ev_tlb_miss_d) +GTEXT(__ev_prot_v) +GTEXT(__ev_privilege_v) +GTEXT(__ev_swi) +GTEXT(__ev_trap) +GTEXT(__ev_extension) +GTEXT(__ev_div_zero) +GTEXT(__ev_dc_error) +GTEXT(__ev_maligned) + +GTEXT(_PrepC) +GTEXT(_IsrWrapper) + +#else + +extern void __reset(void); +extern void __memory_error(void); +extern void __instruction_error(void); +extern void __ev_machine_check(void); +extern void __ev_tlb_miss_i(void); +extern void __ev_tlb_miss_d(void); +extern void __ev_prot_v(void); +extern void __ev_privilege_v(void); +extern void __ev_swi(void); +extern void __ev_trap(void); +extern void __ev_extension(void); +extern void __ev_div_zero(void); +extern void __ev_dc_error(void); +extern void __ev_maligned(void); + +#endif /* _ASMLANGUAGE */ + +#endif /* _VECTOR_TABLE__H_ */ diff --git a/arch/arc/core/atomic.s b/arch/arc/core/atomic.s new file mode 100644 index 00000000000..de9637b51dd --- /dev/null +++ b/arch/arc/core/atomic.s @@ -0,0 +1,445 @@ +/* armAtomic.s - ARC atomic operations library */ + +/* + * Copyright (c) 2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This library provides routines to perform a number of atomic operations +on a memory location: add, subtract, increment, decrement, bitwise OR, +bitwise NOR, bitwise AND, bitwise NAND, set, clear and compare-and-swap. +*/ + +#define _ASMLANGUAGE + +#include +#include + +/* exports */ + +GTEXT(atomic_set) +GTEXT(atomic_get) +GTEXT(atomic_add) +GTEXT(atomic_nand) +GTEXT(atomic_and) +GTEXT(atomic_or) +GTEXT(atomic_xor) +GTEXT(atomic_clear) +GTEXT(atomic_dec) +GTEXT(atomic_inc) +GTEXT(atomic_sub) +GTEXT(atomic_cas) + + .section .TEXT._Atomic, "ax" + .balign 2 + +/******************************************************************************* +* +* atomic_clear - atomically clear a memory location +* +* This routine atomically clears the contents of and returns the old +* value that was in . +* +* This routine can be used from both task and interrupt level. +* +* RETURNS: Contents of before the atomic operation +* +* ERRNO: N/A +* +* atomic_val_t atomic_clear +* ( +* atomic_t *target /@ memory location to clear @/ +* ) +*/ + +SECTION_SUBSEC_FUNC(TEXT, atomic_clear_set, atomic_clear) + mov_s r1, 0 + /* fall through into atomic_set */ + +/******************************************************************************* +* +* atomic_set - atomically set a memory location +* +* This routine atomically sets the contents of to and returns +* the old value that was in . +* +* This routine can be used from both task and interrupt level. +* +* RETURNS: Contents of before the atomic operation +* +* ERRNO: N/A +* +* atomic_val_t atomic_set +* ( +* atomic_t *target, /@ memory location to set @/ +* atomic_val_t value /@ set with this value @/ +* ) +* +*/ + +SECTION_SUBSEC_FUNC(TEXT, atomic_clear_set, atomic_set) + + ex r1, [r0] /* swap new value with old value */ + + j_s.d [blink] + mov_s r0, r1 /* return old value */ + +/****************************************************************************** +* +* atomic_get - Get the value of a shared memory atomically +* +* This routine atomically retrieves the value in *target +* +* atomic_val_t atomic_get +* ( +* atomic_t *target /@ address of atom to be retrieved @/ +* ) +* +* RETURN: value read from address target. +* +*/ + +SECTION_FUNC(TEXT, atomic_get) + ld_s r0, [r0, 0] + j_s [blink] + +/******************************************************************************* +* +* atomic_inc - atomically increment a memory location +* +* This routine atomically increments the value in . The operation is +* done using unsigned integer arithmetic. Various CPU architectures may impose +* restrictions with regards to the alignment and cache attributes of the +* atomic_t type. +* +* This routine can be used from both task and interrupt level. +* +* RETURNS: Contents of before the atomic operation +* +* ERRNO: N/A +* +* atomic_val_t atomic_inc +* ( +* atomic_t *target, /@ memory location to increment @/ +* ) +* +*/ + +SECTION_SUBSEC_FUNC(TEXT, atomic_inc_add, atomic_inc) + mov_s r1, 1 + /* fall through into atomic_add */ + +/******************************************************************************* +* +* atomic_add - atomically add a value to a memory location +* +* This routine atomically adds the contents of and , placing +* the result in . The operation is done using signed integer arithmetic. +* Various CPU architectures may impose restrictions with regards to the +* alignment and cache attributes of the atomic_t type. +* +* This routine can be used from both task and interrupt level. +* +* RETURNS: Contents of before the atomic operation +* +* ERRNO: N/A +* +* atomic_val_t atomic_add +* ( +* atomic_t *target, /@ memory location to add to @/ +* atomic_val_t value /@ value to add @/ +* ) +*/ + +SECTION_SUBSEC_FUNC(TEXT, atomic_inc_add, atomic_add) + + llock r2, [r0] /* load old value and mark exclusive access */ + add_s r3, r1, r2 + scond r3, [r0] /* try to store new value */ + + /* STATUS32.Z = 1 if successful */ + + bne_s atomic_add /* if store is not successful, retry */ + + j_s.d [blink] + mov_s r0, r2 /* return old value */ + +/******************************************************************************* +* +* atomic_dec - atomically decrement a memory location +* +* This routine atomically decrements the value in . The operation is +* done using unsigned integer arithmetic. Various CPU architectures may impose +* restrictions with regards to the alignment and cache attributes of the +* atomic_t type. +* +* This routine can be used from both task and interrupt level. +* +* RETURNS: Contents of before the atomic operation +* +* ERRNO: N/A +* +* atomic_val_t atomic_dec +* ( +* atomic_t *target, /@ memory location to decrement @/ +* ) +* +*/ + +SECTION_SUBSEC_FUNC(TEXT, atomic_dec_sub, atomic_dec) + mov_s r1, 1 + /* fall through into atomic_sub */ + +/******************************************************************************* +* +* atomic_sub - atomically subtract a value from a memory location +* +* This routine atomically subtracts from the contents of , +* placing the result in . The operation is done using signed integer +* arithmetic. Various CPU architectures may impose restrictions with regards to +* the alignment and cache attributes of the atomic_t type. +* +* This routine can be used from both task and interrupt level. +* +* RETURNS: Contents of before the atomic operation +* +* ERRNO: N/A +* +* atomic_val_t atomic_sub +* ( +* atomic_t *target, /@ memory location to subtract from @/ +* atomic_val_t value /@ value to subtract @/ +* ) +* +*/ + +SECTION_SUBSEC_FUNC(TEXT, atomic_dec_sub, atomic_sub) + + llock r2, [r0] /* load old value and mark exclusive access */ + sub r3, r2, r1 + scond r3, [r0] /* try to store new value */ + + /* STATUS32.Z = 1 if successful */ + + bne_s atomic_sub /* if store is not successful, retry */ + + j_s.d [blink] + mov_s r0, r2 /* return old value */ + +/****************************************************************************** +* +* atomic_nand - atomically perform a bitwise NAND on a memory location +* +* This routine atomically performs a bitwise NAND operation of the contents of +* and , placing the result in . +* Various CPU architectures may impose restrictions with regards to the +* alignment and cache attributes of the atomic_t type. +* +* This routine can be used from both task and interrupt level. +* +* RETURNS: Contents of before the atomic operation +* +* ERRNO: N/A +* +* atomic_val_t atomic_nand +* ( +* atomic_t *target, /@ memory location to NAND @/ +* atomic_val_t value /@ NAND with this value @/ +* ) +* +*/ + +SECTION_FUNC(TEXT, atomic_nand) + + llock r2, [r0] /* load old value and mark exclusive access */ + and r3, r1, r2 + not r3, r3 + scond r3, [r0] /* try to store new value */ + + /* STATUS32.Z = 1 if successful */ + + bne_s atomic_nand /* if store is not successful, retry */ + + j_s.d [blink] + mov_s r0, r2 /* return old value */ + +/****************************************************************************** +* +* atomic_and - atomically perform a bitwise AND on a memory location +* +* This routine atomically performs a bitwise AND operation of the contents of +* and , placing the result in . +* Various CPU architectures may impose restrictions with regards to the +* alignment and cache attributes of the atomic_t type. +* +* This routine can be used from both task and interrupt level. +* +* RETURNS: Contents of before the atomic operation +* +* ERRNO: N/A +* +* atomic_val_t atomic_and +* ( +* atomic_t *target, /@ memory location to AND @/ +* atomic_val_t value /@ AND with this value @/ +* ) +* +*/ + +SECTION_FUNC(TEXT, atomic_and) + + llock r2, [r0] /* load old value and mark exclusive access */ + and r3, r1, r2 + scond r3, [r0] /* try to store new value */ + + /* STATUS32.Z = 1 if successful */ + + bne_s atomic_and /* if store is not successful, retry */ + + j_s.d [blink] + mov_s r0, r2 /* return old value */ + +/******************************************************************************* +* +* atomic_or - atomically perform a bitwise OR on memory location +* +* This routine atomically performs a bitwise OR operation of the contents of +* and , placing the result in . +* Various CPU architectures may impose restrictions with regards to the +* alignment and cache attributes of the atomic_t type. +* +* This routine can be used from both task and interrupt level. +* +* RETURNS: Contents of before the atomic operation +* +* ERRNO: N/A +* +* atomic_val_t atomic_or +* ( +* atomic_t *target, /@ memory location to OR @/ +* atomic_val_t value /@ OR with this value @/ +* ) +* +*/ + +SECTION_FUNC(TEXT, atomic_or) + + llock r2, [r0] /* load old value and mark exclusive access */ + or r3, r1, r2 + scond r3, [r0] /* try to store new value */ + + /* STATUS32.Z = 1 if successful */ + + bne_s atomic_or /* if store is not successful, retry */ + + j_s.d [blink] + mov_s r0, r2 /* return old value */ + +/******************************************************************************* +* +* atomic_xor - atomically perform a bitwise XOR on a memory location +* +* This routine atomically performs a bitwise XOR operation of the contents of +* and , placing the result in . +* Various CPU architectures may impose restrictions with regards to the +* alignment and cache attributes of the atomic_t type. +* +* This routine can be used from both task and interrupt level. +* +* RETURNS: Contents of before the atomic operation +* +* ERRNO: N/A +* +* atomic_val_t atomic_xor +* ( +* atomic_t *target, /@ memory location to XOR @/ +* atomic_val_t value /@ XOR with this value @/ +* ) +* +*/ + +SECTION_FUNC(TEXT, atomic_xor) + + llock r2, [r0] /* load old value and mark exclusive access */ + xor r3, r1, r2 + scond r3, [r0] /* try to store new value */ + + /* STATUS32.Z = 1 if successful */ + + bne_s atomic_xor /* if store is not successful, retry */ + + j_s.d [blink] + mov_s r0, r2 /* return old value */ + +/******************************************************************************* +* +* atomic_cas - atomically compare-and-swap the contents of a memory location +* +* This routine performs an atomic compare-and-swap. testing that the contents of +* contains , and if it does, setting the value of +* to . Various CPU architectures may impose restrictions with regards +* to the alignment and cache attributes of the atomic_t type. +* +* This routine can be used from both task and interrupt level. +* +* RETURNS: 1 if the swap is actually executed, 0 otherwise. +* +* ERRNO: N/A +* +* int atomic_cas +* ( +* atomic_t *target, /@ memory location to compare-and-swap @/ +* atomic_val_t oldValue, /@ compare to this value @/ +* atomic_val_t newValue, /@ swap with this value @/ +* ) +* +*/ + +SECTION_FUNC(TEXT, atomic_cas) + + llock r3, [r0] /* load old value and mark exclusive access */ + cmp_s r1, r3 + + bne_s nanoAtomicCas_fail + + scond r2, [r0] /* try to store new value */ + + /* STATUS32.Z = 1 if successful */ + + bne_s atomic_cas /* if store is not successful, retry */ + + j_s.d [blink] + mov_s r0, 1 /* return TRUE */ + + /* failed comparison */ +nanoAtomicCas_fail: + scond r1, [r0] /* write old value to clear the access lock */ + j_s.d [blink] + mov_s r0, 0 /* return FALSE */ diff --git a/arch/arc/core/context.c b/arch/arc/core/context.c new file mode 100644 index 00000000000..3258b30e41f --- /dev/null +++ b/arch/arc/core/context.c @@ -0,0 +1,171 @@ +/* context.c - new context creation for ARCv2 */ + +/* + * Copyright (c) 2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* + * DESCRIPTION + * Core nanokernel fiber related primitives for the ARCv2 processor + * architecture. + */ + +#include +#include +#include +#include +#include +#include + +/* initial stack frame */ +struct init_stack_frame { + uint32_t pc; + uint32_t status32; + uint32_t r3; + uint32_t r2; + uint32_t r1; + uint32_t r0; +}; + +tNANO _NanoKernel = {0}; + +#if defined(CONFIG_HOST_TOOLS_SUPPORT) +#define TOOLS_SUPPORT_INIT(pCcs) toolsSupportInit(pCcs) +#else +#define TOOLS_SUPPORT_INIT(pCcs) \ + do {/* do nothing */ \ + } while ((0)) +#endif + +#if defined(CONFIG_HOST_TOOLS_SUPPORT) +/* + * toolsSupportInit - initialize host-tools support when needed + * + * Currently only inserts the new context in the list of active contexts. + * + * RETURNS: N/A + */ + +static ALWAYS_INLINE void toolsSupportInit(struct s_CCS *pCcs /* context */ + ) +{ + unsigned int key; + + /* + * Add the newly initialized context to head of the list of contexts. + * This singly linked list of contexts maintains ALL the contexts in the + * system: both tasks and fibers regardless of whether they are + * runnable. + */ + + key = irq_lock_inline(); + pCcs->activeLink = _NanoKernel.contexts; + _NanoKernel.contexts = pCcs; + irq_unlock_inline(key); +} +#endif /* CONFIG_HOST_TOOLS_SUPPORT */ + +/* + * _NewContext - initialize a new context (thread) from its stack space + * + * The control structure (CCS) is put at the lower address of the stack. An + * initial context, to be "restored" by __return_from_coop(), is put at + * the other end of the stack, and thus reusable by the stack when not + * needed anymore. + * + * The initial context is a basic stack frame that contains arguments for + * _ContextEntryRtn() return address, that points at _ContextEntryRtn() + * and status register. + * + * is currently unused. + * + * RETURNS: N/A + */ + +void *_NewContext( + char *pStackMem, /* pointer to stack memory */ + unsigned stackSize, /* stack size in bytes */ + _ContextEntry pEntry, /* context (thread) entry point routine */ + void *parameter1, /* first param to entry point */ + void *parameter2, /* second param to entry point */ + void *parameter3, /* third param to entry point */ + int priority, /* fiber priority, -1 for task */ + unsigned options /* unused, for expansion */ +) +{ + char *stackEnd = pStackMem + stackSize; + struct init_stack_frame *pInitCtx; + + tCCS *pCcs = (void *)ROUND_UP(pStackMem, sizeof(uint32_t)); + + /* carve the context entry struct from the "base" of the stack */ + + pInitCtx = (struct init_stack_frame *)(STACK_ROUND_DOWN(stackEnd) - + sizeof(struct init_stack_frame)); + + pInitCtx->pc = ((uint32_t)_ContextEntryWrapper); + pInitCtx->r0 = (uint32_t)pEntry; + pInitCtx->r1 = (uint32_t)parameter1; + pInitCtx->r2 = (uint32_t)parameter2; + pInitCtx->r3 = (uint32_t)parameter3; + /* + * For now set the interrupt priority to 15 + * we can leave interrupt enable flag set to 0 as + * seti instruction in the end of the _Swap() will + * enable the interrupts based on intlock_key + * value. + */ + pInitCtx->status32 = _ARC_V2_STATUS32_E(_ARC_V2_DEF_IRQ_LEVEL); + + pCcs->link = NULL; + pCcs->flags = priority == -1 ? TASK | PREEMPTIBLE : FIBER; + pCcs->prio = priority; + +#ifdef CONFIG_CONTEXT_CUSTOM_DATA + /* Initialize custom data field (value is opaque to kernel) */ + + pCcs->custom_data = NULL; +#endif + + /* + * intlock_key is constructed based on ARCv2 ISA Programmer's + * Reference Manual CLRI instruction description: + * dst[31:6] dst[5] dst[4] dst[3:0] + * 26'd0 1 STATUS32.IE STATUS32.E[3:0] + */ + pCcs->intlock_key = 0x3F; + pCcs->relinquish_cause = _CAUSE_COOP; + pCcs->preempReg.sp = (uint32_t)pInitCtx - __tCalleeSaved_SIZEOF; + + /* initial values in all other registers/CCS entries are irrelevant */ + + TOOLS_SUPPORT_INIT(pCcs); + + return pCcs; +} diff --git a/arch/arc/core/context_wrapper.s b/arch/arc/core/context_wrapper.s new file mode 100644 index 00000000000..3ab2354ff3e --- /dev/null +++ b/arch/arc/core/context_wrapper.s @@ -0,0 +1,64 @@ +/* ctx_wrapper.s - wrapper for _ContextEntryRtn */ + +/* + * Copyright (c) 2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* + * DESCRIPTION + * Wrapper for _ContextEntryRtn routine when called from + * the initial context + */ + +#define _ASMLANGUAGE + +#include +#include + +GTEXT(_ContextEntryWrapper) +GTEXT(_ContextEntryRtn) + + +/* + * _ContextEntryWrapper - wrapper for _ContextEntryRtn + * + * The routine pops parameters for the _ContextEntryRtn from + * stack frame, prepared by the _NewContext() routine + * + * RETURNS: N/A + */ + +SECTION_FUNC(TEXT, _ContextEntryWrapper) + + pop_s r3 + pop_s r2 + pop_s r1 + pop_s r0 + j _ContextEntryRtn + nop diff --git a/arch/arc/core/cpu_idle.s b/arch/arc/core/cpu_idle.s new file mode 100644 index 00000000000..1bd4f0d7806 --- /dev/null +++ b/arch/arc/core/cpu_idle.s @@ -0,0 +1,79 @@ +/* cpu_idle.s - CPU power management */ + +/* + * Copyright (c) 2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +CPU power management routines. +*/ + +#define _ASMLANGUAGE + +#include +#include +#include +#include +#include + +GTEXT(nano_cpu_idle) +GTEXT(nano_cpu_atomic_idle) +GDATA(nano_cpu_sleep_mode) + +SECTION_VAR(BSS, nano_cpu_sleep_mode) + .word 0 + +/* + * nano_cpu_idle - put the CPU in low-power mode + * + * This function always exits with interrupts unlocked. + * + * void nanCpuIdle(void) + */ +SECTION_FUNC(TEXT, nano_cpu_idle) + ld r1, [nano_cpu_sleep_mode] + or r1, r1, (1 << 4) /* set IRQ-enabled bit */ + sleep r1 + j_s.nd [blink] + nop + +/* + * nano_cpu_atomic_idle - put the CPU in low-power mode, entered with IRQs locked + * + * This function exits with interrupts restored to . + * + * void nano_cpu_atomic_idle(unsigned int key) + */ +SECTION_FUNC(TEXT, nano_cpu_atomic_idle) + ld r1, [nano_cpu_sleep_mode] + or r1, r1, (1 << 4) /* set IRQ-enabled bit */ + sleep r1 + j_s.d [blink] + seti r0 diff --git a/arch/arc/core/fast_irq.s b/arch/arc/core/fast_irq.s new file mode 100644 index 00000000000..38c1ae0c6a1 --- /dev/null +++ b/arch/arc/core/fast_irq.s @@ -0,0 +1,284 @@ +/* fast_irq.s - handling of transitions to-and-from fast IRQs (FIRQ) */ + +/* + * Copyright (c) 2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This module implements the code for handling entry to and exit from Fast IRQs. + +See isr_wrapper.s for details. +*/ + +#define _ASMLANGUAGE + +#include +#include +#include +#include +#include "swap_macros.h" + +GTEXT(_firq_enter) +GTEXT(_firq_exit) +GTEXT(_firq_stack_setup) +GDATA(_firq_stack) + +SECTION_VAR(NOINIT, _firq_stack) + .space CONFIG_FIRQ_STACK_SIZE + +/******************************************************************************* +* +* _firq_enter - work to be done before handing control to a FIRQ ISR +* +* The processor switches to a second register bank so registers from the +* current bank do not have to be preserved yet. The only issue is the LP_START/ +* LP_COUNT/LP_END registers, which are not banked. +* +* If all FIRQ ISRs are programmed such that there are no use of the LP +* registers (ie. no LPcc instruction), then the kernel can be configured to +* remove the use of _firq_enter(). +* +* When entering a FIRQ, interrupts might as well be locked: the processor is +* running at its highest priority, and cannot be preempted by anything. +* +* Assumption by _isr_demux: r3 is untouched by _firq_enter. +* +* RETURNS: N/A +*/ + +SECTION_FUNC(TEXT, _firq_enter) + +#ifndef CONFIG_FIRQ_NO_LPCC + /* + * Unlike the rest of context switching code, r2 is loaded with something + * else than 'current' in this routine: this is to preserve r3 so that it + * does not have to be fetched again in _isr_demux. + */ + + /* save LP_START/LP_COUNT/LP_END variables */ + mov_s r1, _NanoKernel + + /* cannot store lp_count directly to memory */ + mov r2, lp_count + st lp_count, [r1, __tNANO_firq_regs_OFFSET + __tFirqRegs_lp_count_OFFSET] + + lr r2, [_ARC_V2_LP_START] + st r2, [r1, __tNANO_firq_regs_OFFSET + __tFirqRegs_lp_start_OFFSET] + lr r2, [_ARC_V2_LP_END] + st r2, [r1, __tNANO_firq_regs_OFFSET + __tFirqRegs_lp_end_OFFSET] +#endif + + j @_isr_demux + +/******************************************************************************* +* +* _firq_exit - work to be done exiting a FIRQ +* +* RETURNS: N/A +*/ + +SECTION_FUNC(TEXT, _firq_exit) + + mov_s r1, _NanoKernel + ld_s r2, [r1, __tNANO_current_OFFSET] + +#ifndef CONFIG_FIRQ_NO_LPCC + + /* assumption: r1 contains _NanoKernel, r2 contains the current thread */ + + /* restore LP_START/LP_COUNT/LP_END variables */ + + /* cannot load lp_count from memory */ + ld r3, [r1, __tNANO_firq_regs_OFFSET + __tFirqRegs_lp_count_OFFSET] + mov lp_count, r3 + + ld r3, [r1, __tNANO_firq_regs_OFFSET + __tFirqRegs_lp_start_OFFSET] + sr r3, [_ARC_V2_LP_START] + ld r3, [r1, __tNANO_firq_regs_OFFSET + __tFirqRegs_lp_end_OFFSET] + sr r3, [_ARC_V2_LP_END] + + /* exiting here: r1/r2 unchanged, r0/r3 destroyed */ +#endif + +#if CONFIG_NUM_IRQ_PRIO_LEVELS > 1 + /* check if we're a nested interrupt: if so, let the interrupted interrupt + * handle the reschedule */ + + lr r3, [_ARC_V2_AUX_IRQ_ACT] + + /* Viper on ARCv2 always runs in kernel mode, so assume bit31 [U] in + * AUX_IRQ_ACT is always 0: if the contents of AUX_IRQ_ACT is not 1, it + * means that another bit is set so an interrupt was interrupted. + */ + + breq.nd r3, 1, _check_if_current_is_the_task + + rtie + +#endif + +.balign 4 +_check_if_current_is_the_task: + + ld r0, [r2, __tCCS_flags_OFFSET] + and.f r0, r0, PREEMPTIBLE + bnz.nd _check_if_a_fiber_is_ready + rtie + +.balign 4 +_check_if_a_fiber_is_ready: + ld r0, [r1, __tNANO_fiber_OFFSET] /* incoming fiber in r0 */ + brne.nd r0, 0, _firq_reschedule + rtie + +.balign 4 +_firq_reschedule: + + /* + * We know there is no interrupted interrupt of lower priority at this + * point, so when switching back to register bank 0, it will contain the + * registers from the interrupted thread. + */ + + /* chose register bank #0 */ + lr r0, [_ARC_V2_STATUS32] + and r0, r0, ~_ARC_V2_STATUS32_RB(7) + kflag r0 + + /* we're back on the outgoing thread's stack */ + _create_irq_stack_frame + + /* + * In a FIRQ, STATUS32 of the outgoing thread is in STATUS32_P0 and the + * PC in ILINK: save them in status32/pc respectively. + */ + + lr r0, [_ARC_V2_STATUS32_P0] + st_s r0, [sp, __tISF_status32_OFFSET] + + st ilink, [sp, __tISF_pc_OFFSET] /* ilink into pc */ + + mov_s r1, _NanoKernel + ld r2, [r1, __tNANO_current_OFFSET] + + _save_callee_saved_regs + + st _CAUSE_FIRQ, [r2, __tCCS_relinquish_cause_OFFSET] + + ld r2, [r1, __tNANO_fiber_OFFSET] + + st r2, [r1, __tNANO_current_OFFSET] + ld r3, [r2, __tCCS_link_OFFSET] + st r3, [r1, __tNANO_fiber_OFFSET] + + /* + * _load_callee_saved_regs expects incoming thread in r2. + * _load_callee_saved_regs restores the stack pointer. + */ + _load_callee_saved_regs + + ld r3, [r2, __tCCS_relinquish_cause_OFFSET] + + breq.nd r3, _CAUSE_RIRQ, _firq_return_from_rirq + nop + breq.nd r3, _CAUSE_FIRQ, _firq_return_from_firq + nop + + /* fall through */ + +.balign 4 +_firq_return_from_coop: + + ld r3, [r2, __tCCS_intlock_key_OFFSET] + st 0, [r2, __tCCS_intlock_key_OFFSET] + + /* pc into ilink */ + pop_s r0 + mov ilink, r0 + + pop_s r0 /* status32 into r0 */ + /* + * There are only two interrupt lock states: locked and unlocked. When + * entering _Swap(), they are always locked, so the IE bit is unset in + * status32. If the incoming thread had them locked recursively, it means + * that the IE bit should stay unset. The only time the bit has to change + * is if they were not locked recursively. + */ + and.f r3, r3, (1 << 4) + or.nz r0, r0, _ARC_V2_STATUS32_IE + sr r0, [_ARC_V2_STATUS32_P0] + + ld r0, [r2, __tCCS_return_value_OFFSET] + rtie + +.balign 4 +_firq_return_from_rirq: +_firq_return_from_firq: + + _pop_irq_stack_frame + + ld ilink, [sp, -4] /* status32 into ilink */ + sr ilink, [_ARC_V2_STATUS32_P0] + ld ilink, [sp, -8] /* pc into ilink */ + + /* fall through to rtie instruction */ + +.balign 4 +_firq_no_reschedule: + + /* LP registers are already restored, just switch back to bank 0 */ + rtie + +/******************************************************************************* +* +* _firq_stack_setup - install the FIRQ stack in register bank 1 +* +* RETURNS: N/A +*/ + +SECTION_FUNC(TEXT, _firq_stack_setup) + + lr r0, [_ARC_V2_STATUS32] + and r0, r0, ~_ARC_V2_STATUS32_RB(7) + or r0, r0, _ARC_V2_STATUS32_RB(1) + kflag r0 + + mov sp, _firq_stack + add sp, sp, CONFIG_FIRQ_STACK_SIZE + + /* + * We have to reload r0 here, because it is bank1 r0 which contains + * garbage, not bank0 r0 containing the previous value of status32. + */ + lr r0, [_ARC_V2_STATUS32] + and r0, r0, ~_ARC_V2_STATUS32_RB(7) + kflag r0 + + j_s.nd [blink] diff --git a/arch/arc/core/fatal.c b/arch/arc/core/fatal.c new file mode 100644 index 00000000000..52121dce0fc --- /dev/null +++ b/arch/arc/core/fatal.c @@ -0,0 +1,114 @@ +/* fatal.c - fatal fault handling */ + +/* + * Copyright (c) 2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This module implements the routines necessary for handling fatal faults on +ARCv2 CPUs. +*/ + +#include +#include +#include +#include + +#ifdef CONFIG_PRINTK +#include +#define PR_EXC(...) printk(__VA_ARGS__) +#else +#define PR_EXC(...) +#endif /* CONFIG_PRINTK */ + +const NANO_ESF __defaultEsf = { + 0xdeaddead, /* placeholder */ +}; + +/******************************************************************************* +* +* _NanoFatalErrorHandler - nanokernel fatal error handler +* +* This routine is called when fatal error conditions are detected by software +* and is responsible only for reporting the error. Once reported, it then +* invokes the user provided routine _SysFatalErrorHandler() which is +* responsible for implementing the error handling policy. +* +* The caller is expected to always provide a usable ESF. In the event that the +* fatal error does not have a hardware generated ESF, the caller should either +* create its own or use a pointer to the global default ESF <__defaultEsf>. +* +* RETURNS: This function does not return. +* +* \NOMANUAL +*/ + +FUNC_NORETURN void _NanoFatalErrorHandler(unsigned int reason, + const NANO_ESF *pEsf) +{ + switch (reason) { + case _NANO_ERR_INVALID_TASK_EXIT: + PR_EXC("***** Invalid Exit Software Error! *****\n"); + break; + +#if defined(CONFIG_STACK_CANARIES) + case _NANO_ERR_STACK_CHK_FAIL: + PR_EXC("***** Stack Check Fail! *****\n"); + break; +#endif + +#ifdef CONFIG_ENHANCED_SECURITY + case _NANO_ERR_INVALID_STRING_OP: + PR_EXC("**** Invalid string operation! ****\n"); + break; +#endif + + default: + PR_EXC("**** Unknown Fatal Error %d! ****\n", reason); + break; + } + PR_EXC("Current context ID = 0x%x\n" + "Faulting instruction address = 0x%x\n", + context_self_get(), + _arc_v2_aux_reg_read(_ARC_V2_ERET)); + + /* + * Now that the error has been reported, call the user implemented + * policy + * to respond to the error. The decisions as to what responses are + * appropriate to the various errors are something the customer must + * decide. + */ + + _SysFatalErrorHandler(reason, pEsf); + + for (;;) + ; +} diff --git a/arch/arc/core/fault.c b/arch/arc/core/fault.c new file mode 100644 index 00000000000..57c3a2610c5 --- /dev/null +++ b/arch/arc/core/fault.c @@ -0,0 +1,109 @@ +/* fault.c - common fault handler for ARCv2 */ + +/* + * Copyright (c) 2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* + * DESCRIPTION + * Common fault handler for ARCv2 processors. + */ + +#include +#include + +#include +#include +#include +#include + +#ifdef CONFIG_PRINTK +#include +#define PR_EXC(...) printk(__VA_ARGS__) +#else +#define PR_EXC(...) +#endif /* CONFIG_PRINTK */ + +#if (CONFIG_FAULT_DUMP > 0) +#define FAULT_DUMP(esf, fault) _FaultDump(esf, fault) +#else +#define FAULT_DUMP(esf, fault) \ + do { \ + (void) esf; \ + (void) fault; \ + } while ((0)) +#endif + +#if (CONFIG_FAULT_DUMP > 0) +/* + * _FaultDump - dump information regarding fault (FAULT_DUMP > 0) + * + * Dump information regarding the fault when CONFIG_FAULT_DUMP is set to 1 + * (short form). + * + * RETURNS: N/A + * + * \NOMANUAL + */ + +void _FaultDump(const NANO_ESF *esf, int fault) +{ + ARG_UNUSED(esf); + uint32_t exc_addr = _arc_v2_aux_reg_read(_ARC_V2_EFA); + uint32_t ecr = _arc_v2_aux_reg_read(_ARC_V2_ECR); + + PR_EXC("Exception vector: 0x%x, cause code: 0x%x, parameter 0x%x\n", + _ARC_V2_ECR_VECTOR(ecr), + _ARC_V2_ECR_CODE(ecr), + _ARC_V2_ECR_PARAMETER(ecr)); + PR_EXC("Address 0x%x\n", exc_addr); +} +#endif /* CONFIG_FAULT_DUMP */ + +/* + * _Fault - fault handler + * + * This routine is called when fatal error conditions are detected by hardware + * and is responsible only for reporting the error. Once reported, it then + * invokes the user provided routine _SysFatalErrorHandler() which is + * responsible for implementing the error handling policy. + * + * RETURNS: This function does not return. + * + * \NOMANUAL + */ + +void _Fault(void) +{ + uint32_t ecr = _arc_v2_aux_reg_read(_ARC_V2_ECR); + + FAULT_DUMP(&__defaultEsf, ecr); + + _SysFatalErrorHandler(_NANO_ERR_HW_EXCEPTION, &__defaultEsf); +} diff --git a/arch/arc/core/fault_s.s b/arch/arc/core/fault_s.s new file mode 100644 index 00000000000..fd5136388e6 --- /dev/null +++ b/arch/arc/core/fault_s.s @@ -0,0 +1,107 @@ +/* fault_s.s - fault handlers for ARCv2 */ + +/* + * Copyright (c) 2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* + * DESCRIPTION + * Fault handlers for ARCv2 processors. + */ + +#define _ASMLANGUAGE + +#include +#include +#include +#include "swap_macros.h" + +GTEXT(_Fault) + +GTEXT(__reset) +GTEXT(__memory_error) +GTEXT(__instruction_error) +GTEXT(__ev_machine_check) +GTEXT(__ev_tlb_miss_i) +GTEXT(__ev_tlb_miss_d) +GTEXT(__ev_prot_v) +GTEXT(__ev_privilege_v) +GTEXT(__ev_swi) +GTEXT(__ev_trap) +GTEXT(__ev_extension) +GTEXT(__ev_div_zero) +GTEXT(__ev_dc_error) +GTEXT(__ev_maligned) +GDATA(_firq_stack) + +SECTION_VAR(BSS, saved_stack_pointer) + .word 0 + +/* + * __fault - fault handler installed in the fault and reserved vectors + */ + +SECTION_SUBSEC_FUNC(TEXT,__fault,__memory_error) +SECTION_SUBSEC_FUNC(TEXT,__fault,__instruction_error) +SECTION_SUBSEC_FUNC(TEXT,__fault,__ev_machine_check) +SECTION_SUBSEC_FUNC(TEXT,__fault,__ev_tlb_miss_i) +SECTION_SUBSEC_FUNC(TEXT,__fault,__ev_tlb_miss_d) +SECTION_SUBSEC_FUNC(TEXT,__fault,__ev_prot_v) +SECTION_SUBSEC_FUNC(TEXT,__fault,__ev_privilege_v) +SECTION_SUBSEC_FUNC(TEXT,__fault,__ev_swi) +SECTION_SUBSEC_FUNC(TEXT,__fault,__ev_trap) +SECTION_SUBSEC_FUNC(TEXT,__fault,__ev_extension) +SECTION_SUBSEC_FUNC(TEXT,__fault,__ev_div_zero) +SECTION_SUBSEC_FUNC(TEXT,__fault,__ev_dc_error) +SECTION_SUBSEC_FUNC(TEXT,__fault,__ev_maligned) + + /* + * Before invoking exception handler, the kernel switches to an exception + * stack, which is really the FIRQ stack, to save the faulting thread's + * registers. It can use the FIRQ stack because it knows it is unused + * since it is save to assume that if an exception has happened in FIRQ + * handler, the problem is fatal and all the kernel can do is just print + * a diagnostic message and halt. + */ + + st sp, [saved_stack_pointer] + mov_s sp, _firq_stack + add sp, sp, CONFIG_FIRQ_STACK_SIZE + + /* save caller saved registers */ + _create_irq_stack_frame + + jl _Fault + + /* if _Fault returns, restore the registers */ + _pop_irq_stack_frame + + /* now restore the stack */ + ld sp,[saved_stack_pointer] + rtie diff --git a/arch/arc/core/ffs.s b/arch/arc/core/ffs.s new file mode 100644 index 00000000000..d7aa34c9a07 --- /dev/null +++ b/arch/arc/core/ffs.s @@ -0,0 +1,94 @@ +/* ffs.S - ARCv2 find first set assembly routines */ + +/* + * Copyright (c) 2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This library implements nanoFfsMsb() and nanoFfsLsb() which returns the +most and least significant bit set respectively. +*/ + +#define _ASMLANGUAGE + +#include +#include + +/* Exports */ + +GTEXT(nanoFfsMsb) +GTEXT(nanoFfsLsb) + +/******************************************************************************* +* +* nanoFfsMsb - find first set bit (searching from the most significant bit) +* +* This routine finds the first bit set in the argument passed it and +* returns the index of that bit. Bits are numbered starting +* at 1 from the least significant bit. A return value of zero indicates that +* the value passed is zero. +* +* RETURNS: most significant bit set +*/ + +SECTION_FUNC(TEXT, nanoFfsMsb) + + /* + * The FLS instruction returns the bit number (0-31), and 0 if the operand + * is 0. So, the bit number must be incremented by 1 only in the case of + * an operand value that is non-zero. + */ + fls.f r0, r0 + j_s.d [blink] + add.nz r0, r0, 1 + +/******************************************************************************* +* +* nanoFfsLsb - find first set bit (searching from the least significant bit) +* +* This routine finds the first bit set in the argument passed it and +* returns the index of that bit. Bits are numbered starting +* at 1 from the least significant bit. A return value of zero indicates that +* the value passed is zero. +* +* RETURNS: least significant bit set +*/ + +SECTION_FUNC(TEXT, nanoFfsLsb) + + /* + * The FFS instruction returns the bit number (0-31), and 31 if the operand + * is 0. So, the bit number must be incremented by 1, or, in the case of an + * operand value of 0, set to 0. + */ + ffs.f r0, r0 + add.nz r0, r0, 1 + j_s.d [blink] + mov.z r0, 0 diff --git a/arch/arc/core/irq_lock.s b/arch/arc/core/irq_lock.s new file mode 100644 index 00000000000..de7da469a60 --- /dev/null +++ b/arch/arc/core/irq_lock.s @@ -0,0 +1,97 @@ +/* irq_lock.s - interrupt locking */ + +/* + * Copyright (c) 2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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 _IRQ_LOCK__H_ +#define _IRQ_LOCK__H_ + +#define _ASMLANGUAGE + +#include +#include +#include +#include + +/******************************************************************************* +* +* irq_lock - disable all interrupts on the local CPU +* +* This routine disables interrupts. It can be called from either interrupt, +* task or fiber level. This routine returns an architecture-dependent +* lock-out key representing the "interrupt disable state" prior to the call; +* this key can be passed to irq_unlock() to re-enable interrupts. +* +* The lock-out key should only be used as the argument to the +* irq_unlock() API. It should never be used to manually re-enable +* interrupts or to inspect or manipulate the contents of the source register. +* +* WARNINGS +* Invoking a VxMicro routine with interrupts locked may result in +* interrupts being re-enabled for an unspecified period of time. If the +* called routine blocks, interrupts will be re-enabled while another +* context executes, or while the system is idle. +* +* The "interrupt disable state" is an attribute of a context. Thus, if a +* fiber or task disables interrupts and subsequently invokes a VxMicro +* system routine that causes the calling context to block, the interrupt +* disable state will be restored when the context is later rescheduled +* for execution. +* +* RETURNS: An architecture-dependent lock-out key representing the +* "interrupt disable state" prior to the call. +* +* \NOMANUAL +*/ + +SECTION_FUNC(TEXT, irq_lock) + j_s.d [blink] + clri r0 + +/******************************************************************************* +* +* irq_unlock - enable all interrupts on the local CPU +* +* This routine re-enables interrupts on the local CPU. The parameter +* is an architecture-dependent lock-out key that is returned by a previous +* invocation of irq_lock(). +* +* This routine can be called from either interrupt, task or fiber level. +* +* RETURNS: N/A +* +* \NOMANUAL +*/ + +SECTION_FUNC(TEXT, irq_unlock) + j_s.d [blink] + seti r0 + +#endif /* _IRQ_LOCK__H_ */ diff --git a/arch/arc/core/irq_manage.c b/arch/arc/core/irq_manage.c new file mode 100644 index 00000000000..a685175baac --- /dev/null +++ b/arch/arc/core/irq_manage.c @@ -0,0 +1,205 @@ +/* irq_manage.c - ARCv2 interrupt management */ + +/* + * Copyright (c) 2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* + * DESCRIPTION + * + * Interrupt management: + * + * - enabling/disabling + * - dynamic ISR connecting/replacing + * + * SW_ISR_TABLE_DYNAMIC has to be enabled for connecting ISRs at runtime. + * + * An IRQ number passed to the parameters found in this file is a + * number from 16 to last IRQ number on the platform. + */ + +#include +#include +#include +#include +#include +#include + +/* + * irq_handler_set - replace an interrupt handler by another + * + * An interrupt's ISR can be replaced at runtime. Care must be taken that the + * interrupt is disabled before doing this. + * + * This routine will hang if is not found in the table and ASSERT_ON is + * enabled. + * + * RETURNS: N/A + */ + +void irq_handler_set( + unsigned int irq, + void (*old)(void *arg), + void (*new)(void *arg), + void *arg +) +{ + int key = irq_lock_inline(); + int index = irq - 16; + + __ASSERT(old == _IsrTable[index].isr, + "expected ISR not found in table"); + + if (old == _IsrTable[index].isr) { + _IsrTable[index].isr = new; + _IsrTable[index].arg = arg; + } + + irq_unlock_inline(key); +} + +/* + * irq_enable - enable an interrupt line + * + * Clear possible pending interrupts on the line, and enable the interrupt + * line. After this call, the CPU will receive interrupts for the specified + * . + * + * RETURNS: N/A + */ + +void irq_enable(unsigned int irq) +{ + int key = irq_lock_inline(); + + _arc_v2_irq_unit_int_enable(irq); + irq_unlock_inline(key); +} + +/* + * irq_disable - disable an interrupt line + * + * Disable an interrupt line. After this call, the CPU will stop receiving + * interrupts for the specified . + * + * RETURNS: N/A + */ + +void irq_disable(unsigned int irq) +{ + int key = irq_lock_inline(); + + _arc_v2_irq_unit_int_disable(irq); + irq_unlock_inline(key); +} + +/* + * irq_priority_set - set an interrupt's priority + * + * Valid values are from 0 to 15. Interrupts of priority 1 are not masked when + * interrupts are locked system-wide, so care must be taken when using them. ISR + * installed with priority 0 interrupts cannot make kernel calls. + * + * The priority is verified if ASSERT_ON is enabled. + * + * RETURNS: N/A + */ + +void irq_priority_set( + unsigned int irq, + unsigned int prio +) +{ + int key = irq_lock_inline(); + + __ASSERT(prio >= 0 && prio < CONFIG_NUM_IRQ_PRIORITIES, + "invalid priority!"); + _arc_v2_irq_unit_prio_set(irq, prio); + irq_unlock_inline(key); +} + +/* + * _SpuriousIRQ - spurious interrupt handler + * + * Installed in all dynamic interrupt slots at boot time. Throws an error if + * called. + * + * RETURNS: N/A + */ + +#include +void _SpuriousIRQ(void *unused) +{ + ARG_UNUSED(unused); + printk("_SpuriousIRQ(). Spinning...\n"); + for (;;) + ; +} + +/* + * irq_connect - connect an ISR to an interrupt line + * + * is connected to interrupt line , a number greater than or equal + * 16. No prior ISR can have been connected on interrupt line since the + * system booted. + * + * This routine will hang if another ISR was connected for interrupt line + * and ASSERT_ON is enabled; if ASSERT_ON is disabled, it will fail silently. + * + * RETURNS: the interrupt line number + */ + +int irq_connect( + unsigned int irq, + unsigned int prio, + void (*isr)(void *arg), + void *arg +) +{ + irq_handler_set(irq, _SpuriousIRQ, isr, arg); + irq_priority_set(irq, prio); + return irq; +} + +/* + * irq_disconnect - disconnect an ISR from an interrupt line + * + * Interrupt line is disconnected from its ISR and the latter is + * replaced by _SpuriousIRQ(). irq_disable() should have been called before + * invoking this routine. + * + * RETURNS: N/A + */ + +void irq_disconnect(unsigned int irq) +{ + int index = irq - 16; + + irq_handler_set(irq, _IsrTable[index].isr, _SpuriousIRQ, NULL); +} diff --git a/arch/arc/core/isr_wrapper.s b/arch/arc/core/isr_wrapper.s new file mode 100644 index 00000000000..33759fd2222 --- /dev/null +++ b/arch/arc/core/isr_wrapper.s @@ -0,0 +1,240 @@ +/* isr_wrapper.s - wrapper around ISRs with logic for context switching */ + +/* + * Copyright (c) 2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION + +Wrapper installed in vector table for handling dynamic interrupts that accept +a parameter. +*/ + +#define _ASMLANGUAGE + +#include +#include +#include +#include +#include +#include + +GTEXT(_isr_enter) +GTEXT(_isr_demux) + +/* +The symbols in this file are not real functions, and neither are +_rirq_enter/_firq_enter: they are jump points. + +The flow is the following: + +ISR -> _isr_enter -- + -> _rirq_enter -> _isr_demux -> ISR -> _rirq_exit + | + + -> _firq_enter -> _isr_demux -> ISR -> _firq_exit + +Context switch explanation: + +The context switch code is spread in these files: + + isr_wrapper.s, swap.s, swap_macros.s, fast_irq.s, regular_irq.s + +IRQ stack frame layout: + + high address + + status32 + pc + [jli_base] + [ldi_base] + [ei_base] + lp_count + lp_start + lp_end + blink + r13 + ... + sp -> r0 + + low address + + [registers not taken into account in the current implementation] + +The context switch code adopts this standard so that it is easier to follow: + + - r1 contains _NanoKernel ASAP and is not overwritten over the lifespan of + the functions. + - r2 contains _NanoKernel.current ASAP, and the incoming thread when we + transition from outgoing context to incoming context + +Not loading _NanoKernel into r0 allows loading _NanoKernel without stomping on +the parameter in r0 in _Swap(). + + +ARCv2 processor have two kinds of interrupts: fast (FIRQ) and regular. The +official documentation calls them regular interrupts IRQ, but the internals of +the kernel calls them RIRQ to differentiate with the 'irq' subsystem, which is +the interrupt API/layer of abstraction. + +FIRQs can be used to allow ISRs to run without having to save any context, +since they work with a second register bank. However, they can be somewhat more +limited than RIRQs since the register bank does not copy every possible +register that is needed to implement all available instructions: an example is +that the 'loop' registers (lp_count, lp_end, lp_start) are not present in the +second bank. The kernel thus takes upon itself to save these extra registers, +if the FIRQ is made known to the kernel. It is possible for a FIRQ to operate +outside of the kernel, but care must be taken to only use instructions that +only use the banked registers. RIRQs must always use the kernel's interrupt +entry and exit mechanisms. + +The kernel is able to handle transitions to and from FIRQ, RIRQ and threads +(fibers/task). The contexts are saved 'lazily': the minimum amount of work is +done upfront, and the rest is done when needed: + +o RIRQ + + All needed regisers to run C code in the ISR are saved automatically + on the outgoing context's stack: loop, status32, pc, and the caller- + saved GPRs. That stack frame layout is pre-determined. If returning + to a fiber, the stack is popped and no registers have to be saved by + the kernel. If a context switch is required, the callee-saved GPRs + are then saved in the context control structure (CCS). + +o FIRQ + + First, a FIRQ can be interrupting a lower-priority RIRQ: if this is the case, + the first does not take a scheduling decision and leaves it the RIRQ to + handle. The limits the amount of code that has to run at interrupt-level. + + GPRs are banked, loop registers are saved in a global structure upon + interrupt entry. If returning to a fiber, loop are poppped and the + CPU switches back to bank 0 for the GPRs. If a context switch is + needed, at this point only are all the registers saved. First, a + stack frame with the same layout as the automatic RIRQ one is created + and then the callee-saved GPRs are saved in the CCS. status32_p0 and + ilink are saved in this case, not status32 and pc. + + To create the stack frame, the FIRQ handling code must first go back to using + bank0 of registers, since that is where the register containing the exiting + thread are saved. Care must be taken not to touch any register before saving + them: the only one usable at that point is the stack pointer. + +o coop + + When a coop context switch is done, the callee-saved registers are + saved in the CCS. The other GPRs do not have to be saved, since the + compiler has already placed them on the stack. + +For restoring the contexts, there are six cases. In all cases, the +callee-saved registers of the incoming thread have to be restored. Then, there +are specifics for each case: + +From coop: + + o to coop + + Restore interrupt lock level and normal function call return. + + o to any irq + + The incoming interrupted thread has an IRQ stack frame containing the + caller-saved registers that has to be popped. status32 has to be restored, + then we jump to the interrupted instruction. + +From FIRQ: + + The processor is back to using bank0, not bank1 anymore, because it had to + save the outgoing context from bank0, and not has to load the incoming one + into bank0. + + o to coop + + The address of the returning instruction from _Swap() is loaded in ilink and + the saved status32 in status32_p0, taking care to adjust the interrupt lock + state desired in status32_p0. The return value is put in r0. + + o to any irq + + The IRQ has saved the caller-saved registers in a stack frame, which must be + popped, and statu32 and pc loaded in status32_p0 and ilink. + +From RIRQ: + + o to coop + + The interrupt return mechanism in the processor expects a stack frame, but + the outgoing context did not create one. A fake one is created here, with + only the relevant values filled in: pc, status32 and the return value in r0. + + There is a discrepancy between the ABI from the ARCv2 docs, including the + way the processor pushes GPRs in pairs in the IRQ stack frame, and the ABI + GCC uses. r13 should be a callee-saved register, but GCC treats it as + caller-saved. This means that the processor pushes it in the stack frame + along with r12, but the compiler does not save it before entering a + function. So, it is saved as part of the callee-saved registers, and + restored there, but the processor restores it *a second time* when popping + the IRQ stack frame. Thus, the correct value must also be put in the fake + stack frame when returning to a thread that context switched out + cooperatively. + + o to any irq + + Both types of IRQs already have an IRQ stack frame: simply return from + interrupt. +*/ + +SECTION_FUNC(TEXT, _isr_enter) + lr r0, [_ARC_V2_AUX_IRQ_ACT] + ffs r0, r0 + cmp r0, 0 + + mov.z r3, _firq_exit + mov.z r2, _firq_enter + mov.nz r3, _rirq_exit + mov.nz r2, _rirq_enter + + j_s.nd [r2] + +/* when getting here, r3 contains the interrupt exit stub to call */ +SECTION_FUNC(TEXT, _isr_demux) + push_s r3 + lr r0, [_ARC_V2_ICAUSE] + sub r0, r0, 16 + + mov r1, _IsrTable + add3 r0, r1, r0 /* table entries are 8-bytes wide */ + + ld r1, [r0, 4] /* ISR into r1 */ + jl_s.d [r1] + ld_s r0, [r0] /* delay slot: ISR parameter into r0 */ + + /* back from ISR, jump to exit stub */ + pop_s r3 + j_s.nd [r3] + nop diff --git a/arch/arc/core/offsets/offsets.c b/arch/arc/core/offsets/offsets.c new file mode 100644 index 00000000000..b4fea0af941 --- /dev/null +++ b/arch/arc/core/offsets/offsets.c @@ -0,0 +1,126 @@ +/* offsets.c - ARCv2 nano kernel structure member offset definition file */ + +/* + * Copyright (c) 2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This module is responsible for the generation of the absolute symbols whose +value represents the member offsets for various ARCv2 nanokernel +structures. + +All of the absolute symbols defined by this module will be present in the +final microkernel or nanokernel ELF image (due to the linker's reference to +the _OffsetAbsSyms symbol). + +INTERNAL +It is NOT necessary to define the offset for every member of a structure. +Typically, only those members that are accessed by assembly language routines +are defined; however, it doesn't hurt to define all fields for the sake of +completeness. + +*/ + +#include +#include +#include + +/* ARCv2-specific tCCS structure member offsets */ +GEN_OFFSET_SYM(tNANO, rirq_sp); +GEN_OFFSET_SYM(tNANO, firq_regs); +#ifdef CONFIG_ADVANCED_POWER_MANAGEMENT +GEN_OFFSET_SYM(tNANO, idle); +#endif /* CONFIG_ADVANCED_POWER_MANAGEMENT */ + +/* ARCv2-specific tCCS structure member offsets */ +GEN_OFFSET_SYM(tCCS, intlock_key); +GEN_OFFSET_SYM(tCCS, relinquish_cause); +GEN_OFFSET_SYM(tCCS, return_value); +#ifdef CONFIG_CONTEXT_CUSTOM_DATA +GEN_OFFSET_SYM(tCCS, custom_data); +#endif + + +/* ARCv2-specific IRQ stack frame structure member offsets */ +GEN_OFFSET_SYM(tISF, r0); +GEN_OFFSET_SYM(tISF, r1); +GEN_OFFSET_SYM(tISF, r2); +GEN_OFFSET_SYM(tISF, r3); +GEN_OFFSET_SYM(tISF, r4); +GEN_OFFSET_SYM(tISF, r5); +GEN_OFFSET_SYM(tISF, r6); +GEN_OFFSET_SYM(tISF, r7); +GEN_OFFSET_SYM(tISF, r8); +GEN_OFFSET_SYM(tISF, r9); +GEN_OFFSET_SYM(tISF, r10); +GEN_OFFSET_SYM(tISF, r11); +GEN_OFFSET_SYM(tISF, r12); +GEN_OFFSET_SYM(tISF, r13); +GEN_OFFSET_SYM(tISF, blink); +GEN_OFFSET_SYM(tISF, lp_end); +GEN_OFFSET_SYM(tISF, lp_start); +GEN_OFFSET_SYM(tISF, lp_count); +GEN_OFFSET_SYM(tISF, pc); +GEN_OFFSET_SYM(tISF, status32); +GEN_ABSOLUTE_SYM(__tISF_SIZEOF, sizeof(tISF)); + +/* ARCv2-specific preempt registers structure member offsets */ +GEN_OFFSET_SYM(tPreempt, sp); +GEN_ABSOLUTE_SYM(__tPreempt_SIZEOF, sizeof(tPreempt)); + +/* ARCv2-specific callee-saved stack */ +GEN_OFFSET_SYM(tCalleeSaved, r13); +GEN_OFFSET_SYM(tCalleeSaved, r14); +GEN_OFFSET_SYM(tCalleeSaved, r15); +GEN_OFFSET_SYM(tCalleeSaved, r16); +GEN_OFFSET_SYM(tCalleeSaved, r17); +GEN_OFFSET_SYM(tCalleeSaved, r18); +GEN_OFFSET_SYM(tCalleeSaved, r19); +GEN_OFFSET_SYM(tCalleeSaved, r20); +GEN_OFFSET_SYM(tCalleeSaved, r21); +GEN_OFFSET_SYM(tCalleeSaved, r22); +GEN_OFFSET_SYM(tCalleeSaved, r23); +GEN_OFFSET_SYM(tCalleeSaved, r24); +GEN_OFFSET_SYM(tCalleeSaved, r25); +GEN_OFFSET_SYM(tCalleeSaved, r26); +GEN_OFFSET_SYM(tCalleeSaved, fp); +GEN_OFFSET_SYM(tCalleeSaved, r30); +GEN_ABSOLUTE_SYM(__tCalleeSaved_SIZEOF, sizeof(tCalleeSaved)); + +/* ARCv2-specific registers-saved-in-FIRQ structure member offsets */ +GEN_OFFSET_SYM(tFirqRegs, lp_count); +GEN_OFFSET_SYM(tFirqRegs, lp_start); +GEN_OFFSET_SYM(tFirqRegs, lp_end); +GEN_ABSOLUTE_SYM(__tFirqRegs_SIZEOF, sizeof(tFirqRegs)); + +/* size of the tCCS structure sans save area for floating point regs */ +GEN_ABSOLUTE_SYM(__tCCS_NOFLOAT_SIZEOF, sizeof(tCCS)); + +GEN_ABS_SYM_END diff --git a/arch/arc/core/regular_irq.s b/arch/arc/core/regular_irq.s new file mode 100644 index 00000000000..17e2d8b245f --- /dev/null +++ b/arch/arc/core/regular_irq.s @@ -0,0 +1,203 @@ +/* regular_irq.s - handling of transitions to-and-from regular IRQs (RIRQ) */ + +/* + * Copyright (c) 2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This module implements the code for handling entry to and exit from regular +IRQs. + +See isr_wrapper.s for details. +*/ + +#define _ASMLANGUAGE + +#include +#include +#include +#include +#include "swap_macros.h" + +GTEXT(_rirq_enter) +GTEXT(_rirq_exit) + +/******************************************************************************* +* +* _rirq_enter - work to be done before handing control to an IRQ ISR +* +* The processor pushes automatically all registers that need to be saved. +* However, since the processor always runs at kernel privilege there is no +* automatic switch to the IRQ stack: this must be done in software. +* +* Assumption by _isr_demux: r3 is untouched by _rirq_enter. +* +* RETURNS: N/A +*/ + +SECTION_FUNC(TEXT, _rirq_enter) + + mov r1, _NanoKernel + ld r2, [r1, __tNANO_current_OFFSET] +#if CONFIG_NUM_REGULAR_IRQ_PRIO_LEVELS == 1 + st sp, [r2, __tCCS_preempReg_OFFSET + __tPreempt_sp_OFFSET] + ld sp, [r1, __tNANO_rirq_sp_OFFSET] +#else +#error regular irq nesting is not implemented +#endif + j _isr_demux + + +/******************************************************************************* +* +* _rirq_exit - work to be done exiting an IRQ +* +* RETURNS: N/A +*/ + +SECTION_FUNC(TEXT, _rirq_exit) + + mov r1, _NanoKernel + ld r2, [r1, __tNANO_current_OFFSET] + +#if CONFIG_NUM_REGULAR_IRQ_PRIO_LEVELS > 1 + /* check if we're a nested interrupt: if so, let the interrupted interrupt + * handle the reschedule */ + + lr r3, [_ARC_V2_AUX_IRQ_ACT] + ffs r0, r3 + + asl r0, 1, r0 + + /* Viper on ARCv2 always runs in kernel mode, so assume bit31 [U] in + * AUX_IRQ_ACT is always 0: if the contents of AUX_IRQ_ACT is greater + * than FFS(AUX_IRQ_ACT), it means that another bit is set so an + * interrupt was interrupted. + */ + + cmp r0, r3 + brgt.nd _rirq_return_from_rirq + ld sp, [r2, __tCCS_preempReg_OFFSET + __tPreempt_sp_OFFSET] +#endif + + /* + * Both (a)reschedule and (b)non-reschedule cases need to load the current + * thread's stack, but don't have to use it until the decision is taken: + * load the delay slots with the 'load stack pointer' instruction. + * + * a) needs to load it to save outgoing context. + * b) needs to load it to restore the interrupted context. + */ + + ld r0, [r2, __tCCS_flags_OFFSET] + and.f r0, r0, PREEMPTIBLE + bz.d _rirq_no_reschedule + ld sp, [r2, __tCCS_preempReg_OFFSET + __tPreempt_sp_OFFSET] + + ld r0, [r1, __tNANO_fiber_OFFSET] /* incoming fiber in r0 */ + cmp r0, 0 + bz.d _rirq_no_reschedule + ld sp, [r2, __tCCS_preempReg_OFFSET + __tPreempt_sp_OFFSET] + +.balign 4 +_rirq_reschedule: + + /* _save_callee_saved_regs expects outgoing thread in r2 */ + _save_callee_saved_regs + + st _CAUSE_RIRQ, [r2, __tCCS_relinquish_cause_OFFSET] + + /* incoming fiber is in r0: it becomes the new 'current' */ + mov r2, r0 + st r2, [r1, __tNANO_current_OFFSET] + ld r3, [r2, __tCCS_link_OFFSET] + st r3, [r1, __tNANO_fiber_OFFSET] + + /* + * _load_callee_saved_regs expects incoming thread in r2. + * _load_callee_saved_regs restores the stack pointer. + */ + _load_callee_saved_regs + + ld r3, [r2, __tCCS_relinquish_cause_OFFSET] + + breq.nd r3, _CAUSE_RIRQ, _rirq_return_from_rirq + nop + breq.nd r3, _CAUSE_FIRQ, _rirq_return_from_firq + nop + + /* fall through */ + +.balign 4 +_rirq_return_from_coop: + + /* status32 and pc (blink) are already on the stack in the right order */ + + /* update status32.ie (explanation in firq_exit:_firq_return_from_coop) */ + ld r0, [sp, 4] + ld r3, [r2, __tCCS_intlock_key_OFFSET] + st 0, [r2, __tCCS_intlock_key_OFFSET] + cmp r3, 0 + or.ne r0, r0, _ARC_V2_STATUS32_IE + st r0, [sp, 4] + + /* carve fake stack */ + + sub sp, sp, (__tISF_SIZEOF - 12) /* a) status32/pc are already on the stack + * b) a real value will be pushed in r0 */ + + /* push return value on stack */ + ld r0, [r2, __tCCS_return_value_OFFSET] + push_s r0 + + /* + * r13 is part of both the callee and caller-saved register sets because + * the processor is only able to save registers in pair in the regular + * IRQ prologue. r13 thus has to be set to its correct value in the IRQ + * stack frame. + */ + st r13, [sp, __tISF_r13_OFFSET] + + /* stack now has the IRQ stack frame layout, pointing to r0 */ + + /* fall through to rtie instruction */ + +.balign 4 +_rirq_return_from_firq: +_rirq_return_from_rirq: + + /* rtie will pop the rest from the stack */ + + /* fall through to rtie instruction */ + +.balign 4 +_rirq_no_reschedule: + + rtie diff --git a/arch/arc/core/swap.s b/arch/arc/core/swap.s new file mode 100644 index 00000000000..3020010bab7 --- /dev/null +++ b/arch/arc/core/swap.s @@ -0,0 +1,202 @@ +/* swap.s - thread context switching */ + +/* + * Copyright (c) 2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This module implements the routines necessary for thread context switching +on ARCv2 CPUs. + +See isr_wrapper.s for details. +*/ + +#define _ASMLANGUAGE + +#include +#include +#include +#include +#include +#include "swap_macros.h" + +GTEXT(_Swap) + +GDATA(_NanoKernel) + +/******************************************************************************* +* +* _Swap - initiate a cooperative context switch +* +* The _Swap() routine is invoked by various nanokernel services to effect +* a cooperative context context switch. Prior to invoking _Swap(), the caller +* disables interrupts via nanoCpuIntLock() and the return 'key' is passed as a +* parameter to _Swap(). The key is in fact the value stored in the register +* operand of a CLRI instruction. +* +* It stores the intlock key parameter into current->intlock_key. + +* Given that _Swap() is called to effect a cooperative context context switch, +* the caller-saved integer registers are saved on the stack by the function +* call preamble to _Swap(). This creates a custom stack frame that will be +* popped when returning from _Swap(), but is not suitable for handling a return +* from an exception. Thus, the fact that the thread is pending because of a +* cooperative call to _Swap() has to be recorded via the _CAUSE_COOP code in +* the relinquish_cause of the context's tCCS. The _IrqExit()/_FirqExit() code +* will take care of doing the right thing to restore the thread status. +* +* When _Swap() is invoked, we know the decision to perform a context switch or +* not has already been taken and a context switch must happen. +* +* RETURNS: may contain a return value setup by a call to fiberRtnValueSet() +* +* C function prototype: +* +* unsigned int _Swap (unsigned int key); +* +*/ + +SECTION_FUNC(TEXT, _Swap) + + /* interrupts are locked, interrupt key is in r0 */ + + mov r1, _NanoKernel + ld r2, [r1, __tNANO_current_OFFSET] + + /* save intlock key */ + st r0, [r2, __tCCS_intlock_key_OFFSET] + st _CAUSE_COOP, [r2, __tCCS_relinquish_cause_OFFSET] + + /* + * Save status32 and blink on the stack before the callee-saved registers. + * This is the same layout as the start of an IRQ stack frame. + */ + lr r3, [_ARC_V2_STATUS32] + push_s r3 + push_s blink + + _save_callee_saved_regs + + ld r2, [r1, __tNANO_fiber_OFFSET] + breq.nd r2, 0, _swap_to_the_task + +.balign 4 +_swap_to_a_fiber: + + ld r3, [r2, __tCCS_link_OFFSET] + b.d _finish_swapping_to_context /* always execute delay slot */ + st r3, [r1, __tNANO_fiber_OFFSET] /* delay slot */ + +.balign 4 +_swap_to_the_task: + + ld r2, [r1, __tNANO_task_OFFSET] + + /* fall through */ + +.balign 4 +_finish_swapping_to_context: + + + /* entering here, r2 contains the new current context */ +#if 0 +/* don't save flags in tNANO: slower, error-prone, and might not even give + * a speed boost where it's supposed to */ + ld r3, [r2, __tCCS_flags_OFFSET] + st r3, [r1, __tNANO_flags_OFFSET] +#endif + + /* XXX - can be moved to delay slot of _CAUSE_RIRQ ? */ + st r2, [r1, __tNANO_current_OFFSET] + + _load_callee_saved_regs + + ld r3, [r2, __tCCS_relinquish_cause_OFFSET] + + breq.nd r3, _CAUSE_RIRQ, _swap_return_from_rirq + nop + breq.nd r3, _CAUSE_FIRQ, _swap_return_from_firq + nop + + /* fall through to _swap_return_from_coop */ + +.balign 4 +_swap_return_from_coop: + + ld r1, [r2, __tCCS_intlock_key_OFFSET] + st 0, [r2, __tCCS_intlock_key_OFFSET] + ld r0, [r2, __tCCS_return_value_OFFSET] + + /* + * Adjust the stack here in case we go to _return_from_exc: this allows + * keeping handling both coop and irq cases in _return_from_exc without + * adding extra logic. + */ + add_s sp, sp, 8 + lr ilink, [_ARC_V2_STATUS32] + bbit1 ilink, _ARC_V2_STATUS32_AE_BIT, _return_from_exc + sub_s sp, sp, 8 + + pop_s blink /* pc into blink */ + pop_s r3 /* status32 into r3 */ + kflag r3 /* write status32 */ + + j_s.d [blink] /* always execute delay slot */ + seti r1 /* delay slot */ + + +.balign 4 +_swap_return_from_rirq: +_swap_return_from_firq: + + _pop_irq_stack_frame + + lr ilink, [_ARC_V2_STATUS32] + bbit1 ilink, _ARC_V2_STATUS32_AE_BIT, _return_from_exc + + ld ilink, [sp, -4] /* status32 into ilink */ + and ilink, ilink, 0x7ffffffe // keep interrupts disabled until seti + kflag ilink + + ld ilink, [sp, -8] /* pc into ilink */ + + j.d [ilink] + seti (_ARC_V2_DEF_IRQ_LEVEL | (1 << 4)) + +.balign 4 +_return_from_exc: + /* put the return address to eret */ + ld ilink, [sp, -8] /* pc into ilink */ + sr ilink, [_ARC_V2_ERET] + + /* put status32 into estatus */ + ld ilink, [sp, -4] /* status32 into ilink */ + sr ilink, [_ARC_V2_ERSTATUS] + rtie diff --git a/arch/arc/core/swap_macros.h b/arch/arc/core/swap_macros.h new file mode 100644 index 00000000000..1f42f2a0002 --- /dev/null +++ b/arch/arc/core/swap_macros.h @@ -0,0 +1,176 @@ +/* swap_macros.h - helper macros for context switch */ + +/* + * Copyright (c) 2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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 _SWAP_MACROS__H_ +#define _SWAP_MACROS__H_ + +#include +#include +#include +#include + +#ifdef _ASMLANGUAGE + +/* entering this macro, current is in r2 */ +.macro _save_callee_saved_regs + + sub_s sp, sp, __tCalleeSaved_SIZEOF + + /* save regs on stack */ + st r13, [sp, __tCalleeSaved_r13_OFFSET] + st r14, [sp, __tCalleeSaved_r14_OFFSET] + st r15, [sp, __tCalleeSaved_r15_OFFSET] + st r16, [sp, __tCalleeSaved_r16_OFFSET] + st r17, [sp, __tCalleeSaved_r17_OFFSET] + st r18, [sp, __tCalleeSaved_r18_OFFSET] + st r19, [sp, __tCalleeSaved_r19_OFFSET] + st r20, [sp, __tCalleeSaved_r20_OFFSET] + st r21, [sp, __tCalleeSaved_r21_OFFSET] + st r22, [sp, __tCalleeSaved_r22_OFFSET] + st r23, [sp, __tCalleeSaved_r23_OFFSET] + st r24, [sp, __tCalleeSaved_r24_OFFSET] + st r25, [sp, __tCalleeSaved_r25_OFFSET] + st r26, [sp, __tCalleeSaved_r26_OFFSET] + st fp, [sp, __tCalleeSaved_fp_OFFSET] + st r30, [sp, __tCalleeSaved_r30_OFFSET] + + /* save stack pointer in tCCS */ + st sp, [r2, __tCCS_preempReg_OFFSET + __tPreempt_sp_OFFSET] +.endm + +/* entering this macro, current is in r2 */ +.macro _load_callee_saved_regs + /* restore stack pointer from tCCS */ + ld sp, [r2, __tCCS_preempReg_OFFSET + __tPreempt_sp_OFFSET] + + ld r13, [sp, __tCalleeSaved_r13_OFFSET] + ld r14, [sp, __tCalleeSaved_r14_OFFSET] + ld r15, [sp, __tCalleeSaved_r15_OFFSET] + ld r16, [sp, __tCalleeSaved_r16_OFFSET] + ld r17, [sp, __tCalleeSaved_r17_OFFSET] + ld r18, [sp, __tCalleeSaved_r18_OFFSET] + ld r19, [sp, __tCalleeSaved_r19_OFFSET] + ld r20, [sp, __tCalleeSaved_r20_OFFSET] + ld r21, [sp, __tCalleeSaved_r21_OFFSET] + ld r22, [sp, __tCalleeSaved_r22_OFFSET] + ld r23, [sp, __tCalleeSaved_r23_OFFSET] + ld r24, [sp, __tCalleeSaved_r24_OFFSET] + ld r25, [sp, __tCalleeSaved_r25_OFFSET] + ld r26, [sp, __tCalleeSaved_r26_OFFSET] + ld fp, [sp, __tCalleeSaved_fp_OFFSET] + ld r30, [sp, __tCalleeSaved_r30_OFFSET] + + add_s sp, sp, __tCalleeSaved_SIZEOF + +.endm + +/* + * Must be called with interrupts locked or in P0. + * Upon exit, sp will be pointing to the stack frame. + */ +.macro _create_irq_stack_frame + + sub_s sp, sp, __tISF_SIZEOF + + st blink, [sp, __tISF_blink_OFFSET] + + /* store these right away so we can use them if needed */ + + st_s r13, [sp, __tISF_r13_OFFSET] + st_s r12, [sp, __tISF_r12_OFFSET] + st r11, [sp, __tISF_r11_OFFSET] + st r10, [sp, __tISF_r10_OFFSET] + st r9, [sp, __tISF_r9_OFFSET] + st r8, [sp, __tISF_r8_OFFSET] + st r7, [sp, __tISF_r7_OFFSET] + st r6, [sp, __tISF_r6_OFFSET] + st r5, [sp, __tISF_r5_OFFSET] + st r4, [sp, __tISF_r4_OFFSET] + st_s r3, [sp, __tISF_r3_OFFSET] + st_s r2, [sp, __tISF_r2_OFFSET] + st_s r1, [sp, __tISF_r1_OFFSET] + st_s r0, [sp, __tISF_r0_OFFSET] + + mov r0, lp_count + st_s r0, [sp, __tISF_lp_count_OFFSET] + lr r0, [_ARC_V2_LP_START] + st_s r0, [sp, __tISF_lp_start_OFFSET] + lr r0, [_ARC_V2_LP_END] + st_s r0, [sp, __tISF_lp_end_OFFSET] + +.endm + +/* + * Must be called with interrupts locked or in P0. + * sp must be pointing the to stack frame. + */ +.macro _pop_irq_stack_frame + + ld blink, [sp, __tISF_blink_OFFSET] + + ld_s r0, [sp, __tISF_lp_count_OFFSET] + mov lp_count, r0 + ld_s r0, [sp, __tISF_lp_start_OFFSET] + sr r0, [_ARC_V2_LP_START] + ld_s r0, [sp, __tISF_lp_end_OFFSET] + sr r0, [_ARC_V2_LP_END] + + ld_s r13, [sp, __tISF_r13_OFFSET] + ld_s r12, [sp, __tISF_r12_OFFSET] + ld r11, [sp, __tISF_r11_OFFSET] + ld r10, [sp, __tISF_r10_OFFSET] + ld r9, [sp, __tISF_r9_OFFSET] + ld r8, [sp, __tISF_r8_OFFSET] + ld r7, [sp, __tISF_r7_OFFSET] + ld r6, [sp, __tISF_r6_OFFSET] + ld r5, [sp, __tISF_r5_OFFSET] + ld r4, [sp, __tISF_r4_OFFSET] + ld_s r3, [sp, __tISF_r3_OFFSET] + ld_s r2, [sp, __tISF_r2_OFFSET] + ld_s r1, [sp, __tISF_r1_OFFSET] + ld_s r0, [sp, __tISF_r0_OFFSET] + + /* + * All gprs have been reloaded, the only one that is still usable is + * ilink. + * + * The pc and status32 values will still be on the stack. We cannot + * pop them yet because the callers of _pop_irq_stack_frame must reload + * status32 differently depending on the context they are running in + * (_Swap(), firq or exception). + */ + add_s sp, sp, __tISF_SIZEOF + +.endm + +#endif /* _ASMLANGUAGE */ +#endif /* _SWAP_MACROS__H_ */ diff --git a/arch/arc/defs.objs b/arch/arc/defs.objs new file mode 100644 index 00000000000..fc607c5dedf --- /dev/null +++ b/arch/arc/defs.objs @@ -0,0 +1,61 @@ +# defs.objs - build system + +# +# Copyright (c) 2015 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors +# may be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. +# + +nkernel_INCLUDE_DIR = $(strip \ + ${vBASE}/arch/${vARCH}/include \ + ${vBASE}/kernel/nanokernel/include \ +) + +nkernel_PATH = $(strip \ + ${vBASE}/arch/${vARCH}/core \ + ${vBASE}/kernel/nanokernel/core \ +) + +nkernel_SRC := + +nkernel_SRC += $(strip \ + ${vBASE}/kernel/common/version.c \ + ${vBASE}/misc/printk.c \ +) + +ifeq ($(CONFIG_ENHANCED_SECURITY),y) + nkernel_SRC += $(strip \ + ${vBASE}/kernel/common/string_s.c \ +) +endif + +nkernel_SRC += $(foreach path,${nkernel_PATH},$(wildcard ${path}/*.c)) +nkernel_SRC += $(foreach path,${nkernel_PATH},$(wildcard ${path}/*.s)) + +nkernel_SRC += ${vKLIB_DIR}/configs.c + +KLIBS += nkernel diff --git a/arch/arc/include/nanok.h b/arch/arc/include/nanok.h new file mode 100644 index 00000000000..3cebe953863 --- /dev/null +++ b/arch/arc/include/nanok.h @@ -0,0 +1,287 @@ +/* nanok.h - private nanokernel definitions */ + +/* + * Copyright (c) 2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This file contains private nanokernel structures definitions and various other +definitions for the ARCv2 processor architecture. + +This file is also included by assembly language files which must #define +_ASMLANGUAGE before including this header file. Note that nanokernel assembly +source files obtains structure offset values via "absolute symbols" in the +offsets.o module. +*/ + +#ifndef _NANOK__H_ +#define _NANOK__H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +#ifndef _ASMLANGUAGE +#include +#endif + +#ifndef _ASMLANGUAGE +struct coop { + /* + * Saved on the stack as part of handling a regular IRQ or by the kernel + * when calling the FIRQ return code. + */ +}; + +struct irq_stack_frame { + uint32_t r0; + uint32_t r1; + uint32_t r2; + uint32_t r3; + uint32_t r4; + uint32_t r5; + uint32_t r6; + uint32_t r7; + uint32_t r8; + uint32_t r9; + uint32_t r10; + uint32_t r11; + uint32_t r12; + uint32_t r13; + uint32_t blink; + uint32_t lp_end; + uint32_t lp_start; + uint32_t lp_count; +#ifdef CONFIG_CODE_DENSITY + /* + * Currently unsupported. This is where those registers are automatically + * pushed on the stack by the CPU when taking a regular IRQ. + */ + uint32_t ei_base; + uint32_t ldi_base; + uint32_t jli_base; +#endif + uint32_t pc; + uint32_t status32; +}; + +typedef struct irq_stack_frame tISF; + +struct preempt { + uint32_t sp; /* r28 */ +}; +typedef struct preempt tPreempt; + +struct callee_saved { + uint32_t r13; + uint32_t r14; + uint32_t r15; + uint32_t r16; + uint32_t r17; + uint32_t r18; + uint32_t r19; + uint32_t r20; + uint32_t r21; + uint32_t r22; + uint32_t r23; + uint32_t r24; + uint32_t r25; + uint32_t r26; + uint32_t fp; /* r27 */ + /* r28 is the stack pointer and saved separately */ + /* r29 is ILINK and does not need to be saved */ + uint32_t r30; + /* + * No need to save r31 (blink), it's either alread pushed as the pc or + * blink on an irq stack frame. + */ +}; +typedef struct callee_saved tCalleeSaved; + +/* registers saved by software when taking a FIRQ */ +struct firq_regs { + uint32_t lp_count; + uint32_t lp_start; + uint32_t lp_end; +}; +typedef struct firq_regs tFirqRegs; + +#endif /* _ASMLANGUAGE */ + +/* Bitmask definitions for the tCCS->flags bit field */ + +#define FIBER 0x000 +#define TASK 0x001 /* 1 = task context, 0 = fiber context */ + +#define INT_ACTIVE 0x002 /* 1 = context is executing interrupt handler */ +#define EXC_ACTIVE 0x004 /* 1 = context is executing exception handler */ +#define USE_FP 0x010 /* 1 = context uses floating point unit */ +#define PREEMPTIBLE 0x020 /* 1 = preemptible context */ +#define ESSENTIAL 0x200 /* 1 = system context that must not abort */ +#define NO_METRICS 0x400 /* 1 = _Swap() not to update task metrics */ + +/* stacks */ + +#define STACK_GROWS_DOWN 0 +#define STACK_GROWS_UP 1 +#define STACK_ALIGN_SIZE 4 + +#define STACK_ROUND_UP(x) ROUND_UP(x, STACK_ALIGN_SIZE) +#define STACK_ROUND_DOWN(x) ROUND_DOWN(x, STACK_ALIGN_SIZE) + +/* + * Reason a context has relinquished control: fibers can only be in the NONE + * or COOP state, tasks can be one in the four. + */ +#define _CAUSE_NONE 0 +#define _CAUSE_COOP 1 +#define _CAUSE_RIRQ 2 +#define _CAUSE_FIRQ 3 + +#ifndef _ASMLANGUAGE + +struct s_CCS { + struct s_CCS *link; /* node in singly-linked list + * _NanoKernel.fibers */ + uint32_t flags; /* bitmask of flags above */ + uint32_t intlock_key; /* interrupt key when relinquishing control */ + int relinquish_cause; /* one of the _CAUSE_xxxx definitions above */ + unsigned int return_value; /* return value from _Swap */ + int prio; /* fiber priority, -1 for a task */ +#ifdef CONFIG_CONTEXT_CUSTOM_DATA + void *custom_data; /* available for custom use */ +#endif + struct coop coopReg; + struct preempt preempReg; +#ifdef CONFIG_HOST_TOOLS_SUPPORT + struct s_CCS *activeLink; /* link to next context in the active list */ +#endif +}; + +struct s_NANO { + tCCS *fiber; /* singly linked list of runnable fiber contexts */ + tCCS *task; /* current task the nanokernel knows about */ + tCCS *current; /* currently scheduled context (fiber or task) */ + +#ifdef CONFIG_HOST_TOOLS_SUPPORT + tCCS *contexts; /* singly linked list of ALL fiber+tasks */ +#endif + +#ifdef CONFIG_FP_SHARING + tCCS *current_fp; /* context (fiber or task) that owns the FP regs */ +#endif + +#ifdef CONFIG_ADVANCED_POWER_MANAGEMENT + int32_t idle; /* Number of ticks for kernel idling */ +#endif + + char *rirq_sp; /* regular IRQ stack pointer base */ + + /* + * FIRQ stack pointer is installed once in the second bank's SP, so + * there is no need to track it in _NanoKernel. + */ + + struct firq_regs firq_regs; +}; + +typedef struct s_NANO tNANO; +extern tNANO _NanoKernel; + +#ifdef CONFIG_CPU_ARCV2 +#include +#include +#endif + +static ALWAYS_INLINE void nanoArchInit(void) +{ + _icache_setup(); + _irq_setup(); +} + +/******************************************************************************* +* +* fiberRtnValueSet - set the return value for the specified fiber (inline) +* +* The register used to store the return value from a function call invocation +* to . It is assumed that the specified is pending, and thus +* the fiber's context is stored in its tCCS structure. +* +* RETURNS: N/A +* +* \NOMANUAL +*/ + +static ALWAYS_INLINE void fiberRtnValueSet(tCCS *fiber, unsigned int value) +{ + fiber->return_value = value; +} + +/******************************************************************************* +* +* _IS_IN_ISR - indicates if kernel is handling interrupt +* +* RETURNS: 1 if interrupt handler is executed, 0 otherwise +* +* \NOMANUAL +*/ + +static ALWAYS_INLINE int _IS_IN_ISR(void) +{ + uint32_t act = _arc_v2_aux_reg_read(_ARC_V2_AUX_IRQ_ACT); + + return ((act & 0xffff) != 0); +} + +extern void _InsertCCS(tCCS **, tCCS *); +extern void *_NewContext(char *, unsigned, _ContextEntry, + _ContextArg, _ContextArg, _ContextArg, + int, unsigned); + +extern unsigned int _Swap(unsigned int); +extern void nanoCpuAtomicIdle(unsigned int); +extern void _ContextEntryWrapper(void); + +static inline void _IntLibInit(void) +{ + /* nothing needed, here because the kernel requires it */ +} + +#endif /* _ASMLANGUAGE */ + +#ifdef __cplusplus +} +#endif + +#endif /* _NANOK__H_ */ diff --git a/arch/arc/include/v2/cache.h b/arch/arc/include/v2/cache.h new file mode 100644 index 00000000000..5a258232b2b --- /dev/null +++ b/arch/arc/include/v2/cache.h @@ -0,0 +1,66 @@ +/* cache.h - cache helper functions (ARC) */ + +/* + * Copyright (c) 2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* + * DESCRIPTION + * This file contains private nanokernel structures definitions and various + * other definitions for the ARCv2 processor architecture. + */ + +#ifndef _ARCV2_CACHE__H_ +#define _ARCV2_CACHE__H_ + +#include + +#ifndef _ASMLANGUAGE + +#define CACHE_ENABLE 0x00 +#define CACHE_DISABLE 0x01 +#define CACHE_DIRECT 0x00 +#define CACHE_CACHE_CONTROLLED 0x20 + +/* + * _icache_enable - sets the I-cache + * + * Enables cache and sets the direct access. + */ +static ALWAYS_INLINE void _icache_setup(void) +{ + uint32_t icache_config = ( + CACHE_DIRECT | /* direct mapping (one-way assoc.) */ + CACHE_ENABLE /* i-cache enabled */ + ); + _arc_v2_aux_reg_write(_ARC_V2_IC_CTRL, icache_config); +} + +#endif /* _ASMLANGUAGE */ +#endif /* _ARCV2_CACHE__H_ */ diff --git a/arch/arc/include/v2/irq.h b/arch/arc/include/v2/irq.h new file mode 100644 index 00000000000..f3d6560480d --- /dev/null +++ b/arch/arc/include/v2/irq.h @@ -0,0 +1,77 @@ +/* irq.h - interrupt helper functions (ARC) */ + +/* + * Copyright (c) 2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* + * DESCRIPTION + * This file contains private nanokernel structures definitions and various + * other definitions for the ARCv2 processor architecture. + */ + +#ifndef _ARCV2_IRQ__H_ +#define _ARCV2_IRQ__H_ + +#define _ARC_V2_AUX_IRQ_CTRL_BLINK (1 << 9) +#define _ARC_V2_AUX_IRQ_CTRL_LOOP_REGS (1 << 10) +#define _ARC_V2_AUX_IRQ_CTRL_14_REGS 7 +#define _ARC_V2_AUX_IRQ_CTRL_16_REGS 8 +#define _ARC_V2_AUX_IRQ_CTRL_32_REGS 16 + +#define _ARC_V2_DEF_IRQ_LEVEL 15 +#define _ARC_V2_WAKE_IRQ_LEVEL 15 + +#ifndef _ASMLANGUAGE + +extern void _firq_stack_setup(void); +extern char _InterruptStack[]; + +/* + * _irq_setup + * + * Configures interrupt handling parameters + */ +static ALWAYS_INLINE void _irq_setup(void) +{ + uint32_t aux_irq_ctrl_value = ( + _ARC_V2_AUX_IRQ_CTRL_LOOP_REGS | /* save lp_xxx registers */ + _ARC_V2_AUX_IRQ_CTRL_BLINK | /* save blink */ + _ARC_V2_AUX_IRQ_CTRL_14_REGS /* save r0 -> r13 (caller-saved) */ + ); + + nano_cpu_sleep_mode = _ARC_V2_WAKE_IRQ_LEVEL; + _arc_v2_aux_reg_write(_ARC_V2_AUX_IRQ_CTRL, aux_irq_ctrl_value); + + _NanoKernel.rirq_sp = _InterruptStack + CONFIG_ISR_STACK_SIZE; + _firq_stack_setup(); +} + +#endif /* _ASMLANGUAGE */ +#endif /* _ARCV2_IRQ__H_ */ diff --git a/arch/arc/interrupt_controller/arcv2_irq_unit.c b/arch/arc/interrupt_controller/arcv2_irq_unit.c new file mode 100644 index 00000000000..c49c8d22469 --- /dev/null +++ b/arch/arc/interrupt_controller/arcv2_irq_unit.c @@ -0,0 +1,103 @@ +/* arcv2_irq_unit.c - ARCv2 Interrupt Unit device driver */ + +/* + * Copyright (c) 2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* + * DESCRIPTION + * The ARCv2 interrupt unit has 16 allocated exceptions associated with + * vectors 0 to 15 and 240 interrupts associated with vectors 16 to 255. + * The interrupt unit is optional in the ARCv2-based processors. When + * building a processor, you can configure the processor to include an + * interrupt unit. The ARCv2 interrupt unit is highly programmable. + */ + +#include +#include +#include + +/* + * _arc_v2_irq_unit_init - initialize the interrupt unit device driver + * + * Initializes the interrupt unit device driver and the device + * itself. + * + * Interrupts are still locked at this point, so there is no need to protect + * the window between a write to IRQ_SELECT and subsequent writes to the + * selected IRQ's registers. + * + * RETURNS: N/A + */ + +void _arc_v2_irq_unit_init(void) +{ + int irq; /* the interrupt index */ + + for (irq = 16; irq < 256; irq++) { + _arc_v2_aux_reg_write(_ARC_V2_IRQ_SELECT, irq); + _arc_v2_aux_reg_write(_ARC_V2_IRQ_PRIORITY, 1); + _arc_v2_aux_reg_write(_ARC_V2_IRQ_ENABLE, _ARC_V2_INT_DISABLE); + _arc_v2_aux_reg_write(_ARC_V2_IRQ_TRIGGER, _ARC_V2_INT_LEVEL); + } +} + +/* + * _arc_v2_irq_unit_int_eoi - send EOI signal to interrupt unit + * + * This routine sends an EOI (End Of Interrupt) signal to the interrupt unit + * to clear a pulse-triggered interrupt. + * + * Interrupts must be locked or the ISR operating at P0 when invoking this + * function. + * + * RETURNS: N/A + */ + +void _arc_v2_irq_unit_int_eoi(int irq) +{ + _arc_v2_aux_reg_write(_ARC_V2_IRQ_SELECT, irq); + _arc_v2_aux_reg_write(_ARC_V2_IRQ_PULSE_CANCEL, 1); +} + +/* + * _arc_v2_irq_unit_int_trigger_set - sets an IRQ line to level/pulse trigger + * + * Sets the IRQ line to trigger an interrupt based on the level or the + * edge of the signal. Valid values for are _ARC_V2_INT_LEVEL and + * _ARC_V2_INT_PULSE. + * + * RETURNS: N/A + */ + +void _arc_v2_irq_unit_trigger_set(int irq, unsigned int trigger) +{ + _arc_v2_aux_reg_write(_ARC_V2_IRQ_SELECT, irq); + _arc_v2_aux_reg_write(_ARC_V2_IRQ_TRIGGER, trigger); +} diff --git a/arch/arc/serial/nsim_uart.c b/arch/arc/serial/nsim_uart.c new file mode 100644 index 00000000000..98bfbc1250c --- /dev/null +++ b/arch/arc/serial/nsim_uart.c @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2014-2015, Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#define NSIM_UART_DATA 0 +#define NSIM_UART_STATUS 1 + +#define DATA_REG(n) (uart[n].regs + NSIM_UART_DATA) +#define STATUS_REG(n) (uart[n].regs + NSIM_UART_STATUS) + +#define TXEMPTY 0x80 /* Transmit FIFO empty and next character can be sent */ + +struct uart { + uint32_t regs; /* MM base address */ +}; + +static struct uart __noinit uart[CONFIG_UART_NUM_SYSTEM_PORTS]; + +/* + * uart_init - initialize fake serial port + * @which: port number + * @init_info: pointer to initialization information + */ +void uart_init(int which, const struct uart_init_info * const init_info) +{ + int key = irq_lock(); + + uart[which].regs = init_info->regs; + irq_unlock(key); +} + +/* + * uart_poll_out - output a character to serial port + * @port: port number + * @c: character to output + */ +unsigned char uart_poll_out(int port, unsigned char c) +{ + + /* wait for transmitter to ready to accept a character */ + while ((_arc_v2_aux_reg_read(STATUS_REG(port)) & TXEMPTY) == 0) + ; + _arc_v2_aux_reg_write(DATA_REG(port), c); + return c; +} diff --git a/arch/arc/timer/arcv2_timer0.c b/arch/arc/timer/arcv2_timer0.c new file mode 100644 index 00000000000..d16376488af --- /dev/null +++ b/arch/arc/timer/arcv2_timer0.c @@ -0,0 +1,247 @@ +/* arcv2_timer0.c - ARC timer 0 device driver */ + +/* + * Copyright (c) 2014-2015 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This module implements a VxMicro device driver for the ARCv2 processor timer 0 +and provides the standard "system clock driver" interfaces. + +\INTERNAL IMPLEMENTATION DETAILS +The ARCv2 processor timer provides a 32-bit incrementing, wrap-to-zero counter. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * A board support package's board.h header must provide definitions for the + * following constants: + * + * CONFIG_ARCV2_TIMER0_CLOCK_FREQ + * + * This is the sysTick input clock frequency. + */ + +#include + +#define _ARC_V2_TMR_CTRL_IE 0x1 /* interrupt enable */ +#define _ARC_V2_TMR_CTRL_NH 0x2 /* count only while not halted */ +#define _ARC_V2_TMR_CTRL_W 0x4 /* watchdog mode enable */ +#define _ARC_V2_TMR_CTRL_IP 0x8 /* interrupt pending flag */ + +/* running total of timer count */ +static uint32_t accumulatedCount = 0; + + +/******************************************************************************* +* +* enable - enable the timer with the given limit/countup value +* +* This routine sets up the timer for operation by: +* - setting value to which the timer will count up to; +* - setting the timer's start value to zero; and +* - enabling interrupt generation. +* +* RETURNS: N/A +* +* \NOMANUAL +*/ + +static ALWAYS_INLINE void enable( + uint32_t count /* interrupt triggers when up-counter reaches this value */ +) +{ + _arc_v2_aux_reg_write(_ARC_V2_TMR0_LIMIT, count); /* write limit value */ + + /* count only when not halted for debug and enable interrupts */ + _arc_v2_aux_reg_write(_ARC_V2_TMR0_CONTROL, + _ARC_V2_TMR_CTRL_NH | _ARC_V2_TMR_CTRL_IE); + + _arc_v2_aux_reg_write(_ARC_V2_TMR0_COUNT, 0); /* write the start value */ +} + +/******************************************************************************* +* +* count_get - get the current counter value +* +* This routine gets the value from the timer's count register. This +* value is the 'time' elapsed from the starting count (assumed to be 0). +* +* RETURNS: the current counter value +* +* \NOMANUAL +*/ +static ALWAYS_INLINE uint32_t count_get(void) +{ + return _arc_v2_aux_reg_read(_ARC_V2_TMR0_COUNT); +} + +/******************************************************************************* +* +* limit_get - get the limit/countup value +* +* This routine gets the value from the timer's limit register, which is the +* value to which the timer will count up to. +* +* RETURNS: the limit value +* +* \NOMANUAL +*/ +static ALWAYS_INLINE uint32_t limit_get(void) +{ + return _arc_v2_aux_reg_read(_ARC_V2_TMR0_LIMIT); +} + +/******************************************************************************* +* +* _timer_int_handler - system clock periodic tick handler +* +* This routine handles the system clock periodic tick interrupt. A TICK_EVENT +* event is pushed onto the microkernel stack. +* +* RETURNS: N/A +* +* \NOMANUAL +*/ + +void _timer_int_handler(void *unused) +{ + uint32_t zero_ip_bit = _ARC_V2_TMR_CTRL_NH | _ARC_V2_TMR_CTRL_IE; + + ARG_UNUSED(unused); + + /* clear the interrupt by writing 0 to IP bit of the control register */ + _arc_v2_aux_reg_write(_ARC_V2_TMR0_CONTROL, zero_ip_bit); + + accumulatedCount += sys_clock_hw_cycles_per_tick; + + nanoTicks++; + + if (nanoTimerList) { + nanoTimerList->ticks--; + + while (nanoTimerList && (!nanoTimerList->ticks)) { + struct nano_timer *expired = nanoTimerList; + struct nano_lifo *lifo = &expired->lifo; + + nanoTimerList = expired->link; + nano_fiber_lifo_put(lifo, expired->userData); + } + } +} + +/******************************************************************************* +* +* timer_driver - initialize and enable the system clock +* +* This routine is used to program the ARCv2 timer to deliver interrupts at the +* rate specified via the 'sys_clock_us_per_tick' global variable. +* +* RETURNS: N/A +*/ + +void timer_driver( + int priority /* priority parameter ignored by this driver */ +) +{ + int irq = CONFIG_ARCV2_TIMER0_INT_LVL; + int prio = CONFIG_ARCV2_TIMER0_INT_PRI; + + ARG_UNUSED(priority); + + /* ensure that the timer will not generate interrupts */ + _arc_v2_aux_reg_write(_ARC_V2_TMR0_CONTROL, 0); + _arc_v2_aux_reg_write(_ARC_V2_TMR0_COUNT, 0); /* clear the count value */ + + (void)irq_connect(irq, prio, _timer_int_handler, 0); + + /* + * Set the reload value to achieve the configured tick rate, enable the + * counter and interrupt generation. + */ + + enable(sys_clock_hw_cycles_per_tick - 1); + + /* everything has been configured: safe to enable the interrupt */ + irq_enable(CONFIG_ARCV2_TIMER0_INT_LVL); +} + +/******************************************************************************* +* +* timer_read - read the BSP timer hardware +* +* This routine returns the current time in terms of timer hardware clock cycles. +* +* RETURNS: up counter of elapsed clock cycles +*/ + +uint32_t timer_read(void) +{ + return (accumulatedCount + count_get()); +} + +#if defined(CONFIG_SYSTEM_TIMER_DISABLE) +/******************************************************************************* +* +* timer_disable - stop announcing ticks into the kernel +* +* This routine disables timer interrupt generation and delivery. +* Note that the timer's counting cannot be stopped by software. +* +* RETURNS: N/A +*/ + +void timer_disable(void) +{ + unsigned int key; /* interrupt lock level */ + uint32_t ctrl_val; /* timer control register value */ + + key = irq_lock(); + + /* disable interrupt generation */ + + ctrl_val = _arc_v2_aux_reg_read(_ARC_V2_TMR0_CONTROL); + _arc_v2_aux_reg_write(_ARC_V2_TMR0_CONTROL, ctrl_val & ~_ARC_V2_TMR_CTRL_IE); + + irq_unlock(key); + + /* disable interrupt in the interrupt controller */ + + irq_disable(CONFIG_ARCV2_TIMER0_INT_LVL); +} +#endif /* CONFIG_SYSTEM_TIMER_DISABLE */ diff --git a/arch/arm/bsp/CortexM/nmi.c b/arch/arm/bsp/CortexM/nmi.c new file mode 100644 index 00000000000..80f44d71707 --- /dev/null +++ b/arch/arm/bsp/CortexM/nmi.c @@ -0,0 +1,117 @@ +/* nmi.c - NMI handler infrastructure */ + +/* + * Copyright (c) 2013-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +Provides a boot time handler that simply hangs in a sleep loop, and a run time +handler that resets the CPU. Also provides a mechanism for hooking a custom +run time handler. +*/ + +#include +#include +#include +#include +#include + +extern void _SysNmiOnReset(void); +#if !defined(CONFIG_RUNTIME_NMI) +#define handler _SysNmiOnReset +#endif + +#ifdef CONFIG_RUNTIME_NMI +typedef void (*_NmiHandler_t)(void); +static handler = _SysNmiOnReset; + +/******************************************************************************* +* +* _DefaultHandler - default NMI handler installed when kernel is up +* +* The default handler outputs a error message and reboots the target. It is +* installed by calling _NmiInit(); +* +* RETURNS: N/A +*/ + +static void _DefaultHandler(void) +{ + printk("NMI received! Rebooting...\n"); + _ScbSystemReset(); +} + +/******************************************************************************* +* +* _NmiInit - install default runtime NMI handler +* +* Meant to be called by BSP code if they want to install a simple NMI handler +* that reboots the target. It should be installed after the console is +* initialized. +* +* RETURNS: N/A +*/ + +void _NmiInit(void) +{ + handler = _DefaultHandler; +} + +/******************************************************************************* +* +* _NmiHandlerSet - install a custom runtime NMI handler +* +* Meant to be called by BSP code if they want to install a custom NMI handler +* that reboots. It should be installed after the console is initialized if it is +* meant to output to the console. +* +* RETURNS: N/A +*/ + +void _NmiHandlerSet(void (*pHandler)(void)) +{ + handler = pHandler; +} +#endif /* CONFIG_RUNTIME_NMI */ + +/******************************************************************************* +* +* __nmi - handler installed in the vector table +* +* Simply call what is installed in 'static void(*handler)(void)'. +* +* RETURNS: N/A +*/ + +void __nmi(void) +{ + handler(); + _ExcExit(); +} diff --git a/arch/arm/bsp/CortexM/prep_c.c b/arch/arm/bsp/CortexM/prep_c.c new file mode 100644 index 00000000000..1ceec3800bf --- /dev/null +++ b/arch/arm/bsp/CortexM/prep_c.c @@ -0,0 +1,108 @@ +/* prep_c.c - full C support initialization */ + +/* + * Copyright (c) 2013-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION + +Initialization of full C support: zero the .bss, copy the .data if XIP, +call _Cstart(). + +Stack is available in this module, but not the global data/bss until their +initialization is performed. +*/ + +#include +#include +#include + +/******************************************************************************* +* +* bssZero - clear BSS +* +* This routine clears the BSS region, so all bytes are 0. +* +* RETURNS: N/A +*/ + +static void bssZero(void) +{ + volatile uint32_t *pBSS = (uint32_t *)&__bss_start; + unsigned int n; + + for (n = 0; n < (unsigned int)&__bss_num_words; n++) { + pBSS[n] = 0; + } +} + +/******************************************************************************* +* +* dataCopy - copy the data section from ROM to RAM +* +* This routine copies the data section from ROM to RAM. +* +* RETURNS: N/A +*/ + +#ifdef CONFIG_XIP +static void dataCopy(void) +{ + volatile uint32_t *pROM = (uint32_t *)&__data_rom_start; + volatile uint32_t *pRAM = (uint32_t *)&__data_ram_start; + unsigned int n; + + for (n = 0; n < (unsigned int)&__data_num_words; n++) { + pRAM[n] = pROM[n]; + } +} +#else +static void dataCopy(void) +{ +} +#endif + +extern FUNC_NORETURN void _Cstart(void); +/******************************************************************************* +* +* _PrepC - prepare to and run C code +* +* This routine prepares for the execution of and runs C code. +* +* RETURNS: N/A +*/ + +void _PrepC(void) +{ + bssZero(); + dataCopy(); + _Cstart(); + CODE_UNREACHABLE; +} diff --git a/arch/arm/bsp/CortexM/reset.s b/arch/arm/bsp/CortexM/reset.s new file mode 100644 index 00000000000..919f7a0fed5 --- /dev/null +++ b/arch/arm/bsp/CortexM/reset.s @@ -0,0 +1,93 @@ +/* reset_s.s - reset handler */ + +/* + * Copyright (c) 2013-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +Reset handler that prepares the system for running C code. +*/ + +#define _ASMLANGUAGE + +#include +#include +#include +#include +#include "vector_table.h" + +_ASM_FILE_PROLOGUE + +GTEXT(__reset) + +/******************************************************************************* +* +* __reset - reset vector +* +* Ran when the system comes out of reset. The processor is in thread mode with +* privileged level. At this point, the main stack pointer (MSP) is already +* pointing to a valid area in SRAM. +* +* Locking interrupts prevents anything but NMIs and hard faults from +* interrupting the CPU. A default NMI handler is already in place in the +* vector table, and the boot code should not generate hard fault, or we're in +* deep trouble. +* +* We want to use the process stack pointer (PSP) instead of the MSP, since the +* MSP is to be set up to point to the one-and-only interrupt stack during later +* boot. That would not be possible if in use for running C code. +* +* When these steps are completed, jump to _PrepC(), which will finish setting +* up the system for running C code. +* +* RETURNS: N/A +*/ + +SECTION_FUNC(TEXT,__reset) + + /* lock interrupts: will get unlocked when switch to main task */ + movs.n r0, #_EXC_IRQ_DEFAULT_PRIO + msr BASEPRI, r0 + + /* + * Set PSP and use it to boot without using MSP, so that it + * gets set to _InterruptStack during nanoInit(). + */ + ldr r0, =__CORTEXM_BOOT_PSP + msr PSP, r0 + movs.n r0, #2 /* switch to using PSP (bit1 of CONTROL reg) */ + msr CONTROL, r0 + +#ifdef CONFIG_WDOG_INIT + /* board-specific watchdog initialization is necessary */ + bl _WdogInit +#endif + + b _PrepC diff --git a/arch/arm/bsp/CortexM/scb.c b/arch/arm/bsp/CortexM/scb.c new file mode 100644 index 00000000000..5792a74410b --- /dev/null +++ b/arch/arm/bsp/CortexM/scb.c @@ -0,0 +1,109 @@ +/* scb.h - ARM CORTEX-M3 System Control Block interface */ + +/* + * Copyright (c) 2013-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION + +Most of the SCB interface consists of simple bit-flipping methods, and is +implemented as inline functions in scb.h. This module thus contains only data +definitions and more complex routines, if needed. +*/ + +#include +#include +#include + +#define SCB_AIRCR_VECTKEY_EN_W 0x05FA + +/******************************************************************************* +* +* _ScbSystemReset - reset the system +* +* This routine resets the processor. +* +* RETURNS: N/A +*/ + +void _ScbSystemReset(void) +{ + union __aircr reg; + + reg.val = __scs.scb.aircr.val; + reg.bit.vectkey = SCB_AIRCR_VECTKEY_EN_W; + reg.bit.sysresetreq = 1; + __scs.scb.aircr.val = reg.val; +} + +/******************************************************************************* +* +* _ScbNumPriGroupSet - set the number of priority groups based on the number +* of exception priorities desired +* +* Exception priorities can be divided in priority groups, inside which there is +* no preemption. The priorities inside a group are only used to decide which +* exception will run when more than one is ready to be handled. +* +* The number of priorities has to be a power of two, from 1 to 128. +* +* RETURNS: N/A +*/ + +void _ScbNumPriGroupSet(unsigned int n /* number of priorities */ + ) +{ + unsigned int set; + union __aircr reg; + + __ASSERT(_IsPowerOfTwo(n) && (n <= 128), + "invalid number of priorities"); + + set = find_first_set(n); + + reg.val = __scs.scb.aircr.val; + + /* num pri bit set prigroup + * --------------------------------- + * 1 1 7 + * 2 2 6 + * 4 3 5 + * 8 4 4 + * 16 5 3 + * 32 6 2 + * 64 7 1 + * 128 8 0 + */ + + reg.bit.prigroup = 8 - set; + reg.bit.vectkey = SCB_AIRCR_VECTKEY_EN_W; + + __scs.scb.aircr.val = reg.val; +} diff --git a/arch/arm/bsp/CortexM/scs.c b/arch/arm/bsp/CortexM/scs.c new file mode 100644 index 00000000000..0369155ff19 --- /dev/null +++ b/arch/arm/bsp/CortexM/scs.c @@ -0,0 +1,46 @@ +/* scs.c - ARM CORTEX-M Series System Control Space */ + +/* + * Copyright (c) 2013-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +Most of the SCS interface consists of simple bit-flipping methods, and is +implemented as inline functions in scs.h. This module thus contains only data +definitions and more complex routines, if needed. +*/ + +#include +#include +#include +#include + +/* the linker always puts this object at 0xe000e000 */ +volatile struct __scs __scs_section __scs; diff --git a/arch/arm/bsp/CortexM/vector_table.h b/arch/arm/bsp/CortexM/vector_table.h new file mode 100644 index 00000000000..8319cf41b1c --- /dev/null +++ b/arch/arm/bsp/CortexM/vector_table.h @@ -0,0 +1,78 @@ +/* vector_table.h - definitions for the boot vector table */ + +/* + * Copyright (c) 2013-2015 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION + +Definitions for the boot vector table. + +System exception handler names all have the same format: + + __ + +No other symbol has the same format, so they are easy to spot. +*/ + +#ifndef _VECTOR_TABLE__H_ +#define _VECTOR_TABLE__H_ + +#ifdef _ASMLANGUAGE + +#include +#include +#include + +/* location of MSP and PSP upon boot: at the end of SRAM */ +.equ __CORTEXM_BOOT_MSP, (0x20000000 + SRAM_SIZE - 8) +.equ __CORTEXM_BOOT_PSP, (__CORTEXM_BOOT_MSP - 0x100) + +GTEXT(__start) +GTEXT(_VxMicroStart) +GTEXT(_VectorTableROM) + +GTEXT(__reset) +GTEXT(__nmi) +GTEXT(__hard_fault) +GTEXT(__mpu_fault) +GTEXT(__bus_fault) +GTEXT(__usage_fault) +GTEXT(__svc) +GTEXT(__debug_monitor) +GTEXT(__pendsv) +GTEXT(__reserved) + +GTEXT(_PrepC) +GTEXT(_IsrWrapper) + +#endif /* _ASMLANGUAGE */ + +#endif /* _VECTOR_TABLE__H_ */ diff --git a/arch/arm/bsp/CortexM/vector_table.s b/arch/arm/bsp/CortexM/vector_table.s new file mode 100644 index 00000000000..0c439bfa01b --- /dev/null +++ b/arch/arm/bsp/CortexM/vector_table.s @@ -0,0 +1,74 @@ +/* vector_table.s - populated vector table in ROM */ + +/* + * Copyright (c) 2013-2015 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +Vector table in ROM for starting system. The reset vector is the system entry +point, ie. the first instruction executed. + +The table is populated with all the system exception handlers. The NMI vector +must be populated with a valid handler since it can happen at any time. The +rest should not be triggered until the kernel is ready to handle them. +*/ + +#define _ASMLANGUAGE + +#include +#include +#include +#include +#include "vector_table.h" + +_ASM_FILE_PROLOGUE + +/* Diab requires a __start symbol */ +SECTION_SUBSEC_FUNC(exc_vector_table,_Start,__start) +SECTION_SUBSEC_FUNC(exc_vector_table,_Start,_VxMicroStart) +SECTION_SUBSEC_FUNC(exc_vector_table,_Start,_VectorTableROM) + + .word __CORTEXM_BOOT_MSP + .word __reset + .word __nmi + + .word __hard_fault + .word __mpu_fault + .word __bus_fault + .word __usage_fault + .word __reserved + .word __reserved + .word __reserved + .word __reserved + .word __svc + .word __debug_monitor + .word __reserved + .word __pendsv + .word _timer_int_handler diff --git a/arch/arm/bsp/rand32.c b/arch/arm/bsp/rand32.c new file mode 100644 index 00000000000..ee2ca906bff --- /dev/null +++ b/arch/arm/bsp/rand32.c @@ -0,0 +1,78 @@ +/* rand32.c - random number generator */ + +/* + * Copyright (c) 2013-2015 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This module provides a non-random implementation of _Rand32Get(), which is not +meant to be used in a final product as a truly random number generator. It +was provided to allow testing of kernel stack canaries on a BSP that does not +(yet) provide a random number generator. +*/ + +#include +#include + +#if defined(CONFIG_TEST_RANDOM_GENERATOR) +#if defined(__GNUC__) + +/******************************************************************************* + * + * _Rand32Init - initialize the random number generator + * + * The non-random number generator does not require any initialization. + * + * RETURNS: N/A + */ + + +void _Rand32Init(void) +{ +} + +/******************************************************************************* + * + * _Rand32Get - get a 32 bit random number + * + * The non-random number generator returns values that are based off the + * target's clock counter, which means that successive calls will normally + * display ever-increasing values. + * + * RETURNS: a 32-bit number + */ + +uint32_t _Rand32Get(void) +{ + return timer_read(); +} + +#endif /* __GNUC__ */ +#endif /* CONFIG_TEST_RANDOM_GENERATOR */ diff --git a/arch/arm/bsp/sysFatalErrorHandler.c b/arch/arm/bsp/sysFatalErrorHandler.c new file mode 100644 index 00000000000..68bb5bf0fc5 --- /dev/null +++ b/arch/arm/bsp/sysFatalErrorHandler.c @@ -0,0 +1,115 @@ +/* sysFatalErrorHandler - ARM Cortex-M system fatal error handler */ + +/* + * Copyright (c) 2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This module provides the _SysFatalErrorHandler() routine for Cortex-M BSPs. +*/ + +/* includes */ + +#include +#include +#include +#include +#include +#include "board.h" + +#ifdef CONFIG_PRINTK +#include +#define PRINTK(...) printk(__VA_ARGS__) +#else +#define PRINTK(...) +#endif + +#ifdef CONFIG_MICROKERNEL +extern void _TaskAbort(void); +static inline void nonEssentialTaskAbort(void) +{ + PRINTK("Fatal fault in task ! Aborting task.\n"); + _TaskAbort(); +} +#define NON_ESSENTIAL_TASK_ABORT() nonEssentialTaskAbort() +#else +#define NON_ESSENTIAL_TASK_ABORT() \ + do {/* nothing */ \ + } while ((0)) +#endif + +/******************************************************************************* +* +* _SysFatalErrorHandler - fatal error handler +* +* This routine implements the corrective action to be taken when the system +* detects a fatal error. +* +* This sample implementation attempts to abort the current context and allow +* the system to continue executing, which may permit the system to continue +* functioning with degraded capabilities. +* +* System designers may wish to enhance or substitute this sample +* implementation to take other actions, such as logging error (or debug) +* information to a persistent repository and/or rebooting the system. +* +* RETURNS: N/A +* +* \NOMANUAL +*/ + +void _SysFatalErrorHandler( + unsigned int reason, /* fatal error reason */ + const NANO_ESF * pEsf /* pointer to exception stack frame */ + ) +{ + nano_context_type_t curCtx = context_type_get(); + + ARG_UNUSED(reason); + ARG_UNUSED(pEsf); + + if ((curCtx == NANO_CTX_ISR) || _context_essential_check(NULL)) { + PRINTK("Fatal fault in %s ! Spinning...\n", + NANO_CTX_ISR == curCtx + ? "ISR" + : NANO_CTX_FIBER == curCtx ? "essential fiber" + : "essential task"); + for (;;) + ; /* spin forever */ + } + + if (NANO_CTX_FIBER == curCtx) { + PRINTK("Fatal fault in fiber ! Aborting fiber.\n"); + fiber_abort(); + return; + } + + NON_ESSENTIAL_TASK_ABORT(); +} diff --git a/arch/arm/core/atomic.s b/arch/arm/core/atomic.s new file mode 100644 index 00000000000..912b095b721 --- /dev/null +++ b/arch/arm/core/atomic.s @@ -0,0 +1,429 @@ +/* armAtomic.s - ARM atomic operations library */ + +/* + * Copyright (c) 2013-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This library provides routines to perform a number of atomic operations +on a memory location: add, subtract, increment, decrement, bitwise OR, +bitwise NOR, bitwise AND, bitwise NAND, set, clear and compare-and-swap. +*/ + +#define _ASMLANGUAGE + +#include +#include + +_ASM_FILE_PROLOGUE + +/* exports */ + +GTEXT(atomic_set) +GTEXT(atomic_get) +GTEXT(atomic_add) +GTEXT(atomic_nand) +GTEXT(atomic_and) +GTEXT(atomic_or) +GTEXT(atomic_xor) +GTEXT(atomic_clear) +GTEXT(atomic_dec) +GTEXT(atomic_inc) +GTEXT(atomic_sub) +GTEXT(atomic_cas) + +/******************************************************************************* +* +* atomic_clear - atomically clear a memory location +* +* This routine atomically clears the contents of and returns the old +* value that was in . +* +* This routine can be used from both task and interrupt level. +* +* RETURNS: Contents of before the atomic operation +* +* ERRNO: N/A +* +* atomic_val_t atomic_clear +* ( +* atomic_t *target /@ memory location to clear @/ +* ) +*/ + +SECTION_SUBSEC_FUNC(TEXT, atomic_clear_set, atomic_clear) + MOV r1, #0 + /* fall through into atomic_set */ + +/******************************************************************************* +* +* atomic_set - atomically set a memory location +* +* This routine atomically sets the contents of to and returns +* the old value that was in . +* +* This routine can be used from both task and interrupt level. +* +* RETURNS: Contents of before the atomic operation +* +* ERRNO: N/A +* +* atomic_val_t atomic_set +* ( +* atomic_t *target, /@ memory location to set @/ +* atomic_val_t value /@ set with this value @/ +* ) +* +*/ + +SECTION_SUBSEC_FUNC(TEXT, atomic_clear_set, atomic_set) + + LDREX r2, [r0] /* load old value and mark exclusive access */ + STREX r12, r1, [r0] /* try to store new value */ + TEQ r12, #0 /* store successful? */ + + BNE atomic_set /* if not, retry */ + + MOV r0, r2 /* return old value */ + MOV pc, lr + +/****************************************************************************** +* +* atomic_get - Get the value of a shared memory atomically +* +* This routine atomically retrieves the value in *target +* +* long atomic_get +* ( +* atomic_t * target /@ address of atom to be retrieved @/ +* ) +* +* RETURN: value read from address target. +* +*/ + +SECTION_FUNC(TEXT, atomic_get) + LDR r0, [r0] + MOV pc, lr + +/******************************************************************************* +* +* atomic_inc - atomically increment a memory location +* +* This routine atomically increments the value in . The operation is +* done using unsigned integer arithmetic. Various CPU architectures may impose +* restrictions with regards to the alignment and cache attributes of the +* atomic_t type. +* +* This routine can be used from both task and interrupt level. +* +* RETURNS: Contents of before the atomic operation +* +* ERRNO: N/A +* +* atomic_val_t atomic_inc +* ( +* atomic_t *target, /@ memory location to increment @/ +* ) +* +*/ + +SECTION_SUBSEC_FUNC(TEXT, atomic_inc_add, atomic_inc) + MOV r1, #1 + /* fall through into atomic_add */ + +/******************************************************************************* +* +* atomic_add - atomically add a value to a memory location +* +* This routine atomically adds the contents of and , placing +* the result in . The operation is done using signed integer arithmetic. +* Various CPU architectures may impose restrictions with regards to the +* alignment and cache attributes of the atomic_t type. +* +* This routine can be used from both task and interrupt level. +* +* RETURNS: Contents of before the atomic operation +* +* ERRNO: N/A +* +* atomic_val_t atomic_add +* ( +* atomic_t *target, /@ memory location to add to @/ +* atomic_val_t value /@ value to add @/ +* ) +*/ + +SECTION_SUBSEC_FUNC(TEXT, atomic_inc_add, atomic_add) + + LDREX r2, [r0] /* load old value and mark exclusive access */ + ADD r3, r2, r1 /* add word */ + STREX r12, r3, [r0] /* try to store new value */ + TEQ r12, #0 /* store successful? */ + + BNE atomic_add /* if not, retry */ + + MOV r0, r2 /* return old value */ + MOV pc, lr + +/******************************************************************************* +* +* atomic_dec - atomically decrement a memory location +* +* This routine atomically decrements the value in . The operation is +* done using unsigned integer arithmetic. Various CPU architectures may impose +* restrictions with regards to the alignment and cache attributes of the +* atomic_t type. +* +* This routine can be used from both task and interrupt level. +* +* RETURNS: Contents of before the atomic operation +* +* ERRNO: N/A +* +* atomic_val_t atomic_dec +* ( +* atomic_t *target, /@ memory location to decrement @/ +* ) +* +*/ + +SECTION_SUBSEC_FUNC(TEXT, atomic_decSub, atomic_dec) + MOV r1, #1 + /* fall through into atomic_sub */ + +/******************************************************************************* +* +* atomic_sub - atomically subtract a value from a memory location +* +* This routine atomically subtracts from the contents of , +* placing the result in . The operation is done using signed integer +* arithmetic. Various CPU architectures may impose restrictions with regards to +* the alignment and cache attributes of the atomic_t type. +* +* This routine can be used from both task and interrupt level. +* +* RETURNS: Contents of before the atomic operation +* +* ERRNO: N/A +* +* atomic_val_t atomic_sub +* ( +* atomic_t *target, /@ memory location to subtract from @/ +* atomic_val_t value /@ value to subtract @/ +* ) +* +*/ + +SECTION_SUBSEC_FUNC(TEXT, atomic_decSub, atomic_sub) + + LDREX r2, [r0] /* load old value and mark exclusive access */ + SUB r3, r2, r1 /* subtract word */ + STREX r12, r3, [r0] /* try to store new value */ + TEQ r12, #0 /* store successful? */ + BNE atomic_sub /* if not, retry */ + + MOV r0, r2 /* return old value */ + MOV pc, lr + +/****************************************************************************** +* +* atomic_nand - atomically perform a bitwise NAND on a memory location +* +* This routine atomically performs a bitwise NAND operation of the contents of +* and , placing the result in . +* Various CPU architectures may impose restrictions with regards to the +* alignment and cache attributes of the atomic_t type. +* +* This routine can be used from both task and interrupt level. +* +* RETURNS: Contents of before the atomic operation +* +* ERRNO: N/A +* +* atomic_val_t atomic_nand +* ( +* atomic_t *target, /@ memory location to NAND @/ +* atomic_val_t value /@ NAND with this value @/ +* ) +* +*/ + +SECTION_FUNC(TEXT, atomic_nand) + + LDREX r2, [r0] /* load old value and mark exclusive access */ + AND r3, r2, r1 /* AND word */ + MVN r3, r3 /* invert */ + STREX r12, r3, [r0] /* try to store new value */ + TEQ r12, #0 /* store successful? */ + BNE atomic_nand /* if not, retry */ + + MOV r0, r2 /* return old value */ + MOV pc, lr + +/****************************************************************************** +* +* atomic_and - atomically perform a bitwise AND on a memory location +* +* This routine atomically performs a bitwise AND operation of the contents of +* and , placing the result in . +* Various CPU architectures may impose restrictions with regards to the +* alignment and cache attributes of the atomic_t type. +* +* This routine can be used from both task and interrupt level. +* +* RETURNS: Contents of before the atomic operation +* +* ERRNO: N/A +* +* atomic_val_t atomic_and +* ( +* atomic_t *target, /@ memory location to AND @/ +* atomic_val_t value /@ AND with this value @/ +* ) +* +*/ + +SECTION_FUNC(TEXT, atomic_and) + + LDREX r2, [r0] /* load old value and mark exclusive access */ + AND r3, r2, r1 /* AND word */ + STREX r12, r3, [r0] /* try to store new value */ + TEQ r12, #0 /* store successful? */ + BNE atomic_and /* if not, retry */ + + MOV r0, r2 /* return old value */ + MOV pc, lr + +/******************************************************************************* +* +* atomic_or - atomically perform a bitwise OR on memory location +* +* This routine atomically performs a bitwise OR operation of the contents of +* and , placing the result in . +* Various CPU architectures may impose restrictions with regards to the +* alignment and cache attributes of the atomic_t type. +* +* This routine can be used from both task and interrupt level. +* +* RETURNS: Contents of before the atomic operation +* +* ERRNO: N/A +* +* atomic_val_t atomic_or +* ( +* atomic_t *target, /@ memory location to OR @/ +* atomic_val_t value /@ OR with this value @/ +* ) +* +*/ + +SECTION_FUNC(TEXT, atomic_or) + + LDREX r2, [r0] /* load old value and mark exclusive access */ + ORR r3, r2, r1 /* OR word */ + STREX r12, r3, [r0] /* try to store new value */ + TEQ r12, #0 /* store successful? */ + BNE atomic_or /* if not, retry */ + + MOV r0, r2 /* return old value */ + MOV pc, lr + +/******************************************************************************* +* +* atomic_xor - atomically perform a bitwise XOR on a memory location +* +* This routine atomically performs a bitwise XOR operation of the contents of +* and , placing the result in . +* Various CPU architectures may impose restrictions with regards to the +* alignment and cache attributes of the atomic_t type. +* +* This routine can be used from both task and interrupt level. +* +* RETURNS: Contents of before the atomic operation +* +* ERRNO: N/A +* +* atomic_val_t atomic_xor +* ( +* atomic_t *target, /@ memory location to XOR @/ +* atomic_val_t value /@ XOR with this value @/ +* ) +* +*/ + +SECTION_FUNC(TEXT, atomic_xor) + + LDREX r2, [r0] /* load old value and mark exclusive access */ + EOR r3, r2, r1 /* XOR word */ + STREX r12, r3, [r0] /* try to store new value */ + TEQ r12, #0 /* store successful? */ + BNE atomic_xor /* if not, retry */ + + MOV r0, r2 /* return old value */ + MOV pc, lr + +/******************************************************************************* +* +* atomic_cas - atomically compare-and-swap the contents of a memory location +* +* This routine performs an atomic compare-and-swap. testing that the contents of +* contains , and if it does, setting the value of +* to . Various CPU architectures may impose restrictions with regards +* to the alignment and cache attributes of the atomic_t type. +* +* This routine can be used from both task and interrupt level. +* +* RETURNS: 1 if the swap is actually executed, 0 otherwise. +* +* ERRNO: N/A +* +* int atomic_cas +* ( +* atomic_t *target, /@ memory location to compare-and-swap @/ +* atomic_val_t oldValue, /@ compare to this value @/ +* atomic_val_t newValue, /@ swap with this value @/ +* ) +* +*/ + +SECTION_FUNC(TEXT, atomic_cas) + + LDREX r3, [r0] /* load the value and mark exclusive access */ + CMP r3, r1 /* if (*target != oldValue) */ + ITT NE + MOVNE r0, #0 /* return FALSE */ + MOVNE pc, lr + STREX r12, r2, [r0] /* try to store if equal */ + TEQ r12, #0 /* store successful? */ + BNE atomic_cas /* if not, retry */ + + MOV r0, #1 /* return TRUE if swap occurred */ + MOV pc, lr diff --git a/arch/arm/core/basepri.s b/arch/arm/core/basepri.s new file mode 100644 index 00000000000..2f07ed943f2 --- /dev/null +++ b/arch/arm/core/basepri.s @@ -0,0 +1,95 @@ +/* basepri.s - ARM Cortex-M interrupt locking via BASEPRI */ + +/* + * Copyright (c) 2013-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION + +Provide irq_lock() and irq_unlock() via the BASEPRI register. This +allows locking up to a certain interrupt priority. VxMicro locks out priorities +2 and lower (higher numbered priorities), in essence leaving priorities 0 and 1 +unlocked. This achieves two purposes: + +1. The service call exception is installed at priority 0, allowing it to be + invoked with interrupts locked. This is needed since 'svc #0' is the + implementation of _Swap(), which is invoked with interrupts locked in the + common implementation of nanokernel objects. + +2. Zero Interrupt Latency (ZLI) is achievable via this by allowing certain + interrupts to set their priority to 1, thus being allowed in when interrupts + are locked for regular interrupts. +*/ + +#define _ASMLANGUAGE + +#include +#include +#include + +_ASM_FILE_PROLOGUE + +GTEXT(irq_lock) +GTEXT(irq_unlock) + +/******************************************************************************* +* +* irq_lock - lock interrupts +* +* Prevent exceptions of priority lower than to the two highest priorities from +* interrupting the CPU. +* +* This function can be called recursively: it will return a key to return the +* state of interrupt locking to the previous level. +* +* RETURNS: a key to return to the previous interrupt locking level +*/ + +SECTION_FUNC(TEXT,irq_lock) + movs.n r1, #_EXC_IRQ_DEFAULT_PRIO + mrs r0, BASEPRI + msr BASEPRI, r1 + bx lr + +/******************************************************************************* +* +* irq_unlock - unlock interrupts +* +* Return the state of interrupt locking to a previous level, passed in via the +* parameter, obtained from a previous call to irq_lock(). +* +* RETURNS: N/A +*/ + +SECTION_FUNC(TEXT,irq_unlock) + msr BASEPRI, r0 + bx lr + + .end diff --git a/arch/arm/core/cpu_idle.s b/arch/arm/core/cpu_idle.s new file mode 100644 index 00000000000..e699d867731 --- /dev/null +++ b/arch/arm/core/cpu_idle.s @@ -0,0 +1,198 @@ +/* cpu_idle.s - ARM CORTEX-M3 power management */ + +/* + * Copyright (c) 2013-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +*/ + +#define _ASMLANGUAGE + +#include +#include +#include +#include +#ifdef CONFIG_TICKLESS_IDLE +#include +#endif + +_ASM_FILE_PROLOGUE + +GTEXT(_CpuIdleInit) +#ifdef CONFIG_ADVANCED_POWER_MANAGEMENT +GTEXT(_NanoIdleValGet) +GTEXT(_NanoIdleValClear) +#endif +GTEXT(nano_cpu_idle) +GTEXT(nano_cpu_atomic_idle) + +#define _SCR_INIT_BITS _SCB_SCR_SEVONPEND + +/******************************************************************************* +* +* _CpuIdleInit - initialization of CPU idle +* +* Only called by nanoArchInit(). Sets SEVONPEND bit once for the system's +* duration. +* +* RETURNS: N/A +* +* C function prototype: +* +* void _CpuIdleInit (void); +*/ + +SECTION_FUNC(TEXT, _CpuIdleInit) + ldr r1, =_SCB_SCR + movs.n r2, #_SCR_INIT_BITS + str r2, [r1] + bx lr + +#ifdef CONFIG_ADVANCED_POWER_MANAGEMENT + +/******************************************************************************* +* +* _NanoIdleValGet - get the kernel idle setting +* +* Returns the nanokernel idle setting, in ticks. Only called by __systick(). +* +* RETURNS: the requested number of ticks for the kernel to be idle +* +* C function prototype: +* +* int32_t _NanoIdleValGet (void); +*/ + +SECTION_FUNC(TEXT, _NanoIdleValGet) + ldr r0, =_NanoKernel + ldr r0, [r0, #__tNANO_idle_OFFSET] + bx lr + +/******************************************************************************* +* +* _NanoIdleValClear - clear the kernel idle setting +* +* Sets the nanokernel idle setting to 0. Only called by __systick(). +* +* RETURNS: N/A +* +* C function prototype: +* +* void _NanoIdleValClear (void); +*/ + +SECTION_FUNC(TEXT, _NanoIdleValClear) + ldr r0, =_NanoKernel + eors.n r1, r1 + str r1, [r0, #__tNANO_idle_OFFSET] + bx lr + +#endif /* CONFIG_ADVANCED_POWER_MANAGEMENT */ + +/******************************************************************************* +* +* nano_cpu_idle - power save idle routine for ARM Cortex-M +* +* This function will be called by the nanokernel idle loop or possibly within +* an implementation of _SysPowerSaveIdle in the microkernel when the +* '_SysPowerSaveFlag' variable is non-zero. The ARM 'wfi' instruction +* will be issued, causing a low-power consumption sleep mode. +* +* RETURNS: N/A +* +* C function prototype: +* +* void nano_cpu_idle (void); +*/ + +SECTION_FUNC(TEXT, nano_cpu_idle) + /* clear BASEPRI so wfi is awakened by incoming interrupts */ + eors.n r0, r0 + msr BASEPRI, r0 + + wfi + + bx lr + +/******************************************************************************* +* +* nano_cpu_atomic_idle - atomically re-enable interrupts and enter low power mode +* +* This function is utilized by the nanokernel object "wait" APIs for task +* contexts, e.g. nano_task_lifo_get_wait(), nano_task_sem_take_wait(), nano_task_stack_pop_wait(), +* and nano_task_fifo_get_wait(). +* +* INTERNAL +* The requirements for nano_cpu_atomic_idle() are as follows: +* 1) The enablement of interrupts and entering a low-power mode needs to be +* atomic, i.e. there should be no period of time where interrupts are +* enabled before the processor enters a low-power mode. See the comments +* in nano_task_lifo_get_wait(), for example, of the race condition that occurs +* if this requirement is not met. +* +* 2) After waking up from the low-power mode, the interrupt lockout state +* must be restored as indicated in the 'imask' input parameter. +* +* RETURNS: N/A +* +* C function prototype: +* +* void nano_cpu_atomic_idle (unsigned int imask); +*/ + +SECTION_FUNC(TEXT, nano_cpu_atomic_idle) + + /* + * r0: interrupt mask from caller + * r1: zero, for setting BASEPRI (needs a register) + */ + + eors.n r1, r1 + + /* + * Lock PRIMASK while sleeping: wfe will still get interrupted by incoming + * interrupts but the CPU will not service them right away. + */ + cpsid i + + /* + * No need to set SEVONPEND, it's set once in _CpuIdleInit() and never + * touched again. + */ + + /* unlock BASEPRI so wfe gets interrupted by incoming interrupts */ + msr BASEPRI, r1 + + wfe + + msr BASEPRI, r0 + cpsie i + bx lr diff --git a/arch/arm/core/exc_exit.s b/arch/arm/core/exc_exit.s new file mode 100644 index 00000000000..460b468a8f4 --- /dev/null +++ b/arch/arm/core/exc_exit.s @@ -0,0 +1,128 @@ +/* exc_exit.s - ARM CORTEX-M3 exception/interrupt exit API */ + +/* + * Copyright (c) 2013-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION + +Provides functions for performing kernel handling when exiting exceptions or +interrupts that are installed directly in the vector table (i.e. that are not +wrapped around by _IsrWrapper()). +*/ + +#define _ASMLANGUAGE + +#include +#include +#include +#include + +_ASM_FILE_PROLOGUE + +GTEXT(_ExcExit) +GTEXT(_IntExit) +GDATA(_NanoKernel) + +#if CONFIG_GDB_INFO + #define _EXIT_EXC_IF_FIBER_PREEMPTED beq _ExcExitWithGdbStub +#else + _EXIT_EXC_IF_FIBER_PREEMPTED: .macro + it eq + bxeq lr + .endm +#endif +#define _EXIT_EXC_IF_FIBER_NOT_READY _EXIT_EXC_IF_FIBER_PREEMPTED + +/******************************************************************************* +* +* _IntExit - kernel housekeeping when exiting interrupt handler installed +* directly in vector table +* +* VxMicro allows installing interrupt handlers (ISRs) directly into the vector +* table to get the lowest interrupt latency possible. This allows the ISR to be +* invoked directly without going through a software interrupt table. However, +* upon exiting the ISR, some kernel work must still be performed, namely +* possible context switching. While ISRs connected in the software interrupt +* table do this automatically via a wrapper, ISRs connected directly in the +* vector table must invoke _IntExit() as the *very last* action before +* returning. +* +* e.g. +* +* void myISR(void) +* { +* printk("in %s\n", __FUNCTION__); +* doStuff(); +* _IntExit(); +* } +* +* RETURNS: N/A +*/ + +SECTION_SUBSEC_FUNC(TEXT, _HandlerModeExit, _IntExit) + +/* _IntExit falls through to _ExcExit (they are aliases of each other) */ + + +/******************************************************************************* +* +* _ExcExit - kernel housekeeping when exiting exception handler installed +* directly in vector table +* +* See _IntExit(). +* +* RETURNS: N/A +*/ + +SECTION_SUBSEC_FUNC(TEXT, _HandlerModeExit, _ExcExit) + + ldr r1, =_NanoKernel + + /* is the current thread preemptible (task) ? */ + ldr r2, [r1, #__tNANO_flags_OFFSET] + ands.w r2, #PREEMPTIBLE + _EXIT_EXC_IF_FIBER_PREEMPTED + + /* is there a fiber ready ? */ + ldr r2, [r1, #__tNANO_fiber_OFFSET] + cmp r2, #0 + _EXIT_EXC_IF_FIBER_NOT_READY + + /* context switch required, pend the PendSV exception */ + ldr r1, =_SCS_ICSR + ldr r2, =_SCS_ICSR_PENDSV + str r2, [r1] + +_ExcExitWithGdbStub: + + _GDB_STUB_EXC_EXIT + + bx lr diff --git a/arch/arm/core/fault.c b/arch/arm/core/fault.c new file mode 100644 index 00000000000..a36b1705884 --- /dev/null +++ b/arch/arm/core/fault.c @@ -0,0 +1,414 @@ +/* fault.c - common fault handler for ARM Cortex-M */ + +/* + * Copyright (c) 2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +Common fault handler for ARM Cortex-M processors. +*/ + +#include +#include + +#include +#include +#include +#include + +#ifdef CONFIG_PRINTK +#include +#define PR_EXC(...) printk(__VA_ARGS__) +#else +#define PR_EXC(...) +#endif /* CONFIG_PRINTK */ + +#if (CONFIG_FAULT_DUMP > 0) +#define FAULT_DUMP(esf, fault) _FaultDump(esf, fault) +#else +#define FAULT_DUMP(esf, fault) \ + do { \ + (void) esf; \ + (void) fault; \ + } while ((0)) +#endif + +#if (CONFIG_FAULT_DUMP == 1) +/******************************************************************************* +* +* _FaultDump - dump information regarding fault (FAULT_DUMP == 1) +* +* Dump information regarding the fault when CONFIG_FAULT_DUMP is set to 1 +* (short form). +* +* eg. (precise bus error escalated to hard fault): +* +* Fault! EXC #3, Thread: 0x200000dc, instr: 0x000011d3 +* HARD FAULT: Escalation (see below)! +* MMFSR: 0x00000000, BFSR: 0x00000082, UFSR: 0x00000000 +* BFAR: 0xff001234 +* +* RETURNS: N/A +* +* \NOMANUAL +*/ + +void _FaultDump(const NANO_ESF *esf, int fault) +{ + int escalation = 0; + + PR_EXC("Fault! EXC #%d, Thread: %x, instr @ %x\n", + fault, + context_self_get(), + esf->pc); + + if (3 == fault) { /* hard fault */ + escalation = _ScbHardFaultIsForced(); + PR_EXC("HARD FAULT: %s\n", + escalation ? "Escalation (see below)!" + : "Bus fault on vector table read\n"); + } + + PR_EXC("MMFSR: %x, BFSR: %x, UFSR: %x\n", + __scs.scb.cfsr.byte.mmfsr.val, + __scs.scb.cfsr.byte.bfsr.val, + __scs.scb.cfsr.byte.ufsr.val); + + if (_ScbMemFaultIsMmfarValid()) { + PR_EXC("MMFAR: %x\n", _ScbMemFaultAddrGet()); + if (escalation) { + _ScbMemFaultMmfarReset(); + } + } + if (_ScbBusFaultIsBfarValid()) { + PR_EXC("BFAR: %x\n", _ScbBusFaultAddrGet()); + if (escalation) { + _ScbBusFaultBfarReset(); + } + } + + /* clear USFR sticky bits */ + _ScbUsageFaultAllFaultsReset(); +} +#endif + +#if (CONFIG_FAULT_DUMP == 2) +/******************************************************************************* +* +* _FaultContextShow - dump context information +* +* See _FaultDump() for example. +* +* RETURNS: N/A +* +* \NOMANUAL +*/ + +static void _FaultContextShow(const NANO_ESF *esf) +{ + PR_EXC(" Executing context ID (thread): 0x%x\n" + " Faulting instruction address: 0x%x\n", + context_self_get(), + esf->pc); +} + +/******************************************************************************* +* +* _MpuFault - dump MPU fault information +* +* See _FaultDump() for example. +* +* RETURNS: N/A +* +* \NOMANUAL +*/ + +static void _MpuFault(const NANO_ESF *esf, + int fromHardFault) +{ + PR_EXC("***** MPU FAULT *****\n"); + + _FaultContextShow(esf); + + if (_ScbMemFaultIsStacking()) { + PR_EXC(" Stacking error\n"); + } else if (_ScbMemFaultIsUnstacking()) { + PR_EXC(" Unstacking error\n"); + } else if (_ScbMemFaultIsDataAccessViolation()) { + PR_EXC(" Data Access Violation\n"); + if (_ScbMemFaultIsMmfarValid()) { + PR_EXC(" Address: 0x%x\n", _ScbMemFaultAddrGet()); + if (fromHardFault) { + _ScbMemFaultMmfarReset(); + } + } + } else if (_ScbMemFaultIsInstrAccessViolation()) { + PR_EXC(" Instruction Access Violation\n"); + } +} + +/******************************************************************************* +* +* _BusFault - dump bus fault information +* +* See _FaultDump() for example. +* +* RETURNS: N/A +* +* \NOMANUAL +*/ + +static void _BusFault(const NANO_ESF *esf, + int fromHardFault) +{ + PR_EXC("***** BUS FAULT *****\n"); + + _FaultContextShow(esf); + + if (_ScbBusFaultIsStacking()) { + PR_EXC(" Stacking error\n"); + } else if (_ScbBusFaultIsUnstacking()) { + PR_EXC(" Unstacking error\n"); + } else if (_ScbBusFaultIsPrecise()) { + PR_EXC(" Precise data bus error\n"); + if (_ScbBusFaultIsBfarValid()) { + PR_EXC(" Address: 0x%x\n", _ScbBusFaultAddrGet()); + if (fromHardFault) { + _ScbBusFaultBfarReset(); + } + } + /* it's possible to have both a precise and imprecise fault */ + if (_ScbBusFaultIsImprecise()) { + PR_EXC(" Imprecise data bus error\n"); + } + } else if (_ScbBusFaultIsImprecise()) { + PR_EXC(" Imprecise data bus error\n"); + } else if (_ScbBusFaultIsInstrBusErr()) { + PR_EXC(" Instruction bus error\n"); + } +} + +/******************************************************************************* +* +* _UsageFault - dump usage fault information +* +* See _FaultDump() for example. +* +* RETURNS: N/A +* +* \NOMANUAL +*/ + +static void _UsageFault(const NANO_ESF *esf) +{ + PR_EXC("***** USAGE FAULT *****\n"); + + _FaultContextShow(esf); + + /* bits are sticky: they stack and must be reset */ + if (_ScbUsageFaultIsDivByZero()) { + PR_EXC(" Division by zero\n"); + } + if (_ScbUsageFaultIsUnaligned()) { + PR_EXC(" Unaligned memory access\n"); + } + if (_ScbUsageFaultIsNoCp()) { + PR_EXC(" No coprocessor instructions\n"); + } + if (_ScbUsageFaultIsInvalidPcLoad()) { + PR_EXC(" Illegal load of EXC_RETURN into PC\n"); + } + if (_ScbUsageFaultIsInvalidState()) { + PR_EXC(" Illegal use of the EPSR\n"); + } + if (_ScbUsageFaultIsUndefinedInstr()) { + PR_EXC(" Attempt to execute undefined instruction\n"); + } + + _ScbUsageFaultAllFaultsReset(); +} + +/******************************************************************************* +* +* _HardFault - dump hard fault information +* +* See _FaultDump() for example. +* +* RETURNS: N/A +* +* \NOMANUAL +*/ + +static void _HardFault(const NANO_ESF *esf) +{ + PR_EXC("***** HARD FAULT *****\n"); + if (_ScbHardFaultIsBusErrOnVectorRead()) { + PR_EXC(" Bus fault on vector table read\n"); + } else if (_ScbHardFaultIsForced()) { + PR_EXC(" Fault escalation (see below)\n"); + if (_ScbIsMemFault()) { + _MpuFault(esf, 1); + } else if (_ScbIsBusFault()) { + _BusFault(esf, 1); + } else if (_ScbIsUsageFault()) { + _UsageFault(esf); + } + } +} + +/******************************************************************************* +* +* _DebugMonitor - dump debug monitor exception information +* +* See _FaultDump() for example. +* +* RETURNS: N/A +* +* \NOMANUAL +*/ + +static void _DebugMonitor(const NANO_ESF *esf) +{ + PR_EXC("***** Debug monitor exception (not implemented) *****\n"); +} + +/******************************************************************************* +* +* _ReservedException - dump reserved exception information +* +* See _FaultDump() for example. +* +* RETURNS: N/A +* +* \NOMANUAL +*/ + +static void _ReservedException(const NANO_ESF *esf, + int fault) +{ + PR_EXC("***** %s %d) *****\n", + fault < 16 ? "Reserved Exception (" : "Spurious interrupt (IRQ ", + fault - 16); +} + +/******************************************************************************* +* +* _FaultDump - dump information regarding fault (FAULT_DUMP == 2) +* +* Dump information regarding the fault when CONFIG_FAULT_DUMP is set to 2 +* (long form). +* +* eg. (precise bus error escalated to hard fault): +* +* Executing context ID (thread): 0x200000dc +* Faulting instruction address: 0x000011d3 +* ***** HARD FAULT ***** +* Fault escalation (see below) +* ***** BUS FAULT ***** +* Precise data bus error +* Address: 0xff001234 +* +* RETURNS: N/A +* +* \NOMANUAL +*/ + +static void _FaultDump(const NANO_ESF *esf, int fault) +{ + switch (fault) { + case 3: + _HardFault(esf); + break; + case 4: + _MpuFault(esf, 0); + break; + case 5: + _BusFault(esf, 0); + break; + case 6: + _UsageFault(esf); + break; + case 12: + _DebugMonitor(esf); + break; + default: + _ReservedException(esf, fault); + break; + } +} +#endif /* FAULT_DUMP == 2 */ + +/******************************************************************************* +* +* _Fault - fault handler +* +* This routine is called when fatal error conditions are detected by hardware +* and is responsible only for reporting the error. Once reported, it then +* invokes the user provided routine _SysFatalErrorHandler() which is +* responsible for implementing the error handling policy. +* +* Since the ESF can be either on the MSP or PSP depending if an exception or +* interrupt was already being handled, it is passed a pointer to both and has +* to find out on which the ESP is present. +* +* RETURNS: This function does not return. +* +* \NOMANUAL +*/ + +void _Fault( + const NANO_ESF *msp, /* pointer to potential ESF on MSP */ + const NANO_ESF *psp /* pointer to potential ESF on PSP */ + ) +{ + const NANO_ESF *esf = _ScbIsNestedExc() ? msp : psp; + int fault = _ScbActiveVectorGet(); + + FAULT_DUMP(esf, fault); + + _SysFatalErrorHandler(_NANO_ERR_HW_EXCEPTION, esf); +} + +/******************************************************************************* +* +* _FaultInit - initialization of fault handling +* +* Turns on the desired hardware faults. +* +* RETURNS: N/A +* +* \NOMANUAL +*/ + +void _FaultInit(void) +{ + _ScbDivByZeroFaultEnable(); + _ScbUnalignedFaultEnable(); +} diff --git a/arch/arm/core/fault_s.s b/arch/arm/core/fault_s.s new file mode 100644 index 00000000000..d9fd9f7bed4 --- /dev/null +++ b/arch/arm/core/fault_s.s @@ -0,0 +1,101 @@ +/* fault_s.s - fault handlers for ARM Cortex-M */ + +/* + * Copyright (c) 2013-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +Fault handlers for ARM Cortex-M processors. +*/ + +#define _ASMLANGUAGE + +#include +#include +#include + +_ASM_FILE_PROLOGUE + +GTEXT(_Fault) + +GTEXT(__hard_fault) +GTEXT(__mpu_fault) +GTEXT(__bus_fault) +GTEXT(__usage_fault) +GTEXT(__debug_monitor) +GTEXT(__reserved) + +/******************************************************************************* +* +* __fault - fault handler installed in the fault and reserved vectors +* +* Entry point for the hard fault, MPU fault, bus fault, usage fault, debug +* monitor and reserved exceptions. +* +* Save the values of the MSP and PSP in r0 and r1 respectively, so the first +* and second parameters to the _Fault() C function that will handle the rest. +* This has to be done because at this point we do not know if the fault +* happened while handling an exception or not, and thus the ESF could be on +* either stack. _Fault() will find out where the ESF resides. +* +* Provides these symbols: +* +* __hard_fault +* __mpu_fault +* __bus_fault +* __usage_fault +* __debug_monitor +* __reserved +*/ + +SECTION_SUBSEC_FUNC(TEXT,__fault,__hard_fault) +SECTION_SUBSEC_FUNC(TEXT,__fault,__mpu_fault) +SECTION_SUBSEC_FUNC(TEXT,__fault,__bus_fault) +SECTION_SUBSEC_FUNC(TEXT,__fault,__usage_fault) +SECTION_SUBSEC_FUNC(TEXT,__fault,__debug_monitor) +SECTION_SUBSEC_FUNC(TEXT,__fault,__reserved) + + _GDB_STUB_EXC_ENTRY + + /* force unlock interrupts */ + eors.n r0, r0 + msr BASEPRI, r0 + + mrs r0, MSP + mrs r1, PSP + + push {lr} + bl _Fault + + _GDB_STUB_EXC_EXIT + + pop {pc} + + .end diff --git a/arch/arm/core/ffs.s b/arch/arm/core/ffs.s new file mode 100644 index 00000000000..9627b7e660c --- /dev/null +++ b/arch/arm/core/ffs.s @@ -0,0 +1,93 @@ +/* ffs.s - ARM find first set assembly routines */ + +/* + * Copyright (c) 2013-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This library implements find_last_set() and find_first_set() which returns the +most and least significant bit set respectively. +*/ + +#define _ASMLANGUAGE + +#include +#include + +_ASM_FILE_PROLOGUE + +/* Exports */ + +GTEXT(find_last_set) +GTEXT(find_first_set) + +/******************************************************************************* +* +* find_last_set - find first set bit (searching from the most significant bit) +* +* This routine finds the first bit set in the argument passed it and +* returns the index of that bit. Bits are numbered starting +* at 1 from the least significant bit. A return value of zero indicates that +* the value passed is zero. +* +* RETURNS: most significant bit set +*/ + +SECTION_FUNC(TEXT, find_last_set) + + cmp r0, #0 + itt ne + clzne r0, r0 + rsbne r0, r0, #32 + + mov pc, lr + +/******************************************************************************* +* +* find_first_set - find first set bit (searching from the least significant bit) +* +* This routine finds the first bit set in the argument passed it and +* returns the index of that bit. Bits are numbered starting +* at 1 from the least significant bit. A return value of zero indicates that +* the value passed is zero. +* +* RETURNS: least significant bit set +*/ + +SECTION_FUNC(TEXT, find_first_set) + + rsb r1, r0, #0 + ands r0, r1, r0 /* r0 = x & (-x): only LSB set */ + + itt ne + clzne r0, r0 /* count leading zeroes */ + rsbne r0, r0, #32 + + mov pc, lr diff --git a/arch/arm/core/gdb_stub.s b/arch/arm/core/gdb_stub.s new file mode 100644 index 00000000000..738d9befe23 --- /dev/null +++ b/arch/arm/core/gdb_stub.s @@ -0,0 +1,163 @@ +/* gdb_stub.s - extra work performed upon exception entry/exit for GDB */ + +/* + * Copyright (c) 2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION + +Prep work done when entering exceptions consists of saving the callee-saved +registers before they get used by exception handlers, and recording the fact +that we are running in an exception. + +Upon exception exit, it must be recorded that the task is not in an exception +anymore. +*/ + +#define _ASMLANGUAGE + +#include +#include +#include +#include +#include + +_ASM_FILE_PROLOGUE + +/******************************************************************************* +* +* _GdbStubExcEntry - exception entry extra work when GDB_INFO is enabled +* +* During normal system operation, the callee-saved registers are saved lazily +* only when a context switch is required. To allow looking at the current +* threads registers while debugging an exception/interrupt, they must be saved +* upon entry since the handler could be using them: thus, looking at the CPU +* registers would show the current system state and not the current *thread*'s +* state. +* +* Also, record the fact that the thread is currently interrupted so that VQEMU +* looks into the CCS and not the CPU registers to obtain the current thread's +* register values. +* +* NOTE: +* - must be called with interrupts locked +* - cannot use r0 without saving it first +* +* RETURNS: N/A +*/ + +SECTION_FUNC(TEXT, _GdbStubExcEntry) + + ldr r1, =_NanoKernel + ldr r2, [r1, #__tNANO_flags_OFFSET] + + /* already in an exception, do not update the registers */ + ands r3, r2, #EXC_ACTIVE + it ne + bxne lr + + orrs r2, #EXC_ACTIVE + str r2, [r1, #__tNANO_flags_OFFSET] + ldr r1, [r1, #__tNANO_current_OFFSET] + str r2, [r1, #__tCCS_flags_OFFSET] + + /* save callee-saved + psp in CCS */ + adds r1, #__tCCS_preempReg_OFFSET + mrs ip, PSP + stmia r1, {v1-v8, ip} + + bx lr + +/******************************************************************************* +* +* _GdbStubExcExit - exception exit extra clean up when GDB_INFO is enabled +* +* Record the fact that the thread is not interrupted anymore so that VQEMU +* looks at the CPU registers and not into the CCS to obtain the current +* thread's register values. Only do this if this is not a nested exception. +* +* NOTE: +* - must be called with interrupts locked +* - cannot use r0 without saving it first +* +* RETURNS: N/A +*/ + +SECTION_FUNC(TEXT, _GdbStubExcExit) + + /* if we're nested (ie. !RETTOBASE), do not reset EXC_ACTIVE */ + ldr r1, =_SCS_ICSR + ldr r1, [r1] + ands r1, #_SCS_ICSR_RETTOBASE + it eq + bxeq lr + + ldr r1, =_NanoKernel + ldr r2, [r1, #__tNANO_flags_OFFSET] + + bic r2, #EXC_ACTIVE + str r2, [r1, #__tNANO_flags_OFFSET] + ldr r1, [r1, #__tNANO_current_OFFSET] + str r2, [r1, #__tCCS_flags_OFFSET] + + bx lr + +/******************************************************************************* +* +* _GdbStubIrqVectorTableEntry - stub for ISRs installed directly in +* vector table +* +* VxMicro on Cortex-M3/4 allows users to configure the kernel such that +* ISRs are installed directly in the vector table for maximum efficiency. +* +* When OS-awareness is enabled, a stub must be inserted to invoke +* _GdbStubExcEntry() before the user ISR runs, to save the current task's +* registers. This stub thus gets inserted in the vector table instead of the +* user's ISR. The user's IRQ vector table gets pushed after the vector table +* automatically by the linker script: this is all transparent to the user. +* This stub must also act as a demuxer that find the running exception and +* invoke the user's real ISR. +* +* RETURNS: N/A +*/ + +SECTION_FUNC(TEXT, _GdbStubIrqVectorTableEntry) + + _GDB_STUB_EXC_ENTRY + + mrs r0, IPSR /* get exception number */ + sub r0, r0, #16 /* get IRQ number */ + ldr r1, =_IrqVectorTable + + /* grab real ISR at address: r1 + (r0 << 2) (table is 4-byte wide) */ + ldr r1, [r1, r0, LSL #2] + + /* jump to ISR, no return: ISR is responsible for calling _IntExit */ + bx r1 diff --git a/arch/arm/core/gdb_stub_irq_vector_table.c b/arch/arm/core/gdb_stub_irq_vector_table.c new file mode 100644 index 00000000000..fe8b4f27e2b --- /dev/null +++ b/arch/arm/core/gdb_stub_irq_vector_table.c @@ -0,0 +1,52 @@ +/* gdb_stub_irq_vector_table.c - stubs for IRQ part of vector table */ + +/* + * Copyright (c) 2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +When GDB is enabled, the static IRQ vector table needs to install the +_GdbStubIrqVectorTableEntry stub to do some work before calling the +user-installed ISRs. +*/ + +#include +#include +#include + +typedef void (*vth)(void); /* Vector Table Handler */ + +#if defined(CONFIG_GDB_INFO) && !defined(CONFIG_SW_ISR_TABLE) + +vth __gdb_stub_irq_vector_table _GdbStubIrqVectorTable[CONFIG_NUM_IRQS] = { + [0 ...(CONFIG_NUM_IRQS - 1)] = _GdbStubIrqVectorTableEntry +}; + +#endif /* CONFIG_GDB_INFO && !CONFIG_SW_ISR_TABLE */ diff --git a/arch/arm/core/irq_init.c b/arch/arm/core/irq_init.c new file mode 100644 index 00000000000..0c18eff1fe7 --- /dev/null +++ b/arch/arm/core/irq_init.c @@ -0,0 +1,65 @@ +/* irq_init.c - ARM Cortex-M interrupt initialization */ + +/* + * Copyright (c) 2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +The ARM Cortex-M architecture provides its own fiber_abort() to deal with +different CPU modes (handler vs thread) when a fiber aborts. When its entry +point returns or when it aborts itself, the CPU is in thread mode and must +call _Swap() (which triggers a service call), but when in handler mode, the +CPU must exit handler mode to cause the context switch, and thus must queue +the PendSV exception. +*/ + +#include +#include +#include +#include + +/******************************************************************************* +* +* _IntLibInit - initialize interrupts +* +* Ensures all interrupts have their priority set to _EXC_IRQ_DEFAULT_PRIO and +* not 0, which they have it set to when coming out of reset. This ensures that +* interrupt locking via BASEPRI works as expected. +* +* RETURNS: N/A +*/ + +void _IntLibInit(void) +{ + int irq = 0; + for (; irq < CONFIG_NUM_IRQS; irq++) { + _NvicIrqPrioSet(irq, _EXC_IRQ_DEFAULT_PRIO); + } +} diff --git a/arch/arm/core/irq_manage.c b/arch/arm/core/irq_manage.c new file mode 100644 index 00000000000..9e2d6b2f51b --- /dev/null +++ b/arch/arm/core/irq_manage.c @@ -0,0 +1,189 @@ +/* irq_manage.c - ARM CORTEX-M3 interrupt management */ + +/* + * Copyright (c) 2013-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION + +Interrupt management: enabling/disabling and dynamic ISR connecting/replacing. +SW_ISR_TABLE_DYNAMIC has to be enabled for connecting ISRs at runtime. +*/ + +#include +#include +#include +#include +#include +#include + +extern void __reserved(void); + +/******************************************************************************* +* +* irq_handler_set - replace an interrupt handler by another +* +* An interrupt's ISR can be replaced at runtime. Care must be taken that the +* interrupt is disabled before doing this. +* +* This routine will hang if is not found in the table and ASSERT_ON is +* enabled. +* +* RETURNS: N/A +*/ + +void irq_handler_set(unsigned int irq, + void (*old)(void *arg), + void (*new)(void *arg), + void *arg) +{ + int key = irq_lock_inline(); + + __ASSERT(old == _IsrTable[irq].isr, "expected ISR not found in table"); + + if (old == _IsrTable[irq].isr) { + _IsrTable[irq].isr = new; + _IsrTable[irq].arg = arg; + } + + irq_unlock_inline(key); +} + +/******************************************************************************* +* +* irq_enable - enable an interrupt line +* +* Clear possible pending interrupts on the line, and enable the interrupt +* line. After this call, the CPU will receive interrupts for the specified +* . +* +* RETURNS: N/A +*/ + +void irq_enable(unsigned int irq) +{ + /* before enabling interrupts, ensure that interrupt is cleared */ + _NvicIrqUnpend(irq); + _NvicIrqEnable(irq); +} + +/******************************************************************************* +* +* irq_disable - disable an interrupt line +* +* Disable an interrupt line. After this call, the CPU will stop receiving +* interrupts for the specified . +* +* RETURNS: N/A +*/ + +void irq_disable(unsigned int irq) +{ + _NvicIrqDisable(irq); +} + +/******************************************************************************* +* +* irq_priority_set - set an interrupt's priority +* +* Valid values are from 1 to 255. Interrupts of priority 1 are not masked when +* interrupts are locked system-wide, so care must be taken when using them. ISR +* installed with priority 1 interrupts cannot make kernel calls. +* +* Priority 0 is reserved for kernel usage and cannot be used. +* +* The priority is verified if ASSERT_ON is enabled. +* +* RETURNS: N/A +*/ + +void irq_priority_set(unsigned int irq, + unsigned int prio) +{ + __ASSERT(prio > 0 && prio < 256, "invalid priority!"); + _NvicIrqPrioSet(irq, _EXC_PRIO(prio)); +} + +/******************************************************************************* +* +* _SpuriousIRQ - spurious interrupt handler +* +* Installed in all dynamic interrupt slots at boot time. Throws an error if +* called. +* +* See __reserved(). +* +* RETURNS: N/A +*/ + +void _SpuriousIRQ(void *unused) +{ + ARG_UNUSED(unused); + __reserved(); +} + +/******************************************************************************* +* +* irq_connect - connect an ISR to an interrupt line +* +* is connected to interrupt line (exception #+16). No prior +* ISR can have been connected on interrupt line since the system booted. +* +* This routine will hang if another ISR was connected for interrupt line +* and ASSERT_ON is enabled; if ASSERT_ON is disabled, it will fail silently. +* +* RETURNS: the interrupt line number +*/ + +int irq_connect(unsigned int irq, + unsigned int prio, + void (*isr)(void *arg), + void *arg) +{ + irq_handler_set(irq, _SpuriousIRQ, isr, arg); + irq_priority_set(irq, prio); + return irq; +} + +/******************************************************************************* +* +* irq_disconnect - disconnect an ISR from an interrupt line +* +* Interrupt line (exception #+16) is disconnected from its ISR and +* the latter is replaced by _SpuriousIRQ(). irq_disable() should have +* been called before invoking this routine. +* +* RETURNS: N/A +*/ + +void irq_disconnect(unsigned int irq) +{ + irq_handler_set(irq, _IsrTable[irq].isr, _SpuriousIRQ, NULL); +} diff --git a/arch/arm/core/isr_wrapper.s b/arch/arm/core/isr_wrapper.s new file mode 100644 index 00000000000..3f3d6be802a --- /dev/null +++ b/arch/arm/core/isr_wrapper.s @@ -0,0 +1,111 @@ +/* isr_wrapper.s - ARM CORTEX-M3 wrapper for ISRs with parameter */ + +/* + * Copyright (c) 2013-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION + +Wrapper installed in vector table for handling dynamic interrupts that accept +a parameter. +*/ + +#define _ASMLANGUAGE + +#include +#include +#include +#include +#include +#include + +_ASM_FILE_PROLOGUE + +GDATA(_IsrTable) + +GTEXT(_IsrWrapper) +GTEXT(_IntExit) + +/******************************************************************************* +* +* _IsrWrapper - wrapper around ISRs when inserted in software ISR table +* +* When inserted in the vector table, _IsrWrapper() demuxes the ISR table using +* the running interrupt number as the index, and invokes the registered ISR +* with its correspoding argument. When returning from the ISR, it determines +* if a context switch needs to happen (see documentation for __pendsv()) and +* pends the PendSV exception if so: the latter will perform the context switch +* itself. +* +* RETURNS: N/A +*/ +SECTION_FUNC(TEXT, _IsrWrapper) + + _GDB_STUB_EXC_ENTRY + + push {lr} /* lr is now the first item on the stack */ + +#ifdef CONFIG_ADVANCED_POWER_MANAGEMENT + /* + * All interrupts are disabled when handling idle wakeup. + * For tickless idle, this ensures that the calculation and programming of + * the device for the next timer deadline is not interrupted. + * For non-tickless idle, this ensures that the clearing of the kernel idle + * state is not interrupted. + * In each case, _SysPowerSaveIdleExit is called with interrupts disabled. + */ + cpsid i /* PRIMASK = 1 */ + + /* is this a wakeup from idle ? */ + ldr r2, =_NanoKernel + ldr r0, [r2, #__tNANO_idle_OFFSET] /* requested idle duration, in ticks */ + cmp r0, #0 + ittt ne + movne r1, #0 + strne r1, [r2, #__tNANO_idle_OFFSET] /* clear kernel idle state */ + blxne _SysPowerSaveIdleExit + + cpsie i /* re-enable interrupts (PRIMASK = 0) */ +#endif /* CONFIG_ADVANCED_POWER_MANAGEMENT */ + + mrs r0, IPSR /* get exception number */ + sub r0, r0, #16 /* get IRQ number */ + lsl r0, r0, #3 /* table is 8-byte wide */ + ldr r1, =_IsrTable + add r1, r1, r0 /* table entry: ISRs must have their MSB set to stay + * in thumb mode */ + + ldmia r1,{r0,r3} /* arg in r0, ISR in r3 */ + blx r3 /* call ISR */ + + pop {lr} + + /* exception return is done in _IntExit(), including _GDB_STUB_EXC_EXIT */ + b _IntExit diff --git a/arch/arm/core/nano_fiber_abort.c b/arch/arm/core/nano_fiber_abort.c new file mode 100644 index 00000000000..86f64069e92 --- /dev/null +++ b/arch/arm/core/nano_fiber_abort.c @@ -0,0 +1,77 @@ +/* nano_fiber_abort.c - ARM Cortex-M fiber_abort() routine */ + +/* + * Copyright (c) 2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +The ARM Cortex-M architecture provides its own fiber_abort() to deal with +different CPU modes (handler vs thread) when a fiber aborts. When its entry +point returns or when it aborts itself, the CPU is in thread mode and must +call _Swap() (which triggers a service call), but when in handler mode, the +CPU must exit handler mode to cause the context switch, and thus must queue +the PendSV exception. +*/ + +#ifdef CONFIG_MICROKERNEL +#include +#include +#endif + +#include +#include +#include +#include +#include + +extern void _NanoFiberSwap(void); + +/******************************************************************************* +* +* fiber_abort - abort the currently executing fiber +* +* Possible reasons for a fiber aborting: +* +* - the fiber explicitly aborts itself by calling this routine +* - the fiber implicitly aborts by returning from its entry point +* - the fiber encounters a fatal exception +* +* RETURNS: N/A +*/ + +void fiber_abort(void) +{ + _ContextExitRtn(_NanoKernel.current); + if (_ScbIsInThreadMode()) { + _NanoFiberSwap(); + } else { + _ScbPendsvSet(); + } +} diff --git a/arch/arm/core/nanocontext.c b/arch/arm/core/nanocontext.c new file mode 100644 index 00000000000..d6b49b16a0c --- /dev/null +++ b/arch/arm/core/nanocontext.c @@ -0,0 +1,151 @@ +/* nanocontext.c - new context creation for ARM Cortex-M */ + +/* + * Copyright (c) 2013-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +Core nanokernel fiber related primitives for the ARM Cortex-M processor +architecture. +*/ + +#include +#include +#include +#include +#include + +tNANO _NanoKernel = {0}; + +#if defined(CONFIG_HOST_TOOLS_SUPPORT) +#define TOOLS_SUPPORT_INIT(pCcs) toolsSupportInit(pCcs) +#else +#define TOOLS_SUPPORT_INIT(pCcs) \ + do {/* do nothing */ \ + } while ((0)) +#endif + +#if defined(CONFIG_HOST_TOOLS_SUPPORT) +/******************************************************************************* +* +* toolsSupportInit - initialize host-tools support when needed +* +* Currently only inserts the new context in the list of active contexts. +* +* RETURNS: N/A +*/ + +static ALWAYS_INLINE void toolsSupportInit(struct s_CCS *pCcs /* context */ + ) +{ + unsigned int key; + + /* + * Add the newly initialized context to head of the list of contexts. + * This singly linked list of contexts maintains ALL the contexts in the + * system: both tasks and fibers regardless of whether they are + * runnable. + */ + + key = irq_lock(); + pCcs->activeLink = _NanoKernel.contexts; + _NanoKernel.contexts = pCcs; + irq_unlock(key); +} +#endif /* CONFIG_HOST_TOOLS_SUPPORT */ + +/******************************************************************************* +* +* _NewContext - intialize a new context (thread) from its stack space +* +* The control structure (CCS) is put at the lower address of the stack. An +* initial context, to be "restored" by __pendsv(), is put at the other end of +* the stack, and thus reusable by the stack when not needed anymore. +* +* The initial context is an exception stack frame (ESF) since exiting the +* PendSV exception will want to pop an ESF. Interestingly, even if the lsb of +* an instruction address to jump to must always be set since the CPU always +* runs in thumb mode, the ESF expects the real address of the instruction, +* with the lsb *not* set (instructions are always aligned on 16 bit halfwords). +* Since the compiler automatically sets the lsb of function addresses, we have +* to unset it manually before storing it in the 'pc' field of the ESF. +* +* is currently unused. +* +* RETURNS: N/A +*/ + +void *_NewContext( + char *pStackMem, /* stack memory */ + unsigned stackSize, /* stack size in bytes */ + _ContextEntry pEntry, /* entry point */ + void *parameter1, /* entry point first param */ + void *parameter2, /* entry point second param */ + void *parameter3, /* entry point third param */ + int priority, /* context priority (-1 for tasks) */ + unsigned options /* misc options (future) */ + ) +{ + char *stackEnd = pStackMem + stackSize; + struct __esf *pInitCtx; + tCCS *pCcs = (void *)ROUND_UP(pStackMem, sizeof(uint32_t)); + + /* carve the context entry struct from the "base" of the stack */ + + pInitCtx = (struct __esf *)(STACK_ROUND_DOWN(stackEnd) - + sizeof(struct __esf)); + + pInitCtx->pc = ((uint32_t)_ContextEntryRtn) & 0xfffffffe; + pInitCtx->a1 = (uint32_t)pEntry; + pInitCtx->a2 = (uint32_t)parameter1; + pInitCtx->a3 = (uint32_t)parameter2; + pInitCtx->a4 = (uint32_t)parameter3; + pInitCtx->xpsr = + 0x01000000UL; /* clear all, thumb bit is 1, even if RO */ + + pCcs->link = NULL; + pCcs->flags = priority == -1 ? TASK | PREEMPTIBLE : FIBER; + pCcs->prio = priority; + +#ifdef CONFIG_CONTEXT_CUSTOM_DATA + /* Initialize custom data field (value is opaque to kernel) */ + + pCcs->custom_data = NULL; +#endif + + pCcs->preempReg.psp = (uint32_t)pInitCtx; + pCcs->basepri = 0; + + /* initial values in all other registers/CCS entries are irrelevant */ + + TOOLS_SUPPORT_INIT(pCcs); + + return pCcs; +} diff --git a/arch/arm/core/nanofatal.c b/arch/arm/core/nanofatal.c new file mode 100644 index 00000000000..0682b226a1e --- /dev/null +++ b/arch/arm/core/nanofatal.c @@ -0,0 +1,132 @@ +/* nanofatal.c - nanokernel fatal error handler for ARM Cortex-M */ + +/* + * Copyright (c) 2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This module provides the _NanoFatalErrorHandler() routine for ARM Cortex-M. +*/ + +/* includes */ + +#include +#include + +#include +#include +#include +#include + +#ifdef CONFIG_PRINTK +#include +#define PR_EXC(...) printk(__VA_ARGS__) +#else +#define PR_EXC(...) +#endif /* CONFIG_PRINTK */ + +/* globals */ + +/* + * Define a default ESF for use with _NanoFatalErrorHandler() in the event + * the caller does not have a NANO_ESF to pass + */ +const NANO_ESF __defaultEsf = {0xdeaddead, /* a1 */ + 0xdeaddead, /* a2 */ + 0xdeaddead, /* a3 */ + 0xdeaddead, /* a4 */ + 0xdeaddead, /* ip */ + 0xdeaddead, /* lr */ + 0xdeaddead, /* pc */ + 0xdeaddead, /* xpsr */ +}; + +/******************************************************************************* +* +* _NanoFatalErrorHandler - nanokernel fatal error handler +* +* This routine is called when fatal error conditions are detected by software +* and is responsible only for reporting the error. Once reported, it then +* invokes the user provided routine _SysFatalErrorHandler() which is +* responsible for implementing the error handling policy. +* +* The caller is expected to always provide a usable ESF. In the event that the +* fatal error does not have a hardware generated ESF, the caller should either +* create its own or use a pointer to the global default ESF <__defaultEsf>. +* +* RETURNS: This function does not return. +* +* \NOMANUAL +*/ + +FUNC_NORETURN void _NanoFatalErrorHandler( + unsigned int reason, /* reason that handler was called */ + const NANO_ESF *pEsf /* pointer to exception stack frame */ + ) +{ + switch (reason) { + case _NANO_ERR_INVALID_TASK_EXIT: + PR_EXC("***** Invalid Exit Software Error! *****\n"); + break; + +#if defined(CONFIG_STACK_CANARIES) + case _NANO_ERR_STACK_CHK_FAIL: + PR_EXC("***** Stack Check Fail! *****\n"); + break; +#endif /* CONFIG_STACK_CANARIES */ + +#ifdef CONFIG_ENHANCED_SECURITY + case _NANO_ERR_INVALID_STRING_OP: + PR_EXC("**** Invalid string operation! ****\n"); + break; +#endif /* CONFIG_ENHANCED_SECURITY */ + + default: + PR_EXC("**** Unknown Fatal Error %d! ****\n", reason); + break; + } + PR_EXC("Current context ID = 0x%x\n" + "Faulting instruction address = 0x%x\n", + context_self_get(), + pEsf->pc); + + /* + * Now that the error has been reported, call the user implemented + * policy + * to respond to the error. The decisions as to what responses are + * appropriate to the various errors are something the customer must + * decide. + */ + + _SysFatalErrorHandler(reason, pEsf); + + for (;;) + ; +} diff --git a/arch/arm/core/offsets/offsets.c b/arch/arm/core/offsets/offsets.c new file mode 100644 index 00000000000..72de63c963d --- /dev/null +++ b/arch/arm/core/offsets/offsets.c @@ -0,0 +1,104 @@ +/* offsets.c - ARM nano kernel structure member offset definition file */ + +/* + * Copyright (c) 2013-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This module is responsible for the generation of the absolute symbols whose +value represents the member offsets for various ARM nanokernel +structures. + +All of the absolute symbols defined by this module will be present in the +final microkernel or nanokernel ELF image (due to the linker's reference to +the _OffsetAbsSyms symbol). + +INTERNAL +It is NOT necessary to define the offset for every member of a structure. +Typically, only those members that are accessed by assembly language routines +are defined; however, it doesn't hurt to define all fields for the sake of +completeness. + +*/ + +#include +#include +#include + +/* ARM-specific tNANO structure member offsets */ + +GEN_OFFSET_SYM(tNANO, flags); +#ifdef CONFIG_ADVANCED_POWER_MANAGEMENT +GEN_OFFSET_SYM(tNANO, idle); +#endif /* CONFIG_ADVANCED_POWER_MANAGEMENT */ + +/* ARM-specific tCCS structure member offsets */ + +GEN_OFFSET_SYM(tCCS, basepri); +#ifdef CONFIG_CONTEXT_CUSTOM_DATA +GEN_OFFSET_SYM(tCCS, custom_data); +#endif + +/* ARM-specific ESF structure member offsets */ + +GEN_OFFSET_SYM(tESF, a1); +GEN_OFFSET_SYM(tESF, a2); +GEN_OFFSET_SYM(tESF, a3); +GEN_OFFSET_SYM(tESF, a4); +GEN_OFFSET_SYM(tESF, ip); +GEN_OFFSET_SYM(tESF, lr); +GEN_OFFSET_SYM(tESF, pc); +GEN_OFFSET_SYM(tESF, xpsr); + +/* size of the entire tESF structure */ + +GEN_ABSOLUTE_SYM(__tESF_SIZEOF, sizeof(tESF)); + +/* ARM-specific preempt registers structure member offsets */ + +GEN_OFFSET_SYM(tPreempt, v1); +GEN_OFFSET_SYM(tPreempt, v2); +GEN_OFFSET_SYM(tPreempt, v3); +GEN_OFFSET_SYM(tPreempt, v4); +GEN_OFFSET_SYM(tPreempt, v5); +GEN_OFFSET_SYM(tPreempt, v6); +GEN_OFFSET_SYM(tPreempt, v7); +GEN_OFFSET_SYM(tPreempt, v8); +GEN_OFFSET_SYM(tPreempt, psp); + +/* size of the entire preempt registers structure */ + +GEN_ABSOLUTE_SYM(__tPreempt_SIZEOF, sizeof(tPreempt)); + +/* size of the tCCS structure sans save area for floating point regs */ + +GEN_ABSOLUTE_SYM(__tCCS_NOFLOAT_SIZEOF, sizeof(tCCS)); + +GEN_ABS_SYM_END diff --git a/arch/arm/core/swap.s b/arch/arm/core/swap.s new file mode 100644 index 00000000000..229786ec5f0 --- /dev/null +++ b/arch/arm/core/swap.s @@ -0,0 +1,223 @@ +/* swap.s - thread context switching for ARM Cortex-M */ + +/* + * Copyright (c) 2013-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This module implements the routines necessary for thread context switching +on ARM Cortex-M3/M4 CPUs. +*/ + +#define _ASMLANGUAGE + +#include +#include +#include +#include + +_ASM_FILE_PROLOGUE + +GTEXT(_Swap) +GTEXT(__svc) +GTEXT(__pendsv) + +GDATA(_NanoKernel) + +/******************************************************************************* +* +* __pendsv - PendSV exception handler, handling context switches +* +* The PendSV exception is the only context in the system that can perform +* context switching. When an execution context finds out it has to switch +* contexts, it pends the PendSV exception. +* +* When PendSV is pended, the decision that a context switch must happen has +* already been taken. In other words, when __pendsv() runs, we *know* we have +* to swap *something*. +* +* The scheduling algorithm is simple: schedule the head of the runnable FIBER +* context list, which is represented by _NanoKernel.fiber. If there are no +* runnable FIBER contexts, then schedule the TASK context represented by +* _NanoKernel.task. The _NanoKernel.task field will never be NULL. +*/ + +SECTION_FUNC(TEXT, __pendsv) + + _GDB_STUB_EXC_ENTRY + + /* load _Nanokernel into r1 and current tCCS into r2 */ + ldr r1, =_NanoKernel + ldr r2, [r1, #__tNANO_current_OFFSET] + + /* addr of callee-saved regs in CCS in r0 */ + add r0, r2, #__tCCS_preempReg_OFFSET + + /* save callee-saved + psp in CCS */ + mrs ip, PSP + stmia r0, {v1-v8, ip} + + /* + * Prepare to clear PendSV with interrupts unlocked, but + * don't clear it yet. PendSV must not be cleared until + * the new thread is context-switched in since all decisions + * to pend PendSV have been taken with the current kernel + * state and this is what we're handling currently. + */ + ldr ip, =_SCS_ICSR + ldr r3, =_SCS_ICSR_UNPENDSV + + /* protect the kernel state while we play with the thread lists */ + movs.n r0, #_EXC_IRQ_DEFAULT_PRIO + msr BASEPRI, r0 + + /* find out incoming context (fiber or task) */ + + /* is there a fiber ready ? */ + ldr r2, [r1, #__tNANO_fiber_OFFSET] + cmp r2, #0 + + /* + * if so, remove fiber from list + * else, the task is the thread we're switching in + */ + itte ne + ldrne.w r0, [r2, #__tCCS_link_OFFSET] /* then */ + strne.w r0, [r1, #__tNANO_fiber_OFFSET] /* then */ + ldreq.w r2, [r1, #__tNANO_task_OFFSET] /* else */ + + /* r2 contains the new thread */ + ldr r0, [r2, #__tCCS_flags_OFFSET] + str r0, [r1, #__tNANO_flags_OFFSET] + str r2, [r1, #__tNANO_current_OFFSET] + + /* + * Clear PendSV so that if another interrupt comes in and + * decides, with the new kernel state baseed on the new thread + * being context-switched in, that it needs to reschedules, it + * will take, but that previously pended PendSVs do not take, + * since they were based on the previous kernel state and this + * has been handled. + */ + + /* _SCS_ICSR is still in ip and _SCS_ICSR_UNPENDSV in r3 */ + str r3, [ip, #0] + + /* restore BASEPRI for the incoming thread */ + ldr r0, [r2, #__tCCS_basepri_OFFSET] + mov ip, #0 + str ip, [r2, #__tCCS_basepri_OFFSET] + msr BASEPRI, r0 + + /* load callee-saved + psp from CCS */ + add r0, r2, #__tCCS_preempReg_OFFSET + ldmia r0, {v1-v8, ip} + msr PSP, ip + + _GDB_STUB_EXC_EXIT + + /* exc return */ + bx lr + +/******************************************************************************* +* +* __svc - service call handler +* +* The service call (svc) is only used in _Swap() to enter handler mode so we +* can go through the PendSV exception to perform a context switch. +* +* RETURNS: N/A +*/ + +SECTION_FUNC(TEXT, __svc) + + _GDB_STUB_EXC_ENTRY + + /* + * Unlock interrupts: + * - in a SVC call, so protected against context switches + * - allow PendSV, since it's running at prio 0xff + */ + eors.n r0, r0 + msr BASEPRI, r0 + + /* set PENDSV bit, pending the PendSV exception */ + ldr r1, =_SCS_ICSR + ldr r2, =_SCS_ICSR_PENDSV + str r2, [r1, #0] + + _GDB_STUB_EXC_EXIT + + /* handler mode exit, to PendSV */ + bx lr + +/******************************************************************************* +* +* _Swap - initiate a cooperative context switch +* +* The _Swap() routine is invoked by various nanokernel services to effect +* a cooperative context context switch. Prior to invoking _Swap(), the caller +* disables interrupts via irq_lock() and the return 'key' is passed as a +* parameter to _Swap(). The 'key' actually represents the BASEPRI register +* prior to disabling interrupts via the BASEPRI mechanism. +* +* _Swap() itself does not do much. +* +* It simply stores the intlock key (the BASEPRI value) parameter into +* current->basepri, and then triggers a service call exception (svc) to setup +* the PendSV exception, which does the heavy lifting of context switching. + +* This is the only place we have to save BASEPRI since the other paths to +* __pendsv all come from handling an interrupt, which means we know the +* interrupts were not locked: in that case the BASEPRI value is 0. +* +* Given that _Swap() is called to effect a cooperative context context switch, +* only the caller-saved integer registers need to be saved in the tCCS of the +* outgoing context. This is all performed by the hardware, which stores it in +* its exception stack frame, created when handling the svc exception. +* +* RETURNS: may contain a return value setup by a call to fiberRtnValueSet() +* +* C function prototype: +* +* unsigned int _Swap (unsigned int basepri); +* +*/ + +SECTION_FUNC(TEXT, _Swap) + + ldr r1, =_NanoKernel + ldr r2, [r1, #__tNANO_current_OFFSET] + str r0, [r2, #__tCCS_basepri_OFFSET] + + svc #0 + + /* r0 contains the return value if needed */ + bx lr diff --git a/arch/arm/core/task_abort.c b/arch/arm/core/task_abort.c new file mode 100644 index 00000000000..feaabde45d1 --- /dev/null +++ b/arch/arm/core/task_abort.c @@ -0,0 +1,86 @@ +/* task_abort.c - ARM Cortex-M _TaskAbort() routine */ + +/* + * Copyright (c) 2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +The ARM Cortex-M architecture provides its own _TaskAbort() to deal with +different CPU modes (handler vs thread) when a task aborts. When its entry +point returns or when it aborts itself, the CPU is in thread mode and must +call the equivalent of task_abort(), but when in handler mode, the +CPU must queue a packet to K_swapper(), then exit handler mode to queue the +PendSV exception and cause the immediate context switch to K_swapper. +*/ + +#ifdef CONFIG_MICROKERNEL + +#include +#include +#include +#include +#include +#include +#include + +static struct k_args cmdpacket; + +/******************************************************************************* +* +* _TaskAbort - abort the current task +* +* Possible reasons for a task aborting: +* +* - the task explicitly aborts itself by calling this routine +* - the task implicitly aborts by returning from its entry point +* - the task encounters a fatal exception +* +* RETURNS: N/A +* +* \NOMANUAL +*/ + +void _TaskAbort(void) +{ + const int taskAbortCode = 1; + if (_ScbIsInThreadMode()) { + _task_ioctl(K_Task->Ident, taskAbortCode); + } else { + cmdpacket.Comm = TSKOP; + cmdpacket.Args.g1.task = K_Task->Ident; + cmdpacket.Args.g1.opt = taskAbortCode; + cmdpacket.Srce = 0; + K_Task->Args = &cmdpacket; + nano_isr_stack_push(&K_Args, (uint32_t) &cmdpacket); + _ScbPendsvSet(); + } +} + +#endif /* CONFIG_MICROKERNEL */ diff --git a/arch/arm/defs.objs b/arch/arm/defs.objs new file mode 100644 index 00000000000..f572d660a91 --- /dev/null +++ b/arch/arm/defs.objs @@ -0,0 +1,73 @@ +# defs.objs - build system + +# +# Copyright (c) 2015 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors +# may be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. +# + +nkernel_BASE = ${vBASE}/kernel/arch/ + +nkernel_INCLUDE_DIR = $(strip \ + ${vBASE}/arch/${vARCH}/include \ + ${vBASE}/kernel/nanokernel/include \ + ${vBASE}/kernel/microkernel/include \ + ${vBASE}/target/src/bsp/arch/${vARCH} \ +) + +nkernel_PATH = $(strip \ + ${vBASE}/arch/${vARCH}/core \ + ${vBASE}/kernel/nanokernel/core \ +) + +nkernel_SRC := +nkernel_SRC_NANOKERNEL_y = $(strip \ + ${vBASE}/kernel/common/version.c \ + ${vBASE}/misc/printk.c \ +) + +nkernel_SRC_MICROKERNEL_y = $(strip \ + ${vBASE}/kernel/nanokernel/task/start_task.c \ +) + +nkernel_SRC += $(strip \ + ${nkernel_SRC_NANOKERNEL_${CONFIG_NANOKERNEL}} \ + ${nkernel_SRC_MICROKERNEL_${CONFIG_MICROKERNEL}} \ +) + +ifeq ($(CONFIG_ENHANCED_SECURITY),y) + nkernel_SRC += $(strip \ + ${vBASE}/kernel/common/string_s.c \ +) +endif + +nkernel_SRC += $(foreach path,${nkernel_PATH},$(wildcard ${path}/*.$c)) +nkernel_SRC += $(foreach path,${nkernel_PATH},$(wildcard ${path}/*.$s)) + +nkernel_SRC += ${vKLIB_DIR}/configs.$c + +KLIBS += nkernel diff --git a/arch/arm/fsl_frdm_k64f/board.h b/arch/arm/fsl_frdm_k64f/board.h new file mode 100644 index 00000000000..b3012cd47df --- /dev/null +++ b/arch/arm/fsl_frdm_k64f/board.h @@ -0,0 +1,217 @@ +/* board.h - board configuration macros for the fsl_frdm_k64f BSP */ + +/* + * Copyright (c) 2014-2015 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This header file is used to specify and describe board-level aspects for the +'fsl_frdm_k64f' BSP. +*/ + +#ifndef _BOARD__H_ +#define _BOARD__H_ + +#include + +#define SRAM_SIZE KB(192) /* 64K in code space (ignored) + 192K in SRAM space \ + */ + +/* default system clock */ + +#define SYSCLK_DEFAULT_IOSC_HZ MHZ(120) + +/* address bases */ + +#define PERIPH_ADDR_BASE_MPU 0x4000D000 /* Memory Protection Unit */ + +#define PERIPH_ADDR_BASE_PCR 0x40049000 /* Port and pin Configuration */ + +#define PERIPH_ADDR_BASE_SIM 0x40047000 /* System Integration module */ + +#define PERIPH_ADDR_BASE_WDOG 0x40052000 /* Watchdog Timer module */ + +#define PERIPH_ADDR_BASE_MCG 0x40064000 /* Multipurpose Clock Generator */ + +#define PERIPH_ADDR_BASE_OSC 0x40065000 /* Oscillator module */ + +#define PERIPH_ADDR_BASE_UART0 0x4006A000 /* UART0 connected to SDA USB */ +#define PERIPH_ADDR_BASE_UART1 0x4006B000 /* not supported */ +#define PERIPH_ADDR_BASE_UART2 0x4006C000 /* not supported */ +#define PERIPH_ADDR_BASE_UART3 0x4006D000 /* not supported */ +#define PERIPH_ADDR_BASE_UART4 0x400EA000 /* not supported - for Bluetooth */ + +#define PERIPH_ADDR_BASE_PMC 0x4007D000 /* Power Mgt Controller module */ + +/* IRQs */ + +#define IRQ_DMA_CHAN0 0 +#define IRQ_DMA_CHAN1 1 +#define IRQ_DMA_CHAN2 2 +#define IRQ_DMA_CHAN3 3 +#define IRQ_DMA_CHAN4 4 +#define IRQ_DMA_CHAN5 5 +#define IRQ_DMA_CHAN6 6 +#define IRQ_DMA_CHAN7 7 +#define IRQ_DMA_CHAN8 8 +#define IRQ_DMA_CHAN9 9 +#define IRQ_DMA_CHAN10 10 +#define IRQ_DMA_CHAN11 11 +#define IRQ_DMA_CHAN12 12 +#define IRQ_DMA_CHAN13 13 +#define IRQ_DMA_CHAN14 14 +#define IRQ_DMA_CHAN15 15 +#define IRQ_DMA_ERR 16 +#define IRQ_MCM 17 +#define IRQ_FLASH_CMD 18 +#define IRQ_FLASH_COLLISION 19 +#define IRQ_LOW_VOLTAGE 20 +#define IRQ_LOW_LEAKAGE 21 +#define IRQ_WDOG_OR_EVM 22 +#define IRQ_RAND_NUM_GEN 23 +#define IRQ_I2C0 24 +#define IRQ_I2C1 25 +#define IRQ_SPI0 26 +#define IRQ_SPI1 27 +#define IRQ_I2S0_TX 28 +#define IRQ_I2S0_RX 29 +#define IRQ_RESERVED0 30 +#define IRQ_UART0_STATUS 31 +#define IRQ_UART0_ERROR 32 +#define IRQ_UART1_STATUS 33 +#define IRQ_UART1_ERROR 34 +#define IRQ_UART2_STATUS 35 +#define IRQ_UART2_ERROR 36 +#define IRQ_UART3_STATUS 37 +#define IRQ_UART3_ERROR 38 +#define IRQ_ADC0 39 +#define IRQ_CMP0 40 +#define IRQ_CMP1 41 +#define IRQ_FTM0 42 +#define IRQ_FTM1 43 +#define IRQ_FTM2 44 +#define IRQ_CMT 45 +#define IRQ_RTC_ALARM 46 +#define IRQ_RTC_SEC 47 +#define IRQ_TIMER0 48 +#define IRQ_TIMER1 49 +#define IRQ_TIMER2 50 +#define IRQ_TIMER3 51 +#define IRQ_PDB 52 +#define IRQ_USB_OTG 53 +#define IRQ_USB_CHARGE 54 +#define IRQ_RESERVED1 55 +#define IRQ_DAC0 56 +#define IRQ_MCG 57 +#define IRQ_LOW_PWR_TIMER 58 +#define IRQ_GPIO_PORTA 59 +#define IRQ_GPIO_PORTB 60 +#define IRQ_GPIO_PORTC 61 +#define IRQ_GPIO_PORTD 62 +#define IRQ_GPIO_PORTE 63 +#define IRQ_SOFTWARE 64 +#define IRQ_SPI2 65 +#define IRQ_UART4_STATUS 66 +#define IRQ_UART4_ERROR 67 +#define IRQ_RESERVED2 68 /* IRQ_UART5_STATUS - UART5 not implemented */ +#define IRQ_RESERVED3 69 /* IRQ_UART5_ERROR - UART5 not implemented */ +#define IRQ_CMP2 70 +#define IRQ_FTM3 71 +#define IRQ_DAC1 72 +#define IRQ_ADC1 73 +#define IRQ_I2C2 74 +#define IRQ_CAN0_MSG_BUF 75 +#define IRQ_CAN0_BUS_OFF 76 +#define IRQ_CAN0_ERROR 77 +#define IRQ_CAN0_TX_WARN 78 +#define IRQ_CAN0_RX_WARN 79 +#define IRQ_CAN0_WAKEUP 80 +#define IRQ_SDHC 81 +#define IRQ_ETH_IEEE1588_TMR 82 +#define IRQ_ETH_TX 83 +#define IRQ_ETH_RX 84 +#define IRQ_ETH_ERR_MISC 85 + +#ifndef _ASMLANGUAGE + +#include +#include + +/* + * UART configuration settings + */ + +#include + +#define CONFIG_UART_NUM_SYSTEM_PORTS 1 +#define CONFIG_UART_NUM_EXTRA_PORTS 0 +#define CONFIG_UART_NUM_PORTS \ + (CONFIG_UART_NUM_SYSTEM_PORTS + CONFIG_UART_NUM_EXTRA_PORTS) + +#define CONFIG_UART_CONSOLE_INDEX 0 +#define CONFIG_UART_CONSOLE_PORT PCR_PORT_B +#define CONFIG_UART_CONSOLE_PORT_RX_PIN 16 +#define CONFIG_UART_CONSOLE_PORT_TX_PIN 17 +#define CONFIG_UART_CONSOLE_PORT_MUX_FUNC PCR_MUX_ALT3 +#define CONFIG_UART_CONSOLE_CLK_FREQ SYSCLK_DEFAULT_IOSC_HZ +#define CONFIG_UART_CONSOLE_BAUDRATE 115200 +#define CONFIG_UART_CONSOLE_REGS PERIPH_ADDR_BASE_UART0 +#define CONFIG_UART_CONSOLE_IRQ IRQ_UART0_STATUS +#define CONFIG_UART_CONSOLE_INT_PRI 3 + +#define EXC_FROM_IRQ(irq) ((irq) + 16) +#define VECTOR_FROM_IRQ(irq) EXC_FROM_IRQ(irq) +#define VECTOR_ADDR(vector) ((uint32_t *)((int)vector << 2)) + +/* + * Device drivers utilize the macros PLB_BYTE_REG_WRITE() and + * PLB_BYTE_REG_READ() to access byte-wide registers on the processor + * local bus (PLB), as opposed to a PCI bus, for example. Boards are + * expected to provide implementations of these macros. + */ + +static inline void __plbByteRegWrite(unsigned char data, unsigned char *pAddr) +{ + *pAddr = data; +} + +#define PLB_BYTE_REG_WRITE(data, address) \ + __plbByteRegWrite((unsigned char)data, (unsigned char *)address) + +static inline unsigned char __plbByteRegRead(unsigned char *pAddr) +{ + return *pAddr; +} + +#define PLB_BYTE_REG_READ(address) __plbByteRegRead((unsigned char *)address) + +#endif /* !_ASMLANGUAGE */ + +#endif /* _BOARD__H_ */ diff --git a/arch/arm/fsl_frdm_k64f/defs.objs b/arch/arm/fsl_frdm_k64f/defs.objs new file mode 100644 index 00000000000..dbf500d9390 --- /dev/null +++ b/arch/arm/fsl_frdm_k64f/defs.objs @@ -0,0 +1,103 @@ +# defs.objs - build system + +# +# Copyright (c) 2015 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors +# may be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. +# + +bsp_INCLUDE_DIR = $(strip \ + ${vBASE}/kernel/common/bsp \ + ${vBASE}/include/bsp \ + ${vBASE}/include \ + ${vBASE}/drivers \ + ${vBASE}/arch/${vARCH} \ + ${vBSP_BASE_DIR}/${vBSP} \ +) + +# initialization +bsp_init_SRC = $(strip \ + arch/arm/bsp/CortexM/vector_table.s \ + arch/arm/bsp/CortexM/reset.s \ + arch/arm/bsp/CortexM/prep_c.c \ + kernel/common/bsp/init.c \ + kernel/common/bsp/ctors.c \ +) + +# arch-specific +bsp_arch_SRC = $(strip \ + arch/arm/bsp/CortexM/scs.c \ + arch/arm/bsp/CortexM/scb.c \ + arch/arm/bsp/CortexM/nmi.c \ +) + +# peripherals +bsp_drivers_SRC_GDB_INFO_y = arch/${vARCH}/timer/systick_gdb.s +bsp_drivers_SRC = $(strip \ + drivers/console/uart_console.c \ + arch/${vARCH}/timer/systick.c \ + drivers/serial/k20UartDrv.c \ + ${bsp_drivers_SRC_GDB_INFO_${CONFIG_GDB_INFO}} \ +) + +# configurable + +bsp_module_SRC_MICROKERNEL_y = $(strip \ +) + +bsp_modules_SRC = $(strip \ + ${bsp_module_SRC_MICROKERNEL_${CONFIG_MICROKERNEL}} \ + ${bsp_module_SRC_RUNTIME_NMI_${CONFIG_RUNTIME_NMI}} \ +) + +# miscellaneous needed by kernel +bsp_misc_SRC = $(strip \ + arch/arm/bsp/sysFatalErrorHandler.c \ + arch/arm/bsp/rand32.c \ +) + +bsp_kernel_SRC = $(strip \ + ${bsp_arch_SRC} \ + ${bsp_init_SRC} \ + ${bsp_modules_SRC} \ + ${bsp_misc_SRC} \ +) + +bsp_SRC_IRQ_VECTOR_TABLE_y = ${vBSP_BASE_DIR}/${vBSP}/irq_vector_table.c +bsp_SRC_SW_ISR_TABLE_y = ${vBSP_BASE_DIR}/${vBSP}/sw_isr_table.c + +bsp_SRC = $(strip \ + ${vBSP_BASE_DIR}/${vBSP}/system.c \ + ${vBSP_BASE_DIR}/${vBSP}/nmi_on_reset.s \ + ${vBSP_BASE_DIR}/${vBSP}/wdog.s \ + ${bsp_SRC_IRQ_VECTOR_TABLE_${CONFIG_IRQ_VECTOR_TABLE_BSP}} \ + ${bsp_SRC_SW_ISR_TABLE_${CONFIG_SW_ISR_TABLE_BSP}} \ + $(foreach src,${bsp_kernel_SRC},$(addprefix ${vBASE}/,${src})) \ + $(foreach src,${bsp_drivers_SRC},$(addprefix ${vBASE}/,${src})) \ +) + +KLIBS += bsp diff --git a/arch/arm/fsl_frdm_k64f/irq_vector_table.c b/arch/arm/fsl_frdm_k64f/irq_vector_table.c new file mode 100644 index 00000000000..aecaed086b4 --- /dev/null +++ b/arch/arm/fsl_frdm_k64f/irq_vector_table.c @@ -0,0 +1,65 @@ +/* irq_vector_table.c - IRQ part of vector table */ + +/* + * Copyright (c) 2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This file contains the IRQ part of the vector table. It is meant to be used +for one of two cases: + +a) When software-managed ISRs (SW_ISR_TABLE) is enabled, and in that case it + binds _IsrWrapper() to all the IRQ entries in the vector table. + +b) When the BSP is written so that device ISRs are installed directly in the + vector table, they are enumerated here. +*/ + +#include +#include + +extern void _IsrWrapper(void); +typedef void (*vth)(void); /* Vector Table Handler */ + +#if defined(CONFIG_SW_ISR_TABLE) + +vth __irq_vector_table _IrqVectorTable[CONFIG_NUM_IRQS] = { + [0 ...(CONFIG_NUM_IRQS - 1)] = _IsrWrapper}; + +#elif !defined(CONFIG_IRQ_VECTOR_TABLE_CUSTOM) + +extern void _SpuriousIRQ(void); + +/* placeholders: fill with real ISRs */ + +vth __irq_vector_table _IrqVectorTable[CONFIG_NUM_IRQS] = { + [0 ...(CONFIG_NUM_IRQS - 1)] = _SpuriousIRQ}; + +#endif /* CONFIG_SW_ISR_TABLE */ diff --git a/arch/arm/fsl_frdm_k64f/linker.cmd b/arch/arm/fsl_frdm_k64f/linker.cmd new file mode 100644 index 00000000000..3b6f69de511 --- /dev/null +++ b/arch/arm/fsl_frdm_k64f/linker.cmd @@ -0,0 +1,60 @@ +/* linker.cmd - Linker command/script file */ + +/* + * Copyright (c) 2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This is the linker script for both standard images and XIP images. +*/ + +/* Flash base address and size */ +#define FLASH_START 0x00000000 +#define FLASH_SIZE 1M + +/* + * K64F Flash configuration fields + * These are 16 bytes, which must be loaded to address 0x400, and include + * default protection and security settings. + * They are loaded at reset to various Flash Memory module (FTFE) registers. + */ +#define SKIP_TO_SECURITY_FRDM_K64F . = 0x400; + +/* + * SRAM base address and size + * + * Although the K64F CPU has a 64 KB region of SRAM at 0x1FFF0000, it is not + * used by this BSP. Only the 192 KB region based at the standard ARMv7-M + * SRAM base address of 0x20000000 is supported. + */ +#define SRAM_START 0x20000000 /* 192K in SRAM space */ +#define SRAM_SIZE 192K + +#include diff --git a/arch/arm/fsl_frdm_k64f/nmi_on_reset.s b/arch/arm/fsl_frdm_k64f/nmi_on_reset.s new file mode 100644 index 00000000000..1ae195af857 --- /dev/null +++ b/arch/arm/fsl_frdm_k64f/nmi_on_reset.s @@ -0,0 +1,53 @@ +/* nmi_on_reset.s - default basic NMI handler before the kernel is up */ + +/* + * Copyright (c) 2013-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +Provide a default handler for NMI before the system is up. The default action +is to hard hang, sleeping. + +This might be preferable than rebooting to help debugging, or because +rebooting might trigger the exact same problem over and over. +*/ + +#define _ASMLANGUAGE + +#include +#include + +_ASM_FILE_PROLOGUE + +GTEXT(_SysNmiOnReset) + +SECTION_FUNC(TEXT, _SysNmiOnReset) + wfi + b _SysNmiOnReset diff --git a/arch/arm/fsl_frdm_k64f/sw_isr_table.c b/arch/arm/fsl_frdm_k64f/sw_isr_table.c new file mode 100644 index 00000000000..722ab041486 --- /dev/null +++ b/arch/arm/fsl_frdm_k64f/sw_isr_table.c @@ -0,0 +1,64 @@ +/* sw_isr_table.c - Software ISR table for fsl_frdm_k64f BSP */ + +/* + * Copyright (c) 2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This contains the ISR table meant to be used for ISRs that take a parameter. +It is also used when ISRs are to be connected at runtime, and in this case +provides a table that is filled with _SpuriousIRQ bindings. +*/ + +#include +#include +#include + +extern void _SpuriousIRQ(void *arg); + +#if defined(CONFIG_SW_ISR_TABLE_DYNAMIC) + +_IsrTableEntry_t __isr_table_section _IsrTable[CONFIG_NUM_IRQS] = { + [0 ...(CONFIG_NUM_IRQS - 1)].arg = (void *)0xABAD1DEA, + [0 ...(CONFIG_NUM_IRQS - 1)].isr = _SpuriousIRQ}; + +#else +#if defined(CONFIG_SW_ISR_TABLE) +#if !defined(CONFIG_SW_ISR_TABLE_STATIC_CUSTOM) + +/* placeholders: fill with real ISRs */ + +_IsrTableEntry_t __isr_table_section _IsrTable[CONFIG_NUM_IRQS] = { + [0 ...(CONFIG_NUM_IRQS - 1)].arg = (void *)0xABAD1DEA, + [0 ...(CONFIG_NUM_IRQS - 1)].isr = _SpuriousIRQ}; + +#endif +#endif +#endif diff --git a/arch/arm/fsl_frdm_k64f/system.c b/arch/arm/fsl_frdm_k64f/system.c new file mode 100644 index 00000000000..7118cacde18 --- /dev/null +++ b/arch/arm/fsl_frdm_k64f/system.c @@ -0,0 +1,381 @@ +/* system.c - system/hardware module for fsl_frdm_k64f BSP */ + +/* + * Copyright (c) 2014-2015 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This module provides routines to initialize and support board-level hardware +for the fsl_frdm_k64f BSP. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(CONFIG_PRINTK) || defined(CONFIG_STDOUT_CONSOLE) +#define DO_CONSOLE_INIT +#endif + +/* board's setting for PLL multipler (PRDIV0) */ +#define FRDM_K64F_PLL_DIV_20 (20 - 1) + +/* board's setting for PLL multipler (VDIV0) */ +#define FRDM_K64F_PLL_MULT_48 (48 - 24) + +#ifdef CONFIG_RUNTIME_NMI +extern void _NmiInit(void); +#define NMI_INIT() _NmiInit() +#else +#define NMI_INIT() +#endif + +/* + * K64F Flash configuration fields + * These 16 bytes, which must be loaded to address 0x400, include default + * protection and security settings. + * They are loaded at reset to various Flash Memory module (FTFE) registers. + * + * The structure is: + * -Backdoor Comparison Key for unsecuring the MCU - 8 bytes + * -Program flash protection bytes, 4 bytes, written to FPROT0-3 + * -Flash security byte, 1 byte, written to FSEC + * -Flash nonvolatile option byte, 1 byte, written to FOPT + * -Reserved, 1 byte, (Data flash protection byte for FlexNVM) + * -Reserved, 1 byte, (EEPROM protection byte for FlexNVM) + * + */ +uint8_t __security_frdm_k64f_section __security_frdm_k64f[] = { + /* Backdoor Comparison Key (unused) */ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /* Program flash protection; 1 bit/region - 0=protected, 1=unprotected + */ + 0xFF, 0xFF, 0xFF, 0xFF, + /* + * Flash security: Backdoor key disabled, Mass erase enabled, + * Factory access enabled, MCU is unsecure + */ + 0xFE, + /* Flash nonvolatile option: NMI enabled, EzPort enabled, Normal boot */ + 0xFF, + /* Reserved for FlexNVM feature (unsupported by this MCU) */ + 0xFF, 0xFF}; + +/******************************************************************************* +* +* clkInit - initialize the system clock +* +* This routine will configure the multipurpose clock generator (MCG) to +* set up the system clock. +* The MCG has nine possible modes, including Stop mode. This routine assumes +* that the current MCG mode is FLL Engaged Internal (FEI), as from reset. +* It transitions through the FLL Bypassed External (FBE) and +* PLL Bypassed External (PBE) modes to get to the desired +* PLL Engaged External (PEE) mode and generate the maximum 120 MHz system clock. +* +* RETURNS: N/A +* +*/ + +static void clkInit(void) +{ + uint8_t temp_reg; + K20_MCG_t *mcg_p = (K20_MCG_t *)PERIPH_ADDR_BASE_MCG; /* clk gen. ctl */ + + /* + * Select the 50 Mhz external clock as the MCG OSC clock. + * MCG Control 7 register: + * - Select OSCCLK0 / XTAL + */ + + temp_reg = mcg_p->c7 & ~MCG_C7_OSCSEL_MASK; + temp_reg |= MCG_C7_OSCSEL_OSC0; + mcg_p->c7 = temp_reg; + + /* + * Transition MCG from FEI mode (at reset) to FBE mode. + */ + + /* + * MCG Control 2 register: + * - Set oscillator frequency range = very high for 50 MHz external + * clock + * - Set oscillator mode = low power + * - Select external reference clock as the oscillator source + */ + + temp_reg = mcg_p->c2 & + ~(MCG_C2_RANGE_MASK | MCG_C2_HGO_MASK | MCG_C2_EREFS_MASK); + + temp_reg |= + (MCG_C2_RANGE_VHIGH | MCG_C2_HGO_LO_PWR | MCG_C2_EREFS_EXT_CLK); + + mcg_p->c2 = temp_reg; + + /* + * MCG Control 1 register: + * - Set system clock source (MCGOUTCLK) = external reference clock + * - Set FLL external reference divider = 1024 (MCG_C1_FRDIV_32_1024) + * to get the FLL frequency of 50 MHz/1024 = 48.828KHz + * (Note: If FLL frequency must be in the in 31.25KHz-39.0625KHz + *range, + * the FLL external reference divider = 1280 + *(MCG_C1_FRDIV_64_1280) + * to get 50 MHz/1280 = 39.0625KHz) + * - Select the external reference clock as the FLL reference source + * + */ + + temp_reg = mcg_p->c1 & + ~(MCG_C1_CLKS_MASK | MCG_C1_FRDIV_MASK | MCG_C1_IREFS_MASK); + + temp_reg |= + (MCG_C1_CLKS_EXT_REF | MCG_C1_FRDIV_32_1024 | MCG_C1_IREFS_EXT); + + mcg_p->c1 = temp_reg; + + /* Confirm that the external reference clock is the FLL reference source + */ + + while ((mcg_p->s & MCG_S_IREFST_MASK) != 0) + ; + ; + + /* Confirm the external ref. clock is the system clock source + * (MCGOUTCLK) */ + + while ((mcg_p->s & MCG_S_CLKST_MASK) != MCG_S_CLKST_EXT_REF) + ; + ; + + /* + * Transition to PBE mode. + * Configure the PLL frequency in preparation for PEE mode. + * The goal is PEE mode with a 120 MHz system clock source (MCGOUTCLK), + * which is calculated as (oscillator clock / PLL divider) * PLL + * multiplier, + * where oscillator clock = 50MHz, PLL divider = 20 and PLL multiplier = + * 48. + */ + + /* + * MCG Control 5 register: + * - Set the PLL divider + */ + + temp_reg = mcg_p->c5 & ~MCG_C5_PRDIV0_MASK; + + temp_reg |= FRDM_K64F_PLL_DIV_20; + + mcg_p->c5 = temp_reg; + + /* + * MCG Control 6 register: + * - Select PLL as output for PEE mode + * - Set the PLL multiplier + */ + + temp_reg = mcg_p->c6 & ~(MCG_C6_PLLS_MASK | MCG_C6_VDIV0_MASK); + + temp_reg |= (MCG_C6_PLLS_PLL | FRDM_K64F_PLL_MULT_48); + + mcg_p->c6 = temp_reg; + + /* Confirm that the PLL clock is selected as the PLL output */ + + while ((mcg_p->s & MCG_S_PLLST_MASK) == 0) + ; + ; + + /* Confirm that the PLL has acquired lock */ + + while ((mcg_p->s & MCG_S_LOCK0_MASK) == 0) + ; + ; + + /* + * Transition to PEE mode. + * MCG Control 1 register: + * - Select PLL as the system clock source (MCGOUTCLK) + */ + + temp_reg = mcg_p->c1 & ~MCG_C1_CLKS_MASK; + + temp_reg |= MCG_C1_CLKS_FLL_PLL; + + mcg_p->c1 = temp_reg; + + /* Confirm that the PLL output is the system clock source (MCGOUTCLK) */ + + while ((mcg_p->s & MCG_S_CLKST_MASK) != MCG_S_CLKST_PLL) + ; + ; +} + +#if defined(DO_CONSOLE_INIT) + +/******************************************************************************* +* +* consoleInit - initialize target-only console +* +* Only used for debugging. +* +* RETURNS: N/A +* +*/ + +#include "console/uart_console.h" + +static void consoleInit(void) +{ + uint32_t port; + uint32_t rxPin; + uint32_t txPin; + K20_PCR_t pcr = {0}; /* Pin Control Register */ + + /* Port/pin ctrl module */ + K20_PORT_PCR_t *port_pcr_p = (K20_PORT_PCR_t *)PERIPH_ADDR_BASE_PCR; + + struct uart_init_info info = { + .baud_rate = CONFIG_UART_CONSOLE_BAUDRATE, + .regs = CONFIG_UART_CONSOLE_REGS, + .sys_clk_freq = CONFIG_UART_CONSOLE_CLK_FREQ, + /* Only supported in polling mode, but init all info fields */ + .irq = CONFIG_UART_CONSOLE_IRQ, + .int_pri = CONFIG_UART_CONSOLE_INT_PRI + }; + + /* UART0 Rx and Tx pin assignments */ + port = CONFIG_UART_CONSOLE_PORT; + rxPin = CONFIG_UART_CONSOLE_PORT_RX_PIN; + txPin = CONFIG_UART_CONSOLE_PORT_TX_PIN; + + /* Enable the UART Rx and Tx Pins */ + pcr.field.mux = CONFIG_UART_CONSOLE_PORT_MUX_FUNC; + + port_pcr_p->port[port].pcr[rxPin] = pcr; + port_pcr_p->port[port].pcr[txPin] = pcr; + + uart_init(CONFIG_UART_CONSOLE_INDEX, &info); + + uartConsoleInit(); +} + +#else +#define consoleInit() \ + do {/* nothing */ \ + } while ((0)) +#endif /* DO_CONSOLE_INIT */ + +/******************************************************************************* +* +* _InitHardware - perform basic hardware initialization +* +* Initialize the interrupt controller device drivers and the +* Kinetis UART device driver. +* Also initialize the timer device driver, if required. +* +* RETURNS: N/A +*/ + +void _InitHardware(void) +{ + /* System Integration module */ + K20_SIM_t *sim_p = (K20_SIM_t *)PERIPH_ADDR_BASE_SIM; + + /* Power Mgt Control module */ + K6x_PMC_t *pmc_p = (K6x_PMC_t *)PERIPH_ADDR_BASE_PMC; + + /* Power Mgt Control module */ + K6x_MPU_t *mpu_p = (K6x_MPU_t *)PERIPH_ADDR_BASE_MPU; + + int oldLevel; /* old interrupt lock level */ + uint32_t temp_reg; + + /* disable interrupts */ + oldLevel = irq_lock(); + + /* enable the port clocks */ + sim_p->scgc5.value |= (SIM_SCGC5_PORTA_CLK_EN | SIM_SCGC5_PORTB_CLK_EN | + SIM_SCGC5_PORTC_CLK_EN | SIM_SCGC5_PORTD_CLK_EN | + SIM_SCGC5_PORTE_CLK_EN); + + /* release I/O power hold to allow normal run state */ + pmc_p->regsc.value |= PMC_REGSC_ACKISO_MASK; + + /* + * Disable memory protection and clear slave port errors. + * Note that the K64F does not implement the optional ARMv7-M memory + * protection unit (MPU), specified by the architecture (PMSAv7), in the + * Cortex-M4 core. Instead, the processor includes its own MPU module. + */ + temp_reg = mpu_p->ctrlErrStatus.value; + temp_reg &= ~MPU_VALID_MASK; + temp_reg |= MPU_SLV_PORT_ERR_MASK; + mpu_p->ctrlErrStatus.value = temp_reg; + + /* clear all faults */ + + _ScbMemFaultAllFaultsReset(); + _ScbBusFaultAllFaultsReset(); + _ScbUsageFaultAllFaultsReset(); + + _ScbHardFaultAllFaultsReset(); + + /* + * Initialize the clock dividers for: + * core and system clocks = 120 MHz (PLL/OUTDIV1) + * bus clock = 60 MHz (PLL/OUTDIV2) + * FlexBus clock = 40 MHz (PLL/OUTDIV3) + * Flash clock = 24 MHz (PLL/OUTDIV4) + */ + sim_p->clkdiv1.value = ((SIM_CLKDIV(1) << SIM_CLKDIV1_OUTDIV1_SHIFT) | + (SIM_CLKDIV(2) << SIM_CLKDIV1_OUTDIV2_SHIFT) | + (SIM_CLKDIV(3) << SIM_CLKDIV1_OUTDIV3_SHIFT) | + (SIM_CLKDIV(5) << SIM_CLKDIV1_OUTDIV4_SHIFT)); + + clkInit(); /* Initialize PLL/system clock to 120 MHz */ + + consoleInit(); /* NOP if not needed */ + + NMI_INIT(); /* install default handler that simply resets the CPU + * if configured in the kernel, NOP otherwise */ + + /* restore interrupt state */ + irq_unlock(oldLevel); +} diff --git a/arch/arm/fsl_frdm_k64f/wdog.s b/arch/arm/fsl_frdm_k64f/wdog.s new file mode 100644 index 00000000000..828301e26d7 --- /dev/null +++ b/arch/arm/fsl_frdm_k64f/wdog.s @@ -0,0 +1,104 @@ +/* wdog.s - watchdog initialization for fsl_frdm_k64f BSP */ + +/* + * Copyright (c) 2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This module initializes the watchdog for the fsl_frdm_k64f BSP. +*/ + +#define _ASMLANGUAGE + +#include +#include +#include + +_ASM_FILE_PROLOGUE + +GTEXT(_WdogInit) + +/* watchdog register offsets */ +#define WDOG_SCTRL_HI_OFFSET 0x0 +#define WDOG_UNLOCK_OFFSET 0xE + +/* watchdog command words */ +#define WDOG_UNLOCK_1_CMD 0xC520 +#define WDOG_UNLOCK_2_CMD 0xD928 + +/******************************************************************************* + * + * _WdogInit - Watchdog timer disable routine + * + * This routine will disable the watchdog timer. + * + * RETURNS: N/A + */ + +SECTION_FUNC(TEXT,_WdogInit) + /* + * NOTE: DO NOT SINGLE STEP THROUGH THIS FUNCTION!!! + * There are timing requirements for the execution of the unlock process. + * Single stepping through the code will cause the CPU to reset. + */ + + /* + * First unlock the watchdog so that we can write to registers. + * + * This sequence must execute within 20 clock cycles, so disable + * interrupts to keep the code atomic and ensure the timing. + */ + + cpsid i + + ldr r0, =PERIPH_ADDR_BASE_WDOG + + movw r1, #WDOG_UNLOCK_1_CMD + strh r1, [r0, #WDOG_UNLOCK_OFFSET] + + movw r1, #WDOG_UNLOCK_2_CMD + strh r1, [r0, #WDOG_UNLOCK_OFFSET] + + /* + * Disable the watchdog. + * + * Writes to control/configuration registers must execute within + * 256 clock cycles after unlocking. + */ + + ldrh r1, [r0, #WDOG_SCTRL_HI_OFFSET] + mov r2, #1 + bics r1, r2 + strh r1, [r0, #WDOG_SCTRL_HI_OFFSET] + + cpsie i + + bx lr + diff --git a/arch/arm/include/CortexM/exc.h b/arch/arm/include/CortexM/exc.h new file mode 100644 index 00000000000..e4675081563 --- /dev/null +++ b/arch/arm/include/CortexM/exc.h @@ -0,0 +1,123 @@ +/* exc.h - exception/interrupt context helpers for Cortex-M CPUs */ + +/* + * Copyright (c) 2013-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +Exception/interrupt context helpers. +*/ + +#ifndef _ARM_CORTEXM_ISR__H_ +#define _ARM_CORTEXM_ISR__H_ + +#include + +#ifdef _ASMLANGUAGE + +/* nothing */ + +#else + +/******************************************************************************* +* +* _IpsrGet - obtain value of IPSR register +* +* Obtain and return current value of IPSR register. +* +* RETURNS: the contents of the IPSR register +* +* \NOMANUAL +*/ + +#if defined(__GNUC__) +static ALWAYS_INLINE uint32_t _IpsrGet(void) +{ + uint32_t vector; + __asm__ volatile("mrs %0, IPSR\n\t" : "=r"(vector)); + return vector; +} +#elif defined(__DCC__) +__asm volatile uint32_t _IpsrGet(void) +{ + % !"r0" mrs r0, IPSR +} +#endif + +/******************************************************************************* +* +* _IsInIsr - find out if running in an ISR context +* +* The current executing vector is found in the IPSR register. We consider the +* IRQs (exception 16 and up), and the PendSV and SYSTICK exceptions, to be +* interrupts. Taking a fault within an exception is also considered in +* interrupt context. +* +* RETURNS: 1 if in ISR, 0 if not. +* +* \NOMANUAL +*/ +static ALWAYS_INLINE int _IsInIsr(void) +{ + uint32_t vector = _IpsrGet(); + + /* IRQs + PendSV + SYSTICK are interrupts */ + return (vector > 13) || (vector && _ScbIsNestedExc()); +} + +/******************************************************************************* +* _ExcSetup - setup system exceptions +* +* Set exception priorities to conform with the BASEPRI locking mechanism. +* Set PendSV priority to lowest possible. +* +* Enable fault exceptions. +* +* RETURNS: N/A +* +* \NOMANUAL +*/ + +static ALWAYS_INLINE void _ExcSetup(void) +{ + _ScbExcPrioSet(_EXC_PENDSV, _EXC_PRIO(0xff)); + _ScbExcPrioSet(_EXC_SVC, _EXC_PRIO(0x01)); + _ScbExcPrioSet(_EXC_MPU_FAULT, _EXC_PRIO(0x01)); + _ScbExcPrioSet(_EXC_BUS_FAULT, _EXC_PRIO(0x01)); + _ScbExcPrioSet(_EXC_USAGE_FAULT, _EXC_PRIO(0x01)); + + _ScbUsageFaultEnable(); + _ScbBusFaultEnable(); + _ScbMemFaultEnable(); +} + +#endif /* _ASMLANGUAGE */ + +#endif /* _ARM_CORTEXM_ISR__H_ */ diff --git a/arch/arm/include/CortexM/stack.h b/arch/arm/include/CortexM/stack.h new file mode 100644 index 00000000000..68619ef32d0 --- /dev/null +++ b/arch/arm/include/CortexM/stack.h @@ -0,0 +1,114 @@ +/* stack.h - stack helpers for Cortex-M CPUs */ + +/* + * Copyright (c) 2013-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +Stack helper functions. +*/ + +#ifndef _ARM_CORTEXM_STACK__H_ +#define _ARM_CORTEXM_STACK__H_ + +#include + +#ifdef CONFIG_STACK_GROWS_DOWN +#define STACK_DIR STACK_GROWS_DOWN +#else +#define STACK_DIR STACK_GROWS_UP +#endif + +#ifdef CONFIG_STACK_ALIGN_DOUBLE_WORD +#define STACK_ALIGN_SIZE 8 +#else +#define STACK_ALIGN_SIZE 4 +#endif + +#ifdef _ASMLANGUAGE + +/* nothing */ + +#else + +#if (STACK_DIR == STACK_GROWS_DOWN) +#define __GET_MSP() \ + STACK_ROUND_DOWN(&_InterruptStack[CONFIG_ISR_STACK_SIZE - 1]) +#else +#define __GET_MSP() STACK_ROUND_UP(&_InterruptStack[0]) +#endif + +extern char _InterruptStack[CONFIG_ISR_STACK_SIZE]; + +/******************************************************************************* +* +* _MspSet - set the value of the Main Stack Pointer register +* +* Store the value of in MSP register. +* +* RETURNS: N/A +* +* \NOMANUAL +*/ + +#if defined(__GNUC__) +static ALWAYS_INLINE void _MspSet(uint32_t msp /* value to store in MSP */ + ) +{ + __asm__ volatile("msr MSP, %0\n\t" : : "r"(msp)); +} +#elif defined(__DCC__) +__asm volatile void _MspSet(uint32_t msp) +{ + % reg msp !"r0" msr MSP, msp +} +#endif + +/******************************************************************************* +* +* _InterruptStackSetup - setup interrupt stack +* +* On Cortex-M, the interrupt stack is registered in the MSP (main stack +* pointer) register, and switched to automatically when taking an exception. +* +* RETURNS: N/A +* +* \NOMANUAL +*/ + +static ALWAYS_INLINE void _InterruptStackSetup(void) +{ + uint32_t msp = __GET_MSP(); + _MspSet(msp); +} + +#endif /* _ASMLANGUAGE */ + +#endif /* _ARM_CORTEXM_STACK__H_ */ diff --git a/arch/arm/include/nanok.h b/arch/arm/include/nanok.h new file mode 100644 index 00000000000..fdade0ab123 --- /dev/null +++ b/arch/arm/include/nanok.h @@ -0,0 +1,227 @@ +/* nanok.h - private nanokernel definitions (ARM) */ + +/* + * Copyright (c) 2013-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This file contains private nanokernel structures definitions and various other +definitions for the ARM Cortex-M3 processor architecture. + +This file is also included by assembly language files which must #define +_ASMLANGUAGE before including this header file. Note that nanokernel assembly +source files obtains structure offset values via "absolute symbols" in the +offsets.o module. +*/ + +#ifndef _NANOK__H_ +#define _NANOK__H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +#ifndef _ASMLANGUAGE +#include +#endif + +#ifndef _ASMLANGUAGE +struct coop { + /* + * Unused for Cortex-M, which automatically saves the neccesary + *registers + * in its exception stack frame. + * + * For Cortex-A, this may be: + * + * uint32_t a1; // r0 + * uint32_t a2; // r1 + * uint32_t a3; // r2 + * uint32_t a4; // r3 + * uint32_t ip; // r12 + * uint32_t lr; // r14 + * uint32_t pc; // r15 + * uint32_t xpsr; + */ +}; + +typedef struct __esf tESF; + +struct preempt { + uint32_t v1; /* r4 */ + uint32_t v2; /* r5 */ + uint32_t v3; /* r6 */ + uint32_t v4; /* r7 */ + uint32_t v5; /* r8 */ + uint32_t v6; /* r9 */ + uint32_t v7; /* r10 */ + uint32_t v8; /* r11 */ + uint32_t psp; /* r13 */ +}; + +typedef struct preempt tPreempt; + +#endif /* _ASMLANGUAGE */ + +/* Bitmask definitions for the tCCS->flags bit field */ + +#define FIBER 0x000 +#define TASK 0x001 /* 1 = task context, 0 = fiber context */ +#define INT_ACTIVE 0x002 /* 1 = context is executing interrupt handler */ +#define EXC_ACTIVE 0x004 /* 1 = context is executing exception handler */ +#define USE_FP 0x010 /* 1 = context uses floating point unit */ +#define PREEMPTIBLE \ + 0x020 /* 1 = preemptible context \ + * NOTE: the value must be < 0x100 to be able to \ + * use a small thumb instr with immediate \ + * when loading PREEMPTIBLE in a GPR \ + */ +#define ESSENTIAL 0x200 /* 1 = system context that must not abort */ +#define NO_METRICS 0x400 /* 1 = _Swap() not to update task metrics */ + +/* stacks */ + +#define STACK_GROWS_DOWN 0 +#define STACK_GROWS_UP 1 + +#define STACK_ROUND_UP(x) ROUND_UP(x, STACK_ALIGN_SIZE) +#define STACK_ROUND_DOWN(x) ROUND_DOWN(x, STACK_ALIGN_SIZE) + +#ifdef CONFIG_CPU_CORTEXM +#include +#include +#endif + +#ifndef _ASMLANGUAGE +struct s_CCS { + struct s_CCS *link; /* singly-linked list in _NanoKernel.fibers */ + uint32_t flags; + uint32_t basepri; + int prio; +#ifdef CONFIG_CONTEXT_CUSTOM_DATA + void *custom_data; /* available for custom use */ +#endif + struct coop coopReg; + struct preempt preempReg; +#if defined(CONFIG_HOST_TOOLS_SUPPORT) + struct s_CCS *activeLink; /* link to next context in the active list */ +#endif +}; + +struct s_NANO { + tCCS *fiber; /* singly linked list of runnable fiber contexts */ + tCCS *task; /* pointer to runnable task context */ + tCCS *current; /* currently scheduled context (fiber or task) */ + int flags; /* tCCS->flags of 'current' context */ + +#if defined(CONFIG_HOST_TOOLS_SUPPORT) + tCCS *contexts; /* singly linked list of ALL fiber+tasks */ +#endif + +#ifdef CONFIG_FP_SHARING + tCCS *current_fp; /* context (fiber or task) that owns the FP regs */ +#endif /* CONFIG_FP_SHARING */ + +#ifdef CONFIG_ADVANCED_POWER_MANAGEMENT + int32_t idle; /* Number of ticks for kernel idling */ +#endif /* CONFIG_ADVANCED_POWER_MANAGEMENT */ + +#if 0 /* not needed, MSP should only be loaded once at startup */ + char *common_isp; /* interrupt stack pointer base */ +#endif +}; + +typedef struct s_NANO tNANO; +extern tNANO _NanoKernel; + +#endif /* _ASMLANGUAGE */ + +#ifndef _ASMLANGUAGE +extern void _FaultInit(void); +extern void _CpuIdleInit(void); +static ALWAYS_INLINE void nanoArchInit(void) +{ + _NanoKernel.flags = FIBER; + _InterruptStackSetup(); + _ExcSetup(); + _FaultInit(); + _CpuIdleInit(); +} + +/******************************************************************************* +* +* fiberRtnValueSet - set the return value for the specified fiber (inline) +* +* The register used to store the return value from a function call invocation +* to . It is assumed that the specified is pending, and thus +* the fiber's context is stored in its tCCS structure. +* +* RETURNS: N/A +* +* \NOMANUAL +*/ + +static ALWAYS_INLINE void fiberRtnValueSet( + tCCS *fiber, /* pointer to fiber */ + unsigned int value /* value to set as return value */ + ) +{ + tESF *pEsf = (void *)fiber->preempReg.psp; + pEsf->a1 = value; +} + +extern void _InsertCCS(tCCS **, tCCS *); +extern void *_NewContext(char *, + unsigned, + _ContextEntry, + _ContextArg, + _ContextArg, + _ContextArg, + int, + unsigned); + +extern unsigned int _Swap(unsigned int); +extern void nano_cpu_atomic_idle(unsigned int); + +#define _IS_IN_ISR() _IsInIsr() + +extern void _IntLibInit(void); + +#endif /* _ASMLANGUAGE */ + +#ifdef __cplusplus +} +#endif + +#endif /* _NANOK__H_ */ diff --git a/arch/arm/include/start_task_arch.h b/arch/arm/include/start_task_arch.h new file mode 100644 index 00000000000..0e9edb9db7a --- /dev/null +++ b/arch/arm/include/start_task_arch.h @@ -0,0 +1,56 @@ +/* start_task.h - ARM nanokernel declarations to start a task */ + +/* + * Copyright (c) 2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +ARM-specific parts of start_task(). + +Currently empty, only here for abstraction. +*/ + +#ifndef _START_TASK_ARCH__H_ +#define _START_TASK_ARCH__H_ + +#include +#include + +#include +#include +#include +#include +#include + +#define _START_TASK_ARCH(pKproc, pOpt) \ + do {/* nothing */ \ + } while ((0)) + +#endif /* _START_TASK_ARCH__H_ */ diff --git a/arch/arm/ti_lm3s6965/board.h b/arch/arm/ti_lm3s6965/board.h new file mode 100644 index 00000000000..44d7dd9c739 --- /dev/null +++ b/arch/arm/ti_lm3s6965/board.h @@ -0,0 +1,149 @@ +/* board.h - board configuration macros for the ti_lm3s6965 BSP */ + +/* + * Copyright (c) 2013-2015 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This header file is used to specify and describe board-level aspects for +the 'ti_lm3s6965' BSP. +*/ + +#ifndef _BOARD__H_ +#define _BOARD__H_ + +#include + +#define SRAM_SIZE KB(64) + +/* default system clock */ + +#define SYSCLK_DEFAULT_IOSC_HZ MHZ(12) + +/* address bases */ + +#define PERIPH_ADDR_BASE_UART0 0x4000C000 +#define PERIPH_ADDR_BASE_UART1 0x4000D000 +#define PERIPH_ADDR_BASE_UART2 0x4000E000 + +/* IRQs */ + +#define IRQ_GPIO_PORTA 0 +#define IRQ_GPIO_PORTB 1 +#define IRQ_GPIO_PORTC 2 +#define IRQ_GPIO_PORTD 3 +#define IRQ_GPIO_PORTE 4 +#define IRQ_UART0 5 +#define IRQ_UART1 6 +#define IRQ_SSI0 7 +#define IRQ_I2C0 8 +#define IRQ_PWM_FAULT 9 +#define IRQ_PWM_GEN0 10 +#define IRQ_PWM_GEN1 11 +#define IRQ_PWM_GEN2 12 +#define IRQ_QEI0 13 +#define IRQ_ADC0_SEQ0 14 +#define IRQ_ADC0_SEQ1 15 +#define IRQ_ADC0_SEQ2 16 +#define IRQ_ADC0_SEQ3 17 +#define IRQ_WDOG0 18 +#define IRQ_TIMER0A 19 +#define IRQ_TIMER0B 20 +#define IRQ_TIMER1A 21 +#define IRQ_TIMER1B 22 +#define IRQ_TIMER2A 23 +#define IRQ_TIMER2B 24 +#define IRQ_ANALOG_COMP0 25 +#define IRQ_ANALOG_COMP1 26 +#define IRQ_RESERVED0 27 +#define IRQ_SYS_CONTROL 28 +#define IRQ_FLASH_MEM_CTRL 29 +#define IRQ_GPIO_PORTF 30 +#define IRQ_GPIO_PORTG 31 +#define IRQ_RESERVED1 32 +#define IRQ_UART2 33 +#define IRQ_RESERVED2 34 +#define IRQ_TIMER3A 35 +#define IRQ_TIMER3B 36 +#define IRQ_I2C1 37 +#define IRQ_QEI1 38 +#define IRQ_RESERVED3 39 +#define IRQ_RESERVED4 40 +#define IRQ_RESERVED5 41 +#define IRQ_ETH 42 +#define IRQ_HIBERNATION 43 + +#ifndef _ASMLANGUAGE + +#include +#include + +/* uart configuration settings */ + +#define CONFIG_UART_NUM_SYSTEM_PORTS 2 +#define CONFIG_UART_NUM_EXTRA_PORTS 1 +#define CONFIG_UART_NUM_PORTS \ + (CONFIG_UART_NUM_SYSTEM_PORTS + CONFIG_UART_NUM_EXTRA_PORTS) + +#define CONFIG_UART_CONSOLE_INDEX 0 +#define CONFIG_UART_CONSOLE_BAUDRATE 115200 +#define CONFIG_UART_CONSOLE_IRQ IRQ_UART0 +#define CONFIG_UART_CONSOLE_INT_PRI 3 +#define CONFIG_UART_CONSOLE_REGS PERIPH_ADDR_BASE_UART0 + +#define EXC_FROM_IRQ(irq) ((irq) + 16) +#define VECTOR_FROM_IRQ(irq) EXC_FROM_IRQ(irq) +#define VECTOR_ADDR(vector) ((uint32_t *)((int)vector << 2)) + +/* + * Device drivers utilize the macros PLB_BYTE_REG_WRITE() and + * PLB_BYTE_REG_READ() to access byte-wide registers on the processor + * local bus (PLB), as opposed to a PCI bus, for example. Boards are + * expected to provide implementations of these macros. + */ + +static inline void __plbByteRegWrite(unsigned char data, unsigned char *pAddr) +{ + *pAddr = data; +} + +#define PLB_BYTE_REG_WRITE(data, address) \ + __plbByteRegWrite((unsigned char)data, (unsigned char *)address) + +static inline unsigned char __plbByteRegRead(unsigned char *pAddr) +{ + return *pAddr; +} + +#define PLB_BYTE_REG_READ(address) __plbByteRegRead((unsigned char *)address) + +#endif /* !_ASMLANGUAGE */ + +#endif /* _BOARD__H_ */ diff --git a/arch/arm/ti_lm3s6965/defs.objs b/arch/arm/ti_lm3s6965/defs.objs new file mode 100644 index 00000000000..4b344f1ab80 --- /dev/null +++ b/arch/arm/ti_lm3s6965/defs.objs @@ -0,0 +1,102 @@ +# defs.objs - build system + +# +# Copyright (c) 2015 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors +# may be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. +# + +bsp_INCLUDE_DIR = $(strip \ + ${vBASE}/kernel/common/bsp \ + ${vBASE}/include/bsp \ + ${vBASE}/include \ + ${vBASE}/arch/${vARCH} \ + ${vBASE}/drivers \ + ${vBSP_BASE_DIR}/${vBSP} \ +) + +# initialization +bsp_init_SRC = $(strip \ + arch/arm/bsp/CortexM/vector_table.s \ + arch/arm/bsp/CortexM/reset.s \ + arch/arm/bsp/CortexM/prep_c.c \ + kernel/common/bsp/init.c \ + kernel/common/bsp/ctors.c \ +) + +# peripherals +bsp_arch_SRC = $(strip \ + arch/arm/bsp/CortexM/scs.c \ + arch/arm/bsp/CortexM/scb.c \ + arch/arm/bsp/CortexM/nmi.c \ +) + +bsp_drivers_SRC_GDB_INFO_y = arch/${vARCH}/timer/systick_gdb.s +bsp_drivers_SRC = $(strip \ + arch/${vARCH}/timer/systick.c \ + drivers/serial/stellarisUartDrv.c \ + drivers/console/uart_console.c \ + ${bsp_drivers_SRC_GDB_INFO_${CONFIG_GDB_INFO}} \ +) + +# configurable + +bsp_module_SRC_MICROKERNEL_y = $(strip \ +) + +bsp_modules_SRC = $(strip \ + ${bsp_module_SRC_MICROKERNEL_${CONFIG_MICROKERNEL}} \ + ${bsp_module_SRC_RUNTIME_NMI_${CONFIG_RUNTIME_NMI}} \ +) + +# miscellaneous needed by kernel +bsp_misc_SRC = $(strip \ + arch/arm/bsp/sysFatalErrorHandler.c \ + arch/arm/bsp/rand32.c \ +) + +bsp_kernel_SRC = $(strip \ + ${bsp_init_SRC} \ + ${bsp_arch_SRC} \ + ${bsp_modules_SRC} \ + ${bsp_misc_SRC} \ +) + +bsp_SRC_IRQ_VECTOR_TABLE_y = ${vBSP_BASE_DIR}/${vBSP}/irq_vector_table.c +bsp_SRC_SW_ISR_TABLE_y = ${vBSP_BASE_DIR}/${vBSP}/sw_isr_table.c + +bsp_SRC = $(strip \ + ${vBSP_BASE_DIR}/${vBSP}/system.c \ + ${vBSP_BASE_DIR}/${vBSP}/nmi_on_reset.s \ + ${vBSP_BASE_DIR}/${vBSP}/scp.c \ + ${bsp_SRC_IRQ_VECTOR_TABLE_${CONFIG_IRQ_VECTOR_TABLE_BSP}} \ + ${bsp_SRC_SW_ISR_TABLE_${CONFIG_SW_ISR_TABLE_BSP}} \ + $(foreach src,${bsp_kernel_SRC},$(addprefix ${vBASE}/,${src})) \ + $(foreach src,${bsp_drivers_SRC},$(addprefix ${vBASE}/,${src})) \ +) + +KLIBS += bsp diff --git a/arch/arm/ti_lm3s6965/irq_vector_table.c b/arch/arm/ti_lm3s6965/irq_vector_table.c new file mode 100644 index 00000000000..9e54a5c09a1 --- /dev/null +++ b/arch/arm/ti_lm3s6965/irq_vector_table.c @@ -0,0 +1,67 @@ +/* irq_vector_table.c - IRQ part of vector table */ + +/* + * Copyright (c) 2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This file contains the IRQ part of the vector table. It is meant to be used +for one of two cases: + +a) When software-managed ISRs (SW_ISR_TABLE) is enabled, and in that case it + binds _IsrWrapper() to all the IRQ entries in the vector table. + +b) When the BSP is written so that device ISRs are installed directly in the + vector table, they are enumerated here. +*/ + +#include +#include + +extern void _IsrWrapper(void); +typedef void (*vth)(void); /* Vector Table Handler */ + +#if defined(CONFIG_SW_ISR_TABLE) + +vth __irq_vector_table _IrqVectorTable[CONFIG_NUM_IRQS] = { + [0 ...(CONFIG_NUM_IRQS - 1)] = _IsrWrapper +}; + +#elif !defined(CONFIG_IRQ_VECTOR_TABLE_CUSTOM) + +extern void _SpuriousIRQ(void); + +/* placeholders: fill with real ISRs */ + +vth __irq_vector_table _IrqVectorTable[CONFIG_NUM_IRQS] = { + [0 ...(CONFIG_NUM_IRQS - 1)] = _SpuriousIRQ +}; + +#endif /* CONFIG_SW_ISR_TABLE */ diff --git a/arch/arm/ti_lm3s6965/linker.cmd b/arch/arm/ti_lm3s6965/linker.cmd new file mode 100644 index 00000000000..bb8abfb57c9 --- /dev/null +++ b/arch/arm/ti_lm3s6965/linker.cmd @@ -0,0 +1,38 @@ +/* linker.cmd - Linker command/script file */ + +/* + * Copyright (c) 2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +#define FLASH_START 0x00000000 +#define SRAM_START 0x20000000 +#define FLASH_SIZE 256K +#define SRAM_SIZE 64K + +#include diff --git a/arch/arm/ti_lm3s6965/nmi_on_reset.s b/arch/arm/ti_lm3s6965/nmi_on_reset.s new file mode 100644 index 00000000000..1ae195af857 --- /dev/null +++ b/arch/arm/ti_lm3s6965/nmi_on_reset.s @@ -0,0 +1,53 @@ +/* nmi_on_reset.s - default basic NMI handler before the kernel is up */ + +/* + * Copyright (c) 2013-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +Provide a default handler for NMI before the system is up. The default action +is to hard hang, sleeping. + +This might be preferable than rebooting to help debugging, or because +rebooting might trigger the exact same problem over and over. +*/ + +#define _ASMLANGUAGE + +#include +#include + +_ASM_FILE_PROLOGUE + +GTEXT(_SysNmiOnReset) + +SECTION_FUNC(TEXT, _SysNmiOnReset) + wfi + b _SysNmiOnReset diff --git a/arch/arm/ti_lm3s6965/scp.c b/arch/arm/ti_lm3s6965/scp.c new file mode 100644 index 00000000000..f9675665bc4 --- /dev/null +++ b/arch/arm/ti_lm3s6965/scp.c @@ -0,0 +1,68 @@ +/* scp.c - TI LM3S6965 System Control Peripherals interface */ + +/* + * Copyright (c) 2013-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION + +Library for controlling target-specific devices present in the 0x400fe000 +peripherals memory region. + +Currently, only enabling the main OSC with default value is implemented. +*/ + +#include +#include +#include + +#include "scp.h" + +/* System Control Peripheral (SCP) Registers */ + +volatile struct __scp __scp_section __scp; + +/******************************************************************************* +* +* _ScpMainOscEnable - enable main oscillator with default frequency of 6MHz +* +* RETURNS: N/A +*/ +void _ScpMainOscEnable(void) +{ + union __rcc reg; + + reg.value = __scp.clock.rcc.value; + reg.bit.moscdis = 0; + reg.bit.oscsrc = _SCP_OSC_SOURCE_MAIN; + reg.bit.xtal = _SCP_CRYSTAL_6MHZ; + + __scp.clock.rcc.value = reg.value; +} diff --git a/arch/arm/ti_lm3s6965/scp.h b/arch/arm/ti_lm3s6965/scp.h new file mode 100644 index 00000000000..02f4ec80486 --- /dev/null +++ b/arch/arm/ti_lm3s6965/scp.h @@ -0,0 +1,179 @@ +/* scp.h - TI LM3S6965 System Control Peripherals interface */ + +/* + * Copyright (c) 2013-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This module defines the System Control Peripheral Registers for TI LM3S6965 +processor. The registers defined are in region 0x400fe000. + + System Control 0x400fe000 + +These modules are not defined: + + Hibernation Module 0x400fc000 + Internal Memory 0x400fd000 + Hibernation Module 0x400fc000 + +The registers and bit field names are taken from the 'Stellaris LM3S6965 +Microcontroller DATA SHEET (DS-LM3S6965-12746.2515) revision H' document, +section 5.4/5.5, pp .184-200. +*/ + +#ifndef _SCP_H_ +#define _SCP_H_ + +#include + +#define _SCP_OSC_SOURCE_MAIN 0 +#define _SCP_OSC_SOURCE_INTERNAL 1 +#define _SCP_OSC_SOURCE_INTERNAL_DIV4 2 +#define _SCP_OSC_SOURCE_INTERNAL_20KHZ 3 +#define _SCP_OSC_SOURCE_EXTERNAL_32KHZ 7 /* Valid with RCC2 only */ + +#define _SCP_CRYSTAL_1MHZ_NOPLL 0 +#define _SCP_CRYSTAL_1_8432MHZ_NOPLL 1 +#define _SCP_CRYSTAL_2MHZ_NOPLL 2 +#define _SCP_CRYSTAL_2_4576MHZ_NOPLL 3 +#define _SCP_CRYSTAL_3_579545MHZ 4 +#define _SCP_CRYSTAL_3_6864MHZ 5 +#define _SCP_CRYSTAL_4MHZ 6 +#define _SCP_CRYSTAL_4_0964MHZ 7 +#define _SCP_CRYSTAL_4_9152MHZ 8 +#define _SCP_CRYSTAL_5MHZ 9 +#define _SCP_CRYSTAL_5_12MHZ 10 +#define _SCP_CRYSTAL_6MHZ 11 /* reset value */ +#define _SCP_CRYSTAL_6_144MHZ 12 +#define _SCP_CRYSTAL_7_3728MHZ 13 +#define _SCP_CRYSTAL_8MHZ 14 +#define _SCP_CRYSTAL_8_192MHZ 15 + +union __rcc { + uint32_t value; + struct { + uint32_t moscdis : 1 __attribute__((packed)); + uint32_t ioscdis : 1 __attribute__((packed)); + uint32_t rsvd__2_3 : 2 __attribute__((packed)); + uint32_t oscsrc : 2 __attribute__((packed)); + uint32_t xtal : 4 __attribute__((packed)); + uint32_t rsvd__10 : 1 __attribute__((packed)); + uint32_t bypass : 1 __attribute__((packed)); + uint32_t rsvd__12 : 1 __attribute__((packed)); + uint32_t pwrdn : 1 __attribute__((packed)); + uint32_t rsvd__14_16 : 3 __attribute__((packed)); + uint32_t pwmdiv : 3 __attribute__((packed)); /* 2**(n+1) */ + uint32_t usepwmdiv : 1 __attribute__((packed)); + uint32_t rsvd__21 : 1 __attribute__((packed)); + uint32_t usesysdiv : 1 __attribute__((packed)); + uint32_t sysdiv : 4 __attribute__((packed)); + uint32_t acg : 1 __attribute__((packed)); + uint32_t rsvd__28_31 : 4 __attribute__((packed)); + } bit; +}; + +union __rcc2 { + uint32_t value; + struct { + uint8_t rsvd__0_3 : 4 __attribute__((packed)); + uint8_t oscsrc2 : 3 __attribute__((packed)); + uint16_t rsvd__7_10 : 4 __attribute__((packed)); + uint8_t bypass2 : 1 __attribute__((packed)); + uint8_t rsvd__12 : 1 __attribute__((packed)); + uint8_t pwrdn2 : 1 __attribute__((packed)); + uint16_t rsvd__14_22 : 9 __attribute__((packed)); + uint16_t sysdiv2 : 6 __attribute__((packed)); + uint8_t rsvd__29_30 : 2 __attribute__((packed)); + uint8_t usercc2 : 1 __attribute__((packed)); + } bit; +}; + +struct __scp { + uint32_t did0; /* 0x000 RO Device ID*/ + uint32_t did1; /* 0x004 RO Device ID*/ + uint32_t dc0; /* 0x008 RO Device Capabilities */ + uint32_t dc1; /* 0x00c RO Device Capabilities */ + uint32_t dc2; /* 0x010 RO Device Capabilities */ + uint32_t dc3; /* 0x014 RO Device Capabilities */ + uint32_t dc4; /* 0x018 RO Device capabilities */ + + uint32_t rsvd__01c_02f[(0x30 - 0x1c) / 4]; + + uint32_t pborctl; /* 0x030 RW Brown-Out Reset ConTroL */ + uint32_t ldopctl; /* 0x034 RW LDO Power ConTroL */ + + uint32_t rsvd__038_03f[(0x40 - 0x38) / 4]; + + uint32_t srcr0; /* 0x040 RW Software Reset Control Register */ + uint32_t srcr1; /* 0x044 RW Software Reset Control Register */ + uint32_t srcr2; /* 0x048 RW Software Reset Control Register */ + + uint32_t rsvd__04c_04f; + + uint32_t ris; /* 0x050 RO Raw Interrupt Status */ + uint32_t imc; /* 0x054 RW Interrupt Mask Control */ + uint32_t misc; /* 0x058 RW1C Masked Int. Status & Clear */ + uint32_t resc; /* 0x05C RW RESet Cause */ + struct { + union __rcc rcc; /* 0x060 RW Run-mode Clock Configuration */ + uint32_t pllcfg; /* 0x064 RW xtal-to-pll translation */ + + uint32_t rsvd__068_06f[(0x70 - 0x068) / 4]; + + union __rcc2 rcc2; /* 0x070 RW Run-mode Clock Configuration */ + + uint32_t rsvd__074_0ff[(0x100 - 0x074) / 4]; + + uint32_t rcgc0; /* 0x100 RW Run-mode Clock Gating */ + uint32_t rcgc1; /* 0x104 RW Run-mode Clock Gating */ + uint32_t rcgc2; /* 0x108 RW Run-mode Clock Gating */ + + uint32_t rsvd__10c_10f; + + uint32_t scgc0; /* 0x110 RW Sleep-mode Clock Gating */ + uint32_t scgc1; /* 0x114 RW Sleep-mode Clock Gating */ + uint32_t scgc2; /* 0x118 RW Sleep-mode Clock Gating */ + + uint32_t rsvd__11c_11f; + + uint32_t dcgc0; /* 0x120 RW Deep sleep mode Clock Gating */ + uint32_t dcgc1; /* 0x124 RW Deep sleep mode Clock Gating */ + uint32_t dcgc2; /* 0x128 RW Deep sleep mode Clock Gating */ + + uint32_t rsvd__12c_143[(0x144 - 0x12c) / 4]; + + uint32_t + dslpclkcfg; /* 0x144 RW Deep SLeeP CLocK ConFiGuration + */ + } clock; +}; + +extern volatile struct __scp __scp; +#endif /* _SCP_H_ */ diff --git a/arch/arm/ti_lm3s6965/sw_isr_table.c b/arch/arm/ti_lm3s6965/sw_isr_table.c new file mode 100644 index 00000000000..37a2603178b --- /dev/null +++ b/arch/arm/ti_lm3s6965/sw_isr_table.c @@ -0,0 +1,66 @@ +/* sw_isr_table.c - Software ISR table for ti_lm3s6965 BSP */ + +/* + * Copyright (c) 2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This contains the ISR table meant to be used for ISRs that take a parameter. +It is also used when ISRs are to be connected at runtime, and in this case +provides a table that is filled with _SpuriousIRQ bindings. +*/ + +#include +#include +#include + +extern void _SpuriousIRQ(void *arg); + +#if defined(CONFIG_SW_ISR_TABLE_DYNAMIC) + +_IsrTableEntry_t __isr_table_section _IsrTable[CONFIG_NUM_IRQS] = { + [0 ...(CONFIG_NUM_IRQS - 1)].arg = (void *)0xABAD1DEA, + [0 ...(CONFIG_NUM_IRQS - 1)].isr = _SpuriousIRQ +}; + +#else +#if defined(CONFIG_SW_ISR_TABLE) +#if !defined(CONFIG_SW_ISR_TABLE_STATIC_CUSTOM) + +/* placeholders: fill with real ISRs */ + +_IsrTableEntry_t __isr_table_section _IsrTable[CONFIG_NUM_IRQS] = { + [0 ...(CONFIG_NUM_IRQS - 1)].arg = (void *)0xABAD1DEA, + [0 ...(CONFIG_NUM_IRQS - 1)].isr = _SpuriousIRQ +}; + +#endif +#endif +#endif diff --git a/arch/arm/ti_lm3s6965/system.c b/arch/arm/ti_lm3s6965/system.c new file mode 100644 index 00000000000..8ecfcf8cb5f --- /dev/null +++ b/arch/arm/ti_lm3s6965/system.c @@ -0,0 +1,135 @@ +/* system.c - system/hardware module for ti_lm3s6965 BSP */ + +/* + * Copyright (c) 2013-2015 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This module provides routines to initialize and support board-level hardware +for the ti_lm3s6965 BSP. +*/ + +#include +#include +#include +#include +#include + +#if defined(CONFIG_PRINTK) || defined(CONFIG_STDOUT_CONSOLE) +#define DO_CONSOLE_INIT +#endif + +#define RCGC1 *((volatile uint32_t *)0x400FE104) + +#define RCGC1_UART0_EN 0x00000001 +#define RCGC1_UART1_EN 0x00000002 +#define RCGC1_UART2_EN 0x00000004 + +#ifdef CONFIG_RUNTIME_NMI +extern void _NmiInit(void); +#define NMI_INIT() _NmiInit() +#else +#define NMI_INIT() +#endif + +#if defined(DO_CONSOLE_INIT) + +/******************************************************************************* +* +* uartGenericInfoInit - initialize initialization information for one UART +* +* RETURNS: N/A +* +*/ + +static inline void uartGenericInfoInit(struct uart_init_info *pInfo) +{ + pInfo->sys_clk_freq = SYSCLK_DEFAULT_IOSC_HZ; + pInfo->baud_rate = CONFIG_UART_CONSOLE_BAUDRATE; +} + +#endif /* DO_CONSOLE_INIT */ + +#if defined(DO_CONSOLE_INIT) + +/******************************************************************************* +* +* consoleInit - initialize target-only console +* +* Only used for debugging. +* +* RETURNS: N/A +* +*/ + +#include + +static void consoleInit(void) +{ + struct uart_init_info info; + + /* enable clock to UART0 */ + RCGC1 |= RCGC1_UART0_EN; + + uartGenericInfoInit(&info); + info.regs = CONFIG_UART_CONSOLE_REGS; + + /* Only supported in polling mode, but init all info fields */ + info.irq = CONFIG_UART_CONSOLE_IRQ; + info.int_pri = CONFIG_UART_CONSOLE_INT_PRI; + + uart_init(CONFIG_UART_CONSOLE_INDEX, &info); + + uartConsoleInit(); +} + +#else +#define consoleInit() \ + do {/* nothing */ \ + } while ((0)) +#endif /* DO_CONSOLE_INIT */ + +/******************************************************************************* +* +* _InitHardware - perform basic hardware initialization +* +* Initialize the interrupt controller device drivers and the +* integrated 16550-compatible UART device driver. +* Also initialize the timer device driver, if required. +* +* RETURNS: N/A +*/ + +void _InitHardware(void) +{ + consoleInit(); /* NOP if not needed */ + NMI_INIT(); /* install default handler that simply resets the CPU + * if configured in the kernel, NOP otherwise */ +} diff --git a/arch/arm/timer/systick.c b/arch/arm/timer/systick.c new file mode 100644 index 00000000000..de5bd4fee87 --- /dev/null +++ b/arch/arm/timer/systick.c @@ -0,0 +1,726 @@ +/* systick.c - ARM systick device driver */ + +/* + * Copyright (c) 2013-2015 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This module implements the VxMicro's CORTEX-M3 ARM's systick device driver. +It provides the standard VxMicro "system clock driver" interfaces. + +The driver utilizes systick to provide kernel ticks. + +\INTERNAL IMPLEMENTATION DETAILS +The systick device provides a 24-bit clear-on-write, decrementing, +wrap-on-zero counter. Only edge sensitive triggered interrupt is supported. + +\INTERNAL PACKAGING DETAILS +The systick device driver is part of the microkernel in both a monolithic kernel +system and a split kernel system; it is not included in the nanokernel portion +of a split kernel. + +The device driver is also part of a nanokernel-only system, but omits more +complex capabilities (such as tickless idle support) that are only used in +conjunction with a microkernel. +*/ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_MICROKERNEL + +#include +#include + +extern struct nano_stack K_Args; + +#endif /* CONFIG_MICROKERNEL */ + +/* running total of timer count */ +static uint32_t accumulatedCount = 0; + +/* + * A board support package's board.h header must provide definitions for the + * following constants: + * + * CONFIG_SYSTICK_CLOCK_FREQ + * + * This is the sysTick input clock frequency. + */ + +#include + +/* defines */ + +/* + * When GDB_INFO is enabled, the handler installed in the vector table + * (__systick), can be found in systick_gdb.s. In this case, the handler + * in this file becomes _Systick() and will be called by __systick. + */ +#ifdef CONFIG_GDB_INFO +#define _TIMER_INT_HANDLER _real_timer_int_handler +#else +#define _TIMER_INT_HANDLER _timer_int_handler +#endif + +#ifdef CONFIG_TICKLESS_IDLE +#define TIMER_MODE_PERIODIC 0 /* normal running mode */ +#define TIMER_MODE_ONE_SHOT 1 /* emulated, since sysTick has 1 mode */ + +#define IDLE_NOT_TICKLESS 0 /* non-tickless idle mode */ +#define IDLE_TICKLESS 1 /* tickless idle mode */ +#endif /* CONFIG_TICKLESS_IDLE */ + +/* globals */ + +#ifdef CONFIG_INT_LATENCY_BENCHMARK +extern uint32_t _HwIntToCHandlerLatency; +#endif + +#ifdef CONFIG_ADVANCED_POWER_MANAGEMENT +extern int32_t _NanoIdleValGet(void); +extern void _NanoIdleValClear(void); +extern void _SysPowerSaveIdleExit(int32_t ticks); +#endif /* CONFIG_ADVANCED_POWER_MANAGEMENT */ + +#ifdef CONFIG_TICKLESS_IDLE +extern int32_t _SysIdleElapsedTicks; +#endif /* CONFIG_TICKLESS_IDLE */ + +/* locals */ + +#ifdef CONFIG_TICKLESS_IDLE +static uint32_t __noinit defaultLoadVal; /* default count */ +static uint32_t idleOrigCount = 0; +static uint32_t __noinit maxSysTicks; +static uint32_t idleOrigTicks = 0; +static uint32_t __noinit maxLoadValue; +static uint32_t __noinit timerIdleSkew; +static unsigned char timerMode = TIMER_MODE_PERIODIC; +static unsigned char idleMode = IDLE_NOT_TICKLESS; +#endif /* CONFIG_TICKLESS_IDLE */ + +#if defined(CONFIG_TICKLESS_IDLE) || \ + defined(CONFIG_SYSTEM_TIMER_DISABLE) + +/******************************************************************************* +* +* sysTickStop - stop the timer +* +* This routine disables the systick counter. +* +* RETURNS: N/A +* +* \NOMANUAL +*/ + +static ALWAYS_INLINE void sysTickStop(void) +{ + union __stcsr reg; + + /* + * Disable the counter and its interrupt while preserving the + * remaining bits. + */ + reg.val = __scs.systick.stcsr.val; + reg.bit.enable = 0; + reg.bit.tickint = 0; + __scs.systick.stcsr.val = reg.val; +} + +#endif /* CONFIG_TICKLESS_IDLE || CONFIG_SYSTEM_TIMER_DISABLE */ + +#ifdef CONFIG_TICKLESS_IDLE + +/******************************************************************************* +* +* sysTickStart - start the timer +* +* This routine enables the systick counter. +* +* RETURNS: N/A +* +* \NOMANUAL +*/ + +static ALWAYS_INLINE void sysTickStart(void) +{ + union __stcsr reg; + + /* + * Enable the counter, its interrupt and set the clock source to be + * the system clock while preserving the remaining bits. + */ + reg.val = + __scs.systick.stcsr.val; /* countflag is cleared by this read */ + reg.bit.enable = 1; + reg.bit.tickint = 1; + reg.bit.clksource = 1; + __scs.systick.stcsr.val = reg.val; +} + +/******************************************************************************* +* +* sysTickCurrentGet - get the current counter value +* +* This routine gets the value from the timer's current value register. This +* value is the 'time' remaining to decrement before the timer triggers an +* interrupt. +* +* RETURNS: the current counter value +* +* \NOMANUAL +*/ +static ALWAYS_INLINE uint32_t sysTickCurrentGet(void) +{ + return __scs.systick.stcvr; +} + +/******************************************************************************* +* +* sysTickReloadGet - get the reload/countdown value +* +* This routine returns the value from the reload value register. +* +* RETURNS: the counter's initial count/wraparound value +* +* \NOMANUAL +*/ +static ALWAYS_INLINE uint32_t sysTickReloadGet(void) +{ + return __scs.systick.strvr; +} + +#endif /* CONFIG_TICKLESS_IDLE */ + +/******************************************************************************* +* +* sysTickReloadSet - set the reload/countdown value +* +* This routine sets value from which the timer will count down and also +* sets the timer's current value register to zero. +* Note that the value given is assumed to be valid (i.e., count < (1<<24)). +* +* RETURNS: N/A +* +* \NOMANUAL +*/ + +static ALWAYS_INLINE void sysTickReloadSet( + uint32_t count /* count from which timer is to count down */ + ) +{ + /* + * Write the reload value and clear the current value in preparation + * for enabling the timer. + * The countflag in the control/status register is also cleared by + * this operation. + */ + __scs.systick.strvr = count; + __scs.systick.stcvr = 0; /* also clears the countflag */ +} + +/******************************************************************************* +* +* _TIMER_INT_HANDLER - system clock tick handler +* +* This routine handles the system clock tick interrupt. A TICK_EVENT event +* is pushed onto the microkernel stack. +* +* The symbol for this routine is either _timer_int_handler (for normal +* system operation) or _real_timer_int_handler (when GDB_INFO is enabled). +* +* RETURNS: N/A +* +* \NOMANUAL +*/ + +void _TIMER_INT_HANDLER(void *unused) +{ + ARG_UNUSED(unused); + +#ifdef CONFIG_INT_LATENCY_BENCHMARK + uint32_t value = __scs.systick.val; + uint32_t delta = __scs.systick.reload - value; + + if (_HwIntToCHandlerLatency > delta) { + /* keep the lowest value observed */ + _HwIntToCHandlerLatency = delta; + } +#endif + +#ifdef CONFIG_ADVANCED_POWER_MANAGEMENT + int32_t numIdleTicks; + + /* + * All interrupts are disabled when handling idle wakeup. + * For tickless idle, this ensures that the calculation and programming + * of + * the device for the next timer deadline is not interrupted. + * For non-tickless idle, this ensures that the clearing of the kernel + * idle + * state is not interrupted. + * In each case, _SysPowerSaveIdleExit is called with interrupts + * disabled. + */ + __asm__(" cpsid i"); /* PRIMASK = 1 */ + +#ifdef CONFIG_TICKLESS_IDLE + /* + * If this a wakeup from a completed tickless idle or after + * _timer_idle_exit has processed a partial idle, return + * to the normal tick cycle. + */ + if (timerMode == TIMER_MODE_ONE_SHOT) { + sysTickStop(); + sysTickReloadSet(defaultLoadVal); + sysTickStart(); + timerMode = TIMER_MODE_PERIODIC; + } + + /* set the number of elapsed ticks and announce them to the kernel */ + + if (idleMode == IDLE_TICKLESS) { + /* tickless idle completed without interruption */ + idleMode = IDLE_NOT_TICKLESS; + _SysIdleElapsedTicks = + idleOrigTicks + 1; /* actual # of idle ticks */ + nano_isr_stack_push(&K_Args, TICK_EVENT); + } else { + /* + * Increment the tick because _timer_idle_exit does not + * account for the tick due to the timer interrupt itself. + * Also, if not in tickless mode, _SysIdleElpasedTicks will be + * 0. + */ + _SysIdleElapsedTicks++; + + /* + * If we transition from 0 elapsed ticks to 1 we need to + * announce the + * tick event to the microkernel. Other cases will be covered by + * _timer_idle_exit. + */ + + if (_SysIdleElapsedTicks == 1) { + nano_isr_stack_push(&K_Args, TICK_EVENT); + } + } + + /* accumulate total counter value */ + accumulatedCount += defaultLoadVal * _SysIdleElapsedTicks; +#else /* !CONFIG_TICKLESS_IDLE */ + /* + * No tickless idle: + * Update the total tick count and announce this tick to the kernel. + */ + accumulatedCount += sys_clock_hw_cycles_per_tick; + + nano_isr_stack_push(&K_Args, TICK_EVENT); +#endif /* CONFIG_TICKLESS_IDLE */ + + numIdleTicks = _NanoIdleValGet(); /* get # of idle ticks requested */ + + if (numIdleTicks) { + _NanoIdleValClear(); /* clear kernel idle setting */ + + /* + * Complete idle processing. + * Note that for tickless idle, nothing will be done in + * _timer_idle_exit. + */ + _SysPowerSaveIdleExit(numIdleTicks); + } + + __asm__(" cpsie i"); /* re-enable interrupts (PRIMASK = 0) */ + +#else /* !CONFIG_ADVANCED_POWER_MANAGEMENT */ + + /* accumulate total counter value */ + accumulatedCount += sys_clock_hw_cycles_per_tick; + +#ifdef CONFIG_MICROKERNEL + /* + * one more tick has occurred -- don't need to do anything special since + * timer is already configured to interrupt on the following tick + */ + nano_isr_stack_push(&K_Args, TICK_EVENT); +#else + nanoTicks++; + + if (nanoTimerList) { + nanoTimerList->ticks--; + + while (nanoTimerList && (!nanoTimerList->ticks)) { + struct nano_timer *expired = nanoTimerList; + struct nano_lifo *chan = &expired->lifo; + nanoTimerList = expired->link; + nano_isr_lifo_put(chan, expired->userData); + } + } +#endif /* CONFIG_MICROKERNEL */ +#endif /* CONFIG_ADVANCED_POWER_MANAGEMENT */ + + extern void _ExcExit(void); + _ExcExit(); +} + +#ifdef CONFIG_TICKLESS_IDLE + +/******************************************************************************* +* +* sysTickTicklessIdleInit - initialize the tickless idle feature +* +* This routine initializes the tickless idle feature by calculating the +* necessary hardware-specific parameters. +* +* Note that the maximum number of ticks that can elapse during a "tickless idle" +* is limited by . The larger the value (the lower the +* tick frequency), the fewer elapsed ticks during a "tickless idle". +* Conversely, the smaller the value (the higher the tick frequency), the +* more elapsed ticks during a "tickless idle". +* +* RETURNS: N/A +* +* \NOMANUAL +*/ + +static void sysTickTicklessIdleInit(void) +{ + /* enable counter, disable interrupt and set clock src to system clock + */ + union __stcsr stcsr = {.bit = {1, 0, 1, 0, 0, 0}}; + volatile uint32_t dummy; /* used to help determine the 'skew time' */ + + /* store the default reload value (which has already been set) */ + defaultLoadVal = sysTickReloadGet(); + + /* calculate the max number of ticks with this 24-bit H/W counter */ + maxSysTicks = 0x00ffffff / defaultLoadVal; + + /* determine the associated load value */ + maxLoadValue = maxSysTicks * defaultLoadVal; + + /* + * Calculate the skew from switching the timer in and out of idle mode. + * The following sequence is emulated: + * 1. Stop the timer. + * 2. Read the current counter value. + * 3. Calculate the new/remaining counter reload value. + * 4. Load the new counter value. + * 5. Set the timer mode to periodic/one-shot. + * 6. Start the timer. + * + * The timer must be running for this to work, so enable the + * systick counter without generating interrupts, using the processor + *clock. + * Note that the reload value has already been set by the caller. + */ + + __scs.systick.stcsr.val |= stcsr.val; + __asm__(" isb"); /* ensure the timer is started before reading */ + + timerIdleSkew = sysTickCurrentGet(); /* start of skew time */ + + __scs.systick.stcsr.val |= stcsr.val; /* normally sysTickStop() */ + + dummy = sysTickCurrentGet(); /* emulate sysTickReloadSet() */ + + /* emulate calculation of the new counter reload value */ + if ((dummy == 1) || (dummy == defaultLoadVal)) { + dummy = maxSysTicks - 1; + dummy += maxLoadValue - defaultLoadVal; + } else { + dummy = dummy - 1; + dummy += dummy * defaultLoadVal; + } + + /* _sysTickStart() without interrupts */ + __scs.systick.stcsr.val |= stcsr.val; + + timerMode = TIMER_MODE_PERIODIC; + + /* skew time calculation for down counter (assumes no rollover) */ + timerIdleSkew -= sysTickCurrentGet(); + + /* restore the previous sysTick state */ + sysTickStop(); + sysTickReloadSet(defaultLoadVal); +} + +/******************************************************************************* +* +* _timer_idle_enter - Place the system timer into idle state +* +* Re-program the timer to enter into the idle state for the given number of +* ticks. It is set to a "one shot" mode where it will fire in the number of +* ticks supplied or the maximum number of ticks that can be programmed into +* hardware. A value of -1 will result in the maximum number of ticks. +* +* RETURNS: N/A +*/ + +void _timer_idle_enter(int32_t ticks /* system ticks */ + ) +{ + sysTickStop(); + + /* + * We're being asked to have the timer fire in "ticks" from now. To + * maintain accuracy we must account for the remaining time left in the + * timer. So we read the count out of it and add it to the requested + * time out + */ + idleOrigCount = sysTickCurrentGet() - timerIdleSkew; + + if ((ticks == -1) || (ticks > maxSysTicks)) { + /* + * We've been asked to fire the timer so far in the future that + * the + * required count value would not fit in the 24-bit reload + * register. + * Instead, we program for the maximum programmable interval + * minus one + * system tick to prevent overflow when the left over count read + * earlier + * is added. + */ + idleOrigCount += maxLoadValue - defaultLoadVal; + idleOrigTicks = maxSysTicks - 1; + } else { + /* leave one tick of buffer to have to time react when coming + * back */ + idleOrigTicks = ticks - 1; + idleOrigCount += idleOrigTicks * defaultLoadVal; + } + + /* + * Set timer to virtual "one shot" mode - sysTick does not have multiple + * modes, so the reload value is simply changed. + */ + timerMode = TIMER_MODE_ONE_SHOT; + idleMode = IDLE_TICKLESS; + sysTickReloadSet(idleOrigCount); + sysTickStart(); +} + +/******************************************************************************* +* +* _timer_idle_exit - handling of tickless idle when interrupted +* +* The routine, called by _SysPowerSaveIdleExit, is responsible for taking +* the timer out of idle mode and generating an interrupt at the next +* tick interval. It is expected that interrupts have been disabled. +* +* Note that in this routine, _SysIdleElapsedTicks must be zero because the +* ticker has done its work and consumed all the ticks. This has to be true +* otherwise idle mode wouldn't have been entered in the first place. +* +* RETURNS: N/A +*/ + +void _timer_idle_exit(void) +{ + uint32_t count; /* timer's current count register value */ + + if (timerMode == TIMER_MODE_PERIODIC) { + /* + * The timer interrupt handler is handling a completed tickless + * idle + * or this has been called by mistake; there's nothing to do + * here. + */ + return; + } + + sysTickStop(); + + /* timer is in idle mode, adjust the ticks expired */ + + count = sysTickCurrentGet(); + + if ((count == 0) || (__scs.systick.stcsr.bit.countflag)) { + /* + * The timer expired and/or wrapped around. Re-set the timer to + * its default value and mode. + */ + sysTickReloadSet(defaultLoadVal); + timerMode = TIMER_MODE_PERIODIC; + + /* + * Announce elapsed ticks to the microkernel. Note we are + * guaranteed + * that the timer ISR will execute before the tick event is + * serviced, + * so _SysIdleElapsedTicks is adjusted to account for it. + */ + _SysIdleElapsedTicks = idleOrigTicks - 1; + nano_isr_stack_push(&K_Args, TICK_EVENT); + } else { + uint32_t elapsed; /* elapsed "counter time" */ + uint32_t remaining; /* remaining "counter time" */ + + elapsed = idleOrigCount - count; + + remaining = elapsed % defaultLoadVal; + + /* ensure that the timer will interrupt at the next tick */ + + if (remaining == 0) { + /* + * Idle was interrupted on a tick boundary. Re-set the + * timer to + * its default value and mode. + */ + sysTickReloadSet(defaultLoadVal); + timerMode = TIMER_MODE_PERIODIC; + } else if (count > remaining) { + /* + * There is less time remaining to the next tick + * boundary than + * time left for idle. Leave in "one shot" mode. + */ + sysTickReloadSet(remaining); + } + + _SysIdleElapsedTicks = elapsed / defaultLoadVal; + + if (_SysIdleElapsedTicks) { + /* Announce elapsed ticks to the microkernel */ + nano_isr_stack_push(&K_Args, TICK_EVENT); + } + } + + idleMode = IDLE_NOT_TICKLESS; + sysTickStart(); +} + +#endif /* CONFIG_TICKLESS_IDLE */ + +/******************************************************************************* +* +* timer_driver - initialize and enable the system clock +* +* This routine is used to program the systick to deliver interrupts at the +* rate specified via the 'sys_clock_us_per_tick' global variable. +* +* RETURNS: N/A +*/ +void timer_driver(int priority /* priority parameter is ignored by this driver + */ + ) +{ + /* enable counter, interrupt and set clock src to system clock */ + union __stcsr stcsr = {.bit = {1, 1, 1, 0, 0, 0}}; + + ARG_UNUSED(priority); + + /* + * Determine the reload value to achieve the configured tick rate. + */ + + /* systick supports 24-bit H/W counter */ + __ASSERT(sys_clock_hw_cycles_per_tick <= (1 << 24), + "sys_clock_hw_cycles_per_tick too large"); + sysTickReloadSet(sys_clock_hw_cycles_per_tick - 1); + +#ifdef CONFIG_TICKLESS_IDLE + + /* calculate hardware-specific parameters for tickless idle */ + + sysTickTicklessIdleInit(); + +#endif /* CONFIG_TICKLESS_IDLE */ + +#ifdef CONFIG_MICROKERNEL + + /* specify the kernel routine that will handle the TICK_EVENT event */ + + task_event_set_handler(TICK_EVENT, K_ticker); + +#endif /* CONFIG_MICROKERNEL */ + + _ScbExcPrioSet(_EXC_SYSTICK, _EXC_IRQ_DEFAULT_PRIO); + + __scs.systick.stcsr.val = stcsr.val; +} + +/******************************************************************************* +* +* timer_read - read the BSP timer hardware +* +* This routine returns the current time in terms of timer hardware clock cycles. +* Some VxMicro facilities (e.g. benchmarking code) directly call timer_read() +* instead of utilizing the 'timer_read_fptr' function pointer. +* +* RETURNS: up counter of elapsed clock cycles +* +* \INTERNAL WARNING +* systick counter is a 24-bit down counter which is reset to "reload" value +* once it reaches 0. +*/ + +uint32_t timer_read(void) +{ + return accumulatedCount + (__scs.systick.strvr - __scs.systick.stcvr); +} + +#ifdef CONFIG_SYSTEM_TIMER_DISABLE + +/******************************************************************************* +* +* timer_disable - stop announcing ticks into the kernel +* +* This routine disables the systick so that timer interrupts are no +* longer delivered. +* +* RETURNS: N/A +*/ + +void timer_disable(void) +{ + unsigned int key; /* interrupt lock level */ + union __stcsr reg; + + key = irq_lock(); + + /* disable the systick counter and systick interrupt */ + + sysTickStop(); + + irq_unlock(key); +} + +#endif /* CONFIG_SYSTEM_TIMER_DISABLE */ diff --git a/arch/arm/timer/systick_gdb.s b/arch/arm/timer/systick_gdb.s new file mode 100644 index 00000000000..8f00f96ee85 --- /dev/null +++ b/arch/arm/timer/systick_gdb.s @@ -0,0 +1,57 @@ +/* systick_gdb.c - ARM systick handler stub for GDB debugging */ + +/* + * Copyright (c) 2014-2015 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +GDB stub needed before the real systick handler runs to be able to display the +correct state of the thread that was interrupted. +*/ + +#ifdef CONFIG_GDB_INFO + +#define _ASMLANGUAGE + +#include +#include +#include + +_ASM_FILE_PROLOGUE + +GTEXT(_timer_int_handler) +GTEXT(_real_timer_int_handler) +SECTION_FUNC(TEXT, _timer_int_handler) + + _GDB_STUB_EXC_ENTRY + + b _real_timer_int_handler + +#endif /* CONFIG_GDB_INFO */ diff --git a/arch/x86/bsp/cache.c b/arch/x86/bsp/cache.c new file mode 100644 index 00000000000..375fabf2056 --- /dev/null +++ b/arch/x86/bsp/cache.c @@ -0,0 +1,75 @@ +/* cache.c - cache manipulation */ + +/* + * Copyright (c) 2013-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ +/* +DESCRIPTION +This module contains functions for manipulation caches. +*/ + +#include +#include +#include + +#ifdef CONFIG_CLFLUSH_INSTRUCTION_SUPPORTED + +#if (CONFIG_CACHE_LINE_SIZE == 0) +#error Cannot use this implementation with a cache line size of 0 +#endif + +/******************************************************************************* +* +* _SysCacheFlush - flush a page to main memory +* +* No alignment is required for either or , but since +* _SysCacheFlush() iterates on the cache lines, a cache line alignment for both +* is optimal. +* +* The cache line size is specified via the CONFIG_CACHE_LINE_SIZE kconfig +* option. +* +* RETURNS: N/A +*/ + +void _SysCacheFlush(VIRT_ADDR virt, size_t size) +{ + int end; + + size = ROUND_UP(size, CONFIG_CACHE_LINE_SIZE); + end = virt + size; + + for (; virt < end; virt += CONFIG_CACHE_LINE_SIZE) { + __asm__ volatile("clflush %0;\n\t" : : "m"(virt)); + } + + __asm__ volatile("mfence;\n\t"); +} + +#endif /* CONFIG_CLFLUSH_INSTRUCTION_SUPPORTED */ diff --git a/arch/x86/bsp/cache_s.s b/arch/x86/bsp/cache_s.s new file mode 100644 index 00000000000..05e8b7df040 --- /dev/null +++ b/arch/x86/bsp/cache_s.s @@ -0,0 +1,64 @@ +/* cache_s.s - cache manipulation */ + +/* + * Copyright (c) 2013-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ +/* +DESCRIPTION +This module contains functions for manipulating caches. +*/ + +#ifndef CONFIG_CLFLUSH_INSTRUCTION_SUPPORTED + +#define _ASMLANGUAGE +#include + + /* externs (internal APIs) */ + GTEXT(_SysCacheFlush) + +/******************************************************************************* +* +* _SysCacheFlush - flush a page to main memory +* +* This implementation flushes the whole cache. +* +* C signature: +* +* void _SysCacheFlush (VIRT_ADDR virt, size_t size) +* +* Both parameters are ignored in this implementation. +* +* RETURNS: N/A +*/ + +SECTION_FUNC(TEXT, _SysCacheFlush) + wbinvd + ret + +#endif /* !CONFIG_CLFLUSH_INSTRUCTION_SUPPORTED */ diff --git a/arch/x86/bsp/crt0.s b/arch/x86/bsp/crt0.s new file mode 100644 index 00000000000..d5162ddbd42 --- /dev/null +++ b/arch/x86/bsp/crt0.s @@ -0,0 +1,662 @@ +/* crt0.s - crt0 module for the IA-32 boards */ + +/* + * Copyright (c) 2010-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ +/* +DESCRIPTION +This module contains the initial code executed by the VxMicro ELF image +after having been loaded into RAM. + +INTERNAL +The CONFIG_PROT_MODE_SWITCH configuration option was once required when +booting/loading an image into a Simics simulation environment, since the +invocation technique involved halting the BIOS code (via a breakpoint) before +it attempted to load a bootloader from disk, and then dumping the VxMicro ELF +image into memory. This meant that the IA-32 processor was executing in 16-bit +real mode (aka real mode) when __start() was called, thus requiring __start() +to perform the 16-bit to 32-bit transition code and other sundry PC-related +initialization steps (eg. enabling address line A20). + +Later advances now allow a VxMicro image to be loaded into the Simics environment +after the system is already in 32-bit protected mode and address line A20 is +enabled. Consequently, the CONFIG_PROT_MODE_SWITCH configuration option +is no longer used by this BSP, and *all* booting scenarios for the BSP (e.g. +via GRUB or any other multiboot compliant bootloader) now assume that the +system is already in 32-bit protected mode and address line A20 is enabled. +However, the code associated with CONFIG_PROT_MODE_SWITCH has been left +in place in case future booting scenarios arise which require its use. + +POMS memory model + +When a kernel configured for POMS starts, it runs at a physical address that +is different from the logical address it has been linked at. So, symbols are not +accessible without doing some translation. It is best then to run at a logical +address ASAP to access give access to symbols, especially to be able to run C +code. To do that, we start using segment selectors for CS/DS/SS that are mapping +the physical location to the logical location at which the kernel is linked, ie. +0x1000. Those segment selectors are 0x18 for CS and 0x20 for DS/SS. + +Before these are used, the startup code uses physical address locations of +some key symbols (eg. the gdt) provided by the linker script. +*/ + +#define _ASMLANGUAGE + +#include + + /* exports (private APIs) */ + + GTEXT(__start) + + /* externs */ + GTEXT(_Cstart) + + GDATA(_IdtBaseAddress) + GDATA(_InterruptStack) + + +#if defined(CONFIG_SSE) + GDATA(_Mxcsr) +#endif /* CONFIG_SSE */ + +#if defined(CONFIG_BOOT_TIME_MEASUREMENT) + GDATA(__start_tsc) +#endif + +#ifdef CONFIG_ADVANCED_IDLE + GDATA(_AdvIdleCheckSleep) + GDATA(_AdvIdleStart) +#endif /* CONFIG_ADVANCED_IDLE */ + +#ifdef CONFIG_PROT_MODE_SWITCH + + /* cold start code in 16-bit real mode */ + + /* + * Switch 'gas' into 16-bit mode, i.e. use a default operand and + * address size of 16 bits since the processor is executing in + * 16-bit real mode. The prevents the assembler from inserting + * 0x66 or 0x67 instruction prefixes when using 16-bit data values + * or 16-bit pointers. + */ + + .code16 + + .section ".xreset", "ax" + .balign 16,0x90 + +__start: +#ifdef CONFIG_BOOT_TIME_MEASUREMENT + /* + * Record BootTime from start of Kernel. + * Store value temporarily in Register EDI & ESI and + * write to memory once memory access is allowed. + * That is, once the data segment register has been setup to access + * the .data/.rodata/.bss section of the linked image. + */ + rdtsc + mov %eax, %esi /* low value */ + mov %edx, %edi /* high value */ +#endif + /* + * Ensure interrupts are disabled. Interrupts are enabled when + * the first VxMicro thread context switch occurs. + */ + + cli + + +/* + * BSPs that need to enable the A20 line to boot properly wil enable this + * option. + */ +#ifdef CONFIG_BOOT_A20_ENABLE + + /* + * Set the stack pointer to just before the start of the .text + * section. This needs to be performed before any BIOS invocations. + * + * Note that attempting to set the stack pointer to beyond the end of + * the static ELF image (indicated via the _end symbol) may result + * in pointer wrap-around for images with large BSS sections + * (since the processor is still in "real" mode and thus the stack + * pointer is only a 16 bits). + */ + + movl $__start, %esp + + /* + * Before switching to 32-bit protected mode, Gate-A20 must be + * enabled (legacy PC hardware issue). + * + * The classical method of enabling address line A20 via the 8042 + * keyboard controller will not be performed. Instead, it will be + * assumed that the board has a relatively modern BIOS which supports + * the following int 15h function: + * + * - int 15h: ax=2400 -> disable A20 + * - int 15h: ax=2401 -> enable A20 + * If successful: CF clear, AH = 00h + * On error: CF set, AH = status + * Status: 01h keyboard controller is in secure mode + * 86h function not supported + * - int 15h: ax=2402 -> query status A20 + * status (0: disabled, 1: enabled) is returned in AL + * - int 15h: ax=2403 -> query A20 support (kbd or port 92) + * status (bit 0: kbd, bit 1: port 92) is returned in BX + * + * Return values: + * If successful: carry flag (CF) clear, AH = 00h + * On error: carry flag (CF) set, AH = status + * Status: 01h keyboard controller is in secure mode + * 86h function not supported + * + * If the int15h method fails, then the system control port A + * (I/O port 0x92) method will be used. + */ + + movw $0x2401, %ax /* ax=2401 -> enable A20 */ + int $0x15 + jnc A20Enabled /* CF = 1 -> try I/O port 0x92 method */ + + /* try enabling Gate-A20 via system control port A (I/O port 0x92) */ + + movb $0x02, %al + outb %al, $0x92 + + xorl %ecx, %ecx +A20EnableWait: + inb $0x92, %al + andb $0x02, %al + loopz A20EnableWait + +A20Enabled: +#endif /* CONFIG_BOOT_A20_ENABLE */ + + /* load Interrupt Descriptor and Global Descriptor tables (IDT & GDT) */ + + lgdt %cs:_GdtRom /* load 32-bit operand size GDT */ + + movl %cr0, %eax /* move CR0 to EAX */ + orl $0x1, %eax /* set the Protection Enable (PE) bit */ + andl $0x9fffffff, %eax /* Enable write-back caching */ + movl %eax, %cr0 /* move EAX to CR0 */ + jmp %cs:vstartProtMode /* flush prefetch input queue */ + +vstartProtMode: + + /* + * At this point, the processor is executing in 32-bit protected + * mode, but the CS selector hasn't been loaded yet, i.e. the + * processor is still effectively executing instructions from a + * 16-bit code segment (thus the .code16 assembler directive still + * needs to be in effect. + */ + + movw $0x10,%ax /* data segment selector (entry = 3) */ + movw %ax,%ds /* set DS */ + movw %ax,%es /* set ES */ + movw %ax,%fs /* set FS */ + movw %ax,%gs /* set GS */ + movw %ax,%ss /* set SS */ + + /* this is 'ljmp $0x08:$vstart32BitCode': diab 5.9.1.0 does not encode + * it correctly */ + .byte 0xea + .long vstart32BitCode + .byte 0x08 + .byte 0x00 + + /* + * Switch 'gas' back to 32-bit data and address defaults. This + * can only be performed after loading the CS segment register + * (via an lcall instruction, for example) with a segment selector + * that describes a 32-bit code segment. + */ + .code32 + +SECTION_FUNC(TEXT_START, vstart32BitCode) + +#else /* !CONFIG_PROT_MODE_SWITCH */ + + /* processor is executing in 32-bit protected mode */ + + .balign 16,0x90 + +SECTION_FUNC(TEXT_START, __start) + +#ifdef CONFIG_BOOT_TIME_MEASUREMENT + /* + * Record BootTime from start of Kernel. + * Store value temporarily in Register edi & esi and + * write to memory once memory access is allowed. + * That is, once the data segment register has been setup to access + * the .data/.rodata/.bss section of the linked image. + */ + rdtsc + mov %eax, %esi /* low value */ + mov %edx, %edi /* high value */ +#endif + + /* Enable write-back caching by clearing the NW and CD bits */ + movl %cr0, %eax + andl $0x9fffffff, %eax + movl %eax, %cr0 + + /* + * Ensure interrupts are disabled. Interrupts are enabled when + * the first VxMicro thread context switch occurs. + */ + + cli + + /* + * Although the bootloader sets up an Interrupt Descriptor Table (IDT) + * and a Global Descriptor Table (GDT), the specification encourages + * booted operating systems to setup their own IDT and GDT. + */ + + lgdt _GdtRom /* load 32-bit operand size GDT */ + +#endif /* !CONFIG_PROT_MODE_SWITCH */ + + + lidt _Idt /* load 32-bit operand size IDT */ + + +#ifndef CONFIG_PROT_MODE_SWITCH + +#ifdef CONFIG_BOOTLOADER_UNKNOWN + /* + * Where we do not do the protected mode switch and the + * bootloader is unknown, do not make the assumption that the segment + * registers are set correctly. + * + * This is a special case for the generic_pc BSP, which must work for + * multiple platforms (QEMU, SIMICS, generic PC board, etc.). With other + * BSPs the bootloader is well known so assumptions can be made. + */ + movw $0x10, %ax /* data segment selector (entry = 3) */ + movw %ax, %ds /* set DS */ + movw %ax, %es /* set ES */ + movw %ax, %fs /* set FS */ + movw %ax, %gs /* set GS */ + movw %ax, %ss /* set SS */ + + /* this is 'ljmp $0x08:$_csSet': diab 5.9.1.0 does not encode + * it correctly */ + .byte 0xea + .long __csSet + .byte 0x08 + .byte 0x00 + +__csSet: +#endif /* CONFIG_BOOTLOADER_UNKNOWN */ + +#endif /* CONFIG_PROT_MODE_SWITCH */ + +#ifdef CONFIG_BOOT_TIME_MEASUREMENT + /* + * Store rdtsc result from temporary regiter ESI & EDI into memory. + */ + mov %esi, __start_tsc /* low value */ + mov %edi, __start_tsc+4 /* high value */ +#endif + +#ifdef CONFIG_ADVANCED_IDLE + + /* + * Set up the temporary stack to call the _AdvIdleCheckSleep routine + * We use the separate stack here in order to avoid the memory + * corruption if the system recovers from deep sleep + */ + movl $_AdvIdleStack, %esp + addl $CONFIG_ADV_IDLE_STACK_SIZE, %esp + + /* align to stack boundary: ROUND_DOWN (%esp, 4) */ + + andl $0xfffffffc, %esp + + /* + * Invoke _AdvIdleCheckSleep() routine that checks if we are restoring + * from deep sleep or not. The routine returns non-zero if the kernel + * is recovering from deep sleep and to 0 if a cold boot is needed. The + * kernel can skip floating point initialization, BSS initialization, + * and data initialization if recovering from deep sleep. + */ + + call _AdvIdleCheckSleep + cmpl $0, %eax + jne memInitDone + +#endif /* CONFIG_ADVANCED_IDLE */ + +#if !defined(CONFIG_FLOAT) + /* + * Force an #NM exception for floating point instructions + * since FP support hasn't been configured + */ + + movl %cr0, %eax /* move CR0 to EAX */ + orl $0x2e, %eax /* CR0[NE+TS+EM+MP]=1 */ + movl %eax, %cr0 /* move EAX to CR0 */ +#else + /* + * Permit use of x87 FPU instructions + * + * Note that all floating point exceptions are masked by default, + * and that _no_ handler for x87 FPU exceptions (#MF) is provided. + */ + + movl %cr0, %eax /* move CR0 to EAX */ + orl $0x22, %eax /* CR0[NE+MP]=1 */ + andl $~0xc, %eax /* CR0[TS+EM]=0 */ + movl %eax, %cr0 /* move EAX to CR0 */ + + fninit /* set x87 FPU to its default state */ + + #if defined(CONFIG_SSE) + /* + * Permit use of SSE instructions + * + * Note that all SSE exceptions are masked by default, + * and that _no_ handler for SSE exceptions (#XM) is provided. + */ + + movl %cr4, %eax /* move CR4 to EAX */ + orl $0x200, %eax /* CR4[OSFXSR] = 1 */ + andl $~0x400, %eax /* CR4[OSXMMEXCPT] = 0 */ + movl %eax, %cr4 /* move EAX to CR4 */ + + ldmxcsr _Mxcsr /* initialize SSE control/status reg */ + + #endif /* CONFIG_SSE */ + +#endif /* !CONFIG_FLOAT */ + +#ifdef CONFIG_XIP + /* + * copy DATA section from ROM to RAM region + * DATA is followed by BSS section. + * Given that BSS section is initialized after this copy, we can + * safely over-write into the next section. + * Note: __data_num_words is a multiple of 4 bytes + * rounded up to next 4 bytes. + * Note: the sections might not be 4 byte aligned. + */ + + movl $__data_ram_start, %edi /* DATA in RAM (dest) */ + movl $__data_rom_start, %esi /* DATA in ROM (src) */ + movl $__data_num_words, %ecx /* Size of DATA in quad bytes */ + je copyDataDone + + #ifdef CONFIG_SSE + /* copy 16 bytes at a time using XMM until < 16 bytes remain */ + + movl %ecx ,%edx /* save number of quad bytes */ + shrl $2, %ecx /* How many 16 bytes? */ + je dataWords + +dataDQ: + movdqu (%esi), %xmm0 + movdqu %xmm0, (%edi) + addl $16, %esi + addl $16, %edi + loop dataDQ + +dataWords: + movl %edx, %ecx /* restore # quad bytes */ + andl $0x3, %ecx /* only need to copy at most 3 quad bytes */ + #endif /* CONFIG_SSE */ + + rep + movsl /* copy data 4 bytes at a time */ +copyDataDone: + +#endif /* CONFIG_XIP */ + + /* + * Clear BSS: bzero (__bss_start, __bss_num_words*4) + * + * It's assumed that BSS size will be a multiple of a long (4 bytes), + * and aligned on a double word (32-bit) boundary + */ + +#ifdef CONFIG_SSE + + /* use XMM register to clear 16 bytes at a time */ + + pxor %xmm0, %xmm0 /* zero out xmm0 register */ + movl $__bss_start, %edi /* load BSS start address */ + movl $__bss_num_words, %ecx /* number of quad bytes in .bss */ + movl %ecx, %edx /* make a copy of # quad bytes */ + shrl $2, %ecx /* How many multiples of 16 byte ? */ + je bssWords +bssDQ: + movdqu %xmm0, (%edi) /* zero 16 bytes... */ + addl $16, %edi + loop bssDQ + + /* fall through to handle the remaining double words (32-bit chunks) */ + +bssWords: + xorl %eax, %eax /* fill memory with 0 */ + movl %edx, %ecx /* move # quad bytes into ECX (for rep) */ + andl $0x3, %ecx /* only need to zero at most 3 quad bytes */ + cld + rep + stosl /* zero memory per 4 bytes */ + +#else /* !CONFIG_SSE */ + + /* clear out BSS double words (32-bits at a time) */ + + xorl %eax, %eax /* fill memory with 0 */ + movl $__bss_start, %edi /* load BSS start address */ + movl $__bss_num_words, %ecx /* number of quad bytes */ + cld + rep + stosl /* zero memory per 4 bytes */ + +#endif /* CONFIG_SSE */ + +memInitDone: + + /* + * Set the stack pointer to the area used for the interrupt stack. + * Note this stack is only used during the execution of __start() and + * _Cstart(), i.e. only until the multi-tasking VxMicro kernel is + * initialized. The dual-purposing of this area of memory is safe since + * interrupts are disabled until the first context switch. + */ + + movl $_InterruptStack, %esp + addl $CONFIG_ISR_STACK_SIZE, %esp + + /* align to stack boundary: ROUND_DOWN (%esp, 4) */ + + andl $0xfffffffc, %esp + + /* activate RAM-based Global Descriptor Table (GDT) */ + + lgdt %ds:_Gdt + + + +#if defined (CONFIG_ADVANCED_IDLE) + /* + * Invoke _AdvIdleStart(_Cstart, _Gdt, _GlobalTss) by jumping to it. + * If it's a cold boot, this routine jumps to _Cstart and the normal + * kernel boot sequence continues; otherwise, it uses the TSS info + * saved in the GDT to resumes kernel processing at the point it was + * when the system went into deep sleep; that is, _AdvIdleFunc() + * completes and returns a non-zero value. + */ + + pushl $_GlobalTss + pushl $_Gdt + pushl $_Cstart + call _AdvIdleStart +#else + /* Jump to C portion of VxMicro kernel initialization and never return */ + + jmp _Cstart + +#endif /* CONFIG_ADVANCED_IDLE */ + +#if defined(CONFIG_SSE) + + /* SSE control & status register initial value */ + +_Mxcsr: + .long 0x1f80 /* all SSE exceptions clear & masked */ + +#endif /* CONFIG_SSE */ + + /* Interrupt Descriptor Table (IDT) definition */ + +_Idt: + .word (CONFIG_IDT_NUM_VECTORS * 8) - 1 /* limit: size of IDT-1 */ + + /* + * Physical start address = 0. When executing natively, this + * will be placed at the same location as the interrupt vector table + * setup by the BIOS (or GRUB?). + */ + + .long _IdtBaseAddress /* physical start address */ + + +#ifdef CONFIG_BOOTLOADER_UNKNOWN + /* Multiboot header definition is needed for some bootloaders */ + + /* + * The multiboot header must be in the first 8 Kb of the kernel image + * (not including the ELF section header(s)) and be aligned on a + * 4 byte boundary. + */ + + .balign 4,0x90 + + .long 0x1BADB002 /* multiboot magic number */ + + /* + * Flags = no bits are being set, specifically bit 16 is not being + * set since the supplied kernel image is an ELF file, and the + * multiboot loader shall use the information from the program and + * section header to load and boot the kernel image. + */ + + .long 0x00000000 + + /* + * checksum = 32-bit unsigned value which, when added to the other + * magic fields (i.e. "magic" and "flags"), must have a 32-bit + * unsigned sum of zero. + */ + + .long -(0x1BADB002 + 0) +#endif /* CONFIG_BOOTLOADER_UNKNOWN */ + + +#ifdef CONFIG_PROT_MODE_SWITCH + /* Global Descriptor Table (GDT) definition */ + .section ".xreset", "ax" + .align 8 +#endif /* CONFIG_PROT_MODE_SWITCH */ + +_GdtRom: + .word _GdtRomEnd - _GdtRomEntries - 1 /* Limit on GDT */ + .long _GdtRomEntries /* table address: _GdtRomEntries */ + + + .balign 16,0x90 + + /* + * The following 3 GDT entries implement the so-called "basic + * flat model", i.e. a single code segment descriptor and a single + * data segment descriptor such that VxMicro has access to a continuous, + * unsegmented address space. Both segment descriptors map the entire + * linear address space (i.e. 0 to 4 GB-1), thus the segmentation + * mechanism will never generate "out of limit memory reference" + * exceptions even if physical memory does not reside at the referenced + * address. + * + * The 'A' (accessed) bit in the type field is _not_ set for all the + * data/code segment descriptors to accomodate placing these entries + * in ROM, since such use is not planned for this platform. + */ + +_GdtRomEntries: + + /* Entry 0 (selector=0x0000): The "NULL descriptor" */ + + .word 0x0000 + .word 0x0000 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + + /* Entry 1 (selector=0x0008): Code descriptor: DPL0 */ + + .word 0xffff /* limit: xffff */ + .word 0x0000 /* base : xxxx0000 */ + .byte 0x00 /* base : xx00xxxx */ + .byte 0x9a /* Code e/r, Present, DPL0 */ + .byte 0xcf /* limit: fxxxx, Page Gra, 32bit */ + .byte 0x00 /* base : 00xxxxxx */ + + /* Entry 2 (selector=0x0010): Data descriptor: DPL0 */ + + .word 0xffff /* limit: xffff */ + .word 0x0000 /* base : xxxx0000 */ + .byte 0x00 /* base : xx00xxxx */ + .byte 0x92 /* Data r/w, Present, DPL0 */ + .byte 0xcf /* limit: fxxxx, Page Gra, 32bit */ + .byte 0x00 /* base : 00xxxxxx */ + + +#ifdef CONFIG_PROT_MODE_SWITCH + /* Reset vector */ + .code16 + .section ".xresetv", "ax" +_ResetVector: + jmp __start +#endif /* CONFIG_PROT_MODE_SWITCH */ + +_GdtRomEnd: + +#ifdef CONFIG_ADVANCED_IDLE + .section .NOINIT + .balign 4,0x90 +_AdvIdleStack: + .fill CONFIG_ADV_IDLE_STACK_SIZE +#endif diff --git a/arch/x86/bsp/driver_static_irq_stubs.s b/arch/x86/bsp/driver_static_irq_stubs.s new file mode 100644 index 00000000000..7ff2ab5b16c --- /dev/null +++ b/arch/x86/bsp/driver_static_irq_stubs.s @@ -0,0 +1,145 @@ +/* driver_static_irq_stubs.s - interrupt stubs */ + +/* + * Copyright (c) 2012-2015, Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This module contains the static interrupt stubs for the various drivers employed +by x86 BSPs. +*/ + +#define _ASMLANGUAGE + +#ifndef CONFIG_DYNAMIC_INT_STUBS + +#include +#include +#include +#include +#include + + /* exports (internal APIs) */ +#if defined(CONFIG_LOAPIC_TIMER) + GTEXT(_loApicTimerIntStub) +#endif + +#if defined(CONFIG_HPET_TIMER) + GTEXT(_hpetIntStub) +#endif + +#if defined (CONFIG_PIC) + GTEXT(_masterStrayIntStub) + GTEXT(_slaveStrayIntStub) +#endif + +#if defined (CONFIG_PIT) + GTEXT(_i8253IntStub) +#endif + + /* externs (internal APIs) */ + + GTEXT(_IntEnt) + GTEXT(_IntExit) + +#if defined(CONFIG_LOAPIC_TIMER) +SECTION_FUNC (TEXT, _loApicTimerIntStub) + call _IntEnt /* Inform kernel interrupt has begun */ + pushl $0 /* Push dummy parameter */ + call _timer_int_handler /* Call actual interrupt handler */ + call _loapic_eoi /* Inform loapic interrupt is done */ + addl $4, %esp /* Clean-up stack from push above */ + jmp _IntExit /* Inform kernel interrupt is done */ +#endif /* CONFIG_LOAPIC_TIMER */ + +#if defined(CONFIG_HPET_TIMER) +SECTION_FUNC(TEXT, _hpetIntStub) + call _IntEnt /* Inform kernel interrupt has begun */ + pushl $0 /* Push dummy parameter */ + call _timer_int_handler /* Call actual interrupt handler */ + call _ioapic_eoi /* Inform ioapic interrupt is done */ + addl $4, %esp /* Clean-up stack from push above */ + jmp _IntExit /* Inform kernel interrupt is done */ +#endif /* CONFIG_HPET_TIMER */ + +#if defined(CONFIG_PIC) +SECTION_FUNC(TEXT, _masterStrayIntStub) + /* + * Handle possible spurious (stray) interrupts on IRQ 7. Since on this + * particular BSP, no device is hooked up to IRQ 7, a C level ISR is + * not called as the call to the BOI routine will not return. + */ + call _IntEnt /* Inform kernel interrupt has begun */ + call _i8259_boi_master /* Call the BOI routine (won't return) */ + + /* + * If an actual device was installed on IRQ 7, then the BOI may return, + * indicating a real interrupt was asserted on IRQ 7. + * The following code should be invoked in this case to invoke the ISR: + * + * pushl $param /+ Push argument to ISR +/ + * call ISR /+ Call 'C' level ISR +/ + * addl $4, %esp /+ pop arg to ISR +/ + * jmp _IntExit /+ Inform kernel interrupt is done +/ + */ + +SECTION_FUNC(TEXT, _slaveStrayIntStub) + /* + * Handle possible spurious (stray) interrupts on IRQ 15 (slave PIC + * IRQ 7). Since on this particular BSP, no device is hooked up to + * IRQ 15, a C level ISR is not called as the call the BOI routine + * will not return. + */ + call _IntEnt /* Inform kernel interrupt has begun */ + call _i8259_boi_slave /* Call the BOI routine (won't return) */ + + /* + * If an actual device was installed on IRQ 15, then the BOI may return, + * indicating a real interrupt was asserted on IRQ 15. + * The following code should be invoked in this case to invoke the ISR: + * + * pushl $param /+ Push argument to ISR +/ + * call ISR /+ Call 'C' level ISR +/ + * addl $4, %esp /+ pop arg to ISR +/ + * jmp _IntExit /+ Inform kernel interrupt is done +/ + */ +#endif /* CONFIG_PIC */ + +#if defined(CONFIG_PIT) +SECTION_FUNC(TEXT, _i8253IntStub) + call _IntEnt /* Inform kernel interrupt has begun */ + pushl $0 /* Push dummy parameter */ + call _timer_int_handler /* Call actual interrupt handler */ + call _i8259_eoi_master /* Inform the PIC interrupt is done */ + addl $4, %esp /* Clean-up stack from push above */ + jmp _IntExit /* Inform kernel interrupt is done */ +#endif /* CONFIG_PIT */ + +#endif /* !CONFIG_DYNAMIC_INT_STUBS */ diff --git a/arch/x86/bsp/i8259Boi.s b/arch/x86/bsp/i8259Boi.s new file mode 100644 index 00000000000..45f9da12f9e --- /dev/null +++ b/arch/x86/bsp/i8259Boi.s @@ -0,0 +1,151 @@ +/* i8259Boi.s - Intel 8259A PIC BOI Handler */ + +/* + * Copyright (c) 2013-2015 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ +/* +DESCRIPTION + +The PIC BOI handler determines if the IRQ in question is a spurious or real +interrupt. The IRQ inputs must remain high until after the falling edge of the +first INTA. A spurious interrupt on IRQ 7 can occur if the IRQ input goes low +before this time when the CPU acknowledges the interrupt. In this case, the +interrupt handler should simply return without sending an EOI command. + +The distinction between a spurious interrupt and a real one is detected by +looking at the in service register (ISR). The bit (bit 7) will be 1 indicating +a real IRQ has been inserted. + +*/ + +/* includes */ +#define _ASMLANGUAGE + +#include +#include + +#include +#include + + /* externs */ + + GTEXT(_IntExit) + GDATA(_I8259SpuriousIntCount) + + +/******************************************************************************* +* +* _i8259_boi_master - detect whether it is spurious interrupt or not +* +* This routine is called before the user's interrupt handler to detect the +* spurious interrupt on the master PIC. If a spurious interrupt condition is +* detected, a global variable is incremented and the execution of the interrupt +* stub is "short circuited", i.e. a return to the interrupted context +* occurs. +* +* void _i8259_boi_master (void) +* +* RETURNS: N/A +*/ + +SECTION_FUNC(TEXT, _i8259_boi_master) + /* disable interrupts */ + pushfl + cli + + /* Master PIC, get contents of in serivce register */ + PLB_BYTE_REG_WRITE (0x0b, PIC_PORT1(PIC_MASTER_BASE_ADRS)) + PLB_BYTE_REG_READ (PIC_PORT1(PIC_MASTER_BASE_ADRS)) + + /* enable interrupts */ + popfl + + /* Contents of ISR in %AL */ + andb $0x80, %al + je spur_isr + + ret + + +/******************************************************************************* +* +* _i8259_boi_slave - detect whether it is spurious interrupt or not +* +* This routine is called before the user's interrupt handler to detect the +* spurious interrupt on the slave PIC. If a spurious interrupt condition is +* detected, a global variable is incremented and the execution of the interrupt +* stub is "short circuited", i.e. a return to the interrupted context +* occurs. +* +* void _i8259_boi_slave (void) +* +* RETURNS: N/A +*/ + +SECTION_FUNC(TEXT, _i8259_boi_slave) + /* disable interrupts */ + pushfl + cli + + /* Slave PIC, get contents of in serivce register */ + PLB_BYTE_REG_WRITE (0x0b, PIC_PORT1 (PIC_SLAVE_BASE_ADRS)) + PLB_BYTE_REG_READ (PIC_PORT1 (PIC_SLAVE_BASE_ADRS)) + + /* Contents of ISR in EAX */ + testb %al, %al + jne check_isr + + /* Check the master PIC's in service register for slave PIC IRQ */ + PLB_BYTE_REG_WRITE (0x0b, PIC_PORT1(PIC_MASTER_BASE_ADRS)) + PLB_BYTE_REG_READ (PIC_PORT1(PIC_MASTER_BASE_ADRS)) + + /* Slave connected to IRQ2 on master */ + testb $0x4, %al + je check_isr + + /* Send non-specific EOI to the master PIC IRQ2 */ + PLB_BYTE_REG_WRITE (I8259_EOI, PIC_IACK (PIC_MASTER_BASE_ADRS)); + +BRANCH_LABEL(check_isr) + /* unlock interrupts */ + popfl + + /* Contents of ISR for either PIC in %AL */ + andb $0x80, %al + je spur_isr + + ret + +BRANCH_LABEL(spur_isr) + /* An actual spurious interrupt. Increment counter and short circuit */ + incl _I8259SpuriousIntCount + + /* Pop the return address */ + addl $4, %esp + jmp _IntExit diff --git a/arch/x86/bsp/rand32.c b/arch/x86/bsp/rand32.c new file mode 100644 index 00000000000..2ef619cc9ca --- /dev/null +++ b/arch/x86/bsp/rand32.c @@ -0,0 +1,84 @@ +/* rand32.c - non-random number generator */ + +/* + * Copyright (c) 2013-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This module provides a non-random implementation of _Rand32Get(), which is not +meant to be used in a final product as a truly random number generator. It +was provided to allow testing of kernel stack canaries on a BSP that does not +(yet) provide a random number generator. +*/ + +#include + +#if defined(CONFIG_TEST_RANDOM_GENERATOR) +/******************************************************************************* + * + * _Rand32Init - initialize the random number generator + * + * The non-random number generator does not require any initialization. + * + * RETURNS: N/A + */ + +void _Rand32Init(void) +{ +} + +/******************************************************************************* + * + * _Rand32Get - get a 32 bit random number + * + * The non-random number generator returns values that are based off the + * CPU's timestamp counter, which means that successive calls will normally + * display ever-increasing values. + * + * RETURNS: a 32-bit number + */ + +#if defined(__GNUC__) +uint32_t _Rand32Get(void) +{ + uint32_t rv; + + __asm__ volatile("rdtsc" : "=a"(rv) : : "%edx"); + + return rv; +} +#elif defined(__DCC__) +__asm volatile uint32_t _Rand32Get(void) +{ + % !"ax", "dx" rdtsc +} +#endif /* __GNUCC__/__DCC__ */ + +#endif /* CONFIG_TEST_RANDOM_GENERATOR */ diff --git a/arch/x86/bsp/sysFatalErrorHandler.c b/arch/x86/bsp/sysFatalErrorHandler.c new file mode 100644 index 00000000000..2fe5ef844b5 --- /dev/null +++ b/arch/x86/bsp/sysFatalErrorHandler.c @@ -0,0 +1,112 @@ +/* sysFatalErrorHandler - common system fatal error handler */ + +/* + * Copyright (c) 2013-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This module provides the _SysFatalErrorHandler() routine which is common to +supported BSPs. +*/ + +/* includes */ + +#include +#include +#include +#include +#include + +#ifdef CONFIG_PRINTK +#include +#define PRINTK(...) printk(__VA_ARGS__) +#else +#define PRINTK(...) +#endif /* CONFIG_PRINTK */ + +/******************************************************************************* +* +* _SysFatalErrorHandler - fatal error handler +* +* This routine implements the corrective action to be taken when the system +* detects a fatal error. +* +* This sample implementation attempts to abort the current context and allow +* the system to continue executing, which may permit the system to continue +* functioning with degraded capabilities. +* +* System designers may wish to enhance or substitute this sample +* implementation to take other actions, such as logging error (or debug) +* information to a persistent repository and/or rebooting the system. +* +* RETURNS: This function does not return. +* +* \NOMANUAL +*/ + +FUNC_NORETURN void _SysFatalErrorHandler( + unsigned int reason, /* fatal error reason */ + const NANO_ESF * pEsf /* pointer to exception stack frame */ + ) +{ + nano_context_type_t curCtx = context_type_get(); + + ARG_UNUSED(reason); + ARG_UNUSED(pEsf); + + if ((curCtx != NANO_CTX_ISR) && !_context_essential_check(NULL)) { +#ifdef CONFIG_MICROKERNEL + if (curCtx == NANO_CTX_TASK) { + extern FUNC_NORETURN void _TaskAbort(void); + PRINTK("Fatal task error! Aborting task.\n"); + _TaskAbort(); + } else +#endif /* CONFIG_MICROKERNEL */ + { + PRINTK("Fatal fiber error! Aborting fiber.\n"); + fiber_abort(); + } + } else { +#ifdef CONFIG_PRINTK + /* + * Conditionalize the ctxText[] definition to prevent an "unused + * variable" warning when the PRINTK kconfig option is disabled. + */ + + static char *ctxText[] = {"ISR", "essential fiber", + "essential task"}; + + PRINTK("Fatal %s error! Spinning...\n", ctxText[curCtx]); +#endif /* CONFIG_PRINTK */ + } + + do { + } while (1); +} diff --git a/arch/x86/bsp/systemApic.c b/arch/x86/bsp/systemApic.c new file mode 100644 index 00000000000..da98c969c5e --- /dev/null +++ b/arch/x86/bsp/systemApic.c @@ -0,0 +1,252 @@ +/* systemApic.c - system module for variants with LOAPIC */ + +/* + * Copyright (c) 2013-2015, Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This module provides routines to initialize and support board-level hardware +for the atom_n28xx variant of generic_pc BSP. +*/ + +#include +#include "board.h" +#include +#include +#include +#include + +/******************************************************************************* +* +* _SysIntVecAlloc - allocate interrupt vector +* +* This BSP provided routine supports the irq_connect() API. This +* routine is required to perform the following 3 functions: +* +* a) Allocate a vector satisfying the requested priority. The utility routine +* _IntVecAlloc() provided by the nanokernel will be used to perform the +* the allocation since the local APIC prioritizes interrupts as assumed +* by _IntVecAlloc(). +* b) Return End of Interrupt (EOI) and Beginning of Interrupt (BOI) related +* information to be used when generating the interrupt stub code, and +* c) If an interrupt vector can be allocated, and the argument is not +* equal to NANO_SOFT_IRQ, the IOAPIC redirection table (RED) or the +* LOAPIC local vector table (LVT) will be updated with the allocated +* interrupt vector. +* +* The board virtualizes IRQs as follows: +* +* - The first IOAPIC_NUM_RTES IRQs are provided by the IOAPIC +* - The remaining IRQs are provided by the LOAPIC. +* +* Thus, for example, if the IOAPIC supports 24 IRQs: +* +* - IRQ0 to IRQ23 map to IOAPIC IRQ0 to IRQ23 +* - IRQ24 to IRQ29 map to LOAPIC LVT entries as follows: +* +* IRQ24 -> LOAPIC_TIMER +* IRQ25 -> LOAPIC_THERMAL +* IRQ26 -> LOAPIC_PMC +* IRQ27 -> LOAPIC_LINT0 +* IRQ28 -> LOAPIC_LINT1 +* IRQ29 -> LOAPIC_ERROR +* +* The IOAPIC_NUM_RTES macro is provided by board.h, and it specifies the number +* of IRQs supported by the on-board I/O APIC device. +* +* RETURNS: the allocated interrupt vector +* +* INTERNAL +* For debug kernels, this routine will return -1 if there are no vectors +* remaining in the specified level, or if the or +* parameters are invalid. +*/ + +int _SysIntVecAlloc( + unsigned int irq, /* virtualized IRQ */ + unsigned int priority, /* get vector from group */ + NANO_EOI_GET_FUNC * boiRtn, /* ptr to BOI routine; NULL if none */ + NANO_EOI_GET_FUNC * eoiRtn, /* ptr to EOI routine; NULL if none */ + void **boiRtnParm, /* BOI routine parameter, if any */ + void **eoiRtnParm, /* EOI routine parameter, if any */ + unsigned char *boiParamRequired, /* BOI routine parameter req? */ + unsigned char *eoiParamRequired /* BOI routine parameter req? */ + ) +{ + int vector; + + ARG_UNUSED(boiRtnParm); + ARG_UNUSED(boiParamRequired); + +#if defined(DEBUG) + if ((priority > 15) || + ((irq > (IOAPIC_NUM_RTES + 5)) && (irq != NANO_SOFT_IRQ))) + return -1; +#endif + + /* + * Use the nanokernel utility function _IntVecAlloc(). A value of + * -1 will be returned if there are no free vectors in the requested + * priority. + */ + + vector = _IntVecAlloc(priority); + __ASSERT(vector != -1, "No free vectors in the requested priority"); + + /* + * Set up the appropriate interrupt controller to generate the allocated + * interrupt vector for the specified IRQ. Also, provide the required + * EOI and BOI related information for the interrupt stub code + *generation + * step. + * + * For software interrupts (NANO_SOFT_IRQ), skip the interrupt + *controller + * programming step, and indicate that a BOI and EOI handler is not + * required. + * + * Skip both steps if a vector could not be allocated. + */ + + *boiRtn = (NANO_EOI_GET_FUNC)NULL; /* a BOI handler is never required */ + *eoiRtn = (NANO_EOI_GET_FUNC)NULL; /* assume NANO_SOFT_IRQ */ + +#if defined(DEBUG) + if ((vector != -1) && (irq != NANO_SOFT_IRQ)) +#else + if (irq != NANO_SOFT_IRQ) +#endif + { + if (irq < IOAPIC_NUM_RTES) { + _ioapic_int_vec_set(irq, vector); + + /* + * query IOAPIC driver to obtain EOI handler information + * for the + * interrupt vector that was just assigned to the + * specified IRQ + */ + + *eoiRtn = (NANO_EOI_GET_FUNC)_ioapic_eoi_get( + irq, (char *)eoiParamRequired, eoiRtnParm); + } else { + _loapic_int_vec_set(irq - IOAPIC_NUM_RTES, vector); + + /* specify that the EOI handler in loApicIntr.c driver + * be invoked */ + + *eoiRtn = (NANO_EOI_GET_FUNC)_loapic_eoi; + *eoiParamRequired = 0; + } + } + + return vector; +} + +/******************************************************************************* +* +* _SysIntVecProgram - program interrupt controller +* +* This BSP provided routine programs the appropriate interrupt controller +* with the given vector based on the given IRQ parameter. +* +* Drivers call this routine instead of irq_connect() when interrupts are +* configured statically. +* +* The Clanton board virtualizes IRQs as follows: +* +* - The first IOAPIC_NUM_RTES IRQs are provided by the IOAPIC so the IOAPIC +* is programmed for these IRQs +* - The remaining IRQs are provided by the LOAPIC and hence the LOAPIC is +* programmed. +* +* The IOAPIC_NUM_RTES macro is provided by board.h, and it specifies the number +* of IRQs supported by the on-board I/O APIC device. +* +*/ + +void _SysIntVecProgram(unsigned int vector, /* vector number */ + unsigned int irq /* virtualized IRQ */ + ) +{ + + if (irq < IOAPIC_NUM_RTES) { + _ioapic_int_vec_set(irq, vector); + } else { + _loapic_int_vec_set(irq - IOAPIC_NUM_RTES, vector); + } +} + + +/******************************************************************************* +* +* irq_enable - enable an individual interrupt (IRQ) +* +* The public interface for enabling/disabling a specific IRQ for the IA-32 +* architecture is defined as follows in include/nanokernel/x86/arch.h +* +* extern void irq_enable (unsigned int irq); +* extern void irq_disable (unsigned int irq); +* +* The irq_enable() routine is provided by the BSP due to the +* IRQ virtualization that is performed by this BSP. See the comments +* in _SysIntVecAlloc() for more information regarding IRQ virtualization. +* +* RETURNS: N/A +*/ + +void irq_enable(unsigned int irq) +{ + if (irq < IOAPIC_NUM_RTES) { + _ioapic_irq_enable(irq); + } else { + _loapic_irq_enable(irq - IOAPIC_NUM_RTES); + } +} + +/******************************************************************************* +* +* irq_disable - disable an individual interrupt (IRQ) +* +* The irq_disable() routine is provided by the BSP due to the +* IRQ virtualization that is performed by this BSP. See the comments +* in _SysIntVecAlloc() for more information regarding IRQ virtualization. +* +* RETURNS: N/A +*/ + +void irq_disable(unsigned int irq) +{ + if (irq < IOAPIC_NUM_RTES) { + _ioapic_irq_disable(irq); + } else { + _loapic_irq_disable(irq - IOAPIC_NUM_RTES); + } +} diff --git a/arch/x86/bsp/systemPic.c b/arch/x86/bsp/systemPic.c new file mode 100644 index 00000000000..a9f96a9310f --- /dev/null +++ b/arch/x86/bsp/systemPic.c @@ -0,0 +1,150 @@ +/* systemPic.c - system module for variants with PIC */ + +/* + * Copyright (c) 2013-2015, Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This module provides routines to initialize and support board-level hardware +for the pentium4 and minuteia variants of the generic_pc BSP. +*/ + +#include "board.h" +#include +#include +#include + +/* Handle possible stray or spurious interrupts on the master and slave PICs */ +extern void _masterStrayIntStub(void); +extern void _slaveStrayIntStub(void); +SYS_INT_REGISTER(_masterStrayIntStub, PIC_MASTER_STRAY_INT_LVL, 0); +SYS_INT_REGISTER(_slaveStrayIntStub, PIC_SLAVE_STRAY_INT_LVL, 0); + +/******************************************************************************* +* +* _SysIntVecAlloc - allocate interrupt vector +* +* This BSP provided routine supports the irq_connect() API. This +* routine performs the following functions: +* +* a) Allocates a vector satisfying the requested priority, where possible. +* When the argument is not equal to NANO_SOFT_IRQ, the vector assigned +* to the during interrupt controller initialization is returned, +* which may or may not have the desired prioritization. (Prioritization of +* such vectors is fixed by the 8259 interrupt controllers, and cannot be +* programmed on an IRQ basis; for example, IRQ0 is always the highest +* priority interrupt no matter which interrupt vector was assigned to IRQ0.) +* b) Provides End of Interrupt (EOI) and Beginning of Interrupt (BOI) related +* information to be used when generating the interrupt stub code. +* +* The pcPentium4 board virtualizes IRQs as follows: +* +* - IRQ0 to IRQ7 are provided by the master i8259 PIC +* - IRQ8 to IRQ15 are provided by the slave i8259 PIC +* +* RETURNS: the allocated interrupt vector +* +* INTERNAL +* For debug kernels, this routine will return -1 for invalid or +* parameter values. +*/ + +int _SysIntVecAlloc( + unsigned int irq, /* virtualized IRQ */ + unsigned int priority, /* get vector from group */ + NANO_EOI_GET_FUNC * boiRtn, /* ptr to BOI routine; NULL if none */ + NANO_EOI_GET_FUNC * eoiRtn, /* ptr to EOI routine; NULL if none */ + void **boiRtnParm, /* BOI routine parameter, if any */ + void **eoiRtnParm, /* EOI routine parameter, if any */ + unsigned char *boiParamRequired, /* BOI routine parameter req? */ + unsigned char *eoiParamRequired /* BOI routine parameter req? */ + ) +{ + int vector; + + ARG_UNUSED(boiRtnParm); + ARG_UNUSED(eoiRtnParm); + +#if defined(DEBUG) + if ((priority > 15) || (irq > 15) && (irq != NANO_SOFT_IRQ)) + return -1; +#endif + + /* The PIC BOI does not require a parameter */ + + *boiParamRequired = 0; + + /* Assume BOI is not required */ + + *boiRtn = (NANO_EOI_GET_FUNC)NULL; + + if (irq != NANO_SOFT_IRQ) { + /* convert interrupt 'vector' to an interrupt controller IRQ + * number */ + + vector = INT_VEC_IRQ0 + irq; + + /* mark vector as allocated */ + + _IntVecMarkAllocated(vector); + + /* vector not handled by PIC, thus don't specify an EOI handler + */ + + if (irq >= N_PIC_IRQS) { + *eoiRtn = (NANO_EOI_GET_FUNC)NULL; + return vector; + } + + if (irq == PIC_MASTER_STRAY_INT_LVL) { + *boiRtn = (NANO_EOI_GET_FUNC)_i8259_boi_master; + } else if (irq == PIC_SLAVE_STRAY_INT_LVL) { + *boiRtn = (NANO_EOI_GET_FUNC)_i8259_boi_slave; + } + + if (irq <= PIC_MASTER_STRAY_INT_LVL) + *eoiRtn = (NANO_EOI_GET_FUNC)_i8259_eoi_master; + else + *eoiRtn = (NANO_EOI_GET_FUNC)_i8259_eoi_slave; + + *eoiParamRequired = 0; + } else { + /* + * Use the nanokernel utility function _IntVecAlloc() to + * allocate + * a vector for software generated interrupts. + */ + + vector = _IntVecAlloc(priority); + *eoiRtn = (NANO_EOI_GET_FUNC)NULL; + } + + return vector; +} diff --git a/arch/x86/core/cpuhalt.s b/arch/x86/core/cpuhalt.s new file mode 100644 index 00000000000..9ea3c0f746d --- /dev/null +++ b/arch/x86/core/cpuhalt.s @@ -0,0 +1,169 @@ +/* cpuhalt.s - VxMicro CPU power management code for IA-32 */ + +/* + * Copyright (c) 2011-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This module provides an implementation of the architecture-specific +nano_cpu_idle() primitive required by the nanokernel idle loop component. +It can be called within an implementation of _SysPowerSaveIdle(), +which is provided for the microkernel by the BSP. + +The module also provides an implementation of nano_cpu_atomic_idle(), which +atomically re-enables interrupts and enters low power mode. + +INTERNAL +These implementations of nano_cpu_idle() and nano_cpu_atomic_idle() could be used +when operating as a Hypervisor guest. More specifically, the Hypervisor +supports the execution of the 'hlt' instruction from a guest (results in a +VM exit), and more importantly, the Hypervisor will respect the +single instruction delay slot after the 'sti' instruction as required +by nano_cpu_atomic_idle(). +*/ + +#define _ASMLANGUAGE + +#include + + /* exports (external APIs) */ + + GTEXT(nano_cpu_idle) + GTEXT(nano_cpu_atomic_idle) + +#if defined(CONFIG_BOOT_TIME_MEASUREMENT) + GDATA(__idle_tsc) +#endif + +#ifndef CONFIG_NO_ISRS + +/******************************************************************************* +* +* nano_cpu_idle - power save idle routine for IA-32 +* +* This function will be called by the nanokernel idle loop or possibly within +* an implementation of _SysPowerSaveIdle in the microkernel when the +* '_SysPowerSaveFlag' variable is non-zero. The IA-32 'hlt' instruction +* will be issued causing a low-power consumption sleep mode. +* +* RETURNS: N/A +* +* C function prototype: +* +* void nano_cpu_idle (void); +*/ + +SECTION_FUNC(TEXT, nano_cpu_idle) +#ifdef CONFIG_INT_LATENCY_BENCHMARK + call _IntLatencyStop +#endif +#if defined(CONFIG_BOOT_TIME_MEASUREMENT) + rdtsc /* record idle timestamp */ + mov %eax, __idle_tsc /* ... low 32 bits */ + mov %edx, __idle_tsc+4 /* ... high 32 bits */ +#endif + sti /* make sure interrupts are enabled */ + hlt /* sleep */ + ret /* return after processing ISR */ + + +/******************************************************************************* +* +* nano_cpu_atomic_idle - atomically re-enable interrupts and enter low power mode +* +* This function is utilized by the nanokernel object "wait" APIs for task +* contexts, e.g. nano_task_lifo_get_wait(), nano_task_sem_take_wait(), nano_task_stack_pop_wait(), +* and nano_task_fifo_get_wait(). +* +* INTERNAL +* The requirements for nano_cpu_atomic_idle() are as follows: +* 1) The enablement of interrupts and entering a low-power mode needs to be +* atomic, i.e. there should be no period of time where interrupts are +* enabled before the processor enters a low-power mode. See the comments +* in nano_task_lifo_get_wait(), for example, of the race condition that occurs +* if this requirement is not met. +* +* 2) After waking up from the low-power mode, the interrupt lockout state +* must be restored as indicated in the 'imask' input parameter. +* +* RETURNS: N/A +* +* C function prototype: +* +* void nano_cpu_atomic_idle (unsigned int imask); +*/ + +SECTION_FUNC(TEXT, nano_cpu_atomic_idle) +#ifdef CONFIG_INT_LATENCY_BENCHMARK + call _IntLatencyStop +#endif + sti /* make sure interrupts are enabled */ + + /* + * The following statement appears in "Intel 64 and IA-32 Architectures + * Software Developer's Manual", regarding the 'sti' instruction: + * + * "After the IF flag is set, the processor begins responding to + * external, maskable interrupts after the next instruction is + * executed." + * + * Thus the IA-32 implementation of nano_cpu_atomic_idle() will atomically + * re-enable interrupts and enter a low-power mode. + */ + + hlt + + /* restore interrupt lockout state before returning to caller */ + + testl $0x200, SP_ARG1(%esp) + jnz skipIntDisable +#ifdef CONFIG_INT_LATENCY_BENCHMARK + call _IntLatencyStart +#endif + cli +BRANCH_LABEL(skipIntDisable) + + ret + +#else + +/* + * When no interrupt support is configured, both nano_cpu_idle() and + * nano_cpu_atomic_idle() are "no op" routines that simply return immediately + * without entering low-power mode. + */ + +SECTION_FUNC(TEXT, nano_cpu_idle) +SECTION_FUNC(TEXT, nano_cpu_atomic_idle) + + ret + +#endif /* !CONFIG_NO_ISRS */ + diff --git a/arch/x86/core/excconnect.c b/arch/x86/core/excconnect.c new file mode 100644 index 00000000000..dc1255893ea --- /dev/null +++ b/arch/x86/core/excconnect.c @@ -0,0 +1,246 @@ +/* excconnect.c - VxMicro exception management support for IA-32 arch */ + +/* + * Copyright (c) 2010-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This module provides routines to manage exceptions (synchronous interrupts) +in VxMicro on the IA-32 architecture. + +This module provides the public routine nanoCpuExcConnect(). + +INTERNAL +An exception is defined as a synchronous interrupt, i.e. an interrupt +asserted as a direct result of program execution as opposed to a +hardware device asserting an interrupt. + +Many (but not all) exceptions are handled by an "exception stub" whose code +is generated by the system itself. The stub performs various actions before +and after invoking the application (or operating system) specific exception +handler; for example, a thread or ISR context save is performed prior to +invoking the exception handler. + +The IA-32 code that makes up a "full" exception stub is shown below. A full +exception stub is one that pushes a dummy error code at the start of +exception processing. Exception types where the processor automatically +pushes an error code when handling an exception utilize similar exception +stubs, however the first instruction is omitted. The use of the dummy error +code means that _ExcEnt() and _ExcExit() do not have to worry about whether +an error code is present on the stack or not. + + + 0x00 pushl $0 /@ push dummy error code @/ + Machine code: 0x68, 0x00, 0x00, 0x00, 0x00 + + 0x05 call _ExcEnt /@ inform kernel of exception @/ + Machine code: 0xe8, 0x00, 0x00, 0x00, 0x00 + + 0x0a call ExcHandler /@ invoke exception handler @/ + Machine code: 0xe8, 0x00, 0x00, 0x00, 0x00 + + /@ _ExcExit() will adjust the stack to discard the error code @/ + + 0x0f jmp _ExcExit /@ restore context context @/ + Machine code: 0xe9, 0x00, 0x00, 0x00, 0x00 + +NOTE: Be sure to update the arch specific definition of the _EXC_STUB_SIZE +macro to reflect the size of the full exception stub (as shown above). +The _EXC_STUB_SIZE macro is defined in kernel/arch/Intel/include/nanok.h +and include/Intel/nanokernel.h. + +*/ + + +#include +#include + + +/* forward declarations */ + +void _NanoCpuExcConnectAtDpl(unsigned int vector, + void (*routine)(NANO_ESF * pEsf), + NANO_EXC_STUB pExcStubMem, + unsigned int dpl); + +/******************************************************************************* +* +* nanoCpuExcConnect - connect a C routine to an exception +* +* This routine connects an exception handler coded in C to the specified +* interrupt vector. An exception is defined as a synchronous interrupt, i.e. +* an interrupt asserted as a direct result of program execution as opposed +* to a hardware device asserting an interrupt. +* +* When the exception specified by is asserted, the current context +* is saved on the current stack, i.e. a switch to some other stack is not +* performed, followed by executing which has the following signature: +* +* void (*routine) (NANO_ESF *pEsf) +* +* The argument points to memory that the system can use to +* synthesize the exception stub that calls . The memory need not be +* initialized, but must be persistent (i.e. it cannot be on the caller's stack). +* Declaring a global or static variable of type NANO_EXC_STUB will provide a +* suitable area of the proper size. +* +* The handler is connected via an interrupt-gate descriptor having a +* descriptor privilege level (DPL) equal to zero. +* +* RETURNS: N/A +* +* INTERNAL +* The function prototype for nanoCpuExcConnect() only exists in nanok.h, +* in other words, it's still considered private since the definitions for +* the NANO_ESF structures have not been completed. +*/ + +void nanoCpuExcConnect(unsigned int vector, /* interrupt vector: 0 to 255 on + IA-32 */ + void (*routine)(NANO_ESF * pEsf), + NANO_EXC_STUB pExcStubMem) +{ + _NanoCpuExcConnectAtDpl(vector, routine, pExcStubMem, 0); +} + +/******************************************************************************* +* +* _NanoCpuExcConnectAtDpl - connect a C routine to an exception +* +* This routine connects an exception handler coded in C to the specified +* interrupt vector. An exception is defined as a synchronous interrupt, i.e. +* an interrupt asserted as a direct result of program execution as opposed +* to a hardware device asserting an interrupt. +* +* When the exception specified by is asserted, the current context +* is saved on the current stack, i.e. a switch to some other stack is not +* performed, followed by executing which has the following signature: +* +* void (*routine) (NANO_ESF *pEsf) +* +* The argument points to memory that the system can use to +* synthesize the exception stub that calls . The memory need not be +* initialized, but must be persistent (i.e. it cannot be on the caller's stack). +* Declaring a global or static variable of type NANO_EXC_STUB will provide a +* suitable area of the proper size. +* +* The handler is connected via an interrupt-gate descriptor having the supplied +* descriptor privilege level (DPL). +* +* RETURNS: N/A +* +* INTERNAL +* The function prototype for nanoCpuExcConnect() only exists in nanok.h, +* in other words, it's still considered private since the definitions for +* the NANO_ESF structures have not been completed. +*/ + +void _NanoCpuExcConnectAtDpl( + unsigned int vector, /* interrupt vector: 0 to 255 on IA-32 */ + void (*routine)(NANO_ESF * pEsf), + NANO_EXC_STUB pExcStubMem, + unsigned int dpl /* priv level for interrupt-gate descriptor */ + ) +{ + extern void _ExcEnt(void); + extern void _ExcExit(void); + unsigned int offsetAdjust = 0; + +#define STUB_PTR pExcStubMem + + /* + * The parameter must be less than IV_INTEL_RESERVED_END, + * however, explicit validation will not be performed in this primitive. + */ + + /* + * If the specified represents an exception type where the CPU + * does not push an error code onto the stack, then generate a stub that + * pushes a dummy code. This results in a single implementation of + * _ExcEnt + * and _ExcExit which expects an error code to be pushed onto the stack + * (along with the faulting CS:EIP and EFLAGS). + */ + + if (((1 << vector) & _EXC_ERROR_CODE_FAULTS) == 0) { + STUB_PTR[0] = IA32_PUSH_OPCODE; + + UNALIGNED_WRITE((unsigned int *)&STUB_PTR[1], + (unsigned int)0 /* value of dummy error code */ + ); + + offsetAdjust = 5; + } + + /* generate code that invokes _ExcEnt() */ + + STUB_PTR[offsetAdjust] = IA32_CALL_OPCODE; + UNALIGNED_WRITE((unsigned int *)&STUB_PTR[1 + offsetAdjust], + (unsigned int)&_ExcEnt - + (unsigned int)&pExcStubMem[5 + offsetAdjust]); + offsetAdjust += 5; + + /* generate code that invokes the exception handler */ + + STUB_PTR[offsetAdjust] = IA32_CALL_OPCODE; + UNALIGNED_WRITE((unsigned int *)&STUB_PTR[1 + offsetAdjust], + (unsigned int)routine - + (unsigned int)&pExcStubMem[5 + offsetAdjust]); + offsetAdjust += 5; + + /* + * generate code that invokes _ExcExit(); note that a jump is used, + * since _ExcExit() takes care of popping the error code and returning + * back to the context that triggered the exception + */ + + STUB_PTR[offsetAdjust] = IA32_JMP_OPCODE; + UNALIGNED_WRITE((unsigned int *)&STUB_PTR[1 + offsetAdjust], + (unsigned int)&_ExcExit - + (unsigned int)&pExcStubMem[5 + offsetAdjust]); + + + /* + * There is no need to explicitly synchronize or flush the instruction + * cache due to the above code synthesis. See the Intel 64 and IA-32 + * Architectures Software Developer's Manual: Volume 3A: System + *Programming + * Guide; specifically the section titled "Self Modifying Code". + * + * Cache synchronization/flushing is not required for the i386 as it + * does not contain any on-chip I-cache; likewise, post-i486 processors + * invalidate the I-cache automatically. An i486 requires the CPU + * to perform a 'jmp' instruction before executing the synthesized code; + * however, the call and return that follows meets this requirement. + */ + + _IntVecSet(vector, (void (*)(void *))pExcStubMem, dpl); +} + diff --git a/arch/x86/core/excstub.s b/arch/x86/core/excstub.s new file mode 100644 index 00000000000..2fa26061364 --- /dev/null +++ b/arch/x86/core/excstub.s @@ -0,0 +1,322 @@ +/* excstub.s - VxMicro exception management support for IA-32 architecture */ + +/* + * Copyright (c) 2011-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This module implements assembly routines to manage exceptions (synchronous +interrupts) in VxMicro on the Intel IA-32 architecture. More specifically, +exceptions are implemented in this module. The stubs are invoked when entering +and exiting a C exception handler. +*/ + +#define _ASMLANGUAGE + +#include +#include +#include /* For MK_ISR_NAME */ +#include /* nanokernel structure offset definitions */ + + +#include + + /* exports (internal APIs) */ + + GTEXT(_ExcEnt) + GTEXT(_ExcExit) + + /* externs (internal APIs) */ + + + +/******************************************************************************* +* +* _ExcEnt - inform the VxMicro kernel of an exception +* +* This function is called from the exception stub created by nanoCpuExcConnect() +* to inform the VxMicro kernel of an exception. This routine currently does +* _not_ increment a context/interrupt specific exception count. Also, +* execution of the exception handler occurs on the current stack, i.e. +* _ExcEnt() does not switch to another stack. The volatile integer +* registers are saved on the stack, and control is returned back to the +* exception stub. +* +* WARNINGS +* +* Host-based tools and the target-based GDB agent depend on the stack frame +* created by this routine to determine the locations of volatile registers. +* These tools must be updated to reflect any changes to the stack frame. +* +* RETURNS: N/A +* +* C function prototype: +* +* void _ExcEnt (void); +* +*/ + +SECTION_FUNC(TEXT, _ExcEnt) + + /* + * The _IntVecSet() routine creates an interrupt-gate descriptor for + * all connections. The processor will automatically clear the IF + * bit in the EFLAGS register upon execution of the handler, thus + * _ExcEnt() (and _IntEnt) need not issue an 'cli' as the first + * instruction. + */ + + + /* + * Note that the processor has pushed both the EFLAGS register + * and the linear return address (cs:eip) onto the stack prior + * to invoking the handler specified in the IDT. + * + * Clear the direction flag. It is automatically restored when the + * exception exits. + */ + + cld + + + /* + * Swap eax and return address on the current stack; + * this saves eax on the stack without losing knowledge + * of how to get back to the exception stub. + */ + +#ifdef CONFIG_LOCK_INSTRUCTION_UNSUPPORTED + + pushl (%esp) + movl %eax, 4(%esp) + popl %eax + +#else + + xchgl %eax, (%esp) + +#endif /* CONFIG_LOCK_INSTRUCTION_UNSUPPORTED*/ + + /* + * Push the remaining volatile registers on the existing stack. + * Note that eax has already been saved on the context stack. + */ + + pushl %ecx + pushl %edx + +#ifdef CONFIG_GDB_INFO + + /* + * Push the cooperative registers on the existing stack as they are + * required by debug tools. + */ + + pushl %edi + pushl %esi + pushl %ebx + pushl %ebp + +#endif /* CONFIG_GDB_INFO */ + + /* + * Save possible faulting address: this has to be done before + * interrupts are re-enabled. + */ + movl %cr2, %ecx + pushl %ecx + + /* ESP is pointing to the ESF at this point */ + + + +#if defined(CONFIG_FP_SHARING) || defined(CONFIG_GDB_INFO) + + movl _NanoKernel + __tNANO_current_OFFSET, %ecx + + incl __tCCS_excNestCount_OFFSET(%ecx) /* inc exception nest count */ + +#ifdef CONFIG_GDB_INFO + + /* + * Save the pointer to the stack frame (NANO_ESF *) in + * the current context if this is the outermost exception. + * The ESF pointer is used by debug tools to locate the volatile + * registers and the stack of the preempted context. + */ + + testl $EXC_ACTIVE, __tCCS_flags_OFFSET (%ecx) + jne alreadyInException + movl %esp, __tCCS_esfPtr_OFFSET(%ecx) + +BRANCH_LABEL(alreadyInException) + +#endif /* CONFIG_GDB_INFO */ + + /* + * Set the EXC_ACTIVE bit in the tCCS of the current context. + * This enables _Swap() to preserve the context's FP registers + * (where needed) if the exception handler causes a context switch. + * It also indicates to debug tools that an exception is being + * handled in the event of a context switch. + */ + + orl $EXC_ACTIVE, __tCCS_flags_OFFSET(%ecx) + +#endif /* CONFIG_FP_SHARING || CONFIG_GDB_INFO */ + + + + /* + * restore interrupt enable state, then "return" back to exception stub + * + * interrupts are enabled only if they were allowed at the time + * the exception was triggered -- this protects kernel level code + * that mustn't be interrupted + * + * Test IF bit of saved EFLAGS and re-enable interrupts if IF=1. + */ + + /* ESP is still pointing to the ESF at this point */ + + testl $0x200, __NANO_ESF_eflags_OFFSET(%esp) + je allDone + sti + +BRANCH_LABEL(allDone) + pushl %esp /* push NANO_ESF * parameter */ + jmp *%eax /* "return" back to stub */ + + +/******************************************************************************* +* +* _ExcExit - inform the VxMicro kernel of an exception exit +* +* This function is called from the exception stub created by nanoCpuExcConnect() +* to inform the VxMicro kernel that the processing of an exception has +* completed. This routine restores the volatile integer registers and +* then control is returned back to the interrupted context or ISR. +* +* RETURNS: N/A +* +* C function prototype: +* +* void _ExcExit (void); +* +*/ + +SECTION_FUNC(TEXT, _ExcExit) + + /* On entry, interrupts may or may not be enabled. */ + + /* discard the NANO_ESF * parameter and CR2 */ + addl $8, %esp + +#if defined(CONFIG_SUPPORT_FP_SHARING) || defined(CONFIG_GDB_INFO) + + movl _NanoKernel + __tNANO_current_OFFSET, %ecx + + /* + * Must lock interrupts to prevent outside interference. + * (Using "lock" prefix would be nicer, but this won't work + * on BSPs that don't respect the CPU's bus lock signal.) + */ + + cli + +#if ( defined(CONFIG_FP_SHARING) || \ + defined(CONFIG_GDB_INFO) ) + /* + * Determine whether exiting from a nested interrupt. + */ + + decl __tCCS_excNestCount_OFFSET(%ecx) /* dec exception nest count */ + + cmpl $0, __tCCS_excNestCount_OFFSET(%ecx) + jne nestedException + + /* + * Clear the EXC_ACTIVE bit in the tCCS of the current context + * if we are not in a nested exception (ie, when we exit the outermost + * exception). + */ + + andl $~EXC_ACTIVE, __tCCS_flags_OFFSET (%ecx) + +BRANCH_LABEL(nestedException) + +#endif /* CONFIG_FP_SHARING || CONFIG_GDB_INFO */ + + +#ifdef CONFIG_GDB_INFO + + /* + * Pop the non-volatile registers from the stack. + * Note that debug tools may have altered the saved register values while + * the task was stopped, and we want to pick up the altered values. + */ + + popl %ebp + popl %ebx + popl %esi + popl %edi + +#endif /* CONFIG_GDB_INFO */ + +#endif /* CONFIG_SUPPORT_FP_SHARING || CONFIG_GDB_INFO */ + + + /* restore edx and ecx which are always saved on the stack */ + + popl %edx + popl %ecx + popl %eax + + addl $4, %esp /* "pop" error code */ + + /* Pop of EFLAGS will re-enable interrupts and restore direction flag */ + iret + +/* Static exception handler stubs */ + + + +#ifdef CONFIG_AUTOMATIC_FP_ENABLING +#if defined(__GNUC__) +NANO_CPU_EXC_CONNECT_NO_ERR(_FpNotAvailableExcHandler,IV_DEVICE_NOT_AVAILABLE,0) +#elif defined(__DCC__) + NANO_CPU_INT_REGISTER_ASM(_FpNotAvailableExcHandler,IV_DEVICE_NOT_AVAILABLE,0) + GTEXT(MK_STUB_NAME(_FpNotAvailableExcHandler)) + SECTION_FUNC(TEXT, MK_STUB_NAME(_FpNotAvailableExcHandler)) + NANO_CPU_EXC_CONNECT_NO_ERR_CODE(_FpNotAvailableExcHandler) +#endif + +#endif /* CONFIG_AUTOMATIC_FP_ENABLING */ + diff --git a/arch/x86/core/ffs.s b/arch/x86/core/ffs.s new file mode 100644 index 00000000000..9c8eb05e80f --- /dev/null +++ b/arch/x86/core/ffs.s @@ -0,0 +1,134 @@ +/* ffs.s - find first set bit APIs for IA-32 architecture */ + +/* + * Copyright (c) 2011-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This module implements the ffsMsb() and ffsLsb() functions for the IA-32 +architecture. + +INTERNAL +Inline versions of these APIs, find_last_set_inline() and find_first_set_inline(), +are defined in arch.h. +*/ + +#define _ASMLANGUAGE + +#include +#include /* nanokernel structure offset definitions */ + + + /* exports (public APIs) */ + + GTEXT(find_last_set) + GTEXT(find_first_set) + +/******************************************************************************* +* +* find_first_set - find first set bit searching from the LSB +* +* This routine finds the first bit set in the passed argument and +* returns the index of that bit. Bits are numbered starting +* at 1 from the least significant bit to 32 for the most significant bit. +* A return value of zero indicates that the value passed is zero. +* +* RETURNS: bit position from 1 to 32, or 0 if the argument is zero. +* +* INTERNAL +* For Intel64 (x86_64) architectures, the 'cmovz' can be removed +* and leverage the fact that the 'bsrl' doesn't modify the destination operand +* when the source operand is zero. The "bitpos" variable can be preloaded +* into the destination register, and given the unconditional ++bitpos that +* is performed after the 'cmovz', the correct results are yielded. +*/ + +SECTION_FUNC(TEXT, find_first_set) + +#if !defined(CONFIG_CMOV_UNSUPPORTED) + + movl $0xffffffff, %ecx /* preload for 0 return value */ + bsfl 0x4(%esp), %eax /* bit scan "forward" */ + cmovz %ecx, %eax /* if operand == 0 then %ecx -> eax */ + addl $1, %eax + ret + +#else + + bsfl 0x4(%esp), %eax /* bit scan "forward" */ + jnz ffsLsb_argNotZero + xorl %eax, %eax /* return 0 when arg=0 */ + ret + +BRANCH_LABEL(ffsLsb_argNotZero) /* this label serves find_first_set() & find_last_set() */ + addl $1, %eax + ret + +#endif /* !CONFIG_CMOV_UNSUPPORTED */ + + +/******************************************************************************* +* +* find_last_set - find first set bit searching from the MSB +* +* This routine finds the first bit set in the passed argument and +* returns the index of that bit. Bits are numbered starting +* at 1 from the least significant bit to 32 for the most significant bit. +* A return value of zero indicates that the value passed is zero. +* +* RETURNS: bit position from 1 to 32, or 0 if the argument is zero. +* +* INTERNAL +* For Intel64 (x86_64) architectures, the 'cmovz' can be removed +* and leverage the fact that the 'bsfl' doesn't modify the destination operand +* when the source operand is zero. The "bitpos" variable can be preloaded +* into the destination register, and given the unconditional ++bitpos that +* is performed after the 'cmovz', the correct results are yielded. +*/ + +SECTION_FUNC(TEXT, find_last_set) + +#if !defined(CONFIG_CMOV_UNSUPPORTED) + + movl $0xffffffff, %ecx /* preload for 0 return value */ + bsrl 0x4(%esp), %eax /* bit scan "reverse" */ + cmovz %ecx, %eax /* if operand == 0 then %ecx -> eax */ + addl $1, %eax + ret + +#else + + bsrl 0x4(%esp), %eax /* bit scan "reverse" */ + jnz ffsLsb_argNotZero + xorl %eax, %eax /* return 0 when arg=0 */ + ret + +#endif /* !CONFIG_CMOV_UNSUPPORTED */ + diff --git a/arch/x86/core/gdt.c b/arch/x86/core/gdt.c new file mode 100644 index 00000000000..d76b97bc550 --- /dev/null +++ b/arch/x86/core/gdt.c @@ -0,0 +1,103 @@ +/* gdt.c - Global Descriptor Table support */ + +/* + * Copyright (c) 2011-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This module contains routines for updating the global descriptor table (GDT) +for the IA-32 architecture. +*/ + +/* includes */ + +#include +#include +#include + +#include +#include +#include + +/* defines */ + +#if (CONFIG_NUM_GDT_SPARE_ENTRIES < 0) +#error "**** CONFIG_NUM_GDT_SPARE_ENTRIES must be at least 0\n\n" +#endif + +#define NUM_BASE_GDT_ENTRIES 3 + +#define MAX_GDT_ENTRIES \ + (NUM_BASE_GDT_ENTRIES + CONFIG_NUM_GDT_SPARE_ENTRIES) + +/* locals */ + +/* + * The RAM based global descriptor table. It is aligned on an 8 byte boundary + * as the Intel manuals recommend this for best performance. + */ + +/* + * For MM_POMS, _GdtEntries must be global so the linker script can + * generate a _GdtEntriesP for crt0.s + */ +static + tGdtDesc + _GdtEntries[MAX_GDT_ENTRIES] + __attribute__((aligned(8))) = { + {/* Entry 0 (selector=0x0000): The "NULL descriptor" */ + 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00}, + { /* Entry 1 (selector=0x0008): Code descriptor: DPL0 */ + 0xffff, /* limit: xffff */ + 0x0000, /* base : xxxx0000 */ + 0x00, /* base : xx00xxxx */ + 0x9b, /* Code e/r, Present, DPL0, Accessed=1 */ + 0xcf, /* limit: fxxxx, Page Gra, 32 bit */ + 0x00 /* base : 00xxxxxx */ + }, + { /* Entry 2 (selector=0x0010): Data descriptor: DPL0 */ + 0xffff, /* limit: xffff */ + 0x0000, /* base : xxxx0000 */ + 0x00, /* base : xx00xxxx */ + 0x93, /* Data r/w, Present, DPL0, Accessed=1 */ + 0xcf, /* limit: fxxxx, Page Gra, 32 bit */ + 0x00 /* base : 00xxxxxx */ + }, +}; + +/* globals */ + +tGdtHeader _Gdt = { + sizeof(tGdtDesc[MAX_GDT_ENTRIES - CONFIG_NUM_GDT_SPARE_ENTRIES]) - + 1, + &_GdtEntries[0]}; + + + diff --git a/arch/x86/core/intboiexit.s b/arch/x86/core/intboiexit.s new file mode 100644 index 00000000000..17b6dc12392 --- /dev/null +++ b/arch/x86/core/intboiexit.s @@ -0,0 +1,82 @@ +/* intboiexit.s - VxMicro spurious interrupt support for IA-32 architecture */ + +/* + * Copyright (c) 2010-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This module implements the single interrupt handling routine _IntBoiExit(). +This routine is used by some interrupt controller drivers (e.g. the Intel +8259A driver) to short circuit the execution of normal interrupt stub +processing when a spurious interrupt is detected. + +When a spurious interrupt condition is detected by the interrupt controller's +"beginning of interrupt" (BOI) handler it forces a return to _IntBoiExit() +rather than returning back to the interrupt stub. The _IntBoiExit() routine +then pops the parameter passed to the BOI handler and branches to _IntExit(), +thereby circumventing execution of the "application" ISR and the interrupt +controller driver's "end of interrupt" (EOI) handler (if present). + +\INTERNAL +The _IntBoiExit() routine is provided in a separate module so that it gets +included in the final image only if an interrupt controller driver utilizing +_IntBoiExit() is present. + +*/ + +#define _ASMLANGUAGE +#include +#include /* nanokernel structure offset definitions */ + + + /* exports (internal APIs) */ + + GTEXT(_IntBoiExit) + + /* externs */ + + GTEXT(_IntExit) + +/******************************************************************************* +* +* _IntBoiExit - exit interrupt handler stub without invoking ISR +* +* This routine exits an interrupt handler stub without invoking the associated +* ISR handler (or the EOI handler, if present). It should only be jumped to +* by an interrupt controller driver's BOI routine, and only if the BOI routine +* is passed a single parameter by the interrupt stub. +* +* \INTERNAL +* A BOI routine that has no parameters can jump directly to _IntExit(). +*/ + +SECTION_FUNC(TEXT, _IntBoiExit) + addl $4, %esp /* pop off the $BoiParameter */ + jmp FUNC(_IntExit) /* exit via kernel */ diff --git a/arch/x86/core/intconnect.c b/arch/x86/core/intconnect.c new file mode 100644 index 00000000000..52a1124fbef --- /dev/null +++ b/arch/x86/core/intconnect.c @@ -0,0 +1,600 @@ +/* intconnect.c - VxMicro interrupt management support for IA-32 arch */ + +/* + * Copyright (c) 2010-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This module provides routines to manage asynchronous interrupts in VxMicro +on the IA-32 architecture. + +This module provides the public routine irq_connect(), the private +routine _IntVecSet(), and the BSP support routines _IntVecAlloc(), +_IntVecMarkAllocated() and _IntVecMarkFree(). + +INTERNAL +The _IdtBaseAddress symbol is used to determine the base address of the IDT. +(It is generated by the linker script, and doesn't correspond to an actual +global variable.) + +Interrupts are handled by an "interrupt stub" whose code is generated by the +system itself. The stub performs various actions before and after invoking +the application (or operating system) specific interrupt handler; for example, +a thread context save is performed prior to invoking the interrupt handler. + +The IA-32 code that makes up a "full" interrupt stub is shown below. A full +interrupt stub is one that is associated with an interrupt vector that requires +a "beginning of interrupt" (BOI) callout and an "end of interrupt" (EOI) callout +(both of which require a parameter). + + 0x00 call _IntEnt /@ inform kernel of interrupt @/ + Machine code: 0xe8, 0x00, 0x00, 0x00, 0x00 + + 0x05 pushl $BoiParameter /@ optional: push BOI handler parameter @/ + Machine code: 0x68, 0x00, 0x00, 0x00, 0x00 + + 0x0a call BoiRoutine /@ optional: callout to BOI rtn @/ + Machine code: 0xe8, 0x00, 0x00, 0x00, 0x00 + + 0x0f pushl $IsrParameter /@ push ISR parameter @/ + Machine code: 0x68, 0x00, 0x00, 0x00, 0x00 + + 0x14 call IsrRoutine /@ invoke ISR @/ + Machine code: 0xe8, 0x00, 0x00, 0x00, 0x00 + + 0x19 pushl $EoiParameter /@ optional: push EOI handler parameter @/ + Machine code: 0x68, 0x00, 0x00, 0x00, 0x00 + + 0x1e call EoiRoutine /@ optional: callout to EOI rtn @/ + Machine code: 0xe8, 0x00, 0x00, 0x00, 0x00 + + 0x23 addl $(4 * numParams), %esp /@ pop parameters @/ + Machine code: 0x83, 0xc4, (4 * numParams) + + 0x26 jmp _IntExit /@ restore context or reschedule @/ + Machine code: 0xe9, 0x00, 0x00, 0x00, 0x00 + +NOTE: Be sure to update the arch specific definition of the _INT_STUB_SIZE macro +to reflect the maximum potential size of the interrupt stub (as shown above). +The _INT_STUB_SIZE macro is defined in kernel/arch/Intel/include/nanok.h +and include/Intel/nanokernel.h + +*/ + +#ifndef CONFIG_NO_ISRS + +#include +#include +#include + +/* the _IdtBaseAddress symbol is generated via a linker script */ + +extern unsigned char _IdtBaseAddress[]; + +extern void _SpuriousIntHandler(void *); +extern void _SpuriousIntNoErrCodeHandler(void *); + +/* + * These 'dummy' variables are used in nanoArchInit() to force the inclusion of + * the spurious interrupt handlers. They *must* be declared in a module other + * than the one they are used in to get around garbage collection issues and + * warnings issued some compilers that they aren't used. Therefore care must + * be taken if they are to be moved. See nanok.h for more information. + */ +void *__DummySpur; +void *__DummyExcEnt; + +/* + * Place the addresses of the spurious interrupt handlers into the intList + * section. The genIdt tool can then populate any unused vectors with + * these routines. + */ +void *__attribute__((section(".spurIsr"))) MK_ISR_NAME(_SpuriousIntHandler) = + &_SpuriousIntHandler; +void *__attribute__((section(".spurNoErrIsr"))) + MK_ISR_NAME(_SpuriousIntNoErrCodeHandler) = + &_SpuriousIntNoErrCodeHandler; + +/* + * Bitfield used to track which interrupt vectors are available for allocation. + * The array is initialized to indicate all vectors are currently available. + * + * NOTE: For portability reasons, the ROUND_UP() macro can NOT be used to + * perform the rounding up calculation below. Unlike both GCC and ICC, the + * Diab compiler generates an error when a macro that takes a parameter is + * used to define the size of an array. + */ + +#define VEC_ALLOC_NUM_INTS ((CONFIG_IDT_NUM_VECTORS + 31) & ~31) / 32 + +static unsigned int _VectorsAllocated[VEC_ALLOC_NUM_INTS] = { + [0 ...(VEC_ALLOC_NUM_INTS - 1)] = 0xffffffff +}; + +/******************************************************************************* +* +* _IntVecSet - connect a routine to an interrupt vector +* +* This routine "connects" the specified to the specified interrupt +* . On the IA-32 architecture, an interrupt vector is a value from +* 0 to 255. This routine merely fills in the appropriate interrupt +* descriptor table (IDT) with an interrupt-gate descriptor such that +* is invoked when interrupt is asserted. The argument specifies +* the privilege level for the interrupt-gate descriptor; (hardware) interrupts +* and exceptions should specify a level of 0, whereas handlers for user-mode +* software generated interrupts should specify 3. +* +* RETURNS: N/A +* +* INTERNAL +* Unlike nanoCpuExcConnect() and irq_connect(), the _IntVecSet() routine +* is a very basic API that simply updates the appropriate entry in Interrupt +* Descriptor Table (IDT) such that the specified routine is invoked when the +* specified interrupt vector is asserted. +* +*/ + +void _IntVecSet( + unsigned int vector, /* interrupt vector: 0 to 255 on IA-32 */ + void (*routine)(void *), + unsigned int dpl /* priv level for interrupt-gate descriptor */ + ) +{ + unsigned long long *pIdtEntry; + + /* + * The parameter must be less than the value of the + * CONFIG_IDT_NUM_VECTORS configuration parameter, however, + * explicit + * validation will not be performed in this primitive. + */ + + pIdtEntry = (unsigned long long *)(_IdtBaseAddress + (vector << 3)); + + + _IdtEntCreate(pIdtEntry, routine, dpl); + +/* not required to synchronize the instruction and data caches */ + +} + +/******************************************************************************* +* +* irq_connect - connect a C routine to a hardware interrupt +* +* This routine connects an interrupt service routine (ISR) coded in C to +* the specified hardware . An interrupt vector will be allocated to +* satisfy the specified . If the interrupt service routine is being +* connected to a software generated interrupt, then must be set to +* NANO_SOFT_IRQ. +* +* The specified represents a virtualized IRQ, i.e. it does not +* necessarily represent a specific IRQ line on a given interrupt controller +* device. The BSP presents a virtualized set of IRQs from 0 to N, where N +* is the total number of IRQs supported by all the interrupt controller devices +* on the board. See the BSP's documentation for the mapping of virtualized +* IRQ to physical IRQ. +* +* When the device asserts an interrupt on the specified , a switch to +* the interrupt stack is performed (if not already executing on the interrupt +* stack), followed by saving the integer (i.e. non-floating point) context of +* the currently executing task, fiber, or ISR. The ISR specified by +* will then be invoked with the single . When the ISR returns, a +* context switch may occur. +* +* The argument points to memory that the system can use to +* synthesize the interrupt stub that calls . The memory need not be +* initialized, but must be persistent (i.e. it cannot be on the caller's stack). +* Declaring a global or static variable of type NANO_INT_STUB will provide a +* suitable area of the proper size. +* +* RETURNS: the allocated interrupt vector +* +* WARNINGS +* Some boards utilize interrupt controllers where the interrupt vector +* cannot be programmed on an IRQ basis; as a result, the vector assigned +* to the during interrupt controller initialization will be returned. +* In these cases, the requested is not honoured since the interrupt +* prioritization is fixed by the interrupt controller (e.g. IRQ0 will always +* be the highest priority interrupt regardless of what interrupt vector +* was assigned to IRQ0). +* +* This routine does not perform range checking on the requested +* and thus, depending on the underlying interrupt controller, may result +* in the assignment of an interrupt vector located in the reserved range of +* the processor. +* +* INTERNAL +* For debug kernels, this routine shall return -1 when there are no +* vectors remaining in the specified level. +*/ + +int irq_connect( + unsigned int irq, /* virtualized IRQ to connect to */ + unsigned int priority, /* requested priority of interrupt */ + void (*routine)(void *parameter), /* C interrupt handler */ + void *parameter, /* parameter passed to C routine */ + NANO_INT_STUB pIntStubMem /* memory for synthesized stub code */ + ) +{ + unsigned char offsetAdjust; + unsigned char numParameters = 1; /* stub always pushes ISR parameter */ + + extern void _IntEnt(void); + extern void _IntExit(void); + + int vector; + NANO_EOI_GET_FUNC boiRtn; + NANO_EOI_GET_FUNC eoiRtn; + void *boiRtnParm; + void *eoiRtnParm; + unsigned char boiParamRequired; + unsigned char eoiParamRequired; + +#define STUB_PTR pIntStubMem + + /* + * Invoke the BSP provided routine _SysIntVecAlloc() which will: + * a) allocate a vector satisfying the requested priority, + * b) return EOI and BOI related information for stub code synthesis, + *and + * c) program the underlying interrupt controller device such that + * when is asserted, the allocated interrupt vector will be + * presented to the CPU. + * + * The _SysIntVecAlloc() routine will use the "utility" routine + * _IntVecAlloc() provided in this module to scan the + *_VectorsAllocated[] + * array for a suitable vector. + */ + + vector = _SysIntVecAlloc(irq, + priority, + &boiRtn, + &eoiRtn, + &boiRtnParm, + &eoiRtnParm, + &boiParamRequired, + &eoiParamRequired); + +#if defined(DEBUG) + /* + * The return value from _SysIntVecAlloc() will be -1 if an invalid + * or was specified, or if a vector could not be + * allocated to honour the requested priority (for the boards that can + * support programming the interrupt vector for each IRQ). + */ + + if (vector == -1) + return (-1); +#endif /* DEBUG */ + + /* + * A minimal interrupt stub code will be synthesized based on the + * values of , , , , + * , and . The invocation of + * _IntEnt() and _IntExit() will always be required. + */ + + STUB_PTR[0] = IA32_CALL_OPCODE; + UNALIGNED_WRITE((unsigned int *)&STUB_PTR[1], + (unsigned int)&_IntEnt - (unsigned int)&pIntStubMem[5]); + + offsetAdjust = 5; + +#ifdef CONFIG_BOI_HANDLER_SUPPORTED + + /* poke in the BOI related opcodes */ + + if (boiRtn == NULL) + /* no need to insert anything */; + else if (boiParamRequired != 0) { + STUB_PTR[offsetAdjust] = IA32_PUSH_OPCODE; + UNALIGNED_WRITE((unsigned int *)&STUB_PTR[1 + offsetAdjust], + (unsigned int)boiRtnParm); + + STUB_PTR[5 + offsetAdjust] = IA32_CALL_OPCODE; + UNALIGNED_WRITE( + (unsigned int *)&STUB_PTR[6 + offsetAdjust], + (unsigned int)boiRtn - + (unsigned int)&pIntStubMem[10 + offsetAdjust]); + + offsetAdjust += 10; + ++numParameters; + } else { + STUB_PTR[offsetAdjust] = IA32_CALL_OPCODE; + UNALIGNED_WRITE( + (unsigned int *)&STUB_PTR[1 + offsetAdjust], + (unsigned int)boiRtn - + (unsigned int)&pIntStubMem[5 + offsetAdjust]); + + offsetAdjust += 5; + } + +#endif /* CONFIG_BOI_HANDLER_SUPPORTED */ + + /* IsrParameter and IsrRoutine always required */ + + STUB_PTR[offsetAdjust] = IA32_PUSH_OPCODE; + UNALIGNED_WRITE((unsigned int *)&STUB_PTR[1 + offsetAdjust], + (unsigned int)parameter); + + STUB_PTR[5 + offsetAdjust] = IA32_CALL_OPCODE; + UNALIGNED_WRITE((unsigned int *)&STUB_PTR[6 + offsetAdjust], + (unsigned int)routine - + (unsigned int)&pIntStubMem[10 + offsetAdjust]); + + offsetAdjust += 10; + +#ifdef CONFIG_EOI_HANDLER_SUPPORTED + + /* poke in the EOI related opcodes */ + + if (eoiRtn == NULL) + /* no need to insert anything */; + else if (eoiParamRequired != 0) { + STUB_PTR[offsetAdjust] = IA32_PUSH_OPCODE; + UNALIGNED_WRITE((unsigned int *)&STUB_PTR[1 + offsetAdjust], + (unsigned int)eoiRtnParm); + + STUB_PTR[5 + offsetAdjust] = IA32_CALL_OPCODE; + UNALIGNED_WRITE( + (unsigned int *)&STUB_PTR[6 + offsetAdjust], + (unsigned int)eoiRtn - + (unsigned int)&pIntStubMem[10 + offsetAdjust]); + + offsetAdjust += 10; + ++numParameters; + } else { + STUB_PTR[offsetAdjust] = IA32_CALL_OPCODE; + UNALIGNED_WRITE( + (unsigned int *)&STUB_PTR[1 + offsetAdjust], + (unsigned int)eoiRtn - + (unsigned int)&pIntStubMem[5 + offsetAdjust]); + + offsetAdjust += 5; + } + +#endif /* CONFIG_EOI_HANDLER_SUPPORTED */ + + /* + * Poke in the stack popping related opcode. Do it a byte at a time + * because + * &STUB_PTR[offsetAdjust] may not be aligned which does not work for + * all + * targets. + */ + + STUB_PTR[offsetAdjust] = IA32_ADD_OPCODE & 0xFF; + STUB_PTR[1 + offsetAdjust] = IA32_ADD_OPCODE >> 8; + STUB_PTR[2 + offsetAdjust] = (unsigned char)(4 * numParameters); + + offsetAdjust += 3; + + /* + * generate code that invokes _IntExit(); note that a jump is used, + * since _IntExit() takes care of returning back to the context that + * experienced the interrupt (i.e. branch tail optimization) + */ + + STUB_PTR[offsetAdjust] = IA32_JMP_OPCODE; + UNALIGNED_WRITE((unsigned int *)&STUB_PTR[1 + offsetAdjust], + (unsigned int)&_IntExit - + (unsigned int)&pIntStubMem[5 + offsetAdjust]); + + + /* + * There is no need to explicitly synchronize or flush the instruction + * cache due to the above code synthesis. See the Intel 64 and IA-32 + * Architectures Software Developer's Manual: Volume 3A: System + *Programming + * Guide; specifically the section titled "Self Modifying Code". + * + * Cache synchronization/flushing is not required for the i386 as it + * does not contain any on-chip I-cache; likewise, post-i486 processors + * invalidate the I-cache automatically. An i486 requires the CPU + * to perform a 'jmp' instruction before executing the synthesized code; + * however, the call and return that follows meets this requirement. + */ + + _IntVecSet(vector, (void (*)(void *))pIntStubMem, 0); + + return vector; +} + +/******************************************************************************* +* +* _IntVecAlloc - allocate a free interrupt vector given +* +* This routine scans the _VectorsAllocated[] array for a free vector that +* satisfies the specified . It is a utility function for use only +* by a BSP's _SysIntVecAlloc() routine. +* +* This routine assumes that the relationship between interrupt priority and +* interrupt vector is : +* +* priority = vector / 16; +* +* Since vectors 0 to 31 are reserved by the IA-32 architecture, the priorities +* of user defined interrupts range from 2 to 15. Each interrupt priority level +* contains 16 vectors, and the prioritization of interrupts within a priority +* level is determined by the vector number; the higher the vector number, the +* higher the priority within that priority level. +* +* It is also assumed that the interrupt controllers are capable of managing +* interrupt requests on a per-vector level as opposed to a per-priority level. +* For example, the local APIC on Pentium4 and later processors, the in-service +* register (ISR) and the interrupt request register (IRR) are 256 bits wide. +* +* RETURNS: allocated interrupt vector +* +* INTERNAL +* For debug kernels, this routine shall return -1 when there are no +* vectors remaining in the specified level. +*/ + +int _IntVecAlloc(unsigned int priority) +{ + unsigned int imask; + unsigned int entryToScan; + unsigned int fsb; /* first set bit in entry */ + int vector; + +#if defined(DEBUG) + /* + * check whether the IDT was configured with sufficient vectors to + * satisfy the priority request. + */ + + if (((priority << 4) + 15) > CONFIG_IDT_NUM_VECTORS) + return (-1); +#endif /* DEBUG */ + + /* + * Atomically allocate a vector from the _VectorsAllocated[] array + * to prevent race conditions with other tasks/fibers attempting to + * allocate an interrupt vector. + */ + + entryToScan = priority >> 1; /* _VectorsAllocated[] entry to scan */ + + /* + * The _VectorsAllocated[] entry specified by 'entryToScan' is a 32-bit + * quantity and thus represents the vectors for a pair of priority + *levels. + * Use find_last_set() to scan for the upper of the 2, and find_first_set() to + *scan + * for the lower of the 2 priorities. + * + * Note that find_first_set/find_last_set returns bit position from 1 to 32, + * or 0 if the argument is zero. + */ + + imask = irq_lock(); + + if ((priority % 2) == 0) { + /* scan from the LSB for even priorities */ + + fsb = find_first_set(_VectorsAllocated[entryToScan]); + +#if defined(DEBUG) + if ((fsb == 0) || (fsb > 16)) { + /* + * No bits are set in the lower 16 bits, thus all + * vectors for this + * priority have been allocated. + */ + + irq_unlock(imask); + return (-1); + } +#endif /* DEBUG */ + } else { + /* scan from the MSB for odd priorities */ + + fsb = find_last_set(_VectorsAllocated[entryToScan]); + +#if defined(DEBUG) + if ((fsb == 0) || (fsb < 17)) { + /* + * No bits are set in the lower 16 bits, thus all + * vectors for this + * priority have been allocated. + */ + + irq_unlock(imask); + return (-1); + } +#endif /* DEBUG */ + } + + /* ffsLsb/ffsMsb returns bit positions as 1 to 32 */ + + --fsb; + + /* mark the vector as allocated */ + + _VectorsAllocated[entryToScan] &= ~(1 << fsb); + + irq_unlock(imask); + + /* compute vector given allocated bit within the priority level */ + + vector = (entryToScan << 5) + fsb; + + return vector; +} + +/******************************************************************************* +* +* _IntVecMarkAllocated - mark interrupt vector as allocated +* +* This routine is used to "reserve" an interrupt vector that is allocated +* or assigned by any means other than _IntVecAllocate(). This marks the vector +* as allocated so that any future invocations of _IntVecAllocate() will not +* return that vector. +* +* RETURNS: N/A +* +*/ + +void _IntVecMarkAllocated(unsigned int vector) +{ + unsigned int entryToSet = vector / 32; + unsigned int bitToSet = vector % 32; + unsigned int imask; + + imask = irq_lock(); + _VectorsAllocated[entryToSet] &= ~(1 << bitToSet); + irq_unlock(imask); +} + +/******************************************************************************* +* +* _IntVecMarkFree - mark interrupt vector as free +* +* This routine is used to "free" an interrupt vector that is allocated +* or assigned using _IntVecAllocate() or _IntVecMarkAllocated(). This marks the +* vector as available so that any future allocations can return that vector. +* +*/ + +void _IntVecMarkFree(unsigned int vector) +{ + unsigned int entryToSet = vector / 32; + unsigned int bitToSet = vector % 32; + unsigned int imask; + + imask = irq_lock(); + _VectorsAllocated[entryToSet] |= (1 << bitToSet); + irq_unlock(imask); +} + +#endif /* CONFIG_NO_ISRS */ diff --git a/arch/x86/core/inthndlset.c b/arch/x86/core/inthndlset.c new file mode 100644 index 00000000000..35b84a815c9 --- /dev/null +++ b/arch/x86/core/inthndlset.c @@ -0,0 +1,146 @@ +/* inthndlset.c - VxMicro interrupt management support for IA-32 arch */ + +/* + * Copyright (c) 2011-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +* DESCRIPTION +* This module contains the irq_handler_set() API. This routine is closely +* associated with irq_connect(), and any changes to the layout of the +* constructed interrupt stub must be reflected in both places. +* +* INTERNAL +* This routine is defined here, rather than in intconnect.c, so that it can be +* omitted from a system image if it isn't required. +*/ + + +#include + + +/* the _IdtBaseAddress symbol is generated via a linker script */ + +extern unsigned char _IdtBaseAddress[]; + +/* + * The FIRST_OPT_OPCODE_OFF macro defines the offset of the first optional + * opcode in an interrupt stub. Given that only the "call _IntEnt" is + * mandatory, the subsequent instruction at offset 5 is "optional". + */ + +#define FIRST_OPT_OPCODE_OFF 5 + +/******************************************************************************* +* +* irq_handler_set - set the handler in an already connected stub +* +* This routine is used to modify an already fully constructed interrupt stub +* to specify a new and/or . +* +* WARNINGS: +* +* A fully constructed interrupt stub is generated via irq_connect(), i.e. +* the irq_handler_set() function must only be called after invoking +* irq_connect(). +* +* The caller must ensure that the associated interrupt does not occur while +* this routine is executing, otherwise race conditions may arise that could +* cause the interrupt stub to invoke the handler using an incorrect routine +* and/or parameter. If possible, silence the source of the associated interrupt +* only, rather than locking out all interrupts. +* +* RETURNS: N/A +* +*/ + +void irq_handler_set + (unsigned int vector, + void (*oldRoutine)(void *parameter), + void (*newRoutine)(void *parameter), + void *parameter) +{ + unsigned int ix = + FIRST_OPT_OPCODE_OFF; /* call _IntEnt is not optional */ + unsigned int *pIdtEntry; + unsigned char *pIntStubMem; + + pIdtEntry = (unsigned int *)(_IdtBaseAddress + (vector << 3)); + pIntStubMem = (unsigned char *)(((uint16_t)pIdtEntry[0]) | + (pIdtEntry[1] & 0xffff0000)); + + /* + * Given the generation of the stub is dynamic, i.e. the invocations of + * an EOI routine (with parameter) and/or BOI routine (with parameter) + * are optional based on the requirements of the interrupt controller, + * the parameter is used to quickly find the correct + * bytes in the stub code to update. + */ + + while (ix < _INT_STUB_SIZE) { + /* locate the call opcode */ + + if (pIntStubMem[ix] == IA32_CALL_OPCODE) { + unsigned int opcodeOffToMatch; + unsigned int opcodeOff; + + /* read the offset encoded in the call opcode */ + + opcodeOff = UNALIGNED_READ( + (unsigned int *)&pIntStubMem[ix + 1]); + opcodeOffToMatch = (unsigned int)oldRoutine - + (unsigned int)&pIntStubMem[ix + 5]; + + /* does the encoded offset match ? */ + + if (opcodeOff == opcodeOffToMatch) { +/* match found -> write new routine and parameter */ + + + UNALIGNED_WRITE( + (unsigned int *)&pIntStubMem[ix + 1], + (unsigned int)newRoutine - + (unsigned int)&pIntStubMem[ix + + 5]); + + UNALIGNED_WRITE( + (unsigned int *)&pIntStubMem[ix - 4], + (unsigned int)parameter); + + + return; /* done */ + } + } + + /* all instructions in the stub are 5 bytes long */ + + ix += 5; + } +} + diff --git a/arch/x86/core/intstub.s b/arch/x86/core/intstub.s new file mode 100644 index 00000000000..60c110b31c8 --- /dev/null +++ b/arch/x86/core/intstub.s @@ -0,0 +1,525 @@ +/* intstub.s - VxMicro interrupt management support for IA-32 architecture */ + +/* + * Copyright (c) 2010-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This module implements assembly routines to manage interrupts in VxMicro on +the Intel IA-32 architecture. More specifically, the interrupt (asynchronous +exception) stubs are implemented in this module. The stubs are invoked when +entering and exiting a C interrupt handler. +*/ + +#define _ASMLANGUAGE + +#ifndef CONFIG_NO_ISRS + +#include +#include +#include /* nanokernel structure offset definitions */ +#include /* _NANO_ERR_SPURIOUS_INT */ + + + + /* exports (internal APIs) */ + + GTEXT(_IntEnt) + GTEXT(_IntExit) + GTEXT(_SpuriousIntNoErrCodeHandler) + GTEXT(_SpuriousIntHandler) + + /* exports (public APIs) */ + + GTEXT(irq_lock) + GTEXT(irq_unlock) + + /* externs */ + + GTEXT(_Swap) + +#ifdef CONFIG_ADVANCED_POWER_MANAGEMENT + GTEXT(_SysPowerSaveIdleExit) +#endif /* CONFIG_ADVANCED_POWER_MANAGEMENT */ + + +#ifdef CONFIG_INT_LATENCY_BENCHMARK + GTEXT(_IntLatencyStart) + GTEXT(_IntLatencyStop) +#endif +/******************************************************************************* +* +* _IntEnt - inform the VxMicro kernel of an interrupt +* +* This function is called from the interrupt stub created by irq_connect() +* to inform the VxMicro kernel of an interrupt. This routine increments +* _NanoKernel.nested (to support interrupt nesting), switches to the +* base of the interrupt stack, if not already on the interrupt stack, and then +* saves the volatile integer registers onto the stack. Finally, control is +* returned back to the interrupt stub code (which will then invoke the +* "application" interrupt service routine). +* +* Only the volatile integer registers are saved since ISRs are assumed not to +* utilize floating point (or SSE) instructions. If an ISR requires the usage +* of floating point (or SSE) instructions, it must first invoke nanoCpuFpSave() +* (or nanoCpuSseSave()) at the beginning of the ISR. A subsequent +* nanoCpuFpRestore() (or nanoCpuSseRestore()) is needed just prior to returning +* from the ISR. Note that the nanoCpuFpSave(), nanoCpuSseSave(), +* nanoCpuFpRestore(), and nanoCpuSseRestore() APIs have not been +* implemented yet. +* +* WARNINGS +* +* Host-based tools and the target-based GDB agent depend on the stack frame +* created by this routine to determine the locations of volatile registers. +* These tools must be updated to reflect any changes to the stack frame. +* +* RETURNS: N/A +* +* C function prototype: +* +* void _IntEnt (void); +* +* NOMANUAL +*/ + +SECTION_FUNC(TEXT, _IntEnt) + + /* + * The _IntVecSet() routine creates an interrupt-gate descriptor for + * all connections. The processor will automatically clear the IF + * bit in the EFLAGS register upon execution of the handler, thus + * _IntEnt() (and _ExcEnt) need not issue an 'cli' as the first + * instruction. + * + * Clear the direction flag. It is automatically restored when the + * interrupt exits via the IRET instruction. + */ + + cld + + + + /* + * Note that the processor has pushed both the EFLAGS register + * and the logical return address (cs:eip) onto the stack prior + * to invoking the handler specified in the IDT + */ + + + /* + * swap eax and return address on the current stack; + * this saves eax on the stack without losing knowledge + * of how to get back to the interrupt stub + */ + +#ifdef CONFIG_LOCK_INSTRUCTION_UNSUPPORTED + + pushl (%esp) + movl %eax, 4(%esp) + popl %eax + +#else + + xchgl %eax, (%esp) + +#endif /* CONFIG_LOCK_INSTRUCTION_UNSUPPORTED*/ + + /* + * The remaining volatile registers are pushed onto the current + * stack. + */ + + pushl %ecx + pushl %edx + +#ifdef CONFIG_INT_LATENCY_BENCHMARK + /* + * Volatile registers are now saved it is safe to start measuring + * how long interrupt are disabled. + * The interrupt gate created by irq_connect disables the + * interrupt. + * + * Preserve EAX as it contains the stub return address. + */ + + pushl %eax + call _IntLatencyStart + popl %eax +#endif + + + /* load %ecx with &_NanoKernel */ + + movl $_NanoKernel, %ecx + + /* switch to the interrupt stack for the non-nested case */ + + incl __tNANO_nested_OFFSET(%ecx) /* inc interrupt nest count */ + cmpl $1, __tNANO_nested_OFFSET(%ecx) /* use int stack if !nested */ + jne alreadyOnIntStack + + /* switch to base of the interrupt stack */ + + movl %esp, %edx /* save current context stack pointer */ + movl __tNANO_common_isp_OFFSET(%ecx), %esp /* load new sp value */ + + + /* save context stack pointer onto base of interrupt stack */ + + pushl %edx /* Save stack pointer */ + +#ifdef CONFIG_ADVANCED_POWER_MANAGEMENT + cmpl $0, __tNANO_idle_OFFSET(%ecx) + jne _HandleIdle + /* fast path is !idle, in the pipeline */ +#endif /* CONFIG_ADVANCED_POWER_MANAGEMENT */ + + + /* fall through to nested case */ + +BRANCH_LABEL(alreadyOnIntStack) +#ifdef CONFIG_INT_LATENCY_BENCHMARK + /* preserve eax which contain stub return address */ + pushl %eax + call _IntLatencyStop + popl %eax +#endif + + sti /* re-enable interrupts */ + jmp *%eax /* "return" back to stub */ + +#ifdef CONFIG_ADVANCED_POWER_MANAGEMENT +BRANCH_LABEL(_HandleIdle) + pushl %eax + push __tNANO_idle_OFFSET(%ecx) + movl $0, __tNANO_idle_OFFSET(%ecx) + + /* + * Beware that a timer driver's _SysPowerSaveIdleExit() implementation might + * expect that interrupts are disabled when invoked. This ensures that + * the calculation and programming of the device for the next timer + * deadline is not interrupted. + */ + + call _SysPowerSaveIdleExit + add $0x4, %esp +#ifdef CONFIG_INT_LATENCY_BENCHMARK + call _IntLatencyStop +#endif + sti /* re-enable interrupts */ + popl %eax + jmp *%eax /* "return" back to stub */ +#endif /* CONFIG_ADVANCED_POWER_MANAGEMENT */ + + +/******************************************************************************* +* +* _IntExit - inform the VxMicro kernel of an interrupt exit +* +* This function is called from the interrupt stub created by irq_connect() +* to inform the VxMicro kernel that the processing of an interrupt has +* completed. This routine decrements _NanoKernel.nested (to support interrupt +* nesting), restores the volatile integer registers, and then switches +* back to the interrupted context's stack, if this isn't a nested interrupt. +* +* Finally, control is returned back to the interrupted fiber context or ISR. +* A context switch _may_ occur if the interrupted context was a task context, +* in which case one or more other fiber and task contexts will execute before +* this routine resumes and control gets returned to the interrupted task. +* +* RETURNS: N/A +* +* C function prototype: +* +* void _IntExit (void); +* +* NOMANUAL +*/ + +SECTION_FUNC(TEXT, _IntExit) + + cli /* disable interrupts */ +#ifdef CONFIG_INT_LATENCY_BENCHMARK + call _IntLatencyStart +#endif + + /* determine whether exiting from a nested interrupt */ + + movl $_NanoKernel, %ecx + decl __tNANO_nested_OFFSET(%ecx) /* dec interrupt nest count */ + jne nestedInterrupt /* 'iret' if nested case */ + + + /* + * Determine whether the execution of the ISR requires a context + * switch. If the interrupted context is PREEMPTIBLE and + * _NanoKernel.fiber is non-NULL, a _Swap() needs to occur. + */ + + movl __tNANO_current_OFFSET (%ecx), %eax + testl $PREEMPTIBLE, __tCCS_flags_OFFSET(%eax) + je noReschedule + cmpl $0, __tNANO_fiber_OFFSET (%ecx) + je noReschedule + + /* + * Set the INT_ACTIVE bit in the tCCS to allow the upcoming call to + * _Swap() to determine whether non-floating registers need to be + * preserved using the lazy save/restore algorithm, or to indicate to + * debug tools that a preemptive context switch has occurred. + * + * Setting the NO_METRICS bit tells _Swap() that the per-context + * [totalRunTime] calculation has already been performed and that + * there is no need to do it again. + */ + +#if defined(CONFIG_FP_SHARING) || defined(CONFIG_GDB_INFO) + orl $INT_ACTIVE, __tCCS_flags_OFFSET(%eax) +#endif + + /* + * A context reschedule is required: keep the volatile registers of + * the interrupted context on the context's stack. Utilize + * the existing _Swap() primitive to save the remaining + * thread's registers (including floating point) and perform + * a switch to the new context. + */ + + popl %esp /* switch back to kernel stack */ + + pushfl /* push KERNEL_LOCK_KEY argument */ + call _Swap + + /* + * The interrupted context thread has now been scheduled, + * as the result of a _later_ invocation of _Swap(). + * + * Now need to restore the interrupted context's environment before + * returning control to it at the point where it was interrupted ... + */ + + +#if ( defined(CONFIG_FP_SHARING) || \ + defined(CONFIG_GDB_INFO) ) + /* + * _Swap() has restored the floating point registers, if needed. + * Clear the INT_ACTIVE bit of the interrupted context's tCCS + * since it has served its purpose. + */ + + movl _NanoKernel + __tNANO_current_OFFSET, %eax + andl $~INT_ACTIVE, __tCCS_flags_OFFSET (%eax) +#endif /* CONFIG_FP_SHARING || CONFIG_GDB_INFO */ + + + addl $4, %esp /* pop KERNEL_LOCK_KEY argument */ + + + + + /* Restore volatile registers and return to the interrupted context */ +#ifdef CONFIG_INT_LATENCY_BENCHMARK + call _IntLatencyStop +#endif + + popl %edx + popl %ecx + popl %eax + + /* Pop of EFLAGS will re-enable interrupts and restore direction flag */ + iret + + +BRANCH_LABEL(noReschedule) + + /* + * A thread reschedule is not required; switch back to the + * interrupted thread's stack and restore volatile registers + */ + + popl %esp /* pop thread stack pointer */ + + + /* fall through to 'nestedInterrupt' */ + + + /* + * For the nested interrupt case, the interrupt stack must still be + * utilized, and more importantly, a rescheduling decision must + * not be performed. + */ + +BRANCH_LABEL(nestedInterrupt) +#ifdef CONFIG_INT_LATENCY_BENCHMARK + call _IntLatencyStop +#endif + popl %edx /* pop volatile registers in reverse order */ + popl %ecx + popl %eax + /* Pop of EFLAGS will re-enable interrupts and restore direction flag */ + iret + + +/******************************************************************************* +* +* _SpuriousIntHandler - +* _SpuriousIntNoErrCodeHandler - spurious interrupt handler stubs +* +* Interrupt-gate descriptors are statically created for all slots in the IDT +* that point to _SpuriousIntHandler() or _SpuriousIntNoErrCodeHandler(). The +* former stub is connected to exception vectors where the processor pushes an +* error code onto the stack (or kernel stack) in addition to the EFLAGS/CS/EIP +* records. +* +* A spurious interrupt is considered a fatal condition, thus this routine +* merely sets up the 'reason' and 'pEsf' parameters to the BSP provided +* routine: _SysFatalHwErrorHandler(). In other words, there is no provision +* to return to the interrupted context and thus the volatile registers +* are not saved. +* +* RETURNS: Never returns +* +* C function prototype: +* +* void _SpuriousIntHandler (void); +* +* INTERNAL +* The _IntVecSet() routine creates an interrupt-gate descriptor for all +* connections. The processor will automatically clear the IF bit +* in the EFLAGS register upon execution of the handler, +* thus _SpuriousIntNoErrCodeHandler()/_SpuriousIntHandler() shall be +* invoked with interrupts disabled. +* +* NOMANUAL +*/ + +SECTION_FUNC(TEXT, _SpuriousIntNoErrCodeHandler) + + pushl $0 /* push dummy err code onto stk */ + + /* fall through to _SpuriousIntHandler */ + + +SECTION_FUNC(TEXT, _SpuriousIntHandler) + + cld /* Clear direction flag */ + + + /* + * The task's regular stack is being used, but push the value of ESP + * anyway so that _ExcExit can "recover the stack pointer" + * without determining whether the exception occured while CPL=3 + */ + + pushl %esp /* push cur stack pointer: pEsf arg */ + +BRANCH_LABEL(finishSpuriousInt) + + /* re-enable interrupts */ + + sti + + /* push the 'unsigned int reason' parameter */ + + pushl $_NANO_ERR_SPURIOUS_INT + +BRANCH_LABEL(callFatalHandler) + + /* call the fatal error handler */ + + call _NanoFatalErrorHandler + + /* handler shouldn't return, but call it again if it does */ + + jmp callFatalHandler + + +/******************************************************************************* +* +* irq_lock - disable interrupts on the local CPU +* +* This routine disables interrupts. It can be called from either interrupt +* or context level. This routine returns an architecture-dependent +* lock-out key representing the "interrupt disable state" prior to the call; +* this key can be passed to fiber_enable_ints() to re-enable interrupts. +* +* The lock-out key should only be used as the argument to the +* fiber_enable_ints() API. It should never be used to manually re-enable +* interrupts or to inspect or manipulate the contents of the source register. +* +* WARNINGS +* Invoking a VxMicro system routine with interrupts locked may result in +* interrupts being re-enabled for an unspecified period of time. If the +* called routine blocks, interrupts will be re-enabled while another +* context executes, or while the system is idle. +* +* The "interrupt disable state" is an attribute of a context, i.e. it's part +* of the context context. Thus, if a context disables interrupts and +* subsequently invokes a VxMicro system routine that causes the calling context +* to block, the interrupt disable state will be restored when the context is +* later rescheduled for execution. +* +* RETURNS: An architecture-dependent lock-out key representing the +* "interrupt disable state" prior to the call. +*/ + +SECTION_FUNC(TEXT, irq_lock) + pushfl + cli +#ifdef CONFIG_INT_LATENCY_BENCHMARK + call _IntLatencyStart +#endif + popl %eax + ret + + +/******************************************************************************* +* +* irq_unlock - enable interrupts on the local CPU +* +* This routine re-enables interrupts on the local CPU. The parameter +* is an architecture-dependent lock-out key that is returned by a previous +* invocation of irq_lock(). +* +* This routine can be called from either a context or ISR context. +*/ + +SECTION_FUNC(TEXT, irq_unlock) + testl $0x200, SP_ARG1(%esp) + jz skipIntEnable +#ifdef CONFIG_INT_LATENCY_BENCHMARK + call _IntLatencyStop +#endif + sti +BRANCH_LABEL(skipIntEnable) + ret + +#endif /* CONFIG_NO_ISRS */ diff --git a/arch/x86/core/msr.s b/arch/x86/core/msr.s new file mode 100644 index 00000000000..75f587a260f --- /dev/null +++ b/arch/x86/core/msr.s @@ -0,0 +1,105 @@ +/* msr.s - Utilities to read/write the Model Specific Registers (MSRs) */ + +/* + * Copyright (c) 2011-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This module provides the implementation of the _MsrWrite() and _MsrRead() +utilities. +*/ + +#define _ASMLANGUAGE + +#include + + /* exports (internal APIs) */ + + GTEXT(_MsrWrite) + GTEXT(_MsrRead) + +/******************************************************************************* +* +* _MsrWrite - write to a model specific register (MSR) +* +* This function is used to write to an MSR. +* +* C function prototype: +* +* void _MsrWrite (unsigned int msr, uint64_t msrData); +* +* The definitions of the so-called "Architectural MSRs" are contained +* in nanok.h and have the format: IA32_XXX_MSR +* +* INTERNAL +* 1) The 'wrmsr' instruction was introduced in the Pentium processor; executing +* this instruction on an earlier IA-32 processor will result in an invalid +* opcode exception. +* 2) The 'wrmsr' uses the ECX, EDX, and EAX registers which matches the set of +* volatile registers! +* +* RETURNS: N/A +*/ + +SECTION_FUNC(TEXT, _MsrWrite) + movl SP_ARG1(%esp), %ecx /* load ECX with */ + movl 0x8(%esp), %eax /* load LS 32-bits of */ + movl 0xc(%esp), %edx /* load MS 32-bits of */ + wrmsr /* write %edx:%eax to the MSR */ + ret + + +/******************************************************************************* +* +* _MsrRead - read from a model specific register (MSR) +* +* This function is used to read from an MSR. +* +* C function prototype: +* +* uint64_t _MsrRead (unsigned int msr); +* +* The definitions of the so-called "Architectural MSRs" are contained +* in nanok.h and have the format: IA32_XXX_MSR +* +* INTERNAL +* 1) The 'rdmsr' instruction was introduced in the Pentium processor; executing +* this instruction on an earlier IA-32 processor will result in an invalid +* opcode exception. +* 2) The 'rdmsr' uses the ECX, EDX, and EAX registers which matches the set of +* volatile registers! +* +* RETURNS: N/A +*/ + +SECTION_FUNC(TEXT, _MsrRead) + movl SP_ARG1(%esp), %ecx /* load ECX with */ + rdmsr /* read MSR into %edx:%eax */ + ret diff --git a/arch/x86/core/nanoatomic.s b/arch/x86/core/nanoatomic.s new file mode 100644 index 00000000000..ceb21039641 --- /dev/null +++ b/arch/x86/core/nanoatomic.s @@ -0,0 +1,499 @@ +/* nanoatomic.s - VxMicro nanokernel atomic operators for IA-32 */ + +/* + * Copyright (c) 2011-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This module provides the atomic operators for IA-32 architectures on BSPs +that support the LOCK prefix instruction. + +The atomic operations are guaranteed to be atomic with respect to interrupt +service routines, and to operations performed by peer processors. + +INTERNAL +These operators are currently unavailable to user space applications, +as there is no requirement for this capability. +*/ + +/* includes */ + +#if !defined(CONFIG_LOCK_INSTRUCTION_UNSUPPORTED) + +#define _ASMLANGUAGE + +#include + + /* exports (public APIs) */ + + GTEXT(atomic_cas) + GTEXT(atomic_add) + GTEXT(atomic_sub) + GTEXT(atomic_inc) + GTEXT(atomic_dec) + GTEXT(atomic_get) + GTEXT(atomic_set) + GTEXT(atomic_clear) + GTEXT(atomic_or) + GTEXT(atomic_xor) + GTEXT(atomic_and) + GTEXT(atomic_nand) + +/******************************************************************************* +* +* atomic_cas - atomic compare-and-set primitive +* +* This routine provides the compare-and-set operator. If the original value at +* equals , then is stored at and the +* function returns 1. +* +* If the original value at does not equal , then the store +* is not done and the function returns 0. +* +* The reading of the original value at , the comparison, +* and the write of the new value (if it occurs) all happen atomically with +* respect to both interrupts and accesses of other processors to . +* +* RETURNS: Returns 1 if is written, 0 otherwise. +* +* int atomic_cas +* ( +* atomic_t * target, /@ address to be tested @/ +* atomic_val_t oldValue, /@ value to compare against @/ +* atomic_val_t newValue /@ value to compare against @/ +* ) +* +* INTERNAL +* The 'cmpxchg' instruction is NOT supported on processor prior to the 80486 +*/ + +SECTION_FUNC(TEXT, atomic_cas) + + movl SP_ARG1(%esp),%edx /* get address */ + movl SP_ARG2(%esp),%eax /* get oldValue to cmp */ + movl SP_ARG3(%esp),%ecx /* get newValue to set */ + lock /* lock the bus during the next inst */ + cmpxchg %ecx,(%edx) /* if (%eax == (%edx) */ + /* {ZF = 1; (%edx) = %ecx;} */ + /* else */ + /* {ZF = 0; %eax = (%edx);} */ + jne atomic_cas1 + movl $1,%eax /* set return status to 1 */ + ret + +BRANCH_LABEL(atomic_cas1) + xorl %eax,%eax /* set return status to 0 */ + ret + + +/******************************************************************************* +* +* atomic_add - atomic add primitive +* +* This routine provides the atomic addition operator. The is +* atomically added to the value at , placing the result at , +* and the old value from is returned. +* +* RETURNS: The previous value from +* +* atomic_val_t atomic_add +* ( +* atomic_t * target, /@ memory location to add to @/ +* atomic_val_t value /@ value to add @/ +* ) +* +* INTERNAL +* The 'xadd' instruction is NOT supported on processor prior to the 80486 +*/ + +SECTION_FUNC(TEXT, atomic_add) + + movl SP_ARG1(%esp),%edx /* get address */ + movl SP_ARG2(%esp),%eax /* get value to add */ + + lock /* lock the bus during the next inst */ + xadd %eax,(%edx) /* TMP = %eax + (%edx) */ + /* %eax = (%edx) */ + /* (%edx) = TMP */ + ret + + +/******************************************************************************* +* +* atomic_sub - atomic subtraction primitive +* +* This routine provides the atomic subtraction operator. The is +* atomically subtracted from the value at , placing the result at +* , and the old value from is returned. +* +* RETURNS: The previous value from +* +* atomic_val_t atomic_sub +* ( +* atomic_t * target, /@ memory location to subtract from @/ +* atomic_val_t value /@ value to subtract @/ +* ) +* +* INTERNAL +* The 'xadd' instruction is NOT supported on processor prior to the 80486 +*/ + +SECTION_FUNC(TEXT, atomic_sub) + + movl SP_ARG1(%esp),%edx /* get address */ + movl SP_ARG2(%esp),%eax /* get value to add */ + negl %eax /* Negate %eax... */ + + lock /* lock the bus during the next inst */ + xadd %eax,(%edx) /* TMP = %eax + (%edx) */ + /* %eax = (%edx) */ + /* (%edx) = TMP */ + ret + + +/******************************************************************************* +* +* atomic_inc - atomic increment primitive +* +* This routine provides the atomic increment operator. The value at +* is atomically incremented by 1, and the old value from is returned. +* +* RETURNS: The value from before the increment +* +* atomic_val_t atomic_inc +* ( +* atomic_t *target /@ memory location to increment @/ +* ) +* +* INTERNAL +* The 'xadd' instruction is NOT supported on processor prior to the 80486 +*/ + +SECTION_FUNC(TEXT, atomic_inc) + + movl SP_ARG1(%esp),%edx /* get address */ + + xorl %eax, %eax + incl %eax /* increment by 1 */ + + lock /* lock the bus during the next inst */ + xadd %eax,(%edx) /* TMP = %eax + (%edx) */ + /* %eax = (%edx) */ + /* (%edx) = TMP */ + ret + + +/******************************************************************************* +* +* atomic_dec - atomic decrement primitive +* +* This routine provides the atomic decrement operator. The value at +* is atomically decremented by 1, and the old value from is returned. +* +* RETURNS: The value from prior to the decrement +* +* atomic_val_t atomic_dec +* ( +* atomic_t *target /@ memory location to decrement @/ +* ) +* +* INTERNAL +* The 'xadd' instruction is NOT supported on processor prior to the 80486 +*/ + +SECTION_FUNC(TEXT, atomic_dec) + + movl SP_ARG1(%esp),%edx /* get address */ + orl $-1,%eax /* dec by 1 */ + + lock /* lock the bus during the next inst */ + xadd %eax,(%edx) /* TMP = %eax + (%edx) */ + /* %eax = (%edx) */ + /* (%edx) = TMP */ + ret + + +/******************************************************************************* +* +* atomic_get - atomic get primitive +* +* This routine provides the atomic get primitive to atomically read +* a value from . It simply does an ordinary load. Note that +* is expected to be aligned to a 4-byte boundary. +* +* RETURNS: The value read from +* +* atomic_t atomic_get +* ( +* atomic_t *target /@ memory location to read from @/ +* ) +* +*/ + +SECTION_FUNC(TEXT, atomic_get) + + movl SP_ARG1(%esp),%edx /* get address */ + movl (%edx), %eax /* get value */ + ret + + +/******************************************************************************* +* +* atomic_set - atomic get-and-set primitive +* +* This routine provides the atomic set operator. The is atomically +* written at and the previous value at is returned. +* +* RETURNS: The previous value from +* +* atomic_val_t atomic_set +* ( +* atomic_t *target, /@ memory location to write to @/ +* atomic_val_t value /@ value to set @/ +* ) +* +* INTERNAL +* The XCHG instruction is executed on the specified address to +* swap in value. The value swapped out is returned by this function. +*/ + +SECTION_FUNC(TEXT, atomic_set) + + movl SP_ARG1(%esp),%edx /* get address */ + movl SP_ARG2(%esp),%eax /* get value to set */ + + /* + * The 'lock' prefix is not required with the 'xchg' instruction. + * According to the IA-32 instruction reference manual: + * + * "If a memory operand is referenced, the processor's locking + * protocol is automatically implemented for the duration of + * the exchange operation, regardless of the presence + * or absence of the LOCK prefix or of the value of the IOPL." + */ + + xchg %eax,(%edx) /* set value with bus-lock */ + + ret + + +/******************************************************************************* +* +* atomic_clear - atomic clear primitive +* +* This routine provides the atomic clear operator. The value of 0 is atomically +* written at and the previous value at is returned. (Hence, +* atomic_clear(pAtomicVar) is equivalent to atomic_set(pAtomicVar, 0).) +* +* RETURNS: The previous value from +* +* atomic_val_t atomic_clear +* ( +* atomic_t *target /@ memory location to write to @/ +* ) +* +*/ + +SECTION_FUNC(TEXT, atomic_clear) + + movl SP_ARG1(%esp),%edx /* get address */ + xorl %eax,%eax /* clear value to set */ + + /* + * The 'lock' prefix is not required with the 'xchg' instruction. + * According to the IA-32 instruction reference manual: + * + * "If a memory operand is referenced, the processor's locking + * protocol is automatically implemented for the duration of + * the exchange operation, regardless of the presence + * or absence of the LOCK prefix or of the value of the IOPL." + */ + + xchg %eax,(%edx) /* swap 'clear' value with bus-lock */ + + ret + + +/******************************************************************************* +* +* atomic_or - atomic bitwise inclusive OR primitive +* +* This routine provides the atomic bitwise inclusive OR operator. The +* is atomically bitwise OR'ed with the value at , placing the result +* at , and the previous value at is returned. +* +* RETURNS: The previous value from +* +* atomic_val_t atomic_or +* ( +* atomic_t *target, /@ memory location to be modified @/ +* atomic_val_t value /@ value to OR @/ +* ) +* +* INTERNAL +* The 'cmpxchg' instruction is NOT supported on processor prior to the 80486 +*/ + +SECTION_FUNC(TEXT, atomic_or) + + movl SP_ARG1(%esp),%edx /* get address */ + movl (%edx),%eax /* get old value */ + +BRANCH_LABEL(atomic_or_retry) + + movl SP_ARG2(%esp),%ecx /* get value to OR */ + orl %eax, %ecx + lock /* lock the bus during the next inst */ + cmpxchg %ecx,(%edx) /* if (%eax == (%edx)) */ + /* {ZF = 1 ; (%edx) = %ecx;} */ + /* else */ + /* {ZF = 0 ; %eax = (%edx);} */ + jnz atomic_or_retry + ret + + +/******************************************************************************* +* +* atomic_xor - atomic bitwise exclusive OR (XOR) primitive +* +* This routine provides the atomic bitwise exclusive OR operator. The +* is atomically bitwise XOR'ed with the value at , placing the result +* at , and the previous value at is returned. +* +* RETURNS: The previous value from +* +* atomic_val_t atomic_xor +* ( +* atomic_t *target, /@ memory location to be modified @/ +* atomic_t value /@ value to XOR @/ +* ) +* +* INTERNAL +* The 'cmpxchg' instruction is NOT supported on processor prior to the 80486 +*/ + +SECTION_FUNC(TEXT, atomic_xor) + + movl SP_ARG1(%esp),%edx /* get address */ + movl (%edx),%eax /* get old value */ + +BRANCH_LABEL(atomic_xor_retry) + + movl SP_ARG2(%esp),%ecx /* get value to set */ + xorl %eax, %ecx + lock /* lock the bus during the next inst */ + cmpxchg %ecx,(%edx) /* if (%eax == (%edx)) */ + /* {ZF = 1 ; (%edx) = %ecx;} */ + /* else */ + /* {ZF = 0 ; %eax = (%edx);} */ + jnz atomic_xor_retry + ret + + +/******************************************************************************* +* +* atomic_and - atomic bitwise AND primitive +* +* This routine provides the atomic bitwise AND operator. The is +* atomically bitwise AND'ed with the value at , placing the result +* at , and the previous value at is returned. +* +* RETURNS: The previous value from +* +* atomic_val_t atomic_and +* ( +* atomic_t *target, /@ memory location to be modified @/ +* atomic_val_t value /@ value to AND @/ +* ) +* +* INTERNAL +* The 'cmpxchg' instruction is NOT supported on processor prior to the 80486 +*/ + +SECTION_FUNC(TEXT, atomic_and) + + movl SP_ARG1(%esp),%edx /* get address */ + movl (%edx),%eax /* get old value */ + +BRANCH_LABEL(atomic_and_retry) + + movl SP_ARG2(%esp),%ecx /* get value to set */ + andl %eax, %ecx + lock /* lock the bus during the next inst */ + cmpxchg %ecx,(%edx) /* if (%eax == (%edx)) */ + /* {ZF = 1 ; (%edx) = %ecx;} */ + /* else */ + /* {ZF = 0 ; %eax = (%edx);} */ + jnz atomic_and_retry + ret + + +/******************************************************************************* +* +* atomic_nand - atomic bitwise NAND primitive +* +* This routine provides the atomic bitwise NAND operator. The is +* atomically bitwise NAND'ed with the value at , placing the result +* at , and the previous value at is returned. +* +* RETURNS: The previous value from +* +* atomic_val_t atomic_nand +* ( +* atomic_t * target, /@ memory location to be modified @/ +* atomic_val_t value /@ value to NAND @/ +* ) +* +* INTERNAL +* The 'cmpxchg' instruction is NOT supported on processor prior to the 80486 +*/ + +SECTION_FUNC(TEXT, atomic_nand) + + movl SP_ARG1(%esp),%edx /* get address */ + movl (%edx),%eax /* get old value */ + +BRANCH_LABEL(atomic_nand_retry) + + movl SP_ARG2(%esp),%ecx /* get value to nand with old value */ + + andl %eax,%ecx + not %ecx + + lock /* lock the bus during the next inst */ + cmpxchg %ecx,(%edx) /* if (%eax == (%edx)) */ + /* {ZF = 1 ; (%edx) = %ecx;} */ + /* else */ + /* {ZF = 0 ; %eax = (%edx);} */ + jnz atomic_nand_retry + ret + +#endif /* !CONFIG_LOCK_INSTRUCTION_UNSUPPORTED */ + diff --git a/arch/x86/core/nanoatomic_nolock.c b/arch/x86/core/nanoatomic_nolock.c new file mode 100644 index 00000000000..fc73ed64fc1 --- /dev/null +++ b/arch/x86/core/nanoatomic_nolock.c @@ -0,0 +1,364 @@ +/* nanoatomic_nolock.c - nanokernel atomic operators for IA-32 */ + +/* + * Copyright (c) 2012-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This module provides the atomic operators for IA-32 architectures on BSPs +that do not support the LOCK prefix instruction. + +The atomic operations are guaranteed to be atomic with respect to interrupt +service routines. However, they are NOT guaranteed to be atomic with respect +to operations performed by peer processors, unlike the versions of these +operators that do utilize the LOCK prefix instruction. + +INTERNAL +These operators are currently unavailable to user space applications +as there is no requirement for this capability. +*/ + +/* includes */ + +#if defined(CONFIG_LOCK_INSTRUCTION_UNSUPPORTED) + +#include +#include + +/******************************************************************************* +* +* atomic_cas - atomic compare-and-set primitive +* +* This routine provides the compare-and-set operator. If the original value at +* equals , then is stored at and the +* function returns 1. +* +* If the original value at does not equal , then the store +* is not done and the function returns 0. +* +* The reading of the original value at , the comparison, +* and the write of the new value (if it occurs) all happen atomically with +* respect to both interrupts and accesses of other processors to . +* +* RETURNS: Returns 1 if is written, 0 otherwise. +*/ + +int atomic_cas( + atomic_t *target, /* address to be tested */ + atomic_val_t oldValue, /* value to compare against */ + atomic_val_t newValue /* value to set to */ + ) +{ + int key; /* interrupt lock level */ + atomic_val_t ovalue; /* temporary storage */ + + key = irq_lock_inline(); + ovalue = *target; + if (ovalue != oldValue) { + irq_unlock_inline(key); + return 0; + } + *target = newValue; + irq_unlock_inline(key); + return 1; +} + +/******************************************************************************* +* +* atomic_add - atomic addition primitive +* +* This routine provides the atomic addition operator. The is +* atomically added to the value at , placing the result at , +* and the old value from is returned. +* +* RETURNS: The previous value from +*/ + +atomic_val_t atomic_add( + atomic_t *target, /* memory location to add to */ + atomic_val_t value /* value to add */ + ) +{ + int key; /* interrupt lock level */ + atomic_val_t ovalue; /* previous value from */ + + key = irq_lock_inline(); + ovalue = *target; + *target = ovalue + value; + irq_unlock_inline(key); + return ovalue; +} + +/******************************************************************************* +* +* atomic_sub - atomic subtraction primitive +* +* This routine provides the atomic subtraction operator. The is +* atomically subtracted from the value at , placing the result at +* , and the old value from is returned. +* +* RETURNS: The previous value from +*/ + +atomic_val_t atomic_sub( + atomic_t *target, /* memory location to subtract from */ + atomic_val_t value /* value to subtract */ + ) +{ + int key; /* interrupt lock level */ + atomic_val_t ovalue; /* previous value from */ + + key = irq_lock_inline(); + ovalue = *target; + *target = ovalue - value; + irq_unlock_inline(key); + return ovalue; +} + +/******************************************************************************* +* +* atomic_inc - atomic increment primitive +* +* This routine provides the atomic increment operator. The value at +* is atomically incremented by 1, and the old value from is returned. +* +* RETURNS: The value from before the increment +*/ + +atomic_val_t atomic_inc( + atomic_t *target /* memory location to increment */ + ) +{ + int key; /* interrupt lock level */ + atomic_val_t ovalue; /* value from before the increment */ + + key = irq_lock_inline(); + ovalue = *target; + *target = ovalue + 1; + irq_unlock_inline(key); + return ovalue; +} + +/******************************************************************************* +* +* atomic_dec - atomic decrement primitive +* +* This routine provides the atomic decrement operator. The value at +* is atomically decremented by 1, and the old value from is returned. +* +* RETURNS: The value from prior to the decrement +*/ + +atomic_val_t atomic_dec( + atomic_t *target /* memory location to decrement */ + ) +{ + int key; /* interrupt lock level */ + atomic_val_t ovalue; /* value from prior to the decrement */ + + key = irq_lock_inline(); + ovalue = *target; + *target = ovalue - 1; + irq_unlock_inline(key); + return ovalue; +} + +/******************************************************************************* +* +* atomic_get - atomic get primitive +* +* This routine provides the atomic get primitive to atomically read +* a value from . It simply does an ordinary load. Note that +* is expected to be aligned to a 4-byte boundary. +* +* RETURNS: The value read from +*/ + +atomic_val_t atomic_get(atomic_t *target /* memory location to read from */ + ) +{ + return *target; +} + +/******************************************************************************* +* +* atomic_set - atomic get-and-set primitive +* +* This routine provides the atomic set operator. The is atomically +* written at and the previous value at is returned. +* +* RETURNS: The previous value from +*/ + +atomic_val_t atomic_set( + atomic_t *target, /* memory location to write to */ + atomic_val_t value /* value to write */ + ) +{ + int key; /* interrupt lock level */ + atomic_val_t ovalue; /* previous value from */ + + key = irq_lock_inline(); + ovalue = *target; + *target = value; + irq_unlock_inline(key); + return ovalue; +} + +/******************************************************************************* +* +* atomic_clear - atomic clear primitive +* +* This routine provides the atomic clear operator. The value of 0 is atomically +* written at and the previous value at is returned. (Hence, +* atomic_clear(pAtomicVar) is equivalent to atomic_set(pAtomicVar, 0).) +* +* RETURNS: The previous value from +*/ + +atomic_val_t atomic_clear( + atomic_t *target /* memory location to write to */ + ) +{ + int key; /* interrupt lock level */ + atomic_val_t ovalue; /* previous value from */ + + key = irq_lock_inline(); + ovalue = *target; + *target = 0; + irq_unlock_inline(key); + return ovalue; +} + +/******************************************************************************* +* +* atomic_or - atomic bitwise inclusive OR primitive +* +* This routine provides the atomic bitwise inclusive OR operator. The +* is atomically bitwise OR'ed with the value at , placing the result +* at , and the previous value at is returned. +* +* RETURNS: The previous value from +*/ + +atomic_val_t atomic_or( + atomic_t *target, /* memory location to be modified */ + atomic_val_t value /* value to OR */ + ) +{ + int key; /* interrupt lock level */ + atomic_val_t ovalue; /* previous value from */ + + key = irq_lock_inline(); + ovalue = *target; + *target = ovalue | value; + irq_unlock_inline(key); + return ovalue; +} + +/******************************************************************************* +* +* atomic_xor - atomic bitwise exclusive OR (XOR) primitive +* +* This routine provides the atomic bitwise exclusive OR operator. The +* is atomically bitwise XOR'ed with the value at , placing the result +* at , and the previous value at is returned. +* +* RETURNS: The previous value from +*/ + +atomic_val_t atomic_xor( + atomic_t *target, /* memory location to be modified */ + atomic_val_t value /* value to XOR */ + ) +{ + int key; /* interrupt lock level */ + atomic_val_t ovalue; /* previous value from */ + + key = irq_lock_inline(); + ovalue = *target; + *target = ovalue ^ value; + irq_unlock_inline(key); + return ovalue; +} + +/******************************************************************************* +* +* atomic_and - atomic bitwise AND primitive +* +* This routine provides the atomic bitwise AND operator. The is +* atomically bitwise AND'ed with the value at , placing the result +* at , and the previous value at is returned. +* +* RETURNS: The previous value from +*/ + +atomic_val_t atomic_and( + atomic_t *target, /* memory location to be modified */ + atomic_val_t value /* value to AND */ + ) +{ + int key; /* interrupt lock level */ + atomic_val_t ovalue; /* previous value from */ + + key = irq_lock_inline(); + ovalue = *target; + *target = ovalue & value; + irq_unlock_inline(key); + return ovalue; +} + +/******************************************************************************* +* +* atomic_nand - atomic bitwise NAND primitive +* +* This routine provides the atomic bitwise NAND operator. The is +* atomically bitwise NAND'ed with the value at , placing the result +* at , and the previous value at is returned. +* +* RETURNS: The previous value from +*/ + +atomic_val_t atomic_nand( + atomic_t *target, /* memory location to be modified */ + atomic_val_t value /* value to NAND */ + ) +{ + int key; /* interrupt lock level */ + atomic_val_t ovalue; /* previous value from */ + + key = irq_lock_inline(); + ovalue = *target; + *target = ~(ovalue & value); + irq_unlock_inline(key); + return ovalue; +} + +#endif /* CONFIG_LOCK_INSTRUCTION_UNSUPPORTED */ diff --git a/arch/x86/core/nanocontext.c b/arch/x86/core/nanocontext.c new file mode 100644 index 00000000000..f50d0be6a4c --- /dev/null +++ b/arch/x86/core/nanocontext.c @@ -0,0 +1,404 @@ +/* nanocontext.c - VxMicro nanokernel context support primitives */ + +/* + * Copyright (c) 2010-2015 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This module provides core nanokernel fiber related primitives for the IA-32 +processor architecture. +*/ + +/* includes */ + +#ifdef CONFIG_MICROKERNEL +#include +#include +#endif /* CONFIG_MICROKERNEL */ + +#include +#include +#include +#include + + +/* the one and only nanokernel control structure */ + +tNANO _NanoKernel = {0}; + +/* forward declaration */ + +#ifdef CONFIG_GDB_INFO +void _ContextEntryWrapper(_ContextEntry, _ContextArg, _ContextArg, _ContextArg); +#endif /* CONFIG_GDB_INFO */ + +/******************************************************************************* +* +* _NewContextInternal - initialize a new execution context +* +* This function is utilized to initialize all execution contexts, both fiber +* contexts, kernel task contexts and user mode task contexts. The 'priority' +* parameter will be set to -1 for the creation of task context. +* +* This function is called by _NewContext() and _NewContextUsr() to initialize +* task contexts. +* +* RETURNS: N/A +* +* \NOMANUAL +*/ + +static void _NewContextInternal( + tCCS * ccs, /* pointer to the new task's ccs */ + char *pStackMem, /* pointer to context stack memory */ + unsigned stackSize, /* size of stack in bytes */ + int priority, /* context priority */ + unsigned options /* context options: USE_FP, USE_SSE */ + ) +{ + unsigned long *pInitialCtx; + +#ifndef CONFIG_FP_SHARING + ARG_UNUSED(options); +#endif /* !CONFIG_FP_SHARING */ + + ccs->link = (tCCS *)NULL; /* context not inserted into list yet */ + ccs->prio = priority; +#if (defined(CONFIG_FP_SHARING) || defined(CONFIG_GDB_INFO)) + ccs->excNestCount = 0; +#endif /* CONFIG_FP_SHARING || CONFIG_GDB_INFO */ + + + if (priority == -1) + ccs->flags = PREEMPTIBLE | TASK; + else + ccs->flags = FIBER; + +#ifdef CONFIG_CONTEXT_CUSTOM_DATA + /* Initialize custom data field (value is opaque to kernel) */ + + ccs->custom_data = NULL; +#endif + + + /* + * The creation of the initial stack for the task (user or kernel) has + * already been done. Now all that is needed is to set the ESP. However, + * we have been passed the base address of the stack which is past the + * initial stack frame. Therefore some of the calculations done in the + * other routines that initialize the stack frame need to be repeated. + */ + + pInitialCtx = (unsigned long *)STACK_ROUND_DOWN(pStackMem + stackSize); + + /* + * We subtract 11 here to account for the context entry routine + * parameters + * (4 of them), eflags, eip, and the edi/esi/ebx/ebp/eax registers. + */ + pInitialCtx -= 11; + + ccs->coopReg.esp = (unsigned long)pInitialCtx; + PRINTK("\nInitial context ESP = 0x%x\n", ccs->coopReg.esp); + +#ifdef CONFIG_FP_SHARING +/* + * Indicate if the context is permitted to use floating point instructions. + * + * The first time the new context is scheduled by _Swap() it is guaranteed + * to inherit an FPU that is in a "sane" state (if the most recent user of + * the FPU was cooperatively swapped out) or a completely "clean" state + * (if the most recent user of the FPU was pre-empted, or if the new context + * is the first user of the FPU). + * + * The USE_FP flag bit is set in the tCCS structure if a context is + * authorized to use _any_ non-integer capability, whether it's the basic + * x87 FPU/MMX capability, SSE instructions, or a combination of both. The + * USE_SSE flag bit is set only if a context can use SSE instructions. + * + * Note: Callers need not follow the aforementioned protocol when passing + * in context options. It is legal for the caller to specify _only_ the + * USE_SSE option bit if a context will be utilizing SSE instructions (and + * possibly x87 FPU/MMX instructions). + */ + +/* + * Implementation Remark: + * Until SysGen reserves SSE_GROUP as 0x10, the following conditional is + * required so that at least systems configured with FLOAT will still operate + * correctly. The issue is that SysGen will utilize group 0x10 user-defined + * groups, and thus tasks placed in the user-defined group will have the + * SSE_GROUP (but not the FPU_GROUP) bit set. This results in both the USE_FP + * and USE_SSE bits being set in the tCCS. For systems configured only with + * FLOAT, the setting of the USE_SSE is harmless, but the setting of USE_FP is + * wasteful. Thus to ensure that that systems configured only with FLOAT + * behave as expected, the USE_SSE option bit is ignored. + * + * Clearly, even with the following conditional, systems configured with + * SSE will not behave as expected since tasks may still be inadvertantly + * have the USE_SSE+USE_FP sets even though they are integer only. + * + * Once the generator tool has been updated to reserve the SSE_GROUP, the + * correct code to use is: + * + * options &= USE_FP | USE_SSE; + * + */ + +#ifdef CONFIG_SSE + options &= USE_FP | USE_SSE; +#else + options &= USE_FP; +#endif + + if (options != 0) { + ccs->flags |= (options | USE_FP); + } +#endif /* CONFIG_FP_SHARING */ + + PRINTK("\ntCCS * = 0x%x", ccs); + +#if defined(CONFIG_HOST_TOOLS_SUPPORT) + { + unsigned int imask; + + /* + * Add the newly initialized context to head of the list of + * contexts. + * This singly linked list of contexts maintains ALL the + * contexts in the + * system: both tasks and fibers regardless of whether they are + * runnable. + */ + + imask = irq_lock(); + ccs->activeLink = _NanoKernel.contexts; + _NanoKernel.contexts = ccs; + irq_unlock(imask); + } +#endif /* CONFIG_HOST_TOOLS_SUPPORT */ +} + +#ifdef CONFIG_GDB_INFO +/******************************************************************************* +* +* _ContextEntryWrapper - adjust stack before invoking _ContextEntryRtn +* +* This function adjusts the initial stack frame created by _NewContext() +* such that the GDB stack frame unwinders recognize it as the outermost frame +* in the context's stack. The function then jumps to _ContextEntryRtn(). +* +* GDB normally stops unwinding a stack when it detects that it has +* reached a function called main(). Kernel tasks, however, do not have +* a main() function, and there does not appear to be a simple way of stopping +* the unwinding of the stack. +* +* Given the initial context created by _NewContext(), GDB expects to find a +* return address on the stack immediately above the context entry routine +* _ContextEntryRtn, in the location occupied by the initial EFLAGS. +* GDB attempts to examine the memory at this return address, which typically +* results in an invalid access to page 0 of memory. +* +* This function overwrites the initial EFLAGS with zero. When GDB subsequently +* attempts to examine memory at address zero, the PeekPoke driver detects +* an invalid access to address zero and returns an error, which causes the +* GDB stack unwinder to stop somewhat gracefully. +* +* __________________ +* | param3 | <------ Top of the stack +* |__________________| +* | param2 | Stack Grows Down +* |__________________| | +* | param1 | V +* |__________________| +* | pEntry | +* |__________________| +* | initial EFLAGS | <---- ESP when invoked by _Swap() +* |__________________| (Zeroed by this routine) +* | entryRtn | <----- Context Entry Routine invoked by _Swap() +* |__________________| (This routine if GDB_INFO) +* | | \ +* |__________________| | +* | | | +* |__________________| | +* | | |---- Initial registers restored by _Swap() +* |__________________| | +* | | | +* |__________________| | +* | | / +* |__________________| +* +* +* The initial EFLAGS cannot be overwritten until after _Swap() has swapped in +* the new context for the first time. This routine is called by _Swap() the +* first time that the new context is swapped in, and it jumps to +* _ContextEntryRtn after it has done its work. +* +* RETURNS: this routine does NOT return. +* +* \NOMANUAL +*/ + +__asm__("\t.globl _ContextEntryRtn\n" + "\t.section .text\n" + "_ContextEntryWrapper:\n" /* should place this func .s file and use + SECTION_FUNC */ + "\tmovl $0, (%esp)\n" /* zero initialEFLAGS location */ + "\tjmp _ContextEntryRtn\n"); +#endif /* CONFIG_GDB_INFO */ + +/******************************************************************************* +* +* _NewContext - create a new kernel execution context +* +* This function is utilized to create execution contexts for both fiber +* contexts and kernel task contexts. +* +* This function is called by start_task() to initialize task contexts, and +* by _FiberStart() (nanoFiberStart) to initialize fiber contexts. +* +* The "context control block" (CCS) is carved from the "end" of the specified +* context stack memory. +* +* RETURNS: opaque pointer to initialized CCS structure +* +* \NOMANUAL +*/ + +void *_NewContext( + char *pStackMem, /* pointer to context stack memory */ + unsigned stackSize, /* size of stack in bytes */ + _ContextEntry pEntry, /* context entry point function */ + void *parameter1, /* first parameter to context entry point function */ + void *parameter2, /* second parameter to context entry point function */ + void *parameter3, /* third parameter to context entry point function */ + int priority, /* context priority */ + unsigned options /* context options: USE_FP, USE_SSE */ + ) +{ + tCCS *ccs; + unsigned long *pInitialContext; + + /* carve the context entry struct from the "base" of the stack */ + + pInitialContext = + (unsigned long *)STACK_ROUND_DOWN(pStackMem + stackSize); + + /* + * Create an initial context on the stack expected by the _Swap() + * primitive. + * Given that both task and fiber contexts execute at privilege 0, the + * setup for both contexts are equivalent. + */ + + /* push arguments required by _ContextEntryRtn() */ + + *--pInitialContext = (unsigned long)parameter3; + *--pInitialContext = (unsigned long)parameter2; + *--pInitialContext = (unsigned long)parameter1; + *--pInitialContext = (unsigned long)pEntry; + + /* push initial EFLAGS; only modify IF and IOPL bits */ + + *--pInitialContext = (EflagsGet() & ~EFLAGS_MASK) | EFLAGS_INITIAL; + +#ifdef CONFIG_GDB_INFO + + /* + * Arrange for the _ContextEntryWrapper() function to be called + * to adjust the stack before _ContextEntryRtn() is invoked. + */ + + *--pInitialContext = (unsigned long)_ContextEntryWrapper; + +#else /* CONFIG_GDB_INFO */ + + *--pInitialContext = (unsigned long)_ContextEntryRtn; + +#endif /* CONFIG_GDB_INFO */ + + /* + * note: stack area for edi, esi, ebx, ebp, and eax registers can be + * left + * uninitialized, since _ContextEntryRtn() doesn't care about the values + * of these registers when it begins execution + */ + + /* + * For kernel tasks and fibers the context the context control struct + * (CCS) + * is located at the "low end" of memory set aside for the context's + * stack + */ + + ccs = (tCCS *)ROUND_UP(pStackMem, CCS_ALIGN); + + _NewContextInternal(ccs, pStackMem, stackSize, priority, options); + + + return ((void *)ccs); +} + + +/******************************************************************************* +* +* _NanoEssentialContextSet - Set ESSENTIAL flag for running fiber or task. +* +* This function is called by the running fiber or task if it deems itself +*essential. +* That is, it cannot terminate or handle any exceptions such as page fault. +* +* RETURNS: N/A +* +* \NOMANUAL +*/ + +void _NanoEssentialContextSet(void) +{ + _NanoKernel.current->flags |= ESSENTIAL; +} + +/******************************************************************************* +* +* _NanoEssentialContextClear - Clear ESSENTIAL flag for running fiber or task. +* +* This function is called by the running fiber or task to render it +*non-essential. +* By default, upon creation, a fiber or task is non-essential. +* +* RETURNS: N/A +* +* \NOMANUAL +*/ + +void _NanoEssentialContextClear(void) +{ + _NanoKernel.current->flags &= ~ESSENTIAL; +} diff --git a/arch/x86/core/nanofatal.c b/arch/x86/core/nanofatal.c new file mode 100644 index 00000000000..f276d21cd93 --- /dev/null +++ b/arch/x86/core/nanofatal.c @@ -0,0 +1,147 @@ +/* nanofatal.c - nanokernel fatal error handler */ + +/* + * Copyright (c) 2013-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This module provides the _NanoFatalErrorHandler() routine. +*/ + +/* includes */ + +/* Stack canaries not supported on Diab */ +#ifdef __DCC__ +#undef CONFIG_STACK_CANARIES +#endif + +#include +#include + +#include +#include +#include +#include +#include + + +/* globals */ + +/* + * Define a default ESF for use with _NanoFatalErrorHandler() in the event + * the caller does not have a NANO_ESF to pass + */ +const NANO_ESF __defaultEsf = { +#ifdef CONFIG_GDB_INFO + 0xdeaddead, /* EBP */ + 0xdeaddead, /* EBX */ + 0xdeaddead, /* ESI */ + 0xdeaddead, /* EDI */ +#endif /* CONFIG_GDB_INFO */ + 0xdeaddead, /* EDX */ + 0xdeaddead, /* ECX */ + 0xdeaddead, /* EAX */ + 0xdeaddead, /* error code */ + 0xdeaddead, /* EIP */ + 0xdeaddead, /* CS */ + 0xdeaddead, /* EFLAGS */ + 0xdeaddead, /* ESP */ + 0xdeaddead /* SS */ +}; + +/******************************************************************************* +* +* _NanoFatalErrorHandler - nanokernel fatal error handler +* +* This routine is called when a fatal error condition is detected by either +* hardware or software. +* +* The caller is expected to always provide a usable ESF. In the event that the +* fatal error does not have a hardware generated ESF, the caller should either +* create its own or use a pointer to the global default ESF <__defaultEsf>. +* +* RETURNS: This function does not return. +* +* \NOMANUAL +*/ + +FUNC_NORETURN void _NanoFatalErrorHandler( + unsigned int reason, /* reason that handler was called */ + const NANO_ESF *pEsf /* pointer to exception stack frame */ + ) +{ + +#ifdef CONFIG_PRINTK + + /* Display diagnostic information about the error */ + + switch (reason) { + case _NANO_ERR_SPURIOUS_INT: + printk("***** Unhandled exception/interrupt occurred! " + "*****\n"); + break; + + + case _NANO_ERR_INVALID_TASK_EXIT: + printk("***** Invalid Exit Software Error! *****\n"); + break; + +#if defined(CONFIG_STACK_CANARIES) + case _NANO_ERR_STACK_CHK_FAIL: + printk("***** Stack Check Fail! *****\n"); + break; +#endif /* CONFIG_STACK_CANARIES */ + + +#ifdef CONFIG_ENHANCED_SECURITY + case _NANO_ERR_INVALID_STRING_OP: + printk("**** Invalid string operation! ****\n"); + break; +#endif /* CONFIG_ENHANCED_SECURITY */ + + default: + printk("**** Unknown Fatal Error %d! ****\n", reason); + break; + } + + printk("Current context ID = 0x%x\n" + "Faulting instruction address = 0x%x\n", + context_self_get(), + pEsf->eip); +#endif /* CONFIG_PRINTK */ + + + /* + * Error was fatal to a kernel task or a fiber, + * so invoke the system fatal error handling policy defined for the BSP + */ + + _SysFatalErrorHandler(reason, pEsf); +} diff --git a/arch/x86/core/nanofloat.c b/arch/x86/core/nanofloat.c new file mode 100644 index 00000000000..a64cc1e2123 --- /dev/null +++ b/arch/x86/core/nanofloat.c @@ -0,0 +1,556 @@ +/* nanofloat.c - VxMicro floating point resource sharing routines */ + +/* + * Copyright (c) 2010-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This module allows multiple tasks and fibers to safely share the system's +floating point resources, by allowing the system to save FPU state information +in a task or fiber's stack region when a pre-emptive context switch occurs. + +The floating point resource sharing mechanism is designed for minimal +intrusiveness. Floating point context saving is only performed for tasks and +fibers that explicitly enable FP resource sharing, to avoid impacting the stack +size requirements of all other tasks and fibers. For those tasks and fibers +that do require FP resource sharing, a "lazy save/restore" mechanism is employed +so that the FPU's register sets are only switched in and out when absolutely +necessary; this avoids wasting effort preserving them when there is no risk +that they will be altered, or when there is no need to preserve their contents. + +The following APIs are provided to allow floating point resource sharing to be +enabled or disabled at run-time: + + void fiber_float_enable (nano_context_id_t ctxId, unsigned int options) + void task_float_enable (nano_context_id_t ctxId, unsigned int options) + void fiber_float_disable (nano_context_id_t ctxId) + void task_float_disable (nano_context_id_t ctxId) + +The 'options' parameter is used to specify what non-integer capabilities are +being used. The same options accepted by nanoFiberStart() are used in the +aforementioned APIs, namely USE_FP and USE_SSE. + +If the VxMicro nanokernel has been built with support for automatic enabling +of floating point resource sharing (CONFIG_AUTOMATIC_FP_ENABLING) the +system automatically enables sharing for any non-enabled task or fiber as soon +as it begins using floating point instructions. (Note: The task or fiber must +have enough room available on its stack to allow floating point state info +to be saved, otherwise stack corruption will occur.) + +If the VxMicro nanokernel has been built without SSE instruction support +(CONFIG_SSE), the system treats USE_SSE as if it was USE_FP. + +If the VxMicro nanokernel has been built without floating point resource +sharing support (CONFIG_FP_SHARING), the aforementioned APIs and +capabilities do not exist. + +NOTE +It is possible for a single task or fiber to utilize floating instructions +_without_ enabling the FP resource sharing feature. Since no other task or +fiber uses the FPU the FP registers won't change when the FP-capable task or +fiber isn't executing, meaning there is no need to save the registers. + +WARNING +The use of floating point instructions by ISRs is not supported by VxMicro. + +INTERNAL +If automatic enabling of floating point resource sharing _is not_ configured +the system leaves CR0[TS] = 0 for all tasks and fibers. This means that any +task or fiber can perform floating point operations at any time without causing +an exception, and the system won't stop a task or fiber that shouldn't be +doing FP stuff from doing it. + +If automatic enabling of floating point resource sharing _is_ configured the +system leaves CR0[TS] = 0 only for tasks and fibers that are allowed to perform +FP operations. All other tasks and fibers have CR0[TS] = 1 so that an attempt +to perform an FP operation will cause an exception, allowing the system to +enable FP resource sharing on its behalf. + +*/ + +#ifdef CONFIG_MICROKERNEL +#include +#include +#endif /* CONFIG_MICROKERNEL */ + +#include +#include + +/* the entire library vanishes without the FP_SHARING option enabled */ + +#ifdef CONFIG_FP_SHARING + +#if defined(CONFIG_SSE) +extern uint32_t _Mxcsr; /* SSE control/status register default value */ +#endif /* CONFIG_SSE */ + +#ifdef CONFIG_AUTOMATIC_FP_ENABLING + +/******************************************************************************* +* +* _FpAccessDisable - disallow use of floating point capabilities +* +* This routine sets CR0[TS] to 1, which disallows the use of FP instructions +* by the currently executing context. +* +* RETURNS: N/A +*/ + +#if defined(__GNUC__) +static void _FpAccessDisable(void) +{ + void *tempReg; + + __asm__ volatile( + "movl %%cr0, %0;\n\t" + "orl $0x8, %0;\n\t" + "movl %0, %%cr0;\n\t" + : "=r"(tempReg) + : + : "memory"); +} +#elif defined(__DCC__) +__asm volatile void _FpAccessDisable(void) +{ + % !"ax" movl % cr0, % eax orl $0x8, % eax movl % eax, % cr0 +} +#endif /* __GNUC__ */ + +#endif /* CONFIG_AUTOMATIC_FP_ENABLING */ + +/******************************************************************************* +* +* _FpCtxSave - save non-integer context information +* +* This routine saves the system's "live" non-integer context into the +* specified CCS. If the specified task or fiber supports SSE then +* x87/MMX/SSEx context info is saved, otherwise only x87/MMX context is saved. +* +* RETURNS: N/A +*/ + +#if defined(__GNUC__) +static void _FpCtxSave(tCCS *ccs) +{ +#ifdef CONFIG_SSE + if (ccs->flags & USE_SSE) { + __asm__ volatile("fxsave (%0);\n\t" + : + : "r"(&ccs->preempFloatReg) + : "memory"); + } else +#endif /* CONFIG_SSE */ + { + __asm__ volatile("fnsave (%0);\n\t" + : + : "r"(&ccs->preempFloatReg) + : "memory"); + } +} +#elif defined(__DCC__) +__asm volatile void _FpCtxSave(tCCS *ccs) +{ + % mem ccs !"ax", "cx" movl ccs, + % eax leal __tCCS_preempFloatReg_OFFSET( % eax), + % ecx /* &preempFloatReg */ +#ifdef CONFIG_SSE + testl $0x20, + __tCCS_flags_OFFSET( % eax) jz 0f fxsave( % ecx) jmp 1f 0 + : fnsave( % ecx)1 : +#else + fnsave( % ecx) +#endif /* CONFIG_SSE */ +} +#endif + +/******************************************************************************* +* +* _FpCtxInit - initialize non-integer context information +* +* This routine initializes the system's "live" non-integer context. +* +* RETURNS: N/A +*/ + +#if defined(__GNUC__) +static inline void _FpCtxInit(tCCS *ccs) +{ + /* initialize x87 FPU */ + __asm__ volatile("fninit\n\t"); + + +#ifdef CONFIG_SSE + if (ccs->flags & USE_SSE) { + /* initialize SSE (since context uses it) */ + __asm__ volatile("ldmxcsr _Mxcsr\n\t"); + + } +#else + ARG_UNUSED(ccs); +#endif /* CONFIG_SSE */ +} +#elif defined(__DCC__) +__asm volatile void _FpCtxInit(tCCS *ccs) +{ + % mem ccs !"ax" + /* initialize x87 FPU */ + fninit + + +#ifdef CONFIG_SSE + movl ccs, + % eax testl $0x20, + __tCCS_flags_OFFSET( % eax) jz 0f + + /* initialize SSE (since context uses it) */ + ldmxcsr _Mxcsr + +0 : +#endif /* CONFIG_SSE */ +} +#endif + +/******************************************************************************* +* +* _FpEnable - enable preservation of non-integer context information +* +* This routine allows the specified task/fiber (which may be the active +* task/fiber) to safely share the system's floating point registers with +* other tasks/fibers. The parameter indicates which floating point +* register sets will be used by the specified task/fiber: +* +* a) USE_FP indicates x87 FPU and MMX registers only +* b) USE_SSE indicates x87 FPU and MMX and SSEx registers +* +* Invoking this routine creates a floating point context for the task/fiber +* that corresponds to an FPU that has been reset. The system will thereafter +* protect the task/fiber's FP context so that it is not altered during +* a pre-emptive context switch. +* +* WARNING +* This routine should only be used to enable floating point support for a +* task/fiber that does not currently have such support enabled already. +* +* RETURNS: N/A +* +* INTERNAL +* Since the transition from "non-FP supporting" to "FP supporting" must be done +* atomically to avoid confusing the floating point logic used by _Swap(), +* this routine locks interrupts to ensure that a context switch does not occur, +* The locking isn't really needed when the routine is called by a fiber +* (since context switching can't occur), but it is harmless and allows a single +* routine to be called by both tasks and fibers (thus saving code space). +* +* If necessary, the interrupt latency impact of calling this routine from a +* fiber could be lessened by re-designing things so that only task-type callers +* locked interrupts (i.e. move the locking to task_float_enable()). However, +* all calls to fiber_float_enable() would need to be reviewed to ensure they +* are only used from a fiber, rather than from "generic" code used by both +* tasks and fibers. +*/ + +void _FpEnable(tCCS *ccs, + unsigned int options /* USE_FP or USE_SSE */ + ) +{ + unsigned int imask; + tCCS *fp_owner; + + /* Lock interrupts to prevent a pre-emptive context switch from occuring + */ + + imask = irq_lock_inline(); + + /* Indicate task/fiber requires non-integer context saving */ + + ccs->flags |= options | USE_FP; /* USE_FP is treated as a "dirty bit" */ + +#ifdef CONFIG_AUTOMATIC_FP_ENABLING + /* + * Current task/fiber might not allow FP instructions, so clear CR0[TS] + * so we can use them. (CR0[TS] gets restored later on, if necessary.) + */ + + __asm__ volatile("clts\n\t"); +#endif /* CONFIG_AUTOMATIC_FP_ENABLING */ + + /* + * Save the existing non-integer context (since it is about to change), + * but only if the FPU is "owned" by an FP-capable task that is + * currently + * handling an interrupt or exception (meaning it's FP context must be + * preserved). + */ + + fp_owner = _NanoKernel.current_fp; + if (fp_owner) { + if (fp_owner->flags & INT_OR_EXC_MASK) { + _FpCtxSave(fp_owner); + } + } + + /* Now create a virgin FP context */ + + _FpCtxInit(ccs); + + /* Associate the new FP context with the specified task/fiber */ + + if (ccs == _NanoKernel.current) { + /* + * When enabling FP support for self, just claim ownership of + *the FPU + * and leave CR0[TS] unset. + * + * (Note: the FP context is "live" in hardware, not saved in + *CCS.) + */ + + _NanoKernel.current_fp = ccs; + } else { + /* + * When enabling FP support for someone else, assign ownership + * of the FPU to them (unless we need it ourselves). + */ + + if ((_NanoKernel.current->flags & USE_FP) != USE_FP) { + /* + * We are not FP-capable, so mark FPU as owned by the + * context + * we've just enabled FP support for, then disable our + * own + * FP access by setting CR0[TS] to its original state. + */ + + _NanoKernel.current_fp = ccs; +#ifdef CONFIG_AUTOMATIC_FP_ENABLING + _FpAccessDisable(); +#endif /* CONFIG_AUTOMATIC_FP_ENABLING */ + } else { + /* + * We are FP-capable (and thus had FPU ownership on + *entry), so save + * the new FP context in their CCS, leave FPU ownership + *with self, + * and leave CR0[TS] unset. + * + * Note: The saved FP context is needed in case the task + *or fiber + * we enabled FP support for is currently pre-empted, + *since _Swap() + * uses it to restore FP context when the task/fiber + *re-activates. + * + * Note: Saving the FP context reinits the FPU, and thus + *our own + * FP context, but that's OK since it didn't need to be + *preserved. + * (i.e. We aren't currently handling an interrupt or + *exception.) + */ + + _FpCtxSave(ccs); + } + } + + irq_unlock_inline(imask); +} + +/******************************************************************************* +* +* fiber_float_enable - enable preservation of non-integer context information +* +* This routine allows a fiber to permit a task/fiber (including itself) to +* safely share the system's floating point registers with other tasks/fibers. +* +* See the description of _FpEnable() for further details. +* +* RETURNS: N/A +*/ + +FUNC_ALIAS(_FpEnable, fiber_float_enable, void); + +/******************************************************************************* +* +* task_float_enable - enable preservation of non-integer context information +* +* This routine allows a task to permit a task/fiber (including itself) to +* safely share the system's floating point registers with other tasks/fibers. +* +* See the description of _FpEnable() for further details. +* +* RETURNS: N/A +*/ + +FUNC_ALIAS(_FpEnable, task_float_enable, void); + +/******************************************************************************* +* +* _FpDisable - disable preservation of non-integer context information +* +* This routine prevents the specified task/fiber (which may be the active +* task/fiber) from safely sharing any of the system's floating point registers +* with other tasks/fibers. +* +* WARNING +* This routine should only be used to disable floating point support for +* a task/fiber that currently has such support enabled. +* +* RETURNS: N/A +* +* INTERNAL +* Since the transition from "FP supporting" to "non-FP supporting" must be done +* atomically to avoid confusing the floating point logic used by _Swap(), +* this routine locks interrupts to ensure that a context switch does not occur, +* The locking isn't really needed when the routine is called by a fiber +* (since context switching can't occur), but it is harmless and allows a single +* routine to be called by both tasks and fibers (thus saving code space). +* +* If necessary, the interrupt latency impact of calling this routine from a +* fiber could be lessened by re-designing things so that only task-type callers +* locked interrupts (i.e. move the locking to task_float_disable()). However, +* all calls to fiber_float_disable() would need to be reviewed to ensure they +* are only used from a fiber, rather than from "generic" code used by both +* tasks and fibers. +*/ + +void _FpDisable(tCCS *ccs) +{ + unsigned int imask; + + /* Lock interrupts to prevent a pre-emptive context switch from occuring + */ + + imask = irq_lock_inline(); + + /* + * Disable _all_ floating point capabilities for the task/fiber, + * regardless + * of the options specified at the time support was enabled. + */ + + ccs->flags &= ~(USE_FP | USE_SSE); + + if (ccs == _NanoKernel.current) { +#ifdef CONFIG_AUTOMATIC_FP_ENABLING + _FpAccessDisable(); +#endif /* CONFIG_AUTOMATIC_FP_ENABLING */ + + _NanoKernel.current_fp = (tCCS *)0; + } else { + if (_NanoKernel.current_fp == ccs) + _NanoKernel.current_fp = (tCCS *)0; + } + + irq_unlock_inline(imask); +} + +/******************************************************************************* +* +* fiber_float_disable - disable preservation of non-integer context +*information +* +* This routine allows a fiber to disallow a task/fiber (including itself) from +* safely sharing any of the system's floating point registers with other +* tasks/fibers. +* +* WARNING +* This routine should only be used to disable floating point support for +* a task/fiber that currently has such support enabled. +* +* RETURNS: N/A +*/ + +FUNC_ALIAS(_FpDisable, fiber_float_disable, void); + +/******************************************************************************* +* +* task_float_disable - disable preservation of non-integer context information +* +* This routine allows a task to disallow a task/fiber (including itself) from +* safely sharing any of the system's floating point registers with other +* tasks/fibers. +* +* WARNING +* This routine should only be used to disable floating point support for +* a task/fiber that currently has such support enabled. +* +* RETURNS: N/A +*/ + +FUNC_ALIAS(_FpDisable, task_float_disable, void); + +#ifdef CONFIG_AUTOMATIC_FP_ENABLING + +/******************************************************************************* +* +* _FpNotAvailableExcHandler - handler for "device not available" exception +* +* This routine is registered to handle the "device not available" exception +* (vector = 7) when the AUTOMATIC_FP_ENABLING configuration option has been +* been selected. +* +* The processor will generate this exception if any x87 FPU, MMX, or SSEx +* instruction is executed while CR0[TS]=1. The handler then enables the +* current task or fiber with the USE_FP option (or the USE_SSE option if the +* SSE configuration option has been enabled). +* +* RETURNS: N/A +*/ + +void _FpNotAvailableExcHandler(NANO_ESF * pEsf /* not used */ + ) +{ + unsigned int enableOption; + + ARG_UNUSED(pEsf); + + /* + * Assume the exception did not occur in the context of an ISR. + * (In other words, CPU cycles will not be consumed to perform + * error checking to ensure the exception was not generated in an ISR.) + */ + + PRINTK("_FpNotAvailableExcHandler() exception handler has been " + "invoked\n"); + +/* Enable the highest level of FP capability configured into the kernel */ + +#ifdef CONFIG_SSE + enableOption = USE_SSE; +#else + enableOption = USE_FP; +#endif + + _FpEnable(_NanoKernel.current, enableOption); +} + +#endif /* CONFIG_AUTOMATIC_FP_ENABLING */ + +#endif /* CONFIG_FP_SHARING */ diff --git a/arch/x86/core/offsets/offsets.c b/arch/x86/core/offsets/offsets.c new file mode 100644 index 00000000000..d34b3f4c7a0 --- /dev/null +++ b/arch/x86/core/offsets/offsets.c @@ -0,0 +1,158 @@ +/* offsets.c - VxMicro nanokernel structure member offset definition file */ + +/* + * Copyright (c) 2010-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This module is responsible for the generation of the absolute symbols whose +value represents the member offsets for various IA-32 nanokernel structures. + +All of the absolute symbols defined by this module will be present in the +final microkernel or nanokernel ELF image (due to the linker's reference to +the _OffsetAbsSyms symbol). + +INTERNAL +It is NOT necessary to define the offset for every member of a structure. +Typically, only those members that are accessed by assembly language routines +are defined; however, it doesn't hurt to define all fields for the sake of +completeness. + +*/ + +#include /* located in kernel/arch/common/include */ + +/* list of headers that define whose structure offsets will be generated */ + +#include +#include + + +#include + +/* Intel-specific tNANO structure member offsets */ + +GEN_OFFSET_SYM(tNANO, nested); +GEN_OFFSET_SYM(tNANO, common_isp); +#ifdef CONFIG_ADVANCED_POWER_MANAGEMENT +GEN_OFFSET_SYM(tNANO, idle); +#endif /* CONFIG_ADVANCED_POWER_MANAGEMENT */ + +/* Intel-specific tCCS structure member offsets */ + +#ifdef CONFIG_GDB_INFO +GEN_OFFSET_SYM(tCCS, esfPtr); +#endif /* CONFIG_GDB_INFO */ +#if (defined(CONFIG_FP_SHARING) || defined(CONFIG_GDB_INFO)) +GEN_OFFSET_SYM(tCCS, excNestCount); +#endif /* CONFIG_FP_SHARING || CONFIG_GDB_INFO */ +#ifdef CONFIG_CONTEXT_CUSTOM_DATA +GEN_OFFSET_SYM(tCCS, custom_data); /* available for custom use */ +#endif +GEN_OFFSET_SYM(tCCS, coopFloatReg); /* start of coop FP register set */ +GEN_OFFSET_SYM(tCCS, preempFloatReg); /* start of prempt FP register set */ + +/* size of the tCCS structure sans save area for floating point regs */ + +GEN_ABSOLUTE_SYM(__tCCS_NOFLOAT_SIZEOF, + sizeof(tCCS) - sizeof(tCoopFloatReg) - + sizeof(tPreempFloatReg)); + +/* tCoopReg structure member offsets: tCCS->coopReg is of type tCoopReg */ + +GEN_OFFSET_SYM(tCoopReg, esp); + +/* tSwapStk structure member offsets */ + +GEN_OFFSET_SYM(tSwapStk, eax); +GEN_OFFSET_SYM(tSwapStk, ebp); +GEN_OFFSET_SYM(tSwapStk, ebx); +GEN_OFFSET_SYM(tSwapStk, esi); +GEN_OFFSET_SYM(tSwapStk, edi); +GEN_OFFSET_SYM(tSwapStk, retAddr); +GEN_OFFSET_SYM(tSwapStk, param); + +/* size of the entire tSwapStk structure */ + +GEN_ABSOLUTE_SYM(__tSwapStk_SIZEOF, sizeof(tSwapStk)); + +/* NANO_ESF structure member offsets */ + +#ifdef CONFIG_GDB_INFO +GEN_OFFSET_SYM(NANO_ESF, ebp); +GEN_OFFSET_SYM(NANO_ESF, ebx); +GEN_OFFSET_SYM(NANO_ESF, esi); +GEN_OFFSET_SYM(NANO_ESF, edi); +#endif /* CONFIG_GDB_INFO */ +GEN_OFFSET_SYM(NANO_ESF, cr2); +GEN_OFFSET_SYM(NANO_ESF, edx); +GEN_OFFSET_SYM(NANO_ESF, ecx); +GEN_OFFSET_SYM(NANO_ESF, eax); +GEN_OFFSET_SYM(NANO_ESF, errorCode); +GEN_OFFSET_SYM(NANO_ESF, eip); +GEN_OFFSET_SYM(NANO_ESF, cs); +GEN_OFFSET_SYM(NANO_ESF, eflags); +GEN_OFFSET_SYM(NANO_ESF, esp); +GEN_OFFSET_SYM(NANO_ESF, ss); + +/* NANO_ISF structure member offsets for host tools */ + +GEN_OFFSET_SYM_HOST(NANO_ISF, edx); +GEN_OFFSET_SYM_HOST(NANO_ISF, ecx); +GEN_OFFSET_SYM_HOST(NANO_ISF, eax); +GEN_OFFSET_SYM_HOST(NANO_ISF, eip); +GEN_OFFSET_SYM_HOST(NANO_ISF, cs); +GEN_OFFSET_SYM_HOST(NANO_ISF, eflags); +GEN_OFFSET_SYM_HOST(NANO_ISF, esp); +GEN_OFFSET_SYM_HOST(NANO_ISF, ss); + +/* NANO_SSF structure member offsets for host tools */ + +#ifdef CONFIG_GDB_INFO +GEN_OFFSET_SYM_HOST(NANO_SSF, ebp); +GEN_OFFSET_SYM_HOST(NANO_SSF, ebx); +GEN_OFFSET_SYM_HOST(NANO_SSF, esi); +GEN_OFFSET_SYM_HOST(NANO_SSF, edi); +#endif /* CONFIG_GDB_INFO */ +GEN_OFFSET_SYM_HOST(NANO_SSF, eip); +GEN_OFFSET_SYM_HOST(NANO_SSF, cs); +GEN_OFFSET_SYM_HOST(NANO_SSF, eflags); +GEN_OFFSET_SYM_HOST(NANO_SSF, esp); +GEN_OFFSET_SYM_HOST(NANO_SSF, ss); + +/* tTaskStateSegment structure member offsets */ + + +/* size of the ISR_LIST structure. Used by linker scripts */ + +GEN_ABSOLUTE_SYM(__ISR_LIST_SIZEOF, sizeof(ISR_LIST)); + + +GEN_ABS_SYM_END diff --git a/arch/x86/core/swap.s b/arch/x86/core/swap.s new file mode 100644 index 00000000000..1b2c61b3188 --- /dev/null +++ b/arch/x86/core/swap.s @@ -0,0 +1,391 @@ +/* swap.s - VxMicro nanokernel swapper code for IA-32 */ + +/* + * Copyright (c) 2010-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This module implements the _Swap() routine for the IA-32 architecture. + +Note that the file include/nanokernel/x86/swapstk.h defines +a representation of the save stack frame generated by _Swap() in order +to generate offsets (in the form of absolute symbols) for consumption by +host tools. Please update swapstk.h if changing the structure of the +save frame on the stack. +*/ + +#define _ASMLANGUAGE + +#include +#include +#include /* nanokernel structure offset definitions */ + + /* exports (internal APIs) */ + + GTEXT(_Swap) + + /* externs */ + + +/******************************************************************************* +* +* _Swap - initiate a cooperative context switch +* +* The _Swap() routine is invoked by various nanokernel services to effect +* a cooperative context context switch. Prior to invoking _Swap(), the +* caller disables interrupts (via irq_lock) and the return 'key' +* is passed as a parameter to _Swap(). The 'key' actually represents +* the EFLAGS register prior to disabling interrupts via a 'cli' instruction. +* +* Given that _Swap() is called to effect a cooperative context context switch, +* only the non-volatile integer registers need to be saved in the tCCS of the +* outgoing context. The restoration of the integer registers of the incoming +* context depends on whether that context was preemptively context switched +* out. The INT_ACTIVE and EXC_ACTIVE bits in the tCCS->flags field will signify +* that the context was preemptively context switched out, and thus both the +* volatile and non-volatile integer registers need to be restored. +* +* The non-volatile registers need to be scrubbed to ensure they contain no +* sensitive information that could compromise system security. This is to +* make sure that information will not be leaked from one application to +* another via these volatile registers. +* +* Here, the integer registers (EAX, ECX, EDX) have been scrubbed. Any changes +* to this routine that alter the values of these registers MUST be reviewed +* for potential security impacts. +* +* Floating point registers are handled using a lazy save/restore +* mechanism since it's expected relatively few contexts will be created +* with the USE_FP or USE_SSE option bits. The nanokernel data structure +* maintains a 'current_fp' field to keep track of the context that "owns" +* the floating point registers. Floating point registers consist of +* ST0->ST7 (x87 FPU and MMX registers) and XMM0 -> XMM7. +* +* All floating point registers are considered 'volatile' thus they will +* only be saved/restored when a preemptive context context switch occurs. +* +* Floating point registers are currently NOT scrubbed, and are subject to +* potential security leaks. +* +* The scheduling algorithm is simple: schedule the head of the runnable +* FIBER context list, which is represented by _NanoKernel.fiber. If there are +* no runnable FIBER contexts, then schedule the TASK context represented +* by _NanoKernel.task. The _NanoKernel.task field will never be NULL. +* +* RETURNS: may contain a return value setup by a call to fiberRtnValueSet() +* +* C function prototype: +* +* unsigned int _Swap (unsigned int eflags); +* +*/ + +SECTION_FUNC(TEXT, _Swap) + movl $_NanoKernel, %eax + + /* + * Push all non-volatile registers onto the stack; do not copy + * any of these registers into the tCCS. Only the 'esp' register + * after all the pushes have been performed) will be stored in the + * tCCS. + */ + + pushl %edi + pushl %esi + pushl %ebx + pushl %ebp + + /* + * Leave slot for eax register when _Swap() needs to return a value; + * pre-populate slot with ebx's value in case _Swap() does not return + * a value. + */ + + pushl %ebx + + + /* save esp into tCCS structure */ + + movl __tNANO_current_OFFSET (%eax), %ecx + movl %esp, __tCCS_coopReg_OFFSET + __tCoopReg_esp_OFFSET (%ecx) + + + /* + * Determine what FIBER or TASK context needs to be swapped in. + * Note that the %eax still contains &_NanoKernel. + */ + + movl __tNANO_fiber_OFFSET (%eax), %ecx + testl %ecx, %ecx + jz swapTask /* Jump if no ready fibers */ + + /* remove the head 'tCCS *' from the runnable context list */ + + movl __tCCS_link_OFFSET (%ecx), %ebx + movl %ebx, __tNANO_fiber_OFFSET (%eax) + jmp restoreContext + + + /* + * There are no FIBER context in the run queue, thus swap in the + * TASK context specified via _NanoKernel.task. The 'task' field + * will _never_ be NULL. + */ + +BRANCH_LABEL(swapTask) + movl __tNANO_task_OFFSET (%eax), %ecx + + /* fall through to 'restoreContext' */ + + + /* + * At this point, the %ecx register contains the 'tCCS *' of + * the TASK or FIBER to be swapped in, and %eax still + * contains &_NanoKernel. + */ + +BRANCH_LABEL(restoreContext) + +#ifdef CONFIG_FP_SHARING +#ifdef CONFIG_AUTOMATIC_FP_ENABLING + /* + * Clear the CR0[TS] bit (in the event the current context + * doesn't have floating point enabled) to prevent the "device not + * available" exception when executing the subsequent fxsave/fnsave + * and/or fxrstor/frstor instructions. + * + * Indeed, it's possible that none of the aforementioned instructions + * need to be executed, for example, the incoming context doesn't + * utilize floating point operations. However, the code responsible + * for setting the CR0[TS] bit appropriately for the incoming context + * (just after the 'restoreContext_NoFloatSwap' label) will leverage + * the fact that the following 'clts' was performed already. + */ + + clts +#endif /* CONFIG_AUTOMATIC_FP_ENABLING */ + + + /* + * Determine whether the incoming context utilizes non-integer + * capabilities _and_ whether the context was context switched + * out preemptively. + */ + + testl $USE_FP, __tCCS_flags_OFFSET (%ecx) + je restoreContext_NoFloatSwap + + + /* + * The incoming context uses non-integer capabilities (x87 FPU and/or + * XMM regs): Was it the last context to use non-integer capabilities? + * If so, there there is no need to restore the non-integer context. + */ + + movl __tNANO_current_fp_OFFSET (%eax), %ebx + cmpl %ebx, %ecx + je restoreContext_NoFloatSwap + + + /* + * The incoming context uses non-integer capabilities (x87 FPU and/or + * XMM regs) and it was _not_ the last context to use the non-integer + * capabilities: Check whether the current FP context actually needs + * to be saved before swapping in the context of the incoming context + */ + + testl %ebx, %ebx + jz restoreContext_NoFloatSave + + + /* + * The incoming context uses non-integer capabilities (x87 FPU and/or + * XMM regs) and it was _not_ the last context to use the non-integer + * capabilities _and_ the current FP context needs to be saved. + * + * Given that the ST[0] -> ST[7] and XMM0 -> XMM7 registers are all + * 'volatile', only save the registers if the "current FP context" + * was preemptively context switched. + */ + + testl $INT_OR_EXC_MASK, __tCCS_flags_OFFSET (%ebx) + je restoreContext_NoFloatSave + + +#ifdef CONFIG_SSE + testl $USE_SSE, __tCCS_flags_OFFSET (%ebx) + je x87FloatSave + + /* + * 'fxsave' does NOT perform an implicit 'fninit', therefore issue an + * 'fninit' to ensure a "clean" FPU state for the incoming context + * (for the case when the fxrstor is not executed). + */ + + fxsave __tCCS_preempFloatReg_OFFSET (%ebx) + fninit + jmp floatSaveDone + +BRANCH_LABEL(x87FloatSave) +#endif /* CONFIG_SSE */ + + /* 'fnsave' performs an implicit 'fninit' after saving state! */ + + fnsave __tCCS_preempFloatReg_OFFSET (%ebx) + + /* fall through to 'floatSaveDone' */ + +BRANCH_LABEL(floatSaveDone) +BRANCH_LABEL(restoreContext_NoFloatSave) + + /********************************************************* + * Restore floating point context of the incoming context. + *********************************************************/ + + /* + * Again, given that the ST[0] -> ST[7] and XMM0 -> XMM7 registers are + * all 'volatile', only restore the registers if the incoming + * context was previously preemptively context switched out. + */ + + testl $INT_OR_EXC_MASK, __tCCS_flags_OFFSET (%ecx) + je restoreContext_NoFloatRestore + +#ifdef CONFIG_SSE + testl $USE_SSE, __tCCS_flags_OFFSET (%ecx) + je x87FloatRestore + + fxrstor __tCCS_preempFloatReg_OFFSET (%ecx) + jmp floatRestoreDone + +BRANCH_LABEL(x87FloatRestore) + +#endif /* CONFIG_SSE */ + + frstor __tCCS_preempFloatReg_OFFSET (%ecx) + + /* fall through to 'floatRestoreDone' */ + +BRANCH_LABEL(floatRestoreDone) +BRANCH_LABEL(restoreContext_NoFloatRestore) + + /* record that the incoming context "owns" the non-integer registers */ + + movl %ecx, __tNANO_current_fp_OFFSET (%eax) + + + /* + * Branch point when none of the non-integer registers need to be + * swapped either due to a) the incoming context does not + * USE_FP | USE_SSE, or b) the incoming context is the same as + * the last context that utilized the non-integer registers. + */ + +BRANCH_LABEL(restoreContext_NoFloatSwap) + +#ifdef CONFIG_AUTOMATIC_FP_ENABLING + /* + * Leave CR0[TS] clear if incoming context utilizes "floating point" + * instructions + */ + + testl $USE_FP, __tCCS_flags_OFFSET (%ecx) + jne CROHandlingDone + + /* + * The incoming context does NOT currently utilize "floating point" + * instructions, so set CR0[TS] to ensure the "device not available" + * exception occurs on the first attempt to access a x87 FPU, MMX, + * or XMM register. + */ + + movl %cr0, %edx + orl $0x8, %edx + movl %edx, %cr0 + +BRANCH_LABEL(CROHandlingDone) + +#endif /* CONFIG_AUTOMATIC_FP_ENABLING */ +#endif /* CONFIG_FP_SHARING */ + + + + + /* update _NanoKernel.current to reflect incoming context */ + + movl %ecx, __tNANO_current_OFFSET (%eax) + + /* recover task/fiber stack pointer from tCCS */ + + movl __tCCS_coopReg_OFFSET + __tCoopReg_esp_OFFSET (%ecx), %esp + + + /* load return value from a possible fiberRtnValueSet() */ + + popl %eax + + /* pop the non-volatile registers from the stack */ + + popl %ebp + popl %ebx + popl %esi + popl %edi + + /* + * For a non-preemptive context switch, it is checked that the volatile + * integer registers have the following values: + * + * 1. ECX - points to the task's own CCS structure. + * 2. EDX - contains the flags field of the task's own CCS structure. + * 3. EAX - may contain one of the two values: + * (a) the return value for _Swap() that was set up by a + * call to fiberRtnValueSet() + * (b) same value as EBX, which is non-volatile + */ + + /* Utilize the 'eflags' parameter to _Swap() */ + + pushl 4(%esp) +#ifdef CONFIG_INT_LATENCY_BENCHMARK + testl $0x200, (%esp) + jz skipIntLatencyStop + + /* save %eax since it used as the return value for _Swap */ + pushl %eax + /* interrupts are being reenabled, stop accumulating time */ + call _IntLatencyStop + /* restore _Swap's %eax */ + popl %eax + +BRANCH_LABEL(skipIntLatencyStop) +#endif + popfl + ret + diff --git a/arch/x86/core/unaligned.s b/arch/x86/core/unaligned.s new file mode 100644 index 00000000000..cc6bcec924c --- /dev/null +++ b/arch/x86/core/unaligned.s @@ -0,0 +1,123 @@ +/* unaligned.s - utility routines to perform unaligned reads/writes */ + +/* + * Copyright (c) 2011-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This module contains utilities to perform unaligned reads/writes from/to a +32-bit quantity. Some memory subsystems to not support the IA-32 byte +enable lines, and thus accessing an unaligned 32-bit quantity is +performed byte-by-byte. +*/ + +#define _ASMLANGUAGE + +#ifdef CONFIG_UNALIGNED_WRITE_UNSUPPORTED + +#include + + /* exports (internal APIs) */ + + GTEXT(_Unaligned32Write) + GTEXT(_Unaligned32Read) + +/******************************************************************************* +* +* _Unaligned32Write - perform an unaligned 32-bit write operation +* +* This function is used during the interrupt and exception stub code +* synthesis step when writing out the 32-bit relative jmp/branch +* offsets. +* +* Generally, the 32-bit offsets are located at an odd memory address. For +* target hardware that don't fully (or properly) decode the byte enable +* lines from the IA-32 processor, this function shall be utilized to write out +* the data byte-by-byte. +* +* The BSP specific configuration option CONFIG_UNALIGNED_WRITE_UNSUPPORTED +* shall be defined when the kernel is built for target hardware that cannot +* support unaligned double word (32-bit) write operations. +* +* C function prototype: +* +* void _Unaligned32Write +* ( +* unsigned int * ptr, +* unsigned int val +* ); +*/ + +SECTION_FUNC(TEXT, _Unaligned32Write) + movl 0x4(%esp), %edx /* fetch ptr argument */ + movl 0x8(%esp), %eax /* fetch val argument */ + movb %al, (%edx) + movb %ah, 1(%edx) + shrl $0x10, %eax + movb %al, 2(%edx) + movb %ah, 3(%edx) + ret + + +/******************************************************************************* +* +* _Unaligned32Read - perform an unaligned 32-bit read operation +* +* This function is used during the interrupt and exception stub code +* synthesis step when reading the 32-bit relative jmp/branch +* offsets. +* +* Generally, the 32-bit offsets are located at an odd memory address. For +* target hardware that don't fully (or properly) decode the byte enable +* lines from the IA-32 processor, this function shall be utilized to read +* the data byte-by-byte. +* +* The BSP specific configuration option CONFIG_UNALIGNED_WRITE_UNSUPPORTED +* shall be defined when the kernel is built for target hardware that cannot +* support unaligned double word (32-bit) write operations. +* +* C function prototype: +* +* unsigned int _Unaligned32Read +* ( +* unsigned int * ptr +* ); +*/ + +SECTION_FUNC(TEXT, _Unaligned32Read) + movl 0x4(%esp), %edx /* fetch ptr argument */ + movb 3(%edx), %ah + movb 2(%edx), %al + shll $0x10, %eax + movb 1(%edx), %ah + movb (%edx), %al + ret + +#endif /* CONFIG_UNALIGNED_WRITE_UNSUPPORTED */ diff --git a/arch/x86/defs.objs b/arch/x86/defs.objs new file mode 100644 index 00000000000..482412968d7 --- /dev/null +++ b/arch/x86/defs.objs @@ -0,0 +1,71 @@ +# defs.objs - build system + +# +# Copyright (c) 2015 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors +# may be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. +# + +nkernel_BASE = ${vKSRC_DIR}/kernel/arch/ + +nkernel_INCLUDE_DIR = $(strip \ + ${vBASE}/arch/${vARCH}/include \ + ${vBASE}/kernel/nanokernel/include \ + ${vBASE}/kernel/microkernel/include \ +) + +nkernel_PATH = $(strip \ + ${vBASE}/arch/${vARCH}/core \ + ${vBASE}/kernel/nanokernel/core \ +) + +nkernel_PATH_y = $(strip \ + ${vBASE}/arch/${vARCH}/task \ + ${vBASE}/kernel/nanokernel/task \ +) + +nkernel_PATH += ${nkernel_PATH_${CONFIG_MICROKERNEL}} + +nkernel_SRC := +ifeq (${CONFIG_NANOKERNEL},y) + nkernel_SRC += $(strip \ + ${vBASE}/kernel/common/version.c \ + ${vBASE}/misc/printk.c \ + ) + ifeq ($(CONFIG_ENHANCED_SECURITY),y) + nkernel_SRC += $(strip \ + ${vBASE}/kernel/common/string_s.c \ + ) + endif +endif + +nkernel_SRC += $(foreach path,${nkernel_PATH},$(wildcard ${path}/*.$c)) +nkernel_SRC += $(foreach path,${nkernel_PATH},$(wildcard ${path}/*.$s)) + +nkernel_SRC += ${vKLIB_DIR}/configs.$c + +KLIBS += nkernel diff --git a/arch/x86/generic_pc/board.h b/arch/x86/generic_pc/board.h new file mode 100644 index 00000000000..4d882f977ff --- /dev/null +++ b/arch/x86/generic_pc/board.h @@ -0,0 +1,386 @@ +/* board.h - board configuration macros for the 'generic_pc' BSP */ + +/* + * Copyright (c) 2010-2015, Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This header file is used to specify and describe board-level aspects for +the 'generic_pc' BSP. +*/ + +#ifndef __INCboardh +#define __INCboardh + +#include + +#ifndef _ASMLANGUAGE +#include +#endif + +#ifdef CONFIG_IOAPIC +#include +#ifdef CONFIG_SERIAL_INTERRUPT_LEVEL +#ifdef CONFIG_SERIAL_INTERRUPT_LOW +#define UART_IOAPIC_FLAGS (IOAPIC_LEVEL | IOAPIC_LOW) +#else +#define UART_IOAPIC_FLAGS (IOAPIC_LEVEL) +#endif +#else /* edge triggered interrupt */ +#ifdef CONFIG_SERIAL_INTERRUPT_LOW +/* generate interrupt on falling edge */ +#define UART_IOAPIC_FLAGS (IOAPIC_LOW) +#else +/* generate interrupt on raising edge */ +#define UART_IOAPIC_FLAGS (0) +#endif +#endif +#endif + +/* programmable interrupt controller info (pair of cascaded 8259A devices) */ + +#define PIC_MASTER_BASE_ADRS 0x20 +#define PIC_SLAVE_BASE_ADRS 0xa0 +#define PIC_MASTER_STRAY_INT_LVL 0x07 /* master PIC stray IRQ */ +#define PIC_SLAVE_STRAY_INT_LVL 0x0f /* slave PIC stray IRQ */ +#define PIC_MAX_INT_LVL 0x0f /* max interrupt level in PIC */ +#define PIC_REG_ADDR_INTERVAL 1 +#define INT_VEC_IRQ0 0x20 /* vector number for PIC IRQ0 */ +#define N_PIC_IRQS 16 /* number of PIC IRQs */ + +/* + * IO APIC (IOAPIC) device information (Intel ioapic) + */ +#define IOAPIC_NUM_RTES 24 /* Number of IRQs = 24 */ + +#define IOAPIC_BASE_ADRS_PHYS 0xFEC00000 /* base physical address */ +#define IOAPIC_SIZE KB(4) + +#define IOAPIC_BASE_ADRS IOAPIC_BASE_ADRS_PHYS + +/* + * Local APIC (LOAPIC) device information (Intel loapic) + */ +#define LOAPIC_BASE_ADRS_PHYS 0xFEE00000 /* base physical address */ +#define LOAPIC_SIZE KB(4) + +#define LOAPIC_BASE_ADRS LOAPIC_BASE_ADRS_PHYS + +/* local APIC timer definitions */ +#define LOAPIC_TIMER_IRQ IOAPIC_NUM_RTES +#define LOAPIC_TIMER_INT_PRI 2 +#define LOAPIC_VEC_BASE(x) (x + 32 + IOAPIC_NUM_RTES) +#define LOAPIC_TIMER_VEC LOAPIC_VEC_BASE(0) + +/* serial port (aka COM port) information */ + +#define COM1_BASE_ADRS 0x3f8 +#define COM1_INT_LVL 0x04 /* COM1 connected to IRQ4 */ +#define COM1_INT_VEC (INT_VEC_IRQ0 + COM1_INT_LVL) +#define COM1_INT_PRI 3 /* not honoured with 8259 PIC */ +#define COM1_BAUD_RATE 115200 + +#define COM2_BASE_ADRS 0x2f8 +#define COM2_INT_LVL 0x03 /* COM2 connected to IRQ3 */ +#define COM2_INT_VEC (INT_VEC_IRQ0 + COM2_INT_LVL) +#define COM2_INT_PRI 3 /* not honoured with 8259 PIC */ +#define COM2_BAUD_RATE 115200 + +#define UART_REG_ADDR_INTERVAL 1 /* address diff of adjacent regs. */ +#define UART_XTAL_FREQ 1843200 + +/* uart configuration settings */ + +/* Generic definitions */ +#define CONFIG_UART_NUM_SYSTEM_PORTS 2 +#define CONFIG_UART_NUM_EXTRA_PORTS 0 +#define CONFIG_UART_BAUDRATE COM1_BAUD_RATE +#define CONFIG_UART_NUM_PORTS \ + (CONFIG_UART_NUM_SYSTEM_PORTS + CONFIG_UART_NUM_EXTRA_PORTS) + +/* Console definitions */ +#define CONFIG_UART_CONSOLE_INDEX 0 +#define CONFIG_UART_CONSOLE_REGS COM1_BASE_ADRS +#define CONFIG_UART_CONSOLE_IRQ COM1_INT_LVL +#define CONFIG_UART_CONSOLE_INT_PRI COM1_INT_PRI + +/* + * Programmable interval timer (PIT) device information (Intel i8253) + * + * The PIT_INT_VEC macro is also used when using the Wind River + * Hypervisor "timerTick" service, whereas the PIT_INT_LVL is not. + */ +#define PIT_INT_VEC INT_VEC_IRQ0 /* PIT interrupt vector */ +#define PIT_INT_LVL 0x00 /* PIT connected to IRQ0 */ +#define PIT_INT_PRI 2 /* not honoured with 8259 PIC */ +#define PIT_BASE_ADRS 0x40 +#define PIT_REG_ADDR_INTERVAL 1 + +#ifndef _ASMLANGUAGE +/* + * The parameter is deliberately ignored. For this BSP, the macro just has + * to make sure that unique vector numbers are generated. + */ +#define SYS_INT_REGISTER(s, irq, pri) \ + NANO_CPU_INT_REGISTER(s, INT_VEC_IRQ0 + (irq), 0) +#endif + +/* Start of the 4 MB virtual address space */ +#define VIRT_ADDR_START 0x00000000 + +#ifndef _ASMLANGUAGE +/* + * Device drivers utilize the macros PLB_BYTE_REG_WRITE() and + * PLB_BYTE_REG_READ() to access byte-wide registers on the processor + * local bus (PLB), as opposed to a PCI bus, for example. Boards are + * expected to provide implementations of these macros. + */ + +#define PLB_BYTE_REG_WRITE(data, address) outByte(data, (unsigned int)address) +#define PLB_BYTE_REG_READ(address) inByte((unsigned int)address) + +/******************************************************************************* +* +* outByte - output a byte to an IA-32 I/O port +* +* This function issues the 'out' instruction to write a byte to the specified +* I/O port. +* +* RETURNS: N/A +* +* NOMANUAL +*/ + +#if defined(__DCC__) +__asm volatile void outByte(unsigned char data, unsigned int port) +{ + % mem data, port; + !"ax", "dx" movl port, % edx movb data, % al outb % al, % dx +} +#elif defined(__GNUC__) +static inline void outByte(unsigned char data, unsigned int port) +{ + __asm__ volatile("outb %%al, %%dx;\n\t" : : "a"(data), "d"(port)); +} +#endif + +/******************************************************************************* +* +* inByte - input a byte from an IA-32 I/O port +* +* This function issues the 'in' instruction to read a byte from the specified +* I/O port. +* +* RETURNS: the byte read from the specified I/O port +* +* NOMANUAL +*/ + +#if defined(__DCC__) +__asm volatile unsigned char inByte(unsigned int port) +{ + % mem port; + !"ax", "dx" movl port, % edx inb % dx, % al +} +#elif defined(__GNUC__) +static inline unsigned char inByte(unsigned int port) +{ + char retByte; + + __asm__ volatile("inb %%dx, %%al;\n\t" : "=a"(retByte) : "d"(port)); + return retByte; +} +#endif + +/* + * Device drivers utilize the macros PLB_WORD_REG_WRITE() and + * PLB_WORD_REG_READ() to access shortword-wide registers on the processor + * local bus (PLB), as opposed to a PCI bus, for example. Boards are + * expected to provide implementations of these macros. + */ + +#define PLB_WORD_REG_WRITE(data, address) outWord(data, (unsigned int)address) +#define PLB_WORD_REG_READ(address) inWord((unsigned int)address) + +/******************************************************************************* +* +* outWord - output a word to an IA-32 I/O port +* +* This function issues the 'out' instruction to write a word to the +* specified I/O port. +* +* RETURNS: N/A +* +* NOMANUAL +*/ + +#if defined(__DCC__) +__asm volatile void outWord(unsigned short data, unsigned int port) +{ + % mem data, port; + !"ax", "dx" movl port, % edx movw data, % ax outw % ax, % dx +} +#elif defined(__GNUC__) +static inline void outWord(unsigned short data, unsigned int port) +{ + __asm__ volatile("outw %%ax, %%dx;\n\t" : : "a"(data), "d"(port)); +} +#endif + +/******************************************************************************* +* +* inWord - input a word from an IA-32 I/O port +* +* This function issues the 'in' instruction to read a word from the +* specified I/O port. +* +* RETURNS: the word read from the specified I/O port +* +* NOMANUAL +*/ + +#if defined(__DCC__) +__asm volatile unsigned short inWord(unsigned int port) +{ + % mem port; + !"ax", "dx" movl port, % edx inw % dx, % ax +} +#elif defined(__GNUC__) +static inline unsigned short inWord(unsigned int port) +{ + unsigned short retWord; + + __asm__ volatile("inw %%dx, %%ax;\n\t" : "=a"(retWord) : "d"(port)); + return retWord; +} +#endif + +/* + * Device drivers utilize the macros PLB_LONG_REG_WRITE() and + * PLB_LONG_REG_READ() to access longword-wide registers on the processor + * local bus (PLB), as opposed to a PCI bus, for example. Boards are + * expected to provide implementations of these macros. + */ + +#define PLB_LONG_REG_WRITE(data, address) outLong(data, (unsigned int)address) +#define PLB_LONG_REG_READ(address) inLong((unsigned int)address) + +/******************************************************************************* +* +* outLong - output a long word to an IA-32 I/O port +* +* This function issues the 'out' instruction to write a long word to the +* specified I/O port. +* +* RETURNS: N/A +* +* NOMANUAL +*/ + +#if defined(__DCC__) +__asm volatile void outLong(unsigned int data, unsigned int port) +{ + % mem data, port; + !"ax", "dx" movl port, % edx movl data, % eax outl % eax, % dx +} +#elif defined(__GNUC__) +static inline void outLong(unsigned int data, unsigned int port) +{ + __asm__ volatile("outl %%eax, %%dx;\n\t" : : "a"(data), "d"(port)); +} +#endif + +/******************************************************************************* +* +* inLong - input a long word from an IA-32 I/O port +* +* This function issues the 'in' instruction to read a long word from the +* specified I/O port. +* +* RETURNS: the long read from the specified I/O port +* +* NOMANUAL +*/ + +#if defined(__DCC__) +__asm volatile unsigned long inLong(unsigned int port) +{ + % mem port; + !"ax", "dx" movl port, % edx inl % dx, % eax +} +#elif defined(__GNUC__) +static inline unsigned long inLong(unsigned int port) +{ + unsigned long retLong; + + __asm__ volatile("inl %%dx, %%eax;\n\t" : "=a"(retLong) : "d"(port)); + return retLong; +} +#endif + +extern void _SysIntVecProgram(unsigned int vector, unsigned int); +#else /* _ASMLANGUAGE */ + +/* + * Assembler macros for PLB_BYTE/WORD/LONG_WRITE/READ + * + * Note that these macros trash the contents of EAX and EDX. + * The read macros return the contents in the EAX register. + */ +#define PLB_BYTE_REG_WRITE(data, address) \ + movb $data, % al; \ + movl $address, % edx; \ + outb % al, % dx + +#define PLB_BYTE_REG_READ(address) \ + movl $address, % edx; \ + inb % dx, % al + +#define PLB_WORD_REG_WRITE(data, address) \ + movw $data, % ax; \ + movl $address, % edx; \ + outw % ax, % dx + +#define PLB_WORD_REG_READ(address) \ + movl $address, % edx; \ + inw % dx, % ax + +#define PLB_LONG_REG_WRITE(data, address) \ + movl $data, % ax; \ + movl $address, % edx; \ + outl % eax, % dx + +#define PLB_LONG_REG_READ(address) \ + movl $address, % edx; \ + inl % dx, % eax + +#endif /* !_ASMLANGUAGE */ + +#endif /* __INCboardh */ diff --git a/arch/x86/generic_pc/defs.objs b/arch/x86/generic_pc/defs.objs new file mode 100644 index 00000000000..6f6e8a3b751 --- /dev/null +++ b/arch/x86/generic_pc/defs.objs @@ -0,0 +1,115 @@ +# defs.objs - build system + +# +# Copyright (c) 2015 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors +# may be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. +# + +bsp_INCLUDE_DIR = $(strip \ + ${vBASE}/kernel/common/bsp \ + ${vBASE}/include/bsp \ + ${vBASE}/include \ + ${vBASE}/drivers \ + ${vBASE}/arch/${vARCH} \ + ${vBSP_BASE_DIR}/${vBSP} \ +) + +bsp_kernel_SRC = $(strip \ + arch/${vARCH}/bsp/crt0.s \ + arch/${vARCH}/bsp/cache.c \ + arch/${vARCH}/bsp/cache_s.s \ + arch/${vARCH}/bsp/rand32.c \ + kernel/common/bsp/init.c \ + kernel/common/bsp/ctors.c \ + arch/${vARCH}/bsp/sysFatalErrorHandler.c \ +) + +bsp_drivers_SRC = $(strip \ + drivers/serial/ns16550.c \ + drivers/console/uart_console.c \ +) + +ifeq (${CONFIG_MICROKERNEL},y) + bsp_kernel_SRC += $(strip \ + ) + bsp_drivers_SRC += $(strip \ + ) +endif + + +# drivers section +# timer drivers +bsp_drivers_SRC_PIT_y = drivers/timer/i8253.c +bsp_drivers_SRC_LOAPIC_TIMER_y = arch/${vARCH}/timer/loApicTimer.c +bsp_drivers_SRC_HPET_y = arch/${vARCH}/timer/hpet.c + +# interrupt controllers +# variable indicates PCI initialization +bsp_PIC_INIT = ${CONFIG_PIC}${CONFIG_SHUTOFF_PIC} + +# variable indicates processing PIC interrupts +bsp_PIC_INTERRUPTS = ${CONFIG_PIC} + +bsp_drivers_SRC_LOAPIC_y = arch/${vARCH}/interrupt_controller/loApicIntr.c +bsp_drivers_SRC_IOAPIC_y = arch/${vARCH}/interrupt_controller/ioApicIntr.c +bsp_drivers_SRC_PIC_y = drivers/interrupt_controller/i8259.c +bsp_kernel_SRC_PICBOI_y = arch/${vARCH}/bsp/i8259Boi.s + +bsp_kernel_SRC += $(strip \ + ${bsp_kernel_SRC_PICBOI_${bsp_PIC_INTERRUPTS}} \ +) + +bsp_drivers_SRC += $(strip \ + ${bsp_drivers_SRC_PIT_${CONFIG_PIT}} \ + ${bsp_drivers_SRC_LOAPIC_TIMER_${CONFIG_LOAPIC_TIMER}} \ + ${bsp_drivers_SRC_HPET_${CONFIG_HPET}} \ + ${bsp_drivers_SRC_LOAPIC_${CONFIG_LOAPIC}} \ + ${bsp_drivers_SRC_IOAPIC_${CONFIG_IOAPIC}} \ + ${bsp_drivers_SRC_PIC_${bsp_PIC_INIT}} \ +) + +# BSP specific section + +bsp_SRC_LOAPIC_y = arch/${vARCH}/bsp/systemApic.c + +bsp_SRC_PIC_y = arch/${vARCH}/bsp/systemPic.c + +bsp_platform_SRC = $(strip \ + ${bsp_SRC_LOAPIC_${CONFIG_LOAPIC}} \ + ${bsp_SRC_PIC_${CONFIG_PIC}} \ + arch/${vARCH}/bsp/driver_static_irq_stubs.s \ +) + +bsp_SRC = $(strip \ + ${vBSP_BASE_DIR}/${vBSP}/system.c \ + $(addprefix ${vBASE}/,${bsp_kernel_SRC}) \ + $(addprefix ${vBASE}/,${bsp_drivers_SRC}) \ + $(addprefix ${vBASE}/,${bsp_platform_SRC}) \ +) + +KLIBS += bsp diff --git a/arch/x86/generic_pc/linker.cmd b/arch/x86/generic_pc/linker.cmd new file mode 100644 index 00000000000..fe158c8240e --- /dev/null +++ b/arch/x86/generic_pc/linker.cmd @@ -0,0 +1,75 @@ +/* linker.cmd - Linker command/script file */ + +/* + * Copyright (c) 2011-2014, Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This is the linker script for both standard images and XIP images. +*/ + +#include + +/* physical address where the kernel is loaded */ +#define PHYS_LOAD_ADDR CONFIG_PHYS_LOAD_ADDR + +/* physical address of RAM */ +#ifdef CONFIG_XIP + #define PHYS_RAM_ADDR 0x00400000 +#else /* !CONFIG_XIP */ + #define PHYS_RAM_ADDR PHYS_LOAD_ADDR +#endif /* CONFIG_XIP */ + +#define KENTRY __start + +MEMORY + { +#ifdef CONFIG_XIP + ROM (rx) : ORIGIN = PHYS_LOAD_ADDR, LENGTH = 72K + RAM (wx) : ORIGIN = PHYS_RAM_ADDR, LENGTH = 128K +#else /* !CONFIG_XIP */ + RAM (wx) : ORIGIN = PHYS_LOAD_ADDR, LENGTH = 192K +#endif /* CONFIG_XIP */ + + /* + * It doesn't matter where this region goes as it is stripped from the + * final ELF image. The address doesn't even have to be valid on the + * target. However, it shouldn't overlap any other regions. + */ + + IDT_LIST : ORIGIN = 2K, LENGTH = 2K + } + +#include + +/* start adding bsp specific linker sections here */ + +/* no sections should appear after linker-epilog.h */ +#include diff --git a/arch/x86/generic_pc/system.c b/arch/x86/generic_pc/system.c new file mode 100644 index 00000000000..b2718492053 --- /dev/null +++ b/arch/x86/generic_pc/system.c @@ -0,0 +1,167 @@ +/* system.c - system/hardware module for the generic_pc BSP */ + +/* + * Copyright (c) 2011-2015, Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This module provides routines to initialize and support board-level hardware +for the generic_pc BSP. +*/ + +#include +#include +#include +#include "board.h" +#include +#include + +#if defined(CONFIG_PIC) || defined(CONFIG_SHUTOFF_PIC) +#define picInit() _i8259_init() +#else +#define picInit() \ + do {/* nothing */ \ + } while ((0)) +#endif /* CONFIG_PIC */ + +#ifdef CONFIG_LOAPIC +#include +static inline void loapicInit(void) +{ + _loapic_init(); +} +#else +#define loapicInit() \ + do {/* nothing */ \ + } while ((0)) +#endif /* CONFIG_LOAPIC */ + +#ifdef CONFIG_IOAPIC +#include +static inline void ioapicInit(void) +{ + _ioapic_init(); +} + +#define uartIrqProg(irq) \ + _ioapic_irq_set((irq), (irq) + INT_VEC_IRQ0, UART_IOAPIC_FLAGS) +#else +#define ioapicInit(mask) \ + do {/* nothing */ \ + } while ((0)) +#define uartIrqProg(irq) \ + do {/* nothing */ \ + } while ((0)) +#endif /* CONFIG_IOAPIC */ + +#if defined(CONFIG_PRINTK) || defined(CONFIG_STDOUT_CONSOLE) +#define DO_CONSOLE_INIT +#endif + + +#ifdef DO_CONSOLE_INIT + +/******************************************************************************* +* +* uartGenericInfoInit - initialize initialization information for one UART +* +* RETURNS: N/A +* +*/ + +static void uartGenericInfoInit(struct uart_init_info *p_info) +{ + p_info->options = 0; + p_info->sys_clk_freq = UART_XTAL_FREQ; + p_info->baud_rate = CONFIG_UART_BAUDRATE; +} + +#endif /* DO_CONSOLE_INIT */ + +#if defined(DO_CONSOLE_INIT) + +/******************************************************************************* +* +* consoleInit - initialize target-only console +* +* Only used for debugging. +* +* RETURNS: N/A +* +*/ + +#include + +static void consoleInit(void) +{ + struct uart_init_info info; + + uartGenericInfoInit(&info); + /* + * Need type casting to avoid compiler warnings about assigning a + * pointer to a smaller integer. We know the size is right... + */ + info.regs = (uint16_t)((unsigned long)CONFIG_UART_CONSOLE_REGS); + info.irq = CONFIG_UART_CONSOLE_IRQ; + info.int_pri = CONFIG_UART_CONSOLE_INT_PRI; + uart_init(CONFIG_UART_CONSOLE_INDEX, &info); + uartConsoleInit(); +} + +#else +#define consoleInit() \ + do {/* nothing */ \ + } while ((0)) +#endif /* DO_CONSOLE_INIT */ + +/******************************************************************************* +* +* _InitHardware - perform basic hardware initialization +* +* Initialize the Intel 8259A interrupt controller device driver and the +* Intel 8250 UART device driver. +* Also initialize the timer device driver, if required. +* +* RETURNS: N/A +*/ + +void _InitHardware(void) +{ + picInit(); /* NOP if not needed */ + loapicInit(); /* NOP if not needed */ + + /* + * IOAPIC is initialized with empty interrupt list + * If there is a device connected to IOAPIC, the initialization + * has to be changed to _IoApicInit (1 << DEV1_IRQ | 1 << DEV2_IRQ) + */ + ioapicInit(); /* NOP if not needed */ + consoleInit(); /* NOP if not needed */ +} diff --git a/arch/x86/include/advidle.h b/arch/x86/include/advidle.h new file mode 100644 index 00000000000..83eca1f11b7 --- /dev/null +++ b/arch/x86/include/advidle.h @@ -0,0 +1,91 @@ +/* advidle.h - header file for custom advanced idle manager */ + +/* + * Copyright (c) 2012-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ +/* +DESCRIPTION +This header file specifies the custom advanced idle management interface. +All of the APIs declared here must be supplied by the custom advanced idle +management system, namely the _AdvIdleCheckSleep(), _AdvIdleFunc() +and _AdvIdleStart() functions. + */ + +#ifndef __INCadvidle +#define __INCadvidle + +#ifdef CONFIG_ADVANCED_IDLE + +/* + * _AdvIdleCheckSleep - determine if advanced sleep has occurred + * + * This routine checks if the system is recovering from advanced + * sleep or cold booting. + * + * RETURNS: 0 if the system is cold booting on a non-zero + * value if the system is recovering from advanced sleep. + */ + +extern int _AdvIdleCheckSleep(void); + +/* + * _AdvIdleStart - continue kernel start-up or awaken kernel from sleep + * + * This routine checks if the system is recovering from advanced sleep and + * either continues the kernel's cold boot sequence at _Cstart or resumes + * kernel operation at the point it went to sleep; in the latter case, control + * passes to the _AdvIdleFunc() that put the system to sleep, which then + * finishes executing. + * + * RETURNS: does not return to caller + */ + +extern void _AdvIdleStart( + void (*_Cstart)(void), /* addr of VxMicro _Cstart function */ + void *_Gdt, /* addr of global descriptor table in RAM */ + void *_GlobalTss /* addr of VxMicro TSS descriptor */ + ); + +/* + * _AdvIdleFunc - perform advanced sleep + * + * This routine checks if the upcoming kernel idle interval is sufficient to + * justify entering advanced sleep mode. If it is, the routine puts the system + * to sleep and then later allows it to resume processing; if not, the routine + * returns immediately without sleeping. + * + * RETURNS: non-zero if advanced sleep occurred; otherwise zero + */ + +extern int _AdvIdleFunc(int32_t ticks /* upcoming kernel idle time */ + ); + +#endif /* CONFIG_ADVANCED_IDLE */ + +#endif /* __INCadvidle */ diff --git a/arch/x86/include/asmPrv.h b/arch/x86/include/asmPrv.h new file mode 100644 index 00000000000..bdbdb1ee0ca --- /dev/null +++ b/arch/x86/include/asmPrv.h @@ -0,0 +1,103 @@ +/* asmPrv.h - Private x86 assembler header */ + +/* + * Copyright (c) 2012-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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 __INCsysX86AsmPrvh +#define __INCsysX86AsmPrvh + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Macro to generate name of stub from name of handler */ +#define MK_STUB_NAME(h) h##Stub + +/* + * Assmembler version of the NANO_CPU_INT_REGISTER macro. + * See arch.h for details + */ +#define NANO_CPU_INT_REGISTER_ASM(handler, vector, dpl) \ + .section ".intList"; \ + MK_ISR_NAME(handler) : .long MK_STUB_NAME(handler); \ + .long vector; \ + .long dpl; + +#define NANO_CPU_EXC_CONNECT_CODE(h) \ + call _ExcEnt; \ + call h; \ + jmp _ExcExit; + +#define NANO_CPU_EXC_CONNECT_NO_ERR_CODE(h) \ + pushl $0; \ + call _ExcEnt; \ + call h; \ + jmp _ExcExit; + +/******************************************************************************* +* +* NANO_CPU_EXC_CONNECT - to generate and register an exception stub +* +* Generates an exception stub for the handler, . It is registered +* on the vector given by with the privilege level ; should always +* be 0. +* +* Use this version of the macro if the processor pushes an error code for the +* given exception. +*/ + +#define NANO_CPU_EXC_CONNECT(h, v, d) \ + NANO_CPU_INT_REGISTER_ASM(h, v, d) GTEXT(MK_STUB_NAME(h)); \ + SECTION_FUNC(TEXT, MK_STUB_NAME(h)) NANO_CPU_EXC_CONNECT_CODE(h) + +/******************************************************************************* +* +* NANO_CPU_EXC_CONNECT_NO_ERR - to generate and register an exception stub +* +* Generates an exception stub for the handler, . It is registered +* on the vector given by with the privilege level ; should always +* be 0. +* +* Use this version of the macro if the processor doesn't push an error code for +* the given exception. The created stub pushes a dummy value of 0 to keep the +* exception stack frame the same. + */ +#define NANO_CPU_EXC_CONNECT_NO_ERR(h, v, d) \ + NANO_CPU_INT_REGISTER_ASM(h, v, d) GTEXT(MK_STUB_NAME(h)); \ + SECTION_FUNC(TEXT, MK_STUB_NAME(h)) \ + NANO_CPU_EXC_CONNECT_NO_ERR_CODE(h) + +#ifdef __cplusplus +} +#endif + +#endif /* __INCsysX86AsmPrvh */ diff --git a/arch/x86/include/gdt.h b/arch/x86/include/gdt.h new file mode 100644 index 00000000000..31ea2cfaf41 --- /dev/null +++ b/arch/x86/include/gdt.h @@ -0,0 +1,84 @@ +/* gdt.h - IA-32 Global Descriptor Table (GDT) definitions */ + +/* + * Copyright (c) 2011-2012, 2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This file provides definitions for the Global Descriptor Table (GDT) for the +IA-32 architecture. +*/ + +#ifndef _GDT_H +#define _GDT_H + +/* includes */ + +#include + +#ifndef _ASMLANGUAGE + +#include +#include + +/* typedefs */ + +/* a generic GDT entry structure definition */ + +typedef struct s_gdtDesc { + uint16_t limitLowerWord; /* bits 0:15 of segment limit */ + uint16_t baseAdrsLowerWord; /* bits 0:15 of segment base address */ + uint8_t baseAdrsMidByte; /* bits 16:23 of segment base address */ + uint8_t descType; /* descriptor type fields */ + uint8_t limitUpperByte; /* bits 16:19 of limit + more type fields */ + uint8_t baseAdrsUpperByte; /* bits 24:31 of segment base address */ +} tGdtDesc; + +/* + * structure definition for the GDT "header" + * (does not include the GDT entries). + * The structure is packed to force the structure to appear "as is". + * Unfortunately, this appears to remove any alignment restrictions + * so the aligned attribute is used. + */ + +typedef struct PACK_STRUCT s_gdtHeader +{ + uint16_t limit; /* GDT limit */ + tGdtDesc *pEntries; /* pointer to the GDT entries */ +} tGdtHeader __attribute__((aligned(4))); + +/* externs */ + +extern tGdtHeader _Gdt; /* GDT is implemented in Intel/core/gdt.c */ + + +#endif /* _ASMLANGUAGE */ +#endif /* _GDT_H */ diff --git a/arch/x86/include/idtEnt.h b/arch/x86/include/idtEnt.h new file mode 100644 index 00000000000..b5bece9b8f5 --- /dev/null +++ b/arch/x86/include/idtEnt.h @@ -0,0 +1 @@ +#include "../../../shared/include/nanokernel/x86/idtEnt.h" diff --git a/arch/x86/include/nanok.h b/arch/x86/include/nanok.h new file mode 100644 index 00000000000..b3107e2a7ef --- /dev/null +++ b/arch/x86/include/nanok.h @@ -0,0 +1,967 @@ +/* nanok.h - private nanokernel definitions (IA-32) */ + +/* + * Copyright (c) 2010-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This file contains private nanokernel structures definitions and various other +definitions for the Intel Architecture 32 bit (IA-32) processor architecture. +The header include/nanokernel.h contains the public nanokernel interface +definitions, with include/arch/nanokernel/x86/arch.h supplying the +IA-32 specific portions of the public nanokernel interface. + +This file is also included by assembly language files which must #define +_ASMLANGUAGE before including this header file. Note that nanokernel assembly +source files obtains structure offset values via "absolute symbols" in the +offsets.o module. +*/ + +#ifndef _NANOK_H +#define _NANOK_H + +/* includes */ + +#include +#include + +#ifndef _ASMLANGUAGE +#include /* public nanokernel API */ +#include /* private IA-32 definitions */ +#include +/* + * This pulls in the code shared with the IDT generator that actually + * constructs an IDT entry. + */ +#include +#endif + +/* increase to 16 bytes (or more?) to support SSE/SSE2 instructions? */ + +#define STACK_ALIGN_SIZE 4 + +/* + * Alignment requirement for the tFpRegSet structure + * + * If support for SSEx extensions is enabled a 16 byte boundary is required, + * since the 'fxsave' and 'fxrstor' instructions require this. In all other + * cases a 4 byte bounday is sufficient. + */ + +#ifdef CONFIG_SSE +#define FP_REG_SET_ALIGN 16 +#else +#define FP_REG_SET_ALIGN 4 +#endif /* CONFIG_SSE */ + +/* + * Alignment requirement for the CCS structure + * + * The CCS must be aligned to the same boundary as that used by + * the FP register set that appears at the end of the structure. + * This applies even for contexts that don't initially use floating point, + * since it is possible to enable floating point support later on. + */ + +#define CCS_ALIGN FP_REG_SET_ALIGN + +/* + * Bitmask definitions for the tCCS->flags bit field + * + * The USE_FP flag bit will be set whenever a context uses any non-integer + * capability, whether it's just the x87 FPU capability, SSE instructions, or + * a combination of both. The USE_SSE flag bit will only be set if a context + * uses SSE instructions. + * + * Note: Any change to the definitions USE_FP and USE_SSE must also be made to + * nanokernel/x86/arch.h. + */ + +#define FIBER 0 +#define TASK 0x1 /* 1 = task context, 0 = fiber context */ +#define INT_ACTIVE 0x2 /* 1 = context is executing interrupt handler */ +#define EXC_ACTIVE 0x4 /* 1 = context is executing exception handler */ +#define USE_FP 0x10 /* 1 = context uses floating point unit */ +#define USE_SSE 0x20 /* 1 = context uses SSEx instructions */ +#define PREEMPTIBLE 0x100 /* 1 = preemptible context */ +#define ESSENTIAL 0x200 /* 1 = system context that must not abort */ +#define NO_METRICS 0x400 /* 1 = _Swap() not to update task metrics */ +#define NO_METRICS_BIT_OFFSET 0xa /* Bit position of NO_METRICS */ + +#define INT_OR_EXC_MASK (INT_ACTIVE | EXC_ACTIVE) + +/* + * Exception/interrupt vector definitions: vectors 20 to 31 are reserved for + * Intel; vectors 32 to 255 are user defined interrupt vectors. + */ + +#define IV_DIVIDE_ERROR 0 +#define IV_DEBUG 1 +#define IV_NON_MASKABLE_INTERRUPT 2 +#define IV_BREAKPOINT 3 +#define IV_OVERFLOW 4 +#define IV_BOUND_RANGE 5 +#define IV_INVALID_OPCODE 6 +#define IV_DEVICE_NOT_AVAILABLE 7 +#define IV_DOUBLE_FAULT 8 +#define IV_COPROC_SEGMENT_OVERRUN 9 +#define IV_INVALID_TSS 10 +#define IV_SEGMENT_NOT_PRESENT 11 +#define IV_STACK_FAULT 12 +#define IV_GENERAL_PROTECTION 13 +#define IV_PAGE_FAULT 14 +#define IV_RESERVED 15 +#define IV_X87_FPU_FP_ERROR 16 +#define IV_ALIGNMENT_CHECK 17 +#define IV_MACHINE_CHECK 18 +#define IV_SIMD_FP 19 +#define IV_INTEL_RESERVED_END 31 + +/* + * Model specific register (MSR) definitions. Use the _MsrRead() and + * _MsrWrite() primitives to read/write the MSRs. Only the so-called + * "Architectural MSRs" are listed, i.e. the subset of MSRs and associated + * bit fields which will not change on future processor generations. + */ + +#define IA32_P5_MC_ADDR_MSR 0x0000 +#define IA32_P5_MC_TYPE_MSR 0x0001 +#define IA32_MONITOR_FILTER_SIZE_MSR 0x0006 +#define IA32_TIME_STAMP_COUNTER_MSR 0x0010 +#define IA32_IA32_PLATFORM_ID_MSR 0x0017 +#define IA32_APIC_BASE_MSR 0x001b +#define IA32_FEATURE_CONTROL_MSR 0x003a +#define IA32_BIOS_SIGN_MSR 0x008b +#define IA32_SMM_MONITOR_CTL_MSR 0x009b +#define IA32_PMC0_MSR 0x00c1 +#define IA32_PMC1_MSR 0x00c2 +#define IA32_PMC2_MSR 0x00c3 +#define IA32_PMC3_MSR 0x00c4 +#define IA32_MPERF_MSR 0x00e7 +#define IA32_APERF_MSR 0x00e8 +#define IA32_MTRRCAP_MSR 0x00fe +#define IA32_SYSENTER_CS_MSR 0x0174 +#define IA32_SYSENTER_ESP_MSR 0x0175 +#define IA32_SYSENTER_EIP_MSR 0x0176 +#define IA32_MCG_CAP_MSR 0x0179 +#define IA32_MCG_STATUS_MSR 0x017a +#define IA32_MCG_CTL_MSR 0x017b +#define IA32_PERFEVTSEL0_MSR 0x0186 +#define IA32_PERFEVTSEL1_MSR 0x0187 +#define IA32_PERFEVTSEL2_MSR 0x0188 +#define IA32_PERFEVTSEL3_MSR 0x0188 +#define IA32_PERF_STATUS_MSR 0x0198 +#define IA32_PERF_CTL_MSR 0x0199 +#define IA32_CLOCK_MODULATION_MSR 0x019a +#define IA32_THERM_INTERRUPT_MSR 0x019b +#define IA32_THERM_STATUS_MSR 0x019c +#define IA32_MISC_ENABLE_MSR 0x01a0 +#define IA32_ENERGY_PERF_BIAS_MSR 0x01b0 +#define IA32_DEBUGCTL_MSR 0x01d9 +#define IA32_SMRR_PHYSBASE_MSR 0x01f2 +#define IA32_SMRR_PHYSMASK_MSR 0x01f3 +#define IA32_PLATFORM_DCA_CAP_MSR 0x01f8 +#define IA32_CPU_DCA_CAP_MSR 0x01f9 +#define IA32_DCA_0_CAP_MSR 0x01fa +#define IA32_MTRR_PHYSBASE0_MSR 0x0200 +#define IA32_MTRR_PHYSMASK0_MSR 0x0201 +#define IA32_MTRR_PHYSBASE1_MSR 0x0202 +#define IA32_MTRR_PHYSMASK1_MSR 0x0203 +#define IA32_MTRR_PHYSBASE2_MSR 0x0204 +#define IA32_MTRR_PHYSMASK2_MSR 0x0205 +#define IA32_MTRR_PHYSBASE3_MSR 0x0206 +#define IA32_MTRR_PHYSMASK3_MSR 0x0207 +#define IA32_MTRR_PHYSBASE4_MSR 0x0208 +#define IA32_MTRR_PHYSMASK4_MSR 0x0209 +#define IA32_MTRR_PHYSBASE5_MSR 0x020a +#define IA32_MTRR_PHYSMASK5_MSR 0x020b +#define IA32_MTRR_PHYSBASE6_MSR 0x020c +#define IA32_MTRR_PHYSMASK6_MSR 0x020d +#define IA32_MTRR_PHYSBASE7_MSR 0x020e +#define IA32_MTRR_PHYSMASK7_MSR 0x020f +#define IA32_MTRR_FIX64K_00000_MSR 0x0250 +#define IA32_MTRR_FIX16K_80000_MSR 0x0258 +#define IA32_MTRR_FIX16K_A0000_MSR 0x0259 +#define IA32_MTRR_FIX4K_C0000_MSR 0x0268 +#define IA32_MTRR_FIX4K_C8000_MSR 0x0269 +#define IA32_MTRR_FIX4K_D0000_MSR 0x026a +#define IA32_MTRR_FIX4K_D8000_MSR 0x026b +#define IA32_MTRR_FIX4K_E0000_MSR 0x026c +#define IA32_MTRR_FIX4K_E8000_MSR 0x026d +#define IA32_MTRR_FIX4K_F0000_MSR 0x026e +#define IA32_MTRR_FIX4K_F8000_MSR 0x026f +#define IA32_PAT_MSR 0x0277 +#define IA32_MC0_CTL2_MSR 0x0280 +#define IA32_MC1_CTL2_MSR 0x0281 +#define IA32_MC2_CTL2_MSR 0x0282 +#define IA32_MC3_CTL2_MSR 0x0283 +#define IA32_MC4_CTL2_MSR 0x0284 +#define IA32_MC5_CTL2_MSR 0x0285 +#define IA32_MC6_CTL2_MSR 0x0286 +#define IA32_MC7_CTL2_MSR 0x0287 +#define IA32_MC8_CTL2_MSR 0x0288 +#define IA32_MC9_CTL2_MSR 0x0289 +#define IA32_MC10_CTL2_MSR 0x028a +#define IA32_MC11_CTL2_MSR 0x028b +#define IA32_MC12_CTL2_MSR 0x028c +#define IA32_MC13_CTL2_MSR 0x028d +#define IA32_MC14_CTL2_MSR 0x028e +#define IA32_MC15_CTL2_MSR 0x028f +#define IA32_MC16_CTL2_MSR 0x0290 +#define IA32_MC17_CTL2_MSR 0x0291 +#define IA32_MC18_CTL2_MSR 0x0292 +#define IA32_MC19_CTL2_MSR 0x0293 +#define IA32_MC20_CTL2_MSR 0x0294 +#define IA32_MC21_CTL2_MSR 0x0295 +#define IA32_MTRR_DEF_TYPE_MSR 0x02ff +#define IA32_FIXED_CTR0_MSR 0x0309 +#define IA32_FIXED_CTR1_MSR 0x030a +#define IA32_FIXED_CTR2_MSR 0x030b +#define IA32_PERF_CAPABILITIES_MSR 0x0345 +#define IA32_FIXED_CTR_CTL_MSR 0x038d +#define IA32_PERF_GLOBAL_STATUS_MSR 0x038e +#define IA32_PERF_GLOBAL_CTRL_MSR 0x038f +#define IA32_PERF_GLOBAL_OVF_CTRL_MSR 0x0390 +#define IA32_PEBS_ENABLE_MSR 0x03f1 +#define IA32_MC0_CTL_MSR 0x0400 +#define IA32_MC0_STATUS 0x0401 +#define IA32_MC0_ADDR_MSR 0x0402 +#define IA32_MC0_MISC_MSR 0x0403 +#define IA32_MC1_CTL_MSR 0x0404 +#define IA32_MC1_STATUS_MSR 0x0405 +#define IA32_MC1_ADDR_MSR 0x0406 +#define IA32_MC1_MISC_MSR 0x0407 +#define IA32_MC2_CTL_MSR 0x0408 +#define IA32_MC2_STATUS_MSR 0x0409 +#define IA32_MC2_ADDR_MSR 0x040a +#define IA32_MC2_MISC_MSR 0x040b +#define IA32_MC3_CTL_MSR 0x040c +#define IA32_MC3_STATUS_MSR 0x040d +#define IA32_MC3_ADDR_MSR 0x040e +#define IA32_MC3_MISC_MSR 0x040f +#define IA32_MC4_CTL_MSR 0x0410 +#define IA32_MC4_STATUS_MSR 0x0411 +#define IA32_MC4_ADDR_MSR 0x0412 +#define IA32_MC4_MISC_MSR 0x0413 +#define IA32_MC5_CTL_MSR 0x0414 +#define IA32_MC5_STATUS_MSR 0x0415 +#define IA32_MC5_ADDR_MSR 0x0416 +#define IA32_MC5_MISC_MSR 0x0417 +#define IA32_MC6_CTL_MSR 0x0418 +#define IA32_MC6_STATUS_MSR 0x0419 +#define IA32_MC6_ADDR_MSR 0x041a +#define IA32_MC6_MISC_MSR 0x041b +#define IA32_MC7_CTL_MSR 0x041c +#define IA32_MC7_STATUS_MSR 0x041d +#define IA32_MC7_ADDR_MSR 0x041e +#define IA32_MC7_MISC_MSR 0x041f +#define IA32_MC8_CTL_MSR 0x0420 +#define IA32_MC8_STATUS_MSR 0x0421 +#define IA32_MC8_ADDR_MSR 0x0422 +#define IA32_MC8_MISC_MSR 0x0423 +#define IA32_MC9_CTL_MSR 0x0424 +#define IA32_MC9_STATUS_MSR 0x0425 +#define IA32_MC9_ADDR_MSR 0x0426 +#define IA32_MC9_MISC_MSR 0x0427 +#define IA32_MC9_CTL_MSR 0x0424 +#define IA32_MC9_STATUS_MSR 0x0425 +#define IA32_MC9_ADDR_MSR 0x0426 +#define IA32_MC9_MISC_MSR 0x0427 +#define IA32_MC9_CTL_MSR 0x0424 +#define IA32_MC9_STATUS_MSR 0x0425 +#define IA32_MC9_ADDR_MSR 0x0426 +#define IA32_MC9_MISC_MSR 0x0427 +#define IA32_MC9_CTL_MSR 0x0424 +#define IA32_MC9_STATUS_MSR 0x0425 +#define IA32_MC9_ADDR_MSR 0x0426 +#define IA32_MC9_MISC_MSR 0x0427 +#define IA32_MC10_CTL_MSR 0x0428 +#define IA32_MC10_STATUS_MSR 0x0429 +#define IA32_MC10_ADDR_MSR 0x042a +#define IA32_MC10_MISC_MSR 0x042b +#define IA32_MC11_CTL_MSR 0x042c +#define IA32_MC11_STATUS_MSR 0x042d +#define IA32_MC11_ADDR_MSR 0x042e +#define IA32_MC11_MISC_MSR 0x042f +#define IA32_MC12_CTL_MSR 0x0430 +#define IA32_MC12_STATUS_MSR 0x0431 +#define IA32_MC12_ADDR_MSR 0x0432 +#define IA32_MC12_MISC_MSR 0x0433 +#define IA32_MC13_CTL_MSR 0x0434 +#define IA32_MC13_STATUS_MSR 0x0435 +#define IA32_MC13_ADDR_MSR 0x0436 +#define IA32_MC13_MISC_MSR 0x0437 +#define IA32_MC14_CTL_MSR 0x0438 +#define IA32_MC14_STATUS_MSR 0x0439 +#define IA32_MC14_ADDR_MSR 0x043a +#define IA32_MC14_MISC_MSR 0x043b +#define IA32_MC15_CTL_MSR 0x043c +#define IA32_MC15_STATUS_MSR 0x043d +#define IA32_MC15_ADDR_MSR 0x043e +#define IA32_MC15_MISC_MSR 0x043f +#define IA32_MC16_CTL_MSR 0x0440 +#define IA32_MC16_STATUS_MSR 0x0441 +#define IA32_MC16_ADDR_MSR 0x0442 +#define IA32_MC16_MISC_MSR 0x0443 +#define IA32_MC17_CTL_MSR 0x0444 +#define IA32_MC17_STATUS_MSR 0x0445 +#define IA32_MC17_ADDR_MSR 0x0446 +#define IA32_MC17_MISC_MSR 0x0447 +#define IA32_MC18_CTL_MSR 0x0448 +#define IA32_MC18_STATUS_MSR 0x0449 +#define IA32_MC18_ADDR_MSR 0x044a +#define IA32_MC18_MISC_MSR 0x044b +#define IA32_MC19_CTL_MSR 0x044c +#define IA32_MC19_STATUS_MSR 0x044d +#define IA32_MC19_ADDR_MSR 0x044e +#define IA32_MC19_MISC_MSR 0x044f +#define IA32_MC20_CTL_MSR 0x0450 +#define IA32_MC20_STATUS_MSR 0x0451 +#define IA32_MC20_ADDR_MSR 0x0452 +#define IA32_MC20_MISC_MSR 0x0453 +#define IA32_MC21_CTL_MSR 0x0454 +#define IA32_MC21_STATUS_MSR 0x0455 +#define IA32_MC21_ADDR_MSR 0x0456 +#define IA32_MC21_MISC_MSR 0x0457 +#define IA32_VMX_BASIC_MSR 0x0480 +#define IA32_VMX_PINBASED_CTLS_MSR 0x0481 +#define IA32_VMX_PROCBASED_CTLS_MSR 0x0482 +#define IA32_VMX_EXIT_CTLS_MSR 0x0483 +#define IA32_VMX_ENTRY_CTLS_MSR 0x0484 +#define IA32_VMX_MISC_MSR 0x0485 +#define IA32_VMX_CRO_FIXED0_MSR 0x0486 +#define IA32_VMX_CRO_FIXED1_MSR 0x0487 +#define IA32_VMX_CR4_FIXED0_MSR 0x0488 +#define IA32_VMX_CR4_FIXED1_MSR 0x0489 +#define IA32_VMX_VMCS_ENUM_MSR 0x048a +#define IA32_VMX_PROCBASED_CTLS2_MSR 0x048b +#define IA32_VMX_EPT_VPID_CAP_MSR 0x048c +#define IA32_VMX_TRUE_PINBASED_CTLS_MSR 0x048d +#define IA32_VMX_TRUE_PROCBASED_CTLS_MSR 0x048e +#define IA32_VMX_TRUE_EXIT_CTLS_MSR 0x048f +#define IA32_VMX_TRUE_ENTRY_CTLS_MSR 0x0490 +#define IA32_DS_AREA_MSR 0x0600 +#define IA32_EXT_XAPICID_MSR 0x0802 +#define IA32_EXT_XAPIC_VERSION_MSR 0x0803 +#define A32_EXT_XAPIC_TPR_MSR 0x0808 +#define IA32_EXT_XAPIC_PPR_MSR 0x080a +#define IA32_EXT_XAPIC_EOI_MSR 0x080d +#define IA32_EXT_XAPIC_LDR_MSR 0x080c +#define IA32_EXT_XAPIC_SIVR_MSR 0x080f +#define IA32_EXT_XAPIC_ISR0_MSR 0x0810 +#define IA32_EXT_XAPIC_ISR1_MSR 0x0811 +#define A32_EXT_XAPIC_ISR2_MSR 0x0812 +#define IA32_EXT_XAPIC_ISR3_MSR 0x0813 +#define IA32_EXT_XAPIC_ISR4_MSR 0x0814 +#define IA32_EXT_XAPIC_ISR5_MSR 0x0815 +#define IA32_EXT_XAPIC_ISR6_MSR 0x0816 +#define IA32_EXT_XAPIC_ISR7_MSR 0x0817 +#define IA32_EXT_XAPIC_TMR0_MSR 0x0818 +#define IA32_EXT_XAPIC_TMR1_MSR 0x0819 +#define IA32_EXT_XAPIC_TMR2_MSR 0x081a +#define IA32_EXT_XAPIC_TMR3_MSR 0x081b +#define IA32_EXT_XAPIC_TMR4_MSR 0x081c +#define IA32_EXT_XAPIC_TMR5_MSR 0x081d +#define IA32_EXT_XAPIC_TMR6_MSR 0x081e +#define IA32_EXT_XAPIC_TMR7_MSR 0x081f +#define IA32_EXT_XAPIC_IRR0_MSR 0x0820 +#define IA32_EXT_XAPIC_IRR1_MSR 0x0821 +#define IA32_EXT_XAPIC_IRR2_MSR 0x0822 +#define IA32_EXT_XAPIC_IRR3_MSR 0x0823 +#define IA32_EXT_XAPIC_IRR4_MSR 0x0824 +#define IA32_EXT_XAPIC_IRR5_MSR 0x0825 +#define IA32_EXT_XAPIC_IRR6_MSR 0x0826 +#define IA32_EXT_XAPIC_IRR7_MSR 0x0827 +#define IA32_EXT_XAPIC_ESR_MSR 0x0828 +#define IA32_EXT_XAPIC_LVT_CMCI_MSR 0x082f +#define IA32_EXT_XAPIC_ICR_MSR 0x0830 +#define IA32_EXT_XAPIC_LVT_TIMER_MSR 0x0832 +#define IA32_EXT_XAPIC_LVT_THERMAL_MSR 0x0833 +#define IA32_EXT_XAPIC_LVT_PMI_MSR 0x0834 +#define IA32_EXT_XAPIC_LVT_LINT0_MSR 0x0835 +#define IA32_EXT_XAPIC_LVT_LINT1_MSR 0x0836 +#define IA32_EXT_XAPIC_LVT_ERROR_MSR 0x0837 +#define IA32_EXT_XAPIC_INIT_COUNT_MSR 0x0838 +#define IA32_EXT_XAPIC_CUR_COUNT_MSR 0x0839 +#define IA32_EXT_XAPIC_DIV_CONF_MSR 0x083e +#define IA32_EXT_XAPIC_SELF_IPI_MSR 0x083f +#define IA32_EFER_MSR 0xc0000080 +#define IA32_STAR_MSR 0xc0000081 +#define IA32_LSTAR_MSR 0xc0000082 +#define IA32_FMASK_MSR 0xc0000084 +#define IA32_FS_BASE_MSR 0xc0000100 +#define IA32_GS_BASE_MSR 0xc0000101 +#define IA32_KERNEL_GS_BASE_MSR 0xc0000102 +#define IA32_TSC_AUX_MSR 0xc0000103 + +/* + * EFLAGS value to utilize for the initial context: + * + * IF (Interrupt Enable Flag) = 1 + * IOPL bits = 0 + * All other "flags" = Don't change state + */ + +#define EFLAGS_INITIAL 0x00000200 +#define EFLAGS_MASK 0x00003200 + +/* The following opcodes are used to create interrupt and exception stubs */ + +#define IA32_CALL_OPCODE 0xe8 +#define IA32_PUSH_OPCODE 0x68 +#define IA32_JMP_OPCODE 0xe9 +#define IA32_ADD_OPCODE 0xc483 + +#ifndef _ASMLANGUAGE + +#include + +#ifdef DEBUG +#include +#define PRINTK(...) printk(__VA_ARGS__) +#else +#define PRINTK(...) +#endif /* DEBUG */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * The following structure defines the set of 'non-volatile' integer registers. + * These registers must be preserved by a called C function. These are the + * only registers that need to be saved/restored when a cooperative context + * switch occurs. + */ + +typedef struct s_coopReg { + unsigned long esp; + + /* + * The following registers are considered non-volatile, i.e. + *callee-save, + * but their values are pushed onto the stack rather than stored in the + *tCCS + * structure: + * + * unsigned long ebp; + * unsigned long ebx; + * unsigned long esi; + * unsigned long edi; + */ + +} tCoopReg; + +/* + * The following structure defines the set of 'volatile' integer registers. + * These registers need not be preserved by a called C function. Given that + * they are not preserved across function calls, they must be save/restored + * (along with the s_coop_reg) when a pre-emptive context switch occurs. + */ + +typedef struct s_preempReg { + + /* + * The volatile registers 'eax', 'ecx' and 'edx' area not included in + *the + * definition of 'tPreempReg' since the interrupt stubs + *(_IntEnt/_IntExit) + * and exception stubs (_ExcEnt/_ExcEnter) use the stack to save and + * restore the values of these registers in order to support interrupt + * nesting. The stubs do _not_ copy the saved values from the stack + *into + * the tCCS. + * + * unsigned long eax; + * unsigned long ecx; + * unsigned long edx; + */ + +} tPreempReg; + +/* + * The macro CONFIG_FP_SHARING shall be set to indicate that the + * saving/restoring of the traditional x87 floating point (and MMX) registers + * are supported by the nanokernel's context swapping code. The macro + * CONFIG_SSE shall _also_ be set if saving/restoring of the XMM + * registers is also supported in the nanokernel's context swapping code. + */ + +#ifdef CONFIG_FP_SHARING + +/* definition of a single x87 (floating point / MMX) register */ + +typedef struct s_FpReg { + unsigned char reg[10]; /* 80 bits: ST[0-7] */ +} tFpReg; + +/* + * The following is the "normal" floating point register save area, or + * more accurately the save area required by the 'fnsave' and 'frstor' + * instructions. The structure matches the layout described in the + * "Intel® 64 and IA-32 Architectures Software Developer’s Manual + * Volume 1: Basic Architecture": Protected Mode x87 FPU State Image in + * Memory, 32-Bit Format. + */ + +typedef struct s_FpRegSet { /* # of bytes: name of register */ + unsigned short fcw; /* 2 : x87 FPU control word */ + unsigned short pad1; /* 2 : N/A */ + unsigned short fsw; /* 2 : x87 FPU status word */ + unsigned short pad2; /* 2 : N/A */ + unsigned short ftw; /* 2 : x87 FPU tag word */ + unsigned short pad3; /* 2 : N/A */ + unsigned int fpuip; /* 4 : x87 FPU instruction pointer offset */ + unsigned short cs; /* 2 : x87 FPU instruction pointer selector */ + unsigned short fop : 11; /* 2 : x87 FPU opcode */ + unsigned short pad4 : 5; /* : 5 bits = 00000 */ + unsigned int fpudp; /* 4 : x87 FPU instr operand ptr offset */ + unsigned short ds; /* 2 : x87 FPU instr operand ptr selector */ + unsigned short pad5; /* 2 : N/A */ + tFpReg fpReg[8]; /* 80 : ST0 -> ST7 */ +} tFpRegSet __attribute__((aligned(FP_REG_SET_ALIGN))); + +#ifdef CONFIG_SSE + +/* definition of a single x87 (floating point / MMX) register */ + +typedef struct s_FpRegEx { + unsigned char reg[10]; /* 80 bits: ST[0-7] or MM[0-7] */ + unsigned char rsrvd[6]; /* 48 bits: reserved */ +} tFpRegEx; + +/* definition of a single XMM register */ + +typedef struct s_XmmReg { + unsigned char reg[16]; /* 128 bits: XMM[0-7] */ +} tXmmReg; + +/* + * The following is the "extended" floating point register save area, or + * more accurately the save area required by the 'fxsave' and 'fxrstor' + * instructions. The structure matches the layout described in the + * "Intel 64 and IA-32 Architectures Software Developer's Manual + * Volume 2A: Instruction Set Reference, A-M", except for the bytes from offset + * 464 to 511 since these "are available to software use. The processor does + * not write to bytes 464:511 of an FXSAVE area". + * + * This structure must be aligned on a 16 byte boundary when the instructions + * fxsave/fxrstor are used to write/read the data to/from the structure. + */ + +typedef struct s_FpRegSetEx /* # of bytes: name of register */ +{ + unsigned short fcw; /* 2 : x87 FPU control word */ + unsigned short fsw; /* 2 : x87 FPU status word */ + unsigned char ftw; /* 1 : x87 FPU abridged tag word */ + unsigned char rsrvd0; /* 1 : reserved */ + unsigned short fop; /* 2 : x87 FPU opcode */ + unsigned int fpuip; /* 4 : x87 FPU instruction pointer offset */ + unsigned short cs; /* 2 : x87 FPU instruction pointer selector */ + unsigned short rsrvd1; /* 2 : reserved */ + unsigned int fpudp; /* 4 : x87 FPU instr operand ptr offset */ + unsigned short ds; /* 2 : x87 FPU instr operand ptr selector */ + unsigned short rsrvd2; /* 2 : reserved */ + unsigned int mxcsr; /* 4 : MXCSR register state */ + unsigned int mxcsrMask; /* 4 : MXCSR register mask */ + tFpRegEx fpReg[8]; /* 128 : x87 FPU/MMX registers */ + tXmmReg xmmReg[8]; /* 128 : XMM registers */ + unsigned char rsrvd3[176]; /* 176 : reserved */ +} tFpRegSetEx __attribute__((aligned(FP_REG_SET_ALIGN))); + +#else /* CONFIG_SSE == 0 */ + +typedef struct s_FpRegSetEx { +} tFpRegSetEx; + +#endif /* CONFIG_SSE == 0 */ + +#else /* CONFIG_FP_SHARING == 0 */ + +/* empty floating point register definition */ + +typedef struct s_FpRegSet { +} tFpRegSet; + +typedef struct s_FpRegSetEx { +} tFpRegSetEx; + +#endif /* CONFIG_FP_SHARING == 0 */ + +/* + * The following structure defines the set of 'non-volatile' x87 FPU/MMX/SSE + * registers. These registers must be preserved by a called C function. + * These are the only registers that need to be saved/restored when a + * cooperative context switch occurs. + */ + +typedef struct s_coopFloatReg { + + /* + * This structure intentionally left blank, i.e. the ST[0] -> ST[7] and + * XMM0 -> XMM7 registers are all 'volatile'. + */ + +} tCoopFloatReg; + +/* + * The following structure defines the set of 'volatile' x87 FPU/MMX/SSE + * registers. Thes registers need not be preserved by a called C function. + * Given that they are not preserved across function calls, they must be + * save/restored (along with s_coopFloatReg) when a pre-emptive context + * switch occurs. + */ + +typedef struct s_preempFloatReg { + union { + tFpRegSet fpRegs; /* contexts with USE_FP utilize this format */ + tFpRegSetEx fpRegsEx; /* contexts with USE_SSE utilize this + format */ + } floatRegsUnion; +} tPreempFloatReg; + +/* + * The context control stucture definition. It contains the + * various fields to manage a _single_ context. The CCS will be aligned + * to the appropriate architecture specific boundary via the + * _NewContext() call. + */ + +struct s_CCS { + /* + * Link to next context in singly-linked context list (such as + * prioritized + * list of runnable fibers, or list of fibers waiting on a nanokernel + * FIFO). + */ + + struct s_CCS *link; + + /* + * See the above flag definitions above for valid bit settings. This + * field must remain near the start of the tCCS structure, specifically + * before any #ifdef'ed fields since the host tools currently use a + * fixed + * offset to read the 'flags' field. + */ + + int flags; + + /* + * Storage space for integer registers. These must also remain near + * the start of the tCCS structure for the same reason mention for + * 'flags'. + */ + + tCoopReg coopReg; /* non-volatile integer register storage */ + tPreempReg preempReg; /* volatile integer register storage */ + +#if defined(CONFIG_HOST_TOOLS_SUPPORT) + struct s_CCS *activeLink; /* link to next context in the active list */ +#endif +#ifdef CONFIG_GDB_INFO + void *esfPtr; /* pointer to exception stack frame saved by */ + /* outermost exception wrapper */ +#endif /* CONFIG_GDB_INFO */ + int prio; /* context priority used to sort linked list */ +#if (defined(CONFIG_FP_SHARING) || defined(CONFIG_GDB_INFO)) + /* + * Nested exception count to maintain setting of EXC_ACTIVE flag across + * outermost exception. EXC_ACTIVE is used by _Swap() lazy FP + * save/restore + * and by debug tools. + */ + unsigned excNestCount; /* nested exception count */ +#endif /* CONFIG_FP_SHARING || CONFIG_GDB_INFO */ + +#ifdef CONFIG_CONTEXT_CUSTOM_DATA + void *custom_data; /* available for custom use */ +#endif + + + /* + * The location of all floating point related structures/fields MUST be + * located at the end of the tCCS structure. This way only the + *fibers/tasks + * that actually utilize non-integer capabilities need to account for + * the increased memory required for storing FP state when sizing + *stacks. + * + * Given that stacks "grow down" on IA-32, and the tCCS structure is + *located + * at the start of a context's "workspace" memory, the stacks of + *fibers/tasks + * that do not utilize floating point instruction can effectively + *consume + * the memory occupied by the 'tCoopFloatReg' and 'tPreempFloatReg' + * structures without ill effect. + */ + + tCoopFloatReg coopFloatReg; /* non-volatile float register storage */ + tPreempFloatReg preempFloatReg; /* volatile float register storage */ +}; + +/* + * The nanokernel structure definition. It contains various fields to + * manage _all_ the contexts in the nanokernel (system level). + */ + +typedef struct s_NANO { + tCCS *fiber; /* singly linked list of runnable fiber contexts */ + tCCS *task; /* pointer to runnable task context */ + tCCS *current; /* currently scheduled context (fiber or task) */ +#if defined(CONFIG_HOST_TOOLS_SUPPORT) + tCCS *contexts; /* singly linked list of ALL fiber+tasks */ +#endif + unsigned nested; /* nested interrupt count */ + char *common_isp; /* interrupt stack pointer base */ + +#ifdef CONFIG_ADVANCED_POWER_MANAGEMENT + int32_t idle; /* Number of ticks for kernel idling */ +#endif /* CONFIG_ADVANCED_POWER_MANAGEMENT */ + + +#ifdef CONFIG_FP_SHARING + /* + * A 'current_sse' field does not exist in addition to the 'current_fp' + * field since it's not possible to divide the IA-32 non-integer + * registers + * into 2 distinct blocks owned by differing contexts. In other words, + * given that the 'fxnsave/fxrstor' instructions save/restore both the + * X87 FPU and XMM registers, it's not possible for a context to only + * "own" the XMM registers. + */ + + tCCS *current_fp; /* context (fiber or task) that owns the FP regs */ +#endif /* CONFIG_FP_SHARING */ +} tNANO; + +/* stack alignment related macros: STACK_ALIGN_SIZE is defined above */ + +#define STACK_ROUND_UP(x) ROUND_UP(x, STACK_ALIGN_SIZE) +#define STACK_ROUND_DOWN(x) ROUND_DOWN(x, STACK_ALIGN_SIZE) + +#ifndef NULL +#define NULL (void *)0 +#endif + +/* variable declarations */ + +/* + * There is only a single instance of the s_NANO structure, given that there + * is only a single nanokernel in the system: _NanoKernel + */ + +extern tNANO _NanoKernel; + +/* inline function definitions */ + +/******************************************************************************* +* +* nanoArchInit - performs architecture-specific initialization +* +* This routine performs architecture-specific initialization of the nanokernel. +* Trivial stuff is done inline; more complex initialization is done via +* function calls. +* +* RETURNS: N/A +* +* \NOMANUAL +*/ + +static inline void nanoArchInit(void) +{ + extern void *__isr___SpuriousIntHandler; + extern void *__DummySpur; + extern void _ExcEnt(void); + extern void *__DummyExcEnt; + extern char _InterruptStack[CONFIG_ISR_STACK_SIZE]; + + _NanoKernel.nested = 0; + +#ifdef CONFIG_NO_ISRS + _NanoKernel.common_isp = (char *)NULL; +#else /* notdef CONFIG_NO_ISRS */ + _NanoKernel.common_isp = (char *)STACK_ROUND_DOWN( + &_InterruptStack[CONFIG_ISR_STACK_SIZE - 1]); +#endif /* notdef CONFIG_NO_ISRS */ + + /* + * Forces the inclusion of the spurious interrupt handlers. If a + * reference + * isn't made then intconnect.o is never pulled in by the linker. + */ + + __DummySpur = &__isr___SpuriousIntHandler; + + /* + * Forces the inclusion of the exception vector stub code. If a + * reference + * isn't made then excstubs.o is never pulled in by the linker. + */ + + __DummyExcEnt = &_ExcEnt; + + +} + +/******************************************************************************* +* +* fiberRtnValueSet - set the return value for the specified fiber (inline) +* +* The register used to store the return value from a function call invocation is +* set to . It is assumed that the specified is pending, and +* thus the fibers context is stored in its tCCS structure. +* +* RETURNS: N/A +* +* \NOMANUAL +*/ + +static inline void fiberRtnValueSet( + tCCS *fiber, /* pointer to fiber */ + unsigned int value /* value to set as return value */ + ) +{ + /* write into 'eax' slot created in _Swap() entry */ + + *(unsigned int *)(fiber->coopReg.esp) = value; +} + +/******************************************************************************* +* +* EflagsGet - return the current value of the EFLAGS register +* +* RETURNS: the EFLAGS register. +* +* \NOMANUAL +*/ + +#if defined(__GNUC__) +static inline unsigned int EflagsGet(void) +{ + unsigned int eflags; /* EFLAGS register contents */ + + __asm__ volatile( + "pushfl;\n\t" + "popl %0;\n\t" + : "=r"(eflags) + : ); + + return eflags; +} +#elif defined(__DCC__) +__asm volatile unsigned int EflagsGet(void) +{ + % !"ax" pushfl popl % eax +} +#endif + +/* definitions to support nanoCpuExcConnect() */ + +#define _EXC_STUB_SIZE 0x14 + +/* + * Performance optimization + * + * Macro PERF_OPT is defined if project is compiled with option other than + * size optimization ("-Os" for GCC+ICC, "-XO -Xsize-opt" for Diab). If the + * last of the compiler options is the size optimization, PERF_OPT is not + * defined and the project is optimized for size, hence the stub should be + * aligned to 1 and not 16. + */ +#ifdef PERF_OPT +#define _EXC_STUB_ALIGN 16 +#else +#define _EXC_STUB_ALIGN 1 +#endif + +typedef unsigned char + __attribute__((aligned(_EXC_STUB_ALIGN))) NANO_EXC_STUB[_EXC_STUB_SIZE]; + +/* + * Macro to declare a dynamic exception stub. Using the macro places the stub + * in the .intStubSection which is located in the image according to the kernel + * configuration. + */ +#define NANO_CPU_EXC_STUB_DECL(s) _NODATA_SECTION(.intStubSect) NANO_EXC_STUB(s) + +/* function prototypes */ + +extern void nano_cpu_atomic_idle(unsigned int imask); +extern unsigned _Swap(unsigned int mask); +extern void _InsertCCS(tCCS **queue, tCCS *ccs); + +extern void _NewContextUsr(void *ccs, int prio, unsigned options); +extern void *_NewContext(char *pStack, + unsigned stackSize, + _ContextEntry pEntry, + _ContextArg arg1, + _ContextArg arg2, + _ContextArg arg3, + int prio, + unsigned options); +extern void nanoCpuExcConnect(unsigned int vector, + void (*routine)(NANO_ESF * pEsf), + NANO_EXC_STUB pExcStubMem); + +extern void _ContextUsrEntryRtn(_ContextEntry, + _ContextArg, + _ContextArg, + _ContextArg); + +extern void _IntVecSet(unsigned int vector, + void (*routine)(void *), + unsigned int dpl); + +extern void _MsrWrite(unsigned int msr, uint64_t msrData); +extern uint64_t _MsrRead(unsigned int msr); + +/* + * _IntLibInit() is called from the non-arch specific nanokernel function, + * _NanoInit(). The IA-32 nanokernel does not require any special + * initialization of the interrupt subsystem. However, we still need to + * provide an _IntLibInit() of some sort to prevent build errors. + */ +static inline void _IntLibInit(void) +{ +} + +#include /* For size_t */ + +#ifdef __cplusplus +} +#endif + +#define _IS_IN_ISR() (_NanoKernel.nested != 0) + +#endif /* _ASMLANGUAGE */ + +#endif /* _NANOK_H */ diff --git a/arch/x86/include/start_task_arch.h b/arch/x86/include/start_task_arch.h new file mode 100644 index 00000000000..ca98f49c88f --- /dev/null +++ b/arch/x86/include/start_task_arch.h @@ -0,0 +1,54 @@ +/* start_task.h - Intel nanokernel declarations to start a task */ + +/* + * Copyright (c) 2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +Intel-specific parts of start_task(). Only FP functionality currently. +*/ + +#ifndef _START_TASK_ARCH__H_ +#define _START_TASK_ARCH__H_ + +#include +#include + +#include +#include +#include +#include +#include + +extern void _StartTaskArch(struct k_proc *, unsigned int *); + +#define _START_TASK_ARCH(pKproc, pOpt) _StartTaskArch(pKproc, pOpt) + +#endif /* _START_TASK_ARCH__H_ */ diff --git a/arch/x86/include/swapstk.h b/arch/x86/include/swapstk.h new file mode 100644 index 00000000000..4fa95109310 --- /dev/null +++ b/arch/x86/include/swapstk.h @@ -0,0 +1,62 @@ +/* swapstk.h - stack frame created by swap (IA-32) */ + +/* + * Copyright (c) 2011-2012, 2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This file details the stack frame generated by _Swap() when it saves a task +or fiber's context. This is specific to the IA-32 processor architecture. + +NOTE: _Swap() does not use this file as it uses the push instruction to save a +context. Changes to the file will not automatically be picked up by _Swap(). +Conversely, changes to _Swap() should be mirrored here if the stack frame is +modified. +*/ + +#ifndef _SWAPSTK_H +#define _SWAPSTK_H + +#ifndef _ASMLANGUAGE + +/* Stack of a saved context */ +typedef struct s_SwapStk { + unsigned int eax; /* EAX register */ + unsigned int ebp; /* EBP register */ + unsigned int ebx; /* EBX register */ + unsigned int esi; /* ESI register */ + unsigned int edi; /* EDI register */ + unsigned int retAddr; /* Return address of caller of _Swap() */ + unsigned int param; /* Parameter passed to _Swap() */ +} tSwapStk; + +#endif /* _ASMLANGUAGE */ + +#endif /* _SWAPSTK_H */ diff --git a/arch/x86/interrupt_controller/ioApicIntr.c b/arch/x86/interrupt_controller/ioApicIntr.c new file mode 100644 index 00000000000..13d583a844c --- /dev/null +++ b/arch/x86/interrupt_controller/ioApicIntr.c @@ -0,0 +1,608 @@ +/* ioApicIntr.c - Intel IO APIC/xAPIC driver */ + +/* + * Copyright (c) 1997-1998, 2000-2002, 2004, 2006-2008, 2011-2015 Wind River + *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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This module is a driver for the IO APIC/xAPIC (Advanced Programmable +Interrupt Controller) for P6 (PentiumPro, II, III) family processors +and P7 (Pentium4) family processors. The IO APIC/xAPIC is included +in the Intel's system chip set, such as ICH2. Software intervention +may be required to enable the IO APIC/xAPIC in some chip sets. +The 8259A interrupt controller is intended for use in a uni-processor +system, IO APIC can be used in either a uni-processor or multi-processor +system. The IO APIC handles interrupts very differently than the 8259A. +Briefly, these differences are: + - Method of Interrupt Transmission. The IO APIC transmits interrupts + through a 3-wire bus and interrupts are handled without the need for + the processor to run an interrupt acknowledge cycle. + - Interrupt Priority. The priority of interrupts in the IO APIC is + independent of the interrupt number. For example, interrupt 10 can + be given a higher priority than interrupt 3. + - More Interrupts. The IO APIC supports a total of 24 interrupts. + +The IO APIC unit consists of a set of interrupt input signals, a 24-entry +by 64-bit Interrupt Redirection Table, programmable registers, and a message +unit for sending and receiving APIC messages over the APIC bus or the +Front-Side (system) bus. IO devices inject interrupts into the system by +asserting one of the interrupt lines to the IO APIC. The IO APIC selects the +corresponding entry in the Redirection Table and uses the information in that +entry to format an interrupt request message. Each entry in the Redirection +Table can be individually programmed to indicate edge/level sensitive interrupt +signals, the interrupt vector and priority, the destination processor, and how +the processor is selected (statically and dynamically). The information in +the table is used to transmit a message to other APIC units (via the APIC bus +or the Front-Side (system) bus). IO APIC is used in the Symmetric IO Mode. +The base address of IO APIC is determined in loapic_init() and stored in the +global variable ioApicBase and ioApicData. +The lower 32 bit value of the redirection table entries for IRQ 0 +to 15 are edge triggered positive high, and for IRQ 16 to 23 are level +triggered positive low. + +This implementation doesn't support multiple IO APICs. + +INCLUDE FILES: ioapic.h loapic.h + +SEE ALSO: loApicIntr.c +*/ + +/* includes */ + +#include +#include + +#include "board.h" + +#include +#include + +#include /* public API declarations */ +#include /* public API declarations and registers */ + +/* defines */ + +/* IO APIC direct register offsets */ + +#define IOAPIC_IND 0x00 /* Index Register */ +#define IOAPIC_DATA 0x10 /* IO window (data) - pc.h */ +#define IOAPIC_IRQPA 0x20 /* IRQ Pin Assertion Register */ +#define IOAPIC_EOI 0x40 /* EOI Register */ + +#ifdef IOAPIC_MSI_REDIRECT + +/* direct addressing of the RTEs; including the "configuration register" */ + +#define IOAPIC_RTE0_LOW 0x1000 +#define IOAPIC_RTE0_HIGH 0x1004 +#define IOAPIC_RTE0_CONFIG 0x1008 +#define IOAPIC_RTE1_LOW 0x1010 +#define IOAPIC_RTE1_HIGH 0x1014 +#define IOAPIC_RTE1_CONFIG 0x1018 +#define IOAPIC_RTE2_LOW 0x1020 +#define IOAPIC_RTE2_HIGH 0x1024 +#define IOAPIC_RTE2_CONFIG 0x1028 + +/* + * etc., etc. until IOAPIC_RTE63_LOW/IOAPIC_RTE63_HIGH/IOAPIC_RTE63_CONFIG + * + * rteLowOffset = IOAPIC_RTE0_LOW + (irq * 0x10) + * rteHighOffset = IOAPIC_RTE0_HIGH + (irq * 0x10) + * rteConfigOffset = IOAPIC_RTE0_CONFIG + (irq * 0x10) + */ + +/* + * An extention to the "standard" IOAPIC design supports a redirection + * capability that allows each RTE to specify which of the 8 "redirection + * registers" to use for determining the MSI address. + */ + +#define IOAPIC_REDIR_ADDR0 0x2000 /* Dummy entry; reads return all 0's */ +#define IOAPIC_REDIR_ADDR1 0x2004 /* MSI redirection selection reg 1 */ +#define IOAPIC_REDIR_ADDR2 0x2008 /* MSI redirection selection reg 2 */ +#define IOAPIC_REDIR_ADDR3 0x200c /* MSI redirection selection reg 3 */ +#define IOAPIC_REDIR_ADDR4 0x2010 /* MSI redirection selection reg 4 */ +#define IOAPIC_REDIR_ADDR5 0x2014 /* MSI redirection selection reg 5 */ +#define IOAPIC_REDIR_ADDR6 0x2018 /* MSI redirection selection reg 6 */ +#define IOAPIC_REDIR_ADDR7 0x201c /* MSI redirection selection reg 7 */ + +/* interrupt status for line interrupts generated via RTE0 through RTE31 */ + +#define IOAPIC_LINE_INT_STAT0 0x2040 + +/* interrupt status for line interrupts generated via RTE32 through RTE64 */ + +#define IOAPIC_LINE_INT_STAT1 0x2044 + +/* interrupt mask for line interrupts generated via RTE0 to RTE31 */ + +#define IOAPIC_LINE_INT_MASK0 0x2048 + +/* interrupt mask for line interrupts generated via RTE32 to RTE63 */ + +#define IOAPIC_LINE_INT_MASK1 0x204c + +#endif /* IOAPIC_MSI_REDIRECT */ + +/* IO APIC indirect register offset */ + +#define IOAPIC_ID 0x00 /* IOAPIC ID */ +#define IOAPIC_VERS 0x01 /* IOAPIC Version */ +#define IOAPIC_ARB 0x02 /* IOAPIC Arbitration ID */ +#define IOAPIC_BOOT 0x03 /* IOAPIC Boot Configuration */ +#define IOAPIC_REDTBL 0x10 /* Redirection Table (24 * 64bit) */ + +/* Interrupt delivery type */ + +#define IOAPIC_DT_APIC 0x0 /* APIC serial bus */ +#define IOAPIC_DT_FS 0x1 /* Front side bus message*/ + +/* Version register bits */ + +#define IOAPIC_MRE_MASK 0x00ff0000 /* Max Red. entry mask */ +#define IOAPIC_PRQ 0x00008000 /* this has IRQ reg */ +#define IOAPIC_VERSION 0x000000ff /* version number */ + +/* Redirection table entry number */ + +#define MAX_REDTABLE_ENTRIES 24 + +/* Redirection table entry bits: upper 32 bit */ + +#define IOAPIC_DESTINATION 0xff000000 + +/* Redirection table entry bits: lower 32 bit */ + +#define IOAPIC_VEC_MASK 0x000000ff + +#ifdef IOAPIC_MSI_REDIRECT + +/* RTE configuration register bits */ + +#define IOAPIC_RTE_CONFIG_REDIR_SEL 0x7 +#define IOAPIC_RTE_CONFIG_LI0EN 0x8 +#define IOAPIC_RTE_CONFIG_LI1EN 0x10 +#define IOAPIC_RTE_CONFIG_LI2EN 0x20 +#define IOAPIC_RTE_CONFIG_BYPASS_MSI_DISABLE 0x40 +#define IOAPIC_RTE_CONFIG_DISABLE_INT_EXT 0x80 + +#endif /* IOAPIC_MSI_REDIRECT */ + +/* forward declarations */ + +#ifndef XIOAPIC_DIRECT_ADDRESSING +static uint32_t __IoApicGet(int32_t offset); +static void __IoApicSet(int32_t offset, uint32_t value); +#endif + +static void ioApicRedSetHi(unsigned int irq, uint32_t upper32); +static void ioApicRedSetLo(unsigned int irq, uint32_t lower32); +static uint32_t ioApicRedGetLo(unsigned int irq); +static void _IoApicRedUpdateLo(unsigned int irq, uint32_t value, + uint32_t mask); + +/* + * The functions irq_enable() and irq_disable() are implemented + * in the BSPs that incorporate this interrupt controller driver due to the + * IRQ virtualization imposed by the BSP. + */ + +/******************************************************************************* +* +* _ioapic_init - initialize the IO APIC or xAPIC +* +* This routine initializes the IO APIC or xAPIC. +* +* RETURNS: N/A +*/ + +void _ioapic_init(void) +{ + int32_t ix; /* redirection table index */ + uint32_t rteValue; /* value to copy into redirection table entry */ + +#ifdef IOAPIC_MSI_REDIRECT + _IoApicRedirRegSet(MSI_REDIRECT_SELECT_ID, MSI_REDIRECT_TARGET_ADDR); +#endif + + /* + * The BSP must define the IOAPIC_NUM_RTES macro to indicate the number + * of redirection table entries supported by the IOAPIC on the board. + * + * Note: The number of actual IRQs supported by the IOAPIC can be + *determined + * at runtime by computing: + * + * ((__IoApicGet(IOAPIC_VERS) & IOAPIC_MRE_MASK) >> 16) + 1 + * + * however, storing the number of IRQs supported in a nanokernel global + * variable is not feasible since any references to this global variable + * from a microkernel-split image would not be able to directly access + *the + * variable; access via an indirection would be needed. + */ + + /* + * Initialize the redirection table entries with default settings; + * actual interrupt vectors are specified during irq_connect(). + * + * A future enhancement should make this initialization "table driven": + * use data provided by a BSP to specify the initial state + */ + + rteValue = IOAPIC_EDGE | IOAPIC_HIGH | IOAPIC_FIXED | IOAPIC_INT_MASK | + IOAPIC_PHYSICAL | 0 /* dummy vector */; + + for (ix = 0; ix < IOAPIC_NUM_RTES; ix++) { + ioApicRedSetHi(ix, 0); + ioApicRedSetLo(ix, rteValue); + } +} + +/******************************************************************************* +* +* _ioapic_eoi - send EOI (End Of Interrupt) signal to IO APIC +* +* This routine sends an EOI signal to the IO APIC's interrupting source. +* +* RETURNS: N/A +*/ + +void _ioapic_eoi(unsigned int irq /* INT number to send EOI */ + ) +{ + *(volatile unsigned int *)(IOAPIC_BASE_ADRS + IOAPIC_EOI) = irq; + *(volatile unsigned int *)(LOAPIC_BASE_ADRS + LOAPIC_EOI) = 0; +} + +/******************************************************************************* +* +* _ioapic_eoi_get - get EOI (End Of Interrupt) information +* +* This routine returns EOI signalling information for a specific IRQ. +* +* RETURNS: address of routine to be called to signal EOI; +* as a side effect, also passes back indication if routine requires +* an interrupt vector argument and what the argument value should be +*/ + +void *_ioapic_eoi_get(unsigned int irq, /* INTIN number of interest */ + char *argRequired, /* ptr to "argument required" result + area */ + void **arg /* ptr to "argument value" result area */ + ) +{ +#ifndef XIOAPIC_DIRECT_ADDRESSING + if (!(__IoApicGet(IOAPIC_VERS) & IOAPIC_PRQ)) { + *argRequired = 0; + return _loapic_eoi; + } +#endif + + /* indicate that an argument to the EOI handler is required */ + + *argRequired = 1; + + /* + * The parameter to the ioApicIntEoi() routine is the vector programmed + * into the redirection table. The BSPs _SysIntVecAlloc() routine + * must invoke _IoApicIntEoiGet() after _IoApicRedVecSet() to ensure the + * redirection table contains the desired interrupt vector. + */ + + *arg = (void *)(ioApicRedGetLo(irq) & IOAPIC_VEC_MASK); + + return _ioapic_eoi; +} + +/******************************************************************************* +* +* _ioapic_irq_enable - enable a specified APIC interrupt input line +* +* This routine enables a specified APIC interrupt input line. +* +* RETURNS: N/A +*/ + +void _ioapic_irq_enable(unsigned int irq /* INTIN number to enable */ + ) +{ + _IoApicRedUpdateLo(irq, 0, IOAPIC_INT_MASK); +} + +/******************************************************************************* +* +* _ioapic_irq_disable - disable a specified APIC interrupt input line +* +* This routine disables a specified APIC interrupt input line. +* +* RETURNS: N/A +*/ + +void _ioapic_irq_disable(unsigned int irq /* INTIN number to disable */ + ) +{ + _IoApicRedUpdateLo(irq, IOAPIC_INT_MASK, IOAPIC_INT_MASK); +} + +/******************************************************************************* +* +* _ioapic_irq_set - programs the interrupt redirection table +* +* This routine sets up the redirection table entry for the specified IRQ +* +* RETURNS: N/A +*/ +void _ioapic_irq_set(unsigned int irq, /* virtualized IRQ */ + unsigned int vector, /* vector number */ + uint32_t flags /* interrupt flags */ + ) +{ + uint32_t rteValue; /* value to copy into redirection table entry */ + + rteValue = IOAPIC_FIXED | IOAPIC_INT_MASK | IOAPIC_PHYSICAL | + (vector & IOAPIC_VEC_MASK) | flags; + ioApicRedSetHi(irq, 0); + ioApicRedSetLo(irq, rteValue); +} + +/******************************************************************************* +* +* _ioapic_int_vec_set - program interrupt vector for specified irq +* +* The routine writes the interrupt vector in the Interrupt Redirection +* Table for specified irq number +* +* RETURNS: N/A +*/ +void _ioapic_int_vec_set(unsigned int irq, /* INT number */ + unsigned int vector /* vector number */ + ) +{ + _IoApicRedUpdateLo(irq, vector, IOAPIC_VEC_MASK); +} + +#ifndef XIOAPIC_DIRECT_ADDRESSING + +/******************************************************************************* +* +* __IoApicGet - read a 32 bit IO APIC register +* +* This routine reads the specified IO APIC register using indirect addressing. +* +* RETURNS: register value +*/ + +static uint32_t __IoApicGet( + int32_t offset /* register offset (8 bits) */ + ) +{ + uint32_t value; /* value */ + int key; /* interrupt lock level */ + + /* lock interrupts to ensure indirect addressing works "atomically" */ + + key = irq_lock(); + + *((volatile char *)(IOAPIC_BASE_ADRS + IOAPIC_IND)) = (char)offset; + value = *((volatile uint32_t *)(IOAPIC_BASE_ADRS + IOAPIC_DATA)); + + irq_unlock(key); + + return value; +} + +/******************************************************************************* +* +* __IoApicSet - write a 32 bit IO APIC register +* +* This routine writes the specified IO APIC register using indirect addressing. +* +* RETURNS: N/A +*/ + +static void __IoApicSet( + int32_t offset, /* register offset (8 bits) */ + uint32_t value /* value to set the register */ + ) +{ + int key; /* interrupt lock level */ + + /* lock interrupts to ensure indirect addressing works "atomically" */ + + key = irq_lock(); + + *(volatile char *)(IOAPIC_BASE_ADRS + IOAPIC_IND) = (char)offset; + *((volatile uint32_t *)(IOAPIC_BASE_ADRS + IOAPIC_DATA)) = value; + + irq_unlock(key); +} + +#endif + +/******************************************************************************* +* +* ioApicRedGetLo - get low 32 bits of Redirection Table entry +* +* This routine reads the low-order 32 bits of a Redirection Table entry. +* +* RETURNS: 32 low-order bits +*/ + +static uint32_t ioApicRedGetLo(unsigned int irq /* INTIN number */ + ) +{ +#ifdef XIOAPIC_DIRECT_ADDRESSING + volatile uint32_t *pEntry; /* pointer to redirection table entry */ + pEntry = (volatile uint32_t *)(IOAPIC_BASE_ADRS + (irq * 0x10) + + IOAPIC_RTE0_LOW); + + return *pEntry; +#else + int32_t offset = IOAPIC_REDTBL + (irq << 1); /* register offset */ + + return __IoApicGet(offset); +#endif +} + +/******************************************************************************* +* +* ioApicRedSetLo - set low 32 bits of Redirection Table entry +* +* This routine writes the low-order 32 bits of a Redirection Table entry. +* +* RETURNS: N/A +*/ + +static void ioApicRedSetLo(unsigned int irq, /* INTIN number */ + uint32_t lower32 /* value to be written */ + ) +{ +#ifdef XIOAPIC_DIRECT_ADDRESSING + volatile uint32_t *pEntry; /* pointer to redirection table entry */ + pEntry = (volatile uint32_t *)(IOAPIC_BASE_ADRS + (irq * 0x10) + + IOAPIC_RTE0_LOW); + + *pEntry = lower32; +#else + int32_t offset = IOAPIC_REDTBL + (irq << 1); /* register offset */ + + __IoApicSet(offset, lower32); +#endif +} + +/******************************************************************************* +* +* ioApicRedSetHi - set high 32 bits of Redirection Table entry +* +* This routine writes the high-order 32 bits of a Redirection Table entry. +* +* RETURNS: N/A +*/ + +static void ioApicRedSetHi(unsigned int irq, /* INTIN number */ + uint32_t upper32 /* value to be written */ + ) +{ +#ifdef XIOAPIC_DIRECT_ADDRESSING + volatile uint32_t *pEntry; /* pointer to redirection table entry */ + pEntry = (volatile uint32_t *)(IOAPIC_BASE_ADRS + (irq * 0x10) + + IOAPIC_RTE0_HIGH); + + *pEntry = upper32; +#else + int32_t offset = IOAPIC_REDTBL + (irq << 1) + 1; /* register offset */ + + __IoApicSet(offset, upper32); +#endif +} + +/******************************************************************************* +* +* _IoApicRedUpdateLo - modify low 32 bits of Redirection Table entry +* +* This routine modifies selected portions of the low-order 32 bits of a +* Redirection Table entry, as indicated by the associate bit mask. +* +* RETURNS: N/A +*/ + +static void _IoApicRedUpdateLo( + unsigned int irq, /* INTIN number */ + uint32_t value, /* value to be written */ + uint32_t mask /* mask of bits to be modified */ + ) +{ + ioApicRedSetLo(irq, (ioApicRedGetLo(irq) & ~mask) | (value & mask)); +} + +#ifdef IOAPIC_MSI_REDIRECT + +/* + * A BSP's board.h file is responsible for setting the IOAPIC_MSI_REDIRECT + * macro if the I/O APIC supports the MSI redirect capability. + */ + +/******************************************************************************* +* +* _IoApicRteConfigSet - write to the RTE config register for specified IRQ +* +* This routine writes the specified 32-bit into the RTE configuration +* register for the specified (0 to (IOAPIC_NUM_RTES - 1)) +* +* RETURNS: void +*/ + +static void _IoApicRteConfigSet(unsigned int irq, /* INTIN number */ + uint32_t value /* value to be written */ + ) +{ + unsigned int offset; /* register offset */ + +#ifdef DEBUG + if (irq >= IOAPIC_NUM_RTES) + return; /* do nothing if is invalid */ +#endif + + offset = IOAPIC_RTE0_CONFIG + (irq * 0x10); + + /* use direct addressing when writing to RTE config register */ + + *((volatile uint32_t *)(IOAPIC_BASE_ADRS + offset)) = value; +} + +/******************************************************************************* +* +* _IoApicRedirRegSet - write to the specified MSI redirection register +* +* This routine writes the 32-bit into the redirection register +* specified by . +* +* RETURNS: void +*/ + +static void _IoApicRedirRegSet(unsigned int reg, uint32_t value) +{ + unsigned int offset; /* register offset */ + +#ifdef DEBUG + if ((reg > 7) || (reg == 0)) + return; /* do nothing if is invalid */ +#endif + + offset = IOAPIC_REDIR_ADDR0 + (reg * 4); + + /* use direct addressing when writing to RTE config register */ + + *((volatile uint32_t *)(IOAPIC_BASE_ADRS + offset)) = value; +} + +#endif /* IOAPIC_MSI_REDIRECT */ diff --git a/arch/x86/interrupt_controller/loApicIntr.c b/arch/x86/interrupt_controller/loApicIntr.c new file mode 100644 index 00000000000..72c4fe5bfa5 --- /dev/null +++ b/arch/x86/interrupt_controller/loApicIntr.c @@ -0,0 +1,420 @@ +/* loApicIntr.c - Intel Pentium[234] Local APIC/xAPIC driver */ + +/* + * Copyright (c) 1984-2008, 2011-2015 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This module is a driver for the local APIC/xAPIC (Advanced Programmable +Interrupt Controller) in P6 (PentiumPro, II, III) family processors +and P7 (Pentium4) family processors. The local APIC/xAPIC is included +in selected P6 (PentiumPro, II, III) and P7 (Pentium4) family processors. +Beginning with the P6 family processors, the presence or absence of an +on-chip local APIC can be detected using the CPUID instruction. When the +CPUID instruction is executed, bit 9 of the feature flags returned in the +EDX register indicates the presence (set) or absence (clear) of an on-chip +local APIC. + +The local APIC performs two main functions for the processor: + - It processes local external interrupts that the processor receives at its + interrupt pins and local internal interrupts that software generates. + - It communicates with an external IO APIC + chip. The external IO APIC receives external interrupt events from + peripheral and direct them to the local APIC. The IO APIC is + part of Intel's system chip set. +The local APIC controls the dispatching of interrupts (to its associated +processor) that it receives either locally or from the IO APIC. It provides +facilities for queuing, nesting and masking of interrupts. It handles the +interrupt delivery protocol with its local processor and accesses to APIC +registers. +A timer on the local APIC allows local generation of interrupts, and +local interrupt pins permit local reception of processor-specific interrupts. +The local APIC can be disabled and used in conjunction with a standard 8259A +style interrupt controller. Disabling the local APIC can be done in hardware +for the Pentium processors or in software for the P6 and P7 (Pentium4) family +processors. + +The local APIC in the Pentium4 processors (called the xAPIC) is an extension +of the local APIC found in the P6 family processors. The primary difference +between the APIC architecture and xAPIC architecture is that with Pentium4 +processors, the local xAPICs and IO xAPIC communicate with one another through +the processors system bus; whereas, with the P6 family processors, communication +between the local APICs and the IO APIC is handled through a dedicated 3-wire +APIC bus. Also, some of the architectural features of the local APIC have been +extended and/or modified in the local xAPIC. + +The base address of the local APIC and IO APIC is taken from the BSP board.h. +It uses LOAPIC_BASE_ADRS and IOAPIC_BASE_ADRS. +This driver contains three routines for use. They are: +_loapic_init() initializes the Local APIC for the interrupt mode chosen. +_loapic_enable()/disable() enables / disables the Local APIC. + +Local APIC is used in the Virtual Wire Mode: delivery mode ExtINT. + +Virtual Wire Mode is one of three interrupt modes defined by the MP +specification. In this mode, interrupts are generated by the 8259A equivalent +PICs (if present) and delivered to the Boot Strap Processor by +the local APIC that is programmed to act as a "virtual Wire"; that +is, the local APIC is logically indistinguishable from a hardware +connection. This is a uniprocessor compatibility mode. + +The local and IO APICs support interrupts in the range of 32 to 255. +Interrupt priority is implied by its vector, according to the following +relationship: "priority = vector / 16". +Here the quotient is rounded down to the nearest integer value to determine +the priority, with 1 being the lowest and 15 is the highest. Because vectors +0 through 31 are reserved for exclusive use by the processor, the priority of +user defined interrupts range from 2 to 15. A value of 15 in the Interrupt +Class field of the Task Priority Register (TPR) will mask off all interrupts, +which require interrupt service. +The P6 family processor's local APIC includes an in-service entry and a holding +entry for each priority level. To avoid losing interrupts, software should +allocate no more than 2 interrupt vectors per priority. The Pentium4 processor +expands this support of all acceptance of two interrupts per vector rather than +per priority level. + +INCLUDE FILES: loapic.h +*/ + +/* includes */ + +#include +#include +#include + +#include "board.h" +#include +#include +#include /* public API declarations */ + +/* defines */ + +/* IA32_APIC_BASE MSR Bits */ + +#define LOAPIC_BASE_MASK 0xfffff000 /* LO APIC Base Addr mask */ +#define LOAPIC_GLOBAL_ENABLE 0x00000800 /* LO APIC Global Enable */ +#define LOAPIC_BSP 0x00000100 /* LO APIC BSP */ + +/* Local APIC ID Register Bits */ + +#define LOAPIC_ID_MASK 0x0f000000 /* LO APIC ID mask */ + +/* Local APIC Version Register Bits */ + +#define LOAPIC_VERSION_MASK 0x000000ff /* LO APIC Version mask */ +#define LOAPIC_MAXLVT_MASK 0x00ff0000 /* LO APIC Max LVT mask */ +#define LOAPIC_PENTIUM4 0x00000014 /* LO APIC in Pentium4 */ +#define LOAPIC_LVT_PENTIUM4 5 /* LO APIC LVT - Pentium4 */ +#define LOAPIC_LVT_P6 4 /* LO APIC LVT - P6 */ +#define LOAPIC_LVT_P5 3 /* LO APIC LVT - P5 */ + +/* Local APIC Vector Table Bits */ + +#define LOAPIC_VECTOR 0x000000ff /* vectorNo */ +#define LOAPIC_MODE 0x00000700 /* delivery mode */ +#define LOAPIC_FIXED 0x00000000 /* delivery mode: FIXED */ +#define LOAPIC_SMI 0x00000200 /* delivery mode: SMI */ +#define LOAPIC_NMI 0x00000400 /* delivery mode: NMI */ +#define LOAPIC_EXT 0x00000700 /* delivery mode: ExtINT */ +#define LOAPIC_IDLE 0x00000000 /* delivery status: Idle */ +#define LOAPIC_PEND 0x00001000 /* delivery status: Pend */ +#define LOAPIC_HIGH 0x00000000 /* polarity: High */ +#define LOAPIC_LOW 0x00002000 /* polarity: Low */ +#define LOAPIC_REMOTE 0x00004000 /* remote IRR */ +#define LOAPIC_EDGE 0x00000000 /* trigger mode: Edge */ +#define LOAPIC_LEVEL 0x00008000 /* trigger mode: Level */ +#define LOAPIC_MASK 0x00010000 /* mask */ + +/* Local APIC Spurious-Interrupt Register Bits */ + +#define LOAPIC_ENABLE 0x100 /* APIC Enabled */ +#define LOAPIC_FOCUS_DISABLE 0x200 /* Focus Processor Checking */ + +/* Local Vector's lock-unlock macro used in loApicIntLock/Unlock */ + +#define LOCKED_TIMER 0x01 +#define LOCKED_PMC 0x02 +#define LOCKED_LINT0 0x04 +#define LOCKED_LINT1 0x08 +#define LOCKED_ERROR 0x10 +#define LOCKED_THERMAL 0x20 + +/* Interrupt Command Register: delivery mode and status */ + +#define MODE_FIXED 0x0 /* delivery mode: Fixed */ +#define MODE_LOWEST 0x1 /* delivery mode: Lowest */ +#define MODE_SMI 0x2 /* delivery mode: SMI */ +#define MODE_NMI 0x4 /* delivery mode: NMI */ +#define MODE_INIT 0x5 /* delivery mode: INIT */ +#define MODE_STARTUP 0x6 /* delivery mode: StartUp */ +#define STATUS_PEND 0x1000 /* delivery status: Pend */ + +/* MP Configuration Table Entries */ + +#define MP_ENTRY_CPU 0 /* Entry Type: CPU */ +#define MP_ENTRY_BUS 1 /* Entry Type: BUS */ +#define MP_ENTRY_IOAPIC 2 /* Entry Type: IO APIC */ +#define MP_ENTRY_IOINTERRUPT 3 /* Entry Type: IO INT */ +#define MP_ENTRY_LOINTERRUPT 4 /* Entry Type: LO INT */ + +/* Extended MP Configuration Table Entries */ + +#define EXT_MP_ENTRY_SASM 128 /* Entry Type: System Address Space Map */ +#define EXT_MP_ENTRY_BHD 129 /* Entry Type: Bus Hierarchy Descriptor */ +#define EXT_MP_ENTRY_CBASM 130 /* Entry Type: Comp Address Space Modifier */ + +/* MP Configuration Table CPU Flags */ + +#define MP_CPU_FLAGS_BP 0x02 + +/* IMCR related bits */ + +#define IMCR_ADRS 0x22 /* IMCR addr reg */ +#define IMCR_DATA 0x23 /* IMCR data reg */ +#define IMCR_REG_SEL 0x70 /* IMCR reg select */ +#define IMCR_IOAPIC_ON 0x01 /* IMCR IOAPIC route enable */ +#define IMCR_IOAPIC_OFF 0x00 /* IMCR IOAPIC route disable */ + + +/******************************************************************************* +* +* _loapic_init - initialize the Local APIC or xAPIC +* +* This routine initializes Local APIC or xAPIC. +* +* RETURNS: N/A +* +*/ + +void _loapic_init(void) +{ + int32_t loApicMaxLvt; /* local APIC Max LVT */ + + /* enable the Local APIC */ + + _loapic_enable(); + + loApicMaxLvt = (*(volatile int *)(LOAPIC_BASE_ADRS + LOAPIC_VER) & + LOAPIC_MAXLVT_MASK) >> + 16; + + /* reset the DFR, TPR, TIMER_CONFIG, and TIMER_ICR */ + + *(volatile int *)(LOAPIC_BASE_ADRS + LOAPIC_DFR) = (int)0xffffffff; + *(volatile int *)(LOAPIC_BASE_ADRS + LOAPIC_TPR) = (int)0x0; + *(volatile int *)(LOAPIC_BASE_ADRS + LOAPIC_TIMER_CONFIG) = (int)0x0; + *(volatile int *)(LOAPIC_BASE_ADRS + LOAPIC_TIMER_ICR) = (int)0x0; + + /* program Local Vector Table for the Virtual Wire Mode */ + + /* set LINT0: extInt, high-polarity, edge-trigger, not-masked */ + + *(volatile int *)(LOAPIC_BASE_ADRS + LOAPIC_LINT0) = + (*(volatile int *)(LOAPIC_BASE_ADRS + LOAPIC_LINT0) & + ~(LOAPIC_MODE | LOAPIC_LOW | LOAPIC_LEVEL | LOAPIC_MASK)) | + (LOAPIC_EXT | LOAPIC_HIGH | LOAPIC_EDGE); + + /* set LINT1: NMI, high-polarity, edge-trigger, not-masked */ + + *(volatile int *)(LOAPIC_BASE_ADRS + LOAPIC_LINT1) = + (*(volatile int *)(LOAPIC_BASE_ADRS + LOAPIC_LINT1) & + ~(LOAPIC_MODE | LOAPIC_LOW | LOAPIC_LEVEL | LOAPIC_MASK)) | + (LOAPIC_NMI | LOAPIC_HIGH | LOAPIC_EDGE); + + /* lock the Local APIC interrupts */ + + *(volatile int *)(LOAPIC_BASE_ADRS + LOAPIC_TIMER) = LOAPIC_MASK; + *(volatile int *)(LOAPIC_BASE_ADRS + LOAPIC_ERROR) = LOAPIC_MASK; + + if (loApicMaxLvt >= LOAPIC_LVT_P6) + *(volatile int *)(LOAPIC_BASE_ADRS + LOAPIC_PMC) = LOAPIC_MASK; + + if (loApicMaxLvt >= LOAPIC_LVT_PENTIUM4) + *(volatile int *)(LOAPIC_BASE_ADRS + LOAPIC_THERMAL) = + LOAPIC_MASK; + + /* discard a pending interrupt if any */ + + *(volatile int *)(LOAPIC_BASE_ADRS + LOAPIC_EOI) = 0; +} + +/******************************************************************************* +* +* _loapic_enable - enable the Local xAPIC +* +* This routine enables the Local xAPIC. +* +* RETURNS: N/A +*/ + +void _loapic_enable(void) +{ + int32_t oldLevel = irq_lock(); /* LOCK INTERRUPTS */ + + *(volatile int *)(LOAPIC_BASE_ADRS + LOAPIC_SVR) |= LOAPIC_ENABLE; + + irq_unlock(oldLevel); /* UNLOCK INTERRUPTS */ +} + +/******************************************************************************* +* +* _loapic_disable - disable the Local xAPIC +* +* This routine disables the Local xAPIC. +* +* RETURNS: N/A +*/ + +void _loapic_disable(void) +{ + int32_t oldLevel = irq_lock(); /* LOCK INTERRUPTS */ + + *(volatile int *)(LOAPIC_BASE_ADRS + LOAPIC_SVR) &= ~LOAPIC_ENABLE; + + irq_unlock(oldLevel); /* UNLOCK INTERRUPTS */ +} + +/******************************************************************************* +* +* _loapic_eoi - send EOI (End Of Interrupt) signal to Local APIC +* +* This routine sends an EOI signal to the Local APIC's interrupting source. +* +* RETURNS: N/A +*/ + +void _loapic_eoi(unsigned int irq) +{ + ARG_UNUSED(irq); + *(volatile int *)(LOAPIC_BASE_ADRS + LOAPIC_EOI) = 0; +} + +/******************************************************************************* +* +* _loapic_int_vec_set - set the vector field in the specified RTE +* +* This routine is utilized by the BSP provided routined _SysIntVecAllocate() +* which in turn is provided to support the irq_connect() API. Once +* a vector has been allocated, this routine is invoked to update the LVT +* entry associated with with the vector. +* +* RETURNS: N/A +*/ + +void _loapic_int_vec_set(unsigned int irq, /* IRQ number of the + interrupt */ + unsigned int vector /* vector to copy + into the LVT */ + ) +{ + volatile int *pLvt; /* pointer to local vector table */ + int32_t oldLevel; /* previous interrupt lock level */ + + /* + * The following mappings are used: + * + * IRQ0 -> LOAPIC_TIMER + * IRQ1 -> LOAPIC_THERMAL + * IRQ2 -> LOAPIC_PMC + * IRQ3 -> LOAPIC_LINT0 + * IRQ4 -> LOAPIC_LINT1 + * IRQ5 -> LOAPIC_ERROR + * + * It's assumed that LVTs are spaced by 0x10 bytes + */ + + pLvt = (volatile int *)(LOAPIC_BASE_ADRS + LOAPIC_TIMER + (irq * 0x10)); + + /* update the 'vector' bits in the LVT */ + + oldLevel = irq_lock(); + *pLvt = (*pLvt & ~LOAPIC_VECTOR) | vector; + irq_unlock(oldLevel); +} + +/******************************************************************************* +* +* _loapic_irq_enable - enable an individual LOAPIC interrupt (IRQ) +* +* This routine clears the interrupt mask bit in the LVT for the specified IRQ +* +* RETURNS: N/A +*/ + +void _loapic_irq_enable(unsigned int irq /* IRQ number of + the interrupt */ + ) +{ + volatile int *pLvt; /* pointer to local vector table */ + int32_t oldLevel; /* previous interrupt lock level */ + + /* + * See the comments in _LoApicLvtVecSet() regarding IRQ to LVT mappings + * and ths assumption concerning LVT spacing. + */ + + pLvt = (volatile int *)(LOAPIC_BASE_ADRS + LOAPIC_TIMER + (irq * 0x10)); + + /* clear the mask bit in the LVT */ + + oldLevel = irq_lock(); + *pLvt = *pLvt & ~LOAPIC_MASK; + irq_unlock(oldLevel); +} + +/******************************************************************************* +* +* _loapic_irq_disable - disable an individual LOAPIC interrupt (IRQ) +* +* This routine clears the interrupt mask bit in the LVT for the specified IRQ +* +* RETURNS: N/A +*/ + +void _loapic_irq_disable(unsigned int irq /* IRQ number of the + interrupt */ + ) +{ + volatile int *pLvt; /* pointer to local vector table */ + int32_t oldLevel; /* previous interrupt lock level */ + + /* + * See the comments in _LoApicLvtVecSet() regarding IRQ to LVT mappings + * and ths assumption concerning LVT spacing. + */ + + pLvt = (volatile int *)(LOAPIC_BASE_ADRS + LOAPIC_TIMER + (irq * 0x10)); + + /* set the mask bit in the LVT */ + + oldLevel = irq_lock(); + *pLvt = *pLvt | LOAPIC_MASK; + irq_unlock(oldLevel); +} diff --git a/arch/x86/quark/board.h b/arch/x86/quark/board.h new file mode 100644 index 00000000000..d231a2873b2 --- /dev/null +++ b/arch/x86/quark/board.h @@ -0,0 +1,477 @@ +/* board.h - board configuration macros for the 'Quark' BSP */ + +/* + * Copyright (c) 2013-2015, Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This header file is used to specify and describe board-level aspects for +the 'Quark' BSP. +*/ + +#ifndef __INCboardh +#define __INCboardh + +#include + +#ifndef _ASMLANGUAGE +#include +#endif + +#define N_PIC_IRQS 16 /* number of PIC IRQs */ +#define INT_VEC_IRQ0 0x20 /* Vector number for IRQ0 */ + +/* + * IO APIC (IOAPIC) device information (Intel ioapic) + */ +#define IOAPIC_NUM_RTES 24 /* Number of IRQs = 24 */ + +#define IOAPIC_BASE_ADRS_PHYS 0xFEC00000 /* base physical address */ +#define IOAPIC_SIZE KB(4) + +#define IOAPIC_BASE_ADRS IOAPIC_BASE_ADRS_PHYS + +/* + * Local APIC (LOAPIC) device information (Intel loapic) + */ + +#define LOAPIC_BASE_ADRS_PHYS 0xFEE00000 /* base physical address */ +#define LOAPIC_SIZE KB(4) + +#define LOAPIC_BASE_ADRS LOAPIC_BASE_ADRS_PHYS +/* + * HPET device information + */ + +#define HPET_BASE_ADRS_PHYS 0xFED00000 +#define HPET_SIZE KB(4) + +#define HPET_BASE_ADRS HPET_BASE_ADRS_PHYS + +#define HPET_TIMER0_IRQ (20) +#define HPET_TIMER0_VEC (HPET_TIMER0_IRQ + INT_VEC_IRQ0) +/* HPET uses falling edge triggered interrupt */ +#define HPET_IOAPIC_FLAGS (IOAPIC_EDGE | IOAPIC_LOW) + +/* serial port (aka COM port) information */ +#define COM1_BAUD_RATE 115200 +#define COM1_PCI_IDX 2 + +#define COM2_BAUD_RATE 115200 +#define COM2_PCI_IDX 0 +#define COM2_INT_LVL 0x11 /* COM2 connected to IRQ17 */ + +#define UART_REG_ADDR_INTERVAL 4 /* address diff of adjacent regs. */ +#define UART_XTAL_FREQ (2764800 * 16) +/* UART uses level triggered interrupt, low level */ +#define UART_IOAPIC_FLAGS (IOAPIC_LEVEL | IOAPIC_LOW) + +/* uart configuration settings */ + +/* Generic definitions */ +#define CONFIG_UART_NUM_SYSTEM_PORTS 2 +#define CONFIG_UART_NUM_EXTRA_PORTS 0 +#define CONFIG_UART_BAUDRATE COM1_BAUD_RATE +#define CONFIG_UART_NUM_PORTS \ + (CONFIG_UART_NUM_SYSTEM_PORTS + CONFIG_UART_NUM_EXTRA_PORTS) + +/* Console definitions */ +#define CONFIG_UART_CONSOLE_INDEX 0 +#define CONFIG_UART_CONSOLE_PCI_IDX COM1_PCI_IDX + +/* + * The irq_connect() API connects to a (virtualized) IRQ and the + * associated interrupt controller is programmed with the allocated vector. + * The Quark board virtualizes IRQs as follows: + * + * - The first IOAPIC_NUM_RTES IRQs are provided by the IOAPIC + * - The remaining IRQs are provided by the LOAPIC. + * + * Thus, for example, if the IOAPIC supports 24 IRQs: + * + * - IRQ0 to IRQ23 map to IOAPIC IRQ0 to IRQ23 + * - IRQ24 to IRQ29 map to LOAPIC LVT entries as follows: + * + * IRQ24 -> LOAPIC_TIMER + * IRQ25 -> LOAPIC_THERMAL + * IRQ26 -> LOAPIC_PMC + * IRQ27 -> LOAPIC_LINT0 + * IRQ28 -> LOAPIC_LINT1 + * IRQ29 -> LOAPIC_ERROR + */ +#define LOAPIC_VEC_BASE(x) (x + INT_VEC_IRQ0 + IOAPIC_NUM_RTES) + +#ifndef _ASMLANGUAGE +/* + * The parameter is deliberately ignored. For this BSP, the macro just has + * to make sure that unique vector numbers are generated. + */ +#define SYS_INT_REGISTER(s, irq, pri) \ + NANO_CPU_INT_REGISTER(s, INT_VEC_IRQ0 + (irq), 0) +#endif + +/* Start of the 4 MB virtual address space */ +#define VIRT_ADDR_START 0x00000000 + +/* PCI definitions */ +#define PCI_CTRL_ADDR_REG 0xCF8 +#define PCI_CTRL_DATA_REG 0xCFC + +#define PCI_INTA 1 +#define PCI_INTB 2 +#define PCI_INTC 3 +#define PCI_INTD 4 + +#ifndef _ASMLANGUAGE +/* + * Device drivers utilize the macros PLB_BYTE_REG_WRITE() and + * PLB_BYTE_REG_READ() to access byte-wide registers on the processor + * local bus (PLB), as opposed to a PCI bus, for example. Boards are + * expected to provide implementations of these macros. + */ + +#define PLB_BYTE_REG_WRITE(data, address) \ + io_outByte(data, (unsigned int)address) +#define PLB_BYTE_REG_READ(address) io_inByte((unsigned int)address) + +/******************************************************************************* +* +* io_outByte - output a byte to an IA-32 I/O port +* +* This function issues the 'out' instruction to write a byte to the specified +* I/O port. +* +* RETURNS: N/A +* +* NOMANUAL +*/ + +#if defined(__DCC__) +__asm volatile void io_outByte(unsigned char data, unsigned int port) +{ + % mem data, port; + !"ax", "dx" movl port, % edx movb data, % al outb % al, % dx +} +#elif defined(__GNUC__) +static inline void io_outByte(unsigned char data, unsigned int port) +{ + __asm__ volatile("outb %%al, %%dx;\n\t" : : "a"(data), "d"(port)); +} +#endif + +/******************************************************************************* +* +* io_inByte - input a byte from an IA-32 I/O port +* +* This function issues the 'in' instruction to read a byte from the specified +* I/O port. +* +* RETURNS: the byte read from the specified I/O port +* +* NOMANUAL +*/ + +#if defined(__DCC__) +__asm volatile unsigned char io_inByte(unsigned int port) +{ + % mem port; + !"ax", "dx" movl port, % edx inb % dx, % al +} +#elif defined(__GNUC__) +static inline unsigned char io_inByte(unsigned int port) +{ + char retByte; + + __asm__ volatile("inb %%dx, %%al;\n\t" : "=a"(retByte) : "d"(port)); + return retByte; +} +#endif + +/******************************************************************************* +* +* outByte - output byte to memory location +* +* RETURNS: N/A +* +* NOMANUAL +*/ + +static inline void outByte(uint8_t data, uint32_t addr) +{ + *(volatile uint8_t *)addr = data; +} + +/******************************************************************************* +* +* inByte - obtain byte value from memory location +* +* This function issues the 'move' instruction to read a byte from the specified +* memory address. +* +* RETURNS: the byte read from the specified memory address +* +* NOMANUAL +*/ + +static inline uint8_t inByte(uint32_t addr) +{ + return *((volatile uint8_t *)addr); +} + +/* + * Device drivers utilize the macros PLB_WORD_REG_WRITE() and + * PLB_WORD_REG_READ() to access shortword-wide registers on the processor + * local bus (PLB), as opposed to a PCI bus, for example. Boards are + * expected to provide implementations of these macros. + */ + +#define PLB_WORD_REG_WRITE(data, address) \ + io_outWord(data, (unsigned int)address) +#define PLB_WORD_REG_READ(address) io_inWord((unsigned int)address) + +/******************************************************************************* +* +* io_outWord - output a word to an IA-32 I/O port +* +* This function issues the 'out' instruction to write a word to the +* specified I/O port. +* +* RETURNS: N/A +* +* NOMANUAL +*/ + +#if defined(__DCC__) +__asm volatile void io_outWord(unsigned short data, unsigned int port) +{ + % mem data, port; + !"ax", "dx" movl port, % edx movw data, % ax outw % ax, % dx +} +#elif defined(__GNUC__) +static inline void io_outWord(unsigned short data, unsigned int port) +{ + __asm__ volatile("outw %%ax, %%dx;\n\t" : : "a"(data), "d"(port)); +} +#endif + +/******************************************************************************* +* +* io_inWord - input a word from an IA-32 I/O port +* +* This function issues the 'in' instruction to read a word from the +* specified I/O port. +* +* RETURNS: the word read from the specified I/O port +* +* NOMANUAL +*/ + +#if defined(__DCC__) +__asm volatile unsigned short io_inWord(unsigned int port) +{ + % mem port; + !"ax", "dx" movl port, % edx inw % dx, % ax +} +#elif defined(__GNUC__) +static inline unsigned short io_inWord(unsigned int port) +{ + unsigned short retWord; + + __asm__ volatile("inw %%dx, %%ax;\n\t" : "=a"(retWord) : "d"(port)); + return retWord; +} +#endif + +/******************************************************************************* +* +* outWord - output word to memory location +* +* RETURNS: N/A +* +* NOMANUAL +*/ + +static inline void outWord(uint16_t data, uint32_t addr) +{ + *(volatile uint16_t *)addr = data; +} + +/******************************************************************************* +* +* inWord - obtain word value from memory location +* +* This function issues the 'move' instruction to read a word from the specified +* memory address. +* +* RETURNS: the word read from the specified memory address +* +* NOMANUAL +*/ + +static inline uint16_t inWord(uint32_t addr) +{ + return *((volatile uint16_t *)addr); +} + +/* + * Device drivers utilize the macros PLB_LONG_REG_WRITE() and + * PLB_LONG_REG_READ() to access longword-wide registers on the processor + * local bus (PLB), as opposed to a PCI bus, for example. Boards are + * expected to provide implementations of these macros. + */ + +#define PLB_LONG_REG_WRITE(data, address) \ + io_outLong(data, (unsigned int)address) +#define PLB_LONG_REG_READ(address) io_inLong((unsigned int)address) + +/******************************************************************************* +* +* io_outLong - output a long word to an IA-32 I/O port +* +* This function issues the 'out' instruction to write a long word to the +* specified I/O port. +* +* RETURNS: N/A +* +* NOMANUAL +*/ + +#if defined(__DCC__) +__asm volatile void io_outLong(unsigned int data, unsigned int port) +{ + % mem data, port; + !"ax", "dx" movl port, % edx movl data, % eax outl % eax, % dx +} +#elif defined(__GNUC__) +static inline void io_outLong(unsigned int data, unsigned int port) +{ + __asm__ volatile("outl %%eax, %%dx;\n\t" : : "a"(data), "d"(port)); +} +#endif + +/******************************************************************************* +* +* io_inLong - input a long word from an IA-32 I/O port +* +* This function issues the 'in' instruction to read a long word from the +* specified I/O port. +* +* RETURNS: the long read from the specified I/O port +* +* NOMANUAL +*/ + +#if defined(__DCC__) +__asm volatile unsigned long io_inLong(unsigned int port) +{ + % mem port; + !"ax", "dx" movl port, % edx inl % dx, % eax +} +#elif defined(__GNUC__) +static inline unsigned long io_inLong(unsigned int port) +{ + unsigned long retLong; + + __asm__ volatile("inl %%dx, %%eax;\n\t" : "=a"(retLong) : "d"(port)); + return retLong; +} +#endif + +/******************************************************************************* +* +* outLong - output long word to memory location +* +* RETURNS: N/A +* +* NOMANUAL +*/ + +static inline void outLong(uint32_t data, uint32_t addr) +{ + *(volatile uint32_t *)addr = data; +} + +/******************************************************************************* +* +* inLong - obtain long word value from memory location +* +* This function issues the 'move' instruction to read a word from the specified +* memory address. +* +* RETURNS: the long word read from the specified memory address +* +* NOMANUAL +*/ + +static inline uint32_t inLong(uint32_t addr) +{ + return *((volatile uint32_t *)addr); +} +#endif /* !_ASMLANGUAGE */ + +/******************************************************************************* +* +* pci_pin2irq - convert PCI interrupt PIN to IRQ +* +* The routine uses "standard design consideration" and implies that +* INTA (pin 1) -> IRQ 16 +* INTB (pin 2) -> IRQ 17 +* INTC (pin 3) -> IRQ 18 +* INTD (pin 4) -> IRQ 19 +* +* RETURNS: IRQ number, -1 if the result is incorrect +* +*/ + +static inline int pci_pin2irq(int pin) +{ + if ((pin < PCI_INTA) || (pin > PCI_INTD)) + return -1; + return N_PIC_IRQS + pin - 1; +} + +/******************************************************************************* +* +* pci_irq2pin - convert IRQ to PCI interrupt pin +* +* RETURNS: pin number, -1 if the result is incorrect +* +*/ + +static inline int pci_irq2pin(int irq) +{ + if ((irq < N_PIC_IRQS) || (irq > N_PIC_IRQS + PCI_INTD - 1)) + return -1; + return irq - N_PIC_IRQS + 1; +} + +extern void _SysIntVecProgram(unsigned int vector, unsigned int); + +#endif /* __INCboardh */ diff --git a/arch/x86/quark/defs.objs b/arch/x86/quark/defs.objs new file mode 100644 index 00000000000..fb65efa3690 --- /dev/null +++ b/arch/x86/quark/defs.objs @@ -0,0 +1,80 @@ +# defs.objs - build system + +# +# Copyright (c) 2015 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors +# may be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. +# + +bsp_INCLUDE_DIR = $(strip \ + ${vBASE}/kernel/common/bsp \ + ${vBASE}/arch/${vARCH} \ + ${vBASE}/include/bsp \ + ${vBASE}/include \ + ${vBASE}/drivers \ + ${vBSP_BASE_DIR}/${vBSP} \ +) + +bsp_kernel_SRC = $(strip \ + arch/${vARCH}/bsp/crt0.s \ + arch/${vARCH}/bsp/cache.c \ + arch/${vARCH}/bsp/cache_s.s \ + arch/${vARCH}/bsp/rand32.c \ + kernel/common/bsp/init.c \ + kernel/common/bsp/ctors.c \ + arch/${vARCH}/bsp/sysFatalErrorHandler.c \ +) + +bsp_drivers_SRC = $(strip \ + arch/${vARCH}/timer/hpet.c \ + arch/${vARCH}/interrupt_controller/ioApicIntr.c \ + arch/${vARCH}/interrupt_controller/loApicIntr.c \ + drivers/serial/ns16550.c \ + drivers/console/uart_console.c \ + drivers/pci/pci_config.c \ + drivers/pci/pci_interface.c \ + drivers/pci/pci.c \ +) + +ifeq (${CONFIG_MICROKERNEL},y) + bsp_kernel_SRC += $(strip \ + ) +endif + +bsp_platform_SRC = $(strip \ + arch/${vARCH}/bsp/systemApic.c \ + arch/${vARCH}/bsp/driver_static_irq_stubs.s \ +) + +bsp_SRC = $(strip \ + ${vBSP_BASE_DIR}/${vBSP}/system.c \ + $(addprefix ${vBASE}/,${bsp_kernel_SRC}) \ + $(addprefix ${vBASE}/,${bsp_drivers_SRC}) \ + $(addprefix ${vBASE}/,${bsp_platform_SRC}) \ +) + +KLIBS += bsp diff --git a/arch/x86/quark/linker.cmd b/arch/x86/quark/linker.cmd new file mode 100644 index 00000000000..e1bdaed9b1e --- /dev/null +++ b/arch/x86/quark/linker.cmd @@ -0,0 +1,75 @@ +/* linker.cmd - Linker command/script file */ + +/* + * Copyright (c) 2011-2014, Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This is the linker script for both standard images and XIP images. +*/ + +#include + +/* physical address where the kernel is loaded */ +#define PHYS_LOAD_ADDR CONFIG_PHYS_LOAD_ADDR + +/* physical address of RAM */ +#ifdef CONFIG_XIP + #define PHYS_RAM_ADDR 0x00400000 +#else /* !CONFIG_XIP */ + #define PHYS_RAM_ADDR PHYS_LOAD_ADDR +#endif /* CONFIG_XIP */ + +#define KENTRY __start + +MEMORY + { +#ifdef CONFIG_XIP + ROM (rx) : ORIGIN = PHYS_LOAD_ADDR, LENGTH = 72K + RAM (wx) : ORIGIN = PHYS_RAM_ADDR, LENGTH = 128K +#else /* !CONFIG_XIP */ + RAM (wx) : ORIGIN = PHYS_LOAD_ADDR, LENGTH = 192K +#endif /* CONFIG_XIP */ + + /* + * It doesn't matter where this region goes as it is stripped from the + * final ELF image. The address doesn't even have to be valid on the + * target. However, it shouldn't overlap any other regions. + */ + + IDT_LIST : ORIGIN = 2K, LENGTH = 2K + } + +#include + +/* start adding bsp specific linker sections here */ + +/* no sections should appear after linker-epilog.h */ +#include diff --git a/arch/x86/quark/system.c b/arch/x86/quark/system.c new file mode 100644 index 00000000000..6497d73ab62 --- /dev/null +++ b/arch/x86/quark/system.c @@ -0,0 +1,176 @@ +/* system.c - system/hardware module for the Quark BSP */ + +/* + * Copyright (c) 2013-2015, Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This module provides routines to initialize and support board-level hardware +for the Quark BSP. + +Implementation Remarks: +Handlers for the secondary serial port have not been added. +*/ + +#include +#include +#include +#include +#include +#include "board.h" +#include +#include +#include +#include + +#define PCI_CLASS_COMM_CTLR 0x07 + +#if defined(CONFIG_PRINTK) || defined(CONFIG_STDOUT_CONSOLE) +#define DO_CONSOLE_INIT +#endif + + + +/******************************************************************************* + * + * _SysPciMap - maps PCI memory region + * + * This routine is defined in the BSP as the memory layout of the board is + * board specific. However, the prototype is located in pci.h. + * + * RETURNS: virtual address + * + */ + +uint32_t _SysPciMap(uint32_t addr, uint32_t size) +{ + ARG_UNUSED(size); + return addr; +} + +#if defined(DO_CONSOLE_INIT) + +/******************************************************************************* +* +* uartGenericInfoInit - initialize initialization information for one UART +* +* RETURNS: N/A +* +*/ + +static void uartGenericInfoInit(struct uart_init_info *p_info) +{ + p_info->options = 0; + p_info->sys_clk_freq = UART_XTAL_FREQ; + p_info->baud_rate = CONFIG_UART_BAUDRATE; +} + +#endif /* DO_CONSOLE_INIT */ + +#if defined(DO_CONSOLE_INIT) + +/******************************************************************************* +* +* consoleInit - initialize target-only console +* +* Only used for debugging. +* +* RETURNS: N/A +* +*/ + +#include + +static void consoleInit(void) +{ + struct uart_init_info info; + uint32_t addr; + uint32_t size; + int irq; + + uartGenericInfoInit(&info); + + /* + * Even though, pci_dev_find() returns an error if the device isn't found, + * we + * ignore it as an error means that the class and/or index supplied is + * incorrect. The serial device *SHOULD* be found. + */ + __ASSERT_EVAL((void)pci_dev_find(PCI_CLASS_COMM_CTLR, + CONFIG_UART_CONSOLE_PCI_IDX, + &addr, + &size, + &irq), + int res = pci_dev_find(PCI_CLASS_COMM_CTLR, + CONFIG_UART_CONSOLE_PCI_IDX, + &addr, + &size, + &irq), + res != -1, + ""); + + info.regs = _SysPciMap(addr, size); + + uart_init(CONFIG_UART_CONSOLE_INDEX, &info); + uartConsoleInit(); +} + +#else +#define consoleInit() \ + do {/* nothing */ \ + } while ((0)) +#endif /* DO_CONSOLE_INIT */ + +/******************************************************************************* +* +* _InitHardware - perform basic hardware initialization +* +* Initialize the Intel LOAPIC and IOAPIC device driver and the +* Intel 8250 UART device driver. +* Also initialize the timer device driver, if required. +* +* RETURNS: N/A +*/ + +void _InitHardware(void) +{ + _loapic_init(); + _ioapic_init(); + + _ioapic_irq_set(HPET_TIMER0_IRQ, HPET_TIMER0_VEC, HPET_IOAPIC_FLAGS); + + pci_bus_scan(1 << PCI_CLASS_COMM_CTLR); + + consoleInit(); /* NOP if not needed */ + +#ifdef PCI_DEBUG + pci_show(); +#endif /* PCI_DEBUG */ +} diff --git a/arch/x86/task/strtask.c b/arch/x86/task/strtask.c new file mode 100644 index 00000000000..e52484c881d --- /dev/null +++ b/arch/x86/task/strtask.c @@ -0,0 +1,96 @@ +/* strtask.c - Intel nanokernel APIs to start a task */ + +/* + * Copyright (c) 2010-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +Intel-specific parts of start_task(). Only FP functionality currently. +*/ + +#ifdef CONFIG_MICROKERNEL + +#include + +/* + * The following IA-32-specific task group is used for tasks that use SSE + * instructions. It is *not* formally reserved by SysGen for this purpose. + * See comments in nanocontext.c regarding the use of SSE_GROUP, and comments + * in task.h regarding task groups reserved by SysGen. + * + * This identifier corresponds to the first user-defined task group. + * It must be updated if any changes are made to the reserved groups. + */ + +#define SSE_GROUP 0x10 + +/******************************************************************************* +* +* _StartTaskArch - Intel-specifc parts of task initialization +* +* RETURNS: N/A +*/ + +void _StartTaskArch( + struct k_proc *X, /* ptr to task control block */ + unsigned int *pOpt /* context options container */ + ) +{ + /* + * The IA-32 nanokernel implementation uses the USE_FP bit in the + * tCCS->flags structure as a "dirty bit". The USE_FP flag bit will be + * set whenever a context uses any non-integer capability, whether it's + * just the x87 FPU capability, SSE instructions, or a combination of + * both. The USE_SSE flag bit will only be set if a context uses SSE + * instructions. + * + * However, callers of nanoFiberStart(), task_fiber_start(), or even + * _NewContext() don't need to follow the protocol used by the IA-32 + * nanokernel w.r.t. managing the tCCS->flags field. If a context + * will be utilizing just the x87 FPU capability, then the USE_FP + * option bit is specified. If a context will be utilizing SSE + * instructions (and possibly x87 FPU capability), then only the + * USE_SSE option bit needs to be specified. + * + * Likewise, the placement of tasks into "groups" doesn't need to follow + * the protocol used by the IA-32 nanokernel w.r.t. managing the + * tCCS->flags field. If a task will utilize just the x87 FPU + *capability, + * then the task only needs to be placed in the FPU_GROUP group. + * If a task utilizes SSE instructions (and possibly x87 FPU + *capability), + * then the task only needs to be placed in the SSE_GROUP group. + */ + + *pOpt |= (X->Group & SSE_GROUP) ? USE_SSE + : (X->Group & FPU_GROUP) ? USE_FP : 0; +} + +#endif /* CONFIG_MICROKERNEL */ diff --git a/arch/x86/timer/hpet.c b/arch/x86/timer/hpet.c new file mode 100644 index 00000000000..22a59e0d357 --- /dev/null +++ b/arch/x86/timer/hpet.c @@ -0,0 +1,712 @@ +/* hpet.c - Intel HPET device driver */ + +/* + * Copyright (c) 2012-2015 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This module implements a VxMicro device driver for the Intel High Precision +Event Timer (HPET) device, and provides the standard "system clock driver" +interfaces. + +The driver utilizes HPET timer0 to provide kernel ticks. + +\INTERNAL IMPLEMENTATION DETAILS +The HPET device driver makes no assumption about the initial state of the HPET, +and explicitly puts the device into a reset-like state. It also assumes that +the main up counter never wraps around to 0 during the lifetime of the system. + +The BSP can configure the HPET to use level rather than the default edge +sensitive interrupts by adding the following to board.h + #define HPET_USE_LEVEL_INTS + +When not configured to support tickless idle timer0 is programmed in periodic +mode so it automatically generates a single interrupt per kernel tick interval. + +When configured to support tickless idle timer0 is programmed in one-shot mode. +When the CPU is not idling the timer interrupt handler sets the timer to expire +when the next kernel tick is due, waits for this to occur, and then repeats +this "ad infinitum". When the CPU begins idling the timer driver reprograms +the expiry time for the timer (thereby overriding the previously scheduled +timer interrupt) and waits for the timer to expire or for a non-timer interrupt +to occur. When the CPU ceases idling the driver determines how many complete +ticks have elapsed, reprograms the timer so that it expires on the next tick, +and announces the number of elapsed ticks (if any) to the microkernel. + +In a nanokernel-only system this device driver omits more complex capabilities +(such as tickless idle support) that are only used with a microkernel. +*/ + +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_MICROKERNEL + +#include +#include + +extern struct nano_stack K_Args; + +#ifdef CONFIG_TICKLESS_IDLE +#define TIMER_SUPPORTS_TICKLESS +#endif + +#endif /* CONFIG_NANOKERNEL */ + +/* + * A board support package's board.h header must provide definitions for the + * following constants: + * + * HPET_BASE_ADRS + * HPET_CLOCK_FREQ + * HPET_TIMER0_IRQ + * HPET_TIMER0_INT_PRI + */ + +#include + +/* defines */ + +/* HPET register offsets */ + +#define GENERAL_CAPS_REG 0 /* 64-bit register */ +#define GENERAL_CONFIG_REG 0x10 /* 64-bit register */ +#define GENERAL_INT_STATUS_REG 0x20 /* 64-bit register */ +#define MAIN_COUNTER_VALUE_REG 0xf0 /* 64-bit register */ + +#define TIMER0_CONFIG_CAPS_REG 0x100 /* 64-bit register */ +#define TIMER0_COMPARATOR_REG 0x108 /* 64-bit register */ +#define TIMER0_FSB_INT_ROUTE_REG 0x110 /* 64-bit register */ + +/* read the GENERAL_CAPS_REG to determine # of timers actually implemented */ + +#define TIMER1_CONFIG_CAP_REG 0x120 /* 64-bit register */ +#define TIMER1_COMPARATOR_REG 0x128 /* 64-bit register */ +#define TIMER1_FSB_INT_ROUTE_REG 0x130 /* 64-bit register */ + +#define TIMER2_CONFIG_CAP_REG 0x140 /* 64-bit register */ +#define TIMER2_COMPARATOR_REG 0x148 /* 64-bit register */ +#define TIMER2_FSB_INT_ROUTE_REG 0x150 /* 64-bit register */ + +/* convenience macros for accessing specific HPET registers */ + +#define _HPET_GENERAL_CAPS \ + ((volatile uint64_t *)(HPET_BASE_ADRS + GENERAL_CAPS_REG)) + +/* + * Although the general configuration register is 64-bits, only a 32-bit access + * is performed since the most significant bits contain no useful information. + */ + +#define _HPET_GENERAL_CONFIG \ + ((volatile uint32_t *)(HPET_BASE_ADRS + GENERAL_CONFIG_REG)) + +/* + * Although the general interrupt status is 64-bits, only a 32-bit access + * is performed since this driver only utilizes timer0 + * (i.e. there is no need to determine the interrupt status of other timers). + */ + +#define _HPET_GENERAL_INT_STATUS \ + ((volatile uint32_t *)(HPET_BASE_ADRS + GENERAL_INT_STATUS_REG)) + +#define _HPET_MAIN_COUNTER_VALUE \ + ((volatile uint64_t *)(HPET_BASE_ADRS + MAIN_COUNTER_VALUE_REG)) +#define _HPET_MAIN_COUNTER_LSW \ + ((volatile uint32_t *)(HPET_BASE_ADRS + MAIN_COUNTER_VALUE_REG)) +#define _HPET_MAIN_COUNTER_MSW \ + ((volatile uint32_t *)(HPET_BASE_ADRS + MAIN_COUNTER_VALUE_REG + 0x4)) + +#define _HPET_TIMER0_CONFIG_CAPS \ + ((volatile uint64_t *)(HPET_BASE_ADRS + TIMER0_CONFIG_CAPS_REG)) +#define _HPET_TIMER0_COMPARATOR \ + ((volatile uint64_t *)(HPET_BASE_ADRS + TIMER0_COMPARATOR_REG)) +#define _HPET_TIMER0_FSB_INT_ROUTE \ + ((volatile uint64_t *)(HPET_BASE_ADRS + TIMER0_FSB_INT_ROUTE_REG)) + +/* general capabilities register macros */ + +#define HPET_COUNTER_CLK_PERIOD(caps) (caps >> 32) +#define HPET_NUM_TIMERS(caps) (((caps >> 8) & 0x1f) + 1) +#define HPET_IS64BITS(caps) (caps & 0x1000) + +/* general configuration register macros */ + +#define HPET_ENABLE_CNF (1 << 0) +#define HPET_LEGACY_RT_CNF (1 << 1) + +/* timer N configuration and capabilities register macros */ + +#define HPET_Tn_INT_ROUTE_CAP(caps) (caps > 32) +#define HPET_Tn_FSB_INT_DEL_CAP(caps) (caps & (1 << 15)) +#define HPET_Tn_FSB_EN_CNF (1 << 14) +#define HPET_Tn_INT_ROUTE_CNF_MASK (0x1f << 9) +#define HPET_Tn_INT_ROUTE_CNF_SHIFT 9 +#define HPET_Tn_32MODE_CNF (1 << 8) +#define HPET_Tn_VAL_SET_CNF (1 << 6) +#define HPET_Tn_SIZE_CAP(caps) (caps & (1 << 5)) +#define HPET_Tn_PER_INT_CAP(caps) (caps & (1 << 4)) +#define HPET_Tn_TYPE_CNF (1 << 3) +#define HPET_Tn_INT_ENB_CNF (1 << 2) +#define HPET_Tn_INT_TYPE_CNF (1 << 1) + +/* + * HPET comparator delay factor; this is the minimum value by which a new + * timer expiration setting must exceed the current main counter value when + * programming a timer in one-shot mode. Failure to allow for delays incurred + * in programming a timer may result in the HPET not generating an interrupt + * when the desired expiration time is reached. (See HPET documentation for + * a more complete description of this issue.) + * + * The value is expressed in main counter units. For example, if the HPET main + * counter increments at a rate of 19.2 MHz, this delay corresponds to 10 us + * (or about 0.1% of a system clock tick, assuming a tick rate of 100 Hz). + */ + +#define HPET_COMP_DELAY 192 + +/* locals */ +#ifdef CONFIG_DYNAMIC_INT_STUBS +static NANO_CPU_INT_STUB_DECL(_hpetIntStub); /* interrupt stub memory */ +#else /* !CONFIG_DYNAMIC_INT_STUBS */ +extern void *_hpetIntStub(void); /* interrupt stub code */ +SYS_INT_REGISTER(_hpetIntStub, HPET_TIMER0_IRQ, HPET_TIMER0_INT_PRI); +#endif /* CONFIG_DYNAMIC_INT_STUBS */ + +#ifdef CONFIG_INT_LATENCY_BENCHMARK +static uint32_t firstIntMainCountValue = 0; +static uint32_t expectedMainCountValue = 0; +#endif + +#ifdef CONFIG_INT_LATENCY_BENCHMARK +extern uint32_t _HwIntToCHandlerLatency; +#endif + +#ifdef TIMER_SUPPORTS_TICKLESS + +/* additional globals, locals, and forward declarations */ + +extern int32_t _SysIdleElapsedTicks; + +static uint32_t __noinit counterLoadValue; /* main counter units + per system tick */ +static uint64_t counterLastValue = + 0; /* counter value for most recent tick */ +static int32_t programmedTicks = + 1; /* # ticks timer is programmed for */ +static int staleIntCheck = + 0; /* is stale interrupt possible? */ + +/******************************************************************************* +* +* _hpetMainCounterAtomic - safely read the main HPET up counter +* +* This routine simulates an atomic read of the 64-bit system clock on CPUs +* that only support 32-bit memory accesses. The most significant word +* of the counter is read twice to ensure it doesn't change while the least +* significant word is being retrieved (as per HPET documentation). +* +* RETURNS: current 64-bit counter value +* +* \NOMANUAL +*/ + +static uint64_t _hpetMainCounterAtomic(void) +{ + uint32_t highBits; + uint32_t lowBits; + + do { + highBits = *_HPET_MAIN_COUNTER_MSW; + lowBits = *_HPET_MAIN_COUNTER_LSW; + } while (highBits != *_HPET_MAIN_COUNTER_MSW); + + return ((uint64_t)highBits << 32) | lowBits; +} + +#endif /* TIMER_SUPPORTS_TICKLESS */ + +/******************************************************************************* +* +* _timer_int_handler - system clock tick handler +* +* This routine handles the system clock tick interrupt. A TICK_EVENT event +* is pushed onto the microkernel stack. +* +* RETURNS: N/A +* +* \NOMANUAL +*/ + +void _timer_int_handler(void *unused) +{ + ARG_UNUSED(unused); + +#ifdef HPET_USE_LEVEL_INTS + /* Acknowledge interrupt */ + *_HPET_GENERAL_INT_STATUS = 1; +#endif + +#ifdef CONFIG_INT_LATENCY_BENCHMARK + uint32_t delta = *_HPET_MAIN_COUNTER_VALUE - expectedMainCountValue; + + if (_HwIntToCHandlerLatency > delta) { + /* keep the lowest value observed */ + _HwIntToCHandlerLatency = delta; + } + /* compute the next expected main counter value */ + expectedMainCountValue += firstIntMainCountValue; +#endif + +#ifdef CONFIG_MICROKERNEL + +#ifndef TIMER_SUPPORTS_TICKLESS + + /* + * one more tick has occurred -- don't need to do anything special since + * timer is already configured to interrupt on the following tick + */ + + nano_isr_stack_push(&K_Args, TICK_EVENT); + +#else + + /* see if interrupt was triggered while timer was being reprogrammed */ + + if (staleIntCheck) { + staleIntCheck = 0; + if (_hpetMainCounterAtomic() < *_HPET_TIMER0_COMPARATOR) { + return; /* ignore "stale" interrupt */ + } + } + + /* configure timer to expire on next tick */ + + counterLastValue = *_HPET_TIMER0_COMPARATOR; + *_HPET_TIMER0_CONFIG_CAPS |= HPET_Tn_VAL_SET_CNF; + *_HPET_TIMER0_COMPARATOR = counterLastValue + counterLoadValue; + programmedTicks = 1; + + /* + * Increment the tick because _timer_idle_exit does not account + * for the tick due to the timer interrupt itself. Also, if not in + * tickless mode, + * _SysIdleElpasedTicks will be 0. + */ + _SysIdleElapsedTicks++; + + /* + * If we transistion from 0 elapsed ticks to 1 we need to announce the + * tick + * event to the microkernel. Other cases will have already been covered + * by + * _timer_idle_exit + */ + + if (_SysIdleElapsedTicks == 1) { + nano_isr_stack_push(&K_Args, TICK_EVENT); + } + +#endif /* !TIMER_SUPPORTS_TICKLESS */ + +#else + nanoTicks++; /* increment nanokernel ticks var */ + + if (nanoTimerList) { + nanoTimerList->ticks--; + + while (nanoTimerList && (!nanoTimerList->ticks)) { + struct nano_timer *expired = nanoTimerList; + struct nano_lifo *chan = &expired->lifo; + nanoTimerList = expired->link; + nano_fiber_lifo_put(chan, expired->userData); + } + } +#endif /* CONFIG_MICROKERNEL */ +} + +#ifdef TIMER_SUPPORTS_TICKLESS + +/* + * Ensure that _timer_idle_enter() is never asked to idle for fewer than 2 + * ticks (since this might require the timer to be reprogrammed for a deadline + * too close to the current time, resulting in a missed interrupt which would + * permanently disable the tick timer) + */ + +#if (CONFIG_TICKLESS_IDLE_THRESH < 2) +#error Tickless idle threshold is too small (must be at least 2) +#endif + +/******************************************************************************* +* +* _timer_idle_enter - Place system timer into idle state +* +* Re-program the timer to enter into the idle state for the given number of +* ticks (-1 means infinite number of ticks). +* +* RETURNS: N/A +* +* \INTERNAL IMPLEMENTATION DETAILS +* Called while interrupts are locked. +*/ + +void _timer_idle_enter(int32_t ticks /* system ticks */ + ) +{ + /* + * reprogram timer to expire at the desired time (which is guaranteed + * to be at least one full tick from the current counter value) + */ + + *_HPET_TIMER0_CONFIG_CAPS |= HPET_Tn_VAL_SET_CNF; + *_HPET_TIMER0_COMPARATOR = + (ticks >= 0) ? counterLastValue + ticks * counterLoadValue + : ~(uint64_t)0; + staleIntCheck = 1; + programmedTicks = ticks; +} + +/******************************************************************************* +* +* _timer_idle_exit - Take system timer out of idle state +* +* Determine how long timer has been idling and reprogram it to interrupt at the +* next tick. +* +* Note that in this routine, _SysTimerElapsedTicks must be zero because the +* ticker has done its work and consumed all the ticks. This has to be true +* otherwise idle mode wouldn't have been entered in the first place. +* +* RETURNS: N/A +* +* \INTERNAL IMPLEMENTATION DETAILS +* Called by _IntEnt() while interrupts are locked. +*/ + +void _timer_idle_exit(void) +{ + uint64_t currTime = _hpetMainCounterAtomic(); + int32_t elapsedTicks; + uint64_t counterNextValue; + + /* see if idling ended because timer expired at the desired tick */ + + if (currTime >= *_HPET_TIMER0_COMPARATOR) { + /* + * update # of ticks since last tick event was announced, + * so that this value is available to ISRs that run before the + * timer + * interrupt handler runs (which is unlikely, but could happen) + */ + + _SysIdleElapsedTicks = programmedTicks - 1; + + /* + * Announce elapsed ticks to the microkernel. Note we are + * guaranteed + * that the timer ISR will execute first before the tick event + * is + * serviced. + */ + nano_isr_stack_push(&K_Args, TICK_EVENT); + + /* timer interrupt handler reprograms the timer for the next + * tick */ + + return; + } + + /* + * idling ceased because a non-timer interrupt occurred + * + * compute how much idle time has elapsed and reprogram the timer + * to expire on the next tick; if the next tick will happen so soon + * that HPET might miss the interrupt declare that tick prematurely + * and program the timer for the tick after that + * + * note: a premature tick declaration has no significant impact on + * the microkernel, which gets informed of the correct number of elapsed + * ticks when the following tick finally occurs; however, any ISRs that + * access _SysIdleElapsedTicks to determine the current time may be + *misled + * during the (very brief) interval before the tick-in-progress finishes + * and the following tick begins + */ + + elapsedTicks = + (int32_t)((currTime - counterLastValue) / counterLoadValue); + counterLastValue += (uint64_t)elapsedTicks * counterLoadValue; + + counterNextValue = counterLastValue + counterLoadValue; + + if ((counterNextValue - currTime) <= HPET_COMP_DELAY) { + elapsedTicks++; + counterNextValue += counterLoadValue; + counterLastValue += counterLoadValue; + } + + *_HPET_TIMER0_CONFIG_CAPS |= HPET_Tn_VAL_SET_CNF; + *_HPET_TIMER0_COMPARATOR = counterNextValue; + staleIntCheck = 1; + + /* + * update # of ticks since last tick event was announced, + * so that this value is available to ISRs that run before the timer + * expires and the timer interrupt handler runs + */ + + _SysIdleElapsedTicks = elapsedTicks; + + if (_SysIdleElapsedTicks) { + /* Announce elapsed ticks to the microkernel */ + nano_isr_stack_push(&K_Args, TICK_EVENT); + } + + /* + * Any elapsed ticks have been accounted for so simply set the + * programmed + * ticks to 1 since the timer has been programmed to fire on the next + * tick + * boundary. + */ + + programmedTicks = 1; +} + +#endif /* TIMER_SUPPORTS_TICKLESS */ + +/******************************************************************************* +* +* timer_driver - initialize and enable the system clock +* +* This routine is used to program the HPET to deliver interrupts at the +* rate specified via the 'sys_clock_us_per_tick' global variable. +* +* RETURNS: N/A +*/ + +void timer_driver(int priority /* priority parameter is ignored by this driver + */ + ) +{ + uint64_t hpetClockPeriod; + uint64_t tickFempto; +#ifndef TIMER_SUPPORTS_TICKLESS + uint32_t counterLoadValue; +#endif + + ARG_UNUSED(priority); + + /* + * Initial state of HPET is unknown, so put it back in a reset-like + * state + * (i.e. set main counter to 0 and disable interrupts) + */ + + *_HPET_GENERAL_CONFIG &= ~HPET_ENABLE_CNF; + *_HPET_MAIN_COUNTER_VALUE = 0; + +/* + * Determine the comparator load value (based on a start count of 0) + * to achieve the configured tick rate. + */ + + /* + * Convert the 'sys_clock_us_per_tick' value + * from microseconds to femptoseconds + */ + + tickFempto = (uint64_t)sys_clock_us_per_tick * 1000000000; + + /* + * This driver shall read the COUNTER_CLK_PERIOD value from the general + * capabilities register rather than rely on a board.h provide macro + * (or the global variable 'sys_clock_hw_cycles_per_tick') + * to determine the frequency of clock applied to the HPET device. + */ + + /* read the clock period: units are fempto (10^-15) seconds */ + + hpetClockPeriod = HPET_COUNTER_CLK_PERIOD(*_HPET_GENERAL_CAPS); + + /* + * compute value for the comparator register to achieve + * 'sys_clock_us_per_tick' period + */ + + counterLoadValue = (uint32_t)(tickFempto / hpetClockPeriod); + + /* + * Initialize "sys_clock_hw_cycles_per_tick" + * (Note: This overrides any value that the host tools may have computed + * at build time using BSP information, such as that in the NLI file.) + */ + + sys_clock_hw_cycles_per_tick = counterLoadValue; + + /* + * Set the comparator register for timer0. The write to the comparator + * register is allowed due to setting the HPET_Tn_VAL_SET_CNF bit. + */ + + *_HPET_TIMER0_CONFIG_CAPS |= HPET_Tn_VAL_SET_CNF; + *_HPET_TIMER0_COMPARATOR = counterLoadValue; + +#ifdef CONFIG_INT_LATENCY_BENCHMARK + firstIntMainCountValue = counterLoadValue; + expectedMainCountValue = firstIntMainCountValue; +#endif + +#ifndef TIMER_SUPPORTS_TICKLESS + /* set timer0 to periodic mode, ready to expire every tick */ + + *_HPET_TIMER0_CONFIG_CAPS |= HPET_Tn_TYPE_CNF; +#else + /* set timer0 to one-shot mode, ready to expire on the first tick */ + + *_HPET_TIMER0_CONFIG_CAPS &= ~HPET_Tn_TYPE_CNF; +#endif /* !TIMER_SUPPORTS_TICKLESS */ + + /* + * Route interrupts to the I/O APIC. If HPET_Tn_INT_TYPE_CNF is set this + * means edge triggered interrupt mode is utilized; Otherwise level + * sensitive interrupts are used. + */ + + /* + * HPET timers IRQ field is 5 bits wide, and hence, can support only + * IRQ's + * up to 31. Some BSPs, however, use IRQs greater than 31. In this case + * program leaves the IRQ fields blank. + */ + + *_HPET_TIMER0_CONFIG_CAPS = +#if HPET_TIMER0_IRQ < 32 + (*_HPET_TIMER0_CONFIG_CAPS & ~HPET_Tn_INT_ROUTE_CNF_MASK) | + (HPET_TIMER0_IRQ << HPET_Tn_INT_ROUTE_CNF_SHIFT) +#else + (*_HPET_TIMER0_CONFIG_CAPS & ~HPET_Tn_INT_ROUTE_CNF_MASK) +#endif + +#ifdef HPET_USE_LEVEL_INTS + | HPET_Tn_INT_TYPE_CNF; +#else + ; +#endif + +#ifdef CONFIG_DYNAMIC_INT_STUBS + /* + * Connect specified routine/parameter to LOAPIC interrupt vector. + * The "connect" will result in the LOAPIC interrupt controller being + * programmed with the allocated vector, i.e. there is no need for + * an explicit setting of the interrupt vector in this driver. + */ + + irq_connect(HPET_TIMER0_IRQ, + HPET_TIMER0_INT_PRI, + _hpetIntHandler, + 0, + _hpetIntStub); +#else + /* + * Although the stub has already been "connected", the vector number + * still + * has to be programmed into the interrupt controller. + */ + + _SysIntVecProgram(HPET_TIMER0_VEC, HPET_TIMER0_IRQ); +#endif + +#ifdef CONFIG_MICROKERNEL + +/* timer_read() is available for microkernel libraries to call directly */ + +/* K_ticker() is the pre-defined event handler for TICK_EVENT */ + +#endif /* CONFIG_MICROKERNEL */ + + /* enable the IRQ in the interrupt controller */ + + irq_enable(HPET_TIMER0_IRQ); + + /* enable the HPET generally, and timer0 specifically */ + + *_HPET_GENERAL_CONFIG |= HPET_ENABLE_CNF; + *_HPET_TIMER0_CONFIG_CAPS |= HPET_Tn_INT_ENB_CNF; +} + +/******************************************************************************* +* +* timer_read - read the BSP timer hardware +* +* This routine returns the current time in terms of timer hardware clock cycles. +* +* RETURNS: up counter of elapsed clock cycles +* +* \INTERNAL WARNING +* If this routine is ever enhanced to return all 64 bits of the counter +* it will need to call _hpetMainCounterAtomic(). +*/ + +uint32_t timer_read(void) +{ + return (uint32_t) *_HPET_MAIN_COUNTER_VALUE; +} + +#ifdef CONFIG_SYSTEM_TIMER_DISABLE + +/******************************************************************************* +* +* timer_disable - stop announcing ticks into the kernel +* +* This routine disables the HPET so that timer interrupts are no +* longer delivered. +* +* RETURNS: N/A +*/ + +void timer_disable(void) +{ + /* + * disable the main HPET up counter and all timer interrupts; + * there is no need to lock interrupts before doing this since + * no other code alters the HPET's main configuration register + * once the driver has been initialized + */ + + *_HPET_GENERAL_CONFIG &= ~HPET_ENABLE_CNF; +} + +#endif /* CONFIG_SYSTEM_TIMER_DISABLE */ diff --git a/arch/x86/timer/loApicTimer.c b/arch/x86/timer/loApicTimer.c new file mode 100644 index 00000000000..06e912849f5 --- /dev/null +++ b/arch/x86/timer/loApicTimer.c @@ -0,0 +1,679 @@ +/* loApicTimer.c - Intel Local APIC driver */ + +/* + * Copyright (c) 2011-2015 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This module implements a VxMicro device driver for the Intel local APIC +device, and provides the standard "system clock driver" interfaces. +This library contains routines for the timer in the Intel local APIC/xAPIC +(Advanced Programmable Interrupt Controller) in P6 (PentiumPro, II, III) +and P7 (Pentium4) family processor. +The local APIC contains a 32-bit programmable timer for use by the local +processor. The time base is derived from the processor's bus clock, +divided by a value specified in the divide configuration register. +After reset, the timer is initialized to zero. +*/ + +/* includes */ + +#include +#include +#include +#include +#include +#include +#include /* LOAPIC registers */ + +#ifdef CONFIG_MICROKERNEL +#include +#include +#endif /* CONFIG_MICROKERNEL */ + +/* + * A board support package's board.h header must provide definitions for the + * following constants: + * + * LOAPIC_BASE_ADRS + * LOAPIC_TIMER_IRQ + * LOAPIC_TIMER_INT_PRI + * + * A board support package's kconf file must provide the following constants: + * CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC + */ + +#include + +/* defines */ + +/* Local APIC Timer Bits */ + +#define LOAPIC_TIMER_DIVBY_2 0x0 /* Divide by 2 */ +#define LOAPIC_TIMER_DIVBY_4 0x1 /* Divide by 4 */ +#define LOAPIC_TIMER_DIVBY_8 0x2 /* Divide by 8 */ +#define LOAPIC_TIMER_DIVBY_16 0x3 /* Divide by 16 */ +#define LOAPIC_TIMER_DIVBY_32 0x8 /* Divide by 32 */ +#define LOAPIC_TIMER_DIVBY_64 0x9 /* Divide by 64 */ +#define LOAPIC_TIMER_DIVBY_128 0xa /* Divide by 128 */ +#define LOAPIC_TIMER_DIVBY_1 0xb /* Divide by 1 */ +#define LOAPIC_TIMER_DIVBY_MASK 0xf /* mask bits */ +#define LOAPIC_TIMER_PERIODIC 0x00020000 /* Timer Mode: Periodic */ + + +#if defined(CONFIG_MICROKERNEL) && defined(CONFIG_TICKLESS_IDLE) +#define TIMER_SUPPORTS_TICKLESS +#endif /* CONFIG_MICROKERNEL && CONFIG_TICKLESS_IDLE */ + +/* Helpful macros and inlines for programming timer */ +#define _REG_TIMER ((volatile uint32_t *)(LOAPIC_BASE_ADRS + LOAPIC_TIMER)) +#define _REG_TIMER_ICR \ + ((volatile uint32_t *)(LOAPIC_BASE_ADRS + LOAPIC_TIMER_ICR)) +#define _REG_TIMER_CCR \ + ((volatile uint32_t *)(LOAPIC_BASE_ADRS + LOAPIC_TIMER_CCR)) +#define _REG_TIMER_CFG \ + ((volatile uint32_t *)(LOAPIC_BASE_ADRS + LOAPIC_TIMER_CONFIG)) + +#if defined(TIMER_SUPPORTS_TICKLESS) +#define TIMER_MODE_PERIODIC 0 +#define TIMER_MODE_PERIODIC_ENT 1 +#else /* !TIMER_SUPPORTS_TICKLESS */ +#define _loApicTimerTicklessIdleInit() \ + do {/* nothing */ \ + } while (0) +#define _loApicTimerTicklessIdleSkew() \ + do {/* nothing */ \ + } while (0) +#endif /* !TIMER_SUPPORTS_TICKLESS */ +/* globals */ + +#if defined(TIMER_SUPPORTS_TICKLESS) +extern int32_t _SysIdleElapsedTicks; +#endif /* TIMER_SUPPORTS_TICKLESS */ + +/* locals */ +#ifdef CONFIG_DYNAMIC_INT_STUBS +static NANO_CPU_INT_STUB_DECL( + _loApicTimerIntStub); /* interrupt stub memory for */ + /* irq_connect() */ +#else /* !CONFIG_DYNAMIC_INT_STUBS */ +extern void *_loApicTimerIntStub; +SYS_INT_REGISTER(_loApicTimerIntStub, LOAPIC_TIMER_IRQ, LOAPIC_TIMER_INT_PRI); +#endif /* CONFIG_DYNAMIC_INT_STUBS */ + +static uint32_t __noinit counterLoadVal; /* computed counter 0 + initial count value */ +static uint32_t accumulatedCount = 0; + +#if defined(TIMER_SUPPORTS_TICKLESS) +static uint32_t _IdleOrigCount = 0; +static uint32_t __noinit _MaxSysTicks; +static uint32_t _IdleOrigTicks = 0; +static uint32_t __noinit _MaxLoadValue; +static uint32_t __noinit _TimerIdleSkew; +static unsigned char _TimerMode = TIMER_MODE_PERIODIC; +#endif /* TIMER_SUPPORTS_TICKLESS */ + +/* externs */ + +#ifdef CONFIG_MICROKERNEL +extern struct nano_stack K_Args; +#endif /* CONFIG_MICROKERNEL */ + +/******************************************************************************* +* +* _loApicTimerPeriodic - set the timer for periodic mode +* +* This routine sets the timer for periodic mode. +* +* RETURNS: N/A +* +* \NOMANUAL +*/ + +static inline void _loApicTimerPeriodic(void) +{ + *_REG_TIMER |= LOAPIC_TIMER_PERIODIC; +} + +#if defined(TIMER_SUPPORTS_TICKLESS) || \ + defined(LOAPIC_TIMER_PERIODIC_WORKAROUND) || \ + defined(CONFIG_SYSTEM_TIMER_DISABLE) +/******************************************************************************* +* +* _loApicTimerStop - stop the timer +* +* This routine stops the timer. +* +* RETURNS: N/A +* +* \NOMANUAL +*/ + +static inline void _loApicTimerStop(void) +{ + *_REG_TIMER |= LOAPIC_MASK; +} +#endif + +#if defined(TIMER_SUPPORTS_TICKLESS) || \ + defined(LOAPIC_TIMER_PERIODIC_WORKAROUND) +/******************************************************************************* +* +* _loApicTimerStart - start the timer +* +* This routine starts the timer. +* +* RETURNS: N/A +* +* \NOMANUAL +*/ + +static inline void _loApicTimerStart(void) +{ + *_REG_TIMER &= ~LOAPIC_MASK; +} +#endif + +/******************************************************************************* +* +* _loApicTimerSetCount - set countdown value +* +* This routine sets value from which the timer will count down. +* +* RETURNS: N/A +* +* \NOMANUAL +*/ + +static inline void _loApicTimerSetCount( + uint32_t count /* count from which timer is to count down */ + ) +{ + *_REG_TIMER_ICR = count; +} + +#if defined(TIMER_SUPPORTS_TICKLESS) +/******************************************************************************* +* +* _loApicTimerOneShot - set the timer for one shot mode +* +* This routine sets the timer for one shot mode. +* +* RETURNS: N/A +* +* \NOMANUAL +*/ + +static inline void _loApicTimerOneShot(void) +{ + *_REG_TIMER &= ~LOAPIC_TIMER_PERIODIC; +} +#endif /* TIMER_SUPPORTS_TICKLESS */ + +/******************************************************************************* +* +* _loApicTimerSetDivider - set the rate at which the timer is decremented +* +* This routine sets rate at which the timer is decremented to match the +* external bus frequency. +* +* RETURNS: N/A +* +* \NOMANUAL +*/ + +static inline void _loApicTimerSetDivider(void) +{ + *_REG_TIMER_CFG = (*_REG_TIMER_CFG & ~0xf) | LOAPIC_TIMER_DIVBY_1; +} + +/******************************************************************************* +* +* _loApicTimerGetRemaining - get the value from the current count register +* +* This routine gets the value from the timer's current count register. This +* value is the 'time' remaining to decrement before the timer triggers an +* interrupt. +* +* RETURNS: N/A +* +* \NOMANUAL +*/ +static inline uint32_t _loApicTimerGetRemaining(void) +{ + return *_REG_TIMER_CCR; +} + +#if defined(TIMER_SUPPORTS_TICKLESS) +/******************************************************************************* +* +* _loApicTimerGetCount - get the value from the initial count register +* +* This routine gets the value from the initial count register. +* +* RETURNS: N/A +* +* \NOMANUAL +*/ +static inline uint32_t _loApicTimerGetCount(void) +{ + return *_REG_TIMER_ICR; +} +#endif /* TIMER_SUPPORTS_TICKLESS */ + +/******************************************************************************* +* +* _timer_int_handler - system clock tick handler +* +* This routine handles the system clock tick interrupt. A TICK_EVENT event +* is pushed onto the microkernel stack. +* +* RETURNS: N/A +*/ + +void _timer_int_handler(void *unused /* parameter is not used */ + ) +{ + ARG_UNUSED(unused); + +#ifdef TIMER_SUPPORTS_TICKLESS + if (_TimerMode == TIMER_MODE_PERIODIC_ENT) { + _loApicTimerStop(); + _loApicTimerPeriodic(); + _loApicTimerSetCount(counterLoadVal); + _loApicTimerStart(); + _TimerMode = TIMER_MODE_PERIODIC; + } + + /* + * Increment the tick because _timer_idle_exit does not account + * for the tick due to the timer interrupt itself. Also, if not in + * tickless mode, + * _SysIdleElpasedTicks will be 0. + */ + _SysIdleElapsedTicks++; + + /* accumulate total counter value */ + accumulatedCount += counterLoadVal * _SysIdleElapsedTicks; + + /* + * If we transistion from 0 elapsed ticks to 1 we need to announce the + * tick event to the microkernel. Other cases will have already been + * covered by _timer_idle_exit + */ + + if (_SysIdleElapsedTicks == 1) { + nano_isr_stack_push(&K_Args, TICK_EVENT); + } + +#else + /* accumulate total counter value */ + accumulatedCount += counterLoadVal; + +#if defined(CONFIG_MICROKERNEL) + /* announce tick into the microkernel */ + nano_isr_stack_push(&K_Args, TICK_EVENT); +#endif + +#endif /*TIMER_SUPPORTS_TICKLESS*/ + +#if defined(CONFIG_NANOKERNEL) + + nanoTicks++; /* increment nanokernel ticks var */ + + if (nanoTimerList != NULL) { + nanoTimerList->ticks--; + + while ((nanoTimerList != NULL) && (!nanoTimerList->ticks)) { + struct nano_timer *expired = nanoTimerList; + struct nano_lifo *chan = &expired->lifo; + nanoTimerList = expired->link; + nano_fiber_lifo_put(chan, expired->userData); + } + } +#endif /* CONFIG_NANOKERNEL */ + +#ifdef LOAPIC_TIMER_PERIODIC_WORKAROUND + /* + * On platforms where the LOAPIC timer periodic mode is broken, + * re-program + * the ICR register with the initial count value. This is only a + * temporary + * workaround. + */ + + _loApicTimerStop(); + _loApicTimerPeriodic(); + _loApicTimerSetCount(counterLoadVal); + _loApicTimerStart(); +#endif /* LOAPIC_TIMER_PERIODIC_WORKAROUND */ +} + +#if defined(TIMER_SUPPORTS_TICKLESS) +/******************************************************************************* +* +* _loApicTimerTicklessIdleInit - initialize the tickless idle feature +* +* This routine initializes the tickless idle feature. Note that the maximum +* number of ticks that can elapse during a "tickless idle" is limited by +* . The larger the value (the lower the tick frequency), the +* fewer elapsed ticks during a "tickless idle". Conversely, the smaller the +* value (the higher the tick frequency), the more elapsed ticks during a +* "tickless idle". +* +* RETURNS: N/A +* +* \NOMANUAL +*/ + +static void _loApicTimerTicklessIdleInit(void) +{ + _MaxSysTicks = 0xffffffff / counterLoadVal; + /* this gives a count that gives the max number of full ticks */ + _MaxLoadValue = _MaxSysTicks * counterLoadVal; +} + +/******************************************************************************* +* +* _i8253TicklessIdleSkew - calculate the skew from idle mode switching +* +* This routine calculates the skew from switching the timer in and out of idle +* mode. The typical sequence is: +* 1. Stop timer. +* 2. Load new counter value. +* 3. Set timer mode to periodic/one-shot +* 4. Start timer. +* +* RETURNS: N/A +* +* \NOMANUAL +*/ + +static void _loApicTimerTicklessIdleSkew(void) +{ + volatile uint32_t dummy; /* used to replicate the 'skew time' */ + + /* Timer must be running for this to work */ + _TimerIdleSkew = _loApicTimerGetRemaining(); + + _loApicTimerStart(); /* This is normally a stop operation */ + dummy = _loApicTimerGetRemaining(); /*_loApicTimerSetCount + (counterLoadVal);*/ + _loApicTimerPeriodic(); + _loApicTimerStart(); + _TimerMode = TIMER_MODE_PERIODIC; + + /* Down counter */ + _TimerIdleSkew -= _loApicTimerGetRemaining(); +} + +/******************************************************************************* +* +* _timer_idle_enter - Place system timer into idle state +* +* Re-program the timer to enter into the idle state for the given number of +* ticks. It is placed into one shot mode where it will fire in the number of +* ticks supplied or the maximum number of ticks that can be programmed into +* hardware. A value of -1 means inifinite number of ticks. +* +* RETURNS: N/A +*/ + +void _timer_idle_enter(int32_t ticks /* system ticks */ + ) +{ + _loApicTimerStop(); + /* + * We're being asked to have the timer fire in "ticks" from now. To + * maintain accuracy we must account for the remaining time left in the + * timer. So we read the count out of it and add it to the requested + * time out + */ + _IdleOrigCount = _loApicTimerGetRemaining() - _TimerIdleSkew; + + if ((ticks == -1) || (ticks > _MaxSysTicks)) { + /* + * We've been asked to fire the timer so far in the future that + * the + * required count value would not fit in the 32 bit counter + * register. + * Instead, we program for the maximum programmable interval + * minus one + * system tick to prevent overflow when the left over count read + * earlier + * is added. + */ + _IdleOrigCount += _MaxLoadValue - counterLoadVal; + _IdleOrigTicks = _MaxSysTicks - 1; + } else { + /* leave one tick of buffer to have to time react when coming + * back ? */ + _IdleOrigTicks = ticks - 1; + _IdleOrigCount += _IdleOrigTicks * counterLoadVal; + } + + _TimerMode = TIMER_MODE_PERIODIC_ENT; + + /* Set timer to one shot mode */ + _loApicTimerOneShot(); + _loApicTimerSetCount(_IdleOrigCount); + _loApicTimerStart(); +} + +/******************************************************************************* +* +* _timer_idle_exit - handling of tickless idle when interrupted +* +* The routine is responsible for taking the timer out of idle mode and +* generating an interrupt at the next tick interval. +* +* Note that in this routine, _SysTimerElapsedTicks must be zero because the +* ticker has done its work and consumed all the ticks. This has to be true +* otherwise idle mode wouldn't have been entered in the first place. +* +* Called in _IntEnt() +* +* RETURNS: N/A +*/ + +void _timer_idle_exit(void) +{ + uint32_t count; /* timer's current count register value */ + + _loApicTimerStop(); + + /* timer is in idle or off mode, adjust the ticks expired */ + + count = _loApicTimerGetRemaining(); + + if ((count == 0) || (count >= _IdleOrigCount)) { + /* Timer expired and/or wrapped around. Place back in periodic + * mode */ + _loApicTimerPeriodic(); + _loApicTimerSetCount(counterLoadVal); + _SysIdleElapsedTicks = _IdleOrigTicks - 1; + _TimerMode = TIMER_MODE_PERIODIC; + /* + * Announce elapsed ticks to the microkernel. Note we are + * guaranteed + * that the timer ISR will execute first before the tick event + * is + * serviced. + */ + nano_isr_stack_push(&K_Args, TICK_EVENT); + } else { + uint32_t elapsed; /* elapsed "counter time" */ + uint32_t remaining; /* remaining "counter time" */ + + elapsed = _IdleOrigCount - count; + + remaining = elapsed % counterLoadVal; + + /* switch timer to periodic mode */ + if (remaining == 0) { + _loApicTimerPeriodic(); + _loApicTimerSetCount(counterLoadVal); + _TimerMode = TIMER_MODE_PERIODIC; + } else if (count > remaining) { + /* less time remaining to the next tick than was + * programmed. Leave in one shot mode */ + _loApicTimerSetCount(remaining); + } + + _SysIdleElapsedTicks = elapsed / counterLoadVal; + + if (_SysIdleElapsedTicks) { + /* Announce elapsed ticks to the microkernel */ + nano_isr_stack_push(&K_Args, TICK_EVENT); + } + } + _loApicTimerStart(); +} +#endif /* TIMER_SUPPORTS_TICKLESS */ + +/******************************************************************************* +* +* timer_driver - initialize and enable the system clock +* +* This routine is used to program the PIT to deliver interrupts at the +* rate specified via the 'sys_clock_us_per_tick' global variable. +* +* RETURNS: N/A +*/ + +void timer_driver(int priority /* priority parameter ignored by this driver */ + ) +{ + ARG_UNUSED(priority); + + /* determine the PIT counter value (in timer clock cycles/system tick) + */ + + counterLoadVal = sys_clock_hw_cycles_per_tick - 1; + + _loApicTimerTicklessIdleInit(); + + _loApicTimerSetDivider(); + _loApicTimerSetCount(counterLoadVal); + _loApicTimerPeriodic(); + +#ifdef CONFIG_DYNAMIC_INT_STUBS + /* + * Connect specified routine/parameter to LOAPIC interrupt vector. + * The "connect" will result in the LOAPIC interrupt controller being + * programmed with the allocated vector, i.e. there is no need for + * an explicit setting of the interrupt vector in this driver. + */ + irq_connect(LOAPIC_TIMER_IRQ, + LOAPIC_TIMER_INT_PRI, + _loApicTimerIntHandler, + 0, + _loApicTimerIntStub); +#else /* !CONFIG_DYNAMIC_INT_STUBS */ + /* + * Although the stub has already been "connected", the vector number + * still + * has to be programmed into the interrupt controller. + */ + _SysIntVecProgram(LOAPIC_TIMER_VEC, LOAPIC_TIMER_IRQ); +#endif /* CONFIG_DYNAMIC_INT_STUBS */ + + _loApicTimerTicklessIdleSkew(); + +#if defined(CONFIG_MICROKERNEL) + +/* timer_read() is available for microkernel libraries to call directly */ + +/* K_ticker() is the pre-defined event handler for TICK_EVENT */ + +#endif /* CONFIG_MICROKERNEL */ + + /* Everything has been configured. It is now safe to enable the + * interrupt */ + irq_enable(LOAPIC_TIMER_IRQ); +} + +/******************************************************************************* +* +* timer_read - read the BSP timer hardware +* +* This routine returns the current time in terms of timer hardware clock cycles. +* +* RETURNS: up counter of elapsed clock cycles +*/ + +uint32_t timer_read(void) +{ + uint32_t val; /* system clock value */ + +#if !defined(TIMER_SUPPORTS_TICKLESS) + /* counter is a down counter so need to subtact from counterLoadVal */ + val = accumulatedCount - _loApicTimerGetRemaining() + counterLoadVal; +#else + /* + * counter is a down counter so need to subtact from what was programmed + * in the reload register + */ + val = accumulatedCount - _loApicTimerGetRemaining() + + _loApicTimerGetCount(); +#endif + + return val; +} + +#if defined(CONFIG_SYSTEM_TIMER_DISABLE) +/******************************************************************************* +* +* timer_disable - stop announcing ticks into the kernel +* +* This routine simply disables the LOAPIC counter such that interrupts are no +* longer delivered. +* +* RETURNS: N/A +*/ + +void timer_disable(void) +{ + unsigned int key; /* interrupt lock level */ + + key = irq_lock(); + + _loApicTimerStop(); + _loApicTimerSetCount(0); + + irq_unlock(key); + + /* disable interrupt in the interrupt controller */ + + irq_disable(LOAPIC_TIMER_IRQ); +} + +#endif /* CONFIG_SYSTEM_TIMER_DISABLE */ diff --git a/config/fsl_frdm_k64f/bsp.kconf b/config/fsl_frdm_k64f/bsp.kconf new file mode 100644 index 00000000000..e33c87e1c5c --- /dev/null +++ b/config/fsl_frdm_k64f/bsp.kconf @@ -0,0 +1,80 @@ +# bsp.kconf - Freescale FRDM-K64F BSP configuration options + +# +# Copyright (c) 2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors +# may be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. +# + +# This BSP-specific file must do the following: +# +# 1) Source the configuration fragment for the ARM CPU it uses. +# 2) Define any configuration options that are unique to this BSP. At a minimum, +# a hidden option of the form BSP_ must be defined. +# 3) Select any generic ARM architecture configuration options that apply +# to this BSP, if they are not selected by default. +# 4) Provide a default value for any generic ARM architecture +# configuration options that apply to this BSP, if no generic default value +# is defined or if the generic default value is not appropriate. + +config ATOMIC_IDLE_WFI + default y + +config NUM_IRQ_PRIO_BITS + default 4 + +config NUM_IRQS + # must be >= the highest interrupt number used + default 32 + +source "ARM_CortexM4.kconf" + +menu "fsl_frdm_k64f BSP Options" + +config BSP_FSL_FRDM_K64F + def_bool y + # omit prompt to signify a "hidden" option + select CPU_CORTEXM4 + +config NLI_CPU_FREQ_MHZ + default "120.0" + +config SYS_CLOCK_HW_CYCLES_PER_SEC + default 120000000 + +config NLI_TIMER_FREQ_MHZ + default "120.0" + +config WDOG_INIT + def_bool y + # omit prompt to signify a "hidden" option + help + This processor enables the watchdog timer with a short timeout + upon reset. Therefore, this requires that the watchdog be configured + during reset handling. + +endmenu diff --git a/config/fsl_frdm_k64f/defs.bsp b/config/fsl_frdm_k64f/defs.bsp new file mode 100644 index 00000000000..927b5e5b7ff --- /dev/null +++ b/config/fsl_frdm_k64f/defs.bsp @@ -0,0 +1,39 @@ +# defs.bsp - build system + +# +# Copyright (c) 2015 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors +# may be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. +# + +ARCH ?= arm +CPU ?= CortexM3 +DEVICE ?= CortexM3 + +# Toolchain is overridable by the project. +VXMICRO_TOOL ?= gcc + diff --git a/config/fsl_frdm_k64f/nkernel/bsp-nkernel.kconf b/config/fsl_frdm_k64f/nkernel/bsp-nkernel.kconf new file mode 100644 index 00000000000..86fc0361ccd --- /dev/null +++ b/config/fsl_frdm_k64f/nkernel/bsp-nkernel.kconf @@ -0,0 +1,34 @@ +# bsp-nkernel.kconf - nanokernel configuration options + +# +# Copyright (c) 2014-2015 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors +# may be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. +# + +comment "Configuring nanokernel for fsl_frdm_k64f" +source "nkernel.kconf" diff --git a/config/fsl_frdm_k64f/ukernel/bsp-ukernel.kconf b/config/fsl_frdm_k64f/ukernel/bsp-ukernel.kconf new file mode 100644 index 00000000000..17b460d05a0 --- /dev/null +++ b/config/fsl_frdm_k64f/ukernel/bsp-ukernel.kconf @@ -0,0 +1,34 @@ +# bsp-ukernel.kconf - microkernel configuration options + +# +# Copyright (c) 2014-2015 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors +# may be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. +# + +comment "Configuring microkernel for fsl_frdm_k64f" +source "ukernel.kconf" diff --git a/config/fsl_frdm_k64f/ukernel/config1p.vpf b/config/fsl_frdm_k64f/ukernel/config1p.vpf new file mode 100644 index 00000000000..96af3dad664 --- /dev/null +++ b/config/fsl_frdm_k64f/ukernel/config1p.vpf @@ -0,0 +1,42 @@ +% Development board : fsl_frdm_k64f +% Target processor : CortexM3 + +% +% Copyright (c) 2015 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors +% may be used to endorse or promote products derived from this software without +% specific prior written permission. +% +% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. +% + +% Warning: Saving a Viper project file (.vpf) with the +% Viper Project Manager (VPM) tool will result in any +% manually entered comments being removed, along with +% any format changes being undone. + + +% DRIVERTYPE CALL +% ================================================ + TIMERDRIVER 'timer_driver(0)' diff --git a/config/generic_pc/bsp-atom_n28xx.kconf b/config/generic_pc/bsp-atom_n28xx.kconf new file mode 100644 index 00000000000..dfc3b6d6420 --- /dev/null +++ b/config/generic_pc/bsp-atom_n28xx.kconf @@ -0,0 +1,73 @@ +# bsp.config - generic_pc BSP atom_n28xx variant configuration options + +# +# Copyright (c) 2013-2014, Wind River 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) Neither the name of Wind River Systems nor the names of its contributors +# may be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. +# + +# This BSP-specific file must do the following: +# +# 1) Define any configuration options that are unique to this BSP. At a minimum, +# a hidden option of the form BSP_ must be defined. +# 2) Select any generic Intel architecture configuration options that apply +# to this BSP, if they are not selected by default. +# 3) Provide a default value for any generic Intel architecture configuration +# options that apply to this BSP, if no generic default value is defined +# or if the generic default value is not appropriate. +# 4) Source the generic Intel architecture configuration options. + +config BSP_ATOM_N28XX + def_bool y + # omit prompt to signify a "hidden" option + select CPU_PENTIUM4 + select SHUTOFF_PIC + select IOAPIC + select LOAPIC + select LOAPIC_TIMER + select EOI_HANDLER_SUPPORTED + select BOOTLOADER_UNKNOWN + select EXTRA_SERIAL_PORT + select SERIAL_INTERRUPT_LEVEL + select CUSTOM_RANDOM_GENERATOR + +config CPU_MIGHT_SUPPORT_CLFLUSH + default y + +config PHYS_LOAD_ADDR + default 0x00100000 + +config NLI_CPU_FREQ_MHZ + default "1800.0" + +config SYS_CLOCK_HW_CYCLES_PER_SEC + default 150000000 + +config NLI_TIMER_FREQ_MHZ + default "150.0" + +source "Intel-core.kconf" diff --git a/config/generic_pc/bsp-minuteia.kconf b/config/generic_pc/bsp-minuteia.kconf new file mode 100644 index 00000000000..44b2c6c980a --- /dev/null +++ b/config/generic_pc/bsp-minuteia.kconf @@ -0,0 +1,67 @@ +# bsp.kconf - generic_pc BSP minuteia variant configuration options + +# +# Copyright (c) 2011-2014, Wind River 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) Neither the name of Wind River Systems nor the names of its contributors +# may be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. +# + +# This BSP-specific file must do the following: +# +# 1) Define any configuration options that are unique to this BSP. At a minimum, +# a hidden option of the form BSP_ must be defined. +# 2) Select any generic Intel architecture configuration options that apply +# to this BSP, if they are not selected by default. +# 3) Provide a default value for any generic Intel architecture configuration +# options that apply to this BSP, if no generic default value is defined +# or if the generic default value is not appropriate. +# 4) Source the generic Intel architecture configuration options. + +config BSP_PCMINUTEIA + def_bool y + # omit prompt to signify a "hidden" option + select CPU_MINUTEIA + select PIC + select PIT + select BOI_HANDLER_SUPPORTED + select EOI_HANDLER_SUPPORTED + select BOOTLOADER_UNKNOWN + select EXTRA_SERIAL_PORT + +config PHYS_LOAD_ADDR + default 0x00100000 + +config NLI_CPU_FREQ_MHZ + default "400.0" + +config SYS_CLOCK_HW_CYCLES_PER_SEC + default 1193180 + +config NLI_TIMER_FREQ_MHZ + default "1.19318" + +source "Intel-core.kconf" diff --git a/config/generic_pc/bsp-pentium4.kconf b/config/generic_pc/bsp-pentium4.kconf new file mode 100644 index 00000000000..be14b95aa85 --- /dev/null +++ b/config/generic_pc/bsp-pentium4.kconf @@ -0,0 +1,70 @@ +# bsp.config - generic_pc BSP pentium4 variant configuration options + +# +# Copyright (c) 2011-2014, Wind River 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) Neither the name of Wind River Systems nor the names of its contributors +# may be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. +# + +# This BSP-specific file must do the following: +# +# 1) Define any configuration options that are unique to this BSP. At a minimum, +# a hidden option of the form BSP_ must be defined. +# 2) Select any generic Intel architecture configuration options that apply +# to this BSP, if they are not selected by default. +# 3) Provide a default value for any generic Intel architecture configuration +# options that apply to this BSP, if no generic default value is defined +# or if the generic default value is not appropriate. +# 4) Source the generic Intel architecture configuration options. + +config BSP_PCPENTIUM4 + def_bool y + # omit prompt to signify a "hidden" option + select CPU_PENTIUM4 + select PIC + select PIT + select BOI_HANDLER_SUPPORTED + select EOI_HANDLER_SUPPORTED + select BOOTLOADER_UNKNOWN + select EXTRA_SERIAL_PORT + +config CPU_MIGHT_SUPPORT_CLFLUSH + default y + +config PHYS_LOAD_ADDR + default 0x00100000 + +config NLI_CPU_FREQ_MHZ + default "400.0" + +config SYS_CLOCK_HW_CYCLES_PER_SEC + default 1193180 + +config NLI_TIMER_FREQ_MHZ + default "1.19318" + +source "Intel-core.kconf" diff --git a/config/generic_pc/defs.bsp b/config/generic_pc/defs.bsp new file mode 100644 index 00000000000..b19d7a72c92 --- /dev/null +++ b/config/generic_pc/defs.bsp @@ -0,0 +1,41 @@ +# defs.bsp - build system + +# +# Copyright (c) 2015 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors +# may be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. +# + +ARCH ?= x86 +BSP_VARIANT ?= pentium4 +CPU ?= ${BSP_VARIANT} +DEVICE ?= ${CPU} + +# Toolchain is overridable by the project. +VXMICRO_TOOL ?= gcc + +RUN = qemu diff --git a/config/generic_pc/nkernel/bsp-nkernelatom_n28xx.kconf b/config/generic_pc/nkernel/bsp-nkernelatom_n28xx.kconf new file mode 100644 index 00000000000..4bc1c5d5314 --- /dev/null +++ b/config/generic_pc/nkernel/bsp-nkernelatom_n28xx.kconf @@ -0,0 +1,34 @@ +# bsp-nkernelatom_n28xx.kconf - nanokernel configuration options + +# +# Copyright (c) 2014-2015 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors +# may be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. +# + +comment "Configuring nanokernel for generic_pc (atom_n28xx variant (atom_n28xx single core)" +source "nkernel.kconf" diff --git a/config/generic_pc/nkernel/bsp-nkernelminuteia.kconf b/config/generic_pc/nkernel/bsp-nkernelminuteia.kconf new file mode 100644 index 00000000000..9e2ad47ec03 --- /dev/null +++ b/config/generic_pc/nkernel/bsp-nkernelminuteia.kconf @@ -0,0 +1,34 @@ +# bsp-nkernelminuteia.kconf - nanokernel configuration options + +# +# Copyright (c) 2014-2015 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors +# may be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. +# + +comment "Configuring nanokernel for generic_pc (minuteia variant)" +source "nkernel.kconf" diff --git a/config/generic_pc/nkernel/bsp-nkernelpentium4.kconf b/config/generic_pc/nkernel/bsp-nkernelpentium4.kconf new file mode 100644 index 00000000000..0528e007977 --- /dev/null +++ b/config/generic_pc/nkernel/bsp-nkernelpentium4.kconf @@ -0,0 +1,34 @@ +# bsp-nkernelpentium4.kconf - nanokernel configuration options + +# +# Copyright (c) 2014-2015 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors +# may be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. +# + +comment "Configuring nanokernel for generic_pc (pentium4 variant)" +source "nkernel.kconf" diff --git a/config/generic_pc/ukernel/bsp-ukernelatom_n28xx.kconf b/config/generic_pc/ukernel/bsp-ukernelatom_n28xx.kconf new file mode 100644 index 00000000000..d2d5352ef1f --- /dev/null +++ b/config/generic_pc/ukernel/bsp-ukernelatom_n28xx.kconf @@ -0,0 +1,34 @@ +# bsp-ukernelatom_n28xx.kconf - microkernel configuration options + +# +# Copyright (c) 2014-2015 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors +# may be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. +# + +comment "Configuring microkernel for generic_pc (atom_n28xx variant (atom_n28xx single core)" +source "ukernel.kconf" diff --git a/config/generic_pc/ukernel/bsp-ukernelminuteia.kconf b/config/generic_pc/ukernel/bsp-ukernelminuteia.kconf new file mode 100644 index 00000000000..35624a1412b --- /dev/null +++ b/config/generic_pc/ukernel/bsp-ukernelminuteia.kconf @@ -0,0 +1,34 @@ +# bsp-ukernelminuteia.kconf - microkernel configuration options + +# +# Copyright (c) 2014-2015 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors +# may be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. +# + +comment "Configuring microkernel for generic_pc (minuteia variant)" +source "ukernel.kconf" diff --git a/config/generic_pc/ukernel/bsp-ukernelpentium4.kconf b/config/generic_pc/ukernel/bsp-ukernelpentium4.kconf new file mode 100644 index 00000000000..c6fbfc9066a --- /dev/null +++ b/config/generic_pc/ukernel/bsp-ukernelpentium4.kconf @@ -0,0 +1,34 @@ +# bsp-ukernelpentium4.kconf - microkernel configuration options + +# +# Copyright (c) 2014-2015 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors +# may be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. +# + +comment "Configuring microkernel for generic_pc (pentium4 variant)" +source "ukernel.kconf" diff --git a/config/generic_pc/ukernel/config1p.vpf b/config/generic_pc/ukernel/config1p.vpf new file mode 100644 index 00000000000..cabb4100964 --- /dev/null +++ b/config/generic_pc/ukernel/config1p.vpf @@ -0,0 +1,41 @@ +% Development board : generic_pc +% Target processor : pentium4 + +% +% Copyright (c) 2015 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors +% may be used to endorse or promote products derived from this software without +% specific prior written permission. +% +% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. +% + +% Warning: Saving a VxMicro project file (.vpf) with the +% VxMicro Project Manager (VPM) tool will result in any +% manually entered comments being removed, along with +% any format changes being undone. + +% DRIVERTYPE CALL +% ================================================ + TIMERDRIVER 'timer_driver(0)' diff --git a/config/quark/bsp.kconf b/config/quark/bsp.kconf new file mode 100644 index 00000000000..bd27d3be6be --- /dev/null +++ b/config/quark/bsp.kconf @@ -0,0 +1,92 @@ +# bsp.kconf - Quark BSP configuration options + +# +# Copyright (c) 2011-2014, Wind River 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) Neither the name of Wind River Systems nor the names of its contributors +# may be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. +# + + +# This BSP-specific file must do the following: +# +# 1) Define any configuration options that are unique to this BSP. At a minimum, +# a hidden option of the form BSP_ must be defined. +# 2) Select any generic Intel architecture configuration options that apply +# to this BSP, if they are not selected by default. +# 3) Provide a default value for any generic Intel architecture configuration +# options that apply to this BSP, if no generic default value is defined +# or if the generic default value is not appropriate. +# 4) Source the generic Intel architecture configuration options. + +config BSP_QUARK + def_bool y + # omit prompt to signify a "hidden" option + select CPU_MINUTEIA + select IOAPIC + select HPET_TIMER + select EOI_HANDLER_SUPPORTED + select BOOTLOADER_UNKNOWN + select EXTRA_SERIAL_PORT + +config MAX_PCI_DEVS + int + prompt "Maximum number of PCI devices" + default 8 + help + This option sets the maximum number of PCI devices the BSP supports. + + +config BOOTLOADER_KEXEC + bool + prompt "VxMicro boots using Linux kexec() system call" + default n + help + This option signifies that Linux boots VxMicro using kexec system call + and utility. This method is used to boot VxMicro over the network. + +config BOOTLOADER_GRUB + bool + prompt "VxMicro boots using GRUB 2.0" + default y + depends on !BOOTLOADER_KEXEC + help + This option signifies that GRUB 2.0 is used to boot VxMicro. GRUB 2.0 + is used to boot VxMicro from SD card. + +config PHYS_LOAD_ADDR + default 0x00100000 + +config NLI_CPU_FREQ_MHZ + default "400.0" + +config SYS_CLOCK_HW_CYCLES_PER_SEC + default 25000000 + +config NLI_TIMER_FREQ_MHZ + default "25.00" + +source "Intel-core.kconf" diff --git a/config/quark/defs.bsp b/config/quark/defs.bsp new file mode 100644 index 00000000000..efccf0d8242 --- /dev/null +++ b/config/quark/defs.bsp @@ -0,0 +1,38 @@ +# defs.bsp - build system + +# +# Copyright (c) 2015 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors +# may be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. +# + +ARCH ?= x86 +CPU ?= minuteia +DEVICE ?= quark + +# Toolchain is overridable by the project. +VXMICRO_TOOL ?= gcc diff --git a/config/quark/nkernel/bsp-nkernel.kconf b/config/quark/nkernel/bsp-nkernel.kconf new file mode 100644 index 00000000000..ff587a04204 --- /dev/null +++ b/config/quark/nkernel/bsp-nkernel.kconf @@ -0,0 +1,35 @@ +# bsp-nkernel.kconf - nanokernel configuration options + +# +# Copyright (c) 2014-2015 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors +# may be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. +# + +comment "Configuring nanokernel for Quark" +source "nkernel.kconf" + diff --git a/config/quark/ukernel/bsp-ukernel.kconf b/config/quark/ukernel/bsp-ukernel.kconf new file mode 100644 index 00000000000..1b8ab38a990 --- /dev/null +++ b/config/quark/ukernel/bsp-ukernel.kconf @@ -0,0 +1,35 @@ +# bsp-ukernel.kconf - microkernel configuration options + +# +# Copyright (c) 2014-2015 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors +# may be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. +# + +comment "Configuring microkernel for Quark" +source "ukernel.kconf" + diff --git a/config/quark/ukernel/config1p.vpf b/config/quark/ukernel/config1p.vpf new file mode 100644 index 00000000000..1315cd1929b --- /dev/null +++ b/config/quark/ukernel/config1p.vpf @@ -0,0 +1,41 @@ +% Development board : Quark +% Target processor : minuteia + +% +% Copyright (c) 2015 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors +% may be used to endorse or promote products derived from this software without +% specific prior written permission. +% +% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. +% + +% Warning: Saving a VxMicro project file (.vpf) with the +% VxMicro Project Manager (VPM) tool will result in any +% manually entered comments being removed, along with +% any format changes being undone. + +% DRIVERTYPE CALL +% =============================================== + TIMERDRIVER 'timer_driver(0)' diff --git a/config/ti_lm3s6965/bsp.kconf b/config/ti_lm3s6965/bsp.kconf new file mode 100644 index 00000000000..40da491a396 --- /dev/null +++ b/config/ti_lm3s6965/bsp.kconf @@ -0,0 +1,79 @@ +# bsp.kconf - TI LM3S6965 BSP configuration options + +# +# Copyright (c) 2013-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors +# may be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. +# + +# This BSP-specific file must do the following: +# +# 1) Source the configuration fragment for the ARM CPU it uses. +# 2) Define any configuration options that are unique to this BSP. At a minimum, +# a hidden option of the form BSP_ must be defined. +# 3) Select any generic ARM architecture configuration options that apply +# to this BSP, if they are not selected by default. +# 4) Provide a default value for any generic ARM architecture +# configuration options that apply to this BSP, if no generic default value +# is defined or if the generic default value is not appropriate. + +config ATOMIC_IDLE_WFI + default n + +config NUM_IRQ_PRIO_BITS + default 3 + +config NUM_IRQS + # must be >= the highest interrupt number used + # - include the UART interrupts + default 7 + +source "ARM_CortexM3.kconf" + +menu "ti_lm3s6965 BSP Options" + +config BSP_TI_LM3S6965 + def_bool y + # omit prompt to signify a "hidden" option + select CPU_CORTEXM3 + +config BSP_TI_LM3S6965_QEMU + def_bool y + # omit prompt to signify a "hidden" option + # BSP has only been tested on QEMU, not on real hardware, so always + # assume it is used for a QEMU target. + +config NLI_CPU_FREQ_MHZ + default "12.0" + +config SYS_CLOCK_HW_CYCLES_PER_SEC + default 12000000 + +config NLI_TIMER_FREQ_MHZ + default "12" + +endmenu diff --git a/config/ti_lm3s6965/defs.bsp b/config/ti_lm3s6965/defs.bsp new file mode 100644 index 00000000000..d87fba2f5a7 --- /dev/null +++ b/config/ti_lm3s6965/defs.bsp @@ -0,0 +1,42 @@ +# defs.bsp - build system + +# +# Copyright (c) 2015 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors +# may be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. +# + +ARCH ?= arm +CPU ?= CortexM3 +DEVICE ?= CortexM3 + +# Toolchain is overridable by the project. +VXMICRO_TOOL ?= gcc + +RUN = qemu + +QEMU_MACHINE = lm3s6965evb diff --git a/config/ti_lm3s6965/nkernel/bsp-nkernel.kconf b/config/ti_lm3s6965/nkernel/bsp-nkernel.kconf new file mode 100644 index 00000000000..729c3b66277 --- /dev/null +++ b/config/ti_lm3s6965/nkernel/bsp-nkernel.kconf @@ -0,0 +1,34 @@ +# bsp-nkernel.kconf - nanokernel configuration options + +# +# Copyright (c) 2014-2015 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors +# may be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. +# + +comment "Configuring nanokernel for ti_lm3s6965" +source "nkernel.kconf" diff --git a/config/ti_lm3s6965/ukernel/bsp-ukernel.kconf b/config/ti_lm3s6965/ukernel/bsp-ukernel.kconf new file mode 100644 index 00000000000..c2495458578 --- /dev/null +++ b/config/ti_lm3s6965/ukernel/bsp-ukernel.kconf @@ -0,0 +1,34 @@ +# bsp-ukernel.kconf - microkernel configuration options + +# +# Copyright (c) 2014-2015 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors +# may be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. +# + +comment "Configuring microkernel for ti_lm3s6965" +source "ukernel.kconf" diff --git a/config/ti_lm3s6965/ukernel/config1p.vpf b/config/ti_lm3s6965/ukernel/config1p.vpf new file mode 100644 index 00000000000..1e7fe226725 --- /dev/null +++ b/config/ti_lm3s6965/ukernel/config1p.vpf @@ -0,0 +1,42 @@ +% Development board : ti_lm3s6965 +% Target processor : CortexM3 + +% +% Copyright (c) 2015 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors +% may be used to endorse or promote products derived from this software without +% specific prior written permission. +% +% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. +% + +% Warning: Saving a Viper project file (.vpf) with the +% Viper Project Manager (VPM) tool will result in any +% manually entered comments being removed, along with +% any format changes being undone. + + +% DRIVERTYPE CALL +% ================================================ + TIMERDRIVER 'timer_driver(0)' diff --git a/drivers/console/uart_console.c b/drivers/console/uart_console.c new file mode 100644 index 00000000000..162ce7f2e41 --- /dev/null +++ b/drivers/console/uart_console.c @@ -0,0 +1,120 @@ +/* uart_console.c - UART-driven console */ + +/* + * Copyright (c) 2011-2012, 2014-2015 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* + DESCRIPTION + + Serial console driver. + Hooks into the printk and fputc (for printf) modules. Poll driven. +*/ + +#include +#include + +#include +#include +#include "console/uart_console.h" +#include +#include + +#define UART CONFIG_UART_CONSOLE_INDEX +#if (UART < 0) || !(UART < CONFIG_UART_NUM_SYSTEM_PORTS) +#error UART number not within ranges (0 to CONFIG_UART_NUM_SYSTEM_PORTS-1) +#endif + +#if 0 /* NOTUSED */ +/****************************************************************************** + * + * consoleIn - get a character from UART + * + * RETURNS: the character or EOF if nothing present + */ + +static int consoleIn(void) +{ + unsigned char c; + if (uart_poll_in(UART, &c) < 0) + return EOF; + else + return (int)c; +} +#endif + +#if defined(CONFIG_PRINTK) || defined(CONFIG_STDOUT_CONSOLE) +/****************************************************************************** + * + * consoleOut - output one character to UART + * + * Outputs both line feed and carriage return in the case of a '\n'. + * + * RETURNS: The character passed as input. + */ + +static int consoleOut(int c /* character to output */ + ) +{ + uart_poll_out(UART, (unsigned char)c); + if ('\n' == c) { + uart_poll_out(UART, (unsigned char)'\r'); + } + return c; +} +#endif + +#if defined(CONFIG_STDOUT_CONSOLE) +extern void __stdout_hook_install(int (*hook)(int)); +#else +#define __stdout_hook_install(x) \ + do {/* nothing */ \ + } while ((0)) +#endif + +#if defined(CONFIG_PRINTK) +extern void __printk_hook_install(int (*fn)(int)); +#else +#define __printk_hook_install(x) \ + do {/* nothing */ \ + } while ((0)) +#endif + +/****************************************************************************** + * + * uartConsoleInit - initialize one UART as the console/debug port + * + * RETURNS: N/A + */ + +void uartConsoleInit(void) +{ + __stdout_hook_install(consoleOut); + __printk_hook_install(consoleOut); +} diff --git a/drivers/console/uart_console.h b/drivers/console/uart_console.h new file mode 100644 index 00000000000..d45b60f933f --- /dev/null +++ b/drivers/console/uart_console.h @@ -0,0 +1,48 @@ +/* uart_console.h - uart console driver */ + +/* + * Copyright (c) 2011, 2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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 _UART_CONSOLE__H_ +#define _UART_CONSOLE__H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +extern void uartConsoleInit(void); + +#ifdef __cplusplus +} +#endif + +#endif /* _UART_CONSOLE__H_ */ diff --git a/drivers/defs.objs b/drivers/defs.objs new file mode 100644 index 00000000000..8c296bceb15 --- /dev/null +++ b/drivers/defs.objs @@ -0,0 +1,40 @@ +# defs.objs - build system + +# +# Copyright (c) 2015 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors +# may be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. +# + +# there are no drivers following this model currently + +# fill in these lines when drivers are available +drv_INCLUDE_DIR = +drv_SRC = + +# uncomment this line when driver of this model become available +# KLIBS += drivers diff --git a/drivers/interrupt_controller/i8259.c b/drivers/interrupt_controller/i8259.c new file mode 100644 index 00000000000..3f4ce2bfaf1 --- /dev/null +++ b/drivers/interrupt_controller/i8259.c @@ -0,0 +1,333 @@ +/* i8259.c - Intel 8259A PIC (Programmable Interrupt Controller) driver */ + +/* + * Copyright (c) 2010-2015 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This module implements a VxMicro device driver for the Intel 8259A PIC +(Programmable Interrupt Controller). In summary, the i8259A supports +up to 8 vectored priority interrupts. Cascading up to 8 PICs allows support +of up to 64 vectored priority interrupts. This device driver assumes two +cascaded 8259A (which is the standard configuration for desktop PC platforms). + +This driver initializes the PICs to operate in fully nested mode, and +issues non-specified EOI mode (an exported routine that must be invoked +just prior to an ISR returning). + +The following is an description of "Fully Nested Mode": +In this mode, interrupt requests are ordered in priority from 0 through 7 +(0 is the highest priority). When an interrupt is acknowledged, the highest +priority request is determined and its vector is placed on the bus. +Additionally, a bit of the Interrupt Service (IS) register is set. This bit +remains set until the microprocessor issues an EOI command immediately before +returning from the interrupt service routine (ISR). While the IS bit is set, +all further interrupts of the same or lower priority are inhibited, while +higher level interrupts are allowed. The _i8259_eoi() routine is used by +the ISR to issue an EOI command. The PICs in a PC typically operate +in this mode. In this mode, while the slave PIC is being serviced by the +master PIC, the slave PIC blocks all higher priority interrupt requests. + +Non-Specific EOI: When the 8259A is operated in the Fully Nested Mode, it +can determine which IS bit to reset on EOI. When a non-specific EOI +command is issued, the 8259A will automatically reset the highest IS bit of +those that are set, since in the fully nested mode the highest IS level is +the last level acknowledged and serviced. + +*/ + +/* + * A board support package's board.h header must provide definitions for the + * following constants: + * + * PIC_REG_ADDR_INTERVAL + * PIC_MASTER_BASE_ADRS + * PIC_SLAVE_BASE_ADRS + * INT_VEC_IRQ0 + * + * ...and the following register access macros: + * + * PLB_BYTE_REG_WRITE + * PLB_BYTE_REG_READ + */ + +/* + * The _i8259_boi_master and _i8259_boi_slave functions are platform + * specific and implemented in assembler + */ + +/* includes */ + +#include +#include +#include +#include + +#include +#include + +/* defines */ + +#define OCW3_DEF 0x08 /* 3rd default control word */ +#define OCW3_PCB 0x04 /* Polling Control Bit */ +#define OCW3_ISR 0x03 /* Read in-service reg */ +#define OCW3_IRR 0x02 /* Read inter request reg */ + +/* globals */ + +#ifndef CONFIG_SHUTOFF_PIC +unsigned int _I8259SpuriousIntCount = + 0; /* track # of spurious interrupts */ + +/* + * The public interface for enabling/disabling a specific IRQ for the IA-32 + * architecture is defined as follows in arch/nanokernel/Intel/arch.h + * + * extern void irq_enable (unsigned int irq); + * extern void irq_disable (unsigned int irq); + * + * Provide the symbolic alias 'irq_enable' and 'irq_disable' + * to the Intel 8259A device driver specific routines _i8259_irq_enable() + * and _i8259_irq_disable(), respectively. + */ + +FUNC_ALIAS(_i8259_irq_enable, irq_enable, void); +FUNC_ALIAS(_i8259_irq_disable, irq_disable, void); +#endif /* CONFIG_SHUTOFF_PIC */ + +/******************************************************************************* +* +* _i8259_init - initialize the Intel 8259A PIC device driver +* +* This routine initializes the Intel 8259A PIC device driver and the device +* itself. +* +* RETURNS: N/A +*/ + +void _i8259_init(void) +{ + + /* + * Initialize the Master PIC device. + * + * Whenever a command is issued with A0=0 and D4=1, this is interpreted + * as Initialization Command Word 1 (ICW1). + * D0 = 1 (ICW4 required) + * D1 = 0 (Cascaded PIC configuration) + * D2 = X (ADI: only used in MCS-80/85 mode) + * D3 = 0 (level triggered interrupt mode: edge triggered) + * D4 = 1 (initiates initialization sequence: see above) + * D5 -> D7 = X (only used in MCS-80/85 mode) + */ + + PLB_BYTE_REG_WRITE(0x11, PIC_PORT1(PIC_MASTER_BASE_ADRS)); + + /* + * ICW2 = upper 5 bits of vector presented by 8259 during /INTA cycle + */ + + PLB_BYTE_REG_WRITE(INT_VEC_IRQ0, PIC_PORT2(PIC_MASTER_BASE_ADRS)); + + /* + * ICW3 (Master): indicate which IRQ has slave connection. On PC + * systems + * the slave PIC is connect to IRQ2. + */ + + PLB_BYTE_REG_WRITE(0x04, PIC_PORT2(PIC_MASTER_BASE_ADRS)); + + /* + * ICW4 + * D0 = 1 (Mode: 0=8085, 1=8086) + * D1 = 0 (AEOI: 1=Auto End of Interrupt, 0=Normal) + * D2 = X (Master/Slave in buffered mode: 1=Master, 0=Slave) + * D3 = 0 (Buffer mode: 0 = non-buffered mode) + * D4 = 0 (SFNM: 1= Special fully nested mode) + */ + + PLB_BYTE_REG_WRITE(0x01, PIC_PORT2(PIC_MASTER_BASE_ADRS)); + + /* + * Initialize the Slave PIC device. + */ + + PLB_BYTE_REG_WRITE(0x11, PIC_PORT1(PIC_SLAVE_BASE_ADRS)); /* ICW1 */ + PLB_BYTE_REG_WRITE(INT_VEC_IRQ0 + 8, PIC_PORT2(PIC_SLAVE_BASE_ADRS)); + PLB_BYTE_REG_WRITE(0x02, PIC_PORT2(PIC_SLAVE_BASE_ADRS)); /* ICW3 */ + PLB_BYTE_REG_WRITE(0x01, PIC_PORT2(PIC_SLAVE_BASE_ADRS)); /* ICW4 */ + + /* disable interrupts */ + + PLB_BYTE_REG_WRITE(0xfb, PIC_IMASK(PIC_MASTER_BASE_ADRS)); + PLB_BYTE_REG_WRITE(0xff, PIC_IMASK(PIC_SLAVE_BASE_ADRS)); +} + +#ifndef CONFIG_SHUTOFF_PIC +/******************************************************************************* +* +* _i8259_eoi_master - send EOI(end of interrupt) signal to the master PIC. +* +* This routine is called at the end of the interrupt handler. +* +* RETURNS: N/A +* +* ERRNO +*/ + +void _i8259_eoi_master(unsigned int irq /* IRQ number to + send EOI: unused */ + ) +{ + ARG_UNUSED(irq); + + /* no need to disable interrupts since only writing to a single port */ + + PLB_BYTE_REG_WRITE(I8259_EOI, PIC_IACK(PIC_MASTER_BASE_ADRS)); +} + +/******************************************************************************* +* +* _i8259_eoi_slave - send EOI(end of interrupt) signal to the slave PIC. +* +* This routine is called at the end of the interrupt handler in the Normal +* Fully Nested Mode. +* +* RETURNS: N/A +* +* ERRNO +*/ + +void _i8259_eoi_slave(unsigned int irq /* IRQ number to + send EOI: unused */ + ) +{ + ARG_UNUSED(irq); + + /* lock interrupts */ + + __asm__ volatile( + "pushfl;\n\t" + "cli;\n\t"); + + PLB_BYTE_REG_WRITE(I8259_EOI, PIC_IACK(PIC_SLAVE_BASE_ADRS)); + PLB_BYTE_REG_WRITE(I8259_EOI, PIC_IACK(PIC_MASTER_BASE_ADRS)); + + /* unlock interrupts */ + + __asm__ volatile("popfl;\n\t"); +} + +/******************************************************************************* +* +* __I8259IntEnable - enable/disable a specified PIC interrupt input line +* +* This routine enables or disables a specified PIC interrupt input line. To +* enable an interrupt input line, the parameter must be non-zero. +* +* The VxMicro nanokernel exports the irq_enable() and irq_disable() +* APIs (mapped to _i8259_irq_enable() and _i8259_irq_disable(), respectively). +* This function is called by _i8259_irq_enable() and _i8259_irq_disable() to +* perform the actual enabling/disabling of an IRQ to minimize footprint. +* +* RETURNS: N/A +* +* see also: _i8259_irq_disable()/_i8259_irq_enable +*/ + +static void __I8259IntEnable( + unsigned int irq, /* IRQ number to enable */ + unsigned char enable /* 0 = disable, otherwise enable */ + ) +{ + unsigned char imask; + unsigned char *picBaseAdrs; + + if (irq < 8) + picBaseAdrs = (unsigned char *)PIC_MASTER_BASE_ADRS; + else + picBaseAdrs = (unsigned char *)PIC_SLAVE_BASE_ADRS; + + /* + * BSPs that utilize this interrupt controller driver virtualize IRQs + * as follows: + * + * - IRQ0 to IRQ7 are provided by the master i8259 PIC + * - IRQ8 to IRQ15 are provided by the slave i8259 PIC + * + * Thus translate the virtualized IRQ parameter to a physical IRQ + */ + + irq %= 8; + + imask = PLB_BYTE_REG_READ(PIC_IMASK(picBaseAdrs)); + + if (enable == 0) + PLB_BYTE_REG_WRITE(imask | (1 << irq), PIC_IMASK(picBaseAdrs)); + else + PLB_BYTE_REG_WRITE(imask & ~(1 << irq), PIC_IMASK(picBaseAdrs)); + +} + +/******************************************************************************* +* +* _i8259_irq_disable - disable a specified PIC interrupt input line +* +* This routine disables a specified PIC interrupt input line. +* +* RETURNS: N/A +* +* SEE ALSO: _i8259_irq_enable() +*/ + +void _i8259_irq_disable(unsigned int irq /* IRQ number to disable */ + ) +{ + return __I8259IntEnable(irq, 0); +} + +/******************************************************************************* +* +* _i8259_irq_enable - enable a specified PIC interrupt input line +* +* This routine enables a specified PIC interrupt input line. +* +* RETURNS: N/A +* +* SEE ALSO: _i8259_irq_disable() +*/ + +void _i8259_irq_enable(unsigned int irq /* IRQ number to enable */ + ) +{ + return __I8259IntEnable(irq, 1); +} + +#endif /* CONFIG_SHUTOFF_PIC */ diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c new file mode 100644 index 00000000000..d45d9dd6c03 --- /dev/null +++ b/drivers/pci/pci.c @@ -0,0 +1,397 @@ +/* pci.c - PCI probe and information routines */ + +/* + * Copyright (c) 2013-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +Module implements routines for PCI bus initialization and query. +Note that the BSP must call pci_bus_scan() before any other PCI +API is called. + +USAGE +In order to use the driver, BSP has to define: +- Register addresses: + - PCI_CTRL_ADDR_REG; + - PCI_CTRL_DATA_REG; +- Register read/write routines: + - PLB_LONG_REG_READ() / PLB_LONG_REG_WRITE(); + - PLB_WORD_REG_READ() / PLB_WORD_REG_WRITE(); + - PLB_BYTE_REG_READ() / PLB_BYTE_REG_WRITE(); +- pci_pin2irq() - the routine that converts the PCI interrupt pin + number to IRQ number. +*/ + +#include +#include +#include +#include +#include + +#include + +#include "pci_mgr.h" +#include "pci.h" + +/* NOTE. These parameters may need to be configurable */ +#define LSPCI_MAX_BUS 256 /* maximum number of buses to scan */ +#define LSPCI_MAX_DEV 32 /* maximum number of devices to scan */ +#define LSPCI_MAX_FUNC 8 /* maximum device functions to scan */ +#define LSPCI_MAX_REG 64 /* maximum device registers to read */ + +/* Base Address Register configuration fields */ + +#define BAR_SPACE(x) ((x) & 0x00000001) + +#define BAR_TYPE(x) ((x) & 0x00000006) +#define BAR_TYPE_32BIT 0 +#define BAR_TYPE_64BIT 4 + +#define BAR_PREFETCH(x) (((x) >> 3) & 0x00000001) +#define BAR_ADDR(x) (((x) >> 4) & 0x0fffffff) + +#define BAR_IO_MASK(x) ((x) & ~0x3) +#define BAR_MEM_MASK(x) ((x) & ~0xf) + +#define MAX_BARS 6 + +static struct pci_dev_info __noinit dev_info[CONFIG_MAX_PCI_DEVS]; +static int dev_info_idx = 0; + +/******************************************************************************* +* +* pci_get_bar_config - return the configuration for the specified BAR +* +* RETURNS: 0 if BAR is implemented, -1 if not. +*/ + +static int pci_bar_config_get(uint32_t bus, + uint32_t dev, + uint32_t func, + uint32_t bar, + uint32_t *config) +{ + union pci_addr_reg pci_ctrl_addr; + uint32_t old_value; + + pci_ctrl_addr.value = 0; + pci_ctrl_addr.field.enable = 1; + pci_ctrl_addr.field.bus = bus; + pci_ctrl_addr.field.device = dev; + pci_ctrl_addr.field.func = func; + pci_ctrl_addr.field.reg = 4 + bar; + + /* save the current setting */ + + pci_read(DEFAULT_PCI_CONTROLLER, + pci_ctrl_addr, + sizeof(old_value), + &old_value); + + /* write to the BAR to see how large it is */ + pci_write(DEFAULT_PCI_CONTROLLER, + pci_ctrl_addr, + sizeof(uint32_t), + 0xffffffff); + pci_read(DEFAULT_PCI_CONTROLLER, pci_ctrl_addr, sizeof(*config), config); + + /* put back the old configuration */ + + pci_write(DEFAULT_PCI_CONTROLLER, + pci_ctrl_addr, + sizeof(old_value), + old_value); + + /* check if this BAR is implemented */ + if (*config != 0xffffffff && *config != 0) + return 0; + + /* BAR not supported */ + + return -1; +} + +/******************************************************************************* + * + * pci_bar_params_get - retrieve the I/O address and IRQ of the specified BAR + * + * RETURN: -1 on error, 0 if 32 bit BAR retrieved or 1 if 64 bit BAR retrieved + * + * NOTE: Routine does not set up parameters for 64 bit BARS, they are ignored. + * + * \NOMANUAL + */ + +static inline int pci_bar_params_get(uint32_t bus, + uint32_t dev, + uint32_t func, + uint32_t bar, + struct pci_dev_info *dev_info) +{ + static union pci_addr_reg pci_ctrl_addr; + uint32_t bar_value; + uint32_t bar_config; + uint32_t addr; + uint32_t mask; + + pci_ctrl_addr.value = 0; + pci_ctrl_addr.field.enable = 1; + pci_ctrl_addr.field.bus = bus; + pci_ctrl_addr.field.device = dev; + pci_ctrl_addr.field.func = func; + pci_ctrl_addr.field.reg = 4 + bar; + + pci_read(DEFAULT_PCI_CONTROLLER, + pci_ctrl_addr, + sizeof(bar_value), + &bar_value); + if (pci_bar_config_get(bus, dev, func, bar, &bar_config) != 0) + return -1; + + if (BAR_SPACE(bar_config) == BAR_SPACE_MEM) { + dev_info->mem_type = BAR_SPACE_MEM; + mask = ~0xf; + if (bar < 5 && BAR_TYPE(bar_config) == BAR_TYPE_64BIT) + return 1; /* 64-bit MEM */ + } else { + dev_info->mem_type = BAR_SPACE_IO; + mask = ~0x3; + } + + dev_info->addr = bar_value & mask; + + addr = bar_config & mask; + if (addr != 0) { + /* calculate the size of the BAR memory required */ + dev_info->size = 1 << (find_first_set_inline(addr) - 1); + } + + return 0; +} + +/******************************************************************************* + * + * pci_dev_scan - scan the specified PCI device for all sub functions + * + * RETURNS: N/A + */ + +static void pci_dev_scan(uint32_t bus, + uint32_t dev, + uint32_t class_mask /* bitmask, bits set for each needed + class */ + ) +{ + uint32_t func; + uint32_t pci_data; + static union pci_addr_reg pci_ctrl_addr; + static union pci_dev pci_dev_header; + int i; + int max_bars; + + if (dev_info_idx == CONFIG_MAX_PCI_DEVS) { + /* No more room in the table */ + return; + } + + /* initialise the PCI controller address register value */ + + pci_ctrl_addr.value = 0; + pci_ctrl_addr.field.enable = 1; + pci_ctrl_addr.field.bus = bus; + pci_ctrl_addr.field.device = dev; + + /* scan all the possible functions for this device */ + + for (func = 0; func < LSPCI_MAX_FUNC; func++) { + pci_ctrl_addr.field.func = func; + pci_read(DEFAULT_PCI_CONTROLLER, + pci_ctrl_addr, + sizeof(pci_data), + &pci_data); + + if (pci_data == 0xffffffff) + continue; + + /* get the PCI header from the device */ + pci_header_get( + DEFAULT_PCI_CONTROLLER, bus, dev, func, &pci_dev_header); + + /* Skip a device if it's class is not specified by the caller */ + if (!((1 << pci_dev_header.field.class) & class_mask)) + continue; + + /* Get memory and interrupt information */ + if ((pci_dev_header.field.hdr_type & 0x7f) == 1) + max_bars = 2; + else + max_bars = MAX_BARS; + for (i = 0; i < max_bars; ++i) { + /* Ignore BARs with errors and 64 bit BARs */ + if (pci_bar_params_get( + bus, dev, func, i, dev_info + dev_info_idx) != + 0) + continue; + else { + dev_info[dev_info_idx].vendor_id = + pci_dev_header.field.vendor_id; + dev_info[dev_info_idx].device_id = + pci_dev_header.field.device_id; + dev_info[dev_info_idx].class = + pci_dev_header.field.class; + dev_info[dev_info_idx].irq = pci_pin2irq( + pci_dev_header.field.interrupt_pin); + dev_info_idx++; + if (dev_info_idx == CONFIG_MAX_PCI_DEVS) { + /* No more room in the table */ + return; + } + } + } + } +} + +/******************************************************************************* + * + * pci_bus_scan - scans PCI bus for devices + * + * The routine scans the PCI bus for the devices, which classes are provided + * in the classMask argument. + * classMask is constructed as: + * (1 << class1) | (1 << class2) | ... | (1 << classN) + * + * \NOMANUAL + */ + +void pci_bus_scan(uint32_t class_mask /* bitmask, bits set for each needed class */ + ) +{ + uint32_t bus; + uint32_t dev; + union pci_addr_reg pci_ctrl_addr; + uint32_t pci_data; + + /* initialise the PCI controller address register value */ + pci_ctrl_addr.value = 0; + pci_ctrl_addr.field.enable = 1; + + /* run through the buses and devices */ + for (bus = 0; bus < LSPCI_MAX_BUS; bus++) { + for (dev = 0; (dev < LSPCI_MAX_DEV) && + (dev_info_idx < CONFIG_MAX_PCI_DEVS); + dev++) { + pci_ctrl_addr.field.bus = bus; + pci_ctrl_addr.field.device = dev; + /* try and read register zero of the first function */ + pci_read(DEFAULT_PCI_CONTROLLER, + pci_ctrl_addr, + sizeof(pci_data), + &pci_data); + + /* scan the device if we found something */ + if (pci_data != 0xffffffff) + pci_dev_scan(bus, dev, class_mask); + } + } +} + +/******************************************************************************* + * + * pci_info_get - returns list of PCI devices + * + * \NOMANUAL + */ +struct pci_dev_info *pci_info_get(void) +{ + return dev_info; +} + +/******************************************************************************* + * + * pci_dev_find - find PCI device of a specified class and specified index + * + * Routine looks through the list of detected PCI devices and if the device + * of specified and exists, sets up
, and . + * + * This function can return error if the specified device is not found. In most + * cases the device class and index are known to exist and therefore will be + * found. However, due to the somewhat dynamic nature of PCI, we allow for the + * fact the device may not be found and another attempt with different + * parameters maybe made. + * + * RETURNS: 0, if device is found, -1 otherwise + */ + +int pci_dev_find(int class, int idx, uint32_t *addr, uint32_t *size, int *irq) +{ + int i; + int j; + for (i = 0, j = 0; i < dev_info_idx; i++) { + if (dev_info[i].class != class) + continue; + + if (j == idx) { + *addr = dev_info[i].addr; + *size = dev_info[i].size; + *irq = dev_info[i].irq; + return 0; + } + j++; + } + return -1; +} + +#ifdef PCI_DEBUG +/******************************************************************************* + * + * pci_show - Show PCI devices + * + * Shows the PCI devices found. + * + * RETURNS: N/A + */ + +void pci_show(void) +{ + int i; + + printk("PCI devices:\n"); + for (i = 0; i < dev_info_idx; i++) { + printk("%X:%X class: 0x%X, %s, addrs: 0x%X-0x%X, IRQ %d\n", + dev_info[i].vendor_id, + dev_info[i].device_id, + dev_info[i].class, + (dev_info[i].mem_type == BAR_SPACE_MEM) ? "MEM" : "I/O", + (uint32_t)dev_info[i].addr, + (uint32_t)(dev_info[i].addr + dev_info[i].size - 1), + dev_info[i].irq); + } +} +#endif /* PCI_DEBUG */ diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h new file mode 100644 index 00000000000..9cfeb8ef4bc --- /dev/null +++ b/drivers/pci/pci.h @@ -0,0 +1,70 @@ +/* pci.h - PCI probe and information routines */ + +/* + * Copyright (c) 2013-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +Module declares routines of PCI bus initialization and query +*/ + +#ifndef _PCI_H_ +#define _PCI_H_ + +#undef PCI_DEBUG + +#define BAR_SPACE_MEM 0 +#define BAR_SPACE_IO 1 + +/* PCI device information */ + +struct pci_dev_info { + uint32_t addr; /* I/O or memory region address */ + uint32_t size; /* memory region size */ + int irq; + uint16_t mem_type; /* memory type: BAR_SPACE_MEM/BAR_SPACE_IO */ + uint16_t vendor_id; + uint16_t device_id; + uint16_t class; +}; + +extern void pci_bus_scan(uint32_t classMask); +extern struct pci_dev_info *pci_info_get(void); +extern int pci_dev_find(int class, + int idx, + uint32_t *addr, + uint32_t *size, + int *irq); + +#ifdef PCI_DEBUG +extern void pci_show(void); +#endif /* PCI_DEBUG */ + +#endif /* _PCI_H_ */ diff --git a/drivers/pci/pci_config.c b/drivers/pci/pci_config.c new file mode 100644 index 00000000000..259a6bc1d90 --- /dev/null +++ b/drivers/pci/pci_config.c @@ -0,0 +1,303 @@ +/* pci_config.c - PCI bus support */ + +/* + * Copyright (c) 2009-2010, 2013-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION + +This module implements the PCI config space access functions + +*/ + +/* includes */ + +#include +#include + +#include "pci_mgr.h" +#include + +#ifdef __MSIX_DEBUG__ +#include +#define _DEBUG_PRINT(fmt, args...) printk(fmt, ##args) +#else +#define _DEBUG_PRINT(fmt, args...) \ + do { \ + } while (0) +#endif + +/******************************************************************************* +* +* pci_config_out_long - write a 32bit data to pci reg in offset +* +* RETURNS: N/A +*/ +void pci_config_out_long(uint32_t bus_no, /* bus number */ + uint32_t device_no, /* device number */ + uint32_t func_no, /* function number */ + uint32_t offset, /* offset into the configuration space */ + uint32_t data /* data written to the offset */ + ) +{ + union pci_addr_reg pci_addr; + + /* create the PCI address we're going to access */ + + pci_addr.field.bus = bus_no; + pci_addr.field.device = device_no; + pci_addr.field.func = func_no; + pci_addr.field.reg = offset / 4; + pci_addr.field.offset = 0; + + /* write to the PCI controller */ + + pci_write(DEFAULT_PCI_CONTROLLER, pci_addr, sizeof(uint32_t), data); +} + +/******************************************************************************* +* +* pci_config_out_word - write a 16bit data to pci reg in offset +* +* RETURNS: N/A +*/ +void pci_config_out_word(uint32_t bus_no, /* bus number */ + uint32_t device_no, /* device number */ + uint32_t func_no, /* function number */ + uint32_t offset, /* offset into the configuration space */ + uint16_t data /* data written to the offset */ + ) +{ + union pci_addr_reg pci_addr; + + /* create the PCI address we're going to access */ + + pci_addr.field.bus = bus_no; + pci_addr.field.device = device_no; + pci_addr.field.func = func_no; + pci_addr.field.reg = offset / 4; + pci_addr.field.offset = offset & 2; + + /* write to the PCI controller */ + + pci_write(DEFAULT_PCI_CONTROLLER, pci_addr, sizeof(uint16_t), data); +} + +/******************************************************************************* +* +* pci_config_out_byte - write a 8bit data to pci reg in offset +* +* RETURNS: N/A +*/ +void pci_config_out_byte(uint32_t bus_no, /* bus number */ + uint32_t device_no, /* device number */ + uint32_t func_no, /* function number */ + uint32_t offset, /* offset into the configuration space */ + uint8_t data /* data written to the offset */ + ) +{ + union pci_addr_reg pci_addr; + + /* create the PCI address we're going to access */ + + pci_addr.field.bus = bus_no; + pci_addr.field.device = device_no; + pci_addr.field.func = func_no; + pci_addr.field.reg = offset / 4; + pci_addr.field.offset = offset % 4; + + /* write to the PCI controller */ + + pci_write(DEFAULT_PCI_CONTROLLER, pci_addr, sizeof(uint8_t), data); +} + +/******************************************************************************* +* +* pci_config_in_long - read a 32bit data from pci reg in offset +* +* RETURNS: N/A +* +*/ +void pci_config_in_long(uint32_t bus_no, /* bus number */ + uint32_t device_no, /* device number */ + uint32_t func_no, /* function number */ + uint32_t offset, /* offset into the configuration space */ + uint32_t *data /* data read from the offset */ + ) +{ + union pci_addr_reg pci_addr; + + /* create the PCI address we're going to access */ + + pci_addr.field.bus = bus_no; + pci_addr.field.device = device_no; + pci_addr.field.func = func_no; + pci_addr.field.reg = offset / 4; + pci_addr.field.offset = 0; + + /* read from the PCI controller */ + + pci_read(DEFAULT_PCI_CONTROLLER, pci_addr, sizeof(uint32_t), data); +} + +/******************************************************************************* +* +* pci_config_in_word - read in a 16bit data from a pci reg in offset +* +* RETURNS: N/A +* +*/ + +void pci_config_in_word(uint32_t bus_no, /* bus number */ + uint32_t device_no, /* device number */ + uint32_t func_no, /* function number */ + uint32_t offset, /* offset into the configuration space */ + uint16_t *data /* data read from the offset */ + ) +{ + union pci_addr_reg pci_addr; + uint32_t pci_data; + + /* create the PCI address we're going to access */ + + pci_addr.field.bus = bus_no; + pci_addr.field.device = device_no; + pci_addr.field.func = func_no; + pci_addr.field.reg = offset / 4; + pci_addr.field.offset = offset & 2; + + /* read from the PCI controller */ + + pci_read(DEFAULT_PCI_CONTROLLER, pci_addr, sizeof(uint16_t), &pci_data); + + /* return the data */ + + *data = (uint16_t)pci_data; +} + +/******************************************************************************* +* +* pci_config_in_byte - read in a 8bit data from a pci reg in offset +* +* RETURNS: N/A +* +*/ + +void pci_config_in_byte(uint32_t bus_no, /* bus number */ + uint32_t device_no, /* device number */ + uint32_t func_no, /* function number */ + uint32_t offset, /* offset into the configuration space */ + uint8_t *data /* data read from the offset */ + ) +{ + union pci_addr_reg pci_addr; + uint32_t pci_data; + + /* create the PCI address we're going to access */ + + pci_addr.field.bus = bus_no; + pci_addr.field.device = device_no; + pci_addr.field.func = func_no; + pci_addr.field.reg = offset / 4; + pci_addr.field.offset = offset % 4; + + /* read from the PCI controller */ + + pci_read(DEFAULT_PCI_CONTROLLER, pci_addr, sizeof(uint8_t), &pci_data); + + /* return the data */ + + *data = (uint8_t)pci_data; +} + +/******************************************************************************* +* +* pci_config_ext_cap_ptr_find - find extended capability in ECP linked list +* +* This routine searches for an extended capability in the linked list of +* capabilities in config space. If found, the offset of the first byte +* of the capability of interest in config space is returned via pOffset. +* +* RETURNS: 0 if Extended Capability found, -1 otherwise +* +*/ + +int pci_config_ext_cap_ptr_find( + uint8_t ext_cap_find_id, /* Extended capabilities ID to search for */ + uint32_t bus, /* PCI bus number */ + uint32_t device, /* PCI device number */ + uint32_t function, /* PCI function number */ + uint8_t *p_offset /* returned config space offset */ + ) +{ + uint16_t tmp_stat; + uint8_t tmp_offset; + uint8_t cap_offset = 0x00; + uint8_t cap_id = 0x00; + + /* Check to see if the device has any extended capabilities */ + + pci_config_in_word(bus, device, function, PCI_CFG_STATUS, &tmp_stat); + + if ((tmp_stat & PCI_STATUS_NEW_CAP) == 0) + return -1; + + /* Get the initial ECP offset and make longword aligned */ + + pci_config_in_byte(bus, device, function, PCI_CFG_CAP_PTR, &cap_offset); + cap_offset &= ~0x02; + + /* Bounds check the ECP offset */ + + if (cap_offset < 0x40) + return -1; + + /* Look for the specified Extended Cap item in the linked list */ + + while (cap_offset != 0x00) { + + /* Get the Capability ID and check */ + + pci_config_in_byte(bus, device, function, (int)cap_offset, &cap_id); + if (cap_id == ext_cap_find_id) { + *p_offset = cap_offset; + return 0; + } + + /* Get the offset to the next New Capabilities item */ + + tmp_offset = cap_offset + (uint8_t)0x01; + pci_config_in_byte( + bus, device, function, (int)tmp_offset, &cap_offset); + } + + return -1; +} + diff --git a/drivers/pci/pci_interface.c b/drivers/pci/pci_interface.c new file mode 100644 index 00000000000..5153c6d5912 --- /dev/null +++ b/drivers/pci/pci_interface.c @@ -0,0 +1,426 @@ +/* pci_interface.c - PCI bus support */ + +/* + * Copyright (c) 2009-2011, 2013-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION + +This module implements the PCI H/W access functions. + +*/ + +/* includes */ + +#include +#include + +#include "pci_mgr.h" +#include +#include + +#if (PCI_CTRL_ADDR_REG == 0) +#error "PCI_CTRL_ADDR_REG cannot be zero" +#endif + +#if (PCI_CTRL_DATA_REG == 0) +#error "PCI_CTRL_DATA_REG cannot be zero" +#endif + +/****************************************************************************** +* +* pci_ctrl_read - read a PCI controller register +* +* This routine reads the specified register from the PCI controller and +* places the data into the provided buffer. +* +* RETURNS: N/A +* +*/ + +static void pci_ctrl_read(uint32_t reg, /* PCI register to read */ + uint32_t *data, /* where to put the data */ + uint32_t size /* size of the data to read (8/16/32 bits) */ + ) +{ + /* read based on the size requested */ + + switch (size) { + /* long (32 bits) */ + case SYS_PCI_ACCESS_32BIT: + *data = PLB_LONG_REG_READ(reg); + break; + /* word (16 bits) */ + case SYS_PCI_ACCESS_16BIT: + *data = PLB_WORD_REG_READ(reg); + break; + /* byte (8 bits) */ + case SYS_PCI_ACCESS_8BIT: + *data = PLB_BYTE_REG_READ(reg); + break; + } +} + +/****************************************************************************** +* +* pci_ctrl_write - write a PCI controller register +* +* This routine writes the provided data to the specified register in the PCI +* controller. +* +* RETURNS: N/A +* +*/ + +static void pci_ctrl_write(uint32_t reg, /* PCI register to write */ + uint32_t data, /* data to write */ + uint32_t size /* size of the data to write (8/16/32 bits) + */ + ) +{ + /* write based on the size requested */ + + switch (size) { + /* long (32 bits) */ + case SYS_PCI_ACCESS_32BIT: + PLB_LONG_REG_WRITE(data, reg); + break; + /* word (16 bits) */ + case SYS_PCI_ACCESS_16BIT: + PLB_WORD_REG_WRITE(data, reg); + break; + /* byte (8 bits) */ + case SYS_PCI_ACCESS_8BIT: + PLB_BYTE_REG_WRITE(data, reg); + break; + } +} + +/****************************************************************************** +* +* pci_ctrl_data_read - read the PCI controller data register +* +* This routine reads the data register of the specified PCI controller. +* +* RETURNS: 0 or -1 +* +*/ + +static int pci_ctrl_data_read(uint32_t controller, /* controller number */ + uint32_t offset, /* offset within data region */ + uint32_t *data, /* returned data */ + uint32_t size /* size of data to read */ + ) +{ + /* we only support one controller */ + + if (controller != DEFAULT_PCI_CONTROLLER) + return (-1); + + pci_ctrl_read(PCI_CTRL_DATA_REG + offset, data, size); + + return 0; +} + +/****************************************************************************** +* +* pci_ctrl_data_write - write the PCI controller data register +* +* This routine writes the provided data to the data register of the +* specified PCI controller. +* +* RETURNS: 0 or -1 +* +*/ + +static int pci_ctrl_data_write(uint32_t controller, /* controller number */ + uint32_t offset, /* offset within address register */ + uint32_t data, /* data to write */ + uint32_t size /* size of data */ + ) +{ + /* we only support one controller */ + + if (controller != DEFAULT_PCI_CONTROLLER) + return (-1); + + pci_ctrl_write(PCI_CTRL_DATA_REG + offset, data, size); + + return 0; +} + +/****************************************************************************** +* +* pci_ctrl_addr_write - write the PCI controller address register +* +* This routine writes the provided data to the address register of the +* specified PCI controller. +* +* RETURNS: 0 or -1 +* +*/ + +static int pci_ctrl_addr_write(uint32_t controller, /* controller number */ + uint32_t offset, /* offset within address register */ + uint32_t data, /* data to write */ + uint32_t size /* size of data */ + ) +{ + /* we only support one controller */ + + if (controller != DEFAULT_PCI_CONTROLLER) + return (-1); + + pci_ctrl_write(PCI_CTRL_ADDR_REG + offset, data, size); + return 0; +} + +/******************************************************************************* +* +* pci_read - read a PCI register from a device +* +* This routine reads data from a PCI device's configuration space. The +* device and register to read is specified by the address parameter ("addr") +* and must be set appropriately by the caller. The address is defined by +* the structure type pci_addr_t and contains the following members: +* +* bus: PCI bus number (0-255) +* device: PCI device number (0-31) +* func: device function number (0-7) +* reg: device 32-bit register number to read (0-63) +* offset: offset within 32-bit register to read (0-3) +* +* The size parameter specifies the number of bytes to read from the PCI +* configuration space, valid values are 1, 2, and 4 bytes. A 32-bit value +* is always returned but it will contain only the number of bytes specified +* by the size parameter. +* +* If multiple PCI controllers are present in the system, the controller id +* can be specified in the "controller" parameter. If only one controller +* is present, the id DEFAULT_PCI_CONTROLLER can be used to denote this +* controller. +* +* Example: +* +* union pci_addr_reg addr; +* uint32_t status; +* +* addr.field.bus = 0; /@ PCI bus zero @/ +* addr.field.device = 1; /@ PCI device one @/ +* addr.field.func = 0; /@ PCI function zero @/ +* addr.field.reg = 4; /@ PCI register 4 @/ +* addr.field.offset = 0; /@ PCI register offset @/ +* +* pci_read (DEFAULT_PCI_CONTROLLER, addr, sizeof(uint16_t), &status); +* +* +* NOTE: +* Reading of PCI data must be performed as an atomic operation. It is up to +* the caller to enforce this. +* +* RETURNS: N/A +* +*/ + +void pci_read(uint32_t controller, /* PCI controller to use */ + union pci_addr_reg addr, /* PCI address to read */ + uint32_t size, /* size of data in bytes */ + uint32_t *data /* data read from device */ + ) +{ + uint32_t access_size; + uint32_t access_offset; + + /* validate the access size */ + + switch (size) { + case 1: + access_size = SYS_PCI_ACCESS_8BIT; + access_offset = addr.field.offset; + break; + case 2: + access_size = SYS_PCI_ACCESS_16BIT; + access_offset = addr.field.offset; + break; + case 4: + default: + access_size = SYS_PCI_ACCESS_32BIT; + access_offset = 0; + break; + } + + /* ensure enable has been set */ + + addr.field.enable = 1; + + /* clear the offset for the address register */ + + addr.field.offset = 0; + + /* read the data from the PCI controller */ + + pci_ctrl_addr_write( + controller, PCI_NO_OFFSET, addr.value, SYS_PCI_ACCESS_32BIT); + + pci_ctrl_data_read(controller, access_offset, data, access_size); +} + +/******************************************************************************* +* +* pci_write - write a to a PCI register +* +* This routine writes data to a PCI device's configuration space. The +* device and register to write is specified by the address parameter ("addr") +* and must be set appropriately by the caller. The address is defined by +* the structure type pci_addr_t and contains the following members: +* +* bus: PCI bus number (0-255) +* device: PCI device number (0-31) +* func: device function number (0-7) +* reg: device register number to read (0-63) +* offset: offset within 32-bit register to write (0-3) +* +* The size parameter specifies the number of bytes to write to the PCI +* configuration space, valid values are 1, 2, and 4 bytes. A 32-bit value +* is always provided but only the number of bytes specified by the size +* parameter will be written to the device. +* +* If multiple PCI controllers are present in the system, the controller id +* can be specified in the "controller" parameter. If only one controller +* is present, the id DEFAULT_PCI_CONTROLLER can be used to denote this +* controller. +* +* Example: +* +* pci_addr_t addr; +* uint32_t bar0 = 0xE0000000; +* +* addr.field.bus = 0; /@ PCI bus zero @/ +* addr.field.device = 1; /@ PCI device one @/ +* addr.field.func = 0; /@ PCI function zero @/ +* addr.field.reg = 16; /@ PCI register 16 @/ +* addr.field.offset = 0; /@ PCI register offset @/ +* +* pci_write (DEFAULT_PCI_CONTROLLER, addr, sizeof(uint32_t), bar0); +* +* NOTE: +* Writing of PCI data must be performed as an atomic operation. It is up to +* the caller to enforce this. +* +* +* RETURNS: N/A +* +*/ + +void pci_write(uint32_t controller, /* controller to use */ + union pci_addr_reg addr, /* PCI address to read */ + uint32_t size, /* size in bytes */ + uint32_t data /* data to write */ + ) +{ + uint32_t access_size; + uint32_t access_offset; + + /* validate the access size */ + + switch (size) { + case 1: + access_size = SYS_PCI_ACCESS_8BIT; + access_offset = addr.field.offset; + break; + case 2: + access_size = SYS_PCI_ACCESS_16BIT; + access_offset = addr.field.offset; + break; + case 4: + default: + access_size = SYS_PCI_ACCESS_32BIT; + access_offset = 0; + break; + } + + /* ensure enable has been set */ + + addr.field.enable = 1; + + /* clear the offset for the address register */ + + addr.field.offset = 0; + + /* write the data to the PCI controller */ + + pci_ctrl_addr_write( + controller, PCI_NO_OFFSET, addr.value, SYS_PCI_ACCESS_32BIT); + pci_ctrl_data_write(controller, access_offset, data, access_size); +} + +/******************************************************************************* +* +* pci_header_get - get the PCI header for a device +* +* This routine reads the PCI header for the specified device and puts the +* result in the supplied header structure. +* +* RETURNS: N/A +*/ + +void pci_header_get(uint32_t controller, /* controller to use */ + uint32_t bus, /* PCI bus number */ + uint32_t dev, /* PCI device number */ + uint32_t func, /* PCI function number */ + union pci_dev *pci_dev_header /* output: device header */ + ) +{ + union pci_addr_reg pci_ctrl_addr; + uint32_t i; + + /* initialise the PCI controller address register value */ + + pci_ctrl_addr.value = 0; + pci_ctrl_addr.field.enable = 1; + pci_ctrl_addr.field.bus = bus; + pci_ctrl_addr.field.device = dev; + pci_ctrl_addr.field.func = func; + + /* clear out the header */ + + k_memset((char *)pci_dev_header, sizeof(union pci_dev), 0); + + /* fill in the PCI header from the device */ + + for (i = 0; i < PCI_HEADER_WORDS; i++) { + pci_ctrl_addr.field.reg = i; + pci_read(controller, + pci_ctrl_addr, + sizeof(uint32_t), + &pci_dev_header->words.word[i]); + } +} + diff --git a/drivers/pci/pci_mgr.h b/drivers/pci/pci_mgr.h new file mode 100644 index 00000000000..f31748f7ed6 --- /dev/null +++ b/drivers/pci/pci_mgr.h @@ -0,0 +1,1649 @@ +/* pci_mgr.h - hypervisor PCI bus manager */ + +/* + * Copyright (c) 2009-2011, 2013-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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 __inc_pci_mgr_h +#define __inc_pci_mgr_h + +#ifdef __cplusplus +extern "C" { + +/* Remapped reserved C++ words */ +#define class _class + +#endif /* __cplusplus */ + +/* requests available from the PCI bus manager */ + +#define SYS_PCI_REQUEST_READ_DATA 1 +#define SYS_PCI_REQUEST_WRITE_DATA 2 +#define SYS_PCI_REQUEST_READ_ADDR 3 +#define SYS_PCI_REQUEST_WRITE_ADDR 4 + +/* requests results */ + +#define SYS_PCI_REQUEST_OK 0 +#define SYS_PCI_REQUEST_FAILED 1 + +/* data access sizes */ + +#define SYS_PCI_ACCESS_8BIT 0 +#define SYS_PCI_ACCESS_16BIT 1 +#define SYS_PCI_ACCESS_32BIT 3 + +#define PCI_MAX_ADDR_CACHE 8 /* cache up to 8 addr writes */ + +#define PCI_HEADER_WORDS 64 /* 64 32-bit words in the header */ + +#define PCI_NO_OFFSET 0 + +/* default controller to use */ + +#define DEFAULT_PCI_CONTROLLER 0 +#define NO_PCI_CONTROLLER 0xffff + +/* maximum number of controllers supported */ + +#define PCI_MAX_CONTROLLER 4 +#define PCI_MAX_MGR PCI_MAX_CONTROLLER + +/* maximum number of extended capabilities */ + +#define PCI_MAX_ECP 32 + +/* invalid pci controller */ + +#define PCI_INVALID_CONTROLLER_ID 0xffffffff + +#ifndef _ASMLANGUAGE + +/* + +PCI Address Register + +The configuration address register is a 32-bit register with the format +shown below. Bit 31 is an enable flag for determining when accesses to +the configuration data should be translated to configuration cycles. Bits +23 through 16 allow the configuration software to choose a specific PCI +bus in the system. Bits 15 through 11 select the specific device on the +PCI Bus. Bits 10 through 8 choose a specific function in a device (if the +device supports multiple functions). Bits 7 through 2 select the specific +32-bit area in the device's configuration space. + ++--------------------------------------------------------+ +| Bit 31 | Bits 30-24 | Bits 23-16 | ++------------------+------------------+------------------+ +| Enable | Reserved | Bus Number | ++--------------------------------------------------------+ + ++---------------------------------------------------------------------------+ +| Bits 15-11 | Bits 10-8 | Bits 7-2 | Bits 1-0 | ++------------------+------------------+------------------+------------------+ +| Device Number | Function Number | Register Number | 00 | ++---------------------------------------------------------------------------+ + +*/ + +union pci_addr_reg { + struct { +#ifdef _BIG_ENDIAN + uint32_t enable : 1; /* access enabled */ + uint32_t reserved1 : 7; + uint32_t bus : 8; /* PCI bus number */ + uint32_t device : 5; /* PCI device number */ + uint32_t func : 3; /* device function number */ + uint32_t reg : 6; /* config space register number */ + uint32_t offset : 2; /* offset for access data */ +#else + uint32_t offset : 2; /* offset for access data */ + uint32_t reg : 6; /* config space register number */ + uint32_t func : 3; /* device function number */ + uint32_t device : 5; /* PCI device number */ + uint32_t bus : 8; /* PCI bus number */ + uint32_t reserved1 : 7; + uint32_t enable : 1; /* access enabled */ +#endif + } field; + uint32_t value; +}; + + +/* + +PCI Extended Address Register + +The configuration address register is a 32-bit register with the format +shown below. Bit 31 is an enable flag for determining when accesses to +the configuration data should be translated to configuration cycles. Bits +23 through 16 allow the configuration software to choose a specific PCI +bus in the system. Bits 15 through 11 select the specific device on the +PCI Bus. Bits 10 through 8 choose a specific function in a device (if the +device supports multiple functions). Bits 7 through 2 select the specific +32-bit area in the device's configuration space. + ++--------------------------------------------------------+ +| Bit 31 | Bits 30-24 | Bits 23-16 | ++------------------+------------------+------------------+ +| Enable | Reserved | Bus Number | ++--------------------------------------------------------+ + ++---------------------------------------------------------------------------+ +| Bits 15-11 | Bits 10-8 | Bits 7-2 | Bits 1-0 | ++------------------+------------------+------------------+------------------+ +| Device Number | Function Number | Register Number | 00 | ++---------------------------------------------------------------------------+ + +*/ + +union pcie_addr_reg { + struct { +#ifdef _BIG_ENDIAN + uint32_t reserved1 : 4; + uint32_t bus : 8; /* PCI bus number */ + uint32_t device : 5; /* PCI device number */ + uint32_t func : 3; /* device function number */ + uint32_t reg : 10; /* config space register number */ + uint32_t reserved0 : 2; +#else + uint32_t reserved0 : 2; + uint32_t reg : 10; /* config space register number */ + uint32_t func : 3; /* device function number */ + uint32_t device : 5; /* PCI device number */ + uint32_t bus : 8; /* PCI bus number */ + uint32_t reserved1 : 4; +#endif + } field; + uint32_t value; +}; + +/* + +PCI Device Structure + +The PCI Specification defines the organization of the 256-byte Configuration +Space registers and imposes a specific template for the space. The table +below shows the layout of the 256-byte Configuration space. All PCI +compliant devices must support the Vendor ID, Device ID, Command and Status, +Revision ID, Class Code and Header Type fields. Implementation of the other +registers is optional, depending upon the devices functionality. + +The PCI devices follow little ENDIAN ordering. The lower addresses contain +the least significant portions of the field. Software to manipulate this +structure must take particular care that the endian-ordering follows the PCI +devices, not the CPUs. + +Header Type 0x00: + ++-----------------------------------------------------------------------------+ +| Register | Bits 31-24 | Bits 23-16 | Bits 15-8 | Bits 7-0 | ++----------+----------------+----------------+----------------+---------------+ +| 00 | Device ID | Vendor ID | ++----------+---------------------------------+--------------------------------+ +| 04 | Status | Command | ++----------+----------------+----------------+--------------------------------+ +| 08 | Class Code | Subclass | Register IF | Revision ID | ++----------+----------------+----------------+----------------+---------------+ +| 0C | BIST | Header type | Latency Timer |Cache Line Size| ++----------+----------------+----------------+----------------+---------------+ +| 10 | Base address #0 (BAR0) | ++----------+------------------------------------------------------------------+ +| 14 | Base address #1 (BAR1) | ++----------+------------------------------------------------------------------+ +| 18 | Base address #2 (BAR2) | ++----------+------------------------------------------------------------------+ +| 1C | Base address #3 (BAR3) | ++----------+------------------------------------------------------------------+ +| 20 | Base address #4 (BAR4) | ++----------+------------------------------------------------------------------+ +| 24 | Base address #5 (BAR5) | ++----------+------------------------------------------------------------------+ +| 28 | Cardbus CIS Pointer | ++----------+---------------------------------+--------------------------------+ +| 2C | Subsystem ID | Subsystem Vendor ID | ++----------+---------------------------------+--------------------------------+ +| 30 | Expansion ROM base address | ++----------+------------------------------------------------------------------+ +| 34 | Reserved | Capability Ptr| ++----------+------------------------------------------------------------------+ +| 38 | Reserved | ++----------+----------------+----------------+----------------+---------------+ +| 3C | Max Latency | Min Grant | Interrupt PIN | Interrupt Line| ++-----------------------------------------------------------------------------+ + + +Header Type 0x01 (PCI-to-PCI bridge): + ++-----------------------------------------------------------------------------+ +| Register | Bits 31-24 | Bits 23-16 | Bits 15-8 | Bits 7-0 | ++----------+----------------+----------------+----------------+---------------+ +| 00 | Device ID | Vendor ID | ++----------+---------------------------------+--------------------------------+ +| 04 | Status | Command | ++----------+----------------+----------------+--------------------------------+ +| 08 | Class Code | Subclass | Revision ID | ++----------+----------------+----------------+----------------+---------------+ +| 0C | BIST | Header type | Latency Timer |Cache Line Size| ++----------+----------------+----------------+----------------+---------------+ +| 10 | Base address #0 (BAR0) | ++----------+------------------------------------------------------------------+ +| 14 | Base address #1 (BAR1) | ++----------+----------------+----------------+----------------+---------------+ +| 18 | Sec Latency | Subordinate Bus| Secondary Bus | Primary Bus | ++----------+----------------+----------------+----------------+---------------+ +| 1C | Secondary Status | I/O Limit | I/O Base | ++----------+---------------------------------+----------------+---------------+ +| 20 | Memory Limit | Memory Base | ++----------+---------------------------------+--------------------------------+ +| 24 | Prefetchable Memory Limit | Prefetchable Memory Base | ++----------+---------------------------------+--------------------------------+ +| 28 | Prefetchable Base Upper 32 Bits | ++----------+------------------------------------------------------------------+ +| 2C | Prefetchable Limit Upper 32 Bits | ++----------+---------------------------------+--------------------------------+ +| 30 | I/O Limit Upper 16 Bits | I/O Base Upper 16 Bits | ++----------+---------------------------------+----------------+---------------+ +| 34 | Reserved | Capability Ptr| ++----------+--------------------------------------------------+---------------+ +| 38 | Expansion ROM base address | ++----------+------------------------------------------------------------------+ +| 3C | Bridge Control | Interrupt PIN | Interrupt Line| ++-----------------------------------------------------------------------------+ + +*/ + +union pci_dev { + + /* Header Type 0x00: standard device */ + + struct { +/* offset 00: */ +#ifdef _BIG_ENDIAN + uint32_t device_id + : 16; /* device identification */ + uint32_t vendor_id + : 16; /* vendor identification */ +#else + uint32_t vendor_id + : 16; /* vendor identification */ + uint32_t device_id + : 16; /* device identification */ +#endif + +/* offset 04: */ + +#ifdef _BIG_ENDIAN + uint32_t status : 16; /* device status */ + uint32_t command + : 16; /* device command register */ +#else + uint32_t command + : 16; /* device command register */ + uint32_t status : 16; /* device status */ +#endif + +/* offset 08: */ +#ifdef _BIG_ENDIAN + uint32_t class : 8; + uint32_t subclass : 8; + uint32_t reg_if : 8; + uint32_t revision : 8; +#else + uint32_t revision : 8; + uint32_t reg_if : 8; + uint32_t subclass : 8; + uint32_t class : 8; +#endif + +/* offset 0C: */ +#ifdef _BIG_ENDIAN + uint32_t bist : 8; + uint32_t hdr_type : 8; + uint32_t latency_timer : 8; + uint32_t cache_line : 8; +#else + uint32_t cache_line : 8; + uint32_t latency_timer : 8; + uint32_t hdr_type : 8; + uint32_t bist : 8; +#endif + + uint32_t bar0; /* offset 10: base address register 0 */ + uint32_t bar1; /* offset 14: base address register 0 */ + uint32_t bar2; /* offset 18: base address register 0 */ + uint32_t bar3; /* offset 1C: base address register 0 */ + uint32_t bar4; /* offset 20: base address register 0 */ + uint32_t bar5; /* offset 24: base address register 0 */ + uint32_t cardbus; /* offset 28: base address register 0 */ + +/* offset 2C: */ +#ifdef _BIG_ENDIAN + uint32_t subsys_id + : 16; /* subsystem identifier */ + uint32_t subvendor_id + : 16; /* subsystem vendor identifier */ +#else + uint32_t subvendor_id + : 16; /* subsystem vendor identifier */ + uint32_t subsys_id + : 16; /* subsystem identifier */ +#endif + + /* offset 30: */ + uint32_t rom_address; + +/* offset 34: */ + +#ifdef _BIG_ENDIAN + uint32_t reserved1 : 24; + uint32_t capability_ptr : 8; +#else + uint32_t capability_ptr : 8; + uint32_t reserved1 : 24; +#endif + + uint32_t reserved2; /* offset 38: */ + +/* offset 3C: */ +#ifdef _BIG_ENDIAN + uint32_t max_latency : 8; + uint32_t min_grant : 8; + uint32_t interrupt_pin + : 8; /* interrupt pin assignment */ + uint32_t interrupt_line + : 8; /* interrupt line assignment */ +#else + uint32_t interrupt_line + : 8; /* interrupt line assignment */ + uint32_t interrupt_pin + : 8; /* interrupt pin assignment */ + uint32_t min_grant : 8; + uint32_t max_latency : 8; +#endif + } field; + + /* Header Type 0x01: PCI-to-PCI bridge */ + + struct { +/* offset 00: */ +#ifdef _BIG_ENDIAN + uint32_t device_id + : 16; /* device identification */ + uint32_t vendor_id + : 16; /* vendor identification */ +#else + uint32_t vendor_id + : 16; /* vendor identification */ + uint32_t device_id + : 16; /* device identification */ +#endif + +/* offset 04: */ +#ifdef _BIG_ENDIAN + uint32_t status : 16; /* device status */ + uint32_t command + : 16; /* device command register */ +#else + uint32_t command + : 16; /* device command register */ + uint32_t status : 16; /* device status */ +#endif + +/* offset 08: */ +#ifdef _BIG_ENDIAN + uint32_t class : 8; + uint32_t subclass : 8; + uint32_t reg_if : 8; + uint32_t revision : 8; +#else + uint32_t revision : 8; + uint32_t reg_if : 8; + uint32_t subclass : 8; + uint32_t class : 8; +#endif + +/* offset 0C: */ +#ifdef _BIG_ENDIAN + uint32_t bist : 8; + uint32_t hdr_type : 8; + uint32_t latency_timer : 8; + uint32_t cache_line : 8; +#else + uint32_t cache_line : 8; + uint32_t latency_timer : 8; + uint32_t hdr_type : 8; + uint32_t bist : 8; +#endif + + uint32_t bar0; /* offset 10: base address register 0 */ + uint32_t bar1; /* offset 14: base address register 0 */ + +/* offset 18: */ +#ifdef _BIG_ENDIAN + uint32_t secondary_latency : 8; + uint32_t subord_bus : 8; + uint32_t secondary_bus : 8; + uint32_t primary_bus : 8; +#else + uint32_t primary_bus : 8; + uint32_t secondary_bus : 8; + uint32_t subord_bus : 8; + uint32_t secondary_latency : 8; + +#endif + +/* offset 1C: */ +#ifdef _BIG_ENDIAN + uint32_t secondary_status : 16; + uint32_t io_limit : 8; + uint32_t io_base : 8; +#else + uint32_t io_base : 8; + uint32_t io_limit : 8; + uint32_t secondary_status : 16; +#endif + +/* offset 20: */ +#ifdef _BIG_ENDIAN + uint32_t mem_limit : 16; + uint32_t mem_base : 16; +#else + uint32_t mem_base : 16; + uint32_t mem_limit : 16; +#endif + +/* offset 24: */ +#ifdef _BIG_ENDIAN + uint32_t pre_mem_limit : 16; + uint32_t pre_mem_base : 16; +#else + uint32_t pre_mem_base : 16; + uint32_t pre_mem_limit : 16; +#endif + + /* offset 28: */ + uint32_t pre_mem_base_upper; + + /* offset 2C: */ + uint32_t pre_mem_limit_upper; + +/* offset 30: */ +#ifdef _BIG_ENDIAN + uint32_t io_limit_upper : 16; + uint32_t io_base_upper : 16; +#else + uint32_t io_base_upper : 16; + uint32_t io_limit_upper : 16; +#endif + +/* offset 34: */ +#ifdef _BIG_ENDIAN + uint32_t reserved : 24; + uint32_t capability_ptr : 8; +#else + uint32_t capability_ptr : 8; + uint32_t reserved : 24; +#endif + + /* offset 38: */ + uint32_t rom_address; + +/* offset 3C: */ +#ifdef _BIG_ENDIAN + uint32_t bridge_control : 16; + uint32_t interrupt_pin + : 8; /* interrupt pin assignment */ + uint32_t interrupt_line + : 8; /* interrupt line assignment */ +#else + uint32_t interrupt_line + : 8; /* interrupt line assignment */ + uint32_t interrupt_pin + : 8; /* interrupt pin assignment */ + uint32_t bridge_control : 16; +#endif + + } bridge_field; + + /* direct access to each word in the PCI header */ + + struct { + uint32_t word0; /* word 0: offset 00 */ + uint32_t word1; /* word 1: offset 04 */ + uint32_t word2; /* word 2: offset 08 */ + uint32_t word3; /* word 3: offset 0C */ + uint32_t word4; /* word 4: offset 10 */ + uint32_t word5; /* word 5: offset 14 */ + uint32_t word6; /* word 6: offset 18 */ + uint32_t word7; /* word 7: offset 1C */ + uint32_t word8; /* word 8: offset 20 */ + uint32_t word9; /* word 9: offset 24 */ + uint32_t word10; /* word 10: offset 28 */ + uint32_t word11; /* word 11: offset 2C */ + uint32_t word12; /* word 12: offset 30 */ + uint32_t word13; /* word 13: offset 34 */ + uint32_t word14; /* word 14: offset 38 */ + uint32_t word15; /* word 15: offset 3C */ + } word; + + struct { + uint32_t word[PCI_HEADER_WORDS]; /* array of words for the + header */ + } words; + +}; + +/* +Generic Capability register set header: + ++-----------------------------------------------------------------------------+ +| Register | Bits 31-24 | Bits 23-16 | Bits 15-8 | Bits 7-0 | ++----------+----------------+----------------+----------------+---------------+ +| 00 | Capability specific data | Next Pointer | Cap ID | ++-----------------------------------------------------------------------------+ +*/ + +union pci_cap_hdr { + struct { + /* offset 00: */ + uint32_t id : 8; /* capability ID */ + uint32_t next_ptr + : 8; /* pointer to next capability */ + uint32_t feature + : 16; /* capability specific field */ + } field; + + uint32_t word; /* array of words for the header */ +} pci_cap_hdr_t; + +union pcie_cap_hdr { + struct { + /* offset 00: */ + uint32_t id : 16; /* capability ID */ + uint32_t version : 4; /* version */ + uint32_t next_ptr + : 12; /* pointer to next capability */ + } field; + + uint32_t word; /* array of words for the header */ +}; + +/* +MSI Capability register set (32-bit): + ++-----------------------------------------------------------------------------+ +| Register | Bits 31-24 | Bits 23-16 | Bits 15-8 | Bits 7-0 | ++----------+----------------+----------------+----------------+---------------+ +| 00 | Message Control Register | Next Pointer | Cap ID | ++----------+---------------------------------+----------------+---------------+ +| 04 | Message Address Register 0 0 | ++----------+---------------------------------+--------------------------------+ +| 0C | | Message Data Register | ++-----------------------------------------------------------------------------+ + +MSI Capability register set (64-bit): + ++-----------------------------------------------------------------------------+ +| Register | Bits 31-24 | Bits 23-16 | Bits 15-8 | Bits 7-0 | ++----------+----------------+----------------+----------------+---------------+ +| 00 | Message Control Register | Next Pointer | Cap ID | ++----------+---------------------------------+----------------+---------------+ +| 04 | Least-Significant 32-bits of Message Address Register 0 0 | ++----------+--------------------------------------------------+---------------+ +| 08 | Most-Significant 32-bits of Message Address Register | ++----------+---------------------------------+--------------------------------+ +| 0C | | Message Data Register | ++-----------------------------------------------------------------------------+ + +*/ + +struct _pci_msi_hdr { + /* common MSI header */ + union { + struct { + /* offset 00: */ + uint32_t id : 8; /* capability ID */ + uint32_t next_ptr + : 8; /* pointer to next capability */ + uint32_t enabled + : 1; /* MSI enabled */ + uint32_t msg_req + : 3; /* requested message count */ + uint32_t msg_grant + : 3; /* granted message count */ + uint32_t is_64_bit + : 1; /* 64-bit capable */ + uint32_t reserved + : 8; /* */ + } msi_cap; + + struct { + /* offset 00: */ + uint32_t id : 8; /* capability ID */ + uint32_t next_ptr + : 8; /* pointer to next capability */ + uint32_t table_size + : 11; /* MSI-x table size */ + uint32_t reserved + : 3; /* */ + uint32_t func_mask + : 1; /* 1 for vectors masked */ + uint32_t enabled + : 1; /* MSI-x enabled */ + } msix_cap; + } cap; + + union { + /* 32-bit MSI header */ + struct { + /* offset 04: */ + uint32_t addr; /* message address register */ + /* offset 08: */ + uint32_t data : 16; /* message data register + */ + uint32_t spare + : 16; /* */ + } regs32; + /* 64-bit MSI header */ + struct { + /* offset 04: */ + uint32_t + addr_low; /* message address register (lower) + */ + /* offset 08: */ + uint32_t addr_high; /* message address register + (upper) */ + /* offset 0C: */ + uint32_t data : 16; /* message data register + */ + uint32_t spare + : 16; /* */ + } regs64; + } regs; +}; + +union pci_msi_hdr { + struct _pci_msi_hdr field; /* MSI header fields */ + uint32_t word[4]; /* array of words for the header */ +}; + +extern uint32_t pci_controller_cnt; /* number of pci controllers; + * initialized to 0 until + * the controllers have been + * created */ + +struct pci_msix_table { + uint32_t msg_addr; + uint32_t msg_addr_high; + uint32_t msg_data; + uint32_t vec_ctrl; +}; + +struct pci_msix_entry { + uint32_t vector; /* guest to write a vector */ + uint16_t entry; /* driver to specify entry, guest OS writes */ +}; + +struct pci_msix_info { + uint32_t bus_no; + uint32_t dev_no; + uint32_t func_no; + uint32_t msix_vec; +}; + +/* manager interface API */ + +extern void pci_read(uint32_t controller, + union pci_addr_reg addr, + uint32_t size, + uint32_t *data); +extern void pci_write(uint32_t controller, + union pci_addr_reg addr, + uint32_t size, + uint32_t data); + +extern void pci_header_get(uint32_t controller, + uint32_t bus, + uint32_t dev, + uint32_t func, + union pci_dev *pci_dev_header); + +/* General PCI configuration access routines */ + +extern void pci_config_out_long(uint32_t bus, /* bus number */ + uint32_t dev, /* device number */ + uint32_t func, /* function number */ + uint32_t offset, /* offset into the configuration + space */ + uint32_t data /* data written to the offset */ + ); + +extern void pci_config_out_word(uint32_t bus, /* bus number */ + uint32_t dev, /* device number */ + uint32_t func, /* function number */ + uint32_t offset, /* offset into the configuration + space */ + uint16_t data /* data written to the offset */ + ); + +extern void pci_config_out_byte(uint32_t bus, /* bus number */ + uint32_t dev, /* device number */ + uint32_t func, /* function number */ + uint32_t offset, /* offset into the configuration + space */ + uint8_t data /* data written to the offset */ + ); + +extern void pci_config_in_long(uint32_t bus, /* bus number */ + uint32_t dev, /* device number */ + uint32_t func, /* function number */ + uint32_t offset, /* offset into the configuration + space */ + uint32_t *data /* return value address */ + ); + +extern void pci_config_in_word(uint32_t bus, /* bus number */ + uint32_t dev, /* device number */ + uint32_t func, /* function number */ + uint32_t offset, /* offset into the configuration + space */ + uint16_t *data /* return value address */ + ); + +extern void pci_config_in_byte(uint32_t bus, /* bus number */ + uint32_t dev, /* device number */ + uint32_t func, /* function number */ + uint32_t offset, /* offset into the configuration + space */ + uint8_t *data /* return value address */ + ); + +extern int pci_config_ext_cap_ptr_find( + uint8_t ext_cap_find_id, /* Extended capabilities ID to search for */ + uint32_t bus, /* PCI bus number */ + uint32_t device, /* PCI device number */ + uint32_t function, /* PCI function number */ + uint8_t *p_offset /* returned config space offset */ + ); + +#endif /* _ASMLANGUAGE */ + +#define PCI_CMD 4 /* command register */ + +/* PCI command bits */ + +#define PCI_CMD_IO_ENABLE 0x0001 /* IO access enable */ +#define PCI_CMD_MEM_ENABLE 0x0002 /* memory access enable */ +#define PCI_CMD_MASTER_ENABLE 0x0004 /* bus master enable */ +#define PCI_CMD_MON_ENABLE 0x0008 /* monitor special cycles enable */ +#define PCI_CMD_WI_ENABLE 0x0010 /* write and invalidate enable */ +#define PCI_CMD_SNOOP_ENABLE 0x0020 /* palette snoop enable */ +#define PCI_CMD_PERR_ENABLE 0x0040 /* parity error enable */ +#define PCI_CMD_WC_ENABLE 0x0080 /* wait cycle enable */ +#define PCI_CMD_SERR_ENABLE 0x0100 /* system error enable */ +#define PCI_CMD_FBTB_ENABLE 0x0200 /* fast back to back enable */ +#define PCI_CMD_INTX_DISABLE 0x0400 /* INTx disable */ + +/* PCI status bits */ + +#define PCI_STATUS_NEW_CAP 0x0010 +#define PCI_STATUS_66_MHZ 0x0020 +#define PCI_STATUS_UDF 0x0040 +#define PCI_STATUS_FAST_BB 0x0080 +#define PCI_STATUS_DATA_PARITY_ERR 0x0100 +#define PCI_STATUS_TARGET_ABORT_GEN 0x0800 +#define PCI_STATUS_TARGET_ABORT_RCV 0x1000 +#define PCI_STATUS_MASTER_ABORT_RCV 0x2000 +#define PCI_STATUS_ASSERT_SERR 0x4000 +#define PCI_STATUS_PARITY_ERROR 0x8000 + +/* Standard device Type 0 configuration register offsets */ +/* Note that only modulo-4 addresses are written to the address register */ + +#define PCI_CFG_VENDOR_ID 0x00 +#define PCI_CFG_DEVICE_ID 0x02 +#define PCI_CFG_COMMAND 0x04 +#define PCI_CFG_STATUS 0x06 +#define PCI_CFG_REVISION 0x08 +#define PCI_CFG_PROGRAMMING_IF 0x09 +#define PCI_CFG_SUBCLASS 0x0a +#define PCI_CFG_CLASS 0x0b +#define PCI_CFG_CACHE_LINE_SIZE 0x0c +#define PCI_CFG_LATENCY_TIMER 0x0d +#define PCI_CFG_HEADER_TYPE 0x0e +#define PCI_CFG_BIST 0x0f +#define PCI_CFG_BASE_ADDRESS_0 0x10 +#define PCI_CFG_BASE_ADDRESS_1 0x14 +#define PCI_CFG_BASE_ADDRESS_2 0x18 +#define PCI_CFG_BASE_ADDRESS_3 0x1c +#define PCI_CFG_BASE_ADDRESS_4 0x20 +#define PCI_CFG_BASE_ADDRESS_5 0x24 +#define PCI_CFG_CIS 0x28 +#define PCI_CFG_SUB_VENDER_ID 0x2c +#define PCI_CFG_SUB_SYSTEM_ID 0x2e +#define PCI_CFG_EXPANSION_ROM 0x30 +#define PCI_CFG_CAP_PTR 0x34 +#define PCI_CFG_RESERVED_0 0x35 +#define PCI_CFG_RESERVED_1 0x38 +#define PCI_CFG_DEV_INT_LINE 0x3c +#define PCI_CFG_DEV_INT_PIN 0x3d +#define PCI_CFG_MIN_GRANT 0x3e +#define PCI_CFG_MAX_LATENCY 0x3f +#define PCI_CFG_SPECIAL_USE 0x41 +#define PCI_CFG_MODE 0x43 +#define PCI_NUM_BARS 6 /* Number of BARs */ + +/* PCI base address mask bits */ + +#define PCI_MEMBASE_MASK ~0xf /* mask for memory base address */ +#define PCI_IOBASE_MASK ~0x3 /* mask for IO base address */ +#define PCI_BASE_IO 0x1 /* IO space indicator */ +#define PCI_BASE_BELOW_1M 0x2 /* memory locate below 1MB */ +#define PCI_BASE_IN_64BITS 0x4 /* memory locate anywhere in 64 bits */ +#define PCI_BASE_PREFETCH 0x8 /* memory prefetchable */ + +/* Base Address Register Memory/IO Attribute bits */ + +#define PCI_BAR_MEM_TYPE_MASK (0x06) +#define PCI_BAR_MEM_ADDR32 (0x00) +#define PCI_BAR_MEM_BELOW_1MB (0x02) +#define PCI_BAR_MEM_ADDR64 (0x04) +#define PCI_BAR_MEM_RESERVED (0x06) + +#define PCI_BAR_MEM_PREF_MASK (0x08) +#define PCI_BAR_MEM_PREFETCH (0x08) +#define PCI_BAR_MEM_NON_PREF (0x00) + +#define PCI_BAR_ALL_MASK \ + (PCI_BAR_SPACE_MASK | PCI_BAR_MEM_TYPE_MASK | PCI_BAR_MEM_PREF_MASK) + +#define PCI_BAR_SPACE_MASK (0x01) +#define PCI_BAR_SPACE_IO (0x01) +#define PCI_BAR_SPACE_MEM (0x00) +#define PCI_BAR_SPACE_NONE PCI_BAR_MEM_RESERVED + +#define PCI_BAR_NONE 0 +#define PCI_BAR_IO 0x1 +#define PCI_BAR_MEM 0x2 + +#define PCI_EXP_2_CAP 0x24 /* Dev 2 cap */ +#define PCI_EXP_2_CTRL 0x28 /* Dev 2 control */ +#define PCI_EXP_2_STATUS 0x2a /* Dev 2 status */ +#define PCI_EXP_2_LINK_CAP 0x2c /* Dev 2 Link cap */ +#define PCI_EXP_2_LINK_CTRL 0x30 /* Dev 2 Link control */ +#define PCI_EXP_2_LINK_STATUS 0x32 /* Dev 2 Link status */ +#define PCI_EXP_2_SLOT_CAP 0x34 /* Dev 2 Slot cap */ +#define PCI_EXP_2_SLOT_CTRL 0x38 /* Dev 2 slot control */ +#define PCI_EXP_2_SLOT_STATUS 0x3a /* Dev 2 slot status */ + +#define PCI_CFG_SPACE_SIZE 0x100 +#define PCIE_CFG_SPACE_SIZE 0x1000 +#define PCIE_CFG_SPACE_TOTAL ((PCIE_CFG_SPACE_SIZE - PCI_CFG_SPACE_SIZE) / 4) + +/* Extended Capabilities (PCI-X 2.0 and Express) */ +#define PCIE_EXT_CAP_ID(header) (header & 0x0000ffff) +#define PCIE_EXT_CAP_VER(header) ((header >> 16) & 0xf) +#define PCIE_EXT_CAP_NEXT(header) ((header >> 20) & 0xffc) + +#define PCIE_EXT_CAP_ID_ERR 1 +#define PCIE_EXT_CAP_ID_VC 2 +#define PCIE_EXT_CAP_ID_DSN 3 +#define PCIE_EXT_CAP_ID_PWR 4 +#define PCIE_EXT_CAP_ID_ARI 14 +#define PCIE_EXT_CAP_ID_ATS 15 +#define PCIE_EXT_CAP_ID_SRIOV 16 + +/* Advanced Error Reporting */ + +#define PCIE_ERR_UNCOR_STATUS 4 /* Uncorrectable Error Status*/ +#define PCIE_ERR_UNC_TRAIN 0x00000001 /* Training */ +#define PCIE_ERR_UNC_DLP 0x00000010 /* Data Link Protocol */ +#define PCIE_ERR_UNC_POISON_TLP 0x00001000 /* Poisoned TLP */ +#define PCIE_ERR_UNC_FCP 0x00002000 /* Flow Control Protocol */ +#define PCIE_ERR_UNC_COMP_TIME 0x00004000 /* Completion Timeout */ +#define PCIE_ERR_UNC_COMP_ABORT 0x00008000 /* Completer Abort */ +#define PCIE_ERR_UNC_UNX_COMP 0x00010000 /* Unexpected Completion */ +#define PCIE_ERR_UNC_RX_OVER 0x00020000 /* Receiver Overflow */ +#define PCIE_ERR_UNC_MALF_TLP 0x00040000 /* Malformed TLP */ +#define PCIE_ERR_UNC_ECRC 0x00080000 /* ECRC Error Status */ +#define PCIE_ERR_UNC_UNSUP 0x00100000 /* Unsupported Request */ +#define PCIE_ERR_UNCOR_MASK 8 /* Uncorrectable Error Mask */ + /* Same bits as above */ +#define PCIE_ERR_UNCOR_SEVER 12 /* Uncorrectable Erro Sev. */ + /* Same bits as above */ +#define PCIE_ERR_COR_STATUS 16 /* Correctable Error Status */ +#define PCIE_ERR_COR_RCVR 0x00000001 /* Receiver Error Status */ +#define PCIE_ERR_COR_BAD_TLP 0x00000040 /* Bad TLP Status */ +#define PCIE_ERR_COR_BAD_DLLP 0x00000080 /* Bad DLLP Status */ +#define PCIE_ERR_COR_REP_ROLL 0x00000100 /* REPLAY_NUM Rollover */ +#define PCIE_ERR_COR_REP_TIMER 0x00001000 /* Replay Timer Timeout */ +#define PCIE_ERR_COR_MASK 20 /* Correctable Error Mask */ + /* Same bits as above */ +#define PCIE_ERR_CAP 24 /* Advanced Error Cap */ +#define PCIE_ERR_CAP_FEP(x) ((x) & 31) /* First Error Pointer */ +#define PCIE_ERR_CAP_ECRC_GENC 0x00000020 /* ECRC Generation Capable */ +#define PCIE_ERR_CAP_ECRC_GENE 0x00000040 /* ECRC Generation Enable */ +#define PCIE_ERR_CAP_ECRC_CHKC 0x00000080 /* ECRC Check Capable */ +#define PCIE_ERR_CAP_ECRC_CHKE 0x00000100 /* ECRC Check Enable */ +#define PCIE_ERR_HEADER_LOG 28 /* Header Log Reg (16 bytes) */ +#define PCIE_ERR_ROOT_COMMAND 44 /* Root Error Command */ +#define PCIE_ERR_ROOT_CMD_COR_EN 0x00000001 /* Correctable Err Report */ +#define PCIE_ERR_ROOT_CMD_NONFATAL_EN 0x00000002 /* Non-fatal Err Reporting */ +#define PCIE_ERR_ROOT_CMD_FATAL_EN 0x00000004 /* Fatal Err Reporting En */ +#define PCIE_ERR_ROOT_STATUS 48 +#define PCIE_ERR_ROOT_COR_RCV 0x00000001 /* ERR_COR Received */ +#define PCIE_ERR_ROOT_MULTI_COR_RCV 0x00000002 /* Multi ERR_COR Received */ +#define PCIE_ERR_ROOT_UNCOR_RCV 0x00000004 /* ERR_FATAL/NONFATAL Rcv */ +#define PCIE_ERR_ROOT_MULTI_UNCOR_RCV 0x00000008 /* Multi ERR_FATAL/NONFATAL*/ +#define PCIE_ERR_ROOT_FIRST_FATAL 0x00000010 /* First Fatal */ +#define PCIE_ERR_ROOT_NONFATAL_RCV 0x00000020 /* Non-Fatal Received */ +#define PCIE_ERR_ROOT_FATAL_RCV 0x00000040 /* Fatal Received */ +#define PCIE_ERR_ROOT_COR_SRC 52 +#define PCIE_ERR_ROOT_SRC 54 + +/* Virtual Channel */ + +#define PCIE_VC_PORT_REG1 4 +#define PCIE_VC_PORT_REG2 8 +#define PCIE_VC_PORT_CTRL 12 +#define PCIE_VC_PORT_STATUS 14 +#define PCIE_VC_RES_CAP 16 +#define PCIE_VC_RES_CTRL 20 +#define PCIE_VC_RES_STATUS 26 + +/* Power Budgeting */ + +#define PCIE_PWR_DSR 4 /* Data Select Register */ +#define PCIE_PWR_DATA 8 /* Data Register */ +#define PCIE_PWR_DATA_BASE(x) ((x) & 0xff) /* Base Power */ +#define PCIE_PWR_DATA_SCALE(x) (((x) >> 8) & 3) /* Data Scale */ +#define PCIE_PWR_DATA_PM_SUB(x) (((x) >> 10) & 7) /* PM Sub State */ +#define PCIE_PWR_DATA_PM_STATE(x) (((x) >> 13) & 3) /* PM State */ +#define PCIE_PWR_DATA_TYPE(x) (((x) >> 15) & 7) /* Type */ +#define PCIE_PWR_DATA_RAIL(x) (((x) >> 18) & 7) /* Power Rail */ +#define PCIE_PWR_CAP 12 /* Capability */ +#define PCIE_PWR_CAP_BUDGET(x) ((x) & 1) /* Included in sys budget */ + +/* + * Hypertransport sub capability types + * + * Unfortunately there are both 3 bit and 5 bit capability types defined + * in the HT spec, catering for that is a little messy. You probably don't + * want to use these directly, just use pci_find_ht_capability() and it + * will do the right thing for you. + */ + +#define HT_3BIT_CAP_MASK 0xE0 +#define HT_CAPTYPE_SLAVE 0x00 /* Slave/Primary link configuration */ +#define HT_CAPTYPE_HOST 0x20 /* Host/Secondary link configuration */ + +#define HT_5BIT_CAP_MASK 0xF8 +#define HT_CAPTYPE_IRQ 0x80 /* IRQ Configuration */ +#define HT_CAPTYPE_REMAPPING_40 0xA0 /* 40 bit address remapping */ +#define HT_CAPTYPE_REMAPPING_64 0xA2 /* 64 bit address remapping */ +#define HT_CAPTYPE_UNITID_CLUMP 0x90 /* Unit ID clumping */ +#define HT_CAPTYPE_EXTCONF 0x98 /* Extended Configuration Space Access*/ +#define HT_CAPTYPE_MSI_MAPPING 0xA8 /* MSI Mapping Capability */ +#define HT_MSI_FLAGS 0x02 /* Offset to flags */ +#define HT_MSI_FLAGS_ENABLE 0x1 /* Mapping enable */ +#define HT_MSI_FLAGS_FIXED 0x2 /* Fixed mapping only */ + /* Fixed addr */ +#define HT_MSI_FIXED_ADDR 0x00000000FEE00000ULL +#define HT_MSI_ADDR_LO 0x04 /* Offset to low addr bits */ + /* Low address bit mask */ +#define HT_MSI_ADDR_LO_MASK 0xFFF00000 +#define HT_MSI_ADDR_HI 0x08 /* Offset to high addr bits */ +#define HT_CAPTYPE_DIRECT_ROUTE 0xB0 /* Direct routing configuration */ +#define HT_CAPTYPE_VCSET 0xB8 /* Virtual Channel configuration */ +#define HT_CAPTYPE_ERROR_RETRY 0xC0 /* Retry on error configuration */ +#define HT_CAPTYPE_GEN3 0xD0 /* Generation 3 hypertransport config */ +#define HT_CAPTYPE_PM 0xE0 /* Hypertransport powermanagement cfg */ + +/* Alternative Routing-ID Interpretation */ +#define PCIE_ARI_CAP 0x04 /* ARI Capability Register */ +#define PCIE_ARI_CAP_MFVC 0x0001 /* MFVC Function Groups Capability */ +#define PCIE_ARI_CAP_ACS 0x0002 /* ACS Function Groups Capability */ + /* Next Function Number */ +#define PCIE_ARI_CAP_NFN(x) (((x) >> 8) & 0xff) +#define PCIE_ARI_CTRL 0x06 /* ARI Control Register */ +#define PCIE_ARI_CTRL_MFVC 0x0001 /* MFVC Function Groups Enable */ +#define PCIE_ARI_CTRL_ACS 0x0002 /* ACS Function Groups Enable */ + /* Function Group */ +#define PCIE_ARI_CTRL_FG(x) (((x) >> 4) & 7) + +/* Address Translation Service */ +#define PCIE_ATS_CAP 0x04 /* ATS Capability Register */ + /* Invalidate Queue Depth */ +#define PCIE_ATS_CAP_QDEP(x) ((x) & 0x1f) +#define PCIE_ATS_MAX_QDEP 32 /* Max Invalidate Queue Depth */ +#define PCIE_ATS_CTRL 0x06 /* ATS Control Register */ +#define PCIE_ATS_CTRL_ENABLE 0x8000 /* ATS Enable */ + /* Smallest Translation Unit */ +#define PCIE_ATS_CTRL_STU(x) ((x) & 0x1f) +#define PCIE_ATS_MIN_STU 12 /* shift of minimum STU block */ + +/* Single Root I/O Virtualization */ +#define PCIE_SRIOV_CAP 0x04 /* SR-IOV Capabilities */ +#define PCIE_SRIOV_CAP_VFM 0x01 /* VF Migration Capable */ + /* Interrupt Message Number */ +#define PCIE_SRIOV_CAP_INTR(x) ((x) >> 21) +#define PCIE_SRIOV_CTRL 0x08 /* SR-IOV Control */ +#define PCIE_SRIOV_CTRL_VFE 0x01 /* VF Enable */ +#define PCIE_SRIOV_CTRL_VFM 0x02 /* VF Migration Enable */ +#define PCIE_SRIOV_CTRL_INTR 0x04 /* VF Migration Interrupt Enable */ +#define PCIE_SRIOV_CTRL_MSE 0x08 /* VF Memory Space Enable */ +#define PCIE_SRIOV_CTRL_ARI 0x10 /* ARI Capable Hierarchy */ +#define PCIE_SRIOV_STATUS 0x0a /* SR-IOV Status */ +#define PCIE_SRIOV_STATUS_VFM 0x01 /* VF Migration Status */ +#define PCIE_SRIOV_INITIAL_VF 0x0c /* Initial VFs */ +#define PCIE_SRIOV_TOTAL_VF 0x0e /* Total VFs */ +#define PCIE_SRIOV_NUM_VF 0x10 /* Number of VFs */ +#define PCIE_SRIOV_FUNC_LINK 0x12 /* Function Dependency Link */ +#define PCIE_SRIOV_VF_OFFSET 0x14 /* First VF Offset */ +#define PCIE_SRIOV_VF_STRIDE 0x16 /* Following VF Stride */ +#define PCIE_SRIOV_VF_DID 0x1a /* VF Device ID */ +#define PCIE_SRIOV_SUP_PGSIZE 0x1c /* Supported Page Sizes */ +#define PCIE_SRIOV_SYS_PGSIZE 0x20 /* System Page Size */ +#define PCIE_SRIOV_BAR0 0x24 /* VF BAR0 */ +#define PCIE_SRIOV_BAR0_UPPER 0x28 /* VF BAR0 upper*/ +#define PCIE_SRIOV_BAR3 0x30 /* VF BAR3 */ +#define PCIE_SRIOV_BAR3_UPPER 0x34 /* VF BAR3 upper */ + +#define PCIE_SRIOV_NUM_BARS 6 /* Number of VF BARs */ +#define PCIE_SRIOV_VFM 0x3c /* VF Migration State Array Offset*/ + /* State BIR */ +#define PCIE_SRIOV_VFM_BIR(x) ((x) & 7) +/* State Offset */ +#define PCIE_SRIOV_VFM_OFFSET(x) ((x) & ~7) +#define PCIE_SRIOV_VFM_UA 0x0 /* Inactive.Unavailable */ +#define PCIE_SRIOV_VFM_MI 0x1 /* Dormant.MigrateIn */ +#define PCIE_SRIOV_VFM_MO 0x2 /* Active.MigrateOut */ +#define PCIE_SRIOV_VFM_AV 0x3 /* Active.Available */ + +/* Extended Capabilities (PCI-X 2.0 and Express) */ + +#define PCI_EXT_CAP_ID(header) (header & 0x0000ffff) +#define PCI_EXT_CAP_VER(header) ((header >> 16) & 0xf) +#define PCI_EXT_CAP_NEXT(header) ((header >> 20) & 0xffc) + +#define PCI_MSIX_ENTRY_SIZE 16 +#define PCI_MSIX_ENTRY_LOWER_ADDR 0 +#define PCI_MSIX_ENTRY_UPPER_ADDR 4 +#define PCI_MSIX_ENTRY_DATA 8 +#define PCI_MSIX_ENTRY_VECTOR_CTRL 12 +#define PCI_MSIX_ENTRY_VECTOR_MASKED 0x1 + +/* PCI-to-PCI bridge Type 1 configuration register offsets */ +/* Note that only modulo-4 addresses are written to the address register */ + +#define PCI_CFG_PRIMARY_BUS 0x18 +#define PCI_CFG_SECONDARY_BUS 0x19 +#define PCI_CFG_SUBORDINATE_BUS 0x1a +#define PCI_CFG_SEC_LATENCY 0x1b +#define PCI_CFG_IO_BASE 0x1c +#define PCI_CFG_IO_LIMIT 0x1d +#define PCI_CFG_SEC_STATUS 0x1e +#define PCI_CFG_MEM_BASE 0x20 +#define PCI_CFG_MEM_LIMIT 0x22 +#define PCI_CFG_PRE_MEM_BASE 0x24 +#define PCI_CFG_PRE_MEM_LIMIT 0x26 +#define PCI_CFG_PRE_MEM_BASE_U 0x28 +#define PCI_CFG_PRE_MEM_LIMIT_U 0x2c +#define PCI_CFG_IO_BASE_U 0x30 +#define PCI_CFG_IO_LIMIT_U 0x32 +#define PCI_CFG_ROM_BASE 0x38 +#define PCI_CFG_BRG_INT_LINE 0x3c +#define PCI_CFG_BRG_INT_PIN 0x3d +#define PCI_CFG_BRIDGE_CONTROL 0x3e + +/* PCI-to-CardBus bridge Type 2 configuration register offsets */ + +#define PCI_CFG_CB_CAP_PTR 0x14 +/* 0x15 - reserved */ +#define PCI_CFG_CB_SEC_STATUS 0x16 +#define PCI_CFG_CB_PRIMARY_BUS 0x18 /* PCI bus no. */ +#define PCI_CFG_CB_BUS 0x19 /* CardBus bus no */ +#define PCI_CFG_CB_SUBORDINATE_BUS 0x1a /* Subordinate bus no. */ +#define PCI_CFG_CB_LATENCY_TIMER 0x1b /* CardBus latency timer */ +#define PCI_CFG_CB_MEM_BASE_0 0x1c +#define PCI_CFG_CB_MEM_LIMIT_0 0x20 +#define PCI_CFG_CB_MEM_BASE_1 0x24 +#define PCI_CFG_CB_MEM_LIMIT_1 0x28 +#define PCI_CFG_CB_IO_BASE_0 0x2c +#define PCI_CFG_CB_IO_BASE_0_HI 0x2e +#define PCI_CFG_CB_IO_LIMIT_0 0x30 +#define PCI_CFG_CB_IO_LIMIT_0_HI 0x32 +#define PCI_CFG_CB_IO_BASE_1 0x34 +#define PCI_CFG_CB_IO_BASE_1_HI 0x36 +#define PCI_CFG_CB_IO_LIMIT_1 0x38 +#define PCI_CFG_CB_IO_LIMIT_1_HI 0x3a +#define PCI_CFG_CB_BRIDGE_CONTROL 0x3e +#define PCI_CFG_CB_SUB_VENDOR_ID 0x40 +#define PCI_CFG_CB_SUB_SYSTEM_ID 0x42 +#define PCI_CFG_CB_16BIT_LEGACY 0x44 +/* 0x48 - 0x7f are reserved */ + +/* PCI Bridge Control Register (0x3E) bits */ + +#define PCI_CFG_PARITY_ERROR 0x01 /* Enable parity detection */ +#define PCI_CFG_SERR 0x02 /* SERR enable */ +#define PCI_CFG_ISA_ENABLE 0x04 /* ISA Disable - bit set = disable*/ +#define PCI_CFG_VGA_ENABLE 0x08 /* Enable VGA addresses */ +#define PCI_CFG_MASTER_ABORT 0x20 /* Signal master abort */ +#define PCI_CFG_SEC_BUS_RESET 0x40 /* secondary bus reset */ +#define PCI_CFG_FAST_BACK 0x80 /* FBB enabled on secondary */ +#define PCI_CFG_PRI_DIS_TO \ + 0x100 /* Primary Discard Timeout: \ + 2^10 PCI cycles */ +#define PCI_CFG_SEC_DIS_TO \ + 0x200 /* 2ndary Discard Timeout: \ + 2^10 PCI cycles */ +#define PCI_CFG_DIS_TIMER_STAT 0x400 /* Discard Timer status */ +#define PCI_CFG_DIS_TIMER_ENABLE 0x800 /* Discard Timer enable */ + +/* Cardbus Bridge Control Register (0x3E) bits */ + +#define PCI_CFG_CB_PARITY_ERROR 0x01 /* Enable parity detection */ +#define PCI_CFG_CB_SERR 0x02 /* SERR enable */ +#define PCI_CFG_CB_ISA_ENABLE 0x04 /* ISA Disable - bit set = disable*/ +#define PCI_CFG_CB_VGA_ENABLE 0x08 /* Enable VGA addresses */ +#define PCI_CFG_CB_MASTER_ABORT 0x20 /* Signal master abort */ +#define PCI_CFG_CB_RESET 0x40 /* Cardbus reset */ +#define PCI_CFG_CB_16BIT_INT 0x80 /* Enable ints for 16-bit cards */ +#define PCI_CFG_CB_PREFETCH0 0x0100 /* Memory 0 prefetch enable */ +#define PCI_CFG_CB_PREFETCH1 0x0200 /* Memory 1 prefetch enable */ +#define PCI_CFG_CB_POST_WRITES 0x0400 /* Posted Writes */ + +/* Power Management registers */ + +#define PCI_PM_CTRL 4 /* PM control register */ +#define PCI_PM_CTRL_NO_RST 0x0008 /* No reset issued by d3-d0 */ + +#define PCI_PSTATE_MASK 0x0003 /* Power state bits */ +#define PCI_PSTATE_D0 0x0000 +#define PCI_PSTATE_D1 0x0001 +#define PCI_PSTATE_D2 0x0002 +#define PCI_PSTATE_D3_HOT 0x0003 +#define PCI_PSTATE_D3_COLD 0x0004 + +/* Advanced Features */ + +#define PCI_AF_CAP 3 +#define PCI_AF_CAP_TRPND 0x01 +#define PCI_AF_CAP_FLR 0x02 +#define PCI_AF_CTRL 4 +#define PCI_AF_CTRL_FLR 0x01 +#define PCI_AF_STATUS 5 +#define PCI_AF_STATUS_TRPND 0x01 + +/* CompactPCI Hot Swap Control & Status Register (HSCSR) defines */ + +#define PCI_HS_CSR_RSVD0 0x01 /* Reserved */ +#define PCI_HS_CSR_EIM 0x02 /* ENUM Interrupt Mask */ +#define PCI_HS_CSR_RSVD2 0x04 /* Reserved */ +#define PCI_HS_CSR_LOO 0x08 /* Blue LED On/Off */ +#define PCI_HS_CSR_RSVD4 0x10 /* Reserved */ +#define PCI_HS_CSR_RSVD5 0x20 /* Reserved */ +#define PCI_HS_CSR_EXT 0x40 /* ENUM Status - EXTract */ +#define PCI_HS_CSR_INS 0x80 /* ENUM Status - INSert */ + +/* PCI Standard Classifications */ + +/* + * PCI classifications are composed from the concatenation of four byte-size + * components: primary (base) class, sub-class, register interface, and + * revision ID. The following comprise the standard PCI classification + * definitions. + */ + +/* + * PCI Primary (Base) Class definitions for find by class function + * Classes 0x12 - 0xFE are reserved for future enhancements + */ + +#define PCI_CLASS_PRE_PCI20 0x00 +#define PCI_CLASS_MASS_STORAGE 0x01 +#define PCI_CLASS_NETWORK_CTLR 0x02 +#define PCI_CLASS_DISPLAY_CTLR 0x03 +#define PCI_CLASS_MMEDIA_DEVICE 0x04 +#define PCI_CLASS_MEM_CTLR 0x05 +#define PCI_CLASS_BRIDGE_CTLR 0x06 +#define PCI_CLASS_COMM_CTLR 0x07 +#define PCI_CLASS_BASE_PERIPH 0x08 +#define PCI_CLASS_INPUT_DEVICE 0x09 +#define PCI_CLASS_DOCK_DEVICE 0x0A +#define PCI_CLASS_PROCESSOR 0x0B +#define PCI_CLASS_SERIAL_BUS 0x0C +#define PCI_CLASS_WIRELESS 0x0D +#define PCI_CLASS_INTLGNT_IO 0x0E +#define PCI_CLASS_SAT_COMM 0x0F +#define PCI_CLASS_EN_DECRYPTION 0x10 +#define PCI_CLASS_DAQ_DSP 0x11 +#define PCI_CLASS_UNDEFINED 0xFF + +/* PCI Subclass definitions */ + +#define PCI_SUBCLASS_00 0x00 +#define PCI_SUBCLASS_01 0x01 +#define PCI_SUBCLASS_02 0x02 +#define PCI_SUBCLASS_03 0x03 +#define PCI_SUBCLASS_04 0x04 +#define PCI_SUBCLASS_05 0x05 +#define PCI_SUBCLASS_06 0x06 +#define PCI_SUBCLASS_07 0x07 +#define PCI_SUBCLASS_08 0x08 +#define PCI_SUBCLASS_09 0x09 +#define PCI_SUBCLASS_0A 0x0A +#define PCI_SUBCLASS_10 0x10 +#define PCI_SUBCLASS_11 0x11 +#define PCI_SUBCLASS_12 0x12 +#define PCI_SUBCLASS_20 0x20 +#define PCI_SUBCLASS_40 0x40 +#define PCI_SUBCLASS_80 0x80 +#define PCI_SUBCLASS_UNDEFINED 0xFF + +/* Base Class 00 are Rev 1.0 and are not defined here. */ + +/* Mass Storage subclasses - Base Class 01h */ + +#define PCI_SUBCLASS_MASS_SCSI (PCI_SUBCLASS_00) +#define PCI_SUBCLASS_MASS_IDE (PCI_SUBCLASS_01) +#define PCI_SUBCLASS_MASS_FLOPPY (PCI_SUBCLASS_02) +#define PCI_SUBCLASS_MASS_IPI (PCI_SUBCLASS_03) +#define PCI_SUBCLASS_MASS_RAID (PCI_SUBCLASS_04) +#define PCI_SUBCLASS_MASS_ATA (PCI_SUBCLASS_05) +#define PCI_REG_IF_ATA_SNGL 0x20 +#define PCI_REG_IF_ATA_CHND 0x30 +#define PCI_SUBCLASS_MASS_OTHER (PCI_SUBCLASS_80) + +/* Network subclasses - Base Class 02h */ + +#define PCI_SUBCLASS_NET_ETHERNET (PCI_SUBCLASS_00) +#define PCI_SUBCLASS_NET_TOKEN_RING (PCI_SUBCLASS_01) +#define PCI_SUBCLASS_NET_FDDI (PCI_SUBCLASS_02) +#define PCI_SUBCLASS_NET_ATM (PCI_SUBCLASS_03) +#define PCI_SUBCLASS_NET_ISDN (PCI_SUBCLASS_04) +#define PCI_SUBCLASS_NET_WFIP (PCI_SUBCLASS_05) +#define PCI_SUBCLASS_NET_PCMIG214 (PCI_SUBCLASS_06) +#define PCI_SUBCLASS_NET_OTHER (PCI_SUBCLASS_80) + +/* Display subclasses - Base Class 03h */ + +#define PCI_SUBCLASS_DISPLAY_VGA (PCI_SUBCLASS_00) +#define PCI_REG_IF_VGA_STD 0x00 +#define PCI_REG_IF_VGA_8514 0x01 +#define PCI_SUBCLASS_DISPLAY_XGA (PCI_SUBCLASS_01) +#define PCI_SUBCLASS_DISPLAY_3D (PCI_SUBCLASS_02) +#define PCI_SUBCLASS_DISPLAY_OTHER (PCI_SUBCLASS_80) + +/* Multimedia subclasses - Base Class 04h */ + +#define PCI_SUBCLASS_MMEDIA_VIDEO (PCI_SUBCLASS_00) +#define PCI_SUBCLASS_MMEDIA_AUDIO (PCI_SUBCLASS_01) +#define PCI_SUBCLASS_MMEDIA_PHONY (PCI_SUBCLASS_02) +#define PCI_SUBCLASS_MMEDIA_OTHER (PCI_SUBCLASS_80) + +/* Memory subclasses - Base Class 05h */ + +#define PCI_SUBCLASS_MEM_RAM (PCI_SUBCLASS_00) +#define PCI_SUBCLASS_MEM_FLASH (PCI_SUBCLASS_01) +#define PCI_SUBCLASS_MEM_OTHER (PCI_SUBCLASS_80) + +/* Bus Bridge Device subclasses - Base Class 06h */ + +#define PCI_SUBCLASS_HOST_PCI_BRIDGE (PCI_SUBCLASS_00) +#define PCI_SUBCLASS_ISA_BRIDGE (PCI_SUBCLASS_01) +#define PCI_SUBCLASS_EISA_BRIDGE (PCI_SUBCLASS_02) +#define PCI_SUBCLASS_MCA_BRIDGE (PCI_SUBCLASS_03) +#define PCI_SUBCLASS_P2P_BRIDGE (PCI_SUBCLASS_04) +#define PCI_REG_IF_P2P_STD 0x00 +#define PCI_REG_IF_P2P_SUB_DECODE 0x01 +#define PCI_SUBCLASS_PCMCIA_BRIDGE (PCI_SUBCLASS_05) +#define PCI_SUBCLASS_NUBUS_BRIDGE (PCI_SUBCLASS_06) +#define PCI_SUBCLASS_CARDBUS_BRIDGE (PCI_SUBCLASS_07) +#define PCI_SUBCLASS_RACEWAY_BRIDGE (PCI_SUBCLASS_08) +#define PCI_REG_IF_RACEWAY_XPARENT 0x00 +#define PCI_REG_IF_RACEWAY_END_PNT 0x01 +#define PCI_SUBCLASS_SEMI_XPARENT (PCI_SUBCLASS_09) +#define PCI_REG_IF_SEMI_XPARENT_PRI 0x40 +#define PCI_REG_IF_SEMI_XPARENT_SEC 0x80 +#define PCI_SUBCLASS_INFINI2PCI (PCI_SUBCLASS_0A) +#define PCI_SUBCLASS_OTHER_BRIDGE (PCI_SUBCLASS_80) + +/* Simple Communications Controller subclasses - Base Class 07h */ + +#define PCI_SUBCLASS_SCC_SERIAL (PCI_SUBCLASS_00) +#define PCI_REG_IF_SERIAL_XT 0x00 +#define PCI_REG_IF_SERIAL_16450 0x01 +#define PCI_REG_IF_SERIAL_16550 0x02 +#define PCI_REG_IF_SERIAL_16650 0x03 +#define PCI_REG_IF_SERIAL_16750 0x04 +#define PCI_REG_IF_SERIAL_16850 0x05 +#define PCI_REG_IF_SERIAL_16950 0x06 +#define PCI_SUBCLASS_SCC_PARLEL (PCI_SUBCLASS_01) +#define PCI_REG_IF_PARLEL_XT 0x00 +#define PCI_REG_IF_PARLEL_BIDIR 0x01 +#define PCI_REG_IF_PARLEL_ECP 0x02 +#define PCI_REG_IF_PARLEL_1284CTLR 0x03 +#define PCI_REG_IF_PARLEL_1284TGT 0xFE +#define PCI_SUBCLASS_SCC_MULTI (PCI_SUBCLASS_02) +#define PCI_SUBCLASS_SCC_MODEM (PCI_SUBCLASS_03) +#define PCI_REG_IF_MODEM_GENERIC 0x00 +#define PCI_REG_IF_MODEM_16450 0x01 +#define PCI_REG_IF_MODEM_16550 0x02 +#define PCI_REG_IF_MODEM_16650 0x03 +#define PCI_REG_IF_MODEM_16750 0x04 +#define PCI_SUBCLASS_SCC_GPIB (PCI_SUBCLASS_04) +#define PCI_SUBCLASS_SCC_SMRTCRD (PCI_SUBCLASS_05) +#define PCI_SUBCLASS_SCC_OTHER (PCI_SUBCLASS_80) + +/* Base System subclasses - Base Class 08h */ + +#define PCI_SUBCLASS_BASESYS_PIC (PCI_SUBCLASS_00) +#define PCI_REG_IF_PIC_GEN8259 0x00 +#define PCI_REG_IF_PIC_ISA 0x01 +#define PCI_REG_IF_PIC_EISA 0x02 +#define PCI_REG_IF_PIC_APIC 0x10 +#define PCI_REG_IF_PIC_xAPIC 0x20 +#define PCI_SUBCLASS_BASESYS_DMA (PCI_SUBCLASS_01) +#define PCI_REG_IF_DMA_GEN8237 0x00 +#define PCI_REG_IF_DMA_ISA 0x01 +#define PCI_REG_IF_DMA_EISA 0x02 +#define PCI_SUBCLASS_BASESYS_TIMER (PCI_SUBCLASS_02) +#define PCI_REG_IF_TIMER_GEN8254 0x00 +#define PCI_REG_IF_TIMER_ISA 0x01 +#define PCI_REG_IF_TIMER_EISA 0x02 +#define PCI_SUBCLASS_BASESYS_RTC (PCI_SUBCLASS_03) +#define PCI_REG_IF_RTC_GENERIC 0x00 +#define PCI_REG_IF_RTC_ISA 0x01 +#define PCI_SUBCLASS_BASESYS_HOTPLUG (PCI_SUBCLASS_04) +#define PCI_SUBCLASS_BASESYS_OTHER (PCI_SUBCLASS_80) + +/* Input Device subclasses - Base Class 09h */ + +#define PCI_SUBCLASS_INPUT_KEYBD (PCI_SUBCLASS_00) +#define PCI_SUBCLASS_INPUT_PEN (PCI_SUBCLASS_01) +#define PCI_SUBCLASS_INPUT_MOUSE (PCI_SUBCLASS_02) +#define PCI_SUBCLASS_INPUT_SCANR (PCI_SUBCLASS_03) +#define PCI_SUBCLASS_INPUT_GAMEPORT (PCI_SUBCLASS_04) +#define PCI_REG_IF_GAMEPORT_GENERIC 0x00 +#define PCI_REG_IF_GAMEPORT_LEGACY 0x10 +#define PCI_SUBCLASS_INPUT_OTHER (PCI_SUBCLASS_80) + +/* Docking Station subclasses - Base Class 0Ah */ + +#define PCI_SUBCLASS_DOCSTATN_GENERIC (PCI_SUBCLASS_00) +#define PCI_SUBCLASS_DOCSTATN_OTHER (PCI_SUBCLASS_80) + +/* Processor subclasses - Base Class 0Bh */ + +#define PCI_SUBCLASS_PROCESSOR_386 (PCI_SUBCLASS_00) +#define PCI_SUBCLASS_PROCESSOR_486 (PCI_SUBCLASS_01) +#define PCI_SUBCLASS_PROCESSOR_PENTIUM (PCI_SUBCLASS_02) +#define PCI_SUBCLASS_PROCESSOR_ALPHA (PCI_SUBCLASS_10) +#define PCI_SUBCLASS_PROCESSOR_POWERPC (PCI_SUBCLASS_20) +#define PCI_SUBCLASS_PROCESSOR_MIPS (PCI_SUBCLASS_30) +#define PCI_SUBCLASS_PROCESSOR_COPROC (PCI_SUBCLASS_40) + +/* Serial bus subclasses - Base Class 0Ch */ + +#define PCI_SUBCLASS_SERBUS_FIREWIRE (PCI_SUBCLASS_00) +#define PCI_REG_IF_FIREWIRE_1394 0x00 +#define PCI_REG_IF_FIREWIRE_HCI1394 0x10 +#define PCI_SUBCLASS_SERBUS_ACCESS (PCI_SUBCLASS_01) +#define PCI_SUBCLASS_SERBUS_SSA (PCI_SUBCLASS_02) +#define PCI_SUBCLASS_SERBUS_USB (PCI_SUBCLASS_03) +#define PCI_REG_IF_USB_UHCI 0x00 +#define PCI_REG_IF_USB_OHCI 0x10 +#define PCI_REG_IF_USB_EHCI 0x20 +#define PCI_REG_IF_USB_XHCI 0x30 +#define PCI_REG_IF_USB_ANY 0x80 +#define PCI_REG_IF_USB_NONHOST 0xFE +#define PCI_SUBCLASS_SERBUS_FIBRE_CHAN (PCI_SUBCLASS_04) +#define PCI_SUBCLASS_SERBUS_SMBUS (PCI_SUBCLASS_05) +#define PCI_SUBCLASS_SERBUS_INFINI (PCI_SUBCLASS_06) +#define PCI_SUBCLASS_SERBUS_IPMI (PCI_SUBCLASS_07) +#define PCI_REG_IF_IPMI_SMIC 0x00 +#define PCI_REG_IF_IPMI_KYBD 0x01 +#define PCI_REG_IF_IPMI_BLCK 0x02 +#define PCI_SUBCLASS_SERBUS_SERCOS (PCI_SUBCLASS_08) +#define PCI_SUBCLASS_SERBUS_CAN (PCI_SUBCLASS_09) +#define PCI_SUBCLASS_SERBUS_OTHER (PCI_SUBCLASS_80) + +/* Wireless subclasses - Base Class 0Dh */ + +#define PCI_SUBCLASS_WIRELESS_IRDA (PCI_SUBCLASS_00) +#define PCI_SUBCLASS_WIRELESS_OTHER_IR (PCI_SUBCLASS_01) +#define PCI_SUBCLASS_WIRELESS_RF (PCI_SUBCLASS_10) +#define PCI_SUBCLASS_WIRELESS_BTOOTH (PCI_SUBCLASS_11) +#define PCI_SUBCLASS_WIRELESS_BBAND (PCI_SUBCLASS_12) +#define PCI_SUBCLASS_WIRELESS_OTHER (PCI_SUBCLASS_80) + +/* + * Intelligent I/O subclasses - Base Class 0Eh + * REG_IF values greater than 0x00 are reserved for I2O + */ + +#define PCI_SUBCLASS_INTELIO (PCI_SUBCLASS_00) +#define PCI_REG_IF_INTELIO_MSG_FIFO 0x00 +#define PCI_8UBCLASS_INTELIO_OTHER (PCI_SUBCLASS_00) + +/* Satellite Device Communication subclasses - Base Class 0Fh */ + +#define PCI_SUBCLASS_SATCOM_TV (PCI_SUBCLASS_00) +#define PCI_SUBCLASS_SATCOM_AUDIO (PCI_SUBCLASS_01) +#define PCI_SUBCLASS_SATCOM_VOICE (PCI_SUBCLASS_03) +#define PCI_SUBCLASS_SATCOM_DATA (PCI_SUBCLASS_04) +#define PCI_SUBCLASS_SATCOM_OTHER (PCI_SUBCLASS_80) + +/* Encryption/Decryption subclasses - Base Class 10h */ + +#define PCI_SUBCLASS_EN_DECRYP_NETWORK (PCI_SUBCLASS_00) +#define PCI_SUBCLASS_EN_DECRYP_ENTRTMNT (PCI_SUBCLASS_10) +#define PCI_SUBCLASS_EN_DECRYP_OTHER (PCI_SUBCLASS_80) + +/* Data Acquisition and Signal Processing subclasses - Base Class 11h */ + +#define PCI_SUBCLASS_DAQ_DSP_DPIO (PCI_SUBCLASS_00) +#define PCI_SUBCLASS_DAQ_DSP_PCTRS (PCI_SUBCLASS_01) +#define PCI_SUBCLASS_DAQ_DSP_COMM (PCI_SUBCLASS_10) +#define PCI_SUBCLASS_DAQ_DSP_MGMT (PCI_SUBCLASS_20) +#define PCI_SUBCLASS_DAQ_DSP_OTHER (PCI_SUBCLASS_80) + +/* PCI status field bit definitions */ + +#define PCI_STATUS_RESERVED_0 0x0001 +#define PCI_STATUS_RESERVED_1 0x0002 +#define PCI_STATUS_RESERVED_2 0x0004 +#define PCI_STATUS_INT_STATUS 0x0008 +#define PCI_STATUS_CAPABILITY_LIST 0x0010 +#define PCI_STATUS_66MHZ 0x0020 +#define PCI_STATUS_UDF_SUPPORTED 0x0040 +#define PCI_STATUS_FAST_B_TO_B 0x0080 +#define PCI_STATUS_DATA_PARITY_ERROR 0x0100 +#define PCI_STATUS_DEVSEL_TIMING 0x0600 +#define PCI_STATUS_SIG_TGT_ABORT 0x0800 +#define PCI_STATUS_RCV_TGT_ABORT 0x1000 +#define PCI_STATUS_RCV_MAST_ABORT 0x2000 +#define PCI_STATUS_SIG_SYS_ERROR 0x4000 +#define PCI_STATUS_DETECT_PARITY_ERROR 0x8000 + +/* PCI Capability register set identification */ + +#define PCI_CAP_RESERVED 0x00 +#define PCI_CAP_POWER_MGMT 0x01 /* Power Management interface */ +#define PCI_CAP_AGP 0x02 /* AGP Capability */ +#define PCI_CAP_VPD 0x03 /* Vital Product Data */ +#define PCI_CAP_SLOT_ID 0x04 /* Bridge Slot Identification */ +#define PCI_CAP_MSI 0x05 /* Message Signaled Interrupts*/ +#define PCI_CAP_HOT_SWAP 0x06 /* CompactPCI Hot Swap */ +#define PCI_CAP_PCIX 0x07 /* PCI-X features */ +#define PCI_CAP_HYPERTRANSPORT 0x08 /* hypertransport support */ +#define PCI_CAP_VENDOR_SPECIFIC 0x09 /* vendor specific */ +#define PCI_CAP_DEBUG_PORT 0x0a /* debug port info */ +#define PCI_CAP_CPCI_RES_CTRL 0x0b /* CompactPCI resource control*/ +#define PCI_CAP_SHPC 0x0c /* hot-plug controller */ +#define PCI_CAP_P2P_SSID 0x0d /* subsystem ID capability */ +#define PCI_CAP_AGP_TARGET 0x0e /* Accelerated Graphics Port */ +#define PCI_CAP_SECURE 0x0f /* secure device */ +#define PCI_CAP_PCI_EXPRESS 0x10 /* PCI Express */ +#define PCI_CAP_MSIX 0x11 /* optional extension to MSI */ +#define PCI_CAP_ADVANCED 0x13 /* advanced Features */ + +/* Extended Capability IDs */ + +#define PCI_EXT_CAP_PCI_PM PCI_CAP_POWER_MGMT +#define PCI_EXT_CAP_AGP PCI_CAP_AGP +#define PCI_EXT_CAP_VPD PCI_CAP_VPD +#define PCI_EXT_CAP_SLOTID PCI_CAP_SLOT_ID +#define PCI_EXT_CAP_MSI PCI_CAP_MSI +#define PCI_EXT_CAP_HOT_SWAP PCI_CAP_HOT_SWAP +#define PCI_EXT_CAP_PCIX PCI_CAP_PCIX +#define PCI_EXT_CAP_DBG_PORT PCI_CAP_DEBUG_PORT +#define PCI_EXT_CAP_CPCI_RES PCI_CAP_CPCI_RES_CTRL +#define PCI_EXT_CAP_HPC PCI_CAP_SHPC +#define PCI_EXT_CAP_EXP PCI_CAP_PCI_EXPRESS +#define PCI_EXT_CAP_MSIX PCI_CAP_MSIX +#define PCI_EXT_CAP_AF PCI_CAP_ADVANCED + +/* Power Management Registers */ + +#define PCI_POWER_MGMT_CAP 2 /* PM Capabilities Register */ +#define PCI_POWER_MGMT_CSR 4 /* PM CSR Register */ +#define PCI_PM_STATE_MASK 0x0003 /* Current power state (D0 to D3) */ +#define PCI_PM_NO_SOFT_RESET 0x0008 /* No reset for D3hot->D0 */ +#define PCI_PM_PME_ENABLE 0x0100 /* PME pin enable */ +#define PCI_PM_DATA_SEL_MASK 0x1e00 /* Data select (??) */ +#define PCI_PM_DATA_SCALE_MASK 0x6000 /* Data scale (??) */ +#define PCI_PM_PME_STATUS 0x8000 /* PME pin status */ + +#define PCI_PWR_D0 0 +#define PCI_PWR_D1 1 +#define PCI_PWR_D2 2 +#define PCI_PWR_D3hot 3 +#define PCI_PWR_D3cold 4 +#define PCI_PWR_BOOTUP 5 + +#define PCI_MSI_FLAGS_ENABLE 0x1 +#define PCI_MSI_FLAGS 2 + +/* MSI-X registers (these are at offset PCI_MSIX_FLAGS) */ + +#define PCI_MSIX_FLAGS 2 +#define PCI_MSIX_FLAGS_QSIZE 0x7FF +#define PCI_MSIX_FLAGS_ENABLE (1 << 15) +#define PCI_MSIX_FLAGS_MASKALL (1 << 14) +#define PCI_MSIX_FLAGS_BIRMASK (7 << 0) +#define PCI_MSIX_TABLE_OFFSET 0x4 + +/* Macros to support Intel VT-d code */ + +#define PCI_BUS(bdf) (((bdf) >> 8) & 0xff) +#define PCI_SLOT(bdf) (((bdf) >> 3) & 0x1f) +#define PCI_FUNC(bdf) ((bdf) & 0x07) +#define PCI_DEVFN(d, f) ((((d) & 0x1f) << 3) | ((f) & 0x07)) +#define PCI_DEVFN2(bdf) ((bdf) & 0xff) +#define PCI_BDF(b, d, f) ((((b) & 0xff) << 8) | PCI_DEVFN(d, f)) +#define PCI_BDF2(b, df) ((((b) & 0xff) << 8) | ((df) & 0xff)) + +/* PCI Express capability registers */ + +#define PCI_EXP_FLAGS 2 /* Capabilities register */ +#define PCI_EXP_FLAGS_VERS 0x000f /* Capability version */ +#define PCI_EXP_FLAGS_TYPE 0x00f0 /* Device/Port type */ +#define PCI_EXP_TYPE_ENDPOINT 0x0 /* Express Endpoint */ +#define PCI_EXP_TYPE_LEG_END 0x1 /* Legacy Endpoint */ +#define PCI_EXP_TYPE_ROOT_PORT 0x4 /* Root Port */ +#define PCI_EXP_TYPE_UPSTREAM 0x5 /* Upstream Port */ +#define PCI_EXP_TYPE_DOWNSTREAM 0x6 /* Downstream Port */ +#define PCI_EXP_TYPE_PCI_BRIDGE 0x7 /* PCI/PCI-X Bridge */ +#define PCI_EXP_TYPE_RC_END 0x9 /* Root Complex Integrated endpt.*/ +#define PCI_EXP_FLAGS_SLOT 0x0100 /* Slot implemented */ +#define PCI_EXP_FLAGS_IRQ 0x3e00 /* Interrupt message number */ +#define PCI_EXP_DEVCAP 4 /* Device capabilities */ +#define PCI_EXP_DEVCAP_PAYLOAD 0x07 /* Max_Payload_Size */ +#define PCI_EXP_DEVCAP_PHANTOM 0x18 /* Phantom functions */ +#define PCI_EXP_DEVCAP_EXT_TAG 0x20 /* Extended tags */ +#define PCI_EXP_DEVCAP_L0S 0x1c0 /* L0s Acceptable Latency */ +#define PCI_EXP_DEVCAP_L1 0xe00 /* L1 Acceptable Latency */ +#define PCI_EXP_DEVCAP_ATN_BUT 0x1000 /* Attention Button Present */ +#define PCI_EXP_DEVCAP_ATN_IND 0x2000 /* Attention Indicator Present */ +#define PCI_EXP_DEVCAP_PWR_IND 0x4000 /* Power Indicator Present */ +#define PCI_EXP_DEVCAP_PWR_VAL 0x3fc0000 /* Slot Power Limit Value */ +#define PCI_EXP_DEVCAP_PWR_SCL 0xc000000 /* Slot Power Limit Scale */ +#define PCI_EXP_DEVCAP_FLR 0x10000000 /* Function Level Reset */ +#define PCI_EXP_DEVCTL 8 /* Device Control */ +#define PCI_EXP_DEVCTL_CERE 0x0001 /* Correctable Error Reporting En*/ +#define PCI_EXP_DEVCTL_NFERE 0x0002 /* Non-Fatal Error Reporting En */ +#define PCI_EXP_DEVCTL_FERE 0x0004 /* Fatal Error Reporting Enable */ +#define PCI_EXP_DEVCTL_URRE 0x0008 /* Unsupported Request Reporting */ +#define PCI_EXP_DEVCTL_RELAX_EN 0x0010 /* Enable relaxed ordering */ +#define PCI_EXP_DEVCTL_PAYLOAD 0x00e0 /* Max_Payload_Size */ +#define PCI_EXP_DEVCTL_EXT_TAG 0x0100 /* Extended Tag Field Enable */ +#define PCI_EXP_DEVCTL_PHANTOM 0x0200 /* Phantom Functions Enable */ +#define PCI_EXP_DEVCTL_AUX_PME 0x0400 /* Auxiliary Power PM Enable */ +#define PCI_EXP_DEVCTL_NOSNOOP_EN 0x0800 /* Enable No Snoop */ +#define PCI_EXP_DEVCTL_READRQ 0x7000 /* Max_Read_Request_Size */ +#define PCI_EXP_DEVCTL_BCR_FLR 0x8000 /* BCR / FLR */ +#define PCI_EXP_DEVSTA 10 /* Device Status */ +#define PCI_EXP_DEVSTA_CED 0x01 /* Correctable Error Detected */ +#define PCI_EXP_DEVSTA_NFED 0x02 /* Non-Fatal Error Detected */ +#define PCI_EXP_DEVSTA_FED 0x04 /* Fatal Error Detected */ +#define PCI_EXP_DEVSTA_URD 0x08 /* Unsupported Request Detected */ +#define PCI_EXP_DEVSTA_AUXPD 0x10 /* AUX Power Detected */ +#define PCI_EXP_DEVSTA_TRPND 0x20 /* Transactions Pending */ +#define PCI_EXP_LNKCAP 12 /* Link Capabilities */ +#define PCI_EXP_LNKCTL 16 /* Link Control */ +#define PCI_EXP_LNKCTL_CLKREQ_EN 0x100 /* Enable clkreq */ +#define PCI_EXP_LNKSTA 18 /* Link Status */ +#define PCI_EXP_SLTCAP 20 /* Slot Capabilities */ +#define PCI_EXP_SLTCTL 24 /* Slot Control */ +#define PCI_EXP_SLTSTA 26 /* Slot Status */ +#define PCI_EXP_RTCTL 28 /* Root Control */ +#define PCI_EXP_RTCTL_SECEE 0x01 /* System Error on Corr. Error */ +#define PCI_EXP_RTCTL_SENFEE 0x02 /* System Error on Non-Fatal Err */ +#define PCI_EXP_RTCTL_SEFEE 0x04 /* System Error on Fatal Error */ +#define PCI_EXP_RTCTL_PMEIE 0x08 /* PME Interrupt Enable */ +#define PCI_EXP_RTCTL_CRSSVE 0x10 /* CRS Software Visibility En */ +#define PCI_EXP_RTCAP 30 /* Root Capabilities */ +#define PCI_EXP_RTSTA 32 /* Root Status */ + +/* PCI-X registers */ + +#define PCI_X_CMD 2 + +#ifdef __cplusplus + +/* Remapped reserved C++ words */ +#undef class +} +#endif /* __cplusplus */ + +#endif /* __inc_pci_mgr_h */ diff --git a/drivers/random/rand32-timer.c b/drivers/random/rand32-timer.c new file mode 100644 index 00000000000..ee2ca906bff --- /dev/null +++ b/drivers/random/rand32-timer.c @@ -0,0 +1,78 @@ +/* rand32.c - random number generator */ + +/* + * Copyright (c) 2013-2015 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This module provides a non-random implementation of _Rand32Get(), which is not +meant to be used in a final product as a truly random number generator. It +was provided to allow testing of kernel stack canaries on a BSP that does not +(yet) provide a random number generator. +*/ + +#include +#include + +#if defined(CONFIG_TEST_RANDOM_GENERATOR) +#if defined(__GNUC__) + +/******************************************************************************* + * + * _Rand32Init - initialize the random number generator + * + * The non-random number generator does not require any initialization. + * + * RETURNS: N/A + */ + + +void _Rand32Init(void) +{ +} + +/******************************************************************************* + * + * _Rand32Get - get a 32 bit random number + * + * The non-random number generator returns values that are based off the + * target's clock counter, which means that successive calls will normally + * display ever-increasing values. + * + * RETURNS: a 32-bit number + */ + +uint32_t _Rand32Get(void) +{ + return timer_read(); +} + +#endif /* __GNUC__ */ +#endif /* CONFIG_TEST_RANDOM_GENERATOR */ diff --git a/drivers/serial/k20UartDrv.c b/drivers/serial/k20UartDrv.c new file mode 100644 index 00000000000..7977d98b21b --- /dev/null +++ b/drivers/serial/k20UartDrv.c @@ -0,0 +1,408 @@ +/* + * Copyright (c) 2013-2015 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This is the UART driver for the Freescale K20 Family of microprocessors. + +USAGE +An _K20_UART_t structure is used to describe the UART. +The BSP's _InitHardware() routine initializes all the +values in the uart_init_info structure before calling uart_init(). + +INCLUDE FILES: drivers/serial/k20Uart.h +*/ + +/* includes */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +/* typedefs */ + +typedef struct { + uint8_t *baseAddr; /* base address of registers */ + uint8_t irq; /* interrupt request level */ + uint8_t intPri; /* interrupt priority */ +} _k20Uart_t; + +/* locals */ + +static _k20Uart_t __noinit uart[CONFIG_UART_NUM_SYSTEM_PORTS]; + +/******************************************************************************* +* +* uart_init - initialize UART channel +* +* This routine is called to reset the chip in a quiescent state. +* It is assumed that this function is called only once per UART. +* +* RETURNS: N/A +*/ + +void uart_init(int which, /* UART channel to initialize */ + const struct uart_init_info * const init_info + ) +{ + int oldLevel; /* old interrupt lock level */ + K20_SIM_t *sim_p = + (K20_SIM_t *)PERIPH_ADDR_BASE_SIM; /* sys integ. ctl */ + C1_t c1; /* UART C1 register value */ + C2_t c2; /* UART C2 register value */ + + uart[which].baseAddr = (uint8_t *)init_info->regs; + uart[which].irq = init_info->irq; + uart[which].intPri = init_info->int_pri; + + K20_UART_t *uart_p = (K20_UART_t *)uart[which].baseAddr; + + /* disable interrupts */ + oldLevel = irq_lock(); + + /* enable clock to Uart - must be done prior to device access */ + _k20SimUartClkEnable(sim_p, which); + + _k20UartBaudRateSet(uart_p, init_info->sys_clk_freq, init_info->baud_rate); + + /* 1 start bit, 8 data bits, no parity, 1 stop bit */ + c1.value = 0; + + uart_p->c1 = c1; + + /* enable Rx and Tx with interrupts disabled */ + c2.value = 0; + c2.field.rxEnable = 1; + c2.field.txEnable = 1; + + uart_p->c2 = c2; + + /* restore interrupt state */ + irq_unlock(oldLevel); +} + +/******************************************************************************* +* +* uart_poll_in - poll the device for input. +* +* RETURNS: 0 if a character arrived, -1 if the input buffer if empty. +*/ + +int uart_poll_in(int which, /* UART channel to select for input */ + unsigned char *pChar /* pointer to char */ + ) +{ + K20_UART_t *uart_p = (K20_UART_t *)uart[which].baseAddr; + + if (uart_p->s1.field.rxDataFull == 0) + return (-1); + + /* got a character */ + *pChar = uart_p->d; + + return 0; +} + +/******************************************************************************* +* +* uart_poll_out - output a character in polled mode. +* +* Checks if the transmitter is empty. If empty, a character is written to +* the data register. +* +* If the hardware flow control is enabled then the handshake signal CTS has to +* be asserted in order to send a character. +* +* RETURNS: sent character +*/ +unsigned char uart_poll_out( + int which, /* UART channel to select for output */ + unsigned char outChar /* char to send */ + ) +{ + K20_UART_t *uart_p = (K20_UART_t *)uart[which].baseAddr; + + /* wait for transmitter to ready to accept a character */ + while (uart_p->s1.field.txDataEmpty == 0) + ; + + uart_p->d = outChar; + + return outChar; +} + +#if CONFIG_UART_HOSTDRV_INTERRUPT_DRIVEN + +/******************************************************************************* +* +* uart_fifo_fill - fill FIFO with data + +* RETURNS: number of bytes sent +*/ + +int uart_fifo_fill(int which, /* UART on which to send */ + const uint8_t *txData, /* data to transmit */ + int len /* number of bytes to send */ + ) +{ + K20_UART_t *uart_p = (K20_UART_t *)uart[which].baseAddr; + uint8_t numTx = 0; + + while ((len - numTx > 0) && (uart_p->s1.field.txDataEmpty == 1)) { + uart_p->d = txData[numTx++]; + } + + return numTx; +} + +/******************************************************************************* +* +* uart_fifo_read - read data from FIFO +* +* RETURNS: number of bytes read +*/ + +int uart_fifo_read(int which, /* UART to receive from */ + uint8_t *rxData, /* data container */ + const int size /* container size */ + ) +{ + K20_UART_t *uart_p = (K20_UART_t *)uart[which].baseAddr; + uint8_t numRx = 0; + + while ((size - numRx > 0) && (uart_p->s1.field.rxDataFull == 0)) { + rxData[numRx++] = uart_p->d; + } + + return numRx; +} + +/******************************************************************************* +* +* uart_irq_tx_enable - enable TX interrupt +* +* RETURNS: N/A +*/ + +void uart_irq_tx_enable(int which /* UART to enable Tx + interrupt */ + ) +{ + K20_UART_t *uart_p = (K20_UART_t *)uart[which].baseAddr; + + uart_p->c2.field.txInt_DmaTx_en = 1; +} + +/******************************************************************************* +* +* uart_irq_tx_disable - disable TX interrupt in IER +* +* RETURNS: N/A +*/ + +void uart_irq_tx_disable( + int which /* UART to disable Tx interrupt */ + ) +{ + K20_UART_t *uart_p = (K20_UART_t *)uart[which].baseAddr; + + uart_p->c2.field.txInt_DmaTx_en = 0; +} + +/******************************************************************************* +* +* uart_irq_tx_ready - check if Tx IRQ has been raised +* +* RETURNS: 1 if an IRQ is ready, 0 otherwise +*/ + +int uart_irq_tx_ready(int which /* UART to check */ + ) +{ + K20_UART_t *uart_p = (K20_UART_t *)uart[which].baseAddr; + + return uart_p->s1.field.txDataEmpty; +} + +/******************************************************************************* +* +* uart_irq_rx_enable - enable RX interrupt in IER +* +* RETURNS: N/A +*/ + +void uart_irq_rx_enable(int which /* UART to enable Rx + interrupt */ + ) +{ + K20_UART_t *uart_p = (K20_UART_t *)uart[which].baseAddr; + + uart_p->c2.field.rxFullInt_dmaTx_en = 1; +} + +/******************************************************************************* +* +* uart_irq_rx_disable - disable RX interrupt in IER +* +* RETURNS: N/A +*/ + +void uart_irq_rx_disable( + int which /* UART to disable Rx interrupt */ + ) +{ + K20_UART_t *uart_p = (K20_UART_t *)uart[which].baseAddr; + + uart_p->c2.field.rxFullInt_dmaTx_en = 0; +} + +/******************************************************************************* +* +* uart_irq_rx_ready - check if Rx IRQ has been raised +* +* RETURNS: 1 if an IRQ is ready, 0 otherwise +*/ + +int uart_irq_rx_ready(int which /* UART to check */ + ) +{ + K20_UART_t *uart_p = (K20_UART_t *)uart[which].baseAddr; + + return uart_p->s1.field.rxDataFull; +} + +/******************************************************************************* +* +* uart_irq_err_enable - enable error interrupt +* +* RETURNS: N/A +*/ + +void uart_irq_err_enable(int which) +{ + K20_UART_t *uart_p = (K20_UART_t *)uart[which].baseAddr; + C3_t c3 = uart_p->c3; + + c3.field.parityErrIntEn = 1; + c3.field.frameErrIntEn = 1; + c3.field.noiseErrIntEn = 1; + c3.field.overrunErrIntEn = 1; + uart_p->c3 = c3; +} + +/******************************************************************************* +* +* uart_irq_err_disable - disable error interrupt +* +* RETURNS: N/A +*/ + +void uart_irq_err_disable(int which /* UART to disable Rx interrupt */ + ) +{ + K20_UART_t *uart_p = (K20_UART_t *)uart[which].baseAddr; + C3_t c3 = uart_p->c3; + + c3.field.parityErrIntEn = 0; + c3.field.frameErrIntEn = 0; + c3.field.noiseErrIntEn = 0; + c3.field.overrunErrIntEn = 0; + uart_p->c3 = c3; +} + +/******************************************************************************* +* +* uart_irq_is_pending - check if Tx or Rx IRQ is pending +* +* RETURNS: 1 if a Tx or Rx IRQ is pending, 0 otherwise +*/ + +int uart_irq_is_pending(int which /* UART to check */ + ) +{ + K20_UART_t *uart_p = (K20_UART_t *)uart[which].baseAddr; + + /* Look only at Tx and Rx data interrupt flags */ + + return ((uart_p->s1.value & (TX_DATA_EMPTY_MASK | RX_DATA_FULL_MASK)) + ? 1 + : 0); +} + +/******************************************************************************* +* +* uart_irq_update - update IRQ status +* +* RETURNS: always 1 +*/ + +int uart_irq_update(int which) +{ + return 1; +} + +/******************************************************************************* +* +* uart_int_connect - connect an ISR to an interrupt line +* +* The kernel configuration allows to setup an interrupt line for a particular +* DUART. This routine installs the ISR of a UART user to the interrupt line +* chosen for the hardware at configuration time. +* +* RETURNS: N/A +*/ + +void uart_int_connect(int which, /* UART to which to connect */ + void (*isr)(void *), /* interrupt handler */ + void *arg, /* argument to pass to handler */ + void *stub /* ptr to interrupt stub code */ + ) +{ +#if !defined(CONFIG_SW_ISR_TABLE_DYNAMIC) + ARG_UNUSED(isr); + ARG_UNUSED(arg); + ARG_UNUSED(stub); +#else + irq_connect((unsigned int)uart[which].irq, + (unsigned int)uart[which].intPri, + isr, + arg); +#endif + + irq_enable((unsigned int)uart[which].irq); +} +#endif /* CONFIG_UART_HOSTDRV_INTERRUPT_DRIVEN */ diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c new file mode 100644 index 00000000000..7706e398ea9 --- /dev/null +++ b/drivers/serial/ns16550.c @@ -0,0 +1,540 @@ +/* ns16550.c - NS16550D serial driver */ + +/* + * Copyright (c) 2010, 2012-2015 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This is the driver for the Intel NS16550 UART Chip used on the PC 386. +It uses the SCCs in asynchronous mode only. + + +USAGE +An ns16550 structure is used to describe the chip. +The BSP's _InitHardware() routine initializes all the +values in the uart_init_info structure before calling uart_init(). + +A board support package's board.h header must provide definitions for: + +- the following register access routines: + + unsigned int inByte(unsigned int address); + void outByte(unsigned char data, unsigned int address); + +- and the following macro for the number of bytes between register addresses: + + UART_REG_ADDR_INTERVAL + + +INCLUDE FILES: drivers/uart.h +*/ + +/* includes */ + +#include +#include +#include + +#include +#include +#include +#include + +/* defines */ + +/* register definitions */ + +#define REG_THR 0x00 /* Transmitter holding reg. */ +#define REG_RDR 0x00 /* Receiver data reg. */ +#define REG_BRDL 0x00 /* Baud rate divisor (LSB) */ +#define REG_BRDH 0x01 /* Baud rate divisor (MSB) */ +#define REG_IER 0x01 /* Interrupt enable reg. */ +#define REG_IIR 0x02 /* Interrupt ID reg. */ +#define REG_FCR 0x02 /* FIFO control reg. */ +#define REG_LCR 0x03 /* Line control reg. */ +#define REG_MDC 0x04 /* Modem control reg. */ +#define REG_LSR 0x05 /* Line status reg. */ +#define REG_MSR 0x06 /* Modem status reg. */ + +/* equates for interrupt enable register */ + +#define IER_RXRDY 0x01 /* receiver data ready */ +#define IER_TBE 0x02 /* transmit bit enable */ +#define IER_LSR 0x04 /* line status interrupts */ +#define IER_MSI 0x08 /* modem status interrupts */ + +/* equates for interrupt identification register */ + +#define IIR_IP 0x01 /* interrupt pending bit */ +#define IIR_MASK 0x07 /* interrupt id bits mask */ +#define IIR_MSTAT 0x00 /* modem status interrupt */ +#define IIR_THRE 0X02 /* transmit holding register empty */ +#define IIR_RBRF 0x04 /* receiver buffer register full */ +#define IIR_ID 0x06 /* interupt ID mask without IP */ +#define IIR_SEOB 0x06 /* serialization error or break */ + +/* equates for FIFO control register */ + +#define FCR_FIFO 0x01 /* enable XMIT and RCVR FIFO */ +#define FCR_RCVRCLR 0x02 /* clear RCVR FIFO */ +#define FCR_XMITCLR 0x04 /* clear XMIT FIFO */ + +/* + * Per PC16550D (Literature Number: SNLS378B): + * + * RXRDY, Mode 0: When in the 16450 Mode (FCR0 = 0) or in + * the FIFO Mode (FCR0 = 1, FCR3 = 0) and there is at least 1 + * character in the RCVR FIFO or RCVR holding register, the + * RXRDY pin (29) will be low active. Once it is activated the + * RXRDY pin will go inactive when there are no more charac- + * ters in the FIFO or holding register. + * + * RXRDY, Mode 1: In the FIFO Mode (FCR0 = 1) when the + * FCR3 = 1 and the trigger level or the timeout has been + * reached, the RXRDY pin will go low active. Once it is acti- + * vated it will go inactive when there are no more characters + * in the FIFO or holding register. + * + * TXRDY, Mode 0: In the 16450 Mode (FCR0 = 0) or in the + * FIFO Mode (FCR0 = 1, FCR3 = 0) and there are no charac- + * ters in the XMIT FIFO or XMIT holding register, the TXRDY + * pin (24) will be low active. Once it is activated the TXRDY + * pin will go inactive after the first character is loaded into the + * XMIT FIFO or holding register. + * + * TXRDY, Mode 1: In the FIFO Mode (FCR0 = 1) when + * FCR3 = 1 and there are no characters in the XMIT FIFO, the + * TXRDY pin will go low active. This pin will become inactive + * when the XMIT FIFO is completely full. + */ +#define FCR_MODE0 0x00 /* set receiver in mode 0 */ +#define FCR_MODE1 0x08 /* set receiver in mode 1 */ + +/* RCVR FIFO interrupt levels: trigger interrupt with this bytes in FIFO */ +#define FCR_FIFO_1 0x00 /* 1 byte in RCVR FIFO */ +#define FCR_FIFO_4 0x40 /* 4 bytes in RCVR FIFO */ +#define FCR_FIFO_8 0x80 /* 8 bytes in RCVR FIFO */ +#define FCR_FIFO_14 0xC0 /* 14 bytes in RCVR FIFO */ + +/* constants for line control register */ + +#define LCR_CS5 0x00 /* 5 bits data size */ +#define LCR_CS6 0x01 /* 6 bits data size */ +#define LCR_CS7 0x02 /* 7 bits data size */ +#define LCR_CS8 0x03 /* 8 bits data size */ +#define LCR_2_STB 0x04 /* 2 stop bits */ +#define LCR_1_STB 0x00 /* 1 stop bit */ +#define LCR_PEN 0x08 /* parity enable */ +#define LCR_PDIS 0x00 /* parity disable */ +#define LCR_EPS 0x10 /* even parity select */ +#define LCR_SP 0x20 /* stick parity select */ +#define LCR_SBRK 0x40 /* break control bit */ +#define LCR_DLAB 0x80 /* divisor latch access enable */ + +/* constants for the modem control register */ + +#define MCR_DTR 0x01 /* dtr output */ +#define MCR_RTS 0x02 /* rts output */ +#define MCR_OUT1 0x04 /* output #1 */ +#define MCR_OUT2 0x08 /* output #2 */ +#define MCR_LOOP 0x10 /* loop back */ + +/* constants for line status register */ + +#define LSR_RXRDY 0x01 /* receiver data available */ +#define LSR_OE 0x02 /* overrun error */ +#define LSR_PE 0x04 /* parity error */ +#define LSR_FE 0x08 /* framing error */ +#define LSR_BI 0x10 /* break interrupt */ +#define LSR_THRE 0x20 /* transmit holding register empty */ +#define LSR_TEMT 0x40 /* transmitter empty */ + +/* constants for modem status register */ + +#define MSR_DCTS 0x01 /* cts change */ +#define MSR_DDSR 0x02 /* dsr change */ +#define MSR_DRI 0x04 /* ring change */ +#define MSR_DDCD 0x08 /* data carrier change */ +#define MSR_CTS 0x10 /* complement of cts */ +#define MSR_DSR 0x20 /* complement of dsr */ +#define MSR_RI 0x40 /* complement of ring signal */ +#define MSR_DCD 0x80 /* complement of dcd */ + +/* convenience defines */ + +#define THR(n) (uart[n].port + REG_THR * UART_REG_ADDR_INTERVAL) +#define RDR(n) (uart[n].port + REG_RDR * UART_REG_ADDR_INTERVAL) +#define BRDL(n) (uart[n].port + REG_BRDL * UART_REG_ADDR_INTERVAL) +#define BRDH(n) (uart[n].port + REG_BRDH * UART_REG_ADDR_INTERVAL) +#define IER(n) (uart[n].port + REG_IER * UART_REG_ADDR_INTERVAL) +#define IIR(n) (uart[n].port + REG_IIR * UART_REG_ADDR_INTERVAL) +#define FCR(n) (uart[n].port + REG_FCR * UART_REG_ADDR_INTERVAL) +#define LCR(n) (uart[n].port + REG_LCR * UART_REG_ADDR_INTERVAL) +#define MDC(n) (uart[n].port + REG_MDC * UART_REG_ADDR_INTERVAL) +#define LSR(n) (uart[n].port + REG_LSR * UART_REG_ADDR_INTERVAL) +#define MSR(n) (uart[n].port + REG_MSR * UART_REG_ADDR_INTERVAL) + +#define IIRC(n) uart[n].iirCache + +#define INBYTE(x) inByte(x) +#define OUTBYTE(x, d) outByte(d, x) + +#if defined(VXMICRO_ARCH_Intel) +#define INT_CONNECT(which, isr, arg, stub) \ + irq_connect((unsigned int)uart[which].irq, \ + (unsigned int)uart[which].intPri, \ + isr, \ + arg, \ + stub) +#else +#define INT_CONNECT(which, isr, arg, stub) \ + do { \ + ARG_UNUSED(stub); \ + irq_connect((unsigned int)uart[which].irq, \ + (unsigned int)uart[which].intPri, \ + isr, \ + arg); \ + } while (0) +#endif /* VXMICRO_ARCH_Intel */ + +/* typedefs */ + +struct ns16550 { + uint32_t port; /* base port number or MM base address */ + uint8_t irq; /* interrupt request level */ + uint8_t intPri; /* interrupt priority */ + uint8_t iirCache; /* cache of IIR since it clears when read */ +}; + +/* locals */ + +static struct ns16550 __noinit uart[CONFIG_UART_NUM_SYSTEM_PORTS]; + +/******************************************************************************* +* +* uart_init - initialize the chip +* +* This routine is called to reset the chip in a quiescent state. +* +* RETURNS: N/A +*/ + +void uart_init(int which, /* UART channel to initialize */ + const struct uart_init_info * const init_info + ) +{ + int oldLevel; /* old interrupt lock level */ + uint32_t divisor; /* baud rate divisor */ + + uart[which].port = init_info->regs; + uart[which].irq = init_info->irq; + uart[which].intPri = init_info->int_pri; + uart[which].iirCache = 0; + + oldLevel = irq_lock(); + + /* calculate baud rate divisor */ + divisor = (init_info->sys_clk_freq / init_info->baud_rate) >> 4; + + /* set the DLAB to access the baud rate divisor registers */ + OUTBYTE(LCR(which), LCR_DLAB); + OUTBYTE(BRDL(which), (unsigned char)(divisor & 0xff)); + OUTBYTE(BRDH(which), (unsigned char)((divisor >> 8) & 0xff)); + + /* 8 data bits, 1 stop bit, no parity, clear DLAB */ + OUTBYTE(LCR(which), LCR_CS8 | LCR_1_STB | LCR_PDIS); + + OUTBYTE(MDC(which), MCR_OUT2 | MCR_RTS | MCR_DTR); + + /* + * Program FIFO: enabled, mode 0 (set for compatibility with quark), + * generate the interrupt at 8th byte + * Clear TX and RX FIFO + */ + OUTBYTE(FCR(which), + FCR_FIFO | FCR_MODE0 | FCR_FIFO_8 | FCR_RCVRCLR | FCR_XMITCLR); + + /* clear the port */ + INBYTE(RDR(which)); + + /* disable interrupts */ + OUTBYTE(IER(which), 0x00); + + irq_unlock(oldLevel); +} + +/******************************************************************************* +* +* uart_poll_in - poll the device for input. +* +* RETURNS: 0 if a character arrived, -1 if the input buffer if empty. +*/ + +int uart_poll_in(int which, /* UART channel to select for input */ + unsigned char *pChar /* pointer to char */ + ) +{ + if ((INBYTE(LSR(which)) & LSR_RXRDY) == 0x00) + return (-1); + + /* got a character */ + *pChar = INBYTE(RDR(which)); + + return 0; +} + +/******************************************************************************* +* +* uart_poll_out - output a character in polled mode. +* +* Checks if the transmitter is empty. If empty, a character is written to +* the data register. +* +* If the hardware flow control is enabled then the handshake signal CTS has to +* be asserted in order to send a character. +* +* RETURNS: sent character +*/ +unsigned char uart_poll_out( + int which, /* UART channel to select for output */ + unsigned char outChar /* char to send */ + ) +{ + /* wait for transmitter to ready to accept a character */ + while ((INBYTE(LSR(which)) & LSR_TEMT) == 0) + ; + + OUTBYTE(THR(which), outChar); + + return outChar; +} + +#if CONFIG_UART_HOSTDRV_INTERRUPT_DRIVEN +/******************************************************************************* +* +* uart_fifo_fill - fill FIFO with data +* +* RETURNS: number of bytes sent +*/ + +int uart_fifo_fill(int which, /* UART on which to send */ + const uint8_t *txData, /* data to transmit */ + int size /* number of bytes to send */ + ) +{ + int i; + for (i = 0; i < size && (INBYTE(LSR(which)) & LSR_THRE) != 0; i++) { + OUTBYTE(THR(which), txData[i]); + } + return i; +} + +/******************************************************************************* +* +* uart_fifo_read - read data from FIFO +* +* RETURNS: number of bytes read +*/ + +int uart_fifo_read(int which, /* UART to receive from */ + uint8_t *rxData, /* data container */ + const int size /* container size */ + ) +{ + int i; + for (i = 0; i < size && (INBYTE(LSR(which)) & LSR_RXRDY) != 0; i++) { + rxData[i] = INBYTE(RDR(which)); + } + + return i; +} + +/******************************************************************************* +* +* uart_irq_tx_enable - enable TX interrupt in IER +* +* RETURNS: N/A +*/ + +void uart_irq_tx_enable(int which /* UART to enable Tx + interrupt */ + ) +{ + OUTBYTE(IER(which), INBYTE(IER(which)) | IER_TBE); +} + +/******************************************************************************* +* +* uart_irq_tx_disable - disable TX interrupt in IER +* +* RETURNS: N/A +*/ + +void uart_irq_tx_disable(int which /* UART to disable Tx interrupt */ + ) +{ + OUTBYTE(IER(which), INBYTE(IER(which)) & (~IER_TBE)); +} + +/******************************************************************************* +* +* uart_irq_tx_ready - check if Tx IRQ has been raised +* +* RETURNS: N/A +*/ + +int uart_irq_tx_ready(int which /* UART to check */ + ) +{ + return ((IIRC(which) & IIR_ID) == IIR_THRE); +} + +/******************************************************************************* +* +* _uart_irq_rx_enable - enable RX interrupt in IER +* +* RETURNS: N/A +*/ + +void uart_irq_rx_enable(int which /* UART to enable Rx + interrupt */ + ) +{ + OUTBYTE(IER(which), INBYTE(IER(which)) | IER_RXRDY); +} + +/******************************************************************************* +* +* uart_irq_rx_disable - disable RX interrupt in IER +* +* RETURNS: N/A +*/ + +void uart_irq_rx_disable(int which /* UART to disable Rx interrupt */ + ) +{ + OUTBYTE(IER(which), INBYTE(IER(which)) & (~IER_RXRDY)); +} + +/******************************************************************************* +* +* uart_irq_rx_ready - check if Rx IRQ has been raised +* +* RETURNS: 1 if an IRQ is ready, 0 otherwise +*/ + +int uart_irq_rx_ready(int which /* UART to check */ + ) +{ + return ((IIRC(which) & IIR_ID) == IIR_RBRF); +} + +/******************************************************************************* +* +* uart_irq_err_enable - enable error interrupt in IER +* +* RETURNS: N/A +*/ + +void uart_irq_err_enable(int which /* UART to enable Rx interrupt */ + ) +{ + OUTBYTE(IER(which), INBYTE(IER(which)) | IER_LSR); +} + +/******************************************************************************* +* +* uart_irq_err_disable - disable error interrupt in IER +* +* RETURNS: 1 if an IRQ is ready, 0 otherwise +*/ + +void uart_irq_err_disable(int which /* UART to disable Rx interrupt */ + ) +{ + OUTBYTE(IER(which), INBYTE(IER(which)) & (~IER_LSR)); +} + +/******************************************************************************* +* +* uart_irq_is_pending - check if any IRQ is pending +* +* RETURNS: 1 if an IRQ is pending, 0 otherwise +*/ + +int uart_irq_is_pending(int which /* UART to check */ + ) +{ + return (!(IIRC(which) & IIR_IP)); +} + +/******************************************************************************* +* +* uart_irq_update - update cached contents of IIR +* +* RETURNS: always 1 +*/ + +int uart_irq_update(int which /* UART to update */ + ) +{ + IIRC(which) = INBYTE(IIR(which)); + + return 1; +} + +/******************************************************************************* +* +* uart_int_connect - connect an ISR to an interrupt line +* +* The kernel configuration allows to setup an interrupt line for a particular +* DUART. This routine installs the ISR of a UART user to the interrupt line +* chosen for the hardware at configuration time. +* +* RETURNS: N/A +*/ + +void uart_int_connect(int which, /* UART to which to connect */ + void (*isr)(void *), /* interrupt handler */ + void *arg, /* argument to pass to handler */ + void *stub /* ptr to interrupt stub code */ + ) +{ +#if !defined(CONFIG_DYNAMIC_INT_STUBS) + ARG_UNUSED(isr); + ARG_UNUSED(arg); + ARG_UNUSED(stub); +#else + INT_CONNECT(which, isr, arg, stub); +#endif /* CONFIG_DYNAMIC_INT_STUBS */ + + irq_enable((unsigned int)uart[which].irq); +} +#endif /* CONFIG_UART_HOSTDRV_INTERRUPT_DRIVEN */ diff --git a/drivers/serial/stellarisUartDrv.c b/drivers/serial/stellarisUartDrv.c new file mode 100644 index 00000000000..392efbe33f2 --- /dev/null +++ b/drivers/serial/stellarisUartDrv.c @@ -0,0 +1,597 @@ +/* stellarisUartDrv.c - Stellaris UART driver */ + +/* + * Copyright (c) 2013-2015 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +Driver for Stellaris UART found namely on TI LM3S6965 board. It is similar to +an 16550 in functionality, but is not register-compatible. + +There is only support for poll-mode, so it can only be used with the printk +and STDOUT_CONSOLE APIs. +*/ + +#include +#include +#include +#include +#include +#include + +/* definitions */ + +/* Stellaris UART module */ +struct _Uart { + uint32_t dr; + union { + uint32_t _sr; + uint32_t _cr; + } u1; + uint8_t _res1[0x010]; + uint32_t fr; + uint8_t _res2[0x04]; + uint32_t ilpr; + uint32_t ibrd; + uint32_t fbrd; + uint32_t lcrh; + uint32_t ctl; + uint32_t ifls; + uint32_t im; + uint32_t ris; + uint32_t mis; + uint32_t icr; + uint8_t _res3[0xf8c]; + + uint32_t PeriphID4; + uint32_t PeriphID5; + uint32_t PeriphID6; + uint32_t PeriphID7; + uint32_t PeriphID0; + uint32_t PeriphID1; + uint32_t PeriphID2; + uint32_t PeriphID3; + + uint32_t PCellID0; + uint32_t PCellID1; + uint32_t PCellID2; + uint32_t PCellID3; +}; + +/* registers */ +#define UARTDR(n) *((volatile uint32_t *)(ports[n].base + 0x000)) +#define UARTSR(n) *((volatile uint32_t *)(ports[n].base + 0x004)) +#define UARTCR(n) *((volatile uint32_t *)(ports[n].base + 0x004)) +#define UARTFR(n) *((volatile uint32_t *)(ports[n].base + 0x018)) +#define UARTILPR(n) *((volatile uint32_t *)(ports[n].base + 0x020)) +#define UARTIBRD(n) *((volatile uint32_t *)(ports[n].base + 0x024)) +#define UARTFBRD(n) *((volatile uint32_t *)(ports[n].base + 0x028)) +#define UARTLCRH(n) *((volatile uint32_t *)(ports[n].base + 0x02C)) +#define UARTCTL(n) *((volatile uint32_t *)(ports[n].base + 0x030)) +#define UARTIFLS(n) *((volatile uint32_t *)(ports[n].base + 0x034)) +#define UARTIM(n) *((volatile uint32_t *)(ports[n].base + 0x038)) +#define UARTRIS(n) *((volatile uint32_t *)(ports[n].base + 0x03C)) +#define UARTMIS(n) *((volatile uint32_t *)(ports[n].base + 0x040)) +#define UARTICR(n) *((volatile uint32_t *)(ports[n].base + 0x044)) + +/* ID registers: UARTPID = UARTPeriphID, UARTPCID = UARTPCellId */ +#define UARTPID4(n) *((volatile uint32_t *)(ports[n].base + 0xFD0)) +#define UARTPID5(n) *((volatile uint32_t *)(ports[n].base + 0xFD4)) +#define UARTPID6(n) *((volatile uint32_t *)(ports[n].base + 0xFD8)) +#define UARTPID7(n) *((volatile uint32_t *)(ports[n].base + 0xFDC)) +#define UARTPID0(n) *((volatile uint32_t *)(ports[n].base + 0xFE0)) +#define UARTPID1(n) *((volatile uint32_t *)(ports[n].base + 0xFE4)) +#define UARTPID2(n) *((volatile uint32_t *)(ports[n].base + 0xFE8)) +#define UARTPID3(n) *((volatile uint32_t *)(ports[n].base + 0xFEC)) +#define UARTPCID0(n) *((volatile uint32_t *)(ports[n].base + 0xFF0)) +#define UARTPCID1(n) *((volatile uint32_t *)(ports[n].base + 0xFF4)) +#define UARTPCID2(n) *((volatile uint32_t *)(ports[n].base + 0xFF8)) +#define UARTPCID3(n) *((volatile uint32_t *)(ports[n].base + 0xFFC)) + +/* muxed UART registers */ +#define sr u1._sr /* Read: receive status */ +#define cr u1._cr /* Write: receive error clear */ + +/* bits */ +#define UARTFR_BUSY 0x00000008 +#define UARTFR_RXFE 0x00000010 +#define UARTFR_TXFF 0x00000020 +#define UARTFR_RXFF 0x00000040 +#define UARTFR_TXFE 0x00000080 + +#define UARTLCRH_FEN 0x00000010 +#define UARTLCRH_WLEN 0x00000060 + +#define UARTCTL_UARTEN 0x00000001 +#define UARTCTL_LBE 0x00000800 +#define UARTCTL_TXEN 0x00000100 +#define UARTCTL_RXEN 0x00000200 + +#define UARTTIM_RXIM 0x00000010 +#define UARTTIM_TXIM 0x00000020 +#define UARTTIM_RTIM 0x00000040 +#define UARTTIM_FEIM 0x00000080 +#define UARTTIM_PEIM 0x00000100 +#define UARTTIM_BEIM 0x00000200 +#define UARTTIM_OEIM 0x00000400 + +#define UARTMIS_RXMIS 0x00000010 +#define UARTMIS_TXMIS 0x00000020 + +struct _StellarisUartPort { + void *base; /* base address of registers */ + uint8_t irq; /* interrupt request number */ + uint8_t intPri; /* interrupt priority level */ +}; + +static struct _StellarisUartPort ports[CONFIG_UART_NUM_PORTS] = { { 0 } }; + +/******************************************************************************* +* +* baudrateSet - set the baud rate +* +* This routine set the given baud rate for the UART. +* +* RETURNS: N/A +*/ + +static void baudrateSet(int port, uint32_t baudrate, uint32_t sysClkFreqInHz) +{ + volatile struct _Uart *pUart = ports[port].base; + uint32_t brdi, brdf, div, rem; + /* upon reset, the system clock uses the intenal OSC @ 12MHz */ + + div = (16 * baudrate); + rem = sysClkFreqInHz % div; + + /* floating part of baud rate (LM3S6965 p.433), equivalent to + * [float part of (SYSCLK / div)] * 64 + 0.5 */ + brdf = ((((rem * 64) << 1) / div) + 1) >> 1; + + /* integer part of baud rate (LM3S6965 p.433) */ + brdi = sysClkFreqInHz / div; + + /* those registers are 32-bit, but the reserved bits should be + * preserved */ + pUart->ibrd = (uint16_t)(brdi & 0xffff); /* 16 bits */ + pUart->fbrd = (uint8_t)(brdf & 0x3f); /* 6 bits */ +} + +/******************************************************************************* +* +* enable - enable the UART +* +* This routine enables the given UART. +* +* RETURNS: N/A +*/ + +static inline void enable(int port) +{ + volatile struct _Uart *pUart = ports[port].base; + pUart->ctl |= UARTCTL_UARTEN; +} + +/******************************************************************************* +* +* disable - disable the UART +* +* This routine disables the given UART. +* +* RETURNS: N/A +*/ + +static inline void disable(int port) +{ + volatile struct _Uart *pUart = ports[port].base; + + pUart->ctl &= ~UARTCTL_UARTEN; + + /* ensure transmissions are complete */ + while (pUart->fr & UARTFR_BUSY) + ; + + /* flush the FIFOs by disabling them */ + pUart->lcrh &= ~UARTLCRH_FEN; +} + +/* + * no stick parity + * 8-bit frame + * FIFOs disabled + * one stop bit + * parity disabled + * send break off + */ +#define LINE_CONTROL_DEFAULTS UARTLCRH_WLEN + +/******************************************************************************* +* +* lineControlDefaultsSet - set the default UART line controls +* +* This routine sets the given UART's line controls to their default settings. +* +* RETURNS: N/A +*/ + +static inline void lineControlDefaultsSet(int port) +{ + volatile struct _Uart *pUart = ports[port].base; + pUart->lcrh = LINE_CONTROL_DEFAULTS; +} + +/******************************************************************************* +* +* uart_init - initialize UART channel +* +* This routine is called to reset the chip in a quiescent state. +* It is assumed that this function is called only once per UART. +* +* RETURNS: N/A +*/ +void uart_init(int port, /* UART channel to initialize */ + const struct uart_init_info * const init_info + ) +{ + ports[port].base = (void *)init_info->regs; + ports[port].irq = init_info->irq; + ports[port].intPri = init_info->int_pri; + + disable(port); + baudrateSet(port, init_info->baud_rate, init_info->sys_clk_freq); + lineControlDefaultsSet(port); + enable(port); +} + +/******************************************************************************* +* +* pollTxReady - get the UART transmit ready status +* +* This routine returns the given UART's transmit ready status. +* +* RETURNS: 0 if ready to transmit, 1 otherwise +*/ + +static int pollTxReady(int port) +{ + volatile struct _Uart *pUart = ports[port].base; + return (pUart->fr & UARTFR_TXFE); +} + +/******************************************************************************* +* +* uart_poll_in - poll the device for input. +* +* RETURNS: 0 if a character arrived, -1 if the input buffer if empty. +*/ + +int uart_poll_in(int port, /* UART channel to select for input */ + unsigned char *pChar /* pointer to char */ + ) +{ + volatile struct _Uart *pUart = ports[port].base; + + if (pUart->fr & UARTFR_RXFE) + return (-1); + + /* got a character */ + *pChar = (unsigned char)pUart->dr; + + return 0; +} + +/******************************************************************************* +* +* uart_poll_out - output a character in polled mode. +* +* Checks if the transmitter is empty. If empty, a character is written to +* the data register. +* +* RETURNS: sent character +*/ +unsigned char uart_poll_out(int port, unsigned char c) +{ + volatile struct _Uart *pUart = ports[port].base; + + while (!pollTxReady(port)) + ; + + /* send a character */ + pUart->dr = (uint32_t)c; + return c; +} + +#if CONFIG_UART_HOSTDRV_INTERRUPT_DRIVEN + +/******************************************************************************* +* +* uart_fifo_fill - fill FIFO with data +* +* RETURNS: number of bytes sent +*/ + +int uart_fifo_fill(int port, /* UART on which to send */ + const uint8_t *txData, /* data to transmit */ + int len /* number of bytes to send */ + ) +{ + volatile struct _Uart *pUart = ports[port].base; + uint8_t numTx = 0; + + while ((len - numTx > 0) && ((pUart->fr & UARTFR_TXFF) == 0)) { + pUart->dr = (uint32_t)txData[numTx++]; + } + + return (int)numTx; +} + +/******************************************************************************* +* +* uart_fifo_read - read data from FIFO +* +* RETURNS: number of bytes read +*/ + +int uart_fifo_read(int port, /* UART to receive from */ + uint8_t *rxData, /* data container */ + const int size /* container size */ + ) +{ + volatile struct _Uart *pUart = ports[port].base; + uint8_t numRx = 0; + + while ((size - numRx > 0) && ((pUart->fr & UARTFR_RXFE) == 0)) { + rxData[numRx++] = (uint8_t)pUart->dr; + } + + return numRx; +} + +/******************************************************************************* +* +* uart_irq_tx_enable - enable TX interrupt +* +* RETURNS: N/A +*/ + +void uart_irq_tx_enable(int port /* UART to enable Tx interrupt */ + ) +{ + static uint8_t first_time = + 1; /* used to allow the first transmission */ + uint32_t saved_ctl; /* saved UARTCTL (control) register */ + uint32_t saved_ibrd; /* saved UARTIBRD (integer baud rate) register */ + uint32_t saved_fbrd; /* saved UARTFBRD (fractional baud rate) register + */ + volatile struct _Uart *pUart = ports[port].base; + + if (first_time) { + /* + * The Tx interrupt will not be set when transmission is first + * enabled. + * A character has to be transmitted before Tx interrupts will + * work, + * so send one via loopback mode. + */ + first_time = 0; + + /* save current control and baud rate settings */ + saved_ctl = pUart->ctl; + saved_ibrd = pUart->ibrd; + saved_fbrd = pUart->fbrd; + + /* send a character with default settings via loopback */ + disable(port); + pUart->fbrd = 0; + pUart->ibrd = 1; + pUart->lcrh = 0; + pUart->ctl = (UARTCTL_UARTEN | UARTCTL_TXEN | UARTCTL_LBE); + pUart->dr = 0; + + while (pUart->fr & UARTFR_BUSY) + ; + + /* restore control and baud rate settings */ + disable(port); + pUart->ibrd = saved_ibrd; + pUart->fbrd = saved_fbrd; + lineControlDefaultsSet(port); + pUart->ctl = saved_ctl; + } + + pUart->im |= UARTTIM_TXIM; +} + +/******************************************************************************* +* +* uart_irq_tx_disable - disable TX interrupt in IER +* +* RETURNS: N/A +*/ + +void uart_irq_tx_disable(int port /* UART to disable Tx interrupt */ + ) +{ + volatile struct _Uart *pUart = ports[port].base; + + pUart->im &= ~UARTTIM_TXIM; +} + +/******************************************************************************* +* +* uart_irq_tx_ready - check if Tx IRQ has been raised +* +* RETURNS: 1 if a Tx IRQ is pending, 0 otherwise +*/ + +int uart_irq_tx_ready(int port /* UART to check */ + ) +{ + volatile struct _Uart *pUart = ports[port].base; + + return ((pUart->mis & UARTMIS_TXMIS) == UARTMIS_TXMIS); +} + +/******************************************************************************* +* +* uart_irq_rx_enable - enable RX interrupt in IER +* +* RETURNS: N/A +*/ + +void uart_irq_rx_enable(int port /* UART to enable Rx interrupt */ + ) +{ + volatile struct _Uart *pUart = ports[port].base; + + pUart->im |= UARTTIM_RXIM; +} + +/******************************************************************************* +* +* uart_irq_rx_disable - disable RX interrupt in IER +* +* RETURNS: N/A +*/ + +void uart_irq_rx_disable(int port /* UART to disable Rx interrupt */ + ) +{ + volatile struct _Uart *pUart = ports[port].base; + + pUart->im &= ~UARTTIM_RXIM; +} + +/******************************************************************************* +* +* uart_irq_rx_ready - check if Rx IRQ has been raised +* +* RETURNS: 1 if an IRQ is ready, 0 otherwise +*/ + +int uart_irq_rx_ready(int port /* UART to check */ + ) +{ + volatile struct _Uart *pUart = ports[port].base; + + return ((pUart->mis & UARTMIS_RXMIS) == UARTMIS_RXMIS); +} + +/******************************************************************************* +* +* uart_irq_err_enable - enable error interrupts +* +* RETURNS: N/A +*/ + +void uart_irq_err_enable(int port /* UART to enable interrupts for */ + ) +{ + volatile struct _Uart *pUart = ports[port].base; + + pUart->im |= (UARTTIM_RTIM | UARTTIM_FEIM | UARTTIM_PEIM | + UARTTIM_BEIM | UARTTIM_OEIM); +} + +/******************************************************************************* +* +* uart_irq_err_disable - disable error interrupts +* +* RETURNS: N/A +*/ + +void uart_irq_err_disable(int port /* UART to disable interrupts for */ + ) +{ + volatile struct _Uart *pUart = ports[port].base; + + pUart->im &= ~(UARTTIM_RTIM | UARTTIM_FEIM | UARTTIM_PEIM | + UARTTIM_BEIM | UARTTIM_OEIM); +} + +/******************************************************************************* +* +* uart_irq_is_pending - check if Tx or Rx IRQ is pending +* +* RETURNS: 1 if a Tx or Rx IRQ is pending, 0 otherwise +*/ + +int uart_irq_is_pending(int port /* UART to check */ + ) +{ + volatile struct _Uart *pUart = ports[port].base; + + /* Look only at Tx and Rx data interrupt flags */ + return ((pUart->mis & (UARTMIS_RXMIS | UARTMIS_TXMIS)) ? 1 : 0); +} + +/******************************************************************************* +* +* uart_irq_update - update IRQ status +* +* RETURNS: always 1 +*/ + +int uart_irq_update(int port) +{ + return 1; +} + +/******************************************************************************* +* +* uart_int_connect - connect an ISR to an interrupt line +* +* The kernel configuration allows to setup an interrupt line for a particular +* UART. This routine installs the ISR of a UART user to the interrupt line +* chosen for the hardware at configuration time. +* +* RETURNS: N/A +*/ + +void uart_int_connect(int port, /* UART port to connect to */ + void (*isr)(void *), /* interrupt handler */ + void *arg, /* argument to pass to handler */ + void *stub /* ptr to interrupt stub code */ + ) +{ +#if !defined(CONFIG_SW_ISR_TABLE_DYNAMIC) + ARG_UNUSED(isr); + ARG_UNUSED(arg); + ARG_UNUSED(stub); +#else + irq_connect((unsigned int)ports[port].irq, + (unsigned int)ports[port].intPri, + isr, + arg); +#endif + + irq_enable((unsigned int)ports[port].irq); +} +#endif /* CONFIG_UART_HOSTDRV_INTERRUPT_DRIVEN */ diff --git a/drivers/timer/i8253.c b/drivers/timer/i8253.c new file mode 100644 index 00000000000..73b5a2c3072 --- /dev/null +++ b/drivers/timer/i8253.c @@ -0,0 +1,660 @@ +/* i8253.c - Intel 8253 PIT (Programmable Interval Timer) driver */ + +/* + * Copyright (c) 2010-2015 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This module implements a VxMicro device driver for the Intel 8253 PIT +(Programmable Interval Timer) device, and provides the standard "system +clock driver" interfaces. + +Channel 0 is programmed to operate in "Interrupt on Terminal Count" mode, +with the interrupt rate determined by the 'sys_clock_us_per_tick' +global variable. +Changing the interrupt rate at runtime is not supported. + +Generally, this module is not utilized in Wind River Hypervisor systems; +instead the Hypervisor tick timer service is utilized to deliver system clock +ticks into the guest operating system. However, this driver has been modified +to access the PIT in scenarios where the PIT registers are mapped into a guest. +An interrupt controller driver will not be utilized, so this driver will +directly invoke the VIOAPIC APIs to configure/unmask the IRQ. +*/ + +/* includes */ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_MICROKERNEL + +#include +#include + +#endif /* CONFIG_MICROKERNEL */ + +/* + * A board support package's board.h header must provide definitions for the + * following constants: + * + * PIC_REG_ADDR_INTERVAL + * PIT_BASE_ADRS + * PIT_CLOCK_FREQ + * PIT_INT_LVL + * PIT_INT_VEC + * + * ...and the following register access macros: + * + * PLB_BYTE_REG_WRITE + * PLB_BYTE_REG_READ + */ + +#include + +/* defines */ + +#if defined(CONFIG_TICKLESS_IDLE) +#define TIMER_SUPPORTS_TICKLESS +#endif + +#if defined(TIMER_SUPPORTS_TICKLESS) + +#define TIMER_MODE_PERIODIC 0 +#define TIMER_MODE_PERIODIC_ENT 1 + +#else /* !TIMER_SUPPORTS_TICKLESS */ + +#define _i8253TicklessIdleInit() \ + do {/* nothing */ \ + } while ((0)) +#define _i8253TicklessIdleSkew() \ + do {/* nothing */ \ + } while (0) + +#endif /* !TIMER_SUPPORTS_TICKLESS */ + +/* register definitions */ + +#define PIT_ADRS(base, reg) (base + (reg * PIT_REG_ADDR_INTERVAL)) + +#define PIT_CNT0(base) PIT_ADRS(base, 0x00) /* counter/channel 0 */ +#define PIT_CNT1(base) PIT_ADRS(base, 0x01) /* counter/channel 1 */ +#define PIT_CNT2(base) PIT_ADRS(base, 0x02) /* counter/channel 2 */ +#define PIT_CMD(base) PIT_ADRS(base, 0x03) /* control word */ + +/* globals */ + +#if defined(TIMER_SUPPORTS_TICKLESS) +extern int32_t _SysIdleElapsedTicks; +#endif + +/* locals */ + +/* interrupt stub memory for irq_connect() */ + +#ifndef CONFIG_DYNAMIC_INT_STUBS +extern void *_i8253IntStub; +SYS_INT_REGISTER(_i8253IntStub, PIT_INT_LVL, PIT_INT_PRI); +#else +static NANO_CPU_INT_STUB_DECL(_i8253IntStub); +#endif + +static uint16_t __noinit counterLoadVal; /* computed counter */ +static volatile uint32_t accumulatedCount = 0; +static uint16_t _currentLoadVal = 0; + +#if defined(TIMER_SUPPORTS_TICKLESS) + +static uint16_t _IdleOrigCount = 0; +static uint16_t _IdleOrigTicks = 0; +static uint16_t __noinit _MaxSysTicks; +static uint16_t __noinit _MaxLoadValue; +static uint16_t __noinit _TimerIdleSkew; + +/* Used to determine if the timer ISR should place the timer in periodic mode */ +static unsigned char _TimerMode = TIMER_MODE_PERIODIC; +#endif /* TIMER_SUPPORTS_TICKLESS */ + +static uint32_t oldCount = 0; /* previous system clock value */ +static uint32_t oldAcc = 0; /* previous accumulated value value */ + +/* externs */ + +#ifdef CONFIG_MICROKERNEL +extern struct nano_stack K_Args; +#endif /* ! CONFIG_MICROKERNEL */ + +#ifdef __DCC__ +__asm volatile unsigned int intLock_inline(void) +{ + % !"ax" pushfl cli popl % eax +} + +__asm volatile void intUnlock_inline(unsigned int key) +{ + % mem key !testl $0x200, key jz 1f sti 1 : +} +#endif + +/******************************************************************************* +* +* _i8253CounterRead - read the i8253 counter register's value +* +* This routine reads the 16 bit value from the i8253 counter register. +* +* RETURNS: counter register's 16 bit value +* +* \NOMANUAL +*/ + +static inline uint16_t _i8253CounterRead(void) +{ + unsigned char lsb; /* least significant byte of counter register */ + unsigned char msb; /* most significant byte of counter register */ + uint16_t count; /* value read from i8253 counter register */ + + PLB_BYTE_REG_WRITE(0x00, PIT_CMD(PIT_BASE_ADRS)); + + /* read counter 0 latched LSB value followed by MSB */ + lsb = PLB_BYTE_REG_READ(PIT_CNT0(PIT_BASE_ADRS)); + msb = PLB_BYTE_REG_READ(PIT_CNT0(PIT_BASE_ADRS)); + + count = lsb | (((uint16_t)msb) << 8); + return count; +} + +/******************************************************************************* +* +* _i8253CounterSet - set the i8253 counter register's value +* +* This routine sets the 16 bit value from which the i8253 timer will +* decrement and sets that counter register to its value. +* +* RETURNS: N/A +* +* \NOMANUAL +*/ + +static inline void _i8253CounterSet( + uint16_t count /* value from which the counter will decrement */ + ) +{ + PLB_BYTE_REG_WRITE((unsigned char)(count & 0xff), + PIT_CNT0(PIT_BASE_ADRS)); + PLB_BYTE_REG_WRITE((unsigned char)((count >> 8) & 0xff), + PIT_CNT0(PIT_BASE_ADRS)); + _currentLoadVal = count; +} + +/******************************************************************************* +* +* _i8253CounterPeriodic - set the i8253 timer to fire periodically +* +* This routine sets the i8253 to fire on a periodic basis. +* +* RETURNS: N/A +* +* \NOMANUAL +*/ + +static inline void _i8253CounterPeriodic( + uint16_t count /* value from which the counter will decrement */ + ) +{ + PLB_BYTE_REG_WRITE(0x36, PIT_CMD(PIT_BASE_ADRS)); + _i8253CounterSet(count); +} + +#if defined(TIMER_SUPPORTS_TICKLESS) +/******************************************************************************* +* +* _i8253CounterOneShot - set the i8253 timer to fire once only +* +* This routine sets the i8253 to fire once only. +* +* RETURNS: N/A +* +* \NOMANUAL +*/ + +static inline void _i8253CounterOneShot( + uint16_t count /* value from which the counter will decrement */ + ) +{ + PLB_BYTE_REG_WRITE(0x30, PIT_CMD(PIT_BASE_ADRS)); + _i8253CounterSet(count); +} +#endif /* !TIMER_SUPPORTS_TICKLESS */ + +/******************************************************************************* +* +* _i8253IntHandlerPeriodic - system clock periodic tick handler +* +* This routine handles the system clock periodic tick interrupt. A TICK_EVENT +* event is pushed onto the microkernel stack. +* +* RETURNS: N/A +* +* \NOMANUAL +*/ + +void _timer_int_handler(void *unusedArg /* not used */ + ) +{ + ARG_UNUSED(unusedArg); + +#ifdef TIMER_SUPPORTS_TICKLESS + if (_TimerMode == TIMER_MODE_PERIODIC_ENT) { + _i8253CounterPeriodic(counterLoadVal); + _TimerMode = TIMER_MODE_PERIODIC; + } + + /* + * Increment the tick because _timer_idle_exit does not account + * for the tick due to the timer interrupt itself. Also, if not in + * tickless mode, + * _SysIdleElpasedTicks will be 0. + */ + _SysIdleElapsedTicks++; + + /* + * If we transistion from 0 elapsed ticks to 1 we need to announce the + * tick event to the microkernel. Other cases will have already been + * covered by _timer_idle_exit + */ + + if (_SysIdleElapsedTicks == 1) { + nano_isr_stack_push(&K_Args, TICK_EVENT); + } + + /* accumulate total counter value */ + accumulatedCount += counterLoadVal * _SysIdleElapsedTicks; + +#else +#if defined(CONFIG_MICROKERNEL) + /* announce tick into the microkernel */ + nano_isr_stack_push(&K_Args, TICK_EVENT); +#endif + + /* accumulate total counter value */ + accumulatedCount += counterLoadVal; +#endif /* TIMER_SUPPORTS_TICKLESS */ + + /* + * Algorithm tries to compensate lost interrupts if any happened and + * prevent the timer from counting backwards + * ULONG_MAX / 2 is the maximal value that oldCount can be more than + * accumulatedCount. If it is more -- consider it as an accumulatedCount + * wrap and do not try to compensate. + */ + if (accumulatedCount < oldCount) { + uint32_t tmp = oldCount - accumulatedCount; + if ((tmp >= counterLoadVal) && (tmp < (ULONG_MAX / 2))) { + accumulatedCount += tmp - tmp % counterLoadVal; + } + } + +#if defined(CONFIG_NANOKERNEL) + nanoTicks++; /* increment nanokernel ticks var */ + + if (nanoTimerList) { + nanoTimerList->ticks--; + + while (nanoTimerList && (!nanoTimerList->ticks)) { + struct nano_timer *expired = nanoTimerList; + struct nano_lifo *chan = &expired->lifo; + nanoTimerList = expired->link; + nano_fiber_lifo_put(chan, expired->userData); + } + } +#endif /* CONFIG_NANOKERNEL */ +} + +#if defined(TIMER_SUPPORTS_TICKLESS) +/******************************************************************************* +* +* _i8253TicklessIdleInit - initialize the tickless idle feature +* +* This routine initializes the tickless idle feature. Note that maximum +* number of ticks that can elapse during a "tickless idle" is limited by +* . The larger the value (the lower the tick frequency), the +* fewer elapsed ticks during a "tickless idle". Conversely, the smaller the +* value (the higher the tick frequency), the more elapsed ticks during a +* "tickless idle". +* +* RETURNS: N/A +* +* \NOMANUAL +*/ + +static void _i8253TicklessIdleInit(void) +{ + _MaxSysTicks = 0xffff / counterLoadVal; + /* this gives a count that gives the max number of full ticks */ + _MaxLoadValue = _MaxSysTicks * counterLoadVal; +} + +/******************************************************************************* +* +* _i8253TicklessIdleSkew - +* +* RETURNS: N/A +* +* \NOMANUAL +*/ + +static void _i8253TicklessIdleSkew(void) +{ + /* TBD */ + _TimerIdleSkew = 0; +} + +/******************************************************************************* +* +* _timer_idle_enter - Place system timer into idle state +* +* Re-program the timer to enter into the idle state for the given number of +* ticks. It is placed into one shot mode where it will fire in the number of +* ticks supplied or the maximum number of ticks that can be programmed into +* hardware. A value of -1 means inifinite number of ticks. +*/ + +void _timer_idle_enter(int32_t ticks /* system ticks */ + ) +{ + uint16_t newCount; + + /* + * We're being asked to have the timer fire in "ticks" from now. To + * maintain accuracy we must account for the remain time left in the + * timer. So we read the count out of it and add it to the requested + * time out + */ + newCount = _i8253CounterRead(); + + if (ticks == -1 || ticks > _MaxSysTicks) { + /* + * We've been asked to fire the timer so far in the future that + * the + * required count value would not fit in the 16 bit counter + * register. + * Instead, we program for the maximum programmable interval + * minus one + * system tick to prevent overflow when the left over count read + * earlier + * is added. + */ + newCount += _MaxLoadValue - counterLoadVal; + _IdleOrigTicks = _MaxSysTicks - 1; + } else { + /* leave one tick of buffer to have to time react when coming + * back ? */ + _IdleOrigTicks = ticks - 1; + newCount += _IdleOrigTicks * counterLoadVal; + } + + _IdleOrigCount = newCount - _TimerIdleSkew; + + /* Stop/start the timer instead of disabling/enabling the interrupt? */ + irq_disable(PIT_INT_LVL); + + _TimerMode = TIMER_MODE_PERIODIC_ENT; + + /* Program for terminal mode. The PIT equivalent of one shot */ + _i8253CounterOneShot(newCount); + + irq_enable(PIT_INT_LVL); +} + +/******************************************************************************* +* +* _timer_idle_exit - handling of tickless idle when interrupted +* +* The routine is responsible for taking the timer out of idle mode and +* generating an interrupt at the next tick interval. +* +* Note that in this routine, _SysTimerElapsedTicks must be zero because the +* ticker has done its work and consumed all the ticks. This has to be true +* otherwise idle mode wouldn't have been entered in the first place. +* +* Called in _IntEnt() +* +* RETURNS: N/A +*/ + +void _timer_idle_exit(void) +{ + uint16_t count; /* current value in i8253 counter register */ + + /* timer is in idle or off mode, adjust the ticks expired */ + + /* request counter 0 to be latched */ + count = _i8253CounterRead(); + + if ((count == 0) || (count >= _IdleOrigCount)) { + /* Timer expired. Place back in periodic mode */ + _i8253CounterPeriodic(counterLoadVal); + _TimerMode = TIMER_MODE_PERIODIC; + _SysIdleElapsedTicks = _IdleOrigTicks - 1; + /* + * Announce elapsed ticks to the microkernel. Note we are + * guaranteed + * that the timer ISR will execute first before the tick event + * is + * serviced. + */ + nano_isr_stack_push(&K_Args, TICK_EVENT); + } else { + uint16_t elapsed; /* elapsed "counter time" */ + uint16_t remaining; /* remaing "counter time" */ + + elapsed = _IdleOrigCount - count; + + remaining = elapsed % counterLoadVal; + + /* switch timer to periodic mode */ + if (remaining == 0) { + _i8253CounterPeriodic(counterLoadVal); + _TimerMode = TIMER_MODE_PERIODIC; + } else if (count > remaining) { + /* less time remaining to the next tick than was + * programmed */ + _i8253CounterOneShot(remaining); + } + + _SysIdleElapsedTicks = elapsed / counterLoadVal; + + if (_SysIdleElapsedTicks) { + /* Announce elapsed ticks to the microkernel */ + nano_isr_stack_push(&K_Args, TICK_EVENT); + } + } +} +#endif /* !TIMER_SUPPORTS_TICKLESS */ + +/******************************************************************************* +* +* timer_driver - initialize and enable the system clock +* +* This routine is used to program the PIT to deliver interrupts at the +* rate specified via the 'sys_clock_us_per_tick' global variable. +* +* RETURNS: N/A +*/ + +void timer_driver(int priority /* priority parameter ignored by this driver */ + ) +{ + ARG_UNUSED(priority); + + /* determine the PIT counter value (in timer clock cycles/system tick) + */ + + counterLoadVal = sys_clock_hw_cycles_per_tick; + + _i8253TicklessIdleInit(); + + /* init channel 0 to generate interrupt at the rate of SYS_CLOCK_RATE */ + + _i8253CounterPeriodic(counterLoadVal); + +#ifdef CONFIG_DYNAMIC_INT_STUBS + /* connect specified routine/parameter to PIT interrupt vector */ + + (void)irq_connect(PIT_INT_LVL, + PIT_INT_PRI, + _i8253IntHandlerPeriodic, + 0, + _i8253IntStub); +#endif /* CONFIG_DYNAMIC_INT_STUBS */ + + _i8253TicklessIdleSkew(); + +#if defined(CONFIG_MICROKERNEL) + +/* timer_read() is available for microkernel libraries to call directly */ + +/* K_ticker() is the pre-defined event handler for TICK_EVENT */ + +#endif /* CONFIG_MICROKERNEL */ + + /* Everything has been configured. It is now safe to enable the + * interrupt */ + irq_enable(PIT_INT_LVL); +} + +/******************************************************************************* +* +* timer_read - read the BSP timer hardware +* +* This routine returns the current time in terms of timer hardware clock cycles. +* +* RETURNS: up counter of elapsed clock cycles +*/ + +uint32_t timer_read(void) +{ + unsigned int key; /* interrupt lock level */ + uint32_t newCount; /* new system clock value */ + +#ifdef CONFIG_INT_LATENCY_BENCHMARK +/* + * Expending irq_lock_inline() code since directly calling it would + * would end up in infinite recursion. + */ +#if defined(__GNUC__) + __asm__ volatile( + "pushfl;\n\t" + "cli;\n\t" + "popl %0;\n\t" + : "=g"(key) + : + : "memory"); +#elif defined(__DCC__) + key = intLock_inline(); +#endif +#else + key = irq_lock_inline(); +#endif + + /* counters are down counters so need to subtact from counterLoadVal */ + newCount = accumulatedCount + _currentLoadVal - _i8253CounterRead(); + + /* + * This algorithm fixes the situation when the timer counter reset + * happened before the timer interrupt (due to possible interrupt + * disable) + */ + if ((newCount < oldCount) && (accumulatedCount == oldAcc)) { + uint32_t tmp = oldCount - newCount; + newCount += tmp - tmp % _currentLoadVal + _currentLoadVal; + } + + oldCount = newCount; + oldAcc = accumulatedCount; + +#ifdef CONFIG_INT_LATENCY_BENCHMARK +/* + * Expending irq_unlock_inline() code since directly calling it would + * would end up in infinite recursion. + */ +#if defined(__GNUC__) + __asm__ volatile( + "testl $0x200, %0;\n\t" + "jz 0f;\n\t" + "sti;\n\t" + "0:\n\t" + : + : "g"(key) + : "cc", "memory"); +#elif defined(__DCC__) + intUnlock_inline(key); +#endif +#else + irq_unlock_inline(key); +#endif + + return newCount; +} + +#if defined(CONFIG_SYSTEM_TIMER_DISABLE) +/******************************************************************************* +* +* timer_disable - stop announcing ticks into the kernel +* +* This routine simply disables the PIT counter such that interrupts are no +* longer delivered. +* +* RETURNS: N/A +*/ + +void timer_disable(void) +{ + unsigned int key; /* interrupt lock level */ + + key = irq_lock(); + + PLB_BYTE_REG_WRITE(0x38, PIT_CMD(PIT_BASE_ADRS)); + PLB_BYTE_REG_WRITE(0, PIT_CNT0(PIT_BASE_ADRS)); + PLB_BYTE_REG_WRITE(0, PIT_CNT0(PIT_BASE_ADRS)); + + irq_unlock(key); + + /* disable interrupt in the interrupt controller */ + + irq_disable(PIT_INT_LVL); +} +#endif /* CONFIG_SYSTEM_TIMER_DISABLE */ diff --git a/host/src/Makefile b/host/src/Makefile new file mode 100644 index 00000000000..4b7259c9ab7 --- /dev/null +++ b/host/src/Makefile @@ -0,0 +1,35 @@ +# Makefile - build all subdirectories containing [mM]akefiles + +# Copyright (c) 2011-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors +# may be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + +# ensure lib is built first +DIRS := $(filter-out lib,$(subst /,,$(sort $(dir $(wildcard */[mM]akefile))))) +DEPS = lib + +include ${VXMICRO_BASE}/make/host/dir.rules diff --git a/host/src/dec2hex/Makefile b/host/src/dec2hex/Makefile new file mode 100644 index 00000000000..22b11b0508f --- /dev/null +++ b/host/src/dec2hex/Makefile @@ -0,0 +1,35 @@ +# +# Makefile - builds decimal number to hexadecimal converter +# + +# Copyright (c) 2013-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors +# may be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + +EXE_NAME = dec2hex + +include ${VXMICRO_BASE}/make/host/exe.build diff --git a/host/src/dec2hex/dec2hex.c b/host/src/dec2hex/dec2hex.c new file mode 100644 index 00000000000..a190465860c --- /dev/null +++ b/host/src/dec2hex/dec2hex.c @@ -0,0 +1,56 @@ +/* dec2hex.c - convert decimal number to hexadecimal */ + +/* + * Copyright (c) 2013-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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 +#include + +void usage ( + char* progname /* name of the program to use */ + ) + { + fprintf (stderr, "Utility converts decimal numbers to hexadecimal\n"); + fprintf (stderr, "Usage: %s \n", progname); + } + +int main ( + int argc, + char* argv[] + ) + { + if (argc != 2) + { + usage (argv[0]); + return -1; + } + printf ("%X\n", atoi(argv[1])); + return 0; + } diff --git a/host/src/genIdt/Makefile b/host/src/genIdt/Makefile new file mode 100644 index 00000000000..011d82679e0 --- /dev/null +++ b/host/src/genIdt/Makefile @@ -0,0 +1,34 @@ +# Makefile - generates IDT generator tool + +# Copyright (c) 2013-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors +# may be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + +EXE_NAME = genIdt +EXTRA_CFLAGS = -I${VXMICRO_BASE}/shared/include + +include ${VXMICRO_BASE}/make/host/exe.build diff --git a/host/src/genIdt/genIdt.c b/host/src/genIdt/genIdt.c new file mode 100644 index 00000000000..a423ca70cef --- /dev/null +++ b/host/src/genIdt/genIdt.c @@ -0,0 +1,339 @@ +/* genIdt.c - Create static IDT */ + +/* + * Copyright (c) 2012-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +Creates a static IA-32 Interrupt Descriptor Table (IDT). + +This program expects to be invoked as follows: + genIdt +All parameters are required. + + is assumed to be a binary file containing the intList section from +the VxMicro ELF image (microkernel.elf, nanokernel.elf, etc.) + + is the same as CONFIG_IDT_NUM_VECTORS. + +No help on usage is provided as it is expected that this program is invoked +from within the VxMicro build system during the link stage. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* These come from the shared directory */ +#include "segselect.h" +#include "idtEnt.h" + +/* Define the following macro to see a verbose or debug output from the tool */ +/*#define DEBUG_GENIDT*/ + +#ifdef DEBUG_GENIDT +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) do {} while (0) +#endif + +#if !defined(WINDOWS) + #define O_BINARY 0 +#endif + +static void get_exec_name(char *pathname); +static void usage(const int len); +static void get_options(int argc, char *argv[]); +static void open_files(void); +static void close_files(void); +static void genIdt(void); +static void clean_exit(const int exit_code); + +typedef struct s_isrList + { + void * fnc; + unsigned int dpl; + } ISR_LIST; + +static ISR_LIST idt[256]; + +enum + { + IFILE=0, /* input file */ + OFILE, /* output file */ + NUSERFILES, /* number of user-provided file names */ + EXECFILE=NUSERFILES, /* for name of executable */ + NFILES /* total number of files open */ + }; +enum { SHORT_USAGE, LONG_USAGE }; + +static int fds[NUSERFILES] = {-1, -1}; +static char *filenames[NFILES]; +static unsigned int numVecs = (unsigned int)-1; +static struct version version = {KERNEL_VERSION, 1, 1, 0}; + +int main(int argc, char *argv[]) + { + get_exec_name(argv[0]); + get_options(argc, argv); /* may exit */ + open_files(); /* may exit */ + genIdt(); + close_files(); + return 0; + } + +static void get_options(int argc, char *argv[]) + { + char *endptr; + int ii, opt; + while ((opt = getopt(argc, argv, "hi:o:n:v")) != -1) + { + switch(opt) + { + case 'i': + filenames[IFILE] = optarg; + break; + case 'o': + { + filenames[OFILE] = optarg; + break; + } + case 'h': + usage(LONG_USAGE); + exit(0); + case 'n': + numVecs = (unsigned int)strtoul(optarg, &endptr, 10); + if (*optarg == '\0' || *endptr != '\0') { + usage(SHORT_USAGE); + exit(-1); + } + break; + case 'v': + show_version(filenames[EXECFILE], &version); + exit(0); + default: + usage(SHORT_USAGE); + exit(-1); + } + } + + if ((unsigned int)-1 == numVecs) + { + usage(SHORT_USAGE); + exit(-1); + } + + for(ii = IFILE; ii < NUSERFILES; ii++) + { + if (!filenames[ii]) + { + usage(SHORT_USAGE); + exit(-1); + } + } + } + +static void get_exec_name(char *pathname) + { + int end = strlen(pathname)-1; + while(end != -1) + { + #if defined (WINDOWS) /* Might have both slashes in path */ + if (pathname[end] == '/' || pathname[end] == '\\') + #else + if (pathname[end] == '/') + #endif + { + if (0 == end || pathname[end-1] != '\\') { + ++end; + break; + } + } + --end; + } + filenames[EXECFILE] = &pathname[end]; + } + +static void open_files(void) + { + int ii; + fds[IFILE] = open(filenames[IFILE], O_RDONLY|O_BINARY); + fds[OFILE] = open(filenames[OFILE], O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, + S_IWUSR|S_IRUSR); + for(ii = 0; ii < NUSERFILES; ii++) + { + int invalid = fds[ii] == -1; + if (invalid) + { + char *invalid = filenames[ii]; + fprintf(stderr, "invalid file %s\n", invalid); + for(--ii; ii >= 0; ii--) + { + close(fds[ii]); + } + exit (-1); + } + } + } + +static void genIdt(void) + { + unsigned int i; + unsigned int size; + void * spurAddr; + void * spurNoErrAddr; + + /* + * First find the address of the spurious interrupt handlers. They are the + * contained in the first 8 bytes of the input file. + */ + if (read (fds[IFILE], &spurAddr, 4) < 4) + goto readError; + + if (read (fds[IFILE], &spurNoErrAddr, 4) < 4) + goto readError; + + PRINTF ("Spurious int handlers found at %p and %p\n", + spurAddr, spurNoErrAddr); + + /* Initially fill in the IDT array with the spurious handlers */ + for (i = 0; i < numVecs; i++) + { + if ((((1 << i) & _EXC_ERROR_CODE_FAULTS)) && (i < 32)) + idt[i].fnc = spurAddr; + else + idt[i].fnc = spurNoErrAddr; + } + + /* + * Now parse the rest of the input file for the other ISRs. The number of + * entries is the next 4 bytes + */ + + if (read (fds[IFILE], &size, 4) < 4) + goto readError; + + PRINTF ("There are %d ISR(s)\n", size); + + if (size > numVecs) + { + fprintf (stderr, "Too many ISRs found. Got %u. Expected less than %u." + " Malformed input file?\n", size, numVecs); + clean_exit(-1); + } + + while (size--) + { + void * addr; + unsigned int vec; + unsigned int dpl; + + /* Get address */ + if (read (fds[IFILE], &addr, 4) < 4) + goto readError; + /* Get vector */ + if (read (fds[IFILE], &vec, 4) < 4) + goto readError; + /* Get dpl */ + if (read (fds[IFILE], &dpl, 4) < 4) + goto readError; + + PRINTF ("ISR @ %p on Vector %d: dpl %d\n", addr, vec, dpl); + idt[vec].fnc = addr; + idt[vec].dpl = dpl; + } + + /* + * We now have the address of all ISR stub/functions captured in idt[]. + * Now construct the actual idt. + */ + + for (i = 0; i < numVecs; i++) + { + unsigned long long idtEnt; + + _IdtEntCreate (&idtEnt, idt[i].fnc, idt[i].dpl); + + write (fds[OFILE], &idtEnt, 8); + } + + return; + +readError: + fprintf(stderr, "Error occured while reading input file. Aborting...\n"); + clean_exit(-1); + } + +static void close_files(void) + { + int ii; + for(ii = 0; ii < NUSERFILES; ii++) + { + close(fds[ii]); + } + } + +static void clean_exit(const int exit_code) + { + close_files(); + exit(exit_code); + } + +static void usage(const int len) + { + fprintf(stderr, + "\n%s -i -n \n", + filenames[EXECFILE]); + + if (len == SHORT_USAGE) + { + return; + } + + fprintf(stderr, + "\n" + " options\n" + "\n" + " -i \n\n" + " [Mandatory] The input file in binary format.\n\n" + " -o \n\n" + " [Mandatory] The output file.\n\n" + " -n \n\n" + " [Mandatory] Number of vectors\n\n" + " -v Display version.\n\n" + " -h Display this help.\n\n" + "\nReturns -1 on error, 0 on success\n\n"); + } diff --git a/host/src/genIdt/idtEnt.h b/host/src/genIdt/idtEnt.h new file mode 120000 index 00000000000..6a07a1d51bc --- /dev/null +++ b/host/src/genIdt/idtEnt.h @@ -0,0 +1 @@ +../../../shared/include/nanokernel/x86/idtEnt.h \ No newline at end of file diff --git a/host/src/genIdt/segselect.h b/host/src/genIdt/segselect.h new file mode 120000 index 00000000000..93a82550963 --- /dev/null +++ b/host/src/genIdt/segselect.h @@ -0,0 +1 @@ +../../../shared/include/nanokernel/x86/segselect.h \ No newline at end of file diff --git a/host/src/genOffsetHeader/Makefile b/host/src/genOffsetHeader/Makefile new file mode 100644 index 00000000000..ba65350ddd7 --- /dev/null +++ b/host/src/genOffsetHeader/Makefile @@ -0,0 +1,33 @@ +# Makefile - build offsets.h generation tool + +# Copyright (c) 2013-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors +# may be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + +EXE_NAME = genOffsetHeader + +include ${VXMICRO_BASE}/make/host/exe.build diff --git a/host/src/genOffsetHeader/elf.h b/host/src/genOffsetHeader/elf.h new file mode 100644 index 00000000000..2cd326a0a8e --- /dev/null +++ b/host/src/genOffsetHeader/elf.h @@ -0,0 +1,389 @@ +/* elf.h - Executable and Linking Format (ELF) definitions */ + +/* + * Copyright (c) 2010, 2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +The definitions in this header conform to the "Tool Interface Standard (TIS) +Executable and Linking Format (ELF) Specification Version 1.2" +*/ + +#ifndef _ELF_H +#define _ELF_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef unsigned int Elf32_Addr; +typedef unsigned short Elf32_Half; +typedef unsigned int Elf32_Off; +typedef int Elf32_Sword; +typedef unsigned int Elf32_Word; + + +/* + * Elf header + */ + +#define EI_NIDENT 16 + +typedef struct + { + unsigned char e_ident[EI_NIDENT]; + Elf32_Half e_type; + Elf32_Half e_machine; + Elf32_Word e_version; + Elf32_Addr e_entry; + Elf32_Off e_phoff; + Elf32_Off e_shoff; + Elf32_Word e_flags; + Elf32_Half e_ehsize; + Elf32_Half e_phentsize; + Elf32_Half e_phnum; + Elf32_Half e_shentsize; + Elf32_Half e_shnum; + Elf32_Half e_shstrndx; + } Elf32_Ehdr; + +#define EHDRSZ sizeof(Elf32_Ehdr) + +/* + * e_ident[] values + */ +#define EI_MAG0 0 +#define EI_MAG1 1 +#define EI_MAG2 2 +#define EI_MAG3 3 +#define EI_CLASS 4 +#define EI_DATA 5 +#define EI_VERSION 6 +#define EI_PAD 7 + +#define ELFMAG0 0x7f +#define ELFMAG1 'E' +#define ELFMAG2 'L' +#define ELFMAG3 'F' +#define ELFMAG "\177ELF" +#define SELFMAG 4 + +/* + * EI_CLASS + */ +#define ELFCLASSNONE 0 +#define ELFCLASS32 1 +#define ELFCLASS64 2 + +/* + * EI_DATA + */ +#define ELFDATANONE 0 +#define ELFDATA2LSB 1 +#define ELFDATA2MSB 2 + +/* + * e_type + */ +#define ET_NONE 0 +#define ET_REL 1 +#define ET_EXEC 2 +#define ET_DYN 3 +#define ET_CORE 4 +#define ET_LOPROC 0xff00 +#define ET_HIPROC 0xffff + +/* + * e_machine + */ +#define EM_NONE 0 /* No machine */ +#define EM_M32 1 /* AT&T WE 32100 */ +#define EM_SPARC 2 /* SPARC */ +#define EM_386 3 /* Intel 80386 */ +#define EM_68K 4 /* Motorola 68000 */ +#define EM_88K 5 /* Motorola 88000 */ +#define EM_486 6 /* Intel 80486 */ +#define EM_860 7 /* Intel 80860 */ +#define EM_MIPS 8 /* MIPS RS3000 Big-Endian */ +#define EM_MIPS_RS4_BE 10 /* MIPS RS4000 Big-Endian */ +#define EM_PPC_OLD 17 /* PowerPC - old */ +#define EM_PPC 20 /* PowerPC */ +#define EM_RCE_OLD 25 /* RCE - old */ +#define EM_NEC_830 36 /* NEC 830 series */ +#define EM_RCE 39 /* RCE */ +#define EM_MCORE 39 /* MCORE */ +#define EM_ARM 40 /* ARM */ +#define EM_SH 42 /* SH */ +#define EM_COLDFIRE 52 /* Motorola ColdFire */ +#define EM_SC 58 /* SC */ +#define EM_M32R 36929 /* M32R */ +#define EM_NEC 36992 /* NEC 850 series */ + +/* + * e_flags + */ +#define EF_PPC_EMB 0x80000000 + +#define EF_MIPS_NOREORDER 0x00000001 +#define EF_MIPS_PIC 0x00000002 +#define EF_MIPS_CPIC 0x00000004 +#define EF_MIPS_ARCH 0xf0000000 +#define EF_MIPS_ARCH_MIPS_2 0x10000000 +#define EF_MIPS_ARCH_MIPS_3 0x20000000 + +/* + * e_version and EI_VERSION + */ +#define EV_NONE 0 +#define EV_CURRENT 1 + +/* + * Special section indexes + */ +#define SHN_UNDEF 0 +#define SHN_LORESERVE 0xff00 +#define SHN_LOPROC 0xff00 +#define SHN_HIPROC 0xff1f +#define SHN_ABS 0xfff1 +#define SHN_COMMON 0xfff2 +#define SHN_HIRESERVE 0xffff + +#define SHN_GHCOMMON 0xff00 +/* + * Section header + */ +typedef struct + { + Elf32_Word sh_name; + Elf32_Word sh_type; /* SHT_... */ + Elf32_Word sh_flags; /* SHF_... */ + Elf32_Addr sh_addr; + Elf32_Off sh_offset; + Elf32_Word sh_size; + Elf32_Word sh_link; + Elf32_Word sh_info; + Elf32_Word sh_addralign; + Elf32_Word sh_entsize; +} Elf32_Shdr; + +#define SHDRSZ sizeof(Elf32_Shdr) + +/* + * sh_type + */ +#define SHT_NULL 0 +#define SHT_PROGBITS 1 +#define SHT_SYMTAB 2 +#define SHT_STRTAB 3 +#define SHT_RELA 4 +#define SHT_HASH 5 +#define SHT_DYNAMIC 6 +#define SHT_NOTE 7 +#define SHT_NOBITS 8 +#define SHT_REL 9 +#define SHT_SHLIB 10 +#define SHT_DYNSYM 11 +#define SHT_COMDAT 12 +#define SHT_LOPROC 0x70000000 +#define SHT_HIPROC 0x7fffffff +#define SHT_LOUSER 0x80000000 +#define SHT_HIUSER 0xffffffff +#define SHT_INIT_ARRAY 14 +#define SHT_FINI_ARRAY 15 +#define SHT_PREINIT_ARRAY 16 +#define SHT_GROUP 17 +#define SHT_SYMTAB_SHNDX 18 +#define SHT_NUM 19 + +/* + * sh_flags + */ +#define SHF_WRITE 0x1 +#define SHF_ALLOC 0x2 +#define SHF_EXECINSTR 0x4 +#define SHF_MASKPROC 0xf0000000 +#define SHF_MERGE 0x10 /* not part of all ELF ABI docs */ +#define SHF_STRINGS 0x20 /* not part of all ELF ABI docs */ +#define SHF_INFO_LINK 0x40 +#define SHF_LINK_ORDER 0x80 +#define SHF_OS_NONCONFORMING 0x100 +#define SHF_GROUP 0x200 +#define SHF_TLS 0x400 + +/* + * Symbol table + */ +typedef struct + { + Elf32_Word st_name; + Elf32_Addr st_value; + Elf32_Word st_size; + unsigned char st_info; + unsigned char st_other; + Elf32_Half st_shndx; + } Elf32_Sym; + +#define STN_UNDEF 0 + +#define STB_LOCAL 0 +#define STB_GLOBAL 1 +#define STB_WEAK 2 +#define STB_LOPROC 13 +#define STB_HIPROC 15 + +#define STT_NOTYPE 0 +#define STT_OBJECT 1 +#define STT_FUNC 2 +#define STT_SECTION 3 +#define STT_FILE 4 +#define STT_COMMON 5 +#define STT_TLS 6 +#define STT_LOOS 10 +#define STT_HIOS 12 +#define STT_LOPROC 13 +#define STT_HIPROC 15 + +#define ELF_ST_BIND(x) ((x) >> 4) +#define ELF_ST_TYPE(x) (((unsigned int) x) & 0xf) +#define ELF32_ST_BIND(x) ELF_ST_BIND(x) +#define ELF32_ST_TYPE(x) ELF_ST_TYPE(x) + + +/* + * The STT_ARM_TFUNC type is used by the gnu compiler to mark Thumb + * functions. The STT_ARM_16BIT type is the thumb equivalent of an + * object. They are not part of the ARM ABI or EABI - they come from gnu. + */ + +#define STT_ARM_TFUNC STT_LOPROC /* GNU Thumb function */ +#define STT_ARM_16BIT STT_HIPROC /* GNU Thumb label */ + + +/* + * Relocation + */ +typedef struct + { + Elf32_Addr r_offset; + Elf32_Word r_info; + } Elf32_Rel; + +typedef struct + { + Elf32_Addr r_offset; + Elf32_Word r_info; + Elf32_Sword r_addend; + } Elf32_Rela; + +#define ELF32_R_SYM(info) ((info)>>8) +#define ELF32_R_TYPE(info) ((unsigned char)(info)) +#define ELF32_R_INFO(sym,type) (((sym)<<8)+(unsigned char)(type)) + +/* + * Program header + */ +typedef struct + { + Elf32_Word p_type; + Elf32_Off p_offset; + Elf32_Addr p_vaddr; + Elf32_Addr p_paddr; + Elf32_Word p_filesz; + Elf32_Word p_memsz; + Elf32_Word p_flags; + Elf32_Word p_align; + } Elf32_Phdr; + +#define PHDRSZ sizeof(Elf32_Phdr) + +/* + * p_type + */ +#define PT_NULL 0 +#define PT_LOAD 1 +#define PT_DYNAMIC 2 +#define PT_INTERP 3 +#define PT_NOTE 4 +#define PT_SHLIB 5 +#define PT_PHDR 6 +#define PT_LOPROC 0x70000000 +#define PT_HIPROC 0x7fffffff + +/* + * p_flags + */ +#define PF_X 0x1 +#define PF_W 0x2 +#define PF_R 0x4 +#define PF_MASKPROC 0xf0000000 + +typedef struct + { + Elf32_Sword d_tag; + union + { + Elf32_Word d_val; + Elf32_Addr d_ptr; + } d_un; + } Elf32_Dyn; + +#define DT_NULL 0 +#define DT_NEEDED 1 +#define DT_PLTRELSZ 2 +#define DT_PLTGOT 3 +#define DT_HASH 4 +#define DT_STRTAB 5 +#define DT_SYMTAB 6 +#define DT_RELA 7 +#define DT_RELASZ 8 +#define DT_RELAENT 9 +#define DT_STRSZ 10 +#define DT_SYMENT 11 +#define DT_INIT 12 +#define DT_FINI 13 +#define DT_SONAME 14 +#define DT_RPATH 15 +#define DT_SYMBOLIC 16 +#define DT_REL 17 +#define DT_RELSZ 18 +#define DT_RELENT 19 +#define DT_PLTREL 20 +#define DT_DEBUG 21 +#define DT_TEXTREL 22 +#define DT_JMPREL 23 +#define DT_LOPROC 0x70000000 +#define DT_HIPROC 0x7fffffff + + +#ifdef __cplusplus +} +#endif + +#endif /* _ELF_H */ diff --git a/host/src/genOffsetHeader/genOffsetHeader.c b/host/src/genOffsetHeader/genOffsetHeader.c new file mode 100644 index 00000000000..66357c31c74 --- /dev/null +++ b/host/src/genOffsetHeader/genOffsetHeader.c @@ -0,0 +1,716 @@ +/* genOffsetHeader.c - generate offset definition header file */ + +/* + * Copyright (c) 2010-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +SYNOPSIS +.tS +genOffsetHeader -i -o +.tE + +DESCRIPTION +This VxMicro development host utility will process an ELF object module that +consists of a series of absolute symbols representing the byte offset of a +structure member and the size of the structure. Each absolute symbol will +be translated into a C preprocessor '#define' directive. For example, +assuming that the module offsets.o contains the following absolute symbols: + + $ nm offsets.o + 00000010 A __tNANO_common_isp_OFFSET + 00000008 A __tNANO_current_OFFSET + 0000000c A __tNANO_nested_OFFSET + 00000000 A __tNANO_fiber_OFFSET + 00000004 A __tNANO_task_OFFSET + +... the following C preprocessor code will be generated: + + #define __tNANO_common_isp_OFFSET 0x10 + #define __tNANO_current_OFFSET 0x8 + #define __tNANO_nested_OFFSET 0xC + #define __tNANO_fiber_OFFSET 0x0 + #define __tNANO_task_OFFSET 0x4 +*/ + +/* includes */ + +#include +#include +#include +#include +#include +#include "elf.h" +#include /* for malloc()/free()/exit() */ +#include /* for strstr() */ +#include +#include + +/* defines */ + +#undef DEBUG + +/* the symbol name suffix used to denote structure member offsets */ + +#define STRUCT_OFF_SUFFIX "_OFFSET" +#define STRUCT_SIZ_SUFFIX "_SIZEOF" + +#ifdef DEBUG +#define DBG_PRINT(args...) printf(args) +#else +#define DBG_PRINT(args...) +#endif + + +/* byte swapping macros */ + +#define SWAB_Elf32_Half(x) ((x >> 8) | (x << 8)) +#define SWAB_Elf32_Word(x) (((x >> 24) & 0xff) | \ + ((x << 8) & 0xff0000) | \ + ((x >> 8) & 0xff00) | \ + ((x << 24) & 0xff000000)) + +#define SWAB_Elf32_Addr SWAB_Elf32_Word +#define SWAB_Elf32_Off SWAB_Elf32_Word +#define SWAB_Elf32_Sword SWAB_Elf32_Word + +#if defined(WINDOWS) + #define OPEN_FLAGS (O_RDONLY|O_BINARY) +#else + #define OPEN_FLAGS (O_RDONLY) +#endif + +/* locals */ + +/* global indicating whether ELF structures need to be byte swapped */ + +static char swabRequired; + + +/* usage information */ + +static char usage[] = "usage: %s -i -o \n"; + + +/* output header file preamble */ + +static char preamble1[] = "\ +/* %s - structure member offsets definition header */\n\ +\n\ +/*\n\ + * Copyright (c) 2010-2014 Wind River Systems, Inc.\n\ + *\n\ + * Redistribution and use in source and binary forms, with or without\n\ + * modification, are permitted provided that the following conditions are met:\n\ + *\n\ + * 1) Redistributions of source code must retain the above copyright notice,\n\ + * this list of conditions and the following disclaimer.\n\ + *\n\ + * 2) Redistributions in binary form must reproduce the above copyright notice,\n\ + * this list of conditions and the following disclaimer in the documentation\n\ + * and/or other materials provided with the distribution.\n\ + *\n\ + * 3) Neither the name of Wind River Systems nor the names of its contributors\n\ + * may be used to endorse or promote products derived from this software without\n\ + * specific prior written permission.\n\ + *\n\ + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n\ + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n\ + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n\ + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE\n\ + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n\ + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n\ + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n\ + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n\ + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n\ + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n\ + * POSSIBILITY OF SUCH DAMAGE.\n\ + */\n\ +\n\ +/* THIS FILE IS AUTO GENERATED. PLEASE DO NOT EDIT */\n\ +\n\ +/*\n\ + * This header file provides macros for the offsets of various structure\n\ + * members. These offset macros are primarily intended to be used in\n\ + * assembly code.\n\ + */\n\n"; + +static char preamble2[] = "\ +/*\n\ + * Auto-generated header guard.\n\ + */\n\ +#ifndef %s\n\ +#define %s\n\ + \n\ +#ifdef __cplusplus\n\ +extern \"C\" {\n\ +#endif\n\ +\n\ +/* defines */\n\n"; + + +/* output header file postscript */ + +static char postscript[] = "\ +\n\ +#ifdef __cplusplus\n\ +}\n\ +#endif\n\ +\n\ +#endif /* _HGUARD_ */\n"; + +static Elf32_Ehdr ehdr; /* ELF header */ +static Elf32_Shdr * shdr; /* pointer to array ELF section headers */ + +/******************************************************************************* +* +* swabElfHdr - byte swap the Elf32_Ehdr structure +* +* RETURNS: N/A +*/ + +static void swabElfHdr(Elf32_Ehdr *pHdrToSwab) +{ + if (swabRequired == 0) + { + return; /* do nothing */ + } + + pHdrToSwab->e_type = SWAB_Elf32_Half (pHdrToSwab->e_type); + pHdrToSwab->e_machine = SWAB_Elf32_Half (pHdrToSwab->e_machine); + pHdrToSwab->e_version = SWAB_Elf32_Word (pHdrToSwab->e_version); + pHdrToSwab->e_entry = SWAB_Elf32_Addr (pHdrToSwab->e_entry); + pHdrToSwab->e_phoff = SWAB_Elf32_Off (pHdrToSwab->e_phoff); + pHdrToSwab->e_shoff = SWAB_Elf32_Off (pHdrToSwab->e_shoff); + pHdrToSwab->e_flags = SWAB_Elf32_Word (pHdrToSwab->e_flags); + pHdrToSwab->e_ehsize = SWAB_Elf32_Half (pHdrToSwab->e_ehsize); + pHdrToSwab->e_phentsize = SWAB_Elf32_Half (pHdrToSwab->e_phentsize); + pHdrToSwab->e_phnum = SWAB_Elf32_Half (pHdrToSwab->e_phnum); + pHdrToSwab->e_shentsize = SWAB_Elf32_Half (pHdrToSwab->e_shentsize); + pHdrToSwab->e_shnum = SWAB_Elf32_Half (pHdrToSwab->e_shnum); + pHdrToSwab->e_shstrndx = SWAB_Elf32_Half (pHdrToSwab->e_shstrndx); +} + +/******************************************************************************* +* +* swabElfSectionHdr - byte swap the Elf32_Shdr structure +* +* RETURNS: N/A +*/ + +static void swabElfSectionHdr(Elf32_Shdr *pHdrToSwab) +{ + if (swabRequired == 0) + { + return; /* do nothing */ + } + + pHdrToSwab->sh_name = SWAB_Elf32_Word (pHdrToSwab->sh_name); + pHdrToSwab->sh_type = SWAB_Elf32_Word (pHdrToSwab->sh_type); + pHdrToSwab->sh_flags = SWAB_Elf32_Word (pHdrToSwab->sh_flags); + pHdrToSwab->sh_addr = SWAB_Elf32_Addr (pHdrToSwab->sh_addr); + pHdrToSwab->sh_offset = SWAB_Elf32_Off (pHdrToSwab->sh_offset); + pHdrToSwab->sh_size = SWAB_Elf32_Word (pHdrToSwab->sh_size); + pHdrToSwab->sh_link = SWAB_Elf32_Word (pHdrToSwab->sh_link); + pHdrToSwab->sh_info = SWAB_Elf32_Word (pHdrToSwab->sh_info); + pHdrToSwab->sh_addralign = SWAB_Elf32_Word (pHdrToSwab->sh_addralign); + pHdrToSwab->sh_addralign = SWAB_Elf32_Word (pHdrToSwab->sh_addralign); +} + + +/******************************************************************************* +* +* swabElfSym - byte swap the Elf32_Sym structure +* +* RETURNS: N/A +*/ + +static void swabElfSym(Elf32_Sym *pHdrToSwab) +{ + if (swabRequired == 0) + { + return; /* do nothing */ + } + + pHdrToSwab->st_name = SWAB_Elf32_Word (pHdrToSwab->st_name); + pHdrToSwab->st_value = SWAB_Elf32_Addr (pHdrToSwab->st_value); + pHdrToSwab->st_size = SWAB_Elf32_Word (pHdrToSwab->st_size); + pHdrToSwab->st_shndx = SWAB_Elf32_Half (pHdrToSwab->st_shndx); +} + +/******************************************************************************* +* +* ehdrLoad - load the ELF header +* +* RETURNS: 0 on success, -1 on failure +*/ + +static int ehdrLoad(int fd /* file descriptor of file from which to read */ + ) +{ + unsigned ix = 0x12345678; /* used to auto-detect endian-ness */ + size_t nBytes; /* number of bytes read from file */ + + lseek (fd, 0, SEEK_SET); + + nBytes = read (fd, &ehdr, sizeof (ehdr)); + if (nBytes != sizeof (ehdr)) + { + fprintf (stderr, "Failed to read ELF header\n"); + return -1; + } + + /* perform some rudimentary ELF file validation */ + + if (strncmp ((char *)ehdr.e_ident, ELFMAG, 4) != 0) + { + fprintf (stderr, "Input object module not ELF format\n"); + return -1; + } + + /* 64-bit ELF module not supported (for now) */ + + if (ehdr.e_ident[EI_CLASS] != ELFCLASS32) + { + fprintf (stderr, "ELF64 class not supported\n"); + return -1; + } + + /* + * Dynamically determine the endianess of the host (in the absence of + * a compile time macro ala _BYTE_ORDER). The ELF structures will require + * byte swapping if the host and target have different byte ordering. + */ + + if (((*(char*)&ix == 0x78) && (ehdr.e_ident[EI_DATA] == ELFDATA2MSB)) || + ((*(char*)&ix == 0x12) && (ehdr.e_ident[EI_DATA] == ELFDATA2LSB))) + { + swabRequired = 1; + DBG_PRINT ("Swab required\n"); + } + + swabElfHdr (&ehdr); /* swap bytes (if required) */ + + /* debugging: dump some important ELF header fields */ + + DBG_PRINT ("Elf header Magic = %s\n", ehdr.e_ident); + DBG_PRINT ("Elf header e_type = %d\n", ehdr.e_type); + DBG_PRINT ("Elf header e_shstrndx = %d\n", ehdr.e_shstrndx); + DBG_PRINT ("Elf header e_shnum = %d\n", ehdr.e_shnum); + + return 0; +} + +/******************************************************************************* +* +* shdrsLoad - load the section headers +* +* RETURNS: 0 on success, -1 on failure +*/ + +int shdrsLoad(int fd /* file descriptor of file from which to read */ + ) +{ + size_t nBytes; /* number of bytes read from file */ + unsigned ix; /* loop index */ + + shdr = malloc (ehdr.e_shnum * sizeof (Elf32_Shdr)); + if (shdr == NULL) + { + fprintf (stderr, "No memory for section headers!\n"); + return -1; + } + + /* Seek to the start of the table of section headers */ + lseek (fd, ehdr.e_shoff, SEEK_SET); + + for (ix = 0; ix < ehdr.e_shnum; ix++) + { + nBytes = read (fd, &shdr[ix], sizeof (Elf32_Shdr)); + if (nBytes != sizeof (Elf32_Shdr)) + { + fprintf (stderr, "Unable to read entire section header (#%d)\n", + ix); + return -1; + } + + swabElfSectionHdr (&shdr[ix]); /* swap bytes (if required) */ + } + + return 0; +} + +/******************************************************************************* +* +* symTblFind - search the section headers for the symbol table +* +* This routine searches the section headers for the symbol table. There is +* expected to be only one symbol table in the section headers. +* +* RETURNS: 0 if found, -1 if not +*/ + +int symTblFind(unsigned *pSymTblOffset, /* ptr to symbol table offset */ + unsigned *pSymTblSize /* ptr to symbol table size */ + ) +{ + unsigned ix; /* loop index */ + + for (ix = 0; ix < ehdr.e_shnum; ++ix) + { + if (shdr[ix].sh_type == SHT_SYMTAB) + { + *pSymTblOffset = shdr[ix].sh_offset; + *pSymTblSize = shdr[ix].sh_size; + + return 0; + } + } + + fprintf (stderr, "Object module missing symbol table!\n"); + + return -1; +} + +/******************************************************************************* +* +* strTblFind - search the section headers for the string table +* +* This routine searches the section headers for the string table associated +* with the symbol names. +* +* Typically, there are two string tables defined in the section headers. These +* are ".shstrtbl" and ".strtbl" for section header names and symbol names +* respectively. It has been observed with the DIAB compiler (but not with +* either the GCC nor ICC compilers) that the two tables may be mashed together +* into one. Consequently, the following algorithm is used to select the +* appropriate string table. +* +* 1. Assume that the first found string table is valid. +* 2. If another string table is found, use that only if its section header +* index does not match the index for ".shstrtbl" stored in the ELF header. +* +* RETURNS 0 if found, -1 if not +*/ + +int strTblFind(unsigned *pStrTblIx /* ptr to string table's index */ + ) +{ + unsigned strTblIx = 0xffffffff; + unsigned ix; + + for (ix = 0; ix < ehdr.e_shnum; ++ix) + { + if (shdr[ix].sh_type == SHT_STRTAB) + { + if ((strTblIx == 0xffffffff) || + (ix != ehdr.e_shstrndx)) + { + strTblIx = ix; + } + } + } + + if (strTblIx == 0xffffffff) + { + fprintf (stderr, "Object module missing string table!\n"); + return -1; + } + + *pStrTblIx = strTblIx; + + return 0; +} + +/******************************************************************************* +* +* strTblLoad - load the string table +* +* RETURNS: 0 on success, -1 on failure +*/ + +int strTblLoad(int fd, /* file descriptor of file from which to read */ + unsigned strTblIx, /* string table's index */ + char **ppStringTable /* ptr to ptr to string table */ + ) +{ + char * pTable; + int nBytes; + + DBG_PRINT ("Allocating %d bytes for string table\n", + shdr[strTblIx].sh_size); + + pTable = malloc (shdr[strTblIx].sh_size); + if (pTable == NULL) + { + fprintf (stderr, "No memory for string table!"); + return -1; + } + + lseek (fd, shdr[strTblIx].sh_offset, SEEK_SET); + + nBytes = read (fd, pTable, shdr[strTblIx].sh_size); + if (nBytes != shdr[strTblIx].sh_size) + { + free (pTable); + fprintf (stderr, "Unable to read entire string table!\n"); + return -1; + } + + *ppStringTable = pTable; + + return 0; +} + +/******************************************************************************* +* +* headerPreambleDump - dump the header preamble to the header file +* +* RETURNS: N/A +*/ + +void headerPreambleDump(FILE *fp, /* file pointer to which to write */ + char *filename /* name of the output file */ + ) +{ + unsigned hash = 5381; /* hash value */ + size_t ix; /* loop counter */ + char fileNameHash[20]; /* '_HGUARD_' + 8 character hash + '\0' */ + + /* dump header file preamble1[] */ + + fprintf (fp, preamble1, filename, filename, filename); + + /* + * Dump header file preamble2[]. Hash file name into something that + * is small enough to be a C macro name and does not have invalid + * characters for a macro name to use as a header guard. The result + * of the hash should be unique enough for our purposes. + */ + + for (ix = 0; ix < sizeof(filename); ++ix) + { + hash = (hash * 33) + (unsigned int) filename[ix]; + } + + sprintf(fileNameHash, "_HGUARD_%08x", hash); + fprintf (fp, preamble2, fileNameHash, fileNameHash); +} + +/******************************************************************************* +* +* headerAbsoluteSymbolsDump - dump the absolute symbols to the header file +* +* RETURNS: N/A +*/ + +void headerAbsoluteSymbolsDump(int fd, /* file descriptor of file from which to read */ + FILE *fp, /* file pointer to which to write */ + Elf32_Off symTblOffset, /* symbol table offset */ + Elf32_Word symTblSize, /* size of the symbol table */ + char *pStringTable /* ptr to the string table */ + ) +{ + Elf32_Sym aSym; /* absolute symbol */ + unsigned ix; /* loop counter */ + unsigned numSyms; /* number of symbols in the symbol table */ + + /* context the symbol table: pick out absolute syms */ + + numSyms = symTblSize / sizeof(Elf32_Sym); + lseek (fd, symTblOffset, SEEK_SET); + + for (ix = 0; ix < numSyms; ++ix) + { + /* read in a single symbol structure */ + + read (fd, &aSym, sizeof(Elf32_Sym)); + + swabElfSym (&aSym); /* swap bytes (if required) */ + + /* + * Only generate definitions for global absolute symbols + * of the form *_OFFSET + */ + + if ((aSym.st_shndx == SHN_ABS) && + (ELF_ST_BIND(aSym.st_info) == STB_GLOBAL)) + { + if ((strstr (&pStringTable[aSym.st_name], + STRUCT_OFF_SUFFIX) != NULL) || + (strstr (&pStringTable[aSym.st_name], + STRUCT_SIZ_SUFFIX) != NULL)) + { + fprintf (fp, "#define\t%s\t0x%X\n", + &pStringTable[aSym.st_name], aSym.st_value); + } + } + } +} + +/******************************************************************************* +* +* headerPostscriptDump - dump the header postscript to the header file +* +* RETURNS: N/A +*/ + +void headerPostscriptDump(FILE *fp /* file pointer to which to write */ + ) +{ + fputs (postscript, fp); +} + +/******************************************************************************* +* +* main - entry point for the genOffsetHeader utility +* +* usage: $ genOffsetHeader -i -o +* +* RETURNS: 0 on success, 1 on failure +*/ + +int main(int argc, char *argv[]) +{ + Elf32_Off symTblOffset = 0; + Elf32_Word symTblSize; /* in bytes */ + char * pStringTable = NULL; + char * inFileName; + char * outFileName; + int option; + int inFd = -1; + FILE * outFile = NULL; + unsigned strTblIx; + + /* argument parsing */ + + if (argc != 5) + { + fprintf (stderr, usage, argv[0]); + goto errorReturn; + } + + while ((option = getopt (argc, argv, "i:o:")) != -1) + { + switch (option) + { + case 'i': + inFileName = optarg; + break; + case 'o': + outFileName = optarg; + break; + default: + fprintf (stderr, usage, argv[0]); + goto errorReturn; + } + } + + /* open input object ELF module and output header file */ + + inFd = open (inFileName, OPEN_FLAGS); + + if (inFd == -1) + { + fprintf (stderr, "Cannot open input object module"); + goto errorReturn; + } + + outFile = fopen (outFileName, "w"); + + if (outFile == NULL) + { + fprintf (stderr, "Cannot open output header file"); + goto errorReturn; + } + + /* + * In the following order, attempt to ... + * 1. Load the ELF header + * 2. Load the section headers + * 3. Find the symbol table + * 4. Find the string table + * 5. Load the string table + * Bail if any of those steps fail. + */ + + if ((ehdrLoad (inFd) != 0) || + (shdrsLoad (inFd) != 0) || + (symTblFind (&symTblOffset, &symTblSize) != 0) || + (strTblFind (&strTblIx) != 0) || + (strTblLoad (inFd, strTblIx, &pStringTable) != 0)) + { + goto errorReturn; + } + + + /* + * Dump the following to the header file ... + * 1. Header file preamble + * 2. Absolute symbols + * 3. Header file postscript + */ + + headerPreambleDump (outFile, outFileName); + headerAbsoluteSymbolsDump (inFd, outFile, + symTblOffset, symTblSize, pStringTable); + headerPostscriptDump (outFile); + + /* done: cleanup */ + + close (inFd); + fclose (outFile); + free (shdr); + free (pStringTable); + + return 0; + +errorReturn: + if (inFd != -1) + { + close (inFd); + } + + if (outFile != NULL) + { + fclose (outFile); + } + + if (shdr != NULL) + { + free (shdr); + } + + if (pStringTable != NULL) + { + free (pStringTable); + } + + return 1; +} diff --git a/host/src/gen_config_abssym/Makefile b/host/src/gen_config_abssym/Makefile new file mode 100644 index 00000000000..885c9d6af25 --- /dev/null +++ b/host/src/gen_config_abssym/Makefile @@ -0,0 +1,33 @@ +# Makefile - build configs.c absolute symbols generator + +# Copyright (c) 2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors +# may be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + +EXE_NAME = gen_config_abssym + +include ${VXMICRO_BASE}/make/host/exe.build diff --git a/host/src/gen_config_abssym/gen_config_abssym.c b/host/src/gen_config_abssym/gen_config_abssym.c new file mode 100644 index 00000000000..d4f029f4bd9 --- /dev/null +++ b/host/src/gen_config_abssym/gen_config_abssym.c @@ -0,0 +1,261 @@ +/* gen_config_abssym.c - generate configs.c from autoconf.h +*/ + +/* + * Copyright (c) 2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION + +Generate configs.c file containing absolute symbols for kconfig options from +autoconf.h. + +configs.c is responsible for the generation of the absolute symbols whose +value represents the settings of various CONFIG configuration options. +These symbols can be used by the VxMicro host tools to determine the +configuration options in effect when the microkernel or nanokernel was built. + +If a configuration macro is defined, a corresponding absolute symbol should +be generated. The absolute symbol should have the same name as the +configuration macro. The symbol value should be: + - the integer 1 for configuration macros of type "bool" (which is the value + assigned to these macros in ) + - the macro value for configuration macros of type "int" or "hex" + - the integer 1 for configuration macros of type "string", as it is not + possible to represent the actual value of the configuration macro. + +No corresponding symbol should be generated when a macro is not defined. + +All of the absolute symbols defined by configs.c will be present in the +final microkernel or nanokernel ELF image (due to the linker's reference to +the _ConfigAbsSyms symbol). +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +static void usage(const int len); +static void get_options(int argc, char *argv[]); +static void open_files(void); +static void close_files(void); +static void generate_files(void); +static void clean_exit(const int exit_code); + +enum { + IFILE=0, /* input file */ + OFILE, /* C output file */ + NUSERFILES, /* number of user-provided file names */ + EXECFILE=NUSERFILES, /* for name of executable */ + NFILES /* total number of files open */ +}; +enum { SHORT_USAGE, LONG_USAGE }; + +static int fds[NUSERFILES] = {-1, -1}; +static const char *filenames[NFILES]; +static struct version version = {KERNEL_VERSION, 1, 0, 0}; + +int main(int argc, char *argv[]) +{ + filenames[EXECFILE] = basename(argv[0]); + get_options(argc, argv); /* may exit */ + open_files(); /* may exit */ + generate_files(); + close_files(); + return 0; +} + +static void get_options(int argc, char *argv[]) +{ + int ii, opt; + while ((opt = getopt(argc, argv, "hi:o:v")) != -1) { + switch(opt) { + case 'i': + filenames[IFILE] = optarg; + break; + case 'o': + filenames[OFILE] = optarg; + break; + case 'h': + usage(LONG_USAGE); + exit(0); + case 'v': + show_version(filenames[EXECFILE], &version); + exit(0); + default: + usage(SHORT_USAGE); + exit(-1); + } + } + for(ii = IFILE; ii < NUSERFILES; ii++) { + if (!filenames[ii]) { + usage(SHORT_USAGE); + exit(-1); + } + } +} + +static void open_files(void) +{ + const int open_w_flags = O_WRONLY|O_CREAT|O_TRUNC; + const mode_t open_mode = S_IWUSR|S_IRUSR; + int ii; + + fds[IFILE] = open_binary(filenames[IFILE], O_RDONLY); + fds[OFILE] = open(filenames[OFILE], open_w_flags, open_mode); + + for(ii = 0; ii < NUSERFILES; ii++) { + int invalid = fds[ii] == -1; + if (invalid) { + const char *invalid = filenames[ii]; + fprintf(stderr, "invalid file %s\n", invalid); + for(--ii; ii >= 0; ii--) { + close(fds[ii]); + } + exit (-1); + } + } +} + +static void write_str(const char *str) +{ + int len = strlen(str); + if (write(fds[OFILE], str, len) != len) { + perror("write"); + clean_exit(-1); + } +} + +static void generate_files(void) +{ + char *buf, *pBuf; + struct stat autoconf_h_stat; + off_t size; + + if (stat(filenames[IFILE], &autoconf_h_stat) == -1) { + perror("stat"); + clean_exit(-1); + } + + buf = malloc(autoconf_h_stat.st_size); + if (!buf) { + perror("out-of-memory"); + clean_exit(-1); + } + + size = read(fds[IFILE], buf, autoconf_h_stat.st_size); + if (autoconf_h_stat.st_size != size) { + perror("read"); + clean_exit(-1); + } + + pBuf = buf; + pBuf = strstr(pBuf, "#define AUTOCONF_INCLUDED"); + + write_str("/* file is auto-generated, do not modify ! */\n\n"); + write_str("#include \n\n"); + write_str("GEN_ABS_SYM_BEGIN (_ConfigAbsSyms)\n\n"); + + for (;;) { + char *sym, *val, *endl, *str = "1"; + + pBuf = strstr(pBuf, "#"); + if (!strncmp(pBuf, "#endif", strlen("#endif"))) { + break; + } + + sym = strstr(pBuf, "CONFIG"); + val = strstr(sym, " ") + 1; + endl = strstr(val, ENDL); + + val[-1] = 0; + endl[0] = 0; + + if (val[0] == '\"') { + val = str; + } + + write_str("GEN_ABSOLUTE_SYM("); + write_str(sym); + write_str(", "); + write_str(val); + write_str(");\n"); + + pBuf = endl + 1; + } + + write_str("\nGEN_ABS_SYM_END\n"); + + free(buf); +} + +static void close_files(void) +{ + int ii; + for(ii = 0; ii < NUSERFILES; ii++) { + close(fds[ii]); + } +} + +static void clean_exit(const int exit_code) +{ + close_files(); + exit(exit_code); +} + +static void usage(const int len) +{ + fprintf(stderr, + "\n%s -i -o \n", + filenames[EXECFILE]); + + if (len == SHORT_USAGE) { + return; + } + + fprintf(stderr, + "\n" + " options\n" + "\n" + " -i \n\n" + " [Mandatory] The pathname of autoconf.h.\n\n" + " -o \n\n" + " [Mandatory] The pathname of output configs.c.\n" + " -v Display version.\n\n" + " -h Display this help.\n\n" + "\nReturns -1 on error, 0 on success\n\n"); +} diff --git a/host/src/include/vxmicro.h b/host/src/include/vxmicro.h new file mode 100644 index 00000000000..deee1a7bff1 --- /dev/null +++ b/host/src/include/vxmicro.h @@ -0,0 +1,35 @@ +/* vxmicro.h - master header file for vxmicro host tools libraries */ + +/* + * Copyright (c) 2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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 +#include +#include diff --git a/host/src/include/vxmicro/os.h b/host/src/include/vxmicro/os.h new file mode 100644 index 00000000000..66e208223ff --- /dev/null +++ b/host/src/include/vxmicro/os.h @@ -0,0 +1,59 @@ +/* os.h - OS abstraction library */ + +/* + * Copyright (c) 2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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 _os__h_ +#define _os__h_ + +#if defined (WINDOWS) + #define ENDL "\r\n" +#else + #define ENDL "\n" +#endif + +#if defined (WINDOWS) +static inline +int is_path_separator(const char c) +{ + /* Might have both '/' and '\' in path */ + return c == '/' || c == '\\'; +} +#else +static inline +int is_path_separator(const char c) +{ + return c == '/'; +} +#endif + +extern int open_binary(const char *pathname, int flags, ...); + +#endif /* _os__h_ */ diff --git a/host/src/include/vxmicro/util.h b/host/src/include/vxmicro/util.h new file mode 100644 index 00000000000..2b516c41ae8 --- /dev/null +++ b/host/src/include/vxmicro/util.h @@ -0,0 +1,46 @@ +/* util.h - misc utilities for build host tools */ + +/* + * Copyright (c) 2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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 _UTIL__H_ +#define _UTIL__H_ + +#define ALIAS(fn,fn_alias,ret) ret fn_alias() __attribute__((alias(#fn))); + +extern const char * basename(const char *pathname); + +static inline +unsigned long round_up(unsigned long x, unsigned long align) +{ + return ((x + (align - 1)) & ~(align - 1)); +} + +#endif /* _UTIL__H_ */ diff --git a/host/src/include/vxmicro/version.h b/host/src/include/vxmicro/version.h new file mode 100644 index 00000000000..68e444a7e1f --- /dev/null +++ b/host/src/include/vxmicro/version.h @@ -0,0 +1,40 @@ +/* version.h - version number library */ + +/* + * Copyright (c) 2013-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +struct version { + int kernel; + int major; + int minor; + int maintenance; +}; + +extern void show_version(const char *name, const struct version *ver); diff --git a/host/src/lib/Makefile b/host/src/lib/Makefile new file mode 100644 index 00000000000..6dd46080ecc --- /dev/null +++ b/host/src/lib/Makefile @@ -0,0 +1,33 @@ +# Makefile - build vxmicro library + +# Copyright (c) 2013-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors +# may be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + +LIB_NAME = vxmicro + +include ${VXMICRO_BASE}/make/host/lib.build diff --git a/host/src/lib/os.c b/host/src/lib/os.c new file mode 100644 index 00000000000..800e1c7a2ef --- /dev/null +++ b/host/src/lib/os.c @@ -0,0 +1,56 @@ +/* os.c - OS abstraction library */ + +/* + * Copyright (c) 2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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 +#include +#include +#include + +#include + +#if defined (WINDOWS) + #define WITH_BINARY(x) (x | O_BINARY) +#else + #define WITH_BINARY(x) (x) +#endif + +int open_binary(const char *pathname, int flags, ...) +{ + va_list ap; + int fd; + + va_start(ap, flags); + fd = open(pathname, WITH_BINARY(flags), va_arg(ap, int)); + va_end(ap); + + return fd; +} diff --git a/host/src/lib/util.c b/host/src/lib/util.c new file mode 100644 index 00000000000..ef8491d8b96 --- /dev/null +++ b/host/src/lib/util.c @@ -0,0 +1,49 @@ +/* util.c - misc utilities library */ + +/* + * Copyright (c) 2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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 +#include + +const char * basename(const char *pathname) +{ + int end = strlen(pathname)-1; + while(end != -1) { + if (is_path_separator(pathname[end])) { + if (0 == end || pathname[end-1] != '\\') { + ++end; + break; + } + } + --end; + } + return &pathname[end]; +} diff --git a/host/src/lib/version.c b/host/src/lib/version.c new file mode 100644 index 00000000000..56345c730e7 --- /dev/null +++ b/host/src/lib/version.c @@ -0,0 +1,45 @@ +/* version.c - version number library */ + +/* + * Copyright (c) 2013-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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 +#include + +void show_version(const char *name, const struct version *ver) +{ + fprintf(stdout, + "\n%s" + " %4d.%d.%d.%3.3d, (c) Wind River Systems, Inc.\n" + " Built on %s at %s\n\n", + name, + ver->kernel, ver->major, ver->minor, ver->maintenance, + __DATE__, __TIME__); +} diff --git a/host/src/mkEvents/Makefile b/host/src/mkEvents/Makefile new file mode 100644 index 00000000000..e3155f000ec --- /dev/null +++ b/host/src/mkEvents/Makefile @@ -0,0 +1,35 @@ +# +# Makefile +# + +# Copyright (c) 2013-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors +# may be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + +EXE_NAME = mkevents + +include ${VXMICRO_BASE}/make/host/exe.build diff --git a/host/src/mkEvents/mkevents.c b/host/src/mkEvents/mkevents.c new file mode 100644 index 00000000000..81e5d799449 --- /dev/null +++ b/host/src/mkEvents/mkevents.c @@ -0,0 +1,71 @@ +/* mkevents.c - Create A VPF Event */ + +/* + * Copyright (c) 2013-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +Creates event object line(s) suitable for inclusion in a VPF file. +The number of events to create is passed in on the command line +in decimal notation. Each event object is outputted on stdout. +*/ + +#include +#include + +void usage ( + char* progname /* name of the program to use */ + ) + { + fprintf (stderr, "Utility creates a series of microkernel VPF event objects. Output is sent to stdout.\n"); + fprintf (stderr, "Usage: %s \n", progname); + } + +#define EVENT_STR " EVENT _TaskIrqEvt%d NULL\n" + +int main ( + int argc, + char* argv[] + ) + { + int i, j; + + if (argc != 2) + { + usage (argv[0]); + return -1; + } + + j = atoi(argv[1]); + for (i = 0; i < j; i++) + printf (EVENT_STR, i); + + return 0; + } diff --git a/host/src/wrsconfig/COPYING-GPL-2.0.txt b/host/src/wrsconfig/COPYING-GPL-2.0.txt new file mode 100755 index 00000000000..fbdd65f6f8b --- /dev/null +++ b/host/src/wrsconfig/COPYING-GPL-2.0.txt @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/host/src/wrsconfig/Makefile b/host/src/wrsconfig/Makefile new file mode 100644 index 00000000000..a582329ddbb --- /dev/null +++ b/host/src/wrsconfig/Makefile @@ -0,0 +1,37 @@ +# Makefile - build wrsconfig tool + +# Copyright (c) 2011-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors +# may be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + +EXE_NAME = wrsconfig +SOURCES = conf.c zconf.tab.c + +EXTRA_CFLAGS = -DKBUILD_NO_NLS=no -DNO_REGEX -DNO_UNAME +EXTRA_CFLAGS_win32 = -DHOST_WIN32 + +include ${VXMICRO_BASE}/make/host/exe.build diff --git a/host/src/wrsconfig/conf.c b/host/src/wrsconfig/conf.c new file mode 100755 index 00000000000..e9063510fe9 --- /dev/null +++ b/host/src/wrsconfig/conf.c @@ -0,0 +1,695 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef HOST_WIN32 + extern long int random(void); + extern void srandom(unsigned int seed); +#endif + +extern int conf_warnings; + +#define LKC_DIRECT_LINK +#include "lkc.h" +/* undef SYMNAME to hide the name of the component being set */ +#define SYMNAME +/* define PREFIX to get the full name of the component */ +/*#define PREFIX */ + +char *myName; /* name of the program taken from argv[0] */ + +static void conf(struct menu *menu); +static void check_conf(struct menu *menu); + +enum { + ask_all, + ask_new, + ask_silent, + set_default, + set_yes, + set_mod, + set_no, + set_random, + set_new_default +} input_mode = ask_all; +char *defconfig_file; + +static int indent = 1; +static int valid_stdin = 1; +static int quiet = 0; +static int conf_cnt; +static char line[512]; +static struct menu *rootEntry; + +#define print_nq(arg...) do {if (quiet == 0){printf(arg);}} while (quiet < 0) + +static char nohelp_text[] = N_("Sorry, no help available for this option yet.\n"); + +static const char *get_help(struct menu *menu) +{ + if (menu_has_help(menu)) + return menu_get_help(menu); + else + return nohelp_text; +} + +static void strip(char *str) +{ + char *p = str; + int l; + + while ((isspace(*p))) + p++; + l = strlen(p); + if (p != str) + memmove(str, p, l + 1); + if (!l) + return; + p = str + l - 1; + while ((isspace(*p))) + *p-- = 0; +} + +static void check_stdin(void) +{ + if (!valid_stdin && input_mode == ask_silent) { + printf(_("aborted!\n\n")); + printf(_("Console input/output is redirected. \n\n")); + exit(1); + } +} + +static int conf_askvalue(struct symbol *sym, const char *def) +{ + enum symbol_type type = sym_get_type(sym); + tristate val; + +#ifdef IDENTIFY_NEW + if (!sym_has_value(sym)) + print_nq("(NEW) "); +#endif + line[0] = '\n'; + line[1] = 0; + + if (!sym_is_changable(sym)) { + print_nq("%s\n", def); + line[0] = '\n'; + line[1] = 0; + return 0; + } + + switch (input_mode) { + case set_no: + case set_mod: + case set_yes: + case set_random: + case set_new_default: + if (sym_has_value(sym)) { + print_nq("%s\n", def); + return 0; + } + break; + case ask_new: + case ask_silent: + if (sym_has_value(sym)) { + print_nq("%s\n", def); + return 0; + } + check_stdin(); + case ask_all: + fflush(stdout); + fgets(line, sizeof(line), stdin); + return 1; + case set_default: + print_nq("%s\n", def); + return 1; + default: + break; + } + + switch (type) { + case S_INT: + case S_HEX: + case S_STRING: + print_nq("%s\n", def); + return 1; + default: + ; + } + switch (input_mode) { + case set_yes: + if (sym_tristate_within_range(sym, yes)) { + line[0] = 'y'; + line[1] = '\n'; + line[2] = 0; + break; + } + case set_mod: + if (type == S_TRISTATE) { + if (sym_tristate_within_range(sym, mod)) { + line[0] = 'm'; + line[1] = '\n'; + line[2] = 0; + break; + } + } else { + if (sym_tristate_within_range(sym, yes)) { + line[0] = 'y'; + line[1] = '\n'; + line[2] = 0; + break; + } + } + case set_no: + if (sym_tristate_within_range(sym, no)) { + line[0] = 'n'; + line[1] = '\n'; + line[2] = 0; + break; + } + case set_random: + do { + val = (tristate)(random() % 3); + } while (!sym_tristate_within_range(sym, val)); + + switch (val) { + case no: line[0] = 'n'; break; + /*case mod: line[0] = 'm'; break;*/ + /*case yes: line[0] = 'y'; break;*/ + /* since we are not supporting the m mode anything that is not n is y */ + default: line[0] = 'y'; break; + } + line[1] = '\n'; + line[2] = 0; + break; + case set_new_default: + line[0] = *def; + line[1] = '\n'; + line[2] = 0; + break; + default: + break; + } + print_nq("%s", line); + return 1; +} + +int conf_string(struct menu *menu) +{ + struct symbol *sym = menu->sym; + const char *def; + + while (1) { + print_nq("%*s%s ", indent - 1, "", menu->prompt->text); + +#ifdef SYMNAME +#ifdef PREFIX + print_nq(" (CONFIG_%s) ", sym->name); +#else + print_nq(" (%s) ", sym->name); +#endif +#endif + def = sym_get_string_value(sym); + if (sym_get_string_value(sym)) + print_nq("[%s] ", def); + if (!conf_askvalue(sym, def)) + return 0; + switch (line[0]) { + case '\n': + break; + case '?': + /* print help */ + if (line[1] == '\n') { + print_nq("\n%s\n", get_help(menu)); + def = NULL; + break; + } + default: + line[strlen(line)-1] = 0; + def = line; + } + if (def && sym_set_string_value(sym, def)) + return 0; + } +} + +static int conf_sym(struct menu *menu) +{ + struct symbol *sym = menu->sym; + tristate oldval, newval; + + while (1) { + print_nq("%*s%s ", indent - 1, "", menu->prompt->text); +#ifdef SYMNAME + if (sym->name) +#ifdef PREFIX + print_nq(" (CONFIG_%s) ", sym->name); +#else + print_nq(" (%s) ", sym->name); +#endif +#endif + print_nq("["); + oldval = sym_get_tristate_value(sym); + switch (oldval) { + case no: + print_nq("N"); + break; + case mod: + print_nq("M"); + break; + case yes: + print_nq("Y"); + break; + } + if (oldval != no && sym_tristate_within_range(sym, no)) + print_nq("/n"); + if (oldval != mod && sym_tristate_within_range(sym, mod)) + print_nq("/m"); + if (oldval != yes && sym_tristate_within_range(sym, yes)) + print_nq("/y"); + if (menu_has_help(menu)) + print_nq("/?"); + print_nq("] "); + if (!conf_askvalue(sym, sym_get_string_value(sym))) + return 0; + strip(line); + + switch (line[0]) { + case 'n': + case 'N': + newval = no; + if (!line[1] || !strcmp(&line[1], "o")) + break; + continue; + case 'm': + case 'M': + newval = mod; + if (!line[1]) + break; + continue; + case 'y': + case 'Y': + newval = yes; + if (!line[1] || !strcmp(&line[1], "es")) + break; + continue; + case 0: + newval = oldval; + break; + case '?': + goto help; + default: + continue; + } + if (sym_set_tristate_value(sym, newval)) + return 0; +help: + print_nq("\n%s\n", get_help(menu)); + } +} + +static int conf_choice(struct menu *menu) +{ + struct symbol *sym, *def_sym; + struct menu *child; + bool is_new; + + sym = menu->sym; + is_new = !sym_has_value(sym); + if (sym_is_changable(sym)) { + conf_sym(menu); + sym_calc_value(sym); + switch (sym_get_tristate_value(sym)) { + case no: + return 1; + case mod: + return 0; + case yes: + break; + } + } else { + switch (sym_get_tristate_value(sym)) { + case no: + return 1; + case mod: + print_nq("%*s%s\n", indent - 1, "", menu_get_prompt(menu)); + return 0; + case yes: + break; + } + } + + while (1) { + int cnt, def; + + print_nq("%*s%s\n", indent - 1, "", menu_get_prompt(menu)); + def_sym = sym_get_choice_value(sym); + cnt = def = 0; + line[0] = 0; + for (child = menu->list; child; child = child->next) { + if (!menu_is_visible(child)) + continue; + if (!child->sym) { + print_nq("%*c %s\n", indent, '*', menu_get_prompt(child)); + continue; + } + cnt++; + if (child->sym == def_sym) { + def = cnt; + print_nq("%*c", indent, '>'); + } else + print_nq("%*c", indent, ' '); + print_nq(" %d. %s", cnt, menu_get_prompt(child)); + +#ifdef SYMNAME + if (child->sym->name) +#ifdef PREFIX + print_nq(" (CONFIG_%s)",child->sym->name); +#else + print_nq(" (%s)", child->sym->name); +#endif +#endif +#ifdef IDENTIFY_NEW + if (!sym_has_value(child->sym)) + print_nq(" (NEW)"); +#endif + print_nq("\n"); + } + print_nq("%*schoice", indent - 1, ""); + if (cnt == 1) { + print_nq("[1]: 1\n"); + goto conf_childs; + } + print_nq("[1-%d", cnt); + if (menu_has_help(menu)) + print_nq("?"); + print_nq("]: "); + switch (input_mode) { + case ask_new: + case ask_silent: + if (!is_new) { + cnt = def; + print_nq("%d\n", cnt); + break; + } + check_stdin(); + case ask_all: + fflush(stdout); + fgets(line, sizeof(line), stdin); + strip(line); + if (line[0] == '?') { + print_nq("\n%s\n", get_help(menu)); + continue; + } + if (!line[0]) + cnt = def; + else if (isdigit(line[0])) + cnt = atoi(line); + else + continue; + break; + case set_random: + def = (random() % cnt) + 1; + case set_default: + case set_yes: + case set_mod: + case set_no: + case set_new_default: + cnt = def; + print_nq("%d\n", cnt); + break; + } + +conf_childs: + for (child = menu->list; child; child = child->next) { + if (!child->sym || !menu_is_visible(child)) + continue; + if (!--cnt) + break; + } + if (!child) + continue; + if (line[strlen(line) - 1] == '?') { + print_nq("\n%s\n", get_help(child)); + continue; + } + sym_set_choice_value(sym, child->sym); + if (child->list) { + indent += 2; + conf(child->list); + indent -= 2; + } + return 1; + } +} + +static void conf(struct menu *menu) +{ + struct symbol *sym; + struct property *prop; + struct menu *child; + + if (!menu_is_visible(menu)) + return; + + sym = menu->sym; + prop = menu->prompt; + if (prop) { + const char *prompt; + + switch (prop->type) { + case P_MENU: + if (input_mode == ask_silent && rootEntry != menu) { + check_conf(menu); + return; + } + case P_COMMENT: + prompt = menu_get_prompt(menu); + if (prompt) + print_nq("%*c\n%*c %s\n%*c\n", + indent, '*', + indent, '*', prompt, + indent, '*'); + default: + ; + } + } + + if (!sym) + goto conf_childs; + + if (sym_is_choice(sym)) { + conf_choice(menu); + if (sym->curr.tri != mod) + return; + goto conf_childs; + } + + switch (sym->type) { + case S_INT: + case S_HEX: + case S_STRING: + conf_string(menu); + break; + default: + conf_sym(menu); + break; + } + +conf_childs: + if (sym) + indent += 2; + for (child = menu->list; child; child = child->next) + conf(child); + if (sym) + indent -= 2; +} + +static void check_conf(struct menu *menu) +{ + struct symbol *sym; + struct menu *child; + + if (!menu_is_visible(menu)) + return; + + sym = menu->sym; + if (sym && !sym_has_value(sym)) { + if (sym_is_changable(sym) || + (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)) { + if (!conf_cnt++) + print_nq(_("*\n* Restart config...\n*\n")); + rootEntry = menu_get_parent_menu(menu); + conf(rootEntry); + } + } + + for (child = menu->list; child; child = child->next) + check_conf(child); +} + +int main(int ac, char **av) +{ + int i = 1; + const char *name; + struct stat tmpstat; + quiet = 0; + + myName = av[0]; + + if (ac > i && av[i][0] == '-') { + switch (av[i++][1]) { + case 'o': + input_mode = ask_new; + break; + case 's': + input_mode = ask_silent; + valid_stdin = isatty(0) && isatty(1) && isatty(2); + break; + case 'S': + input_mode = set_new_default; + quiet = 1; + break; + case 'd': + input_mode = set_default; + break; + case 'D': + input_mode = set_default; + defconfig_file = av[i++]; + if (!defconfig_file) { + printf(_("%s: No default config file specified\n"), + av[0]); + exit(1); + } + break; + case 'n': + input_mode = set_no; + break; + case 'm': + input_mode = set_mod; + break; + case 'y': + input_mode = set_yes; + break; + case 'r': + input_mode = set_random; + srandom(time(NULL)); + break; + case 'h': + case '?': + fprintf(stderr, "See README for usage info\n"); + exit(0); + } + } + name = av[i]; + if (!name) { + printf(_("%s: config file name parameter missing\n"), av[0]); + exit(1); + } + conf_parse(name); + /* zconfdump(stdout); */ + switch (input_mode) { + case set_default: + if (!defconfig_file) + defconfig_file = conf_get_default_confname(); + if (conf_read(defconfig_file)) { + printf("***\n" + "*** Can't find default configuration \"%s\"!\n" + "***\n", defconfig_file); + exit(1); + } + break; + case ask_silent: +#ifdef VXWORKS + if (stat("vsb.config", &tmpstat)) { +#else + if (stat(".config", &tmpstat)) { +#endif + printf(_("***\n" + "missing configuration file can not run in silent mode" + "***\n")); + exit(1); + } + case ask_all: + case ask_new: + conf_read(NULL); + break; + case set_no: + case set_mod: + case set_yes: + case set_random: + case set_new_default: + name = getenv("WRSCONFIG_ALLCONFIG"); + if (!name) /* check old env name */ + name = getenv("VCONFIG_ALLCONFIG"); + if (name && !stat(name, &tmpstat)) { + conf_read_simple(name, S_DEF_USER); + break; + } + switch (input_mode) { + case set_no: name = "allno.config"; break; + case set_mod: name = "allmod.config"; break; + case set_yes: name = "allyes.config"; break; + case set_random: name = "allrandom.config"; break; + case set_new_default: name = "alldef.config"; break; + default: break; + } + if (!stat(name, &tmpstat)) + conf_read_simple(name, S_DEF_USER); + else if (!stat("all.config", &tmpstat)) + conf_read_simple("all.config", S_DEF_USER); + break; + default: + break; + } + + if (conf_warnings) { + fprintf(stderr, _("\n*** Configuration warning(s) found\n\n")); + return 1; + } + + if (input_mode != ask_silent) { + rootEntry = &rootmenu; + conf(&rootmenu); + if (input_mode == ask_all) { + input_mode = ask_silent; + valid_stdin = 1; + } + } else if (conf_get_changed()) { + name = getenv("WRSCONFIG_NOSILENTUPDATE"); + if (!name) /* check old env name */ + name = getenv("VCONFIG_NOSILENTUPDATE"); + if (name && *name) { + fprintf(stderr, _("\n*** configuration requires explicit update.\n\n")); + return 1; + } + } else + goto skip_check; + + do { + conf_cnt = 0; + check_conf(&rootmenu); + } while (conf_cnt); + + if (conf_write(NULL)) { + fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n")); + return 1; + } + +skip_check: + if (conf_write_autoconf()) { + fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n")); + return 1; + } + + return 0; +} diff --git a/host/src/wrsconfig/confdata.c b/host/src/wrsconfig/confdata.c new file mode 100755 index 00000000000..700320b42b6 --- /dev/null +++ b/host/src/wrsconfig/confdata.c @@ -0,0 +1,915 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define LKC_DIRECT_LINK +#include "lkc.h" + +extern char *myName; + +static void conf_warning(const char *fmt, ...) + __attribute__ ((format (printf, 1, 2))); + +static const char *conf_filename; +static int conf_lineno, conf_unsaved; +int conf_warnings; + +static void conf_warning(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + fprintf(stderr, "%s:%d:warning: ", conf_filename, conf_lineno); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); + va_end(ap); + conf_warnings++; +} + +const char *conf_get_configname(void) +{ + char *name = getenv("WRSCONFIG_CONFIG"); + if (!name) /* check old env name */ + name = getenv("VCONFIG_CONFIG"); + +#ifdef VXWORKS + return name ? name : "vsb.config"; +#else + return name ? name : ".config"; +#endif +} + +static char *conf_expand_value(const char *in) +{ + struct symbol *sym; + const char *src; + static char res_value[SYMBOL_MAXLENGTH]; + char *dst, name[SYMBOL_MAXLENGTH]; + + res_value[0] = 0; + dst = name; + while ((src = strchr(in, '$'))) { + strncat(res_value, in, src - in); + src++; + dst = name; + while (isalnum(*src) || *src == '_') + *dst++ = *src++; + *dst = 0; + sym = sym_lookup(name, 0); + sym_calc_value(sym); + strcat(res_value, sym_get_string_value(sym)); + in = src; + } + strcat(res_value, in); + + return res_value; +} + +char *conf_get_default_confname(void) +{ + static char fullname[PATH_MAX+1]; +#if 0 +this bogus code turned off. env is never null so no need for if (env) +which is always true. Thus, we generate a /default.vxconfig fullname +since env is "". The stat of that always fails so we never return fullname. +Also, since default.vxconfig has no expansions in it there is no need +to try expand it. We can replace all this code with "return conf_defname;". +However we want to rename vxConfig to wrsConfig so the default config +filename should be default.wrsConfig. Thus we generate the default filename +so it is backwards compatible in case this program is called vxConfig. + + const char conf_defname[] = "default.vxconfig"; + + struct stat buf; + char *env, *name; + + name = conf_expand_value(conf_defname); + env = ""; + /* env = getenv(SRCTREE); */ + if (env) { + sprintf(fullname, "%s/%s", env, name); + if (!stat(fullname, &buf)) + return fullname; + } + return name; +#endif + + if (strcmp (myName, "vxConfig") == 0) + return "default.vxconfig"; + + sprintf (fullname, "default.%s", myName); + + return fullname; +} + +int conf_read_simple(const char *name, int def) +{ + FILE *in = NULL; + char line[1024]; + char *p, *p2; + struct symbol *sym; + int i, def_flags; + int pfx = strlen("CONFIG_"); + + if (name) { + in = zconf_fopen(name); + } else { + struct property *prop; + + name = conf_get_configname(); + in = zconf_fopen(name); + + if (in) + goto load; + + sym_add_change_count(1); + if (!sym_defconfig_list) + return 1; + + for_all_defaults(sym_defconfig_list, prop) { + if (expr_calc_value(prop->visible.expr) == no || + prop->expr->type != E_SYMBOL) + continue; + name = conf_expand_value(prop->expr->left.sym->name); + in = zconf_fopen(name); + if (in) { + printf(_("#\n" + "# using defaults found in %s\n" + "#\n"), name); + goto load; + } + } + } + if (!in) + return 1; + +load: + conf_filename = name; + conf_lineno = 0; + conf_warnings = 0; + conf_unsaved = 0; + + def_flags = SYMBOL_DEF << def; + for_all_symbols(i, sym) { + sym->flags |= SYMBOL_CHANGED; + sym->flags &= ~(def_flags|SYMBOL_VALID); + if (sym_is_choice(sym)) + sym->flags |= def_flags; + switch (sym->type) { + case S_INT: + case S_HEX: + case S_STRING: + if (sym->def[def].val) + free(sym->def[def].val); + default: + sym->def[def].val = NULL; + sym->def[def].tri = no; + } + } + + while (fgets(line, sizeof(line), in)) { + conf_lineno++; + sym = NULL; + switch (line[0]) { + case '#': + if (memcmp(line + 2, "CONFIG_", pfx)) + continue; + p = strchr(line + 2 + pfx, ' '); + if (!p) + continue; + *p++ = 0; + if (strncmp(p, "is not set", 10)) + continue; + if (def == S_DEF_USER) { + sym = sym_find(line + 2 + pfx); + if (!sym) { + conf_warning("trying to assign nonexistent symbol %s", line + 2 + pfx); + break; + } + } else { + sym = sym_lookup(line + 2 + pfx, 0); + if (sym->type == S_UNKNOWN) + sym->type = S_BOOLEAN; + } + if (sym->flags & def_flags) { + conf_warning("trying to reassign symbol %s", sym->name); + break; + } + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: + sym->def[def].tri = no; + sym->flags |= def_flags; + break; + default: + ; + } + break; + case 'C': + if (memcmp(line, "CONFIG_", pfx)) { + conf_warning("unexpected data"); + continue; + } + p = strchr(line + pfx, '='); + if (!p) + continue; + *p++ = 0; + p2 = strchr(p, '\n'); + if (p2) { + *p2-- = 0; + if (*p2 == '\r') + *p2 = 0; + } + if (def == S_DEF_USER) { + sym = sym_find(line + pfx); + if (!sym) { + conf_warning("trying to assign nonexistent symbol %s", line + pfx); + break; + } + } else { + sym = sym_lookup(line + pfx, 0); + if (sym->type == S_UNKNOWN) + sym->type = S_OTHER; + } + if (sym->flags & def_flags) { + conf_warning("trying to reassign symbol %s", sym->name); + break; + } + switch (sym->type) { + case S_TRISTATE: + if (p[0] == 'm') { + sym->def[def].tri = mod; + sym->flags |= def_flags; + break; + } + case S_BOOLEAN: + if (p[0] == 'y') { + sym->def[def].tri = yes; + sym->flags |= def_flags; + break; + } + if (p[0] == 'n') { + sym->def[def].tri = no; + sym->flags |= def_flags; + break; + } + conf_warning("symbol value '%s' invalid for %s", p, sym->name); + break; + case S_OTHER: + if (*p != '"') { + for (p2 = p; *p2 && !isspace(*p2); p2++) + ; + sym->type = S_STRING; + goto done; + } + case S_STRING: + if (*p++ != '"') + break; + for (p2 = p; (p2 = strpbrk(p2, "\"\\")); p2++) { + if (*p2 == '"') { + *p2 = 0; + break; + } + memmove(p2, p2 + 1, strlen(p2)); + } + if (!p2) { + conf_warning("invalid string found"); + continue; + } + case S_INT: + case S_HEX: +done: + if (sym_string_valid(sym, p)) { + sym->def[def].val = strdup(p); + sym->flags |= def_flags; + } else { + conf_warning("symbol value '%s' invalid for %s", p, sym->name); + continue; + } + break; + default: + ; + } + break; + case '\r': + case '\n': + break; + default: + conf_warning("unexpected data"); + continue; + } + if (sym && sym_is_choice_value(sym)) { + struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym)); + switch (sym->def[def].tri) { + case no: + break; + case mod: + if (cs->def[def].tri == yes) { + conf_warning("%s creates inconsistent choice state", sym->name); + cs->flags &= ~def_flags; + } + break; + case yes: + if (cs->def[def].tri != no) { + conf_warning("%s creates inconsistent choice state", sym->name); + cs->flags &= ~def_flags; + } else + cs->def[def].val = sym; + break; + } + cs->def[def].tri = E_OR(cs->def[def].tri, sym->def[def].tri); + } + } + fclose(in); + + if (modules_sym) + sym_calc_value(modules_sym); + return 0; +} + +int conf_read(const char *name) +{ + struct symbol *sym; + struct property *prop; + struct expr *e; + int i, flags; + + sym_set_change_count(0); + + if (conf_read_simple(name, S_DEF_USER)) + return 1; + + for_all_symbols(i, sym) { + sym_calc_value(sym); + if (sym_is_choice(sym) || (sym->flags & SYMBOL_AUTO)) + goto sym_ok; + if (sym_has_value(sym) && (sym->flags & SYMBOL_WRITE)) { + /* check that calculated value agrees with saved value */ + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: + if (sym->def[S_DEF_USER].tri != sym_get_tristate_value(sym)) + break; + if (!sym_is_choice(sym)) + goto sym_ok; + default: + if (!strcmp(sym->curr.val, sym->def[S_DEF_USER].val)) + goto sym_ok; + break; + } + } else if (!sym_has_value(sym) && !(sym->flags & SYMBOL_WRITE)) + /* no previous value and not saved */ + goto sym_ok; + conf_unsaved++; + /* maybe print value in verbose mode... */ +sym_ok: + if (!sym_is_choice(sym)) + continue; + /* The choice symbol only has a set value (and thus is not new) + * if all its visible childs have values. + */ + prop = sym_get_choice_prop(sym); + flags = sym->flags; + for (e = prop->expr; e; e = e->left.expr) + if (e->right.sym->visible != no) + flags &= e->right.sym->flags; + sym->flags &= flags | ~SYMBOL_DEF_USER; + } + + for_all_symbols(i, sym) { + if (sym_has_value(sym) && !sym_is_choice_value(sym)) { + /* Reset values of generates values, so they'll appear + * as new, if they should become visible, but that + * doesn't quite work if the Kconfig and the saved + * configuration disagree. + */ + if (sym->visible == no && !conf_unsaved) + sym->flags &= ~SYMBOL_DEF_USER; + switch (sym->type) { + case S_STRING: + case S_INT: + case S_HEX: + /* Reset a string value if it's out of range */ + if (sym_string_within_range(sym, sym->def[S_DEF_USER].val)) + break; + sym->flags &= ~(SYMBOL_VALID|SYMBOL_DEF_USER); + conf_unsaved++; + break; + default: + break; + } + } + } + + sym_add_change_count(conf_warnings || conf_unsaved); + + return 0; +} + +int conf_write(const char *name) +{ + FILE *out; + struct symbol *sym; + struct menu *menu; + const char *basename; + char dirname[PATH_MAX+1], tmpname[PATH_MAX+1], newname[PATH_MAX+1]; + int type, l; + const char *str; + time_t now; + int use_timestamp = 1; + char *env; + + dirname[0] = 0; + if (name && name[0]) { + struct stat st; + char *slash; + + if (!stat(name, &st) && S_ISDIR(st.st_mode)) { + strcpy(dirname, name); + strcat(dirname, "/"); + basename = conf_get_configname(); + } else if ((slash = strrchr(name, '/'))) { + int size = slash - name + 1; + memcpy(dirname, name, size); + dirname[size] = 0; + if (slash[1]) + basename = slash + 1; + else + basename = conf_get_configname(); + } else + basename = name; + } else + basename = conf_get_configname(); + + sprintf(newname, "%s%s", dirname, basename); + env = getenv("WRSCONFIG_OVERWRITECONFIG"); + if (!env) /* check old env name */ + env = getenv("VCONFIG_OVERWRITECONFIG"); + if (!env || !*env) { + sprintf(tmpname, "%s.tmpconfig.%d", dirname, (int)getpid()); + out = fopen(tmpname, "w"); + } else { + *tmpname = 0; + out = fopen(newname, "w"); + } + if (!out) + return 1; + + /* sym = sym_lookup("KERNELVERSION", 0); + sym_calc_value(sym); */ + time(&now); + env = getenv("WRSCONFIG_NOTIMESTAMP"); + if (!env) /* check old env name */ + env = getenv("VCONFIG_NOTIMESTAMP"); + if (env && *env) + use_timestamp = 0; + + fprintf(out, _("#\n" + "# Automatically generated file: do not edit\n" + "%s%s" + "#\n"), + use_timestamp ? "# " : "", + use_timestamp ? ctime(&now) : ""); + + if (!conf_get_changed()) + sym_clear_all_valid(); + + menu = rootmenu.list; + while (menu) { + sym = menu->sym; + if (!sym) { + if (!menu_is_visible(menu)) + goto next; + str = menu_get_prompt(menu); + fprintf(out, "\n" + "#\n" + "# %s\n" + "#\n", str); + } else if (!(sym->flags & SYMBOL_CHOICE)) { + sym_calc_value(sym); + if (!(sym->flags & SYMBOL_WRITE)) + goto next; + sym->flags &= ~SYMBOL_WRITE; + type = sym->type; + if (type == S_TRISTATE) { + sym_calc_value(modules_sym); + if (modules_sym->curr.tri == no) + type = S_BOOLEAN; + } + switch (type) { + case S_BOOLEAN: + case S_TRISTATE: + switch (sym_get_tristate_value(sym)) { + case no: + fprintf(out, "# CONFIG_%s is not set\n", sym->name); + break; + case mod: + fprintf(out, "CONFIG_%s=m\n", sym->name); + break; + case yes: + fprintf(out, "CONFIG_%s=y\n", sym->name); + break; + } + break; + case S_STRING: + str = sym_get_string_value(sym); + fprintf(out, "CONFIG_%s=\"", sym->name); + while (1) { + l = strcspn(str, "\"\\"); + if (l) { + fwrite(str, l, 1, out); + str += l; + } + if (!*str) + break; + fprintf(out, "\\%c", *str++); + } + fputs("\"\n", out); + break; + case S_HEX: + str = sym_get_string_value(sym); + if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) { + fprintf(out, "CONFIG_%s=%s\n", sym->name, str); + break; + } + case S_INT: + str = sym_get_string_value(sym); + fprintf(out, "CONFIG_%s=%s\n", sym->name, str); + break; + } + } + +next: + if (menu->list) { + menu = menu->list; + continue; + } + if (menu->next) + menu = menu->next; + else while ((menu = menu->parent)) { + if (menu->next) { + menu = menu->next; + break; + } + } + } + fclose(out); + + if (*tmpname) { + strcat(dirname, basename); + strcat(dirname, ".old"); + loc_rename(newname, dirname); + if (loc_rename(tmpname, newname)) + return 1; + } + + /* printf(_("#\n" + "# configuration written to %s\n" + "#\n"), newname); */ + + sym_set_change_count(0); + + return 0; +} + +#ifdef VXWORKS +int conf_split_config(void) +{ + char *name, path[PATH_MAX+1], *pathName; + char *s, *d, c; + struct symbol *sym; + struct stat sb; + int res, i, fd; + + name = getenv("WRSCONFIG_AUTOCONFIG"); + if (!name) /* check old env name */ + name = getenv("VCONFIG_AUTOCONFIG"); + if (!name) + name = "h/config/auto.conf"; + conf_read_simple(name, S_DEF_AUTO); + + + if (chdir("h")) { + pathName = "h"; + loc_mkdir(pathName, 0755); + if (chdir("h")) { + printf("# mkdir(\"h\") failed\n"); + return 1; + } + } + if (chdir("config")) { + pathName = "config"; + loc_mkdir(pathName, 0755); + if (chdir("config")) { + printf("# mkdir(\"h/config\") failed\n"); + return 1; + } + } + if (chdir(myName)) { + pathName = myName; + loc_mkdir(pathName, 0755); + if (chdir(myName)) { + printf("# mkdir(\"h/config/%s\") failed\n", myName); + return 1; + } + } + if (chdir ("../../..")) { + printf("# cd(\"h/config/%s/../../.. test\") failed\n", myName); + return 1; + } + + file_write_dep("h/config/auto.conf.cmd"); + + sprintf (path, "h/config/%s", myName); + if (chdir(path)) { + printf("# chdir(\"%s\") failed\n", path); + return 1; + } + res = 0; + for_all_symbols(i, sym) { + sym_calc_value(sym); + if ((sym->flags & SYMBOL_AUTO) || !sym->name) + continue; + if (sym->flags & SYMBOL_WRITE) { + if (sym->flags & SYMBOL_DEF_AUTO) { + /* + * symbol has old and new value, + * so compare them... + */ + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: + if (sym_get_tristate_value(sym) == + sym->def[S_DEF_AUTO].tri) + continue; + break; + case S_STRING: + case S_HEX: + case S_INT: + if (!strcmp(sym_get_string_value(sym), + sym->def[S_DEF_AUTO].val)) + continue; + break; + default: + break; + } + } else { + /* + * If there is no old value, only 'no' (unset) + * is allowed as new value. + */ + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: + if (sym_get_tristate_value(sym) == no) + continue; + break; + default: + break; + } + } + } else if (!(sym->flags & SYMBOL_DEF_AUTO)) + /* There is neither an old nor a new value. */ + continue; + /* else + * There is an old value, but no new value ('no' (unset) + * isn't saved in auto.conf, so the old value is always + * different from 'no'). + */ + + /* Replace all '_' and append ".h" */ + s = sym->name; + d = path; + while ((c = *s++)) { + c = tolower(c); + *d++ = (c == '_') ? '/' : c; + } + strcpy(d, ".h"); + + /* Assume directory path already exists. */ + fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644); + if (fd == -1) { + if (errno != ENOENT) { + printf("# open1(%s) failed\n", path); + res = 1; + break; + } + /* + * Create directory components, + * unless they exist already. + */ + d = path; + while ((d = strchr(d, '/'))) { + *d = 0; + + if (stat(path, &sb) && loc_mkdir(path, 0755)) { + printf("# stat/mkdir(%s) failed\n", path); + res = 1; + goto out; + } + *d++ = '/'; + } + /* Try it again. */ + fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644); + if (fd == -1) { + printf("# open2(%s) failed\n", path); + res = 1; + break; + } + } + close(fd); + } +out: + if (chdir("../../..")) { + printf("# chdir(../../..) failed\n"); + return 1; + } + + return res; +} +#endif + +int conf_write_autoconf(void) +{ + struct symbol *sym; + const char *str; + char *name; + FILE *out, *out_h; + time_t now; + int i, l; + + sym_clear_all_valid(); + + +#ifdef VVXWORKS + if (conf_split_config()) { + printf("# conf_split_config failed\n"); + return 1; + } +#endif + + out = fopen(".tmpconfig", "w"); + if (!out) { + printf("# fopen(.tmpconfig) failed\n"); + return 1; + } + + out_h = fopen(".tmpconfig.h", "w"); + if (!out_h) { + printf("# fopen(.tmpconfig.h) failed\n"); + fclose(out); + return 1; + } + + /*sym = sym_lookup("KERNELVERSION", 0); + sym_calc_value(sym); */ + + time(&now); + fprintf(out, "#\n" + "# Automatically generated make config: don't edit\n" + "# %s" + "#\n", + ctime(&now)); + fprintf(out_h, "/*\n" + " * Automatically generated C config: don't edit\n" + " * %s" + " */\n" + "\n#ifndef __AUTOCONF_DONT_USE_AUTOCONF\n" + "\n#ifndef AUTOCONF_INCLUDED\n" + "#define AUTOCONF_INCLUDED\n\n", + ctime(&now)); + + for_all_symbols(i, sym) { + sym_calc_value(sym); + if (!(sym->flags & SYMBOL_WRITE) || !sym->name) + continue; + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: + switch (sym_get_tristate_value(sym)) { + case no: + break; + case mod: + fprintf(out, "CONFIG_%s=m\n", sym->name); + fprintf(out_h, "#define CONFIG_%s_MODULE 1\n", sym->name); + break; + case yes: + fprintf(out, "CONFIG_%s=y\n", sym->name); + fprintf(out_h, "#define CONFIG_%s 1\n", sym->name); + break; + } + break; + case S_STRING: + str = sym_get_string_value(sym); + fprintf(out, "CONFIG_%s=", sym->name); + fprintf(out_h, "#define CONFIG_%s \"", sym->name); + while (1) { + l = strcspn(str, "\"\\"); + if (l) { + fwrite(str, l, 1, out); + fwrite(str, l, 1, out_h); + str += l; + } + if (!*str) + break; + fprintf(out, "\\%c", *str); + fprintf(out_h, "\\%c", *str); + str++; + } + fputs("\n", out); + fputs("\"\n", out_h); + break; + case S_HEX: + str = sym_get_string_value(sym); + if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) { + fprintf(out, "CONFIG_%s=%s\n", sym->name, str); + fprintf(out_h, "#define CONFIG_%s 0x%s\n", sym->name, str); + break; + } + case S_INT: + str = sym_get_string_value(sym); + fprintf(out, "CONFIG_%s=%s\n", sym->name, str); + fprintf(out_h, "#define CONFIG_%s %s\n", sym->name, str); + break; + default: + break; + } + } + fprintf(out_h, "\n#endif /* AUTOCONF_INCLUDED */\n\n"); + fprintf(out_h, "\n#endif /* __AUTOCONF_DONT_USE_AUTOCONF */\n\n"); + + fclose(out); + fclose(out_h); + + + name = getenv("WRSCONFIG_AUTOHEADER"); + if (!name) /* check old env name */ + name = getenv("VCONFIG_AUTOHEADER"); + +#ifdef VXWORKS + if (!name) + name = "h/config/autoconf.h"; +#else + if (!name) + name = "autoconf.h"; +#endif + if (loc_rename(".tmpconfig.h", name)) { + printf("# loc_rename(.tmpconfig.h, %s) failed\n", name); + return 1; + } + name = getenv("WRSCONFIG_AUTOCONFIG"); + if (!name) /* check old env name */ + name = getenv("VCONFIG_AUTOCONFIG"); +#ifdef VXWORKS + if (!name) + name = "h/config/auto.conf"; +#else + if (!name) + name = "auto.conf"; +#endif + /* + * This must be the last step, kbuild has a dependency on auto.conf + * and this marks the successful completion of the previous steps. + */ + if (loc_rename(".tmpconfig", name)) { + printf("# loc_rename(.tmpconfig, %s) failed\n", name); + return 1; + } + return 0; +} + +static int sym_change_count; +static void (*conf_changed_callback)(void); + +void sym_set_change_count(int count) +{ + int _sym_change_count = sym_change_count; + sym_change_count = count; + if (conf_changed_callback && + (bool)_sym_change_count != (bool)count) + conf_changed_callback(); +} + +void sym_add_change_count(int count) +{ + sym_set_change_count(count + sym_change_count); +} + +bool conf_get_changed(void) +{ + return sym_change_count; +} + +void conf_set_changed_callback(void (*fn)(void)) +{ + conf_changed_callback = fn; +} diff --git a/host/src/wrsconfig/expr.c b/host/src/wrsconfig/expr.c new file mode 100755 index 00000000000..6ef90c78d82 --- /dev/null +++ b/host/src/wrsconfig/expr.c @@ -0,0 +1,1100 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include + +#define LKC_DIRECT_LINK +#include "lkc.h" + +#define DEBUG_EXPR 0 + +struct expr *expr_alloc_symbol(struct symbol *sym) +{ + struct expr *e = malloc(sizeof(*e)); + memset(e, 0, sizeof(*e)); + e->type = E_SYMBOL; + e->left.sym = sym; + return e; +} + +struct expr *expr_alloc_one(enum expr_type type, struct expr *ce) +{ + struct expr *e = malloc(sizeof(*e)); + memset(e, 0, sizeof(*e)); + e->type = type; + e->left.expr = ce; + return e; +} + +struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e2) +{ + struct expr *e = malloc(sizeof(*e)); + memset(e, 0, sizeof(*e)); + e->type = type; + e->left.expr = e1; + e->right.expr = e2; + return e; +} + +struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2) +{ + struct expr *e = malloc(sizeof(*e)); + memset(e, 0, sizeof(*e)); + e->type = type; + e->left.sym = s1; + e->right.sym = s2; + return e; +} + +struct expr *expr_alloc_and(struct expr *e1, struct expr *e2) +{ + if (!e1) + return e2; + return e2 ? expr_alloc_two(E_AND, e1, e2) : e1; +} + +struct expr *expr_alloc_or(struct expr *e1, struct expr *e2) +{ + if (!e1) + return e2; + return e2 ? expr_alloc_two(E_OR, e1, e2) : e1; +} + +struct expr *expr_copy(struct expr *org) +{ + struct expr *e; + + if (!org) + return NULL; + + e = malloc(sizeof(*org)); + memcpy(e, org, sizeof(*org)); + switch (org->type) { + case E_SYMBOL: + e->left = org->left; + break; + case E_NOT: + e->left.expr = expr_copy(org->left.expr); + break; + case E_EQUAL: + case E_UNEQUAL: + e->left.sym = org->left.sym; + e->right.sym = org->right.sym; + break; + case E_AND: + case E_OR: + case E_CHOICE: + e->left.expr = expr_copy(org->left.expr); + e->right.expr = expr_copy(org->right.expr); + break; + default: + printf("can't copy type %d\n", e->type); + free(e); + e = NULL; + break; + } + + return e; +} + +void expr_free(struct expr *e) +{ + if (!e) + return; + + switch (e->type) { + case E_SYMBOL: + break; + case E_NOT: + expr_free(e->left.expr); + return; + case E_EQUAL: + case E_UNEQUAL: + break; + case E_OR: + case E_AND: + expr_free(e->left.expr); + expr_free(e->right.expr); + break; + default: + printf("how to free type %d?\n", e->type); + break; + } + free(e); +} + +static int trans_count; + +#define e1 (*ep1) +#define e2 (*ep2) + +static void __expr_eliminate_eq(enum expr_type type, struct expr **ep1, struct expr **ep2) +{ + if (e1->type == type) { + __expr_eliminate_eq(type, &e1->left.expr, &e2); + __expr_eliminate_eq(type, &e1->right.expr, &e2); + return; + } + if (e2->type == type) { + __expr_eliminate_eq(type, &e1, &e2->left.expr); + __expr_eliminate_eq(type, &e1, &e2->right.expr); + return; + } + if (e1->type == E_SYMBOL && e2->type == E_SYMBOL && + e1->left.sym == e2->left.sym && + (e1->left.sym == &symbol_yes || e1->left.sym == &symbol_no)) + return; + if (!expr_eq(e1, e2)) + return; + trans_count++; + expr_free(e1); expr_free(e2); + switch (type) { + case E_OR: + e1 = expr_alloc_symbol(&symbol_no); + e2 = expr_alloc_symbol(&symbol_no); + break; + case E_AND: + e1 = expr_alloc_symbol(&symbol_yes); + e2 = expr_alloc_symbol(&symbol_yes); + break; + default: + ; + } +} + +void expr_eliminate_eq(struct expr **ep1, struct expr **ep2) +{ + if (!e1 || !e2) + return; + switch (e1->type) { + case E_OR: + case E_AND: + __expr_eliminate_eq(e1->type, ep1, ep2); + default: + ; + } + if (e1->type != e2->type) switch (e2->type) { + case E_OR: + case E_AND: + __expr_eliminate_eq(e2->type, ep1, ep2); + default: + ; + } + e1 = expr_eliminate_yn(e1); + e2 = expr_eliminate_yn(e2); +} + +#undef e1 +#undef e2 + +int expr_eq(struct expr *e1, struct expr *e2) +{ + int res, old_count; + + if (e1->type != e2->type) + return 0; + switch (e1->type) { + case E_EQUAL: + case E_UNEQUAL: + return e1->left.sym == e2->left.sym && e1->right.sym == e2->right.sym; + case E_SYMBOL: + return e1->left.sym == e2->left.sym; + case E_NOT: + return expr_eq(e1->left.expr, e2->left.expr); + case E_AND: + case E_OR: + e1 = expr_copy(e1); + e2 = expr_copy(e2); + old_count = trans_count; + expr_eliminate_eq(&e1, &e2); + res = (e1->type == E_SYMBOL && e2->type == E_SYMBOL && + e1->left.sym == e2->left.sym); + expr_free(e1); + expr_free(e2); + trans_count = old_count; + return res; + case E_CHOICE: + case E_RANGE: + case E_NONE: + /* panic */; + } + + if (DEBUG_EXPR) { + expr_fprint(e1, stdout); + printf(" = "); + expr_fprint(e2, stdout); + printf(" ?\n"); + } + + return 0; +} + +struct expr *expr_eliminate_yn(struct expr *e) +{ + struct expr *tmp; + + if (e) switch (e->type) { + case E_AND: + e->left.expr = expr_eliminate_yn(e->left.expr); + e->right.expr = expr_eliminate_yn(e->right.expr); + if (e->left.expr->type == E_SYMBOL) { + if (e->left.expr->left.sym == &symbol_no) { + expr_free(e->left.expr); + expr_free(e->right.expr); + e->type = E_SYMBOL; + e->left.sym = &symbol_no; + e->right.expr = NULL; + return e; + } else if (e->left.expr->left.sym == &symbol_yes) { + free(e->left.expr); + tmp = e->right.expr; + *e = *(e->right.expr); + free(tmp); + return e; + } + } + if (e->right.expr->type == E_SYMBOL) { + if (e->right.expr->left.sym == &symbol_no) { + expr_free(e->left.expr); + expr_free(e->right.expr); + e->type = E_SYMBOL; + e->left.sym = &symbol_no; + e->right.expr = NULL; + return e; + } else if (e->right.expr->left.sym == &symbol_yes) { + free(e->right.expr); + tmp = e->left.expr; + *e = *(e->left.expr); + free(tmp); + return e; + } + } + break; + case E_OR: + e->left.expr = expr_eliminate_yn(e->left.expr); + e->right.expr = expr_eliminate_yn(e->right.expr); + if (e->left.expr->type == E_SYMBOL) { + if (e->left.expr->left.sym == &symbol_no) { + free(e->left.expr); + tmp = e->right.expr; + *e = *(e->right.expr); + free(tmp); + return e; + } else if (e->left.expr->left.sym == &symbol_yes) { + expr_free(e->left.expr); + expr_free(e->right.expr); + e->type = E_SYMBOL; + e->left.sym = &symbol_yes; + e->right.expr = NULL; + return e; + } + } + if (e->right.expr->type == E_SYMBOL) { + if (e->right.expr->left.sym == &symbol_no) { + free(e->right.expr); + tmp = e->left.expr; + *e = *(e->left.expr); + free(tmp); + return e; + } else if (e->right.expr->left.sym == &symbol_yes) { + expr_free(e->left.expr); + expr_free(e->right.expr); + e->type = E_SYMBOL; + e->left.sym = &symbol_yes; + e->right.expr = NULL; + return e; + } + } + break; + default: + ; + } + return e; +} + +/* + * bool FOO!=n => FOO + */ +struct expr *expr_trans_bool(struct expr *e) +{ + if (!e) + return NULL; + switch (e->type) { + case E_AND: + case E_OR: + case E_NOT: + e->left.expr = expr_trans_bool(e->left.expr); + e->right.expr = expr_trans_bool(e->right.expr); + break; + case E_UNEQUAL: + // FOO!=n -> FOO + if (e->left.sym->type == S_TRISTATE) { + if (e->right.sym == &symbol_no) { + e->type = E_SYMBOL; + e->right.sym = NULL; + } + } + break; + default: + ; + } + return e; +} + +/* + * e1 || e2 -> ? + */ +struct expr *expr_join_or(struct expr *e1, struct expr *e2) +{ + struct expr *tmp; + struct symbol *sym1, *sym2; + + if (expr_eq(e1, e2)) + return expr_copy(e1); + if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT) + return NULL; + if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT) + return NULL; + if (e1->type == E_NOT) { + tmp = e1->left.expr; + if (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL) + return NULL; + sym1 = tmp->left.sym; + } else + sym1 = e1->left.sym; + if (e2->type == E_NOT) { + if (e2->left.expr->type != E_SYMBOL) + return NULL; + sym2 = e2->left.expr->left.sym; + } else + sym2 = e2->left.sym; + if (sym1 != sym2) + return NULL; + if (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE) + return NULL; + if (sym1->type == S_TRISTATE) { + if (e1->type == E_EQUAL && e2->type == E_EQUAL && + ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) || + (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes))) { + // (a='y') || (a='m') -> (a!='n') + return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_no); + } + if (e1->type == E_EQUAL && e2->type == E_EQUAL && + ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) || + (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes))) { + // (a='y') || (a='n') -> (a!='m') + return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_mod); + } + if (e1->type == E_EQUAL && e2->type == E_EQUAL && + ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) || + (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod))) { + // (a='m') || (a='n') -> (a!='y') + return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_yes); + } + } + if (sym1->type == S_BOOLEAN && sym1 == sym2) { + if ((e1->type == E_NOT && e1->left.expr->type == E_SYMBOL && e2->type == E_SYMBOL) || + (e2->type == E_NOT && e2->left.expr->type == E_SYMBOL && e1->type == E_SYMBOL)) + return expr_alloc_symbol(&symbol_yes); + } + + if (DEBUG_EXPR) { + printf("optimize ("); + expr_fprint(e1, stdout); + printf(") || ("); + expr_fprint(e2, stdout); + printf(")?\n"); + } + return NULL; +} + +struct expr *expr_join_and(struct expr *e1, struct expr *e2) +{ + struct expr *tmp; + struct symbol *sym1, *sym2; + + if (expr_eq(e1, e2)) + return expr_copy(e1); + if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT) + return NULL; + if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT) + return NULL; + if (e1->type == E_NOT) { + tmp = e1->left.expr; + if (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL) + return NULL; + sym1 = tmp->left.sym; + } else + sym1 = e1->left.sym; + if (e2->type == E_NOT) { + if (e2->left.expr->type != E_SYMBOL) + return NULL; + sym2 = e2->left.expr->left.sym; + } else + sym2 = e2->left.sym; + if (sym1 != sym2) + return NULL; + if (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE) + return NULL; + + if ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_yes) || + (e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_yes)) + // (a) && (a='y') -> (a='y') + return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes); + + if ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_no) || + (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_no)) + // (a) && (a!='n') -> (a) + return expr_alloc_symbol(sym1); + + if ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_mod) || + (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_mod)) + // (a) && (a!='m') -> (a='y') + return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes); + + if (sym1->type == S_TRISTATE) { + if (e1->type == E_EQUAL && e2->type == E_UNEQUAL) { + // (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b' + sym2 = e1->right.sym; + if ((e2->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST)) + return sym2 != e2->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2) + : expr_alloc_symbol(&symbol_no); + } + if (e1->type == E_UNEQUAL && e2->type == E_EQUAL) { + // (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b' + sym2 = e2->right.sym; + if ((e1->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST)) + return sym2 != e1->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2) + : expr_alloc_symbol(&symbol_no); + } + if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL && + ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) || + (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes))) + // (a!='y') && (a!='n') -> (a='m') + return expr_alloc_comp(E_EQUAL, sym1, &symbol_mod); + + if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL && + ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) || + (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes))) + // (a!='y') && (a!='m') -> (a='n') + return expr_alloc_comp(E_EQUAL, sym1, &symbol_no); + + if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL && + ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) || + (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod))) + // (a!='m') && (a!='n') -> (a='m') + return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes); + + if ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_mod) || + (e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_mod) || + (e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_yes) || + (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_yes)) + return NULL; + } + + if (DEBUG_EXPR) { + printf("optimize ("); + expr_fprint(e1, stdout); + printf(") && ("); + expr_fprint(e2, stdout); + printf(")?\n"); + } + return NULL; +} + +static void expr_eliminate_dups1(enum expr_type type, struct expr **ep1, struct expr **ep2) +{ +#define e1 (*ep1) +#define e2 (*ep2) + struct expr *tmp; + + if (e1->type == type) { + expr_eliminate_dups1(type, &e1->left.expr, &e2); + expr_eliminate_dups1(type, &e1->right.expr, &e2); + return; + } + if (e2->type == type) { + expr_eliminate_dups1(type, &e1, &e2->left.expr); + expr_eliminate_dups1(type, &e1, &e2->right.expr); + return; + } + if (e1 == e2) + return; + + switch (e1->type) { + case E_OR: case E_AND: + expr_eliminate_dups1(e1->type, &e1, &e1); + default: + ; + } + + switch (type) { + case E_OR: + tmp = expr_join_or(e1, e2); + if (tmp) { + expr_free(e1); expr_free(e2); + e1 = expr_alloc_symbol(&symbol_no); + e2 = tmp; + trans_count++; + } + break; + case E_AND: + tmp = expr_join_and(e1, e2); + if (tmp) { + expr_free(e1); expr_free(e2); + e1 = expr_alloc_symbol(&symbol_yes); + e2 = tmp; + trans_count++; + } + break; + default: + ; + } +#undef e1 +#undef e2 +} + +static void expr_eliminate_dups2(enum expr_type type, struct expr **ep1, struct expr **ep2) +{ +#define e1 (*ep1) +#define e2 (*ep2) + struct expr *tmp, *tmp1, *tmp2; + + if (e1->type == type) { + expr_eliminate_dups2(type, &e1->left.expr, &e2); + expr_eliminate_dups2(type, &e1->right.expr, &e2); + return; + } + if (e2->type == type) { + expr_eliminate_dups2(type, &e1, &e2->left.expr); + expr_eliminate_dups2(type, &e1, &e2->right.expr); + } + if (e1 == e2) + return; + + switch (e1->type) { + case E_OR: + expr_eliminate_dups2(e1->type, &e1, &e1); + // (FOO || BAR) && (!FOO && !BAR) -> n + tmp1 = expr_transform(expr_alloc_one(E_NOT, expr_copy(e1))); + tmp2 = expr_copy(e2); + tmp = expr_extract_eq_and(&tmp1, &tmp2); + if (expr_is_yes(tmp1)) { + expr_free(e1); + e1 = expr_alloc_symbol(&symbol_no); + trans_count++; + } + expr_free(tmp2); + expr_free(tmp1); + expr_free(tmp); + break; + case E_AND: + expr_eliminate_dups2(e1->type, &e1, &e1); + // (FOO && BAR) || (!FOO || !BAR) -> y + tmp1 = expr_transform(expr_alloc_one(E_NOT, expr_copy(e1))); + tmp2 = expr_copy(e2); + tmp = expr_extract_eq_or(&tmp1, &tmp2); + if (expr_is_no(tmp1)) { + expr_free(e1); + e1 = expr_alloc_symbol(&symbol_yes); + trans_count++; + } + expr_free(tmp2); + expr_free(tmp1); + expr_free(tmp); + break; + default: + ; + } +#undef e1 +#undef e2 +} + +struct expr *expr_eliminate_dups(struct expr *e) +{ + int oldcount; + if (!e) + return e; + + oldcount = trans_count; + while (1) { + trans_count = 0; + switch (e->type) { + case E_OR: case E_AND: + expr_eliminate_dups1(e->type, &e, &e); + expr_eliminate_dups2(e->type, &e, &e); + default: + ; + } + if (!trans_count) + break; + e = expr_eliminate_yn(e); + } + trans_count = oldcount; + return e; +} + +struct expr *expr_transform(struct expr *e) +{ + struct expr *tmp; + + if (!e) + return NULL; + switch (e->type) { + case E_EQUAL: + case E_UNEQUAL: + case E_SYMBOL: + case E_CHOICE: + break; + default: + e->left.expr = expr_transform(e->left.expr); + e->right.expr = expr_transform(e->right.expr); + } + + switch (e->type) { + case E_EQUAL: + if (e->left.sym->type != S_BOOLEAN) + break; + if (e->right.sym == &symbol_no) { + e->type = E_NOT; + e->left.expr = expr_alloc_symbol(e->left.sym); + e->right.sym = NULL; + break; + } + if (e->right.sym == &symbol_mod) { + printf("boolean symbol %s tested for 'm'? test forced to 'n'\n", e->left.sym->name); + e->type = E_SYMBOL; + e->left.sym = &symbol_no; + e->right.sym = NULL; + break; + } + if (e->right.sym == &symbol_yes) { + e->type = E_SYMBOL; + e->right.sym = NULL; + break; + } + break; + case E_UNEQUAL: + if (e->left.sym->type != S_BOOLEAN) + break; + if (e->right.sym == &symbol_no) { + e->type = E_SYMBOL; + e->right.sym = NULL; + break; + } + if (e->right.sym == &symbol_mod) { + printf("boolean symbol %s tested for 'm'? test forced to 'y'\n", e->left.sym->name); + e->type = E_SYMBOL; + e->left.sym = &symbol_yes; + e->right.sym = NULL; + break; + } + if (e->right.sym == &symbol_yes) { + e->type = E_NOT; + e->left.expr = expr_alloc_symbol(e->left.sym); + e->right.sym = NULL; + break; + } + break; + case E_NOT: + switch (e->left.expr->type) { + case E_NOT: + // !!a -> a + tmp = e->left.expr->left.expr; + free(e->left.expr); + free(e); + e = tmp; + e = expr_transform(e); + break; + case E_EQUAL: + case E_UNEQUAL: + // !a='x' -> a!='x' + tmp = e->left.expr; + free(e); + e = tmp; + e->type = e->type == E_EQUAL ? E_UNEQUAL : E_EQUAL; + break; + case E_OR: + // !(a || b) -> !a && !b + tmp = e->left.expr; + e->type = E_AND; + e->right.expr = expr_alloc_one(E_NOT, tmp->right.expr); + tmp->type = E_NOT; + tmp->right.expr = NULL; + e = expr_transform(e); + break; + case E_AND: + // !(a && b) -> !a || !b + tmp = e->left.expr; + e->type = E_OR; + e->right.expr = expr_alloc_one(E_NOT, tmp->right.expr); + tmp->type = E_NOT; + tmp->right.expr = NULL; + e = expr_transform(e); + break; + case E_SYMBOL: + if (e->left.expr->left.sym == &symbol_yes) { + // !'y' -> 'n' + tmp = e->left.expr; + free(e); + e = tmp; + e->type = E_SYMBOL; + e->left.sym = &symbol_no; + break; + } + if (e->left.expr->left.sym == &symbol_mod) { + // !'m' -> 'm' + tmp = e->left.expr; + free(e); + e = tmp; + e->type = E_SYMBOL; + e->left.sym = &symbol_mod; + break; + } + if (e->left.expr->left.sym == &symbol_no) { + // !'n' -> 'y' + tmp = e->left.expr; + free(e); + e = tmp; + e->type = E_SYMBOL; + e->left.sym = &symbol_yes; + break; + } + break; + default: + ; + } + break; + default: + ; + } + return e; +} + +int expr_contains_symbol(struct expr *dep, struct symbol *sym) +{ + if (!dep) + return 0; + + switch (dep->type) { + case E_AND: + case E_OR: + return expr_contains_symbol(dep->left.expr, sym) || + expr_contains_symbol(dep->right.expr, sym); + case E_SYMBOL: + return dep->left.sym == sym; + case E_EQUAL: + case E_UNEQUAL: + return dep->left.sym == sym || + dep->right.sym == sym; + case E_NOT: + return expr_contains_symbol(dep->left.expr, sym); + default: + ; + } + return 0; +} + +bool expr_depends_symbol(struct expr *dep, struct symbol *sym) +{ + if (!dep) + return false; + + switch (dep->type) { + case E_AND: + return expr_depends_symbol(dep->left.expr, sym) || + expr_depends_symbol(dep->right.expr, sym); + case E_SYMBOL: + return dep->left.sym == sym; + case E_EQUAL: + if (dep->left.sym == sym) { + if (dep->right.sym == &symbol_yes || dep->right.sym == &symbol_mod) + return true; + } + break; + case E_UNEQUAL: + if (dep->left.sym == sym) { + if (dep->right.sym == &symbol_no) + return true; + } + break; + default: + ; + } + return false; +} + +struct expr *expr_extract_eq_and(struct expr **ep1, struct expr **ep2) +{ + struct expr *tmp = NULL; + expr_extract_eq(E_AND, &tmp, ep1, ep2); + if (tmp) { + *ep1 = expr_eliminate_yn(*ep1); + *ep2 = expr_eliminate_yn(*ep2); + } + return tmp; +} + +struct expr *expr_extract_eq_or(struct expr **ep1, struct expr **ep2) +{ + struct expr *tmp = NULL; + expr_extract_eq(E_OR, &tmp, ep1, ep2); + if (tmp) { + *ep1 = expr_eliminate_yn(*ep1); + *ep2 = expr_eliminate_yn(*ep2); + } + return tmp; +} + +void expr_extract_eq(enum expr_type type, struct expr **ep, struct expr **ep1, struct expr **ep2) +{ +#define e1 (*ep1) +#define e2 (*ep2) + if (e1->type == type) { + expr_extract_eq(type, ep, &e1->left.expr, &e2); + expr_extract_eq(type, ep, &e1->right.expr, &e2); + return; + } + if (e2->type == type) { + expr_extract_eq(type, ep, ep1, &e2->left.expr); + expr_extract_eq(type, ep, ep1, &e2->right.expr); + return; + } + if (expr_eq(e1, e2)) { + *ep = *ep ? expr_alloc_two(type, *ep, e1) : e1; + expr_free(e2); + if (type == E_AND) { + e1 = expr_alloc_symbol(&symbol_yes); + e2 = expr_alloc_symbol(&symbol_yes); + } else if (type == E_OR) { + e1 = expr_alloc_symbol(&symbol_no); + e2 = expr_alloc_symbol(&symbol_no); + } + } +#undef e1 +#undef e2 +} + +struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym) +{ + struct expr *e1, *e2; + + if (!e) { + e = expr_alloc_symbol(sym); + if (type == E_UNEQUAL) + e = expr_alloc_one(E_NOT, e); + return e; + } + switch (e->type) { + case E_AND: + e1 = expr_trans_compare(e->left.expr, E_EQUAL, sym); + e2 = expr_trans_compare(e->right.expr, E_EQUAL, sym); + if (sym == &symbol_yes) + e = expr_alloc_two(E_AND, e1, e2); + if (sym == &symbol_no) + e = expr_alloc_two(E_OR, e1, e2); + if (type == E_UNEQUAL) + e = expr_alloc_one(E_NOT, e); + return e; + case E_OR: + e1 = expr_trans_compare(e->left.expr, E_EQUAL, sym); + e2 = expr_trans_compare(e->right.expr, E_EQUAL, sym); + if (sym == &symbol_yes) + e = expr_alloc_two(E_OR, e1, e2); + if (sym == &symbol_no) + e = expr_alloc_two(E_AND, e1, e2); + if (type == E_UNEQUAL) + e = expr_alloc_one(E_NOT, e); + return e; + case E_NOT: + return expr_trans_compare(e->left.expr, type == E_EQUAL ? E_UNEQUAL : E_EQUAL, sym); + case E_UNEQUAL: + case E_EQUAL: + if (type == E_EQUAL) { + if (sym == &symbol_yes) + return expr_copy(e); + if (sym == &symbol_mod) + return expr_alloc_symbol(&symbol_no); + if (sym == &symbol_no) + return expr_alloc_one(E_NOT, expr_copy(e)); + } else { + if (sym == &symbol_yes) + return expr_alloc_one(E_NOT, expr_copy(e)); + if (sym == &symbol_mod) + return expr_alloc_symbol(&symbol_yes); + if (sym == &symbol_no) + return expr_copy(e); + } + break; + case E_SYMBOL: + return expr_alloc_comp(type, e->left.sym, sym); + case E_CHOICE: + case E_RANGE: + case E_NONE: + /* panic */; + } + return NULL; +} + +tristate expr_calc_value(struct expr *e) +{ + tristate val1, val2; + const char *str1, *str2; + + if (!e) + return yes; + + switch (e->type) { + case E_SYMBOL: + sym_calc_value(e->left.sym); + return e->left.sym->curr.tri; + case E_AND: + val1 = expr_calc_value(e->left.expr); + val2 = expr_calc_value(e->right.expr); + return E_AND(val1, val2); + case E_OR: + val1 = expr_calc_value(e->left.expr); + val2 = expr_calc_value(e->right.expr); + return E_OR(val1, val2); + case E_NOT: + val1 = expr_calc_value(e->left.expr); + return E_NOT(val1); + case E_EQUAL: + sym_calc_value(e->left.sym); + sym_calc_value(e->right.sym); + str1 = sym_get_string_value(e->left.sym); + str2 = sym_get_string_value(e->right.sym); + return !strcmp(str1, str2) ? yes : no; + case E_UNEQUAL: + sym_calc_value(e->left.sym); + sym_calc_value(e->right.sym); + str1 = sym_get_string_value(e->left.sym); + str2 = sym_get_string_value(e->right.sym); + return !strcmp(str1, str2) ? no : yes; + default: + printf("expr_calc_value: %d?\n", e->type); + return no; + } +} + +int expr_compare_type(enum expr_type t1, enum expr_type t2) +{ +#if 0 + return 1; +#else + if (t1 == t2) + return 0; + switch (t1) { + case E_EQUAL: + case E_UNEQUAL: + if (t2 == E_NOT) + return 1; + case E_NOT: + if (t2 == E_AND) + return 1; + case E_AND: + if (t2 == E_OR) + return 1; + case E_OR: + if (t2 == E_CHOICE) + return 1; + case E_CHOICE: + if (t2 == 0) + return 1; + default: + return -1; + } + printf("[%dgt%d?]", t1, t2); + return 0; +#endif +} + +void expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken) +{ + if (!e) { + fn(data, NULL, "y"); + return; + } + + if (expr_compare_type(prevtoken, e->type) > 0) + fn(data, NULL, "("); + switch (e->type) { + case E_SYMBOL: + if (e->left.sym->name) + fn(data, e->left.sym, e->left.sym->name); + else + fn(data, NULL, ""); + break; + case E_NOT: + fn(data, NULL, "!"); + expr_print(e->left.expr, fn, data, E_NOT); + break; + case E_EQUAL: + fn(data, e->left.sym, e->left.sym->name); + fn(data, NULL, "="); + fn(data, e->right.sym, e->right.sym->name); + break; + case E_UNEQUAL: + fn(data, e->left.sym, e->left.sym->name); + fn(data, NULL, "!="); + fn(data, e->right.sym, e->right.sym->name); + break; + case E_OR: + expr_print(e->left.expr, fn, data, E_OR); + fn(data, NULL, " || "); + expr_print(e->right.expr, fn, data, E_OR); + break; + case E_AND: + expr_print(e->left.expr, fn, data, E_AND); + fn(data, NULL, " && "); + expr_print(e->right.expr, fn, data, E_AND); + break; + case E_CHOICE: + fn(data, e->right.sym, e->right.sym->name); + if (e->left.expr) { + fn(data, NULL, " ^ "); + expr_print(e->left.expr, fn, data, E_CHOICE); + } + break; + case E_RANGE: + fn(data, NULL, "["); + fn(data, e->left.sym, e->left.sym->name); + fn(data, NULL, " "); + fn(data, e->right.sym, e->right.sym->name); + fn(data, NULL, "]"); + break; + default: + { + char buf[32]; + sprintf(buf, "", e->type); + fn(data, NULL, buf); + break; + } + } + if (expr_compare_type(prevtoken, e->type) > 0) + fn(data, NULL, ")"); +} + +static void expr_print_file_helper(void *data, struct symbol *sym, const char *str) +{ + fwrite(str, strlen(str), 1, data); +} + +void expr_fprint(struct expr *e, FILE *out) +{ + expr_print(e, expr_print_file_helper, out, E_NONE); +} + +static void expr_print_gstr_helper(void *data, struct symbol *sym, const char *str) +{ + str_append((struct gstr*)data, str); +} + +void expr_gstr_print(struct expr *e, struct gstr *gs) +{ + expr_print(e, expr_print_gstr_helper, gs, E_NONE); +} diff --git a/host/src/wrsconfig/expr.h b/host/src/wrsconfig/expr.h new file mode 100755 index 00000000000..a195986eec6 --- /dev/null +++ b/host/src/wrsconfig/expr.h @@ -0,0 +1,200 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#ifndef EXPR_H +#define EXPR_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#ifndef __cplusplus +#include +#endif + +struct file { + struct file *next; + struct file *parent; + char *name; + int lineno; + int flags; +}; + +#define FILE_BUSY 0x0001 +#define FILE_SCANNED 0x0002 +#define FILE_PRINTED 0x0004 + +typedef enum tristate { + no, mod, yes +} tristate; + +enum expr_type { + E_NONE, E_OR, E_AND, E_NOT, E_EQUAL, E_UNEQUAL, E_CHOICE, E_SYMBOL, E_RANGE +}; + +union expr_data { + struct expr *expr; + struct symbol *sym; +}; + +struct expr { + enum expr_type type; + union expr_data left, right; +}; + +#define E_OR(dep1, dep2) (((dep1)>(dep2))?(dep1):(dep2)) +#define E_AND(dep1, dep2) (((dep1)<(dep2))?(dep1):(dep2)) +#define E_NOT(dep) (2-(dep)) + +struct expr_value { + struct expr *expr; + tristate tri; +}; + +struct symbol_value { + void *val; + tristate tri; +}; + +enum symbol_type { + S_UNKNOWN, S_BOOLEAN, S_TRISTATE, S_INT, S_HEX, S_STRING, S_OTHER +}; + +enum { + S_DEF_USER, /* main user value */ + S_DEF_AUTO, +}; + +struct symbol { + struct symbol *next; + char *name; + enum symbol_type type; + struct symbol_value curr; + struct symbol_value def[4]; + tristate visible; + int flags; + struct property *prop; + struct expr_value rev_dep; +}; + +#define for_all_symbols(i, sym) for (i = 0; i < 257; i++) for (sym = symbol_hash[i]; sym; sym = sym->next) if (sym->type != S_OTHER) + +#define SYMBOL_CONST 0x0001 +#define SYMBOL_CHECK 0x0008 +#define SYMBOL_CHOICE 0x0010 +#define SYMBOL_CHOICEVAL 0x0020 +#define SYMBOL_PRINTED 0x0040 +#define SYMBOL_VALID 0x0080 +#define SYMBOL_OPTIONAL 0x0100 +#define SYMBOL_WRITE 0x0200 +#define SYMBOL_CHANGED 0x0400 +#define SYMBOL_AUTO 0x1000 +#define SYMBOL_CHECKED 0x2000 +#define SYMBOL_WARNED 0x8000 +#define SYMBOL_DEF 0x10000 +#define SYMBOL_DEF_USER 0x10000 +#define SYMBOL_DEF_AUTO 0x20000 +#define SYMBOL_DEF3 0x40000 +#define SYMBOL_DEF4 0x80000 + +#define SYMBOL_MAXLENGTH 256 +#define SYMBOL_HASHSIZE 257 +#define SYMBOL_HASHMASK 0xff + +enum prop_type { + P_UNKNOWN, P_PROMPT, P_COMMENT, P_MENU, P_DEFAULT, P_CHOICE, P_SELECT, P_RANGE +}; + +struct property { + struct property *next; + struct symbol *sym; + enum prop_type type; + const char *text; + struct expr_value visible; + struct expr *expr; + struct menu *menu; + struct file *file; + int lineno; +}; + +#define for_all_properties(sym, st, tok) \ + for (st = sym->prop; st; st = st->next) \ + if (st->type == (tok)) +#define for_all_defaults(sym, st) for_all_properties(sym, st, P_DEFAULT) +#define for_all_choices(sym, st) for_all_properties(sym, st, P_CHOICE) +#define for_all_prompts(sym, st) \ + for (st = sym->prop; st; st = st->next) \ + if (st->text) + +struct menu { + struct menu *next; + struct menu *parent; + struct menu *list; + struct symbol *sym; + struct property *prompt; + struct expr *dep; + unsigned int flags; + char *help; + struct file *file; + int lineno; + void *data; +}; + +#define MENU_CHANGED 0x0001 +#define MENU_ROOT 0x0002 + +#ifndef SWIG + +extern struct file *file_list; +extern struct file *current_file; +struct file *lookup_file(const char *name); + +extern struct symbol symbol_yes, symbol_no, symbol_mod; +extern struct symbol *modules_sym; +extern struct symbol *sym_defconfig_list; +extern int cdebug; +struct expr *expr_alloc_symbol(struct symbol *sym); +struct expr *expr_alloc_one(enum expr_type type, struct expr *ce); +struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e2); +struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2); +struct expr *expr_alloc_and(struct expr *e1, struct expr *e2); +struct expr *expr_alloc_or(struct expr *e1, struct expr *e2); +struct expr *expr_copy(struct expr *org); +void expr_free(struct expr *e); +int expr_eq(struct expr *e1, struct expr *e2); +void expr_eliminate_eq(struct expr **ep1, struct expr **ep2); +tristate expr_calc_value(struct expr *e); +struct expr *expr_eliminate_yn(struct expr *e); +struct expr *expr_trans_bool(struct expr *e); +struct expr *expr_eliminate_dups(struct expr *e); +struct expr *expr_transform(struct expr *e); +int expr_contains_symbol(struct expr *dep, struct symbol *sym); +bool expr_depends_symbol(struct expr *dep, struct symbol *sym); +struct expr *expr_extract_eq_and(struct expr **ep1, struct expr **ep2); +struct expr *expr_extract_eq_or(struct expr **ep1, struct expr **ep2); +void expr_extract_eq(enum expr_type type, struct expr **ep, struct expr **ep1, struct expr **ep2); +struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym); + +void expr_fprint(struct expr *e, FILE *out); +struct gstr; /* forward */ +void expr_gstr_print(struct expr *e, struct gstr *gs); + +static inline int expr_is_yes(struct expr *e) +{ + return !e || (e->type == E_SYMBOL && e->left.sym == &symbol_yes); +} + +static inline int expr_is_no(struct expr *e) +{ + return e && (e->type == E_SYMBOL && e->left.sym == &symbol_no); +} +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* EXPR_H */ diff --git a/host/src/wrsconfig/fixdep.c b/host/src/wrsconfig/fixdep.c new file mode 100755 index 00000000000..18bf1b3d536 --- /dev/null +++ b/host/src/wrsconfig/fixdep.c @@ -0,0 +1,399 @@ +/* + * "Optimize" a list of dependencies as spit out by gcc -MD + * for the kernel build + * =========================================================================== + * + * Author Kai Germaschewski + * Copyright 2002 by Kai Germaschewski + * + * This software may be used and distributed according to the terms + * of the GNU General Public License, incorporated herein by reference. + * + * + * Introduction: + * + * gcc produces a very nice and correct list of dependencies which + * tells make when to remake a file. + * + * To use this list as-is however has the drawback that virtually + * every file in the kernel includes which then again + * includes + * + * If the user re-runs make *config, linux/autoconf.h will be + * regenerated. make notices that and will rebuild every file which + * includes autoconf.h, i.e. basically all files. This is extremely + * annoying if the user just changed CONFIG_HIS_DRIVER from n to m. + * + * So we play the same trick that "mkdep" played before. We replace + * the dependency on linux/autoconf.h by a dependency on every config + * option which is mentioned in any of the listed prequisites. + * + * kconfig populates a tree in include/config/ with an empty file + * for each config symbol and when the configuration is updated + * the files representing changed config options are touched + * which then let make pick up the changes and the files that use + * the config symbols are rebuilt. + * + * So if the user changes his CONFIG_HIS_DRIVER option, only the objects + * which depend on "include/linux/config/his/driver.h" will be rebuilt, + * so most likely only his driver ;-) + * + * The idea above dates, by the way, back to Michael E Chastain, AFAIK. + * + * So to get dependencies right, there are two issues: + * o if any of the files the compiler read changed, we need to rebuild + * o if the command line given to the compile the file changed, we + * better rebuild as well. + * + * The former is handled by using the -MD output, the later by saving + * the command line used to compile the old object and comparing it + * to the one we would now use. + * + * Again, also this idea is pretty old and has been discussed on + * kbuild-devel a long time ago. I don't have a sensibly working + * internet connection right now, so I rather don't mention names + * without double checking. + * + * This code here has been based partially based on mkdep.c, which + * says the following about its history: + * + * Copyright abandoned, Michael Chastain, . + * This is a C version of syncdep.pl by Werner Almesberger. + * + * + * It is invoked as + * + * fixdep + * + * and will read the dependency file + * + * The transformed dependency snipped is written to stdout. + * + * It first generates a line + * + * cmd_ = + * + * and then basically copies the ..d file to stdout, in the + * process filtering out the dependency on linux/autoconf.h and adding + * dependencies on include/config/my/option.h for every + * CONFIG_MY_OPTION encountered in any of the prequisites. + * + * It will also filter out all the dependencies on *.ver. We need + * to make sure that the generated version checksum are globally up + * to date before even starting the recursive build, so it's too late + * at this point anyway. + * + * The algorithm to grep for "CONFIG_..." is bit unusual, but should + * be fast ;-) We don't even try to really parse the header files, but + * merely grep, i.e. if CONFIG_FOO is mentioned in a comment, it will + * be picked up as well. It's not a problem with respect to + * correctness, since that can only give too many dependencies, thus + * we cannot miss a rebuild. Since people tend to not mention totally + * unrelated CONFIG_ options all over the place, it's not an + * efficiency problem either. + * + * (Note: it'd be easy to port over the complete mkdep state machine, + * but I don't think the added complexity is worth it) + */ +/* + * Note 2: if somebody writes HELLO_CONFIG_BOOM in a file, it will depend onto + * CONFIG_BOOM. This could seem a bug (not too hard to fix), but please do not + * fix it! Some UserModeLinux files (look at arch/um/) call CONFIG_BOOM as + * UML_CONFIG_BOOM, to avoid conflicts with /usr/include/linux/autoconf.h, + * through arch/um/include/uml-config.h; this fixdep "bug" makes sure that + * those files will have correct dependencies. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define INT_CONF ntohl(0x434f4e46) +#define INT_ONFI ntohl(0x4f4e4649) +#define INT_NFIG ntohl(0x4e464947) +#define INT_FIG_ ntohl(0x4649475f) + +char *target; +char *depfile; +char *cmdline; + +void usage(void) + +{ + fprintf(stderr, "Usage: fixdep \n"); + exit(1); +} + +/* + * Print out the commandline prefixed with cmd_ := + */ +void print_cmdline(void) +{ + printf("cmd_%s := %s\n\n", target, cmdline); +} + +char * str_config = NULL; +int size_config = 0; +int len_config = 0; + +/* + * Grow the configuration string to a desired length. + * Usually the first growth is plenty. + */ +void grow_config(int len) +{ + while (len_config + len > size_config) { + if (size_config == 0) + size_config = 2048; + str_config = realloc(str_config, size_config *= 2); + if (str_config == NULL) + { perror("fixdep:malloc"); exit(1); } + } +} + + + +/* + * Lookup a value in the configuration string. + */ +int is_defined_config(const char * name, int len) +{ + const char * pconfig; + const char * plast = str_config + len_config - len; + for ( pconfig = str_config + 1; pconfig < plast; pconfig++ ) { + if (pconfig[ -1] == '\n' + && pconfig[len] == '\n' + && !memcmp(pconfig, name, len)) + return 1; + } + return 0; +} + +/* + * Add a new value to the configuration string. + */ +void define_config(const char * name, int len) +{ + grow_config(len + 1); + + memcpy(str_config+len_config, name, len); + len_config += len; + str_config[len_config++] = '\n'; +} + +/* + * Clear the set of configuration strings. + */ +void clear_config(void) +{ + len_config = 0; + define_config("", 0); +} + +/* + * Record the use of a CONFIG_* word. + */ +void use_config(char *m, int slen) +{ + char s[PATH_MAX]; + char *p; + + if (is_defined_config(m, slen)) + return; + + define_config(m, slen); + + memcpy(s, m, slen); s[slen] = 0; + + for (p = s; p < s + slen; p++) { + if (*p == '_') + *p = '/'; + else + *p = tolower((int)*p); + } + printf(" $(wildcard include/config/%s.h) \\\n", s); +} + +void parse_config_file(char *map, size_t len) +{ + int *end = (int *) (map + len); + /* start at +1, so that p can never be < map */ + int *m = (int *) map + 1; + char *p, *q; + + for (; m < end; m++) { + if (*m == INT_CONF) { p = (char *) m ; goto conf; } + if (*m == INT_ONFI) { p = (char *) m-1; goto conf; } + if (*m == INT_NFIG) { p = (char *) m-2; goto conf; } + if (*m == INT_FIG_) { p = (char *) m-3; goto conf; } + continue; +conf: + if (p > map + len - 7) + continue; + if (memcmp(p, "CONFIG_", 7)) + continue; + for (q = p + 7; q < map + len; q++) { + if (!(isalnum(*q) || *q == '_')) + goto found; + } + continue; + +found: + if (!memcmp(q - 7, "_MODULE", 7)) + q -= 7; + if( (q-p-7) < 0 ) + continue; + use_config(p+7, q-p-7); + } +} + +/* test is s ends in sub */ +int strrcmp(char *s, char *sub) +{ + int slen = strlen(s); + int sublen = strlen(sub); + + if (sublen > slen) + return 1; + + return memcmp(s + slen - sublen, sub, sublen); +} + +void do_config_file(char *filename) +{ + struct stat st; + int fd; + void *map; + + fd = open(filename, O_RDONLY); + if (fd < 0) { + fprintf(stderr, "fixdep: "); + perror(filename); + exit(2); + } + fstat(fd, &st); + if (st.st_size == 0) { + close(fd); + return; + } + map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if ((long) map == -1) { + perror("fixdep: mmap"); + close(fd); + return; + } + + parse_config_file(map, st.st_size); + + munmap(map, st.st_size); + + close(fd); +} + +void parse_dep_file(void *map, size_t len) +{ + char *m = map; + char *end = m + len; + char *p; + char s[PATH_MAX]; + + p = strchr(m, ':'); + if (!p) { + fprintf(stderr, "fixdep: parse error\n"); + exit(1); + } + memcpy(s, m, p-m); s[p-m] = 0; + printf("deps_%s := \\\n", target); + m = p+1; + + clear_config(); + + while (m < end) { + while (m < end && (*m == ' ' || *m == '\\' || *m == '\n')) + m++; + p = m; + while (p < end && *p != ' ') p++; + if (p == end) { + do p--; while (!isalnum(*p)); + p++; + } + memcpy(s, m, p-m); s[p-m] = 0; + if (strrcmp(s, "include/linux/autoconf.h") && + strrcmp(s, "arch/um/include/uml-config.h") && + strrcmp(s, ".ver")) { + printf(" %s \\\n", s); + do_config_file(s); + } + m = p + 1; + } + printf("\n%s: $(deps_%s)\n\n", target, target); + printf("$(deps_%s):\n", target); +} + +void print_deps(void) +{ + struct stat st; + int fd; + void *map; + + fd = open(depfile, O_RDONLY); + if (fd < 0) { + fprintf(stderr, "fixdep: "); + perror(depfile); + exit(2); + } + fstat(fd, &st); + if (st.st_size == 0) { + fprintf(stderr,"fixdep: %s is empty\n",depfile); + close(fd); + return; + } + map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if ((long) map == -1) { + perror("fixdep: mmap"); + close(fd); + return; + } + + parse_dep_file(map, st.st_size); + + munmap(map, st.st_size); + + close(fd); +} + +void traps(void) +{ + static char test[] __attribute__((aligned(sizeof(int)))) = "CONF"; + + if (*(int *)test != INT_CONF) { + fprintf(stderr, "fixdep: sizeof(int) != 4 or wrong endianess? %#x\n", + *(int *)test); + exit(2); + } +} + +int main(int argc, char *argv[]) +{ + traps(); + + if (argc != 4) + usage(); + + depfile = argv[1]; + target = argv[2]; + cmdline = argv[3]; + + print_cmdline(); + print_deps(); + + return 0; +} diff --git a/host/src/wrsconfig/lex.zconf.c b/host/src/wrsconfig/lex.zconf.c new file mode 100755 index 00000000000..0279162579c --- /dev/null +++ b/host/src/wrsconfig/lex.zconf.c @@ -0,0 +1,2266 @@ + +#line 3 "lex.zconf.c" + +#define YY_INT_ALIGNED short int + +/* A lexical scanner generated by flex */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 +#define YY_FLEX_SUBMINOR_VERSION 33 +#if YY_FLEX_SUBMINOR_VERSION > 0 +#define FLEX_BETA +#endif + +/* First, we deal with platform-specific or compiler-specific issues. */ + +/* begin standard C headers. */ +#include +#include +#include +#include + +/* end standard C headers. */ + +/* flex integer type definitions */ + +#ifndef FLEXINT_H +#define FLEXINT_H + +/* C99 systems have . Non-C99 systems may or may not. */ + +#if __STDC_VERSION__ >= 199901L + +/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, + * if you want the limit (max/min) macros for int types. + */ +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS 1 +#endif + +#include +typedef int8_t flex_int8_t; +typedef uint8_t flex_uint8_t; +typedef int16_t flex_int16_t; +typedef uint16_t flex_uint16_t; +typedef int32_t flex_int32_t; +typedef uint32_t flex_uint32_t; +#else +typedef signed char flex_int8_t; +typedef short int flex_int16_t; +typedef int flex_int32_t; +typedef unsigned char flex_uint8_t; +typedef unsigned short int flex_uint16_t; +typedef unsigned int flex_uint32_t; +#endif /* ! C99 */ + +/* Limits of integral types. */ +#ifndef INT8_MIN +#define INT8_MIN (-128) +#endif +#ifndef INT16_MIN +#define INT16_MIN (-32767-1) +#endif +#ifndef INT32_MIN +#define INT32_MIN (-2147483647-1) +#endif +#ifndef INT8_MAX +#define INT8_MAX (127) +#endif +#ifndef INT16_MAX +#define INT16_MAX (32767) +#endif +#ifndef INT32_MAX +#define INT32_MAX (2147483647) +#endif +#ifndef UINT8_MAX +#define UINT8_MAX (255U) +#endif +#ifndef UINT16_MAX +#define UINT16_MAX (65535U) +#endif +#ifndef UINT32_MAX +#define UINT32_MAX (4294967295U) +#endif + +#endif /* ! FLEXINT_H */ + +#ifdef __cplusplus + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +#if __STDC__ + +#define YY_USE_CONST + +#endif /* __STDC__ */ +#endif /* ! __cplusplus */ + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN (yy_start) = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START (((yy_start) - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE zconfrestart(zconfin ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#ifndef YY_BUF_SIZE +#define YY_BUF_SIZE 16384 +#endif + +/* The state buf must be large enough to hold one state per character in the main buffer. + */ +#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) + +#ifndef YY_TYPEDEF_YY_BUFFER_STATE +#define YY_TYPEDEF_YY_BUFFER_STATE +typedef struct yy_buffer_state *YY_BUFFER_STATE; +#endif + +extern int zconfleng; + +extern FILE *zconfin, *zconfout; + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + + #define YY_LESS_LINENO(n) + +/* Return all but the first "n" matched characters back to the input stream. */ +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up zconftext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + *yy_cp = (yy_hold_char); \ + YY_RESTORE_YY_MORE_OFFSET \ + (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up zconftext again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, (yytext_ptr) ) + +/* The following is because we cannot portably get our hands on size_t + * (without autoconf's help, which isn't available because we want + * flex-generated scanners to compile on their own). + */ + +#ifndef YY_TYPEDEF_YY_SIZE_T +#define YY_TYPEDEF_YY_SIZE_T +typedef unsigned int yy_size_t; +#endif + +#ifndef YY_STRUCT_YY_BUFFER_STATE +#define YY_STRUCT_YY_BUFFER_STATE +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + int yy_bs_lineno; /**< The line count. */ + int yy_bs_column; /**< The column count. */ + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; + +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via zconfrestart()), so that the user can continue scanning by + * just pointing zconfin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + + }; +#endif /* !YY_STRUCT_YY_BUFFER_STATE */ + +/* Stack of input buffers. */ +static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */ +static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */ +static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */ + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + * + * Returns the top of the stack, or NULL. + */ +#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \ + ? (yy_buffer_stack)[(yy_buffer_stack_top)] \ + : NULL) + +/* Same as previous macro, but useful when we know that the buffer stack is not + * NULL or when we need an lvalue. For internal use only. + */ +#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] + +/* yy_hold_char holds the character lost when zconftext is formed. */ +static char yy_hold_char; +static int yy_n_chars; /* number of characters read into yy_ch_buf */ +int zconfleng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = (char *) 0; +static int yy_init = 0; /* whether we need to initialize */ +static int yy_start = 0; /* start state number */ + +/* Flag which is used to allow zconfwrap()'s to do buffer switches + * instead of setting up a fresh zconfin. A bit of a hack ... + */ +static int yy_did_buffer_switch_on_eof; + +void zconfrestart (FILE *input_file ); +void zconf_switch_to_buffer (YY_BUFFER_STATE new_buffer ); +YY_BUFFER_STATE zconf_create_buffer (FILE *file,int size ); +void zconf_delete_buffer (YY_BUFFER_STATE b ); +void zconf_flush_buffer (YY_BUFFER_STATE b ); +void zconfpush_buffer_state (YY_BUFFER_STATE new_buffer ); +void zconfpop_buffer_state (void ); + +static void zconfensure_buffer_stack (void ); +static void zconf_load_buffer_state (void ); +static void zconf_init_buffer (YY_BUFFER_STATE b,FILE *file ); + +#define YY_FLUSH_BUFFER zconf_flush_buffer(YY_CURRENT_BUFFER ) + +YY_BUFFER_STATE zconf_scan_buffer (char *base,yy_size_t size ); +YY_BUFFER_STATE zconf_scan_string (yyconst char *yy_str ); +YY_BUFFER_STATE zconf_scan_bytes (yyconst char *bytes,int len ); + +void *zconfalloc (yy_size_t ); +void *zconfrealloc (void *,yy_size_t ); +void zconffree (void * ); + +#define yy_new_buffer zconf_create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! YY_CURRENT_BUFFER ){ \ + zconfensure_buffer_stack (); \ + YY_CURRENT_BUFFER_LVALUE = \ + zconf_create_buffer(zconfin,YY_BUF_SIZE ); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! YY_CURRENT_BUFFER ){\ + zconfensure_buffer_stack (); \ + YY_CURRENT_BUFFER_LVALUE = \ + zconf_create_buffer(zconfin,YY_BUF_SIZE ); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) + +/* Begin user sect3 */ + +#define zconfwrap() 1 +#define YY_SKIP_YYWRAP + +typedef unsigned char YY_CHAR; + +FILE *zconfin = (FILE *) 0, *zconfout = (FILE *) 0; + +typedef int yy_state_type; + +extern int zconflineno; + +int zconflineno = 1; + +extern char *zconftext; +#define yytext_ptr zconftext +static yyconst flex_int16_t yy_nxt[][17] = + { + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0 + }, + + { + 11, 12, 13, 14, 12, 12, 15, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12 + }, + + { + 11, 12, 13, 14, 12, 12, 15, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12 + }, + + { + 11, 16, 16, 17, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 18, 16, 16, 16 + }, + + { + 11, 16, 16, 17, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 18, 16, 16, 16 + + }, + + { + 11, 19, 20, 21, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19 + }, + + { + 11, 19, 20, 21, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19 + }, + + { + 11, 22, 22, 23, 22, 24, 22, 22, 24, 22, + 22, 22, 22, 22, 22, 25, 22 + }, + + { + 11, 22, 22, 23, 22, 24, 22, 22, 24, 22, + 22, 22, 22, 22, 22, 25, 22 + }, + + { + 11, 26, 26, 27, 28, 29, 30, 31, 29, 32, + 33, 34, 35, 35, 36, 37, 38 + + }, + + { + 11, 26, 26, 27, 28, 29, 30, 31, 29, 32, + 33, 34, 35, 35, 36, 37, 38 + }, + + { + -11, -11, -11, -11, -11, -11, -11, -11, -11, -11, + -11, -11, -11, -11, -11, -11, -11 + }, + + { + 11, -12, -12, -12, -12, -12, -12, -12, -12, -12, + -12, -12, -12, -12, -12, -12, -12 + }, + + { + 11, -13, 39, 40, -13, -13, 41, -13, -13, -13, + -13, -13, -13, -13, -13, -13, -13 + }, + + { + 11, -14, -14, -14, -14, -14, -14, -14, -14, -14, + -14, -14, -14, -14, -14, -14, -14 + + }, + + { + 11, 42, 42, 43, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42 + }, + + { + 11, -16, -16, -16, -16, -16, -16, -16, -16, -16, + -16, -16, -16, -16, -16, -16, -16 + }, + + { + 11, -17, -17, -17, -17, -17, -17, -17, -17, -17, + -17, -17, -17, -17, -17, -17, -17 + }, + + { + 11, -18, -18, -18, -18, -18, -18, -18, -18, -18, + -18, -18, -18, 44, -18, -18, -18 + }, + + { + 11, 45, 45, -19, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45 + + }, + + { + 11, -20, 46, 47, -20, -20, -20, -20, -20, -20, + -20, -20, -20, -20, -20, -20, -20 + }, + + { + 11, 48, -21, -21, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48 + }, + + { + 11, 49, 49, 50, 49, -22, 49, 49, -22, 49, + 49, 49, 49, 49, 49, -22, 49 + }, + + { + 11, -23, -23, -23, -23, -23, -23, -23, -23, -23, + -23, -23, -23, -23, -23, -23, -23 + }, + + { + 11, -24, -24, -24, -24, -24, -24, -24, -24, -24, + -24, -24, -24, -24, -24, -24, -24 + + }, + + { + 11, 51, 51, 52, 51, 51, 51, 51, 51, 51, + 51, 51, 51, 51, 51, 51, 51 + }, + + { + 11, -26, -26, -26, -26, -26, -26, -26, -26, -26, + -26, -26, -26, -26, -26, -26, -26 + }, + + { + 11, -27, -27, -27, -27, -27, -27, -27, -27, -27, + -27, -27, -27, -27, -27, -27, -27 + }, + + { + 11, -28, -28, -28, -28, -28, -28, -28, -28, -28, + -28, -28, -28, -28, 53, -28, -28 + }, + + { + 11, -29, -29, -29, -29, -29, -29, -29, -29, -29, + -29, -29, -29, -29, -29, -29, -29 + + }, + + { + 11, 54, 54, -30, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54 + }, + + { + 11, -31, -31, -31, -31, -31, -31, 55, -31, -31, + -31, -31, -31, -31, -31, -31, -31 + }, + + { + 11, -32, -32, -32, -32, -32, -32, -32, -32, -32, + -32, -32, -32, -32, -32, -32, -32 + }, + + { + 11, -33, -33, -33, -33, -33, -33, -33, -33, -33, + -33, -33, -33, -33, -33, -33, -33 + }, + + { + 11, -34, -34, -34, -34, -34, -34, -34, -34, -34, + -34, 56, 57, 57, -34, -34, -34 + + }, + + { + 11, -35, -35, -35, -35, -35, -35, -35, -35, -35, + -35, 57, 57, 57, -35, -35, -35 + }, + + { + 11, -36, -36, -36, -36, -36, -36, -36, -36, -36, + -36, -36, -36, -36, -36, -36, -36 + }, + + { + 11, -37, -37, 58, -37, -37, -37, -37, -37, -37, + -37, -37, -37, -37, -37, -37, -37 + }, + + { + 11, -38, -38, -38, -38, -38, -38, -38, -38, -38, + -38, -38, -38, -38, -38, -38, 59 + }, + + { + 11, -39, 39, 40, -39, -39, 41, -39, -39, -39, + -39, -39, -39, -39, -39, -39, -39 + + }, + + { + 11, -40, -40, -40, -40, -40, -40, -40, -40, -40, + -40, -40, -40, -40, -40, -40, -40 + }, + + { + 11, 42, 42, 43, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42 + }, + + { + 11, 42, 42, 43, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42 + }, + + { + 11, -43, -43, -43, -43, -43, -43, -43, -43, -43, + -43, -43, -43, -43, -43, -43, -43 + }, + + { + 11, -44, -44, -44, -44, -44, -44, -44, -44, -44, + -44, -44, -44, 44, -44, -44, -44 + + }, + + { + 11, 45, 45, -45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45 + }, + + { + 11, -46, 46, 47, -46, -46, -46, -46, -46, -46, + -46, -46, -46, -46, -46, -46, -46 + }, + + { + 11, 48, -47, -47, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48 + }, + + { + 11, -48, -48, -48, -48, -48, -48, -48, -48, -48, + -48, -48, -48, -48, -48, -48, -48 + }, + + { + 11, 49, 49, 50, 49, -49, 49, 49, -49, 49, + 49, 49, 49, 49, 49, -49, 49 + + }, + + { + 11, -50, -50, -50, -50, -50, -50, -50, -50, -50, + -50, -50, -50, -50, -50, -50, -50 + }, + + { + 11, -51, -51, 52, -51, -51, -51, -51, -51, -51, + -51, -51, -51, -51, -51, -51, -51 + }, + + { + 11, -52, -52, -52, -52, -52, -52, -52, -52, -52, + -52, -52, -52, -52, -52, -52, -52 + }, + + { + 11, -53, -53, -53, -53, -53, -53, -53, -53, -53, + -53, -53, -53, -53, -53, -53, -53 + }, + + { + 11, 54, 54, -54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54 + + }, + + { + 11, -55, -55, -55, -55, -55, -55, -55, -55, -55, + -55, -55, -55, -55, -55, -55, -55 + }, + + { + 11, -56, -56, -56, -56, -56, -56, -56, -56, -56, + -56, 60, 57, 57, -56, -56, -56 + }, + + { + 11, -57, -57, -57, -57, -57, -57, -57, -57, -57, + -57, 57, 57, 57, -57, -57, -57 + }, + + { + 11, -58, -58, -58, -58, -58, -58, -58, -58, -58, + -58, -58, -58, -58, -58, -58, -58 + }, + + { + 11, -59, -59, -59, -59, -59, -59, -59, -59, -59, + -59, -59, -59, -59, -59, -59, -59 + + }, + + { + 11, -60, -60, -60, -60, -60, -60, -60, -60, -60, + -60, 57, 57, 57, -60, -60, -60 + }, + + } ; + +static yy_state_type yy_get_previous_state (void ); +static yy_state_type yy_try_NUL_trans (yy_state_type current_state ); +static int yy_get_next_buffer (void ); +static void yy_fatal_error (yyconst char msg[] ); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up zconftext. + */ +#define YY_DO_BEFORE_ACTION \ + (yytext_ptr) = yy_bp; \ + zconfleng = (size_t) (yy_cp - yy_bp); \ + (yy_hold_char) = *yy_cp; \ + *yy_cp = '\0'; \ + (yy_c_buf_p) = yy_cp; + +#define YY_NUM_RULES 33 +#define YY_END_OF_BUFFER 34 +/* This struct is not used in this scanner, + but its presence is necessary. */ +struct yy_trans_info + { + flex_int32_t yy_verify; + flex_int32_t yy_nxt; + }; +static yyconst flex_int16_t yy_accept[61] = + { 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 34, 5, 4, 2, 3, 7, 8, 6, 32, 29, + 31, 24, 28, 27, 26, 22, 17, 13, 16, 20, + 22, 11, 12, 19, 19, 14, 22, 22, 4, 2, + 3, 3, 1, 6, 32, 29, 31, 30, 24, 23, + 26, 25, 15, 20, 9, 19, 19, 21, 10, 18 + } ; + +static yyconst flex_int32_t yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 4, 5, 6, 1, 1, 7, 8, 9, + 10, 1, 1, 1, 11, 12, 12, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 1, 1, 1, + 14, 1, 1, 1, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 1, 15, 1, 1, 13, 1, 13, 13, 13, 13, + + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 1, 16, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +extern int zconf_flex_debug; +int zconf_flex_debug = 0; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +char *zconftext; + +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include +#include +#include + +#define LKC_DIRECT_LINK +#include "lkc.h" + +#define START_STRSIZE 16 + +static struct { + struct file *file; + int lineno; +} current_pos; + +static char *text; +static int text_size, text_asize; + +struct buffer { + struct buffer *parent; + YY_BUFFER_STATE state; +}; + +struct buffer *current_buf; + +static int last_ts, first_ts; + +static void zconf_endhelp(void); +static void zconf_endfile(void); + +void new_string(void) +{ + text = malloc(START_STRSIZE); + text_asize = START_STRSIZE; + text_size = 0; + *text = 0; +} + +void append_string(const char *str, int size) +{ + int new_size = text_size + size + 1; + if (new_size > text_asize) { + new_size += START_STRSIZE - 1; + new_size &= -START_STRSIZE; + text = realloc(text, new_size); + text_asize = new_size; + } + memcpy(text + text_size, str, size); + text_size += size; + text[text_size] = 0; +} + +void alloc_string(const char *str, int size) +{ + text = malloc(size + 1); + memcpy(text, str, size); + text[size] = 0; +} + +#define INITIAL 0 +#define COMMAND 1 +#define HELP 2 +#define STRING 3 +#define PARAM 4 + +#ifndef YY_NO_UNISTD_H +/* Special case for "unistd.h", since it is non-ANSI. We include it way + * down here because we want the user's section 1 to have been scanned first. + * The user has a chance to override it with an option. + */ +#include +#endif + +#ifndef YY_EXTRA_TYPE +#define YY_EXTRA_TYPE void * +#endif + +static int yy_init_globals (void ); + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int zconfwrap (void ); +#else +extern int zconfwrap (void ); +#endif +#endif + + static void yyunput (int c,char *buf_ptr ); + +#ifndef yytext_ptr +static void yy_flex_strncpy (char *,yyconst char *,int ); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * ); +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#define YY_READ_BUF_SIZE 8192 +#endif + +/* Copy whatever the last rule matched to the standard output. */ +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO (void) fwrite( zconftext, zconfleng, 1, zconfout ) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + errno=0; \ + while ( (result = read( fileno(zconfin), (char *) buf, max_size )) < 0 ) \ + { \ + if( errno != EINTR) \ + { \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + break; \ + } \ + errno=0; \ + clearerr(zconfin); \ + }\ +\ + +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) +#endif + +/* end tables serialization structures and prototypes */ + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL_IS_OURS 1 + +extern int zconflex (void); + +#define YY_DECL int zconflex (void) +#endif /* !YY_DECL */ + +/* Code executed at the beginning of each rule, after zconftext and zconfleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +#define YY_RULE_SETUP \ + YY_USER_ACTION + +/** The main scanner function which does all the work. + */ +YY_DECL +{ + register yy_state_type yy_current_state; + register char *yy_cp, *yy_bp; + register int yy_act; + + int str = 0; + int ts, i; + + if ( !(yy_init) ) + { + (yy_init) = 1; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! (yy_start) ) + (yy_start) = 1; /* first start state */ + + if ( ! zconfin ) + zconfin = stdin; + + if ( ! zconfout ) + zconfout = stdout; + + if ( ! YY_CURRENT_BUFFER ) { + zconfensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + zconf_create_buffer(zconfin,YY_BUF_SIZE ); + } + + zconf_load_buffer_state( ); + } + + while ( 1 ) /* loops until end-of-file is reached */ + { + yy_cp = (yy_c_buf_p); + + /* Support of zconftext. */ + *yy_cp = (yy_hold_char); + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = (yy_start); +yy_match: + while ( (yy_current_state = yy_nxt[yy_current_state][ yy_ec[YY_SC_TO_UI(*yy_cp)] ]) > 0 ) + ++yy_cp; + + yy_current_state = -yy_current_state; + +yy_find_action: + yy_act = yy_accept[yy_current_state]; + + YY_DO_BEFORE_ACTION; + +do_action: /* This label is used only to access EOF actions. */ + + switch ( yy_act ) + { /* beginning of action switch */ +case 1: +/* rule 1 can match eol */ +case 2: +/* rule 2 can match eol */ +YY_RULE_SETUP +{ + current_file->lineno++; + return T_EOL; +} + YY_BREAK +case 3: +YY_RULE_SETUP + + YY_BREAK +case 4: +YY_RULE_SETUP +{ + BEGIN(COMMAND); +} + YY_BREAK +case 5: +YY_RULE_SETUP +{ + unput(zconftext[0]); + BEGIN(COMMAND); +} + YY_BREAK + +case 6: +YY_RULE_SETUP +{ + struct kconf_id *id = kconf_id_lookup(zconftext, zconfleng); + BEGIN(PARAM); + current_pos.file = current_file; + current_pos.lineno = current_file->lineno; + if (id && id->flags & TF_COMMAND) { + zconflval.id = id; + return id->token; + } + alloc_string(zconftext, zconfleng); + zconflval.string = text; + return T_WORD; + } + YY_BREAK +case 7: +YY_RULE_SETUP + + YY_BREAK +case 8: +/* rule 8 can match eol */ +YY_RULE_SETUP +{ + BEGIN(INITIAL); + current_file->lineno++; + return T_EOL; + } + YY_BREAK + +case 9: +YY_RULE_SETUP +return T_AND; + YY_BREAK +case 10: +YY_RULE_SETUP +return T_OR; + YY_BREAK +case 11: +YY_RULE_SETUP +return T_OPEN_PAREN; + YY_BREAK +case 12: +YY_RULE_SETUP +return T_CLOSE_PAREN; + YY_BREAK +case 13: +YY_RULE_SETUP +return T_NOT; + YY_BREAK +case 14: +YY_RULE_SETUP +return T_EQUAL; + YY_BREAK +case 15: +YY_RULE_SETUP +return T_UNEQUAL; + YY_BREAK +case 16: +YY_RULE_SETUP +{ + str = zconftext[0]; + new_string(); + BEGIN(STRING); + } + YY_BREAK +case 17: +/* rule 17 can match eol */ +YY_RULE_SETUP +BEGIN(INITIAL); current_file->lineno++; return T_EOL; + YY_BREAK +case 18: +YY_RULE_SETUP +/* ignore */ + YY_BREAK +case 19: +YY_RULE_SETUP +{ + struct kconf_id *id = kconf_id_lookup(zconftext, zconfleng); + if (id && id->flags & TF_PARAM) { + zconflval.id = id; + return id->token; + } + alloc_string(zconftext, zconfleng); + zconflval.string = text; + return T_WORD; + } + YY_BREAK +case 20: +YY_RULE_SETUP +/* comment */ + YY_BREAK +case 21: +/* rule 21 can match eol */ +YY_RULE_SETUP +current_file->lineno++; + YY_BREAK +case 22: +YY_RULE_SETUP + + YY_BREAK +case YY_STATE_EOF(PARAM): +{ + BEGIN(INITIAL); + } + YY_BREAK + +case 23: +/* rule 23 can match eol */ +*yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */ +(yy_c_buf_p) = yy_cp -= 1; +YY_DO_BEFORE_ACTION; /* set up zconftext again */ +YY_RULE_SETUP +{ + append_string(zconftext, zconfleng); + zconflval.string = text; + return T_WORD_QUOTE; + } + YY_BREAK +case 24: +YY_RULE_SETUP +{ + append_string(zconftext, zconfleng); + } + YY_BREAK +case 25: +/* rule 25 can match eol */ +*yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */ +(yy_c_buf_p) = yy_cp -= 1; +YY_DO_BEFORE_ACTION; /* set up zconftext again */ +YY_RULE_SETUP +{ + append_string(zconftext + 1, zconfleng - 1); + zconflval.string = text; + return T_WORD_QUOTE; + } + YY_BREAK +case 26: +YY_RULE_SETUP +{ + append_string(zconftext + 1, zconfleng - 1); + } + YY_BREAK +case 27: +YY_RULE_SETUP +{ + if (str == zconftext[0]) { + BEGIN(PARAM); + zconflval.string = text; + return T_WORD_QUOTE; + } else + append_string(zconftext, 1); + } + YY_BREAK +case 28: +/* rule 28 can match eol */ +YY_RULE_SETUP +{ + printf("%s:%d:warning: multi-line strings not supported\n", zconf_curname(), zconf_lineno()); + current_file->lineno++; + BEGIN(INITIAL); + return T_EOL; + } + YY_BREAK +case YY_STATE_EOF(STRING): +{ + BEGIN(INITIAL); + } + YY_BREAK + +case 29: +YY_RULE_SETUP +{ + ts = 0; + for (i = 0; i < zconfleng; i++) { + if (zconftext[i] == '\t') + ts = (ts & ~7) + 8; + else + ts++; + } + last_ts = ts; + if (first_ts) { + if (ts < first_ts) { + zconf_endhelp(); + return T_HELPTEXT; + } + ts -= first_ts; + while (ts > 8) { + append_string(" ", 8); + ts -= 8; + } + append_string(" ", ts); + } + } + YY_BREAK +case 30: +/* rule 30 can match eol */ +*yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */ +(yy_c_buf_p) = yy_cp -= 1; +YY_DO_BEFORE_ACTION; /* set up zconftext again */ +YY_RULE_SETUP +{ + current_file->lineno++; + zconf_endhelp(); + return T_HELPTEXT; + } + YY_BREAK +case 31: +/* rule 31 can match eol */ +YY_RULE_SETUP +{ + current_file->lineno++; + append_string("\n", 1); + } + YY_BREAK +case 32: +YY_RULE_SETUP +{ + append_string(zconftext, zconfleng); + if (!first_ts) + first_ts = last_ts; + } + YY_BREAK +case YY_STATE_EOF(HELP): +{ + zconf_endhelp(); + return T_HELPTEXT; + } + YY_BREAK + +case YY_STATE_EOF(INITIAL): +case YY_STATE_EOF(COMMAND): +{ + if (current_file) { + zconf_endfile(); + return T_EOL; + } + fclose(zconfin); + yyterminate(); +} + YY_BREAK +case 33: +YY_RULE_SETUP +YY_FATAL_ERROR( "flex scanner jammed" ); + YY_BREAK + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = (yy_hold_char); + YY_RESTORE_YY_MORE_OFFSET + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed zconfin at a new source and called + * zconflex(). If so, then we have to assure + * consistency between YY_CURRENT_BUFFER and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + YY_CURRENT_BUFFER_LVALUE->yy_input_file = zconfin; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( ); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state ); + + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++(yy_c_buf_p); + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = (yy_c_buf_p); + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer( ) ) + { + case EOB_ACT_END_OF_FILE: + { + (yy_did_buffer_switch_on_eof) = 0; + + if ( zconfwrap( ) ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * zconftext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! (yy_did_buffer_switch_on_eof) ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + (yy_c_buf_p) = + (yytext_ptr) + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( ); + + yy_cp = (yy_c_buf_p); + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + (yy_c_buf_p) = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]; + + yy_current_state = yy_get_previous_state( ); + + yy_cp = (yy_c_buf_p); + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ +} /* end of zconflex */ + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ +static int yy_get_next_buffer (void) +{ + register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; + register char *source = (yytext_ptr); + register int number_to_move, i; + int ret_val; + + if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 ) + { + /* We matched a single character, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0; + + else + { + int num_to_read = + YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = YY_CURRENT_BUFFER; + + int yy_c_buf_p_offset = + (int) ((yy_c_buf_p) - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + int new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + zconfrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - + number_to_move - 1; + + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), + (yy_n_chars), num_to_read ); + + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + if ( (yy_n_chars) == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + zconfrestart(zconfin ); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + (yy_n_chars) += number_to_move; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; + + (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; + + return ret_val; +} + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + + static yy_state_type yy_get_previous_state (void) +{ + register yy_state_type yy_current_state; + register char *yy_cp; + + yy_current_state = (yy_start); + + for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) + { + yy_current_state = yy_nxt[yy_current_state][(*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1)]; + } + + return yy_current_state; +} + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state ) +{ + register int yy_is_jam; + + yy_current_state = yy_nxt[yy_current_state][1]; + yy_is_jam = (yy_current_state <= 0); + + return yy_is_jam ? 0 : yy_current_state; +} + + static void yyunput (int c, register char * yy_bp ) +{ + register char *yy_cp; + + yy_cp = (yy_c_buf_p); + + /* undo effects of setting up zconftext */ + *yy_cp = (yy_hold_char); + + if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) + { /* need to shift things up to make room */ + /* +2 for EOB chars. */ + register int number_to_move = (yy_n_chars) + 2; + register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[ + YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2]; + register char *source = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]; + + while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) + *--dest = *--source; + + yy_cp += (int) (dest - source); + yy_bp += (int) (dest - source); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size; + + if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) + YY_FATAL_ERROR( "flex scanner push-back overflow" ); + } + + *--yy_cp = (char) c; + + (yytext_ptr) = yy_bp; + (yy_hold_char) = *yy_cp; + (yy_c_buf_p) = yy_cp; +} + +/** Immediately switch to a different input stream. + * @param input_file A readable stream. + * + * @note This function does not reset the start condition to @c INITIAL . + */ + void zconfrestart (FILE * input_file ) +{ + + if ( ! YY_CURRENT_BUFFER ){ + zconfensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + zconf_create_buffer(zconfin,YY_BUF_SIZE ); + } + + zconf_init_buffer(YY_CURRENT_BUFFER,input_file ); + zconf_load_buffer_state( ); +} + +/** Switch to a different input buffer. + * @param new_buffer The new input buffer. + * + */ + void zconf_switch_to_buffer (YY_BUFFER_STATE new_buffer ) +{ + + /* TODO. We should be able to replace this entire function body + * with + * zconfpop_buffer_state(); + * zconfpush_buffer_state(new_buffer); + */ + zconfensure_buffer_stack (); + if ( YY_CURRENT_BUFFER == new_buffer ) + return; + + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + YY_CURRENT_BUFFER_LVALUE = new_buffer; + zconf_load_buffer_state( ); + + /* We don't actually know whether we did this switch during + * EOF (zconfwrap()) processing, but the only time this flag + * is looked at is after zconfwrap() is called, so it's safe + * to go ahead and always set it. + */ + (yy_did_buffer_switch_on_eof) = 1; +} + +static void zconf_load_buffer_state (void) +{ + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; + zconfin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; + (yy_hold_char) = *(yy_c_buf_p); +} + +/** Allocate and initialize an input buffer state. + * @param file A readable stream. + * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. + * + * @return the allocated buffer state. + */ + YY_BUFFER_STATE zconf_create_buffer (FILE * file, int size ) +{ + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) zconfalloc(sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in zconf_create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) zconfalloc(b->yy_buf_size + 2 ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in zconf_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + zconf_init_buffer(b,file ); + + return b; +} + +/** Destroy the buffer. + * @param b a buffer created with zconf_create_buffer() + * + */ + void zconf_delete_buffer (YY_BUFFER_STATE b ) +{ + + if ( ! b ) + return; + + if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ + YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + zconffree((void *) b->yy_ch_buf ); + + zconffree((void *) b ); +} + +/* Initializes or reinitializes a buffer. + * This function is sometimes called more than once on the same buffer, + * such as during a zconfrestart() or at EOF. + */ + static void zconf_init_buffer (YY_BUFFER_STATE b, FILE * file ) + +{ + int oerrno = errno; + + zconf_flush_buffer(b ); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + + /* If b is the current buffer, then zconf_init_buffer was _probably_ + * called from zconfrestart() or through yy_get_next_buffer. + * In that case, we don't want to reset the lineno or column. + */ + if (b != YY_CURRENT_BUFFER){ + b->yy_bs_lineno = 1; + b->yy_bs_column = 0; + } + + b->yy_is_interactive = 0; + + errno = oerrno; +} + +/** Discard all buffered characters. On the next scan, YY_INPUT will be called. + * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. + * + */ + void zconf_flush_buffer (YY_BUFFER_STATE b ) +{ + if ( ! b ) + return; + + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == YY_CURRENT_BUFFER ) + zconf_load_buffer_state( ); +} + +/** Pushes the new state onto the stack. The new state becomes + * the current state. This function will allocate the stack + * if necessary. + * @param new_buffer The new state. + * + */ +void zconfpush_buffer_state (YY_BUFFER_STATE new_buffer ) +{ + if (new_buffer == NULL) + return; + + zconfensure_buffer_stack(); + + /* This block is copied from zconf_switch_to_buffer. */ + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + /* Only push if top exists. Otherwise, replace top. */ + if (YY_CURRENT_BUFFER) + (yy_buffer_stack_top)++; + YY_CURRENT_BUFFER_LVALUE = new_buffer; + + /* copied from zconf_switch_to_buffer. */ + zconf_load_buffer_state( ); + (yy_did_buffer_switch_on_eof) = 1; +} + +/** Removes and deletes the top of the stack, if present. + * The next element becomes the new top. + * + */ +void zconfpop_buffer_state (void) +{ + if (!YY_CURRENT_BUFFER) + return; + + zconf_delete_buffer(YY_CURRENT_BUFFER ); + YY_CURRENT_BUFFER_LVALUE = NULL; + if ((yy_buffer_stack_top) > 0) + --(yy_buffer_stack_top); + + if (YY_CURRENT_BUFFER) { + zconf_load_buffer_state( ); + (yy_did_buffer_switch_on_eof) = 1; + } +} + +/* Allocates the stack if it does not exist. + * Guarantees space for at least one push. + */ +static void zconfensure_buffer_stack (void) +{ + int num_to_alloc; + + if (!(yy_buffer_stack)) { + + /* First allocation is just for 2 elements, since we don't know if this + * scanner will even need a stack. We use 2 instead of 1 to avoid an + * immediate realloc on the next call. + */ + num_to_alloc = 1; + (yy_buffer_stack) = (struct yy_buffer_state**)zconfalloc + (num_to_alloc * sizeof(struct yy_buffer_state*) + ); + + memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); + + (yy_buffer_stack_max) = num_to_alloc; + (yy_buffer_stack_top) = 0; + return; + } + + if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ + + /* Increase the buffer to prepare for a possible push. */ + int grow_size = 8 /* arbitrary grow size */; + + num_to_alloc = (yy_buffer_stack_max) + grow_size; + (yy_buffer_stack) = (struct yy_buffer_state**)zconfrealloc + ((yy_buffer_stack), + num_to_alloc * sizeof(struct yy_buffer_state*) + ); + + /* zero only the new slots.*/ + memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); + (yy_buffer_stack_max) = num_to_alloc; + } +} + +/** Setup the input buffer state to scan directly from a user-specified character buffer. + * @param base the character buffer + * @param size the size in bytes of the character buffer + * + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE zconf_scan_buffer (char * base, yy_size_t size ) +{ + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE) zconfalloc(sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in zconf_scan_buffer()" ); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + zconf_switch_to_buffer(b ); + + return b; +} + +/** Setup the input buffer state to scan a string. The next call to zconflex() will + * scan from a @e copy of @a str. + * @param yystr a NUL-terminated string to scan + * + * @return the newly allocated buffer state object. + * @note If you want to scan bytes that may contain NUL values, then use + * zconf_scan_bytes() instead. + */ +YY_BUFFER_STATE zconf_scan_string (yyconst char * yystr ) +{ + + return zconf_scan_bytes(yystr,strlen(yystr) ); +} + +/** Setup the input buffer state to scan the given bytes. The next call to zconflex() will + * scan from a @e copy of @a bytes. + * @param bytes the byte buffer to scan + * @param len the number of bytes in the buffer pointed to by @a bytes. + * + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE zconf_scan_bytes (yyconst char * yybytes, int _yybytes_len ) +{ + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = _yybytes_len + 2; + buf = (char *) zconfalloc(n ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in zconf_scan_bytes()" ); + + for ( i = 0; i < _yybytes_len; ++i ) + buf[i] = yybytes[i]; + + buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; + + b = zconf_scan_buffer(buf,n ); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in zconf_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; +} + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +static void yy_fatal_error (yyconst char* msg ) +{ + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); +} + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up zconftext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + zconftext[zconfleng] = (yy_hold_char); \ + (yy_c_buf_p) = zconftext + yyless_macro_arg; \ + (yy_hold_char) = *(yy_c_buf_p); \ + *(yy_c_buf_p) = '\0'; \ + zconfleng = yyless_macro_arg; \ + } \ + while ( 0 ) + +/* Accessor methods (get/set functions) to struct members. */ + +/** Get the current line number. + * + */ +int zconfget_lineno (void) +{ + + return zconflineno; +} + +/** Get the input stream. + * + */ +FILE *zconfget_in (void) +{ + return zconfin; +} + +/** Get the output stream. + * + */ +FILE *zconfget_out (void) +{ + return zconfout; +} + +/** Get the length of the current token. + * + */ +int zconfget_leng (void) +{ + return zconfleng; +} + +/** Get the current token. + * + */ + +char *zconfget_text (void) +{ + return zconftext; +} + +/** Set the current line number. + * @param line_number + * + */ +void zconfset_lineno (int line_number ) +{ + + zconflineno = line_number; +} + +/** Set the input stream. This does not discard the current + * input buffer. + * @param in_str A readable stream. + * + * @see zconf_switch_to_buffer + */ +void zconfset_in (FILE * in_str ) +{ + zconfin = in_str ; +} + +void zconfset_out (FILE * out_str ) +{ + zconfout = out_str ; +} + +int zconfget_debug (void) +{ + return zconf_flex_debug; +} + +void zconfset_debug (int bdebug ) +{ + zconf_flex_debug = bdebug ; +} + +static int yy_init_globals (void) +{ + /* Initialization is the same as for the non-reentrant scanner. + * This function is called from zconflex_destroy(), so don't allocate here. + */ + + (yy_buffer_stack) = 0; + (yy_buffer_stack_top) = 0; + (yy_buffer_stack_max) = 0; + (yy_c_buf_p) = (char *) 0; + (yy_init) = 0; + (yy_start) = 0; + +/* Defined in main.c */ +#ifdef YY_STDINIT + zconfin = stdin; + zconfout = stdout; +#else + zconfin = (FILE *) 0; + zconfout = (FILE *) 0; +#endif + + /* For future reference: Set errno on error, since we are called by + * zconflex_init() + */ + return 0; +} + +/* zconflex_destroy is for both reentrant and non-reentrant scanners. */ +int zconflex_destroy (void) +{ + + /* Pop the buffer stack, destroying each element. */ + while(YY_CURRENT_BUFFER){ + zconf_delete_buffer(YY_CURRENT_BUFFER ); + YY_CURRENT_BUFFER_LVALUE = NULL; + zconfpop_buffer_state(); + } + + /* Destroy the stack itself. */ + zconffree((yy_buffer_stack) ); + (yy_buffer_stack) = NULL; + + /* Reset the globals. This is important in a non-reentrant scanner so the next time + * zconflex() is called, initialization will occur. */ + yy_init_globals( ); + + return 0; +} + +/* + * Internal utility routines. + */ + +#ifndef yytext_ptr +static void yy_flex_strncpy (char* s1, yyconst char * s2, int n ) +{ + register int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; +} +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * s ) +{ + register int n; + for ( n = 0; s[n]; ++n ) + ; + + return n; +} +#endif + +void *zconfalloc (yy_size_t size ) +{ + return (void *) malloc( size ); +} + +void *zconfrealloc (void * ptr, yy_size_t size ) +{ + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return (void *) realloc( (char *) ptr, size ); +} + +void zconffree (void * ptr ) +{ + free( (char *) ptr ); /* see zconfrealloc() for (char *) cast */ +} + +#define YYTABLES_NAME "yytables" + +void zconf_starthelp(void) +{ + new_string(); + last_ts = first_ts = 0; + BEGIN(HELP); +} + +static void zconf_endhelp(void) +{ + zconflval.string = text; + BEGIN(INITIAL); +} + +/* + * Try to open specified file with following names: + * ./name + * $(srctree)/name + * The latter is used when srctree is separate from objtree + * when compiling the kernel. + * Return NULL if file is not found. + */ +FILE *zconf_fopen(const char *name) +{ + char *env, fullname[PATH_MAX+1]; + FILE *f; + + f = fopen(name, "r"); + if (!f && name != NULL && name[0] != '/') { + env = getenv(SRCTREE); + if (env) { + sprintf(fullname, "%s/%s", env, name); + f = fopen(fullname, "r"); + } + } + return f; +} + +void zconf_initscan(const char *name) +{ + zconfin = zconf_fopen(name); + if (!zconfin) { + printf("can't find file %s\n", name); + exit(1); + } + + current_buf = malloc(sizeof(*current_buf)); + memset(current_buf, 0, sizeof(*current_buf)); + + current_file = file_lookup(name); + current_file->lineno = 1; + current_file->flags = FILE_BUSY; +} + +void zconf_nextfile(const char *name) +{ + struct file *file = file_lookup(name); + struct buffer *buf = malloc(sizeof(*buf)); + memset(buf, 0, sizeof(*buf)); + + current_buf->state = YY_CURRENT_BUFFER; + zconfin = zconf_fopen(name); + if (!zconfin) { + printf("%s:%d: can't open file \"%s\"\n", zconf_curname(), zconf_lineno(), name); + exit(1); + } + zconf_switch_to_buffer(zconf_create_buffer(zconfin,YY_BUF_SIZE)); + buf->parent = current_buf; + current_buf = buf; + + if (file->flags & FILE_BUSY) { + printf("recursive scan (%s)?\n", name); + exit(1); + } + if (file->flags & FILE_SCANNED) { + printf("file %s already scanned?\n", name); + exit(1); + } + file->flags |= FILE_BUSY; + file->lineno = 1; + file->parent = current_file; + current_file = file; +} + +static void zconf_endfile(void) +{ + struct buffer *parent; + + current_file->flags |= FILE_SCANNED; + current_file->flags &= ~FILE_BUSY; + current_file = current_file->parent; + + parent = current_buf->parent; + if (parent) { + fclose(zconfin); + zconf_delete_buffer(YY_CURRENT_BUFFER); + zconf_switch_to_buffer(parent->state); + } + free(current_buf); + current_buf = parent; +} + +int zconf_lineno(void) +{ + return current_pos.lineno; +} + +char *zconf_curname(void) +{ + return current_pos.file ? current_pos.file->name : ""; +} + diff --git a/host/src/wrsconfig/lkc.h b/host/src/wrsconfig/lkc.h new file mode 100755 index 00000000000..387548094ec --- /dev/null +++ b/host/src/wrsconfig/lkc.h @@ -0,0 +1,175 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#ifndef LKC_H +#define LKC_H + +#ifdef HOST_WIN32 + #include /* for mkdir() */ +#endif + +#include "expr.h" + +#ifndef KBUILD_NO_NLS +# include +#else +# define gettext(Msgid) ((const char *) (Msgid)) +# define textdomain(Domainname) ((const char *) (Domainname)) +# define bindtextdomain(Domainname, Dirname) ((const char *) (Dirname)) +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef LKC_DIRECT_LINK +#define P(name,type,arg) extern type name arg +#else +#include "lkc_defs.h" +#define P(name,type,arg) extern type (*name ## _p) arg +#endif +#include "lkc_proto.h" +#undef P + +#define SRCTREE "srctree" + +#define PACKAGE "linux" +#define LOCALEDIR "/usr/share/locale" + +#define _(text) gettext(text) +#define N_(text) (text) + + +#define TF_COMMAND 0x0001 +#define TF_PARAM 0x0002 +#define TF_OPTION 0x0004 + +#define T_OPT_MODULES 1 +#define T_OPT_DEFCONFIG_LIST 2 + +struct kconf_id { + int name; + int token; + unsigned int flags; + enum symbol_type stype; +}; + +int zconfparse(void); +void zconfdump(FILE *out); + +extern int zconfdebug; +void zconf_starthelp(void); +FILE *zconf_fopen(const char *name); +void zconf_initscan(const char *name); +void zconf_nextfile(const char *name); +int zconf_lineno(void); +char *zconf_curname(void); + +/* confdata.c */ +const char *conf_get_configname(void); +char *conf_get_default_confname(void); +void sym_set_change_count(int count); +void sym_add_change_count(int count); + +/* kconfig_load.c */ +void kconfig_load(void); + +/* menu.c */ +void menu_init(void); +struct menu *menu_add_menu(void); +void menu_end_menu(void); +void menu_add_entry(struct symbol *sym); +void menu_end_entry(void); +void menu_add_dep(struct expr *dep); +struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep); +struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep); +void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep); +void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep); +void menu_add_option(int token, char *arg); +void menu_finalize(struct menu *parent); +void menu_set_type(int type); + +/* util.c */ +struct file *file_lookup(const char *name); +int file_write_dep(const char *name); + +struct gstr { + size_t len; + char *s; +}; +struct gstr str_new(void); +struct gstr str_assign(const char *s); +void str_free(struct gstr *gs); +void str_append(struct gstr *gs, const char *s); +void str_printf(struct gstr *gs, const char *fmt, ...); +const char *str_get(struct gstr *gs); + +/* symbol.c */ +void sym_init(void); +void sym_clear_all_valid(void); +void sym_set_all_changed(void); +void sym_set_changed(struct symbol *sym); +struct symbol *sym_check_deps(struct symbol *sym); +struct property *prop_alloc(enum prop_type type, struct symbol *sym); +struct symbol *prop_get_symbol(struct property *prop); + +static inline tristate sym_get_tristate_value(struct symbol *sym) +{ + return sym->curr.tri; +} + + +static inline struct symbol *sym_get_choice_value(struct symbol *sym) +{ + return (struct symbol *)sym->curr.val; +} + +static inline bool sym_set_choice_value(struct symbol *ch, struct symbol *chval) +{ + return sym_set_tristate_value(chval, yes); +} + +static inline bool sym_is_choice(struct symbol *sym) +{ + return sym->flags & SYMBOL_CHOICE ? true : false; +} + +static inline bool sym_is_choice_value(struct symbol *sym) +{ + return sym->flags & SYMBOL_CHOICEVAL ? true : false; +} + +static inline bool sym_is_optional(struct symbol *sym) +{ + return sym->flags & SYMBOL_OPTIONAL ? true : false; +} + +static inline bool sym_has_value(struct symbol *sym) +{ + return sym->flags & SYMBOL_DEF_USER ? true : false; +} + +static inline int loc_rename(const char *old, const char *new) +{ +#ifdef HOST_WIN32 + unlink(new); +#endif + return rename(old, new); +} + +static inline int loc_mkdir(const char *path, int mode) +{ +#ifdef HOST_WIN32 + return mkdir(path); +#else + return mkdir(path, mode); +#endif +} + +#ifdef __cplusplus +} +#endif + +#endif /* LKC_H */ diff --git a/host/src/wrsconfig/lkc_proto.h b/host/src/wrsconfig/lkc_proto.h new file mode 100755 index 00000000000..bca8508e4f6 --- /dev/null +++ b/host/src/wrsconfig/lkc_proto.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2011, Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* confdata.c */ +P(conf_parse,void,(const char *name)); +P(conf_read,int,(const char *name)); +P(conf_read_simple,int,(const char *name, int)); +P(conf_write,int,(const char *name)); +P(conf_write_autoconf,int,(void)); +P(conf_get_changed,bool,(void)); +P(conf_set_changed_callback, void,(void (*fn)(void))); + +/* menu.c */ +P(rootmenu,struct menu,); + +P(menu_is_visible,bool,(struct menu *menu)); +P(menu_get_prompt,const char *,(struct menu *menu)); +P(menu_get_root_menu,struct menu *,(struct menu *menu)); +P(menu_get_parent_menu,struct menu *,(struct menu *menu)); +P(menu_has_help,bool,(struct menu *menu)); +P(menu_get_help,const char *,(struct menu *menu)); + +/* symbol.c */ +P(symbol_hash,struct symbol *,[SYMBOL_HASHSIZE]); + +P(sym_lookup,struct symbol *,(const char *name, int isconst)); +P(sym_find,struct symbol *,(const char *name)); +P(sym_re_search,struct symbol **,(const char *pattern)); +P(sym_type_name,const char *,(enum symbol_type type)); +P(sym_calc_value,void,(struct symbol *sym)); +P(sym_get_type,enum symbol_type,(struct symbol *sym)); +P(sym_tristate_within_range,bool,(struct symbol *sym,tristate tri)); +P(sym_set_tristate_value,bool,(struct symbol *sym,tristate tri)); +P(sym_toggle_tristate_value,tristate,(struct symbol *sym)); +P(sym_string_valid,bool,(struct symbol *sym, const char *newval)); +P(sym_string_within_range,bool,(struct symbol *sym, const char *str)); +P(sym_set_string_value,bool,(struct symbol *sym, const char *newval)); +P(sym_is_changable,bool,(struct symbol *sym)); +P(sym_get_choice_prop,struct property *,(struct symbol *sym)); +P(sym_get_default_prop,struct property *,(struct symbol *sym)); +P(sym_get_string_value,const char *,(struct symbol *sym)); + +P(prop_get_type_name,const char *,(enum prop_type type)); + +/* expr.c */ +P(expr_compare_type,int,(enum expr_type t1, enum expr_type t2)); +P(expr_print,void,(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken)); diff --git a/host/src/wrsconfig/menu.c b/host/src/wrsconfig/menu.c new file mode 100755 index 00000000000..ea7af5cd372 --- /dev/null +++ b/host/src/wrsconfig/menu.c @@ -0,0 +1,431 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include + +#define LKC_DIRECT_LINK +#include "lkc.h" + +struct menu rootmenu; +static struct menu **last_entry_ptr; + +struct file *file_list; +struct file *current_file; + +static void menu_warn(struct menu *menu, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + fprintf(stderr, "%s:%d:warning: ", menu->file->name, menu->lineno); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); + va_end(ap); +} + +static void prop_warn(struct property *prop, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + fprintf(stderr, "%s:%d:warning: ", prop->file->name, prop->lineno); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); + va_end(ap); +} + +void menu_init(void) +{ + current_entry = current_menu = &rootmenu; + last_entry_ptr = &rootmenu.list; +} + +void menu_add_entry(struct symbol *sym) +{ + struct menu *menu; + + menu = malloc(sizeof(*menu)); + memset(menu, 0, sizeof(*menu)); + menu->sym = sym; + menu->parent = current_menu; + menu->file = current_file; + menu->lineno = zconf_lineno(); + + *last_entry_ptr = menu; + last_entry_ptr = &menu->next; + current_entry = menu; +} + +void menu_end_entry(void) +{ +} + +struct menu *menu_add_menu(void) +{ + menu_end_entry(); + last_entry_ptr = ¤t_entry->list; + return current_menu = current_entry; +} + +void menu_end_menu(void) +{ + last_entry_ptr = ¤t_menu->next; + current_menu = current_menu->parent; +} + +struct expr *menu_check_dep(struct expr *e) +{ + if (!e) + return e; + + switch (e->type) { + case E_NOT: + e->left.expr = menu_check_dep(e->left.expr); + break; + case E_OR: + case E_AND: + e->left.expr = menu_check_dep(e->left.expr); + e->right.expr = menu_check_dep(e->right.expr); + break; + case E_SYMBOL: + /* change 'm' into 'm' && MODULES */ + if (e->left.sym == &symbol_mod) + return expr_alloc_and(e, expr_alloc_symbol(modules_sym)); + break; + default: + break; + } + return e; +} + +void menu_add_dep(struct expr *dep) +{ + current_entry->dep = expr_alloc_and(current_entry->dep, menu_check_dep(dep)); +} + +void menu_set_type(int type) +{ + struct symbol *sym = current_entry->sym; + + if (sym->type == type) + return; + if (sym->type == S_UNKNOWN) { + sym->type = type; + return; + } + menu_warn(current_entry, "type of '%s' redefined from '%s' to '%s'", + sym->name ? sym->name : "", + sym_type_name(sym->type), sym_type_name(type)); +} + +struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep) +{ + struct property *prop = prop_alloc(type, current_entry->sym); + + prop->menu = current_entry; + prop->expr = expr; + prop->visible.expr = menu_check_dep(dep); + + if (prompt) { + if (isspace(*prompt)) { + prop_warn(prop, "leading whitespace ignored"); + while (isspace(*prompt)) + prompt++; + } + if (current_entry->prompt) + prop_warn(prop, "prompt redefined"); + current_entry->prompt = prop; + } + prop->text = prompt; + + return prop; +} + +struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep) +{ + return menu_add_prop(type, prompt, NULL, dep); +} + +void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep) +{ + menu_add_prop(type, NULL, expr, dep); +} + +void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep) +{ + menu_add_prop(type, NULL, expr_alloc_symbol(sym), dep); +} + +void menu_add_option(int token, char *arg) +{ + struct property *prop; + + switch (token) { + case T_OPT_MODULES: + prop = prop_alloc(P_DEFAULT, modules_sym); + prop->expr = expr_alloc_symbol(current_entry->sym); + break; + case T_OPT_DEFCONFIG_LIST: + if (!sym_defconfig_list) + sym_defconfig_list = current_entry->sym; + else if (sym_defconfig_list != current_entry->sym) + zconf_error("trying to redefine defconfig symbol"); + break; + } +} + +static int menu_range_valid_sym(struct symbol *sym, struct symbol *sym2) +{ + return sym2->type == S_INT || sym2->type == S_HEX || + (sym2->type == S_UNKNOWN && sym_string_valid(sym, sym2->name)); +} + +void sym_check_prop(struct symbol *sym) +{ + struct property *prop; + struct symbol *sym2; + for (prop = sym->prop; prop; prop = prop->next) { + switch (prop->type) { + case P_DEFAULT: + if ((sym->type == S_STRING || sym->type == S_INT || sym->type == S_HEX) && + prop->expr->type != E_SYMBOL) + prop_warn(prop, + "default for config symbol '%'" + " must be a single symbol", sym->name); + break; + case P_SELECT: + sym2 = prop_get_symbol(prop); + if (sym->type != S_BOOLEAN && sym->type != S_TRISTATE) + prop_warn(prop, + "config symbol '%s' uses select, but is " + "not boolean or tristate", sym->name); + else if (sym2->type == S_UNKNOWN) + prop_warn(prop, + "'select' used by config symbol '%s' " + "refers to undefined symbol '%s'", + sym->name, sym2->name); + else if (sym2->type != S_BOOLEAN && sym2->type != S_TRISTATE) + prop_warn(prop, + "'%s' has wrong type. 'select' only " + "accept arguments of boolean and " + "tristate type", sym2->name); + break; + case P_RANGE: + if (sym->type != S_INT && sym->type != S_HEX) + prop_warn(prop, "range is only allowed " + "for int or hex symbols"); + if (!menu_range_valid_sym(sym, prop->expr->left.sym) || + !menu_range_valid_sym(sym, prop->expr->right.sym)) + prop_warn(prop, "range is invalid"); + break; + default: + ; + } + } +} + +void menu_finalize(struct menu *parent) +{ + struct menu *menu, *last_menu; + struct symbol *sym; + struct property *prop; + struct expr *parentdep, *basedep, *dep, *dep2, **ep; + + sym = parent->sym; + if (parent->list) { + if (sym && sym_is_choice(sym)) { + /* find the first choice value and find out choice type */ + for (menu = parent->list; menu; menu = menu->next) { + if (menu->sym) { + current_entry = parent; + menu_set_type(menu->sym->type); + current_entry = menu; + menu_set_type(sym->type); + break; + } + } + parentdep = expr_alloc_symbol(sym); + } else if (parent->prompt) + parentdep = parent->prompt->visible.expr; + else + parentdep = parent->dep; + + for (menu = parent->list; menu; menu = menu->next) { + basedep = expr_transform(menu->dep); + basedep = expr_alloc_and(expr_copy(parentdep), basedep); + basedep = expr_eliminate_dups(basedep); + menu->dep = basedep; + if (menu->sym) + prop = menu->sym->prop; + else + prop = menu->prompt; + for (; prop; prop = prop->next) { + if (prop->menu != menu) + continue; + dep = expr_transform(prop->visible.expr); + dep = expr_alloc_and(expr_copy(basedep), dep); + dep = expr_eliminate_dups(dep); + if (menu->sym && menu->sym->type != S_TRISTATE) + dep = expr_trans_bool(dep); + prop->visible.expr = dep; + if (prop->type == P_SELECT) { + struct symbol *es = prop_get_symbol(prop); + es->rev_dep.expr = expr_alloc_or(es->rev_dep.expr, + expr_alloc_and(expr_alloc_symbol(menu->sym), expr_copy(dep))); + } + } + } + for (menu = parent->list; menu; menu = menu->next) + menu_finalize(menu); + } else if (sym) { + basedep = parent->prompt ? parent->prompt->visible.expr : NULL; + basedep = expr_trans_compare(basedep, E_UNEQUAL, &symbol_no); + basedep = expr_eliminate_dups(expr_transform(basedep)); + last_menu = NULL; + for (menu = parent->next; menu; menu = menu->next) { + dep = menu->prompt ? menu->prompt->visible.expr : menu->dep; + if (!expr_contains_symbol(dep, sym)) + break; + if (expr_depends_symbol(dep, sym)) + goto next; + dep = expr_trans_compare(dep, E_UNEQUAL, &symbol_no); + dep = expr_eliminate_dups(expr_transform(dep)); + dep2 = expr_copy(basedep); + expr_eliminate_eq(&dep, &dep2); + expr_free(dep); + if (!expr_is_yes(dep2)) { + expr_free(dep2); + break; + } + expr_free(dep2); +next: + menu_finalize(menu); + menu->parent = parent; + last_menu = menu; + } + if (last_menu) { + parent->list = parent->next; + parent->next = last_menu->next; + last_menu->next = NULL; + } + } + for (menu = parent->list; menu; menu = menu->next) { + if (sym && sym_is_choice(sym) && menu->sym) { + menu->sym->flags |= SYMBOL_CHOICEVAL; + if (!menu->prompt) + menu_warn(menu, "choice value must have a prompt"); + for (prop = menu->sym->prop; prop; prop = prop->next) { + if (prop->type == P_PROMPT && prop->menu != menu) { + prop_warn(prop, "choice values " + "currently only support a " + "single prompt"); + } + if (prop->type == P_DEFAULT) + prop_warn(prop, "defaults for choice " + "values not supported"); + } + current_entry = menu; + menu_set_type(sym->type); + menu_add_symbol(P_CHOICE, sym, NULL); + prop = sym_get_choice_prop(sym); + for (ep = &prop->expr; *ep; ep = &(*ep)->left.expr) + ; + *ep = expr_alloc_one(E_CHOICE, NULL); + (*ep)->right.sym = menu->sym; + } + if (menu->list && (!menu->prompt || !menu->prompt->text)) { + for (last_menu = menu->list; ; last_menu = last_menu->next) { + last_menu->parent = parent; + if (!last_menu->next) + break; + } + last_menu->next = menu->next; + menu->next = menu->list; + menu->list = NULL; + } + } + + if (sym && !(sym->flags & SYMBOL_WARNED)) { + if (sym->type == S_UNKNOWN) + menu_warn(parent, "config symbol defined without type"); + + if (sym_is_choice(sym) && !parent->prompt) + menu_warn(parent, "choice must have a prompt"); + + /* Check properties connected to this symbol */ + sym_check_prop(sym); + sym->flags |= SYMBOL_WARNED; + } + + if (sym && !sym_is_optional(sym) && parent->prompt) { + sym->rev_dep.expr = expr_alloc_or(sym->rev_dep.expr, + expr_alloc_and(parent->prompt->visible.expr, + expr_alloc_symbol(&symbol_mod))); + } +} + +bool menu_is_visible(struct menu *menu) +{ + struct menu *child; + struct symbol *sym; + tristate visible; + + if (!menu->prompt) + return false; + sym = menu->sym; + if (sym) { + sym_calc_value(sym); + visible = menu->prompt->visible.tri; + } else + visible = menu->prompt->visible.tri = expr_calc_value(menu->prompt->visible.expr); + + if (visible != no) + return true; + if (!sym || sym_get_tristate_value(menu->sym) == no) + return false; + + for (child = menu->list; child; child = child->next) + if (menu_is_visible(child)) + return true; + return false; +} + +const char *menu_get_prompt(struct menu *menu) +{ + if (menu->prompt) + return _(menu->prompt->text); + else if (menu->sym) + return _(menu->sym->name); + return NULL; +} + +struct menu *menu_get_root_menu(struct menu *menu) +{ + return &rootmenu; +} + +struct menu *menu_get_parent_menu(struct menu *menu) +{ + enum prop_type type; + + for (; menu != &rootmenu; menu = menu->parent) { + type = menu->prompt ? menu->prompt->type : 0; + if (type == P_MENU) + break; + } + return menu; +} + +bool menu_has_help(struct menu *menu) +{ + return menu->help != NULL; +} + +const char *menu_get_help(struct menu *menu) +{ + if (menu->help) + return menu->help; + else + return ""; +} diff --git a/host/src/wrsconfig/symbol.c b/host/src/wrsconfig/symbol.c new file mode 100755 index 00000000000..4a309809179 --- /dev/null +++ b/host/src/wrsconfig/symbol.c @@ -0,0 +1,887 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include +#ifndef NO_REGEX +#include +#endif +#ifndef NO_UNAME +#include +#endif + +#define LKC_DIRECT_LINK +#include "lkc.h" + +struct symbol symbol_yes = { + .name = "y", + .curr = { "y", yes }, + .flags = SYMBOL_CONST|SYMBOL_VALID, +}, symbol_mod = { + .name = "m", + .curr = { "m", mod }, + .flags = SYMBOL_CONST|SYMBOL_VALID, +}, symbol_no = { + .name = "n", + .curr = { "n", no }, + .flags = SYMBOL_CONST|SYMBOL_VALID, +}, symbol_empty = { + .name = "", + .curr = { "", no }, + .flags = SYMBOL_VALID, +}; + +struct symbol *sym_defconfig_list; +struct symbol *modules_sym; +tristate modules_val; + +void sym_add_default(struct symbol *sym, const char *def) +{ + struct property *prop = prop_alloc(P_DEFAULT, sym); + + prop->expr = expr_alloc_symbol(sym_lookup(def, 1)); +} + +void sym_init(void) +{ + struct symbol *sym; +#ifndef NO_UNAME + struct utsname uts; +#endif + char *p; + static bool inited = false; + + if (inited) + return; + inited = true; + + sym = sym_lookup("ARCH", 0); + sym->type = S_STRING; + sym->flags |= SYMBOL_AUTO; + p = getenv("ARCH"); + if (p) + sym_add_default(sym, p); + + sym = sym_lookup("KERNELVERSION", 0); + sym->type = S_STRING; + sym->flags |= SYMBOL_AUTO; + p = getenv("KERNELVERSION"); + if (p) + sym_add_default(sym, p); + +#ifndef NO_UNAME + uname(&uts); + sym = sym_lookup("UNAME_RELEASE", 0); + sym->type = S_STRING; + sym->flags |= SYMBOL_AUTO; + sym_add_default(sym, uts.release); +#endif +} + +enum symbol_type sym_get_type(struct symbol *sym) +{ + enum symbol_type type = sym->type; + + if (type == S_TRISTATE) { + if (sym_is_choice_value(sym) && sym->visible == yes) + type = S_BOOLEAN; + else if (modules_val == no) + type = S_BOOLEAN; + } + return type; +} + +const char *sym_type_name(enum symbol_type type) +{ + switch (type) { + case S_BOOLEAN: + return "boolean"; + case S_TRISTATE: + return "tristate"; + case S_INT: + return "integer"; + case S_HEX: + return "hex"; + case S_STRING: + return "string"; + case S_UNKNOWN: + return "unknown"; + case S_OTHER: + break; + } + return "???"; +} + +struct property *sym_get_choice_prop(struct symbol *sym) +{ + struct property *prop; + + for_all_choices(sym, prop) + return prop; + return NULL; +} + +struct property *sym_get_default_prop(struct symbol *sym) +{ + struct property *prop; + + for_all_defaults(sym, prop) { + prop->visible.tri = expr_calc_value(prop->visible.expr); + if (prop->visible.tri != no) + return prop; + } + return NULL; +} + +struct property *sym_get_range_prop(struct symbol *sym) +{ + struct property *prop; + + for_all_properties(sym, prop, P_RANGE) { + prop->visible.tri = expr_calc_value(prop->visible.expr); + if (prop->visible.tri != no) + return prop; + } + return NULL; +} + +static int sym_get_range_val(struct symbol *sym, int base) +{ + sym_calc_value(sym); + switch (sym->type) { + case S_INT: + base = 10; + break; + case S_HEX: + base = 16; + break; + default: + break; + } + return strtol(sym->curr.val, NULL, base); +} + +static void sym_validate_range(struct symbol *sym) +{ + struct property *prop; + int base, val, val2; + char str[64]; + + switch (sym->type) { + case S_INT: + base = 10; + break; + case S_HEX: + base = 16; + break; + default: + return; + } + prop = sym_get_range_prop(sym); + if (!prop) + return; + val = strtol(sym->curr.val, NULL, base); + val2 = sym_get_range_val(prop->expr->left.sym, base); + if (val >= val2) { + val2 = sym_get_range_val(prop->expr->right.sym, base); + if (val <= val2) + return; + } + if (sym->type == S_INT) + sprintf(str, "%d", val2); + else + sprintf(str, "0x%x", val2); + sym->curr.val = strdup(str); +} + +static void sym_calc_visibility(struct symbol *sym) +{ + struct property *prop; + tristate tri; + + /* any prompt visible? */ + tri = no; + for_all_prompts(sym, prop) { + prop->visible.tri = expr_calc_value(prop->visible.expr); + tri = E_OR(tri, prop->visible.tri); + } + if (tri == mod && (sym->type != S_TRISTATE || modules_val == no)) + tri = yes; + if (sym->visible != tri) { + sym->visible = tri; + sym_set_changed(sym); + } + if (sym_is_choice_value(sym)) + return; + tri = no; + if (sym->rev_dep.expr) + tri = expr_calc_value(sym->rev_dep.expr); + if (tri == mod && sym_get_type(sym) == S_BOOLEAN) + tri = yes; + if (sym->rev_dep.tri != tri) { + sym->rev_dep.tri = tri; + sym_set_changed(sym); + } +} + +static struct symbol *sym_calc_choice(struct symbol *sym) +{ + struct symbol *def_sym; + struct property *prop; + struct expr *e; + + /* is the user choice visible? */ + def_sym = sym->def[S_DEF_USER].val; + if (def_sym) { + sym_calc_visibility(def_sym); + if (def_sym->visible != no) + return def_sym; + } + + /* any of the defaults visible? */ + for_all_defaults(sym, prop) { + prop->visible.tri = expr_calc_value(prop->visible.expr); + if (prop->visible.tri == no) + continue; + def_sym = prop_get_symbol(prop); + sym_calc_visibility(def_sym); + if (def_sym->visible != no) + return def_sym; + } + + /* just get the first visible value */ + prop = sym_get_choice_prop(sym); + for (e = prop->expr; e; e = e->left.expr) { + def_sym = e->right.sym; + sym_calc_visibility(def_sym); + if (def_sym->visible != no) + return def_sym; + } + + /* no choice? reset tristate value */ + sym->curr.tri = no; + return NULL; +} + +void sym_calc_value(struct symbol *sym) +{ + struct symbol_value newval, oldval; + struct property *prop; + struct expr *e; + + if (!sym) + return; + + if (sym->flags & SYMBOL_VALID) + return; + sym->flags |= SYMBOL_VALID; + + oldval = sym->curr; + + switch (sym->type) { + case S_INT: + case S_HEX: + case S_STRING: + newval = symbol_empty.curr; + break; + case S_BOOLEAN: + case S_TRISTATE: + newval = symbol_no.curr; + break; + default: + sym->curr.val = sym->name; + sym->curr.tri = no; + return; + } + if (!sym_is_choice_value(sym)) + sym->flags &= ~SYMBOL_WRITE; + + sym_calc_visibility(sym); + + /* set default if recursively called */ + sym->curr = newval; + + switch (sym_get_type(sym)) { + case S_BOOLEAN: + case S_TRISTATE: + if (sym_is_choice_value(sym) && sym->visible == yes) { + prop = sym_get_choice_prop(sym); + newval.tri = (prop_get_symbol(prop)->curr.val == sym) ? yes : no; + } else if (E_OR(sym->visible, sym->rev_dep.tri) != no) { + sym->flags |= SYMBOL_WRITE; + if (sym_has_value(sym)) + newval.tri = sym->def[S_DEF_USER].tri; + else if (!sym_is_choice(sym)) { + prop = sym_get_default_prop(sym); + if (prop) + newval.tri = expr_calc_value(prop->expr); + } + newval.tri = E_OR(E_AND(newval.tri, sym->visible), sym->rev_dep.tri); + } else if (!sym_is_choice(sym)) { + prop = sym_get_default_prop(sym); + if (prop) { + sym->flags |= SYMBOL_WRITE; + newval.tri = expr_calc_value(prop->expr); + } + } + if (newval.tri == mod && sym_get_type(sym) == S_BOOLEAN) + newval.tri = yes; + break; + case S_STRING: + case S_HEX: + case S_INT: + if (sym->visible != no) { + sym->flags |= SYMBOL_WRITE; + if (sym_has_value(sym)) { + newval.val = sym->def[S_DEF_USER].val; + break; + } + } + prop = sym_get_default_prop(sym); + if (prop) { + struct symbol *ds = prop_get_symbol(prop); + if (ds) { + sym->flags |= SYMBOL_WRITE; + sym_calc_value(ds); + newval.val = ds->curr.val; + } + } + break; + default: + ; + } + + sym->curr = newval; + if (sym_is_choice(sym) && newval.tri == yes) + sym->curr.val = sym_calc_choice(sym); + sym_validate_range(sym); + + if (memcmp(&oldval, &sym->curr, sizeof(oldval))) { + sym_set_changed(sym); + if (modules_sym == sym) { + sym_set_all_changed(); + modules_val = modules_sym->curr.tri; + } + } + + if (sym_is_choice(sym)) { + int flags = sym->flags & (SYMBOL_CHANGED | SYMBOL_WRITE); + prop = sym_get_choice_prop(sym); + for (e = prop->expr; e; e = e->left.expr) { + e->right.sym->flags |= flags; + if (flags & SYMBOL_CHANGED) + sym_set_changed(e->right.sym); + } + } +} + +void sym_clear_all_valid(void) +{ + struct symbol *sym; + int i; + + for_all_symbols(i, sym) + sym->flags &= ~SYMBOL_VALID; + sym_add_change_count(1); + if (modules_sym) + sym_calc_value(modules_sym); +} + +void sym_set_changed(struct symbol *sym) +{ + struct property *prop; + + sym->flags |= SYMBOL_CHANGED; + for (prop = sym->prop; prop; prop = prop->next) { + if (prop->menu) + prop->menu->flags |= MENU_CHANGED; + } +} + +void sym_set_all_changed(void) +{ + struct symbol *sym; + int i; + + for_all_symbols(i, sym) + sym_set_changed(sym); +} + +bool sym_tristate_within_range(struct symbol *sym, tristate val) +{ + int type = sym_get_type(sym); + + if (sym->visible == no) + return false; + + if (type != S_BOOLEAN && type != S_TRISTATE) + return false; + + if (type == S_BOOLEAN && val == mod) + return false; + if (sym->visible <= sym->rev_dep.tri) + return false; + if (sym_is_choice_value(sym) && sym->visible == yes) + return val == yes; + return val >= sym->rev_dep.tri && val <= sym->visible; +} + +bool sym_set_tristate_value(struct symbol *sym, tristate val) +{ + tristate oldval = sym_get_tristate_value(sym); + + if (oldval != val && !sym_tristate_within_range(sym, val)) + return false; + + if (!(sym->flags & SYMBOL_DEF_USER)) { + sym->flags |= SYMBOL_DEF_USER; + sym_set_changed(sym); + } + /* + * setting a choice value also resets the new flag of the choice + * symbol and all other choice values. + */ + if (sym_is_choice_value(sym) && val == yes) { + struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym)); + struct property *prop; + struct expr *e; + + cs->def[S_DEF_USER].val = sym; + cs->flags |= SYMBOL_DEF_USER; + prop = sym_get_choice_prop(cs); + for (e = prop->expr; e; e = e->left.expr) { + if (e->right.sym->visible != no) + e->right.sym->flags |= SYMBOL_DEF_USER; + } + } + + sym->def[S_DEF_USER].tri = val; + if (oldval != val) + sym_clear_all_valid(); + + return true; +} + +tristate sym_toggle_tristate_value(struct symbol *sym) +{ + tristate oldval, newval; + + oldval = newval = sym_get_tristate_value(sym); + do { + switch (newval) { + case no: + newval = mod; + break; + case mod: + newval = yes; + break; + case yes: + newval = no; + break; + } + if (sym_set_tristate_value(sym, newval)) + break; + } while (oldval != newval); + return newval; +} + +bool sym_string_valid(struct symbol *sym, const char *str) +{ + signed char ch; + + switch (sym->type) { + case S_STRING: + return true; + case S_INT: + ch = *str++; + if (ch == '-') + ch = *str++; + if (!isdigit(ch)) + return false; + if (ch == '0' && *str != 0) + return false; + while ((ch = *str++)) { + if (!isdigit(ch)) + return false; + } + return true; + case S_HEX: + if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) + str += 2; + ch = *str++; + do { + if (!isxdigit(ch)) + return false; + } while ((ch = *str++)); + return true; + case S_BOOLEAN: + case S_TRISTATE: + switch (str[0]) { + case 'y': case 'Y': + case 'm': case 'M': + case 'n': case 'N': + return true; + } + return false; + default: + return false; + } +} + +bool sym_string_within_range(struct symbol *sym, const char *str) +{ + struct property *prop; + int val; + + switch (sym->type) { + case S_STRING: + return sym_string_valid(sym, str); + case S_INT: + if (!sym_string_valid(sym, str)) + return false; + prop = sym_get_range_prop(sym); + if (!prop) + return true; + val = strtol(str, NULL, 10); + return val >= sym_get_range_val(prop->expr->left.sym, 10) && + val <= sym_get_range_val(prop->expr->right.sym, 10); + case S_HEX: + if (!sym_string_valid(sym, str)) + return false; + prop = sym_get_range_prop(sym); + if (!prop) + return true; + val = strtol(str, NULL, 16); + return val >= sym_get_range_val(prop->expr->left.sym, 16) && + val <= sym_get_range_val(prop->expr->right.sym, 16); + case S_BOOLEAN: + case S_TRISTATE: + switch (str[0]) { + case 'y': case 'Y': + return sym_tristate_within_range(sym, yes); + case 'm': case 'M': + return sym_tristate_within_range(sym, mod); + case 'n': case 'N': + return sym_tristate_within_range(sym, no); + } + return false; + default: + return false; + } +} + +bool sym_set_string_value(struct symbol *sym, const char *newval) +{ + const char *oldval; + char *val; + int size; + + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: + switch (newval[0]) { + case 'y': case 'Y': + return sym_set_tristate_value(sym, yes); + case 'm': case 'M': + return sym_set_tristate_value(sym, mod); + case 'n': case 'N': + return sym_set_tristate_value(sym, no); + } + return false; + default: + ; + } + + if (!sym_string_within_range(sym, newval)) + return false; + + if (!(sym->flags & SYMBOL_DEF_USER)) { + sym->flags |= SYMBOL_DEF_USER; + sym_set_changed(sym); + } + + oldval = sym->def[S_DEF_USER].val; + size = strlen(newval) + 1; + if (sym->type == S_HEX && (newval[0] != '0' || (newval[1] != 'x' && newval[1] != 'X'))) { + size += 2; + sym->def[S_DEF_USER].val = val = malloc(size); + *val++ = '0'; + *val++ = 'x'; + } else if (!oldval || strcmp(oldval, newval)) + sym->def[S_DEF_USER].val = val = malloc(size); + else + return true; + + strcpy(val, newval); + free((void *)oldval); + sym_clear_all_valid(); + + return true; +} + +const char *sym_get_string_value(struct symbol *sym) +{ + tristate val; + + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: + val = sym_get_tristate_value(sym); + switch (val) { + case no: + return "n"; + case mod: + return "m"; + case yes: + return "y"; + } + break; + default: + ; + } + return (const char *)sym->curr.val; +} + +bool sym_is_changable(struct symbol *sym) +{ + return sym->visible > sym->rev_dep.tri; +} + +struct symbol *sym_lookup(const char *name, int isconst) +{ + struct symbol *symbol; + const char *ptr; + char *new_name; + int hash = 0; + + if (name) { + if (name[0] && !name[1]) { + switch (name[0]) { + case 'y': return &symbol_yes; + case 'm': return &symbol_mod; + case 'n': return &symbol_no; + } + } + for (ptr = name; *ptr; ptr++) + hash += *ptr; + hash &= 0xff; + + for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) { + if (!strcmp(symbol->name, name)) { + if ((isconst && symbol->flags & SYMBOL_CONST) || + (!isconst && !(symbol->flags & SYMBOL_CONST))) + return symbol; + } + } + new_name = strdup(name); + } else { + new_name = NULL; + hash = 256; + } + + symbol = malloc(sizeof(*symbol)); + memset(symbol, 0, sizeof(*symbol)); + symbol->name = new_name; + symbol->type = S_UNKNOWN; + if (isconst) + symbol->flags |= SYMBOL_CONST; + + symbol->next = symbol_hash[hash]; + symbol_hash[hash] = symbol; + + return symbol; +} + +struct symbol *sym_find(const char *name) +{ + struct symbol *symbol = NULL; + const char *ptr; + int hash = 0; + + if (!name) + return NULL; + + if (name[0] && !name[1]) { + switch (name[0]) { + case 'y': return &symbol_yes; + case 'm': return &symbol_mod; + case 'n': return &symbol_no; + } + } + for (ptr = name; *ptr; ptr++) + hash += *ptr; + hash &= 0xff; + + for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) { + if (!strcmp(symbol->name, name) && + !(symbol->flags & SYMBOL_CONST)) + break; + } + + return symbol; +} + +#ifndef NO_REGEX +struct symbol **sym_re_search(const char *pattern) +{ + struct symbol *sym, **sym_arr = NULL; + int i, cnt, size; + regex_t re; + + cnt = size = 0; + /* Skip if empty */ + if (strlen(pattern) == 0) + return NULL; + if (regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB|REG_ICASE)) + return NULL; + + for_all_symbols(i, sym) { + if (sym->flags & SYMBOL_CONST || !sym->name) + continue; + if (regexec(&re, sym->name, 0, NULL, 0)) + continue; + if (cnt + 1 >= size) { + void *tmp = sym_arr; + size += 16; + sym_arr = realloc(sym_arr, size * sizeof(struct symbol *)); + if (!sym_arr) { + free(tmp); + return NULL; + } + } + sym_arr[cnt++] = sym; + } + if (sym_arr) + sym_arr[cnt] = NULL; + regfree(&re); + + return sym_arr; +} +#endif + + +struct symbol *sym_check_deps(struct symbol *sym); + +static struct symbol *sym_check_expr_deps(struct expr *e) +{ + struct symbol *sym; + + if (!e) + return NULL; + switch (e->type) { + case E_OR: + case E_AND: + sym = sym_check_expr_deps(e->left.expr); + if (sym) + return sym; + return sym_check_expr_deps(e->right.expr); + case E_NOT: + return sym_check_expr_deps(e->left.expr); + case E_EQUAL: + case E_UNEQUAL: + sym = sym_check_deps(e->left.sym); + if (sym) + return sym; + return sym_check_deps(e->right.sym); + case E_SYMBOL: + return sym_check_deps(e->left.sym); + default: + break; + } + printf("Oops! How to check %d?\n", e->type); + return NULL; +} + +/* return NULL when dependencies are OK */ +struct symbol *sym_check_deps(struct symbol *sym) +{ + struct symbol *sym2; + struct property *prop; + + if (sym->flags & SYMBOL_CHECK) { + fprintf(stderr, "%s:%d:error: found recursive dependency: %s", + sym->prop->file->name, sym->prop->lineno, sym->name); + return sym; + } + if (sym->flags & SYMBOL_CHECKED) + return NULL; + + sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED); + sym2 = sym_check_expr_deps(sym->rev_dep.expr); + if (sym2) + goto out; + + for (prop = sym->prop; prop; prop = prop->next) { + if (prop->type == P_CHOICE || prop->type == P_SELECT) + continue; + sym2 = sym_check_expr_deps(prop->visible.expr); + if (sym2) + goto out; + if (prop->type != P_DEFAULT || sym_is_choice(sym)) + continue; + sym2 = sym_check_expr_deps(prop->expr); + if (sym2) + goto out; + } +out: + if (sym2) + fprintf(stderr, " -> %s%s", sym->name, sym2 == sym? "\n": ""); + sym->flags &= ~SYMBOL_CHECK; + return sym2; +} + +struct property *prop_alloc(enum prop_type type, struct symbol *sym) +{ + struct property *prop; + struct property **propp; + + prop = malloc(sizeof(*prop)); + memset(prop, 0, sizeof(*prop)); + prop->type = type; + prop->sym = sym; + prop->file = current_file; + prop->lineno = zconf_lineno(); + + /* append property to the prop list of symbol */ + if (sym) { + for (propp = &sym->prop; *propp; propp = &(*propp)->next) + ; + *propp = prop; + } + + return prop; +} + +struct symbol *prop_get_symbol(struct property *prop) +{ + if (prop->expr && (prop->expr->type == E_SYMBOL || + prop->expr->type == E_CHOICE)) + return prop->expr->left.sym; + return NULL; +} + +const char *prop_get_type_name(enum prop_type type) +{ + switch (type) { + case P_PROMPT: + return "prompt"; + case P_COMMENT: + return "comment"; + case P_MENU: + return "menu"; + case P_DEFAULT: + return "default"; + case P_CHOICE: + return "choice"; + case P_SELECT: + return "select"; + case P_RANGE: + return "range"; + case P_UNKNOWN: + break; + } + return "unknown"; +} diff --git a/host/src/wrsconfig/test/h/config/auto.conf b/host/src/wrsconfig/test/h/config/auto.conf new file mode 100644 index 00000000000..fc3bca8fdfb --- /dev/null +++ b/host/src/wrsconfig/test/h/config/auto.conf @@ -0,0 +1,5 @@ +# +# Automatically generated make config: don't edit +# Wed Feb 9 17:51:06 2011 +# +CONFIG_CONFIG_STANDALONE=y diff --git a/host/src/wrsconfig/test/h/config/auto.conf.cmd b/host/src/wrsconfig/test/h/config/auto.conf.cmd new file mode 100644 index 00000000000..d343c136d69 --- /dev/null +++ b/host/src/wrsconfig/test/h/config/auto.conf.cmd @@ -0,0 +1,7 @@ +deps_config := \ + vxmicro.wrsconfig + +include/config/auto.conf: \ + $(deps_config) + +$(deps_config): ; diff --git a/host/src/wrsconfig/test/h/config/autoconf.h b/host/src/wrsconfig/test/h/config/autoconf.h new file mode 100644 index 00000000000..ac7b6f2e043 --- /dev/null +++ b/host/src/wrsconfig/test/h/config/autoconf.h @@ -0,0 +1,6 @@ +/* + * Automatically generated C config: don't edit + * Wed Feb 9 17:51:06 2011 + */ +#define AUTOCONF_INCLUDED +#define CONFIG_CONFIG_STANDALONE 1 diff --git a/host/src/wrsconfig/test/h/config/wrsconfig/config/nano/kernel.h b/host/src/wrsconfig/test/h/config/wrsconfig/config/nano/kernel.h new file mode 100644 index 00000000000..e69de29bb2d diff --git a/host/src/wrsconfig/test/h/config/wrsconfig/config/standalone.h b/host/src/wrsconfig/test/h/config/wrsconfig/config/standalone.h new file mode 100644 index 00000000000..e69de29bb2d diff --git a/host/src/wrsconfig/test/vsb.config b/host/src/wrsconfig/test/vsb.config new file mode 100644 index 00000000000..a7fe8550bed --- /dev/null +++ b/host/src/wrsconfig/test/vsb.config @@ -0,0 +1,8 @@ +# +# Automatically generated file: do not edit +# Wed Feb 9 17:51:06 2011 +# +# CONFIG_CONFIG_NANO_KERNEL is not set +CONFIG_CONFIG_STANDALONE=y +# CONFIG_CONFIG_ROUND_ROBIN is not set +# CONFIG_CONFIG_MULTIMODE is not set diff --git a/host/src/wrsconfig/test/vsb.config.old b/host/src/wrsconfig/test/vsb.config.old new file mode 100644 index 00000000000..e79e7257882 --- /dev/null +++ b/host/src/wrsconfig/test/vsb.config.old @@ -0,0 +1,5 @@ +# +# Automatically generated file: do not edit +# Wed Feb 9 17:50:13 2011 +# +CONFIG_CONFIG_NANO_KERNEL=y diff --git a/host/src/wrsconfig/test/vxmicro.wrsconfig b/host/src/wrsconfig/test/vxmicro.wrsconfig new file mode 100644 index 00000000000..64aa47063ff --- /dev/null +++ b/host/src/wrsconfig/test/vxmicro.wrsconfig @@ -0,0 +1,94 @@ +# +# Copyright (c) 2013 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors +# may be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. +# + + +#CONFIG_NANO_KERNEL Enable Nanokernel-only mode + + +#When nanokernel-only mode is set to 'n' then I have the following additional booleans: + + +# CONFIG_STANDALONE Run without a host server (if set to 'y', this forces CPU_LOAD, RUNTIME_CTRL and INSTRUMENTATION to be 'n') + +# CONFIG_CPU_LOAD Enable CPU load monitor +# CONFIG_RUNTIME_CTRL Enable task runtime Control +# CONFIG_INSTRUMENTATION Enable system instrumentation +# CONFIG_ROUND_ROBIN Enable round-robin scheduling +# CONFIG_MULTIMODE Choose SP or MP version of the VSP + + + +config CONFIG_NANO_KERNEL + bool "Nanokernel-only mode" + default y + help + Place your help text here + +config CONFIG_STANDALONE + bool "Run without a host server" + default n + depends on !CONFIG_NANO_KERNEL + help + Place your help text here + +config CONFIG_CPU_LOAD + bool "CPU load monitor" + default y + depends on !CONFIG_NANO_KERNEL && !CONFIG_STANDALONE + help + Place your help text here + +config CONFIG_RUNTIME_CTRL + bool "task runtime Control" + default y + depends on !CONFIG_NANO_KERNEL && !CONFIG_STANDALONE + help + Place your help text here + +config CONFIG_INSTRUMENTATION + bool "system instrumentation" + default y + depends on !CONFIG_NANO_KERNEL && !CONFIG_STANDALONE + help + Place your help text here + +config CONFIG_ROUND_ROBIN + bool "round-robin scheduling" + default y + depends on !CONFIG_NANO_KERNEL + help + Place your help text here + +config CONFIG_MULTIMODE + bool "MP version of the VSP" + default y + depends on !CONFIG_NANO_KERNEL + help + Place your help text here diff --git a/host/src/wrsconfig/util.c b/host/src/wrsconfig/util.c new file mode 100755 index 00000000000..f871c619b7d --- /dev/null +++ b/host/src/wrsconfig/util.c @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2002-2005 Roman Zippel + * Copyright (C) 2002-2005 Sam Ravnborg + * + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include "lkc.h" + +/* file already present in list? If not add it */ +struct file *file_lookup(const char *name) +{ + struct file *file; + + for (file = file_list; file; file = file->next) { + if (!strcmp(name, file->name)) + return file; + } + + file = malloc(sizeof(*file)); + memset(file, 0, sizeof(*file)); + file->name = strdup(name); + file->next = file_list; + file_list = file; + return file; +} + +/* write a dependency file as used by kbuild to track dependencies */ +int file_write_dep(const char *name) +{ + struct file *file; + FILE *out; + + if (!name) + name = ".kconfig.d"; + out = fopen("..config.tmp", "w"); + if (!out) + return 1; + fprintf(out, "deps_config := \\\n"); + for (file = file_list; file; file = file->next) { + if (file->next) + fprintf(out, "\t%s \\\n", file->name); + else + fprintf(out, "\t%s\n", file->name); + } + fprintf(out, "\ninclude/config/auto.conf: \\\n" + "\t$(deps_config)\n\n" + "$(deps_config): ;\n"); + fclose(out); + loc_rename("..config.tmp", name); + return 0; +} + + +/* Allocate initial growable sting */ +struct gstr str_new(void) +{ + struct gstr gs; + gs.s = malloc(sizeof(char) * 64); + gs.len = 16; + strcpy(gs.s, "\0"); + return gs; +} + +/* Allocate and assign growable string */ +struct gstr str_assign(const char *s) +{ + struct gstr gs; + gs.s = strdup(s); + gs.len = strlen(s) + 1; + return gs; +} + +/* Free storage for growable string */ +void str_free(struct gstr *gs) +{ + if (gs->s) + free(gs->s); + gs->s = NULL; + gs->len = 0; +} + +/* Append to growable string */ +void str_append(struct gstr *gs, const char *s) +{ + size_t l = strlen(gs->s) + strlen(s) + 1; + if (l > gs->len) { + gs->s = realloc(gs->s, l); + gs->len = l; + } + strcat(gs->s, s); +} + +/* Append printf formatted string to growable string */ +void str_printf(struct gstr *gs, const char *fmt, ...) +{ + va_list ap; + char s[10000]; /* big enough... */ + va_start(ap, fmt); + vsnprintf(s, sizeof(s), fmt, ap); + str_append(gs, s); + va_end(ap); +} + +/* Retrieve value of growable string */ +const char *str_get(struct gstr *gs) +{ + return gs->s; +} + diff --git a/host/src/wrsconfig/vxmicro.wrsconfig b/host/src/wrsconfig/vxmicro.wrsconfig new file mode 100644 index 00000000000..64aa47063ff --- /dev/null +++ b/host/src/wrsconfig/vxmicro.wrsconfig @@ -0,0 +1,94 @@ +# +# Copyright (c) 2013 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors +# may be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. +# + + +#CONFIG_NANO_KERNEL Enable Nanokernel-only mode + + +#When nanokernel-only mode is set to 'n' then I have the following additional booleans: + + +# CONFIG_STANDALONE Run without a host server (if set to 'y', this forces CPU_LOAD, RUNTIME_CTRL and INSTRUMENTATION to be 'n') + +# CONFIG_CPU_LOAD Enable CPU load monitor +# CONFIG_RUNTIME_CTRL Enable task runtime Control +# CONFIG_INSTRUMENTATION Enable system instrumentation +# CONFIG_ROUND_ROBIN Enable round-robin scheduling +# CONFIG_MULTIMODE Choose SP or MP version of the VSP + + + +config CONFIG_NANO_KERNEL + bool "Nanokernel-only mode" + default y + help + Place your help text here + +config CONFIG_STANDALONE + bool "Run without a host server" + default n + depends on !CONFIG_NANO_KERNEL + help + Place your help text here + +config CONFIG_CPU_LOAD + bool "CPU load monitor" + default y + depends on !CONFIG_NANO_KERNEL && !CONFIG_STANDALONE + help + Place your help text here + +config CONFIG_RUNTIME_CTRL + bool "task runtime Control" + default y + depends on !CONFIG_NANO_KERNEL && !CONFIG_STANDALONE + help + Place your help text here + +config CONFIG_INSTRUMENTATION + bool "system instrumentation" + default y + depends on !CONFIG_NANO_KERNEL && !CONFIG_STANDALONE + help + Place your help text here + +config CONFIG_ROUND_ROBIN + bool "round-robin scheduling" + default y + depends on !CONFIG_NANO_KERNEL + help + Place your help text here + +config CONFIG_MULTIMODE + bool "MP version of the VSP" + default y + depends on !CONFIG_NANO_KERNEL + help + Place your help text here diff --git a/host/src/wrsconfig/zconf.hash.c b/host/src/wrsconfig/zconf.hash.c new file mode 100755 index 00000000000..41cb7e4e4ed --- /dev/null +++ b/host/src/wrsconfig/zconf.hash.c @@ -0,0 +1,242 @@ +/* ANSI-C code produced by gperf version 3.0.1 */ +/* Command-line: gperf */ +/* Computed positions: -k'1,3' */ + +#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ + && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \ + && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \ + && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \ + && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \ + && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \ + && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \ + && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \ + && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \ + && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \ + && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \ + && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \ + && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \ + && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \ + && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \ + && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \ + && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \ + && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \ + && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \ + && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \ + && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \ + && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \ + && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126)) +/* The character set is not based on ISO-646. */ +#error "gperf generated tables don't work with this execution character set. Please report a bug to ." +#endif + +struct kconf_id; +/* maximum key range = 45, duplicates = 0 */ + +#ifdef __GNUC__ +__inline +#else +#ifdef __cplusplus +inline +#endif +#endif +static unsigned int +kconf_id_hash (register const char *str, register unsigned int len) +{ + static unsigned char asso_values[] = + { + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 25, 30, 15, + 0, 15, 0, 47, 5, 15, 47, 47, 30, 20, + 5, 0, 25, 15, 0, 0, 10, 35, 47, 47, + 5, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47 + }; + register int hval = len; + + switch (hval) + { + default: + hval += asso_values[(unsigned char)str[2]]; + /*FALLTHROUGH*/ + case 2: + case 1: + hval += asso_values[(unsigned char)str[0]]; + break; + } + return hval; +} + +struct kconf_id_strings_t + { + char kconf_id_strings_str2[sizeof("on")]; + char kconf_id_strings_str6[sizeof("string")]; + char kconf_id_strings_str7[sizeof("default")]; + char kconf_id_strings_str8[sizeof("def_bool")]; + char kconf_id_strings_str10[sizeof("range")]; + char kconf_id_strings_str11[sizeof("def_boolean")]; + char kconf_id_strings_str12[sizeof("def_tristate")]; + char kconf_id_strings_str13[sizeof("hex")]; + char kconf_id_strings_str14[sizeof("defconfig_list")]; + char kconf_id_strings_str16[sizeof("option")]; + char kconf_id_strings_str17[sizeof("if")]; + char kconf_id_strings_str18[sizeof("optional")]; + char kconf_id_strings_str20[sizeof("endif")]; + char kconf_id_strings_str21[sizeof("choice")]; + char kconf_id_strings_str22[sizeof("endmenu")]; + char kconf_id_strings_str23[sizeof("requires")]; + char kconf_id_strings_str24[sizeof("endchoice")]; + char kconf_id_strings_str26[sizeof("config")]; + char kconf_id_strings_str27[sizeof("modules")]; + char kconf_id_strings_str28[sizeof("int")]; + char kconf_id_strings_str29[sizeof("menu")]; + char kconf_id_strings_str31[sizeof("prompt")]; + char kconf_id_strings_str32[sizeof("depends")]; + char kconf_id_strings_str33[sizeof("tristate")]; + char kconf_id_strings_str34[sizeof("bool")]; + char kconf_id_strings_str35[sizeof("menuconfig")]; + char kconf_id_strings_str36[sizeof("select")]; + char kconf_id_strings_str37[sizeof("boolean")]; + char kconf_id_strings_str39[sizeof("help")]; + char kconf_id_strings_str41[sizeof("source")]; + char kconf_id_strings_str42[sizeof("comment")]; + char kconf_id_strings_str43[sizeof("mainmenu")]; + char kconf_id_strings_str46[sizeof("enable")]; + }; +static struct kconf_id_strings_t kconf_id_strings_contents = + { + "on", + "string", + "default", + "def_bool", + "range", + "def_boolean", + "def_tristate", + "hex", + "defconfig_list", + "option", + "if", + "optional", + "endif", + "choice", + "endmenu", + "requires", + "endchoice", + "config", + "modules", + "int", + "menu", + "prompt", + "depends", + "tristate", + "bool", + "menuconfig", + "select", + "boolean", + "help", + "source", + "comment", + "mainmenu", + "enable" + }; +#define kconf_id_strings ((const char *) &kconf_id_strings_contents) +#ifdef __GNUC__ +__inline +#endif +struct kconf_id * +kconf_id_lookup (register const char *str, register unsigned int len) +{ + enum + { + TOTAL_KEYWORDS = 33, + MIN_WORD_LENGTH = 2, + MAX_WORD_LENGTH = 14, + MIN_HASH_VALUE = 2, + MAX_HASH_VALUE = 46 + }; + + static struct kconf_id wordlist[] = + { + {-1}, {-1}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str2, T_ON, TF_PARAM}, + {-1}, {-1}, {-1}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str6, T_TYPE, TF_COMMAND, S_STRING}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str7, T_DEFAULT, TF_COMMAND, S_UNKNOWN}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str8, T_DEFAULT, TF_COMMAND, S_BOOLEAN}, + {-1}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str10, T_RANGE, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str11, T_DEFAULT, TF_COMMAND, S_BOOLEAN}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str12, T_DEFAULT, TF_COMMAND, S_TRISTATE}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str13, T_TYPE, TF_COMMAND, S_HEX}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str14, T_OPT_DEFCONFIG_LIST,TF_OPTION}, + {-1}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str16, T_OPTION, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str17, T_IF, TF_COMMAND|TF_PARAM}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str18, T_OPTIONAL, TF_COMMAND}, + {-1}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str20, T_ENDIF, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str21, T_CHOICE, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str22, T_ENDMENU, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str23, T_REQUIRES, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str24, T_ENDCHOICE, TF_COMMAND}, + {-1}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str26, T_CONFIG, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str27, T_OPT_MODULES, TF_OPTION}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str28, T_TYPE, TF_COMMAND, S_INT}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str29, T_MENU, TF_COMMAND}, + {-1}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str31, T_PROMPT, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str32, T_DEPENDS, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str33, T_TYPE, TF_COMMAND, S_TRISTATE}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str34, T_TYPE, TF_COMMAND, S_BOOLEAN}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str35, T_MENUCONFIG, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str36, T_SELECT, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str37, T_TYPE, TF_COMMAND, S_BOOLEAN}, + {-1}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str39, T_HELP, TF_COMMAND}, + {-1}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str41, T_SOURCE, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str42, T_COMMENT, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str43, T_MAINMENU, TF_COMMAND}, + {-1}, {-1}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str46, T_SELECT, TF_COMMAND} + }; + + if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) + { + register int key = kconf_id_hash (str, len); + + if (key <= MAX_HASH_VALUE && key >= 0) + { + register int o = wordlist[key].name; + if (o >= 0) + { + register const char *s = o + kconf_id_strings; + + if (*str == *s && !strncmp (str + 1, s + 1, len - 1) && s[len] == '\0') + return &wordlist[key]; + } + } + } + return 0; +} + diff --git a/host/src/wrsconfig/zconf.tab.c b/host/src/wrsconfig/zconf.tab.c new file mode 100755 index 00000000000..544ddf572e5 --- /dev/null +++ b/host/src/wrsconfig/zconf.tab.c @@ -0,0 +1,2348 @@ +/* A Bison parser, made by GNU Bison 2.1. */ + +/* Skeleton parser for Yacc-like parsing with Bison, + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. */ + +/* As a special exception, when this file is copied by Bison into a + Bison output file, you may use that output file without restriction. + This special exception was added by the Free Software Foundation + in version 1.24 of Bison. */ + +/* Written by Richard Stallman by simplifying the original so called + ``semantic'' parser. */ + +/* All symbols defined below should begin with yy or YY, to avoid + infringing on user name space. This should be done even for local + variables, as they might otherwise be expanded by user macros. + There are some unavoidable exceptions within include files to + define necessary library symbols; they are noted "INFRINGES ON + USER NAME SPACE" below. */ + +/* Identify Bison output. */ +#define YYBISON 1 + +/* Bison version. */ +#define YYBISON_VERSION "2.1" + +/* Skeleton name. */ +#define YYSKELETON_NAME "yacc.c" + +/* Pure parsers. */ +#define YYPURE 0 + +/* Using locations. */ +#define YYLSP_NEEDED 0 + +/* Substitute the variable and function names. */ +#define yyparse zconfparse +#define yylex zconflex +#define yyerror zconferror +#define yylval zconflval +#define yychar zconfchar +#define yydebug zconfdebug +#define yynerrs zconfnerrs + + +/* Tokens. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum yytokentype { + T_MAINMENU = 258, + T_MENU = 259, + T_ENDMENU = 260, + T_SOURCE = 261, + T_CHOICE = 262, + T_ENDCHOICE = 263, + T_COMMENT = 264, + T_CONFIG = 265, + T_MENUCONFIG = 266, + T_HELP = 267, + T_HELPTEXT = 268, + T_IF = 269, + T_ENDIF = 270, + T_DEPENDS = 271, + T_REQUIRES = 272, + T_OPTIONAL = 273, + T_PROMPT = 274, + T_TYPE = 275, + T_DEFAULT = 276, + T_SELECT = 277, + T_RANGE = 278, + T_OPTION = 279, + T_ON = 280, + T_WORD = 281, + T_WORD_QUOTE = 282, + T_UNEQUAL = 283, + T_CLOSE_PAREN = 284, + T_OPEN_PAREN = 285, + T_EOL = 286, + T_OR = 287, + T_AND = 288, + T_EQUAL = 289, + T_NOT = 290 + }; +#endif +/* Tokens. */ +#define T_MAINMENU 258 +#define T_MENU 259 +#define T_ENDMENU 260 +#define T_SOURCE 261 +#define T_CHOICE 262 +#define T_ENDCHOICE 263 +#define T_COMMENT 264 +#define T_CONFIG 265 +#define T_MENUCONFIG 266 +#define T_HELP 267 +#define T_HELPTEXT 268 +#define T_IF 269 +#define T_ENDIF 270 +#define T_DEPENDS 271 +#define T_REQUIRES 272 +#define T_OPTIONAL 273 +#define T_PROMPT 274 +#define T_TYPE 275 +#define T_DEFAULT 276 +#define T_SELECT 277 +#define T_RANGE 278 +#define T_OPTION 279 +#define T_ON 280 +#define T_WORD 281 +#define T_WORD_QUOTE 282 +#define T_UNEQUAL 283 +#define T_CLOSE_PAREN 284 +#define T_OPEN_PAREN 285 +#define T_EOL 286 +#define T_OR 287 +#define T_AND 288 +#define T_EQUAL 289 +#define T_NOT 290 + + + + +/* Copy the first part of user declarations. */ + + +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define LKC_DIRECT_LINK +#include "lkc.h" + +#include "zconf.hash.c" + +#define printd(mask, fmt...) if (cdebug & (mask)) printf(fmt) + +#define PRINTD 0x0001 +#define DEBUG_PARSE 0x0002 + +int cdebug = PRINTD; + +extern int zconflex(void); +static void zconfprint(const char *err, ...); +static void zconf_error(const char *err, ...); +static void zconferror(const char *err); +static bool zconf_endtoken(struct kconf_id *id, int starttoken, int endtoken); + +struct symbol *symbol_hash[257]; + +static struct menu *current_menu, *current_entry; + +#define YYDEBUG 0 +#if YYDEBUG +#define YYERROR_VERBOSE +#endif + + +/* Enabling traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif + +/* Enabling verbose error messages. */ +#ifdef YYERROR_VERBOSE +# undef YYERROR_VERBOSE +# define YYERROR_VERBOSE 1 +#else +# define YYERROR_VERBOSE 0 +#endif + +/* Enabling the token table. */ +#ifndef YYTOKEN_TABLE +# define YYTOKEN_TABLE 0 +#endif + +#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED) + +typedef union YYSTYPE { + char *string; + struct file *file; + struct symbol *symbol; + struct expr *expr; + struct menu *menu; + struct kconf_id *id; +} YYSTYPE; +/* Line 196 of yacc.c. */ + +# define yystype YYSTYPE /* obsolescent; will be withdrawn */ +# define YYSTYPE_IS_DECLARED 1 +# define YYSTYPE_IS_TRIVIAL 1 +#endif + + + +/* Copy the second part of user declarations. */ + + +/* Line 219 of yacc.c. */ + + +#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__) +# define YYSIZE_T __SIZE_TYPE__ +#endif +#if ! defined (YYSIZE_T) && defined (size_t) +# define YYSIZE_T size_t +#endif +#if ! defined (YYSIZE_T) && (defined (__STDC__) || defined (__cplusplus)) +# include /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +#endif +#if ! defined (YYSIZE_T) +# define YYSIZE_T unsigned int +#endif + +#ifndef YY_ +# if YYENABLE_NLS +# if ENABLE_NLS +# include /* INFRINGES ON USER NAME SPACE */ +# define YY_(msgid) dgettext ("bison-runtime", msgid) +# endif +# endif +# ifndef YY_ +# define YY_(msgid) msgid +# endif +#endif + +#if ! defined (yyoverflow) || YYERROR_VERBOSE + +/* The parser invokes alloca or malloc; define the necessary symbols. */ + +# ifdef YYSTACK_USE_ALLOCA +# if YYSTACK_USE_ALLOCA +# ifdef __GNUC__ +# define YYSTACK_ALLOC __builtin_alloca +# else +# define YYSTACK_ALLOC alloca +# if defined (__STDC__) || defined (__cplusplus) +# include /* INFRINGES ON USER NAME SPACE */ +# define YYINCLUDED_STDLIB_H +# endif +# endif +# endif +# endif + +# ifdef YYSTACK_ALLOC + /* Pacify GCC's `empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) +# ifndef YYSTACK_ALLOC_MAXIMUM + /* The OS might guarantee only one guard page at the bottom of the stack, + and a page size can be as small as 4096 bytes. So we cannot safely + invoke alloca (N) if N exceeds 4096. Use a slightly smaller number + to allow for a few compiler-allocated temporary stack slots. */ +# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2005 */ +# endif +# else +# define YYSTACK_ALLOC YYMALLOC +# define YYSTACK_FREE YYFREE +# ifndef YYSTACK_ALLOC_MAXIMUM +# define YYSTACK_ALLOC_MAXIMUM ((YYSIZE_T) -1) +# endif +# ifdef __cplusplus +extern "C" { +# endif +# ifndef YYMALLOC +# define YYMALLOC malloc +# if (! defined (malloc) && ! defined (YYINCLUDED_STDLIB_H) \ + && (defined (__STDC__) || defined (__cplusplus))) +void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# ifndef YYFREE +# define YYFREE free +# if (! defined (free) && ! defined (YYINCLUDED_STDLIB_H) \ + && (defined (__STDC__) || defined (__cplusplus))) +void free (void *); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# ifdef __cplusplus +} +# endif +# endif +#endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */ + + +#if (! defined (yyoverflow) \ + && (! defined (__cplusplus) \ + || (defined (YYSTYPE_IS_TRIVIAL) && YYSTYPE_IS_TRIVIAL))) + +/* A type that is properly aligned for any stack member. */ +union yyalloc +{ + short int yyss; + YYSTYPE yyvs; + }; + +/* The size of the maximum gap between one aligned stack and the next. */ +# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) + +/* The size of an array large to enough to hold all stacks, each with + N elements. */ +# define YYSTACK_BYTES(N) \ + ((N) * (sizeof (short int) + sizeof (YYSTYPE)) \ + + YYSTACK_GAP_MAXIMUM) + +/* Copy COUNT objects from FROM to TO. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if defined (__GNUC__) && 1 < __GNUC__ +# define YYCOPY(To, From, Count) \ + __builtin_memcpy (To, From, (Count) * sizeof (*(From))) +# else +# define YYCOPY(To, From, Count) \ + do \ + { \ + YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (To)[yyi] = (From)[yyi]; \ + } \ + while (0) +# endif +# endif + +/* Relocate STACK from its old location to the new one. The + local variables YYSIZE and YYSTACKSIZE give the old and new number of + elements in the stack, and YYPTR gives the new location of the + stack. Advance YYPTR to a properly aligned location for the next + stack. */ +# define YYSTACK_RELOCATE(Stack) \ + do \ + { \ + YYSIZE_T yynewbytes; \ + YYCOPY (&yyptr->Stack, Stack, yysize); \ + Stack = &yyptr->Stack; \ + yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ + yyptr += yynewbytes / sizeof (*yyptr); \ + } \ + while (0) + +#endif + +#if defined (__STDC__) || defined (__cplusplus) + typedef signed char yysigned_char; +#else + typedef short int yysigned_char; +#endif + +/* YYFINAL -- State number of the termination state. */ +#define YYFINAL 3 +/* YYLAST -- Last index in YYTABLE. */ +#define YYLAST 275 + +/* YYNTOKENS -- Number of terminals. */ +#define YYNTOKENS 36 +/* YYNNTS -- Number of nonterminals. */ +#define YYNNTS 45 +/* YYNRULES -- Number of rules. */ +#define YYNRULES 110 +/* YYNRULES -- Number of states. */ +#define YYNSTATES 183 + +/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ +#define YYUNDEFTOK 2 +#define YYMAXUTOK 290 + +#define YYTRANSLATE(YYX) \ + ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) + +/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ +static const unsigned char yytranslate[] = +{ + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, + 35 +}; + +#if YYDEBUG +/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in + YYRHS. */ +static const unsigned short int yyprhs[] = +{ + 0, 0, 3, 5, 6, 9, 12, 15, 20, 23, + 28, 33, 37, 39, 41, 43, 45, 47, 49, 51, + 53, 55, 57, 59, 61, 63, 67, 70, 74, 77, + 81, 84, 85, 88, 91, 94, 97, 100, 103, 107, + 112, 117, 122, 128, 132, 133, 137, 138, 141, 144, + 147, 149, 153, 154, 157, 160, 163, 166, 169, 174, + 178, 181, 186, 187, 190, 194, 196, 200, 201, 204, + 207, 210, 214, 217, 219, 223, 224, 227, 230, 233, + 237, 241, 244, 247, 250, 251, 254, 257, 260, 265, + 269, 273, 274, 277, 279, 281, 284, 287, 290, 292, + 295, 296, 299, 301, 305, 309, 313, 316, 320, 324, + 326 +}; + +/* YYRHS -- A `-1'-separated list of the rules' RHS. */ +static const yysigned_char yyrhs[] = +{ + 37, 0, -1, 38, -1, -1, 38, 40, -1, 38, + 54, -1, 38, 65, -1, 38, 3, 75, 77, -1, + 38, 76, -1, 38, 26, 1, 31, -1, 38, 39, + 1, 31, -1, 38, 1, 31, -1, 16, -1, 19, + -1, 20, -1, 22, -1, 18, -1, 23, -1, 21, + -1, 31, -1, 60, -1, 69, -1, 43, -1, 45, + -1, 67, -1, 26, 1, 31, -1, 1, 31, -1, + 10, 26, 31, -1, 42, 46, -1, 11, 26, 31, + -1, 44, 46, -1, -1, 46, 47, -1, 46, 48, + -1, 46, 73, -1, 46, 71, -1, 46, 41, -1, + 46, 31, -1, 20, 74, 31, -1, 19, 75, 78, + 31, -1, 21, 79, 78, 31, -1, 22, 26, 78, + 31, -1, 23, 80, 80, 78, 31, -1, 24, 49, + 31, -1, -1, 49, 26, 50, -1, -1, 34, 75, + -1, 7, 31, -1, 51, 55, -1, 76, -1, 52, + 57, 53, -1, -1, 55, 56, -1, 55, 73, -1, + 55, 71, -1, 55, 31, -1, 55, 41, -1, 19, + 75, 78, 31, -1, 20, 74, 31, -1, 18, 31, + -1, 21, 26, 78, 31, -1, -1, 57, 40, -1, + 14, 79, 77, -1, 76, -1, 58, 61, 59, -1, + -1, 61, 40, -1, 61, 65, -1, 61, 54, -1, + 4, 75, 31, -1, 62, 72, -1, 76, -1, 63, + 66, 64, -1, -1, 66, 40, -1, 66, 65, -1, + 66, 54, -1, 6, 75, 31, -1, 9, 75, 31, + -1, 68, 72, -1, 12, 31, -1, 70, 13, -1, + -1, 72, 73, -1, 72, 31, -1, 72, 41, -1, + 16, 25, 79, 31, -1, 16, 79, 31, -1, 17, + 79, 31, -1, -1, 75, 78, -1, 26, -1, 27, + -1, 5, 31, -1, 8, 31, -1, 15, 31, -1, + 31, -1, 77, 31, -1, -1, 14, 79, -1, 80, + -1, 80, 34, 80, -1, 80, 28, 80, -1, 30, + 79, 29, -1, 35, 79, -1, 79, 32, 79, -1, + 79, 33, 79, -1, 26, -1, 27, -1 +}; + +/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ +static const unsigned short int yyrline[] = +{ + 0, 105, 105, 107, 109, 110, 111, 112, 113, 114, + 115, 119, 123, 123, 123, 123, 123, 123, 123, 127, + 128, 129, 130, 131, 132, 136, 137, 143, 151, 157, + 165, 175, 177, 178, 179, 180, 181, 182, 185, 193, + 199, 209, 215, 221, 224, 226, 237, 238, 243, 252, + 257, 265, 268, 270, 271, 272, 273, 274, 277, 283, + 294, 300, 310, 312, 317, 325, 333, 336, 338, 339, + 340, 345, 352, 357, 365, 368, 370, 371, 372, 375, + 383, 390, 397, 403, 410, 412, 413, 414, 417, 422, + 427, 435, 437, 442, 443, 446, 447, 448, 452, 453, + 456, 457, 460, 461, 462, 463, 464, 465, 466, 469, + 470 +}; +#endif + +#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE +/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. + First, the terminals, then, starting at YYNTOKENS, nonterminals. */ +static const char *const yytname[] = +{ + "$end", "error", "$undefined", "T_MAINMENU", "T_MENU", "T_ENDMENU", + "T_SOURCE", "T_CHOICE", "T_ENDCHOICE", "T_COMMENT", "T_CONFIG", + "T_MENUCONFIG", "T_HELP", "T_HELPTEXT", "T_IF", "T_ENDIF", "T_DEPENDS", + "T_REQUIRES", "T_OPTIONAL", "T_PROMPT", "T_TYPE", "T_DEFAULT", + "T_SELECT", "T_RANGE", "T_OPTION", "T_ON", "T_WORD", "T_WORD_QUOTE", + "T_UNEQUAL", "T_CLOSE_PAREN", "T_OPEN_PAREN", "T_EOL", "T_OR", "T_AND", + "T_EQUAL", "T_NOT", "$accept", "input", "stmt_list", "option_name", + "common_stmt", "option_error", "config_entry_start", "config_stmt", + "menuconfig_entry_start", "menuconfig_stmt", "config_option_list", + "config_option", "symbol_option", "symbol_option_list", + "symbol_option_arg", "choice", "choice_entry", "choice_end", + "choice_stmt", "choice_option_list", "choice_option", "choice_block", + "if_entry", "if_end", "if_stmt", "if_block", "menu", "menu_entry", + "menu_end", "menu_stmt", "menu_block", "source_stmt", "comment", + "comment_stmt", "help_start", "help", "depends_list", "depends", + "prompt_stmt_opt", "prompt", "end", "nl", "if_expr", "expr", "symbol", 0 +}; +#endif + +# ifdef YYPRINT +/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to + token YYLEX-NUM. */ +static const unsigned short int yytoknum[] = +{ + 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, + 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, + 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 289, 290 +}; +# endif + +/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +static const unsigned char yyr1[] = +{ + 0, 36, 37, 38, 38, 38, 38, 38, 38, 38, + 38, 38, 39, 39, 39, 39, 39, 39, 39, 40, + 40, 40, 40, 40, 40, 41, 41, 42, 43, 44, + 45, 46, 46, 46, 46, 46, 46, 46, 47, 47, + 47, 47, 47, 48, 49, 49, 50, 50, 51, 52, + 53, 54, 55, 55, 55, 55, 55, 55, 56, 56, + 56, 56, 57, 57, 58, 59, 60, 61, 61, 61, + 61, 62, 63, 64, 65, 66, 66, 66, 66, 67, + 68, 69, 70, 71, 72, 72, 72, 72, 73, 73, + 73, 74, 74, 75, 75, 76, 76, 76, 77, 77, + 78, 78, 79, 79, 79, 79, 79, 79, 79, 80, + 80 +}; + +/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ +static const unsigned char yyr2[] = +{ + 0, 2, 1, 0, 2, 2, 2, 4, 2, 4, + 4, 3, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 3, 2, 3, 2, 3, + 2, 0, 2, 2, 2, 2, 2, 2, 3, 4, + 4, 4, 5, 3, 0, 3, 0, 2, 2, 2, + 1, 3, 0, 2, 2, 2, 2, 2, 4, 3, + 2, 4, 0, 2, 3, 1, 3, 0, 2, 2, + 2, 3, 2, 1, 3, 0, 2, 2, 2, 3, + 3, 2, 2, 2, 0, 2, 2, 2, 4, 3, + 3, 0, 2, 1, 1, 2, 2, 2, 1, 2, + 0, 2, 1, 3, 3, 3, 2, 3, 3, 1, + 1 +}; + +/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state + STATE-NUM when YYTABLE doesn't specify something else to do. Zero + means the default is an error. */ +static const unsigned char yydefact[] = +{ + 3, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 12, 16, 13, 14, + 18, 15, 17, 0, 19, 0, 4, 31, 22, 31, + 23, 52, 62, 5, 67, 20, 84, 75, 6, 24, + 84, 21, 8, 11, 93, 94, 0, 0, 95, 0, + 48, 96, 0, 0, 0, 109, 110, 0, 0, 0, + 102, 97, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 98, 7, 71, 79, 80, 27, 29, 0, + 106, 0, 0, 64, 0, 0, 9, 10, 0, 0, + 0, 0, 0, 91, 0, 0, 0, 44, 0, 37, + 36, 32, 33, 0, 35, 34, 0, 0, 91, 0, + 56, 57, 53, 55, 54, 63, 51, 50, 68, 70, + 66, 69, 65, 86, 87, 85, 76, 78, 74, 77, + 73, 99, 105, 107, 108, 104, 103, 26, 82, 0, + 0, 0, 100, 0, 100, 100, 100, 0, 0, 0, + 83, 60, 100, 0, 100, 0, 89, 90, 0, 0, + 38, 92, 0, 0, 100, 46, 43, 25, 0, 59, + 0, 88, 101, 39, 40, 41, 0, 0, 45, 58, + 61, 42, 47 +}; + +/* YYDEFGOTO[NTERM-NUM]. */ +static const short int yydefgoto[] = +{ + -1, 1, 2, 25, 26, 100, 27, 28, 29, 30, + 64, 101, 102, 148, 178, 31, 32, 116, 33, 66, + 112, 67, 34, 120, 35, 68, 36, 37, 128, 38, + 70, 39, 40, 41, 103, 104, 69, 105, 143, 144, + 42, 73, 159, 59, 60 +}; + +/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ +#define YYPACT_NINF -135 +static const short int yypact[] = +{ + -135, 2, 170, -135, -14, 56, 56, -8, 56, 24, + 67, 56, 7, 14, 62, 97, -135, -135, -135, -135, + -135, -135, -135, 156, -135, 166, -135, -135, -135, -135, + -135, -135, -135, -135, -135, -135, -135, -135, -135, -135, + -135, -135, -135, -135, -135, -135, 138, 151, -135, 152, + -135, -135, 163, 167, 176, -135, -135, 62, 62, 185, + -19, -135, 188, 190, 42, 103, 194, 85, 70, 222, + 70, 132, -135, 191, -135, -135, -135, -135, -135, 127, + -135, 62, 62, 191, 104, 104, -135, -135, 193, 203, + 9, 62, 56, 56, 62, 161, 104, -135, 196, -135, + -135, -135, -135, 233, -135, -135, 204, 56, 56, 221, + -135, -135, -135, -135, -135, -135, -135, -135, -135, -135, + -135, -135, -135, -135, -135, -135, -135, -135, -135, -135, + -135, -135, -135, 219, -135, -135, -135, -135, -135, 62, + 209, 212, 240, 224, 240, -1, 240, 104, 41, 225, + -135, -135, 240, 226, 240, 218, -135, -135, 62, 227, + -135, -135, 228, 229, 240, 230, -135, -135, 231, -135, + 232, -135, 112, -135, -135, -135, 234, 56, -135, -135, + -135, -135, -135 +}; + +/* YYPGOTO[NTERM-NUM]. */ +static const short int yypgoto[] = +{ + -135, -135, -135, -135, 94, -45, -135, -135, -135, -135, + 237, -135, -135, -135, -135, -135, -135, -135, -54, -135, + -135, -135, -135, -135, -135, -135, -135, -135, -135, 1, + -135, -135, -135, -135, -135, 195, 235, -44, 159, -5, + 98, 210, -134, -53, -77 +}; + +/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule which + number is the opposite. If zero, do what YYDEFACT says. + If YYTABLE_NINF, syntax error. */ +#define YYTABLE_NINF -82 +static const short int yytable[] = +{ + 46, 47, 3, 49, 79, 80, 52, 135, 136, 84, + 161, 162, 163, 158, 119, 85, 127, 43, 168, 147, + 170, 111, 114, 48, 124, 125, 124, 125, 133, 134, + 176, 81, 82, 53, 139, 55, 56, 140, 141, 57, + 54, 145, -28, 88, 58, -28, -28, -28, -28, -28, + -28, -28, -28, -28, 89, 50, -28, -28, 90, 91, + -28, 92, 93, 94, 95, 96, 97, 165, 98, 121, + 164, 129, 166, 99, 6, 7, 8, 9, 10, 11, + 12, 13, 44, 45, 14, 15, 155, 142, 55, 56, + 7, 8, 57, 10, 11, 12, 13, 58, 51, 14, + 15, 24, 152, -30, 88, 172, -30, -30, -30, -30, + -30, -30, -30, -30, -30, 89, 24, -30, -30, 90, + 91, -30, 92, 93, 94, 95, 96, 97, 61, 98, + 55, 56, -81, 88, 99, -81, -81, -81, -81, -81, + -81, -81, -81, -81, 81, 82, -81, -81, 90, 91, + -81, -81, -81, -81, -81, -81, 132, 62, 98, 81, + 82, 115, 118, 123, 126, 117, 122, 63, 130, 72, + -2, 4, 182, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 74, 75, 14, 15, 16, 146, 17, 18, + 19, 20, 21, 22, 76, 88, 23, 149, 77, -49, + -49, 24, -49, -49, -49, -49, 89, 78, -49, -49, + 90, 91, 106, 107, 108, 109, 72, 81, 82, 86, + 98, 87, 131, 88, 137, 110, -72, -72, -72, -72, + -72, -72, -72, -72, 138, 151, -72, -72, 90, 91, + 156, 81, 82, 157, 81, 82, 150, 154, 98, 171, + 81, 82, 82, 123, 158, 160, 167, 169, 173, 174, + 175, 113, 179, 180, 177, 181, 65, 153, 0, 83, + 0, 0, 0, 0, 0, 71 +}; + +static const short int yycheck[] = +{ + 5, 6, 0, 8, 57, 58, 11, 84, 85, 28, + 144, 145, 146, 14, 68, 34, 70, 31, 152, 96, + 154, 66, 66, 31, 69, 69, 71, 71, 81, 82, + 164, 32, 33, 26, 25, 26, 27, 90, 91, 30, + 26, 94, 0, 1, 35, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 31, 14, 15, 16, 17, + 18, 19, 20, 21, 22, 23, 24, 26, 26, 68, + 147, 70, 31, 31, 4, 5, 6, 7, 8, 9, + 10, 11, 26, 27, 14, 15, 139, 92, 26, 27, + 5, 6, 30, 8, 9, 10, 11, 35, 31, 14, + 15, 31, 107, 0, 1, 158, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 31, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 31, 26, + 26, 27, 0, 1, 31, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 32, 33, 14, 15, 16, 17, + 18, 19, 20, 21, 22, 23, 29, 1, 26, 32, + 33, 67, 68, 31, 70, 67, 68, 1, 70, 31, + 0, 1, 177, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 31, 31, 14, 15, 16, 26, 18, 19, + 20, 21, 22, 23, 31, 1, 26, 1, 31, 5, + 6, 31, 8, 9, 10, 11, 12, 31, 14, 15, + 16, 17, 18, 19, 20, 21, 31, 32, 33, 31, + 26, 31, 31, 1, 31, 31, 4, 5, 6, 7, + 8, 9, 10, 11, 31, 31, 14, 15, 16, 17, + 31, 32, 33, 31, 32, 33, 13, 26, 26, 31, + 32, 33, 33, 31, 14, 31, 31, 31, 31, 31, + 31, 66, 31, 31, 34, 31, 29, 108, -1, 59, + -1, -1, -1, -1, -1, 40 +}; + +/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing + symbol of state STATE-NUM. */ +static const unsigned char yystos[] = +{ + 0, 37, 38, 0, 1, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 14, 15, 16, 18, 19, 20, + 21, 22, 23, 26, 31, 39, 40, 42, 43, 44, + 45, 51, 52, 54, 58, 60, 62, 63, 65, 67, + 68, 69, 76, 31, 26, 27, 75, 75, 31, 75, + 31, 31, 75, 26, 26, 26, 27, 30, 35, 79, + 80, 31, 1, 1, 46, 46, 55, 57, 61, 72, + 66, 72, 31, 77, 31, 31, 31, 31, 31, 79, + 79, 32, 33, 77, 28, 34, 31, 31, 1, 12, + 16, 17, 19, 20, 21, 22, 23, 24, 26, 31, + 41, 47, 48, 70, 71, 73, 18, 19, 20, 21, + 31, 41, 56, 71, 73, 40, 53, 76, 40, 54, + 59, 65, 76, 31, 41, 73, 40, 54, 64, 65, + 76, 31, 29, 79, 79, 80, 80, 31, 31, 25, + 79, 79, 75, 74, 75, 79, 26, 80, 49, 1, + 13, 31, 75, 74, 26, 79, 31, 31, 14, 78, + 31, 78, 78, 78, 80, 26, 31, 31, 78, 31, + 78, 31, 79, 31, 31, 31, 78, 34, 50, 31, + 31, 31, 75 +}; + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY (-2) +#define YYEOF 0 + +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrorlab + + +/* Like YYERROR except do call yyerror. This remains here temporarily + to ease the transition to the new meaning of YYERROR, for GCC. + Once GCC version 2 has supplanted version 1, this can go. */ + +#define YYFAIL goto yyerrlab + +#define YYRECOVERING() (!!yyerrstatus) + +#define YYBACKUP(Token, Value) \ +do \ + if (yychar == YYEMPTY && yylen == 1) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + yytoken = YYTRANSLATE (yychar); \ + YYPOPSTACK; \ + goto yybackup; \ + } \ + else \ + { \ + yyerror (YY_("syntax error: cannot back up")); \ + YYERROR; \ + } \ +while (0) + + +#define YYTERROR 1 +#define YYERRCODE 256 + + +/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. + If N is 0, then set CURRENT to the empty location which ends + the previous symbol: RHS[0] (always defined). */ + +#define YYRHSLOC(Rhs, K) ((Rhs)[K]) +#ifndef YYLLOC_DEFAULT +# define YYLLOC_DEFAULT(Current, Rhs, N) \ + do \ + if (N) \ + { \ + (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ + (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ + (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ + (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ + } \ + else \ + { \ + (Current).first_line = (Current).last_line = \ + YYRHSLOC (Rhs, 0).last_line; \ + (Current).first_column = (Current).last_column = \ + YYRHSLOC (Rhs, 0).last_column; \ + } \ + while (0) +#endif + + +/* YY_LOCATION_PRINT -- Print the location on the stream. + This macro was not mandated originally: define only if we know + we won't break user code: when these are the locations we know. */ + +#ifndef YY_LOCATION_PRINT +# if YYLTYPE_IS_TRIVIAL +# define YY_LOCATION_PRINT(File, Loc) \ + fprintf (File, "%d.%d-%d.%d", \ + (Loc).first_line, (Loc).first_column, \ + (Loc).last_line, (Loc).last_column) +# else +# define YY_LOCATION_PRINT(File, Loc) ((void) 0) +# endif +#endif + + +/* YYLEX -- calling `yylex' with the right arguments. */ + +#ifdef YYLEX_PARAM +# define YYLEX yylex (YYLEX_PARAM) +#else +# define YYLEX yylex () +#endif + +/* Enable debugging if requested. */ +#if YYDEBUG + +# ifndef YYFPRINTF +# include /* INFRINGES ON USER NAME SPACE */ +# define YYFPRINTF fprintf +# endif + +# define YYDPRINTF(Args) \ +do { \ + if (yydebug) \ + YYFPRINTF Args; \ +} while (0) + +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ +do { \ + if (yydebug) \ + { \ + YYFPRINTF (stderr, "%s ", Title); \ + yysymprint (stderr, \ + Type, Value); \ + YYFPRINTF (stderr, "\n"); \ + } \ +} while (0) + +/*------------------------------------------------------------------. +| yy_stack_print -- Print the state stack from its BOTTOM up to its | +| TOP (included). | +`------------------------------------------------------------------*/ + +#if defined (__STDC__) || defined (__cplusplus) +static void +yy_stack_print (short int *bottom, short int *top) +#else +static void +yy_stack_print (bottom, top) + short int *bottom; + short int *top; +#endif +{ + YYFPRINTF (stderr, "Stack now"); + for (/* Nothing. */; bottom <= top; ++bottom) + YYFPRINTF (stderr, " %d", *bottom); + YYFPRINTF (stderr, "\n"); +} + +# define YY_STACK_PRINT(Bottom, Top) \ +do { \ + if (yydebug) \ + yy_stack_print ((Bottom), (Top)); \ +} while (0) + + +/*------------------------------------------------. +| Report that the YYRULE is going to be reduced. | +`------------------------------------------------*/ + +#if defined (__STDC__) || defined (__cplusplus) +static void +yy_reduce_print (int yyrule) +#else +static void +yy_reduce_print (yyrule) + int yyrule; +#endif +{ + int yyi; + unsigned long int yylno = yyrline[yyrule]; + YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu), ", + yyrule - 1, yylno); + /* Print the symbols being reduced, and their result. */ + for (yyi = yyprhs[yyrule]; 0 <= yyrhs[yyi]; yyi++) + YYFPRINTF (stderr, "%s ", yytname[yyrhs[yyi]]); + YYFPRINTF (stderr, "-> %s\n", yytname[yyr1[yyrule]]); +} + +# define YY_REDUCE_PRINT(Rule) \ +do { \ + if (yydebug) \ + yy_reduce_print (Rule); \ +} while (0) + +/* Nonzero means print parse trace. It is left uninitialized so that + multiple parsers can coexist. */ +int yydebug; +#else /* !YYDEBUG */ +# define YYDPRINTF(Args) +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) +# define YY_STACK_PRINT(Bottom, Top) +# define YY_REDUCE_PRINT(Rule) +#endif /* !YYDEBUG */ + + +/* YYINITDEPTH -- initial size of the parser's stacks. */ +#ifndef YYINITDEPTH +# define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only + if the built-in stack extension method is used). + + Do not make this value too large; the results are undefined if + YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) + evaluated with infinite-precision integer arithmetic. */ + +#ifndef YYMAXDEPTH +# define YYMAXDEPTH 10000 +#endif + + + +#if YYERROR_VERBOSE + +# ifndef yystrlen +# if defined (__GLIBC__) && defined (_STRING_H) +# define yystrlen strlen +# else +/* Return the length of YYSTR. */ +static YYSIZE_T +# if defined (__STDC__) || defined (__cplusplus) +yystrlen (const char *yystr) +# else +yystrlen (yystr) + const char *yystr; +# endif +{ + const char *yys = yystr; + + while (*yys++ != '\0') + continue; + + return yys - yystr - 1; +} +# endif +# endif + +# ifndef yystpcpy +# if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE) +# define yystpcpy stpcpy +# else +/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in + YYDEST. */ +static char * +# if defined (__STDC__) || defined (__cplusplus) +yystpcpy (char *yydest, const char *yysrc) +# else +yystpcpy (yydest, yysrc) + char *yydest; + const char *yysrc; +# endif +{ + char *yyd = yydest; + const char *yys = yysrc; + + while ((*yyd++ = *yys++) != '\0') + continue; + + return yyd - 1; +} +# endif +# endif + +# ifndef yytnamerr +/* Copy to YYRES the contents of YYSTR after stripping away unnecessary + quotes and backslashes, so that it's suitable for yyerror. The + heuristic is that double-quoting is unnecessary unless the string + contains an apostrophe, a comma, or backslash (other than + backslash-backslash). YYSTR is taken from yytname. If YYRES is + null, do not copy; instead, return the length of what the result + would have been. */ +static YYSIZE_T +yytnamerr (char *yyres, const char *yystr) +{ + if (*yystr == '"') + { + size_t yyn = 0; + char const *yyp = yystr; + + for (;;) + switch (*++yyp) + { + case '\'': + case ',': + goto do_not_strip_quotes; + + case '\\': + if (*++yyp != '\\') + goto do_not_strip_quotes; + /* Fall through. */ + default: + if (yyres) + yyres[yyn] = *yyp; + yyn++; + break; + + case '"': + if (yyres) + yyres[yyn] = '\0'; + return yyn; + } +do_not_strip_quotes: ; + } + + if (! yyres) + return yystrlen (yystr); + + return yystpcpy (yyres, yystr) - yyres; +} +# endif + +#endif /* YYERROR_VERBOSE */ + + + +#if YYDEBUG +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +#if defined (__STDC__) || defined (__cplusplus) +static void +yysymprint (FILE *yyoutput, int yytype, YYSTYPE *yyvaluep) +#else +static void +yysymprint (yyoutput, yytype, yyvaluep) + FILE *yyoutput; + int yytype; + YYSTYPE *yyvaluep; +#endif +{ + /* Pacify ``unused variable'' warnings. */ + (void) yyvaluep; + + if (yytype < YYNTOKENS) + YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); + else + YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); + + +# ifdef YYPRINT + if (yytype < YYNTOKENS) + YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); +# endif + switch (yytype) + { + default: + break; + } + YYFPRINTF (yyoutput, ")"); +} + +#endif /* ! YYDEBUG */ +/*-----------------------------------------------. +| Release the memory associated to this symbol. | +`-----------------------------------------------*/ + +#if defined (__STDC__) || defined (__cplusplus) +static void +yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep) +#else +static void +yydestruct (yymsg, yytype, yyvaluep) + const char *yymsg; + int yytype; + YYSTYPE *yyvaluep; +#endif +{ + /* Pacify ``unused variable'' warnings. */ + (void) yyvaluep; + + if (!yymsg) + yymsg = "Deleting"; + YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); + + switch (yytype) + { + case 52: /* "choice_entry" */ + + { + fprintf(stderr, "%s:%d: missing end statement for this entry\n", + (yyvaluep->menu)->file->name, (yyvaluep->menu)->lineno); + if (current_menu == (yyvaluep->menu)) + menu_end_menu(); +}; + + break; + case 58: /* "if_entry" */ + + { + fprintf(stderr, "%s:%d: missing end statement for this entry\n", + (yyvaluep->menu)->file->name, (yyvaluep->menu)->lineno); + if (current_menu == (yyvaluep->menu)) + menu_end_menu(); +}; + + break; + case 63: /* "menu_entry" */ + + { + fprintf(stderr, "%s:%d: missing end statement for this entry\n", + (yyvaluep->menu)->file->name, (yyvaluep->menu)->lineno); + if (current_menu == (yyvaluep->menu)) + menu_end_menu(); +}; + + break; + + default: + break; + } +} + + +/* Prevent warnings from -Wmissing-prototypes. */ + +#ifdef YYPARSE_PARAM +# if defined (__STDC__) || defined (__cplusplus) +int yyparse (void *YYPARSE_PARAM); +# else +int yyparse (); +# endif +#else /* ! YYPARSE_PARAM */ +#if defined (__STDC__) || defined (__cplusplus) +int yyparse (void); +#else +int yyparse (); +#endif +#endif /* ! YYPARSE_PARAM */ + + + +/* The look-ahead symbol. */ +int yychar; + +/* The semantic value of the look-ahead symbol. */ +YYSTYPE yylval; + +/* Number of syntax errors so far. */ +int yynerrs; + + + +/*----------. +| yyparse. | +`----------*/ + +#ifdef YYPARSE_PARAM +# if defined (__STDC__) || defined (__cplusplus) +int yyparse (void *YYPARSE_PARAM) +# else +int yyparse (YYPARSE_PARAM) + void *YYPARSE_PARAM; +# endif +#else /* ! YYPARSE_PARAM */ +#if defined (__STDC__) || defined (__cplusplus) +int +yyparse (void) +#else +int +yyparse () + ; +#endif +#endif +{ + + int yystate; + int yyn; + int yyresult; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus; + /* Look-ahead token as an internal (translated) token number. */ + int yytoken = 0; + + /* Three stacks and their tools: + `yyss': related to states, + `yyvs': related to semantic values, + `yyls': related to locations. + + Refer to the stacks thru separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + + /* The state stack. */ + short int yyssa[YYINITDEPTH]; + short int *yyss = yyssa; + short int *yyssp; + + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs = yyvsa; + YYSTYPE *yyvsp; + + + +#define YYPOPSTACK (yyvsp--, yyssp--) + + YYSIZE_T yystacksize = YYINITDEPTH; + + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; + + + /* When reducing, the number of symbols on the RHS of the reduced + rule. */ + int yylen; + + YYDPRINTF ((stderr, "Starting parse\n")); + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. + The wasted elements are never initialized. */ + + yyssp = yyss; + yyvsp = yyvs; + + goto yysetstate; + +/*------------------------------------------------------------. +| yynewstate -- Push a new state, which is found in yystate. | +`------------------------------------------------------------*/ + yynewstate: + /* In all cases, when you get here, the value and location stacks + have just been pushed. so pushing a state here evens the stacks. + */ + yyssp++; + + yysetstate: + *yyssp = yystate; + + if (yyss + yystacksize - 1 <= yyssp) + { + /* Get the current used size of the three stacks, in elements. */ + YYSIZE_T yysize = yyssp - yyss + 1; + +#ifdef yyoverflow + { + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + YYSTYPE *yyvs1 = yyvs; + short int *yyss1 = yyss; + + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. This used to be a + conditional around just the two extra args, but that might + be undefined if yyoverflow is a macro. */ + yyoverflow (YY_("memory exhausted"), + &yyss1, yysize * sizeof (*yyssp), + &yyvs1, yysize * sizeof (*yyvsp), + + &yystacksize); + + yyss = yyss1; + yyvs = yyvs1; + } +#else /* no yyoverflow */ +# ifndef YYSTACK_RELOCATE + goto yyexhaustedlab; +# else + /* Extend the stack our own way. */ + if (YYMAXDEPTH <= yystacksize) + goto yyexhaustedlab; + yystacksize *= 2; + if (YYMAXDEPTH < yystacksize) + yystacksize = YYMAXDEPTH; + + { + short int *yyss1 = yyss; + union yyalloc *yyptr = + (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); + if (! yyptr) + goto yyexhaustedlab; + YYSTACK_RELOCATE (yyss); + YYSTACK_RELOCATE (yyvs); + +# undef YYSTACK_RELOCATE + if (yyss1 != yyssa) + YYSTACK_FREE (yyss1); + } +# endif +#endif /* no yyoverflow */ + + yyssp = yyss + yysize - 1; + yyvsp = yyvs + yysize - 1; + + + YYDPRINTF ((stderr, "Stack size increased to %lu\n", + (unsigned long int) yystacksize)); + + if (yyss + yystacksize - 1 <= yyssp) + YYABORT; + } + + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + + goto yybackup; + +/*-----------. +| yybackup. | +`-----------*/ +yybackup: + +/* Do appropriate processing given the current state. */ +/* Read a look-ahead token if we need one and don't already have one. */ +/* yyresume: */ + + /* First try to decide what to do without reference to look-ahead token. */ + + yyn = yypact[yystate]; + if (yyn == YYPACT_NINF) + goto yydefault; + + /* Not known => get a look-ahead token if don't already have one. */ + + /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol. */ + if (yychar == YYEMPTY) + { + YYDPRINTF ((stderr, "Reading a token: ")); + yychar = YYLEX; + } + + if (yychar <= YYEOF) + { + yychar = yytoken = YYEOF; + YYDPRINTF ((stderr, "Now at end of input.\n")); + } + else + { + yytoken = YYTRANSLATE (yychar); + YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); + } + + /* If the proper action on seeing token YYTOKEN is to reduce or to + detect an error, take that action. */ + yyn += yytoken; + if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) + goto yydefault; + yyn = yytable[yyn]; + if (yyn <= 0) + { + if (yyn == 0 || yyn == YYTABLE_NINF) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + + if (yyn == YYFINAL) + YYACCEPT; + + /* Shift the look-ahead token. */ + YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); + + /* Discard the token being shifted unless it is eof. */ + if (yychar != YYEOF) + yychar = YYEMPTY; + + *++yyvsp = yylval; + + + /* Count tokens shifted since error; after three, turn off error + status. */ + if (yyerrstatus) + yyerrstatus--; + + yystate = yyn; + goto yynewstate; + + +/*-----------------------------------------------------------. +| yydefault -- do the default action for the current state. | +`-----------------------------------------------------------*/ +yydefault: + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + goto yyreduce; + + +/*-----------------------------. +| yyreduce -- Do a reduction. | +`-----------------------------*/ +yyreduce: + /* yyn is the number of a rule to reduce with. */ + yylen = yyr2[yyn]; + + /* If YYLEN is nonzero, implement the default value of the action: + `$$ = $1'. + + Otherwise, the following line sets YYVAL to garbage. + This behavior is undocumented and Bison + users should not rely upon it. Assigning to YYVAL + unconditionally makes the parser a bit smaller, and it avoids a + GCC warning that YYVAL may be used uninitialized. */ + yyval = yyvsp[1-yylen]; + + + YY_REDUCE_PRINT (yyn); + switch (yyn) + { + case 8: + + { zconf_error("unexpected end statement"); ;} + break; + + case 9: + + { zconf_error("unknown statement \"%s\"", (yyvsp[-2].string)); ;} + break; + + case 10: + + { + zconf_error("unexpected option \"%s\"", kconf_id_strings + (yyvsp[-2].id)->name); +;} + break; + + case 11: + + { zconf_error("invalid statement"); ;} + break; + + case 25: + + { zconf_error("unknown option \"%s\"", (yyvsp[-2].string)); ;} + break; + + case 26: + + { zconf_error("invalid option"); ;} + break; + + case 27: + + { + struct symbol *sym = sym_lookup((yyvsp[-1].string), 0); + sym->flags |= SYMBOL_OPTIONAL; + menu_add_entry(sym); + printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), (yyvsp[-1].string)); +;} + break; + + case 28: + + { + menu_end_entry(); + printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno()); +;} + break; + + case 29: + + { + struct symbol *sym = sym_lookup((yyvsp[-1].string), 0); + sym->flags |= SYMBOL_OPTIONAL; + menu_add_entry(sym); + printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), (yyvsp[-1].string)); +;} + break; + + case 30: + + { + if (current_entry->prompt) + current_entry->prompt->type = P_MENU; + else + zconfprint("warning: menuconfig statement without prompt"); + menu_end_entry(); + printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno()); +;} + break; + + case 38: + + { + menu_set_type((yyvsp[-2].id)->stype); + printd(DEBUG_PARSE, "%s:%d:type(%u)\n", + zconf_curname(), zconf_lineno(), + (yyvsp[-2].id)->stype); +;} + break; + + case 39: + + { + menu_add_prompt(P_PROMPT, (yyvsp[-2].string), (yyvsp[-1].expr)); + printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno()); +;} + break; + + case 40: + + { + menu_add_expr(P_DEFAULT, (yyvsp[-2].expr), (yyvsp[-1].expr)); + if ((yyvsp[-3].id)->stype != S_UNKNOWN) + menu_set_type((yyvsp[-3].id)->stype); + printd(DEBUG_PARSE, "%s:%d:default(%u)\n", + zconf_curname(), zconf_lineno(), + (yyvsp[-3].id)->stype); +;} + break; + + case 41: + + { + menu_add_symbol(P_SELECT, sym_lookup((yyvsp[-2].string), 0), (yyvsp[-1].expr)); + printd(DEBUG_PARSE, "%s:%d:select\n", zconf_curname(), zconf_lineno()); +;} + break; + + case 42: + + { + menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,(yyvsp[-3].symbol), (yyvsp[-2].symbol)), (yyvsp[-1].expr)); + printd(DEBUG_PARSE, "%s:%d:range\n", zconf_curname(), zconf_lineno()); +;} + break; + + case 45: + + { + struct kconf_id *id = kconf_id_lookup((yyvsp[-1].string), strlen((yyvsp[-1].string))); + if (id && id->flags & TF_OPTION) + menu_add_option(id->token, (yyvsp[0].string)); + else + zconfprint("warning: ignoring unknown option %s", (yyvsp[-1].string)); + free((yyvsp[-1].string)); +;} + break; + + case 46: + + { (yyval.string) = NULL; ;} + break; + + case 47: + + { (yyval.string) = (yyvsp[0].string); ;} + break; + + case 48: + + { + struct symbol *sym = sym_lookup(NULL, 0); + sym->flags |= SYMBOL_CHOICE; + menu_add_entry(sym); + menu_add_expr(P_CHOICE, NULL, NULL); + printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno()); +;} + break; + + case 49: + + { + (yyval.menu) = menu_add_menu(); +;} + break; + + case 50: + + { + if (zconf_endtoken((yyvsp[0].id), T_CHOICE, T_ENDCHOICE)) { + menu_end_menu(); + printd(DEBUG_PARSE, "%s:%d:endchoice\n", zconf_curname(), zconf_lineno()); + } +;} + break; + + case 58: + + { + menu_add_prompt(P_PROMPT, (yyvsp[-2].string), (yyvsp[-1].expr)); + printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno()); +;} + break; + + case 59: + + { + if ((yyvsp[-2].id)->stype == S_BOOLEAN || (yyvsp[-2].id)->stype == S_TRISTATE) { + menu_set_type((yyvsp[-2].id)->stype); + printd(DEBUG_PARSE, "%s:%d:type(%u)\n", + zconf_curname(), zconf_lineno(), + (yyvsp[-2].id)->stype); + } else + YYERROR; +;} + break; + + case 60: + + { + current_entry->sym->flags |= SYMBOL_OPTIONAL; + printd(DEBUG_PARSE, "%s:%d:optional\n", zconf_curname(), zconf_lineno()); +;} + break; + + case 61: + + { + if ((yyvsp[-3].id)->stype == S_UNKNOWN) { + menu_add_symbol(P_DEFAULT, sym_lookup((yyvsp[-2].string), 0), (yyvsp[-1].expr)); + printd(DEBUG_PARSE, "%s:%d:default\n", + zconf_curname(), zconf_lineno()); + } else + YYERROR; +;} + break; + + case 64: + + { + printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno()); + menu_add_entry(NULL); + menu_add_dep((yyvsp[-1].expr)); + (yyval.menu) = menu_add_menu(); +;} + break; + + case 65: + + { + if (zconf_endtoken((yyvsp[0].id), T_IF, T_ENDIF)) { + menu_end_menu(); + printd(DEBUG_PARSE, "%s:%d:endif\n", zconf_curname(), zconf_lineno()); + } +;} + break; + + case 71: + + { + menu_add_entry(NULL); + menu_add_prompt(P_MENU, (yyvsp[-1].string), NULL); + printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno()); +;} + break; + + case 72: + + { + (yyval.menu) = menu_add_menu(); +;} + break; + + case 73: + + { + if (zconf_endtoken((yyvsp[0].id), T_MENU, T_ENDMENU)) { + menu_end_menu(); + printd(DEBUG_PARSE, "%s:%d:endmenu\n", zconf_curname(), zconf_lineno()); + } +;} + break; + + case 79: + + { + printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), (yyvsp[-1].string)); + zconf_nextfile((yyvsp[-1].string)); +;} + break; + + case 80: + + { + menu_add_entry(NULL); + menu_add_prompt(P_COMMENT, (yyvsp[-1].string), NULL); + printd(DEBUG_PARSE, "%s:%d:comment\n", zconf_curname(), zconf_lineno()); +;} + break; + + case 81: + + { + menu_end_entry(); +;} + break; + + case 82: + + { + printd(DEBUG_PARSE, "%s:%d:help\n", zconf_curname(), zconf_lineno()); + zconf_starthelp(); +;} + break; + + case 83: + + { + current_entry->help = (yyvsp[0].string); +;} + break; + + case 88: + + { + menu_add_dep((yyvsp[-1].expr)); + printd(DEBUG_PARSE, "%s:%d:depends on\n", zconf_curname(), zconf_lineno()); +;} + break; + + case 89: + + { + menu_add_dep((yyvsp[-1].expr)); + printd(DEBUG_PARSE, "%s:%d:depends\n", zconf_curname(), zconf_lineno()); +;} + break; + + case 90: + + { + menu_add_dep((yyvsp[-1].expr)); + printd(DEBUG_PARSE, "%s:%d:requires\n", zconf_curname(), zconf_lineno()); +;} + break; + + case 92: + + { + menu_add_prompt(P_PROMPT, (yyvsp[-1].string), (yyvsp[0].expr)); +;} + break; + + case 95: + + { (yyval.id) = (yyvsp[-1].id); ;} + break; + + case 96: + + { (yyval.id) = (yyvsp[-1].id); ;} + break; + + case 97: + + { (yyval.id) = (yyvsp[-1].id); ;} + break; + + case 100: + + { (yyval.expr) = NULL; ;} + break; + + case 101: + + { (yyval.expr) = (yyvsp[0].expr); ;} + break; + + case 102: + + { (yyval.expr) = expr_alloc_symbol((yyvsp[0].symbol)); ;} + break; + + case 103: + + { (yyval.expr) = expr_alloc_comp(E_EQUAL, (yyvsp[-2].symbol), (yyvsp[0].symbol)); ;} + break; + + case 104: + + { (yyval.expr) = expr_alloc_comp(E_UNEQUAL, (yyvsp[-2].symbol), (yyvsp[0].symbol)); ;} + break; + + case 105: + + { (yyval.expr) = (yyvsp[-1].expr); ;} + break; + + case 106: + + { (yyval.expr) = expr_alloc_one(E_NOT, (yyvsp[0].expr)); ;} + break; + + case 107: + + { (yyval.expr) = expr_alloc_two(E_OR, (yyvsp[-2].expr), (yyvsp[0].expr)); ;} + break; + + case 108: + + { (yyval.expr) = expr_alloc_two(E_AND, (yyvsp[-2].expr), (yyvsp[0].expr)); ;} + break; + + case 109: + + { (yyval.symbol) = sym_lookup((yyvsp[0].string), 0); free((yyvsp[0].string)); ;} + break; + + case 110: + + { (yyval.symbol) = sym_lookup((yyvsp[0].string), 1); free((yyvsp[0].string)); ;} + break; + + + default: break; + } + +/* Line 1126 of yacc.c. */ + + + yyvsp -= yylen; + yyssp -= yylen; + + + YY_STACK_PRINT (yyss, yyssp); + + *++yyvsp = yyval; + + + /* Now `shift' the result of the reduction. Determine what state + that goes to, based on the state we popped back to and the rule + number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; + if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTOKENS]; + + goto yynewstate; + + +/*------------------------------------. +| yyerrlab -- here on detecting error | +`------------------------------------*/ +yyerrlab: + /* If not already recovering from an error, report this error. */ + if (!yyerrstatus) + { + ++yynerrs; +#if YYERROR_VERBOSE + yyn = yypact[yystate]; + + if (YYPACT_NINF < yyn && yyn < YYLAST) + { + int yytype = YYTRANSLATE (yychar); + YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); + YYSIZE_T yysize = yysize0; + YYSIZE_T yysize1; + int yysize_overflow = 0; + char *yymsg = 0; +# define YYERROR_VERBOSE_ARGS_MAXIMUM 5 + char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; + int yyx; + +#if 0 + /* This is so xgettext sees the translatable formats that are + constructed on the fly. */ + YY_("syntax error, unexpected %s"); + YY_("syntax error, unexpected %s, expecting %s"); + YY_("syntax error, unexpected %s, expecting %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); +#endif + char *yyfmt; + char const *yyf; + static char const yyunexpected[] = "syntax error, unexpected %s"; + static char const yyexpecting[] = ", expecting %s"; + static char const yyor[] = " or %s"; + char yyformat[sizeof(yyunexpected) + + sizeof(yyexpecting) - 1 + + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) + * (sizeof(yyor) - 1))]; + char const *yyprefix = yyexpecting; + + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. */ + int yyxbegin = yyn < 0 ? -yyn : 0; + + /* Stay within bounds of both yycheck and yytname. */ + int yychecklim = YYLAST - yyn; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + int yycount = 1; + + yyarg[0] = yytname[yytype]; + yyfmt = yystpcpy (yyformat, yyunexpected); + + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) + { + if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) + { + yycount = 1; + yysize = yysize0; + yyformat[sizeof(yyunexpected) - 1] = '\0'; + break; + } + yyarg[yycount++] = yytname[yyx]; + yysize1 = yysize + yytnamerr (0, yytname[yyx]); + yysize_overflow |= yysize1 < yysize; + yysize = yysize1; + yyfmt = yystpcpy (yyfmt, yyprefix); + yyprefix = yyor; + } + + yyf = YY_(yyformat); + yysize1 = yysize + yystrlen (yyf); + yysize_overflow |= yysize1 < yysize; + yysize = yysize1; + + if (!yysize_overflow && yysize <= YYSTACK_ALLOC_MAXIMUM) + yymsg = (char *) YYSTACK_ALLOC (yysize); + if (yymsg) + { + /* Avoid sprintf, as that infringes on the user's name space. + Don't have undefined behavior even if the translation + produced a string with the wrong number of "%s"s. */ + char *yyp = yymsg; + int yyi = 0; + while ((*yyp = *yyf)) + { + if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) + { + yyp += yytnamerr (yyp, yyarg[yyi++]); + yyf += 2; + } + else + { + yyp++; + yyf++; + } + } + yyerror (yymsg); + YYSTACK_FREE (yymsg); + } + else + { + yyerror (YY_("syntax error")); + goto yyexhaustedlab; + } + } + else +#endif /* YYERROR_VERBOSE */ + yyerror (YY_("syntax error")); + } + + + + if (yyerrstatus == 3) + { + /* If just tried and failed to reuse look-ahead token after an + error, discard it. */ + + if (yychar <= YYEOF) + { + /* Return failure if at end of input. */ + if (yychar == YYEOF) + YYABORT; + } + else + { + yydestruct ("Error: discarding", yytoken, &yylval); + yychar = YYEMPTY; + } + } + + /* Else will try to reuse look-ahead token after shifting the error + token. */ + goto yyerrlab1; + + +/*---------------------------------------------------. +| yyerrorlab -- error raised explicitly by YYERROR. | +`---------------------------------------------------*/ +yyerrorlab: + + /* Pacify compilers like GCC when the user code never invokes + YYERROR and the label yyerrorlab therefore never appears in user + code. */ + if (0) + goto yyerrorlab; + +yyvsp -= yylen; + yyssp -= yylen; + yystate = *yyssp; + goto yyerrlab1; + + +/*-------------------------------------------------------------. +| yyerrlab1 -- common code for both syntax error and YYERROR. | +`-------------------------------------------------------------*/ +yyerrlab1: + yyerrstatus = 3; /* Each real token shifted decrements this. */ + + for (;;) + { + yyn = yypact[yystate]; + if (yyn != YYPACT_NINF) + { + yyn += YYTERROR; + if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) + { + yyn = yytable[yyn]; + if (0 < yyn) + break; + } + } + + /* Pop the current state because it cannot handle the error token. */ + if (yyssp == yyss) + YYABORT; + + + yydestruct ("Error: popping", yystos[yystate], yyvsp); + YYPOPSTACK; + yystate = *yyssp; + YY_STACK_PRINT (yyss, yyssp); + } + + if (yyn == YYFINAL) + YYACCEPT; + + *++yyvsp = yylval; + + + /* Shift the error token. */ + YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); + + yystate = yyn; + goto yynewstate; + + +/*-------------------------------------. +| yyacceptlab -- YYACCEPT comes here. | +`-------------------------------------*/ +yyacceptlab: + yyresult = 0; + goto yyreturn; + +/*-----------------------------------. +| yyabortlab -- YYABORT comes here. | +`-----------------------------------*/ +yyabortlab: + yyresult = 1; + goto yyreturn; + +#ifndef yyoverflow +/*-------------------------------------------------. +| yyexhaustedlab -- memory exhaustion comes here. | +`-------------------------------------------------*/ +yyexhaustedlab: + yyerror (YY_("memory exhausted")); + yyresult = 2; + /* Fall through. */ +#endif + +yyreturn: + if (yychar != YYEOF && yychar != YYEMPTY) + yydestruct ("Cleanup: discarding lookahead", + yytoken, &yylval); + while (yyssp != yyss) + { + yydestruct ("Cleanup: popping", + yystos[*yyssp], yyvsp); + YYPOPSTACK; + } +#ifndef yyoverflow + if (yyss != yyssa) + YYSTACK_FREE (yyss); +#endif + return yyresult; +} + + + + + +void conf_parse(const char *name) +{ + struct symbol *sym; + int i; + + zconf_initscan(name); + + sym_init(); + menu_init(); + modules_sym = sym_lookup(NULL, 0); + modules_sym->type = S_BOOLEAN; + modules_sym->flags |= SYMBOL_AUTO; + rootmenu.prompt = menu_add_prompt(P_MENU, "VxMicro 2.2 Project Configuration", NULL); + +#if YYDEBUG + if (getenv("ZCONF_DEBUG")) + zconfdebug = 1; +#endif + zconfparse(); + if (zconfnerrs) + exit(1); + if (!modules_sym->prop) { + struct property *prop; + + prop = prop_alloc(P_DEFAULT, modules_sym); + prop->expr = expr_alloc_symbol(sym_lookup("MODULES", 0)); + } + menu_finalize(&rootmenu); + for_all_symbols(i, sym) { + if (sym_check_deps(sym)) + zconfnerrs++; + } + if (zconfnerrs) + exit(1); + sym_set_change_count(1); +} + +const char *zconf_tokenname(int token) +{ + switch (token) { + case T_MENU: return "menu"; + case T_ENDMENU: return "endmenu"; + case T_CHOICE: return "choice"; + case T_ENDCHOICE: return "endchoice"; + case T_IF: return "if"; + case T_ENDIF: return "endif"; + case T_DEPENDS: return "depends"; + } + return ""; +} + +static bool zconf_endtoken(struct kconf_id *id, int starttoken, int endtoken) +{ + if (id->token != endtoken) { + zconf_error("unexpected '%s' within %s block", + kconf_id_strings + id->name, zconf_tokenname(starttoken)); + zconfnerrs++; + return false; + } + if (current_menu->file != current_file) { + zconf_error("'%s' in different file than '%s'", + kconf_id_strings + id->name, zconf_tokenname(starttoken)); + fprintf(stderr, "%s:%d: location of the '%s'\n", + current_menu->file->name, current_menu->lineno, + zconf_tokenname(starttoken)); + zconfnerrs++; + return false; + } + return true; +} + +static void zconfprint(const char *err, ...) +{ + va_list ap; + + fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno()); + va_start(ap, err); + vfprintf(stderr, err, ap); + va_end(ap); + fprintf(stderr, "\n"); +} + +static void zconf_error(const char *err, ...) +{ + va_list ap; + + zconfnerrs++; + fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno()); + va_start(ap, err); + vfprintf(stderr, err, ap); + va_end(ap); + fprintf(stderr, "\n"); +} + +static void zconferror(const char *err) +{ +#if YYDEBUG + fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno() + 1, err); +#endif +} + +void print_quoted_string(FILE *out, const char *str) +{ + const char *p; + int len; + + putc('"', out); + while ((p = strchr(str, '"'))) { + len = p - str; + if (len) + fprintf(out, "%.*s", len, str); + fputs("\\\"", out); + str = p + 1; + } + fputs(str, out); + putc('"', out); +} + +void print_symbol(FILE *out, struct menu *menu) +{ + struct symbol *sym = menu->sym; + struct property *prop; + + if (sym_is_choice(sym)) + fprintf(out, "choice\n"); + else + fprintf(out, "config %s\n", sym->name); + switch (sym->type) { + case S_BOOLEAN: + fputs(" boolean\n", out); + break; + case S_TRISTATE: + fputs(" tristate\n", out); + break; + case S_STRING: + fputs(" string\n", out); + break; + case S_INT: + fputs(" integer\n", out); + break; + case S_HEX: + fputs(" hex\n", out); + break; + default: + fputs(" ???\n", out); + break; + } + for (prop = sym->prop; prop; prop = prop->next) { + if (prop->menu != menu) + continue; + switch (prop->type) { + case P_PROMPT: + fputs(" prompt ", out); + print_quoted_string(out, prop->text); + if (!expr_is_yes(prop->visible.expr)) { + fputs(" if ", out); + expr_fprint(prop->visible.expr, out); + } + fputc('\n', out); + break; + case P_DEFAULT: + fputs( " default ", out); + expr_fprint(prop->expr, out); + if (!expr_is_yes(prop->visible.expr)) { + fputs(" if ", out); + expr_fprint(prop->visible.expr, out); + } + fputc('\n', out); + break; + case P_CHOICE: + fputs(" #choice value\n", out); + break; + default: + fprintf(out, " unknown prop %d!\n", prop->type); + break; + } + } + if (menu->help) { + int len = strlen(menu->help); + while (menu->help[--len] == '\n') + menu->help[len] = 0; + fprintf(out, " help\n%s\n", menu->help); + } + fputc('\n', out); +} + +void zconfdump(FILE *out) +{ + struct property *prop; + struct symbol *sym; + struct menu *menu; + + menu = rootmenu.list; + while (menu) { + if ((sym = menu->sym)) + print_symbol(out, menu); + else if ((prop = menu->prompt)) { + switch (prop->type) { + case P_COMMENT: + fputs("\ncomment ", out); + print_quoted_string(out, prop->text); + fputs("\n", out); + break; + case P_MENU: + fputs("\nmenu ", out); + print_quoted_string(out, prop->text); + fputs("\n", out); + break; + default: + ; + } + if (!expr_is_yes(prop->visible.expr)) { + fputs(" depends ", out); + expr_fprint(prop->visible.expr, out); + fputc('\n', out); + } + fputs("\n", out); + } + + if (menu->list) + menu = menu->list; + else if (menu->next) + menu = menu->next; + else while ((menu = menu->parent)) { + if (menu->prompt && menu->prompt->type == P_MENU) + fputs("\nendmenu\n", out); + if (menu->next) { + menu = menu->next; + break; + } + } + } +} + +#include "lex.zconf.c" +#include "util.c" +#include "confdata.c" +#include "expr.c" +#include "symbol.c" +#include "menu.c" + + diff --git a/host/x86-linux2/bin/cat3files b/host/x86-linux2/bin/cat3files new file mode 100755 index 00000000000..c079cc6b049 --- /dev/null +++ b/host/x86-linux2/bin/cat3files @@ -0,0 +1,34 @@ +#!/bin/sh + +# +# Copyright (c) 2011 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors +# may be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. +# + +cat $1 $2 $3 > $4 +exit 0 diff --git a/host/x86-linux2/bin/dirlist b/host/x86-linux2/bin/dirlist new file mode 100755 index 00000000000..f413ac3b6f7 --- /dev/null +++ b/host/x86-linux2/bin/dirlist @@ -0,0 +1,52 @@ +#!/bin/sh + +# +# Copyright (c) 2011 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors +# may be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. +# + +saveDir=$PWD + +for arg +do + if [ -x $dir ] && [ -r $dir ] + then + for dir in * + do + if [ -d $dir ] && [ $dir != "." ] && \ + [ $dir != ".." ] && [ -x $dir ] && [ -r $dir ]; then + cd $dir + if [ $saveDir != $PWD ]; then + echo $PWD + fi + cd $saveDir + fi + done + fi +done +exit 0 diff --git a/host/x86-linux2/bin/filelist b/host/x86-linux2/bin/filelist new file mode 100755 index 00000000000..9de42aabf93 --- /dev/null +++ b/host/x86-linux2/bin/filelist @@ -0,0 +1,43 @@ +#!/bin/sh + +# +# Copyright (c) 2011 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors +# may be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. +# + +saveDir=$PWD + +for arg +do + if [ -f $arg ]; then + cd `dirname $arg` > /dev/null + echo $PWD/`basename $arg` + cd $saveDir > /dev/null + fi +done +exit 0 diff --git a/host/x86-linux2/bin/make-ll b/host/x86-linux2/bin/make-ll new file mode 100755 index 00000000000..eab0d50b688 --- /dev/null +++ b/host/x86-linux2/bin/make-ll @@ -0,0 +1,42 @@ +#!/bin/bash + +# +# Copyright (c) 2014-2015 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors +# may be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. +# + +[ x$(which grep) = x ] && exit -1 + +num_cpus=$(\grep -c "^processor" /proc/cpuinfo) + +if [ x${VXMICRO_JOBS} = x ]; then + VXMICRO_JOBS=$((${num_cpus} * 2 + 1)) +fi + +echo Using $VXMICRO_JOBS threads +nice make --jobs=${VXMICRO_JOBS} --load-average=${num_cpus} $@ diff --git a/host/x86-linux2/bin/truesize b/host/x86-linux2/bin/truesize new file mode 100755 index 00000000000..1df4f4cd53c --- /dev/null +++ b/host/x86-linux2/bin/truesize @@ -0,0 +1,52 @@ +#!/bin/bash + +# +# Copyright (c) 2014-2015 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors +# may be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. +# + +# script to compute true memory footprint of a VxMicro image +# +# usage: truesize <.ELF file> + +if [ -z "$1" ]; then + echo missing .ELF file to be measured + exit +fi + +# ensure gawk is installed + +if [ ! -x "/usr/bin/gawk" ]; then + echo 'script requires GNU awk (i.e. /usr/bin/gawk)' + exit +fi + +# use "objdump" to get section information, +# then pass to AWK script that computes true memory footprint + +objdump -h $1 | truesize.awk diff --git a/host/x86-linux2/bin/truesize.awk b/host/x86-linux2/bin/truesize.awk new file mode 100755 index 00000000000..d1cc840e93f --- /dev/null +++ b/host/x86-linux2/bin/truesize.awk @@ -0,0 +1,209 @@ +#!/usr/bin/gawk -f + +# +# Copyright (c) 2012-2015 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors +# may be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. +# + +# gawk script that computes true memory footprint of a VxMicro image +# from the output of "objdump -h " + +# IMPORTANT: uses gawk builtin function strtonum(), so won't run with plain awk + +# print out headings for section info that will follow; +# initialize byte totals for text, data, and bss classes; +# disable flag that indicates image utilizes MMU; +# disable flag that causes 2nd line of section info to be processed + +BEGIN { + printf("SECTION NAME ADDRESS SIZE HEX PAD\n"); + + first_section = 1; + total_pad = 0; + text = 0; + data = 0; + bss = 0; + kcpages = 0; + rtpages = 0; + kc_size = 0; + rt_size = 0; + nrt_size = 0; + usaps_size= 0; + total_size= 0; + mmu = 0; + + searchline = 0; + } + +# process line marking the start of a "significant" section +# - look for lines with numeric first field and second field that doesn't +# start with "." (i.e. don't want to worry about .debug_XXX and .comment) +# - for each section, capture useful data, record which page(s) it covers, +# and print out basic section information +# - remember how much unused page space is left at the end of the section +# (note: only need to keep this info for the final section) Bernie: Not True. +# - enable flag to cause additional section info on next line to be processed + +/^\ *[0-9]+\ */ && (substr($2,1,1) != ".") \ + { + kc = 0; + rt = 0; + nrt = 0; + usaps = 0; + + phyaddr = strtonum("0x" $5); + addr = strtonum("0x" $4); + size = strtonum("0x" $3); + section = $2; + + if (match($2,/kc/)) { + kc = 1; + kc_size += size; + } else + if (match($2,/rt/)) { + rt = 1; + rt_size += size; + } else + if (match($2,/usaps/)) { + usaps_size += size; + usaps = 1; + } else { + nrt = 1; + nrt_size += size; + } + + total_size += size; + if ((prev_section_pad = addr - endaddr) > 4096) + prev_section_pad = (4096 - (endaddr % 4096)) % 4096; + + endaddr = addr + size; + + startpage = int(addr / 4096); + endpage = int((endaddr - 1) / 4096); + + numpages = 0; + for (pagenum = startpage; pagenum <= endpage; pagenum++) { + pageset[pagenum] = 1; + if (kc==1) + kcpageset[pagenum] = 1; + if (rt==1) + rtpageset[pagenum] = 1; + if (nrt==1) + nrtpageset[pagenum] = 1; + if (usaps==1) + usapspageset[pagenum] = 1; + numpages++; + } + + if (first_section == 1) { + first_section = 0; + printf("%-16s 0x%08x %8d %5x ", section, phyaddr, size, size); + } + else { + printf("%5d\n%-16s 0x%08x %8d %5x ", prev_section_pad, section, phyaddr, size, size); + total_pad += prev_section_pad; + } + +# look for section that requires page alignment +# - set MMU flag to indicate MMU is being used by image +# - Include any unused memory from last section. + + if (match($7,/2**12$/)) { + mmu = 1; + } + unused = (endpage + 1) * 4096 - endaddr; + + + searchline = NR + 1; + } + +# process 2nd line of info for a significant section +# - add size info for section into the appropriate class total. +# based on the attributes of the section + +NR == searchline { + if ($0 ~ "CODE") + text += size; + else if ($0 ~ "DATA") + data += size; + else + bss += size; + } + + +# print out overall memory requirements for image +# - output is given in a similar format to that used by "size", but also +# gives info on memory used for padding (which "size" doesn't account for) +# - note: doesn't report unused padding at the end of an MMU-less image, +# since that memory doesn't really have to be present for the image to run + +END { + dec = text + data + bss; + + numpages = 0; + numkcpages = 0; + numrtpages = 0; + numusapspages = 0; + for (pagenum in pageset) { + numpages++; + if (kcpageset[pagenum] == 1) + numkcpages++; + else if (rtpageset[pagenum] == 1) + numrtpages++; + else if (nrtpageset[pagenum] == 1) + numnrtpages++; + else if (usapspageset[pagenum] == 1) + numusapspages++; + else printf("ERROR/n"); + } + + total = numpages * 4096; + pad = total - dec; + + # Include unused memory from last section only if MMU is enabled + if (mmu) + prev_section_pad = (4096 - (endaddr % 4096)) % 4096; + else { + prev_section_pad = 0; + total -= unused; + pad -= unused; + } + + total_pad += prev_section_pad; + kernel_size = total_size-usaps_size; + + printf("%5d\n", prev_section_pad); + + printf("\n text data bss dec hex pad dec hex\n%7d %7d %7d %7d %7x %7d %7d %7x\n", + text, data, bss, dec, dec, pad, total, total); + printf("\n\t KC\tRT\tNRT\tUSAPS\tKERNEL\tTOTAL\tKERNEL+PAD"); + printf("\n PAGES: %7d %9d %8d %8d %7d%7d", + numkcpages, numrtpages, numnrtpages, numusapspages, numpages-numusapspages, numpages); + printf("\n SIZES: %7d %9d %8d %8d %7d%7d %7d\n", + kc_size, rt_size, nrt_size, usaps_size, kernel_size, total_size, kernel_size+total_pad); + } diff --git a/host/x86-linux2/lib/build_tools/.keep b/host/x86-linux2/lib/build_tools/.keep new file mode 100644 index 00000000000..e69de29bb2d diff --git a/include/absSym.h b/include/absSym.h new file mode 100644 index 00000000000..d07d1706ea5 --- /dev/null +++ b/include/absSym.h @@ -0,0 +1,99 @@ +/* absSym.h - macros to generate absolute symbols */ + +/* + * Copyright (c) 2010, 2012-2014, Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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 ABSSYM_H_ +#define ABSSYM_H_ + +#ifdef __GNUC__ + +#define GEN_ABS_SYM_BEGIN(name) \ + extern void name(void); \ + void name(void) \ + { + +#define GEN_ABS_SYM_END } + +#define GEN_ABS_SYM_HOST(name, value) \ + GEN_ABSOLUTE_SYM(CONFIG_##name, value) + +#if defined(VXMICRO_ARCH_arm) + +/* + * GNU/ARM backend does not have a proper operand modifier which does not + * produces prefix # followed by value, such as %0 for PowerPC, Intel, and + * MIPS. The workaround performed here is using %B0 which converts + * the value to ~(value). Thus "n"(~(value)) is set in operand constraint + * to output (value) in the ARM specific GEN_OFFSET macro. + */ + +#define GEN_ABSOLUTE_SYM(name, value) \ + __asm__(".globl\t" #name "\n\t.equ\t" #name \ + ",%B0" \ + "\n\t.type\t" #name ",%%object" : : "n"(~(value))) + +#elif defined(VXMICRO_ARCH_x86) || defined(VXMICRO_ARCH_arc) + +#define GEN_ABSOLUTE_SYM(name, value) \ + __asm__(".globl\t" #name "\n\t.equ\t" #name \ + ",%c0" \ + "\n\t.type\t" #name ",@object" : : "n"(value)) + +#else +#error processor architecture not supported +#endif + +#elif defined(__DCC__) + +#define GEN_ABS_SYM_BEGIN(name) GEN_ABSOLUTE_SYM(name, 0); + +#define GEN_ABS_SYM_END + +#define GEN_ABSOLUTE_SYM(name, value) \ + const long name __attribute__((absolute)) = (long)(value) + +#define GEN_ABS_SYM_HOST(name, value) \ + const long CONFIG_##name __attribute__((absolute)) = (long)(value) + +#else /* unsupported toolchain */ + +#define GEN_ABS_SYM_BEGIN(name) \ + #error GEN_ABS_SYM_BEGIN macro used with unsupported toolchain + +#define GEN_ABS_SYM_END \ + #error GEN_ABS_SYM_END macro used with unsupported toolchain + +#define GEN_ABSOLUTE_SYM(name) \ + #error GEN_ABSOLUTE_SYM macro used with unsupported toolchain + +#endif /* end of "unsupported toolchain" */ + +#endif /* ABSSYM_H_ */ diff --git a/include/clock_vars.h b/include/clock_vars.h new file mode 100644 index 00000000000..4b031851322 --- /dev/null +++ b/include/clock_vars.h @@ -0,0 +1,70 @@ +/* clock_vars.h - variables needed needed for system clock */ + +/* + * Copyright (c) 2014-2015 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION + +Declare variables used by both system timer device driver and kernel components +that use timer functionality. +*/ + +#ifndef _CLOCK_VARS__H_ +#define _CLOCK_VARS__H_ + +#ifndef _ASMLANGUAGE + +#define sys_clock_ticks_per_sec CONFIG_SYS_CLOCK_TICKS_PER_SEC +#define sys_clock_hw_cycles_per_sec CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC + +/* + * sys_clock_us_per_tick global variable represents a number + * of microseconds in one OS timer tick + */ +extern int sys_clock_us_per_tick; + +/* + * sys_clock_hw_cycles_per_tick global variable represents a number + * of platform clock ticks in one OS timer tick. + * sys_clock_hw_cycles_per_tick often represents a value of divider + * of the board clock frequency + */ +extern int sys_clock_hw_cycles_per_tick; + +#ifdef CONFIG_NANOKERNEL +#include +extern uint32_t nanoTicks; +extern struct nano_timer *nanoTimerList; +#endif /* CONFIG_NANOKERNEL */ + +#endif /* !_ASMLANGUAGE */ + +#endif /* _CLOCK_VARS__H_ */ diff --git a/include/cputype.h b/include/cputype.h new file mode 100644 index 00000000000..dc641c1b0c5 --- /dev/null +++ b/include/cputype.h @@ -0,0 +1,54 @@ +/* cputype.h */ + +/* + * Copyright (c) 1997-2014, Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* This file shall ONLY contain the CPU-core/compiler specific substitutes */ +/* that are necessary to build the EMBEDDED kernel library. */ + +#ifndef _CPUTYPE_H +#define _CPUTYPE_H + +/* + * If this file is part of the host tools build, default to the Intel arch. + * This is done as a temporary workaround until the host tools build issue + * is resolved on the host side. + */ +#if defined(VXMICRO_HOST_TOOLS) || defined(VXMICRO_ARCH_x86) +#include +#elif defined(VXMICRO_ARCH_arm) +#include +#elif defined(VXMICRO_ARCH_arc) +#include +#else +#error "Unknown VXMICRO_ARCH type" +#endif + +#endif /* _CPUTYPE_H */ diff --git a/include/drivers/ioapic.h b/include/drivers/ioapic.h new file mode 100644 index 00000000000..f859fb8ab24 --- /dev/null +++ b/include/drivers/ioapic.h @@ -0,0 +1,81 @@ +/* ioapic.h - public IOAPIC APIs */ + +/* + * Copyright (c) 2012-2015 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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 __INCioapich +#define __INCioapich + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef CONFIG_IOAPIC + +/* + * Redirection table entry bits: lower 32 bit + * Used as flags argument in ioapic_irq_set + */ + +#define IOAPIC_INT_MASK 0x00010000 +#define IOAPIC_TRIGGER_MASK 0x00008000 +#define IOAPIC_LEVEL 0x00008000 +#define IOAPIC_EDGE 0x00000000 +#define IOAPIC_REMOTE 0x00004000 +#define IOAPIC_LOW 0x00002000 +#define IOAPIC_HIGH 0x00000000 +#define IOAPIC_LOGICAL 0x00000800 +#define IOAPIC_PHYSICAL 0x00000000 +#define IOAPIC_FIXED 0x00000000 +#define IOAPIC_LOWEST 0x00000100 +#define IOAPIC_SMI 0x00000200 +#define IOAPIC_NMI 0x00000400 +#define IOAPIC_INIT 0x00000500 +#define IOAPIC_EXTINT 0x00000700 + +#ifdef _ASMLANGUAGE +GTEXT(ioapic_eoi) +#else /* _ASMLANGUAGE */ +void _ioapic_init(void); +void _ioapic_eoi(unsigned int irq); +void *_ioapic_eoi_get(unsigned int irq, char *argRequired, void **arg); +void _ioapic_irq_enable(unsigned int irq); +void _ioapic_irq_disable(unsigned int irq); +void _ioapic_int_vec_set(unsigned int irq, unsigned int vector); +void _ioapic_irq_set(unsigned int irq, unsigned int vector, uint32_t flags); +#endif /* _ASMLANGUAGE */ + +#endif /* CONFIG_IOAPIC */ + +#ifdef __cplusplus +} +#endif + +#endif /* __INCioapich */ diff --git a/include/drivers/k20Mcg.h b/include/drivers/k20Mcg.h new file mode 100644 index 00000000000..ca22470e32f --- /dev/null +++ b/include/drivers/k20Mcg.h @@ -0,0 +1,221 @@ +/* k20Mcg.h - K20 Microprocessor MCG register definitions */ + +/* + * Copyright (c) 2013-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This module defines the Multipurpose Clock Generator (MCG) and Oscillator (OSC) +registers for the K20 Family of microprocessors. +*/ +#ifndef _K20MCG_H_ +#define _K20MCG_H_ + +#include + +/* MCG - module register structure */ +typedef volatile struct +{ + uint8_t c1; /* 0x0 */ + uint8_t c2; /* 0x1 */ + uint8_t c3; /* 0x2 */ + uint8_t c4; /* 0x3 */ + uint8_t c5; /* 0x4 */ + uint8_t c6; /* 0x5 */ + uint8_t s; /* 0x6 */ + uint8_t res_7; + uint8_t sc; /* 0x8 */ + uint8_t res_9; + uint8_t atcvh; /* 0xA */ + uint8_t atcvl; /* 0xB */ + uint8_t c7; /* 0xC */ + uint8_t c8; /* 0xD */ +} K20_MCG_t; + +/* Control 1 register fields */ +#define MCG_C1_IREFSTEN_MASK 0x1 +#define MCG_C1_IREFSTEN_SHIFT 0 +#define MCG_C1_IRCLKEN_MASK 0x2 +#define MCG_C1_IRCLKEN_SHIFT 1 +#define MCG_C1_IREFS_MASK 0x4 +#define MCG_C1_IREFS_SHIFT 2 +#define MCG_C1_IREFS_EXT ((uint8_t)(0 << MCG_C1_IREFS_SHIFT)) +#define MCG_C1_IREFS_INT ((uint8_t)(1 << MCG_C1_IREFS_SHIFT)) +#define MCG_C1_FRDIV_MASK 0x38 +#define MCG_C1_FRDIV_SHIFT 3 +#define MCG_C1_FRDIV_1_32 ((uint8_t)(0 << MCG_C1_FRDIV_SHIFT)) +#define MCG_C1_FRDIV_2_64 ((uint8_t)(1 << MCG_C1_FRDIV_SHIFT)) +#define MCG_C1_FRDIV_4_128 ((uint8_t)(2 << MCG_C1_FRDIV_SHIFT)) +#define MCG_C1_FRDIV_8_256 ((uint8_t)(3 << MCG_C1_FRDIV_SHIFT)) +#define MCG_C1_FRDIV_16_512 ((uint8_t)(4 << MCG_C1_FRDIV_SHIFT)) +#define MCG_C1_FRDIV_32_1024 ((uint8_t)(5 << MCG_C1_FRDIV_SHIFT)) +#define MCG_C1_FRDIV_64_1280 ((uint8_t)(6 << MCG_C1_FRDIV_SHIFT)) +#define MCG_C1_FRDIV_128_1536 ((uint8_t)(7 << MCG_C1_FRDIV_SHIFT)) +#define MCG_C1_CLKS_MASK 0xC0 +#define MCG_C1_CLKS_SHIFT 6 +#define MCG_C1_CLKS_FLL_PLL ((uint8_t)(0 << MCG_C1_CLKS_SHIFT)) +#define MCG_C1_CLKS_INT_REF ((uint8_t)(1 << MCG_C1_CLKS_SHIFT)) +#define MCG_C1_CLKS_EXT_REF ((uint8_t)(2 << MCG_C1_CLKS_SHIFT)) + +/* Control 2 register fields */ +#define MCG_C2_IRCS_MASK 0x1 +#define MCG_C2_IRCS_SHIFT 0 +#define MCG_C2_LP_MASK 0x2 +#define MCG_C2_LP_SHIFT 1 +#define MCG_C2_EREFS_MASK 0x4 +#define MCG_C2_EREFS_SHIFT 2 +#define MCG_C2_EREFS_EXT_CLK ((uint8_t)(0 << MCG_C2_EREFS_SHIFT)) +#define MCG_C2_EREFS_OSC ((uint8_t)(1 << MCG_C2_EREFS_SHIFT)) +#define MCG_C2_HGO_MASK 0x8 +#define MCG_C2_HGO_SHIFT 3 +#define MCG_C2_HGO_LO_PWR ((uint8_t)(0 << MCG_C2_HGO_SHIFT)) +#define MCG_C2_HGO_HI_GAIN ((uint8_t)(1 << MCG_C2_HGO_SHIFT)) +#define MCG_C2_RANGE_MASK 0x30 +#define MCG_C2_RANGE_SHIFT 4 +#define MCG_C2_RANGE_LOW ((uint8_t)(0 << MCG_C2_RANGE_SHIFT)) +#define MCG_C2_RANGE_HIGH ((uint8_t)(1 << MCG_C2_RANGE_SHIFT)) +#define MCG_C2_RANGE_VHIGH ((uint8_t)(2 << MCG_C2_RANGE_SHIFT)) +#define MCG_C2_LOCRE0_MASK 0x80 +#define MCG_C2_LOCRE0_SHIFT 7 + +/* Control 3 register fields */ +#define MCG_C3_SCTRIM_MASK 0xFF +#define MCG_C3_SCTRIM_SHIFT 0 + +/* Control 4 register fields */ +#define MCG_C4_SCFTRIM_MASK 0x1 +#define MCG_C4_SCFTRIM_SHIFT 0 +#define MCG_C4_FCTRIM_MASK 0x1E +#define MCG_C4_FCTRIM_SHIFT 1 +#define MCG_C4_DRST_DRS_MASK 0x60 +#define MCG_C4_DRST_DRS_SHIFT 5 +#define MCG_C4_DMX32_MASK 0x80 +#define MCG_C4_DMX32_SHIFT 7 + +/* Control 5 register fields */ +#define MCG_C5_PRDIV0_MASK 0x1F +#define MCG_C5_PRDIV0_SHIFT 0 +#define MCG_C5_PLLSTEN0_MASK 0x20 +#define MCG_C5_PLLSTEN0_SHIFT 5 +#define MCG_C5_PLLCLKEN0_MASK 0x40 +#define MCG_C5_PLLCLKEN0_SHIFT 6 + +/* Control 6 register fields */ +#define MCG_C6_VDIV0_MASK 0x1F +#define MCG_C6_VDIV0_SHIFT 0 +#define MCG_C6_CME0_MASK 0x20 +#define MCG_C6_CME0_SHIFT 5 +#define MCG_C6_PLLS_MASK 0x40 +#define MCG_C6_PLLS_SHIFT 6 +#define MCG_C6_PLLS_FLL ((uint8_t)(0 << MCG_C6_PLLS_SHIFT)) +#define MCG_C6_PLLS_PLL ((uint8_t)(1 << MCG_C6_PLLS_SHIFT)) +#define MCG_C6_LOLIE0_MASK 0x80 +#define MCG_C6_LOLIE0_SHIFT 7 + +/* Status register fields */ +#define MCG_S_IRCST_MASK 0x1 +#define MCG_S_IRCST_SHIFT 0 +#define MCG_S_OSCINIT0_MASK 0x2 +#define MCG_S_OSCINIT0_SHIFT 1 +#define MCG_S_CLKST_MASK 0xC +#define MCG_S_CLKST_SHIFT 2 +#define MCG_S_CLKST_FLL ((uint8_t)(0 << MCG_S_CLKST_SHIFT)) +#define MCG_S_CLKST_INT_REF ((uint8_t)(1 << MCG_S_CLKST_SHIFT)) +#define MCG_S_CLKST_EXT_REF ((uint8_t)(2 << MCG_S_CLKST_SHIFT)) +#define MCG_S_CLKST_PLL ((uint8_t)(3 << MCG_S_CLKST_SHIFT)) +#define MCG_S_IREFST_MASK 0x10 +#define MCG_S_IREFST_SHIFT 4 +#define MCG_S_PLLST_MASK 0x20 +#define MCG_S_PLLST_SHIFT 5 +#define MCG_S_LOCK0_MASK 0x40 +#define MCG_S_LOCK0_SHIFT 6 +#define MCG_S_LOLS0_MASK 0x80 +#define MCG_S_LOLS0_SHIFT 7 + +/* Status and Control register fields */ +#define MCG_SC_LOCS0_MASK 0x1 +#define MCG_SC_LOCS0_SHIFT 0 +#define MCG_SC_FCRDIV_MASK 0xE +#define MCG_SC_FCRDIV_SHIFT 1 +#define MCG_SC_FLTPRSRV_MASK 0x10 +#define MCG_SC_FLTPRSRV_SHIFT 4 +#define MCG_SC_ATMF_MASK 0x20 +#define MCG_SC_ATMF_SHIFT 5 +#define MCG_SC_ATMS_MASK 0x40 +#define MCG_SC_ATMS_SHIFT 6 +#define MCG_SC_ATME_MASK 0x80 +#define MCG_SC_ATME_SHIFT 7 + +/* Auto Trim Compare Value High register fields */ +#define MCG_ATCVH_ATCVH_MASK 0xFF +#define MCG_ATCVH_ATCVH_SHIFT 0 + +/* Auto Trim Compare Value Low register fields */ +#define MCG_ATCVL_ATCVL_MASK 0xFF +#define MCG_ATCVL_ATCVL_SHIFT 0 + +/* Control 7 register fields */ +#define MCG_C7_OSCSEL_MASK 0x03 +#define MCG_C7_OSCSEL_SHIFT 0 +#define MCG_C7_OSCSEL_OSC0 ((uint8_t)0x0) +#define MCG_C7_OSCSEL_32KHZ_RTC ((uint8_t)0x1) +#define MCG_C7_OSCSEL_OSC1 ((uint8_t)0x2) + +/* Control 8 register fields */ +#define MCG_C8_LOCS1_MASK 0x1 +#define MCG_C8_LOCS1_SHIFT 0 +#define MCG_C8_CME1_MASK 0x20 +#define MCG_C8_CME1_SHIFT 5 +#define MCG_C8_LOLRE_MASK 0x40 +#define MCG_C8_LOLRE_SHIFT 6 + +/* OSC - module register structure */ +typedef volatile struct { + uint8_t cr; /* 0x0 */ +} K20_OSC_t; + +typedef union { + uint32_t value; /* reset 0x00 */ + struct { + uint8_t sc16p : 1 __attribute__((packed)); + uint8_t sc8p : 1 __attribute__((packed)); + uint8_t sc4p : 1 __attribute__((packed)); + uint8_t sc2p : 1 __attribute__((packed)); + uint8_t res_4 : 1 __attribute__((packed)); + uint8_t erefsten : 1 __attribute__((packed)); + uint8_t res_6 : 1 __attribute__((packed)); + uint8_t erclken : 1 __attribute__((packed)); + } field; +} OSC_CR_t; /* 0x0 */ + +/* Control register fields */ +#define OSC_CR_EXT_CLK_EN 0x80 + +#endif /* _K20MCG_H_ */ diff --git a/include/drivers/k20Pcr.h b/include/drivers/k20Pcr.h new file mode 100644 index 00000000000..8cf9930ef3a --- /dev/null +++ b/include/drivers/k20Pcr.h @@ -0,0 +1,105 @@ +/* k20Pcr.h - Freescale K20 microprocessor Pin Control register definitions */ + +/* + * Copyright (c) 2013-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This module defines the PCR (Port/Pin Control/Configuration Registers) for the +K20 Family of microprocessors +*/ + +#ifndef _K20PCR_H_ +#define _K20PCR_H_ + +#include + +#define PCR_PORT_A 0 +#define PCR_PORT_B 1 +#define PCR_PORT_C 2 +#define PCR_PORT_D 3 +#define PCR_PORT_E 4 + +#define PCR_MUX_DISABLED 0 +#define PCR_MUX_ALT1 1 +#define PCR_MUX_ALT2 2 +#define PCR_MUX_ALT3 3 +#define PCR_MUX_ALT4 4 +#define PCR_MUX_ALT5 5 +#define PCR_MUX_ALT6 6 +#define PCR_MUX_ALT7 7 + +typedef union { + uint32_t value; + struct { + uint8_t ps : 1 __attribute__((packed)); + uint8_t pe : 1 __attribute__((packed)); + uint8_t sre : 1 __attribute__((packed)); + uint8_t res_3 : 1 __attribute__((packed)); + uint8_t pfe : 1 __attribute__((packed)); + uint8_t ode : 1 __attribute__((packed)); + uint8_t dse : 1 __attribute__((packed)); + uint8_t res_7 : 1 __attribute__((packed)); + uint8_t mux : 3 __attribute__((packed)); + uint8_t res_11_14 : 4 __attribute__((packed)); + uint8_t lk : 1 __attribute__((packed)); + uint8_t irqc : 4 __attribute__((packed)); + uint8_t res_20_23 : 4 __attribute__((packed)); + uint8_t isf : 1 __attribute__((packed)); + uint8_t res_25_31 : 7 __attribute__((packed)); + } field; +} K20_PCR_t; /* Pin Control Register n, n= 0-31 */ + +typedef union { + uint32_t value; + struct { + uint16_t gpwe : 16 __attribute__((packed)); + uint16_t gpwd : 16 __attribute__((packed)); + } field; +} K20_GPC_t; /* Global Pin Control Low/High Register */ + +/* K20 Microntroller PCR module register structure */ + +typedef volatile struct { + struct { + K20_PCR_t pcr[32] __attribute__((packed)); /* 0x00-07C */ + K20_GPC_t gpchr __attribute__((packed)); /* 0x80 */ + K20_GPC_t gpclr __attribute__((packed)); /* 0x84 */ + uint8_t res_88_9F[0xA0 - 0x88]; /* 0x88-0x9F Reserved */ + uint32_t isfr __attribute__((packed)); /* 0xA0 */ + uint8_t res_A4_FF[0x1000 - 0xA4]; /* 0xA4-0xFFF Reserved */ + } port[5]; +} K20_PORT_PCR_t; + +/* pin control register for port A..E on pin 0..31 */ +#define K20_PCR(base, port, pin) \ + ((K20_PCR_t *)(base + (0x1000 * port) + (pin * 4))) + +#endif /* _K20PCR_H_ */ diff --git a/include/drivers/k20Sim.h b/include/drivers/k20Sim.h new file mode 100644 index 00000000000..ad2be52195d --- /dev/null +++ b/include/drivers/k20Sim.h @@ -0,0 +1,234 @@ +/* k20Sim.h - Freescale K20 microprocessor SIM Module register definitions */ + +/* + * Copyright (c) 2013-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This module defines the SIM (System Integration Module) Registers for the +K20 Family of microprocessors +*/ + +#ifndef _K20SIM_H_ +#define _K20SIM_H_ + +#include +#include + +#define SIM_OCS32K_SYS 0 +#define SIM_OCS32K_RTS 2 +#define SIM_OCS32K_LPO 3 /* 1kHz */ + +typedef union { + uint32_t value; /* reset = 0x8000 F03F */ + struct { + uint32_t res_0_11 : 12 __attribute__((packed)); + uint32_t ramSize : 4 __attribute__((packed)); + uint32_t res_16_17 : 2 __attribute__((packed)); + uint32_t osc32kSel : 2 __attribute__((packed)); + uint32_t res_20_28 : 9 __attribute__((packed)); + uint32_t usbVoltStby : 1 __attribute__((packed)); + uint32_t usbStopStby : 1 __attribute__((packed)); + uint32_t usbRegEn : 1 __attribute__((packed)); + } field; +} SIM_SOPT1_t; /* 0x000 */ + +typedef union { + uint32_t value; + struct { + uint32_t res_0_23 : 24 __attribute__((packed)); + uint32_t usbRegWriteEn : 1 __attribute__((packed)); + uint32_t usbVoltWriteEn : 1 __attribute__((packed)); + uint32_t usbStopWriteEn : 1 __attribute__((packed)); + uint32_t res_27_31 : 5 __attribute__((packed)); + } field; +} SIM_SOPT1CFG_t; /* 0x004 */ + +typedef union { + uint32_t value; + struct { + uint32_t res_0_3 : 4 __attribute__((packed)); + uint32_t rtcClkOutSel : 1 __attribute__((packed)); + uint32_t clkOutSel : 3 __attribute__((packed)); + uint32_t flexBusSL : 2 __attribute__((packed)); + uint32_t res_10 : 1 __attribute__((packed)); + uint32_t ptd7Pad : 1 __attribute__((packed)); + uint32_t traceClkSel : 1 __attribute__((packed)); + uint32_t res_13_15 : 3 __attribute__((packed)); + uint32_t fllPllClkSel : 1 __attribute__((packed)); + uint32_t res_17 : 1 __attribute__((packed)); + uint32_t usbSrc : 1 __attribute__((packed)); + uint32_t res_19_31 : 13 __attribute__((packed)); + } field; +} SIM_SOPT2_t; /* 0x1004 */ + +typedef union { + uint32_t value; + struct { + uint32_t ftm0Flt0 : 1 __attribute__((packed)); + uint32_t ftm0Flt1 : 1 __attribute__((packed)); + uint32_t ftm0Flt2 : 1 __attribute__((packed)); + uint32_t res_3 : 1 __attribute__((packed)); + uint32_t ftm1Flt0 : 1 __attribute__((packed)); + uint32_t res_5_7 : 3 __attribute__((packed)); + uint32_t ftm2Flt0 : 1 __attribute__((packed)); + uint32_t res_9_17 : 9 __attribute__((packed)); + uint32_t ftm1Ch0Src : 2 __attribute__((packed)); + uint32_t ftm2Ch0Src : 2 __attribute__((packed)); + uint32_t res_22_23 : 2 __attribute__((packed)); + uint32_t ftm0ClkSel : 1 __attribute__((packed)); + uint32_t ftm1ClkSel : 1 __attribute__((packed)); + uint32_t ftm2ClkSel : 1 __attribute__((packed)); + uint32_t res_27 : 1 __attribute__((packed)); + uint32_t ftm0Trg0Src : 1 __attribute__((packed)); + uint32_t ftm0Trg1Src : 1 __attribute__((packed)); + uint32_t res_30_31 : 2 __attribute__((packed)); + } field; +} SIM_SOPT4_t; /* 0x100C */ + +typedef union { + uint32_t value; + struct { + uint32_t uart0TxSrc : 2 __attribute__((packed)); + uint32_t uart0RxSrc : 2 __attribute__((packed)); + uint32_t uart1TxSrc : 2 __attribute__((packed)); + uint32_t uart1RxSrc : 2 __attribute__((packed)); + uint32_t res_8_31 : 24 __attribute__((packed)); + } field; +} SIM_SOPT5_t; /* 0x1010 */ + +typedef union { + uint32_t value; + struct { + uint32_t uart0TxSrc : 2 __attribute__((packed)); + uint32_t uart0RxSrc : 2 __attribute__((packed)); + uint32_t uart1TxSrc : 2 __attribute__((packed)); + uint32_t uart1RxSrc : 2 __attribute__((packed)); + uint32_t res_8_31 : 24 __attribute__((packed)); + } field; +} SIM_SCGC1_t; /* 0x1028*/ + +#define SIM_UART_CLK_ENABLE(uart) (uint32_t)(1 << (10 + uart)) +typedef union { + uint32_t value; + struct { + uint32_t res_0 : 1 __attribute__((packed)); + uint32_t ewmClkEn_0 : 1 __attribute__((packed)); + uint32_t cmtClkEn_0 : 1 __attribute__((packed)); + uint32_t res_3_5 : 3 __attribute__((packed)); + uint32_t i2c0ClkEn : 1 __attribute__((packed)); + uint32_t i2c1ClkEn : 1 __attribute__((packed)); + uint32_t res_8_9 : 2 __attribute__((packed)); + uint32_t uart0ClkEn : 1 __attribute__((packed)); + uint32_t uart1ClkEn : 1 __attribute__((packed)); + uint32_t uart2ClkEn : 1 __attribute__((packed)); + uint32_t uart3ClkEn : 1 __attribute__((packed)); + uint32_t res_14_17 : 4 __attribute__((packed)); + uint32_t usbClkEn : 1 __attribute__((packed)); + uint32_t cmpClkEn : 1 __attribute__((packed)); + uint32_t vrefClkEn : 1 __attribute__((packed)); + uint32_t res_21_31 : 11 __attribute__((packed)); + } field; +} SIM_SCGC4_t; /* 0x1034 */ + +#define SIM_SCGC5_PORTA_CLK_EN (1 << 9) +#define SIM_SCGC5_PORTB_CLK_EN (1 << 10) +#define SIM_SCGC5_PORTC_CLK_EN (1 << 11) +#define SIM_SCGC5_PORTD_CLK_EN (1 << 12) +#define SIM_SCGC5_PORTE_CLK_EN (1 << 13) + +typedef union { + uint32_t value; /* reset 0 */ + struct { + uint32_t lptimer : 1 __attribute__((packed)); + uint32_t res_1_4 : 4 __attribute__((packed)); + uint32_t tsi : 1 __attribute__((packed)); + uint32_t res_6_8 : 3 __attribute__((packed)); + uint32_t portA_ClkEn : 1 __attribute__((packed)); + uint32_t portB_ClkEn : 1 __attribute__((packed)); + uint32_t portC_ClkEn : 1 __attribute__((packed)); + uint32_t portD_ClkEn : 1 __attribute__((packed)); + uint32_t portE_ClkEn : 1 __attribute__((packed)); + uint32_t res_14_31 : 18 __attribute__((packed)); + } field; +} SIM_SCGC5_t; /* 0x1038 */ + +#define SIM_CLKDIV1_OUTDIV1_MASK 0xF0000000 +#define SIM_CLKDIV1_OUTDIV1_SHIFT 28 +#define SIM_CLKDIV1_OUTDIV2_MASK 0x0F000000 +#define SIM_CLKDIV1_OUTDIV2_SHIFT 24 +#define SIM_CLKDIV1_OUTDIV3_MASK 0x00F00000 +#define SIM_CLKDIV1_OUTDIV3_SHIFT 20 +#define SIM_CLKDIV1_OUTDIV4_MASK 0x000F0000 +#define SIM_CLKDIV1_OUTDIV4_SHIFT 16 +#define SIM_CLKDIV(value) ((value) - 1) + +typedef union { + uint32_t value; /* reset 0x0001 0000 */ + struct { + uint32_t res_0_15 : 16 __attribute__((packed)); + uint32_t outdiv4 : 4 __attribute__((packed)); + uint32_t outdiv3 : 4 __attribute__((packed)); + uint32_t outdiv2 : 4 __attribute__((packed)); + uint32_t outdiv1 : 4 __attribute__((packed)); + } field; +} SIM_CLKDIV1_t; /* 0x1044 */ + +/* K20 Microntroller SIM module register structure */ + +typedef volatile struct { + SIM_SOPT1_t sopt1; /* 0x0000 */ + SIM_SOPT1CFG_t sopt1Cfg; /* 0x0004 */ + uint8_t res0008_1003[0x1003 - 0x8]; /* 0x0008-0x1003 Reserved */ + SIM_SOPT2_t sopt2; /* 0x1004 */ + uint32_t res1008; /* 0x1008 Reserved */ + SIM_SOPT4_t sopt4; /* 0x100C */ + SIM_SOPT5_t sopt5; /* 0x1010 */ + uint32_t res1014; /* 0x1014 Reserved */ + uint32_t sopt7; /* 0x1018 */ + uint8_t res101c_1027[0x1027 - 0x101c]; /* Reserved */ + SIM_SCGC1_t scgc1; /* 0x1028 */ + uint32_t scgc2; /* 0x102C */ + uint32_t scgc3; /* 0x1030 */ + SIM_SCGC4_t scgc4; /* 0x1034 */ + SIM_SCGC5_t scgc5; /* 0x1038 */ + uint32_t scgc6; /* 0x103C */ + uint32_t scgc7; /* 0x1040 */ + SIM_CLKDIV1_t clkdiv1; /* 0x1044 */ + uint32_t clkdiv2; /* 0x1048 */ + uint8_t res104c_1063[0x1063 - 0x104c]; /* Reserved */ +} K20_SIM_t; + +static ALWAYS_INLINE void _k20SimUartClkEnable(K20_SIM_t *sim_p, uint8_t which) +{ + sim_p->scgc4.value |= SIM_UART_CLK_ENABLE(which); +} + +#endif /* _K20SIM_H_ */ diff --git a/include/drivers/k20Uart.h b/include/drivers/k20Uart.h new file mode 100644 index 00000000000..2261d735df0 --- /dev/null +++ b/include/drivers/k20Uart.h @@ -0,0 +1,252 @@ +/* k20Uart.h - Freescale K20 microprocessor UART register definitions */ + +/* + * Copyright (c) 2013-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This module defines the UART Registers for the K20 Family of microprocessors +*/ + +#ifndef _K20UART_H_ +#define _K20UART_H_ + +#include +#include + +typedef union { + uint8_t value; + struct { + uint8_t sbr : 5 __attribute__((packed)); /* Hi Baud Rate Bits */ + uint8_t res_5 : 1 __attribute__((packed)); + uint8_t rxEdgeIntEn : 1 + __attribute__((packed)); /* RxD Active Edge */ + uint8_t lbkdIntEn : 1 + __attribute__((packed)); /* LIN Break Detect */ + } field; +} BDH_t; /* 0x000 BaudRate High */ + +typedef union { + uint8_t value; + struct { + uint8_t oddParity : 1 __attribute__((packed)); + uint8_t parityEnable : 1 __attribute__((packed)); + uint8_t idleLineType : 1 __attribute__((packed)); + uint8_t rxWakepMethod : 1 __attribute__((packed)); + uint8_t mode9Bit : 1 __attribute__((packed)); + uint8_t remoteLoopback : 1 __attribute__((packed)); + uint8_t uartStopWait : 1 __attribute__((packed)); + uint8_t loopbackEn : 1 __attribute__((packed)); + } field; +} C1_t; /* 0x002 Control 1 */ + +#define RX_EN_MASK 0x04 +#define TX_EN_MASK 0x08 + +typedef union { + uint8_t value; + struct { + uint8_t sendBreak : 1 __attribute__((packed)); + uint8_t rxWakeupCtrl : 1 __attribute__((packed)); + uint8_t rxEnable : 1 __attribute__((packed)); + uint8_t txEnable : 1 __attribute__((packed)); + uint8_t idleLineIntEn : 1 __attribute__((packed)); + uint8_t rxFullInt_dmaTx_en : 1 __attribute__((packed)); + uint8_t txCompleteIntEn : 1 __attribute__((packed)); + uint8_t txInt_DmaTx_en : 1 __attribute__((packed)); + } field; +} C2_t; /* 0x003 Control 2 */ + +typedef union { + uint8_t value; + struct { + uint8_t parityErrIntEn : 1 __attribute__((packed)); + uint8_t frameErrIntEn : 1 __attribute__((packed)); + uint8_t noiseErrIntEn : 1 __attribute__((packed)); + uint8_t overrunErrIntEn : 1 __attribute__((packed)); + uint8_t txDataInvert : 1 __attribute__((packed)); + uint8_t txDataPinOuttDir : 1 __attribute__((packed)); + uint8_t txBit8 : 1 __attribute__((packed)); + uint8_t rxBit8 : 1 __attribute__((packed)); + } field; +} C3_t; /* 0x006 Control 3 */ + +typedef union { + uint8_t value; + struct { + uint8_t brfa : 5 + __attribute__((packed)); /* BaudRateFineAdjust*/ + uint8_t mode10Bit : 1 __attribute__((packed)); + uint8_t matechAddrMode1En : 1 __attribute__((packed)); + uint8_t matchAddrMode2En : 1 __attribute__((packed)); + } field; +} C4_t; /* 0x00A Control 4 */ + +#define TX_DATA_EMPTY_MASK 0x80 +#define RX_DATA_FULL_MASK 0x20 + +typedef union { + uint8_t value; + struct { + uint8_t parityErr : 1 __attribute__((packed)); + uint8_t framingErr : 1 __attribute__((packed)); + uint8_t noice : 1 __attribute__((packed)); + uint8_t rxOverrun : 1 __attribute__((packed)); + uint8_t idleLine : 1 __attribute__((packed)); + uint8_t rxDataFull : 1 __attribute__((packed)); + uint8_t txComplete : 1 __attribute__((packed)); + uint8_t txDataEmpty : 1 __attribute__((packed)); + } field; +} S1_t; /* 0x004 Status 1 */ + +typedef union { + uint8_t value; + struct e { + uint8_t rxActive : 1 __attribute__((packed)); + uint8_t linBkDetectEn : 1 __attribute__((packed)); + uint8_t brkCharLen13 : 1 __attribute__((packed)); + uint8_t rxWakeupIdleDetect : 1 __attribute__((packed)); + uint8_t rxDataInverted : 1 __attribute__((packed)); + uint8_t msbFirst : 1 __attribute__((packed)); + uint8_t rxedgif : 1 __attribute__((packed)); + uint8_t lbkdif : 1 __attribute__((packed)); + } field; +} S2_t; /* 0x005 Status 2 */ + +#define FIFO_SIZE_1 0 +#define FIFO_SIZE_4 1 +#define FIFO_SIZE_8 2 +#define FIFO_SIZE_16 3 +#define FIFO_SIZE_32 4 +#define FIFO_SIZE_64 5 +#define FIFO_SIZE_128 6 +#define FIFO_SIZE_RES 6 /* Reserved size */ + +#define RX_FIFO_EN_MASK 0x08 +#define TX_FIFO_EN_MASK 0x80 + +typedef union { + uint8_t value; + struct { + uint8_t rxFifoSize : 3 __attribute__((packed)); /* read-only */ + uint8_t rxFifoEn : 1 __attribute__((packed)); + uint8_t txFifoSize : 3 __attribute__((packed)); /* read-only */ + uint8_t txFifoEn : 1 __attribute__((packed)); + } field; +} PFIFO_t; /* 0x010 Fifo Parameter 1 */ + +#define RX_FIFO_FLUSH_MASK 0x40 +#define TX_FIFO_FLUSH_MASK 0x80 + +typedef union { + uint8_t value; + struct { + uint8_t rxFifoUnderflowIntEn : 1 __attribute__((packed)); + uint8_t txFifoOverflowIntEn : 1 __attribute__((packed)); + uint8_t rxFifoOverflowIntEn : 1 __attribute__((packed)); + uint8_t res_3 : 3 __attribute__((packed)); + uint8_t rxFifoFlush : 1 + __attribute__((packed)); /* write-only */ + uint8_t txFifoFlush : 1 + __attribute__((packed)); /* write-only */ + } field; +} CFIFO_t; /* 0x011 Fifo Control */ + +typedef volatile struct { + BDH_t bdh; /* 0x000 Baud Rate High */ + uint8_t bdl; /* 0x001 Baud Rate Low (04)*/ + C1_t c1; /* 0x002 Control 1 */ + C2_t c2; /* 0x003 Control 2 */ + S1_t s1; /* 0x004 Status 1 (C0) RO*/ + S2_t s2; /* 0x005 Status 2 */ + C3_t c3; /* 0x006 Control 3 */ + uint8_t d; /* 0x007 Data */ + uint8_t ma1; /* 0x008 Match Address 1 */ + uint8_t ma2; /* 0x009 Match Address 1 */ + C4_t c4; /* 0x00A Control 4 */ + uint8_t c5; /* 0x00B Control 5 */ + uint8_t ed; /* 0x00C Extended Data */ + uint8_t modem; /* 0x00D Modem */ + uint8_t ir; /* 0x00E Infrared */ + uint8_t zReserved00f; /* 0x00F */ + PFIFO_t pfifo; /* 0x010 FIFO Param */ + CFIFO_t cfifo; /* 0x011 FIFO Control */ + uint8_t sfifo; /* 0x012 FIFO Status (C0)*/ + uint8_t twfifo; /* 0x013 FIFO Tx Watermark */ + uint8_t tcfifo; /* 0x014 FIFO Tx Count */ + uint8_t rwfifo; /* 0x015 FIFO Rx Watermark (01)*/ + uint8_t rcfifo; /* 0x016 FIFO Rx Count */ + uint8_t u_7816[0x20 - 0x17]; /* 0x017-0x1F UART ISO-7816 standard */ + uint8_t u_cea709_1[0x32 - 0x20]; /* 0x020-0x31 UART CEA8709.1 standard + */ + uint8_t zReservStatused038_03c[0x1000 - 0x32]; /* 0x032-0xFFF Reserved + */ +} K20_UART_t; /* K20 Microntroller UART module */ + +static ALWAYS_INLINE void _k20UartBaudRateSet(K20_UART_t *uart_p, + uint32_t clkFreq, + uint32_t baudRate) +{ + /* + * The baud rate is calculated as: + * baudRate = clkFreq/(16*(SBR[12:0]+BRFA[5:0]/32)), where + * - SBR is the combined UART Baud Rate Register settings and + * - BRFA is the UART Baud Rate Fine Adjustment setting + * This is equivalent to: + * 32xSBR + BRFA = 2 * clkFreq/baudRate + */ + uint32_t clkBr = 2 * clkFreq / baudRate; + uint16_t sbr = clkBr >> 5; + uint8_t brfa = clkBr - (sbr << 5); + + __ASSERT((sbr && 0x1FFF), "clkFreq is too high or baudRate is too low"); + + /* Note there are other fields (interrupts flag) in BDH register */ + uart_p->bdh.field.sbr = (uint8_t)(sbr >> 8); + uart_p->bdl = (uint8_t)(sbr & 0xFF); + uart_p->c4.field.brfa = brfa; +} + +static inline void _k20UartFifoEnable(K20_UART_t *uart_p) +{ + uint8_t tx_rx_state = uart_p->c2.value && (TX_EN_MASK | RX_EN_MASK); + + /* disable Rx and Tx */ + uart_p->c2.value &= !(TX_EN_MASK | RX_EN_MASK); + + uart_p->pfifo.value |= (TX_FIFO_EN_MASK | RX_FIFO_EN_MASK); + + uart_p->cfifo.value |= (TX_FIFO_FLUSH_MASK | RX_FIFO_FLUSH_MASK); + + /* restore Rx and Tx */ + uart_p->c2.value |= tx_rx_state; +} + +#endif /* _K20UART_H_ */ diff --git a/include/drivers/k20Wdog.h b/include/drivers/k20Wdog.h new file mode 100644 index 00000000000..04009ce81f2 --- /dev/null +++ b/include/drivers/k20Wdog.h @@ -0,0 +1,152 @@ +/* k20Wdog.h - Freescale K20 microprocessor Watch Dog register definitions */ + +/* + * Copyright (c) 2013-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This module defines Watch Dog Registers for the K20 Family of microprocessors +*/ + +#ifndef _K20WDOG_H_ +#define _K20WDOG_H_ + +#include + +/* Sequence of writes within 20 bus cycles for action to take effect */ +#define WDOG_REFRESH_1 0xA602 +#define WDOG_REFRESH_2 0xB480 +#define WDOG_UNLOCK_1 0xC520 +#define WDOG_UNLOCK_2 0xD928 + +typedef union { + uint16_t value; /* reset= 0x01D3 */ + struct { + uint8_t wdogen : 1 __attribute__((packed)); + uint8_t clksrc : 1 __attribute__((packed)); + uint8_t irqrsten : 1 __attribute__((packed)); + uint8_t winen : 1 __attribute__((packed)); + uint8_t allowupdate : 1 __attribute__((packed)); + uint8_t dbgen : 1 __attribute__((packed)); + uint8_t stopen : 1 __attribute__((packed)); + uint8_t waiten : 1 __attribute__((packed)); + uint8_t res_8_9 : 2 __attribute__((packed)); + uint8_t testwdog : 1 __attribute__((packed)); + uint8_t testsel : 1 __attribute__((packed)); + uint8_t bytesel : 2 __attribute__((packed)); + uint8_t disestwdog : 1 __attribute__((packed)); + uint8_t res_15 : 1 __attribute__((packed)); + } field; +} WDOG_STCTRLH_t; + +/* K20 Microntroller WDOG module register structure */ + +typedef volatile struct { + WDOG_STCTRLH_t stctrlh; /* 0x00 */ + uint16_t stctrll; /* 0x02 */ + uint16_t tovalh; /* 0x04 */ + uint16_t tovall; /* 0x06 */ + uint16_t winh; /* 0x08 */ + uint16_t winl; /* 0x0A */ + uint16_t refresh; /* 0x0C */ + uint16_t unlock; /* 0x0E */ + uint16_t tmrouth; /* 0x10 */ + uint16_t tmroutl; /* 0x12 */ + uint16_t rstcnt; /* 0x14 */ + uint16_t presc; /* 0x16 */ +} K20_WDOG_t; + +/***********************************************************************/ +/*!< Macro to enable all interrupts. */ +#define EnableInterrupts __asm__(" CPSIE i"); + +/*!< Macro to disable all interrupts. */ +#define DisableInterrupts __asm__(" CPSID i"); +/***********************************************************************/ + +/******************************************************************************* + * + * wdog_unlock - Watchdog timer unlock routine. + * + * This routine will unlock the watchdog timer registers for write access. + * Writing 0xC520 followed by 0xD928 will unlock the write-once registers + * in the WDOG so they are writable within the WCT period. + * + * RETURNS: N/A + */ +static ALWAYS_INLINE void wdog_unlock(K20_WDOG_t *wdog_p) +{ + /* + * NOTE: DO NOT SINGLE STEP THROUGH THIS FUNCTION!!! + * There are timing requirements for the execution of the unlock + * process. + * Single stepping through the code you will cause the CPU to reset. + */ + + /* + * This sequence must execute within 20 clock cycles, so disable + * interrupts to keep the code atomic and ensure the timing. + */ + DisableInterrupts; + + /* Write 2-word unlock sequence to unlock register */ + wdog_p->unlock = (uint16_t)WDOG_UNLOCK_1; + wdog_p->unlock = (uint16_t)WDOG_UNLOCK_2; + + /* Re-enable interrupts now that we are done */ + EnableInterrupts; +} + +/******************************************************************************* + * + * wdog_disable - Watchdog timer disable routine + * + * This routine will disable the watchdog timer. + * + * RETURNS: N/A + */ +static ALWAYS_INLINE void wdog_disable(K20_WDOG_t *wdog_p) +{ + WDOG_STCTRLH_t stctrlh; + + /* First unlock the watchdog so that we can write to registers */ + wdog_unlock(wdog_p); + + /* + * Writes to control/configuration registers must execute within + * 256 clock cycles after unlocking, so interrupts may need to be + * disabled to ensure the timing. + */ + stctrlh.value = wdog_p->stctrlh.value; + stctrlh.field.wdogen = 0; + wdog_p->stctrlh.value = stctrlh.value; +} + +#endif /* _K20WDOG_H_ */ diff --git a/include/drivers/k6xMpu.h b/include/drivers/k6xMpu.h new file mode 100644 index 00000000000..0c1e6ba3757 --- /dev/null +++ b/include/drivers/k6xMpu.h @@ -0,0 +1,90 @@ +/* k6xMpu.h - Freescale K6x microprocessor MPU register definitions */ + +/* + * Copyright (c) 2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This module defines the Memory Protection Unit (MPU) Registers for the +K6x Family of microprocessors. +NOTE: Not all the registers are currently defined here - only those that are +currently used. +*/ + +#ifndef _K6xMPU_H_ +#define _K6xMPU_H_ + +#include + +#define MPU_VALID_MASK 0x01 +#define MPU_SLV_PORT_ERR_MASK 0xF8 + +typedef union { + uint32_t value; + struct { + uint8_t valid : 1 + __attribute__((packed)); /* MPU valid/enable */ + uint8_t res_1 : 7 __attribute__((packed)); /* RAZ/WI */ + uint8_t numRgnDescs : 4 + __attribute__((packed)); /* # of regions */ + uint8_t numSlvPorts : 4 + __attribute__((packed)); /* # of slave ports */ + uint8_t hwRevLvl : 4 + __attribute__((packed)); /* Hardware revision */ + uint8_t res_20 : 3 __attribute__((packed)); /* RAZ/WI */ + uint8_t res_23 : 1 __attribute__((packed)); /* RAO/WI */ + uint8_t res_24 : 3 __attribute__((packed)); /* RAZ/WI */ + uint8_t slvPortNErr : 5 + __attribute__((packed)); /* slave port N err */ + } field; +} CESR_t; /* 0x000 Control/Error Status Register */ + +#define MPU_NUM_SLV_PORTS 5 +#define MPU_NUM_REGIONS 12 +#define MPU_NUM_WORDS_PER_REGION 4 + +typedef volatile struct { + CESR_t ctrlErrStatus; /* 0x0000 */ + uint32_t errAddr0; /* 0x0010 */ + uint32_t errDetail0; /* 0x0014 */ + uint32_t errAddr1; /* 0x0018 */ + uint32_t errDetail1; /* 0x001C */ + uint32_t errAddr2; /* 0x0020 */ + uint32_t errDetail2; /* 0x0024 */ + uint32_t errAddr3; /* 0x0028 */ + uint32_t errDetail3; /* 0x002C */ + uint32_t errAddr4; /* 0x0030 */ + uint32_t errDetail4; /* 0x0034 */ + uint32_t rgnDesc[MPU_NUM_REGIONS][MPU_NUM_WORDS_PER_REGION]; /* 0x0400 + */ + uint32_t rgnDescAltAccCtrl[MPU_NUM_REGIONS]; /* 0x0800 */ +} K6x_MPU_t; /* K6x Microntroller PMC module */ + +#endif /* _K6xMPU_H_ */ diff --git a/include/drivers/k6xPmc.h b/include/drivers/k6xPmc.h new file mode 100644 index 00000000000..432267e3278 --- /dev/null +++ b/include/drivers/k6xPmc.h @@ -0,0 +1,71 @@ +/* k6xMpu.h - Freescale K6x microprocessor PMC register definitions */ + +/* + * Copyright (c) 2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This module defines the Power Management Controller (PMC) registers for the +K6x Family of microprocessors. +NOTE: Not all the registers are currently defined here - only those that are +currently used. +*/ + +#ifndef _K6xPMC_H_ +#define _K6xPMC_H_ + +#include + +#define PMC_REGSC_ACKISO_MASK 0x08 /* ack I/O isolation (write to clear) */ + +typedef union { + uint8_t value; + struct { + uint8_t bandgapBufEn : 1 + __attribute__((packed)); /* bandgap buffering */ + uint8_t res_1 : 1 __attribute__((packed)); /* SBZ */ + uint8_t regOnStatus : 1 + __attribute__((packed)); /* regulator on, R/O */ + uint8_t ackIsolation : 1 + __attribute__((packed)); /* ack I/O isolation */ + uint8_t bandgapEn : 1 + __attribute__((packed)); /* bandgap enable */ + uint8_t res_5 : 1 __attribute__((packed)); + uint8_t res_6 : 2 __attribute__((packed)); /* RAZ/WI */ + } field; +} REGSC_t; /* 0x0002 Regulator Status/Control Register */ + +typedef volatile struct { + uint8_t lvdsc1; /* 0x0000 */ + uint8_t lvdsc2; /* 0x0001 */ + REGSC_t regsc; /* 0x0002 */ +} K6x_PMC_t; /* K6x Microntroller PMC module */ + +#endif /* _K6xPMC_H_ */ diff --git a/include/drivers/loapic.h b/include/drivers/loapic.h new file mode 100644 index 00000000000..6563249d30a --- /dev/null +++ b/include/drivers/loapic.h @@ -0,0 +1,84 @@ +/* loapic.h - public LOAPIC APIs */ + +/* + * Copyright (c) 2015 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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 __INCloapich +#define __INCloapich + +#ifdef __cplusplus +extern "C" { +#endif + +/* Local APIC Register Offset */ + +#define LOAPIC_ID 0x020 /* Local APIC ID Reg */ +#define LOAPIC_VER 0x030 /* Local APIC Version Reg */ +#define LOAPIC_TPR 0x080 /* Task Priority Reg */ +#define LOAPIC_APR 0x090 /* Arbitration Priority Reg */ +#define LOAPIC_PPR 0x0a0 /* Processor Priority Reg */ +#define LOAPIC_EOI 0x0b0 /* EOI Reg */ +#define LOAPIC_LDR 0x0d0 /* Logical Destination Reg */ +#define LOAPIC_DFR 0x0e0 /* Destination Format Reg */ +#define LOAPIC_SVR 0x0f0 /* Spurious Interrupt Reg */ +#define LOAPIC_ISR 0x100 /* In-service Reg */ +#define LOAPIC_TMR 0x180 /* Trigger Mode Reg */ +#define LOAPIC_IRR 0x200 /* Interrupt Request Reg */ +#define LOAPIC_ESR 0x280 /* Error Status Reg */ +#define LOAPIC_ICRLO 0x300 /* Interrupt Command Reg */ +#define LOAPIC_ICRHI 0x310 /* Interrupt Command Reg */ +#define LOAPIC_TIMER 0x320 /* LVT (Timer) */ +#define LOAPIC_THERMAL 0x330 /* LVT (Thermal) */ +#define LOAPIC_PMC 0x340 /* LVT (PMC) */ +#define LOAPIC_LINT0 0x350 /* LVT (LINT0) */ +#define LOAPIC_LINT1 0x360 /* LVT (LINT1) */ +#define LOAPIC_ERROR 0x370 /* LVT (ERROR) */ +#define LOAPIC_TIMER 0x320 /* LVT (Timer) */ +#define LOAPIC_TIMER_ICR 0x380 /* Timer Initial Count Reg */ +#define LOAPIC_TIMER_CCR 0x390 /* Timer Current Count Reg */ +#define LOAPIC_TIMER_CONFIG 0x3e0 /* Timer Divide Config Reg */ + +#ifdef _ASMLANGUAGE +GTEXT(_loapic_eoi) +#else /* _ASMLANGUAGE */ +extern void _loapic_init(void); +extern void _loapic_eoi(unsigned int irq); +extern void _loapic_int_vec_set(unsigned int irq, unsigned int vector); +extern void _loapic_irq_enable(unsigned int irq); +extern void _loapic_irq_disable(unsigned int irq); +extern void _loapic_enable(void); +extern void _loapic_disable(void); +#endif /* _ASMLANGUAGE */ + +#ifdef __cplusplus +} +#endif + +#endif /* __INCloapich */ diff --git a/include/drivers/pic.h b/include/drivers/pic.h new file mode 100644 index 00000000000..02eddc02971 --- /dev/null +++ b/include/drivers/pic.h @@ -0,0 +1,81 @@ +/* pic.h - public Intel 8259 PIC APIs */ + +/* + * Copyright (c) 2015 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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 __INCpich +#define __INCpich + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(CONFIG_PIC) || defined(CONFIG_SHUTOFF_PIC) + +#define I8259_EOI 0x20 /* EOI bit in OCW2 */ + +/* register definitions */ +#define PIC_ADRS(baseAdrs, reg) (baseAdrs + (reg * PIC_REG_ADDR_INTERVAL)) + +#define PIC_PORT1(base) PIC_ADRS(base, 0x00) /* port 1 */ +#define PIC_PORT2(base) PIC_ADRS(base, 0x01) /* port 2 */ + +#define PIC_IMASK(base) PIC_PORT2(base) /* Int Mask Reg */ +#define PIC_IACK(base) PIC_PORT1(base) /* Int Ack Reg */ + +#define PIC_ISR_MASK(base) PIC_PORT1(base) /* in-service register mask */ +#define PIC_IRR_MASK(base) PIC_PORT1(base) /* interrupt request reg */ + +#ifdef _ASMLANGUAGE + +GTEXT(_i8259_boi_master) +GTEXT(_i8259_boi_slave) +GTEXT(_i8259_eoi_master) +GTEXT(_i8259_eoi_slave) + +#else /* _ASMLANGUAGE */ + +extern void _i8259_init(void); +extern void _i8259_boi_master(void); +extern void _i8259_boi_slave(void); +extern void _i8259_eoi_master(unsigned int irq); +extern void _i8259_eoi_slave(unsigned int irq); +extern void _i8259_irq_enable(unsigned int irq); +extern void _i8259_irq_disable(unsigned int irq); + +#endif /* _ASMLANGUAGE */ + +#endif /* CONFIG_PIC || CONFIG_SHUTOFF_PIC */ + +#ifdef __cplusplus +} +#endif + +#endif /* __INCpich */ diff --git a/include/drivers/rand32.h b/include/drivers/rand32.h new file mode 100644 index 00000000000..840c2d08afd --- /dev/null +++ b/include/drivers/rand32.h @@ -0,0 +1,53 @@ +/* rand32.h - random number generator header file */ + +/* + * Copyright (c) 2013-2014 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This header file declares prototypes for the kernel's random number generator +APIs. + +Typically a BSP should enable the hidden CUSTOM_RANDOM_GENERATOR configuration +option and provide its the implementations for _Rand32Init() and _Rand32Get(). +However, if it does not do so a project requiring random numbers must implement +these routines, or (for testing purposes only) enable the TEST_RANDOM_GENERATOR +configuration option. +*/ + +#ifndef __INCrand32h +#define __INCrand32h + +#include + +extern void _Rand32Init(void); +extern uint32_t _Rand32Get(void); + +#endif /* __INCrand32h */ diff --git a/include/drivers/system_timer.h b/include/drivers/system_timer.h new file mode 100644 index 00000000000..69efc8e36d6 --- /dev/null +++ b/include/drivers/system_timer.h @@ -0,0 +1,69 @@ +/* system_timer.h - timer driver API */ + +/* + * Copyright (c) 2015 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION + +Declare API implemented by system timer driver and used by kernel components. +*/ + +#ifndef _TIMER__H_ +#define _TIMER__H_ + +#ifdef _ASMLANGUAGE + +GTEXT(_timer_int_handler) + +#else /* _ASMLANGUAGE */ + +extern uint32_t timer_read(void); +extern void timer_driver(int prio); +/* + * Timer interrupt handler is one of the routines that the driver + * has to implement, but it is not necessarily an external function. + * The driver may implement it and use only when setting an + * interrupt handler by calling irq_connect. + */ +extern void _timer_int_handler(void *arg); + +#ifdef CONFIG_SYSTEM_TIMER_DISABLE +extern void timer_disable(void); +#endif + +#ifdef CONFIG_TICKLESS_IDLE +extern void _timer_idle_enter(int32_t ticks); +extern void _timer_idle_exit(void); +#endif /* TIMER_SUPPORTS_TICKLESS */ + +#endif /* _ASMLANGUAGE */ + +#endif /* _TIMER__H_ */ diff --git a/include/drivers/uart.h b/include/drivers/uart.h new file mode 100644 index 00000000000..22865d5d875 --- /dev/null +++ b/include/drivers/uart.h @@ -0,0 +1,76 @@ +/* uart.h - public UART driver APIs */ + +/* + * Copyright (c) 2015 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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 __INCuarth +#define __INCuarth + +#ifdef __cplusplus +extern "C" { +#endif + +/* generic UART info structure */ +struct uart_init_info { + int baud_rate; + uint32_t regs; /* base port number or MM base address */ + uint32_t sys_clk_freq; /* in Hz */ + uint8_t options; /* HW Flow Control option */ + uint8_t irq; /* interrupt request number */ + uint8_t int_pri; /* interrupt priority level */ +}; +/* UART driver has to configure the device to 8n1 */ + +void uart_init(int port, const struct uart_init_info *const pinfo); + +/* console I/O functions */ +int uart_poll_in(int port, unsigned char *pChar); +unsigned char uart_poll_out(int which, unsigned char outChar); + +/* interrupt driven I/O functions */ +int uart_fifo_fill(int port, const uint8_t *txData, int len); +int uart_fifo_read(int port, uint8_t *rxData, const int size); +void uart_irq_tx_enable(int port); +void uart_irq_tx_disable(int port); +int uart_irq_tx_ready(int port); +void uart_irq_rx_enable(int port); +void uart_irq_rx_disable(int port); +int uart_irq_rx_ready(int port); +void uart_irq_err_enable(int port); +void uart_irq_err_disable(int port); +int uart_irq_is_pending(int port); +int uart_irq_update(int port); +void uart_int_connect(int port, void (*isr)(void *), void *arg, void *stub); + +#ifdef __cplusplus +} +#endif + +#endif /* __INCuarth */ diff --git a/include/kernel_version.h b/include/kernel_version.h new file mode 100644 index 00000000000..69bd6d90f17 --- /dev/null +++ b/include/kernel_version.h @@ -0,0 +1,62 @@ +/* kernel version macros */ + +/* + * Copyright (c) 2015 Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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 _kernel_version__h_ +#define _kernel_version__h_ + +/* + * The kernel version has been converted from a string to a four-byte + * quantity that is divided into three parts. + * + * Part 1: The two most significant bytes are sub-divided into four nibbles, + * representing the kernel's numeric version, w.x.y.z. These fields denote: + * w -- generation release number + * x -- major release + * y -- minor release + * z -- servicepack release + * Each of these elements must therefore be in the range 0 to 15, inclusive. + * + * Part 2: The next most significant byte is used for a variety of flags and is + * broken down as follows: + * Bits 7..0 - Cleared as the are currently unused. + * + * Part 3: The least significant byte is reserved for future use. + */ +#define KERNEL_VER_GENERATION(ver) ((ver >> 28) & 0x0F) +#define KERNEL_VER_MAJOR(ver) ((ver >> 24) & 0x0F) +#define KERNEL_VER_MINOR(ver) ((ver >> 20) & 0x0F) +#define KERNEL_VER_SERVICEPACK(ver) ((ver >> 16) & 0x0F) + +/* return 8-bit flags */ +#define KERNEL_VER_FLAGS(ver) ((ver >> 8) & 0xFF) + +#endif /* _kernel_version__h_ */ diff --git a/include/linker-defs.h b/include/linker-defs.h new file mode 100644 index 00000000000..b1509d124b9 --- /dev/null +++ b/include/linker-defs.h @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2013-2014, Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +Platform independent, commonly used macros and defines related to linker script. + +This file may be included by: +- Linker script files: for linker section declarations +- C files: for external declaration of address or size of linker section +- Assembly files: for external declaration of address or size of linker section +*/ + +#ifndef _LINKERDEFS_H +#define _LINKERDEFS_H + +#include +#include + +/* include platform dependent linker-defs */ +#ifdef VXMICRO_ARCH_x86 +#include +#elif defined(VXMICRO_ARCH_arm) +/* Nothing yet to include */ +#elif defined(VXMICRO_ARCH_arc) +/* Nothing yet to include */ +#else +#error Arch not supported. +#endif + +#ifdef _LINKER +#ifdef VXMICRO_ARCH_x86 /* LINKER FILES: defines used by linker script */ +/* Should be moved to linker-common-defs.h */ +#if defined(CONFIG_XIP) +#define ROMABLE_REGION ROM +#else +#define ROMABLE_REGION RAM +#endif +#endif + +/* + * If image is loaded via kexec Linux system call, then program + * headers need to be page aligned. + * This can be done by section page aligning. + */ +#ifdef CONFIG_BOOTLOADER_KEXEC +#define KEXEC_PGALIGN_PAD(x) . = ALIGN(x); +#else +#define KEXEC_PGALIGN_PAD(x) +#endif + +#elif defined(_ASMLANGUAGE) +/* Assembly FILES: declaration defined by the linker script */ +GDATA(__bss_start) +GDATA(__bss_num_words) +#ifdef CONFIG_XIP +GDATA(__data_rom_start) +GDATA(__data_ram_start) +GDATA(__data_num_words) +#endif + +#else + +#include +extern char __bss_start[]; +extern int __bss_num_words[]; +#ifdef CONFIG_XIP +extern char __data_rom_start[]; +extern char __data_ram_start[]; +extern int __data_num_words[]; +#endif + +/* C FILES: declaration defined by the linker script */ + +#ifdef VXMICRO_ARCH_x86 +#include /* VIRT_ADDR, PHYS_ADDR */ +#endif /* VXMICRO_ARCH_x86 */ + +/* end address of image. */ +extern char _end[]; +#define _END_VPAGE (VIRT_ADDR) _end + +#endif /* ! _ASMLANGUAGE */ + +#endif /* _LINKERDEFS_H */ diff --git a/include/linker-tool-gcc.h b/include/linker-tool-gcc.h new file mode 100644 index 00000000000..2d0133fd46f --- /dev/null +++ b/include/linker-tool-gcc.h @@ -0,0 +1,105 @@ +/* linker-tool-gcc.h - GCC toolchain linker defs */ + +/* + * Copyright (c) 2013-2014, Wind River 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) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +/* +DESCRIPTION +This header file defines the necessary macros used by the linker script for +use with the GCC linker. +*/ + +#ifndef __LINKER_TOOL_GCC_H +#define __LINKER_TOOL_GCC_H + +#if defined(CONFIG_CPU_CORTEXM) +OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm") +ENTRY(KENTRY) +#elif defined(CONFIG_ARC) +OUTPUT_FORMAT("elf32-littlearc", "elf32-bigarc", "elf32-littlearc") +ENTRY(KENTRY) +#else +OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") +OUTPUT_ARCH(i386) +ENTRY(KENTRY) +#endif + +/* + * The GROUP_START() and GROUP_END() macros are used to define a group + * of sections located in one memory area, such as RAM, ROM, etc. + * The parameter is the name of the memory area. + */ +#define GROUP_START(where) +#define GROUP_END(where) + +/* + * The GROUP_LINK_IN() macro is located at the end of the section + * description and tells the linker that this section is located in + * the memory area specified by argument. + */ +#define GROUP_LINK_IN(where) > where + +/* + * The GROUP_FOLLOWS_AT() macro is located at the end of the section + * and indicates that the section does not specify an address at which + * it is to be loaded, but that it follows a section which did specify + * such an address + */ +#define GROUP_FOLLOWS_AT(where) AT > where + +/* + * The SECTION_PROLOGUE() macro is used to define the beginning of a section. + * The parameter is the name of the section, and the