diff -r -N -C2 0.99.pl6/include/asm/irq.h linux/include/asm/irq.h
*** 0.99.pl6/include/asm/irq.h	Fri Feb 26 19:27:36 1993
--- linux/include/asm/irq.h	Sun Mar  7 12:06:18 1993
***************
*** 134,149 ****
  	"decl _intr_count\n\t" \
  	"jne ret_from_sys_call\n\t" \
! 	"movl _bh_mask,%eax\n\t" \
! 	"andl _bh_active,%eax\n\t" \
  	"je ret_from_sys_call\n\t" \
- 	"incl _intr_count\n\t" \
- 	"sti\n\t" \
- 	"bsfl %eax,%eax\n\t" \
- 	"btrl %eax,_bh_active\n\t" \
- 	"pushl %eax\n\t" \
  	"call _do_bottom_half\n\t" \
- 	"addl $4,%esp\n\t" \
- 	"cli\n\t" \
- 	"decl _intr_count\n\t" \
  	"jmp ret_from_sys_call\n" \
  "\n.align 4\n" \
--- 134,140 ----
  	"decl _intr_count\n\t" \
  	"jne ret_from_sys_call\n\t" \
! 	"cmpl $0, _bh_active\n\t" \
  	"je ret_from_sys_call\n\t" \
  	"call _do_bottom_half\n\t" \
  	"jmp ret_from_sys_call\n" \
  "\n.align 4\n" \
***************
*** 159,164 ****
  	"decl _intr_count\n\t" \
  	"jne 1f\n\t" \
! 	"movl _bh_mask,%eax\n\t" \
! 	"andl _bh_active,%eax\n\t" \
  	"jne 2f\n" \
  	"1:\t" \
--- 150,154 ----
  	"decl _intr_count\n\t" \
  	"jne 1f\n\t" \
! 	"cmpl $0, _bh_active\n\t" \
  	"jne 2f\n" \
  	"1:\t" \
***************
*** 165,177 ****
  	RESTORE_MOST \
  	"\n.align 4\n" \
! 	"2:\tincl _intr_count\n\t" \
! 	"sti\n\t" \
! 	"bsfl %eax,%eax\n\t" \
! 	"btrl %eax,_bh_active\n\t" \
! 	"pushl %eax\n\t" \
! 	"call _do_bottom_half\n\t" \
! 	"addl $4,%esp\n\t" \
! 	"cli\n\t" \
! 	"decl _intr_count\n\t" \
  	RESTORE_MOST \
  "\n\n.align 4\n" \
--- 155,159 ----
  	RESTORE_MOST \
  	"\n.align 4\n" \
! 	"2:\tcall _do_bottom_half\n\t" \
  	RESTORE_MOST \
  "\n\n.align 4\n" \
diff -r -N -C2 0.99.pl6/include/linux/interrupt.h linux/include/linux/interrupt.h
*** 0.99.pl6/include/linux/interrupt.h	Fri Feb 26 19:27:33 1993
--- linux/include/linux/interrupt.h	Sun Mar  7 12:06:05 1993
***************
*** 18,21 ****
--- 18,22 ----
  	CONSOLE_BH,
  	SERIAL_BH,
+ 	TTYTIMER_BH,
  	TTY_BH,
  	INET_BH,
***************
*** 27,30 ****
--- 28,43 ----
  	__asm__ __volatile__("btsl %1,%0":"=m" (bh_active):"ir" (nr));
  }
+ 
+ /*
+  * Macros to disable and enable software interrupts (also known as
+  * "bottom half" processing).
+  */
+ 
+ extern long intr_count;
+ extern void redo_bottom_half(void);
+ 
+ #define SOFT_INT_OFF	do { intr_count++; } while (0)
+ #define SOFT_INT_ON	do { if (--intr_count == 0 && bh_active)\
+ 				 redo_bottom_half(); } while (0)
  
  #endif
diff -r -N -C2 0.99.pl6/kernel/chr_drv/Makefile linux/kernel/chr_drv/Makefile
*** 0.99.pl6/kernel/chr_drv/Makefile	Fri Feb 26 19:27:13 1993
--- linux/kernel/chr_drv/Makefile	Sun Mar  7 14:42:52 1993
***************
*** 15,24 ****
  	$(AS) -c -o $*.o $<
  .c.o:
! 	$(CC) $(CFLAGS) -c $<
  
  SUBDIRS= sound
  
! OBJS  = tty_io.o console.o keyboard.o serial.o \
! 	tty_ioctl.o pty.o lp.o vt.o mem.o mouse.o \
  	busmouse.o psaux.o msbusmouse.o atixlmouse.o
  
--- 15,27 ----
  	$(AS) -c -o $*.o $<
  .c.o:
! 	$(CC) $(CFLAGS) -c -o $*.o $<
  
  SUBDIRS= sound
  
! OBJS  = console.o keyboard.o serial.o \
! 	tty/tty.o tty/ioctl.o tty/tty_0.o \
! 	tty/crted.o tty/ed.o tty/regexp.o tty/edfuncs.o \
! 	tty/update.o tty/output.o \
! 	pty.o lp.o vt.o vt2.o mem.o mouse.o \
  	busmouse.o psaux.o msbusmouse.o atixlmouse.o
  
***************
*** 26,29 ****
--- 29,33 ----
  
  chr_drv.a: $(OBJS)
+ 	rm -f chr_drv.a
  	$(AR) rcs chr_drv.a $(OBJS)
  	sync
***************
*** 43,47 ****
  
  dep:
! 	$(CPP) -M $(KEYBOARD) *.c > .depend
  	for i in $(SUBDIRS); do (cd $$i && $(MAKE) dep) || exit; done
  
--- 47,51 ----
  
  dep:
! 	$(CPP) -M $(KEYBOARD) $(OBJS:.o=.c) > .depend
  	for i in $(SUBDIRS); do (cd $$i && $(MAKE) dep) || exit; done
  
diff -r -N -C2 0.99.pl6/kernel/irq.c linux/kernel/irq.c
*** 0.99.pl6/kernel/irq.c	Fri Feb 26 19:27:27 1993
--- linux/kernel/irq.c	Sun Mar  7 12:06:33 1993
***************
*** 35,39 ****
  #define CR0_NE 32
  
! static unsigned long intr_count=0;
  static unsigned char cache_21 = 0xff;
  static unsigned char cache_A1 = 0xff;
--- 35,39 ----
  #define CR0_NE 32
  
! long intr_count=0;
  static unsigned char cache_21 = 0xff;
  static unsigned char cache_A1 = 0xff;
***************
*** 40,62 ****
  
  unsigned long bh_active = 0;
- unsigned long bh_mask = 0xFFFFFFFF;
  struct bh_struct bh_base[32]; 
  
  /*
!  * do_bottom_half() runs at normal kernel priority: all interrupts
!  * enabled.  do_bottom_half() is atomic with respect to itself: a
!  * bottom_half handler need not be re-entrant.  This function is
!  * called only when bh_active is non-zero and when there aren't any
!  * nested irq's active.
   */
! void do_bottom_half(int nr)
  {
  	struct bh_struct *bh;
  
! 	bh = bh_base+nr;
! 	if (bh->routine != NULL)
! 		bh->routine(bh->data);
! 	else
! 		printk ("irq.c:bad bottom half entry.\n");
  }
  
--- 40,120 ----
  
  unsigned long bh_active = 0;
  struct bh_struct bh_base[32]; 
  
+ 
+ /*
+  * Return the index of the first nonzero bit in arg, or -1 if arg is zero.
+  */
+ static inline int get_first_bit(unsigned long arg)
+ {
+ 	int nr;
+ 
+ 	asm("bsfl %1,%0" : "=r" (nr) : "r" (arg), "0" (-1) : "cc");
+ 	return nr;
+ }
+ 
+ /*
+  * Clear the specified bit in bh_active.
+  */
+ static inline void clear_bh_active_bit(int nr)
+ {
+ 	asm("btrl %1,%0" : "=m" (bh_active) : "r" (nr) : "cc");
+ }
+ 
  /*
!  * do_bottom_half() and redo_bottom_half() run handlers with all
!  * interrupts enabled.  The only difference is that do_bottom_half()
!  * is called with interrupts disabled and redo_bottom_half() is called
!  * with them enabled.  do_bottom_half() is called when returning from
!  * a hardware interrupt, and redo_bottom_half() is called when software
!  * interrupts are reenabled.  Both functions are called only when
!  * intr_count is zero.
!  *
!  * Only one bottom half handler can be run at a time, so that handlers
!  * do not need to be reenterant.
   */
! void do_bottom_half()
! {
! 	int nr;
! 	struct bh_struct *bh;
! 
! 	intr_count = 1;
! 	for (;;) {
! 		nr = get_first_bit(bh_active);
! 		if (nr < 0)
! 			break;
! 		sti();
! 		clear_bh_active_bit(nr);
! 		bh = bh_base + nr;
! 		if (bh->routine != NULL)
! 			bh->routine(bh->data);
! 		else
! 			printk ("irq.c:bad bottom half entry.\n");
! 		cli();
! 	}
! 	intr_count = 0;
! }
! 
! void redo_bottom_half()
  {
+ 	int nr;
  	struct bh_struct *bh;
  
! 	intr_count = 1;
! 	for (;;) {
! 		cli();
! 		nr = get_first_bit(bh_active);
! 		if (nr < 0)
! 			break;
! 		sti();
! 		clear_bh_active_bit(nr);
! 		bh = bh_base + nr;
! 		if (bh->routine != NULL)
! 			bh->routine(bh->data);
! 		else
! 			printk ("irq.c:bad bottom half entry.\n");
! 	}
! 	intr_count = 0;
! 	sti();
  }
  
