2 * Copyright (C) 1996 Roman Zippel
4 * The concept of some functions bases on the original Amiga OS function
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file COPYING in the main directory of this archive
11 #include <linux/types.h>
12 #include <linux/kernel.h>
13 #include <linux/sched.h>
14 #include <linux/interrupt.h>
15 #include <linux/irq.h>
16 #include <linux/kernel_stat.h>
17 #include <linux/init.h>
20 #include <asm/amigahw.h>
21 #include <asm/amigaints.h>
24 volatile struct CIA
*cia
;
25 u_char icr_mask
, icr_data
;
27 int handler_irq
, cia_irq
, server_irq
;
30 &ciaa
, 0, 0, IF_PORTS
,
31 IRQ_AMIGA_AUTO_2
, IRQ_AMIGA_CIAA
,
35 &ciab
, 0, 0, IF_EXTER
,
36 IRQ_AMIGA_AUTO_6
, IRQ_AMIGA_CIAB
,
41 #define CIA_SET_BASE_ADJUST_IRQ(base, irq) \
43 if (irq >= IRQ_AMIGA_CIAB) { \
45 irq -= IRQ_AMIGA_CIAB; \
48 irq -= IRQ_AMIGA_CIAA; \
53 * Cause or clear CIA interrupts, return old interrupt status.
56 static unsigned char cia_set_irq_private(struct ciabase
*base
,
61 old
= (base
->icr_data
|= base
->cia
->icr
);
62 if (mask
& CIA_ICR_SETCLR
)
63 base
->icr_data
|= mask
;
65 base
->icr_data
&= ~mask
;
66 if (base
->icr_data
& base
->icr_mask
)
67 amiga_custom
.intreq
= IF_SETCLR
| base
->int_mask
;
68 return old
& base
->icr_mask
;
71 unsigned char cia_set_irq(unsigned int irq
, int set
)
76 if (irq
>= IRQ_AMIGA_CIAB
)
77 mask
= (1 << (irq
- IRQ_AMIGA_CIAB
));
79 mask
= (1 << (irq
- IRQ_AMIGA_CIAA
));
80 mask
|= (set
) ? CIA_ICR_SETCLR
: 0;
82 CIA_SET_BASE_ADJUST_IRQ(base
, irq
);
84 return cia_set_irq_private(base
, mask
);
87 unsigned char cia_get_irq_mask(unsigned int irq
)
91 CIA_SET_BASE_ADJUST_IRQ(base
, irq
);
93 return base
->cia
->icr
;
97 * Enable or disable CIA interrupts, return old interrupt mask.
100 static unsigned char cia_able_irq_private(struct ciabase
*base
,
105 old
= base
->icr_mask
;
106 base
->icr_data
|= base
->cia
->icr
;
107 base
->cia
->icr
= mask
;
108 if (mask
& CIA_ICR_SETCLR
)
109 base
->icr_mask
|= mask
;
111 base
->icr_mask
&= ~mask
;
112 base
->icr_mask
&= CIA_ICR_ALL
;
114 if (base
->icr_data
& base
->icr_mask
)
115 amiga_custom
.intreq
= IF_SETCLR
| base
->int_mask
;
119 unsigned char cia_able_irq(unsigned int irq
, int enable
)
121 struct ciabase
*base
;
124 if (irq
>= IRQ_AMIGA_CIAB
)
125 mask
= (1 << (irq
- IRQ_AMIGA_CIAB
));
127 mask
= (1 << (irq
- IRQ_AMIGA_CIAA
));
128 mask
|= (enable
) ? CIA_ICR_SETCLR
: 0;
130 CIA_SET_BASE_ADJUST_IRQ(base
, irq
);
132 return cia_able_irq_private(base
, mask
);
135 static void cia_handler(int irq
, void *dev_id
, struct pt_regs
*fp
)
137 struct ciabase
*base
= (struct ciabase
*)dev_id
;
139 struct irqaction
*action
;
144 desc
= irq_desc
+ irq
;
145 ints
= cia_set_irq_private(base
, CIA_ICR_ALL
);
146 amiga_custom
.intreq
= base
->int_mask
;
147 for (i
= 0; i
< CIA_IRQS
; i
++, irq
++) {
149 kstat_cpu(0).irqs
[irq
]++;
150 action
= desc
->action
;
151 action
->handler(irq
, action
->dev_id
, fp
);
156 amiga_do_irq_list(base
->server_irq
, fp
);
159 void __init
cia_init_IRQ(struct ciabase
*base
)
161 extern struct irqaction amiga_sys_irqaction
[AUTO_IRQS
];
162 struct irqaction
*action
;
164 /* clear any pending interrupt and turn off all interrupts */
165 cia_set_irq_private(base
, CIA_ICR_ALL
);
166 cia_able_irq_private(base
, CIA_ICR_ALL
);
168 /* install CIA handler */
169 action
= &amiga_sys_irqaction
[base
->handler_irq
-IRQ_AMIGA_AUTO
];
170 action
->handler
= cia_handler
;
171 action
->dev_id
= base
;
172 action
->name
= base
->name
;
173 setup_irq(base
->handler_irq
, &amiga_sys_irqaction
[base
->handler_irq
-IRQ_AMIGA_AUTO
]);
175 amiga_custom
.intena
= IF_SETCLR
| base
->int_mask
;