]> git.pld-linux.org Git - packages/kernel.git/blob - pcsp1.4-ss4-2.4.19.diff
- added description of djurban's branch
[packages/kernel.git] / pcsp1.4-ss4-2.4.19.diff
1 diff -urN linux-2.4.19-clean/CREDITS linux-2.4.19/CREDITS
2 --- linux-2.4.19-clean/CREDITS  Sun Aug  4 03:44:28 2002
3 +++ linux-2.4.19/CREDITS        Sun Aug  4 03:52:26 2002
4 @@ -361,6 +361,8 @@
5  N: Erik Inge Bolsø
6  E: knan@mo.himolde.no
7  D: Misc kernel hacks
8 +D: Updated PC speaker driver for 2.3
9 +S: Norway
10  
11  N: Andreas E. Bombe
12  E: andreas.bombe@munich.netsurf.de
13 @@ -2698,6 +2700,15 @@
14  S: Sunnyvale, California 94088-4132
15  S: USA
16  
17 +N: Stas Sergeev
18 +E: stssppnn@yahoo.com
19 +W: http://dosemu.sourceforge.net/stas
20 +W: http://www.geocities.com/stssppnn/pcsp.html
21 +D: PC-Speaker driver maintainer
22 +D: vm86 fixes, OSS fixes
23 +D: dosemu hacking
24 +S: Russia
25 +
26  N: Simon Shapiro
27  E: shimon@i-Connect.Net
28  W: http://www.-i-Connect.Net/~shimon
29 diff -urN linux-2.4.19-clean/Documentation/Configure.help linux-2.4.19/Documentation/Configure.help
30 --- linux-2.4.19-clean/Documentation/Configure.help     Sun Aug  4 03:44:29 2002
31 +++ linux-2.4.19/Documentation/Configure.help   Fri Aug 16 18:52:24 2002
32 @@ -18617,11 +18617,6 @@
33    as <file:Documentation/sound/README.modules>; the module will be
34    called soundcore.o.
35  
36 -  I'm told that even without a sound card, you can make your computer
37 -  say more than an occasional beep, by programming the PC speaker.
38 -  Kernel patches and supporting utilities to do that are in the pcsp
39 -  package, available at <ftp://ftp.infradead.org/pub/pcsp/>.
40 -
41  OSS sound modules
42  CONFIG_SOUND_OSS
43    OSS is the Open Sound System suite of sound card drivers.  They make
44 @@ -19401,6 +19396,51 @@
45    Maestro 2E.  See <file:Documentation/sound/Maestro> for more
46    details.
47  
48 +Internal PC speaker support
49 +CONFIG_PCSP
50 +  If you don't have a sound card in your computer, you can include a
51 +  driver for the PC speaker which allows it to act like a primitive
52 +  sound card. You can compile this as a module, in which case only the
53 +  timer-interrupt hooks and frequency initialization code will appear
54 +  in the kernel, and the rest of the driver will be loaded as a module
55 +  whenever you want. Further this driver supports DACs
56 +  (Digital-to-Analog-Converter) connected to the parallel port.
57 +
58 +  You don't need this driver if you only want your computer to beep.
59 +
60 +Use doubled modulation frequency
61 +CONFIG_PCSP_HIGH_FRQ
62 +  Standard modulation frequency for PC-Speaker is 18.5KHz.
63 +  This can produce a high-pitched tone on some motherboards.
64 +  If you have this problem, try enabling this option.
65 +  It will make PC-Speaker driver use 36KHz if possible, but
66 +  it will produce 5-bit sound instead of 6-bit.
67 +
68 +  If unsure, say N.
69 +
70 +PC speaker automatic measurement
71 +CONFIG_PCSP_NO_TEST_SPEED
72 +  The PCSP-driver automatically tests the speed of your computer and
73 +  configure itself at kernel-startup. If your machine is too slow
74 +  (386SX and cannot play with more than 12500 Hz) the driver is disabled
75 +  and you here a beep.
76 +
77 +  However, you can override this if you specify a 'pcsp=SAMPLERATE' at
78 +  kernel commandline or by disabling the automatic speed detection.
79 +  THIS IS NOT RECOMMENDED, your machine may HANG if you select a
80 +  samplerate, which is to high for your machine.
81 +
82 +  If the measurement switch the driver off but an older version was
83 +  working on your machine, please contact me (beck@dresearch.de).
84 +  It is safe to answer 'N' here.
85 +
86 +PC speaker selected samplerate
87 +CONFIG_PCSP_SRATE
88 +  If you have disabled the automatically speed test, select here to
89 +  real samplerate that is used for PC speaker. The full range from
90 +  12000Hz up to 18356 is allowed. Higher rates results in better
91 +  sound quality but may crash your machine if it is too slow (<486DX-33).
92 +
93  ESS Maestro3/Allegro driver
94  CONFIG_SOUND_MAESTRO3
95    Say Y or M if you have a sound system driven by ESS's Maestro 3
96 diff -urN linux-2.4.19-clean/Makefile linux-2.4.19/Makefile
97 --- linux-2.4.19-clean/Makefile Sun Aug  4 03:44:29 2002
98 +++ linux-2.4.19/Makefile       Sun Aug  4 03:52:27 2002
99 @@ -189,6 +189,12 @@
100  DRIVERS-$(CONFIG_HOTPLUG_PCI) += drivers/hotplug/vmlinux-obj.o
101  DRIVERS-$(CONFIG_ISDN_BOOL) += drivers/isdn/vmlinux-obj.o
102  
103 +ifneq ($(CONFIG_SOUND),y)
104 +  ifdef CONFIG_PCSP
105 +  DRIVERS-y += drivers/sound/sounddrivers.o
106 +  endif
107 +endif
108 +
109  DRIVERS := $(DRIVERS-y)
110  
111  
112 diff -urN linux-2.4.19-clean/arch/i386/kernel/time.c linux-2.4.19/arch/i386/kernel/time.c
113 --- linux-2.4.19-clean/arch/i386/kernel/time.c  Thu Mar 14 03:37:55 2002
114 +++ linux-2.4.19/arch/i386/kernel/time.c        Fri Aug 16 19:04:44 2002
115 @@ -38,6 +38,7 @@
116  #include <linux/mm.h>
117  #include <linux/interrupt.h>
118  #include <linux/time.h>
119 +#include <linux/pcsp.h>
120  #include <linux/delay.h>
121  #include <linux/init.h>
122  #include <linux/smp.h>
123 @@ -243,6 +244,14 @@
124         } else
125                 jiffies_p = jiffies_t;
126  
127 +#if defined(CONFIG_PCSP) || defined(CONFIG_PCSP_MODULE)
128 +       /*
129 +        * when using PCSP, we must add the accumulated
130 +        * clockticks from the PCSP driver
131 +        */
132 +       count += pcsp_clockticks - pcsp_timer0_latch;
133 +#endif
134 +
135         count_p = count;
136  
137         count = ((LATCH-1) - count) * TICK_SIZE;
138 diff -urN linux-2.4.19-clean/drivers/char/joystick/analog.c linux-2.4.19/drivers/char/joystick/analog.c
139 --- linux-2.4.19-clean/drivers/char/joystick/analog.c   Fri Oct 26 01:01:51 2001
140 +++ linux-2.4.19/drivers/char/joystick/analog.c Sun Aug  4 03:52:27 2002
141 @@ -39,6 +39,7 @@
142  #include <linux/init.h>
143  #include <linux/input.h>
144  #include <linux/gameport.h>
145 +#include <linux/pcsp.h>
146  #include <asm/timex.h>
147  
148  MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
149 @@ -138,7 +139,7 @@
150  
151  #ifdef __i386__
152  #define TSC_PRESENT    (test_bit(X86_FEATURE_TSC, &boot_cpu_data.x86_capability))
153 -#define GET_TIME(x)    do { if (TSC_PRESENT) rdtscl(x); else { outb(0, 0x43); x = inb(0x40); x |= inb(0x40) << 8; } } while (0)
154 +#define GET_TIME(x)    do { if (TSC_PRESENT) rdtscl(x); else { outb(0, 0x43); x = inb(0x40); x |= inb(0x40) << 8; } x += pcsp_clockticks - pcsp_timer0_latch; } while (0)
155  #define DELTA(x,y)     (TSC_PRESENT?((y)-(x)):((x)-(y)+((x)<(y)?1193180L/HZ:0)))
156  #define TIME_NAME      (TSC_PRESENT?"TSC":"PIT")
157  #elif __x86_64__
158 diff -urN linux-2.4.19-clean/drivers/char/joystick/gameport.c linux-2.4.19/drivers/char/joystick/gameport.c
159 --- linux-2.4.19-clean/drivers/char/joystick/gameport.c Sat Sep 15 01:40:00 2001
160 +++ linux-2.4.19/drivers/char/joystick/gameport.c       Sun Aug  4 03:52:27 2002
161 @@ -39,6 +39,7 @@
162  #include <linux/isapnp.h>
163  #include <linux/stddef.h>
164  #include <linux/delay.h>
165 +#include <linux/pcsp.h>
166  
167  MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
168  MODULE_LICENSE("GPL");
169 @@ -64,7 +65,7 @@
170  {
171  #if defined(__i386__) || defined(__x86_64__)
172  
173 -#define GET_TIME(x)     do { outb(0, 0x43); x = inb(0x40); x |= inb(0x40) << 8; } while (0)
174 +#define GET_TIME(x)     do { outb(0, 0x43); x = inb(0x40); x |= inb(0x40) << 8; x += pcsp_clockticks - pcsp_timer0_latch; } while (0)
175  #define DELTA(x,y)      ((y)-(x)+((y)<(x)?1193180L/HZ:0))
176  
177         unsigned int i, t, t1, t2, t3, tx;
178 diff -urN linux-2.4.19-clean/drivers/char/vt.c linux-2.4.19/drivers/char/vt.c
179 --- linux-2.4.19-clean/drivers/char/vt.c        Fri Nov 16 21:08:28 2001
180 +++ linux-2.4.19/drivers/char/vt.c      Sun Aug  4 03:52:27 2002
181 @@ -95,9 +95,18 @@
182      || (defined(__arm__) && defined(CONFIG_HOST_FOOTBRIDGE)) \
183      || defined(__x86_64__)
184  
185 +#if defined(CONFIG_PCSP) || defined(CONFIG_PCSP_MODULE)
186 +extern char pcsp_speaker;
187 +#endif
188 +
189  static void
190  kd_nosound(unsigned long ignored)
191  {
192 +#if defined(CONFIG_PCSP) || defined(CONFIG_PCSP_MODULE)
193 +       /* can't allow usage of counter 2 if /dev/pcsp use it */
194 +       if (pcsp_speaker)
195 +               return;
196 +#endif
197         /* disable counter 2 */
198         outb(inb_p(0x61)&0xFC, 0x61);
199         return;
200 @@ -110,6 +119,11 @@
201         unsigned int count = 0;
202         unsigned long flags;
203  
204 +#if defined(CONFIG_PCSP) || defined(CONFIG_PCSP_MODULE)
205 +       /* can't allow usage of counter 2 if /dev/pcsp use it */
206 +       if (pcsp_speaker)
207 +               return;
208 +#endif
209         if (hz > 20 && hz < 32767)
210                 count = 1193180 / hz;
211         
212 diff -urN linux-2.4.19-clean/drivers/sound/Config.in linux-2.4.19/drivers/sound/Config.in
213 --- linux-2.4.19-clean/drivers/sound/Config.in  Sun Aug  4 03:44:50 2002
214 +++ linux-2.4.19/drivers/sound/Config.in        Fri Aug 16 18:13:46 2002
215 @@ -126,6 +126,19 @@
216     bool '      Verbose initialisation' CONFIG_SOUND_TRACEINIT
217     bool '      Persistent DMA buffers' CONFIG_SOUND_DMAP
218  
219 +   if [ "$ARCH" = "i386" ]; then
220 +      dep_tristate '    Internal PC speaker support' CONFIG_PCSP $CONFIG_SOUND_OSS
221 +   fi
222 +   if [ "$CONFIG_PCSP" = "y" -o "$CONFIG_PCSP" = "m" ]; then
223 +       bool '      Use doubled modulation frequency' CONFIG_PCSP_HIGH_FRQ
224 +   fi
225 +   if [ "$CONFIG_PCSP" = "y" -o "$CONFIG_PCSP" = "m" ]; then
226 +       bool '      Disable automatic speed detection' CONFIG_PCSP_NO_TEST_SPEED
227 +       if [ "$CONFIG_PCSP_NO_TEST_SPEED" = "y" ] ; then
228 +          int '      Enter a samplerate for PCSP [12000-18356]' CONFIG_PCSP_SRATE 18356
229 +       fi
230 +   fi
231 +
232     if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
233        dep_tristate '    AD1816(A) based cards (EXPERIMENTAL)' CONFIG_SOUND_AD1816 $CONFIG_SOUND_OSS
234     fi
235 diff -urN linux-2.4.19-clean/drivers/sound/Makefile linux-2.4.19/drivers/sound/Makefile
236 --- linux-2.4.19-clean/drivers/sound/Makefile   Sun Aug  4 03:44:50 2002
237 +++ linux-2.4.19/drivers/sound/Makefile Sun Aug  4 03:52:27 2002
238 @@ -10,7 +10,7 @@
239  export-objs    :=  ad1848.o audio_syms.o midi_syms.o mpu401.o \
240                     msnd.o opl3.o sb_common.o sequencer_syms.o \
241                     sound_core.o sound_syms.o uart401.o \
242 -                   nm256_audio.o ac97.o ac97_codec.o aci.o
243 +                   nm256_audio.o ac97.o ac97_codec.o aci.o pcsp_stub.o
244  
245  # Each configuration option enables a list of files.
246  
247 @@ -71,6 +71,7 @@
248  obj-$(CONFIG_SOUND_MAESTRO)    += maestro.o
249  obj-$(CONFIG_SOUND_MAESTRO3)   += maestro3.o ac97_codec.o
250  obj-$(CONFIG_SOUND_TRIDENT)    += trident.o ac97_codec.o
251 +obj-$(CONFIG_PCSP)             += pcsnd.o
252  obj-$(CONFIG_SOUND_EMU10K1)    += ac97_codec.o
253  obj-$(CONFIG_SOUND_BCM_CS4297A)        += swarm_cs4297a.o
254  obj-$(CONFIG_SOUND_RME96XX)     += rme96xx.o
255 @@ -92,6 +93,10 @@
256    obj-y += cs4281/cs4281.o
257  endif
258  
259 +ifdef CONFIG_PCSP
260 + obj-y += pcsp_stub.o
261 +endif
262 +
263  subdir-$(CONFIG_DMASOUND) += dmasound
264  
265  ifeq ($(CONFIG_DMASOUND),y)
266 @@ -102,7 +107,7 @@
267  # Declare multi-part drivers.
268  
269  list-multi     := sound.o gus.o pas2.o sb.o sb_lib.o vidc_mod.o \
270 -    soundcore.o wavefront.o
271 +    soundcore.o wavefront.o pcsnd.o
272  
273  sound-objs     :=                                                      \
274      dev_table.o soundcard.o sound_syms.o               \
275 @@ -118,6 +123,7 @@
276  sb_lib-objs    := sb_common.o sb_audio.o sb_midi.o sb_mixer.o sb_ess.o
277  vidc_mod-objs  := vidc.o vidc_fill.o
278  wavefront-objs  := wavfront.o wf_midi.o yss225.o
279 +pcsnd-objs     := pcsp.o pcsndriv.o pcsp_mixer.o
280  
281  
282  O_TARGET       := sounddrivers.o
283 @@ -152,6 +158,9 @@
284  wavefront.o: $(wavefront-objs)
285         $(LD) -r -o $@ $(wavefront-objs)
286  
287 +pcsnd.o: $(pcsnd-objs)
288 +       $(LD) -r -o $@ $(pcsnd-objs)
289 +
290  # Firmware files that need translation
291  #
292  # The translated files are protected by a file that keeps track
293 diff -urN linux-2.4.19-clean/drivers/sound/pcsndriv.c linux-2.4.19/drivers/sound/pcsndriv.c
294 --- linux-2.4.19-clean/drivers/sound/pcsndriv.c Thu Jan  1 03:00:00 1970
295 +++ linux-2.4.19/drivers/sound/pcsndriv.c       Fri Aug 16 19:09:36 2002
296 @@ -0,0 +1,1274 @@
297 +/*
298 + * linux/drivers/sound/pcsndriv.c
299 + *
300 + * /dev/pcsp implementation
301 + *
302 + * Copyright (C) 1993-1997  Michael Beck 
303 + */
304 +
305 +#include <linux/config.h>
306 +#include <linux/soundcard.h>
307
308 +#include <linux/kernel.h>
309 +#include <linux/sched.h>
310 +#include <linux/errno.h>
311 +#include <linux/ptrace.h>
312 +#include <linux/timex.h>
313 +#include <linux/ioport.h>
314 +#include <linux/mm.h>
315 +#include <linux/slab.h>
316 +#include <linux/init.h>
317 +#include <linux/poll.h>
318 +#include <linux/wait.h>
319 +
320 +#include <asm/io.h>
321 +#include <asm/uaccess.h>
322 +#include <asm/irq.h>
323 +
324 +#ifdef MODULE
325 +#include <linux/config.h>
326 +#define __NO_VERSION__
327 +#include <linux/module.h>
328 +#else
329 +#define MOD_INC_USE_COUNT
330 +#define MOD_DEC_USE_COUNT
331 +#endif
332 +#include <linux/pcsp.h>
333 +#include "sound_config.h"
334 +
335 +/* to avoid gcc warning we define dsp_ulaw unused since it is really not used */
336 +#define dsp_ulaw __attribute__((unused)) _unused_junk
337 +#include "ulaw.h"
338 +
339 +#include "pcsp_tables.h"
340 +
341 +#ifdef CONFIG_APM_CPU_IDLE
342 +#include <linux/pm.h>
343 +static void (*saved_pm_idle)(void);
344 +#endif
345 +
346 +/*
347 + * This function will be used to generate a time delay on very fast
348 + * processors; this delay is only needed for the STO1 because it has
349 + * only one latch, so we must wait some time after we write the value
350 + * for the left channel before we can write the right one
351 + *
352 + * as long as I haven't such, it's empty :-)
353 + */
354 +
355 +//#define PCSP_DEBUG
356 +
357 +#ifndef PCSP_DEBUG
358 +#define assert(expr)
359 +#else
360 +#define assert(expr) \
361 +        if(!(expr)) { \
362 +        printk( "Assertion failed! %s, %s, %s, line=%d\n", \
363 +        #expr,__FILE__,__FUNCTION__,__LINE__); \
364 +        }
365 +#endif
366 +
367 +#define PCSP_NUM_BUFFERS (pcsp.frag_cnt ? pcsp.frag_cnt : PCSP_INIT_BUFFERS)
368 +#define PCSP_BUF_SIZE (pcsp.frag_size ? pcsp.frag_size : pcsp.ablk_size)
369 +#define PCSP_NEXT_BUF(i) ((i + 1) % PCSP_NUM_BUFFERS)
370 +#define PCSP_ULAW_XLAT(i) (pcsp.audio_fmt == AFMT_MU_LAW ? ulaw_dsp[i] : i)
371 +
372 +static volatile int pcsp_full = 0;
373 +static volatile int buf_now_written = -1;
374 +static char pcsp_active = 0;
375 +extern int pcsp_sound_dsp;
376 +
377 +#define PCSP_CPU_DELAY
378 +
379 +/* PCSP internal maximum volume, it's hardcoded */
380 +#define PCSP_MAX_VOLUME                256
381 +
382 +/* need this */
383 +#define MIN(a,b)       ( ((a) < (b)) ? (a) : (b) )
384 +
385 +/* the parallel-ports */
386 +static int pcsp_ports[]       = { 0x3bc, 0x378, 0x278 };
387 +static int pcsp_port_enable[] = { 0,     0,     0     };
388 +
389 +#define LP_NO          3
390 +#define LP_B(port)     pcsp_ports[port]        /* IO address */
391 +#define LP_S(port)     inb_p(LP_B(port) + 1)   /* status */
392 +
393 +/* general pcsp data */
394 +
395 +extern struct pcsp_status pcsp;
396 +
397 +/* Volume-tables */
398 +
399 +static unsigned char vl_tab[256];
400 +static unsigned char left_vol[256], right_vol[256];
401 +
402 +#ifdef PCSP_MIXER
403 +extern int pcsp_mixer_ioctl(int dev, unsigned int cmd, caddr_t ptr);
404 +#endif
405 +
406 +static wait_queue_head_t pcsp_sleep;
407 +
408 +extern int pcsp_set_irq(int (*func)(void));
409 +extern int pcsp_release_irq(void);
410 +static void pcsp_stop_timer(void);
411 +void pcsp_close(int dev);
412 +
413 +/* test if a parallel port is free */
414 +
415 +inline static int pcsp_free_port(int port)
416 +{
417 +       return (pcsp_port_enable[port] || !check_region(LP_B(port), 3));
418 +}
419 +
420 +static void pcsp_reserve_port(int port)
421 +{
422 +       pcsp_port_enable[port] = 1;
423 +       request_region(LP_B(port), 3, "pcsp");
424 +}
425 +
426 +void pcsp_free_ports(void)
427 +{
428 +       int port;
429 +
430 +       for (port = 0; port < LP_NO; ++port)
431 +               if (pcsp_port_enable[port])
432 +                       release_region(LP_B(port), 3);
433 +}
434 +/* test if a Stereo-on-One is on lp(port) */
435 +inline static int stereo1_detect(unsigned port)
436 +{
437 +       if (! pcsp_free_port(port))
438 +               return 0;
439 +       outb(0x7F, LP_B(port));
440 +       if (LP_S(port) & 0x80) {
441 +               outb(0x80, LP_B(port));
442 +               return (LP_S(port) & 0x80) ? 0 : 1;
443 +       }
444 +       return 0;
445 +}
446 +
447 +/* test if a new Stereo-Circuit is on lp(port) */
448 +inline static int stereo_nc_detect(unsigned port)
449 +{
450 +       if (! pcsp_free_port(port))
451 +               return 0;
452 +       outb(0, LP_B(port));
453 +       if (LP_S(port) & 0x40) {
454 +               outb(0xFF, LP_B(port));
455 +               return (LP_S(port) & 0x40) ? 0 : 1;
456 +       }
457 +       return 0;
458 +}
459 +
460 +/* search for Stereo-on-One, return it's port if found */
461 +static int stereo1_init(void)
462 +{
463 +       register int i;
464 +
465 +       for (i = 0; i < LP_NO; ++i) 
466 +               if (stereo1_detect(i)) {
467 +                       pcsp_reserve_port(i);
468 +                       pcsp.port    = LP_B(i);
469 +                       pcsp.act_dev = SNDCARD_STO1;
470 +                       return i;
471 +               }
472 +       return (-ENODEV);
473 +}
474 +
475 +/* search for Stereo-NC, return it's port if found */
476 +static int stereo_nc_init(void)
477 +{
478 +       register int i;
479 +
480 +       for (i = 0; i < LP_NO; ++i) 
481 +               if (stereo_nc_detect(i)) {
482 +                       pcsp_reserve_port(i);
483 +                       pcsp.port    = LP_B(i);
484 +                       pcsp.act_dev = SNDCARD_STNC;
485 +                       return i;
486 +               }
487 +       return (-ENODEV);
488 +}
489 +
490 +inline static int pcsp_factor(void)
491 +{
492 +int factor = 1;
493 +#ifdef PCSP_16BIT
494 +       if (pcsp.audio_fmt == AFMT_S16_LE)
495 +               factor <<= 1;
496 +       if (pcsp.stereo_emu)
497 +               factor <<= 1;
498 +#endif
499 +       return factor;
500 +}
501 +
502 +static volatile int pcsp_buf_avail(int num)
503 +{
504 +int i = PCSP_BUF_SIZE - pcsp.in[num]*pcsp_factor();
505 +
506 +       return ((i > 0) ? i : 0);
507 +}
508 +
509 +static void pcsp_reset_buffers(void)
510 +{
511 +int i;
512 +       for(i = 0; i < PCSP_NUM_BUFFERS; i++)
513 +               pcsp.in[i] = 0;
514 +       pcsp_full = 0;
515 +       pcsp.xfer     = pcsp.index = 0; 
516 +       pcsp.cur_buf  = pcsp.next_buf = 0;
517 +       pcsp.buffer   = pcsp.buf[pcsp.cur_buf];
518 +}
519 +
520 +static void pcsp_next_buffer(void)
521 +{
522 +       pcsp.xfer -= pcsp.in[pcsp.cur_buf] << 16;
523 +       assert(pcsp.xfer >= 0);
524 +       if (pcsp.xfer < 0)
525 +               pcsp.xfer = 0;
526 +       pcsp.index = pcsp.xfer >> 16;
527 +       pcsp.in[pcsp.cur_buf] = 0;
528 +       pcsp.cur_buf = PCSP_NEXT_BUF(pcsp.cur_buf);
529 +       pcsp.buffer = pcsp.buf[pcsp.cur_buf];
530 +}
531 +
532 +static int pcsp_find_free_buffer(void)
533 +{
534 +int free_buf;
535 +       if (pcsp.in[pcsp.next_buf] == 0)
536 +               return pcsp.next_buf;
537 +       if (pcsp_buf_avail(pcsp.next_buf) <= 0)
538 +               return -1;
539 +       free_buf = PCSP_NEXT_BUF(pcsp.next_buf);
540 +       if (free_buf == pcsp.cur_buf)
541 +               return -1;
542 +       assert(pcsp.in[free_buf] == 0);
543 +       pcsp.in[free_buf] = 0;
544 +       return free_buf;
545 +}
546 +
547 +static int pcsp_count_free_buffers(void)
548 +{
549 +int next_free_buf;
550 +       next_free_buf = pcsp_find_free_buffer();
551 +       if (next_free_buf < 0)
552 +               return 0;
553 +       if (next_free_buf >= pcsp.cur_buf)
554 +               return PCSP_NUM_BUFFERS - (next_free_buf - pcsp.cur_buf);
555 +       return pcsp.cur_buf - next_free_buf;
556 +}
557 +
558 +static int pcsp_count_used_bytes(void)
559 +{
560 +int i, cnt, free_buf;
561 +       free_buf = pcsp_find_free_buffer();
562 +       if (free_buf == pcsp.cur_buf)
563 +               return 0;
564 +       if (free_buf < 0)
565 +               free_buf = pcsp.cur_buf;
566 +       cnt = 0;
567 +       i = pcsp.cur_buf;
568 +       do {
569 +               cnt += pcsp.in[i];
570 +               i = PCSP_NEXT_BUF(i);
571 +       } while (i != free_buf);
572 +
573 +#if 0  /* timidity doesn't like it */
574 +       cnt -= pcsp.index;
575 +       if (cnt < 0)
576 +               cnt = 0;
577 +#endif
578 +
579 +       return (cnt * pcsp_factor());
580 +}
581 +
582 +static int pcsp_prep_buffers(int buf_size, int buf_num)
583 +{
584 +int i;
585 +//printk("PCSP: prep_buffers called, size=%i num=%i\n",buf_size, buf_num);
586 +       if (buf_size * buf_num > PCSP_TOTAL_SIZE ||
587 +           buf_size > pcsp.ablk_size || buf_size < 4 
588 +           || buf_num > PCSP_MAX_BUFFERS || buf_num < 2)
589 +               return -EINVAL;
590 +
591 +       if (pcsp.timer_on) {
592 +               pcsp_stop_timer();
593 +       }
594 +
595 +       if (pcsp.allocated) {
596 +               vfree(pcsp.data);
597 +               pcsp.allocated = 0;
598 +       }
599 +       if (! (pcsp.data = vmalloc(buf_size * buf_num)))
600 +               return -ENOMEM;
601 +       pcsp.allocated = 1;
602 +
603 +       for (i = 0; i < buf_num; i++)
604 +               pcsp.buf[i] = pcsp.data + buf_size * i;
605 +
606 +       pcsp_reset_buffers();
607 +
608 +       return 0;
609 +}
610 +
611 +/* the timer-int for playing thru PC-Speaker */
612 +static int pcsp_do_timer(void)
613 +{
614 +       if (pcsp.cur_buf == buf_now_written) {
615 +               assert(0);
616 +               pcsp_stop_timer();
617 +       }
618 +       else {
619 +               if (pcsp.index < pcsp.in[pcsp.cur_buf]) {
620 +                       outb(pcsp.e,     0x61);
621 +                       outb(pcsp.e ^ 1, 0x61);
622 +                       outb(vl_tab[pcsp.buffer[pcsp.index]], 0x42);
623 +
624 +                       assert(pcsp.si > 0);
625 +                       pcsp.xfer += pcsp.si;
626 +                       pcsp.index = pcsp.xfer >> 16;
627 +               }
628 +               if (pcsp.index >= pcsp.in[pcsp.cur_buf]) {
629 +                       pcsp_next_buffer();
630 +#if USE_OSS_FOPS
631 +                       DMAbuf_outputintr(pcsp_sound_dsp, 1);
632 +#else
633 +                       if (waitqueue_active(&pcsp_sleep)) {
634 +                               wake_up_interruptible(&pcsp_sleep);
635 +//printk("PCSP: done block, cur=%i next=%i\n",pcsp.cur_buf,pcsp.next_buf);
636 +                               pcsp_full = 0;
637 +                       }
638 +#endif
639 +                       if (pcsp.in[pcsp.cur_buf] == 0)
640 +                               pcsp_stop_timer();
641 +               }
642 +       }
643 +
644 +#if !USE_OSS_FOPS
645 +    /* workaround for missing locking */
646 +        if (waitqueue_active(&pcsp_sleep) && pcsp_full
647 +           && (pcsp.in[pcsp.next_buf] == 0)) {
648 +#if 0
649 +#ifdef PCSP_DEBUG
650 +               printk("PCSP: Force wake_up!\n");
651 +#endif
652 +#endif
653 +               wake_up_interruptible(&pcsp_sleep);
654 +               pcsp_full = 0;
655 +       }
656 +#endif
657 +       pcsp_clockticks -= pcsp_timer0_latch;
658 +       if (pcsp_clockticks < 0) {
659 +               pcsp_clockticks += LATCH;
660 +               return 0;
661 +       }
662 +       return 1;
663 +}
664 +
665 +/* timer-int for playing thru STO1 */
666 +static int pcsp_do_sto1_timer(void)
667 +{
668 +       static int ret;
669 +
670 +       if (pcsp.index < pcsp.in[pcsp.cur_buf]) {
671 +               if (pcsp.mode) {
672 +                       outb(right_vol[pcsp.buffer[pcsp.index++]], pcsp.port);
673 +                       outb(1, pcsp.port + 2);
674 +                       outb(0, pcsp.port + 2);
675 +
676 +                       /* 
677 +                        * I move the following code because 
678 +                        * I need some time delay for the left DAC
679 +                        * on my 486DX2
680 +                        * this will hopefully enough or we need some
681 +                        * really time wasting jumps here
682 +                        *
683 +                        * This time delay will really be a problem for
684 +                        * pentiums :-(
685 +                        *
686 +                        */
687 +
688 +                       pcsp_clockticks -= pcsp_timer0_latch;
689 +                       if (pcsp_clockticks < 0) {
690 +                               pcsp_clockticks += LATCH;
691 +                               ret = 0;
692 +                       }
693 +                       else
694 +                               ret = 1;
695 +
696 +                       PCSP_CPU_DELAY;
697 +
698 +                       outb(left_vol[pcsp.buffer[pcsp.index++]], pcsp.port);
699 +                       outb(2, pcsp.port + 2);
700 +                       outb(0, pcsp.port + 2);
701 +               }
702 +               else {  /* Mono */
703 +                       outb(left_vol[pcsp.buffer[pcsp.index++]], pcsp.port);
704 +                       pcsp_clockticks -= pcsp_timer0_latch;
705 +                       if (pcsp_clockticks < 0) {
706 +                               pcsp_clockticks += LATCH;
707 +                               ret = 0;
708 +                       }
709 +                       else
710 +                               ret = 1;
711 +               }
712 +       }
713 +       if (pcsp.index >= pcsp.in[pcsp.cur_buf]) {
714 +               pcsp_next_buffer();
715 +#if !USE_OSS_FOPS
716 +                if (waitqueue_active(&pcsp_sleep))
717 +                       wake_up_interruptible(&pcsp_sleep);
718 +#endif
719 +               if (pcsp.in[pcsp.cur_buf] == 0)
720 +                       pcsp_stop_timer();
721 +       }
722 +       return (ret);
723 +}
724 +
725 +/* timer-int for playing thru DACs */
726 +static int pcsp_do_dac_timer(void)
727 +{
728 +       if (pcsp.index < pcsp.in[pcsp.cur_buf]) {
729 +               if (pcsp.act_dev == SNDCARD_DACS)  {
730 +                       if (pcsp.mode) {
731 +                               outb(left_vol[pcsp.buffer[pcsp.index++]], pcsp.port);
732 +                               outb(right_vol[pcsp.buffer[pcsp.index++]], pcsp.portS);
733 +                       }
734 +                       else {
735 +                               outb(left_vol[pcsp.buffer[pcsp.index]], pcsp.port);
736 +                               outb(left_vol[pcsp.buffer[pcsp.index++]], pcsp.portS);
737 +                       }
738 +               }
739 +               else    /* Simple DAC */
740 +                       outb(left_vol[pcsp.buffer[pcsp.index++]], pcsp.port);
741 +       }
742 +       if (pcsp.index >= pcsp.in[pcsp.cur_buf]) {
743 +               pcsp_next_buffer();
744 +#if !USE_OSS_FOPS
745 +                if (waitqueue_active(&pcsp_sleep))
746 +                       wake_up_interruptible(&pcsp_sleep);
747 +#endif
748 +               if (pcsp.in[pcsp.cur_buf] == 0)
749 +                       pcsp_stop_timer();
750 +       }
751 +
752 +       pcsp_clockticks -= pcsp_timer0_latch;
753 +       if (pcsp_clockticks < 0) {
754 +               pcsp_clockticks += LATCH;
755 +               return 0;
756 +       }
757 +       return 1;
758 +}
759 +
760 +/* calculate all needed time-consts, return the 'adjusted' samplerate */
761 +static unsigned pcsp_calc_srate(unsigned rate)
762 +{
763 +       pcsp.timerC = (CLOCK_TICK_RATE + rate / 2) / rate;
764 +       pcsp.srate  = (CLOCK_TICK_RATE + pcsp.timerC / 2) / pcsp.timerC;
765 +
766 +       /* and now for the PC-Speaker */
767 +       pcsp.si     = (pcsp.srate << 16) / SRATE;
768 +       return pcsp.srate;
769 +}
770 +
771 +static void pcsp_start_timer(void)
772 +{
773 +       int result;
774 +
775 +       if (! pcsp.allocated)
776 +               return;
777 +
778 +       if (pcsp.timer_on || !(pcsp.enable_bits & PCM_ENABLE_OUTPUT)) {
779 +               return;
780 +       }
781 +
782 +       if (! pcsp.in[pcsp.cur_buf]) {
783 +               pcsp_reset_buffers();
784 +               return;
785 +       }
786 +
787 +        pcsp.buffer  = pcsp.buf[pcsp.cur_buf];
788 +
789 +       if (pcsp.act_dev == SNDCARD_PCSP) {
790 +               pcsp_speaker = 1;
791 +               pcsp.e = inb(0x61) | 0x03;
792 +               outb_p(0x92, 0x43);     /* binary, mode 1, LSB only, ch 2 */
793 +               outb_p(0x34,0x43);      /* binary, mode 2, LSB/MSB, ch 0 */
794 +               outb_p(pcsp.timerCF & 0xFF, 0x40);
795 +               outb(pcsp.timerCF >> 8 , 0x40);
796 +               if (pcsp_set_irq(pcsp_do_timer) < 0)
797 +                       panic("PCSP: could not modify timer IRQ!");
798 +               pcsp_timer0_latch = pcsp.timerCF;
799 +       }
800 +       else {  /* it's a DAC */
801 +               if (pcsp.act_dev == SNDCARD_STO1)
802 +                       outb(3,pcsp.port + 2);
803 +
804 +               /* get the timer */
805 +               outb_p(0x34,0x43);              /* binary, mode 2, LSB/MSB, ch 0 */
806 +               outb_p(pcsp.timerC & 0xFF, 0x40); 
807 +               outb(pcsp.timerC >> 8 , 0x40);  
808 +               if (pcsp.act_dev == SNDCARD_STO1) 
809 +                               result = pcsp_set_irq(pcsp_do_sto1_timer);
810 +               else
811 +                               result = pcsp_set_irq(pcsp_do_dac_timer);
812 +               if (result < 0)
813 +                       panic("PCSP: could not modify timer IRQ!");
814 +               pcsp_timer0_latch = pcsp.timerC;
815 +       }
816 +       pcsp_clockticks = pcsp.last_clocks;
817 +       pcsp.timer_on = 1;
818 +
819 +#ifdef CONFIG_APM_CPU_IDLE
820 +       saved_pm_idle = pm_idle;
821 +       pm_idle = NULL;
822 +#endif
823 +}
824 +       
825 +/* reset the timer to 100 Hz and reset old timer-int */
826 +static void pcsp_stop_timer(void)
827 +{
828 +//printk("PCSP: stop timer\n");
829 +       if (pcsp.timer_on) {
830 +               /* restore the timer */
831 +               outb_p(0x34,0x43);      /* binary, mode 2, LSB/MSB, ch 0 */
832 +               outb_p(LATCH & 0xff , 0x40);    /* LSB */
833 +               outb(LATCH >> 8 , 0x40);        /* MSB */
834 +
835 +               /* clear clock tick counter */
836 +               pcsp.last_clocks = pcsp_clockticks;
837 +               pcsp_timer0_latch = pcsp_clockticks = LATCH;    
838 +
839 +               if (pcsp_release_irq() < 0)
840 +                       panic("PCSP: could not reset timer IRQ!");
841 +
842 +               pcsp.timer_on = 0;
843 +       }
844 +
845 +       if (pcsp_active && buf_now_written != -1)
846 +               return;
847 +
848 +       /* reset the buffer */
849 +       pcsp_reset_buffers();
850 +
851 +       pcsp_speaker  = 0;
852 +
853 +       if (!pcsp_active)                       /* NONBLOCK close() */
854 +               pcsp_close(0);
855 +#ifdef CONFIG_APM_CPU_IDLE
856 +       pm_idle = saved_pm_idle;
857 +#endif
858 +}
859 +
860 +/*
861 +   calculate a translation-table for PC-Speaker
862 +*/
863 +static void pcsp_calc_vol(int volume)
864 +{
865 +short int i, j;
866 +       for (i = 0; i < 256; ++i) {
867 +               j = (((PCSP_ULAW_XLAT(i) - 128) * volume) / PCSP_MAX_VOLUME) + 128;
868 +               vl_tab[i] = sp_tabs[pcsp.gain][j];
869 +       }
870 +}
871 +
872 +/* calculate linear translation table for DACs */
873 +static void pcsp_calc_voltab(int volume, unsigned char *tab)
874 +{
875 +short int i;
876 +       for (i = 0; i < 256; ++i)
877 +               tab[i] = (((PCSP_ULAW_XLAT(i) - 128) * volume) / PCSP_MAX_VOLUME) + 128;
878 +}
879 +
880 +static inline void pcsp_set_voltables(void)
881 +{
882 +       pcsp_calc_voltab(pcsp.left, left_vol);
883 +       pcsp_calc_voltab(pcsp.right, right_vol);
884 +       pcsp_calc_vol(pcsp.volume);
885 +}
886 +
887 +#ifdef PCSP_MIXER
888 +
889 +/* this is called if /dev/pcmixer change Mastervolume */
890 +inline void pcsp_set_volume(unsigned short v, unsigned short g)
891 +{
892 +       pcsp.left   = (((unsigned)(v & 0x7F) << 8) + 50) / 100;
893 +       pcsp.right  = (((unsigned)(v & 0x7F00)) + 50) / 100;
894 +       pcsp.volume = (pcsp.right + pcsp.left) >> 1;
895 +       pcsp.gain = g & 0xff;
896 +       pcsp_set_voltables();
897 +}
898 +
899 +inline unsigned pcsp_get_mode(void)
900 +{
901 +       return pcsp.mode;
902 +}
903 +#endif
904 +
905 +/*
906 + * set the speed for /dev/pcsp, it's now from 4000 - 99225 Hz,
907 + * but DAC's are bounded by the maximal samplerate
908 + */
909 +inline unsigned long pcsp_set_speed(unsigned long speed)
910 +{
911 +       if (!speed)
912 +               return pcsp.srate;
913 +
914 +       if (speed < 4000)
915 +               speed = 4000;
916 +       if (speed > 99225)
917 +               speed = 99225;
918 +       if (pcsp.act_dev != SNDCARD_PCSP)
919 +               if (speed > pcsp.maxrate)
920 +                       speed = pcsp.maxrate;
921 +       return pcsp_calc_srate(speed);
922 +}
923 +
924 +/*
925 + * set the audio type
926 + */
927 +int pcsp_set_format(int fmt)
928 +{
929 +       if (fmt != AFMT_QUERY) {
930 +               if (! (pcsp.fmt_msk & fmt))     /* Not supported */
931 +                       fmt = AFMT_U8;          /* this is supported */
932 +               pcsp.audio_fmt = fmt;
933 +               /*
934 +                  we must recalculate the volume-tables is we change
935 +                  ulaw-state
936 +               */
937 +               pcsp_set_voltables();
938 +       }
939 +       return pcsp.audio_fmt;
940 +}
941 +
942 +/*
943 + * set the stereo mode if possible
944 + */
945 +static int pcsp_set_stereo(int flag)
946 +{
947 +       if (pcsp.act_dev == SNDCARD_STO1 ||
948 +           pcsp.act_dev == SNDCARD_DACS ) 
949 +#ifdef PCSP_16BIT
950 +               pcsp.stereo_emu = 0;
951 +       else {
952 +               pcsp.stereo_emu = flag ? 1 : 0;
953 +               /* test if the emulation is disabled */
954 +               if (! pcsp.enable_emu && pcsp.stereo_emu) {
955 +                       pcsp.stereo_emu = 0;
956 +                       pcsp.mode = 0;
957 +                       return -EINVAL;
958 +               }
959 +       }
960 +       pcsp.mode = flag ? 1 : 0;
961 +       pcsp_set_voltables();
962 +#else
963 +               pcsp.mode = flag ? 1 : 0;
964 +       else {
965 +               pcsp.mode = 0;
966 +               if (flag)
967 +                       return -EINVAL;
968 +       }
969 +#endif
970 +//printk("PCSP: stereo set to %i\n",pcsp.mode);
971 +       return pcsp.mode;
972 +}
973 +
974 +/*
975 + * wait until the complete buffers are played or a signal has arrised
976 + */
977 +static void pcsp_sync(void)
978 +{
979 +       while (! signal_pending(current) && pcsp.in[pcsp.cur_buf]) {
980 +               if (! pcsp.timer_on)
981 +                       pcsp_start_timer();
982 +               /* Wait until a complete block are ready */
983 +                interruptible_sleep_on(&pcsp_sleep);
984 +        }
985 +}
986 +
987 +/*
988 + * the driver functions
989 + */
990 +void pcsp_close(int dev)
991 +{
992 +       if (pcsp.allocated) {
993 +               vfree(pcsp.data);
994 +               pcsp.allocated = 0;
995 +       }
996 +
997 +       pcsp_active   = 0;
998 +       MOD_DEC_USE_COUNT;
999 +}
1000 +
1001 +static int pcsp_release(struct inode * inode, struct file * file)
1002 +{
1003 +       if (!(file->f_flags & O_NONBLOCK) || pcsp.in[pcsp.cur_buf] == 0) {
1004 +               pcsp_sync();
1005 +               pcsp_stop_timer(); 
1006 +               outb_p(0xb6,0x43);              /* binary, mode 2, LSB/MSB, ch 2 */
1007 +               pcsp_close(0);
1008 +       }
1009 +       else if (!pcsp.timer_on && pcsp.in[pcsp.cur_buf])
1010 +               pcsp_start_timer();
1011 +       pcsp_active = 0;
1012 +       return 0;
1013 +}
1014 +
1015 +static int pcsp_open(struct inode * inode, struct file * file)
1016 +{
1017 +       int ret, minor = MINOR(inode->i_rdev);
1018 +
1019 +       if (pcsp_active)
1020 +               return -EBUSY;
1021 +
1022 +       if (pcsp.timer_on)
1023 +               pcsp_stop_timer();
1024 +
1025 +       switch (minor & 0xf) {
1026 +       case 3:         /* DSP device /dev/dsp* */
1027 +#ifdef PCSP_16BIT
1028 +               pcsp_set_stereo(1);
1029 +               if (pcsp_set_format(AFMT_S16_LE) != AFMT_S16_LE)
1030 +#endif
1031 +                       pcsp_set_format(AFMT_U8);
1032 +               pcsp_set_speed(44100);
1033 +               break;
1034 +       case 4:         /* Sun Audio device /dev/audio* */
1035 +               pcsp_set_format(AFMT_MU_LAW);   /* input is ULAW */
1036 +               pcsp_set_stereo(0);
1037 +               pcsp_set_speed(PCSP_DEFAULT_RATE);
1038 +               break;
1039 +
1040 +       default:
1041 +               printk(KERN_WARNING "PCSP: minor %d (%d) is for unknown device\n",minor,minor& 0xf);
1042 +               return -ENODEV;
1043 +       }
1044 +
1045 +       pcsp.timer_on  =
1046 +       pcsp.frag_size =
1047 +       pcsp.frag_cnt  = 0;
1048 +       pcsp.enable_bits = PCM_ENABLE_OUTPUT;
1049 +
1050 +       if ((ret=pcsp_prep_buffers(ABLK_SIZE, PCSP_INIT_BUFFERS)) == 0) {
1051 +               pcsp_active   = 1;
1052 +               MOD_INC_USE_COUNT;
1053 +       }
1054 +
1055 +       return ret;
1056 +}
1057 +
1058 +
1059 +/*
1060 + * the new version 2 IOCTL's
1061 + */
1062 +static int pcsp_ioctl(struct inode * inode, struct file * file,
1063 +                       unsigned int cmd, unsigned long arg)
1064 +{
1065 +       int ret;
1066 +       int i, *ptr = (int *)arg;
1067 +       audio_buf_info info;
1068 +
1069 +#ifdef PCSP_MIXER
1070 +       if (((cmd >> 8) & 0xff) == 'M') /* it's a Mixer IOCTL */
1071 +               return pcsp_mixer_ioctl(0, cmd, (caddr_t)arg);
1072 +#endif
1073 +       switch (cmd) {
1074 +               case SNDCTL_DSP_SPEED:
1075 +                       if (get_user(arg, ptr))
1076 +                               return -EFAULT;
1077 +                       arg = pcsp_set_speed(arg);
1078 +                       return put_user(arg, ptr);
1079 +
1080 +               case SOUND_PCM_READ_RATE:
1081 +                       return put_user(pcsp.srate, ptr);
1082 +
1083 +               case SNDCTL_DSP_CHANNELS:  /* same as SOUND_PCM_WRITE_CHANNELS */
1084 +                       if (get_user(arg, ptr))
1085 +                               return -EFAULT;
1086 +                       if (arg < 1 || arg > 2)
1087 +                               return -EINVAL;
1088 +                       return pcsp_set_stereo(arg - 1);
1089 +
1090 +               case SNDCTL_DSP_STEREO:
1091 +                       if (get_user(arg, ptr))
1092 +                               return -EFAULT;
1093 +                       return pcsp_set_stereo(arg);
1094 +
1095 +               case SOUND_PCM_READ_CHANNELS:
1096 +                       return put_user(pcsp.mode + 1, ptr);
1097 +
1098 +               case SNDCTL_DSP_GETBLKSIZE:
1099 +                       return put_user(PCSP_BUF_SIZE, ptr);
1100 +
1101 +#if !USE_OSS_FOPS
1102 +               case SNDCTL_DSP_SYNC:   /* syncing, so speed changes work correct */
1103 +                       pcsp_sync();
1104 +                       pcsp_stop_timer();
1105 +                       return (0);
1106 +#endif
1107 +
1108 +               case SNDCTL_DSP_RESET:  /* stops output immediately */
1109 +                       pcsp_stop_timer();
1110 +                       return (0);
1111 +
1112 +               case SNDCTL_DSP_GETFMTS:
1113 +                       return put_user(pcsp.fmt_msk, ptr);
1114 +
1115 +               case SNDCTL_DSP_SETFMT:  /* same as SNDCTL_DSP_SAMPLESIZE */
1116 +                       if (get_user(arg, ptr))
1117 +                               return -EFAULT;
1118 +                       return put_user(pcsp_set_format(arg), ptr);
1119 +
1120 +               case SNDCTL_DSP_GETOSPACE:
1121 +                   info.fragments = pcsp_count_free_buffers();
1122 +                   info.fragstotal = PCSP_NUM_BUFFERS;
1123 +                   info.fragsize = PCSP_BUF_SIZE;
1124 +                   info.bytes = info.fragments * info.fragsize +
1125 +                       (pcsp.in[pcsp.next_buf] ?
1126 +                       pcsp_buf_avail(pcsp.next_buf) : 0);
1127 +                   if (copy_to_user((void *)arg, &info, sizeof(info)))
1128 +                       return -EFAULT;
1129 +                   return 0;
1130 +
1131 +               case SNDCTL_DSP_GETODELAY:
1132 +                       return put_user(pcsp_count_used_bytes(), ptr);
1133 +
1134 +               case SNDCTL_DSP_GETISPACE:
1135 +                       return (-EINVAL);
1136 +
1137 +               case SNDCTL_DSP_NONBLOCK:
1138 +#if !USE_OSS_FOPS
1139 +                       file->f_flags |= O_NONBLOCK;
1140 +#endif
1141 +                       return 0;
1142 +
1143 +               case SNDCTL_DSP_GETCAPS:
1144 +                       return put_user((DSP_CAP_REVISION & 1) |
1145 +                           DSP_CAP_BATCH/* | DSP_CAP_TRIGGER*/, ptr);
1146 +
1147 +               case SOUND_PCM_READ_BITS:
1148 +                       if (pcsp.audio_fmt == AFMT_S16_LE)
1149 +                               return put_user(16, ptr);
1150 +                       return put_user(8, ptr);
1151 +
1152 +               case SNDCTL_DSP_SUBDIVIDE:
1153 +                       /* Too late to change ? */
1154 +                       if (get_user(arg, ptr))
1155 +                               return -EFAULT;
1156 +                       if (pcsp.frag_size || pcsp.frag_cnt)
1157 +                               return -EINVAL;
1158 +                       if (arg != 1 && arg != 2 && arg != 4)
1159 +                               return -EINVAL;
1160 +                       pcsp.frag_size = ABLK_SIZE / arg;
1161 +                       pcsp.frag_cnt = PCSP_INIT_BUFFERS * arg;
1162 +                       return pcsp_prep_buffers(pcsp.frag_size, pcsp.frag_cnt);
1163 +                       
1164 +               case SNDCTL_DSP_POST:
1165 +                       if (! pcsp.timer_on)
1166 +                               pcsp_start_timer();
1167 +                       return (0);
1168 +
1169 +               case SNDCTL_DSP_SETFRAGMENT:
1170 +               {
1171 +                       int bytes, count;
1172 +                       int fact;
1173 +
1174 +                       if (get_user(fact, ptr))
1175 +                               return -EFAULT;
1176 +
1177 +                       if (! fact)
1178 +                               return -EIO;
1179 +
1180 +                       /* Too late to change ? */
1181 +                       if (pcsp.frag_size || pcsp.frag_cnt)
1182 +                               return -EINVAL;
1183 +
1184 +                       bytes = fact & 0xffff;
1185 +                       count = (fact >> 16) & 0xffff;
1186 +
1187 +                       if (bytes < 4 || bytes > 17)    /* <16 || > 128k */
1188 +                               return -EINVAL;
1189 +
1190 +                       if (count < 2)
1191 +                               count = 2;
1192 +
1193 +                       pcsp.frag_size = bytes ? (1 << bytes) : pcsp.ablk_size;
1194 +                       pcsp.frag_cnt = count;
1195 +
1196 +                       if (pcsp.frag_cnt > PCSP_MAX_BUFFERS)
1197 +                               pcsp.frag_cnt = PCSP_MAX_BUFFERS;
1198 +                       if (pcsp.frag_size > pcsp.ablk_size)
1199 +                               pcsp.frag_size = pcsp.ablk_size;
1200 +                       if (pcsp.frag_size * pcsp.frag_cnt > PCSP_TOTAL_SIZE)
1201 +                               pcsp.frag_cnt = PCSP_TOTAL_SIZE / pcsp.frag_size;
1202 +
1203 +                       if (pcsp_prep_buffers(pcsp.frag_size, pcsp.frag_cnt)<0)
1204 +                               return -EINVAL;
1205 +                       
1206 +                       return put_user(bytes | (count << 16), ptr);
1207 +               }
1208 +
1209 +               case PCSP_SET_DEV:
1210 +                        if (get_user(arg, ptr))
1211 +                               return -EFAULT;
1212 +                       switch(arg) {
1213 +                               case SNDCARD_STO1: 
1214 +                                       if (stereo1_init() < 0)
1215 +                                               return (-ENODEV);
1216 +                                       break;
1217 +                               case SNDCARD_PCSP: 
1218 +                               case SNDCARD_DACM: 
1219 +                               case SNDCARD_DACS:
1220 +                                       pcsp.act_dev = arg; break;
1221 +                               case SNDCARD_STNC: 
1222 +                                       if (stereo_nc_init() < 0)
1223 +                                               return (-ENODEV);
1224 +                                       break;
1225 +                               default:
1226 +                                       return (-ENODEV);
1227 +                       }
1228 +                       /* Perhaps we need to adjust the samplerate */
1229 +                       pcsp.srate = pcsp_set_speed(pcsp.srate);
1230 +                       return (0);
1231 +
1232 +               case PCSP_GET_DEV:
1233 +                        return put_user(pcsp.act_dev, ptr);
1234 +
1235 +               case PCSP_SET_PORTS:
1236 +                        if (get_user(arg, ptr))
1237 +                               return -EFAULT;
1238 +                       if ((arg & 0xFF) < LP_NO && (arg >> 8) < LP_NO) {
1239 +                               if (pcsp.act_dev == SNDCARD_STO1) {
1240 +                                       if (stereo1_detect(arg & 0xFF)) {
1241 +                                               pcsp.port = LP_B(arg & 0xFF);
1242 +                                               return (0);
1243 +                                       }
1244 +                               }
1245 +                               else if (pcsp.act_dev == SNDCARD_STNC) {
1246 +                                       if (stereo_nc_detect(arg & 0xFF)) {
1247 +                                               pcsp.port = LP_B(arg & 0xFF);
1248 +                                               return (0);
1249 +                                       }
1250 +                               }
1251 +                               else {
1252 +                                       pcsp.port  = LP_B(arg & 0xFF);
1253 +                                       pcsp.portS = LP_B((arg >> 8) & 0xFF);
1254 +                                       return (0);
1255 +                               }
1256 +                       }
1257 +                       return (-EINVAL);
1258 +
1259 +               case PCSP_GET_PORTS: 
1260 +                       ret = 0;
1261 +                       for (i = 0; i < LP_NO; ++i)
1262 +                               if (LP_B(i) == pcsp.port)
1263 +                                       ret = i;
1264 +                       for (i = 0; i < LP_NO; ++i)
1265 +                               if (LP_B(i) == pcsp.portS)
1266 +                                       ret |= i << 8;
1267 +                       return put_user(ret, ptr);
1268 +
1269 +                case PCSP_GET_MEASURE:
1270 +                       return put_user(pcsp.maxrate, ptr);
1271 +
1272 +               case PCSP_SET_EMU_MODE:
1273 +#ifdef PCSP_16BIT
1274 +                        if (get_user(arg, ptr))
1275 +                               return -EFAULT;
1276 +                       if (arg == PCSP_EMULATION_ON) {
1277 +                               pcsp.enable_emu = 1;
1278 +                               pcsp.fmt_msk |= AFMT_S16_LE;
1279 +                       }
1280 +                       else if (arg == PCSP_EMULATION_OFF) {
1281 +                               pcsp.enable_emu = 0;
1282 +                               pcsp.fmt_msk &= ~AFMT_S16_LE;
1283 +                       }
1284 +                       return put_user(pcsp.enable_emu, ptr);
1285 +#endif
1286 +               case PCSP_GET_VERSION:
1287 +                       return put_user(PCSP_SOUND_VERSION, ptr);
1288 +
1289 +               default :
1290 +                       return (-EINVAL);
1291 +       }
1292 +}
1293 +
1294 +static ssize_t pcsp_read(struct file * file, char * buffer,
1295 +                    size_t count, loff_t *ppos)
1296 +{
1297 +       return -EINVAL;
1298 +}
1299 +
1300 +static ssize_t pcsp_write(struct file * file, const char * buffer,
1301 +                      size_t count, loff_t *ppos)
1302 +{
1303 +int copy_size, total_bytes_written = 0;
1304 +unsigned l, r;
1305 +unsigned char *p;
1306 +int j;
1307 +
1308 +       if (! pcsp.allocated)
1309 +               return -EIO;
1310 +
1311 +       assert(pcsp.timer_on || pcsp.cur_buf == pcsp.next_buf);
1312 +       pcsp_full = 0;
1313 +       do {
1314 +               assert(count >= total_bytes_written);
1315 +               copy_size = pcsp_buf_avail(pcsp.next_buf); /* can't put it under MIN() - racey! */
1316 +               copy_size = MIN(count - total_bytes_written, copy_size);
1317 +
1318 +               if (copy_size > 0) {
1319 +                       buf_now_written = pcsp.next_buf; /* this is our lock:) */
1320 +                       pcsp_full = 0;
1321 +#ifdef PCSP_16BIT
1322 +                       p = pcsp.buf[buf_now_written] + pcsp.in[buf_now_written];
1323 +                       if (pcsp.audio_fmt == AFMT_S16_LE)
1324 +                               if (pcsp.stereo_emu) {
1325 +                                       for (j = 0; j < copy_size >> 2; ++j) {
1326 +                                               get_user(l, (unsigned char *)&buffer[4*j + 1]);
1327 +                                               get_user(r, (unsigned char *)&buffer[4*j + 3]);
1328 +                                               l ^= 0x80;
1329 +                                               r ^= 0x80;
1330 +                                               *p++ = (l + r) >> 1;
1331 +                                       }
1332 +                               }
1333 +                               else {
1334 +                                       for (j = 0; j < copy_size >> 1; ++j) {
1335 +                                               get_user(*p, &buffer[2*j + 1]);
1336 +                                               *p++ ^= 0x80;
1337 +                                       }
1338 +                               }
1339 +                       else if (pcsp.stereo_emu) {
1340 +                                       for (j = 0; j < copy_size >> 1; ++j) {
1341 +                                               get_user(l, (unsigned char *)&buffer[2*j + 0]);
1342 +                                               get_user(r, (unsigned char *)&buffer[2*j + 1]);
1343 +                                               *p++ = (l + r) >> 1;
1344 +                                       }
1345 +                               }
1346 +                       else
1347 +#endif
1348 +                               copy_from_user(p, buffer, copy_size);
1349 +                       pcsp.in[buf_now_written] += copy_size / pcsp_factor();
1350 +                       if (pcsp_buf_avail(buf_now_written) <= 0) {
1351 +                               pcsp.next_buf = PCSP_NEXT_BUF(buf_now_written);
1352 +                               assert(pcsp.next_buf == pcsp.cur_buf ||
1353 +                                   pcsp.in[pcsp.next_buf] == 0);
1354 +                       }
1355 +                       buffer += copy_size;
1356 +                       total_bytes_written += copy_size;
1357 +               }
1358 +               else if (count > total_bytes_written) {
1359 +                       buf_now_written = -1;
1360 +                       assert(! pcsp_full);
1361 +
1362 +                       if (! pcsp.timer_on)
1363 +                               pcsp_start_timer();
1364 +
1365 +#if !USE_OSS_FOPS
1366 +                       if (file->f_flags & O_NONBLOCK) {
1367 +                               return total_bytes_written ?
1368 +                                       total_bytes_written : -EAGAIN;
1369 +                       }
1370 +                       pcsp_full = 1;
1371 +                       interruptible_sleep_on(&pcsp_sleep);
1372 +                       if (signal_pending(current)) {
1373 +                               return total_bytes_written ?
1374 +                                       total_bytes_written : -EINTR;
1375 +                       }
1376 +#endif
1377 +               }
1378 +       } while (count > total_bytes_written);
1379 +
1380 +       assert(count == total_bytes_written);
1381 +
1382 +       buf_now_written = -1;
1383 +//printk("ret from write(), avail=%i\n",pcsp_buf_avail(pcsp.cur_buf));
1384 +       if (! pcsp.timer_on && pcsp_buf_avail(pcsp.cur_buf) <= 0)
1385 +               pcsp_start_timer();
1386 +
1387 +       return total_bytes_written;
1388 +}
1389 +
1390 +static unsigned int pcsp_poll(struct file *file, struct poll_table_struct *wait)
1391 +{
1392 +unsigned int mask = 0;
1393 +       poll_wait(file, &pcsp_sleep, wait);
1394 +       if ((file->f_mode & FMODE_WRITE) && (pcsp_find_free_buffer() != -1))
1395 +               mask |= POLLOUT | POLLWRNORM;
1396 +       if (file->f_mode & FMODE_READ)
1397 +               mask |= POLLERR;
1398 +       return mask;
1399 +}
1400 +
1401 +int pcsp_open1(int dev, int mode)
1402 +{
1403 +int ret;
1404 +//printk("PCSP: open1 called\n");
1405 +        if (!(mode & OPEN_WRITE))
1406 +               return -EINVAL;
1407 +       if (pcsp_active)
1408 +               return -EBUSY;
1409 +
1410 +       pcsp.timer_on  =
1411 +       pcsp.frag_size =
1412 +       pcsp.frag_cnt  = 0;
1413 +       pcsp.enable_bits = PCM_ENABLE_OUTPUT;
1414 +
1415 +       if ((ret=pcsp_prep_buffers(ABLK_SIZE, PCSP_INIT_BUFFERS)) == 0) {
1416 +               pcsp_active   = 1;
1417 +               MOD_INC_USE_COUNT;
1418 +       }
1419 +       return ret;
1420 +}
1421 +
1422 +void pcsp_halt(int dev)
1423 +{
1424 +       pcsp_stop_timer();
1425 +}
1426 +
1427 +int pcsp_speed(int dev, int speed)
1428 +{
1429 +//printk("PCSP: speed set to %i\n",speed);
1430 +       return pcsp_set_speed(speed);
1431 +}
1432 +
1433 +short pcsp_set_channels(int dev, short channels)
1434 +{
1435 +       if (!channels)
1436 +               return pcsp.mode + 1;
1437 +       return pcsp_set_stereo(channels - 1) + 1;
1438 +}
1439 +
1440 +void pcsp_output_block(int dev, unsigned long physbuf, int count, int intrflag)
1441 +{
1442 +    struct audio_operations *adev = audio_devs[dev];
1443 +    struct dma_buffparms *dmap = adev->dmap_out;
1444 +    char *dma_start =
1445 +       (char *)(physbuf - (unsigned long)dmap->raw_buf_phys 
1446 +                + (unsigned long)dmap->raw_buf);
1447 +//printk("PCSP: output_block called, cur=%i next=%i free=%i\n",
1448 +//pcsp.cur_buf,pcsp.next_buf,pcsp_find_free_buffer());
1449 +       pcsp_write(NULL, dma_start, count, NULL);
1450 +}
1451 +
1452 +int pcsp_ioctl1(int dev, unsigned int cmd, caddr_t arg)
1453 +{
1454 +//printk("PCSP: ioctl called, cmd=%i\n",cmd);
1455 +       return pcsp_ioctl(NULL, NULL, cmd, (unsigned long)arg);
1456 +}
1457 +
1458 +int pcsp_prepare_output(int dev, int size, int count)
1459 +{
1460 +//printk("PCSP: prepare_for_output called, size=%i num=%i rsize=%i rnum=%i\n",
1461 +//size, count,
1462 +//audio_devs[dev]->dmap_out->fragment_size, audio_devs[dev]->dmap_out->nbufs);
1463 +       pcsp.frag_size = size;
1464 +       pcsp.frag_cnt = count;
1465 +       audio_devs[dev]->dmap_out->flags |= DMA_NODMA;
1466 +       return pcsp_prep_buffers(size, count);
1467 +}
1468 +
1469 +unsigned int pcsp_set_bits(int dev, unsigned int bits)
1470 +{
1471 +//printk("PCSP: set_bits %i called\n", bits);
1472 +return pcsp_set_format(bits);
1473 +}
1474 +
1475 +void pcsp_set_triggers(int dev, int bits)
1476 +{
1477 +//printk("PCSP: trigger=%i\n",bits);
1478 +       pcsp.enable_bits = bits;
1479 +       if (!pcsp.timer_on && (bits & PCM_ENABLE_OUTPUT) &&
1480 +           pcsp.in[pcsp.cur_buf])
1481 +               pcsp_start_timer();
1482 +}
1483 +
1484 +struct file_operations pcsp_dsp_fops = {
1485 +       owner:          THIS_MODULE,
1486 +       read:           pcsp_read,
1487 +       write:          pcsp_write,
1488 +       poll:           pcsp_poll,
1489 +       ioctl:          pcsp_ioctl,     
1490 +       open:           pcsp_open,
1491 +       release:        pcsp_release,
1492 +};
1493 +
1494 +struct audio_driver pcsp_driver = {
1495 +       owner:                  THIS_MODULE,
1496 +       open:                   pcsp_open1,
1497 +       close:                  pcsp_close,
1498 +       output_block:           pcsp_output_block,
1499 +       ioctl:                  pcsp_ioctl1,
1500 +       prepare_for_output:     pcsp_prepare_output,
1501 +       halt_io:                pcsp_halt,
1502 +       trigger:                pcsp_set_triggers,
1503 +       set_speed:              pcsp_speed,
1504 +       set_bits:               pcsp_set_bits,
1505 +       set_channels:           pcsp_set_channels,
1506 +};
1507 +
1508 +int __init pcsp_device_init(void)
1509 +{
1510 +       int i;
1511 +       if (! pcsp_enabled)
1512 +               return 0;
1513 +
1514 +#if !USE_OSS_FOPS
1515 +        init_waitqueue_head(&pcsp_sleep);
1516 +#endif
1517 +       /* do we need a first-time initialisation? */
1518 +       if (!pcsp.first_boot)
1519 +               return 0;
1520 +
1521 +       pcsp.first_boot   = 0;
1522 +       pcsp.allocated    = 0;
1523 +       pcsp.xfer         = 0;
1524 +       pcsp_clockticks   = pcsp_timer0_latch = pcsp.last_clocks = LATCH;
1525 +       pcsp_active       = 0;
1526 +       pcsp_speaker      = 0;
1527 +       pcsp.timer_on     = 0;
1528 +       pcsp.mode         = 0;
1529 +       pcsp.audio_fmt    = AFMT_U8;
1530 +       pcsp.fmt_msk      = AFMT_QUERY | AFMT_U8 | AFMT_MU_LAW;
1531 +#ifdef PCSP_16BIT
1532 +       pcsp.fmt_msk      |= AFMT_S16_LE;
1533 +#endif
1534 +       pcsp_reset_buffers();
1535 +       pcsp.act_dev      = SNDCARD_PCSP;
1536 +       pcsp.port         = pcsp.portS = 0;
1537 +       pcsp.left         = (PCSP_LEFT_VOL  * 256 + 50) / 100;
1538 +       pcsp.right        = (PCSP_RIGHT_VOL * 256 + 50) / 100;
1539 +       pcsp.volume       = (pcsp.left + pcsp.right) >> 1;
1540 +       pcsp.gain         = PCSP_GAIN * PCSP_MAX_GAIN / 100;
1541 +       pcsp.ablk_size    = ABLK_SIZE;
1542 +       pcsp.frag_size    = 0;
1543 +       pcsp.frag_cnt     = 0;
1544 +       pcsp_set_speed(PCSP_DEFAULT_RATE);
1545 +       pcsp_calc_vol(pcsp.volume);
1546 +       pcsp_calc_voltab(PCSP_LEFT_VOL,  left_vol);
1547 +       pcsp_calc_voltab(PCSP_RIGHT_VOL, right_vol);
1548 +#ifdef PCSP_16BIT
1549 +       pcsp.stereo_emu   = 0;
1550 +       pcsp.enable_emu   = 1;
1551 +#endif
1552 +#ifndef MODULE
1553 +       printk(" PC-Speaker");
1554 +#endif
1555 +       i = stereo1_init();
1556 +       if (i >= 0) {
1557 +#ifndef MODULE
1558 +                       printk(", Stereo-on-One at lpt%d", i);
1559 +#endif
1560 +                       pcsp.ablk_size = 2 * ABLK_SIZE;
1561 +       }
1562 +       i = stereo_nc_init();
1563 +       if (i >= 0) {
1564 +#ifndef MODULE
1565 +                       printk(", New Stereo Circuit at lpt%d", i);
1566 +#endif
1567 +                       pcsp.ablk_size = 2 * ABLK_SIZE;
1568 +       }
1569 +       return 0;
1570 +}
1571 diff -urN linux-2.4.19-clean/drivers/sound/pcsp.c linux-2.4.19/drivers/sound/pcsp.c
1572 --- linux-2.4.19-clean/drivers/sound/pcsp.c     Thu Jan  1 03:00:00 1970
1573 +++ linux-2.4.19/drivers/sound/pcsp.c   Tue Aug 13 00:19:22 2002
1574 @@ -0,0 +1,105 @@
1575 +/*
1576 + * linux/drivers/sound/pcsp.c
1577 + *
1578 + * /dev/pcsp implementation
1579 + *
1580 + * Copyright (C) 1993-1997  Michael Beck 
1581 + */
1582 +
1583 +#include <linux/config.h>
1584 +
1585 +#include <linux/errno.h>
1586 +#include <linux/init.h>
1587 +
1588 +#ifdef MODULE
1589 +#include <linux/module.h>
1590 +
1591 +MODULE_AUTHOR("Michael Beck <beck@DResearch.de>");
1592 +MODULE_DESCRIPTION("PC-Speaker Driver for Linux 2.4.x Version 1.4");
1593 +MODULE_SUPPORTED_DEVICE("pcsp");
1594 +EXPORT_NO_SYMBOLS;
1595 +#endif
1596 +#include <linux/pcsp.h>
1597 +#include "sound_config.h"
1598 +
1599 +extern struct file_operations pcsp_dsp_fops;
1600 +extern struct audio_driver pcsp_driver;
1601 +extern struct mixer_operations pcsp_mixer_ops;
1602 +extern long pcsp_driver_init(long);
1603 +extern int pcsp_set_format(int);
1604 +extern void pcsp_free_ports(void);
1605 +
1606 +
1607 +int pcsp_sound_dsp, pcsp_sound_mixer;
1608 +
1609 +int pcsp_register_driver(void)
1610 +{
1611 +       if ((pcsp_sound_dsp = sound_install_audiodrv(
1612 +           AUDIO_DRIVER_VERSION,
1613 +           "PC-Speaker",
1614 +           &pcsp_driver,
1615 +           sizeof(pcsp_driver),
1616 +           DMA_NODMA,
1617 +           AFMT_U8 | AFMT_MU_LAW
1618 +#ifdef PCSP_16BIT
1619 +           | AFMT_S16_LE
1620 +#endif
1621 +           ,NULL, -1, -1)) < 0) {
1622 +               printk(KERN_WARNING "Unable to install PC speaker driver\n");
1623 +               return 0;
1624 +       }
1625 +#if !USE_OSS_FOPS
1626 +       unregister_sound_dsp((pcsp_sound_dsp<<4)+3);
1627 +       if (register_sound_dsp(&pcsp_dsp_fops, pcsp_sound_dsp) < 0) {
1628 +               printk(KERN_ERR "Oops, unable to register PC speaker DSP device!\n");
1629 +               return 0;
1630 +       }
1631 +#endif
1632 +//     printk("PCSP on device %d\n",pcsp_sound_dsp);
1633 +
1634 +#if defined(PCSP_16BIT) || defined(PCSP_MIXER)
1635 +       if ((pcsp_sound_mixer = sound_install_mixer (
1636 +           MIXER_DRIVER_VERSION,
1637 +           "PC-Speaker",
1638 +           &pcsp_mixer_ops,
1639 +           sizeof(pcsp_mixer_ops),
1640 +           NULL)) < 0) {
1641 +               printk(KERN_WARNING "Unable to register PC speaker mixer device\n");
1642 +               sound_unload_audiodev(pcsp_sound_dsp);
1643 +               return 0;
1644 +       }
1645 +//     printk("PCSP mixer on device %d\n", pcsp_sound_mixer);
1646 +#endif
1647 +       return 1;
1648 +}
1649 +
1650 +#ifdef MODULE
1651 +
1652 +int __init init_module(void)
1653 +{
1654 +        if (! pcsp_enabled) {
1655 +                printk("pcsp disabled\n");
1656 +                return -ENODEV;
1657 +        }
1658 +       
1659 +       if (! pcsp_register_driver())
1660 +               return -EIO;
1661 +
1662 +       pcsp_device_init();
1663 +#ifdef PCSP_MIXER
1664 +       pcsp_mixer_init();
1665 +#endif
1666 +       return 0;
1667 +}
1668 +
1669 +void cleanup_module(void)
1670 +{
1671 +       if (MOD_IN_USE)
1672 +               printk("pcsnd: busy - remove delayed\n");
1673 +       else {
1674 +               pcsp_free_ports();
1675 +               sound_unload_audiodev(pcsp_sound_dsp);
1676 +               sound_unload_mixerdev(pcsp_sound_mixer);
1677 +       }
1678 +}
1679 +#endif
1680 diff -urN linux-2.4.19-clean/drivers/sound/pcsp_mixer.c linux-2.4.19/drivers/sound/pcsp_mixer.c
1681 --- linux-2.4.19-clean/drivers/sound/pcsp_mixer.c       Thu Jan  1 03:00:00 1970
1682 +++ linux-2.4.19/drivers/sound/pcsp_mixer.c     Mon Aug 12 22:29:50 2002
1683 @@ -0,0 +1,143 @@
1684 +/*
1685 + * linux/drivers/sound/pcsp_mixer.c
1686 + * 
1687 + * /dev/pcsp implementation - simple Mixer routines
1688 + * 
1689 + * (C) 1993-1997  Michael Beck
1690 + * Craig Metz (cmetz@thor.tjhsst.edu)
1691 + */
1692 +
1693 +#include <linux/config.h>
1694 +
1695 +#include <linux/errno.h>
1696 +
1697 +#ifdef MODULE
1698 +#define __NO_VERSION__
1699 +#include <linux/module.h>
1700 +#include <linux/version.h>
1701 +#else
1702 +#define MOD_INC_USE_COUNT
1703 +#define MOD_DEC_USE_COUNT
1704 +#endif
1705 +#include <linux/pcsp.h>
1706 +#include "sound_config.h"
1707 +#include "pcsp_tables.h"
1708 +
1709 +#if defined(PCSP_16BIT) || defined(PCSP_MIXER)
1710 +
1711 +#define IOCTL_OUT(arg, ret)             (put_user(ret, (int *)arg))
1712 +#define OFF                            0
1713 +
1714 +#define SUPPORTED_MIXER_DEVICES                (SOUND_MASK_VOLUME | SOUND_MASK_OGAIN)
1715 +
1716 +static unsigned short levels[SOUND_MIXER_NRDEVICES] =
1717 +{
1718 +       PCSP_LEFT_VOL | (PCSP_RIGHT_VOL << 8),          /* Master Volume */
1719 +       /* The next devices are not supported, so they are zero */
1720 +       0,                              /* Bass */
1721 +       0,                              /* Treble */
1722 +       0,                              /* FM */
1723 +       0,                              /* PCM */
1724 +       0,                              /* PC Speaker */
1725 +       0,                              /* Ext Line */
1726 +       0,                              /* Mic */
1727 +       0,                              /* CD */
1728 +       0,                              /* Recording monitor */
1729 +       0,                              /* SB PCM */
1730 +       0,                              /* Recording level */
1731 +       0,                              /* Input gain */
1732 +       PCSP_GAIN | (PCSP_GAIN << 8)            /* Output gain */
1733 +};
1734 +
1735 +extern void pcsp_set_volume(unsigned short, unsigned);
1736 +extern unsigned pcsp_get_mode(void);
1737 +
1738 +int pcsp_mixer_ioctl(int dev, unsigned int cmd, caddr_t ptr)
1739 +{
1740 +       int val, left, right;
1741 +
1742 +       if (((cmd >> 8) & 0xff) == 'M') {
1743 +               if (cmd & IOC_IN) {
1744 +                       if (get_user(val, (int *)ptr))
1745 +                               return -EINVAL;
1746 +
1747 +                       left = val & 0x7f;
1748 +                       right = (val & 0x7f00) >> 8;
1749 +
1750 +                       if (left > 100)
1751 +                               left = 100;
1752 +                       if (right > 100)
1753 +                               right = 100;
1754 +
1755 +                       switch (cmd & 0xff) {
1756 +                               case SOUND_MIXER_VOLUME:        /* Master volume (0-127) */
1757 +                                       levels[SOUND_MIXER_VOLUME] = left | (right << 8);
1758 +                                       break;
1759 +
1760 +                               case SOUND_MIXER_OGAIN:
1761 +                                       right = left;
1762 +                                       left = (left * PCSP_MAX_GAIN / 100) * 100 / PCSP_MAX_GAIN;
1763 +                                       if ((levels[SOUND_MIXER_OGAIN] & 0xff) < right) {
1764 +                                               levels[SOUND_MIXER_OGAIN] = left | (left << 8);
1765 +                                               if (right > left)
1766 +                                                       levels[SOUND_MIXER_OGAIN] +=
1767 +                                                           (100 / PCSP_MAX_GAIN) | ((100 / PCSP_MAX_GAIN) << 8);
1768 +                                       }
1769 +                                       else if ((levels[SOUND_MIXER_OGAIN] & 0xff) > right) {
1770 +                                               levels[SOUND_MIXER_OGAIN] = left | (left << 8);
1771 +                                       }
1772 +                                       break;
1773 +
1774 +                               default:
1775 +                                       return (-EINVAL); 
1776 +                       }
1777 +
1778 +                       pcsp_set_volume(levels[SOUND_MIXER_VOLUME],
1779 +                                       (levels[SOUND_MIXER_OGAIN] & 0xff) * PCSP_MAX_GAIN / 100);
1780 +
1781 +                       return IOCTL_OUT(ptr, val);
1782 +               }
1783 +               
1784 +               switch (cmd & 0xff) {
1785 +                       
1786 +               case SOUND_MIXER_RECSRC:
1787 +                       return IOCTL_OUT(ptr, OFF);
1788 +                       
1789 +               case SOUND_MIXER_STEREODEVS:
1790 +                       return IOCTL_OUT(ptr, SUPPORTED_MIXER_DEVICES & ~(SOUND_MASK_OGAIN));
1791 +                       
1792 +               case SOUND_MIXER_DEVMASK:
1793 +                       return IOCTL_OUT(ptr, SUPPORTED_MIXER_DEVICES);
1794 +                       
1795 +               case SOUND_MIXER_RECMASK:
1796 +                       return IOCTL_OUT(ptr, OFF);
1797 +                       
1798 +               case SOUND_MIXER_CAPS:
1799 +                       return IOCTL_OUT(ptr, 0);
1800 +                       
1801 +               default:
1802 +                       if ((cmd & 0xff) < SOUND_MIXER_NRDEVICES)
1803 +                               return IOCTL_OUT(ptr, levels[cmd & 0xff]);
1804 +                       else
1805 +                               return (-EINVAL);
1806 +               }
1807 +       }
1808 +
1809 +       return (-EINVAL);
1810 +}
1811 +
1812 +struct mixer_operations pcsp_mixer_ops = {
1813 +       owner:                  THIS_MODULE,
1814 +       id:                     "PC-Speaker",
1815 +       name:                   "PCSP Mixer",
1816 +        ioctl:                 pcsp_mixer_ioctl
1817 +};
1818 +
1819 +int pcsp_mixer_init(void)
1820 +{
1821 +       pcsp_set_volume(levels[SOUND_MIXER_VOLUME],
1822 +               (levels[SOUND_MIXER_OGAIN] & 0xff) * PCSP_MAX_GAIN / 100);
1823 +       return 0;
1824 +}
1825 +
1826 +#endif
1827 diff -urN linux-2.4.19-clean/drivers/sound/pcsp_stub.c linux-2.4.19/drivers/sound/pcsp_stub.c
1828 --- linux-2.4.19-clean/drivers/sound/pcsp_stub.c        Thu Jan  1 03:00:00 1970
1829 +++ linux-2.4.19/drivers/sound/pcsp_stub.c      Fri Aug 16 19:10:55 2002
1830 @@ -0,0 +1,389 @@
1831 +/*
1832 + * linux/drivers/sound/pcsp_stub.c
1833 + *
1834 + * /dev/pcsp implementation
1835 + *
1836 + * Copyright (C) 1993-1997  Michael Beck 
1837 + *
1838 + * if PCSP is compiled as a module, this part must
1839 + * be linked with the kernel
1840 + */
1841 +
1842 +#include <linux/config.h>
1843 +#include <linux/module.h>
1844 +#include <linux/fs.h>
1845 +#include <linux/init.h>
1846 +#include <linux/errno.h>
1847 +#include <linux/timex.h>
1848 +#include <linux/interrupt.h>
1849 +#include <linux/random.h>
1850 +#include <linux/smp.h>
1851 +#include <linux/irq.h>
1852 +#ifndef CONFIG_PCSP_MODULE
1853 +#include <linux/sound.h>
1854 +#endif
1855 +
1856 +#include <asm/io.h>
1857 +#include <asm/system.h>
1858 +#include <linux/pcsp.h>
1859 +#include "sound_config.h"
1860 +
1861 +/*
1862 + * need this macros
1863 + */
1864 +#define MIN(a,b)        ( ((a) < (b)) ? (a) : (b) )
1865 +#define MAX(a,b)        ( ((a) > (b)) ? (a) : (b) )
1866 +
1867 +/* the maximal samplerange for PC-Speaker: 18357 Hz */
1868 +#ifndef CONFIG_PCSP_HIGH_FRQ
1869 +#define MIN_CONST      65
1870 +#else
1871 +#define MIN_CONST      33
1872 +#endif
1873 +
1874 +#define MAX_SRATE      (CLOCK_TICK_RATE / MIN_CONST)
1875 +
1876 +
1877 +/*
1878 + * need this to be global
1879 + */
1880 +char pcsp_speaker = 0;
1881 +char pcsp_enabled = -1;
1882 +volatile int pcsp_timer0_latch, pcsp_clockticks;
1883 +volatile int pcsp_test_running;
1884 +
1885 +struct pcsp_status pcsp;
1886 +
1887 +static void *sleep = NULL;
1888 +static int (*pcsp_IRQ)(void) = NULL;
1889 +static struct irqaction pcsp_action, *pcsp_old_action = NULL;
1890 +
1891 +/*
1892 + * this is the PCSP IRQ handler
1893 + */
1894 +asmlinkage void pcsp_run_IRQ(int irq, void *dev_id, struct pt_regs *regs)
1895 +{
1896 +       struct irqaction * action;
1897 +       int status;
1898 +
1899 +       status = pcsp_IRQ();
1900 +       if (! status) {
1901 +               /* Return with this interrupt masked if no action */
1902 +               action = pcsp_old_action;
1903 +               if (action) {
1904 +                       do {
1905 +                               status |= action->flags;
1906 +                               action->handler(irq, action->dev_id, regs);
1907 +                               action = action->next;
1908 +                       } while (action);
1909 +                       if (status & SA_SAMPLE_RANDOM)
1910 +                               add_interrupt_randomness(irq);
1911 +               }
1912 +       }
1913 +}
1914 +
1915 +/*
1916 + * Set the function func to be executed as the timer int.
1917 + * if func returns a 0, the old IRQ0-handler(s) is called
1918 + */
1919 +int pcsp_set_irq(int (*func)(void))
1920 +{
1921 +       unsigned long flags;
1922 +       struct irqaction * action = irq_desc[0].action;
1923 +
1924 +       pcsp_IRQ = func;
1925 +       if (! pcsp_IRQ || ! action)
1926 +               return -EINVAL;
1927 +
1928 +       /* fill in the action */
1929 +       pcsp_action.handler = pcsp_run_IRQ;
1930 +       pcsp_action.flags   = 0;        /* Do NOT allow other IRQ-handlers */
1931 +       pcsp_action.mask    = 0;
1932 +       pcsp_action.name    = "pcsp+timer";
1933 +       pcsp_action.next    = NULL;
1934 +       pcsp_action.dev_id  = NULL;
1935 +
1936 +       /* ok, change the handler */
1937 +       save_flags(flags);
1938 +       cli();
1939 +       irq_desc[0].action = &pcsp_action;
1940 +       restore_flags(flags);
1941 +       pcsp_old_action = action;
1942 +       return 0;
1943 +}
1944 +
1945 +/*
1946 + * reset the IRQ0 to the old handling
1947 + */
1948 +int pcsp_release_irq(void)
1949 +{
1950 +       unsigned long flags;
1951 +
1952 +       save_flags(flags);
1953 +       cli();
1954 +       irq_desc[0].action = pcsp_old_action;
1955 +       restore_flags(flags);
1956 +       pcsp_IRQ = NULL;
1957 +       return 0;
1958 +}
1959 +
1960 +#ifndef CONFIG_PCSP_NO_TEST_SPEED
1961 +/*
1962 +   this is a stupid beep which occurs if PCSP is disabled;
1963 +   it's not needed because we have the message, but who reads it...
1964 +   and this is the PC-Speaker driver :-)
1965 +*/
1966 +void __init pcsp_beep(int count, int cycles)
1967 +{
1968 +       /* enable counter 2 */
1969 +       outb_p(inb_p(0x61)|3, 0x61);
1970 +       /* set command for counter 2, 2 byte write */
1971 +       outb_p(0xB6, 0x43);
1972 +       /* select desired HZ */
1973 +       outb_p(count & 0xff, 0x42);
1974 +       outb((count >> 8) & 0xff, 0x42);
1975 +
1976 +       while (cycles--);
1977 +                
1978 +       /* disable counter 2 */
1979 +       outb(inb_p(0x61)&0xFC, 0x61);
1980 +}
1981 +
1982 +/*
1983 +   the timer-int for testing cpu-speed, mostly the same as
1984 +   for PC-Speaker
1985 + */
1986 +static int __init pcsp_test_intspeed(void)
1987 +{
1988 +       if (pcsp.index < pcsp.in[pcsp.cur_buf]) {
1989 +               outb(pcsp.e,     0x61);
1990 +               outb(pcsp.e ^ 1, 0x61);
1991 +               outb(pcsp.buffer[pcsp.index], 0x42);
1992 +
1993 +               pcsp.xfer += pcsp.si;
1994 +               pcsp.index = pcsp.xfer >> 16;
1995 +       }
1996 +       if (pcsp.index >= pcsp.in[pcsp.cur_buf]) {
1997 +               pcsp.xfer = pcsp.index = 0;
1998 +               pcsp.in[pcsp.cur_buf] = 0;
1999 +               pcsp.cur_buf ^= 1;
2000 +               pcsp.buffer = pcsp.buf[pcsp.cur_buf];
2001 +                if (sleep)     /* NEVER */
2002 +                       nop();
2003 +               if (pcsp.in[pcsp.cur_buf] == 0xFFFF)
2004 +                       pcsp.cur_buf ^= 1;
2005 +       }
2006 +
2007 +       ++pcsp_test_running;
2008 +       return 1;
2009 +}
2010 +
2011 +/*
2012 +   this routine measures the time needed for one timer-int if
2013 +   we play thru PC-Speaker. This is kind of ugly but does the
2014 +   trick.
2015 + */
2016 +static int __init pcsp_measurement(unsigned char *buf, int addon)
2017 +{
2018 +       int count;
2019 +       unsigned long flags;
2020 +
2021 +       pcsp.timerCF      = LATCH;
2022 +       pcsp.buf[0]       =
2023 +       pcsp.buffer       = buf;
2024 +       pcsp.index        = 0;
2025 +       pcsp.xfer         = 0;
2026 +       pcsp.si           = 1 << 16;
2027 +       pcsp.in[0]        = 5 + addon;
2028 +       pcsp.in[1]        = 0;
2029 +       pcsp.cur_buf       = 0;
2030 +       pcsp.e            = inb(0x61) & 0xFC;
2031 +
2032 +       pcsp_test_running = 0;
2033 +
2034 +       if (pcsp_set_irq(pcsp_test_intspeed) < 0)
2035 +               panic("PCSP could not modify timer IRQ!");
2036 +
2037 +       /*
2038 +          Currently (0.99.15d) Linux call chr_dev_init with ints
2039 +          disabled; so we need a sti() to enable them.
2040 +          However, because this can be changed in the future we use
2041 +          save_flags() and restore_flags()
2042 +       */
2043 +       save_flags(flags);
2044 +       sti();
2045 +
2046 +       /*
2047 +         Perhaps we need some sort of timeout here, but if IRQ0
2048 +         isn't working the system hangs later ...
2049 +       */
2050 +       while (pcsp_test_running < 5);
2051 +       restore_flags(flags);
2052 +
2053 +       if (pcsp_release_irq() < 0)
2054 +               panic("PCSP could not reset timer IRQ!");
2055 +
2056 +       outb_p(0x00, 0x43);             /* latch the count ASAP */
2057 +       count = inb_p(0x40);            /* read the latched count */
2058 +       count |= inb(0x40) << 8;
2059 +       return (LATCH - count);
2060 +}
2061 +
2062 +static int __init pcsp_test_speed(void)
2063 +{
2064 +       int worst, worst1, best, best1;
2065 +       unsigned char test_buffer[256];
2066 +
2067 +       worst  = pcsp_measurement(test_buffer, 0);
2068 +       worst1 = pcsp_measurement(test_buffer, 0);
2069 +       best   = pcsp_measurement(test_buffer, 5);
2070 +       best1  = pcsp_measurement(test_buffer, 5);
2071 +
2072 +       worst = MAX(worst, worst1);
2073 +       best  = MIN(best, best1);
2074 +
2075 +#ifdef PCSP_DEBUG
2076 +       printk("  PCSP-Timerint needs %d Ticks in worst case\n", worst);
2077 +       printk("  PCSP-Timerint needs %d Ticks in best case\n", best);
2078 +#endif
2079 +       /* We allow a CPU-usage of 90 % for the best-case ! */
2080 +       pcsp.timerCF = best * 10 / 9;
2081 +       pcsp.maxrate  = CLOCK_TICK_RATE / pcsp.timerCF;
2082 +       printk(" maximal samplerate %d Hz", pcsp.maxrate);
2083 +
2084 +       if (pcsp.maxrate > PCSP_CRITICAL_FREQ) {
2085 +               if (MIN_CONST > pcsp.timerCF) {
2086 +                       pcsp.timerCF = MIN_CONST;
2087 +                       printk(", %d Hz", MAX_SRATE);
2088 +               }
2089 +               printk(" used\n");
2090 +               return 1;
2091 +       }
2092 +
2093 +       printk("\n  This is too SLOW! PCSP-driver DISABLED\n");
2094 +
2095 +       /* very ugly beep, but you hopefully never hear it */
2096 +       pcsp_beep(12000,800000);
2097 +       pcsp_beep(10000,800000);
2098 +       
2099 +       return 0;
2100 +}
2101 +#endif
2102 +
2103 +void __init pcsp_setup(char *s, int *p)
2104 +{
2105 +       if (!strcmp(s, "off")) {
2106 +               pcsp_enabled = 0;
2107 +               return;
2108 +       }
2109 +       if (p[0] > 0 && p[1] > 0)
2110 +               pcsp.maxrate = p[1];
2111 +       pcsp_enabled = 1;
2112 +}
2113 +
2114 +/*
2115 + * initialise the driver by testing the CPU speed and setting
2116 + * the time constants
2117 + */
2118 +void __init pcsp_driver_init(void)
2119 +{ 
2120 +int tmp;
2121 +       if (pcsp_enabled < 0) {
2122 +#ifndef CONFIG_PCSP_NO_TEST_SPEED
2123 +               pcsp_enabled = pcsp_test_speed();
2124 +#else
2125 +               pcsp.maxrate  = 44100;  /* only a BIG freq */
2126 +               pcsp.timerCF = (CLOCK_TICK_RATE + CONFIG_PCSP_SRATE / 2) /
2127 +                               CONFIG_PCSP_SRATE;
2128 +               pcsp_enabled  = 1;
2129 +#endif
2130 +       }
2131 +       else {
2132 +               tmp = MIN(pcsp.maxrate, MAX_SRATE);
2133 +               pcsp.timerCF = (CLOCK_TICK_RATE + tmp / 2) / tmp;
2134 +       }
2135 +}
2136 +
2137 +/*
2138 + * define the PCSP exports:
2139 + * when PCSP is compiled in, only the timer latch must be exported,
2140 + * else we need some help for the PCSP module from this stub
2141 + */
2142 +EXPORT_SYMBOL(pcsp_timer0_latch);
2143 +EXPORT_SYMBOL(pcsp_clockticks);
2144 +
2145 +#ifdef CONFIG_PCSP_MODULE
2146 +EXPORT_SYMBOL(pcsp_enabled);
2147 +EXPORT_SYMBOL(pcsp_speaker);
2148 +EXPORT_SYMBOL(pcsp);
2149 +EXPORT_SYMBOL(pcsp_set_irq);
2150 +EXPORT_SYMBOL(pcsp_release_irq);
2151 +#endif
2152 +
2153 +/*
2154 + * the pcsp_init() function is called in chrdev_init at kernel startup
2155 + */
2156 +#ifndef CONFIG_PCSP_MODULE
2157 +int __init pcsp_init(void)
2158 +{
2159 +       extern int pcsp_sound_dsp;
2160 +#if defined(PCSP_16BIT) || defined(PCSP_MIXER)
2161 +       extern int pcsp_sound_mixer;
2162 +#endif
2163 +       int minor, major;
2164 +
2165 +       /* if disabled in commandline */
2166 +       if (! pcsp_enabled) {
2167 +               printk("PCSP-device disabled\n");
2168 +               return 0;
2169 +       }
2170 +
2171 +       /* first time pcsp is loaded */
2172 +       pcsp.first_boot = 1;
2173 +       
2174 +       if (! pcsp_register_driver())
2175 +               return 0;
2176 +       
2177 +       major = (PCSP_SOUND_VERSION >> 8);
2178 +       minor = (PCSP_SOUND_VERSION & 0xFF);
2179 +       if (! (minor & 0xF))
2180 +               minor >>= 4;
2181 +       printk("PCSP %d.%x measurement:", major, minor);
2182 +       pcsp_driver_init();
2183 +       if (pcsp_enabled) {
2184 +               printk("PCSP %d.%x:", major, minor);
2185 +               pcsp_device_init();
2186 +               printk(" DSP installed on device %d",pcsp_sound_dsp);
2187 +#if defined(PCSP_16BIT) || defined(PCSP_MIXER)
2188 +               pcsp_mixer_init();
2189 +               printk(", Mixer installed on device %d", pcsp_sound_mixer);
2190 +#endif
2191 +               printk("\n");
2192 +       }
2193 +       return 0;
2194 +}
2195 +
2196 +#else
2197 +
2198 +/*
2199 + * this pcsp_init() function is called when the driver itself is 
2200 + * compiled as a module once at kernel-startup
2201 + */
2202 +int __init pcsp_init(void)
2203 +{
2204 +       int minor, major;
2205 +
2206 +       /* first time pcsp is loaded */
2207 +       pcsp.first_boot = 1;
2208 +
2209 +       major = (PCSP_SOUND_VERSION >> 8);
2210 +       minor = (PCSP_SOUND_VERSION & 0xFF);
2211 +       if (! (minor & 0xF))
2212 +               minor >>= 4;
2213 +       printk("PCSP %d.%x measurement:", major, minor);
2214 +       pcsp_driver_init();
2215 +       return 0;
2216 +}
2217 +#endif
2218 +
2219 +module_init(pcsp_init);
2220 diff -urN linux-2.4.19-clean/drivers/sound/pcsp_tables.h linux-2.4.19/drivers/sound/pcsp_tables.h
2221 --- linux-2.4.19-clean/drivers/sound/pcsp_tables.h      Thu Jan  1 03:00:00 1970
2222 +++ linux-2.4.19/drivers/sound/pcsp_tables.h    Fri Aug 16 18:32:01 2002
2223 @@ -0,0 +1,256 @@
2224 +/*
2225 + * linux/drivers/sound/pcsp_tables.h
2226 + *
2227 + * /dev/pcsp implementation
2228 + *
2229 + * Copyright (C) 2002 Stas Sergeev
2230 + */
2231 +
2232 +static unsigned char sp_tabs[][256] = {
2233 +#ifndef CONFIG_PCSP_HIGH_FRQ
2234 +{      /* linear */
2235 +64, 64, 64, 63, 63, 63, 63, 62, 62, 62, 62, 61, 61, 61, 61, 60, 
2236 +60, 60, 60, 59, 59, 59, 59, 58, 58, 58, 58, 57, 57, 57, 57, 56, 
2237 +56, 56, 56, 55, 55, 55, 55, 54, 54, 54, 54, 53, 53, 53, 53, 52, 
2238 +52, 52, 52, 51, 51, 51, 51, 50, 50, 50, 50, 49, 49, 49, 49, 48, 
2239 +48, 48, 48, 47, 47, 47, 47, 46, 46, 46, 46, 45, 45, 45, 45, 44, 
2240 +44, 44, 44, 43, 43, 43, 43, 43, 42, 42, 42, 42, 41, 41, 41, 41, 
2241 +40, 40, 40, 40, 39, 39, 39, 39, 38, 38, 38, 38, 37, 37, 37, 37, 
2242 +36, 36, 36, 36, 35, 35, 35, 35, 34, 34, 34, 34, 33, 33, 33, 33, 
2243 +32, 32, 32, 32, 31, 31, 31, 31, 30, 30, 30, 30, 29, 29, 29, 29, 
2244 +28, 28, 28, 28, 27, 27, 27, 27, 26, 26, 26, 26, 25, 25, 25, 25, 
2245 +24, 24, 24, 24, 23, 23, 23, 23, 22, 22, 22, 22, 22, 21, 21, 21, 
2246 +21, 20, 20, 20, 20, 19, 19, 19, 19, 18, 18, 18, 18, 17, 17, 17, 
2247 +17, 16, 16, 16, 16, 15, 15, 15, 15, 14, 14, 14, 14, 13, 13, 13, 
2248 +13, 12, 12, 12, 12, 11, 11, 11, 11, 10, 10, 10, 10,  9,  9,  9, 
2249 + 9,  8,  8,  8,  8,  7,  7,  7,  7,  6,  6,  6,  6,  5,  5,  5, 
2250 + 5,  4,  4,  4,  4,  3,  3,  3,  3,  2,  2,  2,  2,  1,  1,  1
2251 +},
2252 +{      /* amp 1 */
2253 +64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 63, 
2254 +63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 62, 62, 62, 62, 62, 62, 
2255 +62, 61, 61, 61, 61, 61, 61, 60, 60, 60, 60, 60, 59, 59, 59, 59, 
2256 +59, 58, 58, 58, 58, 58, 57, 57, 57, 57, 56, 56, 56, 56, 55, 55, 
2257 +55, 54, 54, 54, 54, 53, 53, 53, 52, 52, 52, 51, 51, 51, 51, 50, 
2258 +50, 50, 49, 49, 49, 48, 48, 48, 47, 47, 47, 46, 46, 45, 45, 45, 
2259 +44, 44, 44, 43, 43, 43, 42, 42, 41, 41, 41, 40, 40, 40, 39, 39, 
2260 +38, 38, 38, 37, 37, 37, 36, 36, 35, 35, 35, 34, 34, 33, 33, 33, 
2261 +32, 32, 32, 31, 31, 30, 30, 30, 29, 29, 28, 28, 28, 27, 27, 27, 
2262 +26, 26, 25, 25, 25, 24, 24, 24, 23, 23, 22, 22, 22, 21, 21, 21, 
2263 +20, 20, 20, 19, 19, 18, 18, 18, 17, 17, 17, 16, 16, 16, 15, 15, 
2264 +15, 14, 14, 14, 14, 13, 13, 13, 12, 12, 12, 11, 11, 11, 11, 10, 
2265 +10, 10,  9,  9,  9,  9,  8,  8,  8,  8,  7,  7,  7,  7,  7,  6, 
2266 + 6,  6,  6,  6,  5,  5,  5,  5,  5,  4,  4,  4,  4,  4,  4,  3, 
2267 + 3,  3,  3,  3,  3,  3,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 
2268 + 2,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1
2269 +},
2270 +{      /* amp 2 */
2271 +64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 
2272 +64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 
2273 +64, 64, 64, 64, 64, 64, 64, 64, 63, 63, 63, 63, 63, 63, 63, 63, 
2274 +63, 63, 63, 63, 62, 62, 62, 62, 62, 62, 62, 62, 61, 61, 61, 61, 
2275 +61, 60, 60, 60, 60, 60, 59, 59, 59, 59, 58, 58, 58, 57, 57, 57, 
2276 +57, 56, 56, 56, 55, 55, 54, 54, 54, 53, 53, 52, 52, 52, 51, 51, 
2277 +50, 50, 49, 49, 48, 48, 47, 47, 46, 46, 45, 45, 44, 43, 43, 42, 
2278 +42, 41, 41, 40, 39, 39, 38, 38, 37, 36, 36, 35, 35, 34, 33, 33, 
2279 +32, 32, 31, 30, 30, 29, 29, 28, 27, 27, 26, 26, 25, 24, 24, 23, 
2280 +23, 22, 22, 21, 20, 20, 19, 19, 18, 18, 17, 17, 16, 16, 15, 15, 
2281 +14, 14, 13, 13, 13, 12, 12, 11, 11, 11, 10, 10,  9,  9,  9,  8, 
2282 + 8,  8,  8,  7,  7,  7,  6,  6,  6,  6,  5,  5,  5,  5,  5,  4, 
2283 + 4,  4,  4,  4,  3,  3,  3,  3,  3,  3,  3,  3,  2,  2,  2,  2, 
2284 + 2,  2,  2,  2,  2,  2,  2,  2,  1,  1,  1,  1,  1,  1,  1,  1, 
2285 + 1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1, 
2286 + 1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1
2287 +},
2288 +{      /* amp 3 */
2289 +64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 
2290 +64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 
2291 +64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 
2292 +64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 
2293 +64, 64, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 62, 62, 62, 62, 
2294 +62, 62, 61, 61, 61, 61, 60, 60, 60, 60, 59, 59, 58, 58, 58, 57, 
2295 +57, 56, 56, 55, 55, 54, 54, 53, 52, 52, 51, 50, 50, 49, 48, 47, 
2296 +47, 46, 45, 44, 43, 42, 41, 40, 40, 39, 38, 37, 36, 35, 34, 33, 
2297 +32, 31, 30, 29, 28, 27, 26, 25, 25, 24, 23, 22, 21, 20, 19, 18, 
2298 +18, 17, 16, 15, 15, 14, 13, 13, 12, 11, 11, 10, 10,  9,  9,  8, 
2299 + 8,  7,  7,  7,  6,  6,  5,  5,  5,  5,  4,  4,  4,  4,  3,  3, 
2300 + 3,  3,  3,  3,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  1,  1, 
2301 + 1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1, 
2302 + 1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1, 
2303 + 1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1, 
2304 + 1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1
2305 +},
2306 +{      /* amp 4 */
2307 +64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 
2308 +64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 
2309 +64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 
2310 +64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 
2311 +64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 
2312 +64, 64, 64, 64, 64, 64, 64, 63, 63, 63, 63, 63, 63, 63, 62, 62, 
2313 +62, 62, 61, 61, 61, 60, 60, 59, 59, 58, 58, 57, 56, 55, 55, 54, 
2314 +53, 52, 51, 50, 48, 47, 46, 45, 43, 42, 41, 39, 38, 36, 35, 33, 
2315 +32, 30, 29, 27, 26, 24, 23, 22, 20, 19, 18, 17, 15, 14, 13, 12, 
2316 +11, 10, 10,  9,  8,  7,  7,  6,  6,  5,  5,  4,  4,  4,  3,  3, 
2317 + 3,  3,  2,  2,  2,  2,  2,  2,  2,  1,  1,  1,  1,  1,  1,  1, 
2318 + 1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1, 
2319 + 1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1, 
2320 + 1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1, 
2321 + 1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1, 
2322 + 1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1
2323 +}
2324 +#else
2325 +{      /* linear */
2326 +32, 32, 32, 32, 32, 31, 31, 31, 31, 31, 31, 31, 31, 30, 30, 30, 
2327 +30, 30, 30, 30, 30, 29, 29, 29, 29, 29, 29, 29, 29, 28, 28, 28, 
2328 +28, 28, 28, 28, 28, 28, 27, 27, 27, 27, 27, 27, 27, 27, 26, 26, 
2329 +26, 26, 26, 26, 26, 26, 25, 25, 25, 25, 25, 25, 25, 25, 24, 24, 
2330 +24, 24, 24, 24, 24, 24, 23, 23, 23, 23, 23, 23, 23, 23, 23, 22, 
2331 +22, 22, 22, 22, 22, 22, 22, 21, 21, 21, 21, 21, 21, 21, 21, 20, 
2332 +20, 20, 20, 20, 20, 20, 20, 19, 19, 19, 19, 19, 19, 19, 19, 19, 
2333 +18, 18, 18, 18, 18, 18, 18, 18, 17, 17, 17, 17, 17, 17, 17, 17, 
2334 +16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 15, 15, 
2335 +14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 
2336 +13, 12, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 
2337 +11, 10, 10, 10, 10, 10, 10, 10, 10, 10,  9,  9,  9,  9,  9,  9, 
2338 + 9,  9,  8,  8,  8,  8,  8,  8,  8,  8,  7,  7,  7,  7,  7,  7, 
2339 + 7,  7,  6,  6,  6,  6,  6,  6,  6,  6,  5,  5,  5,  5,  5,  5, 
2340 + 5,  5,  5,  4,  4,  4,  4,  4,  4,  4,  4,  3,  3,  3,  3,  3, 
2341 + 3,  3,  3,  2,  2,  2,  2,  2,  2,  2,  2,  1,  1,  1,  1,  1
2342 +},
2343 +{      /* amp 1 */
2344 +32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 
2345 +32, 32, 32, 32, 32, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 
2346 +31, 31, 31, 31, 31, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 29, 
2347 +29, 29, 29, 29, 29, 29, 29, 29, 28, 28, 28, 28, 28, 28, 28, 28, 
2348 +27, 27, 27, 27, 27, 27, 27, 26, 26, 26, 26, 26, 26, 26, 25, 25, 
2349 +25, 25, 25, 25, 24, 24, 24, 24, 24, 24, 23, 23, 23, 23, 23, 23, 
2350 +22, 22, 22, 22, 22, 21, 21, 21, 21, 21, 21, 20, 20, 20, 20, 20, 
2351 +19, 19, 19, 19, 19, 18, 18, 18, 18, 18, 18, 17, 17, 17, 17, 17, 
2352 +16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 
2353 +13, 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 
2354 +10, 10, 10, 10, 10, 10,  9,  9,  9,  9,  9,  9,  8,  8,  8,  8, 
2355 + 8,  8,  7,  7,  7,  7,  7,  7,  7,  6,  6,  6,  6,  6,  6,  6, 
2356 + 5,  5,  5,  5,  5,  5,  5,  5,  4,  4,  4,  4,  4,  4,  4,  4, 
2357 + 4,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  2,  2,  2,  2,  2, 
2358 + 2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  1,  1,  1,  1,  1, 
2359 + 1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1
2360 +},
2361 +{      /* amp 2 */
2362 +32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 
2363 +32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 
2364 +32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 31, 
2365 +31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 30, 
2366 +30, 30, 30, 30, 30, 30, 30, 30, 29, 29, 29, 29, 29, 29, 29, 28, 
2367 +28, 28, 28, 28, 28, 27, 27, 27, 27, 27, 26, 26, 26, 26, 26, 25, 
2368 +25, 25, 25, 24, 24, 24, 24, 23, 23, 23, 23, 22, 22, 22, 22, 21, 
2369 +21, 21, 20, 20, 20, 20, 19, 19, 19, 18, 18, 18, 18, 17, 17, 17, 
2370 +16, 16, 16, 15, 15, 15, 15, 14, 14, 14, 13, 13, 13, 13, 12, 12, 
2371 +12, 11, 11, 11, 11, 10, 10, 10, 10,  9,  9,  9,  9,  8,  8,  8, 
2372 + 8,  7,  7,  7,  7,  7,  6,  6,  6,  6,  6,  5,  5,  5,  5,  5, 
2373 + 5,  4,  4,  4,  4,  4,  4,  4,  3,  3,  3,  3,  3,  3,  3,  3, 
2374 + 3,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 
2375 + 2,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1, 
2376 + 1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1, 
2377 + 1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1
2378 +},
2379 +{      /* amp 3 */
2380 +32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 
2381 +32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 
2382 +32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 
2383 +32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 
2384 +32, 32, 32, 32, 32, 32, 32, 32, 31, 31, 31, 31, 31, 31, 31, 31, 
2385 +31, 31, 31, 31, 31, 30, 30, 30, 30, 30, 30, 29, 29, 29, 29, 29, 
2386 +28, 28, 28, 28, 27, 27, 27, 27, 26, 26, 26, 25, 25, 25, 24, 24, 
2387 +23, 23, 23, 22, 22, 21, 21, 20, 20, 20, 19, 19, 18, 18, 17, 17, 
2388 +16, 16, 15, 15, 14, 14, 13, 13, 13, 12, 12, 11, 11, 10, 10, 10, 
2389 + 9,  9,  8,  8,  8,  7,  7,  7,  6,  6,  6,  6,  5,  5,  5,  5, 
2390 + 4,  4,  4,  4,  4,  3,  3,  3,  3,  3,  3,  2,  2,  2,  2,  2, 
2391 + 2,  2,  2,  2,  2,  2,  2,  2,  1,  1,  1,  1,  1,  1,  1,  1, 
2392 + 1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1, 
2393 + 1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1, 
2394 + 1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1, 
2395 + 1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1
2396 +},
2397 +{      /* amp 4 */
2398 +32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 
2399 +32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 
2400 +32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 
2401 +32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 
2402 +32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 
2403 +32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 31, 31, 31, 31, 31, 
2404 +31, 31, 31, 31, 30, 30, 30, 30, 29, 29, 29, 29, 28, 28, 27, 27, 
2405 +26, 26, 25, 25, 24, 24, 23, 23, 22, 21, 20, 20, 19, 18, 18, 17, 
2406 +16, 15, 15, 14, 13, 13, 12, 11, 10, 10,  9,  9,  8,  8,  7,  7, 
2407 + 6,  6,  5,  5,  4,  4,  4,  4,  3,  3,  3,  3,  2,  2,  2,  2, 
2408 + 2,  2,  2,  2,  2,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1, 
2409 + 1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1, 
2410 + 1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1, 
2411 + 1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1, 
2412 + 1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1, 
2413 + 1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1
2414 +},
2415 +{
2416 +32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 
2417 +32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 
2418 +32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 
2419 +32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 
2420 +32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 
2421 +32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 
2422 +32, 32, 32, 32, 32, 32, 32, 32, 31, 31, 31, 31, 31, 31, 30, 30, 
2423 +30, 29, 29, 28, 28, 27, 26, 25, 25, 24, 23, 22, 20, 19, 18, 17, 
2424 +16, 15, 14, 13, 11, 10,  9,  8,  8,  7,  6,  5,  5,  4,  4,  3, 
2425 + 3,  3,  2,  2,  2,  2,  2,  2,  1,  1,  1,  1,  1,  1,  1,  1, 
2426 + 1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1, 
2427 + 1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1, 
2428 + 1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1, 
2429 + 1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1, 
2430 + 1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1, 
2431 + 1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1
2432 +}
2433 +#endif
2434 +};
2435 +
2436 +#define PCSP_MAX_GAIN (sizeof(sp_tabs)/sizeof(sp_tabs[0]) - 1)
2437 +
2438 +/*
2439 + * The tables were generated with this small program:
2440 +
2441 +#define _GNU_SOURCE
2442 +
2443 +#include <stdio.h>
2444 +#include <stdlib.h>
2445 +#include <math.h>
2446 +
2447 +#define MAX_VAL 64
2448 +#define MIN_VAL 1
2449 +
2450 +double sine(double i) {
2451 +  return ((sin(((i * M_PI) / 255) - M_PI_2) + 1) / 2) * 255;
2452 +}
2453 +
2454 +int fit(double x) {
2455 +  return lrint((x / 255) * (MAX_VAL - MIN_VAL) + MIN_VAL);
2456 +}
2457 +
2458 +int main(int argc, char *argv[]) {
2459 +int i, j, val, amp;
2460 +double tmp;
2461 +  if (argc==2)
2462 +    amp=atoi(argv[1]);
2463 +  else
2464 +    amp=0;
2465 +  for(i=1;i<=256;i++) {
2466 +    tmp = (double)(256-i);
2467 +    for (j=0;j<amp;j++)
2468 +      tmp = sine(tmp);
2469 +    val = fit(tmp);
2470 +    printf("%2i", val);
2471 +    if (i<256)
2472 +      printf(", ");
2473 +    if (i%16 == 0)
2474 +      printf("\n");
2475 +  }
2476 +  return 0;
2477 +}
2478 +
2479 + */
2480 diff -urN linux-2.4.19-clean/include/linux/pcsp.h linux-2.4.19/include/linux/pcsp.h
2481 --- linux-2.4.19-clean/include/linux/pcsp.h     Thu Jan  1 03:00:00 1970
2482 +++ linux-2.4.19/include/linux/pcsp.h   Fri Aug 16 19:16:21 2002
2483 @@ -0,0 +1,152 @@
2484 +#ifndef _LINUX_PCSP_H
2485 +#define _LINUX_PCSP_H
2486 +/*
2487 + * include/linux/pcsp.h
2488 + *
2489 + * /dev/pcsp implementation (dsp & audio for PC Speaker)
2490 + *
2491 + * Copyright (C) 1993-1997  Michael Beck
2492 + */
2493 +
2494 +#if defined (CONFIG_PCSP) || defined (CONFIG_PCSP_MODULE)
2495 +
2496 +#include <linux/ioctl.h>
2497 +
2498 +/* MUST BE defined from 0.5 */
2499 +#define PCSP_SOUND_VERSION     0x104           /* read 1.04 */
2500 +
2501 +/* card ID, real soundcards use 0 to ... */
2502 +
2503 +#define SNDCARD_PCSP   128
2504 +#define SNDCARD_STO1   129
2505 +#define SNDCARD_DACM   130
2506 +#define SNDCARD_DACS   131
2507 +#define SNDCARD_STNC   132
2508 +
2509 +
2510 +/* IOCTL for changing the play-device, real sample rate etc. */
2511 +
2512 +#define PCSP_SET_DEV                                   0x00014350
2513 +#define PCSP_GET_DEV                                   0x00024350
2514 +#define PCSP_SET_PORTS                                 0x00034350
2515 +#define PCSP_GET_PORTS                                 0x00044350
2516 +#if 0
2517 +#define PCSP_SET_VOL                                   0x00054350
2518 +#define PCSP_GET_VOL                                   0x00064350
2519 +#endif
2520 +#define PCSP_SET_SRATE                                 0x00074350
2521 +#define PCSP_GET_SRATE                                 0x00084350
2522 +#define PCSP_GET_MEASURE                               0x00094350
2523 +#define PCSP_SET_EMU_MODE                              0x000A4350
2524 +#define PCSP_GET_VERSION                               0x000F4350
2525 +
2526 +#define PCSP_EMULATION_OFF     0
2527 +#define PCSP_EMULATION_ON      1
2528 +#define PCSP_EMULATION_QUERY   2
2529 +
2530 +
2531
2532 +#if defined(MODULE) || defined(__KERNEL__)
2533 +
2534 +/*
2535 + * If defined, pcsp will use an OSS fops rather than its native fops.
2536 + * It is more safe to use OSS fops, but using native fops will produce
2537 + * a better sound.
2538 + * WARNING: currently pcsp have some problems working with OSS fops.
2539 + * If you know how to fix it, please send me patches.
2540 + */
2541 +#define USE_OSS_FOPS 0
2542 +#define PCSP_16BIT 1
2543 +#define PCSP_MIXER 1
2544 +#define PCSP_LEFT_VOL 100
2545 +#define PCSP_RIGHT_VOL 100
2546 +#define PCSP_GAIN 100
2547 +
2548 +/* the timer stuff */
2549 +#define TIMER_IRQ 0
2550 +#define SRATE          (CLOCK_TICK_RATE / pcsp.timerCF)
2551 +
2552 +/*
2553 + * the default blocksize for playing thru
2554 + * PC-Speaker, STO1 and STNC use twice as much
2555 + */
2556 +
2557 +#define ABLK_SIZE              16384
2558 +#define PCSP_MAX_BUFFERS       512
2559 +#define PCSP_TOTAL_SIZE                262144
2560 +#define PCSP_INIT_BUFFERS      (PCSP_TOTAL_SIZE / ABLK_SIZE)
2561 +
2562 +/* the default samplerate for /dev/audio */
2563 +#ifndef PCSP_DEFAULT_RATE
2564 +#define PCSP_DEFAULT_RATE      8000
2565 +#endif
2566 +
2567 +#ifndef PCSP_MIXER
2568 +#define PCSP_DEFAULT_LEFT      100
2569 +#define PCSP_DEFAULT_RIGHT     100
2570 +#endif
2571 +
2572 +/*
2573 + * the "critical" frequency: if the machine is too slow for this, PCSP
2574 + * is disabled
2575 + */
2576 +#ifndef PCSP_CRITICAL_FREQ
2577 +#define PCSP_CRITICAL_FREQ      12500
2578 +#endif
2579 +
2580 +struct pcsp_status {
2581 +       volatile int    last_clocks;
2582 +       int             allocated;      /* memory allocated successfully */
2583 +       unsigned char   *data;          /* one large buffer */
2584 +       unsigned char   *buf[PCSP_MAX_BUFFERS]; /* fragments */
2585 +       unsigned char   *buffer;        /* current fragment */
2586 +       volatile long long      in[PCSP_MAX_BUFFERS];   /* fragments fill */
2587 +       volatile long long      xfer;
2588 +       volatile long long      index;  /* current playing position */
2589 +       unsigned        enable_bits;    /* for triggers */
2590 +       unsigned        volume;         /* volume for pc-speaker */
2591 +       unsigned        left;           /* left volume */
2592 +       unsigned        right;          /* right volume */
2593 +       unsigned        gain;           /* output gain */
2594 +       unsigned        srate;          /* sample rate */
2595 +       unsigned        si;             /* precalculated step const */
2596 +       unsigned        timerC;         /* hardware timer ticks for srate */
2597 +       unsigned        timerCF;        /* for fixed samplerate */
2598 +       unsigned        act_dev;        /* which device is playing */
2599 +       unsigned        port;           /* on which lp-port */
2600 +       unsigned        portS;          /* for Stereo */
2601 +       volatile unsigned       cur_buf;        /* fragment currently playing */
2602 +       volatile unsigned       next_buf;       /* next fragment to fill */
2603 +       unsigned        maxrate;        /* maximum real sample rate */
2604 +       unsigned        audio_fmt;      /* 16 or 8 bit */
2605 +       unsigned        fmt_msk;        /* supported data formats */
2606 +       unsigned        ablk_size;      /* length of one audio-buffer */
2607 +       unsigned        frag_size;      /* length of one audio-fragment */
2608 +       unsigned        frag_cnt;       /* number of fragments */
2609 +       unsigned char   e;
2610 +       volatile char   timer_on;
2611 +       char            mode;           /* Mono / Stereo */
2612 +       char            stereo_emu;     /* set if Stereo is emulated */
2613 +       char            enable_emu;     /* set if the emulation is enabled */
2614 +       char            first_boot;     /* first time loaded? */
2615 +};
2616 +
2617 +/*
2618 + * the globals
2619 + */
2620 +extern char pcsp_speaker, pcsp_enabled;
2621 +extern volatile int pcsp_timer0_latch, pcsp_clockticks;
2622 +extern struct pcsp_status pcsp;
2623 +
2624 +/* in arch/i386/kernel/irq.c */
2625 +extern int pcsp_set_irq(int (*func)(void));
2626 +extern int pcsp_release_irq(void);
2627 +
2628 +/* in pcsndrv.c and pcsp_mixer.c */
2629 +extern int pcsp_register_driver(void);
2630 +extern int pcsp_device_init(void);
2631 +extern int pcsp_mixer_init(void);
2632 +
2633 +#endif
2634 +#endif
2635 +#endif
This page took 2.474563 seconds and 3 git commands to generate.