Subject: fiq

From: Philip Blundell <[email-masked]>
Date: Sat, 28 Mar 1998 19:22:30 +0000

Hi Russell.

Here's a patch against kernel 2.1 to add rudimentary support for claiming and 
releasing FIQs.  We need something like this to avoid disaster when people 
have more than one FIQ-generating device in the system.

At the moment there is no support for informing devices when the FIQ is 
available to be claimed, but we can add that later.  I think it would be good 
if something like this was included in the kernel.

By the way, did you get my mail about struct sigaction last week?  I didn't 
see a reply but I've had some trouble with my mail here in the last few days. 

p.

--- linux/arch/arm/kernel/irq.c~	Sat Mar 14 21:28:46 1998
+++ linux/arch/arm/kernel/irq.c	Sat Mar 28 18:47:49 1998
@@ -3,6 +3,7 @@
  *
  *  Copyright (C) 1992 Linus Torvalds
  *  Modifications for ARM processor Copyright (C) 1995, 1996 Russell King.
+ *  FIQ support written by Philip Blundell <[email-masked]>, 1998.
  *
  * This file contains the code used by various IRQ handling routines:
  * asking for different IRQ's should be done through these routines
@@ -34,10 +35,14 @@
 #include <asm/system.h>
 #include <asm/hardware.h>
 #include <asm/arch/irq.h>
+#include <asm/fiq.h>
+#include <asm/pgtable.h>
 
 unsigned int local_bh_count[NR_CPUS];
 unsigned int local_irq_count[NR_CPUS];
 spinlock_t irq_controller_lock;
+static struct fiq_handler *current_fiq;
+static unsigned long no_fiq_insn;
 
 #ifndef SMP
 #define irq_enter(cpu, irq)	(++local_irq_count[cpu])
@@ -98,6 +103,8 @@
 		}
 		*p++ = '\n';
 	}
+	p += sprintf(p, "FIQ:              %s\n",
+		     current_fiq?current_fiq->name:"unused");
 	return p - buf;
 }
 
@@ -332,5 +339,33 @@
 {
 	extern void init_dma(void);
 	irq_init_irq();
+	current_fiq = NULL;
+	/* Save a copy of the default FIQ handler (installed by trap_init) */
+	no_fiq_insn = *((unsigned long *)0x1c);
 	init_dma();
+}
+
+int claim_fiq(struct fiq_handler *f)
+{
+	if (current_fiq) {
+		if (current_fiq->callback == NULL || (*current_fiq->callback)())
+			return -EBUSY;
+	}
+	current_fiq = f;
+	return 0;
+}
+
+void release_fiq(struct fiq_handler *f)
+{
+	if (current_fiq != f) {
+		printk(KERN_ERR "%s tried to release FIQ when not owner!\n", 
+		       f->name);
+#ifdef CONFIG_DEBUG_ERRORS
+		__backtrace();
+#endif
+		return;
+	}
+	current_fiq = NULL;
+	*((unsigned long *)0x1c) = no_fiq_insn;
+	flush_page_to_ram(0);
 }
--- /dev/null	Sun Oct 12 19:38:15 1997
+++ linux/include/asm-arm/fiq.h	Sat Mar 28 18:08:57 1998
@@ -0,0 +1,16 @@
+/* Support for FIQ on ARM architectures.
+ * Written by Philip Blundell <[email-masked]>, 1998
+ */
+
+#ifndef __ASM_FIQ_H
+#define __ASM_FIQ_H
+
+struct fiq_handler {
+  const char *name;
+  int (*callback)(void);
+};
+
+extern int claim_fiq(struct fiq_handler *f);
+extern void release_fiq(struct fiq_handler *f);
+
+#endif
--- linux/arch/arm/kernel/dma-a5k.c~	Sun Mar 15 13:45:17 1998
+++ linux/arch/arm/kernel/dma-a5k.c	Sat Mar 28 18:16:08 1998
@@ -12,6 +12,9 @@
 #include <asm/io.h>
 #include <asm/hardware.h>
 #include <asm/pgtable.h>
+#include <asm/fiq.h>
+
+static struct fiq_handler fh = { "floppydma", NULL };
 
 #include "dma.h"
 
@@ -59,6 +62,11 @@
 			fiqhandler_start = &floppy_fiqout_start;
 			fiqhandler_length = &floppy_fiqout_end - &floppy_fiqout_start;
 		}
+		if (claim_fiq (&fh))
+		{
+			printk("floppydma: couldn't claim FIQ.\n");
+			return;
+		}
 		memcpy ((void *)0x1c, fiqhandler_start, fiqhandler_length);
 		flush_page_to_ram(0);
 		floppy_fiqsetup (dma->buf.length, __bus_to_virt(dma->buf.address), (int)PCIO_FLOPPYDMABASE);
@@ -70,8 +78,10 @@
 {
 	if (channel != DMA_VIRTUAL_FLOPPY0)
 		printk ("arch_disable_dma: invalid channel %d\n", channel);
-	else
+	else {
 		disable_irq (dma->dma_irq);
+		release_fiq (&fh);
+	}
 }
 
 __initfunc(void arch_dma_init(dma_t *dma))

unsubscribe: body of `unsubscribe linux-arm' to [email-masked]