Subversion Repositories shark

Rev

Rev 1019 | Blame | Compare with Previous | Last modification | View Log | RSS feed

#include <kernel/int_sem.h>
#include <stdlib.h>
#include <kernel/func.h>
#include <ll/sys/ll/event.h>
#include <ll/i386/pic.h>
#include <tracer.h>

#include <linuxcomp.h>

extern int add_interrupt_job(int no);
extern void set_noint_handler(void * new_handler);

extern int intr_count;

//#define DEBUG_SHARK_GLUE

/* 1-15 for IRQ and 16-63 for timers */
void *timer_arg_table[MAX_TIMER_TABLE];
void *timer_func_table[MAX_TIMER_TABLE];
int  timer_table[MAX_TIMER_TABLE];
int  intr_table[NR_IRQS];

int use_intdrive = 0;
static int current_timer = 0;

void shark_internal_sem_create(void **sem, int init) {
        *sem = (void *)malloc(sizeof(internal_sem_t));
        internal_sem_init((internal_sem_t *)(*sem),init);
}

void shark_internal_sem_wait(void *sem) {
        internal_sem_wait((internal_sem_t *)(sem));
}

void shark_internal_sem_post(void *sem) {
        internal_sem_post((internal_sem_t *)(sem));
}

/* Timers */

int get_free_timer_slot()
{
        int i = current_timer;

        while(timer_table[i] != -1) {
                if (i < MAX_TIMER_TABLE) {
                        i++;
                } else {
                        i = 0;
                }
                if (i == current_timer) return -1;
        }

        current_timer = i+1;
        if (current_timer >= MAX_TIMER_TABLE) current_timer = 0;

        return i;
}

void shark_timer_exec(int n)
{
        int no = n - 16;
        void(*tmp_func)(void*) = timer_func_table[no];

#ifdef DEBUG_SHARK_GLUE
        cprintf("(Timer EXEC %d)", no);
#endif

        if (tmp_func != NULL){
                intr_count++;
                (tmp_func)(timer_arg_table[no]);
                intr_count--;
        }

        timer_table[no] = -1;
        timer_func_table[no] = NULL;
        timer_arg_table[no] = NULL;
}

void fast_call_timer(void *arg)
{
        int no = (int)arg;
        int res;

#ifdef DEBUG_SHARK_GLUE
        cprintf("(Timer fast %d)", no);
#endif

        timer_table[no] = -2;

        if (use_intdrive == TRUE) {
                res = add_interrupt_job(no+16);
        } else {
                shark_timer_exec(no+16);
        }
}

int shark_timer_set(const struct timespec *time, void *handler, void *arg)
{
        SYS_FLAGS f;
        int i;

        f = kern_fsave();

        i = get_free_timer_slot();

        if (i == -1) {
                kern_frestore(f);
                return -1;
        }

        timer_func_table[i] = handler;
        timer_arg_table[i] = arg;

        timer_table[i] = kern_event_post(time, fast_call_timer, (void *)(i));
       
        if (timer_table[i] == -1) {
                kern_frestore(f);
                return -1;
        }

        kern_frestore(f);

        return i;
}

int shark_timer_delete(int index)
{
        SYS_FLAGS f;

        f = kern_fsave();

        if (index < 0 || index >= MAX_TIMER_TABLE) {
                kern_frestore(f);
                return -1;
        }

#ifdef DEBUG_SHARK_GLUE
        cprintf("(Timer Del %d)", index);
#endif

        if (timer_table[index] != -1 && timer_table[index] != -2) {
                timer_func_table[index] = NULL;
                timer_arg_table[index] = NULL;

                kern_event_delete(timer_table[index]);
                timer_table[index] = -1;
        }
        kern_frestore(f);

        return 0;
}

/* Interrupt */
int shark_handler_set(int no, void *fast){

        if ((no >= 1) && (no < 16) && (intr_table[no] <= 0)) {
                if (use_intdrive == TRUE) {
                        intr_table[no] = handler_set(no, NULL, TRUE, NIL, fast);
#ifdef DEBUG_SHARK_GLUE
                        cprintf("(shark_handler_set - INT: %d - %d)", no, intr_table[no]);
#endif
                } else {
                        intr_table[no] = handler_set(no, fast, TRUE, NIL, NULL);
#ifdef DEBUG_SHARK_GLUE
                        cprintf("(Shark_Handler_Set - NOINT: %d - %d)", no, intr_table[no]);
#endif
                }
                return intr_table[no];
        } else {
#ifdef DEBUG_SHARK_GLUE
                cprintf("(shark_handler_set - ERR: %d - %d)", no, intr_table[no]);
#endif
                return -1;
        }
}

int shark_handler_remove(int no){

        if (intr_table[no] == 1) {
                handler_remove(no);
#ifdef DEBUG_SHARK_GLUE
                cprintf("(shark_handler_remove: %d)", no);
#endif
                intr_table[no] = 0;
        }

        return 0;
}
 
/* Boot function */
int shark_interrupt_server(int use_intdrv) {
        int i;

        for(i=0; i<MAX_TIMER_TABLE; i++) {
                timer_arg_table[i] = NULL;
                timer_func_table[i] = NULL;
                timer_table[i] = -1;
        }
        for(i=0; i<NR_IRQS; i++) {
                intr_table[i] = 0;
        }
       
        use_intdrive = use_intdrv;
#ifdef DEBUG_SHARK_GLUE
        cprintf("(Use_intdrive: %d)", use_intdrive);
#endif
        if (use_intdrive == TRUE)
                set_noint_handler(shark_timer_exec);

        return 0;
}