Skip to contentSkip to conversation

kernel hooks for PC-Speaker driver

PATCH New Stas Sergeev 1 participant 1 message Apr 23, 2003 Char and misc drivers

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 kernel hooks for PC-Speaker driver

Hello.

As some of you know, I am maintaining a driver for pc-speaker, which can be downloaded here:
http://www.geocities.com/stssppnn/pcsp.html

I've been asked several times to if not get the driver included into the mainstream kernel, then at least make it fully modular. For this I need a couple of small hooks to be included into the kernel.
The patch that adds all the necessary hooks is attached. It doesn't (intended to) change any existing functionality so it must be absolutely harmless.
It is against 2.4.20 but it can be applied to anything up to 2.4.21-rc1-ac1 with some offsets.

Detailed explanation of the patch follows:
- use_speaker_beep variable controls whether the kd_mksound() can produce a beeps. By default is set to 1.
- Added SA_FIRST flag to add the irq handlers to the head of the chain. Kernel's timer irq handler produces a big latency so that if the pcsp handler is executed after it, the sound is horribly distorted.
- pit_counter0_offset is the variable that gets added to the value got from PIT counter. pscp driver alters the counter so the correction is necessary. Introduced read_pit_counter0() for that purpose.
- handle_timer_irq variable controls whether the kernel's timer handler is to be executed or not. 1 by default.
- use SA_SHIRQ flag for the kernel's timer irq handler to allow the driver to handle that irq as well.

I think this patch is trivial and probably can be applied to some testing tree in order to get the pc-speaker driver a chance for surviving :-)
Let me know if you feel the patch needs more work.

arch/i386/kernel/i386_ksyms.c +2 -0
diff -urN linux-2.4.20-no-pcsp/arch/i386/kernel/i386_ksyms.c linux/arch/i386/kernel/i386_ksyms.c
@@ -14,6 +14,7 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/tty.h>
+#include <linux/kd.h>
 
 #include <asm/semaphore.h>
 #include <asm/processor.h>
@@ -156,6 +157,7 @@
 
 #ifdef CONFIG_VT
 EXPORT_SYMBOL(screen_info);
+EXPORT_SYMBOL(use_speaker_beep);
 #endif
 
 EXPORT_SYMBOL(get_wchan);
arch/i386/kernel/irq.c +10 -5
diff -urN linux-2.4.20-no-pcsp/arch/i386/kernel/irq.c linux/arch/i386/kernel/irq.c
@@ -1023,11 +1023,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;
 	}
 
arch/i386/kernel/time.c +44 -24

100 lines not on this page · raw message

drivers/char/joystick/analog.c +1 -1
diff -urN linux-2.4.20-no-pcsp/drivers/char/joystick/analog.c linux/drivers/char/joystick/analog.c
@@ -137,7 +137,7 @@
  */
 
 #ifdef __i386__
-#define GET_TIME(x)	do { if (cpu_has_tsc) rdtscl(x); else { outb(0, 0x43); x = inb(0x40); x |= inb(0x40) << 8; } } while (0)
+#define GET_TIME(x)	do { if (cpu_has_tsc) rdtscl(x); else { x = read_pit_counter0(); } } while (0)
 #define DELTA(x,y)	(cpu_has_tsc?((y)-(x)):((x)-(y)+((x)<(y)?1193180L/HZ:0)))
 #define TIME_NAME	(cpu_has_tsc?"TSC":"PIT")
 #elif __x86_64__
drivers/char/joystick/gameport.c +2 -1
diff -urN linux-2.4.20-no-pcsp/drivers/char/joystick/gameport.c linux/drivers/char/joystick/gameport.c
@@ -39,6 +39,7 @@
 #include <linux/isapnp.h>
 #include <linux/stddef.h>
 #include <linux/delay.h>
+#include <linux/timex.h>
 
 MODULE_AUTHOR("Vojtech Pavlik <[email protected]>");
 MODULE_LICENSE("GPL");
@@ -64,7 +65,7 @@
 {
 #if defined(__i386__) || defined(__x86_64__)
 
-#define GET_TIME(x)     do { outb(0, 0x43); x = inb(0x40); x |= inb(0x40) << 8; } while (0)
+#define GET_TIME(x)     do { x = read_pit_counter0(); } while (0)
 #define DELTA(x,y)      ((y)-(x)+((y)<(x)?1193180L/HZ:0))
 
 	unsigned int i, t, t1, t2, t3, tx;
drivers/char/vt.c +7 -0
diff -urN linux-2.4.20-no-pcsp/drivers/char/vt.c linux/drivers/char/vt.c
@@ -38,6 +38,7 @@
 #endif /* CONFIG_FB_COMPAT_XPMAC */
 
 char vt_dont_switch;
+int volatile use_speaker_beep = 1;
 extern struct tty_driver console_driver;
 
 #define VT_IS_IN_USE(i)	(console_driver.table[i] && console_driver.table[i]->count)
@@ -98,6 +99,9 @@
 static void
 kd_nosound(unsigned long ignored)
 {
+       if (!use_speaker_beep)
+               return;
+
 	/* disable counter 2 */
 	outb(inb_p(0x61)&0xFC, 0x61);
 	return;
@@ -110,6 +114,9 @@
 	unsigned int count = 0;
 	unsigned long flags;
 
+       if (!use_speaker_beep)
+               return;
+
 	if (hz > 20 && hz < 32767)
 		count = 1193180 / hz;
 	
include/asm-i386/signal.h +1 -0
diff -urN linux-2.4.20-no-pcsp/include/asm-i386/signal.h linux/include/asm-i386/signal.h
@@ -119,6 +119,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 */
include/asm-i386/timex.h +5 -0
diff -urN linux-2.4.20-no-pcsp/include/asm-i386/timex.h linux/include/asm-i386/timex.h
@@ -50,8 +50,13 @@
 #endif
 }
 
+extern int read_pit_counter0(void);
+
 extern unsigned long cpu_khz;
 
+extern volatile int pit_counter0_offset;
+extern volatile int handle_timer_irq;
+
 #define vxtime_lock()		do {} while (0)
 #define vxtime_unlock()		do {} while (0)
 
include/linux/kd.h +1 -0
diff -urN linux-2.4.20-no-pcsp/include/linux/kd.h linux/include/linux/kd.h
@@ -22,6 +22,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] */