diff options
Diffstat (limited to 'arch/sparc64/kernel/irq.c')
-rw-r--r-- | arch/sparc64/kernel/irq.c | 157 |
1 files changed, 14 insertions, 143 deletions
diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c index 6eccb883a..598cece4e 100644 --- a/arch/sparc64/kernel/irq.c +++ b/arch/sparc64/kernel/irq.c @@ -1,4 +1,4 @@ -/* $Id: irq.c,v 1.76 1999/04/02 14:54:30 davem Exp $ +/* $Id: irq.c,v 1.78 1999/08/31 06:54:54 davem Exp $ * irq.c: UltraSparc IRQ handling/init/registry. * * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) @@ -31,11 +31,6 @@ #include <asm/hardirq.h> #include <asm/softirq.h> -#ifdef CONFIG_PCI -#include <linux/pci.h> -#include <asm/pbm.h> -#endif - /* Internal flag, should not be visible elsewhere at all. */ #define SA_IMAP_MASKED 0x100 #define SA_DMA_SYNC 0x200 @@ -79,15 +74,6 @@ struct irqaction *irq_action[NR_IRQS+1] = { NULL, NULL, NULL, NULL, NULL, NULL , NULL, NULL }; -/* Only 8-bits are available, be careful. -DaveM */ -#define IBF_DMA_SYNC 0x01 /* DMA synchronization behind PCI bridge needed. */ -#define IBF_PCI 0x02 /* Indicates PSYCHO/SCHIZO PCI interrupt. */ -#define IBF_ACTIVE 0x04 /* This interrupt is active and has a handler. */ -#define IBF_MULTI 0x08 /* On PCI, indicates shared bucket. */ - -#define __bucket(irq) ((struct ino_bucket *)(unsigned long)(irq)) -#define __irq(bucket) ((unsigned int)(unsigned long)(bucket)) - int get_irq_list(char *buf) { int i, len = 0; @@ -183,67 +169,22 @@ offset(imap_pmgmt), /* Convert Interrupt Mapping register pointer to assosciated * Interrupt Clear register pointer, SYSIO specific version. */ -static unsigned int *sysio_imap_to_iclr(unsigned int *imap) +static volatile unsigned int *sysio_imap_to_iclr(volatile unsigned int *imap) { unsigned long diff; diff = offset(iclr_unused0) - offset(imap_slot0); - return (unsigned int *) (((unsigned long)imap) + diff); + return (volatile unsigned int *) (((unsigned long)imap) + diff); } #undef offset -#ifdef CONFIG_PCI -/* PCI PSYCHO INO number to Sparc PIL level. */ -unsigned char psycho_ino_to_pil[] = { - 7, 5, 4, 2, /* PCI A slot 0 Int A, B, C, D */ - 7, 5, 4, 2, /* PCI A slot 1 Int A, B, C, D */ - 7, 5, 4, 2, /* PCI A slot 2 Int A, B, C, D */ - 7, 5, 4, 2, /* PCI A slot 3 Int A, B, C, D */ - 6, 4, 3, 1, /* PCI B slot 0 Int A, B, C, D */ - 6, 4, 3, 1, /* PCI B slot 1 Int A, B, C, D */ - 6, 4, 3, 1, /* PCI B slot 2 Int A, B, C, D */ - 6, 4, 3, 1, /* PCI B slot 3 Int A, B, C, D */ - 3, /* SCSI */ - 5, /* Ethernet */ - 8, /* Parallel Port */ - 13, /* Audio Record */ - 14, /* Audio Playback */ - 15, /* PowerFail */ - 3, /* second SCSI */ - 11, /* Floppy */ - 2, /* Spare Hardware */ - 9, /* Keyboard */ - 4, /* Mouse */ - 12, /* Serial */ - 10, /* Timer 0 */ - 11, /* Timer 1 */ - 15, /* Uncorrectable ECC */ - 15, /* Correctable ECC */ - 15, /* PCI Bus A Error */ - 15, /* PCI Bus B Error */ - 1, /* Power Management */ -}; - -/* INO number to IMAP register offset for PSYCHO external IRQ's. */ -#define psycho_offset(x) ((unsigned long)(&(((struct psycho_regs *)0)->x))) - -#define psycho_imap_offset(ino) \ - ((ino & 0x20) ? (psycho_offset(imap_scsi) + (((ino) & 0x1f) << 3)) : \ - (psycho_offset(imap_a_slot0) + (((ino) & 0x3c) << 1))) - -#define psycho_iclr_offset(ino) \ - ((ino & 0x20) ? (psycho_offset(iclr_scsi) + (((ino) & 0x1f) << 3)) : \ - (psycho_offset(iclr_a_slot0[0]) + (((ino) & 0x1f)<<3))) - -#endif - /* Now these are always passed a true fully specified sun4u INO. */ void enable_irq(unsigned int irq) { extern int this_is_starfire; struct ino_bucket *bucket = __bucket(irq); - unsigned int *imap; + volatile unsigned int *imap; unsigned long tid; imap = bucket->imap; @@ -257,7 +198,7 @@ void enable_irq(unsigned int irq) : "i" (ASI_UPA_CONFIG)); tid = ((tid & UPA_CONFIG_MID) << 9); } else { - extern unsigned int starfire_translate(unsigned int *imap, + extern unsigned int starfire_translate(volatile unsigned int *imap, unsigned int upaid); tid = (starfire_translate(imap, current->processor) << 26); @@ -278,7 +219,7 @@ void enable_irq(unsigned int irq) void disable_irq(unsigned int irq) { struct ino_bucket *bucket = __bucket(irq); - unsigned int *imap; + volatile unsigned int *imap; imap = bucket->imap; if (imap != NULL) { @@ -306,7 +247,7 @@ static struct ino_bucket pil0_dummy_bucket = { NULL, /* imap */ }; -unsigned int build_irq(int pil, int inofixup, unsigned int *iclr, unsigned int *imap) +unsigned int build_irq(int pil, int inofixup, volatile unsigned int *iclr, volatile unsigned int *imap) { struct ino_bucket *bucket; int ino; @@ -365,7 +306,7 @@ unsigned int sbus_build_irq(void *buscookie, unsigned int ino) struct sysio_regs *sregs = sbus->iommu->sysio_regs; unsigned long offset; int pil; - unsigned int *imap, *iclr; + volatile unsigned int *imap, *iclr; int sbus_level = 0; pil = sysio_ino_to_pil[ino]; @@ -380,7 +321,7 @@ unsigned int sbus_build_irq(void *buscookie, unsigned int ino) panic("BAD SYSIO IRQ offset..."); } offset += ((unsigned long)sregs); - imap = ((unsigned int *)offset); + imap = ((volatile unsigned int *)offset); /* SYSIO inconsistancy. For external SLOTS, we have to select * the right ICLR register based upon the lower SBUS irq level @@ -412,81 +353,11 @@ unsigned int sbus_build_irq(void *buscookie, unsigned int ino) iclraddr = (unsigned long) iclr; iclraddr += ((sbus_level - 1) * 8); - iclr = (unsigned int *) iclraddr; + iclr = (volatile unsigned int *) iclraddr; } return build_irq(pil, sbus_level, iclr, imap); } -#ifdef CONFIG_PCI -unsigned int psycho_build_irq(void *buscookie, int imap_off, int ino, int need_dma_sync) -{ - struct linux_psycho *psycho = (struct linux_psycho *)buscookie; - struct psycho_regs *pregs = psycho->psycho_regs; - unsigned long addr; - struct ino_bucket *bucket; - int pil; - unsigned int *imap, *iclr; - int inofixup = 0; - - pil = psycho_ino_to_pil[ino & PCI_IRQ_INO]; - - addr = (unsigned long) &pregs->imap_a_slot0; - addr = addr + imap_off; - imap = ((unsigned int *)addr) + 1; - - addr = (unsigned long) pregs; - addr += psycho_iclr_offset(ino & (PCI_IRQ_INO)); - iclr = ((unsigned int *)addr) + 1; - - if(!(ino & 0x20)) - inofixup = ino & 0x03; - - /* First check for sharing. */ - ino = (*imap & (SYSIO_IMAP_IGN | SYSIO_IMAP_INO)) + inofixup; - if (ino > NUM_IVECS) { - prom_printf("PSYCHO: Invalid INO %04x (%d:%d:%016lx:%016lx)\n", - ino, pil, inofixup, iclr, imap); - prom_halt(); - } - bucket = &ivector_table[ino]; - if(bucket->flags & IBF_ACTIVE) { - void *old_handler = bucket->irq_info; - unsigned long flags; - - if(old_handler == NULL) { - prom_printf("PSYCHO: Active bucket, but no handler.\n"); - prom_halt(); - } - save_and_cli(flags); - if((bucket->flags & IBF_MULTI) == 0) { - void **vector; - - vector = kmalloc(sizeof(void *) * 4, - GFP_KERNEL); - - /* We might have slept. */ - if((bucket->flags & IBF_MULTI) != 0) { - kfree(vector); - } else { - vector[0] = old_handler; - vector[1] = vector[2] = vector[3] = NULL; - bucket->irq_info = vector; - bucket->flags |= IBF_MULTI; - } - } - restore_flags(flags); - } else { - /* Just init the bucket */ - bucket = __bucket(build_irq(pil, inofixup, iclr, imap)); - } - if (need_dma_sync) - bucket->flags |= IBF_DMA_SYNC; - - bucket->flags |= IBF_PCI; - return __irq(bucket); -} -#endif - static void atomic_bucket_insert(struct ino_bucket *bucket) { unsigned long pstate; @@ -731,7 +602,7 @@ void free_irq(unsigned int irq, void *dev_id) *(bucket->pil + irq_action) = action->next; if(action->flags & SA_IMAP_MASKED) { - unsigned int *imap = bucket->imap; + volatile unsigned int *imap = bucket->imap; void **vector, *orig; int ent; @@ -1286,7 +1157,7 @@ static int retarget_one_irq(struct irqaction *p, int goal_cpu) { extern int this_is_starfire; struct ino_bucket *bucket = __bucket(p->mask); - unsigned int *imap = bucket->imap; + volatile unsigned int *imap = bucket->imap; unsigned int tid; /* Never change this, it causes problems on Ex000 systems. */ @@ -1296,7 +1167,7 @@ static int retarget_one_irq(struct irqaction *p, int goal_cpu) if(this_is_starfire == 0) { tid = __cpu_logical_map[goal_cpu] << 26; } else { - extern unsigned int starfire_translate(unsigned int *imap, + extern unsigned int starfire_translate(volatile unsigned int *imap, unsigned int upaid); tid = (starfire_translate(imap, __cpu_logical_map[goal_cpu]) << 26); @@ -1399,7 +1270,7 @@ void enable_prom_timer(void) prom_timers->count0 = 0; } -__initfunc(void init_IRQ(void)) +void __init init_IRQ(void) { static int called = 0; |