diff -uNr linux-1.0.9/drivers/sound/.blurb linux/drivers/sound/.blurb --- linux-1.0.9/drivers/sound/.blurb Sun Dec 12 20:33:48 1993 +++ linux/drivers/sound/.blurb Mon Apr 1 17:39:34 2002 @@ -5,7 +5,7 @@ recompiled. Most of them will not work without some source modifications. - ******** LINUX VERSION 0.99.14 OR LATER IS REQUIRED ******* + ******** LINUX VERSION 1.0 OR LATER IS REQUIRED ******* See sound/Readme for more details diff -uNr linux-1.0.9/drivers/sound/CHANGELOG linux/drivers/sound/CHANGELOG --- linux-1.0.9/drivers/sound/CHANGELOG Fri Jan 21 14:59:46 1994 +++ linux/drivers/sound/CHANGELOG Mon Apr 1 17:39:34 2002 @@ -1,6 +1,26 @@ -Changelog for version 2.4 +Changelog for version 2.5 ------------------------- +Since 2.5-beta2 +- Some fine tuning to the GUS v3.7 mixer code. +- Fixed speed limits for the plain SB (1.0 to 2.0). + +Since 2.5-beta +- Fixed OPL-3 detection with SB. Caused problems with PAS16. +- GUS v3.7 mixer support. + +Since 2.4 +- Mixer support for Sound Galaxy NX Pro (define __SGNXPRO__ on your local.h). +- Fixed truncated sound on /dev/dsp when the device is closed. +- Linear volume mode for GUS +- Pitch bends larger than +/- 2 octaves. +- MIDI recording for SB and SB Pro. (Untested). +- Some other fixes. +- SB16 MIDI and DSP drivers only initialized if SB16 actually installed. +- Implemented better detection for OPL-3. This should be usefull if you + have an old SB Pro (the non-OPL-3 one) or a SB 2.0 clone which has a OPL-3. +- SVR4.2 support by Ian Hartas. Initial ALPHA TEST version (untested). + Since 2.3b - Fixed bug which made it impossible to make long recordings to disk. Recording was not restarted after a buffer overflow situation. diff -uNr linux-1.0.9/drivers/sound/Makefile linux/drivers/sound/Makefile --- linux-1.0.9/drivers/sound/Makefile Fri Jan 21 14:59:46 1994 +++ linux/drivers/sound/Makefile Mon Apr 1 17:39:42 2002 @@ -5,7 +5,7 @@ # # -VERSION = 2.4 +VERSION = 2.5 TARGET_OS = linux .c.s: @@ -19,14 +19,14 @@ opl3.o sequencer.o midibuf.o sb_card.o pas2_card.o adlib_card.o \ pas2_pcm.o pas2_mixer.o pas2_midi.o gus_card.o gus_wave.o mpu401.o \ gus_midi.o gus_vol.o patmgr.o sb_mixer.o sb16_dsp.o sb_midi.o \ - sb16_midi.o sound_switch.o + sb16_midi.o sound_switch.o ics2101.o all: local.h sound.a -/usr/include/sys/soundcard.h: - @echo "WARNING! Your /usr/include/sys/soundcard.h not found." - @echo "Please make a new /usr/include/sys/soundcard.h containing" - @echo "just a line #include " +os.h: + @$(MAKE) setup-$(TARGET_OS) + @$(MAKE) config + @$(MAKE) dep sound.a: $(OBJS) -rm -f sound.a @@ -35,7 +35,7 @@ clean: rm -f core core.* *.o *.a tmp_make *~ x z *% - rm -f configure sound_stub.c + rm -f configure Makefile sound_stub.c for i in *.c;do rm -f `basename $$i .c`.s;done indent: @@ -43,11 +43,15 @@ local.h: $(MAKE) clean + $(MAKE) setup-$(TARGET_OS) $(MAKE) config $(MAKE) dep -config: configure /usr/include/sys/soundcard.h - @echo Compiling Sound Driver v $(VERSION) for Linux +soundcard.c: $(TARGET_OS)/soundcard.c + ln -sf $(TARGET_OS)/soundcard.c soundcard.c + +config: configure + @$(MAKE) setup-$(TARGET_OS) @./configure > local.h @echo \#define SOUND_VERSION_STRING \"$(VERSION)\" >> local.h @echo \#define SOUND_CONFIG_DATE \"`date`\" >> local.h @@ -56,16 +60,20 @@ @echo \#define SOUND_CONFIG_DOMAIN \"`domainname`\" >> local.h clrconf: - rm -f local.h .depend + rm -f local.h .depend os.h soundcard.c -configure: configure.c /usr/include/sys/soundcard.h +configure: configure.c $(HOSTCC) -o configure configure.c @cat .blurb dep: - $(MAKE) /usr/include/sys/soundcard.h $(CPP) -M *.c > .depend +setup-linux: + @echo Compiling Sound Driver v $(VERSION) for Linux + @ln -sf linux/soundcard.c soundcard.c + @ln -sf linux/os.h os.h + # # include a dependency file if one exists # diff -uNr linux-1.0.9/drivers/sound/Readme linux/drivers/sound/Readme --- linux-1.0.9/drivers/sound/Readme Fri Jan 21 14:59:47 1994 +++ linux/drivers/sound/Readme Mon Apr 1 17:39:34 2002 @@ -1,5 +1,15 @@ -Release notes for the Linux Sound Driver 2.4 +Release notes for the Linux Sound Driver 2.5 -------------------------------------------- +There is also a version called 2.5-beta floating around the net. This +version contains some fixes after it. Mainly to the SB and GUS code. + +CAUTION! The SVR4.2 port has not been tested much. Backup your system + carefully before trying it. + +This is mainly a bug fix release. There are couple of new things such as +linear volume mode for GUS and MIDI recording for SB 2.0 and SB Pro. +Also this version supports the mixer of GUS v3.7. (Support for GUS MAX and +the 16-bit daughtercard is coming sooner or later). NOTE! The sound driver is a part of the Linux kernel distribution also. Check that your kernel doesn't have more recent version than this @@ -17,17 +27,13 @@ No support for the ASP chip yet (the ASP chip can be installed but it's not used by the driver). -You will need the snd-util-2.4.tar.gz and snd-data-0.1.tar.Z +You will need the snd-util-2.5.tar.gz and snd-data-0.1.tar.Z packages to use this driver. They should be in the same ftp site or BBS from where you got this driver. For example at nic.funet.fi:pub/OS/Linux/*. -There is a new version of the tracker program available (tracker-3_19.lzh) but -I don't know where it is available. The tracker 3.10 has bugs and it don't work -without some fixes. Look at the README of the snd-util-2.3. - If you are looking for the installation instructions, please -look at linux/Readme. +look at $OS/Readme. This version supports the following soundcards: GUS, SoundBlaster, SB Pro, SB16, Pro Audio Spectrum 16 and AdLib. @@ -220,21 +226,28 @@ persons have given usefull suggestions. The following is a list of major contributors. (I could have forgotten some names.) - Craig Metz 1/2 of the PAS16 Mixer and PCM support - Rob Hooft Volume computation algorithm for the FM synth. - Mika Liljeberg uLaw encoding and decoding routines - Greg Lee Volume computation algorithm for the GUS and - lot's of valuable suggestions. - Andy Warner ISC port - Jim Lowe FreeBSD port + Craig Metz 1/2 of the PAS16 Mixer and PCM support + Rob Hooft Volume computation algorithm for the FM synth. + Mika Liljeberg uLaw encoding and decoding routines + Greg Lee Volume computation algorithm for the GUS and + lot's of valuable suggestions. + Andy Warner Initial ISC port + Jim Lowe Initial FreeBSD port Anders Baekgaard Bughunting and valuable suggestions. - Joerg Schubert SB16 DSP support. - Andrew Robinson Improvements to the GUS driver + Joerg Schubert SB16 DSP support. + Andrew Robinson Improvements to the GUS driver + Megens SA MIDI recording for SB and SB Pro. + Mikael Nordqvist Linear volume support for GUS. + Ian Hartas SVR4.2 port + Markus Aroharju and + Risto Kankkunen Major contributions to the mixer support + of GUS v3.7. + Hunyue Yau Sound Galaxy NX Pro mixer support. Regards, Hannu Savolainen -hsavolai@cs.helsinki.fi +hannu@voxware.pp.fi, Hannu.Savolainen@Helsinki.fi Snail mail: Hannu Savolainen Pallaksentie 4 A 2 diff -uNr linux-1.0.9/drivers/sound/Readme.linux linux/drivers/sound/Readme.linux --- linux-1.0.9/drivers/sound/Readme.linux Fri Jan 21 14:59:47 1994 +++ linux/drivers/sound/Readme.linux Thu Jan 1 01:00:00 1970 @@ -1,253 +0,0 @@ -Sound Driver version 2.4 for Linux ----------------------------------- - -NOTE! The sound driver is now a part of the Linux kernel distribution. - Check that your kernel doesn't have more recent version than this - when installing a separately distributed sound driver. The - version number of this driver is defined in the makefile. - -Installation ------------- - -- Since this driver is a part of the Linux kernel distribution, no - special steps are required to build the driver itself. - -- In case you are installing a separately distributed sound driver, - you have to do some additional steps. - - Remove all files from the linux/drivers/sound. Old files could - sometimes cause trouble. - - cd linux/drivers. - - gunzip -c snd-driv-X.Y.tar.gz|tar xvf - - - cd ./sound - - cp soundcard.h ultrasound.h /usr/include/linux - -- To build the device files for this driver, you need to run the enclosed - shell script (at the end of this file). - -- Create /usr/include/sys/soundcard.h whic contains just a line: -#include - -- Create /usr/include/sys/ultrasound.h whic contains just a line: -#include - -Boot time configuration (using lilo) ------------------------------------- - -This version of the sound driver has capability to accept the configuration -parameters from the boot loader (for example lilo). By default the -driver is booted using the parameters given before compiling the driver -('make config' or 'make soundconf'). If the kernel is booted using lilo and -the boot command is given manually, it's possible to give the configuration -parameters on the command line. Just hold down the key when lilo -starts. Then give the boot command manually and append a sound= argument -to the boot command line. For example: - -lilo boot: linux sound=0x222071,0x138800 - -The sound= argument could contain several configuration entries separated by a -comma. Each option gives the configuration for one sound device. -Give the options in the order given below. Other order of use is undefined. -Each option is encoded as the following: - - 0xTaaaId, where - || || - || |+---- d = DMA channel (0, 1, 3, 5, 6 or 7) - || +----- I = IRQ (HEXADECIMAL!!! 1=1, ..., 9=9, 10=a, ..., 15=f) - |+-------- aaa = I/O address (hexadecimal) - +---------- T = device type 1=FM Synth (YM3812 or OPL3) - 2=SoundBlaster (1.0 to 2.0, Pro, 16) - 3=ProAudioSpectrum16 - 4=Gravis UltraSound - 5=MPU-401 UART midi - 6=SB16 (16 bit DMA number) - 7=SB16 Midi (MPU-401 emulation) - -These are the configuration templates for various soundcards: - - 0) Disable the sound driver - - sound=0 - - 1) AdLib - - sound=0x138800 - - 2) SoundBlaster family and compatibles - - sound=0x2220Id,0x138800 (remember to set the IRQ and DMA) - or if you have SB16 or SB16ASP, you have to use the following: - (use the same IRQ (the I colums) in all three places. The - the D is the 16 bit DMA channel (5 to 7) and the d is - the 8 bit one (1 or 3). The X is the 2nd digit of the - midi IO address (3 or 0)). - sound=0x2220Id,0x6220ID,0x73X0I0,0x138800 - - 3) ProAudioSpectrum16, ProAudioStudio16, Logitech Soundman16 etc. - - sound=0x3388Id,0x2220Id,0x138800 (set the DMAs and IRQs) - - 4) Gravis UltraSound - - sound=0x42X0Id (X is 1, 2, 3 or 4. Set the DMA and IRQ) - - 5) MPU-401 - - sound=0x5aaaI0 - -If you have more than one soundcards, you have to concatenate the options -for each of the cards. There cannot be more than one sound= argument in the -command line. For example use "sound=0x5aaaI0,0x138800" if you have AdLib -and MPU-401 on your system. -If there are two or more sound= arguments -in the boot command line, just the last one takes effect. The earlier ones -will be ignored silently. - -The boot time configuration feature is intended mainly for distributors of -precompiled kernels. When this feature is used, drivers for all of the -cards have to be enabled before compiling the driver. The configurator program -doesn't enable MPU-401 when the full driver option is selected. It must be -enabled by uncommenting "#define EXCLUDE_MPU401" in the sound/local.h. - -Important note! - -The sound driver is enabled by default. If the kernel is booted without -using the sound=0 option, the sound driver is initialized using the compile -time parameters. This could be dangerous (specially if the MPU-401 driver -is enabled with I/O address 0x330 (used by AHA-1542 also)). If you want to -compile the driver to be inactive by default, you have to append a -#define SND_DEFAULT_ENABLE 0 -to the sound/local.h before compiling the driver. - -Remember to check that the sound setup routine is included in the -bootparams structure in linux/init/main.c. It should contain the following -lines: - -#ifdef CONFIG_SOUND - { "sound=", sound_setup }, -#endif - -In case these lines were not there, you have to insert them (the driver works -without them but it's not possible to give the boot time parameters for the -sound driver). Add also the following line somewhere near the beginning of -linux/init/main.c: - -extern void sound_setup(char *str, int *ints); - -Problems --------- - -If you have any kind of problems, there is a debugging feature which -could help you to solve the problem. To use it, just execute the -command: - - cat /dev/sndstat - -and look at the output. It should display some usefull info about the -driver configuration. If there is no /dev/sndstat -(/dev/sndstat: No such file or directory), ensure that you have executed the -soundinstall script (at the end of this file). The message: -/dev/dsp: No such device means that you don't have the sound driver installed -on your kernel or the driver version is earlier than 1.99.6. - - -- /dev/???????: No such file or directory. -Run the script at the end of this file. - -- /dev/???????: No such device. -You have not booted with a kernel containing the driver or the I/O address -configuration doesn't match your hardaware. - -- The module player (str) plays just a second and then stops completely. -You have incorrect IRQ settings (usual with SB cards). - -- There is pauses in the playback of the module player (str). -The str program requires more than 40% of the speed of a 486/50 to play -without pauses at 44 kHz speed. A 386/25 can hardly play faster than 22 kHz. -You should use lower speed (-s speed), buy a faster computer or a Gravis -UltraSound card. (If you already have GUS, you should use gmod and not the -str). If the DSP_BUFFSIZE in the sound/local.h is less than (nr_channels* -speed_in_Hz * (bits/8))/2, it could explain the pausing problem. Also check -that the turbo swich is on and don't run applications like weather forecasting -on background. Sometimes (very rarely) an IRQ conflict can cause similar -problems with SB cards. -If you want to play modules on a 386sx while recompiling the world, buy a GUS. -It runs without burning your CPU. - -Hannu Savolainen -hsavolai@cs.helsinki.fi - ------------------ cut here ------------------------------ -#!/bin/sh -# -# soudinstall -# -# by Craig Metz - cmetz@thor.tjhsst.edu -# -# Create the devices -# -# Mixer (14, 0) -# -if [ -e /dev/mixer ]; then - rm -f /dev/mixer -fi -mknod -m 666 /dev/mixer c 14 0 - -if [ -e /dev/mixer1 ]; then - rm -f /dev/mixer1 -fi -mknod -m 666 /dev/mixer1 c 14 16 -# -# Sequencer (14, 1) -# -if [ -e /dev/sequencer ]; then - rm -f /dev/sequencer -fi -mknod -m 666 /dev/sequencer c 14 1 -# -# MIDI (14, 2) [ Not implemented ] -# -if [ -e /dev/midi ]; then - rm -f /dev/midi -fi -mknod -m 666 /dev/midi c 14 2 -# -# DSP (14, 3) -# -if [ -e /dev/dsp ]; then - rm -f /dev/dsp -fi -mknod -m 666 /dev/dsp c 14 3 -# -# SPARC audio (14, 4) [ Not fully implemented ] -# -if [ -e /dev/audio ]; then - rm -f /dev/audio -fi -mknod -m 666 /dev/audio c 14 4 -# -# DSP2 (14, 19) /dev/dsp for the second soundcard. -# Also the SB emulation part of the -# PAS16 card. -# -if [ -e /dev/dsp1 ]; then - rm -f /dev/dsp1 -fi -mknod -m 666 /dev/dsp1 c 14 19 -# -# SPARC audio1 (14, 20) [ Not fully implemented ] -# /dev/audio for the second soundcard. -# Also the SB emulation part of the -# PAS16 card. -# -if [ -e /dev/audio1 ]; then - rm -f /dev/audio1 -fi -mknod -m 666 /dev/audio1 c 14 20 -# -# /dev/sndstat (14,6) For debugging purposes -# -if [ -e /dev/sndstat ]; then - rm -f /dev/sndstat -fi -mknod -m 666 /dev/sndstat c 14 6 -exit 0 diff -uNr linux-1.0.9/drivers/sound/adlib_card.c linux/drivers/sound/adlib_card.c --- linux-1.0.9/drivers/sound/adlib_card.c Thu Dec 9 23:22:20 1993 +++ linux/drivers/sound/adlib_card.c Mon Apr 1 17:39:34 2002 @@ -1,10 +1,10 @@ /* * sound/adlib_card.c - * + * * Detection routine for the AdLib card. - * + * * Copyright by Hannu Savolainen 1993 - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: 1. Redistributions of source code must retain the above copyright @@ -12,7 +12,7 @@ * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -24,7 +24,7 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * + * */ #include "sound_config.h" diff -uNr linux-1.0.9/drivers/sound/audio.c linux/drivers/sound/audio.c --- linux-1.0.9/drivers/sound/audio.c Thu Dec 9 23:22:30 1993 +++ linux/drivers/sound/audio.c Mon Apr 1 17:39:34 2002 @@ -1,10 +1,10 @@ /* * sound/audio.c - * + * * Device file manager for /dev/audio - * + * * Copyright by Hannu Savolainen 1993 - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: 1. Redistributions of source code must retain the above copyright @@ -12,7 +12,7 @@ * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -24,7 +24,7 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * + * */ #include "sound_config.h" @@ -38,10 +38,12 @@ #define OFF 0 static int wr_buff_no[MAX_DSP_DEV]; /* != -1, if there is a + * incomplete output block */ static int wr_buff_size[MAX_DSP_DEV], wr_buff_ptr[MAX_DSP_DEV]; -static int audio_mode[MAX_DSP_DEV]; +static int audio_mode[MAX_DSP_DEV]; + #define AM_NONE 0 #define AM_WRITE 1 #define AM_READ 2 @@ -52,16 +54,16 @@ audio_open (int dev, struct fileinfo *file) { int ret; - int bits; - int dev_type = dev & 0x0f; - int mode = file->mode & O_ACCMODE; + int bits; + int dev_type = dev & 0x0f; + int mode = file->mode & O_ACCMODE; dev = dev >> 4; if (dev_type == SND_DEV_DSP16) - bits = 16; + bits = 16; else - bits = 8; + bits = 8; if ((ret = DMAbuf_open (dev, mode)) < 0) return ret; @@ -126,7 +128,7 @@ { int c, p, l; int err; - int dev_type = dev & 0x0f; + int dev_type = dev & 0x0f; dev = dev >> 4; @@ -134,9 +136,9 @@ c = count; if (audio_mode[dev] == AM_READ) /* Direction changed */ - { + { wr_buff_no[dev] = -1; - } + } audio_mode[dev] = AM_WRITE; @@ -170,19 +172,19 @@ } else dsp_devs[dev]->copy_from_user (dev, - wr_dma_buf[dev], wr_buff_ptr[dev], buf, p, l); + wr_dma_buf[dev], wr_buff_ptr[dev], buf, p, l); /* Insert local processing here */ if (dev_type == SND_DEV_AUDIO) - { + { #ifdef linux - /* This just allows interrupts while the conversion is running */ - __asm__ ("sti"); + /* This just allows interrupts while the conversion is running */ + __asm__ ("sti"); #endif - translate_bytes (ulaw_dsp, &wr_dma_buf[dev][wr_buff_ptr[dev]], l); - } + translate_bytes (ulaw_dsp, (unsigned char *) &wr_dma_buf[dev][wr_buff_ptr[dev]], l); + } c -= l; p += l; @@ -207,21 +209,21 @@ int c, p, l; char *dmabuf; int buff_no; - int dev_type = dev & 0x0f; + int dev_type = dev & 0x0f; dev = dev >> 4; p = 0; c = count; if (audio_mode[dev] == AM_WRITE) - { + { if (wr_buff_no[dev] >= 0) { DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev]); wr_buff_no[dev] = -1; } - } + } audio_mode[dev] = AM_READ; @@ -236,14 +238,14 @@ /* Insert any local processing here. */ if (dev_type == SND_DEV_AUDIO) - { + { #ifdef linux - /* This just allows interrupts while the conversion is running */ - __asm__ ("sti"); + /* This just allows interrupts while the conversion is running */ + __asm__ ("sti"); #endif - translate_bytes (dsp_ulaw, dmabuf, l); - } + translate_bytes (dsp_ulaw, (unsigned char *) dmabuf, l); + } COPY_TO_USER (buf, p, dmabuf, l); @@ -260,7 +262,8 @@ audio_ioctl (int dev, struct fileinfo *file, unsigned int cmd, unsigned int arg) { - int dev_type = dev & 0x0f; + int dev_type = dev & 0x0f; + dev = dev >> 4; switch (cmd) @@ -292,7 +295,7 @@ default: if (dev_type == SND_DEV_AUDIO) - return RET_ERROR (EIO); + return RET_ERROR (EIO); return DMAbuf_ioctl (dev, cmd, arg, 0); } @@ -321,14 +324,14 @@ int audio_open (int dev, struct fileinfo *file) - { - return RET_ERROR (ENXIO); - } +{ + return RET_ERROR (ENXIO); +} void audio_release (int dev, struct fileinfo *file) - { - }; +{ +}; int audio_ioctl (int dev, struct fileinfo *file, unsigned int cmd, unsigned int arg) diff -uNr linux-1.0.9/drivers/sound/configure.c linux/drivers/sound/configure.c --- linux-1.0.9/drivers/sound/configure.c Tue Dec 14 13:16:48 1993 +++ linux/drivers/sound/configure.c Mon Apr 1 17:39:34 2002 @@ -1,8 +1,8 @@ /* - * sound/configure.c - Configuration program for the Linux Sound Driver - * + * sound/configure.c - Configuration program for the Linux Sound Driver + * * Copyright by Hannu Savolainen 1993 - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: 1. Redistributions of source code must retain the above copyright @@ -10,7 +10,7 @@ * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -22,7 +22,7 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * + * */ #include @@ -48,12 +48,12 @@ #define OPT_MIDI_AUTO 8 #define OPT_MIDI 9 #define OPT_YM3812_AUTO 10 /* Select this automaticly if user selects - * MIDI or AdLib driver */ + * MIDI or AdLib driver */ #define OPT_YM3812 11 /* Select this if the previous one was not - * selected */ + * selected */ #define OPT_SEQUENCER 12 #define OPT_CHIP_MIDI 13 /* New support added at UW - Milwauklee UW - - * Milwauklee */ + * Milwauklee */ #define OPT_LAST 12 #define ANY_DEVS (B(OPT_AUDIO)|B(OPT_MIDI)|B(OPT_SEQUENCER)|B(OPT_GUS)|B(OPT_MPU401)) @@ -65,7 +65,7 @@ char macro[20]; int verify; int alias; - int default_answ; + int default_answ; } hw_entry; @@ -77,11 +77,11 @@ * second field is a set of options which are not allowed with this one. If * the fourth field is zero, the option is selected without asking * confirmation from the user. - * + * * With this version of the rule table it is possible to select just one type of * hardware. - * - * NOTE! Keep the following table and the questions array in sync with the + * + * NOTE! Keep the following table and the questions array in sync with the * option numbering! */ @@ -127,7 +127,7 @@ }; unsigned long selected_options = 0; -int sb_dma = 0; +int sb_dma = 0; int can_select_option (int nr) @@ -272,11 +272,11 @@ } else { - int def_answ = hw_table[i].default_answ; + int def_answ = hw_table[i].default_answ; - fprintf (stderr, - def_answ ? " %s (y/n) ? " : " %s (n/y) ? ", - questions[i]); + fprintf (stderr, + def_answ ? " %s (y/n) ? " : " %s (n/y) ? ", + questions[i]); if (think_positively (def_answ)) if (hw_table[i].alias) selected_options |= B (hw_table[i].alias); @@ -286,8 +286,8 @@ } } - if (selected_options & B(OPT_SB16)) - selected_options |= B(OPT_SBPRO); + if (selected_options & B (OPT_SB16)) + selected_options |= B (OPT_SBPRO); if (!(selected_options & ANY_DEVS)) { @@ -319,8 +319,9 @@ if (selected_options & B (OPT_SB) && selected_options & (B (OPT_AUDIO) | B (OPT_MIDI))) { fprintf (stderr, "\nIRQ number for SoundBlaster?\n" - "The IRQ adress is defined by the jumpers on your card and\n" - "7 is the factory default. Valid values are 9, 5, 7 and 10.\n" + "The IRQ address is defined by the jumpers on your card.\n" + "The factory default is either 5 or 7 (depending on the model).\n" + "Valid values are 9, 5, 7 and 10.\n" "Enter the value: "); num = ask_value ("%d", 7); @@ -333,7 +334,7 @@ fprintf (stderr, "SoundBlaster IRQ set to %d\n", num); printf ("#define SBC_IRQ %d\n", num); - if (selected_options & B (OPT_SBPRO)) + if (selected_options & (B (OPT_SBPRO) | B (OPT_PAS))) { fprintf (stderr, "\nDMA channel for SoundBlaster?\n" @@ -359,7 +360,7 @@ { fprintf (stderr, "\n16 bit DMA channel for SoundBlaster 16?\n" - "Possible values are 5, 6 or 7\n" + "Possible values are 5, 6 or 7\n" "The default value is 6\n" "Enter the value: "); @@ -373,14 +374,14 @@ fprintf (stderr, "SoundBlaster DMA set to %d\n", num); printf ("#define SB16_DMA %d\n", num); - fprintf (stderr, "\nI/O base for SB16 Midi?\n" - "Possible values are 300 and 330\n" - "The factory default is 330\n" - "Enter the SB16 Midi I/O base: "); - - num = ask_value ("%x", 0x330); - fprintf (stderr, "SB16 Midi I/O base set to %03x\n", num); - printf ("#define SB16MIDI_BASE 0x%03x\n", num); + fprintf (stderr, "\nI/O base for SB16 Midi?\n" + "Possible values are 300 and 330\n" + "The factory default is 330\n" + "Enter the SB16 Midi I/O base: "); + + num = ask_value ("%x", 0x330); + fprintf (stderr, "SB16 Midi I/O base set to %03x\n", num); + printf ("#define SB16MIDI_BASE 0x%03x\n", num); } } @@ -428,7 +429,7 @@ if (selected_options & B (OPT_GUS)) { fprintf (stderr, "\nI/O base for Gravis Ultrasound?\n" - "Valid choises are 210, 220, 230, 240, 250 or 260\n" + "Valid choices are 210, 220, 230, 240, 250 or 260\n" "The factory default is 220\n" "Enter the GUS I/O base: "); @@ -515,12 +516,12 @@ { def_size = 16384; - if (selected_options & (B (OPT_SBPRO) | B (OPT_PAS) | B(OPT_SB16))) + if (selected_options & (B (OPT_SBPRO) | B (OPT_PAS) | B (OPT_SB16))) def_size = 32768; #ifndef __386BSD__ - if (((selected_options & B (OPT_PAS)) || (selected_options & B (OPT_SB16))) && - !full_driver) + if (((selected_options & B (OPT_PAS)) || (selected_options & B (OPT_SB16))) && + !full_driver) def_size = 65536; /* PAS16 or SB16 */ #endif @@ -543,7 +544,7 @@ fprintf (stderr, "The sound driver is now configured.\n"); #if defined(SCO) || defined(ISC) || defined(SYSV) - fprintf(stderr, "Rember to update the System file\n"); + fprintf (stderr, "Remember to update the System file\n"); #endif exit (0); diff -uNr linux-1.0.9/drivers/sound/dev_table.c linux/drivers/sound/dev_table.c --- linux-1.0.9/drivers/sound/dev_table.c Tue Dec 14 17:41:32 1993 +++ linux/drivers/sound/dev_table.c Mon Apr 1 17:39:34 2002 @@ -1,10 +1,10 @@ /* * sound/dev_table.c - * + * * Device call tables. - * + * * Copyright by Hannu Savolainen 1993 - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: 1. Redistributions of source code must retain the above copyright @@ -12,7 +12,7 @@ * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -24,7 +24,7 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * + * */ #define _DEV_TABLE_C_ @@ -39,23 +39,23 @@ for (i = 0; i < (n - 1); i++) if (supported_drivers[i].enabled) - if (supported_drivers[i].probe (&supported_drivers[i].config)) - { + if (supported_drivers[i].probe (&supported_drivers[i].config)) + { #ifndef SHORT_BANNERS - printk ("snd%d", - supported_drivers[i].card_type); + printk ("snd%d", + supported_drivers[i].card_type); #endif - mem_start = supported_drivers[i].attach (mem_start, &supported_drivers[i].config); + mem_start = supported_drivers[i].attach (mem_start, &supported_drivers[i].config); #ifndef SHORT_BANNERS - printk (" at 0x%x irq %d drq %d\n", - supported_drivers[i].config.io_base, - supported_drivers[i].config.irq, - supported_drivers[i].config.dma); + printk (" at 0x%x irq %d drq %d\n", + supported_drivers[i].config.io_base, + supported_drivers[i].config.irq, + supported_drivers[i].config.dma); #endif - } - else - supported_drivers[i].enabled=0; /* Mark as not detected */ + } + else + supported_drivers[i].enabled = 0; /* Mark as not detected */ return mem_start; } @@ -69,14 +69,15 @@ for (i = 0; i < (n - 1); i++) if (supported_drivers[i].card_type == unit) - { + { supported_drivers[i].config.io_base = hw_config->io_base; supported_drivers[i].config.irq = hw_config->irq; supported_drivers[i].config.dma = hw_config->dma; - if (supported_drivers[i].probe (hw_config)) return 1; - supported_drivers[i].enabled=0; /* Mark as not detected */ - return 0; - } + if (supported_drivers[i].probe (hw_config)) + return 1; + supported_drivers[i].enabled = 0; /* Mark as not detected */ + return 0; + } return FALSE; } @@ -115,91 +116,102 @@ } #ifdef linux -void sound_setup(char *str, int *ints) +void +sound_setup (char *str, int *ints) { int i, n = sizeof (supported_drivers) / sizeof (struct card_info); -/* + /* * First disable all drivers */ - for (i=0;i> 20; - - if (card_type > 127) - { - /* Add any future extensions here*/ - return; - } - - ioaddr = (val & 0x000fff00) >> 8; - irq = (val & 0x000000f0) >> 4; - dma = (val & 0x0000000f); - - ptr = -1; - for (j=0;j> 20; + + if (card_type > 127) + { + /* Add any future extensions here */ + return; + } + + ioaddr = (val & 0x000fff00) >> 8; + irq = (val & 0x000000f0) >> 4; + dma = (val & 0x0000000f); + + ptr = -1; + for (j = 0; j < n && ptr == -1; j++) + if (supported_drivers[j].card_type == card_type) + ptr = j; + + if (ptr == -1) + printk ("Sound: Invalid setup parameter 0x%08x\n", val); + else + { + supported_drivers[ptr].enabled = 1; + supported_drivers[ptr].config.io_base = ioaddr; + supported_drivers[ptr].config.irq = irq; + supported_drivers[ptr].config.dma = dma; + } + } } + #else -void sound_chconf(int card_type, int ioaddr, int irq, int dma) +void +sound_chconf (int card_type, int ioaddr, int irq, int dma) { int i, n = sizeof (supported_drivers) / sizeof (struct card_info); - int ptr, j; + int ptr, j; - ptr = -1; - for (j=0;j /* need byte IO */ - -#define deb_outb(x,y) {printk("out %02x, %02x\n", x, y);outb(x,y);} - - -#ifdef HAVE_REALLY_SLOW_DMA_CONTROLLER -#define outb outb_p -#endif - -/* - * NOTES about DMA transfers: - * - * controller 1: channels 0-3, byte operations, ports 00-1F - * controller 2: channels 4-7, word operations, ports C0-DF - * - * - ALL registers are 8 bits only, regardless of transfer size - * - channel 4 is not used - cascades 1 into 2. - * - channels 0-3 are byte - addresses/counts are for physical bytes - * - channels 5-7 are word - addresses/counts are for physical words - * - transfers must not cross physical 64K (0-3) or 128K (5-7) boundaries - * - transfer count loaded to registers is 1 less than actual count - * - controller 2 offsets are all even (2x offsets for controller 1) - * - page registers for 5-7 don't use data bit 0, represent 128K pages - * - page registers for 0-3 use bit 0, represent 64K pages - * - * DMA transfers are limited to the lower 16MB of _physical_ memory. - * Note that addresses loaded into registers must be _physical_ addresses, - * not logical addresses (which may differ if paging is active). - * - * Address mapping for channels 0-3: - * - * A23 ... A16 A15 ... A8 A7 ... A0 (Physical addresses) - * | ... | | ... | | ... | - * | ... | | ... | | ... | - * | ... | | ... | | ... | - * P7 ... P0 A7 ... A0 A7 ... A0 - * | Page | Addr MSB | Addr LSB | (DMA registers) - * - * Address mapping for channels 5-7: - * - * A23 ... A17 A16 A15 ... A9 A8 A7 ... A1 A0 (Physical addresses) - * | ... | \ \ ... \ \ \ ... \ \ - * | ... | \ \ ... \ \ \ ... \ (not used) - * | ... | \ \ ... \ \ \ ... \ - * P7 ... P1 (0) A7 A6 ... A0 A7 A6 ... A0 - * | Page | Addr MSB | Addr LSB | (DMA registers) - * - * Again, channels 5-7 transfer _physical_ words (16 bits), so addresses - * and counts _must_ be word-aligned (the lowest address bit is _ignored_ at - * the hardware level, so odd-byte transfers aren't possible). - * - * Transfer count (_not # bytes_) is limited to 64K, represented as actual - * count - 1 : 64K => 0xFFFF, 1 => 0x0000. Thus, count is always 1 or more, - * and up to 128K bytes may be transferred on channels 5-7 in one operation. - * - */ - -#define MAX_DMA_CHANNELS 8 - -/* 8237 DMA controllers */ -#define IO_DMA1_BASE 0x00 /* 8 bit slave DMA, channels 0..3 */ -#define IO_DMA2_BASE 0xC0 /* 16 bit master DMA, ch 4(=slave input)..7 */ - -/* DMA controller registers */ -#define DMA1_CMD_REG 0x08 /* command register (w) */ -#define DMA1_STAT_REG 0x08 /* status register (r) */ -#define DMA1_REQ_REG 0x09 /* request register (w) */ -#define DMA1_MASK_REG 0x0A /* single-channel mask (w) */ -#define DMA1_MODE_REG 0x0B /* mode register (w) */ -#define DMA1_CLEAR_FF_REG 0x0C /* clear pointer flip-flop (w) */ -#define DMA1_TEMP_REG 0x0D /* Temporary Register (r) */ -#define DMA1_RESET_REG 0x0D /* Master Clear (w) */ -#define DMA1_CLR_MASK_REG 0x0E /* Clear Mask */ -#define DMA1_MASK_ALL_REG 0x0F /* all-channels mask (w) */ - -#define DMA2_CMD_REG 0xD0 /* command register (w) */ -#define DMA2_STAT_REG 0xD0 /* status register (r) */ -#define DMA2_REQ_REG 0xD2 /* request register (w) */ -#define DMA2_MASK_REG 0xD4 /* single-channel mask (w) */ -#define DMA2_MODE_REG 0xD6 /* mode register (w) */ -#define DMA2_CLEAR_FF_REG 0xD8 /* clear pointer flip-flop (w) */ -#define DMA2_TEMP_REG 0xDA /* Temporary Register (r) */ -#define DMA2_RESET_REG 0xDA /* Master Clear (w) */ -#define DMA2_CLR_MASK_REG 0xDC /* Clear Mask */ -#define DMA2_MASK_ALL_REG 0xDE /* all-channels mask (w) */ - -#define DMA_ADDR_0 0x00 /* DMA address registers */ -#define DMA_ADDR_1 0x02 -#define DMA_ADDR_2 0x04 -#define DMA_ADDR_3 0x06 -#define DMA_ADDR_4 0xC0 -#define DMA_ADDR_5 0xC4 -#define DMA_ADDR_6 0xC8 -#define DMA_ADDR_7 0xCC - -#define DMA_CNT_0 0x01 /* DMA count registers */ -#define DMA_CNT_1 0x03 -#define DMA_CNT_2 0x05 -#define DMA_CNT_3 0x07 -#define DMA_CNT_4 0xC2 -#define DMA_CNT_5 0xC6 -#define DMA_CNT_6 0xCA -#define DMA_CNT_7 0xCE - -#define DMA_PAGE_0 0x87 /* DMA page registers */ -#define DMA_PAGE_1 0x83 -#define DMA_PAGE_2 0x81 -#define DMA_PAGE_3 0x82 -#define DMA_PAGE_5 0x8B -#define DMA_PAGE_6 0x89 -#define DMA_PAGE_7 0x8A - -#define DMA_MODE_READ 0x44 /* I/O to memory, no autoinit, increment, single mode */ -#define DMA_MODE_WRITE 0x48 /* memory to I/O, no autoinit, increment, single mode */ -#define DMA_MODE_CASCADE 0xC0 /* pass thru DREQ->HRQ, DACK<-HLDA only */ - -/* enable/disable a specific DMA channel */ -static __inline__ void enable_dma(unsigned int dmanr) -{ - if (dmanr<=3) - deb_outb(dmanr, DMA1_MASK_REG) - else - deb_outb(dmanr & 3, DMA2_MASK_REG); -} - -static __inline__ void disable_dma(unsigned int dmanr) -{ - if (dmanr<=3) - deb_outb(dmanr | 4, DMA1_MASK_REG) - else - deb_outb((dmanr & 3) | 4, DMA2_MASK_REG); -} - -/* Clear the 'DMA Pointer Flip Flop'. - * Write 0 for LSB/MSB, 1 for MSB/LSB access. - * Use this once to initialize the FF to a known state. - * After that, keep track of it. :-) - * --- In order to do that, the DMA routines below should --- - * --- only be used while interrupts are disabled! --- - */ -static __inline__ void clear_dma_ff(unsigned int dmanr) -{ - if (dmanr<=3) - deb_outb(0, DMA1_CLEAR_FF_REG) - else - deb_outb(0, DMA2_CLEAR_FF_REG); -} - -/* set mode (above) for a specific DMA channel */ -static __inline__ void set_dma_mode(unsigned int dmanr, char mode) -{ - if (dmanr<=3) - deb_outb(mode | dmanr, DMA1_MODE_REG) - else - deb_outb(mode | (dmanr&3), DMA2_MODE_REG); -} - -/* Set only the page register bits of the transfer address. - * This is used for successive transfers when we know the contents of - * the lower 16 bits of the DMA current address register, but a 64k boundary - * may have been crossed. - */ -static __inline__ void set_dma_page(unsigned int dmanr, char pagenr) -{ - switch(dmanr) { - case 0: - deb_outb(pagenr, DMA_PAGE_0); - break; - case 1: - deb_outb(pagenr, DMA_PAGE_1); - break; - case 2: - deb_outb(pagenr, DMA_PAGE_2); - break; - case 3: - deb_outb(pagenr, DMA_PAGE_3); - break; - case 5: - deb_outb(pagenr & 0xfe, DMA_PAGE_5); - break; - case 6: - deb_outb(pagenr & 0xfe, DMA_PAGE_6); - break; - case 7: - deb_outb(pagenr & 0xfe, DMA_PAGE_7); - break; - } -} - - -/* Set transfer address & page bits for specific DMA channel. - * Assumes dma flipflop is clear. - */ -static __inline__ void set_dma_addr(unsigned int dmanr, unsigned int a) -{ - set_dma_page(dmanr, a>>16); - if (dmanr <= 3) { - deb_outb( a & 0xff, ((dmanr&3)<<1) + IO_DMA1_BASE ); - deb_outb( (a>>8) & 0xff, ((dmanr&3)<<1) + IO_DMA1_BASE ) - } else { - deb_outb( (a>>1) & 0xff, ((dmanr&3)<<2) + IO_DMA2_BASE ); - deb_outb( (a>>9) & 0xff, ((dmanr&3)<<2) + IO_DMA2_BASE ); - } -} - - -/* Set transfer size (max 64k for DMA1..3, 128k for DMA5..7) for - * a specific DMA channel. - * You must ensure the parameters are valid. - * NOTE: from a manual: "the number of transfers is one more - * than the initial word count"! This is taken into account. - * Assumes dma flip-flop is clear. - * NOTE 2: "count" represents _bytes_ and must be even for channels 5-7. - */ -static __inline__ void set_dma_count(unsigned int dmanr, unsigned int count) -{ - count--; - if (dmanr <= 3) { - deb_outb( count & 0xff, ((dmanr&3)<<1) + 1 + IO_DMA1_BASE ); - deb_outb( (count>>8) & 0xff, ((dmanr&3)<<1) + 1 + IO_DMA1_BASE ); - } else { - deb_outb( (count>>1) & 0xff, ((dmanr&3)<<2) + 2 + IO_DMA2_BASE ); - deb_outb( (count>>9) & 0xff, ((dmanr&3)<<2) + 2 + IO_DMA2_BASE ); - } -} - - -/* Get DMA residue count. After a DMA transfer, this - * should return zero. Reading this while a DMA transfer is - * still in progress will return unpredictable results. - * If called before the channel has been used, it may return 1. - * Otherwise, it returns the number of _bytes_ left to transfer. - * - * Assumes DMA flip-flop is clear. - */ -static __inline__ int get_dma_residue(unsigned int dmanr) -{ - unsigned int io_port = (dmanr<=3)? ((dmanr&3)<<1) + 1 + IO_DMA1_BASE - : ((dmanr&3)<<2) + 2 + IO_DMA2_BASE; - - /* using short to get 16-bit wrap around */ - unsigned short count; - - count = 1 + inb(io_port); - count += inb(io_port) << 8; - - return (dmanr<=3)? count : (count<<1); -} - - -/* These are in kernel/dma.c: */ -extern int request_dma(unsigned int dmanr); /* reserve a DMA channel */ -extern void free_dma(unsigned int dmanr); /* release it again */ - - -#endif /* _ASM_DMA_H */ diff -uNr linux-1.0.9/drivers/sound/dmabuf.c linux/drivers/sound/dmabuf.c --- linux-1.0.9/drivers/sound/dmabuf.c Fri Jan 21 14:59:47 1994 +++ linux/drivers/sound/dmabuf.c Mon Apr 1 17:39:34 2002 @@ -1,10 +1,10 @@ /* * sound/dmabuf.c - * + * * The DMA buffer manager for digitized voice applications - * + * * Copyright by Hannu Savolainen 1993 - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: 1. Redistributions of source code must retain the above copyright @@ -12,7 +12,7 @@ * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -24,7 +24,7 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * + * */ #include "sound_config.h" @@ -88,12 +88,14 @@ */ static int dev_nbufs[MAX_DSP_DEV]; /* # of logical buffers ( >= - * sound_buffcounts[dev] */ + + * sound_buffcounts[dev] */ static int dev_counts[MAX_DSP_DEV][MAX_SUB_BUFFERS]; static int dev_subdivision[MAX_DSP_DEV]; static unsigned long dev_buf_phys[MAX_DSP_DEV][MAX_SUB_BUFFERS]; static char *dev_buf[MAX_DSP_DEV][MAX_SUB_BUFFERS] = - {{NULL}}; +{ + {NULL}}; static int dev_buffsize[MAX_DSP_DEV]; static void @@ -103,8 +105,8 @@ * This routine breaks the physical device buffers to logical ones. */ - unsigned i, p, n; - unsigned sr, nc, sz, bsz; + unsigned i, p, n; + unsigned sr, nc, sz, bsz; sr = dsp_devs[dev]->ioctl (dev, SOUND_PCM_READ_RATE, 0, 1); nc = dsp_devs[dev]->ioctl (dev, SOUND_PCM_READ_CHANNELS, 0, 1); @@ -135,14 +137,15 @@ bsz >>= 1; /* Need at least 2 buffers */ if (dev_subdivision[dev] == 0) - dev_subdivision[dev] = 1; /* Default value */ + dev_subdivision[dev] = 1; /* Default value */ bsz /= dev_subdivision[dev]; /* Use smaller buffers */ - if (bsz == 0) bsz = 4096; /* Just a sanity check */ + if (bsz == 0) + bsz = 4096; /* Just a sanity check */ - while ((sound_buffsizes[dev]*sound_buffcounts[dev])/bsz > MAX_SUB_BUFFERS) - bsz <<= 1; /* Too much buffers */ + while ((sound_buffsizes[dev] * sound_buffcounts[dev]) / bsz > MAX_SUB_BUFFERS) + bsz <<= 1; /* Too much buffers */ dev_buffsize[dev] = bsz; n = 0; @@ -175,7 +178,7 @@ } static void -dma_init_buffers(int dev) +dma_init_buffers (int dev) { RESET_WAIT_QUEUE (dev_sleeper[dev], dev_sleep_flag[dev]); dev_underrun[dev] = 0; @@ -210,7 +213,7 @@ } #ifdef USE_RUNTIME_DMAMEM - sound_dma_malloc(dev); + sound_dma_malloc (dev); #endif if (snd_raw_buf[dev][0] == NULL) @@ -222,7 +225,7 @@ dev_modes[dev] = mode; dev_subdivision[dev] = 0; - dma_init_buffers(dev); + dma_init_buffers (dev); dsp_devs[dev]->ioctl (dev, SOUND_PCM_WRITE_BITS, 8, 1); dsp_devs[dev]->ioctl (dev, SOUND_PCM_WRITE_CHANNELS, 1, 1); dsp_devs[dev]->ioctl (dev, SOUND_PCM_WRITE_RATE, DSP_DEFAULT_SPEED, 1); @@ -233,42 +236,37 @@ static void dma_reset (int dev) { - int retval; - unsigned long flags; + int retval; + unsigned long flags; - DISABLE_INTR(flags); + DISABLE_INTR (flags); dsp_devs[dev]->reset (dev); dsp_devs[dev]->close (dev); if ((retval = dsp_devs[dev]->open (dev, dev_modes[dev])) < 0) - printk("Sound: Reset failed - Can't reopen device\n"); - RESTORE_INTR(flags); + printk ("Sound: Reset failed - Can't reopen device\n"); + RESTORE_INTR (flags); - dma_init_buffers(dev); - reorganize_buffers(dev); + dma_init_buffers (dev); + reorganize_buffers (dev); } static int dma_sync (int dev) { unsigned long flags; - unsigned long time; - int timed_out; if (dma_mode[dev] == DMODE_OUTPUT) { DISABLE_INTR (flags); - timed_out = 0; - time = GET_TIME (); - while ((!(PROCESS_ABORTING (dev_sleeper[dev], dev_sleep_flag[dev]) || - dmabuf_interrupted[dev]) && !timed_out) + dmabuf_interrupted[dev])) && dev_qlen[dev]) { DO_SLEEP (dev_sleeper[dev], dev_sleep_flag[dev], 10 * HZ); - if ((GET_TIME () - time) > (10 * HZ)) - timed_out = 1; + if (TIMED_OUT (dev_sleeper[dev], dev_sleep_flag[dev])) + return dev_qlen[dev]; } RESTORE_INTR (flags); @@ -304,7 +302,7 @@ } #ifdef USE_RUNTIME_DMAMEM - sound_dma_free(dev); + sound_dma_free (dev); #endif dsp_devs[dev]->reset (dev); @@ -321,45 +319,45 @@ DMAbuf_getrdbuffer (int dev, char **buf, int *len) { unsigned long flags; - int err = EIO; + int err = EIO; DISABLE_INTR (flags); if (!dev_qlen[dev]) { if (dev_needs_restart[dev]) - { - dma_reset(dev); - dev_needs_restart[dev] = 0; - } + { + dma_reset (dev); + dev_needs_restart[dev] = 0; + } - if (dma_mode[dev] == DMODE_OUTPUT) /* Was output -> direction change */ - { - dma_sync(dev); - dma_reset(dev); - dma_mode[dev] = DMODE_NONE; - } + if (dma_mode[dev] == DMODE_OUTPUT) /* Was output -> direction change */ + { + dma_sync (dev); + dma_reset (dev); + dma_mode[dev] = DMODE_NONE; + } - if (!bufferalloc_done[dev]) - reorganize_buffers (dev); + if (!bufferalloc_done[dev]) + reorganize_buffers (dev); - if (!dma_mode[dev]) - { - int err; + if (!dma_mode[dev]) + { + int err; - if ((err = dsp_devs[dev]->prepare_for_input (dev, + if ((err = dsp_devs[dev]->prepare_for_input (dev, dev_buffsize[dev], dev_nbufs[dev])) < 0) - { - RESTORE_INTR (flags); - return err; - } - dma_mode[dev] = DMODE_INPUT; - } + { + RESTORE_INTR (flags); + return err; + } + dma_mode[dev] = DMODE_INPUT; + } if (!dev_active[dev]) { - dsp_devs[dev]->start_input (dev, dev_buf_phys[dev][dev_qtail[dev]], + dsp_devs[dev]->start_input (dev, dev_buf_phys[dev][dev_qtail[dev]], dev_buffsize[dev], 0, - !sound_dma_automode[dev] || + !sound_dma_automode[dev] || !dev_started[dev]); dev_active[dev] = 1; dev_started[dev] = 1; @@ -454,25 +452,27 @@ case SNDCTL_DSP_SUBDIVIDE: { - int fact = IOCTL_IN(arg); - - if (fact == 0) - { - fact = dev_subdivision[dev]; - if (fact == 0) fact = 1; - return IOCTL_OUT(arg, fact); - } + int fact = IOCTL_IN (arg); - if (dev_subdivision[dev] != 0) /* Too late to change */ - return RET_ERROR(EINVAL); + if (fact == 0) + { + fact = dev_subdivision[dev]; + if (fact == 0) + fact = 1; + return IOCTL_OUT (arg, fact); + } + + if (dev_subdivision[dev] != 0) /* Too late to change */ + return RET_ERROR (EINVAL); - if (fact > MAX_REALTIME_FACTOR) return RET_ERROR(EINVAL); + if (fact > MAX_REALTIME_FACTOR) + return RET_ERROR (EINVAL); - if (fact != 1 && fact != 2 && fact != 4 && fact != 8 && fact !=16) - return RET_ERROR(EINVAL); + if (fact != 1 && fact != 2 && fact != 4 && fact != 8 && fact != 16) + return RET_ERROR (EINVAL); - dev_subdivision[dev] = fact; - return IOCTL_OUT(arg, fact); + dev_subdivision[dev] = fact; + return IOCTL_OUT (arg, fact); } break; @@ -480,6 +480,7 @@ return dsp_devs[dev]->ioctl (dev, cmd, arg, local); } + /* NOTREACHED */ return RET_ERROR (EIO); } @@ -491,16 +492,15 @@ if (dma_mode[dev] == DMODE_INPUT) /* Was input -> Direction change */ { - dma_reset(dev); - dma_mode[dev] = DMODE_NONE; + dma_reset (dev); + dma_mode[dev] = DMODE_NONE; } - else - if (dev_needs_restart[dev]) /* Restart buffering */ + else if (dev_needs_restart[dev]) /* Restart buffering */ { - dma_sync(dev); - dma_reset(dev); + dma_sync (dev); + dma_reset (dev); } - + dev_needs_restart[dev] = 0; if (!bufferalloc_done[dev]) @@ -563,17 +563,18 @@ dev_counts[dev][dev_qtail[dev]] = l; - dev_needs_restart[dev] = (l != dev_buffsize[dev]); + dev_needs_restart[dev] = (l != dev_buffsize[dev]) && + (sound_dma_automode[dev] || dsp_devs[dev]->flags & NEEDS_RESTART); dev_qtail[dev] = (dev_qtail[dev] + 1) % dev_nbufs[dev]; if (!dev_active[dev]) { dev_active[dev] = 1; - dsp_devs[dev]->output_block (dev, dev_buf_phys[dev][dev_qhead[dev]], - dev_counts[dev][dev_qhead[dev]], 0, - !sound_dma_automode[dev] || !dev_started[dev]); - dev_started[dev] = 1; + dsp_devs[dev]->output_block (dev, dev_buf_phys[dev][dev_qhead[dev]], + dev_counts[dev][dev_qhead[dev]], 0, + !sound_dma_automode[dev] || !dev_started[dev]); + dev_started[dev] = 1; } return 0; @@ -606,7 +607,7 @@ set_dma_count (chan, sound_buffsizes[dev]); enable_dma (chan); RESTORE_INTR (flags); -#else +#else /* linux */ #ifdef __386BSD__ printk ("sound: Invalid DMA mode for device %d\n", dev); @@ -615,24 +616,24 @@ snd_raw_buf_phys[dev][0], sound_buffsizes[dev], chan); -#else -#if defined(ISC) || defined(SCO) +#else /* __386BSD__ */ +#if defined(ISC) || defined(SCO) || defined(SVR42) #ifndef DMAMODE_AUTO printk ("sound: Invalid DMA mode for device %d\n", dev); -#endif +#endif /* DMAMODE_AUTO */ dma_param (chan, ((dma_mode == DMA_MODE_READ) ? DMA_Rdmode : DMA_Wrmode) #ifdef DMAMODE_AUTO | DMAMODE_AUTO -#endif +#endif /* DMAMODE_AUTO */ , snd_raw_buf_phys[dev][0], count); dma_enable (chan); -#else -# error This routine is not valid for this OS. -#endif -#endif +#else /* SYSV */ +#error This routine is not valid for this OS. +#endif /* SYSV */ +#endif /* __386BSD__ */ -#endif +#endif /* linux */ } else { @@ -645,24 +646,24 @@ set_dma_count (chan, count); enable_dma (chan); RESTORE_INTR (flags); -#else +#else /* linux */ #ifdef __386BSD__ isa_dmastart ((dma_mode == DMA_MODE_READ) ? B_READ : B_WRITE, physaddr, count, chan); -#else +#else /* __386BSD__ */ -#if defined(ISC) || defined(SCO) +#if defined(ISC) || defined(SCO) || defined(SVR42) dma_param (chan, ((dma_mode == DMA_MODE_READ) ? DMA_Rdmode : DMA_Wrmode), physaddr, count); dma_enable (chan); -#else -# error This routine is not valid for this OS. -#endif /* !ISC */ -#endif +#else /* SYSV */ +#error This routine is not valid for this OS. +#endif /* SYSV */ +#endif /* __386BSD__ */ -#endif +#endif /* linux */ } return count; @@ -702,17 +703,17 @@ if (dev_qlen[dev]) { - dsp_devs[dev]->output_block (dev, dev_buf_phys[dev][dev_qhead[dev]], - dev_counts[dev][dev_qhead[dev]], 1, - !sound_dma_automode[dev]); + dsp_devs[dev]->output_block (dev, dev_buf_phys[dev][dev_qhead[dev]], + dev_counts[dev][dev_qhead[dev]], 1, + !sound_dma_automode[dev]); dev_active[dev] = 1; } - else - if (underrun_flag) + else if (underrun_flag) { dev_underrun[dev]++; dsp_devs[dev]->halt_xfer (dev); - dev_needs_restart[dev] = 1; + dev_needs_restart[dev] = (sound_dma_automode[dev] || + dsp_devs[dev]->flags & NEEDS_RESTART); } DISABLE_INTR (flags); @@ -734,20 +735,20 @@ } else if (dev_qlen[dev] == (dev_nbufs[dev] - 1)) { - printk("Sound: Recording overrun\n"); + printk ("Sound: Recording overrun\n"); dev_underrun[dev]++; dsp_devs[dev]->halt_xfer (dev); dev_active[dev] = 0; - dev_needs_restart[dev] = 1; + dev_needs_restart[dev] = sound_dma_automode[dev]; } else { dev_qlen[dev]++; dev_qtail[dev] = (dev_qtail[dev] + 1) % dev_nbufs[dev]; - dsp_devs[dev]->start_input (dev, dev_buf_phys[dev][dev_qtail[dev]], + dsp_devs[dev]->start_input (dev, dev_buf_phys[dev][dev_qtail[dev]], dev_buffsize[dev], 1, - !sound_dma_automode[dev]); + !sound_dma_automode[dev]); dev_active[dev] = 1; } @@ -798,13 +799,13 @@ /* * The sound_mem_init() is called by mem_init() immediately after mem_map is * initialized and before free_page_list is created. - * + * * This routine allocates DMA buffers at the end of available physical memory ( * <16M) and marks pages reserved at mem_map. */ #else -/* Stub versions if audio services not included */ +/* Stub versions if audio services not included */ int DMAbuf_open (int dev, int mode) diff -uNr linux-1.0.9/drivers/sound/gus_card.c linux/drivers/sound/gus_card.c --- linux-1.0.9/drivers/sound/gus_card.c Fri Jan 21 14:59:47 1994 +++ linux/drivers/sound/gus_card.c Mon Apr 1 17:39:34 2002 @@ -1,10 +1,10 @@ /* * sound/gus_card.c - * + * * Detection routine for the Gravis Ultrasound. - * + * * Copyright by Hannu Savolainen 1993 - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: 1. Redistributions of source code must retain the above copyright @@ -12,7 +12,7 @@ * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -24,7 +24,7 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * + * */ #include "sound_config.h" @@ -106,7 +106,7 @@ unsigned char src; #ifdef linux - sti(); + sti (); #endif while (1) diff -uNr linux-1.0.9/drivers/sound/gus_hw.h linux/drivers/sound/gus_hw.h --- linux-1.0.9/drivers/sound/gus_hw.h Mon Jun 21 14:19:09 1993 +++ linux/drivers/sound/gus_hw.h Mon Apr 1 17:39:34 2002 @@ -24,6 +24,8 @@ #define u_Command (gus_base + 0x103) #define u_DataLo (gus_base + 0x104) #define u_DataHi (gus_base + 0x105) +#define u_MixData (gus_base + 0x106) /* Rev. 3.7+ mixing */ +#define u_MixSelect (gus_base + 0x506) /* registers. */ #define u_IrqStatus u_Status # define MIDI_TX_IRQ 0x01 /* pending MIDI xmit IRQ */ # define MIDI_RX_IRQ 0x02 /* pending MIDI recv IRQ */ @@ -32,4 +34,17 @@ # define WAVETABLE_IRQ 0x20 /* pending wavetable IRQ */ # define ENVELOPE_IRQ 0x40 /* pending volume envelope IRQ */ # define DMA_TC_IRQ 0x80 /* pending dma tc IRQ */ + +#define ICS2101 1 +# define ICS_MIXDEVS 6 +# define DEV_MIC 0 +# define DEV_LINE 1 +# define DEV_CD 2 +# define DEV_GF1 3 +# define DEV_UNUSED 4 +# define DEV_VOL 5 + +# define CHN_LEFT 0 +# define CHN_RIGHT 1 +#define CS4231 2 #define u_DRAMIO (gus_base + 0x107) diff -uNr linux-1.0.9/drivers/sound/gus_linearvol.h linux/drivers/sound/gus_linearvol.h --- linux-1.0.9/drivers/sound/gus_linearvol.h Thu Jan 1 01:00:00 1970 +++ linux/drivers/sound/gus_linearvol.h Mon Apr 1 17:39:34 2002 @@ -0,0 +1,18 @@ +static unsigned short gus_linearvol[128] = { + 0x0000, 0x08ff, 0x09ff, 0x0a80, 0x0aff, 0x0b40, 0x0b80, 0x0bc0, + 0x0bff, 0x0c20, 0x0c40, 0x0c60, 0x0c80, 0x0ca0, 0x0cc0, 0x0ce0, + 0x0cff, 0x0d10, 0x0d20, 0x0d30, 0x0d40, 0x0d50, 0x0d60, 0x0d70, + 0x0d80, 0x0d90, 0x0da0, 0x0db0, 0x0dc0, 0x0dd0, 0x0de0, 0x0df0, + 0x0dff, 0x0e08, 0x0e10, 0x0e18, 0x0e20, 0x0e28, 0x0e30, 0x0e38, + 0x0e40, 0x0e48, 0x0e50, 0x0e58, 0x0e60, 0x0e68, 0x0e70, 0x0e78, + 0x0e80, 0x0e88, 0x0e90, 0x0e98, 0x0ea0, 0x0ea8, 0x0eb0, 0x0eb8, + 0x0ec0, 0x0ec8, 0x0ed0, 0x0ed8, 0x0ee0, 0x0ee8, 0x0ef0, 0x0ef8, + 0x0eff, 0x0f04, 0x0f08, 0x0f0c, 0x0f10, 0x0f14, 0x0f18, 0x0f1c, + 0x0f20, 0x0f24, 0x0f28, 0x0f2c, 0x0f30, 0x0f34, 0x0f38, 0x0f3c, + 0x0f40, 0x0f44, 0x0f48, 0x0f4c, 0x0f50, 0x0f54, 0x0f58, 0x0f5c, + 0x0f60, 0x0f64, 0x0f68, 0x0f6c, 0x0f70, 0x0f74, 0x0f78, 0x0f7c, + 0x0f80, 0x0f84, 0x0f88, 0x0f8c, 0x0f90, 0x0f94, 0x0f98, 0x0f9c, + 0x0fa0, 0x0fa4, 0x0fa8, 0x0fac, 0x0fb0, 0x0fb4, 0x0fb8, 0x0fbc, + 0x0fc0, 0x0fc4, 0x0fc8, 0x0fcc, 0x0fd0, 0x0fd4, 0x0fd8, 0x0fdc, + 0x0fe0, 0x0fe4, 0x0fe8, 0x0fec, 0x0ff0, 0x0ff4, 0x0ff8, 0x0ffc +}; diff -uNr linux-1.0.9/drivers/sound/gus_midi.c linux/drivers/sound/gus_midi.c --- linux-1.0.9/drivers/sound/gus_midi.c Thu Dec 9 23:23:12 1993 +++ linux/drivers/sound/gus_midi.c Mon Apr 1 17:39:34 2002 @@ -1,10 +1,10 @@ /* * sound/gus2_midi.c - * + * * The low level driver for the GUS Midi Interface. - * + * * Copyright by Hannu Savolainen 1993 - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: 1. Redistributions of source code must retain the above copyright @@ -12,7 +12,7 @@ * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -24,7 +24,7 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * + * */ #include "sound_config.h" diff -uNr linux-1.0.9/drivers/sound/gus_vol.c linux/drivers/sound/gus_vol.c --- linux-1.0.9/drivers/sound/gus_vol.c Fri Jan 21 14:59:48 1994 +++ linux/drivers/sound/gus_vol.c Mon Apr 1 17:39:34 2002 @@ -1,17 +1,18 @@ -/* +/* * gus_vol.c - Compute volume for GUS. - * + * * Greg Lee 1993. */ #include "sound_config.h" #ifndef EXCLUDE_GUS +#include "gus_linearvol.h" #define GUS_VOLUME gus_wave_volume extern int gus_wave_volume; -/* +/* * Calculate gus volume from note velocity, main volume, expression, and * intrinsic patch volume given in patch library. Expression is multiplied * in, so it emphasizes differences in note velocity, while main volume is @@ -20,7 +21,7 @@ * to expression controller messages, if they were found to be used for * dynamic volume adjustments, so here, main volume can be assumed to be * constant throughout a song.) - * + * * Intrinsic patch volume is added in, but if over 64 is also multiplied in, so * we can give a big boost to very weak voices like nylon guitar and the * basses. The normal value is 64. Strings are assigned lower values. @@ -31,27 +32,27 @@ int i, m, n, x; - /* + /* * A voice volume of 64 is considered neutral, so adjust the main volume if * something other than this neutral value was assigned in the patch * library. */ x = 256 + 6 * (voicev - 64); - /* - * Boost expression by voice volume above neutral. + /* + * Boost expression by voice volume above neutral. */ if (voicev > 65) xpn += voicev - 64; xpn += (voicev - 64) / 2; - /* - * Combine multiplicative and level components. + /* + * Combine multiplicative and level components. */ x = vel * xpn * 6 + (voicev / 4) * x; #ifdef GUS_VOLUME - /* + /* * Further adjustment by installation-specific master volume control * (default 60). */ @@ -63,8 +64,8 @@ * Experimental support for the channel main volume */ - mainv = (mainv / 2) + 64; /* Scale to 64 to 127 */ - x = (x * mainv * mainv) / 16384; + mainv = (mainv / 2) + 64; /* Scale to 64 to 127 */ + x = (x * mainv * mainv) / 16384; #endif if (x < 2) @@ -72,7 +73,7 @@ else if (x >= 65535) return ((15 << 8) | 255); - /* + /* * Convert to gus's logarithmic form with 4 bit exponent i and 8 bit * mantissa m. */ @@ -89,14 +90,14 @@ n >>= 1; i++; } - /* + /* * Mantissa is part of linear volume not expressed in exponent. (This is * not quite like real logs -- I wonder if it's right.) */ m = x - (1 << i); - /* - * Adjust mantissa to 8 bits. + /* + * Adjust mantissa to 8 bits. */ if (m > 0) { @@ -109,4 +110,38 @@ return ((i << 8) + m); } +/* + * Volume-values are interpreted as linear values. Volume is based on the + * value supplied with SEQ_START_NOTE(), channel main volume (if compiled in) + * and the volume set by the mixer-device (default 60%). + */ + +unsigned short +gus_linear_vol (int vol, int mainvol) +{ + int mixer_mainvol; + + if (vol <= 0) + vol = 0; + else if (vol >= 127) + vol = 127; + +#ifdef GUS_VOLUME + mixer_mainvol = GUS_VOLUME; +#else + mixer_mainvol = 100; +#endif + +#ifdef GUS_USE_CHN_MAIN_VOLUME + if (mainvol <= 0) + mainvol = 0; + else if (mainvol >= 127) + mainvol = 127; +#else + mainvol = 128; +#endif + + return gus_linearvol[(((vol * mainvol) / 128) * mixer_mainvol) / 100]; +} + #endif diff -uNr linux-1.0.9/drivers/sound/gus_wave.c linux/drivers/sound/gus_wave.c --- linux-1.0.9/drivers/sound/gus_wave.c Fri Jan 21 14:59:50 1994 +++ linux/drivers/sound/gus_wave.c Mon Apr 1 17:39:34 2002 @@ -1,11 +1,10 @@ - -/* +/* * sound/gus_wave.c - * + * * Driver for the Gravis UltraSound wave table synth. - * + * * Copyright by Hannu Savolainen 1993 - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: 1. Redistributions of source code must retain the above copyright @@ -13,7 +12,7 @@ * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -25,7 +24,7 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * + * */ #include "sound_config.h" @@ -61,7 +60,7 @@ unsigned char env_rate[6]; unsigned char env_offset[6]; - /* + /* * Volume computation parameters for gus_adagio_vol() */ int main_vol, expression_vol, patch_vol; @@ -84,28 +83,27 @@ static int nr_voices = 0; static int gus_devnum = 0; static int volume_base, volume_scale, volume_method; -static int gus_line_vol = 100, gus_mic_vol = 0; -static int gus_recmask = SOUND_MASK_MIC; -static int recording_active = 0; +static int gus_line_vol = 100, gus_mic_vol = 0; +static int gus_recmask = SOUND_MASK_MIC; +static int recording_active = 0; -#define VOL_METHOD_ADAGIO 1 int gus_wave_volume = 60; int gus_pcm_volume = 80; static unsigned char mix_image = 0x00; -/* +/* * Current version of this driver doesn't allow synth and PCM functions * at the same time. The active_device specifies the active driver */ static int active_device = 0; -#define GUS_DEV_WAVE 1 /* - * * * Wave table synth */ -#define GUS_DEV_PCM_DONE 2 /* - * * * PCM device, transfer done */ -#define GUS_DEV_PCM_CONTINUE 3 /* - * * * PCM device, transfer the - * second * * * chn */ +#define GUS_DEV_WAVE 1 /* + * * * Wave table synth */ +#define GUS_DEV_PCM_DONE 2 /* + * * * PCM device, transfer done */ +#define GUS_DEV_PCM_CONTINUE 3 /* + * * * PCM device, transfer the + * second * * * chn */ static int gus_sampling_speed; static int gus_sampling_channels; @@ -113,33 +111,33 @@ DEFINE_WAIT_QUEUE (dram_sleeper, dram_sleep_flag); -/* +/* * Variables and buffers for PCM output */ -#define MAX_PCM_BUFFERS (32*MAX_REALTIME_FACTOR) /* - * * * Don't - * * * change - * +#define MAX_PCM_BUFFERS (32*MAX_REALTIME_FACTOR) /* + * * * Don't + * * * change + * */ -static int pcm_bsize, /* - * Current blocksize +static int pcm_bsize, /* + * Current blocksize */ - pcm_nblk, /* - * Current # of blocks + pcm_nblk, /* + * Current # of blocks */ - pcm_banksize; /* + pcm_banksize; /* + - * * * * * # bytes allocated for channels */ -static int pcm_datasize[MAX_PCM_BUFFERS]; /* +static int pcm_datasize[MAX_PCM_BUFFERS]; /* + - * * * * * Actual # of bytes * in blk * */ -static volatile int pcm_head, pcm_tail, pcm_qlen; /* +static volatile int pcm_head, pcm_tail, pcm_qlen; /* + - * * * * * DRAM queue * */ static volatile int pcm_active; @@ -154,62 +152,62 @@ static int freq_div_table[] = { - 44100, /* - * 14 + 44100, /* + * 14 */ - 41160, /* - * 15 + 41160, /* + * 15 */ - 38587, /* - * 16 + 38587, /* + * 16 */ - 36317, /* - * 17 + 36317, /* + * 17 */ - 34300, /* - * 18 + 34300, /* + * 18 */ - 32494, /* - * 19 + 32494, /* + * 19 */ - 30870, /* - * 20 + 30870, /* + * 20 */ - 29400, /* - * 21 + 29400, /* + * 21 */ - 28063, /* - * 22 + 28063, /* + * 22 */ - 26843, /* - * 23 + 26843, /* + * 23 */ - 25725, /* - * 24 + 25725, /* + * 24 */ - 24696, /* - * 25 + 24696, /* + * 25 */ - 23746, /* - * 26 + 23746, /* + * 26 */ - 22866, /* - * 27 + 22866, /* + * 27 */ - 22050, /* - * 28 + 22050, /* + * 28 */ - 21289, /* - * 29 + 21289, /* + * 29 */ - 20580, /* - * 30 + 20580, /* + * 30 */ - 19916, /* - * 31 + 19916, /* + * 31 */ - 19293 /* - * 32 + 19293 /* + * 32 */ }; @@ -228,14 +226,15 @@ static void gus_poke (long addr, unsigned char data); static void compute_and_set_volume (int voice, int volume, int ramp_time); extern unsigned short gus_adagio_vol (int vel, int mainv, int xpn, int voicev); +extern unsigned short gus_linear_vol (int vol, int mainvol); static void compute_volume (int voice, int volume); static void do_volume_irq (int voice); -static void set_input_volumes(void); +static void set_input_volumes (void); -#define INSTANT_RAMP -1 /* - * * * Dont use ramping */ -#define FAST_RAMP 0 /* - * * * Fastest possible ramp */ +#define INSTANT_RAMP -1 /* + * * * Dont use ramping */ +#define FAST_RAMP 0 /* + * * * Fastest possible ramp */ static void reset_sample_memory (void) @@ -249,8 +248,8 @@ for (i = 0; i < 32; i++) patch_map[i] = -1; - gus_poke (0, 0); /* - * Put silence here + gus_poke (0, 0); /* + * Put silence here */ gus_poke (1, 0); @@ -386,7 +385,7 @@ if (is16bit) { - /* + /* * Special processing required for 16 bit patches */ @@ -398,6 +397,10 @@ gus_write16 (reg, (unsigned short) ((address >> 7) & 0xffff)); gus_write16 (reg + 1, (unsigned short) ((address << 9) & 0xffff)); + /* Could writing twice fix problems with GUS_VOICE_POS() ? Lets try... */ + gus_delay (); + gus_write16 (reg, (unsigned short) ((address >> 7) & 0xffff)); + gus_write16 (reg + 1, (unsigned short) ((address << 9) & 0xffff)); } static void @@ -441,13 +444,13 @@ { unsigned char mode = (unsigned char) (m & 0xff); - gus_write8 (0x00, (gus_read8 (0x00) & 0x03) | (mode & 0xfc)); /* - * Don't - * start - * or + gus_write8 (0x00, (gus_read8 (0x00) & 0x03) | (mode & 0xfc)); /* + * Don't + * start + * or * stop * * - * voice + * voice */ gus_delay (); gus_write8 (0x00, (gus_read8 (0x00) & 0x03) | (mode & 0xfc)); @@ -468,8 +471,8 @@ static void gus_voice_volume (unsigned int vol) { - gus_write8 (0x0d, 0x03); /* - * Stop ramp before setting volume + gus_write8 (0x0d, 0x03); /* + * Stop ramp before setting volume */ gus_write16 (0x09, (unsigned short) (vol << 4)); } @@ -508,13 +511,13 @@ { unsigned char mode = (unsigned char) (m & 0xff); - gus_write8 (0x0d, (gus_read8 (0x0d) & 0x03) | (mode & 0xfc)); /* - * Don't - * start - * or + gus_write8 (0x0d, (gus_read8 (0x0d) & 0x03) | (mode & 0xfc)); /* + * Don't + * start + * or * stop * * - * ramping + * ramping */ gus_delay (); gus_write8 (0x0d, (gus_read8 (0x0d) & 0x03) | (mode & 0xfc)); @@ -548,14 +551,14 @@ DISABLE_INTR (flags); gus_select_voice (voice); gus_voice_volume (0); - gus_write_addr (0x0a, 0, 0); /* - * Set current position to 0 + gus_write_addr (0x0a, 0, 0); /* + * Set current position to 0 */ - gus_write8 (0x00, 0x03); /* - * Voice off + gus_write8 (0x00, 0x03); /* + * Voice off */ - gus_write8 (0x0d, 0x03); /* - * Ramping off + gus_write8 (0x0d, 0x03); /* + * Ramping off */ RESTORE_INTR (flags); @@ -588,18 +591,22 @@ { unsigned vol, prev_vol, phase; unsigned char rate; + long int flags; if (voices[voice].mode & WAVE_SUSTAIN_ON && voices[voice].env_phase == 2) { + DISABLE_INTR (flags); + gus_select_voice (voice); gus_rampoff (); - return; /* - * Sustain + RESTORE_INTR (flags); + return; /* + * Sustain */ } if (voices[voice].env_phase >= 5) { - /* + /* * Shoot the voice off */ @@ -608,25 +615,30 @@ } prev_vol = voices[voice].current_volume; - gus_voice_volume (prev_vol); phase = ++voices[voice].env_phase; - compute_volume (voice, voices[voice].midi_volume); - vol = voices[voice].initial_volume * voices[voice].env_offset[phase] / 255; rate = voices[voice].env_rate[phase]; - gus_write8 (0x06, rate); /* - * Ramping rate + + DISABLE_INTR (flags); + gus_select_voice (voice); + + gus_voice_volume (prev_vol); + + + gus_write8 (0x06, rate); /* + * Ramping rate */ voices[voice].volume_irq_mode = VMODE_ENVELOPE; - if (((vol - prev_vol) / 64) == 0) /* - * No significant volume change + if (((vol - prev_vol) / 64) == 0) /* + * No significant volume change */ { - step_envelope (voice); /* - * Continue with the next phase + RESTORE_INTR (flags); + step_envelope (voice); /* + * Continue with the next phase */ return; } @@ -636,8 +648,8 @@ if (vol >= (4096 - 64)) vol = 4096 - 65; gus_ramp_range (0, vol); - gus_rampon (0x20); /* - * Increasing, irq + gus_rampon (0x20); /* + * Increasing, irq */ } else @@ -645,11 +657,12 @@ if (vol <= 64) vol = 65; gus_ramp_range (vol, 4030); - gus_rampon (0x60); /* - * Decreasing, irq + gus_rampon (0x60); /* + * Decreasing, irq */ } voices[voice].current_volume = vol; + RESTORE_INTR (flags); } static void @@ -662,25 +675,26 @@ } static void -start_release (int voice) +start_release (int voice, long int flags) { if (gus_read8 (0x00) & 0x03) - return; /* - * Voice already stopped + return; /* + * Voice already stopped */ - voices[voice].env_phase = 2; /* - * Will be incremented by step_envelope + voices[voice].env_phase = 2; /* + * Will be incremented by step_envelope */ voices[voice].current_volume = voices[voice].initial_volume = - gus_read16 (0x09) >> 4; /* - * Get current volume + gus_read16 (0x09) >> 4; /* + * Get current volume */ voices[voice].mode &= ~WAVE_SUSTAIN_ON; gus_rampoff (); + RESTORE_INTR (flags); step_envelope (voice); } @@ -688,32 +702,37 @@ gus_voice_fade (int voice) { int instr_no = sample_map[voice], is16bits; + long int flags; + + DISABLE_INTR (flags); + gus_select_voice (voice); if (instr_no < 0 || instr_no > MAX_SAMPLE) { - gus_write8 (0x00, 0x03); /* - * Hard stop + gus_write8 (0x00, 0x03); /* + * Hard stop */ + RESTORE_INTR (flags); return; } - is16bits = (samples[instr_no].mode & WAVE_16_BITS) ? 1 : 0; /* + is16bits = (samples[instr_no].mode & WAVE_16_BITS) ? 1 : 0; /* * 8 or 16 * bit - * samples + * samples */ if (voices[voice].mode & WAVE_ENVELOPES) { - start_release (voice); + start_release (voice, flags); return; } - /* + /* * Ramp the volume down but not too quickly. */ - if ((gus_read16 (0x09) >> 4) < 100) /* - * Get current volume + if ((gus_read16 (0x09) >> 4) < 100) /* + * Get current volume */ { gus_voice_off (); @@ -724,10 +743,11 @@ gus_ramp_range (65, 4030); gus_ramp_rate (2, 4); - gus_rampon (0x40 | 0x20); /* - * Down, once, irq + gus_rampon (0x40 | 0x20); /* + * Down, once, irq */ voices[voice].volume_irq_mode = VMODE_HALT; + RESTORE_INTR (flags); } static void @@ -742,24 +762,24 @@ for (i = 0; i < 32; i++) { - gus_voice_init (i); /* - * Turn voice off + gus_voice_init (i); /* + * Turn voice off */ gus_voice_init2 (i); } - INB (u_Status); /* - * Touch the status register + INB (u_Status); /* + * Touch the status register */ - gus_look8 (0x41); /* - * Clear any pending DMA IRQs + gus_look8 (0x41); /* + * Clear any pending DMA IRQs */ - gus_look8 (0x49); /* - * Clear any pending sample IRQs + gus_look8 (0x49); /* + * Clear any pending sample IRQs */ - gus_read8 (0x0f); /* - * Clear pending IRQs + gus_read8 (0x0f); /* + * Clear pending IRQs */ } @@ -768,7 +788,7 @@ gus_initialize (void) { unsigned long flags; - unsigned char dma_image, irq_image, tmp; + register unsigned char dma_image, irq_image, tmp; static unsigned char gus_irq_map[16] = {0, 0, 1, 3, 0, 2, 0, 4, 0, 0, 0, 5, 6, 0, 0, 7}; @@ -778,74 +798,74 @@ DISABLE_INTR (flags); - gus_write8 (0x4c, 0); /* - * Reset GF1 + gus_write8 (0x4c, 0); /* + * Reset GF1 */ gus_delay (); gus_delay (); - gus_write8 (0x4c, 1); /* - * Release Reset + gus_write8 (0x4c, 1); /* + * Release Reset */ gus_delay (); gus_delay (); - /* + /* * Clear all interrupts */ - gus_write8 (0x41, 0); /* - * DMA control + gus_write8 (0x41, 0); /* + * DMA control */ - gus_write8 (0x45, 0); /* - * Timer control + gus_write8 (0x45, 0); /* + * Timer control */ - gus_write8 (0x49, 0); /* - * Sample control + gus_write8 (0x49, 0); /* + * Sample control */ gus_select_max_voices (24); - INB (u_Status); /* - * Touch the status register + INB (u_Status); /* + * Touch the status register */ - gus_look8 (0x41); /* - * Clear any pending DMA IRQs + gus_look8 (0x41); /* + * Clear any pending DMA IRQs */ - gus_look8 (0x49); /* - * Clear any pending sample IRQs + gus_look8 (0x49); /* + * Clear any pending sample IRQs */ - gus_read8 (0x0f); /* - * Clear pending IRQs + gus_read8 (0x0f); /* + * Clear pending IRQs */ - gus_reset (); /* - * Resets all voices + gus_reset (); /* + * Resets all voices */ - gus_look8 (0x41); /* - * Clear any pending DMA IRQs + gus_look8 (0x41); /* + * Clear any pending DMA IRQs */ - gus_look8 (0x49); /* - * Clear any pending sample IRQs + gus_look8 (0x49); /* + * Clear any pending sample IRQs */ - gus_read8 (0x0f); /* - * Clear pending IRQs + gus_read8 (0x0f); /* + * Clear pending IRQs */ - gus_write8 (0x4c, 7); /* - * Master reset | DAC enable | IRQ enable + gus_write8 (0x4c, 7); /* + * Master reset | DAC enable | IRQ enable */ - /* + /* * Set up for Digital ASIC */ OUTB (0x05, gus_base + 0x0f); - mix_image |= 0x02; /* - * Disable line out + mix_image |= 0x02; /* + * Disable line out */ OUTB (mix_image, u_Mixer); @@ -853,11 +873,11 @@ OUTB (0x00, gus_base + 0x0f); - /* + /* * Now set up the DMA and IRQ interface - * + * * The GUS supports two IRQs and two DMAs. - * + * * Just one DMA channel is used. This prevents simultaneous ADC and DAC. * Adding this support requires significant changes to the dmabuf.c, dsp.c * and audio.c also. @@ -868,79 +888,79 @@ if (!tmp) printk ("Warning! GUS IRQ not selected\n"); irq_image |= tmp; - irq_image |= 0x40; /* - * Combine IRQ1 (GF1) and IRQ2 (Midi) + irq_image |= 0x40; /* + * Combine IRQ1 (GF1) and IRQ2 (Midi) */ - dma_image = 0x40; /* - * Combine DMA1 (DRAM) and IRQ2 (ADC) + dma_image = 0x40; /* + * Combine DMA1 (DRAM) and IRQ2 (ADC) */ tmp = gus_dma_map[gus_dma]; if (!tmp) printk ("Warning! GUS DMA not selected\n"); dma_image |= tmp; - /* + /* * For some reason the IRQ and DMA addresses must be written twice */ - /* - * Doing it first time + /* + * Doing it first time */ - OUTB (mix_image, u_Mixer); /* - * Select DMA control + OUTB (mix_image, u_Mixer); /* + * Select DMA control */ - OUTB (dma_image | 0x80, u_IRQDMAControl); /* - * Set DMA address + OUTB (dma_image | 0x80, u_IRQDMAControl); /* + * Set DMA address */ - OUTB (mix_image | 0x40, u_Mixer); /* - * Select IRQ control + OUTB (mix_image | 0x40, u_Mixer); /* + * Select IRQ control */ - OUTB (irq_image, u_IRQDMAControl); /* - * Set IRQ address + OUTB (irq_image, u_IRQDMAControl); /* + * Set IRQ address */ - /* - * Doing it second time + /* + * Doing it second time */ - OUTB (mix_image, u_Mixer); /* - * Select DMA control + OUTB (mix_image, u_Mixer); /* + * Select DMA control */ - OUTB (dma_image, u_IRQDMAControl); /* - * Set DMA address + OUTB (dma_image, u_IRQDMAControl); /* + * Set DMA address */ - OUTB (mix_image | 0x40, u_Mixer); /* - * Select IRQ control + OUTB (mix_image | 0x40, u_Mixer); /* + * Select IRQ control */ - OUTB (irq_image, u_IRQDMAControl); /* - * Set IRQ address + OUTB (irq_image, u_IRQDMAControl); /* + * Set IRQ address */ - gus_select_voice (0); /* - * This disables writes to IRQ/DMA reg + gus_select_voice (0); /* + * This disables writes to IRQ/DMA reg */ - mix_image &= ~0x02; /* - * Enable line out + mix_image &= ~0x02; /* + * Enable line out */ - mix_image |= 0x08; /* - * Enable IRQ + mix_image |= 0x08; /* + * Enable IRQ */ - OUTB (mix_image, u_Mixer); /* - * Turn mixer channels on + OUTB (mix_image, u_Mixer); /* + * Turn mixer channels on * Note! Mic in is left off. */ - gus_select_voice (0); /* - * This disables writes to IRQ/DMA reg + gus_select_voice (0); /* + * This disables writes to IRQ/DMA reg */ - gusintr (0); /* - * Serve pending interrupts + gusintr (0); /* + * Serve pending interrupts */ RESTORE_INTR (flags); } @@ -1048,13 +1068,13 @@ if (sample_no < 0) { printk ("GUS: Undefined patch %d for voice %d\n", instr_no, voice); - return RET_ERROR (EINVAL); /* - * Patch not defined + return RET_ERROR (EINVAL);/* + * Patch not defined */ } - if (sample_ptrs[sample_no] == -1) /* - * Sample not loaded + if (sample_ptrs[sample_no] == -1) /* + * Sample not loaded */ { printk ("GUS: Sample #%d not loaded for patch %d (voice %d)\n", sample_no, instr_no, voice); @@ -1077,13 +1097,15 @@ DISABLE_INTR (flags); if (voices[voice].volume_irq_mode == VMODE_START_NOTE) - voices[voice].kill_pending = 1; + { + voices[voice].kill_pending = 1; + RESTORE_INTR (flags); + } else { - gus_select_voice (voice); + RESTORE_INTR (flags); gus_voice_fade (voice); } - RESTORE_INTR (flags); return 0; } @@ -1094,16 +1116,16 @@ short lo_limit, hi_limit; unsigned long flags; - return; /* - * Currently disabled + return; /* + * Currently disabled */ if (voice < 0 || voice > 31) return; if (voices[voice].mode & WAVE_ENVELOPES && voices[voice].env_phase != 2) - return; /* - * Don't mix with envelopes + return; /* + * Don't mix with envelopes */ if (pressure < 32) @@ -1111,8 +1133,8 @@ DISABLE_INTR (flags); gus_select_voice (voice); gus_rampoff (); - compute_and_set_volume (voice, 255, 0); /* - * Back to original volume + compute_and_set_volume (voice, 255, 0); /* + * Back to original volume */ RESTORE_INTR (flags); return; @@ -1132,8 +1154,8 @@ } gus_ramp_range (lo_limit, hi_limit); gus_ramp_rate (3, 8); - gus_rampon (0x58); /* - * Bidirectional, Down, Loop + gus_rampon (0x58); /* + * Bidirectional, Down, Loop */ RESTORE_INTR (flags); } @@ -1146,24 +1168,36 @@ } static void +guswave_volume_method (int dev, int mode) +{ + if (mode == VOL_METHOD_LINEAR || mode == VOL_METHOD_ADAGIO) + volume_method = mode; +} + +static void compute_volume (int voice, int volume) { if (volume < 128) voices[voice].midi_volume = volume; - switch (volume_method) - { - case VOL_METHOD_ADAGIO: - voices[voice].initial_volume = - gus_adagio_vol (voices[voice].midi_volume, voices[voice].main_vol, - voices[voice].expression_vol, - voices[voice].patch_vol); - break; + switch (volume_method) + { + case VOL_METHOD_ADAGIO: + voices[voice].initial_volume = + gus_adagio_vol (voices[voice].midi_volume, voices[voice].main_vol, + voices[voice].expression_vol, + voices[voice].patch_vol); + break; - default: - voices[voice].initial_volume = volume_base + - (voices[voice].midi_volume * volume_scale); - } + case VOL_METHOD_LINEAR: /* Totally ignores patch-volume and expression */ + voices[voice].initial_volume = + gus_linear_vol (volume, voices[voice].main_vol); + break; + + default: + voices[voice].initial_volume = volume_base + + (voices[voice].midi_volume * volume_scale); + } if (voices[voice].initial_volume > 4030) voices[voice].initial_volume = 4030; @@ -1175,16 +1209,16 @@ int current, target, rate; unsigned long flags; + compute_volume (voice, volume); + voices[voice].current_volume = voices[voice].initial_volume; + DISABLE_INTR (flags); -/* + /* * CAUTION! Interrupts disabled. Enable them before returning */ gus_select_voice (voice); - compute_volume (voice, volume); - voices[voice].current_volume = voices[voice].initial_volume; - current = gus_read16 (0x09) >> 4; target = voices[voice].initial_volume; @@ -1202,8 +1236,8 @@ rate = 16; gus_ramp_rate (0, rate); - if ((target - current) / 64 == 0) /* - * Too close + if ((target - current) / 64 == 0) /* + * Too close */ { gus_rampoff (); @@ -1217,8 +1251,8 @@ if (target > (4095 - 65)) target = 4095 - 65; gus_ramp_range (current, target); - gus_rampon (0x00); /* - * Ramp up, once, no irq + gus_rampon (0x00); /* + * Ramp up, once, no irq */ } else @@ -1227,8 +1261,8 @@ target = 65; gus_ramp_range (target, current); - gus_rampon (0x40); /* - * Ramp down, once, no irq + gus_rampon (0x40); /* + * Ramp down, once, no irq */ } RESTORE_INTR (flags); @@ -1242,14 +1276,14 @@ DISABLE_INTR (flags); gus_select_voice (voice); - status = gus_read8 (0x00); /* - * Voice status + status = gus_read8 (0x00); /* + * Voice status */ RESTORE_INTR (flags); if (status & 0x03) - return; /* - * Voice not started + return; /* + * Voice not started */ if (!(voices[voice].mode & WAVE_ENVELOPES)) @@ -1258,19 +1292,19 @@ return; } - /* + /* * Voice is running and has envelopes. */ DISABLE_INTR (flags); gus_select_voice (voice); - status = gus_read8 (0x0d); /* - * Ramping status + status = gus_read8 (0x0d); /* + * Ramping status */ RESTORE_INTR (flags); - if (status & 0x03) /* - * Sustain phase? + if (status & 0x03) /* + * Sustain phase? */ { compute_and_set_volume (voice, voices[voice].midi_volume, 1); @@ -1282,11 +1316,11 @@ compute_volume (voice, voices[voice].midi_volume); -#if 0 /* - * * * Is this really required */ +#if 0 /* + * * * Is this really required */ voices[voice].current_volume = - gus_read16 (0x09) >> 4; /* - * Get current volume + gus_read16 (0x09) >> 4; /* + * Get current volume */ voices[voice].env_phase--; @@ -1309,15 +1343,15 @@ voices[voice].bender = value; if (voices[voice].volume_irq_mode != VMODE_START_NOTE) - { - freq = compute_finetune (voices[voice].orig_freq, value, voices[voice].bender_range); - voices[voice].current_freq = freq; - - DISABLE_INTR (flags); - gus_select_voice (voice); - gus_voice_freq (freq); - RESTORE_INTR (flags); - } + { + freq = compute_finetune (voices[voice].orig_freq, value, voices[voice].bender_range); + voices[voice].current_freq = freq; + + DISABLE_INTR (flags); + gus_select_voice (voice); + gus_voice_freq (freq); + RESTORE_INTR (flags); + } break; case CTRL_PITCH_BENDER_RANGE: @@ -1328,10 +1362,12 @@ value /= 128; #endif case CTRL_EXPRESSION: - volume_method = VOL_METHOD_ADAGIO; - voices[voice].expression_vol = value; - if (voices[voice].volume_irq_mode != VMODE_START_NOTE) - dynamic_volume_change (voice); + if (volume_method == VOL_METHOD_ADAGIO) + { + voices[voice].expression_vol = value; + if (voices[voice].volume_irq_mode != VMODE_START_NOTE) + dynamic_volume_change (voice); + } break; #ifdef FUTURE_VERSION @@ -1344,14 +1380,13 @@ #endif case CTRL_MAIN_VOLUME: - volume_method = VOL_METHOD_ADAGIO; voices[voice].main_vol = value; if (voices[voice].volume_irq_mode != VMODE_START_NOTE) - dynamic_volume_change (voice); + dynamic_volume_change (voice); break; - default: /* - * Ignore + default: /* + * Ignore */ break; } @@ -1396,7 +1431,7 @@ note_freq = note_to_freq (note_num); - /* + /* * Find a sample within a patch so that the note_freq is between low_note * and high_note. */ @@ -1417,8 +1452,8 @@ if (samples[samplep].low_note <= note_freq && note_freq <= samples[samplep].high_note) sample = samplep; else - samplep = samples[samplep].key; /* - * Follow link + samplep = samples[samplep].key; /* + * Follow link */ } if (sample == -1) @@ -1427,15 +1462,15 @@ if (sample == -1) { printk ("GUS: Patch %d not defined for note %d\n", patch, note_num); - return 0; /* - * Should play default patch ??? + return 0; /* + * Should play default patch ??? */ } - is16bits = (samples[sample].mode & WAVE_16_BITS) ? 1 : 0; /* + is16bits = (samples[sample].mode & WAVE_16_BITS) ? 1 : 0; /* * 8 or 16 * bit - * samples + * samples */ voices[voice].mode = samples[sample].mode; voices[voice].patch_vol = samples[sample].volume; @@ -1453,8 +1488,8 @@ sample_map[voice] = sample; - base_note = samples[sample].base_note / 100; /* - * To avoid overflows + base_note = samples[sample].base_note / 100; /* + * To avoid overflows */ note_freq /= 100; @@ -1462,7 +1497,7 @@ voices[voice].orig_freq = freq; - /* + /* * Since the pitch bender may have been set before playing the note, we * have to calculate the bending now. */ @@ -1479,8 +1514,8 @@ if (samples[sample].mode & WAVE_16_BITS) { - mode |= 0x04; /* - * 16 bits + mode |= 0x04; /* + * 16 bits */ if ((sample_ptrs[sample] >> 18) != ((sample_ptrs[sample] + samples[sample].len) >> 18)) @@ -1493,10 +1528,13 @@ DISABLE_INTR (flags); gus_select_voice (voice); - gus_voice_off (); /* - * It may still be running + gus_voice_off (); /* + * It may still be running */ gus_rampoff (); + + RESTORE_INTR (flags); + if (voices[voice].mode & WAVE_ENVELOPES) { compute_volume (voice, volume); @@ -1505,6 +1543,9 @@ else compute_and_set_volume (voice, volume, 0); + DISABLE_INTR (flags); + gus_select_voice (voice); + if (samples[sample].mode & WAVE_LOOP_BACK) gus_write_addr (0x0a, sample_ptrs[sample] + samples[sample].len - voices[voice].offset_pending, is16bits); /* Sample @@ -1515,13 +1556,13 @@ if (samples[sample].mode & WAVE_LOOPING) { - mode |= 0x08; /* - * Looping on + mode |= 0x08; /* + * Looping on */ if (samples[sample].mode & WAVE_BIDIR_LOOP) - mode |= 0x10; /* - * Bidirectional looping on + mode |= 0x10; /* + * Bidirectional looping on */ if (samples[sample].mode & WAVE_LOOP_BACK) @@ -1532,35 +1573,35 @@ mode |= 0x40; } - gus_write_addr (0x02, sample_ptrs[sample] + samples[sample].loop_start, is16bits); /* - * Loop - * start - * location + gus_write_addr (0x02, sample_ptrs[sample] + samples[sample].loop_start, is16bits); /* + * Loop + * start + * location */ - gus_write_addr (0x04, sample_ptrs[sample] + samples[sample].loop_end, is16bits); /* - * Loop - * end - * location + gus_write_addr (0x04, sample_ptrs[sample] + samples[sample].loop_end, is16bits); /* + * Loop + * end + * location */ } else { - mode |= 0x20; /* - * Loop irq at the end + mode |= 0x20; /* + * Loop irq at the end */ - voices[voice].loop_irq_mode = LMODE_FINISH; /* + voices[voice].loop_irq_mode = LMODE_FINISH; /* * Ramp it down at - * the * end + * the * end */ voices[voice].loop_irq_parm = 1; - gus_write_addr (0x02, sample_ptrs[sample], is16bits); /* - * Loop start - * location + gus_write_addr (0x02, sample_ptrs[sample], is16bits); /* + * Loop start + * location */ - gus_write_addr (0x04, sample_ptrs[sample] + samples[sample].len-1, is16bits); /* - * Loop - * end - * location + gus_write_addr (0x04, sample_ptrs[sample] + samples[sample].len - 1, is16bits); /* + * Loop + * end + * location */ } gus_voice_freq (freq); @@ -1571,9 +1612,9 @@ return 0; } -/* +/* * * New guswave_start_note by Andrew J. Robinson attempts to minimize - * clicking * when the note playing on the voice is changed. It uses volume + * clicking * when the note playing on the voice is changed. It uses volume * ramping. */ static int @@ -1589,26 +1630,31 @@ if (voices[voice].volume_irq_mode == VMODE_START_NOTE) voices[voice].volume_pending = volume; else - ret_val = guswave_start_note2 (dev, voice, note_num, volume); + { + RESTORE_INTR (flags); + ret_val = guswave_start_note2 (dev, voice, note_num, volume); + } } else { - gus_select_voice (voice); - mode = gus_read8 (0x00); - if (mode & 0x20) - gus_write8 (0x00, mode & 0xdf); /* No interrupt! */ - - voices[voice].offset_pending = 0; - voices[voice].kill_pending = 0; - voices[voice].volume_irq_mode = 0; - voices[voice].loop_irq_mode = 0; - - if (voices[voice].sample_pending >= 0) - { - guswave_set_instr (voices[voice].dev_pending, voice, - voices[voice].sample_pending); - voices[voice].sample_pending = -1; - } + gus_select_voice (voice); + mode = gus_read8 (0x00); + if (mode & 0x20) + gus_write8 (0x00, mode & 0xdf); /* No interrupt! */ + + voices[voice].offset_pending = 0; + voices[voice].kill_pending = 0; + voices[voice].volume_irq_mode = 0; + voices[voice].loop_irq_mode = 0; + + if (voices[voice].sample_pending >= 0) + { + RESTORE_INTR (flags); + guswave_set_instr (voices[voice].dev_pending, voice, + voices[voice].sample_pending); + voices[voice].sample_pending = -1; + DISABLE_INTR (flags); + } if ((mode & 0x01) || ((gus_read16 (0x09) >> 4) < 2065)) { @@ -1623,11 +1669,11 @@ gus_rampoff (); gus_ramp_range (2000, 4065); - gus_ramp_rate (0, 63); /* Fastest possible rate */ + gus_ramp_rate (0, 63);/* Fastest possible rate */ gus_rampon (0x20 | 0x40); /* Ramp down, once, irq */ + RESTORE_INTR (flags); } } - RESTORE_INTR (flags); return ret_val; } @@ -1685,10 +1731,10 @@ unsigned long blk_size, blk_end, left, src_offs, target; - sizeof_patch = (long) &patch.data[0] - (long) &patch; /* + sizeof_patch = (long) &patch.data[0] - (long) &patch; /* * Size of * the header - * * info + * * info */ if (format != GUS_PATCH) @@ -1711,7 +1757,7 @@ return RET_ERROR (ENOSPC); } - /* + /* * Copy the header from user space but ignore the first bytes which have * been transferred already. */ @@ -1754,15 +1800,15 @@ } } - free_mem_ptr = (free_mem_ptr + 31) & ~31; /* - * Alignment 32 bytes + free_mem_ptr = (free_mem_ptr + 31) & ~31; /* + * Alignment 32 bytes */ #define GUS_BANK_SIZE (256*1024) if (patch.mode & WAVE_16_BITS) { - /* + /* * 16 bit samples must fit one 256k bank. */ if (patch.len >= GUS_BANK_SIZE) @@ -1774,16 +1820,16 @@ if ((free_mem_ptr / GUS_BANK_SIZE) != ((free_mem_ptr + patch.len) / GUS_BANK_SIZE)) { - unsigned long tmp_mem = /* - * Align to 256K*N + unsigned long tmp_mem = /* + * Align to 256K*N */ ((free_mem_ptr / GUS_BANK_SIZE) + 1) * GUS_BANK_SIZE; if ((tmp_mem + patch.len) > gus_mem_size) return RET_ERROR (ENOSPC); - free_mem_ptr = tmp_mem; /* - * This leaves unusable memory + free_mem_ptr = tmp_mem; /* + * This leaves unusable memory */ } } @@ -1793,8 +1839,8 @@ sample_ptrs[free_sample] = free_mem_ptr; - /* - * Tremolo is not possible with envelopes + /* + * Tremolo is not possible with envelopes */ if (patch.mode & WAVE_ENVELOPES) @@ -1802,14 +1848,14 @@ memcpy ((char *) &samples[free_sample], &patch, sizeof_patch); - /* + /* * Link this_one sample to the list of samples for patch 'instr'. */ samples[free_sample].key = patch_table[instr]; patch_table[instr] = free_sample; - /* + /* * Use DMA to transfer the wave data to the DRAM */ @@ -1817,22 +1863,22 @@ src_offs = 0; target = free_mem_ptr; - while (left) /* - * Not all moved + while (left) /* + * Not all moved */ { blk_size = sound_buffsizes[gus_devnum]; if (blk_size > left) blk_size = left; - /* + /* * DMA cannot cross 256k bank boundaries. Check for that. */ blk_end = target + blk_size; if ((target >> 18) != (blk_end >> 18)) - { /* - * Have to split the block + { /* + * Have to split the block */ blk_end &= ~(256 * 1024 - 1); @@ -1840,7 +1886,7 @@ } #if defined(GUS_NO_DMA) || defined(GUS_PATCH_NO_DMA) - /* + /* * For some reason the DMA is not possible. We have to use PIO. */ { @@ -1853,20 +1899,20 @@ if (patch.mode & WAVE_UNSIGNED) if (!(patch.mode & WAVE_16_BITS) || (i & 0x01)) - data ^= 0x80; /* - * Convert to signed + data ^= 0x80; /* + * Convert to signed */ gus_poke (target + i, data); } } -#else /* - * * * GUS_NO_DMA */ +#else /* + * * * GUS_NO_DMA */ { unsigned long address, hold_address; unsigned char dma_command; unsigned long flags; - /* + /* * OK, move now. First in and then out. */ @@ -1875,13 +1921,13 @@ blk_size); DISABLE_INTR (flags); /******** INTERRUPTS DISABLED NOW ********/ - gus_write8 (0x41, 0); /* - * Disable GF1 DMA + gus_write8 (0x41, 0); /* + * Disable GF1 DMA */ DMAbuf_start_dma (gus_devnum, snd_raw_buf_phys[gus_devnum][0], blk_size, DMA_MODE_WRITE); - /* + /* * Set the DRAM address for the wave data */ @@ -1895,35 +1941,35 @@ address |= (hold_address & 0x000c0000L); } - gus_write16 (0x42, (address >> 4) & 0xffff); /* - * DRAM DMA address + gus_write16 (0x42, (address >> 4) & 0xffff); /* + * DRAM DMA address */ - /* + /* * Start the DMA transfer */ - dma_command = 0x21; /* - * IRQ enable, DMA start + dma_command = 0x21; /* + * IRQ enable, DMA start */ if (patch.mode & WAVE_UNSIGNED) - dma_command |= 0x80; /* - * Invert MSB + dma_command |= 0x80; /* + * Invert MSB */ if (patch.mode & WAVE_16_BITS) - dma_command |= 0x40; /* - * 16 bit _DATA_ + dma_command |= 0x40; /* + * 16 bit _DATA_ */ if (sound_dsp_dmachan[gus_devnum] > 3) - dma_command |= 0x04; /* - * 16 bit DMA channel + dma_command |= 0x04; /* + * 16 bit DMA channel */ - gus_write8 (0x41, dma_command); /* - * Let's go luteet (=bugs) + gus_write8 (0x41, dma_command); /* + * Let's go luteet (=bugs) */ - /* + /* * Sleep here until the DRAM DMA done interrupt is served */ active_device = GUS_DEV_WAVE; @@ -1933,10 +1979,10 @@ printk ("GUS: DMA Transfer timed out\n"); RESTORE_INTR (flags); } -#endif /* - * * * GUS_NO_DMA */ +#endif /* + * * * GUS_NO_DMA */ - /* + /* * Now the next part */ @@ -1944,8 +1990,8 @@ src_offs += blk_size; target += blk_size; - gus_write8 (0x41, 0); /* - * Stop DMA + gus_write8 (0x41, 0); /* + * Stop DMA */ } @@ -1991,8 +2037,8 @@ case _GUS_VOICEON: DISABLE_INTR (flags); gus_select_voice (voice); - p1 &= ~0x20; /* - * Disable intr + p1 &= ~0x20; /* + * Disable intr */ gus_voice_on (p1); RESTORE_INTR (flags); @@ -2006,17 +2052,14 @@ break; case _GUS_VOICEFADE: - DISABLE_INTR (flags); - gus_select_voice (voice); gus_voice_fade (voice); - RESTORE_INTR (flags); break; case _GUS_VOICEMODE: DISABLE_INTR (flags); gus_select_voice (voice); - p1 &= ~0x20; /* - * Disable intr + p1 &= ~0x20; /* + * Disable intr */ gus_voice_mode (p1); RESTORE_INTR (flags); @@ -2043,8 +2086,8 @@ RESTORE_INTR (flags); break; - case _GUS_VOICEVOL2: /* - * Just update the voice value + case _GUS_VOICEVOL2: /* + * Just update the voice value */ voices[voice].initial_volume = voices[voice].current_volume = p1; @@ -2052,8 +2095,8 @@ case _GUS_RAMPRANGE: if (voices[voice].mode & WAVE_ENVELOPES) - break; /* - * NO-NO + break; /* + * NO-NO */ DISABLE_INTR (flags); gus_select_voice (voice); @@ -2063,8 +2106,8 @@ case _GUS_RAMPRATE: if (voices[voice].mode & WAVE_ENVELOPES) - break; /* - * NO-NO + break; /* + * NO-NO */ DISABLE_INTR (flags); gus_select_voice (voice); @@ -2074,13 +2117,13 @@ case _GUS_RAMPMODE: if (voices[voice].mode & WAVE_ENVELOPES) - break; /* - * NO-NO + break; /* + * NO-NO */ DISABLE_INTR (flags); gus_select_voice (voice); - p1 &= ~0x20; /* - * Disable intr + p1 &= ~0x20; /* + * Disable intr */ gus_ramp_mode (p1); RESTORE_INTR (flags); @@ -2088,13 +2131,13 @@ case _GUS_RAMPON: if (voices[voice].mode & WAVE_ENVELOPES) - break; /* - * NO-NO + break; /* + * NO-NO */ DISABLE_INTR (flags); gus_select_voice (voice); - p1 &= ~0x20; /* - * Disable intr + p1 &= ~0x20; /* + * Disable intr */ gus_rampon (p1); RESTORE_INTR (flags); @@ -2102,8 +2145,8 @@ case _GUS_RAMPOFF: if (voices[voice].mode & WAVE_ENVELOPES) - break; /* - * NO-NO + break; /* + * NO-NO */ DISABLE_INTR (flags); gus_select_voice (voice); @@ -2212,8 +2255,8 @@ return gus_sampling_bits; return IOCTL_OUT (arg, gus_sampling_bits); - case SOUND_PCM_WRITE_FILTER: /* - * NOT YET IMPLEMENTED + case SOUND_PCM_WRITE_FILTER: /* + * NOT YET IMPLEMENTED */ return IOCTL_OUT (arg, RET_ERROR (EINVAL)); break; @@ -2255,11 +2298,11 @@ pcm_active = 0; pcm_opened = 1; - if (mode & OPEN_READ) - { - recording_active = 1; - set_input_volumes(); - } + if (mode & OPEN_READ) + { + recording_active = 1; + set_input_volumes (); + } return 0; } @@ -2273,7 +2316,7 @@ active_device = 0; if (recording_active) - set_input_volumes(); + set_input_volumes (); recording_active = 0; } @@ -2313,14 +2356,14 @@ for (chn = 0; chn < gus_sampling_channels; chn++) { mode[chn] = 0x00; - ramp_mode[chn] = 0x03; /* - * Ramping and rollover off + ramp_mode[chn] = 0x03; /* + * Ramping and rollover off */ if (chn == 0) { - mode[chn] |= 0x20; /* - * Loop irq + mode[chn] |= 0x20; /* + * Loop irq */ voices[chn].loop_irq_mode = LMODE_PCM; } @@ -2328,8 +2371,8 @@ if (gus_sampling_bits != 8) { is16bits = 1; - mode[chn] |= 0x04; /* - * 16 bit data + mode[chn] |= 0x04; /* + * 16 bit data */ } else @@ -2338,22 +2381,22 @@ dram_loc = this_one * pcm_bsize; dram_loc += chn * pcm_banksize; - if (this_one == (pcm_nblk - 1)) /* - * Last of the DRAM buffers + if (this_one == (pcm_nblk - 1)) /* + * Last of the DRAM buffers */ { - mode[chn] |= 0x08; /* - * Enable loop + mode[chn] |= 0x08; /* + * Enable loop */ - ramp_mode[chn] = 0x03; /* - * Disable rollover + ramp_mode[chn] = 0x03;/* + * Disable rollover */ } else { if (chn == 0) - ramp_mode[chn] = 0x04; /* - * Enable rollover bit + ramp_mode[chn] = 0x04; /* + * Enable rollover bit */ } @@ -2362,89 +2405,89 @@ gus_voice_freq (speed); if (gus_sampling_channels == 1) - gus_voice_balance (7); /* - * mono + gus_voice_balance (7); /* + * mono */ else if (chn == 0) - gus_voice_balance (0); /* - * left + gus_voice_balance (0); /* + * left */ else - gus_voice_balance (15); /* - * right + gus_voice_balance (15); /* + * right */ - if (!pcm_active) /* - * Voice not started yet + if (!pcm_active) /* + * Voice not started yet */ { - /* + /* * The playback was not started yet (or there has been a pause). * Start the voice (again) and ask for a rollover irq at the end of * this_one block. If this_one one is last of the buffers, use just * the normal loop with irq. */ - gus_voice_off (); /* - * It could already be running + gus_voice_off (); /* + * It could already be running */ gus_rampoff (); gus_voice_volume (1530 + (25 * gus_pcm_volume)); gus_ramp_range (65, 1530 + (25 * gus_pcm_volume)); - gus_write_addr (0x0a, dram_loc, is16bits); /* - * Starting position + gus_write_addr (0x0a, dram_loc, is16bits); /* + * Starting position */ - gus_write_addr (0x02, chn * pcm_banksize, is16bits); /* - * Loop start - * location + gus_write_addr (0x02, chn * pcm_banksize, is16bits); /* + * Loop start + * location */ if (chn != 0) gus_write_addr (0x04, pcm_banksize + (pcm_bsize * pcm_nblk), - is16bits); /* - * Loop end location + is16bits); /* + * Loop end location */ } if (chn == 0) - gus_write_addr (0x04, dram_loc + pcm_datasize[this_one], is16bits); /* - * Loop - * end - * location + gus_write_addr (0x04, dram_loc + pcm_datasize[this_one], is16bits); /* + * Loop + * end + * location */ else - mode[chn] |= 0x08; /* - * Enable loop + mode[chn] |= 0x08; /* + * Enable loop */ if (pcm_datasize[this_one] != pcm_bsize) { - /* - * Incomplete block. Possibly the last one. + /* + * Incomplete block. Possibly the last one. */ if (chn == 0) { - mode[chn] &= ~0x08; /* - * Disable loop + mode[chn] &= ~0x08; /* + * Disable loop */ - mode[chn] |= 0x20; /* - * Enable loop IRQ + mode[chn] |= 0x20;/* + * Enable loop IRQ */ voices[0].loop_irq_mode = LMODE_PCM_STOP; - ramp_mode[chn] = 0x03; /* - * No rollover bit + ramp_mode[chn] = 0x03; /* + * No rollover bit */ } else { - gus_write_addr (0x04, dram_loc + pcm_datasize[this_one], is16bits); /* - * Loop - * end - * location + gus_write_addr (0x04, dram_loc + pcm_datasize[this_one], is16bits); /* + * Loop + * end + * location */ - mode[chn] &= ~0x08; /* - * Disable loop + mode[chn] &= ~0x08; /* + * Disable loop */ } } @@ -2468,11 +2511,11 @@ gus_transfer_output_block (int dev, unsigned long buf, int total_count, int intrflag, int chn) { - /* + /* * This routine transfers one block of audio data to the DRAM. In mono mode * it's called just once. When in stereo mode, this_one routine is called * once for both channels. - * + * * The left/mono channel data is transferred to the beginning of dram and the * right data to the area pointed by gus_page_size. */ @@ -2499,8 +2542,8 @@ else this_one = pcm_current_block; - gus_write8 (0x41, 0); /* - * Disable GF1 DMA + gus_write8 (0x41, 0); /* + * Disable GF1 DMA */ DMAbuf_start_dma (dev, buf + (chn * count), count, DMA_MODE_WRITE); @@ -2515,38 +2558,38 @@ address |= (hold_address & 0x000c0000L); } - gus_write16 (0x42, (address >> 4) & 0xffff); /* - * DRAM DMA address + gus_write16 (0x42, (address >> 4) & 0xffff); /* + * DRAM DMA address */ - dma_command = 0x21; /* - * IRQ enable, DMA start + dma_command = 0x21; /* + * IRQ enable, DMA start */ if (gus_sampling_bits != 8) - dma_command |= 0x40; /* - * 16 bit _DATA_ + dma_command |= 0x40; /* + * 16 bit _DATA_ */ else - dma_command |= 0x80; /* - * Invert MSB + dma_command |= 0x80; /* + * Invert MSB */ if (sound_dsp_dmachan[dev] > 3) - dma_command |= 0x04; /* - * 16 bit DMA channel + dma_command |= 0x04; /* + * 16 bit DMA channel */ - gus_write8 (0x41, dma_command); /* - * Kick on + gus_write8 (0x41, dma_command); /* + * Kick on */ - if (chn == (gus_sampling_channels - 1)) /* - * Last channel + if (chn == (gus_sampling_channels - 1)) /* + * Last channel */ { - /* - * Last (right or mono) channel data + /* + * Last (right or mono) channel data */ active_device = GUS_DEV_PCM_DONE; if (!pcm_active && (pcm_qlen > 2 || count < pcm_bsize)) @@ -2554,9 +2597,9 @@ play_next_pcm_block (); } } - else /* - * * * Left channel data. The right channel - * is * * * transferred after DMA interrupt */ + else /* + * * * Left channel data. The right channel + * is * * * transferred after DMA interrupt */ active_device = GUS_DEV_PCM_CONTINUE; RESTORE_INTR (flags); @@ -2584,20 +2627,20 @@ DMAbuf_start_dma (dev, buf, count, DMA_MODE_READ); - mode = 0xa0; /* - * DMA IRQ enable, invert MSB + mode = 0xa0; /* + * DMA IRQ enable, invert MSB */ if (sound_dsp_dmachan[dev] > 3) - mode |= 0x04; /* - * 16 bit DMA channel + mode |= 0x04; /* + * 16 bit DMA channel */ if (gus_sampling_channels > 1) - mode |= 0x02; /* - * Stereo + mode |= 0x02; /* + * Stereo */ - mode |= 0x01; /* - * DMA enable + mode |= 0x01; /* + * DMA enable */ gus_write8 (0x49, mode); @@ -2612,8 +2655,8 @@ rate = (9878400 / (gus_sampling_speed + 2)) / 16; - gus_write8 (0x48, rate & 0xff); /* - * Set sampling frequency + gus_write8 (0x48, rate & 0xff); /* + * Set sampling frequency */ if (gus_sampling_bits != 8) @@ -2716,6 +2759,7 @@ static struct audio_operations gus_sampling_operations = { "Gravis UltraSound", + NEEDS_RESTART, gus_sampling_open, gus_sampling_close, gus_sampling_output_block, @@ -2745,6 +2789,7 @@ gus_voice_freq (freq); RESTORE_INTR (flags); } + #endif static int @@ -2776,8 +2821,8 @@ while (ptr >= 0 && ptr < free_sample) { rec->data.data8[i]++; - ptr = samples[ptr].key; /* - * Follow link + ptr = samples[ptr].key; /* + * Follow link */ } } @@ -2793,8 +2838,8 @@ while (ptr >= 0 && ptr < free_sample) { rec->data.data32[n++] = ptr; - ptr = samples[ptr].key; /* - * Follow link + ptr = samples[ptr].key; /* + * Follow link */ } } @@ -2815,11 +2860,11 @@ pat = (struct patch_info *) rec->data.data8; - pat->key = GUS_PATCH; /* - * Restore patch type + pat->key = GUS_PATCH; /* + * Restore patch type */ - rec->parm1 = sample_ptrs[ptr]; /* - * DRAM address + rec->parm1 = sample_ptrs[ptr]; /* + * DRAM address */ rec->parm2 = sizeof (struct patch_info); } @@ -2836,13 +2881,13 @@ pat = (struct patch_info *) rec->data.data8; - if (pat->len > samples[ptr].len) /* - * Cannot expand sample + if (pat->len > samples[ptr].len) /* + * Cannot expand sample */ return RET_ERROR (EINVAL); - pat->key = samples[ptr].key; /* - * Ensure the link is correct + pat->key = samples[ptr].key; /* + * Ensure the link is correct */ memcpy ((char *) &samples[ptr], rec->data.data8, @@ -2853,8 +2898,8 @@ return 0; break; - case PM_READ_PATCH: /* - * Returns a block of wave data from the DRAM + case PM_READ_PATCH: /* + * Returns a block of wave data from the DRAM */ { int sample = rec->parm1; @@ -2866,12 +2911,12 @@ return RET_ERROR (EINVAL); if (offs < 0 || offs >= samples[sample].len) - return RET_ERROR (EINVAL); /* - * Invalid offset + return RET_ERROR (EINVAL); /* + * Invalid offset */ - n = samples[sample].len - offs; /* - * Nr of bytes left + n = samples[sample].len - offs; /* + * Nr of bytes left */ if (l > n) @@ -2881,25 +2926,25 @@ l = sizeof (rec->data.data8); if (l <= 0) - return RET_ERROR (EINVAL); /* - * Was there a bug? + return RET_ERROR (EINVAL); /* + * Was there a bug? */ - offs += sample_ptrs[sample]; /* - * Begin offsess + offset to DRAM + offs += sample_ptrs[sample]; /* + * Begin offsess + offset to DRAM */ for (n = 0; n < l; n++) rec->data.data8[n] = gus_peek (offs++); - rec->parm1 = n; /* - * Nr of bytes copied + rec->parm1 = n; /* + * Nr of bytes copied */ } return 0; break; - case PM_WRITE_PATCH: /* - * Writes a block of wave data to the DRAM + case PM_WRITE_PATCH: /* + * Writes a block of wave data to the DRAM */ { int sample = rec->parm1; @@ -2911,12 +2956,12 @@ return RET_ERROR (EINVAL); if (offs < 0 || offs >= samples[sample].len) - return RET_ERROR (EINVAL); /* - * Invalid offset + return RET_ERROR (EINVAL); /* + * Invalid offset */ - n = samples[sample].len - offs; /* - * Nr of bytes left + n = samples[sample].len - offs; /* + * Nr of bytes left */ if (l > n) @@ -2926,18 +2971,18 @@ l = sizeof (rec->data.data8); if (l <= 0) - return RET_ERROR (EINVAL); /* - * Was there a bug? + return RET_ERROR (EINVAL); /* + * Was there a bug? */ - offs += sample_ptrs[sample]; /* - * Begin offsess + offset to DRAM + offs += sample_ptrs[sample]; /* + * Begin offsess + offset to DRAM */ for (n = 0; n < l; n++) gus_poke (offs++, rec->data.data8[n]); - rec->parm1 = n; /* - * Nr of bytes copied + rec->parm1 = n; /* + * Nr of bytes copied */ } return 0; @@ -2968,6 +3013,7 @@ guswave_aftertouch, guswave_controller, guswave_panning, + guswave_volume_method, guswave_patchmgr, #ifdef FUTURE_VERSION guswave_bender @@ -2975,39 +3021,43 @@ }; static void -set_input_volumes(void) +set_input_volumes (void) { - unsigned long flags; - unsigned char mask = 0xff & ~0x06; /* Just line out enabled */ + unsigned long flags; + unsigned char mask = 0xff & ~0x06; /* Just line out enabled */ - DISABLE_INTR(flags); + DISABLE_INTR (flags); -/* - * Enable channels having vol > 10% - * Note! bit 0x01 means line in DISABLED while 0x04 means - * mic in ENABLED. + /* + * Enable channels having vol > 10% + * Note! bit 0x01 means line in DISABLED while 0x04 means + * mic in ENABLED. */ - if (gus_line_vol > 10) mask &= ~0x01; - if (gus_mic_vol > 10) mask |= 0x04; + if (gus_line_vol > 10) + mask &= ~0x01; + if (gus_mic_vol > 10) + mask |= 0x04; - if (recording_active) - { -/* - * Disable channel, if not selected for recording + if (recording_active) + { + /* + * Disable channel, if not selected for recording */ - if (!(gus_recmask & SOUND_MASK_LINE)) mask |= 0x01; - if (!(gus_recmask & SOUND_MASK_MIC)) mask &= ~0x04; - } + if (!(gus_recmask & SOUND_MASK_LINE)) + mask |= 0x01; + if (!(gus_recmask & SOUND_MASK_MIC)) + mask &= ~0x04; + } - mix_image &= ~0x07; - mix_image |= mask & 0x07; - OUTB (mix_image, u_Mixer); + mix_image &= ~0x07; + mix_image |= mask & 0x07; + OUTB (mix_image, u_Mixer); - RESTORE_INTR(flags); + RESTORE_INTR (flags); } -static int -gus_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg) +int +gus_default_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg) { #define MIX_DEVS (SOUND_MASK_MIC|SOUND_MASK_LINE| \ SOUND_MASK_SYNTH|SOUND_MASK_PCM) @@ -3017,9 +3067,9 @@ switch (cmd & 0xff) { case SOUND_MIXER_RECSRC: - gus_recmask = IOCTL_IN(arg) & MIX_DEVS; - if (!(gus_recmask & (SOUND_MASK_MIC|SOUND_MASK_LINE))) - gus_recmask = SOUND_MASK_MIC; + gus_recmask = IOCTL_IN (arg) & MIX_DEVS; + if (!(gus_recmask & (SOUND_MASK_MIC | SOUND_MASK_LINE))) + gus_recmask = SOUND_MASK_MIC; /* Note! Input volumes are updated during next open for recording */ return IOCTL_OUT (arg, gus_recmask); break; @@ -3027,10 +3077,13 @@ case SOUND_MIXER_MIC: { int vol = IOCTL_IN (arg) & 0xff; - if (vol < 0) vol = 0; - if (vol > 100) vol = 100; + + if (vol < 0) + vol = 0; + if (vol > 100) + vol = 100; gus_mic_vol = vol; - set_input_volumes(); + set_input_volumes (); return IOCTL_OUT (arg, vol | (vol << 8)); } break; @@ -3038,27 +3091,30 @@ case SOUND_MIXER_LINE: { int vol = IOCTL_IN (arg) & 0xff; - if (vol < 0) vol = 0; - if (vol > 100) vol = 100; + + if (vol < 0) + vol = 0; + if (vol > 100) + vol = 100; gus_line_vol = vol; - set_input_volumes(); + set_input_volumes (); return IOCTL_OUT (arg, vol | (vol << 8)); } break; case SOUND_MIXER_PCM: - gus_pcm_volume = IOCTL_IN (arg) & 0xff; - if (gus_pcm_volume < 0) - gus_pcm_volume = 0; - if (gus_pcm_volume > 100) - gus_pcm_volume = 100; - gus_sampling_update_volume (); - return IOCTL_OUT (arg, gus_pcm_volume | (gus_pcm_volume << 8)); + gus_pcm_volume = IOCTL_IN (arg) & 0xff; + if (gus_pcm_volume < 0) + gus_pcm_volume = 0; + if (gus_pcm_volume > 100) + gus_pcm_volume = 100; + gus_sampling_update_volume (); + return IOCTL_OUT (arg, gus_pcm_volume | (gus_pcm_volume << 8)); break; case SOUND_MIXER_SYNTH: { - int voice; + int voice; gus_wave_volume = IOCTL_IN (arg) & 0xff; @@ -3069,9 +3125,9 @@ if (active_device == GUS_DEV_WAVE) for (voice = 0; voice < nr_voices; voice++) - dynamic_volume_change (voice); /* + dynamic_volume_change (voice); /* * Apply the new - * volume + * volume */ return IOCTL_OUT (arg, gus_wave_volume | (gus_wave_volume << 8)); @@ -3082,8 +3138,8 @@ return RET_ERROR (EINVAL); } else - switch (cmd & 0xff) /* - * Return parameters + switch (cmd & 0xff) /* + * Return parameters */ { @@ -3100,7 +3156,7 @@ break; case SOUND_MIXER_RECMASK: - return IOCTL_OUT (arg, SOUND_MASK_MIC|SOUND_MASK_LINE); + return IOCTL_OUT (arg, SOUND_MASK_MIC | SOUND_MASK_LINE); break; case SOUND_MIXER_CAPS: @@ -3133,13 +3189,93 @@ static struct mixer_operations gus_mixer_operations = { - gus_mixer_ioctl + gus_default_mixer_ioctl }; +static long +gus_default_mixer_init (long mem_start) +{ + if (num_mixers < MAX_MIXER_DEV) /* + * Don't install if there is another + * mixer + */ + mixer_devs[num_mixers++] = &gus_mixer_operations; + + return mem_start; +} + long gus_wave_init (long mem_start, int irq, int dma) { - printk (" ", (int) gus_mem_size / 1024); + unsigned long flags; + unsigned char val; + char *model_num = "2.4"; + int gus_type = 0x24; /* 2.4 */ + int mixer_type = 0; + + /* + * Try to identify the GUS model. + * + * Versions < 3.6 don't have the digital ASIC. Try to probe it first. + */ + + DISABLE_INTR (flags); + OUTB (0x20, gus_base + 0x0f); + val = INB (gus_base + 0x0f); + RESTORE_INTR (flags); + + if (val != 0xff && (val & 0x06)) /* Should be 0x02? */ + { + /* + * It has the digital ASIC so the card is at least v3.4. + * Next try to detect the true model. + */ + + val = INB (u_MixSelect); + + /* + * Value 255 means pre-3.7 which don't have mixer. + * Values 5 thru 9 mean v3.7 which has a ICS2101 mixer. + * 10 and above is GUS MAX which has the CS4231 codec/mixer. + * + * Sorry. No GUS max support yet but it should be available + * soon after the SDK for GUS MAX is available. + */ + + if (val == 255 || val < 5) + { + model_num = "3.4"; + gus_type = 0x34; + } + else if (val < 10) + { + model_num = "3.7"; + gus_type = 0x37; + mixer_type = ICS2101; + } + else + { + model_num = "MAX"; + gus_type = 0x40; + mixer_type = CS4231; + } + } + else + { + /* + * ASIC not detected so the card must be 2.2 or 2.4. + * There could still be the 16-bit/mixer daughter card. + * It has the same codec/mixer than MAX. + * At this time there is no support for it but it will appear soon. + */ + } + + + printk (" ", model_num, (int) gus_mem_size / 1024); + +#ifndef SCO + sprintf (gus_info.name, "Gravis UltraSound %s (%dk)", model_num, (int) gus_mem_size / 1024); +#endif if (irq < 0 || irq > 15) { @@ -3179,11 +3315,21 @@ else printk ("GUS: Too many PCM devices available\n"); - if (num_mixers < MAX_MIXER_DEV) /* - * Don't install if there is another - * mixer - */ - mixer_devs[num_mixers++] = &gus_mixer_operations; + /* + * Mixer dependent initialization. + */ + + switch (mixer_type) + { + case ICS2101: + gus_line_vol=gus_mic_vol=gus_wave_volume = gus_pcm_volume = 100; + return ics2101_mixer_init (mem_start); + + case CS4231: + /* Available soon */ + default: + return gus_default_mixer_init (mem_start); + } return mem_start; } @@ -3199,8 +3345,8 @@ gus_select_voice (voice); tmp = gus_read8 (0x00); - tmp &= ~0x20; /* - * Disable wave IRQ for this_one voice + tmp &= ~0x20; /* + * Disable wave IRQ for this_one voice */ gus_write8 (0x00, tmp); @@ -3211,12 +3357,12 @@ switch (mode) { - case LMODE_FINISH: /* - * Final loop finished, shoot volume down + case LMODE_FINISH: /* + * Final loop finished, shoot volume down */ - if ((gus_read16 (0x09) >> 4) < 100) /* - * Get current volume + if ((gus_read16 (0x09) >> 4) < 100) /* + * Get current volume */ { gus_voice_off (); @@ -3225,18 +3371,18 @@ break; } gus_ramp_range (65, 4065); - gus_ramp_rate (0, 63); /* - * Fastest possible rate + gus_ramp_rate (0, 63); /* + * Fastest possible rate */ - gus_rampon (0x20 | 0x40); /* - * Ramp down, once, irq + gus_rampon (0x20 | 0x40); /* + * Ramp down, once, irq */ voices[voice].volume_irq_mode = VMODE_HALT; break; case LMODE_PCM_STOP: - pcm_active = 0; /* - * Requires extensive processing + pcm_active = 0; /* + * Requires extensive processing */ case LMODE_PCM: { @@ -3249,8 +3395,8 @@ play_next_pcm_block (); } else - { /* - * Out of data. Just stop the voice + { /* + * Out of data. Just stop the voice */ gus_voice_off (); gus_rampoff (); @@ -3281,8 +3427,8 @@ gus_select_voice (voice); tmp = gus_read8 (0x0d); - tmp &= ~0x20; /* - * Disable volume ramp IRQ + tmp &= ~0x20; /* + * Disable volume ramp IRQ */ gus_write8 (0x0d, tmp); @@ -3292,34 +3438,35 @@ switch (mode) { - case VMODE_HALT: /* - * Decay phase finished + case VMODE_HALT: /* + * Decay phase finished */ + RESTORE_INTR (flags); gus_voice_init (voice); break; case VMODE_ENVELOPE: gus_rampoff (); + RESTORE_INTR (flags); step_envelope (voice); break; case VMODE_START_NOTE: + RESTORE_INTR (flags); guswave_start_note2 (voices[voice].dev_pending, voice, voices[voice].note_pending, voices[voice].volume_pending); if (voices[voice].kill_pending) - guswave_kill_note (voices[voice].dev_pending, voice, 0); + guswave_kill_note (voices[voice].dev_pending, voice, 0); if (voices[voice].sample_pending >= 0) - { - guswave_set_instr (voices[voice].dev_pending, voice, - voices[voice].sample_pending); - voices[voice].sample_pending = -1; - } + { + guswave_set_instr (voices[voice].dev_pending, voice, + voices[voice].sample_pending); + voices[voice].sample_pending = -1; + } break; default:; } - - RESTORE_INTR (flags); } void @@ -3332,37 +3479,37 @@ while (1) { - src = gus_read8 (0x0f); /* - * Get source info + src = gus_read8 (0x0f); /* + * Get source info */ voice = src & 0x1f; src &= 0xc0; if (src == (0x80 | 0x40)) - return; /* - * No interrupt + return; /* + * No interrupt */ voice_bit = 1 << voice; - if (!(src & 0x80)) /* - * Wave IRQ pending + if (!(src & 0x80)) /* + * Wave IRQ pending */ - if (!(wave_ignore & voice_bit) && voice < nr_voices) /* + if (!(wave_ignore & voice_bit) && voice < nr_voices) /* * Not done - * yet + * yet */ { wave_ignore |= voice_bit; do_loop_irq (voice); } - if (!(src & 0x40)) /* - * Volume IRQ pending + if (!(src & 0x40)) /* + * Volume IRQ pending */ - if (!(volume_ignore & voice_bit) && voice < nr_voices) /* + if (!(volume_ignore & voice_bit) && voice < nr_voices) /* * Not done - * yet + * yet */ { volume_ignore |= voice_bit; @@ -3376,11 +3523,11 @@ { unsigned char status; - status = gus_look8 (0x41); /* - * Get DMA IRQ Status + status = gus_look8 (0x41); /* + * Get DMA IRQ Status */ - if (status & 0x40) /* - * DMA Irq pending + if (status & 0x40) /* + * DMA Irq pending */ switch (active_device) { @@ -3405,11 +3552,11 @@ default:; } - status = gus_look8 (0x49); /* - * Get Sampling IRQ Status + status = gus_look8 (0x49); /* + * Get Sampling IRQ Status */ - if (status & 0x40) /* - * Sampling Irq pending + if (status & 0x40) /* + * Sampling Irq pending */ { DMAbuf_inputintr (gus_devnum); diff -uNr linux-1.0.9/drivers/sound/ics2101.c linux/drivers/sound/ics2101.c --- linux-1.0.9/drivers/sound/ics2101.c Thu Jan 1 01:00:00 1970 +++ linux/drivers/sound/ics2101.c Mon Apr 1 17:39:34 2002 @@ -0,0 +1,261 @@ +/* + * sound/ics2101.c + * + * Driver for the ICS2101 mixer of GUS v3.7. + * + * Copyright by Hannu Savolainen 1994 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. 2. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include "sound_config.h" +#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_GUS) + +#include "ultrasound.h" +#include "gus_hw.h" + +#define MIX_DEVS (SOUND_MASK_MIC|SOUND_MASK_LINE| \ + SOUND_MASK_SYNTH| \ + SOUND_MASK_CD | SOUND_MASK_VOLUME) + +extern int gus_base; +static int volumes[ICS_MIXDEVS]; +static int left_fix[ICS_MIXDEVS] = +{1, 1, 1, 2, 1, 2}; +static int right_fix[ICS_MIXDEVS] = +{2, 2, 2, 1, 2, 1}; + +static int +scale_vol(int vol) +{ +#if 1 +/* + * Experimental volume scaling by Risto Kankkunen. + * This should give smoother volume response than just + * a plain multiplication. + */ + int e; + + if (vol < 0) + vol = 0; + if (vol > 100) + vol = 100; + vol = (31 * vol + 50) / 100; + e = 0; + if (vol) { + while (vol < 16) { + vol <<= 1; + e--; + } + vol -= 16; + e += 7; + } + return ((e << 4) + vol); +#else + return ((vol*127)+50)/100; +#endif +} + +static void +write_mix (int dev, int chn, int vol) +{ + int *selector; + unsigned long flags; + int ctrl_addr = dev << 3; + int attn_addr = dev << 3; + + vol=scale_vol(vol); + + if (chn == CHN_LEFT) + { + selector = left_fix; + ctrl_addr |= 0x00; + attn_addr |= 0x02; + } + else + { + selector = right_fix; + ctrl_addr |= 0x01; + attn_addr |= 0x03; + } + + DISABLE_INTR (flags); + OUTB (ctrl_addr, u_MixSelect); + OUTB (selector[dev], u_MixData); + OUTB (attn_addr, u_MixSelect); + OUTB ((unsigned char) vol, u_MixData); + RESTORE_INTR (flags); +} + +static int +set_volumes (int dev, int vol) +{ + int left = vol & 0x00ff; + int right = (vol >> 8) & 0x00ff; + + if (left < 0) + left = 0; + if (left > 100) + left = 100; + if (right < 0) + right = 0; + if (right > 100) + right = 100; + + write_mix (dev, CHN_LEFT, left); + write_mix (dev, CHN_RIGHT, right); + + vol = left + (right << 8); + volumes[dev] = vol; + return vol; +} + +static int +ics2101_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg) +{ + if (((cmd >> 8) & 0xff) == 'M') + { + if (cmd & IOC_IN) + switch (cmd & 0xff) + { + case SOUND_MIXER_RECSRC: + return gus_default_mixer_ioctl (dev, cmd, arg); + break; + + case SOUND_MIXER_MIC: + return IOCTL_OUT (arg, set_volumes (DEV_MIC, IOCTL_IN (arg))); + break; + + case SOUND_MIXER_CD: + return IOCTL_OUT (arg, set_volumes (DEV_CD, IOCTL_IN (arg))); + break; + + case SOUND_MIXER_LINE: + return IOCTL_OUT (arg, set_volumes (DEV_LINE, IOCTL_IN (arg))); + break; + + case SOUND_MIXER_SYNTH: + return IOCTL_OUT (arg, set_volumes (DEV_GF1, IOCTL_IN (arg))); + break; + + case SOUND_MIXER_VOLUME: + return IOCTL_OUT (arg, set_volumes (DEV_VOL, IOCTL_IN (arg))); + break; + + default: + return RET_ERROR (EINVAL); + } + else + switch (cmd & 0xff) /* + * Return parameters + */ + { + + case SOUND_MIXER_RECSRC: + return gus_default_mixer_ioctl (dev, cmd, arg); + break; + + case SOUND_MIXER_DEVMASK: + return IOCTL_OUT (arg, MIX_DEVS); + break; + + case SOUND_MIXER_STEREODEVS: + return IOCTL_OUT (arg, SOUND_MASK_LINE | SOUND_MASK_CD | + SOUND_MASK_SYNTH | SOUND_MASK_VOLUME| + SOUND_MASK_MIC); + break; + + case SOUND_MIXER_RECMASK: + return IOCTL_OUT (arg, SOUND_MASK_MIC | SOUND_MASK_LINE); + break; + + case SOUND_MIXER_CAPS: + return IOCTL_OUT (arg, 0); + break; + + case SOUND_MIXER_MIC: + return IOCTL_OUT (arg, volumes[DEV_MIC]); + break; + + case SOUND_MIXER_LINE: + return IOCTL_OUT (arg, volumes[DEV_LINE]); + break; + + case SOUND_MIXER_CD: + return IOCTL_OUT (arg, volumes[DEV_CD]); + break; + + case SOUND_MIXER_VOLUME: + return IOCTL_OUT (arg, volumes[DEV_VOL]); + break; + + case SOUND_MIXER_SYNTH: + return IOCTL_OUT (arg, volumes[DEV_GF1]); + break; + + default: + return RET_ERROR (EINVAL); + } + } + + return RET_ERROR (EINVAL); +} + +static struct mixer_operations ics2101_mixer_operations = +{ + ics2101_mixer_ioctl +}; + +long +ics2101_mixer_init (long mem_start) +{ + int i; + + if (num_mixers < MAX_MIXER_DEV) + { + mixer_devs[num_mixers++] = &ics2101_mixer_operations; + + /* + * Some GUS v3.7 cards had some channels flipped. Disable + * the flipping feature if the model id is other than 5. + */ + + if (INB (u_MixSelect) != 5) + { + for (i = 0; i < ICS_MIXDEVS; i++) + left_fix[i] = 1; + for (i = 0; i < ICS_MIXDEVS; i++) + right_fix[i] = 2; + } + + set_volumes (DEV_GF1, 0x5a5a); + set_volumes (DEV_CD, 0x5a5a); + set_volumes (DEV_MIC, 0x0000); + set_volumes (DEV_LINE, 0x5a5a); + set_volumes (DEV_VOL, 0x5a5a); + set_volumes (DEV_UNUSED, 0x0000); + } + + return mem_start; +} + +#endif diff -uNr linux-1.0.9/drivers/sound/linux/Readme linux/drivers/sound/linux/Readme --- linux-1.0.9/drivers/sound/linux/Readme Thu Jan 1 01:00:00 1970 +++ linux/drivers/sound/linux/Readme Mon Apr 1 17:39:34 2002 @@ -0,0 +1,254 @@ +Sound Driver version 2.5 for Linux +---------------------------------- + +NOTE! The sound driver is now a part of the Linux kernel distribution. + Check that your kernel doesn't have more recent version than this + when installing a separately distributed sound driver. The + version number of this driver is defined in the makefile. + +Installation +------------ + +- Since this driver is a part of the Linux kernel distribution, no + special steps are required to build the driver itself. + +- In case you are installing a separately distributed sound driver, + you have to do some additional steps. + - Remove all files from the linux/drivers/sound. Old files could + sometimes cause trouble. + - cd linux/drivers. + - gunzip -c snd-driv-X.Y.tar.gz|tar xvf - + - cd ./sound + - cp soundcard.h ultrasound.h /usr/include/linux + +- To build the device files for this driver, you need to run the enclosed + shell script (at the end of this file). + +- Create /usr/include/sys/soundcard.h whic contains just a line: +#include + +- Create /usr/include/sys/ultrasound.h whic contains just a line: +#include + +Boot time configuration (using lilo) +------------------------------------ + +This version of the sound driver has capability to accept the configuration +parameters from the boot loader (for example lilo). By default the +driver is booted using the parameters given before compiling the driver +('make config' or 'make soundconf'). If the kernel is booted using lilo and +the boot command is given manually, it's possible to give the configuration +parameters on the command line. Just hold down the key when lilo +starts. Then give the boot command manually and append a sound= argument +to the boot command line. For example: + +lilo boot: linux sound=0x222071,0x138800 + +The sound= argument could contain several configuration entries separated by a +comma. Each option gives the configuration for one sound device. +Give the options in the order given below. Other order of use is undefined. +Each option is encoded as the following: + + 0xTaaaId, where + || || + || |+---- d = DMA channel (0, 1, 3, 5, 6 or 7) + || +----- I = IRQ (HEXADECIMAL!!! 1=1, ..., 9=9, 10=a, ..., 15=f) + |+-------- aaa = I/O address (hexadecimal) + +---------- T = device type 1=FM Synth (YM3812 or OPL3) + 2=SoundBlaster (1.0 to 2.0, Pro, 16) + 3=ProAudioSpectrum16 + 4=Gravis UltraSound + 5=MPU-401 UART midi + 6=SB16 (16 bit DMA number) + 7=SB16 Midi (MPU-401 emulation) + +These are the configuration templates for various soundcards: + + 0) Disable the sound driver + + sound=0 + + 1) AdLib + + sound=0x138800 + + 2) SoundBlaster family and compatibles + + sound=0x2220Id,0x138800 (remember to set the IRQ and DMA) + or if you have SB16 or SB16ASP, you have to use the following: + (use the same IRQ (the I colums) in all three places. The + the D is the 16 bit DMA channel (5 to 7) and the d is + the 8 bit one (1 or 3). The X is the 2nd digit of the + midi IO address (3 or 0)). + sound=0x2220Id,0x6220ID,0x73X0I0,0x138800 + + 3) ProAudioSpectrum16, ProAudioStudio16, Logitech Soundman16 etc. + + sound=0x3388Id,0x2220Id,0x138800 (set the DMAs and IRQs) + + 4) Gravis UltraSound + + sound=0x42X0Id (X is 1, 2, 3 or 4. Set the DMA and IRQ) + + 5) MPU-401 + + sound=0x5aaaI0 + +If you have more than one soundcards, you have to concatenate the options +for each of the cards. There cannot be more than one sound= argument in the +command line. For example use "sound=0x5aaaI0,0x138800" if you have AdLib +and MPU-401 on your system. +If there are two or more sound= arguments +in the boot command line, just the last one takes effect. The earlier ones +will be ignored silently. + +The boot time configuration feature is intended mainly for distributors of +precompiled kernels. When this feature is used, drivers for all of the +cards have to be enabled before compiling the driver. The configurator program +doesn't enable MPU-401 when the full driver option is selected. It must be +enabled by uncommenting "#define EXCLUDE_MPU401" in the sound/local.h. + +Important note! + +The sound driver is enabled by default. If the kernel is booted without +using the sound=0 option, the sound driver is initialized using the compile +time parameters. This could be dangerous (specially if the MPU-401 driver +is enabled with I/O address 0x330 (used by AHA-1542 also)). If you want to +compile the driver to be inactive by default, you have to append a +#define SND_DEFAULT_ENABLE 0 +to the sound/local.h before compiling the driver. + +Remember to check that the sound setup routine is included in the +bootparams structure in linux/init/main.c. It should contain the following +lines: + +#ifdef CONFIG_SOUND + { "sound=", sound_setup }, +#endif + +In case these lines were not there, you have to insert them (the driver works +without them but it's not possible to give the boot time parameters for the +sound driver). Add also the following line somewhere near the beginning of +linux/init/main.c: + +extern void sound_setup(char *str, int *ints); + +Problems +-------- + +If you have any kind of problems, there is a debugging feature which +could help you to solve the problem. To use it, just execute the +command: + + cat /dev/sndstat + +and look at the output. It should display some usefull info about the +driver configuration. If there is no /dev/sndstat +(/dev/sndstat: No such file or directory), ensure that you have executed the +soundinstall script (at the end of this file). The message: +/dev/dsp: No such device means that you don't have the sound driver installed +on your kernel or the driver version is earlier than 1.99.6. + + +- /dev/???????: No such file or directory. +Run the script at the end of this file. + +- /dev/???????: No such device. +You have not booted with a kernel containing the driver or the I/O address +configuration doesn't match your hardaware. + +- The module player (str) plays just a second and then stops completely. +You have incorrect IRQ settings (usual with SB cards). + +- There is pauses in the playback of the module player (str). +The str program requires more than 40% of the speed of a 486/50 to play +without pauses at 44 kHz speed. A 386/25 can hardly play faster than 22 kHz. +You should use lower speed (-s speed), buy a faster computer or a Gravis +UltraSound card. (If you already have GUS, you should use gmod and not the +str). If the DSP_BUFFSIZE in the sound/local.h is less than (nr_channels* +speed_in_Hz * (bits/8))/2, it could explain the pausing problem. Also check +that the turbo swich is on and don't run applications like weather forecasting +on background. Sometimes (very rarely) an IRQ conflict can cause similar +problems with SB cards. +If you want to play modules on a 386sx while recompiling the world, buy a GUS. +It runs without burning your CPU. + +Hannu Savolainen +Hannu.Savolainen@Helsinki.fi +(hannu@voxware.pp.fi (april 94 ->)) + +----------------- cut here ------------------------------ +#!/bin/sh +# +# soudinstall +# +# by Craig Metz - cmetz@thor.tjhsst.edu +# +# Create the devices +# +# Mixer (14, 0) +# +if [ -e /dev/mixer ]; then + rm -f /dev/mixer +fi +mknod -m 666 /dev/mixer c 14 0 + +if [ -e /dev/mixer1 ]; then + rm -f /dev/mixer1 +fi +mknod -m 666 /dev/mixer1 c 14 16 +# +# Sequencer (14, 1) +# +if [ -e /dev/sequencer ]; then + rm -f /dev/sequencer +fi +mknod -m 666 /dev/sequencer c 14 1 +# +# MIDI (14, 2) [ Not implemented ] +# +if [ -e /dev/midi ]; then + rm -f /dev/midi +fi +mknod -m 666 /dev/midi c 14 2 +# +# DSP (14, 3) +# +if [ -e /dev/dsp ]; then + rm -f /dev/dsp +fi +mknod -m 666 /dev/dsp c 14 3 +# +# SPARC audio (14, 4) [ Not fully implemented ] +# +if [ -e /dev/audio ]; then + rm -f /dev/audio +fi +mknod -m 666 /dev/audio c 14 4 +# +# DSP2 (14, 19) /dev/dsp for the second soundcard. +# Also the SB emulation part of the +# PAS16 card. +# +if [ -e /dev/dsp1 ]; then + rm -f /dev/dsp1 +fi +mknod -m 666 /dev/dsp1 c 14 19 +# +# SPARC audio1 (14, 20) [ Not fully implemented ] +# /dev/audio for the second soundcard. +# Also the SB emulation part of the +# PAS16 card. +# +if [ -e /dev/audio1 ]; then + rm -f /dev/audio1 +fi +mknod -m 666 /dev/audio1 c 14 20 +# +# /dev/sndstat (14,6) For debugging purposes +# +if [ -e /dev/sndstat ]; then + rm -f /dev/sndstat +fi +mknod -m 666 /dev/sndstat c 14 6 +exit 0 diff -uNr linux-1.0.9/drivers/sound/linux/os.h linux/drivers/sound/linux/os.h --- linux-1.0.9/drivers/sound/linux/os.h Thu Jan 1 01:00:00 1970 +++ linux/drivers/sound/linux/os.h Mon Apr 1 17:39:34 2002 @@ -0,0 +1,154 @@ +/* + * OS Specific settings for Linux + * + * Copyright by Hannu Savolainen 1993 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#define ALLOW_SELECT + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef char snd_rw_buf; + +#define FALSE 0 +#define TRUE 1 + +#define COPY_FROM_USER(d, s, o, c) memcpy_fromfs((d), &((s)[o]), (c)) +#define COPY_TO_USER(d, o, s, c) memcpy_tofs(&((d)[o]), (s), (c)) +#define IOCTL_FROM_USER(d, s, o, c) memcpy_fromfs((d), &((s)[o]), (c)) +#define IOCTL_TO_USER(d, o, s, c) memcpy_tofs(&((d)[o]), (s), (c)) + +#define GET_BYTE_FROM_USER(target, addr, offs) target = get_fs_byte(&((addr)[offs])) +#define GET_SHORT_FROM_USER(target, addr, offs) target = get_fs_word(&((addr)[offs])) +#define GET_WORD_FROM_USER(target, addr, offs) target = get_fs_long((long*)&((addr)[offs])) +#define PUT_WORD_TO_USER(addr, offs, data) put_fs_long(data, (long*)&((addr)[offs])) +#define IOCTL_IN(arg) get_fs_long((long *)(arg)) +#define IOCTL_OUT(arg, ret) snd_ioctl_return((int *)arg, ret) + +struct snd_wait { + int mode; int aborting; + }; + +#define DEFINE_WAIT_QUEUE(name, flag) static struct wait_queue *name = NULL; \ + static volatile struct snd_wait flag = {0} +#define DEFINE_WAIT_QUEUES(name, flag) static struct wait_queue *name = {NULL}; \ + static volatile struct snd_wait flag = {{0}} +#define RESET_WAIT_QUEUE(q, f) {f.aborting = 0;f.mode = WK_NONE;} +#define PROCESS_ABORTING(q, f) (f.aborting | (current->signal & ~current->blocked)) +#define SET_ABORT_FLAG(q, f) f.aborting = 1 +#define TIMED_OUT(q, f) (f.mode & WK_TIMEOUT) +#define DO_SLEEP(q, f, time_limit) \ + { unsigned long tl;\ + if (time_limit) tl = current->timeout = jiffies + (time_limit); \ + else tl = 0xffffffff; \ + f.mode = WK_SLEEP;interruptible_sleep_on(&q); \ + if (!(f.mode & WK_WAKEUP)) \ + { \ + if (current->signal & ~current->blocked) \ + f.aborting = 1; \ + else \ + if (jiffies >= tl) f.mode |= WK_TIMEOUT; \ + } \ + f.mode &= ~WK_SLEEP; \ + } +#define SOMEONE_WAITING(q, f) (f.mode & WK_SLEEP) +#define WAKE_UP(q, f) {f.mode = WK_WAKEUP;wake_up(&q);} + +#define ALLOC_DMA_CHN(chn) request_dma(chn) +#define RELEASE_DMA_CHN(chn) free_dma(chn) + +#define GET_TIME() jiffies +#define RELEASE_IRQ free_irq +#define RET_ERROR(err) -err + +/* DISABLE_INTR is used to disable interrupts. + These macros store the current flags to the (unsigned long) variable given + as a parameter. RESTORE_INTR returns the interrupt ebable bit to state + before DISABLE_INTR or ENABLE_INTR */ + +#define DISABLE_INTR(flags) __asm__ __volatile__("pushfl ; popl %0 ; cli":"=r" (flags)); +#define RESTORE_INTR(flags) __asm__ __volatile__("pushl %0 ; popfl": \ + :"r" (flags)); +/* + KERNEL_MALLOC() allocates requested number of memory and + KERNEL_FREE is used to free it. + These macros are never called from interrupt, in addition the + nbytes will never be more than 4096 bytes. Generally the driver + will allocate memory in blocks of 4k. If the kernel has just a + page level memory allocation, 4K can be safely used as the size + (the nbytes parameter can be ignored). +*/ +#define KERNEL_MALLOC(nbytes) kmalloc(nbytes, GFP_KERNEL) +#define KERNEL_FREE(addr) kfree(addr) + +/* + * The macro PERMANENT_MALLOC(typecast, mem_ptr, size, linux_ptr) + * returns size bytes of + * (kernel virtual) memory which will never get freed by the driver. + * This macro is called only during boot. The linux_ptr is a linux specific + * parameter which should be ignored in other operating systems. + * The mem_ptr is a pointer variable where the macro assigns pointer to the + * memory area. The type is the type of the mem_ptr. + */ +#define PERMANENT_MALLOC(typecast, mem_ptr, size, linux_ptr) \ + {mem_ptr = (typecast)linux_ptr; \ + linux_ptr += (size);} + +/* + * The macro DEFINE_TIMER defines variables for the ACTIVATE_TIMER if + * required. The name is the variable/name to be used and the proc is + * the procedure to be called when the timer expires. + */ + +#define DEFINE_TIMER(name, proc) \ + static struct timer_list name = \ + {NULL, 0, 0, 0, proc} + +/* + * The ACTIVATE_TIMER requests system to call 'proc' after 'time' ticks. + */ + +#define ACTIVATE_TIMER(name, proc, time) \ + {name.expires = time; \ + add_timer (&name);} + +#define INB inb +#define OUTB outb diff -uNr linux-1.0.9/drivers/sound/linux/soundcard.c linux/drivers/sound/linux/soundcard.c --- linux-1.0.9/drivers/sound/linux/soundcard.c Thu Jan 1 01:00:00 1970 +++ linux/drivers/sound/linux/soundcard.c Mon Apr 1 17:39:34 2002 @@ -0,0 +1,356 @@ + +/* + * linux/kernel/chr_drv/sound/soundcard.c + * + * Soundcard driver for Linux + * + * Copyright by Hannu Savolainen 1993 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. 2. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include "sound_config.h" + +#ifdef CONFIGURE_SOUNDCARD + +#include + +extern long seq_time; + +static int soundcards_installed = 0; /* Number of installed + + * soundcards */ +static int soundcard_configured = 0; + +static struct fileinfo files[SND_NDEVS]; + +extern char *snd_raw_buf[MAX_DSP_DEV][DSP_BUFFCOUNT]; +extern unsigned long snd_raw_buf_phys[MAX_DSP_DEV][DSP_BUFFCOUNT]; +extern int snd_raw_count[MAX_DSP_DEV]; + +int +snd_ioctl_return (int *addr, int value) +{ + if (value < 0) + return value; + + PUT_WORD_TO_USER (addr, 0, value); + return 0; +} + +static int +sound_read (struct inode *inode, struct file *file, char *buf, int count) +{ + int dev; + + dev = inode->i_rdev; + dev = MINOR (dev); + + return sound_read_sw (dev, &files[dev], buf, count); +} + +static int +sound_write (struct inode *inode, struct file *file, char *buf, int count) +{ + int dev; + + dev = inode->i_rdev; + dev = MINOR (dev); + + return sound_write_sw (dev, &files[dev], buf, count); +} + +static int +sound_lseek (struct inode *inode, struct file *file, off_t offset, int orig) +{ + return RET_ERROR (EPERM); +} + +static int +sound_open (struct inode *inode, struct file *file) +{ + int dev; + + dev = inode->i_rdev; + dev = MINOR (dev); + + if (!soundcard_configured && dev != SND_DEV_CTL && dev != SND_DEV_STATUS) + { + printk ("SoundCard Error: The soundcard system has not been configured\n"); + return RET_ERROR (ENXIO); + } + + files[dev].mode = 0; + + if ((file->f_flags & O_ACCMODE) == O_RDWR) + files[dev].mode = OPEN_READWRITE; + if ((file->f_flags & O_ACCMODE) == O_RDONLY) + files[dev].mode = OPEN_READ; + if ((file->f_flags & O_ACCMODE) == O_WRONLY) + files[dev].mode = OPEN_WRITE; + + return sound_open_sw (dev, &files[dev]); +} + +static void +sound_release (struct inode *inode, struct file *file) +{ + int dev; + + dev = inode->i_rdev; + dev = MINOR (dev); + + sound_release_sw (dev, &files[dev]); +} + +static int +sound_ioctl (struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + int dev; + + dev = inode->i_rdev; + dev = MINOR (dev); + + return sound_ioctl_sw (dev, &files[dev], cmd, arg); +} + +static int +sound_select (struct inode *inode, struct file *file, int sel_type, select_table * wait) +{ + int dev; + + dev = inode->i_rdev; + dev = MINOR (dev); + + DEB (printk ("sound_select(dev=%d, type=0x%x)\n", dev, sel_type)); + + switch (dev & 0x0f) + { + case SND_DEV_SEQ: + return sequencer_select (dev, &files[dev], sel_type, wait); + break; + + default: + return 0; + } + + return 0; +} + +static struct file_operations sound_fops = +{ + sound_lseek, + sound_read, + sound_write, + NULL, /* sound_readdir */ + sound_select, + sound_ioctl, + NULL, + sound_open, + sound_release +}; + +long +soundcard_init (long mem_start) +{ + register_chrdev (SOUND_MAJOR, "sound", &sound_fops); + + soundcard_configured = 1; + + mem_start = sndtable_init (mem_start); /* Initialize call tables and + * detect cards */ + + if (!(soundcards_installed = sndtable_get_cardcount ())) + return mem_start; /* No cards detected */ + + if (num_dspdevs) /* Audio devices present */ + { + mem_start = DMAbuf_init (mem_start); + mem_start = audio_init (mem_start); + } + +#ifndef EXCLUDE_MPU401 + if (num_midis) + mem_start = MIDIbuf_init (mem_start); +#endif + + if (num_midis + num_synths) + mem_start = sequencer_init (mem_start); + + return mem_start; +} + +void +tenmicrosec (void) +{ + int i; + + for (i = 0; i < 16; i++) + inb (0x80); +} + +int +snd_set_irq_handler (int interrupt_level, void (*hndlr) (int)) +{ + int retcode; + + struct sigaction sa; + + sa.sa_handler = hndlr; + +#ifdef SND_SA_INTERRUPT + sa.sa_flags = SA_INTERRUPT; +#else + sa.sa_flags = 0; +#endif + + sa.sa_mask = 0; + sa.sa_restorer = NULL; + + retcode = irqaction (interrupt_level, &sa); + + if (retcode < 0) + { + printk ("Sound: IRQ%d already in use\n", interrupt_level); + } + + return retcode; +} + +void +snd_release_irq (int vect) +{ + free_irq (vect); +} + +void +request_sound_timer (int count) +{ +#ifndef EXCLUDE_SEQUENCER + if (count < 0) + count = jiffies + (-count); + else + count += seq_time; + timer_table[SOUND_TIMER].fn = sequencer_timer; + timer_table[SOUND_TIMER].expires = count; + timer_active |= 1 << SOUND_TIMER; +#endif +} + +void +sound_stop_timer (void) +{ +#ifndef EXCLUDE_SEQUENCER + timer_table[SOUND_TIMER].expires = 0; + timer_active &= ~(1 << SOUND_TIMER); +#endif +} + +#ifndef EXCLUDE_AUDIO +static int +valid_dma_page (unsigned long addr, unsigned long dev_buffsize, unsigned long dma_pagesize) +{ + if (((addr & (dma_pagesize - 1)) + dev_buffsize) <= dma_pagesize) + return 1; + else + return 0; +} + +void +sound_mem_init (void) +{ + int i, dev; + unsigned long start_addr, end_addr, mem_ptr, dma_pagesize; + + mem_ptr = high_memory; + + /* Some sanity checks */ + + if (mem_ptr > (16 * 1024 * 1024)) + mem_ptr = 16 * 1024 * 1024; /* Limit to 16M */ + + for (dev = 0; dev < num_dspdevs; dev++) /* Enumerate devices */ + if (sound_buffcounts[dev] > 0 && sound_dsp_dmachan[dev] > 0) + { + if (sound_dma_automode[dev]) + sound_buffcounts[dev] = 1; + + if (sound_dsp_dmachan[dev] > 3 && sound_buffsizes[dev] > 65536) + dma_pagesize = 131072;/* 128k */ + else + dma_pagesize = 65536; + + /* More sanity checks */ + + if (sound_buffsizes[dev] > dma_pagesize) + sound_buffsizes[dev] = dma_pagesize; + sound_buffsizes[dev] &= 0xfffff000; /* Truncate to n*4k */ + if (sound_buffsizes[dev] < 4096) + sound_buffsizes[dev] = 4096; + + /* Now allocate the buffers */ + + for (snd_raw_count[dev] = 0; snd_raw_count[dev] < sound_buffcounts[dev]; snd_raw_count[dev]++) + { + start_addr = mem_ptr - sound_buffsizes[dev]; + if (!valid_dma_page (start_addr, sound_buffsizes[dev], dma_pagesize)) + start_addr &= ~(dma_pagesize - 1); /* Align address to + * dma_pagesize */ + + end_addr = start_addr + sound_buffsizes[dev] - 1; + + snd_raw_buf[dev][snd_raw_count[dev]] = (char *) start_addr; + snd_raw_buf_phys[dev][snd_raw_count[dev]] = start_addr; + mem_ptr = start_addr; + + for (i = MAP_NR (start_addr); i <= MAP_NR (end_addr); i++) + { + if (mem_map[i]) + panic ("sound_mem_init: Page not free (driver incompatible with kernel).\n"); + + mem_map[i] = MAP_PAGE_RESERVED; + } + } + } /* for dev */ +} + +#endif + +#else + +long +soundcard_init (long mem_start) /* Dummy version */ +{ + return mem_start; +} + +#endif + +#if !defined(CONFIGURE_SOUNDCARD) || defined(EXCLUDE_AUDIO) +void +sound_mem_init (void) +{ + /* Dummy version */ +} + +#endif diff -uNr linux-1.0.9/drivers/sound/midibuf.c linux/drivers/sound/midibuf.c --- linux-1.0.9/drivers/sound/midibuf.c Thu Dec 9 23:23:26 1993 +++ linux/drivers/sound/midibuf.c Mon Apr 1 17:39:34 2002 @@ -1,12 +1,12 @@ /* * sound/midibuf.c - * + * * Device file manager for /dev/midi - * + * * NOTE! This part of the driver is currently just a stub. - * + * * Copyright by Hannu Savolainen 1993 - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: 1. Redistributions of source code must retain the above copyright @@ -14,7 +14,7 @@ * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -26,7 +26,7 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * + * */ #include "sound_config.h" diff -uNr linux-1.0.9/drivers/sound/mpu401.c linux/drivers/sound/mpu401.c --- linux-1.0.9/drivers/sound/mpu401.c Thu Dec 9 23:23:39 1993 +++ linux/drivers/sound/mpu401.c Mon Apr 1 17:39:34 2002 @@ -1,12 +1,12 @@ /* * sound/mpu401.c - * + * * The low level driver for Roland MPU-401 compatible Midi cards. - * + * * This version supports just the DUMB UART mode. - * + * * Copyright by Hannu Savolainen 1993 - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: 1. Redistributions of source code must retain the above copyright @@ -14,7 +14,7 @@ * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -26,7 +26,7 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * + * */ #include "sound_config.h" @@ -35,7 +35,7 @@ #if !defined(EXCLUDE_MPU401) && !defined(EXCLUDE_MIDI) -#define DATAPORT (mpu401_base) /* MPU-401 Data I/O Port on IBM */ +#define DATAPORT (mpu401_base)/* MPU-401 Data I/O Port on IBM */ #define COMDPORT (mpu401_base+1) /* MPU-401 Command Port on IBM */ #define STATPORT (mpu401_base+1) /* MPU-401 Status Port on IBM */ @@ -61,58 +61,16 @@ static int reset_mpu401 (void); static void (*midi_input_intr) (int dev, unsigned char data); -static void -mpu401_input_loop (void) -{ - int count; - - count = 10; - - while (count) /* Not timed out */ - if (input_avail ()) - { - unsigned char c = mpu401_read (); - - count = 100; - - if (mpu401_opened & OPEN_READ) - midi_input_intr (my_dev, c); - } - else - while (!input_avail () && count) - count--; -} - void mpuintr (int unit) { - if (input_avail ()) - mpu401_input_loop (); -} - -/* - * It looks like there is no input interrupts in the UART mode. Let's try - * polling. - */ - -static void -poll_mpu401 (unsigned long dummy) -{ - unsigned long flags; - - DEFINE_TIMER(mpu401_timer, poll_mpu401); - - if (!(mpu401_opened & OPEN_READ)) - return; /* No longer required */ - - DISABLE_INTR (flags); - - if (input_avail ()) - mpu401_input_loop (); - - ACTIVATE_TIMER(mpu401_timer, poll_mpu401, 1); /* Come back later */ + while (input_avail ()) + { + unsigned char c = mpu401_read (); - RESTORE_INTR (flags); + if (mpu401_opened & OPEN_READ) + midi_input_intr (my_dev, c); + } } static int @@ -127,11 +85,10 @@ return RET_ERROR (EBUSY); } - mpu401_input_loop (); + mpuintr (0); midi_input_intr = input; mpu401_opened = mode; - poll_mpu401 (0); /* Enable input polling */ return 0; } @@ -155,7 +112,7 @@ DISABLE_INTR (flags); if (input_avail ()) - mpu401_input_loop (); + mpuintr (0); RESTORE_INTR (flags); @@ -291,7 +248,7 @@ mpu401_opened = 0; if (ok) - mpu401_input_loop (); /* Flush input before enabling interrupts */ + mpuintr (0); /* Flush input before enabling interrupts */ RESTORE_INTR (flags); diff -uNr linux-1.0.9/drivers/sound/opl3.c linux/drivers/sound/opl3.c --- linux-1.0.9/drivers/sound/opl3.c Tue Dec 14 01:41:13 1993 +++ linux/drivers/sound/opl3.c Mon Apr 1 17:39:34 2002 @@ -1,10 +1,10 @@ /* * sound/opl3.c - * + * * A low level driver for Yamaha YM3812 and OPL-3 -chips - * + * * Copyright by Hannu Savolainen 1993 - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: 1. Redistributions of source code must retain the above copyright @@ -12,7 +12,7 @@ * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -24,7 +24,7 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * + * */ /* Major improvements to the FM handling 30AUG92 by Rob Hooft, */ @@ -38,7 +38,7 @@ #define MAX_VOICE 18 #define OFFS_4OP 11 /* Definitions for the operators OP3 and OP4 - * begin here */ + * begin here */ static int opl3_enabled = 0; static int left_address = 0x388, right_address = 0x388, both_address = 0; @@ -70,7 +70,7 @@ static int opl3_ok = 0; static int opl3_busy = 0; -static int fm_model = 0; /* 0=no fm, 1=mono, 2=SB Pro 1, 3=SB Pro 2 */ +static int fm_model = 0; /* 0=no fm, 1=mono, 2=SB Pro 1, 3=SB Pro 2 */ static int store_instr (int instr_no, struct sbi_instrument *instr); static void freq_to_fnum (int freq, int *block, int *fnum); @@ -81,6 +81,9 @@ void enable_opl3_mode (int left, int right, int both) { + if (opl3_enabled) + return; + opl3_enabled = 1; left_address = left; right_address = right; @@ -168,10 +171,10 @@ * This function returns 1 if the FM chicp is present at the given I/O port * The detection algorithm plays with the timer built in the FM chip and * looks for a change in the status register. - * + * * Note! The timers of the FM chip are not connected to AdLib (and compatible) * boards. - * + * * Note2! The chip is initialized if detected. */ @@ -194,7 +197,7 @@ if ((stat1 & 0xE0) != 0x00) { - return 0; /* Should be 0x00 */ + return 0; /* Should be 0x00 */ } opl3_command (ioaddr, TIMER1_REGISTER, 0xff); /* Set timer 1 to 0xff */ @@ -364,7 +367,7 @@ vol2 = instr->operators[3]; if ((instr->operators[10] & 0x01)) - { /* Additive synthesis */ + { /* Additive synthesis */ calc_vol (&vol1, volume); calc_vol (&vol2, volume); } @@ -627,7 +630,7 @@ * register. The OPL-3 survives with just two INBs */ - OUTB ((unsigned char)(addr & 0xff), io_addr); /* Select register */ + OUTB ((unsigned char) (addr & 0xff), io_addr); /* Select register */ if (!opl3_enabled) tenmicrosec (); @@ -635,7 +638,7 @@ for (i = 0; i < 2; i++) INB (io_addr); - OUTB ((unsigned char)(val & 0xff), io_addr + 1); /* Write to register */ + OUTB ((unsigned char) (val & 0xff), io_addr + 1); /* Write to register */ if (!opl3_enabled) { @@ -747,6 +750,11 @@ { } +static void +opl3_volume_method (int dev, int mode) +{ +} + #define SET_VIBRATO(cell) { \ tmp = instr->operators[(cell-1)+(((cell-1)/2)*OFFS_4OP)]; \ if (pressure > 110) \ @@ -852,7 +860,7 @@ opl3_command (map->ioaddr, FNUM_LOW + map->voice_num, data); data = 0x20 | ((block & 0x7) << 2) | ((fnum >> 8) & 0x3); /* KEYON|OCTAVE|MS bits - * of f-num */ + * of f-num */ voices[voice].keyon_byte = data; opl3_command (map->ioaddr, KEYON_BLOCK + map->voice_num, data); break; @@ -886,6 +894,7 @@ opl3_aftertouch, opl3_controller, opl3_panning, + opl3_volume_method, opl3_patchmgr }; @@ -894,8 +903,8 @@ { int i; - PERMANENT_MALLOC(struct sbi_instrument*, instrmap, - SBFM_MAXINSTR*sizeof(*instrmap), mem_start); + PERMANENT_MALLOC (struct sbi_instrument *, instrmap, + SBFM_MAXINSTR * sizeof (*instrmap), mem_start); synth_devs[num_synths++] = &opl3_operations; fm_model = 0; diff -uNr linux-1.0.9/drivers/sound/os.h linux/drivers/sound/os.h --- linux-1.0.9/drivers/sound/os.h Fri Feb 11 12:07:33 1994 +++ linux/drivers/sound/os.h Mon Apr 1 17:39:34 2002 @@ -41,7 +41,7 @@ #include #include #include -#include +#include #include #include #include @@ -140,7 +140,7 @@ #define DEFINE_TIMER(name, proc) \ static struct timer_list name = \ - {NULL, NULL, 0, 0, proc} + {NULL, 0, 0, 0, proc} /* * The ACTIVATE_TIMER requests system to call 'proc' after 'time' ticks. diff -uNr linux-1.0.9/drivers/sound/pas.h linux/drivers/sound/pas.h --- linux-1.0.9/drivers/sound/pas.h Wed Dec 15 01:10:21 1993 +++ linux/drivers/sound/pas.h Mon Apr 1 17:39:34 2002 @@ -138,11 +138,11 @@ char I_C_2_PCM_DMA_translate[] = /* R W PCM PCM DMA channel value translations */ { 4, 1, 2, 3, 0, 5, 6, 7 }; char I_C_3_PCM_IRQ_translate[] = /* R W PCM PCM IRQ level value translation */ - { 0, 0, 1, 2, 3, 4, 5, 6, 0, 0, 7, 8, 9, 0, 10, 11 }; + { 0, 0, 1, 2, 3, 4, 5, 6, 0, 1, 7, 8, 9, 0, 10, 11 }; char E_C_MPU401_IRQ_translate[] = /* R W MIDI MPU401 emulation IRQ value translation */ - { 0x00, 0x00, 0x01, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00, 0x05, 0x06, 0x07 }; + { 0x00, 0x00, 0x01, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x01, 0x05, 0x06, 0x07 }; char E_C_SB_IRQ_translate[] = /* R W PCM SB emulation IRQ translate */ - { 0x00, 0x00, 0x08, 0x10, 0x00, 0x18, 0x00, 0x20, 0x00, 0x00, 0x28, 0x30, 0x38, 0, 0 }; + { 0x00, 0x00, 0x08, 0x10, 0x00, 0x18, 0x00, 0x20, 0x00, 0x08, 0x28, 0x30, 0x38, 0, 0 }; char E_C_SB_DMA_translate[] = /* R W PCM SB emulation DMA translate */ { 0x00, 0x40, 0x80, 0xC0, 0, 0, 0, 0 }; char O_M_1_to_card[] = /* R W Control Translate (OM1 & 0x0f) to card type */ diff -uNr linux-1.0.9/drivers/sound/pas2_card.c linux/drivers/sound/pas2_card.c --- linux-1.0.9/drivers/sound/pas2_card.c Wed Dec 15 01:21:11 1993 +++ linux/drivers/sound/pas2_card.c Mon Apr 1 17:39:34 2002 @@ -2,11 +2,11 @@ #define SND_SA_INTERRUPT /* * sound/pas2_card.c - * + * * Detection routine for the Pro Audio Spectrum cards. - * + * * Copyright by Hannu Savolainen 1993 - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: 1. Redistributions of source code must retain the above copyright @@ -14,7 +14,7 @@ * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -26,7 +26,7 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * + * */ #include "sound_config.h" @@ -196,14 +196,14 @@ ok = 0; } } - -/* + + /* * This fixes the timing problems of the PAS due to the Symphony chipset * as per Media Vision. Only define this if your PAS doesn't work correctly. */ #ifdef SYMPHONY_PAS - OUTB(0x05,0xa8); - OUTB(0x60,0xa9); + OUTB (0x05, 0xa8); + OUTB (0x60, 0xa9); #endif #ifdef BROKEN_BUS_CLOCK @@ -228,35 +228,35 @@ #if !defined(EXCLUDE_SB_EMULATION) || !defined(EXCLUDE_SB) - { - struct address_info *sb_config; + { + struct address_info *sb_config; - if ((sb_config=sound_getconf(SNDCARD_SB))) - { - unsigned char irq_dma; - - /* Turn on Sound Blaster compatibility */ - /* bit 1 = SB emulation */ - /* bit 0 = MPU401 emulation (CDPC only :-( ) */ - pas_write (0x02, COMPATIBILITY_ENABLE); - - /* "Emulation address" */ - pas_write ((sb_config->io_base >> 4) & 0x0f, EMULATION_ADDRESS); - - if (!E_C_SB_DMA_translate[sb_config->dma]) - printk("\n\nPAS16 Warning: Invalid SB DMA %d\n\n", - sb_config->dma); - - if (!E_C_SB_IRQ_translate[sb_config->irq]) - printk("\n\nPAS16 Warning: Invalid SB IRQ %d\n\n", - sb_config->irq); - - irq_dma = E_C_SB_DMA_translate[sb_config->dma] | - E_C_SB_IRQ_translate[sb_config->irq]; - - pas_write(irq_dma, EMULATION_CONFIGURATION); - } - } + if ((sb_config = sound_getconf (SNDCARD_SB))) + { + unsigned char irq_dma; + + /* Turn on Sound Blaster compatibility */ + /* bit 1 = SB emulation */ + /* bit 0 = MPU401 emulation (CDPC only :-( ) */ + pas_write (0x02, COMPATIBILITY_ENABLE); + + /* "Emulation address" */ + pas_write ((sb_config->io_base >> 4) & 0x0f, EMULATION_ADDRESS); + + if (!E_C_SB_DMA_translate[sb_config->dma]) + printk ("\n\nPAS16 Warning: Invalid SB DMA %d\n\n", + sb_config->dma); + + if (!E_C_SB_IRQ_translate[sb_config->irq]) + printk ("\n\nPAS16 Warning: Invalid SB IRQ %d\n\n", + sb_config->irq); + + irq_dma = E_C_SB_DMA_translate[sb_config->dma] | + E_C_SB_IRQ_translate[sb_config->irq]; + + pas_write (irq_dma, EMULATION_CONFIGURATION); + } + } #endif if (!ok) @@ -327,11 +327,11 @@ mem_start = pas_pcm_init (mem_start, hw_config); #endif -# if !defined(EXCLUDE_SB_EMULATION) && !defined(EXCLUDE_SB) +#if !defined(EXCLUDE_SB_EMULATION) && !defined(EXCLUDE_SB) sb_dsp_disable_midi (); /* The SB emulation don't support * midi */ -# endif +#endif #ifndef EXCLUDE_YM3812 enable_opl3_mode (0x388, 0x38a, 0); diff -uNr linux-1.0.9/drivers/sound/pas2_midi.c linux/drivers/sound/pas2_midi.c --- linux-1.0.9/drivers/sound/pas2_midi.c Thu Dec 9 23:24:01 1993 +++ linux/drivers/sound/pas2_midi.c Mon Apr 1 17:39:34 2002 @@ -1,10 +1,10 @@ /* * sound/pas2_midi.c - * + * * The low level driver for the PAS Midi Interface. - * + * * Copyright by Hannu Savolainen 1993 - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: 1. Redistributions of source code must retain the above copyright @@ -12,7 +12,7 @@ * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -24,7 +24,7 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * + * */ #include "sound_config.h" diff -uNr linux-1.0.9/drivers/sound/pas2_mixer.c linux/drivers/sound/pas2_mixer.c --- linux-1.0.9/drivers/sound/pas2_mixer.c Thu Dec 9 23:24:14 1993 +++ linux/drivers/sound/pas2_mixer.c Mon Apr 1 17:39:34 2002 @@ -2,11 +2,11 @@ /* * sound/pas2_mixer.c - * + * * Mixer routines for the Pro Audio Spectrum cards. - * + * * Copyright by Hannu Savolainen 1993 - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: 1. Redistributions of source code must retain the above copyright @@ -14,7 +14,7 @@ * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -26,7 +26,7 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * + * */ #include "sound_config.h" @@ -87,7 +87,7 @@ } if (bits == P_M_MV508_BASS || bits == P_M_MV508_TREBLE) - { /* Bass and trebble are mono devices */ + { /* Bass and trebble are mono devices */ pas_write (P_M_MV508_ADDRESS | bits, PARALLEL_MIXER); pas_write (left, PARALLEL_MIXER); right_vol = left_vol; diff -uNr linux-1.0.9/drivers/sound/pas2_pcm.c linux/drivers/sound/pas2_pcm.c --- linux-1.0.9/drivers/sound/pas2_pcm.c Tue Dec 14 17:22:50 1993 +++ linux/drivers/sound/pas2_pcm.c Mon Apr 1 17:39:34 2002 @@ -1,11 +1,11 @@ #define _PAS2_PCM_C_ /* * sound/pas2_pcm.c - * + * * The low level driver for the Pro Audio Spectrum ADC/DAC. - * + * * Copyright by Hannu Savolainen 1993 - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: 1. Redistributions of source code must retain the above copyright @@ -13,7 +13,7 @@ * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -25,7 +25,7 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * + * */ #include "sound_config.h" @@ -149,7 +149,7 @@ case SOUND_PCM_WRITE_CHANNELS: if (local) - return pcm_set_channels (arg); + return pcm_set_channels (arg); return IOCTL_OUT (arg, pcm_set_channels (IOCTL_IN (arg))); break; @@ -234,7 +234,7 @@ } static void -pas_pcm_output_block (int dev, unsigned long buf, int count, +pas_pcm_output_block (int dev, unsigned long buf, int count, int intrflag, int restart_dma) { unsigned long flags, cnt; @@ -255,8 +255,8 @@ pas_write (pas_read (PCM_CONTROL) & ~P_C_PCM_ENABLE, PCM_CONTROL); - if (restart_dma) - DMAbuf_start_dma (dev, buf, count, DMA_MODE_WRITE); + if (restart_dma) + DMAbuf_start_dma (dev, buf, count, DMA_MODE_WRITE); if (sound_dsp_dmachan[dev] > 3) count >>= 1; @@ -280,7 +280,7 @@ } static void -pas_pcm_start_input (int dev, unsigned long buf, int count, +pas_pcm_start_input (int dev, unsigned long buf, int count, int intrflag, int restart_dma) { unsigned long flags; @@ -300,7 +300,7 @@ DISABLE_INTR (flags); if (restart_dma) - DMAbuf_start_dma (dev, buf, count, DMA_MODE_READ); + DMAbuf_start_dma (dev, buf, count, DMA_MODE_READ); if (sound_dsp_dmachan[dev] > 3) count >>= 1; @@ -337,14 +337,15 @@ static struct audio_operations pas_pcm_operations = { "Pro Audio Spectrum", - pas_pcm_open, /* */ - pas_pcm_close, /* */ - pas_pcm_output_block, /* */ - pas_pcm_start_input, /* */ - pas_pcm_ioctl, /* */ - pas_pcm_prepare_for_input, /* */ - pas_pcm_prepare_for_output, /* */ - pas_pcm_reset, /* */ + NOTHING_SPECIAL, + pas_pcm_open, + pas_pcm_close, + pas_pcm_output_block, + pas_pcm_start_input, + pas_pcm_ioctl, + pas_pcm_prepare_for_input, + pas_pcm_prepare_for_output, + pas_pcm_reset, pas_pcm_reset, /* halt_xfer */ NULL, /* has_output_drained */ NULL /* copy_from_user */ @@ -379,9 +380,9 @@ sound_dma_automode[my_devnum] = 1; } #else - sound_buffcounts[my_devnum] = 2; - sound_buffsizes[my_devnum] = DSP_BUFFSIZE; - sound_dma_automode[my_devnum] = 0; + sound_buffcounts[my_devnum] = 2; + sound_buffsizes[my_devnum] = DSP_BUFFSIZE; + sound_dma_automode[my_devnum] = 0; #endif } else diff -uNr linux-1.0.9/drivers/sound/patmgr.c linux/drivers/sound/patmgr.c --- linux-1.0.9/drivers/sound/patmgr.c Thu Dec 9 23:24:34 1993 +++ linux/drivers/sound/patmgr.c Mon Apr 1 17:39:34 2002 @@ -1,10 +1,10 @@ /* * sound/patmgr.c - * + * * The patch maneger interface for the /dev/sequencer - * + * * Copyright by Hannu Savolainen 1993 - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: 1. Redistributions of source code must retain the above copyright @@ -12,7 +12,7 @@ * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -24,7 +24,7 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * + * */ #define PATMGR_C diff -uNr linux-1.0.9/drivers/sound/sb16_dsp.c linux/drivers/sound/sb16_dsp.c --- linux-1.0.9/drivers/sound/sb16_dsp.c Fri Jan 21 14:59:50 1994 +++ linux/drivers/sound/sb16_dsp.c Mon Apr 1 17:39:34 2002 @@ -1,12 +1,12 @@ /* * sound/sb16_dsp.c - * + * * The low level driver for the SoundBlaster DSP chip. - * + * * (C) 1993 J. Schubert (jsb@sth.ruhr-uni-bochum.de) * * based on SB-driver by (C) Hannu Savolainen - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: 1. Redistributions of source code must retain the above copyright @@ -14,7 +14,7 @@ * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -26,53 +26,55 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * + * */ #define DEB(x) #define DEB1(x) /* -#define DEB_DMARES -*/ + #define DEB_DMARES + */ #include "sound_config.h" #include "sb.h" #include "sb_mixer.h" #if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_SB16) && !defined(EXCLUDE_SB) && !defined(EXCLUDE_AUDIO) && !defined(EXCLUDE_SBPRO) -extern int sbc_base; +extern int sbc_base, sbc_minor, sbc_major; -static int sb16_dsp_ok = 0; /* Set to 1 after successful initialization */ -static int dsp_16bit = 0; -static int dsp_stereo = 0; -static int dsp_current_speed = 8000;/*DSP_DEFAULT_SPEED;*/ -static int dsp_busy = 0; -static int dma16, dma8; +static int sb16_dsp_ok = 0;/* Set to 1 after successful initialization */ +static int dsp_16bit = 0; +static int dsp_stereo = 0; +static int dsp_current_speed = 8000; /*DSP_DEFAULT_SPEED; */ +static int dsp_busy = 0; +static int dma16, dma8; static unsigned long dsp_count = 0; -static int irq_mode = IMODE_NONE; /* IMODE_INPUT, IMODE_OUTPUT or +static int irq_mode = IMODE_NONE; /* IMODE_INPUT, IMODE_OUTPUT or + IMODE_NONE */ -static int my_dev = 0; +static int my_dev = 0; static volatile int intr_active = 0; -static int sb16_dsp_open (int dev, int mode); -static void sb16_dsp_close (int dev); -static void sb16_dsp_output_block (int dev, unsigned long buf, int count,int intrflag, int dma_restart); -static void sb16_dsp_start_input (int dev, unsigned long buf, int count,int intrflag, int dma_restart); -static int sb16_dsp_ioctl (int dev, unsigned int cmd, unsigned int arg,int local); -static int sb16_dsp_prepare_for_input (int dev, int bsize, int bcount); -static int sb16_dsp_prepare_for_output (int dev, int bsize, int bcount); -static void sb16_dsp_reset (int dev); -static void sb16_dsp_halt (int dev); -static int dsp_set_speed (int); -static int dsp_set_stereo (int); -static void dsp_cleanup (void); -int sb_reset_dsp (void); +static int sb16_dsp_open (int dev, int mode); +static void sb16_dsp_close (int dev); +static void sb16_dsp_output_block (int dev, unsigned long buf, int count, int intrflag, int dma_restart); +static void sb16_dsp_start_input (int dev, unsigned long buf, int count, int intrflag, int dma_restart); +static int sb16_dsp_ioctl (int dev, unsigned int cmd, unsigned int arg, int local); +static int sb16_dsp_prepare_for_input (int dev, int bsize, int bcount); +static int sb16_dsp_prepare_for_output (int dev, int bsize, int bcount); +static void sb16_dsp_reset (int dev); +static void sb16_dsp_halt (int dev); +static int dsp_set_speed (int); +static int dsp_set_stereo (int); +static void dsp_cleanup (void); +int sb_reset_dsp (void); static struct audio_operations sb16_dsp_operations = { "SoundBlaster 16", + NOTHING_SPECIAL, sb16_dsp_open, sb16_dsp_close, sb16_dsp_output_block, @@ -86,203 +88,221 @@ NULL }; -static int sb_dsp_command01 (unsigned char val) +static int +sb_dsp_command01 (unsigned char val) { - int i=1<<16; + int i = 1 << 16; - while(--i & (!INB (DSP_STATUS) & 0x80)); - if(!i) - printk("SB16 sb_dsp_command01 Timeout\n"); - return sb_dsp_command(val); + while (--i & (!INB (DSP_STATUS) & 0x80)); + if (!i) + printk ("SB16 sb_dsp_command01 Timeout\n"); + return sb_dsp_command (val); } -static int wait_data_avail(int t) +static int +wait_data_avail (unsigned long t) { - int loopc=5000000; - t+=GET_TIME(); - do { - if(INB(DSP_DATA_AVAIL) & 0x80) - return 1; - } while(--loopc && GET_TIME() 44100) mode = 44100; - dsp_current_speed=mode; - } + { + if (mode < 5000) + mode = 5000; + if (mode > 44100) + mode = 44100; + dsp_current_speed = mode; + } return mode; } -static int dsp_set_stereo(int mode) +static int +dsp_set_stereo (int mode) { -DEB(printk("dsp_set_stereo(%d)\n",mode)); + DEB (printk ("dsp_set_stereo(%d)\n", mode)); - dsp_stereo=mode; + dsp_stereo = mode; return mode; } -static int dsp_set_bits(int arg) { -DEB(printk("dsp_set_bits(%d)\n",arg)); +static int +dsp_set_bits (int arg) +{ + DEB (printk ("dsp_set_bits(%d)\n", arg)); if (arg) - switch(arg) { - case 8: - dsp_16bit=0; break; - case 16: - dsp_16bit=1; break; - default: - return RET_ERROR(EINVAL); - } - return dsp_16bit? 16:8; + switch (arg) + { + case 8: + dsp_16bit = 0; + break; + case 16: + dsp_16bit = 1; + break; + default: + return RET_ERROR (EINVAL); + } + return dsp_16bit ? 16 : 8; } static int -sb16_dsp_ioctl (int dev, unsigned int cmd, unsigned int arg,int local) -{ - switch (cmd) { - case SOUND_PCM_WRITE_RATE: - if(local) - return dsp_set_speed(arg); - return IOCTL_OUT (arg, dsp_set_speed (IOCTL_IN (arg))); - - case SOUND_PCM_READ_RATE: - if(local) - return dsp_current_speed; - return IOCTL_OUT (arg, dsp_current_speed); - - case SNDCTL_DSP_STEREO: - if (local) - return dsp_set_stereo(arg); - return IOCTL_OUT (arg, dsp_set_stereo(IOCTL_IN(arg))); - - case SOUND_PCM_WRITE_CHANNELS: - if (local) - return dsp_set_stereo(arg-1)+1; - return IOCTL_OUT (arg, dsp_set_stereo (IOCTL_IN (arg) - 1) + 1); - - case SOUND_PCM_READ_CHANNELS: - if (local) - return dsp_stereo+1; - return IOCTL_OUT (arg, dsp_stereo+1); - - case SNDCTL_DSP_SAMPLESIZE: - if (local) - return dsp_set_bits (arg); - return IOCTL_OUT (arg, dsp_set_bits (IOCTL_IN (arg))); - - case SOUND_PCM_READ_BITS: - if (local) - return dsp_16bit?16:8; - return IOCTL_OUT (arg, dsp_16bit?16:8); - - case SOUND_PCM_WRITE_FILTER: /* NOT YET IMPLEMENTED */ - if (IOCTL_IN (arg) > 1) - return IOCTL_OUT (arg, RET_ERROR (EINVAL)); - default: - return RET_ERROR (EINVAL); - } - +sb16_dsp_ioctl (int dev, unsigned int cmd, unsigned int arg, int local) +{ + switch (cmd) + { + case SOUND_PCM_WRITE_RATE: + if (local) + return dsp_set_speed (arg); + return IOCTL_OUT (arg, dsp_set_speed (IOCTL_IN (arg))); + + case SOUND_PCM_READ_RATE: + if (local) + return dsp_current_speed; + return IOCTL_OUT (arg, dsp_current_speed); + + case SNDCTL_DSP_STEREO: + if (local) + return dsp_set_stereo (arg); + return IOCTL_OUT (arg, dsp_set_stereo (IOCTL_IN (arg))); + + case SOUND_PCM_WRITE_CHANNELS: + if (local) + return dsp_set_stereo (arg - 1) + 1; + return IOCTL_OUT (arg, dsp_set_stereo (IOCTL_IN (arg) - 1) + 1); + + case SOUND_PCM_READ_CHANNELS: + if (local) + return dsp_stereo + 1; + return IOCTL_OUT (arg, dsp_stereo + 1); + + case SNDCTL_DSP_SAMPLESIZE: + if (local) + return dsp_set_bits (arg); + return IOCTL_OUT (arg, dsp_set_bits (IOCTL_IN (arg))); + + case SOUND_PCM_READ_BITS: + if (local) + return dsp_16bit ? 16 : 8; + return IOCTL_OUT (arg, dsp_16bit ? 16 : 8); + + case SOUND_PCM_WRITE_FILTER: /* NOT YET IMPLEMENTED */ + if (IOCTL_IN (arg) > 1) + return IOCTL_OUT (arg, RET_ERROR (EINVAL)); + default: + return RET_ERROR (EINVAL); + } + return RET_ERROR (EINVAL); } static int sb16_dsp_open (int dev, int mode) { - int retval; + int retval; -DEB(printk("sb16_dsp_open()\n")); + DEB (printk ("sb16_dsp_open()\n")); if (!sb16_dsp_ok) { printk ("SB16 Error: SoundBlaster board not installed\n"); - return RET_ERROR(ENXIO); + return RET_ERROR (ENXIO); } if (intr_active) - return RET_ERROR(EBUSY); + return RET_ERROR (EBUSY); retval = sb_get_irq (); - if (retval<0) + if (retval < 0) return retval; if (ALLOC_DMA_CHN (dma8)) { printk ("SB16: Unable to grab DMA%d\n", dma8); - sb_free_irq(); - return RET_ERROR(EBUSY); + sb_free_irq (); + return RET_ERROR (EBUSY); } if (dma16 != dma8) - if (ALLOC_DMA_CHN (dma16)) - { - printk ("SB16: Unable to grab DMA%d\n", dma16); - sb_free_irq(); - RELEASE_DMA_CHN (dma8); - return RET_ERROR(EBUSY); - } + if (ALLOC_DMA_CHN (dma16)) + { + printk ("SB16: Unable to grab DMA%d\n", dma16); + sb_free_irq (); + RELEASE_DMA_CHN (dma8); + return RET_ERROR (EBUSY); + } - dsp_ini2(); + dsp_ini2 (); irq_mode = IMODE_NONE; dsp_busy = 1; @@ -294,15 +314,16 @@ sb16_dsp_close (int dev) { unsigned long flags; -DEB(printk("sb16_dsp_close()\n")); - sb_dsp_command01(0xd9); - sb_dsp_command01(0xd5); + + DEB (printk ("sb16_dsp_close()\n")); + sb_dsp_command01 (0xd9); + sb_dsp_command01 (0xd5); DISABLE_INTR (flags); RELEASE_DMA_CHN (dma8); if (dma16 != dma8) - RELEASE_DMA_CHN (dma16); + RELEASE_DMA_CHN (dma16); sb_free_irq (); dsp_cleanup (); dsp_busy = 0; @@ -310,7 +331,7 @@ } static void -sb16_dsp_output_block (int dev, unsigned long buf, int count,int intrflag, int dma_restart) +sb16_dsp_output_block (int dev, unsigned long buf, int count, int intrflag, int dma_restart) { unsigned long flags, cnt; @@ -320,51 +341,54 @@ cnt--; #ifdef DEB_DMARES - printk("output_block: %x %d %d\n",buf,count,intrflag); - if(intrflag) { - int pos,chan=sound_dsp_dmachan[dev]; - DISABLE_INTR (flags); - clear_dma_ff(chan); - disable_dma(chan); - pos=get_dma_residue(chan); - enable_dma(chan); - RESTORE_INTR (flags); - printk("dmapos=%d %x\n",pos,pos); - } + printk ("output_block: %x %d %d\n", buf, count, intrflag); + if (intrflag) + { + int pos, chan = sound_dsp_dmachan[dev]; + + DISABLE_INTR (flags); + clear_dma_ff (chan); + disable_dma (chan); + pos = get_dma_residue (chan); + enable_dma (chan); + RESTORE_INTR (flags); + printk ("dmapos=%d %x\n", pos, pos); + } #endif if (sound_dma_automode[dev] && intrflag && - cnt == dsp_count) { - irq_mode = IMODE_OUTPUT; - intr_active = 1; - return; /* Auto mode on. No need to react */ - } + cnt == dsp_count) + { + irq_mode = IMODE_OUTPUT; + intr_active = 1; + return; /* Auto mode on. No need to react */ + } DISABLE_INTR (flags); - + if (dma_restart) - { - sb16_dsp_halt(dev); - DMAbuf_start_dma (dev, buf, count, DMA_MODE_WRITE); - } + { + sb16_dsp_halt (dev); + DMAbuf_start_dma (dev, buf, count, DMA_MODE_WRITE); + } sb_dsp_command (0x41); - sb_dsp_command ((unsigned char)((dsp_current_speed >> 8) & 0xff)); - sb_dsp_command ((unsigned char)(dsp_current_speed & 0xff)); - sb_dsp_command ((unsigned char)(dsp_16bit ? 0xb6 : 0xc6)); - sb_dsp_command ((unsigned char)((dsp_stereo ? 0x20 : 0) + - (dsp_16bit ? 0x10:0))); - sb_dsp_command01 ((unsigned char)(cnt&0xff)); - sb_dsp_command ((unsigned char)(cnt>>8)); + sb_dsp_command ((unsigned char) ((dsp_current_speed >> 8) & 0xff)); + sb_dsp_command ((unsigned char) (dsp_current_speed & 0xff)); + sb_dsp_command ((unsigned char) (dsp_16bit ? 0xb6 : 0xc6)); + sb_dsp_command ((unsigned char) ((dsp_stereo ? 0x20 : 0) + + (dsp_16bit ? 0x10 : 0))); + sb_dsp_command01 ((unsigned char) (cnt & 0xff)); + sb_dsp_command ((unsigned char) (cnt >> 8)); /* sb_dsp_command (0); - sb_dsp_command (0); */ - + sb_dsp_command (0); */ + RESTORE_INTR (flags); - dsp_count=cnt; + dsp_count = cnt; irq_mode = IMODE_OUTPUT; intr_active = 1; } static void -sb16_dsp_start_input (int dev, unsigned long buf, int count,int intrflag, int dma_restart) +sb16_dsp_start_input (int dev, unsigned long buf, int count, int intrflag, int dma_restart) { unsigned long flags, cnt; @@ -374,46 +398,49 @@ cnt--; #ifdef DEB_DMARES -printk("start_input: %x %d %d\n",buf,count,intrflag); - if(intrflag) { - int pos,chan=sound_dsp_dmachan[dev]; - DISABLE_INTR (flags); - clear_dma_ff(chan); - disable_dma(chan); - pos=get_dma_residue(chan); - enable_dma(chan); - RESTORE_INTR (flags); - printk("dmapos=%d %x\n",pos,pos); - } + printk ("start_input: %x %d %d\n", buf, count, intrflag); + if (intrflag) + { + int pos, chan = sound_dsp_dmachan[dev]; + + DISABLE_INTR (flags); + clear_dma_ff (chan); + disable_dma (chan); + pos = get_dma_residue (chan); + enable_dma (chan); + RESTORE_INTR (flags); + printk ("dmapos=%d %x\n", pos, pos); + } #endif if (sound_dma_automode[dev] && intrflag && - cnt == dsp_count) { - irq_mode = IMODE_INPUT; - intr_active = 1; - return; /* Auto mode on. No need to react */ - } + cnt == dsp_count) + { + irq_mode = IMODE_INPUT; + intr_active = 1; + return; /* Auto mode on. No need to react */ + } DISABLE_INTR (flags); - - if (dma_restart) - { - sb16_dsp_halt(dev); + + if (dma_restart) + { + sb16_dsp_halt (dev); DMAbuf_start_dma (dev, buf, count, DMA_MODE_READ); - } + } sb_dsp_command (0x42); - sb_dsp_command ((unsigned char)((dsp_current_speed >> 8) & 0xff)); - sb_dsp_command ((unsigned char)(dsp_current_speed & 0xff)); - sb_dsp_command ((unsigned char)(dsp_16bit ? 0xbe : 0xce)); - sb_dsp_command ((unsigned char)((dsp_stereo ? 0x20 : 0) + - (dsp_16bit ? 0x10:0))); - sb_dsp_command01 ((unsigned char)(cnt&0xff)); - sb_dsp_command ((unsigned char)(cnt>>8)); - + sb_dsp_command ((unsigned char) ((dsp_current_speed >> 8) & 0xff)); + sb_dsp_command ((unsigned char) (dsp_current_speed & 0xff)); + sb_dsp_command ((unsigned char) (dsp_16bit ? 0xbe : 0xce)); + sb_dsp_command ((unsigned char) ((dsp_stereo ? 0x20 : 0) + + (dsp_16bit ? 0x10 : 0))); + sb_dsp_command01 ((unsigned char) (cnt & 0xff)); + sb_dsp_command ((unsigned char) (cnt >> 8)); + /* sb_dsp_command (0); - sb_dsp_command (0); */ + sb_dsp_command (0); */ RESTORE_INTR (flags); - dsp_count=cnt; + dsp_count = cnt; irq_mode = IMODE_INPUT; intr_active = 1; } @@ -421,7 +448,7 @@ static int sb16_dsp_prepare_for_input (int dev, int bsize, int bcount) { - sound_dsp_dmachan[my_dev] = dsp_16bit? dma16:dma8; + sound_dsp_dmachan[my_dev] = dsp_16bit ? dma16 : dma8; dsp_count = 0; dsp_cleanup (); return 0; @@ -430,7 +457,7 @@ static int sb16_dsp_prepare_for_output (int dev, int bsize, int bcount) { - sound_dsp_dmachan[my_dev] = dsp_16bit? dma16:dma8; + sound_dsp_dmachan[my_dev] = dsp_16bit ? dma16 : dma8; dsp_count = 0; dsp_cleanup (); return 0; @@ -446,7 +473,7 @@ static void sb16_dsp_reset (int dev) { - unsigned long flags; + unsigned long flags; DISABLE_INTR (flags); @@ -460,61 +487,52 @@ sb16_dsp_halt (int dev) { if (dsp_16bit) - { - sb_dsp_command01(0xd9); - sb_dsp_command01(0xd5); - } + { + sb_dsp_command01 (0xd9); + sb_dsp_command01 (0xd5); + } else - { - sb_dsp_command01(0xda); - sb_dsp_command01(0xd0); - } + { + sb_dsp_command01 (0xda); + sb_dsp_command01 (0xd0); + } } static void -set_irq_hw(int level) { - int ival; - switch(level) { - case 5: - ival=2; break; - case 7: - ival=4; break; - case 10: - ival=8; break; - default: - printk("SB16_IRQ_LEVEL %d does not exist\n",level); - return; - } - sb_setmixer(IRQ_NR,ival); +set_irq_hw (int level) +{ + int ival; + + switch (level) + { + case 5: + ival = 2; + break; + case 7: + ival = 4; + break; + case 10: + ival = 8; + break; + default: + printk ("SB16_IRQ_LEVEL %d does not exist\n", level); + return; + } + sb_setmixer (IRQ_NR, ival); } long sb16_dsp_init (long mem_start, struct address_info *hw_config) { - int i, major, minor; - - major = minor = 0; - sb_dsp_command (0xe1); /* Get version */ - - for (i = 1000; i; i--) { - if (INB (DSP_DATA_AVAIL) & 0x80) - { /* wait for Data Ready */ - if (major == 0) - major = INB (DSP_READ); - else - { - minor = INB (DSP_READ); - break; - } - } - } + if (sbc_major < 4) + return mem_start; -#ifndef SCO - sprintf (sb16_dsp_operations.name, "SoundBlaster 16 %d.%d", major, minor); +#ifndef SCO + sprintf (sb16_dsp_operations.name, "SoundBlaster 16 %d.%d", sbc_major, sbc_minor); #endif - + printk (" <%s>", sb16_dsp_operations.name); - + if (num_dspdevs < MAX_DSP_DEV) { dsp_devs[my_dev = num_dspdevs++] = &sb16_dsp_operations; @@ -537,47 +555,37 @@ if (sb16_dsp_ok) return 1; /* Already initialized */ - if (!(sb_config=sound_getconf(SNDCARD_SB))) - { - printk("SB16 Error: Plain SB not configured\n"); - return 0; - } - - if (sbc_base != hw_config->io_base) - printk("Warning! SB16 I/O != SB I/O\n"); + if (!(sb_config = sound_getconf (SNDCARD_SB))) + { + printk ("SB16 Error: Plain SB not configured\n"); + return 0; + } /* sb_setmixer(OPSW,0xf); - if(sb_getmixer(OPSW)!=0xf) - return 0; */ - + if(sb_getmixer(OPSW)!=0xf) + return 0; */ + if (!sb_reset_dsp ()) return 0; - if (hw_config->irq != sb_config->irq) - { - printk("SB16 Error: Invalid IRQ number %d/%d\n", - sb_config->irq, hw_config->irq); - return 0; - } - if (hw_config->dma < 4) - if (hw_config->dma != sb_config->dma) - { - printk("SB16 Error: Invalid DMA channel %d/%d\n", - sb_config->dma, hw_config->dma); - return 0; - } + if (hw_config->dma != sb_config->dma) + { + printk ("SB16 Error: Invalid DMA channel %d/%d\n", + sb_config->dma, hw_config->dma); + return 0; + } dma16 = hw_config->dma; dma8 = sb_config->dma; - set_irq_hw(hw_config->irq); - sb_setmixer(DMA_NR, (1<dma) | (1<dma)); + set_irq_hw (sb_config->irq); + sb_setmixer (DMA_NR, (1 << hw_config->dma) | (1 << sb_config->dma)); - DEB(printk ("SoundBlaster 16: IRQ %d DMA %d OK\n",hw_config->irq,hw_config->dma)); - -/* - dsp_showmessage(0xe3,99); -*/ + DEB (printk ("SoundBlaster 16: IRQ %d DMA %d OK\n", sb_config->irq, hw_config->dma)); + + /* + dsp_showmessage(0xe3,99); + */ sb16_dsp_ok = 1; return 1; } @@ -585,24 +593,26 @@ void sb16_dsp_interrupt (int unused) { - int data; - data = INB (DSP_DATA_AVL16); /* Interrupt acknowledge */ + int data; - if (intr_active) - switch (irq_mode) - { - case IMODE_OUTPUT: - intr_active = 0; - DMAbuf_outputintr (my_dev, 1); - break; - - case IMODE_INPUT: - intr_active = 0; - DMAbuf_inputintr (my_dev); - break; - - default: - printk ("SoundBlaster: Unexpected interrupt\n"); - } + data = INB (DSP_DATA_AVL16); /* Interrupt acknowledge */ + + if (intr_active) + switch (irq_mode) + { + case IMODE_OUTPUT: + intr_active = 0; + DMAbuf_outputintr (my_dev, 1); + break; + + case IMODE_INPUT: + intr_active = 0; + DMAbuf_inputintr (my_dev); + break; + + default: + printk ("SoundBlaster: Unexpected interrupt\n"); + } } + #endif diff -uNr linux-1.0.9/drivers/sound/sb16_midi.c linux/drivers/sound/sb16_midi.c --- linux-1.0.9/drivers/sound/sb16_midi.c Fri Dec 3 03:10:08 1993 +++ linux/drivers/sound/sb16_midi.c Mon Apr 1 17:39:34 2002 @@ -1,10 +1,10 @@ /* * sound/sb16_midi.c - * + * * The low level driver for the MPU-401 UART emulation of the SB16. - * + * * Copyright by Hannu Savolainen 1993 - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: 1. Redistributions of source code must retain the above copyright @@ -12,7 +12,7 @@ * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -24,7 +24,7 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * + * */ #include "sound_config.h" @@ -58,26 +58,19 @@ static int reset_sb16midi (void); static void (*midi_input_intr) (int dev, unsigned char data); +extern int sbc_major; + static void sb16midi_input_loop (void) { - int count; - - count = 10; - - while (count) /* Not timed out */ - if (input_avail ()) - { - unsigned char c = sb16midi_read (); - count = 100; + while (input_avail ()) + { + unsigned char c = sb16midi_read (); - if (sb16midi_opened & OPEN_READ) - midi_input_intr (my_dev, c); - } - else - while (!input_avail () && count) - count--; + if (sb16midi_opened & OPEN_READ) + midi_input_intr (my_dev, c); + } } void @@ -87,35 +80,10 @@ sb16midi_input_loop (); } -/* - * It looks like there is no input interrupts in the UART mode. Let's try - * polling. - */ - -static void -poll_sb16midi (unsigned long dummy) -{ - unsigned long flags; - - DEFINE_TIMER(sb16midi_timer, poll_sb16midi); - - if (!(sb16midi_opened & OPEN_READ)) - return; /* No longer required */ - - DISABLE_INTR (flags); - - if (input_avail ()) - sb16midi_input_loop (); - - ACTIVATE_TIMER(sb16midi_timer, poll_sb16midi, 1); /* Come back later */ - - RESTORE_INTR (flags); -} - static int sb16midi_open (int dev, int mode, - void (*input) (int dev, unsigned char data), - void (*output) (int dev) + void (*input) (int dev, unsigned char data), + void (*output) (int dev) ) { if (sb16midi_opened) @@ -127,7 +95,6 @@ midi_input_intr = input; sb16midi_opened = mode; - poll_sb16midi (0); /* Enable input polling */ return 0; } @@ -299,6 +266,8 @@ int ok = 0; sb16midi_base = hw_config->io_base; + if (sbc_major < 4) + return 0; /* SB16 not detected */ if (sb_get_irq () < 0) return 0; diff -uNr linux-1.0.9/drivers/sound/sb_card.c linux/drivers/sound/sb_card.c --- linux-1.0.9/drivers/sound/sb_card.c Thu Dec 9 23:24:43 1993 +++ linux/drivers/sound/sb_card.c Mon Apr 1 17:39:34 2002 @@ -1,10 +1,10 @@ /* * sound/sb_card.c - * + * * Detection routine for the SoundBlaster cards. - * + * * Copyright by Hannu Savolainen 1993 - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: 1. Redistributions of source code must retain the above copyright @@ -12,7 +12,7 @@ * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -24,7 +24,7 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * + * */ #include "sound_config.h" diff -uNr linux-1.0.9/drivers/sound/sb_dsp.c linux/drivers/sound/sb_dsp.c --- linux-1.0.9/drivers/sound/sb_dsp.c Sat Jan 8 13:35:09 1994 +++ linux/drivers/sound/sb_dsp.c Mon Apr 1 17:39:34 2002 @@ -1,10 +1,10 @@ /* * sound/sb_dsp.c - * + * * The low level driver for the SoundBlaster DSP chip. - * + * * Copyright by Hannu Savolainen 1993 - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: 1. Redistributions of source code must retain the above copyright @@ -12,7 +12,7 @@ * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -24,7 +24,11 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * + * + * Modified: + * Hunyue Yau Jan 6 1994 + * Added code to support Sound Galaxy NX Pro + * */ #include "sound_config.h" @@ -35,8 +39,9 @@ #include "sb_mixer.h" #undef SB_TEST_IRQ -int sbc_base = 0; +int sbc_base = 0; static int sbc_irq = 0; +static int open_mode=0; /* * The DSP channel can be used either for input or output. Variable @@ -46,32 +51,33 @@ * future version of this driver. */ -int sb_dsp_ok = 0; /* Set to 1 after successful initialization */ +int sb_dsp_ok = 0; /* Set to 1 after successful initialization */ static int midi_disabled = 0; -int sb_dsp_highspeed = 0; -static int major=1, minor=0; /* DSP version */ -static int dsp_stereo = 0; +int sb_dsp_highspeed = 0; +int sbc_major = 1; +int sbc_minor = 0; /* DSP version */ +static int dsp_stereo = 0; static int dsp_current_speed = DSP_DEFAULT_SPEED; static int sb16 = 0; -static int irq_verified = 0; +static int irq_verified = 0; -int sb_midi_mode = NORMAL_MIDI; -int sb_midi_busy = 0; /* 1 if the process has output to MIDI */ -int sb_dsp_busy = 0; +int sb_midi_mode = NORMAL_MIDI; +int sb_midi_busy = 0; /* 1 if the process has output to MIDI */ +int sb_dsp_busy = 0; + +volatile int sb_irq_mode = IMODE_NONE; /* IMODE_INPUT, IMODE_OUTPUT -volatile int sb_irq_mode = IMODE_NONE; /* IMODE_INPUT, IMODE_OUTPUT * or IMODE_NONE */ static volatile int irq_ok = 0; -int sb_dsp_model = 1; /* 1=SB, 2=SB Pro */ -int sb_duplex_midi = 0; +int sb_duplex_midi = 0; static int my_dev = 0; -volatile int sb_intr_active = 0; +volatile int sb_intr_active = 0; static int dsp_speed (int); static int dsp_set_stereo (int mode); -int sb_dsp_command (unsigned char val); +int sb_dsp_command (unsigned char val); #if !defined(EXCLUDE_MIDI) || !defined(EXCLUDE_AUDIO) @@ -80,9 +86,10 @@ int sb_dsp_command (unsigned char val) { - int i, limit; + int i; + unsigned long limit; - limit = GET_TIME () + 10; /* The timeout is 0.1 secods */ + limit = GET_TIME () + HZ / 10;/* The timeout is 0.1 secods */ /* * Note! the i<500000 is an emergency exit. The sb_dsp_command() is sometimes @@ -109,7 +116,7 @@ void sbintr (int unit) { - int status, data; + int status; #ifndef EXCLUDE_SBPRO if (sb16) @@ -117,10 +124,12 @@ unsigned char src = sb_getmixer (IRQ_STAT); /* Interrupt source register */ #ifndef EXCLUDE_SB16 - if (src & 3) sb16_dsp_interrupt(unit); + if (src & 3) + sb16_dsp_interrupt (unit); #ifndef EXCLUDE_MIDI - if (src & 4) sb16midiintr (unit); /* MPU401 interrupt */ + if (src & 4) + sb16midiintr (unit); /* MPU401 interrupt */ #endif #endif @@ -152,10 +161,7 @@ break; case IMODE_MIDI: - printk ("+"); - data = INB (DSP_READ); - printk ("%x", data); - + sb_midi_interrupt (unit); break; default: @@ -163,29 +169,32 @@ } } -static int sb_irq_usecount = 0; +static int sb_irq_usecount = 0; int -sb_get_irq(void) +sb_get_irq (void) { - int ok; + int ok; - if (!sb_irq_usecount) - if ((ok=snd_set_irq_handler(sbc_irq, sbintr))<0) return ok; + if (!sb_irq_usecount) + if ((ok = snd_set_irq_handler (sbc_irq, sbintr)) < 0) + return ok; - sb_irq_usecount++; + sb_irq_usecount++; - return 0; + return 0; } -void -sb_free_irq(void) +void +sb_free_irq (void) { - if (!sb_irq_usecount) return; + if (!sb_irq_usecount) + return; - sb_irq_usecount--; + sb_irq_usecount--; - if (!sb_irq_usecount) snd_release_irq(sbc_irq); + if (!sb_irq_usecount) + snd_release_irq (sbc_irq); } int @@ -227,17 +236,31 @@ { unsigned char tconst; unsigned long flags; + int max_speed = 44100; if (speed < 4000) speed = 4000; - if (speed > 44100) - speed = 44100; /* Invalid speed */ + /* + * Older SB models don't support higher speeds than 22050. + */ - if (sb_dsp_model == 1 && speed > 22050) - speed = 22050; - /* SB Classic doesn't support higher speed */ + if (sbc_major < 2 || + (sbc_major == 2 && sbc_minor == 0)) + max_speed = 22050; + + /* + * SB models earlier than SB Pro have low limit for the input speed. + */ + if (open_mode != OPEN_WRITE) /* Recording is possible */ + if (sbc_major < 3) /* Limited input speed with these cards */ + if (sbc_major == 2 && sbc_minor > 0) + max_speed = 15000; + else + max_speed = 13000; + if (speed > max_speed) + speed = max_speed; /* Invalid speed */ if (dsp_stereo && speed > 22050) speed = 22050; @@ -256,10 +279,10 @@ if (speed > 22050) { /* High speed mode */ - int tmp; + int tmp; - tconst = (unsigned char) ((65536 - - ((256000000+speed/2) / speed)) >> 8); + tconst = (unsigned char) ((65536 - + ((256000000 + speed / 2) / speed)) >> 8); sb_dsp_highspeed = 1; DISABLE_INTR (flags); @@ -268,22 +291,22 @@ RESTORE_INTR (flags); tmp = 65536 - (tconst << 8); - speed = (256000000+tmp/2) / tmp; + speed = (256000000 + tmp / 2) / tmp; } else { - int tmp; + int tmp; sb_dsp_highspeed = 0; - tconst = (256 - ((1000000+speed/2) / speed)) & 0xff; + tconst = (256 - ((1000000 + speed / 2) / speed)) & 0xff; DISABLE_INTR (flags); - if (sb_dsp_command (0x40)) /* Set time constant */ + if (sb_dsp_command (0x40))/* Set time constant */ sb_dsp_command (tconst); RESTORE_INTR (flags); tmp = 256 - tconst; - speed = (1000000+tmp/2) / tmp; + speed = (1000000 + tmp / 2) / tmp; } if (dsp_stereo) @@ -301,7 +324,7 @@ #ifdef EXCLUDE_SBPRO return 0; #else - if (sb_dsp_model == 1 || sb16) + if (sbc_major < 3 || sb16) return 0; /* Sorry no stereo */ if (mode && sb_midi_busy) @@ -316,7 +339,7 @@ } static void -sb_dsp_output_block (int dev, unsigned long buf, int count, +sb_dsp_output_block (int dev, unsigned long buf, int count, int intrflag, int restart_dma) { unsigned long flags; @@ -334,11 +357,11 @@ if (sb_dsp_highspeed) { DISABLE_INTR (flags); - if (sb_dsp_command (0x48)) /* High speed size */ + if (sb_dsp_command (0x48))/* High speed size */ { - sb_dsp_command ((unsigned char)(count & 0xff)); - sb_dsp_command ((unsigned char)((count >> 8) & 0xff)); - sb_dsp_command (0x91); /* High speed 8 bit DAC */ + sb_dsp_command ((unsigned char) (count & 0xff)); + sb_dsp_command ((unsigned char) ((count >> 8) & 0xff)); + sb_dsp_command (0x91);/* High speed 8 bit DAC */ } else printk ("SB Error: Unable to start (high speed) DAC\n"); @@ -347,10 +370,10 @@ else { DISABLE_INTR (flags); - if (sb_dsp_command (0x14)) /* 8-bit DAC (DMA) */ + if (sb_dsp_command (0x14))/* 8-bit DAC (DMA) */ { - sb_dsp_command ((unsigned char)(count & 0xff)); - sb_dsp_command ((unsigned char)((count >> 8) & 0xff)); + sb_dsp_command ((unsigned char) (count & 0xff)); + sb_dsp_command ((unsigned char) ((count >> 8) & 0xff)); } else printk ("SB Error: Unable to start DAC\n"); @@ -380,11 +403,11 @@ if (sb_dsp_highspeed) { DISABLE_INTR (flags); - if (sb_dsp_command (0x48)) /* High speed size */ + if (sb_dsp_command (0x48))/* High speed size */ { - sb_dsp_command ((unsigned char)(count & 0xff)); - sb_dsp_command ((unsigned char)((count >> 8) & 0xff)); - sb_dsp_command (0x99); /* High speed 8 bit ADC */ + sb_dsp_command ((unsigned char) (count & 0xff)); + sb_dsp_command ((unsigned char) ((count >> 8) & 0xff)); + sb_dsp_command (0x99);/* High speed 8 bit ADC */ } else printk ("SB Error: Unable to start (high speed) ADC\n"); @@ -393,10 +416,10 @@ else { DISABLE_INTR (flags); - if (sb_dsp_command (0x24)) /* 8-bit ADC (DMA) */ + if (sb_dsp_command (0x24))/* 8-bit ADC (DMA) */ { - sb_dsp_command ((unsigned char)(count & 0xff)); - sb_dsp_command ((unsigned char)((count >> 8) & 0xff)); + sb_dsp_command ((unsigned char) (count & 0xff)); + sb_dsp_command ((unsigned char) ((count >> 8) & 0xff)); } else printk ("SB Error: Unable to start ADC\n"); @@ -418,16 +441,16 @@ dsp_cleanup (); dsp_speaker (OFF); - if (major == 3) /* SB Pro */ - { - if (dsp_stereo) - sb_dsp_command(0xa8); - else - sb_dsp_command(0xa0); + if (sbc_major == 3) /* SB Pro */ + { + if (dsp_stereo) + sb_dsp_command (0xa8); + else + sb_dsp_command (0xa0); - dsp_speed (dsp_current_speed);/* Speed must be recalculated if #channels - * changes */ - } + dsp_speed (dsp_current_speed); /* Speed must be recalculated if #channels + * changes */ + } return 0; } @@ -438,12 +461,12 @@ dsp_speaker (ON); #ifndef EXCLUDE_SBPRO - if (major == 3) /* SB Pro */ - { - sb_mixer_set_stereo(dsp_stereo); - dsp_speed (dsp_current_speed);/* Speed must be recalculated if #channels - * changes */ - } + if (sbc_major == 3) /* SB Pro */ + { + sb_mixer_set_stereo (dsp_stereo); + dsp_speed (dsp_current_speed); /* Speed must be recalculated if #channels + * changes */ + } #endif return 0; } @@ -457,7 +480,7 @@ verify_irq (void) { #if 0 - DEFINE_WAIT_QUEUE(testq, testf); + DEFINE_WAIT_QUEUE (testq, testf); irq_ok = 0; @@ -470,11 +493,11 @@ sb_irq_mode = IMODE_INIT; - sb_dsp_command (0xf2); /* This should cause immediate interrupt */ + sb_dsp_command (0xf2); /* This should cause immediate interrupt */ - DO_SLEEP(testq, testf, HZ / 5); + DO_SLEEP (testq, testf, HZ / 5); - sb_free_irq(); + sb_free_irq (); if (!irq_ok) { @@ -506,13 +529,12 @@ if (!irq_verified) { - verify_irq(); - irq_verified = 1; + verify_irq (); + irq_verified = 1; } - else - if (!irq_ok) - printk("SB Warning: Incorrect IRQ setting %d\n", - sbc_irq); + else if (!irq_ok) + printk ("SB Warning: Incorrect IRQ setting %d\n", + sbc_irq); retval = sb_get_irq (); if (retval) @@ -528,6 +550,7 @@ sb_irq_mode = IMODE_NONE; sb_dsp_busy = 1; + open_mode = mode; return 0; } @@ -541,6 +564,7 @@ dsp_speaker (OFF); sb_dsp_busy = 0; sb_dsp_highspeed = 0; + open_mode = 0; } static int @@ -562,7 +586,7 @@ case SOUND_PCM_WRITE_CHANNELS: if (local) - return dsp_set_stereo (arg - 1) + 1; + return dsp_set_stereo (arg - 1) + 1; return IOCTL_OUT (arg, dsp_set_stereo (IOCTL_IN (arg) - 1) + 1); break; @@ -605,6 +629,7 @@ DISABLE_INTR (flags); sb_reset_dsp (); + dsp_speed (dsp_current_speed); dsp_cleanup (); RESTORE_INTR (flags); @@ -631,6 +656,7 @@ static struct audio_operations sb_dsp_operations = { "SoundBlaster", + NOTHING_SPECIAL, sb_dsp_open, sb_dsp_close, sb_dsp_output_block, @@ -650,80 +676,85 @@ sb_dsp_init (long mem_start, struct address_info *hw_config) { int i; + int prostat = 0; - major = minor = 0; - sb_dsp_command (0xe1); /* Get version */ + sbc_major = sbc_minor = 0; + sb_dsp_command (0xe1); /* Get version */ for (i = 1000; i; i--) { if (INB (DSP_DATA_AVAIL) & 0x80) { /* wait for Data Ready */ - if (major == 0) - major = INB (DSP_READ); + if (sbc_major == 0) + sbc_major = INB (DSP_READ); else { - minor = INB (DSP_READ); + sbc_minor = INB (DSP_READ); break; } } } - if (major == 2 || major == 3) - sb_duplex_midi = 1; + if (sbc_major == 2 || sbc_major == 3) /* SB 2.0 or SB Pro */ + sb_duplex_midi = 1; - if (major == 4) - sb16 = 1; - - if (major >= 3) - sb_dsp_model = 2; + if (sbc_major == 4) + sb16 = 1; #ifndef EXCLUDE_SBPRO - if (major >= 3) - sb_mixer_init(major); + if (sbc_major >= 3 || + (sbc_major == 2 && sbc_minor == 1)) /* Sound Galaxy ??? */ + prostat = sb_mixer_init (sbc_major); #endif #ifndef EXCLUDE_YM3812 - if (major > 3 || (major == 3 && minor > 0)) /* SB Pro2 or later */ - { - enable_opl3_mode (OPL3_LEFT, OPL3_RIGHT, OPL3_BOTH); - } + if (sbc_major > 3 || + (sbc_major == 3 && INB (0x388) == 0x00)) /* Non OPL-3 should return 0x06 */ + enable_opl3_mode (OPL3_LEFT, OPL3_RIGHT, OPL3_BOTH); #endif - if (major >= 3) - { + if (sbc_major >= 3) + { #ifndef SCO - sprintf (sb_dsp_operations.name, "SoundBlaster Pro %d.%d", major, minor); + if (prostat) + { + sprintf (sb_dsp_operations.name, "Sound Galaxy NX Pro %d.%d", sbc_major, sbc_minor); + } + else + { + sprintf (sb_dsp_operations.name, "SoundBlaster Pro %d.%d", sbc_major, sbc_minor); + } #endif - } - else - { + } + else + { #ifndef SCO - sprintf (sb_dsp_operations.name, "SoundBlaster %d.%d", major, minor); + sprintf (sb_dsp_operations.name, "SoundBlaster %d.%d", sbc_major, sbc_minor); #endif - } + } printk (" <%s>", sb_dsp_operations.name); #ifndef EXCLUDE_AUDIO -# if !defined(EXCLUDE_SB16) && !defined(EXCLUDE_SBPRO) - if (!sb16) /* There is a better driver for SB16 */ -# endif - if (num_dspdevs < MAX_DSP_DEV) - { - dsp_devs[my_dev = num_dspdevs++] = &sb_dsp_operations; - sound_buffcounts[my_dev] = DSP_BUFFCOUNT; - sound_buffsizes[my_dev] = DSP_BUFFSIZE; - sound_dsp_dmachan[my_dev] = hw_config->dma; - sound_dma_automode[my_dev] = 0; - } - else - printk ("SB: Too many DSP devices available\n"); +#if !defined(EXCLUDE_SB16) && !defined(EXCLUDE_SBPRO) + if (!sb16) /* There is a better driver for SB16 */ +#endif + if (num_dspdevs < MAX_DSP_DEV) + { + dsp_devs[my_dev = num_dspdevs++] = &sb_dsp_operations; + sound_buffcounts[my_dev] = DSP_BUFFCOUNT; + sound_buffsizes[my_dev] = DSP_BUFFSIZE; + sound_dsp_dmachan[my_dev] = hw_config->dma; + sound_dma_automode[my_dev] = 0; + } + else + printk ("SB: Too many DSP devices available\n"); #endif #ifndef EXCLUDE_MIDI if (!midi_disabled && !sb16) /* Midi don't work in the SB emulation mode * of PAS, SB16 has better midi interface */ - sb_midi_init(major); + sb_midi_init (sbc_major); #endif sb_dsp_ok = 1; diff -uNr linux-1.0.9/drivers/sound/sb_midi.c linux/drivers/sound/sb_midi.c --- linux-1.0.9/drivers/sound/sb_midi.c Thu Dec 2 10:56:16 1993 +++ linux/drivers/sound/sb_midi.c Mon Apr 1 17:39:34 2002 @@ -1,10 +1,10 @@ /* * sound/sb_dsp.c - * + * * The low level driver for the SoundBlaster DS chips. - * + * * Copyright by Hannu Savolainen 1993 - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: 1. Redistributions of source code must retain the above copyright @@ -12,7 +12,7 @@ * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -24,7 +24,7 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * + * */ #include "sound_config.h" @@ -49,11 +49,16 @@ extern int sb_dsp_busy; extern int sb_dsp_highspeed; -extern volatile int sb_irq_mode; /* IMODE_INPUT, IMODE_OUTPUT +extern volatile int sb_irq_mode;/* IMODE_INPUT, IMODE_OUTPUT + * or IMODE_NONE */ -extern int sb_dsp_model; /* 1=SB, 2=SB Pro */ extern int sb_duplex_midi; extern int sb_intr_active; +extern int sbc_base; + +static int input_opened = 0; +static void (*midi_input_intr) (int dev, unsigned char data); +static int my_dev = 0; static int sb_midi_open (int dev, int mode, @@ -72,7 +77,7 @@ if (mode != OPEN_WRITE && !sb_duplex_midi) { if (num_midis == 1) - printk ("SoundBlaster: Midi input not currently supported\n"); + printk ("SoundBlaster: MIDI input not supported with plain SB\n"); return RET_ERROR (EPERM); } @@ -96,6 +101,9 @@ sb_reset_dsp (); + if (!sb_dsp_command (0xf2)) /* This is undodumented, isn't it */ + return RET_ERROR (EIO); /* be nice to DSP */ + if (!sb_dsp_command (0x35)) return RET_ERROR (EIO); /* Enter the UART mode */ sb_intr_active = 1; @@ -105,6 +113,9 @@ sb_reset_dsp (); return 0; /* IRQ not free */ } + input_opened = 1; + my_dev = dev; + midi_input_intr = input; } sb_midi_busy = 1; @@ -122,6 +133,7 @@ } sb_intr_active = 0; sb_midi_busy = 0; + input_opened = 0; } static int @@ -174,6 +186,21 @@ return RET_ERROR (EPERM); } +void +sb_midi_interrupt (int dummy) +{ + unsigned long flags; + unsigned char data; + + DISABLE_INTR (flags); + + data = INB (DSP_READ); + if (input_opened) + midi_input_intr (my_dev, data); + + RESTORE_INTR (flags); +} + static struct midi_operations sb_midi_operations = { {"SoundBlaster", 0, 0, SNDCARD_SB}, @@ -189,7 +216,7 @@ }; void -sb_midi_init(int model) +sb_midi_init (int model) { midi_devs[num_midis++] = &sb_midi_operations; } diff -uNr linux-1.0.9/drivers/sound/sb_mixer.c linux/drivers/sound/sb_mixer.c --- linux-1.0.9/drivers/sound/sb_mixer.c Fri Dec 10 00:19:23 1993 +++ linux/drivers/sound/sb_mixer.c Mon Apr 1 17:39:34 2002 @@ -1,11 +1,11 @@ /* * sound/sb_mixer.c - * + * * The low level mixer driver for the SoundBlaster Pro and SB16 cards. - * + * * Copyright by Hannu Savolainen 1993 - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: 1. Redistributions of source code must retain the above copyright @@ -13,7 +13,7 @@ * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -25,7 +25,11 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * + * + * Modified: + * Hunyue Yau Jan 6 1994 + * Added code to support the Sound Galaxy NX Pro mixer. + * */ #include "sound_config.h" @@ -39,56 +43,69 @@ extern int sbc_base; -static int mixer_initialized = 0; +static int mixer_initialized = 0; -static int supported_rec_devices; -static int supported_devices; -static int recmask = 0; -static int mixer_model; -static int mixer_caps; +static int supported_rec_devices; +static int supported_devices; +static int recmask = 0; +static int mixer_model; +static int mixer_caps; static mixer_tab *iomap; void sb_setmixer (unsigned int port, unsigned int value) { - unsigned long flags; + unsigned long flags; - DISABLE_INTR(flags); - OUTB ((unsigned char)(port & 0xff), MIXER_ADDR); /* Select register */ + DISABLE_INTR (flags); + OUTB ((unsigned char) (port & 0xff), MIXER_ADDR); /* Select register */ tenmicrosec (); - OUTB ((unsigned char)(value & 0xff), MIXER_DATA); + OUTB ((unsigned char) (value & 0xff), MIXER_DATA); tenmicrosec (); - RESTORE_INTR(flags); + RESTORE_INTR (flags); } int sb_getmixer (unsigned int port) { int val; - unsigned long flags; + unsigned long flags; - DISABLE_INTR(flags); - OUTB ((unsigned char)(port & 0xff), MIXER_ADDR); /* Select register */ + DISABLE_INTR (flags); + OUTB ((unsigned char) (port & 0xff), MIXER_ADDR); /* Select register */ tenmicrosec (); val = INB (MIXER_DATA); tenmicrosec (); - RESTORE_INTR(flags); + RESTORE_INTR (flags); return val; } void -sb_mixer_set_stereo(int mode) +sb_mixer_set_stereo (int mode) { - if (!mixer_initialized) return; + if (!mixer_initialized) + return; sb_setmixer (OUT_FILTER, ((sb_getmixer (OUT_FILTER) & ~STEREO_DAC) - | (mode ? STEREO_DAC : MONO_DAC))); + | (mode ? STEREO_DAC : MONO_DAC))); } +/* + * Returns: + * 0 No mixer detected. + * 1 Only a plain Sound Blaster Pro style mixer detected. + * 2 The Sound Galaxy NX Pro mixer detected. + */ static int detect_mixer (void) { +#ifdef __SGNXPRO__ + int oldbass, oldtreble; + +#endif + int retcode = 1; + /* * Detect the mixer by changing parameters of two volume channels. If the * values read back match with the values written, the mixer is there (is @@ -102,95 +119,121 @@ if (sb_getmixer (VOC_VOL) != 0x33) return 0; - return 1; +#ifdef __SGNXPRO__ + /* Attempt to detect the SG NX Pro by check for valid bass/treble + * registers. + */ + oldbass = sb_getmixer (BASS_LVL); + oldtreble = sb_getmixer (TREBLE_LVL); + + sb_setmixer (BASS_LVL, 0xaa); + sb_setmixer (TREBLE_LVL, 0x55); + + if ((sb_getmixer (BASS_LVL) != 0xaa) || + (sb_getmixer (TREBLE_LVL) != 0x55)) + { + retcode = 1; /* 1 == Only SB Pro detected */ + } + else + retcode = 2; /* 2 == SG NX Pro detected */ + /* Restore register in either case since SG NX Pro has EEPROM with + * 'preferred' values stored. + */ + sb_setmixer (BASS_LVL, oldbass); + sb_setmixer (TREBLE_LVL, oldtreble); +#endif + return retcode; } static void -change_bits(unsigned char *regval, int dev, int chn, int newval) +change_bits (unsigned char *regval, int dev, int chn, int newval) { - unsigned char mask; - int shift; + unsigned char mask; + int shift; - mask = (1 << (*iomap)[dev][chn].nbits)-1; - newval = ((newval * mask) + 50) / 100; /* Scale it */ + mask = (1 << (*iomap)[dev][chn].nbits) - 1; + newval = ((newval * mask) + 50) / 100; /* Scale it */ - shift = (*iomap)[dev][chn].bitoffs-(*iomap)[dev][LEFT_CHN].nbits+1; + shift = (*iomap)[dev][chn].bitoffs - (*iomap)[dev][LEFT_CHN].nbits + 1; - *regval &= ~(mask << shift); /* Filter out the previous value */ - *regval |= (newval & mask) << shift; /* Set the new value */ + *regval &= ~(mask << shift); /* Filter out the previous value */ + *regval |= (newval & mask) << shift; /* Set the new value */ } static int -sb_mixer_get(int dev) +sb_mixer_get (int dev) { - if (!((1<> 8; + int left = value & 0x000000ff; + int right = (value & 0x0000ff00) >> 8; - int regoffs; - unsigned char val; + int regoffs; + unsigned char val; - if (left > 100) left = 100; - if (right > 100) right = 100; + if (left > 100) + left = 100; + if (right > 100) + right = 100; - if (dev > 31) return RET_ERROR(EINVAL); + if (dev > 31) + return RET_ERROR (EINVAL); - if (!(supported_devices & (1 << dev))) /* Not supported */ - return RET_ERROR(EINVAL); + if (!(supported_devices & (1 << dev))) /* Not supported */ + return RET_ERROR (EINVAL); - regoffs = (*iomap)[dev][LEFT_CHN].regno; + regoffs = (*iomap)[dev][LEFT_CHN].regno; - if (regoffs == 0) - return RET_ERROR(EINVAL); + if (regoffs == 0) + return RET_ERROR (EINVAL); - val = sb_getmixer(regoffs); - change_bits(&val, dev, LEFT_CHN, left); + val = sb_getmixer (regoffs); + change_bits (&val, dev, LEFT_CHN, left); - levels[dev] = left|(left << 8); + levels[dev] = left | (left << 8); - if ((*iomap)[dev][RIGHT_CHN].regno != regoffs) /* Change register */ - { - sb_setmixer(regoffs, val); /* Save the old one */ - regoffs = (*iomap)[dev][RIGHT_CHN].regno; + if ((*iomap)[dev][RIGHT_CHN].regno != regoffs) /* Change register */ + { + sb_setmixer (regoffs, val); /* Save the old one */ + regoffs = (*iomap)[dev][RIGHT_CHN].regno; - if (regoffs == 0) - return left|(left << 8); /* Just left channel present */ + if (regoffs == 0) + return left | (left << 8); /* Just left channel present */ - val = sb_getmixer(regoffs); /* Read the new one */ - } + val = sb_getmixer (regoffs); /* Read the new one */ + } - change_bits(&val, dev, RIGHT_CHN, right); - sb_setmixer(regoffs, val); + change_bits (&val, dev, RIGHT_CHN, right); + sb_setmixer (regoffs, val); - levels[dev] = left | (right << 8); - return left | (right << 8); + levels[dev] = left | (right << 8); + return left | (right << 8); } static void -set_recsrc(int src) +set_recsrc (int src) { - sb_setmixer(RECORD_SRC, (sb_getmixer(RECORD_SRC)&~7) | (src&0x7)); + sb_setmixer (RECORD_SRC, (sb_getmixer (RECORD_SRC) & ~7) | (src & 0x7)); } static int -set_recmask(int mask) +set_recmask (int mask) { - int devmask, i; - unsigned char regimageL, regimageR; + int devmask, i; + unsigned char regimageL, regimageR; - devmask = mask & supported_rec_devices; + devmask = mask & supported_rec_devices; - switch (mixer_model) - { - case 3: + switch (mixer_model) + { + case 3: if (devmask != SOUND_MASK_MIC && devmask != SOUND_MASK_LINE && @@ -209,7 +252,7 @@ } - if (devmask ^ recmask)/* Input source changed */ + if (devmask ^ recmask) /* Input source changed */ { switch (devmask) { @@ -233,23 +276,24 @@ break; - case 4: - if (!devmask) devmask = SOUND_MASK_MIC; - - regimageL = regimageR = 0; - for (i=0;i> 8) & 0xff) == 'M') { if (cmd & IOC_IN) - switch (cmd & 0xff) - { - case SOUND_MIXER_RECSRC: - return IOCTL_OUT(arg, set_recmask(IOCTL_IN(arg))); - break; - - default: - return IOCTL_OUT (arg, sb_mixer_set (cmd & 0xff, IOCTL_IN (arg))); - } - else - switch (cmd & 0xff) /* Return parameters */ - { - - case SOUND_MIXER_RECSRC: - return IOCTL_OUT (arg, recmask); - break; - - case SOUND_MIXER_DEVMASK: - return IOCTL_OUT (arg, supported_devices); - break; + switch (cmd & 0xff) + { + case SOUND_MIXER_RECSRC: + return IOCTL_OUT (arg, set_recmask (IOCTL_IN (arg))); + break; - case SOUND_MIXER_STEREODEVS: - return IOCTL_OUT (arg, supported_devices & - ~(SOUND_MASK_MIC|SOUND_MASK_SPEAKER)); - break; + default: + return IOCTL_OUT (arg, sb_mixer_set (cmd & 0xff, IOCTL_IN (arg))); + } + else + switch (cmd & 0xff) /* Return parameters */ + { - case SOUND_MIXER_RECMASK: - return IOCTL_OUT (arg, supported_rec_devices); - break; + case SOUND_MIXER_RECSRC: + return IOCTL_OUT (arg, recmask); + break; + + case SOUND_MIXER_DEVMASK: + return IOCTL_OUT (arg, supported_devices); + break; + + case SOUND_MIXER_STEREODEVS: + return IOCTL_OUT (arg, supported_devices & + ~(SOUND_MASK_MIC | SOUND_MASK_SPEAKER)); + break; + + case SOUND_MIXER_RECMASK: + return IOCTL_OUT (arg, supported_rec_devices); + break; + + case SOUND_MIXER_CAPS: + return IOCTL_OUT (arg, mixer_caps); + break; - case SOUND_MIXER_CAPS: - return IOCTL_OUT (arg, mixer_caps); - break; - - default: - return IOCTL_OUT (arg, sb_mixer_get (cmd & 0xff)); - } + default: + return IOCTL_OUT (arg, sb_mixer_get (cmd & 0xff)); + } } else return RET_ERROR (EINVAL); @@ -306,48 +350,73 @@ }; static void -sb_mixer_reset(void) +sb_mixer_reset (void) { - int i; + int i; for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) sb_mixer_set (i, levels[i]); - set_recmask(SOUND_MASK_MIC); + set_recmask (SOUND_MASK_MIC); } -void -sb_mixer_init(int major_model) +/* + * Returns a code depending on whether a SG NX Pro was detected. + * 0 == Plain SB 16 or SB Pro + * 1 == SG NX Pro detected. + * + * Used to update message. + */ +int +sb_mixer_init (int major_model) { - sb_setmixer(0x00, 0); /* Reset mixer */ + int mixerstat; + + sb_setmixer (0x00, 0); /* Reset mixer */ - if (!detect_mixer()) return; /* No mixer. Why? */ + mixerstat = detect_mixer (); - mixer_initialized = 1; - mixer_model = major_model; + if (!mixerstat) + return 0; /* No mixer. Why? */ - switch (major_model) - { - case 3: - mixer_caps = SOUND_CAP_EXCL_INPUT; + mixer_initialized = 1; + mixer_model = major_model; + + switch (major_model) + { + case 3: + mixer_caps = SOUND_CAP_EXCL_INPUT; +#ifdef __SGNXPRO__ + if (mixerstat == 2) + { /* A SGNXPRO was detected */ + supported_devices = SGNXPRO_MIXER_DEVICES; + supported_rec_devices = SGNXPRO_RECORDING_DEVICES; + iomap = &sgnxpro_mix; + } + else +#endif + { /* Otherwise plain SB Pro */ supported_devices = SBPRO_MIXER_DEVICES; supported_rec_devices = SBPRO_RECORDING_DEVICES; iomap = &sbpro_mix; - break; - - case 4: - mixer_caps = 0; - supported_devices = SB16_MIXER_DEVICES; - supported_rec_devices = SB16_RECORDING_DEVICES; - iomap = &sb16_mix; - break; - - default: - printk("SB Warning: Unsupported mixer type\n"); - return; } - mixer_devs[num_mixers++] = &sb_mixer_operations; - sb_mixer_reset(); + break; + + case 4: + mixer_caps = 0; + supported_devices = SB16_MIXER_DEVICES; + supported_rec_devices = SB16_RECORDING_DEVICES; + iomap = &sb16_mix; + break; + + default: + printk ("SB Warning: Unsupported mixer type\n"); + return 0; + } + + mixer_devs[num_mixers++] = &sb_mixer_operations; + sb_mixer_reset (); + return (mixerstat == 2); } #endif diff -uNr linux-1.0.9/drivers/sound/sb_mixer.h linux/drivers/sound/sb_mixer.h --- linux-1.0.9/drivers/sound/sb_mixer.h Tue Dec 14 02:04:54 1993 +++ linux/drivers/sound/sb_mixer.h Mon Apr 1 17:39:34 2002 @@ -24,13 +24,29 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. + * + * Modified: + * Hunyue Yau Jan 6 1994 + * Added defines for the Sound Galaxy NX Pro mixer. * */ + #define SBPRO_RECORDING_DEVICES (SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD) +/* Same as SB Pro, unless I find otherwise */ +#define SGNXPRO_RECORDING_DEVICES SBPRO_RECORDING_DEVICES + #define SBPRO_MIXER_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_LINE | SOUND_MASK_MIC | \ SOUND_MASK_CD | SOUND_MASK_VOLUME) +/* SG NX Pro has treble and bass settings on the mixer. The 'speaker' + * channel is the COVOX/DisneySoundSource emulation volume control + * on the mixer. It does NOT control speaker volume. Should have own + * mask eventually? + */ +#define SGNXPRO_MIXER_DEVICES (SBPRO_MIXER_DEVICES|SOUND_MASK_BASS| \ + SOUND_MASK_TREBLE|SOUND_MASK_SPEAKER ) + #define SB16_RECORDING_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_LINE | SOUND_MASK_MIC | \ SOUND_MASK_CD) @@ -62,6 +78,13 @@ #define IRQ_STAT 0x82 #define OPSW 0x3c +/* + * Additional registers on the SG NX Pro + */ +#define COVOX_VOL 0x42 +#define TREBLE_LVL 0x44 +#define BASS_LVL 0x46 + #define FREQ_HI (1 << 3)/* Use High-frequency ANFI filters */ #define FREQ_LOW 0 /* Use Low-frequency ANFI filters */ #define FILT_ON 0 /* Yes, 0 to turn it on, 1 for off */ @@ -108,6 +131,23 @@ MIX_ENT(SOUND_MIXER_RECLEV, 0x00, 0, 0, 0x00, 0, 0) }; +#ifdef __SGNXPRO__ +mixer_tab sgnxpro_mix = { +MIX_ENT(SOUND_MIXER_VOLUME, 0x22, 7, 4, 0x22, 3, 4), +MIX_ENT(SOUND_MIXER_BASS, 0x46, 2, 3, 0x00, 0, 0), +MIX_ENT(SOUND_MIXER_TREBLE, 0x44, 2, 3, 0x00, 0, 0), +MIX_ENT(SOUND_MIXER_SYNTH, 0x26, 7, 4, 0x26, 3, 4), +MIX_ENT(SOUND_MIXER_PCM, 0x04, 7, 4, 0x04, 3, 4), +MIX_ENT(SOUND_MIXER_SPEAKER, 0x42, 2, 3, 0x00, 0, 0), +MIX_ENT(SOUND_MIXER_LINE, 0x2e, 7, 4, 0x2e, 3, 4), +MIX_ENT(SOUND_MIXER_MIC, 0x0a, 2, 3, 0x00, 0, 0), +MIX_ENT(SOUND_MIXER_CD, 0x28, 7, 4, 0x28, 3, 4), +MIX_ENT(SOUND_MIXER_IMIX, 0x00, 0, 0, 0x00, 0, 0), +MIX_ENT(SOUND_MIXER_ALTPCM, 0x00, 0, 0, 0x00, 0, 0), +MIX_ENT(SOUND_MIXER_RECLEV, 0x00, 0, 0, 0x00, 0, 0) +}; +#endif + mixer_tab sb16_mix = { MIX_ENT(SOUND_MIXER_VOLUME, 0x30, 7, 5, 0x31, 7, 5), MIX_ENT(SOUND_MIXER_BASS, 0x46, 7, 4, 0x47, 7, 4), diff -uNr linux-1.0.9/drivers/sound/sequencer.c linux/drivers/sound/sequencer.c --- linux-1.0.9/drivers/sound/sequencer.c Tue Dec 14 01:19:51 1993 +++ linux/drivers/sound/sequencer.c Mon Apr 1 17:39:34 2002 @@ -1,10 +1,10 @@ /* * sound/sequencer.c - * + * * The sequencer personality manager. - * + * * Copyright by Hannu Savolainen 1993 - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: 1. Redistributions of source code must retain the above copyright @@ -12,7 +12,7 @@ * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -24,7 +24,7 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * + * */ #define SEQUENCER_C @@ -46,7 +46,7 @@ static int midi_written[MAX_MIDI_DEV] = {0}; -long seq_time = 0; /* Reference point for the timer */ +unsigned long seq_time = 0; /* Reference point for the timer */ #include "tuning.h" @@ -87,6 +87,9 @@ { if (!iqlen) { + if (c != count) /* Some data has been received */ + return count - c; /* Return what we have */ + DO_SLEEP (midi_sleeper, midi_sleep_flag, 0); if (!iqlen) @@ -327,6 +330,10 @@ synth_devs[dev]->controller (dev, q[3], q[4], *(short *) &q[5]); break; + case SEQ_VOLMODE: + synth_devs[dev]->volume_method (dev, q[3]); + break; + default: return RET_ERROR (EINVAL); } @@ -346,7 +353,7 @@ qhead = ((this_one = qhead) + 1) % SEQ_MAX_QUEUE; qlen--; - q = &queue[this_one*EV_SZ]; + q = &queue[this_one * EV_SZ]; switch (q[0]) { @@ -463,87 +470,87 @@ int sequencer_open (int dev, struct fileinfo *file) - { - int retval, mode, i; +{ + int retval, mode, i; - dev = dev >> 4; - mode = file->mode & O_ACCMODE; + dev = dev >> 4; + mode = file->mode & O_ACCMODE; - DEB (printk ("sequencer_open(dev=%d)\n", dev)); + DEB (printk ("sequencer_open(dev=%d)\n", dev)); - if (!sequencer_ok) - { - printk ("Soundcard: Sequencer not initialized\n"); - return RET_ERROR (ENXIO); - } + if (!sequencer_ok) + { + printk ("Soundcard: Sequencer not initialized\n"); + return RET_ERROR (ENXIO); + } - if (dev) /* Patch manager device */ - { - int err; + if (dev) /* Patch manager device */ + { + int err; - dev--; - if (pmgr_present[dev]) - return RET_ERROR (EBUSY); - if ((err = pmgr_open (dev)) < 0) - return err; /* Failed */ + dev--; + if (pmgr_present[dev]) + return RET_ERROR (EBUSY); + if ((err = pmgr_open (dev)) < 0) + return err; /* Failed */ - pmgr_present[dev] = 1; - return err; - } + pmgr_present[dev] = 1; + return err; + } - if (sequencer_busy) - { - printk ("Sequencer busy\n"); - return RET_ERROR (EBUSY); - } + if (sequencer_busy) + { + printk ("Sequencer busy\n"); + return RET_ERROR (EBUSY); + } - if (!(num_synths + num_midis)) - return RET_ERROR (ENXIO); + if (!(num_synths + num_midis)) + return RET_ERROR (ENXIO); - synth_open_mask = 0; + synth_open_mask = 0; - if (mode == OPEN_WRITE || mode == OPEN_READWRITE) - for (i = 0; i < num_synths; i++) /* Open synth devices */ - if (synth_devs[i]->open (i, mode) < 0) - printk ("Sequencer: Warning! Cannot open synth device #%d\n", i); - else - synth_open_mask |= (1 << i); + if (mode == OPEN_WRITE || mode == OPEN_READWRITE) + for (i = 0; i < num_synths; i++) /* Open synth devices */ + if (synth_devs[i]->open (i, mode) < 0) + printk ("Sequencer: Warning! Cannot open synth device #%d\n", i); + else + synth_open_mask |= (1 << i); - seq_time = GET_TIME (); + seq_time = GET_TIME (); - for (i = 0; i < num_midis; i++) - { - midi_opened[i] = 0; - midi_written[i] = 0; - } + for (i = 0; i < num_midis; i++) + { + midi_opened[i] = 0; + midi_written[i] = 0; + } - if (mode == OPEN_READ || mode == OPEN_READWRITE) - { /* Initialize midi input devices */ - if (!num_midis) - { - printk ("Sequencer: No Midi devices. Input not possible\n"); - return RET_ERROR (ENXIO); - } + if (mode == OPEN_READ || mode == OPEN_READWRITE) + { /* Initialize midi input devices */ + if (!num_midis) + { + printk ("Sequencer: No Midi devices. Input not possible\n"); + return RET_ERROR (ENXIO); + } - for (i = 0; i < num_midis; i++) - { - if ((retval = midi_devs[i]->open (i, mode, + for (i = 0; i < num_midis; i++) + { + if ((retval = midi_devs[i]->open (i, mode, sequencer_midi_input, sequencer_midi_output)) >= 0) - midi_opened[i] = 1; - } - } + midi_opened[i] = 1; + } + } - sequencer_busy = 1; - RESET_WAIT_QUEUE (seq_sleeper, seq_sleep_flag); - RESET_WAIT_QUEUE (midi_sleeper, midi_sleep_flag); - output_treshold = SEQ_MAX_QUEUE / 2; + sequencer_busy = 1; + RESET_WAIT_QUEUE (seq_sleeper, seq_sleep_flag); + RESET_WAIT_QUEUE (midi_sleeper, midi_sleep_flag); + output_treshold = SEQ_MAX_QUEUE / 2; - for (i = 0; i < num_synths; i++) - if (pmgr_present[i]) - pmgr_inform (i, PM_E_OPENED, 0, 0, 0, 0); + for (i = 0; i < num_synths; i++) + if (pmgr_present[i]) + pmgr_inform (i, PM_E_OPENED, 0, 0, 0, 0); - return 0; - } + return 0; +} void seq_drain_midi_queues (void) @@ -578,53 +585,53 @@ void sequencer_release (int dev, struct fileinfo *file) - { - int i; - int mode = file->mode & O_ACCMODE; +{ + int i; + int mode = file->mode & O_ACCMODE; - dev = dev >> 4; + dev = dev >> 4; - DEB (printk ("sequencer_release(dev=%d)\n", dev)); + DEB (printk ("sequencer_release(dev=%d)\n", dev)); - if (dev) /* Patch manager device */ - { - dev--; - pmgr_release (dev); - pmgr_present[dev] = 0; - return; - } + if (dev) /* Patch manager device */ + { + dev--; + pmgr_release (dev); + pmgr_present[dev] = 0; + return; + } - /* + /* * Wait until the queue is empty - */ - - while (!PROCESS_ABORTING (seq_sleeper, seq_sleep_flag) && qlen) - { - seq_sync (); - } + */ - if (mode != OPEN_READ) - seq_drain_midi_queues (); /* Ensure the output queues are empty */ - seq_reset (); - if (mode != OPEN_READ) - seq_drain_midi_queues (); /* Flush the all notes off messages */ + while (!PROCESS_ABORTING (seq_sleeper, seq_sleep_flag) && qlen) + { + seq_sync (); + } - for (i = 0; i < num_midis; i++) - if (midi_opened[i]) - midi_devs[i]->close (i); + if (mode != OPEN_READ) + seq_drain_midi_queues (); /* Ensure the output queues are empty */ + seq_reset (); + if (mode != OPEN_READ) + seq_drain_midi_queues (); /* Flush the all notes off messages */ - if (mode == OPEN_WRITE || mode == OPEN_READWRITE) - for (i = 0; i < num_synths; i++) - if (synth_open_mask & (1 << i)) /* Actually opened */ - if (synth_devs[i]) - synth_devs[i]->close (i); + for (i = 0; i < num_midis; i++) + if (midi_opened[i]) + midi_devs[i]->close (i); + if (mode == OPEN_WRITE || mode == OPEN_READWRITE) for (i = 0; i < num_synths; i++) - if (pmgr_present[i]) - pmgr_inform (i, PM_E_CLOSED, 0, 0, 0, 0); + if (synth_open_mask & (1 << i)) /* Actually opened */ + if (synth_devs[i]) + synth_devs[i]->close (i); - sequencer_busy = 0; - } + for (i = 0; i < num_synths; i++) + if (pmgr_present[i]) + pmgr_inform (i, PM_E_CLOSED, 0, 0, 0, 0); + + sequencer_busy = 0; +} static int seq_sync (void) @@ -686,8 +693,8 @@ { for (chn = 0; chn < 16; chn++) { - midi_outc (i, - (unsigned char)(0xb0 + (chn & 0xff))); /* Channel msg */ + midi_outc (i, + (unsigned char) (0xb0 + (chn & 0xff))); /* Channel msg */ midi_outc (i, 0x7b);/* All notes off */ midi_outc (i, 0); /* Dummy parameter */ } @@ -1040,7 +1047,7 @@ else if (octave > BASE_OCTAVE) note_freq <<= (octave - BASE_OCTAVE); - /* note_freq >>= 1; */ + /* note_freq >>= 1; */ return note_freq; } @@ -1049,7 +1056,7 @@ compute_finetune (unsigned long base_freq, int bend, int range) { unsigned long amount; - int negative, semitones, cents; + int negative, semitones, cents, multiplier = 1; if (!bend) return base_freq; @@ -1073,13 +1080,20 @@ if (bend > range) bend = range; - if (bend > 2399) - bend = 2399; + /* + if (bend > 2399) + bend = 2399; + */ + while (bend > 2399) + { + multiplier *= 4; + bend -= 2400; + } semitones = bend / 100; cents = bend % 100; - amount = semitone_tuning[semitones] * cent_tuning[cents] / 10000; + amount = semitone_tuning[semitones] * multiplier * cent_tuning[cents] / 10000; if (negative) return (base_freq * 10000) / amount; /* Bend down */ @@ -1093,8 +1107,9 @@ { sequencer_ok = 1; - PERMANENT_MALLOC(unsigned char*, queue, SEQ_MAX_QUEUE*EV_SZ, mem_start); - PERMANENT_MALLOC(unsigned char*, iqueue, SEQ_MAX_QUEUE*IEV_SZ, mem_start); + PERMANENT_MALLOC (unsigned char *, queue, SEQ_MAX_QUEUE * EV_SZ, mem_start); + PERMANENT_MALLOC (unsigned char *, iqueue, SEQ_MAX_QUEUE * IEV_SZ, mem_start); + return mem_start; } @@ -1114,14 +1129,14 @@ int sequencer_open (int dev, struct fileinfo *file) - { - return RET_ERROR (ENXIO); - } +{ + return RET_ERROR (ENXIO); +} void sequencer_release (int dev, struct fileinfo *file) - { - } +{ +} int sequencer_ioctl (int dev, struct fileinfo *file, unsigned int cmd, unsigned int arg) diff -uNr linux-1.0.9/drivers/sound/sound_calls.h linux/drivers/sound/sound_calls.h --- linux-1.0.9/drivers/sound/sound_calls.h Tue Dec 14 12:20:36 1993 +++ linux/drivers/sound/sound_calls.h Mon Apr 1 17:39:34 2002 @@ -129,12 +129,13 @@ /* From sb_midi.c */ void sb_midi_init(int model); +void sb_midi_interrupt(int dummy); /* From sb_mixer.c */ void sb_setmixer (unsigned int port, unsigned int value); int sb_getmixer (unsigned int port); void sb_mixer_set_stereo(int mode); -void sb_mixer_init(int major_model); +int sb_mixer_init(int major_model); /* From opl3.c */ int opl3_detect (int ioaddr); @@ -181,6 +182,7 @@ void gus_write8(int reg, unsigned int data); void guswave_dma_irq(void); void gus_delay(void); +int gus_default_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg); /* From gus_midi.c */ long gus_midi_init(long mem_start); @@ -201,3 +203,6 @@ int pmgr_access(int dev, struct patmgr_info *rec); int pmgr_inform(int dev, int event, unsigned long parm1, unsigned long parm2, unsigned long parm3, unsigned long parm4); + +/* From ics2101.c */ +long ics2101_mixer_init(long mem_start); diff -uNr linux-1.0.9/drivers/sound/sound_switch.c linux/drivers/sound/sound_switch.c --- linux-1.0.9/drivers/sound/sound_switch.c Fri Jan 21 14:59:51 1994 +++ linux/drivers/sound/sound_switch.c Mon Apr 1 17:39:34 2002 @@ -1,10 +1,10 @@ /* * sound/sound_switch.c - * + * * The system call switch - * + * * Copyright by Hannu Savolainen 1993 - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: 1. Redistributions of source code must retain the above copyright @@ -12,7 +12,7 @@ * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -24,21 +24,26 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * + * */ +#include +#include #include "sound_config.h" #ifdef CONFIGURE_SOUNDCARD struct sbc_device -{ - int usecount; -}; + { + int usecount; + }; -static struct sbc_device sbc_devices[SND_NDEVS] = {{0}}; +static struct sbc_device sbc_devices[SND_NDEVS] = +{ + {0}}; static int in_use = 0; /* Total # of open device files (excluding + * minor 0) */ /* @@ -53,7 +58,7 @@ { int l; - for (l=0;l<256,s[l];l++); /* l=strlen(s); */ + for (l = 0; l < 256, s[l]; l++); /* l=strlen(s); */ if (status_len + l >= 4000) return 0; @@ -69,27 +74,28 @@ { int l, v; - static char hx[] = "0123456789abcdef"; - char buf[11]; + static char hx[] = "0123456789abcdef"; + char buf[11]; - if (!val) return put_status("0"); + if (!val) + return put_status ("0"); l = 0; - buf[10]=0; + buf[10] = 0; while (val) - { - v = val % radix; - val = val / radix; + { + v = val % radix; + val = val / radix; - buf[9-l] = hx[v]; - l++; - } + buf[9 - l] = hx[v]; + l++; + } if (status_len + l >= 4000) return 0; - memcpy (&status_buf[status_len], &buf[10-l], l); + memcpy (&status_buf[status_len], &buf[10 - l], l); status_len += l; return 1; @@ -114,33 +120,43 @@ if (!put_status ("Config options: ")) return; - if (!put_status_int(SELECTED_SOUND_OPTIONS, 16)) - return; + if (!put_status_int (SELECTED_SOUND_OPTIONS, 16)) + return; if (!put_status ("\n\nHW config: \n")) return; for (i = 0; i < (num_sound_drivers - 1); i++) { - if (!supported_drivers[i].enabled) - if (!put_status ("(")) - return; - - if (!put_status ("Type ")) return; - if (!put_status_int(supported_drivers[i].card_type, 10)) return; - if (!put_status (": ")) return; - if (!put_status (supported_drivers[i].name)) return; - if (!put_status (" at 0x")) return; - if (!put_status_int(supported_drivers[i].config.io_base, 16)) return; - if (!put_status (" irq ")) return; - if (!put_status_int(supported_drivers[i].config.irq, 10)) return; - if (!put_status (" drq ")) return; - if (!put_status_int(supported_drivers[i].config.dma, 10)) return; + if (!supported_drivers[i].enabled) + if (!put_status ("(")) + return; - if (!supported_drivers[i].enabled) - if (!put_status (")")) + if (!put_status ("Type ")) + return; + if (!put_status_int (supported_drivers[i].card_type, 10)) + return; + if (!put_status (": ")) + return; + if (!put_status (supported_drivers[i].name)) + return; + if (!put_status (" at 0x")) + return; + if (!put_status_int (supported_drivers[i].config.io_base, 16)) + return; + if (!put_status (" irq ")) + return; + if (!put_status_int (supported_drivers[i].config.irq, 10)) + return; + if (!put_status (" drq ")) + return; + if (!put_status_int (supported_drivers[i].config.dma, 10)) return; + if (!supported_drivers[i].enabled) + if (!put_status (")")) + return; + if (!put_status ("\n")) return; } @@ -150,10 +166,14 @@ for (i = 0; i < num_dspdevs; i++) { - if (!put_status_int(i, 10)) return; - if (!put_status(": "))return; - if (!put_status(dsp_devs[i]->name))return; - if (!put_status("\n"))return; + if (!put_status_int (i, 10)) + return; + if (!put_status (": ")) + return; + if (!put_status (dsp_devs[i]->name)) + return; + if (!put_status ("\n")) + return; } if (!put_status ("\nSynth devices:\n")) @@ -161,10 +181,14 @@ for (i = 0; i < num_synths; i++) { - if (!put_status_int(i, 10)) return; - if (!put_status(": "))return; - if (!put_status(synth_devs[i]->info->name))return; - if (!put_status("\n"))return; + if (!put_status_int (i, 10)) + return; + if (!put_status (": ")) + return; + if (!put_status (synth_devs[i]->info->name)) + return; + if (!put_status ("\n")) + return; } if (!put_status ("\nMidi devices:\n")) @@ -172,10 +196,14 @@ for (i = 0; i < num_midis; i++) { - if (!put_status_int(i, 10)) return; - if (!put_status(": "))return; - if (!put_status(midi_devs[i]->info.name))return; - if (!put_status("\n"))return; + if (!put_status_int (i, 10)) + return; + if (!put_status (": ")) + return; + if (!put_status (midi_devs[i]->info.name)) + return; + if (!put_status ("\n")) + return; } if (num_mixers) @@ -191,7 +219,7 @@ } static int -read_status (snd_rw_buf *buf, int count) +read_status (snd_rw_buf * buf, int count) { /* * Return at most 'count' bytes from the status_buf. @@ -206,14 +234,14 @@ if (l <= 0) return 0; - COPY_TO_USER(buf, 0, &status_buf[status_ptr], l); + COPY_TO_USER (buf, 0, &status_buf[status_ptr], l); status_ptr += l; return l; } int -sound_read_sw (int dev, struct fileinfo *file, snd_rw_buf *buf, int count) +sound_read_sw (int dev, struct fileinfo *file, snd_rw_buf * buf, int count) { DEB (printk ("sound_read_sw(dev=%d, count=%d)\n", dev, count)); @@ -246,7 +274,7 @@ } int -sound_write_sw (int dev, struct fileinfo *file, snd_rw_buf *buf, int count) +sound_write_sw (int dev, struct fileinfo *file, snd_rw_buf * buf, int count) { DEB (printk ("sound_write_sw(dev=%d, count=%d)\n", dev, count)); @@ -275,6 +303,7 @@ sound_open_sw (int dev, struct fileinfo *file) { int retval; + DEB (printk ("sound_open_sw(dev=%d) : usecount=%d\n", dev, sbc_devices[dev].usecount)); if ((dev >= SND_NDEVS) || (dev < 0)) @@ -373,7 +402,7 @@ int sound_ioctl_sw (int dev, struct fileinfo *file, - unsigned int cmd, unsigned long arg) + unsigned int cmd, unsigned long arg) { DEB (printk ("sound_ioctl_sw(dev=%d, cmd=0x%x, arg=0x%x)\n", dev, cmd, arg)); @@ -414,4 +443,5 @@ return RET_ERROR (EPERM); } + #endif diff -uNr linux-1.0.9/drivers/sound/soundcard.c linux/drivers/sound/soundcard.c --- linux-1.0.9/drivers/sound/soundcard.c Fri Jan 21 14:59:51 1994 +++ linux/drivers/sound/soundcard.c Mon Apr 1 17:39:34 2002 @@ -1,11 +1,11 @@ /* * linux/kernel/chr_drv/sound/soundcard.c - * + * * Soundcard driver for Linux - * + * * Copyright by Hannu Savolainen 1993 - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: 1. Redistributions of source code must retain the above copyright @@ -13,7 +13,7 @@ * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -25,7 +25,7 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * + * */ #include "sound_config.h" @@ -37,6 +37,7 @@ extern long seq_time; static int soundcards_installed = 0; /* Number of installed + * soundcards */ static int soundcard_configured = 0; @@ -209,7 +210,7 @@ } int -snd_set_irq_handler (int interrupt_level, void(*hndlr)(int)) +snd_set_irq_handler (int interrupt_level, void (*hndlr) (int)) { int retcode; @@ -237,9 +238,9 @@ } void -snd_release_irq(int vect) +snd_release_irq (int vect) { - free_irq(vect); + free_irq (vect); } void diff -uNr linux-1.0.9/include/linux/soundcard.h linux/include/linux/soundcard.h --- linux-1.0.9/include/linux/soundcard.h Sun Dec 12 21:34:07 1993 +++ linux/include/linux/soundcard.h Mon Apr 1 17:39:34 2002 @@ -34,13 +34,13 @@ * * Regards, * Hannu Savolainen - * hsavolai@cs.helsinki.fi + * hannu@voxware.pp.fi, Hannu.Savolainen@helsinki.fi */ #define SOUND_VERSION 203 #define VOXWARE -#include +#include /* * Supported card ID numbers (Should be somewhere else?) @@ -310,6 +310,14 @@ #define CTRL_EXPRESSION 253 #define CTRL_MAIN_VOLUME 252 #define SEQ_BALANCE 11 +#define SEQ_VOLMODE 12 + +/* + * Volume mode decides how volumes are used + */ + +#define VOL_METHOD_ADAGIO 1 +#define VOL_METHOD_LINEAR 2 /* * Note! SEQ_WAIT, SEQ_MIDIPUTC and SEQ_ECHO are used also as @@ -630,7 +638,8 @@ * } */ -#define SEQ_DEFINEBUF(len) unsigned char _seqbuf[len]; int _seqbuflen = len, _seqbufptr = 0 +#define SEQ_DEFINEBUF(len) unsigned char _seqbuf[len]; int _seqbuflen = len; int _seqbufptr = 0 +#define SEQ_DECLAREBUF() extern unsigned char _seqbuf[]; extern int _seqbuflen;extern int _seqbufptr #define SEQ_PM_DEFINES struct patmgr_info _pm_info #define _SEQ_NEEDBUF(len) if ((_seqbufptr+(len)) > _seqbuflen) seqbuf_dump() #define _SEQ_ADVBUF(len) _seqbufptr += len @@ -644,6 +653,17 @@ _pm_info.parm1 = bank, _pm_info.parm2 = 128, \ ioctl(seqfd, SNDCTL_PMGR_ACCESS, &_pm_info)) +#define SEQ_VOLUME_MODE(dev, mode) {_SEQ_NEEDBUF(8);\ + _seqbuf[_seqbufptr] = SEQ_EXTENDED;\ + _seqbuf[_seqbufptr+1] = SEQ_VOLMODE;\ + _seqbuf[_seqbufptr+2] = (dev);\ + _seqbuf[_seqbufptr+3] = (mode);\ + _seqbuf[_seqbufptr+4] = 0;\ + _seqbuf[_seqbufptr+5] = 0;\ + _seqbuf[_seqbufptr+6] = 0;\ + _seqbuf[_seqbufptr+7] = 0;\ + _SEQ_ADVBUF(8);} + #define SEQ_START_NOTE(dev, voice, note, vol) {_SEQ_NEEDBUF(8);\ _seqbuf[_seqbufptr] = SEQ_EXTENDED;\ _seqbuf[_seqbufptr+1] = SEQ_NOTEON;\ @@ -734,8 +754,8 @@ _seqbuf[_seqbufptr+2] = (device);\ _seqbuf[_seqbufptr+3] = 0;\ _SEQ_ADVBUF(4);} -#define SEQ_WRPATCH(patch, len) {if (_seqbufptr) seqbuf_dump();\ - if (write(seqfd, (char*)(patch), len)==-1) \ +#define SEQ_WRPATCH(patchx, len) {if (_seqbufptr) seqbuf_dump();\ + if (write(seqfd, (char*)(patchx), len)==-1) \ perror("Write patch: /dev/sequencer");} #endif