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

嵌入式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) - Indigo2 changes
  8.  */
  9. #include <linux/config.h>
  10. #include <linux/init.h>
  11. #include <linux/errno.h>
  12. #include <linux/kernel_stat.h>
  13. #include <linux/signal.h>
  14. #include <linux/sched.h>
  15. #include <linux/types.h>
  16. #include <linux/interrupt.h>
  17. #include <linux/ioport.h>
  18. #include <linux/timex.h>
  19. #include <linux/slab.h>
  20. #include <linux/random.h>
  21. #include <linux/smp.h>
  22. #include <linux/smp_lock.h>
  23. #include <asm/bitops.h>
  24. #include <asm/bootinfo.h>
  25. #include <asm/io.h>
  26. #include <asm/irq.h>
  27. #include <asm/mipsregs.h>
  28. #include <asm/system.h>
  29. #include <asm/ptrace.h>
  30. #include <asm/processor.h>
  31. #include <asm/sgi/sgi.h>
  32. #include <asm/sgi/sgihpc.h>
  33. #include <asm/sgi/sgint23.h>
  34. /*
  35.  * Linux has a controller-independent x86 interrupt architecture.
  36.  * every controller has a 'controller-template', that is used
  37.  * by the main code to do the right thing. Each driver-visible
  38.  * interrupt source is transparently wired to the apropriate
  39.  * controller. Thus drivers need not be aware of the
  40.  * interrupt-controller.
  41.  *
  42.  * Various interrupt controllers we handle: 8259 PIC, SMP IO-APIC,
  43.  * PIIX4's internal 8259 PIC and SGI's Visual Workstation Cobalt (IO-)APIC.
  44.  * (IO-APICs assumed to be messaging to Pentium local-APICs)
  45.  *
  46.  * the code is designed to be easily extended with new/different
  47.  * interrupt controllers, without having to do assembly magic.
  48.  */
  49. struct sgi_int2_regs *sgi_i2regs;
  50. struct sgi_int3_regs *sgi_i3regs;
  51. struct sgi_ioc_ints *ioc_icontrol;
  52. struct sgi_ioc_timers *ioc_timers;
  53. volatile unsigned char *ioc_tclear;
  54. static char lc0msk_to_irqnr[256];
  55. static char lc1msk_to_irqnr[256];
  56. static char lc2msk_to_irqnr[256];
  57. static char lc3msk_to_irqnr[256];
  58. extern asmlinkage void indyIRQ(void);
  59. #ifdef CONFIG_REMOTE_DEBUG
  60. extern void rs_kgdb_hook(int);
  61. #endif
  62. unsigned long spurious_count = 0;
  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. void disable_local_irq(unsigned int irq_nr)
  71. {
  72. unsigned long flags;
  73. save_and_cli(flags);
  74. switch(irq_nr) {
  75. case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
  76. ioc_icontrol->imask0 &= ~(1 << irq_nr);
  77. break;
  78. case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15:
  79. ioc_icontrol->imask1 &= ~(1 << (irq_nr - 8));
  80. break;
  81. case 16: case 17: case 18: case 19: case 20: case 21: case 22: case 23:
  82. ioc_icontrol->cmeimask0 &= ~(1 << (irq_nr - 16));
  83. break;
  84. default:
  85. /* This way we'll see if anyone would ever want vectored
  86.  * level 3 interrupts.  Highly unlikely.
  87.  */
  88. printk("Yeeee, got passed irq_nr %d at disable_irqn", irq_nr);
  89. panic("INVALID IRQ level!");
  90. };
  91. restore_flags(flags);
  92. }
  93. void enable_local_irq(unsigned int irq_nr)
  94. {
  95. unsigned long flags;
  96. save_and_cli(flags);
  97. switch(irq_nr) {
  98. case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
  99. ioc_icontrol->imask0 |= (1 << irq_nr);
  100. break;
  101. case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15:
  102. ioc_icontrol->imask1 |= (1 << (irq_nr - 8));
  103. break;
  104. case 16: case 17: case 18: case 19: case 20: case 21: case 22: case 23:
  105. enable_local_irq(7);
  106. ioc_icontrol->cmeimask0 |= (1 << (irq_nr - 16));
  107. break;
  108. default:
  109. printk("Yeeee, got passed irq_nr %d at disable_irqn", irq_nr);
  110. panic("INVALID IRQ level!");
  111. };
  112. restore_flags(flags);
  113. }
  114. void disable_gio_irq(unsigned int irq_nr)
  115. {
  116. /* XXX TODO XXX */
  117. }
  118. void enable_gio_irq(unsigned int irq_nr)
  119. {
  120. /* XXX TODO XXX */
  121. }
  122. void disable_hpcdma_irq(unsigned int irq_nr)
  123. {
  124. /* XXX TODO XXX */
  125. }
  126. void enable_hpcdma_irq(unsigned int irq_nr)
  127. {
  128. /* XXX TODO XXX */
  129. }
  130. void disable_irq(unsigned int irq_nr)
  131. {
  132. unsigned int n = irq_nr;
  133. if(n >= SGINT_END) {
  134. printk("whee, invalid irq_nr %dn", irq_nr);
  135. panic("IRQ, you lose...");
  136. }
  137. if(n >= SGINT_LOCAL0 && n < SGINT_GIO) {
  138. disable_local_irq(n - SGINT_LOCAL0);
  139. } else if(n >= SGINT_GIO && n < SGINT_HPCDMA) {
  140. disable_gio_irq(n - SGINT_GIO);
  141. } else if(n >= SGINT_HPCDMA && n < SGINT_END) {
  142. disable_hpcdma_irq(n - SGINT_HPCDMA);
  143. } else {
  144. panic("how did I get here?");
  145. }
  146. }
  147. void enable_irq(unsigned int irq_nr)
  148. {
  149. unsigned int n = irq_nr;
  150. if(n >= SGINT_END) {
  151. printk("whee, invalid irq_nr %dn", irq_nr);
  152. panic("IRQ, you lose...");
  153. }
  154. if(n >= SGINT_LOCAL0 && n < SGINT_GIO) {
  155. enable_local_irq(n - SGINT_LOCAL0);
  156. } else if(n >= SGINT_GIO && n < SGINT_HPCDMA) {
  157. enable_gio_irq(n - SGINT_GIO);
  158. } else if(n >= SGINT_HPCDMA && n < SGINT_END) {
  159. enable_hpcdma_irq(n - SGINT_HPCDMA);
  160. } else {
  161. panic("how did I get here?");
  162. }
  163. }
  164. #if 0
  165. /*
  166.  * Currently unused.
  167.  */
  168. static void local_unex(int irq, void *data, struct pt_regs *regs)
  169. {
  170. printk("Whee: unexpected local IRQ at %08lxn",
  171.        (unsigned long) regs->cp0_epc);
  172. printk("DUMP: stat0<%x> stat1<%x> vmeistat<%x>n",
  173.        ioc_icontrol->istat0, ioc_icontrol->istat1,
  174.        ioc_icontrol->vmeistat);
  175. }
  176. #endif
  177. static struct irqaction *local_irq_action[24] = {
  178. NULL, NULL, NULL, NULL,
  179. NULL, NULL, NULL, NULL,
  180. NULL, NULL, NULL, NULL,
  181. NULL, NULL, NULL, NULL,
  182. NULL, NULL, NULL, NULL,
  183. NULL, NULL, NULL, NULL
  184. };
  185. int setup_indy_irq(int irq, struct irqaction * new)
  186. {
  187. printk("setup_indy_irq: Yeee, don't know how to setup irq<%d> for %s  %pn",
  188.        irq, new->name, new->handler);
  189. return 0;
  190. }
  191. static struct irqaction r4ktimer_action = {
  192. NULL, 0, 0, "R4000 timer/counter", NULL, NULL,
  193. };
  194. static struct irqaction indy_berr_action = {
  195. NULL, 0, 0, "IP22 Bus Error", NULL, NULL,
  196. };
  197. static struct irqaction *irq_action[16] = {
  198. NULL, NULL, NULL, NULL,
  199. NULL, NULL, &indy_berr_action, &r4ktimer_action,
  200. NULL, NULL, NULL, NULL,
  201. NULL, NULL, NULL, NULL
  202. };
  203. int get_irq_list(char *buf)
  204. {
  205. int i, len = 0;
  206. int num = 0;
  207. struct irqaction * action;
  208. for (i = 0 ; i < 16 ; i++, num++) {
  209. action = irq_action[i];
  210. if (!action) 
  211. continue;
  212. len += sprintf(buf+len, "%2d: %8d %c %s",
  213. num, kstat.irqs[0][num],
  214. (action->flags & SA_INTERRUPT) ? '+' : ' ',
  215. action->name);
  216. for (action=action->next; action; action = action->next) {
  217. len += sprintf(buf+len, ",%s %s",
  218. (action->flags & SA_INTERRUPT) ? " +" : "",
  219. action->name);
  220. }
  221. len += sprintf(buf+len, " [on-chip]n");
  222. }
  223. for (i = 0 ; i < 24 ; i++, num++) {
  224. action = local_irq_action[i];
  225. if (!action) 
  226. continue;
  227. len += sprintf(buf+len, "%2d: %8d %c %s",
  228. num, kstat.irqs[0][num],
  229. (action->flags & SA_INTERRUPT) ? '+' : ' ',
  230. action->name);
  231. for (action=action->next; action; action = action->next) {
  232. len += sprintf(buf+len, ",%s %s",
  233. (action->flags & SA_INTERRUPT) ? " +" : "",
  234. action->name);
  235. }
  236. len += sprintf(buf+len, " [local]n");
  237. }
  238. return len;
  239. }
  240. /*
  241.  * do_IRQ handles IRQ's that have been installed without the
  242.  * SA_INTERRUPT flag: it uses the full signal-handling return
  243.  * and runs with other interrupts enabled. All relatively slow
  244.  * IRQ's should use this format: notably the keyboard/timer
  245.  * routines.
  246.  */
  247. asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
  248. {
  249. struct irqaction *action;
  250. int do_random, cpu;
  251. cpu = smp_processor_id();
  252. irq_enter(cpu, irq);
  253. kstat.irqs[0][irq]++;
  254. panic(KERN_DEBUG "Got irq %d, press a key.", irq);
  255. /*
  256.  * mask and ack quickly, we don't want the irq controller
  257.  * thinking we're snobs just because some other CPU has
  258.  * disabled global interrupts (we have already done the
  259.  * INT_ACK cycles, it's too late to try to pretend to the
  260.  * controller that we aren't taking the interrupt).
  261.  *
  262.  * Commented out because we've already done this in the
  263.  * machinespecific part of the handler.  It's reasonable to
  264.  * do this here in a highlevel language though because that way
  265.  * we could get rid of a good part of duplicated code ...
  266.  */
  267.         /* mask_and_ack_irq(irq); */
  268. action = *(irq + irq_action);
  269. if (action) {
  270. if (!(action->flags & SA_INTERRUPT))
  271. __sti();
  272. action = *(irq + irq_action);
  273. do_random = 0;
  274. do {
  275. do_random |= action->flags;
  276. action->handler(irq, action->dev_id, regs);
  277. action = action->next;
  278. } while (action);
  279. if (do_random & SA_SAMPLE_RANDOM)
  280. add_interrupt_randomness(irq);
  281. __cli();
  282. }
  283. irq_exit(cpu, irq);
  284. /* unmasking and bottom half handling is done magically for us. */
  285. }
  286. int request_local_irq(unsigned int lirq, void (*func)(int, void *, struct pt_regs *),
  287.       unsigned long iflags, const char *dname, void *devid)
  288. {
  289. struct irqaction *action;
  290. lirq -= SGINT_LOCAL0;
  291. if(lirq >= 24 || !func)
  292. return -EINVAL;
  293. action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL);
  294. if(!action)
  295. return -ENOMEM;
  296. action->handler = func;
  297. action->flags = iflags;
  298. action->mask = 0;
  299. action->name = dname;
  300. action->dev_id = devid;
  301. action->next = 0;
  302. local_irq_action[lirq] = action;
  303. enable_irq(lirq + SGINT_LOCAL0);
  304. return 0;
  305. }
  306. void free_local_irq(unsigned int lirq, void *dev_id)
  307. {
  308. struct irqaction *action;
  309. lirq -= SGINT_LOCAL0;
  310. if(lirq >= 24) {
  311. printk("Aieee: trying to free bogus local irq %dn",
  312.        lirq + SGINT_LOCAL0);
  313. return;
  314. }
  315. action = local_irq_action[lirq];
  316. local_irq_action[lirq] = NULL;
  317. disable_irq(lirq + SGINT_LOCAL0);
  318. kfree(action);
  319. }
  320. int request_irq(unsigned int irq, 
  321. void (*handler)(int, void *, struct pt_regs *),
  322. unsigned long irqflags, 
  323. const char * devname,
  324. void *dev_id)
  325. {
  326. int retval;
  327. struct irqaction * action;
  328. if (irq >= SGINT_END)
  329. return -EINVAL;
  330. if (!handler)
  331. return -EINVAL;
  332. if((irq >= SGINT_LOCAL0) && (irq < SGINT_GIO))
  333. return request_local_irq(irq, handler, irqflags, devname, dev_id);
  334. action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL);
  335. if (!action)
  336. return -ENOMEM;
  337. action->handler = handler;
  338. action->flags = irqflags;
  339. action->mask = 0;
  340. action->name = devname;
  341. action->next = NULL;
  342. action->dev_id = dev_id;
  343. retval = setup_indy_irq(irq, action);
  344. if (retval)
  345. kfree(action);
  346. return retval;
  347. }
  348. void free_irq(unsigned int irq, void *dev_id)
  349. {
  350. struct irqaction * action, **p;
  351. unsigned long flags;
  352. if (irq >= SGINT_END) {
  353. printk("Trying to free IRQ%dn",irq);
  354. return;
  355. }
  356. if((irq >= SGINT_LOCAL0) && (irq < SGINT_GIO)) {
  357. free_local_irq(irq, dev_id);
  358. return;
  359. }
  360. for (p = irq + irq_action; (action = *p) != NULL; p = &action->next) {
  361. if (action->dev_id != dev_id)
  362. continue;
  363. /* Found it - now free it */
  364. save_and_cli(flags);
  365. *p = action->next;
  366. restore_flags(flags);
  367. kfree(action);
  368. return;
  369. }
  370. printk("Trying to free free IRQ%dn",irq);
  371. }
  372. void indy_local0_irqdispatch(struct pt_regs *regs)
  373. {
  374. struct irqaction *action;
  375. unsigned char mask = ioc_icontrol->istat0;
  376. unsigned char mask2 = 0;
  377. int irq, cpu = smp_processor_id();;
  378. mask &= ioc_icontrol->imask0;
  379. if(mask & ISTAT0_LIO2) {
  380. mask2 = ioc_icontrol->vmeistat;
  381. mask2 &= ioc_icontrol->cmeimask0;
  382. irq = lc2msk_to_irqnr[mask2];
  383. action = local_irq_action[irq];
  384. } else {
  385. irq = lc0msk_to_irqnr[mask];
  386. action = local_irq_action[irq];
  387. }
  388. irq_enter(cpu, irq);
  389. kstat.irqs[0][irq + 16]++;
  390. action->handler(irq, action->dev_id, regs);
  391. irq_exit(cpu, irq);
  392. }
  393. void indy_local1_irqdispatch(struct pt_regs *regs)
  394. {
  395. struct irqaction *action;
  396. unsigned char mask = ioc_icontrol->istat1;
  397. unsigned char mask2 = 0;
  398. int irq, cpu = smp_processor_id();;
  399. mask &= ioc_icontrol->imask1;
  400. if(mask & ISTAT1_LIO3) {
  401. printk("WHee: Got an LIO3 irq, winging it...n");
  402. mask2 = ioc_icontrol->vmeistat;
  403. mask2 &= ioc_icontrol->cmeimask1;
  404. irq = lc3msk_to_irqnr[ioc_icontrol->vmeistat];
  405. action = local_irq_action[irq];
  406. } else {
  407. irq = lc1msk_to_irqnr[mask];
  408. action = local_irq_action[irq];
  409. }
  410. irq_enter(cpu, irq);
  411. kstat.irqs[0][irq + 24]++;
  412. action->handler(irq, action->dev_id, regs);
  413. irq_exit(cpu, irq);
  414. }
  415. void indy_buserror_irq(struct pt_regs *regs)
  416. {
  417. int cpu = smp_processor_id();
  418. int irq = 6;
  419. irq_enter(cpu, irq);
  420. kstat.irqs[0][irq]++;
  421. printk("Got a bus error IRQ, shouldn't happen yetn");
  422. show_regs(regs);
  423. printk("Spinning...n");
  424. while(1);
  425. irq_exit(cpu, irq);
  426. }
  427. /* Misc. crap just to keep the kernel linking... */
  428. unsigned long probe_irq_on (void)
  429. {
  430. return 0;
  431. }
  432. int probe_irq_off (unsigned long irqs)
  433. {
  434. return 0;
  435. }
  436. static inline void sgint_init(void)
  437. {
  438. int i;
  439. #ifdef CONFIG_REMOTE_DEBUG
  440. char *ctype;
  441. #endif
  442. sgi_i2regs = (struct sgi_int2_regs *) (KSEG1 + SGI_INT2_BASE);
  443. sgi_i3regs = (struct sgi_int3_regs *) (KSEG1 + SGI_INT3_BASE);
  444. /* Init local mask --> irq tables. */
  445. for(i = 0; i < 256; i++) {
  446. if(i & 0x80) {
  447. lc0msk_to_irqnr[i] = 7;
  448. lc1msk_to_irqnr[i] = 15;
  449. lc2msk_to_irqnr[i] = 23;
  450. lc3msk_to_irqnr[i] = 31;
  451. } else if(i & 0x40) {
  452. lc0msk_to_irqnr[i] = 6;
  453. lc1msk_to_irqnr[i] = 14;
  454. lc2msk_to_irqnr[i] = 22;
  455. lc3msk_to_irqnr[i] = 30;
  456. } else if(i & 0x20) {
  457. lc0msk_to_irqnr[i] = 5;
  458. lc1msk_to_irqnr[i] = 13;
  459. lc2msk_to_irqnr[i] = 21;
  460. lc3msk_to_irqnr[i] = 29;
  461. } else if(i & 0x10) {
  462. lc0msk_to_irqnr[i] = 4;
  463. lc1msk_to_irqnr[i] = 12;
  464. lc2msk_to_irqnr[i] = 20;
  465. lc3msk_to_irqnr[i] = 28;
  466. } else if(i & 0x08) {
  467. lc0msk_to_irqnr[i] = 3;
  468. lc1msk_to_irqnr[i] = 11;
  469. lc2msk_to_irqnr[i] = 19;
  470. lc3msk_to_irqnr[i] = 27;
  471. } else if(i & 0x04) {
  472. lc0msk_to_irqnr[i] = 2;
  473. lc1msk_to_irqnr[i] = 10;
  474. lc2msk_to_irqnr[i] = 18;
  475. lc3msk_to_irqnr[i] = 26;
  476. } else if(i & 0x02) {
  477. lc0msk_to_irqnr[i] = 1;
  478. lc1msk_to_irqnr[i] = 9;
  479. lc2msk_to_irqnr[i] = 17;
  480. lc3msk_to_irqnr[i] = 25;
  481. } else if(i & 0x01) {
  482. lc0msk_to_irqnr[i] = 0;
  483. lc1msk_to_irqnr[i] = 8;
  484. lc2msk_to_irqnr[i] = 16;
  485. lc3msk_to_irqnr[i] = 24;
  486. } else {
  487. lc0msk_to_irqnr[i] = 0;
  488. lc1msk_to_irqnr[i] = 0;
  489. lc2msk_to_irqnr[i] = 0;
  490. lc3msk_to_irqnr[i] = 0;
  491. }
  492. }
  493. /* Indy uses an INT3, Indigo2 uses an INT2 */
  494. if (sgi_guiness) {
  495. ioc_icontrol = &sgi_i3regs->ints;
  496. ioc_timers = &sgi_i3regs->timers;
  497. ioc_tclear = &sgi_i3regs->tclear;
  498. } else {
  499. ioc_icontrol = &sgi_i2regs->ints;
  500. ioc_timers = &sgi_i2regs->timers;
  501. ioc_tclear = &sgi_i2regs->tclear;
  502. }
  503. /* Mask out all interrupts. */
  504. ioc_icontrol->imask0 = 0;
  505. ioc_icontrol->imask1 = 0;
  506. ioc_icontrol->cmeimask0 = 0;
  507. ioc_icontrol->cmeimask1 = 0;
  508. /* Now safe to set the exception vector. */
  509. set_except_vector(0, indyIRQ);
  510. #ifdef CONFIG_REMOTE_DEBUG
  511. ctype = prom_getcmdline();
  512. for(i = 0; i < strlen(ctype); i++) {
  513. if(ctype[i]=='k' && ctype[i+1]=='g' &&
  514.    ctype[i+2]=='d' && ctype[i+3]=='b' &&
  515.    ctype[i+4]=='=' && ctype[i+5]=='t' &&
  516.    ctype[i+6]=='t' && ctype[i+7]=='y' &&
  517.    ctype[i+8]=='d' &&
  518.    (ctype[i+9] == '1' || ctype[i+9] == '2')) {
  519. printk("KGDB: Using serial line /dev/ttyd%d for "
  520.        "sessionn", (ctype[i+9] - '0'));
  521. if(ctype[i+9]=='1')
  522. rs_kgdb_hook(1);
  523. else if(ctype[i+9]=='2')
  524. rs_kgdb_hook(0);
  525. else {
  526. printk("KGDB: whoops bogon tty line "
  527.        "requested, disabling sessionn");
  528. }
  529. }
  530. }
  531. #endif
  532. }
  533. void __init init_IRQ(void)
  534. {
  535. sgint_init();
  536. }