Subversion Repositories HelenOS

Compare Revisions

No changes between revisions

Ignore whitespace Rev 4536 → Rev 4537

/branches/dd/kernel/test/avltree/avltree1.c
194,7 → 194,7
return node;
}
 
static void test_tree_insert(avltree_t *tree, count_t node_count)
static void test_tree_insert(avltree_t *tree, size_t node_count)
{
unsigned int i;
avltree_node_t *newnode;
201,7 → 201,7
avltree_create(tree);
TPRINTF("Inserting %" PRIc " nodes...", node_count);
TPRINTF("Inserting %" PRIs " nodes...", node_count);
for (i = 0; i < node_count; i++) {
newnode = alloc_avltree_node();
214,7 → 214,7
TPRINTF("done.\n");
}
 
static void test_tree_delete(avltree_t *tree, count_t node_count,
static void test_tree_delete(avltree_t *tree, size_t node_count,
int node_position)
{
avltree_node_t *delnode;
245,7 → 245,7
TPRINTF("done.\n");
}
 
static void test_tree_delmin(avltree_t *tree, count_t node_count)
static void test_tree_delmin(avltree_t *tree, size_t node_count)
{
unsigned int i = 0;
/branches/dd/kernel/test/synch/rwlock4.c
148,7 → 148,7
thread_t *thrd;
context_save(&ctx);
TPRINTF("sp=%#x, readers_in=%" PRIc "\n", ctx.sp, rwlock.readers_in);
TPRINTF("sp=%#x, readers_in=%" PRIs "\n", ctx.sp, rwlock.readers_in);
TPRINTF("Creating %" PRIu32 " readers\n", rd);
for (i = 0; i < rd; i++) {
/branches/dd/kernel/test/mm/falloc2.c
52,7 → 52,7
{
int order, run, allocated, i;
uint8_t val = THREAD->tid % THREADS;
index_t k;
size_t k;
void **frames = (void **) malloc(MAX_FRAMES * sizeof(void *), FRAME_ATOMIC);
if (frames == NULL) {
82,9 → 82,9
TPRINTF("Thread #%" PRIu64 " (cpu%u): Deallocating ... \n", THREAD->tid, CPU->id);
for (i = 0; i < allocated; i++) {
for (k = 0; k <= (((index_t) FRAME_SIZE << order) - 1); k++) {
for (k = 0; k <= (((size_t) FRAME_SIZE << order) - 1); k++) {
if (((uint8_t *) frames[i])[k] != val) {
TPRINTF("Thread #%" PRIu64 " (cpu%u): Unexpected data (%c) in block %p offset %#" PRIi "\n", THREAD->tid, CPU->id, ((char *) frames[i])[k], frames[i], k);
TPRINTF("Thread #%" PRIu64 " (cpu%u): Unexpected data (%c) in block %p offset %#" PRIs "\n", THREAD->tid, CPU->id, ((char *) frames[i])[k], frames[i], k);
atomic_inc(&thread_fail);
goto cleanup;
}
/branches/dd/kernel/test/mm/purge1.c
37,7 → 37,7
#include <debug.h>
 
extern void tlb_invalidate_all(void);
extern void tlb_invalidate_pages(asid_t asid, uintptr_t va, count_t cnt);
extern void tlb_invalidate_pages(asid_t asid, uintptr_t va, size_t cnt);
 
char *test_purge1(void)
{
/branches/dd/kernel/genarch/src/mm/asid.c
65,7 → 65,7
#include <adt/list.h>
#include <debug.h>
 
static count_t asids_allocated = 0;
static size_t asids_allocated = 0;
 
/** Allocate free address space identifier.
*
120,7 → 120,7
* of TLB entries (e.g. TSB on sparc64), the
* cache must be invalidated as well.
*/
as_invalidate_translation_cache(as, 0, (count_t) -1);
as_invalidate_translation_cache(as, 0, (size_t) -1);
/*
* Get the system rid of the stolen ASID.
/branches/dd/kernel/genarch/src/mm/page_ht.c
51,8 → 51,8
#include <adt/hash_table.h>
#include <align.h>
 
static index_t hash(unative_t key[]);
static bool compare(unative_t key[], count_t keys, link_t *item);
static size_t hash(unative_t key[]);
static bool compare(unative_t key[], size_t keys, link_t *item);
static void remove_callback(link_t *item);
 
static void ht_mapping_insert(as_t *as, uintptr_t page, uintptr_t frame,
93,11 → 93,11
*
* @return Index into page hash table.
*/
index_t hash(unative_t key[])
size_t hash(unative_t key[])
{
as_t *as = (as_t *) key[KEY_AS];
uintptr_t page = (uintptr_t) key[KEY_PAGE];
index_t index;
size_t index;
/*
* Virtual page addresses have roughly the same probability
124,7 → 124,7
*
* @return true on match, false otherwise.
*/
bool compare(unative_t key[], count_t keys, link_t *item)
bool compare(unative_t key[], size_t keys, link_t *item)
{
pte_t *t;
 
/branches/dd/kernel/genarch/src/ofw/ebus.c
49,7 → 49,7
{
ofw_tree_property_t *prop;
ofw_ebus_range_t *range;
count_t ranges;
size_t ranges;
 
prop = ofw_tree_getprop(node, "ranges");
if (!prop)
91,7 → 91,7
return false;
 
ofw_ebus_intr_map_t *intr_map = prop->value;
count_t count = prop->size / sizeof(ofw_ebus_intr_map_t);
size_t count = prop->size / sizeof(ofw_ebus_intr_map_t);
ASSERT(count);
/branches/dd/kernel/genarch/src/ofw/fhc.c
46,7 → 46,7
{
ofw_tree_property_t *prop;
ofw_fhc_range_t *range;
count_t ranges;
size_t ranges;
 
prop = ofw_tree_getprop(node, "ranges");
if (!prop)
88,7 → 88,7
ofw_tree_property_t *prop;
ofw_central_range_t *range;
count_t ranges;
size_t ranges;
prop = ofw_tree_getprop(node, "ranges");
if (!prop)
/branches/dd/kernel/genarch/src/ofw/ofw_tree.c
247,7 → 247,8
{
char buf[NAME_BUF_LEN + 1];
ofw_tree_node_t *node = ofw_root;
index_t i, j;
size_t i;
size_t j;
if (path[0] != '/')
return NULL;
/branches/dd/kernel/genarch/src/ofw/pci.c
54,7 → 54,7
{
ofw_tree_property_t *prop;
ofw_pci_range_t *range;
count_t ranges;
size_t ranges;
 
prop = ofw_tree_getprop(node, "ranges");
if (!prop) {
97,7 → 97,7
ofw_tree_property_t *prop;
ofw_pci_reg_t *assigned_address;
count_t assigned_addresses;
size_t assigned_addresses;
prop = ofw_tree_getprop(node, "assigned-addresses");
if (!prop)
/branches/dd/kernel/genarch/src/ofw/sbus.c
43,7 → 43,7
{
ofw_tree_property_t *prop;
ofw_sbus_range_t *range;
count_t ranges;
size_t ranges;
/*
* The SBUS support is very rudimentary in that we simply assume
/branches/dd/kernel/genarch/src/acpi/madt.c
62,11 → 62,11
struct madt_l_apic *madt_l_apic_entries = NULL;
struct madt_io_apic *madt_io_apic_entries = NULL;
 
index_t madt_l_apic_entry_index = 0;
index_t madt_io_apic_entry_index = 0;
count_t madt_l_apic_entry_cnt = 0;
count_t madt_io_apic_entry_cnt = 0;
count_t cpu_count = 0;
size_t madt_l_apic_entry_index = 0;
size_t madt_io_apic_entry_index = 0;
size_t madt_l_apic_entry_cnt = 0;
size_t madt_io_apic_entry_cnt = 0;
size_t cpu_count = 0;
 
struct madt_apic_header * * madt_entries_index = NULL;
unsigned int madt_entries_index_cnt = 0;
86,10 → 86,10
/*
* ACPI MADT Implementation of SMP configuration interface.
*/
static count_t madt_cpu_count(void);
static bool madt_cpu_enabled(index_t i);
static bool madt_cpu_bootstrap(index_t i);
static uint8_t madt_cpu_apic_id(index_t i);
static size_t madt_cpu_count(void);
static bool madt_cpu_enabled(size_t i);
static bool madt_cpu_bootstrap(size_t i);
static uint8_t madt_cpu_apic_id(size_t i);
static int madt_irq_to_pin(unsigned int irq);
 
struct smp_config_operations madt_config_operations = {
100,12 → 100,12
.irq_to_pin = madt_irq_to_pin
};
 
count_t madt_cpu_count(void)
size_t madt_cpu_count(void)
{
return madt_l_apic_entry_cnt;
}
 
bool madt_cpu_enabled(index_t i)
bool madt_cpu_enabled(size_t i)
{
ASSERT(i < madt_l_apic_entry_cnt);
return ((struct madt_l_apic *) madt_entries_index[madt_l_apic_entry_index + i])->flags & 0x1;
112,13 → 112,13
 
}
 
bool madt_cpu_bootstrap(index_t i)
bool madt_cpu_bootstrap(size_t i)
{
ASSERT(i < madt_l_apic_entry_cnt);
return ((struct madt_l_apic *) madt_entries_index[madt_l_apic_entry_index + i])->apic_id == l_apic_id();
}
 
uint8_t madt_cpu_apic_id(index_t i)
uint8_t madt_cpu_apic_id(size_t i)
{
ASSERT(i < madt_l_apic_entry_cnt);
return ((struct madt_l_apic *) madt_entries_index[madt_l_apic_entry_index + i])->apic_id;
/branches/dd/kernel/generic/include/symtab.h
48,7 → 48,7
extern char *symtab_fmt_name_lookup(unative_t addr);
extern int symtab_addr_lookup(const char *name, uintptr_t *addr);
extern void symtab_print_search(const char *name);
extern int symtab_compl(char *input, count_t size);
extern int symtab_compl(char *input, size_t size);
 
#ifdef CONFIG_SYMTAB
 
/branches/dd/kernel/generic/include/config.h
50,7 → 50,7
} init_task_t;
 
typedef struct {
count_t cnt;
size_t cnt;
init_task_t tasks[CONFIG_INIT_TASKS];
} init_t;
 
65,8 → 65,8
} ballocs_t;
 
typedef struct {
count_t cpu_count; /**< Number of processors detected. */
volatile count_t cpu_active; /**< Number of processors that are up and running. */
size_t cpu_count; /**< Number of processors detected. */
volatile size_t cpu_active; /**< Number of processors that are up and running. */
uintptr_t base;
size_t kernel_size; /**< Size of memory in bytes taken by kernel and stack */
/branches/dd/kernel/generic/include/string.h
71,20 → 71,20
extern size_t str_size(const char *str);
extern size_t wstr_size(const wchar_t *str);
 
extern size_t str_lsize(const char *str, count_t max_len);
extern size_t wstr_lsize(const wchar_t *str, count_t max_len);
extern size_t str_lsize(const char *str, size_t max_len);
extern size_t wstr_lsize(const wchar_t *str, size_t max_len);
 
extern count_t str_length(const char *str);
extern count_t wstr_length(const wchar_t *wstr);
extern size_t str_length(const char *str);
extern size_t wstr_length(const wchar_t *wstr);
 
extern count_t str_nlength(const char *str, size_t size);
extern count_t wstr_nlength(const wchar_t *str, size_t size);
extern size_t str_nlength(const char *str, size_t size);
extern size_t wstr_nlength(const wchar_t *str, size_t size);
 
extern bool ascii_check(wchar_t ch);
extern bool chr_check(wchar_t ch);
 
extern int str_cmp(const char *s1, const char *s2);
extern int str_lcmp(const char *s1, const char *s2, count_t max_len);
extern int str_lcmp(const char *s1, const char *s2, size_t max_len);
 
extern void str_cpy(char *dest, size_t size, const char *src);
extern void str_ncpy(char *dest, size_t size, const char *src, size_t n);
92,8 → 92,8
 
extern const char *str_chr(const char *str, wchar_t ch);
 
extern bool wstr_linsert(wchar_t *str, wchar_t ch, count_t pos, count_t max_pos);
extern bool wstr_remove(wchar_t *str, count_t pos);
extern bool wstr_linsert(wchar_t *str, wchar_t ch, size_t pos, size_t max_pos);
extern bool wstr_remove(wchar_t *str, size_t pos);
 
#endif
 
/branches/dd/kernel/generic/include/proc/scheduler.h
47,7 → 47,7
typedef struct {
SPINLOCK_DECLARE(lock);
link_t rq_head; /**< List of ready threads. */
count_t n; /**< Number of threads in rq_ready. */
size_t n; /**< Number of threads in rq_ready. */
} runq_t;
 
extern atomic_t nrdy;
/branches/dd/kernel/generic/include/cpu.h
51,18 → 51,18
SPINLOCK_DECLARE(lock);
 
tlb_shootdown_msg_t tlb_messages[TLB_MESSAGE_QUEUE_LEN];
count_t tlb_messages_count;
size_t tlb_messages_count;
context_t saved_context;
 
atomic_t nrdy;
runq_t rq[RQ_COUNT];
volatile count_t needs_relink;
volatile size_t needs_relink;
 
SPINLOCK_DECLARE(timeoutlock);
link_t timeout_active_head;
 
count_t missed_clock_ticks; /**< When system clock loses a tick, it is recorded here
size_t missed_clock_ticks; /**< When system clock loses a tick, it is recorded here
so that clock() can react. This variable is
CPU-local and can be only accessed when interrupts
are disabled. */
/branches/dd/kernel/generic/include/synch/futex.h
49,7 → 49,7
/** Futex hash table link. */
link_t ht_link;
/** Number of tasks that reference this futex. */
count_t refcount;
size_t refcount;
} futex_t;
 
extern void futex_init(void);
/branches/dd/kernel/generic/include/synch/rwlock.h
53,7 → 53,7
*/
mutex_t exclusive;
/** Number of readers in critical section. */
count_t readers_in;
size_t readers_in;
} rwlock_t;
 
#define rwlock_write_lock(rwl) \
/branches/dd/kernel/generic/include/synch/spinlock.h
107,7 → 107,7
extern int printf(const char *, ...);
 
#define DEADLOCK_THRESHOLD 100000000
#define DEADLOCK_PROBE_INIT(pname) count_t pname = 0
#define DEADLOCK_PROBE_INIT(pname) size_t pname = 0
#define DEADLOCK_PROBE(pname, value) \
if ((pname)++ > (value)) { \
(pname) = 0; \
/branches/dd/kernel/generic/include/ddi/irq.h
104,7 → 104,7
/** Top-half pseudocode. */
irq_code_t *code;
/** Counter. */
count_t counter;
size_t counter;
/**
* Link between IRQs that are notifying the same answerbox. The list is
* protected by the answerbox irq_lock.
162,7 → 162,7
SPINLOCK_EXTERN(irq_uspace_hash_table_lock);
extern hash_table_t irq_uspace_hash_table;
 
extern void irq_init(count_t, count_t);
extern void irq_init(size_t, size_t);
extern void irq_initialize(irq_t *);
extern void irq_register(irq_t *);
extern irq_t *irq_dispatch_and_lock(inr_t);
/branches/dd/kernel/generic/include/console/chardev.h
57,11 → 57,11
/** Protects everything below. */
SPINLOCK_DECLARE(lock);
wchar_t buffer[INDEV_BUFLEN];
count_t counter;
size_t counter;
/** Implementation of indev operations. */
indev_operations_t *op;
index_t index;
size_t index;
void *data;
} indev_t;
 
/branches/dd/kernel/generic/include/console/kconsole.h
77,7 → 77,7
/** Function implementing the command. */
int (* func)(cmd_arg_t *);
/** Number of arguments. */
count_t argc;
size_t argc;
/** Argument vector. */
cmd_arg_t *argv;
/** Function for printing detailed help. */
/branches/dd/kernel/generic/include/console/console.h
49,7 → 49,7
extern void klog_update(void);
 
extern wchar_t getc(indev_t *indev);
extern count_t gets(indev_t *indev, char *buf, size_t buflen);
extern size_t gets(indev_t *indev, char *buf, size_t buflen);
extern unative_t sys_klog(int fd, const void *buf, size_t size);
 
extern void grab_console(void);
/branches/dd/kernel/generic/include/arch.h
56,7 → 56,7
* the base address of the stack.
*/
typedef struct {
count_t preemption_disabled; /**< Preemption disabled counter. */
size_t preemption_disabled; /**< Preemption disabled counter. */
thread_t *thread; /**< Current thread. */
task_t *task; /**< Current task. */
cpu_t *cpu; /**< Executing cpu. */
/branches/dd/kernel/generic/include/adt/hash_table.h
47,7 → 47,7
*
* @return Index into hash table.
*/
index_t (* hash)(unative_t key[]);
size_t (* hash)(unative_t key[]);
/** Hash table item comparison function.
*
56,7 → 56,7
*
* @return true if the keys match, false otherwise.
*/
bool (*compare)(unative_t key[], count_t keys, link_t *item);
bool (*compare)(unative_t key[], size_t keys, link_t *item);
 
/** Hash table item removal callback.
*
68,8 → 68,8
/** Hash table structure. */
typedef struct {
link_t *entry;
count_t entries;
count_t max_keys;
size_t entries;
size_t max_keys;
hash_table_operations_t *op;
} hash_table_t;
 
76,11 → 76,11
#define hash_table_get_instance(item, type, member) \
list_get_instance((item), type, member)
 
extern void hash_table_create(hash_table_t *h, count_t m, count_t max_keys,
extern void hash_table_create(hash_table_t *h, size_t m, size_t max_keys,
hash_table_operations_t *op);
extern void hash_table_insert(hash_table_t *h, unative_t key[], link_t *item);
extern link_t *hash_table_find(hash_table_t *h, unative_t key[]);
extern void hash_table_remove(hash_table_t *h, unative_t key[], count_t keys);
extern void hash_table_remove(hash_table_t *h, unative_t key[], size_t keys);
 
#endif
 
/branches/dd/kernel/generic/include/adt/bitmap.h
41,18 → 41,19
 
typedef struct {
uint8_t *map;
count_t bits;
size_t bits;
} bitmap_t;
 
extern void bitmap_initialize(bitmap_t *bitmap, uint8_t *map, count_t bits);
extern void bitmap_set_range(bitmap_t *bitmap, index_t start, count_t bits);
extern void bitmap_clear_range(bitmap_t *bitmap, index_t start, count_t bits);
extern void bitmap_copy(bitmap_t *dst, bitmap_t *src, count_t bits);
extern void bitmap_initialize(bitmap_t *bitmap, uint8_t *map, size_t bits);
extern void bitmap_set_range(bitmap_t *bitmap, size_t start, size_t bits);
extern void bitmap_clear_range(bitmap_t *bitmap, size_t start, size_t bits);
extern void bitmap_copy(bitmap_t *dst, bitmap_t *src, size_t bits);
 
static inline int bitmap_get(bitmap_t *bitmap,index_t bit)
static inline int bitmap_get(bitmap_t *bitmap, size_t bit)
{
if(bit >= bitmap->bits)
return 0;
return !! ((bitmap->map)[bit/8] & (1 << (bit & 7)));
}
 
/branches/dd/kernel/generic/include/adt/btree.h
46,7 → 46,7
/** B-tree node structure. */
typedef struct btree_node {
/** Number of keys. */
count_t keys;
size_t keys;
 
/**
* Keys. We currently support only single keys. Additional room for one
/branches/dd/kernel/generic/include/adt/fifo.h
59,9 → 59,9
#define FIFO_INITIALIZE_STATIC(name, t, itms) \
struct { \
t fifo[(itms)]; \
count_t items; \
index_t head; \
index_t tail; \
size_t items; \
size_t head; \
size_t tail; \
} name = { \
.items = (itms), \
.head = 0, \
80,9 → 80,9
#define FIFO_INITIALIZE_DYNAMIC(name, t, itms) \
struct { \
t *fifo; \
count_t items; \
index_t head; \
index_t tail; \
size_t items; \
size_t head; \
size_t tail; \
} name = { \
.fifo = NULL, \
.items = (itms), \
/branches/dd/kernel/generic/include/mm/frame.h
80,7 → 80,7
#define FRAME_TO_ZONE_FLAGS(frame_flags) 0
 
typedef struct {
count_t refcount; /**< Tracking of shared frames */
size_t refcount; /**< Tracking of shared frames */
uint8_t buddy_order; /**< Buddy system block order */
link_t buddy_link; /**< Link to the next free block inside
one order */
90,10 → 90,10
typedef struct {
pfn_t base; /**< Frame_no of the first frame
in the frames array */
count_t count; /**< Size of zone */
count_t free_count; /**< Number of free frame_t
size_t count; /**< Size of zone */
size_t free_count; /**< Number of free frame_t
structures */
count_t busy_count; /**< Number of busy frame_t
size_t busy_count; /**< Number of busy frame_t
structures */
zone_flags_t flags; /**< Type of the zone */
108,7 → 108,7
*/
typedef struct {
SPINLOCK_DECLARE(lock);
count_t count;
size_t count;
zone_t info[ZONES_MAX];
} zones_t;
 
124,14 → 124,14
return (pfn_t) (addr >> FRAME_WIDTH);
}
 
static inline count_t SIZE2FRAMES(size_t size)
static inline size_t SIZE2FRAMES(size_t size)
{
if (!size)
return 0;
return (count_t) ((size - 1) >> FRAME_WIDTH) + 1;
return (size_t) ((size - 1) >> FRAME_WIDTH) + 1;
}
 
static inline size_t FRAMES2SIZE(count_t frames)
static inline size_t FRAMES2SIZE(size_t frames)
{
return (size_t) (frames << FRAME_WIDTH);
}
156,17 → 156,17
frame_alloc_generic(order, flags, NULL)
 
extern void frame_init(void);
extern void *frame_alloc_generic(uint8_t, frame_flags_t, count_t *);
extern void *frame_alloc_generic(uint8_t, frame_flags_t, size_t *);
extern void frame_free(uintptr_t);
extern void frame_reference_add(pfn_t);
 
extern count_t find_zone(pfn_t frame, count_t count, count_t hint);
extern count_t zone_create(pfn_t, count_t, pfn_t, zone_flags_t);
extern void *frame_get_parent(pfn_t, count_t);
extern void frame_set_parent(pfn_t, void *, count_t);
extern void frame_mark_unavailable(pfn_t, count_t);
extern uintptr_t zone_conf_size(count_t);
extern bool zone_merge(count_t, count_t);
extern size_t find_zone(pfn_t frame, size_t count, size_t hint);
extern size_t zone_create(pfn_t, size_t, pfn_t, zone_flags_t);
extern void *frame_get_parent(pfn_t, size_t);
extern void frame_set_parent(pfn_t, void *, size_t);
extern void frame_mark_unavailable(pfn_t, size_t);
extern uintptr_t zone_conf_size(size_t);
extern bool zone_merge(size_t, size_t);
extern void zone_merge_all(void);
extern uint64_t zone_total_size(void);
 
174,7 → 174,7
* Console functions
*/
extern void zone_print_list(void);
extern void zone_print_one(count_t);
extern void zone_print_one(size_t);
 
#endif
 
/branches/dd/kernel/generic/include/mm/slab.h
72,8 → 72,8
 
typedef struct {
link_t link;
count_t busy; /**< Count of full slots in magazine */
count_t size; /**< Number of slots in magazine */
size_t busy; /**< Count of full slots in magazine */
size_t size; /**< Number of slots in magazine */
void *objs[]; /**< Slots in magazine */
} slab_magazine_t;
 
128,7 → 128,7
 
extern void * slab_alloc(slab_cache_t *, int);
extern void slab_free(slab_cache_t *, void *);
extern count_t slab_reclaim(int);
extern size_t slab_reclaim(int);
 
/* slab subsytem initialization */
extern void slab_cache_init(void);
/branches/dd/kernel/generic/include/mm/tlb.h
61,7 → 61,7
tlb_invalidate_type_t type; /**< Message type. */
asid_t asid; /**< Address space identifier. */
uintptr_t page; /**< Page address. */
count_t count; /**< Number of pages to invalidate. */
size_t count; /**< Number of pages to invalidate. */
} tlb_shootdown_msg_t;
 
extern void tlb_init(void);
68,7 → 68,7
 
#ifdef CONFIG_SMP
extern void tlb_shootdown_start(tlb_invalidate_type_t type, asid_t asid,
uintptr_t page, count_t count);
uintptr_t page, size_t count);
extern void tlb_shootdown_finalize(void);
extern void tlb_shootdown_ipi_recv(void);
#else
84,7 → 84,7
 
extern void tlb_invalidate_all(void);
extern void tlb_invalidate_asid(asid_t asid);
extern void tlb_invalidate_pages(asid_t asid, uintptr_t page, count_t cnt);
extern void tlb_invalidate_pages(asid_t asid, uintptr_t page, size_t cnt);
#endif
 
/** @}
/branches/dd/kernel/generic/include/mm/as.h
94,7 → 94,7
* Number of processors on wich is this address space active.
* Protected by asidlock.
*/
count_t cpu_refcount;
size_t cpu_refcount;
/**
* Address space identifier.
* Constant on architectures that do not support ASIDs.
132,7 → 132,7
/** This lock must be acquired only when the as_area lock is held. */
mutex_t lock;
/** This structure can be deallocated if refcount drops to 0. */
count_t refcount;
size_t refcount;
/**
* B+tree containing complete map of anonymous pages of the shared area.
*/
156,7 → 156,7
};
struct { /**< phys_backend members */
uintptr_t base;
count_t frames;
size_t frames;
};
} mem_backend_data_t;
 
175,7 → 175,7
/** Attributes related to the address space area itself. */
int attributes;
/** Size of this area in multiples of PAGE_SIZE. */
count_t pages;
size_t pages;
/** Base address of this area. */
uintptr_t base;
/** Map of used space. */
225,8 → 225,8
extern int as_area_get_flags(as_area_t *area);
extern bool as_area_check_access(as_area_t *area, pf_access_t access);
extern size_t as_area_get_size(uintptr_t base);
extern int used_space_insert(as_area_t *a, uintptr_t page, count_t count);
extern int used_space_remove(as_area_t *a, uintptr_t page, count_t count);
extern int used_space_insert(as_area_t *a, uintptr_t page, size_t count);
extern int used_space_remove(as_area_t *a, uintptr_t page, size_t count);
 
 
/* Interface to be implemented by architectures. */
/branches/dd/kernel/generic/include/macros.h
83,6 → 83,13
#define STRING(arg) STRING_ARG(arg)
#define STRING_ARG(arg) #arg
 
#define LOWER32(arg) ((arg) & 0xffffffff)
#define UPPER32(arg) (((arg) >> 32) & 0xffffffff)
 
#define MERGE_LOUP32(lo, up) \
((((uint64_t) (lo)) & 0xffffffff) \
| ((((uint64_t) (up)) & 0xffffffff) << 32))
 
/** Pseudorandom generator
*
* A pretty standard linear congruential pseudorandom
/branches/dd/kernel/generic/include/ipc/event.h
49,7 → 49,7
/** Method to be used for the notification. */
unative_t method;
/** Counter. */
count_t counter;
size_t counter;
} event_t;
 
extern void event_init(void);
/branches/dd/kernel/generic/include/ipc/event_types.h
38,9 → 38,15
typedef enum event_type {
EVENT_KLOG = 0,
EVENT_KCONSOLE,
EVENT_WAIT,
EVENT_END
} event_type_t;
 
typedef enum wait_type {
TASK_CREATE = 0,
TASK_DESTROY
} wait_type_t;
 
#endif
 
/** @}
/branches/dd/kernel/generic/include/sort.h
40,8 → 40,8
/*
* sorting routines
*/
extern void bubblesort(void * data, count_t n, size_t e_size, int (* cmp) (void * a, void * b));
extern void qsort(void * data, count_t n, size_t e_size, int (* cmp) (void * a, void * b));
extern void bubblesort(void * data, size_t n, size_t e_size, int (* cmp) (void * a, void * b));
extern void qsort(void * data, size_t n, size_t e_size, int (* cmp) (void * a, void * b));
 
/*
* default sorting comparators
/branches/dd/kernel/generic/src/main/kinit.c
127,7 → 127,7
}
if (config.cpu_count > 1) {
count_t i;
size_t i;
/*
* For each CPU, create its load balancing thread.
140,7 → 140,7
spinlock_unlock(&thread->lock);
thread_ready(thread);
} else
printf("Unable to create kcpulb thread for cpu" PRIc "\n", i);
printf("Unable to create kcpulb thread for cpu" PRIs "\n", i);
}
}
#endif /* CONFIG_SMP */
168,12 → 168,12
/*
* Create user tasks, load RAM disk images.
*/
count_t i;
size_t i;
program_t programs[CONFIG_INIT_TASKS];
for (i = 0; i < init.cnt; i++) {
if (init.tasks[i].addr % FRAME_SIZE) {
printf("init[%" PRIc "].addr is not frame aligned\n", i);
printf("init[%" PRIs "].addr is not frame aligned\n", i);
continue;
}
213,7 → 213,7
int rd = init_rd((rd_header_t *) init.tasks[i].addr, init.tasks[i].size);
if (rd != RE_OK)
printf("Init binary %" PRIc " not used (error %d)\n", i, rd);
printf("Init binary %" PRIs " not used (error %d)\n", i, rd);
}
}
/branches/dd/kernel/generic/src/main/main.c
153,7 → 153,7
config.stack_base = config.base + config.kernel_size;
/* Avoid placing stack on top of init */
count_t i;
size_t i;
for (i = 0; i < init.cnt; i++) {
if (PA_overlaps(config.stack_base, config.stack_size,
init.tasks[i].addr, init.tasks[i].size))
233,7 → 233,7
/* Slab must be initialized after we know the number of processors. */
LOG_EXEC(slab_enable_cpucache());
printf("Detected %" PRIc " CPU(s), %" PRIu64" MiB free memory\n",
printf("Detected %" PRIs " CPU(s), %" PRIu64" MiB free memory\n",
config.cpu_count, SIZE2MB(zone_total_size()));
LOG_EXEC(cpu_init());
247,9 → 247,9
LOG_EXEC(futex_init());
if (init.cnt > 0) {
count_t i;
size_t i;
for (i = 0; i < init.cnt; i++)
LOG("init[%" PRIc "].addr=%#" PRIp ", init[%" PRIc
LOG("init[%" PRIs "].addr=%#" PRIp ", init[%" PRIs
"].size=%#" PRIs, i, init.tasks[i].addr, i,
init.tasks[i].size);
} else
/branches/dd/kernel/generic/src/synch/spinlock.c
75,7 → 75,7
#ifdef CONFIG_DEBUG_SPINLOCK
void spinlock_lock_debug(spinlock_t *sl)
{
count_t i = 0;
size_t i = 0;
bool deadlock_reported = false;
 
preemption_disable();
/branches/dd/kernel/generic/src/synch/waitq.c
415,7 → 415,7
void _waitq_wakeup_unsafe(waitq_t *wq, wakeup_mode_t mode)
{
thread_t *t;
count_t count = 0;
size_t count = 0;
 
loop:
if (list_empty(&wq->head)) {
/branches/dd/kernel/generic/src/synch/futex.c
59,8 → 59,8
static void futex_initialize(futex_t *futex);
 
static futex_t *futex_find(uintptr_t paddr);
static index_t futex_ht_hash(unative_t *key);
static bool futex_ht_compare(unative_t *key, count_t keys, link_t *item);
static size_t futex_ht_hash(unative_t *key);
static bool futex_ht_compare(unative_t *key, size_t keys, link_t *item);
static void futex_ht_remove_callback(link_t *item);
 
/**
288,9 → 288,9
*
* @return Index into futex hash table.
*/
index_t futex_ht_hash(unative_t *key)
size_t futex_ht_hash(unative_t *key)
{
return *key & (FUTEX_HT_SIZE-1);
return (*key & (FUTEX_HT_SIZE - 1));
}
 
/** Compare futex hash table item with a key.
300,7 → 300,7
*
* @return True if the item matches the key. False otherwise.
*/
bool futex_ht_compare(unative_t *key, count_t keys, link_t *item)
bool futex_ht_compare(unative_t *key, size_t keys, link_t *item)
{
futex_t *futex;
 
/branches/dd/kernel/generic/src/debug/symtab.c
55,7 → 55,7
int symtab_name_lookup(unative_t addr, char **name)
{
#ifdef CONFIG_SYMTAB
count_t i;
size_t i;
for (i = 1; symbol_table[i].address_le; i++) {
if (addr < uint64_t_le2host(symbol_table[i].address_le))
112,11 → 112,11
* @return Pointer to the part of string that should be completed or NULL.
*
*/
static const char *symtab_search_one(const char *name, count_t *startpos)
static const char *symtab_search_one(const char *name, size_t *startpos)
{
count_t namelen = str_length(name);
size_t namelen = str_length(name);
count_t pos;
size_t pos;
for (pos = *startpos; symbol_table[pos].address_le; pos++) {
const char *curname = symbol_table[pos].symbol_name;
153,8 → 153,8
int symtab_addr_lookup(const char *name, uintptr_t *addr)
{
#ifdef CONFIG_SYMTAB
count_t found = 0;
count_t pos = 0;
size_t found = 0;
size_t pos = 0;
const char *hint;
while ((hint = symtab_search_one(name, &pos))) {
182,7 → 182,7
void symtab_print_search(const char *name)
{
#ifdef CONFIG_SYMTAB
count_t pos = 0;
size_t pos = 0;
while (symtab_search_one(name, &pos)) {
uintptr_t addr = uint64_t_le2host(symbol_table[pos].address_le);
char *realname = symbol_table[pos].symbol_name;
203,7 → 203,7
* @return 0 - nothing found, 1 - success, >1 print duplicates
*
*/
int symtab_compl(char *input, count_t size)
int symtab_compl(char *input, size_t size)
{
#ifdef CONFIG_SYMTAB
const char *name = input;
216,8 → 216,8
if (str_length(name) == 0)
return 0;
count_t found = 0;
count_t pos = 0;
size_t found = 0;
size_t pos = 0;
const char *hint;
char output[MAX_SYMBOL_NAME];
/branches/dd/kernel/generic/src/time/clock.c
134,7 → 134,7
timeout_t *h;
timeout_handler_t f;
void *arg;
count_t missed_clock_ticks = CPU->missed_clock_ticks;
size_t missed_clock_ticks = CPU->missed_clock_ticks;
unsigned int i;
 
/*
/branches/dd/kernel/generic/src/ddi/ddi.c
97,7 → 97,7
* creating address space area.
*
*/
static int ddi_physmem_map(uintptr_t pf, uintptr_t vp, count_t pages, int flags)
static int ddi_physmem_map(uintptr_t pf, uintptr_t vp, size_t pages, int flags)
{
ASSERT(TASK);
ASSERT((pf % FRAME_SIZE) == 0);
118,9 → 118,9
/* Find the zone of the physical memory */
spinlock_lock(&zones.lock);
count_t znum = find_zone(ADDR2PFN(pf), pages, 0);
size_t znum = find_zone(ADDR2PFN(pf), pages, 0);
if (znum == (count_t) -1) {
if (znum == (size_t) -1) {
/* Frames not found in any zones
* -> assume it is hardware device and allow mapping
*/
242,7 → 242,7
{
return (unative_t) ddi_physmem_map(ALIGN_DOWN((uintptr_t) phys_base,
FRAME_SIZE), ALIGN_DOWN((uintptr_t) virt_base, PAGE_SIZE),
(count_t) pages, (int) flags);
(size_t) pages, (int) flags);
}
 
/** Wrapper for SYS_ENABLE_IOSPACE syscall.
/branches/dd/kernel/generic/src/ddi/irq.c
99,8 → 99,8
* Hash table operations for cases when we know that
* there will be collisions between different keys.
*/
static index_t irq_ht_hash(unative_t *key);
static bool irq_ht_compare(unative_t *key, count_t keys, link_t *item);
static size_t irq_ht_hash(unative_t *key);
static bool irq_ht_compare(unative_t *key, size_t keys, link_t *item);
static void irq_ht_remove(link_t *item);
 
static hash_table_operations_t irq_ht_ops = {
115,8 → 115,8
* However, there might be still collisions among
* elements with single key (sharing of one IRQ).
*/
static index_t irq_lin_hash(unative_t *key);
static bool irq_lin_compare(unative_t *key, count_t keys, link_t *item);
static size_t irq_lin_hash(unative_t *key);
static bool irq_lin_compare(unative_t *key, size_t keys, link_t *item);
static void irq_lin_remove(link_t *item);
 
static hash_table_operations_t irq_lin_ops = {
126,7 → 126,7
};
 
/** Number of buckets in either of the hash tables. */
static count_t buckets;
static size_t buckets;
 
/** Initialize IRQ subsystem.
*
133,7 → 133,7
* @param inrs Numbers of unique IRQ numbers or INRs.
* @param chains Number of chains in the hash table.
*/
void irq_init(count_t inrs, count_t chains)
void irq_init(size_t inrs, size_t chains)
{
buckets = chains;
/*
298,7 → 298,7
*
* @return Index into the hash table.
*/
index_t irq_ht_hash(unative_t key[])
size_t irq_ht_hash(unative_t key[])
{
inr_t inr = (inr_t) key[KEY_INR];
return inr % buckets;
324,7 → 324,7
*
* @return True on match or false otherwise.
*/
bool irq_ht_compare(unative_t key[], count_t keys, link_t *item)
bool irq_ht_compare(unative_t key[], size_t keys, link_t *item)
{
irq_t *irq = hash_table_get_instance(item, irq_t, link);
inr_t inr = (inr_t) key[KEY_INR];
371,7 → 371,7
*
* @return Index into the hash table.
*/
index_t irq_lin_hash(unative_t key[])
size_t irq_lin_hash(unative_t key[])
{
inr_t inr = (inr_t) key[KEY_INR];
return inr;
397,7 → 397,7
*
* @return True on match or false otherwise.
*/
bool irq_lin_compare(unative_t key[], count_t keys, link_t *item)
bool irq_lin_compare(unative_t key[], size_t keys, link_t *item)
{
irq_t *irq = list_get_instance(item, irq_t, link);
devno_t devno = (devno_t) key[KEY_DEVNO];
/branches/dd/kernel/generic/src/console/console.c
61,7 → 61,7
/** Kernel log initialized */
static bool klog_inited = false;
/** First kernel log characters */
static index_t klog_start = 0;
static size_t klog_start = 0;
/** Number of valid kernel log characters */
static size_t klog_len = 0;
/** Number of stored (not printed) kernel log characters */
170,10 → 170,10
* @return Number of characters read.
*
*/
count_t gets(indev_t *indev, char *buf, size_t buflen)
size_t gets(indev_t *indev, char *buf, size_t buflen)
{
size_t offset = 0;
count_t count = 0;
size_t count = 0;
buf[offset] = 0;
wchar_t ch;
226,7 → 226,7
if ((klog_stored > 0) && (stdout) && (stdout->op->write)) {
/* Print charaters stored in kernel log */
index_t i;
size_t i;
for (i = klog_len - klog_stored; i < klog_len; i++)
stdout->op->write(stdout, klog[(klog_start + i) % KLOG_LENGTH], silent);
klog_stored = 0;
/branches/dd/kernel/generic/src/console/cmd.c
513,7 → 513,7
spinlock_lock(&cmd_lock);
link_t *cur;
count_t len = 0;
size_t len = 0;
for (cur = cmd_head.next; cur != &cmd_head; cur = cur->next) {
cmd_info_t *hlp;
hlp = list_get_instance(cur, cmd_info_t, link);
651,7 → 651,7
* call the function.
*/
count_t i;
size_t i;
for (i = 0; i < config.cpu_count; i++) {
if (!cpus[i].active)
continue;
970,7 → 970,7
*/
int cmd_tests(cmd_arg_t *argv)
{
count_t len = 0;
size_t len = 0;
test_t *test;
for (test = tests; test->name != NULL; test++) {
if (str_length(test->name) > len)
/branches/dd/kernel/generic/src/console/kconsole.c
86,7 → 86,7
LIST_INITIALIZE(cmd_head); /**< Command list. */
 
static wchar_t history[KCONSOLE_HISTORY][MAX_CMDLINE] = {};
static count_t history_pos = 0;
static size_t history_pos = 0;
 
/** Initialize kconsole data structures
*
159,9 → 159,9
}
 
/** Print count times a character */
static void print_cc(wchar_t ch, count_t count)
static void print_cc(wchar_t ch, size_t count)
{
count_t i;
size_t i;
for (i = 0; i < count; i++)
putchar(ch);
}
169,7 → 169,7
/** Try to find a command beginning with prefix */
static const char *cmdtab_search_one(const char *name, link_t **startpos)
{
count_t namelen = str_length(name);
size_t namelen = str_length(name);
spinlock_lock(&cmd_lock);
205,7 → 205,7
{
const char *name = input;
count_t found = 0;
size_t found = 0;
link_t *pos = NULL;
const char *hint;
char output[MAX_CMDLINE];
240,7 → 240,7
{
printf("%s> ", prompt);
count_t position = 0;
size_t position = 0;
wchar_t *current = history[history_pos];
current[0] = 0;
280,7 → 280,7
/* Find the beginning of the word
and copy it to tmp */
count_t beg;
size_t beg;
for (beg = position - 1; (beg > 0) && (!isspace(current[beg]));
beg--);
313,7 → 313,7
/* We have a hint */
size_t off = 0;
count_t i = 0;
size_t i = 0;
while ((ch = str_decode(tmp, &off, STR_NO_LIMIT)) != 0) {
if (!wstr_linsert(current, ch, position + i, MAX_CMDLINE))
break;
542,7 → 542,7
if (str_lcmp(hlp->name, cmdline + start,
max(str_length(hlp->name),
str_nlength(cmdline + start, (count_t) (end - start) - 1))) == 0) {
str_nlength(cmdline + start, (size_t) (end - start) - 1))) == 0) {
cmd = hlp;
break;
}
568,7 → 568,7
*/
bool error = false;
count_t i;
size_t i;
for (i = 0; i < cmd->argc; i++) {
start = end;
if (!parse_argument(cmdline, size, &start, &end)) {
659,7 → 659,7
while (true) {
wchar_t *tmp = clever_readline((char *) prompt, stdin);
count_t len = wstr_length(tmp);
size_t len = wstr_length(tmp);
if (!len)
continue;
/branches/dd/kernel/generic/src/printf/vprintf.c
46,7 → 46,7
static int vprintf_str_write(const char *str, size_t size, void *data)
{
size_t offset = 0;
count_t chars = 0;
size_t chars = 0;
while (offset < size) {
putchar(str_decode(str, &offset, size));
59,7 → 59,7
static int vprintf_wstr_write(const wchar_t *str, size_t size, void *data)
{
size_t offset = 0;
count_t chars = 0;
size_t chars = 0;
while (offset < size) {
putchar(str[chars]);
73,7 → 73,7
int puts(const char *str)
{
size_t offset = 0;
count_t chars = 0;
size_t chars = 0;
wchar_t uc;
while ((uc = str_decode(str, &offset, STR_NO_LIMIT)) != 0) {
/branches/dd/kernel/generic/src/printf/vsnprintf.c
82,7 → 82,7
* with the trailing zero => print only a part
* of string
*/
index_t index = 0;
size_t index = 0;
while (index < size) {
wchar_t uc = str_decode(str, &index, size);
130,7 → 130,7
*/
static int vsnprintf_wstr_write(const wchar_t *str, size_t size, vsnprintf_data_t *data)
{
index_t index = 0;
size_t index = 0;
while (index < (size / sizeof(wchar_t))) {
size_t left = data->size - data->len;
/branches/dd/kernel/generic/src/printf/printf_core.c
174,7 → 174,7
*/
static int print_char(const char ch, int width, uint32_t flags, printf_spec_t *ps)
{
count_t counter = 0;
size_t counter = 0;
if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
while (--width > 0) {
/*
212,7 → 212,7
*/
static int print_wchar(const wchar_t ch, int width, uint32_t flags, printf_spec_t *ps)
{
count_t counter = 0;
size_t counter = 0;
if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
while (--width > 0) {
/*
255,12 → 255,12
return printf_putstr(nullstr, ps);
 
/* Print leading spaces. */
count_t strw = str_length(str);
size_t strw = str_length(str);
if (precision == 0)
precision = strw;
 
/* Left padding */
count_t counter = 0;
size_t counter = 0;
width -= precision;
if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
while (width-- > 0) {
311,7 → 311,7
precision = strw;
/* Left padding */
count_t counter = 0;
size_t counter = 0;
width -= precision;
if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
while (width-- > 0) {
433,7 → 433,7
}
width -= precision + size - number_size;
count_t counter = 0;
size_t counter = 0;
if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
while (width-- > 0) {
596,7 → 596,7
size_t nxt = 0; /* Index of the next character from fmt */
size_t j = 0; /* Index to the first not printed nonformating character */
count_t counter = 0; /* Number of characters printed */
size_t counter = 0; /* Number of characters printed */
int retval; /* Return values from nested functions */
while (true) {
/branches/dd/kernel/generic/src/proc/scheduler.c
708,7 → 708,7
continue;
 
spinlock_lock(&cpus[cpu].lock);
printf("cpu%u: address=%p, nrdy=%ld, needs_relink=%" PRIc "\n",
printf("cpu%u: address=%p, nrdy=%ld, needs_relink=%" PRIs "\n",
cpus[cpu].id, &cpus[cpu], atomic_get(&cpus[cpu].nrdy),
cpus[cpu].needs_relink);
/branches/dd/kernel/generic/src/proc/task.c
54,6 → 54,8
#include <func.h>
#include <string.h>
#include <syscall/copy.h>
#include <macros.h>
#include <ipc/event.h>
 
/** Spinlock protecting the tasks_tree AVL tree. */
SPINLOCK_INITIALIZE(tasks_lock);
196,7 → 198,14
avltree_insert(&tasks_tree, &ta->tasks_tree_node);
spinlock_unlock(&tasks_lock);
interrupts_restore(ipl);
 
/*
* Notify about task creation.
*/
if (event_is_subscribed(EVENT_WAIT))
event_notify_3(EVENT_WAIT, TASK_CREATE, LOWER32(ta->taskid),
UPPER32(ta->taskid));
return ta;
}
 
229,6 → 238,13
if (atomic_predec(&t->as->refcount) == 0)
as_destroy(t->as);
/*
* Notify about task destruction.
*/
if (event_is_subscribed(EVENT_WAIT))
event_notify_3(EVENT_WAIT, TASK_DESTROY, LOWER32(t->taskid),
UPPER32(t->taskid));
free(t);
TASK = NULL;
}
/branches/dd/kernel/generic/src/lib/string.c
62,10 → 62,10
* the NULL-terminator), size_t
*
* [wide] string length number of CHARACTERS in a [wide] string (excluding
* the NULL-terminator), count_t
* the NULL-terminator), size_t
*
* [wide] string width number of display cells on a monospace display taken
* by a [wide] string, count_t
* by a [wide] string, size_t
*
*
* Overview of string metrics:@n
75,10 → 75,10
* size n size_t number of BYTES in a string (excluding the
* NULL-terminator)
*
* length l count_t number of CHARACTERS in a string (excluding the
* length l size_t number of CHARACTERS in a string (excluding the
* null terminator)
*
* width w count_t number of display cells on a monospace display
* width w size_t number of display cells on a monospace display
* taken by a string
*
*
97,7 → 97,7
*
* pointer (char *, wchar_t *)
* byte offset (size_t)
* character index (count_t)
* character index (size_t)
*
*/
 
309,9 → 309,9
* @return Number of bytes used by the characters.
*
*/
size_t str_lsize(const char *str, count_t max_len)
size_t str_lsize(const char *str, size_t max_len)
{
count_t len = 0;
size_t len = 0;
size_t offset = 0;
while (len < max_len) {
337,7 → 337,7
* @return Number of bytes used by the wide characters.
*
*/
size_t wstr_lsize(const wchar_t *str, count_t max_len)
size_t wstr_lsize(const wchar_t *str, size_t max_len)
{
return (wstr_nlength(str, max_len * sizeof(wchar_t)) * sizeof(wchar_t));
}
349,9 → 349,9
* @return Number of characters in string.
*
*/
count_t str_length(const char *str)
size_t str_length(const char *str)
{
count_t len = 0;
size_t len = 0;
size_t offset = 0;
while (str_decode(str, &offset, STR_NO_LIMIT) != 0)
367,9 → 367,9
* @return Number of characters in @a str.
*
*/
count_t wstr_length(const wchar_t *wstr)
size_t wstr_length(const wchar_t *wstr)
{
count_t len = 0;
size_t len = 0;
while (*wstr++ != 0)
len++;
385,9 → 385,9
* @return Number of characters in string.
*
*/
count_t str_nlength(const char *str, size_t size)
size_t str_nlength(const char *str, size_t size)
{
count_t len = 0;
size_t len = 0;
size_t offset = 0;
while (str_decode(str, &offset, size) != 0)
404,11 → 404,11
* @return Number of characters in string.
*
*/
count_t wstr_nlength(const wchar_t *str, size_t size)
size_t wstr_nlength(const wchar_t *str, size_t size)
{
count_t len = 0;
count_t limit = ALIGN_DOWN(size, sizeof(wchar_t));
count_t offset = 0;
size_t len = 0;
size_t limit = ALIGN_DOWN(size, sizeof(wchar_t));
size_t offset = 0;
while ((offset < limit) && (*str++ != 0)) {
len++;
496,7 → 496,7
* 1 if second smaller.
*
*/
int str_lcmp(const char *s1, const char *s2, count_t max_len)
int str_lcmp(const char *s1, const char *s2, size_t max_len)
{
wchar_t c1 = 0;
wchar_t c2 = 0;
504,7 → 504,7
size_t off1 = 0;
size_t off2 = 0;
count_t len = 0;
size_t len = 0;
 
while (true) {
if (len >= max_len)
615,7 → 615,7
return;
wchar_t ch;
count_t src_idx = 0;
size_t src_idx = 0;
size_t dst_off = 0;
while ((ch = src[src_idx++]) != 0) {
666,14 → 666,14
* is out of bounds.
*
*/
bool wstr_linsert(wchar_t *str, wchar_t ch, count_t pos, count_t max_pos)
bool wstr_linsert(wchar_t *str, wchar_t ch, size_t pos, size_t max_pos)
{
count_t len = wstr_length(str);
size_t len = wstr_length(str);
if ((pos > len) || (pos + 1 > max_pos))
return false;
count_t i;
size_t i;
for (i = len; i + 1 > pos; i--)
str[i + 1] = str[i];
694,14 → 694,14
* is out of bounds.
*
*/
bool wstr_remove(wchar_t *str, count_t pos)
bool wstr_remove(wchar_t *str, size_t pos)
{
count_t len = wstr_length(str);
size_t len = wstr_length(str);
if (pos >= len)
return false;
count_t i;
size_t i;
for (i = pos + 1; i <= len; i++)
str[i - 1] = str[i];
/branches/dd/kernel/generic/src/lib/sort.c
45,8 → 45,8
 
#define EBUFSIZE 32
 
void _qsort(void * data, count_t n, size_t e_size, int (* cmp) (void * a, void * b), void *tmp, void *pivot);
void _bubblesort(void * data, count_t n, size_t e_size, int (* cmp) (void * a, void * b), void *slot);
void _qsort(void * data, size_t n, size_t e_size, int (* cmp) (void * a, void * b), void *tmp, void *pivot);
void _bubblesort(void * data, size_t n, size_t e_size, int (* cmp) (void * a, void * b), void *slot);
 
/** Quicksort wrapper
*
61,7 → 61,7
* @param cmp Comparator function.
*
*/
void qsort(void * data, count_t n, size_t e_size, int (* cmp) (void * a, void * b))
void qsort(void * data, size_t n, size_t e_size, int (* cmp) (void * a, void * b))
{
uint8_t buf_tmp[EBUFSIZE];
uint8_t buf_pivot[EBUFSIZE];
93,7 → 93,7
* @param pivot Pointer to scratch memory buffer e_size bytes long.
*
*/
void _qsort(void * data, count_t n, size_t e_size, int (* cmp) (void * a, void * b), void *tmp, void *pivot)
void _qsort(void * data, size_t n, size_t e_size, int (* cmp) (void * a, void * b), void *tmp, void *pivot)
{
if (n > 4) {
unsigned int i = 0, j = n - 1;
133,7 → 133,7
* @param cmp Comparator function.
*
*/
void bubblesort(void * data, count_t n, size_t e_size, int (* cmp) (void * a, void * b))
void bubblesort(void * data, size_t n, size_t e_size, int (* cmp) (void * a, void * b))
{
uint8_t buf_slot[EBUFSIZE];
void * slot = buf_slot;
160,7 → 160,7
* @param slot Pointer to scratch memory buffer e_size bytes long.
*
*/
void _bubblesort(void * data, count_t n, size_t e_size, int (* cmp) (void * a, void * b), void *slot)
void _bubblesort(void * data, size_t n, size_t e_size, int (* cmp) (void * a, void * b), void *slot)
{
bool done = false;
void * p;
/branches/dd/kernel/generic/src/adt/btree.c
63,9 → 63,9
static void node_remove_key_and_rsubtree(btree_node_t *node, btree_key_t key);
static btree_node_t *node_split(btree_node_t *node, btree_key_t key, void *value, btree_node_t *rsubtree, btree_key_t *median);
static btree_node_t *node_combine(btree_node_t *node);
static index_t find_key_by_subtree(btree_node_t *node, btree_node_t *subtree, bool right);
static void rotate_from_right(btree_node_t *lnode, btree_node_t *rnode, index_t idx);
static void rotate_from_left(btree_node_t *lnode, btree_node_t *rnode, index_t idx);
static size_t find_key_by_subtree(btree_node_t *node, btree_node_t *subtree, bool right);
static void rotate_from_right(btree_node_t *lnode, btree_node_t *rnode, size_t idx);
static void rotate_from_left(btree_node_t *lnode, btree_node_t *rnode, size_t idx);
static bool try_insert_by_rotation_to_left(btree_node_t *node, btree_key_t key, void *value, btree_node_t *rsubtree);
static bool try_insert_by_rotation_to_right(btree_node_t *node, btree_key_t key, void *value, btree_node_t *rsubtree);
static bool try_rotation_from_left(btree_node_t *rnode);
137,7 → 137,7
*/
void btree_destroy_subtree(btree_node_t *root)
{
count_t i;
size_t i;
 
if (root->keys) {
for (i = 0; i < root->keys + 1; i++) {
269,7 → 269,7
}
if (node->keys > FILL_FACTOR) {
count_t i;
size_t i;
 
/*
* The key can be immediatelly removed.
285,7 → 285,7
}
} else {
index_t idx;
size_t idx;
btree_node_t *rnode, *parent;
 
/*
335,7 → 335,7
continue;
} else {
void *val;
count_t i;
size_t i;
/*
* Now if the key is smaller than cur->key[i]
442,11 → 442,11
*/
void node_insert_key_and_lsubtree(btree_node_t *node, btree_key_t key, void *value, btree_node_t *lsubtree)
{
count_t i;
size_t i;
 
for (i = 0; i < node->keys; i++) {
if (key < node->key[i]) {
count_t j;
size_t j;
for (j = node->keys; j > i; j--) {
node->key[j] = node->key[j - 1];
478,11 → 478,11
*/
void node_insert_key_and_rsubtree(btree_node_t *node, btree_key_t key, void *value, btree_node_t *rsubtree)
{
count_t i;
size_t i;
 
for (i = 0; i < node->keys; i++) {
if (key < node->key[i]) {
count_t j;
size_t j;
for (j = node->keys; j > i; j--) {
node->key[j] = node->key[j - 1];
510,7 → 510,7
*/
void node_remove_key_and_lsubtree(btree_node_t *node, btree_key_t key)
{
count_t i, j;
size_t i, j;
for (i = 0; i < node->keys; i++) {
if (key == node->key[i]) {
538,7 → 538,7
*/
void node_remove_key_and_rsubtree(btree_node_t *node, btree_key_t key)
{
count_t i, j;
size_t i, j;
for (i = 0; i < node->keys; i++) {
if (key == node->key[i]) {
576,7 → 576,7
btree_node_t *node_split(btree_node_t *node, btree_key_t key, void *value, btree_node_t *rsubtree, btree_key_t *median)
{
btree_node_t *rnode;
count_t i, j;
size_t i, j;
 
ASSERT(median);
ASSERT(node->keys == BTREE_MAX_KEYS);
603,7 → 603,7
* Copy big keys, values and subtree pointers to the new right sibling.
* If this is an index node, do not copy the median.
*/
i = (count_t) INDEX_NODE(node);
i = (size_t) INDEX_NODE(node);
for (i += MEDIAN_HIGH_INDEX(node), j = 0; i < node->keys; i++, j++) {
rnode->key[j] = node->key[i];
rnode->value[j] = node->value[i];
636,9 → 636,9
*/
btree_node_t *node_combine(btree_node_t *node)
{
index_t idx;
size_t idx;
btree_node_t *rnode;
count_t i;
size_t i;
 
ASSERT(!ROOT_NODE(node));
685,9 → 685,9
*
* @return Index of the key associated with the subtree.
*/
index_t find_key_by_subtree(btree_node_t *node, btree_node_t *subtree, bool right)
size_t find_key_by_subtree(btree_node_t *node, btree_node_t *subtree, bool right)
{
count_t i;
size_t i;
for (i = 0; i < node->keys + 1; i++) {
if (subtree == node->subtree[i])
706,7 → 706,7
* @param rnode Right sibling.
* @param idx Index of the parent node key that is taking part in the rotation.
*/
void rotate_from_left(btree_node_t *lnode, btree_node_t *rnode, index_t idx)
void rotate_from_left(btree_node_t *lnode, btree_node_t *rnode, size_t idx)
{
btree_key_t key;
 
743,7 → 743,7
* @param rnode Right sibling.
* @param idx Index of the parent node key that is taking part in the rotation.
*/
void rotate_from_right(btree_node_t *lnode, btree_node_t *rnode, index_t idx)
void rotate_from_right(btree_node_t *lnode, btree_node_t *rnode, size_t idx)
{
btree_key_t key;
 
786,7 → 786,7
*/
bool try_insert_by_rotation_to_left(btree_node_t *node, btree_key_t inskey, void *insvalue, btree_node_t *rsubtree)
{
index_t idx;
size_t idx;
btree_node_t *lnode;
 
/*
833,7 → 833,7
*/
bool try_insert_by_rotation_to_right(btree_node_t *node, btree_key_t inskey, void *insvalue, btree_node_t *rsubtree)
{
index_t idx;
size_t idx;
btree_node_t *rnode;
 
/*
872,7 → 872,7
*/
bool try_rotation_from_left(btree_node_t *rnode)
{
index_t idx;
size_t idx;
btree_node_t *lnode;
 
/*
907,7 → 907,7
*/
bool try_rotation_from_right(btree_node_t *lnode)
{
index_t idx;
size_t idx;
btree_node_t *rnode;
 
/*
940,7 → 940,7
*/
void btree_print(btree_t *t)
{
count_t i;
size_t i;
int depth = t->root->depth;
link_t head, *cur;
 
/branches/dd/kernel/generic/src/adt/hash_table.c
51,9 → 51,9
* @param max_keys Maximal number of keys needed to identify an item.
* @param op Hash table operations structure.
*/
void hash_table_create(hash_table_t *h, count_t m, count_t max_keys, hash_table_operations_t *op)
void hash_table_create(hash_table_t *h, size_t m, size_t max_keys, hash_table_operations_t *op)
{
index_t i;
size_t i;
 
ASSERT(h);
ASSERT(op);
83,7 → 83,7
*/
void hash_table_insert(hash_table_t *h, unative_t key[], link_t *item)
{
index_t chain;
size_t chain;
ASSERT(item);
ASSERT(h);
107,7 → 107,7
link_t *hash_table_find(hash_table_t *h, unative_t key[])
{
link_t *cur;
index_t chain;
size_t chain;
ASSERT(h);
ASSERT(h->op);
137,9 → 137,9
* @param key Array of keys that will be compared against items of the hash table.
* @param keys Number of keys in the key array.
*/
void hash_table_remove(hash_table_t *h, unative_t key[], count_t keys)
void hash_table_remove(hash_table_t *h, unative_t key[], size_t keys)
{
index_t chain;
size_t chain;
link_t *cur;
ASSERT(h);
/branches/dd/kernel/generic/src/adt/bitmap.c
54,7 → 54,7
* @param map Address of the memory used to hold the map.
* @param bits Number of bits stored in bitmap.
*/
void bitmap_initialize(bitmap_t *bitmap, uint8_t *map, count_t bits)
void bitmap_initialize(bitmap_t *bitmap, uint8_t *map, size_t bits)
{
bitmap->map = map;
bitmap->bits = bits;
66,13 → 66,13
* @param start Starting bit.
* @param bits Number of bits to set.
*/
void bitmap_set_range(bitmap_t *bitmap, index_t start, count_t bits)
void bitmap_set_range(bitmap_t *bitmap, size_t start, size_t bits)
{
index_t i=0;
index_t aligned_start;
count_t lub; /* leading unaligned bits */
count_t amb; /* aligned middle bits */
count_t tab; /* trailing aligned bits */
size_t i = 0;
size_t aligned_start;
size_t lub; /* leading unaligned bits */
size_t amb; /* aligned middle bits */
size_t tab; /* trailing aligned bits */
ASSERT(start + bits <= bitmap->bits);
116,13 → 116,13
* @param start Starting bit.
* @param bits Number of bits to clear.
*/
void bitmap_clear_range(bitmap_t *bitmap, index_t start, count_t bits)
void bitmap_clear_range(bitmap_t *bitmap, size_t start, size_t bits)
{
index_t i=0;
index_t aligned_start;
count_t lub; /* leading unaligned bits */
count_t amb; /* aligned middle bits */
count_t tab; /* trailing aligned bits */
size_t i = 0;
size_t aligned_start;
size_t lub; /* leading unaligned bits */
size_t amb; /* aligned middle bits */
size_t tab; /* trailing aligned bits */
ASSERT(start + bits <= bitmap->bits);
168,9 → 168,9
* @param src Source bitmap.
* @param bits Number of bits to copy.
*/
void bitmap_copy(bitmap_t *dst, bitmap_t *src, count_t bits)
void bitmap_copy(bitmap_t *dst, bitmap_t *src, size_t bits)
{
index_t i;
size_t i;
ASSERT(bits <= dst->bits);
ASSERT(bits <= src->bits);
/branches/dd/kernel/generic/src/mm/slab.c
156,8 → 156,8
slab_cache_t *cache; /**< Pointer to parent cache. */
link_t link; /**< List of full/partial slabs. */
void *start; /**< Start address of first available item. */
count_t available; /**< Count of available items in this slab. */
index_t nextavail; /**< The index of next available item. */
size_t available; /**< Count of available items in this slab. */
size_t nextavail; /**< The index of next available item. */
} slab_t;
 
#ifdef CONFIG_DEBUG
177,7 → 177,7
slab_t *slab;
size_t fsize;
unsigned int i;
count_t zone = 0;
size_t zone = 0;
data = frame_alloc_generic(cache->order, FRAME_KA | flags, &zone);
if (!data) {
215,7 → 215,7
*
* @return number of freed frames
*/
static count_t slab_space_free(slab_cache_t *cache, slab_t *slab)
static size_t slab_space_free(slab_cache_t *cache, slab_t *slab)
{
frame_free(KA2PA(slab->start));
if (! (cache->flags & SLAB_CACHE_SLINSIDE))
243,7 → 243,7
*
* @return Number of freed pages
*/
static count_t slab_obj_destroy(slab_cache_t *cache, void *obj, slab_t *slab)
static size_t slab_obj_destroy(slab_cache_t *cache, void *obj, slab_t *slab)
{
int freed = 0;
 
371,10 → 371,10
*
* @return Number of freed pages
*/
static count_t magazine_destroy(slab_cache_t *cache, slab_magazine_t *mag)
static size_t magazine_destroy(slab_cache_t *cache, slab_magazine_t *mag)
{
unsigned int i;
count_t frames = 0;
size_t frames = 0;
 
for (i = 0; i < mag->busy; i++) {
frames += slab_obj_destroy(cache, mag->objs[i], NULL);
649,11 → 649,11
* @param flags If contains SLAB_RECLAIM_ALL, do aggressive freeing
* @return Number of freed pages
*/
static count_t _slab_reclaim(slab_cache_t *cache, int flags)
static size_t _slab_reclaim(slab_cache_t *cache, int flags)
{
unsigned int i;
slab_magazine_t *mag;
count_t frames = 0;
size_t frames = 0;
int magcount;
if (cache->flags & SLAB_CACHE_NOMAGAZINE)
771,11 → 771,11
}
 
/* Go through all caches and reclaim what is possible */
count_t slab_reclaim(int flags)
size_t slab_reclaim(int flags)
{
slab_cache_t *cache;
link_t *cur;
count_t frames = 0;
size_t frames = 0;
 
spinlock_lock(&slab_cache_lock);
 
/branches/dd/kernel/generic/src/mm/tlb.c
79,7 → 79,7
* @param count Number of pages, if required by type.
*/
void tlb_shootdown_start(tlb_invalidate_type_t type, asid_t asid,
uintptr_t page, count_t count)
uintptr_t page, size_t count)
{
unsigned int i;
 
108,7 → 108,7
/*
* Enqueue the message.
*/
index_t idx = cpu->tlb_messages_count++;
size_t idx = cpu->tlb_messages_count++;
cpu->tlb_messages[idx].type = type;
cpu->tlb_messages[idx].asid = asid;
cpu->tlb_messages[idx].page = page;
143,7 → 143,7
tlb_invalidate_type_t type;
asid_t asid;
uintptr_t page;
count_t count;
size_t count;
unsigned int i;
ASSERT(CPU);
/branches/dd/kernel/generic/src/mm/backend_anon.c
195,7 → 195,7
node = list_get_instance(cur, btree_node_t, leaf_link);
for (i = 0; i < node->keys; i++) {
uintptr_t base = node->key[i];
count_t count = (count_t) node->value[i];
size_t count = (size_t) node->value[i];
unsigned int j;
for (j = 0; j < count; j++) {
/branches/dd/kernel/generic/src/mm/as.c
418,8 → 418,8
btree_node_t, leaf_link);
if ((cond = (bool) node->keys)) {
uintptr_t b = node->key[node->keys - 1];
count_t c =
(count_t) node->value[node->keys - 1];
size_t c =
(size_t) node->value[node->keys - 1];
unsigned int i = 0;
if (overlaps(b, c * PAGE_SIZE, area->base,
555,10 → 555,10
node = list_get_instance(cur, btree_node_t, leaf_link);
for (i = 0; i < node->keys; i++) {
uintptr_t b = node->key[i];
count_t j;
size_t j;
pte_t *pte;
for (j = 0; j < (count_t) node->value[i]; j++) {
for (j = 0; j < (size_t) node->value[i]; j++) {
page_table_lock(as, false);
pte = page_mapping_find(as, b + j * PAGE_SIZE);
ASSERT(pte && PTE_VALID(pte) &&
788,8 → 788,8
ipl_t ipl;
int page_flags;
uintptr_t *old_frame;
index_t frame_idx;
count_t used_pages;
size_t frame_idx;
size_t used_pages;
/* Flags for the new memory mapping */
page_flags = area_flags_to_page_flags(flags);
827,7 → 827,7
node = list_get_instance(cur, btree_node_t, leaf_link);
for (i = 0; i < node->keys; i++) {
used_pages += (count_t) node->value[i];
used_pages += (size_t) node->value[i];
}
}
 
853,10 → 853,10
node = list_get_instance(cur, btree_node_t, leaf_link);
for (i = 0; i < node->keys; i++) {
uintptr_t b = node->key[i];
count_t j;
size_t j;
pte_t *pte;
for (j = 0; j < (count_t) node->value[i]; j++) {
for (j = 0; j < (size_t) node->value[i]; j++) {
page_table_lock(as, false);
pte = page_mapping_find(as, b + j * PAGE_SIZE);
ASSERT(pte && PTE_VALID(pte) &&
903,9 → 903,9
node = list_get_instance(cur, btree_node_t, leaf_link);
for (i = 0; i < node->keys; i++) {
uintptr_t b = node->key[i];
count_t j;
size_t j;
for (j = 0; j < (count_t) node->value[i]; j++) {
for (j = 0; j < (size_t) node->value[i]; j++) {
page_table_lock(as, false);
 
/* Insert the new mapping */
1397,16 → 1397,16
*
* @return Zero on failure and non-zero on success.
*/
int used_space_insert(as_area_t *a, uintptr_t page, count_t count)
int used_space_insert(as_area_t *a, uintptr_t page, size_t count)
{
btree_node_t *leaf, *node;
count_t pages;
size_t pages;
unsigned int i;
 
ASSERT(page == ALIGN_DOWN(page, PAGE_SIZE));
ASSERT(count);
 
pages = (count_t) btree_search(&a->used_space, page, &leaf);
pages = (size_t) btree_search(&a->used_space, page, &leaf);
if (pages) {
/*
* We hit the beginning of some used space.
1423,8 → 1423,8
if (node) {
uintptr_t left_pg = node->key[node->keys - 1];
uintptr_t right_pg = leaf->key[0];
count_t left_cnt = (count_t) node->value[node->keys - 1];
count_t right_cnt = (count_t) leaf->value[0];
size_t left_cnt = (size_t) node->value[node->keys - 1];
size_t right_cnt = (size_t) leaf->value[0];
/*
* Examine the possibility that the interval fits
1478,7 → 1478,7
}
} else if (page < leaf->key[0]) {
uintptr_t right_pg = leaf->key[0];
count_t right_cnt = (count_t) leaf->value[0];
size_t right_cnt = (size_t) leaf->value[0];
/*
* Investigate the border case in which the left neighbour does
1513,8 → 1513,8
if (node) {
uintptr_t left_pg = leaf->key[leaf->keys - 1];
uintptr_t right_pg = node->key[0];
count_t left_cnt = (count_t) leaf->value[leaf->keys - 1];
count_t right_cnt = (count_t) node->value[0];
size_t left_cnt = (size_t) leaf->value[leaf->keys - 1];
size_t right_cnt = (size_t) node->value[0];
/*
* Examine the possibility that the interval fits
1568,7 → 1568,7
}
} else if (page >= leaf->key[leaf->keys - 1]) {
uintptr_t left_pg = leaf->key[leaf->keys - 1];
count_t left_cnt = (count_t) leaf->value[leaf->keys - 1];
size_t left_cnt = (size_t) leaf->value[leaf->keys - 1];
/*
* Investigate the border case in which the right neighbour
1606,8 → 1606,8
if (page < leaf->key[i]) {
uintptr_t left_pg = leaf->key[i - 1];
uintptr_t right_pg = leaf->key[i];
count_t left_cnt = (count_t) leaf->value[i - 1];
count_t right_cnt = (count_t) leaf->value[i];
size_t left_cnt = (size_t) leaf->value[i - 1];
size_t right_cnt = (size_t) leaf->value[i];
 
/*
* The interval fits between left_pg and right_pg.
1665,7 → 1665,7
}
}
 
panic("Inconsistency detected while adding %" PRIc " pages of used "
panic("Inconsistency detected while adding %" PRIs " pages of used "
"space at %p.", count, page);
}
 
1679,16 → 1679,16
*
* @return Zero on failure and non-zero on success.
*/
int used_space_remove(as_area_t *a, uintptr_t page, count_t count)
int used_space_remove(as_area_t *a, uintptr_t page, size_t count)
{
btree_node_t *leaf, *node;
count_t pages;
size_t pages;
unsigned int i;
 
ASSERT(page == ALIGN_DOWN(page, PAGE_SIZE));
ASSERT(count);
 
pages = (count_t) btree_search(&a->used_space, page, &leaf);
pages = (size_t) btree_search(&a->used_space, page, &leaf);
if (pages) {
/*
* We are lucky, page is the beginning of some interval.
1717,7 → 1717,7
node = btree_leaf_node_left_neighbour(&a->used_space, leaf);
if (node && page < leaf->key[0]) {
uintptr_t left_pg = node->key[node->keys - 1];
count_t left_cnt = (count_t) node->value[node->keys - 1];
size_t left_cnt = (size_t) node->value[node->keys - 1];
 
if (overlaps(left_pg, left_cnt * PAGE_SIZE, page,
count * PAGE_SIZE)) {
1733,7 → 1733,7
return 1;
} else if (page + count * PAGE_SIZE <
left_pg + left_cnt*PAGE_SIZE) {
count_t new_cnt;
size_t new_cnt;
/*
* The interval is contained in the rightmost
1757,7 → 1757,7
if (page > leaf->key[leaf->keys - 1]) {
uintptr_t left_pg = leaf->key[leaf->keys - 1];
count_t left_cnt = (count_t) leaf->value[leaf->keys - 1];
size_t left_cnt = (size_t) leaf->value[leaf->keys - 1];
 
if (overlaps(left_pg, left_cnt * PAGE_SIZE, page,
count * PAGE_SIZE)) {
1772,7 → 1772,7
return 1;
} else if (page + count * PAGE_SIZE < left_pg +
left_cnt * PAGE_SIZE) {
count_t new_cnt;
size_t new_cnt;
/*
* The interval is contained in the rightmost
1799,7 → 1799,7
for (i = 1; i < leaf->keys - 1; i++) {
if (page < leaf->key[i]) {
uintptr_t left_pg = leaf->key[i - 1];
count_t left_cnt = (count_t) leaf->value[i - 1];
size_t left_cnt = (size_t) leaf->value[i - 1];
 
/*
* Now the interval is between intervals corresponding
1819,7 → 1819,7
return 1;
} else if (page + count * PAGE_SIZE <
left_pg + left_cnt * PAGE_SIZE) {
count_t new_cnt;
size_t new_cnt;
/*
* The interval is contained in the
1844,7 → 1844,7
}
 
error:
panic("Inconsistency detected while removing %" PRIc " pages of used "
panic("Inconsistency detected while removing %" PRIs " pages of used "
"space from %p.", count, page);
}
 
1943,7 → 1943,7
as_area_t *area = node->value[i];
mutex_lock(&area->lock);
printf("as_area: %p, base=%p, pages=%" PRIc
printf("as_area: %p, base=%p, pages=%" PRIs
" (%p - %p)\n", area, area->base, area->pages,
area->base, area->base + FRAMES2SIZE(area->pages));
mutex_unlock(&area->lock);
/branches/dd/kernel/generic/src/mm/frame.c
67,29 → 67,29
*/
mutex_t mem_avail_mtx;
condvar_t mem_avail_cv;
count_t mem_avail_req = 0; /**< Number of frames requested. */
count_t mem_avail_gen = 0; /**< Generation counter. */
size_t mem_avail_req = 0; /**< Number of frames requested. */
size_t mem_avail_gen = 0; /**< Generation counter. */
 
/********************/
/* Helper functions */
/********************/
 
static inline index_t frame_index(zone_t *zone, frame_t *frame)
static inline size_t frame_index(zone_t *zone, frame_t *frame)
{
return (index_t) (frame - zone->frames);
return (size_t) (frame - zone->frames);
}
 
static inline index_t frame_index_abs(zone_t *zone, frame_t *frame)
static inline size_t frame_index_abs(zone_t *zone, frame_t *frame)
{
return (index_t) (frame - zone->frames) + zone->base;
return (size_t) (frame - zone->frames) + zone->base;
}
 
static inline bool frame_index_valid(zone_t *zone, index_t index)
static inline bool frame_index_valid(zone_t *zone, size_t index)
{
return (index < zone->count);
}
 
static inline index_t make_frame_index(zone_t *zone, frame_t *frame)
static inline size_t make_frame_index(zone_t *zone, frame_t *frame)
{
return (frame - zone->frames);
}
120,20 → 120,20
* @return Zone number on success, -1 on error.
*
*/
static count_t zones_insert_zone(pfn_t base, count_t count)
static size_t zones_insert_zone(pfn_t base, size_t count)
{
if (zones.count + 1 == ZONES_MAX) {
printf("Maximum zone count %u exceeded!\n", ZONES_MAX);
return (count_t) -1;
return (size_t) -1;
}
count_t i;
size_t i;
for (i = 0; i < zones.count; i++) {
/* Check for overlap */
if (overlaps(base, count,
zones.info[i].base, zones.info[i].count)) {
printf("Zones overlap!\n");
return (count_t) -1;
return (size_t) -1;
}
if (base < zones.info[i].base)
break;
140,7 → 140,7
}
/* Move other zones up */
count_t j;
size_t j;
for (j = zones.count; j > i; j--) {
zones.info[j] = zones.info[j - 1];
zones.info[j].buddy_system->data =
161,10 → 161,10
*
*/
#ifdef CONFIG_DEBUG
static count_t total_frames_free(void)
static size_t total_frames_free(void)
{
count_t total = 0;
count_t i;
size_t total = 0;
size_t i;
for (i = 0; i < zones.count; i++)
total += zones.info[i].free_count;
184,12 → 184,12
* @return Zone index or -1 if not found.
*
*/
count_t find_zone(pfn_t frame, count_t count, count_t hint)
size_t find_zone(pfn_t frame, size_t count, size_t hint)
{
if (hint >= zones.count)
hint = 0;
count_t i = hint;
size_t i = hint;
do {
if ((zones.info[i].base <= frame)
&& (zones.info[i].base + zones.info[i].count >= frame + count))
200,7 → 200,7
i = 0;
} while (i != hint);
return (count_t) -1;
return (size_t) -1;
}
 
/** @return True if zone can allocate specified order */
220,12 → 220,12
* @param hind Preferred zone.
*
*/
static count_t find_free_zone(uint8_t order, zone_flags_t flags, count_t hint)
static size_t find_free_zone(uint8_t order, zone_flags_t flags, size_t hint)
{
if (hint >= zones.count)
hint = 0;
count_t i = hint;
size_t i = hint;
do {
/*
* Check whether the zone meets the search criteria.
243,7 → 243,7
i = 0;
} while (i != hint);
return (count_t) -1;
return (size_t) -1;
}
 
/**************************/
265,7 → 265,7
frame_t *frame = list_get_instance(child, frame_t, buddy_link);
zone_t *zone = (zone_t *) buddy->data;
index_t index = frame_index(zone, frame);
size_t index = frame_index(zone, frame);
do {
if (zone->frames[index].buddy_order != order)
return &zone->frames[index].buddy_link;
291,7 → 291,7
bool is_left = IS_BUDDY_LEFT_BLOCK_ABS(zone, frame);
index_t index;
size_t index;
if (is_left) {
index = (frame_index(zone, frame)) +
(1 << frame->buddy_order);
446,7 → 446,7
* @param frame_idx Frame index relative to zone.
*
*/
static void zone_frame_free(zone_t *zone, index_t frame_idx)
static void zone_frame_free(zone_t *zone, size_t frame_idx)
{
ASSERT(zone_flags_available(zone->flags));
467,7 → 467,7
}
 
/** Return frame from zone. */
static frame_t *zone_get_frame(zone_t *zone, index_t frame_idx)
static frame_t *zone_get_frame(zone_t *zone, size_t frame_idx)
{
ASSERT(frame_idx < zone->count);
return &zone->frames[frame_idx];
474,7 → 474,7
}
 
/** Mark frame in zone unavailable to allocation. */
static void zone_mark_unavailable(zone_t *zone, index_t frame_idx)
static void zone_mark_unavailable(zone_t *zone, size_t frame_idx)
{
ASSERT(zone_flags_available(zone->flags));
503,7 → 503,7
* @param buddy Merged zone buddy.
*
*/
static void zone_merge_internal(count_t z1, count_t z2, zone_t *old_z1, buddy_system_t *buddy)
static void zone_merge_internal(size_t z1, size_t z2, zone_t *old_z1, buddy_system_t *buddy)
{
ASSERT(zone_flags_available(zones.info[z1].flags));
ASSERT(zone_flags_available(zones.info[z2].flags));
529,7 → 529,7
+ buddy_conf_size(order));
/* This marks all frames busy */
count_t i;
size_t i;
for (i = 0; i < zones.info[z1].count; i++)
frame_initialize(&zones.info[z1].frames[i]);
599,11 → 599,11
* @param count Old zone frame count.
*
*/
static void return_config_frames(count_t znum, pfn_t pfn, count_t count)
static void return_config_frames(size_t znum, pfn_t pfn, size_t count)
{
ASSERT(zone_flags_available(zones.info[znum].flags));
count_t cframes = SIZE2FRAMES(zone_conf_size(count));
size_t cframes = SIZE2FRAMES(zone_conf_size(count));
if ((pfn < zones.info[znum].base)
|| (pfn >= zones.info[znum].base + zones.info[znum].count))
614,7 → 614,7
frame = &zones.info[znum].frames[pfn - zones.info[znum].base];
ASSERT(!frame->buddy_order);
count_t i;
size_t i;
for (i = 0; i < cframes; i++) {
zones.info[znum].busy_count++;
zone_frame_free(&zones.info[znum],
634,17 → 634,17
* @param count Allocated frames in block.
*
*/
static void zone_reduce_region(count_t znum, pfn_t frame_idx, count_t count)
static void zone_reduce_region(size_t znum, pfn_t frame_idx, size_t count)
{
ASSERT(zone_flags_available(zones.info[znum].flags));
ASSERT(frame_idx + count < zones.info[znum].count);
uint8_t order = zones.info[znum].frames[frame_idx].buddy_order;
ASSERT((count_t) (1 << order) >= count);
ASSERT((size_t) (1 << order) >= count);
/* Reduce all blocks to order 0 */
count_t i;
for (i = 0; i < (count_t) (1 << order); i++) {
size_t i;
for (i = 0; i < (size_t) (1 << order); i++) {
frame_t *frame = &zones.info[znum].frames[i + frame_idx];
frame->buddy_order = 0;
if (!frame->refcount)
653,7 → 653,7
}
/* Free unneeded frames */
for (i = count; i < (count_t) (1 << order); i++)
for (i = count; i < (size_t) (1 << order); i++)
zone_frame_free(&zones.info[znum], i + frame_idx);
}
 
670,7 → 670,7
* The function uses
*
*/
bool zone_merge(count_t z1, count_t z2)
bool zone_merge(size_t z1, size_t z2)
{
ipl_t ipl = interrupts_disable();
spinlock_lock(&zones.lock);
733,7 → 733,7
zones.info[z2].count);
/* Move zones down */
count_t i;
size_t i;
for (i = z2 + 1; i < zones.count; i++) {
zones.info[i - 1] = zones.info[i];
zones.info[i - 1].buddy_system->data =
758,7 → 758,7
*/
void zone_merge_all(void)
{
count_t i = 0;
size_t i = 0;
while (i < zones.count) {
if (!zone_merge(i, i + 1))
i++;
776,7 → 776,7
* @return Initialized zone.
*
*/
static void zone_construct(zone_t *zone, buddy_system_t *buddy, pfn_t start, count_t count, zone_flags_t flags)
static void zone_construct(zone_t *zone, buddy_system_t *buddy, pfn_t start, size_t count, zone_flags_t flags)
{
zone->base = start;
zone->count = count;
799,7 → 799,7
zone->frames = (frame_t *) ((uint8_t *) zone->buddy_system +
buddy_conf_size(order));
count_t i;
size_t i;
for (i = 0; i < count; i++)
frame_initialize(&zone->frames[i]);
819,7 → 819,7
* @return Size of zone configuration info (in bytes).
*
*/
uintptr_t zone_conf_size(count_t count)
uintptr_t zone_conf_size(size_t count)
{
return (count * sizeof(frame_t) + buddy_conf_size(fnzb(count)));
}
840,7 → 840,7
* @return Zone number or -1 on error.
*
*/
count_t zone_create(pfn_t start, count_t count, pfn_t confframe, zone_flags_t flags)
size_t zone_create(pfn_t start, size_t count, pfn_t confframe, zone_flags_t flags)
{
ipl_t ipl = interrupts_disable();
spinlock_lock(&zones.lock);
855,7 → 855,7
/* If confframe is supposed to be inside our zone, then make sure
* it does not span kernel & init
*/
count_t confcount = SIZE2FRAMES(zone_conf_size(count));
size_t confcount = SIZE2FRAMES(zone_conf_size(count));
if ((confframe >= start) && (confframe < start + count)) {
for (; confframe < start + count; confframe++) {
uintptr_t addr = PFN2ADDR(confframe);
868,7 → 868,7
continue;
bool overlap = false;
count_t i;
size_t i;
for (i = 0; i < init.cnt; i++)
if (overlaps(addr, PFN2ADDR(confcount),
KA2PA(init.tasks[i].addr),
886,11 → 886,11
panic("Cannot find configuration data for zone.");
}
count_t znum = zones_insert_zone(start, count);
if (znum == (count_t) -1) {
size_t znum = zones_insert_zone(start, count);
if (znum == (size_t) -1) {
spinlock_unlock(&zones.lock);
interrupts_restore(ipl);
return (count_t) -1;
return (size_t) -1;
}
buddy_system_t *buddy = (buddy_system_t *) PA2KA(PFN2ADDR(confframe));
898,7 → 898,7
/* If confdata in zone, mark as unavailable */
if ((confframe >= start) && (confframe < start + count)) {
count_t i;
size_t i;
for (i = confframe; i < confframe + confcount; i++)
zone_mark_unavailable(&zones.info[znum],
i - zones.info[znum].base);
911,11 → 911,11
}
/* Non-available zone */
count_t znum = zones_insert_zone(start, count);
if (znum == (count_t) -1) {
size_t znum = zones_insert_zone(start, count);
if (znum == (size_t) -1) {
spinlock_unlock(&zones.lock);
interrupts_restore(ipl);
return (count_t) -1;
return (size_t) -1;
}
zone_construct(&zones.info[znum], NULL, start, count, flags);
930,14 → 930,14
/*******************/
 
/** Set parent of frame. */
void frame_set_parent(pfn_t pfn, void *data, count_t hint)
void frame_set_parent(pfn_t pfn, void *data, size_t hint)
{
ipl_t ipl = interrupts_disable();
spinlock_lock(&zones.lock);
count_t znum = find_zone(pfn, 1, hint);
size_t znum = find_zone(pfn, 1, hint);
ASSERT(znum != (count_t) -1);
ASSERT(znum != (size_t) -1);
zone_get_frame(&zones.info[znum],
pfn - zones.info[znum].base)->parent = data;
946,14 → 946,14
interrupts_restore(ipl);
}
 
void *frame_get_parent(pfn_t pfn, count_t hint)
void *frame_get_parent(pfn_t pfn, size_t hint)
{
ipl_t ipl = interrupts_disable();
spinlock_lock(&zones.lock);
count_t znum = find_zone(pfn, 1, hint);
size_t znum = find_zone(pfn, 1, hint);
ASSERT(znum != (count_t) -1);
ASSERT(znum != (size_t) -1);
void *res = zone_get_frame(&zones.info[znum],
pfn - zones.info[znum].base)->parent;
973,11 → 973,11
* @return Physical address of the allocated frame.
*
*/
void *frame_alloc_generic(uint8_t order, frame_flags_t flags, count_t *pzone)
void *frame_alloc_generic(uint8_t order, frame_flags_t flags, size_t *pzone)
{
count_t size = ((count_t) 1) << order;
size_t size = ((size_t) 1) << order;
ipl_t ipl;
count_t hint = pzone ? (*pzone) : 0;
size_t hint = pzone ? (*pzone) : 0;
loop:
ipl = interrupts_disable();
986,16 → 986,16
/*
* First, find suitable frame zone.
*/
count_t znum = find_free_zone(order,
size_t znum = find_free_zone(order,
FRAME_TO_ZONE_FLAGS(flags), hint);
/* If no memory, reclaim some slab memory,
if it does not help, reclaim all */
if ((znum == (count_t) -1) && (!(flags & FRAME_NO_RECLAIM))) {
if ((znum == (size_t) -1) && (!(flags & FRAME_NO_RECLAIM))) {
spinlock_unlock(&zones.lock);
interrupts_restore(ipl);
count_t freed = slab_reclaim(0);
size_t freed = slab_reclaim(0);
ipl = interrupts_disable();
spinlock_lock(&zones.lock);
1004,7 → 1004,7
znum = find_free_zone(order,
FRAME_TO_ZONE_FLAGS(flags), hint);
if (znum == (count_t) -1) {
if (znum == (size_t) -1) {
spinlock_unlock(&zones.lock);
interrupts_restore(ipl);
1019,7 → 1019,7
}
}
if (znum == (count_t) -1) {
if (znum == (size_t) -1) {
if (flags & FRAME_ATOMIC) {
spinlock_unlock(&zones.lock);
interrupts_restore(ipl);
1027,7 → 1027,7
}
#ifdef CONFIG_DEBUG
count_t avail = total_frames_free();
size_t avail = total_frames_free();
#endif
spinlock_unlock(&zones.lock);
1038,8 → 1038,8
*/
#ifdef CONFIG_DEBUG
printf("Thread %" PRIu64 " waiting for %" PRIc " frames, "
"%" PRIc " available.\n", THREAD->tid, size, avail);
printf("Thread %" PRIu64 " waiting for %" PRIs " frames, "
"%" PRIs " available.\n", THREAD->tid, size, avail);
#endif
mutex_lock(&mem_avail_mtx);
1048,7 → 1048,7
mem_avail_req = min(mem_avail_req, size);
else
mem_avail_req = size;
count_t gen = mem_avail_gen;
size_t gen = mem_avail_gen;
while (gen == mem_avail_gen)
condvar_wait(&mem_avail_cv, &mem_avail_mtx);
1095,9 → 1095,9
* First, find host frame zone for addr.
*/
pfn_t pfn = ADDR2PFN(frame);
count_t znum = find_zone(pfn, 1, NULL);
size_t znum = find_zone(pfn, 1, NULL);
ASSERT(znum != (count_t) -1);
ASSERT(znum != (size_t) -1);
zone_frame_free(&zones.info[znum], pfn - zones.info[znum].base);
1134,9 → 1134,9
/*
* First, find host frame zone for addr.
*/
count_t znum = find_zone(pfn, 1, NULL);
size_t znum = find_zone(pfn, 1, NULL);
ASSERT(znum != (count_t) -1);
ASSERT(znum != (size_t) -1);
zones.info[znum].frames[pfn - zones.info[znum].base].refcount++;
1145,15 → 1145,15
}
 
/** Mark given range unavailable in frame zones. */
void frame_mark_unavailable(pfn_t start, count_t count)
void frame_mark_unavailable(pfn_t start, size_t count)
{
ipl_t ipl = interrupts_disable();
spinlock_lock(&zones.lock);
count_t i;
size_t i;
for (i = 0; i < count; i++) {
count_t znum = find_zone(start + i, 1, 0);
if (znum == (count_t) -1) /* PFN not found */
size_t znum = find_zone(start + i, 1, 0);
if (znum == (size_t) -1) /* PFN not found */
continue;
zone_mark_unavailable(&zones.info[znum],
1182,7 → 1182,7
frame_mark_unavailable(ADDR2PFN(KA2PA(config.stack_base)),
SIZE2FRAMES(config.stack_size));
count_t i;
size_t i;
for (i = 0; i < init.cnt; i++) {
pfn_t pfn = ADDR2PFN(KA2PA(init.tasks[i].addr));
frame_mark_unavailable(pfn,
1207,7 → 1207,7
spinlock_lock(&zones.lock);
uint64_t total = 0;
count_t i;
size_t i;
for (i = 0; i < zones.count; i++)
total += (uint64_t) FRAMES2SIZE(zones.info[i].count);
1241,7 → 1241,7
* the listing).
*/
count_t i;
size_t i;
for (i = 0;; i++) {
ipl_t ipl = interrupts_disable();
spinlock_lock(&zones.lock);
1253,10 → 1253,10
}
uintptr_t base = PFN2ADDR(zones.info[i].base);
count_t count = zones.info[i].count;
size_t count = zones.info[i].count;
zone_flags_t flags = zones.info[i].flags;
count_t free_count = zones.info[i].free_count;
count_t busy_count = zones.info[i].busy_count;
size_t free_count = zones.info[i].free_count;
size_t busy_count = zones.info[i].busy_count;
spinlock_unlock(&zones.lock);
interrupts_restore(ipl);
1263,7 → 1263,7
bool available = zone_flags_available(flags);
printf("%-2" PRIc, i);
printf("%-2" PRIs, i);
#ifdef __32_BITS__
printf(" %10p", base);
1273,13 → 1273,13
printf(" %18p", base);
#endif
printf(" %12" PRIc " %c%c%c ", count,
printf(" %12" PRIs " %c%c%c ", count,
available ? 'A' : ' ',
(flags & ZONE_RESERVED) ? 'R' : ' ',
(flags & ZONE_FIRMWARE) ? 'F' : ' ');
if (available)
printf("%12" PRIc " %12" PRIc,
printf("%12" PRIs " %12" PRIs,
free_count, busy_count);
printf("\n");
1291,13 → 1291,13
* @param num Zone base address or zone number.
*
*/
void zone_print_one(count_t num)
void zone_print_one(size_t num)
{
ipl_t ipl = interrupts_disable();
spinlock_lock(&zones.lock);
count_t znum = (count_t) -1;
size_t znum = (size_t) -1;
count_t i;
size_t i;
for (i = 0; i < zones.count; i++) {
if ((i == num) || (PFN2ADDR(zones.info[i].base) == num)) {
znum = i;
1305,7 → 1305,7
}
}
if (znum == (count_t) -1) {
if (znum == (size_t) -1) {
spinlock_unlock(&zones.lock);
interrupts_restore(ipl);
printf("Zone not found.\n");
1314,9 → 1314,9
uintptr_t base = PFN2ADDR(zones.info[i].base);
zone_flags_t flags = zones.info[i].flags;
count_t count = zones.info[i].count;
count_t free_count = zones.info[i].free_count;
count_t busy_count = zones.info[i].busy_count;
size_t count = zones.info[i].count;
size_t free_count = zones.info[i].free_count;
size_t busy_count = zones.info[i].busy_count;
spinlock_unlock(&zones.lock);
interrupts_restore(ipl);
1323,9 → 1323,9
bool available = zone_flags_available(flags);
printf("Zone number: %" PRIc "\n", znum);
printf("Zone number: %" PRIs "\n", znum);
printf("Zone base address: %p\n", base);
printf("Zone size: %" PRIc " frames (%" PRIs " KiB)\n", count,
printf("Zone size: %" PRIs " frames (%" PRIs " KiB)\n", count,
SIZE2KB(FRAMES2SIZE(count)));
printf("Zone flags: %c%c%c\n",
available ? 'A' : ' ',
1333,9 → 1333,9
(flags & ZONE_FIRMWARE) ? 'F' : ' ');
if (available) {
printf("Allocated space: %" PRIc " frames (%" PRIs " KiB)\n",
printf("Allocated space: %" PRIs " frames (%" PRIs " KiB)\n",
busy_count, SIZE2KB(FRAMES2SIZE(busy_count)));
printf("Available space: %" PRIc " frames (%" PRIs " KiB)\n",
printf("Available space: %" PRIs " frames (%" PRIs " KiB)\n",
free_count, SIZE2KB(FRAMES2SIZE(free_count)));
}
}
/branches/dd/kernel/generic/src/mm/backend_elf.c
82,7 → 82,7
elf_segment_header_t *entry = area->backend_data.segment;
btree_node_t *leaf;
uintptr_t base, frame, page, start_anon;
index_t i;
size_t i;
bool dirty = false;
 
if (!as_area_check_access(area, access))
234,7 → 234,7
elf_header_t *elf = area->backend_data.elf;
elf_segment_header_t *entry = area->backend_data.segment;
uintptr_t base, start_anon;
index_t i;
size_t i;
 
ASSERT((page >= ALIGN_DOWN(entry->p_vaddr, PAGE_SIZE)) &&
(page < entry->p_vaddr + entry->p_memsz));
304,7 → 304,7
for (i = 0; i < node->keys; i++) {
uintptr_t base = node->key[i];
count_t count = (count_t) node->value[i];
size_t count = (size_t) node->value[i];
unsigned int j;
/*
/branches/dd/kernel/generic/src/ipc/event.c
64,8 → 64,8
}
}
 
static int
event_subscribe(event_type_t evno, unative_t method, answerbox_t *answerbox)
static int event_subscribe(event_type_t evno, unative_t method,
answerbox_t *answerbox)
{
if (evno >= EVENT_END)
return ELIMIT;
122,8 → 122,7
}
}
 
void
event_notify(event_type_t evno, unative_t a1, unative_t a2, unative_t a3,
void event_notify(event_type_t evno, unative_t a1, unative_t a2, unative_t a3,
unative_t a4, unative_t a5)
{
ASSERT(evno < EVENT_END);
/branches/dd/kernel/generic/src/ipc/sysipc.c
336,6 → 336,26
return 0;
}
 
static void phones_lock(phone_t *p1, phone_t *p2)
{
if (p1 < p2) {
mutex_lock(&p1->lock);
mutex_lock(&p2->lock);
} else if (p1 > p2) {
mutex_lock(&p2->lock);
mutex_lock(&p1->lock);
} else {
mutex_lock(&p1->lock);
}
}
 
static void phones_unlock(phone_t *p1, phone_t *p2)
{
mutex_unlock(&p1->lock);
if (p1 != p2)
mutex_unlock(&p2->lock);
}
 
/** Called before the request is sent.
*
* @param call Call structure with the request.
355,20 → 375,10
phone_t *cloned_phone;
GET_CHECK_PHONE(cloned_phone, IPC_GET_ARG1(call->data),
return ENOENT);
if (cloned_phone < phone) {
mutex_lock(&cloned_phone->lock);
mutex_lock(&phone->lock);
} else if (cloned_phone > phone) {
mutex_lock(&phone->lock);
mutex_lock(&cloned_phone->lock);
} else {
mutex_lock(&phone->lock);
}
phones_lock(cloned_phone, phone);
if ((cloned_phone->state != IPC_PHONE_CONNECTED) ||
phone->state != IPC_PHONE_CONNECTED) {
if (cloned_phone != phone)
mutex_unlock(&cloned_phone->lock);
mutex_unlock(&phone->lock);
phones_unlock(cloned_phone, phone);
return EINVAL;
}
/*
379,16 → 389,12
*/
newphid = phone_alloc(phone->callee->task);
if (newphid < 0) {
if (cloned_phone != phone)
mutex_unlock(&cloned_phone->lock);
mutex_unlock(&phone->lock);
phones_unlock(cloned_phone, phone);
return ELIMIT;
}
ipc_phone_connect(&phone->callee->task->phones[newphid],
cloned_phone->callee);
if (cloned_phone != phone)
mutex_unlock(&cloned_phone->lock);
mutex_unlock(&phone->lock);
phones_unlock(cloned_phone, phone);
/* Set the new phone for the callee. */
IPC_SET_ARG1(call->data, newphid);
break;
/branches/dd/kernel/arch/sparc64/include/types.h
46,8 → 46,6
typedef unsigned long uint64_t;
 
typedef uint64_t size_t;
typedef uint64_t count_t;
typedef uint64_t index_t;
 
typedef uint64_t uintptr_t;
typedef uint64_t pfn_t;
60,11 → 58,9
typedef struct {
} fncptr_t;
 
/**< Formats for uintptr_t, size_t, count_t and index_t */
/**< Formats for uintptr_t, size_t */
#define PRIp "llx"
#define PRIs "llu"
#define PRIc "llu"
#define PRIi "llu"
 
/**< Formats for (u)int8_t, (u)int16_t, (u)int32_t, (u)int64_t and (u)native_t */
#define PRId8 "d"
/branches/dd/kernel/arch/sparc64/include/mm/tlb.h
322,7 → 322,7
* @return Current value of specified IMMU TLB Data Access
* Register.
*/
static inline uint64_t itlb_data_access_read(index_t entry)
static inline uint64_t itlb_data_access_read(size_t entry)
{
itlb_data_access_addr_t reg;
336,7 → 336,7
* @param entry TLB Entry index.
* @param value Value to be written.
*/
static inline void itlb_data_access_write(index_t entry, uint64_t value)
static inline void itlb_data_access_write(size_t entry, uint64_t value)
{
itlb_data_access_addr_t reg;
353,7 → 353,7
* @return Current value of specified DMMU TLB Data Access
* Register.
*/
static inline uint64_t dtlb_data_access_read(index_t entry)
static inline uint64_t dtlb_data_access_read(size_t entry)
{
dtlb_data_access_addr_t reg;
367,7 → 367,7
* @param entry TLB Entry index.
* @param value Value to be written.
*/
static inline void dtlb_data_access_write(index_t entry, uint64_t value)
static inline void dtlb_data_access_write(size_t entry, uint64_t value)
{
dtlb_data_access_addr_t reg;
383,7 → 383,7
*
* @return Current value of specified IMMU TLB Tag Read Register.
*/
static inline uint64_t itlb_tag_read_read(index_t entry)
static inline uint64_t itlb_tag_read_read(size_t entry)
{
itlb_tag_read_addr_t tag;
 
398,7 → 398,7
*
* @return Current value of specified DMMU TLB Tag Read Register.
*/
static inline uint64_t dtlb_tag_read_read(index_t entry)
static inline uint64_t dtlb_tag_read_read(size_t entry)
{
dtlb_tag_read_addr_t tag;
 
418,7 → 418,7
* @return Current value of specified IMMU TLB Data Access
* Register.
*/
static inline uint64_t itlb_data_access_read(int tlb, index_t entry)
static inline uint64_t itlb_data_access_read(int tlb, size_t entry)
{
itlb_data_access_addr_t reg;
433,7 → 433,7
* @param entry TLB Entry index.
* @param value Value to be written.
*/
static inline void itlb_data_access_write(int tlb, index_t entry,
static inline void itlb_data_access_write(int tlb, size_t entry,
uint64_t value)
{
itlb_data_access_addr_t reg;
453,7 → 453,7
* @return Current value of specified DMMU TLB Data Access
* Register.
*/
static inline uint64_t dtlb_data_access_read(int tlb, index_t entry)
static inline uint64_t dtlb_data_access_read(int tlb, size_t entry)
{
dtlb_data_access_addr_t reg;
469,7 → 469,7
* @param entry TLB Entry index.
* @param value Value to be written.
*/
static inline void dtlb_data_access_write(int tlb, index_t entry,
static inline void dtlb_data_access_write(int tlb, size_t entry,
uint64_t value)
{
dtlb_data_access_addr_t reg;
488,7 → 488,7
*
* @return Current value of specified IMMU TLB Tag Read Register.
*/
static inline uint64_t itlb_tag_read_read(int tlb, index_t entry)
static inline uint64_t itlb_tag_read_read(int tlb, size_t entry)
{
itlb_tag_read_addr_t tag;
 
505,7 → 505,7
*
* @return Current value of specified DMMU TLB Tag Read Register.
*/
static inline uint64_t dtlb_tag_read_read(int tlb, index_t entry)
static inline uint64_t dtlb_tag_read_read(int tlb, size_t entry)
{
dtlb_tag_read_addr_t tag;
 
/branches/dd/kernel/arch/sparc64/include/mm/tsb.h
160,9 → 160,9
struct as;
struct pte;
 
extern void tsb_invalidate(struct as *as, uintptr_t page, count_t pages);
extern void itsb_pte_copy(struct pte *t, index_t index);
extern void dtsb_pte_copy(struct pte *t, index_t index, bool ro);
extern void tsb_invalidate(struct as *as, uintptr_t page, size_t pages);
extern void itsb_pte_copy(struct pte *t, size_t index);
extern void dtsb_pte_copy(struct pte *t, size_t index, bool ro);
 
#endif /* !def __ASM__ */
 
/branches/dd/kernel/arch/sparc64/src/smp/smp.c
61,7 → 61,7
void smp_init(void)
{
ofw_tree_node_t *node;
count_t cnt = 0;
size_t cnt = 0;
if (is_us() || is_us_iii()) {
node = ofw_tree_find_child_by_device_type(cpus_parent(), "cpu");
/branches/dd/kernel/arch/sparc64/src/mm/tlb.c
54,8 → 54,8
#include <arch/mm/tsb.h>
#endif
 
static void dtlb_pte_copy(pte_t *, index_t, bool);
static void itlb_pte_copy(pte_t *, index_t);
static void dtlb_pte_copy(pte_t *, size_t, bool);
static void itlb_pte_copy(pte_t *, size_t);
static void do_fast_instruction_access_mmu_miss_fault(istate_t *, const char *);
static void do_fast_data_access_mmu_miss_fault(istate_t *, tlb_tag_access_reg_t,
const char *);
130,7 → 130,7
* @param ro If true, the entry will be created read-only, regardless
* of its w field.
*/
void dtlb_pte_copy(pte_t *t, index_t index, bool ro)
void dtlb_pte_copy(pte_t *t, size_t index, bool ro)
{
tlb_tag_access_reg_t tag;
tlb_data_t data;
167,7 → 167,7
* @param t Page Table Entry to be copied.
* @param index Zero if lower 8K-subpage, one if higher 8K-subpage.
*/
void itlb_pte_copy(pte_t *t, index_t index)
void itlb_pte_copy(pte_t *t, size_t index)
{
tlb_tag_access_reg_t tag;
tlb_data_t data;
200,7 → 200,7
void fast_instruction_access_mmu_miss(unative_t unused, istate_t *istate)
{
uintptr_t page_16k = ALIGN_DOWN(istate->tpc, PAGE_SIZE);
index_t index = (istate->tpc >> MMU_PAGE_WIDTH) % MMU_PAGES_PER_PAGE;
size_t index = (istate->tpc >> MMU_PAGE_WIDTH) % MMU_PAGES_PER_PAGE;
pte_t *t;
 
page_table_lock(AS, true);
245,7 → 245,7
{
uintptr_t page_8k;
uintptr_t page_16k;
index_t index;
size_t index;
pte_t *t;
 
page_8k = (uint64_t) tag.vpn << MMU_PAGE_WIDTH;
309,7 → 309,7
void fast_data_access_protection(tlb_tag_access_reg_t tag, istate_t *istate)
{
uintptr_t page_16k;
index_t index;
size_t index;
pte_t *t;
 
page_16k = ALIGN_DOWN((uint64_t) tag.vpn << MMU_PAGE_WIDTH, PAGE_SIZE);
579,7 → 579,7
* @param page First page which to sweep out from ITLB and DTLB.
* @param cnt Number of ITLB and DTLB entries to invalidate.
*/
void tlb_invalidate_pages(asid_t asid, uintptr_t page, count_t cnt)
void tlb_invalidate_pages(asid_t asid, uintptr_t page, size_t cnt)
{
unsigned int i;
tlb_context_reg_t pc_save, ctx;
/branches/dd/kernel/arch/sparc64/src/mm/as.c
89,7 → 89,7
* The count must be calculated with respect to the emualted 16K page
* size.
*/
count_t cnt = ((ITSB_ENTRY_COUNT + DTSB_ENTRY_COUNT) *
size_t cnt = ((ITSB_ENTRY_COUNT + DTSB_ENTRY_COUNT) *
sizeof(tsb_entry_t)) >> FRAME_WIDTH;
frame_free(KA2PA((uintptr_t) as->arch.itsb));
return cnt;
101,7 → 101,7
int as_create_arch(as_t *as, int flags)
{
#ifdef CONFIG_TSB
tsb_invalidate(as, 0, (count_t) -1);
tsb_invalidate(as, 0, (size_t) -1);
#endif
return 0;
}
/branches/dd/kernel/arch/sparc64/src/mm/tsb.c
50,13 → 50,14
*
* @param as Address space.
* @param page First page to invalidate in TSB.
* @param pages Number of pages to invalidate. Value of (count_t) -1 means the
* @param pages Number of pages to invalidate. Value of (size_t) -1 means the
* whole TSB.
*/
void tsb_invalidate(as_t *as, uintptr_t page, count_t pages)
void tsb_invalidate(as_t *as, uintptr_t page, size_t pages)
{
index_t i0, i;
count_t cnt;
size_t i0;
size_t i;
size_t cnt;
ASSERT(as->arch.itsb && as->arch.dtsb);
63,7 → 64,7
i0 = (page >> MMU_PAGE_WIDTH) & TSB_INDEX_MASK;
ASSERT(i0 < ITSB_ENTRY_COUNT && i0 < DTSB_ENTRY_COUNT);
 
if (pages == (count_t) -1 || (pages * 2) > ITSB_ENTRY_COUNT)
if (pages == (size_t) -1 || (pages * 2) > ITSB_ENTRY_COUNT)
cnt = ITSB_ENTRY_COUNT;
else
cnt = pages * 2;
81,11 → 82,11
* @param t Software PTE.
* @param index Zero if lower 8K-subpage, one if higher 8K subpage.
*/
void itsb_pte_copy(pte_t *t, index_t index)
void itsb_pte_copy(pte_t *t, size_t index)
{
as_t *as;
tsb_entry_t *tsb;
index_t entry;
size_t entry;
 
ASSERT(index <= 1);
127,11 → 128,11
* @param index Zero if lower 8K-subpage, one if higher 8K-subpage.
* @param ro If true, the mapping is copied read-only.
*/
void dtsb_pte_copy(pte_t *t, index_t index, bool ro)
void dtsb_pte_copy(pte_t *t, size_t index, bool ro)
{
as_t *as;
tsb_entry_t *tsb;
index_t entry;
size_t entry;
ASSERT(index <= 1);
 
/branches/dd/kernel/arch/sparc64/src/drivers/fhc.c
71,7 → 71,7
if (!prop || !prop->value)
return NULL;
count_t regs = prop->size / sizeof(ofw_central_reg_t);
size_t regs = prop->size / sizeof(ofw_central_reg_t);
if (regs + 1 < UART_IMAP_REG)
return NULL;
 
/branches/dd/kernel/arch/sparc64/src/drivers/pci.c
91,7 → 91,7
return NULL;
 
ofw_upa_reg_t *reg = prop->value;
count_t regs = prop->size / sizeof(ofw_upa_reg_t);
size_t regs = prop->size / sizeof(ofw_upa_reg_t);
 
if (regs < SABRE_INTERNAL_REG + 1)
return NULL;
138,7 → 138,7
return NULL;
 
ofw_upa_reg_t *reg = prop->value;
count_t regs = prop->size / sizeof(ofw_upa_reg_t);
size_t regs = prop->size / sizeof(ofw_upa_reg_t);
 
if (regs < PSYCHO_INTERNAL_REG + 1)
return NULL;
/branches/dd/kernel/arch/ia64/include/types.h
54,8 → 54,6
} uint128_t;
 
typedef uint64_t size_t;
typedef uint64_t count_t;
typedef uint64_t index_t;
 
typedef uint64_t uintptr_t;
typedef uint64_t pfn_t;
72,8 → 70,6
 
#define PRIp "lx" /**< Format for uintptr_t. */
#define PRIs "lu" /**< Format for size_t. */
#define PRIc "lu" /**< Format for count_t. */
#define PRIi "lu" /**< Format for index_t. */
 
#define PRId8 "d" /**< Format for int8_t. */
#define PRId16 "d" /**< Format for int16_t. */
/branches/dd/kernel/arch/ia64/include/mm/page.h
240,7 → 240,7
*
* @return Current contents of rr[i].
*/
static inline uint64_t rr_read(index_t i)
static inline uint64_t rr_read(size_t i)
{
uint64_t ret;
ASSERT(i < REGION_REGISTERS);
253,7 → 253,7
* @param i Region register index.
* @param v Value to be written to rr[i].
*/
static inline void rr_write(index_t i, uint64_t v)
static inline void rr_write(size_t i, uint64_t v)
{
ASSERT(i < REGION_REGISTERS);
asm volatile (
/branches/dd/kernel/arch/ia64/include/mm/tlb.h
76,12 → 76,12
extern void dtc_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry);
extern void itc_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry);
 
extern void tr_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry, bool dtr, index_t tr);
extern void dtr_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry, index_t tr);
extern void itr_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry, index_t tr);
extern void tr_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry, bool dtr, size_t tr);
extern void dtr_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry, size_t tr);
extern void itr_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry, size_t tr);
 
extern void dtlb_kernel_mapping_insert(uintptr_t page, uintptr_t frame, bool dtr, index_t tr);
extern void dtr_purge(uintptr_t page, count_t width);
extern void dtlb_kernel_mapping_insert(uintptr_t page, uintptr_t frame, bool dtr, size_t tr);
extern void dtr_purge(uintptr_t page, size_t width);
 
extern void dtc_pte_copy(pte_t *t);
extern void itc_pte_copy(pte_t *t);
/branches/dd/kernel/arch/ia64/src/mm/tlb.c
100,7 → 100,7
}
 
 
void tlb_invalidate_pages(asid_t asid, uintptr_t page, count_t cnt)
void tlb_invalidate_pages(asid_t asid, uintptr_t page, size_t cnt)
{
region_register rr;
bool restore_rr = false;
267,7 → 267,7
* @param tr Translation register.
*/
void
itr_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry, index_t tr)
itr_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry, size_t tr)
{
tr_mapping_insert(va, asid, entry, false, tr);
}
281,7 → 281,7
* @param tr Translation register.
*/
void
dtr_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry, index_t tr)
dtr_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry, size_t tr)
{
tr_mapping_insert(va, asid, entry, true, tr);
}
298,7 → 298,7
*/
void
tr_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry, bool dtr,
index_t tr)
size_t tr)
{
region_register rr;
bool restore_rr = false;
353,7 → 353,7
*/
void
dtlb_kernel_mapping_insert(uintptr_t page, uintptr_t frame, bool dtr,
index_t tr)
size_t tr)
{
tlb_entry_t entry;
382,7 → 382,7
* @param page Virtual page address including VRN bits.
* @param width Width of the purge in bits.
*/
void dtr_purge(uintptr_t page, count_t width)
void dtr_purge(uintptr_t page, size_t width)
{
asm volatile ("ptr.d %0, %1\n" : : "r" (page), "r" (width << 2));
}
/branches/dd/kernel/arch/ia64/src/mm/vhpt.c
53,7 → 53,7
void vhpt_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry)
{
region_register rr_save, rr;
index_t vrn;
size_t vrn;
rid_t rid;
uint64_t tag;
 
/branches/dd/kernel/arch/ia64/src/mm/page.c
131,7 → 131,7
vhpt_entry_t *vhpt_hash(uintptr_t page, asid_t asid)
{
region_register rr_save, rr;
index_t vrn;
size_t vrn;
rid_t rid;
vhpt_entry_t *v;
 
176,7 → 176,7
bool vhpt_compare(uintptr_t page, asid_t asid, vhpt_entry_t *v)
{
region_register rr_save, rr;
index_t vrn;
size_t vrn;
rid_t rid;
bool match;
 
223,7 → 223,7
int flags)
{
region_register rr_save, rr;
index_t vrn;
size_t vrn;
rid_t rid;
uint64_t tag;
 
/branches/dd/kernel/arch/arm32/include/types.h
53,8 → 53,6
typedef unsigned long long uint64_t;
 
typedef uint32_t size_t;
typedef uint32_t count_t;
typedef uint32_t index_t;
 
typedef uint32_t uintptr_t;
typedef uint32_t pfn_t;
69,8 → 67,6
 
#define PRIp "x" /**< Format for uintptr_t. */
#define PRIs "u" /**< Format for size_t. */
#define PRIc "u" /**< Format for count_t. */
#define PRIi "u" /**< Format for index_t. */
 
#define PRId8 "d" /**< Format for int8_t. */
#define PRId16 "d" /**< Format for int16_t. */
/branches/dd/kernel/arch/arm32/include/mm/page.h
94,21 → 94,21
 
/* Get PTE flags accessors for each level. */
#define GET_PTL1_FLAGS_ARCH(ptl0, i) \
get_pt_level0_flags((pte_level0_t *) (ptl0), (index_t) (i))
get_pt_level0_flags((pte_level0_t *) (ptl0), (size_t) (i))
#define GET_PTL2_FLAGS_ARCH(ptl1, i) \
PAGE_PRESENT
#define GET_PTL3_FLAGS_ARCH(ptl2, i) \
PAGE_PRESENT
#define GET_FRAME_FLAGS_ARCH(ptl3, i) \
get_pt_level1_flags((pte_level1_t *) (ptl3), (index_t) (i))
get_pt_level1_flags((pte_level1_t *) (ptl3), (size_t) (i))
 
/* Set PTE flags accessors for each level. */
#define SET_PTL1_FLAGS_ARCH(ptl0, i, x) \
set_pt_level0_flags((pte_level0_t *) (ptl0), (index_t) (i), (x))
set_pt_level0_flags((pte_level0_t *) (ptl0), (size_t) (i), (x))
#define SET_PTL2_FLAGS_ARCH(ptl1, i, x)
#define SET_PTL3_FLAGS_ARCH(ptl2, i, x)
#define SET_FRAME_FLAGS_ARCH(ptl3, i, x) \
set_pt_level1_flags((pte_level1_t *) (ptl3), (index_t) (i), (x))
set_pt_level1_flags((pte_level1_t *) (ptl3), (size_t) (i), (x))
 
/* Macros for querying the last-level PTE entries. */
#define PTE_VALID_ARCH(pte) \
204,7 → 204,7
* @param pt Level 0 page table.
* @param i Index of the entry to return.
*/
static inline int get_pt_level0_flags(pte_level0_t *pt, index_t i)
static inline int get_pt_level0_flags(pte_level0_t *pt, size_t i)
{
pte_level0_t *p = &pt[i];
int np = (p->descriptor_type == PTE_DESCRIPTOR_NOT_PRESENT);
219,7 → 219,7
* @param pt Level 1 page table.
* @param i Index of the entry to return.
*/
static inline int get_pt_level1_flags(pte_level1_t *pt, index_t i)
static inline int get_pt_level1_flags(pte_level1_t *pt, size_t i)
{
pte_level1_t *p = &pt[i];
 
244,7 → 244,7
* @param i index of the entry to be changed
* @param flags new flags
*/
static inline void set_pt_level0_flags(pte_level0_t *pt, index_t i, int flags)
static inline void set_pt_level0_flags(pte_level0_t *pt, size_t i, int flags)
{
pte_level0_t *p = &pt[i];
 
272,7 → 272,7
* @param i Index of the entry to be changed.
* @param flags New flags.
*/
static inline void set_pt_level1_flags(pte_level1_t *pt, index_t i, int flags)
static inline void set_pt_level1_flags(pte_level1_t *pt, size_t i, int flags)
{
pte_level1_t *p = &pt[i];
/branches/dd/kernel/arch/arm32/src/mm/tlb.c
80,7 → 80,7
* @param page Address of the first page whose entry is to be invalidated.
* @param cnt Number of entries to invalidate.
*/
void tlb_invalidate_pages(asid_t asid __attribute__((unused)), uintptr_t page, count_t cnt)
void tlb_invalidate_pages(asid_t asid __attribute__((unused)), uintptr_t page, size_t cnt)
{
unsigned int i;
 
/branches/dd/kernel/arch/ppc32/include/types.h
46,8 → 46,6
typedef unsigned long long uint64_t;
 
typedef uint32_t size_t;
typedef uint32_t count_t;
typedef uint32_t index_t;
 
typedef uint32_t uintptr_t;
typedef uint32_t pfn_t;
60,11 → 58,9
typedef struct {
} fncptr_t;
 
/**< Formats for uintptr_t, size_t, count_t and index_t */
/**< Formats for uintptr_t, size_t */
#define PRIp "x"
#define PRIs "u"
#define PRIc "u"
#define PRIi "u"
 
/**< Formats for (u)int8_t, (u)int16_t, (u)int32_t, (u)int64_t and (u)native_t */
#define PRId8 "d"
/branches/dd/kernel/arch/ppc32/include/mm/page.h
102,21 → 102,21
 
/* Get PTE flags accessors for each level. */
#define GET_PTL1_FLAGS_ARCH(ptl0, i) \
get_pt_flags((pte_t *) (ptl0), (index_t) (i))
get_pt_flags((pte_t *) (ptl0), (size_t) (i))
#define GET_PTL2_FLAGS_ARCH(ptl1, i) \
PAGE_PRESENT
#define GET_PTL3_FLAGS_ARCH(ptl2, i) \
PAGE_PRESENT
#define GET_FRAME_FLAGS_ARCH(ptl3, i) \
get_pt_flags((pte_t *) (ptl3), (index_t) (i))
get_pt_flags((pte_t *) (ptl3), (size_t) (i))
 
/* Set PTE flags accessors for each level. */
#define SET_PTL1_FLAGS_ARCH(ptl0, i, x) \
set_pt_flags((pte_t *) (ptl0), (index_t) (i), (x))
set_pt_flags((pte_t *) (ptl0), (size_t) (i), (x))
#define SET_PTL2_FLAGS_ARCH(ptl1, i, x)
#define SET_PTL3_FLAGS_ARCH(ptl2, i, x)
#define SET_FRAME_FLAGS_ARCH(ptl3, i, x) \
set_pt_flags((pte_t *) (ptl3), (index_t) (i), (x))
set_pt_flags((pte_t *) (ptl3), (size_t) (i), (x))
 
/* Macros for querying the last-level PTEs. */
#define PTE_VALID_ARCH(pte) (*((uint32_t *) (pte)) != 0)
130,7 → 130,7
#include <mm/mm.h>
#include <arch/interrupt.h>
 
static inline int get_pt_flags(pte_t *pt, index_t i)
static inline int get_pt_flags(pte_t *pt, size_t i)
{
pte_t *p = &pt[i];
143,7 → 143,7
(p->global << PAGE_GLOBAL_SHIFT));
}
 
static inline void set_pt_flags(pte_t *pt, index_t i, int flags)
static inline void set_pt_flags(pte_t *pt, size_t i, int flags)
{
pte_t *p = &pt[i];
/branches/dd/kernel/arch/ppc32/src/mm/tlb.c
549,7 → 549,7
}
 
 
void tlb_invalidate_pages(asid_t asid, uintptr_t page, count_t cnt)
void tlb_invalidate_pages(asid_t asid, uintptr_t page, size_t cnt)
{
// TODO
tlb_invalidate_all();
/branches/dd/kernel/arch/ppc32/src/mm/frame.c
57,7 → 57,7
void frame_arch_init(void)
{
pfn_t minconf = 2;
count_t i;
size_t i;
pfn_t start, conf;
size_t size;
/branches/dd/kernel/arch/amd64/include/types.h
46,8 → 46,6
typedef unsigned long long uint64_t;
 
typedef uint64_t size_t;
typedef uint64_t count_t;
typedef uint64_t index_t;
 
typedef uint64_t uintptr_t;
typedef uint64_t pfn_t;
60,11 → 58,9
typedef struct {
} fncptr_t;
 
/**< Formats for uintptr_t, size_t, count_t and index_t */
/**< Formats for uintptr_t, size_t */
#define PRIp "llx"
#define PRIs "llu"
#define PRIc "llu"
#define PRIi "llu"
 
/**< Formats for (u)int8_t, (u)int16_t, (u)int32_t, (u)int64_t and (u)native_t */
#define PRId8 "d"
/branches/dd/kernel/arch/amd64/include/proc/task.h
40,7 → 40,7
 
typedef struct {
/** I/O Permission bitmap Generation counter. */
count_t iomapver;
size_t iomapver;
/** I/O Permission bitmap. */
bitmap_t iomap;
} task_arch_t;
/branches/dd/kernel/arch/amd64/include/mm/page.h
112,33 → 112,33
#define SET_PTL0_ADDRESS_ARCH(ptl0) \
(write_cr3((uintptr_t) (ptl0)))
#define SET_PTL1_ADDRESS_ARCH(ptl0, i, a) \
set_pt_addr((pte_t *) (ptl0), (index_t) (i), a)
set_pt_addr((pte_t *) (ptl0), (size_t) (i), a)
#define SET_PTL2_ADDRESS_ARCH(ptl1, i, a) \
set_pt_addr((pte_t *) (ptl1), (index_t) (i), a)
set_pt_addr((pte_t *) (ptl1), (size_t) (i), a)
#define SET_PTL3_ADDRESS_ARCH(ptl2, i, a) \
set_pt_addr((pte_t *) (ptl2), (index_t) (i), a)
set_pt_addr((pte_t *) (ptl2), (size_t) (i), a)
#define SET_FRAME_ADDRESS_ARCH(ptl3, i, a) \
set_pt_addr((pte_t *) (ptl3), (index_t) (i), a)
set_pt_addr((pte_t *) (ptl3), (size_t) (i), a)
 
/* Get PTE flags accessors for each level. */
#define GET_PTL1_FLAGS_ARCH(ptl0, i) \
get_pt_flags((pte_t *) (ptl0), (index_t) (i))
get_pt_flags((pte_t *) (ptl0), (size_t) (i))
#define GET_PTL2_FLAGS_ARCH(ptl1, i) \
get_pt_flags((pte_t *) (ptl1), (index_t) (i))
get_pt_flags((pte_t *) (ptl1), (size_t) (i))
#define GET_PTL3_FLAGS_ARCH(ptl2, i) \
get_pt_flags((pte_t *) (ptl2), (index_t) (i))
get_pt_flags((pte_t *) (ptl2), (size_t) (i))
#define GET_FRAME_FLAGS_ARCH(ptl3, i) \
get_pt_flags((pte_t *) (ptl3), (index_t) (i))
get_pt_flags((pte_t *) (ptl3), (size_t) (i))
 
/* Set PTE flags accessors for each level. */
#define SET_PTL1_FLAGS_ARCH(ptl0, i, x) \
set_pt_flags((pte_t *) (ptl0), (index_t) (i), (x))
set_pt_flags((pte_t *) (ptl0), (size_t) (i), (x))
#define SET_PTL2_FLAGS_ARCH(ptl1, i, x) \
set_pt_flags((pte_t *) (ptl1), (index_t) (i), (x))
set_pt_flags((pte_t *) (ptl1), (size_t) (i), (x))
#define SET_PTL3_FLAGS_ARCH(ptl2, i, x) \
set_pt_flags((pte_t *) (ptl2), (index_t) (i), (x))
set_pt_flags((pte_t *) (ptl2), (size_t) (i), (x))
#define SET_FRAME_FLAGS_ARCH(ptl3, i, x) \
set_pt_flags((pte_t *) (ptl3), (index_t) (i), (x))
set_pt_flags((pte_t *) (ptl3), (size_t) (i), (x))
 
/* Macros for querying the last-level PTE entries. */
#define PTE_VALID_ARCH(p) \
176,7 → 176,7
*/
#define PFERR_CODE_ID (1 << 4)
 
static inline int get_pt_flags(pte_t *pt, index_t i)
static inline int get_pt_flags(pte_t *pt, size_t i)
{
pte_t *p = &pt[i];
189,7 → 189,7
p->global << PAGE_GLOBAL_SHIFT);
}
 
static inline void set_pt_addr(pte_t *pt, index_t i, uintptr_t a)
static inline void set_pt_addr(pte_t *pt, size_t i, uintptr_t a)
{
pte_t *p = &pt[i];
 
197,7 → 197,7
p->addr_32_51 = a >> 32;
}
 
static inline void set_pt_flags(pte_t *pt, index_t i, int flags)
static inline void set_pt_flags(pte_t *pt, size_t i, int flags)
{
pte_t *p = &pt[i];
/branches/dd/kernel/arch/amd64/include/cpu.h
64,7 → 64,7
int stepping;
tss_t *tss;
count_t iomapver_copy; /** Copy of TASK's I/O Permission bitmap generation count. */
size_t iomapver_copy; /** Copy of TASK's I/O Permission bitmap generation count. */
} cpu_arch_t;
 
struct star_msr {
/branches/dd/kernel/arch/amd64/src/ddi/ddi.c
56,7 → 56,7
*/
int ddi_iospace_enable_arch(task_t *task, uintptr_t ioaddr, size_t size)
{
count_t bits;
size_t bits;
bits = ioaddr + size;
if (bits > IO_PORTS)
98,7 → 98,7
/*
* Enable the range and we are done.
*/
bitmap_clear_range(&task->arch.iomap, (index_t) ioaddr, (count_t) size);
bitmap_clear_range(&task->arch.iomap, (size_t) ioaddr, (size_t) size);
/*
* Increment I/O Permission bitmap generation counter.
117,11 → 117,11
*/
void io_perm_bitmap_install(void)
{
count_t bits;
size_t bits;
ptr_16_64_t cpugdtr;
descriptor_t *gdt_p;
tss_descriptor_t *tss_desc;
count_t ver;
size_t ver;
/* First, copy the I/O Permission Bitmap. */
spinlock_lock(&TASK->lock);
/branches/dd/kernel/arch/amd64/src/interrupt.c
101,7 → 101,7
static void gp_fault(int n, istate_t *istate)
{
if (TASK) {
count_t ver;
size_t ver;
 
spinlock_lock(&TASK->lock);
ver = TASK->arch.iomapver;
/branches/dd/kernel/arch/mips32/include/types.h
46,8 → 46,6
typedef unsigned long long uint64_t;
 
typedef uint32_t size_t;
typedef uint32_t count_t;
typedef uint32_t index_t;
 
typedef uint32_t uintptr_t;
typedef uint32_t pfn_t;
62,8 → 60,6
 
#define PRIp "x" /**< Format for uintptr_t. */
#define PRIs "u" /**< Format for size_t. */
#define PRIc "u" /**< Format for count_t. */
#define PRIi "u" /**< Format for index_t. */
 
#define PRId8 "d" /**< Format for int8_t. */
#define PRId16 "d" /**< Format for int16_t. */
/branches/dd/kernel/arch/mips32/include/arch.h
42,7 → 42,7
 
#include <typedefs.h>
 
extern count_t cpu_count;
extern size_t cpu_count;
 
typedef struct {
uintptr_t addr;
/branches/dd/kernel/arch/mips32/include/mm/page.h
112,21 → 112,21
 
/* Get PTE flags accessors for each level. */
#define GET_PTL1_FLAGS_ARCH(ptl0, i) \
get_pt_flags((pte_t *) (ptl0), (index_t) (i))
get_pt_flags((pte_t *) (ptl0), (size_t) (i))
#define GET_PTL2_FLAGS_ARCH(ptl1, i) \
PAGE_PRESENT
#define GET_PTL3_FLAGS_ARCH(ptl2, i) \
PAGE_PRESENT
#define GET_FRAME_FLAGS_ARCH(ptl3, i) \
get_pt_flags((pte_t *) (ptl3), (index_t) (i))
get_pt_flags((pte_t *) (ptl3), (size_t) (i))
 
/* Set PTE flags accessors for each level. */
#define SET_PTL1_FLAGS_ARCH(ptl0, i, x) \
set_pt_flags((pte_t *) (ptl0), (index_t) (i), (x))
set_pt_flags((pte_t *) (ptl0), (size_t) (i), (x))
#define SET_PTL2_FLAGS_ARCH(ptl1, i, x)
#define SET_PTL3_FLAGS_ARCH(ptl2, i, x)
#define SET_FRAME_FLAGS_ARCH(ptl3, i, x) \
set_pt_flags((pte_t *) (ptl3), (index_t) (i), (x))
set_pt_flags((pte_t *) (ptl3), (size_t) (i), (x))
 
/* Last-level info macros. */
#define PTE_VALID_ARCH(pte) (*((uint32_t *) (pte)) != 0)
140,7 → 140,7
#include <mm/mm.h>
#include <arch/exception.h>
 
static inline int get_pt_flags(pte_t *pt, index_t i)
static inline int get_pt_flags(pte_t *pt, size_t i)
{
pte_t *p = &pt[i];
153,7 → 153,7
(p->g << PAGE_GLOBAL_SHIFT));
}
 
static inline void set_pt_flags(pte_t *pt, index_t i, int flags)
static inline void set_pt_flags(pte_t *pt, size_t i, int flags)
{
pte_t *p = &pt[i];
/branches/dd/kernel/arch/mips32/include/debugger.h
53,7 → 53,7
unative_t instruction; /**< Original instruction */
unative_t nextinstruction; /**< Original instruction following break */
int flags; /**< Flags regarding breakpoint */
count_t counter;
size_t counter;
void (*bkfunc)(void *b, istate_t *istate);
} bpinfo_t;
 
/branches/dd/kernel/arch/mips32/src/mm/tlb.c
560,7 → 560,7
* @param page First page whose TLB entry is to be invalidated.
* @param cnt Number of entries to invalidate.
*/
void tlb_invalidate_pages(asid_t asid, uintptr_t page, count_t cnt)
void tlb_invalidate_pages(asid_t asid, uintptr_t page, size_t cnt)
{
unsigned int i;
ipl_t ipl;
/branches/dd/kernel/arch/mips32/src/mm/frame.c
62,7 → 62,7
pfn_t count;
} phys_region_t;
 
static count_t phys_regions_count = 0;
static size_t phys_regions_count = 0;
static phys_region_t phys_regions[MAX_REGIONS];
 
/** Check whether frame is available
119,7 → 119,7
/* Init tasks */
bool safe = true;
count_t i;
size_t i;
for (i = 0; i < init.cnt; i++)
if (overlaps(frame << ZERO_PAGE_WIDTH, ZERO_PAGE_SIZE,
KA2PA(init.tasks[i].addr), init.tasks[i].size)) {
174,7 → 174,7
cp0_entry_lo1_write(0);
cp0_entry_hi_write(0);
 
count_t i;
size_t i;
for (i = 0; i < TLB_ENTRY_COUNT; i++) {
cp0_index_write(i);
tlbwi();
251,7 → 251,7
printf("Base Size\n");
printf("---------- ----------\n");
count_t i;
size_t i;
for (i = 0; i < phys_regions_count; i++) {
printf("%#010x %10u\n",
PFN2ADDR(phys_regions[i].start), PFN2ADDR(phys_regions[i].count));
/branches/dd/kernel/arch/mips32/src/mips32.c
76,7 → 76,7
/* Stack pointer saved when entering user mode */
uintptr_t supervisor_sp __attribute__ ((section (".text")));
 
count_t cpu_count = 0;
size_t cpu_count = 0;
 
/** Performs mips32-specific initialization before main_bsp() is called. */
void arch_pre_main(void *entry __attribute__((unused)), bootinfo_t *bootinfo)
84,7 → 84,7
/* Setup usermode */
init.cnt = bootinfo->cnt;
count_t i;
size_t i;
for (i = 0; i < min3(bootinfo->cnt, TASKMAP_MAX_RECORDS, CONFIG_INIT_TASKS); i++) {
init.tasks[i].addr = bootinfo->tasks[i].addr;
init.tasks[i].size = bootinfo->tasks[i].size;
/branches/dd/kernel/arch/ia32/include/types.h
46,8 → 46,6
typedef unsigned long long uint64_t;
 
typedef uint32_t size_t;
typedef uint32_t count_t;
typedef uint32_t index_t;
 
typedef uint32_t uintptr_t;
typedef uint32_t pfn_t;
62,8 → 60,6
 
#define PRIp "x" /**< Format for uintptr_t. */
#define PRIs "u" /**< Format for size_t. */
#define PRIc "u" /**< Format for count_t. */
#define PRIi "u" /**< Format for index_t. */
 
#define PRId8 "d" /**< Format for int8_t. */
#define PRId16 "d" /**< Format for int16_t. */
/branches/dd/kernel/arch/ia32/include/smp/smp.h
39,10 → 39,10
 
/** SMP config opertaions interface. */
struct smp_config_operations {
count_t (* cpu_count)(void); /**< Return number of detected processors. */
bool (* cpu_enabled)(index_t i); /**< Check whether the processor of index i is enabled. */
bool (*cpu_bootstrap)(index_t i); /**< Check whether the processor of index i is BSP. */
uint8_t (*cpu_apic_id)(index_t i); /**< Return APIC ID of the processor of index i. */
size_t (* cpu_count)(void); /**< Return number of detected processors. */
bool (* cpu_enabled)(size_t i); /**< Check whether the processor of index i is enabled. */
bool (*cpu_bootstrap)(size_t i); /**< Check whether the processor of index i is BSP. */
uint8_t (*cpu_apic_id)(size_t i); /**< Return APIC ID of the processor of index i. */
int (*irq_to_pin)(unsigned int irq); /**< Return mapping between irq and APIC pin. */
};
 
/branches/dd/kernel/arch/ia32/include/proc/task.h
40,7 → 40,7
 
typedef struct {
/** I/O Permission bitmap Generation counter. */
count_t iomapver;
size_t iomapver;
/** I/O Permission bitmap. */
bitmap_t iomap;
} task_arch_t;
/branches/dd/kernel/arch/ia32/include/mm/page.h
95,21 → 95,21
 
/* Get PTE flags accessors for each level. */
#define GET_PTL1_FLAGS_ARCH(ptl0, i) \
get_pt_flags((pte_t *) (ptl0), (index_t) (i))
get_pt_flags((pte_t *) (ptl0), (size_t) (i))
#define GET_PTL2_FLAGS_ARCH(ptl1, i) \
PAGE_PRESENT
#define GET_PTL3_FLAGS_ARCH(ptl2, i) \
PAGE_PRESENT
#define GET_FRAME_FLAGS_ARCH(ptl3, i) \
get_pt_flags((pte_t *) (ptl3), (index_t) (i))
get_pt_flags((pte_t *) (ptl3), (size_t) (i))
 
/* Set PTE flags accessors for each level. */
#define SET_PTL1_FLAGS_ARCH(ptl0, i, x) \
set_pt_flags((pte_t *) (ptl0), (index_t) (i), (x))
set_pt_flags((pte_t *) (ptl0), (size_t) (i), (x))
#define SET_PTL2_FLAGS_ARCH(ptl1, i, x)
#define SET_PTL3_FLAGS_ARCH(ptl2, i, x)
#define SET_FRAME_FLAGS_ARCH(ptl3, i, x) \
set_pt_flags((pte_t *) (ptl3), (index_t) (i), (x))
set_pt_flags((pte_t *) (ptl3), (size_t) (i), (x))
 
/* Macros for querying the last level entries. */
#define PTE_VALID_ARCH(p) \
145,7 → 145,7
/** When bit on this position is 1, a reserved bit was set in page directory. */
#define PFERR_CODE_RSVD (1 << 3)
 
static inline int get_pt_flags(pte_t *pt, index_t i)
static inline int get_pt_flags(pte_t *pt, size_t i)
{
pte_t *p = &pt[i];
158,7 → 158,7
p->global << PAGE_GLOBAL_SHIFT);
}
 
static inline void set_pt_flags(pte_t *pt, index_t i, int flags)
static inline void set_pt_flags(pte_t *pt, size_t i, int flags)
{
pte_t *p = &pt[i];
/branches/dd/kernel/arch/ia32/include/cpu.h
57,7 → 57,7
unsigned int stepping;
tss_t *tss;
count_t iomapver_copy; /** Copy of TASK's I/O Permission bitmap generation count. */
size_t iomapver_copy; /** Copy of TASK's I/O Permission bitmap generation count. */
} cpu_arch_t;
 
#endif
/branches/dd/kernel/arch/ia32/src/smp/mps.c
86,10 → 86,10
/*
* Implementation of IA-32 SMP configuration interface.
*/
static count_t get_cpu_count(void);
static bool is_cpu_enabled(index_t i);
static bool is_bsp(index_t i);
static uint8_t get_cpu_apic_id(index_t i);
static size_t get_cpu_count(void);
static bool is_cpu_enabled(size_t i);
static bool is_bsp(size_t i);
static uint8_t get_cpu_apic_id(size_t i);
static int mps_irq_to_pin(unsigned int irq);
 
struct smp_config_operations mps_config_operations = {
100,24 → 100,24
.irq_to_pin = mps_irq_to_pin
};
 
count_t get_cpu_count(void)
size_t get_cpu_count(void)
{
return processor_entry_cnt;
}
 
bool is_cpu_enabled(index_t i)
bool is_cpu_enabled(size_t i)
{
ASSERT(i < processor_entry_cnt);
return (bool) ((processor_entries[i].cpu_flags & 0x01) == 0x01);
}
 
bool is_bsp(index_t i)
bool is_bsp(size_t i)
{
ASSERT(i < processor_entry_cnt);
return (bool) ((processor_entries[i].cpu_flags & 0x02) == 0x02);
}
 
uint8_t get_cpu_apic_id(index_t i)
uint8_t get_cpu_apic_id(size_t i)
{
ASSERT(i < processor_entry_cnt);
return processor_entries[i].l_apic_id;
/branches/dd/kernel/arch/ia32/src/ddi/ddi.c
57,7 → 57,7
*/
int ddi_iospace_enable_arch(task_t *task, uintptr_t ioaddr, size_t size)
{
count_t bits;
size_t bits;
 
bits = ioaddr + size;
if (bits > IO_PORTS)
99,7 → 99,7
/*
* Enable the range and we are done.
*/
bitmap_clear_range(&task->arch.iomap, (index_t) ioaddr, (count_t) size);
bitmap_clear_range(&task->arch.iomap, (size_t) ioaddr, (size_t) size);
 
/*
* Increment I/O Permission bitmap generation counter.
118,10 → 118,10
*/
void io_perm_bitmap_install(void)
{
count_t bits;
size_t bits;
ptr_16_32_t cpugdtr;
descriptor_t *gdt_p;
count_t ver;
size_t ver;
 
/* First, copy the I/O Permission Bitmap. */
spinlock_lock(&TASK->lock);
/branches/dd/kernel/arch/ia32/src/mm/tlb.c
59,7 → 59,7
* @param page Address of the first page whose entry is to be invalidated.
* @param cnt Number of entries to invalidate.
*/
void tlb_invalidate_pages(asid_t asid __attribute__((unused)), uintptr_t page, count_t cnt)
void tlb_invalidate_pages(asid_t asid __attribute__((unused)), uintptr_t page, size_t cnt)
{
unsigned int i;
 
/branches/dd/kernel/arch/ia32/src/mm/frame.c
70,7 → 70,7
#endif
pfn_t pfn;
count_t count;
size_t count;
if (e820table[i].type == MEMMAP_MEMORY_AVAILABLE) {
/* To be safe, make available zone possibly smaller */
/branches/dd/kernel/arch/ia32/src/interrupt.c
101,7 → 101,7
static void gp_fault(int n __attribute__((unused)), istate_t *istate)
{
if (TASK) {
count_t ver;
size_t ver;
spinlock_lock(&TASK->lock);
ver = TASK->arch.iomapver;
/branches/dd/uspace/app/bdsh/input.c
32,10 → 32,10
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <io/stream.h>
#include <console.h>
#include <kbd/kbd.h>
#include <kbd/keycode.h>
#include <io/console.h>
#include <io/keycode.h>
#include <io/style.h>
#include <vfs/vfs.h>
#include <errno.h>
#include <bool.h>
 
100,7 → 100,7
 
static void read_line(char *buffer, int n)
{
kbd_event_t ev;
console_event_t ev;
size_t offs, otmp;
wchar_t dec;
 
107,11 → 107,12
offs = 0;
while (true) {
fflush(stdout);
if (kbd_get_event(&ev) < 0)
if (!console_get_event(fphone(stdin), &ev))
return;
if (ev.type == KE_RELEASE)
if (ev.type != KEY_PRESS)
continue;
 
if (ev.key == KC_ENTER || ev.key == KC_NENTER)
break;
if (ev.key == KC_BACKSPACE) {
131,9 → 132,8
continue;
}
if (ev.c >= ' ') {
//putchar(ev.c);
if (chr_encode(ev.c, buffer, &offs, n - 1) == EOK)
console_putchar(ev.c);
putchar(ev.c);
}
}
putchar('\n');
147,9 → 147,9
{
char line[INPUT_MAX];
 
console_set_style(STYLE_EMPHASIS);
console_set_style(fphone(stdout), STYLE_EMPHASIS);
printf("%s", usr->prompt);
console_set_style(STYLE_NORMAL);
console_set_style(fphone(stdout), STYLE_NORMAL);
 
read_line(line, INPUT_MAX);
/* Make sure we don't have rubbish or a C/R happy user */
/branches/dd/uspace/app/bdsh/cmds/modules/bdd/bdd.c
28,6 → 28,7
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "config.h"
#include "util.h"
#include "errors.h"
/branches/dd/uspace/app/bdsh/cmds/modules/kcon/kcon.c
30,7 → 30,8
 
#include <stdio.h>
#include <stdlib.h>
#include <console.h>
#include <io/console.h>
#include <vfs/vfs.h>
#include "config.h"
#include "util.h"
#include "errors.h"
65,7 → 66,7
return CMD_FAILURE;
}
 
console_kcon_enable();
console_kcon_enable(fphone(stdout));
 
return CMD_SUCCESS;
}
/branches/dd/uspace/app/bdsh/cmds/modules/pwd/pwd.c
30,6 → 30,7
 
#include <stdio.h>
#include <stdlib.h>
#include <mem.h>
 
#include "config.h"
#include "errors.h"
/branches/dd/uspace/app/bdsh/cmds/modules/mkdir/mkdir.c
37,6 → 37,7
#include <sys/stat.h>
#include <getopt.h>
#include <stdarg.h>
#include <string.h>
 
#include "config.h"
#include "errors.h"
/branches/dd/uspace/app/bdsh/cmds/modules/rm/rm.c
34,6 → 34,8
#include <fcntl.h>
#include <dirent.h>
#include <getopt.h>
#include <mem.h>
#include <string.h>
 
#include "config.h"
#include "errors.h"
/branches/dd/uspace/app/bdsh/exec.c
123,7 → 123,8
if (tid == 0) {
cli_error(CL_EEXEC, "Cannot spawn `%s'.", cmd);
return 1;
} else {
return 0;
}
task_wait(tid);
return 0;
}
/branches/dd/uspace/app/init/version.c
File deleted
/branches/dd/uspace/app/init/version.h
File deleted
/branches/dd/uspace/app/init/init.c
44,25 → 44,31
#include <task.h>
#include <malloc.h>
#include <macros.h>
#include <console.h>
#include <string.h>
#include <devmap.h>
#include "init.h"
#include "version.h"
 
static bool mount_fs(const char *fstype)
static void info_print(void)
{
printf(NAME ": HelenOS init\n");
}
 
static bool mount_root(const char *fstype)
{
int rc = -1;
char *opts = "";
const char *root_dev = "initrd";
if (str_cmp(fstype, "tmpfs") == 0)
opts = "restore";
 
while (rc < 0) {
rc = mount(fstype, "/", "initrd", opts, IPC_FLAG_BLOCKING);
rc = mount(fstype, "/", root_dev, opts, IPC_FLAG_BLOCKING);
switch (rc) {
case EOK:
printf(NAME ": Root filesystem mounted\n");
printf(NAME ": Root filesystem mounted, %s at %s\n",
fstype, root_dev);
break;
case EBUSY:
printf(NAME ": Root filesystem already mounted\n");
118,11 → 124,35
printf(NAME ": Error spawning %s\n", fname);
}
 
static void getvc(char *dev, char *app)
{
char *argv[4];
char vc[MAX_DEVICE_NAME];
snprintf(vc, MAX_DEVICE_NAME, "/dev/%s", dev);
printf(NAME ": Spawning getvc on %s\n", vc);
dev_handle_t handle;
devmap_device_get_handle(dev, &handle, IPC_FLAG_BLOCKING);
if (handle >= 0) {
argv[0] = "/app/getvc";
argv[1] = vc;
argv[2] = app;
argv[3] = NULL;
if (!task_spawn("/app/getvc", argv))
printf(NAME ": Error spawning getvc on %s\n", vc);
} else
printf(NAME ": Error waiting on %s\n", vc);
}
 
int main(int argc, char *argv[])
{
info_print();
if (!mount_fs(STRING(RDFMT))) {
if (!mount_root(STRING(RDFMT))) {
printf(NAME ": Exiting\n");
return -1;
}
140,12 → 170,14
spawn("/srv/fhc");
spawn("/srv/obio");
console_wait();
version_print();
getvc("vc0", "/app/bdsh");
getvc("vc1", "/app/bdsh");
getvc("vc2", "/app/bdsh");
getvc("vc3", "/app/bdsh");
getvc("vc4", "/app/bdsh");
getvc("vc5", "/app/bdsh");
getvc("vc6", "/app/klog");
spawn("/app/klog");
spawn("/app/bdsh");
usleep(1000000);
spawn("/srv/pci");
/branches/dd/uspace/app/init/init.h
28,7 → 28,7
 
/** @addtogroup init
* @{
*/
*/
/**
* @file
*/
36,10 → 36,11
#ifndef __INIT_H__
#define __INIT_H__
 
#define NAME "init"
#define NAME "init"
 
#define MAX_DEVICE_NAME 32
 
#endif
 
/** @}
*/
 
/branches/dd/uspace/app/init/Makefile
26,8 → 26,6
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
 
include ../../../version
 
## Setup toolchain
#
 
36,10 → 34,7
 
include $(LIBC_PREFIX)/Makefile.toolchain
 
CFLAGS += -I../../srv/kbd/include
 
LIBS = $(LIBC_PREFIX)/libc.a
DEFS += -DRELEASE=$(RELEASE)
 
## Sources
#
46,8 → 41,7
 
OUTPUT = init
SOURCES = \
init.c \
version.c
init.c
 
OBJECTS := $(addsuffix .o,$(basename $(SOURCES)))
 
/branches/dd/uspace/app/tester/console/console1.c
28,12 → 28,13
 
#include <stdio.h>
#include <stdlib.h>
#include <io/stream.h>
#include <io/console.h>
#include <io/color.h>
#include <io/style.h>
#include <vfs/vfs.h>
#include <async.h>
#include "../tester.h"
 
#include <console.h>
 
const char *color_name[] = {
[COLOR_BLACK] = "black",
[COLOR_BLUE] = "blue",
50,21 → 51,21
int i, j;
 
printf("Style test: ");
console_set_style(STYLE_NORMAL);
console_set_style(fphone(stdout), STYLE_NORMAL);
printf("normal ");
console_set_style(STYLE_EMPHASIS);
console_set_style(fphone(stdout), STYLE_EMPHASIS);
printf("emphasized");
console_set_style(STYLE_NORMAL);
console_set_style(fphone(stdout), STYLE_NORMAL);
printf(".\n");
 
printf("Foreground color test:\n");
for (j = 0; j < 2; j++) {
for (i = COLOR_BLACK; i <= COLOR_WHITE; i++) {
console_set_color(i, COLOR_WHITE,
console_set_color(fphone(stdout), i, COLOR_WHITE,
j ? CATTR_BRIGHT : 0);
printf(" %s ", color_name[i]);
}
console_set_color(COLOR_BLACK, COLOR_WHITE, 0);
console_set_color(fphone(stdout), COLOR_BLACK, COLOR_WHITE, 0);
putchar('\n');
}
 
71,11 → 72,11
printf("Background color test:\n");
for (j = 0; j < 2; j++) {
for (i = COLOR_BLACK; i <= COLOR_WHITE; i++) {
console_set_color(COLOR_WHITE, i,
console_set_color(fphone(stdout), COLOR_WHITE, i,
j ? CATTR_BRIGHT : 0);
printf(" %s ", color_name[i]);
}
console_set_color(COLOR_BLACK, COLOR_WHITE, 0);
console_set_color(fphone(stdout), COLOR_BLACK, COLOR_WHITE, 0);
putchar('\n');
}
 
82,24 → 83,24
printf("Now let's test RGB colors:\n");
 
for (i = 0; i < 255; i += 16) {
console_set_rgb_color(0xffffff, i << 16);
console_set_rgb_color(fphone(stdout), 0xffffff, i << 16);
putchar('X');
}
console_set_color(COLOR_BLACK, COLOR_WHITE, 0);
console_set_color(fphone(stdout), COLOR_BLACK, COLOR_WHITE, 0);
putchar('\n');
 
for (i = 0; i < 255; i += 16) {
console_set_rgb_color(0xffffff, i << 8);
console_set_rgb_color(fphone(stdout), 0xffffff, i << 8);
putchar('X');
}
console_set_color(COLOR_BLACK, COLOR_WHITE, 0);
console_set_color(fphone(stdout), COLOR_BLACK, COLOR_WHITE, 0);
putchar('\n');
 
for (i = 0; i < 255; i += 16) {
console_set_rgb_color(0xffffff, i);
console_set_rgb_color(fphone(stdout), 0xffffff, i);
putchar('X');
}
console_set_color(COLOR_BLACK, COLOR_WHITE, 0);
console_set_color(fphone(stdout), COLOR_BLACK, COLOR_WHITE, 0);
putchar('\n');
 
printf("[press a key]\n");
/branches/dd/uspace/app/tester/tester.c
130,6 → 130,7
list_tests();
printf("> ");
fflush(stdout);
c = getchar();
printf("%c\n", c);
/branches/dd/uspace/app/tester/ipc/ping_pong.c
28,41 → 28,46
 
#include <stdio.h>
#include <stdlib.h>
#include <console.h>
#include <sys/time.h>
#include <ipc/ns.h>
#include <async.h>
#include <errno.h>
#include "../tester.h"
 
#define DURATION_SECS 10
#define COUNT_GRANULARITY 100
#define DURATION_SECS 10
#define COUNT_GRANULARITY 100
 
char * test_ping_pong(bool quiet)
char *test_ping_pong(bool quiet)
{
int i;
int w, h;
struct timeval start, now;
long count;
 
printf("Pinging console server for %d seconds...\n", DURATION_SECS);
 
printf("Pinging ns server for %d seconds...\n", DURATION_SECS);
struct timeval start;
if (gettimeofday(&start, NULL) != 0)
return "Failed getting the time.";
 
count = 0;
 
uint64_t count = 0;
while (true) {
struct timeval now;
if (gettimeofday(&now, NULL) != 0)
return "Failed getting the time.";
 
if (tv_sub(&now, &start) >= DURATION_SECS * 1000000L)
break;
 
for (i = 0; i < COUNT_GRANULARITY; i++)
console_get_size(&w, &h);
size_t i;
for (i = 0; i < COUNT_GRANULARITY; i++) {
int retval = async_req_0_0(PHONE_NS, NS_PING);
if (retval != EOK)
return "Failed to send ping message.";
}
count += COUNT_GRANULARITY;
}
 
printf("Completed %ld round trips in %d seconds, %ld RT/s.\n", count,
DURATION_SECS, count / DURATION_SECS);
 
printf("Completed %lu round trips in %u seconds, %lu RT/s.\n",
count, DURATION_SECS, count / DURATION_SECS);
return NULL;
}
/branches/dd/uspace/app/getvc/version.c
0,0 → 1,67
/*
* Copyright (c) 2009 Martin Decky
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup getvc
* @{
*/
/**
* @file
*/
 
#include <unistd.h>
#include <stdio.h>
#include <macros.h>
#include "getvc.h"
#include "version.h"
 
static char *release = STRING(RELEASE);
static char *name = STRING(NAME);
static char *arch = STRING(UARCH);
 
#ifdef REVISION
static char *revision = ", revision " STRING(REVISION);
#else
static char *revision = "";
#endif
 
#ifdef TIMESTAMP
static char *timestamp = "\nBuilt on " STRING(TIMESTAMP);
#else
static char *timestamp = "";
#endif
 
/** Print version information. */
void version_print(const char *vc)
{
printf("HelenOS release %s (%s)%s%s\n", release, name, revision, timestamp);
printf("Running on %s (%s)\n", arch, vc);
printf("Copyright (c) 2001-2009 HelenOS project\n\n");
}
 
/** @}
*/
/branches/dd/uspace/app/getvc/getvc.c
0,0 → 1,100
/*
* Copyright (c) 2009 Martin Decky
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup getvc GetVC
* @brief Console initialization task.
* @{
*/
/**
* @file
*/
 
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <task.h>
#include "version.h"
 
static void usage(void)
{
printf("Usage: getvc <device> <path>\n");
}
 
static void closeall(void)
{
fclose(stdin);
fclose(stdout);
fclose(stderr);
close(0);
close(1);
close(2);
}
 
static task_id_t spawn(char *fname)
{
char *argv[2];
argv[0] = fname;
argv[1] = NULL;
task_id_t id = task_spawn(fname, argv);
if (id == 0)
printf("Error spawning %s\n", fname);
return id;
}
 
int main(int argc, char *argv[])
{
if (argc < 3) {
usage();
return -1;
}
closeall();
stdin = fopen(argv[1], "r");
stdout = fopen(argv[1], "w");
stderr = fopen(argv[1], "w");
if ((stdin == NULL)
|| (stdout == NULL)
|| (stderr == NULL))
return -2;
version_print(argv[1]);
task_id_t id = spawn(argv[2]);
task_wait(id);
return 0;
}
 
/** @}
*/
/branches/dd/uspace/app/getvc/version.h
0,0 → 1,44
/*
* Copyright (c) 2009 Martin Decky
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup getvc
* @{
*/
/**
* @file
*/
 
#ifndef VERSION_H__
#define VERSION_H__
 
extern void version_print(const char *vc);
 
#endif
 
/** @}
*/
/branches/dd/uspace/app/getvc/Makefile
0,0 → 1,79
#
# Copyright (c) 2009 Martin Decky
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# - Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# - The name of the author may not be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
 
include ../../../version
 
## Setup toolchain
#
 
LIBC_PREFIX = ../../lib/libc
SOFTINT_PREFIX = ../../lib/softint
 
include $(LIBC_PREFIX)/Makefile.toolchain
 
LIBS = $(LIBC_PREFIX)/libc.a
DEFS += -DRELEASE=$(RELEASE) "-DNAME=$(NAME)"
 
## Sources
#
 
OUTPUT = getvc
SOURCES = \
getvc.c \
version.c
 
OBJECTS := $(addsuffix .o,$(basename $(SOURCES)))
 
.PHONY: all clean depend disasm
 
all: $(OUTPUT) $(OUTPUT).disasm
 
-include Makefile.depend
 
clean:
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend $(OBJECTS)
 
depend:
$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend
 
$(OUTPUT): $(OBJECTS) $(LIBS)
$(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map
 
disasm: $(OUTPUT).disasm
 
$(OUTPUT).disasm: $(OUTPUT)
$(OBJDUMP) -d $< > $@
 
%.o: %.S
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
 
%.o: %.s
$(AS) $(AFLAGS) $< -o $@
 
%.o: %.c
$(CC) $(DEFS) $(CFLAGS) -c $< -o $@
/branches/dd/uspace/app/getvc/getvc.h
0,0 → 1,42
/*
* Copyright (c) 2009 Martin Decky
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup getvc
* @{
*/
/**
* @file
*/
 
#ifndef GETVC_H__
#define GETVC_H__
 
#endif
 
/** @}
*/
/branches/dd/uspace/app/tetris/pathnames.h
File deleted
/branches/dd/uspace/app/tetris/scores.c
36,7 → 36,7
*/
 
/** @addtogroup tetris
* @{
* @{
*/
/** @file
*/
48,24 → 48,18
*
* Major whacks since then.
*/
 
#include <errno.h>
/* #include <err.h> */
/* #include <fcntl.h> */
/* #include <pwd.h> */
#include <stdio.h>
/* #include <stdlib.h> */
#include <string.h>
#include <kbd/kbd.h>
#include <kbd/keycode.h>
#include <io/console.h>
#include <io/keycode.h>
#include <vfs/vfs.h>
#include <stdlib.h>
/* #include <time.h> */
/* #include <term.h> */
/* #include <unistd.h> */
/* #include <sys/param.h> */
/* #include <sys/stat.h> */
/* #include <sys/types.h> */
#include <fcntl.h>
#include <err.h>
#include <time.h>
 
#include "pathnames.h"
#include "screen.h"
#include "tetris.h"
#include "scores.h"
78,20 → 72,22
* As long as the scores are kept sorted, this is simply the first one at
* that level.
*/
#define NUMSPOTS (MAXHISCORES + 1)
#define NLEVELS (MAXLEVEL + 1)
 
/* static time_t now; */
/* static int nscores; */
/* static int gotscores; */
/* static struct highscore scores[NUMSPOTS]; */
#define NUMSPOTS (MAXHISCORES + 1)
#define NLEVELS (MAXLEVEL + 1)
 
static struct highscore scores[NUMSPOTS];
 
/* static int checkscores(struct highscore *, int); */
/* static int cmpscores(const void *, const void *); */
/* static void getscores(FILE **); */
/* static void printem(int, int, struct highscore *, int, const char *); */
/* static char *thisuser(void); */
/** Copy from hiscore table score with index src to dest
*
*/
static void copyhiscore(int dest, int src)
{
str_cpy(scores[dest].hs_name, STR_BOUNDS(MAXLOGNAME) + 1,
scores[src].hs_name);
scores[dest].hs_score = scores[src].hs_score;
scores[dest].hs_level = scores[src].hs_level;
}
 
void showscores(int firstgame)
{
101,59 → 97,55
moveto(10, 0);
printf("\tRank \tLevel \tName\t points\n");
printf("\t========================================================\n");
for (i = 0; i < NUMSPOTS - 1; i++) {
printf("\t%6d %6d %-16s %20d\n", i+1, scores[i].hs_level, scores[i].hs_name, scores[i].hs_score);
}
for (i = 0; i < NUMSPOTS - 1; i++)
printf("\t%6d %6d %-16s %20d\n",
i + 1, scores[i].hs_level, scores[i].hs_name, scores[i].hs_score);
if (!firstgame) {
printf("\t========================================================\n");
printf("\t Last %6d %-16s %20d\n", scores[NUMSPOTS - 1].hs_level, scores[NUMSPOTS - 1].hs_name, scores[NUMSPOTS - 1].hs_score);
printf("\t Last %6d %-16s %20d\n",
scores[NUMSPOTS - 1].hs_level, scores[NUMSPOTS - 1].hs_name, scores[NUMSPOTS - 1].hs_score);
}
printf("\n\n\n\n\tPress any key to return to main menu.");
getchar();
}
 
/** Copy from hiscore table score with index src to dest
*
*/
static void copyhiscore(int dest, int src)
{
str_cpy(scores[dest].hs_name, STR_BOUNDS(MAXLOGNAME) + 1,
scores[src].hs_name);
scores[dest].hs_score = scores[src].hs_score;
scores[dest].hs_level = scores[src].hs_level;
}
 
void insertscore(int score, int level)
{
int i,j;
int i;
int j;
size_t off;
kbd_event_t ev;
console_event_t ev;
clear_screen();
moveto(10 , 10);
moveto(10, 10);
puts("Insert your name: ");
str_cpy(scores[NUMSPOTS - 1].hs_name, STR_BOUNDS(MAXLOGNAME) + 1,
"Player");
i = 6; off = 6;
 
i = 6;
off = 6;
moveto(10 , 28);
printf("%s%.*s",scores[NUMSPOTS - 1].hs_name,MAXLOGNAME-i,"........................................");
 
printf("%s%.*s", scores[NUMSPOTS - 1].hs_name, MAXLOGNAME-i,
"........................................");
while (1) {
fflush(stdout);
if (kbd_get_event(&ev) != EOK)
if (!console_get_event(fphone(stdin), &ev))
exit(1);
 
if (ev.type == KE_RELEASE)
if (ev.type == KEY_RELEASE)
continue;
 
if (ev.key == KC_ENTER || ev.key == KC_NENTER)
break;
 
if (ev.key == KC_BACKSPACE) {
if (i > 0) {
wchar_t uc;
 
--i;
while (off > 0) {
--off;
163,7 → 155,7
if (uc != U_SPECIAL)
break;
}
 
scores[NUMSPOTS - 1].hs_name[off] = '\0';
}
} else if (ev.c != '\0') {
176,398 → 168,33
}
}
moveto(10 , 28);
printf("%s%.*s",scores[NUMSPOTS - 1].hs_name,MAXLOGNAME-i,"........................................");
moveto(10, 28);
printf("%s%.*s", scores[NUMSPOTS - 1].hs_name, MAXLOGNAME - i,
"........................................");
}
scores[NUMSPOTS - 1].hs_score = score;
scores[NUMSPOTS - 1].hs_score = score;
scores[NUMSPOTS - 1].hs_level = level;
i = NUMSPOTS-1;
i = NUMSPOTS - 1;
while ((i > 0) && (scores[i - 1].hs_score < score))
i--;
 
for (j = NUMSPOTS - 2; j > i; j--) {
copyhiscore(j,j-1);
}
copyhiscore(i, NUMSPOTS - 1);
for (j = NUMSPOTS - 2; j > i; j--)
copyhiscore(j, j-1);
copyhiscore(i, NUMSPOTS - 1);
}
 
void initscores(void)
{
int i;
for(i = 0; i < NUMSPOTS; i++) {
for (i = 0; i < NUMSPOTS; i++) {
str_cpy(scores[i].hs_name, STR_BOUNDS(MAXLOGNAME) + 1, "HelenOS Team");
scores[i].hs_score = (NUMSPOTS - i) * 200;
scores[i].hs_level = (i + 1 > MAXLEVEL?MAXLEVEL:i + 1);
scores[i].hs_score = (NUMSPOTS - i) * 200;
scores[i].hs_level = (i + 1 > MAXLEVEL ? MAXLEVEL : i + 1);
}
}
 
/*
* Read the score file. Can be called from savescore (before showscores)
* or showscores (if savescore will not be called). If the given pointer
* is not NULL, sets *fpp to an open file pointer that corresponds to a
* read/write score file that is locked with LOCK_EX. Otherwise, the
* file is locked with LOCK_SH for the read and closed before return.
*
* Note, we assume closing the stdio file releases the lock.
*/
/* static void */
/* getscores(FILE **fpp) */
/* { */
/* int sd, mint, lck, mask, i; */
/* char *mstr, *human; */
/* FILE *sf; */
 
/* if (fpp != NULL) { */
/* mint = O_RDWR | O_CREAT; */
/* mstr = "r+"; */
/* human = "read/write"; */
/* lck = LOCK_EX; */
/* } else { */
/* mint = O_RDONLY; */
/* mstr = "r"; */
/* human = "reading"; */
/* lck = LOCK_SH; */
/* } */
/* setegid(egid); */
/* mask = umask(S_IWOTH); */
/* sd = open(_PATH_SCOREFILE, mint, 0666); */
/* (void)umask(mask); */
/* setegid(gid); */
/* if (sd < 0) { */
/* if (fpp == NULL) { */
/* nscores = 0; */
/* return; */
/* } */
/* err(1, "cannot open %s for %s", _PATH_SCOREFILE, human); */
/* } */
/* setegid(egid); */
/* if ((sf = fdopen(sd, mstr)) == NULL) */
/* err(1, "cannot fdopen %s for %s", _PATH_SCOREFILE, human); */
/* setegid(gid); */
 
/* /\* */
/* * Grab a lock. */
/* *\/ */
/* if (flock(sd, lck)) */
/* warn("warning: score file %s cannot be locked", */
/* _PATH_SCOREFILE); */
 
/* nscores = fread(scores, sizeof(scores[0]), MAXHISCORES, sf); */
/* if (ferror(sf)) */
/* err(1, "error reading %s", _PATH_SCOREFILE); */
/* for (i = 0; i < nscores; i++) */
/* if (scores[i].hs_level < MINLEVEL || */
/* scores[i].hs_level > MAXLEVEL) */
/* errx(1, "scorefile %s corrupt", _PATH_SCOREFILE); */
 
/* if (fpp) */
/* *fpp = sf; */
/* else */
/* (void)fclose(sf); */
/* } */
 
void
savescore(int level)
{
return;
}
/* struct highscore *sp; */
/* int i; */
/* int change; */
/* FILE *sf; */
/* const char *me; */
 
/* getscores(&sf); */
/* gotscores = 1; */
/* (void)time(&now); */
 
/* /\* */
/* * Allow at most one score per person per level -- see if we */
/* * can replace an existing score, or (easiest) do nothing. */
/* * Otherwise add new score at end (there is always room). */
/* *\/ */
/* change = 0; */
/* me = thisuser(); */
/* for (i = 0, sp = &scores[0]; i < nscores; i++, sp++) { */
/* if (sp->hs_level != level || str_cmp(sp->hs_name, me) != 0) */
/* continue; */
/* if (score > sp->hs_score) { */
/* (void)printf("%s bettered %s %d score of %d!\n", */
/* "\nYou", "your old level", level, */
/* sp->hs_score * sp->hs_level); */
/* sp->hs_score = score; /\* new score *\/ */
/* sp->hs_time = now; /\* and time *\/ */
/* change = 1; */
/* } else if (score == sp->hs_score) { */
/* (void)printf("%s tied %s %d high score.\n", */
/* "\nYou", "your old level", level); */
/* sp->hs_time = now; /\* renew it *\/ */
/* change = 1; /\* gotta rewrite, sigh *\/ */
/* } /\* else new score < old score: do nothing *\/ */
/* break; */
/* } */
/* if (i >= nscores) { */
/* strlcpy(sp->hs_name, me, sizeof sp->hs_name); */
/* sp->hs_level = level; */
/* sp->hs_score = score; */
/* sp->hs_time = now; */
/* nscores++; */
/* change = 1; */
/* } */
 
/* if (change) { */
/* /\* */
/* * Sort & clean the scores, then rewrite. */
/* *\/ */
/* nscores = checkscores(scores, nscores); */
/* rewind(sf); */
/* if (fwrite(scores, sizeof(*sp), nscores, sf) != nscores || */
/* fflush(sf) == EOF) */
/* warnx("error writing %s: %s\n\t-- %s", */
/* _PATH_SCOREFILE, strerror(errno), */
/* "high scores may be damaged"); */
/* } */
/* (void)fclose(sf); /\* releases lock *\/ */
/* } */
 
/*
* Get login name, or if that fails, get something suitable.
* The result is always trimmed to fit in a score.
*/
/* static char * */
/* thisuser(void) */
/* { */
/* const char *p; */
/* struct passwd *pw; */
/* static char u[sizeof(scores[0].hs_name)]; */
 
/* if (u[0]) */
/* return (u); */
/* p = getlogin(); */
/* if (p == NULL || *p == '\0') { */
/* pw = getpwuid(getuid()); */
/* if (pw != NULL) */
/* p = pw->pw_name; */
/* else */
/* p = " ???"; */
/* } */
/* strlcpy(u, p, sizeof(u)); */
/* return (u); */
/* } */
 
/*
* Score comparison function for qsort.
*
* If two scores are equal, the person who had the score first is
* listed first in the highscore file.
*/
/* static int */
/* cmpscores(const void *x, const void *y) */
/* { */
/* const struct highscore *a, *b; */
/* long l; */
 
/* a = x; */
/* b = y; */
/* l = (long)b->hs_level * b->hs_score - (long)a->hs_level * a->hs_score; */
/* if (l < 0) */
/* return (-1); */
/* if (l > 0) */
/* return (1); */
/* if (a->hs_time < b->hs_time) */
/* return (-1); */
/* if (a->hs_time > b->hs_time) */
/* return (1); */
/* return (0); */
/* } */
 
/*
* If we've added a score to the file, we need to check the file and ensure
* that this player has only a few entries. The number of entries is
* controlled by MAXSCORES, and is to ensure that the highscore file is not
* monopolised by just a few people. People who no longer have accounts are
* only allowed the highest score. Scores older than EXPIRATION seconds are
* removed, unless they are someone's personal best.
* Caveat: the highest score on each level is always kept.
*/
/* static int */
/* checkscores(struct highscore *hs, int num) */
/* { */
/* struct highscore *sp; */
/* int i, j, k, numnames; */
/* int levelfound[NLEVELS]; */
/* struct peruser { */
/* char *name; */
/* int times; */
/* } count[NUMSPOTS]; */
/* struct peruser *pu; */
 
/* /\* */
/* * Sort so that highest totals come first. */
/* * */
/* * levelfound[i] becomes set when the first high score for that */
/* * level is encountered. By definition this is the highest score. */
/* *\/ */
/* qsort((void *)hs, nscores, sizeof(*hs), cmpscores); */
/* for (i = MINLEVEL; i < NLEVELS; i++) */
/* levelfound[i] = 0; */
/* numnames = 0; */
/* for (i = 0, sp = hs; i < num;) { */
/* /\* */
/* * This is O(n^2), but do you think we care? */
/* *\/ */
/* for (j = 0, pu = count; j < numnames; j++, pu++) */
/* if (str_cmp(sp->hs_name, pu->name) == 0) */
/* break; */
/* if (j == numnames) { */
/* /\* */
/* * Add new user, set per-user count to 1. */
/* *\/ */
/* pu->name = sp->hs_name; */
/* pu->times = 1; */
/* numnames++; */
/* } else { */
/* /\* */
/* * Two ways to keep this score: */
/* * - Not too many (per user), still has acct, & */
/* * score not dated; or */
/* * - High score on this level. */
/* *\/ */
/* if ((pu->times < MAXSCORES && */
/* getpwnam(sp->hs_name) != NULL && */
/* sp->hs_time + EXPIRATION >= now) || */
/* levelfound[sp->hs_level] == 0) */
/* pu->times++; */
/* else { */
/* /\* */
/* * Delete this score, do not count it, */
/* * do not pass go, do not collect $200. */
/* *\/ */
/* num--; */
/* for (k = i; k < num; k++) */
/* hs[k] = hs[k + 1]; */
/* continue; */
/* } */
/* } */
/* levelfound[sp->hs_level] = 1; */
/* i++, sp++; */
/* } */
/* return (num > MAXHISCORES ? MAXHISCORES : num); */
/* } */
 
/*
* Show current scores. This must be called after savescore, if
* savescore is called at all, for two reasons:
* - Showscores munches the time field.
* - Even if that were not the case, a new score must be recorded
* before it can be shown anyway.
*/
/*
void
showscores(int level)
{
return;
}
*/
/* struct highscore *sp; */
/* int i, n, c; */
/* const char *me; */
/* int levelfound[NLEVELS]; */
 
/* if (!gotscores) */
/* getscores((FILE **)NULL); */
/* (void)printf("\n\t\t Tetris High Scores\n"); */
 
/* /\* */
/* * If level == 0, the person has not played a game but just asked for */
/* * the high scores; we do not need to check for printing in highlight */
/* * mode. If SOstr is null, we can't do highlighting anyway. */
/* *\/ */
/* me = level && SOstr ? thisuser() : NULL; */
 
/* /\* */
/* * Set times to 0 except for high score on each level. */
/* *\/ */
/* for (i = MINLEVEL; i < NLEVELS; i++) */
/* levelfound[i] = 0; */
/* for (i = 0, sp = scores; i < nscores; i++, sp++) { */
/* if (levelfound[sp->hs_level]) */
/* sp->hs_time = 0; */
/* else { */
/* sp->hs_time = 1; */
/* levelfound[sp->hs_level] = 1; */
/* } */
/* } */
 
/* /\* */
/* * Page each screenful of scores. */
/* *\/ */
/* for (i = 0, sp = scores; i < nscores; sp += n) { */
/* n = 20; */
/* if (i + n > nscores) */
/* n = nscores - i; */
/* printem(level, i + 1, sp, n, me); */
/* if ((i += n) < nscores) { */
/* (void)printf("\nHit RETURN to continue."); */
/* (void)fflush(stdout); */
/* while ((c = getchar()) != '\n') */
/* if (c == EOF) */
/* break; */
/* (void)printf("\n"); */
/* } */
/* } */
 
/* if (nscores == 0) */
/* printf("\t\t\t - none to date.\n"); */
/* } */
 
/* static void */
/* printem(int level, int offset, struct highscore *hs, int n, const char *me) */
/* { */
/* struct highscore *sp; */
/* int row, highlight, i; */
/* char buf[100]; */
/* #define TITLE "Rank Score Name (points/level)" */
/* #define TITL2 "==========================================================" */
 
/* printf("%s\n%s\n", TITLE, TITL2); */
 
/* highlight = 0; */
 
/* for (row = 0; row < n; row++) { */
/* sp = &hs[row]; */
/* (void)snprintf(buf, sizeof(buf), */
/* "%3d%c %6d %-31s (%6d on %d)\n", */
/* row + offset, sp->hs_time ? '*' : ' ', */
/* sp->hs_score * sp->hs_level, */
/* sp->hs_name, sp->hs_score, sp->hs_level); */
/* /\* Print leaders every three lines *\/ */
/* if ((row + 1) % 3 == 0) { */
/* for (i = 0; i < sizeof(buf); i++) */
/* if (buf[i] == ' ') */
/* buf[i] = '_'; */
/* } */
/* /\* */
/* * Highlight if appropriate. This works because */
/* * we only get one score per level. */
/* *\/ */
/* if (me != NULL && */
/* sp->hs_level == level && */
/* sp->hs_score == score && */
/* str_cmp(sp->hs_name, me) == 0) { */
/* putpad(SOstr); */
/* highlight = 1; */
/* } */
/* (void)printf("%s", buf); */
/* if (highlight) { */
/* putpad(SEstr); */
/* highlight = 0; */
/* } */
/* } */
/* } */
 
/** @}
*/
 
/branches/dd/uspace/app/tetris/input.c
36,7 → 36,7
*/
 
/** @addtogroup tetris
* @{
* @{
*/
/** @file
*/
57,9 → 57,9
#include "tetris.h"
 
#include <async.h>
#include <vfs/vfs.h>
#include <io/console.h>
#include <ipc/console.h>
#include <console.h>
#include <kbd/kbd.h>
 
/* return true iff the given timeval is positive */
#define TV_POS(tv) \
92,14 → 92,12
* Return 0 => no input, 1 => can read() from stdin
*
*/
int
rwait(struct timeval *tvp)
int rwait(struct timeval *tvp)
{
struct timeval starttv, endtv, *s;
static ipc_call_t charcall;
ipcarg_t rc;
int cons_phone;
 
/*
* Someday, select() will do this for us.
* Just in case that day is now, and no one has
111,15 → 109,15
s = &endtv;
} else
s = NULL;
 
if (!lastchar) {
again:
if (!getchar_inprog) {
cons_phone = console_open(true);
getchar_inprog = async_send_2(cons_phone,
CONSOLE_GETKEY, 0, 0, &charcall);
getchar_inprog = async_send_0(fphone(stdin),
CONSOLE_GET_EVENT, &charcall);
}
if (!s)
if (!s)
async_wait_for(getchar_inprog, &rc);
else if (async_wait_timeout(getchar_inprog, &rc, s->tv_usec) == ETIMEOUT) {
tvp->tv_sec = 0;
126,22 → 124,25
tvp->tv_usec = 0;
return (0);
}
getchar_inprog = 0;
if (rc) {
if (rc)
stop("end of file, help");
}
if (IPC_GET_ARG1(charcall) == KE_RELEASE)
if (IPC_GET_ARG1(charcall) == KEY_RELEASE)
goto again;
 
lastchar = IPC_GET_ARG4(charcall);
}
if (tvp) {
/* since there is input, we may not have timed out */
(void) gettimeofday(&endtv, NULL);
TV_SUB(&endtv, &starttv);
TV_SUB(tvp, &endtv); /* adjust *tvp by elapsed time */
TV_SUB(tvp, &endtv); /* adjust *tvp by elapsed time */
}
return (1);
return 1;
}
 
/*
148,11 → 149,10
* `sleep' for the current turn time (using select).
* Eat any input that might be available.
*/
void
tsleep(void)
void tsleep(void)
{
struct timeval tv;
 
tv.tv_sec = 0;
tv.tv_usec = fallrate;
while (TV_POS(&tv))
165,12 → 165,11
/*
* getchar with timeout.
*/
int
tgetchar(void)
int tgetchar(void)
{
static struct timeval timeleft;
char c;
 
/*
* Reset timeleft to fallrate whenever it is not positive.
* In any case, wait to see if there is any input. If so,
181,17 → 180,18
* Most of the hard work is done by rwait().
*/
if (!TV_POS(&timeleft)) {
faster(); /* go faster */
faster(); /* go faster */
timeleft.tv_sec = 0;
timeleft.tv_usec = fallrate;
}
if (!rwait(&timeleft))
return (-1);
return -1;
c = lastchar;
lastchar = '\0';
return ((int)(unsigned char)c);
return ((int) (unsigned char) c);
}
 
/** @}
*/
 
/branches/dd/uspace/app/tetris/screen.c
36,7 → 36,7
*/
 
/** @addtogroup tetris
* @{
* @{
*/
/** @file
*/
50,21 → 50,24
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <console.h>
 
#include <vfs/vfs.h>
#include <async.h>
#include "screen.h"
#include "tetris.h"
#include <ipc/console.h>
#include <io/console.h>
 
static cell curscreen[B_SIZE]; /* 1 => standout (or otherwise marked) */
#define STOP (B_COLS - 3)
 
static cell curscreen[B_SIZE]; /* non-zero => standout (or otherwise marked) */
static int curscore;
static int isset; /* true => terminal is in game mode */
static int isset; /* true => terminal is in game mode */
 
static const struct shape *lastshape;
 
 
/*
* putstr() is for unpadded strings (either as in termcap(5) or
* simply literal strings);
* simply literal strings);
*/
static inline void putstr(char *s)
{
72,19 → 75,19
putchar(*(s++));
}
 
static void start_standout(void)
static void start_standout(uint32_t color)
{
console_set_rgb_color(0xf0f0f0, 0);
console_set_rgb_color(fphone(stdout), 0xf0f0f0, color);
}
 
static void resume_normal(void)
{
console_set_rgb_color(0, 0xf0f0f0);
console_set_rgb_color(fphone(stdout), 0, 0xf0f0f0);
}
 
void clear_screen(void)
{
console_clear();
console_clear(fphone(stdout));
moveto(0, 0);
}
 
91,23 → 94,20
/*
* Clear the screen, forgetting the current contents in the process.
*/
void
scr_clear(void)
void scr_clear(void)
{
 
resume_normal();
console_clear();
console_clear(fphone(stdout));
curscore = -1;
memset((char *)curscreen, 0, sizeof(curscreen));
memset(curscreen, 0, sizeof(curscreen));
}
 
/*
* Set up screen
*/
void
scr_init(void)
void scr_init(void)
{
console_cursor_visibility(0);
console_cursor_visibility(fphone(stdout), 0);
resume_normal();
scr_clear();
}
114,7 → 114,7
 
void moveto(int r, int c)
{
console_goto(r, c);
console_goto(fphone(stdout), c, r);
}
 
winsize_t winsize;
121,25 → 121,27
 
static int get_display_size(winsize_t *ws)
{
return console_get_size(&ws->ws_row, &ws->ws_col);
return console_get_size(fphone(stdout), &ws->ws_col, &ws->ws_row);
}
 
/*
* Set up screen mode.
*/
void
scr_set(void)
void scr_set(void)
{
winsize_t ws;
 
Rows = 0, Cols = 0;
Rows = 0;
Cols = 0;
if (get_display_size(&ws) == 0) {
Rows = ws.ws_row;
Cols = ws.ws_col;
}
if (Rows < MINROWS || Cols < MINCOLS) {
if ((Rows < MINROWS) || (Cols < MINCOLS)) {
char smallscr[55];
 
snprintf(smallscr, sizeof(smallscr),
"the screen is too small (must be at least %dx%d)",
MINROWS, MINCOLS);
146,7 → 148,7
stop(smallscr);
}
isset = 1;
 
scr_clear();
}
 
153,76 → 155,80
/*
* End screen mode.
*/
void
scr_end(void)
void scr_end(void)
{
console_cursor_visibility(fphone(stdout), 1);
}
 
void
stop(char *why)
void stop(char *why)
{
 
if (isset)
scr_end();
errx(1, "aborting: %s", why);
}
 
 
/*
* Update the screen.
*/
void
scr_update(void)
void scr_update(void)
{
cell *bp, *sp;
cell so, cur_so = 0;
int i, ccol, j;
static const struct shape *lastshape;
 
/* always leave cursor after last displayed point */
cell *bp;
cell *sp;
cell so;
cell cur_so = 0;
int i;
int j;
int ccol;
/* Always leave cursor after last displayed point */
curscreen[D_LAST * B_COLS - 1] = -1;
 
if (score != curscore) {
moveto(0, 0);
printf("Score: %d", score);
curscore = score;
}
 
/* draw preview of next pattern */
if (showpreview && (nextshape != lastshape)) {
/* Draw preview of next pattern */
if ((showpreview) && (nextshape != lastshape)) {
int i;
static int r=5, c=2;
static int r = 5, c = 2;
int tr, tc, t;
 
lastshape = nextshape;
 
/* clean */
/* Clean */
resume_normal();
moveto(r-1, c-1); putstr(" ");
moveto(r, c-1); putstr(" ");
moveto(r+1, c-1); putstr(" ");
moveto(r+2, c-1); putstr(" ");
 
moveto(r-3, c-2);
moveto(r - 1, c - 1);
putstr(" ");
moveto(r, c - 1);
putstr(" ");
moveto(r + 1, c - 1);
putstr(" ");
moveto(r + 2, c - 1);
putstr(" ");
moveto(r - 3, c - 2);
putstr("Next shape:");
 
/* draw */
start_standout();
/* Draw */
start_standout(nextshape->color);
moveto(r, 2 * c);
putstr(" ");
for (i = 0; i < 3; i++) {
t = c + r * B_COLS;
t += nextshape->off[i];
 
tr = t / B_COLS;
tc = t % B_COLS;
 
moveto(tr, 2*tc);
putstr(" ");
}
resume_normal();
}
 
bp = &board[D_FIRST * B_COLS];
sp = &curscreen[D_FIRST * B_COLS];
for (j = D_FIRST; j < D_LAST; j++) {
230,6 → 236,7
for (i = 0; i < B_COLS; bp++, sp++, i++) {
if (*sp == (so = *bp))
continue;
*sp = so;
if (i != ccol) {
if (cur_so) {
238,15 → 245,16
}
moveto(RTOD(j), CTOD(i));
}
if (so != cur_so) {
if (so)
start_standout();
start_standout(so);
else
resume_normal();
cur_so = so;
}
putstr(" ");
 
ccol = i + 1;
/*
* Look ahead a bit, to avoid extra motion if
256,33 → 264,35
* `unnecessarily'. Skip it all, though, if
* the next cell is a different color.
*/
#define STOP (B_COLS - 3)
if (i > STOP || sp[1] != bp[1] || so != bp[1])
if ((i > STOP) || (sp[1] != bp[1]) || (so != bp[1]))
continue;
if (sp[2] != bp[2])
sp[1] = -1;
else if (i < STOP && so == bp[2] && sp[3] != bp[3]) {
else if ((i < STOP) && (so == bp[2]) && (sp[3] != bp[3])) {
sp[2] = -1;
sp[1] = -1;
}
}
}
if (cur_so)
resume_normal();
fflush(stdout);
fflush(stdout);
}
 
/*
* Write a message (set!=0), or clear the same message (set==0).
* Write a message (set != 0), or clear the same message (set == 0).
* (We need its length in case we have to overwrite with blanks.)
*/
void
scr_msg(char *s, int set)
void scr_msg(char *s, int set)
{
int l = str_size(s);
moveto(Rows - 2, ((Cols - l) >> 1) - 1);
if (set)
putstr(s);
else
292,4 → 302,3
 
/** @}
*/
 
/branches/dd/uspace/app/tetris/tetris.h
36,7 → 36,7
*/
 
/** @addtogroup tetris
* @{
* @{
*/
/** @file
*/
55,57 → 55,60
* worrying about addressing problems.
*/
 
/* the board */
#define B_COLS 12
#define B_ROWS 23
#define B_SIZE (B_ROWS * B_COLS)
/* The board */
#define B_COLS 12
#define B_ROWS 23
#define B_SIZE (B_ROWS * B_COLS)
 
typedef unsigned char cell;
extern cell board[B_SIZE]; /* 1 => occupied, 0 => empty */
typedef uint32_t cell;
 
/* the displayed area (rows) */
#define D_FIRST 1
#define D_LAST 22
extern cell board[B_SIZE]; /* 1 => occupied, 0 => empty */
 
/* the active area (rows) */
#define A_FIRST 1
#define A_LAST 21
/* The displayed area (rows) */
#define D_FIRST 1
#define D_LAST 22
 
/* The active area (rows) */
#define A_FIRST 1
#define A_LAST 21
 
/*
* Minimum display size.
*/
#define MINROWS 23
#define MINCOLS 40
#define MINROWS 23
#define MINCOLS 40
 
extern int Rows, Cols; /* current screen size */
/* Current screen size */
extern int Rows;
extern int Cols;
 
/*
* Translations from board coordinates to display coordinates.
* As with board coordinates, display coordiates are zero origin.
*/
#define RTOD(x) ((x) - 1)
#define CTOD(x) ((x) * 2 + (((Cols - 2 * B_COLS) >> 1) - 1))
#define RTOD(x) ((x) - 1)
#define CTOD(x) ((x) * 2 + (((Cols - 2 * B_COLS) >> 1) - 1))
 
/*
* A `shape' is the fundamental thing that makes up the game. There
* are 7 basic shapes, each consisting of four `blots':
*
* X.X X.X X.X
* X.X X.X X.X.X X.X X.X.X X.X.X X.X.X.X
* X X X
* X.X X.X X.X
* X.X X.X X.X.X X.X X.X.X X.X.X X.X.X.X
* X X X
*
* 0 1 2 3 4 5 6
* 0 1 2 3 4 5 6
*
* Except for 3 and 6, the center of each shape is one of the blots.
* This blot is designated (0,0). The other three blots can then be
* This blot is designated (0, 0). The other three blots can then be
* described as offsets from the center. Shape 3 is the same under
* rotation, so its center is effectively irrelevant; it has been chosen
* so that it `sticks out' upward and leftward. Except for shape 6,
* all the blots are contained in a box going from (-1,-1) to (+1,+1);
* all the blots are contained in a box going from (-1, -1) to (+1, +1);
* shape 6's center `wobbles' as it rotates, so that while it `sticks out'
* rightward, its rotation---a vertical line---`sticks out' downward.
* The containment box has to include the offset (2,0), making the overall
* containment box range from offset (-1,-1) to (+2,+1). (This is why
* The containment box has to include the offset (2, 0), making the overall
* containment box range from offset (-1, -1) to (+2, +1). (This is why
* there is only one row above, but two rows below, the display area.)
*
* The game works by choosing one of these shapes at random and putting
116,7 → 119,7
* At this time, any completely filled rows are elided, and blots above
* these rows move down to make more room. A new random shape is again
* introduced at the top of the board, and the whole process repeats.
* The game ends when the new shape will not fit at (1,5).
* The game ends when the new shape will not fit at (1, 5).
*
* While the shapes are falling, the user can rotate them counterclockwise
* 90 degrees (in addition to moving them left or right), provided that the
128,9 → 131,10
* rotated forms.
*/
struct shape {
int rot; /* index of rotated version of this shape */
int rotc; /* -- " -- in classic version */
int off[3]; /* offsets to other blots if center is at (0,0) */
int rot; /* index of rotated version of this shape */
int rotc; /* -- " -- in classic version */
int off[3]; /* offsets to other blots if center is at (0,0) */
uint32_t color;
};
 
extern const struct shape shapes[];
148,15 → 152,16
* The value eventually reaches a limit, and things stop going faster,
* but by then the game is utterly impossible.
*/
extern long fallrate; /* less than 1 million; smaller => faster */
#define faster() (fallrate -= fallrate / 3000)
extern long fallrate; /* less than 1 million; smaller => faster */
 
#define faster() (fallrate -= fallrate / 3000)
 
/*
* Game level must be between 1 and 9. This controls the initial fall rate
* and affects scoring.
*/
#define MINLEVEL 1
#define MAXLEVEL 9
#define MINLEVEL 1
#define MAXLEVEL 9
 
/*
* Scoring is as follows:
170,19 → 175,17
*
* If previewing has been turned on, the score is multiplied by PRE_PENALTY.
*/
#define PRE_PENALTY 0.75
#define PRE_PENALTY 0.75
 
extern int score; /* the obvious thing */
//extern gid_t gid, egid;
extern int score; /* The obvious thing */
 
extern char key_msg[100];
extern int showpreview;
extern int classic;
extern char key_msg[100];
extern int showpreview;
extern int classic;
 
int fits_in(const struct shape *, int);
void place(const struct shape *, int, int);
void stop(char *);
extern int fits_in(const struct shape *, int);
extern void place(const struct shape *, int, int);
extern void stop(char *);
 
/** @}
*/
 
/branches/dd/uspace/app/tetris/scores.h
34,8 → 34,9
*
* @(#)scores.h 8.1 (Berkeley) 5/31/93
*/
 
/** @addtogroup tetris
* @{
* @{
*/
/** @file
*/
44,26 → 45,25
/*
* Tetris scores.
*/
 
#include <sys/time.h>
#include <string.h>
 
#define MAXLOGNAME 16
#define MAXLOGNAME 16
#define MAXHISCORES 10
#define MAXSCORES 9 /* maximum high score entries per person */
#define EXPIRATION (5L * 365 * 24 * 60 * 60)
 
struct highscore {
char hs_name[STR_BOUNDS(MAXLOGNAME) + 1]; /* login name */
int hs_score; /* raw score */
int hs_level; /* play level */
// time_t hs_time; /* time at game end */
char hs_name[STR_BOUNDS(MAXLOGNAME) + 1]; /* login name */
int hs_score; /* raw score */
int hs_level; /* play level */
time_t hs_time; /* time at game end */
};
 
#define MAXHISCORES 10
//#define MAXSCORES 9 /* maximum high score entries per person */
//#define EXPIRATION (5L * 365 * 24 * 60 * 60)
extern void showscores(int);
extern void initscores(void);
extern void insertscore(int score, int level);
 
void savescore(int);
void showscores(int);
void insertscore(int score, int level);
void initscores(void);
 
/** @}
*/
 
/branches/dd/uspace/app/tetris/shapes.c
36,7 → 36,7
*/
 
/** @addtogroup tetris
* @{
* @{
*/
/** @file
*/
50,35 → 50,35
#include <unistd.h>
#include "tetris.h"
 
#define TL -B_COLS-1 /* top left */
#define TC -B_COLS /* top center */
#define TR -B_COLS+1 /* top right */
#define ML -1 /* middle left */
#define MR 1 /* middle right */
#define BL B_COLS-1 /* bottom left */
#define BC B_COLS /* bottom center */
#define BR B_COLS+1 /* bottom right */
#define TL (-B_COLS - 1) /* top left */
#define TC (-B_COLS) /* top center */
#define TR (-B_COLS + 1) /* top right */
#define ML -1 /* middle left */
#define MR 1 /* middle right */
#define BL (B_COLS - 1) /* bottom left */
#define BC B_COLS /* bottom center */
#define BR (B_COLS + 1) /* bottom right */
 
const struct shape shapes[] = {
/* 0*/ { 7, 7, { TL, TC, MR } },
/* 1*/ { 8, 8, { TC, TR, ML } },
/* 2*/ { 9, 11, { ML, MR, BC } },
/* 3*/ { 3, 3, { TL, TC, ML } },
/* 4*/ { 12, 14, { ML, BL, MR } },
/* 5*/ { 15, 17, { ML, BR, MR } },
/* 6*/ { 18, 18, { ML, MR, 2 } }, /* sticks out */
/* 7*/ { 0, 0, { TC, ML, BL } },
/* 8*/ { 1, 1, { TC, MR, BR } },
/* 9*/ { 10, 2, { TC, MR, BC } },
/*10*/ { 11, 9, { TC, ML, MR } },
/*11*/ { 2, 10, { TC, ML, BC } },
/*12*/ { 13, 4, { TC, BC, BR } },
/*13*/ { 14, 12, { TR, ML, MR } },
/*14*/ { 4, 13, { TL, TC, BC } },
/*15*/ { 16, 5, { TR, TC, BC } },
/*16*/ { 17, 15, { TL, MR, ML } },
/*17*/ { 5, 16, { TC, BC, BL } },
/*18*/ { 6, 6, { TC, BC, 2*B_COLS } }/* sticks out */
/* 0 */ { 7, 7, { TL, TC, MR }, 0xff042d},
/* 1 */ { 8, 8, { TC, TR, ML }, 0xff9304},
/* 2 */ { 9, 11, { ML, MR, BC }, 0xbeff04},
/* 3 */ { 3, 3, { TL, TC, ML }, 0x63ff04},
/* 4 */ { 12, 14, { ML, BL, MR }, 0xce04ff},
/* 5 */ { 15, 17, { ML, BR, MR }, 0xff04cf},
/* 6 */ { 18, 18, { ML, MR, 2 }, 0x7604ff}, /* sticks out */
/* 7 */ { 0, 0, { TC, ML, BL }, 0xff042d},
/* 8 */ { 1, 1, { TC, MR, BR }, 0xff9304},
/* 9 */ { 10, 2, { TC, MR, BC }, 0xbeff04},
/* 10 */ { 11, 9, { TC, ML, MR }, 0xbeff04},
/* 11 */ { 2, 10, { TC, ML, BC }, 0xbeff04},
/* 12 */ { 13, 4, { TC, BC, BR }, 0xce04ff},
/* 13 */ { 14, 12, { TR, ML, MR }, 0xce04ff},
/* 14 */ { 4, 13, { TL, TC, BC }, 0xce04ff},
/* 15 */ { 16, 5, { TR, TC, BC }, 0xff04cf},
/* 16 */ { 17, 15, { TL, MR, ML }, 0xff04cf},
/* 17 */ { 5, 16, { TC, BC, BL }, 0xff04cf},
/* 18 */ { 6, 6, { TC, BC, 2 * B_COLS }, 0x7604ff} /* sticks out */
};
 
/*
85,14 → 85,14
* Return true iff the given shape fits in the given position,
* taking the current board into account.
*/
int
fits_in(const struct shape *shape, int pos)
int fits_in(const struct shape *shape, int pos)
{
int *o = shape->off;
 
if (board[pos] || board[pos + *o++] || board[pos + *o++] ||
board[pos + *o])
if ((board[pos]) || (board[pos + *o++]) || (board[pos + *o++]) ||
(board[pos + *o]))
return 0;
return 1;
}
 
100,17 → 100,15
* Write the given shape into the current board, turning it on
* if `onoff' is 1, and off if `onoff' is 0.
*/
void
place(const struct shape *shape, int pos, int onoff)
void place(const struct shape *shape, int pos, int onoff)
{
int *o = shape->off;
 
board[pos] = onoff;
board[pos + *o++] = onoff;
board[pos + *o++] = onoff;
board[pos + *o] = onoff;
board[pos] = onoff ? shape->color : 0x000000;
board[pos + *o++] = onoff ? shape->color : 0x000000;
board[pos + *o++] = onoff ? shape->color : 0x000000;
board[pos + *o] = onoff ? shape->color : 0x000000;
}
 
/** @}
*/
 
/branches/dd/uspace/app/tetris/input.h
36,15 → 36,14
*/
 
/** @addtogroup tetris
* @{
* @{
*/
/** @file
*/
 
int rwait(struct timeval *);
int tgetchar(void);
void tsleep(void);
extern int rwait(struct timeval *);
extern int tgetchar(void);
extern void tsleep(void);
 
/** @}
*/
 
/branches/dd/uspace/app/tetris/screen.h
36,36 → 36,37
*/
 
/** @addtogroup tetris
* @{
* @{
*/
/** @file
*/
 
/*
* putpad() is for padded strings with count=1.
* putpad() is for padded strings with count = 1.
*/
#define putpad(s) tputs(s, 1, put)
#define putpad(s) tputs(s, 1, put)
 
#include <sys/types.h>
#include <async.h>
 
typedef struct {
int ws_row;
int ws_col;
ipcarg_t ws_row;
ipcarg_t ws_col;
} winsize_t;
 
extern winsize_t winsize;
 
void moveto(int r, int c);
void clear_screen(void);
extern void moveto(int r, int c);
extern void clear_screen(void);
 
int put(int); /* just calls putchar; for tputs */
void scr_clear(void);
void scr_end(void);
void scr_init(void);
void scr_msg(char *, int);
void scr_set(void);
void scr_update(void);
/* just calls putchar; for tputs */
extern int put(int);
extern void scr_clear(void);
extern void scr_end(void);
extern void scr_init(void);
extern void scr_msg(char *, int);
extern void scr_set(void);
extern void scr_update(void);
 
/** @}
*/
 
/branches/dd/uspace/app/tetris/tetris.c
36,30 → 36,24
*/
 
/** @addtogroup tetris Tetris
* @brief Tetris ported from OpenBSD
* @{
* @brief Tetris ported from OpenBSD
* @{
*/
/** @file
*/
 
#ifndef lint
static const char copyright[] =
"@(#) Copyright (c) 1992, 1993\n\
The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */
"@(#) Copyright (c) 1992, 1993\n"
"\tThe Regents of the University of California. All rights reserved.\n";
 
/*
* Tetris (or however it is spelled).
*/
 
#include <sys/time.h>
#include <sys/types.h>
 
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <getopt.h>
 
#include "input.h"
#include "scores.h"
66,66 → 60,76
#include "screen.h"
#include "tetris.h"
 
cell board[B_SIZE];
int Rows, Cols;
cell board[B_SIZE];
 
int Rows;
int Cols;
 
const struct shape *curshape;
const struct shape *nextshape;
long fallrate;
int score;
//gid_t gid, egid;
char key_msg[100];
int showpreview, classic;
 
static void elide(void);
static void setup_board(void);
const struct shape *randshape(void);
void onintr(int);
void usage(void);
long fallrate;
int score;
char key_msg[100];
int showpreview;
int classic;
 
static void elide(void);
static void setup_board(void);
static const struct shape *randshape(void);
 
static void usage(void);
 
static int firstgame = 1;
 
/*
* Set up the initial board. The bottom display row is completely set,
* along with another (hidden) row underneath that. Also, the left and
* Set up the initial board. The bottom display row is completely set,
* along with another (hidden) row underneath that. Also, the left and
* right edges are set.
*/
static void
setup_board(void)
static void setup_board(void)
{
int i;
cell *p;
 
p = board;
cell *p = board;
for (i = B_SIZE; i; i--)
*p++ = i <= (2 * B_COLS) || (i % B_COLS) < 2;
*p++ = (i <= (2 * B_COLS) || (i % B_COLS) < 2) ? 0x0000ff : 0x000000;
}
 
/*
* Elide any full active rows.
*/
static void
elide(void)
static void elide(void)
{
int rows = 0;
int i, j, base;
int i;
int j;
int base;
cell *p;
 
for (i = A_FIRST; i < A_LAST; i++) {
base = i * B_COLS + 1;
p = &board[base];
for (j = B_COLS - 2; *p++ != 0;) {
if (--j <= 0) {
/* this row is to be elided */
/* This row is to be elided */
rows++;
memset(&board[base], 0, B_COLS - 2);
memset(&board[base], 0, sizeof(cell) * (B_COLS - 2));
scr_update();
tsleep();
while (--base != 0)
board[base + B_COLS] = board[base];
scr_update();
tsleep();
break;
}
}
}
switch (rows) {
case 1:
score += 10;
144,16 → 148,15
}
}
 
const struct shape *
randshape(void)
const struct shape *randshape(void)
{
const struct shape *tmp;
int i, j;
 
tmp = &shapes[random() % 7];
j = random() % 4;
const struct shape *tmp = &shapes[random() % 7];
int i;
int j = random() % 4;
for (i = 0; i < j; i++)
tmp = &shapes[classic? tmp->rotc : tmp->rot];
tmp = &shapes[classic ? tmp->rotc : tmp->rot];
return (tmp);
}
 
160,7 → 163,7
static void srandomdev(void)
{
struct timeval tv;
 
gettimeofday(&tv, NULL);
srandom(tv.tv_sec + tv.tv_usec / 100000);
}
167,59 → 170,40
 
static void tetris_menu_draw(int level)
{
clear_screen();
moveto(5,10);
puts("Tetris\n\n");
moveto(8,10);
printf("Level = %d (press keys 1 - 9 to change)",level);
moveto(9,10);
printf("Preview is %s (press 'p' to change)", (showpreview?"on ":"off"));
moveto(12,10);
printf("Press 'h' to show hiscore table.");
moveto(13,10);
printf("Press 's' to start game.");
moveto(14,10);
printf("Press 'q' to quit game.");
moveto(20,10);
printf("In game controls:");
moveto(21,0);
puts(key_msg);
clear_screen();
moveto(5, 10);
puts("Tetris\n\n");
moveto(8, 10);
printf("Level = %d (press keys 1 - 9 to change)", level);
moveto(9, 10);
printf("Preview is %s (press 'p' to change)", (showpreview ? "on ": "off"));
moveto(12, 10);
printf("Press 'h' to show hiscore table.");
moveto(13, 10);
printf("Press 's' to start game.");
moveto(14, 10);
printf("Press 'q' to quit game.");
moveto(20, 10);
printf("In game controls:");
moveto(21, 0);
puts(key_msg);
}
 
static int tetris_menu(int *level)
static int tetris_menu(int *level)
{
static int firstgame = 1;
int i;
/* if (showpreview == 0)
(void)printf("Your score: %d point%s x level %d = %d\n",
score, score == 1 ? "" : "s", level, score * level);
else {
(void)printf("Your score: %d point%s x level %d x preview penalty %0.3f = %d\n",
score, score == 1 ? "" : "s", level, (double)PRE_PENALTY,
(int)(score * level * PRE_PENALTY));
score = score * PRE_PENALTY;
}
savescore(level);
 
showscores(level);
printf("\nHit 's' to new game, 'q' to quit.\n");
*/
tetris_menu_draw(*level);
while (1) {
i = getchar();
int i = getchar();
switch(i) {
case 'p':
showpreview = !showpreview;
moveto(9,21);
moveto(9, 21);
if (showpreview)
printf("on ");
else
printf("off");
break;
case 'h':
showscores(firstgame);
235,94 → 219,83
case '3':
case '4':
case '5':
case '6':
case '6':
case '7':
case '8':
case '9':
*level = i - '0';
moveto(8,18);
moveto(8, 18);
printf("%d", *level);
break;
}
}
}
 
int
main(int argc, char *argv[])
int main(int argc, char *argv[])
{
int pos, c;
int pos;
int c;
char *keys;
int level = 2;
char key_write[6][10];
int i, j;
 
int i;
int j;
int ch;
keys = "jkl pq";
 
// gid = getgid();
// egid = getegid();
// setegid(gid);
 
classic = 0;
showpreview = 1;
 
/* while ((ch = getopt(argc, argv, "ck:l:ps")) != -1) */
/* switch(ch) { */
/* case 'c': */
/* /\* */
/* * this means: */
/* * - rotate the other way; */
/* * - no reverse video. */
/* *\/ */
/* classic = 1; */
/* break; */
/* case 'k': */
/* if (str_size(keys = optarg) != 6) */
/* usage(); */
/* break; */
/* case 'l': */
/* level = (int)strtonum(optarg, MINLEVEL, MAXLEVEL, */
/* &errstr); */
/* if (errstr) */
/* errx(1, "level must be from %d to %d", */
/* MINLEVEL, MAXLEVEL); */
/* break; */
/* case 'p': */
/* showpreview = 1; */
/* break; */
/* case 's': */
/* showscores(0); */
/* exit(0); */
/* default: */
/* usage(); */
/* } */
 
/* argc -= optind; */
/* argv += optind; */
 
/* if (argc) */
/* usage(); */
 
 
while ((ch = getopt(argc, argv, "ck:ps")) != -1)
switch(ch) {
case 'c':
/*
* this means:
* - rotate the other way
* - no reverse video
*/
classic = 1;
break;
case 'k':
if (str_size(keys = optarg) != 6)
usage();
break;
case 'p':
showpreview = 1;
break;
case 's':
showscores(0);
exit(0);
default:
usage();
}
argc -= optind;
argv += optind;
if (argc)
usage();
for (i = 0; i <= 5; i++) {
for (j = i+1; j <= 5; j++) {
for (j = i + 1; j <= 5; j++) {
if (keys[i] == keys[j])
errx(1, "duplicate command keys specified.");
}
if (keys[i] == ' ')
str_cpy(key_write[i], sizeof key_write[i], "<space>");
str_cpy(key_write[i], sizeof(key_write[i]), "<space>");
else {
key_write[i][0] = keys[i];
key_write[i][1] = '\0';
}
}
 
snprintf(key_msg, sizeof key_msg,
"%s - left %s - rotate %s - right %s - drop %s - pause %s - quit",
key_write[0], key_write[1], key_write[2], key_write[3],
key_write[4], key_write[5]);
 
snprintf(key_msg, sizeof(key_msg),
"%s - left %s - rotate %s - right %s - drop %s - pause %s - quit",
key_write[0], key_write[1], key_write[2], key_write[3],
key_write[4], key_write[5]);
scr_init();
initscores();
while (tetris_menu(&level)) {
330,17 → 303,17
scr_clear();
setup_board();
srandomdev();
scr_set();
pos = A_FIRST*B_COLS + (B_COLS/2)-1;
pos = A_FIRST * B_COLS + (B_COLS / 2) - 1;
nextshape = randshape();
curshape = randshape();
scr_msg(key_msg, 1);
for (;;) {
while (1) {
place(curshape, pos, 1);
scr_update();
place(curshape, pos, 0);
353,7 → 326,7
pos += B_COLS;
continue;
}
/*
* Put up the current shape `permanently',
* bump score, and elide any full rows.
361,7 → 334,7
place(curshape, pos, 1);
score++;
elide();
/*
* Choose a new shape. If it does not fit,
* the game is over.
368,12 → 341,14
*/
curshape = nextshape;
nextshape = randshape();
pos = A_FIRST*B_COLS + (B_COLS/2)-1;
pos = A_FIRST * B_COLS + (B_COLS / 2) - 1;
if (!fits_in(curshape, pos))
break;
continue;
}
/*
* Handle command keys.
*/
381,10 → 356,11
/* quit */
break;
}
if (c == keys[4]) {
static char msg[] =
"paused - press RETURN to continue";
place(curshape, pos, 1);
do {
scr_update();
391,12 → 367,14
scr_msg(key_msg, 0);
scr_msg(msg, 1);
(void) fflush(stdout);
} while (rwait((struct timeval *)NULL) == -1);
} while (rwait((struct timeval *) NULL) == -1);
scr_msg(msg, 0);
scr_msg(key_msg, 1);
place(curshape, pos, 0);
continue;
}
if (c == keys[0]) {
/* move left */
if (fits_in(curshape, pos - 1))
403,15 → 381,17
pos--;
continue;
}
if (c == keys[1]) {
/* turn */
const struct shape *new = &shapes[
classic? curshape->rotc : curshape->rot];
const struct shape *new =
&shapes[classic ? curshape->rotc : curshape->rot];
if (fits_in(new, pos))
curshape = new;
continue;
}
if (c == keys[2]) {
/* move right */
if (fits_in(curshape, pos + 1))
418,6 → 398,7
pos++;
continue;
}
if (c == keys[3]) {
/* move to bottom */
while (fits_in(curshape, pos + B_COLS)) {
426,6 → 407,7
}
continue;
}
if (c == '\f') {
scr_clear();
scr_msg(key_msg, 1);
434,36 → 416,21
scr_clear();
insertscore(score, level);
score=0;
score = 0;
}
scr_clear();
printf("\n\n\n\t\tGame over.\n");
/*
while ((i = getchar()) != '\n')
if (i == EOF)
break
*/
printf("\nGame over.\n");
scr_end();
 
return 0;
}
 
/* void */
/* onintr(int signo) */
/* { */
/* scr_clear(); /\* XXX signal race *\/ */
/* scr_end(); /\* XXX signal race *\/ */
/* _exit(0); */
/* } */
 
void
usage(void)
void usage(void)
{
(void)fprintf(stderr, "usage: tetris [-ps] [-k keys] [-l level]\n");
fprintf(stderr, "usage: tetris [-ps] [-k keys]\n");
exit(1);
}
 
/** @}
*/
 
/branches/dd/uspace/app/klog/klog.c
40,41 → 40,34
#include <ipc/services.h>
#include <as.h>
#include <sysinfo.h>
#include <io/stream.h>
#include <console.h>
#include <event.h>
#include <errno.h>
#include <io/klog.h>
 
#define NAME "klog"
#define NAME "klog"
 
/* Pointer to klog area */
static wchar_t *klog;
static count_t klog_length;
static size_t klog_length;
 
static void interrupt_received(ipc_callid_t callid, ipc_call_t *call)
{
async_serialize_start();
size_t klog_start = (size_t) IPC_GET_ARG1(*call);
size_t klog_len = (size_t) IPC_GET_ARG2(*call);
size_t klog_stored = (size_t) IPC_GET_ARG3(*call);
size_t i;
count_t klog_start = (count_t) IPC_GET_ARG1(*call);
count_t klog_len = (count_t) IPC_GET_ARG2(*call);
count_t klog_stored = (count_t) IPC_GET_ARG3(*call);
count_t i;
for (i = klog_len - klog_stored; i < klog_len; i++)
putchar(klog[(klog_start + i) % klog_length]);
async_serialize_end();
}
 
int main(int argc, char *argv[])
{
console_wait();
count_t klog_pages = sysinfo_value("klog.pages");
size_t klog_pages = sysinfo_value("klog.pages");
size_t klog_size = klog_pages * PAGE_SIZE;
klog_length = klog_size / sizeof(wchar_t);
klog = (wchar_t *) as_get_mappable_page(klog_pages);
klog = (wchar_t *) as_get_mappable_page(klog_size);
if (klog == NULL) {
printf(NAME ": Error allocating memory area\n");
return -1;
/branches/dd/uspace/app/trace/trace.c
41,6 → 41,8
#include <udebug.h>
#include <async.h>
#include <task.h>
#include <mem.h>
#include <string.h>
#include <loader/loader.h>
 
#include <libc.h>
661,13 → 663,8
resp_def[0] = V_INTEGER; resp_def[1] = V_INTEGER;
resp_def[2] = V_INTEGER; resp_def[3] = V_CHAR;
o = oper_new("getkey", 0, arg_def, V_ERRNO, 4, resp_def);
proto_add_oper(p, CONSOLE_GETKEY, o);
 
arg_def[0] = V_CHAR;
o = oper_new("putchar", 1, arg_def, V_VOID, 0, resp_def);
proto_add_oper(p, CONSOLE_PUTCHAR, o);
o = oper_new("write", 0, arg_def, V_VOID, 0, resp_def);
proto_add_oper(p, CONSOLE_WRITE, o);
o = oper_new("clear", 0, arg_def, V_VOID, 0, resp_def);
proto_add_oper(p, CONSOLE_CLEAR, o);
 
677,9 → 674,7
 
resp_def[0] = V_INTEGER; resp_def[1] = V_INTEGER;
o = oper_new("getsize", 0, arg_def, V_INTEGER, 2, resp_def);
proto_add_oper(p, CONSOLE_GETSIZE, o);
o = oper_new("flush", 0, arg_def, V_VOID, 0, resp_def);
proto_add_oper(p, CONSOLE_FLUSH, o);
proto_add_oper(p, CONSOLE_GET_SIZE, o);
 
arg_def[0] = V_INTEGER;
o = oper_new("set_style", 1, arg_def, V_VOID, 0, resp_def);
/branches/dd/uspace/app/trace/proto.c
35,7 → 35,7
#include <stdio.h>
#include <stdlib.h>
#include <ipc/ipc.h>
#include <libadt/hash_table.h>
#include <adt/hash_table.h>
 
#include "trace.h"
#include "proto.h"
/branches/dd/uspace/app/trace/proto.h
35,7 → 35,7
#ifndef PROTO_H_
#define PROTO_H_
 
#include <libadt/hash_table.h>
#include <adt/hash_table.h>
#include <ipc/ipc.h>
#include "trace.h"
 
/branches/dd/uspace/app/trace/ipcp.c
34,7 → 34,7
 
#include <stdio.h>
#include <stdlib.h>
#include <libadt/hash_table.h>
#include <adt/hash_table.h>
 
#include "ipc_desc.h"
#include "proto.h"
/branches/dd/uspace/lib/libfs/libfs.c
42,6 → 42,7
#include <as.h>
#include <assert.h>
#include <dirent.h>
#include <mem.h>
 
/** Register file system server.
*
208,12 → 209,13
* The path passed in the PLB must be in the canonical file system path format
* as returned by the canonify() function.
*
* @param ops libfs operations structure with function pointers to
* file system implementation
* @param fs_handle File system handle of the file system where to perform
* the lookup.
* @param rid Request ID of the VFS_LOOKUP request.
* @param request VFS_LOOKUP request data itself.
* @param ops libfs operations structure with function pointers to
* file system implementation
* @param fs_handle File system handle of the file system where to perform
* the lookup.
* @param rid Request ID of the VFS_LOOKUP request.
* @param request VFS_LOOKUP request data itself.
*
*/
void libfs_lookup(libfs_ops_t *ops, fs_handle_t fs_handle, ipc_callid_t rid,
ipc_call_t *request)
426,5 → 428,32
ops->node_put(tmp);
}
 
/** Open VFS triplet.
*
* @param ops libfs operations structure with function pointers to
* file system implementation
* @param rid Request ID of the VFS_OPEN_NODE request.
* @param request VFS_OPEN_NODE request data itself.
*
*/
void libfs_open_node(libfs_ops_t *ops, fs_handle_t fs_handle, ipc_callid_t rid,
ipc_call_t *request)
{
dev_handle_t dev_handle = IPC_GET_ARG1(*request);
fs_index_t index = IPC_GET_ARG2(*request);
fs_node_t *node = ops->node_get(dev_handle, index);
if (node == NULL) {
ipc_answer_0(rid, ENOENT);
return;
}
ipc_answer_5(rid, EOK, fs_handle, dev_handle, index,
ops->size_get(node), ops->lnkcnt_get(node));
ops->node_put(node);
}
 
/** @}
*/
/branches/dd/uspace/lib/libfs/libfs.h
26,20 → 26,21
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup libfs
/** @addtogroup libfs
* @{
*/
*/
/**
* @file
*/
 
#ifndef LIBFS_LIBFS_H_
#define LIBFS_LIBFS_H_
#define LIBFS_LIBFS_H_
 
#include "../../srv/vfs/vfs.h"
#include <ipc/vfs.h>
#include <stdint.h>
#include <ipc/ipc.h>
#include <async.h>
#include <devmap.h>
 
typedef struct {
bool mp_active;
49,8 → 50,8
} mp_data_t;
 
typedef struct {
mp_data_t mp_data; /**< Mount point info. */
void *data; /**< Data of the file system implementation. */
mp_data_t mp_data; /**< Mount point info. */
void *data; /**< Data of the file system implementation. */
} fs_node_t;
 
typedef struct {
66,15 → 67,15
unsigned (* lnkcnt_get)(fs_node_t *);
bool (* has_children)(fs_node_t *);
fs_node_t *(* root_get)(dev_handle_t);
char (* plb_get_char)(unsigned pos);
char (* plb_get_char)(unsigned pos);
bool (* is_directory)(fs_node_t *);
bool (* is_file)(fs_node_t *);
} libfs_ops_t;
 
typedef struct {
int fs_handle; /**< File system handle. */
ipcarg_t vfs_phonehash; /**< Initial VFS phonehash. */
uint8_t *plb_ro; /**< Read-only PLB view. */
int fs_handle; /**< File system handle. */
ipcarg_t vfs_phonehash; /**< Initial VFS phonehash. */
uint8_t *plb_ro; /**< Read-only PLB view. */
} fs_reg_t;
 
extern int fs_register(int, fs_reg_t *, vfs_info_t *, async_client_conn_t);
83,9 → 84,10
 
extern void libfs_mount(libfs_ops_t *, fs_handle_t, ipc_callid_t, ipc_call_t *);
extern void libfs_lookup(libfs_ops_t *, fs_handle_t, ipc_callid_t, ipc_call_t *);
extern void libfs_open_node(libfs_ops_t *, fs_handle_t, ipc_callid_t,
ipc_call_t *);
 
#endif
 
/** @}
*/
 
/branches/dd/uspace/lib/libblock/libblock.c
47,8 → 47,9
#include <as.h>
#include <assert.h>
#include <futex.h>
#include <libadt/list.h>
#include <libadt/hash_table.h>
#include <adt/list.h>
#include <adt/hash_table.h>
#include <mem.h>
 
/** Lock protecting the device connection list */
static futex_t dcl_lock = FUTEX_INITIALIZER;
/branches/dd/uspace/lib/libblock/libblock.h
41,8 → 41,8
#include "../../srv/vfs/vfs.h"
#include <futex.h>
#include <rwlock.h>
#include <libadt/hash_table.h>
#include <libadt/list.h>
#include <adt/hash_table.h>
#include <adt/list.h>
 
/*
* Flags that can be used with block_get().
/branches/dd/uspace/lib/libc/include/console.h
File deleted
/branches/dd/uspace/lib/libc/include/console/style.h
File deleted
/branches/dd/uspace/lib/libc/include/console/color.h
File deleted
/branches/dd/uspace/lib/libc/include/kbd/kbd.h
File deleted
/branches/dd/uspace/lib/libc/include/kbd/keycode.h
File deleted
/branches/dd/uspace/lib/libc/include/libadt/hash_table.h
File deleted
/branches/dd/uspace/lib/libc/include/libadt/list.h
File deleted
/branches/dd/uspace/lib/libc/include/libadt/fifo.h
File deleted
/branches/dd/uspace/lib/libc/include/fcntl.h
35,13 → 35,13
#ifndef LIBC_FCNTL_H_
#define LIBC_FCNTL_H_
 
#define O_CREAT 1
#define O_EXCL 2
#define O_TRUNC 4
#define O_APPEND 8
#define O_RDONLY 16
#define O_RDWR 32
#define O_WRONLY 64
#define O_CREAT 1
#define O_EXCL 2
#define O_TRUNC 4
#define O_APPEND 8
#define O_RDONLY 16
#define O_RDWR 32
#define O_WRONLY 64
 
extern int open(const char *, int, ...);
 
/branches/dd/uspace/lib/libc/include/string.h
39,8 → 39,8
#include <sys/types.h>
#include <bool.h>
 
#define U_SPECIAL '?'
#define U_BOM 0xfeff
#define U_SPECIAL '?'
#define U_BOM 0xfeff
 
/** No size limit constant */
#define STR_NO_LIMIT ((size_t) -1)
54,20 → 54,20
extern size_t str_size(const char *str);
extern size_t wstr_size(const wchar_t *str);
 
extern size_t str_lsize(const char *str, count_t max_len);
extern size_t wstr_lsize(const wchar_t *str, count_t max_len);
extern size_t str_lsize(const char *str, size_t max_len);
extern size_t wstr_lsize(const wchar_t *str, size_t max_len);
 
extern count_t str_length(const char *str);
extern count_t wstr_length(const wchar_t *wstr);
extern size_t str_length(const char *str);
extern size_t wstr_length(const wchar_t *wstr);
 
extern count_t str_nlength(const char *str, size_t size);
extern count_t wstr_nlength(const wchar_t *str, size_t size);
extern size_t str_nlength(const char *str, size_t size);
extern size_t wstr_nlength(const wchar_t *str, size_t size);
 
extern bool ascii_check(wchar_t ch);
extern bool chr_check(wchar_t ch);
 
extern int str_cmp(const char *s1, const char *s2);
extern int str_lcmp(const char *s1, const char *s2, count_t max_len);
extern int str_lcmp(const char *s1, const char *s2, size_t max_len);
 
extern void str_cpy(char *dest, size_t size, const char *src);
extern void str_ncpy(char *dest, size_t size, const char *src, size_t n);
78,8 → 78,8
extern const char *str_chr(const char *str, wchar_t ch);
extern const char *str_rchr(const char *str, wchar_t ch);
 
extern bool wstr_linsert(wchar_t *str, wchar_t ch, count_t pos, count_t max_pos);
extern bool wstr_remove(wchar_t *str, count_t pos);
extern bool wstr_linsert(wchar_t *str, wchar_t ch, size_t pos, size_t max_pos);
extern bool wstr_remove(wchar_t *str, size_t pos);
 
extern char *str_dup(const char *);
 
/branches/dd/uspace/lib/libc/include/vfs/vfs.h
36,12 → 36,36
#define LIBC_VFS_H_
 
#include <sys/types.h>
#include <ipc/vfs.h>
#include <ipc/devmap.h>
#include <stdio.h>
 
/**
* This type is a libc version of the VFS triplet.
* It uniquelly identifies a file system node within a file system instance.
*/
typedef struct {
fs_handle_t fs_handle;
dev_handle_t dev_handle;
fs_index_t index;
} fdi_node_t;
 
extern char *absolutize(const char *, size_t *);
 
extern int mount(const char *, const char *, const char *, const char *,
unsigned int flags);
unsigned int);
 
extern void stdio_init(int filc, fdi_node_t *filv[]);
extern void stdio_done(void);
 
extern int open_node(fdi_node_t *, int);
extern int fd_phone(int);
extern int fd_node(int, fdi_node_t *);
 
extern FILE *fopen_node(fdi_node_t *, const char *);
extern int fphone(FILE *);
extern int fnode(FILE *, fdi_node_t *);
 
#endif
 
/** @}
/branches/dd/uspace/lib/libc/include/async.h
43,13 → 43,17
 
typedef ipc_callid_t aid_t;
typedef void (*async_client_conn_t)(ipc_callid_t callid, ipc_call_t *call);
typedef void (*async_pending_t)(void);
 
extern atomic_t async_futex;
 
static inline void async_manager(void)
{
fibril_switch(FIBRIL_TO_MANAGER);
}
 
ipc_callid_t async_get_call_timeout(ipc_call_t *call, suseconds_t usecs);
extern ipc_callid_t async_get_call_timeout(ipc_call_t *call, suseconds_t usecs);
 
static inline ipc_callid_t async_get_call(ipc_call_t *data)
{
return async_get_call_timeout(data, 0);
63,19 → 67,19
*/
 
#define async_send_0(phoneid, method, dataptr) \
async_send_fast((phoneid), (method), 0, 0, 0, 0, (dataptr))
async_send_fast((phoneid), (method), 0, 0, 0, 0, (dataptr))
#define async_send_1(phoneid, method, arg1, dataptr) \
async_send_fast((phoneid), (method), (arg1), 0, 0, 0, (dataptr))
async_send_fast((phoneid), (method), (arg1), 0, 0, 0, (dataptr))
#define async_send_2(phoneid, method, arg1, arg2, dataptr) \
async_send_fast((phoneid), (method), (arg1), (arg2), 0, 0, (dataptr))
async_send_fast((phoneid), (method), (arg1), (arg2), 0, 0, (dataptr))
#define async_send_3(phoneid, method, arg1, arg2, arg3, dataptr) \
async_send_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (dataptr))
async_send_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (dataptr))
#define async_send_4(phoneid, method, arg1, arg2, arg3, arg4, dataptr) \
async_send_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
(dataptr))
async_send_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
(dataptr))
#define async_send_5(phoneid, method, arg1, arg2, arg3, arg4, arg5, dataptr) \
async_send_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
(arg5), (dataptr))
async_send_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
(arg5), (dataptr))
 
extern aid_t async_send_fast(int phoneid, ipcarg_t method, ipcarg_t arg1,
ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4, ipc_call_t *dataptr);
86,34 → 90,35
extern int async_wait_timeout(aid_t amsgid, ipcarg_t *retval,
suseconds_t timeout);
 
fid_t async_new_connection(ipcarg_t in_phone_hash, ipc_callid_t callid,
extern fid_t async_new_connection(ipcarg_t in_phone_hash, ipc_callid_t callid,
ipc_call_t *call, void (*cthread)(ipc_callid_t, ipc_call_t *));
void async_usleep(suseconds_t timeout);
void async_create_manager(void);
void async_destroy_manager(void);
int _async_init(void);
extern void async_usleep(suseconds_t timeout);
extern void async_create_manager(void);
extern void async_destroy_manager(void);
extern int _async_init(void);
 
extern void async_set_client_connection(async_client_conn_t conn);
extern void async_set_interrupt_received(async_client_conn_t conn);
extern void async_set_pending(async_pending_t pend);
 
/* Wrappers for simple communication */
#define async_msg_0(phone, method) \
ipc_call_async_0((phone), (method), NULL, NULL, true)
ipc_call_async_0((phone), (method), NULL, NULL, true)
#define async_msg_1(phone, method, arg1) \
ipc_call_async_1((phone), (method), (arg1), NULL, NULL, \
true)
ipc_call_async_1((phone), (method), (arg1), NULL, NULL, \
true)
#define async_msg_2(phone, method, arg1, arg2) \
ipc_call_async_2((phone), (method), (arg1), (arg2), NULL, NULL, \
true)
ipc_call_async_2((phone), (method), (arg1), (arg2), NULL, NULL, \
true)
#define async_msg_3(phone, method, arg1, arg2, arg3) \
ipc_call_async_3((phone), (method), (arg1), (arg2), (arg3), NULL, NULL, \
true)
ipc_call_async_3((phone), (method), (arg1), (arg2), (arg3), NULL, NULL, \
true)
#define async_msg_4(phone, method, arg1, arg2, arg3, arg4) \
ipc_call_async_4((phone), (method), (arg1), (arg2), (arg3), (arg4), NULL, \
NULL, true)
ipc_call_async_4((phone), (method), (arg1), (arg2), (arg3), (arg4), NULL, \
NULL, true)
#define async_msg_5(phone, method, arg1, arg2, arg3, arg4, arg5) \
ipc_call_async_5((phone), (method), (arg1), (arg2), (arg3), (arg4), \
(arg5), NULL, NULL, true)
ipc_call_async_5((phone), (method), (arg1), (arg2), (arg3), (arg4), \
(arg5), NULL, NULL, true)
 
/*
* User-friendly wrappers for async_req_fast() and async_req_slow(). The macros
122,90 → 127,90
* and slow verion based on m.
*/
#define async_req_0_0(phoneid, method) \
async_req_fast((phoneid), (method), 0, 0, 0, 0, NULL, NULL, NULL, NULL, \
NULL)
async_req_fast((phoneid), (method), 0, 0, 0, 0, NULL, NULL, NULL, NULL, \
NULL)
#define async_req_0_1(phoneid, method, r1) \
async_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), NULL, NULL, NULL, \
NULL)
async_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), NULL, NULL, NULL, \
NULL)
#define async_req_0_2(phoneid, method, r1, r2) \
async_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), (r2), NULL, NULL, \
NULL)
async_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), (r2), NULL, NULL, \
NULL)
#define async_req_0_3(phoneid, method, r1, r2, r3) \
async_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), (r2), (r3), NULL, \
NULL)
async_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), (r2), (r3), NULL, \
NULL)
#define async_req_0_4(phoneid, method, r1, r2, r3, r4) \
async_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), (r2), (r3), (r4), \
NULL)
async_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), (r2), (r3), (r4), \
NULL)
#define async_req_0_5(phoneid, method, r1, r2, r3, r4, r5) \
async_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), (r2), (r3), (r4), \
(r5))
async_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), (r2), (r3), (r4), \
(r5))
#define async_req_1_0(phoneid, method, arg1) \
async_req_fast((phoneid), (method), (arg1), 0, 0, 0, NULL, NULL, NULL, \
NULL, NULL)
async_req_fast((phoneid), (method), (arg1), 0, 0, 0, NULL, NULL, NULL, \
NULL, NULL)
#define async_req_1_1(phoneid, method, arg1, rc1) \
async_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), NULL, NULL, \
NULL, NULL)
async_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), NULL, NULL, \
NULL, NULL)
#define async_req_1_2(phoneid, method, arg1, rc1, rc2) \
async_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), (rc2), NULL, \
NULL, NULL)
async_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), (rc2), NULL, \
NULL, NULL)
#define async_req_1_3(phoneid, method, arg1, rc1, rc2, rc3) \
async_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), (rc2), (rc3), \
NULL, NULL)
async_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), (rc2), (rc3), \
NULL, NULL)
#define async_req_1_4(phoneid, method, arg1, rc1, rc2, rc3, rc4) \
async_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), (rc2), (rc3), \
(rc4), NULL)
async_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), (rc2), (rc3), \
(rc4), NULL)
#define async_req_1_5(phoneid, method, arg1, rc1, rc2, rc3, rc4, rc5) \
async_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), (rc2), (rc3), \
(rc4), (rc5))
async_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), (rc2), (rc3), \
(rc4), (rc5))
#define async_req_2_0(phoneid, method, arg1, arg2) \
async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, NULL, NULL, \
NULL, NULL, NULL)
async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, NULL, NULL, \
NULL, NULL, NULL)
#define async_req_2_1(phoneid, method, arg1, arg2, rc1) \
async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), NULL, \
NULL, NULL, NULL)
async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), NULL, \
NULL, NULL, NULL)
#define async_req_2_2(phoneid, method, arg1, arg2, rc1, rc2) \
async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), (rc2), \
NULL, NULL, NULL)
async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), (rc2), \
NULL, NULL, NULL)
#define async_req_2_3(phoneid, method, arg1, arg2, rc1, rc2, rc3) \
async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), (rc2), \
(rc3), NULL, NULL)
async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), (rc2), \
(rc3), NULL, NULL)
#define async_req_2_4(phoneid, method, arg1, arg2, rc1, rc2, rc3, rc4) \
async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), (rc2), \
(rc3), (rc4), NULL)
async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), (rc2), \
(rc3), (rc4), NULL)
#define async_req_2_5(phoneid, method, arg1, arg2, rc1, rc2, rc3, rc4, rc5) \
async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), (rc2), \
(rc3), (rc4), (rc5))
async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), (rc2), \
(rc3), (rc4), (rc5))
#define async_req_3_0(phoneid, method, arg1, arg2, arg3) \
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, NULL, NULL, \
NULL, NULL, NULL)
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, NULL, NULL, \
NULL, NULL, NULL)
#define async_req_3_1(phoneid, method, arg1, arg2, arg3, rc1) \
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (rc1), \
NULL, NULL, NULL, NULL)
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (rc1), \
NULL, NULL, NULL, NULL)
#define async_req_3_2(phoneid, method, arg1, arg2, arg3, rc1, rc2) \
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (rc1), \
(rc2), NULL, NULL, NULL)
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (rc1), \
(rc2), NULL, NULL, NULL)
#define async_req_3_3(phoneid, method, arg1, arg2, arg3, rc1, rc2, rc3) \
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (rc1), \
(rc2), (rc3), NULL, NULL)
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (rc1), \
(rc2), (rc3), NULL, NULL)
#define async_req_3_4(phoneid, method, arg1, arg2, arg3, rc1, rc2, rc3, rc4) \
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (rc1), \
(rc2), (rc3), (rc4), NULL)
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (rc1), \
(rc2), (rc3), (rc4), NULL)
#define async_req_3_5(phoneid, method, arg1, arg2, arg3, rc1, rc2, rc3, rc4, \
rc5) \
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (rc1), \
(rc2), (rc3), (rc4), (rc5))
#define async_req_4_0(phoneid, method, arg1, arg2, arg3, arg4) \
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), NULL, \
NULL, NULL, NULL, NULL)
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), NULL, \
NULL, NULL, NULL, NULL)
#define async_req_4_1(phoneid, method, arg1, arg2, arg3, arg4, rc1) \
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), (rc1), \
NULL, NULL, NULL, NULL)
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), (rc1), \
NULL, NULL, NULL, NULL)
#define async_req_4_2(phoneid, method, arg1, arg2, arg3, arg4, rc1, rc2) \
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), (rc1), \
(rc2), NULL, NULL, NULL)
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), (rc1), \
(rc2), NULL, NULL, NULL)
#define async_req_4_3(phoneid, method, arg1, arg2, arg3, arg4, rc1, rc2, rc3) \
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), (rc1), \
(rc2), (rc3), NULL, NULL)
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), (rc1), \
(rc2), (rc3), NULL, NULL)
#define async_req_4_4(phoneid, method, arg1, arg2, arg3, arg4, rc1, rc2, rc3, \
rc4) \
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
215,14 → 220,14
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
(rc1), (rc2), (rc3), (rc4), (rc5))
#define async_req_5_0(phoneid, method, arg1, arg2, arg3, arg4, arg5) \
async_req_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
(arg5), NULL, NULL, NULL, NULL, NULL)
async_req_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
(arg5), NULL, NULL, NULL, NULL, NULL)
#define async_req_5_1(phoneid, method, arg1, arg2, arg3, arg4, arg5, rc1) \
async_req_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
(arg5), (rc1), NULL, NULL, NULL, NULL)
async_req_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
(arg5), (rc1), NULL, NULL, NULL, NULL)
#define async_req_5_2(phoneid, method, arg1, arg2, arg3, arg4, arg5, rc1, rc2) \
async_req_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
(arg5), (rc1), (rc2), NULL, NULL, NULL)
async_req_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
(arg5), (rc1), (rc2), NULL, NULL, NULL)
#define async_req_5_3(phoneid, method, arg1, arg2, arg3, arg4, arg5, rc1, rc2, \
rc3) \
async_req_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
253,8 → 258,6
fibril_dec_sercount();
}
 
extern atomic_t async_futex;
 
#endif
 
/** @}
/branches/dd/uspace/lib/libc/include/stdio.h
37,78 → 37,94
 
#include <sys/types.h>
#include <stdarg.h>
#include <adt/list.h>
 
#define EOF (-1)
#define EOF (-1)
 
#include <string.h>
#include <io/stream.h>
 
#define DEBUG(fmt, ...) \
{ \
char buf[256]; \
int n; \
n = snprintf(buf, sizeof(buf), fmt, ##__VA_ARGS__); \
int n = snprintf(buf, sizeof(buf), fmt, ##__VA_ARGS__); \
if (n > 0) \
(void) __SYSCALL3(SYS_KLOG, 1, (sysarg_t) buf, str_size(buf)); \
}
 
#ifndef SEEK_SET
#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2
#endif
 
typedef struct {
/** Linked list pointer. */
link_t link;
/** Underlying file descriptor. */
int fd;
 
/** Error indicator. */
int error;
 
/** End-of-file indicator. */
int eof;
/** Klog indicator */
int klog;
/** Phone to the file provider */
int phone;
} FILE;
 
extern FILE *stdin, *stdout, *stderr;
extern FILE *stdin;
extern FILE *stdout;
extern FILE *stderr;
 
/* Character and string input functions */
extern int fgetc(FILE *);
extern char *fgets(char *, size_t, FILE *);
 
extern int getchar(void);
extern char *gets(char *, size_t);
 
/* Character and string output functions */
extern int fputc(wchar_t, FILE *);
extern int fputs(const char *, FILE *);
 
extern int putchar(wchar_t);
extern int puts(const char *);
extern int putchar(int);
extern int fflush(FILE *);
 
/* Formatted string output functions */
extern int fprintf(FILE *, const char*, ...);
extern int vfprintf(FILE *, const char *, va_list);
 
extern int printf(const char *, ...);
extern int vprintf(const char *, va_list);
 
extern int snprintf(char *, size_t , const char *, ...);
extern int asprintf(char **, const char *, ...);
extern int sprintf(char *, const char *, ...);
extern int snprintf(char *, size_t , const char *, ...);
 
extern int vprintf(const char *, va_list);
extern int vsprintf(char *, const char *, va_list);
extern int vsnprintf(char *, size_t, const char *, va_list);
 
extern int rename(const char *, const char *);
 
/* File stream functions */
extern FILE *fopen(const char *, const char *);
extern FILE *fdopen(int, const char *);
extern int fclose(FILE *);
 
extern size_t fread(void *, size_t, size_t, FILE *);
extern size_t fwrite(const void *, size_t, size_t, FILE *);
 
extern int fseek(FILE *, long, int);
extern void rewind(FILE *);
extern int ftell(FILE *);
extern int feof(FILE *);
 
extern int fflush(FILE *);
extern int ferror(FILE *);
extern void clearerr(FILE *);
 
extern int fgetc(FILE *);
extern int fputc(int, FILE *);
extern int fputs(const char *, FILE *);
/* Misc file functions */
extern int rename(const char *, const char *);
 
extern int fprintf(FILE *, const char *, ...);
extern int vfprintf(FILE *, const char *, va_list);
 
#define getc fgetc
#define putc fputc
 
extern int fseek(FILE *, long, int);
 
#ifndef SEEK_SET
#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2
#endif
 
#endif
 
/** @}
*/
/branches/dd/uspace/lib/libc/include/dirent.h
35,7 → 35,7
#ifndef LIBC_DIRENT_H_
#define LIBC_DIRENT_H_
 
#define NAME_MAX 256
#define NAME_MAX 256
 
struct dirent {
char d_name[NAME_MAX + 1];
46,7 → 46,6
struct dirent res;
} DIR;
 
 
extern DIR *opendir(const char *);
extern struct dirent *readdir(DIR *);
extern void rewinddir(DIR *);
/branches/dd/uspace/lib/libc/include/task.h
42,6 → 42,7
extern task_id_t task_get_id(void);
extern int task_set_name(const char *name);
extern task_id_t task_spawn(const char *path, char *const argv[]);
extern int task_wait(task_id_t id);
 
#endif
 
/branches/dd/uspace/lib/libc/include/fibril_sync.h
0,0 → 1,104
/*
* Copyright (c) 2009 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup libc
* @{
*/
/** @file
*/
 
#ifndef LIBC_FIBRIL_SYNC_H_
#define LIBC_FIBRIL_SYNC_H_
 
#include <async.h>
#include <fibril.h>
#include <adt/list.h>
#include <libarch/tls.h>
 
typedef struct {
int counter;
link_t waiters;
} fibril_mutex_t;
 
#define FIBRIL_MUTEX_INITIALIZE(name) \
fibril_mutex_t name = { \
.counter = 1, \
.waiters = { \
.prev = &name.waiters, \
.next = &name.waiters, \
} \
}
 
typedef struct {
unsigned writers;
unsigned readers;
link_t waiters;
} fibril_rwlock_t;
 
#define FIBRIL_RWLOCK_INITIALIZE(name) \
fibril_rwlock_t name = { \
.readers = 0, \
.writers = 0, \
.waiters = { \
.prev = &name.waiters, \
.next = &name.waiters, \
} \
}
 
typedef struct {
link_t waiters;
} fibril_condvar_t;
 
#define FIBRIL_CONDVAR_INITIALIZE(name) \
fibril_condvar_t name = { \
.waiters = { \
.next = &name.waiters, \
.prev = &name.waiters, \
} \
}
 
extern void fibril_mutex_initialize(fibril_mutex_t *);
extern void fibril_mutex_lock(fibril_mutex_t *);
extern bool fibril_mutex_trylock(fibril_mutex_t *);
extern void fibril_mutex_unlock(fibril_mutex_t *);
 
extern void fibril_rwlock_initialize(fibril_rwlock_t *);
extern void fibril_rwlock_read_lock(fibril_rwlock_t *);
extern void fibril_rwlock_write_lock(fibril_rwlock_t *);
extern void fibril_rwlock_read_unlock(fibril_rwlock_t *);
extern void fibril_rwlock_write_unlock(fibril_rwlock_t *);
 
extern void fibril_condvar_initialize(fibril_condvar_t *);
extern void fibril_condvar_wait(fibril_condvar_t *, fibril_mutex_t *);
extern void fibril_condvar_signal(fibril_condvar_t *);
extern void fibril_condvar_broadcast(fibril_condvar_t *);
 
#endif
 
/** @}
*/
/branches/dd/uspace/lib/libc/include/unistd.h
39,26 → 39,30
#include <libarch/config.h>
 
#ifndef NULL
#define NULL 0
#define NULL 0
#endif
 
#define getpagesize() (PAGE_SIZE)
#define getpagesize() (PAGE_SIZE)
 
#ifndef SEEK_SET
#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2
#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2
#endif
 
extern ssize_t write(int, const void *, size_t);
extern ssize_t read(int, void *, size_t);
 
extern off_t lseek(int, off_t, int);
extern int ftruncate(int, off_t);
 
extern int close(int);
extern int fsync(int);
extern int unlink(const char *);
 
extern char *getcwd(char *buf, size_t);
extern int rmdir(const char *);
extern int chdir(const char *);
extern char *getcwd(char *buf, size_t);
 
extern void _exit(int status) __attribute__ ((noreturn));
extern void *sbrk(ssize_t incr);
/branches/dd/uspace/lib/libc/include/fibril.h
36,17 → 36,18
#define LIBC_FIBRIL_H_
 
#include <libarch/fibril.h>
#include <libadt/list.h>
#include <adt/list.h>
#include <libarch/tls.h>
 
#ifndef context_set
#define context_set(c, _pc, stack, size, ptls) \
(c)->pc = (sysarg_t) (_pc); \
(c)->sp = ((sysarg_t) (stack)) + (size) - SP_DELTA; \
(c)->tls = (sysarg_t) (ptls);
#define context_set(c, _pc, stack, size, ptls) \
(c)->pc = (sysarg_t) (_pc); \
(c)->sp = ((sysarg_t) (stack)) + (size) - SP_DELTA; \
(c)->tls = (sysarg_t) (ptls);
#endif /* context_set */
 
#define FIBRIL_SERIALIZED 1
#define FIBRIL_SERIALIZED 1
#define FIBRIL_WRITER 2
 
typedef enum {
FIBRIL_PREEMPT,
71,6 → 72,9
};
typedef struct fibril fibril_t;
 
/** Fibril-local variable specifier */
#define fibril_local __thread
 
extern int context_save(context_t *c);
extern void context_restore(context_t *c) __attribute__ ((noreturn));
 
/branches/dd/uspace/lib/libc/include/loader/pcb.h
37,6 → 37,7
#define LIBC_PCB_H_
 
#include <sys/types.h>
#include <vfs/vfs.h>
 
typedef void (*entry_point_t)(void);
 
45,19 → 46,26
* Holds pointers to data passed from the program loader to the program
* and/or to the dynamic linker. This includes the program entry point,
* arguments, environment variables etc.
*
*/
typedef struct {
/** Program entry point. */
entry_point_t entry;
 
/** Number of command-line arguments. */
int argc;
/** Command-line arguments. */
char **argv;
 
/** Number of preset files. */
int filc;
/** Preset files. */
fdi_node_t **filv;
/*
* ELF-specific data.
*/
/** Pointer to ELF dynamic section of the program. */
void *dynamic;
} pcb_t;
/branches/dd/uspace/lib/libc/include/loader/loader.h
37,6 → 37,7
#define LIBC_LOADER_H_
 
#include <task.h>
#include <vfs/vfs.h>
 
/** Abstraction of a loader connection */
typedef struct {
48,7 → 49,8
extern loader_t *loader_connect(void);
extern int loader_get_task_id(loader_t *, task_id_t *);
extern int loader_set_pathname(loader_t *, const char *);
extern int loader_set_args(loader_t *, char *const []);
extern int loader_set_args(loader_t *, char *const[]);
extern int loader_set_files(loader_t *, fdi_node_t *const[]);
extern int loader_load_program(loader_t *);
extern int loader_run(loader_t *);
extern void loader_abort(loader_t *);
/branches/dd/uspace/lib/libc/include/io/io.h
File deleted
/branches/dd/uspace/lib/libc/include/io/stream.h
File deleted
/branches/dd/uspace/lib/libc/include/io/printf_core.h
56,5 → 56,3
 
/** @}
*/
/branches/dd/uspace/lib/libc/include/io/klog.h
0,0 → 1,46
/*
* Copyright (c) 2006 Jakub Vana
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup libc
* @{
*/
/** @file
*/
 
#ifndef LIBC_STREAM_H_
#define LIBC_STREAM_H_
 
#include <sys/types.h>
 
extern size_t klog_write(const void *buf, size_t size);
extern void klog_update(void);
 
#endif
 
/** @}
*/
/branches/dd/uspace/lib/libc/include/io/color.h
0,0 → 1,55
/*
* Copyright (c) 2008 Jiri Svoboda
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup libc
* @{
*/
/** @file
*/
 
#ifndef LIBC_IO_COLOR_H_
#define LIBC_IO_COLOR_H_
 
enum console_color {
COLOR_BLACK = 0,
COLOR_BLUE = 1,
COLOR_GREEN = 2,
COLOR_CYAN = 3,
COLOR_RED = 4,
COLOR_MAGENTA = 5,
COLOR_YELLOW = 6,
COLOR_WHITE = 7,
CATTR_BRIGHT = 8,
CATTR_BLINK = 8
};
 
#endif
 
/** @}
*/
/branches/dd/uspace/lib/libc/include/io/style.h
0,0 → 1,46
/*
* Copyright (c) 2008 Jiri Svoboda
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup libc
* @{
*/
/** @file
*/
 
#ifndef LIBC_IO_STYLE_H_
#define LIBC_IO_STYLE_H_
 
enum console_style {
STYLE_NORMAL = 0,
STYLE_EMPHASIS = 1
};
 
#endif
 
/** @}
*/
/branches/dd/uspace/lib/libc/include/io/console.h
0,0 → 1,78
/*
* Copyright (c) 2008 Jiri Svoboda
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup libc
* @{
*/
/** @file
*/
 
#ifndef LIBC_IO_CONSOLE_H_
#define LIBC_IO_CONSOLE_H_
 
#include <ipc/ipc.h>
#include <bool.h>
 
typedef enum {
KEY_PRESS,
KEY_RELEASE
} console_ev_type_t;
 
/** Console event structure. */
typedef struct {
/** Press or release event. */
console_ev_type_t type;
/** Keycode of the key that was pressed or released. */
unsigned int key;
/** Bitmask of modifiers held. */
unsigned int mods;
/** The character that was generated or '\0' for none. */
wchar_t c;
} console_event_t;
 
extern void console_clear(int phone);
 
extern int console_get_size(int phone, ipcarg_t *rows, ipcarg_t *cols);
extern void console_goto(int phone, ipcarg_t row, ipcarg_t col);
 
extern void console_set_style(int phone, int style);
extern void console_set_color(int phone, int fg_color, int bg_color, int flags);
extern void console_set_rgb_color(int phone, int fg_color, int bg_color);
 
extern void console_cursor_visibility(int phone, bool show);
extern void console_kcon_enable(int phone);
 
extern bool console_get_event(int phone, console_event_t *event);
 
#endif
 
/** @}
*/
/branches/dd/uspace/lib/libc/include/io/keycode.h
0,0 → 1,220
/*
* Copyright (c) 2009 Jiri Svoboda
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup libc
* @{
*/
/** @file
*/
 
#ifndef LIBC_IO_KEYCODE_H_
#define LIBC_IO_KEYCODE_H_
 
/** Keycode definitions.
*
* A keycode identifies a key by its position on the keyboard, rather
* than by its label. For human readability, key positions are noted
* with the key label on a keyboard with US layout. This label has
* nothing to do with the character, that the key produces
* -- this is determined by the keymap.
*
* The keyboard model reflects a standard PC keyboard layout.
* Non-standard keyboards need to be mapped to this model in some
* logical way. Scancodes are mapped to keycodes with a scanmap.
*
* For easier mapping to the model and to emphasize the nature of keycodes,
* they really are organized here by position, rather than by label.
*/
enum keycode {
 
/* Main block row 1 */
 
KC_BACKTICK = 1,
 
KC_1,
KC_2,
KC_3,
KC_4,
KC_5,
KC_6,
KC_7,
KC_8,
KC_9,
KC_0,
 
KC_MINUS,
KC_EQUALS,
KC_BACKSPACE,
 
/* Main block row 2 */
 
KC_TAB,
 
KC_Q,
KC_W,
KC_E,
KC_R,
KC_T,
KC_Y,
KC_U,
KC_I,
KC_O,
KC_P,
 
KC_LBRACKET,
KC_RBRACKET,
 
/* Main block row 3 */
 
KC_CAPS_LOCK,
KC_A,
KC_S,
KC_D,
KC_F,
KC_G,
KC_H,
KC_J,
KC_K,
KC_L,
 
KC_SEMICOLON,
KC_QUOTE,
KC_BACKSLASH,
 
KC_ENTER,
 
/* Main block row 4 */
 
KC_LSHIFT,
 
KC_Z,
KC_X,
KC_C,
KC_V,
KC_B,
KC_N,
KC_M,
 
KC_COMMA,
KC_PERIOD,
KC_SLASH,
 
KC_RSHIFT,
 
/* Main block row 5 */
 
KC_LCTRL,
KC_LALT,
KC_SPACE,
KC_RALT,
KC_RCTRL,
 
/* Function keys block */
 
KC_ESCAPE,
 
KC_F1,
KC_F2,
KC_F3,
KC_F4,
KC_F5,
KC_F6,
KC_F7,
KC_F8,
KC_F9,
KC_F10,
KC_F11,
KC_F12,
 
KC_PRTSCR,
KC_SCROLL_LOCK,
KC_PAUSE,
 
/* Cursor keys block */
 
KC_INSERT,
KC_HOME,
KC_PAGE_UP,
 
KC_DELETE,
KC_END,
KC_PAGE_DOWN,
 
KC_UP,
KC_LEFT,
KC_DOWN,
KC_RIGHT,
 
/* Numeric block */
 
KC_NUM_LOCK,
KC_NSLASH,
KC_NTIMES,
KC_NMINUS,
 
KC_NPLUS,
KC_NENTER,
 
KC_N7,
KC_N8,
KC_N9,
 
KC_N4,
KC_N5,
KC_N6,
 
KC_N1,
KC_N2,
KC_N3,
 
KC_N0,
KC_NPERIOD
} keycode_t;
 
enum keymod {
KM_LSHIFT = 0x001,
KM_RSHIFT = 0x002,
KM_LCTRL = 0x004,
KM_RCTRL = 0x008,
KM_LALT = 0x010,
KM_RALT = 0x020,
KM_CAPS_LOCK = 0x040,
KM_NUM_LOCK = 0x080,
KM_SCROLL_LOCK = 0x100,
KM_SHIFT = KM_LSHIFT | KM_RSHIFT,
KM_CTRL = KM_LCTRL | KM_RCTRL,
KM_ALT = KM_LALT | KM_RALT
} keymod_t;
 
#endif
 
/** @}
*/
/branches/dd/uspace/lib/libc/include/adt/hash_table.h
0,0 → 1,94
/*
* Copyright (c) 2006 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup libc
* @{
*/
/** @file
*/
 
#ifndef LIBC_HASH_TABLE_H_
#define LIBC_HASH_TABLE_H_
 
#include <adt/list.h>
#include <unistd.h>
 
typedef unsigned long hash_count_t;
typedef unsigned long hash_index_t;
typedef struct hash_table hash_table_t;
typedef struct hash_table_operations hash_table_operations_t;
 
/** Hash table structure. */
struct hash_table {
link_t *entry;
hash_count_t entries;
hash_count_t max_keys;
hash_table_operations_t *op;
};
 
/** Set of operations for hash table. */
struct hash_table_operations {
/** Hash function.
*
* @param key Array of keys needed to compute hash index. All keys
* must be passed.
*
* @return Index into hash table.
*/
hash_index_t (* hash)(unsigned long key[]);
/** Hash table item comparison function.
*
* @param key Array of keys that will be compared with item. It is
* not necessary to pass all keys.
*
* @return true if the keys match, false otherwise.
*/
int (*compare)(unsigned long key[], hash_count_t keys, link_t *item);
 
/** Hash table item removal callback.
*
* @param item Item that was removed from the hash table.
*/
void (*remove_callback)(link_t *item);
};
 
#define hash_table_get_instance(item, type, member) \
list_get_instance((item), type, member)
 
extern int hash_table_create(hash_table_t *, hash_count_t, hash_count_t,
hash_table_operations_t *);
extern void hash_table_insert(hash_table_t *, unsigned long [], link_t *);
extern link_t *hash_table_find(hash_table_t *, unsigned long []);
extern void hash_table_remove(hash_table_t *, unsigned long [], hash_count_t);
extern void hash_table_destroy(hash_table_t *);
 
#endif
 
/** @}
*/
/branches/dd/uspace/lib/libc/include/adt/list.h
0,0 → 1,201
/*
* Copyright (c) 2001-2004 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup libc
* @{
*/
/** @file
*/
 
#ifndef LIBC_LIST_H_
#define LIBC_LIST_H_
 
#include <unistd.h>
 
/** Doubly linked list head and link type. */
typedef struct link {
struct link *prev; /**< Pointer to the previous item in the list. */
struct link *next; /**< Pointer to the next item in the list. */
} link_t;
 
/** Declare and initialize statically allocated list.
*
* @param name Name of the new statically allocated list.
*/
#define LIST_INITIALIZE(name) link_t name = { \
.prev = &name, \
.next = &name \
}
 
/** Initialize doubly-linked circular list link
*
* Initialize doubly-linked list link.
*
* @param link Pointer to link_t structure to be initialized.
*/
static inline void link_initialize(link_t *link)
{
link->prev = NULL;
link->next = NULL;
}
 
/** Initialize doubly-linked circular list
*
* Initialize doubly-linked circular list.
*
* @param head Pointer to link_t structure representing head of the list.
*/
static inline void list_initialize(link_t *head)
{
head->prev = head;
head->next = head;
}
 
/** Add item to the beginning of doubly-linked circular list
*
* Add item to the beginning of doubly-linked circular list.
*
* @param link Pointer to link_t structure to be added.
* @param head Pointer to link_t structure representing head of the list.
*/
static inline void list_prepend(link_t *link, link_t *head)
{
link->next = head->next;
link->prev = head;
head->next->prev = link;
head->next = link;
}
 
/** Add item to the end of doubly-linked circular list
*
* Add item to the end of doubly-linked circular list.
*
* @param link Pointer to link_t structure to be added.
* @param head Pointer to link_t structure representing head of the list.
*/
static inline void list_append(link_t *link, link_t *head)
{
link->prev = head->prev;
link->next = head;
head->prev->next = link;
head->prev = link;
}
 
/** Insert item before another item in doubly-linked circular list. */
static inline void list_insert_before(link_t *l, link_t *r)
{
list_append(l, r);
}
 
/** Insert item after another item in doubly-linked circular list. */
static inline void list_insert_after(link_t *r, link_t *l)
{
list_prepend(l, r);
}
 
/** Remove item from doubly-linked circular list
*
* Remove item from doubly-linked circular list.
*
* @param link Pointer to link_t structure to be removed from the list it is contained in.
*/
static inline void list_remove(link_t *link)
{
link->next->prev = link->prev;
link->prev->next = link->next;
link_initialize(link);
}
 
/** Query emptiness of doubly-linked circular list
*
* Query emptiness of doubly-linked circular list.
*
* @param head Pointer to link_t structure representing head of the list.
*/
static inline int list_empty(link_t *head)
{
return ((head->next == head) ? 1 : 0);
}
 
 
/** Split or concatenate headless doubly-linked circular list
*
* Split or concatenate headless doubly-linked circular list.
*
* Note that the algorithm works both directions:
* concatenates splitted lists and splits concatenated lists.
*
* @param part1 Pointer to link_t structure leading the first (half of the headless) list.
* @param part2 Pointer to link_t structure leading the second (half of the headless) list.
*/
static inline void headless_list_split_or_concat(link_t *part1, link_t *part2)
{
part1->prev->next = part2;
part2->prev->next = part1;
link_t *hlp = part1->prev;
part1->prev = part2->prev;
part2->prev = hlp;
}
 
 
/** Split headless doubly-linked circular list
*
* Split headless doubly-linked circular list.
*
* @param part1 Pointer to link_t structure leading the first half of the headless list.
* @param part2 Pointer to link_t structure leading the second half of the headless list.
*/
static inline void headless_list_split(link_t *part1, link_t *part2)
{
headless_list_split_or_concat(part1, part2);
}
 
/** Concatenate two headless doubly-linked circular lists
*
* Concatenate two headless doubly-linked circular lists.
*
* @param part1 Pointer to link_t structure leading the first headless list.
* @param part2 Pointer to link_t structure leading the second headless list.
*/
static inline void headless_list_concat(link_t *part1, link_t *part2)
{
headless_list_split_or_concat(part1, part2);
}
 
#define list_get_instance(link, type, member) ((type *) (((void *)(link)) - ((void *) &(((type *) NULL)->member))))
 
extern int list_member(const link_t *link, const link_t *head);
extern void list_concat(link_t *head1, link_t *head2);
extern unsigned int list_count(const link_t *link);
 
#endif
 
/** @}
*/
/branches/dd/uspace/lib/libc/include/adt/fifo.h
0,0 → 1,127
/*
* Copyright (c) 2006 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup libc
* @{
*/
/** @file
*/
 
/*
* This implementation of FIFO stores values in an array
* (static or dynamic). As such, these FIFOs have upper bound
* on number of values they can store. Push and pop operations
* are done via accessing the array through head and tail indices.
* Because of better operation ordering in fifo_pop(), the access
* policy for these two indices is to 'increment (mod size of FIFO)
* and use'.
*/
 
#ifndef LIBC_FIFO_H_
#define LIBC_FIFO_H_
 
#include <malloc.h>
 
typedef unsigned long fifo_count_t;
typedef unsigned long fifo_index_t;
 
#define FIFO_CREATE_STATIC(name, t, itms) \
struct { \
t fifo[(itms)]; \
fifo_count_t items; \
fifo_index_t head; \
fifo_index_t tail; \
} name
 
/** Create and initialize static FIFO.
*
* FIFO is allocated statically.
* This macro is suitable for creating smaller FIFOs.
*
* @param name Name of FIFO.
* @param t Type of values stored in FIFO.
* @param itms Number of items that can be stored in FIFO.
*/
#define FIFO_INITIALIZE_STATIC(name, t, itms) \
FIFO_CREATE_STATIC(name, t, itms) = { \
.items = (itms), \
.head = 0, \
.tail = 0 \
}
 
/** Create and prepare dynamic FIFO.
*
* FIFO is allocated dynamically.
* This macro is suitable for creating larger FIFOs.
*
* @param name Name of FIFO.
* @param t Type of values stored in FIFO.
* @param itms Number of items that can be stored in FIFO.
*/
#define FIFO_INITIALIZE_DYNAMIC(name, t, itms) \
struct { \
t *fifo; \
fifo_count_t items; \
fifo_index_t head; \
fifo_index_t tail; \
} name = { \
.fifo = NULL, \
.items = (itms), \
.head = 0, \
.tail = 0 \
}
 
/** Pop value from head of FIFO.
*
* @param name FIFO name.
*
* @return Leading value in FIFO.
*/
#define fifo_pop(name) \
name.fifo[name.head = (name.head + 1) < name.items ? (name.head + 1) : 0]
 
/** Push value to tail of FIFO.
*
* @param name FIFO name.
* @param value Value to be appended to FIFO.
*
*/
#define fifo_push(name, value) \
name.fifo[name.tail = (name.tail + 1) < name.items ? (name.tail + 1) : 0] = (value)
 
/** Allocate memory for dynamic FIFO.
*
* @param name FIFO name.
*/
#define fifo_create(name) \
name.fifo = malloc(sizeof(*name.fifo) * name.items)
 
#endif
 
/** @}
*/
/branches/dd/uspace/lib/libc/include/macros.h
35,15 → 35,22
#ifndef LIBC_MACROS_H_
#define LIBC_MACROS_H_
 
#define SIZE2KB(size) ((size) >> 10)
#define SIZE2MB(size) ((size) >> 20)
#define SIZE2KB(size) ((size) >> 10)
#define SIZE2MB(size) ((size) >> 20)
 
#define KB2SIZE(kb) ((kb) << 10)
#define MB2SIZE(mb) ((mb) << 20)
#define KB2SIZE(kb) ((kb) << 10)
#define MB2SIZE(mb) ((mb) << 20)
 
#define STRING(arg) STRING_ARG(arg)
#define STRING_ARG(arg) #arg
#define STRING(arg) STRING_ARG(arg)
#define STRING_ARG(arg) #arg
 
#define LOWER32(arg) ((arg) & 0xffffffff)
#define UPPER32(arg) (((arg) >> 32) & 0xffffffff)
 
#define MERGE_LOUP32(lo, up) \
((((uint64_t) (lo)) & 0xffffffff) \
| ((((uint64_t) (up)) & 0xffffffff) << 32))
 
#endif
 
/** @}
/branches/dd/uspace/lib/libc/include/ipc/ipc.h
30,21 → 30,26
* @{
*/
/** @file
*/
*/
 
#ifndef LIBIPC_IPC_H_
#define LIBIPC_IPC_H_
 
#include <task.h>
#include <kernel/ipc/ipc.h>
#include <kernel/ddi/irq.h>
#include <sys/types.h>
#include <kernel/synch/synch.h>
 
#define IPC_FLAG_BLOCKING 0x01
 
typedef sysarg_t ipcarg_t;
 
typedef struct {
ipcarg_t args[IPC_CALL_LEN];
ipcarg_t in_phone_hash;
} ipc_call_t;
 
typedef sysarg_t ipc_callid_t;
 
typedef void (* ipc_async_callback_t)(void *, int, ipc_call_t *);
56,49 → 61,51
* possible, the fast version is used.
*/
#define ipc_call_sync_0_0(phoneid, method) \
ipc_call_sync_fast((phoneid), (method), 0, 0, 0, 0, 0, 0, 0, 0)
ipc_call_sync_fast((phoneid), (method), 0, 0, 0, 0, 0, 0, 0, 0)
#define ipc_call_sync_0_1(phoneid, method, res1) \
ipc_call_sync_fast((phoneid), (method), 0, 0, 0, (res1), 0, 0, 0, 0)
ipc_call_sync_fast((phoneid), (method), 0, 0, 0, (res1), 0, 0, 0, 0)
#define ipc_call_sync_0_2(phoneid, method, res1, res2) \
ipc_call_sync_fast((phoneid), (method), 0, 0, 0, (res1), (res2), 0, 0, 0)
ipc_call_sync_fast((phoneid), (method), 0, 0, 0, (res1), (res2), 0, 0, 0)
#define ipc_call_sync_0_3(phoneid, method, res1, res2, res3) \
ipc_call_sync_fast((phoneid), (method), 0, 0, 0, (res1), (res2), (res3), \
0, 0)
ipc_call_sync_fast((phoneid), (method), 0, 0, 0, (res1), (res2), (res3), \
0, 0)
#define ipc_call_sync_0_4(phoneid, method, res1, res2, res3, res4) \
ipc_call_sync_fast((phoneid), (method), 0, 0, 0, (res1), (res2), (res3), \
(res4), 0)
ipc_call_sync_fast((phoneid), (method), 0, 0, 0, (res1), (res2), (res3), \
(res4), 0)
#define ipc_call_sync_0_5(phoneid, method, res1, res2, res3, res4, res5) \
ipc_call_sync_fast((phoneid), (method), 0, 0, 0, (res1), (res2), (res3), \
(res4), (res5))
ipc_call_sync_fast((phoneid), (method), 0, 0, 0, (res1), (res2), (res3), \
(res4), (res5))
 
#define ipc_call_sync_1_0(phoneid, method, arg1) \
ipc_call_sync_fast((phoneid), (method), (arg1), 0, 0, 0, 0, 0, 0, 0)
ipc_call_sync_fast((phoneid), (method), (arg1), 0, 0, 0, 0, 0, 0, 0)
#define ipc_call_sync_1_1(phoneid, method, arg1, res1) \
ipc_call_sync_fast((phoneid), (method), (arg1), 0, 0, (res1), 0, 0, 0, 0)
ipc_call_sync_fast((phoneid), (method), (arg1), 0, 0, (res1), 0, 0, 0, 0)
#define ipc_call_sync_1_2(phoneid, method, arg1, res1, res2) \
ipc_call_sync_fast((phoneid), (method), (arg1), 0, 0, (res1), (res2), 0, \
0, 0)
ipc_call_sync_fast((phoneid), (method), (arg1), 0, 0, (res1), (res2), 0, \
0, 0)
#define ipc_call_sync_1_3(phoneid, method, arg1, res1, res2, res3) \
ipc_call_sync_fast((phoneid), (method), (arg1), 0, 0, (res1), (res2), \
(res3), 0, 0)
ipc_call_sync_fast((phoneid), (method), (arg1), 0, 0, (res1), (res2), \
(res3), 0, 0)
#define ipc_call_sync_1_4(phoneid, method, arg1, res1, res2, res3, res4) \
ipc_call_sync_fast((phoneid), (method), (arg1), 0, 0, (res1), (res2), \
(res3), (res4), 0)
ipc_call_sync_fast((phoneid), (method), (arg1), 0, 0, (res1), (res2), \
(res3), (res4), 0)
#define ipc_call_sync_1_5(phoneid, method, arg1, res1, res2, res3, res4, \
res5) \
ipc_call_sync_fast((phoneid), (method), (arg1), 0, 0, (res1), (res2), \
(res3), (res4), (res5))
 
#define ipc_call_sync_2_0(phoneid, method, arg1, arg2) \
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), 0, 0, 0, 0, \
0, 0)
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), 0, 0, 0, 0, \
0, 0)
#define ipc_call_sync_2_1(phoneid, method, arg1, arg2, res1) \
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), 0, (res1), 0, 0, \
0, 0)
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), 0, (res1), 0, 0, \
0, 0)
#define ipc_call_sync_2_2(phoneid, method, arg1, arg2, res1, res2) \
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), 0, (res1), \
(res2), 0, 0, 0)
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), 0, (res1), \
(res2), 0, 0, 0)
#define ipc_call_sync_2_3(phoneid, method, arg1, arg2, res1, res2, res3) \
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), 0, (res1), \
(res2), (res3), 0, 0)
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), 0, (res1), \
(res2), (res3), 0, 0)
#define ipc_call_sync_2_4(phoneid, method, arg1, arg2, res1, res2, res3, \
res4) \
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), 0, (res1), \
107,15 → 114,16
res4, res5)\
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), 0, (res1), \
(res2), (res3), (res4), (res5))
 
#define ipc_call_sync_3_0(phoneid, method, arg1, arg2, arg3) \
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, 0, 0, \
0, 0)
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, 0, 0, \
0, 0)
#define ipc_call_sync_3_1(phoneid, method, arg1, arg2, arg3, res1) \
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), (arg3), (res1), \
0, 0, 0, 0)
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), (arg3), (res1), \
0, 0, 0, 0)
#define ipc_call_sync_3_2(phoneid, method, arg1, arg2, arg3, res1, res2) \
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), (arg3), (res1), \
(res2), 0, 0, 0)
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), (arg3), (res1), \
(res2), 0, 0, 0)
#define ipc_call_sync_3_3(phoneid, method, arg1, arg2, arg3, res1, res2, \
res3) \
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), (arg3), \
128,15 → 136,16
res3, res4, res5) \
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), (arg3), \
(res1), (res2), (res3), (res4), (res5))
 
#define ipc_call_sync_4_0(phoneid, method, arg1, arg2, arg3, arg4) \
ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), 0, \
0, 0, 0, 0, 0)
ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), 0, \
0, 0, 0, 0, 0)
#define ipc_call_sync_4_1(phoneid, method, arg1, arg2, arg3, arg4, res1) \
ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), 0, \
(res1), 0, 0, 0, 0)
ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), 0, \
(res1), 0, 0, 0, 0)
#define ipc_call_sync_4_2(phoneid, method, arg1, arg2, arg3, arg4, res1, res2) \
ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), 0, \
(res1), (res2), 0, 0, 0)
ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), 0, \
(res1), (res2), 0, 0, 0)
#define ipc_call_sync_4_3(phoneid, method, arg1, arg2, arg3, arg4, res1, res2, \
res3) \
ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), \
149,12 → 158,13
res3, res4, res5) \
ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), \
(arg4), 0, (res1), (res2), (res3), (res4), (res5))
 
#define ipc_call_sync_5_0(phoneid, method, arg1, arg2, arg3, arg4, arg5) \
ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
(arg5), 0, 0, 0, 0, 0)
ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
(arg5), 0, 0, 0, 0, 0)
#define ipc_call_sync_5_1(phoneid, method, arg1, arg2, arg3, arg4, arg5, res1) \
ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
(arg5), (res1), 0, 0, 0, 0)
ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
(arg5), (res1), 0, 0, 0, 0)
#define ipc_call_sync_5_2(phoneid, method, arg1, arg2, arg3, arg4, arg5, res1, \
res2) \
ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), \
181,10 → 191,12
 
extern ipc_callid_t ipc_wait_cycle(ipc_call_t *, uint32_t, int);
extern ipc_callid_t ipc_wait_for_call_timeout(ipc_call_t *, uint32_t);
 
static inline ipc_callid_t ipc_wait_for_call(ipc_call_t *data)
{
return ipc_wait_for_call_timeout(data, SYNCH_NO_TIMEOUT);
}
 
extern ipc_callid_t ipc_trywait_for_call(ipc_call_t *);
 
/*
194,17 → 206,17
* to m.
*/
#define ipc_answer_0(callid, retval) \
ipc_answer_fast((callid), (retval), 0, 0, 0, 0)
ipc_answer_fast((callid), (retval), 0, 0, 0, 0)
#define ipc_answer_1(callid, retval, arg1) \
ipc_answer_fast((callid), (retval), (arg1), 0, 0, 0)
ipc_answer_fast((callid), (retval), (arg1), 0, 0, 0)
#define ipc_answer_2(callid, retval, arg1, arg2) \
ipc_answer_fast((callid), (retval), (arg1), (arg2), 0, 0)
ipc_answer_fast((callid), (retval), (arg1), (arg2), 0, 0)
#define ipc_answer_3(callid, retval, arg1, arg2, arg3) \
ipc_answer_fast((callid), (retval), (arg1), (arg2), (arg3), 0)
ipc_answer_fast((callid), (retval), (arg1), (arg2), (arg3), 0)
#define ipc_answer_4(callid, retval, arg1, arg2, arg3, arg4) \
ipc_answer_fast((callid), (retval), (arg1), (arg2), (arg3), (arg4))
ipc_answer_fast((callid), (retval), (arg1), (arg2), (arg3), (arg4))
#define ipc_answer_5(callid, retval, arg1, arg2, arg3, arg4, arg5) \
ipc_answer_slow((callid), (retval), (arg1), (arg2), (arg3), (arg4), (arg5))
ipc_answer_slow((callid), (retval), (arg1), (arg2), (arg3), (arg4), (arg5))
 
extern ipcarg_t ipc_answer_fast(ipc_callid_t, ipcarg_t, ipcarg_t, ipcarg_t,
ipcarg_t, ipcarg_t);
246,8 → 258,6
extern void ipc_call_async_slow(int, ipcarg_t, ipcarg_t, ipcarg_t, ipcarg_t,
ipcarg_t, ipcarg_t, void *, ipc_async_callback_t, int);
 
#define IPC_FLAG_BLOCKING 0x01
 
extern int ipc_connect_to_me(int, int, int, int, ipcarg_t *);
extern int ipc_connect_me_to(int, int, int, int);
extern int ipc_connect_me_to_blocking(int, int, int, int);
256,20 → 266,19
extern int ipc_unregister_irq(int, int);
extern int ipc_forward_fast(ipc_callid_t, int, int, ipcarg_t, ipcarg_t, int);
extern int ipc_forward_slow(ipc_callid_t, int, int, ipcarg_t, ipcarg_t,
ipcarg_t, ipcarg_t, ipcarg_t, int);
ipcarg_t, ipcarg_t, ipcarg_t, int);
 
 
/*
* User-friendly wrappers for ipc_share_in_start().
*/
#define ipc_share_in_start_0_0(phoneid, dst, size) \
ipc_share_in_start((phoneid), (dst), (size), 0, NULL)
ipc_share_in_start((phoneid), (dst), (size), 0, NULL)
#define ipc_share_in_start_0_1(phoneid, dst, size, flags) \
ipc_share_in_start((phoneid), (dst), (size), 0, (flags))
ipc_share_in_start((phoneid), (dst), (size), 0, (flags))
#define ipc_share_in_start_1_0(phoneid, dst, size, arg) \
ipc_share_in_start((phoneid), (dst), (size), (arg), NULL)
ipc_share_in_start((phoneid), (dst), (size), (arg), NULL)
#define ipc_share_in_start_1_1(phoneid, dst, size, arg, flags) \
ipc_share_in_start((phoneid), (dst), (size), (arg), (flags))
ipc_share_in_start((phoneid), (dst), (size), (arg), (flags))
 
extern int ipc_share_in_start(int, void *, size_t, ipcarg_t, int *);
extern int ipc_share_in_receive(ipc_callid_t *, size_t *);
284,8 → 293,6
extern int ipc_data_write_receive(ipc_callid_t *, size_t *);
extern int ipc_data_write_finalize(ipc_callid_t, void *, size_t);
 
#include <task.h>
 
extern int ipc_connect_kbox(task_id_t);
 
#endif
/branches/dd/uspace/lib/libc/include/ipc/devmap.h
35,7 → 35,7
 
#include <atomic.h>
#include <ipc/ipc.h>
#include <libadt/list.h>
#include <adt/list.h>
 
#define DEVMAP_NAME_MAXLEN 255
 
/branches/dd/uspace/lib/libc/include/ipc/vfs.h
0,0 → 1,147
/*
* Copyright (c) 2009 Martin Decky
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup libcipc
* @{
*/
/** @file
*/
 
#ifndef LIBC_IPC_VFS_H_
#define LIBC_IPC_VFS_H_
 
#include <sys/types.h>
#include <ipc/ipc.h>
 
#define FS_NAME_MAXLEN 20
#define MAX_PATH_LEN (64 * 1024)
#define PLB_SIZE (2 * MAX_PATH_LEN)
 
/* Basic types. */
typedef int16_t fs_handle_t;
typedef uint32_t fs_index_t;
 
/**
* A structure like this is passed to VFS by each individual FS upon its
* registration. It assosiates a human-readable identifier with each
* registered FS.
*/
typedef struct {
/** Unique identifier of the fs. */
char name[FS_NAME_MAXLEN + 1];
} vfs_info_t;
 
typedef enum {
VFS_OPEN_NODE = IPC_FIRST_USER_METHOD,
VFS_READ,
VFS_WRITE,
VFS_TRUNCATE,
VFS_MOUNT,
VFS_UNMOUNT,
VFS_DEVICE,
VFS_SYNC,
VFS_CLOSE,
VFS_LAST_CMN /* keep this the last member of this enum */
} vfs_request_cmn_t;
 
typedef enum {
VFS_LOOKUP = VFS_LAST_CMN,
VFS_MOUNTED,
VFS_DESTROY,
VFS_LAST_CLNT /* keep this the last member of this enum */
} vfs_request_clnt_t;
 
typedef enum {
VFS_REGISTER = VFS_LAST_CMN,
VFS_OPEN,
VFS_SEEK,
VFS_MKDIR,
VFS_UNLINK,
VFS_RENAME,
VFS_NODE,
VFS_LAST_SRV /* keep this the last member of this enum */
} vfs_request_srv_t;
 
/*
* Lookup flags.
*/
 
/**
* No lookup flags used.
*/
#define L_NONE 0
 
/**
* Lookup will succeed only if the object is a regular file. If L_CREATE is
* specified, an empty file will be created. This flag is mutually exclusive
* with L_DIRECTORY.
*/
#define L_FILE 1
 
/**
* Lookup wil succeed only if the object is a directory. If L_CREATE is
* specified, an empty directory will be created. This flag is mutually
* exclusive with L_FILE.
*/
#define L_DIRECTORY 2
 
/**
* When used with L_CREATE, L_EXCLUSIVE will cause the lookup to fail if the
* object already exists. L_EXCLUSIVE is implied when L_DIRECTORY is used.
*/
#define L_EXCLUSIVE 4
 
/**
* L_CREATE is used for creating both regular files and directories.
*/
#define L_CREATE 8
 
/**
* L_LINK is used for linking to an already existing nodes.
*/
#define L_LINK 16
 
/**
* L_UNLINK is used to remove leaves from the file system namespace. This flag
* cannot be passed directly by the client, but will be set by VFS during
* VFS_UNLINK.
*/
#define L_UNLINK 32
 
/**
* L_OPEN is used to indicate that the lookup operation is a part of VFS_OPEN
* call from the client. This means that the server might allocate some
* resources for the opened file. This flag cannot be passed directly by the
* client.
*/
#define L_OPEN 64
 
#endif
 
/** @}
*/
/branches/dd/uspace/lib/libc/include/ipc/ns.h
35,6 → 35,13
#ifndef LIBIPC_NS_H_
#define LIBIPC_NS_H_
 
#include <ipc/ipc.h>
 
typedef enum {
NS_PING = IPC_FIRST_USER_METHOD,
NS_TASK_WAIT
} ns_request_t;
 
#endif
 
/** @}
/branches/dd/uspace/lib/libc/include/ipc/console.h
27,7 → 27,7
*/
 
/** @addtogroup libcipc
* @{
* @{
*/
/** @file
*/
36,15 → 36,13
#define LIBC_IPC_CONSOLE_H_
 
#include <ipc/ipc.h>
#include <ipc/vfs.h>
 
typedef enum {
CONSOLE_GETKEY = IPC_FIRST_USER_METHOD,
CONSOLE_PUTCHAR,
CONSOLE_WRITE,
CONSOLE_GET_SIZE = VFS_LAST_SRV,
CONSOLE_GET_EVENT,
CONSOLE_GOTO,
CONSOLE_CLEAR,
CONSOLE_GOTO,
CONSOLE_GETSIZE,
CONSOLE_FLUSH,
CONSOLE_SET_STYLE,
CONSOLE_SET_COLOR,
CONSOLE_SET_RGB_COLOR,
53,6 → 51,6
} console_request_t;
 
#endif
 
/** @}
*/
/branches/dd/uspace/lib/libc/include/ipc/loader.h
42,6 → 42,7
LOADER_GET_TASKID,
LOADER_SET_PATHNAME,
LOADER_SET_ARGS,
LOADER_SET_FILES,
LOADER_LOAD,
LOADER_RUN
} loader_request_t;
/branches/dd/uspace/lib/libc/include/errno.h
41,17 → 41,18
 
#include <kernel/errno.h>
 
#define ENAMETOOLONG (-256)
#define EISDIR (-257)
#define ENOTDIR (-258)
#define ENOSPC (-259)
#define EEXIST (-260)
#define ENOTEMPTY (-261)
#define EBADF (-262)
#define ERANGE (-263)
#define EXDEV (-264)
#define EIO (-265)
#define EMLINK (-266)
#define EMFILE (-17)
#define ENAMETOOLONG (-256)
#define EISDIR (-257)
#define ENOTDIR (-258)
#define ENOSPC (-259)
#define EEXIST (-260)
#define ENOTEMPTY (-261)
#define EBADF (-262)
#define ERANGE (-263)
#define EXDEV (-264)
#define EIO (-265)
#define EMLINK (-266)
 
#endif
 
/branches/dd/uspace/lib/libc/Makefile.toolchain
26,10 → 26,10
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
 
CFLAGS = -fno-builtin -Wall -Werror-implicit-function-declaration \
CFLAGS = -I$(LIBC_PREFIX)/include -O3 -imacros $(LIBC_PREFIX)/../../../config.h \
-fexec-charset=UTF-8 -fwide-exec-charset=UTF-32 -finput-charset=UTF-8 \
-Wmissing-prototypes -O3 -nostdlib -nostdinc -imacros \
$(LIBC_PREFIX)/../../../config.h -I$(LIBC_PREFIX)/include -pipe -g
-fno-builtin -Wall -Wextra -Wno-unused-parameter -Wmissing-prototypes \
-Werror-implicit-function-declaration -nostdlib -nostdinc -pipe -g
LFLAGS = -M -N $(SOFTINT_PREFIX)/libsoftint.a
AFLAGS =
 
/branches/dd/uspace/lib/libc/generic/kbd.c
File deleted
/branches/dd/uspace/lib/libc/generic/libadt/hash_table.c
File deleted
/branches/dd/uspace/lib/libc/generic/libadt/list.c
File deleted
/branches/dd/uspace/lib/libc/generic/console.c
File deleted
/branches/dd/uspace/lib/libc/generic/ddi.c
127,7 → 127,7
}
#endif
 
phys = ALIGN_DOWN((uintptr_t) pio_addr, PAGE_SIZE);
phys = (void *) ALIGN_DOWN((uintptr_t) pio_addr, PAGE_SIZE);
offset = pio_addr - phys;
pages = ALIGN_UP(offset + size, PAGE_SIZE) >> PAGE_WIDTH;
virt = as_get_mappable_page(pages << PAGE_WIDTH);
/branches/dd/uspace/lib/libc/generic/task.c
31,7 → 31,7
* @{
*/
/** @file
*/
*/
 
#include <task.h>
#include <libc.h>
39,21 → 39,25
#include <errno.h>
#include <loader/loader.h>
#include <string.h>
#include <ipc/ns.h>
#include <macros.h>
#include <async.h>
 
task_id_t task_get_id(void)
{
task_id_t task_id;
 
(void) __SYSCALL1(SYS_TASK_GET_ID, (sysarg_t) &task_id);
 
return task_id;
}
 
/** Set the task name.
*
* @param name The new name, typically the command used to execute the
* program.
* @return Zero on success or negative error code.
* @param name The new name, typically the command used to execute the
* program.
*
* @return Zero on success or negative error code.
*
*/
int task_set_name(const char *name)
{
65,58 → 69,89
* This is really just a convenience wrapper over the more complicated
* loader API.
*
* @param path pathname of the binary to execute
* @param argv command-line arguments
* @return ID of the newly created task or zero on error.
* @param path pathname of the binary to execute
* @param argv command-line arguments
*
* @return ID of the newly created task or zero on error.
*
*/
task_id_t task_spawn(const char *path, char *const argv[])
task_id_t task_spawn(const char *path, char *const args[])
{
loader_t *ldr;
task_id_t task_id;
int rc;
 
/* Connect to a program loader. */
ldr = loader_connect();
loader_t *ldr = loader_connect();
if (ldr == NULL)
return 0;
 
/* Get task ID. */
rc = loader_get_task_id(ldr, &task_id);
task_id_t task_id;
int rc = loader_get_task_id(ldr, &task_id);
if (rc != EOK)
goto error;
 
/* Send program pathname. */
rc = loader_set_pathname(ldr, path);
if (rc != EOK)
goto error;
 
/* Send arguments. */
rc = loader_set_args(ldr, argv);
rc = loader_set_args(ldr, args);
if (rc != EOK)
goto error;
 
/* Send default files */
fdi_node_t *files[4];
fdi_node_t stdin_node;
fdi_node_t stdout_node;
fdi_node_t stderr_node;
if ((stdin != NULL) && (fnode(stdin, &stdin_node) == EOK))
files[0] = &stdin_node;
else
files[0] = NULL;
if ((stdout != NULL) && (fnode(stdout, &stdout_node) == EOK))
files[1] = &stdout_node;
else
files[1] = NULL;
if ((stderr != NULL) && (fnode(stderr, &stderr_node) == EOK))
files[2] = &stderr_node;
else
files[2] = NULL;
files[3] = NULL;
rc = loader_set_files(ldr, files);
if (rc != EOK)
goto error;
/* Load the program. */
rc = loader_load_program(ldr);
if (rc != EOK)
goto error;
 
/* Run it. */
rc = loader_run(ldr);
if (rc != EOK)
goto error;
 
/* Success */
 
free(ldr);
return task_id;
 
error:
/* Error exit */
error:
loader_abort(ldr);
free(ldr);
 
return 0;
}
 
int task_wait(task_id_t id)
{
return (int) async_req_2_0(PHONE_NS, NS_TASK_WAIT, LOWER32(id), UPPER32(id));
}
 
/** @}
*/
/branches/dd/uspace/lib/libc/generic/fibril_sync.c
0,0 → 1,219
/*
* Copyright (c) 2009 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup libc
* @{
*/
/** @file
*/
 
#include <fibril_sync.h>
#include <fibril.h>
#include <async.h>
#include <adt/list.h>
#include <futex.h>
#include <assert.h>
 
void fibril_mutex_initialize(fibril_mutex_t *fm)
{
fm->counter = 1;
list_initialize(&fm->waiters);
}
 
void fibril_mutex_lock(fibril_mutex_t *fm)
{
futex_down(&async_futex);
if (fm->counter-- <= 0) {
fibril_t *f = (fibril_t *) fibril_get_id();
list_append(&f->link, &fm->waiters);
fibril_switch(FIBRIL_TO_MANAGER);
} else {
futex_up(&async_futex);
}
}
 
bool fibril_mutex_trylock(fibril_mutex_t *fm)
{
bool locked = false;
futex_down(&async_futex);
if (fm->counter > 0) {
fm->counter--;
locked = true;
}
futex_up(&async_futex);
return locked;
}
 
static void _fibril_mutex_unlock_unsafe(fibril_mutex_t *fm)
{
assert(fm->counter <= 0);
if (fm->counter++ < 0) {
link_t *tmp;
fibril_t *f;
assert(!list_empty(&fm->waiters));
tmp = fm->waiters.next;
f = list_get_instance(tmp, fibril_t, link);
list_remove(&f->link);
fibril_add_ready((fid_t) f);
}
}
 
void fibril_mutex_unlock(fibril_mutex_t *fm)
{
futex_down(&async_futex);
_fibril_mutex_unlock_unsafe(fm);
futex_up(&async_futex);
}
 
void fibril_rwlock_initialize(fibril_rwlock_t *frw)
{
frw->writers = 0;
frw->readers = 0;
list_initialize(&frw->waiters);
}
 
void fibril_rwlock_read_lock(fibril_rwlock_t *frw)
{
futex_down(&async_futex);
if (frw->writers) {
fibril_t *f = (fibril_t *) fibril_get_id();
f->flags &= ~FIBRIL_WRITER;
list_append(&f->link, &frw->waiters);
fibril_switch(FIBRIL_TO_MANAGER);
} else {
frw->readers++;
futex_up(&async_futex);
}
}
 
void fibril_rwlock_write_lock(fibril_rwlock_t *frw)
{
futex_down(&async_futex);
if (frw->writers || frw->readers) {
fibril_t *f = (fibril_t *) fibril_get_id();
f->flags |= FIBRIL_WRITER;
list_append(&f->link, &frw->waiters);
fibril_switch(FIBRIL_TO_MANAGER);
} else {
frw->writers++;
futex_up(&async_futex);
}
}
 
static void _fibril_rwlock_common_unlock(fibril_rwlock_t *frw)
{
futex_down(&async_futex);
assert(frw->readers || (frw->writers == 1));
if (frw->readers) {
if (--frw->readers)
goto out;
} else {
frw->writers--;
}
assert(!frw->readers && !frw->writers);
while (!list_empty(&frw->waiters)) {
link_t *tmp = frw->waiters.next;
fibril_t *f = list_get_instance(tmp, fibril_t, link);
if (f->flags & FIBRIL_WRITER) {
if (frw->readers)
break;
list_remove(&f->link);
fibril_add_ready((fid_t) f);
frw->writers++;
break;
} else {
list_remove(&f->link);
fibril_add_ready((fid_t) f);
frw->readers++;
}
}
out:
futex_up(&async_futex);
}
 
void fibril_rwlock_read_unlock(fibril_rwlock_t *frw)
{
_fibril_rwlock_common_unlock(frw);
}
 
void fibril_rwlock_write_unlock(fibril_rwlock_t *frw)
{
_fibril_rwlock_common_unlock(frw);
}
 
void fibril_condvar_initialize(fibril_condvar_t *fcv)
{
list_initialize(&fcv->waiters);
}
 
void fibril_condvar_wait(fibril_condvar_t *fcv, fibril_mutex_t *fm)
{
fibril_t *f = (fibril_t *) fibril_get_id();
 
futex_down(&async_futex);
list_append(&f->link, &fcv->waiters);
_fibril_mutex_unlock_unsafe(fm);
fibril_switch(FIBRIL_TO_MANAGER);
fibril_mutex_lock(fm);
}
 
static void _fibril_condvar_wakeup_common(fibril_condvar_t *fcv, bool once)
{
link_t *tmp;
fibril_t *f;
 
futex_down(&async_futex);
while (!list_empty(&fcv->waiters)) {
tmp = fcv->waiters.next;
f = list_get_instance(tmp, fibril_t, link);
list_remove(&f->link);
fibril_add_ready((fid_t) f);
if (once)
break;
}
futex_up(&async_futex);
}
 
void fibril_condvar_signal(fibril_condvar_t *fcv)
{
_fibril_condvar_wakeup_common(fcv, true);
}
 
void fibril_condvar_broadcast(fibril_condvar_t *fcv)
{
_fibril_condvar_wakeup_common(fcv, false);
}
 
/** @}
*/
/branches/dd/uspace/lib/libc/generic/as.c
30,7 → 30,7
* @{
*/
/** @file
*/
*/
 
#include <as.h>
#include <libc.h>
102,7 → 102,7
static size_t heapsize = 0;
static size_t maxheapsize = (size_t) (-1);
 
static void * last_allocated = 0;
static void *last_allocated = 0;
 
/* Start of heap linker symbol */
extern char _heap;
119,15 → 119,15
void *res;
/* Check for invalid values */
if (incr < 0 && -incr > heapsize)
if ((incr < 0) && (((size_t) -incr) > heapsize))
return NULL;
/* Check for too large value */
if (incr > 0 && incr+heapsize < heapsize)
if ((incr > 0) && (incr + heapsize < heapsize))
return NULL;
/* Check for too small values */
if (incr < 0 && incr+heapsize > heapsize)
if ((incr < 0) && (incr + heapsize > heapsize))
return NULL;
/* Check for user limit */
175,7 → 175,7
asz = 1 << (fnzb64(sz - 1) + 1);
 
/* Set heapsize to some meaningful value */
if (maxheapsize == -1)
if (maxheapsize == (size_t) -1)
set_maxheapsize(MAX_HEAP_SIZE);
/*
/branches/dd/uspace/lib/libc/generic/string.c
138,8 → 138,8
* @param size Size of the output buffer (in bytes).
*
* @return EOK if the character was encoded successfully, EOVERFLOW if there
* was not enough space in the output buffer or EINVAL if the character
* code was invalid.
* was not enough space in the output buffer or EINVAL if the character
* code was invalid.
*/
int chr_encode(const wchar_t ch, char *str, size_t *offset, size_t size)
{
243,9 → 243,9
* @return Number of bytes used by the characters.
*
*/
size_t str_lsize(const char *str, count_t max_len)
size_t str_lsize(const char *str, size_t max_len)
{
count_t len = 0;
size_t len = 0;
size_t offset = 0;
while (len < max_len) {
271,7 → 271,7
* @return Number of bytes used by the wide characters.
*
*/
size_t wstr_lsize(const wchar_t *str, count_t max_len)
size_t wstr_lsize(const wchar_t *str, size_t max_len)
{
return (wstr_nlength(str, max_len * sizeof(wchar_t)) * sizeof(wchar_t));
}
283,9 → 283,9
* @return Number of characters in string.
*
*/
count_t str_length(const char *str)
size_t str_length(const char *str)
{
count_t len = 0;
size_t len = 0;
size_t offset = 0;
while (str_decode(str, &offset, STR_NO_LIMIT) != 0)
301,9 → 301,9
* @return Number of characters in @a str.
*
*/
count_t wstr_length(const wchar_t *wstr)
size_t wstr_length(const wchar_t *wstr)
{
count_t len = 0;
size_t len = 0;
while (*wstr++ != 0)
len++;
319,9 → 319,9
* @return Number of characters in string.
*
*/
count_t str_nlength(const char *str, size_t size)
size_t str_nlength(const char *str, size_t size)
{
count_t len = 0;
size_t len = 0;
size_t offset = 0;
while (str_decode(str, &offset, size) != 0)
338,11 → 338,11
* @return Number of characters in string.
*
*/
count_t wstr_nlength(const wchar_t *str, size_t size)
size_t wstr_nlength(const wchar_t *str, size_t size)
{
count_t len = 0;
count_t limit = ALIGN_DOWN(size, sizeof(wchar_t));
count_t offset = 0;
size_t len = 0;
size_t limit = ALIGN_DOWN(size, sizeof(wchar_t));
size_t offset = 0;
while ((offset < limit) && (*str++ != 0)) {
len++;
430,7 → 430,7
* 1 if second smaller.
*
*/
int str_lcmp(const char *s1, const char *s2, count_t max_len)
int str_lcmp(const char *s1, const char *s2, size_t max_len)
{
wchar_t c1 = 0;
wchar_t c2 = 0;
438,7 → 438,7
size_t off1 = 0;
size_t off2 = 0;
count_t len = 0;
size_t len = 0;
 
while (true) {
if (len >= max_len)
568,7 → 568,7
return;
wchar_t ch;
count_t src_idx = 0;
size_t src_idx = 0;
size_t dst_off = 0;
while ((ch = src[src_idx++]) != 0) {
616,7 → 616,7
wchar_t acc;
size_t off = 0;
size_t last = 0;
char *res = NULL;
const char *res = NULL;
while ((acc = str_decode(str, &off, STR_NO_LIMIT)) != 0) {
if (acc == ch)
641,14 → 641,14
* is out of bounds.
*
*/
bool wstr_linsert(wchar_t *str, wchar_t ch, count_t pos, count_t max_pos)
bool wstr_linsert(wchar_t *str, wchar_t ch, size_t pos, size_t max_pos)
{
count_t len = wstr_length(str);
size_t len = wstr_length(str);
if ((pos > len) || (pos + 1 > max_pos))
return false;
count_t i;
size_t i;
for (i = len; i + 1 > pos; i--)
str[i + 1] = str[i];
669,14 → 669,14
* is out of bounds.
*
*/
bool wstr_remove(wchar_t *str, count_t pos)
bool wstr_remove(wchar_t *str, size_t pos)
{
count_t len = wstr_length(str);
size_t len = wstr_length(str);
if (pos >= len)
return false;
count_t i;
size_t i;
for (i = pos + 1; i <= len; i++)
str[i - 1] = str[i];
/branches/dd/uspace/lib/libc/generic/loader.c
30,7 → 30,7
* @{
*/
/** @file
*/
*/
 
#include <ipc/ipc.h>
#include <ipc/loader.h>
47,9 → 47,12
/** Connect to a new program loader.
*
* Spawns a new program loader task and returns the connection structure.
* @param name Symbolic name to set on the newly created task.
* @return Pointer to the loader connection structure (should be
* de-allocated using free() after use).
*
* @param name Symbolic name to set on the newly created task.
*
* @return Pointer to the loader connection structure (should be
* deallocated using free() after use).
*
*/
int loader_spawn(const char *name)
{
59,19 → 62,16
 
loader_t *loader_connect(void)
{
loader_t *ldr;
int phone_id;
 
phone_id = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_LOAD, 0, 0);
int phone_id = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_LOAD, 0, 0);
if (phone_id < 0)
return NULL;
 
ldr = malloc(sizeof(loader_t));
loader_t *ldr = malloc(sizeof(loader_t));
if (ldr == NULL)
return NULL;
 
ldr->phone_id = phone_id;
return ldr;
return ldr;
}
 
/** Get ID of the new task.
78,27 → 78,26
*
* Retrieves the ID of the new task from the loader.
*
* @param ldr Loader connection structure.
* @param task_id Points to a variable where the ID should be stored.
* @return Zero on success or negative error code.
* @param ldr Loader connection structure.
* @param task_id Points to a variable where the ID should be stored.
*
* @return Zero on success or negative error code.
*
*/
int loader_get_task_id(loader_t *ldr, task_id_t *task_id)
{
/* Get task ID. */
ipc_call_t answer;
aid_t req;
int rc;
ipcarg_t retval;
 
/* Get task ID. */
req = async_send_0(ldr->phone_id, LOADER_GET_TASKID, &answer);
rc = ipc_data_read_start(ldr->phone_id, task_id, sizeof(task_id_t));
aid_t req = async_send_0(ldr->phone_id, LOADER_GET_TASKID, &answer);
int rc = ipc_data_read_start(ldr->phone_id, task_id, sizeof(task_id_t));
if (rc != EOK) {
async_wait_for(req, NULL);
return rc;
}
 
ipcarg_t retval;
async_wait_for(req, &retval);
return (int)retval;
return (int) retval;
}
 
/** Set pathname of the program to load.
107,39 → 106,35
* to the current working directory (it will be absolutized before
* sending to the loader).
*
* @param ldr Loader connection structure.
* @param path Pathname of the program file.
* @return Zero on success or negative error code.
* @param ldr Loader connection structure.
* @param path Pathname of the program file.
*
* @return Zero on success or negative error code.
*
*/
int loader_set_pathname(loader_t *ldr, const char *path)
{
ipc_call_t answer;
aid_t req;
int rc;
ipcarg_t retval;
 
char *pa;
size_t pa_len;
 
pa = absolutize(path, &pa_len);
char *pa = absolutize(path, &pa_len);
if (!pa)
return 0;
 
/* Send program pathname */
req = async_send_0(ldr->phone_id, LOADER_SET_PATHNAME, &answer);
rc = ipc_data_write_start(ldr->phone_id, (void *)pa, pa_len);
ipc_call_t answer;
aid_t req = async_send_0(ldr->phone_id, LOADER_SET_PATHNAME, &answer);
int rc = ipc_data_write_start(ldr->phone_id, (void *) pa, pa_len);
if (rc != EOK) {
async_wait_for(req, NULL);
return rc;
}
 
free(pa);
 
ipcarg_t retval;
async_wait_for(req, &retval);
return (int)retval;
return (int) retval;
}
 
 
/** Set command-line arguments for the program.
*
* Sets the vector of command-line arguments to be passed to the loaded
146,61 → 141,110
* program. By convention, the very first argument is typically the same as
* the command used to execute the program.
*
* @param ldr Loader connection structure.
* @param argv NULL-terminated array of pointers to arguments.
* @return Zero on success or negative error code.
* @param ldr Loader connection structure.
* @param argv NULL-terminated array of pointers to arguments.
*
* @return Zero on success or negative error code.
*
*/
int loader_set_args(loader_t *ldr, char *const argv[])
{
aid_t req;
ipc_call_t answer;
ipcarg_t rc;
 
char *const *ap;
char *dp;
char *arg_buf;
size_t buffer_size;
 
/*
/*
* Serialize the arguments into a single array. First
* compute size of the buffer needed.
*/
ap = argv;
buffer_size = 0;
char *const *ap = argv;
size_t buffer_size = 0;
while (*ap != NULL) {
buffer_size += str_size(*ap) + 1;
++ap;
ap++;
}
 
arg_buf = malloc(buffer_size);
if (arg_buf == NULL) return ENOMEM;
 
char *arg_buf = malloc(buffer_size);
if (arg_buf == NULL)
return ENOMEM;
/* Now fill the buffer with null-terminated argument strings */
ap = argv;
dp = arg_buf;
 
char *dp = arg_buf;
while (*ap != NULL) {
str_cpy(dp, buffer_size - (dp - arg_buf), *ap);
dp += str_size(*ap) + 1;
 
++ap;
ap++;
}
 
/* Send serialized arguments to the loader */
 
req = async_send_0(ldr->phone_id, LOADER_SET_ARGS, &answer);
rc = ipc_data_write_start(ldr->phone_id, (void *)arg_buf, buffer_size);
ipc_call_t answer;
aid_t req = async_send_0(ldr->phone_id, LOADER_SET_ARGS, &answer);
ipcarg_t rc = ipc_data_write_start(ldr->phone_id, (void *) arg_buf, buffer_size);
if (rc != EOK) {
async_wait_for(req, NULL);
return rc;
}
 
async_wait_for(req, &rc);
if (rc != EOK) return rc;
 
if (rc != EOK)
return rc;
/* Free temporary buffer */
free(arg_buf);
return EOK;
}
 
/** Set preset files for the program.
*
* Sets the vector of preset files to be passed to the loaded
* program. By convention, the first three files represent stdin,
* stdout and stderr respectively.
*
* @param ldr Loader connection structure.
* @param files NULL-terminated array of pointers to files.
*
* @return Zero on success or negative error code.
*
*/
int loader_set_files(loader_t *ldr, fdi_node_t *const files[])
{
/*
* Serialize the arguments into a single array. First
* compute size of the buffer needed.
*/
fdi_node_t *const *ap = files;
size_t count = 0;
while (*ap != NULL) {
count++;
ap++;
}
fdi_node_t *files_buf;
files_buf = (fdi_node_t *) malloc(count * sizeof(fdi_node_t));
if (files_buf == NULL)
return ENOMEM;
/* Fill the buffer */
size_t i;
for (i = 0; i < count; i++)
files_buf[i] = *files[i];
/* Send serialized files to the loader */
ipc_call_t answer;
aid_t req = async_send_0(ldr->phone_id, LOADER_SET_FILES, &answer);
ipcarg_t rc = ipc_data_write_start(ldr->phone_id, (void *) files_buf,
count * sizeof(fdi_node_t));
if (rc != EOK) {
async_wait_for(req, NULL);
return rc;
}
async_wait_for(req, &rc);
if (rc != EOK)
return rc;
/* Free temporary buffer */
free(files_buf);
return EOK;
}
 
209,18 → 253,14
* If this function succeeds, the program has been successfully loaded
* and is ready to be executed.
*
* @param ldr Loader connection structure.
* @return Zero on success or negative error code.
* @param ldr Loader connection structure.
*
* @return Zero on success or negative error code.
*
*/
int loader_load_program(loader_t *ldr)
{
int rc;
 
rc = async_req_0_0(ldr->phone_id, LOADER_LOAD);
if (rc != EOK)
return rc;
 
return EOK;
return (int) async_req_0_0(ldr->phone_id, LOADER_LOAD);
}
 
/** Instruct loader to execute the program.
232,17 → 272,17
* After using this function, no further operations must be performed
* on the loader structure. It should be de-allocated using free().
*
* @param ldr Loader connection structure.
* @return Zero on success or negative error code.
* @param ldr Loader connection structure.
*
* @return Zero on success or negative error code.
*
*/
int loader_run(loader_t *ldr)
{
int rc;
 
rc = async_req_0_0(ldr->phone_id, LOADER_RUN);
int rc = async_req_0_0(ldr->phone_id, LOADER_RUN);
if (rc != EOK)
return rc;
 
ipc_hangup(ldr->phone_id);
ldr->phone_id = 0;
return EOK;
254,8 → 294,10
* After using this function, no further operations must be performed
* on the loader structure. It should be de-allocated using free().
*
* @param ldr Loader connection structure.
* @return Zero on success or negative error code.
* @param ldr Loader connection structure.
*
* @return Zero on success or negative error code.
*
*/
void loader_abort(loader_t *ldr)
{
/branches/dd/uspace/lib/libc/generic/fibril.c
33,7 → 33,7
/** @file
*/
 
#include <libadt/list.h>
#include <adt/list.h>
#include <fibril.h>
#include <thread.h>
#include <tls.h>
49,7 → 49,8
#define FIBRIL_INITIAL_STACK_PAGES_NO 1
#endif
 
/** This futex serializes access to ready_list, serialized_list and manage_list.
/**
* This futex serializes access to ready_list, serialized_list and manager_list.
*/
static atomic_t fibril_futex = FUTEX_INITIALIZER;
 
59,12 → 60,12
 
static void fibril_main(void);
 
/** Number of fibrils that are in async_serialized mode */
static int serialized_fibrils; /* Protected by async_futex */
/** Thread-local count of serialization. If >0, we must not preempt */
static __thread int serialization_count;
/** Counter for fibrils residing in async_manager */
static int fibrils_in_manager;
/** Number of threads that are executing a manager fibril. */
static int threads_in_manager;
/** Number of threads that are executing a manager fibril and are serialized. */
static int serialized_threads; /* Protected by async_futex */
/** Fibril-local count of serialization. If > 0, we must not preempt */
static fibril_local int serialization_count;
 
/** Setup fibril information into TCB structure */
fibril_t *fibril_setup(void)
143,11 → 144,11
if (list_empty(&ready_list) && list_empty(&serialized_list))
goto ret_0;
/*
* Do not preempt if there is not sufficient count of fibril
* managers.
* Do not preempt if there is not enough threads to run the
* ready fibrils which are not serialized.
*/
if (list_empty(&serialized_list) &&
fibrils_in_manager <= serialized_fibrils) {
threads_in_manager <= serialized_threads) {
goto ret_0;
}
}
194,7 → 195,7
list_append(&srcf->link, &ready_list);
else if (stype == FIBRIL_FROM_MANAGER) {
list_append(&srcf->link, &manager_list);
fibrils_in_manager--;
threads_in_manager--;
} else {
/*
* If stype == FIBRIL_TO_MANAGER, don't put ourselves to
208,10 → 209,10
if (stype == FIBRIL_TO_MANAGER || stype == FIBRIL_FROM_DEAD) {
dstf = list_get_instance(manager_list.next, fibril_t, link);
if (serialization_count && stype == FIBRIL_TO_MANAGER) {
serialized_fibrils++;
serialized_threads++;
srcf->flags |= FIBRIL_SERIALIZED;
}
fibrils_in_manager++;
threads_in_manager++;
 
if (stype == FIBRIL_FROM_DEAD)
dstf->clean_after_me = srcf;
219,7 → 220,7
if (!list_empty(&serialized_list)) {
dstf = list_get_instance(serialized_list.next, fibril_t,
link);
serialized_fibrils--;
serialized_threads--;
} else {
dstf = list_get_instance(ready_list.next, fibril_t,
link);
269,7 → 270,7
 
/** Add a fibril to the ready list.
*
* @param fid Pinter to the fibril structure of the fibril to be
* @param fid Pointer to the fibril structure of the fibril to be
* added.
*/
void fibril_add_ready(fid_t fid)
287,7 → 288,8
 
/** Add a fibril to the manager list.
*
* @param fid Pinter to the fibril structure of the fibril to be added.
* @param fid Pointer to the fibril structure of the fibril to be
* added.
*/
void fibril_add_manager(fid_t fid)
{
314,7 → 316,8
 
/** Return fibril id of the currently running fibril.
*
* @return Fibril ID of the currently running pseudo thread.
* @return fibril ID of the currently running fibril.
*
*/
fid_t fibril_get_id(void)
{
321,13 → 324,14
return (fid_t) __tcb_get()->fibril_data;
}
 
/** Disable preemption
/** Disable preemption
*
* If the fibril wants to send several message in a row and does not want to be
* preempted, it should start async_serialize_start() in the beginning of
* communication and async_serialize_end() in the end. If it is a true
* multithreaded application, it should protect the communication channel by a
* futex as well. Interrupt messages can still be preempted.
* futex as well.
*
*/
void fibril_inc_sercount(void)
{
/branches/dd/uspace/lib/libc/generic/libc.c
27,28 → 27,29
*/
 
/** @addtogroup lc Libc
* @brief HelenOS C library
* @brief HelenOS C library
* @{
* @}
*/
 
/** @addtogroup libc generic
* @ingroup lc
* @{
*/
 
/** @file
*/
*/
 
#include <libc.h>
#include <stdio.h>
#include <unistd.h>
#include <malloc.h>
#include <tls.h>
#include <thread.h>
#include <fibril.h>
#include <io/stream.h>
#include <ipc/ipc.h>
#include <async.h>
#include <as.h>
#include <console.h>
#include <loader/pcb.h>
 
extern char _heap;
63,28 → 64,30
 
void __main(void *pcb_ptr)
{
fibril_t *f;
int argc;
char **argv;
 
(void) as_area_create(&_heap, 1, AS_AREA_WRITE | AS_AREA_READ);
_async_init();
f = fibril_setup();
__tcb_set(f->tcb);
fibril_t *fibril = fibril_setup();
__tcb_set(fibril->tcb);
/* Save the PCB pointer */
__pcb = (pcb_t *)pcb_ptr;
 
__pcb = (pcb_t *) pcb_ptr;
int argc;
char **argv;
if (__pcb == NULL) {
argc = 0;
argv = NULL;
stdio_init(0, NULL);
} else {
argc = __pcb->argc;
argv = __pcb->argv;
stdio_init(__pcb->filc, __pcb->filv);
}
 
main(argc, argv);
console_flush();
stdio_done();
}
 
void __exit(void)
/branches/dd/uspace/lib/libc/generic/ipc.c
43,7 → 43,7
#include <libc.h>
#include <malloc.h>
#include <errno.h>
#include <libadt/list.h>
#include <adt/list.h>
#include <stdio.h>
#include <unistd.h>
#include <futex.h>
232,7 → 232,7
return;
}
 
if (callid == IPC_CALLRET_FATAL) {
if (callid == (ipc_callid_t) IPC_CALLRET_FATAL) {
futex_up(&ipc_futex);
/* Call asynchronous handler with error code */
if (call->callback)
241,7 → 241,7
return;
}
 
if (callid == IPC_CALLRET_TEMPORARY) {
if (callid == (ipc_callid_t) IPC_CALLRET_TEMPORARY) {
futex_up(&ipc_futex);
 
call->u.msg.phoneid = phoneid;
309,7 → 309,7
callid = __SYSCALL6(SYS_IPC_CALL_ASYNC_FAST, phoneid, method, arg1,
arg2, arg3, arg4);
 
if (callid == IPC_CALLRET_TEMPORARY) {
if (callid == (ipc_callid_t) IPC_CALLRET_TEMPORARY) {
if (!call) {
call = ipc_prepare_async(private, callback);
if (!call)
442,7 → 442,7
call = list_get_instance(queued_calls.next, async_call_t, list);
callid = _ipc_call_async(call->u.msg.phoneid,
&call->u.msg.data);
if (callid == IPC_CALLRET_TEMPORARY) {
if (callid == (ipc_callid_t) IPC_CALLRET_TEMPORARY) {
break;
}
list_remove(&call->list);
451,7 → 451,7
if (call->fid)
fibril_add_ready(call->fid);
if (callid == IPC_CALLRET_FATAL) {
if (callid == (ipc_callid_t) IPC_CALLRET_FATAL) {
if (call->callback)
call->callback(call->private, ENOENT, NULL);
free(call);
/branches/dd/uspace/lib/libc/generic/devmap.c
99,6 → 99,8
if (phone < 0)
return phone;
async_serialize_start();
ipc_call_t answer;
aid_t req = async_send_2(phone, DEVMAP_DRIVER_REGISTER, 0, 0, &answer);
106,6 → 108,7
if (retval != EOK) {
async_wait_for(req, NULL);
async_serialize_end();
return -1;
}
115,6 → 118,8
ipc_connect_to_me(phone, 0, 0, 0, &callback_phonehash);
async_wait_for(req, &retval);
async_serialize_end();
return retval;
}
 
131,6 → 136,8
if (phone < 0)
return phone;
async_serialize_start();
ipc_call_t answer;
aid_t req = async_send_2(phone, DEVMAP_DEVICE_REGISTER, 0, 0,
&answer);
139,11 → 146,14
if (retval != EOK) {
async_wait_for(req, NULL);
async_serialize_end();
return retval;
}
async_wait_for(req, &retval);
async_serialize_end();
if (retval != EOK) {
if (handle != NULL)
*handle = -1;
163,6 → 173,8
if (phone < 0)
return phone;
async_serialize_start();
ipc_call_t answer;
aid_t req = async_send_2(phone, DEVMAP_DEVICE_GET_HANDLE, flags, 0,
&answer);
171,11 → 183,14
if (retval != EOK) {
async_wait_for(req, NULL);
async_serialize_end();
return retval;
}
async_wait_for(req, &retval);
async_serialize_end();
if (retval != EOK) {
if (handle != NULL)
*handle = -1;
211,7 → 226,7
return 0;
ipcarg_t count;
int retval = ipc_call_sync_0_1(phone, DEVMAP_DEVICE_GET_COUNT, &count);
int retval = async_req_0_1(phone, DEVMAP_DEVICE_GET_COUNT, &count);
if (retval != EOK)
return 0;
225,6 → 240,8
if (phone < 0)
return 0;
async_serialize_start();
ipc_call_t answer;
aid_t req = async_send_0(phone, DEVMAP_DEVICE_GET_DEVICES, &answer);
232,11 → 249,14
if (retval != EOK) {
async_wait_for(req, NULL);
async_serialize_end();
return 0;
}
async_wait_for(req, &retval);
async_serialize_end();
if (retval != EOK)
return 0;
/branches/dd/uspace/lib/libc/generic/async.c
95,8 → 95,8
#include <async.h>
#include <fibril.h>
#include <stdio.h>
#include <libadt/hash_table.h>
#include <libadt/list.h>
#include <adt/hash_table.h>
#include <adt/list.h>
#include <ipc/ipc.h>
#include <assert.h>
#include <errno.h>
174,10 → 174,11
} connection_t;
 
/** Identifier of the incoming connection handled by the current fibril. */
__thread connection_t *FIBRIL_connection;
fibril_local connection_t *FIBRIL_connection;
 
static void default_client_connection(ipc_callid_t callid, ipc_call_t *call);
static void default_interrupt_received(ipc_callid_t callid, ipc_call_t *call);
static void default_pending(void);
 
/**
* Pointer to a fibril function that will be used to handle connections.
190,11 → 191,15
*/
static async_client_conn_t interrupt_received = default_interrupt_received;
 
/**
* Pointer to a fibril function that will be used to handle pending
* operations.
*/
static async_pending_t pending = default_pending;
 
static hash_table_t conn_hash_table;
static LIST_INITIALIZE(timeout_list);
 
 
#define CONN_HASH_TABLE_CHAINS 32
 
/** Compute hash into the connection hash table based on the source phone hash.
376,6 → 381,42
return true;
}
 
/** Pending fibril.
*
* After each call the pending operations are executed in a separate
* fibril. The function pending() is c.
*
* @param arg Unused.
*
* @return Always zero.
*
*/
static int pending_fibril(void *arg)
{
pending();
return 0;
}
 
/** Process pending actions.
*
* A new fibril is created which would process the pending operations.
*
* @return False if an error occured.
* True if the execution was passed to the pending fibril.
*
*/
static bool process_pending(void)
{
futex_down(&async_futex);
fid_t fid = fibril_create(pending_fibril, NULL);
fibril_add_ready(fid);
futex_up(&async_futex);
return true;
}
 
/** Return new incoming message for the current (fibril-local) connection.
*
* @param call Storage where the incoming call data will be stored.
472,6 → 513,15
{
}
 
/** Default fibril function that gets called to handle pending operations.
*
* This function is defined as a weak symbol - to be redefined in user code.
*
*/
static void default_pending(void)
{
}
 
/** Wrapper for client connection fibril.
*
* When a new connection arrives, a fibril with this implementing function is
500,9 → 550,10
/* Answer all remaining messages with EHANGUP */
while (!list_empty(&FIBRIL_connection->msg_queue)) {
msg_t *msg
= list_get_instance(FIBRIL_connection->msg_queue.next, msg_t, link);
msg_t *msg;
msg = list_get_instance(FIBRIL_connection->msg_queue.next,
msg_t, link);
list_remove(&msg->link);
ipc_answer_0(msg->callid, EHANGUP);
free(msg);
563,7 → 614,7
}
/* Add connection to the connection hash table */
ipcarg_t key = conn->in_phone_hash;
unsigned long key = conn->in_phone_hash;
futex_down(&async_futex);
hash_table_insert(&conn_hash_table, &key, &conn->link);
588,7 → 639,7
/* Unrouted call - do some default behaviour */
if ((callid & IPC_CALLID_NOTIFICATION)) {
process_notification(callid, call);
return;
goto out;
}
switch (IPC_GET_METHOD(*call)) {
597,15 → 648,19
/* Open new connection with fibril etc. */
async_new_connection(IPC_GET_ARG5(*call), callid, call,
client_connection);
return;
goto out;
}
/* Try to route the call through the connection hash table */
if (route_call(callid, call))
return;
goto out;
/* Unknown call from unknown phone - hang it up */
ipc_answer_0(callid, EHANGUP);
return;
out:
process_pending();
}
 
/** Fire all timeouts that expired. */
663,8 → 718,8
suseconds_t timeout;
if (!list_empty(&timeout_list)) {
awaiter_t *waiter
= list_get_instance(timeout_list.next, awaiter_t, link);
awaiter_t *waiter = list_get_instance(timeout_list.next,
awaiter_t, link);
struct timeval tv;
gettimeofday(&tv, NULL);
681,8 → 736,8
futex_up(&async_futex);
ipc_call_t call;
ipc_callid_t callid
= ipc_wait_cycle(&call, timeout, SYNCH_FLAGS_NONE);
ipc_callid_t callid = ipc_wait_cycle(&call, timeout,
SYNCH_FLAGS_NONE);
if (!callid) {
handle_expired_timeouts();
759,13 → 814,13
*/
static void reply_received(void *arg, int retval, ipc_call_t *data)
{
futex_down(&async_futex);
amsg_t *msg = (amsg_t *) arg;
msg->retval = retval;
futex_down(&async_futex);
/* Copy data after futex_down, just in case the call was detached */
if (msg->dataptr)
if ((msg->dataptr) && (data))
*msg->dataptr = *data;
write_barrier();
994,6 → 1049,16
interrupt_received = intr;
}
 
/** Setter for pending function pointer.
*
* @param pend Function that will implement a new pending
* operations fibril.
*/
void async_set_pending(async_pending_t pend)
{
pending = pend;
}
 
/** Pseudo-synchronous message sending - fast version.
*
* Send message asynchronously and return only after the reply arrives.
/branches/dd/uspace/lib/libc/generic/vfs/vfs.c
49,12 → 49,13
#include <errno.h>
#include <string.h>
#include <devmap.h>
#include "../../../srv/vfs/vfs.h"
#include <ipc/vfs.h>
#include <ipc/devmap.h>
 
int vfs_phone = -1;
futex_t vfs_phone_futex = FUTEX_INITIALIZER;
static int vfs_phone = -1;
static futex_t vfs_phone_futex = FUTEX_INITIALIZER;
static futex_t cwd_futex = FUTEX_INITIALIZER;
 
futex_t cwd_futex = FUTEX_INITIALIZER;
DIR *cwd_dir = NULL;
char *cwd_path = NULL;
size_t cwd_size = 0;
210,9 → 211,10
async_serialize_end();
futex_up(&vfs_phone_futex);
free(pa);
 
if (rc != EOK)
return (int) rc;
return (int) IPC_GET_ARG1(answer);
}
 
221,6 → 223,27
return _open(path, L_FILE, oflag);
}
 
int open_node(fdi_node_t *node, int oflag)
{
futex_down(&vfs_phone_futex);
async_serialize_start();
vfs_connect();
ipc_call_t answer;
aid_t req = async_send_4(vfs_phone, VFS_OPEN_NODE, node->fs_handle,
node->dev_handle, node->index, oflag, &answer);
ipcarg_t rc;
async_wait_for(req, &rc);
async_serialize_end();
futex_up(&vfs_phone_futex);
if (rc != EOK)
return (int) rc;
return (int) IPC_GET_ARG1(answer);
}
 
int close(int fildes)
{
ipcarg_t rc;
291,6 → 314,62
return -1;
}
 
int fd_phone(int fildes)
{
futex_down(&vfs_phone_futex);
async_serialize_start();
vfs_connect();
ipcarg_t device;
ipcarg_t rc = async_req_1_1(vfs_phone, VFS_DEVICE, fildes, &device);
async_serialize_end();
futex_up(&vfs_phone_futex);
if (rc != EOK)
return -1;
return devmap_device_connect((dev_handle_t) device, 0);
}
 
int fd_node(int fildes, fdi_node_t *node)
{
futex_down(&vfs_phone_futex);
async_serialize_start();
vfs_connect();
ipcarg_t fs_handle;
ipcarg_t dev_handle;
ipcarg_t index;
ipcarg_t rc = async_req_1_3(vfs_phone, VFS_NODE, fildes, &fs_handle,
&dev_handle, &index);
async_serialize_end();
futex_up(&vfs_phone_futex);
if (rc == EOK) {
node->fs_handle = (fs_handle_t) fs_handle;
node->dev_handle = (dev_handle_t) dev_handle;
node->index = (fs_index_t) index;
}
return rc;
}
 
int fsync(int fildes)
{
futex_down(&vfs_phone_futex);
async_serialize_start();
vfs_connect();
ipcarg_t rc = async_req_1_0(vfs_phone, VFS_SYNC, fildes);
async_serialize_end();
futex_up(&vfs_phone_futex);
return (int) rc;
}
 
off_t lseek(int fildes, off_t offset, int whence)
{
ipcarg_t rc;
386,7 → 465,7
async_serialize_end();
futex_up(&vfs_phone_futex);
free(pa);
return rc;
return rc;
}
 
static int _unlink(const char *path, int lflag)
416,7 → 495,7
async_serialize_end();
futex_up(&vfs_phone_futex);
free(pa);
return rc;
return rc;
}
 
int unlink(const char *path)
/branches/dd/uspace/lib/libc/generic/mem.c
95,7 → 95,7
 
static void *unaligned_memcpy(void *dst, const void *src, size_t n)
{
int i, j;
size_t i, j;
struct along *adst = dst;
const struct along *asrc = src;
 
/branches/dd/uspace/lib/libc/generic/io/sprintf.c
File deleted
/branches/dd/uspace/lib/libc/generic/io/vsprintf.c
File deleted
/branches/dd/uspace/lib/libc/generic/io/fprintf.c
File deleted
/branches/dd/uspace/lib/libc/generic/io/stream.c
File deleted
/branches/dd/uspace/lib/libc/generic/io/stdio.c
File deleted
/branches/dd/uspace/lib/libc/generic/io/printf.c
34,23 → 34,43
 
#include <io/printf_core.h>
#include <stdio.h>
#include <stdio.h>
 
/** Print formatted text.
* @param fmt format string
*
* @param stream Output stream
* @param fmt Format string
*
* \see For more details about format string see printf_core.
*
*/
int fprintf(FILE *stream, const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
int ret = vfprintf(stream, fmt, args);
va_end(args);
return ret;
}
 
/** Print formatted text to stdout.
*
* @param fmt Format string
*
* \see For more details about format string see printf_core.
*
*/
int printf(const char *fmt, ...)
{
int ret;
va_list args;
 
va_start(args, fmt);
 
ret = vprintf(fmt, args);
int ret = vprintf(fmt, args);
va_end(args);
 
return ret;
}
 
/branches/dd/uspace/lib/libc/generic/io/console.c
0,0 → 1,102
/*
* Copyright (c) 2006 Josef Cejka
* Copyright (c) 2006 Jakub Vana
* Copyright (c) 2008 Jiri Svoboda
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup libc
* @{
*/
/** @file
*/
 
#include <libc.h>
#include <async.h>
#include <io/console.h>
#include <ipc/console.h>
 
void console_clear(int phone)
{
async_msg_0(phone, CONSOLE_CLEAR);
}
 
int console_get_size(int phone, ipcarg_t *rows, ipcarg_t *cols)
{
return async_req_0_2(phone, CONSOLE_GET_SIZE, rows, cols);
}
 
void console_set_style(int phone, int style)
{
async_msg_1(phone, CONSOLE_SET_STYLE, style);
}
 
void console_set_color(int phone, int fg_color, int bg_color, int flags)
{
async_msg_3(phone, CONSOLE_SET_COLOR, fg_color, bg_color, flags);
}
 
void console_set_rgb_color(int phone, int fg_color, int bg_color)
{
async_msg_2(phone, CONSOLE_SET_RGB_COLOR, fg_color, bg_color);
}
 
void console_cursor_visibility(int phone, bool show)
{
async_msg_1(phone, CONSOLE_CURSOR_VISIBILITY, show != false);
}
 
void console_kcon_enable(int phone)
{
async_msg_0(phone, CONSOLE_KCON_ENABLE);
}
 
void console_goto(int phone, ipcarg_t row, ipcarg_t col)
{
async_msg_2(phone, CONSOLE_GOTO, row, col);
}
 
bool console_get_event(int phone, console_event_t *event)
{
ipcarg_t type;
ipcarg_t key;
ipcarg_t mods;
ipcarg_t c;
int rc = async_req_0_4(phone, CONSOLE_GET_EVENT, &type, &key, &mods, &c);
if (rc < 0)
return false;
event->type = type;
event->key = key;
event->mods = mods;
event->c = c;
return true;
}
 
/** @}
*/
/branches/dd/uspace/lib/libc/generic/io/snprintf.c
37,21 → 37,23
#include <io/printf_core.h>
 
/** Print formatted to the given buffer with limited size.
* @param str buffer
* @param size buffer size
* @param fmt format string
*
* @param str Buffer
* @param size Buffer size
* @param fmt Format string
*
* \see For more details about format string see printf_core.
*
*/
int snprintf(char *str, size_t size, const char *fmt, ...)
{
int ret;
va_list args;
va_start(args, fmt);
va_start(args, fmt);
ret = vsnprintf(str, size, fmt, args);
 
int ret = vsnprintf(str, size, fmt, args);
va_end(args);
 
return ret;
}
 
/branches/dd/uspace/lib/libc/generic/io/asprintf.c
36,42 → 36,52
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <io/printf_core.h>
 
static int asprintf_prewrite(const char *str, size_t count, void *unused)
static int asprintf_str_write(const char *str, size_t count, void *unused)
{
return count;
return str_nlength(str, count);
}
 
static int asprintf_wstr_write(const wchar_t *str, size_t count, void *unused)
{
return wstr_nlength(str, count);
}
 
/** Allocate and print to string.
*
* @param strp Address of the pointer where to store the address of
* the newly allocated string.
* @fmt Format strin.
* @param strp Address of the pointer where to store the address of
* the newly allocated string.
* @fmt Format string.
*
* @return Number of characters printed or a negative error code.
* @return Number of characters printed or a negative error code.
*
*/
int asprintf(char **strp, const char *fmt, ...)
{
struct printf_spec ps = {
asprintf_prewrite,
NULL
asprintf_str_write,
asprintf_wstr_write,
NULL
};
int ret;
va_list args;
 
va_start(args, fmt);
ret = printf_core(fmt, &ps, args);
int ret = printf_core(fmt, &ps, args);
va_end(args);
if (ret > 0) {
*strp = malloc(ret + 20);
if (!*strp)
*strp = malloc(STR_BOUNDS(ret) + 1);
if (*strp == NULL)
return -1;
va_start(args, fmt);
vsprintf(*strp, fmt, args);
va_end(args);
vsnprintf(*strp, STR_BOUNDS(ret) + 1, fmt, args);
va_end(args);
}
 
return ret;
}
 
/branches/dd/uspace/lib/libc/generic/io/io.c
30,98 → 30,421
* @{
*/
/** @file
*/
*/
 
#include <libc.h>
#include <stdio.h>
#include <unistd.h>
#include <stdio.h>
#include <io/io.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <console.h>
#include <bool.h>
#include <malloc.h>
#include <io/klog.h>
#include <vfs/vfs.h>
#include <ipc/devmap.h>
#include <adt/list.h>
 
const static char nl = '\n';
static FILE stdin_null = {
.fd = -1,
.error = true,
.eof = true,
.klog = false,
.phone = -1
};
 
int puts(const char *str)
static FILE stdout_klog = {
.fd = -1,
.error = false,
.eof = false,
.klog = true,
.phone = -1
};
 
static FILE stderr_klog = {
.fd = -1,
.error = false,
.eof = false,
.klog = true,
.phone = -1
};
 
FILE *stdin = NULL;
FILE *stdout = NULL;
FILE *stderr = NULL;
 
static LIST_INITIALIZE(files);
 
void stdio_init(int filc, fdi_node_t *filv[])
{
size_t count;
if (filc > 0) {
stdin = fopen_node(filv[0], "r");
} else {
stdin = &stdin_null;
list_append(&stdin->link, &files);
}
if (str == NULL)
return putnchars("(NULL)", 6);
if (filc > 1) {
stdout = fopen_node(filv[1], "w");
} else {
stdout = &stdout_klog;
list_append(&stdout->link, &files);
}
for (count = 0; str[count] != 0; count++);
if (filc > 2) {
stderr = fopen_node(filv[2], "w");
} else {
stderr = &stderr_klog;
list_append(&stderr->link, &files);
}
}
 
void stdio_done(void)
{
link_t *link = files.next;
if (console_write((void *) str, count) == count) {
if (console_write(&nl, 1) == 1)
return 0;
while (link != &files) {
FILE *file = list_get_instance(link, FILE, link);
fclose(file);
link = files.next;
}
}
 
static bool parse_mode(const char *mode, int *flags)
{
/* Parse mode except first character. */
const char *mp = mode;
if (*mp++ == 0) {
errno = EINVAL;
return false;
}
return EOF;
if ((*mp == 'b') || (*mp == 't'))
mp++;
bool plus;
if (*mp == '+') {
mp++;
plus = true;
} else
plus = false;
if (*mp != 0) {
errno = EINVAL;
return false;
}
/* Parse first character of mode and determine flags for open(). */
switch (mode[0]) {
case 'r':
*flags = plus ? O_RDWR : O_RDONLY;
break;
case 'w':
*flags = (O_TRUNC | O_CREAT) | (plus ? O_RDWR : O_WRONLY);
break;
case 'a':
/* TODO: a+ must read from beginning, append to the end. */
if (plus) {
errno = ENOTSUP;
return false;
}
*flags = (O_APPEND | O_CREAT) | (plus ? O_RDWR : O_WRONLY);
default:
errno = EINVAL;
return false;
}
return true;
}
 
/** Put count chars from buffer to stdout without adding newline
* @param buf Buffer with size at least count bytes - NULL pointer NOT allowed!
* @param count
* @return 0 on succes, EOF on fail
/** Open a stream.
*
* @param path Path of the file to open.
* @param mode Mode string, (r|w|a)[b|t][+].
*
*/
int putnchars(const char *buf, size_t count)
FILE *fopen(const char *path, const char *mode)
{
if (console_write((void *) buf, count) == count)
return 0;
int flags;
if (!parse_mode(mode, &flags))
return NULL;
return EOF;
/* Open file. */
FILE *stream = malloc(sizeof(FILE));
if (stream == NULL) {
errno = ENOMEM;
return NULL;
}
stream->fd = open(path, flags, 0666);
if (stream->fd < 0) {
/* errno was set by open() */
free(stream);
return NULL;
}
stream->error = false;
stream->eof = false;
stream->klog = false;
stream->phone = -1;
list_append(&stream->link, &files);
return stream;
}
 
/** Same as puts, but does not print newline at end
FILE *fdopen(int fd, const char *mode)
{
/* Open file. */
FILE *stream = malloc(sizeof(FILE));
if (stream == NULL) {
errno = ENOMEM;
return NULL;
}
stream->fd = fd;
stream->error = false;
stream->eof = false;
stream->klog = false;
stream->phone = -1;
list_append(&stream->link, &files);
return stream;
}
 
FILE *fopen_node(fdi_node_t *node, const char *mode)
{
int flags;
if (!parse_mode(mode, &flags))
return NULL;
/* Open file. */
FILE *stream = malloc(sizeof(FILE));
if (stream == NULL) {
errno = ENOMEM;
return NULL;
}
stream->fd = open_node(node, flags);
if (stream->fd < 0) {
/* errno was set by open_node() */
free(stream);
return NULL;
}
stream->error = false;
stream->eof = false;
stream->klog = false;
stream->phone = -1;
list_append(&stream->link, &files);
return stream;
}
 
int fclose(FILE *stream)
{
int rc = 0;
fflush(stream);
if (stream->phone >= 0)
ipc_hangup(stream->phone);
if (stream->fd >= 0)
rc = close(stream->fd);
list_remove(&stream->link);
if ((stream != &stdin_null)
&& (stream != &stdout_klog)
&& (stream != &stderr_klog))
free(stream);
stream = NULL;
if (rc != 0) {
/* errno was set by close() */
return EOF;
}
return 0;
}
 
/** Read from a stream.
*
* @param buf Destination buffer.
* @param size Size of each record.
* @param nmemb Number of records to read.
* @param stream Pointer to the stream.
*
*/
int putstr(const char *str)
size_t fread(void *buf, size_t size, size_t nmemb, FILE *stream)
{
size_t count;
size_t left = size * nmemb;
size_t done = 0;
if (str == NULL)
return putnchars("(NULL)", 6);
while ((left > 0) && (!stream->error) && (!stream->eof)) {
ssize_t rd = read(stream->fd, buf + done, left);
if (rd < 0)
stream->error = true;
else if (rd == 0)
stream->eof = true;
else {
left -= rd;
done += rd;
}
}
return (done / size);
}
 
for (count = 0; str[count] != 0; count++);
if (console_write((void *) str, count) == count)
return 0;
/** Write to a stream.
*
* @param buf Source buffer.
* @param size Size of each record.
* @param nmemb Number of records to write.
* @param stream Pointer to the stream.
*
*/
size_t fwrite(const void *buf, size_t size, size_t nmemb, FILE *stream)
{
size_t left = size * nmemb;
size_t done = 0;
return EOF;
while ((left > 0) && (!stream->error)) {
ssize_t wr;
if (stream->klog)
wr = klog_write(buf + done, left);
else
wr = write(stream->fd, buf + done, left);
if (wr <= 0)
stream->error = true;
else {
left -= wr;
done += wr;
}
}
return (done / size);
}
 
int putchar(int c)
int fputc(wchar_t c, FILE *stream)
{
char buf[STR_BOUNDS(1)];
size_t offs;
size_t sz = 0;
if (chr_encode(c, buf, &sz, STR_BOUNDS(1)) == EOK) {
size_t wr = fwrite(buf, sz, 1, stream);
if (wr < sz)
return EOF;
return (int) c;
}
return EOF;
}
 
offs = 0;
if (chr_encode(c, buf, &offs, STR_BOUNDS(1)) != EOK)
return EOF;
int putchar(wchar_t c)
{
return fputc(c, stdout);
}
 
if (console_write((void *) buf, offs) == offs)
return c;
int fputs(const char *str, FILE *stream)
{
return fwrite(str, str_size(str), 1, stream);
}
 
return EOF;
int puts(const char *str)
{
return fputs(str, stdout);
}
 
int fgetc(FILE *stream)
{
char c;
 
/* This could be made faster by only flushing when needed. */
if (stdout)
fflush(stdout);
if (stderr)
fflush(stderr);
 
if (fread(&c, sizeof(char), 1, stream) < sizeof(char))
return EOF;
return (int) c;
}
 
int getchar(void)
{
unsigned char c;
return fgetc(stdin);
}
 
int fseek(FILE *stream, long offset, int origin)
{
off_t rc = lseek(stream->fd, offset, origin);
if (rc == (off_t) (-1)) {
/* errno has been set by lseek. */
return -1;
}
console_flush();
if (read_stdin((void *) &c, 1) == 1)
return c;
stream->eof = false;
return EOF;
return 0;
}
 
int fflush(FILE *f)
void rewind(FILE *stream)
{
/* Dummy implementation */
(void) f;
console_flush();
return 0;
(void) fseek(stream, 0, SEEK_SET);
}
 
int fflush(FILE *stream)
{
if (stream->klog) {
klog_update();
return EOK;
}
if (stream->fd >= 0)
return fsync(stream->fd);
return ENOENT;
}
 
int feof(FILE *stream)
{
return stream->eof;
}
 
int ferror(FILE *stream)
{
return stream->error;
}
 
int fphone(FILE *stream)
{
if (stream->fd >= 0) {
if (stream->phone < 0)
stream->phone = fd_phone(stream->fd);
return stream->phone;
}
return -1;
}
 
int fnode(FILE *stream, fdi_node_t *node)
{
if (stream->fd >= 0)
return fd_node(stream->fd, node);
return ENOENT;
}
 
/** @}
*/
/branches/dd/uspace/lib/libc/generic/io/vprintf.c
38,37 → 38,25
#include <io/printf_core.h>
#include <futex.h>
#include <async.h>
#include <console.h>
#include <string.h>
 
static atomic_t printf_futex = FUTEX_INITIALIZER;
 
static int vprintf_str_write(const char *str, size_t size, void *data)
static int vprintf_str_write(const char *str, size_t size, void *stream)
{
size_t offset = 0;
size_t prev;
count_t chars = 0;
while (offset < size) {
prev = offset;
str_decode(str, &offset, size);
console_write(str + prev, offset - prev);
chars++;
}
return chars;
size_t wr = fwrite(str, 1, size, (FILE *) stream);
return str_nlength(str, wr);
}
 
static int vprintf_wstr_write(const wchar_t *str, size_t size, void *data)
static int vprintf_wstr_write(const wchar_t *str, size_t size, void *stream)
{
size_t offset = 0;
size_t boff;
count_t chars = 0;
char buf[4];
size_t chars = 0;
while (offset < size) {
boff = 0;
chr_encode(str[chars], buf, &boff, 4);
console_write(buf, boff);
if (fputc(str[chars], (FILE *) stream) <= 0)
break;
chars++;
offset += sizeof(wchar_t);
}
76,33 → 64,55
return chars;
}
 
 
/** Print formatted text.
* @param fmt format string
* @param ap format parameters
*
* @param stream Output stream
* @param fmt Format string
* @param ap Format parameters
*
* \see For more details about format string see printf_core.
*
*/
int vprintf(const char *fmt, va_list ap)
int vfprintf(FILE *stream, const char *fmt, va_list ap)
{
struct printf_spec ps = {
vprintf_str_write,
vprintf_wstr_write,
NULL
stream
};
/*
* Prevent other threads to execute printf_core()
*/
futex_down(&printf_futex);
/*
* Prevent other pseudo threads of the same thread
* Prevent other fibrils of the same thread
* to execute printf_core()
*/
async_serialize_start();
int ret = printf_core(fmt, &ps, ap);
async_serialize_end();
futex_up(&printf_futex);
return ret;
}
 
/** Print formatted text to stdout.
*
* @param file Output stream
* @param fmt Format string
* @param ap Format parameters
*
* \see For more details about format string see printf_core.
*
*/
int vprintf(const char *fmt, va_list ap)
{
return vfprintf(stdout, fmt, ap);
}
 
/** @}
*/
/branches/dd/uspace/lib/libc/generic/io/vsnprintf.c
82,7 → 82,7
* with the trailing zero => print only a part
* of string
*/
index_t index = 0;
size_t index = 0;
while (index < size) {
wchar_t uc = str_decode(str, &index, size);
130,7 → 130,7
*/
static int vsnprintf_wstr_write(const wchar_t *str, size_t size, vsnprintf_data_t *data)
{
index_t index = 0;
size_t index = 0;
while (index < (size / sizeof(wchar_t))) {
size_t left = data->size - data->len;
/branches/dd/uspace/lib/libc/generic/io/printf_core.c
173,7 → 173,7
*/
static int print_char(const char ch, int width, uint32_t flags, printf_spec_t *ps)
{
count_t counter = 0;
size_t counter = 0;
if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
while (--width > 0) {
/*
211,7 → 211,7
*/
static int print_wchar(const wchar_t ch, int width, uint32_t flags, printf_spec_t *ps)
{
count_t counter = 0;
size_t counter = 0;
if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
while (--width > 0) {
/*
254,12 → 254,12
return printf_putstr(nullstr, ps);
 
/* Print leading spaces. */
count_t strw = str_length(str);
size_t strw = str_length(str);
if (precision == 0)
precision = strw;
 
/* Left padding */
count_t counter = 0;
size_t counter = 0;
width -= precision;
if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
while (width-- > 0) {
310,7 → 310,7
precision = strw;
/* Left padding */
count_t counter = 0;
size_t counter = 0;
width -= precision;
if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
while (width-- > 0) {
432,7 → 432,7
}
width -= precision + size - number_size;
count_t counter = 0;
size_t counter = 0;
if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
while (width-- > 0) {
595,7 → 595,7
size_t nxt = 0; /* Index of the next character from fmt */
size_t j = 0; /* Index to the first not printed nonformating character */
count_t counter = 0; /* Number of characters printed */
size_t counter = 0; /* Number of characters printed */
int retval; /* Return values from nested functions */
while (true) {
/branches/dd/uspace/lib/libc/generic/io/klog.c
0,0 → 1,53
/*
* Copyright (c) 2006 Josef Cejka
* Copyright (c) 2006 Jakub Vana
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup libc
* @{
*/
/** @file
*/
 
#include <libc.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <io/klog.h>
 
size_t klog_write(const void *buf, size_t size)
{
return (size_t) __SYSCALL3(SYS_KLOG, 1, (sysarg_t) buf, size);
}
 
void klog_update(void)
{
(void) __SYSCALL3(SYS_KLOG, 1, NULL, 0);
}
 
/** @}
*/
/branches/dd/uspace/lib/libc/generic/adt/hash_table.c
0,0 → 1,196
/*
* Copyright (c) 2008 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup libc
* @{
*/
/** @file
*/
 
/*
* This is an implementation of generic chained hash table.
*/
 
#include <adt/hash_table.h>
#include <adt/list.h>
#include <unistd.h>
#include <malloc.h>
#include <assert.h>
#include <stdio.h>
#include <string.h>
 
/** Create chained hash table.
*
* @param h Hash table structure. Will be initialized by this call.
* @param m Number of hash table buckets.
* @param max_keys Maximal number of keys needed to identify an item.
* @param op Hash table operations structure.
* @return True on success
*/
int hash_table_create(hash_table_t *h, hash_count_t m, hash_count_t max_keys,
hash_table_operations_t *op)
{
hash_count_t i;
 
assert(h);
assert(op && op->hash && op->compare);
assert(max_keys > 0);
h->entry = malloc(m * sizeof(link_t));
if (!h->entry) {
printf("cannot allocate memory for hash table\n");
return false;
}
memset((void *) h->entry, 0, m * sizeof(link_t));
for (i = 0; i < m; i++)
list_initialize(&h->entry[i]);
h->entries = m;
h->max_keys = max_keys;
h->op = op;
return true;
}
 
/** Destroy a hash table instance.
*
* @param h Hash table to be destroyed.
*/
void hash_table_destroy(hash_table_t *h)
{
assert(h);
assert(h->entry);
free(h->entry);
}
 
/** Insert item into a hash table.
*
* @param h Hash table.
* @param key Array of all keys necessary to compute hash index.
* @param item Item to be inserted into the hash table.
*/
void hash_table_insert(hash_table_t *h, unsigned long key[], link_t *item)
{
hash_index_t chain;
 
assert(item);
assert(h && h->op && h->op->hash && h->op->compare);
 
chain = h->op->hash(key);
assert(chain < h->entries);
list_append(item, &h->entry[chain]);
}
 
/** Search hash table for an item matching keys.
*
* @param h Hash table.
* @param key Array of all keys needed to compute hash index.
*
* @return Matching item on success, NULL if there is no such item.
*/
link_t *hash_table_find(hash_table_t *h, unsigned long key[])
{
link_t *cur;
hash_index_t chain;
 
assert(h && h->op && h->op->hash && h->op->compare);
 
chain = h->op->hash(key);
assert(chain < h->entries);
for (cur = h->entry[chain].next; cur != &h->entry[chain];
cur = cur->next) {
if (h->op->compare(key, h->max_keys, cur)) {
/*
* The entry is there.
*/
return cur;
}
}
return NULL;
}
 
/** Remove all matching items from hash table.
*
* For each removed item, h->remove_callback() is called.
*
* @param h Hash table.
* @param key Array of keys that will be compared against items of
* the hash table.
* @param keys Number of keys in the 'key' array.
*/
void hash_table_remove(hash_table_t *h, unsigned long key[], hash_count_t keys)
{
hash_index_t chain;
link_t *cur;
 
assert(h && h->op && h->op->hash && h->op->compare &&
h->op->remove_callback);
assert(keys <= h->max_keys);
if (keys == h->max_keys) {
 
/*
* All keys are known, hash_table_find() can be used to find the
* entry.
*/
cur = hash_table_find(h, key);
if (cur) {
list_remove(cur);
h->op->remove_callback(cur);
}
return;
}
/*
* Fewer keys were passed.
* Any partially matching entries are to be removed.
*/
for (chain = 0; chain < h->entries; chain++) {
for (cur = h->entry[chain].next; cur != &h->entry[chain];
cur = cur->next) {
if (h->op->compare(key, keys, cur)) {
link_t *hlp;
hlp = cur;
cur = cur->prev;
list_remove(hlp);
h->op->remove_callback(hlp);
continue;
}
}
}
}
 
/** @}
*/
/branches/dd/uspace/lib/libc/generic/adt/list.c
0,0 → 1,112
/*
* Copyright (c) 2004 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup libc
* @{
*/
/** @file
*/
 
#include <adt/list.h>
 
 
/** Check for membership
*
* Check whether link is contained in the list head.
* The membership is defined as pointer equivalence.
*
* @param link Item to look for.
* @param head List to look in.
*
* @return true if link is contained in head, false otherwise.
*
*/
int list_member(const link_t *link, const link_t *head)
{
int found = 0;
link_t *hlp = head->next;
while (hlp != head) {
if (hlp == link) {
found = 1;
break;
}
hlp = hlp->next;
}
return found;
}
 
 
/** Concatenate two lists
*
* Concatenate lists head1 and head2, producing a single
* list head1 containing items from both (in head1, head2
* order) and empty list head2.
*
* @param head1 First list and concatenated output
* @param head2 Second list and empty output.
*
*/
void list_concat(link_t *head1, link_t *head2)
{
if (list_empty(head2))
return;
head2->next->prev = head1->prev;
head2->prev->next = head1;
head1->prev->next = head2->next;
head1->prev = head2->prev;
list_initialize(head2);
}
 
 
/** Count list items
*
* Return the number of items in the list.
*
* @param link List to count.
*
* @return Number of items in the list.
*
*/
unsigned int list_count(const link_t *link)
{
unsigned int count = 0;
link_t *hlp = link->next;
while (hlp != link) {
count++;
hlp = hlp->next;
}
return count;
}
 
/** @}
*/
/branches/dd/uspace/lib/libc/Makefile
46,12 → 46,12
generic/ddi.c \
generic/as.c \
generic/cap.c \
generic/console.c \
generic/devmap.c \
generic/event.c \
generic/mem.c \
generic/string.c \
generic/fibril.c \
generic/fibril_sync.c \
generic/pcb.c \
generic/smc.c \
generic/thread.c \
61,15 → 61,12
generic/io/asprintf.c \
generic/io/io.c \
generic/io/printf.c \
generic/io/fprintf.c \
generic/io/stdio.c \
generic/io/stream.c \
generic/io/sprintf.c \
generic/io/klog.c \
generic/io/snprintf.c \
generic/io/vprintf.c \
generic/io/vsprintf.c \
generic/io/vsnprintf.c \
generic/io/printf_core.c \
generic/io/console.c \
malloc/malloc.c \
generic/sysinfo.c \
generic/ipc.c \
76,12 → 73,11
generic/async.c \
generic/loader.c \
generic/getopt.c \
generic/libadt/list.o \
generic/libadt/hash_table.o \
generic/adt/list.o \
generic/adt/hash_table.o \
generic/time.c \
generic/err.c \
generic/stdlib.c \
generic/kbd.c \
generic/mman.c \
generic/udebug.c \
generic/vfs/vfs.c \
/branches/dd/uspace/lib/libc/arch/sparc64/include/types.h
49,8 → 49,6
 
typedef int64_t ssize_t;
typedef uint64_t size_t;
typedef uint64_t count_t;
typedef uint64_t index_t;
 
typedef uint64_t uintptr_t;
 
/branches/dd/uspace/lib/libc/arch/ia64/include/types.h
49,8 → 49,6
 
typedef int64_t ssize_t;
typedef uint64_t size_t;
typedef uint64_t count_t;
typedef uint64_t index_t;
 
typedef uint64_t uintptr_t;
 
/branches/dd/uspace/lib/libc/arch/arm32/include/tls.h
40,7 → 40,7
 
#define CONFIG_TLS_VARIANT_1
 
/** Offsets for accessing __thread variables are shifted 8 bytes higher. */
/** Offsets for accessing thread-local variables are shifted 8 bytes higher. */
#define ARM_TP_OFFSET (-8)
 
/** TCB (Thread Control Block) struct.
/branches/dd/uspace/lib/libc/arch/arm32/include/types.h
50,8 → 50,6
 
typedef int32_t ssize_t;
typedef uint32_t size_t;
typedef uint32_t count_t;
typedef uint32_t index_t;
 
typedef uint32_t uintptr_t;
 
/branches/dd/uspace/lib/libc/arch/arm32/include/fibril.h
38,7 → 38,7
 
#include <sys/types.h>
#include <align.h>
#include "thread.h"
#include <thread.h>
 
/** Size of a stack item */
#define STACK_ITEM_SIZE 4
/branches/dd/uspace/lib/libc/arch/ppc32/include/types.h
49,8 → 49,6
 
typedef int32_t ssize_t;
typedef uint32_t size_t;
typedef uint32_t count_t;
typedef uint32_t index_t;
 
typedef uint32_t uintptr_t;
 
/branches/dd/uspace/lib/libc/arch/amd64/include/types.h
49,8 → 49,6
 
typedef int64_t ssize_t;
typedef uint64_t size_t;
typedef uint64_t count_t;
typedef uint64_t index_t;
 
typedef uint64_t uintptr_t;
 
/branches/dd/uspace/lib/libc/arch/mips32/include/types.h
50,8 → 50,6
 
typedef int32_t ssize_t;
typedef uint32_t size_t;
typedef uint32_t count_t;
typedef uint32_t index_t;
 
typedef uint32_t uintptr_t;
 
/branches/dd/uspace/lib/libc/arch/ia32/include/types.h
49,8 → 49,6
 
typedef int32_t ssize_t;
typedef uint32_t size_t;
typedef uint32_t count_t;
typedef uint32_t index_t;
 
typedef uint32_t uintptr_t;
 
/branches/dd/uspace/srv/fhc/fhc.c
File deleted
/branches/dd/uspace/srv/fhc/Makefile
File deleted
/branches/dd/uspace/srv/obio/obio.c
File deleted
/branches/dd/uspace/srv/obio/Makefile
File deleted
/branches/dd/uspace/srv/kbd/ctl/pc.c
32,12 → 32,12
*/
/**
* @file
* @brief PC keyboard controller driver.
* @brief PC keyboard controller driver.
*/
 
#include <kbd.h>
#include <kbd/kbd.h>
#include <kbd/keycode.h>
#include <io/console.h>
#include <io/keycode.h>
#include <kbd_ctl.h>
#include <gsp.h>
 
188,7 → 188,7
 
void kbd_ctl_parse_scancode(int scancode)
{
kbd_ev_type_t type;
console_ev_type_t type;
unsigned int key;
int *map;
size_t map_length;
213,9 → 213,9
 
if (scancode & 0x80) {
scancode &= ~0x80;
type = KE_RELEASE;
type = KEY_RELEASE;
} else {
type = KE_PRESS;
type = KEY_PRESS;
}
 
if (scancode < 0 || scancode >= map_length)
/branches/dd/uspace/srv/kbd/ctl/stty.c
36,8 → 36,7
*/
 
#include <kbd.h>
#include <kbd/kbd.h>
#include <kbd/keycode.h>
#include <io/keycode.h>
#include <kbd_ctl.h>
#include <gsp.h>
#include <stroke.h>
/branches/dd/uspace/srv/kbd/ctl/sun.c
36,8 → 36,8
*/
 
#include <kbd.h>
#include <kbd/kbd.h>
#include <kbd/keycode.h>
#include <io/console.h>
#include <io/keycode.h>
#include <kbd_ctl.h>
 
#define KBD_KEY_RELEASE 0x80
52,7 → 52,7
 
void kbd_ctl_parse_scancode(int scancode)
{
kbd_ev_type_t type;
console_ev_type_t type;
unsigned int key;
 
if (scancode < 0 || scancode >= 0x100)
63,9 → 63,9
 
if (scancode & KBD_KEY_RELEASE) {
scancode &= ~KBD_KEY_RELEASE;
type = KE_RELEASE;
type = KEY_RELEASE;
} else {
type = KE_PRESS;
type = KEY_PRESS;
}
 
key = scanmap_simple[scancode];
/branches/dd/uspace/srv/kbd/ctl/gxe_fb.c
36,8 → 36,8
*/
 
#include <kbd.h>
#include <kbd/kbd.h>
#include <kbd/keycode.h>
#include <io/console.h>
#include <io/keycode.h>
#include <kbd_ctl.h>
#include <gsp.h>
#include <stroke.h>
/branches/dd/uspace/srv/kbd/include/key_buffer.h
File deleted
/branches/dd/uspace/srv/kbd/include/gsp.h
37,7 → 37,7
#ifndef KBD_GSP_H_
#define KBD_GSP_H_
 
#include <libadt/hash_table.h>
#include <adt/hash_table.h>
 
enum {
GSP_END = -1, /**< Terminates a sequence. */
/branches/dd/uspace/srv/kbd/include/layout.h
27,10 → 27,10
*/
 
/** @addtogroup kbdgen generic
* @brief HelenOS generic uspace keyboard handler.
* @ingroup kbd
* @brief HelenOS generic uspace keyboard handler.
* @ingroup kbd
* @{
*/
*/
/** @file
*/
 
37,12 → 37,12
#ifndef KBD_LAYOUT_H_
#define KBD_LAYOUT_H_
 
#include <kbd/kbd.h>
#include <sys/types.h>
#include <io/console.h>
 
typedef struct {
void (*reset)(void);
wchar_t (*parse_ev)(kbd_event_t *);
wchar_t (*parse_ev)(console_event_t *);
} layout_op_t;
 
extern layout_op_t us_qwerty_op;
53,5 → 53,4
 
/**
* @}
*/
 
*/
/branches/dd/uspace/srv/kbd/include/kbd.h
27,10 → 27,10
*/
 
/** @addtogroup kbdgen generic
* @brief HelenOS generic uspace keyboard handler.
* @ingroup kbd
* @brief HelenOS generic uspace keyboard handler.
* @ingroup kbd
* @{
*/
*/
/** @file
*/
 
37,17 → 37,17
#ifndef KBD_KBD_H_
#define KBD_KBD_H_
 
#include <key_buffer.h>
#include <keybuffer.h>
#include <ipc/ipc.h>
 
#define KBD_EVENT 1024
#define KBD_MS_LEFT 1025
#define KBD_MS_RIGHT 1026
#define KBD_MS_MIDDLE 1027
#define KBD_MS_MOVE 1028
#define KBD_EVENT 1024
#define KBD_MS_LEFT 1025
#define KBD_MS_RIGHT 1026
#define KBD_MS_MIDDLE 1027
#define KBD_MS_MOVE 1028
 
typedef enum {
KBD_YIELD = IPC_FIRST_USER_METHOD,
KBD_YIELD = IPC_FIRST_USER_METHOD,
KBD_RECLAIM
} kbd_request_t;
 
61,5 → 61,4
 
/**
* @}
*/
 
*/
/branches/dd/uspace/srv/kbd/include/keybuffer.h
0,0 → 1,65
/*
* Copyright (c) 2006 Josef Cejka
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup kbdgen
* @brief HelenOS generic uspace keyboard handler.
* @ingroup kbd
* @{
*/
/** @file
*/
 
#ifndef __KEYBUFFER_H__
#define __KEYBUFFER_H__
 
#include <sys/types.h>
#include <io/console.h>
#include <bool.h>
 
/** Size of buffer for pressed keys */
#define KEYBUFFER_SIZE 128
 
typedef struct {
console_event_t fifo[KEYBUFFER_SIZE];
unsigned long head;
unsigned long tail;
unsigned long items;
} keybuffer_t;
 
extern void keybuffer_free(keybuffer_t *);
extern void keybuffer_init(keybuffer_t *);
extern size_t keybuffer_available(keybuffer_t *);
extern bool keybuffer_empty(keybuffer_t *);
extern void keybuffer_push(keybuffer_t *, const console_event_t *);
extern bool keybuffer_pop(keybuffer_t *, console_event_t *);
 
#endif
 
/**
* @}
*/
/branches/dd/uspace/srv/kbd/genarch/stroke.c
31,17 → 31,18
*/
/**
* @file
* @brief Stroke simulator.
* @brief Stroke simulator.
*
* When simulating a keyboard using a serial TTY we need to convert the
* recognized strokes (such as Shift-A) to sequences of key presses and
* releases (such as 'press Shift, press A, release A, release Shift').
*
*/
 
#include <stroke.h>
#include <kbd.h>
#include <kbd/kbd.h>
#include <kbd/keycode.h>
#include <io/console.h>
#include <io/keycode.h>
 
/** Correspondence between modifers and the modifier keycodes. */
static unsigned int mods_keys[][2] = {
58,7 → 59,7
i = 0;
while (mods_keys[i][0] != 0) {
if (mod & mods_keys[i][0]) {
kbd_push_ev(KE_PRESS, mods_keys[i][1]);
kbd_push_ev(KEY_PRESS, mods_keys[i][1]);
}
++i;
}
65,8 → 66,8
 
/* Simulate key press and release. */
if (key != 0) {
kbd_push_ev(KE_PRESS, key);
kbd_push_ev(KE_RELEASE, key);
kbd_push_ev(KEY_PRESS, key);
kbd_push_ev(KEY_RELEASE, key);
}
 
/* Simulate modifier releases. */
73,7 → 74,7
i = 0;
while (mods_keys[i][0] != 0) {
if (mod & mods_keys[i][0]) {
kbd_push_ev(KE_RELEASE, mods_keys[i][1]);
kbd_push_ev(KEY_RELEASE, mods_keys[i][1]);
}
++i;
}
81,4 → 82,4
 
/**
* @}
*/
*/
/branches/dd/uspace/srv/kbd/genarch/gsp.c
49,7 → 49,7
*/
 
#include <gsp.h>
#include <libadt/hash_table.h>
#include <adt/hash_table.h>
#include <stdlib.h>
#include <stdio.h>
 
/branches/dd/uspace/srv/kbd/generic/key_buffer.c
File deleted
/branches/dd/uspace/srv/kbd/generic/kbd.c
28,10 → 28,10
 
/**
* @addtogroup kbdgen generic
* @brief HelenOS generic uspace keyboard handler.
* @ingroup kbd
* @brief HelenOS generic uspace keyboard handler.
* @ingroup kbd
* @{
*/
*/
/** @file
*/
 
45,12 → 45,12
#include <ipc/ns.h>
#include <async.h>
#include <errno.h>
#include <libadt/fifo.h>
#include <kbd/kbd.h>
#include <kbd/keycode.h>
#include <adt/fifo.h>
#include <io/console.h>
#include <io/keycode.h>
 
#include <kbd.h>
#include <key_buffer.h>
#include <keybuffer.h>
#include <kbd_port.h>
#include <kbd_ctl.h>
#include <layout.h>
88,7 → 88,7
 
void kbd_push_ev(int type, unsigned int key)
{
kbd_event_t ev;
console_event_t ev;
unsigned mod_mask;
 
switch (key) {
102,7 → 102,7
}
 
if (mod_mask != 0) {
if (type == KE_PRESS)
if (type == KEY_PRESS)
mods = mods | mod_mask;
else
mods = mods & ~mod_mask;
116,7 → 116,7
}
 
if (mod_mask != 0) {
if (type == KE_PRESS) {
if (type == KEY_PRESS) {
/*
* Only change lock state on transition from released
* to pressed. This prevents autorepeat from messing
133,7 → 133,7
printf("mods: 0x%x\n", mods);
printf("keycode: %u\n", key);
*/
if (type == KE_PRESS && (mods & KM_LCTRL) &&
if (type == KEY_PRESS && (mods & KM_LCTRL) &&
key == KC_F1) {
active_layout = 0;
layout[active_layout]->reset();
140,7 → 140,7
return;
}
 
if (type == KE_PRESS && (mods & KM_LCTRL) &&
if (type == KEY_PRESS && (mods & KM_LCTRL) &&
key == KC_F2) {
active_layout = 1;
layout[active_layout]->reset();
147,7 → 147,7
return;
}
 
if (type == KE_PRESS && (mods & KM_LCTRL) &&
if (type == KEY_PRESS && (mods & KM_LCTRL) &&
key == KC_F3) {
active_layout = 2;
layout[active_layout]->reset();
/branches/dd/uspace/srv/kbd/generic/keybuffer.c
0,0 → 1,132
/*
* Copyright (c) 2006 Josef Cejka
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup kbdgen
* @brief HelenOS generic uspace keyboard handler.
* @ingroup kbd
* @{
*/
/** @file
*/
 
#include <keybuffer.h>
#include <futex.h>
 
atomic_t keybuffer_futex = FUTEX_INITIALIZER;
 
/** Clear key buffer.
*/
void keybuffer_free(keybuffer_t *keybuffer)
{
futex_down(&keybuffer_futex);
keybuffer->head = 0;
keybuffer->tail = 0;
keybuffer->items = 0;
futex_up(&keybuffer_futex);
}
 
/** Key buffer initialization.
*
*/
void keybuffer_init(keybuffer_t *keybuffer)
{
keybuffer_free(keybuffer);
}
 
/** Get free space in buffer.
*
* This function is useful for processing some scancodes that are translated
* to more than one character.
*
* @return empty buffer space
*
*/
size_t keybuffer_available(keybuffer_t *keybuffer)
{
return KEYBUFFER_SIZE - keybuffer->items;
}
 
/**
*
* @return nonzero, if buffer is not empty.
*
*/
bool keybuffer_empty(keybuffer_t *keybuffer)
{
return (keybuffer->items == 0);
}
 
/** Push key event to key buffer.
*
* If the buffer is full, the event is ignored.
*
* @param keybuffer The keybuffer.
* @param ev The event to push.
*
*/
void keybuffer_push(keybuffer_t *keybuffer, const console_event_t *ev)
{
futex_down(&keybuffer_futex);
if (keybuffer->items < KEYBUFFER_SIZE) {
keybuffer->fifo[keybuffer->tail] = *ev;
keybuffer->tail = (keybuffer->tail + 1) % KEYBUFFER_SIZE;
keybuffer->items++;
}
futex_up(&keybuffer_futex);
}
 
/** Pop event from buffer.
*
* @param edst Pointer to where the event should be saved.
*
* @return True if an event was popped.
*
*/
bool keybuffer_pop(keybuffer_t *keybuffer, console_event_t *edst)
{
futex_down(&keybuffer_futex);
if (keybuffer->items > 0) {
keybuffer->items--;
*edst = (keybuffer->fifo[keybuffer->head]);
keybuffer->head = (keybuffer->head + 1) % KEYBUFFER_SIZE;
futex_up(&keybuffer_futex);
return true;
}
futex_up(&keybuffer_futex);
return false;
}
 
/**
* @}
*/
/branches/dd/uspace/srv/kbd/Makefile
34,7 → 34,7
 
include $(LIBC_PREFIX)/Makefile.toolchain
 
CFLAGS += -Iinclude -I../libadt/include
CFLAGS += -Iinclude
 
LIBS = $(LIBC_PREFIX)/libc.a
 
46,7 → 46,7
generic/kbd.c \
genarch/gsp.c \
genarch/stroke.c \
generic/key_buffer.c
generic/keybuffer.c
 
ARCH_SOURCES =
GENARCH_SOURCES = \
/branches/dd/uspace/srv/kbd/layout/us_qwerty.c
32,12 → 32,12
*/
 
#include <kbd.h>
#include <kbd/kbd.h>
#include <kbd/keycode.h>
#include <io/console.h>
#include <io/keycode.h>
#include <layout.h>
 
static void layout_reset(void);
static wchar_t layout_parse_ev(kbd_event_t *ev);
static wchar_t layout_parse_ev(console_event_t *ev);
 
layout_op_t us_qwerty_op = {
layout_reset,
203,7 → 203,7
{
}
 
static wchar_t layout_parse_ev(kbd_event_t *ev)
static wchar_t layout_parse_ev(console_event_t *ev)
{
wchar_t c;
 
/branches/dd/uspace/srv/kbd/layout/cz.c
27,23 → 27,23
*/
 
/** @addtogroup kbd
* @brief US QWERTY leyout.
* @brief US QWERTY leyout.
* @{
*/
*/
 
#include <kbd.h>
#include <kbd/kbd.h>
#include <kbd/keycode.h>
#include <io/console.h>
#include <io/keycode.h>
#include <bool.h>
#include <layout.h>
 
static void layout_reset(void);
static wchar_t layout_parse_ev(kbd_event_t *ev);
static wchar_t layout_parse_ev(console_event_t *ev);
 
enum m_state {
ms_start,
ms_hacek,
ms_carka
ms_carka
};
 
static enum m_state mstate;
272,7 → 272,7
return map[key];
}
 
static wchar_t parse_ms_hacek(kbd_event_t *ev)
static wchar_t parse_ms_hacek(console_event_t *ev)
{
wchar_t c;
 
290,7 → 290,7
return c;
}
 
static wchar_t parse_ms_carka(kbd_event_t *ev)
static wchar_t parse_ms_carka(console_event_t *ev)
{
wchar_t c;
 
308,7 → 308,7
return c;
}
 
static wchar_t parse_ms_start(kbd_event_t *ev)
static wchar_t parse_ms_start(console_event_t *ev)
{
wchar_t c;
 
383,21 → 383,24
mstate = ms_start;
}
 
static wchar_t layout_parse_ev(kbd_event_t *ev)
static wchar_t layout_parse_ev(console_event_t *ev)
{
if (ev->type != KE_PRESS)
return '\0';
 
if (ev->type != KEY_PRESS)
return 0;
if (key_is_mod(ev->key))
return '\0';
 
return 0;
switch (mstate) {
case ms_start: return parse_ms_start(ev);
case ms_hacek: return parse_ms_hacek(ev);
case ms_carka: return parse_ms_carka(ev);
case ms_start:
return parse_ms_start(ev);
case ms_hacek:
return parse_ms_hacek(ev);
case ms_carka:
return parse_ms_carka(ev);
}
}
 
/**
* @}
*/
*/
/branches/dd/uspace/srv/kbd/layout/us_dvorak.c
32,12 → 32,12
*/
 
#include <kbd.h>
#include <kbd/kbd.h>
#include <kbd/keycode.h>
#include <io/console.h>
#include <io/keycode.h>
#include <layout.h>
 
static void layout_reset(void);
static wchar_t layout_parse_ev(kbd_event_t *ev);
static wchar_t layout_parse_ev(console_event_t *ev);
 
layout_op_t us_dvorak_op = {
layout_reset,
209,7 → 209,7
{
}
 
static wchar_t layout_parse_ev(kbd_event_t *ev)
static wchar_t layout_parse_ev(console_event_t *ev)
{
wchar_t c;
 
/branches/dd/uspace/srv/ns/clonable.c
0,0 → 1,143
/*
* Copyright (c) 2009 Martin Decky
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ns
* @{
*/
 
#include <ipc/ipc.h>
#include <ipc/services.h>
#include <adt/list.h>
#include <bool.h>
#include <errno.h>
#include <assert.h>
#include <stdio.h>
#include <malloc.h>
#include <loader/loader.h>
#include "clonable.h"
#include "ns.h"
 
/** Request for connection to a clonable service. */
typedef struct {
link_t link;
ipcarg_t service;
ipc_call_t call;
ipc_callid_t callid;
} cs_req_t;
 
/** List of clonable-service connection requests. */
static link_t cs_req;
 
int clonable_init(void)
{
list_initialize(&cs_req);
return EOK;
}
 
/** Return true if @a service is clonable. */
bool service_clonable(int service)
{
return (service == SERVICE_LOAD);
}
 
/** Register clonable service.
*
* @param service Service to be registered.
* @param phone Phone to be used for connections to the service.
* @param call Pointer to call structure.
*
*/
void register_clonable(ipcarg_t service, ipcarg_t phone, ipc_call_t *call,
ipc_callid_t callid)
{
if (list_empty(&cs_req)) {
/* There was no pending connection request. */
printf(NAME ": Unexpected clonable server.\n");
ipc_answer_0(callid, EBUSY);
return;
}
cs_req_t *csr = list_get_instance(cs_req.next, cs_req_t, link);
list_remove(&csr->link);
/* Currently we can only handle a single type of clonable service. */
assert(csr->service == SERVICE_LOAD);
ipc_answer_0(callid, EOK);
ipc_forward_fast(csr->callid, phone, IPC_GET_ARG2(csr->call),
IPC_GET_ARG3(csr->call), 0, IPC_FF_NONE);
free(csr);
ipc_hangup(phone);
}
 
/** Connect client to clonable service.
*
* @param service Service to be connected to.
* @param call Pointer to call structure.
* @param callid Call ID of the request.
*
* @return Zero on success or a value from @ref errno.h.
*
*/
void connect_to_clonable(ipcarg_t service, ipc_call_t *call,
ipc_callid_t callid)
{
assert(service == SERVICE_LOAD);
cs_req_t *csr = malloc(sizeof(cs_req_t));
if (csr == NULL) {
ipc_answer_0(callid, ENOMEM);
return;
}
/* Spawn a loader. */
int rc = loader_spawn("loader");
if (rc < 0) {
free(csr);
ipc_answer_0(callid, rc);
return;
}
csr->service = service;
csr->call = *call;
csr->callid = callid;
/*
* We can forward the call only after the server we spawned connects
* to us. Meanwhile we might need to service more connection requests.
* Thus we store the call in a queue.
*/
list_append(&csr->link, &cs_req);
}
 
/**
* @}
*/
/branches/dd/uspace/srv/ns/ns.c
35,93 → 35,28
* @brief Naming service for HelenOS IPC.
*/
 
 
#include <ipc/ipc.h>
#include <ipc/services.h>
#include <ipc/ns.h>
#include <ipc/services.h>
#include <unistd.h>
#include <stdio.h>
#include <bool.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <assert.h>
#include <libadt/list.h>
#include <libadt/hash_table.h>
#include <as.h>
#include <ddi.h>
#include <event.h>
#include <macros.h>
#include <sysinfo.h>
#include <loader/loader.h>
#include <ddi.h>
#include <as.h>
#include "ns.h"
#include "service.h"
#include "clonable.h"
#include "task.h"
 
#define NAME "ns"
 
#define NS_HASH_TABLE_CHAINS 20
 
static int register_service(ipcarg_t service, ipcarg_t phone, ipc_call_t *call);
static void connect_to_service(ipcarg_t service, ipc_call_t *call,
ipc_callid_t callid);
 
void register_clonable(ipcarg_t service, ipcarg_t phone, ipc_call_t *call,
ipc_callid_t callid);
void connect_to_clonable(ipcarg_t service, ipc_call_t *call,
ipc_callid_t callid);
 
 
/* Static functions implementing NS hash table operations. */
static hash_index_t ns_hash(unsigned long *key);
static int ns_compare(unsigned long *key, hash_count_t keys, link_t *item);
static void ns_remove(link_t *item);
 
/** Operations for NS hash table. */
static hash_table_operations_t ns_hash_table_ops = {
.hash = ns_hash,
.compare = ns_compare,
.remove_callback = ns_remove
};
 
/** NS hash table structure. */
static hash_table_t ns_hash_table;
 
/** NS hash table item. */
typedef struct {
link_t link;
ipcarg_t service; /**< Number of the service. */
ipcarg_t phone; /**< Phone registered with the service. */
ipcarg_t in_phone_hash; /**< Incoming phone hash. */
} hashed_service_t;
 
/** Pending connection structure. */
typedef struct {
link_t link;
ipcarg_t service; /**< Number of the service. */
ipc_callid_t callid; /**< Call ID waiting for the connection */
ipcarg_t arg2; /**< Second argument */
ipcarg_t arg3; /**< Third argument */
} pending_req_t;
 
static link_t pending_req;
 
/** Request for connection to a clonable service. */
typedef struct {
link_t link;
ipcarg_t service;
ipc_call_t call;
ipc_callid_t callid;
} cs_req_t;
 
/** List of clonable-service connection requests. */
static link_t cs_req;
 
static void *clockaddr = NULL;
static void *klogaddr = NULL;
 
/** Return true if @a service is clonable. */
static bool service_clonable(int service)
static void get_as_area(ipc_callid_t callid, ipc_call_t *call, void *ph_addr,
size_t pages, void **addr)
{
return (service == SERVICE_LOAD);
}
 
static void get_as_area(ipc_callid_t callid, ipc_call_t *call, void *ph_addr, count_t pages, void **addr)
{
if (ph_addr == NULL) {
ipc_answer_0(callid, ENOENT);
return;
145,67 → 80,53
ipc_answer_2(callid, EOK, (ipcarg_t) *addr, AS_AREA_READ);
}
 
/** Process pending connection requests */
static void process_pending_req()
{
link_t *cur;
loop:
for (cur = pending_req.next; cur != &pending_req; cur = cur->next) {
pending_req_t *pr = list_get_instance(cur, pending_req_t, link);
unsigned long keys[3] = {
pr->service,
0,
0
};
link_t *link = hash_table_find(&ns_hash_table, keys);
if (!link)
continue;
hashed_service_t *hs = hash_table_get_instance(link, hashed_service_t, link);
ipcarg_t retval = ipc_forward_fast(pr->callid, hs->phone,
pr->arg2, pr->arg3, 0, IPC_FF_NONE);
if (!(pr->callid & IPC_CALLID_NOTIFICATION))
ipc_answer_0(pr->callid, retval);
list_remove(cur);
free(pr);
goto loop;
}
}
 
int main(int argc, char **argv)
{
printf(NAME ": HelenOS IPC Naming Service\n");
if (!hash_table_create(&ns_hash_table, NS_HASH_TABLE_CHAINS, 3,
&ns_hash_table_ops)) {
printf(NAME ": No memory available for services\n");
return ENOMEM;
}
int rc = service_init();
if (rc != EOK)
return rc;
list_initialize(&pending_req);
list_initialize(&cs_req);
rc = clonable_init();
if (rc != EOK)
return rc;
rc = task_init();
if (rc != EOK)
return rc;
printf(NAME ": Accepting connections\n");
while (true) {
process_pending_req();
process_pending_conn();
process_pending_wait();
ipc_call_t call;
ipc_callid_t callid = ipc_wait_for_call(&call);
task_id_t id;
ipcarg_t retval;
if (callid & IPC_CALLID_NOTIFICATION) {
id = (task_id_t)
MERGE_LOUP32(IPC_GET_ARG2(call), IPC_GET_ARG3(call));
wait_notification((wait_type_t) IPC_GET_ARG1(call), id);
continue;
}
switch (IPC_GET_METHOD(call)) {
case IPC_M_SHARE_IN:
switch (IPC_GET_ARG3(call)) {
case SERVICE_MEM_REALTIME:
get_as_area(callid, &call, sysinfo_value("clock.faddr"), 1, &clockaddr);
get_as_area(callid, &call,
(void *) sysinfo_value("clock.faddr"),
1, &clockaddr);
break;
case SERVICE_MEM_KLOG:
get_as_area(callid, &call, sysinfo_value("klog.faddr"), sysinfo_value("klog.pages"), &klogaddr);
get_as_area(callid, &call,
(void *) sysinfo_value("klog.faddr"),
sysinfo_value("klog.pages"), &klogaddr);
break;
default:
ipc_answer_0(callid, ENOENT);
241,6 → 162,14
continue;
}
break;
case NS_PING:
retval = EOK;
break;
case NS_TASK_WAIT:
id = (task_id_t)
MERGE_LOUP32(IPC_GET_ARG1(call), IPC_GET_ARG2(call));
wait_for_task(id, &call, callid);
continue;
default:
retval = ENOENT;
break;
254,213 → 183,6
return 0;
}
 
/** Register service.
*
* @param service Service to be registered.
* @param phone Phone to be used for connections to the service.
* @param call Pointer to call structure.
*
* @return Zero on success or a value from @ref errno.h.
*
*/
int register_service(ipcarg_t service, ipcarg_t phone, ipc_call_t *call)
{
unsigned long keys[3] = {
service,
call->in_phone_hash,
0
};
if (hash_table_find(&ns_hash_table, keys))
return EEXISTS;
hashed_service_t *hs = (hashed_service_t *) malloc(sizeof(hashed_service_t));
if (!hs)
return ENOMEM;
link_initialize(&hs->link);
hs->service = service;
hs->phone = phone;
hs->in_phone_hash = call->in_phone_hash;
hash_table_insert(&ns_hash_table, keys, &hs->link);
return 0;
}
 
/** Connect client to service.
*
* @param service Service to be connected to.
* @param call Pointer to call structure.
* @param callid Call ID of the request.
*
* @return Zero on success or a value from @ref errno.h.
*
*/
void connect_to_service(ipcarg_t service, ipc_call_t *call, ipc_callid_t callid)
{
ipcarg_t retval;
unsigned long keys[3] = {
service,
0,
0
};
link_t *link = hash_table_find(&ns_hash_table, keys);
if (!link) {
if (IPC_GET_ARG4(*call) & IPC_FLAG_BLOCKING) {
/* Blocking connection, add to pending list */
pending_req_t *pr = (pending_req_t *) malloc(sizeof(pending_req_t));
if (!pr) {
retval = ENOMEM;
goto out;
}
pr->service = service;
pr->callid = callid;
pr->arg2 = IPC_GET_ARG2(*call);
pr->arg3 = IPC_GET_ARG3(*call);
list_append(&pr->link, &pending_req);
return;
}
retval = ENOENT;
goto out;
}
hashed_service_t *hs = hash_table_get_instance(link, hashed_service_t, link);
retval = ipc_forward_fast(callid, hs->phone, IPC_GET_ARG2(*call),
IPC_GET_ARG3(*call), 0, IPC_FF_NONE);
out:
if (!(callid & IPC_CALLID_NOTIFICATION))
ipc_answer_0(callid, retval);
}
 
/** Register clonable service.
*
* @param service Service to be registered.
* @param phone Phone to be used for connections to the service.
* @param call Pointer to call structure.
*
*/
void register_clonable(ipcarg_t service, ipcarg_t phone, ipc_call_t *call,
ipc_callid_t callid)
{
if (list_empty(&cs_req)) {
/* There was no pending connection request. */
printf(NAME ": Unexpected clonable server.\n");
ipc_answer_0(callid, EBUSY);
return;
}
cs_req_t *csr = list_get_instance(cs_req.next, cs_req_t, link);
list_remove(&csr->link);
/* Currently we can only handle a single type of clonable service. */
assert(csr->service == SERVICE_LOAD);
ipc_answer_0(callid, EOK);
int rc = ipc_forward_fast(csr->callid, phone, IPC_GET_ARG2(csr->call),
IPC_GET_ARG3(csr->call), 0, IPC_FF_NONE);
 
free(csr);
ipc_hangup(phone);
}
 
/** Connect client to clonable service.
*
* @param service Service to be connected to.
* @param call Pointer to call structure.
* @param callid Call ID of the request.
*
* @return Zero on success or a value from @ref errno.h.
*
*/
void connect_to_clonable(ipcarg_t service, ipc_call_t *call,
ipc_callid_t callid)
{
assert(service == SERVICE_LOAD);
cs_req_t *csr = malloc(sizeof(cs_req_t));
if (csr == NULL) {
ipc_answer_0(callid, ENOMEM);
return;
}
/* Spawn a loader. */
int rc = loader_spawn("loader");
if (rc < 0) {
free(csr);
ipc_answer_0(callid, rc);
return;
}
csr->service = service;
csr->call = *call;
csr->callid = callid;
/*
* We can forward the call only after the server we spawned connects
* to us. Meanwhile we might need to service more connection requests.
* Thus we store the call in a queue.
*/
list_append(&csr->link, &cs_req);
}
 
/** Compute hash index into NS hash table.
*
* @param key Pointer keys. However, only the first key (i.e. service number)
* is used to compute the hash index.
*
* @return Hash index corresponding to key[0].
*
*/
hash_index_t ns_hash(unsigned long *key)
{
assert(key);
return (*key % NS_HASH_TABLE_CHAINS);
}
 
/** Compare a key with hashed item.
*
* This compare function always ignores the third key.
* It exists only to make it possible to remove records
* originating from connection with key[1] in_phone_hash
* value. Note that this is close to being classified
* as a nasty hack.
*
* @param key Array of keys.
* @param keys Must be lesser or equal to 3.
* @param item Pointer to a hash table item.
*
* @return Non-zero if the key matches the item, zero otherwise.
*
*/
int ns_compare(unsigned long key[], hash_count_t keys, link_t *item)
{
assert(key);
assert(keys <= 3);
assert(item);
hashed_service_t *hs = hash_table_get_instance(item, hashed_service_t, link);
if (keys == 2)
return key[1] == hs->in_phone_hash;
else
return key[0] == hs->service;
}
 
/** Perform actions after removal of item from the hash table.
*
* @param item Item that was removed from the hash table.
*
*/
void ns_remove(link_t *item)
{
assert(item);
free(hash_table_get_instance(item, hashed_service_t, link));
}
 
/**
* @}
*/
/branches/dd/uspace/srv/ns/service.c
0,0 → 1,254
/*
* Copyright (c) 2009 Martin Decky
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ns
* @{
*/
 
#include <ipc/ipc.h>
#include <adt/hash_table.h>
#include <assert.h>
#include <errno.h>
#include "service.h"
#include "ns.h"
 
#define SERVICE_HASH_TABLE_CHAINS 20
 
/** Service hash table item. */
typedef struct {
link_t link;
ipcarg_t service; /**< Number of the service. */
ipcarg_t phone; /**< Phone registered with the service. */
ipcarg_t in_phone_hash; /**< Incoming phone hash. */
} hashed_service_t;
 
/** Compute hash index into service hash table.
*
* @param key Pointer keys. However, only the first key (i.e. service number)
* is used to compute the hash index.
*
* @return Hash index corresponding to key[0].
*
*/
static hash_index_t service_hash(unsigned long *key)
{
assert(key);
return (*key % SERVICE_HASH_TABLE_CHAINS);
}
 
/** Compare a key with hashed item.
*
* This compare function always ignores the third key.
* It exists only to make it possible to remove records
* originating from connection with key[1] in_phone_hash
* value. Note that this is close to being classified
* as a nasty hack.
*
* @param key Array of keys.
* @param keys Must be lesser or equal to 3.
* @param item Pointer to a hash table item.
*
* @return Non-zero if the key matches the item, zero otherwise.
*
*/
static int service_compare(unsigned long key[], hash_count_t keys, link_t *item)
{
assert(key);
assert(keys <= 3);
assert(item);
hashed_service_t *hs = hash_table_get_instance(item, hashed_service_t, link);
if (keys == 2)
return (key[1] == hs->in_phone_hash);
else
return (key[0] == hs->service);
}
 
/** Perform actions after removal of item from the hash table.
*
* @param item Item that was removed from the hash table.
*
*/
static void service_remove(link_t *item)
{
assert(item);
free(hash_table_get_instance(item, hashed_service_t, link));
}
 
/** Operations for service hash table. */
static hash_table_operations_t service_hash_table_ops = {
.hash = service_hash,
.compare = service_compare,
.remove_callback = service_remove
};
 
/** Service hash table structure. */
static hash_table_t service_hash_table;
 
/** Pending connection structure. */
typedef struct {
link_t link;
ipcarg_t service; /**< Number of the service. */
ipc_callid_t callid; /**< Call ID waiting for the connection */
ipcarg_t arg2; /**< Second argument */
ipcarg_t arg3; /**< Third argument */
} pending_conn_t;
 
static link_t pending_conn;
 
int service_init(void)
{
if (!hash_table_create(&service_hash_table, SERVICE_HASH_TABLE_CHAINS,
3, &service_hash_table_ops)) {
printf(NAME ": No memory available for services\n");
return ENOMEM;
}
list_initialize(&pending_conn);
return EOK;
}
 
/** Process pending connection requests */
void process_pending_conn(void)
{
link_t *cur;
loop:
for (cur = pending_conn.next; cur != &pending_conn; cur = cur->next) {
pending_conn_t *pr = list_get_instance(cur, pending_conn_t, link);
unsigned long keys[3] = {
pr->service,
0,
0
};
link_t *link = hash_table_find(&service_hash_table, keys);
if (!link)
continue;
hashed_service_t *hs = hash_table_get_instance(link, hashed_service_t, link);
ipcarg_t retval = ipc_forward_fast(pr->callid, hs->phone,
pr->arg2, pr->arg3, 0, IPC_FF_NONE);
if (!(pr->callid & IPC_CALLID_NOTIFICATION))
ipc_answer_0(pr->callid, retval);
list_remove(cur);
free(pr);
goto loop;
}
}
 
/** Register service.
*
* @param service Service to be registered.
* @param phone Phone to be used for connections to the service.
* @param call Pointer to call structure.
*
* @return Zero on success or a value from @ref errno.h.
*
*/
int register_service(ipcarg_t service, ipcarg_t phone, ipc_call_t *call)
{
unsigned long keys[3] = {
service,
call->in_phone_hash,
0
};
if (hash_table_find(&service_hash_table, keys))
return EEXISTS;
hashed_service_t *hs = (hashed_service_t *) malloc(sizeof(hashed_service_t));
if (!hs)
return ENOMEM;
link_initialize(&hs->link);
hs->service = service;
hs->phone = phone;
hs->in_phone_hash = call->in_phone_hash;
hash_table_insert(&service_hash_table, keys, &hs->link);
return 0;
}
 
/** Connect client to service.
*
* @param service Service to be connected to.
* @param call Pointer to call structure.
* @param callid Call ID of the request.
*
* @return Zero on success or a value from @ref errno.h.
*
*/
void connect_to_service(ipcarg_t service, ipc_call_t *call, ipc_callid_t callid)
{
ipcarg_t retval;
unsigned long keys[3] = {
service,
0,
0
};
link_t *link = hash_table_find(&service_hash_table, keys);
if (!link) {
if (IPC_GET_ARG4(*call) & IPC_FLAG_BLOCKING) {
/* Blocking connection, add to pending list */
pending_conn_t *pr =
(pending_conn_t *) malloc(sizeof(pending_conn_t));
if (!pr) {
retval = ENOMEM;
goto out;
}
pr->service = service;
pr->callid = callid;
pr->arg2 = IPC_GET_ARG2(*call);
pr->arg3 = IPC_GET_ARG3(*call);
list_append(&pr->link, &pending_conn);
return;
}
retval = ENOENT;
goto out;
}
hashed_service_t *hs = hash_table_get_instance(link, hashed_service_t, link);
retval = ipc_forward_fast(callid, hs->phone, IPC_GET_ARG2(*call),
IPC_GET_ARG3(*call), 0, IPC_FF_NONE);
out:
if (!(callid & IPC_CALLID_NOTIFICATION))
ipc_answer_0(callid, retval);
}
 
/**
* @}
*/
/branches/dd/uspace/srv/ns/task.c
0,0 → 1,269
/*
* Copyright (c) 2009 Martin Decky
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ns
* @{
*/
 
#include <ipc/ipc.h>
#include <adt/hash_table.h>
#include <bool.h>
#include <errno.h>
#include <assert.h>
#include <stdio.h>
#include <macros.h>
#include "task.h"
#include "ns.h"
 
#define TASK_HASH_TABLE_CHAINS 256
 
/* TODO:
*
* The current implementation of waiting on a task is not perfect. If somebody
* wants to wait on a task which has already finished before the NS asked
* the kernel to receive notifications, it would block indefinitively.
*
* A solution to this is to fail immediately on a task for which no creation
* notification was received yet. However, there is a danger of a race condition
* in this solution -- the caller has to make sure that it is not trying to wait
* before the NS has a change to receive the task creation notification. This
* can be assured by waiting for this event in task_spawn().
*
* Finally, as there is currently no convention that each task has to be waited
* for, the NS can leak memory because of the zombie tasks.
*
*/
 
/** Task hash table item. */
typedef struct {
link_t link;
task_id_t id; /**< Task ID. */
bool destroyed;
} hashed_task_t;
 
/** Compute hash index into task hash table.
*
* @param key Pointer keys. However, only the first key (i.e. truncated task
* number) is used to compute the hash index.
*
* @return Hash index corresponding to key[0].
*
*/
static hash_index_t task_hash(unsigned long *key)
{
assert(key);
return (LOWER32(*key) % TASK_HASH_TABLE_CHAINS);
}
 
/** Compare a key with hashed item.
*
* @param key Array of keys.
* @param keys Must be lesser or equal to 2.
* @param item Pointer to a hash table item.
*
* @return Non-zero if the key matches the item, zero otherwise.
*
*/
static int task_compare(unsigned long key[], hash_count_t keys, link_t *item)
{
assert(key);
assert(keys <= 2);
assert(item);
hashed_task_t *ht = hash_table_get_instance(item, hashed_task_t, link);
if (keys == 2)
return ((LOWER32(key[1]) == UPPER32(ht->id))
&& (LOWER32(key[0]) == LOWER32(ht->id)));
else
return (LOWER32(key[0]) == LOWER32(ht->id));
}
 
/** Perform actions after removal of item from the hash table.
*
* @param item Item that was removed from the hash table.
*
*/
static void task_remove(link_t *item)
{
assert(item);
free(hash_table_get_instance(item, hashed_task_t, link));
}
 
/** Operations for task hash table. */
static hash_table_operations_t task_hash_table_ops = {
.hash = task_hash,
.compare = task_compare,
.remove_callback = task_remove
};
 
/** Task hash table structure. */
static hash_table_t task_hash_table;
 
/** Pending task wait structure. */
typedef struct {
link_t link;
task_id_t id; /**< Task ID. */
ipc_callid_t callid; /**< Call ID waiting for the connection */
} pending_wait_t;
 
static link_t pending_wait;
 
int task_init(void)
{
if (!hash_table_create(&task_hash_table, TASK_HASH_TABLE_CHAINS,
2, &task_hash_table_ops)) {
printf(NAME ": No memory available for tasks\n");
return ENOMEM;
}
if (event_subscribe(EVENT_WAIT, 0) != EOK)
printf(NAME ": Error registering wait notifications\n");
list_initialize(&pending_wait);
return EOK;
}
 
/** Process pending wait requests */
void process_pending_wait(void)
{
link_t *cur;
loop:
for (cur = pending_wait.next; cur != &pending_wait; cur = cur->next) {
pending_wait_t *pr = list_get_instance(cur, pending_wait_t, link);
unsigned long keys[2] = {
LOWER32(pr->id),
UPPER32(pr->id)
};
link_t *link = hash_table_find(&task_hash_table, keys);
if (!link)
continue;
hashed_task_t *ht = hash_table_get_instance(link, hashed_task_t, link);
if (!ht->destroyed)
continue;
if (!(pr->callid & IPC_CALLID_NOTIFICATION))
ipc_answer_0(pr->callid, EOK);
hash_table_remove(&task_hash_table, keys, 2);
list_remove(cur);
free(pr);
goto loop;
}
}
 
static void fail_pending_wait(task_id_t id, int rc)
{
link_t *cur;
loop:
for (cur = pending_wait.next; cur != &pending_wait; cur = cur->next) {
pending_wait_t *pr = list_get_instance(cur, pending_wait_t, link);
if (pr->id == id) {
if (!(pr->callid & IPC_CALLID_NOTIFICATION))
ipc_answer_0(pr->callid, rc);
list_remove(cur);
free(pr);
goto loop;
}
}
}
 
void wait_notification(wait_type_t et, task_id_t id)
{
unsigned long keys[2] = {
LOWER32(id),
UPPER32(id)
};
link_t *link = hash_table_find(&task_hash_table, keys);
if (link == NULL) {
hashed_task_t *ht =
(hashed_task_t *) malloc(sizeof(hashed_task_t));
if (ht == NULL) {
fail_pending_wait(id, ENOMEM);
return;
}
link_initialize(&ht->link);
ht->id = id;
ht->destroyed = (et == TASK_CREATE) ? false : true;
hash_table_insert(&task_hash_table, keys, &ht->link);
} else {
hashed_task_t *ht =
hash_table_get_instance(link, hashed_task_t, link);
ht->destroyed = (et == TASK_CREATE) ? false : true;
}
}
 
void wait_for_task(task_id_t id, ipc_call_t *call, ipc_callid_t callid)
{
ipcarg_t retval;
unsigned long keys[2] = {
LOWER32(id),
UPPER32(id)
};
link_t *link = hash_table_find(&task_hash_table, keys);
hashed_task_t *ht = (link != NULL) ?
hash_table_get_instance(link, hashed_task_t, link) : NULL;
if ((ht == NULL) || (!ht->destroyed)) {
/* Add to pending list */
pending_wait_t *pr =
(pending_wait_t *) malloc(sizeof(pending_wait_t));
if (!pr) {
retval = ENOMEM;
goto out;
}
pr->id = id;
pr->callid = callid;
list_append(&pr->link, &pending_wait);
return;
}
hash_table_remove(&task_hash_table, keys, 2);
retval = EOK;
out:
if (!(callid & IPC_CALLID_NOTIFICATION))
ipc_answer_0(callid, retval);
}
 
/**
* @}
*/
/branches/dd/uspace/srv/ns/clonable.h
0,0 → 1,51
/*
* Copyright (c) 2009 Martin Decky
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ns
* @{
*/
 
#ifndef NS_CLONABLE_H__
#define NS_CLONABLE_H__
 
#include <ipc/ipc.h>
#include <bool.h>
 
extern int clonable_init(void);
 
extern bool service_clonable(int service);
extern void register_clonable(ipcarg_t service, ipcarg_t phone,
ipc_call_t *call, ipc_callid_t callid);
extern void connect_to_clonable(ipcarg_t service, ipc_call_t *call,
ipc_callid_t callid);
 
#endif
 
/**
* @}
*/
/branches/dd/uspace/srv/ns/ns.h
0,0 → 1,42
/*
* Copyright (c) 2009 Martin Decky
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ns
* @{
*/
 
#ifndef NS_NS_H__
#define NS_NS_H__
 
#define NAME "ns"
 
#endif
 
/**
* @}
*/
/branches/dd/uspace/srv/ns/service.h
0,0 → 1,49
/*
* Copyright (c) 2009 Martin Decky
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ns
* @{
*/
 
#ifndef NS_SERVICE_H__
#define NS_SERVICE_H__
 
#include <ipc/ipc.h>
 
extern int service_init(void);
extern void process_pending_conn(void);
 
extern int register_service(ipcarg_t service, ipcarg_t phone, ipc_call_t *call);
extern void connect_to_service(ipcarg_t service, ipc_call_t *call,
ipc_callid_t callid);
 
#endif
 
/**
* @}
*/
/branches/dd/uspace/srv/ns/task.h
0,0 → 1,49
/*
* Copyright (c) 2009 Martin Decky
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ns
* @{
*/
 
#ifndef NS_TASK_H__
#define NS_TASK_H__
 
#include <ipc/ipc.h>
#include <event.h>
 
extern int task_init(void);
extern void process_pending_wait(void);
 
extern void wait_notification(wait_type_t et, task_id_t id);
extern void wait_for_task(task_id_t id, ipc_call_t *call, ipc_callid_t callid);
 
#endif
 
/**
* @}
*/
/branches/dd/uspace/srv/ns/Makefile
41,7 → 41,10
 
OUTPUT = ns
SOURCES = \
ns.c
ns.c \
service.c \
clonable.c \
task.c
 
OBJECTS := $(addsuffix .o,$(basename $(SOURCES)))
 
/branches/dd/uspace/srv/console/gcons.h
32,19 → 32,24
/** @file
*/
 
#ifndef _GCONS_H_
#define _GCONS_H_
#ifndef GCONS_H_
#define GCONS_H_
 
#include <sys/types.h>
 
void gcons_init(int phone);
 
void gcons_redraw_console(void);
void gcons_change_console(int consnum);
void gcons_notify_char(int consnum);
void gcons_change_console(size_t index);
void gcons_notify_char(size_t index);
void gcons_in_kernel(void);
void gcons_notify_connect(int consnum);
void gcons_notify_disconnect(int consnum);
void gcons_mouse_move(int dx, int dy);
int gcons_mouse_btn(int state);
 
void gcons_notify_connect(size_t index);
void gcons_notify_disconnect(size_t index);
 
void gcons_mouse_move(ssize_t dx, ssize_t dy);
int gcons_mouse_btn(bool state);
 
#endif
 
/** @}
/branches/dd/uspace/srv/console/screenbuffer.h
37,9 → 37,10
 
#include <stdint.h>
#include <sys/types.h>
#include <bool.h>
 
#define DEFAULT_FOREGROUND 0x0 /**< default console foreground color */
#define DEFAULT_BACKGROUND 0xf0f0f0 /**< default console background color */
#define DEFAULT_FOREGROUND 0x0 /**< default console foreground color */
#define DEFAULT_BACKGROUND 0xf0f0f0 /**< default console background color */
 
typedef struct {
uint8_t style;
72,25 → 73,25
/** One field on screen. It contain one character and its attributes. */
typedef struct {
wchar_t character; /**< Character itself */
attrs_t attrs; /**< Character`s attributes */
attrs_t attrs; /**< Character attributes */
} keyfield_t;
 
/** Structure for buffering state of one virtual console.
*/
typedef struct {
keyfield_t *buffer; /**< Screen content - characters and
their attributes (used as a circular buffer) */
unsigned int size_x; /**< Number of columns */
unsigned int size_y; /**< Number of rows */
keyfield_t *buffer; /**< Screen content - characters and
their attributes (used as a circular buffer) */
size_t size_x; /**< Number of columns */
size_t size_y; /**< Number of rows */
/** Coordinates of last printed character for determining cursor position */
unsigned int position_x;
unsigned int position_y;
size_t position_x;
size_t position_y;
attrs_t attrs; /**< Current attributes. */
unsigned int top_line; /**< Points to buffer[][] line that will
be printed at screen as the first line */
unsigned char is_cursor_visible; /**< Cursor state - default is visible */
attrs_t attrs; /**< Current attributes. */
size_t top_line; /**< Points to buffer[][] line that will
be printed at screen as the first line */
bool is_cursor_visible; /**< Cursor state - default is visible */
} screenbuffer_t;
 
/** Returns keyfield for position on screen
105,7 → 106,7
* @return Keyfield structure with character and its attributes on x, y
*
*/
static inline keyfield_t *get_field_at(screenbuffer_t *scr, unsigned int x, unsigned int y)
static inline keyfield_t *get_field_at(screenbuffer_t *scr, size_t x, size_t y)
{
return scr->buffer + x + ((y + scr->top_line) % scr->size_y) * scr->size_x;
}
138,17 → 139,17
 
 
void screenbuffer_putchar(screenbuffer_t *scr, wchar_t c);
screenbuffer_t *screenbuffer_init(screenbuffer_t *scr, int size_x, int size_y);
screenbuffer_t *screenbuffer_init(screenbuffer_t *scr, size_t size_x, size_t size_y);
 
void screenbuffer_clear(screenbuffer_t *scr);
void screenbuffer_clear_line(screenbuffer_t *scr, unsigned int line);
void screenbuffer_clear_line(screenbuffer_t *scr, size_t line);
void screenbuffer_copy_buffer(screenbuffer_t *scr, keyfield_t *dest);
void screenbuffer_goto(screenbuffer_t *scr, unsigned int x, unsigned int y);
void screenbuffer_set_style(screenbuffer_t *scr, int style);
void screenbuffer_set_color(screenbuffer_t *scr, unsigned int fg_color,
unsigned int bg_color, unsigned int attr);
void screenbuffer_set_rgb_color(screenbuffer_t *scr, unsigned int fg_color,
unsigned int bg_color);
void screenbuffer_goto(screenbuffer_t *scr, size_t x, size_t y);
void screenbuffer_set_style(screenbuffer_t *scr, uint8_t style);
void screenbuffer_set_color(screenbuffer_t *scr, uint8_t fg_color,
uint8_t bg_color, uint8_t attr);
void screenbuffer_set_rgb_color(screenbuffer_t *scr, uint32_t fg_color,
uint32_t bg_color);
 
#endif
 
/branches/dd/uspace/srv/console/console.c
36,37 → 36,30
#include <fb.h>
#include <ipc/ipc.h>
#include <kbd.h>
#include <kbd/keycode.h>
#include <io/keycode.h>
#include <ipc/fb.h>
#include <ipc/services.h>
#include <errno.h>
#include <key_buffer.h>
#include <keybuffer.h>
#include <ipc/console.h>
#include <unistd.h>
#include <async.h>
#include <libadt/fifo.h>
#include <screenbuffer.h>
#include <adt/fifo.h>
#include <sys/mman.h>
#include <stdio.h>
#include <string.h>
#include <sysinfo.h>
#include <event.h>
#include <devmap.h>
 
#include "console.h"
#include "gcons.h"
#include "screenbuffer.h"
 
#define NAME "console"
 
#define MAX_KEYREQUESTS_BUFFERED 32
#define MAX_DEVICE_NAME 32
 
/** Size of cwrite_buf. */
#define CWRITE_BUF_SIZE 256
 
/** Index of currently used virtual console.
*/
int active_console = 0;
int prev_console = 0;
 
/** Phone to the keyboard driver. */
static int kbd_phone;
 
73,28 → 66,26
/** Information about framebuffer */
struct {
int phone; /**< Framebuffer phone */
ipcarg_t cols; /**< Framebuffer columns */
ipcarg_t rows; /**< Framebuffer rows */
ipcarg_t cols; /**< Framebuffer columns */
} fb_info;
 
typedef struct {
keybuffer_t keybuffer; /**< Buffer for incoming keys. */
/** Buffer for unsatisfied request for keys. */
FIFO_CREATE_STATIC(keyrequests, ipc_callid_t,
MAX_KEYREQUESTS_BUFFERED);
int keyrequest_counter; /**< Number of requests in buffer. */
int client_phone; /**< Phone to connected client. */
int used; /**< 1 if this virtual console is
connected to some client. */
screenbuffer_t screenbuffer; /**< Screenbuffer for saving screen
contents and related settings. */
} connection_t;
size_t index; /**< Console index */
size_t refcount; /**< Connection reference count */
dev_handle_t dev_handle; /**< Device handle */
keybuffer_t keybuffer; /**< Buffer for incoming keys. */
screenbuffer_t scr; /**< Screenbuffer for saving screen
contents and related settings. */
} console_t;
 
/** Array of data for virtual consoles */
static connection_t connections[CONSOLE_COUNT];
static console_t consoles[CONSOLE_COUNT];
 
static console_t *active_console = &consoles[0];
static console_t *prev_console = &consoles[0];
static console_t *kernel_console = &consoles[KERNEL_CONSOLE];
 
/** Pointer to memory shared with framebufer used for
faster virtual console switching */
static keyfield_t *interbuffer = NULL;
101,34 → 92,69
 
/** Information on row-span yet unsent to FB driver. */
struct {
int row; /**< Row where the span lies. */
int col; /**< Leftmost column of the span. */
int cnt; /**< Width of the span. */
size_t col; /**< Leftmost column of the span. */
size_t row; /**< Row where the span lies. */
size_t cnt; /**< Width of the span. */
} fb_pending;
 
/** Buffer for receiving data via the CONSOLE_WRITE call from the client. */
static char cwrite_buf[CWRITE_BUF_SIZE];
/** Pending input structure. */
typedef struct {
link_t link;
console_t *cons; /**< Console waiting for input */
ipc_callid_t rid; /**< Call ID waiting for input */
ipc_callid_t callid; /**< Call ID waiting for IPC_DATA_READ */
size_t pos; /**< Position of the last stored data */
size_t size; /**< Size of ther buffer */
char *data; /**< Already stored data */
} pending_input_t;
 
/** Find unused virtual console.
*
*/
static int find_free_connection(void)
LIST_INITIALIZE(pending_input);
 
/** Process pending input requests */
static void process_pending_input(void)
{
int i;
async_serialize_start();
for (i = 0; i < CONSOLE_COUNT; i++) {
if (!connections[i].used)
return i;
link_t *cur;
loop:
for (cur = pending_input.next; cur != &pending_input; cur = cur->next) {
pending_input_t *pr = list_get_instance(cur, pending_input_t, link);
console_event_t ev;
if (keybuffer_pop(&pr->cons->keybuffer, &ev)) {
if (pr->data != NULL) {
if (ev.type == KEY_PRESS) {
pr->data[pr->pos] = ev.c;
pr->pos++;
}
} else {
ipc_answer_4(pr->rid, EOK, ev.type, ev.key, ev.mods, ev.c);
list_remove(cur);
free(pr);
goto loop;
}
}
if ((pr->data != NULL) && (pr->pos == pr->size)) {
(void) ipc_data_read_finalize(pr->callid, pr->data, pr->size);
ipc_answer_1(pr->rid, EOK, pr->size);
free(pr->data);
list_remove(cur);
free(pr);
goto loop;
}
}
return -1;
async_serialize_end();
}
 
static void clrscr(void)
{
async_msg_0(fb_info.phone, FB_CLEAR);
}
 
static void curs_visibility(bool visible)
{
async_msg_1(fb_info.phone, FB_CURSOR_VISIBILITY, visible);
139,11 → 165,16
ipc_call_sync_1_0(fb_info.phone, FB_CURSOR_VISIBILITY, false);
}
 
static void curs_goto(int row, int col)
static void curs_goto(size_t x, size_t y)
{
async_msg_2(fb_info.phone, FB_CURSOR_GOTO, row, col);
async_msg_2(fb_info.phone, FB_CURSOR_GOTO, x, y);
}
 
static void screen_clear(void)
{
async_msg_0(fb_info.phone, FB_CLEAR);
}
 
static void screen_yield(void)
{
ipc_call_sync_0_0(fb_info.phone, FB_SCREEN_YIELD);
166,7 → 197,7
 
static void set_style(int style)
{
async_msg_1(fb_info.phone, FB_SET_STYLE, style);
async_msg_1(fb_info.phone, FB_SET_STYLE, style);
}
 
static void set_color(int fgcolor, int bgcolor, int flags)
196,23 → 227,21
}
 
/** Send an area of screenbuffer to the FB driver. */
static void fb_update_area(connection_t *conn, int x, int y, int w, int h)
static void fb_update_area(console_t *cons, ipcarg_t x0, ipcarg_t y0, ipcarg_t width, ipcarg_t height)
{
int i;
int j;
attrs_t *attrs;
keyfield_t *field;
if (interbuffer) {
for (j = 0; j < h; j++) {
for (i = 0; i < w; i++) {
interbuffer[i + j * w] =
*get_field_at(&conn->screenbuffer, x + i, y + j);
ipcarg_t x;
ipcarg_t y;
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
interbuffer[y * width + x] =
*get_field_at(&cons->scr, x0 + x, y0 + y);
}
}
async_req_4_0(fb_info.phone, FB_DRAW_TEXT_DATA,
x, y, w, h);
x0, y0, width, height);
}
}
 
219,11 → 248,8
/** Flush pending cells to FB. */
static void fb_pending_flush(void)
{
screenbuffer_t *scr
= &(connections[active_console].screenbuffer);
if (fb_pending.cnt > 0) {
fb_update_area(&connections[active_console], fb_pending.col,
fb_update_area(active_console, fb_pending.col,
fb_pending.row, fb_pending.cnt, 1);
fb_pending.cnt = 0;
}
235,18 → 261,18
* the old span is flushed first.
*
*/
static void cell_mark_changed(int row, int col)
static void cell_mark_changed(size_t col, size_t row)
{
if (fb_pending.cnt != 0) {
if ((row != fb_pending.row)
|| (col != fb_pending.col + fb_pending.cnt)) {
if ((col != fb_pending.col + fb_pending.cnt)
|| (row != fb_pending.row)) {
fb_pending_flush();
}
}
if (fb_pending.cnt == 0) {
fb_pending.col = col;
fb_pending.row = row;
fb_pending.col = col;
}
fb_pending.cnt++;
253,82 → 279,67
}
 
/** Print a character to the active VC with buffering. */
static void fb_putchar(wchar_t c, int row, int col)
static void fb_putchar(wchar_t c, ipcarg_t col, ipcarg_t row)
{
async_msg_3(fb_info.phone, FB_PUTCHAR, c, row, col);
async_msg_3(fb_info.phone, FB_PUTCHAR, c, col, row);
}
 
/** Process a character from the client (TTY emulation). */
static void write_char(int console, wchar_t ch)
static void write_char(console_t *cons, wchar_t ch)
{
bool flush_cursor = false;
screenbuffer_t *scr = &(connections[console].screenbuffer);
switch (ch) {
case '\n':
fb_pending_flush();
flush_cursor = true;
scr->position_y++;
scr->position_x = 0;
cons->scr.position_y++;
cons->scr.position_x = 0;
break;
case '\r':
break;
case '\t':
scr->position_x += 8;
scr->position_x -= scr->position_x % 8;
cons->scr.position_x += 8;
cons->scr.position_x -= cons->scr.position_x % 8;
break;
case '\b':
if (scr->position_x == 0)
if (cons->scr.position_x == 0)
break;
scr->position_x--;
if (console == active_console)
cell_mark_changed(scr->position_y, scr->position_x);
screenbuffer_putchar(scr, ' ');
cons->scr.position_x--;
if (cons == active_console)
cell_mark_changed(cons->scr.position_x, cons->scr.position_y);
screenbuffer_putchar(&cons->scr, ' ');
break;
default:
if (console == active_console)
cell_mark_changed(scr->position_y, scr->position_x);
if (cons == active_console)
cell_mark_changed(cons->scr.position_x, cons->scr.position_y);
screenbuffer_putchar(scr, ch);
scr->position_x++;
screenbuffer_putchar(&cons->scr, ch);
cons->scr.position_x++;
}
if (scr->position_x >= scr->size_x) {
flush_cursor = true;
scr->position_y++;
}
if (cons->scr.position_x >= cons->scr.size_x)
cons->scr.position_y++;
if (scr->position_y >= scr->size_y) {
if (cons->scr.position_y >= cons->scr.size_y) {
fb_pending_flush();
scr->position_y = scr->size_y - 1;
screenbuffer_clear_line(scr, scr->top_line);
scr->top_line = (scr->top_line + 1) % scr->size_y;
if (console == active_console)
cons->scr.position_y = cons->scr.size_y - 1;
screenbuffer_clear_line(&cons->scr, cons->scr.top_line);
cons->scr.top_line = (cons->scr.top_line + 1) % cons->scr.size_y;
if (cons == active_console)
async_msg_1(fb_info.phone, FB_SCROLL, 1);
}
scr->position_x = scr->position_x % scr->size_x;
if (console == active_console && flush_cursor)
curs_goto(scr->position_y, scr->position_x);
cons->scr.position_x = cons->scr.position_x % cons->scr.size_x;
}
 
/** Switch to new console */
static void change_console(int newcons)
static void change_console(console_t *cons)
{
connection_t *conn;
int i;
int j;
int rc;
keyfield_t *field;
attrs_t *attrs;
if (newcons == active_console)
if (cons == active_console)
return;
fb_pending_flush();
if (newcons == KERNEL_CONSOLE) {
if (cons == kernel_console) {
async_serialize_start();
curs_hide_sync();
gcons_in_kernel();
336,67 → 347,67
kbd_yield();
async_serialize_end();
if (__SYSCALL0(SYS_DEBUG_ENABLE_CONSOLE)) {
prev_console = active_console;
active_console = KERNEL_CONSOLE;
active_console = kernel_console;
} else
newcons = active_console;
cons = active_console;
}
if (newcons != KERNEL_CONSOLE) {
if (cons != kernel_console) {
size_t x;
size_t y;
int rc = 0;
async_serialize_start();
if (active_console == KERNEL_CONSOLE) {
if (active_console == kernel_console) {
screen_reclaim();
kbd_reclaim();
gcons_redraw_console();
}
active_console = newcons;
gcons_change_console(newcons);
conn = &connections[active_console];
active_console = cons;
gcons_change_console(cons->index);
set_attrs(&conn->screenbuffer.attrs);
set_attrs(&cons->scr.attrs);
curs_visibility(false);
if (interbuffer) {
for (j = 0; j < conn->screenbuffer.size_y; j++) {
for (i = 0; i < conn->screenbuffer.size_x; i++) {
unsigned int size_x;
size_x = conn->screenbuffer.size_x;
interbuffer[j * size_x + i] =
*get_field_at(&conn->screenbuffer, i, j);
for (y = 0; y < cons->scr.size_y; y++) {
for (x = 0; x < cons->scr.size_x; x++) {
interbuffer[y * cons->scr.size_x + x] =
*get_field_at(&cons->scr, x, y);
}
}
/* This call can preempt, but we are already at the end */
rc = async_req_4_0(fb_info.phone, FB_DRAW_TEXT_DATA,
0, 0, conn->screenbuffer.size_x,
conn->screenbuffer.size_y);
0, 0, cons->scr.size_x,
cons->scr.size_y);
}
if ((!interbuffer) || (rc != 0)) {
set_attrs(&conn->screenbuffer.attrs);
clrscr();
attrs = &conn->screenbuffer.attrs;
set_attrs(&cons->scr.attrs);
screen_clear();
for (j = 0; j < conn->screenbuffer.size_y; j++)
for (i = 0; i < conn->screenbuffer.size_x; i++) {
field = get_field_at(&conn->screenbuffer, i, j);
if (!attrs_same(*attrs, field->attrs))
for (y = 0; y < cons->scr.size_y; y++)
for (x = 0; x < cons->scr.size_x; x++) {
keyfield_t *field = get_field_at(&cons->scr, x, y);
if (!attrs_same(cons->scr.attrs, field->attrs))
set_attrs(&field->attrs);
attrs = &field->attrs;
cons->scr.attrs = field->attrs;
if ((field->character == ' ') &&
(attrs_same(field->attrs, conn->screenbuffer.attrs)))
(attrs_same(field->attrs, cons->scr.attrs)))
continue;
fb_putchar(field->character, j, i);
fb_putchar(field->character, x, y);
}
}
curs_goto(conn->screenbuffer.position_y,
conn->screenbuffer.position_x);
curs_visibility(conn->screenbuffer.is_cursor_visible);
curs_goto(cons->scr.position_x, cons->scr.position_y);
curs_visibility(cons->scr.is_cursor_visible);
async_serialize_end();
}
405,31 → 416,19
/** Handler for keyboard */
static void keyboard_events(ipc_callid_t iid, ipc_call_t *icall)
{
ipc_callid_t callid;
ipc_call_t call;
int retval;
kbd_event_t ev;
connection_t *conn;
int newcon;
/* Ignore parameters, the connection is alread opened */
/* Ignore parameters, the connection is already opened */
while (true) {
callid = async_get_call(&call);
ipc_call_t call;
ipc_callid_t callid = async_get_call(&call);
int retval;
console_event_t ev;
switch (IPC_GET_METHOD(call)) {
case IPC_M_PHONE_HUNGUP:
/* TODO: Handle hangup */
return;
case KBD_MS_LEFT:
newcon = gcons_mouse_btn(IPC_GET_ARG1(call));
if (newcon != -1)
change_console(newcon);
retval = 0;
break;
case KBD_MS_MOVE:
gcons_mouse_move(IPC_GET_ARG1(call),
IPC_GET_ARG2(call));
retval = 0;
break;
case KBD_EVENT:
/* Got event from keyboard driver. */
retval = 0;
438,29 → 437,16
ev.mods = IPC_GET_ARG3(call);
ev.c = IPC_GET_ARG4(call);
/* Switch to another virtual console */
conn = &connections[active_console];
if ((ev.key >= KC_F1) && (ev.key < KC_F1 +
CONSOLE_COUNT) && ((ev.mods & KM_CTRL) == 0)) {
if (ev.key == KC_F12)
change_console(KERNEL_CONSOLE);
if (ev.key == KC_F1 + KERNEL_CONSOLE)
change_console(kernel_console);
else
change_console(ev.key - KC_F1);
change_console(&consoles[ev.key - KC_F1]);
break;
}
/* If client is awaiting key, send it */
if (conn->keyrequest_counter > 0) {
conn->keyrequest_counter--;
ipc_answer_4(fifo_pop(conn->keyrequests), EOK,
ev.type, ev.key, ev.mods, ev.c);
break;
}
keybuffer_push(&conn->keybuffer, &ev);
retval = 0;
keybuffer_push(&active_console->keybuffer, &ev);
break;
default:
retval = ENOENT;
469,14 → 455,10
}
}
 
/** Handle CONSOLE_WRITE call. */
static void cons_write(int consnum, ipc_callid_t rid, ipc_call_t *request)
static void cons_write(console_t *cons, ipc_callid_t rid, ipc_call_t *request)
{
ipc_callid_t callid;
size_t size;
wchar_t ch;
size_t off;
if (!ipc_data_write_receive(&callid, &size)) {
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
483,49 → 465,146
return;
}
if (size > CWRITE_BUF_SIZE)
size = CWRITE_BUF_SIZE;
char *buf = (char *) malloc(size);
if (buf == NULL) {
ipc_answer_0(callid, ENOMEM);
ipc_answer_0(rid, ENOMEM);
return;
}
(void) ipc_data_write_finalize(callid, cwrite_buf, size);
(void) ipc_data_write_finalize(callid, buf, size);
async_serialize_start();
off = 0;
size_t off = 0;
while (off < size) {
ch = str_decode(cwrite_buf, &off, size);
write_char(consnum, ch);
wchar_t ch = str_decode(buf, &off, size);
write_char(cons, ch);
}
if (cons == active_console)
curs_goto(cons->scr.position_x, cons->scr.position_y);
async_serialize_end();
gcons_notify_char(consnum);
gcons_notify_char(cons->index);
ipc_answer_1(rid, EOK, size);
free(buf);
}
 
static void cons_read(console_t *cons, ipc_callid_t rid, ipc_call_t *request)
{
ipc_callid_t callid;
size_t size;
if (!ipc_data_read_receive(&callid, &size)) {
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
return;
}
char *buf = (char *) malloc(size);
if (buf == NULL) {
ipc_answer_0(callid, ENOMEM);
ipc_answer_0(rid, ENOMEM);
return;
}
async_serialize_start();
size_t pos = 0;
console_event_t ev;
while ((keybuffer_pop(&cons->keybuffer, &ev)) && (pos < size)) {
if (ev.type == KEY_PRESS) {
buf[pos] = ev.c;
pos++;
}
}
if (pos == size) {
(void) ipc_data_read_finalize(callid, buf, size);
ipc_answer_1(rid, EOK, size);
free(buf);
} else {
pending_input_t *pr = (pending_input_t *) malloc(sizeof(pending_input_t));
if (!pr) {
ipc_answer_0(callid, ENOMEM);
ipc_answer_0(rid, ENOMEM);
free(buf);
async_serialize_end();
return;
}
pr->cons = cons;
pr->rid = rid;
pr->callid = callid;
pr->pos = pos;
pr->size = size;
pr->data = buf;
list_append(&pr->link, &pending_input);
}
async_serialize_end();
}
 
static void cons_get_event(console_t *cons, ipc_callid_t rid, ipc_call_t *request)
{
async_serialize_start();
console_event_t ev;
if (keybuffer_pop(&cons->keybuffer, &ev)) {
ipc_answer_4(rid, EOK, ev.type, ev.key, ev.mods, ev.c);
} else {
pending_input_t *pr = (pending_input_t *) malloc(sizeof(pending_input_t));
if (!pr) {
ipc_answer_0(rid, ENOMEM);
async_serialize_end();
return;
}
pr->cons = cons;
pr->rid = rid;
pr->callid = 0;
pr->data = NULL;
list_append(&pr->link, &pending_input);
}
async_serialize_end();
}
 
/** Default thread for new connections */
static void client_connection(ipc_callid_t iid, ipc_call_t *icall)
{
ipc_callid_t callid;
ipc_call_t call;
int consnum;
ipcarg_t arg1, arg2, arg3, arg4;
connection_t *conn;
screenbuffer_t *scr;
console_t *cons = NULL;
if ((consnum = find_free_connection()) == -1) {
ipc_answer_0(iid, ELIMIT);
size_t i;
for (i = 0; i < CONSOLE_COUNT; i++) {
if (i == KERNEL_CONSOLE)
continue;
if (consoles[i].dev_handle == (dev_handle_t) IPC_GET_ARG1(*icall)) {
cons = &consoles[i];
break;
}
}
if (cons == NULL) {
ipc_answer_0(iid, ENOENT);
return;
}
conn = &connections[consnum];
conn->used = 1;
ipc_callid_t callid;
ipc_call_t call;
ipcarg_t arg1;
ipcarg_t arg2;
ipcarg_t arg3;
async_serialize_start();
gcons_notify_connect(consnum);
conn->client_phone = IPC_GET_ARG5(*icall);
screenbuffer_clear(&conn->screenbuffer);
if (consnum == active_console)
clrscr();
if (cons->refcount == 0)
gcons_notify_connect(cons->index);
cons->refcount++;
/* Accept the connection */
ipc_answer_0(iid, EOK);
537,64 → 616,55
arg1 = 0;
arg2 = 0;
arg3 = 0;
arg4 = 0;
switch (IPC_GET_METHOD(call)) {
case IPC_M_PHONE_HUNGUP:
gcons_notify_disconnect(consnum);
/* Answer all pending requests */
while (conn->keyrequest_counter > 0) {
conn->keyrequest_counter--;
ipc_answer_0(fifo_pop(conn->keyrequests),
ENOENT);
break;
}
conn->used = 0;
cons->refcount--;
if (cons->refcount == 0)
gcons_notify_disconnect(cons->index);
return;
case CONSOLE_PUTCHAR:
write_char(consnum, IPC_GET_ARG1(call));
gcons_notify_char(consnum);
break;
case CONSOLE_WRITE:
case VFS_READ:
async_serialize_end();
cons_write(consnum, callid, &call);
cons_read(cons, callid, &call);
async_serialize_start();
continue;
case VFS_WRITE:
async_serialize_end();
cons_write(cons, callid, &call);
async_serialize_start();
continue;
case VFS_SYNC:
fb_pending_flush();
if (cons == active_console) {
async_req_0_0(fb_info.phone, FB_FLUSH);
curs_goto(cons->scr.position_x, cons->scr.position_y);
}
break;
case CONSOLE_CLEAR:
/* Send message to fb */
if (consnum == active_console) {
async_msg_0(fb_info.phone, FB_CLEAR);
}
if (cons == active_console)
async_msg_0(fb_info.phone, FB_CLEAR);
screenbuffer_clear(&conn->screenbuffer);
screenbuffer_clear(&cons->scr);
break;
case CONSOLE_GOTO:
screenbuffer_goto(&conn->screenbuffer,
IPC_GET_ARG2(call), IPC_GET_ARG1(call));
if (consnum == active_console)
screenbuffer_goto(&cons->scr,
IPC_GET_ARG1(call), IPC_GET_ARG2(call));
if (cons == active_console)
curs_goto(IPC_GET_ARG1(call),
IPC_GET_ARG2(call));
break;
case CONSOLE_GETSIZE:
arg1 = fb_info.rows;
arg2 = fb_info.cols;
case CONSOLE_GET_SIZE:
arg1 = fb_info.cols;
arg2 = fb_info.rows;
break;
case CONSOLE_FLUSH:
fb_pending_flush();
if (consnum == active_console) {
async_req_0_0(fb_info.phone, FB_FLUSH);
scr = &(connections[consnum].screenbuffer);
curs_goto(scr->position_y, scr->position_x);
}
break;
case CONSOLE_SET_STYLE:
fb_pending_flush();
arg1 = IPC_GET_ARG1(call);
screenbuffer_set_style(&conn->screenbuffer, arg1);
if (consnum == active_console)
screenbuffer_set_style(&cons->scr, arg1);
if (cons == active_console)
set_style(arg1);
break;
case CONSOLE_SET_COLOR:
602,9 → 672,8
arg1 = IPC_GET_ARG1(call);
arg2 = IPC_GET_ARG2(call);
arg3 = IPC_GET_ARG3(call);
screenbuffer_set_color(&conn->screenbuffer, arg1,
arg2, arg3);
if (consnum == active_console)
screenbuffer_set_color(&cons->scr, arg1, arg2, arg3);
if (cons == active_console)
set_color(arg1, arg2, arg3);
break;
case CONSOLE_SET_RGB_COLOR:
611,46 → 680,27
fb_pending_flush();
arg1 = IPC_GET_ARG1(call);
arg2 = IPC_GET_ARG2(call);
screenbuffer_set_rgb_color(&conn->screenbuffer, arg1,
arg2);
if (consnum == active_console)
screenbuffer_set_rgb_color(&cons->scr, arg1, arg2);
if (cons == active_console)
set_rgb_color(arg1, arg2);
break;
case CONSOLE_CURSOR_VISIBILITY:
fb_pending_flush();
arg1 = IPC_GET_ARG1(call);
conn->screenbuffer.is_cursor_visible = arg1;
if (consnum == active_console)
cons->scr.is_cursor_visible = arg1;
if (cons == active_console)
curs_visibility(arg1);
break;
case CONSOLE_GETKEY:
if (keybuffer_empty(&conn->keybuffer)) {
/* buffer is empty -> store request */
if (conn->keyrequest_counter <
MAX_KEYREQUESTS_BUFFERED) {
fifo_push(conn->keyrequests, callid);
conn->keyrequest_counter++;
} else {
/*
* No key available and too many
* requests => fail.
*/
ipc_answer_0(callid, ELIMIT);
}
continue;
}
kbd_event_t ev;
keybuffer_pop(&conn->keybuffer, &ev);
arg1 = ev.type;
arg2 = ev.key;
arg3 = ev.mods;
arg4 = ev.c;
break;
case CONSOLE_GET_EVENT:
async_serialize_end();
cons_get_event(cons, callid, &call);
async_serialize_start();
continue;
case CONSOLE_KCON_ENABLE:
change_console(KERNEL_CONSOLE);
change_console(kernel_console);
break;
}
ipc_answer_4(callid, EOK, arg1, arg2, arg3, arg4);
ipc_answer_3(callid, EOK, arg1, arg2, arg3);
}
}
 
659,28 → 709,26
change_console(prev_console);
}
 
int main(int argc, char *argv[])
static bool console_init(void)
{
printf(NAME ": HelenOS Console service\n");
async_serialize_start();
ipcarg_t phonehash;
size_t ib_size;
int i;
async_set_client_connection(client_connection);
/* Connect to keyboard driver */
kbd_phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_KEYBOARD, 0, 0);
if (kbd_phone < 0) {
printf(NAME ": Failed to connect to keyboard service\n");
return -1;
async_serialize_end();
return false;
}
ipcarg_t phonehash;
if (ipc_connect_to_me(kbd_phone, SERVICE_CONSOLE, 0, 0, &phonehash) != 0) {
printf(NAME ": Failed to create callback from keyboard service\n");
return -1;
async_serialize_end();
return false;
}
async_set_pending(process_pending_input);
async_new_connection(phonehash, 0, NULL, keyboard_events);
/* Connect to framebuffer driver */
687,50 → 735,32
fb_info.phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_VIDEO, 0, 0);
if (fb_info.phone < 0) {
printf(NAME ": Failed to connect to video service\n");
async_serialize_end();
return -1;
}
/* Disable kernel output to the console */
__SYSCALL0(SYS_DEBUG_DISABLE_CONSOLE);
/* Register driver */
int rc = devmap_driver_register(NAME, client_connection);
if (rc < 0) {
printf(NAME ": Unable to register driver (%d)\n", rc);
async_serialize_end();
return false;
}
/* Initialize gcons */
gcons_init(fb_info.phone);
/* Synchronize, the gcons can have something in queue */
/* Synchronize, the gcons could put something in queue */
async_req_0_0(fb_info.phone, FB_FLUSH);
async_req_0_2(fb_info.phone, FB_GET_CSIZE, &fb_info.cols, &fb_info.rows);
async_req_0_2(fb_info.phone, FB_GET_CSIZE, &fb_info.rows,
&fb_info.cols);
set_rgb_color(DEFAULT_FOREGROUND, DEFAULT_BACKGROUND);
clrscr();
/* Init virtual consoles */
for (i = 0; i < CONSOLE_COUNT; i++) {
connections[i].used = 0;
keybuffer_init(&connections[i].keybuffer);
connections[i].keyrequests.head = 0;
connections[i].keyrequests.tail = 0;
connections[i].keyrequests.items = MAX_KEYREQUESTS_BUFFERED;
connections[i].keyrequest_counter = 0;
if (screenbuffer_init(&connections[i].screenbuffer,
fb_info.cols, fb_info.rows) == NULL) {
/* FIXME: handle error */
return -1;
}
}
connections[KERNEL_CONSOLE].used = 1;
/* Set up shared memory buffer. */
ib_size = sizeof(keyfield_t) * fb_info.cols * fb_info.rows;
size_t ib_size = sizeof(keyfield_t) * fb_info.cols * fb_info.rows;
interbuffer = as_get_mappable_page(ib_size);
fb_pending.cnt = 0;
if (as_area_create(interbuffer, ib_size, AS_AREA_READ |
AS_AREA_WRITE | AS_AREA_CACHEABLE) != interbuffer) {
AS_AREA_WRITE | AS_AREA_CACHEABLE) != interbuffer)
interbuffer = NULL;
}
if (interbuffer) {
if (ipc_share_out_start(fb_info.phone, interbuffer,
740,14 → 770,45
}
}
fb_pending.cnt = 0;
/* Inititalize consoles */
size_t i;
for (i = 0; i < CONSOLE_COUNT; i++) {
if (i != KERNEL_CONSOLE) {
if (screenbuffer_init(&consoles[i].scr,
fb_info.cols, fb_info.rows) == NULL) {
printf(NAME ": Unable to allocate screen buffer %u\n", i);
async_serialize_end();
return false;
}
screenbuffer_clear(&consoles[i].scr);
keybuffer_init(&consoles[i].keybuffer);
consoles[i].index = i;
consoles[i].refcount = 0;
char vc[MAX_DEVICE_NAME];
snprintf(vc, MAX_DEVICE_NAME, "vc%u", i);
if (devmap_device_register(vc, &consoles[i].dev_handle) != EOK) {
devmap_hangup_phone(DEVMAP_DRIVER);
printf(NAME ": Unable to register device %s\n", vc);
async_serialize_end();
return false;
}
}
}
/* Disable kernel output to the console */
__SYSCALL0(SYS_DEBUG_DISABLE_CONSOLE);
/* Initialize the screen */
gcons_redraw_console();
set_rgb_color(DEFAULT_FOREGROUND, DEFAULT_BACKGROUND);
screen_clear();
curs_goto(0, 0);
curs_visibility(
connections[active_console].screenbuffer.is_cursor_visible);
curs_visibility(active_console->scr.is_cursor_visible);
/* Register at NS */
if (ipc_connect_to_me(PHONE_NS, SERVICE_CONSOLE, 0, 0, &phonehash) != 0)
return -1;
/* Receive kernel notifications */
if (event_subscribe(EVENT_KCONSOLE, 0) != EOK)
printf(NAME ": Error registering kconsole notifications\n");
754,8 → 815,18
async_set_interrupt_received(interrupt_received);
// FIXME: avoid connectiong to itself, keep using klog
// printf(NAME ": Accepting connections\n");
async_serialize_end();
return true;
}
 
int main(int argc, char *argv[])
{
printf(NAME ": HelenOS Console service\n");
if (!console_init())
return -1;
printf(NAME ": Accepting connections\n");
async_manager();
return 0;
/branches/dd/uspace/srv/console/gcons.c
39,6 → 39,7
#include <sys/mman.h>
#include <string.h>
#include <align.h>
#include <bool.h>
 
#include "console.h"
#include "gcons.h"
54,8 → 55,9
 
#define MAIN_COLOR 0xffffff
 
static int use_gcons = 0;
static ipcarg_t xres,yres;
static bool use_gcons = false;
static ipcarg_t xres;
static ipcarg_t yres;
 
enum butstate {
CONS_DISCONNECTED = 0,
77,8 → 79,15
static int ic_pixmaps[CONS_LAST] = {-1, -1, -1, -1, -1, -1};
static int animation = -1;
 
static int active_console = 0;
static size_t active_console = 0;
 
size_t mouse_x;
size_t mouse_y;
 
bool btn_pressed;
size_t btn_x;
size_t btn_y;
 
static void vp_switch(int vp)
{
async_msg_1(fbphone, FB_VIEWPORT_SWITCH, vp);
85,8 → 94,7
}
 
/** Create view port */
static int vp_create(unsigned int x, unsigned int y, unsigned int width,
unsigned int height)
static int vp_create(size_t x, size_t y, size_t width, size_t height)
{
return async_req_2_0(fbphone, FB_VIEWPORT_CREATE, (x << 16) | y,
(width << 16) | height);
97,48 → 105,52
async_msg_0(fbphone, FB_CLEAR);
}
 
static void set_rgb_color(int fgcolor, int bgcolor)
static void set_rgb_color(uint32_t fgcolor, uint32_t bgcolor)
{
async_msg_2(fbphone, FB_SET_RGB_COLOR, fgcolor, bgcolor);
}
 
/** Transparent putchar */
static void tran_putch(char c, int row, int col)
static void tran_putch(wchar_t ch, size_t col, size_t row)
{
async_msg_3(fbphone, FB_PUTCHAR, c, row, col);
async_msg_3(fbphone, FB_PUTCHAR, ch, col, row);
}
 
/** Redraw the button showing state of a given console */
static void redraw_state(int consnum)
static void redraw_state(size_t index)
{
char data[5];
int i;
enum butstate state = console_state[consnum];
vp_switch(cstatus_vp[index]);
vp_switch(cstatus_vp[consnum]);
enum butstate state = console_state[index];
if (ic_pixmaps[state] != -1)
async_msg_2(fbphone, FB_VP_DRAW_PIXMAP, cstatus_vp[consnum],
async_msg_2(fbphone, FB_VP_DRAW_PIXMAP, cstatus_vp[index],
ic_pixmaps[state]);
if (state != CONS_DISCONNECTED && state != CONS_KERNEL &&
state != CONS_DISCONNECTED_SEL) {
snprintf(data, 5, "%d", consnum + 1);
for (i = 0; data[i]; i++)
tran_putch(data[i], 1, 2 + i);
if ((state != CONS_DISCONNECTED) && (state != CONS_KERNEL)
&& (state != CONS_DISCONNECTED_SEL)) {
char data[5];
snprintf(data, 5, "%u", index + 1);
size_t i;
for (i = 0; data[i] != 0; i++)
tran_putch(data[i], 2 + i, 1);
}
}
 
/** Notification run on changing console (except kernel console) */
void gcons_change_console(int consnum)
void gcons_change_console(size_t index)
{
int i;
if (!use_gcons)
return;
if (active_console == KERNEL_CONSOLE) {
size_t i;
for (i = 0; i < CONSOLE_COUNT; i++)
redraw_state(i);
if (animation != -1)
async_msg_1(fbphone, FB_ANIM_START, animation);
} else {
146,73 → 158,74
console_state[active_console] = CONS_DISCONNECTED;
else
console_state[active_console] = CONS_IDLE;
redraw_state(active_console);
}
active_console = consnum;
if (console_state[consnum] == CONS_DISCONNECTED) {
console_state[consnum] = CONS_DISCONNECTED_SEL;
redraw_state(consnum);
} else
console_state[consnum] = CONS_SELECTED;
redraw_state(consnum);
active_console = index;
if ((console_state[index] == CONS_DISCONNECTED)
|| (console_state[index] == CONS_DISCONNECTED_SEL))
console_state[index] = CONS_DISCONNECTED_SEL;
else
console_state[index] = CONS_SELECTED;
redraw_state(index);
vp_switch(console_vp);
}
 
/** Notification function that gets called on new output to virtual console */
void gcons_notify_char(int consnum)
void gcons_notify_char(size_t index)
{
if (!use_gcons)
return;
if ((consnum == active_console) ||
(console_state[consnum] == CONS_HAS_DATA))
if ((index == active_console)
|| (console_state[index] == CONS_HAS_DATA))
return;
console_state[consnum] = CONS_HAS_DATA;
console_state[index] = CONS_HAS_DATA;
if (active_console == KERNEL_CONSOLE)
return;
redraw_state(consnum);
redraw_state(index);
vp_switch(console_vp);
}
 
/** Notification function called on service disconnect from console */
void gcons_notify_disconnect(int consnum)
void gcons_notify_disconnect(size_t index)
{
if (!use_gcons)
return;
if (active_console == consnum)
console_state[consnum] = CONS_DISCONNECTED_SEL;
if (index == active_console)
console_state[index] = CONS_DISCONNECTED_SEL;
else
console_state[consnum] = CONS_DISCONNECTED;
console_state[index] = CONS_DISCONNECTED;
if (active_console == KERNEL_CONSOLE)
return;
redraw_state(consnum);
redraw_state(index);
vp_switch(console_vp);
}
 
/** Notification function called on console connect */
void gcons_notify_connect(int consnum)
void gcons_notify_connect(size_t index)
{
if (!use_gcons)
return;
if (active_console == consnum)
console_state[consnum] = CONS_SELECTED;
if (index == active_console)
console_state[index] = CONS_SELECTED;
else
console_state[consnum] = CONS_IDLE;
console_state[index] = CONS_IDLE;
if (active_console == KERNEL_CONSOLE)
return;
redraw_state(consnum);
redraw_state(index);
vp_switch(console_vp);
}
 
226,25 → 239,24
vp_switch(0);
}
 
/** Return x, where left <= x <= right && |a-x|==min(|a-x|) is smallest */
static inline int limit(int a, int left, int right)
/** Return x, where left <= x <= right && |a-x| == min(|a-x|) is smallest */
static inline int limit(size_t a, size_t left, size_t right)
{
if (a < left)
a = left;
if (a >= right)
a = right - 1;
return a;
}
 
int mouse_x, mouse_y;
int btn_pressed, btn_x, btn_y;
 
/** Handle mouse move
*
* @param dx Delta X of mouse move
* @param dy Delta Y of mouse move
*/
void gcons_mouse_move(int dx, int dy)
void gcons_mouse_move(ssize_t dx, ssize_t dy)
{
mouse_x = limit(mouse_x + dx, 0, xres);
mouse_y = limit(mouse_y + dy, 0, yres);
272,9 → 284,9
 
/** Handle mouse click
*
* @param state New state (1-pressed, 0-depressed)
* @param state New state (true - pressed, false - depressed)
*/
int gcons_mouse_btn(int state)
int gcons_mouse_btn(bool state)
{
int conbut;
281,7 → 293,7
if (state) {
conbut = gcons_find_conbut(mouse_x, mouse_y);
if (conbut != -1) {
btn_pressed = 1;
btn_pressed = true;
btn_x = mouse_x;
btn_y = mouse_y;
}
291,7 → 303,7
if ((!state) && (!btn_pressed))
return -1;
btn_pressed = 0;
btn_pressed = false;
conbut = gcons_find_conbut(mouse_x, mouse_y);
if (conbut == gcons_find_conbut(btn_x, btn_y))
373,9 → 385,11
*
* @param data PPM data
* @param size PPM data size
*
* @return Pixmap identification
*
*/
static int make_pixmap(char *data, int size)
static int make_pixmap(char *data, size_t size)
{
char *shm;
int rc;
464,13 → 478,9
/** Initialize nice graphical console environment */
void gcons_init(int phone)
{
int rc;
int i;
int status_start = STATUS_START;
fbphone = phone;
rc = async_req_0_2(phone, FB_GET_RESOLUTION, &xres, &yres);
int rc = async_req_0_2(phone, FB_GET_RESOLUTION, &xres, &yres);
if (rc)
return;
483,17 → 493,21
console_vp = vp_create(CONSOLE_MARGIN, CONSOLE_TOP,
ALIGN_DOWN(xres - 2 * CONSOLE_MARGIN, 8),
ALIGN_DOWN(yres - (CONSOLE_TOP + CONSOLE_MARGIN), 16));
if (console_vp < 0)
return;
/* Create status buttons */
status_start += (xres - 800) / 2;
size_t status_start = STATUS_START + (xres - 800) / 2;
size_t i;
for (i = 0; i < CONSOLE_COUNT; i++) {
cstatus_vp[i] = vp_create(status_start + CONSOLE_MARGIN +
i * (STATUS_WIDTH + STATUS_SPACE), STATUS_TOP,
STATUS_WIDTH, STATUS_HEIGHT);
if (cstatus_vp[i] < 0)
return;
vp_switch(cstatus_vp[i]);
set_rgb_color(0x202020, 0xffffff);
}
501,27 → 515,28
/* Initialize icons */
ic_pixmaps[CONS_SELECTED] =
make_pixmap(_binary_gfx_cons_selected_ppm_start,
(int) &_binary_gfx_cons_selected_ppm_size);
(size_t) &_binary_gfx_cons_selected_ppm_size);
ic_pixmaps[CONS_IDLE] =
make_pixmap(_binary_gfx_cons_idle_ppm_start,
(int) &_binary_gfx_cons_idle_ppm_size);
(size_t) &_binary_gfx_cons_idle_ppm_size);
ic_pixmaps[CONS_HAS_DATA] =
make_pixmap(_binary_gfx_cons_has_data_ppm_start,
(int) &_binary_gfx_cons_has_data_ppm_size);
(size_t) &_binary_gfx_cons_has_data_ppm_size);
ic_pixmaps[CONS_DISCONNECTED] =
make_pixmap(_binary_gfx_cons_idle_ppm_start,
(int) &_binary_gfx_cons_idle_ppm_size);
(size_t) &_binary_gfx_cons_idle_ppm_size);
ic_pixmaps[CONS_KERNEL] =
make_pixmap(_binary_gfx_cons_kernel_ppm_start,
(int) &_binary_gfx_cons_kernel_ppm_size);
(size_t) &_binary_gfx_cons_kernel_ppm_size);
ic_pixmaps[CONS_DISCONNECTED_SEL] = ic_pixmaps[CONS_SELECTED];
make_anim();
use_gcons = 1;
use_gcons = true;
console_state[0] = CONS_DISCONNECTED_SEL;
console_state[KERNEL_CONSOLE] = CONS_KERNEL;
gcons_redraw_console();
vp_switch(console_vp);
}
 
/** @}
/branches/dd/uspace/srv/console/screenbuffer.c
33,7 → 33,7
*/
 
#include <screenbuffer.h>
#include <console/style.h>
#include <io/style.h>
#include <malloc.h>
#include <unistd.h>
 
66,7 → 66,7
* @return Pointer to screenbuffer (same as scr parameter) or NULL
*
*/
screenbuffer_t *screenbuffer_init(screenbuffer_t *scr, int size_x, int size_y)
screenbuffer_t *screenbuffer_init(screenbuffer_t *scr, size_t size_x, size_t size_y)
{
scr->buffer = (keyfield_t *) malloc(sizeof(keyfield_t) * size_x * size_y);
if (!scr->buffer)
90,7 → 90,7
*/
void screenbuffer_clear(screenbuffer_t *scr)
{
unsigned int i;
size_t i;
for (i = 0; i < (scr->size_x * scr->size_y); i++) {
scr->buffer[i].character = ' ';
98,8 → 98,8
}
scr->top_line = 0;
scr->position_x = 0;
scr->position_y = 0;
scr->position_x = 0;
}
 
/** Clear one buffer line.
108,13 → 108,13
* @param line One buffer line (not a screen line!)
*
*/
void screenbuffer_clear_line(screenbuffer_t *scr, unsigned int line)
void screenbuffer_clear_line(screenbuffer_t *scr, size_t line)
{
unsigned int i;
size_t x;
for (i = 0; i < scr->size_x; i++) {
scr->buffer[i + line * scr->size_x].character = ' ';
scr->buffer[i + line * scr->size_x].attrs = scr->attrs;
for (x = 0; x < scr->size_x; x++) {
scr->buffer[x + line * scr->size_x].character = ' ';
scr->buffer[x + line * scr->size_x].attrs = scr->attrs;
}
}
 
124,11 → 124,11
* @param dest Destination
*
*/
void screenbuffer_copy_buffer(screenbuffer_t *scr, keyfield_t *dest)
void screenbuffer_copy_buffer(screenbuffer_t *scr, keyfield_t *dest)
{
unsigned int i;
size_t i;
for (i = 0; i < scr->size_x * scr->size_y; i++)
for (i = 0; i < (scr->size_x * scr->size_y); i++)
dest[i] = scr->buffer[i];
}
 
139,7 → 139,7
* @param y
*
*/
void screenbuffer_goto(screenbuffer_t *scr, unsigned int x, unsigned int y)
void screenbuffer_goto(screenbuffer_t *scr, size_t x, size_t y)
{
scr->position_x = x % scr->size_x;
scr->position_y = y % scr->size_y;
152,7 → 152,7
* @param bg_color
*
*/
void screenbuffer_set_style(screenbuffer_t *scr, int style)
void screenbuffer_set_style(screenbuffer_t *scr, uint8_t style)
{
scr->attrs.t = at_style;
scr->attrs.a.s.style = style;
165,7 → 165,7
* @param bg_color
*
*/
void screenbuffer_set_color(screenbuffer_t *scr, unsigned int fg_color, unsigned int bg_color, unsigned int flags)
void screenbuffer_set_color(screenbuffer_t *scr, uint8_t fg_color, uint8_t bg_color, uint8_t flags)
{
scr->attrs.t = at_idx;
scr->attrs.a.i.fg_color = fg_color;
180,7 → 180,7
* @param bg_color
*
*/
void screenbuffer_set_rgb_color(screenbuffer_t *scr, unsigned int fg_color, unsigned int bg_color)
void screenbuffer_set_rgb_color(screenbuffer_t *scr, uint32_t fg_color, uint32_t bg_color)
{
scr->attrs.t = at_rgb;
scr->attrs.a.r.fg_color = fg_color;
/branches/dd/uspace/srv/console/Makefile
46,7 → 46,7
GENERIC_SOURCES = \
console.c \
screenbuffer.c \
../kbd/generic/key_buffer.c \
../kbd/generic/keybuffer.c \
gcons.c
 
IMAGES = \
/branches/dd/uspace/srv/bd/file_bd/file_bd.c
0,0 → 1,217
/*
* Copyright (c) 2009 Jiri Svoboda
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup bd
* @{
*/
 
/**
* @file
* @brief File-backed block device driver
*
* Allows accessing a file as a block device. Useful for, e.g., mounting
* a disk image.
*/
 
#include <stdio.h>
#include <unistd.h>
#include <ipc/ipc.h>
#include <ipc/bd.h>
#include <async.h>
#include <as.h>
#include <futex.h>
#include <devmap.h>
#include <sys/types.h>
#include <errno.h>
#include <bool.h>
 
#define NAME "file_bd"
 
static size_t comm_size;
static FILE *img;
 
static dev_handle_t dev_handle;
static atomic_t dev_futex = FUTEX_INITIALIZER;
 
static int file_bd_init(const char *fname);
static void file_bd_connection(ipc_callid_t iid, ipc_call_t *icall);
static int file_bd_read(off_t blk_idx, off_t size, void *buf);
static int file_bd_write(off_t blk_idx, off_t size, void *buf);
 
int main(int argc, char **argv)
{
int rc;
 
printf(NAME ": File-backed block device driver\n");
 
if (argc != 3) {
printf("Expected two arguments (image name, device name).\n");
return -1;
}
 
if (file_bd_init(argv[1]) != EOK)
return -1;
 
rc = devmap_device_register(argv[2], &dev_handle);
if (rc != EOK) {
devmap_hangup_phone(DEVMAP_DRIVER);
printf(NAME ": Unable to register device %s.\n",
argv[2]);
return rc;
}
 
printf(NAME ": Accepting connections\n");
async_manager();
 
/* Not reached */
return 0;
}
 
static int file_bd_init(const char *fname)
{
int rc;
 
rc = devmap_driver_register(NAME, file_bd_connection);
if (rc < 0) {
printf(NAME ": Unable to register driver.\n");
return rc;
}
 
img = fopen(fname, "rb+");
if (img == NULL)
return EINVAL;
 
return EOK;
}
 
static void file_bd_connection(ipc_callid_t iid, ipc_call_t *icall)
{
void *fs_va = NULL;
ipc_callid_t callid;
ipc_call_t call;
ipcarg_t method;
int flags;
int retval;
off_t idx;
off_t size;
 
/* Answer the IPC_M_CONNECT_ME_TO call. */
ipc_answer_0(iid, EOK);
 
if (!ipc_share_out_receive(&callid, &comm_size, &flags)) {
ipc_answer_0(callid, EHANGUP);
return;
}
 
fs_va = as_get_mappable_page(comm_size);
if (fs_va == NULL) {
ipc_answer_0(callid, EHANGUP);
return;
}
 
(void) ipc_share_out_finalize(callid, fs_va);
 
while (1) {
callid = async_get_call(&call);
method = IPC_GET_METHOD(call);
switch (method) {
case IPC_M_PHONE_HUNGUP:
/* The other side has hung up. */
ipc_answer_0(callid, EOK);
return;
case BD_READ_BLOCK:
case BD_WRITE_BLOCK:
idx = IPC_GET_ARG1(call);
size = IPC_GET_ARG2(call);
if (size > comm_size) {
retval = EINVAL;
break;
}
if (method == BD_READ_BLOCK)
retval = file_bd_read(idx, size, fs_va);
else
retval = file_bd_write(idx, size, fs_va);
break;
default:
retval = EINVAL;
break;
}
ipc_answer_0(callid, retval);
}
}
 
static int file_bd_read(off_t blk_idx, off_t size, void *buf)
{
size_t n_rd;
 
printf("file_bd_read\n");
futex_down(&dev_futex);
 
printf("seek\n");
fseek(img, blk_idx * size, SEEK_SET);
printf("read\n");
n_rd = fread(buf, 1, size, img);
printf("done\n");
 
printf("done\n");
 
if (ferror(img)) {
futex_up(&dev_futex);
return EIO; /* Read error */
}
 
futex_up(&dev_futex);
 
if (n_rd < size)
return EINVAL; /* Read beyond end of disk */
 
return EOK;
}
 
static int file_bd_write(off_t blk_idx, off_t size, void *buf)
{
size_t n_wr;
 
futex_down(&dev_futex);
 
fseek(img, blk_idx * size, SEEK_SET);
n_wr = fread(buf, 1, size, img);
 
if (ferror(img) || n_wr < size) {
futex_up(&dev_futex);
return EIO; /* Write error */
}
 
futex_up(&dev_futex);
 
return EOK;
}
 
/**
* @}
*/
/branches/dd/uspace/srv/bd/file_bd/Makefile
0,0 → 1,76
#
# Copyright (c) 2006 Martin Decky
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# - Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# - The name of the author may not be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
 
## Setup toolchain
#
 
 
LIBC_PREFIX = ../../../lib/libc
SOFTINT_PREFIX = ../../../lib/softint
 
include $(LIBC_PREFIX)/Makefile.toolchain
 
LIBS = $(LIBC_PREFIX)/libc.a
 
## Sources
#
 
OUTPUT = file_bd
SOURCES = \
file_bd.c
 
OBJECTS := $(addsuffix .o,$(basename $(SOURCES)))
 
.PHONY: all clean depend disasm
 
all: $(OUTPUT) $(OUTPUT).disasm
 
-include Makefile.depend
 
clean:
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend $(OBJECTS)
 
depend:
$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend
 
$(OUTPUT): $(OBJECTS) $(LIBS)
$(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map
 
disasm: $(OUTPUT).disasm
 
$(OUTPUT).disasm: $(OUTPUT)
$(OBJDUMP) -d $< > $@
 
%.o: %.S
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
 
%.o: %.s
$(AS) $(AFLAGS) $< -o $@
 
%.o: %.c
$(CC) $(DEFS) $(CFLAGS) -c $< -o $@
/branches/dd/uspace/srv/bd/gxe_bd/gxe_bd.c
58,6 → 58,10
STATUS_FAILURE = 0
};
 
enum {
MAX_DISKS = 2
};
 
typedef struct {
uint32_t offset_lo;
uint32_t pad0;
72,17 → 76,12
 
uint32_t status;
 
/* FIXME: Need to fix pio_enable() to support >= page_size areas.
 
uint32_t pad4[3];
uint32_t pad5[0x3fc0];
uint8_t pad5[0x3fc0];
 
uint8_t buffer[512];*/
uint8_t buffer[512];
} gxe_bd_t;
 
typedef struct {
uint8_t buffer[512];
} gxe_buf_t;
 
static const size_t block_size = 512;
static size_t comm_size;
89,17 → 88,19
 
static uintptr_t dev_physical = 0x13000000;
static gxe_bd_t *dev;
static gxe_buf_t *devbuf;
 
static uint32_t disk_id = 0;
static dev_handle_t dev_handle[MAX_DISKS];
 
static atomic_t dev_futex = FUTEX_INITIALIZER;
 
static int gxe_bd_init(void);
static void gxe_bd_connection(ipc_callid_t iid, ipc_call_t *icall);
static int gx_bd_rdwr(ipcarg_t method, off_t offset, off_t size, void *buf);
static int gxe_bd_read_block(uint64_t offset, size_t size, void *buf);
static int gxe_bd_write_block(uint64_t offset, size_t size, const void *buf);
static int gx_bd_rdwr(int disk_id, ipcarg_t method, off_t offset, off_t size,
void *buf);
static int gxe_bd_read_block(int disk_id, uint64_t offset, size_t size,
void *buf);
static int gxe_bd_write_block(int disk_id, uint64_t offset, size_t size,
const void *buf);
 
int main(int argc, char **argv)
{
117,9 → 118,9
 
static int gxe_bd_init(void)
{
dev_handle_t dev_handle;
void *vaddr;
int rc;
int rc, i;
char name[16];
 
rc = devmap_driver_register(NAME, gxe_bd_connection);
if (rc < 0) {
135,21 → 136,17
 
dev = vaddr;
 
rc = pio_enable((void *) dev_physical + 0x4000, sizeof(gxe_buf_t), &vaddr);
if (rc != EOK) {
printf(NAME ": Could not initialize device I/O space.\n");
return rc;
for (i = 0; i < MAX_DISKS; i++) {
snprintf(name, 16, "disk%d", i);
rc = devmap_device_register(name, &dev_handle[i]);
if (rc != EOK) {
devmap_hangup_phone(DEVMAP_DRIVER);
printf(NAME ": Unable to register device %s.\n",
name);
return rc;
}
}
 
devbuf = vaddr;
 
rc = devmap_device_register("disk0", &dev_handle);
if (rc != EOK) {
devmap_hangup_phone(DEVMAP_DRIVER);
printf(NAME ": Unable to register device.\n");
return rc;
}
 
return EOK;
}
 
159,11 → 156,27
ipc_callid_t callid;
ipc_call_t call;
ipcarg_t method;
dev_handle_t dh;
int flags;
int retval;
off_t idx;
off_t size;
int disk_id, i;
 
/* Get the device handle. */
dh = IPC_GET_ARG1(*icall);
 
/* Determine which disk device is the client connecting to. */
disk_id = -1;
for (i = 0; i < MAX_DISKS; i++)
if (dev_handle[i] == dh)
disk_id = i;
 
if (disk_id < 0) {
ipc_answer_0(iid, EINVAL);
return;
}
 
/* Answer the IPC_M_CONNECT_ME_TO call. */
ipc_answer_0(iid, EOK);
 
196,7 → 209,8
retval = EINVAL;
break;
}
retval = gx_bd_rdwr(method, idx * size, size, fs_va);
retval = gx_bd_rdwr(disk_id, method, idx * size,
size, fs_va);
break;
default:
retval = EINVAL;
206,7 → 220,8
}
}
 
static int gx_bd_rdwr(ipcarg_t method, off_t offset, off_t size, void *buf)
static int gx_bd_rdwr(int disk_id, ipcarg_t method, off_t offset, off_t size,
void *buf)
{
int rc;
size_t now;
215,9 → 230,9
now = size < block_size ? size : block_size;
 
if (method == BD_READ_BLOCK)
rc = gxe_bd_read_block(offset, now, buf);
rc = gxe_bd_read_block(disk_id, offset, now, buf);
else
rc = gxe_bd_write_block(offset, now, buf);
rc = gxe_bd_write_block(disk_id, offset, now, buf);
 
if (rc != EOK)
return rc;
234,7 → 249,8
return EOK;
}
 
static int gxe_bd_read_block(uint64_t offset, size_t size, void *buf)
static int gxe_bd_read_block(int disk_id, uint64_t offset, size_t size,
void *buf)
{
uint32_t status;
size_t i;
252,8 → 268,7
}
 
for (i = 0; i < size; i++) {
((uint8_t *) buf)[i] = w =
pio_read_8(&devbuf->buffer[i]);
((uint8_t *) buf)[i] = w = pio_read_8(&dev->buffer[i]);
}
 
futex_up(&dev_futex);
260,14 → 275,14
return EOK;
}
 
static int gxe_bd_write_block(uint64_t offset, size_t size, const void *buf)
static int gxe_bd_write_block(int disk_id, uint64_t offset, size_t size,
const void *buf)
{
uint32_t status;
size_t i;
uint32_t w;
 
for (i = 0; i < size; i++) {
pio_write_8(&devbuf->buffer[i], ((const uint8_t *) buf)[i]);
pio_write_8(&dev->buffer[i], ((const uint8_t *) buf)[i]);
}
 
futex_down(&dev_futex);
/branches/dd/uspace/srv/bd/ata_bd/ata_bd.c
0,0 → 1,440
/*
* Copyright (c) 2009 Jiri Svoboda
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup bd
* @{
*/
 
/**
* @file
* @brief ATA disk driver
*
* This driver currently works only with CHS addressing and uses PIO.
* Currently based on the (now obsolete) ANSI X3.221-1994 (ATA-1) standard.
* At this point only reading is possible, not writing.
*/
 
#include <stdio.h>
#include <libarch/ddi.h>
#include <ddi.h>
#include <ipc/ipc.h>
#include <ipc/bd.h>
#include <async.h>
#include <as.h>
#include <futex.h>
#include <devmap.h>
#include <sys/types.h>
#include <errno.h>
#include <bool.h>
 
#include "ata_bd.h"
 
#define NAME "ata_bd"
 
static const size_t block_size = 512;
static size_t comm_size;
 
static uintptr_t cmd_physical = 0x1f0;
static uintptr_t ctl_physical = 0x170;
static ata_cmd_t *cmd;
static ata_ctl_t *ctl;
 
static dev_handle_t dev_handle[MAX_DISKS];
 
static atomic_t dev_futex = FUTEX_INITIALIZER;
 
static disk_t disk[MAX_DISKS];
 
static int ata_bd_init(void);
static void ata_bd_connection(ipc_callid_t iid, ipc_call_t *icall);
static int ata_bd_rdwr(int disk_id, ipcarg_t method, off_t offset, off_t size,
void *buf);
static int ata_bd_read_block(int disk_id, uint64_t blk_idx, size_t blk_cnt,
void *buf);
static int ata_bd_write_block(int disk_id, uint64_t blk_idx, size_t blk_cnt,
const void *buf);
static int drive_identify(int drive_id, disk_t *d);
 
int main(int argc, char **argv)
{
uint8_t status;
char name[16];
int i, rc;
int n_disks;
 
printf(NAME ": ATA disk driver\n");
 
printf("cmd_physical = 0x%x\n", cmd_physical);
printf("ctl_physical = 0x%x\n", ctl_physical);
 
if (ata_bd_init() != EOK)
return -1;
 
/* Put drives to reset, disable interrupts. */
printf("Reset drives...\n");
pio_write_8(&ctl->device_control, DCR_SRST);
/* FIXME: Find out how to do this properly. */
async_usleep(100);
pio_write_8(&ctl->device_control, 0);
 
do {
status = pio_read_8(&cmd->status);
} while ((status & SR_BSY) != 0);
printf("Done\n");
 
printf("Status = 0x%x\n", pio_read_8(&cmd->status));
 
(void) drive_identify(0, &disk[0]);
(void) drive_identify(1, &disk[1]);
 
n_disks = 0;
 
for (i = 0; i < MAX_DISKS; i++) {
/* Skip unattached drives. */
if (disk[i].present == false)
continue;
 
snprintf(name, 16, "disk%d", i);
rc = devmap_device_register(name, &dev_handle[i]);
if (rc != EOK) {
devmap_hangup_phone(DEVMAP_DRIVER);
printf(NAME ": Unable to register device %s.\n",
name);
return rc;
}
++n_disks;
}
 
if (n_disks == 0) {
printf("No disks detected.\n");
return -1;
}
 
printf(NAME ": Accepting connections\n");
async_manager();
 
/* Not reached */
return 0;
}
 
static int drive_identify(int disk_id, disk_t *d)
{
uint16_t data;
uint8_t status;
int i;
 
printf("Identify drive %d\n", disk_id);
pio_write_8(&cmd->drive_head, ((disk_id != 0) ? DHR_DRV : 0));
async_usleep(100);
pio_write_8(&cmd->command, CMD_IDENTIFY_DRIVE);
 
status = pio_read_8(&cmd->status);
printf("Status = 0x%x\n", status);
 
d->present = false;
 
/*
* Detect if drive is present. This is Qemu only! Need to
* do the right thing to work with real drives.
*/
if ((status & SR_DRDY) == 0) {
printf("None attached.\n");
return ENOENT;
}
 
for (i = 0; i < block_size / 2; i++) {
do {
status = pio_read_8(&cmd->status);
} while ((status & SR_DRDY) == 0);
 
data = pio_read_16(&cmd->data_port);
 
switch (i) {
case 1: d->cylinders = data; break;
case 3: d->heads = data; break;
case 6: d->sectors = data; break;
}
}
 
printf("\n\nStatus = 0x%x\n", pio_read_8(&cmd->status));
 
d->blocks = d->cylinders * d->heads * d->sectors;
 
printf("Geometry: %u cylinders, %u heads, %u sectors\n",
d->cylinders, d->heads, d->sectors);
 
d->present = true;
 
return EOK;
}
 
static int ata_bd_init(void)
{
void *vaddr;
int rc;
 
rc = devmap_driver_register(NAME, ata_bd_connection);
if (rc < 0) {
printf(NAME ": Unable to register driver.\n");
return rc;
}
 
rc = pio_enable((void *) cmd_physical, sizeof(ata_cmd_t), &vaddr);
if (rc != EOK) {
printf(NAME ": Could not initialize device I/O space.\n");
return rc;
}
 
cmd = vaddr;
 
rc = pio_enable((void *) ctl_physical, sizeof(ata_ctl_t), &vaddr);
if (rc != EOK) {
printf(NAME ": Could not initialize device I/O space.\n");
return rc;
}
 
ctl = vaddr;
 
 
return EOK;
}
 
static void ata_bd_connection(ipc_callid_t iid, ipc_call_t *icall)
{
void *fs_va = NULL;
ipc_callid_t callid;
ipc_call_t call;
ipcarg_t method;
dev_handle_t dh;
int flags;
int retval;
off_t idx;
off_t size;
int disk_id, i;
 
/* Get the device handle. */
dh = IPC_GET_ARG1(*icall);
 
/* Determine which disk device is the client connecting to. */
disk_id = -1;
for (i = 0; i < MAX_DISKS; i++)
if (dev_handle[i] == dh)
disk_id = i;
 
if (disk_id < 0 || disk[disk_id].present == false) {
ipc_answer_0(iid, EINVAL);
return;
}
 
/* Answer the IPC_M_CONNECT_ME_TO call. */
ipc_answer_0(iid, EOK);
 
if (!ipc_share_out_receive(&callid, &comm_size, &flags)) {
ipc_answer_0(callid, EHANGUP);
return;
}
 
fs_va = as_get_mappable_page(comm_size);
if (fs_va == NULL) {
ipc_answer_0(callid, EHANGUP);
return;
}
 
(void) ipc_share_out_finalize(callid, fs_va);
 
while (1) {
callid = async_get_call(&call);
method = IPC_GET_METHOD(call);
switch (method) {
case IPC_M_PHONE_HUNGUP:
/* The other side has hung up. */
ipc_answer_0(callid, EOK);
return;
case BD_READ_BLOCK:
case BD_WRITE_BLOCK:
idx = IPC_GET_ARG1(call);
size = IPC_GET_ARG2(call);
if (size > comm_size) {
retval = EINVAL;
break;
}
retval = ata_bd_rdwr(disk_id, method, idx,
size, fs_va);
break;
default:
retval = EINVAL;
break;
}
ipc_answer_0(callid, retval);
}
}
 
static int ata_bd_rdwr(int disk_id, ipcarg_t method, off_t blk_idx, off_t size,
void *buf)
{
int rc;
off_t now;
 
while (size > 0) {
now = size < block_size ? size : (off_t) block_size;
if (now != block_size)
return EINVAL;
 
if (method == BD_READ_BLOCK)
rc = ata_bd_read_block(disk_id, blk_idx, 1, buf);
else
rc = ata_bd_write_block(disk_id, blk_idx, 1, buf);
 
if (rc != EOK)
return rc;
 
buf += block_size;
blk_idx++;
 
if (size > block_size)
size -= block_size;
else
size = 0;
}
 
return EOK;
}
 
 
static int ata_bd_read_block(int disk_id, uint64_t blk_idx, size_t blk_cnt,
void *buf)
{
size_t i;
uint16_t data;
uint8_t status;
uint64_t c, h, s;
uint64_t idx;
uint8_t drv_head;
disk_t *d;
 
d = &disk[disk_id];
 
/* Check device bounds. */
if (blk_idx >= d->blocks)
return EINVAL;
 
/* Compute CHS. */
c = blk_idx / (d->heads * d->sectors);
idx = blk_idx % (d->heads * d->sectors);
 
h = idx / d->sectors;
s = 1 + (idx % d->sectors);
 
/* New value for Drive/Head register */
drv_head =
((disk_id != 0) ? DHR_DRV : 0) |
(h & 0x0f);
 
futex_down(&dev_futex);
 
/* Program a Read Sectors operation. */
 
pio_write_8(&cmd->drive_head, drv_head);
pio_write_8(&cmd->sector_count, 1);
pio_write_8(&cmd->sector_number, s);
pio_write_8(&cmd->cylinder_low, c & 0xff);
pio_write_8(&cmd->cylinder_high, c >> 16);
pio_write_8(&cmd->command, CMD_READ_SECTORS);
 
/* Read data from the disk buffer. */
 
for (i = 0; i < block_size / 2; i++) {
do {
status = pio_read_8(&cmd->status);
} while ((status & SR_DRDY) == 0);
 
data = pio_read_16(&cmd->data_port);
((uint16_t *) buf)[i] = data;
}
 
futex_up(&dev_futex);
return EOK;
}
 
static int ata_bd_write_block(int disk_id, uint64_t blk_idx, size_t blk_cnt,
const void *buf)
{
size_t i;
uint8_t status;
uint64_t c, h, s;
uint64_t idx;
uint8_t drv_head;
disk_t *d;
 
d = &disk[disk_id];
 
/* Check device bounds. */
if (blk_idx >= d->blocks)
return EINVAL;
 
/* Compute CHS. */
c = blk_idx / (d->heads * d->sectors);
idx = blk_idx % (d->heads * d->sectors);
 
h = idx / d->sectors;
s = 1 + (idx % d->sectors);
 
/* New value for Drive/Head register */
drv_head =
((disk_id != 0) ? DHR_DRV : 0) |
(h & 0x0f);
 
futex_down(&dev_futex);
 
/* Program a Read Sectors operation. */
 
pio_write_8(&cmd->drive_head, drv_head);
pio_write_8(&cmd->sector_count, 1);
pio_write_8(&cmd->sector_number, s);
pio_write_8(&cmd->cylinder_low, c & 0xff);
pio_write_8(&cmd->cylinder_high, c >> 16);
pio_write_8(&cmd->command, CMD_WRITE_SECTORS);
 
/* Write data to the disk buffer. */
 
for (i = 0; i < block_size / 2; i++) {
do {
status = pio_read_8(&cmd->status);
} while ((status & SR_DRDY) == 0);
 
pio_write_16(&cmd->data_port, ((uint16_t *) buf)[i]);
}
 
futex_up(&dev_futex);
return EOK;
}
 
 
/**
* @}
*/
/branches/dd/uspace/srv/bd/ata_bd/ata_bd.h
0,0 → 1,137
/*
* Copyright (c) 2009 Jiri Svoboda
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup bd
* @{
*/
/** @file
*/
 
#ifndef __ATA_BD_H__
#define __ATA_BD_H__
 
#include <sys/types.h>
 
enum {
CTL_READ_START = 0,
CTL_WRITE_START = 1,
};
 
enum {
STATUS_FAILURE = 0
};
 
enum {
MAX_DISKS = 2
};
 
typedef union {
/* Read */
struct {
uint8_t data_port;
uint8_t error;
uint8_t sector_count;
uint8_t sector_number;
uint8_t cylinder_low;
uint8_t cylinder_high;
uint8_t drive_head;
uint8_t status;
};
 
/* Write */
struct {
uint8_t pad0[7];
uint8_t command;
};
} ata_cmd_t;
 
typedef union {
/* Read */
struct {
uint8_t pad0[6];
uint8_t alt_status;
uint8_t drive_address;
};
 
/* Write */
struct {
uint8_t pad1[6];
uint8_t device_control;
uint8_t pad2;
};
} ata_ctl_t;
 
enum devctl_bits {
DCR_SRST = 0x04, /**< Software Reset */
DCR_nIEN = 0x02 /**< Interrupt Enable (negated) */
};
 
enum status_bits {
SR_BSY = 0x80, /**< Busy */
SR_DRDY = 0x40, /**< Drive Ready */
SR_DWF = 0x20, /**< Drive Write Fault */
SR_DSC = 0x10, /**< Drive Seek Complete */
SR_DRQ = 0x08, /**< Data Request */
SR_CORR = 0x04, /**< Corrected Data */
SR_IDX = 0x02, /**< Index */
SR_ERR = 0x01 /**< Error */
};
 
enum drive_head_bits {
DHR_DRV = 0x10
};
 
enum error_bits {
ER_BBK = 0x80, /**< Bad Block Detected */
ER_UNC = 0x40, /**< Uncorrectable Data Error */
ER_MC = 0x20, /**< Media Changed */
ER_IDNF = 0x10, /**< ID Not Found */
ER_MCR = 0x08, /**< Media Change Request */
ER_ABRT = 0x04, /**< Aborted Command */
ER_TK0NF = 0x02, /**< Track 0 Not Found */
ER_AMNF = 0x01 /**< Address Mark Not Found */
};
 
enum ata_command {
CMD_IDENTIFY_DRIVE = 0xEC,
CMD_READ_SECTORS = 0x20,
CMD_WRITE_SECTORS = 0x30
};
 
typedef struct {
bool present;
unsigned heads;
unsigned cylinders;
unsigned sectors;
uint64_t blocks;
} disk_t;
 
#endif
 
/** @}
*/
/branches/dd/uspace/srv/bd/ata_bd/Makefile
0,0 → 1,76
#
# Copyright (c) 2006 Martin Decky
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# - Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# - The name of the author may not be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
 
## Setup toolchain
#
 
 
LIBC_PREFIX = ../../../lib/libc
SOFTINT_PREFIX = ../../../lib/softint
 
include $(LIBC_PREFIX)/Makefile.toolchain
 
LIBS = $(LIBC_PREFIX)/libc.a
 
## Sources
#
 
OUTPUT = ata_bd
SOURCES = \
ata_bd.c
 
OBJECTS := $(addsuffix .o,$(basename $(SOURCES)))
 
.PHONY: all clean depend disasm
 
all: $(OUTPUT) $(OUTPUT).disasm
 
-include Makefile.depend
 
clean:
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend $(OBJECTS)
 
depend:
$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend
 
$(OUTPUT): $(OBJECTS) $(LIBS)
$(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map
 
disasm: $(OUTPUT).disasm
 
$(OUTPUT).disasm: $(OUTPUT)
$(OBJDUMP) -d $< > $@
 
%.o: %.S
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
 
%.o: %.s
$(AS) $(AFLAGS) $< -o $@
 
%.o: %.c
$(CC) $(DEFS) $(CFLAGS) -c $< -o $@
/branches/dd/uspace/srv/loader/main.c
53,9 → 53,9
#include <ipc/services.h>
#include <ipc/loader.h>
#include <loader/pcb.h>
#include <console.h>
#include <errno.h>
#include <async.h>
#include <string.h>
#include <as.h>
 
#include <elf.h>
76,6 → 76,13
/** Buffer holding all arguments */
static char *arg_buf = NULL;
 
/** Number of preset files */
static int filc = 0;
/** Preset files vector */
static char **filv = NULL;
/** Buffer holding all preset files */
static fdi_node_t *fil_buf = NULL;
 
static elf_info_t prog_info;
static elf_info_t interp_info;
 
84,7 → 91,7
/** Used to limit number of connections to one. */
static bool connected;
 
static void loader_get_taskid(ipc_callid_t rid, ipc_call_t *request)
static void ldr_get_taskid(ipc_callid_t rid, ipc_call_t *request)
{
ipc_callid_t callid;
task_id_t task_id;
111,7 → 118,7
* @param rid
* @param request
*/
static void loader_set_pathname(ipc_callid_t rid, ipc_call_t *request)
static void ldr_set_pathname(ipc_callid_t rid, ipc_call_t *request)
{
ipc_callid_t callid;
size_t len;
147,7 → 154,7
* @param rid
* @param request
*/
static void loader_set_args(ipc_callid_t rid, ipc_call_t *request)
static void ldr_set_args(ipc_callid_t rid, ipc_call_t *request)
{
ipc_callid_t callid;
size_t buf_size, arg_size;
220,6 → 227,70
ipc_answer_0(rid, EOK);
}
 
/** Receive a call setting preset files of the program to execute.
*
* @param rid
* @param request
*/
static void ldr_set_files(ipc_callid_t rid, ipc_call_t *request)
{
ipc_callid_t callid;
size_t buf_size;
if (!ipc_data_write_receive(&callid, &buf_size)) {
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
return;
}
if ((buf_size % sizeof(fdi_node_t)) != 0) {
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
return;
}
if (fil_buf != NULL) {
free(fil_buf);
fil_buf = NULL;
}
if (filv != NULL) {
free(filv);
filv = NULL;
}
fil_buf = malloc(buf_size);
if (!fil_buf) {
ipc_answer_0(callid, ENOMEM);
ipc_answer_0(rid, ENOMEM);
return;
}
ipc_data_write_finalize(callid, fil_buf, buf_size);
int count = buf_size / sizeof(fdi_node_t);
/* Allocate filvv */
filv = malloc((count + 1) * sizeof(fdi_node_t *));
if (filv == NULL) {
free(fil_buf);
ipc_answer_0(rid, ENOMEM);
return;
}
/*
* Fill filv with argument pointers
*/
int i;
for (i = 0; i < count; i++)
filv[i] = &fil_buf[i];
filc = count;
filv[count] = NULL;
ipc_answer_0(rid, EOK);
}
 
/** Load the previously selected program.
*
* @param rid
226,7 → 297,7
* @param request
* @return 0 on success, !0 on error.
*/
static int loader_load(ipc_callid_t rid, ipc_call_t *request)
static int ldr_load(ipc_callid_t rid, ipc_call_t *request)
{
int rc;
242,6 → 313,9
pcb.argc = argc;
pcb.argv = argv;
pcb.filc = filc;
pcb.filv = filv;
if (prog_info.interp == NULL) {
/* Statically linked program */
is_dyn_linked = false;
270,7 → 344,7
* @param request
* @return 0 on success, !0 on error.
*/
static void loader_run(ipc_callid_t rid, ipc_call_t *request)
static void ldr_run(ipc_callid_t rid, ipc_call_t *request)
{
const char *cp;
283,17 → 357,15
/* Dynamically linked program */
DPRINTF("Run ELF interpreter.\n");
DPRINTF("Entry point: 0x%lx\n", interp_info.entry);
console_close();
ipc_answer_0(rid, EOK);
elf_run(&interp_info, &pcb);
} else {
/* Statically linked program */
console_close();
ipc_answer_0(rid, EOK);
elf_run(&prog_info, &pcb);
}
 
}
/* Not reached */
}
 
302,7 → 374,7
* Receive and carry out commands (of which the last one should be
* to execute the loaded program).
*/
static void loader_connection(ipc_callid_t iid, ipc_call_t *icall)
static void ldr_connection(ipc_callid_t iid, ipc_call_t *icall)
{
ipc_callid_t callid;
ipc_call_t call;
330,19 → 402,22
case IPC_M_PHONE_HUNGUP:
exit(0);
case LOADER_GET_TASKID:
loader_get_taskid(callid, &call);
ldr_get_taskid(callid, &call);
continue;
case LOADER_SET_PATHNAME:
loader_set_pathname(callid, &call);
ldr_set_pathname(callid, &call);
continue;
case LOADER_SET_ARGS:
loader_set_args(callid, &call);
ldr_set_args(callid, &call);
continue;
case LOADER_SET_FILES:
ldr_set_files(callid, &call);
continue;
case LOADER_LOAD:
loader_load(callid, &call);
ldr_load(callid, &call);
continue;
case LOADER_RUN:
loader_run(callid, &call);
ldr_run(callid, &call);
/* Not reached */
default:
retval = ENOENT;
366,7 → 441,7
connected = false;
/* Set a handler of incomming connections. */
async_set_client_connection(loader_connection);
async_set_client_connection(ldr_connection);
/* Register at naming service. */
if (ipc_connect_to_me(PHONE_NS, SERVICE_LOAD, 0, 0, &phonead) != 0)
/branches/dd/uspace/srv/fb/ega.h
27,10 → 27,10
*/
 
/** @addtogroup egafb
* @brief HelenOS EGA framebuffer.
* @brief HelenOS EGA framebuffer.
* @ingroup fbs
* @{
*/
*/
/** @file
*/
 
43,4 → 43,3
 
/** @}
*/
 
/branches/dd/uspace/srv/fb/serial_console.c
43,8 → 43,9
#include <ipc/fb.h>
#include <bool.h>
#include <errno.h>
#include <console/color.h>
#include <console/style.h>
#include <io/color.h>
#include <io/style.h>
#include <string.h>
 
#include "../console/screenbuffer.h"
#include "main.h"
128,9 → 129,9
 
}
 
void serial_goto(const unsigned int row, const unsigned int col)
void serial_goto(const unsigned int col, const unsigned int row)
{
if ((row > scr_height) || (col > scr_width))
if ((col > scr_width) || (row > scr_height))
return;
char control[MAX_CONTROL];
153,7 → 154,7
void serial_scroll(int i)
{
if (i > 0) {
serial_goto(scr_height - 1, 0);
serial_goto(0, scr_height - 1);
while (i--)
serial_puts("\033D");
} else if (i < 0) {
235,17 → 236,24
if (fgcolor < bgcolor)
serial_sgr(SGR_REVERSE_OFF);
else
serial_sgr(SGR_REVERSE);
serial_sgr(SGR_REVERSE);
}
 
static void serial_set_attrs(const attrs_t *a)
{
switch (a->t) {
case at_style: serial_set_style(a->a.s.style); break;
case at_rgb: serial_set_rgb(a->a.r.fg_color, a->a.r.bg_color); break;
case at_idx: serial_set_idx(a->a.i.fg_color,
a->a.i.bg_color, a->a.i.flags); break;
default: break;
case at_style:
serial_set_style(a->a.s.style);
break;
case at_rgb:
serial_set_rgb(a->a.r.fg_color, a->a.r.bg_color);
break;
case at_idx:
serial_set_idx(a->a.i.fg_color,
a->a.i.bg_color, a->a.i.flags);
break;
default:
break;
}
}
 
265,13 → 273,13
keyfield_t *field;
attrs_t *a0, *a1;
 
serial_goto(y, x);
serial_goto(x, y);
a0 = &data[0].attrs;
serial_set_attrs(a0);
 
for (j = 0; j < h; j++) {
if (j > 0 && w != scr_width)
serial_goto(y, x);
serial_goto(x, j);
 
for (i = 0; i < w; i++) {
field = &data[j * w + i];
354,16 → 362,16
break;
}
draw_text_data(interbuf, col, row, w, h);
lastcol = col + w;
lastrow = row + h - 1;
lastcol = col + w;
retval = 0;
break;
case FB_PUTCHAR:
c = IPC_GET_ARG1(call);
row = IPC_GET_ARG2(call);
col = IPC_GET_ARG3(call);
col = IPC_GET_ARG2(call);
row = IPC_GET_ARG3(call);
if ((lastcol != col) || (lastrow != row))
serial_goto(row, col);
serial_goto(col, row);
lastcol = col + 1;
lastrow = row;
serial_putchar(c);
370,15 → 378,15
retval = 0;
break;
case FB_CURSOR_GOTO:
row = IPC_GET_ARG1(call);
col = IPC_GET_ARG2(call);
serial_goto(row, col);
col = IPC_GET_ARG1(call);
row = IPC_GET_ARG2(call);
serial_goto(col, row);
lastcol = col;
lastrow = row;
lastcol = col;
retval = 0;
break;
case FB_GET_CSIZE:
ipc_answer_2(callid, EOK, scr_height, scr_width);
ipc_answer_2(callid, EOK, scr_width, scr_height);
continue;
case FB_CLEAR:
serial_clrscr();
416,7 → 424,7
break;
}
serial_scroll(i);
serial_goto(lastrow, lastcol);
serial_goto(lastcol, lastrow);
retval = 0;
break;
case FB_CURSOR_VISIBILITY:
445,6 → 453,6
}
}
 
/**
/**
* @}
*/
/branches/dd/uspace/srv/fb/serial_console.h
43,7 → 43,7
typedef void (*putc_function_t)(char);
 
void serial_puts(char *str);
void serial_goto(const unsigned int row, const unsigned int col);
void serial_goto(const unsigned int col, const unsigned int row);
void serial_clrscr(void);
void serial_scroll(int i);
void serial_cursor_disable(void);
/branches/dd/uspace/srv/fb/fb.c
51,9 → 51,10
#include <ipc/services.h>
#include <kernel/errno.h>
#include <kernel/genarch/fb/visuals.h>
#include <console/color.h>
#include <console/style.h>
#include <io/color.h>
#include <io/style.h>
#include <async.h>
#include <fibril.h>
#include <bool.h>
 
#include "font-8x16.h"
375,8 → 376,8
*/
static void vport_redraw(viewport_t *vport)
{
unsigned int col;
unsigned int row;
unsigned int col;
for (row = 0; row < vport->rows; row++) {
for (col = 0; col < vport->cols; col++) {
431,8 → 432,8
*/
static void vport_scroll(viewport_t *vport, int lines)
{
unsigned int col;
unsigned int row;
unsigned int col;
unsigned int x;
unsigned int y;
uint32_t glyph;
1038,8 → 1039,8
*
* @return false if the call was not handled byt this function, true otherwise
*
* Note: this function is not threads safe, you would have
* to redefine static variables with __thread
* Note: this function is not thread-safe, you would have
* to redefine static variables with fibril_local.
*
*/
static bool shm_handle(ipc_callid_t callid, ipc_call_t *call, int vp)
1564,7 → 1565,7
unsigned int i;
int scroll;
wchar_t ch;
unsigned int row, col;
unsigned int col, row;
if ((vport->cursor_active) || (anims_enabled))
callid = async_get_call_timeout(&call, 250000);
1601,8 → 1602,8
case FB_PUTCHAR:
ch = IPC_GET_ARG1(call);
row = IPC_GET_ARG2(call);
col = IPC_GET_ARG3(call);
col = IPC_GET_ARG2(call);
row = IPC_GET_ARG3(call);
if ((col >= vport->cols) || (row >= vport->rows)) {
retval = EINVAL;
1620,8 → 1621,8
retval = EOK;
break;
case FB_CURSOR_GOTO:
row = IPC_GET_ARG1(call);
col = IPC_GET_ARG2(call);
col = IPC_GET_ARG1(call);
row = IPC_GET_ARG2(call);
if ((col >= vport->cols) || (row >= vport->rows)) {
retval = EINVAL;
1641,7 → 1642,7
retval = EOK;
break;
case FB_GET_CSIZE:
ipc_answer_2(callid, EOK, vport->rows, vport->cols);
ipc_answer_2(callid, EOK, vport->cols, vport->rows);
continue;
case FB_SCROLL:
scroll = IPC_GET_ARG1(call);
/branches/dd/uspace/srv/fb/ega.c
49,8 → 49,8
#include <ipc/ns.h>
#include <ipc/services.h>
#include <libarch/ddi.h>
#include <console/style.h>
#include <console/color.h>
#include <io/style.h>
#include <io/color.h>
#include <sys/types.h>
 
#include "ega.h"
70,7 → 70,7
int ega_normal_color = 0x0f;
int ega_inverted_color = 0xf0;
 
#define NORMAL_COLOR ega_normal_color
#define NORMAL_COLOR ega_normal_color
#define INVERTED_COLOR ega_inverted_color
 
/* Allow only 1 connection */
95,7 → 95,7
}
}
 
static void cursor_goto(unsigned int row, unsigned int col)
static void cursor_goto(unsigned int col, unsigned int row)
{
int ega_cursor;
 
144,12 → 144,12
}
}
 
static void printchar(wchar_t c, unsigned int row, unsigned int col)
static void printchar(wchar_t c, unsigned int col, unsigned int row)
{
scr_addr[(row * scr_width + col) * 2] = ega_glyph(c);
scr_addr[(row * scr_width + col) * 2 + 1] = style;
cursor_goto(row, col + 1);
cursor_goto(col + 1, row);
}
 
/** Draw text data to viewport.
241,11 → 241,15
static unsigned attr_to_ega_style(const attrs_t *a)
{
switch (a->t) {
case at_style: return style_to_ega_style(a->a.s.style);
case at_rgb: return rgb_to_ega_style(a->a.r.fg_color, a->a.r.bg_color);
case at_idx: return color_to_ega_style(a->a.i.fg_color,
a->a.i.bg_color, a->a.i.flags);
default: return INVERTED_COLOR;
case at_style:
return style_to_ega_style(a->a.s.style);
case at_rgb:
return rgb_to_ega_style(a->a.r.fg_color, a->a.r.bg_color);
case at_idx:
return color_to_ega_style(a->a.i.fg_color,
a->a.i.bg_color, a->a.i.flags);
default:
return INVERTED_COLOR;
}
}
 
312,7 → 316,7
retval = 0;
break;
case FB_GET_CSIZE:
ipc_answer_2(callid, EOK, scr_height, scr_width);
ipc_answer_2(callid, EOK, scr_width, scr_height);
continue;
case FB_CLEAR:
clrscr();
320,23 → 324,23
break;
case FB_PUTCHAR:
c = IPC_GET_ARG1(call);
row = IPC_GET_ARG2(call);
col = IPC_GET_ARG3(call);
col = IPC_GET_ARG2(call);
row = IPC_GET_ARG3(call);
if (col >= scr_width || row >= scr_height) {
retval = EINVAL;
break;
}
printchar(c, row, col);
printchar(c, col, row);
retval = 0;
break;
case FB_CURSOR_GOTO:
row = IPC_GET_ARG1(call);
col = IPC_GET_ARG2(call);
col = IPC_GET_ARG1(call);
row = IPC_GET_ARG2(call);
if (row >= scr_height || col >= scr_width) {
retval = EINVAL;
break;
}
cursor_goto(row, col);
cursor_goto(col, row);
retval = 0;
break;
case FB_SCROLL:
/branches/dd/uspace/srv/fs/devfs/devfs.c
28,7 → 28,7
 
/** @addtogroup fs
* @{
*/
*/
 
/**
* @file devfs.c
74,6 → 74,12
case VFS_LOOKUP:
devfs_lookup(callid, &call);
break;
case VFS_OPEN_NODE:
devfs_open_node(callid, &call);
break;
case VFS_DEVICE:
devfs_device(callid, &call);
break;
case VFS_READ:
devfs_read(callid, &call);
break;
83,6 → 89,12
case VFS_TRUNCATE:
devfs_truncate(callid, &call);
break;
case VFS_CLOSE:
devfs_close(callid, &call);
break;
case VFS_SYNC:
devfs_sync(callid, &call);
break;
case VFS_DESTROY:
devfs_destroy(callid, &call);
break;
122,6 → 134,6
return 0;
}
 
/**
/**
* @}
*/
/branches/dd/uspace/srv/fs/devfs/devfs_ops.c
41,13 → 41,56
#include <malloc.h>
#include <string.h>
#include <libfs.h>
#include <adt/hash_table.h>
#include "devfs.h"
#include "devfs_ops.h"
 
#define PLB_GET_CHAR(pos) (devfs_reg.plb_ro[pos % PLB_SIZE])
 
/** Opened devices structure */
typedef struct {
dev_handle_t handle;
int phone;
size_t refcount;
link_t link;
} device_t;
 
/** Hash table of opened devices */
static hash_table_t devices;
 
#define DEVICES_KEYS 1
#define DEVICES_KEY_HANDLE 0
#define DEVICES_BUCKETS 256
 
/* Implementation of hash table interface for the nodes hash table. */
static hash_index_t devices_hash(unsigned long key[])
{
return key[DEVICES_KEY_HANDLE] % DEVICES_BUCKETS;
}
 
static int devices_compare(unsigned long key[], hash_count_t keys, link_t *item)
{
device_t *dev = hash_table_get_instance(item, device_t, link);
return (dev->handle == (dev_handle_t) key[DEVICES_KEY_HANDLE]);
}
 
static void devices_remove_callback(link_t *item)
{
free(hash_table_get_instance(item, device_t, link));
}
 
static hash_table_operations_t devices_ops = {
.hash = devices_hash,
.compare = devices_compare,
.remove_callback = devices_remove_callback
};
 
bool devfs_init(void)
{
if (!hash_table_create(&devices, DEVICES_BUCKETS,
DEVICES_KEYS, &devices_ops))
return false;
if (devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING) < 0)
return false;
103,8 → 146,7
return;
}
/* This is a read-only filesystem */
if ((lflag & L_CREATE) || (lflag & L_LINK) || (lflag & L_UNLINK)) {
if ((lflag & L_LINK) || (lflag & L_UNLINK)) {
ipc_answer_0(rid, ENOTSUP);
return;
}
123,7 → 165,7
ipc_answer_0(rid, ENOENT);
} else {
if (lflag & L_FILE) {
count_t len;
size_t len;
if (last >= first)
len = last - first + 1;
else
135,7 → 177,7
return;
}
count_t i;
size_t i;
for (i = 0; i < len; i++)
name[i] = PLB_GET_CHAR(first + i);
148,6 → 190,38
return;
}
if (lflag & L_OPEN) {
unsigned long key[] = {
[DEVICES_KEY_HANDLE] = (unsigned long) handle
};
link_t *lnk = hash_table_find(&devices, key);
if (lnk == NULL) {
int phone = devmap_device_connect(handle, 0);
if (phone < 0) {
free(name);
ipc_answer_0(rid, ENOENT);
return;
}
device_t *dev = (device_t *) malloc(sizeof(device_t));
if (dev == NULL) {
free(name);
ipc_answer_0(rid, ENOMEM);
return;
}
dev->handle = handle;
dev->phone = phone;
dev->refcount = 1;
hash_table_insert(&devices, key, &dev->link);
} else {
device_t *dev = hash_table_get_instance(lnk, device_t, link);
dev->refcount++;
}
}
free(name);
ipc_answer_5(rid, EOK, devfs_reg.fs_handle, dev_handle, handle, 0, 1);
156,6 → 230,61
}
}
 
void devfs_open_node(ipc_callid_t rid, ipc_call_t *request)
{
dev_handle_t handle = IPC_GET_ARG2(*request);
unsigned long key[] = {
[DEVICES_KEY_HANDLE] = (unsigned long) handle
};
link_t *lnk = hash_table_find(&devices, key);
if (lnk == NULL) {
int phone = devmap_device_connect(handle, 0);
if (phone < 0) {
ipc_answer_0(rid, ENOENT);
return;
}
device_t *dev = (device_t *) malloc(sizeof(device_t));
if (dev == NULL) {
ipc_answer_0(rid, ENOMEM);
return;
}
dev->handle = handle;
dev->phone = phone;
dev->refcount = 1;
hash_table_insert(&devices, key, &dev->link);
} else {
device_t *dev = hash_table_get_instance(lnk, device_t, link);
dev->refcount++;
}
ipc_answer_3(rid, EOK, 0, 1, L_FILE);
}
 
void devfs_device(ipc_callid_t rid, ipc_call_t *request)
{
fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
if (index != 0) {
unsigned long key[] = {
[DEVICES_KEY_HANDLE] = (unsigned long) index
};
link_t *lnk = hash_table_find(&devices, key);
if (lnk == NULL) {
ipc_answer_0(rid, ENOENT);
return;
}
ipc_answer_1(rid, EOK, (ipcarg_t) index);
} else
ipc_answer_0(rid, ENOTSUP);
}
 
void devfs_read(ipc_callid_t rid, ipc_call_t *request)
{
fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
162,34 → 291,59
off_t pos = (off_t) IPC_GET_ARG3(*request);
if (index != 0) {
ipc_answer_1(rid, ENOENT, 0);
return;
}
/*
* Receive the read request.
*/
ipc_callid_t callid;
size_t size;
if (!ipc_data_read_receive(&callid, &size)) {
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
return;
}
size_t bytes = 0;
if (index != 0) {
(void) ipc_data_read_finalize(callid, NULL, bytes);
unsigned long key[] = {
[DEVICES_KEY_HANDLE] = (unsigned long) index
};
link_t *lnk = hash_table_find(&devices, key);
if (lnk == NULL) {
ipc_answer_0(rid, ENOENT);
return;
}
device_t *dev = hash_table_get_instance(lnk, device_t, link);
ipc_callid_t callid;
if (!ipc_data_read_receive(&callid, NULL)) {
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
return;
}
/* Make a request at the driver */
ipc_call_t answer;
aid_t msg = async_send_3(dev->phone, IPC_GET_METHOD(*request),
IPC_GET_ARG1(*request), IPC_GET_ARG2(*request),
IPC_GET_ARG3(*request), &answer);
/* Forward the IPC_M_DATA_READ request to the driver */
ipc_forward_fast(callid, dev->phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
/* Wait for reply from the driver. */
ipcarg_t rc;
async_wait_for(msg, &rc);
size_t bytes = IPC_GET_ARG1(answer);
/* Driver reply is the final result of the whole operation */
ipc_answer_1(rid, rc, bytes);
} else {
count_t count = devmap_device_get_count();
ipc_callid_t callid;
size_t size;
if (!ipc_data_read_receive(&callid, &size)) {
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
return;
}
size_t count = devmap_device_get_count();
dev_desc_t *desc = malloc(count * sizeof(dev_desc_t));
if (desc == NULL) {
ipc_answer_0(callid, ENOENT);
ipc_answer_1(rid, ENOENT, 0);
ipc_answer_0(callid, ENOMEM);
ipc_answer_1(rid, ENOMEM, 0);
return;
}
count_t max = devmap_device_get_devices(count, desc);
size_t max = devmap_device_get_devices(count, desc);
if (pos < max) {
ipc_data_read_finalize(callid, desc[pos].name, str_size(desc[pos].name) + 1);
200,10 → 354,9
}
free(desc);
bytes = 1;
ipc_answer_1(rid, EOK, 1);
}
ipc_answer_1(rid, EOK, bytes);
}
 
void devfs_write(ipc_callid_t rid, ipc_call_t *request)
211,20 → 364,46
fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
off_t pos = (off_t) IPC_GET_ARG3(*request);
/*
* Receive the write request.
*/
ipc_callid_t callid;
size_t size;
if (!ipc_data_write_receive(&callid, &size)) {
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
return;
if (index != 0) {
unsigned long key[] = {
[DEVICES_KEY_HANDLE] = (unsigned long) index
};
link_t *lnk = hash_table_find(&devices, key);
if (lnk == NULL) {
ipc_answer_0(rid, ENOENT);
return;
}
device_t *dev = hash_table_get_instance(lnk, device_t, link);
ipc_callid_t callid;
if (!ipc_data_write_receive(&callid, NULL)) {
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
return;
}
/* Make a request at the driver */
ipc_call_t answer;
aid_t msg = async_send_3(dev->phone, IPC_GET_METHOD(*request),
IPC_GET_ARG1(*request), IPC_GET_ARG2(*request),
IPC_GET_ARG3(*request), &answer);
/* Forward the IPC_M_DATA_WRITE request to the driver */
ipc_forward_fast(callid, dev->phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
/* Wait for reply from the driver. */
ipcarg_t rc;
async_wait_for(msg, &rc);
size_t bytes = IPC_GET_ARG1(answer);
/* Driver reply is the final result of the whole operation */
ipc_answer_1(rid, rc, bytes);
} else {
/* Read-only filesystem */
ipc_answer_0(rid, ENOTSUP);
}
// TODO
ipc_answer_0(callid, ENOENT);
ipc_answer_2(rid, ENOENT, 0, 0);
}
 
void devfs_truncate(ipc_callid_t rid, ipc_call_t *request)
232,6 → 411,66
ipc_answer_0(rid, ENOTSUP);
}
 
void devfs_close(ipc_callid_t rid, ipc_call_t *request)
{
fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
if (index != 0) {
unsigned long key[] = {
[DEVICES_KEY_HANDLE] = (unsigned long) index
};
link_t *lnk = hash_table_find(&devices, key);
if (lnk == NULL) {
ipc_answer_0(rid, ENOENT);
return;
}
device_t *dev = hash_table_get_instance(lnk, device_t, link);
dev->refcount--;
if (dev->refcount == 0) {
ipc_hangup(dev->phone);
hash_table_remove(&devices, key, DEVICES_KEYS);
}
ipc_answer_0(rid, EOK);
} else
ipc_answer_0(rid, ENOTSUP);
}
 
void devfs_sync(ipc_callid_t rid, ipc_call_t *request)
{
fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
if (index != 0) {
unsigned long key[] = {
[DEVICES_KEY_HANDLE] = (unsigned long) index
};
link_t *lnk = hash_table_find(&devices, key);
if (lnk == NULL) {
ipc_answer_0(rid, ENOENT);
return;
}
device_t *dev = hash_table_get_instance(lnk, device_t, link);
/* Make a request at the driver */
ipc_call_t answer;
aid_t msg = async_send_2(dev->phone, IPC_GET_METHOD(*request),
IPC_GET_ARG1(*request), IPC_GET_ARG2(*request), &answer);
/* Wait for reply from the driver */
ipcarg_t rc;
async_wait_for(msg, &rc);
/* Driver reply is the final result of the whole operation */
ipc_answer_0(rid, rc);
} else
ipc_answer_0(rid, ENOTSUP);
}
 
void devfs_destroy(ipc_callid_t rid, ipc_call_t *request)
{
ipc_answer_0(rid, ENOTSUP);
239,4 → 478,4
 
/**
* @}
*/
*/
/branches/dd/uspace/srv/fs/devfs/devfs_ops.h
28,7 → 28,7
 
/** @addtogroup fs
* @{
*/
*/
 
#ifndef DEVFS_DEVFS_OPS_H_
#define DEVFS_DEVFS_OPS_H_
41,9 → 41,13
extern void devfs_mounted(ipc_callid_t, ipc_call_t *);
extern void devfs_mount(ipc_callid_t, ipc_call_t *);
extern void devfs_lookup(ipc_callid_t, ipc_call_t *);
extern void devfs_open_node(ipc_callid_t, ipc_call_t *);
extern void devfs_device(ipc_callid_t, ipc_call_t *);
extern void devfs_sync(ipc_callid_t, ipc_call_t *);
extern void devfs_read(ipc_callid_t, ipc_call_t *);
extern void devfs_write(ipc_callid_t, ipc_call_t *);
extern void devfs_truncate(ipc_callid_t, ipc_call_t *);
extern void devfs_close(ipc_callid_t, ipc_call_t *);
extern void devfs_destroy(ipc_callid_t, ipc_call_t *);
 
#endif
/branches/dd/uspace/srv/fs/tmpfs/tmpfs.h
38,7 → 38,7
#include <atomic.h>
#include <sys/types.h>
#include <bool.h>
#include <libadt/hash_table.h>
#include <adt/hash_table.h>
 
#ifndef dprintf
#define dprintf(...) printf(__VA_ARGS__)
86,7 → 86,11
extern void tmpfs_read(ipc_callid_t, ipc_call_t *);
extern void tmpfs_write(ipc_callid_t, ipc_call_t *);
extern void tmpfs_truncate(ipc_callid_t, ipc_call_t *);
extern void tmpfs_close(ipc_callid_t, ipc_call_t *);
extern void tmpfs_destroy(ipc_callid_t, ipc_call_t *);
extern void tmpfs_open_node(ipc_callid_t, ipc_call_t *);
extern void tmpfs_device(ipc_callid_t, ipc_call_t *);
extern void tmpfs_sync(ipc_callid_t, ipc_call_t *);
 
extern bool tmpfs_restore(dev_handle_t);
 
/branches/dd/uspace/srv/fs/tmpfs/tmpfs.c
114,9 → 114,21
case VFS_TRUNCATE:
tmpfs_truncate(callid, &call);
break;
case VFS_CLOSE:
tmpfs_close(callid, &call);
break;
case VFS_DESTROY:
tmpfs_destroy(callid, &call);
break;
case VFS_OPEN_NODE:
tmpfs_open_node(callid, &call);
break;
case VFS_DEVICE:
tmpfs_device(callid, &call);
break;
case VFS_SYNC:
tmpfs_sync(callid, &call);
break;
default:
ipc_answer_0(callid, ENOTSUP);
break;
/branches/dd/uspace/srv/fs/tmpfs/tmpfs_ops.c
47,7 → 47,7
#include <stdio.h>
#include <assert.h>
#include <sys/types.h>
#include <libadt/hash_table.h>
#include <adt/hash_table.h>
#include <as.h>
#include <libfs.h>
 
596,6 → 596,11
ipc_answer_0(rid, EOK);
}
 
void tmpfs_close(ipc_callid_t rid, ipc_call_t *request)
{
ipc_answer_0(rid, EOK);
}
 
void tmpfs_destroy(ipc_callid_t rid, ipc_call_t *request)
{
dev_handle_t dev_handle = (dev_handle_t)IPC_GET_ARG1(*request);
618,6 → 623,22
ipc_answer_0(rid, rc);
}
 
void tmpfs_open_node(ipc_callid_t rid, ipc_call_t *request)
{
libfs_open_node(&tmpfs_libfs_ops, tmpfs_reg.fs_handle, rid, request);
}
 
void tmpfs_device(ipc_callid_t rid, ipc_call_t *request)
{
ipc_answer_0(rid, ENOTSUP);
}
 
void tmpfs_sync(ipc_callid_t rid, ipc_call_t *request)
{
/* Dummy implementation */
ipc_answer_0(rid, EOK);
}
 
/**
* @}
*/
*/
/branches/dd/uspace/srv/fs/fat/fat_idx.c
39,8 → 39,8
#include "../../vfs/vfs.h"
#include <errno.h>
#include <string.h>
#include <libadt/hash_table.h>
#include <libadt/list.h>
#include <adt/hash_table.h>
#include <adt/list.h>
#include <assert.h>
#include <futex.h>
 
/branches/dd/uspace/srv/fs/fat/fat.h
206,7 → 206,11
extern void fat_read(ipc_callid_t, ipc_call_t *);
extern void fat_write(ipc_callid_t, ipc_call_t *);
extern void fat_truncate(ipc_callid_t, ipc_call_t *);
extern void fat_close(ipc_callid_t, ipc_call_t *);
extern void fat_destroy(ipc_callid_t, ipc_call_t *);
extern void fat_open_node(ipc_callid_t, ipc_call_t *);
extern void fat_device(ipc_callid_t, ipc_call_t *);
extern void fat_sync(ipc_callid_t, ipc_call_t *);
 
extern fat_idx_t *fat_idx_get_new(dev_handle_t);
extern fat_idx_t *fat_idx_get_by_pos(dev_handle_t, fat_cluster_t, unsigned);
/branches/dd/uspace/srv/fs/fat/fat_fat.c
46,6 → 46,7
#include <align.h>
#include <assert.h>
#include <futex.h>
#include <mem.h>
 
/**
* The fat_alloc_lock futex protects all copies of the File Allocation Table
/branches/dd/uspace/srv/fs/fat/fat.c
107,9 → 107,21
case VFS_TRUNCATE:
fat_truncate(callid, &call);
break;
case VFS_CLOSE:
fat_close(callid, &call);
break;
case VFS_DESTROY:
fat_destroy(callid, &call);
break;
case VFS_OPEN_NODE:
fat_open_node(callid, &call);
break;
case VFS_DEVICE:
fat_device(callid, &call);
break;
case VFS_SYNC:
fat_sync(callid, &call);
break;
default:
ipc_answer_0(callid, ENOTSUP);
break;
/branches/dd/uspace/srv/fs/fat/fat_ops.c
48,8 → 48,8
#include <errno.h>
#include <string.h>
#include <byteorder.h>
#include <libadt/hash_table.h>
#include <libadt/list.h>
#include <adt/hash_table.h>
#include <adt/list.h>
#include <assert.h>
#include <futex.h>
#include <sys/mman.h>
1169,6 → 1169,11
return;
}
 
void fat_close(ipc_callid_t rid, ipc_call_t *request)
{
ipc_answer_0(rid, EOK);
}
 
void fat_destroy(ipc_callid_t rid, ipc_call_t *request)
{
dev_handle_t dev_handle = (dev_handle_t)IPC_GET_ARG1(*request);
1185,6 → 1190,22
ipc_answer_0(rid, rc);
}
 
void fat_open_node(ipc_callid_t rid, ipc_call_t *request)
{
libfs_open_node(&fat_libfs_ops, fat_reg.fs_handle, rid, request);
}
 
void fat_device(ipc_callid_t rid, ipc_call_t *request)
{
ipc_answer_0(rid, ENOTSUP);
}
 
void fat_sync(ipc_callid_t rid, ipc_call_t *request)
{
/* Dummy implementation */
ipc_answer_0(rid, EOK);
}
 
/**
* @}
*/
*/
/branches/dd/uspace/srv/pci/pci.h
2,9 → 2,10
#define PCI_H
 
//#include <arch/types.h>
#include <libadt/list.h>
#include <adt/list.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
struct pci_drv;
struct pci_dev;
/branches/dd/uspace/srv/devmap/devmap.c
41,7 → 41,7
#include <stdio.h>
#include <errno.h>
#include <bool.h>
#include <futex.h>
#include <fibril_sync.h>
#include <stdlib.h>
#include <string.h>
#include <ipc/devmap.h>
62,8 → 62,8
ipcarg_t phone;
/** Device driver name */
char *name;
/** Futex for list of devices owned by this driver */
atomic_t devices_futex;
/** Fibril mutex for list of devices owned by this driver */
fibril_mutex_t devices_mutex;
} devmap_driver_t;
 
/** Info about registered device
95,15 → 95,15
LIST_INITIALIZE(pending_req);
 
/* Locking order:
* drivers_list_futex
* devices_list_futex
* (devmap_driver_t *)->devices_futex
* create_handle_futex
* drivers_list_mutex
* devices_list_mutex
* (devmap_driver_t *)->devices_mutex
* create_handle_mutex
**/
 
static atomic_t devices_list_futex = FUTEX_INITIALIZER;
static atomic_t drivers_list_futex = FUTEX_INITIALIZER;
static atomic_t create_handle_futex = FUTEX_INITIALIZER;
static FIBRIL_MUTEX_INITIALIZE(devices_list_mutex);
static FIBRIL_MUTEX_INITIALIZE(drivers_list_mutex);
static FIBRIL_MUTEX_INITIALIZE(create_handle_mutex);
 
static dev_handle_t last_handle = 0;
 
110,13 → 110,12
static dev_handle_t devmap_create_handle(void)
{
/* TODO: allow reusing old handles after their unregistration
* and implement some version of LRU algorithm
* and implement some version of LRU algorithm, avoid overflow
*/
/* FIXME: overflow */
futex_down(&create_handle_futex);
fibril_mutex_lock(&create_handle_mutex);
last_handle++;
futex_up(&create_handle_futex);
fibril_mutex_unlock(&create_handle_mutex);
return last_handle;
}
131,7 → 130,7
while (item != &devices_list) {
device = list_get_instance(item, devmap_device_t, devices);
if (0 == str_cmp(device->name, name))
if (str_cmp(device->name, name) == 0)
break;
item = item->next;
}
150,7 → 149,7
*/
static devmap_device_t *devmap_device_find_handle(dev_handle_t handle)
{
futex_down(&devices_list_futex);
fibril_mutex_lock(&devices_list_mutex);
link_t *item = (&devices_list)->next;
devmap_device_t *device = NULL;
163,13 → 162,13
}
if (item == &devices_list) {
futex_up(&devices_list_futex);
fibril_mutex_unlock(&devices_list_mutex);
return NULL;
}
device = list_get_instance(item, devmap_device_t, devices);
futex_up(&devices_list_futex);
fibril_mutex_unlock(&devices_list_mutex);
return device;
}
249,7 → 248,7
/*
* Send confirmation to sender and get data into buffer.
*/
if (EOK != ipc_data_write_finalize(callid, driver->name, name_size)) {
if (ipc_data_write_finalize(callid, driver->name, name_size) != EOK) {
free(driver->name);
free(driver);
ipc_answer_0(iid, EREFUSED);
258,21 → 257,21
driver->name[name_size] = 0;
/* Initialize futex for list of devices owned by this driver */
futex_initialize(&(driver->devices_futex), 1);
/* Initialize mutex for list of devices owned by this driver */
fibril_mutex_initialize(&driver->devices_mutex);
/*
* Initialize list of asociated devices
*/
list_initialize(&(driver->devices));
list_initialize(&driver->devices);
/*
* Create connection to the driver
* Create connection to the driver
*/
ipc_call_t call;
callid = async_get_call(&call);
if (IPC_M_CONNECT_TO_ME != IPC_GET_METHOD(call)) {
if (IPC_GET_METHOD(call) != IPC_M_CONNECT_TO_ME) {
ipc_answer_0(callid, ENOTSUP);
free(driver->name);
287,7 → 286,7
list_initialize(&(driver->drivers));
futex_down(&drivers_list_futex);
fibril_mutex_lock(&drivers_list_mutex);
/* TODO:
* check that no driver with name equal to driver->name is registered
297,7 → 296,7
* Insert new driver into list of registered drivers
*/
list_append(&(driver->drivers), &drivers_list);
futex_up(&drivers_list_futex);
fibril_mutex_unlock(&drivers_list_mutex);
ipc_answer_0(iid, EOK);
314,7 → 313,7
if (driver == NULL)
return EEXISTS;
futex_down(&drivers_list_futex);
fibril_mutex_lock(&drivers_list_mutex);
if (driver->phone != 0)
ipc_hangup(driver->phone);
323,8 → 322,8
list_remove(&(driver->drivers));
/* Unregister all its devices */
futex_down(&devices_list_futex);
futex_down(&(driver->devices_futex));
fibril_mutex_lock(&devices_list_mutex);
fibril_mutex_lock(&driver->devices_mutex);
while (!list_empty(&(driver->devices))) {
devmap_device_t *device = list_get_instance(driver->devices.next,
332,9 → 331,9
devmap_device_unregister_core(device);
}
futex_up(&(driver->devices_futex));
futex_up(&devices_list_futex);
futex_up(&drivers_list_futex);
fibril_mutex_unlock(&driver->devices_mutex);
fibril_mutex_unlock(&devices_list_mutex);
fibril_mutex_unlock(&drivers_list_mutex);
/* free name and driver */
if (driver->name != NULL)
347,7 → 346,7
 
 
/** Process pending lookup requests */
static void process_pending_lookup()
static void process_pending_lookup(void)
{
link_t *cur;
364,6 → 363,7
free(pr->name);
list_remove(cur);
free(pr);
goto loop;
}
}
419,12 → 419,12
list_initialize(&(device->devices));
list_initialize(&(device->driver_devices));
futex_down(&devices_list_futex);
fibril_mutex_lock(&devices_list_mutex);
/* Check that device with such name is not already registered */
if (NULL != devmap_device_find_name(device->name)) {
printf(NAME ": Device '%s' already registered\n", device->name);
futex_up(&devices_list_futex);
fibril_mutex_unlock(&devices_list_mutex);
free(device->name);
free(device);
ipc_answer_0(iid, EEXISTS);
440,16 → 440,14
list_append(&device->devices, &devices_list);
/* Insert device into list of devices that belog to one driver */
futex_down(&device->driver->devices_futex);
fibril_mutex_lock(&device->driver->devices_mutex);
list_append(&device->driver_devices, &device->driver->devices);
futex_up(&device->driver->devices_futex);
futex_up(&devices_list_futex);
fibril_mutex_unlock(&device->driver->devices_mutex);
fibril_mutex_unlock(&devices_list_mutex);
ipc_answer_1(iid, EOK, device->handle);
process_pending_lookup();
}
 
/**
600,14 → 598,14
 
static void devmap_get_count(ipc_callid_t iid, ipc_call_t *icall)
{
futex_down(&devices_list_futex);
fibril_mutex_lock(&devices_list_mutex);
ipc_answer_1(iid, EOK, list_count(&devices_list));
futex_up(&devices_list_futex);
fibril_mutex_unlock(&devices_list_mutex);
}
 
static void devmap_get_devices(ipc_callid_t iid, ipc_call_t *icall)
{
futex_down(&devices_list_futex);
fibril_mutex_lock(&devices_list_mutex);
ipc_callid_t callid;
size_t size;
623,7 → 621,7
return;
}
count_t count = size / sizeof(dev_desc_t);
size_t count = size / sizeof(dev_desc_t);
dev_desc_t *desc = (dev_desc_t *) malloc(size);
if (desc == NULL) {
ipc_answer_0(callid, ENOMEM);
631,7 → 629,7
return;
}
count_t pos = 0;
size_t pos = 0;
link_t *item = devices_list.next;
while ((item != &devices_list) && (pos < count)) {
652,7 → 650,7
free(desc);
futex_up(&devices_list_futex);
fibril_mutex_unlock(&devices_list_mutex);
ipc_answer_1(iid, EOK, pos);
}
677,7 → 675,7
list_initialize(&(device->devices));
list_initialize(&(device->driver_devices));
futex_down(&devices_list_futex);
fibril_mutex_lock(&devices_list_mutex);
/* Get unique device handle */
device->handle = devmap_create_handle();
686,7 → 684,7
/* Insert device into list of all devices */
list_append(&device->devices, &devices_list);
futex_up(&devices_list_futex);
fibril_mutex_unlock(&devices_list_mutex);
return true;
}
699,7 → 697,7
/* Accept connection */
ipc_answer_0(iid, EOK);
devmap_driver_t *driver = NULL;
devmap_driver_t *driver = NULL;
devmap_driver_register(&driver);
if (NULL == driver)
713,7 → 711,6
switch (IPC_GET_METHOD(call)) {
case IPC_M_PHONE_HUNGUP:
cont = false;
/* Exit thread */
continue;
case DEVMAP_DRIVER_UNREGISTER:
if (NULL == driver)
766,7 → 763,6
switch (IPC_GET_METHOD(call)) {
case IPC_M_PHONE_HUNGUP:
cont = false;
/* Exit thread */
continue;
case DEVMAP_DEVICE_GET_HANDLE:
devmap_get_handle(callid, &call);
806,7 → 802,7
break;
default:
/* No such interface */
ipc_answer_0(iid, ENOENT);
ipc_answer_0(iid, ENOENT);
}
}
 
822,7 → 818,9
return -1;
}
/* Set a handler of incomming connections */
/* Set a handler of incomming connections and
pending operations */
async_set_pending(process_pending_lookup);
async_set_client_connection(devmap_connection);
/* Register device mapper at naming service */
/branches/dd/uspace/srv/cir/obio/Makefile
0,0 → 1,76
#
# Copyright (c) 2006 Martin Decky
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# - Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# - The name of the author may not be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
 
## Setup toolchain
#
 
 
LIBC_PREFIX = ../../../lib/libc
SOFTINT_PREFIX = ../../../lib/softint
 
include $(LIBC_PREFIX)/Makefile.toolchain
 
LIBS = $(LIBC_PREFIX)/libc.a
 
## Sources
#
 
OUTPUT = obio
SOURCES = \
obio.c
 
OBJECTS := $(addsuffix .o,$(basename $(SOURCES)))
 
.PHONY: all clean depend disasm
 
all: $(OUTPUT) $(OUTPUT).disasm
 
-include Makefile.depend
 
clean:
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend $(OBJECTS)
 
depend:
$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend
 
$(OUTPUT): $(OBJECTS) $(LIBS)
$(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map
 
disasm: $(OUTPUT).disasm
 
$(OUTPUT).disasm: $(OUTPUT)
$(OBJDUMP) -d $< > $@
 
%.o: %.S
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
 
%.o: %.s
$(AS) $(AFLAGS) $< -o $@
 
%.o: %.c
$(CC) $(DEFS) $(CFLAGS) -c $< -o $@
/branches/dd/uspace/srv/cir/obio/obio.c
0,0 → 1,158
/*
* Copyright (c) 2009 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup obio
* @{
*/
 
/**
* @file obio.c
* @brief OBIO driver.
*
* OBIO is a short for on-board I/O. On UltraSPARC IIi and systems with U2P,
* there is a piece of the root PCI bus controller address space, which
* contains interrupt mapping and clear registers for all on-board devices.
* Although UltraSPARC IIi and U2P are different in general, these registers can
* be found at the same addresses.
*/
 
#include <ipc/ipc.h>
#include <ipc/services.h>
#include <ipc/bus.h>
#include <ipc/ns.h>
#include <sysinfo.h>
#include <as.h>
#include <ddi.h>
#include <align.h>
#include <bool.h>
#include <errno.h>
#include <async.h>
#include <align.h>
#include <async.h>
#include <stdio.h>
#include <ipc/devmap.h>
 
#define NAME "obio"
 
#define OBIO_SIZE 0x1898
 
#define OBIO_IMR_BASE 0x200
#define OBIO_IMR(ino) (OBIO_IMR_BASE + ((ino) & INO_MASK))
 
#define OBIO_CIR_BASE 0x300
#define OBIO_CIR(ino) (OBIO_CIR_BASE + ((ino) & INO_MASK))
 
#define INO_MASK 0x1f
 
static void *base_phys;
static volatile uint64_t *base_virt;
 
/** Handle one connection to obio.
*
* @param iid Hash of the request that opened the connection.
* @param icall Call data of the request that opened the connection.
*/
static void obio_connection(ipc_callid_t iid, ipc_call_t *icall)
{
ipc_callid_t callid;
ipc_call_t call;
 
/*
* Answer the first IPC_M_CONNECT_ME_TO call.
*/
ipc_answer_0(iid, EOK);
 
while (1) {
int inr;
callid = async_get_call(&call);
switch (IPC_GET_METHOD(call)) {
case BUS_CLEAR_INTERRUPT:
inr = IPC_GET_ARG1(call);
base_virt[OBIO_CIR(inr & INO_MASK)] = 0;
ipc_answer_0(callid, EOK);
break;
default:
ipc_answer_0(callid, EINVAL);
break;
}
}
}
 
/** Initialize the OBIO driver.
*
* So far, the driver heavily depends on information provided by the kernel via
* sysinfo. In the future, there should be a standalone OBIO driver.
*/
static bool obio_init(void)
{
ipcarg_t phonead;
 
base_phys = (void *) sysinfo_value("obio.base.physical");
if (!base_phys) {
printf(NAME ": no OBIO registers found\n");
return false;
}
 
base_virt = as_get_mappable_page(OBIO_SIZE);
int flags = AS_AREA_READ | AS_AREA_WRITE;
int retval = physmem_map(base_phys, (void *) base_virt,
ALIGN_UP(OBIO_SIZE, PAGE_SIZE) >> PAGE_WIDTH, flags);
if (retval < 0) {
printf(NAME ": Error mapping OBIO registers\n");
return false;
}
printf(NAME ": OBIO registers with base at %p\n", base_phys);
 
async_set_client_connection(obio_connection);
ipc_connect_to_me(PHONE_NS, SERVICE_OBIO, 0, 0, &phonead);
return true;
}
 
int main(int argc, char **argv)
{
printf(NAME ": HelenOS OBIO driver\n");
if (!obio_init())
return -1;
printf(NAME ": Accepting connections\n");
async_manager();
 
/* Never reached */
return 0;
}
 
/**
* @}
*/
Property changes:
Added: svn:mergeinfo
/branches/dd/uspace/srv/cir/obio
Property changes:
Added: svn:mergeinfo
/branches/dd/uspace/srv/cir/fhc/Makefile
0,0 → 1,76
#
# Copyright (c) 2006 Martin Decky
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# - Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# - The name of the author may not be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
 
## Setup toolchain
#
 
 
LIBC_PREFIX = ../../../lib/libc
SOFTINT_PREFIX = ../../../lib/softint
 
include $(LIBC_PREFIX)/Makefile.toolchain
 
LIBS = $(LIBC_PREFIX)/libc.a
 
## Sources
#
 
OUTPUT = fhc
SOURCES = \
fhc.c
 
OBJECTS := $(addsuffix .o,$(basename $(SOURCES)))
 
.PHONY: all clean depend disasm
 
all: $(OUTPUT) $(OUTPUT).disasm
 
-include Makefile.depend
 
clean:
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend $(OBJECTS)
 
depend:
$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend
 
$(OUTPUT): $(OBJECTS) $(LIBS)
$(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map
 
disasm: $(OUTPUT).disasm
 
$(OUTPUT).disasm: $(OUTPUT)
$(OBJDUMP) -d $< > $@
 
%.o: %.S
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
 
%.o: %.s
$(AS) $(AFLAGS) $< -o $@
 
%.o: %.c
$(CC) $(DEFS) $(CFLAGS) -c $< -o $@
/branches/dd/uspace/srv/cir/fhc/fhc.c
0,0 → 1,157
/*
* Copyright (c) 2009 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup fhc
* @{
*/
 
/**
* @file fhc.c
* @brief FHC bus controller driver.
*/
 
#include <ipc/ipc.h>
#include <ipc/services.h>
#include <ipc/bus.h>
#include <ipc/ns.h>
#include <sysinfo.h>
#include <as.h>
#include <ddi.h>
#include <align.h>
#include <bool.h>
#include <errno.h>
#include <async.h>
#include <align.h>
#include <async.h>
#include <stdio.h>
#include <ipc/devmap.h>
 
#define NAME "fhc"
 
#define FHC_UART_INR 0x39
 
#define FHC_UART_IMAP 0x0
#define FHC_UART_ICLR 0x4
 
static void *fhc_uart_phys;
static volatile uint32_t *fhc_uart_virt;
static size_t fhc_uart_size;
 
/** Handle one connection to fhc.
*
* @param iid Hash of the request that opened the connection.
* @param icall Call data of the request that opened the connection.
*/
static void fhc_connection(ipc_callid_t iid, ipc_call_t *icall)
{
ipc_callid_t callid;
ipc_call_t call;
 
/*
* Answer the first IPC_M_CONNECT_ME_TO call.
*/
ipc_answer_0(iid, EOK);
 
while (1) {
int inr;
callid = async_get_call(&call);
switch (IPC_GET_METHOD(call)) {
case BUS_CLEAR_INTERRUPT:
inr = IPC_GET_ARG1(call);
switch (inr) {
case FHC_UART_INR:
fhc_uart_virt[FHC_UART_ICLR] = 0;
ipc_answer_0(callid, EOK);
break;
default:
ipc_answer_0(callid, ENOTSUP);
break;
}
break;
default:
ipc_answer_0(callid, EINVAL);
break;
}
}
}
 
/** Initialize the FHC driver.
*
* So far, the driver heavily depends on information provided by the kernel via
* sysinfo. In the future, there should be a standalone FHC driver.
*/
static bool fhc_init(void)
{
ipcarg_t phonead;
 
fhc_uart_size = sysinfo_value("fhc.uart.size");
fhc_uart_phys = (void *) sysinfo_value("fhc.uart.physical");
if (!fhc_uart_size) {
printf(NAME ": no FHC UART registers found\n");
return false;
}
 
fhc_uart_virt = as_get_mappable_page(fhc_uart_size);
int flags = AS_AREA_READ | AS_AREA_WRITE;
int retval = physmem_map(fhc_uart_phys, (void *) fhc_uart_virt,
ALIGN_UP(fhc_uart_size, PAGE_SIZE) >> PAGE_WIDTH, flags);
if (retval < 0) {
printf(NAME ": Error mapping FHC UART registers\n");
return false;
}
printf(NAME ": FHC UART registers at %p, %d bytes\n", fhc_uart_phys,
fhc_uart_size);
 
async_set_client_connection(fhc_connection);
ipc_connect_to_me(PHONE_NS, SERVICE_FHC, 0, 0, &phonead);
return true;
}
 
int main(int argc, char **argv)
{
printf(NAME ": HelenOS FHC bus controller driver\n");
if (!fhc_init())
return -1;
printf(NAME ": Accepting connections\n");
async_manager();
 
/* Never reached */
return 0;
}
 
/**
* @}
*/
/branches/dd/uspace/srv/vfs/vfs.c
43,7 → 43,7
#include <bool.h>
#include <string.h>
#include <as.h>
#include <libadt/list.h>
#include <adt/list.h>
#include <atomic.h>
#include "vfs.h"
 
94,6 → 94,9
case VFS_OPEN:
vfs_open(callid, &call);
break;
case VFS_OPEN_NODE:
vfs_open_node(callid, &call);
break;
case VFS_CLOSE:
vfs_close(callid, &call);
break;
118,6 → 121,15
case VFS_RENAME:
vfs_rename(callid, &call);
break;
case VFS_DEVICE:
vfs_device(callid, &call);
break;
case VFS_SYNC:
vfs_sync(callid, &call);
break;
case VFS_NODE:
vfs_node(callid, &call);
break;
default:
ipc_answer_0(callid, ENOTSUP);
break;
164,6 → 176,7
/*
* Set a connectio handling function/fibril.
*/
async_set_pending(vfs_process_pending_mount);
async_set_client_connection(vfs_connection);
/*
/branches/dd/uspace/srv/vfs/vfs_ops.c
44,8 → 44,8
#include <string.h>
#include <bool.h>
#include <futex.h>
#include <rwlock.h>
#include <libadt/list.h>
#include <fibril_sync.h>
#include <adt/list.h>
#include <unistd.h>
#include <ctype.h>
#include <fcntl.h>
66,6 → 66,7
dev_handle_t dev_handle; /**< Device handle */
} pending_req_t;
 
FIBRIL_MUTEX_INITIALIZE(pending_lock);
LIST_INITIALIZE(pending_req);
 
/**
72,7 → 73,7
* This rwlock prevents the race between a triplet-to-VFS-node resolution and a
* concurrent VFS operation which modifies the file system namespace.
*/
RWLOCK_INITIALIZE(namespace_rwlock);
FIBRIL_RWLOCK_INITIALIZE(namespace_rwlock);
 
vfs_pair_t rootfs = {
.fs_handle = 0,
93,15 → 94,15
int phone;
aid_t msg;
ipc_call_t answer;
/* Resolve the path to the mountpoint. */
rwlock_write_lock(&namespace_rwlock);
fibril_rwlock_write_lock(&namespace_rwlock);
if (rootfs.fs_handle) {
/* We already have the root FS. */
if (str_cmp(mp, "/") == 0) {
/* Trying to mount root FS over root FS */
fibril_rwlock_write_unlock(&namespace_rwlock);
ipc_answer_0(rid, EBUSY);
rwlock_write_unlock(&namespace_rwlock);
return;
}
108,15 → 109,15
rc = vfs_lookup_internal(mp, L_DIRECTORY, &mp_res, NULL);
if (rc != EOK) {
/* The lookup failed for some reason. */
fibril_rwlock_write_unlock(&namespace_rwlock);
ipc_answer_0(rid, rc);
rwlock_write_unlock(&namespace_rwlock);
return;
}
mp_node = vfs_node_get(&mp_res);
if (!mp_node) {
fibril_rwlock_write_unlock(&namespace_rwlock);
ipc_answer_0(rid, ENOMEM);
rwlock_write_unlock(&namespace_rwlock);
return;
}
141,18 → 142,18
rc = ipc_data_write_start(phone, (void *)opts,
str_size(opts));
if (rc != EOK) {
vfs_release_phone(phone);
async_wait_for(msg, NULL);
vfs_release_phone(phone);
fibril_rwlock_write_unlock(&namespace_rwlock);
ipc_answer_0(rid, rc);
rwlock_write_unlock(&namespace_rwlock);
return;
}
vfs_release_phone(phone);
async_wait_for(msg, &rc);
vfs_release_phone(phone);
if (rc != EOK) {
fibril_rwlock_write_unlock(&namespace_rwlock);
ipc_answer_0(rid, rc);
rwlock_write_unlock(&namespace_rwlock);
return;
}
 
174,8 → 175,8
mr_node = vfs_node_get(&mr_res);
assert(mr_node);
fibril_rwlock_write_unlock(&namespace_rwlock);
ipc_answer_0(rid, rc);
rwlock_write_unlock(&namespace_rwlock);
return;
} else {
/*
182,8 → 183,8
* We can't resolve this without the root filesystem
* being mounted first.
*/
fibril_rwlock_write_unlock(&namespace_rwlock);
ipc_answer_0(rid, ENOENT);
rwlock_write_unlock(&namespace_rwlock);
return;
}
}
207,13 → 208,13
/* send connection */
rc = async_req_1_0(phone, IPC_M_CONNECTION_CLONE, mountee_phone);
if (rc != EOK) {
vfs_release_phone(phone);
async_wait_for(msg, NULL);
vfs_release_phone(phone);
/* Mount failed, drop reference to mp_node. */
if (mp_node)
vfs_node_put(mp_node);
ipc_answer_0(rid, rc);
rwlock_write_unlock(&namespace_rwlock);
fibril_rwlock_write_unlock(&namespace_rwlock);
return;
}
220,17 → 221,17
/* send the mount options */
rc = ipc_data_write_start(phone, (void *)opts, str_size(opts));
if (rc != EOK) {
vfs_release_phone(phone);
async_wait_for(msg, NULL);
vfs_release_phone(phone);
/* Mount failed, drop reference to mp_node. */
if (mp_node)
vfs_node_put(mp_node);
fibril_rwlock_write_unlock(&namespace_rwlock);
ipc_answer_0(rid, rc);
rwlock_write_unlock(&namespace_rwlock);
return;
}
vfs_release_phone(phone);
async_wait_for(msg, &rc);
vfs_release_phone(phone);
if (rc == EOK) {
rindex = (fs_index_t) IPC_GET_ARG1(answer);
254,7 → 255,7
}
 
ipc_answer_0(rid, rc);
rwlock_write_unlock(&namespace_rwlock);
fibril_rwlock_write_unlock(&namespace_rwlock);
}
 
/** Process pending mount requests */
263,9 → 264,10
link_t *cur;
loop:
fibril_mutex_lock(&pending_lock);
for (cur = pending_req.next; cur != &pending_req; cur = cur->next) {
pending_req_t *pr = list_get_instance(cur, pending_req_t, link);
 
fs_handle_t fs_handle = fs_name_to_handle(pr->fs_name, true);
if (!fs_handle)
continue;
282,8 → 284,11
free(pr->opts);
list_remove(cur);
free(pr);
fibril_mutex_unlock(&pending_lock);
fibril_yield();
goto loop;
}
fibril_mutex_unlock(&pending_lock);
}
 
void vfs_mount(ipc_callid_t rid, ipc_call_t *request)
462,7 → 467,9
pr->rid = rid;
pr->dev_handle = dev_handle;
link_initialize(&pr->link);
fibril_mutex_lock(&pending_lock);
list_append(&pr->link, &pending_req);
fibril_mutex_unlock(&pending_lock);
return;
}
490,7 → 497,7
ipc_answer_0(rid, ENOMEM);
return;
}
 
/*
* The POSIX interface is open(path, oflag, mode).
* We can receive oflags and mode along with the VFS_OPEN call; the path
503,29 → 510,30
int oflag = IPC_GET_ARG2(*request);
int mode = IPC_GET_ARG3(*request);
size_t len;
 
/*
* Make sure that we are called with exactly one of L_FILE and
* L_DIRECTORY.
* L_DIRECTORY. Make sure that the user does not pass L_OPEN.
*/
if ((lflag & (L_FILE | L_DIRECTORY)) == 0 ||
(lflag & (L_FILE | L_DIRECTORY)) == (L_FILE | L_DIRECTORY)) {
if (((lflag & (L_FILE | L_DIRECTORY)) == 0) ||
((lflag & (L_FILE | L_DIRECTORY)) == (L_FILE | L_DIRECTORY)) ||
((lflag & L_OPEN) != 0)) {
ipc_answer_0(rid, EINVAL);
return;
}
 
if (oflag & O_CREAT)
lflag |= L_CREATE;
if (oflag & O_EXCL)
lflag |= L_EXCLUSIVE;
 
ipc_callid_t callid;
 
if (!ipc_data_write_receive(&callid, &len)) {
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
return;
}
char *path = malloc(len + 1);
if (!path) {
ipc_answer_0(callid, ENOMEM);
532,6 → 540,7
ipc_answer_0(rid, ENOMEM);
return;
}
int rc;
if ((rc = ipc_data_write_finalize(callid, path, len))) {
ipc_answer_0(rid, rc);
546,40 → 555,40
* triplet.
*/
if (lflag & L_CREATE)
rwlock_write_lock(&namespace_rwlock);
fibril_rwlock_write_lock(&namespace_rwlock);
else
rwlock_read_lock(&namespace_rwlock);
 
fibril_rwlock_read_lock(&namespace_rwlock);
/* The path is now populated and we can call vfs_lookup_internal(). */
vfs_lookup_res_t lr;
rc = vfs_lookup_internal(path, lflag, &lr, NULL);
if (rc) {
rc = vfs_lookup_internal(path, lflag | L_OPEN, &lr, NULL);
if (rc != EOK) {
if (lflag & L_CREATE)
rwlock_write_unlock(&namespace_rwlock);
fibril_rwlock_write_unlock(&namespace_rwlock);
else
rwlock_read_unlock(&namespace_rwlock);
fibril_rwlock_read_unlock(&namespace_rwlock);
ipc_answer_0(rid, rc);
free(path);
return;
}
 
/* Path is no longer needed. */
free(path);
 
vfs_node_t *node = vfs_node_get(&lr);
if (lflag & L_CREATE)
rwlock_write_unlock(&namespace_rwlock);
fibril_rwlock_write_unlock(&namespace_rwlock);
else
rwlock_read_unlock(&namespace_rwlock);
 
fibril_rwlock_read_unlock(&namespace_rwlock);
/* Truncate the file if requested and if necessary. */
if (oflag & O_TRUNC) {
rwlock_write_lock(&node->contents_rwlock);
fibril_rwlock_write_lock(&node->contents_rwlock);
if (node->size) {
rc = vfs_truncate_internal(node->fs_handle,
node->dev_handle, node->index, 0);
if (rc) {
rwlock_write_unlock(&node->contents_rwlock);
fibril_rwlock_write_unlock(&node->contents_rwlock);
vfs_node_put(node);
ipc_answer_0(rid, rc);
return;
586,9 → 595,9
}
node->size = 0;
}
rwlock_write_unlock(&node->contents_rwlock);
fibril_rwlock_write_unlock(&node->contents_rwlock);
}
 
/*
* Get ourselves a file descriptor and the corresponding vfs_file_t
* structure.
601,10 → 610,87
}
vfs_file_t *file = vfs_file_get(fd);
file->node = node;
if (oflag & O_APPEND)
if (oflag & O_APPEND)
file->append = true;
/*
* The following increase in reference count is for the fact that the
* file is being opened and that a file structure is pointing to it.
* It is necessary so that the file will not disappear when
* vfs_node_put() is called. The reference will be dropped by the
* respective VFS_CLOSE.
*/
vfs_node_addref(node);
vfs_node_put(node);
/* Success! Return the new file descriptor to the client. */
ipc_answer_1(rid, EOK, fd);
}
 
void vfs_open_node(ipc_callid_t rid, ipc_call_t *request)
{
// FIXME: check for sanity of the supplied fs, dev and index
if (!vfs_files_init()) {
ipc_answer_0(rid, ENOMEM);
return;
}
/*
* The interface is open_node(fs, dev, index, oflag).
*/
vfs_lookup_res_t lr;
lr.triplet.fs_handle = IPC_GET_ARG1(*request);
lr.triplet.dev_handle = IPC_GET_ARG2(*request);
lr.triplet.index = IPC_GET_ARG3(*request);
int oflag = IPC_GET_ARG4(*request);
fibril_rwlock_read_lock(&namespace_rwlock);
int rc = vfs_open_node_internal(&lr);
if (rc != EOK) {
fibril_rwlock_read_unlock(&namespace_rwlock);
ipc_answer_0(rid, rc);
return;
}
vfs_node_t *node = vfs_node_get(&lr);
fibril_rwlock_read_unlock(&namespace_rwlock);
/* Truncate the file if requested and if necessary. */
if (oflag & O_TRUNC) {
fibril_rwlock_write_lock(&node->contents_rwlock);
if (node->size) {
rc = vfs_truncate_internal(node->fs_handle,
node->dev_handle, node->index, 0);
if (rc) {
fibril_rwlock_write_unlock(&node->contents_rwlock);
vfs_node_put(node);
ipc_answer_0(rid, rc);
return;
}
node->size = 0;
}
fibril_rwlock_write_unlock(&node->contents_rwlock);
}
/*
* Get ourselves a file descriptor and the corresponding vfs_file_t
* structure.
*/
int fd = vfs_fd_alloc();
if (fd < 0) {
vfs_node_put(node);
ipc_answer_0(rid, fd);
return;
}
vfs_file_t *file = vfs_file_get(fd);
file->node = node;
if (oflag & O_APPEND)
file->append = true;
/*
* The following increase in reference count is for the fact that the
* file is being opened and that a file structure is pointing to it.
* It is necessary so that the file will not disappear when
613,18 → 699,137
*/
vfs_node_addref(node);
vfs_node_put(node);
 
/* Success! Return the new file descriptor to the client. */
ipc_answer_1(rid, EOK, fd);
}
 
void vfs_close(ipc_callid_t rid, ipc_call_t *request)
void vfs_node(ipc_callid_t rid, ipc_call_t *request)
{
int fd = IPC_GET_ARG1(*request);
int rc = vfs_fd_free(fd);
/* Lookup the file structure corresponding to the file descriptor. */
vfs_file_t *file = vfs_file_get(fd);
if (!file) {
ipc_answer_0(rid, ENOENT);
return;
}
ipc_answer_3(rid, EOK, file->node->fs_handle, file->node->dev_handle,
file->node->index);
}
 
void vfs_device(ipc_callid_t rid, ipc_call_t *request)
{
int fd = IPC_GET_ARG1(*request);
/* Lookup the file structure corresponding to the file descriptor. */
vfs_file_t *file = vfs_file_get(fd);
if (!file) {
ipc_answer_0(rid, ENOENT);
return;
}
/*
* Lock the open file structure so that no other thread can manipulate
* the same open file at a time.
*/
fibril_mutex_lock(&file->lock);
int fs_phone = vfs_grab_phone(file->node->fs_handle);
/* Make a VFS_DEVICE request at the destination FS server. */
aid_t msg;
ipc_call_t answer;
msg = async_send_2(fs_phone, IPC_GET_METHOD(*request),
file->node->dev_handle, file->node->index, &answer);
vfs_release_phone(fs_phone);
 
/* Wait for reply from the FS server. */
ipcarg_t rc;
async_wait_for(msg, &rc);
fibril_mutex_unlock(&file->lock);
ipc_answer_1(rid, EOK, IPC_GET_ARG1(answer));
}
 
void vfs_sync(ipc_callid_t rid, ipc_call_t *request)
{
int fd = IPC_GET_ARG1(*request);
/* Lookup the file structure corresponding to the file descriptor. */
vfs_file_t *file = vfs_file_get(fd);
if (!file) {
ipc_answer_0(rid, ENOENT);
return;
}
/*
* Lock the open file structure so that no other thread can manipulate
* the same open file at a time.
*/
fibril_mutex_lock(&file->lock);
int fs_phone = vfs_grab_phone(file->node->fs_handle);
/* Make a VFS_SYMC request at the destination FS server. */
aid_t msg;
ipc_call_t answer;
msg = async_send_2(fs_phone, IPC_GET_METHOD(*request),
file->node->dev_handle, file->node->index, &answer);
 
vfs_release_phone(fs_phone);
 
/* Wait for reply from the FS server. */
ipcarg_t rc;
async_wait_for(msg, &rc);
fibril_mutex_unlock(&file->lock);
ipc_answer_0(rid, rc);
}
 
void vfs_close(ipc_callid_t rid, ipc_call_t *request)
{
int fd = IPC_GET_ARG1(*request);
/* Lookup the file structure corresponding to the file descriptor. */
vfs_file_t *file = vfs_file_get(fd);
if (!file) {
ipc_answer_0(rid, ENOENT);
return;
}
/*
* Lock the open file structure so that no other thread can manipulate
* the same open file at a time.
*/
fibril_mutex_lock(&file->lock);
int fs_phone = vfs_grab_phone(file->node->fs_handle);
/* Make a VFS_CLOSE request at the destination FS server. */
aid_t msg;
ipc_call_t answer;
msg = async_send_2(fs_phone, IPC_GET_METHOD(*request),
file->node->dev_handle, file->node->index, &answer);
 
vfs_release_phone(fs_phone);
/* Wait for reply from the FS server. */
ipcarg_t rc;
async_wait_for(msg, &rc);
fibril_mutex_unlock(&file->lock);
int retval = IPC_GET_ARG1(answer);
if (retval != EOK)
ipc_answer_0(rid, retval);
retval = vfs_fd_free(fd);
ipc_answer_0(rid, retval);
}
 
static void vfs_rdwr(ipc_callid_t rid, ipc_call_t *request, bool read)
{
 
667,7 → 872,7
* Lock the open file structure so that no other thread can manipulate
* the same open file at a time.
*/
futex_down(&file->lock);
fibril_mutex_lock(&file->lock);
 
/*
* Lock the file's node so that no other client can read/write to it at
674,9 → 879,9
* the same time.
*/
if (read)
rwlock_read_lock(&file->node->contents_rwlock);
fibril_rwlock_read_lock(&file->node->contents_rwlock);
else
rwlock_write_lock(&file->node->contents_rwlock);
fibril_rwlock_write_lock(&file->node->contents_rwlock);
 
if (file->node->type == VFS_NODE_DIRECTORY) {
/*
684,7 → 889,7
* while we are in readdir().
*/
assert(read);
rwlock_read_lock(&namespace_rwlock);
fibril_rwlock_read_lock(&namespace_rwlock);
}
int fs_phone = vfs_grab_phone(file->node->fs_handle);
704,31 → 909,32
* don't have to bother.
*/
ipc_forward_fast(callid, fs_phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
 
vfs_release_phone(fs_phone);
/* Wait for reply from the FS server. */
ipcarg_t rc;
async_wait_for(msg, &rc);
size_t bytes = IPC_GET_ARG1(answer);
 
if (file->node->type == VFS_NODE_DIRECTORY)
rwlock_read_unlock(&namespace_rwlock);
fibril_rwlock_read_unlock(&namespace_rwlock);
/* Unlock the VFS node. */
if (read)
rwlock_read_unlock(&file->node->contents_rwlock);
fibril_rwlock_read_unlock(&file->node->contents_rwlock);
else {
/* Update the cached version of node's size. */
if (rc == EOK)
file->node->size = IPC_GET_ARG2(answer);
rwlock_write_unlock(&file->node->contents_rwlock);
fibril_rwlock_write_unlock(&file->node->contents_rwlock);
}
/* Update the position pointer and unlock the open file. */
if (rc == EOK)
file->pos += bytes;
futex_up(&file->lock);
fibril_mutex_unlock(&file->lock);
/*
* FS server's reply is the final result of the whole operation we
762,40 → 968,40
}
 
off_t newpos;
futex_down(&file->lock);
fibril_mutex_lock(&file->lock);
if (whence == SEEK_SET) {
file->pos = off;
futex_up(&file->lock);
fibril_mutex_unlock(&file->lock);
ipc_answer_1(rid, EOK, off);
return;
}
if (whence == SEEK_CUR) {
if (file->pos + off < file->pos) {
futex_up(&file->lock);
fibril_mutex_unlock(&file->lock);
ipc_answer_0(rid, EOVERFLOW);
return;
}
file->pos += off;
newpos = file->pos;
futex_up(&file->lock);
fibril_mutex_unlock(&file->lock);
ipc_answer_1(rid, EOK, newpos);
return;
}
if (whence == SEEK_END) {
rwlock_read_lock(&file->node->contents_rwlock);
fibril_rwlock_read_lock(&file->node->contents_rwlock);
size_t size = file->node->size;
rwlock_read_unlock(&file->node->contents_rwlock);
fibril_rwlock_read_unlock(&file->node->contents_rwlock);
if (size + off < size) {
futex_up(&file->lock);
fibril_mutex_unlock(&file->lock);
ipc_answer_0(rid, EOVERFLOW);
return;
}
newpos = size + off;
futex_up(&file->lock);
fibril_mutex_unlock(&file->lock);
ipc_answer_1(rid, EOK, newpos);
return;
}
futex_up(&file->lock);
fibril_mutex_unlock(&file->lock);
ipc_answer_0(rid, EINVAL);
}
 
824,16 → 1030,16
ipc_answer_0(rid, ENOENT);
return;
}
futex_down(&file->lock);
fibril_mutex_lock(&file->lock);
 
rwlock_write_lock(&file->node->contents_rwlock);
fibril_rwlock_write_lock(&file->node->contents_rwlock);
rc = vfs_truncate_internal(file->node->fs_handle,
file->node->dev_handle, file->node->index, size);
if (rc == EOK)
file->node->size = size;
rwlock_write_unlock(&file->node->contents_rwlock);
fibril_rwlock_write_unlock(&file->node->contents_rwlock);
 
futex_up(&file->lock);
fibril_mutex_unlock(&file->lock);
ipc_answer_0(rid, (ipcarg_t)rc);
}
 
863,10 → 1069,10
}
path[len] = '\0';
rwlock_write_lock(&namespace_rwlock);
fibril_rwlock_write_lock(&namespace_rwlock);
int lflag = L_DIRECTORY | L_CREATE | L_EXCLUSIVE;
rc = vfs_lookup_internal(path, lflag, NULL, NULL);
rwlock_write_unlock(&namespace_rwlock);
fibril_rwlock_write_unlock(&namespace_rwlock);
free(path);
ipc_answer_0(rid, rc);
}
897,13 → 1103,13
}
path[len] = '\0';
rwlock_write_lock(&namespace_rwlock);
fibril_rwlock_write_lock(&namespace_rwlock);
lflag &= L_DIRECTORY; /* sanitize lflag */
vfs_lookup_res_t lr;
rc = vfs_lookup_internal(path, lflag | L_UNLINK, &lr, NULL);
free(path);
if (rc != EOK) {
rwlock_write_unlock(&namespace_rwlock);
fibril_rwlock_write_unlock(&namespace_rwlock);
ipc_answer_0(rid, rc);
return;
}
917,7 → 1123,7
futex_down(&nodes_futex);
node->lnkcnt--;
futex_up(&nodes_futex);
rwlock_write_unlock(&namespace_rwlock);
fibril_rwlock_write_unlock(&namespace_rwlock);
vfs_node_put(node);
ipc_answer_0(rid, EOK);
}
998,11 → 1204,11
vfs_lookup_res_t old_lr;
vfs_lookup_res_t new_lr;
vfs_lookup_res_t new_par_lr;
rwlock_write_lock(&namespace_rwlock);
fibril_rwlock_write_lock(&namespace_rwlock);
/* Lookup the node belonging to the old file name. */
rc = vfs_lookup_internal(oldc, L_NONE, &old_lr, NULL);
if (rc != EOK) {
rwlock_write_unlock(&namespace_rwlock);
fibril_rwlock_write_unlock(&namespace_rwlock);
ipc_answer_0(rid, rc);
free(old);
free(new);
1010,7 → 1216,7
}
vfs_node_t *old_node = vfs_node_get(&old_lr);
if (!old_node) {
rwlock_write_unlock(&namespace_rwlock);
fibril_rwlock_write_unlock(&namespace_rwlock);
ipc_answer_0(rid, ENOMEM);
free(old);
free(new);
1019,7 → 1225,7
/* Determine the path to the parent of the node with the new name. */
char *parentc = str_dup(newc);
if (!parentc) {
rwlock_write_unlock(&namespace_rwlock);
fibril_rwlock_write_unlock(&namespace_rwlock);
ipc_answer_0(rid, rc);
free(old);
free(new);
1034,7 → 1240,7
rc = vfs_lookup_internal(parentc, L_NONE, &new_par_lr, NULL);
free(parentc); /* not needed anymore */
if (rc != EOK) {
rwlock_write_unlock(&namespace_rwlock);
fibril_rwlock_write_unlock(&namespace_rwlock);
ipc_answer_0(rid, rc);
free(old);
free(new);
1043,7 → 1249,7
/* Check whether linking to the same file system instance. */
if ((old_node->fs_handle != new_par_lr.triplet.fs_handle) ||
(old_node->dev_handle != new_par_lr.triplet.dev_handle)) {
rwlock_write_unlock(&namespace_rwlock);
fibril_rwlock_write_unlock(&namespace_rwlock);
ipc_answer_0(rid, EXDEV); /* different file systems */
free(old);
free(new);
1059,7 → 1265,7
case EOK:
new_node = vfs_node_get(&new_lr);
if (!new_node) {
rwlock_write_unlock(&namespace_rwlock);
fibril_rwlock_write_unlock(&namespace_rwlock);
ipc_answer_0(rid, ENOMEM);
free(old);
free(new);
1070,7 → 1276,7
futex_up(&nodes_futex);
break;
default:
rwlock_write_unlock(&namespace_rwlock);
fibril_rwlock_write_unlock(&namespace_rwlock);
ipc_answer_0(rid, ENOTEMPTY);
free(old);
free(new);
1079,7 → 1285,7
/* Create the new link for the new name. */
rc = vfs_lookup_internal(newc, L_LINK, NULL, NULL, old_node->index);
if (rc != EOK) {
rwlock_write_unlock(&namespace_rwlock);
fibril_rwlock_write_unlock(&namespace_rwlock);
if (new_node)
vfs_node_put(new_node);
ipc_answer_0(rid, rc);
1093,7 → 1299,7
/* Destroy the link for the old name. */
rc = vfs_lookup_internal(oldc, L_UNLINK, NULL, NULL);
if (rc != EOK) {
rwlock_write_unlock(&namespace_rwlock);
fibril_rwlock_write_unlock(&namespace_rwlock);
vfs_node_put(old_node);
if (new_node)
vfs_node_put(new_node);
1105,7 → 1311,7
futex_down(&nodes_futex);
old_node->lnkcnt--;
futex_up(&nodes_futex);
rwlock_write_unlock(&namespace_rwlock);
fibril_rwlock_write_unlock(&namespace_rwlock);
vfs_node_put(old_node);
if (new_node)
vfs_node_put(new_node);
1116,4 → 1322,4
 
/**
* @}
*/
*/
/branches/dd/uspace/srv/vfs/vfs_register.c
45,14 → 45,14
#include <string.h>
#include <ctype.h>
#include <bool.h>
#include <futex.h>
#include <libadt/list.h>
#include <fibril_sync.h>
#include <adt/list.h>
#include <as.h>
#include <assert.h>
#include <atomic.h>
#include "vfs.h"
 
atomic_t fs_head_futex = FUTEX_INITIALIZER;
FIBRIL_MUTEX_INITIALIZE(fs_head_lock);
link_t fs_head;
 
atomic_t fs_handle_next = {
159,7 → 159,7
return;
}
link_initialize(&fs_info->fs_link);
futex_initialize(&fs_info->phone_futex, 1);
fibril_mutex_initialize(&fs_info->phone_lock);
rc = ipc_data_write_finalize(callid, &fs_info->vfs_info, size);
if (rc != EOK) {
180,8 → 180,7
return;
}
futex_down(&fs_head_futex);
fibril_inc_sercount();
fibril_mutex_lock(&fs_head_lock);
 
/*
* Check for duplicit registrations.
191,8 → 190,7
* We already register a fs like this.
*/
dprintf("FS is already registered.\n");
fibril_dec_sercount();
futex_up(&fs_head_futex);
fibril_mutex_unlock(&fs_head_lock);
free(fs_info);
ipc_answer_0(callid, EEXISTS);
ipc_answer_0(rid, EEXISTS);
214,8 → 212,7
if (IPC_GET_METHOD(call) != IPC_M_CONNECT_TO_ME) {
dprintf("Unexpected call, method = %d\n", IPC_GET_METHOD(call));
list_remove(&fs_info->fs_link);
fibril_dec_sercount();
futex_up(&fs_head_futex);
fibril_mutex_unlock(&fs_head_lock);
free(fs_info);
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
233,8 → 230,7
if (!ipc_share_in_receive(&callid, &size)) {
dprintf("Unexpected call, method = %d\n", IPC_GET_METHOD(call));
list_remove(&fs_info->fs_link);
fibril_dec_sercount();
futex_up(&fs_head_futex);
fibril_mutex_unlock(&fs_head_lock);
ipc_hangup(fs_info->phone);
free(fs_info);
ipc_answer_0(callid, EINVAL);
248,8 → 244,7
if (size != PLB_SIZE) {
dprintf("Client suggests wrong size of PFB, size = %d\n", size);
list_remove(&fs_info->fs_link);
fibril_dec_sercount();
futex_up(&fs_head_futex);
fibril_mutex_unlock(&fs_head_lock);
ipc_hangup(fs_info->phone);
free(fs_info);
ipc_answer_0(callid, EINVAL);
273,16 → 268,10
fs_info->fs_handle = (fs_handle_t) atomic_postinc(&fs_handle_next);
ipc_answer_1(rid, EOK, (ipcarg_t) fs_info->fs_handle);
fibril_dec_sercount();
futex_up(&fs_head_futex);
fibril_mutex_unlock(&fs_head_lock);
dprintf("\"%.*s\" filesystem successfully registered, handle=%d.\n",
FS_NAME_MAXLEN, fs_info->vfs_info.name, fs_info->fs_handle);
/* Process pending mount requests possibly waiting
* for this filesystem implementation.
*/
vfs_process_pending_mount();
}
 
/** For a given file system handle, implement policy for allocating a phone.
302,28 → 291,18
* be more demanding). Instead, we simply take the respective
* phone_futex and keep it until vfs_release_phone().
*/
futex_down(&fs_head_futex);
fibril_mutex_lock(&fs_head_lock);
link_t *cur;
fs_info_t *fs;
for (cur = fs_head.next; cur != &fs_head; cur = cur->next) {
fs = list_get_instance(cur, fs_info_t, fs_link);
if (fs->fs_handle == handle) {
futex_up(&fs_head_futex);
/*
* For now, take the futex unconditionally.
* Oh yeah, serialization rocks.
* It will be up'ed in vfs_release_phone().
*/
futex_down(&fs->phone_futex);
/*
* Avoid deadlock with other fibrils in the same thread
* by disabling fibril preemption.
*/
fibril_inc_sercount();
return fs->phone;
fibril_mutex_unlock(&fs_head_lock);
fibril_mutex_lock(&fs->phone_lock);
return fs->phone;
}
}
futex_up(&fs_head_futex);
fibril_mutex_unlock(&fs_head_lock);
return 0;
}
 
335,23 → 314,18
{
bool found = false;
 
/*
* Undo the fibril_inc_sercount() done in vfs_grab_phone().
*/
fibril_dec_sercount();
futex_down(&fs_head_futex);
fibril_mutex_lock(&fs_head_lock);
link_t *cur;
for (cur = fs_head.next; cur != &fs_head; cur = cur->next) {
fs_info_t *fs = list_get_instance(cur, fs_info_t, fs_link);
if (fs->phone == phone) {
found = true;
futex_up(&fs_head_futex);
futex_up(&fs->phone_futex);
fibril_mutex_unlock(&fs_head_lock);
fibril_mutex_unlock(&fs->phone_lock);
return;
}
}
futex_up(&fs_head_futex);
fibril_mutex_unlock(&fs_head_lock);
 
/*
* Not good to get here.
362,8 → 336,8
/** Convert file system name to its handle.
*
* @param name File system name.
* @param lock If true, the function will down and up the
* fs_head_futex.
* @param lock If true, the function will lock and unlock the
* fs_head_lock.
*
* @return File system handle or zero if file system not found.
*/
372,7 → 346,7
int handle = 0;
if (lock)
futex_down(&fs_head_futex);
fibril_mutex_lock(&fs_head_lock);
link_t *cur;
for (cur = fs_head.next; cur != &fs_head; cur = cur->next) {
fs_info_t *fs = list_get_instance(cur, fs_info_t, fs_link);
382,7 → 356,7
}
}
if (lock)
futex_up(&fs_head_futex);
fibril_mutex_unlock(&fs_head_lock);
return handle;
}
 
/branches/dd/uspace/srv/vfs/vfs.h
28,70 → 28,26
 
/** @addtogroup fs
* @{
*/
*/
 
#ifndef VFS_VFS_H_
#define VFS_VFS_H_
 
#include <ipc/ipc.h>
#include <libadt/list.h>
#include <adt/list.h>
#include <fibril_sync.h>
#include <futex.h>
#include <rwlock.h>
#include <sys/types.h>
#include <devmap.h>
#include <bool.h>
#include <ipc/vfs.h>
 
// FIXME: according to CONFIG_DEBUG
// #define dprintf(...) printf(__VA_ARGS__)
// #define dprintf(...) printf(__VA_ARGS__)
 
#define dprintf(...)
 
#define VFS_FIRST IPC_FIRST_USER_METHOD
 
/* Basic types. */
typedef int16_t fs_handle_t;
typedef uint32_t fs_index_t;
 
typedef enum {
VFS_READ = VFS_FIRST,
VFS_WRITE,
VFS_TRUNCATE,
VFS_MOUNT,
VFS_UNMOUNT,
VFS_LAST_CMN, /* keep this the last member of this enum */
} vfs_request_cmn_t;
 
typedef enum {
VFS_LOOKUP = VFS_LAST_CMN,
VFS_MOUNTED,
VFS_DESTROY,
VFS_LAST_CLNT, /* keep this the last member of this enum */
} vfs_request_clnt_t;
 
typedef enum {
VFS_REGISTER = VFS_LAST_CMN,
VFS_OPEN,
VFS_CLOSE,
VFS_SEEK,
VFS_MKDIR,
VFS_UNLINK,
VFS_RENAME,
VFS_LAST_SRV, /* keep this the last member of this enum */
} vfs_request_srv_t;
 
#define FS_NAME_MAXLEN 20
 
/**
* A structure like this is passed to VFS by each individual FS upon its
* registration. It assosiates a human-readable identifier with each
* registered FS.
*/
typedef struct {
/** Unique identifier of the fs. */
char name[FS_NAME_MAXLEN + 1];
} vfs_info_t;
 
/**
* A structure like this will be allocated for each registered file system.
*/
typedef struct {
98,7 → 54,7
link_t fs_link;
vfs_info_t vfs_info;
fs_handle_t fs_handle;
futex_t phone_futex; /**< Phone serializing futex. */
fibril_mutex_t phone_lock;
ipcarg_t phone;
} fs_info_t;
 
105,8 → 61,8
/**
* VFS_PAIR uniquely represents a file system instance.
*/
#define VFS_PAIR \
fs_handle_t fs_handle; \
#define VFS_PAIR \
fs_handle_t fs_handle; \
dev_handle_t dev_handle;
 
/**
116,8 → 72,8
* @note fs_handle, dev_handle and index are meant to be returned in one
* IPC reply.
*/
#define VFS_TRIPLET \
VFS_PAIR; \
#define VFS_TRIPLET \
VFS_PAIR; \
fs_index_t index;
 
typedef struct {
128,45 → 84,6
VFS_TRIPLET;
} vfs_triplet_t;
 
/*
* Lookup flags.
*/
/**
* No lookup flags used.
*/
#define L_NONE 0
/**
* Lookup will succeed only if the object is a regular file. If L_CREATE is
* specified, an empty file will be created. This flag is mutually exclusive
* with L_DIRECTORY.
*/
#define L_FILE 1
/**
* Lookup wil succeed only if the object is a directory. If L_CREATE is
* specified, an empty directory will be created. This flag is mutually
* exclusive with L_FILE.
*/
#define L_DIRECTORY 2
/**
* When used with L_CREATE, L_EXCLUSIVE will cause the lookup to fail if the
* object already exists. L_EXCLUSIVE is implied when L_DIRECTORY is used.
*/
#define L_EXCLUSIVE 4
/**
* L_CREATE is used for creating both regular files and directories.
*/
#define L_CREATE 8
/**
* L_LINK is used for linking to an already existing nodes.
*/
#define L_LINK 16
/**
* L_UNLINK is used to remove leaves from the file system namespace. This flag
* cannot be passed directly by the client, but will be set by VFS during
* VFS_UNLINK.
*/
#define L_UNLINK 32
 
typedef enum vfs_node_type {
VFS_NODE_UNKNOWN,
VFS_NODE_FILE,
205,7 → 122,7
/**
* Holding this rwlock prevents modifications of the node's contents.
*/
rwlock_t contents_rwlock;
fibril_rwlock_t contents_rwlock;
} vfs_node_t;
 
/**
214,7 → 131,7
*/
typedef struct {
/** Serializes access to this open file. */
futex_t lock;
fibril_mutex_t lock;
 
vfs_node_t *node;
234,10 → 151,6
 
extern vfs_pair_t rootfs; /**< Root file system. */
 
#define MAX_PATH_LEN (64 * 1024)
 
#define PLB_SIZE (2 * MAX_PATH_LEN)
 
/** Each instance of this type describes one path lookup in progress. */
typedef struct {
link_t plb_link; /**< Active PLB entries list link. */
252,7 → 165,7
#define MAX_MNTOPTS_LEN 256
 
/** Holding this rwlock prevents changes in file system namespace. */
extern rwlock_t namespace_rwlock;
extern fibril_rwlock_t namespace_rwlock;
 
extern int vfs_grab_phone(fs_handle_t);
extern void vfs_release_phone(int);
259,8 → 172,9
 
extern fs_handle_t fs_name_to_handle(char *, bool);
 
extern int vfs_lookup_internal(char *, int, vfs_lookup_res_t *, vfs_pair_t *,
...);
extern int vfs_lookup_internal(char *, int, vfs_lookup_res_t *,
vfs_pair_t *, ...);
extern int vfs_open_node_internal(vfs_lookup_res_t *);
 
extern bool vfs_nodes_init(void);
extern vfs_node_t *vfs_node_get(vfs_lookup_res_t *);
283,6 → 197,10
extern void vfs_register(ipc_callid_t, ipc_call_t *);
extern void vfs_mount(ipc_callid_t, ipc_call_t *);
extern void vfs_open(ipc_callid_t, ipc_call_t *);
extern void vfs_open_node(ipc_callid_t, ipc_call_t *);
extern void vfs_device(ipc_callid_t, ipc_call_t *);
extern void vfs_sync(ipc_callid_t, ipc_call_t *);
extern void vfs_node(ipc_callid_t, ipc_call_t *);
extern void vfs_close(ipc_callid_t, ipc_call_t *);
extern void vfs_read(ipc_callid_t, ipc_call_t *);
extern void vfs_write(ipc_callid_t, ipc_call_t *);
/branches/dd/uspace/srv/vfs/vfs_node.c
39,8 → 39,8
#include <stdlib.h>
#include <string.h>
#include <futex.h>
#include <rwlock.h>
#include <libadt/hash_table.h>
#include <fibril_sync.h>
#include <adt/hash_table.h>
#include <assert.h>
#include <async.h>
#include <errno.h>
177,10 → 177,10
node->lnkcnt = result->lnkcnt;
node->type = result->type;
link_initialize(&node->nh_link);
rwlock_initialize(&node->contents_rwlock);
fibril_rwlock_initialize(&node->contents_rwlock);
hash_table_insert(&nodes, key, &node->nh_link);
} else {
node = hash_table_get_instance(tmp, vfs_node_t, nh_link);
node = hash_table_get_instance(tmp, vfs_node_t, nh_link);
if (node->type == VFS_NODE_UNKNOWN &&
result->type != VFS_NODE_UNKNOWN) {
/* Upgrade the node type. */
233,4 → 233,4
 
/**
* @}
*/
*/
/branches/dd/uspace/srv/vfs/vfs_lookup.c
28,10 → 28,10
 
/** @addtogroup fs
* @{
*/
*/
 
/**
* @file vfs_lookup.c
* @file vfs_lookup.c
* @brief
*/
 
43,26 → 43,27
#include <stdarg.h>
#include <bool.h>
#include <futex.h>
#include <libadt/list.h>
#include <adt/list.h>
#include <vfs/canonify.h>
 
#define min(a, b) ((a) < (b) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))
 
futex_t plb_futex = FUTEX_INITIALIZER;
link_t plb_head; /**< PLB entry ring buffer. */
link_t plb_head; /**< PLB entry ring buffer. */
uint8_t *plb = NULL;
 
/** Perform a path lookup.
*
* @param path Path to be resolved; it must be a NULL-terminated
* string.
* @param lflag Flags to be used during lookup.
* @param result Empty structure where the lookup result will be stored.
* Can be NULL.
* @param altroot If non-empty, will be used instead of rootfs as the root
* of the whole VFS tree.
* @param path Path to be resolved; it must be a NULL-terminated
* string.
* @param lflag Flags to be used during lookup.
* @param result Empty structure where the lookup result will be stored.
* Can be NULL.
* @param altroot If non-empty, will be used instead of rootfs as the root
* of the whole VFS tree.
*
* @return EOK on success or an error code from errno.h.
* @return EOK on success or an error code from errno.h.
*
*/
int vfs_lookup_internal(char *path, int lflag, vfs_lookup_res_t *result,
vfs_pair_t *altroot, ...)
163,10 → 164,10
(ipcarg_t) root->dev_handle, (ipcarg_t) lflag, (ipcarg_t) index,
&answer);
vfs_release_phone(phone);
 
ipcarg_t rc;
async_wait_for(req, &rc);
 
futex_down(&plb_futex);
list_remove(&entry.plb_link);
/*
176,7 → 177,7
memset(plb, 0, cnt2);
futex_up(&plb_futex);
 
if ((rc == EOK) && result) {
if ((rc == EOK) && (result)) {
result->triplet.fs_handle = (fs_handle_t) IPC_GET_ARG1(answer);
result->triplet.dev_handle = (dev_handle_t) IPC_GET_ARG2(answer);
result->triplet.index = (fs_index_t) IPC_GET_ARG3(answer);
193,6 → 194,39
return rc;
}
 
/** Perform a node open operation.
*
* @return EOK on success or an error code from errno.h.
*
*/
int vfs_open_node_internal(vfs_lookup_res_t *result)
{
int phone = vfs_grab_phone(result->triplet.fs_handle);
ipc_call_t answer;
aid_t req = async_send_2(phone, VFS_OPEN_NODE,
(ipcarg_t) result->triplet.dev_handle,
(ipcarg_t) result->triplet.index, &answer);
vfs_release_phone(phone);
ipcarg_t rc;
async_wait_for(req, &rc);
if (rc == EOK) {
result->size = (size_t) IPC_GET_ARG1(answer);
result->lnkcnt = (unsigned) IPC_GET_ARG2(answer);
if (IPC_GET_ARG3(answer) & L_FILE)
result->type = VFS_NODE_FILE;
else if (IPC_GET_ARG3(answer) & L_DIRECTORY)
result->type = VFS_NODE_DIRECTORY;
else
result->type = VFS_NODE_UNKNOWN;
}
return rc;
}
 
/**
* @}
*/
/branches/dd/uspace/srv/vfs/vfs_file.c
40,6 → 40,8
#include <string.h>
#include <assert.h>
#include <bool.h>
#include <fibril.h>
#include <fibril_sync.h>
#include "vfs.h"
 
/**
57,7 → 59,7
* This resource being per-connection and, in the first place, per-fibril, we
* don't need to protect it by a futex.
*/
__thread vfs_file_t **files = NULL;
fibril_local vfs_file_t **files = NULL;
 
/** Initialize the table of open files. */
bool vfs_files_init(void)
89,7 → 91,7
return ENOMEM;
memset(files[i], 0, sizeof(vfs_file_t));
futex_initialize(&files[i]->lock, 1);
fibril_mutex_initialize(&files[i]->lock);
vfs_file_addref(files[i]);
return (int) i;
}
/branches/dd/uspace/Makefile
37,6 → 37,8
lib/libblock \
lib/softint \
lib/softfloat \
srv/bd/ata_bd \
srv/bd/file_bd \
srv/bd/gxe_bd \
srv/bd/rd \
srv/ns \
54,6 → 56,7
app/trace \
app/klog \
app/init \
app/getvc \
app/bdsh
 
ifeq ($(UARCH),amd64)
70,10 → 73,10
 
ifeq ($(UARCH),sparc64)
DIRS += \
srv/fhc \
srv/obio \
srv/pci \
app/lspci
app/lspci \
srv/cir/fhc \
srv/cir/obio
endif
 
BUILDS := $(addsuffix .build,$(DIRS))
/branches/dd/boot/arch/sparc64/loader/Makefile
103,16 → 103,18
$(USPACEDIR)/srv/console/console \
$(USPACEDIR)/srv/pci/pci \
$(USPACEDIR)/srv/fs/devfs/devfs \
$(USPACEDIR)/srv/fs/tmpfs/tmpfs
$(USPACEDIR)/srv/fs/tmpfs/tmpfs \
$(USPACEDIR)/srv/bd/file_bd/file_bd
 
ifeq ($(MACHINE),generic)
RD_SRVS += \
$(USPACEDIR)/srv/fs/fat/fat \
$(USPACEDIR)/srv/fhc/fhc \
$(USPACEDIR)/srv/obio/obio
$(USPACEDIR)/srv/cir/fhc/fhc \
$(USPACEDIR)/srv/cir/obio/obio
endif
 
RD_APPS = \
$(USPACEDIR)/app/getvc/getvc \
$(USPACEDIR)/app/tetris/tetris \
$(USPACEDIR)/app/trace/trace \
$(USPACEDIR)/app/bdsh/bdsh \
/branches/dd/boot/arch/ia64/loader/types.h
41,7 → 41,4
typedef uint64_t uintptr_t;
typedef uint64_t unative_t;
 
typedef unsigned long count_t;
 
 
#endif
/branches/dd/boot/arch/ia64/loader/Makefile
102,9 → 102,11
$(USPACEDIR)/srv/console/console \
$(USPACEDIR)/srv/fs/devfs/devfs \
$(USPACEDIR)/srv/fs/tmpfs/tmpfs \
$(USPACEDIR)/srv/fs/fat/fat
$(USPACEDIR)/srv/fs/fat/fat \
$(USPACEDIR)/srv/bd/file_bd/file_bd
 
RD_APPS = \
$(USPACEDIR)/app/getvc/getvc \
$(USPACEDIR)/app/tetris/tetris \
$(USPACEDIR)/app/tester/tester \
$(USPACEDIR)/app/trace/trace \
/branches/dd/boot/arch/arm32/loader/Makefile
91,9 → 91,12
$(USPACEDIR)/srv/console/console \
$(USPACEDIR)/srv/fs/devfs/devfs \
$(USPACEDIR)/srv/fs/tmpfs/tmpfs \
$(USPACEDIR)/srv/fs/fat/fat
$(USPACEDIR)/srv/fs/fat/fat \
$(USPACEDIR)/srv/bd/file_bd/file_bd \
$(USPACEDIR)/srv/bd/gxe_bd/gxe_bd
 
RD_APPS = \
$(USPACEDIR)/app/getvc/getvc \
$(USPACEDIR)/app/tetris/tetris \
$(USPACEDIR)/app/tester/tester \
$(USPACEDIR)/app/trace/trace \
/branches/dd/boot/arch/ppc32/loader/Makefile
90,9 → 90,11
$(USPACEDIR)/srv/console/console \
$(USPACEDIR)/srv/fs/devfs/devfs \
$(USPACEDIR)/srv/fs/tmpfs/tmpfs \
$(USPACEDIR)/srv/fs/fat/fat
$(USPACEDIR)/srv/fs/fat/fat \
$(USPACEDIR)/srv/bd/file_bd/file_bd
 
RD_APPS = \
$(USPACEDIR)/app/getvc/getvc \
$(USPACEDIR)/app/tetris/tetris \
$(USPACEDIR)/app/tester/tester \
$(USPACEDIR)/app/trace/trace \
/branches/dd/boot/arch/amd64/Makefile.inc
49,9 → 49,12
$(USPACEDIR)/srv/console/console \
$(USPACEDIR)/srv/fs/devfs/devfs \
$(USPACEDIR)/srv/fs/tmpfs/tmpfs \
$(USPACEDIR)/srv/fs/fat/fat
$(USPACEDIR)/srv/fs/fat/fat \
$(USPACEDIR)/srv/bd/ata_bd/ata_bd \
$(USPACEDIR)/srv/bd/file_bd/file_bd
 
RD_APPS = \
$(USPACEDIR)/app/getvc/getvc \
$(USPACEDIR)/app/tetris/tetris \
$(USPACEDIR)/app/tester/tester \
$(USPACEDIR)/app/trace/trace \
/branches/dd/boot/arch/mips32/loader/Makefile
104,9 → 104,11
$(USPACEDIR)/srv/fs/devfs/devfs \
$(USPACEDIR)/srv/fs/tmpfs/tmpfs \
$(USPACEDIR)/srv/fs/fat/fat \
$(USPACEDIR)/srv/bd/file_bd/file_bd \
$(USPACEDIR)/srv/bd/gxe_bd/gxe_bd
 
RD_APPS = \
$(USPACEDIR)/app/getvc/getvc \
$(USPACEDIR)/app/tetris/tetris \
$(USPACEDIR)/app/tester/tester \
$(USPACEDIR)/app/trace/trace \
/branches/dd/boot/arch/ia32/Makefile.inc
49,9 → 49,12
$(USPACEDIR)/srv/console/console \
$(USPACEDIR)/srv/fs/devfs/devfs \
$(USPACEDIR)/srv/fs/tmpfs/tmpfs \
$(USPACEDIR)/srv/fs/fat/fat
$(USPACEDIR)/srv/fs/fat/fat \
$(USPACEDIR)/srv/bd/ata_bd/ata_bd \
$(USPACEDIR)/srv/bd/file_bd/file_bd
 
RD_APPS = \
$(USPACEDIR)/app/getvc/getvc \
$(USPACEDIR)/app/tetris/tetris \
$(USPACEDIR)/app/tester/tester \
$(USPACEDIR)/app/trace/trace \