indy_int.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:12k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * indy_int.c: Routines for generic manipulation of the INT[23] ASIC
  3.  *             found on INDY workstations..
  4.  *
  5.  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
  6.  * Copyright (C) 1997, 1998 Ralf Baechle (ralf@gnu.org)
  7.  * Copyright (C) 1999 Andrew R. Baker (andrewb@uab.edu) 
  8.  *                    - Indigo2 changes
  9.  *                    - Interrupt handling fixes
  10.  */
  11. #include <linux/init.h>
  12. #include <linux/errno.h>
  13. #include <linux/kernel_stat.h>
  14. #include <linux/signal.h>
  15. #include <linux/sched.h>
  16. #include <linux/types.h>
  17. #include <linux/interrupt.h>
  18. #include <linux/ioport.h>
  19. #include <linux/timex.h>
  20. #include <linux/slab.h>
  21. #include <linux/random.h>
  22. #include <linux/smp.h>
  23. #include <linux/smp_lock.h>
  24. #include <asm/bitops.h>
  25. #include <asm/bootinfo.h>
  26. #include <asm/io.h>
  27. #include <asm/irq.h>
  28. #include <asm/mipsregs.h>
  29. #include <asm/system.h>
  30. #include <asm/ptrace.h>
  31. #include <asm/processor.h>
  32. #include <asm/sgi/sgi.h>
  33. #include <asm/sgi/sgihpc.h>
  34. #include <asm/sgi/sgint23.h>
  35. #include <asm/sgialib.h>
  36. #include <asm/gdb-stub.h>
  37. /*
  38.  * Linux has a controller-independent x86 interrupt architecture.
  39.  * every controller has a 'controller-template', that is used
  40.  * by the main code to do the right thing. Each driver-visible
  41.  * interrupt source is transparently wired to the apropriate
  42.  * controller. Thus drivers need not be aware of the
  43.  * interrupt-controller.
  44.  *
  45.  * Various interrupt controllers we handle: 8259 PIC, SMP IO-APIC,
  46.  * PIIX4's internal 8259 PIC and SGI's Visual Workstation Cobalt (IO-)APIC.
  47.  * (IO-APICs assumed to be messaging to Pentium local-APICs)
  48.  *
  49.  * the code is designed to be easily extended with new/different
  50.  * interrupt controllers, without having to do assembly magic.
  51.  */
  52. /* #define DEBUG_SGINT */
  53. struct sgi_int2_regs *sgi_i2regs;
  54. struct sgi_int3_regs *sgi_i3regs;
  55. struct sgi_ioc_ints *ioc_icontrol;
  56. struct sgi_ioc_timers *ioc_timers;
  57. volatile unsigned char *ioc_tclear;
  58. static char lc0msk_to_irqnr[256];
  59. static char lc1msk_to_irqnr[256];
  60. static char lc2msk_to_irqnr[256];
  61. static char lc3msk_to_irqnr[256];
  62. extern asmlinkage void indyIRQ(void);
  63. /* Local IRQ's are layed out logically like this:
  64.  *
  65.  * 0  --> 7   ==   local 0 interrupts
  66.  * 8  --> 15  ==   local 1 interrupts
  67.  * 16 --> 23  ==   vectored level 2 interrupts
  68.  * 24 --> 31  ==   vectored level 3 interrupts (not used)
  69.  */
  70. static void enable_local0_irq(unsigned int irq)
  71. {
  72. unsigned long flags;
  73. save_and_cli(flags);
  74. ioc_icontrol->imask0 |= (1 << (irq - SGINT_LOCAL0));
  75. restore_flags(flags);
  76. }
  77. static unsigned int startup_local0_irq(unsigned int irq)
  78. {
  79. enable_local0_irq(irq);
  80. return 0; /* Never anything pending  */
  81. }
  82. static void disable_local0_irq(unsigned int irq)
  83. {
  84. unsigned long flags;
  85. save_and_cli(flags);
  86. ioc_icontrol->imask0 &= ~(1 << (irq - SGINT_LOCAL0));
  87. restore_flags(flags);
  88. }
  89. #define shutdown_local0_irq disable_local0_irq
  90. #define mask_and_ack_local0_irq disable_local0_irq
  91. static void end_local0_irq (unsigned int irq)
  92. {
  93. if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
  94. enable_local0_irq(irq);
  95. }
  96. static struct hw_interrupt_type ip22_local0_irq_type = {
  97. "IP22 local 0",
  98. startup_local0_irq,
  99. shutdown_local0_irq,
  100. enable_local0_irq,
  101. disable_local0_irq,
  102. mask_and_ack_local0_irq,
  103. end_local0_irq,
  104. NULL
  105. };
  106. static void enable_local1_irq(unsigned int irq)
  107. {
  108. unsigned long flags;
  109. save_and_cli(flags);
  110. ioc_icontrol->imask1 |= (1 << (irq - SGINT_LOCAL1));
  111. restore_flags(flags);
  112. }
  113. static unsigned int startup_local1_irq(unsigned int irq)
  114. {
  115. enable_local1_irq(irq);
  116. return 0; /* Never anything pending  */
  117. }
  118. void disable_local1_irq(unsigned int irq)
  119. {
  120. unsigned long flags;
  121. save_and_cli(flags);
  122. ioc_icontrol->imask1 &= ~(1 << (irq- SGINT_LOCAL1));
  123. restore_flags(flags);
  124. }
  125. #define shutdown_local1_irq disable_local1_irq
  126. #define mask_and_ack_local1_irq disable_local1_irq
  127. static void end_local1_irq (unsigned int irq)
  128. {
  129. if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
  130. enable_local1_irq(irq);
  131. }
  132. static struct hw_interrupt_type ip22_local1_irq_type = {
  133. "IP22 local 1",
  134. startup_local1_irq,
  135. shutdown_local1_irq,
  136. enable_local1_irq,
  137. disable_local1_irq,
  138. mask_and_ack_local1_irq,
  139. end_local1_irq,
  140. NULL
  141. };
  142. static void enable_local2_irq(unsigned int irq)
  143. {
  144. unsigned long flags;
  145. save_and_cli(flags);
  146. enable_local0_irq(7);
  147. ioc_icontrol->cmeimask0 |= (1 << (irq - SGINT_LOCAL2));
  148. restore_flags(flags);
  149. }
  150. static unsigned int startup_local2_irq(unsigned int irq)
  151. {
  152. enable_local2_irq(irq);
  153. return 0; /* Never anything pending  */
  154. }
  155. void disable_local2_irq(unsigned int irq)
  156. {
  157. unsigned long flags;
  158. save_and_cli(flags);
  159. ioc_icontrol->cmeimask0 &= ~(1 << (irq - SGINT_LOCAL2));
  160. restore_flags(flags);
  161. }
  162. #define shutdown_local2_irq disable_local2_irq
  163. #define mask_and_ack_local2_irq disable_local2_irq
  164. static void end_local2_irq (unsigned int irq)
  165. {
  166. if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
  167. enable_local2_irq(irq);
  168. }
  169. static struct hw_interrupt_type ip22_local2_irq_type = {
  170. "IP22 local 2",
  171. startup_local2_irq,
  172. shutdown_local2_irq,
  173. enable_local2_irq,
  174. disable_local2_irq,
  175. mask_and_ack_local2_irq,
  176. end_local2_irq,
  177. NULL
  178. };
  179. static void enable_local3_irq(unsigned int irq)
  180. {
  181. unsigned long flags;
  182. save_and_cli(flags);
  183. printk("Yeeee, got passed irq_nr %d at enable_local3_irqn", irq);
  184. panic("INVALID IRQ level!");
  185. restore_flags(flags);
  186. }
  187. static unsigned int startup_local3_irq(unsigned int irq)
  188. {
  189. enable_local3_irq(irq);
  190. return 0; /* Never anything pending  */
  191. }
  192. void disable_local3_irq(unsigned int irq)
  193. {
  194. unsigned long flags;
  195. save_and_cli(flags);
  196. /*
  197.  * This way we'll see if anyone would ever want vectored level 3
  198.  * interrupts.  Highly unlikely.
  199.  */
  200. printk("Yeeee, got passed irq_nr %d at disable_local3_irqn", irq);
  201. panic("INVALID IRQ level!");
  202. restore_flags(flags);
  203. }
  204. #define shutdown_local3_irq disable_local3_irq
  205. #define mask_and_ack_local3_irq disable_local3_irq
  206. static void end_local3_irq (unsigned int irq)
  207. {
  208. if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
  209. enable_local3_irq(irq);
  210. }
  211. static struct hw_interrupt_type ip22_local3_irq_type = {
  212. "IP22 local 3",
  213. startup_local3_irq,
  214. shutdown_local3_irq,
  215. enable_local3_irq,
  216. disable_local3_irq,
  217. mask_and_ack_local3_irq,
  218. end_local3_irq,
  219. NULL
  220. };
  221. void enable_gio_irq(unsigned int irq)
  222. {
  223. /* XXX TODO XXX */
  224. }
  225. static unsigned int startup_gio_irq(unsigned int irq)
  226. {
  227. enable_gio_irq(irq);
  228. return 0; /* Never anything pending  */
  229. }
  230. void disable_gio_irq(unsigned int irq)
  231. {
  232. /* XXX TODO XXX */
  233. }
  234. #define shutdown_gio_irq disable_gio_irq
  235. #define mask_and_ack_gio_irq disable_gio_irq
  236. static void end_gio_irq (unsigned int irq)
  237. {
  238. if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
  239. enable_gio_irq(irq);
  240. }
  241. static struct hw_interrupt_type ip22_gio_irq_type = {
  242. "IP22 GIO",
  243. startup_gio_irq,
  244. shutdown_gio_irq,
  245. enable_gio_irq,
  246. disable_gio_irq,
  247. mask_and_ack_gio_irq,
  248. end_gio_irq,
  249. NULL
  250. };
  251. void enable_hpcdma_irq(unsigned int irq)
  252. {
  253. /* XXX TODO XXX */
  254. }
  255. static unsigned int startup_hpcdma_irq(unsigned int irq)
  256. {
  257. enable_hpcdma_irq(irq);
  258. return 0; /* Never anything pending  */
  259. }
  260. void disable_hpcdma_irq(unsigned int irq)
  261. {
  262. /* XXX TODO XXX */
  263. }
  264. #define shutdown_hpcdma_irq disable_hpcdma_irq
  265. #define mask_and_ack_hpcdma_irq disable_hpcdma_irq
  266. static void end_hpcdma_irq (unsigned int irq)
  267. {
  268. if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
  269. enable_hpcdma_irq(irq);
  270. }
  271. static struct hw_interrupt_type ip22_hpcdma_irq_type = {
  272. "IP22 HPC DMA",
  273. startup_hpcdma_irq,
  274. shutdown_hpcdma_irq,
  275. enable_hpcdma_irq,
  276. disable_hpcdma_irq,
  277. mask_and_ack_hpcdma_irq,
  278. end_hpcdma_irq,
  279. NULL
  280. };
  281. static struct irqaction r4ktimer_action = {
  282. NULL, 0, 0, "R4000 timer/counter", NULL, NULL,
  283. };
  284. static struct irqaction indy_berr_action = {
  285. NULL, 0, 0, "IP22 Bus Error", NULL, NULL,
  286. };
  287. static struct irqaction *irq_action[16] = {
  288. NULL, NULL, NULL, NULL,
  289. NULL, NULL, &indy_berr_action, &r4ktimer_action,
  290. NULL, NULL, NULL, NULL,
  291. NULL, NULL, NULL, NULL
  292. };
  293. void indy_local0_irqdispatch(struct pt_regs *regs)
  294. {
  295. unsigned char mask = ioc_icontrol->istat0;
  296. unsigned char mask2 = 0;
  297. int irq;
  298. mask &= ioc_icontrol->imask0;
  299. if (mask & ISTAT0_LIO2) {
  300. mask2 = ioc_icontrol->vmeistat;
  301. mask2 &= ioc_icontrol->cmeimask0;
  302. irq = lc2msk_to_irqnr[mask2];
  303. } else {
  304. irq = lc0msk_to_irqnr[mask];
  305. }
  306. /* if irq == 0, then the interrupt has already been cleared */
  307. if (irq == 0)
  308. goto end;
  309. do_IRQ(irq, regs);
  310. goto end;
  311. no_handler:
  312. printk("No handler for local0 irq: %in", irq);
  313. end:
  314. return;
  315. }
  316. void indy_local1_irqdispatch(struct pt_regs *regs)
  317. {
  318. unsigned char mask = ioc_icontrol->istat1;
  319. unsigned char mask2 = 0;
  320. int irq;
  321. mask &= ioc_icontrol->imask1;
  322. if (mask & ISTAT1_LIO3) {
  323. printk("WHee: Got an LIO3 irq, winging it...n");
  324. mask2 = ioc_icontrol->vmeistat;
  325. mask2 &= ioc_icontrol->cmeimask1;
  326. irq = lc3msk_to_irqnr[ioc_icontrol->vmeistat];
  327. } else {
  328. irq = lc1msk_to_irqnr[mask];
  329. }
  330. /* if irq == 0, then the interrupt has already been cleared */
  331. /* not sure if it is needed here, but it is needed for local0 */
  332. if (irq == 0)
  333. goto end;
  334. do_IRQ(irq, regs);
  335. goto end;
  336. no_handler:
  337. printk("No handler for local1 irq: %in", irq);
  338. end:
  339. return;
  340. }
  341. void indy_buserror_irq(struct pt_regs *regs)
  342. {
  343. int cpu = smp_processor_id();
  344. int irq = 6;
  345. irq_enter(cpu, irq);
  346. kstat.irqs[0][irq]++;
  347. printk("Got a bus error IRQ, shouldn't happen yetn");
  348. show_regs(regs);
  349. printk("Spinning...n");
  350. while(1);
  351. irq_exit(cpu, irq);
  352. }
  353. void __init init_IRQ(void)
  354. {
  355. int i;
  356. sgi_i2regs = (struct sgi_int2_regs *) (KSEG1 + SGI_INT2_BASE);
  357. sgi_i3regs = (struct sgi_int3_regs *) (KSEG1 + SGI_INT3_BASE);
  358. /* Init local mask --> irq tables. */
  359. for (i = 0; i < 256; i++) {
  360. if (i & 0x80) {
  361. lc0msk_to_irqnr[i] = 7;
  362. lc1msk_to_irqnr[i] = 15;
  363. lc2msk_to_irqnr[i] = 23;
  364. lc3msk_to_irqnr[i] = 31;
  365. } else if (i & 0x40) {
  366. lc0msk_to_irqnr[i] = 6;
  367. lc1msk_to_irqnr[i] = 14;
  368. lc2msk_to_irqnr[i] = 22;
  369. lc3msk_to_irqnr[i] = 30;
  370. } else if (i & 0x20) {
  371. lc0msk_to_irqnr[i] = 5;
  372. lc1msk_to_irqnr[i] = 13;
  373. lc2msk_to_irqnr[i] = 21;
  374. lc3msk_to_irqnr[i] = 29;
  375. } else if (i & 0x10) {
  376. lc0msk_to_irqnr[i] = 4;
  377. lc1msk_to_irqnr[i] = 12;
  378. lc2msk_to_irqnr[i] = 20;
  379. lc3msk_to_irqnr[i] = 28;
  380. } else if (i & 0x08) {
  381. lc0msk_to_irqnr[i] = 3;
  382. lc1msk_to_irqnr[i] = 11;
  383. lc2msk_to_irqnr[i] = 19;
  384. lc3msk_to_irqnr[i] = 27;
  385. } else if (i & 0x04) {
  386. lc0msk_to_irqnr[i] = 2;
  387. lc1msk_to_irqnr[i] = 10;
  388. lc2msk_to_irqnr[i] = 18;
  389. lc3msk_to_irqnr[i] = 26;
  390. } else if (i & 0x02) {
  391. lc0msk_to_irqnr[i] = 1;
  392. lc1msk_to_irqnr[i] = 9;
  393. lc2msk_to_irqnr[i] = 17;
  394. lc3msk_to_irqnr[i] = 25;
  395. } else if (i & 0x01) {
  396. lc0msk_to_irqnr[i] = 0;
  397. lc1msk_to_irqnr[i] = 8;
  398. lc2msk_to_irqnr[i] = 16;
  399. lc3msk_to_irqnr[i] = 24;
  400. } else {
  401. lc0msk_to_irqnr[i] = 0;
  402. lc1msk_to_irqnr[i] = 0;
  403. lc2msk_to_irqnr[i] = 0;
  404. lc3msk_to_irqnr[i] = 0;
  405. }
  406. }
  407. /* Indy uses an INT3, Indigo2 uses an INT2 */
  408. if (sgi_guiness) {
  409. ioc_icontrol = &sgi_i3regs->ints;
  410. ioc_timers = &sgi_i3regs->timers;
  411. ioc_tclear = &sgi_i3regs->tclear;
  412. } else {
  413. ioc_icontrol = &sgi_i2regs->ints;
  414. ioc_timers = &sgi_i2regs->timers;
  415. ioc_tclear = &sgi_i2regs->tclear;
  416. }
  417. /* Mask out all interrupts. */
  418. ioc_icontrol->imask0 = 0;
  419. ioc_icontrol->imask1 = 0;
  420. ioc_icontrol->cmeimask0 = 0;
  421. ioc_icontrol->cmeimask1 = 0;
  422. set_except_vector(0, indyIRQ);
  423. init_generic_irq();
  424. for (i = SGINT_LOCAL0; i < SGINT_END; i++) {
  425. hw_irq_controller *handler;
  426. if (i < SGINT_LOCAL1)
  427. handler = &ip22_local0_irq_type;
  428. else if (i < SGINT_LOCAL2)
  429. handler = &ip22_local1_irq_type;
  430. else if (i < SGINT_LOCAL3)
  431. handler = &ip22_local2_irq_type;
  432. else if (i < SGINT_GIO)
  433. handler = &ip22_local3_irq_type;
  434. else if (i < SGINT_HPCDMA)
  435. handler = &ip22_gio_irq_type;
  436. else if (i < SGINT_END)
  437. handler = &ip22_hpcdma_irq_type;
  438. irq_desc[i].status = IRQ_DISABLED;
  439. irq_desc[i].action = 0;
  440. irq_desc[i].depth = 1;
  441. irq_desc[i].handler = handler;
  442. }
  443. }