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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * BK Id: %F% %I% %G% %U% %#%
  3.  */
  4. /*
  5.  *  linux/arch/m68k/amiga/cia.c - CIA support
  6.  *
  7.  *  Copyright (C) 1996 Roman Zippel
  8.  *
  9.  *  The concept of some functions bases on the original Amiga OS function
  10.  *
  11.  * This file is subject to the terms and conditions of the GNU General Public
  12.  * License.  See the file COPYING in the main directory of this archive
  13.  * for more details.
  14.  */
  15. #include <linux/types.h>
  16. #include <linux/kernel.h>
  17. #include <linux/sched.h>
  18. #include <linux/interrupt.h>
  19. #include <linux/irq.h>
  20. #include <linux/kernel_stat.h>
  21. #include <linux/init.h>
  22. #include <asm/irq.h>
  23. #include <asm/amigahw.h>
  24. #include <asm/amigaints.h>
  25. struct ciabase {
  26. volatile struct CIA *cia;
  27. u_char icr_mask, icr_data;
  28. u_short int_mask;
  29. int handler_irq, cia_irq, server_irq;
  30. char *name;
  31. } ciaa_base = {
  32. &ciaa, 0, 0, IF_PORTS,
  33. IRQ_AMIGA_AUTO_2, IRQ_AMIGA_CIAA,
  34. IRQ_AMIGA_PORTS,
  35. "CIAA handler"
  36. }, ciab_base = {
  37. &ciab, 0, 0, IF_EXTER,
  38. IRQ_AMIGA_AUTO_6, IRQ_AMIGA_CIAB,
  39. IRQ_AMIGA_EXTER,
  40. "CIAB handler"
  41. };
  42. #define CIA_SET_BASE_ADJUST_IRQ(base, irq)
  43. do {
  44. if (irq >= IRQ_AMIGA_CIAB) {
  45. base = &ciab_base;
  46. irq -= IRQ_AMIGA_CIAB;
  47. } else {
  48. base = &ciaa_base;
  49. irq -= IRQ_AMIGA_CIAA;
  50. }
  51. } while (0)
  52. /*
  53.  *  Cause or clear CIA interrupts, return old interrupt status.
  54.  */
  55. static unsigned char cia_set_irq_private(struct ciabase *base,
  56.  unsigned char mask)
  57. {
  58. u_char old;
  59. old = (base->icr_data |= base->cia->icr);
  60. if (mask & CIA_ICR_SETCLR)
  61. base->icr_data |= mask;
  62. else
  63. base->icr_data &= ~mask;
  64. if (base->icr_data & base->icr_mask)
  65. custom.intreq = IF_SETCLR | base->int_mask;
  66. return old & base->icr_mask;
  67. }
  68. unsigned char cia_set_irq(unsigned int irq, int set)
  69. {
  70. struct ciabase *base;
  71. unsigned char mask;
  72. if (irq >= IRQ_AMIGA_CIAB)
  73. mask = (1 << (irq - IRQ_AMIGA_CIAB));
  74. else
  75. mask = (1 << (irq - IRQ_AMIGA_CIAA));
  76. mask |= (set) ? CIA_ICR_SETCLR : 0;
  77. CIA_SET_BASE_ADJUST_IRQ(base, irq);
  78. return cia_set_irq_private(base, mask);
  79. }
  80. unsigned char cia_get_irq_mask(unsigned int irq)
  81. {
  82. struct ciabase *base;
  83. CIA_SET_BASE_ADJUST_IRQ(base, irq);
  84. return base->cia->icr;
  85. }
  86. /*
  87.  *  Enable or disable CIA interrupts, return old interrupt mask.
  88.  */
  89. static unsigned char cia_able_irq_private(struct ciabase *base,
  90.   unsigned char mask)
  91. {
  92. u_char old;
  93. old = base->icr_mask;
  94. base->icr_data |= base->cia->icr;
  95. base->cia->icr = mask;
  96. if (mask & CIA_ICR_SETCLR)
  97. base->icr_mask |= mask;
  98. else
  99. base->icr_mask &= ~mask;
  100. base->icr_mask &= CIA_ICR_ALL;
  101. if (base->icr_data & base->icr_mask)
  102. custom.intreq = IF_SETCLR | base->int_mask;
  103. return old;
  104. }
  105. unsigned char cia_able_irq(unsigned int irq, int enable)
  106. {
  107. struct ciabase *base;
  108. unsigned char mask;
  109. if (irq >= IRQ_AMIGA_CIAB)
  110. mask = (1 << (irq - IRQ_AMIGA_CIAB));
  111. else
  112. mask = (1 << (irq - IRQ_AMIGA_CIAA));
  113. mask |= (enable) ? CIA_ICR_SETCLR : 0;
  114. CIA_SET_BASE_ADJUST_IRQ(base, irq);
  115. return cia_able_irq_private(base, mask);
  116. }
  117. static void cia_handler(int irq, void *dev_id, struct pt_regs *fp)
  118. {
  119. struct ciabase *base = (struct ciabase *)dev_id;
  120. irq_desc_t *desc;
  121. struct irqaction *action;
  122. int i;
  123. unsigned char ints;
  124. irq = base->cia_irq;
  125. desc = irq_desc + irq;
  126. ints = cia_set_irq_private(base, CIA_ICR_ALL);
  127. custom.intreq = base->int_mask;
  128. for (i = 0; i < CIA_IRQS; i++, irq++) {
  129. if (ints & 1) {
  130. kstat.irqs[0][irq]++;
  131. action = desc->action;
  132. action->handler(irq, action->dev_id, fp);
  133. }
  134. ints >>= 1;
  135. desc++;
  136. }
  137. amiga_do_irq_list(base->server_irq, fp);
  138. }
  139. void __init cia_init_IRQ(struct ciabase *base)
  140. {
  141. extern struct irqaction amiga_sys_irqaction[AUTO_IRQS];
  142. struct irqaction *action;
  143. /* clear any pending interrupt and turn off all interrupts */
  144. cia_set_irq_private(base, CIA_ICR_ALL);
  145. cia_able_irq_private(base, CIA_ICR_ALL);
  146. /* install CIA handler */
  147. action = &amiga_sys_irqaction[base->handler_irq-IRQ_AMIGA_AUTO];
  148. action->handler = cia_handler;
  149. action->dev_id = base;
  150. action->name = base->name;
  151. setup_irq(base->handler_irq, &amiga_sys_irqaction[base->handler_irq-IRQ_AMIGA_AUTO]);
  152. custom.intena = IF_SETCLR | base->int_mask;
  153. }