/branches/dynload/kernel/test/test.c |
---|
34,6 → 34,8 |
#include <test.h> |
bool test_quiet; |
test_t tests[] = { |
#include <atomic/atomic1.def> |
#include <avltree/avltree1.def> |
/branches/dynload/kernel/test/btree/btree1.c |
---|
33,15 → 33,14 |
static void *data = (void *) 0xdeadbeef; |
char * test_btree1(bool quiet) |
char *test_btree1(void) |
{ |
btree_t t; |
int i; |
btree_create(&t); |
if (!quiet) |
printf("Inserting keys.\n"); |
TPRINTF("Inserting keys.\n"); |
btree_insert(&t, 19, data, NULL); |
btree_insert(&t, 20, data, NULL); |
btree_insert(&t, 21, data, NULL); |
78,11 → 77,10 |
for (i = 100; i >= 50; i--) |
btree_insert(&t, i, data, NULL); |
if (!quiet) |
if (!test_quiet) |
btree_print(&t); |
if (!quiet) |
printf("Removing keys.\n"); |
TPRINTF("Removing keys.\n"); |
btree_remove(&t, 50, NULL); |
btree_remove(&t, 49, NULL); |
btree_remove(&t, 51, NULL); |
158,7 → 156,7 |
btree_remove(&t, 35, NULL); |
btree_remove(&t, 36, NULL); |
if (!quiet) |
if (!test_quiet) |
btree_print(&t); |
return NULL; |
/branches/dynload/kernel/test/avltree/avltree1.c |
---|
41,7 → 41,7 |
*/ |
static avltree_node_t avltree_nodes[NODE_COUNT]; |
/* |
/* |
* head of free nodes' list: |
*/ |
static avltree_node_t *first_free_node = NULL; |
58,11 → 58,11 |
if (!node) |
return NULL; |
if (node->lft) { |
tmp = test_tree_parents(node->lft); |
if (tmp != node) { |
printf("Bad parent pointer key: %" PRIu64 |
TPRINTF("Bad parent pointer key: %" PRIu64 |
", address: %p\n", tmp->key, node->lft); |
} |
} |
69,7 → 69,7 |
if (node->rgt) { |
tmp = test_tree_parents(node->rgt); |
if (tmp != node) { |
printf("Bad parent pointer key: %" PRIu64 |
TPRINTF("Bad parent pointer key: %" PRIu64 |
", address: %p\n", |
tmp->key,node->rgt); |
} |
80,49 → 80,50 |
int test_tree_balance(avltree_node_t *node) |
{ |
int h1, h2, diff; |
if (!node) |
return 0; |
h1 = test_tree_balance(node->lft); |
h2 = test_tree_balance(node->rgt); |
diff = h2 - h1; |
if (diff != node->balance || (diff != -1 && diff != 0 && diff != 1)) { |
printf("Bad balance\n"); |
} |
return h1 > h2 ? h1 + 1 : h2 + 1; |
if ((diff != node->balance) || ((diff != -1) && (diff != 0) && (diff != 1))) |
TPRINTF("Bad balance\n"); |
return ((h1 > h2) ? (h1 + 1) : (h2 + 1)); |
} |
/** |
* Prints the structure of the node, which is level levels from the top of the |
* tree. |
* tree. |
*/ |
static void |
print_tree_structure_flat(avltree_node_t *node, int level) |
static void print_tree_structure_flat(avltree_node_t *node, int level) |
{ |
/* |
* You can set the maximum level as high as you like. |
* Most of the time, you'll want to debug code using small trees, |
* so that a large level indicates a loop, which is a bug. |
* Most of the time, you'll want to debug code using small trees, |
* so that a large level indicates a loop, which is a bug. |
*/ |
if (level > 16) { |
printf("[...]"); |
TPRINTF("[...]"); |
return; |
} |
if (node == NULL) |
return; |
printf("%" PRIu64 "[%" PRIu8 "]", node->key, node->balance); |
TPRINTF("%" PRIu64 "[%" PRIu8 "]", node->key, node->balance); |
if (node->lft != NULL || node->rgt != NULL) { |
printf("("); |
TPRINTF("("); |
print_tree_structure_flat(node->lft, level + 1); |
if (node->rgt != NULL) { |
printf(","); |
TPRINTF(","); |
print_tree_structure_flat(node->rgt, level + 1); |
} |
printf(")"); |
TPRINTF(")"); |
} |
} |
129,10 → 130,10 |
static void alloc_avltree_node_prepare(void) |
{ |
int i; |
for (i = 0; i < NODE_COUNT - 1; i++) { |
for (i = 0; i < NODE_COUNT - 1; i++) |
avltree_nodes[i].par = &avltree_nodes[i + 1]; |
} |
avltree_nodes[i].par = NULL; |
/* |
139,37 → 140,44 |
* Node keys which will be used for insertion. Up to NODE_COUNT size of |
* array. |
*/ |
/* First tree node and same key */ |
avltree_nodes[0].key = 60; |
avltree_nodes[1].key = 60; |
avltree_nodes[2].key = 60; |
/* LL rotation */ |
avltree_nodes[3].key = 50; |
avltree_nodes[4].key = 40; |
avltree_nodes[5].key = 30; |
/* LR rotation */ |
avltree_nodes[6].key = 20; |
avltree_nodes[7].key = 20; |
avltree_nodes[8].key = 25; |
avltree_nodes[9].key = 25; |
/* LL rotation in lower floor */ |
avltree_nodes[10].key = 35; |
/* RR rotation */ |
avltree_nodes[11].key = 70; |
avltree_nodes[12].key = 80; |
/* RL rotation */ |
avltree_nodes[13].key = 90; |
avltree_nodes[14].key = 85; |
/* Insert 0 key */ |
avltree_nodes[15].key = 0; |
avltree_nodes[16].key = 0; |
/* Insert reverse */ |
avltree_nodes[17].key = 600; |
avltree_nodes[18].key = 500; |
avltree_nodes[19].key = 400; |
avltree_nodes[20].key = 300; |
for (i = 21; i < NODE_COUNT; i++) |
avltree_nodes[i].key = i * 3; |
179,40 → 187,35 |
static avltree_node_t *alloc_avltree_node(void) |
{ |
avltree_node_t *node; |
node = first_free_node; |
first_free_node = first_free_node->par; |
return node; |
} |
static void test_tree_insert(avltree_t *tree, count_t node_count, bool quiet) |
static void test_tree_insert(avltree_t *tree, count_t node_count) |
{ |
unsigned int i; |
avltree_node_t *newnode; |
avltree_create(tree); |
if (!quiet) |
printf("Inserting %" PRIc " nodes...", node_count); |
TPRINTF("Inserting %" PRIc " nodes...", node_count); |
for (i = 0; i < node_count; i++) { |
newnode = alloc_avltree_node(); |
avltree_insert(tree, newnode); |
if (!quiet) { |
test_tree_parents(tree->root); |
test_tree_balance(tree->root); |
} |
test_tree_parents(tree->root); |
test_tree_balance(tree->root); |
} |
if (!quiet) |
printf("done.\n"); |
TPRINTF("done.\n"); |
} |
static void test_tree_delete(avltree_t *tree, count_t node_count, |
int node_position, bool quiet) |
int node_position) |
{ |
avltree_node_t *delnode; |
unsigned int i; |
219,71 → 222,61 |
switch (node_position) { |
case 0: |
if (!quiet) |
printf("Deleting root nodes..."); |
TPRINTF("Deleting root nodes..."); |
while (tree->root != NULL) { |
delnode = tree->root; |
avltree_delete(tree, delnode); |
if (!quiet) { |
test_tree_parents(tree->root); |
test_tree_balance(tree->root); |
} |
} |
test_tree_parents(tree->root); |
test_tree_balance(tree->root); |
} |
break; |
case 1: |
if (!quiet) |
printf("Deleting nodes according to creation time..."); |
TPRINTF("Deleting nodes according to creation time..."); |
for (i = 0; i < node_count; i++) { |
avltree_delete(tree, &avltree_nodes[i]); |
if (!quiet) { |
test_tree_parents(tree->root); |
test_tree_balance(tree->root); |
} |
test_tree_parents(tree->root); |
test_tree_balance(tree->root); |
} |
break; |
break; |
} |
if (!quiet) |
printf("done.\n"); |
TPRINTF("done.\n"); |
} |
static void test_tree_delmin(avltree_t *tree, count_t node_count, bool quiet) |
static void test_tree_delmin(avltree_t *tree, count_t node_count) |
{ |
unsigned int i = 0; |
if (!quiet) |
printf("Deleting minimum nodes..."); |
TPRINTF("Deleting minimum nodes..."); |
while (tree->root != NULL) { |
i++; |
avltree_delete_min(tree); |
if (!quiet) { |
test_tree_parents(tree->root); |
test_tree_balance(tree->root); |
} |
test_tree_parents(tree->root); |
test_tree_balance(tree->root); |
} |
if (!quiet && (i != node_count)) |
printf("Bad node count. Some nodes have been lost!\n"); |
if (!quiet) |
printf("done.\n"); |
if (i != node_count) |
TPRINTF("Bad node count. Some nodes have been lost!\n"); |
TPRINTF("done.\n"); |
} |
char *test_avltree1(bool quiet) |
char *test_avltree1(void) |
{ |
alloc_avltree_node_prepare(); |
test_tree_insert(&avltree, NODE_COUNT, quiet); |
test_tree_delete(&avltree, NODE_COUNT, 0, quiet); |
test_tree_insert(&avltree, NODE_COUNT); |
test_tree_delete(&avltree, NODE_COUNT, 0); |
alloc_avltree_node_prepare(); |
test_tree_insert(&avltree, NODE_COUNT, quiet); |
test_tree_delete(&avltree, NODE_COUNT, 1, quiet); |
test_tree_insert(&avltree, NODE_COUNT); |
test_tree_delete(&avltree, NODE_COUNT, 1); |
alloc_avltree_node_prepare(); |
test_tree_insert(&avltree, NODE_COUNT, quiet); |
test_tree_delmin(&avltree, NODE_COUNT, quiet); |
test_tree_insert(&avltree, NODE_COUNT); |
test_tree_delmin(&avltree, NODE_COUNT); |
return NULL; |
} |
/branches/dynload/kernel/test/synch/rwlock1.c |
---|
35,39 → 35,39 |
#include <synch/waitq.h> |
#include <synch/rwlock.h> |
#define READERS 50 |
#define WRITERS 50 |
#define READERS 50 |
#define WRITERS 50 |
static rwlock_t rwlock; |
char * test_rwlock1(bool quiet) |
char *test_rwlock1(void) |
{ |
rwlock_initialize(&rwlock); |
rwlock_write_lock(&rwlock); |
rwlock_write_unlock(&rwlock); |
rwlock_write_unlock(&rwlock); |
rwlock_read_lock(&rwlock); |
rwlock_read_lock(&rwlock); |
rwlock_read_lock(&rwlock); |
rwlock_read_lock(&rwlock); |
rwlock_read_lock(&rwlock); |
rwlock_read_lock(&rwlock); |
rwlock_read_unlock(&rwlock); |
rwlock_read_unlock(&rwlock); |
rwlock_read_unlock(&rwlock); |
rwlock_read_unlock(&rwlock); |
rwlock_read_unlock(&rwlock); |
rwlock_read_unlock(&rwlock); |
rwlock_write_lock(&rwlock); |
rwlock_write_unlock(&rwlock); |
rwlock_write_unlock(&rwlock); |
rwlock_read_lock(&rwlock); |
rwlock_read_unlock(&rwlock); |
rwlock_write_lock(&rwlock); |
rwlock_write_unlock(&rwlock); |
rwlock_write_unlock(&rwlock); |
rwlock_read_lock(&rwlock); |
rwlock_read_unlock(&rwlock); |
/branches/dynload/kernel/test/synch/rwlock2.c |
---|
34,38 → 34,34 |
#include <synch/rwlock.h> |
#define READERS 50 |
#define WRITERS 50 |
#define READERS 50 |
#define WRITERS 50 |
static rwlock_t rwlock; |
static bool sh_quiet; |
static void writer(void *arg) |
{ |
if (!sh_quiet) |
printf("Trying to lock rwlock for writing....\n"); |
TPRINTF("Trying to lock rwlock for writing....\n"); |
rwlock_write_lock(&rwlock); |
rwlock_write_unlock(&rwlock); |
if (!sh_quiet) |
printf("Trying to lock rwlock for reading....\n"); |
TPRINTF("Trying to lock rwlock for reading....\n"); |
rwlock_read_lock(&rwlock); |
rwlock_read_unlock(&rwlock); |
rwlock_read_unlock(&rwlock); |
} |
char * test_rwlock2(bool quiet) |
char *test_rwlock2(void) |
{ |
thread_t *thrd; |
sh_quiet = quiet; |
rwlock_initialize(&rwlock); |
rwlock_read_lock(&rwlock); |
rwlock_read_lock(&rwlock); |
rwlock_read_lock(&rwlock); |
rwlock_read_lock(&rwlock); |
rwlock_read_lock(&rwlock); |
thrd = thread_create(writer, NULL, TASK, 0, "writer", false); |
if (thrd) |
72,7 → 68,7 |
thread_ready(thrd); |
else |
return "Could not create thread"; |
thread_sleep(1); |
rwlock_read_unlock(&rwlock); |
/branches/dynload/kernel/test/synch/rwlock3.c |
---|
34,41 → 34,35 |
#include <synch/rwlock.h> |
#define THREADS 4 |
#define THREADS 4 |
static atomic_t thread_count; |
static rwlock_t rwlock; |
static bool sh_quiet; |
static void reader(void *arg) |
{ |
thread_detach(THREAD); |
if (!sh_quiet) |
printf("cpu%u, tid %" PRIu64 ": trying to lock rwlock for reading....\n", CPU->id, THREAD->tid); |
TPRINTF("cpu%u, tid %" PRIu64 ": trying to lock rwlock for reading....\n", CPU->id, THREAD->tid); |
rwlock_read_lock(&rwlock); |
rwlock_read_unlock(&rwlock); |
if (!sh_quiet) { |
printf("cpu%u, tid %" PRIu64 ": success\n", CPU->id, THREAD->tid); |
printf("cpu%u, tid %" PRIu64 ": trying to lock rwlock for writing....\n", CPU->id, THREAD->tid); |
} |
TPRINTF("cpu%u, tid %" PRIu64 ": success\n", CPU->id, THREAD->tid); |
TPRINTF("cpu%u, tid %" PRIu64 ": trying to lock rwlock for writing....\n", CPU->id, THREAD->tid); |
rwlock_write_lock(&rwlock); |
rwlock_write_unlock(&rwlock); |
if (!sh_quiet) |
printf("cpu%u, tid %" PRIu64 ": success\n", CPU->id, THREAD->tid); |
TPRINTF("cpu%u, tid %" PRIu64 ": success\n", CPU->id, THREAD->tid); |
atomic_dec(&thread_count); |
} |
char * test_rwlock3(bool quiet) |
char *test_rwlock3(void) |
{ |
int i; |
thread_t *thrd; |
sh_quiet = quiet; |
atomic_set(&thread_count, THREADS); |
79,16 → 73,15 |
thrd = thread_create(reader, NULL, TASK, 0, "reader", false); |
if (thrd) |
thread_ready(thrd); |
else if (!quiet) |
printf("Could not create reader %d\n", i); |
else |
TPRINTF("Could not create reader %d\n", i); |
} |
thread_sleep(1); |
rwlock_write_unlock(&rwlock); |
while (atomic_get(&thread_count) > 0) { |
if (!quiet) |
printf("Threads left: %ld\n", atomic_get(&thread_count)); |
TPRINTF("Threads left: %ld\n", atomic_get(&thread_count)); |
thread_sleep(1); |
} |
/branches/dynload/kernel/test/synch/semaphore1.c |
---|
35,9 → 35,9 |
#include <synch/waitq.h> |
#include <synch/semaphore.h> |
#define AT_ONCE 3 |
#define PRODUCERS 50 |
#define CONSUMERS 50 |
#define AT_ONCE 3 |
#define PRODUCERS 50 |
#define CONSUMERS 50 |
static semaphore_t sem; |
47,10 → 47,10 |
static void producer(void *arg) |
{ |
thread_detach(THREAD); |
thread_detach(THREAD); |
waitq_sleep(&can_start); |
semaphore_down(&sem); |
atomic_inc(&items_produced); |
thread_usleep(250); |
59,7 → 59,7 |
static void consumer(void *arg) |
{ |
thread_detach(THREAD); |
thread_detach(THREAD); |
waitq_sleep(&can_start); |
69,7 → 69,7 |
semaphore_up(&sem); |
} |
char * test_semaphore1(bool quiet) |
char *test_semaphore1(void) |
{ |
int i, j, k; |
int consumers, producers; |
76,10 → 76,10 |
waitq_initialize(&can_start); |
semaphore_initialize(&sem, AT_ONCE); |
for (i = 1; i <= 3; i++) { |
thread_t *thrd; |
atomic_set(&items_produced, 0); |
atomic_set(&items_consumed, 0); |
86,8 → 86,8 |
consumers = i * CONSUMERS; |
producers = (4 - i) * PRODUCERS; |
printf("Creating %d consumers and %d producers...", consumers, producers); |
TPRINTF("Creating %d consumers and %d producers...", consumers, producers); |
for (j = 0; j < (CONSUMERS + PRODUCERS) / 2; j++) { |
for (k = 0; k < i; k++) { |
thrd = thread_create(consumer, NULL, TASK, 0, "consumer", false); |
94,7 → 94,7 |
if (thrd) |
thread_ready(thrd); |
else |
printf("could not create consumer %d\n", i); |
TPRINTF("could not create consumer %d\n", i); |
} |
for (k = 0; k < (4 - i); k++) { |
thrd = thread_create(producer, NULL, TASK, 0, "producer", false); |
101,17 → 101,17 |
if (thrd) |
thread_ready(thrd); |
else |
printf("could not create producer %d\n", i); |
TPRINTF("could not create producer %d\n", i); |
} |
} |
printf("ok\n"); |
TPRINTF("ok\n"); |
thread_sleep(1); |
waitq_wakeup(&can_start, WAKEUP_ALL); |
while ((items_consumed.count != consumers) || (items_produced.count != producers)) { |
printf("%d consumers remaining, %d producers remaining\n", consumers - items_consumed.count, producers - items_produced.count); |
TPRINTF("%d consumers remaining, %d producers remaining\n", consumers - items_consumed.count, producers - items_produced.count); |
thread_sleep(1); |
} |
} |
/branches/dynload/kernel/test/synch/rwlock4.c |
---|
40,13 → 40,12 |
#include <synch/synch.h> |
#include <synch/spinlock.h> |
#define READERS 50 |
#define WRITERS 50 |
#define READERS 50 |
#define WRITERS 50 |
static atomic_t thread_count; |
static rwlock_t rwlock; |
static atomic_t threads_fault; |
static bool sh_quiet; |
SPINLOCK_INITIALIZE(rw_lock); |
57,8 → 56,8 |
static uint32_t random(uint32_t max) |
{ |
uint32_t rc; |
spinlock_lock(&rw_lock); |
spinlock_lock(&rw_lock); |
rc = seed % max; |
seed = (((seed << 2) ^ (seed >> 2)) * 487) + rc; |
spinlock_unlock(&rw_lock); |
70,43 → 69,39 |
int rc, to; |
thread_detach(THREAD); |
waitq_sleep(&can_start); |
to = random(40000); |
if (!sh_quiet) |
printf("cpu%u, tid %" PRIu64 " w+ (%d)\n", CPU->id, THREAD->tid, to); |
TPRINTF("cpu%u, tid %" PRIu64 " w+ (%d)\n", CPU->id, THREAD->tid, to); |
rc = rwlock_write_lock_timeout(&rwlock, to); |
if (SYNCH_FAILED(rc)) { |
if (!sh_quiet) |
printf("cpu%u, tid %" PRIu64 " w!\n", CPU->id, THREAD->tid); |
TPRINTF("cpu%u, tid %" PRIu64 " w!\n", CPU->id, THREAD->tid); |
atomic_dec(&thread_count); |
return; |
} |
if (!sh_quiet) |
printf("cpu%u, tid %" PRIu64 " w=\n", CPU->id, THREAD->tid); |
TPRINTF("cpu%u, tid %" PRIu64 " w=\n", CPU->id, THREAD->tid); |
if (rwlock.readers_in) { |
if (!sh_quiet) |
printf("Oops."); |
TPRINTF("Oops.\n"); |
atomic_inc(&threads_fault); |
atomic_dec(&thread_count); |
return; |
} |
thread_usleep(random(1000000)); |
if (rwlock.readers_in) { |
if (!sh_quiet) |
printf("Oops."); |
TPRINTF("Oops.\n"); |
atomic_inc(&threads_fault); |
atomic_dec(&thread_count); |
return; |
} |
rwlock_write_unlock(&rwlock); |
if (!sh_quiet) |
printf("cpu%u, tid %" PRIu64 " w-\n", CPU->id, THREAD->tid); |
TPRINTF("cpu%u, tid %" PRIu64 " w-\n", CPU->id, THREAD->tid); |
atomic_dec(&thread_count); |
} |
118,33 → 113,28 |
to = random(2000); |
if (!sh_quiet) |
printf("cpu%u, tid %" PRIu64 " r+ (%d)\n", CPU->id, THREAD->tid, to); |
TPRINTF("cpu%u, tid %" PRIu64 " r+ (%d)\n", CPU->id, THREAD->tid, to); |
rc = rwlock_read_lock_timeout(&rwlock, to); |
if (SYNCH_FAILED(rc)) { |
if (!sh_quiet) |
printf("cpu%u, tid %" PRIu64 " r!\n", CPU->id, THREAD->tid); |
TPRINTF("cpu%u, tid %" PRIu64 " r!\n", CPU->id, THREAD->tid); |
atomic_dec(&thread_count); |
return; |
} |
if (!sh_quiet) |
printf("cpu%u, tid %" PRIu64 " r=\n", CPU->id, THREAD->tid); |
TPRINTF("cpu%u, tid %" PRIu64 " r=\n", CPU->id, THREAD->tid); |
thread_usleep(30000); |
rwlock_read_unlock(&rwlock); |
if (!sh_quiet) |
printf("cpu%u, tid %" PRIu64 " r-\n", CPU->id, THREAD->tid); |
TPRINTF("cpu%u, tid %" PRIu64 " r-\n", CPU->id, THREAD->tid); |
atomic_dec(&thread_count); |
} |
char * test_rwlock4(bool quiet) |
char *test_rwlock4(void) |
{ |
context_t ctx; |
uint32_t i; |
sh_quiet = quiet; |
waitq_initialize(&can_start); |
rwlock_initialize(&rwlock); |
158,28 → 148,25 |
thread_t *thrd; |
context_save(&ctx); |
if (!quiet) { |
printf("sp=%#x, readers_in=%" PRIc "\n", ctx.sp, rwlock.readers_in); |
printf("Creating %" PRIu32 " readers\n", rd); |
} |
TPRINTF("sp=%#x, readers_in=%" PRIc "\n", ctx.sp, rwlock.readers_in); |
TPRINTF("Creating %" PRIu32 " readers\n", rd); |
for (i = 0; i < rd; i++) { |
thrd = thread_create(reader, NULL, TASK, 0, "reader", false); |
if (thrd) |
thread_ready(thrd); |
else if (!quiet) |
printf("Could not create reader %" PRIu32 "\n", i); |
else |
TPRINTF("Could not create reader %" PRIu32 "\n", i); |
} |
if (!quiet) |
printf("Creating %" PRIu32 " writers\n", wr); |
TPRINTF("Creating %" PRIu32 " writers\n", wr); |
for (i = 0; i < wr; i++) { |
thrd = thread_create(writer, NULL, TASK, 0, "writer", false); |
if (thrd) |
thread_ready(thrd); |
else if (!quiet) |
printf("Could not create writer %" PRIu32 "\n", i); |
else |
TPRINTF("Could not create writer %" PRIu32 "\n", i); |
} |
thread_usleep(20000); |
186,8 → 173,7 |
waitq_wakeup(&can_start, WAKEUP_ALL); |
while (atomic_get(&thread_count) > 0) { |
if (!quiet) |
printf("Threads left: %ld\n", atomic_get(&thread_count)); |
TPRINTF("Threads left: %ld\n", atomic_get(&thread_count)); |
thread_sleep(1); |
} |
/branches/dynload/kernel/test/synch/semaphore2.c |
---|
50,8 → 50,8 |
static uint32_t random(uint32_t max) |
{ |
uint32_t rc; |
spinlock_lock(&sem_lock); |
spinlock_lock(&sem_lock); |
rc = seed % max; |
seed = (((seed << 2) ^ (seed >> 2)) * 487) + rc; |
spinlock_unlock(&sem_lock); |
67,21 → 67,21 |
waitq_sleep(&can_start); |
to = random(20000); |
printf("cpu%u, tid %" PRIu64 " down+ (%d)\n", CPU->id, THREAD->tid, to); |
TPRINTF("cpu%u, tid %" PRIu64 " down+ (%d)\n", CPU->id, THREAD->tid, to); |
rc = semaphore_down_timeout(&sem, to); |
if (SYNCH_FAILED(rc)) { |
printf("cpu%u, tid %" PRIu64 " down!\n", CPU->id, THREAD->tid); |
TPRINTF("cpu%u, tid %" PRIu64 " down!\n", CPU->id, THREAD->tid); |
return; |
} |
printf("cpu%u, tid %" PRIu64 " down=\n", CPU->id, THREAD->tid); |
TPRINTF("cpu%u, tid %" PRIu64 " down=\n", CPU->id, THREAD->tid); |
thread_usleep(random(30000)); |
semaphore_up(&sem); |
printf("cpu%u, tid %" PRIu64 " up\n", CPU->id, THREAD->tid); |
TPRINTF("cpu%u, tid %" PRIu64 " up\n", CPU->id, THREAD->tid); |
} |
char * test_semaphore2(bool quiet) |
char *test_semaphore2(void) |
{ |
uint32_t i, k; |
91,13 → 91,13 |
thread_t *thrd; |
k = random(7) + 1; |
printf("Creating %" PRIu32 " consumers\n", k); |
TPRINTF("Creating %" PRIu32 " consumers\n", k); |
for (i = 0; i < k; i++) { |
thrd = thread_create(consumer, NULL, TASK, 0, "consumer", false); |
if (thrd) |
thread_ready(thrd); |
else |
printf("Error creating thread\n"); |
TPRINTF("Error creating thread\n"); |
} |
thread_usleep(20000); |
/branches/dynload/kernel/test/synch/rwlock5.c |
---|
35,8 → 35,8 |
#include <synch/waitq.h> |
#include <synch/rwlock.h> |
#define READERS 50 |
#define WRITERS 50 |
#define READERS 50 |
#define WRITERS 50 |
static rwlock_t rwlock; |
47,9 → 47,9 |
static void writer(void *arg) |
{ |
thread_detach(THREAD); |
waitq_sleep(&can_start); |
rwlock_write_lock(&rwlock); |
atomic_inc(&items_written); |
rwlock_write_unlock(&rwlock); |
58,7 → 58,7 |
static void reader(void *arg) |
{ |
thread_detach(THREAD); |
waitq_sleep(&can_start); |
rwlock_read_lock(&rwlock); |
66,7 → 66,7 |
rwlock_read_unlock(&rwlock); |
} |
char * test_rwlock5(bool quiet) |
char *test_rwlock5(void) |
{ |
int i, j, k; |
long readers, writers; |
76,15 → 76,15 |
for (i = 1; i <= 3; i++) { |
thread_t *thrd; |
atomic_set(&items_read, 0); |
atomic_set(&items_written, 0); |
readers = i * READERS; |
writers = (4 - i) * WRITERS; |
printf("Creating %ld readers and %ld writers...", readers, writers); |
TPRINTF("Creating %ld readers and %ld writers...", readers, writers); |
for (j = 0; j < (READERS + WRITERS) / 2; j++) { |
for (k = 0; k < i; k++) { |
thrd = thread_create(reader, NULL, TASK, 0, "reader", false); |
91,7 → 91,7 |
if (thrd) |
thread_ready(thrd); |
else |
printf("Could not create reader %d\n", k); |
TPRINTF("Could not create reader %d\n", k); |
} |
for (k = 0; k < (4 - i); k++) { |
thrd = thread_create(writer, NULL, TASK, 0, "writer", false); |
98,17 → 98,17 |
if (thrd) |
thread_ready(thrd); |
else |
printf("Could not create writer %d\n", k); |
TPRINTF("Could not create writer %d\n", k); |
} |
} |
printf("ok\n"); |
TPRINTF("ok\n"); |
thread_sleep(1); |
waitq_wakeup(&can_start, WAKEUP_ALL); |
while ((items_read.count != readers) || (items_written.count != writers)) { |
printf("%d readers remaining, %d writers remaining, readers_in=%d\n", readers - items_read.count, writers - items_written.count, rwlock.readers_in); |
TPRINTF("%d readers remaining, %d writers remaining, readers_in=%d\n", readers - items_read.count, writers - items_written.count, rwlock.readers_in); |
thread_usleep(100000); |
} |
} |
/branches/dynload/kernel/test/test.h |
---|
38,8 → 38,17 |
#include <arch/types.h> |
#include <typedefs.h> |
typedef char *(*test_entry_t)(bool); |
extern bool test_quiet; |
#define TPRINTF(format, ...) \ |
{ \ |
if (!test_quiet) { \ |
printf(format, ##__VA_ARGS__); \ |
} \ |
} |
typedef char *(*test_entry_t)(void); |
typedef struct { |
char *name; |
char *desc; |
47,33 → 56,33 |
bool safe; |
} test_t; |
extern char *test_atomic1(bool quiet); |
extern char *test_avltree1(bool quiet); |
extern char *test_btree1(bool quiet); |
extern char *test_mips1(bool quiet); |
extern char *test_fault1(bool quiet); |
extern char *test_fpu1(bool quiet); |
extern char *test_sse1(bool quiet); |
extern char *test_mips2(bool quiet); |
extern char *test_falloc1(bool quiet); |
extern char *test_falloc2(bool quiet); |
extern char *test_mapping1(bool quiet); |
extern char *test_purge1(bool quiet); |
extern char *test_slab1(bool quiet); |
extern char *test_slab2(bool quiet); |
extern char *test_rwlock1(bool quiet); |
extern char *test_rwlock2(bool quiet); |
extern char *test_rwlock3(bool quiet); |
extern char *test_rwlock4(bool quiet); |
extern char *test_rwlock5(bool quiet); |
extern char *test_semaphore1(bool quiet); |
extern char *test_semaphore2(bool quiet); |
extern char *test_print1(bool quiet); |
extern char *test_print2(bool quiet); |
extern char *test_print3(bool quiet); |
extern char *test_print4(bool quiet); |
extern char *test_thread1(bool quiet); |
extern char *test_sysinfo1(bool quiet); |
extern char *test_atomic1(void); |
extern char *test_avltree1(void); |
extern char *test_btree1(void); |
extern char *test_mips1(void); |
extern char *test_fault1(void); |
extern char *test_fpu1(void); |
extern char *test_sse1(void); |
extern char *test_mips2(void); |
extern char *test_falloc1(void); |
extern char *test_falloc2(void); |
extern char *test_mapping1(void); |
extern char *test_purge1(void); |
extern char *test_slab1(void); |
extern char *test_slab2(void); |
extern char *test_rwlock1(void); |
extern char *test_rwlock2(void); |
extern char *test_rwlock3(void); |
extern char *test_rwlock4(void); |
extern char *test_rwlock5(void); |
extern char *test_semaphore1(void); |
extern char *test_semaphore2(void); |
extern char *test_print1(void); |
extern char *test_print2(void); |
extern char *test_print3(void); |
extern char *test_print4(void); |
extern char *test_thread1(void); |
extern char *test_sysinfo1(void); |
extern test_t tests[]; |
/branches/dynload/kernel/test/debug/mips1_skip.c |
---|
28,7 → 28,7 |
#include <test.h> |
char *test_mips1(bool quiet) |
char *test_mips1(void) |
{ |
return NULL; |
} |
/branches/dynload/kernel/test/debug/mips1.c |
---|
36,10 → 36,9 |
#include <arch.h> |
char *test_mips1(bool quiet) |
char *test_mips1(void) |
{ |
if (!quiet) |
printf("If kconsole is compiled in, you should enter debug mode now.\n"); |
TPRINTF("If kconsole is compiled in, you should enter debug mode now.\n"); |
asm volatile ( |
"break\n" |
/branches/dynload/kernel/test/thread/thread1.c |
---|
36,37 → 36,33 |
#include <arch.h> |
#define THREADS 5 |
#define THREADS 5 |
static atomic_t finish; |
static atomic_t threads_finished; |
static bool sh_quiet; |
static void threadtest(void *data) |
{ |
thread_detach(THREAD); |
thread_detach(THREAD); |
while (atomic_get(&finish)) { |
if (!sh_quiet) |
printf("%" PRIu64 " ", THREAD->tid); |
TPRINTF("%" PRIu64 " ", THREAD->tid); |
thread_usleep(100000); |
} |
atomic_inc(&threads_finished); |
} |
char * test_thread1(bool quiet) |
char *test_thread1(void) |
{ |
unsigned int i, total = 0; |
sh_quiet = quiet; |
atomic_set(&finish, 1); |
atomic_set(&threads_finished, 0); |
for (i = 0; i < THREADS; i++) { |
thread_t *t; |
if (!(t = thread_create(threadtest, NULL, TASK, 0, "threadtest", false))) { |
if (!quiet) |
printf("Could not create thread %d\n", i); |
TPRINTF("Could not create thread %d\n", i); |
break; |
} |
thread_ready(t); |
73,14 → 69,12 |
total++; |
} |
if (!quiet) |
printf("Running threads for 10 seconds...\n"); |
TPRINTF("Running threads for 10 seconds...\n"); |
thread_sleep(10); |
atomic_set(&finish, 0); |
while (atomic_get(&threads_finished) < ((long) total)) { |
if (!quiet) |
printf("Threads left: %d\n", total - atomic_get(&threads_finished)); |
TPRINTF("Threads left: %d\n", total - atomic_get(&threads_finished)); |
thread_sleep(1); |
} |
/branches/dynload/kernel/test/mm/falloc1.c |
---|
36,12 → 36,13 |
#include <debug.h> |
#include <align.h> |
#define MAX_FRAMES 1024 |
#define MAX_ORDER 8 |
#define TEST_RUNS 2 |
#define MAX_FRAMES 1024 |
#define MAX_ORDER 8 |
#define TEST_RUNS 2 |
char * test_falloc1(bool quiet) { |
uintptr_t * frames = (uintptr_t *) malloc(MAX_FRAMES * sizeof(uintptr_t), 0); |
char *test_falloc1(void) { |
uintptr_t *frames |
= (uintptr_t *) malloc(MAX_FRAMES * sizeof(uintptr_t), 0); |
int results[MAX_ORDER + 1]; |
int i, order, run; |
52,11 → 53,10 |
if (frames == NULL) |
return "Unable to allocate frames"; |
for (run = 0; run < TEST_RUNS; run++) { |
for (order = 0; order <= MAX_ORDER; order++) { |
if (!quiet) |
printf("Allocating %d frames blocks ... ", 1 << order); |
TPRINTF("Allocating %d frames blocks ... ", 1 << order); |
allocated = 0; |
for (i = 0; i < MAX_FRAMES >> order; i++) { |
63,8 → 63,7 |
frames[allocated] = (uintptr_t) frame_alloc(order, FRAME_ATOMIC | FRAME_KA); |
if (ALIGN_UP(frames[allocated], FRAME_SIZE << order) != frames[allocated]) { |
if (!quiet) |
printf("Block at address %p (size %dK) is not aligned\n", frames[allocated], (FRAME_SIZE << order) >> 10); |
TPRINTF("Block at address %p (size %dK) is not aligned\n", frames[allocated], (FRAME_SIZE << order) >> 10); |
return "Test failed"; |
} |
71,15 → 70,13 |
if (frames[allocated]) |
allocated++; |
else { |
if (!quiet) |
printf("done. "); |
TPRINTF("done. "); |
break; |
} |
} |
if (!quiet) |
printf("%d blocks allocated.\n", allocated); |
TPRINTF("%d blocks allocated.\n", allocated); |
if (run) { |
if (results[order] != allocated) |
return "Possible frame leak"; |
86,17 → 83,15 |
} else |
results[order] = allocated; |
if (!quiet) |
printf("Deallocating ... "); |
TPRINTF("Deallocating ... "); |
for (i = 0; i < allocated; i++) |
frame_free(KA2PA(frames[i])); |
if (!quiet) |
printf("done.\n"); |
TPRINTF("done.\n"); |
} |
} |
free(frames); |
return NULL; |
/branches/dynload/kernel/test/mm/falloc2.c |
---|
39,17 → 39,16 |
#include <memstr.h> |
#include <arch.h> |
#define MAX_FRAMES 256 |
#define MAX_ORDER 8 |
#define MAX_FRAMES 256 |
#define MAX_ORDER 8 |
#define THREAD_RUNS 1 |
#define THREADS 8 |
#define THREAD_RUNS 1 |
#define THREADS 8 |
static atomic_t thread_count; |
static atomic_t thread_fail; |
static bool sh_quiet; |
static void falloc(void * arg) |
static void falloc(void *arg) |
{ |
int order, run, allocated, i; |
uint8_t val = THREAD->tid % THREADS; |
57,8 → 56,7 |
void **frames = (void **) malloc(MAX_FRAMES * sizeof(void *), FRAME_ATOMIC); |
if (frames == NULL) { |
if (!sh_quiet) |
printf("Thread #%" PRIu64 " (cpu%u): Unable to allocate frames\n", THREAD->tid, CPU->id); |
TPRINTF("Thread #%" PRIu64 " (cpu%u): Unable to allocate frames\n", THREAD->tid, CPU->id); |
atomic_inc(&thread_fail); |
atomic_dec(&thread_count); |
return; |
65,11 → 63,10 |
} |
thread_detach(THREAD); |
for (run = 0; run < THREAD_RUNS; run++) { |
for (order = 0; order <= MAX_ORDER; order++) { |
if (!sh_quiet) |
printf("Thread #%" PRIu64 " (cpu%u): Allocating %d frames blocks ... \n", THREAD->tid, CPU->id, 1 << order); |
TPRINTF("Thread #%" PRIu64 " (cpu%u): Allocating %d frames blocks ... \n", THREAD->tid, CPU->id, 1 << order); |
allocated = 0; |
for (i = 0; i < (MAX_FRAMES >> order); i++) { |
81,17 → 78,13 |
break; |
} |
if (!sh_quiet) |
printf("Thread #%" PRIu64 " (cpu%u): %d blocks allocated.\n", THREAD->tid, CPU->id, allocated); |
TPRINTF("Thread #%" PRIu64 " (cpu%u): %d blocks allocated.\n", THREAD->tid, CPU->id, allocated); |
TPRINTF("Thread #%" PRIu64 " (cpu%u): Deallocating ... \n", THREAD->tid, CPU->id); |
if (!sh_quiet) |
printf("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++) { |
if (((uint8_t *) frames[i])[k] != val) { |
if (!sh_quiet) |
printf("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 %#" PRIi "\n", THREAD->tid, CPU->id, ((char *) frames[i])[k], frames[i], k); |
atomic_inc(&thread_fail); |
goto cleanup; |
} |
99,32 → 92,28 |
frame_free(KA2PA(frames[i])); |
} |
if (!sh_quiet) |
printf("Thread #%" PRIu64 " (cpu%u): Finished run.\n", THREAD->tid, CPU->id); |
TPRINTF("Thread #%" PRIu64 " (cpu%u): Finished run.\n", THREAD->tid, CPU->id); |
} |
} |
cleanup: |
cleanup: |
free(frames); |
if (!sh_quiet) |
printf("Thread #%" PRIu64 " (cpu%u): Exiting\n", THREAD->tid, CPU->id); |
TPRINTF("Thread #%" PRIu64 " (cpu%u): Exiting\n", THREAD->tid, CPU->id); |
atomic_dec(&thread_count); |
} |
char * test_falloc2(bool quiet) |
char *test_falloc2(void) |
{ |
unsigned int i; |
sh_quiet = quiet; |
atomic_set(&thread_count, THREADS); |
atomic_set(&thread_fail, 0); |
for (i = 0; i < THREADS; i++) { |
thread_t * thrd = thread_create(falloc, NULL, TASK, 0, "falloc", false); |
if (!thrd) { |
if (!quiet) |
printf("Could not create thread %u\n", i); |
TPRINTF("Could not create thread %u\n", i); |
break; |
} |
thread_ready(thrd); |
131,8 → 120,7 |
} |
while (atomic_get(&thread_count) > 0) { |
if (!quiet) |
printf("Threads left: %ld\n", atomic_get(&thread_count)); |
TPRINTF("Threads left: %ld\n", atomic_get(&thread_count)); |
thread_sleep(1); |
} |
/branches/dynload/kernel/test/mm/slab1.c |
---|
33,23 → 33,21 |
#include <arch.h> |
#include <memstr.h> |
#define VAL_COUNT 1024 |
#define VAL_COUNT 1024 |
static void * data[VAL_COUNT]; |
static void *data[VAL_COUNT]; |
static void testit(int size, int count, bool quiet) |
static void testit(int size, int count) |
{ |
slab_cache_t *cache; |
int i; |
if (!quiet) |
printf("Creating cache, object size: %d.\n", size); |
TPRINTF("Creating cache, object size: %d.\n", size); |
cache = slab_cache_create("test_cache", size, 0, NULL, NULL, |
SLAB_CACHE_NOMAGAZINE); |
SLAB_CACHE_NOMAGAZINE); |
if (!quiet) |
printf("Allocating %d items...", count); |
TPRINTF("Allocating %d items...", count); |
for (i = 0; i < count; i++) { |
data[i] = slab_alloc(cache, 0); |
56,78 → 54,71 |
memsetb(data[i], size, 0); |
} |
if (!quiet) { |
printf("done.\n"); |
printf("Freeing %d items...", count); |
} |
TPRINTF("done.\n"); |
TPRINTF("Freeing %d items...", count); |
for (i = 0; i < count; i++) |
slab_free(cache, data[i]); |
if (!quiet) { |
printf("done.\n"); |
printf("Allocating %d items...", count); |
} |
TPRINTF("done.\n"); |
TPRINTF("Allocating %d items...", count); |
for (i = 0; i < count; i++) { |
data[i] = slab_alloc(cache, 0); |
memsetb(data[i], size, 0); |
} |
if (!quiet) { |
printf("done.\n"); |
printf("Freeing %d items...", count / 2); |
} |
TPRINTF("done.\n"); |
TPRINTF("Freeing %d items...", count / 2); |
for (i = count - 1; i >= count / 2; i--) |
slab_free(cache, data[i]); |
if (!quiet) { |
printf("done.\n"); |
printf("Allocating %d items...", count / 2); |
} |
TPRINTF("done.\n"); |
TPRINTF("Allocating %d items...", count / 2); |
for (i = count / 2; i < count; i++) { |
data[i] = slab_alloc(cache, 0); |
memsetb(data[i], size, 0); |
} |
if (!quiet) { |
printf("done.\n"); |
printf("Freeing %d items...", count); |
} |
TPRINTF("done.\n"); |
TPRINTF("Freeing %d items...", count); |
for (i = 0; i < count; i++) |
slab_free(cache, data[i]); |
if (!quiet) |
printf("done.\n"); |
TPRINTF("done.\n"); |
slab_cache_destroy(cache); |
if (!quiet) |
printf("Test complete.\n"); |
TPRINTF("Test complete.\n"); |
} |
static void testsimple(bool quiet) |
static void testsimple(void) |
{ |
testit(100, VAL_COUNT, quiet); |
testit(200, VAL_COUNT, quiet); |
testit(1024, VAL_COUNT, quiet); |
testit(2048, 512, quiet); |
testit(4000, 128, quiet); |
testit(8192, 128, quiet); |
testit(16384, 128, quiet); |
testit(16385, 128, quiet); |
testit(100, VAL_COUNT); |
testit(200, VAL_COUNT); |
testit(1024, VAL_COUNT); |
testit(2048, 512); |
testit(4000, 128); |
testit(8192, 128); |
testit(16384, 128); |
testit(16385, 128); |
} |
#define THREADS 6 |
#define THR_MEM_COUNT 1024 |
#define THR_MEM_SIZE 128 |
#define THREADS 6 |
#define THR_MEM_COUNT 1024 |
#define THR_MEM_SIZE 128 |
static void * thr_data[THREADS][THR_MEM_COUNT]; |
static void *thr_data[THREADS][THR_MEM_COUNT]; |
static slab_cache_t *thr_cache; |
static semaphore_t thr_sem; |
static bool sh_quiet; |
static void slabtest(void *data) |
{ |
136,8 → 127,7 |
thread_detach(THREAD); |
if (!sh_quiet) |
printf("Starting thread #%" PRIu64 "...\n", THREAD->tid); |
TPRINTF("Starting thread #%" PRIu64 "...\n", THREAD->tid); |
for (j = 0; j < 10; j++) { |
for (i = 0; i < THR_MEM_COUNT; i++) |
150,24 → 140,23 |
slab_free(thr_cache, thr_data[offs][i]); |
} |
if (!sh_quiet) |
printf("Thread #%" PRIu64 " finished\n", THREAD->tid); |
TPRINTF("Thread #%" PRIu64 " finished\n", THREAD->tid); |
semaphore_up(&thr_sem); |
} |
static void testthreads(bool quiet) |
static void testthreads(void) |
{ |
thread_t *t; |
int i; |
thr_cache = slab_cache_create("thread_cache", THR_MEM_SIZE, 0, NULL, NULL, |
SLAB_CACHE_NOMAGAZINE); |
SLAB_CACHE_NOMAGAZINE); |
semaphore_initialize(&thr_sem, 0); |
for (i = 0; i < THREADS; i++) { |
if (!(t = thread_create(slabtest, (void *) (unative_t) i, TASK, 0, "slabtest", false))) { |
if (!quiet) |
printf("Could not create thread %d\n", i); |
TPRINTF("Could not create thread %d\n", i); |
} else |
thread_ready(t); |
} |
177,16 → 166,13 |
slab_cache_destroy(thr_cache); |
if (!quiet) |
printf("Test complete.\n"); |
TPRINTF("Test complete.\n"); |
} |
char * test_slab1(bool quiet) |
char *test_slab1(void) |
{ |
sh_quiet = quiet; |
testsimple(); |
testthreads(); |
testsimple(quiet); |
testthreads(quiet); |
return NULL; |
} |
/branches/dynload/kernel/test/mm/purge1.c |
---|
39,7 → 39,7 |
extern void tlb_invalidate_all(void); |
extern void tlb_invalidate_pages(asid_t asid, uintptr_t va, count_t cnt); |
char * test_purge1(bool quiet) |
char *test_purge1(void) |
{ |
tlb_entry_t entryi; |
tlb_entry_t entryd; |
/branches/dynload/kernel/test/mm/slab2.c |
---|
36,18 → 36,18 |
#include <synch/condvar.h> |
#include <synch/mutex.h> |
#define ITEM_SIZE 256 |
#define ITEM_SIZE 256 |
/** Fill memory with 2 caches, when allocation fails, |
* free one of the caches. We should have everything in magazines, |
* now allocation should clean magazines and allow for full allocation. |
*/ |
static void totalmemtest(bool quiet) |
static void totalmemtest(void) |
{ |
slab_cache_t *cache1; |
slab_cache_t *cache2; |
int i; |
void *data1, *data2; |
void *olddata1 = NULL, *olddata2 = NULL; |
54,8 → 54,7 |
cache1 = slab_cache_create("cache1_tst", ITEM_SIZE, 0, NULL, NULL, 0); |
cache2 = slab_cache_create("cache2_tst", ITEM_SIZE, 0, NULL, NULL, 0); |
if (!quiet) |
printf("Allocating..."); |
TPRINTF("Allocating..."); |
/* Use atomic alloc, so that we find end of memory */ |
do { |
74,13 → 73,12 |
*((void **) data2) = olddata2; |
olddata1 = data1; |
olddata2 = data2; |
} while (1); |
} while (true); |
if (!quiet) { |
printf("done.\n"); |
printf("Deallocating cache2..."); |
} |
TPRINTF("done.\n"); |
TPRINTF("Deallocating cache2..."); |
/* We do not have memory - now deallocate cache2 */ |
while (olddata2) { |
data2 = *((void **) olddata2); |
88,16 → 86,14 |
olddata2 = data2; |
} |
if (!quiet) { |
printf("done.\n"); |
printf("Allocating to cache1...\n"); |
} |
TPRINTF("done.\n"); |
TPRINTF("Allocating to cache1...\n"); |
for (i = 0; i < 30; i++) { |
data1 = slab_alloc(cache1, FRAME_ATOMIC); |
if (!data1) { |
if (!quiet) |
printf("Incorrect memory size - use another test."); |
TPRINTF("Incorrect memory size - use another test."); |
return; |
} |
memsetb(data1, ITEM_SIZE, 0); |
104,7 → 100,7 |
*((void **) data1) = olddata1; |
olddata1 = data1; |
} |
while (1) { |
while (true) { |
data1 = slab_alloc(cache1, FRAME_ATOMIC); |
if (!data1) |
break; |
113,8 → 109,7 |
olddata1 = data1; |
} |
if (!quiet) |
printf("Deallocating cache1..."); |
TPRINTF("Deallocating cache1..."); |
while (olddata1) { |
data1 = *((void **) olddata1); |
122,10 → 117,10 |
olddata1 = data1; |
} |
if (!quiet) { |
printf("done.\n"); |
TPRINTF("done.\n"); |
if (!test_quiet) |
slab_print_list(); |
} |
slab_cache_destroy(cache1); |
slab_cache_destroy(cache2); |
135,9 → 130,8 |
static semaphore_t thr_sem; |
static condvar_t thread_starter; |
static mutex_t starter_mutex; |
static bool sh_quiet; |
#define THREADS 8 |
#define THREADS 8 |
static void slabtest(void *priv) |
{ |
149,14 → 143,12 |
condvar_wait(&thread_starter,&starter_mutex); |
mutex_unlock(&starter_mutex); |
if (!sh_quiet) |
printf("Starting thread #%" PRIu64 "...\n", THREAD->tid); |
TPRINTF("Starting thread #%" PRIu64 "...\n", THREAD->tid); |
/* Alloc all */ |
if (!sh_quiet) |
printf("Thread #%" PRIu64 " allocating...\n", THREAD->tid); |
TPRINTF("Thread #%" PRIu64 " allocating...\n", THREAD->tid); |
while (1) { |
while (true) { |
/* Call with atomic to detect end of memory */ |
new = slab_alloc(thr_cache, FRAME_ATOMIC); |
if (!new) |
165,8 → 157,7 |
data = new; |
} |
if (!sh_quiet) |
printf("Thread #%" PRIu64 " releasing...\n", THREAD->tid); |
TPRINTF("Thread #%" PRIu64 " releasing...\n", THREAD->tid); |
while (data) { |
new = *((void **)data); |
175,10 → 166,9 |
data = new; |
} |
if (!sh_quiet) |
printf("Thread #%" PRIu64 " allocating...\n", THREAD->tid); |
TPRINTF("Thread #%" PRIu64 " allocating...\n", THREAD->tid); |
while (1) { |
while (true) { |
/* Call with atomic to detect end of memory */ |
new = slab_alloc(thr_cache, FRAME_ATOMIC); |
if (!new) |
187,8 → 177,7 |
data = new; |
} |
if (!sh_quiet) |
printf("Thread #%" PRIu64 " releasing...\n", THREAD->tid); |
TPRINTF("Thread #%" PRIu64 " releasing...\n", THREAD->tid); |
while (data) { |
new = *((void **)data); |
197,14 → 186,15 |
data = new; |
} |
if (!sh_quiet) |
printf("Thread #%" PRIu64 " finished\n", THREAD->tid); |
TPRINTF("Thread #%" PRIu64 " finished\n", THREAD->tid); |
slab_print_list(); |
if (!test_quiet) |
slab_print_list(); |
semaphore_up(&thr_sem); |
} |
static void multitest(int size, bool quiet) |
static void multitest(int size) |
{ |
/* Start 8 threads that just allocate as much as possible, |
* then release everything, then again allocate, then release |
212,48 → 202,42 |
thread_t *t; |
int i; |
if (!quiet) |
printf("Running stress test with size %d\n", size); |
TPRINTF("Running stress test with size %d\n", size); |
condvar_initialize(&thread_starter); |
mutex_initialize(&starter_mutex, MUTEX_PASSIVE); |
thr_cache = slab_cache_create("thread_cache", size, 0, NULL, NULL, 0); |
semaphore_initialize(&thr_sem,0); |
for (i = 0; i < THREADS; i++) { |
if (!(t = thread_create(slabtest, NULL, TASK, 0, "slabtest", false))) { |
if (!quiet) |
printf("Could not create thread %d\n", i); |
TPRINTF("Could not create thread %d\n", i); |
} else |
thread_ready(t); |
} |
thread_sleep(1); |
condvar_broadcast(&thread_starter); |
for (i = 0; i < THREADS; i++) |
semaphore_down(&thr_sem); |
slab_cache_destroy(thr_cache); |
if (!quiet) |
printf("Stress test complete.\n"); |
TPRINTF("Stress test complete.\n"); |
} |
char * test_slab2(bool quiet) |
char *test_slab2(void) |
{ |
sh_quiet = quiet; |
TPRINTF("Running reclaim single-thread test .. pass 1\n"); |
totalmemtest(); |
if (!quiet) |
printf("Running reclaim single-thread test .. pass 1\n"); |
totalmemtest(quiet); |
if (!quiet) |
printf("Running reclaim single-thread test .. pass 2\n"); |
totalmemtest(quiet); |
if (!quiet) |
printf("Reclaim test OK.\n"); |
TPRINTF("Running reclaim single-thread test .. pass 2\n"); |
totalmemtest(); |
multitest(128, quiet); |
multitest(2048, quiet); |
multitest(8192, quiet); |
TPRINTF("Reclaim test OK.\n"); |
multitest(128); |
multitest(2048); |
multitest(8192); |
return NULL; |
} |
/branches/dynload/kernel/test/mm/purge1_skip.c |
---|
28,7 → 28,7 |
#include <test.h> |
char *test_purge1(bool quiet) |
char *test_purge1(void) |
{ |
return NULL; |
} |
/branches/dynload/kernel/test/mm/mapping1.c |
---|
35,40 → 35,36 |
#include <arch/types.h> |
#include <debug.h> |
#define PAGE0 0x10000000 |
#define PAGE1 (PAGE0+PAGE_SIZE) |
#define PAGE0 0x10000000 |
#define PAGE1 (PAGE0 + PAGE_SIZE) |
#define VALUE0 0x01234567 |
#define VALUE1 0x89abcdef |
#define VALUE0 0x01234567 |
#define VALUE1 0x89abcdef |
char * test_mapping1(bool quiet) |
char *test_mapping1(void) |
{ |
uintptr_t frame0, frame1; |
uint32_t v0, v1; |
frame0 = (uintptr_t) frame_alloc(ONE_FRAME, FRAME_KA); |
frame1 = (uintptr_t) frame_alloc(ONE_FRAME, FRAME_KA); |
if (!quiet) |
printf("Writing %#x to physical address %p.\n", VALUE0, KA2PA(frame0)); |
TPRINTF("Writing %#x to physical address %p.\n", VALUE0, KA2PA(frame0)); |
*((uint32_t *) frame0) = VALUE0; |
if (!quiet) |
printf("Writing %#x to physical address %p.\n", VALUE1, KA2PA(frame1)); |
TPRINTF("Writing %#x to physical address %p.\n", VALUE1, KA2PA(frame1)); |
*((uint32_t *) frame1) = VALUE1; |
if (!quiet) |
printf("Mapping virtual address %p to physical address %p.\n", PAGE0, KA2PA(frame0)); |
TPRINTF("Mapping virtual address %p to physical address %p.\n", PAGE0, KA2PA(frame0)); |
page_mapping_insert(AS_KERNEL, PAGE0, KA2PA(frame0), PAGE_PRESENT | PAGE_WRITE); |
if (!quiet) |
printf("Mapping virtual address %p to physical address %p.\n", PAGE1, KA2PA(frame1)); |
TPRINTF("Mapping virtual address %p to physical address %p.\n", PAGE1, KA2PA(frame1)); |
page_mapping_insert(AS_KERNEL, PAGE1, KA2PA(frame1), PAGE_PRESENT | PAGE_WRITE); |
v0 = *((uint32_t *) PAGE0); |
v1 = *((uint32_t *) PAGE1); |
if (!quiet) { |
printf("Value at virtual address %p is %#x.\n", PAGE0, v0); |
printf("Value at virtual address %p is %#x.\n", PAGE1, v1); |
} |
TPRINTF("Value at virtual address %p is %#x.\n", PAGE0, v0); |
TPRINTF("Value at virtual address %p is %#x.\n", PAGE1, v1); |
if (v0 != VALUE0) |
return "Value at v0 not equal to VALUE0"; |
75,25 → 71,22 |
if (v1 != VALUE1) |
return "Value at v1 not equal to VALUE1"; |
if (!quiet) |
printf("Writing %#x to virtual address %p.\n", 0, PAGE0); |
TPRINTF("Writing %#x to virtual address %p.\n", 0, PAGE0); |
*((uint32_t *) PAGE0) = 0; |
if (!quiet) |
printf("Writing %#x to virtual address %p.\n", 0, PAGE1); |
*((uint32_t *) PAGE1) = 0; |
TPRINTF("Writing %#x to virtual address %p.\n", 0, PAGE1); |
*((uint32_t *) PAGE1) = 0; |
v0 = *((uint32_t *) PAGE0); |
v1 = *((uint32_t *) PAGE1); |
if (!quiet) { |
printf("Value at virtual address %p is %#x.\n", PAGE0, *((uint32_t *) PAGE0)); |
printf("Value at virtual address %p is %#x.\n", PAGE1, *((uint32_t *) PAGE1)); |
} |
TPRINTF("Value at virtual address %p is %#x.\n", PAGE0, *((uint32_t *) PAGE0)); |
TPRINTF("Value at virtual address %p is %#x.\n", PAGE1, *((uint32_t *) PAGE1)); |
if (v0 != 0) |
return "Value at v0 not equal to 0"; |
if (v1 != 0) |
return "Value at v1 not equal to 0"; |
return NULL; |
return NULL; |
} |
/branches/dynload/kernel/test/fpu/fpu1_ia64.c |
---|
63,7 → 63,6 |
static atomic_t threads_ok; |
static atomic_t threads_fault; |
static waitq_t can_start; |
static bool sh_quiet; |
static void e(void *data) |
{ |
85,8 → 84,7 |
} |
if ((int) (100000000 * e) != E_10e8) { |
if (!sh_quiet) |
printf("tid%" PRIu64 ": e*10e8=%zd should be %" PRIun "\n", THREAD->tid, (unative_t) (100000000 * e), (unative_t) E_10e8); |
TPRINTF("tid%" PRIu64 ": e*10e8=%zd should be %" PRIun "\n", THREAD->tid, (unative_t) (100000000 * e), (unative_t) E_10e8); |
atomic_inc(&threads_fault); |
break; |
} |
119,8 → 117,7 |
} |
if ((int) (1000000 * pi) != PI_10e8) { |
if (!sh_quiet) |
printf("tid%" PRIu64 ": pi*10e8=%zd should be %" PRIun "\n", THREAD->tid, (unative_t) (1000000 * pi), (unative_t) (PI_10e8 / 100)); |
TPRINTF("tid%" PRIu64 ": pi*10e8=%zd should be %" PRIun "\n", THREAD->tid, (unative_t) (1000000 * pi), (unative_t) (PI_10e8 / 100)); |
atomic_inc(&threads_fault); |
break; |
} |
128,24 → 125,21 |
atomic_inc(&threads_ok); |
} |
char * test_fpu1(bool quiet) |
char *test_fpu1(void) |
{ |
unsigned int i, total = 0; |
sh_quiet = quiet; |
waitq_initialize(&can_start); |
atomic_set(&threads_ok, 0); |
atomic_set(&threads_fault, 0); |
if (!quiet) |
printf("Creating %u threads... ", 2 * THREADS); |
TPRINTF("Creating %u threads... ", 2 * THREADS); |
for (i = 0; i < THREADS; i++) { |
for (i = 0; i < THREADS; i++) { |
thread_t *t; |
if (!(t = thread_create(e, NULL, TASK, 0, "e", false))) { |
if (!quiet) |
printf("could not create thread %u\n", 2 * i); |
TPRINTF("could not create thread %u\n", 2 * i); |
break; |
} |
thread_ready(t); |
152,8 → 146,7 |
total++; |
if (!(t = thread_create(pi, NULL, TASK, 0, "pi", false))) { |
if (!quiet) |
printf("could not create thread %u\n", 2 * i + 1); |
TPRINTF("could not create thread %u\n", 2 * i + 1); |
break; |
} |
thread_ready(t); |
160,15 → 153,13 |
total++; |
} |
if (!quiet) |
printf("ok\n"); |
TPRINTF("ok\n"); |
thread_sleep(1); |
waitq_wakeup(&can_start, WAKEUP_ALL); |
while (atomic_get(&threads_ok) != (long) total) { |
if (!quiet) |
printf("Threads left: %d\n", total - atomic_get(&threads_ok)); |
TPRINTF("Threads left: %d\n", total - atomic_get(&threads_ok)); |
thread_sleep(1); |
} |
/branches/dynload/kernel/test/fpu/fpu1_x86.c |
---|
60,7 → 60,6 |
static atomic_t threads_ok; |
static atomic_t threads_fault; |
static waitq_t can_start; |
static bool sh_quiet; |
static void e(void *data) |
{ |
82,8 → 81,7 |
} |
if ((int) (100000000 * e) != E_10e8) { |
if (!sh_quiet) |
printf("tid%" PRIu64 ": e*10e8=%zd should be %" PRIun "\n", THREAD->tid, (unative_t) (100000000 * e), (unative_t) E_10e8); |
TPRINTF("tid%" PRIu64 ": e*10e8=%zd should be %" PRIun "\n", THREAD->tid, (unative_t) (100000000 * e), (unative_t) E_10e8); |
atomic_inc(&threads_fault); |
break; |
} |
116,8 → 114,7 |
} |
if ((int) (100000000 * pi) != PI_10e8) { |
if (!sh_quiet) |
printf("tid%" PRIu64 ": pi*10e8=%zd should be %" PRIun "\n", THREAD->tid, (unative_t) (100000000 * pi), (unative_t) PI_10e8); |
TPRINTF("tid%" PRIu64 ": pi*10e8=%zd should be %" PRIun "\n", THREAD->tid, (unative_t) (100000000 * pi), (unative_t) PI_10e8); |
atomic_inc(&threads_fault); |
break; |
} |
125,24 → 122,21 |
atomic_inc(&threads_ok); |
} |
char * test_fpu1(bool quiet) |
char *test_fpu1(void) |
{ |
unsigned int i, total = 0; |
sh_quiet = quiet; |
waitq_initialize(&can_start); |
atomic_set(&threads_ok, 0); |
atomic_set(&threads_fault, 0); |
if (!quiet) |
printf("Creating %u threads... ", 2 * THREADS); |
TPRINTF("Creating %u threads... ", 2 * THREADS); |
for (i = 0; i < THREADS; i++) { |
for (i = 0; i < THREADS; i++) { |
thread_t *t; |
if (!(t = thread_create(e, NULL, TASK, 0, "e", false))) { |
if (!quiet) |
printf("could not create thread %u\n", 2 * i); |
TPRINTF("could not create thread %u\n", 2 * i); |
break; |
} |
thread_ready(t); |
149,8 → 143,7 |
total++; |
if (!(t = thread_create(pi, NULL, TASK, 0, "pi", false))) { |
if (!quiet) |
printf("could not create thread %u\n", 2 * i + 1); |
TPRINTF("could not create thread %u\n", 2 * i + 1); |
break; |
} |
thread_ready(t); |
157,15 → 150,13 |
total++; |
} |
if (!quiet) |
printf("ok\n"); |
TPRINTF("ok\n"); |
thread_sleep(1); |
waitq_wakeup(&can_start, WAKEUP_ALL); |
while (atomic_get(&threads_ok) != (long) total) { |
if (!quiet) |
printf("Threads left: %d\n", total - atomic_get(&threads_ok)); |
TPRINTF("Threads left: %d\n", total - atomic_get(&threads_ok)); |
thread_sleep(1); |
} |
/branches/dynload/kernel/test/fpu/mips2_skip.c |
---|
28,7 → 28,7 |
#include <test.h> |
char * test_mips2(bool quiet) |
char *test_mips2(void) |
{ |
return NULL; |
} |
/branches/dynload/kernel/test/fpu/fpu1_skip.c |
---|
28,7 → 28,7 |
#include <test.h> |
char * test_fpu1(bool quiet) |
char *test_fpu1(void) |
{ |
return NULL; |
} |
/branches/dynload/kernel/test/fpu/sse1_skip.c |
---|
28,7 → 28,7 |
#include <test.h> |
char * test_sse1(bool quiet) |
char *test_sse1(void) |
{ |
return NULL; |
} |
/branches/dynload/kernel/test/fpu/mips2.c |
---|
43,7 → 43,6 |
static atomic_t threads_ok; |
static atomic_t threads_fault; |
static waitq_t can_start; |
static bool sh_quiet; |
static void testit1(void *data) |
{ |
69,8 → 68,7 |
); |
if (arg != after_arg) { |
if (!sh_quiet) |
printf("General reg tid%" PRIu64 ": arg(%d) != %d\n", THREAD->tid, arg, after_arg); |
TPRINTF("General reg tid%" PRIu64 ": arg(%d) != %d\n", THREAD->tid, arg, after_arg); |
atomic_inc(&threads_fault); |
break; |
} |
101,8 → 99,7 |
); |
if (arg != after_arg) { |
if (!sh_quiet) |
printf("General reg tid%" PRIu64 ": arg(%d) != %d\n", THREAD->tid, arg, after_arg); |
TPRINTF("General reg tid%" PRIu64 ": arg(%d) != %d\n", THREAD->tid, arg, after_arg); |
atomic_inc(&threads_fault); |
break; |
} |
111,24 → 108,21 |
} |
char * test_mips2(bool quiet) |
char *test_mips2(void) |
{ |
unsigned int i, total = 0; |
sh_quiet = quiet; |
waitq_initialize(&can_start); |
atomic_set(&threads_ok, 0); |
atomic_set(&threads_fault, 0); |
if (!quiet) |
printf("Creating %u threads... ", 2 * THREADS); |
TPRINTF("Creating %u threads... ", 2 * THREADS); |
for (i = 0; i < THREADS; i++) { |
thread_t *t; |
if (!(t = thread_create(testit1, (void *) ((unative_t) 2 * i), TASK, 0, "testit1", false))) { |
if (!quiet) |
printf("could not create thread %u\n", 2 * i); |
TPRINTF("could not create thread %u\n", 2 * i); |
break; |
} |
thread_ready(t); |
135,8 → 129,7 |
total++; |
if (!(t = thread_create(testit2, (void *) ((unative_t) 2 * i + 1), TASK, 0, "testit2", false))) { |
if (!quiet) |
printf("could not create thread %u\n", 2 * i + 1); |
TPRINTF("could not create thread %u\n", 2 * i + 1); |
break; |
} |
thread_ready(t); |
143,15 → 136,13 |
total++; |
} |
if (!quiet) |
printf("ok\n"); |
TPRINTF("ok\n"); |
thread_sleep(1); |
waitq_wakeup(&can_start, WAKEUP_ALL); |
while (atomic_get(&threads_ok) != (long) total) { |
if (!quiet) |
printf("Threads left: %d\n", total - atomic_get(&threads_ok)); |
TPRINTF("Threads left: %d\n", total - atomic_get(&threads_ok)); |
thread_sleep(1); |
} |
/branches/dynload/kernel/test/fpu/sse1.c |
---|
43,25 → 43,23 |
static atomic_t threads_ok; |
static atomic_t threads_fault; |
static waitq_t can_start; |
static bool sh_quiet; |
static void testit1(void *data) |
{ |
int i; |
int arg __attribute__((aligned(16))) = (int) ((unative_t) data); |
int after_arg __attribute__((aligned(16))); |
thread_detach(THREAD); |
waitq_sleep(&can_start); |
for (i = 0; i < ATTEMPTS; i++) { |
asm volatile ( |
"movlpd %[arg], %%xmm2\n" |
: [arg] "=m" (arg) |
); |
delay(DELAY); |
asm volatile ( |
"movlpd %%xmm2, %[after_arg]\n" |
69,8 → 67,7 |
); |
if (arg != after_arg) { |
if (!sh_quiet) |
printf("tid%" PRIu64 ": arg(%d) != %d\n", THREAD->tid, arg, after_arg); |
TPRINTF("tid%" PRIu64 ": arg(%d) != %d\n", THREAD->tid, arg, after_arg); |
atomic_inc(&threads_fault); |
break; |
} |
87,13 → 84,13 |
thread_detach(THREAD); |
waitq_sleep(&can_start); |
for (i = 0; i < ATTEMPTS; i++) { |
asm volatile ( |
"movlpd %[arg], %%xmm2\n" |
: [arg] "=m" (arg) |
); |
scheduler(); |
asm volatile ( |
"movlpd %%xmm2, %[after_arg]\n" |
101,8 → 98,7 |
); |
if (arg != after_arg) { |
if (!sh_quiet) |
printf("tid%" PRIu64 ": arg(%d) != %d\n", THREAD->tid, arg, after_arg); |
TPRINTF("tid%" PRIu64 ": arg(%d) != %d\n", THREAD->tid, arg, after_arg); |
atomic_inc(&threads_fault); |
break; |
} |
110,25 → 106,21 |
atomic_inc(&threads_ok); |
} |
char * test_sse1(bool quiet) |
char *test_sse1(void) |
{ |
unsigned int i, total = 0; |
sh_quiet = quiet; |
waitq_initialize(&can_start); |
atomic_set(&threads_ok, 0); |
atomic_set(&threads_fault, 0); |
if (!quiet) |
printf("Creating %u threads... ", 2 * THREADS); |
TPRINTF("Creating %u threads... ", 2 * THREADS); |
for (i = 0; i < THREADS; i++) { |
thread_t *t; |
if (!(t = thread_create(testit1, (void *) ((unative_t) 2 * i), TASK, 0, "testit1", false))) { |
if (!quiet) |
printf("could not create thread %u\n", 2 * i); |
TPRINTF("could not create thread %u\n", 2 * i); |
break; |
} |
thread_ready(t); |
135,8 → 127,7 |
total++; |
if (!(t = thread_create(testit2, (void *) ((unative_t) 2 * i + 1), TASK, 0, "testit2", false))) { |
if (!quiet) |
printf("could not create thread %u\n", 2 * i + 1); |
TPRINTF("could not create thread %u\n", 2 * i + 1); |
break; |
} |
thread_ready(t); |
143,15 → 134,13 |
total++; |
} |
if (!quiet) |
printf("ok\n"); |
TPRINTF("ok\n"); |
thread_sleep(1); |
waitq_wakeup(&can_start, WAKEUP_ALL); |
while (atomic_get(&threads_ok) != (long) total) { |
if (!quiet) |
printf("Threads left: %d\n", total - atomic_get(&threads_ok)); |
TPRINTF("Threads left: %d\n", total - atomic_get(&threads_ok)); |
thread_sleep(1); |
} |
/branches/dynload/kernel/test/sysinfo/sysinfo1.c |
---|
32,9 → 32,9 |
#include <test.h> |
#include <sysinfo/sysinfo.h> |
char * test_sysinfo1(bool quiet) |
char *test_sysinfo1(void) |
{ |
if (!quiet) |
if (!test_quiet) |
sysinfo_dump(NULL, 0); |
return NULL; |
} |
/branches/dynload/kernel/test/fault/fault1.c |
---|
36,8 → 36,7 |
#include <arch.h> |
char * test_fault1(bool quiet) |
char *test_fault1(void) |
{ |
((int *)(0))[1] = 0; |
/branches/dynload/kernel/test/atomic/atomic1.c |
---|
31,7 → 31,7 |
#include <atomic.h> |
#include <debug.h> |
char * test_atomic1(bool quiet) |
char *test_atomic1(void) |
{ |
atomic_t a; |
/branches/dynload/kernel/test/print/print2.c |
---|
29,31 → 29,29 |
#include <print.h> |
#include <test.h> |
char *test_print2(bool quiet) |
char *test_print2(void) |
{ |
if (!quiet) { |
printf("Testing printf(\"%%c %%3.2c %%-3.2c %%2.3c %%-2.3c\", 'a', 'b', 'c', 'd', 'e'):\n"); |
printf("Expected output: [a] [ b] [c ] [ d] [e ]\n"); |
printf("Real output: [%c] [%3.2c] [%-3.2c] [%2.3c] [%-2.3c]\n\n", 'a', 'b', 'c', 'd', 'e'); |
printf("Testing printf(\"%%d %%3.2d %%-3.2d %%2.3d %%-2.3d\", 1, 2, 3, 4, 5):\n"); |
printf("Expected output: [1] [ 02] [03 ] [004] [005]\n"); |
printf("Real output: [%d] [%3.2d] [%-3.2d] [%2.3d] [%-2.3d]\n\n", 1, 2, 3, 4, 5); |
printf("Testing printf(\"%%d %%3.2d %%-3.2d %%2.3d %%-2.3d\", -1, -2, -3, -4, -5):\n"); |
printf("Expected output: [-1] [-02] [-03] [-004] [-005]\n"); |
printf("Real output: [%d] [%3.2d] [%-3.2d] [%2.3d] [%-2.3d]\n\n", -1, -2, -3, -4, -5); |
printf("Testing printf(\"%%#x %%5.3#x %%-5.3#x %%3.5#x %%-3.5#x\", 17, 18, 19, 20, 21):\n"); |
printf("Expected output: [0x11] [0x012] [0x013] [0x00014] [0x00015]\n"); |
printf("Real output: [%#x] [%#5.3x] [%#-5.3x] [%#3.5x] [%#-3.5x]\n\n", 17, 18, 19, 20, 21); |
unative_t nat = 0x12345678u; |
printf("Testing printf(\"%%#" PRIx64 " %%#" PRIx32 " %%#" PRIx16 " %%#" PRIx8 " %%#" PRIxn " %%#" PRIx64 " %%s\", 0x1234567887654321ll, 0x12345678, 0x1234, 0x12, nat, 0x1234567887654321ull, \"Lovely string\"):\n"); |
printf("Expected output: [0x1234567887654321] [0x12345678] [0x1234] [0x12] [0x12345678] [0x1234567887654321] \"Lovely string\"\n"); |
printf("Real output: [%#" PRIx64 "] [%#" PRIx32 "] [%#" PRIx16 "] [%#" PRIx8 "] [%#" PRIxn "] [%#" PRIx64 "] \"%s\"\n\n", 0x1234567887654321ll, 0x12345678, 0x1234, 0x12, nat, 0x1234567887654321ull, "Lovely string"); |
} |
TPRINTF("Testing printf(\"%%c %%3.2c %%-3.2c %%2.3c %%-2.3c\", 'a', 'b', 'c', 'd', 'e'):\n"); |
TPRINTF("Expected output: [a] [ b] [c ] [ d] [e ]\n"); |
TPRINTF("Real output: [%c] [%3.2c] [%-3.2c] [%2.3c] [%-2.3c]\n\n", 'a', 'b', 'c', 'd', 'e'); |
TPRINTF("Testing printf(\"%%d %%3.2d %%-3.2d %%2.3d %%-2.3d\", 1, 2, 3, 4, 5):\n"); |
TPRINTF("Expected output: [1] [ 02] [03 ] [004] [005]\n"); |
TPRINTF("Real output: [%d] [%3.2d] [%-3.2d] [%2.3d] [%-2.3d]\n\n", 1, 2, 3, 4, 5); |
TPRINTF("Testing printf(\"%%d %%3.2d %%-3.2d %%2.3d %%-2.3d\", -1, -2, -3, -4, -5):\n"); |
TPRINTF("Expected output: [-1] [-02] [-03] [-004] [-005]\n"); |
TPRINTF("Real output: [%d] [%3.2d] [%-3.2d] [%2.3d] [%-2.3d]\n\n", -1, -2, -3, -4, -5); |
TPRINTF("Testing printf(\"%%#x %%5.3#x %%-5.3#x %%3.5#x %%-3.5#x\", 17, 18, 19, 20, 21):\n"); |
TPRINTF("Expected output: [0x11] [0x012] [0x013] [0x00014] [0x00015]\n"); |
TPRINTF("Real output: [%#x] [%#5.3x] [%#-5.3x] [%#3.5x] [%#-3.5x]\n\n", 17, 18, 19, 20, 21); |
unative_t nat = 0x12345678u; |
TPRINTF("Testing printf(\"%%#" PRIx64 " %%#" PRIx32 " %%#" PRIx16 " %%#" PRIx8 " %%#" PRIxn " %%#" PRIx64 " %%s\", 0x1234567887654321ll, 0x12345678, 0x1234, 0x12, nat, 0x1234567887654321ull, \"Lovely string\"):\n"); |
TPRINTF("Expected output: [0x1234567887654321] [0x12345678] [0x1234] [0x12] [0x12345678] [0x1234567887654321] \"Lovely string\"\n"); |
TPRINTF("Real output: [%#" PRIx64 "] [%#" PRIx32 "] [%#" PRIx16 "] [%#" PRIx8 "] [%#" PRIxn "] [%#" PRIx64 "] \"%s\"\n\n", 0x1234567887654321ll, 0x12345678, 0x1234, 0x12, nat, 0x1234567887654321ull, "Lovely string"); |
return NULL; |
} |
/branches/dynload/kernel/test/print/print3.c |
---|
32,32 → 32,30 |
#define BUFFER_SIZE 32 |
char *test_print3(bool quiet) |
char *test_print3(void) |
{ |
if (!quiet) { |
char buffer[BUFFER_SIZE]; |
int retval; |
printf("Testing snprintf(buffer, " STRING(BUFFER_SIZE) ", \"Short text without parameters.\"):\n"); |
printf("Expected result: retval=30 buffer=\"Short text without parameters.\"\n"); |
retval = snprintf(buffer, BUFFER_SIZE, "Short text without parameters."); |
printf("Real result: retval=%d buffer=\"%s\"\n\n", retval, buffer); |
printf("Testing snprintf(buffer, " STRING(BUFFER_SIZE) ", \"Very very very long text without parameters.\"):\n"); |
printf("Expected result: retval=44 buffer=\"Very very very long text withou\"\n"); |
retval = snprintf(buffer, BUFFER_SIZE, "Very very very long text without parameters."); |
printf("Real result: retval=%d buffer=\"%s\"\n\n", retval, buffer); |
printf("Testing snprintf(buffer, " STRING(BUFFER_SIZE) ", \"Short %%s.\", \"text\"):\n"); |
printf("Expected result: retval=11 buffer=\"Short text.\"\n"); |
retval = snprintf(buffer, BUFFER_SIZE, "Short %s.", "text"); |
printf("Real result: retval=%d buffer=\"%s\"\n\n", retval, buffer); |
printf("Testing snprintf(buffer, " STRING(BUFFER_SIZE) ", \"Very long %%s. This text's length is more than %%d. We are interested in the result.\", \"text\", " STRING(BUFFER_SIZE) "):\n"); |
printf("Expected result: retval=84 buffer=\"Very long text. This text's len\"\n"); |
retval = snprintf(buffer, BUFFER_SIZE, "Very long %s. This text's length is more than %d. We are interested in the result.", "text", BUFFER_SIZE); |
printf("Real result: retval=%d buffer=\"%s\"\n\n", retval, buffer); |
} |
char buffer[BUFFER_SIZE]; |
int retval; |
TPRINTF("Testing snprintf(buffer, " STRING(BUFFER_SIZE) ", \"Short text without parameters.\"):\n"); |
TPRINTF("Expected result: retval=30 buffer=\"Short text without parameters.\"\n"); |
retval = snprintf(buffer, BUFFER_SIZE, "Short text without parameters."); |
TPRINTF("Real result: retval=%d buffer=\"%s\"\n\n", retval, buffer); |
TPRINTF("Testing snprintf(buffer, " STRING(BUFFER_SIZE) ", \"Very very very long text without parameters.\"):\n"); |
TPRINTF("Expected result: retval=44 buffer=\"Very very very long text withou\"\n"); |
retval = snprintf(buffer, BUFFER_SIZE, "Very very very long text without parameters."); |
TPRINTF("Real result: retval=%d buffer=\"%s\"\n\n", retval, buffer); |
TPRINTF("Testing snprintf(buffer, " STRING(BUFFER_SIZE) ", \"Short %%s.\", \"text\"):\n"); |
TPRINTF("Expected result: retval=11 buffer=\"Short text.\"\n"); |
retval = snprintf(buffer, BUFFER_SIZE, "Short %s.", "text"); |
TPRINTF("Real result: retval=%d buffer=\"%s\"\n\n", retval, buffer); |
TPRINTF("Testing snprintf(buffer, " STRING(BUFFER_SIZE) ", \"Very long %%s. This text's length is more than %%d. We are interested in the result.\", \"text\", " STRING(BUFFER_SIZE) "):\n"); |
TPRINTF("Expected result: retval=84 buffer=\"Very long text. This text's len\"\n"); |
retval = snprintf(buffer, BUFFER_SIZE, "Very long %s. This text's length is more than %d. We are interested in the result.", "text", BUFFER_SIZE); |
TPRINTF("Real result: retval=%d buffer=\"%s\"\n\n", retval, buffer); |
return NULL; |
} |
/branches/dynload/kernel/test/print/print4.c |
---|
29,56 → 29,54 |
#include <print.h> |
#include <test.h> |
char *test_print4(bool quiet) |
char *test_print4(void) |
{ |
if (!quiet) { |
printf("ASCII printable characters (32 - 127) using printf(\"%%c\") and printf(\"%%lc\"):\n"); |
TPRINTF("ASCII printable characters (32 - 127) using printf(\"%%c\") and printf(\"%%lc\"):\n"); |
uint8_t group; |
for (group = 1; group < 4; group++) { |
TPRINTF("%#" PRIx8 ": ", group << 5); |
uint8_t group; |
for (group = 1; group < 4; group++) { |
printf("%#" PRIx8 ": ", group << 5); |
uint8_t index; |
for (index = 0; index < 32; index++) |
printf("%c", (char) ((group << 5) + index)); |
printf(" "); |
for (index = 0; index < 32; index++) |
printf("%lc", (wchar_t) ((group << 5) + index)); |
printf("\n"); |
} |
uint8_t index; |
for (index = 0; index < 32; index++) |
TPRINTF("%c", (char) ((group << 5) + index)); |
printf("\nExtended ASCII characters (128 - 255) using printf(\"%%lc\"):\n"); |
TPRINTF(" "); |
for (index = 0; index < 32; index++) |
TPRINTF("%lc", (wchar_t) ((group << 5) + index)); |
for (group = 4; group < 8; group++) { |
printf("%#" PRIx8 ": ", group << 5); |
uint8_t index; |
for (index = 0; index < 32; index++) |
printf("%lc", (wchar_t) ((group << 5) + index)); |
printf("\n"); |
} |
TPRINTF("\n"); |
} |
TPRINTF("\nExtended ASCII characters (128 - 255) using printf(\"%%lc\"):\n"); |
for (group = 4; group < 8; group++) { |
TPRINTF("%#" PRIx8 ": ", group << 5); |
printf("\nUTF-8 strings using printf(\"%%s\"):\n"); |
printf("English: %s\n", "Quick brown fox jumps over the lazy dog"); |
printf("Czech: %s\n", "Příliš žluťoučký kůň úpěl ďábelské ódy"); |
printf("Greek: %s\n", "á½® ξεῖν’, ἀγγÎλλειν Λακεδαιμονίοις ὅτι τῇδε"); |
printf("Hebrew: %s\n", "משוואת ברנולי היא משוואה בהידרודינמיקה"); |
printf("Arabic: %s\n", "التوزيع الجغرافي للحمل العنقودي"); |
printf("Russian: %s\n", "Леннон познакомился с художницей-авангардисткой"); |
printf("Armenian: %s\n", "ÕÕ¯Õ½Õ¥Ö Õ°Ö€Õ¡Õ¿Õ¡Ö€Õ¡Õ¯Õ¾Õ¥Õ¬ ÔµÖ€Õ¸Ö‚Õ½Õ¡Õ²Õ¥Õ´Õ« Õ°Õ¡ÕµÕ¯Õ¡Õ¯Õ¡Õ¶"); |
uint8_t index; |
for (index = 0; index < 32; index++) |
TPRINTF("%lc", (wchar_t) ((group << 5) + index)); |
printf("\nUTF-32 strings using printf(\"%%ls\"):\n"); |
printf("English: %ls\n", L"Quick brown fox jumps over the lazy dog"); |
printf("Czech: %ls\n", L"Příliš žluťoučký kůň úpěl ďábelské ódy"); |
printf("Greek: %ls\n", L"á½® ξεῖν’, ἀγγÎλλειν Λακεδαιμονίοις ὅτι τῇδε"); |
printf("Hebrew: %ls\n", L"משוואת ברנולי היא משוואה בהידרודינמיקה"); |
printf("Arabic: %ls\n", L"التوزيع الجغرافي للحمل العنقودي"); |
printf("Russian: %ls\n", L"Леннон познакомился с художницей-авангардисткой"); |
printf("Armenian: %ls\n", L"ÕÕ¯Õ½Õ¥Ö Õ°Ö€Õ¡Õ¿Õ¡Ö€Õ¡Õ¯Õ¾Õ¥Õ¬ ÔµÖ€Õ¸Ö‚Õ½Õ¡Õ²Õ¥Õ´Õ« Õ°Õ¡ÕµÕ¯Õ¡Õ¯Õ¡Õ¶"); |
TPRINTF("\n"); |
} |
TPRINTF("\nUTF-8 strings using printf(\"%%s\"):\n"); |
TPRINTF("English: %s\n", "Quick brown fox jumps over the lazy dog"); |
TPRINTF("Czech: %s\n", "Příliš žluťoučký kůň úpěl ďábelské ódy"); |
TPRINTF("Greek: %s\n", "á½® ξεῖν’, ἀγγÎλλειν Λακεδαιμονίοις ὅτι τῇδε"); |
TPRINTF("Hebrew: %s\n", "משוואת ברנולי היא משוואה בהידרודינמיקה"); |
TPRINTF("Arabic: %s\n", "التوزيع الجغرافي للحمل العنقودي"); |
TPRINTF("Russian: %s\n", "Леннон познакомился с художницей-авангардисткой"); |
TPRINTF("Armenian: %s\n", "ÕÕ¯Õ½Õ¥Ö Õ°Ö€Õ¡Õ¿Õ¡Ö€Õ¡Õ¯Õ¾Õ¥Õ¬ ÔµÖ€Õ¸Ö‚Õ½Õ¡Õ²Õ¥Õ´Õ« Õ°Õ¡ÕµÕ¯Õ¡Õ¯Õ¡Õ¶"); |
TPRINTF("\nUTF-32 strings using printf(\"%%ls\"):\n"); |
TPRINTF("English: %ls\n", L"Quick brown fox jumps over the lazy dog"); |
TPRINTF("Czech: %ls\n", L"Příliš žluťoučký kůň úpěl ďábelské ódy"); |
TPRINTF("Greek: %ls\n", L"á½® ξεῖν’, ἀγγÎλλειν Λακεδαιμονίοις ὅτι τῇδε"); |
TPRINTF("Hebrew: %ls\n", L"משוואת ברנולי היא משוואה בהידרודינמיקה"); |
TPRINTF("Arabic: %ls\n", L"التوزيع الجغرافي للحمل العنقودي"); |
TPRINTF("Russian: %ls\n", L"Леннон познакомился с художницей-авангардисткой"); |
TPRINTF("Armenian: %ls\n", L"ÕÕ¯Õ½Õ¥Ö Õ°Ö€Õ¡Õ¿Õ¡Ö€Õ¡Õ¯Õ¾Õ¥Õ¬ ÔµÖ€Õ¸Ö‚Õ½Õ¡Õ²Õ¥Õ´Õ« Õ°Õ¡ÕµÕ¯Õ¡Õ¯Õ¡Õ¶"); |
return NULL; |
} |
/branches/dynload/kernel/test/print/print1.c |
---|
29,29 → 29,27 |
#include <print.h> |
#include <test.h> |
char *test_print1(bool quiet) |
char *test_print1(void) |
{ |
if (!quiet) { |
printf("Testing printf(\"%%*.*s\", 5, 3, \"text\"):\n"); |
printf("Expected output: \" tex\"\n"); |
printf("Real output: \"%*.*s\"\n\n", 5, 3, "text"); |
printf("Testing printf(\"%%10.8s\", \"very long text\"):\n"); |
printf("Expected output: \" very lon\"\n"); |
printf("Real output: \"%10.8s\"\n\n", "very long text"); |
printf("Testing printf(\"%%8.10s\", \"text\"):\n"); |
printf("Expected output: \"text\"\n"); |
printf("Real output: \"%8.10s\"\n\n", "text"); |
printf("Testing printf(\"%%8.10s\", \"very long text\"):\n"); |
printf("Expected output: \"very long \"\n"); |
printf("Real output: \"%8.10s\"\n\n", "very long text"); |
printf("Testing printf(\"%%s\", NULL):\n"); |
printf("Expected output: \"(NULL)\"\n"); |
printf("Real output: \"%s\"\n\n", NULL); |
} |
TPRINTF("Testing printf(\"%%*.*s\", 5, 3, \"text\"):\n"); |
TPRINTF("Expected output: \" tex\"\n"); |
TPRINTF("Real output: \"%*.*s\"\n\n", 5, 3, "text"); |
TPRINTF("Testing printf(\"%%10.8s\", \"very long text\"):\n"); |
TPRINTF("Expected output: \" very lon\"\n"); |
TPRINTF("Real output: \"%10.8s\"\n\n", "very long text"); |
TPRINTF("Testing printf(\"%%8.10s\", \"text\"):\n"); |
TPRINTF("Expected output: \"text\"\n"); |
TPRINTF("Real output: \"%8.10s\"\n\n", "text"); |
TPRINTF("Testing printf(\"%%8.10s\", \"very long text\"):\n"); |
TPRINTF("Expected output: \"very long \"\n"); |
TPRINTF("Real output: \"%8.10s\"\n\n", "very long text"); |
TPRINTF("Testing printf(\"%%s\", NULL):\n"); |
TPRINTF("Expected output: \"(NULL)\"\n"); |
TPRINTF("Real output: \"%s\"\n\n", NULL); |
return NULL; |
} |
/branches/dynload/kernel/genarch/include/kbrd/scanc_pc.h |
---|
26,30 → 26,21 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup genarch |
/** @addtogroup genarch |
* @{ |
*/ |
/** |
* @file |
* @brief Scan codes for pc keyboards. |
* @brief Scan codes for PC keyboards. |
*/ |
#ifndef KERN_SCANC_PC_H_ |
#define KERN_SCANC_PC_H_ |
#define SC_ESC 0x01 |
#define SC_BACKSPACE 0x0e |
#define SC_LSHIFT 0x2a |
#define SC_RSHIFT 0x36 |
#define SC_CAPSLOCK 0x3a |
#define SC_SPEC_ESCAPE 0xe0 |
#define SC_LEFTARR 0x4b |
#define SC_RIGHTARR 0x4d |
#define SC_UPARR 0x48 |
#define SC_DOWNARR 0x50 |
#define SC_DELETE 0x53 |
#define SC_HOME 0x47 |
#define SC_END 0x4f |
#define SC_SCAN_ESCAPE 0xe0 |
#endif |
/branches/dynload/kernel/genarch/include/kbrd/scanc_sun.h |
---|
26,30 → 26,21 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup genarch |
/** @addtogroup genarch |
* @{ |
*/ |
/** |
* @file |
* @brief Scan codes for sun keyboards. |
* @brief Scan codes for Sun keyboards. |
*/ |
#ifndef KERN_SCANC_SUN_H_ |
#define KERN_SCANC_SUN_H_ |
#define SC_ESC 0x1d |
#define SC_BACKSPACE 0x2b |
#define SC_LSHIFT 0x63 |
#define SC_RSHIFT 0x6e |
#define SC_CAPSLOCK 0x77 |
#define SC_SPEC_ESCAPE 0xe0 /* ??? */ |
#define SC_LEFTARR 0x18 |
#define SC_RIGHTARR 0x1c |
#define SC_UPARR 0x14 |
#define SC_DOWNARR 0x1b |
#define SC_DELETE 0x42 |
#define SC_HOME 0x34 |
#define SC_END 0x4a |
#define SC_SCAN_ESCAPE 0xe0 |
#endif |
/branches/dynload/kernel/genarch/include/kbrd/kbrd.h |
---|
37,9 → 37,23 |
#define KERN_KBD_H_ |
#include <console/chardev.h> |
#include <proc/thread.h> |
#include <synch/spinlock.h> |
extern void kbrd_init(indev_t *devin); |
typedef struct { |
thread_t *thread; |
indev_t *sink; |
indev_t raw; |
SPINLOCK_DECLARE(keylock); /**< keylock protects keyflags and lockflags. */ |
volatile unsigned int keyflags; /**< Tracking of multiple keypresses. */ |
volatile unsigned int lockflags; /**< Tracking of multiple keys lockings. */ |
} kbrd_instance_t; |
extern kbrd_instance_t *kbrd_init(void); |
extern indev_t *kbrd_wire(kbrd_instance_t *, indev_t *); |
#endif |
/** @} |
/branches/dynload/kernel/genarch/include/kbrd/scanc.h |
---|
26,7 → 26,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup genarch |
/** @addtogroup genarch |
* @{ |
*/ |
/** |
36,11 → 36,13 |
#ifndef KERN_SCANC_H_ |
#define KERN_SCANC_H_ |
#define SPECIAL '?' |
#include <typedefs.h> |
extern char sc_primary_map[]; |
extern char sc_secondary_map[]; |
#define SCANCODES 128 |
extern wchar_t sc_primary_map[SCANCODES]; |
extern wchar_t sc_secondary_map[SCANCODES]; |
#endif |
/** @} |
/branches/dynload/kernel/genarch/include/drivers/ns16550/ns16550.h |
---|
62,12 → 62,13 |
/** Structure representing the ns16550 device. */ |
typedef struct { |
irq_t irq; |
ns16550_t *ns16550; |
irq_t irq; |
indev_t kbrdin; |
indev_t *kbrdin; |
} ns16550_instance_t; |
extern indev_t *ns16550_init(ns16550_t *, inr_t, cir_t, void *); |
extern ns16550_instance_t *ns16550_init(ns16550_t *, inr_t, cir_t, void *); |
extern void ns16550_wire(ns16550_instance_t *, indev_t *); |
#endif |
/branches/dynload/kernel/genarch/include/drivers/dsrln/dsrlnin.h |
---|
49,10 → 49,11 |
typedef struct { |
irq_t irq; |
dsrlnin_t *dsrlnin; |
indev_t kbrdin; |
indev_t *srlnin; |
} dsrlnin_instance_t; |
extern indev_t *dsrlnin_init(dsrlnin_t *, inr_t); |
extern dsrlnin_instance_t *dsrlnin_init(dsrlnin_t *, inr_t); |
extern void dsrlnin_wire(dsrlnin_instance_t *, indev_t *); |
#endif |
/branches/dynload/kernel/genarch/include/drivers/i8042/i8042.h |
---|
49,10 → 49,12 |
typedef struct { |
irq_t irq; |
i8042_t *i8042; |
indev_t kbrdin; |
indev_t *kbrdin; |
} i8042_instance_t; |
extern indev_t *i8042_init(i8042_t *, inr_t); |
extern i8042_instance_t *i8042_init(i8042_t *, inr_t); |
extern void i8042_wire(i8042_instance_t *, indev_t *); |
extern void i8042_cpu_reset(i8042_t *); |
#endif |
/branches/dynload/kernel/genarch/include/drivers/z8530/z8530.h |
---|
116,10 → 116,11 |
typedef struct { |
irq_t irq; |
z8530_t *z8530; |
indev_t kbrdin; |
indev_t *kbrdin; |
} z8530_instance_t; |
extern indev_t *z8530_init(z8530_t *, inr_t, cir_t, void *); |
extern z8530_instance_t *z8530_init(z8530_t *, inr_t, cir_t, void *); |
extern void z8530_wire(z8530_instance_t *, indev_t *); |
#endif |
/branches/dynload/kernel/genarch/include/drivers/via-cuda/cuda.h |
---|
0,0 → 1,57 |
/* |
* 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. |
*/ |
/** @addtogroup genarch |
* @{ |
*/ |
/** @file |
*/ |
#ifndef KERN_CUDA_H_ |
#define KERN_CUDA_H_ |
#include <ddi/irq.h> |
#include <arch/types.h> |
#include <console/chardev.h> |
typedef struct { |
} cuda_t; |
typedef struct { |
irq_t irq; |
cuda_t *cuda; |
indev_t *kbrdin; |
} cuda_instance_t; |
extern cuda_instance_t *cuda_init(cuda_t *, inr_t, cir_t, void *); |
extern void cuda_wire(cuda_instance_t *, indev_t *); |
#endif |
/** @} |
*/ |
Property changes: |
Added: svn:mergeinfo |
/branches/dynload/kernel/genarch/include/srln/srln.h |
---|
37,9 → 37,18 |
#define KERN_SRLN_H_ |
#include <console/chardev.h> |
#include <proc/thread.h> |
extern void srln_init(indev_t *devin); |
typedef struct { |
thread_t *thread; |
indev_t *sink; |
indev_t raw; |
} srln_instance_t; |
extern srln_instance_t *srln_init(void); |
extern indev_t *srln_wire(srln_instance_t *, indev_t *); |
#endif |
/** @} |
/branches/dynload/kernel/genarch/Makefile.inc |
---|
93,6 → 93,11 |
genarch/src/drivers/z8530/z8530.c |
endif |
ifeq ($(CONFIG_VIA_CUDA),y) |
GENARCH_SOURCES += \ |
genarch/src/drivers/via-cuda/cuda.c |
endif |
ifeq ($(CONFIG_PC_KBD),y) |
GENARCH_SOURCES += \ |
genarch/src/kbrd/kbrd.c \ |
/branches/dynload/kernel/genarch/src/kbrd/kbrd.c |
---|
52,10 → 52,7 |
#include <arch.h> |
#include <macros.h> |
#ifdef CONFIG_SUN_KBD |
#define IGNORE_CODE 0x7f |
#endif |
#define IGNORE_CODE 0x7f |
#define KEY_RELEASE 0x80 |
#define PRESSED_SHIFT (1 << 0) |
62,73 → 59,35 |
#define PRESSED_CAPSLOCK (1 << 1) |
#define LOCKED_CAPSLOCK (1 << 0) |
static indev_t kbrdout; |
indev_operations_t kbrdout_ops = { |
static indev_operations_t kbrd_raw_ops = { |
.poll = NULL |
}; |
SPINLOCK_INITIALIZE(keylock); /**< keylock protects keyflags and lockflags. */ |
static volatile int keyflags; /**< Tracking of multiple keypresses. */ |
static volatile int lockflags; /**< Tracking of multiple keys lockings. */ |
static void key_released(uint8_t); |
static void key_pressed(uint8_t); |
static void kkbrd(void *arg) |
{ |
indev_t *in = (indev_t *) arg; |
while (true) { |
uint8_t sc = _getc(in); |
#ifdef CONFIG_SUN_KBD |
if (sc == IGNORE_CODE) |
continue; |
#endif |
if (sc & KEY_RELEASE) |
key_released(sc ^ KEY_RELEASE); |
else |
key_pressed(sc); |
} |
} |
void kbrd_init(indev_t *devin) |
{ |
indev_initialize("kbrd", &kbrdout, &kbrdout_ops); |
thread_t *thread |
= thread_create(kkbrd, devin, TASK, 0, "kkbrd", false); |
if (thread) { |
stdin = &kbrdout; |
thread_ready(thread); |
} |
} |
/** Process release of key. |
* |
* @param sc Scancode of the key being released. |
*/ |
void key_released(uint8_t sc) |
static void key_released(kbrd_instance_t *instance, wchar_t sc) |
{ |
spinlock_lock(&keylock); |
spinlock_lock(&instance->keylock); |
switch (sc) { |
case SC_LSHIFT: |
case SC_RSHIFT: |
keyflags &= ~PRESSED_SHIFT; |
instance->keyflags &= ~PRESSED_SHIFT; |
break; |
case SC_CAPSLOCK: |
keyflags &= ~PRESSED_CAPSLOCK; |
if (lockflags & LOCKED_CAPSLOCK) |
lockflags &= ~LOCKED_CAPSLOCK; |
instance->keyflags &= ~PRESSED_CAPSLOCK; |
if (instance->lockflags & LOCKED_CAPSLOCK) |
instance->lockflags &= ~LOCKED_CAPSLOCK; |
else |
lockflags |= LOCKED_CAPSLOCK; |
instance->lockflags |= LOCKED_CAPSLOCK; |
break; |
default: |
break; |
} |
spinlock_unlock(&keylock); |
spinlock_unlock(&instance->keylock); |
} |
/** Process keypress. |
135,74 → 94,94 |
* |
* @param sc Scancode of the key being pressed. |
*/ |
void key_pressed(uint8_t sc) |
static void key_pressed(kbrd_instance_t *instance, wchar_t sc) |
{ |
char *map = sc_primary_map; |
char ascii = sc_primary_map[sc]; |
bool shift, capslock; |
bool letter = false; |
bool letter; |
bool shift; |
bool capslock; |
spinlock_lock(&keylock); |
spinlock_lock(&instance->keylock); |
switch (sc) { |
case SC_LSHIFT: |
case SC_RSHIFT: |
keyflags |= PRESSED_SHIFT; |
instance->keyflags |= PRESSED_SHIFT; |
break; |
case SC_CAPSLOCK: |
keyflags |= PRESSED_CAPSLOCK; |
instance->keyflags |= PRESSED_CAPSLOCK; |
break; |
case SC_SPEC_ESCAPE: |
case SC_SCAN_ESCAPE: |
break; |
case SC_LEFTARR: |
indev_push_character(stdin, 0x1b); |
indev_push_character(stdin, 0x5b); |
indev_push_character(stdin, 0x44); |
break; |
case SC_RIGHTARR: |
indev_push_character(stdin, 0x1b); |
indev_push_character(stdin, 0x5b); |
indev_push_character(stdin, 0x43); |
break; |
case SC_UPARR: |
indev_push_character(stdin, 0x1b); |
indev_push_character(stdin, 0x5b); |
indev_push_character(stdin, 0x41); |
break; |
case SC_DOWNARR: |
indev_push_character(stdin, 0x1b); |
indev_push_character(stdin, 0x5b); |
indev_push_character(stdin, 0x42); |
break; |
case SC_HOME: |
indev_push_character(stdin, 0x1b); |
indev_push_character(stdin, 0x4f); |
indev_push_character(stdin, 0x48); |
break; |
case SC_END: |
indev_push_character(stdin, 0x1b); |
indev_push_character(stdin, 0x4f); |
indev_push_character(stdin, 0x46); |
break; |
case SC_DELETE: |
indev_push_character(stdin, 0x1b); |
indev_push_character(stdin, 0x5b); |
indev_push_character(stdin, 0x33); |
indev_push_character(stdin, 0x7e); |
break; |
default: |
letter = islower(ascii); |
capslock = (keyflags & PRESSED_CAPSLOCK) || |
(lockflags & LOCKED_CAPSLOCK); |
shift = keyflags & PRESSED_SHIFT; |
if (letter && capslock) |
letter = islower(sc_primary_map[sc]); |
shift = instance->keyflags & PRESSED_SHIFT; |
capslock = (instance->keyflags & PRESSED_CAPSLOCK) || |
(instance->lockflags & LOCKED_CAPSLOCK); |
if ((letter) && (capslock)) |
shift = !shift; |
if (shift) |
map = sc_secondary_map; |
indev_push_character(stdin, map[sc]); |
indev_push_character(instance->sink, sc_secondary_map[sc]); |
else |
indev_push_character(instance->sink, sc_primary_map[sc]); |
break; |
} |
spinlock_unlock(&keylock); |
spinlock_unlock(&instance->keylock); |
} |
static void kkbrd(void *arg) |
{ |
kbrd_instance_t *instance = (kbrd_instance_t *) arg; |
while (true) { |
wchar_t sc = indev_pop_character(&instance->raw); |
if (sc == IGNORE_CODE) |
continue; |
if (sc & KEY_RELEASE) |
key_released(instance, (sc ^ KEY_RELEASE) & 0x7f); |
else |
key_pressed(instance, sc & 0x7f); |
} |
} |
kbrd_instance_t *kbrd_init(void) |
{ |
kbrd_instance_t *instance |
= malloc(sizeof(kbrd_instance_t), FRAME_ATOMIC); |
if (instance) { |
instance->thread |
= thread_create(kkbrd, (void *) instance, TASK, 0, "kkbrd", false); |
if (!instance->thread) { |
free(instance); |
return NULL; |
} |
instance->sink = NULL; |
indev_initialize("kbrd", &instance->raw, &kbrd_raw_ops); |
spinlock_initialize(&instance->keylock, "instance_keylock"); |
instance->keyflags = 0; |
instance->lockflags = 0; |
} |
return instance; |
} |
indev_t *kbrd_wire(kbrd_instance_t *instance, indev_t *sink) |
{ |
ASSERT(instance); |
ASSERT(sink); |
instance->sink = sink; |
thread_ready(instance->thread); |
return &instance->raw; |
} |
/** @} |
*/ |
/branches/dynload/kernel/genarch/src/kbrd/scanc_pc.c |
---|
26,174 → 26,195 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup genarch |
/** @addtogroup genarch |
* @{ |
*/ |
/** |
* @file |
* @brief Scan codes for pc keyboards. |
* @brief Scan codes for PC keyboards. |
*/ |
#include <genarch/kbrd/scanc.h> |
#include <typedefs.h> |
#include <string.h> |
/** Primary meaning of scancodes. */ |
char sc_primary_map[] = { |
SPECIAL, /* 0x00 */ |
SPECIAL, /* 0x01 - Esc */ |
wchar_t sc_primary_map[SCANCODES] = { |
U_NULL, /* 0x00 - undefined */ |
U_ESCAPE, /* 0x01 - Esc */ |
'1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', |
'\b', /* 0x0e - Backspace */ |
'\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', |
SPECIAL, /* 0x1d - LCtrl */ |
'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', |
'`', |
SPECIAL, /* 0x2a - LShift */ |
'\\', |
'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', |
SPECIAL, /* 0x36 - RShift */ |
'*', |
SPECIAL, /* 0x38 - LAlt */ |
'\b', /* 0x0e - Backspace */ |
'\t', /* 0x0f - Tab */ |
'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', |
'\n', /* 0x1e - Enter */ |
U_SPECIAL, /* 0x1d - Left Ctrl */ |
'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`', |
U_SPECIAL, /* 0x2a - Left Shift */ |
'\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', |
U_SPECIAL, /* 0x36 - Right Shift */ |
U_SPECIAL, /* 0x37 - Print Screen */ |
U_SPECIAL, /* 0x38 - Left Alt */ |
' ', |
SPECIAL, /* 0x3a - CapsLock */ |
SPECIAL, /* 0x3b - F1 */ |
SPECIAL, /* 0x3c - F2 */ |
SPECIAL, /* 0x3d - F3 */ |
SPECIAL, /* 0x3e - F4 */ |
SPECIAL, /* 0x3f - F5 */ |
SPECIAL, /* 0x40 - F6 */ |
SPECIAL, /* 0x41 - F7 */ |
SPECIAL, /* 0x42 - F8 */ |
SPECIAL, /* 0x43 - F9 */ |
SPECIAL, /* 0x44 - F10 */ |
SPECIAL, /* 0x45 - NumLock */ |
SPECIAL, /* 0x46 - ScrollLock */ |
'7', '8', '9', '-', |
'4', '5', '6', '+', |
'1', '2', '3', |
'0', '.', |
SPECIAL, /* 0x54 - Alt-SysRq */ |
SPECIAL, /* 0x55 - F11/F12/PF1/FN */ |
SPECIAL, /* 0x56 - unlabelled key next to LAlt */ |
SPECIAL, /* 0x57 - F11 */ |
SPECIAL, /* 0x58 - F12 */ |
SPECIAL, /* 0x59 */ |
SPECIAL, /* 0x5a */ |
SPECIAL, /* 0x5b */ |
SPECIAL, /* 0x5c */ |
SPECIAL, /* 0x5d */ |
SPECIAL, /* 0x5e */ |
SPECIAL, /* 0x5f */ |
SPECIAL, /* 0x60 */ |
SPECIAL, /* 0x61 */ |
SPECIAL, /* 0x62 */ |
SPECIAL, /* 0x63 */ |
SPECIAL, /* 0x64 */ |
SPECIAL, /* 0x65 */ |
SPECIAL, /* 0x66 */ |
SPECIAL, /* 0x67 */ |
SPECIAL, /* 0x68 */ |
SPECIAL, /* 0x69 */ |
SPECIAL, /* 0x6a */ |
SPECIAL, /* 0x6b */ |
SPECIAL, /* 0x6c */ |
SPECIAL, /* 0x6d */ |
SPECIAL, /* 0x6e */ |
SPECIAL, /* 0x6f */ |
SPECIAL, /* 0x70 */ |
SPECIAL, /* 0x71 */ |
SPECIAL, /* 0x72 */ |
SPECIAL, /* 0x73 */ |
SPECIAL, /* 0x74 */ |
SPECIAL, /* 0x75 */ |
SPECIAL, /* 0x76 */ |
SPECIAL, /* 0x77 */ |
SPECIAL, /* 0x78 */ |
SPECIAL, /* 0x79 */ |
SPECIAL, /* 0x7a */ |
SPECIAL, /* 0x7b */ |
SPECIAL, /* 0x7c */ |
SPECIAL, /* 0x7d */ |
SPECIAL, /* 0x7e */ |
SPECIAL, /* 0x7f */ |
U_SPECIAL, /* 0x3a - CapsLock */ |
U_SPECIAL, /* 0x3b - F1 */ |
U_SPECIAL, /* 0x3c - F2 */ |
U_SPECIAL, /* 0x3d - F3 */ |
U_SPECIAL, /* 0x3e - F4 */ |
U_SPECIAL, /* 0x3f - F5 */ |
U_SPECIAL, /* 0x40 - F6 */ |
U_SPECIAL, /* 0x41 - F7 */ |
U_SPECIAL, /* 0x42 - F8 */ |
U_SPECIAL, /* 0x43 - F9 */ |
U_SPECIAL, /* 0x44 - F10 */ |
U_SPECIAL, /* 0x45 - NumLock */ |
U_SPECIAL, /* 0x46 - ScrollLock */ |
U_HOME_ARROW, /* 0x47 - Home */ |
U_UP_ARROW, /* 0x48 - Up Arrow */ |
U_PAGE_UP, /* 0x49 - Page Up */ |
'-', |
U_LEFT_ARROW, /* 0x4b - Left Arrow */ |
'5', /* 0x4c - Numpad Center */ |
U_RIGHT_ARROW, /* 0x4d - Right Arrow */ |
'+', |
U_END_ARROW, /* 0x4f - End */ |
U_DOWN_ARROW, /* 0x50 - Down Arrow */ |
U_PAGE_DOWN, /* 0x51 - Page Down */ |
'0', /* 0x52 - Numpad Insert */ |
U_DELETE, /* 0x53 - Delete */ |
U_SPECIAL, /* 0x54 - Alt-SysRq */ |
U_SPECIAL, /* 0x55 - F11/F12/PF1/FN */ |
U_SPECIAL, /* 0x56 - unlabelled key next to LAlt */ |
U_SPECIAL, /* 0x57 - F11 */ |
U_SPECIAL, /* 0x58 - F12 */ |
U_SPECIAL, /* 0x59 */ |
U_SPECIAL, /* 0x5a */ |
U_SPECIAL, /* 0x5b */ |
U_SPECIAL, /* 0x5c */ |
U_SPECIAL, /* 0x5d */ |
U_SPECIAL, /* 0x5e */ |
U_SPECIAL, /* 0x5f */ |
U_SPECIAL, /* 0x60 */ |
U_SPECIAL, /* 0x61 */ |
U_SPECIAL, /* 0x62 */ |
U_SPECIAL, /* 0x63 */ |
U_SPECIAL, /* 0x64 */ |
U_SPECIAL, /* 0x65 */ |
U_SPECIAL, /* 0x66 */ |
U_SPECIAL, /* 0x67 */ |
U_SPECIAL, /* 0x68 */ |
U_SPECIAL, /* 0x69 */ |
U_SPECIAL, /* 0x6a */ |
U_SPECIAL, /* 0x6b */ |
U_SPECIAL, /* 0x6c */ |
U_SPECIAL, /* 0x6d */ |
U_SPECIAL, /* 0x6e */ |
U_SPECIAL, /* 0x6f */ |
U_SPECIAL, /* 0x70 */ |
U_SPECIAL, /* 0x71 */ |
U_SPECIAL, /* 0x72 */ |
U_SPECIAL, /* 0x73 */ |
U_SPECIAL, /* 0x74 */ |
U_SPECIAL, /* 0x75 */ |
U_SPECIAL, /* 0x76 */ |
U_SPECIAL, /* 0x77 */ |
U_SPECIAL, /* 0x78 */ |
U_SPECIAL, /* 0x79 */ |
U_SPECIAL, /* 0x7a */ |
U_SPECIAL, /* 0x7b */ |
U_SPECIAL, /* 0x7c */ |
U_SPECIAL, /* 0x7d */ |
U_SPECIAL, /* 0x7e */ |
U_SPECIAL /* 0x7f */ |
}; |
/** Secondary meaning of scancodes. */ |
char sc_secondary_map[] = { |
SPECIAL, /* 0x00 */ |
SPECIAL, /* 0x01 - Esc */ |
wchar_t sc_secondary_map[SCANCODES] = { |
U_NULL, /* 0x00 - undefined */ |
U_ESCAPE, /* 0x01 - Esc */ |
'!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', |
SPECIAL, /* 0x0e - Backspace */ |
'\t', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', '\n', |
SPECIAL, /* 0x1d - LCtrl */ |
'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"', |
'~', |
SPECIAL, /* 0x2a - LShift */ |
'|', |
'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', '?', |
SPECIAL, /* 0x36 - RShift */ |
'*', |
SPECIAL, /* 0x38 - LAlt */ |
'\b', /* 0x0e - Backspace */ |
'\t', /* 0x0f - Tab */ |
'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', |
'\n', /* 0x1e - Enter */ |
U_SPECIAL, /* 0x1d - Left Ctrl */ |
'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"', '~', |
U_SPECIAL, /* 0x2a - Left Shift */ |
'|', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', '?', |
U_SPECIAL, /* 0x36 - Right Shift */ |
U_SPECIAL, /* 0x37 - Print Screen */ |
U_SPECIAL, /* 0x38 - Left Alt */ |
' ', |
SPECIAL, /* 0x3a - CapsLock */ |
SPECIAL, /* 0x3b - F1 */ |
SPECIAL, /* 0x3c - F2 */ |
SPECIAL, /* 0x3d - F3 */ |
SPECIAL, /* 0x3e - F4 */ |
SPECIAL, /* 0x3f - F5 */ |
SPECIAL, /* 0x40 - F6 */ |
SPECIAL, /* 0x41 - F7 */ |
SPECIAL, /* 0x42 - F8 */ |
SPECIAL, /* 0x43 - F9 */ |
SPECIAL, /* 0x44 - F10 */ |
SPECIAL, /* 0x45 - NumLock */ |
SPECIAL, /* 0x46 - ScrollLock */ |
'7', '8', '9', '-', |
'4', '5', '6', '+', |
'1', '2', '3', |
'0', '.', |
SPECIAL, /* 0x54 - Alt-SysRq */ |
SPECIAL, /* 0x55 - F11/F12/PF1/FN */ |
SPECIAL, /* 0x56 - unlabelled key next to LAlt */ |
SPECIAL, /* 0x57 - F11 */ |
SPECIAL, /* 0x58 - F12 */ |
SPECIAL, /* 0x59 */ |
SPECIAL, /* 0x5a */ |
SPECIAL, /* 0x5b */ |
SPECIAL, /* 0x5c */ |
SPECIAL, /* 0x5d */ |
SPECIAL, /* 0x5e */ |
SPECIAL, /* 0x5f */ |
SPECIAL, /* 0x60 */ |
SPECIAL, /* 0x61 */ |
SPECIAL, /* 0x62 */ |
SPECIAL, /* 0x63 */ |
SPECIAL, /* 0x64 */ |
SPECIAL, /* 0x65 */ |
SPECIAL, /* 0x66 */ |
SPECIAL, /* 0x67 */ |
SPECIAL, /* 0x68 */ |
SPECIAL, /* 0x69 */ |
SPECIAL, /* 0x6a */ |
SPECIAL, /* 0x6b */ |
SPECIAL, /* 0x6c */ |
SPECIAL, /* 0x6d */ |
SPECIAL, /* 0x6e */ |
SPECIAL, /* 0x6f */ |
SPECIAL, /* 0x70 */ |
SPECIAL, /* 0x71 */ |
SPECIAL, /* 0x72 */ |
SPECIAL, /* 0x73 */ |
SPECIAL, /* 0x74 */ |
SPECIAL, /* 0x75 */ |
SPECIAL, /* 0x76 */ |
SPECIAL, /* 0x77 */ |
SPECIAL, /* 0x78 */ |
SPECIAL, /* 0x79 */ |
SPECIAL, /* 0x7a */ |
SPECIAL, /* 0x7b */ |
SPECIAL, /* 0x7c */ |
SPECIAL, /* 0x7d */ |
SPECIAL, /* 0x7e */ |
SPECIAL, /* 0x7f */ |
U_SPECIAL, /* 0x3a - CapsLock */ |
U_SPECIAL, /* 0x3b - F1 */ |
U_SPECIAL, /* 0x3c - F2 */ |
U_SPECIAL, /* 0x3d - F3 */ |
U_SPECIAL, /* 0x3e - F4 */ |
U_SPECIAL, /* 0x3f - F5 */ |
U_SPECIAL, /* 0x40 - F6 */ |
U_SPECIAL, /* 0x41 - F7 */ |
U_SPECIAL, /* 0x42 - F8 */ |
U_SPECIAL, /* 0x43 - F9 */ |
U_SPECIAL, /* 0x44 - F10 */ |
U_SPECIAL, /* 0x45 - NumLock */ |
U_SPECIAL, /* 0x46 - ScrollLock */ |
U_HOME_ARROW, /* 0x47 - Home */ |
U_UP_ARROW, /* 0x48 - Up Arrow */ |
U_PAGE_UP, /* 0x49 - Page Up */ |
'-', |
U_LEFT_ARROW, /* 0x4b - Left Arrow */ |
'5', /* 0x4c - Numpad Center */ |
U_RIGHT_ARROW, /* 0x4d - Right Arrow */ |
'+', |
U_END_ARROW, /* 0x4f - End */ |
U_DOWN_ARROW, /* 0x50 - Down Arrow */ |
U_PAGE_DOWN, /* 0x51 - Page Down */ |
'0', /* 0x52 - Numpad Insert */ |
U_DELETE, /* 0x53 - Delete */ |
U_SPECIAL, /* 0x54 - Alt-SysRq */ |
U_SPECIAL, /* 0x55 - F11/F12/PF1/FN */ |
U_SPECIAL, /* 0x56 - unlabelled key next to LAlt */ |
U_SPECIAL, /* 0x57 - F11 */ |
U_SPECIAL, /* 0x58 - F12 */ |
U_SPECIAL, /* 0x59 */ |
U_SPECIAL, /* 0x5a */ |
U_SPECIAL, /* 0x5b */ |
U_SPECIAL, /* 0x5c */ |
U_SPECIAL, /* 0x5d */ |
U_SPECIAL, /* 0x5e */ |
U_SPECIAL, /* 0x5f */ |
U_SPECIAL, /* 0x60 */ |
U_SPECIAL, /* 0x61 */ |
U_SPECIAL, /* 0x62 */ |
U_SPECIAL, /* 0x63 */ |
U_SPECIAL, /* 0x64 */ |
U_SPECIAL, /* 0x65 */ |
U_SPECIAL, /* 0x66 */ |
U_SPECIAL, /* 0x67 */ |
U_SPECIAL, /* 0x68 */ |
U_SPECIAL, /* 0x69 */ |
U_SPECIAL, /* 0x6a */ |
U_SPECIAL, /* 0x6b */ |
U_SPECIAL, /* 0x6c */ |
U_SPECIAL, /* 0x6d */ |
U_SPECIAL, /* 0x6e */ |
U_SPECIAL, /* 0x6f */ |
U_SPECIAL, /* 0x70 */ |
U_SPECIAL, /* 0x71 */ |
U_SPECIAL, /* 0x72 */ |
U_SPECIAL, /* 0x73 */ |
U_SPECIAL, /* 0x74 */ |
U_SPECIAL, /* 0x75 */ |
U_SPECIAL, /* 0x76 */ |
U_SPECIAL, /* 0x77 */ |
U_SPECIAL, /* 0x78 */ |
U_SPECIAL, /* 0x79 */ |
U_SPECIAL, /* 0x7a */ |
U_SPECIAL, /* 0x7b */ |
U_SPECIAL, /* 0x7c */ |
U_SPECIAL, /* 0x7d */ |
U_SPECIAL, /* 0x7e */ |
U_SPECIAL /* 0x7f */ |
}; |
/** @} |
/branches/dynload/kernel/genarch/src/kbrd/scanc_sun.c |
---|
26,48 → 26,50 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup genarch |
/** @addtogroup genarch |
* @{ |
*/ |
/** |
* @file |
* @brief Scan codes for Sun keyboards. |
* @brief Scan codes for Sun keyboards. |
*/ |
#include <genarch/kbrd/scanc.h> |
#include <typedefs.h> |
#include <string.h> |
/** Primary meaning of scancodes. */ |
char sc_primary_map[] = { |
[0x00] = SPECIAL, |
[0x01] = SPECIAL, |
[0x02] = SPECIAL, |
[0x03] = SPECIAL, |
[0x04] = SPECIAL, |
[0x05] = SPECIAL, /* F1 */ |
[0x06] = SPECIAL, /* F2 */ |
[0x07] = SPECIAL, /* F10 */ |
[0x08] = SPECIAL, /* F3 */ |
[0x09] = SPECIAL, /* F11 */ |
[0x0a] = SPECIAL, /* F4 */ |
[0x0b] = SPECIAL, /* F12 */ |
[0x0c] = SPECIAL, /* F5 */ |
[0x0d] = SPECIAL, /* RAlt */ |
[0x0e] = SPECIAL, /* F6 */ |
[0x0f] = SPECIAL, |
[0x10] = SPECIAL, /* F7 */ |
[0x11] = SPECIAL, /* F8 */ |
[0x12] = SPECIAL, /* F9 */ |
[0x13] = SPECIAL, /* LAlt */ |
[0x14] = SPECIAL, /* Up Arrow */ |
[0x15] = SPECIAL, /* Pause */ |
[0x16] = SPECIAL, |
[0x17] = SPECIAL, /* Scroll Lock */ |
[0x18] = SPECIAL, /* Left Arrow */ |
[0x19] = SPECIAL, |
[0x1a] = SPECIAL, |
[0x1b] = SPECIAL, /* Down Arrow */ |
[0x1c] = SPECIAL, /* Right Arrow */ |
[0x1d] = SPECIAL, /* Esc */ |
wchar_t sc_primary_map[SCANCODES] = { |
[0x00] = U_SPECIAL, |
[0x01] = U_SPECIAL, |
[0x02] = U_SPECIAL, |
[0x03] = U_SPECIAL, |
[0x04] = U_SPECIAL, |
[0x05] = U_SPECIAL, /* F1 */ |
[0x06] = U_SPECIAL, /* F2 */ |
[0x07] = U_SPECIAL, /* F10 */ |
[0x08] = U_SPECIAL, /* F3 */ |
[0x09] = U_SPECIAL, /* F11 */ |
[0x0a] = U_SPECIAL, /* F4 */ |
[0x0b] = U_SPECIAL, /* F12 */ |
[0x0c] = U_SPECIAL, /* F5 */ |
[0x0d] = U_SPECIAL, /* Right Alt */ |
[0x0e] = U_SPECIAL, /* F6 */ |
[0x0f] = U_SPECIAL, |
[0x10] = U_SPECIAL, /* F7 */ |
[0x11] = U_SPECIAL, /* F8 */ |
[0x12] = U_SPECIAL, /* F9 */ |
[0x13] = U_SPECIAL, /* Left Alt */ |
[0x14] = U_UP_ARROW, /* Up Arrow */ |
[0x15] = U_SPECIAL, /* Pause */ |
[0x16] = U_SPECIAL, |
[0x17] = U_SPECIAL, /* Scroll Lock */ |
[0x18] = U_LEFT_ARROW, /* Left Arrow */ |
[0x19] = U_SPECIAL, |
[0x1a] = U_SPECIAL, |
[0x1b] = U_DOWN_ARROW, /* Down Arrow */ |
[0x1c] = U_RIGHT_ARROW, /* Right Arrow */ |
[0x1d] = U_ESCAPE, /* Esc */ |
[0x1e] = '1', |
[0x1f] = '2', |
[0x20] = '3', |
81,17 → 83,17 |
[0x28] = '-', |
[0x29] = '=', |
[0x2a] = '`', |
[0x2b] = '\b', /* Backspace */ |
[0x2c] = SPECIAL, /* Insert */ |
[0x2d] = SPECIAL, |
[0x2e] = '/', /* numeric keypad */ |
[0x2f] = '*', /* numeric keypad */ |
[0x30] = SPECIAL, |
[0x31] = SPECIAL, |
[0x32] = '.', /* numeric keypad */ |
[0x33] = SPECIAL, |
[0x34] = SPECIAL, /* Home */ |
[0x35] = '\t', /* Tab */ |
[0x2b] = '\b', /* Backspace */ |
[0x2c] = U_SPECIAL, /* Insert */ |
[0x2d] = U_SPECIAL, |
[0x2e] = '/', /* Numpad / */ |
[0x2f] = '*', /* Numpad * */ |
[0x30] = U_SPECIAL, |
[0x31] = U_SPECIAL, |
[0x32] = '.', /* Numpad . */ |
[0x33] = U_SPECIAL, |
[0x34] = U_HOME_ARROW, /* Home */ |
[0x35] = '\t', /* Tab */ |
[0x36] = 'q', |
[0x37] = 'w', |
[0x38] = 'e', |
104,17 → 106,17 |
[0x3f] = 'p', |
[0x40] = '[', |
[0x41] = ']', |
[0x42] = SPECIAL, /* Del */ |
[0x43] = SPECIAL, |
[0x44] = '7', /* numeric keypad */ |
[0x45] = '8', /* numeric keypad */ |
[0x46] = '9', /* numeric keypad */ |
[0x47] = '-', /* numeric keypad */ |
[0x48] = SPECIAL, |
[0x49] = SPECIAL, |
[0x4a] = SPECIAL, /* End */ |
[0x4b] = SPECIAL, |
[0x4c] = SPECIAL, /* Control */ |
[0x42] = U_DELETE, /* Delete */ |
[0x43] = U_SPECIAL, |
[0x44] = '7', /* Numpad 7 */ |
[0x45] = '8', /* Numpad 8 */ |
[0x46] = '9', /* Numpad 9 */ |
[0x47] = '-', /* Numpad - */ |
[0x48] = U_SPECIAL, |
[0x49] = U_SPECIAL, |
[0x4a] = U_END_ARROW, /* End */ |
[0x4b] = U_SPECIAL, |
[0x4c] = U_SPECIAL, /* Control */ |
[0x4d] = 'a', |
[0x4e] = 's', |
[0x4f] = 'd', |
127,17 → 129,17 |
[0x56] = ';', |
[0x57] = '\'', |
[0x58] = '\\', |
[0x59] = '\n', /* Enter */ |
[0x5a] = '\n', /* Enter on numeric keypad */ |
[0x5b] = '4', /* numeric keypad */ |
[0x5c] = '5', /* numeric keypad */ |
[0x5d] = '6', /* numeric keypad */ |
[0x5e] = '0', /* numeric keypad */ |
[0x5f] = SPECIAL, |
[0x60] = SPECIAL, /* Page Up */ |
[0x61] = SPECIAL, |
[0x62] = SPECIAL, /* Num Lock */ |
[0x63] = SPECIAL, /* LShift */ |
[0x59] = '\n', /* Enter */ |
[0x5a] = '\n', /* Numpad Enter */ |
[0x5b] = '4', /* Numpad 4 */ |
[0x5c] = '5', /* Numpad 5 */ |
[0x5d] = '6', /* Numpad 6 */ |
[0x5e] = '0', /* Numpad 0 */ |
[0x5f] = U_SPECIAL, |
[0x60] = U_PAGE_UP, /* Page Up */ |
[0x61] = U_SPECIAL, |
[0x62] = U_SPECIAL, /* NumLock */ |
[0x63] = U_SPECIAL, /* Left Shift */ |
[0x64] = 'z', |
[0x65] = 'x', |
[0x66] = 'c', |
148,58 → 150,58 |
[0x6b] = ',', |
[0x6c] = '.', |
[0x6d] = '/', |
[0x6e] = SPECIAL, /* RShift */ |
[0x6f] = SPECIAL, |
[0x70] = '1', /* numeric keypad */ |
[0x71] = '2', /* numeric keypad */ |
[0x72] = '3', /* numeric keypad */ |
[0x73] = SPECIAL, |
[0x74] = SPECIAL, |
[0x75] = SPECIAL, |
[0x76] = SPECIAL, |
[0x77] = SPECIAL, /* Caps Lock */ |
[0x78] = SPECIAL, |
[0x6e] = U_SPECIAL, /* Right Shift */ |
[0x6f] = U_SPECIAL, |
[0x70] = '1', /* Numpad 1 */ |
[0x71] = '2', /* Numpad 2 */ |
[0x72] = '3', /* Numpad 3 */ |
[0x73] = U_SPECIAL, |
[0x74] = U_SPECIAL, |
[0x75] = U_SPECIAL, |
[0x76] = U_SPECIAL, |
[0x77] = U_SPECIAL, /* CapsLock */ |
[0x78] = U_SPECIAL, |
[0x79] = ' ', |
[0x7a] = SPECIAL, |
[0x7b] = SPECIAL, /* Page Down */ |
[0x7c] = SPECIAL, |
[0x7d] = '+', /* numeric key pad */ |
[0x7e] = SPECIAL, |
[0x7f] = SPECIAL |
[0x7a] = U_SPECIAL, |
[0x7b] = U_PAGE_DOWN, /* Page Down */ |
[0x7c] = U_SPECIAL, |
[0x7d] = '+', /* Numpad + */ |
[0x7e] = U_SPECIAL, |
[0x7f] = U_SPECIAL |
}; |
/** Secondary meaning of scancodes. */ |
char sc_secondary_map[] = { |
[0x00] = SPECIAL, |
[0x01] = SPECIAL, |
[0x02] = SPECIAL, |
[0x03] = SPECIAL, |
[0x04] = SPECIAL, |
[0x05] = SPECIAL, /* F1 */ |
[0x06] = SPECIAL, /* F2 */ |
[0x07] = SPECIAL, /* F10 */ |
[0x08] = SPECIAL, /* F3 */ |
[0x09] = SPECIAL, /* F11 */ |
[0x0a] = SPECIAL, /* F4 */ |
[0x0b] = SPECIAL, /* F12 */ |
[0x0c] = SPECIAL, /* F5 */ |
[0x0d] = SPECIAL, /* RAlt */ |
[0x0e] = SPECIAL, /* F6 */ |
[0x0f] = SPECIAL, |
[0x10] = SPECIAL, /* F7 */ |
[0x11] = SPECIAL, /* F8 */ |
[0x12] = SPECIAL, /* F9 */ |
[0x13] = SPECIAL, /* LAlt */ |
[0x14] = SPECIAL, /* Up Arrow */ |
[0x15] = SPECIAL, /* Pause */ |
[0x16] = SPECIAL, |
[0x17] = SPECIAL, /* Scroll Lock */ |
[0x18] = SPECIAL, /* Left Arrow */ |
[0x19] = SPECIAL, |
[0x1a] = SPECIAL, |
[0x1b] = SPECIAL, /* Down Arrow */ |
[0x1c] = SPECIAL, /* Right Arrow */ |
[0x1d] = SPECIAL, /* Esc */ |
wchar_t sc_secondary_map[SCANCODES] = { |
[0x00] = U_SPECIAL, |
[0x01] = U_SPECIAL, |
[0x02] = U_SPECIAL, |
[0x03] = U_SPECIAL, |
[0x04] = U_SPECIAL, |
[0x05] = U_SPECIAL, /* F1 */ |
[0x06] = U_SPECIAL, /* F2 */ |
[0x07] = U_SPECIAL, /* F10 */ |
[0x08] = U_SPECIAL, /* F3 */ |
[0x09] = U_SPECIAL, /* F11 */ |
[0x0a] = U_SPECIAL, /* F4 */ |
[0x0b] = U_SPECIAL, /* F12 */ |
[0x0c] = U_SPECIAL, /* F5 */ |
[0x0d] = U_SPECIAL, /* Right Alt */ |
[0x0e] = U_SPECIAL, /* F6 */ |
[0x0f] = U_SPECIAL, |
[0x10] = U_SPECIAL, /* F7 */ |
[0x11] = U_SPECIAL, /* F8 */ |
[0x12] = U_SPECIAL, /* F9 */ |
[0x13] = U_SPECIAL, /* Left Alt */ |
[0x14] = U_UP_ARROW, /* Up Arrow */ |
[0x15] = U_SPECIAL, /* Pause */ |
[0x16] = U_SPECIAL, |
[0x17] = U_SPECIAL, /* Scroll Lock */ |
[0x18] = U_LEFT_ARROW, /* Left Arrow */ |
[0x19] = U_SPECIAL, |
[0x1a] = U_SPECIAL, |
[0x1b] = U_DOWN_ARROW, /* Down Arrow */ |
[0x1c] = U_RIGHT_ARROW, /* Right Arrow */ |
[0x1d] = U_ESCAPE, /* Esc */ |
[0x1e] = '!', |
[0x1f] = '@', |
[0x20] = '#', |
213,17 → 215,17 |
[0x28] = '_', |
[0x29] = '+', |
[0x2a] = '~', |
[0x2b] = SPECIAL, /* Backspace */ |
[0x2c] = SPECIAL, /* Insert */ |
[0x2d] = SPECIAL, |
[0x2e] = '/', /* numeric keypad */ |
[0x2f] = '*', /* numeric keypad */ |
[0x30] = SPECIAL, |
[0x31] = SPECIAL, |
[0x32] = '.', /* numeric keypad */ |
[0x33] = SPECIAL, |
[0x34] = SPECIAL, /* Home */ |
[0x35] = SPECIAL, /* Tab */ |
[0x2b] = '\b', /* Backspace */ |
[0x2c] = U_SPECIAL, /* Insert */ |
[0x2d] = U_SPECIAL, |
[0x2e] = '/', /* Numpad / */ |
[0x2f] = '*', /* Numpad * */ |
[0x30] = U_SPECIAL, |
[0x31] = U_SPECIAL, |
[0x32] = '.', /* Numpad . */ |
[0x33] = U_SPECIAL, |
[0x34] = U_HOME_ARROW, /* Home */ |
[0x35] = '\t', /* Tab */ |
[0x36] = 'Q', |
[0x37] = 'W', |
[0x38] = 'E', |
236,17 → 238,17 |
[0x3f] = 'P', |
[0x40] = '{', |
[0x41] = '}', |
[0x42] = SPECIAL, /* Del */ |
[0x43] = SPECIAL, |
[0x44] = '7', /* numeric keypad */ |
[0x45] = '8', /* numeric keypad */ |
[0x46] = '9', /* numeric keypad */ |
[0x47] = '-', /* numeric keypad */ |
[0x48] = SPECIAL, |
[0x49] = SPECIAL, |
[0x4a] = SPECIAL, /* End */ |
[0x4b] = SPECIAL, |
[0x4c] = SPECIAL, /* Control */ |
[0x42] = U_DELETE, /* Delete */ |
[0x43] = U_SPECIAL, |
[0x44] = '7', /* Numpad 7 */ |
[0x45] = '8', /* Numpad 8 */ |
[0x46] = '9', /* Numpad 9 */ |
[0x47] = '-', /* Numpad - */ |
[0x48] = U_SPECIAL, |
[0x49] = U_SPECIAL, |
[0x4a] = U_END_ARROW, /* End */ |
[0x4b] = U_SPECIAL, |
[0x4c] = U_SPECIAL, /* Control */ |
[0x4d] = 'A', |
[0x4e] = 'S', |
[0x4f] = 'D', |
259,17 → 261,17 |
[0x56] = ':', |
[0x57] = '"', |
[0x58] = '|', |
[0x59] = SPECIAL, /* Enter */ |
[0x5a] = SPECIAL, /* Enter on numeric keypad */ |
[0x5b] = '4', /* numeric keypad */ |
[0x5c] = '5', /* numeric keypad */ |
[0x5d] = '6', /* numeric keypad */ |
[0x5e] = '0', /* numeric keypad */ |
[0x5f] = SPECIAL, |
[0x60] = SPECIAL, /* Page Up */ |
[0x61] = SPECIAL, |
[0x62] = SPECIAL, /* Num Lock */ |
[0x63] = SPECIAL, /* LShift */ |
[0x59] = '\n', /* Enter */ |
[0x5a] = '\n', /* Numpad Enter */ |
[0x5b] = '4', /* Numpad 4 */ |
[0x5c] = '5', /* Numpad 5 */ |
[0x5d] = '6', /* Numpad 6 */ |
[0x5e] = '0', /* Numpad 0 */ |
[0x5f] = U_SPECIAL, |
[0x60] = U_PAGE_UP, /* Page Up */ |
[0x61] = U_SPECIAL, |
[0x62] = U_SPECIAL, /* NumLock */ |
[0x63] = U_SPECIAL, /* Left Shift */ |
[0x64] = 'Z', |
[0x65] = 'X', |
[0x66] = 'C', |
280,24 → 282,24 |
[0x6b] = '<', |
[0x6c] = '>', |
[0x6d] = '?', |
[0x6e] = SPECIAL, /* RShift */ |
[0x6f] = SPECIAL, |
[0x70] = '1', /* numeric keypad */ |
[0x71] = '2', /* numeric keypad */ |
[0x72] = '3', /* numeric keypad */ |
[0x73] = SPECIAL, |
[0x74] = SPECIAL, |
[0x75] = SPECIAL, |
[0x76] = SPECIAL, |
[0x77] = SPECIAL, /* Caps Lock */ |
[0x78] = SPECIAL, |
[0x6e] = U_SPECIAL, /* Right Shift */ |
[0x6f] = U_SPECIAL, |
[0x70] = '1', /* Numpad 1 */ |
[0x71] = '2', /* Numpad 2 */ |
[0x72] = '3', /* Numpad 3 */ |
[0x73] = U_SPECIAL, |
[0x74] = U_SPECIAL, |
[0x75] = U_SPECIAL, |
[0x76] = U_SPECIAL, |
[0x77] = U_SPECIAL, /* CapsLock */ |
[0x78] = U_SPECIAL, |
[0x79] = ' ', |
[0x7a] = SPECIAL, |
[0x7b] = SPECIAL, /* Page Down */ |
[0x7c] = SPECIAL, |
[0x7d] = '+', /* numeric key pad */ |
[0x7e] = SPECIAL, |
[0x7f] = SPECIAL |
[0x7a] = U_SPECIAL, |
[0x7b] = U_PAGE_DOWN, /* Page Down */ |
[0x7c] = U_SPECIAL, |
[0x7d] = '+', /* Numpad + */ |
[0x7e] = U_SPECIAL, |
[0x7f] = U_SPECIAL |
}; |
/** @} |
/branches/dynload/kernel/genarch/src/fb/fb.c |
---|
47,6 → 47,7 |
#include <config.h> |
#include <bitops.h> |
#include <print.h> |
#include <string.h> |
#include <ddi/ddi.h> |
#include <arch/types.h> |
79,8 → 80,6 |
#define FG_COLOR 0xffff00 |
#define INV_COLOR 0xaaaaaa |
#define CURSOR 0x2588 |
#define RED(x, bits) ((x >> (8 + 8 + 8 - bits)) & ((1 << bits) - 1)) |
#define GREEN(x, bits) ((x >> (8 + 8 - bits)) & ((1 << bits) - 1)) |
#define BLUE(x, bits) ((x >> (8 - bits)) & ((1 << bits) - 1)) |
200,7 → 199,7 |
/** Draw character at given position |
* |
*/ |
static void glyph_draw(uint16_t glyph, unsigned int col, unsigned int row, bool silent) |
static void glyph_draw(uint16_t glyph, unsigned int col, unsigned int row, bool silent, bool overlay) |
{ |
unsigned int x = COL2X(col); |
unsigned int y = ROW2Y(row); |
209,7 → 208,8 |
if (y >= ytrim) |
logo_hide(silent); |
backbuf[BB_POS(col, row)] = glyph; |
if (!overlay) |
backbuf[BB_POS(col, row)] = glyph; |
if (!silent) { |
for (yd = 0; yd < FONT_SCANLINES; yd++) |
269,13 → 269,19 |
static void cursor_put(bool silent) |
{ |
glyph_draw(fb_font_glyph(CURSOR), position % cols, position / cols, silent); |
unsigned int col = position % cols; |
unsigned int row = position / cols; |
glyph_draw(fb_font_glyph(U_CURSOR), col, row, silent, true); |
} |
static void cursor_remove(bool silent) |
{ |
glyph_draw(fb_font_glyph(0), position % cols, position / cols, silent); |
unsigned int col = position % cols; |
unsigned int row = position / cols; |
glyph_draw(backbuf[BB_POS(col, row)], col, row, silent, true); |
} |
307,13 → 313,13 |
cursor_remove(silent); |
do { |
glyph_draw(fb_font_glyph(' '), position % cols, |
position / cols, silent); |
position / cols, silent, false); |
position++; |
} while ((position % 8) && (position < cols * rows)); |
break; |
default: |
glyph_draw(fb_font_glyph(ch), position % cols, |
position / cols, silent); |
position / cols, silent, false); |
position++; |
} |
/branches/dynload/kernel/genarch/src/ofw/ebus.c |
---|
127,7 → 127,7 |
if (!controller) |
return false; |
if (strcmp(ofw_tree_node_name(controller), "pci") != 0) { |
if (str_cmp(ofw_tree_node_name(controller), "pci") != 0) { |
/* |
* This is not a PCI node. |
*/ |
/branches/dynload/kernel/genarch/src/ofw/fhc.c |
---|
66,7 → 66,7 |
*pa = addr; |
return true; |
} |
if (strcmp(ofw_tree_node_name(node->parent), "central") != 0) |
if (str_cmp(ofw_tree_node_name(node->parent), "central") != 0) |
panic("Unexpected parent node: %s.", ofw_tree_node_name(node->parent)); |
ofw_central_reg_t central_reg; |
/branches/dynload/kernel/genarch/src/ofw/ofw_tree.c |
---|
66,7 → 66,7 |
unsigned int i; |
for (i = 0; i < node->properties; i++) { |
if (strcmp(node->property[i].name, name) == 0) |
if (str_cmp(node->property[i].name, name) == 0) |
return &node->property[i]; |
} |
109,7 → 109,7 |
* Try to find the disambigued name. |
*/ |
for (cur = node->child; cur; cur = cur->peer) { |
if (strcmp(cur->da_name, name) == 0) |
if (str_cmp(cur->da_name, name) == 0) |
return cur; |
} |
121,7 → 121,7 |
* are not always fully-qualified. |
*/ |
for (cur = node->child; cur; cur = cur->peer) { |
if (strcmp(ofw_tree_node_name(cur), name) == 0) |
if (str_cmp(ofw_tree_node_name(cur), name) == 0) |
return cur; |
} |
146,7 → 146,7 |
prop = ofw_tree_getprop(cur, "device_type"); |
if (!prop || !prop->value) |
continue; |
if (strcmp(prop->value, name) == 0) |
if (str_cmp(prop->value, name) == 0) |
return cur; |
} |
203,7 → 203,7 |
prop = ofw_tree_getprop(cur, "device_type"); |
if (!prop || !prop->value) |
continue; |
if (strcmp(prop->value, name) == 0) |
if (str_cmp(prop->value, name) == 0) |
return cur; |
} |
229,7 → 229,7 |
prop = ofw_tree_getprop(cur, "name"); |
if (!prop || !prop->value) |
continue; |
if (strcmp(prop->value, name) == 0) |
if (str_cmp(prop->value, name) == 0) |
return cur; |
} |
252,14 → 252,15 |
if (path[0] != '/') |
return NULL; |
for (i = 1; i < strlen(path) && node; i = j + 1) { |
for (j = i; j < strlen(path) && path[j] != '/'; j++) |
; |
if (i == j) /* skip extra slashes */ |
for (i = 1; (i < str_size(path)) && (node); i = j + 1) { |
for (j = i; (j < str_size(path)) && (path[j] != '/'); j++); |
/* Skip extra slashes */ |
if (i == j) |
continue; |
memcpy(buf, &path[i], j - i); |
buf[j - i] = '\0'; |
buf[j - i] = 0; |
node = ofw_tree_find_child(node, buf); |
} |
/branches/dynload/kernel/genarch/src/ofw/pci.c |
---|
58,7 → 58,7 |
prop = ofw_tree_getprop(node, "ranges"); |
if (!prop) { |
if (strcmp(ofw_tree_node_name(node->parent), "pci") == 0) |
if (str_cmp(ofw_tree_node_name(node->parent), "pci") == 0) |
return ofw_pci_apply_ranges(node->parent, reg, pa); |
return false; |
} |
/branches/dynload/kernel/genarch/src/drivers/ns16550/ns16550.c |
---|
43,10 → 43,6 |
#define LSR_DATA_READY 0x01 |
static indev_operations_t kbrdin_ops = { |
.poll = NULL |
}; |
static irq_ownership_t ns16550_claim(irq_t *irq) |
{ |
ns16550_instance_t *instance = irq->instance; |
64,11 → 60,18 |
ns16550_t *dev = instance->ns16550; |
if (pio_read_8(&dev->lsr) & LSR_DATA_READY) { |
uint8_t x = pio_read_8(&dev->rbr); |
indev_push_character(&instance->kbrdin, x); |
uint8_t data = pio_read_8(&dev->rbr); |
indev_push_character(instance->kbrdin, data); |
} |
} |
/**< Clear input buffer. */ |
static void ns16550_clear_buffer(ns16550_t *dev) |
{ |
while ((pio_read_8(&dev->lsr) & LSR_DATA_READY)) |
(void) pio_read_8(&dev->rbr); |
} |
/** Initialize ns16550. |
* |
* @param dev Addrress of the beginning of the device in I/O space. |
77,38 → 80,43 |
* @param cir Clear interrupt function. |
* @param cir_arg First argument to cir. |
* |
* @return Keyboard device pointer or NULL on failure. |
* @return Keyboard instance or NULL on failure. |
* |
*/ |
indev_t *ns16550_init(ns16550_t *dev, inr_t inr, cir_t cir, void *cir_arg) |
ns16550_instance_t *ns16550_init(ns16550_t *dev, inr_t inr, cir_t cir, void *cir_arg) |
{ |
ns16550_instance_t *instance |
= malloc(sizeof(ns16550_instance_t), FRAME_ATOMIC); |
if (!instance) |
return NULL; |
if (instance) { |
instance->ns16550 = dev; |
instance->kbrdin = NULL; |
irq_initialize(&instance->irq); |
instance->irq.devno = device_assign_devno(); |
instance->irq.inr = inr; |
instance->irq.claim = ns16550_claim; |
instance->irq.handler = ns16550_irq_handler; |
instance->irq.instance = instance; |
instance->irq.cir = cir; |
instance->irq.cir_arg = cir_arg; |
} |
indev_initialize("ns16550", &instance->kbrdin, &kbrdin_ops); |
return instance; |
} |
void ns16550_wire(ns16550_instance_t *instance, indev_t *kbrdin) |
{ |
ASSERT(instance); |
ASSERT(kbrdin); |
instance->ns16550 = dev; |
irq_initialize(&instance->irq); |
instance->irq.devno = device_assign_devno(); |
instance->irq.inr = inr; |
instance->irq.claim = ns16550_claim; |
instance->irq.handler = ns16550_irq_handler; |
instance->irq.instance = instance; |
instance->irq.cir = cir; |
instance->irq.cir_arg = cir_arg; |
instance->kbrdin = kbrdin; |
irq_register(&instance->irq); |
while ((pio_read_8(&dev->lsr) & LSR_DATA_READY)) |
(void) pio_read_8(&dev->rbr); |
ns16550_clear_buffer(instance->ns16550); |
/* Enable interrupts */ |
pio_write_8(&dev->ier, IER_ERBFI); |
pio_write_8(&dev->mcr, MCR_OUT2); |
return &instance->kbrdin; |
pio_write_8(&instance->ns16550->ier, IER_ERBFI); |
pio_write_8(&instance->ns16550->mcr, MCR_OUT2); |
} |
/** @} |
/branches/dynload/kernel/genarch/src/drivers/dsrln/dsrlnin.c |
---|
40,10 → 40,6 |
#include <arch/asm.h> |
#include <ddi/device.h> |
static indev_operations_t kbrdin_ops = { |
.poll = NULL |
}; |
static irq_ownership_t dsrlnin_claim(irq_t *irq) |
{ |
return IRQ_ACCEPT; |
54,29 → 50,35 |
dsrlnin_instance_t *instance = irq->instance; |
dsrlnin_t *dev = instance->dsrlnin; |
indev_push_character(&instance->kbrdin, pio_read_8(&dev->data)); |
indev_push_character(instance->srlnin, pio_read_8(&dev->data)); |
} |
indev_t *dsrlnin_init(dsrlnin_t *dev, inr_t inr) |
dsrlnin_instance_t *dsrlnin_init(dsrlnin_t *dev, inr_t inr) |
{ |
dsrlnin_instance_t *instance |
= malloc(sizeof(dsrlnin_instance_t), FRAME_ATOMIC); |
if (!instance) |
return NULL; |
if (instance) { |
instance->dsrlnin = dev; |
instance->srlnin = NULL; |
irq_initialize(&instance->irq); |
instance->irq.devno = device_assign_devno(); |
instance->irq.inr = inr; |
instance->irq.claim = dsrlnin_claim; |
instance->irq.handler = dsrlnin_irq_handler; |
instance->irq.instance = instance; |
} |
indev_initialize("dsrlnin", &instance->kbrdin, &kbrdin_ops); |
return instance; |
} |
void dsrlnin_wire(dsrlnin_instance_t *instance, indev_t *srlnin) |
{ |
ASSERT(instance); |
ASSERT(srlnin); |
instance->dsrlnin = dev; |
irq_initialize(&instance->irq); |
instance->irq.devno = device_assign_devno(); |
instance->irq.inr = inr; |
instance->irq.claim = dsrlnin_claim; |
instance->irq.handler = dsrlnin_irq_handler; |
instance->irq.instance = instance; |
instance->srlnin = srlnin; |
irq_register(&instance->irq); |
return &instance->kbrdin; |
} |
/** @} |
/branches/dynload/kernel/genarch/src/drivers/dsrln/dsrlnout.c |
---|
40,13 → 40,18 |
#include <arch/asm.h> |
#include <console/console.h> |
#include <sysinfo/sysinfo.h> |
#include <string.h> |
static ioport8_t *dsrlnout_base; |
static void dsrlnout_putchar(outdev_t *dev __attribute__((unused)), const char ch, bool silent) |
static void dsrlnout_putchar(outdev_t *dev __attribute__((unused)), const wchar_t ch, bool silent) |
{ |
if (!silent) |
pio_write_8(dsrlnout_base, ch); |
if (!silent) { |
if (ascii_check(ch)) |
pio_write_8(dsrlnout_base, ch); |
else |
pio_write_8(dsrlnout_base, U_SPECIAL); |
} |
} |
static outdev_t dsrlnout_console; |
/branches/dynload/kernel/genarch/src/drivers/i8042/i8042.c |
---|
34,6 → 34,7 |
* @brief i8042 processor driver |
* |
* It takes care of the i8042 serial communication. |
* |
*/ |
#include <genarch/drivers/i8042/i8042.h> |
43,12 → 44,9 |
#include <mm/slab.h> |
#include <ddi/device.h> |
static indev_operations_t kbrdin_ops = { |
.poll = NULL |
}; |
#define i8042_SET_COMMAND 0x60 |
#define i8042_COMMAND 0x69 |
#define i8042_CPU_RESET 0xfe |
#define i8042_BUFFER_FULL_MASK 0x01 |
#define i8042_WAIT_MASK 0x02 |
72,37 → 70,57 |
if (((status = pio_read_8(&dev->status)) & i8042_BUFFER_FULL_MASK)) { |
uint8_t data = pio_read_8(&dev->data); |
indev_push_character(&instance->kbrdin, data); |
indev_push_character(instance->kbrdin, data); |
} |
} |
/**< Clear input buffer. */ |
static void i8042_clear_buffer(i8042_t *dev) |
{ |
while (pio_read_8(&dev->status) & i8042_BUFFER_FULL_MASK) |
(void) pio_read_8(&dev->data); |
} |
/** Initialize i8042. */ |
indev_t *i8042_init(i8042_t *dev, inr_t inr) |
i8042_instance_t *i8042_init(i8042_t *dev, inr_t inr) |
{ |
i8042_instance_t *instance |
= malloc(sizeof(i8042_instance_t), FRAME_ATOMIC); |
if (!instance) |
return NULL; |
if (instance) { |
instance->i8042 = dev; |
instance->kbrdin = NULL; |
irq_initialize(&instance->irq); |
instance->irq.devno = device_assign_devno(); |
instance->irq.inr = inr; |
instance->irq.claim = i8042_claim; |
instance->irq.handler = i8042_irq_handler; |
instance->irq.instance = instance; |
} |
indev_initialize("i8042", &instance->kbrdin, &kbrdin_ops); |
return instance; |
} |
void i8042_wire(i8042_instance_t *instance, indev_t *kbrdin) |
{ |
ASSERT(instance); |
ASSERT(kbrdin); |
instance->i8042 = dev; |
irq_initialize(&instance->irq); |
instance->irq.devno = device_assign_devno(); |
instance->irq.inr = inr; |
instance->irq.claim = i8042_claim; |
instance->irq.handler = i8042_irq_handler; |
instance->irq.instance = instance; |
instance->kbrdin = kbrdin; |
irq_register(&instance->irq); |
i8042_clear_buffer(instance->i8042); |
} |
/* Reset CPU by pulsing pin 0 */ |
void i8042_cpu_reset(i8042_t *dev) |
{ |
interrupts_disable(); |
/* |
* Clear input buffer. |
*/ |
while (pio_read_8(&dev->status) & i8042_BUFFER_FULL_MASK) |
(void) pio_read_8(&dev->data); |
i8042_clear_buffer(dev); |
return &instance->kbrdin; |
/* Reset CPU */ |
pio_write_8(&dev->status, i8042_CPU_RESET); |
} |
/** @} |
/branches/dynload/kernel/genarch/src/drivers/z8530/z8530.c |
---|
41,10 → 41,6 |
#include <mm/slab.h> |
#include <ddi/device.h> |
static indev_operations_t kbrdin_ops = { |
.poll = NULL |
}; |
static inline void z8530_write(ioport8_t *ctl, uint8_t reg, uint8_t val) |
{ |
/* |
82,51 → 78,58 |
z8530_t *dev = instance->z8530; |
if (z8530_read(&dev->ctl_a, RR0) & RR0_RCA) { |
uint8_t x = z8530_read(&dev->ctl_a, RR8); |
indev_push_character(&instance->kbrdin, x); |
uint8_t data = z8530_read(&dev->ctl_a, RR8); |
indev_push_character(instance->kbrdin, data); |
} |
} |
/** Initialize z8530. */ |
indev_t *z8530_init(z8530_t *dev, inr_t inr, cir_t cir, void *cir_arg) |
z8530_instance_t *z8530_init(z8530_t *dev, inr_t inr, cir_t cir, void *cir_arg) |
{ |
z8530_instance_t *instance |
= malloc(sizeof(z8530_instance_t), FRAME_ATOMIC); |
if (!instance) |
return false; |
if (instance) { |
instance->z8530 = dev; |
instance->kbrdin = NULL; |
irq_initialize(&instance->irq); |
instance->irq.devno = device_assign_devno(); |
instance->irq.inr = inr; |
instance->irq.claim = z8530_claim; |
instance->irq.handler = z8530_irq_handler; |
instance->irq.instance = instance; |
instance->irq.cir = cir; |
instance->irq.cir_arg = cir_arg; |
} |
indev_initialize("z8530", &instance->kbrdin, &kbrdin_ops); |
return instance; |
} |
void z8530_wire(z8530_instance_t *instance, indev_t *kbrdin) |
{ |
ASSERT(instance); |
ASSERT(kbrdin); |
instance->z8530 = dev; |
instance->kbrdin = kbrdin; |
irq_initialize(&instance->irq); |
instance->irq.devno = device_assign_devno(); |
instance->irq.inr = inr; |
instance->irq.claim = z8530_claim; |
instance->irq.handler = z8530_irq_handler; |
instance->irq.instance = instance; |
instance->irq.cir = cir; |
instance->irq.cir_arg = cir_arg; |
irq_register(&instance->irq); |
(void) z8530_read(&dev->ctl_a, RR8); |
(void) z8530_read(&instance->z8530->ctl_a, RR8); |
/* |
* Clear any pending TX interrupts or we never manage |
* to set FHC UART interrupt state to idle. |
*/ |
z8530_write(&dev->ctl_a, WR0, WR0_TX_IP_RST); |
z8530_write(&instance->z8530->ctl_a, WR0, WR0_TX_IP_RST); |
/* interrupt on all characters */ |
z8530_write(&dev->ctl_a, WR1, WR1_IARCSC); |
z8530_write(&instance->z8530->ctl_a, WR1, WR1_IARCSC); |
/* 8 bits per character and enable receiver */ |
z8530_write(&dev->ctl_a, WR3, WR3_RX8BITSCH | WR3_RX_ENABLE); |
z8530_write(&instance->z8530->ctl_a, WR3, WR3_RX8BITSCH | WR3_RX_ENABLE); |
/* Master Interrupt Enable. */ |
z8530_write(&dev->ctl_a, WR9, WR9_MIE); |
return &instance->kbrdin; |
z8530_write(&instance->z8530->ctl_a, WR9, WR9_MIE); |
} |
/** @} |
/branches/dynload/kernel/genarch/src/drivers/via-cuda/cuda.c |
---|
0,0 → 1,78 |
/* |
* 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. |
*/ |
/** @addtogroup genarch |
* @{ |
*/ |
/** @file |
*/ |
#include <genarch/drivers/via-cuda/cuda.h> |
#include <console/chardev.h> |
#include <ddi/irq.h> |
#include <arch/asm.h> |
#include <mm/slab.h> |
#include <ddi/device.h> |
static irq_ownership_t cuda_claim(irq_t *irq) |
{ |
return IRQ_DECLINE; |
} |
static void cuda_irq_handler(irq_t *irq) |
{ |
} |
cuda_instance_t *cuda_init(cuda_t *dev, inr_t inr, cir_t cir, void *cir_arg) |
{ |
cuda_instance_t *instance |
= malloc(sizeof(cuda_instance_t), FRAME_ATOMIC); |
if (instance) { |
instance->cuda = dev; |
instance->kbrdin = NULL; |
irq_initialize(&instance->irq); |
instance->irq.devno = device_assign_devno(); |
instance->irq.inr = inr; |
instance->irq.claim = cuda_claim; |
instance->irq.handler = cuda_irq_handler; |
instance->irq.instance = instance; |
instance->irq.cir = cir; |
instance->irq.cir_arg = cir_arg; |
} |
return instance; |
} |
void cuda_wire(cuda_instance_t *instance, indev_t *kbrdin) |
{ |
} |
/** @} |
*/ |
Property changes: |
Added: svn:mergeinfo |
/branches/dynload/kernel/genarch/src/drivers/ega/ega.c |
---|
44,6 → 44,7 |
#include <arch/types.h> |
#include <arch/asm.h> |
#include <memstr.h> |
#include <string.h> |
#include <console/chardev.h> |
#include <console/console.h> |
#include <sysinfo/sysinfo.h> |
425,45 → 426,56 |
/* |
* This function takes care of scrolling. |
*/ |
static void ega_check_cursor(void) |
static void ega_check_cursor(bool silent) |
{ |
if (ega_cursor < EGA_SCREEN) |
return; |
memmove((void *) videoram, (void *) (videoram + EGA_COLS * 2), |
(EGA_SCREEN - EGA_COLS) * 2); |
memmove((void *) backbuf, (void *) (backbuf + EGA_COLS * 2), |
(EGA_SCREEN - EGA_COLS) * 2); |
memsetw(videoram + (EGA_SCREEN - EGA_COLS) * 2, EGA_COLS, EMPTY_CHAR); |
memsetw(backbuf + (EGA_SCREEN - EGA_COLS) * 2, EGA_COLS, EMPTY_CHAR); |
if (!silent) { |
memmove((void *) videoram, (void *) (videoram + EGA_COLS * 2), |
(EGA_SCREEN - EGA_COLS) * 2); |
memsetw(videoram + (EGA_SCREEN - EGA_COLS) * 2, EGA_COLS, EMPTY_CHAR); |
} |
ega_cursor = ega_cursor - EGA_COLS; |
} |
static void ega_show_cursor(void) |
static void ega_show_cursor(bool silent) |
{ |
pio_write_8(ega_base + EGA_INDEX_REG, 0x0a); |
uint8_t stat = pio_read_8(ega_base + EGA_DATA_REG); |
pio_write_8(ega_base + EGA_INDEX_REG, 0x0a); |
pio_write_8(ega_base + EGA_DATA_REG, stat & (~(1 << 5))); |
if (!silent) { |
pio_write_8(ega_base + EGA_INDEX_REG, 0x0a); |
uint8_t stat = pio_read_8(ega_base + EGA_DATA_REG); |
pio_write_8(ega_base + EGA_INDEX_REG, 0x0a); |
pio_write_8(ega_base + EGA_DATA_REG, stat & (~(1 << 5))); |
} |
} |
static void ega_move_cursor(void) |
static void ega_move_cursor(bool silent) |
{ |
pio_write_8(ega_base + EGA_INDEX_REG, 0x0e); |
pio_write_8(ega_base + EGA_DATA_REG, (uint8_t) ((ega_cursor >> 8) & 0xff)); |
pio_write_8(ega_base + EGA_INDEX_REG, 0x0f); |
pio_write_8(ega_base + EGA_DATA_REG, (uint8_t) (ega_cursor & 0xff)); |
if (!silent) { |
pio_write_8(ega_base + EGA_INDEX_REG, 0x0e); |
pio_write_8(ega_base + EGA_DATA_REG, (uint8_t) ((ega_cursor >> 8) & 0xff)); |
pio_write_8(ega_base + EGA_INDEX_REG, 0x0f); |
pio_write_8(ega_base + EGA_DATA_REG, (uint8_t) (ega_cursor & 0xff)); |
} |
} |
static void ega_sync_cursor(void) |
static void ega_sync_cursor(bool silent) |
{ |
pio_write_8(ega_base + EGA_INDEX_REG, 0x0e); |
uint8_t hi = pio_read_8(ega_base + EGA_DATA_REG); |
pio_write_8(ega_base + EGA_INDEX_REG, 0x0f); |
uint8_t lo = pio_read_8(ega_base + EGA_DATA_REG); |
if (!silent) { |
pio_write_8(ega_base + EGA_INDEX_REG, 0x0e); |
uint8_t hi = pio_read_8(ega_base + EGA_DATA_REG); |
pio_write_8(ega_base + EGA_INDEX_REG, 0x0f); |
uint8_t lo = pio_read_8(ega_base + EGA_DATA_REG); |
ega_cursor = (hi << 8) | lo; |
} else |
ega_cursor = 0; |
ega_cursor = (hi << 8) | lo; |
if (ega_cursor >= EGA_SCREEN) |
ega_cursor = 0; |
470,12 → 482,14 |
if ((ega_cursor % EGA_COLS) != 0) |
ega_cursor = (ega_cursor + EGA_COLS) - ega_cursor % EGA_COLS; |
memsetw(videoram + ega_cursor * 2, EGA_SCREEN - ega_cursor, EMPTY_CHAR); |
memsetw(backbuf + ega_cursor * 2, EGA_SCREEN - ega_cursor, EMPTY_CHAR); |
ega_check_cursor(); |
ega_move_cursor(); |
ega_show_cursor(); |
if (!silent) |
memsetw(videoram + ega_cursor * 2, EGA_SCREEN - ega_cursor, EMPTY_CHAR); |
ega_check_cursor(silent); |
ega_move_cursor(silent); |
ega_show_cursor(silent); |
} |
static void ega_display_char(wchar_t ch, bool silent) |
485,7 → 499,7 |
uint8_t style; |
if ((index >> 8)) { |
glyph = '?'; |
glyph = U_SPECIAL; |
style = INVAL; |
} else { |
glyph = index & 0xff; |
524,11 → 538,9 |
ega_cursor++; |
break; |
} |
ega_check_cursor(); |
ega_check_cursor(silent); |
ega_move_cursor(silent); |
if (!silent) |
ega_move_cursor(); |
spinlock_unlock(&egalock); |
interrupts_restore(ipl); |
} |
551,7 → 563,7 |
/* Synchronize the back buffer and cursor position. */ |
memcpy(backbuf, videoram, EGA_VRAM_SIZE); |
ega_sync_cursor(); |
ega_sync_cursor(silent); |
outdev_initialize("ega", &ega_console, &ega_ops); |
stdout = &ega_console; |
567,8 → 579,8 |
void ega_redraw(void) |
{ |
memcpy(videoram, backbuf, EGA_VRAM_SIZE); |
ega_move_cursor(); |
ega_show_cursor(); |
ega_move_cursor(silent); |
ega_show_cursor(silent); |
} |
/** @} |
/branches/dynload/kernel/genarch/src/multiboot/multiboot.c |
---|
41,39 → 41,35 |
/** Extract command name from the multiboot module command line. |
* |
* @param buf Destination buffer (will always null-terminate). |
* @param n Size of destination buffer. |
* @param buf Destination buffer (will always NULL-terminate). |
* @param sz Size of destination buffer (in bytes). |
* @param cmd_line Input string (the command line). |
* |
*/ |
static void extract_command(char *buf, size_t n, const char *cmd_line) |
static void extract_command(char *buf, size_t sz, const char *cmd_line) |
{ |
const char *start, *end, *cp; |
size_t max_len; |
/* Find the first space. */ |
end = strchr(cmd_line, ' '); |
const char *end = str_chr(cmd_line, ' '); |
if (end == NULL) |
end = cmd_line + strlen(cmd_line); |
end = cmd_line + str_size(cmd_line); |
/* |
* Find last occurence of '/' before 'end'. If found, place start at |
* next character. Otherwise, place start at beginning of buffer. |
*/ |
cp = end; |
start = buf; |
const char *cp = end; |
const char *start = buf; |
while (cp != start) { |
if (*cp == '/') { |
start = cp + 1; |
break; |
} |
--cp; |
cp--; |
} |
/* Copy the command and null-terminate the string. */ |
max_len = min(n - 1, (size_t) (end - start)); |
strncpy(buf, start, max_len + 1); |
buf[max_len] = '\0'; |
/* Copy the command. */ |
str_ncpy(buf, sz, start, (size_t) (end - start)); |
} |
/** Parse multiboot information structure. |
87,8 → 83,6 |
void multiboot_info_parse(uint32_t signature, const multiboot_info_t *mi) |
{ |
uint32_t flags; |
multiboot_mod_t *mods; |
uint32_t i; |
if (signature == MULTIBOOT_LOADER_MAGIC) |
flags = mi->flags; |
98,10 → 92,11 |
} |
/* Copy module information. */ |
uint32_t i; |
if ((flags & MBINFO_FLAGS_MODS) != 0) { |
init.cnt = min(mi->mods_count, CONFIG_INIT_TASKS); |
mods = (multiboot_mod_t *) MULTIBOOT_PTR(mi->mods_addr); |
multiboot_mod_t *mods |
= (multiboot_mod_t *) MULTIBOOT_PTR(mi->mods_addr); |
for (i = 0; i < init.cnt; i++) { |
init.tasks[i].addr = PA2KA(mods[i].start); |
113,7 → 108,7 |
CONFIG_TASK_NAME_BUFLEN, |
MULTIBOOT_PTR(mods[i].string)); |
} else |
init.tasks[i].name[0] = '\0'; |
init.tasks[i].name[0] = 0; |
} |
} else |
init.cnt = 0; |
120,13 → 115,9 |
/* Copy memory map. */ |
int32_t mmap_length; |
multiboot_mmap_t *mme; |
uint32_t size; |
if ((flags & MBINFO_FLAGS_MMAP) != 0) { |
mmap_length = mi->mmap_length; |
mme = MULTIBOOT_PTR(mi->mmap_addr); |
int32_t mmap_length = mi->mmap_length; |
multiboot_mmap_t *mme = MULTIBOOT_PTR(mi->mmap_addr); |
e820counter = 0; |
i = 0; |
134,7 → 125,7 |
e820table[i++] = mme->mm_info; |
/* Compute address of next structure. */ |
size = sizeof(mme->size) + mme->size; |
uint32_t size = sizeof(mme->size) + mme->size; |
mme = ((void *) mme) + size; |
mmap_length -= size; |
} |
/branches/dynload/kernel/genarch/src/srln/srln.c |
---|
39,21 → 39,72 |
#include <console/console.h> |
#include <proc/thread.h> |
#include <arch.h> |
#include <string.h> |
static indev_t srlnout; |
indev_operations_t srlnout_ops = { |
static indev_operations_t srln_raw_ops = { |
.poll = NULL |
}; |
static void ksrln(void *arg) |
{ |
indev_t *in = (indev_t *) arg; |
srln_instance_t *instance = (srln_instance_t *) arg; |
bool cr = false; |
uint32_t escape = 0; |
while (true) { |
uint8_t ch = _getc(in); |
wchar_t ch = indev_pop_character(&instance->raw); |
/* ANSI escape sequence processing */ |
if (escape != 0) { |
escape <<= 8; |
escape |= ch & 0xff; |
if ((escape == 0x1b4f) || (escape == 0x1b5b) || (escape == 0x1b5b33)) |
continue; |
switch (escape) { |
case 0x1b4f46: |
case 0x1b5b46: |
ch = U_END_ARROW; |
escape = 0; |
break; |
case 0x1b4f48: |
case 0x1b5b48: |
ch = U_HOME_ARROW; |
escape = 0; |
break; |
case 0x1b5b41: |
ch = U_UP_ARROW; |
escape = 0; |
break; |
case 0x1b5b42: |
ch = U_DOWN_ARROW; |
escape = 0; |
break; |
case 0x1b5b43: |
ch = U_RIGHT_ARROW; |
escape = 0; |
break; |
case 0x1b5b44: |
ch = U_LEFT_ARROW; |
escape = 0; |
break; |
case 0x1b5b337e: |
ch = U_DELETE; |
escape = 0; |
break; |
default: |
escape = 0; |
} |
} |
if (ch == 0x1b) { |
escape = ch & 0xff; |
continue; |
} |
/* Replace carriage return with line feed |
and suppress any following line feed */ |
if ((ch == '\n') && (cr)) { |
cr = false; |
continue; |
65,24 → 116,44 |
} else |
cr = false; |
/* Backspace */ |
if (ch == 0x7f) |
ch = '\b'; |
indev_push_character(stdin, ch); |
indev_push_character(instance->sink, ch); |
} |
} |
void srln_init(indev_t *devin) |
srln_instance_t *srln_init(void) |
{ |
indev_initialize("srln", &srlnout, &srlnout_ops); |
thread_t *thread |
= thread_create(ksrln, devin, TASK, 0, "ksrln", false); |
srln_instance_t *instance |
= malloc(sizeof(srln_instance_t), FRAME_ATOMIC); |
if (instance) { |
instance->thread |
= thread_create(ksrln, (void *) instance, TASK, 0, "ksrln", false); |
if (!instance->thread) { |
free(instance); |
return NULL; |
} |
instance->sink = NULL; |
indev_initialize("srln", &instance->raw, &srln_raw_ops); |
} |
if (thread) { |
stdin = &srlnout; |
thread_ready(thread); |
} |
return instance; |
} |
indev_t *srln_wire(srln_instance_t *instance, indev_t *sink) |
{ |
ASSERT(instance); |
ASSERT(sink); |
instance->sink = sink; |
thread_ready(instance->thread); |
return &instance->raw; |
} |
/** @} |
*/ |
/branches/dynload/kernel/generic/include/event/event.h |
---|
File deleted |
/branches/dynload/kernel/generic/include/event/event_types.h |
---|
File deleted |
/branches/dynload/kernel/generic/include/byteorder.h |
---|
36,6 → 36,7 |
#define KERN_BYTEORDER_H_ |
#include <arch/byteorder.h> |
#include <arch/types.h> |
#if !(defined(ARCH_IS_BIG_ENDIAN) ^ defined(ARCH_IS_LITTLE_ENDIAN)) |
#error The architecture must be either big-endian or little-endian. |
/branches/dynload/kernel/generic/include/symtab.h |
---|
26,7 → 26,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup generic |
/** @addtogroup generic |
* @{ |
*/ |
/** @file |
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 *name); |
extern int symtab_compl(char *input, count_t size); |
#ifdef CONFIG_SYMTAB |
/branches/dynload/kernel/generic/include/sysinfo/sysinfo.h |
---|
26,7 → 26,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup generic |
/** @addtogroup generic |
* @{ |
*/ |
/** @file |
36,6 → 36,7 |
#define KERN_SYSINFO_H_ |
#include <arch/types.h> |
#include <string.h> |
typedef union sysinfo_item_val { |
unative_t val; |
59,13 → 60,13 |
int subinfo_type; |
} sysinfo_item_t; |
#define SYSINFO_VAL_VAL 0 |
#define SYSINFO_VAL_FUNCTION 1 |
#define SYSINFO_VAL_UNDEFINED '?' |
#define SYSINFO_VAL_VAL 0 |
#define SYSINFO_VAL_FUNCTION 1 |
#define SYSINFO_VAL_UNDEFINED U_SPECIAL |
#define SYSINFO_SUBINFO_NONE 0 |
#define SYSINFO_SUBINFO_TABLE 1 |
#define SYSINFO_SUBINFO_FUNCTION 2 |
#define SYSINFO_SUBINFO_NONE 0 |
#define SYSINFO_SUBINFO_TABLE 1 |
#define SYSINFO_SUBINFO_FUNCTION 2 |
typedef unative_t (*sysinfo_val_fn_t)(sysinfo_item_t *root); |
typedef unative_t (*sysinfo_subinfo_fn_t)(const char *subname); |
/branches/dynload/kernel/generic/include/string.h |
---|
37,26 → 37,64 |
#include <typedefs.h> |
#define UTF8_NO_LIMIT ((index_t) -1) |
/**< Common Unicode characters */ |
#define U_SPECIAL '?' |
extern char invalch; |
#define U_LEFT_ARROW 0x2190 |
#define U_UP_ARROW 0x2191 |
#define U_RIGHT_ARROW 0x2192 |
#define U_DOWN_ARROW 0x2193 |
extern wchar_t utf8_decode(const char *str, index_t *index, index_t limit); |
extern bool utf8_encode(const wchar_t ch, char *str, index_t *index, index_t limit); |
extern size_t utf8_count_bytes(const char *str, count_t count); |
extern bool ascii_check(const wchar_t ch); |
extern bool unicode_check(const wchar_t ch); |
#define U_PAGE_UP 0x21de |
#define U_PAGE_DOWN 0x21df |
extern size_t strlen(const char *str); |
extern size_t strlen_utf8(const char *str); |
extern size_t strlen_utf32(const wchar_t *str); |
#define U_HOME_ARROW 0x21f1 |
#define U_END_ARROW 0x21f2 |
extern int strcmp(const char *src, const char *dst); |
extern int strncmp(const char *src, const char *dst, size_t len); |
extern void strncpy(char *dest, const char *src, size_t len); |
#define U_NULL 0x2400 |
#define U_ESCAPE 0x241b |
#define U_DELETE 0x2421 |
extern char *strchr(const char *s, int i); |
#define U_CURSOR 0x2588 |
#define U_BOM 0xfeff |
/**< No size limit constant */ |
#define STR_NO_LIMIT ((size_t) -1) |
/**< Maximum size of a string containing cnt characters */ |
#define STR_BOUNDS(cnt) (cnt << 2) |
extern wchar_t str_decode(const char *str, size_t *offset, size_t sz); |
extern int chr_encode(wchar_t ch, char *str, size_t *offset, size_t sz); |
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 count_t str_length(const char *str); |
extern count_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 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 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); |
extern void wstr_nstr(char *dst, const wchar_t *src, size_t size); |
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); |
#endif |
/** @} |
/branches/dynload/kernel/generic/include/console/chardev.h |
---|
46,7 → 46,7 |
/* Input character device operations interface. */ |
typedef struct { |
/** Read character directly from device, assume interrupts disabled. */ |
char (* poll)(struct indev *); |
wchar_t (* poll)(struct indev *); |
} indev_operations_t; |
/** Character input device. */ |
56,7 → 56,7 |
/** Protects everything below. */ |
SPINLOCK_DECLARE(lock); |
uint8_t buffer[INDEV_BUFLEN]; |
wchar_t buffer[INDEV_BUFLEN]; |
count_t counter; |
/** Implementation of indev operations. */ |
71,7 → 71,7 |
/* Output character device operations interface. */ |
typedef struct { |
/** Write character to output. */ |
void (* write)(struct outdev *, wchar_t c, bool silent); |
void (* write)(struct outdev *, wchar_t, bool); |
} outdev_operations_t; |
/** Character input device. */ |
88,11 → 88,14 |
extern void indev_initialize(char *name, indev_t *indev, |
indev_operations_t *op); |
extern void indev_push_character(indev_t *indev, uint8_t ch); |
extern void indev_push_character(indev_t *indev, wchar_t ch); |
extern wchar_t indev_pop_character(indev_t *indev); |
extern void outdev_initialize(char *name, outdev_t *outdev, |
outdev_operations_t *op); |
extern bool check_poll(indev_t *indev); |
#endif /* KERN_CHARDEV_H_ */ |
/** @} |
/branches/dynload/kernel/generic/include/console/kconsole.h |
---|
39,8 → 39,8 |
#include <synch/spinlock.h> |
#include <ipc/irq.h> |
#define MAX_CMDLINE 256 |
#define KCONSOLE_HISTORY 10 |
#define MAX_CMDLINE 256 |
#define KCONSOLE_HISTORY 10 |
typedef enum { |
ARG_TYPE_INVALID = 0, |
47,7 → 47,7 |
ARG_TYPE_INT, |
ARG_TYPE_STRING, |
/** Variable type - either symbol or string. */ |
ARG_TYPE_VAR |
ARG_TYPE_VAR |
} cmd_arg_type_t; |
/** Structure representing one argument of kconsole command line. */ |
96,7 → 96,7 |
extern void kconsole(char *prompt, char *msg, bool kcon); |
extern void kconsole_thread(void *data); |
extern int cmd_register(cmd_info_t *cmd); |
extern bool cmd_register(cmd_info_t *cmd); |
#endif |
/branches/dynload/kernel/generic/include/console/console.h |
---|
40,19 → 40,17 |
extern indev_t *stdin; |
extern outdev_t *stdout; |
extern bool silent; |
extern indev_t *stdin_wire(void); |
extern void console_init(void); |
extern void klog_init(void); |
extern void klog_update(void); |
extern bool check_poll(indev_t *indev); |
extern uint8_t getc(indev_t *indev); |
extern uint8_t _getc(indev_t *indev); |
extern wchar_t getc(indev_t *indev); |
extern count_t gets(indev_t *indev, char *buf, size_t buflen); |
extern unative_t sys_klog(int fd, const void * buf, size_t count); |
extern unative_t sys_klog(int fd, const void *buf, size_t size); |
extern void grab_console(void); |
extern void release_console(void); |
/branches/dynload/kernel/generic/include/printf/printf_core.h |
---|
40,11 → 40,11 |
/** Structure for specifying output methods for different printf clones. */ |
typedef struct { |
/* UTF-8 output function, returns number of printed UTF-8 characters or EOF */ |
int (*write_utf8)(const char *, size_t, void *); |
/* String output function, returns number of printed characters or EOF */ |
int (*str_write)(const char *, size_t, void *); |
/* UTF-32 output function, returns number of printed UTF-32 characters or EOF */ |
int (*write_utf32)(const wchar_t *, size_t, void *); |
/* Wide string output function, returns number of printed characters or EOF */ |
int (*wstr_write)(const wchar_t *, size_t, void *); |
/* User data - output stream specification, state, locks, etc. */ |
void *data; |
/branches/dynload/kernel/generic/include/ipc/event.h |
---|
0,0 → 1,79 |
/* |
* 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 generic |
* @{ |
*/ |
/** @file |
*/ |
#ifndef KERN_EVENT_H_ |
#define KERN_EVENT_H_ |
#include <ipc/event_types.h> |
#include <arch/types.h> |
#include <synch/spinlock.h> |
#include <ipc/ipc.h> |
/** Event notification structure. */ |
typedef struct { |
SPINLOCK_DECLARE(lock); |
/** Answerbox for notifications. */ |
answerbox_t *answerbox; |
/** Method to be used for the notification. */ |
unative_t method; |
/** Counter. */ |
count_t counter; |
} event_t; |
extern void event_init(void); |
extern unative_t sys_event_subscribe(unative_t, unative_t); |
extern bool event_is_subscribed(event_type_t); |
extern void event_cleanup_answerbox(answerbox_t *); |
#define event_notify_0(e) \ |
event_notify((e), 0, 0, 0, 0, 0) |
#define event_notify_1(e, a1) \ |
event_notify((e), (a1), 0, 0, 0, 0) |
#define event_notify_2(e, a1, a2) \ |
event_notify((e), (a1), (a2), 0, 0, 0) |
#define event_notify_3(e, a1, a2, a3) \ |
event_notify((e), (a1), (a2), (a3), 0, 0) |
#define event_notify_4(e, a1, a2, a3, a4) \ |
event_notify((e), (a1), (a2), (a3), (a4), 0) |
#define event_notify_5(e, a1, a2, a3, a4, a5) \ |
event_notify((e), (a1), (a2), (a3), (a4), (a5)) |
extern void event_notify(event_type_t, unative_t, unative_t, unative_t, |
unative_t, unative_t); |
#endif |
/** @} |
*/ |
Property changes: |
Added: svn:mergeinfo |
/branches/dynload/kernel/generic/include/ipc/event_types.h |
---|
0,0 → 1,47 |
/* |
* 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 generic |
* @{ |
*/ |
/** @file |
*/ |
#ifndef KERN_EVENT_TYPES_H_ |
#define KERN_EVENT_TYPES_H_ |
typedef enum event_type { |
EVENT_KLOG = 0, |
EVENT_KCONSOLE, |
EVENT_END |
} event_type_t; |
#endif |
/** @} |
*/ |
Property changes: |
Added: svn:mergeinfo |
/branches/dynload/kernel/generic/src/event/event.c |
---|
File deleted |
/branches/dynload/kernel/generic/src/synch/spinlock.c |
---|
32,9 → 32,9 |
/** |
* @file |
* @brief Spinlocks. |
* @brief Spinlocks. |
*/ |
#include <synch/spinlock.h> |
#include <atomic.h> |
#include <arch/barrier.h> |
106,9 → 106,9 |
#endif |
if (i++ > DEADLOCK_THRESHOLD) { |
printf("cpu%u: looping on spinlock %" PRIp ":%s, " |
"caller=%" PRIp "(%s)", CPU->id, sl, sl->name, |
"caller=%" PRIp "(%s)\n", CPU->id, sl, sl->name, |
CALLER, symtab_fmt_name_lookup(CALLER)); |
i = 0; |
deadlock_reported = true; |
} |
/branches/dynload/kernel/generic/src/main/kinit.c |
---|
186,14 → 186,14 |
char *name; |
name = init.tasks[i].name; |
if (name[0] == '\0') |
if (name[0] == 0) |
name = "<unknown>"; |
ASSERT(TASK_NAME_BUFLEN >= INIT_PREFIX_LEN); |
strncpy(namebuf, INIT_PREFIX, TASK_NAME_BUFLEN); |
strncpy(namebuf + INIT_PREFIX_LEN, name, |
TASK_NAME_BUFLEN - INIT_PREFIX_LEN); |
str_cpy(namebuf, TASK_NAME_BUFLEN, INIT_PREFIX); |
str_cpy(namebuf + INIT_PREFIX_LEN, |
TASK_NAME_BUFLEN - INIT_PREFIX_LEN, name); |
int rc = program_create_from_image((void *) init.tasks[i].addr, |
namebuf, &programs[i]); |
218,19 → 218,11 |
} |
/* |
* Run user tasks with small delays |
* to avoid intermixed klog output. |
* |
* TODO: This certainly does not guarantee |
* anything, it just works in most of the |
* cases. Some better way how to achieve |
* nice klog output should be found. |
* Run user tasks. |
*/ |
for (i = 0; i < init.cnt; i++) { |
if (programs[i].task != NULL) { |
if (programs[i].task != NULL) |
program_ready(&programs[i]); |
thread_usleep(10000); |
} |
} |
#ifdef CONFIG_KCONSOLE |
/branches/dynload/kernel/generic/src/main/main.c |
---|
32,7 → 32,7 |
/** |
* @file |
* @brief Main initialization kernel function for all processors. |
* @brief Main initialization kernel function for all processors. |
* |
* During kernel boot, all processors, after architecture dependent |
* initialization, start executing code found in this file. After |
82,7 → 82,7 |
#include <smp/smp.h> |
#include <ddi/ddi.h> |
#include <main/main.h> |
#include <event/event.h> |
#include <ipc/event.h> |
/** Global configuration structure. */ |
config_t config; |
/branches/dynload/kernel/generic/src/main/shutdown.c |
---|
32,10 → 32,11 |
/** |
* @file |
* @brief Shutdown procedures. |
* @brief Shutdown procedures. |
*/ |
#include <arch.h> |
#include <func.h> |
#include <print.h> |
void reboot(void) |
47,6 → 48,7 |
#endif |
arch_reboot(); |
halt(); |
} |
/** @} |
/branches/dynload/kernel/generic/src/debug/symtab.c |
---|
32,7 → 32,7 |
/** |
* @file |
* @brief Kernel symbol resolver. |
* @brief Kernel symbol resolver. |
*/ |
#include <symtab.h> |
43,30 → 43,33 |
#include <typedefs.h> |
#include <errno.h> |
/** Get name of symbol that seems most likely to correspond to address. |
/** Get name of a symbol that seems most likely to correspond to address. |
* |
* @param addr Address. |
* @param name Place to store pointer to the symbol name. |
* @param addr Address. |
* @param name Place to store pointer to the symbol name. |
* |
* @return Zero on success or negative error code, ENOENT if not found, |
* ENOTSUP if symbol table not available. |
* @return Zero on success or negative error code, ENOENT if not found, |
* ENOTSUP if symbol table not available. |
* |
*/ |
int symtab_name_lookup(unative_t addr, char **name) |
{ |
#ifdef CONFIG_SYMTAB |
count_t i; |
for (i = 1; symbol_table[i].address_le; ++i) { |
for (i = 1; symbol_table[i].address_le; i++) { |
if (addr < uint64_t_le2host(symbol_table[i].address_le)) |
break; |
} |
if (addr >= uint64_t_le2host(symbol_table[i - 1].address_le)) { |
*name = symbol_table[i - 1].symbol_name; |
return EOK; |
} |
*name = NULL; |
return ENOENT; |
#else |
*name = NULL; |
return ENOTSUP; |
78,21 → 81,24 |
* Returns name of closest corresponding symbol, "Not found" if none exists |
* or "N/A" if no symbol information is available. |
* |
* @param addr Address. |
* @param name Place to store pointer to the symbol name. |
* @param addr Address. |
* @param name Place to store pointer to the symbol name. |
* |
* @return Pointer to a human-readable string. |
* @return Pointer to a human-readable string. |
* |
*/ |
char *symtab_fmt_name_lookup(unative_t addr) |
{ |
int rc; |
char *name; |
rc = symtab_name_lookup(addr, &name); |
int rc = symtab_name_lookup(addr, &name); |
switch (rc) { |
case EOK: return name; |
case ENOENT: return "Not found"; |
default: return "N/A"; |
case EOK: |
return name; |
case ENOENT: |
return "Not found"; |
default: |
return "N/A"; |
} |
} |
100,95 → 106,90 |
/** Find symbols that match the parameter forward and print them. |
* |
* @param name - search string |
* @param startpos - starting position, changes to found position |
* @return Pointer to the part of string that should be completed or NULL |
* @param name Search string |
* @param startpos Starting position, changes to found position |
* |
* @return Pointer to the part of string that should be completed or NULL. |
* |
*/ |
static char * symtab_search_one(const char *name, int *startpos) |
static const char *symtab_search_one(const char *name, count_t *startpos) |
{ |
unsigned int namelen = strlen(name); |
char *curname; |
int i, j; |
int colonoffset = -1; |
for (i = 0; name[i]; i++) |
if (name[i] == ':') { |
colonoffset = i; |
break; |
} |
for (i = *startpos; symbol_table[i].address_le; ++i) { |
/* Find a ':' in name */ |
curname = symbol_table[i].symbol_name; |
for (j = 0; curname[j] && curname[j] != ':'; j++) |
; |
if (!curname[j]) |
count_t namelen = str_length(name); |
count_t pos; |
for (pos = *startpos; symbol_table[pos].address_le; pos++) { |
const char *curname = symbol_table[pos].symbol_name; |
/* Find a ':' in curname */ |
const char *colon = str_chr(curname, ':'); |
if (colon == NULL) |
continue; |
j -= colonoffset; |
curname += j; |
if (strlen(curname) < namelen) |
if (str_length(curname) < namelen) |
continue; |
if (strncmp(curname, name, namelen) == 0) { |
*startpos = i; |
return curname + namelen; |
if (str_lcmp(name, curname, namelen) == 0) { |
*startpos = pos; |
return (curname + str_lsize(curname, namelen)); |
} |
} |
return NULL; |
} |
#endif |
/** Return address that corresponds to the entry |
/** Return address that corresponds to the entry. |
* |
* Search symbol table, and if there is one match, return it |
* |
* @param name Name of the symbol |
* @param addr Place to store symbol address |
* @param name Name of the symbol |
* @param addr Place to store symbol address |
* |
* @return Zero on success, ENOENT - not found, EOVERFLOW - duplicate |
* symbol, ENOTSUP - no symbol information available. |
* @return Zero on success, ENOENT - not found, EOVERFLOW - duplicate |
* symbol, ENOTSUP - no symbol information available. |
* |
*/ |
int symtab_addr_lookup(const char *name, uintptr_t *addr) |
{ |
#ifdef CONFIG_SYMTAB |
count_t found = 0; |
char *hint; |
int i; |
i = 0; |
while ((hint = symtab_search_one(name, &i))) { |
if (!strlen(hint)) { |
*addr = uint64_t_le2host(symbol_table[i].address_le); |
count_t pos = 0; |
const char *hint; |
while ((hint = symtab_search_one(name, &pos))) { |
if (str_length(hint) == 0) { |
*addr = uint64_t_le2host(symbol_table[pos].address_le); |
found++; |
} |
i++; |
pos++; |
} |
if (found > 1) |
return EOVERFLOW; |
if (found < 1) |
return ENOENT; |
return EOK; |
#else |
return ENOTSUP; |
#endif |
} |
/** Find symbols that match parameter and prints them */ |
/** Find symbols that match parameter and print them */ |
void symtab_print_search(const char *name) |
{ |
#ifdef CONFIG_SYMTAB |
int i; |
uintptr_t addr; |
char *realname; |
i = 0; |
while (symtab_search_one(name, &i)) { |
addr = uint64_t_le2host(symbol_table[i].address_le); |
realname = symbol_table[i].symbol_name; |
count_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; |
printf("%p: %s\n", addr, realname); |
i++; |
pos++; |
} |
#else |
printf("No symbol information available.\n"); |
#endif |
196,55 → 197,54 |
/** Symtab completion |
* |
* @param input - Search string, completes to symbol name |
* @returns - 0 - nothing found, 1 - success, >1 print duplicates |
* @param input Search string, completes to symbol name |
* @param size Input buffer size |
* |
* @return 0 - nothing found, 1 - success, >1 print duplicates |
* |
*/ |
int symtab_compl(char *input) |
int symtab_compl(char *input, count_t size) |
{ |
#ifdef CONFIG_SYMTAB |
char output[MAX_SYMBOL_NAME + 1]; |
int startpos = 0; |
char *foundtxt; |
int found = 0; |
int i; |
char *name = input; |
/* Allow completion of pointers */ |
if (name[0] == '*' || name[0] == '&') |
const char *name = input; |
/* Allow completion of pointers */ |
if ((name[0] == '*') || (name[0] == '&')) |
name++; |
/* Do not print everything */ |
if (!strlen(name)) |
/* Do not print all symbols */ |
if (str_length(name) == 0) |
return 0; |
output[0] = '\0'; |
while ((foundtxt = symtab_search_one(name, &startpos))) { |
startpos++; |
if (!found) |
strncpy(output, foundtxt, strlen(foundtxt) + 1); |
else { |
for (i = 0; output[i] && foundtxt[i] && |
output[i] == foundtxt[i]; i++) |
; |
output[i] = '\0'; |
} |
count_t found = 0; |
count_t pos = 0; |
const char *hint; |
char output[MAX_SYMBOL_NAME]; |
output[0] = 0; |
while ((hint = symtab_search_one(name, &pos))) { |
if ((found == 0) || (str_length(output) > str_length(hint))) |
str_cpy(output, MAX_SYMBOL_NAME, hint); |
pos++; |
found++; |
} |
if (!found) |
return 0; |
if (found > 1 && !strlen(output)) { |
if ((found > 1) && (str_length(output) != 0)) { |
printf("\n"); |
startpos = 0; |
while ((foundtxt = symtab_search_one(name, &startpos))) { |
printf("%s\n", symbol_table[startpos].symbol_name); |
startpos++; |
pos = 0; |
while ((hint = symtab_search_one(name, &pos))) { |
printf("%s\n", symbol_table[pos].symbol_name); |
pos++; |
} |
} |
strncpy(input, output, MAX_SYMBOL_NAME); |
if (found > 0) |
str_cpy(input, size, output); |
return found; |
#else |
return 0; |
#endif |
/branches/dynload/kernel/generic/src/interrupt/interrupt.c |
---|
145,7 → 145,7 |
if (((i + 1) % 20) == 0) { |
printf(" -- Press any key to continue -- "); |
spinlock_unlock(&exctbl_lock); |
_getc(stdin); |
indev_pop_character(stdin); |
spinlock_lock(&exctbl_lock); |
printf("\n"); |
} |
/branches/dynload/kernel/generic/src/ddi/irq.c |
---|
101,11 → 101,12 |
*/ |
static index_t irq_ht_hash(unative_t *key); |
static bool irq_ht_compare(unative_t *key, count_t keys, link_t *item); |
static void irq_ht_remove(link_t *item); |
static hash_table_operations_t irq_ht_ops = { |
.hash = irq_ht_hash, |
.compare = irq_ht_compare, |
.remove_callback = NULL /* not used */ |
.remove_callback = irq_ht_remove, |
}; |
/** |
116,11 → 117,12 |
*/ |
static index_t irq_lin_hash(unative_t *key); |
static bool irq_lin_compare(unative_t *key, count_t keys, link_t *item); |
static void irq_lin_remove(link_t *item); |
static hash_table_operations_t irq_lin_ops = { |
.hash = irq_lin_hash, |
.compare = irq_lin_compare, |
.remove_callback = NULL /* not used */ |
.remove_callback = irq_lin_remove, |
}; |
/** Number of buckets in either of the hash tables. */ |
347,6 → 349,17 |
return rv; |
} |
/** Unlock IRQ structure after hash_table_remove(). |
* |
* @param lnk Link in the removed and locked IRQ structure. |
*/ |
void irq_ht_remove(link_t *lnk) |
{ |
irq_t *irq __attribute__((unused)) |
= hash_table_get_instance(lnk, irq_t, link); |
spinlock_unlock(&irq->lock); |
} |
/** Compute hash index for the key. |
* |
* This function computes hash index into |
406,5 → 419,16 |
return rv; |
} |
/** Unlock IRQ structure after hash_table_remove(). |
* |
* @param lnk Link in the removed and locked IRQ structure. |
*/ |
void irq_lin_remove(link_t *lnk) |
{ |
irq_t *irq __attribute__((unused)) |
= hash_table_get_instance(lnk, irq_t, link); |
spinlock_unlock(&irq->lock); |
} |
/** @} |
*/ |
/branches/dynload/kernel/generic/src/console/console.c |
---|
41,21 → 41,22 |
#include <arch/types.h> |
#include <ddi/irq.h> |
#include <ddi/ddi.h> |
#include <event/event.h> |
#include <ipc/event.h> |
#include <ipc/irq.h> |
#include <arch.h> |
#include <func.h> |
#include <print.h> |
#include <putchar.h> |
#include <atomic.h> |
#include <syscall/copy.h> |
#include <errno.h> |
#include <string.h> |
#define KLOG_SIZE PAGE_SIZE |
#define KLOG_PAGES 4 |
#define KLOG_LENGTH (KLOG_PAGES * PAGE_SIZE / sizeof(wchar_t)) |
#define KLOG_LATENCY 8 |
/** Kernel log cyclic buffer */ |
static wchar_t klog[KLOG_SIZE] __attribute__ ((aligned (PAGE_SIZE))); |
static wchar_t klog[KLOG_LENGTH] __attribute__ ((aligned (PAGE_SIZE))); |
/** Kernel log initialized */ |
static bool klog_inited = false; |
68,9 → 69,6 |
/** Number of stored kernel log characters for uspace */ |
static size_t klog_uspace = 0; |
/** Silence output */ |
bool silent = false; |
/** Kernel log spinlock */ |
SPINLOCK_INITIALIZE(klog_lock); |
77,10 → 75,28 |
/** Physical memory area used for klog buffer */ |
static parea_t klog_parea; |
static indev_operations_t stdin_ops = { |
.poll = NULL |
}; |
/** Silence output */ |
bool silent = false; |
/** Standard input and output character devices */ |
indev_t *stdin = NULL; |
outdev_t *stdout = NULL; |
indev_t *stdin_wire(void) |
{ |
if (stdin == NULL) { |
stdin = malloc(sizeof(indev_t), FRAME_ATOMIC); |
if (stdin != NULL) |
indev_initialize("stdin", stdin, &stdin_ops); |
} |
return stdin; |
} |
/** Initialize kernel logging facility |
* |
* The shared area contains kernel cyclic buffer. Userspace application may |
93,7 → 109,6 |
void *faddr = (void *) KA2PA(klog); |
ASSERT((uintptr_t) faddr % FRAME_SIZE == 0); |
ASSERT(KLOG_SIZE % FRAME_SIZE == 0); |
klog_parea.pbase = (uintptr_t) faddr; |
klog_parea.frames = SIZE2FRAMES(sizeof(klog)); |
100,7 → 115,7 |
ddi_parea_register(&klog_parea); |
sysinfo_set_item_val("klog.faddr", NULL, (unative_t) faddr); |
sysinfo_set_item_val("klog.pages", NULL, SIZE2FRAMES(sizeof(klog))); |
sysinfo_set_item_val("klog.pages", NULL, KLOG_PAGES); |
spinlock_lock(&klog_lock); |
klog_inited = true; |
109,8 → 124,14 |
void grab_console(void) |
{ |
bool prev = silent; |
silent = false; |
arch_grab_console(); |
/* Force the console to print the prompt */ |
if ((stdin) && (prev)) |
indev_push_character(stdin, '\n'); |
} |
void release_console(void) |
137,55 → 158,6 |
return true; |
} |
bool check_poll(indev_t *indev) |
{ |
if (indev == NULL) |
return false; |
if (indev->op == NULL) |
return false; |
return (indev->op->poll != NULL); |
} |
/** Get character from input character device. Do not echo character. |
* |
* @param indev Input character device. |
* @return Character read. |
* |
*/ |
uint8_t _getc(indev_t *indev) |
{ |
if (atomic_get(&haltstate)) { |
/* If we are here, we are hopefully on the processor that |
* issued the 'halt' command, so proceed to read the character |
* directly from input |
*/ |
if (check_poll(indev)) |
return indev->op->poll(indev); |
/* No other way of interacting with user */ |
interrupts_disable(); |
if (CPU) |
printf("cpu%u: ", CPU->id); |
else |
printf("cpu: "); |
printf("halted (no polling input)\n"); |
cpu_halt(); |
} |
waitq_sleep(&indev->wq); |
ipl_t ipl = interrupts_disable(); |
spinlock_lock(&indev->lock); |
uint8_t ch = indev->buffer[(indev->index - indev->counter) % INDEV_BUFLEN]; |
indev->counter--; |
spinlock_unlock(&indev->lock); |
interrupts_restore(ipl); |
return ch; |
} |
/** Get string from input character device. |
* |
* Read characters from input character device until first occurrence |
192,7 → 164,7 |
* of newline character. |
* |
* @param indev Input character device. |
* @param buf Buffer where to store string terminated by '\0'. |
* @param buf Buffer where to store string terminated by NULL. |
* @param buflen Size of the buffer. |
* |
* @return Number of characters read. |
200,36 → 172,38 |
*/ |
count_t gets(indev_t *indev, char *buf, size_t buflen) |
{ |
index_t index = 0; |
size_t offset = 0; |
count_t count = 0; |
buf[offset] = 0; |
while (index < buflen) { |
char ch = _getc(indev); |
wchar_t ch; |
while ((ch = indev_pop_character(indev)) != '\n') { |
if (ch == '\b') { |
if (index > 0) { |
index--; |
/* Space backspace, space */ |
if (count > 0) { |
/* Space, backspace, space */ |
putchar('\b'); |
putchar(' '); |
putchar('\b'); |
count--; |
offset = str_lsize(buf, count); |
buf[offset] = 0; |
} |
continue; |
} |
putchar(ch); |
if (ch == '\n') { /* end of string => write 0, return */ |
buf[index] = '\0'; |
return (count_t) index; |
} |
buf[index++] = ch; |
if (chr_encode(ch, buf, &offset, buflen - 1) == EOK) { |
putchar(ch); |
count++; |
buf[offset] = 0; |
} |
} |
return (count_t) index; |
return count; |
} |
/** Get character from input device & echo it to screen */ |
uint8_t getc(indev_t *indev) |
wchar_t getc(indev_t *indev) |
{ |
uint8_t ch = _getc(indev); |
wchar_t ch = indev_pop_character(indev); |
putchar(ch); |
return ch; |
} |
254,16 → 228,16 |
/* Print charaters stored in kernel log */ |
index_t i; |
for (i = klog_len - klog_stored; i < klog_len; i++) |
stdout->op->write(stdout, klog[(klog_start + i) % KLOG_SIZE], silent); |
stdout->op->write(stdout, klog[(klog_start + i) % KLOG_LENGTH], silent); |
klog_stored = 0; |
} |
/* Store character in the cyclic kernel log */ |
klog[(klog_start + klog_len) % KLOG_SIZE] = ch; |
if (klog_len < KLOG_SIZE) |
klog[(klog_start + klog_len) % KLOG_LENGTH] = ch; |
if (klog_len < KLOG_LENGTH) |
klog_len++; |
else |
klog_start = (klog_start + 1) % KLOG_SIZE; |
klog_start = (klog_start + 1) % KLOG_LENGTH; |
if ((stdout) && (stdout->op->write)) |
stdout->op->write(stdout, ch, silent); |
295,25 → 269,25 |
* Print to kernel log. |
* |
*/ |
unative_t sys_klog(int fd, const void * buf, size_t count) |
unative_t sys_klog(int fd, const void *buf, size_t size) |
{ |
char *data; |
int rc; |
if (count > PAGE_SIZE) |
if (size > PAGE_SIZE) |
return ELIMIT; |
if (count > 0) { |
data = (char *) malloc(count + 1, 0); |
if (size > 0) { |
data = (char *) malloc(size + 1, 0); |
if (!data) |
return ENOMEM; |
rc = copy_from_uspace(data, buf, count); |
rc = copy_from_uspace(data, buf, size); |
if (rc) { |
free(data); |
return rc; |
} |
data[count] = 0; |
data[size] = 0; |
printf("%s", data); |
free(data); |
320,7 → 294,7 |
} else |
klog_update(); |
return count; |
return size; |
} |
/** @} |
/branches/dynload/kernel/generic/src/console/cmd.c |
---|
31,8 → 31,8 |
*/ |
/** |
* @file cmd.c |
* @brief Kernel console command wrappers. |
* @file cmd.c |
* @brief Kernel console command wrappers. |
* |
* This file is meant to contain all wrapper functions for |
* all kconsole commands. The point is in separating |
64,7 → 64,7 |
#include <proc/task.h> |
#include <ipc/ipc.h> |
#include <ipc/irq.h> |
#include <event/event.h> |
#include <ipc/event.h> |
#include <symtab.h> |
#include <errno.h> |
513,14 → 513,14 |
spinlock_lock(&cmd_lock); |
link_t *cur; |
size_t len = 0; |
count_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); |
spinlock_lock(&hlp->lock); |
if (strlen(hlp->name) > len) |
len = strlen(hlp->name); |
if (str_length(hlp->name) > len) |
len = str_length(hlp->name); |
spinlock_unlock(&hlp->lock); |
} |
582,7 → 582,7 |
int cmd_desc(cmd_arg_t *argv) |
{ |
link_t *cur; |
spinlock_lock(&cmd_lock); |
for (cur = cmd_head.next; cur != &cmd_head; cur = cur->next) { |
590,8 → 590,8 |
hlp = list_get_instance(cur, cmd_info_t, link); |
spinlock_lock(&hlp->lock); |
if (strncmp(hlp->name, (const char *) argv->buffer, strlen(hlp->name)) == 0) { |
if (str_lcmp(hlp->name, (const char *) argv->buffer, str_length(hlp->name)) == 0) { |
printf("%s - %s\n", hlp->name, hlp->description); |
if (hlp->help) |
hlp->help(); |
598,12 → 598,12 |
spinlock_unlock(&hlp->lock); |
break; |
} |
spinlock_unlock(&hlp->lock); |
} |
spinlock_unlock(&cmd_lock); |
return 1; |
} |
956,6 → 956,7 |
release_console(); |
event_notify_0(EVENT_KCONSOLE); |
indev_pop_character(stdin); |
return 1; |
} |
969,11 → 970,11 |
*/ |
int cmd_tests(cmd_arg_t *argv) |
{ |
size_t len = 0; |
count_t len = 0; |
test_t *test; |
for (test = tests; test->name != NULL; test++) { |
if (strlen(test->name) > len) |
len = strlen(test->name); |
if (str_length(test->name) > len) |
len = str_length(test->name); |
} |
for (test = tests; test->name != NULL; test++) |
996,7 → 997,8 |
interrupts_restore(ipl); |
/* Execute the test */ |
char * ret = test->entry(false); |
test_quiet = false; |
char *ret = test->entry(); |
/* Update and read thread accounting */ |
ipl = interrupts_disable(); |
1048,7 → 1050,8 |
interrupts_restore(ipl); |
/* Execute the test */ |
char * ret = test->entry(true); |
test_quiet = true; |
char * ret = test->entry(); |
/* Update and read thread accounting */ |
ipl = interrupts_disable(); |
1096,7 → 1099,7 |
{ |
test_t *test; |
if (strcmp((char *) argv->buffer, "*") == 0) { |
if (str_cmp((char *) argv->buffer, "*") == 0) { |
for (test = tests; test->name != NULL; test++) { |
if (test->safe) { |
printf("\n"); |
1108,7 → 1111,7 |
bool fnd = false; |
for (test = tests; test->name != NULL; test++) { |
if (strcmp(test->name, (char *) argv->buffer) == 0) { |
if (str_cmp(test->name, (char *) argv->buffer) == 0) { |
fnd = true; |
run_test(test); |
break; |
1133,24 → 1136,33 |
test_t *test; |
uint32_t cnt = argv[1].intval; |
bool fnd = false; |
for (test = tests; test->name != NULL; test++) { |
if (strcmp(test->name, (char *) argv->buffer) == 0) { |
fnd = true; |
if (test->safe) |
run_bench(test, cnt); |
else |
printf("Unsafe test\n"); |
break; |
if (str_cmp((char *) argv->buffer, "*") == 0) { |
for (test = tests; test->name != NULL; test++) { |
if (test->safe) { |
if (!run_bench(test, cnt)) |
break; |
} |
} |
} else { |
bool fnd = false; |
for (test = tests; test->name != NULL; test++) { |
if (str_cmp(test->name, (char *) argv->buffer) == 0) { |
fnd = true; |
if (test->safe) |
run_bench(test, cnt); |
else |
printf("Unsafe test\n"); |
break; |
} |
} |
if (!fnd) |
printf("Unknown test\n"); |
} |
if (!fnd) |
printf("Unknown test\n"); |
return 1; |
} |
/branches/dynload/kernel/generic/src/console/chardev.c |
---|
35,6 → 35,9 |
#include <console/chardev.h> |
#include <synch/waitq.h> |
#include <synch/spinlock.h> |
#include <print.h> |
#include <func.h> |
#include <arch.h> |
/** Initialize input character device. |
* |
59,7 → 62,7 |
* @param ch Character being pushed. |
* |
*/ |
void indev_push_character(indev_t *indev, uint8_t ch) |
void indev_push_character(indev_t *indev, wchar_t ch) |
{ |
ASSERT(indev); |
79,6 → 82,46 |
spinlock_unlock(&indev->lock); |
} |
/** Pop character from input character device. |
* |
* @param indev Input character device. |
* |
* @return Character read. |
* |
*/ |
wchar_t indev_pop_character(indev_t *indev) |
{ |
if (atomic_get(&haltstate)) { |
/* If we are here, we are hopefully on the processor that |
* issued the 'halt' command, so proceed to read the character |
* directly from input |
*/ |
if (check_poll(indev)) |
return indev->op->poll(indev); |
/* No other way of interacting with user */ |
interrupts_disable(); |
if (CPU) |
printf("cpu%u: ", CPU->id); |
else |
printf("cpu: "); |
printf("halted (no polling input)\n"); |
cpu_halt(); |
} |
waitq_sleep(&indev->wq); |
ipl_t ipl = interrupts_disable(); |
spinlock_lock(&indev->lock); |
wchar_t ch = indev->buffer[(indev->index - indev->counter) % INDEV_BUFLEN]; |
indev->counter--; |
spinlock_unlock(&indev->lock); |
interrupts_restore(ipl); |
return ch; |
} |
/** Initialize output character device. |
* |
* @param outdev Output character device. |
93,5 → 136,16 |
outdev->op = op; |
} |
bool check_poll(indev_t *indev) |
{ |
if (indev == NULL) |
return false; |
if (indev->op == NULL) |
return false; |
return (indev->op->poll != NULL); |
} |
/** @} |
*/ |
/branches/dynload/kernel/generic/src/console/kconsole.c |
---|
31,10 → 31,11 |
*/ |
/** |
* @file kconsole.c |
* @brief Kernel console. |
* @file kconsole.c |
* @brief Kernel console. |
* |
* This file contains kernel thread managing the kernel console. |
* |
*/ |
#include <console/kconsole.h> |
56,6 → 57,7 |
#include <symtab.h> |
#include <errno.h> |
#include <putchar.h> |
#include <string.h> |
/** Simple kernel console. |
* |
64,7 → 66,7 |
* but makes it possible for other kernel subsystems to |
* register their own commands. |
*/ |
/** Locking. |
* |
* There is a list of cmd_info_t structures. This list |
79,15 → 81,13 |
* When locking two cmd info structures, structure with |
* lower address must be locked first. |
*/ |
SPINLOCK_INITIALIZE(cmd_lock); /**< Lock protecting command list. */ |
LIST_INITIALIZE(cmd_head); /**< Command list. */ |
static cmd_info_t *parse_cmdline(char *cmdline, size_t len); |
static bool parse_argument(char *cmdline, size_t len, index_t *start, |
index_t *end); |
static char history[KCONSOLE_HISTORY][MAX_CMDLINE] = {}; |
SPINLOCK_INITIALIZE(cmd_lock); /**< Lock protecting command list. */ |
LIST_INITIALIZE(cmd_head); /**< Command list. */ |
static wchar_t history[KCONSOLE_HISTORY][MAX_CMDLINE] = {}; |
static count_t history_pos = 0; |
/** Initialize kconsole data structures |
* |
* This is the most basic initialization, almost no |
97,10 → 97,10 |
void kconsole_init(void) |
{ |
unsigned int i; |
cmd_init(); |
for (i = 0; i < KCONSOLE_HISTORY; i++) |
history[i][0] = '\0'; |
history[i][0] = 0; |
} |
/** Register kconsole command. |
107,9 → 107,10 |
* |
* @param cmd Structure describing the command. |
* |
* @return 0 on failure, 1 on success. |
* @return False on failure, true on success. |
* |
*/ |
int cmd_register(cmd_info_t *cmd) |
bool cmd_register(cmd_info_t *cmd) |
{ |
link_t *cur; |
119,16 → 120,14 |
* Make sure the command is not already listed. |
*/ |
for (cur = cmd_head.next; cur != &cmd_head; cur = cur->next) { |
cmd_info_t *hlp; |
cmd_info_t *hlp = list_get_instance(cur, cmd_info_t, link); |
hlp = list_get_instance(cur, cmd_info_t, link); |
if (hlp == cmd) { |
/* The command is already there. */ |
spinlock_unlock(&cmd_lock); |
return 0; |
return false; |
} |
/* Avoid deadlock. */ |
if (hlp < cmd) { |
spinlock_lock(&hlp->lock); |
137,13 → 136,13 |
spinlock_lock(&cmd->lock); |
spinlock_lock(&hlp->lock); |
} |
if ((strncmp(hlp->name, cmd->name, max(strlen(cmd->name), |
strlen(hlp->name))) == 0)) { |
if (str_cmp(hlp->name, cmd->name) == 0) { |
/* The command is already there. */ |
spinlock_unlock(&hlp->lock); |
spinlock_unlock(&cmd->lock); |
spinlock_unlock(&cmd_lock); |
return 0; |
return false; |
} |
spinlock_unlock(&hlp->lock); |
156,11 → 155,11 |
list_append(&cmd->link, &cmd_head); |
spinlock_unlock(&cmd_lock); |
return 1; |
return true; |
} |
/** Print count times a character */ |
static void rdln_print_c(wchar_t ch, count_t count) |
static void print_cc(wchar_t ch, count_t count) |
{ |
count_t i; |
for (i = 0; i < count; i++) |
167,313 → 166,265 |
putchar(ch); |
} |
/** Insert character to string */ |
static void insert_char(char *str, char ch, int pos) |
/** Try to find a command beginning with prefix */ |
static const char *cmdtab_search_one(const char *name, link_t **startpos) |
{ |
int i; |
count_t namelen = str_length(name); |
for (i = strlen(str); i > pos; i--) |
str[i] = str[i - 1]; |
str[pos] = ch; |
} |
/** Try to find a command beginning with prefix */ |
static const char *cmdtab_search_one(const char *name,link_t **startpos) |
{ |
size_t namelen = strlen(name); |
const char *curname; |
spinlock_lock(&cmd_lock); |
if (!*startpos) |
if (*startpos == NULL) |
*startpos = cmd_head.next; |
for (; *startpos != &cmd_head; *startpos = (*startpos)->next) { |
cmd_info_t *hlp; |
hlp = list_get_instance(*startpos, cmd_info_t, link); |
curname = hlp->name; |
if (strlen(curname) < namelen) |
cmd_info_t *hlp = list_get_instance(*startpos, cmd_info_t, link); |
const char *curname = hlp->name; |
if (str_length(curname) < namelen) |
continue; |
if (strncmp(curname, name, namelen) == 0) { |
spinlock_unlock(&cmd_lock); |
return curname+namelen; |
if (str_lcmp(curname, name, namelen) == 0) { |
spinlock_unlock(&cmd_lock); |
return (curname + str_lsize(curname, namelen)); |
} |
} |
spinlock_unlock(&cmd_lock); |
spinlock_unlock(&cmd_lock); |
return NULL; |
} |
/** Command completion of the commands |
/** Command completion of the commands |
* |
* @param name - string to match, changed to hint on exit |
* @return number of found matches |
* @param name String to match, changed to hint on exit |
* @param size Input buffer size |
* |
* @return Number of found matches |
* |
*/ |
static int cmdtab_compl(char *name) |
static int cmdtab_compl(char *input, size_t size) |
{ |
static char output[/*MAX_SYMBOL_NAME*/128 + 1]; |
link_t *startpos = NULL; |
const char *foundtxt; |
int found = 0; |
int i; |
output[0] = '\0'; |
while ((foundtxt = cmdtab_search_one(name, &startpos))) { |
startpos = startpos->next; |
if (!found) |
strncpy(output, foundtxt, strlen(foundtxt) + 1); |
else { |
for (i = 0; output[i] && foundtxt[i] && |
output[i] == foundtxt[i]; i++) |
; |
output[i] = '\0'; |
} |
const char *name = input; |
count_t found = 0; |
link_t *pos = NULL; |
const char *hint; |
char output[MAX_CMDLINE]; |
output[0] = 0; |
while ((hint = cmdtab_search_one(name, &pos))) { |
if ((found == 0) || (str_length(output) > str_length(hint))) |
str_cpy(output, MAX_CMDLINE, hint); |
pos = pos->next; |
found++; |
} |
if (!found) |
return 0; |
if (found > 1 && !strlen(output)) { |
if ((found > 1) && (str_length(output) != 0)) { |
printf("\n"); |
startpos = NULL; |
while ((foundtxt = cmdtab_search_one(name, &startpos))) { |
cmd_info_t *hlp; |
hlp = list_get_instance(startpos, cmd_info_t, link); |
printf("%s - %s\n", hlp->name, hlp->description); |
startpos = startpos->next; |
pos = NULL; |
while ((hint = cmdtab_search_one(name, &pos))) { |
cmd_info_t *hlp = list_get_instance(pos, cmd_info_t, link); |
printf("%s (%s)\n", hlp->name, hlp->description); |
pos = pos->next; |
} |
} |
strncpy(name, output, 128/*MAX_SYMBOL_NAME*/); |
if (found > 0) |
str_cpy(input, size, output); |
return found; |
} |
static char *clever_readline(const char *prompt, indev_t *input) |
static wchar_t *clever_readline(const char *prompt, indev_t *indev) |
{ |
static int histposition = 0; |
static char tmp[MAX_CMDLINE + 1]; |
int curlen = 0, position = 0; |
char *current = history[histposition]; |
int i; |
char mod; /* Command Modifier */ |
char c; |
printf("%s> ", prompt); |
while (1) { |
c = _getc(input); |
if (c == '\n') { |
putchar(c); |
count_t position = 0; |
wchar_t *current = history[history_pos]; |
current[0] = 0; |
while (true) { |
wchar_t ch = indev_pop_character(indev); |
if (ch == '\n') { |
/* Enter */ |
putchar(ch); |
break; |
} |
if (c == '\b') { /* Backspace */ |
if (ch == '\b') { |
/* Backspace */ |
if (position == 0) |
continue; |
for (i = position; i < curlen; i++) |
current[i - 1] = current[i]; |
curlen--; |
position--; |
putchar('\b'); |
for (i = position; i < curlen; i++) |
putchar(current[i]); |
putchar(' '); |
rdln_print_c('\b', curlen - position + 1); |
continue; |
if (wstr_remove(current, position - 1)) { |
position--; |
putchar('\b'); |
printf("%ls ", current + position); |
print_cc('\b', wstr_length(current) - position + 1); |
continue; |
} |
} |
if (c == '\t') { /* Tabulator */ |
int found; |
if (ch == '\t') { |
/* Tab completion */ |
/* Move to the end of the word */ |
for (; position < curlen && current[position] != ' '; |
for (; (current[position] != 0) && (!isspace(current[position])); |
position++) |
putchar(current[position]); |
/* Copy to tmp last word */ |
for (i = position - 1; i >= 0 && current[i] != ' '; i--) |
; |
/* If word begins with * or &, skip it */ |
if (tmp[0] == '*' || tmp[0] == '&') |
for (i = 1; tmp[i]; i++) |
tmp[i - 1] = tmp[i]; |
i++; /* I is at the start of the word */ |
strncpy(tmp, current + i, position - i + 1); |
if (i == 0) { /* Command completion */ |
found = cmdtab_compl(tmp); |
} else { /* Symtab completion */ |
found = symtab_compl(tmp); |
if (position == 0) |
continue; |
/* Find the beginning of the word |
and copy it to tmp */ |
count_t beg; |
for (beg = position - 1; (beg > 0) && (!isspace(current[beg])); |
beg--); |
if (isspace(current[beg])) |
beg++; |
char tmp[STR_BOUNDS(MAX_CMDLINE)]; |
wstr_nstr(tmp, current + beg, position - beg + 1); |
int found; |
if (beg == 0) { |
/* Command completion */ |
found = cmdtab_compl(tmp, STR_BOUNDS(MAX_CMDLINE)); |
} else { |
/* Symbol completion */ |
found = symtab_compl(tmp, STR_BOUNDS(MAX_CMDLINE)); |
} |
if (found == 0) |
if (found == 0) |
continue; |
for (i = 0; tmp[i] && curlen < MAX_CMDLINE; |
i++, curlen++) |
insert_char(current, tmp[i], i + position); |
if (strlen(tmp) || found == 1) { /* If we have a hint */ |
for (i = position; i < curlen; i++) |
putchar(current[i]); |
position += strlen(tmp); |
/* Add space to end */ |
if (found == 1 && position == curlen && |
curlen < MAX_CMDLINE) { |
current[position] = ' '; |
curlen++; |
if (found > 1) { |
/* No unique hint, list was printed */ |
printf("%s> ", prompt); |
printf("%ls", current); |
print_cc('\b', wstr_length(current) - position); |
continue; |
} |
/* We have a hint */ |
size_t off = 0; |
count_t i = 0; |
while ((ch = str_decode(tmp, &off, STR_NO_LIMIT)) != 0) { |
if (!wstr_linsert(current, ch, position + i, MAX_CMDLINE)) |
break; |
i++; |
} |
printf("%ls", current + position); |
position += str_length(tmp); |
print_cc('\b', wstr_length(current) - position); |
if (position == wstr_length(current)) { |
/* Insert a space after the last completed argument */ |
if (wstr_linsert(current, ' ', position, MAX_CMDLINE)) { |
printf("%ls", current + position); |
position++; |
putchar(' '); |
} |
} else { /* No hint, table was printed */ |
printf("%s> ", prompt); |
for (i = 0; i < curlen; i++) |
putchar(current[i]); |
position += strlen(tmp); |
} |
rdln_print_c('\b', curlen - position); |
continue; |
} |
if (c == 0x1b) { /* Special command */ |
mod = _getc(input); |
c = _getc(input); |
if (mod != 0x5b && mod != 0x4f) |
continue; |
if (c == 0x33 && _getc(input) == 0x7e) { |
/* Delete */ |
if (position == curlen) |
continue; |
for (i = position + 1; i < curlen; i++) { |
putchar(current[i]); |
current[i - 1] = current[i]; |
} |
putchar(' '); |
rdln_print_c('\b', curlen - position); |
curlen--; |
} else if (c == 0x48) { /* Home */ |
rdln_print_c('\b', position); |
position = 0; |
} else if (c == 0x46) { /* End */ |
for (i = position; i < curlen; i++) |
putchar(current[i]); |
position = curlen; |
} else if (c == 0x44) { /* Left */ |
if (position > 0) { |
putchar('\b'); |
position--; |
} |
continue; |
} else if (c == 0x43) { /* Right */ |
if (position < curlen) { |
putchar(current[position]); |
position++; |
} |
continue; |
} else if (c == 0x41 || c == 0x42) { |
/* Up, down */ |
rdln_print_c('\b', position); |
rdln_print_c(' ', curlen); |
rdln_print_c('\b', curlen); |
if (c == 0x41) /* Up */ |
histposition--; |
else |
histposition++; |
if (histposition < 0) { |
histposition = KCONSOLE_HISTORY - 1; |
} else { |
histposition = |
histposition % KCONSOLE_HISTORY; |
} |
current = history[histposition]; |
printf("%s", current); |
curlen = strlen(current); |
position = curlen; |
continue; |
if (ch == U_LEFT_ARROW) { |
/* Left */ |
if (position > 0) { |
putchar('\b'); |
position--; |
} |
continue; |
} |
if (curlen >= MAX_CMDLINE) |
if (ch == U_RIGHT_ARROW) { |
/* Right */ |
if (position < wstr_length(current)) { |
putchar(current[position]); |
position++; |
} |
continue; |
insert_char(current, c, position); |
curlen++; |
for (i = position; i < curlen; i++) |
putchar(current[i]); |
position++; |
rdln_print_c('\b',curlen - position); |
} |
if (curlen) { |
histposition++; |
histposition = histposition % KCONSOLE_HISTORY; |
} |
current[curlen] = '\0'; |
return current; |
} |
bool kconsole_check_poll(void) |
{ |
return check_poll(stdin); |
} |
/** Kernel console prompt. |
* |
* @param prompt Kernel console prompt (e.g kconsole/panic). |
* @param msg Message to display in the beginning. |
* @param kcon Wait for keypress to show the prompt |
* and never exit. |
* |
*/ |
void kconsole(char *prompt, char *msg, bool kcon) |
{ |
cmd_info_t *cmd_info; |
count_t len; |
char *cmdline; |
if (!stdin) { |
LOG("No stdin for kernel console"); |
return; |
} |
if (msg) |
printf("%s", msg); |
if (kcon) |
_getc(stdin); |
else |
printf("Type \"exit\" to leave the console.\n"); |
while (true) { |
cmdline = clever_readline((char *) prompt, stdin); |
len = strlen(cmdline); |
if (!len) |
} |
if ((ch == U_UP_ARROW) || (ch == U_DOWN_ARROW)) { |
/* Up, down */ |
print_cc('\b', position); |
print_cc(' ', wstr_length(current)); |
print_cc('\b', wstr_length(current)); |
if (ch == U_UP_ARROW) { |
/* Up */ |
if (history_pos == 0) |
history_pos = KCONSOLE_HISTORY - 1; |
else |
history_pos--; |
} else { |
/* Down */ |
history_pos++; |
history_pos = history_pos % KCONSOLE_HISTORY; |
} |
current = history[history_pos]; |
printf("%ls", current); |
position = wstr_length(current); |
continue; |
} |
if ((!kcon) && (len == 4) && (strncmp(cmdline, "exit", 4) == 0)) |
break; |
if (ch == U_HOME_ARROW) { |
/* Home */ |
print_cc('\b', position); |
position = 0; |
continue; |
} |
cmd_info = parse_cmdline(cmdline, len); |
if (!cmd_info) |
if (ch == U_END_ARROW) { |
/* End */ |
printf("%ls", current + position); |
position = wstr_length(current); |
continue; |
} |
(void) cmd_info->func(cmd_info->argv); |
if (ch == U_DELETE) { |
/* Delete */ |
if (position == wstr_length(current)) |
continue; |
if (wstr_remove(current, position)) { |
printf("%ls ", current + position); |
print_cc('\b', wstr_length(current) - position + 1); |
} |
continue; |
} |
if (wstr_linsert(current, ch, position, MAX_CMDLINE)) { |
printf("%ls", current + position); |
position++; |
print_cc('\b', wstr_length(current) - position); |
} |
} |
if (wstr_length(current) > 0) { |
history_pos++; |
history_pos = history_pos % KCONSOLE_HISTORY; |
} |
return current; |
} |
/** Kernel console managing thread. |
* |
*/ |
void kconsole_thread(void *data) |
bool kconsole_check_poll(void) |
{ |
kconsole("kconsole", "Kernel console ready (press any key to activate)\n", true); |
return check_poll(stdin); |
} |
static int parse_int_arg(char *text, size_t len, unative_t *result) |
static bool parse_int_arg(const char *text, size_t len, unative_t *result) |
{ |
uintptr_t symaddr; |
bool isaddr = false; |
bool isptr = false; |
int rc; |
static char symname[MAX_SYMBOL_NAME]; |
/* If we get a name, try to find it in symbol table */ |
if (text[0] == '&') { |
485,67 → 436,113 |
text++; |
len--; |
} |
if (text[0] < '0' || text[0] > '9') { |
strncpy(symname, text, min(len + 1, MAX_SYMBOL_NAME)); |
rc = symtab_addr_lookup(symname, &symaddr); |
if ((text[0] < '0') || (text[0] > '9')) { |
char symname[MAX_SYMBOL_NAME]; |
str_ncpy(symname, MAX_SYMBOL_NAME, text, len + 1); |
uintptr_t symaddr; |
int rc = symtab_addr_lookup(symname, &symaddr); |
switch (rc) { |
case ENOENT: |
printf("Symbol %s not found.\n", symname); |
return -1; |
return false; |
case EOVERFLOW: |
printf("Duplicate symbol %s.\n", symname); |
symtab_print_search(symname); |
return -1; |
default: |
return false; |
case ENOTSUP: |
printf("No symbol information available.\n"); |
return -1; |
return false; |
} |
if (isaddr) |
*result = (unative_t)symaddr; |
*result = (unative_t) symaddr; |
else if (isptr) |
*result = **((unative_t **)symaddr); |
*result = **((unative_t **) symaddr); |
else |
*result = *((unative_t *)symaddr); |
} else { /* It's a number - convert it */ |
*result = *((unative_t *) symaddr); |
} else { |
/* It's a number - convert it */ |
*result = atoi(text); |
if (isptr) |
*result = *((unative_t *)*result); |
*result = *((unative_t *) *result); |
} |
return true; |
} |
return 0; |
/** Parse argument. |
* |
* Find start and end positions of command line argument. |
* |
* @param cmdline Command line as read from the input device. |
* @param size Size (in bytes) of the string. |
* @param start On entry, 'start' contains pointer to the offset |
* of the first unprocessed character of cmdline. |
* On successful exit, it marks beginning of the next argument. |
* @param end Undefined on entry. On exit, 'end' is the offset of the first |
* character behind the next argument. |
* |
* @return False on failure, true on success. |
* |
*/ |
static bool parse_argument(const char *cmdline, size_t size, size_t *start, size_t *end) |
{ |
ASSERT(start != NULL); |
ASSERT(end != NULL); |
bool found_start = false; |
size_t offset = *start; |
size_t prev = *start; |
wchar_t ch; |
while ((ch = str_decode(cmdline, &offset, size)) != 0) { |
if (!found_start) { |
if (!isspace(ch)) { |
*start = prev; |
found_start = true; |
} |
} else { |
if (isspace(ch)) |
break; |
} |
prev = offset; |
} |
*end = prev; |
return found_start; |
} |
/** Parse command line. |
* |
* @param cmdline Command line as read from input device. |
* @param len Command line length. |
* @param cmdline Command line as read from input device. |
* @param size Size (in bytes) of the string. |
* |
* @return Structure describing the command. |
* |
*/ |
cmd_info_t *parse_cmdline(char *cmdline, size_t len) |
static cmd_info_t *parse_cmdline(const char *cmdline, size_t size) |
{ |
index_t start = 0, end = 0; |
cmd_info_t *cmd = NULL; |
link_t *cur; |
count_t i; |
int error = 0; |
if (!parse_argument(cmdline, len, &start, &end)) { |
size_t start = 0; |
size_t end = 0; |
if (!parse_argument(cmdline, size, &start, &end)) { |
/* Command line did not contain alphanumeric word. */ |
return NULL; |
} |
spinlock_lock(&cmd_lock); |
cmd_info_t *cmd = NULL; |
link_t *cur; |
for (cur = cmd_head.next; cur != &cmd_head; cur = cur->next) { |
cmd_info_t *hlp; |
hlp = list_get_instance(cur, cmd_info_t, link); |
cmd_info_t *hlp = list_get_instance(cur, cmd_info_t, link); |
spinlock_lock(&hlp->lock); |
if (strncmp(hlp->name, &cmdline[start], max(strlen(hlp->name), |
end - start + 1)) == 0) { |
if (str_lcmp(hlp->name, cmdline + start, |
max(str_length(hlp->name), |
str_nlength(cmdline + start, (count_t) (end - start) - 1))) == 0) { |
cmd = hlp; |
break; |
} |
553,7 → 550,7 |
spinlock_unlock(&hlp->lock); |
} |
spinlock_unlock(&cmd_lock); |
spinlock_unlock(&cmd_lock); |
if (!cmd) { |
/* Unknown command. */ |
560,7 → 557,7 |
printf("Unknown command.\n"); |
return NULL; |
} |
/* cmd == hlp is locked */ |
/* |
569,52 → 566,54 |
* converted to those specified in the cmd info |
* structure. |
*/ |
bool error = false; |
count_t i; |
for (i = 0; i < cmd->argc; i++) { |
char *buf; |
start = end + 1; |
if (!parse_argument(cmdline, len, &start, &end)) { |
start = end; |
if (!parse_argument(cmdline, size, &start, &end)) { |
printf("Too few arguments.\n"); |
spinlock_unlock(&cmd->lock); |
return NULL; |
} |
error = 0; |
char *buf; |
switch (cmd->argv[i].type) { |
case ARG_TYPE_STRING: |
buf = (char *) cmd->argv[i].buffer; |
strncpy(buf, (const char *) &cmdline[start], |
min((end - start) + 2, cmd->argv[i].len)); |
buf[min((end - start) + 1, cmd->argv[i].len - 1)] = |
'\0'; |
str_ncpy(buf, cmd->argv[i].len, cmdline + start, |
end - start); |
break; |
case ARG_TYPE_INT: |
if (parse_int_arg(cmdline + start, end - start + 1, |
case ARG_TYPE_INT: |
if (!parse_int_arg(cmdline + start, end - start, |
&cmd->argv[i].intval)) |
error = 1; |
error = true; |
break; |
case ARG_TYPE_VAR: |
if (start != end && cmdline[start] == '"' && |
cmdline[end] == '"') { |
buf = (char *) cmd->argv[i].buffer; |
strncpy(buf, (const char *) &cmdline[start + 1], |
min((end-start), cmd->argv[i].len)); |
buf[min((end - start), cmd->argv[i].len - 1)] = |
'\0'; |
cmd->argv[i].intval = (unative_t) buf; |
cmd->argv[i].vartype = ARG_TYPE_STRING; |
} else if (!parse_int_arg(cmdline + start, |
end - start + 1, &cmd->argv[i].intval)) { |
if ((start < end - 1) && (cmdline[start] == '"')) { |
if (cmdline[end - 1] == '"') { |
buf = (char *) cmd->argv[i].buffer; |
str_ncpy(buf, cmd->argv[i].len, |
cmdline + start + 1, |
(end - start) - 1); |
cmd->argv[i].intval = (unative_t) buf; |
cmd->argv[i].vartype = ARG_TYPE_STRING; |
} else { |
printf("Wrong synxtax.\n"); |
error = true; |
} |
} else if (parse_int_arg(cmdline + start, |
end - start, &cmd->argv[i].intval)) { |
cmd->argv[i].vartype = ARG_TYPE_INT; |
} else { |
printf("Unrecognized variable argument.\n"); |
error = 1; |
error = true; |
} |
break; |
case ARG_TYPE_INVALID: |
default: |
printf("invalid argument type\n"); |
error = 1; |
printf("Invalid argument type\n"); |
error = true; |
break; |
} |
} |
624,8 → 623,8 |
return NULL; |
} |
start = end + 1; |
if (parse_argument(cmdline, len, &start, &end)) { |
start = end; |
if (parse_argument(cmdline, size, &start, &end)) { |
printf("Too many arguments.\n"); |
spinlock_unlock(&cmd->lock); |
return NULL; |
635,42 → 634,55 |
return cmd; |
} |
/** Parse argument. |
/** Kernel console prompt. |
* |
* Find start and end positions of command line argument. |
* @param prompt Kernel console prompt (e.g kconsole/panic). |
* @param msg Message to display in the beginning. |
* @param kcon Wait for keypress to show the prompt |
* and never exit. |
* |
* @param cmdline Command line as read from the input device. |
* @param len Number of characters in cmdline. |
* @param start On entry, 'start' contains pointer to the index |
* of first unprocessed character of cmdline. |
* On successful exit, it marks beginning of the next argument. |
* @param end Undefined on entry. On exit, 'end' points to the last character |
* of the next argument. |
* |
* @return false on failure, true on success. |
*/ |
bool parse_argument(char *cmdline, size_t len, index_t *start, index_t *end) |
void kconsole(char *prompt, char *msg, bool kcon) |
{ |
index_t i; |
bool found_start = false; |
if (!stdin) { |
LOG("No stdin for kernel console"); |
return; |
} |
ASSERT(start != NULL); |
ASSERT(end != NULL); |
if (msg) |
printf("%s", msg); |
for (i = *start; i < len; i++) { |
if (!found_start) { |
if (isspace(cmdline[i])) |
(*start)++; |
else |
found_start = true; |
} else { |
if (isspace(cmdline[i])) |
break; |
} |
if (kcon) |
indev_pop_character(stdin); |
else |
printf("Type \"exit\" to leave the console.\n"); |
while (true) { |
wchar_t *tmp = clever_readline((char *) prompt, stdin); |
count_t len = wstr_length(tmp); |
if (!len) |
continue; |
char cmdline[STR_BOUNDS(MAX_CMDLINE)]; |
wstr_nstr(cmdline, tmp, STR_BOUNDS(MAX_CMDLINE)); |
if ((!kcon) && (len == 4) && (str_lcmp(cmdline, "exit", 4) == 0)) |
break; |
cmd_info_t *cmd_info = parse_cmdline(cmdline, STR_BOUNDS(MAX_CMDLINE)); |
if (!cmd_info) |
continue; |
(void) cmd_info->func(cmd_info->argv); |
} |
*end = i - 1; |
} |
return found_start; |
/** Kernel console managing thread. |
* |
*/ |
void kconsole_thread(void *data) |
{ |
kconsole("kconsole", "Kernel console ready (press any key to activate)\n", true); |
} |
/** @} |
/branches/dynload/kernel/generic/src/printf/vprintf.c |
---|
43,14 → 43,13 |
SPINLOCK_INITIALIZE(printf_lock); /**< vprintf spinlock */ |
static int vprintf_write_utf8(const char *str, size_t size, void *data) |
static int vprintf_str_write(const char *str, size_t size, void *data) |
{ |
index_t index = 0; |
index_t chars = 0; |
size_t offset = 0; |
count_t chars = 0; |
while (index < size) { |
putchar(utf8_decode(str, &index, size - 1)); |
index++; |
while (offset < size) { |
putchar(str_decode(str, &offset, size)); |
chars++; |
} |
57,27 → 56,28 |
return chars; |
} |
static int vprintf_write_utf32(const wchar_t *str, size_t size, void *data) |
static int vprintf_wstr_write(const wchar_t *str, size_t size, void *data) |
{ |
index_t index = 0; |
size_t offset = 0; |
count_t chars = 0; |
while (index < (size / sizeof(wchar_t))) { |
putchar(str[index]); |
index++; |
while (offset < size) { |
putchar(str[chars]); |
chars++; |
offset += sizeof(wchar_t); |
} |
return index; |
return chars; |
} |
int puts(const char *str) |
{ |
index_t index = 0; |
index_t chars = 0; |
size_t offset = 0; |
count_t chars = 0; |
wchar_t uc; |
while ((uc = utf8_decode(str, &index, UTF8_NO_LIMIT)) != 0) { |
while ((uc = str_decode(str, &offset, STR_NO_LIMIT)) != 0) { |
putchar(uc); |
index++; |
chars++; |
} |
87,8 → 87,8 |
int vprintf(const char *fmt, va_list ap) |
{ |
printf_spec_t ps = { |
vprintf_write_utf8, |
vprintf_write_utf32, |
vprintf_str_write, |
vprintf_wstr_write, |
NULL |
}; |
/branches/dynload/kernel/generic/src/printf/vsnprintf.c |
---|
36,6 → 36,7 |
#include <printf/printf_core.h> |
#include <string.h> |
#include <memstr.h> |
#include <errno.h> |
typedef struct { |
size_t size; /* Total size of the buffer (in bytes) */ |
43,7 → 44,7 |
char *dst; /* Destination */ |
} vsnprintf_data_t; |
/** Write UTF-8 string to given buffer. |
/** Write string to given buffer. |
* |
* Write at most data->size plain characters including trailing zero. |
* According to C99, snprintf() has to return number of characters that |
51,16 → 52,16 |
* the return value is not the number of actually printed characters |
* but size of the input string. |
* |
* @param str Source UTF-8 string to print. |
* @param str Source string to print. |
* @param size Number of plain characters in str. |
* @param data Structure describing destination string, counter |
* of used space and total string size. |
* |
* @return Number of UTF-8 characters to print (not characters actually |
* @return Number of characters to print (not characters actually |
* printed). |
* |
*/ |
static int vsnprintf_write_utf8(const char *str, size_t size, vsnprintf_data_t *data) |
static int vsnprintf_str_write(const char *str, size_t size, vsnprintf_data_t *data) |
{ |
size_t left = data->size - data->len; |
77,7 → 78,7 |
} |
if (left <= size) { |
/* We have not enought space for whole string |
/* We do not have enough space for the whole string |
* with the trailing zero => print only a part |
* of string |
*/ |
84,13 → 85,10 |
index_t index = 0; |
while (index < size) { |
wchar_t uc = utf8_decode(str, &index, size - 1); |
wchar_t uc = str_decode(str, &index, size); |
if (!utf8_encode(uc, data->dst, &data->len, data->size - 2)) |
if (chr_encode(uc, data->dst, &data->len, data->size - 1) != EOK) |
break; |
data->len++; |
index++; |
} |
/* Put trailing zero at end, but not count it |
113,7 → 111,7 |
return ((int) size); |
} |
/** Write UTF-32 string to given buffer. |
/** Write wide string to given buffer. |
* |
* Write at most data->size plain characters including trailing zero. |
* According to C99, snprintf() has to return number of characters that |
121,16 → 119,16 |
* the return value is not the number of actually printed characters |
* but size of the input string. |
* |
* @param str Source UTF-32 string to print. |
* @param str Source wide string to print. |
* @param size Number of bytes in str. |
* @param data Structure describing destination string, counter |
* of used space and total string size. |
* |
* @return Number of UTF-8 characters to print (not characters actually |
* @return Number of wide characters to print (not characters actually |
* printed). |
* |
*/ |
static int vsnprintf_write_utf32(const wchar_t *str, size_t size, vsnprintf_data_t *data) |
static int vsnprintf_wstr_write(const wchar_t *str, size_t size, vsnprintf_data_t *data) |
{ |
index_t index = 0; |
149,10 → 147,9 |
return ((int) size); |
} |
if (!utf8_encode(str[index], data->dst, &data->len, data->size - 2)) |
if (chr_encode(str[index], data->dst, &data->len, data->size - 1) != EOK) |
break; |
data->len++; |
index++; |
} |
172,8 → 169,8 |
str |
}; |
printf_spec_t ps = { |
(int(*) (const char *, size_t, void *)) vsnprintf_write_utf8, |
(int(*) (const wchar_t *, size_t, void *)) vsnprintf_write_utf32, |
(int(*) (const char *, size_t, void *)) vsnprintf_str_write, |
(int(*) (const wchar_t *, size_t, void *)) vsnprintf_wstr_write, |
&data |
}; |
/branches/dynload/kernel/generic/src/printf/printf_core.c |
---|
81,53 → 81,54 |
static char nullstr[] = "(NULL)"; |
static char digits_small[] = "0123456789abcdef"; |
static char digits_big[] = "0123456789ABCDEF"; |
static char invalch = U_SPECIAL; |
/** Print one or more UTF-8 characters without adding newline. |
/** Print one or more characters without adding newline. |
* |
* @param buf Buffer holding UTF-8 characters with size of |
* @param buf Buffer holding characters with size of |
* at least size bytes. NULL is not allowed! |
* @param size Size of the buffer in bytes. |
* @param ps Output method and its data. |
* |
* @return Number of UTF-8 characters printed. |
* @return Number of characters printed. |
* |
*/ |
static int printf_putnchars_utf8(const char *buf, size_t size, |
static int printf_putnchars(const char *buf, size_t size, |
printf_spec_t *ps) |
{ |
return ps->write_utf8((void *) buf, size, ps->data); |
return ps->str_write((void *) buf, size, ps->data); |
} |
/** Print one or more UTF-32 characters without adding newline. |
/** Print one or more wide characters without adding newline. |
* |
* @param buf Buffer holding UTF-32 characters with size of |
* @param buf Buffer holding wide characters with size of |
* at least size bytes. NULL is not allowed! |
* @param size Size of the buffer in bytes. |
* @param ps Output method and its data. |
* |
* @return Number of UTF-32 characters printed. |
* @return Number of wide characters printed. |
* |
*/ |
static int printf_putnchars_utf32(const wchar_t *buf, size_t size, |
static int printf_wputnchars(const wchar_t *buf, size_t size, |
printf_spec_t *ps) |
{ |
return ps->write_utf32((void *) buf, size, ps->data); |
return ps->wstr_write((void *) buf, size, ps->data); |
} |
/** Print UTF-8 string without adding a newline. |
/** Print string without adding a newline. |
* |
* @param str UTF-8 string to print. |
* @param str String to print. |
* @param ps Write function specification and support data. |
* |
* @return Number of UTF-8 characters printed. |
* @return Number of characters printed. |
* |
*/ |
static int printf_putstr(const char *str, printf_spec_t *ps) |
{ |
if (str == NULL) |
return printf_putnchars_utf8(nullstr, strlen(nullstr), ps); |
return printf_putnchars(nullstr, str_size(nullstr), ps); |
return ps->write_utf8((void *) str, strlen(str), ps->data); |
return ps->str_write((void *) str, str_size(str), ps->data); |
} |
/** Print one ASCII character. |
141,14 → 142,14 |
static int printf_putchar(const char ch, printf_spec_t *ps) |
{ |
if (!ascii_check(ch)) |
return ps->write_utf8((void *) &invalch, 1, ps->data); |
return ps->str_write((void *) &invalch, 1, ps->data); |
return ps->write_utf8(&ch, 1, ps->data); |
return ps->str_write(&ch, 1, ps->data); |
} |
/** Print one UTF-32 character. |
/** Print one wide character. |
* |
* @param c UTF-32 character to be printed. |
* @param c Wide character to be printed. |
* @param ps Output method. |
* |
* @return Number of characters printed. |
156,10 → 157,10 |
*/ |
static int printf_putwchar(const wchar_t ch, printf_spec_t *ps) |
{ |
if (!unicode_check(ch)) |
return ps->write_utf8((void *) &invalch, 1, ps->data); |
if (!chr_check(ch)) |
return ps->str_write((void *) &invalch, 1, ps->data); |
return ps->write_utf32(&ch, sizeof(wchar_t), ps->data); |
return ps->wstr_write(&ch, sizeof(wchar_t), ps->data); |
} |
/** Print one formatted ASCII character. |
200,7 → 201,7 |
return (int) (counter + 1); |
} |
/** Print one formatted UTF-32 character. |
/** Print one formatted wide character. |
* |
* @param ch Character to print. |
* @param width Width modifier. |
238,26 → 239,27 |
return (int) (counter + 1); |
} |
/** Print UTF-8 string. |
/** Print string. |
* |
* @param str UTF-8 string to be printed. |
* @param str String to be printed. |
* @param width Width modifier. |
* @param precision Precision modifier. |
* @param flags Flags that modify the way the string is printed. |
* |
* @return Number of UTF-8 characters printed, negative value on failure. |
* @return Number of characters printed, negative value on failure. |
*/ |
static int print_utf8(char *str, int width, unsigned int precision, |
uint32_t flags, printf_spec_t *ps) |
static int print_str(char *str, int width, unsigned int precision, |
uint32_t flags, printf_spec_t *ps) |
{ |
if (str == NULL) |
return printf_putstr(nullstr, ps); |
/* Print leading spaces */ |
size_t size = strlen_utf8(str); |
/* Print leading spaces. */ |
count_t strw = str_length(str); |
if (precision == 0) |
precision = size; |
precision = strw; |
/* Left padding */ |
count_t counter = 0; |
width -= precision; |
if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) { |
266,42 → 268,49 |
counter++; |
} |
} |
/* Part of @a str fitting into the alloted space. */ |
int retval; |
size_t bytes = utf8_count_bytes(str, min(size, precision)); |
if ((retval = printf_putnchars_utf8(str, bytes, ps)) < 0) |
size_t size = str_lsize(str, precision); |
if ((retval = printf_putnchars(str, size, ps)) < 0) |
return -counter; |
counter += retval; |
/* Right padding */ |
while (width-- > 0) { |
if (printf_putchar(' ', ps) == 1) |
counter++; |
} |
return ((int) counter); |
} |
/** Print UTF-32 string. |
/** Print wide string. |
* |
* @param str UTF-32 string to be printed. |
* @param str Wide string to be printed. |
* @param width Width modifier. |
* @param precision Precision modifier. |
* @param flags Flags that modify the way the string is printed. |
* |
* @return Number of UTF-32 characters printed, negative value on failure. |
* @return Number of wide characters printed, negative value on failure. |
*/ |
static int print_utf32(wchar_t *str, int width, unsigned int precision, |
uint32_t flags, printf_spec_t *ps) |
static int print_wstr(wchar_t *str, int width, unsigned int precision, |
uint32_t flags, printf_spec_t *ps) |
{ |
if (str == NULL) |
return printf_putstr(nullstr, ps); |
/* Print leading spaces */ |
size_t size = strlen_utf32(str); |
if (*str == U_BOM) |
str++; |
/* Print leading spaces. */ |
size_t strw = wstr_length(str); |
if (precision == 0) |
precision = size; |
precision = strw; |
/* Left padding */ |
count_t counter = 0; |
width -= precision; |
if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) { |
311,18 → 320,20 |
} |
} |
/* Part of @a wstr fitting into the alloted space. */ |
int retval; |
size_t bytes = min(size, precision) * sizeof(wchar_t); |
if ((retval = printf_putnchars_utf32(str, bytes, ps)) < 0) |
size_t size = wstr_lsize(str, precision); |
if ((retval = printf_wputnchars(str, size, ps)) < 0) |
return -counter; |
counter += retval; |
/* Right padding */ |
while (width-- > 0) { |
if (printf_putchar(' ', ps) == 1) |
counter++; |
} |
return ((int) counter); |
} |
537,8 → 548,8 |
* - "h" Signed or unsigned short.@n |
* - "" Signed or unsigned int (default value).@n |
* - "l" Signed or unsigned long int.@n |
* If conversion is "c", the character is wchar_t (UTF-32).@n |
* If conversion is "s", the string is wchar_t * (UTF-32).@n |
* If conversion is "c", the character is wchar_t (wide character).@n |
* If conversion is "s", the string is wchar_t * (wide string).@n |
* - "ll" Signed or unsigned long long int.@n |
* |
* CONVERSION:@n |
546,15 → 557,12 |
* |
* - c Print single character. The character is expected to be plain |
* ASCII (e.g. only values 0 .. 127 are valid).@n |
* If type is "l", then the character is expected to be UTF-32 |
* If type is "l", then the character is expected to be wide character |
* (e.g. values 0 .. 0x10ffff are valid). |
* |
* - s Print zero terminated string. If a NULL value is passed as |
* value, "(NULL)" is printed instead.@n |
* The string is expected to be correctly encoded UTF-8 (or plain |
* ASCII, which is a subset of UTF-8).@n |
* If type is "l", then the string is expected to be correctly |
* encoded UTF-32. |
* If type is "l", then the string is expected to be wide string. |
* |
* - P, p Print value of a pointer. Void * value is expected and it is |
* printed in hexadecimal notation with prefix (as with \%#X / \%#x |
574,29 → 582,35 |
* - X, x Print hexadecimal number with upper- or lower-case. Prefix is |
* not printed by default. |
* |
* All other characters from fmt except the formatting directives are printed in |
* All other characters from fmt except the formatting directives are printed |
* verbatim. |
* |
* @param fmt Formatting NULL terminated string (UTF-8 or plain ASCII). |
* @param fmt Format NULL-terminated string. |
* |
* @return Number of UTF-8 characters printed, negative value on failure. |
* @return Number of characters printed, negative value on failure. |
* |
*/ |
int printf_core(const char *fmt, printf_spec_t *ps, va_list ap) |
{ |
index_t i = 0; /* Index of the currently processed character from fmt */ |
index_t j = 0; /* Index to the first not printed nonformating character */ |
size_t i; /* Index of the currently processed character from fmt */ |
size_t nxt = 0; /* Index of the next character from fmt */ |
size_t j = 0; /* Index to the first not printed nonformating character */ |
wchar_t uc; /* Current UTF-32 character decoded from fmt */ |
count_t counter = 0; /* Number of UTF-8 characters printed */ |
count_t counter = 0; /* Number of characters printed */ |
int retval; /* Return values from nested functions */ |
while ((uc = utf8_decode(fmt, &i, UTF8_NO_LIMIT)) != 0) { |
while (true) { |
i = nxt; |
wchar_t uc = str_decode(fmt, &nxt, STR_NO_LIMIT); |
if (uc == 0) |
break; |
/* Control character */ |
if (uc == '%') { |
/* Print common characters if any processed */ |
if (i > j) { |
if ((retval = printf_putnchars_utf8(&fmt[j], i - j, ps)) < 0) { |
if ((retval = printf_putnchars(&fmt[j], i - j, ps)) < 0) { |
/* Error */ |
counter = -counter; |
goto out; |
611,8 → 625,8 |
bool end = false; |
do { |
i++; |
uc = utf8_decode(fmt, &i, UTF8_NO_LIMIT); |
i = nxt; |
uc = str_decode(fmt, &nxt, STR_NO_LIMIT); |
switch (uc) { |
case '#': |
flags |= __PRINTF_FLAG_PREFIX; |
637,18 → 651,21 |
/* Width & '*' operator */ |
int width = 0; |
if (isdigit(uc)) { |
while ((uc = utf8_decode(fmt, &i, UTF8_NO_LIMIT)) != 0) { |
while (true) { |
width *= 10; |
width += uc - '0'; |
i = nxt; |
uc = str_decode(fmt, &nxt, STR_NO_LIMIT); |
if (uc == 0) |
break; |
if (!isdigit(uc)) |
break; |
width *= 10; |
width += uc - '0'; |
i++; |
} |
} else if (uc == '*') { |
/* Get width value from argument list */ |
i++; |
uc = utf8_decode(fmt, &i, UTF8_NO_LIMIT); |
i = nxt; |
uc = str_decode(fmt, &nxt, STR_NO_LIMIT); |
width = (int) va_arg(ap, int); |
if (width < 0) { |
/* Negative width sets '-' flag */ |
660,21 → 677,24 |
/* Precision and '*' operator */ |
int precision = 0; |
if (uc == '.') { |
i++; |
uc = utf8_decode(fmt, &i, UTF8_NO_LIMIT); |
i = nxt; |
uc = str_decode(fmt, &nxt, STR_NO_LIMIT); |
if (isdigit(uc)) { |
while ((uc = utf8_decode(fmt, &i, UTF8_NO_LIMIT)) != 0) { |
while (true) { |
precision *= 10; |
precision += uc - '0'; |
i = nxt; |
uc = str_decode(fmt, &nxt, STR_NO_LIMIT); |
if (uc == 0) |
break; |
if (!isdigit(uc)) |
break; |
precision *= 10; |
precision += uc - '0'; |
i++; |
} |
} else if (fmt[i] == '*') { |
} else if (uc == '*') { |
/* Get precision value from the argument list */ |
i++; |
uc = utf8_decode(fmt, &i, UTF8_NO_LIMIT); |
i = nxt; |
uc = str_decode(fmt, &nxt, STR_NO_LIMIT); |
precision = (int) va_arg(ap, int); |
if (precision < 0) { |
/* Ignore negative precision */ |
692,11 → 712,11 |
case 'h': |
/* Char or short */ |
qualifier = PrintfQualifierShort; |
i++; |
uc = utf8_decode(fmt, &i, UTF8_NO_LIMIT); |
i = nxt; |
uc = str_decode(fmt, &nxt, STR_NO_LIMIT); |
if (uc == 'h') { |
i++; |
uc = utf8_decode(fmt, &i, UTF8_NO_LIMIT); |
i = nxt; |
uc = str_decode(fmt, &nxt, STR_NO_LIMIT); |
qualifier = PrintfQualifierByte; |
} |
break; |
703,11 → 723,11 |
case 'l': |
/* Long or long long */ |
qualifier = PrintfQualifierLong; |
i++; |
uc = utf8_decode(fmt, &i, UTF8_NO_LIMIT); |
i = nxt; |
uc = str_decode(fmt, &nxt, STR_NO_LIMIT); |
if (uc == 'l') { |
i++; |
uc = utf8_decode(fmt, &i, UTF8_NO_LIMIT); |
i = nxt; |
uc = str_decode(fmt, &nxt, STR_NO_LIMIT); |
qualifier = PrintfQualifierLongLong; |
} |
break; |
724,9 → 744,9 |
*/ |
case 's': |
if (qualifier == PrintfQualifierLong) |
retval = print_utf32(va_arg(ap, wchar_t *), width, precision, flags, ps); |
retval = print_wstr(va_arg(ap, wchar_t *), width, precision, flags, ps); |
else |
retval = print_utf8(va_arg(ap, char *), width, precision, flags, ps); |
retval = print_str(va_arg(ap, char *), width, precision, flags, ps); |
if (retval < 0) { |
counter = -counter; |
734,7 → 754,7 |
} |
counter += retval; |
j = i + 1; |
j = nxt; |
goto next_char; |
case 'c': |
if (qualifier == PrintfQualifierLong) |
748,7 → 768,7 |
}; |
counter += retval; |
j = i + 1; |
j = nxt; |
goto next_char; |
/* |
852,15 → 872,14 |
} |
counter += retval; |
j = i + 1; |
j = nxt; |
} |
next_char: |
i++; |
; |
} |
if (i > j) { |
if ((retval = printf_putnchars_utf8(&fmt[j], i - j, ps)) < 0) { |
if ((retval = printf_putnchars(&fmt[j], i - j, ps)) < 0) { |
/* Error */ |
counter = -counter; |
goto out; |
/branches/dynload/kernel/generic/src/proc/task.c |
---|
151,7 → 151,7 |
ta->as = as; |
memcpy(ta->name, name, TASK_NAME_BUFLEN); |
ta->name[TASK_NAME_BUFLEN - 1] = '\0'; |
ta->name[TASK_NAME_BUFLEN - 1] = 0; |
atomic_set(&ta->refcount, 0); |
atomic_set(&ta->lifecount, 0); |
274,7 → 274,7 |
return (unative_t) rc; |
namebuf[name_len] = '\0'; |
strncpy(TASK->name, namebuf, TASK_NAME_BUFLEN); |
str_cpy(TASK->name, TASK_NAME_BUFLEN, namebuf); |
return EOK; |
} |
/branches/dynload/kernel/generic/src/proc/program.c |
---|
207,7 → 207,7 |
if (rc != 0) |
return (unative_t) rc; |
namebuf[name_len] = '\0'; |
namebuf[name_len] = 0; |
/* Spawn the new task. */ |
/branches/dynload/kernel/generic/src/proc/thread.c |
---|
316,7 → 316,7 |
interrupts_restore(ipl); |
memcpy(t->name, name, THREAD_NAME_BUFLEN); |
t->name[THREAD_NAME_BUFLEN - 1] = '\0'; |
t->name[THREAD_NAME_BUFLEN - 1] = 0; |
t->thread_code = func; |
t->thread_arg = arg; |
723,7 → 723,7 |
if (rc != 0) |
return (unative_t) rc; |
namebuf[name_len] = '\0'; |
namebuf[name_len] = 0; |
/* |
* In case of failure, kernel_uarg will be deallocated in this function. |
/branches/dynload/kernel/generic/src/lib/string.c |
---|
32,7 → 32,73 |
/** |
* @file |
* @brief Miscellaneous functions. |
* @brief String functions. |
* |
* Strings and characters use the Universal Character Set (UCS). The standard |
* strings, called just strings are encoded in UTF-8. Wide strings (encoded |
* in UTF-32) are supported to a limited degree. A single character is |
* represented as wchar_t.@n |
* |
* Overview of the terminology:@n |
* |
* Term Meaning |
* -------------------- ---------------------------------------------------- |
* byte 8 bits stored in uint8_t (unsigned 8 bit integer) |
* |
* character UTF-32 encoded Unicode character, stored in wchar_t |
* (signed 32 bit integer), code points 0 .. 1114111 |
* are valid |
* |
* ASCII character 7 bit encoded ASCII character, stored in char |
* (usually signed 8 bit integer), code points 0 .. 127 |
* are valid |
* |
* string UTF-8 encoded NULL-terminated Unicode string, char * |
* |
* wide string UTF-32 encoded NULL-terminated Unicode string, |
* wchar_t * |
* |
* [wide] string size number of BYTES in a [wide] string (excluding |
* the NULL-terminator), size_t |
* |
* [wide] string length number of CHARACTERS in a [wide] string (excluding |
* the NULL-terminator), count_t |
* |
* [wide] string width number of display cells on a monospace display taken |
* by a [wide] string, count_t |
* |
* |
* Overview of string metrics:@n |
* |
* Metric Abbrev. Type Meaning |
* ------ ------ ------ ------------------------------------------------- |
* 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 |
* null terminator) |
* |
* width w count_t number of display cells on a monospace display |
* taken by a string |
* |
* |
* Function naming prefixes:@n |
* |
* chr_ operate on characters |
* ascii_ operate on ASCII characters |
* str_ operate on strings |
* wstr_ operate on wide strings |
* |
* [w]str_[n|l|w] operate on a prefix limited by size, length |
* or width |
* |
* |
* A specific character inside a [wide] string can be referred to by:@n |
* |
* pointer (char *, wchar_t *) |
* byte offset (size_t) |
* character index (count_t) |
* |
*/ |
#include <string.h> |
40,378 → 106,607 |
#include <cpu.h> |
#include <arch/asm.h> |
#include <arch.h> |
#include <console/kconsole.h> |
#include <errno.h> |
#include <align.h> |
#include <debug.h> |
char invalch = '?'; |
/** Byte mask consisting of lowest @n bits (out of 8) */ |
#define LO_MASK_8(n) ((uint8_t) ((1 << (n)) - 1)) |
/** Decode a single UTF-8 character from a NULL-terminated string. |
/** Byte mask consisting of lowest @n bits (out of 32) */ |
#define LO_MASK_32(n) ((uint32_t) ((1 << (n)) - 1)) |
/** Byte mask consisting of highest @n bits (out of 8) */ |
#define HI_MASK_8(n) (~LO_MASK_8(8 - (n))) |
/** Number of data bits in a UTF-8 continuation byte */ |
#define CONT_BITS 6 |
/** Decode a single character from a string. |
* |
* Decode a single UTF-8 character from a plain char NULL-terminated |
* string. Decoding starts at @index and this index is incremented |
* if the current UTF-8 string is encoded in more than a single byte. |
* Decode a single character from a string of size @a size. Decoding starts |
* at @a offset and this offset is moved to the beginning of the next |
* character. In case of decoding error, offset generally advances at least |
* by one. However, offset is never moved beyond size. |
* |
* @param str Plain character NULL-terminated string. |
* @param index Index (counted in plain characters) where to start |
* the decoding. |
* @param limit Maximal allowed value of index. |
* @param str String (not necessarily NULL-terminated). |
* @param offset Byte offset in string where to start decoding. |
* @param size Size of the string (in bytes). |
* |
* @return Decoded character in UTF-32 or '?' if the encoding is wrong. |
* @return Value of decoded character, U_SPECIAL on decoding error or |
* NULL if attempt to decode beyond @a size. |
* |
*/ |
wchar_t utf8_decode(const char *str, index_t *index, index_t limit) |
wchar_t str_decode(const char *str, size_t *offset, size_t size) |
{ |
uint8_t c1; /* First plain character from str */ |
uint8_t c2; /* Second plain character from str */ |
uint8_t c3; /* Third plain character from str */ |
uint8_t c4; /* Fourth plain character from str */ |
if (*offset + 1 > size) |
return 0; |
if (*index > limit) |
return invalch; |
/* First byte read from string */ |
uint8_t b0 = (uint8_t) str[(*offset)++]; |
c1 = (uint8_t) str[*index]; |
/* Determine code length */ |
if ((c1 & 0x80) == 0) { |
/* Plain ASCII (code points 0 .. 127) */ |
return (wchar_t) c1; |
} |
unsigned int b0_bits; /* Data bits in first byte */ |
unsigned int cbytes; /* Number of continuation bytes */ |
if ((c1 & 0xe0) == 0xc0) { |
/* Code points 128 .. 2047 */ |
if (*index + 1 > limit) |
return invalch; |
c2 = (uint8_t) str[*index + 1]; |
if ((c2 & 0xc0) == 0x80) { |
(*index)++; |
return ((wchar_t) ((c1 & 0x1f) << 6) | (c2 & 0x3f)); |
} else |
return invalch; |
if ((b0 & 0x80) == 0) { |
/* 0xxxxxxx (Plain ASCII) */ |
b0_bits = 7; |
cbytes = 0; |
} else if ((b0 & 0xe0) == 0xc0) { |
/* 110xxxxx 10xxxxxx */ |
b0_bits = 5; |
cbytes = 1; |
} else if ((b0 & 0xf0) == 0xe0) { |
/* 1110xxxx 10xxxxxx 10xxxxxx */ |
b0_bits = 4; |
cbytes = 2; |
} else if ((b0 & 0xf8) == 0xf0) { |
/* 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */ |
b0_bits = 3; |
cbytes = 3; |
} else { |
/* 10xxxxxx -- unexpected continuation byte */ |
return U_SPECIAL; |
} |
if ((c1 & 0xf0) == 0xe0) { |
/* Code points 2048 .. 65535 */ |
if (*index + 2 > limit) |
return invalch; |
c2 = (uint8_t) str[*index + 1]; |
if ((c2 & 0xc0) == 0x80) { |
(*index)++; |
c3 = (uint8_t) str[*index + 1]; |
if ((c3 & 0xc0) == 0x80) { |
(*index)++; |
return ((wchar_t) ((c1 & 0x0f) << 12) | ((c2 & 0x3f) << 6) | (c3 & 0x3f)); |
} else |
return invalch; |
} else |
return invalch; |
} |
if (*offset + cbytes > size) |
return U_SPECIAL; |
if ((c1 & 0xf8) == 0xf0) { |
/* Code points 65536 .. 1114111 */ |
if (*index + 3 > limit) |
return invalch; |
wchar_t ch = b0 & LO_MASK_8(b0_bits); |
/* Decode continuation bytes */ |
while (cbytes > 0) { |
uint8_t b = (uint8_t) str[(*offset)++]; |
c2 = (uint8_t) str[*index + 1]; |
if ((c2 & 0xc0) == 0x80) { |
(*index)++; |
c3 = (uint8_t) str[*index + 1]; |
if ((c3 & 0xc0) == 0x80) { |
(*index)++; |
c4 = (uint8_t) str[*index + 1]; |
if ((c4 & 0xc0) == 0x80) { |
(*index)++; |
return ((wchar_t) ((c1 & 0x07) << 18) | ((c2 & 0x3f) << 12) | ((c3 & 0x3f) << 6) | (c4 & 0x3f)); |
} else |
return invalch; |
} else |
return invalch; |
} else |
return invalch; |
/* Must be 10xxxxxx */ |
if ((b & 0xc0) != 0x80) |
return U_SPECIAL; |
/* Shift data bits to ch */ |
ch = (ch << CONT_BITS) | (wchar_t) (b & LO_MASK_8(CONT_BITS)); |
cbytes--; |
} |
return invalch; |
return ch; |
} |
/** Encode a single UTF-32 character as UTF-8 |
/** Encode a single character to string representation. |
* |
* Encode a single UTF-32 character as UTF-8 and store it into |
* the given buffer at @index. Encoding starts at @index and |
* this index is incremented if the UTF-8 character takes |
* more than a single byte. |
* Encode a single character to string representation (i.e. UTF-8) and store |
* it into a buffer at @a offset. Encoding starts at @a offset and this offset |
* is moved to the position where the next character can be written to. |
* |
* @param ch Input UTF-32 character. |
* @param str Output buffer. |
* @param index Index (counted in plain characters) where to start |
* the encoding |
* @param limit Maximal allowed value of index. |
* @param ch Input character. |
* @param str Output buffer. |
* @param offset Byte offset where to start writing. |
* @param size Size of the output buffer (in bytes). |
* |
* @return True if the character was encoded or false if there is not |
* enought space in the output buffer or the character is invalid |
* Unicode code point. |
* |
* @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. |
*/ |
bool utf8_encode(const wchar_t ch, char *str, index_t *index, index_t limit) |
int chr_encode(wchar_t ch, char *str, size_t *offset, size_t size) |
{ |
if (*index > limit) |
return false; |
if (*offset >= size) |
return EOVERFLOW; |
if ((ch >= 0) && (ch <= 127)) { |
/* Plain ASCII (code points 0 .. 127) */ |
str[*index] = ch & 0x7f; |
return true; |
} |
if (!chr_check(ch)) |
return EINVAL; |
if ((ch >= 128) && (ch <= 2047)) { |
/* Code points 128 .. 2047 */ |
if (*index + 1 > limit) |
return false; |
str[*index] = 0xc0 | ((ch >> 6) & 0x1f); |
(*index)++; |
str[*index] = 0x80 | (ch & 0x3f); |
return true; |
} |
/* Unsigned version of ch (bit operations should only be done |
on unsigned types). */ |
uint32_t cc = (uint32_t) ch; |
if ((ch >= 2048) && (ch <= 65535)) { |
/* Code points 2048 .. 65535 */ |
if (*index + 2 > limit) |
return false; |
str[*index] = 0xe0 | ((ch >> 12) & 0x0f); |
(*index)++; |
str[*index] = 0x80 | ((ch >> 6) & 0x3f); |
(*index)++; |
str[*index] = 0x80 | (ch & 0x3f); |
return true; |
/* Determine how many continuation bytes are needed */ |
unsigned int b0_bits; /* Data bits in first byte */ |
unsigned int cbytes; /* Number of continuation bytes */ |
if ((cc & ~LO_MASK_32(7)) == 0) { |
b0_bits = 7; |
cbytes = 0; |
} else if ((cc & ~LO_MASK_32(11)) == 0) { |
b0_bits = 5; |
cbytes = 1; |
} else if ((cc & ~LO_MASK_32(16)) == 0) { |
b0_bits = 4; |
cbytes = 2; |
} else if ((cc & ~LO_MASK_32(21)) == 0) { |
b0_bits = 3; |
cbytes = 3; |
} else { |
/* Codes longer than 21 bits are not supported */ |
return EINVAL; |
} |
if ((ch >= 65536) && (ch <= 1114111)) { |
/* Code points 65536 .. 1114111 */ |
if (*index + 3 > limit) |
return false; |
str[*index] = 0xf0 | ((ch >> 18) & 0x07); |
(*index)++; |
str[*index] = 0x80 | ((ch >> 12) & 0x3f); |
(*index)++; |
str[*index] = 0x80 | ((ch >> 6) & 0x3f); |
(*index)++; |
str[*index] = 0x80 | (ch & 0x3f); |
return true; |
/* Check for available space in buffer */ |
if (*offset + cbytes >= size) |
return EOVERFLOW; |
/* Encode continuation bytes */ |
unsigned int i; |
for (i = cbytes; i > 0; i--) { |
str[*offset + i] = 0x80 | (cc & LO_MASK_32(CONT_BITS)); |
cc = cc >> CONT_BITS; |
} |
return false; |
/* Encode first byte */ |
str[*offset] = (cc & LO_MASK_32(b0_bits)) | HI_MASK_8(8 - b0_bits - 1); |
/* Advance offset */ |
*offset += cbytes + 1; |
return EOK; |
} |
/** Get bytes used by UTF-8 characters. |
/** Get size of string. |
* |
* Get the number of bytes (count of plain characters) which |
* are used by a given count of UTF-8 characters in a string. |
* As UTF-8 encoding is multibyte, there is no constant |
* correspondence between number of characters and used bytes. |
* Get the number of bytes which are used by the string @a str (excluding the |
* NULL-terminator). |
* |
* @param str UTF-8 string to consider. |
* @param count Number of UTF-8 characters to count. |
* @param str String to consider. |
* |
* @return Number of bytes used by the characters. |
* @return Number of bytes used by the string |
* |
*/ |
size_t utf8_count_bytes(const char *str, count_t count) |
size_t str_size(const char *str) |
{ |
size_t size = 0; |
index_t index = 0; |
while ((utf8_decode(str, &index, UTF8_NO_LIMIT) != 0) && (size < count)) { |
while (*str++ != 0) |
size++; |
index++; |
return size; |
} |
/** Get size of wide string. |
* |
* Get the number of bytes which are used by the wide string @a str (excluding the |
* NULL-terminator). |
* |
* @param str Wide string to consider. |
* |
* @return Number of bytes used by the wide string |
* |
*/ |
size_t wstr_size(const wchar_t *str) |
{ |
return (wstr_length(str) * sizeof(wchar_t)); |
} |
/** Get size of string with length limit. |
* |
* Get the number of bytes which are used by up to @a max_len first |
* characters in the string @a str. If @a max_len is greater than |
* the length of @a str, the entire string is measured (excluding the |
* NULL-terminator). |
* |
* @param str String to consider. |
* @param max_len Maximum number of characters to measure. |
* |
* @return Number of bytes used by the characters. |
* |
*/ |
size_t str_lsize(const char *str, count_t max_len) |
{ |
count_t len = 0; |
size_t offset = 0; |
while (len < max_len) { |
if (str_decode(str, &offset, STR_NO_LIMIT) == 0) |
break; |
len++; |
} |
return index; |
return offset; |
} |
/** Check whether character is plain ASCII. |
/** Get size of wide string with length limit. |
* |
* @return True if character is plain ASCII. |
* Get the number of bytes which are used by up to @a max_len first |
* wide characters in the wide string @a str. If @a max_len is greater than |
* the length of @a str, the entire wide string is measured (excluding the |
* NULL-terminator). |
* |
* @param str Wide string to consider. |
* @param max_len Maximum number of wide characters to measure. |
* |
* @return Number of bytes used by the wide characters. |
* |
*/ |
bool ascii_check(const wchar_t ch) |
size_t wstr_lsize(const wchar_t *str, count_t max_len) |
{ |
if ((ch >= 0) && (ch <= 127)) |
return true; |
return (wstr_nlength(str, max_len * sizeof(wchar_t)) * sizeof(wchar_t)); |
} |
/** Get number of characters in a string. |
* |
* @param str NULL-terminated string. |
* |
* @return Number of characters in string. |
* |
*/ |
count_t str_length(const char *str) |
{ |
count_t len = 0; |
size_t offset = 0; |
return false; |
while (str_decode(str, &offset, STR_NO_LIMIT) != 0) |
len++; |
return len; |
} |
/** Check whether character is Unicode. |
/** Get number of characters in a wide string. |
* |
* @return True if character is valid Unicode code point. |
* @param str NULL-terminated wide string. |
* |
* @return Number of characters in @a str. |
* |
*/ |
bool unicode_check(const wchar_t ch) |
count_t wstr_length(const wchar_t *wstr) |
{ |
if ((ch >= 0) && (ch <= 1114111)) |
return true; |
count_t len = 0; |
return false; |
while (*wstr++ != 0) |
len++; |
return len; |
} |
/** Return number of plain characters in a string. |
/** Get number of characters in a string with size limit. |
* |
* @param str NULL-terminated string. |
* @param str NULL-terminated string. |
* @param size Maximum number of bytes to consider. |
* |
* @return Number of characters in str. |
* @return Number of characters in string. |
* |
*/ |
size_t strlen(const char *str) |
count_t str_nlength(const char *str, size_t size) |
{ |
size_t size; |
for (size = 0; str[size]; size++); |
count_t len = 0; |
size_t offset = 0; |
return size; |
while (str_decode(str, &offset, size) != 0) |
len++; |
return len; |
} |
/** Return number of UTF-8 characters in a string. |
/** Get number of characters in a string with size limit. |
* |
* @param str NULL-terminated UTF-8 string. |
* @param str NULL-terminated string. |
* @param size Maximum number of bytes to consider. |
* |
* @return Number of UTF-8 characters in str. |
* @return Number of characters in string. |
* |
*/ |
size_t strlen_utf8(const char *str) |
count_t wstr_nlength(const wchar_t *str, size_t size) |
{ |
size_t size = 0; |
index_t index = 0; |
count_t len = 0; |
count_t limit = ALIGN_DOWN(size, sizeof(wchar_t)); |
count_t offset = 0; |
while (utf8_decode(str, &index, UTF8_NO_LIMIT) != 0) { |
size++; |
index++; |
while ((offset < limit) && (*str++ != 0)) { |
len++; |
offset += sizeof(wchar_t); |
} |
return size; |
return len; |
} |
/** Return number of UTF-32 characters in a string. |
/** Check whether character is plain ASCII. |
* |
* @param str NULL-terminated UTF-32 string. |
* @return True if character is plain ASCII. |
* |
* @return Number of UTF-32 characters in str. |
*/ |
bool ascii_check(wchar_t ch) |
{ |
if ((ch >= 0) && (ch <= 127)) |
return true; |
return false; |
} |
/** Check whether character is valid |
* |
* @return True if character is a valid Unicode code point. |
* |
*/ |
size_t strlen_utf32(const wchar_t *str) |
bool chr_check(wchar_t ch) |
{ |
size_t size; |
for (size = 0; str[size]; size++); |
if ((ch >= 0) && (ch <= 1114111)) |
return true; |
return size; |
return false; |
} |
/** Compare two NULL terminated strings |
/** Compare two NULL terminated strings. |
* |
* Do a char-by-char comparison of two NULL terminated strings. |
* Do a char-by-char comparison of two NULL-terminated strings. |
* The strings are considered equal iff they consist of the same |
* characters on the minimum of their lengths. |
* |
* @param src First string to compare. |
* @param dst Second string to compare. |
* @param s1 First string to compare. |
* @param s2 Second string to compare. |
* |
* @return 0 if the strings are equal, -1 if first is smaller, 1 if second smaller. |
* @return 0 if the strings are equal, -1 if first is smaller, |
* 1 if second smaller. |
* |
*/ |
int strcmp(const char *src, const char *dst) |
int str_cmp(const char *s1, const char *s2) |
{ |
for (; *src && *dst; src++, dst++) { |
if (*src < *dst) |
wchar_t c1 = 0; |
wchar_t c2 = 0; |
size_t off1 = 0; |
size_t off2 = 0; |
while (true) { |
c1 = str_decode(s1, &off1, STR_NO_LIMIT); |
c2 = str_decode(s2, &off2, STR_NO_LIMIT); |
if (c1 < c2) |
return -1; |
if (*src > *dst) |
if (c1 > c2) |
return 1; |
if (c1 == 0 || c2 == 0) |
break; |
} |
if (*src == *dst) |
return 0; |
if (!*src) |
return -1; |
return 1; |
return 0; |
} |
/** Compare two NULL terminated strings |
/** Compare two NULL terminated strings with length limit. |
* |
* Do a char-by-char comparison of two NULL terminated strings. |
* Do a char-by-char comparison of two NULL-terminated strings. |
* The strings are considered equal iff they consist of the same |
* characters on the minimum of their lengths and specified maximal |
* length. |
* characters on the minimum of their lengths and the length limit. |
* |
* @param src First string to compare. |
* @param dst Second string to compare. |
* @param len Maximal length for comparison. |
* @param s1 First string to compare. |
* @param s2 Second string to compare. |
* @param max_len Maximum number of characters to consider. |
* |
* @return 0 if the strings are equal, -1 if first is smaller, 1 if second smaller. |
* @return 0 if the strings are equal, -1 if first is smaller, |
* 1 if second smaller. |
* |
*/ |
int strncmp(const char *src, const char *dst, size_t len) |
int str_lcmp(const char *s1, const char *s2, count_t max_len) |
{ |
unsigned int i; |
wchar_t c1 = 0; |
wchar_t c2 = 0; |
for (i = 0; (*src) && (*dst) && (i < len); src++, dst++, i++) { |
if (*src < *dst) |
size_t off1 = 0; |
size_t off2 = 0; |
count_t len = 0; |
while (true) { |
if (len >= max_len) |
break; |
c1 = str_decode(s1, &off1, STR_NO_LIMIT); |
c2 = str_decode(s2, &off2, STR_NO_LIMIT); |
if (c1 < c2) |
return -1; |
if (*src > *dst) |
if (c1 > c2) |
return 1; |
if (c1 == 0 || c2 == 0) |
break; |
++len; |
} |
return 0; |
} |
/** Copy string. |
* |
* Copy source string @a src to destination buffer @a dest. |
* No more than @a size bytes are written. If the size of the output buffer |
* is at least one byte, the output string will always be well-formed, i.e. |
* null-terminated and containing only complete characters. |
* |
* @param dst Destination buffer. |
* @param count Size of the destination buffer (must be > 0). |
* @param src Source string. |
*/ |
void str_cpy(char *dest, size_t size, const char *src) |
{ |
wchar_t ch; |
size_t src_off; |
size_t dest_off; |
/* There must be space for a null terminator in the buffer. */ |
ASSERT(size > 0); |
if (i == len || *src == *dst) |
return 0; |
if (!*src) |
return -1; |
return 1; |
src_off = 0; |
dest_off = 0; |
while ((ch = str_decode(src, &src_off, STR_NO_LIMIT)) != 0) { |
if (chr_encode(ch, dest, &dest_off, size - 1) != EOK) |
break; |
} |
dest[dest_off] = '\0'; |
} |
/** Copy size-limited substring. |
* |
* Copy prefix of string @a src of max. size @a size to destination buffer |
* @a dest. No more than @a size bytes are written. The output string will |
* always be well-formed, i.e. null-terminated and containing only complete |
* characters. |
* |
* No more than @a n bytes are read from the input string, so it does not |
* have to be null-terminated. |
* |
* @param dst Destination buffer. |
* @param count Size of the destination buffer (must be > 0). |
* @param src Source string. |
* @param n Maximum number of bytes to read from @a src. |
*/ |
void str_ncpy(char *dest, size_t size, const char *src, size_t n) |
{ |
wchar_t ch; |
size_t src_off; |
size_t dest_off; |
/* There must be space for a null terminator in the buffer. */ |
ASSERT(size > 0); |
src_off = 0; |
dest_off = 0; |
/** Copy NULL terminated string. |
while ((ch = str_decode(src, &src_off, n)) != 0) { |
if (chr_encode(ch, dest, &dest_off, size - 1) != EOK) |
break; |
} |
dest[dest_off] = '\0'; |
} |
/** Copy NULL-terminated wide string to string |
* |
* Copy at most 'len' characters from string 'src' to 'dest'. |
* If 'src' is shorter than 'len', '\0' is inserted behind the |
* last copied character. |
* Copy source wide string @a src to destination buffer @a dst. |
* No more than @a size bytes are written. NULL-terminator is always |
* written after the last succesfully copied character (i.e. if the |
* destination buffer is has at least 1 byte, it will be always |
* NULL-terminated). |
* |
* @param src Source string. |
* @param dest Destination buffer. |
* @param len Size of destination buffer. |
* @param src Source wide string. |
* @param dst Destination buffer. |
* @param count Size of the destination buffer. |
* |
*/ |
void strncpy(char *dest, const char *src, size_t len) |
void wstr_nstr(char *dst, const wchar_t *src, size_t size) |
{ |
unsigned int i; |
/* No space for the NULL-terminator in the buffer */ |
if (size == 0) |
return; |
for (i = 0; i < len; i++) { |
if (!(dest[i] = src[i])) |
return; |
wchar_t ch; |
count_t src_idx = 0; |
size_t dst_off = 0; |
while ((ch = src[src_idx++]) != 0) { |
if (chr_encode(ch, dst, &dst_off, size) != EOK) |
break; |
} |
dest[i - 1] = '\0'; |
if (dst_off >= size) |
dst[size - 1] = 0; |
else |
dst[dst_off] = 0; |
} |
/** Find first occurence of character in string. |
* |
* @param s String to search. |
* @param i Character to look for. |
* @param str String to search. |
* @param ch Character to look for. |
* |
* @return Pointer to character in @a s or NULL if not found. |
* @return Pointer to character in @a str or NULL if not found. |
* |
*/ |
extern char *strchr(const char *s, int i) |
const char *str_chr(const char *str, wchar_t ch) |
{ |
while (*s != '\0') { |
if (*s == i) |
return (char *) s; |
++s; |
wchar_t acc; |
size_t off = 0; |
size_t last = 0; |
while ((acc = str_decode(str, &off, STR_NO_LIMIT)) != 0) { |
if (acc == ch) |
return (str + last); |
last = off; |
} |
return NULL; |
} |
/** Insert a wide character into a wide string. |
* |
* Insert a wide character into a wide string at position |
* @a pos. The characters after the position are shifted. |
* |
* @param str String to insert to. |
* @param ch Character to insert to. |
* @param pos Character index where to insert. |
@ @param max_pos Characters in the buffer. |
* |
* @return True if the insertion was sucessful, false if the position |
* is out of bounds. |
* |
*/ |
bool wstr_linsert(wchar_t *str, wchar_t ch, count_t pos, count_t max_pos) |
{ |
count_t len = wstr_length(str); |
if ((pos > len) || (pos + 1 > max_pos)) |
return false; |
count_t i; |
for (i = len; i + 1 > pos; i--) |
str[i + 1] = str[i]; |
str[pos] = ch; |
return true; |
} |
/** Remove a wide character from a wide string. |
* |
* Remove a wide character from a wide string at position |
* @a pos. The characters after the position are shifted. |
* |
* @param str String to remove from. |
* @param pos Character index to remove. |
* |
* @return True if the removal was sucessful, false if the position |
* is out of bounds. |
* |
*/ |
bool wstr_remove(wchar_t *str, count_t pos) |
{ |
count_t len = wstr_length(str); |
if (pos >= len) |
return false; |
count_t i; |
for (i = pos + 1; i <= len; i++) |
str[i - 1] = str[i]; |
return true; |
} |
/** @} |
*/ |
/branches/dynload/kernel/generic/src/adt/hash_table.c |
---|
32,7 → 32,7 |
/** |
* @file |
* @brief Implementation of generic chained hash table. |
* @brief Implementation of generic chained hash table. |
* |
* This file contains implementation of generic chained hash table. |
*/ |
56,13 → 56,15 |
index_t i; |
ASSERT(h); |
ASSERT(op && op->hash && op->compare); |
ASSERT(op); |
ASSERT(op->hash); |
ASSERT(op->compare); |
ASSERT(max_keys > 0); |
h->entry = (link_t *) malloc(m * sizeof(link_t), 0); |
if (!h->entry) { |
if (!h->entry) |
panic("Cannot allocate memory for hash table."); |
} |
memsetb(h->entry, m * sizeof(link_t), 0); |
for (i = 0; i < m; i++) |
82,10 → 84,13 |
void hash_table_insert(hash_table_t *h, unative_t key[], link_t *item) |
{ |
index_t chain; |
ASSERT(item); |
ASSERT(h && h->op && h->op->hash && h->op->compare); |
ASSERT(h); |
ASSERT(h->op); |
ASSERT(h->op->hash); |
ASSERT(h->op->compare); |
chain = h->op->hash(key); |
ASSERT(chain < h->entries); |
103,9 → 108,12 |
{ |
link_t *cur; |
index_t chain; |
ASSERT(h && h->op && h->op->hash && h->op->compare); |
ASSERT(h); |
ASSERT(h->op); |
ASSERT(h->op->hash); |
ASSERT(h->op->compare); |
chain = h->op->hash(key); |
ASSERT(chain < h->entries); |
123,7 → 131,7 |
/** Remove all matching items from hash table. |
* |
* For each removed item, h->remove_callback() is called. |
* For each removed item, h->remove_callback() is called (if not NULL). |
* |
* @param h Hash table. |
* @param key Array of keys that will be compared against items of the hash table. |
133,12 → 141,15 |
{ |
index_t chain; |
link_t *cur; |
ASSERT(h && h->op && h->op->hash && h->op->compare && h->op->remove_callback); |
ASSERT(h); |
ASSERT(h->op); |
ASSERT(h->op->hash); |
ASSERT(h->op->compare); |
ASSERT(keys <= h->max_keys); |
if (keys == h->max_keys) { |
/* |
* All keys are known, hash_table_find() can be used to find the entry. |
*/ |
146,7 → 157,8 |
cur = hash_table_find(h, key); |
if (cur) { |
list_remove(cur); |
h->op->remove_callback(cur); |
if (h->op->remove_callback) |
h->op->remove_callback(cur); |
} |
return; |
} |
164,7 → 176,8 |
cur = cur->prev; |
list_remove(hlp); |
h->op->remove_callback(hlp); |
if (h->op->remove_callback) |
h->op->remove_callback(hlp); |
continue; |
} |
/branches/dynload/kernel/generic/src/mm/slab.c |
---|
936,7 → 936,7 |
void *malloc(unsigned int size, int flags) |
{ |
ASSERT(_slab_initialized); |
ASSERT(size && size <= (1 << SLAB_MAX_MALLOC_W)); |
ASSERT(size <= (1 << SLAB_MAX_MALLOC_W)); |
if (size < (1 << SLAB_MIN_MALLOC_W)) |
size = (1 << SLAB_MIN_MALLOC_W); |
/branches/dynload/kernel/generic/src/mm/frame.c |
---|
992,14 → 992,27 |
/* If no memory, reclaim some slab memory, |
if it does not help, reclaim all */ |
if ((znum == (count_t) -1) && (!(flags & FRAME_NO_RECLAIM))) { |
spinlock_unlock(&zones.lock); |
interrupts_restore(ipl); |
count_t freed = slab_reclaim(0); |
ipl = interrupts_disable(); |
spinlock_lock(&zones.lock); |
if (freed > 0) |
znum = find_free_zone(order, |
FRAME_TO_ZONE_FLAGS(flags), hint); |
if (znum == (count_t) -1) { |
spinlock_unlock(&zones.lock); |
interrupts_restore(ipl); |
freed = slab_reclaim(SLAB_RECLAIM_ALL); |
ipl = interrupts_disable(); |
spinlock_lock(&zones.lock); |
if (freed > 0) |
znum = find_free_zone(order, |
FRAME_TO_ZONE_FLAGS(flags), hint); |
/branches/dynload/kernel/generic/src/syscall/syscall.c |
---|
48,7 → 48,7 |
#include <synch/futex.h> |
#include <synch/smc.h> |
#include <ddi/ddi.h> |
#include <event/event.h> |
#include <ipc/event.h> |
#include <security/cap.h> |
#include <sysinfo/sysinfo.h> |
#include <console/console.h> |
/branches/dynload/kernel/generic/src/ipc/event.c |
---|
0,0 → 1,155 |
/* |
* 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 generic |
* @{ |
*/ |
/** |
* @file |
* @brief Kernel event notifications. |
*/ |
#include <ipc/event.h> |
#include <ipc/event_types.h> |
#include <mm/slab.h> |
#include <arch/types.h> |
#include <synch/spinlock.h> |
#include <console/console.h> |
#include <memstr.h> |
#include <errno.h> |
#include <arch.h> |
/** |
* The events array. |
* Arranging the events in this two-dimensional array should decrease the |
* likelyhood of cacheline ping-pong. |
*/ |
static event_t events[EVENT_END]; |
/** Initialize kernel events. */ |
void event_init(void) |
{ |
unsigned int i; |
for (i = 0; i < EVENT_END; i++) { |
spinlock_initialize(&events[i].lock, "event.lock"); |
events[i].answerbox = NULL; |
events[i].counter = 0; |
events[i].method = 0; |
} |
} |
static int |
event_subscribe(event_type_t evno, unative_t method, answerbox_t *answerbox) |
{ |
if (evno >= EVENT_END) |
return ELIMIT; |
spinlock_lock(&events[evno].lock); |
int res; |
if (events[evno].answerbox == NULL) { |
events[evno].answerbox = answerbox; |
events[evno].method = method; |
events[evno].counter = 0; |
res = EOK; |
} else |
res = EEXISTS; |
spinlock_unlock(&events[evno].lock); |
return res; |
} |
unative_t sys_event_subscribe(unative_t evno, unative_t method) |
{ |
return (unative_t) event_subscribe((event_type_t) evno, (unative_t) |
method, &TASK->answerbox); |
} |
bool event_is_subscribed(event_type_t evno) |
{ |
bool res; |
ASSERT(evno < EVENT_END); |
spinlock_lock(&events[evno].lock); |
res = events[evno].answerbox != NULL; |
spinlock_unlock(&events[evno].lock); |
return res; |
} |
void event_cleanup_answerbox(answerbox_t *answerbox) |
{ |
unsigned int i; |
for (i = 0; i < EVENT_END; i++) { |
spinlock_lock(&events[i].lock); |
if (events[i].answerbox == answerbox) { |
events[i].answerbox = NULL; |
events[i].counter = 0; |
events[i].method = 0; |
} |
spinlock_unlock(&events[i].lock); |
} |
} |
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); |
spinlock_lock(&events[evno].lock); |
if (events[evno].answerbox != NULL) { |
call_t *call = ipc_call_alloc(FRAME_ATOMIC); |
if (call) { |
call->flags |= IPC_CALL_NOTIF; |
call->priv = ++events[evno].counter; |
IPC_SET_METHOD(call->data, events[evno].method); |
IPC_SET_ARG1(call->data, a1); |
IPC_SET_ARG2(call->data, a2); |
IPC_SET_ARG3(call->data, a3); |
IPC_SET_ARG4(call->data, a4); |
IPC_SET_ARG5(call->data, a5); |
spinlock_lock(&events[evno].answerbox->irq_lock); |
list_append(&call->link, &events[evno].answerbox->irq_notifs); |
spinlock_unlock(&events[evno].answerbox->irq_lock); |
waitq_wakeup(&events[evno].answerbox->wq, WAKEUP_FIRST); |
} |
} |
spinlock_unlock(&events[evno].lock); |
} |
/** @} |
*/ |
Property changes: |
Added: svn:mergeinfo |
/branches/dynload/kernel/generic/src/ipc/sysipc.c |
---|
332,7 → 332,7 |
src = IPC_GET_ARG1(call->data); |
size = IPC_GET_ARG2(call->data); |
if ((size <= 0) || (size > DATA_XFER_LIMIT)) |
if (size > DATA_XFER_LIMIT) |
return ELIMIT; |
call->buffer = (uint8_t *) malloc(size, 0); |
/branches/dynload/kernel/generic/src/ipc/ipc.c |
---|
44,7 → 44,7 |
#include <synch/synch.h> |
#include <ipc/ipc.h> |
#include <ipc/kbox.h> |
#include <event/event.h> |
#include <ipc/event.h> |
#include <errno.h> |
#include <mm/slab.h> |
#include <arch.h> |
51,8 → 51,6 |
#include <proc/task.h> |
#include <memstr.h> |
#include <debug.h> |
#include <print.h> |
#include <console/console.h> |
#include <proc/thread.h> |
/branches/dynload/kernel/generic/src/ipc/irq.c |
---|
128,13 → 128,14 |
/** Register an answerbox as a receiving end for IRQ notifications. |
* |
* @param box Receiving answerbox. |
* @param inr IRQ number. |
* @param devno Device number. |
* @param method Method to be associated with the notification. |
* @param ucode Uspace pointer to top-half pseudocode. |
* @param box Receiving answerbox. |
* @param inr IRQ number. |
* @param devno Device number. |
* @param method Method to be associated with the notification. |
* @param ucode Uspace pointer to top-half pseudocode. |
* |
* @return EBADMEM, ENOENT or EEXISTS on failure or 0 on success. |
* @return EBADMEM, ENOENT or EEXISTS on failure or 0 on success. |
* |
*/ |
int ipc_irq_register(answerbox_t *box, inr_t inr, devno_t devno, |
unative_t method, irq_code_t *ucode) |
142,11 → 143,12 |
ipl_t ipl; |
irq_code_t *code; |
irq_t *irq; |
link_t *hlp; |
unative_t key[] = { |
(unative_t) inr, |
(unative_t) devno |
}; |
if (ucode) { |
code = code_from_uspace(ucode); |
if (!code) |
154,7 → 156,7 |
} else { |
code = NULL; |
} |
/* |
* Allocate and populate the IRQ structure. |
*/ |
169,7 → 171,7 |
irq->notif_cfg.method = method; |
irq->notif_cfg.code = code; |
irq->notif_cfg.counter = 0; |
/* |
* Enlist the IRQ structure in the uspace IRQ hash table and the |
* answerbox's list. |
176,23 → 178,28 |
*/ |
ipl = interrupts_disable(); |
spinlock_lock(&irq_uspace_hash_table_lock); |
spinlock_lock(&irq->lock); |
spinlock_lock(&box->irq_lock); |
if (hash_table_find(&irq_uspace_hash_table, key)) { |
hlp = hash_table_find(&irq_uspace_hash_table, key); |
if (hlp) { |
irq_t *hirq __attribute__((unused)) |
= hash_table_get_instance(hlp, irq_t, link); |
/* hirq is locked */ |
spinlock_unlock(&hirq->lock); |
code_free(code); |
spinlock_unlock(&box->irq_lock); |
spinlock_unlock(&irq->lock); |
spinlock_unlock(&irq_uspace_hash_table_lock); |
free(irq); |
interrupts_restore(ipl); |
return EEXISTS; |
} |
spinlock_lock(&irq->lock); /* Not really necessary, but paranoid */ |
spinlock_lock(&box->irq_lock); |
hash_table_insert(&irq_uspace_hash_table, key, &irq->link); |
list_append(&irq->notif_cfg.link, &box->irq_head); |
spinlock_unlock(&box->irq_lock); |
spinlock_unlock(&irq->lock); |
spinlock_unlock(&irq_uspace_hash_table_lock); |
interrupts_restore(ipl); |
return EOK; |
} |
222,7 → 229,7 |
return ENOENT; |
} |
irq = hash_table_get_instance(lnk, irq_t, link); |
spinlock_lock(&irq->lock); |
/* irq is locked */ |
spinlock_lock(&box->irq_lock); |
ASSERT(irq->notif_cfg.answerbox == box); |
233,11 → 240,19 |
/* Remove the IRQ from the answerbox's list. */ |
list_remove(&irq->notif_cfg.link); |
/* |
* We need to drop the IRQ lock now because hash_table_remove() will try |
* to reacquire it. That basically violates the natural locking order, |
* but a deadlock in hash_table_remove() is prevented by the fact that |
* we already held the IRQ lock and didn't drop the hash table lock in |
* the meantime. |
*/ |
spinlock_unlock(&irq->lock); |
/* Remove the IRQ from the uspace IRQ hash table. */ |
hash_table_remove(&irq_uspace_hash_table, key, 2); |
spinlock_unlock(&irq_uspace_hash_table_lock); |
spinlock_unlock(&irq->lock); |
spinlock_unlock(&box->irq_lock); |
/* Free up the IRQ structure. */ |
291,13 → 306,21 |
/* Unlist from the answerbox. */ |
list_remove(&irq->notif_cfg.link); |
/* Remove from the hash table. */ |
hash_table_remove(&irq_uspace_hash_table, key, 2); |
/* Free up the pseudo code and associated structures. */ |
code_free(irq->notif_cfg.code); |
/* |
* We need to drop the IRQ lock now because hash_table_remove() |
* will try to reacquire it. That basically violates the natural |
* locking order, but a deadlock in hash_table_remove() is |
* prevented by the fact that we already held the IRQ lock and |
* didn't drop the hash table lock in the meantime. |
*/ |
spinlock_unlock(&irq->lock); |
/* Remove from the hash table. */ |
hash_table_remove(&irq_uspace_hash_table, key, 2); |
free(irq); |
} |
/branches/dynload/kernel/Makefile |
---|
161,7 → 161,6 |
generic/src/ddi/irq.c \ |
generic/src/ddi/device.c \ |
generic/src/debug/symtab.c \ |
generic/src/event/event.c \ |
generic/src/interrupt/interrupt.c \ |
generic/src/main/main.c \ |
generic/src/main/kinit.c \ |
214,6 → 213,7 |
generic/src/ipc/sysipc.c \ |
generic/src/ipc/ipcrsc.c \ |
generic/src/ipc/irq.c \ |
generic/src/ipc/event.c \ |
generic/src/security/cap.c \ |
generic/src/sysinfo/sysinfo.c |
/branches/dynload/kernel/arch/sparc64/include/memstr.h |
---|
26,7 → 26,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup sparc64 |
/** @addtogroup sparc64 |
* @{ |
*/ |
/** @file |
/branches/dynload/kernel/arch/sparc64/include/atomic.h |
---|
123,7 → 123,7 |
"ldx %0, %2\n" |
"brz %2, 0b\n" |
"nop\n" |
"ba 1b\n" |
"ba %xcc, 1b\n" |
"nop\n" |
"2:\n" |
: "+m" (*((uint64_t *) x)), "+r" (tmp1), "+r" (tmp2) : "r" (0) |
/branches/dynload/kernel/arch/sparc64/include/trap/trap_table.h |
---|
100,7 → 100,7 |
.macro PREEMPTIBLE_HANDLER f |
sethi %hi(\f), %g1 |
b preemptible_handler |
ba %xcc, preemptible_handler |
or %g1, %lo(\f), %g1 |
.endm |
/branches/dynload/kernel/arch/sparc64/include/trap/mmu.h |
---|
103,17 → 103,20 |
* Note that branch-delay slots are used in order to save space. |
*/ |
0: |
mov VA_DMMU_TAG_ACCESS, %g1 |
ldxa [%g1] ASI_DMMU, %g1 ! read the faulting Context and VPN |
sethi %hi(fast_data_access_mmu_miss_data_hi), %g7 |
wr %g0, ASI_DMMU, %asi |
ldxa [VA_DMMU_TAG_ACCESS] %asi, %g1 ! read the faulting Context and VPN |
set TLB_TAG_ACCESS_CONTEXT_MASK, %g2 |
andcc %g1, %g2, %g3 ! get Context |
bnz 0f ! Context is non-zero |
bnz %xcc, 0f ! Context is non-zero |
andncc %g1, %g2, %g3 ! get page address into %g3 |
bz 0f ! page address is zero |
bz %xcc, 0f ! page address is zero |
ldx [%g7 + %lo(end_of_identity)], %g4 |
cmp %g3, %g4 |
bgeu %xcc, 0f |
sethi %hi(kernel_8k_tlb_data_template), %g2 |
ldx [%g2 + %lo(kernel_8k_tlb_data_template)], %g2 |
or %g3, %g2, %g2 |
ldx [%g7 + %lo(kernel_8k_tlb_data_template)], %g2 |
add %g3, %g2, %g2 |
stxa %g2, [%g0] ASI_DTLB_DATA_IN_REG ! identity map the kernel page |
retry |
138,8 → 141,7 |
* Read the Tag Access register for the higher-level handler. |
* This is necessary to survive nested DTLB misses. |
*/ |
mov VA_DMMU_TAG_ACCESS, %g2 |
ldxa [%g2] ASI_DMMU, %g2 |
ldxa [VA_DMMU_TAG_ACCESS] %asi, %g2 |
/* |
* g2 will be passed as an argument to fast_data_access_mmu_miss(). |
/branches/dynload/kernel/arch/sparc64/include/mm/frame.h |
---|
73,6 → 73,8 |
typedef union frame_address frame_address_t; |
extern uintptr_t last_frame; |
extern uintptr_t end_of_identity; |
extern void frame_arch_init(void); |
#define physmem_print() |
/branches/dynload/kernel/arch/sparc64/include/drivers/sgcn.h |
---|
37,17 → 37,18 |
#include <arch/types.h> |
#include <console/chardev.h> |
#include <proc/thread.h> |
/* number of bytes in the TOC magic, including the terminating '\0' */ |
/* number of bytes in the TOC magic, including the NULL-terminator */ |
#define TOC_MAGIC_BYTES 8 |
/* number of bytes in the TOC key, including the terminating '\0' */ |
/* number of bytes in the TOC key, including the NULL-terminator */ |
#define TOC_KEY_SIZE 8 |
/* maximum number of entries in the SRAM table of contents */ |
#define MAX_TOC_ENTRIES 32 |
/* number of bytes in the SGCN buffer magic, including the terminating '\0' */ |
/* number of bytes in the SGCN buffer magic, including the NULL-terminator */ |
#define SGCN_MAGIC_BYTES 4 |
/** |
116,11 → 117,17 |
uint32_t out_wrptr; |
} __attribute__ ((packed)) sgcn_buffer_header_t; |
void sgcn_grab(void); |
void sgcn_release(void); |
indev_t *sgcnin_init(void); |
void sgcnout_init(void); |
typedef struct { |
thread_t *thread; |
indev_t *srlnin; |
} sgcn_instance_t; |
extern void sgcn_grab(void); |
extern void sgcn_release(void); |
extern sgcn_instance_t *sgcnin_init(void); |
extern void sgcnin_wire(sgcn_instance_t *, indev_t *); |
extern void sgcnout_init(void); |
#endif |
/** @} |
/branches/dynload/kernel/arch/sparc64/include/drivers/kbd.h |
---|
26,7 → 26,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup sparc64 |
/** @addtogroup sparc64 |
* @{ |
*/ |
/** @file |
38,15 → 38,6 |
#include <arch/types.h> |
#include <genarch/ofw/ofw_tree.h> |
typedef enum { |
KBD_UNKNOWN, |
KBD_Z8530, |
KBD_NS16550, |
KBD_SGCN |
} kbd_type_t; |
extern kbd_type_t kbd_type; |
extern void kbd_init(ofw_tree_node_t *node); |
#endif |
/branches/dynload/kernel/arch/sparc64/src/asm.S |
---|
225,10 → 225,15 |
.global memsetb |
memsetb: |
b _memsetb |
ba %xcc, _memsetb |
nop |
.global memsetw |
memsetw: |
ba %xcc, _memsetw |
nop |
.macro WRITE_ALTERNATE_REGISTER reg, bit |
rdpr %pstate, %g1 ! save PSTATE.PEF |
wrpr %g0, (\bit | PSTATE_PRIV_BIT), %pstate |
/branches/dynload/kernel/arch/sparc64/src/console.c |
---|
26,7 → 26,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup sparc64 |
/** @addtogroup sparc64 |
* @{ |
*/ |
/** @file |
92,10 → 92,15 |
static void serengeti_init(void) |
{ |
#ifdef CONFIG_SGCN_KBD |
indev_t *kbrdin; |
kbrdin = sgcnin_init(); |
if (kbrdin) |
srlnin_init(kbrdin); |
sgcn_instance_t *sgcn_instance = sgcnin_init(); |
if (sgcn_instance) { |
srln_instance_t *srln_instance = srln_init(); |
if (srln_instance) { |
indev_t *sink = stdin_wire(); |
indev_t *srln = srln_wire(srln_instance, sink); |
sgcnin_wire(sgcn_instance, srln); |
} |
} |
#endif |
#ifdef CONFIG_SGCN_PRN |
sgcnout_init(); |
118,7 → 123,7 |
/* "def-cn" = "default console" */ |
prop = ofw_tree_getprop(aliases, "def-cn"); |
if ((!prop) || (!prop->value) || (strcmp(prop->value, "/sgcn") != 0)) { |
if ((!prop) || (!prop->value) || (str_cmp(prop->value, "/sgcn") != 0)) { |
standard_console_init(aliases); |
} else { |
serengeti_init(); |
134,15 → 139,10 |
#ifdef CONFIG_FB |
scr_redraw(); |
#endif |
switch (kbd_type) { |
#ifdef CONFIG_SGCN |
case KBD_SGCN: |
sgcn_grab(); |
break; |
#ifdef CONFIG_SGCN_KBD |
sgcn_grab(); |
#endif |
default: |
break; |
} |
} |
/** Return console to userspace |
150,15 → 150,9 |
*/ |
void arch_release_console(void) |
{ |
switch (kbd_type) { |
#ifdef CONFIG_SGCN |
case KBD_SGCN: |
sgcn_release(); |
break; |
#ifdef CONFIG_SGCN_KBD |
sgcn_release(); |
#endif |
default: |
break; |
} |
} |
/** @} |
/branches/dynload/kernel/arch/sparc64/src/sparc64.c |
---|
61,8 → 61,8 |
for (i = 0; i < bootinfo.taskmap.count; i++) { |
init.tasks[i].addr = (uintptr_t) bootinfo.taskmap.tasks[i].addr; |
init.tasks[i].size = bootinfo.taskmap.tasks[i].size; |
strncpy(init.tasks[i].name, bootinfo.taskmap.tasks[i].name, |
CONFIG_TASK_NAME_BUFLEN); |
str_cpy(init.tasks[i].name, CONFIG_TASK_NAME_BUFLEN, |
bootinfo.taskmap.tasks[i].name); |
} |
/* Copy boot allocations info. */ |
/branches/dynload/kernel/arch/sparc64/src/trap/trap_table.S |
---|
341,7 → 341,7 |
.org trap_table + (TT_TRAP_INSTRUCTION_0+\cur)*ENTRY_SIZE |
.global trap_instruction_\cur\()_tl0 |
trap_instruction_\cur\()_tl0: |
ba trap_instruction_handler |
ba %xcc, trap_instruction_handler |
mov \cur, %g2 |
.endr |
478,9 → 478,9 |
*/ |
rdpr %tl, %g3 |
cmp %g3, 1 |
be 1f |
be %xcc, 1f |
nop |
0: ba 0b ! this is for debugging, if we ever get here |
0: ba %xcc, 0b ! this is for debugging, if we ever get here |
nop ! it will be easy to find |
1: |
499,7 → 499,7 |
wrpr %g4, 0, %cwp ! resynchronize CWP |
andcc %g3, TSTATE_PRIV_BIT, %g0 ! if this trap came from the privileged mode... |
bnz 0f ! ...skip setting of kernel stack and primary context |
bnz %xcc, 0f ! ...skip setting of kernel stack and primary context |
nop |
.endif |
545,7 → 545,7 |
flush %l0 |
.if NOT(\is_syscall) |
ba 1f |
ba %xcc, 1f |
nop |
0: |
save %sp, -PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE, %sp |
672,7 → 672,7 |
and %l0, NWINDOWS - 1, %l0 ! %l0 mod NWINDOWS |
rdpr %cwp, %l1 |
cmp %l0, %l1 |
bz 0f ! CWP is ok |
bz %xcc, 0f ! CWP is ok |
nop |
/* |
712,7 → 712,7 |
.if NOT(\is_syscall) |
rdpr %tstate, %g1 |
andcc %g1, TSTATE_PRIV_BIT, %g0 ! if we are not returning to userspace..., |
bnz 1f ! ...skip restoring userspace windows |
bnz %xcc, 1f ! ...skip restoring userspace windows |
nop |
.endif |
749,7 → 749,7 |
*/ |
clr %g4 |
0: andcc %g7, UWB_ALIGNMENT - 1, %g0 ! alignment check |
bz 0f ! %g7 is UWB_ALIGNMENT-aligned, no more windows to refill |
bz %xcc, 0f ! %g7 is UWB_ALIGNMENT-aligned, no more windows to refill |
nop |
add %g7, -STACK_WINDOW_SAVE_AREA_SIZE, %g7 |
774,7 → 774,7 |
and %g3, NWINDOWS - 1, %g3 |
wrpr %g3, 0, %cwp ! switch to the preceeding window |
ba 0b |
ba %xcc, 0b |
inc %g4 |
0: |
785,7 → 785,7 |
wrpr %g1, 0, %cwp |
add %g4, %g2, %g2 |
cmp %g2, NWINDOWS - 2 |
bg 2f ! fix the CANRESTORE=NWINDOWS-1 anomaly |
bg %xcc, 2f ! fix the CANRESTORE=NWINDOWS-1 anomaly |
mov NWINDOWS - 2, %g1 ! use dealy slot for both cases |
sub %g1, %g2, %g1 |
/branches/dynload/kernel/arch/sparc64/src/mm/tlb.c |
---|
199,12 → 199,12 |
/** ITLB miss handler. */ |
void fast_instruction_access_mmu_miss(unative_t unused, istate_t *istate) |
{ |
uintptr_t va = ALIGN_DOWN(istate->tpc, PAGE_SIZE); |
uintptr_t page_16k = ALIGN_DOWN(istate->tpc, PAGE_SIZE); |
index_t index = (istate->tpc >> MMU_PAGE_WIDTH) % MMU_PAGES_PER_PAGE; |
pte_t *t; |
page_table_lock(AS, true); |
t = page_mapping_find(AS, va); |
t = page_mapping_find(AS, page_16k); |
if (t && PTE_EXECUTABLE(t)) { |
/* |
* The mapping was found in the software page hash table. |
222,7 → 222,8 |
* handler. |
*/ |
page_table_unlock(AS, true); |
if (as_page_fault(va, PF_ACCESS_EXEC, istate) == AS_PF_FAULT) { |
if (as_page_fault(page_16k, PF_ACCESS_EXEC, istate) == |
AS_PF_FAULT) { |
do_fast_instruction_access_mmu_miss_fault(istate, |
__func__); |
} |
242,11 → 243,13 |
*/ |
void fast_data_access_mmu_miss(tlb_tag_access_reg_t tag, istate_t *istate) |
{ |
uintptr_t va; |
uintptr_t page_8k; |
uintptr_t page_16k; |
index_t index; |
pte_t *t; |
va = ALIGN_DOWN((uint64_t) tag.vpn << MMU_PAGE_WIDTH, PAGE_SIZE); |
page_8k = (uint64_t) tag.vpn << MMU_PAGE_WIDTH; |
page_16k = ALIGN_DOWN(page_8k, PAGE_SIZE); |
index = tag.vpn % MMU_PAGES_PER_PAGE; |
if (tag.context == ASID_KERNEL) { |
254,6 → 257,15 |
/* NULL access in kernel */ |
do_fast_data_access_mmu_miss_fault(istate, tag, |
__func__); |
} else if (page_8k >= end_of_identity) { |
/* |
* The kernel is accessing the I/O space. |
* We still do identity mapping for I/O, |
* but without caching. |
*/ |
dtlb_insert_mapping(page_8k, KA2PA(page_8k), |
PAGESIZE_8K, false, false); |
return; |
} |
do_fast_data_access_mmu_miss_fault(istate, tag, "Unexpected " |
"kernel page fault."); |
260,7 → 272,7 |
} |
page_table_lock(AS, true); |
t = page_mapping_find(AS, va); |
t = page_mapping_find(AS, page_16k); |
if (t) { |
/* |
* The mapping was found in the software page hash table. |
278,7 → 290,8 |
* handler. |
*/ |
page_table_unlock(AS, true); |
if (as_page_fault(va, PF_ACCESS_READ, istate) == AS_PF_FAULT) { |
if (as_page_fault(page_16k, PF_ACCESS_READ, istate) == |
AS_PF_FAULT) { |
do_fast_data_access_mmu_miss_fault(istate, tag, |
__func__); |
} |
295,15 → 308,15 |
*/ |
void fast_data_access_protection(tlb_tag_access_reg_t tag, istate_t *istate) |
{ |
uintptr_t va; |
uintptr_t page_16k; |
index_t index; |
pte_t *t; |
va = ALIGN_DOWN((uint64_t) tag.vpn << MMU_PAGE_WIDTH, PAGE_SIZE); |
page_16k = ALIGN_DOWN((uint64_t) tag.vpn << MMU_PAGE_WIDTH, PAGE_SIZE); |
index = tag.vpn % MMU_PAGES_PER_PAGE; /* 16K-page emulation */ |
page_table_lock(AS, true); |
t = page_mapping_find(AS, va); |
t = page_mapping_find(AS, page_16k); |
if (t && PTE_WRITABLE(t)) { |
/* |
* The mapping was found in the software page hash table and is |
313,7 → 326,7 |
t->a = true; |
t->d = true; |
dtlb_demap(TLB_DEMAP_PAGE, TLB_DEMAP_SECONDARY, |
va + index * MMU_PAGE_SIZE); |
page_16k + index * MMU_PAGE_SIZE); |
dtlb_pte_copy(t, index, false); |
#ifdef CONFIG_TSB |
dtsb_pte_copy(t, index, false); |
325,7 → 338,8 |
* handler. |
*/ |
page_table_unlock(AS, true); |
if (as_page_fault(va, PF_ACCESS_WRITE, istate) == AS_PF_FAULT) { |
if (as_page_fault(page_16k, PF_ACCESS_WRITE, istate) == |
AS_PF_FAULT) { |
do_fast_data_access_protection_fault(istate, tag, |
__func__); |
} |
/branches/dynload/kernel/arch/sparc64/src/mm/frame.c |
---|
79,6 → 79,8 |
*/ |
frame_mark_unavailable(ADDR2PFN(KA2PA(PFN2ADDR(0))), 1); |
} |
end_of_identity = PA2KA(last_frame); |
} |
/** @} |
/branches/dynload/kernel/arch/sparc64/src/mm/page.c |
---|
53,12 → 53,12 |
* |
* We are currently using identity mapping for mapping device registers. |
* |
* @param physaddr Physical address of the page where the device is |
* located. |
* @param size Size of the device's registers. This argument is |
* ignored. |
* @param physaddr Physical address of the page where the device is |
* located. |
* @param size Size of the device's registers. |
* |
* @return Virtual address of the page where the device is mapped. |
* @return Virtual address of the page where the device is mapped. |
* |
*/ |
uintptr_t hw_map(uintptr_t physaddr, size_t size) |
{ |
/branches/dynload/kernel/arch/sparc64/src/dummy.s |
---|
42,5 → 42,5 |
.global cpu_halt |
cpu_halt: |
b cpu_halt |
ba %xcc, cpu_halt |
nop |
/branches/dynload/kernel/arch/sparc64/src/drivers/kbd.c |
---|
54,100 → 54,140 |
#include <print.h> |
#include <sysinfo/sysinfo.h> |
kbd_type_t kbd_type = KBD_UNKNOWN; |
#ifdef CONFIG_SUN_KBD |
/** Initialize keyboard. |
* |
* Traverse OpenFirmware device tree in order to find necessary |
* info about the keyboard device. |
* |
* @param node Keyboard device node. |
*/ |
void kbd_init(ofw_tree_node_t *node) |
#ifdef CONFIG_Z8530 |
static bool kbd_z8530_init(ofw_tree_node_t *node) |
{ |
size_t offset; |
uintptr_t aligned_addr; |
ofw_tree_property_t *prop; |
const char *name; |
const char *name = ofw_tree_node_name(node); |
if (str_cmp(name, "zs") != 0) |
return false; |
/* |
* Read 'interrupts' property. |
*/ |
ofw_tree_property_t *prop = ofw_tree_getprop(node, "interrupts"); |
if ((!prop) || (!prop->value)) { |
printf("z8530: Unable to find interrupts property\n"); |
return false; |
} |
uint32_t interrupts = *((uint32_t *) prop->value); |
/* |
* Read 'reg' property. |
*/ |
prop = ofw_tree_getprop(node, "reg"); |
if ((!prop) || (!prop->value)) { |
printf("z8530: Unable to find reg property\n"); |
return false; |
} |
size_t size = ((ofw_fhc_reg_t *) prop->value)->size; |
uintptr_t pa; |
if (!ofw_fhc_apply_ranges(node->parent, |
((ofw_fhc_reg_t *) prop->value), &pa)) { |
printf("z8530: Failed to determine address\n"); |
return false; |
} |
inr_t inr; |
cir_t cir; |
void *cir_arg; |
if (!ofw_fhc_map_interrupt(node->parent, |
((ofw_fhc_reg_t *) prop->value), interrupts, &inr, &cir, |
&cir_arg)) { |
printf("z8530: Failed to determine interrupt\n"); |
return false; |
} |
#ifdef CONFIG_NS16550 |
ns16550_t *ns16550; |
#endif |
#ifdef CONFIG_Z8530 |
z8530_t *z8530; |
#endif |
/* |
* We need to pass aligned address to hw_map(). |
* However, the physical keyboard address can |
* be pretty much unaligned, depending on the |
* underlying controller. |
*/ |
uintptr_t aligned_addr = ALIGN_DOWN(pa, PAGE_SIZE); |
size_t offset = pa - aligned_addr; |
name = ofw_tree_node_name(node); |
z8530_t *z8530 = (z8530_t *) |
(hw_map(aligned_addr, offset + size) + offset); |
z8530_instance_t *z8530_instance = z8530_init(z8530, inr, cir, cir_arg); |
if (z8530_instance) { |
kbrd_instance_t *kbrd_instance = kbrd_init(); |
if (kbrd_instance) { |
indev_t *sink = stdin_wire(); |
indev_t *kbrd = kbrd_wire(kbrd_instance, sink); |
z8530_wire(z8530_instance, kbrd); |
} |
} |
/* |
* Determine keyboard serial controller type. |
* This is the necessary evil until the userspace drivers are |
* entirely self-sufficient. |
*/ |
if (strcmp(name, "zs") == 0) |
kbd_type = KBD_Z8530; |
else if (strcmp(name, "su") == 0) |
kbd_type = KBD_NS16550; |
sysinfo_set_item_val("kbd", NULL, true); |
sysinfo_set_item_val("kbd.inr", NULL, inr); |
sysinfo_set_item_val("kbd.address.kernel", NULL, |
(uintptr_t) z8530); |
sysinfo_set_item_val("kbd.address.physical", NULL, pa); |
sysinfo_set_item_val("kbd.type.z8530", NULL, true); |
if (kbd_type == KBD_UNKNOWN) { |
printf("Unknown keyboard device.\n"); |
return; |
} |
return true; |
} |
#endif /* CONFIG_Z8530 */ |
#ifdef CONFIG_NS16550 |
static bool kbd_ns16550_init(ofw_tree_node_t *node) |
{ |
const char *name = ofw_tree_node_name(node); |
if (str_cmp(name, "su") != 0) |
return false; |
/* |
* Read 'interrupts' property. |
*/ |
uint32_t interrupts; |
prop = ofw_tree_getprop(node, "interrupts"); |
if ((!prop) || (!prop->value)) |
panic("Cannot find 'interrupt' property."); |
interrupts = *((uint32_t *) prop->value); |
ofw_tree_property_t *prop = ofw_tree_getprop(node, "interrupts"); |
if ((!prop) || (!prop->value)) { |
printf("ns16550: Unable to find interrupts property\n"); |
return false; |
} |
uint32_t interrupts = *((uint32_t *) prop->value); |
/* |
* Read 'reg' property. |
*/ |
prop = ofw_tree_getprop(node, "reg"); |
if ((!prop) || (!prop->value)) |
panic("Cannot find 'reg' property."); |
if ((!prop) || (!prop->value)) { |
printf("ns16550: Unable to find reg property\n"); |
return false; |
} |
size_t size = ((ofw_ebus_reg_t *) prop->value)->size; |
uintptr_t pa; |
size_t size; |
if (!ofw_ebus_apply_ranges(node->parent, |
((ofw_ebus_reg_t *) prop->value), &pa)) { |
printf("ns16550: Failed to determine address\n"); |
return false; |
} |
inr_t inr; |
switch (kbd_type) { |
case KBD_Z8530: |
size = ((ofw_fhc_reg_t *) prop->value)->size; |
if (!ofw_fhc_apply_ranges(node->parent, |
((ofw_fhc_reg_t *) prop->value), &pa)) { |
printf("Failed to determine keyboard address.\n"); |
return; |
} |
if (!ofw_fhc_map_interrupt(node->parent, |
((ofw_fhc_reg_t *) prop->value), interrupts, &inr, &cir, |
&cir_arg)) { |
printf("Failed to determine keyboard interrupt.\n"); |
return; |
} |
break; |
case KBD_NS16550: |
size = ((ofw_ebus_reg_t *) prop->value)->size; |
if (!ofw_ebus_apply_ranges(node->parent, |
((ofw_ebus_reg_t *) prop->value), &pa)) { |
printf("Failed to determine keyboard address.\n"); |
return; |
} |
if (!ofw_ebus_map_interrupt(node->parent, |
((ofw_ebus_reg_t *) prop->value), interrupts, &inr, &cir, |
&cir_arg)) { |
printf("Failed to determine keyboard interrupt.\n"); |
return; |
}; |
break; |
default: |
panic("Unexpected keyboard type."); |
cir_t cir; |
void *cir_arg; |
if (!ofw_ebus_map_interrupt(node->parent, |
((ofw_ebus_reg_t *) prop->value), interrupts, &inr, &cir, |
&cir_arg)) { |
printf("ns16550: Failed to determine interrupt\n"); |
return false; |
} |
/* |
156,59 → 196,58 |
* be pretty much unaligned, depending on the |
* underlying controller. |
*/ |
aligned_addr = ALIGN_DOWN(pa, PAGE_SIZE); |
offset = pa - aligned_addr; |
uintptr_t aligned_addr = ALIGN_DOWN(pa, PAGE_SIZE); |
size_t offset = pa - aligned_addr; |
switch (kbd_type) { |
ns16550_t *ns16550 = (ns16550_t *) |
(hw_map(aligned_addr, offset + size) + offset); |
ns16550_instance_t *ns16550_instance = ns16550_init(ns16550, inr, cir, cir_arg); |
if (ns16550_instance) { |
kbrd_instance_t *kbrd_instance = kbrd_init(); |
if (kbrd_instance) { |
indev_t *sink = stdin_wire(); |
indev_t *kbrd = kbrd_wire(kbrd_instance, sink); |
ns16550_wire(ns16550_instance, kbrd); |
} |
} |
/* |
* This is the necessary evil until the userspace drivers are |
* entirely self-sufficient. |
*/ |
sysinfo_set_item_val("kbd", NULL, true); |
sysinfo_set_item_val("kbd.inr", NULL, inr); |
sysinfo_set_item_val("kbd.address.kernel", NULL, |
(uintptr_t) ns16550); |
sysinfo_set_item_val("kbd.address.physical", NULL, pa); |
sysinfo_set_item_val("kbd.type.ns16550", NULL, true); |
return true; |
} |
#endif /* CONFIG_NS16550 */ |
/** Initialize keyboard. |
* |
* Traverse OpenFirmware device tree in order to find necessary |
* info about the keyboard device. |
* |
* @param node Keyboard device node. |
* |
*/ |
void kbd_init(ofw_tree_node_t *node) |
{ |
#ifdef CONFIG_Z8530 |
case KBD_Z8530: |
z8530 = (z8530_t *) hw_map(aligned_addr, offset + size) + |
offset; |
indev_t *kbrdin_z8530 = z8530_init(z8530, inr, cir, cir_arg); |
if (kbrdin_z8530) |
kbrd_init(kbrdin_z8530); |
/* |
* This is the necessary evil until the userspace drivers are |
* entirely self-sufficient. |
*/ |
sysinfo_set_item_val("kbd", NULL, true); |
sysinfo_set_item_val("kbd.type", NULL, KBD_Z8530); |
sysinfo_set_item_val("kbd.inr", NULL, inr); |
sysinfo_set_item_val("kbd.address.kernel", NULL, |
(uintptr_t) z8530); |
sysinfo_set_item_val("kbd.address.physical", NULL, pa); |
break; |
kbd_z8530_init(node); |
#endif |
#ifdef CONFIG_NS16550 |
case KBD_NS16550: |
ns16550 = (ns16550_t *) hw_map(aligned_addr, offset + size) + |
offset; |
indev_t *kbrdin_ns16550 = ns16550_init(ns16550, inr, cir, cir_arg); |
if (kbrdin_ns16550) |
kbrd_init(kbrdin_ns16550); |
/* |
* This is the necessary evil until the userspace driver is |
* entirely self-sufficient. |
*/ |
sysinfo_set_item_val("kbd", NULL, true); |
sysinfo_set_item_val("kbd.type", NULL, KBD_NS16550); |
sysinfo_set_item_val("kbd.inr", NULL, inr); |
sysinfo_set_item_val("kbd.address.kernel", NULL, |
(uintptr_t) ns16550); |
sysinfo_set_item_val("kbd.address.physical", NULL, pa); |
break; |
kbd_ns16550_init(node); |
#endif |
default: |
printf("Kernel is not compiled with the necessary keyboard " |
"driver this machine requires.\n"); |
} |
} |
#endif |
#endif /* CONFIG_SUN_KBD */ |
/** @} |
*/ |
/branches/dynload/kernel/arch/sparc64/src/drivers/scr.c |
---|
63,13 → 63,13 |
name = ofw_tree_node_name(node); |
if (strcmp(name, "SUNW,m64B") == 0) |
if (str_cmp(name, "SUNW,m64B") == 0) |
scr_type = SCR_ATYFB; |
else if (strcmp(name, "SUNW,XVR-100") == 0) |
else if (str_cmp(name, "SUNW,XVR-100") == 0) |
scr_type = SCR_XVR; |
else if (strcmp(name, "SUNW,ffb") == 0) |
else if (str_cmp(name, "SUNW,ffb") == 0) |
scr_type = SCR_FFB; |
else if (strcmp(name, "cgsix") == 0) |
else if (str_cmp(name, "cgsix") == 0) |
scr_type = SCR_CGSIX; |
if (scr_type == SCR_UNKNOWN) { |
/branches/dynload/kernel/arch/sparc64/src/drivers/sgcn.c |
---|
31,7 → 31,7 |
*/ |
/** |
* @file |
* @brief SGCN driver. |
* @brief SGCN driver. |
*/ |
#include <arch.h> |
101,9 → 101,6 |
/** Returns a pointer to the console buffer header. */ |
#define SGCN_BUFFER_HEADER (SGCN_BUFFER(sgcn_buffer_header_t, 0)) |
/** defined in drivers/kbd.c */ |
extern kbd_type_t kbd_type; |
/** starting address of SRAM, will be set by the init_sram_begin function */ |
static uintptr_t sram_begin; |
130,7 → 127,7 |
/* functions referenced from definitions of I/O operations structures */ |
static void sgcn_putchar(outdev_t *, const char, bool); |
static void sgcn_putchar(outdev_t *, const wchar_t, bool); |
/** SGCN output device operations */ |
static outdev_operations_t sgcnout_ops = { |
137,12 → 134,6 |
.write = sgcn_putchar |
}; |
/** SGCN input device operations */ |
static indev_operations_t sgcnin_ops = { |
.poll = NULL |
}; |
static indev_t sgcnin; /**< SGCN input device. */ |
static outdev_t sgcnout; /**< SGCN output device. */ |
/** |
207,12 → 198,12 |
init_sram_begin(); |
ASSERT(strcmp(SRAM_TOC->magic, SRAM_TOC_MAGIC) == 0); |
ASSERT(str_cmp(SRAM_TOC->magic, SRAM_TOC_MAGIC) == 0); |
/* lookup TOC entry with the correct key */ |
uint32_t i; |
for (i = 0; i < MAX_TOC_ENTRIES; i++) { |
if (strcmp(SRAM_TOC->keys[i].key, CONSOLE_KEY) == 0) |
if (str_cmp(SRAM_TOC->keys[i].key, CONSOLE_KEY) == 0) |
break; |
} |
ASSERT(i < MAX_TOC_ENTRIES); |
264,18 → 255,20 |
} |
/** |
* SGCN output operation. Prints a single character to the SGCN. If the line |
* feed character is written ('\n'), the carriage return character ('\r') is |
* written straight away. |
* SGCN output operation. Prints a single character to the SGCN. Newline |
* character is converted to CRLF. |
*/ |
static void sgcn_putchar(outdev_t *od, const char c, bool silent) |
static void sgcn_putchar(outdev_t *od, const wchar_t ch, bool silent) |
{ |
if (!silent) { |
spinlock_lock(&sgcn_output_lock); |
sgcn_do_putchar(c); |
if (c == '\n') |
sgcn_do_putchar('\r'); |
if (ascii_check(ch)) { |
if (ch == '\n') |
sgcn_do_putchar('\r'); |
sgcn_do_putchar(ch); |
} else |
sgcn_do_putchar(U_SPECIAL); |
spinlock_unlock(&sgcn_output_lock); |
} |
286,7 → 279,7 |
*/ |
void sgcn_grab(void) |
{ |
kbd_disabled = true; |
kbd_disabled = false; |
} |
/** |
302,7 → 295,7 |
* there are some unread characters in the input queue. If so, it picks them up |
* and sends them to the upper layers of HelenOS. |
*/ |
static void sgcn_poll() |
static void sgcn_poll(sgcn_instance_t *instance) |
{ |
uint32_t begin = SGCN_BUFFER_HEADER->in_begin; |
uint32_t end = SGCN_BUFFER_HEADER->in_end; |
320,13 → 313,12 |
volatile uint32_t *in_rdptr_ptr = &(SGCN_BUFFER_HEADER->in_rdptr); |
while (*in_rdptr_ptr != *in_wrptr_ptr) { |
buf_ptr = (volatile char *) |
SGCN_BUFFER(char, SGCN_BUFFER_HEADER->in_rdptr); |
char c = *buf_ptr; |
*in_rdptr_ptr = (((*in_rdptr_ptr) - begin + 1) % size) + begin; |
indev_push_character(&sgcnin, c); |
indev_push_character(instance->srlnin, c); |
} |
spinlock_unlock(&sgcn_input_lock); |
335,11 → 327,10 |
/** |
* Polling thread function. |
*/ |
static void kkbdpoll(void *arg) { |
static void ksgcnpoll(void *instance) { |
while (1) { |
if (!silent) { |
sgcn_poll(); |
} |
if (!silent) |
sgcn_poll(instance); |
thread_usleep(POLL_INTERVAL); |
} |
} |
347,23 → 338,36 |
/** |
* A public function which initializes input from the Serengeti console. |
*/ |
indev_t *sgcnin_init(void) |
sgcn_instance_t *sgcnin_init(void) |
{ |
sgcn_buffer_begin_init(); |
sgcn_instance_t *instance = |
malloc(sizeof(sgcn_instance_t), FRAME_ATOMIC); |
if (instance) { |
instance->srlnin = NULL; |
instance->thread = thread_create(ksgcnpoll, instance, TASK, 0, |
"ksgcnpoll", true); |
if (!instance->thread) { |
free(instance); |
return NULL; |
} |
} |
return instance; |
} |
kbd_type = KBD_SGCN; |
void sgcnin_wire(sgcn_instance_t *instance, indev_t *srlnin) |
{ |
ASSERT(instance); |
ASSERT(srlnin); |
instance->srlnin = srlnin; |
thread_ready(instance->thread); |
sysinfo_set_item_val("kbd", NULL, true); |
sysinfo_set_item_val("kbd.type", NULL, KBD_SGCN); |
thread_t *t = thread_create(kkbdpoll, NULL, TASK, 0, "kkbdpoll", true); |
if (!t) |
panic("Cannot create kkbdpoll."); |
thread_ready(t); |
indev_initialize("sgcnin", &sgcnin, &sgcnin_ops); |
return &sgcnin; |
} |
/** |
/branches/dynload/kernel/arch/sparc64/src/drivers/pci.c |
---|
183,7 → 183,7 |
/* |
* First, verify this is a PCI node. |
*/ |
ASSERT(strcmp(ofw_tree_node_name(node), "pci") == 0); |
ASSERT(str_cmp(ofw_tree_node_name(node), "pci") == 0); |
/* |
* Determine PCI controller model. |
192,13 → 192,13 |
if (!prop || !prop->value) |
return NULL; |
if (strcmp(prop->value, "SUNW,sabre") == 0) { |
if (str_cmp(prop->value, "SUNW,sabre") == 0) { |
/* |
* PCI controller Sabre. |
* This model is found on UltraSPARC IIi based machines. |
*/ |
return pci_sabre_init(node); |
} else if (strcmp(prop->value, "SUNW,psycho") == 0) { |
} else if (str_cmp(prop->value, "SUNW,psycho") == 0) { |
/* |
* PCI controller Psycho. |
* Used on UltraSPARC II based processors, for instance, |
/branches/dynload/kernel/arch/sparc64/src/start.S |
---|
84,7 → 84,7 |
! l5 <= physmem_base[(PHYSMEM_ADDR_SIZE - 1):13] |
sllx %l5, 13 + (63 - (PHYSMEM_ADDR_SIZE - 1)), %l5 |
srlx %l5, 63 - (PHYSMEM_ADDR_SIZE - 1), %l5 |
/* |
* Setup basic runtime environment. |
*/ |
294,7 → 294,7 |
/* Not reached. */ |
0: |
ba 0b |
ba %xcc, 0b |
nop |
333,7 → 333,7 |
2: |
ldx [%g2], %g3 |
cmp %g3, %g1 |
bne 2b |
bne %xcc, 2b |
nop |
/* |
352,7 → 352,7 |
#endif |
0: |
ba 0b |
ba %xcc, 0b |
nop |
381,10 → 381,31 |
.quad 0 |
/* |
* This variable is used by the fast_data_MMU_miss trap handler. In runtime, it |
* is further modified to reflect the starting address of physical memory. |
* The fast_data_access_mmu_miss_data_hi label and the end_of_identity and |
* kernel_8k_tlb_data_template variables are meant to stay together, |
* aligned on 16B boundary. |
*/ |
.global fast_data_access_mmu_miss_data_hi |
.global end_of_identity |
.global kernel_8k_tlb_data_template |
.align 16 |
/* |
* This label is used by the fast_data_access_MMU_miss trap handler. |
*/ |
fast_data_access_mmu_miss_data_hi: |
/* |
* This variable is used by the fast_data_access_MMU_miss trap handler. |
* In runtime, it is modified to contain the address of the end of physical |
* memory. |
*/ |
end_of_identity: |
.quad -1 |
/* |
* This variable is used by the fast_data_access_MMU_miss trap handler. |
* In runtime, it is further modified to reflect the starting address of |
* physical memory. |
*/ |
kernel_8k_tlb_data_template: |
#ifdef CONFIG_VIRT_IDX_DCACHE |
.quad ((1 << TTE_V_SHIFT) | (PAGESIZE_8K << TTE_SIZE_SHIFT) | TTE_CP | \ |
/branches/dynload/kernel/arch/ia64/include/ski/ski.h |
---|
File deleted |
/branches/dynload/kernel/arch/ia64/include/arch.h |
---|
26,7 → 26,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup ia64 |
/** @addtogroup ia64 |
* @{ |
*/ |
/** @file |
37,7 → 37,7 |
#define LOADED_PROG_STACK_PAGES_NO 2 |
#include <arch/ski/ski.h> |
#include <arch/drivers/ski.h> |
extern void arch_pre_main(void); |
/branches/dynload/kernel/arch/ia64/include/asm.h |
---|
46,7 → 46,7 |
{ |
uintptr_t prt = (uintptr_t) port; |
*((uint8_t *)(IA64_IOSPACE_ADDRESS + |
*((ioport8_t *)(IA64_IOSPACE_ADDRESS + |
((prt & 0xfff) | ((prt >> 2) << 12)))) = v; |
asm volatile ("mf\n" ::: "memory"); |
56,7 → 56,7 |
{ |
uintptr_t prt = (uintptr_t) port; |
*((uint16_t *)(IA64_IOSPACE_ADDRESS + |
*((ioport16_t *)(IA64_IOSPACE_ADDRESS + |
((prt & 0xfff) | ((prt >> 2) << 12)))) = v; |
asm volatile ("mf\n" ::: "memory"); |
66,7 → 66,7 |
{ |
uintptr_t prt = (uintptr_t) port; |
*((uint32_t *)(IA64_IOSPACE_ADDRESS + |
*((ioport32_t *)(IA64_IOSPACE_ADDRESS + |
((prt & 0xfff) | ((prt >> 2) << 12)))) = v; |
asm volatile ("mf\n" ::: "memory"); |
78,7 → 78,7 |
asm volatile ("mf\n" ::: "memory"); |
return *((uint8_t *)(IA64_IOSPACE_ADDRESS + |
return *((ioport8_t *)(IA64_IOSPACE_ADDRESS + |
((prt & 0xfff) | ((prt >> 2) << 12)))); |
} |
88,7 → 88,7 |
asm volatile ("mf\n" ::: "memory"); |
return *((uint16_t *)(IA64_IOSPACE_ADDRESS + |
return *((ioport16_t *)(IA64_IOSPACE_ADDRESS + |
((prt & 0xfff) | ((prt >> 2) << 12)))); |
} |
98,7 → 98,7 |
asm volatile ("mf\n" ::: "memory"); |
return *((uint32_t *)(IA64_IOSPACE_ADDRESS + |
return *((ioport32_t *)(IA64_IOSPACE_ADDRESS + |
((prt & 0xfff) | ((prt >> 2) << 12)))); |
} |
/branches/dynload/kernel/arch/ia64/include/drivers/ski.h |
---|
0,0 → 1,56 |
/* |
* Copyright (c) 2005 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 ia64 |
* @{ |
*/ |
/** @file |
*/ |
#ifndef KERN_ia64_SKI_H_ |
#define KERN_ia64_SKI_H_ |
#include <console/chardev.h> |
#include <proc/thread.h> |
typedef struct { |
thread_t *thread; |
indev_t *srlnin; |
} ski_instance_t; |
extern void skiout_init(void); |
extern ski_instance_t *skiin_init(void); |
extern void skiin_wire(ski_instance_t *, indev_t *); |
extern void ski_kbd_grab(void); |
extern void ski_kbd_release(void); |
#endif |
/** @} |
*/ |
Property changes: |
Added: svn:mergeinfo |
/branches/dynload/kernel/arch/ia64/Makefile.inc |
---|
64,8 → 64,7 |
arch/$(KARCH)/src/drivers/it.c |
ifeq ($(MACHINE),ski) |
ARCH_SOURCES += arch/$(KARCH)/src/ski/ski.c |
DEFS += -DSKI |
ARCH_SOURCES += arch/$(KARCH)/src/drivers/ski.c |
BFD = binary |
endif |
/branches/dynload/kernel/arch/ia64/src/ski/ski.c |
---|
File deleted |
/branches/dynload/kernel/arch/ia64/src/smp/smp.c |
---|
33,7 → 33,7 |
*/ |
#include <arch.h> |
#include <arch/ski/ski.h> |
#include <arch/drivers/ski.h> |
#include <arch/drivers/it.h> |
#include <arch/interrupt.h> |
#include <arch/barrier.h> |
/branches/dynload/kernel/arch/ia64/src/ia64.c |
---|
33,7 → 33,7 |
*/ |
#include <arch.h> |
#include <arch/ski/ski.h> |
#include <arch/drivers/ski.h> |
#include <arch/drivers/it.h> |
#include <arch/interrupt.h> |
#include <arch/barrier.h> |
87,8 → 87,8 |
((unsigned long) bootinfo->taskmap.tasks[i].addr) | |
VRN_MASK; |
init.tasks[i].size = bootinfo->taskmap.tasks[i].size; |
strncpy(init.tasks[i].name, bootinfo->taskmap.tasks[i].name, |
CONFIG_TASK_NAME_BUFLEN); |
str_cpy(init.tasks[i].name, CONFIG_TASK_NAME_BUFLEN, |
bootinfo->taskmap.tasks[i].name); |
} |
} |
148,11 → 148,17 |
void arch_post_smp_init(void) |
{ |
#ifdef SKI |
indev_t *in; |
in = skiin_init(); |
if (in) |
srln_init(in); |
#ifdef MACHINE_ski |
ski_instance_t *ski_instance = skiin_init(); |
if (ski_instance) { |
srln_instance_t *srln_instance = srln_init(); |
if (srln_instance) { |
indev_t *sink = stdin_wire(); |
indev_t *srln = srln_wire(srln_instance, sink); |
skiin_wire(ski_instance, srln); |
} |
} |
skiout_init(); |
#endif |
161,10 → 167,16 |
#endif |
#ifdef CONFIG_NS16550 |
indev_t *kbrdin_ns16550 |
ns16550_instance_t *ns16550_instance |
= ns16550_init((ns16550_t *) NS16550_BASE, NS16550_IRQ, NULL, NULL); |
if (kbrdin_ns16550) |
srln_init(kbrdin_ns16550); |
if (ns16550_instance) { |
srln_instance_t *srln_instance = srln_init(); |
if (srln_instance) { |
indev_t *sink = stdin_wire(); |
indev_t *srln = srln_wire(srln_instance, sink); |
ns16550_wire(ns16550_instance, srln); |
} |
} |
sysinfo_set_item_val("kbd", NULL, true); |
sysinfo_set_item_val("kbd.inr", NULL, NS16550_IRQ); |
176,9 → 188,15 |
#endif |
#ifdef CONFIG_I8042 |
indev_t *kbrdin_i8042 = i8042_init((i8042_t *) I8042_BASE, IRQ_KBD); |
if (kbrdin_i8042) |
kbrd_init(kbrdin_i8042); |
i8042_instance_t *i8042_instance = i8042_init((i8042_t *) I8042_BASE, IRQ_KBD); |
if (i8042_instance) { |
kbrd_instance_t *kbrd_instance = kbrd_init(); |
if (kbrd_instance) { |
indev_t *sink = stdin_wire(); |
indev_t *kbrd = kbrd_wire(kbrd_instance, sink); |
i8042_wire(i8042_instance, kbrd); |
} |
} |
sysinfo_set_item_val("kbd", NULL, true); |
sysinfo_set_item_val("kbd.inr", NULL, IRQ_KBD); |
238,7 → 256,7 |
*/ |
void arch_grab_console(void) |
{ |
#ifdef SKI |
#ifdef MACHINE_ski |
ski_kbd_grab(); |
#endif |
} |
248,7 → 266,7 |
*/ |
void arch_release_console(void) |
{ |
#ifdef SKI |
#ifdef MACHINE_ski |
ski_kbd_release(); |
#endif |
} |
/branches/dynload/kernel/arch/ia64/src/cpu/cpu.c |
---|
55,7 → 55,7 |
*((uint64_t *) &vendor[0 * sizeof(uint64_t)]) = CPU->arch.cpuid0; |
*((uint64_t *) &vendor[1 * sizeof(uint64_t)]) = CPU->arch.cpuid1; |
vendor[sizeof(vendor) - 1] = '\0'; |
vendor[sizeof(vendor) - 1] = 0; |
switch(m->arch.cpuid3.family) { |
case FAMILY_ITANIUM: |
/branches/dynload/kernel/arch/ia64/src/interrupt.c |
---|
54,6 → 54,7 |
#include <synch/spinlock.h> |
#include <mm/tlb.h> |
#include <symtab.h> |
#include <putchar.h> |
#define VECTORS_64_BUNDLE 20 |
#define VECTORS_16_BUNDLE 48 |
/branches/dynload/kernel/arch/ia64/src/drivers/ski.c |
---|
0,0 → 1,227 |
/* |
* Copyright (c) 2005 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 ia64 |
* @{ |
*/ |
/** @file |
*/ |
#include <arch/drivers/ski.h> |
#include <console/console.h> |
#include <console/chardev.h> |
#include <sysinfo/sysinfo.h> |
#include <arch/types.h> |
#include <proc/thread.h> |
#include <synch/spinlock.h> |
#include <arch/asm.h> |
#include <arch/drivers/kbd.h> |
#include <string.h> |
#include <arch.h> |
#define POLL_INTERVAL 10000 /* 10 ms */ |
#define SKI_INIT_CONSOLE 20 |
#define SKI_GETCHAR 21 |
#define SKI_PUTCHAR 31 |
static void ski_putchar(outdev_t *, const wchar_t, bool); |
static outdev_operations_t skiout_ops = { |
.write = ski_putchar |
}; |
static outdev_t skiout; /**< Ski output device. */ |
static bool initialized = false; |
static bool kbd_disabled = false; |
/** Initialize debug console |
* |
* Issue SSC (Simulator System Call) to |
* to open debug console. |
* |
*/ |
static void ski_init(void) |
{ |
if (initialized) |
return; |
asm volatile ( |
"mov r15 = %0\n" |
"break 0x80000\n" |
: |
: "i" (SKI_INIT_CONSOLE) |
: "r15", "r8" |
); |
initialized = true; |
} |
static void ski_do_putchar(const wchar_t ch) |
{ |
asm volatile ( |
"mov r15 = %[cmd]\n" |
"mov r32 = %[ch]\n" /* r32 is in0 */ |
"break 0x80000\n" /* modifies r8 */ |
: |
: [cmd] "i" (SKI_PUTCHAR), [ch] "r" (ch) |
: "r15", "in0", "r8" |
); |
} |
/** Display character on debug console |
* |
* Use SSC (Simulator System Call) to |
* display character on debug console. |
* |
* @param dev Character device. |
* @param ch Character to be printed. |
* @param silent Whether the output should be silenced. |
* |
*/ |
static void ski_putchar(outdev_t *dev, const wchar_t ch, bool silent) |
{ |
if (!silent) { |
if (ascii_check(ch)) { |
if (ch == '\n') |
ski_do_putchar('\r'); |
ski_do_putchar(ch); |
} else |
ski_do_putchar(U_SPECIAL); |
} |
} |
void skiout_init(void) |
{ |
ski_init(); |
outdev_initialize("skiout", &skiout, &skiout_ops); |
stdout = &skiout; |
sysinfo_set_item_val("fb", NULL, false); |
} |
/** Ask debug console if a key was pressed. |
* |
* Use SSC (Simulator System Call) to |
* get character from debug console. |
* |
* This call is non-blocking. |
* |
* @return ASCII code of pressed key or 0 if no key pressed. |
* |
*/ |
static wchar_t ski_getchar(void) |
{ |
uint64_t ch; |
asm volatile ( |
"mov r15 = %1\n" |
"break 0x80000;;\n" /* modifies r8 */ |
"mov %0 = r8;;\n" |
: "=r" (ch) |
: "i" (SKI_GETCHAR) |
: "r15", "r8" |
); |
return (wchar_t) ch; |
} |
/** Ask keyboard if a key was pressed. */ |
static void poll_keyboard(ski_instance_t *instance) |
{ |
if (kbd_disabled) |
return; |
wchar_t ch = ski_getchar(); |
if (ch != 0) |
indev_push_character(instance->srlnin, ch); |
} |
/** Kernel thread for polling keyboard. */ |
static void kskipoll(void *arg) |
{ |
ski_instance_t *instance = (ski_instance_t *) arg; |
while (true) { |
if (!silent) |
poll_keyboard(instance); |
thread_usleep(POLL_INTERVAL); |
} |
} |
ski_instance_t *skiin_init(void) |
{ |
ski_init(); |
ski_instance_t *instance = |
malloc(sizeof(ski_instance_t), FRAME_ATOMIC); |
if (instance) { |
instance->thread = thread_create(kskipoll, instance, TASK, 0, |
"kskipoll", true); |
if (!instance->thread) { |
free(instance); |
return NULL; |
} |
instance->srlnin = NULL; |
} |
return instance; |
} |
void skiin_wire(ski_instance_t *instance, indev_t *srlnin) |
{ |
ASSERT(instance); |
ASSERT(srlnin); |
instance->srlnin = srlnin; |
thread_ready(instance->thread); |
sysinfo_set_item_val("kbd", NULL, true); |
sysinfo_set_item_val("kbd.type", NULL, KBD_SKI); |
} |
void ski_kbd_grab(void) |
{ |
kbd_disabled = false; |
} |
void ski_kbd_release(void) |
{ |
kbd_disabled = true; |
} |
/** @} |
*/ |
Property changes: |
Added: svn:mergeinfo |
/branches/dynload/kernel/arch/arm32/include/console.h |
---|
File deleted |
/branches/dynload/kernel/arch/arm32/Makefile.inc |
---|
51,7 → 51,6 |
arch/$(KARCH)/src/cpu/cpu.c \ |
arch/$(KARCH)/src/ddi/ddi.c \ |
arch/$(KARCH)/src/interrupt.c \ |
arch/$(KARCH)/src/console.c \ |
arch/$(KARCH)/src/exception.c \ |
arch/$(KARCH)/src/userspace.c \ |
arch/$(KARCH)/src/mm/as.c \ |
/branches/dynload/kernel/arch/arm32/src/console.c |
---|
File deleted |
/branches/dynload/kernel/arch/arm32/src/asm.S |
---|
30,6 → 30,7 |
.text |
.global memsetb |
.global memsetw |
.global memcpy |
.global memcpy_from_uspace |
.global memcpy_to_uspace |
39,6 → 40,9 |
memsetb: |
b _memsetb |
memsetw: |
b _memsetw |
memcpy: |
memcpy_from_uspace: |
memcpy_to_uspace: |
/branches/dynload/kernel/arch/arm32/src/arm32.c |
---|
35,7 → 35,6 |
#include <arch.h> |
#include <config.h> |
#include <arch/console.h> |
#include <genarch/fb/fb.h> |
#include <genarch/fb/visuals.h> |
#include <genarch/drivers/dsrln/dsrlnin.h> |
42,6 → 41,7 |
#include <genarch/drivers/dsrln/dsrlnout.h> |
#include <genarch/srln/srln.h> |
#include <sysinfo/sysinfo.h> |
#include <console/console.h> |
#include <ddi/irq.h> |
#include <arch/drivers/gxemul.h> |
#include <print.h> |
62,8 → 62,8 |
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; |
strncpy(init.tasks[i].name, bootinfo->tasks[i].name, |
CONFIG_TASK_NAME_BUFLEN); |
str_cpy(init.tasks[i].name, CONFIG_TASK_NAME_BUFLEN, |
bootinfo->tasks[i].name); |
} |
} |
128,12 → 128,19 |
{ |
#ifdef CONFIG_ARM_KBD |
/* |
* Initialize the msim/GXemul keyboard port. Then initialize the serial line |
* module and connect it to the msim/GXemul keyboard. Enable keyboard interrupts. |
* Initialize the GXemul keyboard port. Then initialize the serial line |
* module and connect it to the GXemul keyboard. |
*/ |
indev_t *kbrdin = dsrlnin_init((dsrlnin_t *) gxemul_kbd, GXEMUL_KBD_IRQ); |
if (kbrdin) |
srln_init(kbrdin); |
dsrlnin_instance_t *dsrlnin_instance |
= dsrlnin_init((dsrlnin_t *) gxemul_kbd, GXEMUL_KBD_IRQ); |
if (dsrlnin_instance) { |
srln_instance_t *srln_instance = srln_init(); |
if (srln_instance) { |
indev_t *sink = stdin_wire(); |
indev_t *srln = srln_wire(srln_instance, sink); |
dsrlnin_wire(dsrlnin_instance, srln); |
} |
} |
/* |
* This is the necessary evil until the userspace driver is entirely |
201,5 → 208,18 |
return addr; |
} |
/** Acquire console back for kernel. */ |
void arch_grab_console(void) |
{ |
#ifdef CONFIG_FB |
fb_redraw(); |
#endif |
} |
/** Return console to userspace. */ |
void arch_release_console(void) |
{ |
} |
/** @} |
*/ |
/branches/dynload/kernel/arch/ppc32/include/drivers/cuda.h |
---|
File deleted |
/branches/dynload/kernel/arch/ppc32/include/drivers/pic.h |
---|
26,7 → 26,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup ppc32 |
/** @addtogroup ppc32 |
* @{ |
*/ |
/** @file |
36,6 → 36,7 |
#define KERN_ppc32_PIC_H_ |
#include <arch/types.h> |
#include <ddi/irq.h> |
#define PIC_PENDING_LOW 8 |
#define PIC_PENDING_HIGH 4 |
44,11 → 45,11 |
#define PIC_ACK_LOW 10 |
#define PIC_ACK_HIGH 6 |
void pic_init(uintptr_t base, size_t size); |
void pic_enable_interrupt(int intnum); |
void pic_disable_interrupt(int intnum); |
void pic_ack_interrupt(int intnum); |
int pic_get_pending(void); |
extern void pic_init(uintptr_t base, size_t size, cir_t *cir, void **cir_arg); |
extern void pic_enable_interrupt(inr_t intnum); |
extern void pic_disable_interrupt(inr_t intnum); |
extern void pic_ack_interrupt(void *arg, inr_t intnum); |
extern int pic_get_pending(void); |
#endif |
/branches/dynload/kernel/arch/ppc32/Makefile.inc |
---|
54,7 → 54,6 |
arch/$(KARCH)/src/cpu/cpu.c \ |
arch/$(KARCH)/src/proc/scheduler.c \ |
arch/$(KARCH)/src/ddi/ddi.c \ |
arch/$(KARCH)/src/drivers/cuda.c \ |
arch/$(KARCH)/src/mm/as.c \ |
arch/$(KARCH)/src/mm/frame.c \ |
arch/$(KARCH)/src/mm/page.c \ |
/branches/dynload/kernel/arch/ppc32/src/asm.S |
---|
34,6 → 34,7 |
.global iret |
.global iret_syscall |
.global memsetb |
.global memsetw |
.global memcpy |
.global memcpy_from_uspace |
.global memcpy_to_uspace |
201,10 → 202,13 |
lwz sp, 160(sp) |
rfi |
memsetb: |
b _memsetb |
memsetw: |
b _memsetw |
memcpy: |
memcpy_from_uspace: |
memcpy_to_uspace: |
/branches/dynload/kernel/arch/ppc32/src/ppc32.c |
---|
35,7 → 35,7 |
#include <config.h> |
#include <arch.h> |
#include <arch/boot/boot.h> |
#include <arch/drivers/cuda.h> |
#include <genarch/drivers/via-cuda/cuda.h> |
#include <arch/interrupt.h> |
#include <genarch/fb/fb.h> |
#include <genarch/fb/visuals.h> |
44,10 → 44,12 |
#include <console/console.h> |
#include <ddi/irq.h> |
#include <arch/drivers/pic.h> |
#include <align.h> |
#include <macros.h> |
#include <string.h> |
#define IRQ_COUNT 64 |
#define IRQ_CUDA 10 |
bootinfo_t bootinfo; |
61,8 → 63,8 |
for (i = 0; i < min3(bootinfo.taskmap.count, TASKMAP_MAX_RECORDS, CONFIG_INIT_TASKS); i++) { |
init.tasks[i].addr = PA2KA(bootinfo.taskmap.tasks[i].addr); |
init.tasks[i].size = bootinfo.taskmap.tasks[i].size; |
strncpy(init.tasks[i].name, bootinfo.taskmap.tasks[i].name, |
CONFIG_TASK_NAME_BUFLEN); |
str_cpy(init.tasks[i].name, CONFIG_TASK_NAME_BUFLEN, |
bootinfo.taskmap.tasks[i].name); |
} |
} |
117,10 → 119,27 |
if (bootinfo.macio.addr) { |
/* Initialize PIC */ |
pic_init(bootinfo.macio.addr, PAGE_SIZE); |
cir_t cir; |
void *cir_arg; |
pic_init(bootinfo.macio.addr, PAGE_SIZE, &cir, &cir_arg); |
#ifdef CONFIG_VIA_CUDA |
uintptr_t pa = bootinfo.macio.addr + 0x16000; |
uintptr_t aligned_addr = ALIGN_DOWN(pa, PAGE_SIZE); |
size_t offset = pa - aligned_addr; |
size_t size = 2 * PAGE_SIZE; |
cuda_t *cuda = (cuda_t *) |
(hw_map(aligned_addr, offset + size) + offset); |
/* Initialize I/O controller */ |
cuda_init(bootinfo.macio.addr + 0x16000, 2 * PAGE_SIZE); |
cuda_instance_t *cuda_instance = |
cuda_init(cuda, IRQ_CUDA, cir, cir_arg); |
if (cuda_instance) { |
indev_t *sink = stdin_wire(); |
cuda_wire(cuda_instance, sink); |
} |
#endif |
} |
/* Merge all zones to 1 big zone */ |
186,5 → 205,11 |
return addr; |
} |
void arch_reboot(void) |
{ |
// TODO |
while (1); |
} |
/** @} |
*/ |
/branches/dynload/kernel/arch/ppc32/src/dummy.s |
---|
30,6 → 30,7 |
.global asm_delay_loop |
.global sys_tls_set |
.global cpu_halt |
sys_tls_set: |
b sys_tls_set |
36,3 → 37,6 |
asm_delay_loop: |
blr |
cpu_halt: |
b cpu_halt |
/branches/dynload/kernel/arch/ppc32/src/interrupt.c |
---|
60,7 → 60,6 |
int inum; |
while ((inum = pic_get_pending()) != -1) { |
bool ack = false; |
irq_t *irq = irq_dispatch_and_lock(inum); |
if (irq) { |
/* |
69,11 → 68,17 |
if (irq->preack) { |
/* Acknowledge the interrupt before processing */ |
pic_ack_interrupt(inum); |
ack = true; |
if (irq->cir) |
irq->cir(irq->cir_arg, irq->inr); |
} |
irq->handler(irq); |
if (!irq->preack) { |
if (irq->cir) |
irq->cir(irq->cir_arg, irq->inr); |
} |
spinlock_unlock(&irq->lock); |
} else { |
/* |
83,9 → 88,6 |
printf("cpu%u: spurious interrupt (inum=%d)\n", CPU->id, inum); |
#endif |
} |
if (!ack) |
pic_ack_interrupt(inum); |
} |
} |
/branches/dynload/kernel/arch/ppc32/src/drivers/cuda.c |
---|
File deleted |
/branches/dynload/kernel/arch/ppc32/src/drivers/pic.c |
---|
26,7 → 26,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup ppc32 |
/** @addtogroup ppc32 |
* @{ |
*/ |
/** @file |
40,12 → 40,14 |
static volatile uint32_t *pic = NULL; |
void pic_init(uintptr_t base, size_t size) |
void pic_init(uintptr_t base, size_t size, cir_t *cir, void **cir_arg) |
{ |
pic = (uint32_t *) hw_map(base, size); |
*cir = pic_ack_interrupt; |
*cir_arg = NULL; |
} |
void pic_enable_interrupt(int intnum) |
void pic_enable_interrupt(inr_t intnum) |
{ |
if (pic) { |
if (intnum < 32) |
56,7 → 58,7 |
} |
void pic_disable_interrupt(int intnum) |
void pic_disable_interrupt(inr_t intnum) |
{ |
if (pic) { |
if (intnum < 32) |
66,7 → 68,7 |
} |
} |
void pic_ack_interrupt(int intnum) |
void pic_ack_interrupt(void *arg, inr_t intnum) |
{ |
if (pic) { |
if (intnum < 32) |
/branches/dynload/kernel/arch/amd64/src/amd64.c |
---|
197,10 → 197,15 |
* Initialize the i8042 controller. Then initialize the keyboard |
* module and connect it to i8042. Enable keyboard interrupts. |
*/ |
indev_t *kbrdin = i8042_init((i8042_t *) I8042_BASE, IRQ_KBD); |
if (kbrdin) { |
kbrd_init(kbrdin); |
trap_virtual_enable_irqs(1 << IRQ_KBD); |
i8042_instance_t *i8042_instance = i8042_init((i8042_t *) I8042_BASE, IRQ_KBD); |
if (i8042_instance) { |
kbrd_instance_t *kbrd_instance = kbrd_init(); |
if (kbrd_instance) { |
indev_t *sink = stdin_wire(); |
indev_t *kbrd = kbrd_wire(kbrd_instance, sink); |
i8042_wire(i8042_instance, kbrd); |
trap_virtual_enable_irqs(1 << IRQ_KBD); |
} |
} |
/* |
281,5 → 286,12 |
return addr; |
} |
void arch_reboot(void) |
{ |
#ifdef CONFIG_PC_KBD |
i8042_cpu_reset((i8042_t *) I8042_BASE); |
#endif |
} |
/** @} |
*/ |
/branches/dynload/kernel/arch/amd64/src/pm.c |
---|
230,24 → 230,5 |
tr_load(gdtselector(TSS_DES)); |
} |
/* Reboot the machine by initiating |
* a triple fault |
*/ |
void arch_reboot(void) |
{ |
preemption_disable(); |
ipl_t ipl = interrupts_disable(); |
memsetb(idt, sizeof(idt), 0); |
idtr_load(&idtr); |
interrupts_restore(ipl); |
asm volatile ( |
"int $0x03\n" |
"cli\n" |
"hlt\n" |
); |
} |
/** @} |
*/ |
/branches/dynload/kernel/arch/mips32/include/console.h |
---|
File deleted |
/branches/dynload/kernel/arch/mips32/include/elf.h |
---|
35,9 → 35,11 |
#ifndef KERN_mips32_ELF_H_ |
#define KERN_mips32_ELF_H_ |
#include <byteorder.h> |
#define ELF_MACHINE EM_MIPS |
#ifdef BIG_ENDIAN |
#ifdef ARCH_IS_BIG_ENDIAN |
# define ELF_DATA_ENCODING ELFDATA2MSB |
#else |
# define ELF_DATA_ENCODING ELFDATA2LSB |
/branches/dynload/kernel/arch/mips32/Makefile.inc |
---|
60,7 → 60,6 |
arch/$(KARCH)/src/context.S \ |
arch/$(KARCH)/src/panic.S \ |
arch/$(KARCH)/src/mips32.c \ |
arch/$(KARCH)/src/console.c \ |
arch/$(KARCH)/src/asm.S \ |
arch/$(KARCH)/src/exception.c \ |
arch/$(KARCH)/src/interrupt.c \ |
/branches/dynload/kernel/arch/mips32/src/console.c |
---|
File deleted |
/branches/dynload/kernel/arch/mips32/src/asm.S |
---|
63,6 → 63,12 |
nop |
.global memsetw |
memsetw: |
j _memsetw |
nop |
.global memcpy |
.global memcpy_from_uspace |
.global memcpy_to_uspace |
/branches/dynload/kernel/arch/mips32/src/mips32.c |
---|
36,16 → 36,14 |
#include <arch/cp0.h> |
#include <arch/exception.h> |
#include <mm/as.h> |
#include <userspace.h> |
#include <arch/console.h> |
#include <memstr.h> |
#include <proc/thread.h> |
#include <proc/uarg.h> |
#include <print.h> |
#include <console/console.h> |
#include <syscall/syscall.h> |
#include <sysinfo/sysinfo.h> |
#include <arch/interrupt.h> |
#include <console/chardev.h> |
#include <arch/barrier.h> |
59,7 → 57,6 |
#include <config.h> |
#include <string.h> |
#include <arch/drivers/msim.h> |
#include <arch/asm/regname.h> |
/* Size of the code jumping to the exception handler code |
91,8 → 88,8 |
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; |
strncpy(init.tasks[i].name, bootinfo->tasks[i].name, |
CONFIG_TASK_NAME_BUFLEN); |
str_cpy(init.tasks[i].name, CONFIG_TASK_NAME_BUFLEN, |
bootinfo->tasks[i].name); |
} |
for (i = 0; i < CPUMAP_MAX_RECORDS; i++) { |
169,10 → 166,16 |
* Initialize the msim/GXemul keyboard port. Then initialize the serial line |
* module and connect it to the msim/GXemul keyboard. Enable keyboard interrupts. |
*/ |
indev_t *kbrdin = dsrlnin_init((dsrlnin_t *) MSIM_KBD_ADDRESS, MSIM_KBD_IRQ); |
if (kbrdin) { |
srln_init(kbrdin); |
cp0_unmask_int(MSIM_KBD_IRQ); |
dsrlnin_instance_t *dsrlnin_instance |
= dsrlnin_init((dsrlnin_t *) MSIM_KBD_ADDRESS, MSIM_KBD_IRQ); |
if (dsrlnin_instance) { |
srln_instance_t *srln_instance = srln_init(); |
if (srln_instance) { |
indev_t *sink = stdin_wire(); |
indev_t *srln = srln_wire(srln_instance, sink); |
dsrlnin_wire(dsrlnin_instance, srln); |
cp0_unmask_int(MSIM_KBD_IRQ); |
} |
} |
/* |
248,5 → 251,19 |
return addr; |
} |
void arch_grab_console(void) |
{ |
#ifdef CONFIG_FB |
fb_redraw(); |
#endif |
} |
/** Return console to userspace |
* |
*/ |
void arch_release_console(void) |
{ |
} |
/** @} |
*/ |
/branches/dynload/kernel/arch/ia32/src/ia32.c |
---|
80,7 → 80,7 |
void arch_pre_main(uint32_t signature, const multiboot_info_t *mi) |
{ |
/* Parse multiboot information obtained from the bootloader. */ |
multiboot_info_parse(signature, mi); |
multiboot_info_parse(signature, mi); |
#ifdef CONFIG_SMP |
/* Copy AP bootstrap routines below 1 MB. */ |
155,10 → 155,15 |
* Initialize the i8042 controller. Then initialize the keyboard |
* module and connect it to i8042. Enable keyboard interrupts. |
*/ |
indev_t *kbrdin = i8042_init((i8042_t *) I8042_BASE, IRQ_KBD); |
if (kbrdin) { |
kbrd_init(kbrdin); |
trap_virtual_enable_irqs(1 << IRQ_KBD); |
i8042_instance_t *i8042_instance = i8042_init((i8042_t *) I8042_BASE, IRQ_KBD); |
if (i8042_instance) { |
kbrd_instance_t *kbrd_instance = kbrd_init(); |
if (kbrd_instance) { |
indev_t *sink = stdin_wire(); |
indev_t *kbrd = kbrd_wire(kbrd_instance, sink); |
i8042_wire(i8042_instance, kbrd); |
trap_virtual_enable_irqs(1 << IRQ_KBD); |
} |
} |
/* |
237,5 → 242,12 |
return addr; |
} |
void arch_reboot(void) |
{ |
#ifdef CONFIG_PC_KBD |
i8042_cpu_reset((i8042_t *) I8042_BASE); |
#endif |
} |
/** @} |
*/ |
/branches/dynload/kernel/arch/ia32/src/pm.c |
---|
232,28 → 232,5 |
gdtr_load(&cpugdtr); |
} |
/* Reboot the machine by initiating |
* a triple fault |
*/ |
void arch_reboot(void) |
{ |
preemption_disable(); |
ipl_t ipl = interrupts_disable(); |
memsetb(idt, sizeof(idt), 0); |
ptr_16_32_t idtr; |
idtr.limit = sizeof(idt); |
idtr.base = (uintptr_t) idt; |
idtr_load(&idtr); |
interrupts_restore(ipl); |
asm volatile ( |
"int $0x03\n" |
"cli\n" |
"hlt\n" |
); |
} |
/** @} |
*/ |