mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-19 05:37:54 +00:00
parent
e1be0b3f67
commit
52110b9d89
@ -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.
|
||||
|
@ -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_ */
|
@ -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_ */
|
@ -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_ */
|
@ -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_ */
|
@ -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_ */
|
@ -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_ */
|
@ -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_ */
|
@ -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_ */
|
@ -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_ */
|
@ -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_ */
|
@ -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_ */
|
@ -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_ */
|
@ -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_ */
|
@ -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_ */
|
@ -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_ */
|
@ -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_ */
|
@ -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
|
@ -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)
|
||||
{
|
||||
}
|
@ -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);
|
||||
};
|
@ -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();
|
||||
}
|
@ -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();
|
||||
}
|
@ -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);
|
||||
}
|
@ -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");
|
||||
}
|
@ -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");
|
||||
}
|
||||
}
|
@ -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();
|
||||
|
||||
}
|
@ -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_ */
|
@ -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();
|
||||
}
|
@ -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);
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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); }
|
@ -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);
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
@ -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_ */
|
@ -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");
|
||||
}
|
||||
}
|
@ -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
|
@ -1,3 +0,0 @@
|
||||
TARGET = test-dde_kit
|
||||
SRC_CC = test.cc
|
||||
LIBS = dde_kit
|
@ -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;
|
||||
}
|
@ -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" "$@"
|
@ -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
|
Loading…
Reference in New Issue
Block a user