diff -urN linux-2.6.10/arch/i386/kernel/time.c linux-2.6.10-pcsp/arch/i386/kernel/time.c
--- linux-2.6.10/arch/i386/kernel/time.c	2004-12-26 00:37:55.000000000 +0300
+++ linux-2.6.10-pcsp/arch/i386/kernel/time.c	2005-01-06 01:07:34.000000000 +0300
@@ -76,6 +76,9 @@
 
 EXPORT_SYMBOL(jiffies_64);
 
+volatile int pit_counter0_offset = 0;
+EXPORT_SYMBOL(pit_counter0_offset);
+
 unsigned long cpu_khz;	/* Detected as we calibrate the TSC */
 
 extern unsigned long wall_jiffies;
diff -urN linux-2.6.10/arch/i386/kernel/timers/timer_pit.c linux-2.6.10-pcsp/arch/i386/kernel/timers/timer_pit.c
--- linux-2.6.10/arch/i386/kernel/timers/timer_pit.c	2004-12-26 00:36:50.000000000 +0300
+++ linux-2.6.10-pcsp/arch/i386/kernel/timers/timer_pit.c	2005-01-06 01:07:34.000000000 +0300
@@ -139,6 +139,12 @@
 	} else
 		jiffies_p = jiffies_t;
 
+       /*
+        * when using PCSP, we must add the accumulated
+        * clockticks from the PCSP driver
+        */
+	count += pit_counter0_offset;
+
 	count_p = count;
 
 	spin_unlock_irqrestore(&i8253_lock, flags);
diff -urN linux-2.6.10/arch/i386/mach-default/setup.c linux-2.6.10-pcsp/arch/i386/mach-default/setup.c
--- linux-2.6.10/arch/i386/mach-default/setup.c	2004-10-21 21:21:57.000000000 +0400
+++ linux-2.6.10-pcsp/arch/i386/mach-default/setup.c	2005-01-06 01:07:34.000000000 +0300
@@ -71,7 +71,7 @@
 {
 }
 
-static struct irqaction irq0  = { timer_interrupt, SA_INTERRUPT, CPU_MASK_NONE, "timer", NULL, NULL};
+static struct irqaction irq0  = { timer_interrupt, SA_INTERRUPT | SA_SHIRQ, CPU_MASK_NONE, "timer", NULL, NULL};
 
 /**
  * time_init_hook - do any specific initialisations for the system timer.
diff -urN linux-2.6.10/arch/i386/mach-visws/setup.c linux-2.6.10-pcsp/arch/i386/mach-visws/setup.c
--- linux-2.6.10/arch/i386/mach-visws/setup.c	2004-08-20 11:51:21.000000000 +0400
+++ linux-2.6.10-pcsp/arch/i386/mach-visws/setup.c	2005-01-06 01:07:34.000000000 +0300
@@ -112,7 +112,7 @@
 
 static struct irqaction irq0 = {
 	.handler =	timer_interrupt,
-	.flags =	SA_INTERRUPT,
+	.flags =	SA_INTERRUPT | SA_SHIRQ,
 	.name =		"timer",
 };
 
diff -urN linux-2.6.10/arch/i386/mach-voyager/setup.c linux-2.6.10-pcsp/arch/i386/mach-voyager/setup.c
--- linux-2.6.10/arch/i386/mach-voyager/setup.c	2004-10-21 21:21:57.000000000 +0400
+++ linux-2.6.10-pcsp/arch/i386/mach-voyager/setup.c	2005-01-06 01:07:34.000000000 +0300
@@ -40,7 +40,7 @@
 {
 }
 
-static struct irqaction irq0  = { timer_interrupt, SA_INTERRUPT, CPU_MASK_NONE, "timer", NULL, NULL};
+static struct irqaction irq0  = { timer_interrupt, SA_INTERRUPT | SA_SHIRQ, CPU_MASK_NONE, "timer", NULL, NULL};
 
 void __init time_init_hook(void)
 {
diff -urN linux-2.6.10/CREDITS linux-2.6.10-pcsp/CREDITS
--- linux-2.6.10/CREDITS	2004-12-26 00:36:47.000000000 +0300
+++ linux-2.6.10-pcsp/CREDITS	2005-01-06 01:07:34.000000000 +0300
@@ -392,6 +392,8 @@
 N: Erik Inge Bolsų
 E: knan@mo.himolde.no
 D: Misc kernel hacks
+D: Updated PC speaker driver for 2.3
+S: Norway
 
 N: Andreas E. Bombe
 E: andreas.bombe@munich.netsurf.de
@@ -2985,6 +2987,14 @@
 S: Sunnyvale, California 94088-4132
 S: USA
 
+N: Stas Sergeev
+E: stsp@users.sourceforge.net
+W: http://www.geocities.com/stssppnn/pcsp.html
+D: PC-Speaker driver maintainer
+D: vm86 fixes, misc fixes
+D: dosemu developer
+S: Russia
+
 N: Simon Shapiro
 E: shimon@i-Connect.Net
 W: http://www.-i-Connect.Net/~shimon
diff -urN linux-2.6.10/drivers/input/gameport/gameport.c linux-2.6.10-pcsp/drivers/input/gameport/gameport.c
--- linux-2.6.10/drivers/input/gameport/gameport.c	2004-08-20 11:51:21.000000000 +0400
+++ linux-2.6.10-pcsp/drivers/input/gameport/gameport.c	2005-01-06 01:07:34.000000000 +0300
@@ -50,6 +50,7 @@
 	outb_p(0x00, 0x43);
 	count = inb_p(0x40);
 	count |= inb_p(0x40) << 8;
+	count += pit_counter0_offset;
 	spin_unlock_irqrestore(&i8253_lock, flags);
 
 	return count;
diff -urN linux-2.6.10/drivers/input/joystick/analog.c linux-2.6.10-pcsp/drivers/input/joystick/analog.c
--- linux-2.6.10/drivers/input/joystick/analog.c	2004-10-30 18:30:40.000000000 +0400
+++ linux-2.6.10-pcsp/drivers/input/joystick/analog.c	2005-01-06 01:07:34.000000000 +0300
@@ -154,6 +154,7 @@
         outb_p(0x00, 0x43);
         count = inb_p(0x40);
         count |= inb_p(0x40) << 8;
+        count += pit_counter0_offset;
         spin_unlock_irqrestore(&i8253_lock, flags);
 
         return count;
diff -urN linux-2.6.10/drivers/input/misc/pcspkr.c linux-2.6.10-pcsp/drivers/input/misc/pcspkr.c
--- linux-2.6.10/drivers/input/misc/pcspkr.c	2004-08-20 11:51:21.000000000 +0400
+++ linux-2.6.10-pcsp/drivers/input/misc/pcspkr.c	2005-01-06 01:07:34.000000000 +0300
@@ -16,6 +16,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/input.h>
+#include <linux/kd.h>
 #include <asm/8253pit.h>
 #include <asm/io.h>
 
@@ -26,6 +27,7 @@
 static char pcspkr_name[] = "PC Speaker";
 static char pcspkr_phys[] = "isa0061/input0";
 static struct input_dev pcspkr_dev;
+int volatile use_speaker_beep;
 
 spinlock_t i8253_beep_lock = SPIN_LOCK_UNLOCKED;
 
@@ -37,6 +39,10 @@
 	if (type != EV_SND)
 		return -1;
 
+	/* pcsp audio driver can set this */
+	if (!use_speaker_beep)
+		return -1;
+
 	switch (code) {
 		case SND_BELL: if (value) value = 1000;
 		case SND_TONE: break;
@@ -81,6 +87,8 @@
 
 	input_register_device(&pcspkr_dev);
 
+	use_speaker_beep = 1;
+
         printk(KERN_INFO "input: %s\n", pcspkr_name);
 
 	return 0;
@@ -93,3 +101,5 @@
 
 module_init(pcspkr_init);
 module_exit(pcspkr_exit);
+
+EXPORT_SYMBOL(use_speaker_beep);
diff -urN linux-2.6.10/include/asm-i386/signal.h linux-2.6.10-pcsp/include/asm-i386/signal.h
--- linux-2.6.10/include/asm-i386/signal.h	2004-10-21 21:22:22.000000000 +0400
+++ linux-2.6.10-pcsp/include/asm-i386/signal.h	2005-01-06 01:07:34.000000000 +0300
@@ -122,6 +122,7 @@
 #define SA_PROBE		SA_ONESHOT
 #define SA_SAMPLE_RANDOM	SA_RESTART
 #define SA_SHIRQ		0x04000000
+#define SA_FIRST		0x02000000
 #endif
 
 #define SIG_BLOCK          0	/* for blocking signals */
diff -urN linux-2.6.10/include/asm-i386/timex.h linux-2.6.10-pcsp/include/asm-i386/timex.h
--- linux-2.6.10/include/asm-i386/timex.h	2004-10-30 18:30:51.000000000 +0400
+++ linux-2.6.10-pcsp/include/asm-i386/timex.h	2005-01-06 01:07:34.000000000 +0300
@@ -51,4 +51,6 @@
 
 extern unsigned long cpu_khz;
 
+extern volatile int pit_counter0_offset;
+
 #endif
diff -urN linux-2.6.10/include/linux/interrupt.h linux-2.6.10-pcsp/include/linux/interrupt.h
--- linux-2.6.10/include/linux/interrupt.h	2004-12-26 00:37:12.000000000 +0300
+++ linux-2.6.10-pcsp/include/linux/interrupt.h	2005-01-06 01:07:34.000000000 +0300
@@ -31,6 +31,7 @@
 
 #define IRQ_NONE	(0)
 #define IRQ_HANDLED	(1)
+#define IRQ_DONE	(2)
 #define IRQ_RETVAL(x)	((x) != 0)
 
 struct irqaction {
diff -urN linux-2.6.10/include/linux/kd.h linux-2.6.10-pcsp/include/linux/kd.h
--- linux-2.6.10/include/linux/kd.h	2004-10-21 21:22:24.000000000 +0400
+++ linux-2.6.10-pcsp/include/linux/kd.h	2005-01-06 01:07:34.000000000 +0300
@@ -23,6 +23,7 @@
 
 #define KIOCSOUND	0x4B2F	/* start sound generation (0 for off) */
 #define KDMKTONE	0x4B30	/* generate tone */
+extern volatile int use_speaker_beep;
 
 #define KDGETLED	0x4B31	/* return current led state */
 #define KDSETLED	0x4B32	/* set led state [lights, not flags] */
diff -urN linux-2.6.10/kernel/irq/handle.c linux-2.6.10-pcsp/kernel/irq/handle.c
--- linux-2.6.10/kernel/irq/handle.c	2004-12-26 00:37:13.000000000 +0300
+++ linux-2.6.10-pcsp/kernel/irq/handle.c	2005-01-06 01:06:05.000000000 +0300
@@ -96,11 +96,11 @@
 
 	do {
 		ret = action->handler(irq, action->dev_id, regs);
-		if (ret == IRQ_HANDLED)
+		if (ret & IRQ_HANDLED)
 			status |= action->flags;
 		retval |= ret;
 		action = action->next;
-	} while (action);
+	} while (action && !(retval & IRQ_DONE));
 
 	if (status & SA_SAMPLE_RANDOM)
 		add_interrupt_randomness(irq);
diff -urN linux-2.6.10/kernel/irq/manage.c linux-2.6.10-pcsp/kernel/irq/manage.c
--- linux-2.6.10/kernel/irq/manage.c	2004-10-30 18:30:53.000000000 +0400
+++ linux-2.6.10-pcsp/kernel/irq/manage.c	2005-01-06 01:07:07.000000000 +0300
@@ -186,11 +186,16 @@
 			return -EBUSY;
 		}
 
-		/* add new interrupt at end of irq queue */
-		do {
-			p = &old->next;
-			old = *p;
-		} while (old);
+		if (!(new->flags & SA_FIRST)) {
+			/* add new interrupt at end of irq queue */
+			do {
+				p = &old->next;
+				old = *p;
+			} while (old);
+		} else {
+			/* add new interrupt at front of irq queue */
+			new->next = old;
+		}
 		shared = 1;
 	}
 
diff -urN linux-2.6.10/kernel/irq/spurious.c linux-2.6.10-pcsp/kernel/irq/spurious.c
--- linux-2.6.10/kernel/irq/spurious.c	2004-10-30 18:30:53.000000000 +0400
+++ linux-2.6.10-pcsp/kernel/irq/spurious.c	2005-01-06 01:05:36.000000000 +0300
@@ -27,7 +27,7 @@
 {
 	struct irqaction *action;
 
-	if (action_ret != IRQ_HANDLED && action_ret != IRQ_NONE) {
+	if (!(action_ret & IRQ_HANDLED) && action_ret != IRQ_NONE) {
 		printk(KERN_ERR "irq event %d: bogus return value %x\n",
 				irq, action_ret);
 	} else {
@@ -57,7 +57,7 @@
 
 void note_interrupt(unsigned int irq, irq_desc_t *desc, irqreturn_t action_ret)
 {
-	if (action_ret != IRQ_HANDLED) {
+	if (!(action_ret & IRQ_HANDLED)) {
 		desc->irqs_unhandled++;
 		if (action_ret != IRQ_NONE)
 			report_bad_irq(irq, desc, action_ret);
--- linux-2.6.10/arch/i386/Kconfig	2005-01-17 09:42:38.000000000 +0300
+++ linux-2.6.10-pcsp/arch/i386/Kconfig	2005-01-21 16:11:24.175798448 +0300
@@ -1235,3 +1235,8 @@
 	bool
 	depends on X86 && !EMBEDDED
 	default y
+
+config HAVE_PCSP_HOOK
+	bool
+	depends on X86_PC
+	default y
