Subversion Repositories shark

Rev

Rev 559 | Rev 1007 | Go to most recent revision | 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 <linuxcomp.h>

//#define DEBUG_SHARK_GLUE

PID intr_server = NIL;

#define MAX_INT_LIST 50

/* 1-15 for IRQ and 16-63 for timers */

void *int_arg_table[MAX_INT_TABLE];
void *int_func_table[MAX_INT_TABLE];
int  timer_table[MAX_INT_TABLE];

int int_list[MAX_INT_LIST];
int next_free_int = 0;
int next_execute_int = 0;

/* FIFO add job */
int add_interrupt_job(int no)
{

        int old_free_int = next_free_int;

        int_list[next_free_int] = no;
        next_free_int++;

        if (next_free_int == MAX_INT_LIST) next_free_int = 0;
        if (next_free_int == next_execute_int) {
                next_free_int = old_free_int;
                return -1;
        }

        return 0;

}

/* FIFO get job */
int get_interrupt_job()
{

        int res = -1;

        if (next_free_int != next_execute_int) {
                res = int_list[next_execute_int];
                next_execute_int++;
                if (next_execute_int == MAX_INT_LIST) next_execute_int = 0;
        }

        return res;
       
}

static int current_timer = 16;

int get_free_timer_slot()
{

        int i = current_timer, count = 0;

        while(timer_table[i] != -1) {
                if (i < MAX_INT_TABLE) {
                        i++;
                        count++;
                } else {
                        i = 16;
                }
                if (count > 2) return -1;
        }

        current_timer = i+1;
        if (current_timer >= MAX_INT_TABLE) current_timer = 16;

        return i;

}

extern void linux_intr(int no);
extern void linux_timer(int no);


/* The Interrupt TASK is an aperiodic task designed for
        the INTDRIVE module. */


TASK Interrupt_Server(void *arg)
{

        int no;

        while(1) {

                no = get_interrupt_job();

                if (no != -1 && no < 16) {
                        linux_intr(no);
                        irq_unmask(no);
                }

                if (no != -1 && no >= 16) {
                        linux_timer(no);
                        timer_table[no] = -1;
                        int_func_table[no] = NULL;
                        int_arg_table[no] = NULL;
                }

                task_endcycle();

        }

}

int shark_interrupt_server() {

        HARD_TASK_MODEL ht;
        int i;

        for(i=0;i<MAX_INT_TABLE;i++) {
                int_arg_table[i] = NULL;
                int_func_table[i] = NULL;
                timer_table[i] = -1;
        }


        hard_task_default_model(ht);
        hard_task_def_wcet(ht,10000);
        hard_task_def_interrupt(ht);
        hard_task_def_system(ht);
        hard_task_def_nokill(ht);

        intr_server = task_create("Interrupt Server",Interrupt_Server,&ht,NULL);
        if (intr_server == NIL)
                return -1;

        return 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 */

void fast_call_timer(void *arg)
{

        int no = (int)arg,res;

        #ifdef DEBUG_SHARK_GLUE
          cprintf("(Timer Exe)");
        #endif

        timer_table[no] = -2;

        res = add_interrupt_job(no);
        if (intr_server != NIL && res == 0)
                task_activate(intr_server);

}

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

        f = kern_fsave();

        #ifdef DEBUG_SHARK_GLUE
          cprintf("(Timer Set)");
        #endif

        i = get_free_timer_slot();

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

        int_func_table[i] = handler;
        int_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_INT_TABLE) {
                kern_frestore(f);
                return -1;
        }

        #ifdef DEBUG_SHARK_GLUE
          cprintf("(Timer Del)");
        #endif

        if (timer_table[index] != -1 && timer_table[index] != -2) {

                int_func_table[index] = NULL;
                int_arg_table[index] = NULL;
       
                kern_event_delete(timer_table[index]);

                timer_table[index] = -1;

        }                                                                                                        
        kern_frestore(f);

        return 0;

}

/* Interrupt */

void fast_call_intr(int no)
{
        int res;

        #ifdef DEBUG_SHARK_GLUE
          cprintf("(Int Exe)");
        #endif

        irq_mask(no);

        res = add_interrupt_job(no);
        if (intr_server != NIL && res == 0)
                task_activate(intr_server);

}

int shark_handler_set(int no, void *fast, void *arg){

        if (no >= 1 && no < 16 && int_func_table[no] == NULL) {
                int_arg_table[no] = arg;
                int_func_table[no] = fast;
                return handler_set(no, fast_call_intr, NIL, TRUE);
        } else {
                return -1;
        }

}

int shark_handler_remove(int no){

        int_func_table[no] = NULL;
        int_arg_table[no] = NULL;
        handler_remove(no);
        return 0;

}