diff --git a/config/cml/container_ruleset.template b/config/cml/container_ruleset.template index 974ce2a..450e7f1 100644 --- a/config/cml/container_ruleset.template +++ b/config/cml/container_ruleset.template @@ -137,7 +137,8 @@ default CONT%(cn)d_OPT_NAME from ((CONT%(cn)d_BAREMETAL_PROJ_THREADS_DEMO==y) ? "thread_demo%(cn)d" : ((CONT%(cn)d_BAREMETAL_PROJ_TEST_SUITE==y) ? "test_suite%(cn)d" : ((CONT%(cn)d_BAREMETAL_PROJ_UART_SERVICE==y) ? "uart_service%(cn)d" : -((CONT%(cn)d_BAREMETAL_PROJ_TIMER_SERVICE==y) ? "timer_service%(cn)d" : "empty%(cn)d")))))) +((CONT%(cn)d_BAREMETAL_PROJ_KMI_SERVICE==y) ? "kmi_service%(cn)d" : +((CONT%(cn)d_BAREMETAL_PROJ_TIMER_SERVICE==y) ? "timer_service%(cn)d" : "empty%(cn)d"))))))) when CONT%(cn)d_TYPE_LINUX==y suppress cont%(cn)d_default_pager_params unless CONT%(cn)d_TYPE_POSIX==y suppress cont%(cn)d_posix_pager_params @@ -168,6 +169,7 @@ CONT%(cn)d_BAREMETAL_PROJ_THREADS_DEMO 'Thread Library Demo' CONT%(cn)d_BAREMETAL_PROJ_TEST_SUITE 'Microkernel Tests' CONT%(cn)d_BAREMETAL_PROJ_UART_SERVICE 'UART Service' CONT%(cn)d_BAREMETAL_PROJ_TIMER_SERVICE 'Timer Service' +CONT%(cn)d_BAREMETAL_PROJ_KMI_SERVICE 'Keyboard Mouse Service' choices cont%(cn)d_baremetal_params CONT%(cn)d_BAREMETAL_PROJ_EMPTY @@ -176,6 +178,7 @@ choices cont%(cn)d_baremetal_params CONT%(cn)d_BAREMETAL_PROJ_TEST_SUITE CONT%(cn)d_BAREMETAL_PROJ_UART_SERVICE CONT%(cn)d_BAREMETAL_PROJ_TIMER_SERVICE + CONT%(cn)d_BAREMETAL_PROJ_KMI_SERVICE default CONT%(cn)d_BAREMETAL_PROJ_EMPTY menu cont%(cn)d_default_pager_params @@ -232,16 +235,22 @@ cont%(cn)d_cap_device_uart1 'Container %(cn)d UART1 Menu' cont%(cn)d_cap_device_uart2 'Container %(cn)d UART2 Menu' cont%(cn)d_cap_device_uart3 'Container %(cn)d UART3 Menu' cont%(cn)d_cap_device_timer1 'Container %(cn)d TIMER23 Menu' +cont%(cn)d_cap_device_keyboard0 'Container %(cn)d KEYBOARD0 Menu' +cont%(cn)d_cap_device_mouse0 'Container %(cn)d MOUSE0 Menu' CONT%(cn)d_CAP_DEVICE_UART1_USE 'Container %(cn)d UART1 Enable' CONT%(cn)d_CAP_DEVICE_UART2_USE 'Container %(cn)d UART2 Enable' CONT%(cn)d_CAP_DEVICE_UART3_USE 'Container %(cn)d UART3 Enable' CONT%(cn)d_CAP_DEVICE_TIMER1_USE 'Container %(cn)d TIMER23 Enable' +CONT%(cn)d_CAP_DEVICE_KEYBOARD0_USE 'Container %(cn)d KEYBOARD0 Enable' +CONT%(cn)d_CAP_DEVICE_MOUSE0_USE 'Container %(cn)d MOUSE0 Enable' default CONT%(cn)d_CAP_DEVICE_UART1_USE from n default CONT%(cn)d_CAP_DEVICE_UART2_USE from n default CONT%(cn)d_CAP_DEVICE_UART3_USE from n default CONT%(cn)d_CAP_DEVICE_TIMER1_USE from n +default CONT%(cn)d_CAP_DEVICE_KEYBOARD0_USE from n +default CONT%(cn)d_CAP_DEVICE_MOUSE0_USE from n menu cont%(cn)d_cap_device_uart1 CONT%(cn)d_CAP_DEVICE_UART1_USE @@ -255,11 +264,19 @@ menu cont%(cn)d_cap_device_uart3 menu cont%(cn)d_cap_device_timer1 CONT%(cn)d_CAP_DEVICE_TIMER1_USE +menu cont%(cn)d_cap_device_keyboard0 + CONT%(cn)d_CAP_DEVICE_KEYBOARD0_USE + +menu cont%(cn)d_cap_device_mouse0 + CONT%(cn)d_CAP_DEVICE_MOUSE0_USE + menu cont%(cn)d_device_list cont%(cn)d_cap_device_uart1 cont%(cn)d_cap_device_uart2 cont%(cn)d_cap_device_uart3 cont%(cn)d_cap_device_timer1 + cont%(cn)d_cap_device_keyboard0 + cont%(cn)d_cap_device_mouse0 # # Settings for Custom Capabilities diff --git a/config/cml/examples/kmi/kmi-pb926.cml b/config/cml/examples/kmi/kmi-pb926.cml new file mode 100644 index 0000000..a912d1f --- /dev/null +++ b/config/cml/examples/kmi/kmi-pb926.cml @@ -0,0 +1,316 @@ +# +# Automatically generated, don't edit +# +# Generated on: amit-laptop-ubuntu +# At: Mon, 29 Mar 2010 17:55:04 +0000 +# Linux version 2.6.28-11-generic (buildd@palmer) (gcc version 4.3.3 (Ubuntu 4.3.3-5ubuntu4) ) #42-Ubuntu SMP Fri Apr 17 01:57:59 UTC 2009 + +# +# Codezero Microkernel Configurator +# + +# +# Main architecture +# +CONFIG_ARCH_ARM=y + + +# +# ARM Architecture Configuration +# + +# +# ARM Platform Type +# + +# +# ARM Platform Type +# +CONFIG_PLATFORM_EB=n +CONFIG_PLATFORM_PBA8=n +CONFIG_PLATFORM_PB926=y +CONFIG_PLATFORM_PB11MPCORE=n +CONFIG_PLATFORM_BEAGLE=n +CONFIG_PLATFORM_PBA9=n + + + +# +# ARM CPU type +# + +# +# ARM Processor Type +# +CONFIG_CPU_ARM926=y + + + + +# +# Generic Processor Properties +# +CONFIG_ICACHE_DISABLE=n +CONFIG_DCACHE_DISABLE=n + + +# +# Generic Kernel Properties +# +CONFIG_PREEMPT_DISABLE=n +CONFIG_DEBUG_ACCOUNTING=n +CONFIG_DEBUG_SPINLOCKS=n +CONFIG_SCHED_TICKS=1000 + + +# +# Toolchain Prefix +# +CONFIG_TOOLCHAIN="arm-none-eabi-" + + +# +# Container Setup +# +CONFIG_CAPABILITIES=y +CONFIG_CONTAINERS=1 + +# +# Container 0 Parameters +# + +# +# Container 0 Type +# +CONFIG_CONT0_TYPE_BAREMETAL=y +CONFIG_CONT0_TYPE_POSIX=n +CONFIG_CONT0_TYPE_LINUX=n + + +# +# Container 0 Options +# +CONFIG_CONT0_OPT_NAME="kmi_service0" + +# +# Baremetal Project +# +CONFIG_CONT0_BAREMETAL_PROJ_EMPTY=n +CONFIG_CONT0_BAREMETAL_PROJ_HELLO_WORLD=n +CONFIG_CONT0_BAREMETAL_PROJ_THREADS_DEMO=n +CONFIG_CONT0_BAREMETAL_PROJ_TEST_SUITE=n +CONFIG_CONT0_BAREMETAL_PROJ_UART_SERVICE=n +CONFIG_CONT0_BAREMETAL_PROJ_TIMER_SERVICE=n +CONFIG_CONT0_BAREMETAL_PROJ_KMI_SERVICE=y + + +# +# Container 0 Default Pager Parameters +# +CONFIG_CONT0_PAGER_LMA=0x100000 +CONFIG_CONT0_PAGER_VMA=0xa0000000 + + +# +# Container 0 Physical Memory Regions (Capabilities) +# +CONFIG_CONT0_PHYSMEM_REGIONS=1 +CONFIG_CONT0_PHYS0_START=0x100000 +CONFIG_CONT0_PHYS0_END=0xe00000 + + +# +# Container 0 Virtual Memory Regions (Capabilities) +# +CONFIG_CONT0_VIRTMEM_REGIONS=1 +CONFIG_CONT0_VIRT0_START=0xa0000000 +CONFIG_CONT0_VIRT0_END=0xb0000000 + + +# +# Container 0 Capability List +# + +# +# Container 0 Thread Pool Capability +# +CONFIG_CONT0_CAP_THREADPOOL_USE=y +CONFIG_CONT0_CAP_THREADPOOL_SIZE=64 + + +# +# Container 0 Space Pool Capability +# +CONFIG_CONT0_CAP_SPACEPOOL_USE=y +CONFIG_CONT0_CAP_SPACEPOOL_SIZE=64 + + +# +# Container 0 Mutex Pool Capability +# +CONFIG_CONT0_CAP_MUTEXPOOL_USE=y +CONFIG_CONT0_CAP_MUTEXPOOL_SIZE=100 + + +# +# Container 0 Map Pool Capability +# +CONFIG_CONT0_CAP_MAPPOOL_USE=y +CONFIG_CONT0_CAP_MAPPOOL_SIZE=800 + + +# +# Container 0 Capability Pool Capability +# +CONFIG_CONT0_CAP_CAPPOOL_USE=y +CONFIG_CONT0_CAP_CAPPOOL_SIZE=32 + + +# +# Container 0 Thread Control Capability +# +CONFIG_CONT0_CAP_TCTRL_USE=y +CONFIG_CONT0_CAP_TCTRL_TARGET_CURRENT_CONTAINER=y +CONFIG_CONT0_CAP_TCTRL_TARGET_CURRENT_PAGER_SPACE=n + + +# +# Container 0 Exchange Registers Capability +# +CONFIG_CONT0_CAP_EXREGS_USE=y +CONFIG_CONT0_CAP_EXREGS_TARGET_CURRENT_CONTAINER=y +CONFIG_CONT0_CAP_EXREGS_TARGET_CURRENT_PAGER_SPACE=n + + +# +# Container 0 IPC Capability +# +CONFIG_CONT0_CAP_IPC_USE=y +CONFIG_CONT0_CAP_IPC_TARGET_CURRENT_CONTAINER=y +CONFIG_CONT0_CAP_IPC_TARGET_CURRENT_PAGER_SPACE=n +CONFIG_CONT0_CAP_IPC_TARGET_ANOTHER_CONTAINER=n +CONFIG_CONT0_CAP_IPC_TARGET_ANOTHER_PAGER=n + + +# +# Container 0 Capability Control Capability +# +CONFIG_CONT0_CAP_CAPCTRL_USE=y +CONFIG_CONT0_CAP_CAPCTRL_TARGET_CURRENT_CONTAINER=y +CONFIG_CONT0_CAP_CAPCTRL_TARGET_CURRENT_PAGER_SPACE=n + + +# +# Container 0 Userspace Mutex Control Capability +# +CONFIG_CONT0_CAP_UMUTEX_USE=y +CONFIG_CONT0_CAP_UMUTEX_TARGET_CURRENT_CONTAINER=y +CONFIG_CONT0_CAP_UMUTEX_TARGET_CURRENT_PAGER_SPACE=n + + +# +# Container 0 IRQ Control Capability +# +CONFIG_CONT0_CAP_IRQCTRL_USE=y +CONFIG_CONT0_CAP_IRQCTRL_TARGET_CURRENT_CONTAINER=y +CONFIG_CONT0_CAP_IRQCTRL_TARGET_CURRENT_PAGER_SPACE=n + + +# +# Container 0 Custom Capability 0 Parameters +# +CONFIG_CONT0_CAP_CUSTOM0_USE=n + + +# +# Container 0 Custom Capability 1 Parameters +# +CONFIG_CONT0_CAP_CUSTOM1_USE=n + + +# +# Container 0 Custom Capability 2 Parameters +# +CONFIG_CONT0_CAP_CUSTOM2_USE=n + + +# +# Container 0 Custom Capability 3 Parameters +# +CONFIG_CONT0_CAP_CUSTOM3_USE=n + + + +# +# Container 0 Devices (Capabilities) +# + +# +# Container 0 UART1 Menu +# +CONFIG_CONT0_CAP_DEVICE_UART1_USE=n + + +# +# Container 0 UART2 Menu +# +CONFIG_CONT0_CAP_DEVICE_UART2_USE=n + + +# +# Container 0 UART3 Menu +# +CONFIG_CONT0_CAP_DEVICE_UART3_USE=n + + +# +# Container 0 TIMER23 Menu +# +CONFIG_CONT0_CAP_DEVICE_TIMER1_USE=n + + +# +# Container 0 KEYBOARD0 Menu +# +CONFIG_CONT0_CAP_DEVICE_KEYBOARD0_USE=y + + +# +# Container 0 MOUSE0 Menu +# +CONFIG_CONT0_CAP_DEVICE_MOUSE0_USE=y + + + + + + +# +# Derived symbols +# +CONFIG_CONT3_START_PC_ADDR=0xd0000000 +CONFIG_DEBUG_PERFMON_KERNEL=n +CONFIG_SUBARCH_V5=y +CONFIG_CONT1_PAGER_LOAD_ADDR=0x1100000 +CONFIG_DRIVER_IRQ_PL190=y +CONFIG_DRIVER_TIMER_SP804=y +CONFIG_CONT2_START_PC_ADDR=0xc0000000 +CONFIG_DRIVER_IRQ_GIC=n +CONFIG_CONT2_PAGER_VIRT_ADDR=0xc0000000 +CONFIG_RAM_BASE_PLAT=0 +CONFIG_DRIVER_INTC_OMAP=n +CONFIG_CONT2_PAGER_LOAD_ADDR=0x2100000 +CONFIG_CONT1_PAGER_VIRT_ADDR=0xb0000000 +CONFIG_CONT3_PAGER_LOAD_ADDR=0x3100000 +CONFIG_SUBARCH_V7=n +CONFIG_SUBARCH_V6=n +CONFIG_DRIVER_TIMER_OMAP=n +CONFIG_CONT0_PAGER_LOAD_ADDR=0x100000 +CONFIG_CONT0_PAGER_VIRT_ADDR=0xa0000000 +CONFIG_DRIVER_UART_OMAP=n +CONFIG_DRIVER_UART_PL011=y +CONFIG_CONT3_PAGER_VIRT_ADDR=0xd0000000 +CONFIG_CONT0_START_PC_ADDR=0xa0000000 +CONFIG_CONT1_START_PC_ADDR=0xb0000000 +# +# That's all, folks! diff --git a/conts/baremetal/kmi_service/SConstruct b/conts/baremetal/kmi_service/SConstruct new file mode 100755 index 0000000..707fb8a --- /dev/null +++ b/conts/baremetal/kmi_service/SConstruct @@ -0,0 +1,70 @@ +# -*- mode: python; coding: utf-8; -*- +# +# Codezero -- Virtualization microkernel for embedded systems. +# +# Copyright © 2009 B Labs Ltd +# +import os, shelve, sys +from os.path import * + +PROJRELROOT = '../..' + +sys.path.append(PROJRELROOT) + +from config.projpaths import * +from config.configuration import * +from configure import * + +config = configuration_retrieve() +arch = config.arch +platform = config.platform +gcc_arch_flag = config.gcc_arch_flag + +# Wrapper library for system calls +LIBL4_RELDIR = 'conts/libl4' +KERNEL_INCLUDE = join(PROJROOT, 'include') +LIBL4_DIR = join(PROJROOT, LIBL4_RELDIR) +LIBL4_INCLUDE = join(LIBL4_DIR, 'include') +LIBL4_LIBPATH = join(BUILDDIR, LIBL4_RELDIR) + +# Some user-space libraries +LIBC_RELDIR = 'conts/libc' +LIBC_DIR = join(PROJROOT, LIBC_RELDIR) +LIBC_LIBPATH = join(BUILDDIR, LIBC_RELDIR) +LIBC_INCLUDE = [join(LIBC_DIR, 'include'), \ + join(LIBC_DIR, 'include/arch' + '/' + arch)] + +LIBDEV_RELDIR = 'conts/libdev' +LIBDEV_DIR = join(PROJROOT, LIBDEV_RELDIR) +LIBDEV_LIBPATH = join(join(BUILDDIR, LIBDEV_RELDIR), 'sys-userspace') +LIBDEV_INCLUDE = join(LIBDEV_DIR, 'include') + +LIBMEM_RELDIR = 'conts/libmem' +LIBMEM_DIR = join(PROJROOT, LIBMEM_RELDIR) +LIBMEM_LIBPATH = join(BUILDDIR, LIBMEM_RELDIR) +LIBMEM_INCLUDE = LIBMEM_DIR + +env = Environment(CC = config.toolchain + 'gcc', + # We don't use -nostdinc because sometimes we need standard headers, + # such as stdarg.h e.g. for variable args, as in printk(). + CCFLAGS = ['-g', '-nostdlib', '-ffreestanding', '-std=gnu99', '-Wall', \ + '-Werror', '-march=' + gcc_arch_flag], \ + LINKFLAGS = ['-nostdlib', '-T' + "include/linker.lds", "-u_start"],\ + ASFLAGS = ['-D__ASSEMBLY__'], \ + PROGSUFFIX = '.elf', # The suffix to use for final executable + ENV = {'PATH' : os.environ['PATH']}, # Inherit shell path + LIBS = ['gcc', 'libl4', 'c-userspace', 'libdev-userspace', \ + 'libmm', 'libmc', 'libmalloc', 'gcc', 'c-userspace'], + # libgcc.a - This is required for division routines. + CPPPATH = ["#include", KERNEL_INCLUDE, LIBL4_INCLUDE, LIBDEV_INCLUDE, \ + LIBC_INCLUDE, LIBMEM_INCLUDE], + LIBPATH = [LIBL4_LIBPATH, LIBDEV_LIBPATH, LIBC_LIBPATH, LIBMEM_LIBPATH], + CPPFLAGS = '-include l4/config.h -include l4/macros.h -include l4/types.h') + +src = Glob('*.[cS]') +src += Glob('src/*.[cS]') +src += Glob('src/arch/*.[cS]') + +objs = env.Object(src) +prog = env.Program('main.elf', objs) +Depends(prog, 'include/linker.lds') diff --git a/conts/baremetal/kmi_service/container.c b/conts/baremetal/kmi_service/container.c new file mode 100755 index 0000000..7bcbf9e --- /dev/null +++ b/conts/baremetal/kmi_service/container.c @@ -0,0 +1,21 @@ +/* + * Container entry point for pager + * + * Copyright (C) 2007-2009 B Labs Ltd. + */ + +#include +#include + + +void main(void); + +void __container_init(void) +{ + /* Generic L4 initialisation */ + __l4_init(); + + /* Entry to main */ + main(); +} + diff --git a/conts/baremetal/kmi_service/include/container.h b/conts/baremetal/kmi_service/include/container.h new file mode 100755 index 0000000..45481dd --- /dev/null +++ b/conts/baremetal/kmi_service/include/container.h @@ -0,0 +1,13 @@ +/* + * Autogenerated definitions for this container. + */ +#ifndef __CONTAINER_H__ +#define __CONTAINER_H__ + + +#define __CONTAINER_NAME__ "kmi_service" +#define __CONTAINER_ID__ 0 +#define __CONTAINER__ "cont0" + + +#endif /* __CONTAINER_H__ */ diff --git a/conts/baremetal/kmi_service/include/keyboard.h b/conts/baremetal/kmi_service/include/keyboard.h new file mode 100755 index 0000000..7c783b0 --- /dev/null +++ b/conts/baremetal/kmi_service/include/keyboard.h @@ -0,0 +1,18 @@ +/* + * Keyboard details. + */ +#ifndef __KEYBOARD_H__ +#define __KEYBOARD_H__ + +#include + +/* + * Keyboard structure + */ +struct keyboard { + unsigned long base; /* Virtual base address */ + struct capability cap; /* Capability describing keyboard */ + struct keyboard_state state; +}; + +#endif /* __KEYBOARD_H__ */ diff --git a/conts/baremetal/kmi_service/include/linker.h b/conts/baremetal/kmi_service/include/linker.h new file mode 100755 index 0000000..e39da2f --- /dev/null +++ b/conts/baremetal/kmi_service/include/linker.h @@ -0,0 +1,7 @@ +#ifndef __LINKER_H__ +#define __LINKER_H__ + +extern char vma_start[]; +extern char __end[]; + +#endif /* __LINKER_H__ */ diff --git a/conts/baremetal/kmi_service/include/mouse.h b/conts/baremetal/kmi_service/include/mouse.h new file mode 100755 index 0000000..46c1e0c --- /dev/null +++ b/conts/baremetal/kmi_service/include/mouse.h @@ -0,0 +1,19 @@ +/* + * Mouse details. + */ +#ifndef __MOUSE_H__ +#define __MOUSE_H__ + +#include +#include +#include + +/* + * Keyboard structure + */ +struct mouse { + unsigned long base; /* Virtual base address */ + struct capability cap; /* Capability describing keyboard */ +}; + +#endif /* __MOUSE_H__ */ diff --git a/conts/baremetal/kmi_service/include/thread.h b/conts/baremetal/kmi_service/include/thread.h new file mode 100755 index 0000000..1805d27 --- /dev/null +++ b/conts/baremetal/kmi_service/include/thread.h @@ -0,0 +1,19 @@ +#ifndef __THREAD_H__ +#define __THREAD_H__ + +#include +#include L4LIB_INC_ARCH(syslib.h) +#include L4LIB_INC_ARCH(syscalls.h) +#include +#include + + +int thread_create(int (*func)(void *), void *args, unsigned int flags, + struct task_ids *new_ids); + +/* For same space */ +#define STACK_SIZE 0x1000 + +#define THREADS_TOTAL 10 + +#endif /* __THREAD_H__ */ diff --git a/conts/baremetal/kmi_service/main.c b/conts/baremetal/kmi_service/main.c new file mode 100755 index 0000000..80ca1f5 --- /dev/null +++ b/conts/baremetal/kmi_service/main.c @@ -0,0 +1,424 @@ +/* + * Keyboard and Mouse service for userspace + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define KEYBOARDS_TOTAL 1 +#define MOUSE_TOTAL 1 + +static struct capability caparray[32]; +static int total_caps = 0; + +struct keyboard kbd[KEYBOARDS_TOTAL]; +struct mouse mouse[MOUSE_TOTAL]; + +int cap_read_all() +{ + int ncaps; + int err; + + /* Read number of capabilities */ + if ((err = l4_capability_control(CAP_CONTROL_NCAPS, + 0, &ncaps)) < 0) { + printf("l4_capability_control() reading # of" + " capabilities failed.\n Could not " + "complete CAP_CONTROL_NCAPS request.\n"); + BUG(); + } + total_caps = ncaps; + + /* Read all capabilities */ + if ((err = l4_capability_control(CAP_CONTROL_READ, + 0, caparray)) < 0) { + printf("l4_capability_control() reading of " + "capabilities failed.\n Could not " + "complete CAP_CONTROL_READ_CAPS request.\n"); + BUG(); + } + return 0; +} + +int cap_share_all_with_space() +{ + int err; + + /* Share all capabilities */ + if ((err = l4_capability_control(CAP_CONTROL_SHARE, + CAP_SHARE_ALL_SPACE, 0)) < 0) { + printf("l4_capability_control() sharing of " + "capabilities failed.\n Could not " + "complete CAP_CONTROL_SHARE request. err=%d\n", + err); + BUG(); + } + + return 0; +} + +/* + * Scans for up to KEYBOARDS_TOTAL + * keyboard devices and MOUSE_TOTAL mouse + * in capabilities. + */ +int kmi_probe_devices(void) +{ + int keyboards = 0, nmouse = 0; + + /* Scan for timer devices */ + for (int i = 0; i < total_caps; i++) { + /* Match device type */ + if (cap_devtype(&caparray[i]) == CAP_DEVTYPE_KEYBOARD) { + /* Copy to correct device index */ + memcpy(&kbd[cap_devnum(&caparray[i])].cap, + &caparray[i], sizeof(kbd[0].cap)); + keyboards++; + } + if (cap_devtype(&caparray[i]) == CAP_DEVTYPE_MOUSE) { + /* Copy to correct device index */ + memcpy(&mouse[cap_devnum(&caparray[i])].cap, + &caparray[i], sizeof(mouse[0].cap)); + nmouse++; + } + + } + + if (keyboards != KEYBOARDS_TOTAL) { + printf("%s: Error, not all keyboards could be found. " + "keyboards=%d\n", __CONTAINER_NAME__, keyboards); + return -ENODEV; + } + if (nmouse != MOUSE_TOTAL) { + printf("%s: Error, not all mouse could be found. " + "mouse=%d\n", __CONTAINER_NAME__, nmouse); + return -ENODEV; + } + + return 0; +} + +int keyboard_irq_handler(void *arg) +{ + int err; + struct keyboard *keyboard = (struct keyboard *)arg; + const int slot = 0; + + /* + * For versatile, KMI refernce clock = 24MHz + * KMI manual says we need 8MHz clock, + * so divide by 3 + */ + kmi_keyboard_init(keyboard->base, 3); + printf("%s: Keyboard initialization done..\n", __CONTAINER_NAME__); + + /* Register self for timer irq, using notify slot 0 */ + if ((err = l4_irq_control(IRQ_CONTROL_REGISTER, slot, + keyboard->cap.irq)) < 0) { + printf("%s: FATAL: Keyboard irq could not be registered. " + "err=%d\n", __FUNCTION__, err); + BUG(); + } + + /* Handle irqs forever */ + while (1) { + char c; + + /* Block on irq */ + int data = l4_irq_wait(slot, keyboard->cap.irq); + while (data--) + if ((c = kmi_keyboard_read(keyboard->base, &keyboard->state))) + printf("%c", c); + } +} + +int mouse_irq_handler(void *arg) +{ + int err; + struct mouse *mouse = (struct mouse *)arg; + const int slot = 0; + + /* + * For versatile, KMI refernce clock = 24MHz + * KMI manual says we need 8MHz clock, + * so divide by 3 + */ + kmi_mouse_init(mouse->base, 3); + printf("%s: Mouse initialization done..\n", __CONTAINER_NAME__); + + /* Register self for timer irq, using notify slot 0 */ + if ((err = l4_irq_control(IRQ_CONTROL_REGISTER, slot, + mouse->cap.irq)) < 0) { + printf("%s: FATAL: Mouse irq could not be registered. " + "err=%d\n", __FUNCTION__, err); + BUG(); + } + + /* Handle irqs forever */ + while (1) { + int c; + + /* Block on irq */ + int data = l4_irq_wait(slot, mouse->cap.irq); + while (data--) + if ((c = kmi_data_read(mouse->base))) + printf("mouse data: %d\n", c); + } +} + +int kmi_setup_devices(void) +{ + struct task_ids irq_tids; + int err; + + for (int i = 0; i < KEYBOARDS_TOTAL; i++) { + /* Get one page from address pool */ + kbd[i].base = (unsigned long)l4_new_virtual(1); + kbd[i].state.shift = 0; + kbd[i].state.caps_lock = 0; + kbd[i].state.keyup = 0; + + /* Map timer to a virtual address region */ + if (IS_ERR(l4_map((void *)__pfn_to_addr(kbd[i].cap.start), + (void *)kbd[i].base, kbd[i].cap.size, + MAP_USR_IO, self_tid()))) { + printf("%s: FATAL: Failed to map Keyboard device " + "%d to a virtual address\n", + __CONTAINER_NAME__, + cap_devnum(&kbd[i].cap)); + BUG(); + } + + /* + * Create new keyboard irq handler thread. + * + * This will initialize its keyboard argument, register + * itself as its irq handler, initiate keyboard and + * wait on irqs. + */ + if ((err = thread_create(keyboard_irq_handler, &kbd[i], + TC_SHARE_SPACE, + &irq_tids)) < 0) { + printf("FATAL: Creation of irq handler " + "thread failed.\n"); + BUG(); + } + } + + for (int i = 0; i < MOUSE_TOTAL; i++) { + /* Get one page from address pool */ + mouse[i].base = (unsigned long)l4_new_virtual(1); + + /* Map timer to a virtual address region */ + if (IS_ERR(l4_map((void *)__pfn_to_addr(mouse[i].cap.start), + (void *)mouse[i].base, mouse[i].cap.size, + MAP_USR_IO, self_tid()))) { + printf("%s: FATAL: Failed to map Mouse device " + "%d to a virtual address\n", + __CONTAINER_NAME__, cap_devnum(&mouse[i].cap)); + BUG(); + } + + /* + * Create new mouse irq handler thread. + * + * This will initialize its mouse argument, register + * itself as its irq handler, initiate mouse and + * wait on irqs. + */ + if ((err = thread_create(mouse_irq_handler, &mouse[i], + TC_SHARE_SPACE, &irq_tids)) < 0) { + printf("FATAL: Creation of irq handler " + "thread failed.\n"); + BUG(); + } + } + + return 0; +} + +/* + * Declare a statically allocated char buffer + * with enough bitmap size to cover given size + */ +#define DECLARE_IDPOOL(name, size) \ +char name[(sizeof(struct id_pool) + ((size >> 12) >> 3))] + +#define PAGE_POOL_SIZE SZ_1MB +static struct address_pool device_vaddr_pool; +DECLARE_IDPOOL(device_id_pool, PAGE_POOL_SIZE); + +/* + * Initialize a virtual address pool + * for mapping physical devices. + */ +void init_vaddr_pool(void) +{ + for (int i = 0; i < total_caps; i++) { + /* Find the virtual memory region for this process */ + if (cap_type(&caparray[i]) == CAP_TYPE_MAP_VIRTMEM + && __pfn_to_addr(caparray[i].start) == + (unsigned long)vma_start) { + + /* + * Do we have any unused virtual space + * where we run, and do we have enough + * pages of it to map all timers? + */ + if (__pfn(page_align_up(__end)) + KEYBOARDS_TOTAL + + MOUSE_TOTAL <= caparray[i].end) { + /* + * Yes. We initialize the device + * virtual memory pool here. + * + * We may allocate virtual memory + * addresses from this pool. + */ + address_pool_init(&device_vaddr_pool, + (struct id_pool *)&device_id_pool, + page_align_up(__end), + __pfn_to_addr(caparray[i].end)); + return; + } else + goto out_err; + } + } + +out_err: + printf("%s: FATAL: No virtual memory " + "region available to map " + "devices.\n", __CONTAINER_NAME__); + BUG(); +} + +void *l4_new_virtual(int npages) +{ + return address_new(&device_vaddr_pool, npages, PAGE_SIZE); +} + +void handle_requests(void) +{ + u32 mr[MR_UNUSED_TOTAL]; + l4id_t senderid; + u32 tag; + int ret; + + printf("%s: Initiating ipc.\n", __CONTAINER__); + if ((ret = l4_receive(L4_ANYTHREAD)) < 0) { + printf("%s: %s: IPC Error: %d. Quitting...\n", __CONTAINER__, + __FUNCTION__, ret); + BUG(); + } + + /* Syslib conventional ipc data which uses first few mrs. */ + tag = l4_get_tag(); + senderid = l4_get_sender(); + + /* Read mrs not used by syslib */ + for (int i = 0; i < MR_UNUSED_TOTAL; i++) + mr[i] = read_mr(MR_UNUSED_START + i); + + /* + * TODO: + * + * Maybe add tags here that handle requests for sharing + * of the requested timer device with the client? + * + * In order to be able to do that, we should have a + * shareable/grantable capability to the device. Also + * the request should (currently) come from a task + * inside the current container + */ + switch (tag) { + default: + printf("%s: Error received ipc from 0x%x residing " + "in container %x with an unrecognized tag: " + "0x%x\n", __CONTAINER__, senderid, + __cid(senderid), tag); + } + + /* Reply */ + if ((ret = l4_ipc_return(ret)) < 0) { + printf("%s: IPC return error: %d.\n", __FUNCTION__, ret); + BUG(); + } +} + +/* + * UTCB-size aligned utcb. + * + * BIG WARNING NOTE: This declaration is legal if we are + * running in a disjoint virtual address space, where the + * utcb declaration lies in a unique virtual address in + * the system. + */ +#define DECLARE_UTCB(name) \ + struct utcb name ALIGN(sizeof(struct utcb)) + +DECLARE_UTCB(utcb); + +/* Set up own utcb for ipc */ +int l4_utcb_setup(void *utcb_address) +{ + struct task_ids ids; + struct exregs_data exregs; + int err; + + l4_getid(&ids); + + /* Clear utcb */ + memset(utcb_address, 0, sizeof(struct utcb)); + + /* Setup exregs for utcb request */ + memset(&exregs, 0, sizeof(exregs)); + exregs_set_utcb(&exregs, (unsigned long)utcb_address); + + if ((err = l4_exchange_registers(&exregs, ids.tid)) < 0) + return err; + + return 0; +} + +void main(void) +{ + int err; + + /* Read all capabilities */ + cap_read_all(); + + /* Share all with space */ + cap_share_all_with_space(); + + /* Scan for keyboard devices in capabilities */ + kmi_probe_devices(); + + /* Initialize virtual address pool for timers */ + init_vaddr_pool(); + + /* Setup own static utcb */ + if ((err = l4_utcb_setup(&utcb)) < 0) { + printf("FATAL: Could not set up own utcb. " + "err=%d\n", err); + BUG(); + } + + /* Map and initialize keyboard devices */ + kmi_setup_devices(); + + /* Listen for timer requests */ + while (1) + handle_requests(); +} + + diff --git a/conts/baremetal/kmi_service/src/new_thread.S b/conts/baremetal/kmi_service/src/new_thread.S new file mode 100755 index 0000000..68c5ea5 --- /dev/null +++ b/conts/baremetal/kmi_service/src/new_thread.S @@ -0,0 +1,11 @@ +#include +#include L4LIB_INC_ARCH(asm.h) + +BEGIN_PROC(local_setup_new_thread) + ldr r0, [sp, #-4]! @ Load first argument. + mov lr, pc @ Save return address + ldr pc, [sp, #-4]! @ Load function pointer from stack +new_thread_exit: + b new_thread_exit @ We infinitely loop for now. +END_PROC(local_setup_new_thread) + diff --git a/conts/baremetal/kmi_service/src/thread.c b/conts/baremetal/kmi_service/src/thread.c new file mode 100755 index 0000000..5a865d9 --- /dev/null +++ b/conts/baremetal/kmi_service/src/thread.c @@ -0,0 +1,73 @@ +/* + * Thread creation userspace helpers + * + * Copyright (C) 2009 B Labs Ltd. + */ +#include +#include + +char stack[THREADS_TOTAL][STACK_SIZE] ALIGN(8); +char *__stack_ptr = &stack[1][0]; + +char utcb[THREADS_TOTAL][UTCB_SIZE] ALIGN(8); +char *__utcb_ptr = &utcb[1][0]; + +extern void local_setup_new_thread(void); + +int thread_create(int (*func)(void *), void *args, unsigned int flags, + struct task_ids *new_ids) +{ + struct task_ids ids; + struct exregs_data exregs; + int err; + + l4_getid(&ids); + + /* Shared space only */ + if (!(TC_SHARE_SPACE & flags)) { + printf("%s: This function allows only " + "shared space thread creation.\n", + __FUNCTION__); + return -EINVAL; + } + + /* Create thread */ + if ((err = l4_thread_control(THREAD_CREATE | flags, &ids)) < 0) + return err; + + /* Check if more stack/utcb available */ + if ((unsigned long)__utcb_ptr == + (unsigned long)&utcb[THREADS_TOTAL][0]) + return -ENOMEM; + if ((unsigned long)__stack_ptr == + (unsigned long)&stack[THREADS_TOTAL][0]) + return -ENOMEM; + + /* First word of new stack is arg */ + ((unsigned long *)__stack_ptr)[-1] = (unsigned long)args; + + /* Second word of new stack is function address */ + ((unsigned long *)__stack_ptr)[-2] = (unsigned long)func; + + /* Setup new thread pc, sp, utcb */ + memset(&exregs, 0, sizeof(exregs)); + exregs_set_stack(&exregs, (unsigned long)__stack_ptr); + exregs_set_utcb(&exregs, (unsigned long)__utcb_ptr); + exregs_set_pc(&exregs, (unsigned long)local_setup_new_thread); + + if ((err = l4_exchange_registers(&exregs, ids.tid)) < 0) + return err; + + /* Update utcb, stack pointers */ + __stack_ptr += STACK_SIZE; + __utcb_ptr += UTCB_SIZE; + + /* Start the new thread */ + if ((err = l4_thread_control(THREAD_RUN, &ids)) < 0) + return err; + + memcpy(new_ids, &ids, sizeof(ids)); + + return 0; +} + diff --git a/conts/baremetal/timer_service/main.c b/conts/baremetal/timer_service/main.c index d3754ba..9944dfc 100644 --- a/conts/baremetal/timer_service/main.c +++ b/conts/baremetal/timer_service/main.c @@ -372,9 +372,9 @@ void init_vaddr_pool(void) * addresses from this pool. */ address_pool_init(&device_vaddr_pool, - (struct id_pool *)&device_id_pool, - page_align_up(__end), - __pfn_to_addr(caparray[i].end)); + (struct id_pool *)&device_id_pool, + page_align_up(__end), + __pfn_to_addr(caparray[i].end)); return; } else goto out_err; diff --git a/conts/libdev/SConscript b/conts/libdev/SConscript index 13f18d9..5528dba 100644 --- a/conts/libdev/SConscript +++ b/conts/libdev/SConscript @@ -36,6 +36,8 @@ objects += SConscript('uart/pl011/SConscript', duplicate=0, \ exports = {'platform' : platform, 'env' : e}) objects += SConscript('timer/sp804/SConscript', duplicate=0, \ exports = {'platform' : platform, 'env' : e}) +objects += SConscript('kmi/pl050/SConscript', duplicate=0, \ + exports = {'platform' : platform, 'env' : e}) objects += SConscript('uart/omap/SConscript', duplicate=0, \ exports = {'platform' : platform, 'env' : e}) diff --git a/conts/libdev/include/libdev/kmi.h b/conts/libdev/include/libdev/kmi.h new file mode 100755 index 0000000..3745780 --- /dev/null +++ b/conts/libdev/include/libdev/kmi.h @@ -0,0 +1,26 @@ + +#ifndef __KMI_H__ +#define __KMI_H__ + +/* + * Current keyboard state + */ +struct keyboard_state{ + int keyup; + int shift; + int caps_lock; +}; + +/* Common functions */ +void kmi_irq_handler(unsigned long base); +int kmi_data_read(unsigned long base); + +/* Keyboard specific calls */ +char kmi_keyboard_read(unsigned long base, struct keyboard_state *state); +void kmi_keyboard_init(unsigned long base, unsigned int div); + +/* Mouse specific calls */ +void kmi_mouse_enable(unsigned long base); +void kmi_mouse_init(unsigned long base, unsigned int div); + +#endif /* __KMI_H__ */ diff --git a/conts/libdev/kmi/pl050/SConscript b/conts/libdev/kmi/pl050/SConscript new file mode 100644 index 0000000..302f224 --- /dev/null +++ b/conts/libdev/kmi/pl050/SConscript @@ -0,0 +1,14 @@ +Import('env', 'platform') + +#Platforms using pl050 +plat_list = ('eb', 'pba8', 'pba9', 'pb11mpcore', 'pb926') + +# The set of source files associated with this SConscript file. +src_local = [] + +for plat_supported in plat_list: + if plat_supported == platform: + src_local += Glob('*.c') + +obj = env.StaticObject(src_local) +Return('obj') diff --git a/conts/libdev/kmi/pl050/keymap.h b/conts/libdev/kmi/pl050/keymap.h new file mode 100755 index 0000000..37be670 --- /dev/null +++ b/conts/libdev/kmi/pl050/keymap.h @@ -0,0 +1,280 @@ + +#ifndef __KEYMAP_H__ +#define __KEYMAP_H__ + +/* Special meaning keys */ +#define KEYCODE_LSHIFT 0x101 +#define KEYCODE_RSHIFT 0x102 +#define KEYCODE_LCTRL 0x103 +#define KEYCODE_RCTRL 0x104 +#define KEYCODE_ALT 0x105 +#define KEYCODE_ALTGR 0x106 + +#define KEYCODE_CAPSLK 0x201 +#define KEYCODE_SCRLK 0x202 +#define KEYCODE_NUMLK 0x203 + +#define KEYCODE_TAB 0x301 +#define KEYCODE_BACKSP 0x302 +#define KEYCODE_RETURN 0x303 +#define KEYCODE_ESCAPE 0x304 +#define KEYCODE_ENTER 0x305 + +#define KEYCODE_PRTSCR 0x401 +#define KEYCODE_BREAK 0x402 +#define KEYCODE_INSERT 0x403 +#define KEYCODE_HOME 0x404 +#define KEYCODE_PAGEUP 0x405 +#define KEYCODE_DELETE 0x406 +#define KEYCODE_END 0x407 +#define KEYCODE_PAGEDN 0x408 + +#define KEYCODE_UP 0x501 +#define KEYCODE_DOWN 0x502 +#define KEYCODE_LEFT 0x503 +#define KEYCODE_RIGHT 0x504 +#define KEYCODE_CENTER 0x505 + +#define KEYCODE_F1 0x601 +#define KEYCODE_F2 0x602 +#define KEYCODE_F3 0x603 +#define KEYCODE_F4 0x604 +#define KEYCODE_F5 0x605 +#define KEYCODE_F6 0x606 +#define KEYCODE_F7 0x607 +#define KEYCODE_F8 0x608 +#define KEYCODE_F9 0x609 +#define KEYCODE_F10 0x60A +#define KEYCODE_F11 0x60B +#define KEYCODE_F12 0x60C + +#define KEYCODE_WINL 0x701 +#define KEYCODE_WINR 0x702 +#define KEYCODE_MENU 0x703 + +#define MODIFIER_EXTENDED 0x00100000 +#define MODIFIER_EXTENDED2 0x00200000 +#define MODIFIER_RCTRL 0x00400000 +#define MODIFIER_RSHIFT 0x00800000 +#define MODIFIER_LSHIFT 0x01000000 +#define MODIFIER_LCTRL 0x02000000 +#define MODIFIER_ALT 0x04000000 +#define MODIFIER_ALTGR 0x08000000 +#define MODIFIER_SCRLK 0x10000000 +#define MODIFIER_NUMLK 0x20000000 +#define MODIFIER_CAPSLK 0x40000000 +#define MODIFIER_RELEASE 0x80000000 +#define MODIFIER_SHIFT (MODIFIER_LSHIFT | MODIFIER_RSHIFT) +#define MODIFIER_CTRL (MODIFIER_LCTRL | MODIFIER_RCTRL) + +struct keyboard_key { + int nomods; + int shift; + int ext_nomods; + int ext_shift; +}; + +/* + * Keymap for a UK keyboard + * maps key numbers->key codes + * + * We will use scan code index to get the key + * + * FIXME: element 1 and 4 gives, muticharacter + * character constant error, fix this. + */ +struct keyboard_key keymap_uk2[256] = { +/* 0 */ {0,0,0,0}, +#if 0 +/* 1 */ {'`','¬',0,0}, +#else +/* 1 */ {'`',0,0,0}, +#endif +/* 2 */ {'1','!',0,0}, +/* 3 */ {'2','"',0,0}, +#if 0 +/* 4 */ {'3','£',0,0}, +#else +/* 4 */ {'3',0,0,0}, +#endif +/* 5 */ {'4','$',0,0}, +/* 6 */ {'5','%',0,0}, +/* 7 */ {'6','^',0,0}, +/* 8 */ {'7','&',0,0}, +/* 9 */ {'8','*',0,0}, +/* 10 */ {'9','(',0,0}, +/* 11 */ {'0',')',0,0}, +/* 12 */ {'-','_',0,0}, +/* 13 */ {'=','+',0,0}, +/* 14 */ {0,0,0,0}, +/* 15 */ {KEYCODE_BACKSP,0,0,0}, +/* 16 */ {KEYCODE_TAB,0,0,0}, +/* 17 */ {'q','Q',0,0}, +/* 18 */ {'w','W',0,0}, +/* 19 */ {'e','E',0,0}, +/* 20 */ {'r','R',0,0}, +/* 21 */ {'t','T',0,0}, +/* 22 */ {'y','Y',0,0}, +/* 23 */ {'u','U',0,0}, +/* 24 */ {'i','I',0,0}, +/* 25 */ {'o','O',0,0}, +/* 26 */ {'p','P',0,0}, +/* 27 */ {'[','{',0,0}, +/* 28 */ {']','}',0,0}, +/* 29 */ {'#','~',0,0}, +/* 30 */ {KEYCODE_CAPSLK,0,0,0}, +/* 31 */ {'a','A',0,0}, +/* 32 */ {'s','S',0,0}, +/* 33 */ {'d','D',0,0}, +/* 34 */ {'f','F',0,0}, +/* 35 */ {'g','G',0,0}, +/* 36 */ {'h','H',0,0}, +/* 37 */ {'j','J',0,0}, +/* 38 */ {'k','K',0,0}, +/* 39 */ {'l','L',0,0}, +/* 40 */ {';',':',0,0}, +/* 41 */ {'\'','@',0,0}, +/* 42 */ {0,0,0,0}, +/* 43 */ {KEYCODE_RETURN,0,KEYCODE_ENTER,0}, +/* 44 */ {KEYCODE_LSHIFT,0,0,0}, +/* 45 */ {'\\','|',0,0}, +/* 46 */ {'z','Z',0,0}, +/* 47 */ {'x','X',0,0}, +/* 48 */ {'c','C',0,0}, +/* 49 */ {'v','V',0,0}, +/* 50 */ {'b','B',0,0}, +/* 51 */ {'n','N',0,0}, +/* 52 */ {'m','M',0,0}, +/* 53 */ {',','<',0,0}, +/* 54 */ {'.','>',0,0}, +/* 55 */ {'/','?','/' | MODIFIER_NUMLK,0}, +/* 56 */ {0,0,0,0}, +/* 57 */ {KEYCODE_RSHIFT,0,0,0}, +/* 58 */ {KEYCODE_LCTRL,0,KEYCODE_RCTRL,0}, +/* 59 */ {0,0,0,0}, +/* 60 */ {KEYCODE_ALT,0,KEYCODE_ALTGR,0}, +/* 61 */ {' ',0,0,0}, +/* 62 */ {KEYCODE_ALTGR,0,0,0}, +/* 63 */ {0,0,0,0}, +/* 64 */ {KEYCODE_RCTRL,0,0,0}, +/* 65 */ {0,0,0,0}, +/* 66 */ {0,0,0,0}, +/* 67 */ {0,0,0,0}, +/* 68 */ {0,0,0,0}, +/* 69 */ {0,0,0,0}, +/* 70 */ {0,0,0,0}, +/* 71 */ {0,0,0,0}, +/* 72 */ {0,0,0,0}, +/* 73 */ {0,0,0,0}, +/* 74 */ {0,0,0,0}, +/* 75 */ {KEYCODE_INSERT,0,0,0}, +/* 76 */ {KEYCODE_DELETE,0,0,0}, +/* 77 */ {0,0,0,0}, +/* 78 */ {0,0,0,0}, +/* 79 */ {KEYCODE_LEFT,0,0,0}, +/* 80 */ {KEYCODE_HOME,0,0,0}, +/* 81 */ {KEYCODE_END,0,0,0}, +/* 82 */ {0,0,0,0}, +/* 83 */ {KEYCODE_UP,0,0,0}, +/* 84 */ {KEYCODE_DOWN,0,0,0}, +/* 85 */ {KEYCODE_PAGEUP,0,0,0}, +/* 86 */ {KEYCODE_PAGEDN,0,0,0}, +/* 87 */ {0,0,0,0}, +/* 88 */ {0,0,0,0}, +/* 89 */ {KEYCODE_RIGHT,0,0,0}, +/* 90 */ {KEYCODE_NUMLK,0,KEYCODE_BREAK,0}, +/* 91 */ {KEYCODE_HOME | MODIFIER_NUMLK,0,KEYCODE_HOME,0}, +/* 92 */ {KEYCODE_LEFT | MODIFIER_NUMLK,0,KEYCODE_LEFT,0}, +/* 93 */ {KEYCODE_END | MODIFIER_NUMLK,0,KEYCODE_END,0}, +/* 94 */ {0,0,0,0}, +/* 95 */ {'/' | MODIFIER_NUMLK,0,0}, +/* 96 */ {KEYCODE_UP | MODIFIER_NUMLK,0,KEYCODE_UP,0}, +/* 97 */ {KEYCODE_CENTER | MODIFIER_NUMLK,0,KEYCODE_CENTER,0}, +/* 98 */ {KEYCODE_DOWN | MODIFIER_NUMLK,0,KEYCODE_DOWN,0}, +/* 99 */ {KEYCODE_INSERT | MODIFIER_NUMLK,0,KEYCODE_INSERT,0}, +/* 100 */ {'*' | MODIFIER_NUMLK,0,KEYCODE_PRTSCR,0}, +/* 101 */ {KEYCODE_PAGEUP | MODIFIER_NUMLK,0,KEYCODE_PAGEUP,0}, +/* 102 */ {KEYCODE_RIGHT | MODIFIER_NUMLK,0,KEYCODE_RIGHT,0}, +/* 103 */ {KEYCODE_PAGEDN | MODIFIER_NUMLK,0,KEYCODE_PAGEDN,0}, +/* 104 */ {KEYCODE_DELETE | MODIFIER_NUMLK,0,KEYCODE_DELETE,0}, +/* 105 */ {'-' | MODIFIER_NUMLK,0,0,0}, +/* 106 */ {'+' | MODIFIER_NUMLK,0,0,0}, +/* 107 */ {KEYCODE_ENTER,0,0,0}, +/* 108 */ {0,0,0,0}, +/* 109 */ {0,0,0,0}, +/* 110 */ {KEYCODE_ESCAPE,0,0,0}, +/* 111 */ {0,0,0,0}, +/* 112 */ {KEYCODE_F1,0,0,7}, +/* 113 */ {KEYCODE_F2,0,0,0}, +/* 114 */ {KEYCODE_F3,0,0,0}, +/* 115 */ {KEYCODE_F4,0,0,0}, +/* 116 */ {KEYCODE_F5,0,0,0}, +/* 117 */ {KEYCODE_F6,0,0,0}, +/* 118 */ {KEYCODE_F7,0,0,0}, +/* 119 */ {KEYCODE_F8,0,0,0}, +/* 120 */ {KEYCODE_F9,0,0,0}, +/* 121 */ {KEYCODE_F10,0,0,0}, +/* 122 */ {KEYCODE_F11,0,0,0}, +/* 123 */ {KEYCODE_F12,0,0,0}, +/* 124 */ {KEYCODE_PRTSCR,0,0,0}, +/* 125 */ {KEYCODE_SCRLK,0,KEYCODE_BREAK,0}, +/* 126 */ {KEYCODE_BREAK,0,0,0}, +/* 127 */ {0,0,0,0}, +/* 128 */ {KEYCODE_WINL,0,KEYCODE_WINL,0}, +/* 129 */ {KEYCODE_WINR,0,KEYCODE_WINR,0}, +/* 130 */ {KEYCODE_MENU,0,KEYCODE_MENU,0}, +/* currently no keys with numbers > 130 */ +/* 131 */ {0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}, +/* 140 */ {0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}, +/* 150 */ {0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}, +/* 160 */ {0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}, +/* 170 */ {0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}, +/* 180 */ {0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}, +/* 190 */ {0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}, +/* 200 */ {0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}, +/* 210 */ {0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}, +/* 220 */ {0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}, +/* 230 */ {0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}, +/* 240 */ {0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}, +/* 250 */ {0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0} +}; + +/* + * Scan code to key number conversion table for + * an extended AT keyboard in mode 2 + * + * This will give us the key index for keyboard + */ +int scancode_mode2_extended[256] = { + 0, 120, 0, 116, 114, 112, 113, + 123, 0, 121, 119, 117, 115, 16, + 1, 0, 0, 60, 44, 0, 58, + 17, 2, 0, 0, 0, 46, 32, + 31, 18, 3, 128, 0, 48, 47, + 33, 19, 5, 4, 129, 0, 61, + 49, 34, 21, 20, 6, 130, 0, + 51, 50, 36, 35, 22, 7, 0, + 0, 0, 52, 37, 23, 8, 9, + 0, 0, 53, 38, 24, 25, 11, + 10, 0, 0, 54, 55, 39, 40, + 26, 12, 0, 0, 0, 41, 0, + 27, 13, 0, 0, 30, 57, 43, + 28, 0, 29, 0, 0, 0, 45, + 0, 0, 0, 0, 15, 0, 0, + 93, 0, 92, 91, 0, 0, 0, + 99, 104, 98, 97, 102, 96, 110, + 90, 122, 106, 103, 105, 100, 101, + 125, 0, 0, 0, 0, 118, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, + /* no keys with codes > 0x8F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +#endif /* __KEYMAP_H__ */ diff --git a/conts/libdev/kmi/pl050/kmi.c b/conts/libdev/kmi/pl050/kmi.c new file mode 100755 index 0000000..7659d39 --- /dev/null +++ b/conts/libdev/kmi/pl050/kmi.c @@ -0,0 +1,387 @@ + +/* + * PL050 Primecell Keyboard, Mouse driver + * + * Copyright (C) 2010 Amit Mahajan + */ + +#include +#include "kmi.h" +#include "keymap.h" + +/* + * Reading Rx data automatically clears the RXITR + */ +void kmi_irq_handler(unsigned long base) +{ +} + +int kmi_data_read(unsigned long base) +{ + /* Check and return if data present */ + if (*(volatile unsigned long *)(base + PL050_KMISTAT) & KMI_RXFULL) + return *(volatile unsigned long *)(base + PL050_KMIDATA); + else + return 0; +} + +#if 0 +char kmi_keyboard_read(int c, struct keyboard_state *state) +{ + int keycode, shkeycode; + int keynum; + int extflag; + int modmask; + + /* Special codes */ + switch (c) { + case 0xF0: + /* release */ + state->modifiers |= MODIFIER_RELEASE; + return 0; + case 0xE0: + /* extended */ + state->modifiers |= MODIFIER_EXTENDED; + return 0; + case 0xE1: + /* extended for 2 characters - only used for Break in mode 2 */ + state->modifiers |= MODIFIER_EXTENDED; + state->modifiers |= MODIFIER_EXTENDED2; + return 0; + } + + extflag = 1; + modmask = 0xFFFFFFFF; + + /* Is this a scan code? */ + if (c > 0 && c <= 0x9F) + { + keynum = scancode_mode2_extended[c]; + + /* ignore unrecognised codes */ + if (!keynum) + { + state->modifiers &= ~MODIFIER_RELEASE; + return 0; + } + + /* is this an extended code? */ + if (state->modifiers & MODIFIER_EXTENDED) + { + keycode = keymap_uk2[keynum].ext_nomods; + extflag = 0; + state->modifiers &= ~MODIFIER_EXTENDED; + if (!keycode) + { + state->modifiers &= ~MODIFIER_RELEASE; + return 0; + } + } + else if (state->modifiers & MODIFIER_EXTENDED2) + { + keycode = keymap_uk2[keynum].ext_nomods; + extflag = 0; + state->modifiers &= ~MODIFIER_EXTENDED2; + if (!keycode) + { + state->modifiers &= ~MODIFIER_RELEASE; + return 0; + } + } + else + { + keycode = keymap_uk2[keynum].nomods; + if (!keycode) + { + state->modifiers &= ~MODIFIER_RELEASE; + return 0; + } + } + + /* handle shift */ + if (state->modifiers & MODIFIER_CAPSLK) + { + if (keycode >= 'a' && keycode <= 'z') + { + if (!(state->modifiers & MODIFIER_SHIFT)) + { + shkeycode = !extflag ? keymap_uk2[keynum].ext_shift : keymap_uk2[keynum].shift; + if (shkeycode) + keycode = shkeycode; + } + } + else + { + if (state->modifiers & MODIFIER_SHIFT) + { + shkeycode = !extflag ? keymap_uk2[keynum].ext_shift : keymap_uk2[keynum].shift; + if (shkeycode) + keycode = shkeycode; + } + } + } + else + { + if (state->modifiers & MODIFIER_SHIFT) + { + shkeycode = extflag ? keymap_uk2[keynum].ext_shift : keymap_uk2[keynum].shift; + if (shkeycode) + keycode = shkeycode; + } + } + + /* handle the numeric keypad */ + if (keycode & MODIFIER_NUMLK) + { + keycode &= ~MODIFIER_NUMLK; + + if (state->modifiers & MODIFIER_NUMLK) + { + if (!(state->modifiers & MODIFIER_SHIFT)) + { + switch (keycode) + { + case KEYCODE_HOME: + keycode = '7'; + break; + case KEYCODE_UP: + keycode = '8'; + break; + case KEYCODE_PAGEUP: + keycode = '9'; + break; + case KEYCODE_LEFT: + keycode = '4'; + break; + case KEYCODE_CENTER: + keycode = '5'; + break; + case KEYCODE_RIGHT: + keycode = '6'; + break; + case KEYCODE_END: + keycode = '1'; + break; + case KEYCODE_DOWN: + keycode = '2'; + break; + case KEYCODE_PAGEDN: + keycode = '3'; + break; + case KEYCODE_INSERT: + keycode = '0'; + break; + case KEYCODE_DELETE: + keycode = '.'; + break; + } + } + else + modmask = ~MODIFIER_SHIFT; + } + } + + /* modifier keys */ + switch (keycode) + { + case KEYCODE_LSHIFT: + if (state->modifiers & MODIFIER_RELEASE) + state->modifiers &= ~(MODIFIER_LSHIFT | MODIFIER_RELEASE); + else + state->modifiers |= MODIFIER_LSHIFT; + return 0; + + case KEYCODE_RSHIFT: + if (state->modifiers & MODIFIER_RELEASE) + state->modifiers &= ~(MODIFIER_RSHIFT | MODIFIER_RELEASE); + else + state->modifiers |= MODIFIER_RSHIFT; + return 0; + + case KEYCODE_LCTRL: + if (state->modifiers & MODIFIER_RELEASE) + state->modifiers &= ~(MODIFIER_LCTRL | MODIFIER_RELEASE); + else + state->modifiers |= MODIFIER_LCTRL; + return 0; + + case KEYCODE_RCTRL: + if (state->modifiers & MODIFIER_RELEASE) + state->modifiers &= ~(MODIFIER_RCTRL | MODIFIER_RELEASE); + else + state->modifiers |= MODIFIER_RCTRL; + return 0; + + case KEYCODE_ALT: + if (state->modifiers & MODIFIER_RELEASE) + state->modifiers &= ~(MODIFIER_ALT | MODIFIER_RELEASE); + else + state->modifiers |= MODIFIER_ALT; + return 0; + + case KEYCODE_ALTGR: + if (state->modifiers & MODIFIER_RELEASE) + state->modifiers &= ~(MODIFIER_ALTGR | MODIFIER_RELEASE); + else + state->modifiers |= MODIFIER_ALTGR; + return 0; + + case KEYCODE_CAPSLK: + if (state->modifiers & MODIFIER_RELEASE) + state->modifiers &= ~MODIFIER_RELEASE; + else + { + state->modifiers ^= MODIFIER_CAPSLK; + //__keyb_update_locks (state); + } + return 0; + + case KEYCODE_SCRLK: + if (state->modifiers & MODIFIER_RELEASE) + state->modifiers &= ~MODIFIER_RELEASE; + else + { + state->modifiers ^= MODIFIER_SCRLK; + //__keyb_update_locks (state); + } + return 0; + + case KEYCODE_NUMLK: + if (state->modifiers & MODIFIER_RELEASE) + state->modifiers &= ~MODIFIER_RELEASE; + else + { + state->modifiers ^= MODIFIER_NUMLK; + //__keyb_update_locks (state); + } + return 0; + } + + if (state->modifiers & MODIFIER_RELEASE) + { + /* clear release condition */ + state->modifiers &= ~MODIFIER_RELEASE; + } + else + { + /* write code into the buffer */ + return keycode; + } + return 0; + } + + return 0; +} +#endif + +/* + * Simple logic to interpret keyboard keys and shift keys + * TODO: Add support for all the modifier keys + * + * Keyevents work in 3 phase manner, if you press 'A': + * 1. scan code for 'A' is generated + * 2. Key release event i.e KYBD_DATA_KEYUP + * 3. scan code for 'A' again is generated + */ +char kmi_keyboard_read(unsigned long base, struct keyboard_state *state) +{ + int keynum, keycode = 0; + + /* Read Keyboard RX buffer */ + unsigned char data = kmi_data_read(base); + + /* if a key up occurred (key released) occured */ + if (data == KYBD_DATA_KEYUP) { + state->keyup = 1; + return 0; + } + else if (state->keyup){ + state->keyup = 0; + + /* Check if shift was lifted */ + if ((data == KYBD_DATA_SHIFTL) || (data == KYBD_DATA_SHIFTR)) { + state->shift = 0; + } + else { + /* Find key number */ + keynum = scancode_mode2_extended[data]; + if(state->shift) + keycode = keymap_uk2[keynum].shift; + else + keycode = keymap_uk2[keynum].nomods; + + } + + } + else if ((data == KYBD_DATA_SHIFTL) || (data == KYBD_DATA_SHIFTR)) { + state->shift = 1; + } + + return (unsigned char)keycode; +} + +void kmi_keyboard_init(unsigned long base, unsigned int div) +{ + /* STOP KMI */ + *(volatile unsigned long *)(base + PL050_KMICR) = 0x0; + + /* + * For versatile, KMI refernce clock = 24MHz + * KMI manual says we need 8MHz clock, + * so divide by 3 + */ + *(volatile unsigned long *)(base + PL050_KMICLKDIV) = div; + + /* Enable KMI and TX/RX interrupts */ + *(volatile unsigned long *)(base + PL050_KMICR) = + KMI_RXINTR | KMI_EN; + + /* Reset and wait for reset to complete */ + *(volatile unsigned long *)(base + PL050_KMIDATA) = + KYBD_DATA_RESET; + while(kmi_data_read(base) != KYBD_DATA_RTR); +} + +void kmi_mouse_enable(unsigned long base) +{ + unsigned long *datareg = (unsigned long *)(base + PL050_KMIDATA); + + *datareg = MOUSE_DATA_ENABLE; + + /*sleep for sometime here */ + + while (*datareg != MOUSE_DATA_ACK); +} + +void kmi_mouse_init(unsigned long base, unsigned int div) +{ + int data[2]; + + /* STOP KMI */ + *(volatile unsigned long *)(base + PL050_KMICR) = 0x0; + + /* + * For versatile, KMI refernce clock = 24MHz + * KMI manual says we need 8MHz clock, + * so divide by 3 + */ + *(volatile unsigned long *)(base + PL050_KMICLKDIV) = div; + + /* Enable KMI and TX/RX interrupts */ + *(volatile unsigned long *)(base + PL050_KMICR) = + KMI_RXINTR | KMI_EN; + + /* Reset and wait for reset to complete */ + *(volatile unsigned long *)(base + PL050_KMIDATA) = + MOUSE_DATA_RESET; + + do { + data[0] = kmi_data_read(base); + /* Some sleep here */ + data[1] = kmi_data_read(base); + }while((data[0] != MOUSE_DATA_ACK) && (data[1] != MOUSE_DATA_RTR)); + + /* Set enable data code to mouse */ + kmi_mouse_enable(base); +} + diff --git a/conts/libdev/kmi/pl050/kmi.h b/conts/libdev/kmi/pl050/kmi.h new file mode 100755 index 0000000..6b07b2c --- /dev/null +++ b/conts/libdev/kmi/pl050/kmi.h @@ -0,0 +1,59 @@ + +#ifndef __PL050_KMI_H__ +#define __PL050_KMI_H__ + +/* Register offsets */ +#define PL050_KMICR 0x00 +#define PL050_KMISTAT 0x04 +#define PL050_KMIDATA 0x08 +#define PL050_KMICLKDIV 0x0C +#define PL050_KMIIR 0x10 + +/* Bit definitions for KMI control register */ +#define KMI_TYPE (1 << 0x5) +#define KMI_RXINTR (1 << 0x4) +#define KMI_TXINTR (1 << 0x3) +#define KMI_EN (1 << 0x2) +#define KMI_FD (1 << 0x1) +#define KMI_FC (1 << 0x0) + +/* KMI generic defines */ +#define KMI_DATA_RESET 0xFF +#define KMI_DATA_RTR 0xAA + +/* Keyboard special defines */ +#define KYBD_DATA_RESET KMI_DATA_RESET // Keyboard reset +#define KYBD_DATA_RTR KMI_DATA_RTR // Keyboard response to reset + +#define KYBD_DATA_KEYUP 0xF0 // Key up control code +#define KYBD_DATA_SHIFTL 18 // Shift key left +#define KYBD_DATA_SHIFTR 89 // Shift key right + +/* Bit definitions for KMI STAT register */ +#define KMI_TXEMPTY (1 << 0x6) +#define KMI_TXBUSY (1 << 0x5) +#define KMI_RXFULL (1 << 0x4) +#define KMI_RXBUSY (1 << 0x3) +#define KMI_RXPARITY (1 << 0x2) +#define KMI_CLKIN (1 << 0x1) +#define KMI_DATAIN (1 << 0x0) + +/* Mouse special defines */ +#define MOUSE_DATA_RESET KMI_DATA_RESET // Mouse reset +#define MOUSE_DATA_RTR KMI_DATA_RTR // Mouse response to reset +#define MOUSE_DATA_ACK 0xFA +#define MOUSE_DATA_ENABLE 0xF4 // Mouse enable + +/* Common functions */ +void kmi_irq_handler(unsigned long base); +int kmi_data_read(unsigned long base); + +/* Keyboard specific calls */ +char kmi_keyboard_read(unsigned long base, struct keyboard_state *state); +void kmi_keyboard_init(unsigned long base, unsigned int div); + +/* Mouse specific calls */ +void kmi_mouse_enable(unsigned long base); +void kmi_mouse_init(unsigned long base, unsigned int div); + +#endif /* __PL050_KMI_H__ */ diff --git a/include/l4/generic/cap-types.h b/include/l4/generic/cap-types.h index fb50cf2..033f791 100644 --- a/include/l4/generic/cap-types.h +++ b/include/l4/generic/cap-types.h @@ -46,6 +46,8 @@ */ #define CAP_DEVTYPE_TIMER 1 #define CAP_DEVTYPE_UART 2 +#define CAP_DEVTYPE_KEYBOARD 3 +#define CAP_DEVTYPE_MOUSE 4 #define CAP_DEVTYPE_OTHER 0xF #define CAP_DEVTYPE_MASK 0xFFFF #define CAP_DEVNUM_MASK 0xFFFF0000 diff --git a/include/l4/generic/irq.h b/include/l4/generic/irq.h index b6523ff..26ff8da 100644 --- a/include/l4/generic/irq.h +++ b/include/l4/generic/irq.h @@ -47,6 +47,9 @@ struct irq_desc { /* Notification slot for this irq */ int task_notify_slot; + /* If user will ack this irq */ + int user_ack; + /* Waitqueue head for this irq */ struct waitqueue_head wqh_irq; diff --git a/include/l4/platform/pb926/irq.h b/include/l4/platform/pb926/irq.h index 2ac4a01..061542c 100644 --- a/include/l4/platform/pb926/irq.h +++ b/include/l4/platform/pb926/irq.h @@ -13,7 +13,7 @@ * an irq on any irq chip. */ #define VIC_CHIP_OFFSET 0 -#define SIC_CHIP_OFFSET 32 +#define SIC_CHIP_OFFSET 31 /* Maximum irqs on VIC and SIC */ #define VIC_IRQS_MAX 32 @@ -33,6 +33,8 @@ /* Secondary Interrupt controller local IRQ numbers */ #define SIC_IRQ_SWI 0 +#define SIC_IRQ_KEYBOARD 3 +#define SIC_IRQ_MOUSE 4 #define SIC_IRQ_UART3 6 /* Global irq numbers, note these should reflect global device names */ @@ -47,6 +49,7 @@ #define IRQ_SICSWI (SIC_IRQ_SWI + SIC_CHIP_OFFSET) #define IRQ_UART3 (SIC_IRQ_UART3 + SIC_CHIP_OFFSET) - +#define IRQ_KEYBOARD0 (SIC_IRQ_KEYBOARD + SIC_CHIP_OFFSET) +#define IRQ_MOUSE0 (SIC_IRQ_MOUSE + SIC_CHIP_OFFSET) #endif /* __PLATFORM_IRQ_H__ */ diff --git a/include/l4/platform/pb926/offsets.h b/include/l4/platform/pb926/offsets.h index 393f131..ad5db0e 100644 --- a/include/l4/platform/pb926/offsets.h +++ b/include/l4/platform/pb926/offsets.h @@ -17,6 +17,8 @@ * as we use these names for device capability */ #define PLATFORM_SYSTEM_REGISTERS 0x10000000 /* System registers */ +#define PLATFORM_KEYBOARD0_BASE 0x10006000 /* Keyboard */ +#define PLATFORM_MOUSE0_BASE 0x10007000 /* Mouse */ #define PLATFORM_SYSCTRL_BASE 0x101E0000 /* System controller */ #define PLATFORM_WATCHDOG_BASE 0x101E1000 /* Watchdog */ #define PLATFORM_TIMER0_BASE 0x101E2000 /* Timers 0 and 1 */ @@ -44,7 +46,9 @@ #define PLATFORM_SYSCTRL_VBASE (IO_AREA0_VADDR + (4 * DEVICE_PAGE)) /* Add userspace devices here as they become necessary for irqs */ -#define PLATFORM_TIMER1_VBASE (IO_AREA0_VADDR + (6 * DEVICE_PAGE)) +#define PLATFORM_TIMER1_VBASE (IO_AREA0_VADDR + (6 * DEVICE_PAGE)) +#define PLATFORM_KEYBOARD0_VBASE (IO_AREA0_VADDR + (7 * DEVICE_PAGE)) +#define PLATFORM_MOUSE0_VBASE (IO_AREA0_VADDR + (8 * DEVICE_PAGE)) /* The SP810 system controller offsets */ #define SP810_BASE PLATFORM_SYSCTRL_VBASE @@ -55,6 +59,8 @@ #define PLATFORM_UART2_SIZE 0x1000 #define PLATFORM_UART3_SIZE 0x1000 #define PLATFORM_TIMER1_SIZE 0x1000 +#define PLATFORM_KEYBOARD0_SIZE 0x1000 +#define PLATFORM_MOUSE0_SIZE 0x1000 #endif /* __PLATFORM_PB926_OFFSETS_H__ */ diff --git a/scripts/cml/generate_container_cml.py b/scripts/cml/generate_container_cml.py index 075de18..6aaa892 100755 --- a/scripts/cml/generate_container_cml.py +++ b/scripts/cml/generate_container_cml.py @@ -50,7 +50,7 @@ device_suppress_sym = \ '''\tcont${CONTID}_cap_device_${DEVNAME_LOWER} ''' -devices = ['UART1', 'UART2', 'UART3', 'TIMER1'] +devices = ['UART1', 'UART2', 'UART3', 'TIMER1', 'KEYBOARD0', 'MOUSE0'] # # When a symbol is used by a single container, sometimes it is diff --git a/src/api/irq.c b/src/api/irq.c index cfa1ab2..1811e3a 100644 --- a/src/api/irq.c +++ b/src/api/irq.c @@ -111,6 +111,16 @@ int irq_wait(l4id_t irq_index) if ((ret = tcb_check_and_lazy_map_utcb(current, 1)) < 0) return ret; + /* + * In case user has asked for unmasking the irq only after + * user hanlder is done, unmask the irq + * + * FIXME: This is not the correct place for this call, + * fix this. + */ + if (desc->user_ack) + irq_enable(irq_index); + /* Wait until the irq changes slot value */ WAIT_EVENT(&desc->wqh_irq, utcb->notify[desc->task_notify_slot] != 0, diff --git a/src/generic/irq.c b/src/generic/irq.c index 4eac287..75027fc 100644 --- a/src/generic/irq.c +++ b/src/generic/irq.c @@ -152,7 +152,11 @@ void do_irq(void) BUG(); } - irq_enable(irq_index); + /* + * Do not enable irq if user wants to do it explicitely + */ + if (!this_irq->user_ack) + irq_enable(irq_index); } diff --git a/src/platform/pb926/irq.c b/src/platform/pb926/irq.c index b5c451a..d5d1398 100644 --- a/src/platform/pb926/irq.c +++ b/src/platform/pb926/irq.c @@ -65,6 +65,23 @@ static int platform_timer_user_handler(struct irq_desc *desc) return 0; } +/* + * Keyboard handler for userspace + */ +static int platform_keyboard_user_handler(struct irq_desc *desc) +{ + irq_thread_notify(desc); + return 0; +} + +/* + * Mouse handler for userspace + */ +static int platform_mouse_user_handler(struct irq_desc *desc) +{ + irq_thread_notify(desc); + return 0; +} /* * Built-in irq handlers initialised at compile time. @@ -75,11 +92,25 @@ struct irq_desc irq_desc_array[IRQS_MAX] = { .name = "Timer0", .chip = &irq_chip_array[0], .handler = platform_timer_handler, + .user_ack = 0, }, [IRQ_TIMER1] = { .name = "Timer1", .chip = &irq_chip_array[0], .handler = platform_timer_user_handler, + .user_ack = 0, + }, + [IRQ_KEYBOARD0] = { + .name = "Keyboard", + .chip = &irq_chip_array[1], + .handler = platform_keyboard_user_handler, + .user_ack = 1, + }, + [IRQ_MOUSE0] = { + .name = "Mouse", + .chip = &irq_chip_array[1], + .handler = platform_mouse_user_handler, + .user_ack = 1, }, }; diff --git a/src/platform/pb926/platform.c b/src/platform/pb926/platform.c index ac81f9b..2535f3b 100644 --- a/src/platform/pb926/platform.c +++ b/src/platform/pb926/platform.c @@ -30,45 +30,66 @@ */ int platform_setup_device_caps(struct kernel_resources *kres) { - struct capability *uart[4], *timer[2]; + struct capability *uart[3], *timer[1], + *keyboard[1], *mouse[1]; /* Setup capabilities for userspace uarts and timers */ + uart[0] = alloc_bootmem(sizeof(*uart[0]), 0); + uart[0]->start = __pfn(PLATFORM_UART1_BASE); + uart[0]->end = uart[0]->start + 1; + uart[0]->size = uart[0]->end - uart[1]->start; + cap_set_devtype(uart[0], CAP_DEVTYPE_UART); + cap_set_devnum(uart[0], 1); + link_init(&uart[0]->list); + cap_list_insert(uart[0], &kres->devmem_free); + uart[1] = alloc_bootmem(sizeof(*uart[1]), 0); - uart[1]->start = __pfn(PLATFORM_UART1_BASE); + uart[1]->start = __pfn(PLATFORM_UART2_BASE); uart[1]->end = uart[1]->start + 1; uart[1]->size = uart[1]->end - uart[1]->start; cap_set_devtype(uart[1], CAP_DEVTYPE_UART); - cap_set_devnum(uart[1], 1); + cap_set_devnum(uart[1], 2); link_init(&uart[1]->list); cap_list_insert(uart[1], &kres->devmem_free); uart[2] = alloc_bootmem(sizeof(*uart[2]), 0); - uart[2]->start = __pfn(PLATFORM_UART2_BASE); + uart[2]->start = __pfn(PLATFORM_UART3_BASE); uart[2]->end = uart[2]->start + 1; uart[2]->size = uart[2]->end - uart[2]->start; cap_set_devtype(uart[2], CAP_DEVTYPE_UART); - cap_set_devnum(uart[2], 2); + cap_set_devnum(uart[2], 3); link_init(&uart[2]->list); cap_list_insert(uart[2], &kres->devmem_free); - uart[3] = alloc_bootmem(sizeof(*uart[3]), 0); - uart[3]->start = __pfn(PLATFORM_UART3_BASE); - uart[3]->end = uart[3]->start + 1; - uart[3]->size = uart[3]->end - uart[3]->start; - cap_set_devtype(uart[3], CAP_DEVTYPE_UART); - cap_set_devnum(uart[3], 3); - link_init(&uart[3]->list); - cap_list_insert(uart[3], &kres->devmem_free); - /* Setup timer1 capability as free */ - timer[1] = alloc_bootmem(sizeof(*timer[1]), 0); - timer[1]->start = __pfn(PLATFORM_TIMER1_BASE); - timer[1]->end = timer[1]->start + 1; - timer[1]->size = timer[1]->end - timer[1]->start; - cap_set_devtype(timer[1], CAP_DEVTYPE_TIMER); - cap_set_devnum(timer[1], 1); - link_init(&timer[1]->list); - cap_list_insert(timer[1], &kres->devmem_free); + timer[0] = alloc_bootmem(sizeof(*timer[0]), 0); + timer[0]->start = __pfn(PLATFORM_TIMER1_BASE); + timer[0]->end = timer[0]->start + 1; + timer[0]->size = timer[0]->end - timer[0]->start; + cap_set_devtype(timer[0], CAP_DEVTYPE_TIMER); + cap_set_devnum(timer[0], 1); + link_init(&timer[0]->list); + cap_list_insert(timer[0], &kres->devmem_free); + + /* Setup keyboard capability as free */ + keyboard[0] = alloc_bootmem(sizeof(*keyboard[0]), 0); + keyboard[0]->start = __pfn(PLATFORM_KEYBOARD0_BASE); + keyboard[0]->end = keyboard[0]->start + 1; + keyboard[0]->size = keyboard[0]->end - keyboard[0]->start; + cap_set_devtype(keyboard[0], CAP_DEVTYPE_KEYBOARD); + cap_set_devnum(keyboard[0], 0); + link_init(&keyboard[0]->list); + cap_list_insert(keyboard[0], &kres->devmem_free); + + /* Setup mouse capability as free */ + mouse[0] = alloc_bootmem(sizeof(*mouse[0]), 0); + mouse[0]->start = __pfn(PLATFORM_MOUSE0_BASE); + mouse[0]->end = mouse[0]->start + 1; + mouse[0]->size = mouse[0]->end - mouse[0]->start; + cap_set_devtype(mouse[0], CAP_DEVTYPE_MOUSE); + cap_set_devnum(mouse[0], 0); + link_init(&mouse[0]->list); + cap_list_insert(mouse[0], &kres->devmem_free); return 0; } @@ -116,11 +137,21 @@ void init_platform_irq_controller() irq_controllers_init(); } +/* Add userspace devices here as you develop their irq handlers */ void init_platform_devices() { - /* Add userspace devices here as you develop their irq handlers */ + /* TIMER23 */ add_boot_mapping(PLATFORM_TIMER1_BASE, PLATFORM_TIMER1_VBASE, PAGE_SIZE, MAP_IO_DEFAULT); + + /* KEYBOARD - KMI0 */ + add_boot_mapping(PLATFORM_KEYBOARD0_BASE, PLATFORM_KEYBOARD0_VBASE, + PAGE_SIZE, MAP_IO_DEFAULT); + + /* MOUSE - KMI1 */ + add_boot_mapping(PLATFORM_MOUSE0_BASE, PLATFORM_MOUSE0_VBASE, + PAGE_SIZE, MAP_IO_DEFAULT); + } /* If these bits are off, 32Khz OSC source is used */