Subject: My diffs vs. 0303 snapshot
To: None <port-powerpc@NetBSD.ORG, tsubai@iri.co.jp>
From: Charles M. Hannum <mycroft@mit.edu>
List: port-powerpc
Date: 03/12/1998 06:44:57
This patch contains a few things:

1) I #ifdef'ed the ADB calls in clock.c, so that the OFCONS kernel
   builds again.  Doesn't actually seem to talk to my console, though.

2) I reintroduced the full interrupt hierarchy from the i386 port.  I
   believe this is desirable, and we should eventually use splserial()
   for zs intterrupts, but I haven't made that change.  This has the
   effect of fixing the bug that not all interrupts block softclock(),
   which caused lossage with at least NFS.

3) I reintroduced the `interrupt sharing types'.  There is a register
   that I believe is used to switch between level-trigger and
   edge-trigger interrupt, and we should support that.  (It may even be
   necessary for Nubus machines, but I don't know.)

4) I added the DELAY() you recommended in the ADB setup, which seems to
   fix the hangs at autoconfig time.

5) I fixed an ommission in the DDB changes from me that you included.

6) I added the NATM and NETATALK glue in the netisr handler.


diff -rc2 powermac/conf/files.powermac /sys/arch/powermac/conf/files.powermac
*** powermac/conf/files.powermac	Sun Mar  1 22:48:49 1998
--- /sys/arch/powermac/conf/files.powermac	Wed Mar  4 15:08:07 1998
***************
*** 104,108 ****
  device adb
  attach adb at obio
! file arch/powermac/dev/adb.c			adb
  file arch/powermac/dev/adb_direct.c		adb
  file arch/powermac/dev/adbsys.c			adb
--- 104,108 ----
  device adb
  attach adb at obio
! file arch/powermac/dev/adb.c			adb needs-flag
  file arch/powermac/dev/adb_direct.c		adb
  file arch/powermac/dev/adbsys.c			adb
diff -rc2 powermac/dev/adb.c /sys/arch/powermac/dev/adb.c
*** powermac/dev/adb.c	Mon Mar  2 02:47:44 1998
--- /sys/arch/powermac/dev/adb.c	Wed Mar 11 23:41:16 1998
***************
*** 135,139 ****
  	printf(" irq %d\n", ca->ca_intr[0]);
  
! 	intr_establish(ca->ca_intr[0], 0, IPL_TTY, adb_intr, sc);
  
  	adb_polling = 1;
--- 135,139 ----
  	printf(" irq %d\n", ca->ca_intr[0]);
  
! 	intr_establish(ca->ca_intr[0], IST_LEVEL, IPL_TTY, adb_intr, sc);
  
  	adb_polling = 1;
diff -rc2 powermac/dev/adb_direct.c /sys/arch/powermac/dev/adb_direct.c
*** powermac/dev/adb_direct.c	Mon Mar  2 08:51:52 1998
--- /sys/arch/powermac/dev/adb_direct.c	Thu Mar 12 04:59:25 1998
***************
*** 1257,1260 ****
--- 1257,1262 ----
  	adb_hw_setup();		/* init the VIA bits and hard reset ADB */
  
+ 	DELAY(1000);
+ 
  	/* send an ADB reset first */
  	adb_op_sync((Ptr) 0, (Ptr) 0, (Ptr) 0, (short) 0x00);
diff -rc2 powermac/dev/esp.c /sys/arch/powermac/dev/esp.c
*** powermac/dev/esp.c	Tue Feb 24 08:17:12 1998
--- /sys/arch/powermac/dev/esp.c	Wed Mar 11 23:41:26 1998
***************
*** 296,300 ****
  
  	/* and the interuppts */
! 	intr_establish(esc->sc_pri, 0, IPL_BIO, (void *)ncr53c9x_intr, sc);
  
  	/* Do the common parts of attachment. */
--- 296,301 ----
  
  	/* and the interuppts */
! 	intr_establish(esc->sc_pri, IST_LEVEL, IPL_BIO, (void *)ncr53c9x_intr,
! 	    sc);
  
  	/* Do the common parts of attachment. */
diff -rc2 powermac/dev/if_mc.c /sys/arch/powermac/dev/if_mc.c
*** powermac/dev/if_mc.c	Tue Feb 24 09:03:06 1998
--- /sys/arch/powermac/dev/if_mc.c	Wed Mar 11 23:41:35 1998
***************
*** 167,173 ****
  
  	/* install interrupt handlers */
! 	/*intr_establish(ca->ca_intr[1], 0, IPL_NET, mc_dmaintr, sc);*/
! 	intr_establish(ca->ca_intr[2], 0, IPL_NET, mc_dmaintr, sc);
! 	intr_establish(ca->ca_intr[0], 0, IPL_NET, mcintr, sc);
  
  	sc->sc_biucc = XMTSP_64;
--- 167,173 ----
  
  	/* install interrupt handlers */
! 	/*intr_establish(ca->ca_intr[1], IST_LEVEL, IPL_NET, mc_dmaintr, sc);*/
! 	intr_establish(ca->ca_intr[2], IST_LEVEL, IPL_NET, mc_dmaintr, sc);
! 	intr_establish(ca->ca_intr[0], IST_LEVEL, IPL_NET, mcintr, sc);
  
  	sc->sc_biucc = XMTSP_64;
diff -rc2 powermac/dev/zs.c /sys/arch/powermac/dev/zs.c
*** powermac/dev/zs.c	Sun Mar  1 22:39:51 1998
--- /sys/arch/powermac/dev/zs.c	Wed Mar 11 23:41:43 1998
***************
*** 397,406 ****
  
  	/* XXX - Now safe to install interrupt handlers. */
! 	intr_establish(intr_a, 0, IPL_TTY, zshard, NULL);
! 	intr_establish(intr_b, 0, IPL_TTY, zshard, NULL);
! 	/*intr_establish(28, 0, IPL_SOFTTTY, zssoft, NULL);*/
        {
! 	extern int softtty_inited;	/* XXX */
! 	softtty_inited = 1;
        }
  
--- 397,406 ----
  
  	/* XXX - Now safe to install interrupt handlers. */
! 	intr_establish(intr_a, IST_LEVEL, IPL_TTY, zshard, NULL);
! 	intr_establish(intr_b, IST_LEVEL, IPL_TTY, zshard, NULL);
! 	/*intr_establish(SIR_SOFTSERIAL, 0, IPL_SOFTSERIAL, zssoft, NULL);*/
        {
! 	extern int softserial_inited;	/* XXX */
! 	softserial_inited = 1;
        }
  
***************
*** 489,493 ****
  			if (zssoftpending == 0) {
  				zssoftpending = 1;
! 				setsofttty();
  			}
  		}
--- 489,493 ----
  			if (zssoftpending == 0) {
  				zssoftpending = 1;
! 				setsoftserial();
  			}
  		}
diff -rc2 powermac/include/cpu.h /sys/arch/powermac/include/cpu.h
*** powermac/include/cpu.h	Thu Feb 12 09:57:47 1998
--- /sys/arch/powermac/include/cpu.h	Wed Mar 11 23:42:53 1998
***************
*** 50,54 ****
  	void (*setsoftnet) __P((void));
  	void (*clock_return) __P((struct clockframe *, int));
- 	void (*irq_establish) __P((int, int, void (*)(void *), void *));
  };
  extern struct machvec machine_interface;
--- 50,53 ----
***************
*** 59,64 ****
  #define	clock_return(frame, level)		\
  	((*machine_interface.clock_return)((frame), (level)))
- #define	irq_establish(irq, level, handler, arg)	\
- 	(intr_establish( (irq), 0, (level), (handler), (arg)))
  
  #define	CLKF_USERMODE(frame)	(((frame)->srr1 & PSL_PR) != 0)
--- 58,61 ----
diff -rc2 powermac/include/db_machdep.h /sys/arch/powermac/include/db_machdep.h
*** powermac/include/db_machdep.h	Tue Feb 24 09:45:01 1998
--- /sys/arch/powermac/include/db_machdep.h	Wed Mar  4 14:41:40 1998
***************
*** 45,81 ****
  typedef	int		db_expr_t;	/* expression - signed */
  struct powerpc_saved_state {
! 	u_int32_t	r0;		/* data registers */
! 	u_int32_t	r1;
! 	u_int32_t	r2;
! 	u_int32_t	r3;
! 	u_int32_t	r4;
! 	u_int32_t	r5;
! 	u_int32_t	r6;
! 	u_int32_t	r7;
! 	u_int32_t	r8;
! 	u_int32_t	r9;
! 	u_int32_t	r10;
! 	u_int32_t	r11;
! 	u_int32_t	r12;
! 	u_int32_t	r13;
! 	u_int32_t	r14;
! 	u_int32_t	r15;
! 	u_int32_t	r16;
! 	u_int32_t	r17;
! 	u_int32_t	r18;
! 	u_int32_t	r19;
! 	u_int32_t	r20;
! 	u_int32_t	r21;
! 	u_int32_t	r22;
! 	u_int32_t	r23;
! 	u_int32_t	r24;
! 	u_int32_t	r25;
! 	u_int32_t	r26;
! 	u_int32_t	r27;
! 	u_int32_t	r28;
! 	u_int32_t	r29;
! 	u_int32_t	r30;
! 	u_int32_t	r31;
! 	u_int32_t	r32;
  	u_int32_t	iar;
  	u_int32_t	msr;
--- 45,49 ----
  typedef	int		db_expr_t;	/* expression - signed */
  struct powerpc_saved_state {
! 	u_int32_t	r[32];		/* data registers */
  	u_int32_t	iar;
  	u_int32_t	msr;
diff -rc2 powermac/include/intr.h /sys/arch/powermac/include/intr.h
*** powermac/include/intr.h	Mon Feb 16 05:11:34 1998
--- /sys/arch/powermac/include/intr.h	Sat Mar  7 01:33:29 1998
***************
*** 36,50 ****
  /* Interrupt priority `levels'. */
  #define	IPL_NONE	9	/* nothing */
! #define	IPL_SOFTCLOCK	8	/* software clock interrupt */
! #define	IPL_SOFTNET	7	/* software network interrupt */
  #define	IPL_BIO		6	/* block I/O */
  #define	IPL_NET		5	/* network */
! #define	IPL_TTY		4	/* terminal */
  #define	IPL_IMP		3	/* memory allocation */
  #define	IPL_AUDIO	2	/* audio */
  #define	IPL_CLOCK	1	/* clock */
! #define	IPL_HIGH	0	/* everything */
  #define	NIPL		10
  
  #ifndef _LOCORE
  
--- 36,58 ----
  /* Interrupt priority `levels'. */
  #define	IPL_NONE	9	/* nothing */
! #define	IPL_SOFTCLOCK	8	/* timeouts */
! #define	IPL_SOFTNET	7	/* protocol stacks */
  #define	IPL_BIO		6	/* block I/O */
  #define	IPL_NET		5	/* network */
! #define	IPL_SOFTSERIAL	4	/* serial */
! #define	IPL_TTY		3	/* terminal */
  #define	IPL_IMP		3	/* memory allocation */
  #define	IPL_AUDIO	2	/* audio */
  #define	IPL_CLOCK	1	/* clock */
! #define	IPL_HIGH	1	/* everything */
! #define	IPL_SERIAL	0	/* serial */
  #define	NIPL		10
  
+ /* Interrupt sharing types. */
+ #define	IST_NONE	0	/* none */
+ #define	IST_PULSE	1	/* pulsed */
+ #define	IST_EDGE	2	/* edge-triggered */
+ #define	IST_LEVEL	3	/* level-triggered */
+ 
  #ifndef _LOCORE
  
***************
*** 74,78 ****
  static __inline int spllower __P((int));
  static __inline void splx __P((int));
! static __inline void set_sint __P((int));
  
  extern volatile int cpl, ipending, astpending, tickspending;
--- 82,86 ----
  static __inline int spllower __P((int));
  static __inline void splx __P((int));
! static __inline void softintr __P((int));
  
  extern volatile int cpl, ipending, astpending, tickspending;
***************
*** 85,107 ****
   */
  static __inline int
! splraise(newcpl)
! 	int newcpl;
  {
! 	int oldcpl;
  
  	__asm__ volatile("sync; eieio\n");	/* don't reorder.... */
! 	oldcpl = cpl;
! 	cpl = oldcpl | newcpl;
  	__asm__ volatile("sync; eieio\n");	/* reorder protect */
! 	return(oldcpl);
  }
  
  static __inline void
! splx(newcpl)
! 	int newcpl;
  {
  	__asm__ volatile("sync; eieio\n");	/* reorder protect */
! 	cpl = newcpl;
! 	if(ipending & ~newcpl)
  		do_pending_int();
  	__asm__ volatile("sync; eieio\n");	/* reorder protect */
--- 93,116 ----
   */
  static __inline int
! splraise(ncpl)
! 	int ncpl;
  {
! 	int ocpl;
  
  	__asm__ volatile("sync; eieio\n");	/* don't reorder.... */
! 	ocpl = cpl;
! 	cpl = ocpl | ncpl;
  	__asm__ volatile("sync; eieio\n");	/* reorder protect */
! 	return (ocpl);
  }
  
  static __inline void
! splx(ncpl)
! 	int ncpl;
  {
+ 
  	__asm__ volatile("sync; eieio\n");	/* reorder protect */
! 	cpl = ncpl;
! 	if (ipending & ~ncpl)
  		do_pending_int();
  	__asm__ volatile("sync; eieio\n");	/* reorder protect */
***************
*** 109,124 ****
  
  static __inline int
! spllower(newcpl)
! 	int newcpl;
  {
! 	int oldcpl;
  
  	__asm__ volatile("sync; eieio\n");	/* reorder protect */
! 	oldcpl = cpl;
! 	cpl = newcpl;
! 	if(ipending & ~newcpl)
  		do_pending_int();
  	__asm__ volatile("sync; eieio\n");	/* reorder protect */
! 	return(oldcpl);
  }
  
--- 118,133 ----
  
  static __inline int
! spllower(ncpl)
! 	int ncpl;
  {
! 	int ocpl;
  
  	__asm__ volatile("sync; eieio\n");	/* reorder protect */
! 	ocpl = cpl;
! 	cpl = ncpl;
! 	if (ipending & ~ncpl)
  		do_pending_int();
  	__asm__ volatile("sync; eieio\n");	/* reorder protect */
! 	return (ocpl);
  }
  
***************
*** 126,169 ****
   * the disable/enable. i need to read the manual once more.... */
  static __inline void
! set_sint(pending)
! 	int	pending;
  {
! 	int	msrsave;
  
! 	__asm__ ("mfmsr %0" : "=r"(msrsave));
! 	__asm__ volatile ("mtmsr %0" :: "r"(msrsave & ~PSL_EE));
! 	ipending |= pending;
! 	__asm__ volatile ("mtmsr %0" :: "r"(msrsave));
  }
  
  #define	ICU_LEN		32
  
! #define	SINT_CLOCK	0x10000000
! #define	SINT_NET	0x20000000
! #define	SINT_TTY	0x40000000
! #define	SPL_CLOCK	0x80000000
! #define	SINT_MASK	(SINT_CLOCK|SINT_NET|SINT_TTY)
! 
! #define	CNT_SINT_TTY	28
! #define	CNT_SINT_NET	29
! #define	CNT_SINT_CLOCK	30
! #define	CNT_CLOCK	31
  
  #define splbio()	splraise(imask[IPL_BIO])
  #define splnet()	splraise(imask[IPL_NET])
  #define spltty()	splraise(imask[IPL_TTY])
! #define splclock()	splraise(SPL_CLOCK|SINT_CLOCK|SINT_NET)
! #define splimp()	splraise(imask[IPL_IMP])
! #define splstatclock()	splhigh()
! #define	splsoftclock()	spllower(SINT_CLOCK)
! #define	splsoftnet()	splraise(SINT_NET)
! #define	splsofttty()	splraise(SINT_TTY)
! 
! #define	setsoftclock()	set_sint(SINT_CLOCK);
! #define	setsoftnet()	set_sint(SINT_NET);
! #define	setsofttty()	set_sint(SINT_TTY);
  
! #define	splhigh()	splraise(0xffffffff)
  #define	spl0()		spllower(0)
  
  #endif /* !_LOCORE */
--- 135,188 ----
   * the disable/enable. i need to read the manual once more.... */
  static __inline void
! softintr(ipl)
! 	int ipl;
  {
! 	int msrsave;
  
! 	__asm__ volatile("mfmsr %0" : "=r"(msrsave));
! 	__asm__ volatile("mtmsr %0" :: "r"(msrsave & ~PSL_EE));
! 	ipending |= 1 << ipl;
! 	__asm__ volatile("mtmsr %0" :: "r"(msrsave));
  }
  
  #define	ICU_LEN		32
  
! /* Soft interrupt masks. */
! #define	SIR_CLOCK	28
! #define	SIR_NET		29
! #define	SIR_SERIAL	30
! #define	SPL_CLOCK	31
  
+ /*
+  * Hardware interrupt masks
+  */
  #define splbio()	splraise(imask[IPL_BIO])
  #define splnet()	splraise(imask[IPL_NET])
  #define spltty()	splraise(imask[IPL_TTY])
! #define	splaudio()	splraise(imask[IPL_AUDIO])
! #define splclock()	splraise(imask[IPL_CLOCK])
! #define splstatclock()	splclock()
! #define	splserial()	splraise(imask[IPL_SERIAL])
! 
! /*
!  * Software interrupt masks
!  *
!  * NOTE: splsoftclock() is used by hardclock() to lower the priority from
!  * clock to softclock before it calls softclock().
!  */
! #define	splsoftclock()	spllower(imask[IPL_SOFTCLOCK])
! #define	splsoftnet()	splraise(imask[IPL_SOFTNET])
! #define	splsoftserial()	splraise(imask[IPL_SOFTSERIAL])
  
! /*
!  * Miscellaneous
!  */
! #define splimp()	splraise(imask[IPL_IMP])
! #define	splhigh()	splraise(imask[IPL_HIGH])
  #define	spl0()		spllower(0)
+ 
+ #define	setsoftclock()	softintr(SIR_CLOCK)
+ #define	setsoftnet()	softintr(SIR_NET)
+ #define	setsoftserial()	softintr(SIR_SERIAL)
  
  #endif /* !_LOCORE */
diff -rc2 powermac/pci/pci_machdep.c /sys/arch/powermac/pci/pci_machdep.c
*** powermac/pci/pci_machdep.c	Mon Feb  9 11:20:31 1998
--- /sys/arch/powermac/pci/pci_machdep.c	Wed Mar 11 23:42:13 1998
***************
*** 246,250 ****
  		panic("pci_intr_establish: bogus handle 0x%x\n", ih);
  
! 	return intr_establish(ih, 0, level, func, arg);
  }
  
--- 246,250 ----
  		panic("pci_intr_establish: bogus handle 0x%x\n", ih);
  
! 	return intr_establish(ih, IST_LEVEL, level, func, arg);
  }
  
diff -rc2 powermac/powermac/clock.c /sys/arch/powermac/powermac/clock.c
*** powermac/powermac/clock.c	Mon Mar  2 01:01:33 1998
--- /sys/arch/powermac/powermac/clock.c	Wed Mar 11 21:53:33 1998
***************
*** 39,42 ****
--- 39,44 ----
  #include <machine/cpu.h>
  
+ #include "adb.h"
+ 
  /*
   * Initially we assume a processor with a bus frequency of 12.5 MHz.
***************
*** 49,55 ****
  #define SECDAY 86400
  
  extern int adb_read_date_time __P((int *));
  extern int adb_set_date_time __P((int));
! 
  
  void
--- 51,58 ----
  #define SECDAY 86400
  
+ #if NADB > 0
  extern int adb_read_date_time __P((int *));
  extern int adb_set_date_time __P((int));
! #endif
  
  void
***************
*** 63,67 ****
  	 * If we can't read from RTC, use the fs time.
  	 */
! 	if (adb_read_date_time(&rtc_time) < 0) {
  		time.tv_sec = base;
  		return;
--- 66,73 ----
  	 * If we can't read from RTC, use the fs time.
  	 */
! #if NADB > 0
! 	if (adb_read_date_time(&rtc_time) < 0)
! #endif
! 	{
  		time.tv_sec = base;
  		return;
***************
*** 88,92 ****
--- 94,101 ----
  resettodr()
  {
+ 
+ #if NADB > 0
  	adb_set_date_time(time.tv_sec);
+ #endif
  }
  
***************
*** 126,130 ****
  
  	pri = splclock();
! 	if (pri & SPL_CLOCK)
  		tickspending += nticks;
  	else {
--- 135,139 ----
  
  	pri = splclock();
! 	if (pri & (1 << SPL_CLOCK))
  		tickspending += nticks;
  	else {
***************
*** 142,146 ****
  		 * Do softclock stuff only on the last iteration.
  		 */
! 		frame->pri = pri | SINT_CLOCK;
  		while (--nticks > 0)
  			hardclock(frame);
--- 151,155 ----
  		 * Do softclock stuff only on the last iteration.
  		 */
! 		frame->pri = pri | (1 << SIR_CLOCK);
  		while (--nticks > 0)
  			hardclock(frame);
diff -rc2 powermac/powermac/extintr.c /sys/arch/powermac/powermac/extintr.c
*** powermac/powermac/extintr.c	Wed Feb 18 07:29:55 1998
--- /sys/arch/powermac/powermac/extintr.c	Wed Mar 11 21:59:52 1998
***************
*** 54,68 ****
  volatile int cpl, ipending, astpending, tickspending;
  int imask[NIPL];
- int intrmask[ICU_LEN], intrlevel[ICU_LEN];
- struct intrhand *intrhand[ICU_LEN];
  u_char *interrupt_reg;
  
! void intr_calculatemasks();
  
! int fakeintr(arg)
! 	void *arg;
! {
! 	return 0;
! }
  
  #define INT_STATE_REG  (interrupt_reg + 0x20)
--- 54,65 ----
  volatile int cpl, ipending, astpending, tickspending;
  int imask[NIPL];
  u_char *interrupt_reg;
  
! void intr_calculatemasks __P((void));
! char *intr_typename __P((int));
! int fakeintr __P((void *));
  
! int intrtype[ICU_LEN], intrmask[ICU_LEN], intrlevel[ICU_LEN];
! struct intrhand *intrhand[ICU_LEN];
  
  #define INT_STATE_REG  (interrupt_reg + 0x20)
***************
*** 72,131 ****
  
  /*
!  * external interrupt handler
   */
  void
! ext_intr()
  {
! 	int i, irq = 0;
! 	int o_imen, r_imen;
! 	int pcpl;
! 	struct intrhand *ih;
! 	volatile unsigned long int_state;
! 	extern long intrcnt[];
! 	extern int cold;
! 
! 	pcpl = splhigh() ;	/* Turn off all */
! start:
! 	int_state = in32rb(INT_STATE_REG);
  
! 	if (int_state == 0 && cold == 0) {
! 		printf("stray interrupt\n");
! 		goto out;
  	}
  
! 	for (i = 0; i < 32; i++) {
! 		if (int_state & (1 << i)) {
! 			irq = i;
! 			break;
! 		}
  	}
  
! 	o_imen = imen;
! 	r_imen = 1 << irq;
! 	imen |= r_imen;
  
! 	out32rb(INT_CLEAR_REG, r_imen);
! 	/*out32rb(INT_ENABLE_REG, ~imen);*/
  
! 	if ((pcpl & r_imen) != 0) {
! 		ipending |= r_imen;	/* Masked! Mark this as pending */
! 	} else {
! 		ih = intrhand[irq];
! 		while (ih) {
! 			(*ih->ih_fun)(ih->ih_arg);
! 			ih = ih->ih_next;
! 		}
! 		imen = o_imen;
  
! 		/*out32rb(INT_CLEAR_REG, r_imen);*/
! 		/*out32rb(INT_ENABLE_REG, ~imen);*/
  
! 		intrcnt[irq]++;
  	}
- 	int_state &= ~r_imen;
- 	if (int_state) goto start;
  
! out:
! 	splx(pcpl);	/* Process pendings. */
  }
  
--- 69,198 ----
  
  /*
!  * Recalculate the interrupt masks from scratch.
!  * We could code special registry and deregistry versions of this function that
!  * would be faster, but the code would be nastier, and we don't expect this to
!  * happen very much anyway.
   */
  void
! intr_calculatemasks()
  {
! 	int irq, level;
! 	struct intrhand *q;
  
! 	/* First, figure out which levels each IRQ uses. */
! 	for (irq = 0; irq < ICU_LEN; irq++) {
! 		register int levels = 0;
! 		for (q = intrhand[irq]; q; q = q->ih_next)
! 			levels |= 1 << q->ih_level;
! 		intrlevel[irq] = levels;
  	}
  
! 	/* Then figure out which IRQs use each level. */
! 	for (level = 0; level < NIPL; level++) {
! 		register int irqs = 0;
! 		for (irq = 0; irq < ICU_LEN; irq++)
! 			if (intrlevel[irq] & (1 << level))
! 				irqs |= 1 << irq;
! 		imask[level] = irqs;
  	}
  
! 	/*
! 	 * Initialize soft interrupt masks to block themselves.
! 	 */
! 	imask[IPL_SOFTCLOCK] = 1 << SIR_CLOCK;
! 	imask[IPL_SOFTNET] = 1 << SIR_NET;
! 	imask[IPL_SOFTSERIAL] = 1 << SIR_SERIAL;
  
! 	/*
! 	 * IPL_NONE is used for hardware interrupts that are never blocked,
! 	 * and do not block anything else.
! 	 */
! 	imask[IPL_NONE] = 0;
  
! 	/*
! 	 * Enforce a hierarchy that gives slow devices a better chance at not
! 	 * dropping data.
! 	 */
! 	imask[IPL_SOFTCLOCK] |= imask[IPL_NONE];
! 	imask[IPL_SOFTNET] |= imask[IPL_SOFTCLOCK];
! 	imask[IPL_BIO] |= imask[IPL_SOFTNET];
! 	imask[IPL_NET] |= imask[IPL_BIO];
! 	imask[IPL_SOFTSERIAL] |= imask[IPL_NET];
! 	imask[IPL_TTY] |= imask[IPL_SOFTSERIAL];
  
! 	/*
! 	 * There are tty, network and disk drivers that use free() at interrupt
! 	 * time, so imp > (tty | net | bio).
! 	 */
! 	imask[IPL_IMP] |= imask[IPL_TTY];
  
! 	imask[IPL_AUDIO] |= imask[IPL_IMP];
! 
! 	/*
! 	 * Since run queues may be manipulated by both the statclock and tty,
! 	 * network, and disk drivers, clock > imp.
! 	 */
! 	imask[IPL_CLOCK] |= imask[IPL_AUDIO];
! 
! 	/*
! 	 * IPL_HIGH must block everything that can manipulate a run queue.
! 	 */
! 	imask[IPL_HIGH] |= imask[IPL_CLOCK];
! 
! 	/*
! 	 * We need serial drivers to run at the absolute highest priority to
! 	 * avoid overruns, so serial > high.
! 	 */
! 	imask[IPL_SERIAL] |= imask[IPL_HIGH];
! 
! 	/* And eventually calculate the complete masks. */
! 	for (irq = 0; irq < ICU_LEN; irq++) {
! 		register int irqs = 1 << irq;
! 		for (q = intrhand[irq]; q; q = q->ih_next)
! 			irqs |= imask[q->ih_level];
! 		intrmask[irq] = irqs;
  	}
  
! 	/* Lastly, determine which IRQs are actually in use. */
! 	{
! 		register int irqs = 0;
! 		for (irq = 0; irq < ICU_LEN; irq++)
! 			if (intrhand[irq])
! 				irqs |= 1 << irq;
! 		imen = ~irqs;
! 		out32rb(INT_ENABLE_REG, ~imen);
! 	}
! }
! 
! int
! fakeintr(arg)
! 	void *arg;
! {
! 
! 	return 0;
! }
! 
! #define	LEGAL_IRQ(x)	((x) >= 0 && (x) < ICU_LEN)
! 
! char *
! intr_typename(type)
! 	int type;
! {
! 
! 	switch (type) {
!         case IST_NONE :
! 		return ("none");
!         case IST_PULSE:
! 		return ("pulsed");
!         case IST_EDGE:
! 		return ("edge-triggered");
!         case IST_LEVEL:
! 		return ("level-triggered");
! 	default:
! 		panic("intr_typename: invalid type %d", type);
! #if 1 /* XXX */
! 		return ("unknown");
! #endif
! 	}
  }
  
***************
*** 144,158 ****
  	static struct intrhand fakehand = {fakeintr};
  	extern int cold;
- 	u_int mask;
- 
- 	if (type != 0) {
- 		printf("intr_establish: unknown type (%d)\n", type);
- 		return NULL;
- 	}
  
  	/* no point in sleeping unless someone can free memory. */
  	ih = malloc(sizeof *ih, M_DEVBUF, cold ? M_NOWAIT : M_WAITOK);
  	if (ih == NULL)
! 		panic("isa_intr_establish: can't malloc handler info");
  
  	/*
--- 211,238 ----
  	static struct intrhand fakehand = {fakeintr};
  	extern int cold;
  
  	/* no point in sleeping unless someone can free memory. */
  	ih = malloc(sizeof *ih, M_DEVBUF, cold ? M_NOWAIT : M_WAITOK);
  	if (ih == NULL)
! 		panic("intr_establish: can't malloc handler info");
! 
! 	if (!LEGAL_IRQ(irq) || type == IST_NONE)
! 		panic("intr_establish: bogus irq or type");
! 
! 	switch (intrtype[irq]) {
! 	case IST_NONE:
! 		intrtype[irq] = type;
! 		break;
! 	case IST_EDGE:
! 	case IST_LEVEL:
! 		if (type == intrtype[irq])
! 			break;
! 	case IST_PULSE:
! 		if (type != IST_NONE)
! 			panic("intr_establish: can't share %s with %s",
! 			    intr_typename(intrtype[irq]),
! 			    intr_typename(type));
! 		break;
! 	}
  
  	/*
***************
*** 185,192 ****
  	*p = ih;
  
- 	mask = in32rb(INT_ENABLE_REG);
- 	mask |= 1 << irq;
- 	out32rb(INT_ENABLE_REG, mask);
- 
  	return (ih);
  }
--- 265,268 ----
***************
*** 203,206 ****
--- 279,285 ----
  	struct intrhand **p, *q;
  
+ 	if (!LEGAL_IRQ(irq))
+ 		panic("intr_disestablish: bogus irq");
+ 
  	/*
  	 * Remove the handler from the chain.
***************
*** 216,298 ****
  
  	intr_calculatemasks();
  }
  
  /*
!  * Recalculate the interrupt masks from scratch.
!  * We could code special registry and deregistry versions of this function that
!  * would be faster, but the code would be nastier, and we don't expect this to
!  * happen very much anyway.
   */
  void
! intr_calculatemasks()
  {
! 	int irq, level;
! 	struct intrhand *q;
  
! 	/* First, figure out which levels each IRQ uses. */
! 	for (irq = 0; irq < ICU_LEN; irq++) {
! 		register int levels = 0;
! 		for (q = intrhand[irq]; q; q = q->ih_next)
! 			levels |= 1 << q->ih_level;
! 		intrlevel[irq] = levels;
! 	}
  
! 	/* Then figure out which IRQs use each level. */
! 	for (level = 0; level < NIPL; level++) {
! 		register int irqs = 0;
! 		for (irq = 0; irq < ICU_LEN; irq++)
! 			if (intrlevel[irq] & (1 << level))
! 				irqs |= 1 << irq;
! 		imask[level] = irqs | SINT_MASK;
  	}
  
! 	/*
! 	 * IPL_NONE is used for hardware interrupts that are never blocked,
! 	 * and do not block anything else.
! 	 */
! 	imask[IPL_NONE] = 0;
  
! 	/*
! 	 * Enforce a hierarchy that gives slow devices a better chance at not
! 	 * dropping data.
! 	 */
! 	imask[IPL_TTY] |= imask[IPL_NET] | imask[IPL_BIO];
! 	imask[IPL_NET] |= imask[IPL_BIO];
  
! 	/*
! 	 * There are tty, network and disk drivers that use free() at interrupt
! 	 * time, so imp > (tty | net | bio).
! 	 */
! 	imask[IPL_IMP] |= imask[IPL_TTY] | imask[IPL_NET] | imask[IPL_BIO];
! 	imask[IPL_AUDIO] |= imask[IPL_IMP];
  
! 	/*
! 	 * Since run queues may be manipulated by both the statclock and tty,
! 	 * network, and disk drivers, clock > imp.
! 	 */
! 	imask[IPL_CLOCK] |= imask[IPL_AUDIO];
  
! 	/*
! 	 * IPL_HIGH must block everything that can manipulate a run queue.
! 	 */
! 	imask[IPL_HIGH] = 0xffffffff;
  
! 	/* And eventually calculate the complete masks. */
! 	for (irq = 0; irq < ICU_LEN; irq++) {
! 		register int irqs = 1 << irq;
! 		for (q = intrhand[irq]; q; q = q->ih_next)
! 			irqs |= imask[q->ih_level];
! 		intrmask[irq] = irqs | SINT_MASK;
  	}
  
! 	{
! 		register int irqs = 0;
! 		for (irq = 0; irq < ICU_LEN; irq++)
! 			if (intrhand[irq])
! 				irqs |= 1 << irq;
! 		imen = ~irqs;
! 
! 		/*out32rb(INT_ENABLE_REG, ~imen);*/
! 	}
  }
  
--- 295,360 ----
  
  	intr_calculatemasks();
+ 
+ 	if (intrhand[irq] == NULL)
+ 		intrtype[irq] = IST_NONE;
  }
  
  /*
!  * external interrupt handler
   */
  void
! ext_intr()
  {
! 	int i, irq = 0;
! 	int o_imen, r_imen;
! 	int pcpl;
! 	struct intrhand *ih;
! 	volatile unsigned long int_state;
! 	extern long intrcnt[];
! 	extern int cold;
  
! 	pcpl = splhigh() ;	/* Turn off all */
! start:
! 	int_state = in32rb(INT_STATE_REG);
  
! 	if (int_state == 0 && cold == 0) {
! 		printf("stray interrupt\n");
! 		goto out;
  	}
  
! 	for (i = 0; i < 32; i++) {
! 		if (int_state & (1 << i)) {
! 			irq = i;
! 			break;
! 		}
! 	}
  
! 	o_imen = imen;
! 	r_imen = 1 << irq;
! 	imen |= r_imen;
  
! 	out32rb(INT_CLEAR_REG, r_imen);
! 	/*out32rb(INT_ENABLE_REG, ~imen);*/
  
! 	if ((pcpl & r_imen) != 0) {
! 		ipending |= r_imen;	/* Masked! Mark this as pending */
! 	} else {
! 		ih = intrhand[irq];
! 		while (ih) {
! 			(*ih->ih_fun)(ih->ih_arg);
! 			ih = ih->ih_next;
! 		}
! 		imen = o_imen;
  
! 		/*out32rb(INT_CLEAR_REG, r_imen);*/
! 		/*out32rb(INT_ENABLE_REG, ~imen);*/
  
! 		intrcnt[irq]++;
  	}
+ 	int_state &= ~r_imen;
+ 	if (int_state) goto start;
  
! out:
! 	splx(pcpl);	/* Process pendings. */
  }
  
***************
*** 335,354 ****
  	/*out32rb(INT_ENABLE_REG, ~imen);*/
  
! 	if (ipending & SINT_CLOCK) {
! 		ipending &= ~SINT_CLOCK;
  		softclock();
! 		intrcnt[CNT_SINT_CLOCK]++;
  	}
! 	if (ipending & SINT_NET) {
! 		extern int netisr;
! 		int pisr = netisr;
! 		netisr = 0;
! 		ipending &= ~SINT_NET;
! 		softnet(pisr);
! 		intrcnt[CNT_SINT_NET]++;
! 	}
! 	if (ipending & SINT_TTY) {
! 		ipending &= ~SINT_TTY;
! 		softtty();
  	}
  	ipending &= pcpl;
--- 397,414 ----
  	/*out32rb(INT_ENABLE_REG, ~imen);*/
  
! 	if (ipending & (1 << SIR_CLOCK)) {
! 		ipending &= ~(1 << SIR_CLOCK);
  		softclock();
! 		intrcnt[SIR_CLOCK]++;
  	}
! 	if (ipending & (1 << SIR_NET)) {
! 		ipending &= ~(1 << SIR_NET);
! 		softnet();
! 		intrcnt[SIR_NET]++;
! 	}
! 	if (ipending & (1 << SIR_SERIAL)) {
! 		ipending &= ~(1 << SIR_SERIAL);
! 		softserial();
! 		intrcnt[SIR_SERIAL]++;
  	}
  	ipending &= pcpl;
diff -rc2 powermac/powermac/machdep.c /sys/arch/powermac/powermac/machdep.c
*** powermac/powermac/machdep.c	Mon Mar  2 09:12:28 1998
--- /sys/arch/powermac/powermac/machdep.c	Sat Mar  7 01:28:03 1998
***************
*** 688,694 ****
   */
  void
! softnet(isr)
! 	int isr;
  {
  #ifdef	INET
  #include "arp.h"
--- 688,699 ----
   */
  void
! softnet()
  {
+ 	extern volatile int netisr;
+ 	int isr;
+ 
+ 	isr = netisr;
+ 	netisr = 0;
+ 
  #ifdef	INET
  #include "arp.h"
***************
*** 716,719 ****
--- 721,732 ----
  		ccittintr();
  #endif
+ #ifdef	NATM
+ 	if (isr & (1 << NETISR_NATM))
+ 		natmintr();
+ #endif
+ #ifdef	NETATALK
+ 	if (isr & (1 << NETISR_ATALK))
+ 		atintr();
+ #endif
  #include "ppp.h"
  #if NPPP > 0
***************
*** 724,735 ****
  
  #include "zsc.h"
! int softtty_inited = 0;
  /*
   * Soft tty interrupts.
   */
  void
! softtty()
  {
! 	if (softtty_inited) {
  #if NZSC > 0
  		zssoft();	/* XXX */
--- 737,748 ----
  
  #include "zsc.h"
! int softserial_inited = 0;
  /*
   * Soft tty interrupts.
   */
  void
! softserial()
  {
! 	if (softserial_inited) {
  #if NZSC > 0
  		zssoft();	/* XXX */