Resent-Date: Mon, 30 Aug 1999 20:30:25 +0200 (MET DST)
Date: Mon, 30 Aug 1999 20:30:01 +0200 (MET DST)
From: Roman Zippel <zippel@fh-brandenburg.de>
X-Sender: zippel@zeus
To: Linux/m68k <linux-m68k@lists.linux-m68k.org>
Subject: experimental patch for 2.3.14
Resent-From: linux-m68k@phil.uni-sb.de

Hi,

This patch implements basically two things - realtime interrupts and a
system call stack. The realtime interrupts are not very useful yet, but as
a side effect they implement something else - slow interrupts. As Jes
version immediatly blows up on my computer with a stack overflow, what is
very likely also the reason for Geert's crash. (I'm running a serial
console at 56000bps, so it immediatly crashes after mounting root).
Anyway, this is a safe version of slow interrupts (I hope), I don't
execute them immediatly, instead I'm running them after the fast
interrupts.
The system call stack patch moves the registers d2-d5 to the switch stack,
so that the registers d1-d5 for the arguments only saved for system calls
and immediatly dropped after them, so that normal system calls and
interrupts are slightly faster now.
It's not a realease version yet, so just look at it, try it and tell me
what you think.

bye, Roman

diff -Nur -X /opt/home/roman/src/m68k_nodiff linux-2.3.14/arch/m68k/amiga/amiints.c linux-rtl/arch/m68k/amiga/amiints.c
--- linux-2.3.14/arch/m68k/amiga/amiints.c	Fri Aug 20 20:46:51 1999
+++ linux-rtl/arch/m68k/amiga/amiints.c	Sun Aug 29 20:16:42 1999
@@ -19,31 +19,20 @@
  *                           called again.
  *           The whole interrupt handling for CIAs is moved to cia.c
  *           /Roman Zippel
- *
- * 07/08/99: rewamp of the interrupt handling - we now have two types of
- *           interrupts, normal and fast handlers, fast handlers being
- *           marked with SA_INTERRUPT and runs with all other interrupts
- *           disabled. Normal interrupts disable their own source but
- *           run with all other interrupt sources enabled.
- *           PORTS and EXTER interrupts are always shared even if the
- *           drivers do not explicitly mark this when calling
- *           request_irq which they really should do.
- *           This is similar to the way interrupts are handled on all
- *           other architectures and makes a ton of sense besides
- *           having the advantage of making it easier to share
- *           drivers.
- *           /Jes
  */
 
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
 #include <linux/kernel_stat.h>
 #include <linux/init.h>
 
 #include <asm/system.h>
 #include <asm/irq.h>
 #include <asm/traps.h>
+#include <asm/pgtable.h>
 #include <asm/amigahw.h>
 #include <asm/amigaints.h>
 #include <asm/amipcmcia.h>
@@ -52,26 +41,25 @@
                            void (*handler)(int, void *, struct pt_regs *),
                            unsigned long flags, const char *devname, void *dev_id);
 extern void cia_free_irq(struct ciabase *base, unsigned int irq, void *dev_id);
-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];
+extern void cia_init_IRQ(void);
 
 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
+	IF_TBE, IF_DSKBLK, IF_SOFT, IF_PORTS, IF_COPPER, IF_VERTB, IF_BLIT,
+	IF_AUD0, IF_AUD1, IF_AUD2, IF_AUD3, IF_RBF, IF_DSKSYN, IF_EXTER
 };
-static const unsigned char ami_servers[AMI_STD_IRQS] = {
-	1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1
+static const unsigned char ami_servers[AMI_IRQS] = {
+	0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0
 };
 
 static short ami_ablecount[AMI_IRQS];
 
-static void ami_badint(int irq, void *dev_id, struct pt_regs *fp)
-{
-	num_spurious += 1;
-}
+static void ami_int1(int irq, void *dev_id, struct pt_regs *fp);
+static void ami_int2(int irq, void *dev_id, struct pt_regs *fp);
+static void ami_int3(int irq, void *dev_id, struct pt_regs *fp);
+static void ami_int4(int irq, void *dev_id, struct pt_regs *fp);
+static void ami_int5(int irq, void *dev_id, struct pt_regs *fp);
+static void ami_int6(int irq, void *dev_id, struct pt_regs *fp);
 
 /*
  * void amiga_init_IRQ(void)
@@ -88,22 +76,11 @@
 {
 	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;
 
+	vectors[VEC_INT7] = amiga_nmi_handler;
+
 	/* turn off PCMCIA interrupts */
 	if (AMIGAHW_PRESENT(PCMCIA))
 		pcmcia_disable_irq();
@@ -113,66 +90,18 @@
 	custom.intreq = 0x7fff;
 	custom.intena = IF_SETCLR | IF_INTEN;
 
-	cia_init_IRQ(&ciaa_base);
-	cia_init_IRQ(&ciab_base);
-}
-
-static inline void 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;
-		/*
-		 * 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);
-}
-
-static inline void amiga_delete_irq(irq_node_t **list, void *dev_id)
-{
-	unsigned long flags;
-	irq_node_t *node;
-
-	save_flags(flags);
-	cli();
+#ifdef CONFIG_RT_INTERRUPT
+	mach_do_slowirq = amiga_do_slowirq_request;
+#endif
+
+	request_irq(IRQ_AMIGA_AUTO_1, ami_int1, IRQ_FLG_REALTIME, "int1 handler", NULL);
+	request_irq(IRQ_AMIGA_AUTO_2, ami_int2, IRQ_FLG_REALTIME, "int2 handler", NULL);
+	request_irq(IRQ_AMIGA_AUTO_3, ami_int3, IRQ_FLG_REALTIME, "int3 handler", NULL);
+	request_irq(IRQ_AMIGA_AUTO_4, ami_int4, IRQ_FLG_REALTIME, "int4 handler", NULL);
+	request_irq(IRQ_AMIGA_AUTO_5, ami_int5, IRQ_FLG_REALTIME, "int5 handler", NULL);
+	request_irq(IRQ_AMIGA_AUTO_6, ami_int6, IRQ_FLG_REALTIME, "int6 handler", NULL);
 
-	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__);
+	cia_init_IRQ();
 }
 
 /*
@@ -181,18 +110,35 @@
  *                     If the addition was successful, it returns 0.
  */
 
-int amiga_request_irq(unsigned int irq,
-		      void (*handler)(int, void *, struct pt_regs *),
+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;
+	unsigned int vec;
+	int res;
 
 	if (irq >= AMI_IRQS) {
-		printk ("%s: Unknown IRQ %d from %s\n", __FUNCTION__,
-			irq, devname);
+		printk ("%s: Unknown IRQ %d from %s\n", __FUNCTION__, irq, devname);
 		return -ENXIO;
 	}
 
+	flags &= ~IRQ_FLG_LIST;
+	if (flags & SA_INTERRUPT)
+		flags |= IRQ_FLG_FAST;
+#ifndef CONFIG_RT_INTERRUPT
+	if (flags & IRQ_FLG_REALTIME)
+		flags |= IRQ_FLG_FAST;
+#endif
+
+	if (irq >= IRQ_AMIGA_AUTO) {
+		vec = irq - IRQ_AMIGA_AUTO + VEC_SPUR;
+
+		res = sys_request_irq(vec, handler, flags, devname, dev_id);
+		if (!res)
+			vectors[vec] = amiga_inthandler;
+
+		return res;
+	}
+
 	if (irq >= IRQ_AMIGA_AUTO)
 		return sys_request_irq(irq - IRQ_AMIGA_AUTO, handler,
 		                       flags, devname, dev_id);
@@ -205,43 +151,43 @@
 		return cia_request_irq(&ciaa_base, irq - IRQ_AMIGA_CIAA,
 		                       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;
-		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;
+	vec = irq + VEC_USER;
+	if (ami_servers[irq])
+		flags |= IRQ_FLG_LIST;
+
+	res = sys_request_irq(vec, handler, flags, devname, dev_id);
+	if (!res) {
+		if (flags & IRQ_FLG_FASTQUEUE)
+			amiga_fastintmask |= 1 << irq;
+		else
+			amiga_slowintmask |= 1 << irq;
+		flush_icache_range((unsigned long)&amiga_slowintmask,
+		                   ((unsigned long)&amiga_fastintmask)+2);
+		/* enable the interrupt */
+		if (!ami_ablecount[irq])
+			custom.intena = IF_SETCLR | ami_intena_vals[irq];
 	}
 
-	/* enable the interrupt */
-	if (irq < IRQ_AMIGA_PORTS && !ami_ablecount[irq])
-		custom.intena = IF_SETCLR | ami_intena_vals[irq];
-
 	return 0;
 }
 
 void amiga_free_irq(unsigned int irq, void *dev_id)
 {
+	unsigned int vec;
+
 	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);
+	if (irq >= IRQ_AMIGA_AUTO) {
+		vec = irq - IRQ_AMIGA_AUTO + VEC_SPUR;
+
+		sys_free_irq(vec, dev_id);
+		vectors[vec] = bad_interrupt;
+
+		return;
+	}
 
 	if (irq >= IRQ_AMIGA_CIAB) {
 		cia_free_irq(&ciab_base, irq - IRQ_AMIGA_CIAB, dev_id);
@@ -253,21 +199,18 @@
 		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;
+	vec = irq + VEC_USER;
+	sys_free_irq(vec, dev_id);
+
+	/* if list empty, disable the interrupt */
+	if (!userirq_list[irq])
+		amiga_fastintmask &= ~(1 << irq);
+	if (!userirq_slowlist[irq])
+		amiga_slowintmask &= ~(1 << irq);
+	flush_icache_range((unsigned long)&amiga_slowintmask,
+		((unsigned long)&amiga_fastintmask)+2);
+	if (!userirq_list[irq] && !userirq_slowlist[irq])
 		custom.intena = ami_intena_vals[irq];
-	}
 }
 
 /*
@@ -344,79 +287,12 @@
 	custom.intena = ami_intena_vals[irq];
 }
 
-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);
-}
-
-void amiga_do_irq_list(int irq, struct pt_regs *fp, struct irq_server *server)
-{
-	irq_node_t *node, *slow_nodes;
-	unsigned short flags, intena;
-
-	kstat.irqs[0][SYS_IRQS + irq]++;
-	if (server->count++)
-		server->reentrance = 1;
-
-	intena = ami_intena_vals[irq];
-	custom.intreq = intena;
-
-	/* serve first fast handlers - there can only be one of these */
-	node = ami_irq_list[irq];
-
-	/*
-	 * Timer interrupts show up like this
-	 */
-	if (!node) {
-		server->count--;
-		return;
-	}
-
-	if (node && (node->flags & SA_INTERRUPT)) {
-		save_flags(flags);
-		cli();
-		node->handler(irq, node->dev_id, fp);
-		restore_flags(flags);
-
-		server->count--;
-		return;
-	}
-
-	/*
-	 * Disable the interrupt source in question and reenable all
-	 * other interrupts. No interrupt handler should ever touch
-	 * the intena flags directly!
-	 */
-	custom.intena = intena;
-	save_flags(flags);
-	sti();
-
-	slow_nodes = node;
-	for (;;) {
-		for (; node; node = node->next)
-			node->handler(irq, node->dev_id, fp);
-
-		if (!server->reentrance) {
-			server->count--;
-			restore_flags(flags);
-			custom.intena = IF_SETCLR | intena;
-			return;
-		}
-
-		server->reentrance = 0;
-		node = slow_nodes;
-	}
-}
-
 /*
  * The builtin Amiga hardware interrupt handlers.
  */
 
-static void ami_int1(int irq, void *dev_id, struct pt_regs *fp)
+static void ami_int1(int ints, void *dev_id, struct pt_regs *fp)
 {
-	unsigned short ints = custom.intreqr & custom.intenar;
-
 	/* if serial transmit buffer empty, interrupt */
 	if (ints & IF_TBE) {
 		custom.intreq = IF_TBE;
@@ -436,11 +312,16 @@
 	}
 }
 
-static void ami_int3(int irq, void *dev_id, struct pt_regs *fp)
+static void ami_int2(int ints, void *dev_id, struct pt_regs *fp)
 {
-	unsigned short ints = custom.intreqr & custom.intenar;
-	static struct irq_server server = {0, 0};
+	if (ints & IF_PORTS) {
+		custom.intreq = IF_PORTS;
+		amiga_do_irq_list(IRQ_AMIGA_PORTS, fp);
+	}
+}
 
+static void ami_int3(int ints, void *dev_id, struct pt_regs *fp)
+{
 	/* if a blitter interrupt */
 	if (ints & IF_BLIT) {
 		custom.intreq = IF_BLIT;
@@ -448,20 +329,20 @@
 	}
 
 	/* if a copper interrupt */
-	if (ints & IF_COPER) {
-		custom.intreq = IF_COPER;
+	if (ints & IF_COPPER) {
+		custom.intreq = IF_COPPER;
 		amiga_do_irq(IRQ_AMIGA_COPPER, fp);
 	}
 
 	/* if a vertical blank interrupt */
-	if (ints & IF_VERTB)
-		amiga_do_irq_list(IRQ_AMIGA_VERTB, fp, &server);
+	if (ints & IF_VERTB) {
+		custom.intreq = IF_VERTB;
+		amiga_do_irq_list(IRQ_AMIGA_VERTB, fp);
+	}
 }
 
-static void ami_int4(int irq, void *dev_id, struct pt_regs *fp)
+static void ami_int4(int ints, void *dev_id, struct pt_regs *fp)
 {
-	unsigned short ints = custom.intreqr & custom.intenar;
-
 	/* if audio 0 interrupt */
 	if (ints & IF_AUD0) {
 		custom.intreq = IF_AUD0;
@@ -487,10 +368,8 @@
 	}
 }
 
-static void ami_int5(int irq, void *dev_id, struct pt_regs *fp)
+static void ami_int5(int ints, void *dev_id, struct pt_regs *fp)
 {
-	unsigned short ints = custom.intreqr & custom.intenar;
-
 	/* if serial receive buffer full interrupt */
 	if (ints & IF_RBF) {
 		/* acknowledge of IF_RBF must be done by the serial interrupt */
@@ -504,38 +383,64 @@
 	}
 }
 
-static void ami_int7(int irq, void *dev_id, struct pt_regs *fp)
+static void ami_int6(int ints, void *dev_id, struct pt_regs *fp)
 {
-	panic ("level 7 interrupt received\n");
+	if (ints & IF_EXTER) {
+		custom.intreq = IF_EXTER;
+		amiga_do_irq_list(IRQ_AMIGA_EXTER, fp);
+	}
 }
 
-void (*amiga_default_handler[SYS_IRQS])(int, void *, struct pt_regs *) = {
-	ami_badint, ami_int1, ami_badint, ami_int3,
-	ami_int4, ami_int5, ami_badint, ami_int7
-};
-
-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;
+#ifdef CONFIG_RT_INTERRUPT
+rt_lockdefine(rtirq_lock);
+#endif
+
+void amiga_do_slowirq_request(void)
+{
+	int old_mask, old_request, irq;
+	static struct pt_regs dummy_regs;
+#ifdef CONFIG_RT_INTERRUPT
+	int oldcnt;
+	rt_flagsdefine;
+
+again:
+	rt_exchange(rtirq_lock, &slowirq_request, old_request, 0);
+#else
+	old_request = xchg(&slowirq_request, 0);
+#endif
+	old_mask = old_request;
+	custom.intreq = old_mask & (0x3fff & ~IF_RBF);
+	while (old_request) {
+#ifdef CONFIG_APUS
+#else
+		asm ("bfffo %1{#0,#32},%0; bfclr %1{%0,#1}"
+		     : "=&d" (irq), "=d" (old_request)
+		     : "1" (old_request): "cc");
+		irq = 31 - irq;
+#endif
+		if (ami_servers[irq])
+			amiga_do_slowirq_list(irq, &dummy_regs);
+		else
+			amiga_do_slowirq(irq, &dummy_regs);
+	}
+	custom.intena = IF_SETCLR | (old_mask & 0x3fff);
+	if ((old_mask >>= AMI_STD_IRQS)) {
+		cia_able_irq(&ciaa_base, CIA_ICR_SETCLR | (old_mask & CIA_ICR_ALL));
+		if ((old_mask >>= CIA_IRQS))
+			cia_able_irq(&ciab_base, CIA_ICR_SETCLR | old_mask);
+	}
+	if (bh_active & bh_mask)
+		do_bottom_half();
+
+#ifdef CONFIG_RT_INTERRUPT
+	slowirq_enable = 1;
+
+	/* increment slowirq_busycnt, it must get 1 again */
+	rt_exchange(rtirq_lock, &slowirq_busycnt, oldcnt, oldcnt + 1);
+	if (oldcnt) {
+		/* set it to 0 and hope no interrupts disturbs us this time */
+		slowirq_busycnt = 0;
+		goto again;
+	}
+#endif
 }
diff -Nur -X /opt/home/roman/src/m68k_nodiff linux-2.3.14/arch/m68k/amiga/cia.c linux-rtl/arch/m68k/amiga/cia.c
--- linux-2.3.14/arch/m68k/amiga/cia.c	Fri Aug 20 20:46:52 1999
+++ linux-rtl/arch/m68k/amiga/cia.c	Sun Aug 29 12:01:13 1999
@@ -18,27 +18,24 @@
 #include <linux/init.h>
 
 #include <asm/irq.h>
+#include <asm/traps.h>
+#include <asm/system.h>
 #include <asm/amigahw.h>
 #include <asm/amigaints.h>
 
 struct ciabase {
 	volatile struct CIA *cia;
-	u_char icr_mask, icr_data;
+	int cia_irq;
 	u_short int_mask;
-	int handler_irq, cia_irq, server_irq;
-	char *name;
-	struct irq_server server;
-	irq_handler_t irq_list[CIA_IRQS];
+	u_char allocmask, pad;
+	u_char icr_mask, icr_data;
+	u_char fastmask, slowmask;
 } ciaa_base = {
-	&ciaa, 0, 0, IF_PORTS,
-	IRQ_AMIGA_AUTO_2, IRQ_AMIGA_CIAA,
-	IRQ_AMIGA_PORTS,
-	"CIAA handler", {0, 0}
+	&ciaa, IRQ_AMIGA_CIAA,
+	IF_PORTS, CIA_ICR_ALL, 0, 0, 0, 0, 0
 }, ciab_base = {
-	&ciab, 0, 0, IF_EXTER,
-	IRQ_AMIGA_AUTO_6, IRQ_AMIGA_CIAB,
-	IRQ_AMIGA_EXTER,
-	"CIAB handler", {0, 0}
+	&ciab, IRQ_AMIGA_CIAB,
+	IF_EXTER, CIA_ICR_ALL, 0, 0, 0, 0, 0
 };
 
 /*
@@ -66,23 +63,17 @@
 
 unsigned char cia_able_irq(struct ciabase *base, unsigned char mask)
 {
-	u_char old, tmp;
-	int i;
+	u_char old;
 
 	old = base->icr_mask;
 	base->icr_data |= base->cia->icr;
+	mask &= CIA_ICR_SETCLR | base->allocmask;
 	base->cia->icr = mask;
 	if (mask & CIA_ICR_SETCLR)
 		base->icr_mask |= mask;
 	else
 		base->icr_mask &= ~mask;
 	base->icr_mask &= CIA_ICR_ALL;
-	for (i = 0, tmp = 1; i < CIA_IRQS; i++, tmp <<= 1) {
-		if ((tmp & base->icr_mask) && !base->irq_list[i].handler) {
-			base->icr_mask &= ~tmp;
-			base->cia->icr = tmp;
-		}
-	}
 	if (base->icr_data & base->icr_mask)
 		custom.intreq = IF_SETCLR | base->int_mask;
 	return old;
@@ -92,83 +83,87 @@
                     void (*handler)(int, void *, struct pt_regs *),
                     unsigned long flags, const char *devname, void *dev_id)
 {
+	unsigned int vec;
+	int res;
 	u_char mask;
 
-	base->irq_list[irq].handler = handler;
-	base->irq_list[irq].flags   = flags;
-	base->irq_list[irq].dev_id  = dev_id;
-	base->irq_list[irq].devname = devname;
+	vec = VEC_USER + base->cia_irq + irq;
+	res = sys_request_irq(vec, handler, flags, devname, dev_id);
 
-	/* enable the interrupt */
-	mask = 1 << irq;
-	cia_set_irq(base, mask);
-	cia_able_irq(base, CIA_ICR_SETCLR | mask);
+	if (!res) {
+		mask = 1 << irq;
+		if (flags & IRQ_FLG_FASTQUEUE)
+			base->fastmask |= mask;
+		else
+			base->slowmask |= mask;
+		/* enable the interrupt */
+		base->allocmask |= mask;
+		cia_set_irq(base, mask);
+		cia_able_irq(base, CIA_ICR_SETCLR | mask);
+	}
 	return 0;
 }
 
 void cia_free_irq(struct ciabase *base, unsigned int irq, void *dev_id)
 {
-	if (base->irq_list[irq].dev_id != dev_id)
-		printk("%s: removing probably wrong IRQ %i from %s\n",
-		       __FUNCTION__, base->cia_irq + irq,
-		       base->irq_list[irq].devname);
+	unsigned int vec;
+	u_char mask;
 
-	base->irq_list[irq].handler = NULL;
-	base->irq_list[irq].flags   = 0;
+	vec = VEC_USER + base->cia_irq + irq;
+	sys_free_irq(vec, dev_id);
 
-	cia_able_irq(base, 1 << irq);
+	mask = 1 << irq;
+	if (!userirq_list[base->cia_irq + irq])
+		base->fastmask &= ~mask;
+	if (!userirq_slowlist[base->cia_irq + irq])
+		base->slowmask &= ~mask;
+	if (!userirq_list[base->cia_irq + irq] &&
+	    !userirq_slowlist[base->cia_irq + irq]) {
+		cia_able_irq(base, mask);
+		base->allocmask &= ~mask;
+	}
 }
 
 static void cia_handler(int irq, void *dev_id, struct pt_regs *fp)
 {
 	struct ciabase *base = (struct ciabase *)dev_id;
-	int mach_irq, i;
-	unsigned char ints;
+	unsigned char ints, slowints;
 
-	mach_irq = base->cia_irq;
-	irq = SYS_IRQS + mach_irq;
 	ints = cia_set_irq(base, CIA_ICR_ALL);
+	if ((slowints = ints & base->slowmask)) {
+		set_slowirq_request(slowints << base->cia_irq);
+		cia_able_irq(base, slowints);
+	}
+	ints &= base->fastmask;
+
 	custom.intreq = base->int_mask;
-	for (i = 0; i < CIA_IRQS; i++, irq++, mach_irq++) {
-		if (ints & 1) {
-			kstat.irqs[0][irq]++;
-			base->irq_list[i].handler(mach_irq, base->irq_list[i].dev_id, fp);
+	if ( ints ) {
+		unsigned int irq = base->cia_irq + CIA_IRQS - 1;
+		irq_node_t **list = &userirq_list[irq];
+		unsigned int *stat = &kstat.irqs[0][irq + AUTO_IRQ_NR];
+		for (ints <<= 3; ints; ints <<= 1) {
+			if ( ints & 0x80 ) {
+				(*stat)++;
+				(*list)->handler(irq, (*list)->dev_id, fp);
+			}
+			stat--; list--; irq--;
 		}
-		ints >>= 1;
 	}
-	amiga_do_irq_list(base->server_irq, fp, &base->server);
 }
 
-void __init cia_init_IRQ(struct ciabase *base)
+void __init cia_init_IRQ(void)
 {
-	int i;
-
-	/* init isr handlers */
-	for (i = 0; i < CIA_IRQS; i++) {
-		base->irq_list[i].handler = NULL;
-		base->irq_list[i].flags   = 0;
-	}
-
 	/* clear any pending interrupt and turn off all interrupts */
-	cia_set_irq(base, CIA_ICR_ALL);
-	cia_able_irq(base, CIA_ICR_ALL);
+	cia_set_irq(&ciaa_base, CIA_ICR_ALL);
+	cia_able_irq(&ciaa_base, CIA_ICR_ALL);
+	cia_set_irq(&ciab_base, CIA_ICR_ALL);
+	cia_able_irq(&ciab_base, CIA_ICR_ALL);
+	ciaa_base.allocmask = ciab_base.allocmask = 0;
 
 	/* install CIA handler */
-	request_irq(base->handler_irq, cia_handler, 0, base->name, base);
+	request_irq(IRQ_AMIGA_PORTS, cia_handler, IRQ_FLG_FAST|IRQ_FLG_REALTIME,
+	            "ciaa handler", &ciaa_base);
+	request_irq(IRQ_AMIGA_EXTER, cia_handler, IRQ_FLG_FAST|IRQ_FLG_REALTIME,
+	            "ciab handler", &ciab_base);
 
-	custom.intena = IF_SETCLR | base->int_mask;
-}
-
-int cia_get_irq_list(struct ciabase *base, char *buf)
-{
-	int i, j, len = 0;
-
-	j = base->cia_irq;
-	for (i = 0; i < CIA_IRQS; i++) {
-		len += sprintf(buf+len, "cia  %2d: %10d ", j + i,
-			       kstat.irqs[0][SYS_IRQS + j + i]);
-			len += sprintf(buf+len, "  ");
-		len += sprintf(buf+len, "%s\n", base->irq_list[i].devname);
-	}
-	return len;
 }
diff -Nur -X /opt/home/roman/src/m68k_nodiff linux-2.3.14/arch/m68k/amiga/config.c linux-rtl/arch/m68k/amiga/config.c
--- linux-2.3.14/arch/m68k/amiga/config.c	Fri Aug 20 20:46:53 1999
+++ linux-rtl/arch/m68k/amiga/config.c	Sun Aug 29 20:04:09 1999
@@ -54,7 +54,6 @@
 extern int amiga_kbdrate (struct kbd_repeat *);
 /* amiga specific irq functions */
 extern void amiga_init_IRQ (void);
-extern void (*amiga_default_handler[]) (int, void *, struct pt_regs *);
 extern int amiga_request_irq (unsigned int irq,
 			      void (*handler)(int, void *, struct pt_regs *),
                               unsigned long flags, const char *devname,
@@ -64,7 +63,6 @@
 extern void amiga_disable_irq (unsigned int);
 static void amiga_get_model(char *model);
 static int amiga_get_hardware_list(char *buffer);
-extern int amiga_get_irq_list (char *);
 /* amiga specific timer functions */
 static unsigned long amiga_gettimeoffset (void);
 static void a3000_gettod (int *, int *, int *, int *, int *, int *);
@@ -343,14 +341,12 @@
   mach_keyb_init       = amiga_keyb_init;
   mach_kbdrate         = amiga_kbdrate;
   mach_init_IRQ        = amiga_init_IRQ;
-  mach_default_handler = &amiga_default_handler;
   mach_request_irq     = amiga_request_irq;
   mach_free_irq        = amiga_free_irq;
   enable_irq           = amiga_enable_irq;
   disable_irq          = amiga_disable_irq;
   mach_get_model       = amiga_get_model;
   mach_get_hardware_list = amiga_get_hardware_list;
-  mach_get_irq_list    = amiga_get_irq_list;
   mach_gettimeoffset   = amiga_gettimeoffset;
   if (AMIGAHW_PRESENT(A3000_CLK)){
     mach_gettod  = a3000_gettod;
diff -Nur -X /opt/home/roman/src/m68k_nodiff linux-2.3.14/arch/m68k/config.in linux-rtl/arch/m68k/config.in
--- linux-2.3.14/arch/m68k/config.in	Fri Aug 20 20:46:49 1999
+++ linux-rtl/arch/m68k/config.in	Sun Aug 29 01:13:55 1999
@@ -72,6 +72,10 @@
   if [ "$CONFIG_M68060" = "y" ]; then
     bool 'Use write-through caching for 68060 supervisor accesses' CONFIG_060_WRITETHROUGH
   fi
+  if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+    bool 'Enable realtime interrupts' CONFIG_RT_INTERRUPT
+    bool 'Enable new system stack' CONFIG_SYS_STACK
+  fi
 fi
 endmenu
 
diff -Nur -X /opt/home/roman/src/m68k_nodiff linux-2.3.14/arch/m68k/fpsp040/skeleton.S linux-rtl/arch/m68k/fpsp040/skeleton.S
--- linux-2.3.14/arch/m68k/fpsp040/skeleton.S	Tue May 18 16:00:20 1999
+++ linux-rtl/arch/m68k/fpsp040/skeleton.S	Thu Aug 26 23:10:17 1999
@@ -70,9 +70,9 @@
 	frestore	(%sp)+
 	unlk		%a6
 
-	SAVE_ALL_INT
-	GET_CURRENT(%d0)
-	movel	%sp,%sp@- 		| stack frame pointer argument
+	save_all_int
+	get_current
+	pea	%sp@	 		| stack frame pointer argument
 	bsrl	SYMBOL_NAME(trap_c)
 	addql	#4,%sp
 	bral	SYMBOL_NAME(ret_from_exception)
@@ -161,8 +161,8 @@
 	frestore	(%sp)+
 	unlk		%a6
 
-	SAVE_ALL_INT
-	GET_CURRENT(%d0)
+	save_all_int
+	get_current
 	movel	%sp,%sp@- 		| stack frame pointer argument
 	bsrl	SYMBOL_NAME(trap_c)
 	addql	#4,%sp
@@ -187,8 +187,8 @@
 	frestore	(%sp)+
 	unlk		%a6
 
-	SAVE_ALL_INT
-	GET_CURRENT(%d0)
+	save_all_int
+	get_current
 	movel	%sp,%sp@- 		| stack frame pointer argument
 	bsrl	SYMBOL_NAME(trap_c)
 	addql	#4,%sp
@@ -213,8 +213,8 @@
 	frestore	(%sp)+
 	unlk		%a6
 
-	SAVE_ALL_INT
-	GET_CURRENT(%d0)
+	save_all_int
+	get_current
 	movel	%sp,%sp@- 		| stack frame pointer argument
 	bsrl	SYMBOL_NAME(trap_c)
 	addql	#4,%sp
@@ -235,8 +235,8 @@
 	frestore	(%sp)+
 	unlk		%a6
 
-	SAVE_ALL_INT
-	GET_CURRENT(%d0)
+	save_all_int
+	get_current
 	movel	%sp,%sp@- 		| stack frame pointer argument
 	bsrl	SYMBOL_NAME(trap_c)
 	addql	#4,%sp
@@ -257,8 +257,8 @@
 	frestore	(%sp)+
 	unlk		%a6
 
-	SAVE_ALL_INT
-	GET_CURRENT(%d0)
+	save_all_int
+	get_current
 	movel	%sp,%sp@- 		| stack frame pointer argument
 	bsrl	SYMBOL_NAME(trap_c)
 	addql	#4,%sp
@@ -285,8 +285,8 @@
 	frestore	(%sp)+
 	unlk		%a6
 
-	SAVE_ALL_INT
-	GET_CURRENT(%d0)
+	save_all_int
+	get_current
 	movel	%sp,%sp@- 		| stack frame pointer argument
 	bsrl	SYMBOL_NAME(trap_c)
 	addql	#4,%sp
@@ -306,8 +306,8 @@
 	jmp	fpsp_fline
 real_fline:
 
-	SAVE_ALL_INT
-	GET_CURRENT(%d0)
+	save_all_int
+	get_current
 	movel	%sp,%sp@- 		| stack frame pointer argument
 	bsrl	SYMBOL_NAME(trap_c)
 	addql	#4,%sp
@@ -328,8 +328,8 @@
 	frestore	(%sp)+
 	unlk		%a6
 
-	SAVE_ALL_INT
-	GET_CURRENT(%d0)
+	save_all_int
+	get_current
 	movel	%sp,%sp@- 		| stack frame pointer argument
 	bsrl	SYMBOL_NAME(trap_c)
 	addql	#4,%sp
@@ -379,12 +379,12 @@
 	beq	.Lnotkern
 	rte
 .Lnotkern:
-	SAVE_ALL_INT
-	GET_CURRENT(%d0)
+	save_all_int
+	get_current
 	tstl	%curptr@(TASK_NEEDRESCHED)
 	jne	SYMBOL_NAME(ret_from_exception)	| deliver signals,
 						| reschedule etc..
-	RESTORE_ALL
+	restore_all
 
 |
 |	mem_write --- write to user or supervisor address space
diff -Nur -X /opt/home/roman/src/m68k_nodiff linux-2.3.14/arch/m68k/ifpsp060/iskeleton.S linux-rtl/arch/m68k/ifpsp060/iskeleton.S
--- linux-2.3.14/arch/m68k/ifpsp060/iskeleton.S	Tue May 18 16:00:20 1999
+++ linux-rtl/arch/m68k/ifpsp060/iskeleton.S	Wed Aug 25 20:02:00 1999
@@ -73,12 +73,12 @@
 	beq	.Lnotkern
 	rte
 .Lnotkern:
-	SAVE_ALL_INT
-	GET_CURRENT(%d0)
+	save_all_int
+	get_current
 	tstl	%curptr@(TASK_NEEDRESCHED)
 	jne	SYMBOL_NAME(ret_from_exception)	| deliver signals,
 						| reschedule etc..
-	RESTORE_ALL
+	restore_all
 
 |
 | _060_real_chk():
diff -Nur -X /opt/home/roman/src/m68k_nodiff linux-2.3.14/arch/m68k/kernel/entry.S linux-rtl/arch/m68k/kernel/entry.S
--- linux-2.3.14/arch/m68k/kernel/entry.S	Tue Aug 24 01:00:37 1999
+++ linux-rtl/arch/m68k/kernel/entry.S	Sun Aug 29 20:18:40 1999
@@ -33,33 +33,34 @@
 #include <linux/sys.h>
 #include <linux/config.h>
 #include <linux/linkage.h>
-#include <asm/entry.h>
 #include <asm/errno.h>
 #include <asm/setup.h>
 #include <asm/segment.h>
+#include <asm/irq.h>
 #include <asm/traps.h>
 
 #include "m68k_defs.h"
 
+#include <asm/entry.h>
+
 .globl SYMBOL_NAME(system_call), SYMBOL_NAME(buserr), SYMBOL_NAME(trap)
 .globl SYMBOL_NAME(resume), SYMBOL_NAME(ret_from_exception)
 .globl SYMBOL_NAME(ret_from_signal)
 .globl SYMBOL_NAME(inthandler), SYMBOL_NAME(sys_call_table)
 .globl SYMBOL_NAME(sys_fork), SYMBOL_NAME(sys_clone), SYMBOL_NAME(sys_vfork)
-.globl SYMBOL_NAME(ret_from_interrupt), SYMBOL_NAME(bad_interrupt)
 
 .text
 ENTRY(buserr)
-	SAVE_ALL_INT
-	GET_CURRENT(%d0)
+	save_all_int
+	get_current
 	movel	%sp,%sp@- 		| stack frame pointer argument
 	bsrl	SYMBOL_NAME(buserr_c)
 	addql	#4,%sp
 	jra	SYMBOL_NAME(ret_from_exception)
 
 ENTRY(trap)
-	SAVE_ALL_INT
-	GET_CURRENT(%d0)
+	save_all_int
+	get_current
 	movel	%sp,%sp@- 		| stack frame pointer argument
 	bsrl	SYMBOL_NAME(trap_c)
 	addql	#4,%sp
@@ -83,40 +84,50 @@
 	jra	SYMBOL_NAME(ret_from_exception)
 
 badsys:
-	movel	#-ENOSYS,PT_D0(%sp)
+	drop_sys_stack
+	movel	#-ENOSYS,%sp@(PT_D0)
 	jra	SYMBOL_NAME(ret_from_exception)
 
 do_trace:
-	movel	#-ENOSYS,PT_D0(%sp)	| needed for strace
+	drop_sys_stack
+
+	| save top of frame
+	movel	%sp,%curptr@(TASK_THREAD+THREAD_ESP0)
+
+	movel	#-ENOSYS,%sp@(PT_D0)	| needed for strace
 	subql	#4,%sp
-	SAVE_SWITCH_STACK
+	save_switch_stack
 	jbsr	SYMBOL_NAME(syscall_trace)
-	RESTORE_SWITCH_STACK
+	restore_switch_stack
 	addql	#4,%sp
-	jbsr	@(SYMBOL_NAME(sys_call_table),%d2:l:4)@(0)
-	movel	%d0,%sp@(PT_D0)		| save the return value
+	rebuild_sys_stack
+	movel	%sp@(SC_SIZEOF+PT_SYSCALL),%d1
+	movel	#-ENOSYS,%d0
+	cmpl	#NR_syscalls,%d1
+	jcc	1f
+	jbsr	@(SYMBOL_NAME(sys_call_table),%d1:l:4)@(0)
+1:	movel	%d0,%sp@(SC_SIZEOF+PT_D0) | save the return value
+	drop_sys_stack
 	subql	#4,%sp			| dummy return address
-	SAVE_SWITCH_STACK
+	save_switch_stack
 	jbsr	SYMBOL_NAME(syscall_trace)
 
 SYMBOL_NAME_LABEL(ret_from_signal)
-	RESTORE_SWITCH_STACK
+	restore_switch_stack
 	addql	#4,%sp
 	jra	SYMBOL_NAME(ret_from_exception)
 
 ENTRY(system_call)
-	SAVE_ALL_SYS
-	movel	%d0,%d2
+	save_all_sys
+	save_sys_stack
+	get_current	%d1
 
-	GET_CURRENT(%d0)
-	| save top of frame
-	movel	%sp,%curptr@(TASK_THREAD+THREAD_ESP0)
-
-	cmpl	#NR_syscalls,%d2
-	jcc	badsys
 	btst	#PF_TRACESYS_BIT,%curptr@(TASK_FLAGS+PF_TRACESYS_OFF)
 	jne	do_trace
-	jbsr	@(SYMBOL_NAME(sys_call_table),%d2:l:4)@(0)
+	cmpl	#NR_syscalls,%d0
+	jcc	badsys
+	jbsr	@(SYMBOL_NAME(sys_call_table),%d0:l:4)@(0)
+	drop_sys_stack
 	movel	%d0,%sp@(PT_D0)		| save the return value
 
 SYMBOL_NAME_LABEL(ret_from_exception)
@@ -128,10 +139,6 @@
 	andw	#ALLOWINT,%sr
 	tstl	%curptr@(TASK_NEEDRESCHED)
 	jne	SYMBOL_NAME(reschedule)
-#if 0
-	cmpl	#SYMBOL_NAME(task),%curptr	| task[0] cannot have signals
-	jeq	2f
-#endif
 					| check for delayed trace
 	bclr	#PF_DTRACE_BIT,%curptr@(TASK_FLAGS+PF_DTRACE_OFF)
 	jne	do_delayed_trace
@@ -140,19 +147,19 @@
 	jne	SYMBOL_NAME(reschedule)
 
 	tstl	%curptr@(TASK_SIGPENDING)
-	jne	Lsignal_return
-2:	RESTORE_ALL
+	jne	signal_return
+2:	restore_all
 
-Lsignal_return:
+signal_return:
 	subql	#4,%sp			| dummy return address
-	SAVE_SWITCH_STACK
-	pea	%sp@(SWITCH_STACK_SIZE)
+	save_switch_stack
+	pea	%sp@(SW_SIZEOF)
 	clrl	%sp@-
 	bsrl	SYMBOL_NAME(do_signal)
 	addql	#8,%sp
-	RESTORE_SWITCH_STACK
+	restore_switch_stack
 	addql	#4,%sp
-	RESTORE_ALL
+	restore_all
 
 do_delayed_trace:
 	bclr	#7,%sp@(PT_SR)		| clear trace bit in SR
@@ -164,139 +171,260 @@
 	addql	#4,%sp
 	jra	5b
 
+/*
+** Interrupt construction set. :-)
+** You can build your own interrupts with these macros.
+*/
 
-#if 0
-#if CONFIG_AMIGA
-SYMBOL_NAME_LABEL(ami_inthandler)
+| general interrupt entry
+| intnodes - vector of ptr to interrupt nodes
+| firstvec, firststatvec - first entry in intnodes/int stats
+| -> %a0 contains first int node, %d0 exception vector
+.macro	int_entry intnodes, firstvec, firststatvec=VEC_SPUR
 	addql	#1,SYMBOL_NAME(local_irq_count)
-	SAVE_ALL_INT
-	GET_CURRENT(%d0)
+	save_all_int
+	get_current
 
+| extract exception vector, do some statistic and get (first) int node
 	bfextu	%sp@(PT_VECTOR){#4,#12},%d0
 	movel	%d0,%a0
-	addql	#1,%a0@(SYMBOL_NAME(kstat)+STAT_IRQ-VECOFF(VEC_SPUR))
-	movel	%a0@(SYMBOL_NAME(autoirq_list)-VECOFF(VEC_SPUR)),%a0
-
-| amiga vector int handler get the req mask instead of irq vector
-	lea	CUSTOMBASE,%a1
-	movew	%a1@(C_INTREQR),%d0
-	andw	%a1@(C_INTENAR),%d0
+	addql	#1,%a0@(SYMBOL_NAME(kstat)+STAT_IRQ-VECOFF(\firststatvec))
+	movel	%a0@(SYMBOL_NAME(\intnodes)-VECOFF(\firstvec)),%a0
+.endm
 
-| prepare stack (push frame pointer, dev_id & req mask)
+| call a single interrupt node
+.macro	int_callnode exit=SYMBOL_NAME(ret_from_interrupt_cleanup)
 	pea	%sp@
 	movel	%a0@(IRQ_DEVID),%sp@-
 	movel	%d0,%sp@-
-	pea	%pc@(SYMBOL_NAME(ret_from_interrupt):w)
-	jbra	@(IRQ_HANDLER,%a0)@(0)
-
-ENTRY(nmi_handler)
-	rte
+	pea	%pc@(\exit:w)
+	jra	@(IRQ_HANDLER,%a0)@(0)
+.endm
+
+| after int_callnode the stack must be cleaned up
+.macro	int_cleanup
+	lea	%sp@(12),%sp
+.endm
+
+| call a list of interrupt nodes
+.macro	int_callnodelist exit=SYMBOL_NAME(ret_from_interrupt)
+	movel	%a0@(IRQ_NEXT),%sp@-
+	pea	%sp@(4)
+	movel	%a0@(IRQ_DEVID),%sp@-
+	movel	%d0,%sp@-
+1:	jsr	@(IRQ_HANDLER,%a0)@(0)
+	movel	%sp@(12),%d0
+	jeq	2f
+	movel	%d0,%a0
+| only modify devid on stack, we expect the rest to be unmodified
+	movel	%a0@(IRQ_DEVID),%sp@(4)
+	movel	%a0@(IRQ_NEXT),%sp@(12)
+	jra	1b
+2:	lea	%sp@(16),%sp
+	jra	\exit
+.endm
+
+| help macro for the two exit macro to check for a nested interrupt.
+| For the 060 we can be sure that at least one instruction of an
+| exception is executed, so the counter check is sufficient.
+.macro int_returncheck dest
+#ifndef CPU_M68060_ONLY
+#if MAX_NOINT_IPL == 0
+	bftst	%sp@(PT_SR){#5,#3}
+	jne	\dest
+#else
+	bfextu	%sp@(PT_SR){#5,#3},%d0
+	cmpiw	#MAX_NOINT_IPL,%d0
+	jhi	\dest
 #endif
 #endif
+.endm
 
-/*
-** This is the main interrupt handler, responsible for calling process_int()
-*/
-SYMBOL_NAME_LABEL(inthandler)
-	SAVE_ALL_INT
-	GET_CURRENT(%d0)
-	addql	#1,SYMBOL_NAME(local_irq_count)
-					|  put exception # in d0
-	bfextu %sp@(PT_VECTOR){#4,#10},%d0
-
-	movel	%sp,%sp@-
-	movel	%d0,%sp@- 		|  put vector # on stack
-#if defined(MACH_Q40_ONLY) && defined(CONFIG_BLK_DEV_FD)
-	btstb	#4,0xff000000	| Q40 floppy needs very special treatment ...
-	jbeq	1f
-	btstb	#3,0xff000004		
-	jbeq	1f
-	jbsr	SYMBOL_NAME(floppy_hardint)
-	jbra	3f
-1:
-#endif		
-	jbsr	SYMBOL_NAME(process_int)|  process the IRQ
-3:     	addql	#8,%sp			|  pop parameters off stack
-
-SYMBOL_NAME_LABEL(ret_from_interrupt)
+.macro	int_return
 	subql	#1,SYMBOL_NAME(local_irq_count)
-	jeq	1f
+	jeq	2f
+1:	
+	restore_all
+	ALIGN
 2:
-	RESTORE_ALL
-1:
-#if 1
-	bfextu  %sp@(PT_SR){#5,#3},%d0	| Check for nested interrupt.
-#if MAX_NOINT_IPL > 0
-	cmpiw	#MAX_NOINT_IPL,%d0
-#endif
-	jhi	2b
-#endif
-	/* check if we need to do software interrupts */
+	int_returncheck 1b
 
+	/* check if we need to do software interrupts */
 	movel	SYMBOL_NAME(bh_active),%d0
 	andl	SYMBOL_NAME(bh_mask),%d0
 	jeq	SYMBOL_NAME(ret_from_exception)
 
 	pea	SYMBOL_NAME(ret_from_exception)
 	jra	SYMBOL_NAME(do_bottom_half)
+.endm
 
+.macro	int_slowreturn do_slowrequest
+	movel	SYMBOL_NAME(local_irq_count),%d0
+	subql	#1,%d0
+	jeq	2f
+1:	movel	%d0,SYMBOL_NAME(local_irq_count)
+	restore_all
+	ALIGN
+2:
+	int_returncheck 1b
+#ifdef CONFIG_RT_INTERRUPT
+	tstl	SYMBOL_NAME(slowirq_enable)
+	jeq	1b
+#endif
+3:
+#ifdef CONFIG_RT_INTERRUPT
+	subql	#1,SYMBOL_NAME(slowirq_busycnt)
+	jlt	1b
+#endif
+	andw	#0xf8ff,%sr
+	jsr	\do_slowrequest
+
+#ifndef CONFIG_RT_INTERRUPT
+	orw	#0x0700,%sr
+	tstl	SYMBOL_NAME(slowirq_request)
+	jne	3b
+	clrl	SYMBOL_NAME(local_irq_count)
+	jra	SYMBOL_NAME(ret_from_exception)
+#else
+	| almost the same as above, but also tries to minimize
+	| the time where interrupts are disabled
+	btst	#5,%sp@(PT_SR)		| check if returning to kernel
+	jeq	1f
+	orw	#0x0700,%sr
+	tstl	SYMBOL_NAME(slowirq_request)
+	jne	3b
+	clrl	SYMBOL_NAME(local_irq_count)
+	restore_all
+1:	orw	#0x0700,%sr
+	tstl	SYMBOL_NAME(slowirq_request)
+	jne	3b
+	clrl	SYMBOL_NAME(local_irq_count)
+	andw	#0xf8ff,%sr
+	jra	SYMBOL_NAME(ret_from_exception)
+#endif
+.endm
 
+
+#ifdef CONFIG_AMIGA
+/*
+** Special Amiga interrupt handler
+*/
+ENTRY(amiga_inthandler)
+	int_entry autoirq_list,VEC_SPUR
+
+| amiga vector int handler get the req mask instead of irq vector
+       lea     CUSTOMBASE,%a1
+       movew   %a1@(C_INTREQR),%d0
+       andw    %a1@(C_INTENAR),%d0
+
+.globl	SYMBOL_NAME(amiga_slowintmask),SYMBOL_NAME(amiga_fastintmask)
+
+| disable slow ints and modify req mask
+	movew	%d0,%d1
+.equ	SYMBOL_NAME(amiga_slowintmask),.+2
+	andw	#0:w,%d1
+	jeq	1f
+	orw	%d1,SYMBOL_NAME(slowirq_request+2)
+	movew	%d1,%a1@(C_INTENA)
+.equ	SYMBOL_NAME(amiga_fastintmask),.+2
+1:	andw	#0:w,%d0
+	jeq	SYMBOL_NAME(amiga_fastret_from_irq)
+
+	int_callnode SYMBOL_NAME(amiga_ret_from_irq)
+
+ENTRY(amiga_ret_from_irq)
+	int_cleanup
+SYMBOL_NAME_LABEL(amiga_fastret_from_irq)
+	int_slowreturn SYMBOL_NAME(amiga_do_slowirq_request)
+
+ENTRY(amiga_nmi_handler)
+	rte
+#endif
+
+#if defined(CONFIG_HP300)
+ENTRY(autoirq_handler)
+	int_entry autoirq_list,VEC_SPUR
+	lsrl	#2,%d0
+	int_callnode SYMBOL_NAME(cleanup_from_interrupt)
+
+ENTRY(autoirq_listhandler)
+	int_entry autoirq_list,VEC_SPUR
+	lsrl	#2,%d0
+	int_callnodelist SYMBOL_NAME(ret_from_interrupt)
+
+ENTRY(cleanup_from_interrupt)
+	int_cleanup
+SYMBOL_NAME_LABEL(ret_from_interrupt)
+	int_return
+#endif
+
+#if defined(CONFIG_APOLLO)
+ENTRY(appolloirq_handler)
+	int_entry userirq_list, 160, 160+VEC_SPUR
+	lsrl	#2,%d0
+	int_callnode SYMBOL_NAME(apollo_ret_from_irq)
+
+ENTRY(appollo_ret_from_irq)
+	int_cleanup
+#warning add something
+	int_return
+#endif
 /* Handler for uninitialized and spurious interrupts */
 
-SYMBOL_NAME_LABEL(bad_interrupt)
+ENTRY(bad_interrupt)
 	addql	#1,SYMBOL_NAME(num_spurious)
 	rte
 
 ENTRY(sys_fork)
-	SAVE_SWITCH_STACK	
-	pea	%sp@(SWITCH_STACK_SIZE)
+	changeto_switch_stack
+	pea	%sp@(SW_SIZEOF)
 	jbsr	SYMBOL_NAME(m68k_fork)
 	addql	#4,%sp
-	RESTORE_SWITCH_STACK
+	changeto_sys_stack
 	rts
 
 ENTRY(sys_clone)
-	SAVE_SWITCH_STACK
-	pea	%sp@(SWITCH_STACK_SIZE)
+	changeto_switch_stack
+	pea	%sp@(SW_SIZEOF)
 	jbsr	SYMBOL_NAME(m68k_clone)
 	addql	#4,%sp
-	RESTORE_SWITCH_STACK
+	changeto_sys_stack
 	rts
 
 ENTRY(sys_vfork)
-	SAVE_SWITCH_STACK	
-	pea	%sp@(SWITCH_STACK_SIZE)
+	changeto_switch_stack
+	pea	%sp@(SW_SIZEOF)
 	jbsr	SYMBOL_NAME(m68k_vfork)
 	addql	#4,%sp
-	RESTORE_SWITCH_STACK
+	changeto_sys_stack
 	rts
 
 ENTRY(sys_sigsuspend)
-	SAVE_SWITCH_STACK
-	pea	%sp@(SWITCH_STACK_SIZE)
+	changeto_switch_stack
+	pea	%sp@(SW_SIZEOF)
 	jbsr	SYMBOL_NAME(do_sigsuspend)
 	addql	#4,%sp
-	RESTORE_SWITCH_STACK
+	changeto_sys_stack
 	rts
 
 ENTRY(sys_rt_sigsuspend)
-	SAVE_SWITCH_STACK
-	pea	%sp@(SWITCH_STACK_SIZE)
+	changeto_switch_stack
+	pea	%sp@(SW_SIZEOF)
 	jbsr	SYMBOL_NAME(do_rt_sigsuspend)
 	addql	#4,%sp
-	RESTORE_SWITCH_STACK
+	changeto_sys_stack
 	rts
 
 ENTRY(sys_sigreturn)
-	SAVE_SWITCH_STACK
+	changeto_switch_stack
 	jbsr	SYMBOL_NAME(do_sigreturn)
-	RESTORE_SWITCH_STACK
+	changeto_sys_stack nodrop=1
 	rts
 
 ENTRY(sys_rt_sigreturn)
-	SAVE_SWITCH_STACK
+	changeto_switch_stack
 	jbsr	SYMBOL_NAME(do_rt_sigreturn)
-	RESTORE_SWITCH_STACK
+	changeto_sys_stack nodrop=1
 	rts
 
 SYMBOL_NAME_LABEL(resume)
@@ -319,7 +447,7 @@
 	movel	%d0,%a0@(TASK_THREAD+THREAD_USP)
 
 	/* save non-scratch registers on stack */
-	SAVE_SWITCH_STACK
+	save_switch_stack
 
 	/* save current kernel stack pointer */
 	movel	%sp,%a0@(TASK_THREAD+THREAD_KSP)
@@ -390,7 +518,7 @@
 	movel	%a1@(TASK_THREAD+THREAD_KSP),%sp
 
 	/* restore non-scratch registers */
-	RESTORE_SWITCH_STACK
+	restore_switch_stack
 
 	/* restore user stack pointer */
 	movel	%a1@(TASK_THREAD+THREAD_USP),%a0
diff -Nur -X /opt/home/roman/src/m68k_nodiff linux-2.3.14/arch/m68k/kernel/head.S linux-rtl/arch/m68k/kernel/head.S
--- linux-2.3.14/arch/m68k/kernel/head.S	Fri Aug 20 20:46:57 1999
+++ linux-rtl/arch/m68k/kernel/head.S	Sat Aug 28 12:03:29 1999
@@ -259,6 +259,7 @@
 #include <linux/init.h>
 #include <asm/bootinfo.h>
 #include <asm/setup.h>
+#include <asm/entry.h>
 #include <asm/pgtable.h>
 #include "m68k_defs.h"
 
@@ -386,6 +387,12 @@
 #endif
 #endif
 
+/* The __INITDATA stuff is a no-op when ftrace or kgdb are turned on */
+#ifndef __INITDATA
+#define __INITDATA	.data
+#define __FINIT		.previous
+#endif
+
 /* Several macros to make the writing of subroutines easier:
  * - func_start marks the beginning of the routine which setups the frame
  *   register and saves the registers, it also defines another macro
@@ -503,18 +510,10 @@
 
 .macro	puts		string
 #if defined(CONSOLE) || defined(SERIAL_DEBUG)
-/* The __INITDATA stuff is a no-op when ftrace or kgdb are turned on */
-#if defined(CONFIG_FTRACE) || defined(CONFIG_KGDB)
-	bra 1f
-#endif
 	__INITDATA
 .Lstr\@:
 	.string	"\string"
 	__FINIT
-#if defined(CONFIG_FTRACE) || defined(CONFIG_KGDB)
-	.align 2
-1:
-#endif
 	pea	%pc@(.Lstr\@)
 	func_call	puts
 	addql	#4,%sp
@@ -1352,8 +1351,8 @@
 /*
  * Setup initial stack pointer
  */
-	lea	SYMBOL_NAME(init_task_union),%a2
-	lea	0x2000(%a2),%sp
+	lea	SYMBOL_NAME(init_task_union),%curptr
+	lea	0x2000(%curptr),%sp
 
 /* jump to the kernel start */
 	putc	'\n'
diff -Nur -X /opt/home/roman/src/m68k_nodiff linux-2.3.14/arch/m68k/kernel/ints.c linux-rtl/arch/m68k/kernel/ints.c
--- linux-2.3.14/arch/m68k/kernel/ints.c	Fri Aug 20 20:46:58 1999
+++ linux-rtl/arch/m68k/kernel/ints.c	Sun Aug 29 20:14:33 1999
@@ -23,11 +23,17 @@
  *           If you want to replace a default handler you should know what
  *           you're doing, since it might handle different other irq sources
  *           which must be served                               /Roman Zippel
+ * 01/08/99: new interrupt managemant, that handles user vector interrupts as
+ *           well, sys_request_irq takes now the vector number from traps.h as
+ *           argument, process_int() is gone, every machine has to provide its
+ *           own interrupt entry and insert it into the vector table, examples
+ *           are in entry.S.                                    /Roman Zippel
  */
 
 #include <linux/config.h>
 #include <linux/types.h>
 #include <linux/sched.h>
+#include <linux/malloc.h>
 #include <linux/kernel_stat.h>
 #include <linux/errno.h>
 #include <linux/init.h>
@@ -43,23 +49,29 @@
 #include <asm/q40ints.h>
 #endif
 
-/* table for system interrupt handlers */
-static irq_handler_t irq_list[SYS_IRQS];
-
-static const char *default_names[SYS_IRQS] = {
-	"spurious int", "int1 handler", "int2 handler", "int3 handler",
-	"int4 handler", "int5 handler", "int6 handler", "int7 handler"
-};
-
 /* The number of spurious interrupts */
 volatile unsigned int num_spurious;
 
-#define NUM_IRQ_NODES 100
-static irq_node_t nodes[NUM_IRQ_NODES];
-
-unsigned int local_irq_count[NR_CPUS];
+/* static irq nodes used during bootup */
+#define NUM_IRQ_NODES 16
+static irq_node_t boot_nodes[NUM_IRQ_NODES];
+
+/* table for auto vector interrupt handlers */
+irq_node_t *autoirq_list[AUTO_IRQ_NR] = { NULL };
+irq_node_t *autoirq_slowlist[AUTO_IRQ_NR] = { NULL };
+
+#if USER_IRQ_NR
+/* table for user vector interrupt handlers */
+irq_node_t *userirq_list[USER_IRQ_NR] = { NULL };
+irq_node_t *userirq_slowlist[USER_IRQ_NR] = { NULL };
+#endif
 
-unsigned int local_bh_count[NR_CPUS];
+unsigned int local_irq_count[NR_CPUS] = { 0 };
+unsigned int local_bh_count[NR_CPUS] = { 0 };
+unsigned int local_slowirq_count[NR_CPUS] = { 0 };
+volatile int slowirq_enable = 0;
+volatile int slowirq_request = 0;
+volatile int slowirq_busycnt = 1;
 
 static void dummy_enable_irq(unsigned int irq);
 static void dummy_disable_irq(unsigned int irq);
@@ -67,6 +79,7 @@
 		void (*handler) (int, void *, struct pt_regs *),
 		unsigned long flags, const char *devname, void *dev_id);
 static void dummy_free_irq(unsigned int irq, void *dev_id);
+static void dummy_do_slowirq(void);
 
 void (*enable_irq) (unsigned int) = dummy_enable_irq;
 void (*disable_irq) (unsigned int) = dummy_disable_irq;
@@ -74,7 +87,9 @@
 int (*mach_request_irq) (unsigned int, void (*)(int, void *, struct pt_regs *),
                       unsigned long, const char *, void *) = dummy_request_irq;
 void (*mach_free_irq) (unsigned int, void *) = dummy_free_irq;
-
+#ifdef CONFIG_RT_INTERRUPT
+void (*mach_do_slowirq)(void) = dummy_do_slowirq;
+#endif
 /*
  * void init_IRQ(void)
  *
@@ -90,31 +105,104 @@
 {
 	int i;
 
-	for (i = 0; i < SYS_IRQS; i++) {
-		if (mach_default_handler)
-			irq_list[i].handler = (*mach_default_handler)[i];
-		irq_list[i].flags   = 0;
-		irq_list[i].dev_id  = NULL;
-		irq_list[i].devname = default_names[i];
-	}
+	for (i = 0; i < AUTO_IRQ_NR; i++)
+		autoirq_list[i] = NULL;
+
+#if USER_IRQ_NR
+	for (i = 0; i < USER_IRQ_NR; i++)
+		userirq_list[i] = NULL;
+#endif
 
 	for (i = 0; i < NUM_IRQ_NODES; i++)
-		nodes[i].handler = NULL;
+		boot_nodes[i].handler = NULL;
 
-	mach_init_IRQ ();
+	mach_init_IRQ();
 }
 
 irq_node_t *new_irq_node(void)
 {
 	irq_node_t *node;
-	short i;
+	int i;
 
-	for (node = nodes, i = NUM_IRQ_NODES-1; i >= 0; node++, i--)
+	for (node = boot_nodes, i = 0; i < NUM_IRQ_NODES; node++, i--)
 		if (!node->handler)
-			return node;
+			break;
+
+	if (!node)
+		node = kmalloc(sizeof(irq_node_t), GFP_KERNEL);
+
+	if (node) {
+		node->handler = NULL;
+		node->flags = 0;
+	}
+
+	return node;
+}
+
+void free_irq_node(irq_node_t *node)
+{
+	if (node >= &boot_nodes[0] || node < &boot_nodes[NUM_IRQ_NODES])
+		node->handler = NULL;
+	else
+		kfree(node);
+}
 
-	printk ("new_irq_node: out of nodes\n");
-	return NULL;
+static irq_node_t **get_irqlist(unsigned int irq, unsigned long flags)
+{
+	irq_node_t **list = NULL;
+
+	if (irq > VEC_SPUR && irq <= VEC_INT7) {
+		list = &autoirq_slowlist[irq - VEC_SPUR];
+		if (flags & IRQ_FLG_FASTQUEUE)
+			list = &autoirq_list[irq - VEC_SPUR];
+	}
+
+#if USER_IRQ_NR
+	if (irq >= VEC_USER && irq <= VEC_USER + USER_IRQ_NR) {
+		list = &userirq_slowlist[irq - VEC_USER];
+		if (flags & IRQ_FLG_FASTQUEUE)
+			list = &userirq_list[irq - VEC_USER];
+	}
+#endif
+
+	return list;
+}
+
+static irq_node_t **find_irqnode(unsigned int irq, void *dev_id)
+{
+	irq_node_t **list = NULL;
+	irq_node_t **slowlist = NULL;
+
+	if (irq > VEC_SPUR && irq <= VEC_INT7) {
+		list = &autoirq_list[irq - VEC_SPUR];
+		slowlist = &autoirq_slowlist[irq - VEC_SPUR];
+	}
+
+#if USER_IRQ_NR
+	if (irq >= VEC_USER && irq <= VEC_USER + USER_IRQ_NR) {
+		list = &userirq_list[irq - VEC_USER];
+		slowlist = &userirq_slowlist[irq - VEC_USER];
+	}
+#endif
+
+	/* First scan fast list and continue with slow list */
+	while (list) {
+		if (!*list) {
+			list = slowlist;
+			slowlist = NULL;
+			continue;
+		}
+
+		if (!*list)
+			return NULL;
+
+		if ((*list)->dev_id == dev_id)
+			break;
+
+		list = &(*list)->next;
+	}
+
+	return list;
 }
 
 /*
@@ -138,49 +226,83 @@
                     void (*handler)(int, void *, struct pt_regs *), 
                     unsigned long flags, const char *devname, void *dev_id)
 {
-	if (irq < IRQ1 || irq > IRQ7) {
-		printk("%s: Incorrect IRQ %d from %s\n",
-		       __FUNCTION__, irq, devname);
-		return -ENXIO;
-	}
+	irq_node_t **list;
+	irq_node_t *node;
 
-#if 0
-	if (!(irq_list[irq].flags & IRQ_FLG_STD)) {
-		if (irq_list[irq].flags & IRQ_FLG_LOCK) {
-			printk("%s: IRQ %d from %s is not replaceable\n",
-			       __FUNCTION__, irq, irq_list[irq].devname);
+	list = find_irqnode(irq, dev_id);
+	if (list) {
+		if (!(flags & IRQ_FLG_REPLACE)) {
+			printk("%s: %s can't replace IRQ %x from %s\n",
+			       __FUNCTION__, devname, irq, (*list)->devname);
 			return -EBUSY;
 		}
-		if (!(flags & IRQ_FLG_REPLACE)) {
-			printk("%s: %s can't replace IRQ %d from %s\n",
-			       __FUNCTION__, devname, irq, irq_list[irq].devname);
+		if ((*list)->flags & IRQ_FLG_LOCK) {
+			printk("%s: IRQ %x from %s is not replaceable\n",
+			       __FUNCTION__, irq, (*list)->devname);
+			return -EBUSY;
+		}
+
+		node = *list;
+		*list = node->next;
+
+		list = get_irqlist(irq, flags);
+	} else {
+		list = get_irqlist(irq, flags);
+		if (!list) {
+			printk("%s: Incorrect IRQ %x from %s\n",
+			       __FUNCTION__, irq, devname);
+			return -ENXIO;
+		}
+
+		if (*list && !(flags & IRQ_FLG_LIST)) {
+			printk("%s: IRQ %x is busy (%s)\n", __FUNCTION__,
+			       irq, (*list)->devname);
 			return -EBUSY;
 		}
+
+		node = new_irq_node();
+		if (!node)
+			return -ENOMEM;
 	}
-#endif
 
-	irq_list[irq].handler = handler;
-	irq_list[irq].flags   = flags;
-	irq_list[irq].dev_id  = dev_id;
-	irq_list[irq].devname = devname;
+	node->handler = handler;
+	node->flags   = flags;
+	node->dev_id  = dev_id;
+	node->devname = devname;
+
+	if (node->flags & IRQ_FLG_SLOW) {
+		while (*list)
+			list = &(*list)->next;
+	} else if (node->flags & IRQ_FLG_FAST) {
+		node->flags &= ~IRQ_FLG_SLOW;
+		while (*list && (*list)->flags & IRQ_FLG_FAST)
+			list = &(*list)->next;
+	} else {
+		while (*list && !((*list)->flags & IRQ_FLG_SLOW))
+			list = &(*list)->next;
+	}
+
+	node->next = *list;
+	*list = node;
+
 	return 0;
 }
 
 void sys_free_irq(unsigned int irq, void *dev_id)
 {
-	if (irq < IRQ1 || irq > IRQ7) {
-		printk("%s: Incorrect IRQ %d\n", __FUNCTION__, irq);
+	irq_node_t **list;
+	irq_node_t *node;
+
+	list = find_irqnode(irq, dev_id);
+	if (!list) {
+		printk("%s: No handler with id 0x%p found for IRQ %x\n",
+		       __FUNCTION__, dev_id, irq);
 		return;
 	}
 
-	if (irq_list[irq].dev_id != dev_id)
-		printk("%s: Removing probably wrong IRQ %d from %s\n",
-		       __FUNCTION__, irq, irq_list[irq].devname);
-
-	irq_list[irq].handler = (*mach_default_handler)[irq];
-	irq_list[irq].flags   = 0;
-	irq_list[irq].dev_id  = NULL;
-	irq_list[irq].devname = default_names[irq];
+	node = *list;
+	*list = node->next;
+	free_irq_node(node);
 }
 
 /*
@@ -229,35 +351,88 @@
 	printk("calling uninitialized disable_irq()\n");
 }
 
-asmlinkage void process_int(unsigned long vec, struct pt_regs *fp)
+#ifdef CONFIG_RT_INTERRUPT
+static void dummy_do_slowirq(void)
 {
-	if (vec >= VEC_INT1 && vec <= VEC_INT7 && !MACH_IS_BVME6000) {
-		vec -= VEC_SPUR;
-		kstat.irqs[0][vec]++;
-		irq_list[vec].handler(vec, irq_list[vec].dev_id, fp);
-	} else {
-		if (mach_process_int)
-			mach_process_int(vec, fp);
-		else
-			panic("Can't process interrupt vector %ld\n", vec);
-		return;
-	}
+	/* just a dummy */
 }
+#endif
 
 int get_irq_list(char *buf)
 {
-	int i, len = 0;
+	irq_node_t **list;
+	irq_node_t **slowlist;
+	int i, len;
+
+	len = sprintf(buf, "auto %2x: %10u     spurious int\n",
+	              0, num_spurious);
 
 	/* autovector interrupts */
-	if (mach_default_handler) {
-		for (i = 0; i < SYS_IRQS; i++) {
-			len += sprintf(buf+len, "auto %2d: %10u ", i,
-			               i ? kstat.irqs[0][i] : num_spurious);
-				len += sprintf(buf+len, "  ");
-			len += sprintf(buf+len, "%s\n", irq_list[i].devname);
+	for (i = 1; i < AUTO_IRQ_NR; i++) {
+		list = &autoirq_list[i];
+		slowlist = &autoirq_slowlist[i];
+		if (!*list && !*slowlist)
+			continue;
+		len += sprintf(buf+len, "auto %2d: %10u ",
+		               i, kstat.irqs[0][i]);
+		if (!*list) {
+			list = slowlist;
+			slowlist = NULL;
+		}
+		while (1) {
+			len += sprintf(buf+len, "%c%c%c %s\n",
+			               (*list)->flags & IRQ_FLG_REALTIME ? 'R' : ' ',
+			               (*list)->flags & IRQ_FLG_LOCK ? 'L' : ' ',
+			               (*list)->flags & IRQ_FLG_FAST ? 'F' :
+			               ((*list)->flags & IRQ_FLG_SLOW ? 'S' : ' '),
+			               (*list)->devname);
+			list = &(*list)->next;
+			if (!*list) {
+				if (!(list = slowlist))
+					break;
+				slowlist = NULL;
+			}
+			if (!*list)
+				break;
+			len += sprintf(buf+len, "                    ");
+		}
+	}
+
+#if USER_IRQ_NR
+	/* uservector interrupts */
+	for (i = 0; i < USER_IRQ_NR; i++) {
+		list = &userirq_list[i];
+		slowlist = &userirq_slowlist[i];
+		if (!*list && !*slowlist)
+			continue;
+		len += sprintf(buf+len, "user %2d: %10u ",
+		               i, kstat.irqs[0][AUTO_IRQ_NR+i]);
+		if (!*list) {
+			list = slowlist;
+			slowlist = NULL;
+		}
+		while (1) {
+			len += sprintf(buf+len, "%c%c%c %s\n",
+			               (*list)->flags & IRQ_FLG_REALTIME ? 'R' : ' ',
+			               (*list)->flags & IRQ_FLG_LOCK ? 'L' : ' ',
+			               (*list)->flags & IRQ_FLG_FAST ? 'F' :
+			               ((*list)->flags & IRQ_FLG_SLOW ? 'S' : ' '),
+			               (*list)->devname);
+			list = &(*list)->next;
+			if (!*list) {
+				if (!(list = slowlist))
+					break;
+				slowlist = NULL;
+			}
+			if (!*list)
+				break;
+			len += sprintf(buf+len, "                    ");
 		}
 	}
+#endif
+
+	if (mach_get_irq_list)
+		len += mach_get_irq_list(buf+len);
 
-	len += mach_get_irq_list(buf+len);
 	return len;
 }
diff -Nur -X /opt/home/roman/src/m68k_nodiff linux-2.3.14/arch/m68k/kernel/m68k_defs.c linux-rtl/arch/m68k/kernel/m68k_defs.c
--- linux-2.3.14/arch/m68k/kernel/m68k_defs.c	Tue Aug 10 20:14:37 1999
+++ linux-rtl/arch/m68k/kernel/m68k_defs.c	Sun Aug 29 02:00:48 1999
@@ -43,19 +43,23 @@
 
 	/* offsets into the pt_regs */
 	DEFINE(PT_D0, offsetof(struct pt_regs, d0));
-	DEFINE(PT_ORIG_D0, offsetof(struct pt_regs, orig_d0));
 	DEFINE(PT_D1, offsetof(struct pt_regs, d1));
-	DEFINE(PT_D2, offsetof(struct pt_regs, d2));
-	DEFINE(PT_D3, offsetof(struct pt_regs, d3));
-	DEFINE(PT_D4, offsetof(struct pt_regs, d4));
-	DEFINE(PT_D5, offsetof(struct pt_regs, d5));
 	DEFINE(PT_A0, offsetof(struct pt_regs, a0));
 	DEFINE(PT_A1, offsetof(struct pt_regs, a1));
 	DEFINE(PT_A2, offsetof(struct pt_regs, a2));
+	DEFINE(PT_SYSCALL, offsetof(struct pt_regs, syscall));
 	DEFINE(PT_PC, offsetof(struct pt_regs, pc));
 	DEFINE(PT_SR, offsetof(struct pt_regs, sr));
 	/* bitfields are a bit difficult */
 	DEFINE(PT_VECTOR, offsetof(struct pt_regs, pc) + 4);
+
+	/* size of switchstack and syscall stack */
+	DEFINE(SW_SIZEOF, sizeof(struct switch_stack));
+#ifdef CONFIG_SYS_STACK
+	DEFINE(SC_SIZEOF, sizeof(struct syscall_stack));
+#else
+	DEFINE(SC_SIZEOF, 0);
+#endif
 
 	/* offsets into the irq_handler struct */
 	DEFINE(IRQ_HANDLER, offsetof(struct irq_node, handler));
diff -Nur -X /opt/home/roman/src/m68k_nodiff linux-2.3.14/arch/m68k/kernel/process.c linux-rtl/arch/m68k/kernel/process.c
--- linux-2.3.14/arch/m68k/kernel/process.c	Fri Aug 20 20:47:00 1999
+++ linux-rtl/arch/m68k/kernel/process.c	Sun Aug 29 01:51:53 1999
@@ -108,14 +108,12 @@
 	printk("\n");
 	printk("Format %02x  Vector: %04x  PC: %08lx  Status: %04x\n",
 	       regs->format, regs->vector, regs->pc, regs->sr);
-	printk("ORIG_D0: %08lx  D0: %08lx  A2: %08lx  A1: %08lx\n",
-	       regs->orig_d0, regs->d0, regs->a2, regs->a1);
-	printk("A0: %08lx  D5: %08lx  D4: %08lx\n",
-	       regs->a0, regs->d5, regs->d4);
-	printk("D3: %08lx  D2: %08lx  D1: %08lx\n",
-	       regs->d3, regs->d2, regs->d1);
+	printk("A0: %08lx  A1: %08lx  A2: %08lx  SYS: %08lx\n",
+	       regs->a0, regs->a1, regs->a2, regs->syscall);
+	printk("D0: %08lx  D1: %08lx", regs->d0, regs->d1);
 	if (!(regs->sr & PS_S))
-		printk("USP: %08lx\n", rdusp());
+		printk("  USP: %08lx", rdusp());
+	printk("\n");
 }
 
 /*
@@ -191,7 +189,7 @@
 
 	/* syscall2 puts clone_flags in d1 and usp in d2 */
 	clone_flags = regs->d1;
-	newsp = regs->d2;
+	newsp = SW_PTR(regs)->d2;
 	if (!newsp)
 		newsp = rdusp();
 	return do_fork(clone_flags, newsp, regs);
@@ -298,10 +296,17 @@
 	dump->u_ar0 = (struct user_regs_struct *)((int)&dump->regs - (int)dump);
 	sw = ((struct switch_stack *)regs) - 1;
 	dump->regs.d1 = regs->d1;
+#ifdef CONFIG_SYS_STACK
+	dump->regs.d2 = sw->d2;
+	dump->regs.d3 = sw->d3;
+	dump->regs.d4 = sw->d4;
+	dump->regs.d5 = sw->d5;
+#else
 	dump->regs.d2 = regs->d2;
 	dump->regs.d3 = regs->d3;
 	dump->regs.d4 = regs->d4;
 	dump->regs.d5 = regs->d5;
+#endif
 	dump->regs.d6 = sw->d6;
 	dump->regs.d7 = sw->d7;
 	dump->regs.a0 = regs->a0;
@@ -312,7 +317,7 @@
 	dump->regs.a5 = sw->a5;
 	dump->regs.a6 = sw->a6;
 	dump->regs.d0 = regs->d0;
-	dump->regs.orig_d0 = regs->orig_d0;
+	dump->regs.orig_d0 = regs->syscall;
 	dump->regs.stkadj = regs->stkadj;
 	dump->regs.sr = regs->sr;
 	dump->regs.pc = regs->pc;
@@ -328,7 +333,11 @@
 {
 	int error;
 	char * filename;
-	struct pt_regs *regs = (struct pt_regs *) &name;
+#ifdef CONFIG_SYS_STACK
+	struct pt_regs *regs = (struct pt_regs *)(((struct syscall_stack *)&name)+1);
+#else
+	struct pt_regs *regs = (struct pt_regs *)&name;
+#endif
 
 	lock_kernel();
 	filename = getname(name);
diff -Nur -X /opt/home/roman/src/m68k_nodiff linux-2.3.14/arch/m68k/kernel/ptrace.c linux-rtl/arch/m68k/kernel/ptrace.c
--- linux-2.3.14/arch/m68k/kernel/ptrace.c	Fri Aug 20 20:47:01 1999
+++ linux-rtl/arch/m68k/kernel/ptrace.c	Sun Aug 29 01:55:20 1999
@@ -46,11 +46,16 @@
    saved.  Notice that usp has no stack-slot and needs to be treated
    specially (see get_reg/put_reg below). */
 static int regoff[] = {
+#ifdef CONFIG_SYS_STACK
+	PT_REG(d1), SW_REG(d2), SW_REG(d3), SW_REG(d4),
+	SW_REG(d5), SW_REG(d6), SW_REG(d7), PT_REG(a0),
+#else
 	PT_REG(d1), PT_REG(d2), PT_REG(d3), PT_REG(d4),
 	PT_REG(d5), SW_REG(d6), SW_REG(d7), PT_REG(a0),
+#endif
 	PT_REG(a1), PT_REG(a2), SW_REG(a3), SW_REG(a4),
 	SW_REG(a5), SW_REG(a6), PT_REG(d0), -1,
-	PT_REG(orig_d0), PT_REG(sr), PT_REG(pc),
+	PT_REG(syscall), PT_REG(sr), PT_REG(pc),
 };
 
 /*
diff -Nur -X /opt/home/roman/src/m68k_nodiff linux-2.3.14/arch/m68k/kernel/signal.c linux-rtl/arch/m68k/kernel/signal.c
--- linux-2.3.14/arch/m68k/kernel/signal.c	Fri Aug 20 20:47:02 1999
+++ linux-rtl/arch/m68k/kernel/signal.c	Sun Aug 29 01:53:58 1999
@@ -74,7 +74,7 @@
  */
 asmlinkage int do_sigsuspend(struct pt_regs *regs)
 {
-	old_sigset_t mask = regs->d3;
+	old_sigset_t mask = SW_PTR(regs)->d3;
 	sigset_t saveset;
 
 	mask &= _BLOCKABLE;
@@ -95,7 +95,7 @@
 do_rt_sigsuspend(struct pt_regs *regs)
 {
 	sigset_t *unewset = (sigset_t *)regs->d1;
-	size_t sigsetsize = (size_t)regs->d2;
+	size_t sigsetsize = (size_t)SW_PTR(regs)->d2;
 	sigset_t saveset, newset;
 
 	/* XXX: Don't preclude handling different sized sigset_t's.  */
@@ -334,7 +334,7 @@
 	regs->a1 = context.sc_a1;
 	regs->sr = (regs->sr & 0xff00) | (context.sc_sr & 0xff);
 	regs->pc = context.sc_pc;
-	regs->orig_d0 = -1;		/* disable syscall checks */
+	regs->syscall = -1;		/* disable syscall checks */
 	wrusp(context.sc_usp);
 	formatvec = context.sc_formatvec;
 	regs->format = formatvec >> 12;
@@ -415,10 +415,17 @@
 	/* restore passed registers */
 	err |= __get_user(regs->d0, &gregs[0]);
 	err |= __get_user(regs->d1, &gregs[1]);
+#ifdef CONFIG_SYS_STACK
+	err |= __get_user(sw->d2, &gregs[2]);
+	err |= __get_user(sw->d3, &gregs[3]);
+	err |= __get_user(sw->d4, &gregs[4]);
+	err |= __get_user(sw->d5, &gregs[5]);
+#else
 	err |= __get_user(regs->d2, &gregs[2]);
 	err |= __get_user(regs->d3, &gregs[3]);
 	err |= __get_user(regs->d4, &gregs[4]);
 	err |= __get_user(regs->d5, &gregs[5]);
+#endif
 	err |= __get_user(sw->d6, &gregs[6]);
 	err |= __get_user(sw->d7, &gregs[7]);
 	err |= __get_user(regs->a0, &gregs[8]);
@@ -433,7 +440,7 @@
 	err |= __get_user(regs->pc, &gregs[16]);
 	err |= __get_user(temp, &gregs[17]);
 	regs->sr = (regs->sr & 0xff00) | (temp & 0xff);
-	regs->orig_d0 = -1;		/* disable syscall checks */
+	regs->syscall = -1;		/* disable syscall checks */
 	err |= __get_user(temp, &uc->uc_formatvec);
 	regs->format = temp >> 12;
 	regs->vector = temp & 0xfff;
@@ -669,10 +676,17 @@
 	err |= __put_user(MCONTEXT_VERSION, &uc->uc_mcontext.version);
 	err |= __put_user(regs->d0, &gregs[0]);
 	err |= __put_user(regs->d1, &gregs[1]);
+#ifdef CONFIG_SYS_STACK
+	err |= __put_user(sw->d2, &gregs[2]);
+	err |= __put_user(sw->d3, &gregs[3]);
+	err |= __put_user(sw->d4, &gregs[4]);
+	err |= __put_user(sw->d5, &gregs[5]);
+#else
 	err |= __put_user(regs->d2, &gregs[2]);
 	err |= __put_user(regs->d3, &gregs[3]);
 	err |= __put_user(regs->d4, &gregs[4]);
 	err |= __put_user(regs->d5, &gregs[5]);
+#endif
 	err |= __put_user(sw->d6, &gregs[6]);
 	err |= __put_user(sw->d7, &gregs[7]);
 	err |= __put_user(regs->a0, &gregs[8]);
@@ -947,7 +961,7 @@
 	/* fallthrough */
 	case -ERESTARTNOINTR:
 	do_restart:
-		regs->d0 = regs->orig_d0;
+		regs->d0 = regs->syscall;
 		regs->pc -= 2;
 		break;
 	}
@@ -961,7 +975,7 @@
 	      sigset_t *oldset, struct pt_regs *regs)
 {
 	/* are we from a system call? */
-	if (regs->orig_d0 >= 0)
+	if (regs->syscall >= 0)
 		/* If so, check system call restarting.. */
 		handle_restart(regs, ka, 1);
 
@@ -1013,7 +1027,7 @@
 			regs->sr &= ~PS_T;
 
 			/* Did we come from a system call? */
-			if (regs->orig_d0 >= 0) {
+			if (regs->syscall >= 0) {
 				/* Restart the system call the same way as
 				   if the process were not traced.  */
 				struct k_sigaction *ka =
@@ -1112,7 +1126,7 @@
 	}
 
 	/* Did we come from a system call? */
-	if (regs->orig_d0 >= 0)
+	if (regs->syscall >= 0)
 		/* Restart the system call - no handlers present */
 		handle_restart(regs, NULL, 0);
 
diff -Nur -X /opt/home/roman/src/m68k_nodiff linux-2.3.14/arch/m68k/kernel/traps.c linux-rtl/arch/m68k/kernel/traps.c
--- linux-2.3.14/arch/m68k/kernel/traps.c	Fri Aug 20 20:47:03 1999
+++ linux-rtl/arch/m68k/kernel/traps.c	Thu Aug 26 21:48:18 1999
@@ -33,6 +33,7 @@
 #include <asm/fpu.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
+#include <asm/irq.h>
 #include <asm/traps.h>
 #include <asm/pgtable.h>
 #include <asm/machdep.h>
@@ -53,19 +54,14 @@
 	0, 0, buserr, trap, trap, trap, trap, trap,
 	trap, trap, trap, trap, trap, trap, trap, trap,
 	trap, trap, trap, trap, trap, trap, trap, trap,
-	inthandler, inthandler, inthandler, inthandler,
-	inthandler, inthandler, inthandler, inthandler,
+	bad_interrupt, bad_interrupt, bad_interrupt, bad_interrupt,
+	bad_interrupt, bad_interrupt, bad_interrupt, bad_interrupt,
 	/* TRAP #0-15 */
 	system_call, trap, trap, trap, trap, trap, trap, trap,
 	trap, trap, trap, trap, trap, trap, trap, trap,
 	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 };
 
-/* nmi handler for the Amiga */
-asm(".text\n"
-    __ALIGN_STR "\n"
-    SYMBOL_NAME_STR(nmihandler) ": rte");
-
 void __init base_trap_init(void)
 {
 	/* setup the exception vector table */
@@ -132,17 +128,12 @@
 			vectors[i] = trap;
 
 	for (i = 64; i < 256; i++)
-		vectors[i] = inthandler;
+		vectors[i] = bad_interrupt;
 
 #ifdef CONFIG_M68KFPU_EMU
 	if (FPU_IS_EMU)
 		vectors[VEC_LINE11] = fpu_emu;
 #endif
-
-        /* if running on an amiga, make the NMI interrupt do nothing */
-	if (MACH_IS_AMIGA) {
-		vectors[VEC_INT7] = nmihandler;
-	}
 }
 
 
@@ -893,10 +884,8 @@
 	printk("%s: %08x\n",str,nr);
 	printk("PC: [<%08lx>]\nSR: %04x  SP: %p  a2: %08lx\n",
 	       fp->pc, fp->sr, fp, fp->a2);
-	printk("d0: %08lx    d1: %08lx    d2: %08lx    d3: %08lx\n",
-	       fp->d0, fp->d1, fp->d2, fp->d3);
-	printk("d4: %08lx    d5: %08lx    a0: %08lx    a1: %08lx\n",
-	       fp->d4, fp->d5, fp->a0, fp->a1);
+	printk("d0: %08lx  d1: %08lx  a0: %08lx  a1: %08lx\n",
+	       fp->d0, fp->d1, fp->a0, fp->a1);
 
 	printk("Process %s (pid: %d, stackpage=%08lx)\n",
 		current->comm, current->pid, PAGE_SIZE+(unsigned long)current);
diff -Nur -X /opt/home/roman/src/m68k_nodiff linux-2.3.14/arch/m68k/math-emu/fp_entry.S linux-rtl/arch/m68k/math-emu/fp_entry.S
--- linux-2.3.14/arch/m68k/math-emu/fp_entry.S	Fri Aug 20 20:47:14 1999
+++ linux-rtl/arch/m68k/math-emu/fp_entry.S	Wed Aug 25 20:02:40 1999
@@ -47,8 +47,8 @@
 
 	.text
 SYMBOL_NAME_LABEL(fpu_emu)
-	SAVE_ALL_INT
-	GET_CURRENT(%d0)
+	save_all_int
+	get_current
 
 #if defined(CPU_M68020_OR_M68030) && defined(CPU_M68040_OR_M68060)
         tst.l	SYMBOL_NAME(m68k_is040or060)
diff -Nur -X /opt/home/roman/src/m68k_nodiff linux-2.3.14/drivers/video/amifb.c linux-rtl/drivers/video/amifb.c
--- linux-2.3.14/drivers/video/amifb.c	Sun Aug 29 20:24:13 1999
+++ linux-rtl/drivers/video/amifb.c	Sun Aug 29 20:27:15 1999
@@ -599,8 +599,8 @@
 
 #define arraysize(x)	(sizeof(x)/sizeof(*(x)))
 
-#define VBlankOn()	custom.intena = IF_SETCLR|IF_COPER
-#define VBlankOff()	custom.intena = IF_COPER
+#define VBlankOn()	custom.intena = IF_SETCLR|IF_COPPER
+#define VBlankOff()	custom.intena = IF_COPPER
 
 
 	/*
@@ -1785,13 +1785,10 @@
 
 	ami_init_copper();
 
-	if (request_irq(IRQ_AMIGA_AUTO_3, amifb_interrupt, 0,
+	if (request_irq(IRQ_AMIGA_COPPER, amifb_interrupt,
+	                IRQ_FLG_REALTIME|IRQ_FLG_LOCK, 
 	                "fb vertb handler", NULL))
 		panic("Couldn't add vblank interrupt\n");
-	ami_intena_vals[IRQ_AMIGA_VERTB] = IF_COPER;
-	ami_intena_vals[IRQ_AMIGA_COPPER] = 0;
-	custom.intena = IF_VERTB;
-	custom.intena = IF_SETCLR | IF_COPER;
 
 	amifb_set_var(&var, -1, &fb_info);
 
@@ -1876,57 +1873,41 @@
 
 static void amifb_interrupt(int irq, void *dev_id, struct pt_regs *fp)
 {
-	u_short ints = custom.intreqr & custom.intenar;
-	static struct irq_server server = {0, 0};
 	unsigned long flags;
 
-	if (ints & IF_BLIT) {
-		custom.intreq = IF_BLIT;
-		amiga_do_irq(IRQ_AMIGA_BLIT, fp);
-	}
-
-	if (ints & IF_COPER) {
-		custom.intreq = IF_COPER;
-		if (do_vmode_pan || do_vmode_full)
-			ami_update_display();
-
-		if (do_vmode_full)
-			ami_init_display();
-
-		if (do_vmode_pan) {
-			flash_cursor();
-			ami_rebuild_copper();
-			do_cursor = do_vmode_pan = 0;
-		} else if (do_cursor) {
-			flash_cursor();
-			ami_set_sprite();
-			do_cursor = 0;
-		} else {
-			if (flash_cursor())
-				ami_set_sprite();
-		}
+	if (do_vmode_pan || do_vmode_full)
+		ami_update_display();
 
-		save_flags(flags);
-		cli();
-		if (get_vbpos() < down2(currentpar.diwstrt_v - 6))
-			custom.copjmp2 = 0;
-		restore_flags(flags);
+	if (do_vmode_full)
+		ami_init_display();
 
-		if (do_blank) {
-			ami_do_blank();
-			do_blank = 0;
-		}
+	if (do_vmode_pan) {
+		flash_cursor();
+		ami_rebuild_copper();
+		do_cursor = do_vmode_pan = 0;
+	} else if (do_cursor) {
+		flash_cursor();
+		ami_set_sprite();
+		do_cursor = 0;
+	} else {
+		if (flash_cursor())
+			ami_set_sprite();
+	}
 
-		if (do_vmode_full) {
-			ami_reinit_copper();
-			do_vmode_full = 0;
-		}
-		amiga_do_irq_list(IRQ_AMIGA_VERTB, fp, &server);
+	r_save_flags(flags);
+	r_cli();
+	if (get_vbpos() < down2(currentpar.diwstrt_v - 6))
+		custom.copjmp2 = 0;
+	r_restore_flags(flags);
+
+	if (do_blank) {
+		ami_do_blank();
+		do_blank = 0;
 	}
 
-	if (ints & IF_VERTB) {
-		printk("%s: Warning: IF_VERTB was enabled\n", __FUNCTION__);
-		custom.intena = IF_VERTB;
+	if (do_vmode_full) {
+		ami_reinit_copper();
+		do_vmode_full = 0;
 	}
 }
 
@@ -3182,7 +3163,7 @@
 		(cop++)->l = CMOVE2(loww(p), sprpt[i]);
 	}
 
-	(cop++)->l = CMOVE(IF_SETCLR | IF_COPER, intreq);
+	(cop++)->l = CMOVE(IF_SETCLR | IF_COPPER, intreq);
 	copdisplay.wait = cop;
 	(cop++)->l = CEND;
 	(cop++)->l = CMOVE(0, copjmp2);
diff -Nur -X /opt/home/roman/src/m68k_nodiff linux-2.3.14/include/asm-i386/rt.h linux-rtl/include/asm-i386/rt.h
--- linux-2.3.14/include/asm-i386/rt.h	Thu Jan  1 01:00:00 1970
+++ linux-rtl/include/asm-i386/rt.h	Wed Aug  4 21:19:50 1999
@@ -0,0 +1,151 @@
+#ifndef _ASM_I386_ATOMIC_H
+#define _ASM_I386_ATOMIC_H
+
+#ifdef __SMP__
+#else
+#define __LOCK
+#endif
+
+#define __has_bit_instr
+
+#if 0
+
+#define rt_lockdefine( lock )	unsigned long lock
+#define rt_define			unsigned long __rt_flags
+#define rt_enter( lock )		asm volatile ("cli": : :"memory")
+#define rt_leave( lock )		asm volatile ("sti": : :"memory")
+
+#else
+
+#define __has_rt_instr
+
+#define __rt_init( ptr, old ) ({ old = *(ptr); })
+
+#define __rt_reserve( ptr, old )
+
+#define __rt_update( ptr, old, new ) ({			\
+	unsigned char res;					\
+	asm volatile (__LOCK "cmpxchg %3,%1; sete %0"		\
+		: "=q" (res),  "=m" (*(ptr)), "=&a" (old)	\
+		: "r" (new), "1" (*(ptr)), "2" (old));		\
+	res;							\
+})
+
+#define rt_do_exchange( lock, ptr, old, new ) ({		\
+	old = *(ptr);						\
+	asm volatile ("1:"					\
+		: "=&a" (old), "=m" (*(ptr))			\
+		: "0" (old), "1" (*(ptr)));			\
+	asm volatile (__LOCK "cmpxchg %2,%0; jne 1b"		\
+		: "=m" (*(ptr)), "=&a" (old)			\
+		: "r" (new), "0" (*(ptr)), "1" (old));		\
+})
+
+#define rt_inserthead( lock, ptr, old, new ) ({		\
+	typeof(*(ptr)) __val = *(ptr);				\
+	asm volatile ("1:"					\
+		: "=&r" (__val), "=m" (*(ptr))			\
+		: "0" (__val), "1" (*(ptr)));			\
+	old = __val;						\
+	asm volatile (__LOCK "cmpxchg %2,%0; jne 1b"		\
+		: "=m" (*(ptr)), "=&a" (__val)			\
+		: "r" (new), "0" (*(ptr)), "1" (__val));	\
+})
+
+#endif
+
+/* Note: no "lock" prefix even on SMP: xchg always implies lock anyway */
+
+#define rt_do_exchange_const( lock, ptr, old, new ) ({	\
+	asm volatile ("xchg.l %1,%0"				\
+		: "=m" (*(ptr)), "=r" (old)			\
+		: "0" (*(ptr)), "1" (new));			\
+})
+
+#define rt_inc( lock, ptr ) ({				\
+	asm volatile (__LOCK "incl %0"				\
+		: "=m" (*(ptr)) : "0" (*(ptr)));		\
+})
+
+#define rt_dec( lock, ptr ) ({				\
+	asm volatile (__LOCK "decl %0"				\
+		: "=m" (*(ptr)) : "0" (*(ptr)));		\
+})
+
+#define rt_dec_test( lock, ptr ) ({				\
+	unsigned char __res;					\
+								\
+	asm volatile (__LOCK "decl %0; sete %1"			\
+		: "=m" (*(ptr)), "=qm" (__res)			\
+		: "1" (*(ptr)));				\
+	__res != 0;						\
+})
+
+#define rt_add( lock, ptr, val ) ({				\
+	asm volatile (__LOCK "addl %1,%0"			\
+		: "=m" (*(ptr)) : "ir" (val), "0" (*(ptr)));	\
+})
+
+#define rt_sub( lock, ptr, val ) ({				\
+	asm volatile (__LOCK "subl %1,%0"			\
+		: "=m" (*(ptr)) : "ir" (val), "0" (*(ptr)));	\
+})
+
+#define rt_do_setmask( lock, ptr, mask ) ({			\
+	asm volatile (__LOCK "orl %1,%0"			\
+		: "=m" (*(ptr)) : "ir" (val), "0" (*(ptr)));	\
+})
+
+#define rt_do_clrmask( lock, ptr, mask ) ({			\
+	asm volatile (__LOCK "andl %1,%0"			\
+		: "=m" (*(ptr)) : "ir" (~(val)), "0" (*(ptr)));	\
+})
+
+#define rt_do_chgmask( lock, ptr, mask ) ({			\
+	asm volatile (__LOCK "xorl %1,%0"			\
+		: "=m" (*(ptr)) : "ir" (~(val)), "0" (*(ptr)));	\
+})
+
+#define rt_do_setbit( lock, ptr, bit ) ({			\
+	asm volatile (__LOCK "btsl %1,%0"			\
+		: "=m" (*(ptr)) : "Ir" (bit), "0" (*(ptr)));	\
+})
+
+#define rt_do_clrbit( lock, ptr, bit ) ({			\
+	asm volatile (__LOCK "btrl %1,%0"			\
+		: "=m" (*(ptr)) : "Ir" (bit), "0" (*(ptr)));	\
+})
+
+#define rt_do_chgbit( lock, ptr, bit ) ({			\
+	asm volatile (__LOCK "btcl %1,%0"			\
+		: "=m" (*(ptr)) : "Ir" (bit), "0" (*(ptr)));	\
+})
+
+#define rt_do_test_setbit( lock, ptr, bit ) ({		\
+	int __res;						\
+								\
+	asm volatile (__LOCK "btsl %2,%1; tsbbl %0,%0"		\
+		: "=r" (__res), "=m" (*(ptr))			\
+		: "Ir" (bit), "1" (*(ptr)));			\
+	__res;							\
+})
+
+#define rt_do_test_clrbit( lock, ptr, bit ) ({		\
+	int __res;						\
+								\
+	asm volatile (__LOCK "btrl %2,%1; tsbbl %0,%0"		\
+		: "=r" (__res),"=m" (*(ptr))			\
+		: "Ir" (bit), "1" (*(ptr)));			\
+	__res;							\
+})
+
+#define rt_do_test_chgbit( lock, ptr, bit ) ({		\
+	int __res;						\
+								\
+	asm volatile (__LOCK "btcl %2,%1; tsbbl %0,%0"		\
+		: "=r" (__res),"=m" (*(ptr))			\
+		: "Ir" (bit), "1" (*(ptr)));			\
+	__res;							\
+})
+
+#endif /* _ASM_I386_ATOMIC_H */
diff -Nur -X /opt/home/roman/src/m68k_nodiff linux-2.3.14/include/asm-m68k/amigaints.h linux-rtl/include/asm-m68k/amigaints.h
--- linux-2.3.14/include/asm-m68k/amigaints.h	Tue May 18 16:01:03 1999
+++ linux-rtl/include/asm-m68k/amigaints.h	Sun Aug 29 20:33:49 1999
@@ -10,8 +10,12 @@
 ** Created 10/2/92 by Greg Harp
 */
 
-#ifndef _ASMm68k_AMIGAINTS_H_
-#define _ASMm68k_AMIGAINTS_H_
+#ifndef _M68K_AMIGAINTS_H_
+#define _M68K_AMIGAINTS_H_
+
+#include <linux/linkage.h>
+#include <linux/kernel_stat.h>
+#include <asm/irq.h>
 
 /*
 ** Amiga Interrupt sources.
@@ -23,35 +27,21 @@
 #define CIA_IRQS            (5)
 #define AMI_IRQS            (32) /* AUTO_IRQS+AMI_STD_IRQS+2*CIA_IRQS */
 
-/* vertical blanking interrupt */
-#define IRQ_AMIGA_VERTB     0
-
-/* copper interrupt */
-#define IRQ_AMIGA_COPPER    1
-
-/* Audio interrupts */
-#define IRQ_AMIGA_AUD0	    2
-#define IRQ_AMIGA_AUD1	    3
-#define IRQ_AMIGA_AUD2	    4
-#define IRQ_AMIGA_AUD3	    5
-
-/* Blitter done interrupt */
-#define IRQ_AMIGA_BLIT	    6
-
-/* floppy disk interrupts */
-#define IRQ_AMIGA_DSKSYN    7
-#define IRQ_AMIGA_DSKBLK    8
-
-/* builtin serial port interrupts */
-#define IRQ_AMIGA_RBF	    9
-#define IRQ_AMIGA_TBE	    10
-
-/* software interrupts */
-#define IRQ_AMIGA_SOFT      11
-
-/* interrupts from external hardware */
-#define IRQ_AMIGA_PORTS	    12
-#define IRQ_AMIGA_EXTER	    13
+/* Amiga standard interrupt sources */
+#define IRQ_AMIGA_TBE		0
+#define IRQ_AMIGA_DSKBLK	1
+#define IRQ_AMIGA_SOFT		2
+#define IRQ_AMIGA_PORTS		3
+#define IRQ_AMIGA_COPPER	4
+#define IRQ_AMIGA_VERTB		5
+#define IRQ_AMIGA_BLIT		6
+#define IRQ_AMIGA_AUD0		7
+#define IRQ_AMIGA_AUD1		8
+#define IRQ_AMIGA_AUD2		9
+#define IRQ_AMIGA_AUD3		10
+#define IRQ_AMIGA_RBF		11
+#define IRQ_AMIGA_DSKSYN	12
+#define IRQ_AMIGA_EXTER		13
 
 /* CIA interrupt sources */
 #define IRQ_AMIGA_CIAA      14
@@ -78,8 +68,6 @@
 #define IRQ_AMIGA_AUTO_6    30
 #define IRQ_AMIGA_AUTO_7    31
 
-#define IRQ_FLOPPY	    IRQ_AMIGA_DSKBLK
-
 /* INTREQR masks */
 #define IRQ1_MASK   0x0007	/* INTREQR mask for IRQ 1 */
 #define IRQ2_MASK   0x0008	/* INTREQR mask for IRQ 2 */
@@ -100,21 +88,54 @@
 #define IF_AUD0     0x0080	/* audio channel 0 done interrupt */
 #define IF_BLIT     0x0040	/* blitter done interrupt */
 #define IF_VERTB    0x0020	/* vertical blanking interrupt */
-#define IF_COPER    0x0010	/* copper interrupt */
+#define IF_COPPER   0x0010	/* copper interrupt */
 #define IF_PORTS    0x0008	/* external level 2 and CIA A interrupt */
 #define IF_SOFT     0x0004	/* software initiated interrupt */
 #define IF_DSKBLK   0x0002	/* diskblock DMA finished */
 #define IF_TBE	    0x0001	/* serial transmit buffer empty interrupt */
 
-struct irq_server {
-	unsigned short count, reentrance;
-};
+extern unsigned short amiga_slowintmask, amiga_fastintmask;
 
-extern void amiga_do_irq(int irq, struct pt_regs *fp);
-extern void amiga_do_irq_list(int irq, struct pt_regs *fp, struct irq_server *server);
+asmlinkage void amiga_inthandler(void);
+asmlinkage void amiga_nmi_handler(void);
+asmlinkage void amiga_do_slowirq_request(void);
+
+extern inline void amiga_do_irq(int irq, struct pt_regs *fp)
+{
+	kstat.irqs[0][AUTO_IRQ_NR + irq]++;
+	userirq_list[irq]->handler(irq, userirq_list[irq]->dev_id, fp);
+}
+
+extern inline void amiga_do_irq_list(int irq, struct pt_regs *fp)
+{
+	irq_node_t *node;
+
+	kstat.irqs[0][AUTO_IRQ_NR + irq]++;
+	/* serve handlers */
+	for (node = userirq_list[irq]; node; node = node->next)
+		node->handler(irq, node->dev_id, fp);
+}
+
+extern inline void amiga_do_slowirq(int irq, struct pt_regs *fp)
+{
+	kstat.irqs[0][AUTO_IRQ_NR + irq]++;
+	userirq_slowlist[irq]->handler(irq, userirq_slowlist[irq]->dev_id, fp);
+}
+
+extern inline void amiga_do_slowirq_list(int irq, struct pt_regs *fp)
+{
+	irq_node_t *node;
+
+	/* serve handlers */
+	for (node = userirq_slowlist[irq]; node; node = node->next)
+		node->handler(irq, node->dev_id, fp);
+}
 
-/* CIA interrupt control register bits */
+/*
+ * CIA specific definitions
+ */
 
+/* CIA interrupt control register bits */
 #define CIA_ICR_TA	0x01
 #define CIA_ICR_TB	0x02
 #define CIA_ICR_ALRM	0x04
@@ -132,4 +153,4 @@
 extern unsigned char cia_set_irq(struct ciabase *base, unsigned char mask);
 extern unsigned char cia_able_irq(struct ciabase *base, unsigned char mask);
 
-#endif /* asm-m68k/amigaints.h */
+#endif /* _M68K_AMIGAINTS_H_ */
diff -Nur -X /opt/home/roman/src/m68k_nodiff linux-2.3.14/include/asm-m68k/elf.h linux-rtl/include/asm-m68k/elf.h
--- linux-2.3.14/include/asm-m68k/elf.h	Tue May 18 16:01:03 1999
+++ linux-rtl/include/asm-m68k/elf.h	Sun Aug 29 16:00:50 1999
@@ -42,31 +42,57 @@
 
 #define ELF_ET_DYN_BASE         0xD0000000UL
 
+#ifdef CONFIG_SYS_STACK
 #define ELF_CORE_COPY_REGS(pr_reg, regs)				\
-	/* Bleech. */							\
-	pr_reg[0] = regs->d1;						\
-	pr_reg[1] = regs->d2;						\
-	pr_reg[2] = regs->d3;						\
-	pr_reg[3] = regs->d4;						\
-	pr_reg[4] = regs->d5;						\
-	pr_reg[7] = regs->a0;						\
-	pr_reg[8] = regs->a1;						\
-	pr_reg[9] = regs->a2;						\
-	pr_reg[14] = regs->d0;						\
-	pr_reg[15] = rdusp();						\
-	pr_reg[16] = regs->orig_d0;					\
-	pr_reg[17] = regs->sr;						\
-	pr_reg[18] = regs->pc;						\
-	pr_reg[19] = (regs->format << 12) | regs->vector;		\
-	{								\
-	  struct switch_stack *sw = ((struct switch_stack *)regs) - 1;	\
-	  pr_reg[5] = sw->d6;						\
-	  pr_reg[6] = sw->d7;						\
-	  pr_reg[10] = sw->a3;						\
-	  pr_reg[11] = sw->a4;						\
-	  pr_reg[12] = sw->a5;						\
-	  pr_reg[13] = sw->a6;						\
-	}
+{									\
+	struct switch_stack *sw = ((struct switch_stack *)regs) - 1;	\
+	pr_reg[PT_D0] = regs->d0;					\
+	pr_reg[PT_D1] = regs->d1;					\
+	pr_reg[PT_D2] = sw->d2;						\
+	pr_reg[PT_D3] = sw->d3;						\
+	pr_reg[PT_D4] = sw->d4;						\
+	pr_reg[PT_D5] = sw->d5;						\
+	pr_reg[PT_D6] = sw->d6;						\
+	pr_reg[PT_D7] = sw->d7;						\
+	pr_reg[PT_A0] = regs->a0;					\
+	pr_reg[PT_A1] = regs->a1;					\
+	pr_reg[PT_A2] = regs->a2;					\
+	pr_reg[PT_A3] = sw->a3;						\
+	pr_reg[PT_A4] = sw->a4;						\
+	pr_reg[PT_A5] = sw->a5;						\
+	pr_reg[PT_A6] = sw->a6;						\
+	pr_reg[PT_USP] = rdusp();					\
+	pr_reg[PT_ORIG_D0] = regs->syscall;				\
+	pr_reg[PT_SR] = regs->sr;					\
+	pr_reg[PT_PC] = regs->pc;					\
+	pr_reg[PT_VEC] = (regs->format << 12) | regs->vector;		\
+}
+#else
+#define ELF_CORE_COPY_REGS(pr_reg, regs)				\
+{									\
+	struct switch_stack *sw = ((struct switch_stack *)regs) - 1;	\
+	pr_reg[PT_D0] = regs->d0;					\
+	pr_reg[PT_D1] = regs->d1;					\
+	pr_reg[PT_D2] = regs->d2;					\
+	pr_reg[PT_D3] = regs->d3;					\
+	pr_reg[PT_D4] = regs->d4;					\
+	pr_reg[PT_D5] = regs->d5;					\
+	pr_reg[PT_D6] = sw->d6;						\
+	pr_reg[PT_D7] = sw->d7;						\
+	pr_reg[PT_A0] = regs->a0;					\
+	pr_reg[PT_A1] = regs->a1;					\
+	pr_reg[PT_A2] = regs->a2;					\
+	pr_reg[PT_A3] = sw->a3;						\
+	pr_reg[PT_A4] = sw->a4;						\
+	pr_reg[PT_A5] = sw->a5;						\
+	pr_reg[PT_A6] = sw->a6;						\
+	pr_reg[PT_USP] = rdusp();					\
+	pr_reg[PT_ORIG_D0] = regs->syscall;				\
+	pr_reg[PT_SR] = regs->sr;					\
+	pr_reg[PT_PC] = regs->pc;					\
+	pr_reg[PT_VEC] = (regs->format << 12) | regs->vector;		\
+}
+#endif
 
 /* This yields a mask that user programs can use to figure out what
    instruction set this cpu supports.  */
diff -Nur -X /opt/home/roman/src/m68k_nodiff linux-2.3.14/include/asm-m68k/entry.h linux-rtl/include/asm-m68k/entry.h
--- linux-2.3.14/include/asm-m68k/entry.h	Tue May 18 16:01:03 1999
+++ linux-rtl/include/asm-m68k/entry.h	Sun Aug 29 16:02:41 1999
@@ -59,13 +59,10 @@
 PF_DTRACE_OFF = 1
 PF_DTRACE_BIT = 5
 
-#define SAVE_ALL_INT save_all_int
-#define SAVE_ALL_SYS save_all_sys
-#define RESTORE_ALL restore_all
 /*
  * This defines the normal kernel pt-regs layout.
  *
- * regs a3-a6 and d6-d7 are preserved by C code
+ * regs a3-a6 and d2-d7 are preserved by C code
  * the kernel doesn't mess with usp unless it needs to
  */
 #ifndef CONFIG_KGDB
@@ -75,62 +72,108 @@
  */
 .macro	save_all_int
 	clrl	%sp@-		| stk_adj
-	pea	-1:w		| orig d0
+	pea	-1:w		| syscall
+#ifdef CONFIG_SYS_STACK
+	moveml	%d0/%d1/%a0/%a1/%curptr,%sp@-
+#else
 	movel	%d0,%sp@-	| d0
 	moveml	%d1-%d5/%a0-%a1/%curptr,%sp@-
+#endif
 .endm
 
 .macro	save_all_sys
 	clrl	%sp@-		| stk_adj
-	movel	%d0,%sp@-	| orig d0
+	movel	%d0,%sp@-	| syscall
+#ifdef CONFIG_SYS_STACK
+	moveml	%d0/%d1/%a0/%a1/%curptr,%sp@-
+#else
 	movel	%d0,%sp@-	| d0
 	moveml	%d1-%d5/%a0-%a1/%curptr,%sp@-
+#endif
 .endm
+
 #else
 /* Need to save the "missing" registers for kgdb...
  */
 .macro	save_all_int
 	clrl	%sp@-		| stk_adj
-	pea	-1:w		| orig d0
-	movel	%d0,%sp@-	| d0
-	moveml	%d1-%d5/%a0-%a1/%curptr,%sp@-
+	moveml	%d0/%d1/%a0/%a1/%curptr,%sp@-
 	moveml	%d6-%d7,kgdb_registers+GDBOFFA_D6
 	moveml	%a3-%a6,kgdb_registers+GDBOFFA_A3
 .endm
 
-.macro	save_all_sys
-	clrl	%sp@-		| stk_adj
-	movel	%d0,%sp@-	| orig d0
-	movel	%d0,%sp@-	| d0
-	moveml	%d1-%d5/%a0-%a1/%curptr,%sp@-
-	moveml	%d6-%d7,kgdb_registers+GDBOFFA_D6
-	moveml	%a3-%a6,kgdb_registers+GDBOFFA_A3
-.endm
 #endif
 
-.macro	restore_all
-	moveml	%sp@+,%a0-%a1/%curptr/%d1-%d5
-	movel	%sp@+,%d0
-	addql	#4,%sp		| orig d0
-	addl	%sp@+,%sp	| stk adj
-	rte
+.macro	save_sys_stack
+#ifdef CONFIG_SYS_STACK
+	moveml	%d1-%d5,%sp@-
+#endif
 .endm
 
-#define SWITCH_STACK_SIZE (6*4+4)	/* includes return address */
+.macro	rebuild_sys_stack
+#ifdef CONFIG_SYS_STACK
+	movel	%sp@(PT_D1),%d1
+	moveml	%d1-%d5,%sp@-
+#endif
+.endm
 
-#define SAVE_SWITCH_STACK save_switch_stack
-#define RESTORE_SWITCH_STACK restore_switch_stack
-#define GET_CURRENT(tmp) get_current tmp
+.macro	drop_sys_stack
+#ifdef CONFIG_SYS_STACK
+	lea	%sp@(20),%sp
+#endif
+.endm
 
 .macro	save_switch_stack
-	moveml	%a3-%a6/%d6-%d7,%sp@-
+#ifdef CONFIG_SYS_STACK
+	moveml	%d2-%d7/%a3-%a6,%sp@-
+#else
+	moveml	%d6-%d7/%a3-%a6,%sp@-
+#endif
 .endm
 
 .macro	restore_switch_stack
-	moveml	%sp@+,%a3-%a6/%d6-%d7
+#ifdef CONFIG_SYS_STACK
+	moveml	%sp@+,%d2-%d7/%a3-%a6
+#else
+	moveml	%sp@+,%d6-%d7/%a3-%a6
+#endif
+.endm
+
+.macro	changeto_switch_stack
+#ifdef CONFIG_SYS_STACK
+	movel	%sp@+,%d1
+	drop_sys_stack
+	movel	%d1,%sp@-
+#endif
+	save_switch_stack
+.endm
+
+.macro	changeto_sys_stack	nodrop=0
+	.if	\nodrop
+	restore_switch_stack
+	.else
+	lea	%sp@(SW_SIZEOF-4),%sp
+	.endif
+#ifdef CONFIG_SYS_STACK
+	movel	%sp@+,%d1
+	lea	%sp@(-SC_SIZEOF),%sp
+	movel	%d1,%sp@-
+#endif
+.endm
+
+.macro	restore_all
+#ifdef CONFIG_SYS_STACK
+	moveml	%sp@+,%d0/%d1/%a0/%a1/%curptr
+#else
+	moveml	%sp@+,%d1-%d5/%a0-%a1/%curptr
+	movel	%sp@+,%d0
+#endif
+	addql	#4,%sp		| syscall
+	addl	%sp@+,%sp	| stk adj
+	rte
 .endm
 
-.macro	get_current reg=%d0
+.macro	get_current reg=%d1
 	movel	%sp,\reg
 	andw	#-8192,\reg
 	movel	\reg,%curptr
diff -Nur -X /opt/home/roman/src/m68k_nodiff linux-2.3.14/include/asm-m68k/hardirq.h linux-rtl/include/asm-m68k/hardirq.h
--- linux-2.3.14/include/asm-m68k/hardirq.h	Tue Aug 10 20:24:42 1999
+++ linux-rtl/include/asm-m68k/hardirq.h	Wed Aug 25 21:19:53 1999
@@ -7,7 +7,11 @@
 
 #define in_interrupt() (local_irq_count[smp_processor_id()] + local_bh_count[smp_processor_id()] != 0)
 
-#define hardirq_trylock(cpu)	(local_irq_count[cpu] == 0)
+/* the bottomhalf is already protected by softirq_trylock() and
+ * the interrupt exit guarantees already that do_bottom_half()
+ * is only called from the last interrupt
+ */
+#define hardirq_trylock(cpu)	(1)
 #define hardirq_endlock(cpu)	do { } while (0)
 
 #define hardirq_enter(cpu)	(local_irq_count[cpu]++)
diff -Nur -X /opt/home/roman/src/m68k_nodiff linux-2.3.14/include/asm-m68k/irq.h linux-rtl/include/asm-m68k/irq.h
--- linux-2.3.14/include/asm-m68k/irq.h	Fri Aug 20 20:56:31 1999
+++ linux-rtl/include/asm-m68k/irq.h	Sun Aug 29 20:17:41 1999
@@ -4,46 +4,32 @@
 #include <linux/config.h>
 
 /*
- * # of m68k interrupts
+ * # of auto and user vector m68k interrupts. This number is used for kstat, so
+ * the first 8 are always the autovector interrupts, the rest is machine
+ * specific. It can be either the # of used vector interrupts or the # of other
+ * interrupt sources. The highest value wins if compiled for several machines.
  */
 
-#define SYS_IRQS 8
+#define AUTO_IRQ_NR 8
 
-/*
- * This should be the same as the max(NUM_X_SOURCES) for all the
- * different m68k hosts compiled into the kernel.
- * Currently the Atari has 72 and the Amiga 24, but if both are
- * supported in the kernel it is better to make room for 72.
- */
 #if defined(CONFIG_ATARI)
-#define NR_IRQS (72+SYS_IRQS)
+#define USER_IRQ_NR 72
+#elif defined(CONFIG_AMIGA)
+#define USER_IRQ_NR 24
+#elif defined(CONFIG_APOLLO)
+#define USER_IRQ_NR 16
 #else
-#define NR_IRQS (24+SYS_IRQS)
+#define USER_IRQ_NR 0
 #endif
 
 /*
- * Interrupt source definitions
- * General interrupt sources are the level 1-7.
- * Adding an interrupt service routine for one of these sources
- * results in the addition of that routine to a chain of routines.
- * Each one is called in succession.  Each individual interrupt
- * service routine should determine if the device associated with
- * that routine requires service.
- */
-
-#define IRQ1		(1)	/* level 1 interrupt */
-#define IRQ2		(2)	/* level 2 interrupt */
-#define IRQ3		(3)	/* level 3 interrupt */
-#define IRQ4		(4)	/* level 4 interrupt */
-#define IRQ5		(5)	/* level 5 interrupt */
-#define IRQ6		(6)	/* level 6 interrupt */
-#define IRQ7		(7)	/* level 7 interrupt (non-maskable) */
-
-/*
- * "Generic" interrupt sources
+ * This should be the same as the max(NUM_X_SOURCES) for all the
+ * different m68k hosts compiled into the kernel.
  */
 
-#define IRQ_SCHED_TIMER	(8)    /* interrupt source for scheduling timer */
+#define NR_IRQS (AUTO_IRQ_NR+USER_IRQ_NR)
+
+#ifndef __ASSEMBLY__
 
 static __inline__ int irq_cannonicalize(int irq)
 {
@@ -83,12 +69,20 @@
  * mechanism like all other architectures - SA_INTERRUPT and SA_SHIRQ
  * are your friends.
  */
-#ifndef CONFIG_AMIGA
 #define IRQ_FLG_LOCK	(0x0001)	/* handler is not replaceable	*/
 #define IRQ_FLG_REPLACE	(0x0002)	/* replace existing handler	*/
 #define IRQ_FLG_FAST	(0x0004)
 #define IRQ_FLG_SLOW	(0x0008)
-#define IRQ_FLG_STD	(0x8000)	/* internally used		*/
+#define IRQ_FLG_LIST	(0x0010)
+#define IRQ_FLG_REALTIME (0x0020)
+
+/* only used by the interrupt management! depending on the config option
+ * IRQ_FLG_FASTQUEUE decides about on which queue a handler is put on.
+ */
+#ifdef CONFIG_RT_INTERRUPT
+#define IRQ_FLG_FASTQUEUE IRQ_FLG_REALTIME
+#else
+#define IRQ_FLG_FASTQUEUE IRQ_FLG_FAST
 #endif
 
 /*
@@ -103,22 +97,34 @@
 	struct irq_node *next;
 } irq_node_t;
 
-/*
- * This structure has only 4 elements for speed reasons
- */
-typedef struct irq_handler {
-	void		(*handler)(int, void *, struct pt_regs *);
-	unsigned long	flags;
-	void		*dev_id;
-	const char	*devname;
-} irq_handler_t;
+extern int sys_request_irq(unsigned int, void (*)(int, void *, struct pt_regs *), 
+                           unsigned long, const char *, void *);
+extern int sys_request_listirq(unsigned int, void (*)(int, void *, struct pt_regs *), 
+                               unsigned long, const char *, void *);
+extern void sys_free_irq(unsigned int, void *);
+
+extern irq_node_t *autoirq_list[];
+extern irq_node_t *userirq_list[];
+extern irq_node_t *autoirq_slowlist[];
+extern irq_node_t *userirq_slowlist[];
+extern volatile int slowirq_busycnt;
 
 /* count of spurious interrupts */
 extern volatile unsigned int num_spurious;
+extern volatile int slowirq_request;
+
+/* standard interrupt handlers */
+asmlinkage void autoirq_handler(void);
+asmlinkage void autoirq_listhandler(void);
+asmlinkage void userirq_handler(void);
+asmlinkage void bad_interrupt(void);
 
 /*
  * This function returns a new irq_node_t
  */
 extern irq_node_t *new_irq_node(void);
+extern void free_irq_node(irq_node_t *);
+
+#endif /* __ASSEMBLY__ */
 
 #endif /* _M68K_IRQ_H_ */
diff -Nur -X /opt/home/roman/src/m68k_nodiff linux-2.3.14/include/asm-m68k/m68kserial.h linux-rtl/include/asm-m68k/m68kserial.h
--- linux-2.3.14/include/asm-m68k/m68kserial.h	Fri Aug 20 21:14:08 1999
+++ linux-rtl/include/asm-m68k/m68kserial.h	Sun Aug 29 20:30:34 1999
@@ -337,7 +337,7 @@
 					    int ch, int err )
 {
 	struct tty_struct *tty = info->tty;
-	
+
 	if (tty->flip.count >= TTY_FLIPBUF_SIZE)
 		return;
 	tty->flip.count++;
diff -Nur -X /opt/home/roman/src/m68k_nodiff linux-2.3.14/include/asm-m68k/machdep.h linux-rtl/include/asm-m68k/machdep.h
--- linux-2.3.14/include/asm-m68k/machdep.h	Tue May 18 16:01:03 1999
+++ linux-rtl/include/asm-m68k/machdep.h	Wed Aug 25 21:29:44 1999
@@ -15,14 +15,12 @@
 extern void (*mach_kbd_leds) (unsigned int);
 /* machine dependent irq functions */
 extern void (*mach_init_IRQ) (void);
-extern void (*(*mach_default_handler)[]) (int, void *, struct pt_regs *);
 extern int (*mach_request_irq) (unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
                                 unsigned long flags, const char *devname, void *dev_id);
 extern void (*mach_free_irq) (unsigned int irq, void *dev_id);
 extern void (*mach_get_model) (char *model);
 extern int (*mach_get_hardware_list) (char *buffer);
 extern int (*mach_get_irq_list) (char *buf);
-extern void (*mach_process_int) (int irq, struct pt_regs *fp);
 /* machine dependent timer functions */
 extern unsigned long (*mach_gettimeoffset)(void);
 extern void (*mach_gettod)(int *year, int *mon, int *day, int *hour,
diff -Nur -X /opt/home/roman/src/m68k_nodiff linux-2.3.14/include/asm-m68k/ptrace.h linux-rtl/include/asm-m68k/ptrace.h
--- linux-2.3.14/include/asm-m68k/ptrace.h	Tue May 18 16:01:03 1999
+++ linux-rtl/include/asm-m68k/ptrace.h	Sun Aug 29 15:57:06 1999
@@ -1,6 +1,8 @@
 #ifndef _M68K_PTRACE_H
 #define _M68K_PTRACE_H
 
+#include <linux/config.h>
+
 #define PT_D1	   0
 #define PT_D2	   1
 #define PT_D3	   2
@@ -20,28 +22,37 @@
 #define PT_ORIG_D0 16
 #define PT_SR	   17
 #define PT_PC	   18
+#define PT_VEC	   19
 
 #ifndef __ASSEMBLY__
 
 /* this struct defines the way the registers are stored on the
-   stack during a system call. */
+   stack during an exception. */
 
 struct pt_regs {
-  long     d1;
-  long     d2;
-  long     d3;
-  long     d4;
-  long     d5;
-  long     a0;
-  long     a1;
-  long     a2;
-  long     d0;
-  long     orig_d0;
-  long     stkadj;
-  unsigned short sr;
-  unsigned long  pc;
-  unsigned format :  4; /* frame format specifier */
-  unsigned vector : 12; /* vector offset */
+#ifdef CONFIG_SYS_STACK
+	unsigned long  d0;
+	unsigned long  d1;
+	unsigned long  a0;
+	unsigned long  a1;
+	unsigned long  a2;
+#else
+	unsigned long  d1;
+	unsigned long  d2;
+	unsigned long  d3;
+	unsigned long  d4;
+	unsigned long  d5;
+	unsigned long  a0;
+	unsigned long  a1;
+	unsigned long  a2;
+	unsigned long  d0;
+#endif
+	unsigned long  syscall;
+	unsigned long  stkadj;
+	unsigned short sr;
+	unsigned long  pc;
+	unsigned format :  4; /* frame format specifier */
+	unsigned vector : 12; /* vector offset */
 };
 
 /*
@@ -49,6 +60,12 @@
  * switcher: it's pushed after the normal "struct pt_regs".
  */
 struct switch_stack {
+#ifdef CONFIG_SYS_STACK
+	unsigned long  d2;
+	unsigned long  d3;
+	unsigned long  d4;
+	unsigned long  d5;
+#endif
 	unsigned long  d6;
 	unsigned long  d7;
 	unsigned long  a3;
@@ -57,6 +74,24 @@
 	unsigned long  a6;
 	unsigned long  retpc;
 };
+
+#ifdef CONFIG_SYS_STACK
+/* this macro can be used to get access to the switch_stack in front of pt_regs */ 
+#define SW_PTR(pt_ptr)	((struct switch_stack *)(pt_ptr)-1)
+
+/*
+ * This is the stack used during system calls for the arguments
+ */
+struct syscall_stack {
+	unsigned long  d1;
+	unsigned long  d2;
+	unsigned long  d3;
+	unsigned long  d4;
+	unsigned long  d5;
+};
+#else
+#define SW_PTR(pt_ptr)	(pt_ptr)
+#endif
 
 /* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
 #define PTRACE_GETREGS            12
diff -Nur -X /opt/home/roman/src/m68k_nodiff linux-2.3.14/include/asm-m68k/rt.h linux-rtl/include/asm-m68k/rt.h
--- linux-2.3.14/include/asm-m68k/rt.h	Thu Jan  1 01:00:00 1970
+++ linux-rtl/include/asm-m68k/rt.h	Sun Aug 29 01:32:35 1999
@@ -0,0 +1,163 @@
+#ifndef _ASM_M68K_ATOMIC_H
+#define _ASM_M68K_ATOMIC_H
+
+#include <linux/config.h>
+
+#ifndef CONFIG_RMW_INSNS
+
+#define __has_bit_instr
+
+#define rt_lockdeclare(lock)
+#define rt_lockdefine(lock)
+#define rt_flagsdefine	unsigned long __rt_flags
+#define rt_enter(lock) \
+	asm volatile ("movew %%sr,%0; oriw #0x0700,%%sr" : "=d" (__rt_flags) : :"memory")
+#define rt_leave(lock) \
+	asm volatile ("movew %0,%%sr": : "d" (__rt_flags) :"memory")
+
+#else
+
+#define __has_rt_instr
+
+#define __rt_init( ptr , data )	((data) = *(ptr))
+
+#define __rt_reserve( ptr, data )
+
+#define __rt_update( ptr, data, new ) ({			\
+	unsigned char res;					\
+								\
+	asm volatile ( "cas.l %3,%4,%5; seq %0"			\
+		: "=d" (res), "=&d" (data), "=m" (*(ptr))	\
+		: "1" (data), "d" (new), "2" (*(ptr)));		\
+	res;							\
+})
+
+#define rt_do_exchange( lock, ptr, old, new ) ({		\
+	old = *(ptr);						\
+	asm volatile ("1:"					\
+		: "=&d" (old), "=m" (*(ptr))			\
+		: "0" (old), "1" (*(ptr)));			\
+	asm volatile ("cas.l %2,%3,%4; jne 1b"			\
+		: "=&d" (old), "=m" (*(ptr))			\
+		: "0" (old), "d" (new), "1" (*(ptr)));		\
+})
+
+#define rt_do_exchange_const( lock, ptr, old, new ) ({	\
+	asm volatile ("1: cas.l %2,%3,%4; jne 1b"		\
+		: "=&d" (old), "=m" (*(ptr))			\
+		: "0" (*(ptr)), "d" (new), "1" (*(ptr)));	\
+})
+
+#define rt_inserthead( lock, ptr, old, new ) ({		\
+	typeof(*(ptr)) __val = *(ptr);				\
+								\
+	asm volatile ( "1:"					\
+		: "=&d" (__val), "=m" (*(ptr))			\
+		: "0" (__val), "1" (*(ptr)));			\
+	old = __val;						\
+	asm volatile ( "cas.l %2,%3,%4; jne 1b"			\
+		: "=&d" (__val), "=m" (*(ptr))			\
+		: "0" (__val), "d" (new), "1" (*(ptr)) );	\
+})
+
+#endif
+
+#define rt_inc( lock, ptr ) ({				\
+	asm volatile ("addq.l #1,%0"				\
+		: "=m" (*(ptr)): "0" (*(ptr)));			\
+})
+
+#define rt_dec( lock, ptr ) ({				\
+	asm volatile ("subq.l #1,%0"				\
+		: "=m" (*(ptr)): "0" (*(ptr)));			\
+})
+
+#define rt_dec_test( lock, ptr ) ({				\
+	unsigned char res;					\
+								\
+	asm volatile ( "subq.l #1,%1; sne %0"			\
+		: "=d" (res), "=m" (*(ptr)) : "1" (*(ptr)) );	\
+	res != 0;						\
+})
+
+
+#define rt_add( lock, ptr, val ) ({				\
+	asm volatile ( "add.l %1,%0": "=m" (*(ptr))		\
+		: "d" (val), "0" (*(ptr)) );			\
+})
+
+#define rt_sub( lock, ptr, val ) ({				\
+	asm volatile ( "sub.l %1,%0": "=m" (*(ptr))		\
+		: "d" (val), "0" (*(ptr)) );			\
+})
+
+#define rt_do_setmask( lock, ptr, mask ) ({			\
+	asm volatile ( "or.l %1,%0": "=m" (*(ptr))		\
+		: "d" (mask), "0" (*(ptr)) );			\
+})
+
+#define rt_do_clrmask( lock, ptr, mask ) ({			\
+	asm volatile ( "and.l %1,%0": "=m" (*(ptr))		\
+		: "d" (~(mask)), "0" (*(ptr)) );		\
+})
+
+#define rt_do_chgmask( lock, ptr, mask ) ({			\
+	asm volatile ( "xor.l %1,%0": "=m" (*(ptr))		\
+		: "d" (mask), "0" (*(ptr)) );			\
+})
+
+#define rt_do_setbit( lock, ptr, bit ) ({			\
+	unsigned char *__ptr;					\
+								\
+	__ptr = (unsigned char *)(ptr) + (3 - (bit >> 3));	\
+	asm volatile ( "bset %1,%0": "=m" (*(__ptr))		\
+		: "id" (bit & 7), "0" (*(__ptr)) );		\
+})
+
+#define rt_do_clrbit( lock, ptr, bit ) ({			\
+	unsigned char *__ptr;					\
+								\
+	__ptr = (unsigned char *)(ptr) + (3 - (bit >> 3));	\
+	asm volatile ( "bclr %1,%0": "=m" (*(__ptr))		\
+		: "id" (bit & 7), "0" (*(__ptr)) );		\
+})
+
+#define rt_do_chgbit( lock, ptr, bit ) ({			\
+	unsigned char *__ptr;					\
+								\
+	__ptr = (unsigned char *)(ptr) + (3 - (bit >> 3));	\
+	asm volatile ( "bchg %1,%0": "=m" (*(__ptr))		\
+		: "id" (bit & 7), "0" (*(__ptr)) );		\
+})
+
+#define rt_do_test_setbit( lock, ptr, bit ) ({		\
+	unsigned char *__ptr, __res;				\
+								\
+	__ptr = (unsigned char *)(ptr) + (3 - (bit >> 3));	\
+	asm volatile ( "bset %2,%1; sne %0"			\
+		: "=r" (__res), "=m" (*(__ptr))			\
+		: "id" (bit & 7), "1" (*(__ptr)) );		\
+	__res;							\
+})
+
+#define rt_do_test_clrbit( lock, ptr, bit ) ({		\
+	unsigned char *__ptr, __res;				\
+								\
+	__ptr = (unsigned char *)(ptr) + (3 - (bit >> 3));	\
+	asm volatile ( "bclr %2,%1; sne %0"			\
+		: "=r" (__res), "=m" (*(__ptr))			\
+		: "id" (bit & 7), "1" (*(__ptr)) );		\
+	__res;							\
+})
+
+#define rt_do_test_chgbit( lock, ptr, bit ) ({		\
+	unsigned char *__ptr, __res;				\
+								\
+	__ptr = (unsigned char *)(ptr) + (3 - (bit >> 3));	\
+	asm volatile ( "bchg %2,%1; sne %0"			\
+		: "=r" (__res), "=m" (*(__ptr))			\
+		: "id" (bit & 7), "1" (*(__ptr)) );		\
+	__res;							\
+})
+
+#endif /* _ASM_M68K_ATOMIC_H */
diff -Nur -X /opt/home/roman/src/m68k_nodiff linux-2.3.14/include/asm-m68k/system.h linux-rtl/include/asm-m68k/system.h
--- linux-2.3.14/include/asm-m68k/system.h	Tue Aug 10 20:24:53 1999
+++ linux-rtl/include/asm-m68k/system.h	Sun Aug 29 12:36:19 1999
@@ -3,7 +3,9 @@
 
 #include <linux/config.h> /* get configuration macros */
 #include <linux/linkage.h>
+#include <linux/rt.h>
 #include <asm/segment.h>
+#include <asm/hardirq.h>
 
 #define prepare_to_switch()	do { } while(0)
 
@@ -34,6 +36,17 @@
  * the mm structures are shared in d2 (to avoid atc flushing).
  */
 asmlinkage void resume(void);
+#ifdef CONFIG_SYS_STACK
+#define switch_to(prev,next,last) {					\
+  register void *_prev __asm__ ("a0") = (prev);				\
+  register void *_next __asm__ ("a1") = (next);				\
+  register void *_last __asm__ ("d1");					\
+  __asm__ __volatile__("jbsr " SYMBOL_NAME_STR(resume)			\
+		       : "=d" (_last) : "a" (_prev), "a" (_next)	\
+		       : "d0", "d1", "a0", "a1");			\
+  (last) = _last;							\
+}
+#else
 #define switch_to(prev,next,last) { \
   register void *_prev __asm__ ("a0") = (prev); \
   register void *_next __asm__ ("a1") = (next); \
@@ -43,6 +56,7 @@
 		       : "d0", "d1", "d2", "d3", "d4", "d5", "a0", "a1"); \
   (last) = _last; \
 }
+#endif
 
 #define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
 #define tas(ptr) (xchg((ptr),1))
@@ -51,28 +65,78 @@
 #define __xg(x) ((volatile struct __xchg_dummy *)(x))
 
 #if defined(MACH_ATARI_ONLY) && !defined(CONFIG_HADES)
-/* block out HSYNC on the atari */
-#define __sti() __asm__ __volatile__ ("andiw #0xfbff,%/sr": : : "memory")
+#define r_sti() ({							\
+	if (local_irq_count[smp_processor_id()] <= 1)			\
+		/* block out HSYNC on the atari */			\
+		asm volatile ("andiw #0xfbff,%%sr": : : "memory");	\
+})
 #else /* portable version */
-#define __sti() __asm__ __volatile__ ("andiw #0xf8ff,%/sr": : : "memory")
-#endif /* machine compilation types */ 
-#define __cli() __asm__ __volatile__ ("oriw  #0x0700,%/sr": : : "memory")
+#define r_sti() ({							\
+	if (local_irq_count[smp_processor_id()] <= 1)			\
+		asm volatile ("andiw #0xf8ff,%%sr": : : "memory");	\
+})
+#endif /* machine compilation types */
+#define r_cli() asm volatile ("oriw  #0x0700,%%sr": : : "memory")
+
+#define r_save_flags(x)							\
+	asm volatile ("movew %%sr,%0":"=d" (x) : :"memory")
+#define r_restore_flags(x)						\
+	asm volatile ("movew %0,%%sr": :"d" (x) : "memory")
+
+#ifdef CONFIG_RT_INTERRUPT
+extern volatile int slowirq_enable;
+extern volatile int slowirq_busycnt;
+extern void (*mach_do_slowirq)(void);
+
+#define __sti() ({						\
+	rt_flagsdefine;						\
+	slowirq_enable = 1;					\
+	if (!rt_dec_test(rtirq_lock, &slowirq_busycnt))		\
+		mach_do_slowirq();				\
+})
+#define __cli() ({						\
+	slowirq_enable = 0;					\
+})
+#define __save_flags(x) ({					\
+	(x) = slowirq_enable;					\
+})
+#define __restore_flags(x) ({					\
+	if (x)							\
+		__sti();					\
+	else							\
+		__cli();					\
+})
+
+rt_lockdeclare(rtirq_lock);
+
+#define set_slowirq_request(mask) ({				\
+	rt_flagsdefine;						\
+	rt_setmask(rtirq_lock, &slowirq_request, (mask));	\
+})
+
+#else /* CONFIG_RT_INTERRUPT */
+
+#define __sti()			r_sti()
+#define __cli()			r_cli()
+#define __save_flags(x)		r_save_flags(x)
+#define __restore_flags(x)	r_restore_flags(x)
+
+#define set_slowirq_request(mask)				\
+	asm volatile ("orl %2,%1" : "=m" (slowirq_request)	\
+	              : "0" (slowirq_request), "id" (mask))
+
+#endif /* CONFIG_RT_INTERRUPT */
+
 #define nop() __asm__ __volatile__ ("nop"::)
 #define mb()  __asm__ __volatile__ (""   : : :"memory")
 #define rmb()  __asm__ __volatile__ (""   : : :"memory")
 #define wmb()  __asm__ __volatile__ (""   : : :"memory")
 
-#define __save_flags(x) \
-__asm__ __volatile__("movew %/sr,%0":"=d" (x) : /* no input */ :"memory")
-
-#define __restore_flags(x) \
-__asm__ __volatile__("movew %0,%/sr": /* no outputs */ :"d" (x) : "memory")
-
-#define cli() __cli()
-#define sti() __sti()
-#define save_flags(x) __save_flags(x)
-#define restore_flags(x) __restore_flags(x)
-#define save_and_cli(flags)   do { save_flags(flags); cli(); } while(0)
+#define cli()			__cli()
+#define sti()			__sti()
+#define save_flags(x)		__save_flags(x)
+#define restore_flags(x)	__restore_flags(x)
+#define save_and_cli(flags)	({ save_flags(flags); cli(); })
 
 #ifndef CONFIG_RMW_INSNS
 static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
diff -Nur -X /opt/home/roman/src/m68k_nodiff linux-2.3.14/include/asm-ppc/rt.h linux-rtl/include/asm-ppc/rt.h
--- linux-2.3.14/include/asm-ppc/rt.h	Thu Jan  1 01:00:00 1970
+++ linux-rtl/include/asm-ppc/rt.h	Wed Aug  4 21:19:50 1999
@@ -0,0 +1,42 @@
+#ifndef _ASM_PPC_ATOMIC_H
+#define _ASM_PPC_ATOMIC_H
+
+#define __has_rt_instr
+
+#ifdef __SMP__
+#define __SYNC	"sync; "
+#endif 
+
+#define __rt_init( ptr, old )
+
+#define __rt_reserve( ptr, old ) ({				\
+	asm volatile ( "lwarx %0,0,%1"				\
+		: "=r" (old) : "m" (*(ptr)) );			\
+})
+
+#define __rt_update( ptr, old, new ) ({			\
+	unsigned int __res;					\
+	asm volatile ( __SYNC "stwcx. %2,0,%1; mfcr %0"		\
+		: "=r" (__res), "=m" (*(ptr))			\
+		: "r" (new) : "cc" );				\
+	__res & 0x20000000;					\
+})
+
+#define rt_exchange( ptr, old, new ) ({			\
+	asm volatile ( "1: lwarx %0,0,%1"			\
+		: "=r" (old) : "m" (*(ptr)) );			\
+	asm volatile ( __SYNC "stwcx. %1,0,%0; bne- 1b"		\
+		: "=m" (*(ptr)) : "r" ((new)) : "cc" );		\
+})
+
+#define rt_inserthead( ptr, old, new ) ({			\
+	typeof(*(ptr)) __val;					\
+								\
+	asm volatile ( "1: lwarx %0,0,%1"			\
+		: "=r" (__val) : "m" (*(ptr)) );		\
+	(old) = __val;						\
+	asm volatile ( __SYNC "stwcx. %1,0,%0; bne- 1b"		\
+		: "=m" (*(ptr)) : "r" ((new)) : "cc" );		\
+})
+
+#endif /* _ASM_PPC_ATOMIC_H */
diff -Nur -X /opt/home/roman/src/m68k_nodiff linux-2.3.14/include/linux/rt.h linux-rtl/include/linux/rt.h
--- linux-2.3.14/include/linux/rt.h	Thu Jan  1 01:00:00 1970
+++ linux-rtl/include/linux/rt.h	Sun Aug 29 01:32:35 1999
@@ -0,0 +1,426 @@
+/*
+ * linux/include/linux/atomic.h
+ *
+ * Copyright (C) 1998, Roman Zippel
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ *
+ * For a more detailed documentation about this, see ....
+ */
+
+#ifndef _LINUX_ATOMIC_H
+#define _LINUX_ATOMIC_H
+
+#ifdef __KERNEL__
+
+#include <asm/rt.h>
+
+#ifdef __has_rt_instr
+
+/* atomic instructions are available, so no need for synchronization with an
+ * atomic lock.
+ */
+
+#define rt_lockdeclare( dummylock )
+#define rt_lockdefine( dummylock )
+#define rt_flagsdefine
+#define rt_enter( dummylock )
+#define rt_leave( dummylock )
+
+#define __rt_exchange( ptr, old, new ) rt_exchange( dummylock, ptr, old, new )
+#define __rt_inserthead( ptr, old, new ) rt_inserthead( dummylock, ptr, old, new )
+
+#define __rt_inc( ptr ) rt_inc( dummylock, ptr )
+#define __rt_dec( ptr ) rt_dec( dummylock, ptr )
+#define __rt_dec_test( ptr ) rt_dec_test( dummylock, ptr )
+#define __rt_add( ptr, val ) rt_add( dummylock, ptr, val )
+#define __rt_sub( ptr, val ) rt_sub( dummylock, ptr, val )
+
+#define __rt_setmask( ptr, val ) rt_setmask( dummylock, ptr, val )
+#define __rt_clrmask( ptr, val ) rt_clrmask( dummylock, ptr, val )
+#define __rt_chgmask( ptr, val ) rt_chgmask( dummylock, ptr, val )
+#define __rt_test_setmask( ptr, val ) rt_test_setmask( dummylock, ptr, val )
+#define __rt_test_clrmask( ptr, val ) rt_test_clrmask( dummylock, ptr, val )
+#define __rt_test_chgmask( ptr, val ) rt_test_chgmask( dummylock, ptr, val )
+
+#define __rt_setbit( ptr, val ) rt_setbit( dummylock, ptr, val )
+#define __rt_clrbit( ptr, val ) rt_clrbit( dummylock, ptr, val )
+#define __rt_chgbit( ptr, val ) rt_chgbit( dummylock, ptr, val )
+#define __rt_test_setbit( ptr, val ) rt_test_setbit( dummylock, ptr, val )
+#define __rt_test_clrbit( ptr, val ) rt_test_clrbit( dummylock, ptr, val )
+#define __rt_test_chgbit( ptr, val ) rt_test_chgbit( dummylock, ptr, val )
+
+#else
+
+/* synchronization with an atomic lock is needed, that is done by atomic_enter()
+ * and atomic_leave(), between them we can let the compiler do the work
+ */
+
+#define __rt_init( ptr, old )		({ (old) = *(ptr); })
+#define __rt_reserve( ptr, old )
+#define __rt_update( ptr, old, new )	({ *(ptr) = (new); 1; })
+
+#define __rt_exchange( ptr, old, new )		\
+	({ (old) = *(ptr); *(ptr) = (new); (void)0; })
+#define __rt_inserthead( ptr, old, new )		\
+	({ (old) = *(ptr); *(ptr) = (new); (void)0; })
+#define __rt_inc( ptr )		( (void)(*(ptr)++) )
+#define __rt_dec( ptr )		( (void)(*(ptr)--) )
+#define __rt_dec_test( ptr )	( --*(ptr) )
+#define __rt_add( ptr, val )	( (void)(*(ptr) += (val)) )
+#define __rt_sub( ptr, val )	( (void)(*(ptr) -= (val)) )
+#define __rt_setmask( ptr, mask )	( (void)(*(ptr) |= (mask)) )
+#define __rt_clrmask( ptr, mask )	( (void)(*(ptr) &= ~(mask)) )
+#define __rt_chgmask( ptr, mask )	( (void)(*(ptr) ^= (mask)) )
+
+/* for the following macros the C version is ugly, see if there is a more
+ * efficient version available.
+ */
+
+#ifdef __has_bit_instr
+
+#define __rt_test_setmask( ptr, mask ) rt_test_setmask( dummylock, ptr, mask )
+#define __rt_test_clrmask( ptr, mask ) rt_test_clrmask( dummylock, ptr, mask )
+#define __rt_test_chgmask( ptr, mask ) rt_test_chgmask( dummylock, ptr, mask )
+
+#else
+
+#define __rt_test_setmask( ptr, mask ) ({			\
+	typeof(*(ptr)) __oldval = *(ptr);			\
+								\
+	*(ptr) |= (mask);					\
+	__oldval & (mask);					\
+})
+
+#define __rt_test_clrmask( ptr, val ) ({			\
+	typeof(*(ptr)) __oldval = *(ptr);			\
+								\
+	*(ptr) &= ~(val);					\
+	__oldval & (mask);					\
+})
+
+#define __rt_test_chgmask( ptr, val ) ({			\
+	typeof(*(ptr)) __oldval = *(ptr);			\
+								\
+	*(ptr) ^= (mask);					\
+	__oldval & (mask);					\
+})
+
+#endif
+
+#endif
+
+/* atomically exchange a memory value and return the old value, if <new> is
+ * constant, a more efficient macro might be available.
+ */
+
+#ifndef rt_do_exchange
+#define rt_do_exchange( lock, ptr, old, new ) ({		\
+	rt_define;						\
+								\
+	rt_enter( lock );					\
+	__rt_init( ptr, old );				\
+	do {							\
+		__rt_reserve( ptr, old );			\
+	} while ( !__rt_update(ptr, old, (new)) );		\
+	rt_leave( lock );					\
+})
+#endif
+
+#ifndef rt_do_exchange_const
+#define rt_do_exchange_const( lock, ptr, old, new ) rt_do_exchange( lock, ptr, old, new )
+#endif
+
+#ifndef rt_exchange
+#define rt_exchange( lock, ptr, old, new ) ({		\
+	if ( __builtin_constant_p(new) )			\
+		rt_do_exchange_const( lock, ptr, old, new );\
+	else							\
+		rt_do_exchange( lock, ptr, old, new );	\
+})
+#endif
+
+#ifndef rt_inserthead
+#define rt_inserthead( lock, ptr, old, new ) ({		\
+	typeof(*(ptr)) __val;					\
+	rt_define;						\
+								\
+	rt_enter( lock );					\
+	__rt_init( ptr, __val );				\
+	do {							\
+		__rt_reserve( ptr, __val );			\
+		old = __val;					\
+	} while ( !__rt_update(ptr, __val, (new)) );	\
+	rt_leave( lock );					\
+})
+#endif
+
+/* atomically increment the value */
+#ifndef rt_inc
+#define rt_inc( lock, ptr ) ({				\
+	typeof(*(ptr)) __val;					\
+								\
+	rt_exchange( lock, ptr, __val, __val + 1 );		\
+})
+#endif
+
+/* atomically decrement the value */
+#ifndef rt_dec
+#define rt_dec( lock, ptr ) ({				\
+	typeof(*(ptr)) __val;					\
+								\
+	rt_exchange( lock, ptr, __val, __val - 1 );		\
+})
+#endif
+
+/* atomically decrement the value and test the result */
+#ifndef rt_dec_test
+#define rt_dec_test( lock, ptr ) ({				\
+	typeof(*(ptr)) __val;					\
+								\
+	rt_exchange( lock, ptr, __val, __val - 1 );		\
+	__val != 0;						\
+})
+#endif
+
+/* atomically add a value */
+#ifndef rt_add
+#define rt_add( lock, ptr, val ) ({				\
+	typeof(*(ptr)) __val;					\
+								\
+	rt_exchange( lock, ptr, __val, __val + (val) );	\
+})
+#endif
+
+/* atomically subtract a value */
+#ifndef rt_sub
+#define rt_sub( lock, ptr, val ) ({				\
+	typeof(*(ptr)) __val;					\
+								\
+	rt_exchange( lock, ptr, __val, __val - (val) );	\
+})
+#endif
+
+#define __getbitnr( mask ) ({					\
+	int bit = -1;						\
+								\
+	if ( __builtin_constant_p(mask) ) {			\
+		switch ( mask ) {				\
+		case 1 <<  0: bit =  0; break;			\
+		case 1 <<  1: bit =  1; break;			\
+		case 1 <<  2: bit =  2; break;			\
+		case 1 <<  3: bit =  3; break;			\
+		case 1 <<  4: bit =  4; break;			\
+		case 1 <<  5: bit =  5; break;			\
+		case 1 <<  6: bit =  6; break;			\
+		case 1 <<  7: bit =  7; break;			\
+		case 1 <<  8: bit =  8; break;			\
+		case 1 <<  9: bit =  9; break;			\
+		case 1 << 10: bit = 10; break;			\
+		case 1 << 11: bit = 11; break;			\
+		case 1 << 12: bit = 12; break;			\
+		case 1 << 13: bit = 13; break;			\
+		case 1 << 14: bit = 14; break;			\
+		case 1 << 15: bit = 15; break;			\
+		case 1 << 16: bit = 16; break;			\
+		case 1 << 17: bit = 17; break;			\
+		case 1 << 18: bit = 18; break;			\
+		case 1 << 19: bit = 19; break;			\
+		case 1 << 20: bit = 20; break;			\
+		case 1 << 21: bit = 21; break;			\
+		case 1 << 22: bit = 22; break;			\
+		case 1 << 23: bit = 23; break;			\
+		case 1 << 24: bit = 24; break;			\
+		case 1 << 25: bit = 25; break;			\
+		case 1 << 26: bit = 26; break;			\
+		case 1 << 27: bit = 27; break;			\
+		case 1 << 28: bit = 28; break;			\
+		case 1 << 29: bit = 29; break;			\
+		case 1 << 30: bit = 30; break;			\
+		case 1 << 31: bit = 31; break;			\
+		}						\
+	}							\
+	bit;							\
+})
+
+#define __getmask( bit ) ( 1 << bit )
+
+/* atomically set a mask/bit, if the mask has only a single bit set,
+ * try a bit operation if available
+ */
+
+#ifndef rt_do_setmask
+#define rt_do_setmask( lock, ptr, mask ) ({			\
+	typeof(*(ptr)) __val;					\
+								\
+	rt_exchange( lock, ptr, __val, __val | (mask) );	\
+})
+#endif
+
+#ifndef rt_do_setbit
+#define rt_do_setbit( lock, ptr, bit ) rt_do_setmask( lock, ptr, __getmask(bit) );
+#endif
+
+#ifndef rt_setmask
+#define rt_setmask( lock, ptr, mask ) ({			\
+	int bit = __getbitnr( mask );				\
+								\
+	if ( bit < 0 )						\
+		rt_do_setmask( lock, ptr, mask );		\
+	else							\
+		rt_do_setbit( lock, ptr, bit );		\
+})
+#endif
+
+#define rt_setbit( lock, ptr, bit ) rt_do_setbit( lock, ptr, bit )
+
+/* atomically clear a mask/bit, if the mask has only a single bit set,
+ * try a bit operation if available
+ */
+
+#ifndef rt_do_clrmask
+#define rt_do_clrmask( lock, ptr, mask ) ({			\
+	typeof(*(ptr)) __val;					\
+								\
+	rt_exchange( lock, ptr, __val, __val & ~(mask) );	\
+})
+#endif
+
+#ifndef rt_do_clrbit
+#define rt_do_clrbit( lock, ptr, bit ) rt_do_clrmask( lock, ptr, __getmask(bit) );
+#endif
+
+#ifndef rt_clrmask
+#define rt_clrmask( lock, ptr, mask ) ({			\
+	int bit = __getbitnr( mask );				\
+								\
+	if ( bit < 0 )						\
+		rt_do_clrmask( lock, ptr, mask );		\
+	else							\
+		rt_do_clrbit( lock, ptr, bit );		\
+})
+#endif
+
+#define rt_clrbit( lock, ptr, bit ) rt_do_clrbit( lock, ptr, bit )
+
+/* atomically change a mask/bit, if the mask has only a single bit set,
+ * try a bit operation if available
+ */
+
+#ifndef rt_do_chgmask
+#define rt_do_chgmask( lock, ptr, mask ) ({			\
+	typeof(*(ptr)) __val;					\
+								\
+	rt_exchange( lock, ptr, __val, __val ^ (mask) );	\
+})
+#endif
+
+#ifndef rt_do_chgbit
+#define rt_do_chgbit( lock, ptr, bit ) rt_do_chgmask( lock, ptr, __getmask(bit) );
+#endif
+
+#ifndef rt_chgmask
+#define rt_chgmask( lock, ptr, mask ) ({			\
+	int bit = __getbitnr( mask );				\
+								\
+	if ( bit < 0 )						\
+		rt_do_chgmask( lock, ptr, mask );		\
+	else							\
+		rt_do_chgbit( lock, ptr, bit );		\
+})
+#endif
+
+#define rt_chgbit( lock, ptr, bit ) rt_do_chgbit( lock, ptr, bit )
+
+/* atomically set a mask/bit and test it against the old value */
+
+#ifndef rt_do_test_setmask
+#define rt_do_test_setmask( lock, ptr, mask ) ({		\
+	typeof(*(ptr)) __oldval;				\
+								\
+	rt_exchange( lock, ptr, __oldval, __oldval | (mask) );\
+	__oldval & (mask);					\
+})
+#endif
+
+#ifndef rt_do_test_setbit
+#define rt_do_test_setbit( lock, ptr, bit ) rt_do_test_setmask( lock, ptr, __getmask(bit) );
+#endif
+
+#ifndef rt_test_setmask
+#define rt_test_setmask( lock, ptr, mask ) ({		\
+	int res, bit = __getbitnr( mask );			\
+								\
+	if ( bit < 0 )						\
+		res = rt_do_test_setmask( lock, ptr, mask );\
+	else							\
+		res = rt_do_test_setbit( lock, ptr, bit );	\
+	res;							\
+})
+#endif
+
+#define rt_test_setbit( lock, ptr, bit ) rt_do_test_setbit( lock, ptr, bit )
+
+/* atomically clear a mask/bit and test it against the old value */
+
+#ifndef rt_do_test_clrmask
+#define rt_do_test_clrmask( lock, ptr, mask ) ({		\
+	typeof(*(ptr)) __val;					\
+								\
+	rt_exchange( lock, ptr, __val, __val & ~(mask) );	\
+	__val & (mask);						\
+})
+#endif
+
+#ifndef rt_do_test_clrbit
+#define rt_do_test_clrbit( lock, ptr, bit ) rt_do_test_clrmask( lock, ptr, __getmask(bit) );
+#endif
+
+#ifndef rt_test_clrmask
+#define rt_test_clrmask( lock, ptr, mask ) ({		\
+	int res, bit = __getbitnr( mask );			\
+								\
+	if ( bit < 0 )						\
+		res = rt_do_test_clrmask( lock, ptr, mask );\
+	else							\
+		res = rt_do_test_clrbit( lock, ptr, bit );	\
+	res;							\
+})
+#endif
+
+#define rt_test_clrbit( lock, ptr, bit ) rt_do_test_clrbit( lock, ptr, bit )
+
+/* atomically change a mask/bit and test it against the old value */
+
+#ifndef rt_do_test_chgmask
+#define rt_do_test_chgmask( lock, ptr, mask ) ({		\
+	typeof(*(ptr)) __val;					\
+								\
+	rt_exchange( lock, ptr, __val, __val ^ (mask) );	\
+	__val & (mask);						\
+})
+#endif
+
+#ifndef rt_do_test_chgbit
+#define rt_do_test_chgbit( lock, ptr, bit ) rt_do_test_chgmask( lock, ptr, __getmask(bit) );
+#endif
+
+#ifndef rt_test_chgmask
+#define rt_test_chgmask( lock, ptr, mask ) ({		\
+	int res, bit = __getbitnr( mask );			\
+								\
+	if ( bit < 0 )						\
+		res = rt_do_test_chgmask( lock, ptr, mask );\
+	else							\
+		res = rt_do_test_chgbit( lock, ptr, bit );	\
+	res;							\
+})
+#endif
+
+#define rt_test_chgbit( lock, ptr, bit ) rt_do_test_chgbit( lock, ptr, bit )
+
+#endif /* __KERNEL__ */
+
+#endif /* _LINUX_ATOMIC_H */
diff -Nur -X /opt/home/roman/src/m68k_nodiff linux-2.3.14/include/linux/tqueue.h linux-rtl/include/linux/tqueue.h
--- linux-2.3.14/include/linux/tqueue.h	Tue May 18 16:01:05 1999
+++ linux-rtl/include/linux/tqueue.h	Sun Aug 29 12:36:19 1999
@@ -13,9 +13,8 @@
 #ifndef _LINUX_TQUEUE_H
 #define _LINUX_TQUEUE_H
 
-#include <asm/bitops.h>
+#include <linux/rt.h>
 #include <asm/system.h>
-#include <asm/spinlock.h>
 
 /*
  * New proposed "bottom half" handlers:
@@ -75,7 +74,7 @@
  * interrupt.
  */
 
-extern spinlock_t tqueue_lock;
+rt_lockdeclare(tqueue_lock);
 
 /*
  * queue_task
@@ -83,13 +82,12 @@
 extern __inline__ void queue_task(struct tq_struct *bh_pointer,
 			   task_queue *bh_list)
 {
-	if (!test_and_set_bit(0,&bh_pointer->sync)) {
-		unsigned long flags;
-		spin_lock_irqsave(&tqueue_lock, flags);
-		bh_pointer->next = *bh_list;
-		*bh_list = bh_pointer;
-		spin_unlock_irqrestore(&tqueue_lock, flags);
-	}
+	rt_flagsdefine;
+
+	rt_enter(tqueue_lock);
+	if (!__rt_test_setbit(&bh_pointer->sync, 0))
+		__rt_inserthead(bh_list, bh_pointer->next, bh_pointer);
+	rt_leave(tqueue_lock);
 }
 
 /*
@@ -98,14 +96,11 @@
 extern __inline__ void run_task_queue(task_queue *list)
 {
 	if (*list) {
-		unsigned long flags;
 		struct tq_struct *p;
+		rt_flagsdefine;
+
+		rt_exchange(tqueue_lock, list, p, NULL);
 
-		spin_lock_irqsave(&tqueue_lock, flags);
-		p = *list;
-		*list = NULL;
-		spin_unlock_irqrestore(&tqueue_lock, flags);
-		
 		while (p) {
 			void *arg;
 			void (*f) (void *);
diff -Nur -X /opt/home/roman/src/m68k_nodiff linux-2.3.14/init/main.c linux-rtl/init/main.c
--- linux-2.3.14/init/main.c	Fri Aug 20 21:14:08 1999
+++ linux-rtl/init/main.c	Wed Aug 25 21:48:04 1999
@@ -499,6 +499,9 @@
 	}
 
 	memory_start = kmem_cache_init(memory_start, memory_end);
+#ifdef CONFIG_RT_INTERRUPT
+	r_sti();
+#endif
 	sti();
 	calibrate_delay();
 #ifdef CONFIG_BLK_DEV_INITRD
diff -Nur -X /opt/home/roman/src/m68k_nodiff linux-2.3.14/kernel/printk.c linux-rtl/kernel/printk.c
--- linux-2.3.14/kernel/printk.c	Fri Aug 20 20:58:10 1999
+++ linux-rtl/kernel/printk.c	Thu Aug 26 22:59:07 1999
@@ -344,8 +344,9 @@
 	char	buf[16];
 	signed char msg_level = -1;
 	char	*q;
+	long    flags;
 
-	spin_lock_irq(&console_lock);
+	spin_lock_irqsave(&console_lock, flags);
 	/*
 	 *	See if we want to use this console driver. If we
 	 *	didn't select a console we take the first one
@@ -422,7 +423,7 @@
 		j = 0;
 	}
  out:
-	spin_unlock_irq(&console_lock);
+	spin_unlock_irqrestore(&console_lock, flags);
 }
 
 

