Rev 526 |
Rev 565 |
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
;
}
int get_free_timer_slot
()
{
int i
= 16;
while(timer_table
[i
] != -1)
if (i
< MAX_INT_TABLE
) i
++; else return -1;
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
);
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;
}