Ejemplo n.º 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) ;
}
Ejemplo n.º 2
0
asmlinkage void 
do_entInt(unsigned long type, unsigned long vector,
	  unsigned long la_ptr, struct pt_regs *regs)
{
	struct pt_regs *old_regs;
	switch (type) {
	case 0:
#ifdef CONFIG_SMP
		handle_ipi(regs);
		return;
#else
		irq_err_count++;
		printk(KERN_CRIT "Interprocessor interrupt? "
		       "You must be kidding!\n");
#endif
		break;
	case 1:
		old_regs = set_irq_regs(regs);
#ifdef CONFIG_SMP
	  {
		long cpu;

		local_irq_disable();
		smp_percpu_timer_interrupt(regs);
		cpu = smp_processor_id();
		if (cpu != boot_cpuid) {
		        kstat_incr_irqs_this_cpu(RTC_IRQ, irq_to_desc(RTC_IRQ));
		} else {
			handle_irq(RTC_IRQ);
		}
	  }
#else
		handle_irq(RTC_IRQ);
#endif
		set_irq_regs(old_regs);
		return;
	case 2:
		old_regs = set_irq_regs(regs);
		alpha_mv.machine_check(vector, la_ptr);
		set_irq_regs(old_regs);
		return;
	case 3:
		old_regs = set_irq_regs(regs);
		alpha_mv.device_interrupt(vector);
		set_irq_regs(old_regs);
		return;
	case 4:
		perf_irq(la_ptr, regs);
		return;
	default:
		printk(KERN_CRIT "Hardware intr %ld %lx? Huh?\n",
		       type, vector);
	}
	printk(KERN_CRIT "PC = %016lx PS=%04lx\n", regs->pc, regs->ps);
}
Ejemplo n.º 3
0
static inline void dispatch_multiple_rtc_irq() {
    rtc_reg_map *regs = RTC->regs;
    uint32 dsr = regs->CRH & regs->CRL;
    void (**hs)(void) = RTC->handlers;
    uint32 handled = 0;
	
    handle_irq(dsr, RTC_CRL_SECF, hs, RTC_SECONDS_INTERRUPT, handled);
    handle_irq(dsr, RTC_CRL_ALRF, hs, RTC_ALARM_GLOBAL_INTERRUPT, handled);
    handle_irq(dsr, RTC_CRL_OWF, hs, RTC_OVERFLOW_INTERRUPT, handled);
	
    regs->CRL &= ~handled;
}
Ejemplo n.º 4
0
static inline void dispatch_adv_cc(timer_dev *dev) {
    uint32_t dsr = dev->regs->DIER & dev->regs->SR;
    void (**hs)(void) = dev->handlers;
    uint32_t handled = 0;

    handle_irq(dsr, TIMER_SR_CC4IF, hs, TIMER_CC4_INTERRUPT, handled);
    handle_irq(dsr, TIMER_SR_CC3IF, hs, TIMER_CC3_INTERRUPT, handled);
    handle_irq(dsr, TIMER_SR_CC2IF, hs, TIMER_CC2_INTERRUPT, handled);
    handle_irq(dsr, TIMER_SR_CC1IF, hs, TIMER_CC1_INTERRUPT, handled);

    dev->regs->SR &= ~handled;
}
Ejemplo n.º 5
0
static inline void dispatch_adv_trg_com(timer_dev *dev) {
    uint32_t dsr = dev->regs->DIER & dev->regs->SR;
    void (**hs)(void) = dev->handlers;
    uint32_t handled = 0; /* Logical OR of SR interrupt flags we end up
                         * handling.  We clear these.  User handlers
                         * must clear overcapture flags, to avoid
                         * wasting time in output mode. */

    handle_irq(dsr, TIMER_SR_TIF,   hs, TIMER_TRG_INTERRUPT, handled);
    handle_irq(dsr, TIMER_SR_COMIF, hs, TIMER_COM_INTERRUPT, handled);

    dev->regs->SR &= ~handled;
}
static void
mikasa_device_interrupt(unsigned long vector)
{
	unsigned long pld;
	unsigned int i;

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

	/*
	 * 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);
		} else {
			handle_irq(i);
		}
	}
}
Ejemplo n.º 7
0
/*
 * do_IRQ handles all normal device IRQ's (the special
 * SMP cross-CPU interrupts have their own specific
 * handlers).
 */
__visible unsigned int __irq_entry do_IRQ(struct pt_regs *regs)
{
	struct pt_regs *old_regs = set_irq_regs(regs);

	/* high bit used in ret_from_ code  */
	unsigned vector = ~regs->orig_ax;
	unsigned irq;

	irq_enter();
	exit_idle();

	irq = __this_cpu_read(vector_irq[vector]);

	if (!handle_irq(irq, regs)) {
		ack_APIC_irq();

		if (irq != VECTOR_RETRIGGERED) {
			pr_emerg_ratelimited("%s: %d.%d No irq handler for vector (irq %d)\n",
					     __func__, smp_processor_id(),
					     vector, irq);
		} else {
			__this_cpu_write(vector_irq[vector], VECTOR_UNDEFINED);
		}
	}

	irq_exit();

	set_irq_regs(old_regs);
	return 1;
}
Ejemplo n.º 8
0
/*
 * do_IRQ handles all normal device IRQ's (the special
 * SMP cross-CPU interrupts have their own specific
 * handlers).
 */
unsigned int __irq_entry do_IRQ(struct pt_regs *regs)
{
	struct pt_regs *old_regs = set_irq_regs(regs);

	/* high bit used in ret_from_ code  */
	unsigned vector = ~regs->orig_ax;
	unsigned irq;

	irq_enter();
	exit_idle();

	irq = __this_cpu_read(vector_irq[vector]);

	if (!handle_irq(irq, regs)) {
		ack_APIC_irq();

		if (printk_ratelimit())
			pr_emerg("%s: %d.%d No irq handler for vector (irq %d)\n",
				__func__, smp_processor_id(), vector, irq);
	}

	irq_exit();

	set_irq_regs(old_regs);
	return 1;
}
Ejemplo n.º 9
0
static void 
miata_srm_device_interrupt(unsigned long vector)
{
	int irq;

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

	/*
	 * I really hate to do this, but the MIATA SRM console ignores the
	 *  low 8 bits in the interrupt summary register, and reports the
	 *  vector 0x80 *lower* than I expected from the bit numbering in
	 *  the documentation.
	 * This was done because the low 8 summary bits really aren't used
	 *  for reporting any interrupts (the PCI-ISA bridge, bit 7, isn't
	 *  used for this purpose, as PIC interrupts are delivered as the
	 *  vectors 0x800-0x8f0).
	 * But I really don't want to change the fixup code for allocation
	 *  of IRQs, nor the alpha_irq_mask maintenance stuff, both of which
	 *  look nice and clean now.
	 * So, here's this grotty hack... :-(
	 */
	if (irq >= 16)
		irq = irq + 8;

	handle_irq(irq);
}
Ejemplo n.º 10
0
static void 
jensen_device_interrupt(unsigned long vector, struct pt_regs * regs)
{
	int irq;

	switch (vector) {
	case 0x660:
		printk("Whee.. NMI received. Probable hardware error\n");
		printk("61=%02x, 461=%02x\n", inb(0x61), inb(0x461));
		return;

	/* local device interrupts: */
	case 0x900: irq = 4; break;		/* com1 -> irq 4 */
	case 0x920: irq = 3; break;		/* com2 -> irq 3 */
	case 0x980: irq = 1; break;		/* kbd -> irq 1 */
	case 0x990: irq = 9; break;		/* mouse -> irq 9 */

	default:
		if (vector > 0x900) {
			printk("Unknown local interrupt %lx\n", vector);
			return;
		}

		irq = (vector - 0x800) >> 4;
		if (irq == 1)
			irq = 7;
		break;
	}

	handle_irq(irq, regs);
}
Ejemplo n.º 11
0
/* Check if the pending bit for an IRQ line is set; if so, call the handler
 * function.  */
static void check_irq_pending(uchar irq_num)
{
    bool handle = FALSE;

    /* Check the appropriate hardware register, depending on the IRQ number.  */
    if (irq_num >= 64)
    {
        if (regs->IRQ_basic_pending & (1 << (irq_num - 64)))
        {
            handle = TRUE;
        }
    }
    else if (irq_num >= 32)
    {
        if (regs->IRQ_pending_2 & (1 << (irq_num - 32)))
        {
            handle = TRUE;
        }
    }
    else
    {
        if (regs->IRQ_pending_1 & (1 << irq_num))
        {
            handle = TRUE;
        }
    }
    if (handle)
    {
        handle_irq(irq_num);
        /* The pending bit should have been cleared in a device-specific way by
         * the handler function.  As far as we can tell, it cannot be cleared
         * directly through the interrupt controller.  */
    }
}
Ejemplo n.º 12
0
static void 
rx164_device_interrupt(unsigned long vector)
{
	unsigned long pld;
	volatile unsigned int *dirr;
	long i;

	/* Read the interrupt summary register.  On Polaris, this is
	   the DIRR register in PCI config space (offset 0x84).  */
	dirr = (void *)(POLARIS_DENSE_CONFIG_BASE + 0x84);
	pld = *dirr;

	/*
	 * 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 == 20) {
			isa_no_iack_sc_device_interrupt(vector);
		} else {
			handle_irq(16+i);
		}
	}
}
Ejemplo n.º 13
0
static void
dp264_device_interrupt(unsigned long vector, struct pt_regs * regs)
{
#if 1
	printk("dp264_device_interrupt: NOT IMPLEMENTED YET!! \n");
#else
	unsigned long pld;
	unsigned int i;

	/* Read the interrupt summary register of TSUNAMI */
	pld = TSUNAMI_cchip->dir0.csr;

	/*
	 * 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 == 55)
			isa_device_interrupt(vector, regs);
		else
			handle_irq(16 + i, 16 + i, regs);
#if 0
		TSUNAMI_cchip->dir0.csr = 1UL << i; mb();
		tmp = TSUNAMI_cchip->dir0.csr;
#endif
	}
#endif
}
static void 
miata_srm_device_interrupt(unsigned long vector)
{
	int irq;

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

	/*
                                                                   
                                                                  
                                                                  
                       
                                                                   
                                                                   
                                                                  
                          
                                                                   
                                                                     
                             
                                      
  */
	if (irq >= 16)
		irq = irq + 8;

	handle_irq(irq);
}
static void 
rawhide_srm_device_interrupt(unsigned long vector)
{
	int irq;

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

        /*
         * The RAWHIDE SRM console reports PCI interrupts with a vector
	 * 0x80 *higher* than one might expect, as PCI IRQ 0 (ie bit 0)
	 * shows up as IRQ 24, etc, etc. We adjust it down by 8 to have
	 * it line up with the actual bit numbers from the REQ registers,
	 * which is how we manage the interrupts/mask. Sigh...
	 *
	 * Also, PCI #1 interrupts are offset some more... :-(
         */

	if (irq == 52) {
		/* SCSI on PCI1 is special.  */
		irq = 72;
	}

	/* Adjust by which hose it is from.  */
	irq -= ((irq + 16) >> 2) & 0x38;

	handle_irq(irq);
}
Ejemplo n.º 16
0
/*
 * do_IRQ handles all normal device IRQ's (the special
 * SMP cross-CPU interrupts have their own specific
 * handlers).
 */
unsigned int __irq_entry do_IRQ(struct pt_regs *regs)
{
   // 取得原来的寄存器
	struct pt_regs *old_regs = set_irq_regs(regs);

   // 取得中断向量号
	/* high bit used in ret_from_ code  */
	unsigned vector = ~regs->orig_ax;
	unsigned irq;

   // 退出idle进程
	exit_idle();
   // 进入中断。使表示中断处理程序嵌套数量的计数器递增。
   // 计数器是指当前进程thread_info结构的preempt_count字段
	irq_enter();

   // 中断线号与设备的中断号之间对应关系,有系统分配
   // 分配表是一个per-cpu变量的vector_irq
	irq = __get_cpu_var(vector_irq)[vector];

	if (!handle_irq(irq, regs)) {
		ack_APIC_irq();

		if (printk_ratelimit())
			pr_emerg("%s: %d.%d No irq handler for vector (irq %d)\n",
				__func__, smp_processor_id(), vector, irq);
	}

   // 结束中断
	irq_exit();

	set_irq_regs(old_regs);
	return 1;
}
Ejemplo n.º 17
0
static void 
titan_srm_device_interrupt(unsigned long vector)
{
	int irq;

	irq = (vector - 0x800) >> 4;
	handle_irq(irq);
}
Ejemplo n.º 18
0
void irq_entry(regs *r)
{
   ASSERT(!are_interrupts_enabled());
   DEBUG_VALIDATE_STACK_PTR();
   ASSERT(get_curr_task() != NULL);
   DEBUG_check_not_same_interrupt_nested(regs_intnum(r));

   handle_irq(r);
}
Ejemplo n.º 19
0
static void 
wildfire_device_interrupt(unsigned long vector, struct pt_regs * regs)
{
	int irq;

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

	/*
	 * bits 10-8:	source QBB ID
	 * bits 7-6:	PCA
	 * bits 5-0:	irq in PCA
	 */

	handle_irq(irq, regs);
	return;
}
Ejemplo n.º 20
0
asmregparm unsigned int do_IRQ(struct pt_regs *regs)
{
	/* high bit used in ret_from_ code  */
	unsigned vector = ~regs->orig_ax;
	unsigned irq;

	irq_enter();
	irq = vector_irq[vector];
 	if (!handle_irq(irq, regs)) {
 		ack_APIC_irq();
 	}
 	irq_exit();
	
	/* Give scheduler a chance to run */
	if (irq == 0) kt_sched_tick();
 	return 1;
}
Ejemplo n.º 21
0
/*
 * do_IRQ handles all normal device IRQ's (the special
 * SMP cross-CPU interrupts have their own specific
 * handlers).
 */
__visible unsigned int __irq_entry do_IRQ(struct pt_regs *regs)
{
	struct pt_regs *old_regs = set_irq_regs(regs);
	struct irq_desc * desc;
	/* high bit used in ret_from_ code  */
	unsigned vector = ~regs->orig_ax;

	/*
	 * NB: Unlike exception entries, IRQ entries do not reliably
	 * handle context tracking in the low-level entry code.  This is
	 * because syscall entries execute briefly with IRQs on before
	 * updating context tracking state, so we can take an IRQ from
	 * kernel mode with CONTEXT_USER.  The low-level entry code only
	 * updates the context if we came from user mode, so we won't
	 * switch to CONTEXT_KERNEL.  We'll fix that once the syscall
	 * code is cleaned up enough that we can cleanly defer enabling
	 * IRQs.
	 */

	entering_irq();

	/* entering_irq() tells RCU that we're not quiescent.  Check it. */
	RCU_LOCKDEP_WARN(!rcu_is_watching(), "IRQ failed to wake up RCU");

	desc = __this_cpu_read(vector_irq[vector]);

	if (!handle_irq(desc, regs)) {
		ack_APIC_irq();

		if (desc != VECTOR_RETRIGGERED) {
			pr_emerg_ratelimited("%s: %d.%d No irq handler for vector\n",
					     __func__, smp_processor_id(),
					     vector);
		} else {
			__this_cpu_write(vector_irq[vector], VECTOR_UNUSED);
		}
	}

	exiting_irq();

	set_irq_regs(old_regs);
	return 1;
}
Ejemplo n.º 22
0
void irq_handler (unsigned int port_number)
{
  system_call_thread_name_set ("IRQ handler");

  if (system_call_irq_register (serial_port[port_number].irq, "Serial (UART)")
      != STORM_RETURN_SUCCESS)
  {
    log_print_formatted (&log_structure, LOG_URGENCY_EMERGENCY,
               "Could not allocate IRQ %d.", serial_port[port_number].irq);
    return;
  }

  while (TRUE)
  {
    system_call_irq_wait (serial_port[port_number].irq);
    handle_irq (port_number);
    system_call_irq_acknowledge (serial_port[port_number].irq);
  }
}
Ejemplo n.º 23
0
/*
 * do_IRQ handles all normal device IRQ's (the special
 * SMP cross-CPU interrupts have their own specific
 * handlers).
 */
__visible unsigned int __irq_entry do_IRQ(struct pt_regs *regs)
{
	/* 将栈顶地址保存到全局变量__irq_regs中,old_regs用于保存现在的__irq_regs值 */
	struct pt_regs *old_regs = set_irq_regs(regs);

	/* 获取中断向量号,因为中断向量号是以取反方式保存的,这里再次取反 */
	unsigned vector = ~regs->orig_ax;
	/* 中断向量号 */
	unsigned irq;

	/* 硬中断计数器增加,硬中断计数器保存在preempt_count */
	irq_enter();
	/* 这里开始禁止调度,因为preempt_count不为0 */

	/* 退出idle进程(如果当前进程是idle进程的情况下) */
	exit_idle();

	/* 根据中断向量号获取中断号 */
	irq = __this_cpu_read(vector_irq[vector]);

	/* 主要函数是handle_irq,进行中断服务例程的处理 */
	if (!handle_irq(irq, regs)) {
		/* EIO模式的应答 */
		ack_APIC_irq();

		/* 该中断号并没有发生过多次触发 */
		if (irq != VECTOR_RETRIGGERED) {
			pr_emerg_ratelimited("%s: %d.%d No irq handler for vector (irq %d)\n",
					     __func__, smp_processor_id(),
					     vector, irq);
		} else {
			/* 将此中断向量号对应的vector_irq设置为未定义 */
			__this_cpu_write(vector_irq[vector], VECTOR_UNDEFINED);
		}
	}
	/* 硬中断计数器减少,并检查是否有软中断需要执行,如果有,会设置CPU在开中断的状态下执行软中断处理 */
	irq_exit();
	/* 这里开始允许调度 */

	/* 恢复原来的__irq_regs值 */
	set_irq_regs(old_regs);
	return 1;
}
Ejemplo n.º 24
0
static void 
clipper_srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
{
	int irq;

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

/*
	 * The SRM console reports PCI interrupts with a vector calculated by:
	 *
	 *	0x900 + (0x10 * DRIR-bit)
	 *
	 * So bit 16 shows up as IRQ 32, etc.
	 * 
	 * CLIPPER uses bits 8-47 for PCI interrupts, so we do not need
	 * to scale down the vector reported, we just use it.
	 *
	 * Eg IRQ 24 is DRIR bit 8, etc, etc
	 */
	handle_irq(irq, regs);
}
Ejemplo n.º 25
0
static void
dp264_device_interrupt(unsigned long vector)
{
	unsigned long pld;
	unsigned int i;

	/* Read the interrupt summary register of TSUNAMI */
	pld = TSUNAMI_cchip->dir0.csr;

	/*
	 * 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 == 55)
			isa_device_interrupt(vector);
		else
			handle_irq(16 + i);
	}
}
Ejemplo n.º 26
0
static void
alcor_device_interrupt(unsigned long vector)
{
	unsigned long pld;
	unsigned int i;

	/* Read the interrupt summary register of the GRU */
	pld = (*(vuip)GRU_INT_REQ) & GRU_INT_REQ_BITS;

	/*
	 * 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);
		} else {
			handle_irq(16 + i);
		}
	}
}
static void
alcor_device_interrupt(unsigned long vector)
{
	unsigned long pld;
	unsigned int i;

	/*                                                */
	pld = (*(vuip)GRU_INT_REQ) & GRU_INT_REQ_BITS;

	/*
                                                              
                                      
  */
	while (pld) {
		i = ffz(~pld);
		pld &= pld - 1; /*                     */
		if (i == 31) {
			isa_device_interrupt(vector);
		} else {
			handle_irq(16 + i);
		}
	}
}
static void 
cabriolet_device_interrupt(unsigned long v)
{
	unsigned long pld;
	unsigned int i;

	/*                                      */
	pld = inb(0x804) | (inb(0x805) << 8) | (inb(0x806) << 16);

	/*
                                                              
                                      
  */
	while (pld) {
		i = ffz(~pld);
		pld &= pld - 1;	/*                     */
		if (i == 4) {
			isa_device_interrupt(v);
		} else {
			handle_irq(16 + i);
		}
	}
}
static void 
cabriolet_device_interrupt(unsigned long v, struct pt_regs *r)
{
	unsigned long pld;
	unsigned int i;

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

	/*
	 * 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(v, r);
		} else {
			handle_irq(16 + i, r);
		}
	}
}
Ejemplo n.º 30
0
static void 
dp264_srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
{
	int irq;

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

	/*
	 * The SRM console reports PCI interrupts with a vector calculated by:
	 *
	 *	0x900 + (0x10 * DRIR-bit)
	 *
	 * So bit 16 shows up as IRQ 32, etc.
	 * 
	 * On DP264/BRICK/MONET, we adjust it down by 16 because at least
	 * that many of the low order bits of the DRIR are not used, and
	 * so we don't count them.
	 */
	if (irq >= 32)
		irq -= 16;

	handle_irq(irq, regs);
}