os: remove dde_kit

Issue #1565
This commit is contained in:
Alexander Boettcher 2015-06-10 12:55:45 +02:00 committed by Christian Helmuth
parent e1be0b3f67
commit 52110b9d89
40 changed files with 1 additions and 4614 deletions

View File

@ -16,5 +16,4 @@ This is the example operating system based on the Genode OS framework:
against shared libraries.
:_Lib_: contains libraries used by the components of the OS repository,
in particular the device-driver kit, the alarm framework, and support
for dynamic linking.
for example, the alarm framework.

View File

@ -1,37 +0,0 @@
/*
* \brief Assertion macro
* \author Christian Helmuth
* \date 2008-11-04
*/
/*
* Copyright (C) 2008-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _INCLUDE__DDE_KIT__ASSERT_H_
#define _INCLUDE__DDE_KIT__ASSERT_H_
#include <dde_kit/printf.h>
#include <dde_kit/panic.h>
/**
* Assert a condition
*
* \param expr expression that must be true
*
* If the expression is not true, dde_kit_panic() is called.
*/
#define dde_kit_assert(expr) \
do { \
if (!(expr)) { \
dde_kit_print("Assertion failed: "#expr"\n"); \
dde_kit_printf(" File: %s:%d\n", __FILE__, __LINE__); \
dde_kit_printf(" Function: %s()\n", __FUNCTION__); \
dde_kit_panic("Assertion failed."); \
} \
} while (0);
#endif /* _INCLUDE__DDE_KIT__ASSERT_H_ */

View File

@ -1,24 +0,0 @@
/*
* \brief DDE Kit generals
* \author Christian Helmuth
* \date 2008-10-22
*/
/*
* Copyright (C) 2008-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _INCLUDE__DDE_KIT__DDE_KIT_H_
#define _INCLUDE__DDE_KIT__DDE_KIT_H_
/**
* Initialize the DDE Kit
*
* This function must be called before any other DDE function is used.
*/
void dde_kit_init(void);
#endif /* _INCLUDE__DDE_KIT__DDE_KIT_H_ */

View File

@ -1,33 +0,0 @@
/*
* \brief Support for initializers (i.e., constructors)
* \author Christian Helmuth
* \date 2008-08-15
*/
/*
* Copyright (C) 2008-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _INCLUDE__DDE_KIT__INITCALL_H_
#define _INCLUDE__DDE_KIT__INITCALL_H_
/**
* Mark function as DDE kit initcall
*
* \param fn function name
* \param id identifier to distinguish multiple calls to 'fn'
*
* The initcall function must comply 'int func(void)'.
* The marked function is exported via a non-static symbol called
* "dde_kit_initcall_<id>_<fn>". On driver startup, the driver environment has
* to explicitly call these functions.
*
* This is the right mechanism to mark, e.g., Linux module_init() functions.
*/
#define DDE_KIT_INITCALL(fn,id) \
int (*dde_kit_initcall_##id##_##fn)(void) = fn
#endif /* _INCLUDE__DDE_KIT__INITCALL_H_ */

View File

@ -1,60 +0,0 @@
/*
* \brief Hardware-interrupt subsystem
* \author Christian Helmuth
* \date 2008-08-15
*
* The DDE kit supports registration of one handler function per interrupt. If
* any specific DDE implementation needs to register more than one handler,
* multiplexing has to be implemented there!
*/
/*
* Copyright (C) 2008-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _INCLUDE__DDE_KIT__INTERRUPT_H_
#define _INCLUDE__DDE_KIT__INTERRUPT_H_
/**
* Attach to hardware interrupt
*
* \param irq IRQ number to attach to
* \param shared set to 1 if interrupt sharing is supported; set to 0
* otherwise
* \param thread_init called just after DDE kit internal init and before any
* other function
* \param handler IRQ handler for interrupt irq
* \param priv private token (argument for thread_init and handler)
*
* \return attachment state
* \retval 0 success
* \retval !0 error
*/
int dde_kit_interrupt_attach(int irq, int shared, void(*thread_init)(void *),
void(*handler)(void *), void *priv);
/**
* Detach from a previously attached interrupt.
*
* \param irq IRQ number
*/
void dde_kit_interrupt_detach(int irq);
/**
* Block interrupt.
*
* \param irq IRQ number to block
*/
void dde_kit_interrupt_disable(int irq);
/**
* Enable interrupt.
*
* \param irq IRQ number to block
*/
void dde_kit_interrupt_enable(int irq);
#endif /* _INCLUDE__DDE_KIT__INTERRUPT_H_ */

View File

@ -1,65 +0,0 @@
/*
* \brief Locks (i.e., mutex)
* \author Christian Helmuth
* \date 2008-08-15
*/
/*
* Copyright (C) 2008-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _INCLUDE__DDE_KIT__LOCK_H_
#define _INCLUDE__DDE_KIT__LOCK_H_
/**
* Private lock type
*/
struct dde_kit_lock;
/**
* Initialize lock
*
* \param out_lock lock handle (output parameter)
*
* The created lock is free (not acquired) after initialization.
*/
void dde_kit_lock_init(struct dde_kit_lock **out_lock);
/**
* Destroy lock
*
* \param lock lock handle
*
* The old lock handle is invalidated.
*/
void dde_kit_lock_deinit(struct dde_kit_lock *lock);
/**
* Acquire lock
*
* \param lock lock handle
*/
void dde_kit_lock_lock(struct dde_kit_lock *lock);
/**
* Acquire a lock (non-blocking)
*
* \param lock lock handle
*
* \return lock state
* \retval 0 lock was aquired
* \retval 1 lock was not aquired
*/
int dde_kit_lock_try_lock(struct dde_kit_lock *lock);
/**
* Release lock
*
* \param lock lock handle
*/
void dde_kit_lock_unlock(struct dde_kit_lock *lock);
#endif /* _INCLUDE__DDE_KIT__LOCK_H_ */

View File

@ -1,134 +0,0 @@
/*
* \brief Memory subsystem
* \author Christian Helmuth
* \date 2008-08-15
*/
/*
* Copyright (C) 2008-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _INCLUDE__DDE_KIT__MEMORY_H_
#define _INCLUDE__DDE_KIT__MEMORY_H_
#include <dde_kit/types.h>
/*******************
** Slab facility **
*******************/
struct dde_kit_slab;
/**
* Store user pointer in slab cache
*
* \param slab pointer to slab cache
* \param data user pointer
*/
void dde_kit_slab_set_data(struct dde_kit_slab * slab, void *data);
/**
* Read user pointer from slab cache
*
* \param slab pointer to slab cache
*
* \return stored user pointer or 0
*/
void *dde_kit_slab_get_data(struct dde_kit_slab * slab);
/**
* Allocate slab in slab cache
*
* \param slab pointer to slab cache
*
* \return pointer to allocated slab
*/
void *dde_kit_slab_alloc(struct dde_kit_slab * slab);
/**
* Deallocate slab in slab cache
*
* \param slab pointer to slab cache
* \param objp pointer to allocated slab
*/
void dde_kit_slab_free(struct dde_kit_slab * slab, void *objp);
/**
* Destroy slab cache
*
* \param slab pointer to slab cache structure
*/
void dde_kit_slab_destroy(struct dde_kit_slab * slab);
/**
* Initialize slab cache
*
* \param size size of cache objects
*
* \return pointer to new slab cache or 0 on error
*
* Allocated blocks have valid virt->phys mappings and are physically
* contiguous.
*/
struct dde_kit_slab * dde_kit_slab_init(unsigned size);
/**********************************
** Large-block memory allocator **
**********************************/
/**
* Allocate large memory block
*
* \param size block size
*
* \return pointer to new memory block
*
* Allocations via this allocator may be slow (because RPCs to remote services
* may be involved) and should be used only for large blocks of several pages.
* If allocations/deallocations are relatively dynamic the large memory
* allocator should be used as backend for a block caching frontend.
*
* Allocated blocks have valid virt->phys mappings and are physically
* contiguous.
*/
void *dde_kit_large_malloc(dde_kit_size_t size);
/**
* Free large memory block
*
* \param p pointer to memory block
*/
void dde_kit_large_free(void *p);
/*****************************
** Simple memory allocator **
*****************************/
/**
* Allocate memory block via simple allocator
*
* \param size block size
*
* \return pointer to new memory block
*
* The blocks allocated via this allocator CANNOT be used for DMA or other
* device operations, i.e., there exists no virt->phys mapping.
*/
void *dde_kit_simple_malloc(dde_kit_size_t size);
/**
* Free memory block via simple allocator
*
* \param p pointer to memory block
*
* As in C99, if 'p' is NULL no operation is performed.
*/
void dde_kit_simple_free(void *p);
#endif /* _INCLUDE__DDE_KIT__MEMORY_H_ */

View File

@ -1,33 +0,0 @@
/*
* \brief Debugging support
* \author Christian Helmuth
* \date 2008-08-15
*/
/*
* Copyright (C) 2008-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _INCLUDE__DDE_KIT__PANIC_H_
#define _INCLUDE__DDE_KIT__PANIC_H_
/**
* Print message and block
*
* \param fmt message format string
*/
__attribute__((noreturn)) void dde_kit_panic(const char *fmt, ...);
/**
* Print debug message and block
*
* \param fmt message format string
*
* Logs the debug message with appended newline.
*/
void dde_kit_debug(const char *fmt, ...);
#endif /* _INCLUDE__DDE_KIT__PANIC_H_ */

View File

@ -1,177 +0,0 @@
/*
* \brief PCI bus access
* \author Christian Helmuth
* \date 2008-10-01
*
* The DDE Kit provides virtual PCI bus hierarchy, which may be a subset of
* the PCI bus with the same bus-device-function IDs.
*/
/*
* Copyright (C) 2008-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _INCLUDE__DDE_KIT__PCI_H_
#define _INCLUDE__DDE_KIT__PCI_H_
#include <dde_kit/types.h>
/********************************
** Configuration space access **
********************************/
/**
* Read byte from PCI config space
*
* \param bus bus number
* \param dev device number
* \param fun function number
* \param pos offset in config space
*
* \retval val read value
*
* \return 0 on success, -1 otherwise
*/
void dde_kit_pci_readb(int bus, int dev, int fun, int pos, dde_kit_uint8_t *val);
/**
* Read word from PCI config space
*
* \param bus bus number
* \param dev device number
* \param fun function number
* \param pos offset in config space
*
* \retval val read value
*
* \return 0 on success, -1 otherwise
*/
void dde_kit_pci_readw(int bus, int dev, int fun, int pos, dde_kit_uint16_t *val);
/**
* Read dword from PCI config space
*
* \param bus bus number
* \param dev device number
* \param fun function number
* \param pos offset in config space
*
* \retval val read value
*
* \return 0 on success, -1 otherwise
*/
void dde_kit_pci_readl(int bus, int dev, int fun, int pos, dde_kit_uint32_t *val);
/**
* Write byte to PCI config space
*
* \param bus bus number
* \param dev device number
* \param fun function number
* \param pos offset in config space
* \param val value to write
*
* \return 0 on success, -1 otherwise
*/
void dde_kit_pci_writeb(int bus, int dev, int fun, int pos, dde_kit_uint8_t val);
/**
* Write word to PCI config space
*
* \param bus bus number
* \param dev device number
* \param fun function number
* \param pos offset in config space
* \param val value to write
*
* \return 0 on success, -1 otherwise
*/
void dde_kit_pci_writew(int bus, int dev, int fun, int pos, dde_kit_uint16_t val);
/**
* Write dword to PCI config space.
*
* \param bus bus number
* \param dev device number
* \param fun function number
* \param pos offset in config space
* \param val value to write
*
* \return 0 on success, -1 otherwise
*/
void dde_kit_pci_writel(int bus, int dev, int fun, int pos, dde_kit_uint32_t val);
/***************************
** Convenience functions **
***************************/
/**
* Find first PCI device on virtual bus tree
*
* \retval bus bus number
* \retval dev device number
* \retval fun function number
*
* \return 0 on success, -1 otherwise
*/
int dde_kit_pci_first_device(int *bus, int *dev, int *fun);
/**
* Find next PCI device
*
* \param bus bus number to start at
* \param dev device number to start at
* \param fun function number to start at
*
* \retval bus bus number
* \retval dev device number
* \retval fun function number
*
* \return 0 on success, -1 otherwise
*/
int dde_kit_pci_next_device(int *bus, int *dev, int *fun);
/**
* Allocate a DMA buffer and map it. If an IOMMU is available this functions
* takes care that DMA to this buffer for the given PCI device is permitted.
*
* \retval bus bus number
* \retval dev device number
* \retval fun function number
*
* \return 0 in case of failure, otherwise the virtual address of the buffer.
*/
dde_kit_addr_t dde_kit_pci_alloc_dma_buffer(int bus, int dev, int fun,
dde_kit_size_t size);
/**
* Initialize PCI subsystem
*
* The PCI subsystem can be instructed to request solely a specific PCI device
* or a specific PCI subset (one class or multiple). The parameters are
* described by the parameters device_class and class_mask, which are used to
* filter PCI class codes as described by the pseudo code:
*
* for each 'pci_device' out of 'all_pci_devices' try
* {
* bool nohit = (pci_device.class_code() ^ device_class) & class_mask
* if (!nohit)
* use 'pci_device' with this PCI subsystem
* }
*
* If no restriction to the PCI subsystem should be applied, use 0 for the
* device_class and class_mask.
*
* \param device_class filter applied with 'bitwise XOR' operand to the class
* code of each PCI device
* \param class_mask filter applied with 'bitwise AND' operand to the result
* out of device_class and PCI class code of each device
*/
void dde_kit_pci_init(unsigned device_class, unsigned class_mask);
#endif /* _INCLUDE__DDE_KIT__PCI_H_ */

View File

@ -1,72 +0,0 @@
/*
* \brief Virtual page-table facility
* \author Christian Helmuth
* \date 2008-08-15
*/
/*
* Copyright (C) 2008-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _INCLUDE__DDE_KIT__PGTAB_H_
#define _INCLUDE__DDE_KIT__PGTAB_H_
#include <dde_kit/types.h>
/**
* Set virtual->physical mapping for VM pages
*
* \param virt virtual start address for region
* \param phys physical start address for region
* \param pages number of pages in region
*/
void dde_kit_pgtab_set_region(void *virt, dde_kit_addr_t phys, unsigned pages);
/**
* Set virtual->physical mapping for VM region
*
* \param virt virtual start address for region
* \param phys physical start address for region
* \param size number of bytes in region
*/
void dde_kit_pgtab_set_region_with_size(void *virt, dde_kit_addr_t phys,
dde_kit_size_t size);
/**
* Clear virtual->physical mapping for VM region
*
* \param virt virtual start address for region
*/
void dde_kit_pgtab_clear_region(void *virt);
/**
* Get physical address for virtual address
*
* \param virt virtual address
*
* \return physical address
*/
dde_kit_addr_t dde_kit_pgtab_get_physaddr(void *virt);
/**
* Get virtual address for physical address
*
* \param phys physical address
*
* \return virtual address
*/
dde_kit_addr_t dde_kit_pgtab_get_virtaddr(dde_kit_addr_t phys);
/**
* Get size of VM region.
*
* \param virt virtual address
*
* \return VM region size (in bytes)
*/
dde_kit_size_t dde_kit_pgtab_get_size(void *virt);
#endif /* _INCLUDE__DDE_KIT__PGTAB_H_ */

View File

@ -1,56 +0,0 @@
/*
* \brief Formatted output
* \author Christian Helmuth
* \date 2008-08-15
*/
/*
* Copyright (C) 2008-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _INCLUDE__DDE_KIT__PRINTF_H_
#define _INCLUDE__DDE_KIT__PRINTF_H_
#include <stdarg.h>
/**
* Print message
*
* \param msg message string
*/
void dde_kit_print(const char *msg);
/**
* Print formatted message (varargs variant)
*
* \param fmt format string
*/
void dde_kit_printf(const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
/**
* Print formatted message (va_list variant)
*
* \param fmt format string
* \param va variable argument list
*/
void dde_kit_vprintf(const char *fmt, va_list va) __attribute__ ((format (printf, 1, 0)));
/**
* Log current function and message
*
* \param doit if false logging is suppressed
* \param msg format string plus arguments
*/
#define dde_kit_log(doit, msg...) \
do { \
if (doit) { \
dde_kit_printf("%s(): ", __func__); \
dde_kit_printf(msg); \
dde_kit_printf("\n"); \
} \
} while(0);
#endif /* _INCLUDE__DDE_KIT__PRINTF_H_ */

View File

@ -1,115 +0,0 @@
/*
* \brief Hardware-resource access
* \author Christian Helmuth
* \date 2008-10-21
*/
/*
* Copyright (C) 2008-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _INCLUDE__DDE_KIT__RESOURCES_H_
#define _INCLUDE__DDE_KIT__RESOURCES_H_
#include <dde_kit/types.h>
/**
* Allocate I/O port range (x86)
*
* \param start first port of range
* \param size size of port range
*
* \return 0 on success, -1 otherwise
*/
int dde_kit_request_io(dde_kit_addr_t start, dde_kit_size_t size,
unsigned short bar, dde_kit_uint8_t bus,
dde_kit_uint8_t dev, dde_kit_uint8_t func);
/**
* Free I/O port range (x86)
*
* \param start first port of range
* \param size size of port range
*
* \return 0 on success, -1 otherwise
*/
int dde_kit_release_io(dde_kit_addr_t start, dde_kit_size_t size);
/**
* Read I/O port (byte)
*
* \param port port to read
*
* \return value read from port
*/
unsigned char dde_kit_inb(dde_kit_addr_t port);
/**
* Read I/O port (2-byte)
*
* \param port port to read
*
* \return value read from port
*/
unsigned short dde_kit_inw(dde_kit_addr_t port);
/**
* Read I/O port (4-byte)
*
* \param port port to read
*
* \return value read from port
*/
unsigned long dde_kit_inl(dde_kit_addr_t port);
/**
* Write I/O port (byte)
*
* \param port port to write
* \param val value to write
*/
void dde_kit_outb(dde_kit_addr_t port, unsigned char val);
/**
* Write I/O port (2-byte)
*
* \param port port to write
* \param val value to write
*/
void dde_kit_outw(dde_kit_addr_t port, unsigned short val);
/**
* Write I/O port (4-byte)
*
* \param port port to write
* \param val value to write
*/
void dde_kit_outl(dde_kit_addr_t port, unsigned long val);
/**
* Allocate MMIO range
*
* \param start begin of MMIO range
* \param size size of MMIO range
* \param wc if !0 request write-combined memory mapping
*
* \retval vaddr virtual start address mapped range
* \return 0 on success, -1 otherwise
*/
int dde_kit_request_mem(dde_kit_addr_t start, dde_kit_size_t size,
int wc, dde_kit_addr_t *vaddr);
/**
* Free MMIO range
*
* \param start begin of MMIO range
* \param size size of MMIO range
*
* \return 0 on success, -1 otherwise
*/
int dde_kit_release_mem(dde_kit_addr_t start, dde_kit_size_t size);
#endif /* _INCLUDE__DDE_KIT__RESOURCES_H_ */

View File

@ -1,73 +0,0 @@
/*
* \brief Semaphores
* \author Christian Helmuth
* \date 2008-09-15
*/
/*
* Copyright (C) 2008-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _INCLUDE__DDE_KIT__SEMAPHORE_H_
#define _INCLUDE__DDE_KIT__SEMAPHORE_H_
struct dde_kit_sem;
typedef struct dde_kit_sem dde_kit_sem_t;
/**
* Initialize DDE kit semaphore
*
* \param value initial semaphore counter
*
* \return pointer to new semaphore
*/
dde_kit_sem_t *dde_kit_sem_init(int value);
/**
* Deinitialize semaphore
*
* \param sem semaphore reference
*/
void dde_kit_sem_deinit(dde_kit_sem_t *sem);
/**
* Acquire semaphore
*
* \param sem semaphore reference
*/
void dde_kit_sem_down(dde_kit_sem_t *sem);
/**
* Acquire semaphore (non-blocking)
*
* \param sem semaphore reference
*
* \return semaphore state
* \retval 0 semaphore was acquired
* \retval !=0 semaphore was not acquired
*/
int dde_kit_sem_down_try(dde_kit_sem_t *sem);
/**
* Acquire semaphore (with timeout)
*
* \param sem semaphore reference
* \param timeout timeout (in ms)
*
* \return semaphore state
* \retval 0 semaphore was acquired
* \retval !=0 semaphore was not acquired
*/
//int dde_kit_sem_down_timed(dde_kit_sem_t *sem, int timout);
/**
* Release semaphore
*
* \param sem semaphore reference
*/
void dde_kit_sem_up(dde_kit_sem_t *sem);
#endif /* _INCLUDE__DDE_KIT__SEMAPHORE_H_ */

View File

@ -1,50 +0,0 @@
/*
* \brief Spin lock
* \author Norman Feske
* \date 2012-01-27
*/
/*
* Copyright (C) 2012-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _INCLUDE__DDE_KIT__SPIN_LOCK_H_
#define _INCLUDE__DDE_KIT__SPIN_LOCK_H_
/**
* Private spin lock type
*/
typedef volatile int dde_kit_spin_lock;
enum { DDE_KIT_SPIN_LOCK_LOCKED, DDE_KIT_SPIN_LOCK_UNLOCKED };
/**
* Initialize spin lock
*
* \param out_lock lock handle (output parameter)
*
* The created lock is free (not acquired) after initialization.
*/
void dde_kit_spin_lock_init(dde_kit_spin_lock *spin_lock);
/**
* Acquire spin lock
*/
void dde_kit_spin_lock_lock(dde_kit_spin_lock *spin_lock);
/**
* Try to acquire a lock (non-blocking)
*/
int dde_kit_spin_lock_try_lock(dde_kit_spin_lock *spin_lock);
/**
* Release spin lock
*/
void dde_kit_spin_lock_unlock(dde_kit_spin_lock *spin_lock);
#endif /* _INCLUDE__DDE_KIT__SPIN_LOCK_H_ */

View File

@ -1,138 +0,0 @@
/*
* \brief Thread facility
* \author Christian Helmuth
* \date 2008-10-20
*/
/*
* Copyright (C) 2008-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _INCLUDE__DDE_KIT__THREAD_H_
#define _INCLUDE__DDE_KIT__THREAD_H_
#include <dde_kit/lock.h>
struct dde_kit_thread;
/**
* Create thread
*
* \param fun thread function
* \param arg argument to thread function, set to NULL if not needed
* \param name thread name
*
* \return thread handle
*
* Create a new thread running the specified function with argument arg. The
* thread is assigned the given name.
*
* All DDE kit threads support thread-local storage where one data pointer may
* be stored and retrieved.
*/
struct dde_kit_thread * dde_kit_thread_create(void (*fun)(void *), void *arg, const char *name);
/**
* Adopt calling as DDE kit thread
*
* \param name thread name
*
* \return thread handle
*/
struct dde_kit_thread * dde_kit_thread_adopt_myself(const char *name);
/**
* Get handle of current thread
*
* \return thread handle
*/
struct dde_kit_thread * dde_kit_thread_myself(void);
/**
* Get thread-local data of a specific thread
*
* \param thread thread handle
*
* \return thread-local data of this thread
*/
void * dde_kit_thread_get_data(struct dde_kit_thread * thread);
/**
* Get thread-local data of current thread
*
* \return thread-local data of current thread
*/
void * dde_kit_thread_get_my_data(void);
/**
* Set thread-local data of specific thread
*
* \param thread thread handle
* \param data thread-local data pointer
*/
void dde_kit_thread_set_data(struct dde_kit_thread *thread, void *data);
/**
* Set thread-local data of current thread
*
* \param data thread-local data pointer
*/
void dde_kit_thread_set_my_data(void *data);
/**
* Sleep (milliseconds)
*
* \param msecs time to sleep in milliseconds
*/
void dde_kit_thread_msleep(unsigned long msecs);
/**
* Sleep (microseconds)
*
* \param usecs time to sleep in microseconds
*/
void dde_kit_thread_usleep(unsigned long usecs);
/**
* Sleep (nanoseconds)
*
* \param nsecs time to sleep in nanoseconds
*/
void dde_kit_thread_nsleep(unsigned long nsecs);
/**
* Exit current thread
*/
void dde_kit_thread_exit(void);
/**
* Get thread name
*
* \param thread thread handle
*/
const char *dde_kit_thread_get_name(struct dde_kit_thread *thread);
/**
* Get unique ID
*
* \param thread thread handle
* \return artificial thread ID
*
* DDE kit does not allow direct access to the thread data structure, since
* this struct contains platform-specific data types. However, applications
* might want to get some kind of ID related to a dde_kit_thread, for instance
* to use it as a Linux-like PID.
*
* XXX This function may be removed.
*/
int dde_kit_thread_get_id(struct dde_kit_thread *thread);
/**
* Hint that this thread is done and may be scheduled somehow
*/
void dde_kit_thread_schedule(void);
#endif /* _INCLUDE__DDE_KIT__THREAD_H_ */

View File

@ -1,84 +0,0 @@
/*
* \brief Timers and tick
* \author Christian Helmuth
* \date 2008-10-22
*
* DDE kit provides a generic timer implementation that enables users to
* execute a callback function after a certain period of time. Therefore, DDE
* kit starts a timer thread that executes callbacks and keeps track of the
* currently running timers.
*/
/*
* Copyright (C) 2008-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _INCLUDE__DDE_KIT__TIMER_H_
#define _INCLUDE__DDE_KIT__TIMER_H_
#include <dde_kit/thread.h>
/**********
** Tick **
**********/
/** Timer tick (global symbol) */
extern volatile unsigned long dde_kit_timer_ticks;
/** Timer tick rate */
enum { DDE_KIT_HZ = 100 };
/***********
** Timer **
***********/
struct dde_kit_timer;
/**
* Add timer event handler
*
* \param fn function to call on timeout
* \param priv private handler token
* \param timeout absolute timeout (in DDE kit ticks)
*
* \return timer reference on success; 0 otherwise
*
* After the absolute timeout has expired, function fn is called with args as
* arguments.
*/
struct dde_kit_timer *dde_kit_timer_add(void (*fn)(void *), void *priv,
unsigned long timeout);
/**
* Delete timer
*
* \param timer timer reference
*/
void dde_kit_timer_del(struct dde_kit_timer *timer);
/**
* Schedule absolute timeout
*
* \param timer timer reference
* \param timeout absolute timeout (in DDE kit ticks)
*/
void dde_kit_timer_schedule_absolute(struct dde_kit_timer *timer, unsigned long timeout);
/**
* Check whether a timer is pending
*
* \param timer timer reference
*/
int dde_kit_timer_pending(struct dde_kit_timer *timer);
/** Init timers and ticks */
void dde_kit_timer_init(void(*thread_init)(void *), void *priv);
#endif /* _INCLUDE__DDE_KIT__TIMER_H_ */

View File

@ -1,41 +0,0 @@
/*
* \brief DDE Kit types
* \author Christian Helmuth
* \date 2008-08-15
*
* DDE Kit defines a strict boundary between the host system, i.e., Genode, and
* the emulated system, e.g., Linux. Therefore we cannot use Genode headers for
* type definition directly. We must redefine all required types to prevent
* potential incompatiblities and conflicts.
*/
/*
* Copyright (C) 2008-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _INCLUDE__DDE_KIT__TYPES_H_
#define _INCLUDE__DDE_KIT__TYPES_H_
#include <base/fixed_stdint.h> /* free-standing standard interger types */
enum {
DDE_KIT_PAGE_SHIFT = 12,
DDE_KIT_PAGE_SIZE = 1 << DDE_KIT_PAGE_SHIFT, /* our page size is 4096 */
};
typedef genode_int8_t dde_kit_int8_t;
typedef genode_uint8_t dde_kit_uint8_t;
typedef genode_int16_t dde_kit_int16_t;
typedef genode_uint16_t dde_kit_uint16_t;
typedef genode_int32_t dde_kit_int32_t;
typedef genode_uint32_t dde_kit_uint32_t;
typedef genode_int64_t dde_kit_int64_t;
typedef genode_uint64_t dde_kit_uint64_t;
typedef unsigned long dde_kit_addr_t;
typedef __SIZE_TYPE__ dde_kit_size_t;
#endif /* _INCLUDE__DDE_KIT__TYPES_H_ */

View File

@ -1,17 +0,0 @@
SRC_C = lock.cc semaphore.cc panic.cc printf.cc interrupt.cc pgtab.cc \
memory.cc thread.cc pci_tree.cc pci.cc resources.cc timer.cc \
dde_kit.cc spin_lock.cc
LIBS = base alarm
#
# Enable 'spin_lock.cc' to reuse the spinlock implementation of the base
# repository by including the corresponding non-public headers local to
# 'base-<platform>/src'. Because the platform-specific parts of these headers
# may contain code that invokes system calls, we need to specify the 'syscall'
# lib as well. This way, the needed include-search directories are supplied to
# the build system via the respective 'import-syscall.mk' file.
#
LIBS += syscall
REP_INC_DIR += src/base/lock src/platform
vpath % $(REP_DIR)/src/lib/dde_kit

View File

@ -1,20 +0,0 @@
/*
* \brief DDE Kit generals and initialization
* \author Christian Helmuth
* \date 2008-10-22
*/
/*
* Copyright (C) 2008-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
extern "C" {
#include <dde_kit/dde_kit.h>
}
extern "C" void dde_kit_init(void)
{
}

View File

@ -1,27 +0,0 @@
/*
* \brief Lib internal interface to use and request resources provided by
* platform driver
* \author Alexander Boettcher
* \date 2015-04-05
*/
/*
* Copyright (C) 2015 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#pragma once
#include <io_port_session/capability.h>
namespace Dde_kit { class Device; }
class Dde_kit::Device {
public:
static Genode::Io_port_session_capability io_port(int bus, int dev,
int fun,
unsigned short bda);
};

View File

@ -1,222 +0,0 @@
/*
* \brief Hardware-interrupt subsystem
* \author Christian Helmuth
* \date 2008-08-15
*
* Open issues:
*
* - IRQ thread priority
* - IRQ sharing
* - IRQ detachment
* - Could be solved by just killing driver process and reclaiming all
* resources.
* - error handling on attachment
*/
/*
* Copyright (C) 2008-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#include <base/env.h>
#include <base/lock.h>
#include <base/printf.h>
#include <base/thread.h>
#include <base/snprintf.h>
#include <util/avl_tree.h>
#include <irq_session/connection.h>
extern "C" {
#include <dde_kit/interrupt.h>
#include <dde_kit/thread.h>
}
#include "thread.h"
using namespace Genode;
class Irq_handler : Dde_kit::Thread, public Avl_node<Irq_handler>
{
private:
unsigned _irq_number; /* IRQ number */
Irq_connection _irq; /* IRQ connection */
char _thread_name[10];
void (*_handler)(void *); /* handler function */
void (*_init)(void *); /* thread init function */
void *_priv; /* private handler token */
bool _shared; /* true, if IRQ sharing is supported */
int _handle_irq; /* nested irq disable counter */
Lock _lock; /* synchronize access to counter */
Genode::Signal_receiver _sig_rec;
Genode::Signal_dispatcher<Irq_handler> _irq_dispatcher;
const char * _compose_thread_name(unsigned irq)
{
snprintf(_thread_name, sizeof(_thread_name), "irq.%02x", irq);
return _thread_name;
}
void _handle(unsigned)
{
_irq.ack_irq();
/* only call registered handler function, if IRQ is not disabled */
_lock.lock();
if (_handle_irq) _handler(_priv);
_lock.unlock();
}
public:
Irq_handler(unsigned irq, void (*handler)(void *), void *priv,
void (*init)(void *) = 0, bool shared = false)
:
Dde_kit::Thread(_compose_thread_name(irq)), _irq_number(irq),
_irq(irq), _handler(handler), _init(init), _priv(priv),
_shared(shared), _handle_irq(1), _lock(Lock::LOCKED),
_irq_dispatcher(_sig_rec, *this, &Irq_handler::_handle)
{
_irq.sigh(_irq_dispatcher);
start();
/* wait until thread is started */
Lock::Guard guard(_lock);
/* initial ack so that we will receive further interrupts */
_irq.ack_irq();
}
/** Enable IRQ handling */
void enable()
{
Lock::Guard lock_guard(_lock);
++_handle_irq;
}
/** Disable IRQ handling */
void disable()
{
Lock::Guard lock_guard(_lock);
--_handle_irq;
}
/** Thread entry */
void entry()
{
dde_kit_thread_adopt_myself(_thread_name);
/* call user init function before doing anything else here */
if (_init) _init(_priv);
/* unblock creating thread */
_lock.unlock();
while (1) {
using namespace Genode;
Signal sig = _sig_rec.wait_for_signal();
int num = sig.num();
Signal_dispatcher_base *dispatcher;
dispatcher = dynamic_cast<Signal_dispatcher_base *>(sig.context());
dispatcher->dispatch(num);
}
}
/** AVL node comparison */
bool higher(Irq_handler *irq_handler) {
return (_irq_number < irq_handler->_irq_number); }
/** AVL node lookup */
Irq_handler *lookup(unsigned irq_number)
{
if (irq_number == _irq_number) return this;
Irq_handler *h = child(_irq_number < irq_number);
return h ? h->lookup(irq_number) : 0;
}
};
class Irq_handler_database : public Avl_tree<Irq_handler>
{
private:
Lock _lock;
public:
Irq_handler *lookup(unsigned irq_number)
{
Lock::Guard lock_guard(_lock);
return first() ? first()->lookup(irq_number) : 0;
}
void insert(Irq_handler *h)
{
Lock::Guard lock_guard(_lock);
Avl_tree<Irq_handler>::insert(h);
}
void remove(Irq_handler *h)
{
Lock::Guard lock_guard(_lock);
Avl_tree<Irq_handler>::remove(h);
}
};
static Irq_handler_database *irq_handlers()
{
static Irq_handler_database _irq_handlers;
return &_irq_handlers;
}
extern "C" int dde_kit_interrupt_attach(int irq, int shared,
void(*thread_init)(void *),
void(*handler)(void *), void *priv)
{
Irq_handler *h;
try {
h = new (env()->heap()) Irq_handler(irq, handler, priv, thread_init);
} catch (...) {
PERR("allocation failed (size=%zd)", sizeof(*h));
return -1;
}
irq_handlers()->insert(h);
return 0;
}
extern "C" void dde_kit_interrupt_detach(int irq) {
PERR("not implemented yet"); }
extern "C" void dde_kit_interrupt_disable(int irq)
{
Irq_handler *h = irq_handlers()->lookup(irq);
if (h) h->disable();
}
extern "C" void dde_kit_interrupt_enable(int irq)
{
Irq_handler *h = irq_handlers()->lookup(irq);
if (h) h->enable();
}

View File

@ -1,67 +0,0 @@
/*
* \brief Locks (i.e., mutex)
* \author Christian Helmuth
* \date 2008-08-15
*
* Open issues:
*
* - What about slabs for locks?
*/
/*
* Copyright (C) 2008-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#include <base/env.h>
#include <base/lock.h>
#include <base/printf.h>
extern "C" {
#include <dde_kit/lock.h>
}
struct dde_kit_lock { };
extern "C" void dde_kit_lock_init(struct dde_kit_lock **out_lock)
{
try {
*out_lock = reinterpret_cast<struct dde_kit_lock *>
(new (Genode::env()->heap()) Genode::Lock());
} catch (...) {
PERR("lock creation failed");
}
}
extern "C" void dde_kit_lock_deinit(struct dde_kit_lock *lock)
{
try {
destroy(Genode::env()->heap(), reinterpret_cast<Genode::Lock *>(lock));
} catch (...) { }
}
extern "C" void dde_kit_lock_lock(struct dde_kit_lock *lock)
{
reinterpret_cast<Genode::Lock *>(lock)->lock();
}
extern "C" int dde_kit_lock_try_lock(struct dde_kit_lock *lock)
{
PERR("not implemented - will potentially block");
reinterpret_cast<Genode::Lock *>(lock)->lock();
/* success */
return 0;
}
extern "C" void dde_kit_lock_unlock(struct dde_kit_lock *lock)
{
reinterpret_cast<Genode::Lock *>(lock)->unlock();
}

View File

@ -1,303 +0,0 @@
/*
* \brief Memory subsystem
* \author Christian Helmuth
* \date 2008-08-15
*
* Open issues:
*
* - Rethink file split up
* - What about slabs for large malloc blocks?
*/
/*
* Copyright (C) 2008-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#include <base/env.h>
#include <base/lock.h>
#include <base/printf.h>
#include <base/slab.h>
#include <util/avl_tree.h>
#include <util/misc_math.h>
#include <dataspace/client.h>
#include <os/attached_ram_dataspace.h>
extern "C" {
#include <dde_kit/memory.h>
#include <dde_kit/pgtab.h>
}
using namespace Genode;
/*****************************
** Backing store allocator **
*****************************/
/*
* The backing store allocator allocates RAM dataspaces and maintains virtual
* page-table entries.
*/
class Backing_store_allocator : public Allocator
{
private:
class Block : public Avl_node<Block>
{
private:
Attached_ram_dataspace *_ram_ds;
public:
Block(Attached_ram_dataspace *ram_ds) : _ram_ds(ram_ds) { }
Attached_ram_dataspace *ram_ds() const { return _ram_ds; }
/* AVL node comparison */
bool higher(Block *b) {
return _ram_ds->local_addr<void>() < b->_ram_ds->local_addr<void>(); }
/* AVL node lookup */
Block *lookup(void *virt)
{
if (virt == _ram_ds->local_addr<void>()) return this;
Block *b = child(_ram_ds->local_addr<void>() < virt);
return b ? b->lookup(virt) : 0;
}
};
Avl_tree<Block> _map; /* backing store block map */
size_t _consumed; /* allocated memory size */
Lock _lock; /* synchronize access to allocator */
public:
Backing_store_allocator() { }
virtual ~Backing_store_allocator() { }
/***************
** Allocator **
***************/
bool alloc(size_t size, void **out_addr)
{
Lock::Guard lock_guard(_lock);
Attached_ram_dataspace *ram_ds;
/* alloc and attach RAM dataspace */
try {
ram_ds = new (env()->heap()) Attached_ram_dataspace(env()->ram_session(), size);
} catch (...) {
PERR("RAM allocation failed (size=%zx)", size);
return false;
}
/* setup virt->phys and phys->virt mappings */
void *virt = ram_ds->local_addr<void>();
addr_t phys = Dataspace_client(ram_ds->cap()).phys_addr();
dde_kit_pgtab_set_region_with_size(virt, phys, size);
/* store allocation in our map */
Block *b = new (env()->heap()) Block(ram_ds);
/* cleanup on error */
if (!b) {
dde_kit_pgtab_clear_region(virt);
destroy(env()->heap(), ram_ds);
return false;
}
_map.insert(b);
_consumed += size;
*out_addr = virt;
return true;
}
void free(void *virt, size_t size)
{
Lock::Guard lock_guard(_lock);
/* lookup address */
Block *b = _map.first() ? _map.first()->lookup(virt) : 0;
if (!b) return;
Attached_ram_dataspace *ram_ds = b->ram_ds();
/*
* We support freeing of the whole block only.
*/
if (size && (size != dde_kit_pgtab_get_size(virt)))
PERR("Cannot split RAM allocations - the whole block is free'd.");
/* remove allocation from our map */
_map.remove(b);
/* delete virt->phys and phys->virt mappings */
dde_kit_pgtab_clear_region(virt);
/* detach and free RAM dataspace */
destroy(env()->heap(), ram_ds);
/* free meta data */
destroy(env()->heap(), b);
}
size_t consumed() const { return _consumed; }
size_t overhead(size_t size) const { return 0; }
bool need_size_for_free() const override { return false; }
};
/**
* Get backing store allocator
*
* \return reference to static backing store object
*/
static Backing_store_allocator * backing_store_allocator()
{
static Backing_store_allocator _backing_store_allocator;
return &_backing_store_allocator;
}
/*******************
** Slab facility **
*******************/
struct dde_kit_slab : public Slab
{
private:
void *_data;
size_t _object_size;
/*
* Each slab in the slab cache contains about 8 objects as proposed in
* the paper by Bonwick and block sizes are multiples of page size.
*/
size_t _calculate_block_size(size_t object_size)
{
size_t block_size = 8 * (object_size + sizeof(Slab_entry)) + sizeof(Slab_block);
return align_addr(block_size, DDE_KIT_PAGE_SHIFT);
}
public:
dde_kit_slab(size_t object_size)
:
Slab(object_size, _calculate_block_size(object_size), 0, backing_store_allocator()),
_object_size(object_size) { }
inline void *alloc()
{
void *result;
return (Slab::alloc(_object_size, &result) ? result : 0);
}
inline void *data() const { return _data; }
inline void data(void *data) { _data = data; }
};
extern "C" void dde_kit_slab_set_data(struct dde_kit_slab * slab, void *data) {
slab->data(data); }
extern "C" void *dde_kit_slab_get_data(struct dde_kit_slab * slab) {
return slab->data(); }
extern "C" void *dde_kit_slab_alloc(struct dde_kit_slab * slab) {
return slab->alloc(); }
extern "C" void dde_kit_slab_free(struct dde_kit_slab * slab, void *objp) {
slab->free(objp); }
extern "C" void dde_kit_slab_destroy(struct dde_kit_slab * slab) {
destroy(env()->heap(), slab); }
extern "C" struct dde_kit_slab * dde_kit_slab_init(unsigned size)
{
dde_kit_slab *slab_cache;
try {
slab_cache = new (env()->heap()) dde_kit_slab(size);
} catch (...) {
PERR("allocation failed (size=%zd)", sizeof(*slab_cache));
return 0;
}
return slab_cache;
}
/**********************************
** Large-block memory allocator **
**********************************/
extern "C" void *dde_kit_large_malloc(dde_kit_size_t size)
{
void *virt;
if (!backing_store_allocator()->alloc(size, &virt))
return 0;
return virt;
}
extern "C" void dde_kit_large_free(void *virt) {
backing_store_allocator()->free(virt, 0);
}
/*****************************
** Simple memory allocator **
*****************************/
extern "C" void *dde_kit_simple_malloc(dde_kit_size_t size)
{
/*
* We store the size of the allocation at the very
* beginning of the allocated block and return
* the subsequent address. This way, we can retrieve
* the size information when freeing the block.
*/
size_t real_size = size + sizeof(size_t);
size_t *addr;
try {
addr = (size_t *)env()->heap()->alloc(real_size);
} catch (...) {
return 0;
}
*addr = real_size;
return addr + 1;
}
extern "C" void dde_kit_simple_free(void *p)
{
if (!p) return;
size_t *addr = ((size_t *)p) - 1;
env()->heap()->free(addr, *addr);
}

View File

@ -1,42 +0,0 @@
/*
* \brief Debugging support
* \author Christian Helmuth
* \date 2008-08-15
*/
/*
* Copyright (C) 2008-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#include <base/printf.h>
#include <base/sleep.h>
extern "C" {
#include <dde_kit/panic.h>
}
extern "C" void dde_kit_panic(const char *fmt, ...)
{
va_list va;
va_start(va, fmt);
Genode::vprintf(fmt, va);
va_end(va);
Genode::printf("\n");
/* XXX original implementation enters a kernel debugger here */
Genode::sleep_forever();
}
extern "C" void dde_kit_debug(const char *fmt, ...)
{
va_list va;
va_start(va, fmt);
Genode::vprintf(fmt, va);
va_end(va);
Genode::printf("\n");
}

View File

@ -1,181 +0,0 @@
/*
* \brief PCI bus access
* \author Christian Helmuth
* \date 2008-10-22
*
* We provide a virtual PCI bus hierarchy in pci_tree.cc:
*
* - Grab all accessible devices at pci_drv and populate virtual bus hierarchy.
* (This also works if parents/device managers limit device access in the
* future.)
* - DDE kit C interface in pci.cc
* - Read/write config space
* - Convenience functions
*/
/*
* Copyright (C) 2008-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#include <base/printf.h>
#include <dataspace/client.h>
#include <io_port_session/capability.h>
extern "C" {
#include <dde_kit/pci.h>
#include <dde_kit/pgtab.h>
}
#include "pci_tree.h"
#include "device.h"
static const bool verbose = false;
static Dde_kit::Pci_tree *pci_tree(unsigned device_class = 0,
unsigned class_mask = 0)
{
static Dde_kit::Pci_tree _pci_tree(device_class, class_mask);
return &_pci_tree;
}
Genode::Io_port_session_capability Dde_kit::Device::io_port(int bus, int dev, int fun, unsigned short bda) {
return pci_tree()->io_port(bus, dev, fun, bda); }
/********************************
** Configuration space access **
********************************/
extern "C" void dde_kit_pci_readb(int bus, int dev, int fun, int pos, dde_kit_uint8_t *val)
{
try {
*val = pci_tree()->config_read(bus, dev, fun, pos, Pci::Device::ACCESS_8BIT) & 0xff;
} catch (...) {
if (verbose)
PWRN("PCI device %02x:%02x.%x not found", bus, dev, fun);
*val = ~0;
}
}
extern "C" void dde_kit_pci_readw(int bus, int dev, int fun, int pos, dde_kit_uint16_t *val)
{
try {
*val = pci_tree()->config_read(bus, dev, fun, pos, Pci::Device::ACCESS_16BIT) & 0xffff;
} catch (...) {
if (verbose)
PWRN("PCI device %02x:%02x.%x not found", bus, dev, fun);
*val = ~0;
}
}
extern "C" void dde_kit_pci_readl(int bus, int dev, int fun, int pos, dde_kit_uint32_t *val)
{
try {
*val = pci_tree()->config_read(bus, dev, fun, pos, Pci::Device::ACCESS_32BIT);
} catch (...) {
if (verbose)
PWRN("PCI device %02x:%02x.%x not found", bus, dev, fun);
*val = ~0;
}
}
extern "C" void dde_kit_pci_writeb(int bus, int dev, int fun, int pos, dde_kit_uint8_t val)
{
try {
pci_tree()->config_write(bus, dev, fun, pos, val, Pci::Device::ACCESS_8BIT);
} catch (...) {
if (verbose)
PWRN("PCI device %02x:%02x.%x not found", bus, dev, fun);
}
}
extern "C" void dde_kit_pci_writew(int bus, int dev, int fun, int pos, dde_kit_uint16_t val)
{
try {
pci_tree()->config_write(bus, dev, fun, pos, val, Pci::Device::ACCESS_16BIT);
} catch (...) {
if (verbose)
PWRN("PCI device %02x:%02x.%x not found", bus, dev, fun);
}
}
extern "C" void dde_kit_pci_writel(int bus, int dev, int fun, int pos, dde_kit_uint32_t val)
{
try {
pci_tree()->config_write(bus, dev, fun, pos, val, Pci::Device::ACCESS_32BIT);
} catch (...) {
if (verbose)
PWRN("PCI device %02x:%02x.%x not found", bus, dev, fun);
}
}
/***************************
** Convenience functions **
***************************/
extern "C" int dde_kit_pci_first_device(int *bus, int *dev, int *fun)
{
try {
pci_tree()->first_device(bus, dev, fun);
return 0;
} catch (...) {
return -1;
}
}
extern "C" int dde_kit_pci_next_device(int *bus, int *dev, int *fun)
{
try {
pci_tree()->next_device(bus, dev, fun);
return 0;
} catch (...) {
return -1;
}
}
extern "C" dde_kit_addr_t dde_kit_pci_alloc_dma_buffer(int bus, int dev,
int fun,
dde_kit_size_t size)
{
try {
using namespace Genode;
Ram_dataspace_capability ram_cap;
ram_cap = pci_tree()->alloc_dma_buffer(bus, dev, fun, size);
addr_t base = (addr_t)env()->rm_session()->attach(ram_cap);
/* add to DDE-kit page tables */
addr_t phys = Dataspace_client(ram_cap).phys_addr();
dde_kit_pgtab_set_region_with_size((void *)base, phys, size);
return base;
} catch (...) {
return 0;
}
}
/********************
** Initialization **
********************/
extern "C" void dde_kit_pci_init(unsigned device_class, unsigned class_mask)
{
try {
pci_tree(device_class, class_mask);
} catch (...) {
PERR("PCI initialization failed");
}
}

View File

@ -1,83 +0,0 @@
/*
* \brief Virtual PCI bus tree for DDE kit
* \author Christian Helmuth
* \date 2008-10-22
*/
/*
* Copyright (C) 2008-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#include "pci_tree.h"
using namespace Dde_kit;
static const bool verbose = false;
static const bool verbose_access = false;
/****************
** PCI device **
****************/
uint32_t Pci_device::config_read(unsigned char address, Pci::Device::Access_size size)
{
uint32_t result = _device.config_read(address, size);
if (verbose_access)
PDBG("PCI read cfg (%d) %x of %02x:%02x.%x -- %x",
size, address, bus(), dev(), fun(), result);
return result;
}
void Pci_device::config_write(unsigned char address, uint32_t val,
Pci::Device::Access_size size)
{
_device.config_write(address, val, size);
if (verbose_access)
PDBG("PCI write cfg (%d) %x (%x) of %02x:%02x.%x",
size, address, val, bus(), dev(), fun());
}
/*************
** PCI bus **
*************/
Pci_tree::Pci_tree(unsigned device_class, unsigned class_mask)
{
/*
* Iterate through all accessible devices and populate virtual
* PCI bus tree.
*/
Pci::Device_capability prev_device_cap;
Pci::Device_capability device_cap = _pci_drv.first_device(device_class,
class_mask);
while (device_cap.valid()) {
Pci_device *device = new (env()->heap()) Pci_device(device_cap);
_devices.insert(device);
prev_device_cap = device_cap;
for (unsigned i = 0; i < 2; i++) {
try {
device_cap = _pci_drv.next_device(prev_device_cap, device_class,
class_mask);
break;
} catch (Pci::Device::Quota_exceeded) {
Genode::env()->parent()->upgrade(_pci_drv.cap(), "ram_quota=4096");
}
}
}
if (verbose)
_show_devices();
}

View File

@ -1,293 +0,0 @@
/*
* \brief Virtual PCI bus tree for DDE kit
* \author Christian Helmuth
* \date 2008-10-22
*/
/*
* Copyright (C) 2008-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _PCI_TREE_H_
#define _PCI_TREE_H_
#include <base/stdint.h>
#include <base/printf.h>
#include <base/lock.h>
#include <util/avl_tree.h>
#include <pci_session/connection.h>
#include <pci_device/client.h>
#include <io_port_session/capability.h>
namespace Dde_kit {
using namespace Genode;
class Pci_device : public Avl_node<Pci_device>
{
public:
static inline unsigned short knit_bdf(int bus, int dev, int fun)
{
return ((bus & 0xff) << 8)
| ((dev & 0x1f) << 3)
| (fun & 0x07);
}
private:
Pci::Device_client _device;
unsigned short _bdf; /* bus:device:function */
public:
Pci_device(Pci::Device_capability device_cap)
:
_device(device_cap)
{
unsigned char bus = ~0, dev = ~0, fun = ~0;
_device.bus_address(&bus, &dev, &fun);
_bdf = knit_bdf(bus, dev, fun);
}
/***************
** Accessors **
***************/
unsigned short bdf() const { return _bdf; }
unsigned char bus() const { return (_bdf >> 8) & 0xff; }
unsigned char dev() const { return (_bdf >> 3) & 0x1f; }
unsigned char fun() const { return _bdf & 0x07; }
/********************************
** Configuration space access **
********************************/
uint32_t config_read(unsigned char address, Pci::Device::Access_size size);
void config_write(unsigned char address, uint32_t val,
Pci::Device::Access_size size);
/** AVL node comparison */
bool higher(Pci_device *device) {
return (_bdf < device->_bdf); }
Pci_device *next(Pci_device *root, Side direction)
{
/*
* The predecessor of a node is the right-most node of the left
* subtree or the parent right after the first "left turn" up to
* the root of the tree. Symmetrically, the successor of a node is
* the left-most node of the right subtree or the parent right
* after the first "right turn" up to the root of the tree.
*/
if (child(direction)) {
Pci_device *n = child(direction);
while (true) {
if (!n->child(!direction))
return n;
else
n = n->child(!direction);
}
} else {
Pci_device *n = this;
for (Pci_device *parent = static_cast<Pci_device *>(n->_parent);
n != root;
n = parent, parent = static_cast<Pci_device *>(n->_parent)) {
if (n == parent->child(!direction))
return parent;
}
return 0;
}
}
void show()
{
if (child(LEFT)) child(LEFT)->show();
unsigned char ht = config_read(0x0e, Pci::Device::ACCESS_8BIT) & 0xff;
PINF("%02x:%02x.%x %04x:%04x (%x) ht=%02x",
bus(), dev(), fun(),
_device.vendor_id(), _device.device_id(), _device.base_class(), ht);
if (child(RIGHT)) child(RIGHT)->show();
}
Ram_dataspace_capability alloc_dma_buffer(Pci::Connection &pci_drv,
size_t size)
{
for (unsigned i = 0; i < 2; i++) {
try {
return pci_drv.alloc_dma_buffer(size);
} catch (Pci::Device::Quota_exceeded) {
if (i == 0) {
char buf[32];
Genode::snprintf(buf, sizeof(buf), "ram_quota=%zd",
size);
Genode::env()->parent()->upgrade(pci_drv.cap(),
buf);
}
}
}
return Ram_dataspace_capability();
}
Genode::Io_port_session_capability io_port(unsigned short bar) {
return _device.io_port(_device.phys_bar_to_virt(bar)); }
};
class Pci_tree
{
public:
class Not_found : public Exception { };
private:
int _current_dev_num;
Pci::Connection _pci_drv;
Avl_tree<Pci_device> _devices;
Lock _lock;
/* Lookup device for given BDF */
Pci_device *_lookup(unsigned short bdf)
{
if (!_devices.first())
throw Not_found();
Pci_device *d = _devices.first();
do {
if (bdf == d->bdf())
return d;
if (bdf < d->bdf())
d = d->child(Pci_device::LEFT);
else
d = d->child(Pci_device::RIGHT);
} while (d);
throw Not_found();
}
/** Find lowest BDF */
void _first_bdf(int *bus, int *dev, int *fun)
{
if (!_devices.first())
throw Not_found();
Pci_device *first, *prev, *root;
first = prev = root = _devices.first();
do {
first = prev;
prev = prev->next(root, Pci_device::LEFT);
} while (prev);
*bus = first->bus();
*dev = first->dev();
*fun = first->fun();
}
/** Find next BDF */
void _next_bdf(Pci_device *prev, int *bus, int *dev, int *fun)
{
if (!_devices.first())
throw Not_found();
Pci_device *next = prev->next(_devices.first(), Pci_device::RIGHT);
if (!next)
throw Not_found();
*bus = next->bus();
*dev = next->dev();
*fun = next->fun();
}
void _show_devices()
{
if (_devices.first())
_devices.first()->show();
}
public:
Pci_tree(unsigned device_class, unsigned class_mask);
uint32_t config_read(int bus, int dev, int fun, unsigned char address,
Pci::Device::Access_size size)
{
Lock::Guard lock_guard(_lock);
unsigned short bdf = Pci_device::knit_bdf(bus, dev, fun);
return _lookup(bdf)->config_read(address, size);
}
void config_write(int bus, int dev, int fun, unsigned char address,
uint32_t val, Pci::Device::Access_size size)
{
Lock::Guard lock_guard(_lock);
unsigned short bdf = Pci_device::knit_bdf(bus, dev, fun);
_lookup(bdf)->config_write(address, val, size);
}
/**
* Lookup first device
*/
void first_device(int *bus, int *dev, int *fun)
{
Lock::Guard lock_guard(_lock);
_first_bdf(bus, dev, fun);
}
/**
* Lookup next device
*/
void next_device(int *bus, int *dev, int *fun)
{
Lock::Guard lock_guard(_lock);
Pci_device *d = _lookup(Pci_device::knit_bdf(*bus, *dev, *fun));
_next_bdf(d, bus, dev, fun);
}
Ram_dataspace_capability alloc_dma_buffer(int bus, int dev,
int fun, size_t size)
{
Lock::Guard lock_guard(_lock);
unsigned short bdf = Pci_device::knit_bdf(bus, dev, fun);
return _lookup(bdf)->alloc_dma_buffer(_pci_drv, size);
}
Io_port_session_capability io_port(int bus, int dev, int fun, unsigned short bda)
{
Lock::Guard lock_guard(_lock);
unsigned short bdf = Pci_device::knit_bdf(bus, dev, fun);
return _lookup(bdf)->io_port(bda);
}
};
}
#endif /* _PCI_TREE_H_ */

View File

@ -1,194 +0,0 @@
/*
* \brief Virtual page-table facility
* \author Christian Helmuth
* \date 2008-08-15
*/
/*
* Copyright (C) 2008-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#include <base/stdint.h>
#include <base/env.h>
#include <base/sync_allocator.h>
#include <base/allocator_avl.h>
#include <base/printf.h>
extern "C" {
#include <dde_kit/pgtab.h>
}
using namespace Genode;
class Mem_region
{
private:
addr_t _base; /* region base address */
size_t _size; /* region size */
addr_t _mapped_base; /* base address in other address space */
public:
Mem_region() : _base(0), _size(0), _mapped_base(0) { }
Mem_region(addr_t base, size_t size, addr_t mapped_base)
: _base(base), _size(size), _mapped_base(mapped_base) { }
/***************
** Accessors **
***************/
addr_t base() const { return _base; }
size_t size() const { return _size; }
addr_t mapped_base() const { return _mapped_base; }
};
typedef Allocator_avl_tpl<Mem_region> Mem_region_allocator;
class Mem_map : public Synchronized_range_allocator<Mem_region_allocator>
{
public:
Mem_map()
: Synchronized_range_allocator<Mem_region_allocator>(env()->heap()) {
add_range(0, ~0); }
/***********************************
** Wrapped Allocator_avl methods **
***********************************/
/**
* Assign custom meta data to block at specified address
*/
void metadata(void *addr, Mem_region region)
{
Lock::Guard lock_guard(*lock());
raw()->metadata(addr, region);
}
/**
* Return meta data that was attached to block at specified address
*/
Mem_region * metadata(void *addr)
{
Lock::Guard lock_guard(*lock());
return raw()->metadata(addr);
}
};
static Mem_map * phys_to_virt_map()
{
static Mem_map _phys_to_virt_map;
return &_phys_to_virt_map;
}
static Mem_map * virt_to_phys_map()
{
static Mem_map _virt_to_phys_map;
return &_virt_to_phys_map;
}
extern "C" void dde_kit_pgtab_set_region(void *virt, dde_kit_addr_t phys, unsigned pages)
{
dde_kit_pgtab_set_region_with_size(virt, phys, pages << DDE_KIT_PAGE_SHIFT);
}
extern "C" void dde_kit_pgtab_set_region_with_size(void *virt, dde_kit_addr_t phys,
dde_kit_size_t size)
{
Mem_map *map;
Mem_region region;
/* add region to virtual memory map */
map = virt_to_phys_map();
region = Mem_region(reinterpret_cast<addr_t>(virt), size, phys);
if (map->alloc_addr(size, reinterpret_cast<addr_t>(virt)).is_ok())
map->metadata(virt, region);
else
PWRN("virt->phys mapping for [%lx,%lx) failed",
reinterpret_cast<addr_t>(virt), reinterpret_cast<addr_t>(virt) + size);
/* add region to physical memory map for reverse lookup */
map = phys_to_virt_map();
region = Mem_region(phys, size, reinterpret_cast<addr_t>(virt));
if (map->alloc_addr(size, phys).is_ok())
map->metadata(reinterpret_cast<void *>(phys), region);
else
PWRN("phys->virt mapping for [%lx,%lx) failed", phys, phys + size);
}
extern "C" void dde_kit_pgtab_clear_region(void *virt)
{
Mem_region *region =virt_to_phys_map()->metadata(virt);
if (!region) {
PWRN("no virt->phys mapping @ %p", virt);
return;
}
void *phys = reinterpret_cast<void *>(region->mapped_base());
/* remove region from both maps */
virt_to_phys_map()->free(virt);
phys_to_virt_map()->free(phys);
}
extern "C" dde_kit_addr_t dde_kit_pgtab_get_physaddr(void *virt)
{
addr_t phys;
Mem_region *region = virt_to_phys_map()->metadata(virt);
if (!region) {
PWRN("no virt->phys mapping @ %p", virt);
return 0;
}
phys = reinterpret_cast<addr_t>(virt) - region->base() + region->mapped_base();
return phys;
}
extern "C" dde_kit_addr_t dde_kit_pgtab_get_virtaddr(dde_kit_addr_t phys)
{
addr_t virt;
Mem_region *region = phys_to_virt_map()->metadata(reinterpret_cast<void *>(phys));
if (!region) {
PWRN("no phys->virt mapping @ %p", reinterpret_cast<void *>(phys));
return 0;
}
virt = phys - region->base() + region->mapped_base();
return virt;
}
extern "C" dde_kit_size_t dde_kit_pgtab_get_size(void *virt)
{
Mem_region *region =virt_to_phys_map()->metadata(virt);
if (!region) {
PWRN("no virt->phys mapping @ %p", virt);
return 0;
}
return region->size();
}

View File

@ -1,40 +0,0 @@
/*
* \brief Formatted output
* \author Christian Helmuth
* \date 2008-08-15
*/
/*
* Copyright (C) 2008-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#include <base/printf.h>
extern "C" {
#include <dde_kit/printf.h>
}
extern "C" void dde_kit_print(const char *msg)
{
Genode::printf("%s", msg);
}
extern "C" void dde_kit_printf(const char *fmt, ...)
{
va_list va;
va_start(va, fmt);
Genode::vprintf(fmt, va);
va_end(va);
}
extern "C" void dde_kit_vprintf(const char *fmt, va_list va)
{
Genode::vprintf(fmt, va);
}

View File

@ -1,344 +0,0 @@
/*
* \brief Hardware-resource access
* \author Christian Helmuth
* \date 2008-10-21
*/
/*
* Copyright (C) 2008-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#include <base/lock.h>
#include <base/stdint.h>
#include <util/avl_tree.h>
#include <io_port_session/connection.h>
#include <io_mem_session/connection.h>
#include <dataspace/client.h>
extern "C" {
#include <dde_kit/resources.h>
#include <dde_kit/pgtab.h>
}
#include "device.h"
using namespace Genode;
static const bool verbose = false;
class Range : public Avl_node<Range>
{
public:
class Not_found : public Exception { };
class Overlap : public Exception { };
class Resource_not_accessible : public Exception { };
private:
addr_t _base;
size_t _size;
public:
Range(addr_t base, size_t size) : _base(base), _size(size) { }
/** AVL node comparison */
bool higher(Range *range) {
return (_base + _size <= range->_base); }
/** AVL node lookup */
Range *lookup(addr_t addr, size_t size)
{
Range *r = this;
do {
if (addr >= r->_base) {
if (addr + size <= r->_base + r->_size)
return r;
else if (addr < r->_base + r->_size)
throw Overlap();
}
if (addr < r->_base)
r = r->child(LEFT);
else
r = r->child(RIGHT);
} while (r);
throw Not_found();
}
/**
* Log ranges of node and all children
*/
void log_ranges()
{
if (child(LEFT))
child(LEFT)->log_ranges();
PLOG(" [%08lx,%08lx)", _base, _base + _size);
if (child(RIGHT))
child(RIGHT)->log_ranges();
}
addr_t base() const { return _base; }
size_t size() const { return _size; }
};
template <typename TYPE>
class Range_database : Avl_tree<Range>
{
private:
Lock _lock;
void _log_ranges(const char *op, addr_t b, size_t s)
{
PLOG("Range_db %p: %s [%08lx,%08lx)", this, op, b, b + s);
if (!first())
PLOG(" <no ranges>");
else
first()->log_ranges();
}
public:
TYPE *lookup(addr_t addr, size_t size)
{
Lock::Guard lock_guard(_lock);
if (!first()) throw Range::Not_found();
return static_cast<TYPE *>(first()->lookup(addr, size));
}
void insert(Range *range)
{
Lock::Guard lock_guard(_lock);
Avl_tree<Range>::insert(range);
if (verbose)
_log_ranges("INSERT", range->base(), range->size());
}
void remove(Range *range)
{
Lock::Guard lock_guard(_lock);
Avl_tree<Range>::remove(range);
if (verbose)
_log_ranges("REMOVE", range->base(), range->size());
}
};
/***************
** I/O ports **
***************/
class Port_range;
static Range_database<Port_range> *ports()
{
static Range_database<Port_range> _ports;
return &_ports;
}
class Port_range : public Range, public Io_port_session_client
{
public:
Port_range(addr_t base, size_t size, Io_port_session_capability cap)
: Range(base, size), Io_port_session_client(cap) {
ports()->insert(this); }
~Port_range() { ports()->remove(this); }
};
extern "C" int dde_kit_request_io(dde_kit_addr_t addr, dde_kit_size_t size,
unsigned short bar, dde_kit_uint8_t bus,
dde_kit_uint8_t dev, dde_kit_uint8_t func)
{
try {
new (env()->heap()) Port_range(addr, size, Dde_kit::Device::io_port(bus, dev, func, bar));
return 0;
} catch (...) {
return -1;
}
}
extern "C" int dde_kit_release_io(dde_kit_addr_t addr, dde_kit_size_t size)
{
try {
destroy(env()->heap(), ports()->lookup(addr, size));
return 0;
} catch (...) {
return -1;
}
}
extern "C" unsigned char dde_kit_inb(dde_kit_addr_t port)
{
try {
return ports()->lookup(port, 1)->inb(port);
} catch (...) {
return 0;
}
}
extern "C" unsigned short dde_kit_inw(dde_kit_addr_t port)
{
try {
return ports()->lookup(port, 2)->inw(port);
} catch (...) {
return 0;
}
}
extern "C" unsigned long dde_kit_inl(dde_kit_addr_t port)
{
try {
return ports()->lookup(port, 4)->inl(port);
} catch (...) {
return 0;
}
}
extern "C" void dde_kit_outb(dde_kit_addr_t port, unsigned char val)
{
try {
ports()->lookup(port, 1)->outb(port, val);
} catch (...) { }
}
extern "C" void dde_kit_outw(dde_kit_addr_t port, unsigned short val)
{
try {
ports()->lookup(port, 2)->outw(port, val);
} catch (...) { }
}
extern "C" void dde_kit_outl(dde_kit_addr_t port, unsigned long val)
{
try {
ports()->lookup(port, 4)->outl(port, val);
} catch (...) { }
}
/******************
** MMIO regions **
******************/
class Mem_range;
static Range_database<Mem_range> *mem_db()
{
static Range_database<Mem_range> _mem_db;
return &_mem_db;
}
class Mem_range : public Range, public Io_mem_connection
{
private:
bool _wc;
Io_mem_dataspace_capability _ds;
addr_t _vaddr;
public:
Mem_range(addr_t base, size_t size, bool wc)
:
Range(base, size), Io_mem_connection(base, size, wc),
_wc(wc), _ds(dataspace())
{
if (!_ds.valid()) throw Resource_not_accessible();
_vaddr = env()->rm_session()->attach(_ds);
_vaddr |= base & 0xfff;
dde_kit_pgtab_set_region_with_size((void *)_vaddr, base, size);
mem_db()->insert(this);
}
~Mem_range()
{
mem_db()->remove(this);
dde_kit_pgtab_clear_region((void *)_vaddr);
}
addr_t vaddr() const { return _vaddr; }
bool wc() const { return _wc; }
};
extern "C" int dde_kit_request_mem(dde_kit_addr_t addr, dde_kit_size_t size,
int wc, dde_kit_addr_t *vaddr)
{
/*
* We check if a resource comprising the requested region was allocated
* before (with the same access type, i.e., wc flag) and then return the
* mapping address. In case of overlapping requests, there's nothing else
* for it but to return an error.
*/
try {
Mem_range *r = mem_db()->lookup(addr, size);
if (!!wc != r->wc()) {
PERR("I/O memory access type mismatch");
return -1;
}
*vaddr = r->vaddr() + (addr - r->base());
return 0;
} catch (Mem_range::Overlap) {
PERR("overlapping I/O memory region requested");
return -1;
} catch (Mem_range::Not_found) { }
/* request resource if no previous allocation was found */
try {
*vaddr = (new (env()->heap()) Mem_range(addr, size, !!wc))->vaddr();
return 0;
} catch (...) {
return -1;
}
}
extern "C" int dde_kit_release_mem(dde_kit_addr_t addr, dde_kit_size_t size)
{
try {
destroy(env()->heap(), mem_db()->lookup(addr, size));
return 0;
} catch (...) {
return -1;
}
}

View File

@ -1,66 +0,0 @@
/*
* \brief Semaphores
* \author Christian Helmuth
* \date 2008-09-15
*/
/*
* Copyright (C) 2008-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#include <base/env.h>
#include <base/printf.h>
#include <base/semaphore.h>
extern "C" {
#include <dde_kit/semaphore.h>
}
using namespace Genode;
struct dde_kit_sem : public Semaphore
{
public:
dde_kit_sem(int value) : Semaphore(value) { }
};
extern "C" void dde_kit_sem_down(dde_kit_sem_t *sem) {
sem->down(); }
extern "C" int dde_kit_sem_down_try(dde_kit_sem_t *sem)
{
PERR("not implemented - will potentially block");
sem->down();
/* success */
return 0;
}
extern "C" void dde_kit_sem_up(dde_kit_sem_t *sem) { sem->up(); }
extern "C" dde_kit_sem_t *dde_kit_sem_init(int value)
{
dde_kit_sem *s;
try {
s = new (env()->heap()) dde_kit_sem(value);
} catch (...) {
PERR("allocation failed (size=%zd)", sizeof(*s));
return 0;
}
return s;
}
extern "C" void dde_kit_sem_deinit(dde_kit_sem_t *sem) {
destroy(env()->heap(), sem); }

View File

@ -1,65 +0,0 @@
/*
* \brief Spin lock
* \author Norman Feske
* \date 2012-01-27
*/
/*
* Copyright (C) 2012-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#include <base/env.h>
#include <cpu/atomic.h>
#include <base/printf.h>
#include <spin_lock.h> /* included from 'base/src/base/lock/' */
extern "C" {
#include <dde_kit/spin_lock.h>
}
template <bool b> struct Static_assert { };
/* specialization for successful static assertion */
template <> struct Static_assert<true> { static void assert() { } };
extern "C" void dde_kit_spin_lock_init(dde_kit_spin_lock *spin_lock)
{
/*
* Check at compile time that the enum values defined for DDE Kit
* correspond to those defined in 'base/src/base/lock/spin_lock.h'.
*/
Static_assert<(int)DDE_KIT_SPIN_LOCK_LOCKED == (int)SPINLOCK_LOCKED >::assert();
Static_assert<(int)DDE_KIT_SPIN_LOCK_UNLOCKED == (int)SPINLOCK_UNLOCKED>::assert();
*spin_lock = SPINLOCK_UNLOCKED;
}
extern "C" void dde_kit_spin_lock_lock(dde_kit_spin_lock *spin_lock)
{
spinlock_lock(spin_lock);
}
extern "C" int dde_kit_spin_lock_try_lock(dde_kit_spin_lock *spin_lock)
{
PERR("not implemented - will potentially block");
spinlock_lock(spin_lock);
/* success */
return 0;
}
extern "C" void dde_kit_spin_lock_unlock(dde_kit_spin_lock *spin_lock)
{
spinlock_unlock(spin_lock);
}

View File

@ -1,308 +0,0 @@
/*
* \brief Thread facility
* \author Christian Helmuth
* \date 2008-10-20
*
*/
/*
* Copyright (C) 2008-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#include <base/env.h>
#include <base/sleep.h>
#include <base/lock.h>
#include <base/printf.h>
extern "C" {
#include <dde_kit/thread.h>
#include <dde_kit/timer.h>
}
#include "thread.h"
using namespace Genode;
/***********+**************
** Thread info database **
**************************/
class Thread_info_database : public Avl_tree<Dde_kit::Thread_info>
{
private:
Lock _lock;
public:
Dde_kit::Thread_info *lookup(Thread_base *thread_base)
{
Lock::Guard lock_guard(_lock);
if (!first()) throw Dde_kit::Thread_info::Not_found();
return first()->lookup(thread_base);
}
void insert(Dde_kit::Thread_info *info)
{
Lock::Guard lock_guard(_lock);
Avl_tree<Dde_kit::Thread_info>::insert(info);
}
void remove(Dde_kit::Thread_info *info)
{
Lock::Guard lock_guard(_lock);
Avl_tree<Dde_kit::Thread_info>::remove(info);
}
};
static Thread_info_database *threads()
{
static Thread_info_database _threads;
return &_threads;
}
/********************************
** Generic thread information **
********************************/
unsigned Dde_kit::Thread_info::_id_counter = 0x1000;
bool Dde_kit::Thread_info::higher(Thread_info *info)
{
return (info->_thread_base >= _thread_base);
}
Dde_kit::Thread_info *Dde_kit::Thread_info::lookup(Thread_base *thread_base)
{
Dde_kit::Thread_info *info = this;
do {
if (thread_base == info->_thread_base) return info;
if (thread_base < info->_thread_base)
info = info->child(LEFT);
else
info = info->child(RIGHT);
} while (info);
/* thread not in AVL tree */
throw Not_found();
}
Dde_kit::Thread_info::Thread_info(Thread_base *thread_base, const char *name)
: _thread_base(thread_base), _name(name), _id(_id_counter++)
{ }
Dde_kit::Thread_info::~Thread_info()
{ }
/********************
** DDE Kit thread **
********************/
static Dde_kit::Thread_info *adopt_thread(Thread_base *thread, const char *name)
{
Dde_kit::Thread_info *info = 0;
try {
info = new (env()->heap()) Dde_kit::Thread_info(thread, name);
threads()->insert(info);
} catch (...) {
PERR("thread adoption failed");
return 0;
}
return info;
}
struct dde_kit_thread : public Dde_kit::Thread_info
{
/**
* Dummy constructor
*
* This constructor is never executed because we only use pointers to
* 'dde_kit_thread'. Even though, this constructor is never used, gcc-3.4
* (e.g., used for OKL4v2) would report an error if it did not exist.
*/
dde_kit_thread() : Dde_kit::Thread_info(0, 0) { }
};
class _Thread : public Dde_kit::Thread
{
private:
void (*_thread_fn)(void *);
void *_thread_arg;
Dde_kit::Thread_info *_thread_info;
public:
_Thread(const char *name, void (*thread_fn)(void *), void *thread_arg)
:
Dde_kit::Thread(name),
_thread_fn(thread_fn), _thread_arg(thread_arg),
_thread_info(adopt_thread(this, name))
{ start(); }
void entry() { _thread_fn(_thread_arg); }
Dde_kit::Thread_info *thread_info() { return _thread_info; }
};
extern "C" struct dde_kit_thread *dde_kit_thread_create(void (*fun)(void *),
void *arg, const char *name)
{
_Thread *thread;
try {
thread = new (env()->heap()) _Thread(name, fun, arg);
} catch (...) {
PERR("thread creation failed");
return 0;
}
return static_cast<struct dde_kit_thread *>(thread->thread_info());
}
extern "C" struct dde_kit_thread *dde_kit_thread_adopt_myself(const char *name)
{
try {
return static_cast<dde_kit_thread *>(adopt_thread(Thread_base::myself(), name));
} catch (...) {
PERR("thread adoption failed");
return 0;
}
}
extern "C" struct dde_kit_thread *dde_kit_thread_myself()
{
try {
return static_cast<struct dde_kit_thread *>
(threads()->lookup(Thread_base::myself()));
} catch (...) {
return 0;
}
}
extern "C" void * dde_kit_thread_get_data(struct dde_kit_thread *thread) {
return static_cast<Dde_kit::Thread_info *>(thread)->data(); }
extern "C" void * dde_kit_thread_get_my_data(void)
{
try {
return (threads()->lookup(Thread_base::myself()))->data();
} catch (...) {
PERR("current thread not in database");
return 0;
}
}
extern "C" void dde_kit_thread_set_data(struct dde_kit_thread *thread, void *data) {
reinterpret_cast<Dde_kit::Thread_info *>(thread)->data(data); }
extern "C" void dde_kit_thread_set_my_data(void *data)
{
try {
(threads()->lookup(Thread_base::myself()))->data(data);
} catch (...) {
PERR("current thread not in database");
}
}
extern "C" void dde_kit_thread_exit(void)
{
PERR("not implemented yet");
sleep_forever();
}
extern "C" const char *dde_kit_thread_get_name(struct dde_kit_thread *thread) {
return reinterpret_cast<Dde_kit::Thread_info *>(thread)->name(); }
extern "C" int dde_kit_thread_get_id(struct dde_kit_thread *thread) {
return reinterpret_cast<Dde_kit::Thread_info *>(thread)->id(); }
extern "C" void dde_kit_thread_schedule(void)
{
/* FIXME */
}
/*********************
** Sleep interface **
*********************/
static void _wake_up_msleep(void *lock)
{
reinterpret_cast<Lock *>(lock)->unlock();
}
extern "C" void dde_kit_thread_msleep(unsigned long msecs)
{
/*
* This simple msleep() registers a timer that fires after 'msecs' and
* blocks on 'lock'. The registered timer handler just unlocks 'lock' and
* the sleeping thread unblocks.
*/
Lock *lock;
struct dde_kit_timer *timer;
unsigned long timeout = dde_kit_timer_ticks + (msecs * DDE_KIT_HZ) / 1000;
lock = new (env()->heap()) Lock(Lock::LOCKED);
timer = dde_kit_timer_add(_wake_up_msleep, lock, timeout);
lock->lock();
dde_kit_timer_del(timer);
destroy((env()->heap()), lock);
}
extern "C" void dde_kit_thread_usleep(unsigned long usecs)
{
unsigned long msecs = usecs / 1000;
if (msecs > 1)
dde_kit_thread_msleep(msecs);
else
dde_kit_thread_schedule();
}
extern "C" void dde_kit_thread_nsleep(unsigned long nsecs)
{
unsigned long msecs = nsecs / 1000000;
if (msecs > 1)
dde_kit_thread_msleep(msecs);
else
dde_kit_thread_schedule();
}

View File

@ -1,69 +0,0 @@
/*
* \brief Thread facility
* \author Christian Helmuth
* \date 2008-10-20
*/
/*
* Copyright (C) 2008-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#include <base/thread.h>
#include <util/avl_tree.h>
#ifndef _THREAD_H_
#define _THREAD_H_
namespace Dde_kit {
using namespace Genode;
typedef Genode::Thread<0x2000> Thread;
/*
* The thread information is splitted from the actual (runable) thread, so
* that information for adopted threads can be managed.
*/
class Thread_info : public Avl_node<Thread_info>
{
public:
class Not_found : public Exception { };
private:
Thread_base *_thread_base;
const char *_name;
unsigned _id;
void *_data;
static unsigned _id_counter;
public:
Thread_info(Thread_base *thread_base, const char *name);
~Thread_info();
/** AVL node comparison */
bool higher(Thread_info *info);
/** AVL node lookup */
Thread_info *lookup(Thread_base *thread_base);
/***************
** Accessors **
***************/
Thread_base *thread_base() { return _thread_base; }
const char *name() const { return _name; }
void name(const char *name) { _name = name; }
unsigned id() const { return _id; }
void *data() const { return _data; }
void data(void *data) { _data = data; }
};
}
#endif /* _THREAD_H_ */

View File

@ -1,214 +0,0 @@
/*
* \brief Timers and ticks
* \author Christian Helmuth
* \date 2008-10-22
*/
/*
* Copyright (C) 2008-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#include <util/list.h>
#include <os/alarm.h>
#include <timer_session/connection.h>
#include <base/printf.h>
extern "C" {
#include <dde_kit/timer.h>
}
#include "thread.h"
using namespace Genode;
/************************
** Timer tick symbols **
************************/
volatile unsigned long dde_kit_timer_ticks;
/***************************
** Timer thread and tick **
***************************/
class Timer_thread : Dde_kit::Thread, public Alarm_scheduler
{
private:
unsigned _period_in_ms;
void(*_init)(void *);
void *_priv;
Timer::Connection _timer;
List<dde_kit_timer> _destroy_list;
Lock _destroy_list_lock;
void _enqueue_destroy(dde_kit_timer *timer)
{
Lock::Guard lock_guard(_destroy_list_lock);
_destroy_list.insert(timer);
}
dde_kit_timer * _dequeue_next_destroy()
{
Lock::Guard lock_guard(_destroy_list_lock);
dde_kit_timer *timer = _destroy_list.first();
if (timer)
_destroy_list.remove(timer);
return timer;
}
public:
Timer_thread(unsigned hz, void(*init)(void *), void *priv)
: Dde_kit::Thread("timer"), _period_in_ms(1000/hz), _init(init), _priv(priv)
{
dde_kit_timer_ticks = 0;
start();
}
void entry()
{
dde_kit_thread_adopt_myself("timer");
/* call provided init function */
if (_init) _init(_priv);
/* timer tick loop */
while (true) {
dde_kit_timer *timer;
/*
* XXX This approach drifts with the execution time of handlers
* and timer destruction.
*/
_timer.msleep(_period_in_ms);
++dde_kit_timer_ticks;
/* execute all scheduled alarms */
Alarm_scheduler::handle(dde_kit_timer_ticks);
/* finish pending alarm object destruction */
while ((timer = _dequeue_next_destroy()))
destroy(env()->heap(), timer);
}
};
/**
* Schedule timer for destruction (garbage collection)
*
* \param timer timer fo destroy
*/
void destroy_timer(dde_kit_timer *timer)
{
_enqueue_destroy(timer);
}
};
static Timer_thread *_timer_thread;
/*************+******
** Timer facility **
********************/
class dde_kit_timer : public Alarm, public List<dde_kit_timer>::Element
{
private:
void (*_handler)(void *); /* handler function */
void *_priv; /* private handler token */
bool _pending; /* true if timer is pending */
protected:
bool on_alarm(unsigned) override
{
/* if timer is really pending, call registered handler function */
if (_pending) {
_pending = false;
_handler(_priv);
}
/* do not schedule again */
return false;
}
public:
dde_kit_timer(void (*handler)(void *), void *priv, unsigned long absolute_timeout)
: _handler(handler), _priv(priv), _pending(true) {
schedule(absolute_timeout); }
void schedule(unsigned long absolute_timeout)
{
_pending = true;
_timer_thread->schedule_absolute(this, absolute_timeout);
}
bool pending() const { return _pending; }
/**
* Schedule destruction of this timer on next tick
*
* Note: The timed event scheduler (alarm.h) does not allow to modify
* alarm objects in the on_alarm function. But, drivers do this
* frequently when modifying timer objects on timeout occurence.
*/
void destroy()
{
_pending = false;
_timer_thread->destroy_timer(this);
}
};
extern "C" struct dde_kit_timer *dde_kit_timer_add(void (*fn)(void *), void *priv,
unsigned long timeout)
{
try {
return new (env()->heap()) dde_kit_timer(fn, priv, timeout);
} catch (...) {
PERR("timer creation failed");
return 0;
}
}
extern "C" void dde_kit_timer_schedule_absolute(struct dde_kit_timer *timer, unsigned long timeout) {
timer->schedule(timeout); }
extern "C" void dde_kit_timer_del(struct dde_kit_timer *timer)
{
try {
timer->destroy();
} catch (...) { }
}
extern "C" int dde_kit_timer_pending(struct dde_kit_timer *timer) {
return timer->pending();
}
extern "C" void dde_kit_timer_init(void(*thread_init)(void *), void *priv)
{
try {
static Timer_thread t(DDE_KIT_HZ, thread_init, priv);
_timer_thread = &t;
} catch (...) {
PERR("Timer thread creation failed");
}
}

View File

@ -1,186 +0,0 @@
/*
* \brief Interface to i8042 controller
* \author Norman Feske
* \date 2007-09-21
*
* This is a simplified version for DDE kit test. The original resides in the
* os repository under src/drivers/input/ps2.
*/
/*
* Copyright (C) 2007-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _I8042_H_
#define _I8042_H_
#include <io_port_session/connection.h>
#include <base/env.h>
class I8042
{
enum Register
{
REG_DATA = 0x60,
REG_STATUS = 0x64,
REG_COMMAND = 0x64,
};
enum Flag
{
/* status register */
STAT_OBF = 0x01,
STAT_IBF = 0x02,
/* control register */
CTRL_KBD_INT = 0x01,
CTRL_AUX_INT = 0x02,
CTRL_XLATE = 0x40,
};
enum Command
{
CMD_READ = 0x20,
CMD_WRITE = 0x60,
CMD_TEST = 0xaa,
CMD_AUX_ENABLE = 0xa8,
CMD_AUX_TEST = 0xa9,
CMD_KBD_ENABLE = 0xae,
CMD_KBD_TEST = 0xab,
CMD_AUX_WRITE = 0xd4,
};
enum Return
{
RET_TEST_OK = 0x55,
RET_KBD_TEST_OK = 0x00,
RET_AUX_TEST_OK = 0x00,
};
private:
Genode::Io_port_connection _data_port; /* data port */
Genode::Io_port_connection _stat_port; /* status/command port */
/**
* Read controller status
*/
unsigned char _status() { return _stat_port.inb(REG_STATUS); }
/**
* Read data from controller
*/
unsigned char _data() { return _data_port.inb(REG_DATA); }
/**
* Issue command to controller
*/
void _command(unsigned char cmd)
{
while (_input_buffer_full());
_stat_port.outb(REG_STATUS, cmd);
}
/**
* Send data to controller
*/
void _data(unsigned char value)
{
while (_input_buffer_full());
_data_port.outb(REG_DATA, value);
}
/**
* Convenience functions for accessing the controller status
*/
bool _output_buffer_full() { return _status() & STAT_OBF; }
bool _input_buffer_full() { return _status() & STAT_IBF; }
/**
* Wait for data and read
*/
unsigned char _wait_data()
{
while (!_output_buffer_full());
return _data();
}
public:
/**
* Constructor
*/
I8042() : _data_port(REG_DATA, 1), _stat_port(REG_STATUS, 1) { reset(); }
/**
* Test and initialize controller
*/
void reset()
{
int ret = 0;
/* read remaining data in controller */
while (_output_buffer_full()) _data();
/* run self tests */
_command(CMD_TEST);
if ((ret = _wait_data()) != RET_TEST_OK) {
Genode::printf("i8042: self test failed (%x)\n", ret);
return;
}
_command(CMD_KBD_TEST);
if ((ret = _wait_data()) != RET_KBD_TEST_OK) {
Genode::printf("i8042: kbd test failed (%x)\n", ret);
return;
}
_command(CMD_AUX_TEST);
if ((ret = _wait_data()) != RET_AUX_TEST_OK) {
Genode::printf("i8042: aux test failed (%x)\n", ret);
return;
}
/* enable keyboard and mouse */
_command(CMD_READ);
ret = _wait_data();
ret &= ~CTRL_XLATE;
ret |= CTRL_KBD_INT | CTRL_AUX_INT;
_command(CMD_WRITE);
_data(ret);
_command(CMD_KBD_ENABLE);
_command(CMD_AUX_ENABLE);
/* initialize keyboard */
_data(0xf0);
if (_data() != 0xfa) {
PWRN("Scan code setting not supported");
} else {
_data(2);
if (_data() != 0xfa)
PWRN("Scan code 2 not supported");
}
/* initialize mouse */
_command(CMD_AUX_WRITE);
_data(0xf6);
if (_data() != 0xfa)
PWRN("Could not set defaults");
_command(CMD_AUX_WRITE);
_data(0xf4);
if (_data() != 0xfa)
PWRN("Could not enable stream");
}
/**
* Flush data from controller
*/
void flush() { while (_output_buffer_full()) _data(); }
};
#endif

View File

@ -1,3 +0,0 @@
TARGET = test-dde_kit
SRC_CC = test.cc
LIBS = dde_kit

View File

@ -1,643 +0,0 @@
/*
* \brief DDE kit test program
* \author Christian Helmuth
* \date 2008-08-15
*/
/*
* Copyright (C) 2008-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#include <base/env.h>
#include <base/printf.h>
#include <base/lock.h>
#include <base/semaphore.h>
#include <timer_session/connection.h>
extern "C" {
#include <dde_kit/dde_kit.h>
#include <dde_kit/lock.h>
#include <dde_kit/semaphore.h>
#include <dde_kit/printf.h>
#include <dde_kit/interrupt.h>
#include <dde_kit/initcall.h>
#include <dde_kit/pgtab.h>
#include <dde_kit/memory.h>
#include <dde_kit/thread.h>
#include <dde_kit/pci.h>
#include <dde_kit/resources.h>
#include <dde_kit/timer.h>
#include <dde_kit/panic.h>
}
/* we directly map 'jiffies' to 'dde_kit_timer_ticks' */
#define jiffies dde_kit_timer_ticks
static Timer::Session_client *timer = 0;
static void test_locks()
{
PDBG("=== starting lock test ===");
struct dde_kit_lock *locks[10];
PDBG("avail() w/o locks: %zd", Genode::env()->ram_session()->avail());
for (unsigned i = 0; i < sizeof(locks)/sizeof(*locks); ++i) {
dde_kit_lock_init(&locks[i]);
dde_kit_lock_lock(locks[i]);
}
PDBG("avail() w/ locks: %zd", Genode::env()->ram_session()->avail());
for (unsigned i = 0; i < sizeof(locks)/sizeof(*locks); ++i) {
dde_kit_lock_unlock(locks[i]);
dde_kit_lock_deinit(locks[i]);
}
PDBG("avail() w/o locks: %zd", Genode::env()->ram_session()->avail());
for (unsigned i = 0; i < sizeof(locks)/sizeof(*locks); ++i) {
dde_kit_lock_init(&locks[i]);
dde_kit_lock_lock(locks[i]);
}
PDBG("avail() w/ locks: %zd", Genode::env()->ram_session()->avail());
for (unsigned i = 0; i < sizeof(locks)/sizeof(*locks); ++i) {
dde_kit_lock_unlock(locks[i]);
dde_kit_lock_deinit(locks[i]);
}
PDBG("avail() w/o locks: %zd", Genode::env()->ram_session()->avail());
PDBG("=== finished lock test ===");
}
static void test_semaphores()
{
PDBG("=== starting semaphore test ===");
dde_kit_sem_t *sem[10];
PDBG("avail() w/o semaphores: %zd", Genode::env()->ram_session()->avail());
for (unsigned i = 0; i < sizeof(sem)/sizeof(*sem); ++i) {
sem[i] = dde_kit_sem_init(1);
dde_kit_sem_down(sem[i]);
}
PDBG("avail() w/ semaphores: %zd", Genode::env()->ram_session()->avail());
for (unsigned i = 0; i < sizeof(sem)/sizeof(*sem); ++i) {
dde_kit_sem_up(sem[i]);
dde_kit_sem_deinit(sem[i]);
}
PDBG("avail() w/o semaphores: %zd", Genode::env()->ram_session()->avail());
for (unsigned i = 0; i < sizeof(sem)/sizeof(*sem); ++i) {
sem[i] = dde_kit_sem_init(4);
dde_kit_sem_down(sem[i]);
dde_kit_sem_down(sem[i]);
dde_kit_sem_down(sem[i]);
dde_kit_sem_down(sem[i]);
}
PDBG("avail() w/ semaphores: %zd", Genode::env()->ram_session()->avail());
for (unsigned i = 0; i < sizeof(sem)/sizeof(*sem); ++i) {
dde_kit_sem_up(sem[i]);
dde_kit_sem_deinit(sem[i]);
}
PDBG("avail() w/o semaphores: %zd", Genode::env()->ram_session()->avail());
PDBG("=== finished semaphore test ===");
}
static void test_printf()
{
PDBG("=== starting printf test ===");
dde_kit_print("This is a log message.\n");
dde_kit_print("This is another log message.\n");
dde_kit_printf("The quick brown fox jumps over the lazy dog.\n");
dde_kit_printf("The quick brown fox jumps over %s lazy dogs. ", "three");
dde_kit_printf("The quick brown fox jumps over %s lazy dog.\n", "a huge");
PDBG("=== finished printf test ===");
}
#include "i8042.h"
static I8042 *i8042;
static void test_interrupt_init(void *priv)
{
static unsigned cnt = 0;
PDBG("%d: %s", cnt, (const char *) priv);
++cnt;
}
static void test_interrupt_handler(void *priv)
{
static unsigned cnt = 0;
PDBG("%d: %s", cnt, (const char *) priv);
++cnt;
i8042->flush();
}
static void test_interrupt()
{
PDBG("=== starting interrupt test ===");
PDBG("Please use keyboard or mouse to trigger interrupt handling!");
i8042 = new (Genode::env()->heap()) I8042();
int err0, err1;
err0 = dde_kit_interrupt_attach(1, 0, test_interrupt_init,
test_interrupt_handler, (void *)"kbd");
err1 = dde_kit_interrupt_attach(12, 0, test_interrupt_init,
test_interrupt_handler, (void *)"aux");
enum { DURATION = 2000 };
if (!err0 && !err1) {
dde_kit_interrupt_disable(12);
PDBG("IRQ12 disabled");
timer->msleep(DURATION);
dde_kit_interrupt_disable(1);
PDBG("IRQ1 disabled");
timer->msleep(DURATION);
dde_kit_interrupt_enable(12);
i8042->reset();
PDBG("IRQ12 enabled");
timer->msleep(DURATION);
dde_kit_interrupt_enable(1);
i8042->reset();
PDBG("IRQ1 enabled");
timer->msleep(DURATION);
} else
PERR("interrupt attach failed");
if (!err0) dde_kit_interrupt_detach(1);
if (!err1) dde_kit_interrupt_detach(12);
destroy(Genode::env()->heap(), i8042);
PDBG("=== finished interrupt test ===");
}
static int test_initcall_fn()
{
PDBG("called");
return 0;
}
DDE_KIT_INITCALL(test_initcall_fn,noid);
DDE_KIT_INITCALL(test_initcall_fn,id);
static void test_initcall()
{
PDBG("=== starting initcall test ===");
dde_kit_initcall_id_test_initcall_fn();
dde_kit_initcall_noid_test_initcall_fn();
PDBG("=== finished initcall test ===");
}
static void test_pgtab()
{
PDBG("=== starting pgtab test ===");
dde_kit_addr_t virt, phys; dde_kit_size_t size;
virt = phys = 0;
PDBG("phys(%lx) => %lx", virt, dde_kit_pgtab_get_physaddr((void *)virt));
PDBG("virt(%lx) => %lx", phys, dde_kit_pgtab_get_virtaddr(phys));
PDBG("size(%lx) => %zx", virt, dde_kit_pgtab_get_size((void *)virt));
virt = 0x40000000; phys = 0x20000000; size = 0x10000000;
dde_kit_pgtab_set_region((void *)virt, phys, size >> DDE_KIT_PAGE_SHIFT);
PDBG("virt [%lx,%lx) => phys [%lx,%lx)", virt, virt + size, phys, phys + size);
virt = 0x80000000; phys = 0x80000000; size = 0x10000000;
dde_kit_pgtab_set_region_with_size((void *)virt, phys, size);
PDBG("virt [%lx,%lx) => phys [%lx,%lx)", virt, virt + size, phys, phys + size);
virt = 0x40000000; phys = 0x20000000;
PDBG("phys(%lx) => %lx", virt, dde_kit_pgtab_get_physaddr((void *)virt));
PDBG("virt(%lx) => %lx", phys, dde_kit_pgtab_get_virtaddr(phys));
PDBG("size(%lx) => %zx", virt, dde_kit_pgtab_get_size((void *)virt));
virt = phys = 0x80000000;
PDBG("phys(%lx) => %lx", virt, dde_kit_pgtab_get_physaddr((void *)virt));
PDBG("virt(%lx) => %lx", phys, dde_kit_pgtab_get_virtaddr(phys));
PDBG("size(%lx) => %zx", virt, dde_kit_pgtab_get_size((void *)virt));
virt = 0x40000000;
dde_kit_pgtab_clear_region((void *)virt);
virt = 0x40000000; phys = 0x20000000;
PDBG("phys(%lx) => %lx", virt, dde_kit_pgtab_get_physaddr((void *)virt));
PDBG("virt(%lx) => %lx", phys, dde_kit_pgtab_get_virtaddr(phys));
PDBG("size(%lx) => %zx", virt, dde_kit_pgtab_get_size((void *)virt));
virt = phys = 0x80000000;
PDBG("phys(%lx) => %lx", virt, dde_kit_pgtab_get_physaddr((void *)virt));
PDBG("virt(%lx) => %lx", phys, dde_kit_pgtab_get_virtaddr(phys));
PDBG("size(%lx) => %zx", virt, dde_kit_pgtab_get_size((void *)virt));
virt = 0x80000000;
dde_kit_pgtab_clear_region((void *)virt);
virt = 0x40000000; phys = 0x20000000;
PDBG("phys(%lx) => %lx", virt, dde_kit_pgtab_get_physaddr((void *)virt));
PDBG("virt(%lx) => %lx", phys, dde_kit_pgtab_get_virtaddr(phys));
PDBG("size(%lx) => %zx", virt, dde_kit_pgtab_get_size((void *)virt));
virt = phys = 0x80000000;
PDBG("phys(%lx) => %lx", virt, dde_kit_pgtab_get_physaddr((void *)virt));
PDBG("virt(%lx) => %lx", phys, dde_kit_pgtab_get_virtaddr(phys));
PDBG("size(%lx) => %zx", virt, dde_kit_pgtab_get_size((void *)virt));
PDBG("=== finished pgtab test ===");
}
static void test_memory()
{
PDBG("=== starting memory test ===");
void *b0, *b1; dde_kit_size_t size;
PDBG("--- large-block memory allocator ---");
b0 = 0; size = 0x1000;
b0 = dde_kit_large_malloc(size);
PDBG("phys(%p) => %lx", b0, dde_kit_pgtab_get_physaddr(b0));
PDBG("size(%p) => %zx", b0, dde_kit_pgtab_get_size(b0));
dde_kit_large_free(b0);
/* must fail */
PDBG("phys(%p) => %lx", b0, dde_kit_pgtab_get_physaddr(b0));
b0 = 0; size = 0x3fff;
b0 = dde_kit_large_malloc(size);
b1 = 0; size = 0x4000;
b1 = dde_kit_large_malloc(size);
PDBG("phys(%p) => %lx", b0, dde_kit_pgtab_get_physaddr(b0));
PDBG("size(%p) => %zx", b0, dde_kit_pgtab_get_size(b0));
PDBG("phys(%p) => %lx", b1, dde_kit_pgtab_get_physaddr(b1));
PDBG("size(%p) => %zx", b1, dde_kit_pgtab_get_size(b1));
dde_kit_large_free(b0);
dde_kit_large_free(b1);
PDBG("--- simple memory allocator ---");
b0 = 0; size = 32;
b0 = dde_kit_simple_malloc(size);
b1 = 0; size = 64;
b1 = dde_kit_simple_malloc(size);
/* must fail */
PDBG("phys(%p) => %lx", b0, dde_kit_pgtab_get_physaddr(b0));
dde_kit_simple_free(b0);
dde_kit_simple_free(b1);
PDBG("--- slab allocator ---");
struct dde_kit_slab *cache;
enum { num_ptr = 100 };
void *ptr[num_ptr];
Genode::size_t sizes[4] = { 404, 36, 2004, 50 };
for (unsigned j = 0; j < sizeof(sizes) / sizeof(*sizes); ++j) {
PDBG("size = %zd", sizes[j]);
PDBG("avail() w/o slab cache: %zd", Genode::env()->ram_session()->avail());
cache = dde_kit_slab_init(sizes[j]);
PDBG("avail() w/ slab cache: %zd", Genode::env()->ram_session()->avail());
dde_kit_slab_set_data(cache, &cache);
for (unsigned i = 0; i < num_ptr; ++i) ptr[i] = dde_kit_slab_alloc(cache);
PDBG(" slab50 phys(%p) => %lx", ptr[50], dde_kit_pgtab_get_physaddr(ptr[50]));
PDBG(" slab50 size(%p) => %zx", ptr[50], dde_kit_pgtab_get_size(ptr[50]));
PDBG("avail() w/ slab alloc: %zd", Genode::env()->ram_session()->avail());
for (unsigned i = 0; i < num_ptr; ++i) dde_kit_slab_free(cache, ptr[i]);
/* could fail */
PDBG(" slab50 phys(%p) => %lx", ptr[50], dde_kit_pgtab_get_physaddr(ptr[50]));
PDBG(" slab50 size(%p) => %zx", ptr[50], dde_kit_pgtab_get_size(ptr[50]));
if (dde_kit_slab_get_data(cache) != &cache)
PERR("slab cache data pointer corrupt");
else
dde_kit_slab_destroy(cache);
PDBG("avail() w/o slab cache: %zd", Genode::env()->ram_session()->avail());
/* must fail */
PDBG(" slab50 phys(%p) => %lx", ptr[50], dde_kit_pgtab_get_physaddr(ptr[50]));
PDBG(" slab50 size(%p) => %zx", ptr[50], dde_kit_pgtab_get_size(ptr[50]));
}
PDBG("=== finished memory test ===");
}
static Genode::Semaphore *ready;
static void test_thread_fn(void *p)
{
Genode::Lock *lock = (Genode::Lock *)p;
for (unsigned i = 0; i < 3; ++i) {
lock->lock();
PDBG("Here I am arg=%p name=\"%s\" id=%x data=%p",
lock,
dde_kit_thread_get_name(dde_kit_thread_myself()),
dde_kit_thread_get_id(dde_kit_thread_myself()),
dde_kit_thread_get_my_data());
dde_kit_thread_schedule();
switch (i) {
case 0:
dde_kit_thread_msleep((unsigned long)dde_kit_thread_get_my_data() / 10);
break;
case 1:
dde_kit_thread_usleep((unsigned long)dde_kit_thread_get_my_data() * 100);
break;
case 2:
dde_kit_thread_nsleep((unsigned long)dde_kit_thread_get_my_data() * 100000);
break;
}
dde_kit_thread_set_my_data((void *) 0);
ready->up();
}
lock->lock();
dde_kit_thread_exit();
}
static void test_thread()
{
static Genode::Lock lock1(Genode::Lock::LOCKED);
static Genode::Lock lock2(Genode::Lock::LOCKED);
static Genode::Lock lock3(Genode::Lock::LOCKED);
static Genode::Semaphore _ready; ready = &_ready;
struct dde_kit_thread *t[3];
PDBG("=== starting thread test ===");
/* we need timing for msleep() */
dde_kit_timer_init(0, 0);
t[0] = dde_kit_thread_create(test_thread_fn, &lock1, "eins");
t[1] = dde_kit_thread_create(test_thread_fn, &lock2, "zwei");
t[2] = dde_kit_thread_create(test_thread_fn, &lock3, "drei");
dde_kit_thread_set_data(t[0], (void *)0x1000);
dde_kit_thread_set_data(t[1], (void *)0x2000);
dde_kit_thread_set_data(t[2], (void *)0x3000);
lock1.unlock(); lock2.unlock(); lock3.unlock();
_ready.down(); _ready.down(); _ready.down();
PDBG("t[0]->data = %p", dde_kit_thread_get_data(t[0]));
PDBG("t[1]->data = %p", dde_kit_thread_get_data(t[1]));
PDBG("t[2]->data = %p", dde_kit_thread_get_data(t[2]));
dde_kit_thread_set_data(t[0], (void *)0x1001);
dde_kit_thread_set_data(t[1], (void *)0x2001);
dde_kit_thread_set_data(t[2], (void *)0x3001);
lock1.unlock(); lock2.unlock(); lock3.unlock();
_ready.down(); _ready.down(); _ready.down();
PDBG("t[0]->data = %p", dde_kit_thread_get_data(t[0]));
PDBG("t[1]->data = %p", dde_kit_thread_get_data(t[1]));
PDBG("t[2]->data = %p", dde_kit_thread_get_data(t[2]));
dde_kit_thread_set_data(t[0], (void *)0x1002);
dde_kit_thread_set_data(t[1], (void *)0x2002);
dde_kit_thread_set_data(t[2], (void *)0x3002);
lock1.unlock(); lock2.unlock(); lock3.unlock();
_ready.down(); _ready.down(); _ready.down();
PDBG("t[0]->data = %p", dde_kit_thread_get_data(t[0]));
PDBG("t[1]->data = %p", dde_kit_thread_get_data(t[1]));
PDBG("t[2]->data = %p", dde_kit_thread_get_data(t[2]));
lock1.unlock(); lock2.unlock(); lock3.unlock();
struct dde_kit_thread *me = dde_kit_thread_adopt_myself("main");
dde_kit_thread_set_my_data((void *) 0xf000);
PDBG("me->data = %p", dde_kit_thread_get_my_data());
dde_kit_thread_set_data(me, (void *) 0xf001);
PDBG("me->data = %p", dde_kit_thread_get_data(me));
PDBG("=== finished thread test ===");
}
static void test_pci()
{
PDBG("=== starting PCI test ===");
dde_kit_pci_init(0, 0);
enum { BUS_MAX = 4, DEV_MAX = 8 };
PDBG("direct access to bus 0-%d devices 0-%d function 0", BUS_MAX, DEV_MAX);
for (unsigned b = 0; b < BUS_MAX; ++b)
for (unsigned d = 0; d < DEV_MAX; ++d) {
unsigned v;
dde_kit_pci_readl(b, d, 0, 0, &v);
PDBG(" PCI %02x:%02x.0: %08x", b, d, v);
}
PDBG("iterating PCI bus hierarchy with convenience functions");
int bus = 0, dev = 0, fun = 0;
for (int ret = dde_kit_pci_first_device(&bus, &dev, &fun);
ret == 0;
ret = dde_kit_pci_next_device(&bus, &dev, &fun))
PDBG(" Found PCI %02x:%02x.%x", bus, dev, fun);
PDBG("=== finished PCI test ===");
}
static void test_resources()
{
PDBG("=== starting resource test ===");
dde_kit_addr_t addr, a; dde_kit_size_t size, s; int wc;
dde_kit_addr_t vaddr; int ret;
/* should succeed */
addr = 0xf0000000; size = 0x01000000; wc = 1;
ret = dde_kit_request_mem(addr, size, wc, &vaddr);
PDBG("mreq [%04lx,%04lx) => %d @ %p (pgtab %p)", addr, addr + size, ret, (void *)vaddr,
(void *)dde_kit_pgtab_get_physaddr((void *)vaddr));
/* rerequest resource */
ret = dde_kit_request_mem(addr, size, wc, &vaddr);
PDBG("mreq [%04lx,%04lx) => %d @ %p (pgtab %p)", addr, addr + size, ret, (void *)vaddr,
(void *)dde_kit_pgtab_get_physaddr((void *)vaddr));
/* rerequest part of resource */
a = addr + 0x2000; s = size - 0x2000;
ret = dde_kit_request_mem(a, s, wc, &vaddr);
PDBG("mreq [%04lx,%04lx) => %d @ %p", a, a + s, ret, (void *)vaddr);
/* rerequest resource with different access type which fails */
a = addr + 0x2000; s = size - 0x2000;
ret = dde_kit_request_mem(a, s, !wc, &vaddr);
PDBG("mreq [%04lx,%04lx) => %d @ %p", a, a + s, ret, (void *)vaddr);
/* request resource overlapping existing which fails */
a = addr + size / 2; s = size;
ret = dde_kit_request_mem(a, s, wc, &vaddr);
PDBG("mreq [%04lx,%04lx) => %d @ %p", a, a + s, ret, (void *)vaddr);
/* release resource */
ret = dde_kit_release_mem(addr, size);
PDBG("mrel [%04lx,%04lx) => %d (pgtab %p)", addr, addr + size, ret,
(void *)dde_kit_pgtab_get_physaddr((void *)vaddr));
/* should fail */
addr = 0x1000; size = 0x1000; wc = 0;
ret = dde_kit_request_mem(addr, size, wc, &vaddr);
PDBG("mreq [%04lx,%04lx) => %d @ %p", addr, addr + size, ret, (void *)vaddr);
PDBG("mrel [%04lx,%04lx) => %d", addr, addr + size, dde_kit_release_mem(addr, size));
PDBG("=== finished resource test ===");
}
static void test_timer_fn(void *id)
{
PDBG("timer %ld fired at %ld", (long) id, jiffies);
}
static void test_timer()
{
PDBG("=== starting timer tick test ===");
dde_kit_timer_init(0, 0);
PDBG("--- tick ---");
PDBG("timer tick: %ld (%ld)", jiffies, dde_kit_timer_ticks);
timer->msleep(2000);
PDBG("timer tick: %ld (%ld)", jiffies, dde_kit_timer_ticks);
PDBG("--- simple timer ---");
dde_kit_timer_add(test_timer_fn, (void *)1, jiffies + 2 * DDE_KIT_HZ);
dde_kit_timer_add(test_timer_fn, (void *)2, jiffies + 4 * DDE_KIT_HZ);
dde_kit_timer *t = dde_kit_timer_add(test_timer_fn, (void *)3,
jiffies + 6 * DDE_KIT_HZ);
timer->msleep(5000);
dde_kit_timer_del(t);
PDBG("timer tick: %ld (%ld)", jiffies, dde_kit_timer_ticks);
timer->msleep(2000);
PDBG("--- stress test ---");
dde_kit_timer *timers[512];
for (unsigned long i = 0; i < sizeof(timers)/sizeof(*timers); ++i)
timers[i] = dde_kit_timer_add(test_timer_fn, (void *)i, jiffies + (i % 128) * (DDE_KIT_HZ / 100));
PDBG("created %zd timers", sizeof(timers)/sizeof(*timers));
timer->msleep(500);
for (unsigned i = 0; i < sizeof(timers)/sizeof(*timers); ++i)
dde_kit_timer_del(timers[i]);
PDBG("deleted %zd timers", sizeof(timers)/sizeof(*timers));
timer->msleep(2000);
PDBG("=== finished timer tick test ===");
}
static void test_panic()
{
PDBG("=== starting panic test ===");
if (1)
dde_kit_panic("Don't panic, it's just a test.");
else
dde_kit_debug("Don't panic, it's just a test.");
PDBG("=== finished panic test ===");
}
int main(int argc, char **argv)
{
PDBG("test-dde_kit started...");
timer = new (Genode::env()->heap()) Timer::Connection();
if (0) test_locks();
if (0) test_semaphores();
if (0) test_printf();
if (0) test_interrupt();
if (0) test_initcall();
if (0) test_pgtab();
if (0) test_memory();
if (0) test_thread();
if (1) test_pci();
if (0) test_resources();
if (0) test_timer();
if (1) test_panic();
return 0;
}

View File

@ -1,9 +0,0 @@
#!/bin/sh
#
# usage: dde_kit_adapt_sources <list of source files>
#
sed -i "s#l4/dde/ddekit#dde_kit#" "$@"
sed -i "s#l4/dde/linux26#dde_linux26#" "$@"
sed -i "s/ddekit/dde_kit/g" "$@"
sed -i "s/DDEKIT/DDE_KIT/g" "$@"

View File

@ -1,24 +0,0 @@
#!/bin/sh
#
# usage: dde_kit_find_initcalls <list of object files>
#
tempfile="/tmp/dde_kit-$(date +%s)"
nm -C "$@" | grep "dde_kit_initcall_" > $tempfile
sed -i "s/^.* \(dde_kit_initcall_.*\)/\1/" $tempfile
echo "/*"
echo " * Automatically generated by \"os/tool/dde_kit_find_initcalls $@\"."
echo " */"
cat $tempfile | sed "s/\(.*\)/extern int (*\1)(void);/" | sort | uniq
echo
echo "void do_initcalls(void)"
echo "{"
cat $tempfile | sed "s/\(.*\)/ \1();/" | sort | uniq
echo "}"
echo "/*"
echo " * End of automatically generated code."
echo " */"
rm $tempfile