From e94953a39641f8015cd22f5dd05883c0e14e70e8 Mon Sep 17 00:00:00 2001 From: Dirk Vogt Date: Fri, 25 Feb 2011 12:40:31 +0000 Subject: [PATCH] added libddekit --- lib/Makefile | 3 +- lib/libddekit/Makefile | 6 + lib/libddekit/build/Makefile | 6 + lib/libddekit/build/ddekit/Makefile | 11 + .../build/ddekit_usb_client/Makefile | 9 + .../build/ddekit_usb_server/Makefile | 10 + lib/libddekit/src/common.h | 14 + lib/libddekit/src/condvar.c | 119 +++ lib/libddekit/src/dde.c | 138 +++ lib/libddekit/src/dde.h | 1 + lib/libddekit/src/debug.h | 7 + lib/libddekit/src/initcall.c | 57 ++ lib/libddekit/src/irq.c | 257 ++++++ lib/libddekit/src/irq.h | 5 + lib/libddekit/src/lock.c | 118 +++ lib/libddekit/src/mem.c | 460 ++++++++++ lib/libddekit/src/msg_queue.c | 155 ++++ lib/libddekit/src/panic.c | 34 + lib/libddekit/src/pci.c | 447 ++++++++++ lib/libddekit/src/pgtab.c | 313 +++++++ lib/libddekit/src/printf.c | 33 + lib/libddekit/src/resource.c | 138 +++ lib/libddekit/src/semaphore.c | 111 +++ lib/libddekit/src/thread.c | 499 +++++++++++ lib/libddekit/src/thread.h | 42 + lib/libddekit/src/timer.c | 315 +++++++ lib/libddekit/src/timer.h | 11 + lib/libddekit/src/usb_client.c | 223 +++++ lib/libddekit/src/usb_server.c | 805 ++++++++++++++++++ lib/libddekit/src/util.h | 3 + share/mk/bsd.prog.mk | 2 +- 31 files changed, 4350 insertions(+), 2 deletions(-) create mode 100644 lib/libddekit/Makefile create mode 100644 lib/libddekit/build/Makefile create mode 100644 lib/libddekit/build/ddekit/Makefile create mode 100644 lib/libddekit/build/ddekit_usb_client/Makefile create mode 100644 lib/libddekit/build/ddekit_usb_server/Makefile create mode 100644 lib/libddekit/src/common.h create mode 100644 lib/libddekit/src/condvar.c create mode 100644 lib/libddekit/src/dde.c create mode 100644 lib/libddekit/src/dde.h create mode 100644 lib/libddekit/src/debug.h create mode 100644 lib/libddekit/src/initcall.c create mode 100644 lib/libddekit/src/irq.c create mode 100644 lib/libddekit/src/irq.h create mode 100644 lib/libddekit/src/lock.c create mode 100644 lib/libddekit/src/mem.c create mode 100644 lib/libddekit/src/msg_queue.c create mode 100644 lib/libddekit/src/panic.c create mode 100644 lib/libddekit/src/pci.c create mode 100644 lib/libddekit/src/pgtab.c create mode 100644 lib/libddekit/src/printf.c create mode 100644 lib/libddekit/src/resource.c create mode 100644 lib/libddekit/src/semaphore.c create mode 100644 lib/libddekit/src/thread.c create mode 100644 lib/libddekit/src/thread.h create mode 100644 lib/libddekit/src/timer.c create mode 100644 lib/libddekit/src/timer.h create mode 100644 lib/libddekit/src/usb_client.c create mode 100644 lib/libddekit/src/usb_server.c create mode 100644 lib/libddekit/src/util.h diff --git a/lib/Makefile b/lib/Makefile index 4f7e8ba59..e1485acec 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -2,7 +2,8 @@ SUBDIR= csu libc libcurses libdriver libnetdriver libedit libm libsys \ libtimers libutil libbz2 libl libhgfs libz libfetch libarchive \ - libvtreefs libaudiodriver libmthread libexec libdevman libusb + libvtreefs libaudiodriver libmthread libexec libdevman libusb \ + libddekit .if ${COMPILER_TYPE} == "ack" SUBDIR+= ack/libd ack/libe ack/libfp ack/liby diff --git a/lib/libddekit/Makefile b/lib/libddekit/Makefile new file mode 100644 index 000000000..a04e90657 --- /dev/null +++ b/lib/libddekit/Makefile @@ -0,0 +1,6 @@ + +.if ${COMPILER_TYPE} == "gnu" +SUBDIR = build +.endif + +.include diff --git a/lib/libddekit/build/Makefile b/lib/libddekit/build/Makefile new file mode 100644 index 000000000..7015b6205 --- /dev/null +++ b/lib/libddekit/build/Makefile @@ -0,0 +1,6 @@ +.if ${COMPILER_TYPE} == "gnu" +SUBDIR = ddekit ddekit_usb_client ddekit_usb_server +.endif +.include + + diff --git a/lib/libddekit/build/ddekit/Makefile b/lib/libddekit/build/ddekit/Makefile new file mode 100644 index 000000000..38e8c9a5d --- /dev/null +++ b/lib/libddekit/build/ddekit/Makefile @@ -0,0 +1,11 @@ +.if ${COMPILER_TYPE} == "gnu" +LIB= ddekit +SRC_DIR = /usr/src/lib/libddekit/src +VPATH = $(SRC_DIR) + +SRCS = pci.c printf.c mem.c pgtab.c dde.c initcall.c thread.c condvar.c lock.c semaphore.c timer.c panic.c irq.c resource.c msg_queue.c + +CFLAGS += -Wall +.endif +.include + diff --git a/lib/libddekit/build/ddekit_usb_client/Makefile b/lib/libddekit/build/ddekit_usb_client/Makefile new file mode 100644 index 000000000..b5f94bf75 --- /dev/null +++ b/lib/libddekit/build/ddekit_usb_client/Makefile @@ -0,0 +1,9 @@ +.if ${COMPILER_TYPE} == "gnu" +LIB= ddekit_usb_client +SRC_DIR = /usr/src/lib/libddekit/src +VPATH = $(SRC_DIR) +SRCS = usb_client.c +CFLAGS += -DDDEBUG=1 -Wall -I../../include +.endif +.include + diff --git a/lib/libddekit/build/ddekit_usb_server/Makefile b/lib/libddekit/build/ddekit_usb_server/Makefile new file mode 100644 index 000000000..aaf1d384e --- /dev/null +++ b/lib/libddekit/build/ddekit_usb_server/Makefile @@ -0,0 +1,10 @@ +.if ${COMPILER_TYPE} == "gnu" +LIB= ddekit_usb_server +SRC_DIR = /usr/src/lib/libddekit/src +VPATH = $(SRC_DIR) +SRCS = usb_server.c +CFLAGS += -DDDEBUG=1 -I../../include -Wall +.endif +.include + + diff --git a/lib/libddekit/src/common.h b/lib/libddekit/src/common.h new file mode 100644 index 000000000..d74ac3203 --- /dev/null +++ b/lib/libddekit/src/common.h @@ -0,0 +1,14 @@ +#define _MINIX +#define _POSIX_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include diff --git a/lib/libddekit/src/condvar.c b/lib/libddekit/src/condvar.c new file mode 100644 index 000000000..e2d43fb01 --- /dev/null +++ b/lib/libddekit/src/condvar.c @@ -0,0 +1,119 @@ +#include "common.h" + +#include +#include +#include + +#ifdef DDEBUG_LEVEL_CONDVAR +#undef DDEBUG +#define DDEBUG DDEBUG_LEVEL_CONDVAR +#endif + +#include "debug.h" +#include "util.h" +#include "thread.h" + +struct ddekit_condvar { + ddekit_thread_t * wait_queue; +}; + +/*****************************************************************************/ +/* ddekit_condvar_init */ +/*****************************************************************************/ +PUBLIC ddekit_condvar_t * ddekit_condvar_init(void) { + ddekit_condvar_t *cv; + cv = (ddekit_condvar_t *) ddekit_simple_malloc(sizeof(ddekit_condvar_t)); + DDEBUG_MSG_VERBOSE("cv: %p", cv); + return cv; +} + +/*****************************************************************************/ +/* ddekit_condvar_deinit */ +/*****************************************************************************/ +PUBLIC void ddekit_condvar_deinit(ddekit_condvar_t *cvp) { + DDEBUG_MSG_VERBOSE("cv: %p", cvp); + ddekit_simple_free(cvp); +} + +/*****************************************************************************/ +/* ddekit_condvar_wait */ +/*****************************************************************************/ +PUBLIC void ddekit_condvar_wait(ddekit_condvar_t *cv, ddekit_lock_t *mp) { + + DDEBUG_MSG_VERBOSE("wait cv: %p, thread id: %d, name: %s", + cv, ddekit_thread_myself()->id, ddekit_thread_myself()->name); + + ddekit_lock_unlock(mp); + + if(cv->wait_queue == NULL) { + cv->wait_queue = ddekit_thread_myself(); + } else { + ddekit_thread_t *pos = cv->wait_queue; + while(pos->next != NULL) { + pos = pos->next; + } + pos->next = ddekit_thread_myself(); + } + + _ddekit_thread_schedule(); + + DDEBUG_MSG_VERBOSE("wakeup cv: %p, thread id: %d, name: %s", + cv, ddekit_thread_myself()->id, ddekit_thread_myself()->name); + + ddekit_lock_lock(mp); +} +/*****************************************************************************/ +/* ddekit_condvar_wait_timed */ +/*****************************************************************************/ +PUBLIC int ddekit_condvar_wait_timed +(ddekit_condvar_t *cvp, ddekit_lock_t *mp, int timo) +{ + /* + * Only used by ddefbsd, so not implemented + */ + WARN_UNIMPL; + return 0; +} + + +/*****************************************************************************/ +/* ddekit_condvar_signal */ +/*****************************************************************************/ +PUBLIC void ddekit_condvar_signal(ddekit_condvar_t *cv) +{ + + DDEBUG_MSG_VERBOSE("cv: %p", cv); + + if(cv->wait_queue) { + ddekit_thread_t *th = cv->wait_queue; + cv->wait_queue = th->next; + th->next = NULL; + _ddekit_thread_enqueue(th); + + DDEBUG_MSG_VERBOSE("waking up cv: %p, thread id: %d, name: %s", + cv, th->id, th->name); + } + ddekit_thread_schedule(); +} + + +/*****************************************************************************/ +/* ddekit_condvar_broadcast */ +/*****************************************************************************/ +void ddekit_condvar_broadcast(ddekit_condvar_t *cv) { + + DDEBUG_MSG_VERBOSE("cv: %p", cv); + + while (cv->wait_queue) { + ddekit_thread_t *th = cv->wait_queue; + cv->wait_queue = th->next; + th->next = NULL; + _ddekit_thread_enqueue(th); + + DDEBUG_MSG_VERBOSE("waking up cv: %p, thread id: %d, name: %s", + cv, th->id, th->name); + + } + ddekit_thread_schedule(); +} + diff --git a/lib/libddekit/src/dde.c b/lib/libddekit/src/dde.c new file mode 100644 index 000000000..cfb84c738 --- /dev/null +++ b/lib/libddekit/src/dde.c @@ -0,0 +1,138 @@ +#include "common.h" +#include +#include +#include +#include +#include +#include +#include + +#include "debug.h" +#include "timer.h" /* _ddekit_timer_interrupt() */ +#include "thread.h" /* _ddekit_thread_set_myprio() */ +#include "irq.h" + + +static ddekit_sem_t *exit_sem; + +unsigned long long jiffies; + +void ddekit_pgtab_init(void); + +static ddekit_thread_t *dispatch_th = 0; + + +FORWARD _PROTOTYPE(void dispatcher_thread, (void * unused)); +FORWARD _PROTOTYPE(void ddekit_dispatcher_thread_init, (void)); + +/****************************************************************************/ +/* dispatcher_thread */ +/****************************************************************************/ +PRIVATE void dispatcher_thread(void *unused) { + + /* + * Gets all messages and dispatches them. + * + * NOTE: this thread runs only when no other ddekit is + * ready. So please take care that youre threads + * leave some time for the others! + */ + message m; + int r; + int i; + + _ddekit_thread_set_myprio(0); + + for( ; ; ) { + + /* Trigger a timer interrupt at each loop iteration */ + _ddekit_timer_update(); + + /* Wait for messages */ + if ((r = sef_receive(ANY, &m)) != 0) { + ddekit_panic("ddekit", "sef_receive failed", r); + } + + + _ddekit_timer_interrupt(); + + _ddekit_thread_wakeup_sleeping(); + + if (is_notify(m.m_type)) { + switch (_ENDPOINT_P(m.m_source)) { + case HARDWARE: + for (i =0 ; i < 32 ; i++) + { + if(m.NOTIFY_ARG & (1 << i)) + { + _ddekit_interrupt_trigger(i); + } + } + break; + case CLOCK: + _ddekit_timer_pending = 0; + break; + default: + ddekit_thread_schedule(); + } + + } else { + + /* + * I don't know how to handle this msg, + * but maybe we have a msg queue which can + * handle this msg. + */ + + ddekit_minix_queue_msg(&m); + } + } +} + +/****************************************************************************/ +/* ddekit_dispatcher_thread_init */ +/****************************************************************************/ +PRIVATE void ddekit_dispatcher_thread_init() +{ + + dispatch_th = ddekit_thread_create(dispatcher_thread, NULL, "dispatch"); + + ddekit_thread_schedule(); +} + +/****************************************************************************/ +/* ddekit_init */ +/****************************************************************************/ +PUBLIC void ddekit_init(void) +{ + sef_startup(); + + ddekit_pgtab_init(); + + ddekit_init_threads(); + + ddekit_init_irqs(); + + ddekit_init_timers(); + + ddekit_dispatcher_thread_init(); + + exit_sem = ddekit_sem_init(0); +} + +/****************************************************************************/ +/* dispatcher_shutdown */ +/****************************************************************************/ +void ddekit_shutdown() +{ + ddekit_sem_up(exit_sem); +} + +/****************************************************************************/ +/* ddekit_minix_wait_exit */ +/****************************************************************************/ +void ddekit_minix_wait_exit(void) +{ + ddekit_sem_down(exit_sem); +} + diff --git a/lib/libddekit/src/dde.h b/lib/libddekit/src/dde.h new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/lib/libddekit/src/dde.h @@ -0,0 +1 @@ + diff --git a/lib/libddekit/src/debug.h b/lib/libddekit/src/debug.h new file mode 100644 index 000000000..f2e590796 --- /dev/null +++ b/lib/libddekit/src/debug.h @@ -0,0 +1,7 @@ +#ifndef DDEKIT_DEBUG_MACROS_H +#define DDEKIT_DEBUG_MACROS_H + +#include +#include + +#endif /* DDEKIT_DEBUG_MACROS_H */ diff --git a/lib/libddekit/src/initcall.c b/lib/libddekit/src/initcall.c new file mode 100644 index 000000000..4963b0b47 --- /dev/null +++ b/lib/libddekit/src/initcall.c @@ -0,0 +1,57 @@ +#include "common.h" + +#include + + +#ifdef DDEKIT_DEBUG_INITCALL +#undef DDEBUG +#define DDEBUG DDEKIT_DEBUG_INITCALL +#endif + +#include "debug.h" + +static struct __ddekit_initcall_s head = {0,0,0}; + +/****************************************************************************/ +/* __ddekit_add_initcall */ +/****************************************************************************/ +PUBLIC void __attribute__((used)) +__ddekit_add_initcall(struct __ddekit_initcall_s * ic) { + + /* This function is required for the DDEKIT_INITCALL makro */ + + struct __ddekit_initcall_s *i = 0; + + DDEBUG_MSG_VERBOSE("adding initcall (%p) to %p with prio %d head at %p", + ic, ic->func, ic->prio, &head); + + for (i = &head; i; i=i->next) + { + if (!i->next) { + i->next = ic; + return; + } + if (i->next->prio > ic->prio) { + ic->next = i->next; + i->next = ic; + return; + } + } +} + +/****************************************************************************/ +/* ddekit_do_initcalls */ +/****************************************************************************/ +PUBLIC void ddekit_do_initcalls() +{ + struct __ddekit_initcall_s *i = 0; + + DDEBUG_MSG_VERBOSE("exectuing initcalls (head at %p, head->next = %p)", + &head, head.next); + + for (i = head.next; i; i=i->next) { + DDEBUG_MSG_VERBOSE("executing initcall: %p with prio %d", + i->func, i->prio); + i->func(); + } +} diff --git a/lib/libddekit/src/irq.c b/lib/libddekit/src/irq.c new file mode 100644 index 000000000..c87583176 --- /dev/null +++ b/lib/libddekit/src/irq.c @@ -0,0 +1,257 @@ +#include "common.h" +#include +#include +#include +#include + +#ifdef DDEBUG_LEVEL_IRQ +#undef DDEBUG +#define DDEBUG DDEBUG_LEVEL_IRQ +#endif + +#include "debug.h" + +struct ddekit_irq_s { + int irq; + int irq_hook; + int shared; + void(*thread_init)(void *); + void(*handler)(void *); + void *priv; + int enabled; + ddekit_thread_t *th; + ddekit_sem_t *sem; + struct ddekit_irq_s *next; +}; + +static struct ddekit_irq_s *irqs = 0; +static ddekit_lock_t lock; + +/****************************************************************************** + * Local helpers * + *****************************************************************************/ + + +FORWARD _PROTOTYPE( void ddekit_irq_lock, (void)); +FORWARD _PROTOTYPE( void ddekit_irq_unlock, (void)); +FORWARD _PROTOTYPE( struct ddekit_irq_s* find_by_irq, (int irq)); +FORWARD _PROTOTYPE( void ddekit_irq_remove, (struct ddekit_irq_s *irq_s)); +FORWARD _PROTOTYPE( void ddekit_irq_thread, (void *data)); + +/****************************************************************************** + * ddekit_irq_lock * + *****************************************************************************/ +PRIVATE void ddekit_irq_lock(void) +{ + ddekit_lock_lock(&lock); +} + +/****************************************************************************** + * ddekit_irq_unlock * + *****************************************************************************/ +PRIVATE void ddekit_irq_unlock(void) +{ + ddekit_lock_unlock(&lock); +} + +/****************************************************************************** + * find_by_irq * + *****************************************************************************/ +PRIVATE struct ddekit_irq_s * find_by_irq(int irq) +{ + struct ddekit_irq_s * irq_s; + ddekit_irq_lock(); + if (!irqs) { + return 0; + } + + irq_s = irqs; + + while(irq_s) { + if(irq_s->irq==irq) + break; + irq_s = irq_s->next; + } + + ddekit_irq_unlock(); + return irq_s; +} + +/****************************************************************************** + * ddekit_irq_remove * + *****************************************************************************/ +PRIVATE void ddekit_irq_remove(struct ddekit_irq_s *irq_s) +{ + struct ddekit_irq_s *i; + + ddekit_irq_lock(); + + if(!irqs) { + ddekit_irq_unlock(); + return; + } + + if(irqs==irq_s) { + irqs=irq_s->next; + ddekit_irq_unlock(); + return; + } + + i = irqs; + + while(i) { + if (i->next == irq_s) { + i->next = irq_s->next; + ddekit_irq_unlock(); + return; + } + i = i->next; + } + + ddekit_irq_unlock(); +} + +/****************************************************************************** + * ddekit_irq_thread * + *****************************************************************************/ +PRIVATE void ddekit_irq_thread(void *data) +{ + /* For each IRQ line an own thread is started */ + + struct ddekit_irq_s *irq_s = (struct ddekit_irq_s *) data; + + /* call IRQ thread init function */ + irq_s->thread_init(irq_s->priv); + + while(1) { + + /* Wait for IRQs */ + DDEBUG_MSG_VERBOSE("wating for IRQ %d to occur", irq_s->irq); + ddekit_sem_down(irq_s->sem); + DDEBUG_MSG_VERBOSE("executing handler for IRQ %d", irq_s->irq); + irq_s->handler(irq_s->priv); + + } +} + + +/****************************************************************************** + * DDEKIT public API (include/dde/ddekit) * + *****************************************************************************/ + +/****************************************************************************** + * ddekit_interrupt_attach * + *****************************************************************************/ +ddekit_thread_t *ddekit_interrupt_attach(int irq, + int shared, + void(*thread_init)(void *), + void(*handler)(void *), + void *priv) +{ + struct ddekit_irq_s *irq_s; + char name[32]; + irq_s = (struct ddekit_irq_s *) + ddekit_simple_malloc(sizeof(struct ddekit_irq_s)); + + irq_s->sem = ddekit_sem_init(0); + irq_s->irq = irq; + irq_s->irq_hook = irq; + irq_s->shared = shared; + irq_s->thread_init = thread_init; + irq_s->handler = handler; + irq_s->priv = priv; + irq_s->next = 0; + irq_s->enabled = 1; + + /* create interrupt thread */ + snprintf(name, 32, "ddekit_irq_%d",irq); + irq_s->th = ddekit_thread_create(ddekit_irq_thread, irq_s, name); + + /* attach to IRQ */ + sys_irqsetpolicy(irq, + 0, /* not automatically re-enable interupts */ + &irq_s->irq_hook); + + /* add to IRQ list */ + ddekit_irq_lock(); + irq_s->next = irqs; + irqs=irq_s; + ddekit_irq_unlock(); + + DDEBUG_MSG_INFO("Attached to irq %d (hook: %d)", irq, irq_s->irq_hook); + + return irq_s->th; +} + +/****************************************************************************** + * ddekit_interrupt_detach * + *****************************************************************************/ +void ddekit_interrupt_detach(int irq) +{ + struct ddekit_irq_s *irq_s; + + irq_s = find_by_irq(irq); + + sys_irqrmpolicy(&irq_s->irq_hook); + + ddekit_thread_terminate(irq_s->th); + ddekit_irq_remove(irq_s); + ddekit_simple_free(irq_s); + DDEBUG_MSG_VERBOSE(" IRQ %d", irq); +} + +/****************************************************************************** + * ddekit_interrupt_disable * + *****************************************************************************/ +void ddekit_interrupt_disable(int irq) +{ + struct ddekit_irq_s *irq_s; + irq_s = find_by_irq(irq); + irq_s->enabled=0; + //sys_irqdisable(&irq_s->irq_hook); + DDEBUG_MSG_VERBOSE(" IRQ %d", irq); +} + +/****************************************************************************** + * ddekit_interrupt_enable * + *****************************************************************************/ +void ddekit_interrupt_enable(int irq) +{ + struct ddekit_irq_s *irq_s; + irq_s = find_by_irq(irq); + irq_s->enabled=1; + //sys_irqenable(&irq_s->irq_hook); + DDEBUG_MSG_VERBOSE(" IRQ %d", irq); +} + +/****************************************************************************** + * ddekit_init_irqs * + *****************************************************************************/ +void ddekit_init_irqs() +{ + ddekit_lock_init(&lock); +} + +/****************************************************************************** + * DDEKIT internals (src/irq.h) * + *****************************************************************************/ + +/****************************************************************************** + * _ddekit_interrupt_trigger * + *****************************************************************************/ +PUBLIC void _ddekit_interrupt_trigger(int irq) +{ + struct ddekit_irq_s *irq_s; + + irq_s = find_by_irq(irq); + + if (irq_s) { + DDEBUG_MSG_VERBOSE("Triggering IRQ %d", irq); + ddekit_sem_up(irq_s->sem); + sys_irqenable(&irq_s->irq_hook); + } else { + DDEBUG_MSG_WARN("no handler for IRQ %d", irq); + } +} + + diff --git a/lib/libddekit/src/irq.h b/lib/libddekit/src/irq.h new file mode 100644 index 000000000..8c9ec1ebe --- /dev/null +++ b/lib/libddekit/src/irq.h @@ -0,0 +1,5 @@ +#ifndef DDEKIT_IRQ_MINIX_H +#define DDEKIT_IRQ_MINIX_H 1 +_PROTOTYPE( void ddekit_init_irqs, (void) ); +_PROTOTYPE( void _ddekit_interrupt_trigger, (int irq_hook) ); +#endif diff --git a/lib/libddekit/src/lock.c b/lib/libddekit/src/lock.c new file mode 100644 index 000000000..fecb64989 --- /dev/null +++ b/lib/libddekit/src/lock.c @@ -0,0 +1,118 @@ +#include "common.h" + +#include +#include +#include + +#ifdef DDEBUG_LEVEL_LOCK +#undef DDEBUG +#define DDEBUG DDEBUG_LEVEL_LOCK +#endif + +#include "debug.h" +#include "thread.h" + +struct ddekit_lock { + ddekit_thread_t *owner; + ddekit_thread_t *wait_queue; +}; + + +/****************************************************************************** + * ddekit_lock_init_locked * + *****************************************************************************/ +PUBLIC void ddekit_lock_init_locked(ddekit_lock_t *mtx) +{ + (*mtx) = (struct ddekit_lock *) + ddekit_simple_malloc(sizeof(struct ddekit_lock)); + + (*mtx)->wait_queue = NULL; + (*mtx)->owner = ddekit_thread_myself(); +} + +/****************************************************************************** + * ddekit_lock_init_unlocked * + *****************************************************************************/ +PUBLIC void ddekit_lock_init_unlocked(ddekit_lock_t *mtx) +{ + (*mtx) = (struct ddekit_lock *) + ddekit_simple_malloc(sizeof(struct ddekit_lock)); + (*mtx)->owner = NULL; + (*mtx)->wait_queue = NULL; +} + +/****************************************************************************** + * ddekit_lock_deinit * + *****************************************************************************/ +PUBLIC void ddekit_lock_deinit (ddekit_lock_t *mtx) +{ + ddekit_simple_free(*mtx); +} + +/****************************************************************************** + * ddekit_lock_lock * + *****************************************************************************/ +PUBLIC void ddekit_lock_lock (ddekit_lock_t *mtx) +{ + if ((*mtx)->owner == NULL) { + (*mtx)->owner = ddekit_thread_myself(); + } else { + + if ((*mtx)->wait_queue == NULL) { + (*mtx)->wait_queue = ddekit_thread_myself(); + } else { + ddekit_thread_t *pos = (*mtx)->wait_queue; + while(pos->next != NULL) { + pos = pos->next; + } + pos->next = ddekit_thread_myself(); + } + + _ddekit_thread_schedule(); + + if ((*mtx)->owner != NULL) { + _ddekit_print_backtrace((*mtx)->owner); + _ddekit_print_backtrace(ddekit_thread_myself()); + ddekit_panic("owner!=NULL: %s (I am %s)\n", + (*mtx)->owner->name, ddekit_thread_myself()->name); + } + + (*mtx)->owner = ddekit_thread_myself(); + } +} + +/****************************************************************************** + * ddekit_lock_try_lock * + *****************************************************************************/ +PUBLIC int ddekit_lock_try_lock(ddekit_lock_t *mtx) +{ + if ((*mtx)->owner == NULL) { + (*mtx)->owner = ddekit_thread_myself(); + return 0; + } else { + return -1; + } +} + +/****************************************************************************** + * ddekit_lock_unlock * + *****************************************************************************/ +PUBLIC void ddekit_lock_unlock (ddekit_lock_t *mtx) { + ddekit_assert((*mtx)->owner != NULL); + (*mtx)->owner = NULL; + if((*mtx)->wait_queue) { + ddekit_thread_t *waiter = (*mtx)->wait_queue; + (*mtx)->wait_queue = waiter->next; + waiter->next= NULL; + _ddekit_thread_enqueue(waiter); + ddekit_yield(); + } +} + +/****************************************************************************** + * ddekit_lock_owner * + *****************************************************************************/ +PUBLIC int ddekit_lock_owner(ddekit_lock_t *mtx) { + return ddekit_thread_get_id((*mtx)->owner); +} + diff --git a/lib/libddekit/src/mem.c b/lib/libddekit/src/mem.c new file mode 100644 index 000000000..423b56ae9 --- /dev/null +++ b/lib/libddekit/src/mem.c @@ -0,0 +1,460 @@ +#include "common.h" + +#include +#include +#include +#include +#include +#include + +#ifdef DDEKIT_DEBUG_MEM +#undef DDEBUG +#define DDEBUG DDEKIT_DEBUG_MEM +#endif +#include "debug.h" +#include "util.h" + +#define SLAB_SIZE (4096*4) + +struct ddekit_slab; + +struct ddekit_slab_slab { + struct ddekit_slab * cache; + unsigned long free; + void *objects; + void *mem; + struct ddekit_slab_slab *next; + struct ddekit_slab_slab *prev; +}; + +struct ddekit_slab { + ddekit_lock_t lock; + void * data; /* user pointer */ + int contiguous; /* is it coniguous mem*/ + unsigned size; /* the size of he objects */ + unsigned number; /* the number of objects stored per slab */ + struct ddekit_slab_slab full; + struct ddekit_slab_slab partial; + struct ddekit_slab_slab empty; +}; + +FORWARD _PROTOTYPE( void ddekit_slab_lock, (struct ddekit_slab * sc) ); +FORWARD _PROTOTYPE( void ddekit_slab_unlock, (struct ddekit_slab * sc) ); +FORWARD _PROTOTYPE( struct ddekit_slab_slab * ddekit_slab_find_slab, + (struct ddekit_slab * sc, void * obj)); +FORWARD _PROTOTYPE(void ddekit_slab_slab_insert, + (struct ddekit_slab_slab *list, + struct ddekit_slab_slab *s)); +FORWARD _PROTOTYPE( void ddekit_slab_slab_remove, (struct ddekit_slab_slab *s)); +FORWARD _PROTOTYPE( void ddekit_slab_grow, (struct ddekit_slab * sc)); +FORWARD _PROTOTYPE( void *ddekit_slab_getobj, (struct ddekit_slab_slab *s)); +FORWARD _PROTOTYPE( void ddekit_slab_free_slab, + (struct ddekit_slab_slab * sl, int cont)); + +/****************************************************************************** + * ddekit_simple_malloc * + *****************************************************************************/ +PUBLIC void *ddekit_simple_malloc(unsigned size) +{ + /* Simple memory allocation... malloc and free should be ok... */ + void * r = malloc(size); + if (!r) { + ddekit_panic("out of mem?"); + } + DDEBUG_MSG_VERBOSE("%p", r); + return r; +} + +/****************************************************************************** + * ddekit_simple_free * + *****************************************************************************/ +PUBLIC void ddekit_simple_free(void *p) +{ + DDEBUG_MSG_VERBOSE("%p", p); + free(p); +} + +/****************************************************************************** + * ddekit_large_malloc * + *****************************************************************************/ +PUBLIC void *ddekit_large_malloc(int size) +{ + ddekit_addr_t phys; + /* allocate a piece of coniguous memory */ + void * r = alloc_contig(size, AC_ALIGN4K, &phys); + if (!r) { + ddekit_panic("out of mem?"); + } + ddekit_pgtab_set_region_with_size(r, phys, size, PTE_TYPE_LARGE); + DDEBUG_MSG_VERBOSE("%p, phys: %p, size: %p.",r, phys, size); + DDEBUG_MSG_VERBOSE("%p", r); + return r; +} + +/****************************************************************************** + * ddekit_large_free * + *****************************************************************************/ +PUBLIC void ddekit_large_free(void *p) +{ + unsigned len; + DDEBUG_MSG_VERBOSE("get size of region %x", p); + len= ddekit_pgtab_get_size(p); + DDEBUG_MSG_VERBOSE("freeing %x, len %d...", p , len); + ddekit_pgtab_clear_region(p, 0); /* type is not used here... */ + DDEBUG_MSG_VERBOSE("cleared region", p , len); + free_contig(p, len); + DDEBUG_MSG_VERBOSE("freed mem", p , len); + DDEBUG_MSG_VERBOSE("%p", p); +} + +/****************************************************************************** + * ddekit_contig_malloc * + *****************************************************************************/ +PUBLIC void *ddekit_contig_malloc(unsigned long size, unsigned long low, + unsigned long high, unsigned long aligment, + unsigned long boundary) +{ + WARN_UNIMPL; + return 0; +} + +/****************************************************************************** + * ddekit_slab_lock * + *****************************************************************************/ +PRIVATE DDEKIT_INLINE void ddekit_slab_lock(struct ddekit_slab * sc) { + ddekit_lock_lock(&sc->lock); +} + +/****************************************************************************** + * ddekit_slab_unlock * + *****************************************************************************/ +PRIVATE DDEKIT_INLINE void ddekit_slab_unlock(struct ddekit_slab * sc) { + ddekit_lock_unlock(&sc->lock); +} + +/****************************************************************************** + * ddekit_slab_find_slab * + *****************************************************************************/ +PRIVATE struct ddekit_slab_slab * +ddekit_slab_find_slab(struct ddekit_slab * sc, void * obj) +{ + + struct ddekit_slab_slab *s; + + for( s = sc->full.next; s!=&sc->full; s = s->next ) + { + if (s->mem <= obj && obj < s->mem+(SLAB_SIZE)) + { + return s; + } + } + + for( s = sc->partial.next; s!=&sc->partial; s = s->next ) + { + if (s->mem <= obj && obj < s->mem+(SLAB_SIZE)) + { + return s; + } + } + + return 0; +} + +/****************************************************************************** + * ddekit_slab_slab_insert * + *****************************************************************************/ +static void ddekit_slab_slab_insert(struct ddekit_slab_slab *list, + struct ddekit_slab_slab *s) +{ + s->prev = list; + s->next = list->next; + list->next->prev = s; + list->next = s; +} + +/****************************************************************************** + * ddekit_slab_slab_remove * + *****************************************************************************/ +PRIVATE void ddekit_slab_slab_remove(struct ddekit_slab_slab *s) +{ + s->next->prev = s->prev; + s->prev->next = s->next; + s->next = s->prev = 0; +} + + +/****************************************************************************** + * ddekit_slab_grow * + *****************************************************************************/ +PRIVATE void ddekit_slab_grow(struct ddekit_slab *sc) +{ + /* + * NOTE: + * As it doesn't seem to make problems ddekit_slabs are disregarding + * alignment. However this should be revisited, maybe this leads to + * performance degregation somewhere. + * Further the ddekit_slab doesn't have to be real slab, as the entries are + * initialized in the personalized DDEs. (slab is simple the wrong name.) + */ + int i; + char *p; + void **p1; + struct ddekit_slab_slab *s; + + /* allocate slab control structure */ + + s = (struct ddekit_slab_slab *) + ddekit_simple_malloc(sizeof(struct ddekit_slab_slab)); + + s->cache = sc; + + if(sc->contiguous) + s->mem = ddekit_large_malloc(SLAB_SIZE); + else + s->mem = ddekit_simple_malloc(SLAB_SIZE); + + /* setup the object list */ + + s->free = sc->number; + + /* put obj into list */ + p1 = s->mem; + *p1 = s->mem; + s->objects = p1; + + DDEBUG_MSG_VERBOSE("obj size: %d, memory at: %p , first obj: %p, %p ", + sc->size, s->mem, s->objects); + + for (i = 0; i < s->free; i++) + { + p = *p1; + p1 = (void **) (p + sc->size); + + if ( i != s->free-1 ) + { + *p1 = p1+1; + DDEBUG_MSG_VERBOSE("%p, %p -> %p", p, p1, *p1); + } + else + { + *p1 = 0; + DDEBUG_MSG_VERBOSE("%p, %p -> %p", p, p1, *p1); + } + } + + /* add new slab to free list */ + ddekit_slab_slab_insert(&sc->empty, s); +} + + +/****************************************************************************** + * ddekit_slab_getobj * + *****************************************************************************/ +PRIVATE void *ddekit_slab_getobj(struct ddekit_slab_slab *s) +{ + struct ddekit_slab *sc; + void *ret = 0; + + sc = s->cache; + ret = s->objects; + + /* get pointer to next object */ + + s->objects = *(void **)((char *) ret + sc->size); + s->free--; + + DDEBUG_MSG_VERBOSE("old: %p new: %p", ret, s->objects); + + /* if no more objects move to full */ + + if (!s->free) + { + ddekit_slab_slab_remove(s); + ddekit_slab_slab_insert(&sc->full,s); + } + + if (s->free == sc->number-1) + { + ddekit_slab_slab_remove(s); + ddekit_slab_slab_insert(&sc->partial,s); + } + + return ret; +} + +/****************************************************************************** + * ddekit_slab_alloc * + *****************************************************************************/ +PUBLIC void *ddekit_slab_alloc(struct ddekit_slab * sc) +{ + struct ddekit_slab_slab *s=0; + + ddekit_slab_lock(sc); + + DDEBUG_MSG_VERBOSE("from slab %p", sc); + + /* first try from partial */ + if (sc->partial.next != &sc->partial) { + DDEBUG_MSG_VERBOSE("from slab %p partial (next=%p)", sc,sc->partial.next); + s = sc->partial.next; + } + + /* must grow? */ + if (!s && (sc->empty.next == &sc->empty )){ + DDEBUG_MSG_VERBOSE("slab %p has to grow", sc); + ddekit_slab_grow(sc); + } + + /* take from free? */ + if (!s) { + DDEBUG_MSG_VERBOSE("from slab %p empty", sc); + s = sc->empty.next; + } + + ddekit_slab_unlock(sc); + + return ddekit_slab_getobj(s); +} + +/****************************************************************************** + * ddekit_slab_free * + *****************************************************************************/ +PUBLIC void ddekit_slab_free(struct ddekit_slab *sc, void* obj) +{ + void **p; + + struct ddekit_slab_slab *s = 0; + + ddekit_slab_lock(sc); + /* first find slab the obj came from */ + + s = ddekit_slab_find_slab(sc, obj); + + p = (void **)((char *) obj + sc->size); + + *p= s->objects; + s->objects=obj; + + DDEBUG_MSG_VERBOSE("old: %p, new: %p",*p,s->objects ); + + s->free++; + + if (s->free == sc->number) { + ddekit_slab_slab_remove(s); + ddekit_slab_slab_insert(&sc->empty, s); + } + + if (s->free == 1) { + ddekit_slab_slab_remove(s); + ddekit_slab_slab_insert(&sc->partial, s); + } + + ddekit_slab_unlock(sc); +} + +/****************************************************************************** + * ddekit_slab_set_data * + *****************************************************************************/ +PUBLIC void ddekit_slab_set_data(struct ddekit_slab * sc, void *data) +{ + ddekit_slab_lock(sc); + sc->data = data; + ddekit_slab_unlock(sc); +} + +/****************************************************************************** + * ddekit_slab_get_data * + *****************************************************************************/ +PUBLIC void *ddekit_slab_get_data (struct ddekit_slab *sc) +{ + void *ret; + ddekit_slab_lock(sc); + ret=sc->data; + ddekit_slab_unlock(sc); + return ret; +} + + +/****************************************************************************** + * ddekit_slab_init * + *****************************************************************************/ +PUBLIC struct ddekit_slab * ddekit_slab_init(unsigned size, int contiguous) +{ + + struct ddekit_slab * sc = 0; + + sc = (struct ddekit_slab *) + ddekit_simple_malloc(sizeof(struct ddekit_slab)); + + sc->data = 0; + sc->contiguous = contiguous; + sc->size = size; + sc->number = SLAB_SIZE/(size+sizeof(void*)); + + if (sc->number == 0) { + ddekit_panic("objects too big!"); + } + + sc->empty.next = sc->empty.prev = &sc->empty; + sc->partial.next = sc->partial.prev = &sc->partial; + sc->full.next = sc->full.prev = &sc->full; + + ddekit_lock_init(&sc->lock); + + DDEBUG_MSG_VERBOSE("initialzed slab cache %p: size %x, number %d ", + sc, sc->size, sc->number); + + DDEBUG_MSG_VERBOSE("partial %p next %p", &sc->partial, sc->partial.next); + return sc ; + +} + + +/****************************************************************************** + * ddekit_slab_free_slab * + *****************************************************************************/ +PRIVATE void ddekit_slab_free_slab(struct ddekit_slab_slab * sl, int cont) +{ + + struct ddekit_slab_slab *s,*t; + + if (!sl) { + ddekit_panic("no slab to free!"); + } + + for ( s = sl->next; s != sl; ) + { + DDEBUG_MSG_VERBOSE("cont: %d, %p, s->mem", cont, s->mem); + if(cont) + { + ddekit_large_free(s->mem); + } + else + { + ddekit_simple_free(s->mem); + } + t = s; + s = s->next; + ddekit_simple_free(t); + } + +} + +/****************************************************************************** + * ddekit_slab_destroy * + *****************************************************************************/ +PUBLIC void ddekit_slab_destroy(struct ddekit_slab *sc) +{ + DDEBUG_MSG_VERBOSE("%p full", sc); + ddekit_slab_free_slab(&sc->full,sc->contiguous); + + DDEBUG_MSG_VERBOSE("%p empty", sc); + ddekit_slab_free_slab(&sc->empty,sc->contiguous); + + DDEBUG_MSG_VERBOSE("%p partial", sc); + ddekit_slab_free_slab(&sc->partial,sc->contiguous); + + ddekit_lock_deinit(&sc->lock); + + ddekit_simple_free(sc); +} diff --git a/lib/libddekit/src/msg_queue.c b/lib/libddekit/src/msg_queue.c new file mode 100644 index 000000000..b2eaf20eb --- /dev/null +++ b/lib/libddekit/src/msg_queue.c @@ -0,0 +1,155 @@ +#include "common.h" + +#include +#include +#include +#include + +#define MESSAGE_QUEUE_SIZE 16 + +#ifdef DDEBUG_LEVEL_MSG_Q +#undef DDEBUG +#define DDEBUG DDEBUG_LEVEL_MSG_Q +#endif + +#include "debug.h" + +struct ddekit_minix_msg_q { + + unsigned from, to; + + message messages[MESSAGE_QUEUE_SIZE]; + ddekit_sem_t *msg_w_sem, *msg_r_sem; + int msg_r_pos, msg_w_pos; + + struct ddekit_minix_msg_q *next; +}; + +PRIVATE struct ddekit_minix_msg_q * _list = NULL; +FORWARD _PROTOTYPE(void _ddekit_minix_queue_msg, + (struct ddekit_minix_msg_q *mq, message *m)); + +/***************************************************************************** + * ddekit_minix_create_msg_q * + ****************************************************************************/ +PUBLIC struct ddekit_minix_msg_q * +ddekit_minix_create_msg_q(unsigned from, unsigned to) +{ + struct ddekit_minix_msg_q *mq = (struct ddekit_minix_msg_q *) + ddekit_simple_malloc(sizeof(struct ddekit_minix_msg_q)); + + mq->from = from; + mq->to = to; + mq->msg_w_pos = 0; + mq->msg_r_pos = 0; + + mq->msg_r_sem = ddekit_sem_init(0); + mq->msg_w_sem = ddekit_sem_init(MESSAGE_QUEUE_SIZE); + + /* TODO: check for overlapping message ranges */ + mq->next = _list; + _list = mq; + + DDEBUG_MSG_VERBOSE("created msg_q from %x to %x\n", from , to); + + return mq; +} + +/***************************************************************************** + * ddekit_minix_deregister_msg_q * + ****************************************************************************/ +PUBLIC void ddekit_minix_deregister_msg_q(struct ddekit_minix_msg_q *mq) +{ + struct ddekit_minix_msg_q *prev =_list, *it; + + for (it = _list->next; it != NULL ; it = it->next) { + if (it == mq) { + prev->next = it->next; + break; + } + prev=it; + } + + ddekit_sem_deinit(mq->msg_r_sem); + ddekit_sem_deinit(mq->msg_w_sem); + + ddekit_simple_free(mq); + + DDEBUG_MSG_VERBOSE("destroyed msg_q from \n"); +} + +/***************************************************************************** + * _ddekit_minix_queue_msg * + ****************************************************************************/ +PRIVATE void +_ddekit_minix_queue_msg(struct ddekit_minix_msg_q *mq, message *m) +{ + int full; + full = ddekit_sem_down_try(mq->msg_w_sem); + + if (full) { + /* Our message queue is full... inform the sender. */ + int result; + DDEBUG_MSG_WARN("Receive queue is full. Ommiting ingoing msg.\n"); + + m->m_type = TASK_REPLY; + m->REP_STATUS = EAGAIN; + result = asynsend(m->m_source, m); + + if (result != 0) { + ddekit_panic("unable to send reply to %d: %d\n", + m->m_source, result); + } + + } else { + /* queue the message */ + memcpy(&mq->messages[mq->msg_w_pos], m, sizeof(message)); + + if (++mq->msg_w_pos == MESSAGE_QUEUE_SIZE) { + mq->msg_w_pos = 0; + } + DDEBUG_MSG_VERBOSE("ddekit_minix_queue_msg: queueing msg %x\n", + m->m_type); + ddekit_sem_up(mq->msg_r_sem); + } +} + +/***************************************************************************** + * ddekit_minix_queue_msg * + ****************************************************************************/ +void ddekit_minix_queue_msg(message *m) +{ + struct ddekit_minix_msg_q *it, *mq = NULL; + + for (it = _list; it !=NULL ; it = it->next) { + if (m->m_type >= it->from && m->m_type <= it->to) { + mq = it; + break; + } + } + if (mq == NULL) { + DDEBUG_MSG_VERBOSE("no q for msgtype %x\n", m->m_type); + return; + } + _ddekit_minix_queue_msg(mq,m); +} + +/***************************************************************************** + * ddekit_minix_rcv * + ****************************************************************************/ +PUBLIC void ddekit_minix_rcv(struct ddekit_minix_msg_q *mq, message *m) +{ + DDEBUG_MSG_VERBOSE("waiting for message"); + + ddekit_sem_down(mq->msg_r_sem); + + memcpy(m, &mq->messages[mq->msg_r_pos], sizeof(message)); + + if (++mq->msg_r_pos == MESSAGE_QUEUE_SIZE) { + mq->msg_r_pos = 0; + } + + DDEBUG_MSG_VERBOSE("unqueing message"); + + ddekit_sem_up(mq->msg_w_sem); +} diff --git a/lib/libddekit/src/panic.c b/lib/libddekit/src/panic.c new file mode 100644 index 000000000..bf20415c2 --- /dev/null +++ b/lib/libddekit/src/panic.c @@ -0,0 +1,34 @@ +#include "common.h" +#include +#include + +/****************************************************************************/ +/* ddekit_panic */ +/****************************************************************************/ +PUBLIC void ddekit_panic(char *fmt, ...) +{ + + int r; + va_list va; + + printf("%c[31;1mPANIC: \033[0m\n",0x1b); + va_start(va,fmt); + r = vprintf(fmt, va); + va_end(va); + panic("","",0); + + while(1) + ; +} + +/****************************************************************************/ +/* ddekit_debug */ +/****************************************************************************/ +PUBLIC void ddekit_debug(char *fmt, ...) +{ + int r; + va_list va; + va_start(va,fmt); + r = vprintf(fmt, va); + va_end(va); +} diff --git a/lib/libddekit/src/pci.c b/lib/libddekit/src/pci.c new file mode 100644 index 000000000..aaa01d0d0 --- /dev/null +++ b/lib/libddekit/src/pci.c @@ -0,0 +1,447 @@ +/** + * pci.c + * @author: Dirk Vogt + * @date: 2010-02-18 + */ + +#include "common.h" + +#include +#include +#include + + +#ifdef DDEBUG_LEVEL_PCI +#undef DDEBUG +#define DDEBUG DDEBUG_LEVEL_PCI +#endif + +#include "util.h" +#include "debug.h" + +#define PCI_MAX_DEVS 32 + +#define PCI_TAKE_ALL (-1) + +struct ddekit_pci_dev { + int devind; /* thats how we identify the defice at the pci server */ + ddekit_uint16_t vid; /* as we get them for */ + /* free during iteration store them */ + ddekit_uint16_t did; + int bus; + int slot; /* slot should equal index in dev array */ + int func; /* don't support multiple functionalities yet -> 0 */ +}; + +struct ddekit_pci_dev pci_devs[PCI_MAX_DEVS]; + +FORWARD _PROTOTYPE( struct ddekit_pci_dev * ddekit_get_dev_helper, + (int bus, int slot, int func)); + +/****************************************************************************/ +/* ddekit_pci_init_only_one */ +/****************************************************************************/ +PUBLIC void ddekit_pci_init_only_one(int skip) +{ + /* + * If skip is not PCI_TAKE_ALL this function will skip skip PCI DEVICES + * and than only take on PCI device. + */ + + int res, count, more, take_all = 0; + + if (skip == -1) { + take_all = 1; + } + + DDEBUG_MSG_INFO("Initializing PCI subsystem..."); + + pci_init1("symbol clash"); + + /* + * Iterate the PCI-bus + */ + + more = 1; + + for (count = 0 ; count < PCI_MAX_DEVS ; count++) { + + struct ddekit_pci_dev *d = &pci_devs[count]; + + if (more) { + if ( count==0 ) { + res = pci_first_dev(&d->devind, &d->vid, &d->did); + } else { + d->devind = pci_devs[count-1].devind; + res = pci_next_dev(&d->devind, &d->vid, &d->did); + } + + if (res && d->devind!=0 && (take_all || skip == 0)) { + + DDEBUG_MSG_VERBOSE("Found pci device: " + "(ind: %x, vid: %x, did: %x) " + "mapped to slot %x", + d->devind, d->vid, d->did, count); + d->slot = count; + d->bus = 0; + d->func = 0; + res = pci_reserve_ok(d->devind); + if (res != 0) { + ddekit_panic("ddekit_pci_init_only_one: " + "pci_reserve_ok failed (%d)\n",res); + } + + } else { + /* no more PCI devices */ + DDEBUG_MSG_VERBOSE("Found %d PCI devices.", count); + d->devind = -1; + more = 0; + } /*if (res) */ + } else { + d->devind = -1; + } + if (!take_all) { + skip--; + } + } +} + +/****************************************************************************/ +/* ddekit_pci_get_device_id */ +/****************************************************************************/ +PUBLIC void ddekit_pci_init(void) +{ + ddekit_pci_init_only_one(DDEKIT_PCI_ANY_ID); +} + +/****************************************************************************/ +/* ddekit_pci_get_device_id */ +/****************************************************************************/ +int ddekit_pci_get_device(int nr, int *bus, int *slot, int *func) +{ + if(nr >= 0 && nr < PCI_MAX_DEVS) { + + *bus = 0; + *slot = nr; + *func =0; + + return 0; + } + + return -1; +} + +/****************************************************************************/ +/* ddekit_pci_get_device_id */ +/****************************************************************************/ +PRIVATE struct ddekit_pci_dev * +ddekit_get_dev_helper(int bus, int slot, int func) +{ + /* + * Used internally to look up devices. + * Should make it easier to support multiple buses somewhen + */ + struct ddekit_pci_dev * ret = 0; + if (slot >= 0 && slot < PCI_MAX_DEVS) { + ret = &pci_devs[slot]; + } + if (ret->devind == -1) { + ret = 0; + } + return ret; +} + +/****************************************************************************/ +/* ddekit_pci_read */ +/****************************************************************************/ +PUBLIC int ddekit_pci_read +(int bus, int slot, int func, int pos, int len, ddekit_uint32_t *val) +{ + switch(len) { + case 1: + return ddekit_pci_readb(bus, slot, func, pos, + (ddekit_uint8_t*) val); + case 2: + return ddekit_pci_readw(bus, slot, func, pos, + (ddekit_uint16_t*) val); + case 4: + return ddekit_pci_readl(bus, slot, func, pos, val); + default: return -1; + } +} + +/****************************************************************************/ +/* ddekit_pci_write */ +/****************************************************************************/ +PUBLIC int ddekit_pci_write +(int bus, int slot, int func, int pos, int len, ddekit_uint32_t val) +{ + switch(len) { + case 1: + return ddekit_pci_writeb(bus, slot, func, pos, + (ddekit_uint8_t) val); + case 2: + return ddekit_pci_writew(bus, slot, func, pos, + (ddekit_uint16_t) val); + case 4: + return ddekit_pci_writel(bus, slot, func, pos, val); + default: return -1; + } +} + +/****************************************************************************/ +/* ddekit_pci_readb */ +/****************************************************************************/ +PUBLIC int ddekit_pci_readb (int bus, int slot, int func, int pos, ddekit_uint8_t *val) { + struct ddekit_pci_dev * dev = ddekit_get_dev_helper(bus, slot, func); + if (func!=0) { + *val=0; + return 0; + } + if (dev) { + *val = pci_attr_r8 (dev->devind, pos); + DDEBUG_MSG_VERBOSE("bus: %d, slot: %d, func: %d, pos: %x %x", + bus, slot, func, pos, *val); + return 0; + } + return -1; +} + +/****************************************************************************/ +/* ddekit_pci_readw */ +/****************************************************************************/ +PUBLIC int ddekit_pci_readw +(int bus, int slot, int func, int pos, ddekit_uint16_t *val) { + struct ddekit_pci_dev * dev = ddekit_get_dev_helper(bus, slot, func); + if (func!=0) { + *val=0; + return 0; + } + if (dev) { + *val = pci_attr_r16 (dev->devind, pos); + DDEBUG_MSG_VERBOSE("bus: %d, slot: %d, func: %d, pos: %x %x", + bus, slot, func, pos, *val); + return 0; + } + return -1; +} + +/****************************************************************************/ +/* ddekit_pci_readl */ +/****************************************************************************/ +PUBLIC int ddekit_pci_readl +(int bus, int slot, int func, int pos, ddekit_uint32_t *val) { + struct ddekit_pci_dev * dev = ddekit_get_dev_helper(bus, slot, func); + if (func!=0) { + *val=0; + return 0; + } + if (dev) { + *val = pci_attr_r32 (dev->devind, pos); + DDEBUG_MSG_VERBOSE("bus: %d, slot: %d, func: %d, pos: %x %x", + bus, slot, func, pos, *val); + return 0; + } + return -1; +} + +/****************************************************************************/ +/* ddekit_pci_writeb */ +/****************************************************************************/ +PUBLIC int ddekit_pci_writeb +(int bus, int slot, int func, int pos, ddekit_uint8_t val) { + struct ddekit_pci_dev * dev = ddekit_get_dev_helper(bus, slot, func); + if (dev) { + pci_attr_w8 (dev->devind, pos, val); + DDEBUG_MSG_VERBOSE("bus: %d, slot: %d, func: %d, pos: %x %x", + bus, slot, func, pos, val); + return 0; + } + return -1; +} + +/****************************************************************************/ +/* ddekit_pci_writel */ +/****************************************************************************/ +PUBLIC int ddekit_pci_writew +(int bus, int slot, int func, int pos, ddekit_uint16_t val) { + struct ddekit_pci_dev * dev = ddekit_get_dev_helper(bus, slot, func); + if (dev) { + pci_attr_w16 (dev->devind, pos, val); + DDEBUG_MSG_VERBOSE("bus: %d, slot: %d, func: %d, pos: %x %x", + bus,slot,func,pos, val); + return 0; + } + return -1; +} + +/****************************************************************************/ +/* ddekit_pci_writel */ +/****************************************************************************/ +PUBLIC int ddekit_pci_writel +(int bus, int slot, int func, int pos, ddekit_uint32_t val) { + struct ddekit_pci_dev * dev = ddekit_get_dev_helper(bus, slot, func); + if (dev) { + pci_attr_w32 (dev->devind, pos, val); + DDEBUG_MSG_VERBOSE("bus: %d, slot: %d, func: %d, pos: %x %x",bus,slot,func,pos, val); + return 0; + } + return -1; +} + +/****************************************************************************/ +/* ddekit_pci_find_device */ +/****************************************************************************/ +PUBLIC struct ddekit_pci_dev *ddekit_pci_find_device +(int *bus, int *slot, int *func, struct ddekit_pci_dev *start) +{ + int i,search=0; + + if(!start) + search = 1; + + for(i=0; i < PCI_MAX_DEVS ; i++) + { + /* start searching? */ + if (search) + search = (&pci_devs[i]==start); + else + { + struct ddekit_pci_dev * dev = &pci_devs[i]; + if ((*slot==dev->slot || *slot == DDEKIT_PCI_ANY_ID) + && (*func==dev->func || *func == DDEKIT_PCI_ANY_ID)) + { + return dev; + } + } + } + return 0; +} + +/* + * XXX: Those are neither used be DDEFBSD or DDELinux implement them + * when you need them + */ + +/****************************************************************************/ +/* ddekit_pci_enable_device */ +/****************************************************************************/ +PUBLIC int ddekit_pci_enable_device(struct ddekit_pci_dev *dev) +{ + WARN_UNIMPL; + return 0; +} + +/****************************************************************************/ +/* ddekit_pci_disable_device */ +/****************************************************************************/ +PUBLIC int ddekit_pci_disable_device(struct ddekit_pci_dev *dev) +{ + WARN_UNIMPL; + return 0; +} + +/****************************************************************************/ +/* ddekit_pci_set_master */ +/****************************************************************************/ +PUBLIC void ddekit_pci_set_master(struct ddekit_pci_dev *dev) +{ + WARN_UNIMPL; +} + +/****************************************************************************/ +/* ddekit_pci_get_vendor */ +/****************************************************************************/ +PUBLIC unsigned short ddekit_pci_get_vendor(struct ddekit_pci_dev *dev) +{ + WARN_UNIMPL; + return 0; +} + +/****************************************************************************/ +/* ddekit_pci_get_device_id */ +/****************************************************************************/ +PUBLIC unsigned short ddekit_pci_get_device_id(struct ddekit_pci_dev *dev) +{ + WARN_UNIMPL; + return 0; +} + +/****************************************************************************/ +/* ddekit_pci_get_sub_vendor */ +/****************************************************************************/ +PUBLIC unsigned short ddekit_pci_get_sub_vendor(struct ddekit_pci_dev *dev) +{ + WARN_UNIMPL; + return 0; +} + +/****************************************************************************/ +/* ddekit_pci_get_sub_device */ +/****************************************************************************/ +PUBLIC unsigned short ddekit_pci_get_sub_device(struct ddekit_pci_dev *dev) +{ + WARN_UNIMPL; + return 0; +} + +/****************************************************************************/ +/* ddekit_pci_get_dev_class */ +/****************************************************************************/ +PUBLIC unsigned ddekit_pci_get_dev_class(struct ddekit_pci_dev *dev) +{ + WARN_UNIMPL; + return 0; +} + +/****************************************************************************/ +/* ddekit_pci_get_irq */ +/****************************************************************************/ +PUBLIC unsigned long +ddekit_pci_get_irq(struct ddekit_pci_dev *dev) +{ + WARN_UNIMPL; + return 0; +} + +/****************************************************************************/ +/* ddekit_pci_get_name */ +/****************************************************************************/ +PUBLIC char *ddekit_pci_get_name(struct ddekit_pci_dev *dev) +{ + WARN_UNIMPL; + return 0; +} + +/****************************************************************************/ +/* ddekit_pci_get_slot_name */ +/****************************************************************************/ +PUBLIC char *ddekit_pci_get_slot_name(struct ddekit_pci_dev *dev) +{ + WARN_UNIMPL; + return 0; +} + +/****************************************************************************/ +/* ddekit_pci_get_resource */ +/****************************************************************************/ +PUBLIC ddekit_pci_res_t * +ddekit_pci_get_resource(struct ddekit_pci_dev *dev, unsigned int idx) +{ + WARN_UNIMPL; + return 0; +} + +/****************************************************************************/ +/* ddekit_pci_irq_enable */ +/****************************************************************************/ +PUBLIC int ddekit_pci_irq_enable +(int bus, int slot, int func, int pin, int *irq) +{ + /* call not needed */ +#if 0 + WARN_UNIMPL; +#endif + return 0; +} + diff --git a/lib/libddekit/src/pgtab.c b/lib/libddekit/src/pgtab.c new file mode 100644 index 000000000..f7c70fd05 --- /dev/null +++ b/lib/libddekit/src/pgtab.c @@ -0,0 +1,313 @@ +/* + * @author: Dirk Vogt + * @date 2010-02-10 + * + * This file implements a local pagetable, to prevent IPC on physical + * address lookups. For now it's implement in a signle linked list. + * + * As soon as the DDE will use a premeptive thread mechanism access to + * the page table has to be sznchronized. + */ +#include "common.h" + +#include +#include +#include + +#ifdef DDEBUG_LEVEL_PGTAB +#undef DDEBUG +#define DDEBUG DDEBUG_LEVEL_PGTAB +#endif + +#include "util.h" +#include "debug.h" + + +FORWARD _PROTOTYPE( void lock_pgtab, (void)); +FORWARD _PROTOTYPE( void unlock_pgtab, (void)); +FORWARD _PROTOTYPE( struct dde_pgtab_region * allocate_region, (void)); +FORWARD _PROTOTYPE( void free_region, (struct dde_pgtab_region *r)); +FORWARD _PROTOTYPE( void add_region, (struct dde_pgtab_region *r)); +FORWARD _PROTOTYPE( void rm_region, (struct dde_pgtab_region *r)); +FORWARD _PROTOTYPE( struct dde_pgtab_region * find_region_virt, (ddekit_addr_t va)); +FORWARD _PROTOTYPE( struct dde_pgtab_region * find_region_phys, (ddekit_addr_t pa)); + +struct dde_pgtab_region { + ddekit_addr_t vm_start; + ddekit_addr_t phy_start; + unsigned size; + unsigned type; /* do we really have to keep track of the type here? */ + struct dde_pgtab_region *next; + struct dde_pgtab_region *prev; +}; + +PRIVATE struct dde_pgtab_region head = {0,0,0,0,&head,&head}; +PRIVATE ddekit_lock_t lock; + +/* + * INTERNAL HELPERS + */ + +/****************************************************************************/ +/* lock_pgtab */ +/****************************************************************************/ +PRIVATE void lock_pgtab() +{ + ddekit_lock_lock(&lock); +} + + +/****************************************************************************/ +/* unlock_pgtab */ +/****************************************************************************/ +PRIVATE void unlock_pgtab() +{ + ddekit_lock_unlock(&lock); +} + +/****************************************************************************/ +/* dde_pgtab_region */ +/****************************************************************************/ +PRIVATE struct dde_pgtab_region * allocate_region() +{ + struct dde_pgtab_region * res; + + res = (struct dde_pgtab_region *) + ddekit_simple_malloc(sizeof(struct dde_pgtab_region)); + if (!res) + { + DDEBUG_MSG_ERR("Could not allocate region"); + } + return res; +} + +/****************************************************************************/ +/* free_region */ +/****************************************************************************/ +PRIVATE void free_region(struct dde_pgtab_region *r) +{ + ddekit_simple_free(r); +} + +/****************************************************************************/ +/* add_region */ +/****************************************************************************/ +PRIVATE void add_region (struct dde_pgtab_region *r) +{ + r->next = head.next; + head.next = r; + r->prev = &head; + + if (r->next) { + + r->next->prev = r; + + } +} + +/****************************************************************************/ +/* rm_region */ +/****************************************************************************/ +PRIVATE void rm_region(struct dde_pgtab_region *r) +{ + if (r->next) { + r->next->prev = r->prev; + } + if (r->prev) { + r->prev->next = r->next; + } + r->next = 0; + r->prev = 0; +} + + +/****************************************************************************/ +/* find_region_virt */ +/****************************************************************************/ +PRIVATE struct dde_pgtab_region * find_region_virt(ddekit_addr_t va) +{ + struct dde_pgtab_region * r; + + for( r = head.next; r != &head ; r = r->next ) { + + if ( (r->vm_start <= va) && (va < (r->vm_start + r->size) ) ) { + break; + } + } + + if (r == &head) { + DDEBUG_MSG_VERBOSE("No virt->phys mapping found for %x", va); + r = 0; + } + + return r; +} + +/****************************************************************************/ +/* find_region_phys */ +/****************************************************************************/ +PRIVATE struct dde_pgtab_region * find_region_phys(ddekit_addr_t pa) +{ + struct dde_pgtab_region * r; + + for( r = head.next; r != &head ; r = r->next ) { + if ( (r->phy_start <= pa) && (pa < (r->phy_start + r->size) ) ) + break; + } + + if (r == &head) { + r=0; + DDEBUG_MSG_VERBOSE("No phys->virt mapping found for %x", pa); + } + + return r; +} + +/****************************************************************************/ +/* ddekit_pgtab_do_fo_each_region */ +/****************************************************************************/ +PUBLIC void ddekit_pgtab_do_fo_each_region(void (*func) (unsigned, unsigned)) { + struct dde_pgtab_region * r; + + for( r = head.next; r != &head ; r = r->next ) { + ddekit_printf("%p",r->vm_start); + func(r->vm_start, r->size); + } +} + +/* + * Interface implementation + */ + +/****************************************************************************/ +/* ddekit_pgtab_set_region */ +/****************************************************************************/ +PUBLIC void ddekit_pgtab_set_region(void *virt, ddekit_addr_t phys, int pages, int type) +{ + ddekit_pgtab_set_region_with_size(virt, phys, (4096)*pages, type); +} + +/****************************************************************************/ +/* ddekit_pgtab_set_region_with_size */ +/****************************************************************************/ +PUBLIC void ddekit_pgtab_set_region_with_size(void *virt, ddekit_addr_t phys, int size, int type) +{ + struct dde_pgtab_region * r; + + lock_pgtab(); + + r = allocate_region(); + + r->vm_start = (ddekit_addr_t) virt; + r->phy_start = phys; + r->size = size; + r->type = type; + + add_region(r); + + unlock_pgtab(); +} + + +/****************************************************************************/ +/* ddekit_pgtab_clear_region */ +/****************************************************************************/ +PUBLIC void ddekit_pgtab_clear_region(void *virt, int type) { + + struct dde_pgtab_region *r; + + lock_pgtab(); + + r = find_region_virt((ddekit_addr_t)virt); + + if (r) + { + rm_region(r); + free_region(r); + } + + unlock_pgtab(); + +} + + +/****************************************************************************/ +/* ddekit_pgtab_get_physaddr */ +/****************************************************************************/ +PUBLIC ddekit_addr_t ddekit_pgtab_get_physaddr(const void *virt) +{ + struct dde_pgtab_region *r; + ddekit_addr_t ret = 0; + lock_pgtab(); + r = find_region_virt((ddekit_addr_t)virt); + unlock_pgtab(); + if (r != NULL) { + + ret = ((ddekit_addr_t) virt - r->vm_start) + r->phy_start; + DDEBUG_MSG_VERBOSE("pa: %p -> %p\n", virt, ret); + } + + return ret; +} + +/****************************************************************************/ +/* ddekit_pgtab_get_virtaddr */ +/****************************************************************************/ +PUBLIC ddekit_addr_t ddekit_pgtab_get_virtaddr(const ddekit_addr_t physical) +{ + struct dde_pgtab_region *r; + lock_pgtab(); + r = find_region_phys((ddekit_addr_t)physical); + unlock_pgtab(); + if (r != NULL) + { + return ((ddekit_addr_t) physical - r->phy_start) + r->vm_start; + } + + return 0; +} + +/****************************************************************************/ +/* ddekit_pgtab_get_size */ +/****************************************************************************/ +PUBLIC int ddekit_pgtab_get_type(const void *virt) +{ + /* + * needed for dde fbsd + */ + struct dde_pgtab_region *r; + + lock_pgtab(); + r = find_region_virt((ddekit_addr_t)virt); + unlock_pgtab(); + return r->type; +} + + +/****************************************************************************/ +/* ddekit_pgtab_get_size */ +/****************************************************************************/ +PUBLIC int ddekit_pgtab_get_size(const void *virt) +{ + /* + * needed for fbsd + */ + struct dde_pgtab_region *r; + + lock_pgtab(); + r = find_region_virt((ddekit_addr_t)virt); + unlock_pgtab(); + if(r) + return r->size; + else + return 0; +} + +/****************************************************************************/ +/* ddekit_pgtab_init */ +/****************************************************************************/ +PUBLIC void ddekit_pgtab_init() { + /* called by ddekit_init() */ + ddekit_lock_init(&lock); +} + diff --git a/lib/libddekit/src/printf.c b/lib/libddekit/src/printf.c new file mode 100644 index 000000000..deef59e22 --- /dev/null +++ b/lib/libddekit/src/printf.c @@ -0,0 +1,33 @@ +#include "common.h" +#include + +/****************************************************************************/ +/* ddekit_print */ +/****************************************************************************/ +PUBLIC int ddekit_print(const char* c) +{ + return ddekit_printf(c); +} + +/****************************************************************************/ +/* ddekit_printf */ +/****************************************************************************/ +PUBLIC int ddekit_printf(const char* fmt, ...) +{ + int r; + va_list va; + + va_start(va,fmt); + r = vprintf(fmt, va); + va_end(va); + + return r; +} + +/****************************************************************************/ +/* ddekit_vprintf */ +/****************************************************************************/ +PUBLIC int ddekit_vprintf(const char *fmt, va_list va) +{ + return vprintf(fmt, va); +} diff --git a/lib/libddekit/src/resource.c b/lib/libddekit/src/resource.c new file mode 100644 index 000000000..ae7e1232e --- /dev/null +++ b/lib/libddekit/src/resource.c @@ -0,0 +1,138 @@ +#include "common.h" +#include +#include +#include + +#include + +#ifdef DDEBUG_LEVEL_RESOURCE +#undef DDEBUG +#define DDEBUG DDEBUG_LEVEL_RESOURCE +#endif + +#include "debug.h" +#include "util.h" + +/****************************************************************************/ +/* ddekit_release_dma */ +/****************************************************************************/ +PUBLIC int ddekit_request_dma(int nr) { + WARN_UNIMPL; + /* do we stil use isa dma ? imho no.*/ + return -1; +} + +/****************************************************************************/ +/* ddekit_request_dma */ +/****************************************************************************/ +PUBLIC int ddekit_release_dma(int nr) { + WARN_UNIMPL; + /* do we stil use isa dma ? imho no.*/ + return -1; +} + +/* + * In minix we don't need to explicitly request IO-ports, ... + */ +/****************************************************************************/ +/* ddekit_release/request_io */ +/****************************************************************************/ +PUBLIC int ddekit_request_io (ddekit_addr_t start, ddekit_addr_t count) { + return 0; +} +PUBLIC int ddekit_release_io (ddekit_addr_t start, ddekit_addr_t count) { + return 0; +} + +/****************************************************************************/ +/* ddekit_request_mem */ +/****************************************************************************/ +PUBLIC int ddekit_request_mem +(ddekit_addr_t start, ddekit_addr_t size, ddekit_addr_t *vaddr) { + + *vaddr = (ddekit_addr_t) vm_map_phys(SELF, (void *)start, size); + + DDEBUG_MSG_VERBOSE("start: %x, size: %d, virt: %x", start, size, *vaddr); + + if( *vaddr == (ddekit_addr_t) NULL) { + ddekit_panic("unable to map IO memory from %p of size %d", + start, size); + } + return (vaddr==NULL); +} + +/****************************************************************************/ +/* ddekit_release_mem */ +/****************************************************************************/ +PUBLIC int ddekit_release_mem(ddekit_addr_t start, ddekit_addr_t size) +{ + return vm_unmap_phys(SELF,(void *) start, size ); +} + +/****************************************************************************/ +/* ddekit_inb */ +/****************************************************************************/ +PUBLIC unsigned char ddekit_inb(ddekit_addr_t port) { + unsigned long ret; + if (sys_inb(port, &ret)) { + ddekit_panic("sys_inb failed."); + } + DDEBUG_MSG_VERBOSE("read port %x: %x", port, ret); + return (char) ret; +} + +/****************************************************************************/ +/* ddekit_inw */ +/****************************************************************************/ +PUBLIC unsigned short ddekit_inw(ddekit_addr_t port) { + unsigned long ret; + if (sys_inw(port, &ret)) { + ddekit_panic("sys_inw failed."); + } + DDEBUG_MSG_VERBOSE("read port %x: %x", port, ret); + return (short) ret; +} + +/****************************************************************************/ +/* ddekit_inl */ +/****************************************************************************/ +PUBLIC unsigned long ddekit_inl(ddekit_addr_t port){ + unsigned long ret; + if (sys_inl(port, &ret)) { + ddekit_panic("sys_outl failed."); + } + DDEBUG_MSG_VERBOSE("read port %x: %x", port, ret); + return ret; +} + +/****************************************************************************/ +/* ddekit_outb */ +/****************************************************************************/ +PUBLIC void ddekit_outb(ddekit_addr_t port, unsigned char val) { + if (sys_outb(port,val)) { + ddekit_panic("sys_outb failed."); + } + DDEBUG_MSG_VERBOSE("write port %x: %x", port, val); +} + +/****************************************************************************/ +/* ddekit_outw */ +/****************************************************************************/ +PUBLIC void ddekit_outw(ddekit_addr_t port, unsigned short val) { + if (sys_outw(port,val)) { + ddekit_panic("sys_outw failed."); + } + DDEBUG_MSG_VERBOSE("write port %x: %x", port, val); +} + +/****************************************************************************/ +/* ddekit_outl */ +/****************************************************************************/ +PUBLIC void ddekit_outl(ddekit_addr_t port, unsigned long val) { + if (sys_outl(port,val)) { + ddekit_panic("sys_outl failed."); + } + DDEBUG_MSG_VERBOSE("write port %x: %x", port, val); +} + + diff --git a/lib/libddekit/src/semaphore.c b/lib/libddekit/src/semaphore.c new file mode 100644 index 000000000..61d7866fa --- /dev/null +++ b/lib/libddekit/src/semaphore.c @@ -0,0 +1,111 @@ +#include "common.h" +#include +#include +#include +#include +#include + +#ifdef DDEBUG_LEVEL_SEMAPHORE +#undef DDEBUG +#define DDEBUG DDEBUG_LEVEL_SEMAPHORE +#endif + +#include "debug.h" +#include "thread.h" + +struct ddekit_sem { + unsigned count; + ddekit_thread_t *wait_queue; +}; + +#define SEM_DEBUG(p) \ + do { \ + DDEBUG_MSG_VERBOSE("%s, %p, %d\n",__func__, sem, sem->count); \ + } while(0) + +/***************************************************************************** + * ddekit_sem_init * + *************************+**************************************************/ +PUBLIC ddekit_sem_t *ddekit_sem_init(int value) +{ + ddekit_sem_t *sem; + + sem = (ddekit_sem_t *) ddekit_simple_malloc(sizeof(ddekit_sem_t)); + + sem->count = value; + sem->wait_queue = NULL; + + SEM_DEBUG(p); + return sem; +} + +/***************************************************************************** + * ddekit_sem_deinit * + ****************************************************************************/ +PUBLIC void ddekit_sem_deinit(ddekit_sem_t *sem) +{ + SEM_DEBUG(p); + ddekit_simple_free(sem); +} + +/***************************************************************************** + * ddekit_sem_down * + ****************************************************************************/ +PUBLIC void ddekit_sem_down(ddekit_sem_t *sem) +{ + SEM_DEBUG(p); + if(sem->count == 0) { + if(sem->wait_queue == NULL) { + sem->wait_queue = ddekit_thread_myself(); + } else { + ddekit_thread_t *pos = sem->wait_queue; + while(pos->next != NULL) { + pos = pos->next; + } + pos->next = ddekit_thread_myself(); + } + _ddekit_thread_schedule(); + } else { + sem->count--; + } +} + +/***************************************************************************** + * ddekit_sem_down_try * + ****************************************************************************/ +PUBLIC int ddekit_sem_down_try(ddekit_sem_t *sem) +{ + if(sem->count == 0) { + return -1; + } + sem->count--; + return 0; +} + +/***************************************************************************** + * ddekit_sem_up * + ****************************************************************************/ +PUBLIC void ddekit_sem_up(ddekit_sem_t *sem) +{ + SEM_DEBUG(p); + if (sem->wait_queue == NULL) { + sem->count++; + return; + } else { + ddekit_thread_t *waiter = sem->wait_queue; + sem->wait_queue = waiter->next; + waiter->next = NULL; + _ddekit_thread_enqueue(waiter); + ddekit_thread_schedule(); + } +} + +/**************************************************************************** + * ddekit_sem_down_timed * + ***************************************************************************/ +PUBLIC int ddekit_sem_down_timed(ddekit_sem_t *sem, int timo ) +{ + ddekit_panic("not implemented!"); + return 0; +} + diff --git a/lib/libddekit/src/thread.c b/lib/libddekit/src/thread.c new file mode 100644 index 000000000..dcefa2757 --- /dev/null +++ b/lib/libddekit/src/thread.c @@ -0,0 +1,499 @@ +#include "common.h" +#include +#include +#include +#include +#include + +#ifdef DDEBUG_LEVEL_THREAD +#undef DDEBUG +#define DDEBUG DDEBUG_LEVEL_THREAD +#endif + +#include "debug.h" +#include "util.h" +#include "thread.h" +#include "timer.h" + + +/* Incremented to generate unique thread IDs */ +PRIVATE unsigned id; + +PRIVATE ddekit_thread_t *ready_queue[DDEKIT_THREAD_PRIOS]; + +PRIVATE ddekit_thread_t *sleep_queue; + +/* Handle to the running thread, set in _dde_kit_thread_schedule() */ +PRIVATE ddekit_thread_t *current = NULL; + +FORWARD _PROTOTYPE( void _ddekit_thread_start, (ddekit_thread_t *th)); +FORWARD _PROTOTYPE( void _ddekit_thread_sleep, (unsigned long until)); + +/***************************************************************************** + * _ddekit_thread_start * + ****************************************************************************/ +PRIVATE void _ddekit_thread_start(ddekit_thread_t *th) +{ + /* entry point of newly created threads */ + th->fun(th->arg); + ddekit_thread_exit(); +} + +/***************************************************************************** + * _ddekit_thread_sleep * + ****************************************************************************/ +PRIVATE void _ddekit_thread_sleep(unsigned long until) +{ + current->next = sleep_queue; + sleep_queue = current; + current->sleep_until = until; + _ddekit_thread_schedule(); + +} + +/***************************************************************************** + * DDEKIT public thread API (ddekit/thread.h) * + ****************************************************************************/ + +/***************************************************************************** + * ddekit_yield * + ****************************************************************************/ +PUBLIC void ddekit_yield() +{ + ddekit_thread_schedule(); +} + +/***************************************************************************** + * ddekit_thread_schedule * + ****************************************************************************/ +PUBLIC void ddekit_thread_schedule() +{ + _ddekit_thread_enqueue(current); + _ddekit_thread_schedule(); +} + +/***************************************************************************** + * ddekit_thread_create * + ****************************************************************************/ +PUBLIC ddekit_thread_t * +ddekit_thread_create(void (*fun)(void *), void *arg, const char *name) +{ + ddekit_thread_t *th = + (ddekit_thread_t *) ddekit_simple_malloc(sizeof(ddekit_thread_t)); + + strncpy(th->name, name, DDEKIT_THREAD_NAMELEN); + th->name[DDEKIT_THREAD_NAMELEN-1] = 0; + + th->stack = ddekit_large_malloc(DDEKIT_THREAD_STACKSIZE); + + th->arg = arg; + th->fun = fun; + + th->id = id++; + th->prio = DDEKIT_THREAD_STDPRIO; + th->next = NULL; + th->sleep_sem = ddekit_sem_init(0); + + + /* setup stack */ + + void **ptr = (void **)(th->stack + DDEKIT_THREAD_STACKSIZE); + *(--ptr) = th; + --ptr; + --ptr; + + /* TAKEN FROM P_THREAD (written by david?)*/ +#ifdef __ACK__ + th->jb[0].__pc = _ddekit_thread_start; + th->jb[0].__sp = ptr; +#else /* !__ACK__ */ +#include +#if defined(JB_PC) && defined(JB_SP) + /* um, yikes. */ + + *((void (**)(void))(&((char *)th->jb)[JB_PC])) = + (void *)_ddekit_thread_start; + + *((void **)(&((char *)th->jb)[JB_SP])) = ptr; +#else +#error "Unsupported Minix architecture" +#endif +#endif /* !__ACK__ */ + + DDEBUG_MSG_VERBOSE("created thread %s, stack at: %p\n", name, + th->stack + DDEKIT_THREAD_STACKSIZE); + _ddekit_thread_enqueue(th); + + return th; +} + +/***************************************************************************** + * ddekit_thread_get_data * + ****************************************************************************/ +PUBLIC void *ddekit_thread_get_data(ddekit_thread_t *thread) +{ + return thread->data; +} + +/***************************************************************************** + * ddekit_thread_get_my_data * + ****************************************************************************/ +PUBLIC void *ddekit_thread_get_my_data(void) +{ + return current->data; +} + +/***************************************************************************** + * ddekit_thread_myself * + ****************************************************************************/ +PUBLIC +ddekit_thread_t *ddekit_thread_myself(void) +{ + return current; +} + +/***************************************************************************** + * ddekit_thread_setup_myself * + ****************************************************************************/ +PUBLIC +ddekit_thread_t *ddekit_thread_setup_myself(const char *name) { + ddekit_thread_t *th = + (ddekit_thread_t *) ddekit_simple_malloc(sizeof(ddekit_thread_t)); + + strncpy(th->name, name, DDEKIT_THREAD_NAMELEN); + th->name[DDEKIT_THREAD_NAMELEN-1] = 0; + th->stack = NULL; + th->next = NULL; + th->id = id++; + th->prio = DDEKIT_THREAD_STDPRIO; + th->sleep_sem = ddekit_sem_init(0); +#if DDEBUG >= 4 + _ddekit_print_backtrace(th); +#endif + return th; +} + +/***************************************************************************** + * ddekit_thread_set_data * + ****************************************************************************/ +PUBLIC void ddekit_thread_set_data(ddekit_thread_t *thread, void *data) +{ + thread->data=data; +} + +/***************************************************************************** + * ddekit_thread_set_my_data * + ****************************************************************************/ +PUBLIC void ddekit_thread_set_my_data(void *data) +{ + current->data = data; +} + +/***************************************************************************** + * ddekit_thread_usleep * + ****************************************************************************/ +void ddekit_thread_usleep(unsigned long usecs) +{ + /* + * Cannot use usleep here, because it's implemented in vfs. + * Assuming the anyway no finder granularity than system's HZ value + * can be reached. So we use dde_kit_thread_msleep for now. + */ + + /* If no timeout is 0 return immediately */ + if (usecs == 0) + return; + + unsigned long to = usecs/1000; + + /* round up to to possible granularity */ + + if (to == 0) + to = 1; + + ddekit_thread_msleep(to); +} + +/***************************************************************************** + * ddekit_thread_nsleep * + ****************************************************************************/ +PUBLIC void ddekit_thread_nsleep(unsigned long nsecs) +{ + /* + * Cannot use usleep here, because it's implemented in vfs. + * Assuming the anyway no finder granularity than system's HZ value + * can be reached. So we use dde_kit_thread_msleep. + */ + + /* If no timeout is 0 return immediately */ + if (nsecs == 0) + return; + + unsigned long to = nsecs/1000; + + /* round up to to possible granularity */ + + if (to == 0) + to = 1; + + ddekit_thread_usleep(to); +} + +/***************************************************************************** + * ddekit_thread_msleep * + ****************************************************************************/ +PUBLIC void ddekit_thread_msleep(unsigned long msecs) +{ + unsigned long to; + + to = (msecs*HZ/1000); + + if (to == 0) { + to = 1; + } + + ddekit_thread_t *th = ddekit_thread_myself(); + + if (th == NULL) { + ddekit_panic("th==NULL!"); + } + + if (th->sleep_sem == NULL) { + ddekit_panic("th->sleepsem==NULL! %p %s ", th, th->name); + } + + /* generate a timer interrupt at to */ + ddekit_add_timer(NULL, NULL, to+jiffies); + _ddekit_thread_sleep(to+jiffies); +} + +/***************************************************************************** + * ddekit_thread_sleep * + ****************************************************************************/ +PUBLIC void ddekit_thread_sleep(ddekit_lock_t *lock) +{ + WARN_UNIMPL; +} + +/***************************************************************************** + * ddekit_thread_exit * + ****************************************************************************/ +PUBLIC void ddekit_thread_exit() +{ + ddekit_sem_down(current->sleep_sem); + ddekit_panic("thread running after exit!\n"); + /* not reached */ + while(1); +} + +/***************************************************************************** + * ddekit_thread_terminate * + ****************************************************************************/ +PUBLIC void ddekit_thread_terminate(ddekit_thread_t *thread) +{ + /* todo */ +} + +/***************************************************************************** + * ddekit_thread_get_name * + ****************************************************************************/ +PUBLIC const char *ddekit_thread_get_name(ddekit_thread_t *thread) +{ + return thread->name; +} + +/***************************************************************************** + * ddekit_thread_get_id * + ****************************************************************************/ +PUBLIC int ddekit_thread_get_id(ddekit_thread_t *thread) +{ + return thread->id; +} + +/***************************************************************************** + * ddekit_init_threads * + ****************************************************************************/ +PUBLIC void ddekit_init_threads(void) +{ + int i; + + for (i =0 ; i < DDEKIT_THREAD_PRIOS ; i++) { + ready_queue[i] = NULL; + } + + current = ddekit_thread_setup_myself("main"); + + DDEBUG_MSG_INFO("ddekit thread subsystem initialized"); +} + +/***************************************************************************** + * DDEKIT internals (src/thread.h) * + *****************************************************************************/ + +/***************************************************************************** + * _ddekit_thread_schedule * + ****************************************************************************/ +PUBLIC void _ddekit_thread_schedule() +{ + + DDEBUG_MSG_VERBOSE("called schedule id: %d name %s, prio: %d", + current->id, current->name, current->prio); + + /* get our tcb */ + ddekit_thread_t * th = current; + +#if DDEBUG >= 4 + _ddekit_print_backtrace(th); +#endif + + /* save our context */ + if (_setjmp(th->jb) == 0) { + + int i; + + /* find a runnable thread */ + + current = NULL; + + for (i = DDEKIT_THREAD_PRIOS-1; i >= 0; i--) { + if (ready_queue[i]!=NULL) { + current = ready_queue[i]; + ready_queue[i] = current->next; + current->next=NULL; + break; + } + } + + if (current == NULL) { + ddekit_panic("No runable threads?!"); + } + + DDEBUG_MSG_VERBOSE("switching to id: %d name %s, prio: %d", + current->id, current->name, current->prio); +#if DDEBUG >= 4 + _ddekit_print_backtrace(current); +#endif + _longjmp(current->jb, 1); + } + +} + +/***************************************************************************** + * _ddekit_thread_enqueue * + ****************************************************************************/ +PUBLIC void _ddekit_thread_enqueue(ddekit_thread_t *th) +{ + + DDEBUG_MSG_VERBOSE("enqueueing thread: id: %d name %s, prio: %d", + th->id, th->name, th->prio); + +#if DDEBUG >= 4 + _ddekit_print_backtrace(th); +#endif + + ddekit_assert(th->next==NULL); + + if (ready_queue[th->prio] != NULL) { + ddekit_thread_t *pos = ready_queue[th->prio]; + while (pos->next != NULL) { + pos = pos->next; + } + pos->next = th; + } else { + ready_queue[th->prio] = th; + } +} + +/***************************************************************************** + * _ddekit_thread_set_myprio * + ****************************************************************************/ +PUBLIC void _ddekit_thread_set_myprio(int prio) +{ + DDEBUG_MSG_VERBOSE("changing thread prio, id: %d name %s, old prio: %d, " + "new prio: %d", current->id, current->name, current->prio); + + current->prio = prio; + ddekit_thread_schedule(); +} + +/***************************************************************************** + * _ddekit_thread_wakeup_sleeping * + ****************************************************************************/ +PUBLIC void _ddekit_thread_wakeup_sleeping() +{ + ddekit_thread_t *th = sleep_queue; + + sleep_queue = NULL; + + while (th != NULL) { + ddekit_thread_t *th1 = th->next; + if (th->sleep_until > jiffies) { + th->next = sleep_queue; + sleep_queue = th; + } else { + th->next = NULL; + _ddekit_thread_enqueue(th); + } + th = th1; + } + + ddekit_thread_schedule(); +} + +#define FUNC_STACKTRACE(statement) \ +{ \ + reg_t bp, pc, hbp; \ + extern reg_t get_bp(void); \ + \ + bp= get_bp(); \ + while(bp) \ + { \ + pc= ((reg_t *)bp)[1]; \ + hbp= ((reg_t *)bp)[0]; \ + statement; \ + if (hbp != 0 && hbp <= bp) \ + { \ + pc = -1; \ + statement; \ + break; \ + } \ + bp= hbp; \ + } \ +} + +/***************************************************************************** + * _ddekit_print_backtrace * + ****************************************************************************/ +PUBLIC void _ddekit_print_backtrace(ddekit_thread_t *th) +{ + unsigned long bp, pc, hbp; + + ddekit_printf("%s: ", th->name); + +#ifdef __ACK__ + bp =th->jb[0].__bp; +#else /* !__ACK__ */ +#include +#if defined(JB_PC) && defined(JB_SP) + /* um, yikes. */ + bp = (unsigned long) *((void **)(&((char *)th->jb)[JB_BP])); +#else +#error "Unsupported Minix architecture" +#endif +#endif /* !__ACK__ */ + + while (bp) { + pc = ((unsigned long *)bp)[1]; + hbp = ((unsigned long *)bp)[0]; + + ddekit_printf("0x%lx ", (unsigned long) pc); + + if (hbp != 0 && hbp <= bp) { + pc = -1; + ddekit_printf("0x%lx ", (unsigned long) pc); + break; + } + bp= hbp; + } + ddekit_printf("\n"); +} diff --git a/lib/libddekit/src/thread.h b/lib/libddekit/src/thread.h new file mode 100644 index 000000000..322fa6223 --- /dev/null +++ b/lib/libddekit/src/thread.h @@ -0,0 +1,42 @@ +#ifndef DDEKIT_SRC_THREAD_H +#define DDEKIT_SRC_THREAD_H 1 +#include +#include +#include + +#define DDEKIT_THREAD_NAMELEN 32 +#define DDEKIT_THREAD_PRIOS 3 +#define DDEKIT_THREAD_STDPRIO 1 + +#define DDEKIT_THREAD_STACKSIZE (4096*16) + +/* This threadlib makes following assumptions: + * No Preemption, + * No signals, + * No blocking syscalls + * Threads cooperate. + */ + +struct ddekit_thread { + int id; + int prio; + void (*fun)(void *); + char *stack; + void *arg; + void *data; + unsigned sleep_until; + char name[DDEKIT_THREAD_NAMELEN]; + jmp_buf jb; + ddekit_sem_t *sleep_sem; + struct ddekit_thread * next; +}; + + +void _ddekit_thread_set_myprio(int prio); +void _ddekit_thread_enqueue(ddekit_thread_t *th); +void _ddekit_thread_schedule(); +void _ddekit_thread_wakeup_sleeping(); +void _ddekit_print_backtrace(ddekit_thread_t *th); + + +#endif diff --git a/lib/libddekit/src/timer.c b/lib/libddekit/src/timer.c new file mode 100644 index 000000000..75e848ed5 --- /dev/null +++ b/lib/libddekit/src/timer.c @@ -0,0 +1,315 @@ +#include "common.h" + +#include +#include +#include +#include + +#ifdef DDEBUG_LEVEL_TIMER +#undef DDEBUG +#define DDEBUG DDEBUG_LEVEL_TIMER +#endif + +#include "debug.h" +#include "thread.h" + +#define DDEBUG_MSG_TIMER(t) \ + DDEBUG_MSG_VERBOSE("id: %d, exp: %d, fn: %d, now %d", \ + (t)->id, (t)->exp, (t)->fn, jiffies) + +typedef clock_t myclock_t; + +struct ddekit_timer_s { + void (*fn)(void *); + void *args; + int id; + myclock_t exp; + struct ddekit_timer_s * next; +}; + + +PRIVATE ddekit_sem_t *pending_timer_ints; + +/* are we currently expecting a alarm notify? */ +int _ddekit_timer_pending = 0; + +PUBLIC unsigned long long jiffies; +PUBLIC unsigned long HZ; + +PRIVATE struct ddekit_timer_s list = {0,0,-1,1,0}; +PRIVATE int _id = 0 ; +PRIVATE ddekit_thread_t *th; +PRIVATE ddekit_lock_t lock; + +FORWARD _PROTOTYPE( void lock_timer, (void)); +FORWARD _PROTOTYPE( void unlock_timer, (void)); +FORWARD _PROTOTYPE( clock_t get_current_clock, (void)); +FORWARD _PROTOTYPE( void remove_timer, (int id)); +FORWARD _PROTOTYPE( int insert_timer, (struct ddekit_timer_s *t)); +FORWARD _PROTOTYPE( struct ddekit_timer_s * get_next, ( myclock_t exp )); +FORWARD _PROTOTYPE( void ddekit_timer_thread, (void *data)); + + /**************************************************************************** + * Private funtions * + ****************************************************************************/ + +/***************************************************************************** + * lock_timer * + ****************************************************************************/ +PRIVATE void lock_timer() +{ + ddekit_lock_lock(&lock); +} + +/***************************************************************************** + * unlock_timer * + ****************************************************************************/ +static void unlock_timer() +{ + ddekit_lock_unlock(&lock); +} + +/***************************************************************************** + * get_current_clock * + ****************************************************************************/ +static myclock_t get_current_clock() +{ + /* returns the current clock tick */ + myclock_t ret; + getuptime(&ret); + return ret; +} + +/***************************************************************************** + * remove_timer * + ****************************************************************************/ +PRIVATE void remove_timer(int id) +{ + /* removes a timer from the timer list */ + struct ddekit_timer_s *l,*m; + + lock_timer(); + + for (l = &list; l && l->next && l->next->id!=id; l = l->next ) + ; + + if (l && l->next) { + m = l->next; + + DDEBUG_MSG_VERBOSE( + "deleting timer at for tick: %d fn: %p, (now: %d)\n", + m->exp, m->fn, jiffies); + + l->next = m->next; + DDEBUG_MSG_TIMER(m); + + ddekit_simple_free(m); + } + + unlock_timer(); +} + +/***************************************************************************** + * insert_timer * + ****************************************************************************/ +PRIVATE int insert_timer(struct ddekit_timer_s *t) +{ + /* inserts a timer to the timer list */ + int ret; + + lock_timer(); + + struct ddekit_timer_s *l; + + for (l = &list; l->next && l->next->exp <= t->exp; l = l->next) { + + } + + t->next = l->next; + l->next = t; + + t->id = ret = _id; + + _id++; + + if (_id==0) { + DDEBUG_MSG_WARN("Timer ID overflow..."); + } + + DDEBUG_MSG_TIMER(t); + + unlock_timer(); + + return ret; +} + +/***************************************************************************** + * get_next * + ****************************************************************************/ +PRIVATE struct ddekit_timer_s * get_next( myclock_t exp ) +{ + /* + * this one get the next timer, which's timeout expired, + * returns NULL if no timer is pending + */ + struct ddekit_timer_s * ret = 0; + lock_timer(); + if (list.next) + { + if (list.next->exp <= exp) + { + ret = list.next; + list.next = ret->next; + } + } + unlock_timer(); + return ret; +} + +/***************************************************************************** + * ddekit_timer_thread * + ****************************************************************************/ +PRIVATE void ddekit_timer_thread(void * data) +{ + struct ddekit_timer_s * l; + + /* rock around the clock! */ + for ( ; ; ) + { + /* wait for timer interrupts */ + ddekit_sem_down(pending_timer_ints); + DDEBUG_MSG_VERBOSE("handling timer interrupt"); + + /* execute all expired timers */ + while( (l = get_next(jiffies)) != 0 ) { + DDEBUG_MSG_TIMER(l); + if (l->fn) { + l->fn(l->args); + } + ddekit_simple_free(l); + } + } +} + + + /**************************************************************************** + * Public functions (ddekit/timer.h) * + ****************************************************************************/ + +/***************************************************************************** + * ddekit_add_timer * + ****************************************************************************/ +PUBLIC int ddekit_add_timer +(void (*fn)(void *), void *args, unsigned long timeout) +{ + struct ddekit_timer_s *t; + + t = (struct ddekit_timer_s *) + ddekit_simple_malloc(sizeof(struct ddekit_timer_s )); + + t->fn = fn; + t->args = args; + t->exp = (myclock_t) timeout; + + return insert_timer(t); +} + +/***************************************************************************** + * ddekit_del_timer * + ****************************************************************************/ +PUBLIC int ddekit_del_timer(int timer) +{ + remove_timer(timer); + return 0; +} + +/***************************************************************************** + * ddekit_timer_pending * + ****************************************************************************/ +PUBLIC int ddekit_timer_pending(int timer) +{ + int ret=0; + struct ddekit_timer_s *t; + lock_timer(); + for (t=list.next; t; t = t->next) { + if (t->id==timer) { + ret = 1; + } + + } + unlock_timer(); + return ret; +} + +/***************************************************************************** + * ddekit_init_timers * + ****************************************************************************/ +PUBLIC void ddekit_init_timers(void) +{ + static int first_time=0; + + if (!first_time) + { + ddekit_lock_init(&lock); + jiffies = get_current_clock(); + HZ = sys_hz(); + pending_timer_ints = ddekit_sem_init(0); + th = ddekit_thread_create(ddekit_timer_thread, 0, "timer"); + first_time=1; + DDEBUG_MSG_INFO("DDEkit timer subsustem initialized"); + } +} + +/***************************************************************************** + * ddekit_get_timer_thread * + ****************************************************************************/ +PUBLIC ddekit_thread_t *ddekit_get_timer_thread(void) +{ + return th; +} + +/**************************************************************************** + * ddekit_internal (src/timer.h) * + ****************************************************************************/ + +/***************************************************************************** + * _ddekit_timer_interrupt * + ****************************************************************************/ +PUBLIC void _ddekit_timer_interrupt(void) +{ + jiffies = get_current_clock(); + DDEBUG_MSG_VERBOSE("now: %d", jiffies); + ddekit_sem_up(pending_timer_ints); +} + +/***************************************************************************** + * _ddekit_timer_update * + ****************************************************************************/ +PUBLIC void _ddekit_timer_update() +{ + lock_timer(); + + static myclock_t next_timout; + if(list.next) + { + if(!_ddekit_timer_pending || list.next->exp < next_timout) { + + unsigned to = list.next->exp - jiffies; + + _ddekit_timer_pending = 1; + + if (list.next->exp <= jiffies) { + DDEBUG_MSG_WARN("Timeout lies in past to %d, now: %d", + list.next->exp, jiffies); + to = 1; + } + + sys_setalarm(to, 0 /* REL */); + + DDEBUG_MSG_VERBOSE("requesting alarm for clock tick %d , now %d", + list.next->exp, jiffies); + } + next_timout = list.next->exp; + } + unlock_timer(); +} diff --git a/lib/libddekit/src/timer.h b/lib/libddekit/src/timer.h new file mode 100644 index 000000000..0d7751bb2 --- /dev/null +++ b/lib/libddekit/src/timer.h @@ -0,0 +1,11 @@ +#ifndef DDEKIT_TIMER_MINIX_H +#define DDEKIT_TIMER_MINIX_H 1 + + +extern unsigned long long jiffies; +extern unsigned long HZ; + +void _ddekit_timer_interrupt(void); +extern int _ddekit_timer_pending; +void _ddekit_timer_update(void); +#endif diff --git a/lib/libddekit/src/usb_client.c b/lib/libddekit/src/usb_client.c new file mode 100644 index 000000000..13463dbd3 --- /dev/null +++ b/lib/libddekit/src/usb_client.c @@ -0,0 +1,223 @@ +#include "common.h" +#include +#include +#include +#include + +struct ddekit_usb_dev { + int id; + unsigned int interfaces; + void *data; + struct ddekit_usb_dev *next; + struct ddekit_usb_dev *prev; +}; + +struct ddekit_usb_dev dev_list_head = { + .next = &dev_list_head, + .prev = &dev_list_head, +}; + +PRIVATE struct ddekit_usb_driver *d_usb_driver; + +FORWARD _PROTOTYPE( void _ddekit_usb_completion, (struct usb_urb *mx)); +FORWARD _PROTOTYPE( void _ddekit_usb_connect, + ( unsigned int dev_id, unsigned int interfaces)); +FORWARD _PROTOTYPE(void _ddekit_usb_disconnect, (unsigned dev_id)); + +struct usb_driver mx_usb_driver = { + .urb_completion = _ddekit_usb_completion, + .connect_device = _ddekit_usb_connect, + .disconnect_device = _ddekit_usb_disconnect +}; + +/***************************************************************************** + * _ddekit_usb_completion * + ****************************************************************************/ +PRIVATE void _ddekit_usb_completion(struct usb_urb *mx_urb) +{ + + struct ddekit_usb_urb *d_urb = (struct ddekit_usb_urb *) mx_urb->priv; + + /* XXX: copy stuff back into d_urb */ + + d_urb->status = mx_urb->status; + d_urb->error_count = mx_urb->interval; + d_urb->transfer_flags = mx_urb->error_count; + d_urb->actual_length = mx_urb->actual_length; + d_urb->ddekit_priv = NULL; + + if (mx_urb->type == USB_TRANSFER_CTL) { + memcpy(d_urb->setup_packet, mx_urb->setup_packet, 8); + } + + if (mx_urb->type == USB_TRANSFER_ISO) { + d_urb->start_frame = mx_urb->start_frame; + + memcpy(d_urb->iso_desc, mx_urb->buffer + d_urb->size, + d_urb->number_of_packets * sizeof(struct usb_iso_packet_desc)); + } + + memcpy(d_urb->data, mx_urb->buffer, d_urb->size); + + /* free mx_urb */ + ddekit_simple_free(mx_urb); + + /* 'give back' URB */ + + + d_usb_driver->completion(d_urb->priv); +} + + +/***************************************************************************** + * _ddekit_usb_connect * + ****************************************************************************/ +PRIVATE void _ddekit_usb_connect(unsigned int dev_id, unsigned int interfaces) +{ + struct ddekit_usb_dev *d_dev = (struct ddekit_usb_dev *) + ddekit_simple_malloc(sizeof(struct ddekit_usb_dev)); + + d_dev->data = NULL; + d_dev->id = dev_id; + d_dev->interfaces = interfaces; + + /* add to list */ + + d_dev->next = dev_list_head.next; + d_dev->prev = &dev_list_head; + + dev_list_head.next = d_dev; + d_dev->next->prev = d_dev; + d_usb_driver->connect(d_dev, interfaces); +} + +/***************************************************************************** + * _ddekit_usb_disconnect * + ****************************************************************************/ +PUBLIC void _ddekit_usb_disconnect(unsigned dev_id) +{ + /* find dev */ + struct ddekit_usb_dev *it; + struct ddekit_usb_dev *d_dev = NULL; + + + for (it = dev_list_head.next; it != &dev_list_head; it= it->next) { + if (it->id == dev_id) { + d_dev = it; + break; + } + } + + if (d_dev == NULL) { + return; + } + + d_usb_driver->disconnect(d_dev); +} + +/***************************************************************************** + * ddekit_usb_dev_set_data * + ****************************************************************************/ +PUBLIC int ddekit_usb_dev_set_data(struct ddekit_usb_dev *dev, void *data) +{ + dev->data = data; + return 0; +} + +/***************************************************************************** + * ddekit_usb_dev_get_data * + ****************************************************************************/ +PUBLIC void *ddekit_usb_dev_get_data(struct ddekit_usb_dev *dev) +{ + return dev->data; +} + +/***************************************************************************** + * ddekit_usb_submit_urb * + ****************************************************************************/ +PUBLIC int ddekit_usb_submit_urb(struct ddekit_usb_urb *d_urb) +{ + int res; + unsigned urb_size = USB_URBSIZE(d_urb->size, d_urb->number_of_packets); + + /* create mx urb out of d_urb */ + struct usb_urb *mx_urb = (struct usb_urb*) + ddekit_simple_malloc(urb_size); + + mx_urb->urb_size = urb_size; + + mx_urb->dev_id = d_urb->dev->id; + mx_urb->type = d_urb->type; + mx_urb->endpoint = d_urb->endpoint; + mx_urb->direction = d_urb->direction; + mx_urb->interval = d_urb->interval; + mx_urb->transfer_flags = d_urb->transfer_flags; + mx_urb->size = d_urb->size; + mx_urb->priv = d_urb; + + if (mx_urb->type == USB_TRANSFER_CTL) { + memcpy(mx_urb->setup_packet, d_urb->setup_packet, 8); + } + + if (mx_urb->type == USB_TRANSFER_ISO) { + mx_urb->number_of_packets = d_urb->number_of_packets; + mx_urb->start_frame = d_urb->start_frame; + + memcpy(mx_urb->buffer + d_urb->size, d_urb->iso_desc, + d_urb->number_of_packets * sizeof(struct usb_iso_packet_desc)); + } + + memcpy(mx_urb->buffer, d_urb->data, d_urb->size); + + d_urb->ddekit_priv = mx_urb; + + /* submit mx_urb */ + res = usb_send_urb(mx_urb); + + return res; +} + +/***************************************************************************** + * ddekit_usb_cancle_urb * + ****************************************************************************/ +PUBLIC int ddekit_usb_cancle_urb(struct ddekit_usb_urb *d_urb) +{ + int res; + + /* get the associated mx_urb */ + struct usb_urb *mx_urb = (struct usb_urb *) d_urb->ddekit_priv; + + res = usb_cancle_urb(mx_urb); + + return res; +} + +static void _ddekit_usb_thread() +{ + struct ddekit_minix_msg_q *mq = ddekit_minix_create_msg_q(USB_BASE, + USB_BASE + 0x1000); + message m; + + while (1) { + ddekit_minix_rcv(mq, &m); + usb_handle_msg(&mx_usb_driver,&m); + } + +} + +/***************************************************************************** + * ddekit_usb_init * + ****************************************************************************/ +PUBLIC int ddekit_usb_init +(struct ddekit_usb_driver *drv, + ddekit_usb_malloc_fn *unused, + ddekit_usb_free_fn *_unused) +{ + + /* start usb_thread */ + d_usb_driver = drv; + usb_init("dde"); + _ddekit_usb_thread(); + return 0; +} + diff --git a/lib/libddekit/src/usb_server.c b/lib/libddekit/src/usb_server.c new file mode 100644 index 000000000..2220497c5 --- /dev/null +++ b/lib/libddekit/src/usb_server.c @@ -0,0 +1,805 @@ +#include "common.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_URBS 10 + +#define DRIVER_UNUSED 0 +#define DRIVER_ACTIVE 1 +#define DRIVER_BOUND 2 + +#if 0 +#define DEBUG_MSG(fmt, ...) ddekit_printf("%s : "fmt"\n", __func__, ##__VA_ARGS__ ) +#else +#define DEBUG_MSG(fmt, ...) +#endif + +#undef DDEBUG +#define DDEBUG 0 +#include "debug.h" + +#define MAX_DEVS 256 +#define MAX_DRIVERS 256 +#define OK 0 + +#define INVAL_DEV (-1) + +struct my_context { + unsigned urb_id; + struct ddekit_usb_urb *d_urb; + struct usb_urb *mx_urb; + struct minix_usb_driver *drv; + gid_t gid; +}; + +struct minix_usb_driver { + endpoint_t ep; /* address of the client */ + + int status; /* In what state is the client? */ + + int dev; /* which device is this driver handling */ + unsigned interfaces; /* which interfaces of the device the + driver is handling */ + + struct ddekit_usb_urb *urbs[MAX_URBS]; /* pending urbs */ + + unsigned long urb_id; /* generation of driver_local urb_ids */ +}; + +struct minix_usb_device { + struct ddekit_usb_dev *dev; + unsigned int interfaces; +}; + +FORWARD _PROTOTYPE( struct minix_usb_driver *find_driver,(endpoint_t ep)); +FORWARD _PROTOTYPE( struct minix_usb_driver *find_unused_driver, (void)); +FORWARD _PROTOTYPE( int add_to_pending_urbs, + (struct minix_usb_driver *drv, struct ddekit_usb_urb *urb)); +FORWARD _PROTOTYPE( int remove_from_pending_urbs, + (struct minix_usb_driver *drv, struct ddekit_usb_urb *urb)); +FORWARD _PROTOTYPE( struct ddekit_usb_urb * find_pending_urb, + (struct minix_usb_driver *drv, unsigned urb_id)); +FORWARD _PROTOTYPE( void register_driver, (message *msg)); +FORWARD _PROTOTYPE( struct ddekit_usb_urb *ddekit_usb_urb_from_mx_urb, + (struct usb_urb *mx_urb)); +FORWARD _PROTOTYPE( void submit_urb, (message *msg)); +FORWARD _PROTOTYPE( void cancle_urb, (message *msg)); +FORWARD _PROTOTYPE( void completion_callback, (void *priv)); + +FORWARD _PROTOTYPE( void prepare_devman_usbdev, + (struct ddekit_usb_dev * dev, int dev_id, + unsigned int interfaces, struct devman_usb_dev *dudev)); +FORWARD _PROTOTYPE( void device_disconnect_callback, (struct ddekit_usb_dev * dev)); +FORWARD _PROTOTYPE( int add_acl, + (int dev_id, unsigned interfaces, endpoint_t ep) ); +FORWARD _PROTOTYPE( int del_acl, + (int dev_id, unsigned interaces, endpoint_t ep) ); +FORWARD _PROTOTYPE( int handle_msg, (message *msg)); +FORWARD _PROTOTYPE( void _ddekit_usb_thread, ()); +FORWARD _PROTOTYPE( void device_connect_callback, + (struct ddekit_usb_dev * dev, unsigned int interfaces)); + +_PROTOTYPE( char *_ddekit_usb_get_manufacturer, (struct ddekit_usb_dev *ddev)); +_PROTOTYPE( char *_ddekit_usb_get_product, (struct ddekit_usb_dev *ddev)); +_PROTOTYPE( char *_ddekit_usb_get_serial, (struct ddekit_usb_dev *ddev)); +_PROTOTYPE( usb_device_descriptor_t *_ddekit_usb_get_device_desc, + (struct ddekit_usb_dev *ddev)); +_PROTOTYPE( usb_interface_descriptor_t *_ddekit_usb_get_interface_desc, + (struct ddekit_usb_dev *ddev, int inum)); + + +PRIVATE ddekit_usb_malloc_fn my_malloc; +PRIVATE ddekit_usb_free_fn my_free; +PRIVATE struct minix_usb_driver gbl_drivers[MAX_DRIVERS]; +PRIVATE struct minix_usb_device _devices[MAX_DEVS]; + +PRIVATE struct ddekit_usb_driver my_driver = { + .completion = completion_callback, + .connect = device_connect_callback, + .disconnect = device_disconnect_callback, +}; + + +/***************************************************************************** + * find_driver * + ****************************************************************************/ +PRIVATE struct minix_usb_driver *find_driver(endpoint_t ep) +{ + int i; + for (i = 0; i < MAX_DRIVERS; i++ ){ + if (gbl_drivers[i].ep == ep) { + return &gbl_drivers[i]; + } + } + return NULL; +} + +/***************************************************************************** + * find_unused_driver * + ****************************************************************************/ +PRIVATE struct minix_usb_driver *find_unused_driver() +{ + int i; + for (i = 0; i < MAX_DRIVERS; i++ ){ + if (gbl_drivers[i].status == DRIVER_UNUSED) { + return &gbl_drivers[i]; + } + } + return NULL; +} + +/***************************************************************************** + * add_to_pending_urbs * + ****************************************************************************/ +PRIVATE int add_to_pending_urbs(struct minix_usb_driver *drv, + struct ddekit_usb_urb *urb) +{ + int i; + + for (i = 0; i < MAX_URBS; i++) { + if (drv->urbs[i] == NULL) { + drv->urbs[i] = urb; + return 0; + } + } + + return -1; +} + +/***************************************************************************** + * remove_from_pending_urbs * + ****************************************************************************/ +PRIVATE int remove_from_pending_urbs(struct minix_usb_driver *drv, + struct ddekit_usb_urb *urb) +{ + int i; + + for (i = 0; i < MAX_URBS; i++) { + if (drv->urbs[i] == urb) { + drv->urbs[i] = NULL; + return 0; + } + } + + return -1; +} + +/***************************************************************************** + * find_pending_urb * + ****************************************************************************/ +PRIVATE struct ddekit_usb_urb * find_pending_urb(struct minix_usb_driver *drv, + unsigned urb_id) +{ + int i; + + for (i = 0; i < MAX_URBS; i++) { + if (((struct my_context*)drv->urbs[i]->priv)->urb_id == urb_id) { + return drv->urbs[i]; + } + } + + return NULL; +} + +/***************************************************************************** + * register_driver * + ****************************************************************************/ +PRIVATE void register_driver(message *msg) +{ + endpoint_t ep = msg->m_source; + struct minix_usb_driver *drv; + + msg->m_type=USB_REPLY; + + if ( (drv = find_driver(ep)) != NULL) { + msg->m_type = USB_REPLY; + msg->USB_RESULT = OK; + send(ep,msg); + } else { + msg->m_type = USB_REPLY; + msg->USB_RESULT = EPERM; + send(ep,msg); + return; + } + + DEBUG_MSG("DRIVER %d registered \n" + "Announcing device %d, interfaces 0x%x\n", + ep, + drv->dev, + drv->interfaces); + + /* hand out the device */ + msg->m_type = USB_ANNOUCE_DEV; + msg->USB_DEV_ID = drv->dev; + msg->USB_INTERFACES = drv->interfaces; + send(ep, msg); +} + +/***************************************************************************** + * deregister_driver * + ****************************************************************************/ +PRIVATE void deregister_driver(message *msg) +{ + endpoint_t ep = msg->m_source; + + struct minix_usb_driver *drv; + + msg->m_type=USB_REPLY; + + if ( (drv = find_driver(ep)) == NULL) { + DEBUG_MSG("Non-registered driver tries to unregister."); + return; + } else { + /* do not accept requests for this client anymore! */ + drv->status = DRIVER_UNUSED; + + msg->USB_RESULT = 0; + asynsend3(ep, msg, AMF_NOREPLY); + } +} + +/***************************************************************************** + * ddekit_usb_urb_from_mx_urb * + ****************************************************************************/ +PRIVATE struct ddekit_usb_urb *ddekit_usb_urb_from_mx_urb(struct usb_urb *mx_urb) +{ + /* + * A helper function that generates (allocates and initializes) + * a ddekit_usb_urb. + */ + + struct ddekit_usb_urb *d_urb = (struct ddekit_usb_urb *) + my_malloc(sizeof(struct ddekit_usb_urb)); + + if (d_urb == NULL) { + return NULL; + } + + d_urb->type = mx_urb->type; + d_urb->direction = mx_urb->direction; + d_urb->transfer_flags = mx_urb->transfer_flags; + d_urb->size = mx_urb->size; + d_urb->data = mx_urb->buffer; + d_urb->interval = mx_urb->interval; + d_urb->endpoint = mx_urb->endpoint; + + if (d_urb->type == USB_TRANSFER_CTL) { + d_urb->setup_packet = mx_urb->setup_packet; + } + DEBUG_MSG("setup_package at %p", d_urb->setup_packet); + + if (d_urb->type == USB_TRANSFER_ISO) { + d_urb->iso_desc = (struct ddekit_usb_iso_packet_desc *) + mx_urb->buffer + mx_urb->iso_desc_offset; + d_urb->number_of_packets = mx_urb->number_of_packets; + } + + return d_urb; +} + +/***************************************************************************** + * submit_urb * + ****************************************************************************/ +PRIVATE void submit_urb(message *msg) +{ + /* + * submit_urb + * + * Handles a submit_urb from a minix USB device driver. It copies the + * usb_urb structure containing the buffers and generates and tries to + * submit a ddekit_usb_urb. The reference to the ddekit_usb_urb is stored + * in the driver structure in order to be able to cancle the URB on the + * clients request. + */ + endpoint_t ep = msg->m_source; + struct minix_usb_driver *drv; + + /* find driver */ + if ( (drv = find_driver(ep)) == NULL) { + DEBUG_MSG("Non-registered driver tries to send URB."); + return; + } else { + + int res; + + struct usb_urb *mx_urb = (struct usb_urb*) + my_malloc(msg->USB_GRANT_SIZE+sizeof(void *)); + + if (mx_urb == NULL) { + DEBUG_MSG("Can't allocat mem for mx_urb."); + res = ENOMEM; + goto out; + } + + /* copy in URB */ + res = sys_safecopyfrom(ep, msg->USB_GRANT_ID, 0, + (vir_bytes) &mx_urb->dev_id, msg->USB_GRANT_SIZE, D); + + if (res != 0) { + DEBUG_MSG("sys_safecopyfrom failed "); + my_free(mx_urb); + res = EINVAL; + goto out; + } + + DEBUG_MSG("URB type: %d", mx_urb->type); + /* check if urb is valid */ + if (mx_urb->dev_id >= MAX_DEVS && mx_urb->dev_id < 0) { + DEBUG_MSG("Bogus device ID."); + res = EINVAL; + goto out; + } + + /* create ddekit_usb_urb */ + struct ddekit_usb_urb *d_urb = ddekit_usb_urb_from_mx_urb(mx_urb); + d_urb->dev = _devices[drv->dev].dev; + /* submit urb */ + + if (!d_urb) { + res = ENOMEM; + goto out; + } + + struct my_context *ctx = (struct my_context *) + my_malloc(sizeof(struct my_context)); + + if(!ctx) { + res = ENOMEM; + goto out; + } + + ctx->drv = drv; + ctx->urb_id = drv->urb_id++; + mx_urb->urb_id = ctx->urb_id; + ctx->mx_urb = mx_urb; + ctx->d_urb = d_urb; + ctx->gid = msg->USB_GRANT_ID; + + DEBUG_MSG("ctx: %p, urb_id: %d, d_urb: %p, mx_urb: %p, drv: %d, gid: %d ", + ctx, ctx->urb_id, ctx->d_urb, ctx->mx_urb, ctx->drv, ctx->gid); + + d_urb->priv = ctx; + + res = add_to_pending_urbs(drv, d_urb); + + if (res == 0) { + DEBUG_MSG("submitting urb..."); + res = ddekit_usb_submit_urb(d_urb); + if(res) { + DEBUG_MSG("submitting urb failed (err: %d)", res); + remove_from_pending_urbs(drv, d_urb); + } + } + +out: + /* reply */ + msg->m_type = USB_REPLY; + msg->USB_URB_ID = mx_urb->urb_id; + msg->USB_RESULT = res; + + if(res != 0) { + + if (mx_urb != NULL) { + my_free(mx_urb); + } + if (ctx != NULL) { + my_free(ctx); + } + + if (d_urb != NULL) { + my_free(d_urb); + } + + } + + /* send reply */ + send(ep, msg); + } +} + + +/* + * cancle_urb + * + * Cancels the submission of an URB identified by a URB_id + */ +/***************************************************************************** + * cancle_urb * + ****************************************************************************/ +PRIVATE void cancle_urb(message *msg) +{ + endpoint_t ep = msg->m_source; + + struct minix_usb_driver *drv; + + msg->USB_RESULT = -1; + msg->m_type = USB_REPLY; + + /* find driver */ + if ( (drv = find_driver(ep)) == NULL) { + DEBUG_MSG("Non-registered driver tries to cancel URB."); + return; + } else { + struct ddekit_usb_urb *d_urb = NULL; + + d_urb = find_pending_urb(drv, msg->USB_URB_ID); + + if (d_urb != NULL) { + ddekit_usb_cancle_urb(d_urb); + msg->USB_RESULT = 0; + } else { + DEBUG_MSG("No URB to cancle"); + msg->USB_RESULT = ENODEV; + } + } + + send(ep, msg); +} + + +/***************************************************************************** + * completion_callback * + ****************************************************************************/ +PRIVATE void completion_callback(void *priv) +{ + /* + * completion_callback + * + * This is called by the DDE side. Here the data is copied back to + * the driver and a message is send to inform the driver about the + * completion. + */ + message msg; + int res; + struct my_context *ctx = (struct my_context *)priv; + struct usb_urb *mx_urb = ctx->mx_urb; + struct ddekit_usb_urb *d_urb = ctx->d_urb; + struct minix_usb_driver *drv = ctx->drv; + + DEBUG_MSG("ctx: %p, urb_id: %d, d_urb: %p, mx_urb: %p, drv: %d, gid: %d ", + ctx, ctx->urb_id, ctx->d_urb, ctx->mx_urb, ctx->drv, ctx->gid); + + /* update data in minix URB */ + mx_urb->status = d_urb->status; + mx_urb->actual_length = d_urb->actual_length; + mx_urb->error_count = d_urb->error_count; + mx_urb->transfer_flags = d_urb->transfer_flags; + + remove_from_pending_urbs(drv, d_urb); + + /* copy out URB */ + res = sys_safecopyto(drv->ep, ctx->gid, 0, + (vir_bytes) ((char*)mx_urb) + sizeof(void*), + mx_urb->urb_size - sizeof(void*), D); + + if (res != 0) { + DEBUG_MSG("Copy out failed: %d", res); + DEBUG_MSG(" URB ID: %d, Grant-ID: %d, Grant-size: %d", ctx->urb_id, + ctx->gid, mx_urb->urb_size); + } + + /* send message to client */ + msg.m_type = USB_COMPLETE_URB; + msg.USB_URB_ID = ctx->urb_id; + asynsend3(drv->ep, &msg, AMF_NOREPLY); + + /* free stuff */ + my_free(ctx); + my_free(mx_urb); + my_free(d_urb); +} + + +/***************************************************************************** + * prepare_devman_usbdev * + ****************************************************************************/ +PRIVATE void prepare_devman_usbdev +(struct ddekit_usb_dev * dev, int dev_id, unsigned int interfaces, + struct devman_usb_dev *dudev) +{ + int j; + int intf_count; + /* + * currently this is only implemented by stub driver + */ + + usb_device_descriptor_t *desc = _ddekit_usb_get_device_desc(dev); + + dudev->manufacturer = _ddekit_usb_get_manufacturer(dev); + dudev->product = _ddekit_usb_get_product(dev); + dudev->serial = _ddekit_usb_get_serial(dev); + + dudev->desc = desc; + + intf_count = 0; + + for (j=0; j < 32; j++) { + if (interfaces & (1 << j)) { + dudev->interfaces[intf_count++].desc = + _ddekit_usb_get_interface_desc(dev, j); + } + } + + dudev->intf_count = intf_count; + dudev->dev_id = dev_id; +} + +/***************************************************************************** + * device_connect_callback * + ****************************************************************************/ +PRIVATE void +device_connect_callback +(struct ddekit_usb_dev * dev, unsigned int interfaces) { + + int i, res; + + /* add to device list */ + for (i=0; i < MAX_DEVS; i++) { + if (_devices[i].dev == NULL) + break; + } + + if (_devices[i].dev!= NULL) { + DEBUG_MSG("Too much devices..."); + } else { + _devices[i].dev = dev; + _devices[i].interfaces = (1 << interfaces); + } + + struct devman_usb_dev *dudev; + + dudev = devman_usb_device_new(i); + + prepare_devman_usbdev(dev, i, interfaces, dudev); + + if (dudev == NULL) { + /* TODO: ERROR */ + printf("ERROR: !"); + } + + ddekit_usb_dev_set_data(dev, dudev); + + res = devman_usb_device_add(dudev); + + if (res != 0) { + /* TODO: Error*/ + printf("ERROR!"); + } +} + +/***************************************************************************** + * device_disconnect_callback * + ****************************************************************************/ +PRIVATE void device_disconnect_callback(struct ddekit_usb_dev * dev) +{ + int i; + + /* remove ACL entry */ + for (i = 0; i< MAX_DRIVERS; i++) { + if (gbl_drivers[i].dev != INVAL_DEV + && _devices[gbl_drivers[i].dev].dev == dev) { + struct minix_usb_driver *drv = &gbl_drivers[i]; + drv->ep = 0; + drv->status = DRIVER_UNUSED; + drv->dev = INVAL_DEV; + } + } + + for (i=0; i < MAX_DEVS; i++) { + if (_devices[i].dev == dev) { + _devices[i].dev = NULL; + _devices[i].interfaces = 0; + } + } + + + /* get the devman device */ + struct devman_usb_dev * dudev = NULL; + + dudev = ddekit_usb_dev_get_data(dev); + + if (dudev == NULL) { + /* TODO: error */ + } + + devman_usb_device_remove(dudev); + + /* free the devman dev */ + devman_usb_device_delete(dudev); +} + + +/***************************************************************************** + * add_acl * + ****************************************************************************/ +PRIVATE int add_acl(int dev_id, unsigned interfaces, endpoint_t ep) +{ + /* + * This functions binds a specific USB interface to a client. + */ + int i; + struct minix_usb_driver *drv; + + if (_devices[dev_id].dev == NULL) { + /* if no device with that ID */ + return ENODEV; + } + + /* is the device allready given to a client*/ + for (i = 0; i< MAX_DRIVERS; i++) { + if (gbl_drivers[i].status != DRIVER_UNUSED && + gbl_drivers[i].dev == dev_id) { + printf("devid: %d\n", dev_id); + return EBUSY; + } + } + + /* bind device to client */ + drv = find_unused_driver(); + + if (drv == NULL) { + return ENOMEM; + } + + drv->status = DRIVER_BOUND; + drv->dev = dev_id; + drv->interfaces = 1 << interfaces; + drv->ep = ep; + drv->urb_id = 0; + + return OK; +} + +/***************************************************************************** + * del_acl * + ****************************************************************************/ +PRIVATE int del_acl(int dev_id, unsigned interfaces, endpoint_t ep) +{ + struct minix_usb_driver *drv; + int dev, withdraw = 0; + message msg; + + /* find driver */ + drv = find_driver(ep); + + if (drv == NULL) { + return ENOENT; + } + + dev = drv->dev; + + if (drv->status == DRIVER_ACTIVE) { + withdraw = 1; + } + + drv->ep = 0; + drv->status = DRIVER_UNUSED; + drv->dev = INVAL_DEV; + + if (withdraw) { + msg.m_type = USB_WITHDRAW_DEV; + msg.USB_DEV_ID = dev; + asynsend3(ep, &msg, AMF_NOREPLY); + } + + return 0; +} + +/***************************************************************************** + * handle_msg * + ****************************************************************************/ +PRIVATE int handle_msg(message *msg) +{ + /* + * handle_msg + * + * The dispatcher for USB related messages. + */ + + switch(msg->m_type) { + case USB_RQ_INIT: + register_driver(msg); + return 1; + case USB_RQ_DEINIT: + deregister_driver(msg); + return 1; + case USB_RQ_SEND_URB: + submit_urb(msg); + return 1; + case USB_RQ_CANCEL_URB: + cancle_urb(msg); + return 1; + default: + return 0; + } +} + +/***************************************************************************** + * devman_tread * + ****************************************************************************/ +PRIVATE void devman_thread(void *unused) +{ + struct ddekit_minix_msg_q *mq = ddekit_minix_create_msg_q(DEVMAN_BASE, + DEVMAN_BASE + 0xff); + + message m; + while (1) { + ddekit_minix_rcv(mq, &m); + devman_handle_msg(&m); + } +} + +/***************************************************************************** + * _ddekit_usb_thread * + ****************************************************************************/ +PRIVATE void _ddekit_usb_thread(void * unused) +{ + struct ddekit_minix_msg_q *mq = ddekit_minix_create_msg_q(USB_BASE, + USB_BASE + 0xff); + + message m; + + /* create devman thread */ + ddekit_thread_t * dmth; + + dmth = ddekit_thread_create(devman_thread, NULL, "devman_thread"); + + while (1) { + ddekit_minix_rcv(mq, &m); + handle_msg(&m); + } +} + + +/***************************************************************************** + * bind_cb * + ****************************************************************************/ +PRIVATE int bind_cb (struct devman_usb_bind_cb_data *data, endpoint_t ep) +{ + if(data) { + return add_acl(data->dev_id, data->interface, ep); + } else { + printf("warning: missing cb_data!\n"); + return EINVAL; + } +} + +/***************************************************************************** + * unbind_cb * + ****************************************************************************/ +PRIVATE int unbind_cb (struct devman_usb_bind_cb_data *data, endpoint_t ep) +{ + if(data) { + return del_acl(data->dev_id, data->interface, ep); + } else { + printf("warning: missing cb_data!\n"); + return EINVAL; + } +} + +/***************************************************************************** + * ddekit_usb_server_init * + ****************************************************************************/ +PUBLIC void ddekit_usb_server_init() +{ + int i; + /* + * this function has to be called inside the context of an dedicated + * DDELinux thread + */ + devman_usb_init(bind_cb, unbind_cb); + ddekit_usb_init(&my_driver, &my_malloc, &my_free); + for (i = 0; i< MAX_DRIVERS; i++) { + gbl_drivers[i].dev = DRIVER_UNUSED; + gbl_drivers[i].dev = INVAL_DEV; + } + _ddekit_usb_thread(NULL); + +} diff --git a/lib/libddekit/src/util.h b/lib/libddekit/src/util.h new file mode 100644 index 000000000..b003e1918 --- /dev/null +++ b/lib/libddekit/src/util.h @@ -0,0 +1,3 @@ +#include + +#define WARN_UNIMPL ddekit_printf("WARNING: %s unimplemented!\n", __func__) diff --git a/share/mk/bsd.prog.mk b/share/mk/bsd.prog.mk index cc337be9a..52adbfffc 100644 --- a/share/mk/bsd.prog.mk +++ b/share/mk/bsd.prog.mk @@ -59,7 +59,7 @@ MKDEP_SUFFIXES?= .o .ln # rumpfs_tmpfs rumpfs_udf rumpfs_ufs .for _lib in \ c curses driver netdriver edit end m sys timers util bz2 l hgfs \ - audiodriver exec devman usb + audiodriver exec ddekit devman usb .ifndef LIB${_lib:tu} LIB${_lib:tu}= ${DESTDIR}/usr/lib/lib${_lib}.a .if ${COMPILER_TYPE} == "ack"