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

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * linux/arch/alpha/kernel/sys_eiger.c
  3.  *
  4.  * Copyright (C) 1995 David A Rusling
  5.  * Copyright (C) 1996, 1999 Jay A Estabrook
  6.  * Copyright (C) 1998, 1999 Richard Henderson
  7.  * Copyright (C) 1999 Iain Grant
  8.  *
  9.  * Code supporting the EIGER (EV6+TSUNAMI).
  10.  */
  11. #include <linux/kernel.h>
  12. #include <linux/types.h>
  13. #include <linux/mm.h>
  14. #include <linux/sched.h>
  15. #include <linux/pci.h>
  16. #include <linux/init.h>
  17. #include <asm/ptrace.h>
  18. #include <asm/system.h>
  19. #include <asm/dma.h>
  20. #include <asm/irq.h>
  21. #include <asm/bitops.h>
  22. #include <asm/mmu_context.h>
  23. #include <asm/io.h>
  24. #include <asm/pci.h>
  25. #include <asm/pgtable.h>
  26. #include <asm/core_tsunami.h>
  27. #include <asm/hwrpb.h>
  28. #include "proto.h"
  29. #include "irq_impl.h"
  30. #include "pci_impl.h"
  31. #include "machvec_impl.h"
  32. /* Note that this interrupt code is identical to TAKARA.  */
  33. /* Note mask bit is true for DISABLED irqs.  */
  34. static unsigned long cached_irq_mask[2] = { -1, -1 };
  35. static inline void
  36. eiger_update_irq_hw(unsigned long irq, unsigned long mask)
  37. {
  38. int regaddr;
  39. mask = (irq >= 64 ? mask << 16 : mask >> ((irq - 16) & 0x30));
  40. regaddr = 0x510 + (((irq - 16) >> 2) & 0x0c);
  41. outl(mask & 0xffff0000UL, regaddr);
  42. }
  43. static inline void
  44. eiger_enable_irq(unsigned int irq)
  45. {
  46. unsigned long mask;
  47. mask = (cached_irq_mask[irq >= 64] &= ~(1UL << (irq & 63)));
  48. eiger_update_irq_hw(irq, mask);
  49. }
  50. static void
  51. eiger_disable_irq(unsigned int irq)
  52. {
  53. unsigned long mask;
  54. mask = (cached_irq_mask[irq >= 64] |= 1UL << (irq & 63));
  55. eiger_update_irq_hw(irq, mask);
  56. }
  57. static unsigned int
  58. eiger_startup_irq(unsigned int irq)
  59. {
  60. eiger_enable_irq(irq);
  61. return 0; /* never anything pending */
  62. }
  63. static void
  64. eiger_end_irq(unsigned int irq)
  65. {
  66. if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
  67. eiger_enable_irq(irq);
  68. }
  69. static struct hw_interrupt_type eiger_irq_type = {
  70. typename: "EIGER",
  71. startup: eiger_startup_irq,
  72. shutdown: eiger_disable_irq,
  73. enable: eiger_enable_irq,
  74. disable: eiger_disable_irq,
  75. ack: eiger_disable_irq,
  76. end: eiger_end_irq,
  77. };
  78. static void
  79. eiger_device_interrupt(unsigned long vector, struct pt_regs * regs)
  80. {
  81. unsigned intstatus;
  82. /*
  83.  * The PALcode will have passed us vectors 0x800 or 0x810,
  84.  * which are fairly arbitrary values and serve only to tell
  85.  * us whether an interrupt has come in on IRQ0 or IRQ1. If
  86.  * it's IRQ1 it's a PCI interrupt; if it's IRQ0, it's
  87.  * probably ISA, but PCI interrupts can come through IRQ0
  88.  * as well if the interrupt controller isn't in accelerated
  89.  * mode.
  90.  *
  91.  * OTOH, the accelerator thing doesn't seem to be working
  92.  * overly well, so what we'll do instead is try directly
  93.  * examining the Master Interrupt Register to see if it's a
  94.  * PCI interrupt, and if _not_ then we'll pass it on to the
  95.  * ISA handler.
  96.  */
  97. intstatus = inw(0x500) & 15;
  98. if (intstatus) {
  99. /*
  100.  * This is a PCI interrupt. Check each bit and
  101.  * despatch an interrupt if it's set.
  102.  */
  103. if (intstatus & 8) handle_irq(16+3, regs);
  104. if (intstatus & 4) handle_irq(16+2, regs);
  105. if (intstatus & 2) handle_irq(16+1, regs);
  106. if (intstatus & 1) handle_irq(16+0, regs);
  107. } else {
  108. isa_device_interrupt(vector, regs);
  109. }
  110. }
  111. static void
  112. eiger_srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
  113. {
  114. int irq = (vector - 0x800) >> 4;
  115. handle_irq(irq, regs);
  116. }
  117. static void __init
  118. eiger_init_irq(void)
  119. {
  120. long i;
  121. outb(0, DMA1_RESET_REG);
  122. outb(0, DMA2_RESET_REG);
  123. outb(DMA_MODE_CASCADE, DMA2_MODE_REG);
  124. outb(0, DMA2_MASK_REG);
  125. if (alpha_using_srm)
  126. alpha_mv.device_interrupt = eiger_srm_device_interrupt;
  127. for (i = 16; i < 128; i += 16)
  128. eiger_update_irq_hw(i, -1);
  129. init_i8259a_irqs();
  130. for (i = 16; i < 128; ++i) {
  131. irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
  132. irq_desc[i].handler = &eiger_irq_type;
  133. }
  134. }
  135. static int __init
  136. eiger_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
  137. {
  138. u8 irq_orig;
  139. /* The SRM console has already calculated out the IRQ value's for
  140.    option cards. As this works lets just read in the value already
  141.    set and change it to a useable value by Linux.
  142.    All the IRQ values generated by the console are greater than 90,
  143.    so we subtract 80 because it is (90 - allocated ISA IRQ's).  */
  144. pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq_orig);
  145. return irq_orig - 0x80;
  146. }
  147. static u8 __init
  148. eiger_swizzle(struct pci_dev *dev, u8 *pinp)
  149. {
  150. struct pci_controller *hose = dev->sysdata;
  151. int slot, pin = *pinp;
  152. int bridge_count = 0;
  153. /* Find the number of backplane bridges.  */
  154. int backplane = inw(0x502) & 0x0f;
  155. switch (backplane)
  156. {
  157.    case 0x00: bridge_count = 0; break; /* No bridges */
  158.    case 0x01: bridge_count = 1; break; /* 1 */
  159.    case 0x03: bridge_count = 2; break; /* 2 */
  160.    case 0x07: bridge_count = 3; break; /* 3 */
  161.    case 0x0f: bridge_count = 4; break; /* 4 */
  162. };
  163. /*  Check first for the built-in bridges on hose 0. */
  164. if (hose->index == 0
  165.     && PCI_SLOT(dev->bus->self->devfn) > 20-bridge_count) {
  166. slot = PCI_SLOT(dev->devfn);
  167. } else {
  168. /* Must be a card-based bridge.  */
  169. do {
  170. /* Check for built-in bridges on hose 0. */
  171. if (hose->index == 0
  172.     && (PCI_SLOT(dev->bus->self->devfn)
  173. > 20 - bridge_count)) {
  174.                    slot = PCI_SLOT(dev->devfn);
  175. break;
  176. }
  177. pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
  178. /* Move up the chain of bridges.  */
  179. dev = dev->bus->self;
  180. /* Slot of the next bridge.  */
  181. slot = PCI_SLOT(dev->devfn);
  182. } while (dev->bus->self);
  183. }
  184. *pinp = pin;
  185. return slot;
  186. }
  187. /*
  188.  * The System Vectors
  189.  */
  190. struct alpha_machine_vector eiger_mv __initmv = {
  191. vector_name: "Eiger",
  192. DO_EV6_MMU,
  193. DO_DEFAULT_RTC,
  194. DO_TSUNAMI_IO,
  195. DO_TSUNAMI_BUS,
  196. machine_check: tsunami_machine_check,
  197. max_dma_address: ALPHA_MAX_DMA_ADDRESS,
  198. min_io_address: DEFAULT_IO_BASE,
  199. min_mem_address: DEFAULT_MEM_BASE,
  200. pci_dac_offset: TSUNAMI_DAC_OFFSET,
  201. nr_irqs: 128,
  202. device_interrupt: eiger_device_interrupt,
  203. init_arch: tsunami_init_arch,
  204. init_irq: eiger_init_irq,
  205. init_rtc: common_init_rtc,
  206. init_pci: common_init_pci,
  207. kill_arch: tsunami_kill_arch,
  208. pci_map_irq: eiger_map_irq,
  209. pci_swizzle: eiger_swizzle,
  210. };
  211. ALIAS_MV(eiger)