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

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * linux/arch/alpha/kernel/sys_noritake.c
  3.  *
  4.  * Copyright (C) 1995 David A Rusling
  5.  * Copyright (C) 1996 Jay A Estabrook
  6.  * Copyright (C) 1998, 1999 Richard Henderson
  7.  *
  8.  * Code supporting the NORITAKE (AlphaServer 1000A), 
  9.  * CORELLE (AlphaServer 800), and ALCOR Primo (AlphaStation 600A).
  10.  */
  11. #include <linux/config.h>
  12. #include <linux/kernel.h>
  13. #include <linux/types.h>
  14. #include <linux/mm.h>
  15. #include <linux/sched.h>
  16. #include <linux/pci.h>
  17. #include <linux/init.h>
  18. #include <asm/ptrace.h>
  19. #include <asm/system.h>
  20. #include <asm/dma.h>
  21. #include <asm/irq.h>
  22. #include <asm/bitops.h>
  23. #include <asm/mmu_context.h>
  24. #include <asm/io.h>
  25. #include <asm/pgtable.h>
  26. #include <asm/core_apecs.h>
  27. #include <asm/core_cia.h>
  28. #include "proto.h"
  29. #include "irq_impl.h"
  30. #include "pci_impl.h"
  31. #include "machvec_impl.h"
  32. /* Note mask bit is true for ENABLED irqs.  */
  33. static int cached_irq_mask;
  34. static inline void
  35. noritake_update_irq_hw(int irq, int mask)
  36. {
  37. int port = 0x54a;
  38. if (irq >= 32) {
  39.     mask >>= 16;
  40.     port = 0x54c;
  41. }
  42. outw(mask, port);
  43. }
  44. static void
  45. noritake_enable_irq(unsigned int irq)
  46. {
  47. noritake_update_irq_hw(irq, cached_irq_mask |= 1 << (irq - 16));
  48. }
  49. static void
  50. noritake_disable_irq(unsigned int irq)
  51. {
  52. noritake_update_irq_hw(irq, cached_irq_mask &= ~(1 << (irq - 16)));
  53. }
  54. static unsigned int
  55. noritake_startup_irq(unsigned int irq)
  56. {
  57. noritake_enable_irq(irq);
  58. return 0;
  59. }
  60. static struct hw_interrupt_type noritake_irq_type = {
  61. typename: "NORITAKE",
  62. startup: noritake_startup_irq,
  63. shutdown: noritake_disable_irq,
  64. enable: noritake_enable_irq,
  65. disable: noritake_disable_irq,
  66. ack: noritake_disable_irq,
  67. end: noritake_enable_irq,
  68. };
  69. static void 
  70. noritake_device_interrupt(unsigned long vector, struct pt_regs *regs)
  71. {
  72. unsigned long pld;
  73. unsigned int i;
  74. /* Read the interrupt summary registers of NORITAKE */
  75. pld = (((unsigned long) inw(0x54c) << 32)
  76.        | ((unsigned long) inw(0x54a) << 16)
  77.        | ((unsigned long) inb(0xa0) << 8)
  78.        | inb(0x20));
  79. /*
  80.  * Now for every possible bit set, work through them and call
  81.  * the appropriate interrupt handler.
  82.  */
  83. while (pld) {
  84. i = ffz(~pld);
  85. pld &= pld - 1; /* clear least bit set */
  86. if (i < 16) {
  87. isa_device_interrupt(vector, regs);
  88. } else {
  89. handle_irq(i, regs);
  90. }
  91. }
  92. }
  93. static void 
  94. noritake_srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
  95. {
  96. int irq;
  97. irq = (vector - 0x800) >> 4;
  98. /*
  99.  * I really hate to do this, too, but the NORITAKE SRM console also
  100.  * reports PCI vectors *lower* than I expected from the bit numbers
  101.  * in the documentation.
  102.  * But I really don't want to change the fixup code for allocation
  103.  * of IRQs, nor the alpha_irq_mask maintenance stuff, both of which
  104.  * look nice and clean now.
  105.  * So, here's this additional grotty hack... :-(
  106.  */
  107. if (irq >= 16)
  108. irq = irq + 1;
  109. handle_irq(irq, regs);
  110. }
  111. static void __init
  112. noritake_init_irq(void)
  113. {
  114. long i;
  115. if (alpha_using_srm)
  116. alpha_mv.device_interrupt = noritake_srm_device_interrupt;
  117. outw(0, 0x54a);
  118. outw(0, 0x54c);
  119. for (i = 16; i < 48; ++i) {
  120. irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
  121. irq_desc[i].handler = &noritake_irq_type;
  122. }
  123. init_i8259a_irqs();
  124. common_init_isa_dma();
  125. }
  126. /*
  127.  * PCI Fixup configuration.
  128.  *
  129.  * Summary @ 0x542, summary register #1:
  130.  * Bit      Meaning
  131.  * 0        All valid ints from summary regs 2 & 3
  132.  * 1        QLOGIC ISP1020A SCSI
  133.  * 2        Interrupt Line A from slot 0
  134.  * 3        Interrupt Line B from slot 0
  135.  * 4        Interrupt Line A from slot 1
  136.  * 5        Interrupt line B from slot 1
  137.  * 6        Interrupt Line A from slot 2
  138.  * 7        Interrupt Line B from slot 2
  139.  * 8        Interrupt Line A from slot 3
  140.  * 9        Interrupt Line B from slot 3
  141.  *10        Interrupt Line A from slot 4
  142.  *11        Interrupt Line B from slot 4
  143.  *12        Interrupt Line A from slot 5
  144.  *13        Interrupt Line B from slot 5
  145.  *14        Interrupt Line A from slot 6
  146.  *15        Interrupt Line B from slot 6
  147.  *
  148.  * Summary @ 0x544, summary register #2:
  149.  * Bit      Meaning
  150.  * 0        OR of all unmasked ints in SR #2
  151.  * 1        OR of secondary bus ints
  152.  * 2        Interrupt Line C from slot 0
  153.  * 3        Interrupt Line D from slot 0
  154.  * 4        Interrupt Line C from slot 1
  155.  * 5        Interrupt line D from slot 1
  156.  * 6        Interrupt Line C from slot 2
  157.  * 7        Interrupt Line D from slot 2
  158.  * 8        Interrupt Line C from slot 3
  159.  * 9        Interrupt Line D from slot 3
  160.  *10        Interrupt Line C from slot 4
  161.  *11        Interrupt Line D from slot 4
  162.  *12        Interrupt Line C from slot 5
  163.  *13        Interrupt Line D from slot 5
  164.  *14        Interrupt Line C from slot 6
  165.  *15        Interrupt Line D from slot 6
  166.  *
  167.  * The device to slot mapping looks like:
  168.  *
  169.  * Slot     Device
  170.  *  7       Intel PCI-EISA bridge chip
  171.  *  8       DEC PCI-PCI bridge chip
  172.  * 11       PCI on board slot 0
  173.  * 12       PCI on board slot 1
  174.  * 13       PCI on board slot 2
  175.  *   
  176.  *
  177.  * This two layered interrupt approach means that we allocate IRQ 16 and 
  178.  * above for PCI interrupts.  The IRQ relates to which bit the interrupt
  179.  * comes in on.  This makes interrupt processing much easier.
  180.  */
  181. static int __init
  182. noritake_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
  183. {
  184. static char irq_tab[15][5] __initdata = {
  185. /*INT    INTA   INTB   INTC   INTD */
  186. /* note: IDSELs 16, 17, and 25 are CORELLE only */
  187. { 16+1,  16+1,  16+1,  16+1,  16+1},  /* IdSel 16,  QLOGIC */
  188. {   -1,    -1,    -1,    -1,    -1},  /* IdSel 17, S3 Trio64 */
  189. {   -1,    -1,    -1,    -1,    -1},  /* IdSel 18,  PCEB */
  190. {   -1,    -1,    -1,    -1,    -1},  /* IdSel 19,  PPB  */
  191. {   -1,    -1,    -1,    -1,    -1},  /* IdSel 20,  ???? */
  192. {   -1,    -1,    -1,    -1,    -1},  /* IdSel 21,  ???? */
  193. { 16+2,  16+2,  16+3,  32+2,  32+3},  /* IdSel 22,  slot 0 */
  194. { 16+4,  16+4,  16+5,  32+4,  32+5},  /* IdSel 23,  slot 1 */
  195. { 16+6,  16+6,  16+7,  32+6,  32+7},  /* IdSel 24,  slot 2 */
  196. { 16+8,  16+8,  16+9,  32+8,  32+9}, /* IdSel 25,  slot 3 */
  197. /* The following 5 are actually on PCI bus 1, which is 
  198.    across the built-in bridge of the NORITAKE only.  */
  199. { 16+1,  16+1,  16+1,  16+1,  16+1},  /* IdSel 16,  QLOGIC */
  200. { 16+8,  16+8,  16+9,  32+8,  32+9},  /* IdSel 17,  slot 3 */
  201. {16+10, 16+10, 16+11, 32+10, 32+11},  /* IdSel 18,  slot 4 */
  202. {16+12, 16+12, 16+13, 32+12, 32+13},  /* IdSel 19,  slot 5 */
  203. {16+14, 16+14, 16+15, 32+14, 32+15},  /* IdSel 20,  slot 6 */
  204. };
  205. const long min_idsel = 5, max_idsel = 19, irqs_per_slot = 5;
  206. return COMMON_TABLE_LOOKUP;
  207. }
  208. static u8 __init
  209. noritake_swizzle(struct pci_dev *dev, u8 *pinp)
  210. {
  211. int slot, pin = *pinp;
  212. if (dev->bus->number == 0) {
  213. slot = PCI_SLOT(dev->devfn);
  214. }
  215. /* Check for the built-in bridge */
  216. else if (PCI_SLOT(dev->bus->self->devfn) == 8) {
  217. slot = PCI_SLOT(dev->devfn) + 15; /* WAG! */
  218. }
  219. else
  220. {
  221. /* Must be a card-based bridge.  */
  222. do {
  223. if (PCI_SLOT(dev->bus->self->devfn) == 8) {
  224. slot = PCI_SLOT(dev->devfn) + 15;
  225. break;
  226. }
  227. pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn)) ;
  228. /* Move up the chain of bridges.  */
  229. dev = dev->bus->self;
  230. /* Slot of the next bridge.  */
  231. slot = PCI_SLOT(dev->devfn);
  232. } while (dev->bus->self);
  233. }
  234. *pinp = pin;
  235. return slot;
  236. }
  237. #if defined(CONFIG_ALPHA_GENERIC) || !defined(CONFIG_ALPHA_PRIMO)
  238. static void
  239. noritake_apecs_machine_check(unsigned long vector, unsigned long la_ptr,
  240.      struct pt_regs * regs)
  241. {
  242. #define MCHK_NO_DEVSEL 0x205U
  243. #define MCHK_NO_TABT 0x204U
  244.         struct el_common *mchk_header;
  245.         unsigned int code;
  246.         mchk_header = (struct el_common *)la_ptr;
  247.         /* Clear the error before any reporting.  */
  248.         mb();
  249.         mb(); /* magic */
  250.         draina();
  251.         apecs_pci_clr_err();
  252.         wrmces(0x7);
  253.         mb();
  254.         code = mchk_header->code;
  255.         process_mcheck_info(vector, la_ptr, regs, "NORITAKE APECS",
  256.                             (mcheck_expected(0)
  257.                              && (code == MCHK_NO_DEVSEL
  258.                                  || code == MCHK_NO_TABT)));
  259. }
  260. #endif
  261. /*
  262.  * The System Vectors
  263.  */
  264. #if defined(CONFIG_ALPHA_GENERIC) || !defined(CONFIG_ALPHA_PRIMO)
  265. struct alpha_machine_vector noritake_mv __initmv = {
  266. vector_name: "Noritake",
  267. DO_EV4_MMU,
  268. DO_DEFAULT_RTC,
  269. DO_APECS_IO,
  270. DO_APECS_BUS,
  271. machine_check: noritake_apecs_machine_check,
  272. max_dma_address: ALPHA_MAX_DMA_ADDRESS,
  273. min_io_address: EISA_DEFAULT_IO_BASE,
  274. min_mem_address: APECS_AND_LCA_DEFAULT_MEM_BASE,
  275. nr_irqs: 48,
  276. device_interrupt: noritake_device_interrupt,
  277. init_arch: apecs_init_arch,
  278. init_irq: noritake_init_irq,
  279. init_rtc: common_init_rtc,
  280. init_pci: common_init_pci,
  281. kill_arch: NULL,
  282. pci_map_irq: noritake_map_irq,
  283. pci_swizzle: noritake_swizzle,
  284. };
  285. ALIAS_MV(noritake)
  286. #endif
  287. #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_PRIMO)
  288. struct alpha_machine_vector noritake_primo_mv __initmv = {
  289. vector_name: "Noritake-Primo",
  290. DO_EV5_MMU,
  291. DO_DEFAULT_RTC,
  292. DO_CIA_IO,
  293. DO_CIA_BUS,
  294. machine_check: cia_machine_check,
  295. max_dma_address: ALPHA_MAX_DMA_ADDRESS,
  296. min_io_address: EISA_DEFAULT_IO_BASE,
  297. min_mem_address: CIA_DEFAULT_MEM_BASE,
  298. nr_irqs: 48,
  299. device_interrupt: noritake_device_interrupt,
  300. init_arch: cia_init_arch,
  301. init_irq: noritake_init_irq,
  302. init_rtc: common_init_rtc,
  303. init_pci: cia_init_pci,
  304. pci_map_irq: noritake_map_irq,
  305. pci_swizzle: noritake_swizzle,
  306. };
  307. ALIAS_MV(noritake_primo)
  308. #endif