Subject: luna68k and x68k MI softintr(9)
To: None <port-luna68k@NetBSD.org, port-x68k@NetBSD.org>
From: Izumi Tsutsui <tsutsui@ceres.dti.ne.jp>
List: port-hp300
Date: 03/03/2007 21:12:45
I'm not sure how many luna68k and x68k users there are
outside of Japan, but I'd also post a patch that
adds MI softintr(9) support (which is now mandatory
after newlock2 merge) based on hp300 implementation
(using VAX REI emulation and trap).

Changes are simple, just copy hp300/softintr.c into
m68k/softintr.c, modify it, and put several tweaks in each
MD files.

This patch also contains which create a.out kernel for
the luna68k PROM monitor, but I'm not sure if it's really work. 

Pre-compiled kernels are also available:
http://www.ceres.dti.ne.jp/~tsutsui/netbsd/netbsd-luna68k-GENERIC-20070303.gz
http://www.ceres.dti.ne.jp/~tsutsui/netbsd/netbsd-luna68k-GENERIC.aout-20070303.gz
http://www.ceres.dti.ne.jp/~tsutsui/netbsd/netbsd-x68k-GENERIC-20070303.gz

---
Izumi Tsutsui


Index: arch/cats/conf/Makefile.cats.inc
===================================================================
RCS file: /cvsroot/src/sys/arch/cats/conf/Makefile.cats.inc,v
retrieving revision 1.17
diff -u -r1.17 Makefile.cats.inc
--- arch/cats/conf/Makefile.cats.inc	24 Nov 2005 12:54:29 -0000	1.17
+++ arch/cats/conf/Makefile.cats.inc	3 Mar 2007 11:54:00 -0000
@@ -17,7 +17,7 @@
 
 SYSTEM_LD_HEAD_EXTRA+=; \
 	( cat ${ARM}/conf/kern.ldscript.head ; \
-	  OBJDUMP=${OBJDUMP} ${HOST_SH} ${ARM}/conf/mkldscript.sh \
+	  OBJDUMP=${OBJDUMP} ${HOST_SH} $S/conf/mkldscript.sh \
 		${SYSTEM_OBJ} ; \
 	  cat ${ARM}/conf/kern.ldscript.tail ) > ldscript
 
Index: arch/hp300/conf/files.hp300
===================================================================
RCS file: /cvsroot/src/sys/arch/hp300/conf/files.hp300,v
retrieving revision 1.75
diff -u -r1.75 files.hp300
--- arch/hp300/conf/files.hp300	20 Jul 2006 13:21:38 -0000	1.75
+++ arch/hp300/conf/files.hp300	3 Mar 2007 11:54:01 -0000
@@ -188,7 +188,6 @@
 file	arch/hp300/hp300/leds.c			useleds
 file	arch/hp300/hp300/mem.c
 file	arch/hp300/hp300/pmap_bootstrap.c	compile-with "${NOPROF_C}"
-file	arch/hp300/hp300/softintr.c
 file	arch/hp300/hp300/trap.c
 file	arch/hp300/hp300/disksubr.c
 file	arch/m68k/m68k/cacheops.c
@@ -196,6 +195,7 @@
 file	arch/m68k/m68k/kgdb_machdep.c		kgdb
 file	arch/m68k/m68k/pmap_motorola.c
 file	arch/m68k/m68k/procfs_machdep.c		procfs
+file	arch/m68k/m68k/softintr.c
 file	arch/m68k/m68k/sys_machdep.c
 file	arch/m68k/m68k/vm_machdep.c
 
Index: arch/hp300/include/intr.h
===================================================================
RCS file: /cvsroot/src/sys/arch/hp300/include/intr.h,v
retrieving revision 1.19
diff -u -r1.19 intr.h
--- arch/hp300/include/intr.h	16 Feb 2007 02:53:46 -0000	1.19
+++ arch/hp300/include/intr.h	3 Mar 2007 11:54:01 -0000
@@ -69,20 +69,6 @@
 #define	IPL_LOCK	IPL_HIGH
 #define	NIPL		12
 
-#define	SI_SOFTSERIAL	0	/* serial software interrupts */
-#define	SI_SOFTNET	1	/* network software interrupts */
-#define	SI_SOFTCLOCK	2	/* clock software interrupts */
-#define	SI_SOFT		3	/* other software interrupts */
-
-#define	SI_NQUEUES	4
-
-#define	SI_QUEUENAMES {							\
-	"serial",							\
-	"net",								\
-	"clock",							\
-	"misc",								\
-}
-
 /*
  * Convert PSL values to m68k CPU IPLs and vice-versa.
  * Note: CPU IPL values are different from IPL_* used by splraiseipl().
@@ -150,43 +136,6 @@
 	struct evcnt hi_evcnt;
 };
 
-/*
- * Software Interrupts.
- */
-
-struct hp300_soft_intrhand {
-	LIST_ENTRY(hp300_soft_intrhand) sih_q;
-	struct hp300_soft_intr *sih_intrhead;
-	void (*sih_fn)(void *);
-	void *sih_arg;
-	volatile int sih_pending;
-};
-
-struct hp300_soft_intr {
-	LIST_HEAD(, hp300_soft_intrhand) hsi_q;
-	struct evcnt hsi_evcnt;
-	uint8_t hsi_ipl;
-};
-
-void	*softintr_establish(int, void (*)(void *), void *);
-void	softintr_disestablish(void *);
-void	softintr_init(void);
-void	softintr_dispatch(void);
-
-extern volatile uint8_t ssir;
-#define setsoft(x)	ssir |= (1<<(x))
-
-#define softintr_schedule(arg)				\
-do {							\
-	struct hp300_soft_intrhand *__sih = (arg);	\
-	__sih->sih_pending = 1;				\
-	setsoft(__sih->sih_intrhead->hsi_ipl);		\
-} while (0)
-
-/* XXX For legacy software interrupts */
-extern struct hp300_soft_intrhand *softnet_intrhand;
-#define setsoftnet()	softintr_schedule(softnet_intrhand)
-
 /* locore.s */
 int	spl0(void);
 
@@ -196,8 +145,9 @@
 void	intr_disestablish(void *);
 void	intr_dispatch(int);
 void	intr_printlevels(void);
-void	netintr(void);
 
 #endif /* _KERNEL */
 
+#include <m68k/softintr.h>
+
 #endif /* _HP300_INTR_H_ */
Index: arch/luna68k/conf/Makefile.luna68k
===================================================================
RCS file: /cvsroot/src/sys/arch/luna68k/conf/Makefile.luna68k,v
retrieving revision 1.18
diff -u -r1.18 Makefile.luna68k
--- arch/luna68k/conf/Makefile.luna68k	11 Dec 2005 12:17:51 -0000	1.18
+++ arch/luna68k/conf/Makefile.luna68k	3 Mar 2007 11:54:04 -0000
@@ -54,8 +54,25 @@
 ##
 ## (5) link settings
 ##
-LINKFORMAT=	-N
-TEXTADDR?=	0xc000
+LINKFORMAT=	-T ldscript
+.if (${OBJECT_FMT} == "ELF")
+# Need to convert the kernel from ELF to a.out so that OpenFirmware
+# can load it.
+
+LINKFLAGS=      -T ldscript
+
+SYSTEM_LD_HEAD_EXTRA+=; \
+	( cat ${LUNA68K}/conf/kern.ldscript.head ; \
+	  OBJDUMP=${OBJDUMP} ${HOST_SH} $S/conf/mkldscript.sh \
+	        ${SYSTEM_OBJ} ; \
+	  cat ${LUNA68K}/conf/kern.ldscript.tail ) > ldscript
+
+SYSTEM_LD_TAIL_EXTRA+=; \
+	echo \
+	 "${OBJCOPY} -O a.out-m68k-netbsd -R .ident -R .comment -R .note.netbsd.ident $@ $@.aout"; \
+	${OBJCOPY} -O a.out-m68k-netbsd \
+	    -R .ident -R .comment -R .note.netbsd.ident $@ $@.aout
+.endif
 
 ##
 ## (6) port specific target dependencies
Index: arch/luna68k/conf/files.luna68k
===================================================================
RCS file: /cvsroot/src/sys/arch/luna68k/conf/files.luna68k,v
retrieving revision 1.17
diff -u -r1.17 files.luna68k
--- arch/luna68k/conf/files.luna68k	11 Dec 2005 12:17:52 -0000	1.17
+++ arch/luna68k/conf/files.luna68k	3 Mar 2007 11:54:04 -0000
@@ -19,6 +19,7 @@
 file arch/m68k/m68k/db_memrw.c		ddb | kgdb
 file arch/m68k/m68k/pmap_motorola.c
 file arch/m68k/m68k/procfs_machdep.c	procfs
+file arch/m68k/m68k/softintr.c
 file arch/m68k/m68k/sys_machdep.c
 file arch/m68k/m68k/vm_machdep.c
 file dev/cons.c
Index: arch/luna68k/include/cpu.h
===================================================================
RCS file: /cvsroot/src/sys/arch/luna68k/include/cpu.h,v
retrieving revision 1.14
diff -u -r1.14 cpu.h
--- arch/luna68k/include/cpu.h	16 Feb 2007 02:53:48 -0000	1.14
+++ arch/luna68k/include/cpu.h	3 Mar 2007 11:54:04 -0000
@@ -158,22 +158,6 @@
 extern int	astpending;	/* need to trap before returning to user mode */
 extern int	want_resched;	/* resched() was called */
 
-/*
- * simulated software interrupt register
- */
-extern unsigned char ssir;
-
-#define SIR_NET		0x1
-#define SIR_CLOCK	0x2
-
-#define siron(x)	\
-	__asm volatile ("orb %0,%1" : : "di" ((u_char)(x)), "g" (ssir))
-#define siroff(x)	\
-	__asm volatile ("andb %0,%1" : : "di" ((u_char)~(x)), "g" (ssir))
-
-#define setsoftnet()	siron(SIR_NET)
-#define setsoftclock()	siron(SIR_CLOCK)
-
 #endif /* _KERNEL */
 
 /*
Index: arch/luna68k/include/intr.h
===================================================================
RCS file: /cvsroot/src/sys/arch/luna68k/include/intr.h,v
retrieving revision 1.6
diff -u -r1.6 intr.h
--- arch/luna68k/include/intr.h	16 Feb 2007 02:53:48 -0000	1.6
+++ arch/luna68k/include/intr.h	3 Mar 2007 11:54:04 -0000
@@ -47,16 +47,18 @@
 #include <machine/psl.h>
 
 #define splnone()	spl0()
-#define splsoftclock()  splraise1()
-#define splsoftnet()    splraise1()
-#define splbio()        spl2()
-#define splnet()        spl3()
-#define spltty()        spl6()
-#define splclock()      spl5()
-#define splstatclock()	spl5()
-#define splvm()         spl7()
-#define splhigh()       spl7()
-#define splsched()      spl7()
+#define splsoft()	splraise1()
+#define splsoftclock()	splsoft()
+#define splsoftnet()	splsoft()
+#define splsoftserial()	splsoft()
+#define splbio()	splraise2()
+#define splnet()	splraise3()
+#define spltty()	splraise6()
+#define splclock()	splraise5()
+#define splstatclock()	splraise5()
+#define splvm()		spl7()
+#define splhigh()	spl7()
+#define splsched()	spl7()
 #define spllock()	spl7()
 
 /* watch out for side effects */
@@ -67,18 +69,20 @@
 #define	IPL_NONE	0
 #define	IPL_SOFTCLOCK	1
 #define	IPL_SOFTNET	2
-#define	IPL_BIO		3
-#define	IPL_NET		4
-#define	IPL_CLOCK	5
-#define	IPL_STATCLOCK	6
-#define	IPL_TTY		7
-#define	IPL_VM		8
-#define	IPL_SCHED	9
-#define	IPL_HIGH	10
-#define	IPL_LOCK	11
-#define	NIPLS		12
+#define	IPL_SOFTSERIAL	3
+#define	IPL_SOFT	4
+#define	IPL_BIO		5
+#define	IPL_NET		6
+#define	IPL_CLOCK	7
+#define	IPL_STATCLOCK	8
+#define	IPL_TTY		9
+#define	IPL_VM		10
+#define	IPL_SCHED	11
+#define	IPL_HIGH	12
+#define	IPL_LOCK	13
+#define	NIPL		14
 
-extern const int ipl2spl_table[NIPLS];
+extern const int ipl2spl_table[NIPL];
 
 typedef int ipl_t;
 typedef struct {
@@ -100,4 +104,6 @@
 }
 #endif /* _KERNEL */
 
+#include <m68k/softintr.h>
+
 #endif	/* _MACHINE_INTR_H */
Index: arch/luna68k/include/types.h
===================================================================
RCS file: /cvsroot/src/sys/arch/luna68k/include/types.h,v
retrieving revision 1.3
diff -u -r1.3 types.h
--- arch/luna68k/include/types.h	14 Sep 2006 15:04:07 -0000	1.3
+++ arch/luna68k/include/types.h	3 Mar 2007 11:54:04 -0000
@@ -6,6 +6,7 @@
 #include <m68k/types.h>
 
 #define	__HAVE_TIMECOUNTER
+#define	__HAVE_GENERIC_SOFT_INTERRUPTS
 #define	__HAVE_GENERIC_TODR
 
 #endif
Index: arch/luna68k/luna68k/autoconf.c
===================================================================
RCS file: /cvsroot/src/sys/arch/luna68k/luna68k/autoconf.c,v
retrieving revision 1.6
diff -u -r1.6 autoconf.c
--- arch/luna68k/luna68k/autoconf.c	11 Dec 2005 12:17:52 -0000	1.6
+++ arch/luna68k/luna68k/autoconf.c	3 Mar 2007 11:54:04 -0000
@@ -64,6 +64,7 @@
 
 	(void)splhigh();
 	isrinit();
+	softintr_init();
 	if (config_rootfound("mainbus", NULL) == NULL)
 		panic("autoconfig failed, no root");
 
Index: arch/luna68k/luna68k/isr.c
===================================================================
RCS file: /cvsroot/src/sys/arch/luna68k/luna68k/isr.c,v
retrieving revision 1.9
diff -u -r1.9 isr.c
--- arch/luna68k/luna68k/isr.c	21 Dec 2006 15:55:23 -0000	1.9
+++ arch/luna68k/luna68k/isr.c	3 Mar 2007 11:54:04 -0000
@@ -296,17 +296,19 @@
 
 }
 
-const int ipl2spl_table[NIPLS] = {
-	[IPL_NONE] = PSL_S|PSL_IPL0,
-	[IPL_SOFTCLOCK] = PSL_S|PSL_IPL1,
-	[IPL_SOFTNET] = PSL_S|PSL_IPL1,
-	[IPL_BIO] = PSL_S|PSL_IPL2,
-	[IPL_NET] = PSL_S|PSL_IPL3,
-	[IPL_CLOCK] = PSL_S|PSL_IPL5,
-	[IPL_STATCLOCK] = PSL_S|PSL_IPL5,
-	[IPL_TTY] = PSL_S|PSL_IPL6,
-	[IPL_VM] = PSL_S|PSL_IPL7,
-	[IPL_SCHED] = PSL_S|PSL_IPL7,
-	[IPL_HIGH] = PSL_S|PSL_IPL7,
-	[IPL_LOCK] = PSL_S|PSL_IPL7,
+const int ipl2spl_table[NIPL] = {
+	[IPL_NONE]       = PSL_S|PSL_IPL0,
+	[IPL_SOFTCLOCK]  = PSL_S|PSL_IPL1,
+	[IPL_SOFTNET]    = PSL_S|PSL_IPL1,
+	[IPL_SOFTSERIAL] = PSL_S|PSL_IPL1,
+	[IPL_SOFT]       = PSL_S|PSL_IPL1,
+	[IPL_BIO]        = PSL_S|PSL_IPL2,
+	[IPL_NET]        = PSL_S|PSL_IPL3,
+	[IPL_CLOCK]      = PSL_S|PSL_IPL5,
+	[IPL_STATCLOCK]  = PSL_S|PSL_IPL5,
+	[IPL_TTY]        = PSL_S|PSL_IPL6,
+	[IPL_VM]         = PSL_S|PSL_IPL7,
+	[IPL_SCHED]      = PSL_S|PSL_IPL7,
+	[IPL_HIGH]       = PSL_S|PSL_IPL7,
+	[IPL_LOCK]       = PSL_S|PSL_IPL7,
 };
Index: arch/luna68k/luna68k/locore.s
===================================================================
RCS file: /cvsroot/src/sys/arch/luna68k/luna68k/locore.s,v
retrieving revision 1.23
diff -u -r1.23 locore.s
--- arch/luna68k/luna68k/locore.s	11 Dec 2005 12:17:52 -0000	1.23
+++ arch/luna68k/luna68k/locore.s	3 Mar 2007 11:54:04 -0000
@@ -866,7 +866,6 @@
  * This code is complicated by the fact that sendsig may have been called
  * necessitating a stack cleanup.
  */
-BSS(ssir,1)
 
 ASENTRY_NOPROFILE(rei)
 	tstl	_C_LABEL(astpending)	| AST pending?
Index: arch/luna68k/luna68k/trap.c
===================================================================
RCS file: /cvsroot/src/sys/arch/luna68k/luna68k/trap.c,v
retrieving revision 1.40
diff -u -r1.40 trap.c
--- arch/luna68k/luna68k/trap.c	9 Feb 2007 21:55:05 -0000	1.40
+++ arch/luna68k/luna68k/trap.c	3 Mar 2007 11:54:04 -0000
@@ -514,17 +514,9 @@
 
 	case T_SSIR:		/* software interrupt */
 	case T_SSIR|T_USER:
-		if (ssir & SIR_NET) {
-			void netintr __P((void));
-			siroff(SIR_NET);
-			uvmexp.softs++;
-			netintr();
-		}
-		if (ssir & SIR_CLOCK) {
-			siroff(SIR_CLOCK);
-			uvmexp.softs++;
-			softclock(NULL);
-		}
+
+		softintr_dispatch();
+
 		/*
 		 * If this was not an AST trap, we are all done.
 		 */
Index: arch/shark/conf/Makefile.shark.inc
===================================================================
RCS file: /cvsroot/src/sys/arch/shark/conf/Makefile.shark.inc,v
retrieving revision 1.6
diff -u -r1.6 Makefile.shark.inc
--- arch/shark/conf/Makefile.shark.inc	24 Nov 2005 12:54:30 -0000	1.6
+++ arch/shark/conf/Makefile.shark.inc	3 Mar 2007 11:54:06 -0000
@@ -12,7 +12,7 @@
 
 SYSTEM_LD_HEAD_EXTRA+=; \
 	( cat ${ARM}/conf/kern.ldscript.head ; \
-	  OBJDUMP=${OBJDUMP} ${HOST_SH} ${ARM}/conf/mkldscript.sh \
+	  OBJDUMP=${OBJDUMP} ${HOST_SH} $S/conf/mkldscript.sh \
 		${SYSTEM_OBJ} ; \
 	  cat ${ARM}/conf/kern.ldscript.tail ) > ldscript
 
Index: arch/x68k/conf/files.x68k
===================================================================
RCS file: /cvsroot/src/sys/arch/x68k/conf/files.x68k,v
retrieving revision 1.61
diff -u -r1.61 files.x68k
--- arch/x68k/conf/files.x68k	11 Dec 2005 12:19:37 -0000	1.61
+++ arch/x68k/conf/files.x68k	3 Mar 2007 11:54:08 -0000
@@ -39,6 +39,7 @@
 file	arch/m68k/m68k/db_memrw.c	ddb
 file	arch/m68k/m68k/pmap_motorola.c
 file	arch/m68k/m68k/procfs_machdep.c	procfs
+file	arch/m68k/m68k/softintr.c
 file	arch/m68k/m68k/sys_machdep.c
 file	arch/m68k/m68k/vm_machdep.c
 
Index: arch/x68k/dev/kbd.c
===================================================================
RCS file: /cvsroot/src/sys/arch/x68k/dev/kbd.c,v
retrieving revision 1.26
diff -u -r1.26 kbd.c
--- arch/x68k/dev/kbd.c	24 Jan 2007 13:08:11 -0000	1.26
+++ arch/x68k/dev/kbd.c	3 Mar 2007 11:54:08 -0000
@@ -67,11 +67,12 @@
 
 	int sc_event_mode;	/* if true, collect events, else pass to ite */
 	struct evvar sc_events; /* event queue state */
+	void *sc_softintr_cookie;
 };
 
 void	kbdenable(int);
 int	kbdintr (void *);
-void	kbdsoftint(void);
+void	kbdsoftint(void *);
 void	kbd_bell(int);
 int	kbdcngetc(void);
 void	kbd_setLED(void);
@@ -113,8 +114,8 @@
 static void 
 kbdattach(struct device *parent, struct device *self, void *aux)
 {
-	struct kbd_softc *k = (void*) self;
-	struct mfp_softc *mfp = (void*) parent;
+	struct kbd_softc *sc = (void *)self;
+	struct mfp_softc *mfp = (void *)parent;
 	int s;
 
 	kbd_attached = 1;
@@ -122,11 +123,12 @@
 	s = spltty();
 
 	/* MFP interrupt #12 is for USART receive buffer full */
-	intio_intr_establish(mfp->sc_intr + 12, "kbd", kbdintr, self);
+	intio_intr_establish(mfp->sc_intr + 12, "kbd", kbdintr, sc);
+	sc->sc_softintr_cookie = softintr_establish(IPL_SOFT, kbdsoftint, sc);
 
 	kbdenable(1);
-	k->sc_event_mode = 0;
-	k->sc_events.ev_io = 0;
+	sc->sc_event_mode = 0;
+	sc->sc_events.ev_io = 0;
 	splx(s);
 
 	printf("\n");
@@ -318,7 +320,7 @@
 kbdintr(void *arg)
 {
 	u_char c, st;
-	struct kbd_softc *k = arg; /* XXX */
+	struct kbd_softc *sc = arg;
 	struct firm_event *fe;
 	int put;
 
@@ -331,9 +333,9 @@
 		return 0;	/* intr caused by an err -- no char received */
 
 	/* if not in event mode, deliver straight to ite to process key stroke */
-	if (! k->sc_event_mode) {
+	if (!sc->sc_event_mode) {
 		kbdbuf[kbdputoff++ & KBDBUFMASK] = c;
-		setsoftkbd();
+		softintr_schedule(sc->sc_softintr_cookie);
 		return 0;
 	}
 
@@ -341,24 +343,24 @@
 	   event and put it in the queue.  If the queue is full, the
 	   keystroke is lost (sorry!). */
 
-	put = k->sc_events.ev_put;
-	fe = &k->sc_events.ev_q[put];
+	put = sc->sc_events.ev_put;
+	fe = &sc->sc_events.ev_q[put];
 	put = (put + 1) % EV_QSIZE;
-	if (put == k->sc_events.ev_get) {
+	if (put == sc->sc_events.ev_get) {
 		log(LOG_WARNING, "keyboard event queue overflow\n"); /* ??? */
 		return 0;
 	}
 	fe->id = KEY_CODE(c);
 	fe->value = KEY_UP(c) ? VKEY_UP : VKEY_DOWN;
 	getmicrotime(&fe->time);
-	k->sc_events.ev_put = put;
-	EV_WAKEUP(&k->sc_events);
+	sc->sc_events.ev_put = put;
+	EV_WAKEUP(&sc->sc_events);
 
 	return 0;
 }
 
 void 
-kbdsoftint(void)			/* what if ite is not configured? */
+kbdsoftint(void *arg)			/* what if ite is not configured? */
 {
 	int s;
 
Index: arch/x68k/dev/zs.c
===================================================================
RCS file: /cvsroot/src/sys/arch/x68k/dev/zs.c,v
retrieving revision 1.29
diff -u -r1.29 zs.c
--- arch/x68k/dev/zs.c	28 Mar 2006 17:38:28 -0000	1.29
+++ arch/x68k/dev/zs.c	3 Mar 2007 11:54:08 -0000
@@ -139,7 +139,6 @@
 extern struct cfdriver zsc_cd;
 
 static int zshard(void *);
-int zssoft(void *);
 static int zs_get_speed(struct zs_chanstate *);
 
 
@@ -277,6 +276,8 @@
 	 */
 	if (intio_intr_establish(ia->ia_intr, "zs", zshard, zsc))
 		panic("zs_attach: interrupt vector busy");
+	zsc->zsc_softintr_cookie = softintr_establish(IPL_SOFTSERIAL,
+	    (void (*)(void *))zsc_intr_soft, zsc);
 	/* XXX; evcnt_attach() ? */
 
 	/*
@@ -329,35 +330,12 @@
 
 	/* We are at splzs here, so no need to lock. */
 	if (zsc->zsc_cs[0]->cs_softreq || zsc->zsc_cs[1]->cs_softreq)
-		setsoftserial();
+		softintr_schedule(zsc->zsc_softintr_cookie);
 
 	return (rval);
 }
 
 /*
- * Shared among the all chips. We have to look at all of them.
- */
-int 
-zssoft(void *arg)
-{
-	struct zsc_softc *zsc;
-	int s, unit;
-
-	/* Make sure we call the tty layer at spltty. */
-	s = spltty();
-	for (unit = 0; unit < zsc_cd.cd_ndevs; unit++) {
-		zsc = zsc_cd.cd_devs[unit];
-		if (zsc == NULL)
-			continue;
-		(void) zsc_intr_soft(zsc);
-	}
-	splx(s);
-
-	return (1);
-}
-
-
-/*
  * Compute the current baud rate given a ZS channel.
  */
 static int 
Index: arch/x68k/include/intr.h
===================================================================
RCS file: /cvsroot/src/sys/arch/x68k/include/intr.h,v
retrieving revision 1.12
diff -u -r1.12 intr.h
--- arch/x68k/include/intr.h	16 Feb 2007 02:53:51 -0000	1.12
+++ arch/x68k/include/intr.h	3 Mar 2007 11:54:08 -0000
@@ -46,6 +46,21 @@
 /* spl0 requires checking for software interrupts */
 void	spl0(void);
 
+#define splsoft()	splraise1()
+#define splsoftclock()	splsoft()
+#define splsoftnet()	splsoft()
+#define splsoftserial()	splsoft()
+#define splbio()	splraise3()
+#define splnet()        splraise4()
+#define spltty()        splraise4()
+#define splvm()         splraise4()
+#define splserial()     splraise5()
+#define splclock()      splraise6()
+#define splstatclock()  splclock()
+#define splhigh()       spl7()
+#define splsched()      spl7()
+#define spllock()       spl7()
+
 #define	splnone()	spl0()
 #define	splzs()		splraise5()	/* disallow serial interrupts */
 
@@ -53,54 +68,38 @@
 #define splx(s)         ((s) & PSL_IPL ? _spl(s) : spl0())
 
 #define	IPL_NONE	0
-#define	IPL_SOFTCLOCK	(PSL_S|PSL_IPL1)
-#define	IPL_SOFTNET	(PSL_S|PSL_IPL1)
-#define	IPL_BIO		(PSL_S|PSL_IPL3)
-#define	IPL_NET		(PSL_S|PSL_IPL4)
-#define	IPL_TTY		(PSL_S|PSL_IPL4)
-#define	IPL_VM		(PSL_S|PSL_IPL4)
-#define	IPL_CLOCK	(PSL_S|PSL_IPL6)
-#define	IPL_STATCLOCK	(PSL_S|PSL_IPL6)
-#define	IPL_SCHED	(PSL_S|PSL_IPL7)
-#define	IPL_HIGH	(PSL_S|PSL_IPL7)
-#define	IPL_LOCK	(PSL_S|PSL_IPL7)
+#define	IPL_SOFTCLOCK	1
+#define	IPL_SOFTNET	2
+#define	IPL_SOFTSERIAL	3
+#define	IPL_SOFT	4
+#define	IPL_BIO		5
+#define	IPL_NET		6
+#define	IPL_TTY		7
+#define	IPL_VM		8
+#define	IPL_SERIAL	9
+#define	IPL_CLOCK	10
+#define	IPL_STATCLOCK	IPL_CLOCK
+#define	IPL_HIGH	11
+#define	IPL_SCHED	IPL_HIGH
+#define	IPL_LOCK	IPL_HIGH
+#define	NIPL		12
 
 typedef int ipl_t;
 typedef struct {
-	ipl_t _ipl;
+	ipl_t _psl;
 } ipl_cookie_t;
 
-static inline ipl_cookie_t
-makeiplcookie(ipl_t ipl)
-{
-
-	return (ipl_cookie_t){._ipl = ipl};
-}
+ipl_cookie_t makeiplcookie(ipl_t);
 
 static inline int
 splraiseipl(ipl_cookie_t icookie)
 {
 
-	return _splraise(icookie._ipl);
+	return _splraise(icookie._psl);
 }
 
-#include <sys/spl.h>
+#endif /* _KERNEL && ! _LOCORE */
 
-/*
- * simulated software interrupt register
- */
-extern unsigned char ssir;
-
-#define SIR_NET		0x1
-#define SIR_CLOCK	0x2
-#define SIR_SERIAL	0x4
-#define SIR_KBD		0x8
-
-#define siroff(x)	ssir &= ~(x)
-#define setsoftnet()	ssir |= SIR_NET
-#define setsoftclock()	ssir |= SIR_CLOCK
-#define setsoftserial() ssir |= SIR_SERIAL
-#define setsoftkbd()    ssir |= SIR_KBD
+#include <m68k/softintr.h>
 
-#endif /* _KERNEL && ! _LOCORE */
-#endif
+#endif /* !_X68K_INTR_H_ */
Index: arch/x68k/include/types.h
===================================================================
RCS file: /cvsroot/src/sys/arch/x68k/include/types.h,v
retrieving revision 1.11
diff -u -r1.11 types.h
--- arch/x68k/include/types.h	19 Sep 2006 10:13:10 -0000	1.11
+++ arch/x68k/include/types.h	3 Mar 2007 11:54:08 -0000
@@ -6,6 +6,7 @@
 #include <m68k/types.h>
 
 #define	__HAVE_DEVICE_REGISTER
+#define	__HAVE_GENERIC_SOFT_INTERRUPTS
 #define	__HAVE_GENERIC_TODR
 #define	__HAVE_TIMECOUNTER
 
Index: arch/x68k/include/z8530var.h
===================================================================
RCS file: /cvsroot/src/sys/arch/x68k/include/z8530var.h,v
retrieving revision 1.6
diff -u -r1.6 z8530var.h
--- arch/x68k/include/z8530var.h	11 Dec 2005 12:19:44 -0000	1.6
+++ arch/x68k/include/z8530var.h	3 Mar 2007 11:54:08 -0000
@@ -138,6 +138,7 @@
 	/* Machine-dependent part follows... */
 	struct zs_chanstate  zsc_cs_store[2];
 	struct zsdevice *zsc_addr;
+	void *zsc_softintr_cookie;
 };
 
 /*
Index: arch/x68k/x68k/autoconf.c
===================================================================
RCS file: /cvsroot/src/sys/arch/x68k/x68k/autoconf.c,v
retrieving revision 1.49
diff -u -r1.49 autoconf.c
--- arch/x68k/x68k/autoconf.c	24 Nov 2006 22:04:24 -0000	1.49
+++ arch/x68k/x68k/autoconf.c	3 Mar 2007 11:54:09 -0000
@@ -73,6 +73,8 @@
 {
 	x68k_realconfig = 1;
 
+	softintr_init();
+
 	if (config_rootfound("mainbus", NULL) == NULL)
 		panic("no mainbus found");
 
Index: arch/x68k/x68k/machdep.c
===================================================================
RCS file: /cvsroot/src/sys/arch/x68k/x68k/machdep.c,v
retrieving revision 1.135
diff -u -r1.135 machdep.c
--- arch/x68k/x68k/machdep.c	22 Feb 2007 06:49:34 -0000	1.135
+++ arch/x68k/x68k/machdep.c	3 Mar 2007 11:54:09 -0000
@@ -903,28 +903,31 @@
 	return(0);
 }
 
-void netintr(void);
-
 void
-netintr(void)
+intrhand(int sr)
 {
-
-#define DONETISR(bit, fn) do {		\
-	if (netisr & (1 << bit)) {	\
-		netisr &= ~(1 << bit);	\
-		fn();			\
-	}				\
-} while (0)
-
-#include <net/netisr_dispatch.h>
-
-#undef DONETISR
+	printf("intrhand: unexpected sr 0x%x\n", sr);
 }
 
-void
-intrhand(int sr)
+static const int ipl2psl_table[] = {
+	[IPL_NONE]       = PSL_IPL0,
+	[IPL_SOFT]       = PSL_IPL1,
+	[IPL_SOFTCLOCK]  = PSL_IPL1,
+	[IPL_SOFTNET]    = PSL_IPL1,
+	[IPL_SOFTSERIAL] = PSL_IPL1,
+	[IPL_BIO]        = PSL_IPL3,
+	[IPL_NET]        = PSL_IPL4,
+	[IPL_TTY]        = PSL_IPL4,
+	[IPL_VM]         = PSL_IPL4,
+	[IPL_CLOCK]      = PSL_IPL6,
+	[IPL_HIGH]       = PSL_IPL7,
+};
+
+ipl_cookie_t
+makeiplcookie(ipl_t ipl)
 {
-	printf("intrhand: unexpected sr 0x%x\n", sr);
+
+	return (ipl_cookie_t){._psl = ipl2psl_table[ipl] | PSL_S};
 }
 
 #if (defined(DDB) || defined(DEBUG)) && !defined(PANICBUTTON)
Index: arch/x68k/x68k/trap.c
===================================================================
RCS file: /cvsroot/src/sys/arch/x68k/x68k/trap.c,v
retrieving revision 1.84
diff -u -r1.84 trap.c
--- arch/x68k/x68k/trap.c	22 Feb 2007 06:49:34 -0000	1.84
+++ arch/x68k/x68k/trap.c	3 Mar 2007 11:54:09 -0000
@@ -596,39 +596,9 @@
 
 	case T_SSIR:		/* software interrupt */
 	case T_SSIR|T_USER:
-		if (ssir & SIR_NET) {
-			void netintr(void);
-			siroff(SIR_NET);
-			uvmexp.softs++;
-			netintr();
-		}
-		if (ssir & SIR_CLOCK) {
-			siroff(SIR_CLOCK);
-			uvmexp.softs++;
-			softclock(NULL);
-		}
-		if (ssir & SIR_SERIAL) {
-#include "zsc.h"
-#if NZSC > 0
-			void zssoft(int);
-#endif
-			siroff(SIR_SERIAL);
-			uvmexp.softs++;
-#if NZSC > 0
-			zssoft(0);
-#endif
-		}
-		if (ssir & SIR_KBD) {
-#include "kbd.h"
-#if NKBD > 0
-			void	kbdsoftint(void);
-#endif
-			siroff(SIR_KBD);
-			uvmexp.softs++;
-#if NKBD > 0
-			kbdsoftint();
-#endif
-		}
+
+		softintr_dispatch();
+
 		/*
 		 * If this was not an AST trap, we are all done.
 		 */
--- /dev/null	2007-03-03 20:17:41.000000000 +0900
+++ arch/luna68k/conf/kern.ldscript.head	2007-03-03 19:50:25.000000000 +0900
@@ -0,0 +1,14 @@
+/*	$NetBSD$	*/
+
+OUTPUT_FORMAT("elf32-m68k")
+OUTPUT_ARCH(m68k)
+SECTIONS
+{
+  . = 0x0000c020;	/* 0x20 == sizeof(a.out header) */
+
+  /* Read-only sections, merged into text segment: */
+  .text :
+  {
+    *(.text)
+    *(.text.*)
+    *(.rodata) *(.rodata.*)
--- /dev/null	2007-03-03 20:17:41.000000000 +0900
+++ arch/luna68k/conf/kern.ldscript.tail	2007-03-03 19:34:45.000000000 +0900
@@ -0,0 +1,35 @@
+/*	$NetBSD$	*/
+
+  } =0
+  PROVIDE (__etext = .);
+  PROVIDE (_etext = .);
+  PROVIDE (etext = .);
+  . = ALIGN(0x1000);
+  .data :
+  {
+    __data_start = . ;
+    *(.data)
+    *(.data.*)
+    *(.sdata)
+    *(.sdata.*)
+  }
+  _edata = .;
+  PROVIDE (edata = .);
+  __bss_start = .;
+  __bss_start__ = .;
+  .bss       :
+  {
+   *(.dynbss)
+   *(.bss)
+   *(.bss.*)
+   *(COMMON)
+   /* Align here to ensure that the .bss section occupies space up to
+      _end.  Align after .bss to ensure correct alignment even if the
+      .bss section disappears because there are no input sections.  */
+   . = ALIGN(32 / 8);
+  }
+  . = ALIGN(32 / 8);
+  _end = .;
+  _bss_end__ = . ; __bss_end__ = . ; __end__ = . ;
+  PROVIDE (end = .);
+}
--- /dev/null	2007-03-03 20:17:41.000000000 +0900
+++ arch/m68k/include/softintr.h	2007-03-03 14:00:05.000000000 +0900
@@ -0,0 +1,96 @@
+/*	$NetBSD$	*/
+
+/*-
+ * Copyright (c) 1996, 1997, 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *        This product includes software developed by the NetBSD
+ *        Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _M68K_SOFTINTR_H_
+#define	_M68K_SOFTINTR_H_
+
+#define	SI_SOFTSERIAL	0	/* serial software interrupts */
+#define	SI_SOFTNET	1	/* network software interrupts */
+#define	SI_SOFTCLOCK	2	/* clock software interrupts */
+#define	SI_SOFT		3	/* other software interrupts */
+
+#define	SI_NQUEUES	4
+
+#define	SI_QUEUENAMES {							\
+	"serial",							\
+	"net",								\
+	"clock",							\
+	"misc",								\
+}
+
+#ifdef _KERNEL
+#include <sys/device.h>
+#include <sys/queue.h>
+#include <machine/psl.h>
+
+struct m68k_soft_intrhand {
+	LIST_ENTRY(m68k_soft_intrhand) sih_q;
+	struct m68k_soft_intr *sih_intrhead;
+	void (*sih_func)(void *);
+	void *sih_arg;
+	volatile int sih_pending;
+};
+
+struct m68k_soft_intr {
+	LIST_HEAD(, m68k_soft_intrhand) msi_q;
+	struct evcnt msi_evcnt;
+	uint8_t msi_ipl;
+};
+
+void *softintr_establish(int, void (*)(void *), void *);
+void softintr_disestablish(void *);
+void softintr_init(void);
+void softintr_dispatch(void);
+
+extern volatile uint8_t ssir;
+#define setsoft(x)	ssir |= (1 << (x))
+
+#define softintr_schedule(arg)				\
+do {							\
+	struct m68k_soft_intrhand *__sih = (arg);	\
+	__sih->sih_pending = 1;				\
+	setsoft(__sih->sih_intrhead->msi_ipl);		\
+} while (/* CONSTCOND */0)
+
+/* XXX For legacy software interrupts */
+extern struct m68k_soft_intrhand *softnet_intrhand;
+#define setsoftnet()	softintr_schedule(softnet_intrhand)
+
+#endif /* _KERNEL */
+
+#endif /* _M68K_SOFTINTR_H_ */
--- /dev/null	2007-03-03 20:17:41.000000000 +0900
+++ arch/m68k/m68k/softintr.c	2007-03-03 13:59:29.000000000 +0900
@@ -0,0 +1,239 @@
+/*	$NetBSD$	*/
+
+/*-
+ * Copyright (c) 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Steve C. Woodford and Jason R. Thorpe.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *        This product includes software developed by the NetBSD
+ *        Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Generic soft interrupt implementation for m68k ports which use
+ * hp300 style simulated software interrupt with VAX REI emulation.
+ *
+ * Based heavily on the alpha implementation by Jason Thorpe.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/malloc.h>
+#include <sys/sched.h>
+
+#include <net/netisr.h>
+
+#include <uvm/uvm_extern.h>
+
+#include <m68k/asm_single.h>
+
+#include <machine/cpu.h>
+#include <machine/intr.h>
+
+struct m68k_soft_intrhand *softnet_intrhand;
+volatile uint8_t ssir;
+
+static struct m68k_soft_intr m68k_soft_intrs[SI_NQUEUES];
+
+static void netintr(void);
+
+/*
+ * softintr_init()
+ *
+ *	Initialise hp300 style software interrupt subsystem.
+ */
+void
+softintr_init(void)
+{
+	static const char *softintr_names[] = SI_QUEUENAMES;
+	struct m68k_soft_intr *msi;
+	int i;
+
+	for (i = 0; i < SI_NQUEUES; i++) {
+		msi = &m68k_soft_intrs[i];
+		LIST_INIT(&msi->msi_q);
+		msi->msi_ipl = i;
+		evcnt_attach_dynamic(&msi->msi_evcnt, EVCNT_TYPE_INTR,
+		    NULL, "soft", softintr_names[i]);
+	}
+
+	/* Establish legacy software interrupt handlers */
+	softnet_intrhand = softintr_establish(IPL_SOFTNET,
+	    (void (*)(void *))netintr, NULL);
+
+	KASSERT(softnet_intrhand != NULL);
+}
+
+/*
+ * softintr_dispatch()
+ *
+ *	Internal function for running queued soft interrupts.
+ */
+void
+softintr_dispatch(void)
+{
+	struct m68k_soft_intr *msi;
+	struct m68k_soft_intrhand *sih;
+	bool handled;
+	uint8_t mask;
+
+	do {
+		handled = false;
+		mask = 0x01;
+		for (msi = m68k_soft_intrs;
+		    msi < &m68k_soft_intrs[SI_NQUEUES];
+		    msi++, mask <<= 1) {
+
+			if ((ssir & mask) == 0)
+				continue;
+
+			msi->msi_evcnt.ev_count++;
+			handled = true;
+			single_inst_bclr_b(ssir, mask);
+
+			for (sih = LIST_FIRST(&msi->msi_q);
+			     sih != NULL;
+			     sih = LIST_NEXT(sih, sih_q)) {
+				if (sih->sih_pending) {
+					uvmexp.softs++;
+					sih->sih_pending = 0;
+					(*sih->sih_func)(sih->sih_arg);
+				}
+			}
+		}
+	} while (handled);
+}
+
+static int
+ipl2si(ipl_t ipl)
+{
+	int si;
+
+	switch (ipl) {
+	case IPL_SOFTNET:
+		si = SI_SOFTNET;
+		break;
+	case IPL_SOFTCLOCK:
+		si = SI_SOFTCLOCK;
+		break;
+	case IPL_SOFTSERIAL:
+		si = SI_SOFTSERIAL;
+		break;
+	default:
+		si = SI_SOFT;
+		break;
+	}
+
+	return si;
+}
+
+/*
+ * softintr_establish()		[interface]
+ *
+ *	Register a software interrupt handler.
+ */
+void *
+softintr_establish(int ipl, void (*func)(void *), void *arg)
+{
+	struct m68k_soft_intr *msi;
+	struct m68k_soft_intrhand *sih;
+	int s;
+
+	if (__predict_false(ipl >= NIPL || ipl < 0 || func == NULL))
+		panic("%s: invalid ipl (%d) or function", __func__, ipl);
+
+	msi = &m68k_soft_intrs[ipl2si(ipl)];
+
+	sih = malloc(sizeof(struct m68k_soft_intrhand), M_DEVBUF, M_NOWAIT);
+	if (__predict_true(sih != NULL)) {
+		sih->sih_intrhead = msi;
+		sih->sih_func = func;
+		sih->sih_arg = arg;
+		sih->sih_pending = 0;
+		s = splsoft();
+		LIST_INSERT_HEAD(&msi->msi_q, sih, sih_q);
+		splx(s);
+	}
+	return sih;
+}
+
+/*
+ * softintr_disestablish()	[interface]
+ *
+ *	Unregister a software interrupt handler.
+ */
+void
+softintr_disestablish(void *arg)
+{
+	struct m68k_soft_intrhand *sih;
+	int s;
+
+	sih = arg;
+
+	s = splsoft();
+	LIST_REMOVE(sih, sih_q);
+	splx(s);
+
+	free(sih, M_DEVBUF);
+}
+
+void
+netintr(void)
+{
+	int s, isr;
+
+	for (;;) {
+		s = splhigh();
+		isr = netisr;
+		netisr = 0;
+		splx(s);
+
+		if (isr == 0)
+			return;
+
+#define DONETISR(bit, func)						\
+		do {							\
+			if (isr & (1 << bit))				\
+				func();					\
+		} while (/* CONSTCOND */0)
+
+		s = splsoftnet();
+
+#include <net/netisr_dispatch.h>
+
+#undef DONETISR
+
+		splx(s);
+	}
+}
--- /dev/null	2007-03-03 20:17:41.000000000 +0900
+++ conf/mkldscript.sh	2007-03-03 20:06:55.000000000 +0900
@@ -0,0 +1,15 @@
+#!/bin/sh
+#	$NetBSD$
+
+TEMPLATE=$1
+shift
+
+SETS=`$OBJDUMP -x $* | fgrep "RELOCATION RECORDS FOR [link_set" | \
+        sort -u | sed 's/^.*\[\(.*\)\]:$/\1/'`
+
+for s in $SETS; do
+        printf "    . = ALIGN(4);\n"
+        printf "    PROVIDE (__start_%s = .);\n" $s
+        printf "    *(%s)\n" $s
+        printf "    PROVIDE (__stop_%s = .);\n" $s
+done