irq.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:8k
- /*
- * Platform dependent support for SGI SN1
- *
- * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Further, this software is distributed without any warranty that it is
- * free of the rightful claim of any third person regarding infringement
- * or the like. Any license provided herein, whether implied or
- * otherwise, applies only to this software file. Patent licenses, if
- * any, provided herein do not apply to combinations of this program with
- * other software, or any other product whatsoever.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
- * Mountain View, CA 94043, or:
- *
- * http://www.sgi.com
- *
- * For further information regarding this notice, see:
- *
- * http://oss.sgi.com/projects/GenInfo/NoticeExplan
- */
- #include <linux/config.h>
- #include <linux/init.h>
- #include <linux/sched.h>
- #include <asm/current.h>
- #include <linux/irq.h>
- #include <linux/interrupt.h>
- #include <asm/page.h>
- #include <asm/pgtable.h>
- #include <asm/sn/sgi.h>
- #include <asm/sn/iograph.h>
- #include <asm/sn/invent.h>
- #include <linux/devfs_fs_kernel.h>
- #include <asm/sn/hcl.h>
- #include <asm/sn/types.h>
- #include <asm/sn/pci/bridge.h>
- #include <asm/sn/pci/pciio.h>
- #include <asm/sn/pci/pciio_private.h>
- #ifdef ajmtestintr
- #include <asm/sn/pci/pcibr.h>
- #include <asm/sn/pci/pcibr_private.h>
- #endif /* ajmtestintr */
- #include <asm/sn/sn_cpuid.h>
- #include <asm/sn/io.h>
- #include <asm/sn/intr.h>
- #include <asm/sn/addrs.h>
- #include <asm/sn/driver.h>
- #include <asm/sn/arch.h>
- int irq_to_bit_pos(int irq);
- static unsigned int
- sn_startup_irq(unsigned int irq)
- {
- return(0);
- }
- static void
- sn_shutdown_irq(unsigned int irq)
- {
- }
- static void
- sn_disable_irq(unsigned int irq)
- {
- }
- static void
- sn_enable_irq(unsigned int irq)
- {
- }
- static void
- sn_ack_irq(unsigned int irq)
- {
- #ifdef CONFIG_IA64_SGI_SN1
- int bit = -1;
- unsigned long long intpend_val;
- int subnode;
- #endif
- #ifdef CONFIG_IA64_SGI_SN2
- unsigned long event_occurred, mask = 0;
- #endif
- int nasid;
- irq = irq & 0xff;
- nasid = smp_physical_node_id();
- #ifdef CONFIG_IA64_SGI_SN1
- subnode = cpuid_to_subnode(smp_processor_id());
- if (irq == SGI_UART_IRQ) {
- intpend_val = REMOTE_HUB_PI_L(nasid, subnode, PI_INT_PEND0);
- if (intpend_val & (1L<<GFX_INTR_A) ) {
- bit = GFX_INTR_A;
- REMOTE_HUB_PI_CLR_INTR(nasid, subnode, bit);
- }
- if ( intpend_val & (1L<<GFX_INTR_B) ) {
- bit = GFX_INTR_B;
- REMOTE_HUB_PI_CLR_INTR(nasid, subnode, bit);
- }
- if (intpend_val & (1L<<PG_MIG_INTR) ) {
- bit = PG_MIG_INTR;
- REMOTE_HUB_PI_CLR_INTR(nasid, subnode, bit);
- }
- if (intpend_val & (1L<<CC_PEND_A)) {
- bit = CC_PEND_A;
- REMOTE_HUB_PI_CLR_INTR(nasid, subnode, bit);
- }
- if (intpend_val & (1L<<CC_PEND_B)) {
- bit = CC_PEND_B;
- REMOTE_HUB_PI_CLR_INTR(nasid, subnode, bit);
- }
- return;
- }
- bit = irq_to_bit_pos(irq);
- REMOTE_HUB_PI_CLR_INTR(nasid, subnode, bit);
- #endif
- #ifdef CONFIG_IA64_SGI_SN2
- event_occurred = HUB_L( (unsigned long *)GLOBAL_MMR_ADDR(nasid,SH_EVENT_OCCURRED) );
- if (event_occurred & SH_EVENT_OCCURRED_UART_INT_MASK) {
- mask |= (1 << SH_EVENT_OCCURRED_UART_INT_SHFT);
- }
- if (event_occurred & SH_EVENT_OCCURRED_IPI_INT_MASK) {
- mask |= (1 << SH_EVENT_OCCURRED_IPI_INT_SHFT);
- }
- if (event_occurred & SH_EVENT_OCCURRED_II_INT0_MASK) {
- mask |= (1 << SH_EVENT_OCCURRED_II_INT0_SHFT);
- }
- if (event_occurred & SH_EVENT_OCCURRED_II_INT1_MASK) {
- mask |= (1 << SH_EVENT_OCCURRED_II_INT1_SHFT);
- }
- HUB_S((unsigned long *)GLOBAL_MMR_ADDR(nasid, SH_EVENT_OCCURRED_ALIAS), mask );
- #endif
- }
- static void
- sn_end_irq(unsigned int irq)
- {
- #ifdef CONFIG_IA64_SGI_SN1
- unsigned long long intpend_val, mask = 0x70L;
- int subnode;
- #endif
- int nasid;
- #ifdef CONFIG_IA64_SGI_SN2
- unsigned long event_occurred;
- #endif
- irq = irq & 0xff;
- #ifdef CONFIG_IA64_SGI_SN1
- if (irq == SGI_UART_IRQ) {
- nasid = smp_physical_node_id();
- subnode = cpuid_to_subnode(smp_processor_id());
- intpend_val = REMOTE_HUB_PI_L(nasid, subnode, PI_INT_PEND0);
- if (intpend_val & mask) {
- platform_send_ipi(smp_processor_id(), SGI_UART_IRQ, IA64_IPI_DM_INT, 0);
- }
- }
- #endif
- #ifdef CONFIG_IA64_SGI_SN2
- if (irq == SGI_UART_VECTOR) {
- nasid = smp_physical_node_id();
- event_occurred = HUB_L( (unsigned long *)GLOBAL_MMR_ADDR(nasid,SH_EVENT_OCCURRED) );
- // If the UART bit is set here, we may have received an interrupt from the
- // UART that the driver missed. To make sure, we IPI ourselves to force us
- // to look again.
- if (event_occurred & SH_EVENT_OCCURRED_UART_INT_MASK) {
- platform_send_ipi(smp_processor_id(), SGI_UART_VECTOR, IA64_IPI_DM_INT, 0);
- }
- }
- #endif
- }
- static void
- sn_set_affinity_irq(unsigned int irq, unsigned long mask)
- {
- }
- struct hw_interrupt_type irq_type_iosapic_level = {
- "SN hub",
- sn_startup_irq,
- sn_shutdown_irq,
- sn_enable_irq,
- sn_disable_irq,
- sn_ack_irq,
- sn_end_irq,
- sn_set_affinity_irq
- };
- #define irq_type_sn irq_type_iosapic_level
- struct irq_desc *_sn_irq_desc[NR_CPUS];
- struct irq_desc *
- sn_irq_desc(unsigned int irq) {
- int cpu = irq >> 8;
- irq = irq & 0xff;
- return(_sn_irq_desc[cpu] + irq);
- }
- u8
- sn_irq_to_vector(u8 irq) {
- return(irq & 0xff);
- }
- unsigned int
- sn_local_vector_to_irq(u8 vector) {
- return (CPU_VECTOR_TO_IRQ(smp_processor_id(), vector));
- }
- int
- sn_valid_irq(u8 irq) {
- return( ((irq & 0xff) < NR_IRQS) && ((irq >> 8) < NR_CPUS) );
- }
- void *kmalloc(size_t, int);
- void
- sn_irq_init (void)
- {
- int i;
- irq_desc_t *base_desc = _irq_desc;
- for (i=IA64_FIRST_DEVICE_VECTOR; i<NR_IRQS; i++) {
- if (base_desc[i].handler == &no_irq_type) {
- base_desc[i].handler = &irq_type_sn;
- }
- }
- }
- void
- sn_init_irq_desc(void) {
- int i;
- irq_desc_t *base_desc = _irq_desc, *p;
- for (i=0; i < NR_CPUS; i++) {
- p = page_address(alloc_pages_node(local_cnodeid(), GFP_KERNEL,
- get_order(sizeof(struct irq_desc) * NR_IRQS) ) );
- ASSERT(p);
- memcpy(p, base_desc, sizeof(struct irq_desc) * NR_IRQS);
- _sn_irq_desc[i] = p;
- }
- }
- #if !defined(CONFIG_IA64_SGI_SN)
- void
- sn_pci_fixup(void)
- {
- }
- #endif
- int
- bit_pos_to_irq(int bit) {
- #define BIT_TO_IRQ 64
- if (bit > 118) bit = 118;
- #ifdef CONFIG_IA64_SGI_SN1
- if (bit >= GFX_INTR_A && bit <= CC_PEND_B) {
- return SGI_UART_IRQ;
- }
- #endif
- return bit + BIT_TO_IRQ;
- }
- int
- irq_to_bit_pos(int irq) {
- #define IRQ_TO_BIT 64
- int bit = irq - IRQ_TO_BIT;
- return bit;
- }
- #ifdef ajmtestintr
- #include <linux/timer.h>
- struct timer_list intr_test_timer;
- int intr_test_icount[NR_IRQS];
- struct intr_test_reg_struct {
- pcibr_soft_t pcibr_soft;
- int slot;
- };
- struct intr_test_reg_struct intr_test_registered[NR_IRQS];
- void
- intr_test_handle_timer(unsigned long data) {
- int i;
- bridge_t *bridge;
- for (i=0;i<NR_IRQS;i++) {
- if (intr_test_registered[i].pcibr_soft) {
- pcibr_soft_t pcibr_soft = intr_test_registered[i].pcibr_soft;
- xtalk_intr_t intr = pcibr_soft->bs_intr[intr_test_registered[i].slot].bsi_xtalk_intr;
- /* send interrupt */
- bridge = pcibr_soft->bs_base;
- bridge->b_force_always[intr_test_registered[i].slot].intr = 1;
- }
- }
- del_timer(&intr_test_timer);
- intr_test_timer.expires = jiffies + HZ/100;
- add_timer(&intr_test_timer);
- }
- void
- intr_test_set_timer(void) {
- intr_test_timer.expires = jiffies + HZ/100;
- intr_test_timer.function = intr_test_handle_timer;
- add_timer(&intr_test_timer);
- }
- void
- intr_test_register_irq(int irq, pcibr_soft_t pcibr_soft, int slot) {
- irq = irq & 0xff;
- intr_test_registered[irq].pcibr_soft = pcibr_soft;
- intr_test_registered[irq].slot = slot;
- }
- void
- intr_test_handle_intr(int irq, void *junk, struct pt_regs *morejunk) {
- intr_test_icount[irq]++;
- printk("RECEIVED %d INTERRUPTS ON IRQ %dn",intr_test_icount[irq], irq);
- }
- #endif /* ajmtestintr */