Beispiel #1
0
/*
 * Jensen is special: the vector is 0x8X0 for EISA interrupt X, and
 * 0x9X0 for the local motherboard interrupts..
 *
 *	0x660 - NMI
 *
 *	0x800 - IRQ0  interval timer (not used, as we use the RTC timer)
 *	0x810 - IRQ1  line printer (duh..)
 *	0x860 - IRQ6  floppy disk
 *	0x8E0 - IRQ14 SCSI controller
 *
 *	0x900 - COM1
 *	0x920 - COM2
 *	0x980 - keyboard
 *	0x990 - mouse
 *
 * PCI-based systems are more sane: they don't have the local
 * interrupts at all, and have only normal PCI interrupts from
 * devices.  Happily it's easy enough to do a sane mapping from the
 * Jensen..  Note that this means that we may have to do a hardware
 * "ack" to a different interrupt than we report to the rest of the
 * world.
 */
static inline void srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
{
	int irq, ack;
	unsigned long flags;

	save_flags(flags);
	cli();


	ack = irq = (vector - 0x800) >> 4;

#ifdef CONFIG_ALPHA_JENSEN
	switch (vector) {
	      case 0x660: handle_nmi(regs); return;
		/* local device interrupts: */
	      case 0x900: handle_irq(4, regs); return;	/* com1 -> irq 4 */
	      case 0x920: handle_irq(3, regs); return;	/* com2 -> irq 3 */
	      case 0x980: handle_irq(1, regs); return;	/* kbd -> irq 1 */
	      case 0x990: handle_irq(9, regs); return;	/* mouse -> irq 9 */
	      default:
		if (vector > 0x900) {
			printk("Unknown local interrupt %lx\n", vector);
		}
	}
	/* irq1 is supposed to be the keyboard, silly Jensen (is this really needed??) */
	if (irq == 1)
		irq = 7;
#endif /* CONFIG_ALPHA_JENSEN */

	device_interrupt(irq, ack, regs);

	restore_flags(flags) ;
}
Beispiel #2
0
static inline void eb66_and_eb64p_device_interrupt(unsigned long vector,
						   struct pt_regs * regs)
{
	unsigned long pld;
	unsigned int i;
	unsigned long flags;

	save_flags(flags);
	cli();

	/* read the interrupt summary registers */
	pld = inb(0x26) | (inb(0x27) << 8);
	/*
	 * Now, for every possible bit set, work through
	 * them and call the appropriate interrupt handler.
	 */
	while (pld) {
		i = ffz(~pld);
		pld &= pld - 1;	/* clear least bit set */

		if (i == 5) {
			isa_device_interrupt(vector, regs);
		} else {
			device_interrupt(16 + i, 16 + i, regs);
		}
	}
	restore_flags(flags);
}
Beispiel #3
0
static inline void mikasa_device_interrupt(unsigned long vector,
					   struct pt_regs * regs)
{
	unsigned long pld;
	unsigned int i;
	unsigned long flags;

	save_flags(flags);
	cli();

        /* read the interrupt summary registers */
        pld = (((unsigned long) (~inw(0x534)) & 0x0000ffffUL) << 16) |
	       (((unsigned long) inb(0xa0))  <<  8) |
	       ((unsigned long) inb(0x20));

#if 0
        printk("[0x%08lx]", pld);
#endif

        /*
         * Now for every possible bit set, work through them and call
         * the appropriate interrupt handler.
         */
        while (pld) {
		i = ffz(~pld);
		pld &= pld - 1; /* clear least bit set */
		if (i < 16) {
			isa_device_interrupt(vector, regs);
		} else {
			device_interrupt(i, i, regs);
		}
        }
	restore_flags(flags);
}
Beispiel #4
0
static inline void cabriolet_and_eb66p_device_interrupt(unsigned long vector,
							struct pt_regs * regs)
{
	unsigned long pld;
	unsigned int i;
	unsigned long flags;

	save_flags(flags);
	cli();

	/* read the interrupt summary registers */
	pld = inb(0x804) | (inb(0x805) << 8) | (inb(0x806) << 16);

#if 0
	printk("[0x%04X/0x%04X]", pld, inb(0x20) | (inb(0xA0) << 8));
#endif

	/*
	 * Now for every possible bit set, work through them and call
	 * the appropriate interrupt handler.
	 */
	while (pld) {
		i = ffz(~pld);
		pld &= pld - 1;	/* clear least bit set */
		if (i == 4) {
			isa_device_interrupt(vector, regs);
		} else {
			device_interrupt(16 + i, 16 + i, regs);
		}
	}
	restore_flags(flags);
}
Beispiel #5
0
/* we have to conditionally compile this because of GRU_xxx symbols */
static inline void alcor_and_xlt_device_interrupt(unsigned long vector,
                                                  struct pt_regs * regs)
{
        unsigned long pld;
        unsigned int i;
        unsigned long flags;

        save_flags(flags);
        cli();

        /* read the interrupt summary register of the GRU */
        pld = (*(unsigned int *)GRU_INT_REQ) & GRU_INT_REQ_BITS;

#if 0
        printk("[0x%08lx/0x%04x]", pld, inb(0x20) | (inb(0xA0) << 8));
#endif

        /*
         * Now for every possible bit set, work through them and call
         * the appropriate interrupt handler.
         */
        while (pld) {
                i = ffz(~pld);
                pld &= pld - 1; /* clear least bit set */
                if (i == 31) {
                        isa_device_interrupt(vector, regs);
                } else {
                        device_interrupt(16 + i, 16 + i, regs);
                }
        }
        restore_flags(flags);
}
Beispiel #6
0
/*
 * Wait the given number of ticks for an interrupt. If the timeout was too
 * short such that we didn't need to receive an interrupt (because our setup
 * time exceeded the wait time), 'interrupt_received' will be 0. Otherwise,
 * it will be 1.
 */
static void
clock_pause(uint64_t ticks, int *interrupt_received)
{
    /* Wait for the timeout. */
    uint64_t time = timer_get_ticks(timer_device.ti);
    int already_passed = timer_timeout(timer_device.ti, time + ticks);
    if (already_passed) {
        /* If it happened while we were still setting up, just return. */
        *interrupt_received = 0;
        return;
    }

    /* Otherwise, wait for an interrupt. */
    while (!device_interrupt(timer_device.di, okn_syscall_interrupt_wait()));
    *interrupt_received = 1;
}
Beispiel #7
0
/* Wait for the specified time (in microseconds) */
void
clock_wait(uint64_t time)
{
    int error;
    uint64_t clock = clock_read();
    uint64_t timeout = clock + time;

    error = okn_syscall_interrupt_register(CLOCK_IRQ);
    assert(!error);
    if (timer_timeout(timer_device.ti, us_to_ticks(timer_device.frequency, timeout))) {
        error = okn_syscall_interrupt_deregister(CLOCK_IRQ);
        assert(!error);
        return; /* Already expired */
    }
    /* wait for the interrupt */
    while(!device_interrupt(timer_device.di, okn_syscall_interrupt_wait()));
    error = okn_syscall_interrupt_deregister(CLOCK_IRQ);
    assert(!error);
}
Beispiel #8
0
/* process an interrupt generated by clock_generate_interrupt 
 * returns True if it was the generated interrupt, 
 * False if it was a different interrupt 
 */
int
clock_process_interrupt(void)
{
    return device_interrupt(timer_device.di, CLOCK_IRQ);
}
Beispiel #9
0
/*
 * Handle ISA interrupt via the PICs.
 */
static inline void isa_device_interrupt(unsigned long vector,
					struct pt_regs * regs)
{
#if defined(CONFIG_ALPHA_APECS)
#	define IACK_SC	APECS_IACK_SC
#elif defined(CONFIG_ALPHA_LCA)
#	define IACK_SC	LCA_IACK_SC
#elif defined(CONFIG_ALPHA_CIA)
#	define IACK_SC	CIA_IACK_SC
#else
	/*
	 * This is bogus but necessary to get it to compile
	 * on all platforms.  If you try to use this on any
	 * other than the intended platforms, you'll notice
	 * real fast...
	 */
#	define IACK_SC	1L
#endif
	int j;

#if 1
	/*
	 * Generate a PCI interrupt acknowledge cycle.  The PIC will
	 * respond with the interrupt vector of the highest priority
	 * interrupt that is pending.  The PALcode sets up the
	 * interrupts vectors such that irq level L generates vector
	 * L.
	 */
	j = *(volatile int *) IACK_SC;
	j &= 0xff;
	if (j == 7) {
		if (!(inb(0x20) & 0x80)) {
			/* it's only a passive release... */
			return;
		}
	}
	device_interrupt(j, j, regs);
#else
	unsigned long pic;

	/*
	 * It seems to me that the probability of two or more *device*
	 * interrupts occurring at almost exactly the same time is
	 * pretty low.  So why pay the price of checking for
	 * additional interrupts here if the common case can be
	 * handled so much easier?
	 */
	/* 
	 *  The first read of gives you *all* interrupting lines.
	 *  Therefore, read the mask register and and out those lines
	 *  not enabled.  Note that some documentation has 21 and a1 
	 *  write only.  This is not true.
	 */
	pic = inb(0x20) | (inb(0xA0) << 8);	/* read isr */
	pic &= ~irq_mask;			/* apply mask */
	pic &= 0xFFFB;				/* mask out cascade & hibits */

	while (pic) {
		j = ffz(~pic);
		pic &= pic - 1;
		device_interrupt(j, j, regs);
	}
#endif
}