patch-1.3.73 linux/arch/alpha/kernel/irq.c
Next file: linux/arch/alpha/kernel/signal.c
Previous file: linux/arch/alpha/defconfig
Back to the patch index
Back to the overall index
- Lines: 243
- Date:
Mon Mar 11 13:44:46 1996
- Orig file:
v1.3.72/linux/arch/alpha/kernel/irq.c
- Orig date:
Tue Mar 5 10:10:45 1996
diff -u --recursive --new-file v1.3.72/linux/arch/alpha/kernel/irq.c linux/arch/alpha/kernel/irq.c
@@ -135,9 +135,9 @@
struct irqaction * action;
for (i = 0 ; i < NR_IRQS ; i++) {
- action = irq_action[i];
+ action = irq_action[i];
if (!action)
- continue;
+ continue;
len += sprintf(buf+len, "%2d: %8d %c %s",
i, kstat.interrupts[i],
(action->flags & SA_INTERRUPT) ? '+' : ' ',
@@ -172,36 +172,40 @@
const char * devname,
void *dev_id)
{
- struct irqaction *action, *tmp = NULL;
+ int shared = 0;
+ struct irqaction * action, **p;
unsigned long flags;
if (irq >= NR_IRQS)
return -EINVAL;
- /* don't accept requests for irq #0 */
- if (!irq)
- return -EINVAL;
if (!handler)
- return -EINVAL;
- action = irq_action[irq];
+ return -EINVAL;
+ p = irq_action + irq;
+ action = *p;
if (action) {
- if ((action->flags & SA_SHIRQ) && (irqflags & SA_SHIRQ)) {
- for (tmp = action; tmp->next; tmp = tmp->next);
- } else {
- return -EBUSY;
- }
- if ((action->flags & SA_INTERRUPT) ^ (irqflags & SA_INTERRUPT)) {
- printk("Attempt to mix fast and slow interrupts on IRQ%d denied\n", irq);
- return -EBUSY;
- }
+ /* Can't share interrupts unless both agree to */
+ if (!(action->flags & irqflags & SA_SHIRQ))
+ return -EBUSY;
+
+ /* Can't share interrupts unless both are same type */
+ if ((action->flags ^ irqflags) & SA_INTERRUPT)
+ return -EBUSY;
+
+ /* add new interrupt at end of irq queue */
+ do {
+ p = &action->next;
+ action = *p;
+ } while (action);
+ shared = 1;
}
- save_flags(flags);
- cli();
+
action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL);
- if (!action) {
- restore_flags(flags);
- return -ENOMEM;
- }
-
+ if (!action)
+ return -ENOMEM;
+
+ if (irqflags & SA_SAMPLE_RANDOM)
+ rand_initialize_irq(irq);
+
action->handler = handler;
action->flags = irqflags;
action->mask = 0;
@@ -209,61 +213,41 @@
action->next = NULL;
action->dev_id = dev_id;
- if (tmp) {
- tmp->next = action;
- } else {
- irq_action[irq] = action;
- enable_irq(irq);
- if (irq >= 8 && irq < 16) {
- enable_irq(2); /* ensure cascade is enabled too */
- }
- }
+ save_flags(flags);
+ cli();
+ *p = action;
+
+ if (!shared)
+ unmask_irq(irq);
restore_flags(flags);
return 0;
}
-
+
void free_irq(unsigned int irq, void *dev_id)
{
- struct irqaction * action = irq_action[irq];
- struct irqaction * tmp = NULL;
+ struct irqaction * action, **p;
unsigned long flags;
if (irq >= NR_IRQS) {
- printk("Trying to free IRQ%d\n", irq);
+ printk("Trying to free IRQ%d\n",irq);
return;
}
- if (!action || !action->handler) {
- printk("Trying to free free IRQ%d\n", irq);
+ for (p = irq + irq_action; (action = *p) != NULL; p = &action->next) {
+ if (action->dev_id != dev_id)
+ continue;
+
+ /* Found it - now free it */
+ save_flags(flags);
+ cli();
+ *p = action->next;
+ if (!irq[irq_action])
+ mask_irq(irq);
+ restore_flags(flags);
+ kfree(action);
return;
}
- if (dev_id) {
- for (; action; action = action->next) {
- if (action->dev_id == dev_id) break;
- tmp = action;
- }
- if (!action) {
- printk("Trying to free free shared IRQ%d\n",irq);
- return;
- }
- } else if (action->flags & SA_SHIRQ) {
- printk("Trying to free shared IRQ%d with NULL device ID\n", irq);
- return;
- }
- save_flags(flags);
- cli();
- if (action && tmp) {
- tmp->next = action->next;
- } else {
- irq_action[irq] = action->next;
- }
- kfree_s(action, sizeof(struct irqaction));
-
- if (!irq_action[irq]) {
- mask_irq(irq);
- }
-
- restore_flags(flags);
+ printk("Trying to free free IRQ%d\n",irq);
}
static inline void handle_nmi(struct pt_regs * regs)
@@ -281,9 +265,9 @@
printk("PC = %016lx PS=%04lx\n", regs->pc, regs->ps);
printk("Expecting: ");
for (i = 0; i < 16; i++)
- if ((action = irq_action[i]))
- while (action->handler) {
- printk("[%s:%d] ", action->name, i);
+ if ((action = irq_action[i]))
+ while (action->handler) {
+ printk("[%s:%d] ", action->name, i);
action = action->next;
}
printk("\n");
@@ -303,12 +287,12 @@
kstat.interrupts[irq]++;
if (!action) {
- unexpected_irq(irq, regs);
- return;
+ unexpected_irq(irq, regs);
+ return;
}
do {
- action->handler(irq, action->dev_id, regs);
- action = action->next;
+ action->handler(irq, action->dev_id, regs);
+ action = action->next;
} while (action);
}
@@ -326,10 +310,10 @@
if (action) {
/* quick interrupts get executed with no extra overhead */
if (action->flags & SA_INTERRUPT) {
- while (action) {
- action->handler(irq, action->dev_id, regs);
- action = action->next;
- }
+ while (action) {
+ action->handler(irq, action->dev_id, regs);
+ action = action->next;
+ }
ack_irq(ack);
return;
}
@@ -369,7 +353,7 @@
#elif defined(CONFIG_ALPHA_ALCOR)
# define IACK_SC ALCOR_IACK_SC
#else
- /*
+ /*
* This is bogus but necessary to get it to compile
* on all platforms. If you try to use this on any
* other than the intended platforms, you'll notice
@@ -390,10 +374,10 @@
j = *(volatile int *) IACK_SC;
j &= 0xff;
if (j == 7) {
- if (!(inb(0x20) & 0x80)) {
- /* it's only a passive release... */
- return;
- }
+ if (!(inb(0x20) & 0x80)) {
+ /* it's only a passive release... */
+ return;
+ }
}
device_interrupt(j, j, regs);
#else
@@ -558,7 +542,7 @@
unsigned int i;
for (i = NR_IRQS - 1; i > 0; i--) {
- action = irq_action[i];
+ action = irq_action[i];
if (!action) {
enable_irq(i);
irqs |= (1 << i);
@@ -679,4 +663,5 @@
outb(cache_26, 0x26);
outb(cache_27, 0x27);
#endif
+ enable_irq(2); /* enable cascade */
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov
with Sam's (original) version of this