irq.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:8k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * Platform dependent support for SGI SN1
  3.  *
  4.  * Copyright (c) 2000-2002 Silicon Graphics, Inc.  All Rights Reserved.
  5.  * 
  6.  * This program is free software; you can redistribute it and/or modify it 
  7.  * under the terms of version 2 of the GNU General Public License 
  8.  * as published by the Free Software Foundation.
  9.  * 
  10.  * This program is distributed in the hope that it would be useful, but 
  11.  * WITHOUT ANY WARRANTY; without even the implied warranty of 
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
  13.  * 
  14.  * Further, this software is distributed without any warranty that it is 
  15.  * free of the rightful claim of any third person regarding infringement 
  16.  * or the like.  Any license provided herein, whether implied or 
  17.  * otherwise, applies only to this software file.  Patent licenses, if 
  18.  * any, provided herein do not apply to combinations of this program with 
  19.  * other software, or any other product whatsoever.
  20.  * 
  21.  * You should have received a copy of the GNU General Public 
  22.  * License along with this program; if not, write the Free Software 
  23.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
  24.  * 
  25.  * Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, 
  26.  * Mountain View, CA  94043, or:
  27.  * 
  28.  * http://www.sgi.com 
  29.  * 
  30.  * For further information regarding this notice, see: 
  31.  * 
  32.  * http://oss.sgi.com/projects/GenInfo/NoticeExplan
  33.  */
  34. #include <linux/config.h>
  35. #include <linux/init.h>
  36. #include <linux/sched.h>
  37. #include <asm/current.h>
  38. #include <linux/irq.h>
  39. #include <linux/interrupt.h>
  40. #include <asm/page.h>
  41. #include <asm/pgtable.h>
  42. #include <asm/sn/sgi.h>
  43. #include <asm/sn/iograph.h>
  44. #include <asm/sn/invent.h>
  45. #include <linux/devfs_fs_kernel.h>
  46. #include <asm/sn/hcl.h>
  47. #include <asm/sn/types.h>
  48. #include <asm/sn/pci/bridge.h>
  49. #include <asm/sn/pci/pciio.h>
  50. #include <asm/sn/pci/pciio_private.h>
  51. #ifdef ajmtestintr
  52. #include <asm/sn/pci/pcibr.h>
  53. #include <asm/sn/pci/pcibr_private.h>
  54. #endif /* ajmtestintr */
  55. #include <asm/sn/sn_cpuid.h>
  56. #include <asm/sn/io.h>
  57. #include <asm/sn/intr.h>
  58. #include <asm/sn/addrs.h>
  59. #include <asm/sn/driver.h>
  60. #include <asm/sn/arch.h>
  61. int irq_to_bit_pos(int irq);
  62. static unsigned int
  63. sn_startup_irq(unsigned int irq)
  64. {
  65.         return(0);
  66. }
  67. static void
  68. sn_shutdown_irq(unsigned int irq)
  69. {
  70. }
  71. static void
  72. sn_disable_irq(unsigned int irq)
  73. {
  74. }
  75. static void
  76. sn_enable_irq(unsigned int irq)
  77. {
  78. }
  79. static void
  80. sn_ack_irq(unsigned int irq)
  81. {
  82. #ifdef CONFIG_IA64_SGI_SN1
  83. int bit = -1;
  84. unsigned long long intpend_val;
  85. int subnode;
  86. #endif
  87. #ifdef CONFIG_IA64_SGI_SN2
  88. unsigned long event_occurred, mask = 0;
  89. #endif
  90. int nasid;
  91. irq = irq & 0xff;
  92. nasid = smp_physical_node_id();
  93. #ifdef CONFIG_IA64_SGI_SN1
  94. subnode = cpuid_to_subnode(smp_processor_id());
  95. if (irq == SGI_UART_IRQ) {
  96. intpend_val = REMOTE_HUB_PI_L(nasid, subnode, PI_INT_PEND0);
  97. if (intpend_val & (1L<<GFX_INTR_A) ) {
  98. bit = GFX_INTR_A;
  99. REMOTE_HUB_PI_CLR_INTR(nasid, subnode, bit);
  100. }
  101. if ( intpend_val & (1L<<GFX_INTR_B) ) {
  102. bit = GFX_INTR_B;
  103. REMOTE_HUB_PI_CLR_INTR(nasid, subnode, bit);
  104. }
  105. if (intpend_val & (1L<<PG_MIG_INTR) ) {
  106. bit = PG_MIG_INTR;
  107. REMOTE_HUB_PI_CLR_INTR(nasid, subnode, bit);
  108. }
  109. if (intpend_val & (1L<<CC_PEND_A)) {
  110. bit = CC_PEND_A;
  111. REMOTE_HUB_PI_CLR_INTR(nasid, subnode, bit);
  112. }
  113. if (intpend_val & (1L<<CC_PEND_B)) {
  114. bit = CC_PEND_B;
  115. REMOTE_HUB_PI_CLR_INTR(nasid, subnode, bit);
  116. }
  117. return;
  118. }
  119. bit = irq_to_bit_pos(irq);
  120. REMOTE_HUB_PI_CLR_INTR(nasid, subnode, bit);
  121. #endif
  122. #ifdef CONFIG_IA64_SGI_SN2
  123. event_occurred = HUB_L( (unsigned long *)GLOBAL_MMR_ADDR(nasid,SH_EVENT_OCCURRED) );
  124. if (event_occurred & SH_EVENT_OCCURRED_UART_INT_MASK) {
  125. mask |= (1 << SH_EVENT_OCCURRED_UART_INT_SHFT);
  126. }
  127. if (event_occurred & SH_EVENT_OCCURRED_IPI_INT_MASK) {
  128. mask |= (1 << SH_EVENT_OCCURRED_IPI_INT_SHFT);
  129. }
  130. if (event_occurred & SH_EVENT_OCCURRED_II_INT0_MASK) {
  131. mask |= (1 << SH_EVENT_OCCURRED_II_INT0_SHFT);
  132. }
  133. if (event_occurred & SH_EVENT_OCCURRED_II_INT1_MASK) {
  134. mask |= (1 << SH_EVENT_OCCURRED_II_INT1_SHFT);
  135. }
  136. HUB_S((unsigned long *)GLOBAL_MMR_ADDR(nasid, SH_EVENT_OCCURRED_ALIAS), mask );
  137. #endif
  138. }
  139. static void
  140. sn_end_irq(unsigned int irq)
  141. {
  142. #ifdef CONFIG_IA64_SGI_SN1
  143. unsigned long long intpend_val, mask = 0x70L;
  144. int subnode;
  145. #endif
  146. int nasid;
  147. #ifdef CONFIG_IA64_SGI_SN2
  148. unsigned long event_occurred;
  149. #endif
  150. irq = irq & 0xff;
  151. #ifdef CONFIG_IA64_SGI_SN1
  152. if (irq == SGI_UART_IRQ) {
  153. nasid = smp_physical_node_id();
  154. subnode = cpuid_to_subnode(smp_processor_id());
  155. intpend_val = REMOTE_HUB_PI_L(nasid, subnode, PI_INT_PEND0);
  156. if (intpend_val & mask) {
  157. platform_send_ipi(smp_processor_id(), SGI_UART_IRQ, IA64_IPI_DM_INT, 0);
  158. }
  159. }
  160. #endif
  161. #ifdef CONFIG_IA64_SGI_SN2
  162. if (irq == SGI_UART_VECTOR) {
  163. nasid = smp_physical_node_id();
  164. event_occurred = HUB_L( (unsigned long *)GLOBAL_MMR_ADDR(nasid,SH_EVENT_OCCURRED) );
  165. // If the UART bit is set here, we may have received an interrupt from the
  166. // UART that the driver missed.  To make sure, we IPI ourselves to force us
  167. // to look again.
  168. if (event_occurred & SH_EVENT_OCCURRED_UART_INT_MASK) {
  169. platform_send_ipi(smp_processor_id(), SGI_UART_VECTOR, IA64_IPI_DM_INT, 0);
  170. }
  171. }
  172. #endif
  173. }
  174. static void
  175. sn_set_affinity_irq(unsigned int irq, unsigned long mask)
  176. {
  177. }
  178. struct hw_interrupt_type irq_type_iosapic_level = {
  179. "SN hub",
  180. sn_startup_irq,
  181. sn_shutdown_irq,
  182. sn_enable_irq,
  183. sn_disable_irq,
  184. sn_ack_irq, 
  185. sn_end_irq,
  186. sn_set_affinity_irq
  187. };
  188. #define irq_type_sn irq_type_iosapic_level
  189. struct irq_desc *_sn_irq_desc[NR_CPUS];
  190. struct irq_desc *
  191. sn_irq_desc(unsigned int irq) {
  192. int cpu = irq >> 8;
  193. irq = irq & 0xff;
  194. return(_sn_irq_desc[cpu] + irq);
  195. }
  196. u8
  197. sn_irq_to_vector(u8 irq) {
  198. return(irq & 0xff);
  199. }
  200. unsigned int
  201. sn_local_vector_to_irq(u8 vector) {
  202. return (CPU_VECTOR_TO_IRQ(smp_processor_id(), vector));
  203. }
  204. int
  205. sn_valid_irq(u8 irq) {
  206. return( ((irq & 0xff) < NR_IRQS) && ((irq >> 8) < NR_CPUS) );
  207. }
  208. void *kmalloc(size_t, int);
  209. void
  210. sn_irq_init (void)
  211. {
  212. int i;
  213. irq_desc_t *base_desc = _irq_desc;
  214. for (i=IA64_FIRST_DEVICE_VECTOR; i<NR_IRQS; i++) {
  215. if (base_desc[i].handler == &no_irq_type) {
  216. base_desc[i].handler = &irq_type_sn;
  217. }
  218. }
  219. }
  220. void
  221. sn_init_irq_desc(void) {
  222. int i;
  223. irq_desc_t *base_desc = _irq_desc, *p;
  224. for (i=0; i < NR_CPUS; i++) {
  225. p =  page_address(alloc_pages_node(local_cnodeid(), GFP_KERNEL,
  226. get_order(sizeof(struct irq_desc) * NR_IRQS) ) );
  227. ASSERT(p);
  228. memcpy(p, base_desc, sizeof(struct irq_desc) * NR_IRQS);
  229. _sn_irq_desc[i] = p;
  230. }
  231. }
  232. #if !defined(CONFIG_IA64_SGI_SN)
  233. void
  234. sn_pci_fixup(void)
  235. {
  236. }
  237. #endif
  238. int
  239. bit_pos_to_irq(int bit) {
  240. #define BIT_TO_IRQ 64
  241. if (bit > 118) bit = 118;
  242. #ifdef CONFIG_IA64_SGI_SN1
  243. if (bit >= GFX_INTR_A && bit <= CC_PEND_B) {
  244. return SGI_UART_IRQ;
  245. }
  246. #endif
  247.         return bit + BIT_TO_IRQ;
  248. }
  249. int
  250. irq_to_bit_pos(int irq) {
  251. #define IRQ_TO_BIT 64
  252. int bit = irq - IRQ_TO_BIT;
  253.         return bit;
  254. }
  255. #ifdef ajmtestintr
  256. #include <linux/timer.h>
  257. struct timer_list intr_test_timer;
  258. int intr_test_icount[NR_IRQS];
  259. struct intr_test_reg_struct {
  260. pcibr_soft_t pcibr_soft;
  261. int slot;
  262. };
  263. struct intr_test_reg_struct intr_test_registered[NR_IRQS];
  264. void
  265. intr_test_handle_timer(unsigned long data) {
  266. int i;
  267. bridge_t *bridge;
  268. for (i=0;i<NR_IRQS;i++) {
  269. if (intr_test_registered[i].pcibr_soft) {
  270. pcibr_soft_t pcibr_soft = intr_test_registered[i].pcibr_soft;
  271. xtalk_intr_t intr = pcibr_soft->bs_intr[intr_test_registered[i].slot].bsi_xtalk_intr;
  272. /* send interrupt */
  273. bridge = pcibr_soft->bs_base;
  274. bridge->b_force_always[intr_test_registered[i].slot].intr = 1;
  275. }
  276. }
  277. del_timer(&intr_test_timer);
  278. intr_test_timer.expires = jiffies + HZ/100;
  279. add_timer(&intr_test_timer);
  280. }
  281. void
  282. intr_test_set_timer(void) {
  283. intr_test_timer.expires = jiffies + HZ/100;
  284. intr_test_timer.function = intr_test_handle_timer;
  285. add_timer(&intr_test_timer);
  286. }
  287. void
  288. intr_test_register_irq(int irq, pcibr_soft_t pcibr_soft, int slot) {
  289. irq = irq & 0xff;
  290. intr_test_registered[irq].pcibr_soft = pcibr_soft;
  291. intr_test_registered[irq].slot = slot;
  292. }
  293. void
  294. intr_test_handle_intr(int irq, void *junk, struct pt_regs *morejunk) {
  295. intr_test_icount[irq]++;
  296. printk("RECEIVED %d INTERRUPTS ON IRQ %dn",intr_test_icount[irq], irq);
  297. }
  298. #endif /* ajmtestintr */