Merge branch 'rebase' of git://git.l4dev.org/~amit/codezero into amit

Conflicts:
	conts/baremetal/timer_service/main.c
This commit is contained in:
Bahadir Balban
2009-12-04 00:41:51 +02:00
61 changed files with 911 additions and 57 deletions

View File

@@ -47,12 +47,12 @@ CONT%(cn)d_LINUX_ROOTFS_ADDRESS 'Container %(cn)d Linux ROOTFS Address'
default CONT%(cn)d_PAGER_LMA from CONT%(cn)d_PHYS0_START
default CONT%(cn)d_PAGER_VMA from CONT%(cn)d_VIRT0_START
default CONT%(cn)d_PAGER_SHM_START from 0x40000000
default CONT%(cn)d_PAGER_SHM_END from 0x50000000
default CONT%(cn)d_PAGER_TASK_START from 0x30000000
default CONT%(cn)d_PAGER_TASK_END from 0x40000000
default CONT%(cn)d_PAGER_UTCB_START from 0xf8100000
default CONT%(cn)d_PAGER_UTCB_END from 0xf8200000
default CONT%(cn)d_PAGER_SHM_START from CONT%(cn)d_VIRT1_START
default CONT%(cn)d_PAGER_SHM_END from CONT%(cn)d_VIRT1_END
default CONT%(cn)d_PAGER_TASK_START from CONT%(cn)d_VIRT2_START
default CONT%(cn)d_PAGER_TASK_END from CONT%(cn)d_VIRT2_END
default CONT%(cn)d_PAGER_UTCB_START from CONT%(cn)d_VIRT3_START
default CONT%(cn)d_PAGER_UTCB_END from CONT%(cn)d_VIRT3_END
default CONT%(cn)d_LINUX_ZRELADDR from (CONT%(cn)d_LINUX_PHYS_OFFSET + 0x8000)
default CONT%(cn)d_LINUX_PAGE_OFFSET from CONT%(cn)d_VIRT0_START
default CONT%(cn)d_LINUX_PHYS_OFFSET from CONT%(cn)d_PHYS0_START
@@ -128,7 +128,16 @@ default CONT%(cn)d_VIRT4_END from (CONT%(cn)d_VIRT4_START + 0x10000000)
default CONT%(cn)d_VIRT5_START from 0xe0000000
default CONT%(cn)d_VIRT5_END from 0xf0000000
default CONT%(cn)d_OPT_NAME from (CONT%(cn)d_TYPE_LINUX==y) ? "linux%(cn)d" : ((CONT%(cn)d_TYPE_BAREMETAL==y) ? "baremetal%(cn)d" : "posix%(cn)d")
derive baremetal%(cn)d from
(CONT%(cn)d_BAREMETAL_PROJ_EMPTY==y) ? "empty%(cn)d" :
((CONT%(cn)d_BAREMETAL_PROJ_HELLO_WORLD==y) ? "hello_world%(cn)d" :
((CONT%(cn)d_BAREMETAL_PROJ_THREADS_DEMO==y) ? "thread_demo%(cn)d" :
((CONT%(cn)d_BAREMETAL_PROJ_TEST==y) ? "test%(cn)d" :
((CONT%(cn)d_BAREMETAL_PROJ_UART_SERVICE==y) ? "uart_service%(cn)d" :
((CONT%(cn)d_BAREMETAL_PROJ_CLCD_SERVICE==y) ? "clcd_service%(cn)d" :
((CONT%(cn)d_BAREMETAL_PROJ_TIMER_SERVICE==y) ? "timer_service%(cn)d" : "baremetal_noname%(cn)d" ))))))
default CONT%(cn)d_OPT_NAME from (CONT%(cn)d_TYPE_LINUX==y) ? "linux%(cn)d" : ((CONT%(cn)d_TYPE_BAREMETAL==y) ? baremetal%(cn)d : "posix%(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
@@ -152,22 +161,24 @@ cont%(cn)d_linux_pager_params 'Container %(cn)d Linux Pager Parameters'
cont%(cn)d_default_pager_params 'Container %(cn)d Default Pager Parameters'
cont%(cn)d_posix_pager_params 'Container %(cn)d POSIX Pager Parameters'
cont%(cn)d_baremetal_params 'Baremetal Project'
CONT%(cn)d_BAREMETAL_PROJ0 'Empty Project'
CONT%(cn)d_BAREMETAL_PROJ1 'Hello World'
CONT%(cn)d_BAREMETAL_PROJ2 'Thread Library Demo'
CONT%(cn)d_BAREMETAL_PROJ3 'Test Project'
CONT%(cn)d_BAREMETAL_PROJ4 'UART Service'
CONT%(cn)d_BAREMETAL_PROJ5 'Timer Service'
cont%(cn)d_baremetal_params 'Baremetal Project'
CONT%(cn)d_BAREMETAL_PROJ_EMPTY 'Empty Project'
CONT%(cn)d_BAREMETAL_PROJ_HELLO_WORLD 'Hello World'
CONT%(cn)d_BAREMETAL_PROJ_THREADS_DEMO 'Thread Library Demo'
CONT%(cn)d_BAREMETAL_PROJ_TEST 'Test Project'
CONT%(cn)d_BAREMETAL_PROJ_UART_SERVICE 'UART Service'
CONT%(cn)d_BAREMETAL_PROJ_TIMER_SERVICE 'Timer Service'
CONT%(cn)d_BAREMETAL_PROJ_CLCD_SERVICE 'CLCD Service'
choices cont%(cn)d_baremetal_params
CONT%(cn)d_BAREMETAL_PROJ0
CONT%(cn)d_BAREMETAL_PROJ1
CONT%(cn)d_BAREMETAL_PROJ2
CONT%(cn)d_BAREMETAL_PROJ3
CONT%(cn)d_BAREMETAL_PROJ4
CONT%(cn)d_BAREMETAL_PROJ5
default CONT%(cn)d_BAREMETAL_PROJ0
CONT%(cn)d_BAREMETAL_PROJ_EMPTY
CONT%(cn)d_BAREMETAL_PROJ_HELLO_WORLD
CONT%(cn)d_BAREMETAL_PROJ_THREADS_DEMO
CONT%(cn)d_BAREMETAL_PROJ_TEST
CONT%(cn)d_BAREMETAL_PROJ_UART_SERVICE
CONT%(cn)d_BAREMETAL_PROJ_TIMER_SERVICE
CONT%(cn)d_BAREMETAL_PROJ_CLCD_SERVICE
default CONT%(cn)d_BAREMETAL_PROJ_EMPTY
menu cont%(cn)d_default_pager_params
CONT%(cn)d_PAGER_LMA@
@@ -223,16 +234,19 @@ 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_clcd 'Container %(cn)d CLCD 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_CLCD0_USE 'Container %(cn)d CLCD 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_CLCD0_USE from n
menu cont%(cn)d_cap_device_uart1
CONT%(cn)d_CAP_DEVICE_UART1_USE
@@ -246,11 +260,15 @@ 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_clcd
CONT%(cn)d_CAP_DEVICE_CLCD0_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_clcd
#
# Settings for Custom Capabilities

View File

@@ -12,7 +12,6 @@ class Container:
self.name = None
self.type = None
self.id = id
self.baremetal_id = 0
self.pager_lma = 0
self.pager_vma = 0
self.pager_size = 0
@@ -131,10 +130,7 @@ class configuration:
# TODO: Carry this over to Container() as static method???
def get_container_parameter(self, id, param, val):
if param[:len("SOURCE_PATH")] == "SOURCE_PATH":
parts = val.split("\"", 3)
self.containers[id].src_path = parts[1]
elif param[:len("PAGER_LMA")] == "PAGER_LMA":
if param[:len("PAGER_LMA")] == "PAGER_LMA":
self.containers[id].pager_lma = int(val, 0)
elif param[:len("PAGER_VMA")] == "PAGER_VMA":
self.containers[id].pager_vma = int(val, 0)
@@ -173,12 +169,11 @@ class configuration:
if regionid + 1 > self.containers[id].phys_regions:
self.containers[id].phys_regions = regionid + 1
elif param[:len("OPT_NAME")] == "OPT_NAME":
dirname = val[1:-1].lower()
self.containers[id].dirname = dirname
self.containers[id].name = dirname
elif param[:len("BAREMETAL_PROJ")] == "BAREMETAL_PROJ":
param1 = param.split("_", 1)
self.containers[id].baremetal_id = param1[1][-1:]
name = val[1:-1].lower()
self.containers[id].name = name
elif param[:len("BAREMETAL_PROJ_")] == "BAREMETAL_PROJ_":
param1 = param.split("_", 2)
self.containers[id].dirname = param1[2].lower()
elif param[:len("CAP_")] == "CAP_":
prefix, param_rest = param.split('_', 1)
prepare_capability(self.containers[id], param_rest, val)

View File

@@ -0,0 +1,67 @@
# -*- 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 *
config = configuration_retrieve()
platform = config.platform
arch = config.arch
gcc_cpu_flag = config.gcc_cpu_flag
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)
# Locally important paths are here
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, 'uart/include'),
join(LIBDEV_DIR, 'clcd/pl110/include')]
LIBDEV_CCFLAGS = '-DPLATFORM_' + platform.upper()
# FIXME: Add these to autogenerated SConstruct !!!
LIBMEM_RELDIR = 'conts/libmem'
LIBMEM_DIR = join(PROJROOT, LIBMEM_RELDIR)
LIBMEM_LIBPATH = join(BUILDDIR, LIBMEM_RELDIR)
LIBMEM_INCLUDE = LIBMEM_DIR
env = Environment(CC = config.user_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', ('-mcpu=' + gcc_cpu_flag), LIBDEV_CCFLAGS],
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', 'libmalloc', 'c-userspace', 'libdev-userspace', '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]')
objs = env.Object(src)
prog = env.Program('main.elf', objs)
Depends(prog, 'include/linker.lds')

View File

@@ -0,0 +1,277 @@
/*
* CLCD service for userspace
*/
#include <l4lib/arch/syslib.h>
#include <l4lib/arch/syscalls.h>
#include <l4lib/addr.h>
#include <l4lib/exregs.h>
#include <l4lib/ipcdefs.h>
#include <l4/api/errno.h>
#include <l4/api/space.h>
#include <capability.h>
#include <container.h>
#include <pl110_clcd.h> /* FIXME: Its best if this is <libdev/uart/pl011.h> */
#include <linker.h>
#define CLCD_TOTAL 1
static struct capability caparray[32];
static int total_caps = 0;
struct capability clcd_cap[CLCD_TOTAL];
int cap_read_all()
{
int ncaps;
int err;
/* Read number of capabilities */
if ((err = l4_capability_control(CAP_CONTROL_NCAPS,
0, 0, 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, 0, 0, caparray)) < 0) {
printf("l4_capability_control() reading of "
"capabilities failed.\n Could not "
"complete CAP_CONTROL_READ_CAPS request.\n");
BUG();
}
return 0;
}
/*
* Scans for up to CLCD_TOTAL clcd devices in capabilities.
*/
int clcd_probe_devices(void)
{
int clcds = 0;
/* Scan for clcd devices */
for (int i = 0; i < total_caps; i++) {
/* Match device type */
if (cap_devtype(&caparray[i]) == CAP_DEVTYPE_CLCD) {
/* Copy to correct device index */
memcpy(&clcd_cap[cap_devnum(&caparray[i])],
&caparray[i], sizeof(clcd_cap[0]));
clcds++;
}
}
if (clcds != CLCD_TOTAL) {
printf("%s: Error, not all clcd could be found. "
"total clcds=%d\n", __CONTAINER_NAME__, clcds);
return -ENODEV;
}
return 0;
}
/*
* 1MB frame buffer,
* FIXME: can we do dma in this buffer?
*/
#define CLCD_FRAMEBUFFER_SZ 0x100000
static char framebuffer[CLCD_FRAMEBUFFER_SZ];
static struct pl110_clcd clcd[CLCD_TOTAL];
int clcd_setup_devices(void)
{
for (int i = 0; i < CLCD_TOTAL; i++) {
/* Get one page from address pool */
clcd[i].virt_base = (unsigned long)l4_new_virtual(1);
/* Map clcd to a virtual address region */
if (IS_ERR(l4_map((void *)__pfn_to_addr(clcd_cap[i].start),
(void *)clcd[i].virt_base, clcd_cap[i].size,
MAP_USR_IO_FLAGS,
self_tid()))) {
printf("%s: FATAL: Failed to map CLCD device "
"%d to a virtual address\n",
__CONTAINER_NAME__,
cap_devnum(&clcd_cap[i]));
BUG();
}
/* Initialize clcd */
pl110_initialise(&clcd[i], framebuffer);
}
return 0;
}
static struct address_pool device_vaddr_pool;
/*
* 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 clcd?
*/
if (__pfn(page_align_up(__end))
+ CLCD_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,
page_align_up(__end),
__pfn_to_addr(caparray[i].end),
CLCD_TOTAL);
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 cld 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
*/
/*
* FIXME: Right now we are talking to CLCD by default, we need to define protocol
* for sommunication with CLCD service
*/
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 in-place 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();
/* Scan for clcd devices in capabilities */
clcd_probe_devices();
/* Initialize virtual address pool for clcds */
init_vaddr_pool();
/* Map and initialize clcd devices */
clcd_setup_devices();
/* Setup own utcb */
if ((err = l4_utcb_setup(&utcb)) < 0) {
printf("FATAL: Could not set up own utcb. "
"err=%d\n", err);
BUG();
}
/* Listen for clcd requests */
while (1)
handle_requests();
}

View File

@@ -0,0 +1,36 @@
#ifndef __TIMER_H__
#define __TIMER_H__
/*
* Timer specific things are here
*/
#include <l4lib/mutex.h>
#include <l4/lib/list.h>
/*
* Structure representing the sleeping tasks,
* tgid: tgid of sleeping task
* wait_count: time left, in microseconds, after which task
* will be signalled to get out of sleep
*/
struct timer_task {
struct link list;
l4id_t tgid;
unsigned int wait_count;
};
/*
* Timer structure,
* base: base address of sp804 timer encapsulated
* count: Count in microseconds from the start of this timer
* tasklist: list of tasks sleeping for some value of count
* lock: lock protecting the corruption of tasklist
*/
struct sp804_timer {
unsigned int base;
unsigned int count;
struct link tasklist;
struct l4_mutex lock;
};
#endif /* __TIMER_H__ */

View File

@@ -9,11 +9,12 @@
#include <l4/api/errno.h>
#include <l4/api/space.h>
#include <malloc/malloc.h>
#include <capability.h>
#include <container.h>
#include "sp804_timer.h"
#include <linker.h>
#include <timer.h>
/* Frequency of timer in MHz */
#define TIMER_FREQUENCY 1
@@ -188,16 +189,36 @@ int timer_probe_devices(void)
static struct sp804_timer timer[TIMERS_TOTAL];
struct timer_task *get_timer_task(l4id_t tgid)
{
/* May be we can prepare a cache for timer_task structs */
struct timer_task *task = (struct timer_task *)kzalloc(sizeof(struct timer_task));
link_init(&task->list);
task->tgid = tgid;
task->wait_count = timer[0].count;
return task;
}
void free_timer_task(struct timer_task *task)
{
kfree(task);
}
int timer_setup_devices(void)
{
for (int i = 0; i < TIMERS_TOTAL; i++) {
/* Get one page from address pool */
timer[i].base = (unsigned long)l4_new_virtual(1);
timer[i].count = 0;
link_init(&timer[i].tasklist);
l4_mutex_init(&timer[i].lock);
/* Map timers to a virtual address region */
if (IS_ERR(l4_map((void *)__pfn_to_addr(timer_cap[i].start),
(void *)timer[i].base, timer_cap[i].size, MAP_USR_IO_FLAGS,
self_tid()))) {
(void *)timer[i].base, timer_cap[i].size, MAP_USR_IO_FLAGS,
self_tid()))) {
printf("%s: FATAL: Failed to map TIMER device "
"%d to a virtual address\n",
__CONTAINER_NAME__,
@@ -206,7 +227,7 @@ int timer_setup_devices(void)
}
/* Initialise timer */
sp804_init(timer[i].base, SP804_TIMER_RUNMODE_FREERUN, \
sp804_init(timer[i].base, SP804_TIMER_RUNMODE_PERIODIC, \
SP804_TIMER_WRAPMODE_WRAPPING, SP804_TIMER_WIDTH32BIT, \
SP804_TIMER_IRQDISABLE);
@@ -264,18 +285,48 @@ void *l4_new_virtual(int npages)
return address_new(&device_vaddr_pool, npages, PAGE_SIZE);
}
int timer_gettime(int devno)
void timer_irq_handler(void)
{
return sp804_read_value(timer[devno].base);
struct timer_task *struct_ptr, *temp_ptr;
timer[0].count += 1;
/*
* FIXME:
* Traverse through the sleeping process list and
* wake any process if required, we need to put this part in bottom half
*/
list_foreach_removable_struct(struct_ptr, temp_ptr, &timer[0].tasklist, list)
if (struct_ptr->wait_count == timer[0].count) {
/* Remove task from list */
l4_mutex_lock(&timer[0].lock);
list_remove(&struct_ptr->list);
l4_mutex_unlock(&timer[0].lock);
/* wake the sleeping process, send wake ipc */
free_timer_task(struct_ptr);
}
}
void timer_sleep(int sec)
int timer_gettime(void)
{
/*
* TODO: We need to have a timer struct already present to be used
* as reference for us. to implement this call
*/
return timer[0].count;
}
void timer_sleep(l4id_t tgid, int sec)
{
struct timer_task *task = get_timer_task(tgid);
/* Check for overflow */
task->wait_count += (sec * 1000000);
l4_mutex_lock(&timer[0].lock);
list_insert_tail(&task->list, &timer[0].tasklist);
l4_mutex_unlock(&timer[0].lock);
}
void handle_requests(void)
{
u32 mr[MR_UNUSED_TOTAL];
@@ -311,11 +362,12 @@ void handle_requests(void)
*/
switch (tag) {
case L4_IPC_TAG_TIMER_GETTIME:
timer_gettime(1);
mr[0] = timer_gettime();
break;
case L4_IPC_TAG_TIMER_SLEEP:
timer_sleep(mr[0]);
timer_sleep(senderid, mr[0]);
/* TODO: Halt the caller for mr[0] seconds */
break;
default:

View File

@@ -0,0 +1,21 @@
/*
* Container entry point for pager
*
* Copyright (C) 2007-2009 B Labs Ltd.
*/
#include <l4lib/init.h>
#include <l4lib/utcb.h>
extern void main(void);
void __container_init(void)
{
/* Generic L4 initialisation */
__l4_init();
/* Entry to main */
main();
}

View File

@@ -0,0 +1,12 @@
#ifndef __UART_SERVICE_CAPABILITY_H__
#define __UART_SERVICE_CAPABILITY_H__
#include <l4lib/capability.h>
#include <l4/api/capability.h>
#include <l4/generic/cap-types.h>
void cap_print(struct capability *cap);
void cap_list_print(struct cap_list *cap_list);
int cap_read_all();
#endif /* header */

View File

@@ -0,0 +1,13 @@
/*
* Autogenerated definitions for this container.
*/
#ifndef __CONTAINER_H__
#define __CONTAINER_H__
#define __CONTAINER_NAME__ "uart_service"
#define __CONTAINER_ID__ 0
#define __CONTAINER__ "cont0"
#endif /* __CONTAINER_H__ */

View File

@@ -0,0 +1,7 @@
#ifndef __LINKER_H__
#define __LINKER_H__
extern char vma_start[];
extern char __end[];
#endif /* __LINKER_H__ */

View File

@@ -24,13 +24,18 @@ LIBDEV_UART_PATH = join(PROJROOT, 'conts/libdev/uart')
# Path for timer files
LIBDEV_TIEMR_PATH = join(PROJROOT, 'conts/libdev/timer/sp804')
# Path for clcd files
LIBDEV_CLCD_PATH = join(PROJROOT, 'conts/libdev/clcd/pl110')
e = env.Clone()
e.Append(CPPPATH = [LIBDEV_UART_PATH + '/include', LIBDEV_TIEMR_PATH + '/include'],
e.Append(CPPPATH = [LIBDEV_UART_PATH + '/include', LIBDEV_TIEMR_PATH + '/include',
LIBDEV_CLCD_PATH + '/include',],
CCFLAGS = ['-nostdinc', '-DVARIANT_' + variant.upper(),
'-DPLATFORM_' + platform.upper()])
source = Glob('uart/src' + '/*.c') + \
Glob('timer/sp804/src' + '/*.c')
Glob('timer/sp804/src' + '/*.c') + \
Glob('clcd/pl110/src' + '/*.c')
objects = e.StaticObject(source)
library = e.StaticLibrary('libdev-' + variant, objects)

View File

@@ -0,0 +1,104 @@
#ifndef __PL110_CLCD_H__
#define __PL110_CLCD_H__
/* Register offsets */
#define PL110_CLCD_TIMING0 0x000 /* Horizontal Axis Panel Control*/
#define PL110_CLCD_TIMING1 0x004 /* Vertical Axis Panel Control */
#define PL110_CLCD_TIMING2 0x008 /* Clock and Polarity Signal Control*/
#define PL110_CLCD_TIMING3 0x00c /* Line End Control */
#define PL110_CLCD_UPBASE 0x010 /* Upper Panel Frame Base Address*/
#define PL110_CLCD_LPBASE 0x014 /* Lower Panel Frame Base Address */
#define PL110_CLCD_IMSC 0x018 /* Interrupt Mast Set Clear */
#define PL110_CLCD_CONTROL 0x01c /* CLCD Control */
#define PL110_CLCD_RIS 0x020 /* Raw Interrupt Status */
#define PL110_CLCD_MIS 0x024 /* Masked Interrupt Status */
#define PL110_CLCD_ICR 0x028 /* Interrupt Clear */
#define PL110_CLCD_UPCURR 0x02c /* Upper Panel Current Address Value */
#define PL110_CLCD_LPCURR 0x030 /* Lower Panel Current Address Value */
//#define PL110_LCD_PALETTE
#define PL110_CLCD_PERIPHID0 0xfe0 /* Peripheral Identification */
#define PL110_CLCD_PERIPHID1 0xfe4 /* Peripheral Identification */
#define PL110_CLCD_PERIPHID2 0xfe8 /* Peripheral Identification */
#define PL110_CLCD_PERIPHID3 0xfec /* Peripheral Identification */
#define PL110_CLCD_PCELLID0 0xff0 /* Peripheral Identification */
#define PL110_CLCD_PCELLID1 0xff4 /* PrimeCell Identification */
#define PL110_CLCD_PCELLID2 0xff8 /* PrimeCell Identification */
#define PL110_CLCD_PCELLID3 0xffc /* PrimeCell Identification */
/* Scan mode */
#define SCAN_VMODE_NONINTERLACED 0 /* non interlaced */
#define SCAN_VMODE_INTERLACED 1 /* interlaced */
#define SCAN_VMODE_DOUBLE 2 /* double scan */
#define SCAN_VMODE_ODD_FLD_FIRST 4 /* interlaced: top line first */
#define SCAN_VMODE_MASK 255
/* Control Register Bits */
#define PL110_CNTL_LCDEN (1 << 0)
#define PL110_CNTL_LCDBPP1 (0 << 1)
#define PL110_CNTL_LCDBPP2 (1 << 1)
#define PL110_CNTL_LCDBPP4 (2 << 1)
#define PL110_CNTL_LCDBPP8 (3 << 1)
#define PL110_CNTL_LCDBPP16 (4 << 1)
#define PL110_CNTL_LCDBPP16_565 (6 << 1)
#define PL110_CNTL_LCDBPP24 (5 << 1)
#define PL110_CNTL_LCDBW (1 << 4)
#define PL110_CNTL_LCDTFT (1 << 5)
#define PL110_CNTL_LCDMONO8 (1 << 6)
#define PL110_CNTL_LCDDUAL (1 << 7)
#define PL110_CNTL_BGR (1 << 8)
#define PL110_CNTL_BEBO (1 << 9)
#define PL110_CNTL_BEPO (1 << 10)
#define PL110_CNTL_LCDPWR (1 << 11)
#define PL110_CNTL_LCDVCOMP(x) ((x) << 12)
#define PL110_CNTL_LDMAFIFOTIME (1 << 15)
#define PL110_CNTL_WATERMARK (1 << 16)
#define PL110_TIM2_CLKSEL (1 << 5)
#define PL110_TIM2_IVS (1 << 11)
#define PL110_TIM2_IHS (1 << 12)
#define PL110_TIM2_IPC (1 << 13)
#define PL110_TIM2_IOE (1 << 14)
#define PL110_TIM2_BCD (1 << 26)
struct videomode {
const char *name; /* optional */
unsigned int refresh; /* optional */
unsigned int xres;
unsigned int yres;
unsigned int pixclock;
unsigned int left_margin;
unsigned int right_margin;
unsigned int upper_margin;
unsigned int lower_margin;
unsigned int hsync_len;
unsigned int vsync_len;
unsigned int sync;
unsigned int vmode;
unsigned int flag;
};
struct pl110_clcd_panel {
struct videomode mode;
signed short width; /* width in mm */
signed short height; /* height in mm */
unsigned int tim2;
unsigned int tim3;
unsigned int cntl;
unsigned int bpp:8,
fixedtimings:1,
grayscale:1;
unsigned int connector;
};
struct pl110_clcd {
unsigned int virt_base;
struct pl110_clcd_panel *panel;
char *frame_buffer;
};
void pl110_initialise(struct pl110_clcd *clcd, char *buf);
#endif /* __PL110_CLCD_H__ */

View File

@@ -0,0 +1,68 @@
#include <pl110_clcd.h>
#define read(a) *((volatile unsigned int *)(a))
#define write(v, a) (*((volatile unsigned int *)(a)) = v)
#define setbit(bit, a) write(read(a) | bit, a)
#define clrbit(bit, a) write(read(a) & ~bit, a)
/*
* Default panel, we will use this for now
* Seems like qemu has support for this
*/
static struct pl110_clcd_panel vga = {
.mode = {
.name = "VGA",
.refresh = 60,
.xres = 640,
.yres = 480,
.pixclock = 39721,
.left_margin = 40,
.right_margin = 24,
.upper_margin = 32,
.lower_margin = 11,
.hsync_len = 96,
.vsync_len = 2,
.sync = 0,
.vmode = SCAN_VMODE_NONINTERLACED,
},
.width = -1,
.height = -1,
.tim2 = PL110_TIM2_BCD | PL110_TIM2_IPC,
.cntl = PL110_CNTL_LCDTFT | PL110_CNTL_LCDVCOMP(1),
.bpp = 16,
};
static void pl110_clcd_set_uppanel_fb(unsigned int clcd_base,
unsigned int fb_base)
{
write(fb_base, (clcd_base + PL110_CLCD_UPBASE));
}
#if 0
static void pl110_clcd_set_lwrpanel_fb(unsigned int clcd_base, unsigned int fb_base)
{
write(fb_base, (clcd_base +PL110_CLCD_LPBASE));
}
static unsigned int pl110_clcd_get_uppanel_fb(unsigned int clcd_base)
{
return read((clcd_base +PL110_CLCD_UPBASE));
}
static unsigned int pl110_clcd_get_lwrpanel_fb(unsigned int clcd_base)
{
return read((clcd_base +PL110_CLCD_LPBASE));
}
#endif
void pl110_initialise(struct pl110_clcd *clcd, char *buf)
{
clcd->panel = &vga;
clcd->frame_buffer = buf;
pl110_clcd_set_uppanel_fb(clcd->virt_base, (unsigned int)(buf));
}

View File

@@ -56,10 +56,6 @@
#define SP804_TIMERMIS 0x14
#define SP804_TIMERBGLOAD 0x18
struct sp804_timer {
unsigned int base;
};
void sp804_init(unsigned int timer_base, int runmode, int wrapmode, \
int width, int irq_enable);
void sp804_irq_handler(unsigned int timer_base);

View File

@@ -10,6 +10,8 @@
#define setbit(bit, a) write(read(a) | bit, a)
#define clrbit(bit, a) write(read(a) & ~bit, a)
extern void timer_irq_handler(void);
void sp804_irq_handler(unsigned int timer_base)
{
/*
@@ -17,6 +19,7 @@ void sp804_irq_handler(unsigned int timer_base)
* as it automatically reloads and wraps
*/
write(1, (timer_base + SP804_TIMERINTCLR));
timer_irq_handler();
}
static inline void sp804_control(unsigned int timer_base, int bit, int setclr)

View File

@@ -24,6 +24,7 @@
#define PB926_UART1_BASE 0x101F2000 /* Console port (UART1) */
#define PB926_UART2_BASE 0x101F3000 /* Console port (UART2) */
#define PB926_UART3_BASE 0x10009000 /* Console port (UART3) */
#define PB926_CLCD_BASE 0x10120000 /* Color LCD */
/*
* Uart virtual address until a file-based console access

View File

@@ -29,17 +29,21 @@
#define PB926_UART_SIZE 0x1000
#define PB926_TIMER_SIZE 0x1000
#define PB926_CLCD_SIZE 0x1000
#define PLATFORM_UART1_BASE PB926_UART1_BASE
#define PLATFORM_UART2_BASE PB926_UART2_BASE
#define PLATFORM_UART3_BASE PB926_UART3_BASE
#define PLATFORM_UART1_SIZE PB926_UART_SIZE
#define PLATFORM_UART2_SIZE PB926_UART_SIZE
#define PLATFORM_UART3_SIZE PB926_UART_SIZE
#define PLATFORM_TIMER1_BASE PB926_TIMER23_BASE
#define PLATFORM_TIMER1_SIZE PB926_TIMER_SIZE
#define PLATFORM_CLCD0_BASE PB926_CLCD_BASE
#define PLATFORM_CLCD0_SIZE PB926_CLCD_SIZE
int platform_setup_device_caps(struct kernel_resources *kres);
void platform_irq_enable(int irq);
void platform_irq_disable(int irq);

View File

@@ -0,0 +1,166 @@
#! /usr/bin/env python2.6
# -*- mode: python; coding: utf-8; -*-
#
# Script to add/remove project to baremetal
# menu of main screen
#
# This script should be called from project root directory
#
import os, sys, shutil, re
PROJRELROOT = '../../'
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), PROJRELROOT)))
from optparse import OptionParser
from os.path import join
from shutil import copytree
from config.projpaths import *
def parse_cmdline_options():
usage = "usage: %prog [options] arg"
parser = OptionParser(usage)
parser.add_option("-a", "--add", action = "store_true", default = False,
dest = "addproject", help = "Add new project to baremetal projects")
parser.add_option("-d", "--del", action = "store_true", default = False,
dest = "delproject", help = "Delete existing project from baremetal projects")
parser.add_option("-i", "--desc", type = "string", dest = "projdesc",
help = "Description of new project to be added")
parser.add_option("-s", "--src", type = "string", dest = "srcpath",
help = "With -a, Source directory for new project to be added \
With -d, Source directory of baremetal project to be deleted")
(options, args) = parser.parse_args()
# Sanity checks
if (not options.addproject and not options.delproject) or \
(options.addproject and options.delproject):
parser.error("Only one of -a or -d needed, use -h argument for help")
exit()
if options.addproject:
add_del = 1
if not options.projdesc or not options.srcpath:
parser.error("--desc or --src missing, use -h argument for help")
exit()
if options.delproject:
add_del = 0
if options.projdesc or not options.srcpath:
parser.error("--desc provided or --src missing with -d, use -h argument for help")
exit()
return options.projdesc, options.srcpath, add_del
def container_cml_templ_del_symbl(projname):
cont_templ = "config/cml/container_ruleset.template"
sym = "CONT%(cn)d_BAREMETAL_PROJ_" + projname.upper()
buffer = ""
with open(cont_templ, 'r') as fin:
exist = False
# Prepare buffer for new cont_templ with new project symbols added
for line in fin:
parts = line.split()
# Find out where baremetal symbols start in cont_templ
if len(parts) > 1 and parts[0] == sym:
exist = True
continue
elif len(parts) == 1 and parts[0] == sym:
continue
buffer += line
if exist == False:
print "Baremetal project named " + projname + " does not exist"
exit()
# Write new cont_templ
with open(cont_templ, 'w+') as fout:
fout.write(buffer)
def container_cml_templ_add_symbl(projdesc, projname):
cont_templ = "config/cml/container_ruleset.template"
pattern = re.compile("(CONT\%\(cn\)d_BAREMETAL_PROJ_)(.*)")
baremetal_name_templ = "CONT%(cn)d_BAREMETAL_PROJ_"
new_sym = baremetal_name_templ + projname.upper()
buffer = ""
with open(cont_templ, 'r') as fin:
baremetal_sym_found = False
last_baremetal_proj = ""
# Prepare buffer for new cont_templ with new project symbols added
for line in fin:
parts = line.split()
# Find out where baremetal symbols start in cont_templ
if len(parts) > 1 and re.match(pattern, parts[0]):
baremetal_sym_found = True
# Find the name of last baremetal project already present in list
last_baremetal_proj = parts[0][len(baremetal_name_templ):]
# We are done with baremetal symbols, add new symbol to buffer
elif baremetal_sym_found == True:
baremetal_sym_found = False
sym_def = new_sym + "\t\'" + projdesc + "\'\n"
buffer += sym_def
# Search for baremetal menu and add new project symbol
elif len(parts) == 1 and \
parts[0] == baremetal_name_templ + last_baremetal_proj:
sym_reference = "\t" + new_sym + "\n"
line += sym_reference
buffer += line
# Write new cont_templ
with open(cont_templ, 'w+') as fout:
fout.write(buffer)
def add_project(projdesc, srcdir, projname):
container_cml_templ_add_symbl(projdesc, projname)
baremetal_dir = "conts/baremetal"
dest_dir = join(baremetal_dir, projname)
print "Copying source files from " + srcdir + " to " + dest_dir
shutil.copytree(srcdir, dest_dir)
print "Done, New baremetal project " + projname + \
" is ready to be used."
def del_project(srcdir, projname):
container_cml_templ_del_symbl(projname)
baremetal_dir = "conts/baremetal"
src_dir = join(baremetal_dir, projname)
print "Deleting source files from " + src_dir
shutil.rmtree(src_dir, "ignore_errors")
print "Done.."
def main():
projdesc, srcdir, add_del = parse_cmdline_options()
# Get the base directory
projpath, projname = os.path.split(srcdir)
# Python's basename() doesnot work fine if path ends with /,
# so we need to manually correct this
if projname == "":
projpath, projname = os.path.split(projpath)
if add_del == 1:
add_project(projdesc, srcdir, projname)
else:
del_project(srcdir, projname)
# Delete the config.cml file, so that user can see new projects
os.system("rm -f " + CML2_CONFIG_FILE)
if __name__ == "__main__":
main()

View File

@@ -49,8 +49,7 @@ class BaremetalContGenerator:
def create_baremetal_srctree(self, config, cont):
# First, create the base project directory and sources
str = 'baremetal' + cont.baremetal_id
shutil.copytree(join(self.BAREMETAL_PROJ_SRC_DIR, str), self.CONT_SRC_DIR)
shutil.copytree(join(self.BAREMETAL_PROJ_SRC_DIR, cont.dirname), self.CONT_SRC_DIR)
def copy_baremetal_build_desc(self, config, cont):
id_header = '[Container ID]\n'
@@ -114,7 +113,7 @@ class BaremetalContGenerator:
for cont in config.containers:
if cont.type == "baremetal":
# Determine container directory name.
self.CONT_SRC_DIR = join(self.BAREMETAL_SRC_BASEDIR, cont.dirname.lower())
self.CONT_SRC_DIR = join(self.BAREMETAL_SRC_BASEDIR, cont.name.lower())
self.build_readme_out = join(self.CONT_SRC_DIR, self.build_readme_name)
self.build_desc_out = join(self.CONT_SRC_DIR, self.build_desc_name)
self.linker_lds_out = join(join(self.CONT_SRC_DIR, 'include'), \
@@ -122,7 +121,7 @@ class BaremetalContGenerator:
self.container_h_out = join(join(self.CONT_SRC_DIR, 'include'), \
self.container_h_name)
if not os.path.exists(join(self.BAREMETAL_SRC_BASEDIR, cont.dirname)):
if not os.path.exists(join(self.BAREMETAL_SRC_BASEDIR, cont.name)):
self.create_baremetal_sources(config, cont)
else:
# Don't create new sources but update configuration

View File

@@ -26,7 +26,7 @@
*/
int platform_setup_device_caps(struct kernel_resources *kres)
{
struct capability *uart[4], *timer[4];
struct capability *uart[4], *timer[4], *clcd[1];
/* Setup capabilities for userspace uarts and timers */
uart[1] = alloc_bootmem(sizeof(*uart[1]), 0);
@@ -66,6 +66,16 @@ int platform_setup_device_caps(struct kernel_resources *kres)
link_init(&timer[1]->list);
cap_list_insert(timer[1], &kres->devmem_free);
/* Setup clcd capability as free */
clcd[0] = alloc_bootmem(sizeof(*clcd[0]), 0);
clcd[0]->start = __pfn(PB926_CLCD_BASE);
clcd[0]->end = clcd[0]->start + 1;
clcd[0]->size = clcd[0]->end - clcd[0]->start;
cap_set_devtype(clcd[0], CAP_DEVTYPE_CLCD);
cap_set_devnum(clcd[0], 0);
link_init(&clcd[0]->list);
cap_list_insert(clcd[0], &kres->devmem_free);
return 0;
}