From e695b6a4896f520b1283cc0a177e78d94b940457 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 23 Nov 2007 15:09:29 -0500 Subject: [PATCH] Import 1.1.10 --- Makefile | 2 +- drivers/net/3c509.c | 11 +- drivers/sound/.blurb | 6 - drivers/sound/CHANGELOG | 27 +- drivers/sound/Makefile | 4 +- drivers/sound/Readme | 116 +-- drivers/sound/Readme.linux | 5 +- drivers/sound/adlib_card.c | 10 +- drivers/sound/audio.c | 73 +- drivers/sound/configure.c | 72 +- drivers/sound/dev_table.c | 180 +++-- drivers/sound/dev_table.h | 6 +- drivers/sound/dmabuf.c | 227 +++--- drivers/sound/gus_card.c | 12 +- drivers/sound/gus_hw.h | 15 + drivers/sound/gus_linearvol.h | 18 + drivers/sound/gus_midi.c | 10 +- drivers/sound/gus_vol.c | 67 +- drivers/sound/gus_wave.c | 1417 ++++++++++++++++++--------------- drivers/sound/ics2101.c | 261 ++++++ drivers/sound/midibuf.c | 12 +- drivers/sound/mpu401.c | 75 +- drivers/sound/opl3.c | 41 +- drivers/sound/os.h | 4 +- drivers/sound/pas.h | 6 +- drivers/sound/pas2_card.c | 66 +- drivers/sound/pas2_midi.c | 10 +- drivers/sound/pas2_mixer.c | 12 +- drivers/sound/pas2_pcm.c | 45 +- drivers/sound/patmgr.c | 10 +- drivers/sound/sb16_dsp.c | 670 ++++++++-------- drivers/sound/sb16_midi.c | 65 +- drivers/sound/sb_card.c | 10 +- drivers/sound/sb_dsp.c | 301 +++---- drivers/sound/sb_midi.c | 45 +- drivers/sound/sb_mixer.c | 349 ++++---- drivers/sound/sb_mixer.h | 40 + drivers/sound/sequencer.c | 268 ++++--- drivers/sound/sound_calls.h | 7 +- drivers/sound/sound_switch.c | 140 ++-- drivers/sound/soundcard.c | 17 +- fs/namei.c | 10 + include/asm/segment.h | 14 - include/linux/sched.h | 4 +- include/linux/soundcard.h | 28 +- include/linux/vm86.h | 10 +- ipc/msg.c | 8 +- ipc/sem.c | 2 +- ipc/shm.c | 14 +- kernel/sched.c | 11 +- kernel/sys.c | 17 + kernel/vm86.c | 34 +- mm/memory.c | 27 +- mm/swap.c | 42 +- net/inet/icmp.c | 1 + net/inet/skbuff.c | 9 +- 56 files changed, 2817 insertions(+), 2146 deletions(-) create mode 100644 drivers/sound/gus_linearvol.h create mode 100644 drivers/sound/ics2101.c diff --git a/Makefile b/Makefile index da6cfeab68e8..e1993d7ef64d 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 1 PATCHLEVEL = 1 -SUBLEVEL = 9 +SUBLEVEL = 10 all: Version zImage diff --git a/drivers/net/3c509.c b/drivers/net/3c509.c index f4e9348b30f1..18bcf799a663 100644 --- a/drivers/net/3c509.c +++ b/drivers/net/3c509.c @@ -91,17 +91,20 @@ int el3_probe(struct device *dev) /* First check for a board on the EISA bus. */ if (EISA_bus) { for (ioaddr = 0x1000; ioaddr < 0x9000; ioaddr += 0x1000) { - if (inw(ioaddr) != 0x6d50) + /* Check the standard EISA ID register for an encoded '3Com'. */ + if (inw(ioaddr + 0xC80) != 0x6d50) continue; + /* Change the register set to the configuration window 0. */ + outw(0x0800, ioaddr + 0xC80 + EL3_CMD); + irq = inw(ioaddr + 8) >> 12; if_port = inw(ioaddr + 6)>>14; for (i = 0; i < 3; i++) phys_addr[i] = htons(read_eeprom(ioaddr, i)); - /* Restore the "Manufacturer ID" to the EEPROM read register. */ - /* The manual says to restore "Product ID" (reg. 3). !???! */ - read_eeprom(ioaddr, 7); + /* Restore the "Product ID" to the EEPROM read register. */ + read_eeprom(ioaddr, 3); /* Was the EISA code an add-on hack? Nahhhhh... */ goto found; diff --git a/drivers/sound/.blurb b/drivers/sound/.blurb index 92aebccbf45d..5a74edfdaecb 100644 --- a/drivers/sound/.blurb +++ b/drivers/sound/.blurb @@ -4,9 +4,3 @@ NOTE! This driver version is not compatible with the version 1.0c. other programs using ioctl calls of the driver, they must be recompiled. Most of them will not work without some source modifications. - - ******** LINUX VERSION 0.99.14 OR LATER IS REQUIRED ******* - - See sound/Readme for more details - - Hannu diff --git a/drivers/sound/CHANGELOG b/drivers/sound/CHANGELOG index 78168dd5d672..f274c834bc9a 100644 --- a/drivers/sound/CHANGELOG +++ b/drivers/sound/CHANGELOG @@ -1,5 +1,28 @@ -Changelog for version 2.4 -------------------------- +Changelog for version 2.5a +-------------------------- + +Since 2.5 +- Minor fix to read from /dev/sequencer + +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. diff --git a/drivers/sound/Makefile b/drivers/sound/Makefile index dcf00d5ed2aa..6200fa91482e 100644 --- a/drivers/sound/Makefile +++ b/drivers/sound/Makefile @@ -5,7 +5,7 @@ # # -VERSION = 2.4 +VERSION = 2.5a TARGET_OS = linux .c.s: @@ -19,7 +19,7 @@ OBJS = soundcard.o audio.o dmabuf.o sb_dsp.o dev_table.o \ 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 diff --git a/drivers/sound/Readme b/drivers/sound/Readme index bd47edef7c36..4438b3ee468c 100644 --- a/drivers/sound/Readme +++ b/drivers/sound/Readme @@ -1,5 +1,13 @@ -Release notes for the Linux Sound Driver 2.4 --------------------------------------------- +Release notes for the Linux Sound Driver 2.5a +--------------------------------------------- +This directory contains just the Linux version. The portable version +(SCO/ISC, FreeBSD/NetBSD and SVR4.2) is available from sunsite.unc.edu: +pub/Linux/kernel/sound. + +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 +25,13 @@ time with the /dev/dsp. Also the WaveBlaster daughter board is supported. 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. @@ -36,19 +40,6 @@ In addition there is rather limited support for MPU-401. Most of the features of the /dev/sequencer device file are available just for GUS owners. -NOTE! There are separate driver for CD-ROMS supported by - some soundcards. The driver for CDU31A (Fusion 16) is - called cdu31a-0.6.diff.z. It will be contained in the - Linux version 0.99.12. The driver for the CD-ROM of SB Pro - is sbpcd0.4.tar.gz (these were the latest versions when I wrote - this). These files should be at least at sunsite.unc.edu. - Also the SCSI interface of the PAS16 should be supported by - Linux 0.99.13k and later. - - There is also a driver for joystick. Look for file joystick-0.5.tar.gz - (sunsite). - - Compatibility with the earlier versions --------------------------------------- @@ -104,58 +95,6 @@ at the same time, the ioctl(SNDCTL_FM_LOAD_INSTR) is obsolete. In addition there is some new fields which must be initialized. Look at the sbiset.c in the snd-util-2.0 package for further info. -This version is almost 100% compatible with the alpha test version (1.99.9). The -difference is in the installation procedure. - -Using this driver with other operating systems than Linux ---------------------------------------------------------- - -This package contains just the Linux version. The version 2.3 -for SCO is available at nic.funet.fi:pub/OS/Linux/ALPHA/sound. -The version 2.3 doesn't work well with xxxxxBSD. Use the version -2.3 for them. - -/dev/sndstat ------------- - -The /dev/sndstat is now available in the SCO and BSD versions also. - -This is a new devicefile for debugging purposes. A better place for -it is in the /proc -directory but I was just too lazy to implement it -properly. The /dev/sndstat (major 14, minor 6) is a file which returns -info about the current configuration (see the example below). If you -send me a error/problem report, please include a printout from this -device to your message (cat /dev/sndstat). - -Note! This device file is currently present only in the Linux version - of this driver. - ------- cut here --- cat /dev/sndstat example -------- -Sound Driver:1.99.7 (Fri Jul 9 17:01:47 GMT 1993 root@lucifer.savolai.fi) -Config options: 0x00000d4b - -HW config: -Type 4: Gravis Ultrasound at 0x210 irq 15 drq 6 -Type 3: ProAudioSpectrum at 0x388 irq 10 drq 3 -Type 2: SoundBlaster at 0x220 irq 7 drq 1 -Type 1: AdLib at 0x388 irq 0 drq 0 - -PCM devices: -00: Gravis UltraSound -01: Pro Audio Spectrum -02: SoundBlaster 2.0 - -Synth devices: -00: Gravis UltraSound -01: Yamaha OPL-3 - -Midi devices: -00: Gravis UltraSound -01: Pro Audio Spectrum - -Mixer(s) installed ------- cut here ---- End of Example ----------- - Known bugs/limitations ---------------------- @@ -164,7 +103,6 @@ Known bugs/limitations recording process too much. A delay longer than 0.1 to 0.3 seconds is too much. - The SB16 driver sometimes swaps the left and right channels together. -- Midi input doesn't work with SB and SB Pro (SB16 works). - It's not possible to open /dev/dsp (or /dev/audio) while the /dev/sequencer is open for output and GUS is the only soundcard installed. It's possible if /dev/dsp is opened before /dev/sequencer @@ -173,9 +111,6 @@ Known bugs/limitations - MPU-401 driver hangs the computer on boot if there is no MPU-401 installed. It uses by default the I/O port 0x330 whic is used by Adaptec 1542 SCSI adapter. -- There are some problems in midi input with MPU-401 and the SB16 midi - (MPU-401 emulation). This makes it impossible to read long sysex dumps - using these devices. - The /dev/sequencer playback to GUS sounds sometimes rather weird. Hitting ^C and playing again should solve this problem. This is propably caused by incompatibilities between GUS and certain VLB motherboards (like mine). @@ -220,21 +155,28 @@ This driver contains code by several contributors. In addition several other 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 --git a/drivers/sound/Readme.linux b/drivers/sound/Readme.linux index d585f59687af..080a23d54c89 100644 --- a/drivers/sound/Readme.linux +++ b/drivers/sound/Readme.linux @@ -1,4 +1,4 @@ -Sound Driver version 2.4 for Linux +Sound Driver version 2.5 for Linux ---------------------------------- NOTE! The sound driver is now a part of the Linux kernel distribution. @@ -174,7 +174,8 @@ 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 +Hannu.Savolainen@Helsinki.fi +(hannu@voxware.pp.fi (april 94 ->)) ----------------- cut here ------------------------------ #!/bin/sh diff --git a/drivers/sound/adlib_card.c b/drivers/sound/adlib_card.c index 3b7df5ebd925..6365069384a5 100644 --- a/drivers/sound/adlib_card.c +++ b/drivers/sound/adlib_card.c @@ -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 --git a/drivers/sound/audio.c b/drivers/sound/audio.c index 03d6b7fcaf47..f27f9d5fa09f 100644 --- a/drivers/sound/audio.c +++ b/drivers/sound/audio.c @@ -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 @@ int 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 @@ audio_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count) { int c, p, l; int err; - int dev_type = dev & 0x0f; + int dev_type = dev & 0x0f; dev = dev >> 4; @@ -134,9 +136,9 @@ audio_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count) c = count; if (audio_mode[dev] == AM_READ) /* Direction changed */ - { + { wr_buff_no[dev] = -1; - } + } audio_mode[dev] = AM_WRITE; @@ -170,19 +172,19 @@ audio_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count) } 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 @@ audio_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count) 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 @@ audio_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count) /* 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 @@ int 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 @@ audio_ioctl (int dev, struct fileinfo *file, 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 @@ audio_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count) 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 --git a/drivers/sound/configure.c b/drivers/sound/configure.c index f6e4cb66c960..dd9a81609c74 100644 --- a/drivers/sound/configure.c +++ b/drivers/sound/configure.c @@ -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 @@ typedef struct char macro[20]; int verify; int alias; - int default_answ; + int default_answ; } hw_entry; @@ -77,11 +77,11 @@ hw_entry; * 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 @@ char *questions[] = }; unsigned long selected_options = 0; -int sb_dma = 0; +int sb_dma = 0; int can_select_option (int nr) @@ -272,11 +272,11 @@ main (int argc, char *argv[]) } 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 @@ main (int argc, char *argv[]) } } - 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 @@ main (int argc, char *argv[]) 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); @@ -331,9 +332,10 @@ main (int argc, char *argv[]) num = 7; } fprintf (stderr, "SoundBlaster IRQ set to %d\n", num); + printf ("#define SBC_BASE 0x220\n"); 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 +361,7 @@ main (int argc, char *argv[]) { 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 +375,14 @@ main (int argc, char *argv[]) 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: "); + 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); + 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 +430,7 @@ main (int argc, char *argv[]) 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 +517,12 @@ main (int argc, char *argv[]) { 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 +545,7 @@ main (int argc, char *argv[]) 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 --git a/drivers/sound/dev_table.c b/drivers/sound/dev_table.c index ca0e5145f06d..7f7cae11d02e 100644 --- a/drivers/sound/dev_table.c +++ b/drivers/sound/dev_table.c @@ -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 @@ sndtable_init (long mem_start) 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 @@ sndtable_probe (int unit, struct address_info *hw_config) 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 @@ sndtable_get_cardcount (void) } #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= - * 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 @@ reorganize_buffers (int dev) * 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 @@ reorganize_buffers (int dev) 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 @@ reorganize_buffers (int dev) } 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 @@ DMAbuf_open (int dev, int mode) } #ifdef USE_RUNTIME_DMAMEM - sound_dma_malloc(dev); + sound_dma_malloc (dev); #endif if (snd_raw_buf[dev][0] == NULL) @@ -222,7 +225,7 @@ DMAbuf_open (int dev, int mode) 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 @@ DMAbuf_open (int dev, int mode) 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 @@ DMAbuf_release (int dev, int mode) } #ifdef USE_RUNTIME_DMAMEM - sound_dma_free(dev); + sound_dma_free (dev); #endif dsp_devs[dev]->reset (dev); @@ -321,45 +319,45 @@ int 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 @@ DMAbuf_ioctl (int dev, unsigned int cmd, unsigned int arg, int local) case SNDCTL_DSP_SUBDIVIDE: { - int fact = IOCTL_IN(arg); + int fact = IOCTL_IN (arg); - if (fact == 0) - { - fact = dev_subdivision[dev]; - if (fact == 0) fact = 1; - return IOCTL_OUT(arg, fact); - } + 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 (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 @@ DMAbuf_ioctl (int dev, unsigned int cmd, unsigned int arg, int local) return dsp_devs[dev]->ioctl (dev, cmd, arg, local); } + /* NOTREACHED */ return RET_ERROR (EIO); } @@ -491,16 +492,15 @@ DMAbuf_getwrbuffer (int dev, char **buf, int *size) 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 @@ DMAbuf_start_output (int dev, int buff_no, int l) 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 @@ DMAbuf_start_dma (int dev, unsigned long physaddr, int count, int dma_mode) 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 @@ DMAbuf_start_dma (int dev, unsigned long physaddr, int count, int dma_mode) 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 @@ DMAbuf_start_dma (int dev, unsigned long physaddr, int count, int dma_mode) 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 @@ DMAbuf_outputintr (int dev, int underrun_flag) 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 @@ DMAbuf_inputintr (int dev) } 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 @@ DMAbuf_reset_dma (int chan) /* * 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 --git a/drivers/sound/gus_card.c b/drivers/sound/gus_card.c index d031a456fdd1..c7cfc0a7ab6c 100644 --- a/drivers/sound/gus_card.c +++ b/drivers/sound/gus_card.c @@ -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 @@ gusintr (int unit) unsigned char src; #ifdef linux - sti(); + sti (); #endif while (1) diff --git a/drivers/sound/gus_hw.h b/drivers/sound/gus_hw.h index 48233e7e1e32..f97a0b8670e3 100644 --- a/drivers/sound/gus_hw.h +++ b/drivers/sound/gus_hw.h @@ -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 --git a/drivers/sound/gus_linearvol.h b/drivers/sound/gus_linearvol.h new file mode 100644 index 000000000000..7ad0c30d4fd9 --- /dev/null +++ b/drivers/sound/gus_linearvol.h @@ -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 --git a/drivers/sound/gus_midi.c b/drivers/sound/gus_midi.c index 5e06f7f239ee..935c5c90b324 100644 --- a/drivers/sound/gus_midi.c +++ b/drivers/sound/gus_midi.c @@ -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 --git a/drivers/sound/gus_vol.c b/drivers/sound/gus_vol.c index ea3ece358216..055a1170e9fb 100644 --- a/drivers/sound/gus_vol.c +++ b/drivers/sound/gus_vol.c @@ -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 @@ extern int gus_wave_volume; * 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 @@ gus_adagio_vol (int vel, int mainv, int xpn, int voicev) 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 @@ gus_adagio_vol (int vel, int mainv, int xpn, int voicev) * 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 @@ gus_adagio_vol (int vel, int mainv, int xpn, int voicev) 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 @@ gus_adagio_vol (int vel, int mainv, int xpn, int voicev) 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 @@ gus_adagio_vol (int vel, int mainv, int xpn, int voicev) 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 --git a/drivers/sound/gus_wave.c b/drivers/sound/gus_wave.c index aea174d27f5a..924cd9375a6e 100644 --- a/drivers/sound/gus_wave.c +++ b/drivers/sound/gus_wave.c @@ -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 @@ struct voice_info 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 gus_busy = 0; 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 @@ static int gus_sampling_bits; 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 @@ struct voice_info voices[32]; 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 struct synth_info gus_info = 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 @@ reset_sample_memory (void) 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 @@ gus_write_addr (int reg, unsigned long address, int is16bit) if (is16bit) { - /* + /* * Special processing required for 16 bit patches */ @@ -398,6 +397,10 @@ gus_write_addr (int reg, unsigned long address, int is16bit) 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 @@ gus_voice_mode (unsigned int m) { 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 @@ gus_voice_freq (unsigned long freq) 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 @@ gus_ramp_mode (unsigned int m) { 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 @@ gus_voice_init (int voice) 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 @@ step_envelope (int voice) { 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 @@ step_envelope (int voice) } 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 @@ step_envelope (int voice) 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 @@ step_envelope (int voice) 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 @@ init_envelope (int voice) } 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 @@ static void 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_voice_fade (int voice) 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 @@ gus_reset (void) 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 @@ static void 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 @@ gus_initialize (void) 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 @@ gus_initialize (void) 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 @@ gus_initialize (void) 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 @@ guswave_set_instr (int dev, int voice, int instr_no) 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 @@ guswave_kill_note (int dev, int voice, int velocity) 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 @@ guswave_aftertouch (int dev, int voice, int pressure) 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 @@ guswave_aftertouch (int dev, int voice, int pressure) 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 @@ guswave_aftertouch (int dev, int voice, int pressure) } 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); } @@ -1145,25 +1167,37 @@ guswave_panning (int dev, int voice, int value) voices[voice].panning = value; } +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 @@ compute_and_set_volume (int voice, int volume, int ramp_time) 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 @@ compute_and_set_volume (int voice, int volume, int ramp_time) 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 @@ compute_and_set_volume (int voice, int volume, int ramp_time) 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 @@ compute_and_set_volume (int voice, int volume, int ramp_time) 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 @@ dynamic_volume_change (int voice) 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 @@ dynamic_volume_change (int voice) 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 @@ dynamic_volume_change (int voice) 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 @@ guswave_controller (int dev, int voice, int ctrl_num, int value) 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 @@ guswave_controller (int dev, int voice, int ctrl_num, int value) 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 @@ guswave_controller (int dev, int voice, int ctrl_num, int value) #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 @@ guswave_start_note2 (int dev, int voice, int note_num, int volume) 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 @@ guswave_start_note2 (int dev, int voice, int note_num, int volume) 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 @@ guswave_start_note2 (int dev, int voice, int note_num, int volume) 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 @@ guswave_start_note2 (int dev, int voice, int note_num, int volume) 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 @@ guswave_start_note2 (int dev, int voice, int note_num, int volume) 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 @@ guswave_start_note2 (int dev, int voice, int note_num, int volume) 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 @@ guswave_start_note2 (int dev, int voice, int note_num, int volume) 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 @@ guswave_start_note2 (int dev, int voice, int note_num, int volume) 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 @@ guswave_start_note2 (int dev, int voice, int note_num, int volume) 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 @@ guswave_start_note2 (int dev, int voice, int note_num, int volume) 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 @@ guswave_start_note2 (int dev, int voice, int note_num, int volume) 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 @@ guswave_start_note (int dev, int voice, int note_num, int volume) 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! */ + 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; + 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; - } + 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 @@ guswave_start_note (int dev, int voice, int note_num, int volume) 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 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr, 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 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr, return RET_ERROR (ENOSPC); } - /* + /* * Copy the header from user space but ignore the first bytes which have * been transferred already. */ @@ -1754,15 +1800,15 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr, } } - 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 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr, 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 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr, 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 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr, 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 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr, 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 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr, } #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 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr, 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 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr, 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 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr, 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 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr, 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 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr, src_offs += blk_size; target += blk_size; - gus_write8 (0x41, 0); /* - * Stop DMA + gus_write8 (0x41, 0); /* + * Stop DMA */ } @@ -1991,8 +2037,8 @@ guswave_hw_control (int dev, unsigned char *event) 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 @@ guswave_hw_control (int dev, unsigned char *event) 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 @@ guswave_hw_control (int dev, unsigned char *event) 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 @@ guswave_hw_control (int dev, unsigned char *event) 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 @@ guswave_hw_control (int dev, unsigned char *event) 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 @@ guswave_hw_control (int dev, unsigned char *event) 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 @@ guswave_hw_control (int dev, unsigned char *event) 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 @@ guswave_hw_control (int dev, unsigned char *event) 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 @@ gus_sampling_ioctl (int dev, unsigned int cmd, unsigned int arg, int local) 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 @@ gus_sampling_open (int dev, int mode) 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 @@ gus_sampling_close (int dev) active_device = 0; if (recording_active) - set_input_volumes(); + set_input_volumes (); recording_active = 0; } @@ -2313,14 +2356,14 @@ play_next_pcm_block (void) 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 @@ play_next_pcm_block (void) if (gus_sampling_bits != 8) { is16bits = 1; - mode[chn] |= 0x04; /* - * 16 bit data + mode[chn] |= 0x04; /* + * 16 bit data */ } else @@ -2338,22 +2381,22 @@ play_next_pcm_block (void) 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 @@ play_next_pcm_block (void) 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 @@ static void 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 @@ gus_transfer_output_block (int dev, unsigned long buf, 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 @@ gus_transfer_output_block (int dev, unsigned long buf, 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 @@ gus_transfer_output_block (int dev, unsigned long buf, 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 @@ gus_sampling_start_input (int dev, unsigned long buf, int count, 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 @@ gus_sampling_prepare_for_input (int dev, int bsize, int bcount) 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 @@ gus_copy_from_user (int dev, char *localbuf, int localoffs, 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 @@ guswave_bender (int dev, int voice, int value) gus_voice_freq (freq); RESTORE_INTR (flags); } + #endif static int @@ -2776,8 +2821,8 @@ guswave_patchmgr (int dev, struct patmgr_info *rec) 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 @@ guswave_patchmgr (int dev, struct patmgr_info *rec) 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 @@ guswave_patchmgr (int dev, struct patmgr_info *rec) 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 @@ guswave_patchmgr (int dev, struct patmgr_info *rec) 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 @@ guswave_patchmgr (int dev, struct patmgr_info *rec) 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 @@ guswave_patchmgr (int dev, struct patmgr_info *rec) 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 @@ guswave_patchmgr (int dev, struct patmgr_info *rec) 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 @@ guswave_patchmgr (int dev, struct patmgr_info *rec) 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 @@ guswave_patchmgr (int dev, struct patmgr_info *rec) 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 @@ static struct synth_operations guswave_operations = guswave_aftertouch, guswave_controller, guswave_panning, + guswave_volume_method, guswave_patchmgr, #ifdef FUTURE_VERSION guswave_bender @@ -2975,39 +3021,43 @@ static struct synth_operations guswave_operations = }; 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 @@ gus_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg) 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 @@ gus_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg) 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 @@ gus_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg) 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 @@ gus_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg) 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 @@ gus_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg) return RET_ERROR (EINVAL); } else - switch (cmd & 0xff) /* - * Return parameters + switch (cmd & 0xff) /* + * Return parameters */ { @@ -3100,7 +3156,7 @@ gus_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg) 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 @@ gus_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg) 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 @@ gus_wave_init (long mem_start, int irq, int dma) 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 @@ do_loop_irq (int voice) 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 @@ do_loop_irq (int voice) 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 @@ do_loop_irq (int voice) 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 @@ do_loop_irq (int voice) 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 @@ do_volume_irq (int voice) 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 @@ do_volume_irq (int voice) 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 @@ gus_voice_irq (void) 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 @@ guswave_dma_irq (void) { 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 @@ guswave_dma_irq (void) 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 --git a/drivers/sound/ics2101.c b/drivers/sound/ics2101.c new file mode 100644 index 000000000000..df65b5d067ab --- /dev/null +++ b/drivers/sound/ics2101.c @@ -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 +#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 --git a/drivers/sound/midibuf.c b/drivers/sound/midibuf.c index 54b7266ad6ca..7dadb3f8fa74 100644 --- a/drivers/sound/midibuf.c +++ b/drivers/sound/midibuf.c @@ -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 --git a/drivers/sound/mpu401.c b/drivers/sound/mpu401.c index 8be8fee579a1..68b461bb3c44 100644 --- a/drivers/sound/mpu401.c +++ b/drivers/sound/mpu401.c @@ -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 my_dev; 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 @@ mpu401_open (int dev, int mode, 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 @@ mpu401_out (int dev, unsigned char midi_byte) DISABLE_INTR (flags); if (input_avail ()) - mpu401_input_loop (); + mpuintr (0); RESTORE_INTR (flags); @@ -291,7 +248,7 @@ reset_mpu401 (void) mpu401_opened = 0; if (ok) - mpu401_input_loop (); /* Flush input before enabling interrupts */ + mpuintr (0); /* Flush input before enabling interrupts */ RESTORE_INTR (flags); diff --git a/drivers/sound/opl3.c b/drivers/sound/opl3.c index 09e27654fd57..65e783432c4c 100644 --- a/drivers/sound/opl3.c +++ b/drivers/sound/opl3.c @@ -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 already_initialized = 0; 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 @@ static unsigned char connection_mask = 0x00; 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 @@ opl3_detect (int ioaddr) * 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 @@ opl3_detect (int ioaddr) 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 @@ set_voice_volume (int voice, int volume) 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 @@ opl3_command (int io_addr, unsigned int addr, unsigned int val) * 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 @@ opl3_command (int io_addr, unsigned int addr, unsigned int val) 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 @@ opl3_panning (int dev, int voice, int pressure) { } +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_controller (int dev, int voice, int ctrl_num, int value) 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 @@ static struct synth_operations opl3_operations = opl3_aftertouch, opl3_controller, opl3_panning, + opl3_volume_method, opl3_patchmgr }; @@ -894,8 +903,8 @@ opl3_init (long mem_start) { 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 --git a/drivers/sound/os.h b/drivers/sound/os.h index 76a3b057ecf2..fc1b0f5cae7d 100644 --- a/drivers/sound/os.h +++ b/drivers/sound/os.h @@ -37,7 +37,6 @@ #include #include #include -#include #include #include #include @@ -46,6 +45,7 @@ #include #include #include +#include typedef char snd_rw_buf; @@ -141,7 +141,7 @@ struct snd_wait { #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 --git a/drivers/sound/pas.h b/drivers/sound/pas.h index 797c8fdbcd24..9902e03e4bfe 100644 --- a/drivers/sound/pas.h +++ b/drivers/sound/pas.h @@ -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 --git a/drivers/sound/pas2_card.c b/drivers/sound/pas2_card.c index 98a2f92ea9b6..a3030a44af75 100644 --- a/drivers/sound/pas2_card.c +++ b/drivers/sound/pas2_card.c @@ -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 @@ config_pas_hw (struct address_info *hw_config) 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 @@ config_pas_hw (struct address_info *hw_config) #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; + 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); + /* 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); + /* "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_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); + 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]; + irq_dma = E_C_SB_DMA_translate[sb_config->dma] | + E_C_SB_IRQ_translate[sb_config->irq]; - pas_write(irq_dma, EMULATION_CONFIGURATION); - } - } + pas_write (irq_dma, EMULATION_CONFIGURATION); + } + } #endif if (!ok) @@ -327,11 +327,11 @@ attach_pas_card (long mem_start, struct address_info *hw_config) 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 --git a/drivers/sound/pas2_midi.c b/drivers/sound/pas2_midi.c index 13cf97dca501..4a07b0b59bf8 100644 --- a/drivers/sound/pas2_midi.c +++ b/drivers/sound/pas2_midi.c @@ -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 --git a/drivers/sound/pas2_mixer.c b/drivers/sound/pas2_mixer.c index 63be9e5b6f73..fd3e1065a244 100644 --- a/drivers/sound/pas2_mixer.c +++ b/drivers/sound/pas2_mixer.c @@ -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 @@ mixer_output (int right_vol, int left_vol, int div, int bits, } 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 --git a/drivers/sound/pas2_pcm.c b/drivers/sound/pas2_pcm.c index b396f61532d8..06742d5589fa 100644 --- a/drivers/sound/pas2_pcm.c +++ b/drivers/sound/pas2_pcm.c @@ -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 @@ pas_pcm_ioctl (int dev, unsigned int cmd, unsigned int arg, int local) 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 @@ pas_pcm_close (int dev) } 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_pcm_output_block (int dev, unsigned long buf, int count, 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 @@ pas_pcm_output_block (int dev, unsigned long buf, int count, } 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 @@ pas_pcm_start_input (int dev, unsigned long buf, int count, 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 @@ pas_pcm_prepare_for_output (int dev, int bsize, int bcount) 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 @@ pas_pcm_init (long mem_start, struct address_info *hw_config) 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 --git a/drivers/sound/patmgr.c b/drivers/sound/patmgr.c index f5697ae265a5..042d42d4067c 100644 --- a/drivers/sound/patmgr.c +++ b/drivers/sound/patmgr.c @@ -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 --git a/drivers/sound/sb16_dsp.c b/drivers/sound/sb16_dsp.c index 02040c7bda85..f9297bca4d7c 100644 --- a/drivers/sound/sb16_dsp.c +++ b/drivers/sound/sb16_dsp.c @@ -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 @@ static struct audio_operations sb16_dsp_operations = 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) +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); - } - + 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 @@ static void 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 @@ DEB(printk("sb16_dsp_close()\n")); } 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 @@ sb16_dsp_output_block (int dev, unsigned long buf, int count,int intrflag, int d 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 @@ sb16_dsp_start_input (int dev, unsigned long buf, int count,int intrflag, int dm 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 @@ printk("start_input: %x %d %d\n",buf,count,intrflag); 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 @@ sb16_dsp_prepare_for_input (int dev, int bsize, int bcount) 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 @@ dsp_cleanup (void) static void sb16_dsp_reset (int dev) { - unsigned long flags; + unsigned long flags; DISABLE_INTR (flags); @@ -460,61 +487,52 @@ static void 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 @@ sb16_dsp_detect (struct address_info *hw_config) 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 @@ sb16_dsp_detect (struct address_info *hw_config) void sb16_dsp_interrupt (int unused) { - int data; - 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"); - } + int data; + + 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 --git a/drivers/sound/sb16_midi.c b/drivers/sound/sb16_midi.c index 2fc475ae9223..0ce274047c79 100644 --- a/drivers/sound/sb16_midi.c +++ b/drivers/sound/sb16_midi.c @@ -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 my_dev; 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 @@ sb16midiintr (int unit) 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 @@ sb16midi_open (int dev, int mode, midi_input_intr = input; sb16midi_opened = mode; - poll_sb16midi (0); /* Enable input polling */ return 0; } @@ -299,6 +266,8 @@ probe_sb16midi (struct address_info *hw_config) 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 --git a/drivers/sound/sb_card.c b/drivers/sound/sb_card.c index ef90b4bef312..f7588e1ca172 100644 --- a/drivers/sound/sb_card.c +++ b/drivers/sound/sb_card.c @@ -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 --git a/drivers/sound/sb_dsp.c b/drivers/sound/sb_dsp.c index d6297e5b663f..ce62cf9ebbe0 100644 --- a/drivers/sound/sb_dsp.c +++ b/drivers/sound/sb_dsp.c @@ -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 @@ static int sbc_irq = 0; * 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 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 @@ sb_dsp_command (unsigned char val) void sbintr (int unit) { - int status, data; + int status; #ifndef EXCLUDE_SBPRO if (sb16) @@ -117,10 +124,12 @@ sbintr (int unit) 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 @@ sbintr (int unit) break; case IMODE_MIDI: - printk ("+"); - data = INB (DSP_READ); - printk ("%x", data); - + sb_midi_interrupt (unit); break; default: @@ -163,29 +169,32 @@ sbintr (int unit) } } -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 @@ dsp_speed (int speed) { 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 (sbc_major < 2 || + (sbc_major == 2 && sbc_minor == 0)) + max_speed = 22050; - if (sb_dsp_model == 1 && speed > 22050) - speed = 22050; - /* SB Classic doesn't support higher speed */ + /* + * 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 @@ dsp_speed (int speed) 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 @@ dsp_speed (int speed) 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 @@ dsp_set_stereo (int mode) #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 @@ dsp_set_stereo (int mode) } 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 @@ sb_dsp_output_block (int dev, unsigned long buf, int count, 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 @@ sb_dsp_output_block (int dev, unsigned long buf, int count, 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 @@ sb_dsp_start_input (int dev, unsigned long buf, int count, int intrflag, 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 @@ sb_dsp_start_input (int dev, unsigned long buf, int count, int intrflag, 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 @@ sb_dsp_prepare_for_input (int dev, int bsize, int bcount) 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 @@ sb_dsp_prepare_for_output (int dev, int bsize, int bcount) 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 @@ static int verify_irq (void) { #if 0 - DEFINE_WAIT_QUEUE(testq, testf); + DEFINE_WAIT_QUEUE (testq, testf); irq_ok = 0; @@ -470,11 +493,11 @@ verify_irq (void) 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 @@ sb_dsp_open (int dev, int mode) 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_dsp_open (int dev, int mode) sb_irq_mode = IMODE_NONE; sb_dsp_busy = 1; + open_mode = mode; return 0; } @@ -541,6 +564,7 @@ sb_dsp_close (int dev) dsp_speaker (OFF); sb_dsp_busy = 0; sb_dsp_highspeed = 0; + open_mode = 0; } static int @@ -562,7 +586,7 @@ sb_dsp_ioctl (int dev, unsigned int cmd, unsigned int arg, int local) 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 @@ sb_dsp_reset (int dev) DISABLE_INTR (flags); sb_reset_dsp (); + dsp_speed (dsp_current_speed); dsp_cleanup (); RESTORE_INTR (flags); @@ -631,6 +656,7 @@ sb_dsp_detect (struct address_info *hw_config) static struct audio_operations sb_dsp_operations = { "SoundBlaster", + NOTHING_SPECIAL, sb_dsp_open, sb_dsp_close, sb_dsp_output_block, @@ -650,80 +676,85 @@ long 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 (major == 4) - sb16 = 1; + if (sbc_major == 2 || sbc_major == 3) /* SB 2.0 or SB Pro */ + sb_duplex_midi = 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 --git a/drivers/sound/sb_midi.c b/drivers/sound/sb_midi.c index b5bdd211419f..fed19aba3a08 100644 --- a/drivers/sound/sb_midi.c +++ b/drivers/sound/sb_midi.c @@ -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_midi_busy; /* 1 if the process has output to MIDI */ 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 @@ sb_midi_open (int dev, int mode, 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_midi_open (int dev, int mode, 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_midi_open (int dev, int mode, 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_midi_close (int dev) } sb_intr_active = 0; sb_midi_busy = 0; + input_opened = 0; } static int @@ -174,6 +186,21 @@ sb_midi_ioctl (int dev, unsigned cmd, unsigned arg) 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 @@ static struct midi_operations sb_midi_operations = }; void -sb_midi_init(int model) +sb_midi_init (int model) { midi_devs[num_midis++] = &sb_midi_operations; } diff --git a/drivers/sound/sb_mixer.c b/drivers/sound/sb_mixer.c index afd49c54897c..39b97caf8cd7 100644 --- a/drivers/sound/sb_mixer.c +++ b/drivers/sound/sb_mixer.c @@ -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 @@ detect_mixer (void) 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 @@ set_recmask(int mask) } - if (devmask ^ recmask)/* Input source changed */ + if (devmask ^ recmask) /* Input source changed */ { switch (devmask) { @@ -233,23 +276,24 @@ set_recmask(int mask) break; - case 4: - if (!devmask) devmask = SOUND_MASK_MIC; + 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))); - } + 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 */ - { + switch (cmd & 0xff) /* Return parameters */ + { - case SOUND_MIXER_RECSRC: - return IOCTL_OUT (arg, recmask); - 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_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_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_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 struct mixer_operations sb_mixer_operations = }; 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 --git a/drivers/sound/sb_mixer.h b/drivers/sound/sb_mixer.h index 304af6423baa..4caf7730226f 100644 --- a/drivers/sound/sb_mixer.h +++ b/drivers/sound/sb_mixer.h @@ -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_ALTPCM, 0x00, 0, 0, 0x00, 0, 0), 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 --git a/drivers/sound/sequencer.c b/drivers/sound/sequencer.c index 9024922a55c5..fc02464a9f8f 100644 --- a/drivers/sound/sequencer.c +++ b/drivers/sound/sequencer.c @@ -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_opened[MAX_MIDI_DEV] = 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" @@ -77,6 +77,7 @@ int sequencer_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count) { int c = count, p = 0; + unsigned long flags; dev = dev >> 4; @@ -85,12 +86,22 @@ sequencer_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count) while (c > 3) { + DISABLE_INTR (flags); if (!iqlen) { + if (c != count) /* Some data has been received */ + { + RESTORE_INTR (flags); + return count - c; /* Return what we have */ + } + DO_SLEEP (midi_sleeper, midi_sleep_flag, 0); if (!iqlen) - return count - c; + { + RESTORE_INTR (flags); + return count - c; + } } COPY_TO_USER (buf, p, &iqueue[iqhead * IEV_SZ], IEV_SZ); @@ -99,6 +110,7 @@ sequencer_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count) iqhead = (iqhead + 1) % SEQ_MAX_QUEUE; iqlen--; + RESTORE_INTR (flags); } return count - c; @@ -118,11 +130,11 @@ copy_to_input (unsigned char *event) if (iqlen >= (SEQ_MAX_QUEUE - 1)) return; /* Overflow */ + DISABLE_INTR (flags); memcpy (&iqueue[iqtail * IEV_SZ], event, IEV_SZ); iqlen++; iqtail = (iqtail + 1) % SEQ_MAX_QUEUE; - DISABLE_INTR (flags); if (SOMEONE_WAITING (midi_sleeper, midi_sleep_flag)) { WAKE_UP (midi_sleeper, midi_sleep_flag); @@ -327,6 +339,10 @@ extended_event (unsigned char *q) 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 +362,7 @@ seq_startplay (void) 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 +479,87 @@ seq_startplay (void) 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 +594,53 @@ seq_drain_midi_queues (void) 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); + + for (i = 0; i < num_synths; i++) + if (pmgr_present[i]) + pmgr_inform (i, PM_E_CLOSED, 0, 0, 0, 0); - sequencer_busy = 0; - } + sequencer_busy = 0; +} static int seq_sync (void) @@ -686,8 +702,8 @@ seq_reset (void) { 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 +1056,7 @@ note_to_freq (int note_num) else if (octave > BASE_OCTAVE) note_freq <<= (octave - BASE_OCTAVE); - /* note_freq >>= 1; */ + /* note_freq >>= 1; */ return note_freq; } @@ -1049,7 +1065,7 @@ unsigned long 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 +1089,20 @@ compute_finetune (unsigned long base_freq, int bend, int range) 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 +1116,9 @@ sequencer_init (long mem_start) { 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 +1138,14 @@ sequencer_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count) 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 --git a/drivers/sound/sound_calls.h b/drivers/sound/sound_calls.h index 97fb7699666e..abc82001b776 100644 --- a/drivers/sound/sound_calls.h +++ b/drivers/sound/sound_calls.h @@ -129,12 +129,13 @@ int probe_sb16midi(struct address_info *hw_config); /* 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 @@ unsigned char gus_read8 (int reg); 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_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count); 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 --git a/drivers/sound/sound_switch.c b/drivers/sound/sound_switch.c index 0cc81508d1aa..68c757586083 100644 --- a/drivers/sound/sound_switch.c +++ b/drivers/sound/sound_switch.c @@ -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,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" @@ -32,13 +32,16 @@ #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 +56,7 @@ put_status (char *s) { 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 +72,28 @@ put_status_int (unsigned int val, int radix) { 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 +118,43 @@ init_status (void) 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 (!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 (")")) + 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 +164,14 @@ init_status (void) 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 +179,14 @@ init_status (void) 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 +194,14 @@ init_status (void) 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 +217,7 @@ init_status (void) } 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 +232,14 @@ read_status (snd_rw_buf *buf, int count) 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 +272,7 @@ sound_read_sw (int dev, struct fileinfo *file, snd_rw_buf *buf, int count) } 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 +301,7 @@ int 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 +400,7 @@ sound_release_sw (int dev, struct fileinfo *file) 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 +441,5 @@ sound_ioctl_sw (int dev, struct fileinfo *file, return RET_ERROR (EPERM); } + #endif diff --git a/drivers/sound/soundcard.c b/drivers/sound/soundcard.c index ddf71801638d..9708994c7d92 100644 --- a/drivers/sound/soundcard.c +++ b/drivers/sound/soundcard.c @@ -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 @@ tenmicrosec (void) } 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 @@ snd_set_irq_handler (int interrupt_level, void(*hndlr)(int)) } void -snd_release_irq(int vect) +snd_release_irq (int vect) { - free_irq(vect); + free_irq (vect); } void diff --git a/fs/namei.c b/fs/namei.c index 03ff84baca0a..b229c042bf06 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -407,9 +407,11 @@ int do_mknod(const char * filename, int mode, dev_t dev) iput(dir); return -EPERM; } + dir->i_count++; down(&dir->i_sem); error = dir->i_op->mknod(dir,basename,namelen,mode,dev); up(&dir->i_sem); + iput(dir); return error; } @@ -462,9 +464,11 @@ static int do_mkdir(const char * pathname, int mode) iput(dir); return -EPERM; } + dir->i_count++; down(&dir->i_sem); error = dir->i_op->mkdir(dir,basename,namelen,mode); up(&dir->i_sem); + iput(dir); return error; } @@ -588,9 +592,11 @@ static int do_symlink(const char * oldname, const char * newname) iput(dir); return -EPERM; } + dir->i_count++; down(&dir->i_sem); error = dir->i_op->symlink(dir,basename,namelen,oldname); up(&dir->i_sem); + iput(dir); return error; } @@ -647,9 +653,11 @@ static int do_link(struct inode * oldinode, const char * newname) iput(oldinode); return -EPERM; } + dir->i_count++; down(&dir->i_sem); error = dir->i_op->link(oldinode, dir, basename, namelen); up(&dir->i_sem); + iput(dir); return error; } @@ -723,10 +731,12 @@ static int do_rename(const char * oldname, const char * newname) iput(new_dir); return -EPERM; } + new_dir->i_count++; down(&new_dir->i_sem); error = old_dir->i_op->rename(old_dir, old_base, old_len, new_dir, new_base, new_len); up(&new_dir->i_sem); + iput(new_dir); return error; } diff --git a/include/asm/segment.h b/include/asm/segment.h index 2406d874822f..ec85292da441 100644 --- a/include/asm/segment.h +++ b/include/asm/segment.h @@ -52,20 +52,6 @@ __asm__ ("movl %0,%%fs:%1": /* no outputs */ :"ir" (val),"m" (*addr)); #define put_fs_long(x,addr) put_user_long((x),(int *)(addr)) -static inline void and_user_long(unsigned long val,int * addr) -{ -__asm__ ("andl %0,%%fs:%1": /* no outputs */ :"ir" (val),"m" (*addr)); -} - -#define and_fs_long(x,addr) and_user_long((x),(int *)(addr)) - -static inline void or_user_long(unsigned long val,int * addr) -{ -__asm__ ("orl %0,%%fs:%1": /* no outputs */ :"ir" (val),"m" (*addr)); -} - -#define or_fs_long(x,addr) or_user_long((x),(int *)(addr)) - static inline void __generic_memcpy_tofs(void * to, const void * from, unsigned long n) { __asm__("cld\n\t" diff --git a/include/linux/sched.h b/include/linux/sched.h index f5719a9f3420..99a12abdb1d8 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -365,9 +365,7 @@ __asm__("str %%ax\n\t" \ * tha math co-processor latest. */ #define switch_to(tsk) \ -__asm__("cmpl %%ecx,_current\n\t" \ - "je 1f\n\t" \ - "cli\n\t" \ +__asm__("cli\n\t" \ "xchgl %%ecx,_current\n\t" \ "ljmp %0\n\t" \ "sti\n\t" \ diff --git a/include/linux/soundcard.h b/include/linux/soundcard.h index 0603dd3b63a1..60d6d99f8f9f 100644 --- a/include/linux/soundcard.h +++ b/include/linux/soundcard.h @@ -34,7 +34,7 @@ * * Regards, * Hannu Savolainen - * hsavolai@cs.helsinki.fi + * hannu@voxware.pp.fi, Hannu.Savolainen@helsinki.fi */ #define SOUND_VERSION 203 @@ -310,6 +310,14 @@ struct patmgr_info { /* Note! size must be < 4k since kmalloc() is used */ #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 @@ void seqbuf_dump(void); /* This function must be provided by programs */ * } */ -#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 @@ void seqbuf_dump(void); /* This function must be provided by programs */ _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 @@ void seqbuf_dump(void); /* This function must be provided by programs */ _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 diff --git a/include/linux/vm86.h b/include/linux/vm86.h index 573dcc7c3cfd..10227edaf0e7 100644 --- a/include/linux/vm86.h +++ b/include/linux/vm86.h @@ -40,7 +40,7 @@ #define VM86_SIGNAL 0 /* return due to signal */ #define VM86_UNKNOWN 1 /* unhandled GP fault - IO-instruction or similar */ #define VM86_INTx 2 /* int3/int x instruction (ARG = x) */ -#define VM86_STI 3 /* sti/popfl instruction enabled virtual interrupts */ +#define VM86_STI 3 /* sti/popf/iret instruction enabled virtual interrupts */ /* * This is the stack-layout when we have done a "SAVE_ALL" from vm86 @@ -103,14 +103,6 @@ struct vm86_struct { void handle_vm86_fault(struct vm86_regs *, long); -extern inline int is_revectored(int nr, struct revectored_struct * bitmap) -{ - __asm__ __volatile__("btl %2,%%fs:%1\n\tsbbl %0,%0" - :"=r" (nr) - :"m" (*bitmap),"r" (nr)); - return nr; -} - #endif #endif diff --git a/ipc/msg.c b/ipc/msg.c index fa900515ea79..aedbd4fd8f8e 100644 --- a/ipc/msg.c +++ b/ipc/msg.c @@ -84,7 +84,7 @@ int sys_msgsnd (int msqid, struct msgbuf *msgp, int msgsz, int msgflg) if (msgque[id] == IPC_UNUSED || msgque[id] == IPC_NOID || ipcp->seq != msqid / MSGMNI) { - kfree_s (msgh, sizeof(*msgh) + msgsz); + kfree(msgh); return -EIDRM; } @@ -194,7 +194,7 @@ int sys_msgrcv (int msqid, struct msgbuf *msgp, int msgsz, long msgtyp, wake_up (&msq->wwait); put_fs_long (nmsg->msg_type, &msgp->mtype); memcpy_tofs (msgp->mtext, nmsg->msg_spot, msgsz); - kfree_s (nmsg, sizeof(*nmsg) + msgsz); + kfree(nmsg); return msgsz; } else { /* did not find a message */ if (msgflg & IPC_NOWAIT) @@ -311,9 +311,9 @@ static void freeque (int id) for (msgp = msq->msg_first; msgp; msgp = msgh ) { msgh = msgp->msg_next; msghdrs--; - kfree_s (msgp, sizeof(*msgp) + msgp->msg_ts); + kfree(msgp); } - kfree_s (msq, sizeof (*msq)); + kfree(msq); } int sys_msgctl (int msqid, int cmd, struct msqid_ds *buf) diff --git a/ipc/sem.c b/ipc/sem.c index 393ef5f833cc..072cf55988a6 100644 --- a/ipc/sem.c +++ b/ipc/sem.c @@ -144,7 +144,7 @@ static void freeary (int id) wake_up (&sma->eventn); schedule(); } - kfree_s (sma, sizeof (*sma) + sma->sem_nsems * sizeof (struct sem)); + kfree(sma); return; } diff --git a/ipc/shm.c b/ipc/shm.c index 6f8edcab4477..71b4dedf8f57 100644 --- a/ipc/shm.c +++ b/ipc/shm.c @@ -95,7 +95,7 @@ found: shm_segs[id] = (struct shmid_ds *) IPC_UNUSED; if (shm_lock) wake_up (&shm_lock); - kfree_s (shp, sizeof (*shp)); + kfree(shp); return -ENOMEM; } @@ -186,9 +186,9 @@ static void killseg (int id) shm_swp--; } } - kfree_s (shp->shm_pages, numpages * sizeof (ulong)); + kfree(shp->shm_pages); shm_tot -= numpages; - kfree_s (shp, sizeof (*shp)); + kfree(shp); return; } @@ -439,7 +439,7 @@ int sys_shmat (int shmid, char *shmaddr, int shmflg, ulong *raddr) if (!shmd) return -ENOMEM; if ((shp != shm_segs[id]) || (shp->shm_perm.seq != shmid / SHMMNI)) { - kfree_s (shmd, sizeof (*shmd)); + kfree(shmd); return -EIDRM; } shmd->shm_sgn = (SHM_SWP_TYPE << 1) | (id << SHM_ID_SHIFT) | @@ -458,7 +458,7 @@ int sys_shmat (int shmid, char *shmaddr, int shmflg, ulong *raddr) if ((err = shm_map (shmd, shmflg & SHM_REMAP))) { if (--shp->shm_nattch <= 0 && shp->shm_perm.mode & SHM_DEST) killseg(id); - kfree_s (shmd, sizeof (*shmd)); + kfree(shmd); return err; } @@ -497,7 +497,7 @@ static void detach (struct shm_desc **shmdp) found: unmap_page_range (shmd->start, shp->shm_segsz); /* sleeps */ - kfree_s (shmd, sizeof (*shmd)); + kfree(shmd); shp->shm_lpid = current->pid; shp->shm_dtime = CURRENT_TIME; if (--shp->shm_nattch <= 0 && shp->shm_perm.mode & SHM_DEST) @@ -550,7 +550,7 @@ int shm_fork (struct task_struct *p1, struct task_struct *p2) if (!tmp) { while (new_desc) { tmp = new_desc->task_next; - kfree_s (new_desc, sizeof (*new_desc)); + kfree(new_desc); new_desc = tmp; } free_page_tables (p2); diff --git a/kernel/sched.c b/kernel/sched.c index 44c105261b33..388a78f2f913 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -222,7 +222,7 @@ confuse_gcc1: ++current->counter; } #endif - c = -1; + c = -1000; next = p = &init_task; for (;;) { if ((p = p->next_task) == &init_task) @@ -235,8 +235,9 @@ confuse_gcc2: for_each_task(p) p->counter = (p->counter >> 1) + p->priority; } - if(current != next) - kstat.context_swtch++; + if (current == next) + return; + kstat.context_swtch++; switch_to(next); /* Now maybe reload the debug registers */ if(current->debugreg[7]){ @@ -634,8 +635,8 @@ static void do_timer(struct pt_regs * regs) } #endif } - if (current == task[0] || (--current->counter)<=0) { - current->counter=0; + if (current != task[0] && 0 > --current->counter) { + current->counter = 0; need_resched = 1; } /* Update ITIMER_PROF for the current task */ diff --git a/kernel/sys.c b/kernel/sys.c index 396b139a5d1d..dcef7bb904bb 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -35,6 +35,23 @@ asmlinkage int sys_ni_syscall(void) return -EINVAL; } +asmlinkage int sys_idle(void) +{ + int i; + + /* Map out the low memory: it's no longer needed */ + for (i = 0 ; i < 768 ; i++) + swapper_pg_dir[i] = 0; + + /* endless idle loop with no priority at all */ + current->counter = -100; + for (;;) { + if (!need_resched) + __asm__("hlt"); + schedule(); + } +} + static int proc_sel(struct task_struct *p, int which, int who) { switch (which) { diff --git a/kernel/vm86.c b/kernel/vm86.c index 02cd58d35488..9739133f83c7 100644 --- a/kernel/vm86.c +++ b/kernel/vm86.c @@ -22,13 +22,14 @@ /* * virtual flags (16 and 32-bit versions) */ -#define VFLAGS(regs) (*(unsigned short *)&(current->v86flags)) -#define VEFLAGS(regs) (current->v86flags) +#define VFLAGS (*(unsigned short *)&(current->v86flags)) +#define VEFLAGS (current->v86flags) #define set_flags(X,new,mask) \ ((X) = ((X) & ~(mask)) | ((new) & (mask))) #define SAFE_MASK (0xDD5) +#define RETURN_MASK (0xDFF) asmlinkage struct pt_regs * save_v86_state(struct vm86_regs * regs) { @@ -38,6 +39,7 @@ asmlinkage struct pt_regs * save_v86_state(struct vm86_regs * regs) printk("no vm86_info: BAD\n"); do_exit(SIGSEGV); } + set_flags(regs->eflags, VEFLAGS, VIF_MASK | current->v86mask); memcpy_tofs(¤t->vm86_info->regs,regs,sizeof(*regs)); put_fs_long(current->screen_bitmap,¤t->vm86_info->screen_bitmap); tmp = current->tss.esp0; @@ -91,9 +93,9 @@ asmlinkage int sys_vm86(struct vm86_struct * v86) * has set it up safely, so this makes sure interrupt etc flags are * inherited from protected mode. */ - current->v86flags = info.regs.eflags; + VEFLAGS = info.regs.eflags; info.regs.eflags &= SAFE_MASK; - info.regs.eflags |= ~SAFE_MASK & pt_regs->eflags; + info.regs.eflags |= pt_regs->eflags & ~SAFE_MASK; info.regs.eflags |= VM_MASK; switch (info.cpu_type) { @@ -142,14 +144,14 @@ static inline void return_to_32bit(struct vm86_regs * regs16, int retval) static inline void set_IF(struct vm86_regs * regs) { - current->v86flags |= VIF_MASK; - if (current->v86flags & VIP_MASK) + VEFLAGS |= VIF_MASK; + if (VEFLAGS & VIP_MASK) return_to_32bit(regs, VM86_STI); } static inline void clear_IF(struct vm86_regs * regs) { - current->v86flags &= ~VIF_MASK; + VEFLAGS &= ~VIF_MASK; } static inline void clear_TF(struct vm86_regs * regs) @@ -159,7 +161,7 @@ static inline void clear_TF(struct vm86_regs * regs) static inline void set_vflags_long(unsigned long eflags, struct vm86_regs * regs) { - set_flags(VEFLAGS(regs), eflags, current->v86mask); + set_flags(VEFLAGS, eflags, current->v86mask); set_flags(regs->eflags, eflags, SAFE_MASK); if (eflags & IF_MASK) set_IF(regs); @@ -167,7 +169,7 @@ static inline void set_vflags_long(unsigned long eflags, struct vm86_regs * regs static inline void set_vflags_short(unsigned short flags, struct vm86_regs * regs) { - set_flags(VFLAGS(regs), flags, current->v86mask); + set_flags(VFLAGS, flags, current->v86mask); set_flags(regs->eflags, flags, SAFE_MASK); if (flags & IF_MASK) set_IF(regs); @@ -175,11 +177,19 @@ static inline void set_vflags_short(unsigned short flags, struct vm86_regs * reg static inline unsigned long get_vflags(struct vm86_regs * regs) { - unsigned long flags = regs->eflags & SAFE_MASK; + unsigned long flags = regs->eflags & RETURN_MASK; - if (current->v86flags & VIF_MASK) + if (VEFLAGS & VIF_MASK) flags |= IF_MASK; - return flags | (VEFLAGS(regs) & current->v86mask); + return flags | (VEFLAGS & current->v86mask); +} + +static inline int is_revectored(int nr, struct revectored_struct * bitmap) +{ + __asm__ __volatile__("btl %2,%%fs:%1\n\tsbbl %0,%0" + :"=r" (nr) + :"m" (*bitmap),"r" (nr)); + return nr; } /* diff --git a/mm/memory.c b/mm/memory.c index 0732b1cbb853..fece4a8f0bb8 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -1011,6 +1011,8 @@ void show_mem(void) show_buffers(); } +extern unsigned long free_area_init(unsigned long, unsigned long); + /* * paging_init() sets up the page tables - note that the first 4MB are * already mapped by head.S. @@ -1056,7 +1058,7 @@ unsigned long paging_init(unsigned long start_mem, unsigned long end_mem) } } invalidate(); - return start_mem; + return free_area_init(start_mem, end_mem); } void mem_init(unsigned long start_low_mem, @@ -1065,33 +1067,12 @@ void mem_init(unsigned long start_low_mem, int codepages = 0; int reservedpages = 0; int datapages = 0; - unsigned long tmp, mask; - unsigned short * p; + unsigned long tmp; extern int etext; cli(); end_mem &= PAGE_MASK; high_memory = end_mem; - start_mem += 0x0000000f; - start_mem &= ~0x0000000f; - tmp = MAP_NR(end_mem); - mem_map = (unsigned short *) start_mem; - p = mem_map + tmp; - start_mem = (unsigned long) p; - while (p > mem_map) - *--p = MAP_PAGE_RESERVED; - - /* set up the free-area data structures */ - for (mask = PAGE_MASK, tmp = 0 ; tmp < NR_MEM_LISTS ; tmp++, mask <<= 1) { - unsigned long bitmap_size; - free_area_list[tmp].prev = free_area_list[tmp].next = &free_area_list[tmp]; - end_mem = (end_mem + ~mask) & mask; - bitmap_size = end_mem >> (PAGE_SHIFT + tmp); - bitmap_size = (bitmap_size + 7) >> 3; - free_area_map[tmp] = (unsigned char *) start_mem; - memset((void *) start_mem, 0, bitmap_size); - start_mem += bitmap_size; - } /* mark usable pages in the mem_map[] */ start_low_mem = PAGE_ALIGN(start_low_mem); diff --git a/mm/swap.c b/mm/swap.c index 03540bc2ee9e..e61c90a837b7 100644 --- a/mm/swap.c +++ b/mm/swap.c @@ -263,17 +263,6 @@ static inline int try_to_swap_out(unsigned long * table_ptr) return 1 + mem_map[MAP_NR(page)]; } -/* - * sys_idle() does nothing much: it just searches for likely candidates for - * swapping out or forgetting about. This speeds up the search when we - * actually have to swap. - */ -asmlinkage int sys_idle(void) -{ - need_resched = 1; - return 0; -} - /* * A new implementation of swap_out(). We do not swap complete processes, * but only a small number of blocks, before we continue with the next @@ -896,3 +885,34 @@ void si_swapinfo(struct sysinfo *val) val->totalswap <<= PAGE_SHIFT; return; } + +/* + * set up the free-area data structures: + * - mark all pages MAP_PAGE_RESERVED + * - mark all memory queues empty + * - clear the memory bitmaps + */ +unsigned long free_area_init(unsigned long start_mem, unsigned long end_mem) +{ + unsigned short * p; + unsigned long mask = PAGE_MASK; + int i; + + mem_map = (unsigned short *) start_mem; + p = mem_map + MAP_NR(end_mem); + start_mem = (unsigned long) p; + while (p > mem_map) + *--p = MAP_PAGE_RESERVED; + + for (i = 0 ; i < NR_MEM_LISTS ; i++, mask <<= 1) { + unsigned long bitmap_size; + free_area_list[i].prev = free_area_list[i].next = &free_area_list[i]; + end_mem = (end_mem + ~mask) & mask; + bitmap_size = end_mem >> (PAGE_SHIFT + i); + bitmap_size = (bitmap_size + 7) >> 3; + free_area_map[i] = (unsigned char *) start_mem; + memset((void *) start_mem, 0, bitmap_size); + start_mem += bitmap_size; + } + return start_mem; +} diff --git a/net/inet/icmp.c b/net/inet/icmp.c index 5dacf6de9eab..1b934f5cc31f 100644 --- a/net/inet/icmp.c +++ b/net/inet/icmp.c @@ -186,6 +186,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, struct device *dev) icmp_statistics.IcmpOutErrors++; return; } + skb->free = 1; /* * Build Layer 2-3 headers for message back to source. diff --git a/net/inet/skbuff.c b/net/inet/skbuff.c index daabad659757..859935acc436 100644 --- a/net/inet/skbuff.c +++ b/net/inet/skbuff.c @@ -387,7 +387,8 @@ void kfree_skb(struct sk_buff *skb, int rw) { if (skb == NULL) { - printk("kfree_skb: skb = NULL\n"); + printk("kfree_skb: skb = NULL (from %08lx)\n", + ((unsigned long *) &skb)[-1]); return; } IS_SKB(skb); @@ -397,9 +398,11 @@ void kfree_skb(struct sk_buff *skb, int rw) return; } if (skb->free == 2) - printk("Warning: kfree_skb passed an skb that nobody set the free flag on!\n"); + printk("Warning: kfree_skb passed an skb that nobody set the free flag on! (from %08lx)\n", + ((unsigned long *) &skb)[-1]); if (skb->next) - printk("Warning: kfree_skb passed an skb still on a list.\n"); + printk("Warning: kfree_skb passed an skb still on a list (from %08lx).\n", + ((unsigned long *) &skb)[-1]); if (skb->sk) { if(skb->sk->prot!=NULL) -- 2.39.5