Subversion Repositories shark

Rev

Rev 526 | Rev 856 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

#include <linuxcomp.h>

#include <asm/ptrace.h>
#include <asm-generic/errno-base.h>
#include <linux/kernel.h>

extern void *int_arg_table[MAX_INT_TABLE];
extern void *int_func_table[MAX_INT_TABLE];

#define MAX_IRQS 16

#ifndef NIL
#define NIL     -1                      /*+ integer unvalid value   +*/
#endif

struct int_handler {
        void (*func)(int, void *dev_id, struct pt_regs *);
        void *data;
        int flags;
        struct int_handler *next;
};

static struct irq_handler_list {
        struct int_handler *handlers;
} irq_list[MAX_IRQS];

void init_linux_irq();
extern void fast_call_intr(int no);
extern void* malloc(int size);
extern void free(void *ptr);
extern int handler_set(int no, void (*fast)(int), int pi, BYTE lock);
extern int handler_remove(int no);

unsigned long intr_count = 0;
static int init = 0;

/*
* Generic Linux interrupt handler.
*/

void linux_intr(int irq)
{
        struct pt_regs regs;
        struct int_handler *ihp;

        // irq_mask(irq);

        intr_count++;

        ihp=irq_list[irq].handlers;
        while (ihp) {
                (*ihp->func)(irq, ihp->data, &regs);
                ihp=ihp->next;
        }

        intr_count--;
        //        irq_unmask(irq);

}

void add_list(struct int_handler** headp, struct int_handler *ihp)
{
        if (*headp == NULL) {
                *headp=ihp;
                return;
        }
        ihp->next=*headp;
        *headp=ihp;
}

#define USE_IRQ_SERVER

/*
* Attach a handler to an IRQ.
*/

int request_irq(unsigned int irq, void (*handler)(int, void *dev_id, struct pt_regs *), unsigned long flags, const char *device, void *dev_id)
{
        struct int_handler *ihp;

        if (init == 0)
                init_linux_irq();

        ihp=malloc(sizeof(struct int_handler));
        if (ihp == NULL)
                return -ENOMEM;

        if (irq_list[irq].handlers == NULL)
        {
                //* Warning: check if irq is used from somebody that doesn't share!
#ifdef USE_IRQ_SERVER
                shark_handler_set(irq, NULL, NULL);
#else
                handler_set(irq, linux_intr, NIL, TRUE);
#endif
        }
        ihp->func = handler;
        ihp->flags = flags;
        ihp->data = dev_id;
        ihp->next = NULL;
        add_list(&irq_list[irq].handlers, ihp);

        return 0;
}

/*
* Deallocate an irq
*/

void free_irq(unsigned int irq, void *dev_id)
{
        struct int_handler **headp, *ihp;

        headp=&irq_list[irq].handlers;
        while (*headp)
        {
                ihp=*headp;
                if (ihp->data == dev_id)
                {
                        *headp=ihp->next;
                        free(ihp);
                        break;
                }
                headp=&ihp->next;
        }

        if (irq_list[irq].handlers == NULL)
        {
                handler_remove(irq);
        }
}

void init_linux_irq()
{
        int i;

        for (i=0; i<MAX_IRQS; i++)
        {
                irq_list[i].handlers = NULL;
        }
        init=1;
}