patch-2.4.20 linux-2.4.20/arch/ppc/amiga/amiints.c
Next file: linux-2.4.20/arch/ppc/amiga/cia.c
Previous file: linux-2.4.20/arch/ppc/Makefile
Back to the patch index
Back to the overall index
- Lines: 295
- Date:
Thu Nov 28 15:53:11 2002
- Orig file:
linux-2.4.19/arch/ppc/amiga/amiints.c
- Orig date:
Mon May 21 17:04:46 2001
diff -urN linux-2.4.19/arch/ppc/amiga/amiints.c linux-2.4.20/arch/ppc/amiga/amiints.c
@@ -1,5 +1,5 @@
/*
- * BK Id: SCCS/s.amiints.c 1.8 05/21/01 00:48:24 cort
+ * BK Id: %F% %I% %G% %U% %#%
*/
/*
* linux/arch/m68k/amiga/amiints.c -- Amiga Linux interrupt handling code
@@ -42,6 +42,8 @@
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
#include <linux/kernel_stat.h>
#include <linux/init.h>
@@ -63,9 +65,6 @@
extern void cia_init_IRQ(struct ciabase *base);
extern int cia_get_irq_list(struct ciabase *base, char *buf);
-/* irq node variables for amiga interrupt sources */
-static irq_node_t *ami_irq_list[AMI_STD_IRQS];
-
unsigned short ami_intena_vals[AMI_STD_IRQS] = {
IF_VERTB, IF_COPER, IF_AUD0, IF_AUD1, IF_AUD2, IF_AUD3, IF_BLIT,
IF_DSKSYN, IF_DSKBLK, IF_RBF, IF_TBE, IF_SOFT, IF_PORTS, IF_EXTER
@@ -78,7 +77,7 @@
static void ami_badint(int irq, void *dev_id, struct pt_regs *fp)
{
- num_spurious += 1;
+/* num_spurious += 1;*/
}
/*
@@ -97,25 +96,12 @@
{
int i;
- /* initialize handlers */
- for (i = 0; i < AMI_STD_IRQS; i++) {
- if (ami_servers[i]) {
- ami_irq_list[i] = NULL;
- } else {
- ami_irq_list[i] = new_irq_node();
- ami_irq_list[i]->handler = ami_badint;
- ami_irq_list[i]->flags = 0;
- ami_irq_list[i]->dev_id = NULL;
- ami_irq_list[i]->devname = NULL;
- ami_irq_list[i]->next = NULL;
- }
- }
for (i = 0; i < AMI_IRQS; i++)
ami_ablecount[i] = 0;
/* turn off PCMCIA interrupts */
if (AMIGAHW_PRESENT(PCMCIA))
- pcmcia_disable_irq();
+ gayle.inten = GAYLE_IRQ_IDE;
/* turn off all interrupts... */
custom.intena = 0x7fff;
@@ -138,152 +124,6 @@
cia_init_IRQ(&ciab_base);
}
-static inline int amiga_insert_irq(irq_node_t **list, irq_node_t *node)
-{
- unsigned long flags;
- irq_node_t *cur;
-
- if (!node->dev_id)
- printk("%s: Warning: dev_id of %s is zero\n",
- __FUNCTION__, node->devname);
-
- save_flags(flags);
- cli();
-
- cur = *list;
-
- if (node->flags & SA_INTERRUPT) {
- if (node->flags & SA_SHIRQ)
- return -EBUSY;
- /*
- * There should never be more than one
- */
- while (cur && cur->flags & SA_INTERRUPT) {
- list = &cur->next;
- cur = cur->next;
- }
- } else {
- while (cur) {
- list = &cur->next;
- cur = cur->next;
- }
- }
-
- node->next = cur;
- *list = node;
-
- restore_flags(flags);
- return 0;
-}
-
-static inline void amiga_delete_irq(irq_node_t **list, void *dev_id)
-{
- unsigned long flags;
- irq_node_t *node;
-
- save_flags(flags);
- cli();
-
- for (node = *list; node; list = &node->next, node = *list) {
- if (node->dev_id == dev_id) {
- *list = node->next;
- /* Mark it as free. */
- node->handler = NULL;
- restore_flags(flags);
- return;
- }
- }
- restore_flags(flags);
- printk ("%s: tried to remove invalid irq\n", __FUNCTION__);
-}
-
-/*
- * amiga_request_irq : add an interrupt service routine for a particular
- * machine specific interrupt source.
- * If the addition was successful, it returns 0.
- */
-
-int amiga_request_irq(unsigned int irq,
- void (*handler)(int, void *, struct pt_regs *),
- unsigned long flags, const char *devname, void *dev_id)
-{
- irq_node_t *node;
- int error = 0;
-
- if (irq >= AMI_IRQS) {
- printk ("%s: Unknown IRQ %d from %s\n", __FUNCTION__,
- irq, devname);
- return -ENXIO;
- }
-
- if (irq >= IRQ_AMIGA_AUTO)
- return sys_request_irq(irq - IRQ_AMIGA_AUTO, handler,
- flags, devname, dev_id);
-
- if (irq >= IRQ_AMIGA_CIAA)
- return cia_request_irq(irq, handler, flags, devname, dev_id);
-
- /*
- * IRQ_AMIGA_PORTS & IRQ_AMIGA_EXTER defaults to shared,
- * we could add a check here for the SA_SHIRQ flag but all drivers
- * should be aware of sharing anyway.
- */
- if (ami_servers[irq]) {
- if (!(node = new_irq_node()))
- return -ENOMEM;
- node->handler = handler;
- node->flags = flags;
- node->dev_id = dev_id;
- node->devname = devname;
- node->next = NULL;
- error = amiga_insert_irq(&ami_irq_list[irq], node);
- } else {
- ami_irq_list[irq]->handler = handler;
- ami_irq_list[irq]->flags = flags;
- ami_irq_list[irq]->dev_id = dev_id;
- ami_irq_list[irq]->devname = devname;
- }
-
- /* enable the interrupt */
- if (irq < IRQ_AMIGA_PORTS && !ami_ablecount[irq])
- custom.intena = IF_SETCLR | ami_intena_vals[irq];
-
- return error;
-}
-
-void amiga_free_irq(unsigned int irq, void *dev_id)
-{
- if (irq >= AMI_IRQS) {
- printk ("%s: Unknown IRQ %d\n", __FUNCTION__, irq);
- return;
- }
-
- if (irq >= IRQ_AMIGA_AUTO) {
- sys_free_irq(irq - IRQ_AMIGA_AUTO, dev_id);
- return;
- }
- if (irq >= IRQ_AMIGA_CIAA) {
- cia_free_irq(irq, dev_id);
- return;
- }
-
- if (ami_servers[irq]) {
- amiga_delete_irq(&ami_irq_list[irq], dev_id);
- /* if server list empty, disable the interrupt */
- if (!ami_irq_list[irq] && irq < IRQ_AMIGA_PORTS)
- custom.intena = ami_intena_vals[irq];
- } else {
- if (ami_irq_list[irq]->dev_id != dev_id)
- printk("%s: removing probably wrong IRQ %d from %s\n",
- __FUNCTION__, irq, ami_irq_list[irq]->devname);
- ami_irq_list[irq]->handler = ami_badint;
- ami_irq_list[irq]->flags = 0;
- ami_irq_list[irq]->dev_id = NULL;
- ami_irq_list[irq]->devname = NULL;
- custom.intena = ami_intena_vals[irq];
- }
-}
-
/*
* Enable/disable a particular machine specific interrupt source.
* Note that this may affect other interrupts in case of a shared interrupt.
@@ -350,20 +190,24 @@
inline void amiga_do_irq(int irq, struct pt_regs *fp)
{
- kstat.irqs[0][SYS_IRQS + irq]++;
- ami_irq_list[irq]->handler(irq, ami_irq_list[irq]->dev_id, fp);
+ irq_desc_t *desc = irq_desc + irq;
+ struct irqaction *action = desc->action;
+
+ kstat.irqs[0][irq]++;
+ action->handler(irq, action->dev_id, fp);
}
void amiga_do_irq_list(int irq, struct pt_regs *fp)
{
- irq_node_t *node;
+ irq_desc_t *desc = irq_desc + irq;
+ struct irqaction *action;
- kstat.irqs[0][SYS_IRQS + irq]++;
+ kstat.irqs[0][irq]++;
custom.intreq = ami_intena_vals[irq];
- for (node = ami_irq_list[irq]; node; node = node->next)
- node->handler(irq, node->dev_id, fp);
+ for (action = desc->action; action; action = action->next)
+ action->handler(irq, action->dev_id, fp);
}
/*
@@ -469,9 +313,15 @@
/* The PPC irq handling links all handlers requested on the same vector
and executes them in a loop. Having ami_badint at the end of the chain
is a bad idea. */
-void (*amiga_default_handler[SYS_IRQS])(int, void *, struct pt_regs *) = {
- NULL, ami_int1, NULL, ami_int3,
- ami_int4, ami_int5, NULL, ami_int7
+struct irqaction amiga_sys_irqaction[AUTO_IRQS] = {
+ { handler: ami_badint, name: "spurious int" },
+ { handler: ami_int1, name: "int1 handler" },
+ { 0, /* CIAA */ },
+ { handler: ami_int3, name: "int3 handler" },
+ { handler: ami_int4, name: "int4 handler" },
+ { handler: ami_int5, name: "int5 handler" },
+ { 0, /* CIAB */ },
+ { handler: ami_int7, name: "int7 handler" },
};
#else
void (*amiga_default_handler[SYS_IRQS])(int, void *, struct pt_regs *) = {
@@ -479,29 +329,3 @@
ami_int4, ami_int5, ami_badint, ami_int7
};
#endif
-
-int amiga_get_irq_list(char *buf)
-{
- int i, len = 0;
- irq_node_t *node;
-
- for (i = 0; i < AMI_STD_IRQS; i++) {
- if (!(node = ami_irq_list[i]))
- continue;
- len += sprintf(buf+len, "ami %2d: %10u ", i,
- kstat.irqs[0][SYS_IRQS + i]);
- do {
- if (node->flags & SA_INTERRUPT)
- len += sprintf(buf+len, "F ");
- else
- len += sprintf(buf+len, " ");
- len += sprintf(buf+len, "%s\n", node->devname);
- if ((node = node->next))
- len += sprintf(buf+len, " ");
- } while (node);
- }
-
- len += cia_get_irq_list(&ciaa_base, buf+len);
- len += cia_get_irq_list(&ciab_base, buf+len);
- return len;
-}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)