kernel hooks for PC-Speaker driver
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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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] */