Subversion Repositories shark

Rev

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

/* Project:     OSLib
 * Description: The OS Construction Kit
 * Date:                1.6.2000
 * Idea by:             Luca Abeni & Gerardo Lamastra
 *
 * OSLib is an SO project aimed at developing a common, easy-to-use
 * low-level infrastructure for developing OS kernels and Embedded
 * Applications; it partially derives from the HARTIK project but it
 * currently is independently developed.
 *
 * OSLib is distributed under GPL License, and some of its code has
 * been derived from the Linux kernel source; also some important
 * ideas come from studying the DJGPP go32 extender.
 *
 * We acknowledge the Linux Community, Free Software Foundation,
 * D.J. Delorie and all the other developers who believe in the
 * freedom of software and ideas.
 *
 * For legalese, check out the included GPL license.
 */


/*      Interrupt Events */

#include <arch/i386/stdlib.h>
#include <ll/i386/mem.h>
#include <ll/i386/error.h>
#include <ll/i386/hw-arch.h>
#include <ll/i386/pit.h>
#include <ll/i386/pic.h>
#include <ll/sys/ll/ll-data.h>
#include <ll/sys/ll/ll-instr.h>
#include <ll/sys/ll/time.h>
#include <ll/sys/ll/event.h>

FILE(IntEvent);

extern int activeInt;
void (*evt_prol) (void) = NULL;
void (*evt_epil) (void) = NULL;

struct intentry irqs[16];

void irq_init(void)
{
    int i;

    /* Initialize the interrupt handlers list!!! */
    for (i = 0; i < 16; i++) {
        irqs[i].status = INTSTAT_FREE;
        irqs[i].index = i;
        irqs[i].handler = NULL; /* Paranoia */
        irqs[i].par = NULL;     /* Paranoia */
    }
    activeInt = 0;
}

int ll_ActiveInt(void)
{
    return activeInt;
}

int irq_bind(int irq, void (*handler) (void *p), DWORD flags)
{

    if ((irqs[irq].status != INTSTAT_FREE) &&
        ((flags & INT_FORCE) != INT_FORCE)) {
        return -1;
    }

    irqs[irq].status = INTSTAT_ASSIGNED;

    if (handler != NULL) {
        irqs[irq].handler = handler;
        irqs[irq].par = &(irqs[irq].index);
        irqs[irq].flags = flags;
    } else {
        irqs[irq].status = INTSTAT_FREE;
    }

    return 1;
}

void act_int(BYTE n)
{
    static int ai_called = 0;

    if ((n >= PIC1_BASE) && (n < PIC1_BASE + 8)) {
      n = n - PIC1_BASE;
    } else if ((n >= PIC2_BASE) && (n < PIC2_BASE + 8)) {
      n = n - PIC2_BASE + 8;
    } else {
      /* Wow... Here, we are in error... Return? */
      return;
    }

    activeInt++;
    if (activeInt == 1 && evt_prol != NULL) {
        evt_prol();
    }
    if (irqs[n].status == INTSTAT_ASSIGNED) {
        irqs[n].status = INTSTAT_BUSY;
        if (irqs[n].flags & INT_PREEMPTABLE) {
            sti();
        }
        irqs[n].handler(irqs[n].par);
        if (irqs[n].flags & INT_PREEMPTABLE) {
            cli();
        }
        irqs[n].status = INTSTAT_ASSIGNED;
    }
    ai_called++;
    if (activeInt == 1 && evt_epil != NULL) {
        evt_epil();
    }
    activeInt--;
}