added libddekit

This commit is contained in:
Dirk Vogt 2011-02-25 12:40:31 +00:00
parent 3c9012886f
commit e94953a396
31 changed files with 4350 additions and 2 deletions

View file

@ -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

6
lib/libddekit/Makefile Normal file
View file

@ -0,0 +1,6 @@
.if ${COMPILER_TYPE} == "gnu"
SUBDIR = build
.endif
.include <bsd.subdir.mk>

View file

@ -0,0 +1,6 @@
.if ${COMPILER_TYPE} == "gnu"
SUBDIR = ddekit ddekit_usb_client ddekit_usb_server
.endif
.include <bsd.subdir.mk>

View file

@ -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 <bsd.lib.mk>

View file

@ -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 <bsd.lib.mk>

View file

@ -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 <bsd.lib.mk>

View file

@ -0,0 +1,14 @@
#define _MINIX
#define _POSIX_SOURCE
#include <minix/callnr.h>
#include <minix/com.h>
#include <minix/config.h>
#include <minix/const.h>
#include <minix/endpoint.h>
#include <minix/ipc.h>
#include <minix/syslib.h>
#include <minix/sysutil.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>

119
lib/libddekit/src/condvar.c Normal file
View file

@ -0,0 +1,119 @@
#include "common.h"
#include <ddekit/condvar.h>
#include <ddekit/lock.h>
#include <ddekit/memory.h>
#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();
}

138
lib/libddekit/src/dde.c Normal file
View file

@ -0,0 +1,138 @@
#include "common.h"
#include <ddekit/initcall.h>
#include <ddekit/minix/msg_queue.h>
#include <ddekit/panic.h>
#include <ddekit/pci.h>
#include <ddekit/semaphore.h>
#include <ddekit/timer.h>
#include <signal.h>
#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);
}

1
lib/libddekit/src/dde.h Normal file
View file

@ -0,0 +1 @@

View file

@ -0,0 +1,7 @@
#ifndef DDEKIT_DEBUG_MACROS_H
#define DDEKIT_DEBUG_MACROS_H
#include <ddekit/printf.h>
#include <ddekit/debug.h>
#endif /* DDEKIT_DEBUG_MACROS_H */

View file

@ -0,0 +1,57 @@
#include "common.h"
#include <ddekit/initcall.h>
#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();
}
}

257
lib/libddekit/src/irq.c Normal file
View file

@ -0,0 +1,257 @@
#include "common.h"
#include <ddekit/interrupt.h>
#include <ddekit/memory.h>
#include <ddekit/semaphore.h>
#include <ddekit/thread.h>
#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);
}
}

5
lib/libddekit/src/irq.h Normal file
View file

@ -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

118
lib/libddekit/src/lock.c Normal file
View file

@ -0,0 +1,118 @@
#include "common.h"
#include <ddekit/assert.h>
#include <ddekit/memory.h>
#include <ddekit/semaphore.h>
#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);
}

460
lib/libddekit/src/mem.c Normal file
View file

@ -0,0 +1,460 @@
#include "common.h"
#include <ddekit/lock.h>
#include <ddekit/memory.h>
#include <ddekit/panic.h>
#include <ddekit/pgtab.h>
#include <ddekit/inline.h>
#include <ddekit/types.h>
#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);
}

View file

@ -0,0 +1,155 @@
#include "common.h"
#include <ddekit/memory.h>
#include <ddekit/minix/msg_queue.h>
#include <ddekit/panic.h>
#include <ddekit/semaphore.h>
#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);
}

34
lib/libddekit/src/panic.c Normal file
View file

@ -0,0 +1,34 @@
#include "common.h"
#include <ddekit/panic.h>
#include <ddekit/printf.h>
/****************************************************************************/
/* 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);
}

447
lib/libddekit/src/pci.c Normal file
View file

@ -0,0 +1,447 @@
/**
* pci.c
* @author: Dirk Vogt
* @date: 2010-02-18
*/
#include "common.h"
#include <ddekit/pci.h>
#include <ddekit/panic.h>
#include <minix/syslib.h>
#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;
}

313
lib/libddekit/src/pgtab.c Normal file
View file

@ -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 <ddekit/pgtab.h>
#include <ddekit/memory.h>
#include <ddekit/lock.h>
#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);
}

View file

@ -0,0 +1,33 @@
#include "common.h"
#include <ddekit/printf.h>
/****************************************************************************/
/* 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);
}

View file

@ -0,0 +1,138 @@
#include "common.h"
#include <ddekit/panic.h>
#include <ddekit/resources.h>
#include <ddekit/pgtab.h>
#include <minix/vm.h>
#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);
}

View file

@ -0,0 +1,111 @@
#include "common.h"
#include <ddekit/condvar.h>
#include <ddekit/lock.h>
#include <ddekit/memory.h>
#include <ddekit/panic.h>
#include <ddekit/semaphore.h>
#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;
}

499
lib/libddekit/src/thread.c Normal file
View file

@ -0,0 +1,499 @@
#include "common.h"
#include <ddekit/assert.h>
#include <ddekit/condvar.h>
#include <ddekit/memory.h>
#include <ddekit/panic.h>
#include <ddekit/timer.h>
#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 <sys/jmp_buf.h>
#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 <sys/jmp_buf.h>
#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");
}

View file

@ -0,0 +1,42 @@
#ifndef DDEKIT_SRC_THREAD_H
#define DDEKIT_SRC_THREAD_H 1
#include <ddekit/thread.h>
#include <ddekit/semaphore.h>
#include <setjmp.h>
#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

315
lib/libddekit/src/timer.c Normal file
View file

@ -0,0 +1,315 @@
#include "common.h"
#include <ddekit/memory.h>
#include <ddekit/semaphore.h>
#include <ddekit/thread.h>
#include <ddekit/timer.h>
#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();
}

11
lib/libddekit/src/timer.h Normal file
View file

@ -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

View file

@ -0,0 +1,223 @@
#include "common.h"
#include <ddekit/usb.h>
#include <ddekit/memory.h>
#include <ddekit/minix/msg_queue.h>
#include <minix/usb.h>
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;
}

View file

@ -0,0 +1,805 @@
#include "common.h"
#include <ddekit/minix/msg_queue.h>
#include <ddekit/panic.h>
#include <ddekit/printf.h>
#include <ddekit/usb.h>
#include <minix/safecopies.h>
#include <minix/usb.h>
#include <minix/usb_ch9.h>
#include <minix/devman.h>
#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);
}

3
lib/libddekit/src/util.h Normal file
View file

@ -0,0 +1,3 @@
#include <ddekit/printf.h>
#define WARN_UNIMPL ddekit_printf("WARNING: %s unimplemented!\n", __func__)

View file

@ -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"