aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Murray <markm@FreeBSD.org>1997-11-10 18:10:41 +0000
committerMark Murray <markm@FreeBSD.org>1997-11-10 18:10:41 +0000
commit8bfc1067c3b493685418300fea866d851ab98a63 (patch)
treecb233efdc05a92c1e2283040d95ca68fefed6548
parent915f1f5d0871c790bcb1a126ef69a6b88e2d14f2 (diff)
downloadsrc-vendor/voxware.tar.gz
src-vendor/voxware.zip
Import of guspnp23.vendor/voxware
Notes
Notes: svn path=/cvs2svn/branches/AMANCIO/; revision=31106
-rw-r--r--sys/i386/isa/sound/CHANGELOG104
-rw-r--r--sys/i386/isa/sound/README16
-rw-r--r--sys/i386/isa/sound/Readme.modules186
-rw-r--r--sys/i386/isa/sound/Readme.v3036
-rw-r--r--sys/i386/isa/sound/ad1848.c2272
-rw-r--r--sys/i386/isa/sound/ad1848_mixer.h36
-rw-r--r--sys/i386/isa/sound/adlib_card.c29
-rw-r--r--sys/i386/isa/sound/aedsp16.c838
-rw-r--r--sys/i386/isa/sound/audio.c599
-rw-r--r--sys/i386/isa/sound/awe_wave.c51
-rw-r--r--sys/i386/isa/sound/dev_table.c414
-rw-r--r--sys/i386/isa/sound/dev_table.h696
-rw-r--r--sys/i386/isa/sound/dmabuf.c1944
-rw-r--r--sys/i386/isa/sound/gus_card.c221
-rw-r--r--sys/i386/isa/sound/gus_midi.c347
-rw-r--r--sys/i386/isa/sound/gus_vol.c171
-rw-r--r--sys/i386/isa/sound/gus_wave.c6536
-rw-r--r--sys/i386/isa/sound/hex2hex.h2
-rw-r--r--sys/i386/isa/sound/ics2101.c362
-rw-r--r--sys/i386/isa/sound/local.h201
-rw-r--r--sys/i386/isa/sound/midi_ctrl.h8
-rw-r--r--sys/i386/isa/sound/midi_synth.c797
-rw-r--r--sys/i386/isa/sound/midi_synth.h10
-rw-r--r--sys/i386/isa/sound/midibuf.c618
-rw-r--r--sys/i386/isa/sound/mpu401.c2271
-rw-r--r--sys/i386/isa/sound/opl3.c1697
-rw-r--r--sys/i386/isa/sound/opl3.h15
-rw-r--r--sys/i386/isa/sound/os.h343
-rw-r--r--sys/i386/isa/sound/pas2_card.c498
-rw-r--r--sys/i386/isa/sound/pas2_midi.c407
-rw-r--r--sys/i386/isa/sound/pas2_mixer.c566
-rw-r--r--sys/i386/isa/sound/pas2_pcm.c604
-rw-r--r--sys/i386/isa/sound/patmgr.c323
-rw-r--r--sys/i386/isa/sound/pcm86.c6
-rw-r--r--sys/i386/isa/sound/pss.c1403
-rw-r--r--sys/i386/isa/sound/sb16_dsp.c733
-rw-r--r--sys/i386/isa/sound/sb16_midi.c333
-rw-r--r--sys/i386/isa/sound/sb_card.c47
-rw-r--r--sys/i386/isa/sound/sb_dsp.c1481
-rw-r--r--sys/i386/isa/sound/sb_midi.c251
-rw-r--r--sys/i386/isa/sound/sb_mixer.c668
-rw-r--r--sys/i386/isa/sound/sb_mixer.h214
-rw-r--r--sys/i386/isa/sound/sequencer.c2597
-rw-r--r--sys/i386/isa/sound/sound.doc155
-rw-r--r--sys/i386/isa/sound/sound_calls.h224
-rw-r--r--sys/i386/isa/sound/sound_config.h183
-rw-r--r--sys/i386/isa/sound/sound_switch.c633
-rw-r--r--sys/i386/isa/sound/sound_timer.c458
-rw-r--r--sys/i386/isa/sound/soundcard.c773
-rw-r--r--sys/i386/isa/sound/soundvers.h3
-rw-r--r--sys/i386/isa/sound/sscape.c1340
-rw-r--r--sys/i386/isa/sound/sys_timer.c328
-rw-r--r--sys/i386/isa/sound/trix.c443
-rw-r--r--sys/i386/isa/sound/uart6850.c320
-rw-r--r--sys/i386/isa/sound/ulaw.h130
-rw-r--r--sys/i386/isa/sound/ultrasound.h72
56 files changed, 19258 insertions, 16755 deletions
diff --git a/sys/i386/isa/sound/CHANGELOG b/sys/i386/isa/sound/CHANGELOG
index fcdbb8e3eae6..878e2b75874a 100644
--- a/sys/i386/isa/sound/CHANGELOG
+++ b/sys/i386/isa/sound/CHANGELOG
@@ -1,10 +1,100 @@
-Changelog for version 2.90
-------------------------------------
-
-This is an intermediate release (v3.0 prototype with some experimental
-features disabled). See experimental.txt for more info.
+Changelog for version 3.5-alpha7
+--------------------------------
+
+Since 3.5-alpha6
+- Changed all #ifndef EXCLUDE_xx stuff to #ifdef CONFIG_xx. Modified
+configure to handle this.
+- Removed initialization messages from the
+modularized version. They can be enabled by using init_trace=1 in
+the insmod command line (insmod sound init_trace=1).
+- More AIX stuff.
+- Added support for syncronizing dsp/audio devices with /dev/sequencer.
+- mmap() support for dsp/audio devices.
+
+Since 3.5-alpha5
+- AIX port.
+- Changed some xxx_PATCH macros in soundcard.h to work with
+ big endian machines.
+
+Since 3.5-alpha4
+- Removed the 'setfx' stuff from the version distributed with kernel
+ sources.
+
+Since 3.5-alpha3
+- Moved stuff from the 'setfx' program to the AudioTriX Pro driver.
+
+Since 3.5-alpha2
+- Modifications to makefile and configure.c. Unnecessary sources
+ are no longer compiled. Newly created local.h is also copied to
+ /etc/soundconf. "make oldconfig" reads /etc/soundconf and produces
+ new local.h which is compatible with current version of the driver.
+- Some fixes to the SB16 support.
+- Fixed random protection fault in gus_wave.c
+
+Since 3.5-alpha1
+- Modified to work with Linux-1.3.33 and leater
+- Some minor changes
-Since pre-3.0-949712
+Since 3.0.2
+- Support for CS4232 based PnP cards (AcerMagic S23 etc).
+- Full duplex support for some CS4231, CS4232 and AD1845 based cards
+(GUA MAX, AudioTrix Pro, AcerMagic S23 and many MAD16/Mozart cards
+having a codec mentioned above).
+- Almost fully rewritten loadable modules support.
+- Fixed some bugs.
+- Huge amount of testing (more testing is still required).
+- mmap() support (works with some cards). Requires much more testing.
+- Sample/patch/program loading for TB Maui/Tropez. No initialization
+since TB doesn't allow me to release that code.
+- Using CS4231 compatible codecs as timer for /dev/music.
+
+Since 3.0.1
+- Added allocation of I/O ports, DMA channels and interrupts
+to the initialization code. This may break modules support since
+the driver may not free some resources on unload. Should be fixed soon.
+
+Since 3.0
+- Some important bug fixes.
+- select() for /dev/dsp and /dev/audio (Linux only).
+(To use select() with read, you have to call read() to start
+the recording. Calling write() kills recording immediately so
+use select() carefully when you are writing a half duplex app.
+Full duplex mode is not implemented yet.) Select works also with
+/dev/sequencer and /dev/music. Maybe with /dev/midi## too.
+
+Since 3.0-beta2
+- Minor fixes.
+- Added Readme.cards
+
+Since 3.0-beta1
+- Minor fixes to the modules support.
+- Eliminated call to sb_free_irq() in ad1848.c
+- Rewritten MAD16&Mozart support (not tested with MAD16 Pro).
+- Fix to DMA initialization of PSS cards.
+- Some fixes to ad1848/cs42xx mixer support (GUS MAX, MSS, etc.)
+- Fixed some bugs in the PSS driver which caused I/O errors with
+ the MSS mode (/dev/dsp).
+
+Since 3.0-950506
+- Recording with GUS MAX fixed. It works when the driver is configured
+ to use two DMA channels with GUS MAX (16 bit ones recommended).
+
+Since 3.0-94xxxx
+- Too many changes
+
+Since 3.0-940818
+- Fixes for Linux 1.1.4x.
+- Disables Disney Sound System with SG NX Pro 16 (less noise).
+
+Since 2.90-2
+- Fixes to soundcard.h
+- Non blocking mode to /dev/sequencer
+- Experimental detection code for Ensoniq Soundscape.
+
+Since 2.90
+- Minor and major bug fixes
+
+Since pre-3.0-940712
- GUS MAX support
- Partially working MSS/WSS support (could work with some cards).
- Hardware u-Law and A-Law support with AD1848/CS4248 and CS4231 codecs
@@ -52,7 +142,7 @@ Since 2.4
- 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
+- Implemented better detection for OPL-3. This should be useful 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).
diff --git a/sys/i386/isa/sound/README b/sys/i386/isa/sound/README
index a4a084706e5b..1c31ac66c2a7 100644
--- a/sys/i386/isa/sound/README
+++ b/sys/i386/isa/sound/README
@@ -38,14 +38,14 @@ Compatibility with the earlier versions
This version is backward compatible with the version 2.X. All programs
compiled with sys/soundcard.h of v2.X should work without problems.
PROGRAMS COMPILED WITH THE sys/soundcard.h OF THIS VERSION WILL NOT
-WORK WITH v2.X DRIVER. BE CAREFULL WHEN DISTRIBUTING BINARIES COMPILED
+WORK WITH v2.X DRIVER. BE CAREFUL WHEN DISTRIBUTING BINARIES COMPILED
FOR THIS VERSION.
Contributors
------------
This driver contains code by several contributors. In addition several other
-persons have given usefull suggestions. The following is a list of major
+persons have given useful 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
@@ -74,7 +74,13 @@ Hannu Savolainen
hannu@voxware.pp.fi
Snail mail: Hannu Savolainen
- Pallaksentie 4 A 2
- 00970 Helsinki
+ Hiekkalaiturintie 3 A 8
+ 00980 Helsinki
Finland
-FAX: +358 0 395 1968 (usually not connected)
+FAX: +358 0 341 6272 (answers if I have my machine (mgetty) on).
+
+NOTE! I probably don't answer to Snail mail or FAX messages. Sending answer
+ to each of them is simply too expensive and time consuming. However I
+ try to reply every email message I get (within a week). If you don't
+ get response, please check how your address is written in the message
+ header. I can't answer if I don't have a valid reply address.
diff --git a/sys/i386/isa/sound/Readme.modules b/sys/i386/isa/sound/Readme.modules
index 315540f510c1..2dab12552d1b 100644
--- a/sys/i386/isa/sound/Readme.modules
+++ b/sys/i386/isa/sound/Readme.modules
@@ -1,87 +1,99 @@
- Linux sound-driver module
- (c) Peter Trattler
- License: GPL (Gnu Public License)
-
-
-Idea:
-
-I've modified the sources for the sound driver to allow simply insert and
-remove the sound driver from the kernel by calling (only available for Linux)
-
- insmod /usr/src/linux/modules/sound.o
-
-and
-
- rmmod sound
-
-This may be useful if you are doing one of the following things:
-
-1) Debugging the sound driver
-2) Creating a new device within the sound-driver
-3) You do not the sound driver all the time (as it wastes quite a lot of
-memory for its buffers)
-
-
-Compilation:
-
-Go to /usr/src/linux and make the following steps:
-
-a) configure the sound driver: To do that call "make config" and enable the
-sound-driver -- you will be asked different questions about your
-sound-hardware (remember not to use a too big DMA-Buffer size; you
-should use 16kB, if you have 16Bit devices, otherwise you can use 32kB)
-
-b) disable the sound driver in the kernel: call make config again but answer
-'N' to "Sound card support"
-
-c) run "make modules"; the sound-driver sound.o should end up in
-/usr/src/linux/modules
-
-
-If memory is tight:
-
-I've allocated at about 70kB for the sound-drivers internal tables. If this
-is too much, 'insmod sound.o' will generate the following warning
-...
-use 'insmod memsize=xxxx'
-...
-You can only use this command, if you have (I think) at least
-modules-1.1.87 or up. You can also switch debugging on by running the command
-
-insmod sound.o debugmem=1
-
-
-Files I changed:
-
-I've only changed the files soundcard.c(most changes) and some changes within
-the Makefile, sound_config.h and the Makefile in /usr/src/linux/drivers
-
-
-Bugs:
-
-a) As the kmalloc (..., GFP_DMA) caused some unexpected errors (I don't know if
-it is my fault), I created some code, which is (by default) enabled by
-
-#define KMALLOC_DMA_BROKEN 1 (within soundcard.c).
-
-It trys to allocate a large enough region, so that the complete dma-buffer
-can be occupied in this space. If it does not fit within this region it
-doubles the size of it. But this can cause problems, if the sound-buffer is
-too big (as kmalloc can only handle regions at up to circa 100kB).
-
-So take care to use for 8Bit devices a sound-DMA-buffer of 32kB (maximum)
-and for 16Bit devices a maximum of 16kB. Otherwise the allocation scheme
-might fail.
-
-b) Buffers allocated by the different sound devices via calls to kmalloc are
-not freed, if the sound driver is removed again (these buffers tend to be
-quite small -- so it does not harm a lot)
-
-c) If there is not enough (kernel-) memory available, the installation of
-the sound-driver fails. (This happens quite often, if you did not install the
-driver right after booting -- [PS: I've only got 5MB of Ram, so this might
-be the source for this problem])
-
-
-Author:
- Peter Trattler (peter@sbox.tu-graz.ac.at)
+Building a loadable sound driver
+================================
+
+Loadable module support in version 3.5 of VoxWare is mostly rewritten since
+the previous version (3.0.1). This means that some things have changed.
+
+To compile the sound driver as a loadable module you have to perform
+the following steps:
+
+1) Install modules-1.2.8.tar.gz package (or later if available).
+2a) Check that symbol remap_page_range is defined in linux/init/ksyms.c.
+Insert a line containing "X(remap_page_range)," if required. The driver will
+not load if this line is missing.
+2b) Recompile kernel with soundcard support disabled.
+3) Boot the new kernel.
+4) cd to the sound driver source directory (this directory). It's no
+longer required that the sound driver sources are installed in the
+kernel source tree (linux/drivers/sound). When installing a separately
+distributed sound driver you may install the sources for example to
+/usr/src/sound.
+5) Execute make in the sound driver source directory. Enter
+configuration parameters as described in Readme.cards. Then just wait until
+the driver is compiled OK.
+6) Copy sound.o to the directory where insmod expects to find it.
+("make install" copies it to /lib/modules/misc).
+7) Use command "insmod sound" to load the driver.
+
+8) The sound driver can be removed using command "rmmod sound".
+
+
+Parameters accepted by the loadable sound driver
+================================================
+
+Setting DMA buffer size
+-----------------------
+
+The driver allocates a DMA buffer (or two for full duplex devices)
+every time the audio device (/dev/dsp or /dev/audio) is opened
+and frees it when the device is closed. Size of this buffer is defined
+when the driver is configured (the last question). The buffer size
+can be redefined when loading the driver if required (note that this is
+an optional feature which is not normally required). The buffer size
+is redefined by adding dma_pagesize= parameter to the insmod command line.
+For example:
+
+ insmod sound dma_buffsize=32768
+
+Minimum buffer size is 4096 and the maximum depends on the DMA channe.
+For 8 bit channels (0 to 3) the limit is 64k and for 16 bit ones (5 to 7)
+it's 128k. Driver selects a suitable buffer size automaticly in case
+you try to spesify an invalid size.
+
+Q: What is the right DMA buffer size?
+
+A: It depends on the sampling rate, machine speed and the load of the system.
+Large buffers are required on slow machines, when recording/playing CD-quality
+audio or when there are other processes running on the same system. Also
+recording to hard disk is likely to require large buffers.
+
+Very small buffers are sufficient when you are just playing 8kHz audio files
+on an empty P133 system. Using a 128k byffer just wastes 120k (or 250k)
+of valuable physical RAM memory.
+
+The right buffer sice can be easily found by making some experiments
+with the dma_buffsize= parameter. I use usually 16k buffers on a DX4/100 system
+and 64k on an old 386 system.
+
+NOTE! DMA buffers are used only by /dev/audio# and /dev/dsp# devices.
+ Other device files don't use them but there are two exceptions:
+ GUS driver uses DMA buffers when loading samples to the card.
+ Ensoniq SoundScape driver uses them when doanloading the microcode
+ file (sndscape.co[012]) to the card. Using large buffers doesn't
+ increase performance in these cases.
+
+Configuring device parameters when loading the driver
+-----------------------------------------------------
+
+The loadable version of the sound driver accepts now the same
+sound= parameter that has been available in the LILO command line.
+In this way it's possible to change I/O port, IRQ and DMA addresses
+and to enable/disable various cards at load time. Normally
+the driver uses the configuration parameters entered when compiling
+and configuring the driver.
+Look at Readme.linux for more info.
+
+NOTE! This method is not normally required. You should use it only when
+ you have to use different configuration than normally. The sound=
+ command line parameter is error phrone and not recommended.
+
+Debugging and tracing
+---------------------
+
+Modularized sound driver doesn't display messages during initialization as
+the kernel compiled one does. This feature can be turned on by adding
+init_trace=1 to the insmod command line.
+
+For example:
+
+ insmod sound init_trace=1
diff --git a/sys/i386/isa/sound/Readme.v30 b/sys/i386/isa/sound/Readme.v30
index cade461d2a6d..826710ea09cf 100644
--- a/sys/i386/isa/sound/Readme.v30
+++ b/sys/i386/isa/sound/Readme.v30
@@ -1,38 +1,24 @@
VoxWare v3.0
------------
-This is a PROTOTYPE of the VoxWare v3.0 to be released late 94.
-
-All features of v2.5 should work as earlier. There could be some
+All features of v2.90-2 should work as earlier. There could be some
omissions but they are unintentional. I started this version thread
after v2.3 so all features implemented before it are there.
-Even this is a prototype, there should not be any fatal bugs. The
-prototype just means that I don't have implemented all features
-completely. Mainly in the /dev/sequencer2 driver.
-For example recording from /dev/sequencer2 won't work
-with other cards than a full features MPU-401 or clones. As well the
-way how the MIDI controllers are handled will change.
-
-IMPORTANT!!!!!!!!!!!!!!!!!
-
-Don't distribute any binaries compiled with the soundcard.h of this version.
-They will not work together with older drivers.
-
New features
============
There are now two new device interfaces. The /dev/midi## is a raw
tty like interface to MIDI ports. There is a device file for each MIDI
port on your system. They are named (/dev/midi00 to /dev/midiNN).
-The second addition is the /dev/sequencer2 which is higher level interface
+The second addition is the /dev/music which is higher level interface
than the old /dev/sequencer. It's intended for writing device independent
applications like sequencers.
/dev/midi##
-----------
-This interface should be useful for applications like MIDI sysex librarians.
+This interface should be usefull for applications like MIDI sysex librarians.
There are (currently) no timing features so making music could be impossible.
There are as many /dev/midi## devices as there are MIDI ports in the system.
@@ -67,7 +53,7 @@ It's not available for the so called MPU UART ports of some soundcards
If this ioctl is called with mode=1, the interface is put to the intelligent
(coprocessor) mode. NOTE! The MIDI port will be reset when this ioctl is called.
It could have some strange effects if not called immediately after open. This
-call returns EINVAL if the midi port doesn't support the MPU-401 intelligent
+vall returns EINVAL if the midi port doesn't support the MPU-401 intelligent
mode.
ioctl(fd, SNDCTL_MIDI_MPUCMD, &cmdstruct) is valid only if the MIDI port
@@ -95,15 +81,15 @@ where:
data Buffer for the command arguments and returned
data.
-Be extremely careful with the nr_args and nr_returns fields. They
+Be extremely carefull with the nr_args and nr_returns fields. They
must match the command. An incorrect value will put the card and
the driver out of sync. Refer to the MPU-401/MQX-32M documentation for further
-details.
+datails.
-/dev/sequencer2 (if you find a better name, please let me know).
----------------
+/dev/music (/dev/sequencer2)
+----------------------------
This device file works much like the /dev/sequencer which has been present
since the beginning. The main differences are the following:
@@ -113,7 +99,7 @@ the result is somewhere between the MIDI specification and the synth devices of
/dev/sequencer. Both kind of devices are accessed using the SEQ_START_NOTE()
like macros. The voice number parameters of the API macros have been redefined
to denote MIDI channels. This means that the driver allocates voices for
-the channels automatically (this is a responsibility/right of an application
+the channels automaticly (this is a responsibility/right of an application
with /dev/sequencer). The result is that a SEQ_START_NOTE() macro has
similar effects for a synth channel than on a MIDI port. This kind of
solution provides better device independence than the /dev/sequencer. The
@@ -130,12 +116,12 @@ return sum of internal synthesizers (GUS, OPL3) and MIDI ports in the systems.
- The new interface is used much like the ordinary /dev/sequencer. The
event format is new so you have to use the API macros defined in the
-sys/soundcard.h. The interface will probably change before the final 3.0
+sys/soundcard.h. The interface is will propably change before the final 3.0
release but using the API macros should ensure compatibility in source level.
The new event format is not recognized by version 2.X so don't try to
distribute binaries compiled with soundcard.h of v3.X.
-- The basic API usage is similar to the current one. There are some new
+- The basic API useage is similar to the current one. There are some new
macros but the older ones should work as earlier. The most important
incompatibility is that the /dev/sequencer2 driver allocates voices itself.
The other one is that the application must send SEQ_START_TIMER() as it's
diff --git a/sys/i386/isa/sound/ad1848.c b/sys/i386/isa/sound/ad1848.c
index b08f5f76cc68..05d77fa36172 100644
--- a/sys/i386/isa/sound/ad1848.c
+++ b/sys/i386/isa/sound/ad1848.c
@@ -1,14 +1,29 @@
/*
* sound/ad1848.c
+ *
+ * Modified by Luigi Rizzo (luigi@iet.unipi.it)
*
- * The low level driver for the AD1848/CS4248 codec chip which
- * is used for example in the MS Sound System.
- *
- * The CS4231 which is used in the GUS MAX and some other cards is
- * upwards compatible with AD1848 and this driver is able to drive it.
- *
- * Copyright by Hannu Savolainen 1994
+ * The low level driver for the AD1848/CS4248 codec chip which is used for
+ * example in the MS Sound System.
+ *
+ * The CS4231 which is used in the GUS MAX and some other cards is upwards
+ * compatible with AD1848 and this driver is able to drive it.
+ *
+ * CS4231A and AD1845 are upward compatible with CS4231. However the new
+ * features of these chips are different.
+ *
+ * CS4232 is a PnP audio chip which contains a CS4231A (and SB, MPU). CS4232A is
+ * an improved version of CS4232.
+ *
+ * CS4236 is also a PnP audio chip similar to the 4232
*
+ * OPTi931 is another high-end 1848-type chip. It differs in the use
+ * of the high 16 registers and configuration stuff. Luckily, being a
+ * PnP device, we can avoid black magic to identify the chip and be
+ * sure of its identity.
+ *
+ * Copyright by Hannu Savolainen 1994, 1995
+ *
* 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
@@ -16,7 +31,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
@@ -28,53 +43,88 @@
* 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: Riccardo Facchetti 24 Mar 1995 - Added the Audio Excel DSP 16
+ * initialization routine.
*/
#define DEB(x)
#define DEB1(x)
-#include "sound_config.h"
+#include <i386/isa/sound/sound_config.h>
+
+#if defined(CONFIG_AD1848)
+
+#include <i386/isa/sound/ad1848_mixer.h>
+#include <i386/isa/sound/iwdefs.h>
+
+extern struct isa_driver mssdriver;
+
+extern void IwaveStopDma(BYTE path);
+
+typedef struct {
+ int base;
+ int irq;
+ int dual_dma; /* 1, when two DMA channels allocated */
+ u_char MCE_bit;
+ u_char saved_regs[16];
+
+ int speed;
+ u_char speed_bits;
+ int channels;
+ int audio_format;
+ u_char format_bits;
+
+ u_long xfer_count;
+ int irq_mode;
+ int intr_active;
+ int opened;
+ char *chip_name;
+ int mode;
+#define MD_1848 1
+#define MD_4231 2
+#define MD_4231A 3
+#define MD_1845 4
+#define MD_MAXMODE 5
+
+ /* Mixer parameters */
+ int recmask;
+ int supported_devices;
+ int supported_rec_devices;
+ u_short levels[32];
+ int dev_no;
+ volatile u_long timer_ticks;
+ int timer_running;
+ int irq_ok;
+ sound_os_info *osp;
+} ad1848_info;
-#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_AD1848)
+static int nr_ad1848_devs = 0;
+static volatile char irq2dev[17] =
+ {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
-#define IMODE_NONE 0
-#define IMODE_OUTPUT 1
-#define IMODE_INPUT 2
-#define IMODE_INIT 3
-#define IMODE_MIDI 4
+static int timer_installed = -1;
+static int mute_flag = 0;
+static char mixer2codec[MAX_MIXER_DEV] = {0};
-typedef struct
+static int ad_format_mask[MD_MAXMODE /* devc->mode */ ] =
{
- int base;
- int irq;
- int dma_capture, dma_playback;
- unsigned char MCE_bit;
-
- int speed;
- unsigned char speed_bits;
- int channels;
- int audio_format;
- unsigned char format_bits;
+ /* 0 - none */ 0,
+ /* 1 - AD1848 */ AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW,
- int xfer_count;
- int irq_mode;
- int intr_active;
- int opened;
- char *chip_name;
- int mode;
-}
+ /*
+ * AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW | AFMT_U16_LE |
+ * AFMT_IMA_ADPCM,
+ */
-ad1848_info;
+ /* 2 - CS4231 */ AFMT_U8 | AFMT_S16_LE | AFMT_U16_LE,
-static int nr_ad1848_devs = 0;
-static char irq2dev[16] =
-{-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1};
+ /*
+ * AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW | AFMT_U16_LE |
+ * AFMT_IMA_ADPCM,
+ */
-static int ad_format_mask[2 /*devc->mode*/ ] =
-{
- AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW,
- AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW | AFMT_U16_LE | AFMT_IMA_ADPCM
+ /* 3 - CS4231A */ AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW,
+ /* 4 - AD1845 */ AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW
};
static ad1848_info dev_info[MAX_AUDIO_DEV];
@@ -84,870 +134,1704 @@ static ad1848_info dev_info[MAX_AUDIO_DEV];
#define io_Status(d) ((d)->base+2)
#define io_Polled_IO(d) ((d)->base+3)
-static int ad1848_open (int dev, int mode);
-static void ad1848_close (int dev);
-static int ad1848_ioctl (int dev, unsigned int cmd, unsigned int arg, int local);
-static void ad1848_output_block (int dev, unsigned long buf, int count, int intrflag, int dma_restart);
-static void ad1848_start_input (int dev, unsigned long buf, int count, int intrflag, int dma_restart);
-static int ad1848_prepare_for_IO (int dev, int bsize, int bcount);
-static void ad1848_reset (int dev);
-static void ad1848_halt (int dev);
-void ad1848_interrupt (int dev);
+static int ad1848_open(int dev, int mode);
+static void ad1848_close(int dev);
+static int ad1848_ioctl(int dev, u_int cmd, ioctl_arg arg, int local);
+static void ad1848_output_block(int dev, u_long buf, int count, int intrflag, int dma_restart);
+static void ad1848_start_input(int dev, u_long buf, int count, int intrflag, int dma_restart);
+static int ad1848_prepare_for_IO(int dev, int bsize, int bcount);
+static void ad1848_reset(int dev);
+static void ad1848_halt(int dev);
+static void ad1848_halt_input(int dev);
+static void ad1848_halt_output(int dev);
+static void ad1848_trigger(int dev, int bits);
+static int ad1848_tmr_install(int dev);
+static void ad1848_tmr_reprogram(int dev);
+void adintr(int);
+
+/*
+ * AD_WAIT_INIT waits if we are initializing the board and we cannot modify
+ * its settings
+ */
+#define AD_WAIT_INIT(x) {int t=x; while(t>0 && inb(devc->base) == 0x80) t-- ; }
+
+short ipri_to_irq(u_short ipri);
+
+void
+adintr(unit)
+{
+ static short unit_to_irq[4] = {9, -1, -1, -1};
+ struct isa_device *dev;
+
+ if (unit_to_irq[unit] > 0)
+ ad1848_interrupt(unit_to_irq[unit]);
+ else {
+ dev = find_isadev(isa_devtab_null, &mssdriver, unit);
+ if (!dev)
+ printf("ad1848: Couldn't determine unit\n");
+ else {
+ unit_to_irq[unit] = ipri_to_irq(dev->id_irq);
+ ad1848_interrupt(unit_to_irq[unit]);
+ }
+ }
+}
static int
-ad_read (ad1848_info * devc, int reg)
+ad_read(ad1848_info * devc, int reg)
{
- unsigned long flags;
- int x;
+ u_long flags;
+ int x;
- DISABLE_INTR (flags);
- OUTB ((unsigned char) (reg & 0xff) | devc->MCE_bit, io_Index_Addr (devc));
- x = INB (io_Indexed_Data (devc));
- /* printk("(%02x<-%02x) ", reg|devc->MCE_bit, x); */
- RESTORE_INTR (flags);
+ AD_WAIT_INIT(900000);
+ flags = splhigh();
+ outb(io_Index_Addr(devc), (u_char) (reg & 0xff) | devc->MCE_bit);
+ x = inb(io_Indexed_Data(devc));
+ splx(flags);
- return x;
+ return x;
}
static void
-ad_write (ad1848_info * devc, int reg, int data)
+ad_write(ad1848_info * devc, int reg, u_char data)
{
- unsigned long flags;
+ u_long flags;
+
+ AD_WAIT_INIT(90000);
- DISABLE_INTR (flags);
- OUTB ((unsigned char) (reg & 0xff) | devc->MCE_bit, io_Index_Addr (devc));
- OUTB ((unsigned char) (data & 0xff), io_Indexed_Data (devc));
- /* printk("(%02x->%02x) ", reg|devc->MCE_bit, data); */
- RESTORE_INTR (flags);
+ flags = splhigh();
+ outb(io_Index_Addr(devc), (u_char) (reg & 0xff) | devc->MCE_bit);
+ outb(io_Indexed_Data(devc), (u_char) (data & 0xff));
+ splx(flags);
}
static void
-ad_set_MCE (ad1848_info * devc, int state)
+wait_for_calibration(ad1848_info * devc)
{
- unsigned long flags;
+ int timeout = 0;
- DISABLE_INTR (flags);
- if (state)
- devc->MCE_bit = 0x40;
- else
- devc->MCE_bit = 0x00;
- OUTB (devc->MCE_bit, io_Index_Addr (devc));
- RESTORE_INTR (flags);
+ /*
+ * Wait until the auto calibration process has finished.
+ *
+ * 1) Wait until the chip becomes ready (reads don't return 0x80).
+ * 2) Wait until the ACI bit of I11 gets on and then off.
+ */
+
+ AD_WAIT_INIT(100000);
+ if (inb(devc->base) & 0x80)
+ printf("ad1848: Auto calibration timed out(1).\n");
+
+ timeout = 100;
+ while (timeout > 0 && !(ad_read(devc, 11) & 0x20))
+ timeout--;
+ if (!(ad_read(devc, 11) & 0x20))
+ return;
+
+ timeout = 20000;
+ while (timeout > 0 && ad_read(devc, 11) & 0x20)
+ timeout--;
+ if (ad_read(devc, 11) & 0x20)
+ printf("ad1848: Auto calibration timed out(3).\n");
}
static void
-wait_for_calibration (ad1848_info * devc)
+ad_mute(ad1848_info * devc)
{
- int timeout = 0;
+ int i;
+ u_char prev;
- /*
- * Wait until the auto calibration process has finished.
- *
- * 1) Wait until the chip becomes ready (reads don't return 0x80).
- * 2) Wait until the ACI bit of I11 gets on and then off.
- */
+ mute_flag = 1;
- timeout = 100000;
- while (timeout > 0 && INB (devc->base) == 0x80)
- timeout--;
- if (INB (devc->base) == 0x80)
- printk ("ad1848: Auto calibration timed out(1).\n");
+ /*
+ * Save old register settings and mute output channels
+ */
+ for (i = 6; i < 8; i++) {
+ prev = devc->saved_regs[i] = ad_read(devc, i);
+ ad_write(devc, i, prev | 0x80);
+ }
+}
- timeout = 100000;
- while (timeout > 0 && !(ad_read (devc, 11) & 0x20))
- timeout--;
- if (!(ad_read (devc, 11) & 0x20))
- printk ("ad1848: Auto calibration timed out(2).\n");
+static void
+ad_unmute(ad1848_info * devc)
+{
+ int i;
+
+ mute_flag = 0;
+ /*
+ * Restore back old volume registers (unmute)
+ */
+ for (i = 6; i < 8; i++)
+ ad_write(devc, i, devc->saved_regs[i] & ~0x80);
+ }
- timeout = 100000;
- while (timeout > 0 && ad_read (devc, 11) & 0x20)
- timeout--;
- if (ad_read (devc, 11) & 0x20)
- printk ("ad1848: Auto calibration timed out(3).\n");
+static void
+ad_enter_MCE(ad1848_info * devc)
+{
+ u_long flags;
+
+ AD_WAIT_INIT(1000);
+ devc->MCE_bit = 0x40;
+ flags = splhigh();
+ if ( ( inb(io_Index_Addr(devc)) & 0x40) == 0 )
+ outb(io_Index_Addr(devc), devc->MCE_bit);
+ splx(flags);
}
-static struct audio_operations ad1848_pcm_operations[MAX_AUDIO_DEV] =
+static void
+ad_leave_MCE(ad1848_info * devc)
{
- {
- "Generic AD1848 codec",
- DMA_AUTOMODE,
- AFMT_U8, /* Will be set later */
- NULL,
- ad1848_open,
- ad1848_close,
- ad1848_output_block,
- ad1848_start_input,
- ad1848_ioctl,
- ad1848_prepare_for_IO,
- ad1848_prepare_for_IO,
- ad1848_reset,
- ad1848_halt,
- NULL,
- NULL
- }};
+ u_long flags;
+ u_char prev;
+
+ AD_WAIT_INIT(1000);
+
+ flags = splhigh();
+
+ devc->MCE_bit = 0x00;
+ prev = inb(io_Index_Addr(devc));
+ /* XXX the next call is redundant ? */
+ outb(io_Index_Addr(devc), 0x00); /* Clear the MCE bit */
+
+ if ((prev & 0x40) == 0) { /* Not in MCE mode */
+ splx(flags);
+ return;
+ }
+ outb(io_Index_Addr(devc), 0x00); /* Clear the MCE bit */
+ wait_for_calibration(devc);
+ splx(flags);
+}
+
static int
-ad1848_open (int dev, int mode)
+ad1848_set_recmask(ad1848_info * devc, int mask)
{
- int err;
- ad1848_info *devc = NULL;
- unsigned long flags;
-
- DEB (printk ("ad1848_open(int mode = %X)\n", mode));
+ u_char recdev;
+ int i, n;
- if (dev < 0 || dev >= num_audiodevs)
- return RET_ERROR (ENXIO);
+ mask &= devc->supported_rec_devices;
- devc = (ad1848_info *) audio_devs[dev]->devc;
+ n = 0;
+ for (i = 0; i < 32; i++)/* Count selected device bits */
+ if (mask & (1 << i))
+ n++;
- DISABLE_INTR (flags);
- if (devc->opened)
- {
- RESTORE_INTR (flags);
- printk ("ad1848: Already opened\n");
- return RET_ERROR (EBUSY);
- }
+ if (n == 0)
+ mask = SOUND_MASK_MIC;
+ else if (n != 1) { /* Too many devices selected */
+ mask &= ~devc->recmask; /* Filter out active settings */
- if (devc->irq) /* Not managed by another driver */
- if ((err = snd_set_irq_handler (devc->irq, ad1848_interrupt)) < 0)
- {
- printk ("ad1848: IRQ in use\n");
- RESTORE_INTR (flags);
- return err;
- }
+ n = 0;
+ for (i = 0; i < 32; i++) /* Count selected device bits */
+ if (mask & (1 << i))
+ n++;
- if (DMAbuf_open_dma (dev) < 0)
- {
- RESTORE_INTR (flags);
- printk ("ad1848: DMA in use\n");
- return RET_ERROR (EBUSY);
+ if (n != 1)
+ mask = SOUND_MASK_MIC;
+ }
+ switch (mask) {
+ case SOUND_MASK_MIC:
+ recdev = 2;
+ break;
+
+ case SOUND_MASK_LINE:
+ case SOUND_MASK_LINE3:
+ recdev = 0;
+ break;
+
+ case SOUND_MASK_CD:
+ case SOUND_MASK_LINE1:
+ recdev = 1;
+ break;
+
+ case SOUND_MASK_IMIX:
+ recdev = 3;
+ break;
+
+ default:
+ mask = SOUND_MASK_MIC;
+ recdev = 2;
}
- devc->intr_active = 0;
- devc->opened = 1;
- RESTORE_INTR (flags);
+ recdev <<= 6;
+ ad_write(devc, 0, (ad_read(devc, 0) & 0x3f) | recdev);
+ ad_write(devc, 1, (ad_read(devc, 1) & 0x3f) | recdev);
- return 0;
+ devc->recmask = mask;
+ return mask;
}
static void
-ad1848_close (int dev)
+change_bits(u_char *regval, int dev, int chn, int newval)
{
- unsigned long flags;
- ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc;
+ u_char mask;
+ int shift;
+
+ if (mix_devices[dev][chn].polarity == 1) /* Reverse */
+ newval = 100 - newval;
- DEB (printk ("ad1848_close(void)\n"));
+ mask = (1 << mix_devices[dev][chn].nbits) - 1;
+ shift = mix_devices[dev][chn].bitpos;
+ newval = (int) ((newval * mask) + 50) / 100; /* Scale it */
- DISABLE_INTR (flags);
+ *regval &= ~(mask << shift); /* Clear bits */
+ *regval |= (newval & mask) << shift; /* Set new value */
+}
- devc->intr_active = 0;
- if (devc->irq) /* Not managed by another driver */
- snd_release_irq (devc->irq);
- ad1848_reset (dev);
- DMAbuf_close_dma (dev);
- devc->opened = 0;
+static int
+ad1848_mixer_get(ad1848_info * devc, int dev)
+{
+ if (!((1 << dev) & devc->supported_devices))
+ return -(EINVAL);
- RESTORE_INTR (flags);
+ return devc->levels[dev];
}
+#define CLMICI 0x00781601
+#define CRMICI 0x00791701
+
static int
-set_speed (ad1848_info * devc, int arg)
+ad1848_mixer_set(ad1848_info * devc, int dev, int value)
{
- /*
- * The sampling speed is encoded in the least significant nible of I8. The
- * LSB selects the clock source (0=24.576 MHz, 1=16.9344 Mhz) and other
- * three bits select the divisor (indirectly):
- *
- * The available speeds are in the following table. Keep the speeds in
- * the increasing order.
- */
- typedef struct
- {
- int speed;
- unsigned char bits;
- }
- speed_struct;
-
- static speed_struct speed_table[] =
- {
- {5510, (0 << 1) | 1},
- {5510, (0 << 1) | 1},
- {6620, (7 << 1) | 1},
- {8000, (0 << 1) | 0},
- {9600, (7 << 1) | 0},
- {11025, (1 << 1) | 1},
- {16000, (1 << 1) | 0},
- {18900, (2 << 1) | 1},
- {22050, (3 << 1) | 1},
- {27420, (2 << 1) | 0},
- {32000, (3 << 1) | 0},
- {33075, (6 << 1) | 1},
- {37800, (4 << 1) | 1},
- {44100, (5 << 1) | 1},
- {48000, (6 << 1) | 0}
- };
-
- int i, n, selected = -1;
-
- n = sizeof (speed_table) / sizeof (speed_struct);
-
- if (arg < speed_table[0].speed)
- selected = 0;
- if (arg > speed_table[n - 1].speed)
- selected = n - 1;
-
- for (i = 1 /*really*/ ; selected == -1 && i < n; i++)
- if (speed_table[i].speed == arg)
- selected = i;
- else if (speed_table[i].speed > arg)
- {
- int diff1, diff2;
-
- diff1 = arg - speed_table[i - 1].speed;
- diff2 = speed_table[i].speed - arg;
-
- if (diff1 < diff2)
- selected = i - 1;
- else
- selected = i;
- }
+ int left = value & 0x000000ff;
+ int right = (value & 0x0000ff00) >> 8;
+ int retvol;
- if (selected == -1)
- {
- printk ("ad1848: Can't find speed???\n");
- selected = 3;
- }
+ int regoffs;
+ u_char val;
+ /* u_char clci, crmici, clmici, clici, crici; */
+
+ if (left > 100)
+ left = 100;
+ if (right > 100)
+ right = 100;
+
+ if (mix_devices[dev][RIGHT_CHN].nbits == 0) /* Mono control */
+ right = left;
+
+ retvol = left | (right << 8);
+
+ /* Scale volumes */
+ left = mix_cvt[left];
+ right = mix_cvt[right];
+
+ /* Scale it again */
+ left = mix_cvt[left];
+ right = mix_cvt[right];
- devc->speed = speed_table[selected].speed;
- devc->speed_bits = speed_table[selected].bits;
- return devc->speed;
+ if (dev > 31)
+ return -(EINVAL);
+
+ if (!(devc->supported_devices & (1 << dev)))
+ return -(EINVAL);
+
+ if (mix_devices[dev][LEFT_CHN].nbits == 0)
+ return -(EINVAL);
+
+ devc->levels[dev] = retvol;
+
+ /*
+ * Set the left channel
+ */
+ /* IwaveCodecMode(CODEC_MODE3); Default codec mode */
+
+ regoffs = mix_devices[dev][LEFT_CHN].regno;
+ val = ad_read(devc, regoffs);
+
+ change_bits(&val, dev, LEFT_CHN, left);
+ ad_write(devc, regoffs, val);
+ devc->saved_regs[regoffs] = val;
+
+ /*
+ * Set the right channel
+ */
+
+ if (mix_devices[dev][RIGHT_CHN].nbits == 0)
+ return retvol; /* Was just a mono channel */
+
+ regoffs = mix_devices[dev][RIGHT_CHN].regno;
+ val = ad_read(devc, regoffs);
+ change_bits(&val, dev, RIGHT_CHN, right);
+ ad_write(devc, regoffs, val);
+ devc->saved_regs[regoffs] = val;
+
+ return retvol;
}
-static int
-set_channels (ad1848_info * devc, int arg)
+static void
+ad1848_mixer_reset(ad1848_info * devc)
{
- if (arg != 1 && arg != 2)
- return devc->channels;
+ int i;
+
+ devc->recmask = 0;
+ if (devc->mode != MD_1848)
+ devc->supported_devices = MODE2_MIXER_DEVICES;
+ else
+ devc->supported_devices = MODE1_MIXER_DEVICES;
+
+ devc->supported_rec_devices = MODE1_REC_DEVICES;
- devc->channels = arg;
- return arg;
+ for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
+ if (devc->supported_devices & (1 << i))
+ ad1848_mixer_set(devc, i, default_mixer_levels[i]);
+ ad1848_set_recmask(devc, SOUND_MASK_MIC);
}
static int
-set_format (ad1848_info * devc, int arg)
+ad1848_mixer_ioctl(int dev, u_int cmd, ioctl_arg arg)
{
+ ad1848_info *devc;
+ int codec_dev = mixer2codec[dev];
- static struct format_tbl
- {
- int format;
- unsigned char bits;
- }
- format2bits [] =
- {
- {
- 0, 0
- }
- ,
- {
- AFMT_MU_LAW, 1
- }
- ,
- {
- AFMT_A_LAW, 3
- }
- ,
- {
- AFMT_IMA_ADPCM, 5
- }
- ,
- {
- AFMT_U8, 0
- }
- ,
+ if (!codec_dev)
+ return -(ENXIO);
+
+ codec_dev--;
+
+ devc = (ad1848_info *) audio_devs[codec_dev]->devc;
+
+ if (((cmd >> 8) & 0xff) == 'M') {
+ if (cmd & IOC_IN)
+ switch (cmd & 0xff) {
+ case SOUND_MIXER_RECSRC:
+ return *(int *) arg = ad1848_set_recmask(devc, (*(int *) arg));
+ break;
+
+ default:
+ return *(int *) arg = ad1848_mixer_set(devc, cmd & 0xff, (*(int *) arg));
+ }
+ else
+ switch (cmd & 0xff) { /* Return parameters */
+
+ case SOUND_MIXER_RECSRC:
+ return *(int *) arg = devc->recmask;
+ break;
+
+ case SOUND_MIXER_DEVMASK:
+ return *(int *) arg = devc->supported_devices;
+ break;
+
+ case SOUND_MIXER_STEREODEVS:
+ return *(int *) arg = devc->supported_devices & ~(SOUND_MASK_SPEAKER | SOUND_MASK_IMIX);
+ break;
+
+ case SOUND_MIXER_RECMASK:
+ return *(int *) arg = devc->supported_rec_devices;
+ break;
+
+ case SOUND_MIXER_CAPS:
+ return *(int *) arg = SOUND_CAP_EXCL_INPUT;
+ break;
+
+ default:
+ return *(int *) arg = ad1848_mixer_get(devc, cmd & 0xff);
+ }
+ } else
+ return -(EINVAL);
+}
+
+static struct audio_operations ad1848_pcm_operations[MAX_AUDIO_DEV] =
+{
{
- AFMT_S16_LE, 2
+ "Generic AD1848 codec",
+ /* DMA_AUTOMODE | DMA_DUPLEX, */
+ DMA_AUTOMODE,
+ AFMT_U8, /* Will be set later */
+ NULL,
+ ad1848_open,
+ ad1848_close,
+ ad1848_output_block,
+ ad1848_start_input,
+ ad1848_ioctl,
+ ad1848_prepare_for_IO,
+ ad1848_prepare_for_IO,
+ ad1848_reset,
+ ad1848_halt,
+ NULL,
+ NULL,
+ ad1848_halt_input,
+ ad1848_halt_output,
+ ad1848_trigger
}
- ,
- {
- AFMT_S16_BE, 6
+};
+
+static struct mixer_operations ad1848_mixer_operations =
+{
+ "AD1848/CS4248/CS4231",
+ ad1848_mixer_ioctl
+};
+
+static int
+ad1848_open(int dev, int mode)
+{
+ ad1848_info *devc = NULL;
+ u_long flags;
+ int otherside = audio_devs[dev]->otherside;
+
+ if (dev < 0 || dev >= num_audiodevs)
+ return -(ENXIO);
+
+ if (otherside != -1) {
+ if (audio_devs[otherside]->busy)
+ return -(EBUSY);
}
- ,
- {
- AFMT_S8, 0
+ if (audio_devs[dev]->busy)
+ return -(EBUSY);
+
+ devc = (ad1848_info *) audio_devs[dev]->devc;
+
+ flags = splhigh();
+ if (audio_devs[dev]->busy) {
+ splx(flags);
+ return -(EBUSY);
}
- ,
- {
- AFMT_U16_LE, 0
+ devc->dual_dma = 0;
+
+ if (audio_devs[dev]->flags & DMA_DUPLEX) {
+ devc->dual_dma = 1;
}
- ,
- {
- AFMT_U16_BE, 0
+ devc->intr_active = 0;
+ audio_devs[dev]->busy = 1;
+ devc->irq_mode = 0;
+ ad1848_trigger(dev, 0);
+ splx(flags);
+ /*
+ * Mute output until the playback really starts. This decreases
+ * clicking.
+ */
+ ad_mute(devc);
+
+ return 0;
+}
+
+static void
+ad1848_close(int dev)
+{
+ u_long flags;
+ ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc;
+ int otherside = audio_devs[dev]->otherside;
+
+ if (otherside != -1) {
+ if (audio_devs[otherside]->busy)
+ return;
}
- };
- int i, n = sizeof (format2bits) / sizeof (struct format_tbl);
+ DEB(printf("ad1848_close(void)\n"));
- if (!(arg & ad_format_mask[devc->mode]))
- arg = AFMT_U8;
+ flags = splhigh();
- devc->audio_format = arg;
+ ad_mute(devc);
- for (i = 0; i < n; i++)
- if (format2bits[i].format == arg)
- {
- if ((devc->format_bits = format2bits[i].bits) == 0)
- return devc->audio_format = AFMT_U8; /* Was not supported */
+ ad_write(devc, 9, ad_read(devc, 9) & ~0x1);
+ outb(io_Status(devc), 0); /* Clear interrupt status */
+ /*
+ * ad_write (devc, 15,0); ad_write (devc, 14,0);
+ */
+ devc->irq_mode &= ~PCM_ENABLE_OUTPUT;
- return arg;
- }
+ devc->intr_active = 0;
+ ad1848_reset(dev);
- /* Still hanging here. Something must be terribly wrong */
- devc->format_bits = 0;
- return devc->audio_format = AFMT_U8;
+ devc->opened = 0;
+ devc->irq_mode = 0;
+ audio_devs[dev]->busy = 0;
+ ad_unmute(devc);
+ splx(flags);
}
static int
-ad1848_ioctl (int dev, unsigned int cmd, unsigned int arg, int local)
+set_speed(ad1848_info * devc, int arg)
{
- ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc;
+ /*
+ * The sampling speed is encoded in the least significant nible of
+ * I8. The LSB selects the clock source (0=24.576 MHz, 1=16.9344 Mhz)
+ * and other three bits select the divisor (indirectly):
+ *
+ * The available speeds are in the following table. Keep the speeds in
+ * the increasing order.
+ */
+ typedef struct {
+ int speed;
+ u_char bits;
+ } speed_struct;
+
+ static speed_struct speed_table[] = {
+ {5510, (0 << 1) | 1},
+ {5510, (0 << 1) | 1},
+ {6620, (7 << 1) | 1},
+ {8000, (0 << 1) | 0},
+ {9600, (7 << 1) | 0},
+ {11025, (1 << 1) | 1},
+ {16000, (1 << 1) | 0},
+ {18900, (2 << 1) | 1},
+ {22050, (3 << 1) | 1},
+ {27420, (2 << 1) | 0},
+ {32000, (3 << 1) | 0},
+ {33075, (6 << 1) | 1},
+ {37800, (4 << 1) | 1},
+ {44100, (5 << 1) | 1},
+ {48000, (6 << 1) | 0}
+ };
+
+ int i, n, selected = -1;
+
+ n = sizeof(speed_table) / sizeof(speed_struct);
+
+ if (devc->mode == MD_1845) { /* AD1845 has different timer than others */
+ RANGE (arg, 4000, 50000) ;
+
+ devc->speed = arg;
+ devc->speed_bits = speed_table[selected].bits;
+ return devc->speed;
+ }
+ if (arg < speed_table[0].speed)
+ selected = 0;
+ if (arg > speed_table[n - 1].speed)
+ selected = n - 1;
+
+ for (i = 1 /* really */ ; selected == -1 && i < n; i++)
+ if (speed_table[i].speed == arg)
+ selected = i;
+ else if (speed_table[i].speed > arg) {
+ int diff1, diff2;
+
+ diff1 = arg - speed_table[i - 1].speed;
+ diff2 = speed_table[i].speed - arg;
+
+ if (diff1 < diff2)
+ selected = i - 1;
+ else
+ selected = i;
+ }
+ if (selected == -1) {
+ printf("ad1848: Can't find speed???\n");
+ selected = 3;
+ }
+ devc->speed = speed_table[selected].speed;
+ devc->speed_bits = speed_table[selected].bits;
+ return devc->speed;
+}
- switch (cmd)
- {
+static int
+set_channels(ad1848_info * devc, int arg)
+{
+ if (arg != 1 && arg != 2)
+ return devc->channels;
+
+ devc->channels = arg;
+ return arg;
+}
+
+static int
+set_format(ad1848_info * devc, int arg)
+{
+ static struct format_tbl {
+ int format;
+ u_char bits;
+ } format2bits[] = {
+ { 0, 0 } ,
+ { AFMT_MU_LAW, 1 } ,
+ { AFMT_A_LAW, 3 } ,
+ { AFMT_IMA_ADPCM, 5 } ,
+ { AFMT_U8, 0 } ,
+ { AFMT_S16_LE, 2 } ,
+ { AFMT_S16_BE, 6 } ,
+ { AFMT_S8, 0 } ,
+ { AFMT_U16_LE, 0 } ,
+ { AFMT_U16_BE, 0 }
+ };
+ int i, n = sizeof(format2bits) / sizeof(struct format_tbl);
+
+
+ if (!(arg & ad_format_mask[devc->mode]))
+ arg = AFMT_U8;
+
+ devc->audio_format = arg;
+
+ for (i = 0; i < n; i++)
+ if (format2bits[i].format == arg) {
+ if ((devc->format_bits = format2bits[i].bits) == 0)
+ return devc->audio_format = AFMT_U8; /* Was not supported */
+ return arg;
+ }
+ /* Still hanging here. Something must be terribly wrong */
+ devc->format_bits = 0;
+ return devc->audio_format = AFMT_U8;
+}
+
+/* XXX check what is arg, (int) or *(int *) lr970705 */
+static int
+ad1848_ioctl(int dev, u_int cmd, ioctl_arg arg, int local)
+{
+ ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc;
+
+ switch (cmd) {
case SOUND_PCM_WRITE_RATE:
- if (local)
- return set_speed (devc, arg);
- return IOCTL_OUT (arg, set_speed (devc, IOCTL_IN (arg)));
+ if (local)
+ return set_speed(devc, (int) arg);
+ return *(int *) arg = set_speed(devc, (*(int *) arg));
case SOUND_PCM_READ_RATE:
- if (local)
- return devc->speed;
- return IOCTL_OUT (arg, devc->speed);
+ if (local)
+ return devc->speed;
+ return *(int *) arg = devc->speed;
case SNDCTL_DSP_STEREO:
- if (local)
- return set_channels (devc, arg + 1) - 1;
- return IOCTL_OUT (arg, set_channels (devc, IOCTL_IN (arg) + 1) - 1);
+ if (local)
+ return set_channels(devc, (int) arg + 1) - 1;
+ return *(int *) arg = set_channels(devc, (*(int *) arg) + 1) - 1;
case SOUND_PCM_WRITE_CHANNELS:
- if (local)
- return set_channels (devc, arg);
- return IOCTL_OUT (arg, set_channels (devc, IOCTL_IN (arg)));
+ if (local)
+ return set_channels(devc, (int) arg);
+ return *(int *) arg = set_channels(devc, (*(int *) arg));
case SOUND_PCM_READ_CHANNELS:
- if (local)
- return devc->channels;
- return IOCTL_OUT (arg, devc->channels);
+ if (local)
+ return devc->channels;
+ return *(int *) arg = devc->channels;
case SNDCTL_DSP_SAMPLESIZE:
- if (local)
- return set_format (devc, arg);
- return IOCTL_OUT (arg, set_format (devc, IOCTL_IN (arg)));
+ if (local)
+ return set_format(devc, (int) arg);
+ return *(int *) arg = set_format(devc, (*(int *) arg));
case SOUND_PCM_READ_BITS:
- if (local)
- return devc->audio_format;
- return IOCTL_OUT (arg, devc->audio_format);
+ if (local)
+ return devc->audio_format;
+ return *(int *) arg = devc->audio_format;
+
+
+ case FIOASYNC:
+ if (local)
+ return 1;
+ return *(int *) arg = 1;
+
+ case FIONBIO:
+ if (local)
+ return 1;
+ return *(int *) arg = 1;
+
default:;
}
- return RET_ERROR (EINVAL);
+ return -(EINVAL);
}
static void
-ad1848_output_block (int dev, unsigned long buf, int count, int intrflag, int dma_restart)
+ad1848_output_block(int dev, u_long buf, int count, int intrflag, int dma_restart)
{
- unsigned long flags, cnt;
- ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc;
+ u_long flags, cnt;
+ ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc;
+
+ cnt = count;
+ if (devc->audio_format == AFMT_IMA_ADPCM) {
+ cnt /= 4;
+ } else {
+ if (devc->audio_format & (AFMT_S16_LE | AFMT_S16_BE)) /* 16 bit data */
+ cnt >>= 1;
+ }
+ if (devc->channels > 1)
+ cnt >>= 1;
+ cnt--;
+ if (mute_flag)
+ ad_unmute(devc);
- cnt = count;
+ if ( devc->irq_mode & PCM_ENABLE_OUTPUT &&
+ audio_devs[dev]->flags & DMA_AUTOMODE && intrflag &&
+ cnt == devc->xfer_count) {
+ devc->irq_mode |= PCM_ENABLE_OUTPUT;
+ devc->intr_active = 1;
- if (devc->audio_format == AFMT_IMA_ADPCM)
- {
- cnt /= 4;
}
- else
- {
- if (devc->audio_format & (AFMT_S16_LE | AFMT_S16_BE)) /* 16 bit data */
+ flags = splhigh();
+
+ if (dma_restart) {
+
+ DMAbuf_start_dma(dev, buf, count, 1);
+ }
+ ad_write(devc, 15, (u_char) (cnt & 0xff));
+ ad_write(devc, 14, (u_char) ((cnt >> 8) & 0xff));
+
+ devc->xfer_count = cnt;
+ devc->irq_mode |= PCM_ENABLE_OUTPUT;
+ devc->intr_active = 1;
+ splx(flags);
+}
+
+static void
+ad1848_start_input(int dev, u_long buf, int count,
+ int intrflag, int dma_restart)
+{
+ u_long flags, cnt;
+ ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc;
+
+ cnt = count;
+ if (devc->audio_format == AFMT_IMA_ADPCM)
+ cnt /= 4;
+ else if (devc->audio_format & (AFMT_S16_LE | AFMT_S16_BE)) /* 16 bit data */
cnt >>= 1;
+ if (devc->channels > 1)
+ cnt >>= 1;
+ cnt--;
+
+ if ( devc->irq_mode & PCM_ENABLE_INPUT &&
+ audio_devs[dev]->flags & DMA_AUTOMODE && intrflag &&
+ cnt == devc->xfer_count) {
+ devc->irq_mode |= PCM_ENABLE_INPUT;
+ devc->intr_active = 1;
+ return; /* Auto DMA mode on. No need to react */
}
- if (devc->channels > 1)
- cnt >>= 1;
- cnt--;
+ flags = splhigh();
- if (audio_devs[dev]->flags & DMA_AUTOMODE &&
- intrflag &&
- cnt == devc->xfer_count)
- {
- devc->irq_mode = IMODE_OUTPUT;
- devc->intr_active = 1;
- return; /*
- * Auto DMA mode on. No need to react
- */
+ if (dma_restart) {
+ /* ad1848_halt (dev); */
+ DMAbuf_start_dma(dev, buf, count, 0);
+ }
+ if (devc->mode == MD_1848 || !devc->dual_dma) {/* Single DMA chan. mode */
+ ad_write(devc, 15, (u_char) (cnt & 0xff));
+ ad_write(devc, 14, (u_char) ((cnt >> 8) & 0xff));
+ } else { /* Dual DMA channel mode */
+ ad_write(devc, 31, (u_char) (cnt & 0xff));
+ ad_write(devc, 30, (u_char) ((cnt >> 8) & 0xff));
}
- DISABLE_INTR (flags);
- if (dma_restart)
- {
- ad1848_halt (dev);
- DMAbuf_start_dma (dev, buf, count, DMA_MODE_WRITE);
+ /* ad_write (devc, 9, ad_read (devc, 9) | 0x02); *//* Capture enable */
+ ad_unmute(devc);
+
+ devc->xfer_count = cnt;
+ devc->irq_mode |= PCM_ENABLE_INPUT;
+ devc->intr_active = 1;
+ splx(flags);
+}
+
+static int
+ad1848_prepare_for_IO(int dev, int bsize, int bcount)
+{
+ int timeout;
+ u_char fs, old_fs;
+ u_long flags;
+ ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc;
+
+ if (devc->irq_mode)
+ return 0;
+
+ fs = devc->speed_bits | (devc->format_bits << 5);
+
+ if (devc->channels > 1)
+ fs |= 0x10;
+ old_fs = fs;
+
+ flags = splhigh();
+
+ if (devc->mode == MD_1845) { /* Use alternate speed select regs */
+ fs &= 0xf0; /* Mask off the rate select bits */
+
+ ad_write(devc, 22, (devc->speed >> 8) & 0xff); /* Speed MSB */
+ ad_write(devc, 23, devc->speed & 0xff); /* Speed LSB */
}
- ad_set_MCE (devc, 1);
+ ad_enter_MCE(devc); /* Enables changes to the format select reg */
+
+ ad_write(devc, 8, fs);
- ad_write (devc, 15, (unsigned char) (cnt & 0xff));
- ad_write (devc, 14, (unsigned char) ((cnt >> 8) & 0xff));
+ /*
+ * Write to I8 starts resyncronization. Wait until it completes.
+ */
+ AD_WAIT_INIT(10000);
+ /*
+ * If mode == 2 (CS4231), set I28 also. It's the capture format
+ * register.
+ */
+ if (devc->mode != MD_1848) {
+ ad_write(devc, 28, fs);
+
+ /*
+ * Write to I28 starts resyncronization. Wait until it completes.
+ */
+ AD_WAIT_INIT(10000);
+ }
- ad_write (devc, 9, 0x0d); /*
- * Playback enable, single DMA channel mode,
- * auto calibration on.
- */
+ ad_write(devc, 9, ad_read(devc, 9) & ~0x08);
- ad_set_MCE (devc, 0); /*
- * Starts the calibration process and
- * enters playback mode after it.
- */
- wait_for_calibration (devc);
+ ad_leave_MCE(devc);
- devc->xfer_count = cnt;
- devc->irq_mode = IMODE_OUTPUT;
- devc->intr_active = 1;
- RESTORE_INTR (flags);
+ splx(flags);
+
+ devc->xfer_count = 0;
+#ifdef CONFIG_SEQUENCER
+ if (dev == timer_installed && devc->timer_running)
+ if ((fs & 0x01) != (old_fs & 0x01)) {
+ ad1848_tmr_reprogram(dev);
+ }
+#endif
+ return 0;
}
static void
-ad1848_start_input (int dev, unsigned long buf, int count, int intrflag, int dma_restart)
+ad1848_reset(int dev)
{
- unsigned long flags, cnt;
- ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc;
+ ad1848_halt(dev);
+}
- /* int count_reg = (devc->mode == 1) ? 14 : 30; */
+static void
+ad1848_halt(int dev)
+{
+ ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc;
+ u_long flags;
+ int timeout;
- cnt = count;
- if (devc->audio_format == AFMT_IMA_ADPCM)
- {
- cnt /= 4;
- }
- else
- {
- if (devc->audio_format & (AFMT_S16_LE | AFMT_S16_BE)) /* 16 bit data */
- cnt >>= 1;
- }
- if (devc->channels > 1)
- cnt >>= 1;
- cnt--;
+ flags = splhigh();
- if (audio_devs[dev]->flags & DMA_AUTOMODE &&
- intrflag &&
- cnt == devc->xfer_count)
- {
- devc->irq_mode = IMODE_INPUT;
- devc->intr_active = 1;
- return; /*
- * Auto DMA mode on. No need to react
- */
- }
- DISABLE_INTR (flags);
+ ad_mute(devc);
- if (dma_restart)
- {
- ad1848_halt (dev);
- DMAbuf_start_dma (dev, buf, count, DMA_MODE_READ);
- }
+ ad_write(devc, 9, ad_read(devc, 9) & ~0x03); /* Stop DMA */
- ad_set_MCE (devc, 1);
-#if 0
- ad_write (devc, count_reg + 1, (unsigned char) (cnt & 0xff));
- ad_write (devc, count_reg, (unsigned char) ((cnt >> 8) & 0xff));
-#else
- ad_write (devc, 15, (unsigned char) (cnt & 0xff));
- ad_write (devc, 14, (unsigned char) ((cnt >> 8) & 0xff));
- if (devc->mode == 2)
- {
- ad_write (devc, 31, (unsigned char) (cnt & 0xff));
- ad_write (devc, 32, (unsigned char) ((cnt >> 8) & 0xff));
+ ad_write(devc, 14, 0); /* Clear DMA counter */
+ ad_write(devc, 15, 0); /* Clear DMA counter */
+
+ if (devc->mode != MD_1848) {
+ ad_write(devc, 30, 0); /* Clear DMA counter */
+ ad_write(devc, 31, 0); /* Clear DMA counter */
}
-#endif
- ad_write (devc, 9, 0x0e); /*
- * Capture enable, single DMA channel mode,
- * auto calibration on.
- */
+ for (timeout = 0; timeout < 1000 && !(inb(io_Status(devc)) & 0x01);
+ timeout++); /* Wait for interrupt */
- ad_set_MCE (devc, 0); /*
- * Starts the calibration process and
- * enters playback mode after it.
- */
- wait_for_calibration (devc);
+ outb(io_Status(devc), 0); /* Clear interrupt status */
- devc->xfer_count = cnt;
- devc->irq_mode = IMODE_INPUT;
- devc->intr_active = 1;
- RESTORE_INTR (flags);
-}
+ devc->irq_mode = 0;
-static int
-ad1848_prepare_for_IO (int dev, int bsize, int bcount)
-{
- int timeout;
- unsigned char fs;
- unsigned long flags;
- ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc;
-
- DISABLE_INTR (flags);
- ad_set_MCE (devc, 1); /* Enables changes to the format select reg */
- fs = devc->speed_bits | (devc->format_bits << 5);
-
- if (devc->channels > 1)
- fs |= 0x10;
-
- ad_write (devc, 8, fs);
- /*
- * Write to I8 starts resyncronization. Wait until it completes.
- */
- timeout = 10000;
- while (timeout > 0 && INB (devc->base) == 0x80)
- timeout--;
-
- ad_set_MCE (devc, 0); /*
- * Starts the calibration process and
- * enters playback mode after it.
- */
- wait_for_calibration (devc);
- RESTORE_INTR (flags);
-
- /*
- * If mode == 2 (CS4231), set I28 also. It's the capture format register.
- */
- if (devc->mode == 2)
- {
- ad_set_MCE (devc, 1);
- ad_write (devc, 28, fs);
-
- /*
- * Write to I28 starts resyncronization. Wait until it completes.
- */
- timeout = 10000;
- while (timeout > 0 && INB (devc->base) == 0x80)
- timeout--;
+ /* DMAbuf_reset_dma (dev); */
+ splx(flags);
+}
- ad_set_MCE (devc, 0); /*
- * Starts the calibration process and
- * enters playback mode after it.
- */
- wait_for_calibration (devc);
- RESTORE_INTR (flags);
+static void
+ad1848_halt_input(int dev)
+{
+ ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc;
+ u_long flags;
+ u_char playing;
+ if (devc->mode == MD_1848) {
+ ad1848_halt(dev);
+ return;
}
- devc->xfer_count = 0;
- return 0;
+ playing = ad_read(devc, 9);
+ if (!(playing & 0x2))
+ return;
+
+ flags = splhigh();
+
+ ad_mute(devc);
+ ad_write(devc, 9, playing & ~0x02); /* Stop capture */
+
+ outb(io_Status(devc), 0); /* Clear interrupt status */
+ outb(io_Status(devc), 0); /* Clear interrupt status */
+
+ devc->irq_mode &= ~PCM_ENABLE_INPUT;
+
+ splx(flags);
}
static void
-ad1848_reset (int dev)
+ad1848_halt_output(int dev)
{
- ad1848_halt (dev);
+ ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc;
+ u_long flags;
+ u_char playing;
+
+ playing = ad_read(devc, 9);
+ if (!(playing & 0x1)) {
+ devc->irq_mode &= ~PCM_ENABLE_OUTPUT;
+ return;
+ }
+ /* IwaveStopDma(PLAYBACK); */
+ if (devc->mode == MD_1848) {
+ ad1848_halt(dev);
+ return;
+ }
+ flags = splhigh();
+ /* ad_mute (devc); */
+
+ ad_write(devc, 9, playing & ~0x1);
+ outb(io_Status(devc), 0); /* Clear interrupt status */
+ /*
+ * ad_write (devc, 15,0); ad_write (devc, 14,0);
+ */
+ devc->irq_mode &= ~PCM_ENABLE_OUTPUT;
+
+ splx(flags);
}
static void
-ad1848_halt (int dev)
+ad1848_trigger(int dev, int state)
{
- ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc;
+ ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc;
+ u_long flags;
+ u_char tmp;
+
+ flags = splhigh();
+ state &= devc->irq_mode;
+
+ tmp = ad_read(devc, 9) & ~0x03;
+ if (state & PCM_ENABLE_INPUT)
+ tmp |= 0x02;
+ if (state & PCM_ENABLE_OUTPUT) {
+ tmp |= 0x01;
+ }
+ ad_write(devc, 9, tmp);
- ad_write (devc, 9, 0); /* Clear the PEN and CEN bits (among others) */
- OUTB (0, io_Status (devc)); /* Clear interrupt status */
+ splx(flags);
}
+
int
-ad1848_detect (int io_base)
+ad1848_detect(int io_base, int *ad_flags, sound_os_info * osp)
{
+ static int last_probe_addr=0, last_result=0; /* to avoid multiple probes*/
+ int i;
+ ad1848_info *devc = &dev_info[nr_ad1848_devs];
+ u_char tmp, tmp1, tmp2 ;
+
+ DDB(printf("ad1848_detect(%x)\n", io_base));
+ if (io_base == last_probe_addr)
+ return last_result;
+ else {
+ last_result = 0; /* default value for detect */
+ last_probe_addr = io_base ;
+ }
-#define DDB(x) x
+ if (ad_flags)
+ *ad_flags = 0;
- unsigned char tmp;
- int i;
- ad1848_info *devc = &dev_info[nr_ad1848_devs];
- unsigned char tmp1 = 0xff, tmp2 = 0xff;
+ if (nr_ad1848_devs >= MAX_AUDIO_DEV) {
+ DDB(printf("ad1848 detect error - step 0\n"));
+ return 0 ;
+ }
+ devc->base = io_base;
+ devc->irq_ok = 0;
+ devc->timer_running = 0;
+ devc->MCE_bit = 0x40;
+ devc->irq = 0;
+ devc->opened = 0;
+ devc->chip_name = "AD1848";
+ devc->mode = MD_1848; /* AD1848 or CS4248 */
+ devc->osp = osp;
+
+ /*
+ * Check that the I/O address is in use.
+ *
+ * The bit 0x80 of the base I/O port is known to be 0 after the chip has
+ * performed it's power on initialization. Just assume this has
+ * happened before the OS is starting.
+ *
+ * If the I/O address is unused, it typically returns 0xff.
+ */
+
+ DDB(printf("ad1848_detect() - step A\n"));
+
+ if ((inb(devc->base) & 0x80) != 0x00) { /* Not a AD1848 */
+ DDB(printf("ad1848 detect error - step A,"
+ " inb(base) = 0x%02x, want 0XXX.XXXX\n",
+ inb(devc->base)));
+ return 0;
+ }
+ /*
+ * Test if it's possible to change contents of the indirect
+ * registers. Registers 0 and 1 are ADC volume registers. The bit
+ * 0x10 is read only so try to avoid using it.
+ */
+
+ DDB(printf("ad1848_detect() - step B, test indirect register\n"));
+
+ ad_write(devc, 0, 0xaa);
+ ad_write(devc, 1, 0x45);/* 0x55 with bit 0x10 clear */
+ tmp1 = ad_read(devc, 0) ;
+ tmp2 = ad_read(devc, 1) ;
+ if ( tmp1 != 0xaa || tmp2 != 0x45) {
+ DDB(printf("ad1848 detect error - step B (0x%02x/0x%02x) want 0xaa/0x45\n", tmp1, tmp2));
+ return 0;
+ }
+ DDB(printf("ad1848_detect() - step C\n"));
+ ad_write(devc, 0, 0x45);
+ ad_write(devc, 1, 0xaa);
+ tmp1 = ad_read(devc, 0) ;
+ tmp2 = ad_read(devc, 1) ;
- if (nr_ad1848_devs >= MAX_AUDIO_DEV)
- return 0;
+ if (tmp1 != 0x45 || tmp2 != 0xaa) {
+ DDB(printf("ad1848 detect error - step C (%x/%x)\n", tmp1, tmp2));
- devc->base = io_base;
- devc->MCE_bit = 0x40;
- devc->irq = 0;
- devc->dma_capture = 0;
- devc->dma_playback = 0;
- devc->opened = 0;
- devc->chip_name = "AD1848";
- devc->mode = 1; /* MODE1 = original AD1848 */
-
- /*
- * Check that the I/O address is in use.
- *
- * The bit 0x80 of the base I/O port is known to be 0 after the
- * chip has performed it's power on initialization. Just assume
- * this has happened before the OS is starting.
- *
- * If the I/O address is unused, it typically returns 0xff.
- */
+ return 0;
+ }
+ /*
+ * The indirect register I12 has some read only bits. Lets try to
+ * change them.
+ */
+
+ DDB(printf("ad1848_detect() - step D, last 4 bits of I12 readonly\n"));
+ tmp = ad_read(devc, 12);
+ ad_write(devc, 12, (~tmp) & 0x0f);
+ tmp1 = ad_read(devc, 12);
+
+ if ((tmp & 0x0f) != (tmp1 & 0x0f)) {
+ DDB(printf("ad1848 detect error - step D, I12 (0x%02x was 0x%02x)\n",
+ tmp1, tmp));
+ return 0;
+ }
- if ((INB (devc->base) & 0x80) != 0x00) /* Not a AD1884 */
- {
- DDB (printk ("ad_detect_A\n"));
- return 0;
+ /*
+ * NOTE! Last 4 bits of the reg I12 tell the chip revision.
+ * 0x01=RevB
+ * 0x0A=RevC. also CS4231/CS4231A and OPTi931
+ */
+
+
+ /*
+ * The original AD1848/CS4248 has just 15 indirect registers. This
+ * means that I0 and I16 should return the same value (etc.). Ensure
+ * that the Mode2 enable bit of I12 is 0. Otherwise this test fails
+ * with CS4231.
+ */
+
+ DDB(printf("ad1848_detect() - step F\n"));
+ ad_write(devc, 12, 0); /* Mode2=disabled */
+
+ for (i = 0; i < 16; i++)
+ if ((tmp1 = ad_read(devc, i)) != (tmp2 = ad_read(devc, i + 16))) {
+ DDB(printf("ad1848 detect warning - step F(I%d/0x%02x/0x%02x)\n",
+ i, tmp1, tmp2));
+ /*
+ * note - this seems to fail on the 4232 on I11. So we just break
+ * rather than fail.
+ */
+ break ; /* return 0; */
+ }
+ /*
+ * Try to switch the chip to mode2 (CS4231) by setting the MODE2 bit
+ * (0x40). The bit 0x80 is always 1 in CS4248 and CS4231.
+ *
+ * On the OPTi931, however, I12 is readonly and only contains the
+ * chip revision ID (as in the CS4231A). The upper bits return 0.
+ */
+
+ DDB(printf("ad1848_detect() - step G\n"));
+ ad_write(devc, 12, 0x40); /* Set mode2, clear 0x80 */
+
+ tmp1 = ad_read(devc, 12);
+ if (tmp1 & 0x80) {
+ if (ad_flags)
+ *ad_flags |= AD_F_CS4248;
+
+ devc->chip_name = "CS4248"; /* Our best knowledge just now */
}
+ if ((tmp1 & 0xf0) == 0x00) {
+ printf("this should be an OPTi931\n");
+ } else if ((tmp1 & 0xc0) == 0xC0) {
+ /*
+ * The 4231 has bit7=1 always, and bit6 we just set to 1.
+ * We want to check that this is really a CS4231
+ * Verify that setting I0 doesn't change I16.
+ */
+ DDB(printf("ad1848_detect() - step H\n"));
+ ad_write(devc, 16, 0); /* Set I16 to known value */
- /*
- * Test if it's possible to change contents of the indirect registers.
- * Registers 0 and 1 are ADC volume registers. The bit 0x10 is read only
- * so try to avoid using it.
-*/
+ ad_write(devc, 0, 0x45);
+ if ((tmp1 = ad_read(devc, 16)) != 0x45) { /* No change -> CS4231? */
- ad_write (devc, 0, 0xaa);
- ad_write (devc, 1, 0x45); /* 0x55 with bit 0x10 clear */
+ ad_write(devc, 0, 0xaa);
+ if ((tmp1 = ad_read(devc, 16)) == 0xaa) { /* Rotten bits? */
+ DDB(printf("ad1848 detect error - step H(%x)\n", tmp1));
+ return 0;
+ }
+ /*
+ * Verify that some bits of I25 are read only.
+ */
+
+ DDB(printf("ad1848_detect() - step I\n"));
+ tmp1 = ad_read(devc, 25); /* Original bits */
+ ad_write(devc, 25, ~tmp1); /* Invert all bits */
+ if ((ad_read(devc, 25) & 0xe7) == (tmp1 & 0xe7)) {
+ int id;
+
+ /*
+ * It's at least CS4231
+ */
+ devc->chip_name = "CS4231";
+ devc->mode = MD_4231;
+
+ /*
+ * It could be an AD1845 or CS4231A as well.
+ * CS4231 and AD1845 report the same revision info in I25
+ * while the CS4231A reports different.
+ */
+
+ DDB(printf("ad1848_detect() - step I\n"));
+ id = ad_read(devc, 25) & 0xe7;
+ /*
+ * b7-b5 = version number;
+ * 100 : all CS4231
+ * 101 : CS4231A
+ *
+ * b2-b0 = chip id;
+ */
+ switch (id) {
+
+ case 0xa0:
+ devc->chip_name = "CS4231A";
+ devc->mode = MD_4231A;
+ break;
+
+ case 0xa2:
+ devc->chip_name = "CS4232";
+ devc->mode = MD_4231A;
+ break;
+
+ case 0xb2:
+ /* strange: the 4231 data sheet says b4-b3 are XX
+ * so this should be the same as 0xa2
+ */
+ devc->chip_name = "CS4232A";
+ devc->mode = MD_4231A;
+ break;
+
+ case 0x80:
+ /*
+ * It must be a CS4231 or AD1845. The register I23
+ * of CS4231 is undefined and it appears to be read
+ * only. AD1845 uses I23 for setting sample rate.
+ * Assume the chip is AD1845 if I23 is changeable.
+ */
+
+ tmp = ad_read(devc, 23);
+
+ ad_write(devc, 23, ~tmp);
+ if (ad_read(devc, 23) != tmp) { /* AD1845 ? */
+ devc->chip_name = "AD1845";
+ devc->mode = MD_1845;
+ }
+ ad_write(devc, 23, tmp); /* Restore */
+ break;
+
+ case 0x83: /* CS4236 */
+ default: /* Assume CS4231 */
+ printf("unknown id 0x%02x, assuming CS4231\n", id);
+ devc->mode = MD_4231;
+
+ }
+ }
+ ad_write(devc, 25, tmp1); /* Restore bits */
- if ((tmp1 = ad_read (devc, 0)) != 0xaa || (tmp2 = ad_read (devc, 1)) != 0x45)
- {
- DDB (printk ("ad_detect_B (%x/%x)\n", tmp1, tmp2));
- return 0;
+ DDB(printf("ad1848_detect() - step K\n"));
+ }
}
+ DDB(printf("ad1848_detect() - step L\n"));
- ad_write (devc, 0, 0x45);
- ad_write (devc, 1, 0xaa);
+ if (ad_flags) {
+ if (devc->mode != MD_1848)
+ *ad_flags |= AD_F_CS4231;
+ }
+ DDB(printf("ad1848_detect() - Detected OK\n"));
+ return (last_result = 1);
+}
- if ((tmp1 = ad_read (devc, 0)) != 0x45 || (tmp2 = ad_read (devc, 1)) != 0xaa)
- {
- DDB (printk ("ad_detect_C (%x/%x)\n", tmp1, tmp2));
- return 0;
+void
+ad1848_init(char *name, int io_base, int irq,
+ int dma_playback, int dma_capture, int share_dma, sound_os_info * osp)
+{
+
+ /*
+ * NOTE! If irq < 0, there is another driver which has allocated the
+ * IRQ so that this driver doesn't need to allocate/deallocate it.
+ * The actually used IRQ is ABS(irq).
+ */
+
+ /*
+ * Initial values for the indirect registers of CS4248/AD1848.
+ */
+ static int init_values[] = {
+ 0xa8, /* MIXOUTL: src:mic, +20dB, gain +12dB */
+ 0xa8, /* MIXOUTR: src:mic, +20dB, gain +12dB */
+ 0x08, /* CDL Input: mute, +6dB */
+ 0x08, /* CDR Input: mute, +6dB */
+ 0x08, /* FML Input: mute, +6dB */
+ 0x08, /* FMR Input: mute, +6dB */
+ 0x80, /* DAC-L Input: enable, 0dB */
+ 0x80, /* DAC-R Input: enable, 0dB */
+ /* 0xa8, 0xa8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, */
+ 0x00, /* 8bit, lin, uns, mono, 8KHz */
+ 0x0c, /* dma-cap, dma-pb, autocal, single dma, disable cap/pb */
+ 0x02, /* int enable */
+ 0x00, /* clear error status */
+ 0x8a, /* rev. id (low bytes readonly) */
+ 0x00,
+ 0x00, /* playback upper base count */
+ 0x00, /* playback lower base count */
+
+ /* Positions 16 to 31 just for CS4231 and newer devices */
+ /* I16-I17: alt. feature enable on the 4231, but AUXL Input
+ * on the OPTi931 (where the features are set elsewhere
+ */
+ 0x81, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+ int i, my_dev;
+
+ ad1848_info *devc = &dev_info[nr_ad1848_devs];
+
+ if (!ad1848_detect(io_base, NULL, osp))
+ return;
+
+ devc->irq = (irq > 0) ? irq : 0;
+ devc->opened = 0;
+ devc->timer_ticks = 0;
+ devc->osp = osp;
+
+ if (nr_ad1848_devs != 0) {
+ bcopy((char *) &ad1848_pcm_operations[0],
+ (char *) &ad1848_pcm_operations[nr_ad1848_devs],
+ sizeof(struct audio_operations));
}
+ for (i = 0; i < 16; i++)
+ ad_write(devc, i, init_values[i]);
+
+ ad_mute(devc); /* Initialize some variables */
+ ad_unmute(devc); /* Leave it unmuted now */
+
+ if (devc->mode > MD_1848) {
+ if (dma_capture == dma_playback ||
+ dma_capture == -1 || dma_playback == -1) {
+ ad_write(devc, 9, ad_read(devc, 9) | 0x04); /* Single DMA mode */
+ ad1848_pcm_operations[nr_ad1848_devs].flags &= ~DMA_DUPLEX;
+ } else {
+ ad_write(devc, 9, ad_read(devc, 9) & ~0x04); /* Dual DMA mode */
+ ad1848_pcm_operations[nr_ad1848_devs].flags |= DMA_DUPLEX;
+ }
- /*
- * The indirect register I12 has some read only bits. Lets
- * try to change them.
- */
+ ad_write(devc, 12, ad_read(devc, 12) | 0x40); /* Mode2 = enabled */
+ for (i = 16; i < 32; i++)
+ ad_write(devc, i, init_values[i]);
- tmp = ad_read (devc, 12);
- ad_write (devc, 12, (~tmp) & 0x0f);
+ if (devc->mode == MD_4231A) {
+ /* Enable full * calibration */
+ ad_write(devc, 9, init_values[9] | 0x18);
+ }
- if ((tmp & 0x0f) != ((tmp1 = ad_read (devc, 12)) & 0x0f))
- {
- DDB (printk ("ad_detect_D (%x)\n", tmp1));
- return 0;
+ if (devc->mode == MD_1845) {
+ /* Alternate freq select enabled */
+ ad_write(devc, 27, init_values[27] | 0x08);
+ }
+ } else {
+ ad1848_pcm_operations[nr_ad1848_devs].flags &= ~DMA_DUPLEX;
+ ad_write(devc, 9, ad_read(devc, 9) | 0x04); /* Single DMA mode */
}
- /*
- * NOTE! Last 4 bits of the reg I12 tell the chip revision.
- * 0x01=RevB and 0x0A=RevC.
- */
+ outb(io_Status(devc), 0); /* Clear pending interrupts */
- /*
- * The original AD1848/CS4248 has just 15 indirect registers. This means
- * that I0 and I16 should return the same value (etc.).
- * Ensure that the Mode2 enable bit of I12 is 0. Otherwise this test fails
- * with CS4231.
- */
+ if (name != NULL && name[0] != 0)
+ sprintf(ad1848_pcm_operations[nr_ad1848_devs].name,
+ "%s (%s)", name, devc->chip_name);
+ else
+ sprintf(ad1848_pcm_operations[nr_ad1848_devs].name,
+ "Generic audio codec (%s)", devc->chip_name);
- ad_write (devc, 12, 0); /* Mode2=disabled */
+ conf_printf2(ad1848_pcm_operations[nr_ad1848_devs].name,
+ devc->base, devc->irq, dma_playback, dma_capture);
- for (i = 0; i < 16; i++)
- if ((tmp1 = ad_read (devc, i)) != (tmp2 = ad_read (devc, i + 16)))
- {
- DDB (printk ("ad_detect_F(%d/%x/%x)\n", i, tmp1, tmp2));
- return 0;
- }
- /*
- * Try to switch the chip to mode2 (CS4231) by setting the MODE2 bit (0x40).
- * The bit 0x80 is always 1 in CS4248 and CS4231.
- */
+ /* ad1848_pcm_operations[nr_ad1848_devs].flags |= DMA_AUTOMODE ; */
- ad_write (devc, 12, 0x40); /* Set mode2, clear 0x80 */
+ if (num_audiodevs < MAX_AUDIO_DEV) {
+ audio_devs[my_dev = num_audiodevs++] =
+ &ad1848_pcm_operations[nr_ad1848_devs];
+ if (irq > 0) {
+ audio_devs[my_dev]->devc = devc;
+ irq2dev[irq] = my_dev;
+ if (snd_set_irq_handler(devc->irq, ad1848_interrupt, devc->osp)<0) {
+ printf("ad1848: IRQ in use\n");
+ }
+#ifdef NO_IRQ_TEST
+ if (devc->mode != MD_1848) {
+ int x;
+ u_char tmp = ad_read(devc, 16);
- tmp1 = ad_read (devc, 12);
- if (tmp1 & 0x80)
- devc->chip_name = "CS4248";
+ devc->timer_ticks = 0;
- if ((tmp1 & 0xc0) == (0x80 | 0x40))
- {
- /*
- * CS4231 detected - is it?
- *
- * Verify that setting I0 doesn't change I16.
- */
- ad_write (devc, 16, 0); /* Set I16 to known value */
+ ad_write(devc, 21, 0x00); /* Timer msb */
+ ad_write(devc, 20, 0x10); /* Timer lsb */
- ad_write (devc, 0, 0x45);
- if ((tmp1 = ad_read (devc, 16)) != 0x45) /* No change -> CS4231? */
- {
+ ad_write(devc, 16, tmp | 0x40); /* Enable timer */
+ for (x = 0; x < 100000 && devc->timer_ticks == 0; x++);
+ ad_write(devc, 16, tmp & ~0x40); /* Disable timer */
- ad_write (devc, 0, 0xaa);
- if ((tmp1 = ad_read (devc, 16)) == 0xaa) /* Rotten bits? */
- {
- DDB (printk ("ad_detect_H(%x)\n", tmp1));
- return 0;
- }
+ if (devc->timer_ticks == 0)
+ printf("[IRQ conflict???]");
+ else
+ devc->irq_ok = 1;
- /*
- * It's a CS4231 - So what!
- * (Mode2 will be supported later)
+ } else
+ devc->irq_ok = 1; /* Couldn't test. assume it's OK */
+#else
+ devc->irq_ok = 1;
+#endif
+ } else if (irq < 0)
+ irq2dev[-irq] = devc->dev_no = my_dev;
+
+ audio_devs[my_dev]->otherside = -1 ;
+ audio_devs[my_dev]->flags |= DMA_AUTOMODE | DMA_DUPLEX;
+ audio_devs[my_dev]->dmachan1 = dma_playback;
+ audio_devs[my_dev]->dmachan2 = dma_capture;
+ audio_devs[my_dev]->buffsize = DSP_BUFFSIZE;
+ audio_devs[my_dev]->devc = devc;
+ audio_devs[my_dev]->format_mask = ad_format_mask[devc->mode];
+ nr_ad1848_devs++;
+
+#ifdef CONFIG_SEQUENCER
+ if (devc->mode != MD_1848 && devc->irq_ok)
+ ad1848_tmr_install(my_dev);
+#endif
+
+ /*
+ * Toggle the MCE bit. It completes the initialization phase.
*/
- devc->chip_name = "CS4231";
- devc->mode = 2;
+
+ ad_enter_MCE(devc); /* In case the bit was off */
+ ad_leave_MCE(devc);
+
+ if (num_mixers < MAX_MIXER_DEV) {
+ mixer2codec[num_mixers] = my_dev + 1;
+ audio_devs[my_dev]->mixer_dev = num_mixers;
+ mixer_devs[num_mixers++] = &ad1848_mixer_operations;
+ ad1848_mixer_reset(devc);
}
+ } else
+ printf("AD1848: Too many PCM devices available\n");
+}
+
+void
+ad1848_interrupt(int irq)
+{
+ u_char status;
+ ad1848_info *devc;
+ int dev;
+
+ if (irq < 0 || irq > 15)
+ dev = -1;
+ else
+ dev = irq2dev[irq];
+
+ if (dev < 0 || dev >= num_audiodevs) {
+ for (irq = 0; irq < 17; irq++)
+ if (irq2dev[irq] != -1)
+ break;
+
+ if (irq > 15) {
+ printf("ad1848.c: Bogus interrupt %d\n", irq);
+ return;
+ }
+ dev = irq2dev[irq];
}
+ devc = (ad1848_info *) audio_devs[dev]->devc;
+
+ status = inb(io_Status(devc));
+
+ if (status & 0x01) { /* we have an interrupt */
+ int alt_stat = 0xff ;
+
+ if (devc->mode != MD_1848) {
+ /*
+ * high-end devices have full-duplex dma and timer.
+ * the exact reason for the interrupt is in reg. I24.
+ * For old devices, we fake the interrupt bits, and
+ * determine the real reason basing on the device mode.
+ */
+ alt_stat = ad_read(devc, 24);
+ if (alt_stat & 0x40) { /* Timer interrupt */
+ devc->timer_ticks++;
+#ifdef CONFIG_SEQUENCER
+ if (timer_installed == dev && devc->timer_running)
+ sound_timer_interrupt();
+#endif
+ }
+ }
+
+ outb(io_Status(devc), 0); /* Clear interrupt status */
+
+ if (audio_devs[dev]->busy) {
+
+ if (devc->irq_mode & PCM_ENABLE_OUTPUT && alt_stat & 0x10)
+ DMAbuf_outputintr(dev, 1);
- return 1;
+ if (devc->irq_mode & PCM_ENABLE_INPUT && alt_stat & 0x20)
+ DMAbuf_inputintr(dev);
+ }
+ }
}
+/*
+ * Some extra code for the MS Sound System
+ */
+
+#ifdef amancio
void
-ad1848_init (char *name, int io_base, int irq, int dma_playback, int dma_capture)
+check_opl3(int base, struct address_info * hw_config)
{
- /*
- * NOTE! If irq < 0, there is another driver which has allocated the IRQ
- * so that this driver doesn't need to allocate/deallocate it.
- * The actually used IRQ is ABS(irq).
- */
- /*
- * Initial values for the indirect registers of CS4248/AD1848.
+ if (!opl3_detect(base, hw_config->osp))
+ return;
+
+ opl3_init(0, base, hw_config->osp);
+}
+#endif
+
+/*
+ * this is the probe routine. Note, it is not necessary to
+ * go through this for PnP devices, since they are already
+ * indentified precisely using their PnP id.
+ *
*/
- static int init_values[] =
- {
- 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00,
- 0x00, 0x08, 0x02, 0x00, 0xca, 0x00, 0x00, 0x00
- };
- int i, my_dev;
- ad1848_info *devc = &dev_info[nr_ad1848_devs];
-
- if (!ad1848_detect (io_base))
- return;
-
- devc->irq = (irq > 0) ? irq : 0;
- devc->dma_capture = dma_playback;
- devc->dma_playback = dma_capture;
- devc->opened = 0;
-
- if (nr_ad1848_devs != 0)
- {
- memcpy ((char *) &ad1848_pcm_operations[nr_ad1848_devs],
- (char *) &ad1848_pcm_operations[0],
- sizeof (struct audio_operations));
- }
- for (i = 0; i < 16; i++)
- ad_write (devc, i, init_values[i]);
+int
+probe_mss(struct address_info * hw_config)
+{
+ u_char tmp;
- OUTB (0, io_Status (devc)); /* Clear pending interrupts */
+ DDB(printf("Entered probe_mss(io 0x%x, type %d)\n",
+ hw_config->io_base, hw_config->card_subtype));
-#ifndef SCO
- sprintf (ad1848_pcm_operations[nr_ad1848_devs].name,
- "%s (%s)", name, devc->chip_name);
+ if (hw_config->card_subtype == 1) { /* Has no IRQ/DMA registers */
+ /* check_opl3(0x388, hw_config); */
+ goto probe_ms_end;
+ }
+
+#if defined(CONFIG_AEDSP16) && defined(AEDSP16_MSS)
+ /*
+ * Initialize Audio Excel DSP 16 to MSS: before any operation we must
+ * enable MSS I/O ports.
+ */
+ InitAEDSP16_MSS(hw_config);
#endif
- if (irq > 0)
- printk (" <%s>", ad1848_pcm_operations[nr_ad1848_devs].name);
+ /*
+ * Check if the IO port returns valid signature. The original MS
+ * Sound system returns 0x04 while some cards (AudioTriX Pro for
+ * example) return 0x00 or 0x0f.
+ */
- if (num_audiodevs < MAX_AUDIO_DEV)
- {
- audio_devs[my_dev = num_audiodevs++] = &ad1848_pcm_operations[nr_ad1848_devs];
- if (irq > 0)
- irq2dev[irq] = my_dev;
- else if (irq < 0)
- irq2dev[-irq] = my_dev;
+ if ((tmp = inb(hw_config->io_base + 3)) == 0xff) { /* Bus float */
+ DDB(printf("I/O address inactive (%x), force type 1\n", tmp));
+ hw_config->card_subtype = 1 ;
+ goto probe_ms_end;
+ }
- audio_devs[my_dev]->dmachan = dma_playback;
- audio_devs[my_dev]->buffcount = 1;
- audio_devs[my_dev]->buffsize = DSP_BUFFSIZE * 2;
- audio_devs[my_dev]->devc = devc;
- audio_devs[my_dev]->format_mask = ad_format_mask[devc->mode];
- nr_ad1848_devs++;
+ if ((tmp & 0x3f) != 0x04 &&
+ (tmp & 0x3f) != 0x0f &&
+ (tmp & 0x3f) != 0x00) {
+ DDB(printf("No MSS signature detected on port 0x%x (0x%x)\n",
+ hw_config->io_base, inb(hw_config->io_base + 3)));
+ return 0;
}
- else
- printk ("AD1848: Too many PCM devices available\n");
+ if (hw_config->irq > 11) {
+ printf("MSS: Bad IRQ %d\n", hw_config->irq);
+ return 0;
+ }
+ if (hw_config->dma != 0 && hw_config->dma != 1 && hw_config->dma != 3) {
+ printf("MSS: Bad DMA %d\n", hw_config->dma);
+ return 0;
+ }
+ /*
+ * Check that DMA0 is not in use with a 8 bit board.
+ */
+
+ if (hw_config->dma == 0 && inb(hw_config->io_base + 3) & 0x80) {
+ printf("MSS: Can't use DMA0 with a 8 bit card/slot\n");
+ return 0;
+ }
+ if (hw_config->irq > 7 && hw_config->irq != 9 &&
+ inb(hw_config->io_base + 3) & 0x80) {
+ printf("MSS: Can't use IRQ%d with a 8 bit card/slot\n", hw_config->irq);
+ return 0;
+ }
+probe_ms_end:
+ return ad1848_detect(hw_config->io_base + 4, NULL, hw_config->osp);
}
void
-ad1848_interrupt (int irq)
+attach_mss(struct address_info * hw_config)
{
- unsigned char status;
- ad1848_info *devc;
- int dev;
-
- if (irq < 0 || irq > 15)
- return; /* Bogus irq */
- dev = irq2dev[irq];
- if (dev < 0 || dev >= num_audiodevs)
- return; /* Bogus dev */
- devc = (ad1848_info *) audio_devs[dev]->devc;
- status = INB (io_Status (devc));
-
- if (status & 0x01)
- {
- if (devc->opened && devc->irq_mode == IMODE_OUTPUT)
- {
- DMAbuf_outputintr (dev, 1);
- }
+#if 0
+ /*
+ * XXX do we really need to detect it again ? - lr970712
+ */
+ if (!ad1848_detect(hw_config->io_base + 4, NULL, hw_config->osp))
+ return ;
+#endif
- if (devc->opened && devc->irq_mode == IMODE_INPUT)
- DMAbuf_inputintr (dev);
+ if (hw_config->card_subtype == 1) { /* Has no IRQ/DMA registers */
+ ad1848_init("MS Sound System1", hw_config->io_base + 4,
+ hw_config->irq,
+ hw_config->dma,
+ hw_config->dma2, 0, hw_config->osp);
+ } else {
+ /*
+ * Set the IRQ and DMA addresses.
+ */
+ static char interrupt_bits[12] = {
+ -1, -1, -1, -1, -1, -1, -1, 0x08, -1, 0x10, 0x18, 0x20
+ };
+ static char dma_bits[4] = {
+ 1, 2, 0, 3
+ };
+
+ int config_port = hw_config->io_base + 0;
+ int version_port = hw_config->io_base + 3;
+ char bits = interrupt_bits[hw_config->irq];
+
+ if (bits == -1)
+ return ;
+
+ outb(config_port, bits | 0x40);
+ if ((inb(version_port) & 0x40) == 0)
+ printf("[IRQ Conflict?]");
+
+ /* Write IRQ+DMA setup */
+ outb(config_port, bits | dma_bits[hw_config->dma]);
+
+ ad1848_init("MS Sound System0", hw_config->io_base + 4,
+ hw_config->irq,
+ hw_config->dma,
+ hw_config->dma, 0, hw_config->osp);
}
-
- OUTB (0, io_Status (devc)); /* Clear interrupt status */
+ return ;
}
-#endif
/*
- * Some extra code for the MS Sound System
+ * WSS compatible PnP codec support.
+ * XXX I doubt it works now - lr970712
*/
-#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_MSS)
int
-probe_ms_sound (struct address_info *hw_config)
+probe_pnp_ad1848(struct address_info * hw_config)
{
- if ((INB (hw_config->io_base + 3) & 0x04) == 0)
- return 0; /* WSS ID test failed */
+ return ad1848_detect(hw_config->io_base, NULL, hw_config->osp);
+}
- if (hw_config->irq > 11)
- return 0;
+void
+attach_pnp_ad1848(struct address_info * hw_config)
+{
- if (hw_config->dma != 0 && hw_config->dma != 1 && hw_config->dma != 3)
- return 0;
+ ad1848_init(hw_config->name, hw_config->io_base,
+ hw_config->irq,
+ hw_config->dma,
+ hw_config->dma2, 0, hw_config->osp);
+}
+
+#ifdef CONFIG_SEQUENCER
+/*
+ * Timer stuff (for /dev/music).
+ */
+
+static u_int current_interval = 0;
+
+static u_int
+ad1848_tmr_start(int dev, u_int usecs)
+{
+ u_long flags;
+ ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc;
+ u_long xtal_nsecs; /* nanoseconds per xtal oscillaror tick */
+ u_long divider;
+
+ flags = splhigh();
+
+ /*
+ * Length of the timer interval (in nanoseconds) depends on the
+ * selected crystal oscillator. Check this from bit 0x01 of I8.
+ *
+ * AD1845 has just one oscillator which has cycle time of 10.050 us
+ * (when a 24.576 MHz xtal oscillator is used).
+ *
+ * Convert requested interval to nanoseconds before computing the timer
+ * divider.
+ */
+
+ if (devc->mode == MD_1845)
+ xtal_nsecs = 10050;
+ else if (ad_read(devc, 8) & 0x01)
+ xtal_nsecs = 9920;
+ else
+ xtal_nsecs = 9969;
+
+ divider = (usecs * 1000 + xtal_nsecs / 2) / xtal_nsecs;
+
+ if (divider < 100) /* Don't allow shorter intervals than about 1ms */
+ divider = 100;
+
+ if (divider > 65535) /* Overflow check */
+ divider = 65535;
+
+ ad_write(devc, 21, (divider >> 8) & 0xff); /* Set upper bits */
+ ad_write(devc, 20, divider & 0xff); /* Set lower bits */
+ ad_write(devc, 16, ad_read(devc, 16) | 0x40); /* Start the timer */
+ devc->timer_running = 1;
+ splx(flags);
+
+ return current_interval = (divider * xtal_nsecs + 500) / 1000;
+}
+
+static void
+ad1848_tmr_reprogram(int dev)
+{
+ /*
+ * Audio driver has changed sampling rate so that a different xtal
+ * oscillator was selected. We have to reprogram the timer rate.
+ */
- return ad1848_detect (hw_config->io_base + 4);
+ ad1848_tmr_start(dev, current_interval);
+ sound_timer_syncinterval(current_interval);
}
-long
-attach_ms_sound (long mem_start, struct address_info *hw_config)
+static void
+ad1848_tmr_disable(int dev)
{
- static unsigned char interrupt_bits[12] =
- {-1, -1, -1, -1, -1, -1, -1, 0x08, -1, 0x10, 0x18, 0x20};
- char bits;
+ u_long flags;
+ ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc;
- static unsigned char dma_bits[4] = {1, 2, 0, 3};
+ flags = splhigh();
+ ad_write(devc, 16, ad_read(devc, 16) & ~0x40);
+ devc->timer_running = 0;
+ splx(flags);
+}
- int config_port = hw_config->io_base + 0, version_port = hw_config->io_base + 3;
+static void
+ad1848_tmr_restart(int dev)
+{
+ u_long flags;
+ ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc;
- if (!ad1848_detect (hw_config->io_base + 4))
- return mem_start;
+ if (current_interval == 0)
+ return;
- /*
- * Set the IRQ and DMA addresses.
- */
+ flags = splhigh();
+ ad_write(devc, 16, ad_read(devc, 16) | 0x40);
+ devc->timer_running = 1;
+ splx(flags);
+}
- bits = interrupt_bits[hw_config->irq];
- if (bits == -1)
- return mem_start;
+static struct sound_lowlev_timer ad1848_tmr = {
+ 0,
+ ad1848_tmr_start,
+ ad1848_tmr_disable,
+ ad1848_tmr_restart
+};
- OUTB (bits | 0x40, config_port); /* Verify IRQ (I guess) */
- if ((INB (version_port) & 0x40) == 0)
- printk ("[IRQ?]");
+static int
+ad1848_tmr_install(int dev)
+{
+ if (timer_installed != -1)
+ return 0; /* Don't install another timer */
- OUTB (bits | dma_bits[hw_config->dma], config_port); /* Write IRQ+DMA setup */
+ timer_installed = ad1848_tmr.dev = dev;
+ sound_timer_init(&ad1848_tmr, audio_devs[dev]->name);
- ad1848_init ("MS Sound System", hw_config->io_base + 4,
- hw_config->irq,
- hw_config->dma,
- hw_config->dma);
- return mem_start;
+ return 1;
}
-
+#endif
#endif
diff --git a/sys/i386/isa/sound/ad1848_mixer.h b/sys/i386/isa/sound/ad1848_mixer.h
index 9404047ce77d..7a1d3230ece7 100644
--- a/sys/i386/isa/sound/ad1848_mixer.h
+++ b/sys/i386/isa/sound/ad1848_mixer.h
@@ -35,9 +35,10 @@
* (Actually this is not a mapping but rather some kind of interleaving
* solution).
*/
+#define GUSMAX_MIXER
#ifdef GUSMAX_MIXER
#define MODE1_REC_DEVICES (SOUND_MASK_LINE | SOUND_MASK_MIC | \
- SOUND_MASK_CD)
+ SOUND_MASK_CD|SOUND_MASK_IMIX)
#define MODE1_MIXER_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_MIC | \
SOUND_MASK_CD | \
@@ -50,7 +51,7 @@
SOUND_MASK_PCM | SOUND_MASK_IMIX)
#else /* Generic mapping */
#define MODE1_REC_DEVICES (SOUND_MASK_LINE3 | SOUND_MASK_MIC | \
- SOUND_MASK_LINE1)
+ SOUND_MASK_LINE1|SOUND_MASK_IMIX)
#define MODE1_MIXER_DEVICES (SOUND_MASK_LINE1 | SOUND_MASK_MIC | \
SOUND_MASK_LINE2 | \
@@ -70,6 +71,14 @@ struct mixer_def {
unsigned int nbits:4;
};
+static char mix_cvt[101] = {
+ 0, 0,3,7,10,13,16,19,21,23,26,28,30,32,34,35,37,39,40,42,
+ 43,45,46,47,49,50,51,52,53,55,56,57,58,59,60,61,62,63,64,65,
+ 65,66,67,68,69,70,70,71,72,73,73,74,75,75,76,77,77,78,79,79,
+ 80,81,81,82,82,83,84,84,85,85,86,86,87,87,88,88,89,89,90,90,
+ 91,91,92,92,93,93,94,94,95,95,96,96,96,97,97,98,98,98,99,99,
+ 100
+};
typedef struct mixer_def mixer_ent;
@@ -83,7 +92,7 @@ typedef struct mixer_def mixer_ent;
*/
#define MIX_ENT(name, reg_l, pola_l, pos_l, len_l, reg_r, pola_r, pos_r, len_r) \
- {{reg_l, pola_l, pos_r, len_l}, {reg_r, pola_r, pos_r, len_r}}
+ {{reg_l, pola_l, pos_l, len_l}, {reg_r, pola_r, pos_r, len_r}}
mixer_ent mix_devices[32][2] = { /* As used in GUS MAX */
MIX_ENT(SOUND_MIXER_VOLUME, 0, 0, 0, 0, 0, 0, 0, 0),
@@ -93,7 +102,7 @@ MIX_ENT(SOUND_MIXER_SYNTH, 4, 1, 0, 5, 5, 1, 0, 5),
MIX_ENT(SOUND_MIXER_PCM, 6, 1, 0, 6, 7, 1, 0, 6),
MIX_ENT(SOUND_MIXER_SPEAKER, 26, 1, 0, 4, 0, 0, 0, 0),
MIX_ENT(SOUND_MIXER_LINE, 18, 1, 0, 5, 19, 1, 0, 5),
-MIX_ENT(SOUND_MIXER_MIC, 0, 1, 5, 1, 1, 1, 5, 1),
+MIX_ENT(SOUND_MIXER_MIC, 0, 0, 5, 1, 1, 0, 5, 1),
MIX_ENT(SOUND_MIXER_CD, 2, 1, 0, 5, 3, 1, 0, 5),
MIX_ENT(SOUND_MIXER_IMIX, 13, 1, 2, 6, 0, 0, 0, 0),
MIX_ENT(SOUND_MIXER_ALTPCM, 0, 0, 0, 0, 0, 0, 0, 0),
@@ -111,20 +120,23 @@ static unsigned short default_mixer_levels[SOUND_MIXER_NRDEVICES] =
0x3232, /* Bass */
0x3232, /* Treble */
0x4b4b, /* FM */
- 0x6464, /* PCM */
+ 0x4040, /* PCM */
0x4b4b, /* PC Speaker */
- 0x4b4b, /* Ext Line */
- 0x1010, /* Mic */
+ /* 0x2020, Ext Line */
+ 0x0000, /* Ext Line */
+ 0x4040, /* Mic */
0x4b4b, /* CD */
0x0000, /* Recording monitor */
0x4b4b, /* SB PCM */
0x4b4b, /* Recording level */
- 0x4b4b, /* Input gain */
- 0x4b4b, /* Output gain */
- 0x4b4b, /* Line1 */
- 0x4b4b, /* Line2 */
- 0x4b4b /* Line3 */
+ 0x2525, /* Input gain */
+ 0x0000, /* Output gain */
+ /* 0x4040, Line1 */
+ 0x0000, /* Line1 */
+ 0x0000, /* Line2 */
+ 0x1515, /* Line3 (usually line in)*/
};
#define LEFT_CHN 0
#define RIGHT_CHN 1
+
diff --git a/sys/i386/isa/sound/adlib_card.c b/sys/i386/isa/sound/adlib_card.c
index 6365069384a5..41039b934d0a 100644
--- a/sys/i386/isa/sound/adlib_card.c
+++ b/sys/i386/isa/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,28 +24,23 @@
* 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"
+#include <i386/isa/sound/sound_config.h>
-#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_YM3812)
+#if defined(CONFIG_YM3812)
-long
-attach_adlib_card (long mem_start, struct address_info *hw_config)
+void
+attach_adlib_card(struct address_info * hw_config)
{
-
- if (opl3_detect (FM_MONO))
- {
- mem_start = opl3_init (mem_start);
- }
- return mem_start;
+ opl3_init(hw_config->io_base, hw_config->osp);
}
int
-probe_adlib (struct address_info *hw_config)
+probe_adlib(struct address_info * hw_config)
{
- return opl3_detect (FM_MONO);
+ return opl3_detect(hw_config->io_base, hw_config->osp);
}
#endif
diff --git a/sys/i386/isa/sound/aedsp16.c b/sys/i386/isa/sound/aedsp16.c
index b14a24618f0c..e69de29bb2d1 100644
--- a/sys/i386/isa/sound/aedsp16.c
+++ b/sys/i386/isa/sound/aedsp16.c
@@ -1,838 +0,0 @@
-/*
- sound/aedsp16.c
-
- Audio Excel DSP 16 software configuration routines
-
- Copyright (C) 1995 Riccardo Facchetti (riccardo@cdc8g5.cdc.polimi.it)
-
- 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.
-
- READ THIS
-
- This module is intended for Audio Excel DSP 16 Sound Card.
-
- Audio Excel DSP 16 is an SB pro II, Microsoft Sound System
- and MPU-401 compatible card.
- It is software-only configurable (no jumpers to hard-set irq/dma/mpu-irq),
- so before this module, the only way to configure the DSP under linux was
- boot the MS-BAU loading the sound.sys device driver (this driver soft-
- configure the sound board hardware by massaging someone of its registers),
- and then ctrl-alt-del to boot linux with the DSP configured by the DOG
- driver.
-
- This module works configuring your Audio Excel DSP 16's
- irq, dma and mpu-401-irq. The voxware probe routines rely on the
- fact that if the hardware is there, they can detect it. The problem
- with AEDSP16 is that no hardware can be found by the probe routines
- if the sound card is not well configured. Sometimes the kernel probe
- routines can find an SBPRO even when the card is not configured (this
- is the standard setup of the card), but the SBPRO emulation don't work
- well if the card is not properly initialized. For this reason
-
- InitAEDSP16_...()
-
- routines are called before the voxware probe routines try to detect the
- hardware.
-
- NOTE (READ THE NOTE TOO, IT CONTAIN USEFUL INFORMATIONS)
-
- The Audio Excel DSP 16 Sound Card emulates both SBPRO and MSS;
- the voxware sound driver can be configured for SBPRO and MSS cards
- at the same time, but the aedsp16 can't be two cards!!
- When we configure it, we have to choose the SBPRO or the MSS emulation
- for AEDSP16. We also can install a *REAL* card of the other type
- (see [1], not tested but I can't see any reason for it to fail).
-
- NOTE: If someone can test the combination AEDSP16+MSS or AEDSP16+SBPRO
- please let me know if it works.
-
- The MPU-401 support can be compiled in together with one of the other
- two operating modes.
-
- The board configuration calls, are in the probe_...() routines because
- we have to configure the board before probing it for a particular
- hardware. After card configuration, we can probe the hardware.
-
- NOTE: This is something like plug-and-play: we have only to plug
- the AEDSP16 board in the socket, and then configure and compile
- a kernel that uses the AEDSP16 software configuration capability.
- No jumper setting is needed!
-
- For example, if you want AEDSP16 to be an SBPro, on irq 10, dma 3
- you have just to make config the voxware package, configuring
- the SBPro sound card with that parameters, then when configure
- asks if you have an AEDSP16, answer yes. That's it.
- Compile the kernel and run it.
-
- NOTE: This means that you can choose irq and dma, but not the
- I/O addresses. To change I/O addresses you have to set them
- with jumpers.
-
- NOTE: InitAEDSP16_...() routines get as parameter the hw_config,
- the hardware configuration of the - to be configured - board.
- The InitAEDSP16() routine, configure the board following our
- wishes, that are in the hw_config structure.
-
- You can change the irq/dma/mirq settings WITHOUT THE NEED to open
- your computer and massage the jumpers (there are no irq/dma/mirq
- jumpers to be configured anyway, only I/O port ones have to be
- configured with jumpers)
-
- For some ununderstandable reason, the card default of irq 7, dma 1,
- don't work for me. Seems to be an IRQ or DMA conflict. Under heavy
- HDD work, the kernel start to erupt out a lot of messages like:
-
- 'Sound: DMA timed out - IRQ/DRQ config error?'
-
- For what I can say, I have NOT any conflict at irq 7 (under linux I'm
- using the lp polling driver), and dma line 1 is unused as stated by
- /proc/dma. I can suppose this is a bug of AEDSP16. I know my hardware so
- I'm pretty sure I have not any conflict, but may be I'm wrong. Who knows!
- Anyway a setting of irq 10, dma 3 works really fine.
-
- NOTE: if someone can use AEDSP16 with irq 7, dma 1, please let me know
- the emulation mode, all the installed hardware and the hardware
- configuration (irq and dma settings of all the hardware).
-
- This init module should work with SBPRO+MSS, when one of the two is
- the AEDSP16 emulation and the other the real card. (see [1])
- For example:
-
- AEDSP16 (0x220) in SBPRO emu (0x220) + real MSS + other
- AEDSP16 (0x220) in MSS emu + real SBPRO (0x240) + other
-
- MPU401 should work. (see [1])
-
- [1] Not tested by me for lack of hardware.
-
- TODO, WISHES AND TECH
-
- May be there's lot of redundant delays, but for now I want to leave it
- this way.
-
- Should be interesting eventually write down a new ioctl for the
- aedsp16, to let the suser() change the irq/dma/mirq on the fly.
- The thing is not trivial.
- In the real world, there's no need to have such an ioctl because
- when we configure the kernel for compile, we can choose the config
- parameters. If we change our mind, we can easily re-config the kernel
- and re-compile.
- Why let the suser() change the config parameters on the fly ?
- If anyone have a reasonable answer to this question, I will write down
- the code to do it.
-
- More integration with voxware, using voxware low level routines to
- read-write dsp is not possible because you may want to have MSS
- support and in that case we can not rely on the functions included
- in sb_dsp.c to control 0x2yy I/O ports. I will continue to use my
- own I/O functions.
-
- - About I/O ports allocation -
-
- The request_region should be done at device probe in every sound card
- module. This module is not the best site for requesting regions.
- When the request_region code will be added to the main modules such as
- sb, adlib, gus, ad1848, etc, the requesting code in this module should
- go away.
-
- I think the request regions should be done this way:
-
- if (check_region(...))
- return ERR; // I/O region alredy reserved
- device_probe(...);
- device_attach(...);
- request_region(...); // reserve only when we are sure all is okay
-
- Request the 2x0h region in any case if we are using this card.
-
- NOTE: the "(sbpro)" string with which we are requesting the aedsp16 region
- (see code) does not mean necessarly that we are emulating sbpro.
- It mean that the region is the sbpro I/O ports region. We use this
- region to access the control registers of the card, and if emulating
- sbpro, I/O sbpro registers too. If we are emulating MSS, the sbpro
- registers are not used, in no way, to emulate an sbpro: they are
- used only for configuration pourposes.
-
- Someone pointed out that should be possible use both the SBPRO and MSS
- modes because the sound card have all the two chipsets, supposing that
- the card is really two cards. I have tried something to have the two
- modes work together, but, for some reason unknown to me, without success.
-
- I think all the soft-config only cards have an init sequence similar to
- this. If you have a card that is not an aedsp16, you can try to start
- with this module changing it (mainly in the CMD? I think) to fit your
- needs.
-
- Started Fri Mar 17 16:13:18 MET 1995
-
- v0.1 (ALPHA, was an user-level program called AudioExcelDSP16.c)
- - Initial code.
- v0.2 (ALPHA)
- - Cleanups.
- - Integrated with Linux voxware v 2.90-2 kernel sound driver.
- - SoundBlaster Pro mode configuration.
- - Microsoft Sound System mode configuration.
- - MPU-401 mode configuration.
- v0.3 (ALPHA)
- - Cleanups.
- - Rearranged the code to let InitAEDSP16 be more general.
- - Erased the REALLY_SLOW_IO. We don't need it. Erased the linux/io.h
- inclusion too. We rely on os.h
- - Used the INB and OUTB #defined in os.h instead of inb and outb.
- - Corrected the code for GetCardName (DSP Copyright) to get a variable
- len string (we are not sure about the len of Copyright string).
- This works with any SB and compatible.
- - Added the code to request_region at device init (should go in
- the main body of voxware).
- v0.4 (BETA)
- - Better configure.c patch for aedsp16 configuration (better
- logic of inclusion of AEDSP16 support)
- - Modified the conditional compilation to better support more than
- one sound card of the emulated type (read the NOTES above)
- - Moved the sb init routine from the attach to the very first
- probe in sb_card.c
- - Rearrangemens and cleanups
- - Wiped out some unnecessary code and variables: this is kernel
- code so it is better save some TEXT and DATA
- - Fixed the request_region code. We must allocate the aedsp16 (sbpro)
- I/O ports in any case because they are used to access the DSP
- configuration registers and we can not allow anyone to get them.
- v0.5
- - cleanups on comments
- - prep for diffs against v3.0-proto-950402
-
- */
-
-/*
- * Include the main voxware header file. It include all the os/voxware/etc
- * headers needed by this source.
- */
-#include "sound_config.h"
-/*
- * all but ioport.h :)
- */
-#include <linux/ioport.h>
-
-#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_AEDSP16)
-
-#define VERSION "0.5" /* Version of Audio Excel DSP 16 driver */
-
-#undef AEDSP16_DEBUG /* Define this to enable debug code */
-/* Actually no debug code is activated */
-
-/*
- * Hardware related defaults
- */
-#define IRQ 7 /* 5 7(default) 9 10 11 */
-#define MIRQ 0 /* 5 7 9 10 0(default), 0 means disable */
-#define DMA 1 /* 0 1(default) 3 */
-
-/*
- * Commands of AEDSP16's DSP (SBPRO+special).
- * For now they are CMDn, in the future they may change.
- */
-#define CMD1 0xe3 /* Get DSP Copyright */
-#define CMD2 0xe1 /* Get DSP Version */
-#define CMD3 0x88 /* */
-#define CMD4 0x5c /* */
-#define CMD5 0x50 /* Set M&I&DRQ mask (the real config) */
-#define CMD6 0x8c /* Enable Microsoft Sound System mode */
-
-/*
- * Offsets of AEDSP16 DSP I/O ports. The offest is added to portbase
- * to have the actual I/O port.
- * Register permissions are:
- * (wo) == Write Only
- * (ro) == Read Only
- * (w-) == Write
- * (r-) == Read
- */
-#define DSP_RESET 0x06 /* offset of DSP RESET (wo) */
-#define DSP_READ 0x0a /* offset of DSP READ (ro) */
-#define DSP_WRITE 0x0c /* offset of DSP WRITE (w-) */
-#define DSP_COMMAND 0x0c /* offset of DSP COMMAND (w-) */
-#define DSP_STATUS 0x0c /* offset of DSP STATUS (r-) */
-#define DSP_DATAVAIL 0x0e /* offset of DSP DATA AVAILABLE (ro) */
-
-
-#define RETRY 10 /* Various retry values on I/O opera- */
-#define STATUSRETRY 1000 /* tions. Sometimes we have to */
-#define HARDRETRY 500000 /* wait for previous cmd to complete */
-
-/*
- * Size of character arrays that store name and version of sound card
- */
-#define CARDNAMELEN 15 /* Size of the card's name in chars */
-#define CARDVERLEN 2 /* Size of the card's version in chars */
-
-/*
- * Bit mapped flags for calling InitAEDSP16(), and saving the current
- * emulation mode.
- */
-#define INIT_NONE (0 )
-#define INIT_SBPRO (1<<0)
-#define INIT_MSS (1<<1)
-#define INIT_MPU401 (1<<2)
-#define RESET_DSP16 (1<<3)
-
-/* Base HW Port for Audio Card */
-static int portbase = AEDSP16_BASE;
-static int irq = IRQ; /* irq for DSP I/O */
-static int mirq = MIRQ; /* irq for MPU-401 I/O */
-static int dma = DMA; /* dma for DSP I/O */
-
-/* Init status of the card */
-static int ae_init = INIT_NONE; /* (bitmapped variable) */
-static int oredparams = 0; /* Will contain or'ed values of params */
-static int gc = 0; /* generic counter (utility counter) */
-struct orVals
- { /* Contain the values to be or'ed */
- int val; /* irq|mirq|dma */
- int or; /* oredparams |= TheStruct.or */
- };
-
-/*
- * Magic values that the DSP will eat when configuring irq/mirq/dma
- */
-/* DSP IRQ conversion array */
-static struct orVals orIRQ[] =
-{
- {0x05, 0x28},
- {0x07, 0x08},
- {0x09, 0x10},
- {0x0a, 0x18},
- {0x0b, 0x20},
- {0x00, 0x00}
-};
-
-/* MPU-401 IRQ conversion array */
-static struct orVals orMIRQ[] =
-{
- {0x05, 0x04},
- {0x07, 0x44},
- {0x09, 0x84},
- {0x0a, 0xc4},
- {0x00, 0x00}
-};
-
-/* DMA Channels conversion array */
-static struct orVals orDMA[] =
-{
- {0x00, 0x01},
- {0x01, 0x02},
- {0x03, 0x03},
- {0x00, 0x00}
-};
-
-/*
- * Buffers to store audio card informations
- */
-static char AudioExcelName[CARDNAMELEN + 1];
-static char AudioExcelVersion[CARDVERLEN + 1];
-
-static void
-tenmillisec (void)
-{
-
- for (gc = 0; gc < 1000; gc++)
- tenmicrosec ();
-}
-
-static int
-WaitForDataAvail (int port)
-{
- int loop = STATUSRETRY;
- unsigned char ret = 0;
-
- do
- {
- ret = INB (port + DSP_DATAVAIL);
- /*
- * Wait for data available (bit 7 of ret == 1)
- */
- }
- while (!(ret & 0x80) && loop--);
-
- if (ret & 0x80)
- return 0;
-
- return -1;
-}
-
-static int
-ReadData (int port)
-{
- if (WaitForDataAvail (port))
- return -1;
- return INB (port + DSP_READ);
-}
-
-static int
-CheckDSPOkay (int port)
-{
- return ((ReadData (port) == 0xaa) ? 0 : -1);
-}
-
-static int
-ResetBoard (int port)
-{
- /*
- * Reset DSP
- */
- OUTB (1, (port + DSP_RESET));
- tenmicrosec ();
- OUTB (0, (port + DSP_RESET));
- tenmicrosec ();
- tenmicrosec ();
- return CheckDSPOkay (port);
-}
-
-static int
-WriteDSPCommand (int port, int cmd)
-{
- unsigned char ret;
- int loop = HARDRETRY;
-
- do
- {
- ret = INB (port + DSP_STATUS);
- /*
- * DSP ready to receive data if bit 7 of ret == 0
- */
- if (!(ret & 0x80))
- {
- OUTB (cmd, port + DSP_COMMAND);
- return 0;
- }
- }
- while (loop--);
-
- printk ("[aedsp16] DSP Command (0x%x) timeout.\n", cmd);
- return -1;
-}
-
-int
-InitMSS (int port)
-{
-
- tenmillisec ();
-
- if (WriteDSPCommand (port, CMD6))
- {
- printk ("[aedsp16] CMD 0x%x: failed!\n", CMD6);
- return -1;
- }
-
- tenmillisec ();
-
- return 0;
-}
-
-static int
-SetUpBoard (int port)
-{
- int loop = RETRY;
-
- do
- {
- if (WriteDSPCommand (portbase, CMD3))
- {
- printk ("[aedsp16] CMD 0x%x: failed!\n", CMD3);
- return -1;
- }
-
- tenmillisec ();
-
- }
- while (WaitForDataAvail (port) && loop--);
-
-#if defined(THIS_SHOULD_GO_AWAY)
- if (CheckDSPOkay (port))
- {
- printk ("[aedsp16] CheckDSPOkay: failed\n");
- return -1;
- }
-#else
- if (ReadData (port) == -1)
- {
- printk ("[aedsp16] ReadData after CMD 0x%x: failed\n", CMD3);
- return -1;
- }
-#endif
-
- if (WriteDSPCommand (portbase, CMD4))
- {
- printk ("[aedsp16] CMD 0x%x: failed!\n", CMD4);
- return -1;
- }
-
- if (WriteDSPCommand (portbase, CMD5))
- {
- printk ("[aedsp16] CMD 0x%x: failed!\n", CMD5);
- return -1;
- }
-
- if (WriteDSPCommand (portbase, oredparams))
- {
- printk ("[aedsp16] Initialization of (M)IRQ and DMA: failed!\n");
- return -1;
- }
- return 0;
-}
-
-static int
-GetCardVersion (int port)
-{
- int len = 0;
- int ret;
- int ver[3];
-
- do
- {
- if ((ret = ReadData (port)) == -1)
- return -1;
- /*
- * We alredy know how many int are stored (2), so we know when the
- * string is finished.
- */
- ver[len++] = ret;
- }
- while (len < CARDVERLEN);
- sprintf (AudioExcelVersion, "%d.%d", ver[0], ver[1]);
- return 0;
-}
-
-static int
-GetCardName (int port)
-{
- int len = 0;
- int ret;
-
- do
- {
- if ((ret = ReadData (port)) == -1)
- /*
- * If no more data availabe, return to the caller, no error if len>0.
- * We have no other way to know when the string is finished.
- */
- return (len ? 0 : -1);
-
- AudioExcelName[len++] = ret;
-
- }
- while (len < CARDNAMELEN);
- return 0;
-}
-
-static void
-InitializeHardParams (void)
-{
-
- memset (AudioExcelName, 0, CARDNAMELEN + 1);
- memset (AudioExcelVersion, 0, CARDVERLEN + 1);
-
- for (gc = 0; orIRQ[gc].or; gc++)
- if (orIRQ[gc].val == irq)
- oredparams |= orIRQ[gc].or;
-
- for (gc = 0; orMIRQ[gc].or; gc++)
- if (orMIRQ[gc].or == mirq)
- oredparams |= orMIRQ[gc].or;
-
- for (gc = 0; orDMA[gc].or; gc++)
- if (orDMA[gc].val == dma)
- oredparams |= orDMA[gc].or;
-}
-
-static int
-InitAEDSP16 (int which)
-{
- static char *InitName = NULL;
-
- InitializeHardParams ();
-
- if (ResetBoard (portbase))
- {
- printk ("[aedsp16] ResetBoard: failed!\n");
- return -1;
- }
-
-#if defined(THIS_SHOULD_GO_AWAY)
- if (CheckDSPOkay (portbase))
- {
- printk ("[aedsp16] CheckDSPOkay: failed!\n");
- return -1;
- }
-#endif
-
- if (WriteDSPCommand (portbase, CMD1))
- {
- printk ("[aedsp16] CMD 0x%x: failed!\n", CMD1);
- return -1;
- }
-
- if (GetCardName (portbase))
- {
- printk ("[aedsp16] GetCardName: failed!\n");
- return -1;
- }
-
- /*
- * My AEDSP16 card return SC-6000 in AudioExcelName, so
- * if we have something different, we have to be warned.
- */
- if (strcmp ("SC-6000", AudioExcelName))
- printk ("[aedsp16] Warning: non SC-6000 audio card!\n");
-
- if (WriteDSPCommand (portbase, CMD2))
- {
- printk ("[aedsp16] CMD 0x%x: failed!\n", CMD2);
- return -1;
- }
-
- if (GetCardVersion (portbase))
- {
- printk ("[aedsp16] GetCardVersion: failed!\n");
- return -1;
- }
-
- if (SetUpBoard (portbase))
- {
- printk ("[aedsp16] SetUpBoard: failed!\n");
- return -1;
- }
-
- if (which == INIT_MSS)
- {
- if (InitMSS (portbase))
- {
- printk ("[aedsp16] Can't initialize Microsoft Sound System mode.\n");
- return -1;
- }
- }
-
- /*
- * If we are resetting, do not print any message because we may be
- * in playing and we do not want lost too much time.
- */
- if (!(which & RESET_DSP16))
- {
- if (which & INIT_MPU401)
- InitName = "MPU401";
- else if (which & INIT_SBPRO)
- InitName = "SBPro";
- else if (which & INIT_MSS)
- InitName = "MSS";
- else
- InitName = "None";
-
- printk ("Audio Excel DSP 16 init v%s (%s %s) [%s]\n",
- VERSION, AudioExcelName,
- AudioExcelVersion, InitName);
- }
-
- tenmillisec ();
-
- return 0;
-}
-
-#if defined(AEDSP16_SBPRO)
-
-int
-InitAEDSP16_SBPRO (struct address_info *hw_config)
-{
- /*
- * If the card is alredy init'ed MSS, we can not init it to SBPRO too
- * because the board can not emulate simultaneously MSS and SBPRO.
- */
- if (ae_init & INIT_MSS)
- return -1;
- if (ae_init & INIT_SBPRO)
- return 0;
-
- /*
- * For now we will leave this
- * code included only when INCLUDE_AEDSP16 is configured in, but it should
- * be better include it every time.
- */
- if (!(ae_init & INIT_MPU401))
- {
- if (check_region (hw_config->io_base, 0x0f))
- {
- printk ("AEDSP16/SBPRO I/O port region is alredy in use.\n");
- return -1;
- }
- }
-
- /*
- * Set up the internal hardware parameters, to let the driver reach
- * the Sound Card.
- */
- portbase = hw_config->io_base;
- irq = hw_config->irq;
- dma = hw_config->dma;
- if (InitAEDSP16 (INIT_SBPRO))
- return -1;
-
- if (!(ae_init & INIT_MPU401))
- request_region (hw_config->io_base, 0x0f, "aedsp16 (sbpro)");
-
- ae_init |= INIT_SBPRO;
- return 0;
-}
-
-#endif /* AEDSP16_SBPRO */
-
-#if defined(AEDSP16_MSS)
-
-int
-InitAEDSP16_MSS (struct address_info *hw_config)
-{
- /*
- * If the card is alredy init'ed SBPRO, we can not init it to MSS too
- * because the board can not emulate simultaneously MSS and SBPRO.
- */
- if (ae_init & INIT_SBPRO)
- return -1;
- if (ae_init & INIT_MSS)
- return 0;
-
- /*
- * For now we will leave this
- * code included only when INCLUDE_AEDSP16 is configured in, but it should
- * be better include it every time.
- */
- if (check_region (hw_config->io_base, 0x08))
- {
- printk ("MSS I/O port region is alredy in use.\n");
- return -1;
- }
-
- /*
- * We must allocate the AEDSP16 region too because these are the I/O ports
- * to access card's control registers.
- */
- if (!(ae_init & INIT_MPU401))
- {
- if (check_region (AEDSP16_BASE, 0x0f))
- {
- printk ("AEDSP16 I/O port region is alredy in use.\n");
- return -1;
- }
- }
-
-
- /*
- * If we are configuring the card for MSS, the portbase for card configuration
- * is the default one (0x220 unless you have changed the factory default
- * with board switches), so no need to modify the portbase variable.
- * The default is AEDSP16_BASE, that is the right value.
- */
- irq = hw_config->irq;
- dma = hw_config->dma;
- if (InitAEDSP16 (INIT_MSS))
- return -1;
-
- request_region (hw_config->io_base, 0x08, "aedsp16 (mss)");
-
- if (!(ae_init & INIT_MPU401))
- request_region (AEDSP16_BASE, 0x0f, "aedsp16 (sbpro)");
-
- ae_init |= INIT_MSS;
- return 0;
-}
-
-#endif /* AEDSP16_MSS */
-
-#if defined(AEDSP16_MPU401)
-
-int
-InitAEDSP16_MPU401 (struct address_info *hw_config)
-{
- if (ae_init & INIT_MPU401)
- return 0;
-
- /*
- * For now we will leave this
- * code included only when INCLUDE_AEDSP16 is configured in, but it should
- * be better include it every time.
- */
- if (check_region (hw_config->io_base, 0x02))
- {
- printk ("SB I/O port region is alredy in use.\n");
- return -1;
- }
-
- /*
- * We must allocate the AEDSP16 region too because these are the I/O ports
- * to access card's control registers.
- */
- if (!(ae_init & (INIT_MSS | INIT_SBPRO)))
- {
- if (check_region (AEDSP16_BASE, 0x0f))
- {
- printk ("AEDSP16 I/O port region is alredy in use.\n");
- return -1;
- }
- }
-
- /*
- * If mpu401, the irq and dma are not important, do not touch it
- * because we may use the default if sbpro is not yet configured,
- * we may use the sbpro ones if configured, and nothing wrong
- * should happen.
- *
- * The mirq default is 0, but once set it to non-0 value, we should
- * not touch it anymore (unless I write an ioctl to do it, of course).
- */
- mirq = hw_config->irq;
- if (InitAEDSP16 (INIT_MPU401))
- return -1;
-
- request_region (hw_config->io_base, 0x02, "aedsp16 (mpu401)");
-
- if (!(ae_init & (INIT_MSS | INIT_SBPRO)))
- request_region (AEDSP16_BASE, 0x0f, "aedsp16 (sbpro)");
-
- ae_init |= INIT_MPU401;
- return 0;
-}
-
-#endif /* AEDSP16_MPU401 */
-
-#if 0 /* Leave it out for now. We are not using this portion of code. */
-
-/*
- * Entry point for a reset function.
- * May be I will write the infamous ioctl :)
- */
-int
-ResetAEDSP16 (void)
-{
-#if defined(AEDSP16_DEBUG)
- printk ("[aedsp16] ResetAEDSP16 called.\n");
-#endif
- return InitAEDSP16 (RESET_DSP16);
-}
-
-#endif /* 0 */
-
-#endif /* !EXCLUDE_AEDSP16 */
diff --git a/sys/i386/isa/sound/audio.c b/sys/i386/isa/sound/audio.c
index d5a4acce44e3..a48524800d40 100644
--- a/sys/i386/isa/sound/audio.c
+++ b/sys/i386/isa/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,27 +24,30 @@
* 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"
+#include <i386/isa/sound/sound_config.h>
-#ifdef CONFIGURE_SOUNDCARD
-#ifndef EXCLUDE_AUDIO
+#ifdef CONFIG_AUDIO
-#include "ulaw.h"
+#include <i386/isa/sound/ulaw.h>
+#include <i386/isa/sound/coproc.h>
#define ON 1
#define OFF 0
+int
+DMAbuf_poll(int dev, struct fileinfo * file, int events, select_table * wait);
-static int wr_buff_no[MAX_AUDIO_DEV]; /*
- * != -1, if there is
- * a incomplete output
- * block in the queue.
- */
+int
+audio_poll(int dev, struct fileinfo * file, int events, select_table * wait);
+
+static int wr_buff_no[MAX_AUDIO_DEV];
+ /* != -1, if there is a incomplete output block in the queue. */
static int wr_buff_size[MAX_AUDIO_DEV], wr_buff_ptr[MAX_AUDIO_DEV];
static int audio_mode[MAX_AUDIO_DEV];
+static int dev_nblock[MAX_AUDIO_DEV]; /* 1 if in noblocking mode */
#define AM_NONE 0
#define AM_WRITE 1
@@ -54,371 +57,413 @@ static char *wr_dma_buf[MAX_AUDIO_DEV];
static int audio_format[MAX_AUDIO_DEV];
static int local_conversion[MAX_AUDIO_DEV];
+#if defined(NO_INLINE_ASM) || !defined(i386)
+static void
+translate_bytes(const u_char *table, u_char *buff, int n);
+
+#else
+extern inline void
+translate_bytes(const void *table, void *buff, int n);
+#endif
+
static int
-set_format (int dev, int fmt)
+set_format(int dev, int fmt)
{
- if (fmt != AFMT_QUERY)
- {
+ if (fmt != AFMT_QUERY) {
- local_conversion[dev] = 0;
+ local_conversion[dev] = 0;
- if (!(audio_devs[dev]->format_mask & fmt)) /* Not supported */
- if (fmt == AFMT_MU_LAW)
- {
- fmt = AFMT_U8;
- local_conversion[dev] = AFMT_MU_LAW;
- }
- else
- fmt = AFMT_U8; /* This is always supported */
+ if (!(audio_devs[dev]->format_mask & fmt)) /* Not supported */
+ if (fmt == AFMT_MU_LAW) {
+ fmt = AFMT_U8;
+ local_conversion[dev] = AFMT_MU_LAW;
+ } else
+ fmt = AFMT_U8; /* This is always supported */
- audio_format[dev] = DMAbuf_ioctl (dev, SNDCTL_DSP_SETFMT, fmt, 1);
+ audio_format[dev] = DMAbuf_ioctl(dev, SNDCTL_DSP_SETFMT,
+ (ioctl_arg) fmt, 1);
}
+ if (local_conversion[dev]) /* This shadows the HW format */
+ return local_conversion[dev];
- if (local_conversion[dev]) /* This shadows the HW format */
- return local_conversion[dev];
-
- return audio_format[dev];
+ return audio_format[dev];
}
int
-audio_open (int dev, struct fileinfo *file)
+audio_open(int dev, struct fileinfo * file)
{
- int ret;
- int bits;
- int dev_type = dev & 0x0f;
- int mode = file->mode & O_ACCMODE;
+ int ret;
+ int bits;
+ int dev_type = dev & 0x0f;
+ int mode = file->mode & O_ACCMODE;
- dev = dev >> 4;
+ dev = dev >> 4;
- if (dev_type == SND_DEV_DSP16)
- bits = 16;
- else
- bits = 8;
+ bits = (dev_type == SND_DEV_DSP16) ? 16 : 8 ;
- if ((ret = DMAbuf_open (dev, mode)) < 0)
- return ret;
+ if ((ret = DMAbuf_open(dev, mode)) < 0)
+ return ret;
- local_conversion[dev] = 0;
+ if (audio_devs[dev]->coproc)
+ if ((ret = audio_devs[dev]->coproc->
+ open(audio_devs[dev]->coproc->devc, COPR_PCM)) < 0) {
+ audio_release(dev, file);
+ printf("Sound: Can't access coprocessor device\n");
- if (DMAbuf_ioctl (dev, SNDCTL_DSP_SETFMT, bits, 1) != bits)
- {
- audio_release (dev, file);
- return RET_ERROR (ENXIO);
- }
+ return ret;
+ }
+ local_conversion[dev] = 0;
- if (dev_type == SND_DEV_AUDIO)
- {
- set_format (dev, AFMT_MU_LAW);
+ if (DMAbuf_ioctl(dev, SNDCTL_DSP_SETFMT, (ioctl_arg) bits, 1) != bits) {
+ audio_release(dev, file);
+ return -(ENXIO);
}
- else
- set_format (dev, bits);
- wr_buff_no[dev] = -1;
- audio_mode[dev] = AM_NONE;
+ set_format(dev, (dev_type == SND_DEV_AUDIO) ? AFMT_MU_LAW : bits ) ;
+
+ wr_buff_no[dev] = -1;
+ audio_mode[dev] = AM_NONE;
+ wr_buff_size[dev] = wr_buff_ptr[dev] = 0;
+ dev_nblock[dev] = 0;
- return ret;
+ return ret;
}
void
-audio_release (int dev, struct fileinfo *file)
+audio_release(int dev, struct fileinfo * file)
{
- int mode;
+ int mode;
- dev = dev >> 4;
- mode = file->mode & O_ACCMODE;
+ dev = dev >> 4;
+ mode = file->mode & O_ACCMODE;
- if (wr_buff_no[dev] >= 0)
- {
- DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev]);
-
- wr_buff_no[dev] = -1;
+ if (wr_buff_no[dev] >= 0) {
+ DMAbuf_start_output(dev, wr_buff_no[dev], wr_buff_ptr[dev]);
+ wr_buff_no[dev] = -1;
}
+ if (audio_devs[dev]->coproc)
+ audio_devs[dev]->coproc->close(audio_devs[dev]->coproc->devc,COPR_PCM);
+ DMAbuf_release(dev, mode);
+ audio_devs[dev]->dmap_out->mapping_flags &= ~DMA_MAP_MAPPED ;
- DMAbuf_release (dev, mode);
}
-#ifdef NO_INLINE_ASM
+#if defined(NO_INLINE_ASM) || !defined(i386)
static void
-translate_bytes (const unsigned char *table, unsigned char *buff, unsigned long n)
+translate_bytes(const u_char *table, u_char *buff, int n)
{
- unsigned long i;
+ u_long i;
+
+ if (n <= 0)
+ return;
- for (i = 0; i < n; ++i)
- buff[i] = table[buff[i]];
+ for (i = 0; i < n; ++i)
+ buff[i] = table[buff[i]];
}
#else
extern inline void
-translate_bytes (const void *table, void *buff, unsigned long n)
+translate_bytes(const void *table, void *buff, int n)
{
- __asm__ ("cld\n"
- "1:\tlodsb\n\t"
- "xlatb\n\t"
- "stosb\n\t"
- "loop 1b\n\t":
- :"b" ((long) table), "c" (n), "D" ((long) buff), "S" ((long) buff)
- :"bx", "cx", "di", "si", "ax");
+ if (n > 0) {
+ __asm__("cld\n"
+ "1:\tlodsb\n\t"
+ "xlatb\n\t"
+ "stosb\n\t"
+ "loop 1b\n\t":
+ :"b"((long) table), "c"(n), "D"((long) buff), "S"((long) buff)
+ :"bx", "cx", "di", "si", "ax");
+ }
}
#endif
int
-audio_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
+audio_write(int dev, struct fileinfo * file, snd_rw_buf * buf, int count)
{
- int c, p, l;
- int err;
+ int c, p, l;
+ int err;
- dev = dev >> 4;
+ dev = dev >> 4;
- p = 0;
- c = count;
+ p = 0;
+ c = count;
- if (audio_mode[dev] == AM_READ) /*
- * Direction changed
- */
- {
- wr_buff_no[dev] = -1;
+ if ((audio_mode[dev] & AM_READ) &&
+ !(audio_devs[dev]->flags & DMA_DUPLEX)) { /* Direction change */
+ wr_buff_no[dev] = -1;
+ }
+ if (audio_devs[dev]->flags & DMA_DUPLEX)
+ audio_mode[dev] |= AM_WRITE;
+ else
+ audio_mode[dev] = AM_WRITE;
+
+ if (!count) { /* Flush output */
+ if (wr_buff_no[dev] >= 0) {
+ DMAbuf_start_output(dev, wr_buff_no[dev], wr_buff_ptr[dev]);
+ wr_buff_no[dev] = -1;
+ }
+ return 0;
}
+ while (c) { /* Perform output blocking */
+ if (wr_buff_no[dev] < 0) {
+ /* There is no incomplete buffers */
+ if ((wr_buff_no[dev] = DMAbuf_getwrbuffer(dev,
+ &wr_dma_buf[dev], &wr_buff_size[dev],
+ dev_nblock[dev])) < 0) {
+ /* Handle nonblocking mode */
+ if (dev_nblock[dev] && wr_buff_no[dev] == -(EAGAIN))
+ return p; /* No more space. Return # of accepted bytes */
+ return wr_buff_no[dev];
+ }
+ wr_buff_ptr[dev] = 0;
+ }
+ l = c;
+ if (l > (wr_buff_size[dev] - wr_buff_ptr[dev]))
+ l = (wr_buff_size[dev] - wr_buff_ptr[dev]);
- audio_mode[dev] = AM_WRITE;
+ if (!audio_devs[dev]->copy_from_user) { /* No device specific
+ * copy routine */
- if (!count) /*
- * Flush output
- */
- {
- if (wr_buff_no[dev] >= 0)
- {
- DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev]);
+ if (uiomove(&wr_dma_buf[dev][wr_buff_ptr[dev]], l, buf)) {
+ printf("sb: Bad copyin()!\n");
+ };
+ } else
+ audio_devs[dev]->copy_from_user(dev,
+ wr_dma_buf[dev], wr_buff_ptr[dev], buf, p, l);
- wr_buff_no[dev] = -1;
- }
- return 0;
- }
- while (c)
- { /*
- * Perform output blocking
- */
- if (wr_buff_no[dev] < 0) /*
- * There is no incomplete buffers
- */
- {
- if ((wr_buff_no[dev] = DMAbuf_getwrbuffer (dev, &wr_dma_buf[dev], &wr_buff_size[dev])) < 0)
- {
- return wr_buff_no[dev];
+ /*
+ * Insert local processing here
+ */
+
+ if (local_conversion[dev] == AFMT_MU_LAW) {
+ translate_bytes(ulaw_dsp,
+ (u_char *) &wr_dma_buf[dev][wr_buff_ptr[dev]], l);
+ }
+ c -= l;
+ p += l;
+ wr_buff_ptr[dev] += l;
+
+ if (wr_buff_ptr[dev] >= wr_buff_size[dev]) {
+ if ((err = DMAbuf_start_output(dev, wr_buff_no[dev],
+ wr_buff_ptr[dev])) < 0) {
+ return err;
}
- wr_buff_ptr[dev] = 0;
+ wr_buff_no[dev] = -1;
}
+ }
- l = c;
- if (l > (wr_buff_size[dev] - wr_buff_ptr[dev]))
- l = (wr_buff_size[dev] - wr_buff_ptr[dev]);
+ return count;
+}
- if (!audio_devs[dev]->copy_from_user)
- { /*
- * No device specific copy routine
- */
- COPY_FROM_USER (&wr_dma_buf[dev][wr_buff_ptr[dev]], buf, p, l);
+int
+audio_read(int dev, struct fileinfo * file, snd_rw_buf * buf, int count)
+{
+ int c, p, l;
+ char *dmabuf;
+ int buff_no;
+
+ dev = dev >> 4;
+ p = 0;
+ c = count;
+ if ((audio_mode[dev] & AM_WRITE) &&
+ !(audio_devs[dev]->flags & DMA_DUPLEX)) {
+ if (wr_buff_no[dev] >= 0) {
+ DMAbuf_start_output(dev, wr_buff_no[dev], wr_buff_ptr[dev]);
+
+ if (!(audio_devs[dev]->flags & DMA_DUPLEX))
+ wr_buff_no[dev] = -1;
}
- else
- audio_devs[dev]->copy_from_user (dev,
- wr_dma_buf[dev], wr_buff_ptr[dev], buf, p, l);
-
-
- /*
- * Insert local processing here
- */
-
- if (local_conversion[dev] == AFMT_MU_LAW)
- {
-#ifdef linux
- /*
- * This just allows interrupts while the conversion is running
- */
- __asm__ ("sti");
-#endif
- translate_bytes (ulaw_dsp, (unsigned char *) &wr_dma_buf[dev][wr_buff_ptr[dev]], l);
+ }
+ if (audio_devs[dev]->flags & DMA_DUPLEX)
+ audio_mode[dev] |= AM_READ;
+ else
+ audio_mode[dev] = AM_READ;
+
+ while (c) {
+ if ((buff_no = DMAbuf_getrdbuffer(dev, &dmabuf, &l,
+ dev_nblock[dev])) < 0) {
+ /*
+ * Nonblocking mode handling. Return current # of bytes
+ */
+
+ if (dev_nblock[dev] && buff_no == -(EAGAIN))
+ return p;
+
+ return buff_no;
}
+ if (l > c)
+ l = c;
- c -= l;
- p += l;
- wr_buff_ptr[dev] += l;
+ /*
+ * Insert any local processing here.
+ */
- if (wr_buff_ptr[dev] >= wr_buff_size[dev])
- {
- if ((err = DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev])) < 0)
- {
- return err;
- }
-
- wr_buff_no[dev] = -1;
+ if (local_conversion[dev] == AFMT_MU_LAW) {
+ translate_bytes(dsp_ulaw, (u_char *) dmabuf, l);
}
+ if (uiomove(dmabuf, l, buf)) {
+ printf("sb: Bad copyout()!\n");
+ };
- }
+ DMAbuf_rmchars(dev, buff_no, l);
- return count;
+ p += l;
+ c -= l;
+ }
+ return count - c;
}
int
-audio_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
+audio_ioctl(int dev, struct fileinfo * file, u_int cmd, ioctl_arg arg)
{
- int c, p, l;
- char *dmabuf;
- int buff_no;
+ dev = dev >> 4;
+ if (((cmd >> 8) & 0xff) == 'C') {
+ if (audio_devs[dev]->coproc) /* Coprocessor ioctl */
+ return audio_devs[dev]->coproc->ioctl(audio_devs[dev]->coproc->devc, cmd, arg, 0);
+ else
+ printf("/dev/dsp%d: No coprocessor for this device\n", dev);
- dev = dev >> 4;
- p = 0;
- c = count;
+ return -(ENXIO);
+ } else
+ switch (cmd) {
- if (audio_mode[dev] == AM_WRITE)
- {
- if (wr_buff_no[dev] >= 0)
- {
- DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev]);
+ case SNDCTL_DSP_SYNC:
+ if (wr_buff_no[dev] >= 0) {
+ DMAbuf_start_output(dev, wr_buff_no[dev], wr_buff_ptr[dev]);
+ wr_buff_no[dev] = -1;
+ }
+ return DMAbuf_ioctl(dev, cmd, arg, 0);
+ break;
- wr_buff_no[dev] = -1;
- }
- }
+ case SNDCTL_DSP_POST:
+ if (wr_buff_no[dev] >= 0) {
+ DMAbuf_start_output(dev, wr_buff_no[dev], wr_buff_ptr[dev]);
+ wr_buff_no[dev] = -1;
+ }
+ return 0;
+ break;
- audio_mode[dev] = AM_READ;
+ case SNDCTL_DSP_RESET:
+ wr_buff_no[dev] = -1;
+ audio_mode[dev] = AM_NONE;
+ return DMAbuf_ioctl(dev, cmd, arg, 0);
+ break;
- while (c)
- {
- if ((buff_no = DMAbuf_getrdbuffer (dev, &dmabuf, &l)) < 0)
- return buff_no;
+ case SNDCTL_DSP_GETFMTS:
+ return *(int *) arg = audio_devs[dev]->format_mask;
+ break;
- if (l > c)
- l = c;
+ case SNDCTL_DSP_SETFMT:
+ return *(int *) arg = set_format(dev, (*(int *) arg));
- /*
- * Insert any local processing here.
- */
-
- if (local_conversion[dev] == AFMT_MU_LAW)
- {
-#ifdef linux
- /*
- * This just allows interrupts while the conversion is running
- */
- __asm__ ("sti");
-#endif
+ case SNDCTL_DSP_GETISPACE:
+ if ((audio_mode[dev] & AM_WRITE) &&
+ !(audio_devs[dev]->flags & DMA_DUPLEX))
+ return -(EBUSY);
- translate_bytes (dsp_ulaw, (unsigned char *) dmabuf, l);
- }
+ else {
+ audio_buf_info info;
+ int err = DMAbuf_ioctl(dev, cmd, (ioctl_arg) & info, 1);
- COPY_TO_USER (buf, p, dmabuf, l);
+ if (err < 0)
+ return err;
- DMAbuf_rmchars (dev, buff_no, l);
+ bcopy((char *) &info, &(((char *) arg)[0]), sizeof(info));
+ return 0;
+ }
- p += l;
- c -= l;
- }
+ case SNDCTL_DSP_GETOSPACE:
+ if ((audio_mode[dev] & AM_READ) &&
+ !(audio_devs[dev]->flags & DMA_DUPLEX))
+ return -(EBUSY);
+ else {
+ audio_buf_info info;
+ int err = DMAbuf_ioctl(dev, cmd, (ioctl_arg) & info, 1);
- return count - c;
-}
+ if (err < 0)
+ return err;
-int
-audio_ioctl (int dev, struct fileinfo *file,
- unsigned int cmd, unsigned int arg)
-{
+ if (wr_buff_no[dev] != -1)
+ info.bytes += wr_buff_size[dev] - wr_buff_ptr[dev];
- dev = dev >> 4;
+ bcopy((char *) &info, &(((char *) arg)[0]), sizeof(info));
+ return 0;
+ }
- switch (cmd)
- {
- case SNDCTL_DSP_SYNC:
- if (wr_buff_no[dev] >= 0)
- {
- DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev]);
+ case SNDCTL_DSP_NONBLOCK:
+ dev_nblock[dev] = 1;
+ return 0;
+ break;
- wr_buff_no[dev] = -1;
- }
- return DMAbuf_ioctl (dev, cmd, arg, 0);
- break;
+ case SNDCTL_DSP_GETCAPS:
+ {
+ int info = 1; /* Revision level of this ioctl() */
- case SNDCTL_DSP_POST:
- if (wr_buff_no[dev] >= 0)
- {
- DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev]);
+ if (audio_devs[dev]->flags & DMA_DUPLEX)
+ info |= DSP_CAP_DUPLEX;
- wr_buff_no[dev] = -1;
- }
- return 0;
- break;
+ if (audio_devs[dev]->coproc)
+ info |= DSP_CAP_COPROC;
- case SNDCTL_DSP_RESET:
- wr_buff_no[dev] = -1;
- return DMAbuf_ioctl (dev, cmd, arg, 0);
- break;
+ if (audio_devs[dev]->local_qlen) /* Dev. has hidden buffs */
+ info |= DSP_CAP_BATCH;
- case SNDCTL_DSP_GETFMTS:
- return IOCTL_OUT (arg, audio_devs[dev]->format_mask);
- break;
+ if (audio_devs[dev]->trigger) /* Supports SETTRIGGER */
+ info |= DSP_CAP_TRIGGER;
- case SNDCTL_DSP_SETFMT:
- return IOCTL_OUT (arg, set_format (dev, IOCTL_IN (arg)));
+ info |= DSP_CAP_MMAP;
+ bcopy((char *) &info, &(((char *) arg)[0]), sizeof(info));
+ return 0;
+ }
+ break;
- default:
- return DMAbuf_ioctl (dev, cmd, arg, 0);
- break;
- }
-}
-long
-audio_init (long mem_start)
-{
- /*
- * NOTE! This routine could be called several times during boot.
- */
- return mem_start;
+ case FIOASYNC:
+ return *(int *) arg = 1;
+
+ case FIONBIO:
+ return *(int *) arg = 1;
+
+ default:
+ return DMAbuf_ioctl(dev, cmd, arg, 0);
+ }
}
-#else
+#ifdef ALLOW_POLL
/*
- * Stub versions
+ * XXX should we use spltty() in the select calls ? - lr970714
+ *
*/
int
-audio_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
+audio_poll(int dev, struct fileinfo * file, int events, select_table * wait)
{
- return RET_ERROR (EIO);
-}
+ dev = dev >> 4;
-int
-audio_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
-{
- return RET_ERROR (EIO);
-}
+ if (events & (POLLOUT | POLLWRNORM)) {
+ if ((audio_mode[dev] & AM_WRITE) &&
+ !(audio_devs[dev]->flags & DMA_DUPLEX))
+ return 0; /* Not recording */
-int
-audio_open (int dev, struct fileinfo *file)
-{
- 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)
-{
- return RET_ERROR (EIO);
-}
+ return (DMAbuf_poll(dev, file, events, wait));
+ }
-int
-audio_lseek (int dev, struct fileinfo *file, off_t offset, int orig)
-{
- return RET_ERROR (EIO);
-}
+ if (events & (POLLIN | POLLRDNORM)) {
+ if ((audio_mode[dev] & AM_READ) &&
+ !(audio_devs[dev]->flags & DMA_DUPLEX))
+ return 0; /* Wrong direction */
-long
-audio_init (long mem_start)
-{
- return mem_start;
-}
+ if (wr_buff_no[dev] != -1)
+ return 1; /* There is space in the current buffer */
-#endif
+ return ( DMAbuf_poll(dev, file, events, wait) );
+
+ }
+ return 0;
+}
+#endif /* ALLOW_POLL */
#endif
diff --git a/sys/i386/isa/sound/awe_wave.c b/sys/i386/isa/sound/awe_wave.c
index 47818165a9e4..dec20b2e41bc 100644
--- a/sys/i386/isa/sound/awe_wave.c
+++ b/sys/i386/isa/sound/awe_wave.c
@@ -31,8 +31,8 @@
/* if you're using obsolete VoxWare 3.0.x on Linux 1.2.x (or FreeBSD),
* uncomment the following line
*/
-#define AWE_OBSOLETE_VOXWARE
+#define AWE_OBSOLETE_VOXWARE
#ifdef AWE_OBSOLETE_VOXWARE
@@ -88,9 +88,6 @@
#include <i386/isa/sound/awe_voice.h>
#ifdef AWE_OBSOLETE_VOXWARE
-#ifdef __FreeBSD__
-#define SEQUENCER_C
-#endif
#include <i386/isa/sound/tuning.h>
#else
#include "../tuning.h"
@@ -333,11 +330,25 @@ static void awe_set_reverb_mode(int mode);
#define awe_request_region() /* nothing */
#define awe_release_region() /* nothing */
+#ifdef __FreeBSD__
+# ifndef PERMANENT_MALLOC
+# define PERMANENT_MALLOC(typecast, mem_ptr, size) \
+ {mem_ptr = (typecast)malloc(size, M_DEVBUF, M_NOWAIT); \
+ if (!mem_ptr)panic("SOUND: Cannot allocate memory\n");}
+# endif
+# ifndef printk
+# define printk printf
+# endif
+# ifndef RET_ERROR
+# define RET_ERROR(err) -(err)
+# endif
+#endif
+
#else /* AWE_OBSOLETE_VOXWARE */
/* the following macros are osbolete */
-#define PERMANENT_MALLOC(type,var,size,memptr) \
+#define PERMANENT_MALLOC(type,var,size) \
var = (type)(sound_mem_blocks[sound_nblocks++] = vmalloc(size))
#define RET_ERROR(err) -err
@@ -431,8 +442,8 @@ static struct synth_operations awe_operations =
* attach / unload interface
*================================================================*/
-#ifdef AWE_OBSOLETE_VOXWARE
-long attach_awe_obsolete(long mem_start, struct address_info *hw_config)
+#if defined(AWE_OBSOLETE_VOXWARE) || defined(__FreeBSD__)
+void attach_awe_obsolete(struct address_info *hw_config)
#else
int attach_awe(void)
#endif
@@ -440,23 +451,23 @@ int attach_awe(void)
/* check presence of AWE32 card */
if (! awe_detect()) {
printk("AWE32: not detected\n");
- return 0;
+ return ;
}
/* check AWE32 ports are available */
if (awe_check_port()) {
printk("AWE32: I/O area already used.\n");
- return 0;
+ return ;
}
/* allocate sample tables */
PERMANENT_MALLOC(awe_sample_info *, samples,
- AWE_MAX_SAMPLES * sizeof(awe_sample_info), mem_start);
+ AWE_MAX_SAMPLES * sizeof(awe_sample_info) );
PERMANENT_MALLOC(awe_voice_list *, infos,
- AWE_MAX_INFOS * sizeof(awe_voice_list), mem_start);
+ AWE_MAX_INFOS * sizeof(awe_voice_list) );
if (samples == NULL || infos == NULL) {
printk("AWE32: can't allocate sample tables\n");
- return 0;
+ return ;
}
if (num_synths >= MAX_SYNTH_DEV)
@@ -488,29 +499,19 @@ int attach_awe(void)
awe_present = 1;
#ifdef AWE_OBSOLETE_VOXWARE
- return mem_start;
+ return ;
#else
return 1;
#endif
}
-
-void unload_awe(void)
-{
- if (awe_present) {
- awe_reset_samples();
- awe_release_region();
- }
-}
-
-
#ifdef AWE_OBSOLETE_VOXWARE
-int probe_awe_obsolete(struct address_info *hw_config)
+int
+probe_awe_obsolete(struct address_info *hw_config)
{
return 1;
/*return awe_detect();*/
}
-
#endif
/*================================================================
diff --git a/sys/i386/isa/sound/dev_table.c b/sys/i386/isa/sound/dev_table.c
index 1eb57bbb08c1..42e5197b2c46 100644
--- a/sys/i386/isa/sound/dev_table.c
+++ b/sys/i386/isa/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,246 +24,280 @@
* 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_
-#include "sound_config.h"
+#include <i386/isa/sound/sound_config.h>
-#ifdef CONFIGURE_SOUNDCARD
+#if NSND > 0
+
+int sound_started = 0;
+
+int sndtable_get_cardcount(void);
+int snd_find_driver(int type);
+void sndtable_init(void);
+int sndtable_probe(int unit, struct address_info * hw_config);
+int sndtable_init_card(int unit, struct address_info * hw_config);
+int sndtable_identify_card(char *name);
+void sound_chconf(int card_type, int ioaddr, int irq, int dma);
+static void start_services(void);
+static void start_cards(void);
+struct address_info *sound_getconf(int card_type);
int
-snd_find_driver (int type)
+snd_find_driver(int type)
{
- int i, n = sizeof (sound_drivers) / sizeof (struct driver_info);
+ int i, n = num_sound_drivers;
- for (i = 0; i < (n - 1); i++)
- if (sound_drivers[i].card_type == type)
- return i;
+ for (i = 0; i < n; i++)
+ if (sound_drivers[i].card_type == type)
+ return i;
- return -1; /*
- * Not found
- */
+ return -1;
}
-long
-sndtable_init (long mem_start)
+static void
+start_services()
{
- int i, n = sizeof (snd_installed_cards) / sizeof (struct card_info);
- int drv;
-
- for (i = 0; i < (n - 1); i++)
- if (snd_installed_cards[i].enabled)
- if ((drv = snd_find_driver (snd_installed_cards[i].card_type)) == -1)
- snd_installed_cards[i].enabled = 0; /*
- * Mark as not detected
- */
- else if (sound_drivers[drv].probe (&snd_installed_cards[i].config))
- {
-#ifndef SHORT_BANNERS
- printk ("snd%d",
- snd_installed_cards[i].card_type);
+ int soundcards_installed;
+
+ if (!(soundcards_installed = sndtable_get_cardcount()))
+ return ; /* No cards detected */
+
+#ifdef CONFIG_AUDIO
+ if (num_audiodevs) /* Audio devices present */
+ DMAbuf_init();
#endif
- mem_start = sound_drivers[drv].attach (mem_start, &snd_installed_cards[i].config);
-#ifndef SHORT_BANNERS
- printk (" at 0x%x irq %d drq %d\n",
- snd_installed_cards[i].config.io_base,
- snd_installed_cards[i].config.irq,
- snd_installed_cards[i].config.dma);
+#ifdef CONFIG_MIDI
+ if (num_midis)
+ /* MIDIbuf_init(0) */;
#endif
+
+#ifdef CONFIG_SEQUENCER
+ if (num_midis + num_synths)
+ sequencer_init();
+#endif
+}
+
+static void
+start_cards()
+{
+ int drv, i, n = num_sound_cards;
+ struct card_info *ci = snd_installed_cards ;
+
+ sound_started = 1;
+ if (trace_init)
+ printf("Sound initialization started\n");
+
+ /*
+ * Check the number of cards actually defined in the table
+ */
+
+ for (i = 0; i < n && snd_installed_cards[i].card_type; i++)
+ num_sound_cards = i + 1;
+
+ for (i = 0; i < n && ci->card_type; ci++, i++)
+ if (ci->enabled) {
+ if ((drv = snd_find_driver(ci->card_type)) == -1) {
+ ci->enabled = 0; /* Mark as not detected */
+ continue;
+ }
+ ci->config.card_subtype = sound_drivers[drv].card_subtype;
+
+ if (sound_drivers[drv].probe(&(ci->config)))
+ sound_drivers[drv].attach(&(ci->config));
+ else
+ ci->enabled = 0; /* Mark as not detected */
}
- else
- snd_installed_cards[i].enabled = 0; /*
- * Mark as not detected
- */
- return mem_start;
+ if (trace_init)
+ printf("Sound initialization complete\n");
}
+void
+sndtable_init()
+{
+ start_cards();
+}
+
+/*
+ * sndtable_probe probes a specific device. unit is the voxware unit number.
+ */
+
int
-sndtable_probe (int unit, struct address_info *hw_config)
- {
- int i, n = sizeof (snd_installed_cards) / sizeof (struct card_info);
+sndtable_probe(int unit, struct address_info * hw_config)
+{
+ int i, sel = -1, n = num_sound_cards;
+ struct card_info *ci = snd_installed_cards ;
+
+ DDB(printf("-- sndtable_probe(%d)\n", unit));
+
+ /*
+ * for some reason unit 0 always succeeds ?
+ */
if (!unit)
- return TRUE;
+ return TRUE;
- for (i = 0; i < (n - 1); i++)
- if (snd_installed_cards[i].enabled)
- if (snd_installed_cards[i].card_type == unit)
- {
- int drv;
+ sound_started = 1;
- snd_installed_cards[i].config.io_base = hw_config->io_base;
- snd_installed_cards[i].config.irq = hw_config->irq;
- snd_installed_cards[i].config.dma = hw_config->dma;
- if ((drv = snd_find_driver (snd_installed_cards[i].card_type)) == -1)
- snd_installed_cards[i].enabled = 0; /*
- * Mark as not
- * detected
- */
- else if (sound_drivers[drv].probe (hw_config))
- return 1;
- snd_installed_cards[i].enabled = 0; /*
- * Mark as not detected
- */
- return 0;
- }
+ for (i=0; i<n && sel== -1 && ci->card_type; ci++, i++)
+ if ( (ci->enabled) && (ci->card_type == unit) ) {
+ /* DDB(printf("-- found card %d\n", i) ); */
+ sel = i; /* and break */
+ }
- return FALSE;
- }
+ /*
+ * not found. Creates a new entry in the table for this unit.
+ */
+ if (sel == -1 && num_sound_cards < max_sound_cards) {
+ int i;
-int
-sndtable_init_card (int unit, struct address_info *hw_config)
- {
- int i, n = sizeof (snd_installed_cards) / sizeof (struct card_info);
+ i = sel = (num_sound_cards++);
+ DDB(printf("-- installing card %d\n", i) );
- if (!unit)
- {
- if (sndtable_init (0) != 0)
- panic ("snd: Invalid memory allocation\n");
- return TRUE;
- }
-
- for (i = 0; i < (n - 1); i++)
- if (snd_installed_cards[i].card_type == unit)
- {
- int drv;
-
- snd_installed_cards[i].config.io_base = hw_config->io_base;
- snd_installed_cards[i].config.irq = hw_config->irq;
- snd_installed_cards[i].config.dma = hw_config->dma;
-
- if ((drv = snd_find_driver (snd_installed_cards[i].card_type)) == -1)
- snd_installed_cards[i].enabled = 0; /*
- * Mark as not detected
- */
- else if (sound_drivers[drv].attach (0, hw_config) != 0)
- panic ("snd#: Invalid memory allocation\n");
- return TRUE;
+ ci = &snd_installed_cards[sel] ;
+ ci->card_type = unit;
+ ci->enabled = 1;
+ }
+ /* DDB(printf("-- installed card %d\n", sel) ); */
+ if (sel != -1) {
+ int drv;
+
+ ci->config.io_base = hw_config->io_base;
+ ci->config.irq = hw_config->irq;
+ ci->config.dma = hw_config->dma;
+ ci->config.dma2 = hw_config->dma2;
+ ci->config.name = hw_config->name;
+ ci->config.always_detect = hw_config->always_detect;
+ ci->config.card_subtype = hw_config->card_subtype;
+ ci->config.osp = hw_config->osp;
+
+ if ((drv = snd_find_driver(ci->card_type)) == -1) {
+ ci->enabled = 0;
+ DDB(printf("Failed to find driver\n"));
+ return FALSE;
}
+ DDB(printf("-- Driver name '%s' probe 0x%08x\n",
+ sound_drivers[drv].name, sound_drivers[drv].probe));
- return FALSE;
- }
+ hw_config->card_subtype =
+ ci->config.card_subtype = sound_drivers[drv].card_subtype;
-int
-sndtable_get_cardcount (void)
-{
- return num_audiodevs + num_mixers + num_synths + num_midis;
+ if (sound_drivers[drv].probe(hw_config)) {
+ DDB(printf("-- Hardware probed OK\n"));
+ return TRUE;
+ }
+ DDB(printf("-- Failed to find hardware\n"));
+ ci->enabled = 0; /* mark as not detected */
+ return FALSE;
+ }
+ return FALSE;
}
-#ifdef linux
-void
-sound_setup (char *str, int *ints)
+int
+sndtable_init_card(int unit, struct address_info * hw_config)
{
- int i, n = sizeof (snd_installed_cards) / sizeof (struct card_info);
-
- /*
- * First disable all drivers
- */
+ int i, n = num_sound_cards;
+ struct card_info *ci = snd_installed_cards ;
- for (i = 0; i < n; i++)
- snd_installed_cards[i].enabled = 0;
+ DDB(printf("sndtable_init_card(%d) entered\n", unit));
- if (ints[0] == 0 || ints[1] == 0)
- return;
- /*
- * Then enable them one by time
- */
+ if (!unit) {
+ sndtable_init() ;
+ return TRUE;
+ }
+ for (i = 0; i < n && ci->card_type; ci++, i++)
+ if (ci->card_type == unit) {
+ int drv;
- for (i = 1; i <= ints[0]; i++)
- {
- int card_type, ioaddr, irq, dma, ptr, j;
- unsigned int val;
+ ci->config.io_base = hw_config->io_base;
+ ci->config.irq = hw_config->irq;
+ ci->config.dma = hw_config->dma;
+ ci->config.dma2 = hw_config->dma2;
+ ci->config.name = hw_config->name;
+ ci->config.always_detect = hw_config->always_detect;
+ ci->config.card_subtype = hw_config->card_subtype;
+ ci->config.osp = hw_config->osp;
+
+ if ((drv = snd_find_driver(ci->card_type)) == -1)
+ ci->enabled = 0; /* Mark not fnd */
+ else {
+ DDB(printf("Located card - calling attach routine\n"));
+ sound_drivers[drv].attach(hw_config) ;
+ DDB(printf("attach routine finished\n"));
+ }
+ start_services();
+ return TRUE;
+ }
+ DDB(printf("sndtable_init_card: No card defined with type=%d, num cards: %d\n",
+ unit, num_sound_cards));
+ return FALSE;
+}
- val = (unsigned int) ints[i];
+int
+sndtable_get_cardcount(void)
+{
+ return num_audiodevs + num_mixers + num_synths + num_midis;
+}
- card_type = (val & 0x0ff00000) >> 20;
+int
+sndtable_identify_card(char *name)
+{
+ int i, n = num_sound_drivers;
- if (card_type > 127)
- {
- /*
- * Add any future extensions here
- */
- return;
- }
+ if (name == NULL)
+ return 0;
- ioaddr = (val & 0x000fff00) >> 8;
- irq = (val & 0x000000f0) >> 4;
- dma = (val & 0x0000000f);
+ for (i = 0; i < n; i++)
+ if (sound_drivers[i].driver_id != NULL) {
+ char *id = sound_drivers[i].driver_id;
+ int j;
- ptr = -1;
- for (j = 0; j < n && ptr == -1; j++)
- if (snd_installed_cards[j].card_type == card_type &&
- !snd_installed_cards[j].enabled) /*
- * Not already found
- */
- ptr = j;
-
- if (ptr == -1)
- printk ("Sound: Invalid setup parameter 0x%08x\n", val);
- else
- {
- snd_installed_cards[ptr].enabled = 1;
- snd_installed_cards[ptr].config.io_base = ioaddr;
- snd_installed_cards[ptr].config.irq = irq;
- snd_installed_cards[ptr].config.dma = dma;
+ for (j = 0; j < 80 && name[j] == id[j]; j++)
+ if (id[j] == 0 && name[j] == 0) /* Match */
+ return sound_drivers[i].card_type;
}
- }
+ return 0;
}
-#else
void
-sound_chconf (int card_type, int ioaddr, int irq, int dma)
+sound_chconf(int card_type, int ioaddr, int irq, int dma)
{
- int i, n = sizeof (snd_installed_cards) / sizeof (struct card_info);
-
- int ptr, j;
-
- ptr = -1;
- for (j = 0; j < n && ptr == -1; j++)
- if (snd_installed_cards[j].card_type == card_type &&
- !snd_installed_cards[j].enabled) /*
- * Not already found
- */
- ptr = j;
-
- if (ptr != -1)
- {
- snd_installed_cards[ptr].enabled = 1;
- if (ioaddr)
- snd_installed_cards[ptr].config.io_base = ioaddr;
- if (irq)
- snd_installed_cards[ptr].config.irq = irq;
- if (dma)
- snd_installed_cards[ptr].config.dma = dma;
+ int j, ptr = -1, n = num_sound_cards;
+
+ for (j = 0; j < n && ptr == -1 && snd_installed_cards[j].card_type; j++)
+ if (snd_installed_cards[j].card_type == card_type &&
+ !snd_installed_cards[j].enabled) /* Not already found */
+ ptr = j;
+
+ if (ptr != -1) {
+ snd_installed_cards[ptr].enabled = 1;
+ if (ioaddr)
+ snd_installed_cards[ptr].config.io_base = ioaddr;
+ if (irq)
+ snd_installed_cards[ptr].config.irq = irq;
+ if (dma)
+ snd_installed_cards[ptr].config.dma = dma;
+ snd_installed_cards[ptr].config.dma2 = -1;
}
}
-#endif
struct address_info *
-sound_getconf (int card_type)
+sound_getconf(int card_type)
{
- int j, ptr;
- int n = sizeof (snd_installed_cards) / sizeof (struct card_info);
+ int j, ptr = -1, n = num_sound_cards;
- ptr = -1;
- for (j = 0; j < n && ptr == -1; j++)
- if (snd_installed_cards[j].card_type == card_type)
- ptr = j;
+ for (j = 0; j < n && ptr == -1 && snd_installed_cards[j].card_type; j++)
+ if (snd_installed_cards[j].card_type == card_type)
+ ptr = j;
- if (ptr == -1)
- return (struct address_info *) NULL;
-
- return &snd_installed_cards[ptr].config;
-}
+ if (ptr == -1)
+ return (struct address_info *) NULL;
-#else
-
-void
-sound_setup (char *str, int *ints)
-{
+ return &snd_installed_cards[ptr].config;
}
#endif
diff --git a/sys/i386/isa/sound/dev_table.h b/sys/i386/isa/sound/dev_table.h
index 12b20baf7d82..63067a4b7714 100644
--- a/sys/i386/isa/sound/dev_table.h
+++ b/sys/i386/isa/sound/dev_table.h
@@ -1,58 +1,66 @@
/*
- * dev_table.h
- *
- * Global definitions for device call tables
+ * dev_table.h
+ *
+ * Global definitions for 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
- * 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
+ * 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.
- *
-
-*/
+ *
+ */
#ifndef _DEV_TABLE_H_
#define _DEV_TABLE_H_
/*
- * NOTE! NOTE! NOTE! NOTE!
- *
- * If you modify this file, please check the dev_table.c also.
- *
- * NOTE! NOTE! NOTE! NOTE!
+ * NOTE! NOTE! NOTE! NOTE!
+ *
+ * If you modify this file, please check the dev_table.c also.
+ *
+ * NOTE! NOTE! NOTE! NOTE!
*/
+extern int sound_started;
+
struct driver_info {
- int card_type; /* From soundcard.h */
- char *name;
- long (*attach) (long mem_start, struct address_info *hw_config);
- int (*probe) (struct address_info *hw_config);
+ char *driver_id;
+ int card_subtype; /* Driver specific. Usually 0 */
+ int card_type; /* From soundcard.h */
+ char *name;
+ void (*attach) (struct address_info * hw_config);
+ int (*probe) (struct address_info * hw_config);
};
struct card_info {
- int card_type; /* Link (search key) to the driver list */
+ int card_type; /* Link (search key) to the driver list */
struct address_info config;
- int enabled;
+ int enabled;
};
+typedef struct pnp_sounddev {
+ int id;
+ void (*setup) (void *dev);
+ char *driver_name;
+} pnp_sounddev;
+
/*
* Device specific parameters (used only by dmabuf.c)
*/
@@ -63,283 +71,523 @@ struct card_info {
#define DMODE_INPUT 2
struct dma_buffparms {
- int dma_mode; /* DMODE_INPUT, DMODE_OUTPUT or DMODE_NONE */
-
- /*
- * Pointers to raw buffers
- */
+ int dma_mode; /* DMODE_INPUT, DMODE_OUTPUT or DMODE_NONE */
- char *raw_buf[DSP_BUFFCOUNT];
- unsigned long raw_buf_phys[DSP_BUFFCOUNT];
- int raw_count;
+ char *raw_buf; /* Pointers to raw buffers */
+ u_long raw_buf_phys;
- /*
- * Device state tables
- */
+ /*
+ * Device state tables
+ */
- unsigned long flags;
+ u_long flags;
#define DMA_BUSY 0x00000001
#define DMA_RESTART 0x00000002
#define DMA_ACTIVE 0x00000004
#define DMA_STARTED 0x00000008
#define DMA_ALLOC_DONE 0x00000020
- int open_mode;
+ int open_mode;
/*
* Queue parameters.
*/
- int qlen;
- int qhead;
- int qtail;
+ int qlen;
+ int qhead;
+ int qtail;
+
+ int nbufs;
+ int counts[MAX_SUB_BUFFERS];
+ int subdivision;
- int nbufs;
- int counts[MAX_SUB_BUFFERS];
- int subdivision;
- char *buf[MAX_SUB_BUFFERS];
- unsigned long buf_phys[MAX_SUB_BUFFERS];
+ int fragment_size;
+ int max_fragments;
- int fragment_size;
- int max_fragments;
+ int bytes_in_use;
- int bytes_in_use;
+ int underrun_count;
+ int byte_counter;
- int underrun_count;
+ int mapping_flags;
+#define DMA_MAP_MAPPED 0x00000001
+ char neutral_byte;
};
+/*
+ * Structure for use with various microcontrollers and DSP processors in the
+ * recent soundcards.
+ */
+typedef struct coproc_operations {
+ char name[32];
+ int (*open) (void *devc, int sub_device);
+ void (*close) (void *devc, int sub_device);
+ int (*ioctl) (void *devc, u_int cmd, ioctl_arg arg, int local);
+ void (*reset) (void *devc);
+
+ void *devc; /* Driver specific info */
+} coproc_operations;
+
struct audio_operations {
- char name[32];
- int flags;
+ char name[32];
+ int flags;
#define NOTHING_SPECIAL 0
#define NEEDS_RESTART 1
#define DMA_AUTOMODE 2
- int format_mask; /* Bitmask for supported audio formats */
- void *devc; /* Driver specific info */
- int (*open) (int dev, int mode);
- void (*close) (int dev);
- void (*output_block) (int dev, unsigned long buf,
- int count, int intrflag, int dma_restart);
- void (*start_input) (int dev, unsigned long buf,
- int count, int intrflag, int dma_restart);
- int (*ioctl) (int dev, unsigned int cmd, unsigned int arg, int local);
- int (*prepare_for_input) (int dev, int bufsize, int nbufs);
- int (*prepare_for_output) (int dev, int bufsize, int nbufs);
- void (*reset) (int dev);
- void (*halt_xfer) (int dev);
- int (*local_qlen)(int dev);
- void (*copy_from_user)(int dev, char *localbuf, int localoffs,
- snd_rw_buf *userbuf, int useroffs, int len);
- int buffcount;
- long buffsize;
- int dmachan;
- struct dma_buffparms *dmap;
+#define DMA_DUPLEX 4
+ int format_mask; /* Bitmask for supported audio formats */
+ void *devc; /* Driver specific info */
+ int (*open) (int dev, int mode);
+ void (*close) (int dev);
+ void (*output_block) (int dev, unsigned long buf,
+ int count, int intrflag, int dma_restart);
+ void (*start_input) (int dev, unsigned long buf,
+ int count, int intrflag, int dma_restart);
+ int (*ioctl) (int dev, u_int cmd, ioctl_arg arg, int local);
+ int (*prepare_for_input) (int dev, int bufsize, int nbufs);
+ int (*prepare_for_output) (int dev, int bufsize, int nbufs);
+ void (*reset) (int dev);
+ void (*halt_xfer) (int dev);
+ int (*local_qlen) (int dev);
+ void (*copy_from_user) (int dev, char *localbuf, int localoffs,
+ snd_rw_buf * userbuf, int useroffs, int len);
+ void (*halt_input) (int dev);
+ void (*halt_output) (int dev);
+ void (*trigger) (int dev, int bits);
+ long buffsize;
+ int dmachan1, dmachan2;
+ struct dma_buffparms *dmap_in, *dmap_out;
+ struct coproc_operations *coproc;
+ int mixer_dev;
+ int enable_bits;
+ int open_mode;
+ int go;
+ int otherside;
+ int busy;
};
struct mixer_operations {
- int (*ioctl) (int dev, unsigned int cmd, unsigned int arg);
+ char name[32];
+ int (*ioctl) (int dev, unsigned int cmd, ioctl_arg arg);
};
struct synth_operations {
struct synth_info *info;
- int midi_dev;
- int synth_type;
- int synth_subtype;
-
- int (*open) (int dev, int mode);
- void (*close) (int dev);
- int (*ioctl) (int dev, unsigned int cmd, unsigned int arg);
- int (*kill_note) (int dev, int voice, int note, int velocity);
- int (*start_note) (int dev, int voice, int note, int velocity);
- int (*set_instr) (int dev, int voice, int instr);
- void (*reset) (int dev);
- void (*hw_control) (int dev, unsigned char *event);
- int (*load_patch) (int dev, int format, snd_rw_buf *addr,
- int offs, int count, int pmgr_flag);
- void (*aftertouch) (int dev, int voice, int pressure);
- void (*controller) (int dev, int voice, int ctrl_num, int value);
- void (*panning) (int dev, int voice, int value);
- void (*volume_method) (int dev, int mode);
- int (*pmgr_interface) (int dev, struct patmgr_info *info);
- void (*bender) (int dev, int chn, int value);
- int (*alloc_voice) (int dev, int chn, int note, struct voice_alloc_info *alloc);
-
- struct voice_alloc_info alloc;
- struct channel_info chn_info[16];
+ int midi_dev;
+ int synth_type;
+ int synth_subtype;
+
+ int (*open) (int dev, int mode);
+ void (*close) (int dev);
+ int (*ioctl) (int dev, unsigned int cmd, ioctl_arg arg);
+ int (*kill_note) (int dev, int voice, int note, int velocity);
+ int (*start_note) (int dev, int voice, int note, int velocity);
+ int (*set_instr) (int dev, int voice, int instr);
+ void (*reset) (int dev);
+ void (*hw_control) (int dev, unsigned char *event);
+ int (*load_patch) (int dev, int format, snd_rw_buf * addr,
+ int offs, int count, int pmgr_flag);
+ void (*aftertouch) (int dev, int voice, int pressure);
+ void (*controller) (int dev, int voice, int ctrl_num, int value);
+ void (*panning) (int dev, int voice, int value);
+ void (*volume_method) (int dev, int mode);
+ int (*pmgr_interface) (int dev, struct patmgr_info * info);
+ void (*bender) (int dev, int chn, int value);
+ int (*alloc_voice) (int dev, int chn, int note, struct voice_alloc_info * alloc);
+ void (*setup_voice) (int dev, int voice, int chn);
+ int (*send_sysex) (int dev, unsigned char *bytes, int len);
+
+ struct voice_alloc_info alloc;
+ struct channel_info chn_info[16];
+};
+
+struct midi_input_info { /* MIDI input scanner variables */
+#define MI_MAX 10
+ int m_busy;
+ unsigned char m_buf[MI_MAX];
+ unsigned char m_prev_status; /* For running status */
+ int m_ptr;
+#define MST_INIT 0
+#define MST_DATA 1
+#define MST_SYSEX 2
+ int m_state;
+ int m_left;
};
struct midi_operations {
struct midi_info info;
struct synth_operations *converter;
- int (*open) (int dev, int mode,
- void (*inputintr)(int dev, unsigned char data),
- void (*outputintr)(int dev)
- );
- void (*close) (int dev);
- int (*ioctl) (int dev, unsigned int cmd, unsigned int arg);
- int (*putc) (int dev, unsigned char data);
- int (*start_read) (int dev);
- int (*end_read) (int dev);
- void (*kick)(int dev);
- int (*command) (int dev, unsigned char *data);
- int (*buffer_status) (int dev);
- int (*prefix_cmd) (int dev, unsigned char status);
+ struct midi_input_info in_info;
+ int (*open) (int dev, int mode,
+ void (*inputintr) (int dev, unsigned char data),
+ void (*outputintr) (int dev) );
+ void (*close) (int dev);
+ int (*ioctl) (int dev, unsigned int cmd, ioctl_arg arg);
+ int (*putc) (int dev, unsigned char data);
+ int (*start_read) (int dev);
+ int (*end_read) (int dev);
+ void (*kick) (int dev);
+ int (*command) (int dev, unsigned char *data);
+ int (*buffer_status) (int dev);
+ int (*prefix_cmd) (int dev, unsigned char status);
+ struct coproc_operations *coproc;
+};
+
+struct sound_lowlev_timer {
+ int dev;
+ u_int (*tmr_start) (int dev, unsigned int usecs);
+ void (*tmr_disable) (int dev);
+ void (*tmr_restart) (int dev);
};
struct sound_timer_operations {
struct sound_timer_info info;
- int priority;
- int devlink;
- int (*open)(int dev, int mode);
- void (*close)(int dev);
- int (*event)(int dev, unsigned char *ev);
- unsigned long (*get_time)(int dev);
- int (*ioctl) (int dev, unsigned int cmd, unsigned int arg);
- void (*arm_timer)(int dev, long time);
+ int priority;
+ int devlink;
+ int (*open) (int dev, int mode);
+ void (*close) (int dev);
+ int (*event) (int dev, unsigned char *ev);
+ u_long (*get_time) (int dev);
+ int (*ioctl) (int dev, unsigned int cmd, ioctl_arg arg);
+ void (*arm_timer) (int dev, long time);
};
-#ifdef _DEV_TABLE_C_
- struct audio_operations *audio_devs[MAX_AUDIO_DEV] = {NULL}; int num_audiodevs = 0;
- struct mixer_operations *mixer_devs[MAX_MIXER_DEV] = {NULL}; int num_mixers = 0;
- struct synth_operations *synth_devs[MAX_SYNTH_DEV+MAX_MIDI_DEV] = {NULL}; int num_synths = 0;
- struct midi_operations *midi_devs[MAX_MIDI_DEV] = {NULL}; int num_midis = 0;
-
-#ifndef EXCLUDE_SEQUENCER
- extern struct sound_timer_operations default_sound_timer;
- struct sound_timer_operations *sound_timer_devs[MAX_TIMER_DEV] =
- {&default_sound_timer, NULL};
- int num_sound_timers = 1;
+#ifdef _DEV_TABLE_C_
+struct audio_operations *audio_devs[MAX_AUDIO_DEV] = {NULL};
+int num_audiodevs = 0;
+struct mixer_operations *mixer_devs[MAX_MIXER_DEV] = {NULL};
+int num_mixers = 0;
+struct synth_operations *synth_devs[MAX_SYNTH_DEV + MAX_MIDI_DEV] = {NULL};
+int num_synths = 0;
+struct midi_operations *midi_devs[MAX_MIDI_DEV] = {NULL};
+int num_midis = 0;
+
+#ifdef CONFIG_SEQUENCER
+extern struct sound_timer_operations default_sound_timer;
+struct sound_timer_operations *sound_timer_devs[MAX_TIMER_DEV] =
+ {&default_sound_timer, NULL};
+int num_sound_timers = 1;
#else
- struct sound_timer_operations *sound_timer_devs[MAX_TIMER_DEV] =
- {NULL};
- int num_sound_timers = 0;
+struct sound_timer_operations *sound_timer_devs[MAX_TIMER_DEV] = {NULL};
+int num_sound_timers = 0;
#endif
/*
* List of low level drivers compiled into the kernel.
+ *
+ * remember, each entry contains:
+
+ char *driver_id;
+ int card_subtype; (Driver specific. Usually 0)
+ int card_type; (From soundcard.h)
+ char *name;
+ void (*attach) (struct address_info * hw_config);
+ int (*probe) (struct address_info * hw_config);
+ *
*/
- struct driver_info sound_drivers[] = {
-#ifndef EXCLUDE_PSS
- {SNDCARD_PSS, "Echo Personal Sound System PSS (ESC614)", attach_pss, probe_pss},
+struct driver_info sound_drivers[] = {
+
+#ifdef CONFIG_PSS
+ {"PSSECHO", 0, SNDCARD_PSS, "Echo Personal Sound System PSS (ESC614)",
+ attach_pss, probe_pss},
+ {"PSSMPU", 0, SNDCARD_PSS_MPU, "PSS-MPU",
+ attach_pss_mpu, probe_pss_mpu},
+ {"PSSMSS", 0, SNDCARD_PSS_MSS, "PSS-MSS",
+ attach_pss_mss, probe_pss_mss},
#endif
-#ifndef EXCLUDE_YM3812
- {SNDCARD_ADLIB, "OPL-2/OPL-3 FM", attach_adlib_card, probe_adlib},
+
+#ifdef CONFIG_MSS
+ /* XXX changed type from 0 to 1 -lr 970705 */
+ {"MSS", 1, SNDCARD_MSS, "MS Sound System",
+ attach_mss, probe_mss},
+ /* MSS without IRQ/DMA config registers (for DEC Alphas) */
+ {"PCXBJ", 1, SNDCARD_PSEUDO_MSS, "MS Sound System (AXP)",
+ attach_mss, probe_mss},
#endif
-#ifndef EXCLUDE_PAS
- {SNDCARD_PAS, "ProAudioSpectrum", attach_pas_card, probe_pas},
+
+#ifdef CONFIG_MAD16
+ {"MAD16", 0, SNDCARD_MAD16, "MAD16/Mozart (MSS)",
+ attach_mad16, probe_mad16},
+ {"MAD16MPU", 0, SNDCARD_MAD16_MPU, "MAD16/Mozart (MPU)",
+ attach_mad16_mpu, probe_mad16_mpu},
#endif
-#if !defined(EXCLUDE_MPU401) && !defined(EXCLUDE_MIDI)
- {SNDCARD_MPU401,"Roland MPU-401", attach_mpu401, probe_mpu401},
+
+#ifdef CONFIG_CS4232
+ {"CS4232", 0, SNDCARD_CS4232, "CS4232",
+ attach_cs4232, probe_cs4232},
+ {"CS4232MPU", 0, SNDCARD_CS4232_MPU, "CS4232 MIDI",
+ attach_cs4232_mpu, probe_cs4232_mpu},
#endif
-#if !defined(EXCLUDE_UART6850) && !defined(EXCLUDE_MIDI)
- {SNDCARD_UART6850,"6860 UART Midi", attach_uart6850, probe_uart6850},
+
+#ifdef CONFIG_YM3812
+ {"OPL3", 0, SNDCARD_ADLIB, "OPL-2/OPL-3 FM",
+ attach_adlib_card, probe_adlib},
#endif
-#ifndef EXCLUDE_SB
- {SNDCARD_SB, "SoundBlaster", attach_sb_card, probe_sb},
+
+#ifdef CONFIG_PAS
+ {"PAS16", 0, SNDCARD_PAS, "ProAudioSpectrum",
+ attach_pas_card, probe_pas},
#endif
-#if !defined(EXCLUDE_SB) && !defined(EXCLUDE_SB16)
-#ifndef EXCLUDE_AUDIO
- {SNDCARD_SB16, "SoundBlaster16", sb16_dsp_init, sb16_dsp_detect},
+
+#if defined(CONFIG_MPU401) && defined(CONFIG_MIDI)
+ {"MPU401", 0, SNDCARD_MPU401, "Roland MPU-401",
+ attach_mpu401, probe_mpu401},
#endif
-#ifndef EXCLUDE_MIDI
- {SNDCARD_SB16MIDI,"SB16 MIDI", attach_sb16midi, probe_sb16midi},
+
+#if defined(CONFIG_MAUI)
+ {"MAUI", 0, SNDCARD_MAUI, "TB Maui",
+ attach_maui, probe_maui},
#endif
+
+#if defined(CONFIG_UART6850) && defined(CONFIG_MIDI)
+ {"MIDI6850", 0, SNDCARD_UART6850, "6860 UART Midi",
+ attach_uart6850, probe_uart6850},
#endif
-#ifndef EXCLUDE_GUS16
- {SNDCARD_GUS16, "Ultrasound 16-bit opt.", attach_gus_db16, probe_gus_db16},
+
+#ifdef CONFIG_SB
+ {"SBLAST", 0, SNDCARD_SB, "SoundBlaster",
+ attach_sb_card, probe_sb},
#endif
-#ifndef EXCLUDE_MSS
- {SNDCARD_MSS, "MS Sound System", attach_ms_sound, probe_ms_sound},
+
+#if defined(CONFIG_SB) && defined(CONFIG_SB16)
+#ifdef CONFIG_AUDIO
+ {"SB16", 0, SNDCARD_SB16, "SoundBlaster16",
+ sb16_dsp_init, sb16_dsp_detect},
+#endif
+#ifdef CONFIG_AWE32
+ {"AWE32", 0, SNDCARD_AWE32, "AWE32 Synth",
+ attach_awe_obsolete, probe_awe_obsolete},
+#endif
+#ifdef CONFIG_MIDI
+ {"SB16MIDI", 0, SNDCARD_SB16MIDI, "SB16 MIDI",
+ attach_sb16midi, probe_sb16midi},
#endif
-#ifndef EXCLUDE_GUS
- {SNDCARD_GUS, "Gravis Ultrasound", attach_gus_card, probe_gus},
#endif
- {0, "*?*", NULL, NULL}
- };
+#ifdef CONFIG_GUS16
+ {"GUS16", 0, SNDCARD_GUS16, "Ultrasound 16-bit opt.",
+ attach_gus_db16, probe_gus_db16},
+#endif
+
+#ifdef CONFIG_GUS
+ {"GUS", 0, SNDCARD_GUS, "Gravis Ultrasound",
+ attach_gus_card, probe_gus},
+#endif
+
+#ifdef CONFIG_SSCAPE
+ {"SSCAPE", 0, SNDCARD_SSCAPE, "Ensoniq Soundscape",
+ attach_sscape, probe_sscape},
+ {"SSCAPEMSS", 0, SNDCARD_SSCAPE_MSS, "MS Sound System (SoundScape)",
+ attach_ss_mss, probe_ss_mss},
+#endif
+
+#if NTRIX > 0
+ {"TRXPRO", 0, SNDCARD_TRXPRO, "MediaTriX AudioTriX Pro",
+ attach_trix_wss, probe_trix_wss},
+ {"TRXPROSB", 0, SNDCARD_TRXPRO_SB, "AudioTriX (SB mode)",
+ attach_trix_sb, probe_trix_sb},
+ {"TRXPROMPU", 0, SNDCARD_TRXPRO_MPU, "AudioTriX MIDI",
+ attach_trix_mpu, probe_trix_mpu},
+#endif
+
+#ifdef CONFIG_PNP
+ {"AD1848", 0, 500, "PnP MSS",
+ attach_pnp_ad1848, probe_pnp_ad1848},
+#endif
+
+ {NULL, 0, 0, "*?*", NULL, NULL}
+};
+
+int num_sound_drivers =
+sizeof(sound_drivers) / sizeof(struct driver_info);
+int max_sound_drivers =
+sizeof(sound_drivers) / sizeof(struct driver_info);
+
+#define FULL_SOUND
+
+#ifndef FULL_SOUND
/*
- * List of devices actually configured in the system.
+ * List of devices actually configured in the system.
+ *
+ * Note! The detection order is significant. Don't change it.
+ *
+ * remember, the list contains
+ *
+ * int card_type; (Link (search key) to the driver list)
+ * struct address_info config;
+ * io_base, irq, dma, dma2,
+ * always_detect, char *name, struct... *osp
+ * int enabled;
+ * void *for_driver_use;
*
- * Note! The detection order is significant. Don't change it.
*/
- struct card_info snd_installed_cards[] = {
-#ifndef EXCLUDE_PSS
- {SNDCARD_PSS, {PSS_BASE, PSS_IRQ, PSS_DMA}, SND_DEFAULT_ENABLE},
+struct card_info snd_installed_cards[] = {
+#ifdef CONFIG_PSS
+ {SNDCARD_PSS, {PSS_BASE, 0, -1, -1}, SND_DEFAULT_ENABLE},
+#ifdef PSS_MPU_BASE
+ {SNDCARD_PSS_MPU, {PSS_MPU_BASE, PSS_MPU_IRQ, 0, -1}, SND_DEFAULT_ENABLE},
#endif
-#if !defined(EXCLUDE_MPU401) && !defined(EXCLUDE_MIDI)
- {SNDCARD_MPU401, {MPU_BASE, MPU_IRQ, 0}, SND_DEFAULT_ENABLE},
-#ifdef MPU2_BASE
- {SNDCARD_MPU401, {MPU2_BASE, MPU2_IRQ, 0}, SND_DEFAULT_ENABLE},
+#ifdef PSS_MSS_BASE
+ {SNDCARD_PSS_MSS, {PSS_MSS_BASE, PSS_MSS_IRQ, PSS_MSS_DMA, -1}, SND_DEFAULT_ENABLE},
#endif
-#ifdef MPU3_BASE
- {SNDCARD_MPU401, {MPU3_BASE, MPU2_IRQ, 0}, SND_DEFAULT_ENABLE},
+#endif /* config PSS */
+
+#if NTRIX > 0
+ {SNDCARD_TRXPRO, {TRIX_BASE, TRIX_IRQ, TRIX_DMA, TRIX_DMA2}, SND_DEFAULT_ENABLE},
+#ifdef TRIX_SB_BASE
+ {SNDCARD_TRXPRO_SB, {TRIX_SB_BASE, TRIX_SB_IRQ, TRIX_SB_DMA, -1}, SND_DEFAULT_ENABLE},
#endif
+#ifdef TRIX_MPU_BASE
+ {SNDCARD_TRXPRO_MPU, {TRIX_MPU_BASE, TRIX_MPU_IRQ, 0, -1}, SND_DEFAULT_ENABLE},
#endif
-#ifndef EXCLUDE_MSS
- {SNDCARD_MSS, {MSS_BASE, MSS_IRQ, MSS_DMA}, SND_DEFAULT_ENABLE},
-# ifdef MSS2_BASE
- {SNDCARD_MSS, {MSS2_BASE, MSS2_IRQ, MSS2_DMA}, SND_DEFAULT_ENABLE},
-# endif
+#endif /* NTRIX > 0 */
+
+#ifdef CONFIG_SSCAPE
+ {SNDCARD_SSCAPE, {SSCAPE_BASE, SSCAPE_IRQ, SSCAPE_DMA, -1}, SND_DEFAULT_ENABLE},
+ {SNDCARD_SSCAPE_MSS, {SSCAPE_MSS_BASE, SSCAPE_MSS_IRQ, SSCAPE_MSS_DMA, -1}, SND_DEFAULT_ENABLE},
#endif
-#if !defined(EXCLUDE_UART6850) && !defined(EXCLUDE_MIDI)
- {SNDCARD_UART6850, {U6850_BASE, U6850_IRQ, 0}, SND_DEFAULT_ENABLE},
+#ifdef CONFIG_MAD16
+ {SNDCARD_MAD16, {MAD16_BASE, MAD16_IRQ, MAD16_DMA, MAD16_DMA2}, SND_DEFAULT_ENABLE},
+#ifdef MAD16_MPU_BASE
+ {SNDCARD_MAD16_MPU, {MAD16_MPU_BASE, MAD16_MPU_IRQ, 0, -1}, SND_DEFAULT_ENABLE},
#endif
+#endif /* CONFIG_MAD16 */
-#ifndef EXCLUDE_PAS
- {SNDCARD_PAS, {PAS_BASE, PAS_IRQ, PAS_DMA}, SND_DEFAULT_ENABLE},
+#ifdef CONFIG_CS4232
+#ifdef CS4232_MPU_BASE
+ {SNDCARD_CS4232_MPU, {CS4232_MPU_BASE, CS4232_MPU_IRQ, 0, -1}, SND_DEFAULT_ENABLE},
+#endif
+ {SNDCARD_CS4232, {CS4232_BASE, CS4232_IRQ, CS4232_DMA, CS4232_DMA2}, SND_DEFAULT_ENABLE},
#endif
-#ifndef EXCLUDE_SB
- {SNDCARD_SB, {SBC_BASE, SBC_IRQ, SBC_DMA}, SND_DEFAULT_ENABLE},
+#ifdef CONFIG_MSS
+#ifdef PSEUDO_MSS
+ {SNDCARD_MSS, {MSS_BASE, MSS_IRQ, MSS_DMA, -1}, SND_DEFAULT_ENABLE},
+#else
+ {SNDCARD_PSEUDO_MSS, {MSS_BASE, MSS_IRQ, MSS_DMA, -1}, SND_DEFAULT_ENABLE},
#endif
+#ifdef MSS2_BASE
+ {SNDCARD_MSS, {MSS2_BASE, MSS2_IRQ, MSS2_DMA, -1}, SND_DEFAULT_ENABLE},
+#endif
+#endif /* CONFIG_MSS */
-#if !defined(EXCLUDE_SB) && !defined(EXCLUDE_SB16)
-#ifndef EXCLUDE_AUDIO
- {SNDCARD_SB16, {SBC_BASE, SBC_IRQ, SB16_DMA}, SND_DEFAULT_ENABLE},
+#ifdef CONFIG_PAS
+ {SNDCARD_PAS, {PAS_BASE, PAS_IRQ, PAS_DMA, -1}, SND_DEFAULT_ENABLE},
#endif
-#ifndef EXCLUDE_MIDI
- {SNDCARD_SB16MIDI,{SB16MIDI_BASE, SBC_IRQ, 0}, SND_DEFAULT_ENABLE},
+
+#ifdef CONFIG_SB
+#ifndef SBC_DMA
+#define SBC_DMA 1
#endif
+ {SNDCARD_SB, {SBC_BASE, SBC_IRQ, SBC_DMA, -1}, SND_DEFAULT_ENABLE},
#endif
-#ifndef EXCLUDE_GUS
-#ifndef EXCLUDE_GUS16
- {SNDCARD_GUS16, {GUS16_BASE, GUS16_IRQ, GUS16_DMA}, SND_DEFAULT_ENABLE},
+#if defined(CONFIG_MAUI)
+ {SNDCARD_MAUI, {MAUI_BASE, MAUI_IRQ, 0, -1}, SND_DEFAULT_ENABLE},
+#endif
+
+#if defined(CONFIG_MPU401) && defined(CONFIG_MIDI)
+ {SNDCARD_MPU401, {MPU_BASE, MPU_IRQ, 0, -1}, SND_DEFAULT_ENABLE},
+#ifdef MPU2_BASE
+ {SNDCARD_MPU401, {MPU2_BASE, MPU2_IRQ, 0, -1}, SND_DEFAULT_ENABLE},
+#endif
+#ifdef MPU3_BASE
+ {SNDCARD_MPU401, {MPU3_BASE, MPU2_IRQ, 0, -1}, SND_DEFAULT_ENABLE},
+#endif
+#endif
+
+#if defined(CONFIG_UART6850) && defined(CONFIG_MIDI)
+ {SNDCARD_UART6850, {U6850_BASE, U6850_IRQ, 0, -1}, SND_DEFAULT_ENABLE},
+#endif
+
+#if defined(CONFIG_SB) && defined(CONFIG_SB16)
+#ifdef CONFIG_AUDIO
+ {SNDCARD_SB16, {SBC_BASE, SBC_IRQ, SB16_DMA, -1}, SND_DEFAULT_ENABLE},
+#endif
+#ifdef CONFIG_MIDI
+ {SNDCARD_SB16MIDI, {SB16MIDI_BASE, SBC_IRQ, 0, -1}, SND_DEFAULT_ENABLE},
+#endif
+#ifdef CONFIG_AWE32
+ {SNDCARD_AWE32,{AWE32_BASE, 0, 0, -1}, SND_DEFAULT_ENABLE},
#endif
- {SNDCARD_GUS, {GUS_BASE, GUS_IRQ, GUS_DMA}, SND_DEFAULT_ENABLE},
#endif
-#ifndef EXCLUDE_YM3812
- {SNDCARD_ADLIB, {FM_MONO, 0, 0}, SND_DEFAULT_ENABLE},
+#ifdef CONFIG_GUS
+#ifdef CONFIG_GUS16
+ {SNDCARD_GUS16, {GUS16_BASE, GUS16_IRQ, GUS16_DMA, -1}, SND_DEFAULT_ENABLE},
+#endif
+ {SNDCARD_GUS, {GUS_BASE, GUS_IRQ, GUS_DMA, GUS_DMA2}, SND_DEFAULT_ENABLE},
#endif
- {0, {0}, 0}
- };
- int num_sound_drivers =
- sizeof(sound_drivers) / sizeof (struct driver_info);
- int num_sound_cards =
- sizeof(snd_installed_cards) / sizeof (struct card_info);
+#ifdef CONFIG_YM3812
+ {SNDCARD_ADLIB, {FM_MONO, 0, 0, -1}, SND_DEFAULT_ENABLE},
+#endif
+ /* Define some expansion space */
+ {0, {0}, 0},
+ {0, {0}, 0},
+ {0, {0}, 0},
+ {0, {0}, 0},
+ {0, {0}, 0}
+};
+int num_sound_cards = sizeof(snd_installed_cards) / sizeof(struct card_info);
+int max_sound_cards = sizeof(snd_installed_cards) / sizeof(struct card_info);
#else
- extern struct audio_operations * audio_devs[MAX_AUDIO_DEV]; int num_audiodevs;
- extern struct mixer_operations * mixer_devs[MAX_MIXER_DEV]; extern int num_mixers;
- extern struct synth_operations * synth_devs[MAX_SYNTH_DEV+MAX_MIDI_DEV]; extern int num_synths;
- extern struct midi_operations * midi_devs[MAX_MIDI_DEV]; extern int num_midis;
- extern struct sound_timer_operations * sound_timer_devs[MAX_SYNTH_DEV+MAX_MIDI_DEV]; extern int num_sound_timers;
-
- extern struct driver_info sound_drivers[];
- extern int num_sound_drivers;
- extern struct card_info snd_installed_cards[];
- extern int num_sound_cards;
-
-long sndtable_init(long mem_start);
-int sndtable_get_cardcount (void);
-struct address_info *sound_getconf(int card_type);
-void sound_chconf(int card_type, int ioaddr, int irq, int dma);
-int snd_find_driver(int type);
+int num_sound_cards = 0;
+struct card_info snd_installed_cards[20] = {{0}};
+int max_sound_cards = 20;
+#endif
-#endif /* _DEV_TABLE_C_ */
-#endif /* _DEV_TABLE_H_ */
+#ifdef MODULE
+int trace_init = 0;
+#else
+int trace_init = 1;
+#endif
+
+#else
+extern struct audio_operations *audio_devs[MAX_AUDIO_DEV];
+int num_audiodevs;
+extern struct mixer_operations *mixer_devs[MAX_MIXER_DEV];
+extern int num_mixers;
+extern struct synth_operations *synth_devs[MAX_SYNTH_DEV + MAX_MIDI_DEV];
+extern int num_synths;
+extern struct midi_operations *midi_devs[MAX_MIDI_DEV];
+extern int num_midis;
+extern struct sound_timer_operations *sound_timer_devs[MAX_TIMER_DEV];
+extern int num_sound_timers;
+
+extern struct driver_info sound_drivers[];
+extern int num_sound_drivers;
+extern int max_sound_drivers;
+extern struct card_info snd_installed_cards[];
+extern int num_sound_cards;
+extern int max_sound_cards;
+
+extern int trace_init;
+
+void sndtable_init(void);
+int sndtable_get_cardcount(void);
+struct address_info *sound_getconf(int card_type);
+void sound_chconf(int card_type, int ioaddr, int irq, int dma);
+int snd_find_driver(int type);
+int sndtable_identify_card(char *name);
+void sound_setup(char *str, int *ints);
+
+int sound_alloc_dmap(int dev, struct dma_buffparms * dmap, int chan);
+void sound_free_dmap(int dev, struct dma_buffparms * dmap);
+extern int soud_map_buffer(int dev, struct dma_buffparms * dmap, buffmem_desc * info);
+void install_pnp_sounddrv(struct pnp_sounddev * drv);
+int sndtable_probe(int unit, struct address_info * hw_config);
+int sndtable_init_card(int unit, struct address_info * hw_config);
+void sound_timer_init(struct sound_lowlev_timer * t, char *name);
+int
+sound_start_dma(int dev, struct dma_buffparms * dmap, int chan,
+ unsigned long physaddr,
+ int count, int dma_mode, int autoinit);
+void sound_dma_intr(int dev, struct dma_buffparms * dmap, int chan);
+
+#endif /* _DEV_TABLE_C_ */
+#endif /* _DEV_TABLE_H_ */
diff --git a/sys/i386/isa/sound/dmabuf.c b/sys/i386/isa/sound/dmabuf.c
index 0e275b6a3aea..db1824efab15 100644
--- a/sys/i386/isa/sound/dmabuf.c
+++ b/sys/i386/isa/sound/dmabuf.c
@@ -1,10 +1,10 @@
/*
* sound/dmabuf.c
- *
+ *
* The DMA buffer manager for digitized voice applications
- *
- * Copyright by Hannu Savolainen 1993, 1994
- *
+ *
+ * Copyright by Hannu Savolainen 1993, 1994, 1995
+ *
* 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,941 +24,1579 @@
* 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"
+#include <i386/isa/sound/sound_config.h>
+#include <i386/include/md_var.h>
-#ifdef CONFIGURE_SOUNDCARD
+#if defined(CONFIG_AUDIO) || defined(CONFIG_GUS)
+#ifdef ALLOW_POLL
-#include "sound_calls.h"
-
-#if !defined(EXCLUDE_AUDIO) || !defined(EXCLUDE_GUS)
+int
+DMAbuf_poll(int dev, struct fileinfo * file, int events, select_table * wait);
+#endif;
-DEFINE_WAIT_QUEUES (dev_sleeper[MAX_AUDIO_DEV], dev_sleep_flag[MAX_AUDIO_DEV]);
+static void
+reorganize_buffers(int dev, struct dma_buffparms * dmap);
-static struct dma_buffparms dmaps[MAX_AUDIO_DEV] =
-{0}; /*
- * Primitive way to allocate
- * such a large array.
- * Needs dynamic run-time alloction.
- */
+static int *in_sleeper[MAX_AUDIO_DEV] = {NULL};
+static volatile struct snd_wait in_sleep_flag[MAX_AUDIO_DEV] = {{0}};
+static int *out_sleeper[MAX_AUDIO_DEV] = {NULL};
+static volatile struct snd_wait out_sleep_flag[MAX_AUDIO_DEV] = {{0}};
-static void
-reorganize_buffers (int dev)
-{
- /*
- * This routine breaks the physical device buffers to logical ones.
- */
+static int ndmaps = 0;
- struct dma_buffparms *dmap = audio_devs[dev]->dmap;
- struct audio_operations *dsp_dev = audio_devs[dev];
+#define MAX_DMAP (MAX_AUDIO_DEV*2)
- unsigned i, p, n;
- unsigned sr, nc, sz, bsz;
+static struct dma_buffparms dmaps[MAX_DMAP] = {{0}};
+/*
+ * Primitive way to allocate such a large array. Needs dynamic run-time
+ * alloction.
+ */
- if (dmap->fragment_size == 0)
- { /* Compute the fragment size using the default algorithm */
+static int space_in_queue(int dev);
- sr = dsp_dev->ioctl (dev, SOUND_PCM_READ_RATE, 0, 1);
- nc = dsp_dev->ioctl (dev, SOUND_PCM_READ_CHANNELS, 0, 1);
- sz = dsp_dev->ioctl (dev, SOUND_PCM_READ_BITS, 0, 1);
+static void dma_reset_output(int dev);
+static void dma_reset_input(int dev);
- if (sr < 1 || nc < 1 || sz < 1)
- {
- printk ("Warning: Invalid PCM parameters[%d] sr=%d, nc=%d, sz=%d\n",
- dev, sr, nc, sz);
- sr = DSP_DEFAULT_SPEED;
- nc = 1;
- sz = 8;
+static void
+reorganize_buffers(int dev, struct dma_buffparms * dmap)
+{
+ /*
+ * This routine breaks the physical device buffers to logical ones.
+ */
+
+ struct audio_operations *dsp_dev = audio_devs[dev];
+ u_int sr, nc;
+ int bsz, sz, n, i;
+
+ if (dmap->fragment_size == 0) {
+ /* Compute the fragment size using the default algorithm */
+
+ sr = dsp_dev->ioctl(dev, SOUND_PCM_READ_RATE, 0, 1);
+ nc = dsp_dev->ioctl(dev, SOUND_PCM_READ_CHANNELS, 0, 1);
+ sz = dsp_dev->ioctl(dev, SOUND_PCM_READ_BITS, 0, 1);
+
+ if (sz == 8)
+ dmap->neutral_byte = 254;
+ else
+ dmap->neutral_byte = 0x00;
+
+ if (sr < 1 || nc < 1 || sz < 1) {
+ printf("Warning: Invalid PCM parameters[%d] sr=%d, nc=%d, sz=%d\n",
+ dev, sr, nc, sz);
+ sr = DSP_DEFAULT_SPEED;
+ nc = 1;
+ sz = 8;
}
+ sz = sr * nc * sz;
+
+ sz /= 8; /* #bits -> #bytes */
+
+ /*
+ * Compute a buffer size for time not exeeding 1 second.
+ * Usually this algorithm gives a buffer size for 0.5 to 1.0
+ * seconds of sound (using the current speed, sample size and
+ * #channels).
+ */
+
+ bsz = dsp_dev->buffsize;
+ while (bsz > sz)
+ bsz /= 2;
+
+ if (bsz == dsp_dev->buffsize)
+ bsz /= 2; /* Needs at least 2 buffers */
+
+ if (dmap->subdivision == 0) /* Not already set */
+ dmap->subdivision = 1; /* Init to default value */
+ else
+ bsz /= dmap->subdivision;
+
+ if (bsz < 16)
+ bsz = 16; /* Just a sanity check */
+
+ dmap->fragment_size = bsz;
+ } else {
+ /*
+ * The process has specified the buffer sice with
+ * SNDCTL_DSP_SETFRAGMENT or the buffer sice computation has
+ * already been done.
+ */
+
+ if (dmap->fragment_size > (audio_devs[dev]->buffsize / 2))
+ dmap->fragment_size = (audio_devs[dev]->buffsize / 2);
+ bsz = dmap->fragment_size;
+ }
- sz /= 8; /* #bits -> #bytes */
-
- sz = sr * nc * sz;
+ bsz &= ~0x03; /* Force size which is multiple of 4 bytes */
+#ifdef OS_DMA_ALIGN_CHECK
+ OS_DMA_ALIGN_CHECK(bsz);
+#endif
- /*
- * Compute a buffer size for time not exeeding 1 second.
- * Usually this algorithm gives a buffer size for 0.5 to 1.0 seconds
- * of sound (using the current speed, sample size and #channels).
- */
+ n = dsp_dev->buffsize / bsz;
- bsz = dsp_dev->buffsize;
- while (bsz > sz)
- bsz /= 2;
+ if (n > MAX_SUB_BUFFERS)
+ n = MAX_SUB_BUFFERS;
- if (dsp_dev->buffcount == 1 && bsz == dsp_dev->buffsize)
- bsz /= 2; /* Needs at least 2 buffers */
+ if (n > dmap->max_fragments)
+ n = dmap->max_fragments;
+ dmap->nbufs = n;
+ dmap->bytes_in_use = n * bsz;
- if (dmap->subdivision == 0) /* Not already set */
- dmap->subdivision = 1; /* Init to default value */
+ for (i = 0; i < dmap->nbufs; i++) {
+ dmap->counts[i] = 0;
+ }
- bsz /= dmap->subdivision;
+ if (dmap->raw_buf)
+ fillw (dmap->neutral_byte, dmap->raw_buf,
+ dmap->bytes_in_use/2);
- if (bsz < 64)
- bsz = 4096; /* Just a sanity check */
+ dmap->flags |= DMA_ALLOC_DONE;
- while ((dsp_dev->buffsize * dsp_dev->buffcount) / bsz > MAX_SUB_BUFFERS)
- bsz *= 2;
+}
- dmap->fragment_size = bsz;
- }
- else
- {
- /*
- * The process has specified the buffer sice with SNDCTL_DSP_SETFRAGMENT or
- * the buffer sice computation has already been done.
- */
- if (dmap->fragment_size > audio_devs[dev]->buffsize)
- dmap->fragment_size = audio_devs[dev]->buffsize;
- bsz = dmap->fragment_size;
+static void
+dma_init_buffers(int dev, struct dma_buffparms * dmap)
+{
+ if (dmap == audio_devs[dev]->dmap_out) {
+ out_sleep_flag[dev].aborting = 0;
+ out_sleep_flag[dev].mode = WK_NONE;
+ } else {
+ in_sleep_flag[dev].aborting = 0;
+ in_sleep_flag[dev].mode = WK_NONE;
}
- /*
- * Now computing addresses for the logical buffers
- */
+ dmap->flags = DMA_BUSY; /* Other flags off */
+ dmap->qlen = dmap->qhead = dmap->qtail = 0;
+ dmap->nbufs = 1;
+ dmap->bytes_in_use = audio_devs[dev]->buffsize;
- n = 0;
- for (i = 0; i < dmap->raw_count &&
- n < dmap->max_fragments &&
- n < MAX_SUB_BUFFERS; i++)
+ dmap->dma_mode = DMODE_NONE;
+ dmap->mapping_flags = 0;
+ dmap->neutral_byte = 0x00;
+}
+
+static int
+open_dmap(int dev, int mode, struct dma_buffparms * dmap, int chan)
+{
+ if (dmap->flags & DMA_BUSY)
+ return -(EBUSY);
+
+#ifdef RUNTIME_DMA_ALLOC
{
- p = 0;
+ int err;
- while ((p + bsz) <= dsp_dev->buffsize &&
- n < dmap->max_fragments &&
- n < MAX_SUB_BUFFERS)
- {
- dmap->buf[n] = dmap->raw_buf[i] + p;
- dmap->buf_phys[n] = dmap->raw_buf_phys[i] + p;
- p += bsz;
- n++;
- }
+ if ((err = sound_alloc_dmap(dev, dmap, chan)) < 0)
+ return err;
}
+#endif
- dmap->nbufs = n;
- dmap->bytes_in_use = n * bsz;
+ if (dmap->raw_buf == NULL)
+ return -(ENOSPC); /* Memory allocation failed during boot */
- for (i = 0; i < dmap->nbufs; i++)
- {
- dmap->counts[i] = 0;
+ if (0) {
+ printf("Unable to grab(2) DMA%d for the audio driver\n", chan);
+ return -(EBUSY);
}
+ dmap->open_mode = mode;
+ dmap->subdivision = dmap->underrun_count = 0;
+ dmap->fragment_size = 0;
+ dmap->max_fragments = 65536; /* Just a large value */
+ dmap->byte_counter = 0;
+ isa_dma_acquire(chan);
- dmap->flags |= DMA_ALLOC_DONE;
+ dma_init_buffers(dev, dmap);
+
+ return 0;
}
static void
-dma_init_buffers (int dev)
+close_dmap(int dev, struct dma_buffparms * dmap, int chan)
{
- struct dma_buffparms *dmap = audio_devs[dev]->dmap = &dmaps[dev];
-
- RESET_WAIT_QUEUE (dev_sleeper[dev], dev_sleep_flag[dev]);
-
- dmap->flags = DMA_BUSY; /* Other flags off */
- dmap->qlen = dmap->qhead = dmap->qtail = 0;
-
- dmap->qlen = dmap->qtail = dmap->qhead = 0;
- dmap->dma_mode = DMODE_NONE;
+ if (dmap->flags & DMA_BUSY)
+ dmap->dma_mode = DMODE_NONE;
+ dmap->flags &= ~DMA_BUSY;
+ isa_dma_release(chan);
+#ifdef RUNTIME_DMA_ALLOC
+ sound_free_dmap(dev, dmap);
+#endif
}
int
-DMAbuf_open (int dev, int mode)
+DMAbuf_open(int dev, int mode)
{
- int retval;
- struct dma_buffparms *dmap = NULL;
+ int retval;
+ struct dma_buffparms *dmap_in = NULL;
+ struct dma_buffparms *dmap_out = NULL;
- if (dev >= num_audiodevs)
- {
- printk ("PCM device %d not installed.\n", dev);
- return RET_ERROR (ENXIO);
+ if (dev >= num_audiodevs) {
+ printf("PCM device %d not installed.\n", dev);
+ return -(ENXIO);
}
-
- if (!audio_devs[dev])
- {
- printk ("PCM device %d not initialized\n", dev);
- return RET_ERROR (ENXIO);
+ if (!audio_devs[dev]) {
+ printf("PCM device %d not initialized\n", dev);
+ return -(ENXIO);
}
+ if (!(audio_devs[dev]->flags & DMA_DUPLEX)) {
+ audio_devs[dev]->dmap_in = audio_devs[dev]->dmap_out;
+ audio_devs[dev]->dmachan2 = audio_devs[dev]->dmachan1;
+ }
+ if ((retval = audio_devs[dev]->open(dev, mode)) < 0)
+ return retval;
- dmap = audio_devs[dev]->dmap = &dmaps[dev];
-
- if (dmap->flags & DMA_BUSY)
- return RET_ERROR (EBUSY);
+ dmap_out = audio_devs[dev]->dmap_out;
+ dmap_in = audio_devs[dev]->dmap_in;
-#ifdef USE_RUNTIME_DMAMEM
- dmap->raw_buf[0] = NULL;
- sound_dma_malloc (dev);
-#endif
+ if ((retval = open_dmap(dev, mode, dmap_out, audio_devs[dev]->dmachan1)) < 0) {
+ audio_devs[dev]->close(dev);
+ return retval;
+ }
+ audio_devs[dev]->enable_bits = mode;
- if (dmap->raw_buf[0] == NULL)
- return RET_ERROR (ENOSPC); /* Memory allocation failed during boot */
+ if (audio_devs[dev]->flags & DMA_DUPLEX && dmap_out != dmap_in) {
+ if ((retval = open_dmap(dev, mode, dmap_in, audio_devs[dev]->dmachan2)) < 0) {
+ audio_devs[dev]->close(dev);
+ close_dmap(dev, dmap_out, audio_devs[dev]->dmachan1);
+ return retval;
+ }
+ }
+ audio_devs[dev]->open_mode = mode;
+ audio_devs[dev]->go = 1;
- if ((retval = audio_devs[dev]->open (dev, mode)) < 0)
- return retval;
+ in_sleep_flag[dev].aborting = 0;
+ in_sleep_flag[dev].mode = WK_NONE;
- dmap->open_mode = mode;
- dmap->subdivision = dmap->underrun_count = 0;
- dmap->fragment_size = 0;
- dmap->max_fragments = 65536; /* Just a large value */
+ out_sleep_flag[dev].aborting = 0;
+ out_sleep_flag[dev].mode = WK_NONE;
- dma_init_buffers (dev);
- audio_devs[dev]->ioctl (dev, SOUND_PCM_WRITE_BITS, 8, 1);
- audio_devs[dev]->ioctl (dev, SOUND_PCM_WRITE_CHANNELS, 1, 1);
- audio_devs[dev]->ioctl (dev, SOUND_PCM_WRITE_RATE, DSP_DEFAULT_SPEED, 1);
+ audio_devs[dev]->ioctl(dev, SOUND_PCM_WRITE_BITS, (ioctl_arg) 8, 1);
+ audio_devs[dev]->ioctl(dev, SOUND_PCM_WRITE_CHANNELS, (ioctl_arg) 1, 1);
+ audio_devs[dev]->ioctl(dev, SOUND_PCM_WRITE_RATE, (ioctl_arg) DSP_DEFAULT_SPEED, 1);
- return 0;
+ return 0;
}
static void
-dma_reset (int dev)
+dma_reset(int dev)
{
- int retval;
- unsigned long flags;
+ u_long flags;
- DISABLE_INTR (flags);
+ flags = splhigh();
+ audio_devs[dev]->reset(dev);
+ splx(flags);
- audio_devs[dev]->reset (dev);
- audio_devs[dev]->close (dev);
+ dma_reset_output(dev);
- if ((retval = audio_devs[dev]->open (dev, audio_devs[dev]->dmap->open_mode)) < 0)
- printk ("Sound: Reset failed - Can't reopen device\n");
- RESTORE_INTR (flags);
+ if (audio_devs[dev]->flags & DMA_DUPLEX)
+ dma_reset_input(dev);
+}
- dma_init_buffers (dev);
- reorganize_buffers (dev);
+static void
+dma_reset_output(int dev)
+{
+ u_long flags;
+
+ flags = splhigh();
+ if (!(audio_devs[dev]->flags & DMA_DUPLEX) ||
+ !audio_devs[dev]->halt_output)
+ audio_devs[dev]->reset(dev);
+ else
+ audio_devs[dev]->halt_output(dev);
+ splx(flags);
+
+ dma_init_buffers(dev, audio_devs[dev]->dmap_out);
+ reorganize_buffers(dev, audio_devs[dev]->dmap_out);
+}
+
+static void
+dma_reset_input(int dev)
+{
+ u_long flags;
+
+ flags = splhigh();
+ if (!(audio_devs[dev]->flags & DMA_DUPLEX) ||
+ !audio_devs[dev]->halt_input)
+ audio_devs[dev]->reset(dev);
+ else
+ audio_devs[dev]->halt_input(dev);
+ splx(flags);
+
+ dma_init_buffers(dev, audio_devs[dev]->dmap_in);
+ reorganize_buffers(dev, audio_devs[dev]->dmap_in);
}
static int
-dma_sync (int dev)
+dma_sync(int dev)
{
- unsigned long flags;
+ u_long flags;
+ int i = 0;
+
+ if (!audio_devs[dev]->go && (!audio_devs[dev]->enable_bits & PCM_ENABLE_OUTPUT))
+ return 0;
+
+ if (audio_devs[dev]->dmap_out->dma_mode == DMODE_OUTPUT) {
+ flags = splhigh();
+
+ out_sleep_flag[dev].aborting = 0;
+#ifdef ALLOW_BUFFER_MAPPING
+ if(audio_devs[dev]->dmap_out->mapping_flags & DMA_MAP_MAPPED &&
+ audio_devs[dev]->dmap_out->qlen) {
+ splx(flags);
+
+ return audio_devs[dev]->dmap_out->qlen;
+ }
- if (audio_devs[dev]->dmap->dma_mode == DMODE_OUTPUT)
- {
- DISABLE_INTR (flags);
+#endif
+ while (!PROCESS_ABORTING (out_sleep_flag[dev])
+ && audio_devs[dev]->dmap_out->qlen){
+ int chn;
+
+ out_sleeper[dev] = &chn;
+ DO_SLEEP1(chn, out_sleep_flag[dev], 10 * hz);
+ if (TIMED_OUT (out_sleep_flag[dev]) ) {
+
+ splx(flags);
+
+ return audio_devs[dev]->dmap_out->qlen;
- while (!PROCESS_ABORTING (dev_sleeper[dev], dev_sleep_flag[dev])
- && audio_devs[dev]->dmap->qlen)
- {
- DO_SLEEP (dev_sleeper[dev], dev_sleep_flag[dev], 10 * HZ);
- if (TIMED_OUT (dev_sleeper[dev], dev_sleep_flag[dev]))
- {
- RESTORE_INTR (flags);
- return audio_devs[dev]->dmap->qlen;
- }
+ }
}
- RESTORE_INTR (flags);
- /*
- * Some devices such as GUS have huge amount of on board RAM for the
- * audio data. We have to wait util the device has finished playing.
- */
- DISABLE_INTR (flags);
- if (audio_devs[dev]->local_qlen) /* Device has hidden buffers */
- {
- while (!(PROCESS_ABORTING (dev_sleeper[dev], dev_sleep_flag[dev]))
- && audio_devs[dev]->local_qlen (dev))
- {
- DO_SLEEP (dev_sleeper[dev], dev_sleep_flag[dev], HZ);
+ splx(flags);
+
+ /*
+ * Some devices such as GUS have huge amount of on board RAM
+ * for the audio data. We have to wait until the device has
+ * finished playing.
+ */
+
+ flags = splhigh();
+ if (audio_devs[dev]->local_qlen) { /* Device has hidden buffers */
+ while (!(PROCESS_ABORTING (out_sleep_flag[dev]))
+ && audio_devs[dev]->local_qlen(dev)) {
+ int chn;
+ out_sleeper[dev] = &chn;
+ DO_SLEEP(chn, out_sleep_flag[dev], 10 * hz);
+
}
}
- RESTORE_INTR (flags);
+ splx(flags);
}
- return audio_devs[dev]->dmap->qlen;
+ return audio_devs[dev]->dmap_out->qlen;
}
int
-DMAbuf_release (int dev, int mode)
+DMAbuf_release(int dev, int mode)
{
- unsigned long flags;
+ u_long flags;
- if (!(PROCESS_ABORTING (dev_sleeper[dev], dev_sleep_flag[dev]))
- && (audio_devs[dev]->dmap->dma_mode == DMODE_OUTPUT))
- {
- dma_sync (dev);
+ if (!((out_sleep_flag[dev].aborting))
+ && (audio_devs[dev]->dmap_out->dma_mode == DMODE_OUTPUT)) {
+ dma_sync(dev);
}
+ flags = splhigh();
-#ifdef USE_RUNTIME_DMAMEM
- sound_dma_free (dev);
-#endif
+ audio_devs[dev]->close(dev);
- DISABLE_INTR (flags);
- audio_devs[dev]->reset (dev);
+ close_dmap(dev, audio_devs[dev]->dmap_out, audio_devs[dev]->dmachan1);
- audio_devs[dev]->close (dev);
+ if (audio_devs[dev]->flags & DMA_DUPLEX)
+ close_dmap(dev, audio_devs[dev]->dmap_in, audio_devs[dev]->dmachan2);
+ audio_devs[dev]->open_mode = 0;
- audio_devs[dev]->dmap->dma_mode = DMODE_NONE;
- audio_devs[dev]->dmap->flags &= ~DMA_BUSY;
- RESTORE_INTR (flags);
+ splx(flags);
- return 0;
+ return 0;
}
-int
-DMAbuf_getrdbuffer (int dev, char **buf, int *len)
+static int
+activate_recording(int dev, struct dma_buffparms * dmap)
{
- unsigned long flags;
- int err = EIO;
- struct dma_buffparms *dmap = audio_devs[dev]->dmap;
+ if (!(audio_devs[dev]->enable_bits & PCM_ENABLE_INPUT))
+ return 0;
- DISABLE_INTR (flags);
- if (!dmap->qlen)
- {
- if (dmap->flags & DMA_RESTART)
- {
- dma_reset (dev);
- dmap->flags &= ~DMA_RESTART;
- }
+ if (dmap->flags & DMA_RESTART) {
+ dma_reset_input(dev);
+ dmap->flags &= ~DMA_RESTART;
+ }
+ if (dmap->dma_mode == DMODE_OUTPUT) { /* Direction change */
+ dma_sync(dev);
+ dma_reset(dev);
+ dmap->dma_mode = DMODE_NONE;
+ }
+ if (!(dmap->flags & DMA_ALLOC_DONE))
+ reorganize_buffers(dev, dmap);
- if (dmap->dma_mode == DMODE_OUTPUT) /* Direction change */
- {
- dma_sync (dev);
- dma_reset (dev);
- dmap->dma_mode = DMODE_NONE;
- }
+ if (!dmap->dma_mode) {
+ int err;
- if (!(dmap->flags & DMA_ALLOC_DONE))
- reorganize_buffers (dev);
+ if ((err = audio_devs[dev]->prepare_for_input(dev,
+ dmap->fragment_size, dmap->nbufs)) < 0) {
+ return err;
+ }
+ dmap->dma_mode = DMODE_INPUT;
+ }
+ if (!(dmap->flags & DMA_ACTIVE)) {
+ audio_devs[dev]->start_input(dev,
+ dmap->raw_buf_phys + dmap->qtail * dmap->fragment_size,
+ dmap->fragment_size, 0,
+ !(audio_devs[dev]->flags & DMA_AUTOMODE) ||
+ !(dmap->flags & DMA_STARTED));
+ dmap->flags |= DMA_ACTIVE | DMA_STARTED;
+ if (audio_devs[dev]->trigger)
+ audio_devs[dev]->trigger(dev,
+ audio_devs[dev]->enable_bits * audio_devs[dev]->go);
+ }
+ return 0;
+}
- if (dmap->dma_mode)
- {
- int err;
+int
+DMAbuf_getrdbuffer(int dev, char **buf, int *len, int dontblock)
+{
+ u_long flags;
+ int err = EIO;
+ struct dma_buffparms *dmap = audio_devs[dev]->dmap_in;
+
+ flags = splhigh();
+#ifdef ALLOW_BUFFER_MAPPING
+ if (audio_devs[dev]->dmap_in->mapping_flags & DMA_MAP_MAPPED) {
+ printf("Sound: Can't read from mmapped device (1)\n");
+ return -(EINVAL);
+ } else
+#endif
+ if (!dmap->qlen) {
+ int timeout;
- if ((err = audio_devs[dev]->prepare_for_input (dev,
- dmap->fragment_size, dmap->nbufs)) < 0)
- {
- RESTORE_INTR (flags);
- return err;
- }
- dmap->dma_mode = DMODE_INPUT;
+ if ((err = activate_recording(dev, dmap)) < 0) {
+ splx(flags);
+ return err;
}
+ /* Wait for the next block */
- if (!(dmap->flags & DMA_ACTIVE))
- {
- audio_devs[dev]->start_input (dev, dmap->buf_phys[dmap->qtail],
- dmap->fragment_size, 0,
- !(audio_devs[dev]->flags & DMA_AUTOMODE) ||
- !(dmap->flags & DMA_STARTED));
- dmap->flags |= DMA_ACTIVE | DMA_STARTED;
+ if (dontblock) {
+ splx(flags);
+ return -(EAGAIN);
}
+ if (!(audio_devs[dev]->enable_bits & PCM_ENABLE_INPUT) &
+ audio_devs[dev]->go) {
+ splx(flags);
+ return -(EAGAIN);
+ }
+ if (!audio_devs[dev]->go)
+ timeout = 0;
+ else
+ timeout = 2 * hz;
- /* Wait for the next block */
-
- DO_SLEEP (dev_sleeper[dev], dev_sleep_flag[dev], 2 * HZ);
- if (TIMED_OUT (dev_sleeper[dev], dev_sleep_flag[dev]))
{
- printk ("Sound: DMA timed out - IRQ/DRQ config error?\n");
- err = EIO;
- SET_ABORT_FLAG (dev_sleeper[dev], dev_sleep_flag[dev]);
- }
- else
- err = EINTR;
+ int chn;
+
+ in_sleeper[dev] = &chn;
+ DO_SLEEP(chn, in_sleep_flag[dev], timeout);
+
+ };
+ /* XXX note -- nobody seems to set the mode to WK_TIMEOUT - lr */
+ if ((in_sleep_flag[dev].mode & WK_TIMEOUT)) {
+ /* XXX hey, we are in splhigh here ? lr 970705 */
+ printf("Sound: DMA (input) timed out - IRQ/DRQ config error?\n");
+ err = EIO;
+ audio_devs[dev]->reset(dev);
+ in_sleep_flag[dev].aborting = 1;
+ } else
+ err = EINTR;
}
- RESTORE_INTR (flags);
+ splx(flags);
- if (!dmap->qlen)
- return RET_ERROR (err);
+ if (!dmap->qlen)
+ return -(err);
- *buf = &dmap->buf[dmap->qhead][dmap->counts[dmap->qhead]];
- *len = dmap->fragment_size - dmap->counts[dmap->qhead];
+ *buf = &dmap->raw_buf[dmap->qhead * dmap->fragment_size + dmap->counts[dmap->qhead]];
+ *len = dmap->fragment_size - dmap->counts[dmap->qhead];
- return dmap->qhead;
+ return dmap->qhead;
}
int
-DMAbuf_rmchars (int dev, int buff_no, int c)
+DMAbuf_rmchars(int dev, int buff_no, int c)
+{
+ struct dma_buffparms *dmap = audio_devs[dev]->dmap_in;
+
+ int p = dmap->counts[dmap->qhead] + c;
+
+#ifdef ALLOW_BUFFER_MAPPING
+ if (audio_devs[dev]->dmap_in->mapping_flags & DMA_MAP_MAPPED) {
+ printf("Sound: Can't read from mmapped device (2)\n");
+ return -(EINVAL);
+ } else
+#endif
+ if (p >= dmap->fragment_size) { /* This buffer is completely empty */
+ dmap->counts[dmap->qhead] = 0;
+ if (dmap->qlen <= 0 || dmap->qlen > dmap->nbufs)
+ printf("\nSound: Audio queue1 corrupted for dev%d (%d/%d)\n",
+ dev, dmap->qlen, dmap->nbufs);
+ dmap->qlen--;
+ dmap->qhead = (dmap->qhead + 1) % dmap->nbufs;
+ } else
+ dmap->counts[dmap->qhead] = p;
+
+ return 0;
+}
+
+static int
+dma_subdivide(int dev, struct dma_buffparms * dmap, ioctl_arg arg, int fact)
{
- struct dma_buffparms *dmap = audio_devs[dev]->dmap;
+ if (fact == 0) {
+ fact = dmap->subdivision;
+ if (fact == 0)
+ fact = 1;
+ return *(int *) arg = fact;
+ }
+ if (dmap->subdivision != 0 || dmap->fragment_size)/* Loo late to change */
+ return -(EINVAL);
- int p = dmap->counts[dmap->qhead] + c;
+ if (fact > MAX_REALTIME_FACTOR)
+ return -(EINVAL);
+
+ if (fact != 1 && fact != 2 && fact != 4 && fact != 8 && fact != 16)
+ return -(EINVAL);
+
+ dmap->subdivision = fact;
+ return *(int *) arg = fact;
+}
+
+static int
+dma_set_fragment(int dev, struct dma_buffparms * dmap, ioctl_arg arg, int fact)
+{
+ int bytes, count;
+
+ if (fact == 0)
+ return -(EIO);
+
+ if (dmap->subdivision != 0 || dmap->fragment_size)/* Loo late to change */
+ return -(EINVAL);
+
+ bytes = fact & 0xffff;
+ count = (fact >> 16) & 0xffff;
+
+ if (count == 0)
+ count = MAX_SUB_BUFFERS;
+
+#if amancio
+ if (bytes < 4 || bytes > 17) /* <16 || > 128k */
+ return -(EINVAL);
+#endif
+
+ if (count < 2)
+ return -(EINVAL);
+
+#ifdef OS_DMA_MINBITS
+ if (bytes < OS_DMA_MINBITS)
+ bytes = OS_DMA_MINBITS;
+#endif
+
+ dmap->fragment_size = (1 << bytes);
+
+ dmap->max_fragments = count;
+
+ if (dmap->fragment_size > audio_devs[dev]->buffsize)
+ dmap->fragment_size = audio_devs[dev]->buffsize;
+
+ if (dmap->fragment_size == audio_devs[dev]->buffsize &&
+ audio_devs[dev]->flags & DMA_AUTOMODE)
+ dmap->fragment_size /= 2; /* Needs at least 2 buffers */
+
+ dmap->subdivision = 1; /* Disable SNDCTL_DSP_SUBDIVIDE */
+ return *(int *) arg = bytes | (count << 16);
+}
+
+static int
+get_buffer_pointer(int dev, int chan, struct dma_buffparms * dmap)
+{
+ int pos;
+ u_long flags;
+
+ flags = splhigh();
- if (p >= dmap->fragment_size)
- { /* This buffer is completely empty */
- dmap->counts[dmap->qhead] = 0;
- if (dmap->qlen <= 0 || dmap->qlen > dmap->nbufs)
- printk ("\nSound: Audio queue1 corrupted for dev%d (%d/%d)\n",
- dev, dmap->qlen, dmap->nbufs);
- dmap->qlen--;
- dmap->qhead = (dmap->qhead + 1) % dmap->nbufs;
+ if (!(dmap->flags & DMA_ACTIVE))
+ pos = 0;
+ else
+ {
+ pos = isa_dmastatus(chan);
}
+
+ splx(flags);
+
+ pos = dmap->bytes_in_use - pos ;
+ if (audio_devs[dev]->flags & DMA_AUTOMODE)
+ return pos;
else
- dmap->counts[dmap->qhead] = p;
+ {
+ pos = dmap->fragment_size - pos;
+ if (pos < 0)
+ return 0;
+ return pos;
+ }
+
- return 0;
}
int
-DMAbuf_ioctl (int dev, unsigned int cmd, unsigned int arg, int local)
+DMAbuf_ioctl(int dev, u_int cmd, ioctl_arg arg, int local)
{
- struct dma_buffparms *dmap = audio_devs[dev]->dmap;
+ struct dma_buffparms *dmap_out = audio_devs[dev]->dmap_out;
+ struct dma_buffparms *dmap_in = audio_devs[dev]->dmap_in;
+
+ switch (cmd) {
+
- switch (cmd)
- {
case SNDCTL_DSP_RESET:
- dma_reset (dev);
- return 0;
- break;
+ dma_reset(dev);
+ return 0;
+ break;
case SNDCTL_DSP_SYNC:
- dma_sync (dev);
- dma_reset (dev);
- return 0;
- break;
+ dma_sync(dev);
+ dma_reset(dev);
+ return 0;
+ break;
case SNDCTL_DSP_GETBLKSIZE:
- if (!(dmap->flags & DMA_ALLOC_DONE))
- reorganize_buffers (dev);
+ if (!(dmap_out->flags & DMA_ALLOC_DONE))
+ reorganize_buffers(dev, dmap_out);
- return IOCTL_OUT (arg, dmap->fragment_size);
- break;
+ return *(int *) arg = dmap_out->fragment_size;
+ break;
- case SNDCTL_DSP_SUBDIVIDE:
- {
- int fact = IOCTL_IN (arg);
+ case SNDCTL_DSP_SETBLKSIZE:
+ {
+ int size = (*(int *) arg);
- if (fact == 0)
- {
- fact = dmap->subdivision;
- if (fact == 0)
- fact = 1;
- return IOCTL_OUT (arg, fact);
- }
+ if (!(dmap_out->flags & DMA_ALLOC_DONE) && size) {
+ if ((size >> 16) > 0 )
+ dmap_out->fragment_size = size >> 16;
+ else {
+ dmap_out->fragment_size = size;
+ }
+ dmap_out->max_fragments = 8888;
+
+ size &= 0xffff;
- if (dmap->subdivision != 0 ||
- dmap->fragment_size)/* Loo late to change */
- return RET_ERROR (EINVAL);
+ if (audio_devs[dev]->flags & DMA_DUPLEX) {
+ dmap_in->fragment_size = size;
+ dmap_in->max_fragments = 8888;
+ }
+ return 0;
- if (fact > MAX_REALTIME_FACTOR)
- return RET_ERROR (EINVAL);
+ } else
+ return -(EINVAL); /* Too late to change */
+
+ }
+ break;
+
+ case SNDCTL_DSP_SUBDIVIDE:
+ {
+ int fact = (*(int *) arg);
+ int ret;
- if (fact != 1 && fact != 2 && fact != 4 && fact != 8 && fact != 16)
- return RET_ERROR (EINVAL);
+ ret = dma_subdivide(dev, dmap_out, arg, fact);
+ if (ret < 0)
+ return ret;
- dmap->subdivision = fact;
- return IOCTL_OUT (arg, fact);
- }
- break;
+ if (audio_devs[dev]->flags & DMA_DUPLEX)
+ ret = dma_subdivide(dev, dmap_in, arg, fact);
+
+ return ret;
+ }
+ break;
case SNDCTL_DSP_SETFRAGMENT:
- {
- int fact = IOCTL_IN (arg);
- int bytes, count;
+ {
+ int fact = (*(int *) arg);
+ int ret;
- if (fact == 0)
- return RET_ERROR (EIO);
+ ret = dma_set_fragment(dev, dmap_out, arg, fact);
+ if (ret < 0)
+ return ret;
- if (dmap->subdivision != 0 ||
- dmap->fragment_size)/* Loo late to change */
- return RET_ERROR (EINVAL);
+ if (audio_devs[dev]->flags & DMA_DUPLEX)
+ ret = dma_set_fragment(dev, dmap_in, arg, fact);
- bytes = fact & 0xffff;
- count = (fact >> 16) & 0xffff;
+ return ret;
+ }
+ break;
- if (count == 0)
- count = MAX_SUB_BUFFERS;
+ case SNDCTL_DSP_GETISPACE:
+ case SNDCTL_DSP_GETOSPACE:
+ if (!local)
+ return -(EINVAL);
+ else {
+ struct dma_buffparms *dmap = dmap_out;
- if (bytes < 7 || bytes > 17) /* <64 || > 128k */
- return RET_ERROR (EINVAL);
+ audio_buf_info *info = (audio_buf_info *) arg;
- if (count < 2)
- return RET_ERROR (EINVAL);
+ if (cmd == SNDCTL_DSP_GETISPACE && audio_devs[dev]->flags & DMA_DUPLEX)
+ dmap = dmap_in;
- dmap->fragment_size = (1 << bytes);
- dmap->max_fragments = count;
+#ifdef ALLOW_BUFFER_MAPPING
+ if (dmap->mapping_flags & DMA_MAP_MAPPED)
+ return -(EINVAL);
+#endif
- if (dmap->fragment_size > audio_devs[dev]->buffsize)
- dmap->fragment_size = audio_devs[dev]->buffsize;
+ if (!(dmap->flags & DMA_ALLOC_DONE))
+ reorganize_buffers(dev, dmap);
+
+ info->fragstotal = dmap->nbufs;
+
+ if (cmd == SNDCTL_DSP_GETISPACE)
+ info->fragments = dmap->qlen;
+ else {
+ if (!space_in_queue(dev))
+ info->fragments = 0;
+ else {
+ info->fragments = dmap->nbufs - dmap->qlen;
+ if (audio_devs[dev]->local_qlen) {
+ int tmp = audio_devs[dev]->local_qlen(dev);
+
+ if (tmp & info->fragments)
+ tmp--; /* This buffer has been counted twice */
+ info->fragments -= tmp;
+ }
+ }
+ }
- if (dmap->fragment_size == audio_devs[dev]->buffsize &&
- audio_devs[dev]->flags & DMA_AUTOMODE)
- dmap->fragment_size /= 2; /* Needs at least 2 buffers */
+ if (info->fragments < 0)
+ info->fragments = 0;
+ else if (info->fragments > dmap->nbufs)
+ info->fragments = dmap->nbufs;
- dmap->subdivision = 1; /* Disable SNDCTL_DSP_SUBDIVIDE */
- return IOCTL_OUT (arg, bytes | (count << 16));
- }
- break;
+ info->fragsize = dmap->fragment_size;
+ info->bytes = info->fragments * dmap->fragment_size;
+
+ if (cmd == SNDCTL_DSP_GETISPACE && dmap->qlen)
+ info->bytes -= dmap->counts[dmap->qhead];
+ }
+ return 0;
+
+ case SNDCTL_DSP_SETTRIGGER:
+ {
+ u_long flags;
+
+ int bits = (*(int *) arg) & audio_devs[dev]->open_mode;
+ int changed;
+
+ if (audio_devs[dev]->trigger == NULL)
+ return -(EINVAL);
+
+ if (!(audio_devs[dev]->flags & DMA_DUPLEX))
+ if ((bits & PCM_ENABLE_INPUT) && (bits & PCM_ENABLE_OUTPUT)) {
+ printf("Sound: Device doesn't have full duplex capability\n");
+ return -(EINVAL);
+ }
+ flags = splhigh();
+ changed = audio_devs[dev]->enable_bits ^ bits;
+
+ if ((changed & bits) & PCM_ENABLE_INPUT && audio_devs[dev]->go) {
+ if (!(dmap_in->flags & DMA_ALLOC_DONE))
+ reorganize_buffers(dev, dmap_in);
+ activate_recording(dev, dmap_in);
+ }
+#ifdef ALLOW_BUFFER_MAPPING
+ if ((changed & bits) & PCM_ENABLE_OUTPUT &&
+ dmap_out->mapping_flags & DMA_MAP_MAPPED &&
+ audio_devs[dev]->go) {
+ if (!(dmap_out->flags & DMA_ALLOC_DONE))
+ reorganize_buffers(dev, dmap_out);
+
+ audio_devs[dev]->prepare_for_output (dev,
+ dmap_out->fragment_size, dmap_out->nbufs);
+
+ dmap_out->counts[dmap_out->qhead] = dmap_out->fragment_size;
+ DMAbuf_start_output(dev, 0, dmap_out->fragment_size);
+ dmap_out->dma_mode = DMODE_OUTPUT;
+ }
+#endif
+
+ audio_devs[dev]->enable_bits = bits;
+ if (changed && audio_devs[dev]->trigger)
+ audio_devs[dev]->trigger(dev, bits * audio_devs[dev]->go);
+ splx(flags);
+ }
+ case SNDCTL_DSP_GETTRIGGER:
+ return *(int *) arg = audio_devs[dev]->enable_bits;
+ break;
+
+ case SNDCTL_DSP_SETSYNCRO:
+
+ if (!audio_devs[dev]->trigger)
+ return -(EINVAL);
+
+ audio_devs[dev]->trigger(dev, 0);
+ audio_devs[dev]->go = 0;
+ return 0;
+ break;
+
+ case SNDCTL_DSP_GETIPTR:
+ {
+ count_info info;
+ u_long flags;
+
+ flags = splhigh();
+ info.bytes = audio_devs[dev]->dmap_in->byte_counter;
+ info.ptr = get_buffer_pointer(dev, audio_devs[dev]->dmachan2, audio_devs[dev]->dmap_in);
+ info.blocks = audio_devs[dev]->dmap_in->qlen;
+ info.bytes += info.ptr;
+
+ bcopy((char *) &info, &(((char *) arg)[0]), sizeof(info));
+
+#ifdef ALLOW_BUFFER_MAPPING
+ if (audio_devs[dev]->dmap_in->mapping_flags & DMA_MAP_MAPPED)
+ audio_devs[dev]->dmap_in->qlen = 0; /* Ack interrupts */
+#endif
+ splx(flags);
+ return 0;
+ }
+ break;
+
+ case SNDCTL_DSP_GETOPTR:
+ {
+ count_info info;
+ u_long flags;
+
+ flags = splhigh();
+ info.bytes = audio_devs[dev]->dmap_out->byte_counter;
+ info.ptr = get_buffer_pointer(dev, audio_devs[dev]->dmachan1, audio_devs[dev]->dmap_out);
+ info.blocks = audio_devs[dev]->dmap_out->qlen;
+ info.bytes += info.ptr;
+ bcopy((char *) &info, &(((char *) arg)[0]), sizeof(info));
+
+#ifdef ALLOW_BUFFER_MAPPING
+ if (audio_devs[dev]->dmap_out->mapping_flags & DMA_MAP_MAPPED)
+ audio_devs[dev]->dmap_out->qlen = 0; /* Ack interrupts */
+#endif
+ splx(flags);
+ return 0;
+ }
+ break;
default:
- return audio_devs[dev]->ioctl (dev, cmd, arg, local);
+ return audio_devs[dev]->ioctl(dev, cmd, arg, local);
}
+}
- return RET_ERROR (EIO);
+/*
+ * DMAbuf_start_devices() is called by the /dev/music driver to start one or
+ * more audio devices at desired moment.
+ */
+
+void
+DMAbuf_start_devices(u_int devmask)
+{
+ int dev;
+
+ for (dev = 0; dev < num_audiodevs; dev++)
+ if (devmask & (1 << dev))
+ if (audio_devs[dev]->open_mode != 0)
+ if (!audio_devs[dev]->go) {
+ /* OK to start the device */
+ audio_devs[dev]->go = 1;
+
+ if (audio_devs[dev]->trigger)
+ audio_devs[dev]->trigger(dev,
+ audio_devs[dev]->enable_bits * audio_devs[dev]->go);
+ }
}
static int
-space_in_queue (int dev)
+space_in_queue(int dev)
{
- int len, max, tmp;
- struct dma_buffparms *dmap = audio_devs[dev]->dmap;
-
- if (dmap->qlen == dmap->nbufs)/* No space at all */
- return 0;
-
- /*
- * Verify that there are no more pending buffers than the limit
- * defined by the process.
- */
-
- max = dmap->max_fragments;
- len = dmap->qlen;
-
- if (audio_devs[dev]->local_qlen)
- {
- tmp = audio_devs[dev]->local_qlen (dev);
- if (tmp & len)
- tmp--; /*
- * This buffer has been counted twice
- */
- len += tmp;
+ int len, max, tmp;
+ struct dma_buffparms *dmap = audio_devs[dev]->dmap_out;
+ if (dmap->qlen >= dmap->nbufs) /* No space at all */
+ return 0;
+
+ /*
+ * Verify that there are no more pending buffers than the limit
+ * defined by the process.
+ */
+
+ max = dmap->max_fragments;
+ len = dmap->qlen;
+
+ if (audio_devs[dev]->local_qlen) {
+ tmp = audio_devs[dev]->local_qlen(dev);
+ if (tmp & len)
+ tmp--; /* This buffer has been counted twice */
+ len += tmp;
}
- if (len >= max)
- return 0;
- return 1;
+ if (len >= max)
+ return 0;
+ return 1;
}
int
-DMAbuf_getwrbuffer (int dev, char **buf, int *size)
+DMAbuf_getwrbuffer(int dev, char **buf, int *size, int dontblock)
{
- unsigned long flags;
- int abort, err = EIO;
- struct dma_buffparms *dmap = audio_devs[dev]->dmap;
-
- if (dmap->dma_mode == DMODE_INPUT) /* Direction change */
- {
- dma_reset (dev);
- dmap->dma_mode = DMODE_NONE;
- }
- else if (dmap->flags & DMA_RESTART) /* Restart buffering */
- {
- dma_sync (dev);
- dma_reset (dev);
+ u_long flags;
+ int abort, err = EIO;
+ struct dma_buffparms *dmap = audio_devs[dev]->dmap_out;
+
+#ifdef ALLOW_BUFFER_MAPPING
+ if (audio_devs[dev]->dmap_out->mapping_flags & DMA_MAP_MAPPED) {
+ printf("Sound: Can't write to mmapped device (3)\n");
+ return -(EINVAL);
}
+#endif
- dmap->flags &= ~DMA_RESTART;
+ if (dmap->dma_mode == DMODE_INPUT) { /* Direction change */
+ dma_reset(dev);
+ dmap->dma_mode = DMODE_NONE;
+ } else if (dmap->flags & DMA_RESTART) { /* Restart buffering */
+ dma_sync(dev);
+ dma_reset_output(dev);
+ }
+ dmap->flags &= ~DMA_RESTART;
- if (!(dmap->flags & DMA_ALLOC_DONE))
- reorganize_buffers (dev);
+ if (!(dmap->flags & DMA_ALLOC_DONE))
+ reorganize_buffers(dev, dmap);
- if (!dmap->dma_mode)
- {
- int err;
+ if (!dmap->dma_mode) {
+ int err;
- dmap->dma_mode = DMODE_OUTPUT;
- if ((err = audio_devs[dev]->prepare_for_output (dev,
- dmap->fragment_size, dmap->nbufs)) < 0)
- return err;
+ dmap->dma_mode = DMODE_OUTPUT;
+ if ((err = audio_devs[dev]->prepare_for_output(dev,
+ dmap->fragment_size, dmap->nbufs)) < 0)
+ return err;
}
+ flags = splhigh();
+ abort = 0;
+ while (!space_in_queue(dev) && !abort) {
+ int timeout;
- DISABLE_INTR (flags);
+ if (dontblock) {
+ splx(flags);
+ return -(EAGAIN);
+ }
+ if (!(audio_devs[dev]->enable_bits & PCM_ENABLE_OUTPUT) &&
+ audio_devs[dev]->go) {
+ splx(flags);
+ return -(EAGAIN);
+ }
+ /*
+ * Wait for free space
+ */
+ if (!audio_devs[dev]->go)
+ timeout = 0;
+ else
+ timeout = 2 * hz;
- abort = 0;
- while (!space_in_queue (dev) &&
- !abort)
- {
- /*
- * Wait for free space
- */
- DO_SLEEP (dev_sleeper[dev], dev_sleep_flag[dev], 2 * HZ);
- if (TIMED_OUT (dev_sleeper[dev], dev_sleep_flag[dev]))
{
- printk ("Sound: DMA timed out - IRQ/DRQ config error?\n");
- err = EIO;
- abort = 1;
- SET_ABORT_FLAG (dev_sleeper[dev], dev_sleep_flag[dev]);
+ int chn;
+
+ out_sleep_flag[dev].mode = WK_SLEEP;
+ out_sleeper[dev] = &chn;
+ DO_SLEEP2(chn, out_sleep_flag[dev], timeout);
+
+ if ((out_sleep_flag[dev].mode & WK_TIMEOUT)) {
+ printf("Sound: DMA (output) timed out - IRQ/DRQ config error?\n");
+ err = EIO;
+ abort = 1;
+ out_sleep_flag[dev].aborting = 1;
+ audio_devs[dev]->reset(dev);
+ } else if ((out_sleep_flag[dev].aborting) ||
+ CURSIG(curproc)) {
+ err = EINTR;
+ abort = 1;
}
- else if (PROCESS_ABORTING (dev_sleeper[dev], dev_sleep_flag[dev]))
- {
- err = EINTR;
- abort = 1;
}
}
- RESTORE_INTR (flags);
+ splx(flags);
- if (!space_in_queue (dev))
- {
- return RET_ERROR (err); /* Caught a signal ? */
+ if (!space_in_queue(dev)) {
+ return -(err); /* Caught a signal ? */
}
-
- *buf = dmap->buf[dmap->qtail];
- *size = dmap->fragment_size;
- dmap->counts[dmap->qtail] = 0;
-
- return dmap->qtail;
+ *buf = dmap->raw_buf + dmap->qtail * dmap->fragment_size;
+ *size = dmap->fragment_size;
+ dmap->counts[dmap->qtail] = 0;
+ return dmap->qtail;
}
int
-DMAbuf_start_output (int dev, int buff_no, int l)
+DMAbuf_start_output(int dev, int buff_no, int l)
{
- struct dma_buffparms *dmap = audio_devs[dev]->dmap;
+ struct dma_buffparms *dmap = audio_devs[dev]->dmap_out;
- if (buff_no != dmap->qtail)
- printk ("Sound warning: DMA buffers out of sync %d != %d\n", buff_no, dmap->qtail);
+ /*
+ * Bypass buffering if using mmaped access
+ */
- dmap->qlen++;
- if (dmap->qlen <= 0 || dmap->qlen > dmap->nbufs)
- printk ("\nSound: Audio queue2 corrupted for dev%d (%d/%d)\n",
- dev, dmap->qlen, dmap->nbufs);
+#ifdef ALLOW_BUFFER_MAPPING
+ if (audio_devs[dev]->dmap_out->mapping_flags & DMA_MAP_MAPPED) {
+ l = dmap->fragment_size;
+ dmap->counts[dmap->qtail] = l;
+ dmap->flags &= ~DMA_RESTART;
+ dmap->qtail = (dmap->qtail + 1) % dmap->nbufs;
+ } else
+#else
+ if (dmap != NULL)
+#endif
+ {
- dmap->counts[dmap->qtail] = l;
+ if (buff_no != dmap->qtail)
+ printf("Sound warning: DMA buffers out of sync %d != %d\n", buff_no, dmap->qtail);
- if ((l != dmap->fragment_size) &&
- ((audio_devs[dev]->flags & DMA_AUTOMODE) &&
- audio_devs[dev]->flags & NEEDS_RESTART))
- dmap->flags |= DMA_RESTART;
- else
- dmap->flags &= ~DMA_RESTART;
+ dmap->qlen++;
+ if (dmap->qlen <= 0 || dmap->qlen > dmap->nbufs)
+ printf("\nSound: Audio queue2 corrupted for dev%d (%d/%d)\n",
+ dev, dmap->qlen, dmap->nbufs);
- dmap->qtail = (dmap->qtail + 1) % dmap->nbufs;
+ dmap->counts[dmap->qtail] = l;
- if (!(dmap->flags & DMA_ACTIVE))
- {
- dmap->flags |= DMA_ACTIVE;
- audio_devs[dev]->output_block (dev, dmap->buf_phys[dmap->qhead],
- dmap->counts[dmap->qhead], 0,
- !(audio_devs[dev]->flags & DMA_AUTOMODE) ||
- !(dmap->flags & DMA_STARTED));
- dmap->flags |= DMA_STARTED;
- }
+ if ((l != dmap->fragment_size) &&
+ ((audio_devs[dev]->flags & DMA_AUTOMODE) &&
+ audio_devs[dev]->flags & NEEDS_RESTART))
+ dmap->flags |= DMA_RESTART;
+ else
+ dmap->flags &= ~DMA_RESTART;
- return 0;
+ dmap->qtail = (dmap->qtail + 1) % dmap->nbufs;
+ }
+ if (!(dmap->flags & DMA_ACTIVE)) {
+ dmap->flags |= DMA_ACTIVE;
+ audio_devs[dev]->output_block(dev, dmap->raw_buf_phys +
+ dmap->qhead * dmap->fragment_size,
+ dmap->counts[dmap->qhead], 0,
+ !(audio_devs[dev]->flags & DMA_AUTOMODE) ||
+ !(dmap->flags & DMA_STARTED));
+ dmap->flags |= DMA_STARTED;
+ if (audio_devs[dev]->trigger)
+ audio_devs[dev]->trigger(dev,
+ audio_devs[dev]->enable_bits * audio_devs[dev]->go);
+ }
+ return 0;
}
int
-DMAbuf_start_dma (int dev, unsigned long physaddr, int count, int dma_mode)
+DMAbuf_start_dma(int dev, u_long physaddr, int count, int dma_mode)
{
- int chan = audio_devs[dev]->dmachan;
- struct dma_buffparms *dmap = audio_devs[dev]->dmap;
- unsigned long flags;
+ int chan;
+ struct dma_buffparms *dmap;
- /*
- * This function is not as portable as it should be.
- */
+ if (dma_mode == 1) {
+ chan = audio_devs[dev]->dmachan1;
+ dmap = audio_devs[dev]->dmap_out;
- /*
- * The count must be one less than the actual size. This is handled by
- * set_dma_addr()
- */
+ } else {
+ chan = audio_devs[dev]->dmachan2;
+ dmap = audio_devs[dev]->dmap_in;
+ }
- if (audio_devs[dev]->flags & DMA_AUTOMODE)
- { /*
- * Auto restart mode. Transfer the whole *
- * buffer
- */
-#ifdef linux
- DISABLE_INTR (flags);
- disable_dma (chan);
- clear_dma_ff (chan);
- set_dma_mode (chan, dma_mode | DMA_AUTOINIT);
- set_dma_addr (chan, dmap->raw_buf_phys[0]);
- set_dma_count (chan, dmap->bytes_in_use);
- enable_dma (chan);
- RESTORE_INTR (flags);
-#else
+ /*
+ * The count must be one less than the actual size. This is handled
+ * by set_dma_addr()
+ */
-#ifdef __386BSD__
- printk ("sound: Invalid DMA mode for device %d\n", dev);
+#ifndef PSEUDO_DMA_AUTOINIT
+ if (audio_devs[dev]->flags & DMA_AUTOMODE) {
+ /* Auto restart mode. Transfer the whole buffer */
+ isa_dmastart(B_RAW | ((dma_mode == 0) ? B_READ : B_WRITE),
+ (caddr_t) dmap->raw_buf_phys, dmap->bytes_in_use, chan);
- isa_dmastart ((dma_mode == DMA_MODE_READ) ? B_READ : B_WRITE,
- dmap->raw_buf_phys[0],
- dmap->bytes_in_use,
- chan);
-#else
-#if defined(GENERIC_SYSV)
-#ifndef DMAMODE_AUTO
- printk ("sound: Invalid DMA mode for device %d\n", dev);
-#endif
- dma_param (chan, ((dma_mode == DMA_MODE_READ) ? DMA_Rdmode : DMA_Wrmode)
-#ifdef DMAMODE_AUTO
- | DMAMODE_AUTO
+ } else
#endif
- ,
- dmap->raw_buf_phys[0], dmap->bytes_in_use);
- dma_enable (chan);
-#else
-#error This routine is not valid for this OS.
+ {
+ isa_dmastart((dma_mode == 0) ? B_READ : B_WRITE,
+ (caddr_t) physaddr, count, chan);
+ }
+ return count;
+}
+
+void
+DMAbuf_init()
+{
+ int dev;
+
+ /*
+ * NOTE! This routine could be called several times.
+ * XXX is it ok to make it run only the first time ? -- lr970710
+ */
+
+ for (dev = 0; dev < num_audiodevs; dev++)
+ if (audio_devs[dev]->dmap_out == NULL) {
+ audio_devs[dev]->dmap_out =
+ audio_devs[dev]->dmap_in = &dmaps[ndmaps++];
+
+ if (audio_devs[dev]->flags & DMA_DUPLEX)
+ audio_devs[dev]->dmap_in = &dmaps[ndmaps++];
+ }
+}
+
+void
+DMAbuf_outputintr(int dev, int event_type)
+{
+ /*
+ * Event types: 0 = DMA transfer done. Device still has more data in
+ * the local buffer. 1 = DMA transfer done. Device doesn't have local
+ * buffer or it's empty now. 2 = No DMA transfer but the device has
+ * now more space in it's local buffer.
+ */
+
+ u_long flags;
+ struct dma_buffparms *dmap = audio_devs[dev]->dmap_out;
+ dmap->byte_counter += dmap->counts[dmap->qhead];
+#ifdef OS_DMA_INTR
+ sound_dma_intr(dev, audio_devs[dev]->dmap_out, audio_devs[dev]->dmachan1);
#endif
+#ifdef ALLOW_BUFFER_MAPPING
+ if (dmap->mapping_flags & DMA_MAP_MAPPED) {
+ /* mmapped access */
+
+ int p = dmap->fragment_size * dmap->qhead;
+
+ dmap->qhead = (dmap->qhead + 1) % dmap->nbufs;
+ dmap->qlen++; /* Yes increment it (don't decrement) */
+ dmap->flags &= ~DMA_ACTIVE;
+ dmap->counts[dmap->qhead] = dmap->fragment_size;
+
+ if (!(audio_devs[dev]->flags & DMA_AUTOMODE)) {
+ audio_devs[dev]->output_block(dev, dmap->raw_buf_phys +
+ dmap->qhead * dmap->fragment_size,
+ dmap->counts[dmap->qhead], 1,
+ !(audio_devs[dev]->flags & DMA_AUTOMODE));
+ if (audio_devs[dev]->trigger)
+ audio_devs[dev]->trigger(dev,
+ audio_devs[dev]->enable_bits * audio_devs[dev]->go);
+ }
+#ifdef PSEUDO_DMA_AUTOINIT
+ else {
+ DMAbuf_start_dma(dev, dmap->raw_buf_phys +
+ dmap->qhead * dmap->fragment_size,
+ dmap->counts[dmap->qhead], 1);
+ }
#endif
+ dmap->flags |= DMA_ACTIVE;
+ } else
#endif
- }
- else
- {
-#ifdef linux
- DISABLE_INTR (flags);
- disable_dma (chan);
- clear_dma_ff (chan);
- set_dma_mode (chan, dma_mode);
- set_dma_addr (chan, physaddr);
- set_dma_count (chan, count);
- enable_dma (chan);
- RESTORE_INTR (flags);
-#else
-#ifdef __386BSD__
- isa_dmastart ((dma_mode == DMA_MODE_READ) ? B_READ : B_WRITE,
- physaddr,
- count,
- chan);
-#else
+ if (event_type != 2) {
+ if (dmap->qlen <= 0 || dmap->qlen > dmap->nbufs) {
+ printf("\nSound: Audio queue3 corrupted for dev%d (%d/%d)\n",
+ dev, dmap->qlen, dmap->nbufs);
+ return;
+ }
+ isa_dmadone(0, 0, 0, audio_devs[dev]->dmachan1);
-#if defined(GENERIC_SYSV)
- 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 /* GENERIC_SYSV */
-#endif
+ dmap->qlen--;
+ dmap->qhead = (dmap->qhead + 1) % dmap->nbufs;
+ dmap->flags &= ~DMA_ACTIVE;
+ if (dmap->qlen) {
+ /* if (!(audio_devs[dev]->flags & NEEDS_RESTART)) */
+ {
+ audio_devs[dev]->output_block(dev, dmap->raw_buf_phys +
+ dmap->qhead * dmap->fragment_size,
+ dmap->counts[dmap->qhead], 1,
+ !(audio_devs[dev]->flags & DMA_AUTOMODE));
+ if (audio_devs[dev]->trigger)
+ audio_devs[dev]->trigger(dev,
+ audio_devs[dev]->enable_bits * audio_devs[dev]->go);
+ }
+#ifdef PSEUDO_DMA_AUTOINIT
+ /* else */
+ {
+ DMAbuf_start_dma(dev, dmap->raw_buf_phys +
+ dmap->qhead * dmap->fragment_size,
+ dmap->counts[dmap->qhead], 1);
+ }
#endif
- }
-
- return count;
-}
+ dmap->flags |= DMA_ACTIVE;
+ } else if (event_type == 1) {
+ dmap->underrun_count++;
+ if ((audio_devs[dev]->flags & DMA_DUPLEX) &&
+ audio_devs[dev]->halt_output)
+ audio_devs[dev]->halt_output(dev);
+ else
+ audio_devs[dev]->halt_xfer(dev);
+
+ if ((audio_devs[dev]->flags & DMA_AUTOMODE) &&
+ audio_devs[dev]->flags & NEEDS_RESTART)
+ dmap->flags |= DMA_RESTART;
+ else
+ dmap->flags &= ~DMA_RESTART;
+ }
+ } /* event_type != 2 */
+ flags = splhigh();
-long
-DMAbuf_init (long mem_start)
-{
- int dev;
+ if ((out_sleep_flag[dev].mode & WK_SLEEP)) {
+ out_sleep_flag[dev].mode = WK_WAKEUP;
+ wakeup(out_sleeper[dev]);
+ }
- /*
- * NOTE! This routine could be called several times.
- */
+ if(selinfo[dev].si_pid) {
+ selwakeup(&selinfo[dev]);
+ }
- for (dev = 0; dev < num_audiodevs; dev++)
- audio_devs[dev]->dmap = &dmaps[dev];
- return mem_start;
+ splx(flags);
}
void
-DMAbuf_outputintr (int dev, int event_type)
-{
- /*
- * Event types:
- * 0 = DMA transfer done. Device still has more data in the local
- * buffer.
- * 1 = DMA transfer done. Device doesn't have local buffer or it's
- * empty now.
- * 2 = No DMA transfer but the device has now more space in it's local
- * buffer.
- */
+DMAbuf_inputintr(int dev)
+{
+ u_long flags;
+ struct dma_buffparms *dmap = audio_devs[dev]->dmap_in;
- unsigned long flags;
- struct dma_buffparms *dmap = audio_devs[dev]->dmap;
+ dmap->byte_counter += dmap->fragment_size;
- if (event_type != 2)
- {
- if (dmap->qlen <= 0 || dmap->qlen > dmap->nbufs)
- {
- printk ("\nSound: Audio queue3 corrupted for dev%d (%d/%d)\n",
- dev, dmap->qlen, dmap->nbufs);
- return;
+#ifdef OS_DMA_INTR
+ sound_dma_intr(dev, audio_devs[dev]->dmap_in, audio_devs[dev]->dmachan2);
+#endif
+ isa_dmadone(0, 0, 0, audio_devs[dev]->dmachan2);
+
+#ifdef ALLOW_BUFFER_MAPPING
+ if (dmap->mapping_flags & DMA_MAP_MAPPED) {
+ dmap->qtail = (dmap->qtail + 1) % dmap->nbufs;
+ dmap->qlen++;
+
+ if (!(audio_devs[dev]->flags & NEEDS_RESTART)) {
+ audio_devs[dev]->start_input(dev, dmap->raw_buf_phys +
+ dmap->qtail * dmap->fragment_size,
+ dmap->fragment_size, 1,
+ !(audio_devs[dev]->flags & DMA_AUTOMODE));
+ if (audio_devs[dev]->trigger)
+ audio_devs[dev]->trigger(dev,
+ audio_devs[dev]->enable_bits * audio_devs[dev]->go);
}
+#ifdef PSEUDO_DMA_AUTOINIT
+ else {
+ DMAbuf_start_dma(dev, dmap->raw_buf_phys +
+ dmap->qtail * dmap->fragment_size,
+ dmap->counts[dmap->qtail], 0);
+ }
+#endif
- dmap->qlen--;
- dmap->qhead = (dmap->qhead + 1) % dmap->nbufs;
- dmap->flags &= ~DMA_ACTIVE;
-
- if (dmap->qlen)
+ dmap->flags |= DMA_ACTIVE;
+ } else
+#endif
+ if (dmap->qlen == (dmap->nbufs - 1)) {
+ /* printf ("Sound: Recording overrun\n"); */
+ dmap->underrun_count++;
+ if ((audio_devs[dev]->flags & DMA_DUPLEX) &&
+ audio_devs[dev]->halt_input)
+ audio_devs[dev]->halt_input(dev);
+ else
+ audio_devs[dev]->halt_xfer(dev);
+
+ dmap->flags &= ~DMA_ACTIVE;
+ if (audio_devs[dev]->flags & DMA_AUTOMODE)
+ dmap->flags |= DMA_RESTART;
+ else
+ dmap->flags &= ~DMA_RESTART;
+ } else {
+ dmap->qlen++;
+ if (dmap->qlen <= 0 || dmap->qlen > dmap->nbufs)
+ printf("\nSound: Audio queue4 corrupted for dev%d (%d/%d)\n",
+ dev, dmap->qlen, dmap->nbufs);
+ dmap->qtail = (dmap->qtail + 1) % dmap->nbufs;
+
+ /* if (!(audio_devs[dev]->flags & DMA_AUTOMODE)) */
{
- audio_devs[dev]->output_block (dev, dmap->buf_phys[dmap->qhead],
- dmap->counts[dmap->qhead], 1,
- !(audio_devs[dev]->flags & DMA_AUTOMODE));
- dmap->flags |= DMA_ACTIVE;
+ audio_devs[dev]->start_input(dev, dmap->raw_buf_phys +
+ dmap->qtail * dmap->fragment_size,
+ dmap->fragment_size, 1,
+ !(audio_devs[dev]->flags & DMA_AUTOMODE));
+ if (audio_devs[dev]->trigger)
+ audio_devs[dev]->trigger(dev,
+ audio_devs[dev]->enable_bits * audio_devs[dev]->go);
}
- else if (event_type == 1)
+#ifdef PSEUDO_DMA_AUTOINIT
+ /* else */
{
- dmap->underrun_count++;
- audio_devs[dev]->halt_xfer (dev);
- if ((audio_devs[dev]->flags & DMA_AUTOMODE) &&
- audio_devs[dev]->flags & NEEDS_RESTART)
- dmap->flags |= DMA_RESTART;
- else
- dmap->flags &= ~DMA_RESTART;
+ DMAbuf_start_dma(dev, dmap->raw_buf_phys +
+ dmap->qtail * dmap->fragment_size,
+ dmap->counts[dmap->qtail], 0);
}
- } /* event_type != 2 */
+#endif
- DISABLE_INTR (flags);
- if (SOMEONE_WAITING (dev_sleeper[dev], dev_sleep_flag[dev]))
- {
- WAKE_UP (dev_sleeper[dev], dev_sleep_flag[dev]);
+ dmap->flags |= DMA_ACTIVE;
+ }
+
+ flags = splhigh();
+ if ((in_sleep_flag[dev].mode & WK_SLEEP)) {
+ in_sleep_flag[dev].mode = WK_WAKEUP;
+ wakeup(in_sleeper[dev]);
}
- RESTORE_INTR (flags);
+ if (selinfo[dev].si_pid)
+ selwakeup(&selinfo[dev]);
+ splx(flags);
+}
+
+int
+DMAbuf_open_dma(int dev)
+{
+ int err;
+ u_long flags;
+ flags = splhigh();
+
+ if ((err = open_dmap(dev, OPEN_READWRITE, audio_devs[dev]->dmap_out,
+ audio_devs[dev]->dmachan1)) < 0) {
+ splx(flags);
+ return -(EBUSY);
+ }
+ dma_init_buffers(dev, audio_devs[dev]->dmap_out);
+ /* audio_devs[dev]->dmap_out->flags |= DMA_ALLOC_DONE; */
+ audio_devs[dev]->dmap_out->fragment_size = audio_devs[dev]->buffsize;
+ /* reorganize_buffers (dev, audio_devs[dev]->dmap_out); */
+
+ if (audio_devs[dev]->flags & DMA_DUPLEX) {
+ if ((err = open_dmap(dev, OPEN_READWRITE,
+ audio_devs[dev]->dmap_in, audio_devs[dev]->dmachan2)) < 0) {
+ printf("Unable to grab DMA%d for the audio driver\n",
+ audio_devs[dev]->dmachan2);
+ close_dmap(dev, audio_devs[dev]->dmap_out,
+ audio_devs[dev]->dmachan1);
+ splx(flags);
+ return -(EBUSY);
+ }
+ dma_init_buffers(dev, audio_devs[dev]->dmap_in);
+ /* audio_devs[dev]->dmap_in->flags |= DMA_ALLOC_DONE; */
+ audio_devs[dev]->dmap_in->fragment_size = audio_devs[dev]->buffsize;
+ /* reorganize_buffers (dev, audio_devs[dev]->dmap_in); */
+ } else {
+ audio_devs[dev]->dmap_in = audio_devs[dev]->dmap_out;
+ audio_devs[dev]->dmachan2 = audio_devs[dev]->dmachan1;
+ }
+
+ splx(flags);
+ return 0;
}
void
-DMAbuf_inputintr (int dev)
+DMAbuf_close_dma(int dev)
{
- unsigned long flags;
- struct dma_buffparms *dmap = audio_devs[dev]->dmap;
+ DMAbuf_reset_dma(dev);
+ close_dmap(dev, audio_devs[dev]->dmap_out, audio_devs[dev]->dmachan1);
- if (dmap->qlen == (dmap->nbufs - 1))
- {
- printk ("Sound: Recording overrun\n");
- dmap->underrun_count++;
- audio_devs[dev]->halt_xfer (dev);
- dmap->flags &= ~DMA_ACTIVE;
- if (audio_devs[dev]->flags & DMA_AUTOMODE)
- dmap->flags |= DMA_RESTART;
- else
- dmap->flags &= ~DMA_RESTART;
- }
- else
- {
- dmap->qlen++;
- if (dmap->qlen <= 0 || dmap->qlen > dmap->nbufs)
- printk ("\nSound: Audio queue4 corrupted for dev%d (%d/%d)\n",
- dev, dmap->qlen, dmap->nbufs);
- dmap->qtail = (dmap->qtail + 1) % dmap->nbufs;
+ if (audio_devs[dev]->flags & DMA_DUPLEX)
+ close_dmap(dev, audio_devs[dev]->dmap_in, audio_devs[dev]->dmachan2);
- audio_devs[dev]->start_input (dev, dmap->buf_phys[dmap->qtail],
- dmap->fragment_size, 1,
- !(audio_devs[dev]->flags & DMA_AUTOMODE));
- dmap->flags |= DMA_ACTIVE;
- }
+}
- DISABLE_INTR (flags);
- if (SOMEONE_WAITING (dev_sleeper[dev], dev_sleep_flag[dev]))
- {
- WAKE_UP (dev_sleeper[dev], dev_sleep_flag[dev]);
- }
- RESTORE_INTR (flags);
+void
+DMAbuf_reset_dma(int dev)
+{
}
+#ifdef ALLOW_POLL
+
int
-DMAbuf_open_dma (int dev)
+DMAbuf_poll(int dev, struct fileinfo * file, int events, select_table * wait)
{
- unsigned long flags;
- int chan = audio_devs[dev]->dmachan;
+ struct dma_buffparms *dmap;
+ u_long flags;
+ int revents = 0;
+
+ dmap = audio_devs[dev]->dmap_in;
+
+ if (events & (POLLIN | POLLRDNORM)) {
+ if (dmap->dma_mode != DMODE_INPUT) {
+ if ((audio_devs[dev]->flags & DMA_DUPLEX) && !dmap->qlen &&
+ audio_devs[dev]->enable_bits & PCM_ENABLE_INPUT &&
+ audio_devs[dev]->go) {
+ u_long flags;
+
+ flags = splhigh();
+
+ activate_recording(dev, dmap);
+ splx(flags);
+
+ }
+ return 0;
+ }
+ if (!dmap->qlen) {
+ flags = splhigh();
+
+ selrecord(wait, &selinfo[dev]);
+
+ splx(flags);
+
+ return 0;
+ } else
+ revents |= events & (POLLIN | POLLRDNORM);
- if (ALLOC_DMA_CHN (chan))
- {
- printk ("Unable to grab DMA%d for the audio driver\n", chan);
- return RET_ERROR (EBUSY);
}
- DISABLE_INTR (flags);
-#ifdef linux
- disable_dma (chan);
- clear_dma_ff (chan);
-#endif
- RESTORE_INTR (flags);
+ if (events & (POLLOUT | POLLWRNORM)) {
+
+ dmap = audio_devs[dev]->dmap_out;
+ if (dmap->dma_mode == DMODE_INPUT)
+ return 0;
+
+ if (dmap->dma_mode == DMODE_NONE)
+ return ( events & (POLLOUT | POLLWRNORM));
+
+ if (dmap->mapping_flags & DMA_MAP_MAPPED) {
+
+ if(dmap->qlen)
+ return 1;
+ flags = splhigh();
+ selrecord(wait, &selinfo[dev]);
+
+ splx(flags);
+
+ return 0;
+
+ }
+ if (!space_in_queue(dev)) {
+ flags = splhigh();
+ selrecord(wait, &selinfo[dev]);
+ splx(flags);
- return 0;
-}
+ } else
+ revents |= events & (POLLOUT | POLLWRNORM);
-void
-DMAbuf_close_dma (int dev)
-{
- int chan = audio_devs[dev]->dmachan;
- DMAbuf_reset_dma (chan);
- RELEASE_DMA_CHN (chan);
+ }
+
+ return (revents);
}
-void
-DMAbuf_reset_dma (int chan)
+
+#ifdef amancio
+int
+DMAbuf_select(int dev, struct fileinfo * file, int sel_type, select_table * wait)
{
+ struct dma_buffparms *dmap = audio_devs[dev]->dmap_out;
+ struct dma_buffparms *dmapin = audio_devs[dev]->dmap_in;
+ u_long flags;
+
+ switch (sel_type) {
+ case FREAD:
+ if (dmapin->dma_mode != DMODE_INPUT)
+ return 0;
+
+ if (!dmap->qlen) {
+ flags = splhigh();
+ selrecord(wait, &selinfo[dev]);
+ splx(flags);
+
+ return 0;
+ }
+ return 1;
+ break;
+
+ case FWRITE:
+ if (dmap->dma_mode == DMODE_INPUT)
+ return 0;
+
+ if (dmap->dma_mode == DMODE_NONE)
+ return 1;
+
+ if (!space_in_queue(dev)) {
+ flags = splhigh();
+
+ selrecord(wait, &selinfo[dev]);
+ splx(flags);
+
+ return 0;
+ }
+ return 1;
+ break;
+
+ }
+
+ return 0;
}
-/*
- * 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.
- */
+#endif /* ALLOW_POLL */
+#endif
-#else
+#else /* CONFIG_AUDIO */
/*
* Stub versions if audio services not included
*/
int
-DMAbuf_open (int dev, int mode)
+DMAbuf_open(int dev, int mode)
{
- return RET_ERROR (ENXIO);
+ return -(ENXIO);
}
int
-DMAbuf_release (int dev, int mode)
+DMAbuf_release(int dev, int mode)
{
- return 0;
+ return 0;
}
int
-DMAbuf_getwrbuffer (int dev, char **buf, int *size)
+DMAbuf_getwrbuffer(int dev, char **buf, int *size, int dontblock)
{
- return RET_ERROR (EIO);
+ return -(EIO);
}
int
-DMAbuf_getrdbuffer (int dev, char **buf, int *len)
+DMAbuf_getrdbuffer(int dev, char **buf, int *len, int dontblock)
{
- return RET_ERROR (EIO);
+ return -(EIO);
}
int
-DMAbuf_rmchars (int dev, int buff_no, int c)
+DMAbuf_rmchars(int dev, int buff_no, int c)
{
- return RET_ERROR (EIO);
+ return -(EIO);
}
int
-DMAbuf_start_output (int dev, int buff_no, int l)
+DMAbuf_start_output(int dev, int buff_no, int l)
{
- return RET_ERROR (EIO);
+ return -(EIO);
}
int
-DMAbuf_ioctl (int dev, unsigned int cmd, unsigned int arg, int local)
+DMAbuf_ioctl(int dev, u_int cmd, ioctl_arg arg, int local)
{
- return RET_ERROR (EIO);
+ return -(EIO);
}
-long
-DMAbuf_init (long mem_start)
+void
+DMAbuf_init()
{
- return mem_start;
}
int
-DMAbuf_start_dma (int dev, unsigned long physaddr, int count, int dma_mode)
+DMAbuf_start_dma(int dev, u_long physaddr, int count, int dma_mode)
{
- return RET_ERROR (EIO);
+ return -(EIO);
}
int
-DMAbuf_open_dma (int chan)
+DMAbuf_open_dma(int dev)
{
- return RET_ERROR (ENXIO);
+ return -(ENXIO);
}
void
-DMAbuf_close_dma (int chan)
+DMAbuf_close_dma(int dev)
{
- return;
+ return;
}
void
-DMAbuf_reset_dma (int chan)
+DMAbuf_reset_dma(int dev)
{
- return;
+ return;
}
void
-DMAbuf_inputintr (int dev)
+DMAbuf_inputintr(int dev)
{
- return;
+ return;
}
void
-DMAbuf_outputintr (int dev, int underrun_flag)
+DMAbuf_outputintr(int dev, int underrun_flag)
{
- return;
+ return;
}
-
-#endif
-
-#endif
+#endif /* CONFIG_AUDIO */
diff --git a/sys/i386/isa/sound/gus_card.c b/sys/i386/isa/sound/gus_card.c
index 614532c7d114..2f73ce61c72c 100644
--- a/sys/i386/isa/sound/gus_card.c
+++ b/sys/i386/isa/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,143 +24,138 @@
* 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"
+#include <i386/isa/sound/sound_config.h>
-#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_GUS)
+#if defined(CONFIG_GUS)
-#include "gus_hw.h"
-
-void gusintr (int);
+#include <i386/isa/sound/gus_hw.h>
+#include <i386/isa/sound/iwdefs.h>
int gus_base, gus_irq, gus_dma;
extern int gus_wave_volume;
extern int gus_pcm_volume;
extern int have_gus_max;
+extern int gus_timer_enabled;
+
+sound_os_info *gus_osp;
+
+#ifndef NOGUSPNP
+int IwaveOpen(char voices, char mode, struct address_info * hw);
+#endif
-long
-attach_gus_card (long mem_start, struct address_info *hw_config)
+void
+attach_gus_card(struct address_info * hw_config)
{
- int io_addr;
+ int io_addr;
- snd_set_irq_handler (hw_config->irq, gusintr);
+ gus_osp = hw_config->osp;
- if (gus_wave_detect (hw_config->io_base)) /*
- * Try first the default
- */
- {
- mem_start = gus_wave_init (mem_start, hw_config->irq, hw_config->dma);
-#ifndef EXCLUDE_MIDI
- mem_start = gus_midi_init (mem_start);
-#endif
-#ifndef EXCLUDE_SEQUENCER
- sound_timer_init (hw_config->io_base + 8);
+ snd_set_irq_handler(hw_config->irq, gusintr, hw_config->osp);
+
+ if (gus_wave_detect(hw_config->io_base)) {
+ /* Try first the default */
+ gus_wave_init(hw_config);
+
+ /* 0x10c-> is MAX */
+
+ if (hw_config->dma2 != -1 && hw_config->dma2 != hw_config->dma)
+ if (0)
+ printf("gus_card.c: Can't allocate DMA channel2\n");
+#ifdef CONFIG_MIDI
+ gus_midi_init();
#endif
- return mem_start;
+ return ;
}
-
#ifndef EXCLUDE_GUS_IODETECT
- /*
- * Look at the possible base addresses (0x2X0, X=1, 2, 3, 4, 5, 6)
- */
-
- for (io_addr = 0x210; io_addr <= 0x260; io_addr += 0x10)
- if (io_addr != hw_config->io_base) /*
- * Already tested
- */
- if (gus_wave_detect (io_addr))
- {
- printk (" WARNING! GUS found at %x, config was %x ", io_addr, hw_config->io_base);
- mem_start = gus_wave_init (mem_start, hw_config->irq, hw_config->dma);
-#ifndef EXCLUDE_MIDI
- mem_start = gus_midi_init (mem_start);
+ /*
+ * Look at the possible base addresses (0x2X0, X=1, 2, 3, 4, 5, 6)
+ */
+
+ for (io_addr = 0x210; io_addr <= 0x260; io_addr += 0x10)
+ if ( (io_addr != hw_config->io_base) /* Already tested */
+ && (gus_wave_detect(io_addr)) ) {
+ hw_config->io_base = io_addr;
+
+ printf(" WARNING! GUS found at %x, config was %x ",
+ io_addr, hw_config->io_base);
+ gus_wave_init(hw_config);
+ /* 0x10c-> is MAX */
+ if (hw_config->dma2 != -1 && hw_config->dma2 != hw_config->dma)
+ if (0)
+ printf("gus_card.c: Can't allocate DMA channel2\n");
+#ifdef CONFIG_MIDI
+ gus_midi_init();
#endif
-#ifndef EXCLUDE_SEQUENCER
- sound_timer_init (io_addr + 8);
-#endif
- return mem_start;
+ return ;
}
-
#endif
-
- return mem_start; /*
- * Not detected
- */
}
int
-probe_gus (struct address_info *hw_config)
+probe_gus(struct address_info * hw_config)
{
- int io_addr;
-
- if (gus_wave_detect (hw_config->io_base))
- return 1;
+ int io_addr;
-#ifndef EXCLUDE_GUS_IODETECT
-
- /*
- * Look at the possible base addresses (0x2X0, X=1, 2, 3, 4, 5, 6)
- */
-
- for (io_addr = 0x210; io_addr <= 0x260; io_addr += 0x10)
- if (io_addr != hw_config->io_base) /*
- * Already tested
- */
- if (gus_wave_detect (io_addr))
+ gus_osp = hw_config->osp;
+#ifndef NOGUSPNP
+ IwaveOpen((char) 32, (char) GUS_MODE, hw_config);
+#endif
+ if (gus_wave_detect(hw_config->io_base))
return 1;
+ printf("oops I didnt find gus \n");
+#undef EXCLUDE_GUS_IODETECT
+#ifndef EXCLUDE_GUS_IODETECT
+ /*
+ * Look at the possible base addresses (0x2X0, X=1, 2, 3, 4, 5, 6)
+ */
+ for (io_addr = 0x210; io_addr <= 0x260; io_addr += 0x10)
+ if ( (io_addr != hw_config->io_base) /* Already tested */
+ && (gus_wave_detect(io_addr)) ) {
+ hw_config->io_base = io_addr;
+ return 1;
+ }
#endif
- return 0;
+ return 0;
}
void
-gusintr (int irq)
+gusintr(int irq)
{
- unsigned char src;
-
-#ifdef linux
- sti ();
-#endif
+ u_char src;
-#ifndef EXCLUDE_GUSMAX
- if (have_gus_max)
- ad1848_interrupt (irq);
+#ifdef CONFIG_GUSMAX
+ if (have_gus_max)
+ ad1848_interrupt(irq);
#endif
- while (1)
- {
- if (!(src = INB (u_IrqStatus)))
- return;
+ for (;;) {
+ if (!(src = inb(u_IrqStatus)))
+ return;
- if (src & DMA_TC_IRQ)
- {
- guswave_dma_irq ();
- }
-
- if (src & (MIDI_TX_IRQ | MIDI_RX_IRQ))
- {
-#ifndef EXCLUDE_MIDI
- gus_midi_interrupt (0);
+ if (src & DMA_TC_IRQ)
+ guswave_dma_irq();
+#ifdef CONFIG_MIDI
+ if (src & (MIDI_TX_IRQ | MIDI_RX_IRQ))
+ gus_midi_interrupt(0);
#endif
- }
-
- if (src & (GF1_TIMER1_IRQ | GF1_TIMER2_IRQ))
- {
-#ifndef EXCLUDE_SEQUENCER
- sound_timer_interrupt ();
+ if (src & (GF1_TIMER1_IRQ | GF1_TIMER2_IRQ)) {
+#ifdef CONFIG_SEQUENCER
+ if (gus_timer_enabled)
+ sound_timer_interrupt();
+ gus_write8(0x45, 0); /* Ack IRQ */
+ gus_timer_command(4, 0x80); /* Reset IRQ flags */
#else
- gus_write8 (0x45, 0); /* Stop timers */
+ gus_write8(0x45, 0); /* Stop timers */
#endif
}
-
- if (src & (WAVETABLE_IRQ | ENVELOPE_IRQ))
- {
- gus_voice_irq ();
- }
+ if (src & (WAVETABLE_IRQ | ENVELOPE_IRQ))
+ gus_voice_irq();
}
}
@@ -169,25 +164,25 @@ gusintr (int irq)
/*
* Some extra code for the 16 bit sampling option
*/
-#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_GUS16)
+#if defined(CONFIG_GUS16)
int
-probe_gus_db16 (struct address_info *hw_config)
+probe_gus_db16(struct address_info * hw_config)
{
- return ad1848_detect (hw_config->io_base);
+ return ad1848_detect(hw_config->io_base, NULL, hw_config->osp);
}
-long
-attach_gus_db16 (long mem_start, struct address_info *hw_config)
+void
+attach_gus_db16(struct address_info * hw_config)
{
- gus_pcm_volume = 100;
- gus_wave_volume = 90;
-
- ad1848_init ("GUS 16 bit sampling", hw_config->io_base,
- hw_config->irq,
- hw_config->dma,
- hw_config->dma);
- return mem_start;
+ gus_pcm_volume = 100;
+ gus_wave_volume = 90;
+
+ ad1848_init("GUS 16 bit sampling", hw_config->io_base,
+ hw_config->irq,
+ hw_config->dma,
+ hw_config->dma, 0,
+ hw_config->osp);
}
#endif
diff --git a/sys/i386/isa/sound/gus_midi.c b/sys/i386/isa/sound/gus_midi.c
index 87aea6251daf..0dfc7c502a33 100644
--- a/sys/i386/isa/sound/gus_midi.c
+++ b/sys/i386/isa/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,16 +24,13 @@
* 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"
+#include <i386/isa/sound/sound_config.h>
-#ifdef CONFIGURE_SOUNDCARD
-
-#include "gus_hw.h"
-
-#if !defined(EXCLUDE_GUS) && !defined(EXCLUDE_MIDI)
+#if defined(CONFIG_GUS) && defined(CONFIG_MIDI)
+#include <i386/isa/sound/gus_hw.h>
static int midi_busy = 0, input_opened = 0;
static int my_dev;
@@ -46,264 +43,232 @@ static unsigned char tmp_queue[256];
static volatile int qlen;
static volatile unsigned char qhead, qtail;
extern int gus_base, gus_irq, gus_dma;
+extern sound_os_info *gus_osp;
-#define GUS_MIDI_STATUS() INB(u_MidiStatus)
+#define GUS_MIDI_STATUS() inb( u_MidiStatus)
static int
-gus_midi_open (int dev, int mode,
- void (*input) (int dev, unsigned char data),
- void (*output) (int dev)
+gus_midi_open(int dev, int mode,
+ void (*input) (int dev, unsigned char data),
+ void (*output) (int dev)
)
{
- if (midi_busy)
- {
- printk ("GUS: Midi busy\n");
- return RET_ERROR (EBUSY);
- }
-
- OUTB (MIDI_RESET, u_MidiControl);
- gus_delay ();
-
- gus_midi_control = 0;
- input_opened = 0;
-
- if (mode == OPEN_READ || mode == OPEN_READWRITE)
- {
- gus_midi_control |= MIDI_ENABLE_RCV;
- input_opened = 1;
- }
+ if (midi_busy) {
+ printf("GUS: Midi busy\n");
+ return -(EBUSY);
+ }
+ outb(u_MidiControl, MIDI_RESET);
+ gus_delay();
- if (mode == OPEN_WRITE || mode == OPEN_READWRITE)
- {
- gus_midi_control |= MIDI_ENABLE_XMIT;
- }
+ gus_midi_control = 0;
+ input_opened = 0;
- OUTB (gus_midi_control, u_MidiControl); /*
- * Enable
- */
+ if (mode == OPEN_READ || mode == OPEN_READWRITE) {
+ gus_midi_control |= MIDI_ENABLE_RCV;
+ input_opened = 1;
+ }
+ if (mode == OPEN_WRITE || mode == OPEN_READWRITE) {
+ gus_midi_control |= MIDI_ENABLE_XMIT;
+ }
+ outb(u_MidiControl, gus_midi_control); /* Enable */
- midi_busy = 1;
- qlen = qhead = qtail = output_used = 0;
- midi_input_intr = input;
+ midi_busy = 1;
+ qlen = qhead = qtail = output_used = 0;
+ midi_input_intr = input;
- return 0;
+ return 0;
}
static int
-dump_to_midi (unsigned char midi_byte)
+dump_to_midi(unsigned char midi_byte)
{
- unsigned long flags;
- int ok = 0;
-
- output_used = 1;
-
- DISABLE_INTR (flags);
-
- if (GUS_MIDI_STATUS () & MIDI_XMIT_EMPTY)
- {
- ok = 1;
- OUTB (midi_byte, u_MidiData);
- }
- else
- {
- /*
- * Enable Midi xmit interrupts (again)
- */
- gus_midi_control |= MIDI_ENABLE_XMIT;
- OUTB (gus_midi_control, u_MidiControl);
- }
-
- RESTORE_INTR (flags);
- return ok;
+ unsigned long flags;
+ int ok = 0;
+
+ output_used = 1;
+
+ flags = splhigh();
+
+ if (GUS_MIDI_STATUS() & MIDI_XMIT_EMPTY) {
+ ok = 1;
+ outb(u_MidiData, midi_byte);
+ } else {
+ /*
+ * Enable Midi xmit interrupts (again)
+ */
+ gus_midi_control |= MIDI_ENABLE_XMIT;
+ outb(u_MidiControl, gus_midi_control);
+ }
+
+ splx(flags);
+ return ok;
}
static void
-gus_midi_close (int dev)
+gus_midi_close(int dev)
{
- /*
- * Reset FIFO pointers, disable intrs
- */
+ /*
+ * Reset FIFO pointers, disable intrs
+ */
- OUTB (MIDI_RESET, u_MidiControl);
- midi_busy = 0;
+ outb(u_MidiControl, MIDI_RESET);
+ midi_busy = 0;
}
static int
-gus_midi_out (int dev, unsigned char midi_byte)
+gus_midi_out(int dev, unsigned char midi_byte)
{
- unsigned long flags;
+ unsigned long flags;
- /*
- * Drain the local queue first
- */
+ /*
+ * Drain the local queue first
+ */
- DISABLE_INTR (flags);
+ flags = splhigh();
- while (qlen && dump_to_midi (tmp_queue[qhead]))
- {
- qlen--;
- qhead++;
- }
+ while (qlen && dump_to_midi(tmp_queue[qhead])) {
+ qlen--;
+ qhead++;
+ }
- RESTORE_INTR (flags);
+ splx(flags);
- /*
- * Output the byte if the local queue is empty.
- */
+ /*
+ * Output the byte if the local queue is empty.
+ */
- if (!qlen)
- if (dump_to_midi (midi_byte))
- return 1; /*
- * OK
- */
+ if (!qlen)
+ if (dump_to_midi(midi_byte))
+ return 1; /* OK */
- /*
- * Put to the local queue
- */
+ /*
+ * Put to the local queue
+ */
- if (qlen >= 256)
- return 0; /*
- * Local queue full
- */
+ if (qlen >= 256)
+ return 0; /* Local queue full */
- DISABLE_INTR (flags);
+ flags = splhigh();
- tmp_queue[qtail] = midi_byte;
- qlen++;
- qtail++;
+ tmp_queue[qtail] = midi_byte;
+ qlen++;
+ qtail++;
- RESTORE_INTR (flags);
+ splx(flags);
- return 1;
+ return 1;
}
static int
-gus_midi_start_read (int dev)
+gus_midi_start_read(int dev)
{
- return 0;
+ return 0;
}
static int
-gus_midi_end_read (int dev)
+gus_midi_end_read(int dev)
{
- return 0;
+ return 0;
}
static int
-gus_midi_ioctl (int dev, unsigned cmd, unsigned arg)
+gus_midi_ioctl(int dev, unsigned cmd, ioctl_arg arg)
{
- return RET_ERROR (EINVAL);
+ return -(EINVAL);
}
static void
-gus_midi_kick (int dev)
+gus_midi_kick(int dev)
{
}
static int
-gus_midi_buffer_status (int dev)
+gus_midi_buffer_status(int dev)
{
- unsigned long flags;
+ unsigned long flags;
- if (!output_used)
- return 0;
+ if (!output_used)
+ return 0;
- DISABLE_INTR (flags);
+ flags = splhigh();
- if (qlen && dump_to_midi (tmp_queue[qhead]))
- {
- qlen--;
- qhead++;
- }
-
- RESTORE_INTR (flags);
+ if (qlen && dump_to_midi(tmp_queue[qhead])) {
+ qlen--;
+ qhead++;
+ }
+ splx(flags);
- return (qlen > 0) | !(GUS_MIDI_STATUS () & MIDI_XMIT_EMPTY);
+ return (qlen > 0) | !(GUS_MIDI_STATUS() & MIDI_XMIT_EMPTY);
}
#define MIDI_SYNTH_NAME "Gravis Ultrasound Midi"
#define MIDI_SYNTH_CAPS SYNTH_CAP_INPUT
-#include "midi_synth.h"
+#include <i386/isa/sound/midi_synth.h>
static struct midi_operations gus_midi_operations =
{
- {"Gravis UltraSound Midi", 0, 0, SNDCARD_GUS},
- &std_midi_synth,
- gus_midi_open,
- gus_midi_close,
- gus_midi_ioctl,
- gus_midi_out,
- gus_midi_start_read,
- gus_midi_end_read,
- gus_midi_kick,
- NULL, /*
- * command
- */
- gus_midi_buffer_status,
- NULL
+ {"Gravis UltraSound Midi", 0, 0, SNDCARD_GUS},
+ &std_midi_synth,
+ {0},
+ gus_midi_open,
+ gus_midi_close,
+ gus_midi_ioctl,
+ gus_midi_out,
+ gus_midi_start_read,
+ gus_midi_end_read,
+ gus_midi_kick,
+ NULL, /* command */
+ gus_midi_buffer_status,
+ NULL
};
-long
-gus_midi_init (long mem_start)
+void
+gus_midi_init()
{
- if (num_midis >= MAX_MIDI_DEV)
- {
- printk ("Sound: Too many midi devices detected\n");
- return mem_start;
- }
-
- OUTB (MIDI_RESET, u_MidiControl);
+ if (num_midis >= MAX_MIDI_DEV) {
+ printf("Sound: Too many midi devices detected\n");
+ return;
+ }
+ outb(u_MidiControl, MIDI_RESET);
- std_midi_synth.midi_dev = my_dev = num_midis;
- midi_devs[num_midis++] = &gus_midi_operations;
- return mem_start;
+ std_midi_synth.midi_dev = my_dev = num_midis;
+ midi_devs[num_midis++] = &gus_midi_operations;
+ return;
}
void
-gus_midi_interrupt (int dummy)
+gus_midi_interrupt(int dummy)
{
- unsigned char stat, data;
- unsigned long flags;
-
- DISABLE_INTR (flags);
-
- stat = GUS_MIDI_STATUS ();
-
- if (stat & MIDI_RCV_FULL)
- {
- data = INB (u_MidiData);
- if (input_opened)
- midi_input_intr (my_dev, data);
- }
-
- if (stat & MIDI_XMIT_EMPTY)
- {
- while (qlen && dump_to_midi (tmp_queue[qhead]))
- {
- qlen--;
- qhead++;
- }
+ unsigned char stat, data;
+ unsigned long flags;
- if (!qlen)
- {
- /*
- * Disable Midi output interrupts, since no data in the buffer
- */
- gus_midi_control &= ~MIDI_ENABLE_XMIT;
- OUTB (gus_midi_control, u_MidiControl);
- }
- }
+ flags = splhigh();
- if (stat & MIDI_FRAME_ERR)
- printk ("Midi framing error\n");
- if (stat & MIDI_OVERRUN && input_opened)
- printk ("GUS: Midi input overrun\n");
+ stat = GUS_MIDI_STATUS();
- RESTORE_INTR (flags);
+ if (stat & MIDI_RCV_FULL) {
+ data = inb(u_MidiData);
+ if (input_opened)
+ midi_input_intr(my_dev, data);
+ }
+ if (stat & MIDI_XMIT_EMPTY) {
+ while (qlen && dump_to_midi(tmp_queue[qhead])) {
+ qlen--;
+ qhead++;
+ }
+
+ if (!qlen) {
+ /*
+ * Disable Midi output interrupts, since no data in
+ * the buffer
+ */
+ gus_midi_control &= ~MIDI_ENABLE_XMIT;
+ outb(u_MidiControl, gus_midi_control);
+ }
+ }
+ splx(flags);
}
#endif
-
-#endif
diff --git a/sys/i386/isa/sound/gus_vol.c b/sys/i386/isa/sound/gus_vol.c
index 055a1170e9fb..fc66618f3b9c 100644
--- a/sys/i386/isa/sound/gus_vol.c
+++ b/sys/i386/isa/sound/gus_vol.c
@@ -1,16 +1,19 @@
/*
* gus_vol.c - Compute volume for GUS.
- *
+ *
* Greg Lee 1993.
*/
-#include "sound_config.h"
-#ifndef EXCLUDE_GUS
-#include "gus_linearvol.h"
+#include <i386/isa/sound/sound_config.h>
+
+#ifdef CONFIG_GUS
+#include <i386/isa/sound/gus_linearvol.h>
#define GUS_VOLUME gus_wave_volume
extern int gus_wave_volume;
+unsigned short gus_adagio_vol(int vel, int mainv, int xpn, int voicev);
+unsigned short gus_linear_vol(int vol, int mainvol);
/*
* Calculate gus volume from note velocity, main volume, expression, and
@@ -21,93 +24,87 @@ 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.
*/
unsigned short
-gus_adagio_vol (int vel, int mainv, int xpn, int voicev)
+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.
- */
- if (voicev > 65)
- xpn += voicev - 64;
- xpn += (voicev - 64) / 2;
-
- /*
- * Combine multiplicative and level components.
- */
- x = vel * xpn * 6 + (voicev / 4) * x;
+ 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.
+ */
+ if (voicev > 65)
+ xpn += voicev - 64;
+ xpn += (voicev - 64) / 2;
+
+ /*
+ * 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).
- */
- x = (x * GUS_VOLUME * GUS_VOLUME) / 10000;
+ /*
+ * Further adjustment by installation-specific master volume control
+ * (default 60).
+ */
+ x = (x * GUS_VOLUME * GUS_VOLUME) / 10000;
#endif
#ifdef GUS_USE_CHN_MAIN_VOLUME
- /*
- * Experimental support for the channel main volume
- */
+ /*
+ * 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)
- return (0);
- else if (x >= 65535)
- return ((15 << 8) | 255);
-
- /*
- * Convert to gus's logarithmic form with 4 bit exponent i and 8 bit
- * mantissa m.
- */
- n = x;
- i = 7;
- if (n < 128)
- {
- while (i > 0 && n < (1 << i))
- i--;
+ if (x < 2)
+ return (0);
+ else if (x >= 65535)
+ return ((15 << 8) | 255);
+
+ /*
+ * Convert to gus's logarithmic form with 4 bit exponent i and 8 bit
+ * mantissa m.
+ */
+ n = x;
+ i = 7;
+ if (n < 128) {
+ while (i > 0 && n < (1 << i))
+ i--;
+ } else
+ while (n > 255) {
+ 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.
+ */
+ if (m > 0) {
+ if (i > 8)
+ m >>= i - 8;
+ else if (i < 8)
+ m <<= 8 - i;
}
- else
- while (n > 255)
- {
- 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.
- */
- if (m > 0)
- {
- if (i > 8)
- m >>= i - 8;
- else if (i < 8)
- m <<= 8 - i;
- }
-
- return ((i << 8) + m);
+ return ((i << 8) + m);
}
/*
@@ -117,31 +114,25 @@ gus_adagio_vol (int vel, int mainv, int xpn, int voicev)
*/
unsigned short
-gus_linear_vol (int vol, int mainvol)
+gus_linear_vol(int vol, int mainvol)
{
- int mixer_mainvol;
+ int mixer_mainvol;
- if (vol <= 0)
- vol = 0;
- else if (vol >= 127)
- vol = 127;
+ RANGE (vol, 0, 127) ;
#ifdef GUS_VOLUME
- mixer_mainvol = GUS_VOLUME;
+ mixer_mainvol = GUS_VOLUME;
#else
- mixer_mainvol = 100;
+ mixer_mainvol = 100;
#endif
#ifdef GUS_USE_CHN_MAIN_VOLUME
- if (mainvol <= 0)
- mainvol = 0;
- else if (mainvol >= 127)
- mainvol = 127;
+ RANGE (mainvol, 0, 127);
#else
- mainvol = 128;
+ mainvol = 127;
#endif
- return gus_linearvol[(((vol * mainvol) / 128) * mixer_mainvol) / 100];
+ return gus_linearvol[(((vol * mainvol) / 127) * mixer_mainvol) / 100];
}
#endif
diff --git a/sys/i386/isa/sound/gus_wave.c b/sys/i386/isa/sound/gus_wave.c
index 5f8e39c8ae5b..8cb3419dffa8 100644
--- a/sys/i386/isa/sound/gus_wave.c
+++ b/sys/i386/isa/sound/gus_wave.c
@@ -1,10 +1,10 @@
/*
* sound/gus_wave.c
- *
+ *
* Driver for the Gravis UltraSound wave table synth.
- *
+ *
* Copyright by Hannu Savolainen 1993, 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
@@ -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,76 +24,109 @@
* 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"
-#include "ultrasound.h"
-#include "gus_hw.h"
+#include <i386/isa/sound/sound_config.h>
+#include <i386/isa/sound/ultrasound.h>
+#include <i386/isa/sound/gus_hw.h>
+#include <i386/isa/sound/iwdefs.h>
+#include <machine/clock.h>
-#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_GUS)
+/* PnP stuff */
+#define GUS_PNP_ID 0x100561e
-#define MAX_SAMPLE 128
+#define MAX_CARDS 8
+#define MAX_GUS_PNP 12
+
+
+/* Static ports */
+#define PADDRESS 0x279
+#define PWRITE_DATA 0xa79
+#define SET_CSN 0x06
+#define PSTATUS 0x05
+
+/* PnP Registers. Write to ADDRESS and then use WRITE/READ_DATA */
+#define SET_RD_DATA 0x00
+#define SERIAL_ISOLATION 0x01
+#define WAKE 0x03
+
+#if defined(CONFIG_GUS)
+
+IWAVE iw;
+#define ENTER_CRITICAL
+
+#define LEAVE_CRITICAL
+
+#define MAX_SAMPLE 150
#define MAX_PATCH 256
-struct voice_info
- {
- unsigned long orig_freq;
- unsigned long current_freq;
- unsigned long mode;
- int bender;
- int bender_range;
- int panning;
- int midi_volume;
- unsigned int initial_volume;
- unsigned int current_volume;
- int loop_irq_mode, loop_irq_parm;
+
+u_int gus_pnp_found[MAX_GUS_PNP] =
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+struct voice_info {
+ u_long orig_freq;
+ u_long current_freq;
+ u_long mode;
+ int bender;
+ int bender_range;
+ int panning;
+ int midi_volume;
+ u_int initial_volume;
+ u_int current_volume;
+ int loop_irq_mode, loop_irq_parm;
#define LMODE_FINISH 1
#define LMODE_PCM 2
#define LMODE_PCM_STOP 3
- int volume_irq_mode, volume_irq_parm;
+ int volume_irq_mode, volume_irq_parm;
#define VMODE_HALT 1
#define VMODE_ENVELOPE 2
#define VMODE_START_NOTE 3
- int env_phase;
- unsigned char env_rate[6];
- unsigned char env_offset[6];
+ int env_phase;
+ u_char env_rate[6];
+ u_char env_offset[6];
- /*
- * Volume computation parameters for gus_adagio_vol()
- */
- int main_vol, expression_vol, patch_vol;
+ /*
+ * Volume computation parameters for gus_adagio_vol()
+ */
+ int main_vol, expression_vol, patch_vol;
- /* Variables for "Ultraclick" removal */
- int dev_pending, note_pending, volume_pending, sample_pending;
- char kill_pending;
- long offset_pending;
+ /* Variables for "Ultraclick" removal */
+ int dev_pending, note_pending, volume_pending, sample_pending;
+ char kill_pending;
+ long offset_pending;
- };
+};
static struct voice_alloc_info *voice_alloc;
extern int gus_base;
extern int gus_irq, gus_dma;
+static int gus_dma2 = -1;
+static int dual_dma_mode = 0;
static long gus_mem_size = 0;
static long free_mem_ptr = 0;
-static int gus_busy = 0;
+static int gus_no_dma = 0;
static int nr_voices = 0;
static int gus_devnum = 0;
static int volume_base, volume_scale, volume_method;
static int gus_recmask = SOUND_MASK_MIC;
static int recording_active = 0;
+static int only_read_access = 0;
+static int only_8_bits = 0;
int gus_wave_volume = 60;
int gus_pcm_volume = 80;
int have_gus_max = 0;
static int gus_line_vol = 100, gus_mic_vol = 0;
-static unsigned char mix_image = 0x00;
+static u_char mix_image = 0x00;
+int gus_timer_enabled = 0;
/*
- * Current version of this driver doesn't allow synth and PCM functions
- * at the same time. The active_device specifies the active driver
+ * 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;
@@ -105,7 +138,9 @@ static int gus_sampling_speed;
static int gus_sampling_channels;
static int gus_sampling_bits;
-DEFINE_WAIT_QUEUE (dram_sleeper, dram_sleep_flag);
+static int *dram_sleeper = NULL;
+static volatile struct snd_wait dram_sleep_flag =
+{0};
/*
* Variables and buffers for PCM output
@@ -120,39 +155,45 @@ static volatile int dma_active;
static int pcm_opened = 0;
static int pcm_current_dev;
static int pcm_current_block;
-static unsigned long pcm_current_buf;
+static u_long pcm_current_buf;
static int pcm_current_count;
static int pcm_current_intrflag;
+extern sound_os_info *gus_osp;
+
struct voice_info voices[32];
static int freq_div_table[] =
{
- 44100, /* 14 */
- 41160, /* 15 */
- 38587, /* 16 */
- 36317, /* 17 */
- 34300, /* 18 */
- 32494, /* 19 */
- 30870, /* 20 */
- 29400, /* 21 */
- 28063, /* 22 */
- 26843, /* 23 */
- 25725, /* 24 */
- 24696, /* 25 */
- 23746, /* 26 */
- 22866, /* 27 */
- 22050, /* 28 */
- 21289, /* 29 */
- 20580, /* 30 */
- 19916, /* 31 */
- 19293 /* 32 */
+ 44100, /* 14 */
+ 41160, /* 15 */
+ 38587, /* 16 */
+ 36317, /* 17 */
+ 34300, /* 18 */
+ 32494, /* 19 */
+ 30870, /* 20 */
+ 29400, /* 21 */
+ 28063, /* 22 */
+ 26843, /* 23 */
+ 25725, /* 24 */
+ 24696, /* 25 */
+ 23746, /* 26 */
+ 22866, /* 27 */
+ 22050, /* 28 */
+ 21289, /* 29 */
+ 20580, /* 30 */
+ 19916, /* 31 */
+ 19293 /* 32 */
};
static struct patch_info *samples;
+struct patch_info *dbg_samples;
+int dbg_samplep;
+
static long sample_ptrs[MAX_SAMPLE + 1];
static int sample_map[32];
static int free_sample;
+static int mixer_type = 0;
static int patch_table[MAX_PATCH];
@@ -161,3086 +202,4673 @@ static int patch_map[32];
static struct synth_info gus_info =
{"Gravis UltraSound", 0, SYNTH_TYPE_SAMPLE, SAMPLE_TYPE_GUS, 0, 16, 0, MAX_PATCH};
-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 gus_default_mixer_init(void);
+
+int guswave_start_note2(int dev, int voice, int note_num, int volume);
+static void gus_poke(long addr, u_char data);
+void compute_and_set_volume(int voice, int volume, int ramp_time);
+extern u_short gus_adagio_vol(int vel, int mainv, int xpn, int voicev);
+extern u_short gus_linear_vol(int vol, int mainvol);
+void compute_volume(int voice, int volume);
+void do_volume_irq(int voice);
+static void set_input_volumes(void);
+static void gus_tmr_install(int io_base);
+
+void SEND(int d, int r);
+int get_serial(int rd_port, u_char *data);
+void send_Initiation_LFSR(void);
+int isolation_protocol(int rd_port);
+
#define INSTANT_RAMP -1 /* Instant change. No ramping */
#define FAST_RAMP 0 /* Fastest possible ramp */
+
+/* Crystal Select */
+#define CODEC_XTAL2 0x01 /* 16.9344 crystal */
+#define CODEC_XTAL1 0x00 /* 24.576 crystal */
+/************************************************************************/
+
+/************************************************************************/
+/* Definitions for CONFIG_1 register */
+#define CODEC_CFIG1I_DEFAULT 0x03 | 0x8
+#define CODEC_CAPTURE_PIO 0x80 /* Capture PIO enable */
+#define CODEC_PLAYBACK_PIO 0x40 /* Playback PIO enable */
+#define CODEC_AUTOCALIB 0x08 /* auto calibrate */
+#define CODEC_SINGLE_DMA 0x04 /* Use single DMA channel */
+#define CODEC_RE 0x02 /* Capture enable */
+#define CODEC_PE 0x01 /* playback enable */
+/************************************************************************/
+
+/************************************************************************/
+/* Definitions for CONFIG_2 register */
+#define CODEC_CFIG2I_DEFAULT 0x81
+#define CODEC_OFVS 0x80 /* Output Full Scale Voltage */
+#define CODEC_TE 0x40 /* Timer Enable */
+#define CODEC_RSCD 0x20 /* Recors Sample Counter Disable */
+#define CODEC_PSCD 0x10 /* Playback Sample Counter Disable */
+#define CODEC_DAOF 0x01 /* D/A Ouput Force Enable */
+/************************************************************************/
+
+/************************************************************************/
+/* Definitions for CONFIG_3 register */
+/* #define CODEC_CFIG3I_DEFAULT 0xe0 0x02 when synth DACs are working */
+
+#define CODEC_CFIG3I_DEFAULT 0xc0 /* 0x02 when synth DACs are working */
+#define CODEC_RPIE 0x80 /* Record FIFO IRQ Enable */
+#define CODEC_PPIE 0x40 /* Playback FIFO IRQ Enable */
+#define CODEC_FT_MASK 0x30 /* FIFO Threshold Select */
+#define CODEC_PVFM 0x04 /* Playback Variable Frequency Mode */
+#define CODEC_SYNA 0x02 /* AUX1/Synth Signal Select */
+/************************************************************************/
+
+/************************************************************************/
+/* Definitions for EXTERNAL_CONTROL register */
+#define CODEC_CEXTI_DEFAULT 0x00
+#define CODEC_IRQ_ENABLE 0x02 /* interrupt enable */
+#define CODEC_GPOUT1 0x80 /* external control #1 */
+#define CODEC_GPOUT0 0x40 /* external control #0 */
+/************************************************************************/
+
+/************************************************************************/
+/* Definitions for MODE_SELECT_ID register */
+#define CODEC_MODE_DEFAULT 0x40
+#define CODEC_MODE_MASK 0x60
+#define CODEC_ID_BIT4 0x80
+#define CODEC_ID_BIT3_0 0x0F
+/************************************************************************/
+#define CONFIG_1 0x09
+#define EXTERNAL_CONTROL 0x0a/* Pin control */
+#define STATUS_2 0x0b/* Test and initialization */
+#define MODE_SELECT_ID 0x0c/* Miscellaneaous information */
+#define LOOPBACK 0x0d/* Digital Mix */
+#define UPPER_PLAY_COUNT 0x0e/* Playback Upper Base Count */
+#define LOWER_PLAY_COUNT 0x0f/* Playback Lower Base Count */
+#define CONFIG_2 0x10
+#define CONFIG_3 0x11
+
+
+#define IWL_CODEC_OUT(reg, val) \
+ { outb(iwl_codec_base, reg); outb(iwl_codec_data, val); }
+
+#define IWL_CODEC_IN(reg, val) \
+ { outb(iwl_codec_base, reg); val = inb(iwl_codec_data); }
+
+
+u_char gus_look8(int reg);
+
+void gus_write16(int reg, u_int data);
+
+u_short gus_read16(int reg);
+
+void gus_write_addr(int reg, u_long address, int is16bit);
+void IwaveLineLevel(char level, char index);
+void IwaveInputSource(BYTE index, BYTE source);
+void IwaveDelay(WORD count);
+void IwaveStopDma(BYTE path);
+void IwavePnpGetCfg(void);
+void IwavePnpDevice(BYTE dev);
+void IwavePnpSetCfg(void);
+void IwavePnpKey(void);
+BYTE IwavePnpIsol(PORT * pnpread);
+void IwaveCfgIOSpace(void);
+
+void IwavePnpSerial(PORT pnprdp, BYTE csn, BYTE * vendor, DWORD * serial);
+
+
+void IwavePnpPeek(PORT pnprdp, WORD bytes, BYTE * data);
+void IwavePnpEeprom(BYTE ctrl);
+void IwavePnpActivate(BYTE dev, BYTE bool);
+
+void IwavePnpPower(BYTE mode);
+void IwavePnpWake(BYTE csn);
+PORT IwavePnpIOcheck(PORT base, BYTE no_ports);
+
+BYTE IwavePnpGetCSN(DWORD VendorID, BYTE csn_max);
+BYTE IwavePnpPing(DWORD VendorID);
+WORD IwaveMemSize(void);
+BYTE IwaveMemPeek(ADDRESS addr);
+void IwaveMemPoke(ADDRESS addr, BYTE datum);
+void IwaveMemCfg(DWORD * lpbanks);
+void IwaveCodecIrq(BYTE mode);
+WORD IwaveRegPeek(DWORD reg_mnem);
+
+void IwaveRegPoke(DWORD reg_mnem, WORD datum);
+void IwaveCodecMode(char mode);
+void IwaveLineMute(BYTE mute, BYTE inx);
+void Iwaveinitcodec(void);
+int IwaveOpen(char voices, char mode, struct address_info * hw);
+
+
static void
-reset_sample_memory (void)
+reset_sample_memory(void)
{
- int i;
+ int i;
- for (i = 0; i <= MAX_SAMPLE; i++)
- sample_ptrs[i] = -1;
- for (i = 0; i < 32; i++)
- sample_map[i] = -1;
- for (i = 0; i < 32; i++)
- patch_map[i] = -1;
+ for (i = 0; i <= MAX_SAMPLE; i++)
+ sample_ptrs[i] = -1;
+ for (i = 0; i < 32; i++)
+ sample_map[i] = -1;
+ for (i = 0; i < 32; i++)
+ patch_map[i] = -1;
- gus_poke (0, 0); /* Put a silent sample to the beginning */
- gus_poke (1, 0);
- free_mem_ptr = 2;
+ gus_poke(0, 0); /* Put a silent sample to the beginning */
+ gus_poke(1, 0);
+ free_mem_ptr = 2;
- free_sample = 0;
+ free_sample = 0;
- for (i = 0; i < MAX_PATCH; i++)
- patch_table[i] = -1;
+ for (i = 0; i < MAX_PATCH; i++)
+ patch_table[i] = -1;
}
void
-gus_delay (void)
+gus_delay(void)
{
- int i;
+ int i;
- for (i = 0; i < 7; i++)
- INB (u_DRAMIO);
+ for (i = 0; i < 7; i++)
+ inb(u_DRAMIO);
}
static void
-gus_poke (long addr, unsigned char data)
+gus_poke(long addr, u_char data)
{ /* Writes a byte to the DRAM */
- unsigned long flags;
+ u_long flags;
- DISABLE_INTR (flags);
- OUTB (0x43, u_Command);
- OUTB (addr & 0xff, u_DataLo);
- OUTB ((addr >> 8) & 0xff, u_DataHi);
+ flags = splhigh();
+ outb(u_Command, 0x43);
+ outb(u_DataLo, addr & 0xff);
+ outb(u_DataHi, (addr >> 8) & 0xff);
- OUTB (0x44, u_Command);
- OUTB ((addr >> 16) & 0xff, u_DataHi);
- OUTB (data, u_DRAMIO);
- RESTORE_INTR (flags);
+ outb(u_Command, 0x44);
+ outb(u_DataHi, (addr >> 16) & 0xff);
+ outb(u_DRAMIO, data);
+ splx(flags);
}
-static unsigned char
-gus_peek (long addr)
+static u_char
+gus_peek(long addr)
{ /* Reads a byte from the DRAM */
- unsigned long flags;
- unsigned char tmp;
+ u_long flags;
+ u_char tmp;
- DISABLE_INTR (flags);
- OUTB (0x43, u_Command);
- OUTB (addr & 0xff, u_DataLo);
- OUTB ((addr >> 8) & 0xff, u_DataHi);
+ flags = splhigh();
+ outb(u_Command, 0x43);
+ outb(u_DataLo, addr & 0xff);
+ outb(u_DataHi, (addr >> 8) & 0xff);
- OUTB (0x44, u_Command);
- OUTB ((addr >> 16) & 0xff, u_DataHi);
- tmp = INB (u_DRAMIO);
- RESTORE_INTR (flags);
+ outb(u_Command, 0x44);
+ outb(u_DataHi, (addr >> 16) & 0xff);
+ tmp = inb(u_DRAMIO);
+ splx(flags);
- return tmp;
+ return tmp;
}
void
-gus_write8 (int reg, unsigned int data)
+gus_write8(int reg, u_int data)
{ /* Writes to an indirect register (8 bit) */
- unsigned long flags;
+ u_long flags;
- DISABLE_INTR (flags);
-
- OUTB (reg, u_Command);
- OUTB ((unsigned char) (data & 0xff), u_DataHi);
-
- RESTORE_INTR (flags);
+ flags = splhigh();
+ outb(u_Command, reg);
+ outb(u_DataHi, (u_char) (data & 0xff));
+ splx(flags);
}
-unsigned char
-gus_read8 (int reg)
-{ /* Reads from an indirect register (8 bit). Offset 0x80. */
- unsigned long flags;
- unsigned char val;
+u_char
+gus_read8(int reg)
+{ /* Reads from an indirect register (8 bit). Offset 0x80. */
+ u_long flags;
+ u_char val;
- DISABLE_INTR (flags);
- OUTB (reg | 0x80, u_Command);
- val = INB (u_DataHi);
- RESTORE_INTR (flags);
+ flags = splhigh();
+ outb(u_Command, reg | 0x80);
+ val = inb(u_DataHi);
+ splx(flags);
- return val;
+ return val;
}
-unsigned char
-gus_look8 (int reg)
-{ /* Reads from an indirect register (8 bit). No additional offset. */
- unsigned long flags;
- unsigned char val;
+u_char
+gus_look8(int reg)
+{ /* Reads from an indirect register (8 bit). No additional offset. */
+ u_long flags;
+ u_char val;
- DISABLE_INTR (flags);
- OUTB (reg, u_Command);
- val = INB (u_DataHi);
- RESTORE_INTR (flags);
+ flags = splhigh();
+ outb(u_Command, reg);
+ val = inb(u_DataHi);
+ splx(flags);
- return val;
+ return val;
}
void
-gus_write16 (int reg, unsigned int data)
-{ /* Writes to an indirect register (16 bit) */
- unsigned long flags;
+gus_write16(int reg, u_int data)
+{ /* Writes to an indirect register (16 bit) */
+ u_long flags;
- DISABLE_INTR (flags);
+ flags = splhigh();
- OUTB (reg, u_Command);
+ outb(u_Command, reg);
- OUTB ((unsigned char) (data & 0xff), u_DataLo);
- OUTB ((unsigned char) ((data >> 8) & 0xff), u_DataHi);
+ outb(u_DataLo, (u_char) (data & 0xff));
+ outb(u_DataHi, (u_char) ((data >> 8) & 0xff));
- RESTORE_INTR (flags);
+ splx(flags);
}
-unsigned short
-gus_read16 (int reg)
-{ /* Reads from an indirect register (16 bit). Offset 0x80. */
- unsigned long flags;
- unsigned char hi, lo;
+u_short
+gus_read16(int reg)
+{ /* Reads from an indirect register (16 bit). Offset 0x80. */
+ u_long flags;
+ u_char hi, lo;
- DISABLE_INTR (flags);
+ flags = splhigh();
- OUTB (reg | 0x80, u_Command);
+ outb(u_Command, reg | 0x80);
- lo = INB (u_DataLo);
- hi = INB (u_DataHi);
+ lo = inb(u_DataLo);
+ hi = inb(u_DataHi);
- RESTORE_INTR (flags);
+ splx(flags);
- return ((hi << 8) & 0xff00) | lo;
+ return ((hi << 8) & 0xff00) | lo;
}
void
-gus_write_addr (int reg, unsigned long address, int is16bit)
+gus_write_addr(int reg, u_long address, int is16bit)
{ /* Writes an 24 bit memory address */
- unsigned long hold_address;
- unsigned long flags;
+ u_long hold_address;
+ u_long flags;
- DISABLE_INTR (flags);
- if (is16bit)
- {
- /*
- * Special processing required for 16 bit patches
- */
-
- hold_address = address;
- address = address >> 1;
- address &= 0x0001ffffL;
- address |= (hold_address & 0x000c0000L);
- }
+ flags = splhigh();
+ if (is16bit) {
+ /*
+ * Special processing required for 16 bit patches
+ */
- 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));
- RESTORE_INTR (flags);
+ hold_address = address;
+ address = address >> 1;
+ address &= 0x0001ffffL;
+ address |= (hold_address & 0x000c0000L);
+ }
+ gus_write16(reg, (u_short) ((address >> 7) & 0xffff));
+ gus_write16(reg + 1, (u_short) ((address << 9) & 0xffff));
+ /*
+ * Could writing twice fix problems with GUS_VOICE_POS() ? Lets try...
+ */
+ gus_delay();
+ gus_write16(reg, (u_short) ((address >> 7) & 0xffff));
+ gus_write16(reg + 1, (u_short) ((address << 9) & 0xffff));
+ splx(flags);
}
static void
-gus_select_voice (int voice)
+gus_select_voice(int voice)
{
- if (voice < 0 || voice > 31)
- return;
+ if (voice < 0 || voice > 31)
+ return;
- OUTB (voice, u_Voice);
+ outb(u_Voice, voice);
}
static void
-gus_select_max_voices (int nvoices)
+gus_select_max_voices(int nvoices)
{
- if (nvoices < 14)
- nvoices = 14;
- if (nvoices > 32)
- nvoices = 32;
+ if (nvoices < 14)
+ nvoices = 14;
+ if (nvoices > 32)
+ nvoices = 32;
- voice_alloc->max_voice = nr_voices = nvoices;
+ voice_alloc->max_voice = nr_voices = nvoices;
- gus_write8 (0x0e, (nvoices - 1) | 0xc0);
+ gus_write8(0x0e, (nvoices - 1) | 0xc0);
}
static void
-gus_voice_on (unsigned int mode)
+gus_voice_on(u_int mode)
{
- gus_write8 (0x00, (unsigned char) (mode & 0xfc));
- gus_delay ();
- gus_write8 (0x00, (unsigned char) (mode & 0xfc));
+ gus_write8(0x00, (u_char) (mode & 0xfc));
+ gus_delay();
+ gus_write8(0x00, (u_char) (mode & 0xfc));
}
static void
-gus_voice_off (void)
+gus_voice_off(void)
{
- gus_write8 (0x00, gus_read8 (0x00) | 0x03);
+ gus_write8(0x00, gus_read8(0x00) | 0x03);
}
static void
-gus_voice_mode (unsigned int m)
+gus_voice_mode(u_int m)
{
- unsigned char mode = (unsigned char) (m & 0xff);
+ u_char mode = (u_char) (m & 0xff);
- gus_write8 (0x00, (gus_read8 (0x00) & 0x03) |
- (mode & 0xfc)); /* Don't touch last two bits */
- gus_delay ();
- gus_write8 (0x00, (gus_read8 (0x00) & 0x03) | (mode & 0xfc));
+ gus_write8(0x00, (gus_read8(0x00) & 0x03) |
+ (mode & 0xfc)); /* Don't touch last two bits */
+ gus_delay();
+ gus_write8(0x00, (gus_read8(0x00) & 0x03) | (mode & 0xfc));
}
static void
-gus_voice_freq (unsigned long freq)
+gus_voice_freq(u_long freq)
{
- unsigned long divisor = freq_div_table[nr_voices - 14];
- unsigned short fc;
+ u_long divisor = freq_div_table[nr_voices - 14];
+ u_short fc;
- fc = (unsigned short) (((freq << 9) + (divisor >> 1)) / divisor);
- fc = fc << 1;
+ fc = (u_short) (((freq << 9) + (divisor >> 1)) / divisor);
+ fc = fc << 1;
- gus_write16 (0x01, fc);
+ gus_write16(0x01, fc);
}
static void
-gus_voice_volume (unsigned int vol)
+gus_voice_volume(u_int vol)
{
- gus_write8 (0x0d, 0x03); /* Stop ramp before setting volume */
- gus_write16 (0x09, (unsigned short) (vol << 4));
+ gus_write8(0x0d, 0x03); /* Stop ramp before setting volume */
+ gus_write16(0x09, (u_short) (vol << 4));
}
static void
-gus_voice_balance (unsigned int balance)
+gus_voice_balance(u_int balance)
{
- gus_write8 (0x0c, (unsigned char) (balance & 0xff));
+ gus_write8(0x0c, (u_char) (balance & 0xff));
}
static void
-gus_ramp_range (unsigned int low, unsigned int high)
+gus_ramp_range(u_int low, u_int high)
{
- gus_write8 (0x07, (unsigned char) ((low >> 4) & 0xff));
- gus_write8 (0x08, (unsigned char) ((high >> 4) & 0xff));
+ gus_write8(0x07, (u_char) ((low >> 4) & 0xff));
+ gus_write8(0x08, (u_char) ((high >> 4) & 0xff));
}
static void
-gus_ramp_rate (unsigned int scale, unsigned int rate)
+gus_ramp_rate(u_int scale, u_int rate)
{
- gus_write8 (0x06, (unsigned char) (((scale & 0x03) << 6) | (rate & 0x3f)));
+ gus_write8(0x06, (u_char) (((scale & 0x03) << 6) | (rate & 0x3f)));
}
static void
-gus_rampon (unsigned int m)
+gus_rampon(u_int m)
{
- unsigned char mode = (unsigned char) (m & 0xff);
+ u_char mode = (u_char) (m & 0xff);
- gus_write8 (0x0d, mode & 0xfc);
- gus_delay ();
- gus_write8 (0x0d, mode & 0xfc);
+ gus_write8(0x0d, mode & 0xfc);
+ gus_delay();
+ gus_write8(0x0d, mode & 0xfc);
}
static void
-gus_ramp_mode (unsigned int m)
+gus_ramp_mode(u_int m)
{
- unsigned char mode = (unsigned char) (m & 0xff);
+ u_char mode = (u_char) (m & 0xff);
- gus_write8 (0x0d, (gus_read8 (0x0d) & 0x03) |
- (mode & 0xfc)); /* Leave the last 2 bits alone */
- gus_delay ();
- gus_write8 (0x0d, (gus_read8 (0x0d) & 0x03) | (mode & 0xfc));
+ gus_write8(0x0d, (gus_read8(0x0d) & 0x03) |
+ (mode & 0xfc)); /* Leave the last 2 bits alone */
+ gus_delay();
+ gus_write8(0x0d, (gus_read8(0x0d) & 0x03) | (mode & 0xfc));
}
static void
-gus_rampoff (void)
+gus_rampoff(void)
{
- gus_write8 (0x0d, 0x03);
+ gus_write8(0x0d, 0x03);
}
static void
-gus_set_voice_pos (int voice, long position)
+gus_set_voice_pos(int voice, long position)
{
- int sample_no;
-
- if ((sample_no = sample_map[voice]) != -1)
- if (position < samples[sample_no].len)
- if (voices[voice].volume_irq_mode == VMODE_START_NOTE)
- voices[voice].offset_pending = position;
- else
- gus_write_addr (0x0a, sample_ptrs[sample_no] + position,
- samples[sample_no].mode & WAVE_16_BITS);
+ int sample_no;
+
+ if ((sample_no = sample_map[voice]) != -1)
+ if (position < samples[sample_no].len)
+ if (voices[voice].volume_irq_mode == VMODE_START_NOTE)
+ voices[voice].offset_pending = position;
+ else
+ gus_write_addr(0x0a, sample_ptrs[sample_no] + position,
+ samples[sample_no].mode & WAVE_16_BITS);
}
static void
-gus_voice_init (int voice)
+gus_voice_init(int voice)
{
- unsigned long flags;
-
- DISABLE_INTR (flags);
- gus_select_voice (voice);
- gus_voice_volume (0);
- gus_write_addr (0x0a, 0, 0); /* Set current position to 0 */
- gus_write8 (0x00, 0x03); /* Voice off */
- gus_write8 (0x0d, 0x03); /* Ramping off */
- voice_alloc->map[voice] = 0;
- RESTORE_INTR (flags);
+ u_long flags;
+
+ flags = splhigh();
+ gus_select_voice(voice);
+ gus_voice_volume(0);
+ gus_voice_off();
+ gus_write_addr(0x0a, 0, 0); /* Set current position to 0 */
+ gus_write8(0x00, 0x03); /* Voice off */
+ gus_write8(0x0d, 0x03); /* Ramping off */
+ voice_alloc->map[voice] = 0;
+ voice_alloc->alloc_times[voice] = 0;
+ splx(flags);
}
static void
-gus_voice_init2 (int voice)
-{
- voices[voice].panning = 0;
- voices[voice].mode = 0;
- voices[voice].orig_freq = 20000;
- voices[voice].current_freq = 20000;
- voices[voice].bender = 0;
- voices[voice].bender_range = 200;
- voices[voice].initial_volume = 0;
- voices[voice].current_volume = 0;
- voices[voice].loop_irq_mode = 0;
- voices[voice].loop_irq_parm = 0;
- voices[voice].volume_irq_mode = 0;
- voices[voice].volume_irq_parm = 0;
- voices[voice].env_phase = 0;
- voices[voice].main_vol = 127;
- voices[voice].patch_vol = 127;
- voices[voice].expression_vol = 127;
- voices[voice].sample_pending = -1;
+gus_voice_init2(int voice)
+{
+ voices[voice].panning = 0;
+ voices[voice].mode = 0;
+ voices[voice].orig_freq = 20000;
+ voices[voice].current_freq = 20000;
+ voices[voice].bender = 0;
+ voices[voice].bender_range = 200;
+ voices[voice].initial_volume = 0;
+ voices[voice].current_volume = 0;
+ voices[voice].loop_irq_mode = 0;
+ voices[voice].loop_irq_parm = 0;
+ voices[voice].volume_irq_mode = 0;
+ voices[voice].volume_irq_parm = 0;
+ voices[voice].env_phase = 0;
+ voices[voice].main_vol = 127;
+ voices[voice].patch_vol = 127;
+ voices[voice].expression_vol = 127;
+ voices[voice].sample_pending = -1;
}
static void
-step_envelope (int voice)
+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 ();
- RESTORE_INTR (flags);
- return;
- /*
- * Sustain phase begins. Continue envelope after receiving note off.
- */
+ u_int vol, prev_vol, phase;
+ u_char rate;
+ long int flags;
+
+ if (voices[voice].mode & WAVE_SUSTAIN_ON && voices[voice].env_phase == 2) {
+ flags = splhigh();
+ gus_select_voice(voice);
+ gus_rampoff();
+ splx(flags);
+ return;
+ /*
+ * Sustain phase begins. Continue envelope after receiving
+ * note off.
+ */
}
-
- if (voices[voice].env_phase >= 5)
- { /* Envelope finished. Shoot the voice down */
- gus_voice_init (voice);
- return;
+ if (voices[voice].env_phase >= 5) { /* Envelope finished. Shoot
+ * the voice down */
+ gus_voice_init(voice);
+ return;
}
-
- prev_vol = voices[voice].current_volume;
- 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];
-
- 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 */
- {
- RESTORE_INTR (flags);
- step_envelope (voice); /* Continue the envelope on the next step */
- return;
+ prev_vol = voices[voice].current_volume;
+ 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];
+
+ flags = splhigh();
+ 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 */
+ splx(flags);
+ step_envelope(voice); /* Continue the envelope on the next
+ * step */
+ return;
}
-
- if (vol > prev_vol)
- {
- if (vol >= (4096 - 64))
- vol = 4096 - 65;
- gus_ramp_range (0, vol);
- gus_rampon (0x20); /* Increasing volume, with IRQ */
- }
- else
- {
- if (vol <= 64)
- vol = 65;
- gus_ramp_range (vol, 4030);
- gus_rampon (0x60); /* Decreasing volume, with IRQ */
+ if (vol > prev_vol) {
+ if (vol >= (4096 - 64))
+ vol = 4096 - 65;
+ gus_ramp_range(0, vol);
+ gus_rampon(0x20); /* Increasing volume, with IRQ */
+ } else {
+ if (vol <= 64)
+ vol = 65;
+ gus_ramp_range(vol, 4030);
+ gus_rampon(0x60); /* Decreasing volume, with IRQ */
}
- voices[voice].current_volume = vol;
- RESTORE_INTR (flags);
+ voices[voice].current_volume = vol;
+ splx(flags);
}
static void
-init_envelope (int voice)
+init_envelope(int voice)
{
- voices[voice].env_phase = -1;
- voices[voice].current_volume = 64;
+ voices[voice].env_phase = -1;
+ voices[voice].current_volume = 64;
- step_envelope (voice);
+ step_envelope(voice);
}
static void
-start_release (int voice, long int flags)
+start_release(int voice, long int flags)
{
- if (gus_read8 (0x00) & 0x03)
- return; /* Voice already stopped */
+ if (gus_read8(0x00) & 0x03)
+ 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].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);
+ voices[voice].mode &= ~WAVE_SUSTAIN_ON;
+ gus_rampoff();
+ splx(flags);
+ step_envelope(voice);
}
static void
-gus_voice_fade (int voice)
+gus_voice_fade(int voice)
{
- int instr_no = sample_map[voice], is16bits;
- long int flags;
+ int instr_no = sample_map[voice], is16bits;
+ long int flags;
- DISABLE_INTR (flags);
- gus_select_voice (voice);
+ flags = splhigh();
+ gus_select_voice(voice);
- if (instr_no < 0 || instr_no > MAX_SAMPLE)
- {
- gus_write8 (0x00, 0x03); /* Hard stop */
- voice_alloc->map[voice] = 0;
- RESTORE_INTR (flags);
- return;
+ if (instr_no < 0 || instr_no > MAX_SAMPLE) {
+ gus_write8(0x00, 0x03); /* Hard stop */
+ voice_alloc->map[voice] = 0;
+ splx(flags);
+ return;
}
+ is16bits = (samples[instr_no].mode & WAVE_16_BITS) ? 1 : 0; /* 8 or 16 bits */
- is16bits = (samples[instr_no].mode & WAVE_16_BITS) ? 1 : 0; /* 8 or 16 bits */
-
- if (voices[voice].mode & WAVE_ENVELOPES)
- {
- start_release (voice, flags);
- return;
+ if (voices[voice].mode & WAVE_ENVELOPES) {
+ start_release(voice, flags);
+ return;
}
-
- /*
- * Ramp the volume down but not too quickly.
- */
- if ((int) (gus_read16 (0x09) >> 4) < 100) /* Get current volume */
- {
- gus_voice_off ();
- gus_rampoff ();
- gus_voice_init (voice);
- return;
+ /*
+ * Ramp the volume down but not too quickly.
+ */
+ if ((int) (gus_read16(0x09) >> 4) < 100) { /* Get current volume */
+ gus_voice_off();
+ gus_rampoff();
+ gus_voice_init(voice);
+ return;
}
-
- gus_ramp_range (65, 4030);
- gus_ramp_rate (2, 4);
- gus_rampon (0x40 | 0x20); /* Down, once, with IRQ */
- voices[voice].volume_irq_mode = VMODE_HALT;
- RESTORE_INTR (flags);
+ gus_ramp_range(65, 4030);
+ gus_ramp_rate(2, 4);
+ gus_rampon(0x40 | 0x20);/* Down, once, with IRQ */
+ voices[voice].volume_irq_mode = VMODE_HALT;
+ splx(flags);
}
static void
-gus_reset (void)
+gus_reset(void)
{
- int i;
+ int i;
- gus_select_max_voices (24);
- volume_base = 3071;
- volume_scale = 4;
- volume_method = VOL_METHOD_ADAGIO;
+ gus_select_max_voices(24);
+ volume_base = 3071;
+ volume_scale = 4;
+ volume_method = VOL_METHOD_ADAGIO;
- for (i = 0; i < 32; i++)
- {
- gus_voice_init (i); /* Turn voice off */
- gus_voice_init2 (i);
+ for (i = 0; i < 32; i++) {
+ 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 (0x49); /* Clear any pending sample IRQs */
+ gus_look8(0x41); /* Clear any pending DMA IRQs */
+ gus_look8(0x49); /* Clear any pending sample IRQs */
- gus_read8 (0x0f); /* Clear pending IRQs */
+ gus_read8(0x0f); /* Clear pending IRQs */
}
static void
-gus_initialize (void)
+gus_initialize(void)
{
- unsigned long flags;
- unsigned char dma_image, irq_image, tmp;
+ u_long flags;
+ u_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};
+ static u_char gus_irq_map[16] =
+ {0, 0, 0, 3, 0, 2, 0, 4, 0, 1, 0, 5, 6, 0, 0, 7};
- static unsigned char gus_dma_map[8] =
- {0, 1, 0, 2, 0, 3, 4, 5};
+ static u_char gus_dma_map[8] =
+ {0, 1, 0, 2, 0, 3, 4, 5};
- DISABLE_INTR (flags);
- gus_write8 (0x4c, 0); /* Reset GF1 */
- gus_delay ();
- gus_delay ();
+ flags = splhigh();
+ gus_write8(0x4c, 0); /* Reset GF1 */
+ gus_delay();
+ gus_delay();
- gus_write8 (0x4c, 1); /* Release Reset */
- gus_delay ();
- gus_delay ();
+ gus_write8(0x4c, 1); /* Release Reset */
+ gus_delay();
+ gus_delay();
- /*
- * Clear all interrupts
- */
-
- gus_write8 (0x41, 0); /* DMA control */
- gus_write8 (0x45, 0); /* Timer control */
- gus_write8 (0x49, 0); /* Sample control */
+ /*
+ * Clear all interrupts
+ */
- gus_select_max_voices (24);
+ gus_write8(0x41, 0); /* DMA control */
+ gus_write8(0x45, 0); /* Timer control */
+ gus_write8(0x49, 0); /* Sample control */
- INB (u_Status); /* Touch the status register */
+ gus_select_max_voices(24);
- gus_look8 (0x41); /* Clear any pending DMA IRQs */
- gus_look8 (0x49); /* Clear any pending sample IRQs */
- gus_read8 (0x0f); /* Clear pending IRQs */
+ inb(u_Status); /* Touch the status register */
- gus_reset (); /* Resets all voices */
+ gus_look8(0x41); /* Clear any pending DMA IRQs */
+ gus_look8(0x49); /* Clear any pending sample IRQs */
+ gus_read8(0x0f); /* Clear pending IRQs */
- gus_look8 (0x41); /* Clear any pending DMA IRQs */
- gus_look8 (0x49); /* Clear any pending sample IRQs */
- gus_read8 (0x0f); /* Clear pending IRQs */
+ gus_reset(); /* Resets all voices */
- gus_write8 (0x4c, 7); /* Master reset | DAC enable | IRQ enable */
+ gus_look8(0x41); /* Clear any pending DMA IRQs */
+ gus_look8(0x49); /* Clear any pending sample IRQs */
+ gus_read8(0x0f); /* Clear pending IRQs */
- /*
- * Set up for Digital ASIC
- */
+ gus_write8(0x4c, 7); /* Master reset | DAC enable | IRQ enable */
- OUTB (0x05, gus_base + 0x0f);
+ /*
+ * Set up for Digital ASIC
+ */
- mix_image |= 0x02; /* Disable line out */
- OUTB (mix_image, u_Mixer);
+ outb(gus_base + 0x0f, 0x05);
- OUTB (0x00, u_IRQDMAControl);
+ mix_image |= 0x02; /* Disable line out (for a moment) */
+ outb(u_Mixer, mix_image);
- OUTB (0x00, gus_base + 0x0f);
+ outb(u_IRQDMAControl, 0x00);
- /*
- * 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.
- */
+ outb(gus_base + 0x0f, 0x00);
- irq_image = 0;
- tmp = gus_irq_map[gus_irq];
- if (!tmp)
- printk ("Warning! GUS IRQ not selected\n");
- irq_image |= tmp;
- irq_image |= 0x40; /* Combine IRQ1 (GF1) and IRQ2 (Midi) */
+ /*
+ * 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.
+ */
- 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;
+ irq_image = 0;
+ tmp = gus_irq_map[gus_irq];
+ if (!tmp)
+ printf("Warning! GUS IRQ not selected\n");
+ irq_image |= tmp;
+ irq_image |= 0x40; /* Combine IRQ1 (GF1) and IRQ2 (Midi) */
+
+ dual_dma_mode = 1;
+ if (gus_dma2 == gus_dma || gus_dma2 == -1) {
+ dual_dma_mode = 0;
+ dma_image = 0x40; /* Combine DMA1 (DRAM) and IRQ2 (ADC) */
+
+ tmp = gus_dma_map[gus_dma];
+ if (!tmp)
+ printf("Warning! GUS DMA not selected\n");
+
+ dma_image |= tmp;
+ } else
+ /* Setup dual DMA channel mode for GUS MAX */
+ {
+ dma_image = gus_dma_map[gus_dma];
+ if (!dma_image)
+ printf("Warning! GUS DMA not selected\n");
+
+ tmp = gus_dma_map[gus_dma2] << 3;
+ if (!tmp) {
+ printf("Warning! Invalid GUS MAX DMA\n");
+ tmp = 0x40; /* Combine DMA channels */
+ dual_dma_mode = 0;
+ }
+ dma_image |= tmp;
+ }
- /*
- * For some reason the IRQ and DMA addresses must be written twice
- */
+ /*
+ * 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 (dma_image | 0x80, u_IRQDMAControl); /* Set DMA address */
+ outb(u_Mixer, mix_image); /* Select DMA control */
+ outb(u_IRQDMAControl, dma_image | 0x80); /* Set DMA address */
- OUTB (mix_image | 0x40, u_Mixer); /* Select IRQ control */
- OUTB (irq_image, u_IRQDMAControl); /* Set IRQ address */
+ outb(u_Mixer, mix_image | 0x40); /* Select IRQ control */
+ outb(u_IRQDMAControl, irq_image); /* Set IRQ address */
- /*
- * Doing it second time
- */
+ /*
+ * Doing it second time
+ */
- OUTB (mix_image, u_Mixer); /* Select DMA control */
- OUTB (dma_image, u_IRQDMAControl); /* Set DMA address */
+ outb(u_Mixer, mix_image); /* Select DMA control */
+ outb(u_IRQDMAControl, dma_image); /* Set DMA address */
- OUTB (mix_image | 0x40, u_Mixer); /* Select IRQ control */
- OUTB (irq_image, u_IRQDMAControl); /* Set IRQ address */
+ outb(u_Mixer, mix_image | 0x40); /* Select IRQ control */
+ outb(u_IRQDMAControl, irq_image); /* 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 |= 0x08; /* Enable IRQ */
- OUTB (mix_image, u_Mixer); /*
- * Turn mixer channels on
- * Note! Mic in is left off.
- */
+ mix_image &= ~0x02; /* Enable line out */
+ mix_image |= 0x08; /* Enable IRQ */
+ outb(u_Mixer, mix_image); /* 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 */
- RESTORE_INTR (flags);
+ gusintr(0); /* Serve pending interrupts */
+ splx(flags);
}
int
-gus_wave_detect (int baseaddr)
+gus_wave_detect(int baseaddr)
{
- unsigned long i;
- unsigned long loc;
-
- gus_base = baseaddr;
-
- gus_write8 (0x4c, 0); /* Reset GF1 */
- gus_delay ();
- gus_delay ();
-
- gus_write8 (0x4c, 1); /* Release Reset */
- gus_delay ();
- gus_delay ();
-
- /* See if there is first block there.... */
- gus_poke (0L, 0xaa);
- if (gus_peek (0L) != 0xaa)
- return (0);
-
- /* Now zero it out so that I can check for mirroring .. */
- gus_poke (0L, 0x00);
- for (i = 1L; i < 1024L; i++)
- {
- int n, failed;
-
- /* check for mirroring ... */
- if (gus_peek (0L) != 0)
- break;
- loc = i << 10;
-
- for (n = loc - 1, failed = 0; n <= loc; n++)
- {
- gus_poke (loc, 0xaa);
- if (gus_peek (loc) != 0xaa)
- failed = 1;
-
- gus_poke (loc, 0x55);
- if (gus_peek (loc) != 0x55)
- failed = 1;
+ u_long i;
+ u_long loc;
+ gus_base = baseaddr;
+
+ gus_write8(0x4c, 0); /* Reset GF1 */
+ gus_delay();
+ gus_delay();
+
+ gus_write8(0x4c, 1); /* Release Reset */
+ gus_delay();
+ gus_delay();
+
+ /* See if there is first block there.... */
+ gus_poke(0L, 0xaa);
+ if (gus_peek(0L) != 0xaa)
+ return (0);
+
+ /* Now zero it out so that I can check for mirroring .. */
+ gus_poke(0L, 0x00);
+ for (i = 1L; i < 1024L; i++) {
+ int n, failed;
+
+ /* check for mirroring ... */
+ if (gus_peek(0L) != 0)
+ break;
+ loc = i << 10;
+
+ for (n = loc - 1, failed = 0; n <= loc; n++) {
+ gus_poke(loc, 0xaa);
+ if (gus_peek(loc) != 0xaa)
+ failed = 1;
+
+ gus_poke(loc, 0x55);
+ if (gus_peek(loc) != 0x55)
+ failed = 1;
+ }
+
+ if (failed)
+ break;
}
-
- if (failed)
- break;
- }
- gus_mem_size = i << 10;
- return 1;
+ gus_mem_size = i << 10;
+ return 1;
}
static int
-guswave_ioctl (int dev,
- unsigned int cmd, unsigned int arg)
+guswave_ioctl(int dev,
+ u_int cmd, ioctl_arg arg)
{
- switch (cmd)
- {
+ switch (cmd) {
case SNDCTL_SYNTH_INFO:
- gus_info.nr_voices = nr_voices;
- IOCTL_TO_USER ((char *) arg, 0, &gus_info, sizeof (gus_info));
- return 0;
- break;
+ gus_info.nr_voices = nr_voices;
+ bcopy(&gus_info, &(((char *) arg)[0]), sizeof(gus_info));
+ return 0;
+ break;
case SNDCTL_SEQ_RESETSAMPLES:
- reset_sample_memory ();
- return 0;
- break;
+ reset_sample_memory();
+ return 0;
+ break;
case SNDCTL_SEQ_PERCMODE:
- return 0;
- break;
+ return 0;
+ break;
case SNDCTL_SYNTH_MEMAVL:
- return gus_mem_size - free_mem_ptr - 32;
+ return gus_mem_size - free_mem_ptr - 32;
default:
- return RET_ERROR (EINVAL);
+ return -(EINVAL);
}
}
static int
-guswave_set_instr (int dev, int voice, int instr_no)
+guswave_set_instr(int dev, int voice, int instr_no)
{
- int sample_no;
-
- if (instr_no < 0 || instr_no > MAX_PATCH)
- return RET_ERROR (EINVAL);
+ int sample_no;
- if (voice < 0 || voice > 31)
- return RET_ERROR (EINVAL);
+ if (instr_no < 0 || instr_no > MAX_PATCH)
+ return -(EINVAL);
- if (voices[voice].volume_irq_mode == VMODE_START_NOTE)
- {
- voices[voice].sample_pending = instr_no;
- return 0;
- }
-
- sample_no = patch_table[instr_no];
- patch_map[voice] = -1;
-
- if (sample_no < 0)
- {
- printk ("GUS: Undefined patch %d for voice %d\n", instr_no, voice);
- return RET_ERROR (EINVAL);/* Patch not defined */
- }
+ if (voice < 0 || voice > 31)
+ return -(EINVAL);
- 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);
- return RET_ERROR (EINVAL);
- }
+ if (voices[voice].volume_irq_mode == VMODE_START_NOTE) {
+ voices[voice].sample_pending = instr_no;
+ return 0;
+ }
+ sample_no = patch_table[instr_no];
+ patch_map[voice] = -1;
- sample_map[voice] = sample_no;
- patch_map[voice] = instr_no;
- return 0;
+ if (sample_no < 0) {
+ printf("GUS: Undefined patch %d for voice %d\n", instr_no, voice);
+ return -(EINVAL); /* Patch not defined */
+ }
+ if (sample_ptrs[sample_no] == -1) { /* Sample not loaded */
+ printf("GUS: Sample #%d not loaded for patch %d (voice %d)\n",
+ sample_no, instr_no, voice);
+ return -(EINVAL);
+ }
+ sample_map[voice] = sample_no;
+ patch_map[voice] = instr_no;
+ return 0;
}
static int
-guswave_kill_note (int dev, int voice, int note, int velocity)
+guswave_kill_note(int dev, int voice, int note, int velocity)
{
- unsigned long flags;
-
- DISABLE_INTR (flags);
- voice_alloc->map[voice] = 0xffff;
- if (voices[voice].volume_irq_mode == VMODE_START_NOTE)
- {
- voices[voice].kill_pending = 1;
- RESTORE_INTR (flags);
- }
- else
- {
- RESTORE_INTR (flags);
- gus_voice_fade (voice);
+ u_long flags;
+
+ flags = splhigh();
+ /* voice_alloc->map[voice] = 0xffff; */
+ if (voices[voice].volume_irq_mode == VMODE_START_NOTE) {
+ voices[voice].kill_pending = 1;
+ splx(flags);
+ } else {
+ splx(flags);
+ gus_voice_fade(voice);
}
- return 0;
+ splx(flags);
+ return 0;
}
static void
-guswave_aftertouch (int dev, int voice, int pressure)
+guswave_aftertouch(int dev, int voice, int pressure)
{
- short lo_limit, hi_limit;
- unsigned long flags;
-
- return; /* Procedure 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 */
-
- if (pressure < 32)
- {
- DISABLE_INTR (flags);
- gus_select_voice (voice);
- gus_rampoff ();
- compute_and_set_volume (voice, 255, 0); /* Back to original volume */
- RESTORE_INTR (flags);
- return;
- }
-
- hi_limit = voices[voice].current_volume;
- lo_limit = hi_limit * 99 / 100;
- if (lo_limit < 65)
- lo_limit = 65;
-
- DISABLE_INTR (flags);
- gus_select_voice (voice);
- if (hi_limit > (4095 - 65))
- {
- hi_limit = 4095 - 65;
- gus_voice_volume (hi_limit);
- }
- gus_ramp_range (lo_limit, hi_limit);
- gus_ramp_rate (3, 8);
- gus_rampon (0x58); /* Bidirectional, dow, loop */
- RESTORE_INTR (flags);
}
static void
-guswave_panning (int dev, int voice, int value)
+guswave_panning(int dev, int voice, int value)
{
- if (voice >= 0 || voice < 32)
- voices[voice].panning = value;
+ if (voice >= 0 || voice < 32)
+ voices[voice].panning = value;
}
static void
-guswave_volume_method (int dev, int mode)
+guswave_volume_method(int dev, int mode)
{
- if (mode == VOL_METHOD_LINEAR || mode == VOL_METHOD_ADAGIO)
- volume_method = mode;
+ if (mode == VOL_METHOD_LINEAR || mode == VOL_METHOD_ADAGIO)
+ volume_method = mode;
}
-static void
-compute_volume (int voice, int volume)
+void
+compute_volume(int voice, int volume)
{
- if (volume < 128)
- voices[voice].midi_volume = volume;
+ if (volume < 128)
+ voices[voice].midi_volume = volume;
- switch (volume_method)
- {
+ 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;
+ voices[voice].initial_volume =
+ gus_adagio_vol(voices[voice].midi_volume, voices[voice].main_vol,
+ voices[voice].expression_vol, voices[voice].patch_vol);
+ break;
- case VOL_METHOD_LINEAR: /* Totally ignores patch-volume and expression */
- voices[voice].initial_volume =
- gus_linear_vol (volume, voices[voice].main_vol);
- break;
+ 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);
+ voices[voice].initial_volume = volume_base +
+ (voices[voice].midi_volume * volume_scale);
}
- if (voices[voice].initial_volume > 4030)
- voices[voice].initial_volume = 4030;
+ if (voices[voice].initial_volume > 4030)
+ voices[voice].initial_volume = 4030;
}
-static void
-compute_and_set_volume (int voice, int volume, int ramp_time)
+void
+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;
+ int curr, target, rate;
+ u_long flags;
- 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;
+ flags = splhigh();
+ /*
+ * CAUTION! Interrupts disabled. Enable them before returning
+ */
- if (ramp_time == INSTANT_RAMP)
- {
- gus_rampoff ();
- gus_voice_volume (target);
- RESTORE_INTR (flags);
- return;
- }
+ gus_select_voice(voice);
- if (ramp_time == FAST_RAMP)
- rate = 63;
- else
- rate = 16;
- gus_ramp_rate (0, rate);
+ curr = gus_read16(0x09) >> 4;
+ target = voices[voice].initial_volume;
- if ((target - current) / 64 == 0) /* Close enough to target. */
- {
- gus_rampoff ();
- gus_voice_volume (target);
- RESTORE_INTR (flags);
- return;
+ if (ramp_time == INSTANT_RAMP) {
+ gus_rampoff();
+ gus_voice_volume(target);
+ splx(flags);
+ return;
}
-
- if (target > current)
- {
- if (target > (4095 - 65))
- target = 4095 - 65;
- gus_ramp_range (current, target);
- gus_rampon (0x00); /* Ramp up, once, no IRQ */
+ if (ramp_time == FAST_RAMP)
+ rate = 63;
+ else
+ rate = 16;
+ gus_ramp_rate(0, rate);
+
+ if ((target - curr) / 64 == 0) { /* Close enough to target. */
+ gus_rampoff();
+ gus_voice_volume(target);
+ splx(flags);
+ return;
}
- else
- {
- if (target < 65)
- target = 65;
-
- gus_ramp_range (target, current);
- gus_rampon (0x40); /* Ramp down, once, no irq */
+ if (target > curr) {
+ if (target > (4095 - 65))
+ target = 4095 - 65;
+ gus_ramp_range(curr, target);
+ gus_rampon(0x00); /* Ramp up, once, no IRQ */
+ } else {
+ if (target < 65)
+ target = 65;
+
+ gus_ramp_range(target, curr);
+ gus_rampon(0x40); /* Ramp down, once, no irq */
}
- RESTORE_INTR (flags);
+ splx(flags);
}
static void
-dynamic_volume_change (int voice)
+dynamic_volume_change(int voice)
{
- unsigned char status;
- unsigned long flags;
-
- DISABLE_INTR (flags);
- gus_select_voice (voice);
- status = gus_read8 (0x00); /* Get voice status */
- RESTORE_INTR (flags);
+ u_char status;
+ u_long flags;
- if (status & 0x03)
- return; /* Voice was not running */
+ flags = splhigh();
+ gus_select_voice(voice);
+ status = gus_read8(0x00); /* Get voice status */
+ splx(flags);
- if (!(voices[voice].mode & WAVE_ENVELOPES))
- {
- compute_and_set_volume (voice, voices[voice].midi_volume, 1);
- return;
- }
+ if (status & 0x03)
+ return; /* Voice was not running */
- /*
- * Voice is running and has envelopes.
- */
-
- DISABLE_INTR (flags);
- gus_select_voice (voice);
- status = gus_read8 (0x0d); /* Ramping status */
- RESTORE_INTR (flags);
+ if (!(voices[voice].mode & WAVE_ENVELOPES)) {
+ compute_and_set_volume(voice, voices[voice].midi_volume, 1);
+ return;
+ }
+ /*
+ * Voice is running and has envelopes.
+ */
- if (status & 0x03) /* Sustain phase? */
- {
- compute_and_set_volume (voice, voices[voice].midi_volume, 1);
- return;
- }
+ flags = splhigh();
+ gus_select_voice(voice);
+ status = gus_read8(0x0d); /* Ramping status */
+ splx(flags);
- if (voices[voice].env_phase < 0)
- return;
+ if (status & 0x03) { /* Sustain phase? */
+ compute_and_set_volume(voice, voices[voice].midi_volume, 1);
+ return;
+ }
+ if (voices[voice].env_phase < 0)
+ return;
- compute_volume (voice, voices[voice].midi_volume);
+ compute_volume(voice, voices[voice].midi_volume);
}
static void
-guswave_controller (int dev, int voice, int ctrl_num, int value)
+guswave_controller(int dev, int voice, int ctrl_num, int value)
{
- unsigned long flags;
- unsigned long freq;
-
- if (voice < 0 || voice > 31)
- return;
-
- switch (ctrl_num)
- {
- case CTRL_PITCH_BENDER:
- 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);
- }
- break;
-
- case CTRL_PITCH_BENDER_RANGE:
- voices[voice].bender_range = value;
- break;
- case CTL_EXPRESSION:
- value /= 128;
- case CTRL_EXPRESSION:
- 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;
-
- case CTL_PAN:
- voices[voice].panning = (value * 2) - 128;
- break;
-
- case CTL_MAIN_VOLUME:
- value = (value * 100) / 16383;
-
- case CTRL_MAIN_VOLUME:
- voices[voice].main_vol = value;
- if (voices[voice].volume_irq_mode != VMODE_START_NOTE)
- dynamic_volume_change (voice);
- break;
-
- default:
- break;
- }
+ u_long flags;
+ u_long freq;
+
+ if (voice < 0 || voice > 31)
+ return;
+
+ switch (ctrl_num) {
+ case CTRL_PITCH_BENDER:
+ 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;
+
+ flags = splhigh();
+ gus_select_voice(voice);
+ gus_voice_freq(freq);
+ splx(flags);
+ }
+ break;
+
+ case CTRL_PITCH_BENDER_RANGE:
+ voices[voice].bender_range = value;
+ break;
+ case CTL_EXPRESSION:
+ value /= 128;
+ case CTRL_EXPRESSION:
+ 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;
+
+ case CTL_PAN:
+ voices[voice].panning = (value * 2) - 128;
+ break;
+
+ case CTL_MAIN_VOLUME:
+ value = (value * 100) / 16383;
+
+ case CTRL_MAIN_VOLUME:
+ voices[voice].main_vol = value;
+ if (voices[voice].volume_irq_mode != VMODE_START_NOTE)
+ dynamic_volume_change(voice);
+ break;
+
+ default:
+ break;
+ }
}
-static int
-guswave_start_note2 (int dev, int voice, int note_num, int volume)
+int
+guswave_start_note2(int dev, int voice, int note_num, int volume)
{
- int sample, best_sample, best_delta, delta_freq;
- int is16bits, samplep, patch, pan;
- unsigned long note_freq, base_note, freq, flags;
- unsigned char mode = 0;
-
- if (voice < 0 || voice > 31)
- {
- printk ("GUS: Invalid voice\n");
- return RET_ERROR (EINVAL);
+ int sample, best_sample, best_delta, delta_freq;
+ int is16bits, samplep, patch, pan;
+ u_long note_freq, base_note, freq, flags;
+ u_char mode = 0;
+
+ if (voice < 0 || voice > 31) {
+ printf("GUS: Invalid voice\n");
+ return -(EINVAL);
}
-
- if (note_num == 255)
- {
- if (voices[voice].mode & WAVE_ENVELOPES)
- {
- voices[voice].midi_volume = volume;
- dynamic_volume_change (voice);
- return 0;
+ if (note_num == 255) {
+ if (voices[voice].mode & WAVE_ENVELOPES) {
+ voices[voice].midi_volume = volume;
+ dynamic_volume_change(voice);
+ return 0;
}
-
- compute_and_set_volume (voice, volume, 1);
- return 0;
- }
-
- if ((patch = patch_map[voice]) == -1)
- {
- return RET_ERROR (EINVAL);
- }
-
- if ((samplep = patch_table[patch]) == -1)
- {
- return RET_ERROR (EINVAL);
+ compute_and_set_volume(voice, volume, 1);
+ return 0;
}
+ if ((patch = patch_map[voice]) == -1)
+ return -(EINVAL);
+ if ((samplep = patch_table[patch]) == -1)
+ return -(EINVAL);
+ note_freq = note_to_freq(note_num);
- 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.
- */
- sample = -1;
-
- best_sample = samplep;
- best_delta = 1000000;
- while (samplep >= 0 && sample == -1)
- {
- delta_freq = note_freq - samples[samplep].base_note;
- if (delta_freq < 0)
- delta_freq = -delta_freq;
- if (delta_freq < best_delta)
- {
- best_sample = samplep;
- best_delta = delta_freq;
- }
- if (samples[samplep].low_note <= note_freq &&
- note_freq <= samples[samplep].high_note)
- sample = samplep;
- else
- samplep = samples[samplep].key; /*
- * Follow link
- */
+ /*
+ * Find a sample within a patch so that the note_freq is between
+ * low_note and high_note.
+ */
+ sample = -1;
+
+ best_sample = samplep;
+ best_delta = 1000000;
+ while (samplep >= 0 && sample == -1) {
+ dbg_samples = samples;
+ dbg_samplep = samplep;
+
+ delta_freq = note_freq - samples[samplep].base_note;
+ if (delta_freq < 0)
+ delta_freq = -delta_freq;
+ if (delta_freq < best_delta) {
+ best_sample = samplep;
+ best_delta = delta_freq;
+ }
+ if (samples[samplep].low_note <= note_freq &&
+ note_freq <= samples[samplep].high_note)
+ sample = samplep;
+ else
+ samplep = samples[samplep].key; /* Follow link */
}
- if (sample == -1)
- sample = best_sample;
+ if (sample == -1)
+ sample = best_sample;
- if (sample == -1)
- {
- printk ("GUS: Patch %d not defined for note %d\n", patch, note_num);
- return 0; /* Should play default patch ??? */
+ if (sample == -1) {
+ printf("GUS: Patch %d not defined for note %d\n", patch, note_num);
+ return 0; /* Should play default patch ??? */
}
+ is16bits = (samples[sample].mode & WAVE_16_BITS) ? 1 : 0;
+ voices[voice].mode = samples[sample].mode;
+ voices[voice].patch_vol = samples[sample].volume;
- is16bits = (samples[sample].mode & WAVE_16_BITS) ? 1 : 0;
- voices[voice].mode = samples[sample].mode;
- voices[voice].patch_vol = samples[sample].volume;
+ if (voices[voice].mode & WAVE_ENVELOPES) {
+ int i;
- if (voices[voice].mode & WAVE_ENVELOPES)
- {
- int i;
-
- for (i = 0; i < 6; i++)
- {
- voices[voice].env_rate[i] = samples[sample].env_rate[i];
- voices[voice].env_offset[i] = samples[sample].env_offset[i];
+ for (i = 0; i < 6; i++) {
+ voices[voice].env_rate[i] = samples[sample].env_rate[i];
+ voices[voice].env_offset[i] = samples[sample].env_offset[i];
}
}
+ sample_map[voice] = sample;
- sample_map[voice] = sample;
-
- base_note = samples[sample].base_note / 100; /* Try to avoid overflows */
- note_freq /= 100;
+ base_note = samples[sample].base_note / 100; /* Try to avoid overflows */
+ note_freq /= 100;
- freq = samples[sample].base_freq * note_freq / base_note;
+ freq = samples[sample].base_freq * note_freq / base_note;
- voices[voice].orig_freq = freq;
+ voices[voice].orig_freq = freq;
- /*
- * Since the pitch bender may have been set before playing the note, we
- * have to calculate the bending now.
- */
-
- freq = compute_finetune (voices[voice].orig_freq, voices[voice].bender,
- voices[voice].bender_range);
- voices[voice].current_freq = freq;
-
- pan = (samples[sample].panning + voices[voice].panning) / 32;
- pan += 7;
- if (pan < 0)
- pan = 0;
- if (pan > 15)
- pan = 15;
+ /*
+ * Since the pitch bender may have been set before playing the note,
+ * we have to calculate the bending now.
+ */
- if (samples[sample].mode & WAVE_16_BITS)
- {
- mode |= 0x04; /* 16 bits */
- if ((sample_ptrs[sample] >> 18) !=
- ((sample_ptrs[sample] + samples[sample].len) >> 18))
- printk ("GUS: Sample address error\n");
+ freq = compute_finetune(voices[voice].orig_freq, voices[voice].bender,
+ voices[voice].bender_range);
+ voices[voice].current_freq = freq;
+
+ pan = (samples[sample].panning + voices[voice].panning) / 32;
+ pan += 7;
+ if (pan < 0)
+ pan = 0;
+ if (pan > 15)
+ pan = 15;
+
+ if (samples[sample].mode & WAVE_16_BITS) {
+ mode |= 0x04; /* 16 bits */
+ if ((sample_ptrs[sample] >> 18) !=
+ ((sample_ptrs[sample] + samples[sample].len) >> 18))
+ printf("GUS: Sample address error\n");
}
+ /*
+ * CAUTION! Interrupts disabled. Don't return before enabling
+ */
- /*************************************************************************
- * CAUTION! Interrupts disabled. Don't return before enabling
- *************************************************************************/
-
- DISABLE_INTR (flags);
- gus_select_voice (voice);
- gus_voice_off ();
- gus_rampoff ();
+ flags = splhigh();
+ gus_select_voice(voice);
+ gus_voice_off();
+ gus_rampoff();
- RESTORE_INTR (flags);
+ splx(flags);
- if (voices[voice].mode & WAVE_ENVELOPES)
- {
- compute_volume (voice, volume);
- init_envelope (voice);
+ if (voices[voice].mode & WAVE_ENVELOPES) {
+ compute_volume(voice, volume);
+ init_envelope(voice);
+ } else {
+ compute_and_set_volume(voice, volume, 0);
}
- else
- compute_and_set_volume (voice, volume, 0);
- DISABLE_INTR (flags);
- gus_select_voice (voice);
+ flags = splhigh();
+ 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); /* start=end */
- else
- gus_write_addr (0x0a, sample_ptrs[sample] + voices[voice].offset_pending,
- is16bits); /* Sample start=begin */
+ if (samples[sample].mode & WAVE_LOOP_BACK)
+ gus_write_addr(0x0a, sample_ptrs[sample] + samples[sample].len -
+ voices[voice].offset_pending, is16bits); /* start=end */
+ else
+ gus_write_addr(0x0a, sample_ptrs[sample] + voices[voice].offset_pending,
+ is16bits); /* Sample start=begin */
- if (samples[sample].mode & WAVE_LOOPING)
- {
- mode |= 0x08;
+ if (samples[sample].mode & WAVE_LOOPING) {
+ mode |= 0x08;
- if (samples[sample].mode & WAVE_BIDIR_LOOP)
- mode |= 0x10;
+ if (samples[sample].mode & WAVE_BIDIR_LOOP)
+ mode |= 0x10;
- if (samples[sample].mode & WAVE_LOOP_BACK)
- {
- gus_write_addr (0x0a,
- sample_ptrs[sample] + samples[sample].loop_end -
- voices[voice].offset_pending, is16bits);
- mode |= 0x40;
+ if (samples[sample].mode & WAVE_LOOP_BACK) {
+ gus_write_addr(0x0a,
+ sample_ptrs[sample] + samples[sample].loop_end -
+ voices[voice].offset_pending, is16bits);
+ mode |= 0x40;
}
-
- 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(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 */
+ } else {
+ mode |= 0x20; /* Loop IRQ at the end */
+ voices[voice].loop_irq_mode = LMODE_FINISH; /* Ramp down at the end */
+ voices[voice].loop_irq_parm = 1;
+ 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 */
}
- else
- {
- mode |= 0x20; /* Loop IRQ at the end */
- voices[voice].loop_irq_mode = LMODE_FINISH; /* Ramp down at the end */
- voices[voice].loop_irq_parm = 1;
- 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_voice_freq (freq);
- gus_voice_balance (pan);
- gus_voice_on (mode);
- RESTORE_INTR (flags);
+ gus_voice_freq(freq);
+ gus_voice_balance(pan);
+ gus_voice_on(mode);
+ splx(flags);
- return 0;
+ 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
- * ramping.
+ * when the note playing on the voice is changed. It uses volume ramping.
*/
static int
-guswave_start_note (int dev, int voice, int note_num, int volume)
+guswave_start_note(int dev, int voice, int note_num, int volume)
{
- long int flags;
- int mode;
- int ret_val = 0;
-
- DISABLE_INTR (flags);
- if (note_num == 255)
- {
- if (voices[voice].volume_irq_mode == VMODE_START_NOTE)
- voices[voice].volume_pending = volume;
- else
- {
- RESTORE_INTR (flags);
- ret_val = guswave_start_note2 (dev, voice, note_num, volume);
+ long int flags;
+ int mode;
+ int ret_val = 0;
+
+ flags = splhigh();
+ if (note_num == 255) {
+ 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);
}
- }
- else
- {
- gus_select_voice (voice);
- mode = gus_read8 (0x00);
- if (mode & 0x20)
- gus_write8 (0x00, mode & 0xdf); /* No interrupt! */
-
- voices[voice].offset_pending = 0;
- voices[voice].kill_pending = 0;
- voices[voice].volume_irq_mode = 0;
- voices[voice].loop_irq_mode = 0;
-
- if (voices[voice].sample_pending >= 0)
- {
- 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) || (int) ((gus_read16 (0x09) >> 4) < 2065))
- {
- ret_val = guswave_start_note2 (dev, voice, note_num, volume);
- }
- else
- {
- voices[voice].dev_pending = dev;
- voices[voice].note_pending = note_num;
- voices[voice].volume_pending = volume;
- voices[voice].volume_irq_mode = VMODE_START_NOTE;
-
- gus_rampoff ();
- gus_ramp_range (2000, 4065);
- gus_ramp_rate (0, 63);/* Fastest possible rate */
- gus_rampon (0x20 | 0x40); /* Ramp down, once, irq */
- RESTORE_INTR (flags);
+ } else {
+ gus_select_voice(voice);
+ mode = gus_read8(0x00);
+ if (mode & 0x20)
+ gus_write8(0x00, mode & 0xdf); /* No interrupt! */
+
+ voices[voice].offset_pending = 0;
+ voices[voice].kill_pending = 0;
+ voices[voice].volume_irq_mode = 0;
+ voices[voice].loop_irq_mode = 0;
+
+ if (voices[voice].sample_pending >= 0) {
+ splx(flags); /* Run temporarily with interrupts
+ * enabled */
+ guswave_set_instr(voices[voice].dev_pending, voice,
+ voices[voice].sample_pending);
+ voices[voice].sample_pending = -1;
+ flags = splhigh();
+ gus_select_voice(voice); /* Reselect the voice
+ * (just to be sure) */
+ }
+ if ((mode & 0x01) || (int) ((gus_read16(0x09) >> 4) < 2065)) {
+ ret_val = guswave_start_note2(dev, voice, note_num, volume);
+ } else {
+ voices[voice].dev_pending = dev;
+ voices[voice].note_pending = note_num;
+ voices[voice].volume_pending = volume;
+ voices[voice].volume_irq_mode = VMODE_START_NOTE;
+
+ gus_rampoff();
+ gus_ramp_range(2000, 4065);
+ gus_ramp_rate(0, 63); /* Fastest possible rate */
+ gus_rampon(0x20 | 0x40); /* Ramp down, once, irq */
}
}
- return ret_val;
+ splx(flags);
+ return ret_val;
}
static void
-guswave_reset (int dev)
+guswave_reset(int dev)
{
- int i;
+ int i;
- for (i = 0; i < 32; i++)
- {
- gus_voice_init (i);
- gus_voice_init2 (i);
+ for (i = 0; i < 32; i++) {
+ gus_voice_init(i);
+ gus_voice_init2(i);
}
}
static int
-guswave_open (int dev, int mode)
+guswave_open(int dev, int mode)
{
- int err;
+ int err;
+ int otherside = audio_devs[dev]->otherside;
- if (gus_busy)
- return RET_ERROR (EBUSY);
+ if (otherside != -1) {
+ if (audio_devs[otherside]->busy)
+ return -(EBUSY);
+ }
+ if (audio_devs[dev]->busy)
+ return -(EBUSY);
- gus_initialize ();
+ gus_initialize();
+ voice_alloc->timestamp = 0;
- if ((err = DMAbuf_open_dma (gus_devnum)) < 0)
- return err;
+ if ((err = DMAbuf_open_dma(gus_devnum)) < 0) {
+ printf("GUS: Loading saples without DMA\n");
+ gus_no_dma = 1; /* Upload samples using PIO */
+ } else
+ gus_no_dma = 0;
- RESET_WAIT_QUEUE (dram_sleeper, dram_sleep_flag);
- gus_busy = 1;
- active_device = GUS_DEV_WAVE;
+ dram_sleep_flag.aborting = 0;
+ dram_sleep_flag.mode = WK_NONE;
+ active_device = GUS_DEV_WAVE;
- gus_reset ();
+ audio_devs[dev]->busy = 1;
+ gus_reset();
- return 0;
+ return 0;
}
static void
-guswave_close (int dev)
+guswave_close(int dev)
{
- gus_busy = 0;
- active_device = 0;
- gus_reset ();
+ int otherside = audio_devs[dev]->otherside;
- DMAbuf_close_dma (gus_devnum);
+ if (otherside != -1) {
+ if (audio_devs[otherside]->busy)
+ return;
+ }
+ audio_devs[dev]->busy = 0;
+
+ active_device = 0;
+ gus_reset();
+
+ if (!gus_no_dma)
+ DMAbuf_close_dma(gus_devnum);
}
static int
-guswave_load_patch (int dev, int format, snd_rw_buf * addr,
- int offs, int count, int pmgr_flag)
+guswave_load_patch(int dev, int format, snd_rw_buf * addr,
+ int offs, int count, int pmgr_flag)
{
- struct patch_info patch;
- int instr;
- long sizeof_patch;
+ struct patch_info patch;
+ int instr;
+ long sizeof_patch;
- unsigned long blk_size, blk_end, left, src_offs, target;
+ u_long blk_size, blk_end, left, src_offs, target;
- sizeof_patch = (long) &patch.data[0] - (long) &patch; /* Header size */
+ sizeof_patch = (long) &patch.data[0] - (long) &patch; /* Header size */
- if (format != GUS_PATCH)
- {
- printk ("GUS Error: Invalid patch format (key) 0x%x\n", format);
- return RET_ERROR (EINVAL);
+ if (format != GUS_PATCH) {
+ printf("GUS Error: Invalid patch format (key) 0x%x\n", format);
+ return -(EINVAL);
}
-
- if (count < sizeof_patch)
- {
- printk ("GUS Error: Patch header too short\n");
- return RET_ERROR (EINVAL);
+ if (count < sizeof_patch) {
+ printf("GUS Error: Patch header too short\n");
+ return -(EINVAL);
}
+ count -= sizeof_patch;
- count -= sizeof_patch;
-
- if (free_sample >= MAX_SAMPLE)
- {
- printk ("GUS: Sample table full\n");
- return RET_ERROR (ENOSPC);
+ if (free_sample >= MAX_SAMPLE) {
+ printf("GUS: Sample table full\n");
+ return -(ENOSPC);
}
+ /*
+ * Copy the header from user space but ignore the first bytes which
+ * have been transferred already.
+ */
- /*
- * Copy the header from user space but ignore the first bytes which have
- * been transferred already.
- */
-
- COPY_FROM_USER (&((char *) &patch)[offs], addr, offs, sizeof_patch - offs);
+ if (uiomove(&((char *) &patch)[offs], sizeof_patch - offs, addr)) {
+ printf("audio: Bad copyin()!\n");
+ };
- instr = patch.instr_no;
+ instr = patch.instr_no;
- if (instr < 0 || instr > MAX_PATCH)
- {
- printk ("GUS: Invalid patch number %d\n", instr);
- return RET_ERROR (EINVAL);
+ if (instr < 0 || instr > MAX_PATCH) {
+ printf("GUS: Invalid patch number %d\n", instr);
+ return -(EINVAL);
}
-
- if (count < patch.len)
- {
- printk ("GUS Warning: Patch record too short (%d<%d)\n",
- count, (int) patch.len);
- patch.len = count;
+ if (count < patch.len) {
+ printf("GUS Warning: Patch record too short (%d<%d)\n",
+ count, (int) patch.len);
+ patch.len = count;
}
-
- if (patch.len <= 0 || patch.len > gus_mem_size)
- {
- printk ("GUS: Invalid sample length %d\n", (int) patch.len);
- return RET_ERROR (EINVAL);
+ if (patch.len <= 0 || patch.len > gus_mem_size) {
+ printf("GUS: Invalid sample length %d\n", (int) patch.len);
+ return -(EINVAL);
}
-
- if (patch.mode & WAVE_LOOPING)
- {
- if (patch.loop_start < 0 || patch.loop_start >= patch.len)
- {
- printk ("GUS: Invalid loop start\n");
- return RET_ERROR (EINVAL);
+ if (patch.mode & WAVE_LOOPING) {
+ if (patch.loop_start < 0 || patch.loop_start >= patch.len) {
+ printf("GUS: Invalid loop start\n");
+ return -(EINVAL);
}
-
- if (patch.loop_end < patch.loop_start || patch.loop_end > patch.len)
- {
- printk ("GUS: Invalid loop end\n");
- return RET_ERROR (EINVAL);
+ if (patch.loop_end < patch.loop_start || patch.loop_end > patch.len) {
+ printf("GUS: Invalid loop end\n");
+ return -(EINVAL);
}
}
-
- free_mem_ptr = (free_mem_ptr + 31) & ~31; /* 32 byte alignment */
+ free_mem_ptr = (free_mem_ptr + 31) & ~31; /* 32 byte alignment */
#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)
- {
- printk ("GUS: Sample (16 bit) too long %d\n", (int) patch.len);
- return RET_ERROR (ENOSPC);
+ if (patch.mode & WAVE_16_BITS) {
+ /*
+ * 16 bit samples must fit one 256k bank.
+ */
+ if (patch.len >= GUS_BANK_SIZE) {
+ printf("GUS: Sample (16 bit) too long %d\n", (int) patch.len);
+ return -(ENOSPC);
}
+ if ((free_mem_ptr / GUS_BANK_SIZE) !=
+ ((free_mem_ptr + patch.len) / GUS_BANK_SIZE)) {
+ u_long tmp_mem = /* Aligning to 256K */
+ ((free_mem_ptr / GUS_BANK_SIZE) + 1) * GUS_BANK_SIZE;
- if ((free_mem_ptr / GUS_BANK_SIZE) !=
- ((free_mem_ptr + patch.len) / GUS_BANK_SIZE))
- {
- unsigned long tmp_mem = /* Aling to 256K */
- ((free_mem_ptr / GUS_BANK_SIZE) + 1) * GUS_BANK_SIZE;
-
- if ((tmp_mem + patch.len) > gus_mem_size)
- return RET_ERROR (ENOSPC);
+ if ((tmp_mem + patch.len) > gus_mem_size)
+ return -(ENOSPC);
- free_mem_ptr = tmp_mem; /* This leaves unusable memory */
+ free_mem_ptr = tmp_mem; /* This leaves unusable memory */
}
}
+ if ((free_mem_ptr + patch.len) > gus_mem_size)
+ return -(ENOSPC);
- if ((free_mem_ptr + patch.len) > gus_mem_size)
- return RET_ERROR (ENOSPC);
+ sample_ptrs[free_sample] = free_mem_ptr;
- sample_ptrs[free_sample] = free_mem_ptr;
-
- /*
- * Tremolo is not possible with envelopes
- */
-
- if (patch.mode & WAVE_ENVELOPES)
- patch.mode &= ~WAVE_TREMOLO;
-
- 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
- */
+ /*
+ * Tremolo is not possible with envelopes
+ */
- left = patch.len;
- src_offs = 0;
- target = free_mem_ptr;
+ if (patch.mode & WAVE_ENVELOPES)
+ patch.mode &= ~WAVE_TREMOLO;
- while (left) /* Not completely transferred yet */
- {
- blk_size = audio_devs[gus_devnum]->buffsize;
- if (blk_size > left)
- blk_size = left;
+ bcopy(&patch, (char *) &samples[free_sample], sizeof_patch);
- /*
- * DMA cannot cross 256k bank boundaries. Check for that.
- */
- blk_end = target + blk_size;
-
- if ((target >> 18) != (blk_end >> 18))
- { /* Split the block */
+ /*
+ * Link this_one sample to the list of samples for patch 'instr'.
+ */
- blk_end &= ~(256 * 1024 - 1);
- blk_size = blk_end - target;
- }
+ samples[free_sample].key = patch_table[instr];
+ patch_table[instr] = free_sample;
-#if defined(GUS_NO_DMA) || defined(GUS_PATCH_NO_DMA)
- /*
- * For some reason the DMA is not possible. We have to use PIO.
- */
- {
- long i;
- unsigned char data;
+ /*
+ * Use DMA to transfer the wave data to the DRAM
+ */
- for (i = 0; i < blk_size; i++)
- {
- GET_BYTE_FROM_USER (data, addr, sizeof_patch + i);
- if (patch.mode & WAVE_UNSIGNED)
+ left = patch.len;
+ src_offs = 0;
+ target = free_mem_ptr;
- if (!(patch.mode & WAVE_16_BITS) || (i & 0x01))
- data ^= 0x80; /* Convert to signed */
- gus_poke (target + i, data);
- }
- }
-#else /* GUS_NO_DMA */
- {
- unsigned long address, hold_address;
- unsigned char dma_command;
- unsigned long flags;
+ while (left) { /* Not completely transferred yet */
+ /* blk_size = audio_devs[gus_devnum]->buffsize; */
+ blk_size = audio_devs[gus_devnum]->dmap_out->bytes_in_use;
+ if (blk_size > left)
+ blk_size = left;
/*
- * OK, move now. First in and then out.
+ * DMA cannot cross 256k bank boundaries. Check for that.
*/
+ blk_end = target + blk_size;
- COPY_FROM_USER (audio_devs[gus_devnum]->dmap->raw_buf[0],
- addr, sizeof_patch + src_offs,
- blk_size);
+ if ((target >> 18) != (blk_end >> 18)) { /* Split the block */
+ blk_end &= ~(256 * 1024 - 1);
+ blk_size = blk_end - target;
+ }
+ if (gus_no_dma) {
+ /*
+ * For some reason the DMA is not possible. We have
+ * to use PIO.
+ */
+ long i;
+ u_char data;
+
+ for (i = 0; i < blk_size; i++) {
+ uiomove((char *) &(data), 1, addr);
+ if (patch.mode & WAVE_UNSIGNED)
+ if (!(patch.mode & WAVE_16_BITS) || (i & 0x01))
+ data ^= 0x80; /* Convert to signed */
+ gus_poke(target + i, data);
+ }
+ } else {
+ u_long address, hold_address;
+ u_char dma_command;
+ u_long flags;
+
+ /*
+ * OK, move now. First in and then out.
+ */
+
+ if (uiomove(audio_devs[gus_devnum]->dmap_out->raw_buf, blk_size, addr)) {
+ printf("audio: Bad copyin()!\n");
+ };
+
+ flags = splhigh();
+ /******** INTERRUPTS DISABLED NOW ********/
+ gus_write8(0x41, 0); /* Disable GF1 DMA */
+ DMAbuf_start_dma(gus_devnum,
+ audio_devs[gus_devnum]->dmap_out->raw_buf_phys,
+ blk_size, 1);
+
+ /*
+ * Set the DRAM address for the wave data
+ */
+
+ address = target;
+
+ if (audio_devs[gus_devnum]->dmachan1 > 3) {
+ hold_address = address;
+ address = address >> 1;
+ address &= 0x0001ffffL;
+ address |= (hold_address & 0x000c0000L);
+ }
+ gus_write16(0x42, (address >> 4) & 0xffff); /* DRAM DMA address */
- DISABLE_INTR (flags); /******** INTERRUPTS DISABLED NOW ********/
- gus_write8 (0x41, 0); /* Disable GF1 DMA */
- DMAbuf_start_dma (gus_devnum,
- audio_devs[gus_devnum]->dmap->raw_buf_phys[0],
- blk_size, DMA_MODE_WRITE);
+ /*
+ * Start the DMA transfer
+ */
- /*
- * Set the DRAM address for the wave data
- */
+ dma_command = 0x21; /* IRQ enable, DMA start */
+ if (patch.mode & WAVE_UNSIGNED)
+ dma_command |= 0x80; /* Invert MSB */
+ if (patch.mode & WAVE_16_BITS)
+ dma_command |= 0x40; /* 16 bit _DATA_ */
+ if (audio_devs[gus_devnum]->dmachan1 > 3)
+ dma_command |= 0x04; /* 16 bit DMA _channel_ */
- address = target;
+ gus_write8(0x41, dma_command); /* Lets bo luteet (=bugs) */
- if (audio_devs[gus_devnum]->dmachan > 3)
- {
- hold_address = address;
- address = address >> 1;
- address &= 0x0001ffffL;
- address |= (hold_address & 0x000c0000L);
- }
+ /*
+ * Sleep here until the DRAM DMA done interrupt is
+ * served
+ */
+ active_device = GUS_DEV_WAVE;
- gus_write16 (0x42, (address >> 4) & 0xffff); /* DRAM DMA address */
- /*
- * Start the DMA transfer
- */
+ {
+ int chn;
- dma_command = 0x21; /* IRQ enable, DMA start */
- if (patch.mode & WAVE_UNSIGNED)
- dma_command |= 0x80; /* Invert MSB */
- if (patch.mode & WAVE_16_BITS)
- dma_command |= 0x40; /* 16 bit _DATA_ */
- if (audio_devs[gus_devnum]->dmachan > 3)
- dma_command |= 0x04; /* 16 bit DMA _channel_ */
+ dram_sleep_flag.mode = WK_SLEEP;
+ dram_sleeper = &chn;
+ DO_SLEEP(chn, dram_sleep_flag, hz);
- gus_write8 (0x41, dma_command); /* Lets bo luteet (=bugs) */
+ };
+ if ((dram_sleep_flag.mode & WK_TIMEOUT))
+ printf("GUS: DMA Transfer timed out\n");
+ splx(flags);
+ }
/*
- * Sleep here until the DRAM DMA done interrupt is served
+ * Now the next part
*/
- active_device = GUS_DEV_WAVE;
-
- DO_SLEEP (dram_sleeper, dram_sleep_flag, HZ);
- if (TIMED_OUT (dram_sleeper, dram_sleep_flag))
- printk ("GUS: DMA Transfer timed out\n");
- RESTORE_INTR (flags);
- }
-#endif /* GUS_NO_DMA */
-
- /*
- * Now the next part
- */
- left -= blk_size;
- src_offs += blk_size;
- target += blk_size;
+ left -= blk_size;
+ src_offs += blk_size;
+ target += blk_size;
- gus_write8 (0x41, 0); /* Stop DMA */
+ gus_write8(0x41, 0); /* Stop DMA */
}
- free_mem_ptr += patch.len;
+ free_mem_ptr += patch.len;
- if (!pmgr_flag)
- pmgr_inform (dev, PM_E_PATCH_LOADED, instr, free_sample, 0, 0);
- free_sample++;
- return 0;
+ if (!pmgr_flag)
+ pmgr_inform(dev, PM_E_PATCH_LOADED, instr, free_sample, 0, 0);
+ free_sample++;
+ return 0;
}
static void
-guswave_hw_control (int dev, unsigned char *event)
+guswave_hw_control(int dev, u_char *event)
{
- int voice, cmd;
- unsigned short p1, p2;
- unsigned long plong, flags;
-
- cmd = event[2];
- voice = event[3];
- p1 = *(unsigned short *) &event[4];
- p2 = *(unsigned short *) &event[6];
- plong = *(unsigned long *) &event[4];
-
- if ((voices[voice].volume_irq_mode == VMODE_START_NOTE) &&
- (cmd != _GUS_VOICESAMPLE) && (cmd != _GUS_VOICE_POS))
- do_volume_irq (voice);
-
- switch (cmd)
- {
-
- case _GUS_NUMVOICES:
- DISABLE_INTR (flags);
- gus_select_voice (voice);
- gus_select_max_voices (p1);
- RESTORE_INTR (flags);
- break;
-
- case _GUS_VOICESAMPLE:
- guswave_set_instr (dev, voice, p1);
- break;
-
- case _GUS_VOICEON:
- DISABLE_INTR (flags);
- gus_select_voice (voice);
- p1 &= ~0x20; /* Don't allow interrupts */
- gus_voice_on (p1);
- RESTORE_INTR (flags);
- break;
-
- case _GUS_VOICEOFF:
- DISABLE_INTR (flags);
- gus_select_voice (voice);
- gus_voice_off ();
- RESTORE_INTR (flags);
- break;
-
- case _GUS_VOICEFADE:
- gus_voice_fade (voice);
- break;
-
- case _GUS_VOICEMODE:
- DISABLE_INTR (flags);
- gus_select_voice (voice);
- p1 &= ~0x20; /* Don't allow interrupts */
- gus_voice_mode (p1);
- RESTORE_INTR (flags);
- break;
-
- case _GUS_VOICEBALA:
- DISABLE_INTR (flags);
- gus_select_voice (voice);
- gus_voice_balance (p1);
- RESTORE_INTR (flags);
- break;
-
- case _GUS_VOICEFREQ:
- DISABLE_INTR (flags);
- gus_select_voice (voice);
- gus_voice_freq (plong);
- RESTORE_INTR (flags);
- break;
-
- case _GUS_VOICEVOL:
- DISABLE_INTR (flags);
- gus_select_voice (voice);
- gus_voice_volume (p1);
- RESTORE_INTR (flags);
- break;
-
- case _GUS_VOICEVOL2: /* Just update the software voice level */
- voices[voice].initial_volume =
- voices[voice].current_volume = p1;
- break;
-
- case _GUS_RAMPRANGE:
- if (voices[voice].mode & WAVE_ENVELOPES)
- break; /* NO-NO */
- DISABLE_INTR (flags);
- gus_select_voice (voice);
- gus_ramp_range (p1, p2);
- RESTORE_INTR (flags);
- break;
-
- case _GUS_RAMPRATE:
- if (voices[voice].mode & WAVE_ENVELOPES)
- break; /* NJET-NJET */
- DISABLE_INTR (flags);
- gus_select_voice (voice);
- gus_ramp_rate (p1, p2);
- RESTORE_INTR (flags);
- break;
-
- case _GUS_RAMPMODE:
- if (voices[voice].mode & WAVE_ENVELOPES)
- break; /* NO-NO */
- DISABLE_INTR (flags);
- gus_select_voice (voice);
- p1 &= ~0x20; /* Don't allow interrupts */
- gus_ramp_mode (p1);
- RESTORE_INTR (flags);
- break;
-
- case _GUS_RAMPON:
- if (voices[voice].mode & WAVE_ENVELOPES)
- break; /* EI-EI */
- DISABLE_INTR (flags);
- gus_select_voice (voice);
- p1 &= ~0x20; /* Don't allow interrupts */
- gus_rampon (p1);
- RESTORE_INTR (flags);
- break;
-
- case _GUS_RAMPOFF:
- if (voices[voice].mode & WAVE_ENVELOPES)
- break; /* NEJ-NEJ */
- DISABLE_INTR (flags);
- gus_select_voice (voice);
- gus_rampoff ();
- RESTORE_INTR (flags);
- break;
-
- case _GUS_VOLUME_SCALE:
- volume_base = p1;
- volume_scale = p2;
- break;
-
- case _GUS_VOICE_POS:
- DISABLE_INTR (flags);
- gus_select_voice (voice);
- gus_set_voice_pos (voice, plong);
- RESTORE_INTR (flags);
- break;
-
- default:;
- }
+ int voice, cmd;
+ u_short p1, p2;
+ u_long plong, flags;
+
+ cmd = event[2];
+ voice = event[3];
+ p1 = *(u_short *) &event[4];
+ p2 = *(u_short *) &event[6];
+ plong = *(u_long *) &event[4];
+
+ if ((voices[voice].volume_irq_mode == VMODE_START_NOTE) &&
+ (cmd != _GUS_VOICESAMPLE) && (cmd != _GUS_VOICE_POS))
+ do_volume_irq(voice);
+
+ switch (cmd) {
+
+ case _GUS_NUMVOICES:
+ flags = splhigh();
+ gus_select_voice(voice);
+ gus_select_max_voices(p1);
+ splx(flags);
+ break;
+
+ case _GUS_VOICESAMPLE:
+ guswave_set_instr(dev, voice, p1);
+ break;
+
+ case _GUS_VOICEON:
+ flags = splhigh();
+ gus_select_voice(voice);
+ p1 &= ~0x20; /* Don't allow interrupts */
+ gus_voice_on(p1);
+ splx(flags);
+ break;
+
+ case _GUS_VOICEOFF:
+ flags = splhigh();
+ gus_select_voice(voice);
+ gus_voice_off();
+ splx(flags);
+ break;
+
+ case _GUS_VOICEFADE:
+ gus_voice_fade(voice);
+ break;
+
+ case _GUS_VOICEMODE:
+ flags = splhigh();
+ gus_select_voice(voice);
+ p1 &= ~0x20; /* Don't allow interrupts */
+ gus_voice_mode(p1);
+ splx(flags);
+ break;
+
+ case _GUS_VOICEBALA:
+ flags = splhigh();
+ gus_select_voice(voice);
+ gus_voice_balance(p1);
+ splx(flags);
+ break;
+
+ case _GUS_VOICEFREQ:
+ flags = splhigh();
+ gus_select_voice(voice);
+ gus_voice_freq(plong);
+ splx(flags);
+ break;
+
+ case _GUS_VOICEVOL:
+ flags = splhigh();
+ gus_select_voice(voice);
+ gus_voice_volume(p1);
+ splx(flags);
+ break;
+
+ case _GUS_VOICEVOL2: /* Just update the software voice level */
+ voices[voice].initial_volume =
+ voices[voice].current_volume = p1;
+ break;
+
+ case _GUS_RAMPRANGE:
+ if (voices[voice].mode & WAVE_ENVELOPES)
+ break; /* NO-NO */
+ flags = splhigh();
+ gus_select_voice(voice);
+ gus_ramp_range(p1, p2);
+ splx(flags);
+ break;
+
+ case _GUS_RAMPRATE:
+ if (voices[voice].mode & WAVE_ENVELOPES)
+ break; /* NJET-NJET */
+ flags = splhigh();
+ gus_select_voice(voice);
+ gus_ramp_rate(p1, p2);
+ splx(flags);
+ break;
+
+ case _GUS_RAMPMODE:
+ if (voices[voice].mode & WAVE_ENVELOPES)
+ break; /* NO-NO */
+ flags = splhigh();
+ gus_select_voice(voice);
+ p1 &= ~0x20; /* Don't allow interrupts */
+ gus_ramp_mode(p1);
+ splx(flags);
+ break;
+
+ case _GUS_RAMPON:
+ if (voices[voice].mode & WAVE_ENVELOPES)
+ break; /* EI-EI */
+ flags = splhigh();
+ gus_select_voice(voice);
+ p1 &= ~0x20; /* Don't allow interrupts */
+ gus_rampon(p1);
+ splx(flags);
+ break;
+
+ case _GUS_RAMPOFF:
+ if (voices[voice].mode & WAVE_ENVELOPES)
+ break; /* NEJ-NEJ */
+ flags = splhigh();
+ gus_select_voice(voice);
+ gus_rampoff();
+ splx(flags);
+ break;
+
+ case _GUS_VOLUME_SCALE:
+ volume_base = p1;
+ volume_scale = p2;
+ break;
+
+ case _GUS_VOICE_POS:
+ flags = splhigh();
+ gus_select_voice(voice);
+ gus_set_voice_pos(voice, plong);
+ splx(flags);
+ break;
+
+ default:;
+ }
}
static int
-gus_sampling_set_speed (int speed)
+gus_sampling_set_speed(int speed)
{
- if (speed <= 0)
- return gus_sampling_speed;
- if (speed > 44100)
- speed = 44100;
+ if (speed <= 0)
+ speed = gus_sampling_speed;
+
+ RANGE(speed, 4000, 44100);
+ gus_sampling_speed = speed;
- gus_sampling_speed = speed;
- return speed;
+ if (only_read_access) {
+ /* Compute nearest valid recording speed and return it */
+
+ speed = (9878400 / (gus_sampling_speed + 2)) / 16;
+ speed = (9878400 / (speed * 16)) - 2;
+ }
+ return speed;
}
static int
-gus_sampling_set_channels (int channels)
+gus_sampling_set_channels(int channels)
{
- if (!channels)
- return gus_sampling_channels;
- if (channels > 2)
- channels = 2;
- if (channels < 1)
- channels = 1;
- gus_sampling_channels = channels;
- return channels;
+ if (!channels)
+ return gus_sampling_channels;
+ RANGE(channels, 1, 2);
+ gus_sampling_channels = channels;
+ return channels;
}
static int
-gus_sampling_set_bits (int bits)
+gus_sampling_set_bits(int bits)
{
- if (!bits)
- return gus_sampling_bits;
+ if (!bits)
+ return gus_sampling_bits;
+
+ if (bits != 8 && bits != 16)
+ bits = 8;
- if (bits != 8 && bits != 16)
- bits = 8;
+ if (only_8_bits)
+ bits = 8;
- gus_sampling_bits = bits;
- return bits;
+ gus_sampling_bits = bits;
+ return bits;
}
static int
-gus_sampling_ioctl (int dev, unsigned int cmd, unsigned int arg, int local)
+gus_sampling_ioctl(int dev, u_int cmd, ioctl_arg arg, int local)
{
- switch (cmd)
- {
- case SOUND_PCM_WRITE_RATE:
- if (local)
- return gus_sampling_set_speed (arg);
- return IOCTL_OUT (arg, gus_sampling_set_speed (IOCTL_IN (arg)));
- break;
-
- case SOUND_PCM_READ_RATE:
- if (local)
- return gus_sampling_speed;
- return IOCTL_OUT (arg, gus_sampling_speed);
- break;
-
- case SNDCTL_DSP_STEREO:
- if (local)
- return gus_sampling_set_channels (arg + 1) - 1;
- return IOCTL_OUT (arg, gus_sampling_set_channels (IOCTL_IN (arg) + 1) - 1);
- break;
-
- case SOUND_PCM_WRITE_CHANNELS:
- if (local)
- return gus_sampling_set_channels (arg);
- return IOCTL_OUT (arg, gus_sampling_set_channels (IOCTL_IN (arg)));
- break;
-
- case SOUND_PCM_READ_CHANNELS:
- if (local)
- return gus_sampling_channels;
- return IOCTL_OUT (arg, gus_sampling_channels);
- break;
-
- case SNDCTL_DSP_SETFMT:
- if (local)
- return gus_sampling_set_bits (arg);
- return IOCTL_OUT (arg, gus_sampling_set_bits (IOCTL_IN (arg)));
- break;
-
- case SOUND_PCM_READ_BITS:
- if (local)
- return gus_sampling_bits;
- return IOCTL_OUT (arg, gus_sampling_bits);
-
- case SOUND_PCM_WRITE_FILTER: /* NOT POSSIBLE */
- return IOCTL_OUT (arg, RET_ERROR (EINVAL));
- break;
-
- case SOUND_PCM_READ_FILTER:
- return IOCTL_OUT (arg, RET_ERROR (EINVAL));
- break;
+ switch (cmd) {
+ case SOUND_PCM_WRITE_RATE:
+ if (local)
+ return gus_sampling_set_speed((int) arg);
+ return *(int *) arg = gus_sampling_set_speed((*(int *) arg));
+ break;
+
+ case SOUND_PCM_READ_RATE:
+ if (local)
+ return gus_sampling_speed;
+ return *(int *) arg = gus_sampling_speed;
+ break;
+
+ case SNDCTL_DSP_STEREO:
+ if (local)
+ return gus_sampling_set_channels((int) arg + 1) - 1;
+ return *(int *) arg = gus_sampling_set_channels((*(int *) arg) + 1) - 1;
+ break;
+
+ case SOUND_PCM_WRITE_CHANNELS:
+ if (local)
+ return gus_sampling_set_channels((int) arg);
+ return *(int *) arg = gus_sampling_set_channels((*(int *) arg));
+ break;
+
+ case SOUND_PCM_READ_CHANNELS:
+ if (local)
+ return gus_sampling_channels;
+ return *(int *) arg = gus_sampling_channels;
+ break;
+
+ case SNDCTL_DSP_SETFMT:
+ if (local)
+ return gus_sampling_set_bits((int) arg);
+ return *(int *) arg = gus_sampling_set_bits((*(int *) arg));
+ break;
+
+ case SOUND_PCM_READ_BITS:
+ if (local)
+ return gus_sampling_bits;
+ return *(int *) arg = gus_sampling_bits;
+
+ case SOUND_PCM_WRITE_FILTER: /* NOT POSSIBLE */
+ return *(int *) arg = -(EINVAL);
+ break;
+
+ case SOUND_PCM_READ_FILTER:
+ return *(int *) arg = -(EINVAL);
+ break;
- default:
- return RET_ERROR (EINVAL);
- }
- return RET_ERROR (EINVAL);
+ }
+ return -(EINVAL);
}
static void
-gus_sampling_reset (int dev)
+gus_sampling_reset(int dev)
{
+ if (recording_active) {
+ gus_write8(0x49, 0x00); /* Halt recording */
+ set_input_volumes();
+ }
}
static int
-gus_sampling_open (int dev, int mode)
+gus_sampling_open(int dev, int mode)
{
-#ifdef GUS_NO_DMA
- printk ("GUS: DMA mode not enabled. Device not supported\n");
- return RET_ERROR (ENXIO);
-#endif
- if (gus_busy)
- return RET_ERROR (EBUSY);
+ int otherside = audio_devs[dev]->otherside;
+ if (otherside != -1) {
+ if (audio_devs[otherside]->busy)
+ return -(EBUSY);
+ }
+ if (audio_devs[dev]->busy)
+ return -(EBUSY);
- gus_initialize ();
- gus_busy = 1;
- active_device = 0;
+ gus_initialize();
- gus_reset ();
- reset_sample_memory ();
- gus_select_max_voices (14);
+ active_device = 0;
- pcm_active = 0;
- dma_active = 0;
- pcm_opened = 1;
- if (mode & OPEN_READ)
- {
- recording_active = 1;
- set_input_volumes ();
- }
+ gus_reset();
+ reset_sample_memory();
+ gus_select_max_voices(14);
- return 0;
+ pcm_active = 0;
+ dma_active = 0;
+ pcm_opened = 1;
+ audio_devs[dev]->busy = 1;
+
+ if (mode & OPEN_READ) {
+ recording_active = 1;
+ set_input_volumes();
+ }
+ only_read_access = !(mode & OPEN_WRITE);
+ only_8_bits = mode & OPEN_READ;
+ if (only_8_bits)
+ audio_devs[dev]->format_mask = AFMT_U8;
+ else
+ audio_devs[dev]->format_mask = AFMT_U8 | AFMT_S16_LE;
+
+ return 0;
}
static void
-gus_sampling_close (int dev)
+gus_sampling_close(int dev)
{
- gus_reset ();
- gus_busy = 0;
- pcm_opened = 0;
- active_device = 0;
+ int otherside = audio_devs[dev]->otherside;
+ audio_devs[dev]->busy = 0;
- if (recording_active)
- set_input_volumes ();
+ if (otherside != -1) {
+ if (audio_devs[otherside]->busy)
+ return;
+ }
+ gus_reset();
- recording_active = 0;
+ pcm_opened = 0;
+ active_device = 0;
+
+ if (recording_active) {
+ gus_write8(0x49, 0x00); /* Halt recording */
+ set_input_volumes();
+ }
+ recording_active = 0;
}
static void
-gus_sampling_update_volume (void)
+gus_sampling_update_volume(void)
{
- unsigned long flags;
- int voice;
-
- DISABLE_INTR (flags);
- if (pcm_active && pcm_opened)
- for (voice = 0; voice < gus_sampling_channels; voice++)
- {
- gus_select_voice (voice);
- gus_rampoff ();
- gus_voice_volume (1530 + (25 * gus_pcm_volume));
- gus_ramp_range (65, 1530 + (25 * gus_pcm_volume));
- }
- RESTORE_INTR (flags);
+ u_long flags;
+ int voice;
+
+ if (pcm_active && pcm_opened)
+ for (voice = 0; voice < gus_sampling_channels; voice++) {
+ flags = splhigh();
+ gus_select_voice(voice);
+ gus_rampoff();
+ gus_voice_volume(1530 + (25 * gus_pcm_volume));
+ gus_ramp_range(65, 1530 + (25 * gus_pcm_volume));
+ splx(flags);
+ }
}
static void
-play_next_pcm_block (void)
+play_next_pcm_block(void)
{
- unsigned long flags;
- int speed = gus_sampling_speed;
- int this_one, is16bits, chn;
- unsigned long dram_loc;
- unsigned char mode[2], ramp_mode[2];
+ u_long flags;
+ int speed = gus_sampling_speed;
+ int this_one, is16bits, chn;
+ u_long dram_loc;
+ u_char mode[2], ramp_mode[2];
- if (!pcm_qlen)
- return;
+ if (!pcm_qlen)
+ return;
- this_one = pcm_head;
+ this_one = pcm_head;
- for (chn = 0; chn < gus_sampling_channels; chn++)
- {
- mode[chn] = 0x00;
- ramp_mode[chn] = 0x03; /* Ramping and rollover off */
-
- if (chn == 0)
- {
- mode[chn] |= 0x20; /* Loop IRQ */
- voices[chn].loop_irq_mode = LMODE_PCM;
- }
-
- if (gus_sampling_bits != 8)
- {
- is16bits = 1;
- mode[chn] |= 0x04; /* 16 bit data */
- }
- else
- is16bits = 0;
-
- dram_loc = this_one * pcm_bsize;
- dram_loc += chn * pcm_banksize;
-
- if (this_one == (pcm_nblk - 1)) /* Last fragment of the DRAM buffer */
- {
- mode[chn] |= 0x08; /* Enable loop */
- ramp_mode[chn] = 0x03;/* Disable rollover bit */
- }
- else
- {
- if (chn == 0)
- ramp_mode[chn] = 0x04; /* Enable rollover bit */
- }
-
- DISABLE_INTR (flags);
- gus_select_voice (chn);
- gus_voice_freq (speed);
-
- if (gus_sampling_channels == 1)
- gus_voice_balance (7); /* mono */
- else if (chn == 0)
- gus_voice_balance (0); /* left */
- else
- gus_voice_balance (15); /* right */
-
- if (!pcm_active) /* Playback not already active */
- {
- /*
- * 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 ();
- 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 (0x02, chn * pcm_banksize, is16bits); /* Loop start */
-
- if (chn != 0)
- gus_write_addr (0x04, pcm_banksize + (pcm_bsize * pcm_nblk),
- is16bits); /* Loop end location */
- }
-
- if (chn == 0)
- gus_write_addr (0x04, dram_loc + pcm_datasize[this_one],
- is16bits); /* Loop end location */
- else
- mode[chn] |= 0x08; /* Enable looping */
-
- if (pcm_datasize[this_one] != pcm_bsize)
- {
- /*
- * Incompletely filled block. Possibly the last one.
- */
- if (chn == 0)
- {
- mode[chn] &= ~0x08; /* Disable looping */
- mode[chn] |= 0x20;/* Enable IRQ at the end */
- voices[0].loop_irq_mode = LMODE_PCM_STOP;
- ramp_mode[chn] = 0x03; /* No rollover bit */
- }
- else
- {
- gus_write_addr (0x04, dram_loc + pcm_datasize[this_one],
- is16bits); /* Loop end location */
- mode[chn] &= ~0x08; /* Disable looping */
- }
+ for (chn = 0; chn < gus_sampling_channels; chn++) {
+ mode[chn] = 0x00;
+ ramp_mode[chn] = 0x03; /* Ramping and rollover off */
+
+ if (chn == 0) {
+ mode[chn] |= 0x20; /* Loop IRQ */
+ voices[chn].loop_irq_mode = LMODE_PCM;
+ }
+ if (gus_sampling_bits != 8) {
+ is16bits = 1;
+ mode[chn] |= 0x04; /* 16 bit data */
+ } else
+ is16bits = 0;
+
+ dram_loc = this_one * pcm_bsize;
+ dram_loc += chn * pcm_banksize;
+
+ if (this_one == (pcm_nblk - 1)) { /* Last fragment of the
+ * DRAM buffer */
+ mode[chn] |= 0x08; /* Enable loop */
+ ramp_mode[chn] = 0x03; /* Disable rollover bit */
+ } else {
+ if (chn == 0)
+ ramp_mode[chn] = 0x04; /* Enable rollover bit */
}
- RESTORE_INTR (flags);
+ flags = splhigh();
+ gus_select_voice(chn);
+ gus_voice_freq(speed);
+
+ if (gus_sampling_channels == 1)
+ gus_voice_balance(7); /* mono */
+ else if (chn == 0)
+ gus_voice_balance(0); /* left */
+ else
+ gus_voice_balance(15); /* right */
+
+ if (!pcm_active) { /* Playback not already active */
+ /*
+ * 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();
+ 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(0x02, chn * pcm_banksize, is16bits); /* Loop start */
+
+ if (chn != 0)
+ gus_write_addr(0x04, pcm_banksize + (pcm_bsize * pcm_nblk) - 1,
+ is16bits); /* Loop end location */
+ }
+ if (chn == 0)
+ gus_write_addr(0x04, dram_loc + pcm_datasize[this_one] - 1,
+ is16bits); /* Loop end location */
+ else
+ mode[chn] |= 0x08; /* Enable looping */
+
+ if (pcm_datasize[this_one] != pcm_bsize) {
+ /*
+ * Incompletely filled block. Possibly the last one.
+ */
+ if (chn == 0) {
+ mode[chn] &= ~0x08; /* Disable looping */
+ mode[chn] |= 0x20; /* Enable IRQ at the end */
+ voices[0].loop_irq_mode = LMODE_PCM_STOP;
+ ramp_mode[chn] = 0x03; /* No rollover bit */
+ } else {
+ gus_write_addr(0x04, dram_loc + pcm_datasize[this_one],
+ is16bits); /* Loop end location */
+ mode[chn] &= ~0x08; /* Disable looping */
+ }
+ }
+ splx(flags);
}
- for (chn = 0; chn < gus_sampling_channels; chn++)
- {
- DISABLE_INTR (flags);
- gus_select_voice (chn);
- gus_write8 (0x0d, ramp_mode[chn]);
- gus_voice_on (mode[chn]);
- RESTORE_INTR (flags);
+ for (chn = 0; chn < gus_sampling_channels; chn++) {
+ flags = splhigh();
+ gus_select_voice(chn);
+ gus_write8(0x0d, ramp_mode[chn]);
+ gus_voice_on(mode[chn]);
+ splx(flags);
}
- pcm_active = 1;
+ pcm_active = 1;
}
static void
-gus_transfer_output_block (int dev, unsigned long buf,
- int total_count, int intrflag, int chn)
+gus_transfer_output_block(int dev, u_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.
- */
-
- int this_one, count;
- unsigned long flags;
- unsigned char dma_command;
- unsigned long address, hold_address;
-
- DISABLE_INTR (flags);
-
- count = total_count / gus_sampling_channels;
-
- if (chn == 0)
- {
- if (pcm_qlen >= pcm_nblk)
- printk ("GUS Warning: PCM buffers out of sync\n");
+ /*
+ * 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.
+ */
- this_one = pcm_current_block = pcm_tail;
- pcm_qlen++;
- pcm_tail = (pcm_tail + 1) % pcm_nblk;
- pcm_datasize[this_one] = count;
- }
- else
- this_one = pcm_current_block;
+ int this_one, count;
+ u_long flags;
+ u_char dma_command;
+ u_long address, hold_address;
- gus_write8 (0x41, 0); /* Disable GF1 DMA */
- DMAbuf_start_dma (dev, buf + (chn * count), count, DMA_MODE_WRITE);
+ flags = splhigh();
- address = this_one * pcm_bsize;
- address += chn * pcm_banksize;
+ count = total_count / gus_sampling_channels;
- if (audio_devs[dev]->dmachan > 3)
- {
- hold_address = address;
- address = address >> 1;
- address &= 0x0001ffffL;
- address |= (hold_address & 0x000c0000L);
- }
+ if (chn == 0) {
+ if (pcm_qlen >= pcm_nblk)
+ printf("GUS Warning: PCM buffers out of sync\n");
- gus_write16 (0x42, (address >> 4) & 0xffff); /* DRAM DMA address */
+ this_one = pcm_current_block = pcm_tail;
+ pcm_qlen++;
+ pcm_tail = (pcm_tail + 1) % pcm_nblk;
+ pcm_datasize[this_one] = count;
+ } else
+ this_one = pcm_current_block;
- dma_command = 0x21; /* IRQ enable, DMA start */
+ gus_write8(0x41, 0); /* Disable GF1 DMA */
+ DMAbuf_start_dma(dev, buf + (chn * count), count, 1);
- if (gus_sampling_bits != 8)
- dma_command |= 0x40; /* 16 bit _DATA_ */
- else
- dma_command |= 0x80; /* Invert MSB */
+ address = this_one * pcm_bsize;
+ address += chn * pcm_banksize;
- if (audio_devs[dev]->dmachan > 3)
- dma_command |= 0x04; /* 16 bit DMA channel */
+ if (audio_devs[dev]->dmachan1 > 3) {
+ hold_address = address;
+ address = address >> 1;
+ address &= 0x0001ffffL;
+ address |= (hold_address & 0x000c0000L);
+ }
+ gus_write16(0x42, (address >> 4) & 0xffff); /* DRAM DMA address */
- gus_write8 (0x41, dma_command); /* Kickstart */
+ dma_command = 0x21; /* IRQ enable, DMA start */
- if (chn == (gus_sampling_channels - 1)) /* Last channel */
- {
- /*
- * Last (right or mono) channel data
- */
- dma_active = 1; /* DMA started. There is a unacknowledged buffer */
- active_device = GUS_DEV_PCM_DONE;
- if (!pcm_active && (pcm_qlen > 0 || count < pcm_bsize))
- {
- play_next_pcm_block ();
+ if (gus_sampling_bits != 8)
+ dma_command |= 0x40; /* 16 bit _DATA_ */
+ else
+ dma_command |= 0x80; /* Invert MSB */
+
+ if (audio_devs[dev]->dmachan1 > 3)
+ dma_command |= 0x04; /* 16 bit DMA channel */
+
+ gus_write8(0x41, dma_command); /* Kickstart */
+
+ if (chn == (gus_sampling_channels - 1)) { /* Last channel */
+ /*
+ * Last (right or mono) channel data
+ */
+ dma_active = 1; /* DMA started. There is a unacknowledged
+ * buffer */
+ active_device = GUS_DEV_PCM_DONE;
+ if (!pcm_active && (pcm_qlen > 0 || count < pcm_bsize)) {
+ play_next_pcm_block();
+ }
+ } else {
+ /*
+ * Left channel data. The right channel is transferred after
+ * DMA interrupt
+ */
+ active_device = GUS_DEV_PCM_CONTINUE;
}
- }
- else
- {
- /*
- * Left channel data. The right channel
- * is transferred after DMA interrupt
- */
- active_device = GUS_DEV_PCM_CONTINUE;
- }
- RESTORE_INTR (flags);
+ splx(flags);
}
static void
-gus_sampling_output_block (int dev, unsigned long buf, int total_count,
- int intrflag, int restart_dma)
+gus_sampling_output_block(int dev, u_long buf, int total_count,
+ int intrflag, int restart_dma)
{
- pcm_current_buf = buf;
- pcm_current_count = total_count;
- pcm_current_intrflag = intrflag;
- pcm_current_dev = dev;
- gus_transfer_output_block (dev, buf, total_count, intrflag, 0);
+ pcm_current_buf = buf;
+ pcm_current_count = total_count;
+ pcm_current_intrflag = intrflag;
+ pcm_current_dev = dev;
+ gus_transfer_output_block(dev, buf, total_count, intrflag, 0);
}
static void
-gus_sampling_start_input (int dev, unsigned long buf, int count,
- int intrflag, int restart_dma)
+gus_sampling_start_input(int dev, u_long buf, int count,
+ int intrflag, int restart_dma)
{
- unsigned long flags;
- unsigned char mode;
+ u_long flags;
+ u_char mode;
- DISABLE_INTR (flags);
+ flags = splhigh();
- DMAbuf_start_dma (dev, buf, count, DMA_MODE_READ);
+ DMAbuf_start_dma(dev, buf, count, 0);
- mode = 0xa0; /* DMA IRQ enabled, invert MSB */
+ mode = 0xa0; /* DMA IRQ enabled, invert MSB */
- if (audio_devs[dev]->dmachan > 3)
- mode |= 0x04; /* 16 bit DMA channel */
- if (gus_sampling_channels > 1)
- mode |= 0x02; /* Stereo */
- mode |= 0x01; /* DMA enable */
+ if (audio_devs[dev]->dmachan2 > 3)
+ mode |= 0x04; /* 16 bit DMA channel */
+ if (gus_sampling_channels > 1)
+ mode |= 0x02; /* Stereo */
+ mode |= 0x01; /* DMA enable */
- gus_write8 (0x49, mode);
+ gus_write8(0x49, mode);
- RESTORE_INTR (flags);
+ splx(flags);
}
static int
-gus_sampling_prepare_for_input (int dev, int bsize, int bcount)
+gus_sampling_prepare_for_input(int dev, int bsize, int bcount)
{
- unsigned int rate;
+ u_int rate;
- rate = (9878400 / (gus_sampling_speed + 2)) / 16;
+ rate = (9878400 / (gus_sampling_speed + 2)) / 16;
- gus_write8 (0x48, rate & 0xff); /* Set sampling rate */
+ gus_write8(0x48, rate & 0xff); /* Set sampling rate */
- if (gus_sampling_bits != 8)
- {
- printk ("GUS Error: 16 bit recording not supported\n");
- return RET_ERROR (EINVAL);
+ if (gus_sampling_bits != 8) {
+ printf("GUS Error: 16 bit recording not supported\n");
+ return -(EINVAL);
}
-
- return 0;
+ return 0;
}
static int
-gus_sampling_prepare_for_output (int dev, int bsize, int bcount)
+gus_sampling_prepare_for_output(int dev, int bsize, int bcount)
{
- int i;
+ int i;
- long mem_ptr, mem_size;
+ long mem_ptr, mem_size;
- mem_ptr = 0;
- mem_size = gus_mem_size / gus_sampling_channels;
+ mem_ptr = 0;
+ mem_size = gus_mem_size / gus_sampling_channels;
- if (mem_size > (256 * 1024))
- mem_size = 256 * 1024;
+ if (mem_size > (256 * 1024))
+ mem_size = 256 * 1024;
- pcm_bsize = bsize / gus_sampling_channels;
- pcm_head = pcm_tail = pcm_qlen = 0;
+ pcm_bsize = bsize / gus_sampling_channels;
+ pcm_head = pcm_tail = pcm_qlen = 0;
- pcm_nblk = MAX_PCM_BUFFERS;
- if ((pcm_bsize * pcm_nblk) > mem_size)
- pcm_nblk = mem_size / pcm_bsize;
+ pcm_nblk = MAX_PCM_BUFFERS;
+ if ((pcm_bsize * pcm_nblk) > mem_size)
+ pcm_nblk = mem_size / pcm_bsize;
- for (i = 0; i < pcm_nblk; i++)
- pcm_datasize[i] = 0;
+ for (i = 0; i < pcm_nblk; i++)
+ pcm_datasize[i] = 0;
- pcm_banksize = pcm_nblk * pcm_bsize;
+ pcm_banksize = pcm_nblk * pcm_bsize;
- if (gus_sampling_bits != 8 && pcm_banksize == (256 * 1024))
- pcm_nblk--;
+ if (gus_sampling_bits != 8 && pcm_banksize == (256 * 1024))
+ pcm_nblk--;
- return 0;
+ return 0;
}
static int
-gus_local_qlen (int dev)
+gus_local_qlen(int dev)
{
- return pcm_qlen;
+ return pcm_qlen;
}
static void
-gus_copy_from_user (int dev, char *localbuf, int localoffs,
- snd_rw_buf * userbuf, int useroffs, int len)
+gus_copy_from_user(int dev, char *localbuf, int localoffs,
+ snd_rw_buf * userbuf, int useroffs, int len)
{
- if (gus_sampling_channels == 1)
- {
- COPY_FROM_USER (&localbuf[localoffs], userbuf, useroffs, len);
- }
- else if (gus_sampling_bits == 8)
- {
- int in_left = useroffs;
- int in_right = useroffs + 1;
- char *out_left, *out_right;
- int i;
-
- len /= 2;
- localoffs /= 2;
- out_left = &localbuf[localoffs];
- out_right = out_left + pcm_bsize;
-
- for (i = 0; i < len; i++)
- {
- GET_BYTE_FROM_USER (*out_left++, userbuf, in_left);
- in_left += 2;
- GET_BYTE_FROM_USER (*out_right++, userbuf, in_right);
- in_right += 2;
+ if (gus_sampling_channels == 1) {
+
+ if (uiomove(&localbuf[localoffs], len, userbuf)) {
+ printf("audio: Bad copyin()!\n");
+ };
+ } else if (gus_sampling_bits == 8) {
+ int in_left = useroffs;
+ int in_right = useroffs + 1;
+ char *out_left, *out_right;
+ int i;
+
+ len /= 2;
+ localoffs /= 2;
+ out_left = &localbuf[localoffs];
+ out_right = out_left + pcm_bsize;
+
+ for (i = 0; i < len; i++) {
+ uiomove((char *) &(*out_left++), 1, userbuf);
+ in_left += 2;
+ uiomove((char *) &(*out_right++), 1, userbuf);
+ in_right += 2;
+ }
+ } else {
+ int in_left = useroffs;
+ int in_right = useroffs + 2;
+ short *out_left, *out_right;
+ int i;
+
+ len /= 4;
+ localoffs /= 2;
+
+ out_left = (short *) &localbuf[localoffs];
+ out_right = out_left + (pcm_bsize / 2);
+
+ for (i = 0; i < len; i++) {
+ uiomove((char *) &(*out_left++), 2, userbuf);
+ in_left += 2;
+ uiomove((char *) &(*out_right++), 2, userbuf);
+ in_right += 2;
+ }
}
- }
- else
- {
- int in_left = useroffs;
- int in_right = useroffs + 1;
- short *out_left, *out_right;
- int i;
-
- len /= 4;
- localoffs /= 4;
-
- out_left = (short *) &localbuf[localoffs];
- out_right = out_left + (pcm_bsize / 2);
-
- for (i = 0; i < len; i++)
- {
- GET_SHORT_FROM_USER (*out_left++, (short *) userbuf, in_left);
- in_left += 2;
- GET_SHORT_FROM_USER (*out_right++, (short *) userbuf, in_right);
- in_right += 2;
- }
- }
}
static struct audio_operations gus_sampling_operations =
{
- "Gravis UltraSound",
- NEEDS_RESTART,
- AFMT_U8 | AFMT_S16_LE,
- NULL,
- gus_sampling_open,
- gus_sampling_close,
- gus_sampling_output_block,
- gus_sampling_start_input,
- gus_sampling_ioctl,
- gus_sampling_prepare_for_input,
- gus_sampling_prepare_for_output,
- gus_sampling_reset,
- gus_sampling_reset,
- gus_local_qlen,
- gus_copy_from_user
+ "Gravis UltraSound",
+ NEEDS_RESTART,
+ AFMT_U8 | AFMT_S16_LE,
+ NULL,
+ gus_sampling_open,
+ gus_sampling_close,
+ gus_sampling_output_block,
+ gus_sampling_start_input,
+ gus_sampling_ioctl,
+ gus_sampling_prepare_for_input,
+ gus_sampling_prepare_for_output,
+ gus_sampling_reset,
+ gus_sampling_reset,
+ gus_local_qlen,
+ gus_copy_from_user
};
static void
-guswave_bender (int dev, int voice, int value)
+guswave_setup_voice(int dev, int voice, int chn)
{
- int freq;
- unsigned long flags;
-
- voices[voice].bender = value - 8192;
- freq = compute_finetune (voices[voice].orig_freq, value,
- voices[voice].bender_range);
- voices[voice].current_freq = freq;
+ struct channel_info *info =
+ &synth_devs[dev]->chn_info[chn];
+
+ guswave_set_instr(dev, voice, info->pgm_num);
+
+ voices[voice].expression_vol =
+ info->controllers[CTL_EXPRESSION]; /* Just msb */
+ voices[voice].main_vol =
+ (info->controllers[CTL_MAIN_VOLUME] * 100) / 128;
+ voices[voice].panning =
+ (info->controllers[CTL_PAN] * 2) - 128;
+ voices[voice].bender = info->bender_value;
+}
- DISABLE_INTR (flags);
- gus_select_voice (voice);
- gus_voice_freq (freq);
- RESTORE_INTR (flags);
+static void
+guswave_bender(int dev, int voice, int value)
+{
+ int freq;
+ u_long flags;
+
+ voices[voice].bender = value - 8192;
+ freq = compute_finetune(voices[voice].orig_freq, value - 8192,
+ voices[voice].bender_range);
+ voices[voice].current_freq = freq;
+
+ flags = splhigh();
+ gus_select_voice(voice);
+ gus_voice_freq(freq);
+ splx(flags);
}
static int
-guswave_patchmgr (int dev, struct patmgr_info *rec)
+guswave_patchmgr(int dev, struct patmgr_info * rec)
{
- int i, n;
+ int i, n;
- switch (rec->command)
- {
- case PM_GET_DEVTYPE:
- rec->parm1 = PMTYPE_WAVE;
- return 0;
- break;
+ switch (rec->command) {
+ case PM_GET_DEVTYPE:
+ rec->parm1 = PMTYPE_WAVE;
+ return 0;
+ break;
- case PM_GET_NRPGM:
- rec->parm1 = MAX_PATCH;
- return 0;
- break;
+ case PM_GET_NRPGM:
+ rec->parm1 = MAX_PATCH;
+ return 0;
+ break;
- case PM_GET_PGMMAP:
- rec->parm1 = MAX_PATCH;
+ case PM_GET_PGMMAP:
+ rec->parm1 = MAX_PATCH;
- for (i = 0; i < MAX_PATCH; i++)
- {
- int ptr = patch_table[i];
+ for (i = 0; i < MAX_PATCH; i++) {
+ int ptr = patch_table[i];
- rec->data.data8[i] = 0;
+ rec->data.data8[i] = 0;
- while (ptr >= 0 && ptr < free_sample)
- {
- rec->data.data8[i]++;
- ptr = samples[ptr].key; /* Follow link */
- }
- }
- return 0;
- break;
+ while (ptr >= 0 && ptr < free_sample) {
+ rec->data.data8[i]++;
+ ptr = samples[ptr].key; /* Follow link */
+ }
+ }
+ return 0;
+ break;
- case PM_GET_PGM_PATCHES:
- {
- int ptr = patch_table[rec->parm1];
-
- n = 0;
-
- while (ptr >= 0 && ptr < free_sample)
- {
- rec->data.data32[n++] = ptr;
- ptr = samples[ptr].key; /* Follow link */
- }
- }
- rec->parm1 = n;
- return 0;
- break;
-
- case PM_GET_PATCH:
- {
- int ptr = rec->parm1;
- struct patch_info *pat;
-
- if (ptr < 0 || ptr >= free_sample)
- return RET_ERROR (EINVAL);
-
- memcpy (rec->data.data8, (char *) &samples[ptr],
- sizeof (struct patch_info));
+ case PM_GET_PGM_PATCHES:
+ {
+ int ptr = patch_table[rec->parm1];
- pat = (struct patch_info *) rec->data.data8;
-
- pat->key = GUS_PATCH; /* Restore patch type */
- rec->parm1 = sample_ptrs[ptr]; /* DRAM location */
- rec->parm2 = sizeof (struct patch_info);
- }
- return 0;
- break;
-
- case PM_SET_PATCH:
- {
- int ptr = rec->parm1;
- struct patch_info *pat;
-
- if (ptr < 0 || ptr >= free_sample)
- return RET_ERROR (EINVAL);
-
- pat = (struct patch_info *) rec->data.data8;
-
- if (pat->len > samples[ptr].len) /* Cannot expand sample */
- return RET_ERROR (EINVAL);
-
- pat->key = samples[ptr].key; /* Ensure the link is correct */
-
- memcpy ((char *) &samples[ptr], rec->data.data8,
- sizeof (struct patch_info));
-
- pat->key = GUS_PATCH;
- }
- return 0;
- break;
-
- case PM_READ_PATCH: /* Returns a block of wave data from the DRAM */
- {
- int sample = rec->parm1;
- int n;
- long offs = rec->parm2;
- int l = rec->parm3;
-
- if (sample < 0 || sample >= free_sample)
- return RET_ERROR (EINVAL);
-
- if (offs < 0 || offs >= samples[sample].len)
- return RET_ERROR (EINVAL); /* Invalid offset */
-
- n = samples[sample].len - offs; /* Num of bytes left */
-
- if (l > n)
- l = n;
-
- if (l > sizeof (rec->data.data8))
- l = sizeof (rec->data.data8);
-
- if (l <= 0)
- return RET_ERROR (EINVAL); /*
- * Was there a bug?
- */
-
- 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
- */
- }
- return 0;
- break;
-
- case PM_WRITE_PATCH: /*
- * Writes a block of wave data to the DRAM
- */
- {
- int sample = rec->parm1;
- int n;
- long offs = rec->parm2;
- int l = rec->parm3;
-
- if (sample < 0 || sample >= free_sample)
- return RET_ERROR (EINVAL);
-
- if (offs < 0 || offs >= samples[sample].len)
- return RET_ERROR (EINVAL); /*
- * Invalid offset
- */
-
- n = samples[sample].len - offs; /*
- * Nr of bytes left
- */
-
- if (l > n)
- l = n;
-
- if (l > sizeof (rec->data.data8))
- l = sizeof (rec->data.data8);
-
- if (l <= 0)
- return RET_ERROR (EINVAL); /*
- * Was there a bug?
- */
-
- 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
- */
- }
- return 0;
- break;
+ n = 0;
- default:
- return RET_ERROR (EINVAL);
- }
+ while (ptr >= 0 && ptr < free_sample) {
+ rec->data.data32[n++] = ptr;
+ ptr = samples[ptr].key; /* Follow link */
+ }
+ }
+ rec->parm1 = n;
+ return 0;
+ break;
+
+ case PM_GET_PATCH:
+ {
+ int ptr = rec->parm1;
+ struct patch_info *pat;
+
+ if (ptr < 0 || ptr >= free_sample)
+ return -(EINVAL);
+
+ bcopy((char *) &samples[ptr], rec->data.data8, sizeof(struct patch_info));
+
+ pat = (struct patch_info *) rec->data.data8;
+
+ pat->key = GUS_PATCH; /* Restore patch type */
+ rec->parm1 = sample_ptrs[ptr]; /* DRAM location */
+ rec->parm2 = sizeof(struct patch_info);
+ }
+ return 0;
+ break;
+
+ case PM_SET_PATCH:
+ {
+ int ptr = rec->parm1;
+ struct patch_info *pat;
+
+ if (ptr < 0 || ptr >= free_sample)
+ return -(EINVAL);
+
+ pat = (struct patch_info *) rec->data.data8;
+
+ if (pat->len > samples[ptr].len) /* Cannot expand sample */
+ return -(EINVAL);
+
+ pat->key = samples[ptr].key; /* Ensure the link is
+ * correct */
+
+ bcopy(rec->data.data8, (char *) &samples[ptr], sizeof(struct patch_info));
+
+ pat->key = GUS_PATCH;
+ }
+ return 0;
+ break;
+
+ case PM_READ_PATCH: /* Returns a block of wave data from the DRAM */
+ {
+ int sample = rec->parm1;
+ int n;
+ long offs = rec->parm2;
+ int l = rec->parm3;
+
+ if (sample < 0 || sample >= free_sample)
+ return -(EINVAL);
+
+ if (offs < 0 || offs >= samples[sample].len)
+ return -(EINVAL); /* Invalid offset */
+
+ n = samples[sample].len - offs; /* Num of bytes left */
+
+ if (l > n)
+ l = n;
+
+ if (l > sizeof(rec->data.data8))
+ l = sizeof(rec->data.data8);
+
+ if (l <= 0)
+ return -(EINVAL); /* Was there a bug? */
+
+ 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 */
+ }
+ return 0;
+ break;
+
+ case PM_WRITE_PATCH: /* Writes a block of wave data to the DRAM */
+ {
+ int sample = rec->parm1;
+ int n;
+ long offs = rec->parm2;
+ int l = rec->parm3;
+
+ if (sample < 0 || sample >= free_sample)
+ return -(EINVAL);
+
+ if (offs < 0 || offs >= samples[sample].len)
+ return -(EINVAL); /* Invalid offset */
+
+ n = samples[sample].len - offs; /* Nr of bytes left */
+
+ if (l > n)
+ l = n;
+
+ if (l > sizeof(rec->data.data8))
+ l = sizeof(rec->data.data8);
+
+ if (l <= 0)
+ return -(EINVAL); /* Was there a bug? */
+
+ 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 */
+ }
+ return 0;
+ break;
+
+ default:
+ return -(EINVAL);
+ }
}
static int
-guswave_alloc (int dev, int chn, int note, struct voice_alloc_info *alloc)
+guswave_alloc(int dev, int chn, int note, struct voice_alloc_info * alloc)
{
- int i, p;
+ int i, p, best = -1, best_time = 0x7fffffff;
- p = alloc->ptr;
- /*
- * First look for a completely stopped voice
- */
+ p = alloc->ptr;
+ /*
+ * First look for a completely stopped voice
+ */
- for (i = 0; i < alloc->max_voice; i++)
- {
- if (alloc->map[p] == 0)
- {
- alloc->ptr = p;
- return p;
+ for (i = 0; i < alloc->max_voice; i++) {
+ if (alloc->map[p] == 0) {
+ alloc->ptr = p;
+ return p;
+ }
+ if (alloc->alloc_times[p] < best_time) {
+ best = p;
+ best_time = alloc->alloc_times[p];
+ }
+ p = (p + 1) % alloc->max_voice;
}
- p = (p + 1) % alloc->max_voice;
- }
- /*
- * Then look for a releasing voice
- */
+ /*
+ * Then look for a releasing voice
+ */
- for (i = 0; i < alloc->max_voice; i++)
- {
- if (alloc->map[p] == 0xffff)
- {
- alloc->ptr = p;
- return p;
+ for (i = 0; i < alloc->max_voice; i++) {
+ if (alloc->map[p] == 0xffff) {
+ alloc->ptr = p;
+ return p;
+ }
+ p = (p + 1) % alloc->max_voice;
}
- p = (p + 1) % alloc->max_voice;
- }
- printk ("GUS: Out of free voices\n");
- alloc->ptr = p;
- return p;
+ if (best >= 0)
+ p = best;
+
+ alloc->ptr = p;
+ return p;
}
static struct synth_operations guswave_operations =
{
- &gus_info,
- 0,
- SYNTH_TYPE_SAMPLE,
- SAMPLE_TYPE_GUS,
- guswave_open,
- guswave_close,
- guswave_ioctl,
- guswave_kill_note,
- guswave_start_note,
- guswave_set_instr,
- guswave_reset,
- guswave_hw_control,
- guswave_load_patch,
- guswave_aftertouch,
- guswave_controller,
- guswave_panning,
- guswave_volume_method,
- guswave_patchmgr,
- guswave_bender,
- guswave_alloc
+ &gus_info,
+ 0,
+ SYNTH_TYPE_SAMPLE,
+ SAMPLE_TYPE_GUS,
+ guswave_open,
+ guswave_close,
+ guswave_ioctl,
+ guswave_kill_note,
+ guswave_start_note,
+ guswave_set_instr,
+ guswave_reset,
+ guswave_hw_control,
+ guswave_load_patch,
+ guswave_aftertouch,
+ guswave_controller,
+ guswave_panning,
+ guswave_volume_method,
+ guswave_patchmgr,
+ guswave_bender,
+ guswave_alloc,
+ guswave_setup_voice
};
static void
-set_input_volumes (void)
+set_input_volumes(void)
{
- unsigned long flags;
- unsigned char mask = 0xff & ~0x06; /* Just line out enabled */
+ u_long flags;
+ u_char mask = 0xff & ~0x06; /* Just line out enabled */
- DISABLE_INTR (flags);
+ if (have_gus_max) /* Don't disturb GUS MAX */
+ return;
- /*
- * 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 (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;
- }
+ flags = splhigh();
- mix_image &= ~0x07;
- mix_image |= mask & 0x07;
- OUTB (mix_image, u_Mixer);
+ /*
+ * Enable channels having vol > 10% Note! bit 0x01 means the line in
+ * DISABLED while 0x04 means the mic in ENABLED.
+ */
+ 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 (!(gus_recmask & SOUND_MASK_LINE))
+ mask |= 0x01;
+ if (!(gus_recmask & SOUND_MASK_MIC))
+ mask &= ~0x04;
+ }
+ mix_image &= ~0x07;
+ mix_image |= mask & 0x07;
+ outb(u_Mixer, mix_image);
- RESTORE_INTR (flags);
+ splx(flags);
}
int
-gus_default_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg)
+gus_default_mixer_ioctl(int dev, u_int cmd, ioctl_arg arg)
{
+
#define MIX_DEVS (SOUND_MASK_MIC|SOUND_MASK_LINE| \
SOUND_MASK_SYNTH|SOUND_MASK_PCM)
- if (((cmd >> 8) & 0xff) == 'M')
- {
- if (cmd & IOC_IN)
- 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;
- /* Note! Input volumes are updated during next open for recording */
- return IOCTL_OUT (arg, gus_recmask);
- break;
- case SOUND_MIXER_MIC:
- {
- int vol = IOCTL_IN (arg) & 0xff;
-
- if (vol < 0)
- vol = 0;
- if (vol > 100)
- vol = 100;
- gus_mic_vol = vol;
- set_input_volumes ();
- return IOCTL_OUT (arg, vol | (vol << 8));
+ if (((cmd >> 8) & 0xff) == 'M') {
+ if (cmd & IOC_IN)
+ switch (cmd & 0xff) {
+ case SOUND_MIXER_RECSRC:
+ gus_recmask = (*(int *) 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 *(int *) arg = gus_recmask;
+ break;
+
+ case SOUND_MIXER_MIC:
+ {
+ int vol = (*(int *) arg) & 0xff;
+
+ if (vol < 0)
+ vol = 0;
+ if (vol > 100)
+ vol = 100;
+ gus_mic_vol = vol;
+ set_input_volumes();
+ return *(int *) arg = vol | (vol << 8);
+ }
+ break;
+
+ case SOUND_MIXER_LINE:
+ {
+ int vol = (*(int *) arg) & 0xff;
+
+ if (vol < 0)
+ vol = 0;
+ if (vol > 100)
+ vol = 100;
+ gus_line_vol = vol;
+ set_input_volumes();
+ return *(int *) arg = vol | (vol << 8);
+ }
+ break;
+
+ case SOUND_MIXER_PCM:
+ gus_pcm_volume = (*(int *) arg) & 0xff;
+ RANGE (gus_pcm_volume, 0, 100);
+ gus_sampling_update_volume();
+ return *(int *) arg = gus_pcm_volume | (gus_pcm_volume << 8);
+ break;
+
+ case SOUND_MIXER_SYNTH:
+ {
+ int voice;
+
+ gus_wave_volume = (*(int *) arg) & 0xff;
+
+ RANGE (gus_wave_volume , 0, 100);
+
+ if (active_device == GUS_DEV_WAVE)
+ for (voice = 0; voice < nr_voices; voice++)
+ dynamic_volume_change(voice); /* Apply the new vol */
+
+ return *(int *) arg = gus_wave_volume | (gus_wave_volume << 8);
+ }
+ break;
+
+ default:
+ return -(EINVAL);
}
- break;
+ else
+ switch (cmd & 0xff) { /* Return parameters */
- case SOUND_MIXER_LINE:
- {
- int vol = IOCTL_IN (arg) & 0xff;
-
- if (vol < 0)
- vol = 0;
- if (vol > 100)
- vol = 100;
- gus_line_vol = vol;
- set_input_volumes ();
- return IOCTL_OUT (arg, vol | (vol << 8));
- }
- break;
+ case SOUND_MIXER_RECSRC:
+ return *(int *) arg = gus_recmask;
+ 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));
- break;
+ case SOUND_MIXER_DEVMASK:
+ return *(int *) arg = MIX_DEVS;
+ break;
- case SOUND_MIXER_SYNTH:
- {
- int voice;
+ case SOUND_MIXER_STEREODEVS:
+ return *(int *) arg = 0;
+ break;
- gus_wave_volume = IOCTL_IN (arg) & 0xff;
+ case SOUND_MIXER_RECMASK:
+ return *(int *) arg = SOUND_MASK_MIC | SOUND_MASK_LINE;
+ break;
- if (gus_wave_volume < 0)
- gus_wave_volume = 0;
- if (gus_wave_volume > 100)
- gus_wave_volume = 100;
+ case SOUND_MIXER_CAPS:
+ return *(int *) arg = 0;
+ break;
- if (active_device == GUS_DEV_WAVE)
- for (voice = 0; voice < nr_voices; voice++)
- dynamic_volume_change (voice); /* Apply the new vol */
+ case SOUND_MIXER_MIC:
+ return *(int *) arg = gus_mic_vol | (gus_mic_vol << 8);
+ break;
- return IOCTL_OUT (arg, gus_wave_volume | (gus_wave_volume << 8));
+ case SOUND_MIXER_LINE:
+ return *(int *) arg = gus_line_vol | (gus_line_vol << 8);
+ break;
+
+ case SOUND_MIXER_PCM:
+ return *(int *) arg = gus_pcm_volume | (gus_pcm_volume << 8);
+ break;
+
+ case SOUND_MIXER_SYNTH:
+ return *(int *) arg = gus_wave_volume | (gus_wave_volume << 8);
+ break;
+
+ default:
+ return -(EINVAL);
}
- break;
+} else
+ return -(EINVAL);
+}
- default:
- return RET_ERROR (EINVAL);
- }
- else
- switch (cmd & 0xff) /*
- * Return parameters
- */
- {
-
- case SOUND_MIXER_RECSRC:
- return IOCTL_OUT (arg, gus_recmask);
- break;
+static struct mixer_operations gus_mixer_operations = {"Gravis Ultrasound", gus_default_mixer_ioctl};
- case SOUND_MIXER_DEVMASK:
- return IOCTL_OUT (arg, MIX_DEVS);
- break;
+static void
+gus_default_mixer_init()
+{
+if (num_mixers < MAX_MIXER_DEV) /* Don't install if there is another
+ * mixer */
+ mixer_devs[num_mixers++] = &gus_mixer_operations;
- case SOUND_MIXER_STEREODEVS:
- return IOCTL_OUT (arg, 0);
- break;
+if (have_gus_max) {
+ /*
+ * Enable all mixer channels on the GF1 side. Otherwise
+ * recording will not be possible using GUS MAX.
+ */
+ mix_image &= ~0x07;
+ mix_image |= 0x04; /* All channels enabled */
+ outb(u_Mixer, mix_image);
+}
+}
- case SOUND_MIXER_RECMASK:
- return IOCTL_OUT (arg, SOUND_MASK_MIC | SOUND_MASK_LINE);
- break;
+/* start of pnp code */
- case SOUND_MIXER_CAPS:
- return IOCTL_OUT (arg, 0);
- break;
+void
+SEND(int d, int r)
+{
+outb(PADDRESS, d);
+outb(PWRITE_DATA, r);
+}
- case SOUND_MIXER_MIC:
- return IOCTL_OUT (arg, gus_mic_vol | (gus_mic_vol << 8));
- break;
- case SOUND_MIXER_LINE:
- return IOCTL_OUT (arg, gus_line_vol | (gus_line_vol << 8));
- break;
- case SOUND_MIXER_PCM:
- return IOCTL_OUT (arg, gus_pcm_volume | (gus_pcm_volume << 8));
- break;
- case SOUND_MIXER_SYNTH:
- return IOCTL_OUT (arg, gus_wave_volume | (gus_wave_volume << 8));
- break;
+/*
+ * Get the device's serial number. Returns 1 if the serial is valid.
+ */
+int
+get_serial(int rd_port, u_char *data)
+{
+ int i, bit, valid = 0, sum = 0x6a;
- default:
- return RET_ERROR (EINVAL);
- }
- }
- else
- return RET_ERROR (EINVAL);
+ bzero(data, sizeof(char) * 9);
+
+ for (i = 0; i < 72; i++) {
+ bit = inb((rd_port << 2) | 0x3) == 0x55;
+ DELAY(250); /* Delay 250 usec */
+
+ /* Can't Short Circuit the next evaluation, so 'and' is last */
+ bit = (inb((rd_port << 2) | 0x3) == 0xaa) && bit;
+ DELAY(250); /* Delay 250 usec */
+
+ valid = valid || bit;
+
+ if (i < 64)
+ sum = (sum >> 1) |
+ (((sum ^ (sum >> 1) ^ bit) << 7) & 0xff);
+
+ data[i / 8] = (data[i / 8] >> 1) | (bit ? 0x80 : 0);
+ }
+ valid = valid && (data[8] == sum);
+
+ return valid;
}
-static struct mixer_operations gus_mixer_operations =
+void
+send_Initiation_LFSR()
{
- gus_default_mixer_ioctl
-};
+ int cur, i;
+
+ /* Reset the LSFR */
+ outb(PADDRESS, 0);
+ outb(PADDRESS, 0);
-static long
-gus_default_mixer_init (long mem_start)
+ cur = 0x6a;
+ outb(PADDRESS, cur);
+
+ for (i = 1; i < 32; i++) {
+ cur = (cur >> 1) | (((cur ^ (cur >> 1)) << 7) & 0xff);
+ outb(PADDRESS, cur);
+ }
+}
+
+
+
+int
+isolation_protocol(int rd_port)
{
- if (num_mixers < MAX_MIXER_DEV) /*
- * Don't install if there is another
- * mixer
- */
- mixer_devs[num_mixers++] = &gus_mixer_operations;
+ int csn;
+ u_char data[9];
+
+ send_Initiation_LFSR();
- return mem_start;
+ /* Reset CSN for All Cards */
+ SEND(0x02, 0x04);
+
+ for (csn = 1; (csn < MAX_CARDS); csn++) {
+ /* Wake up cards without a CSN */
+
+ SEND(WAKE, 0);
+ SEND(SET_RD_DATA, rd_port);
+ outb(PADDRESS, SERIAL_ISOLATION);
+ DELAY(1000); /* Delay 1 msec */
+ if (get_serial(rd_port, data)) {
+ printf("Board Vendor ID: %c%c%c%02x%02x",
+ ((data[0] & 0x7c) >> 2) + 64,
+ (((data[0] & 0x03) << 3) | ((data[1] & 0xe0) >> 5)) + 64,
+ (data[1] & 0x1f) + 64, data[2], data[3]);
+ printf(" Board Serial Number: %08x\n", *(int *) &(data[4]));
+
+ SEND(SET_CSN, csn); /* Move this out of this
+ * function XXX */
+ outb(PADDRESS, PSTATUS);
+
+
+ return rd_port;
+ } else
+ break;
+ }
+
+ return 0;
}
-long
-gus_wave_init (long mem_start, int irq, int dma)
+
+
+void
+IwaveDelay(WORD count)
{
- unsigned long flags;
- unsigned char val;
- char *model_num = "2.4";
- int gus_type = 0x24; /* 2.4 */
- int mixer_type = 0;
+ WORD cur_cnt = 0, last_cnt;
+ BYTE reg, portb;
+
+ count = 1193 * count; /* convert number of ms to counter */
+ last_cnt = count;
+ portb = inb(0x61) & 0xFC;
+ outb(0x61, portb); /* disable counter */
+ outb(0x43, 0xB0); /* load LSB first then MSB */
+ outb(0x42, (BYTE) count);
+ outb(0x42, (BYTE) (count >> 8));
+ outb(0x61, (BYTE) (portb | 0x01)); /* enable counter */
+ while (cur_cnt <= count) {
+ outb(0x43, 0x80); /* latch counter */
+ reg = inb(0x42);/* read latched value */
+ cur_cnt = (((WORD) inb(0x42)) << 8) | reg;
+ if (cur_cnt > last_cnt)
+ break;
+ last_cnt = cur_cnt;
+ }
+ outb(0x61, portb); /* disable counter */
+}
- /*
- * Try to identify the GUS model.
- *
- * Versions < 3.6 don't have the digital ASIC. Try to probe it first.
+/*
+ * ########################################################################
+ *
+ * FUNCTION: IwaveStopDma
+ *
+ * PROFILE: This function stops an active DMA transfer to or from the record or
+ * playback FIFOs. Set the "path" variable to either PLAYBACK or RECORD.
+ * ########################################################################
*/
- DISABLE_INTR (flags);
- OUTB (0x20, gus_base + 0x0f);
- val = INB (gus_base + 0x0f);
- RESTORE_INTR (flags);
+void
+IwaveStopDma(BYTE path)
+{
+ BYTE reg;
- 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.
- */
+ ENTER_CRITICAL;
+ reg = inb(iw.pcodar) & 0xE0;
+ outb(iw.pcodar, reg | _CFIG1I); /* select CFIG1I */
+ outb(iw.cdatap, (BYTE) (inb(iw.cdatap) & ~path)); /* disable playback path */
+ LEAVE_CRITICAL;
+}
- val = INB (u_MixSelect);
+/*
+ * ########################################################################
+ *
+ * FUNCTION : IwaveInputSource
+ *
+ * PROFILE: This function allows the calling program to select among any of
+ * several possible sources to the ADC's. The possible input sources and
+ * their corresponding symbolic constants are: - Line (LINE_IN) - Aux1
+ * (AUX1_IN) - Microphone (MIC_IN) - Mixer (MIX_IN)
+ *
+ * Set the first argument to either LEFT_SOURCE or RIGHT_SOURCE. Always use the
+ * symbolic contants for the arguments.
+ *
+ * ########################################################################
+ */
+void
+IwaveInputSource(BYTE index, BYTE source)
+{
+ BYTE reg;
+
+ ENTER_CRITICAL;
+ reg = inb(iw.pcodar) & 0xE0;
+ outb(iw.pcodar, reg | index); /* select register CLICI or CRICI */
+ reg = inb(iw.cdatap) & ~MIX_IN;
+ source &= MIX_IN;
+ outb(iw.cdatap, (BYTE) (reg | source));
+ LEAVE_CRITICAL;
+}
+void
+IwavePnpGetCfg(void)
+{
+ WORD val;
+
+
+ ENTER_CRITICAL;
+ IwavePnpDevice(AUDIO);
+ outb(_PIDXR, 0x60); /* select P2X0HI */
+ val = ((WORD) inb(iw.pnprdp)) << 8; /* get P2XR[9:8] */
+ outb(_PIDXR, 0x61); /* select P2XRLI */
+ iw.p2xr = val + (WORD) inb(iw.pnprdp); /* get P2XR[7:4] */
+
+ outb(_PIDXR, 0x62); /* select P3X0HI */
+ val = ((WORD) inb(iw.pnprdp)) << 8; /* get P3XR[9:8] */
+ outb(_PIDXR, 0x63); /* select P3X0LI */
+ iw.p3xr = val + (WORD) inb(iw.pnprdp); /* get P3XR[7:3] */
+
+ outb(_PIDXR, 0x64); /* select PHCAI */
+ val = ((WORD) inb(iw.pnprdp)) << 8; /* get PCODAR[9:8] */
+ outb(_PIDXR, 0x65); /* select PLCAI */
+ iw.pcodar = val + (WORD) inb(iw.pnprdp); /* get PCODAR[7:2] */
+
+ outb(_PIDXR, 0x70); /* select PUI1SI */
+ iw.synth_irq = (WORD) (inb(iw.pnprdp) & 0x0F); /* Synth IRQ number */
+
+ outb(_PIDXR, 0x72); /* select PUI2SI */
+ iw.midi_irq = (WORD) (inb(iw.pnprdp) & 0x0F); /* MIDI IRQ number */
+
+ outb(_PIDXR, 0x74); /* select PUD1SI */
+ iw.dma1_chan = inb(iw.pnprdp) & 0x07; /* DMA1 chan (LMC/Codec Rec) */
+
+ outb(_PIDXR, 0x75); /* select PUD2SI */
+ iw.dma2_chan = inb(iw.pnprdp) & 0x07; /* DMA2 chan (codec play) */
+
+
+ IwavePnpDevice(EXT); /* select external device */
+ outb(_PIDXR, 0x60); /* select PRAHI */
+ val = ((WORD) inb(iw.pnprdp)) << 8; /* get PCDRAR[9:8] */
+ outb(_PIDXR, 0x61); /* select PRALI */
+ iw.pcdrar = val + (WORD) inb(iw.pnprdp); /* get PCDRAR[7:4] */
+ outb(_PIDXR, 0x62); /* select PATAHI */
+ val = ((WORD) inb(iw.pnprdp)) << 8; /* get PATAAR[9:8] */
+ outb(_PIDXR, 0x63); /* select PATALI */
+ iw.pataar = val + (WORD) inb(iw.pnprdp); /* get PATAAR[7:1] */
+
+ outb(_PIDXR, 0x70); /* select PRISI */
+ iw.ext_irq = (WORD) (inb(iw.pnprdp) & 0x0F); /* Ext Dev IRQ number */
+
+ outb(_PIDXR, 0x74); /* select PRDSI */
+ iw.ext_chan = inb(iw.pnprdp) & 0x07; /* Ext Dev DMA channel */
+
+ IwavePnpDevice(MPU401); /* Select MPU401 Device */
+ outb(_PIDXR, 0x60); /* select P401HI */
+ val = ((WORD) inb(iw.pnprdp)) << 8; /* get P401AR[9:8] */
+ outb(_PIDXR, 0x61); /* select P401LI */
+ iw.p401ar = val + (WORD) inb(iw.pnprdp); /* get P401AR[7:1] */
+
+ outb(_PIDXR, 0x70); /* select PMISI */
+ iw.mpu_irq = (WORD) (inb(iw.pnprdp) & 0x0F); /* MPU401 Dev IRQ number */
+
+ IwavePnpDevice(GAME); /* Select GAME logical Device */
+ outb(_PIDXR, 0x60); /* select P201HI */
+ val = ((WORD) inb(iw.pnprdp)) << 8; /* get P201AR[9:8] */
+ outb(_PIDXR, 0x61); /* select P201LI */
+ iw.p201ar = val + (WORD) inb(iw.pnprdp); /* get P201AR[7:6] */
+
+ IwavePnpDevice(EMULATION); /* Select SB and ADLIB Device */
+ outb(_PIDXR, 0x60); /* select P388HI */
+ val = ((WORD) inb(iw.pnprdp)) << 8; /* get P388AR[9:8] */
+ outb(_PIDXR, 0x61); /* select P388LI */
+ iw.p388ar = val + inb(iw.pnprdp); /* get P388AR[7:6] */
+ outb(_PIDXR, 0x70); /* select PSBISI */
+ iw.emul_irq = (WORD) (inb(iw.pnprdp) & 0x0F); /* emulation Dev IRQ
+ * number */
+ LEAVE_CRITICAL;
+}
+
+void
+IwavePnpSetCfg(void)
+{
+ ENTER_CRITICAL;
+ IwavePnpDevice(AUDIO); /* select audio device */
+ outb(_PIDXR, 0x60); /* select P2X0HI */
+ outb(_PNPWRP, (BYTE) (iw.p2xr >> 8)); /* set P2XR[9:8] */
+ outb(_PIDXR, 0x61); /* select P2X0LI */
+ outb(_PNPWRP, (BYTE) iw.p2xr); /* set P2XR[7:4] */
+ /* P2XR[3:0]=0 */
+ outb(_PIDXR, 0x62); /* select P3X0HI */
+ outb(_PNPWRP, (BYTE) (iw.p3xr >> 8)); /* set P3XR[9:8] */
+ outb(_PIDXR, 0x63); /* select P3X0LI */
+ outb(_PNPWRP, (BYTE) (iw.p3xr)); /* set P3XR[7:3] */
+ /* P3XR[2:0]=0 */
+ outb(_PIDXR, 0x64); /* select PHCAI */
+ outb(_PNPWRP, (BYTE) (iw.pcodar >> 8)); /* set PCODAR[9:8] */
+ outb(_PIDXR, 0x65); /* select PLCAI */
+ outb(_PNPWRP, (BYTE) iw.pcodar); /* set PCODAR[7:2] */
+
+ outb(_PIDXR, 0x70); /* select PUI1SI */
+ outb(_PNPWRP, (BYTE) (iw.synth_irq & 0x0F)); /* Synth IRQ number */
+ outb(_PIDXR, 0x72); /* select PUI2SI */
+ outb(_PNPWRP, (BYTE) (iw.midi_irq & 0x0F)); /* MIDI IRQ number */
+
+ outb(_PIDXR, 0x74); /* select PUD1SI */
+ outb(_PNPWRP, (BYTE) (iw.dma1_chan & 0x07)); /* DMA channel 1 */
+ outb(_PIDXR, 0x75); /* select PUD2SI */
+ outb(_PNPWRP, (BYTE) (iw.dma2_chan & 0x07)); /* DMA channel 2 */
+
+ IwavePnpDevice(EXT);
+ outb(_PIDXR, 0x60); /* select PRAHI */
+ outb(_PNPWRP, (BYTE) (iw.pcdrar >> 8)); /* set PCDRAR[9:8] */
+ outb(_PIDXR, 0x61); /* select PRALI */
+ outb(_PNPWRP, (BYTE) iw.pcdrar); /* set PCDRAR[7:3] */
+ /* PCDRAR[2:0]=0 */
+ outb(_PIDXR, 0x62); /* select PATAHI */
+ outb(_PNPWRP, (BYTE) (iw.pataar >> 8)); /* set PATAAR[9:8] */
+ outb(_PIDXR, 0x63); /* select PATALI */
+ outb(_PNPWRP, (BYTE) iw.pataar); /* set PATAAR[7:1] */
+ /* PATAAR[0]=0 */
+ outb(_PIDXR, 0x70); /* select PRISI */
+ outb(_PNPWRP, (BYTE) (iw.ext_irq & 0x0F)); /* Ext Dev IRQ number */
+ outb(_PIDXR, 0x74); /* select PRDSI */
+ outb(_PNPWRP, (BYTE) (iw.ext_chan & 0x07)); /* Ext Dev DMA channel */
+
+ IwavePnpDevice(GAME);
+ outb(_PIDXR, 0x60); /* select P201HI */
+ outb(_PNPWRP, (BYTE) (iw.p201ar >> 8)); /* set P201RAR[9:8] */
+ outb(_PIDXR, 0x61); /* select P201LI */
+ outb(_PNPWRP, (BYTE) iw.p201ar); /* set P201AR[7:6] */
+
+ IwavePnpDevice(EMULATION);
+ outb(_PIDXR, 0x60); /* select P388HI */
+ outb(_PNPWRP, (BYTE) (iw.p388ar >> 8)); /* set P388AR[9:8] */
+ outb(_PIDXR, 0x61); /* select P388LI */
+ outb(_PNPWRP, (BYTE) iw.p388ar); /* set P388AR[7:6] */
+
+ outb(_PIDXR, 0x70); /* select PSBISI */
+ outb(_PNPWRP, (BYTE) (iw.emul_irq & 0x0F)); /* emulation IRQ number */
+
+ IwavePnpDevice(MPU401);
+ outb(_PIDXR, 0x60); /* select P401HI */
+ outb(_PNPWRP, (BYTE) (iw.p401ar >> 8)); /* set P401AR[9:8] */
+ outb(_PIDXR, 0x61); /* select P401LI */
+ outb(_PNPWRP, (BYTE) iw.p401ar); /* set P401AR[7:1] */
+
+ outb(_PIDXR, 0x70); /* select PMISI */
+ outb(_PNPWRP, (BYTE) (iw.mpu_irq & 0x0F)); /* MPU emulation IRQ
+ * number */
+ LEAVE_CRITICAL;
+}
+
+void
+IwaveCfgIOSpace(void)
+{
+ ENTER_CRITICAL;
+ IwavePnpDevice(AUDIO); /* select audio device */
+ outb(_PIDXR, 0x60); /* select P2X0HI */
+ outb(_PNPWRP, (BYTE) (iw.p2xr >> 8)); /* set P2XR[9:8] */
+ outb(_PIDXR, 0x61); /* select P2X0LI */
+ outb(_PNPWRP, (BYTE) iw.p2xr); /* set P2XR[7:4] */
+ /* P2XR[3:0]=0 */
+ outb(_PIDXR, 0x62); /* select P3X0HI */
+ outb(_PNPWRP, (BYTE) (iw.p3xr >> 8)); /* set P3XR[9:8] */
+ outb(_PIDXR, 0x63); /* select P3X0LI */
+ outb(_PNPWRP, (BYTE) (iw.p3xr)); /* set P3XR[7:3] */
+ /* P3XR[2:0]=0 */
+ outb(_PIDXR, 0x64); /* select PHCAI */
+ outb(_PNPWRP, (BYTE) (iw.pcodar >> 8)); /* set PCODAR[9:8] */
+ outb(_PIDXR, 0x65); /* select PLCAI */
+ outb(_PNPWRP, (BYTE) iw.pcodar); /* set PCODAR[7:2] */
+
+ IwavePnpDevice(EXT);
+ outb(_PIDXR, 0x60); /* select PRAHI */
+ outb(_PNPWRP, (BYTE) (iw.pcdrar >> 8)); /* set PCDRAR[9:8] */
+ outb(_PIDXR, 0x61); /* select PRALI */
+ outb(_PNPWRP, (BYTE) iw.pcdrar); /* set PCDRAR[7:3] */
+ /* PCDRAR[2:0]=0 */
+ outb(_PIDXR, 0x62); /* select PATAHI */
+ outb(_PNPWRP, (BYTE) (iw.pataar >> 8)); /* set PATAAR[9:8] */
+ outb(_PIDXR, 0x63); /* select PATALI */
+ outb(_PNPWRP, (BYTE) iw.pataar); /* set PATAAR[7:1] */
+ /* PATAAR[0]=0 */
+ IwavePnpDevice(GAME);
+ outb(_PIDXR, 0x60); /* select P201HI */
+ outb(_PNPWRP, (BYTE) (iw.p201ar >> 8)); /* set P201RAR[9:8] */
+ outb(_PIDXR, 0x61); /* select P201LI */
+ outb(_PNPWRP, (BYTE) iw.p201ar); /* set P201AR[7:6] */
+
+ IwavePnpDevice(EMULATION);
+ outb(_PIDXR, 0x60); /* select P388HI */
+ outb(_PNPWRP, (BYTE) (iw.p388ar >> 8)); /* set P388AR[9:8] */
+ outb(_PIDXR, 0x61); /* select P388LI */
+ outb(_PNPWRP, (BYTE) iw.p388ar); /* set P388AR[7:6] */
+
+ IwavePnpDevice(MPU401);
+ outb(_PIDXR, 0x60); /* select P401HI */
+ outb(_PNPWRP, (BYTE) (iw.p401ar >> 8)); /* set P401AR[9:8] */
+ outb(_PIDXR, 0x61); /* select P401LI */
+ outb(_PNPWRP, (BYTE) iw.p401ar); /* set P401AR[7:1] */
+ LEAVE_CRITICAL;
+}
- /*
- * 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;
+/* ######################################################################## */
+/* FILE: iwpnp.c */
+/* */
+/* REMARKS: This file contains the definitions for the InterWave's DDK */
+/* functions dedicated to the configuration of the InterWave */
+/* PNP logic. */
+/* */
+/* UPDATE: 4/07/95 */
+/* ######################################################################## */
+/* */
+/* FUNCTION: IwavePnpKey */
+/* */
+/* PROFILE: This function issues the initiation key that places the PNP */
+/* logic into configuration mode. The PNP logic is quiescent at */
+/* power up and must be enabled by software. This function will */
+/* do 32 I/O writes to the PIDXR (0x0279). The function will */
+/* first reset the LFSR to its initial value by a sequence of two */
+/* write cycles of 0x00 to PIDXR before issuing the key. */
+/* */
+/* ######################################################################## */
+void
+IwavePnpKey(void)
+{
+ /* send_Initiation_LFSR(); */
+
+ BYTE code = 0x6A;
+ BYTE msb;
+ BYTE i;
+
+ /* ############################################### */
+ /* Reset Linear Feedback Shift Reg. */
+ /* ############################################### */
+ outb(0x279, 0x00);
+ outb(0x279, 0x00);
+
+ outb(0x279, code); /* Initial value */
+
+ for (i = 1; i < 32; i++) {
+ msb = ((code & 0x01) ^ ((code & 0x02) >> 1)) << 7;
+ code = (code >> 1) | msb;
+ outb(0x279, code);
}
- else if (val < 10)
- {
- model_num = "3.7";
- gus_type = 0x37;
- mixer_type = ICS2101;
+
+}
+
+BYTE
+IwavePnpIsol(PORT * pnpread)
+{
+ int num_pnp_devs;
+ int rd_port = 0;
+ printf("Checking for GUS Plug-n-Play ...\n");
+
+ /* Try various READ_DATA ports from 0x203-0x3ff */
+ for (rd_port = 0x80; (rd_port < 0xff); rd_port += 0x10) {
+ if (0)
+ printf("Trying Read_Port at %x\n",
+ (rd_port << 2) | 0x3);
+
+ num_pnp_devs = isolation_protocol(rd_port);
+ if (num_pnp_devs) {
+ *pnpread = rd_port << 2 | 0x3;
+ break;
+ }
+ }
+ if (!num_pnp_devs) {
+ printf("No Plug-n-Play devices were found\n");
+ return 0;
+ }
+ return 1;
+}
+
+/* ######################################################################## */
+/* */
+/* FUNCTION: IwavePnpSerial */
+/* */
+/* PROFILE: This function reads the first nine bytes of the data from */
+/* the serial EEPROM and returns the Vendor ID and the serial */
+/* number. First, it resets the EEPROM control logic by */
+/* issuing a WAKE[CSN] command. The function will return an */
+/* ASCII string for the vendor ID into the char array pointed */
+/* to by "vendor" in the VVVNNNN format. The serial number */
+/* is placed in the 32-bit variable pointed to by "serial". */
+/* Note that the 9th byte is read but not used as it is invalid */
+/* when the serial identifier is read via PRESDI. */
+/* */
+/* This function assumes that the PNP state machine is not in */
+/* the "wait for key state". Otherwise, unpredictable results */
+/* will be obtained. */
+/* */
+/* ######################################################################## */
+void
+IwavePnpSerial(PORT pnprdp,
+ BYTE csn,
+ BYTE * vendor,
+ DWORD * serial)
+{
+ BYTE presdi, digit, i;
+
+ *serial = 0L;
+
+ /* ####################################### */
+ /* Reset Serial EEPROM logic */
+ /* ####################################### */
+ IwavePnpWake(csn); /* Wake card up */
+
+ for (i = 1; i <= 4; i++) {
+ IwavePnpPeek(pnprdp, 1, &presdi);
+
+ switch (i) {
+ case 1:
+ *(vendor++) = ((presdi & 0x7C) >> 2) | 0x40; /* 1st char */
+ *vendor = (presdi & 0x03) << 3; /* isolate bits[4:3] of
+ * 2nd char */
+ break;
+ case 2:
+ *vendor = ((presdi & 0xE0) >> 5) | (*vendor);
+ *(vendor++) = (*vendor) | 0x40; /* 2nd char */
+ *vendor = (presdi & 0x1F) | 0x40; /* 3rd char */
+ break;
+ case 3:
+ case 4:
+ digit = (presdi & 0xF0) >> 4;
+ if (digit <= 0x09)
+ *(++vendor) = digit + 0x30; /* ASCII of digit */
+ else
+ *(++vendor) = (digit & 0x07) + 0x3F;
+ digit = presdi & 0x0F;
+ if (digit <= 0x09)
+ *(++vendor) = digit + 0x30;
+ else
+ *(++vendor) = (digit & 0x07) + 0x3F;
+ break;
+ }
+ }
+ *(++vendor) = '\0';
+ IwavePnpPeek(pnprdp, 4, (BYTE *) serial);
+ IwavePnpPeek(pnprdp, 1, NULL); /* discard checksum */
+}
+/* ######################################################################## */
+/* */
+/* FUNCTION: IwavePnpPeek */
+/* */
+/* PROFILE: This function will return the number of specified bytes of */
+/* resource data from the serial EEPROM. The function will NOT */
+/* reset the serial EEPROM logic to allow reading the entire */
+/* EEPROM by issuing repeated calls. The caller must supply a */
+/* pointer to where the data are to be stored. */
+/* It is assumed that the InterWave is not in either "sleep" */
+/* or "wait for key" states. Note that on the first call, if */
+/* the caller means to read from the beggining of data the */
+/* serial EEPROM logic must be reset. For this, the caller */
+/* should issue a WAKE[CSN] command */
+/* */
+/* ######################################################################## */
+void
+IwavePnpPeek(PORT pnprdp, WORD bytes, BYTE * data)
+{
+ WORD i;
+ BYTE datum;
+
+ for (i = 1; i <= bytes; i++) {
+ outb(_PIDXR, 0x05); /* select PRESSI */
+
+ while (TRUE) { /* wait til new data byte is ready */
+ if (inb(pnprdp) & PNP_DATA_RDY)
+ break; /* new resource byte ready */
+ }
+ outb(_PIDXR, 0x04); /* select PRESDI */
+ datum = inb(pnprdp); /* read resource byte */
+ if (data != NULL)
+ *(data++) = datum; /* store it */
}
- else
- {
- model_num = "MAX";
- gus_type = 0x40;
- mixer_type = CS4231;
-#ifndef EXCLUDE_GUSMAX
- {
- unsigned char max_config = 0x40; /* Codec enable */
+}
+/* ######################################################################## */
+/* */
+/* FUNCTION: IwavePnpEeprom */
+/* */
+/* PROFILE: This function allows the caller to control the serial */
+/* EEPROM directly while the audio device is inactive. To */
+/* de-activate the audio device issue the call */
+/* IwavePnpActivate(AUDIO,OFF). */
+/* */
+/* ######################################################################## */
+void
+IwavePnpEeprom(BYTE ctrl)
+{
+ ENTER_CRITICAL;
+ outb(_PIDXR, 0xF1); /* select PSECI */
+ outb(_PNPWRP, ctrl); /* write PSECI */
+ LEAVE_CRITICAL;
+}
+/* ######################################################################## */
+/* */
+/* FUNCTION: IwavePnpActivate */
+/* */
+/* PROFILE: This function will activate or de-activate the audio device */
+/* or the external device on the InterWave. Set the "dev" arg */
+/* to AUDIO for the audio device or EXT for the external device. */
+/* Set "bool" to ON or OFF to turn the device on or off the ISA */
+/* bus. Notice that for a logical device to work, it must be */
+/* activated. */
+/* */
+/* ######################################################################## */
+void
+IwavePnpActivate(BYTE dev, BYTE bool)
+{
+ IwavePnpDevice(dev); /* select audio device */
+ ENTER_CRITICAL;
+ outb(_PIDXR, ACTIVATE_DEV); /* select Activate Register */
+ outb(_PNPWRP, bool); /* write register */
+ LEAVE_CRITICAL;
- if (dma > 3)
- max_config |= 0x30; /* 16 bit playback and capture DMAs */
+}
+/* ######################################################################## */
+/* */
+/* FUNCTION: IwavePnpDevice */
+/* */
+/* PROFILE: This function allows the caller to select between five */
+/* logical devices available on the InterWave.It is assumed */
+/* that the PNP state machine is in configuration mode. */
+/* */
+/* ######################################################################## */
+void
+IwavePnpDevice(BYTE dev)
+{
+ ENTER_CRITICAL;
+ outb(_PIDXR, _PLDNI); /* select PLDNI */
+ outb(_PNPWRP, dev); /* write PLDNI */
+ LEAVE_CRITICAL;
+}
+/* ######################################################################## */
+/* */
+/* FUNCTION: IwavePnpPower */
+/* */
+/* PROFILE: This function allows the caller to disable major sections of */
+/* the InterWave to prevent them from consuming power and */
+/* loading the ISA bus. */
+/* */
+/* It is assumed that the PNP state machine is in configuration */
+/* mode. */
+/* */
+/* ######################################################################## */
+void
+IwavePnpPower(BYTE mode)
+{
+ ENTER_CRITICAL;
+ outb(_PIDXR, _PPWRI); /* select PPWRI */
+ outb(_PNPWRP, mode); /* write PPWRI */
+ LEAVE_CRITICAL;
+}
+/* ######################################################################## */
+/* */
+/* FUNCTION: IwavePnpWake */
+/* */
+/* PROFILE: This function issues a WAKE[CSN] command to the InterWave. If */
+/* the CSN matches the PNP state machine will enter the */
+/* configuration state. Otherwise it will enter the sleep mode. */
+/* */
+/* It is assumed that the PNP state machine is not in the */
+/* "wait for key" state. */
+/* */
+/* ######################################################################## */
+void
+IwavePnpWake(BYTE csn)
+{
+ ENTER_CRITICAL;
+ outb(_PIDXR, _PWAKEI); /* select PWAKEI */
+ outb(_PNPWRP, csn); /* write csn */
+ LEAVE_CRITICAL;
+}
+/* ######################################################################## */
+/* */
+/* FUNCTION: IwavePnpIOcheck */
+/* */
+/* PROFILE: This function allows the caller to perform a conflict check */
+/* on an I/O port to be used by a logical device. The function */
+/* receives the base address of the I/O range as well as the */
+/* number of ports in the range and then performs the I/O check */
+/* protocol. It returns the address of the port if a conflict */
+/* is detected or IO_CHK if no conflict is detected. */
+/* */
+/* This function assumes that the logical device has been de- */
+/* activated and that the PNP state machine is in config mode. */
+/* */
+/* ######################################################################## */
+PORT
+IwavePnpIOcheck(PORT base, BYTE no_ports)
+{
+ BYTE i;
+ PORT portid;
- max_config |= (gus_base >> 4) & 0x0f; /* Extract the X from 2X0 */
+ outb(_PIDXR, RANGE_IOCHK); /* select IO range check reg */
- OUTB (max_config, gus_base + 0x106); /* UltraMax control */
- }
+ for (i = 0; i < no_ports; i++) {
+ portid = base + i; /* port to check */
+ outb(_PNPWRP, 0x02); /* must drive 0xAA onto bus */
+ if (inb(portid) != 0xAA)
+ return (portid); /* IO conflict detected */
- if (ad1848_detect (gus_base + 0x10c))
- {
- gus_mic_vol = gus_line_vol = gus_pcm_volume = 100;
- gus_wave_volume = 90;
- have_gus_max = 1;
- ad1848_init ("GUS MAX", gus_base + 0x10c,
- -irq,
- dma,
- dma);
- }
- else
- printk ("[Where's the CS4231?]");
-#endif
+ outb(_PNPWRP, 0x03); /* must drive 0x55 onto bus */
+ if (inb(portid) != 0x55)
+ return (portid); /* IO conflict detected */
}
- }
- 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.
+ return (IO_OK);
+}
+/* ######################################################################## */
+/* */
+/* FUNCTION: IwavePnpGetCSN */
+/* */
+/* PROFILE: This function allows the caller to detect an InterWave based */
+/* adapter board and will return its asigned CSN so that an */
+/* an application can access its PnP interface and determine the */
+/* borad's current configuration. In conducting its search for */
+/* the InterWave IC, the function will use the first 32 bits of */
+/* the Serial Identifier called the vendor ID in the PnP ISA */
+/* spec. The last 4 bits in the Vendor ID represent a revision */
+/* number for the particular product and this function gives the */
+/* caller the option of taking this revision number into account */
+/* or not in the search. If the function fails to find the */
+/* InterWave IC it will return FALSE. */
+/* */
+/* ######################################################################## */
+BYTE
+IwavePnpGetCSN(DWORD VendorID, BYTE csn_max)
+{
+ BYTE csn;
+ DWORD vendor;
+
+ IwavePnpKey(); /* Key to access PnP Interface */
+ VendorID &= (0xFFFFFFF0); /* reset 4 least significant bits */
+
+ for (csn = 1; csn <= csn_max; csn++) {
+ IwavePnpWake(csn); /* Select card */
+ IwavePnpPeek(iw.pnprdp, 4, (BYTE *) & vendor); /* get vendor ID */
+ vendor &= (0xFFFFFFF0);
+ if (vendor == VendorID) { /* If IDs match, InterWave is
+ * found */
+ outb(_PIDXR, 0x02); /* Place all cards in
+ * wait-for-key state */
+ outb(0x0A79, 0x02);
+ return (csn);
+ }
+ }
+ outb(_PIDXR, 0x02); /* Place all cards in wait-for-key state */
+ outb(0x0A79, 0x02);
+ return (FALSE); /* InterWave IC not found */
+}
+/* ######################################################################## */
+/* */
+/*
+ * FUNCTION: IwavePnpPing
+ */
+/* */
+/* PROFILE: This function allows the caller to detect an InterWave based */
+/* adapter board and will return its asigned CSN so that an */
+/* an application can access its PnP interface and determine the */
+/* borad's current configuration. In conducting its search for */
+/* the InterWave IC, the function will use the first 32 bits of */
+/* the Serial Identifier called the vendor ID in the PnP ISA */
+/* spec. The last 4 bits in the Vendor ID represent a revision */
+/* number for the particular product and will not be included */
+/* in the search. The function will return the Vendor ID and the */
+/* calling application should check the revision bits to make */
+/* sure they are compatible with the board. */
+/* */
+/* ######################################################################## */
+BYTE
+IwavePnpPing(DWORD VendorID)
+{
+ BYTE csn;
+
+ VendorID &= (0xFFFFFFF0); /* reset 4 least significant bits */
+ IwavePnpKey(); /* Key to access PnP Interface */
+ while (iw.pnprdp <= 0x23F) {
+ for (csn = 1; csn <= 10; csn++) {
+ IwavePnpWake(csn); /* Select card */
+ IwavePnpPeek(iw.pnprdp, 4, (BYTE *) & iw.vendor); /* get vendor ID */
+
+
+ if (((iw.vendor) & 0xFFFFFFF0) == VendorID) { /* If IDs match,
+ * InterWave is found */
+
+ outb(_PIDXR, 0x02); /* Place all cards in
+ * wait-for-key state */
+ outb(0x0A79, 0x02);
+ return (csn);
+ }
+ }
+ iw.pnprdp += 0x04;
+ }
+ outb(_PIDXR, 0x02); /* Place all cards in wait-for-key state */
+ outb(0x0A79, 0x02);
+ return (FALSE); /* InterWave IC not found */
+}
+
+/* end of pnp code */
+
+WORD
+IwaveMemSize(void)
+{
+ BYTE datum = 0x55;
+ ADDRESS local = 0L;
+
+ outb(iw.igidxr, _LMCI);
+ outb(iw.i8dp, inb(iw.i8dp) & 0xFD); /* DRAM I/O cycles selected */
+
+ while (TRUE) {
+ IwaveMemPoke(local, datum);
+ IwaveMemPoke(local + 1L, datum + 1);
+ if (IwaveMemPeek(local) != datum || IwaveMemPeek(local + 1L) != (datum + 1) || IwaveMemPeek(0L) != 0x55)
+ break;
+ local += RAM_STEP;
+ datum++;
+ }
+ return ((WORD) (local >> 10));
+}
+
+BYTE
+IwaveMemPeek(ADDRESS addr)
+{
+ PORT p3xr;
+
+ p3xr = iw.p3xr;
+
+
+ outb(iw.igidxr, 0x43); /* Select LMALI */
+ outw(iw.i16dp, (WORD) addr); /* Lower 16 bits of LM */
+ outb(iw.igidxr, 0x44); /* Select LMAHI */
+ outb(iw.i8dp, (BYTE) (addr >> 16)); /* Upper 8 bits of LM */
+ return (inb(iw.lmbdr)); /* return byte from LMBDR */
+}
+
+
+void
+IwaveMemPoke(ADDRESS addr, BYTE datum)
+{
+ PORT p3xr;
+ p3xr = iw.p3xr;
+
+
+ outb(iw.igidxr, 0x43); /* Select LMALI */
+ outw(iw.i16dp, (WORD) addr); /* Lower 16 bits of LM */
+ outb(iw.igidxr, 0x44); /* Select LMAHI */
+ outb(iw.i8dp, (BYTE) (addr >> 16)); /* Upper 8 bits of LM */
+ outb(iw.lmbdr, datum); /* Write byte to LMBDR */
+}
+
+/* ######################################################################## */
+/* */
+/* FUNCTION: IwaveMemCfg */
+/* */
+/* PROFILE : This function determines the amount of DRAM from its */
+/* configuration accross all banks. It sets the configuration */
+/* into register LMCFI and stores the total amount of DRAM */
+/* into iw.size_mem (Kbytes). */
+/* */
+/* The function first places the IC in enhanced mode to allow */
+/* full access to all DRAM locations. Then it selects full */
+/* addressing span (LMCFI[3:0]=0x0C). Finally, it determines */
+/* the amount of DRAM in each bank and from this the actual */
+/* configuration. */
+/* */
+/* Note that if a configuration other than one indicated in */
+/* the manual is implemented, this function will select */
+/* full addressing span (LMCFI[3:0]=0xC). */
+/* */
+/* ######################################################################## */
+void
+IwaveMemCfg(DWORD * lpbanks)
+{
+ DWORD bank[4] = {0L, 0L, 0L, 0L};
+ DWORD addr = 0L, base = 0L, cnt = 0L;
+ BYTE i, reg, ram = FALSE;
+ WORD lmcfi;
+ /* */
+ ENTER_CRITICAL;
+ outb(iw.igidxr, 0x99);
+ reg = inb(iw.i8dp); /* image of sgmi */
+ outb(iw.igidxr, 0x19);
+ outb(iw.i8dp, (BYTE) (reg | 0x01)); /* enable enhaced mode */
+ outb(iw.igidxr, _LMCFI);/* select LM Conf Reg */
+ lmcfi = inw(iw.i16dp) & 0xFFF0;
+ outw(iw.i16dp, lmcfi | 0x000C); /* max addr span */
+ /* */
+ /* Clear every RAM_STEPth location */
+ /* */
+ while (addr < RAM_MAX) {
+ IwaveMemPoke(addr, 0x00);
+ addr += RAM_STEP;
+ }
+ /* */
+ /* Determine amount of RAM in each bank */
+ /* */
+ for (i = 0; i < 4; i++) {
+ IwaveMemPoke(base, 0xAA); /* mark start of bank */
+ IwaveMemPoke(base + 1L, 0x55);
+ if ((IwaveMemPeek(base) == 0xAA) && (IwaveMemPeek(base + 1L) == 0x55))
+ ram = TRUE;
+ if (ram) {
+ while (cnt < BANK_MAX) {
+ bank[i] += RAM_STEP;
+ cnt += RAM_STEP;
+ addr = base + cnt;
+ if (IwaveMemPeek(addr) == 0xAA)
+ break;
+ }
+ }
+ if (lpbanks != NULL) {
+ *lpbanks = bank[i];
+ lpbanks++;
+ }
+ bank[i] = bank[i] >> 10;
+ base += BANK_MAX;
+ cnt = 0L;
+ ram = FALSE;
+ }
+ /* */
+ iw.flags &= ~DRAM_HOLES;
+ outb(iw.igidxr, _LMCFI);
+ if (bank[0] == 256 && bank[1] == 0 && bank[2] == 0 && bank[3] == 0)
+ outw(iw.i16dp, lmcfi);
+ else if (bank[0] == 256 && bank[1] == 256 && bank[2] == 0 && bank[3] == 0)
+ outw(iw.i16dp, lmcfi | 0x01);
+ else if (bank[0] == 256 && bank[1] == 256 && bank[2] == 256 && bank[3] == 256)
+ outw(iw.i16dp, lmcfi | 0x02);
+ else if (bank[0] == 256 && bank[1] == 1024 && bank[2] == 0 && bank[3] == 0)
+ outw(iw.i16dp, lmcfi | 0x03);
+ else if (bank[0] == 256 && bank[1] == 1024 && bank[2] == 1024 && bank[3] == 1024)
+ outw(iw.i16dp, lmcfi | 0x04);
+ else if (bank[0] == 256 && bank[1] == 256 && bank[2] == 1024 && bank[3] == 0)
+ outw(iw.i16dp, lmcfi | 0x05);
+ else if (bank[0] == 256 && bank[1] == 256 && bank[2] == 1024 && bank[3] == 1024)
+ outw(iw.i16dp, lmcfi | 0x06);
+ else if (bank[0] == 1024 && bank[1] == 0 && bank[2] == 0 && bank[3] == 0)
+ outw(iw.i16dp, lmcfi | 0x07);
+ else if (bank[0] == 1024 && bank[1] == 1024 && bank[2] == 0 && bank[3] == 0)
+ outw(iw.i16dp, lmcfi | 0x08);
+ else if (bank[0] == 1024 && bank[1] == 1024 && bank[2] == 1024 && bank[3] == 1024)
+ outw(iw.i16dp, lmcfi | 0x09);
+ else if (bank[0] == 4096 && bank[1] == 0 && bank[2] == 0 && bank[3] == 0)
+ outw(iw.i16dp, lmcfi | 0x0A);
+ else if (bank[0] == 4096 && bank[1] == 4096 && bank[2] == 0 && bank[3] == 0)
+ outw(iw.i16dp, lmcfi | 0x0B);
+ else /* Flag the non-contiguous config of memory */
+ iw.flags |= DRAM_HOLES;
+ /* */
+ outb(iw.igidxr, 0x19); /* restore sgmi */
+ outb(iw.i8dp, reg);
+ LEAVE_CRITICAL;
+}
+
+
+/* ######################################################################## */
+/**/
+/* FUNCTION: IwaveCodecIrq */
+/**/
+/* PROFILE: This function disables or enables the Codec Interrupts. To */
+/* enable interrupts set CEXTI[2] high thus causing all interrupt */
+/* sources (CSR3I[6:4]) to pass onto the IRQ pin. To disable */
+/* interrupts set CEXTI[1]=0. To enable Code IRQs issue this call: */
+/**/
+/* IwaveCodecIrq(CODEC_IRQ_ENABLE). To disable IRQs issue the call */
+/**/
+/* IwaveCodeIrq(~CODEC_IRQ_ENABLE). */
+/**/
+/* ######################################################################## */
+void
+IwaveCodecIrq(BYTE mode)
+{
+ BYTE reg;
+
+ ENTER_CRITICAL;
+ reg = inb(iw.pcodar) & 0xE0;
+ outb(iw.pcodar, reg | _CSR3I); /* select CSR3I */
+ outb(iw.cdatap, 0x00); /* clear all interrupts */
+ outb(iw.pcodar + 0x02, 0x00); /* clear CSR1R */
+ outb(iw.pcodar, reg | _CEXTI); /* select CEXTI */
+ reg = inb(iw.cdatap);
+ if (mode == CODEC_IRQ_ENABLE) /* enable Codec Irqs */
+ outb(iw.cdatap, (BYTE) (reg | CODEC_IRQ_ENABLE));
+ else /* disable Codec Irqs */
+ outb(iw.cdatap, (BYTE) (reg & ~CODEC_IRQ_ENABLE));
+ LEAVE_CRITICAL;
+}
+
+
+/* ######################################################################### */
+/**/
+/* FUNCTION: IwaveRegPeek */
+/**/
+/* PROFILE : This function returns the value stored in any readable */
+/* InterWave register. It takes as input a pointer to a */
+/* structure containing the addresses of the relocatable I/O */
+/* space as well as a register mnemonic. To correctly use this */
+/* function, the programmer must use the mnemonics defined in */
+/* "iwdefs.h". These mnemonics contain coded information used */
+/* by the function to properly access the desired register. */
+/**/
+/* An attempt to read from a write-only register will return */
+/* meaningless data. */
+/**/
+/* ######################################################################### */
+WORD
+IwaveRegPeek(DWORD reg_mnem)
+{
+ BYTE index, val;
+ WORD reg_id, offset;
+
+ offset = (WORD) ((BYTE) reg_mnem);
+ reg_id = (WORD) (reg_mnem >> 16);
+ index = (BYTE) (reg_mnem >> 8);
+
+ /* ################################################### */
+ /* Logic to read registers in P2XR block & GMCR */
+ /* ################################################### */
+
+ if (reg_id >= 0x0001 && reg_id <= 0x001A) { /* UMCR to GMCR */
+ if (reg_id <= 0x000E) /* UMCR to USRR */
+ return ((WORD) inb(iw.p2xr + offset));
+
+ if (reg_id == 0x0019)
+ return ((WORD) inb(iw.p201ar));
+
+ else { /* GUS Hidden registers or GMCR */
+ BYTE iveri;
+
+ outb(iw.igidxr, 0x5B); /* select IVERI */
+ iveri = inb(iw.i8dp); /* read IVERI */
+ outb(iw.i8dp, (BYTE) (iveri | 0x09)); /* set IVERI[3,0] */
+ if (reg_id == 0x001A) { /* GMCR */
+ val = inb(iw.p3xr);
+ outb(iw.i8dp, iveri); /* restore IVERI */
+ return ((WORD) val);
+ }
+ val = inb(iw.p2xr + 0x0F); /* read URCR */
+ val = (val & 0xF8) | index; /* value for URCR[2:0] */
+ outb(iw.p2xr + 0x0F, val); /* set URCR[2:0] */
+
+ if (reg_mnem == UDCI || reg_mnem == UICI) {
+ val = inb(iw.p2xr);
+ if (reg_mnem == UDCI)
+ outb(iw.p2xr, (BYTE) (val & 0xBF));
+ else
+ outb(iw.p2xr, (BYTE) (val | 0x40));
+ }
+ val = inb(iw.p2xr + 0x0B);
+ outb(iw.igidxr, 0x5B); /* select IVERI */
+ outb(iw.i8dp, iveri); /* restore IVERI */
+ return ((WORD) val); /* read register */
+ }
+ }
+ /* ################################################### */
+ /* Logic to read registers in P3XR block */
+ /* ################################################### */
+
+ if (reg_id >= 0x001B && reg_id <= 0x005C) { /* GMSR to LMBDR */
+ if (reg_id == 0x005C) /* LMBDR */
+ return ((WORD) inb(iw.lmbdr));
+
+ if (reg_id >= 0x001B && reg_id <= 0x0021) /* GMSR to I8DP */
+ if (offset == 0x04)
+ return (inw(iw.i16dp));
+ else
+ return ((WORD) inb(iw.p3xr + offset));
+ else { /* indexed registers */
+
+ if (reg_id <= 0x003F)
+ index |= 0x80; /* adjust for reading */
+
+ outb(iw.igidxr, index); /* select register */
+
+ if (offset == 0x04)
+ return (inw(iw.i16dp));
+ else
+ return ((WORD) inb(iw.i8dp));
+ }
+ }
+ /* #################################################### */
+ /* Logic to read registers in PCODAR block */
+ /* #################################################### */
+
+ if (reg_id >= 0x005D && reg_id <= 0x0081) { /* CIDXR to CLRCTI */
+ if (reg_id <= 0x0061)
+ return ((WORD) inb(iw.pcodar + offset)); /* CRDR */
+
+ else { /* indexed registers */
+ BYTE cidxr;
+
+ cidxr = inb(iw.pcodar);
+ cidxr = (cidxr & 0xE0) + index;
+ outb(iw.pcodar, cidxr); /* select register */
+ return ((WORD) inb(iw.cdatap));
+ }
+ }
+ /* ##################################################### */
+ /* Logic to read the PnP registers */
+ /* ##################################################### */
+ if (reg_id >= 0x0082 && reg_id <= 0x00B7) { /* PCSNBR to PMITI */
+ if (reg_id == 0x0085)
+ return ((WORD) inb(iw.pnprdp));
+
+ if (reg_id < 0x0085)
+ return ((WORD) inb((WORD) reg_mnem));
+
+ else { /* indexed registers */
+ if (reg_id >= 0x008E && reg_id <= 0x00B7) {
+ outb(0x0279, 0x07); /* select PLDNI */
+ outb(0xA79, (BYTE) offset); /* select logical dev */
+ }
+ outb(0x0279, index); /* select the register */
+ return ((WORD) inb(iw.pnprdp));
+ }
+ }
+ return 0;
+}
+/* ######################################################################### */
+/**/
+/* FUNCTION: IwaveRegPoke */
+/**/
+/* PROFILE : This function writes a value to any writable */
+/* InterWave register. It takes as input a pointer to a */
+/* structure containing the addresses of the relocatable I/O */
+/* space as well as a register mnemonic. To correctly use this */
+/* function, the programmer must use the mnemonics defined in */
+/* "iwdefs.h". These mnemonics contain coded information used */
+/* by the function to properly access the desired register. */
+/**/
+/* This function does not guard against writing to read-only */
+/* registers. It is the programmer's responsibility to ensure */
+/* that the writes are to valid registers. */
+/**/
+/* ######################################################################### */
+void
+IwaveRegPoke(DWORD reg_mnem, WORD datum)
+{
+ BYTE index;
+ BYTE val;
+ WORD reg_id;
+ WORD offset;
+
+ offset = (WORD) ((BYTE) reg_mnem);
+ reg_id = (WORD) (reg_mnem >> 16);
+ index = (BYTE) (reg_mnem >> 8);
+
+
+ /* ####################################################### */
+ /* Logic to write to registers in P2XR block */
+ /* ####################################################### */
+ if (reg_id >= 0x0001 && reg_id <= 0x0019) { /* UMCR to GGCR */
+ if (reg_id <= 0x000E) { /* UMCR to USRR */
+ outb(iw.p2xr + offset, (BYTE) datum);
+ return;
+ }
+ if (reg_id == 0x0019) {
+ outb(iw.p201ar, (BYTE) datum);
+ return;
+ } else { /* GUS Hidden registers */
+
+ BYTE iveri;
+
+ outb(iw.igidxr, 0x5B); /* select IVERI */
+ iveri = inb(iw.i8dp); /* read IVERI */
+ outb(iw.i8dp, (BYTE) (iveri | 0x09)); /* set IVERI[3,0] */
+ val = inb(iw.p2xr + 0x0F); /* read URCR */
+ val = (val & 0xF8) | index; /* value for URCR[2:0] */
+ outb(iw.p2xr + 0x0F, val); /* set URCR[2:0] */
+
+ if (reg_mnem == UDCI || reg_mnem == UICI) {
+ val = inb(iw.p2xr); /* read UMCR */
+ if (reg_mnem == UDCI)
+ outb(iw.p2xr, (BYTE) (val & 0xBF)); /* set UMCR[6]=0 */
+ else
+ outb(iw.p2xr, (BYTE) (val | 0x40)); /* set UMCR[6]=1 */
+ }
+ outb(iw.p2xr + 0x0B, (BYTE) datum); /* write register */
+ outb(iw.igidxr, 0x5B); /* select IVERI */
+ outb(iw.i8dp, iveri); /* restore IVERI */
+ return;
+ }
+ }
+ /* ############################################################# */
+ /* Logic to write to registers in P3XR block */
+ /* ############################################################# */
+
+ if (reg_id >= 0x001A && reg_id <= 0x005C) { /* GMCR to LMBDR */
+
+ if (reg_id == 0x005C) { /* LMBDR */
+ outb(iw.lmbdr, (BYTE) datum);
+ return;
+ }
+ if (reg_id == 0x001B) /* GMSR */
+ return;
+
+ if (reg_id >= 0x001A && reg_id <= 0x0021) /* GMCR to I8DP */
+ if (offset == 0x04)
+ outw(iw.i16dp, datum);
+ else
+ outb(iw.p3xr + offset, (BYTE) datum);
+ else { /* indexed registers */
+ outb(iw.igidxr, index); /* select register */
+
+ if (offset == 0x04)
+ outw(iw.i16dp, datum);
+ else
+ outb(iw.i8dp, (BYTE) datum);
+ }
+ }
+ /* /################################################### */
+ /* Logic to write to registers in PCODAR block */
+ /* ################################################### */
+
+ if (reg_id >= 0x005C && reg_id <= 0x0081) { /* CIDXR to CLRCTI */
+ if (reg_id <= 0x0061)
+ outb(iw.pcodar + offset, (BYTE) datum);
+
+ else { /* one of the indexed registers */
+ BYTE cidxr;
+
+ cidxr = inb(iw.pcodar);
+ cidxr = (cidxr & 0xE0) + index;
+ outb(iw.pcodar, cidxr); /* select register */
+ outb(iw.cdatap, (BYTE) datum);
+ }
+ }
+ /* ###################################################### */
+ /* Logic to write to the PnP registers */
+ /* ###################################################### */
+ if (reg_id >= 0x0082 && reg_id <= 0x00B7) {
+ if (reg_id == 0x0085) {
+ outb(iw.pnprdp, (BYTE) datum);
+ return;
+ }
+ if (reg_id < 0x0085)
+ outb((WORD) reg_mnem, (BYTE) datum);
+
+ else { /* one of the indexed registers */
+ if (reg_id >= 0x008E && reg_id <= 0x00B7) {
+ outb(0x0279, 0x07); /* select PLDNI */
+ outb(0xA79, (BYTE) offset); /* select logical dev */
+ }
+ outb(0x0279, index); /* select the register */
+ outb(0xA79, (BYTE) datum);
+ }
+ }
+}
+
+
+void
+IwaveLineLevel(char level, char index)
+{
+ char reg;
+
+ level &= 0x1F;
+
+ ENTER_CRITICAL;
+ reg = inb(iw.pcodar) & 0xE0;
+ outb(iw.pcodar, reg | index); /* select register */
+ outb(iw.cdatap, (BYTE) ((inb(iw.cdatap) & 0x80) | level)); /* set level */
+ LEAVE_CRITICAL;
+}
+
+void
+IwaveCodecMode(char mode)
+{
+ char reg;
+
+ ENTER_CRITICAL;
+ reg = inb(iw.pcodar) & 0xE0;
+ outb(iw.pcodar, reg | _CMODEI); /* select CMODEI */
+ outb(iw.cdatap, mode);
+ LEAVE_CRITICAL;
+ iw.cmode = mode;
+}
+
+void
+IwaveLineMute(BYTE mute, BYTE inx)
+{
+ BYTE reg;
+
+ ENTER_CRITICAL;
+ reg = inb(iw.pcodar) & 0xE0;
+ outb(iw.pcodar, reg | inx); /* select register */
+ if (mute == ON)
+ outb(iw.cdatap, (BYTE) (inb(iw.cdatap) | 0x80)); /* mute */
+ else
+ outb(iw.cdatap, (BYTE) (inb(iw.cdatap) & 0x7F)); /* unmute */
+ LEAVE_CRITICAL;
+}
+
+void
+Iwaveinitcodec()
+{
+
+ u_short iwl_codec_base = iw.pcodar;
+ u_short iwl_codec_data = iw.pcodar + 1;
+ u_short foo;
+
+
+
+ /*
+ * Set the CEXTI register foo = CODEC_CEXTI_DEFAULT;
+ * IWL_CODEC_OUT(EXTERNAL_CONTROL, foo);
+ */
+ /*
+ * Disable Interrupts iwl_codec_disable_irqs();
*/
- }
+ /* Set the CODEC to Operate in Mode 3 */
+ IWL_CODEC_OUT(MODE_SELECT_ID, 0x6C);
+ foo = inb(iwl_codec_data);
- printk (" <Gravis UltraSound %s (%dk)>", model_num, (int) gus_mem_size / 1024);
+ /* Set the configuration registers to their default values */
+ foo = CODEC_CFIG1I_DEFAULT;
+ IWL_CODEC_OUT(CONFIG_1 | CODEC_MCE, foo);
+ outb(iwl_codec_base, CONFIG_1);
+ foo = CODEC_CFIG2I_DEFAULT;
+ IWL_CODEC_OUT(CONFIG_2, foo);
-#ifndef SCO
- sprintf (gus_info.name, "Gravis UltraSound %s (%dk)", model_num, (int) gus_mem_size / 1024);
-#endif
+ foo = CODEC_CFIG3I_DEFAULT;
+ IWL_CODEC_OUT(CONFIG_3, foo);
- if (irq < 0 || irq > 15)
- {
- printk ("ERROR! Invalid IRQ#%d. GUS Disabled", irq);
- return mem_start;
- }
+}
- if (dma < 0 || dma > 7)
- {
- printk ("ERROR! Invalid DMA#%d. GUS Disabled", dma);
- return mem_start;
- }
- gus_irq = irq;
- gus_dma = dma;
- if (num_synths >= MAX_SYNTH_DEV)
- printk ("GUS Error: Too many synthesizers\n");
- else
- {
- voice_alloc = &guswave_operations.alloc;
- synth_devs[num_synths++] = &guswave_operations;
- }
+int
+IwaveOpen(char voices, char mode, struct address_info * hw)
+{
- PERMANENT_MALLOC (struct patch_info *, samples,
- (MAX_SAMPLE + 1) * sizeof (*samples), mem_start);
+ u_long flags;
+ u_char tmp;
- reset_sample_memory ();
+ flags = splhigh();
- gus_initialize ();
+ iw.pnprdp = 0;
+ if (IwavePnpIsol(&iw.pnprdp)) {
- if (num_audiodevs < MAX_AUDIO_DEV)
- {
- audio_devs[gus_devnum = num_audiodevs++] = &gus_sampling_operations;
- audio_devs[gus_devnum]->dmachan = dma;
- audio_devs[gus_devnum]->buffcount = 1;
- audio_devs[gus_devnum]->buffsize = DSP_BUFFSIZE;
- }
- else
- printk ("GUS: Too many PCM devices available\n");
+ iw.vendor = GUS_PNP_ID;
- /*
- * Mixer dependent initialization.
- */
+ iw.csn = IwavePnpPing(iw.vendor);
- switch (mixer_type)
- {
- case ICS2101:
- gus_mic_vol = gus_line_vol = gus_pcm_volume = 100;
- gus_wave_volume = 90;
- return ics2101_mixer_init (mem_start);
+ IwavePnpKey();
- case CS4231:
- /* Initialized elsewhere (ad1848.c) */
- default:
- return gus_default_mixer_init (mem_start);
- }
+ IwavePnpWake(iw.csn);
+
+ IwavePnpGetCfg();
+ IwavePnpKey();
+
+ IwavePnpWake(iw.csn);
+ }
+ if (hw->irq > 0) {
+ /* I see the user wants to set the GUS PnP */
+ /* Okay lets do it */
+ iw.csn = 1;
+ iw.p2xr = hw->io_base;
+ iw.p3xr = hw->io_base + 0x100;
+ iw.pcodar = hw->io_base + 0x10c;
+
+ iw.synth_irq = hw->irq;
+
+ iw.midi_irq = hw->irq;
+
+ iw.dma1_chan = hw->dma;
+
+ if (hw->dma2 == -1) {
+ iw.dma2_chan = hw->dma;
+ } else {
+ iw.dma2_chan = hw->dma2;
+ }
+
+
+ } else {
+
+ /* tell the os what we are doing 8) */
+ hw->io_base = iw.p2xr;
+ hw->irq = iw.synth_irq;
+ /*
+ * iw.dma1_chan = 1; iw.dma2_chan = 3 ;
+ */
+ hw->dma = iw.dma1_chan;
+ hw->dma2 = iw.dma2_chan;
- return mem_start;
+
+ }
+
+ if (iw.csn > 0 && iw.csn < MAX_GUS_PNP) {
+ gus_pnp_found[iw.csn] = hw->io_base;
+
+ }
+ iw.cdatap = iw.pcodar + 1;
+ iw.csr1r = iw.pcodar + 2;
+ iw.cxdr = iw.pcodar + 3;/* CPDR or CRDR */
+ iw.gmxr = iw.p3xr;
+ iw.gmxdr = iw.p3xr + 1; /* GMTDR or GMRDR */
+ iw.svsr = iw.p3xr + 2;
+ iw.igidxr = iw.p3xr + 3;
+ iw.i16dp = iw.p3xr + 4;
+ iw.i8dp = iw.p3xr + 5;
+ iw.lmbdr = iw.p3xr + 7;
+ iw.voices = voices;
+
+ if (iw.pnprdp > 0 && iw.csn > 0) {
+ IwavePnpSetCfg();
+ IwavePnpActivate(AUDIO, ON);
+ IwavePnpActivate(EXT, ON);
+ }
+ /* IwavePnpActivate(EMULATION,ON); */
+
+
+ /* reset */
+ outb(iw.igidxr, _URSTI);/* Pull reset */
+ outb(iw.i8dp, 0x00);
+ DELAY(1000 * 30);
+
+ outb(iw.i8dp, 0x01); /* Release reset */
+ DELAY(1000 * 30);
+
+ /* end of reset */
+
+
+ IwaveMemCfg(NULL);
+
+
+ tmp = IwaveRegPeek(IDECI);
+
+ IwaveRegPoke(IDECI, tmp | 0x18);
+
+ IwaveCodecMode(CODEC_MODE2); /* Default codec mode */
+ IwaveRegPoke(ICMPTI, 0);
+
+ outb(iw.igidxr, 0x99);
+ tmp = inb(iw.i8dp);
+ outb(iw.igidxr, 0x19);
+ outb(iw.i8dp, tmp);
+
+
+
+ IwaveCodecIrq(~CODEC_IRQ_ENABLE);
+
+ Iwaveinitcodec();
+
+ outb(iw.p2xr, 0x0c); /* Disable line in, mic and line out */
+
+ IwaveRegPoke(CLCI, 0x3f << 2);
+
+ IwaveLineLevel(0, _CLOAI);
+ IwaveLineLevel(0, _CROAI);
+
+ IwaveLineMute(OFF, _CLOAI);
+ IwaveLineMute(OFF, _CROAI);
+
+ IwaveLineLevel(0, _CLLICI);
+ IwaveLineLevel(0, _CRLICI);
+ IwaveLineMute(OFF, _CLLICI);
+ IwaveLineMute(OFF, _CRLICI);
+
+ IwaveLineLevel(0, _CLDACI);
+ IwaveLineLevel(0, _CRDACI);
+ IwaveLineMute(ON, _CLDACI);
+ IwaveLineMute(ON, _CRDACI);
+
+ IwaveLineLevel(0, _CLLICI);
+ IwaveLineLevel(0, _CRLICI);
+ IwaveLineMute(ON, _CLLICI);
+ IwaveLineMute(ON, _CRLICI);
+
+
+ IwaveInputSource(LEFT_SOURCE, MIC_IN);
+ IwaveInputSource(RIGHT_SOURCE, MIC_IN);
+
+ outb(iw.pcodar, 0x9 | 0x40);
+ outb(iw.cdatap, 0);
+ IwaveCodecIrq(CODEC_IRQ_ENABLE);
+ outb(iw.pcodar, _CFIG3I | 0x20);
+
+
+ outb(iw.cdatap, 0xC2); /* Enable Mode 3 IRQs & Synth */
+
+ outb(iw.igidxr, _URSTI);
+ outb(iw.i8dp, GF1_SET | GF1_OUT_ENABLE | GF1_IRQ_ENABLE);
+ DELAY(1000 * 30);
+ iw.size_mem = IwaveMemSize(); /* Bytes of RAM in this mode */
+ outb(iw.p2xr, 0xc); /* enable output */
+ IwaveRegPoke(CLCI, 0x3f << 2);
+
+ IwaveCodecIrq(CODEC_IRQ_ENABLE);
+ splx(flags);
+
+ DELAY(1000 * 100);
+ IwaveRegPoke(CPDFI, 0);
+
+ return (TRUE);
}
-static void
-do_loop_irq (int voice)
+
+void
+gus_wave_init(struct address_info * hw_config)
{
- unsigned char tmp;
- int mode, parm;
- unsigned long flags;
+ u_long flags;
+ u_char val, gus_pnp_seen = 0;
+ char *model_num = "2.4";
+ int gus_type = 0x24; /* 2.4 */
+ int irq = hw_config->irq, dma = hw_config->dma, dma2 = hw_config->dma2;
+ int otherside = -1, i;
+
+ if (irq < 0 || irq > 15) {
+ printf("ERROR! Invalid IRQ#%d. GUS Disabled", irq);
+ return;
+ }
+ if (dma < 0 || dma > 7) {
+ printf("ERROR! Invalid DMA#%d. GUS Disabled", dma);
+ return;
+ }
+ for (i = 0; i < MAX_GUS_PNP; i++) {
+ if (gus_pnp_found[i] != 0 && gus_pnp_found[i] == hw_config->io_base)
+ gus_pnp_seen = 1;
+ }
+#ifdef NOGUSPNP
+ gus_pnp_seen = 0;
+#endif
- DISABLE_INTR (flags);
- gus_select_voice (voice);
+ gus_irq = irq;
+ gus_dma = dma;
+ gus_dma2 = dma2;
- tmp = gus_read8 (0x00);
- tmp &= ~0x20; /*
- * Disable wave IRQ for this_one voice
- */
- gus_write8 (0x00, tmp);
+ if (gus_dma2 == -1)
+ gus_dma2 = dma;
- mode = voices[voice].loop_irq_mode;
- voices[voice].loop_irq_mode = 0;
- parm = voices[voice].loop_irq_parm;
+ /*
+ * Try to identify the GUS model.
+ *
+ * Versions < 3.6 don't have the digital ASIC. Try to probe it first.
+ */
- switch (mode)
- {
+ flags = splhigh();
+ outb(gus_base + 0x0f, 0x20);
+ val = inb(gus_base + 0x0f);
+ splx(flags);
- case LMODE_FINISH: /*
- * Final loop finished, shoot volume down
- */
-
- if ((int) (gus_read16 (0x09) >> 4) < 100) /*
- * Get current volume
- */
- {
- gus_voice_off ();
- gus_rampoff ();
- gus_voice_init (voice);
- break;
- }
- gus_ramp_range (65, 4065);
- gus_ramp_rate (0, 63); /*
- * Fastest possible rate
- */
- gus_rampon (0x20 | 0x40); /*
- * Ramp down, once, irq
- */
- voices[voice].volume_irq_mode = VMODE_HALT;
- break;
-
- case LMODE_PCM_STOP:
- pcm_active = 0; /* Signal to the play_next_pcm_block routine */
- case LMODE_PCM:
- {
- int orig_qlen = pcm_qlen;
- int flag; /* 0 or 2 */
-
- pcm_qlen--;
- pcm_head = (pcm_head + 1) % pcm_nblk;
- if (pcm_qlen)
- {
- play_next_pcm_block ();
- }
- else
- { /* Underrun. Just stop the voice */
- gus_voice_off ();
- gus_rampoff ();
- pcm_active = 0;
- }
+ 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);
/*
- * If the queue was full before this interrupt, the DMA transfer was
- * suspended. Let it continue now.
- */
- if (dma_active)
- {
- if (pcm_qlen == 0)
- flag = 1; /* Underflow */
+ * 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.
+ *
+ */
+
+ if (gus_pnp_seen)
+ val = 66;
+
+ 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 {
+ if (gus_pnp_seen)
+ model_num = "PNP";
else
- flag = 0;
- dma_active = 0;
- }
- else
- flag = 2; /* Just notify the dmabuf.c */
- DMAbuf_outputintr (gus_devnum, flag);
- }
- break;
+ model_num = "MAX";
+
+ gus_type = 0x40;
+ mixer_type = CS4231;
+#ifdef CONFIG_GUSMAX
+ {
+ u_char max_config = 0x40; /* Codec enable */
+
+ if (gus_dma2 == -1)
+ gus_dma2 = gus_dma;
+
+ if (gus_dma > 3)
+ max_config |= 0x10; /* 16 bit capture DMA */
+
+ if (gus_dma2 > 3)
+ max_config |= 0x20; /* 16 bit playback DMA */
+
+ max_config |= (gus_base >> 4) & 0x0f; /* Extract the X from
+ * 2X0 */
+
+ outb(gus_base + 0x106, max_config); /* UltraMax control */
+ }
+
+ if (ad1848_detect(gus_base + 0x10c, NULL, hw_config->osp)) {
+
+ gus_mic_vol = gus_line_vol = gus_pcm_volume = 100;
+ gus_wave_volume = 90;
+ have_gus_max = 1;
+ if (gus_pnp_seen) {
+
+ ad1848_init("GUS PNP", gus_base + 0x10c,
+ -irq,
+ gus_dma2, /* Playback DMA */
+ gus_dma, /* Capture DMA */
+ 1, /* Share DMA channels with GF1 */
+ hw_config->osp);
+
+
+ } else {
+ ad1848_init("GUS MAX", gus_base + 0x10c,
+ -irq,
+ gus_dma2, /* Playback DMA */
+ gus_dma, /* Capture DMA */
+ 1, /* Share DMA channels with GF1 */
+ hw_config->osp);
+ }
+ otherside = num_audiodevs - 1;
+
+ } else
+ printf("[Where's the CS4231?]");
+#else
+ printf("\n\n\nGUS MAX support was not compiled in!!!\n\n\n\n");
+#endif
+ }
+ } else {
+ /*
+ * ASIC not detected so the card must be 2.2 or 2.4. There
+ * could still be the 16-bit/mixer daughter card.
+ */
+ }
- default:;
+ if (gus_pnp_seen) {
+ sprintf(gus_info.name, "Gravis %s (%dk)", model_num, (int) gus_mem_size / 1024);
+ } else {
+ sprintf(gus_info.name, "Gravis UltraSound %s (%dk)", model_num, (int) gus_mem_size / 1024);
+ }
+ conf_printf(gus_info.name, hw_config);
+
+ if (num_synths >= MAX_SYNTH_DEV)
+ printf("GUS Error: Too many synthesizers\n");
+ else {
+ voice_alloc = &guswave_operations.alloc;
+ synth_devs[num_synths++] = &guswave_operations;
+#ifdef CONFIG_SEQUENCER
+ gus_tmr_install(gus_base + 8);
+#endif
+ }
+ samples = (struct patch_info *) malloc((MAX_SAMPLE + 1) * sizeof(*samples), M_DEVBUF, M_NOWAIT);
+ if (!samples)
+ panic("SOUND: Cannot allocate memory\n");
+
+ reset_sample_memory();
+
+ gus_initialize();
+
+ if (num_audiodevs < MAX_AUDIO_DEV) {
+ audio_devs[gus_devnum = num_audiodevs++] = &gus_sampling_operations;
+ audio_devs[gus_devnum]->otherside = otherside;
+ audio_devs[gus_devnum]->dmachan1 = dma;
+ audio_devs[gus_devnum]->dmachan2 = dma2;
+ audio_devs[gus_devnum]->buffsize = DSP_BUFFSIZE;
+ if (otherside != -1) {
+ /*
+ * glue logic to prevent people from opening the gus
+ * max via the gf1 and the cs4231 side . Only the gf1
+ * or the cs4231 are allowed to be open
+ */
+
+ audio_devs[otherside]->otherside = gus_devnum;
+ }
+ if (dma2 != dma && dma2 != -1)
+ audio_devs[gus_devnum]->flags |= DMA_DUPLEX;
+ } else
+ printf("GUS: Too many PCM devices available\n");
+
+ /*
+ * Mixer dependent initialization.
+ */
+
+ switch (mixer_type) {
+ case ICS2101:
+ gus_mic_vol = gus_line_vol = gus_pcm_volume = 100;
+ gus_wave_volume = 90;
+ ics2101_mixer_init();
+ return;
+
+ case CS4231:
+ /* Initialized elsewhere (ad1848.c) */
+ default:
+ gus_default_mixer_init();
+ return;
}
- RESTORE_INTR (flags);
}
static void
-do_volume_irq (int voice)
+do_loop_irq(int voice)
{
- unsigned char tmp;
- int mode, parm;
- unsigned long flags;
+ u_char tmp;
+ int mode, parm;
+ u_long flags;
+
+ flags = splhigh();
+ gus_select_voice(voice);
+
+ tmp = gus_read8(0x00);
+ tmp &= ~0x20; /* Disable wave IRQ for this_one voice */
+ gus_write8(0x00, tmp);
+
+ if (tmp & 0x03) /* Voice stopped */
+ voice_alloc->map[voice] = 0;
+
+ mode = voices[voice].loop_irq_mode;
+ voices[voice].loop_irq_mode = 0;
+ parm = voices[voice].loop_irq_parm;
+
+ switch (mode) {
+
+ case LMODE_FINISH: /* Final loop finished, shoot volume down */
+
+ if ((int) (gus_read16(0x09) >> 4) < 100) { /* Get current volume */
+ gus_voice_off();
+ gus_rampoff();
+ gus_voice_init(voice);
+ break;
+ }
+ gus_ramp_range(65, 4065);
+ gus_ramp_rate(0, 63); /* Fastest possible rate */
+ gus_rampon(0x20 | 0x40); /* Ramp down, once, irq */
+ voices[voice].volume_irq_mode = VMODE_HALT;
+ break;
+
+ case LMODE_PCM_STOP:
+ pcm_active = 0; /* Signal to the play_next_pcm_block routine */
+ case LMODE_PCM:
+ {
+ int flag; /* 0 or 2 */
+
+ pcm_qlen--;
+ pcm_head = (pcm_head + 1) % pcm_nblk;
+ if (pcm_qlen && pcm_active) {
+ play_next_pcm_block();
+ } else {/* Underrun. Just stop the voice */
+ gus_select_voice(0); /* Left channel */
+ gus_voice_off();
+ gus_rampoff();
+ gus_select_voice(1); /* Right channel */
+ gus_voice_off();
+ gus_rampoff();
+ pcm_active = 0;
+ }
+
+ /*
+ * If the queue was full before this interrupt, the
+ * DMA transfer was suspended. Let it continue now.
+ */
+ if (dma_active) {
+ if (pcm_qlen == 0)
+ flag = 1; /* Underflow */
+ else
+ flag = 0;
+ dma_active = 0;
+ } else
+ flag = 2; /* Just notify the dmabuf.c */
+ DMAbuf_outputintr(gus_devnum, flag);
+ }
+ break;
+
+ default:;
+ }
+ splx(flags);
+}
- DISABLE_INTR (flags);
+void
+do_volume_irq(int voice)
+{
+ u_char tmp;
+ int mode, parm;
+ u_long flags;
- gus_select_voice (voice);
+ flags = splhigh();
- tmp = gus_read8 (0x0d);
- tmp &= ~0x20; /*
- * Disable volume ramp IRQ
- */
- gus_write8 (0x0d, tmp);
+ gus_select_voice(voice);
- mode = voices[voice].volume_irq_mode;
- voices[voice].volume_irq_mode = 0;
- parm = voices[voice].volume_irq_parm;
+ tmp = gus_read8(0x0d);
+ tmp &= ~0x20; /* Disable volume ramp IRQ */
+ gus_write8(0x0d, tmp);
- switch (mode)
- {
- 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,
- voices[voice].note_pending, 0);
+ mode = voices[voice].volume_irq_mode;
+ voices[voice].volume_irq_mode = 0;
+ parm = voices[voice].volume_irq_parm;
- if (voices[voice].sample_pending >= 0)
- {
- guswave_set_instr (voices[voice].dev_pending, voice,
- voices[voice].sample_pending);
- voices[voice].sample_pending = -1;
+ switch (mode) {
+ case VMODE_HALT: /* Decay phase finished */
+ splx(flags);
+ gus_voice_init(voice);
+ break;
+
+ case VMODE_ENVELOPE:
+ gus_rampoff();
+ splx(flags);
+ step_envelope(voice);
+ break;
+
+ case VMODE_START_NOTE:
+ splx(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,
+ voices[voice].note_pending, 0);
+
+ if (voices[voice].sample_pending >= 0) {
+ guswave_set_instr(voices[voice].dev_pending, voice,
+ voices[voice].sample_pending);
+ voices[voice].sample_pending = -1;
+ }
+ break;
+
+ default:;
}
- break;
+}
- default:;
- }
+void
+gus_voice_irq(void)
+{
+ u_long wave_ignore = 0, volume_ignore = 0;
+ u_long voice_bit;
+
+ u_char src, voice;
+
+ while (1) {
+ src = gus_read8(0x0f); /* Get source info */
+ voice = src & 0x1f;
+ src &= 0xc0;
+
+ if (src == (0x80 | 0x40))
+ return; /* No interrupt */
+
+ voice_bit = 1 << voice;
+
+ if (!(src & 0x80)) /* Wave IRQ pending */
+ if (!(wave_ignore & voice_bit) && (int) voice < nr_voices) { /* Not done yet */
+ wave_ignore |= voice_bit;
+ do_loop_irq(voice);
+ }
+ if (!(src & 0x40)) /* Volume IRQ pending */
+ if (!(volume_ignore & voice_bit) && (int) voice < nr_voices) { /* Not done yet */
+ volume_ignore |= voice_bit;
+ do_volume_irq(voice);
+ }
+ }
}
void
-gus_voice_irq (void)
+guswave_dma_irq(void)
{
- unsigned long wave_ignore = 0, volume_ignore = 0;
- unsigned long voice_bit;
+ u_char status;
+
+ status = gus_look8(0x41); /* Get DMA IRQ Status */
+ if (status & 0x40) /* DMA interrupt pending */
+ switch (active_device) {
+ case GUS_DEV_WAVE:
+ if ((dram_sleep_flag.mode & WK_SLEEP)) {
+ dram_sleep_flag.mode = WK_WAKEUP;
+ wakeup(dram_sleeper);
+ };
+ break;
- unsigned char src, voice;
+ case GUS_DEV_PCM_CONTINUE: /* Left channel data transferred */
+ gus_transfer_output_block(pcm_current_dev, pcm_current_buf,
+ pcm_current_count, pcm_current_intrflag, 1);
+ break;
- while (1)
- {
- src = gus_read8 (0x0f); /*
- * Get source info
- */
- voice = src & 0x1f;
- src &= 0xc0;
-
- if (src == (0x80 | 0x40))
- return; /*
- * No interrupt
- */
-
- voice_bit = 1 << voice;
-
- if (!(src & 0x80)) /*
- * Wave IRQ pending
- */
- if (!(wave_ignore & voice_bit) && (int) voice < nr_voices) /*
- * Not done
- * yet
- */
- {
- wave_ignore |= voice_bit;
- do_loop_irq (voice);
- }
-
- if (!(src & 0x40)) /*
- * Volume IRQ pending
- */
- if (!(volume_ignore & voice_bit) && (int) voice < nr_voices) /*
- * Not done
- * yet
- */
- {
- volume_ignore |= voice_bit;
- do_volume_irq (voice);
- }
- }
+ case GUS_DEV_PCM_DONE: /* Right or mono channel data transferred */
+ if (pcm_qlen < pcm_nblk) {
+ int flag = (1 - dma_active) * 2; /* 0 or 2 */
+
+ if (pcm_qlen == 0)
+ flag = 1; /* Underrun */
+ dma_active = 0;
+ DMAbuf_outputintr(gus_devnum, flag);
+ }
+ break;
+
+ default:;
+ }
+
+ status = gus_look8(0x49); /* Get Sampling IRQ Status */
+ if (status & 0x40) { /* Sampling Irq pending */
+ DMAbuf_inputintr(gus_devnum);
+ }
}
+#ifdef CONFIG_SEQUENCER
+/*
+ * Timer stuff
+ */
+
+static volatile int select_addr, data_addr;
+static volatile int curr_timer = 0;
+
void
-guswave_dma_irq (void)
+gus_timer_command(u_int addr, u_int val)
{
- unsigned char status;
+ int i;
- status = gus_look8 (0x41); /* Get DMA IRQ Status */
- if (status & 0x40) /* DMA interrupt pending */
- switch (active_device)
- {
- case GUS_DEV_WAVE:
- if (SOMEONE_WAITING (dram_sleeper, dram_sleep_flag))
- WAKE_UP (dram_sleeper, dram_sleep_flag);
- break;
+ outb(select_addr, (u_char) (addr & 0xff));
- case GUS_DEV_PCM_CONTINUE: /* Left channel data transferred */
- gus_transfer_output_block (pcm_current_dev, pcm_current_buf,
- pcm_current_count,
- pcm_current_intrflag, 1);
- break;
+ for (i = 0; i < 2; i++)
+ inb(select_addr);
- case GUS_DEV_PCM_DONE: /* Right or mono channel data transferred */
- if (pcm_qlen < pcm_nblk)
- {
- int flag = (1 - dma_active) * 2; /* 0 or 2 */
+ outb(data_addr, (u_char) (val & 0xff));
- if (pcm_qlen == 0)
- flag = 1; /* Underrun */
- dma_active = 0;
- DMAbuf_outputintr (gus_devnum, flag);
- }
- break;
+ for (i = 0; i < 2; i++)
+ inb(select_addr);
+}
+
+static void
+arm_timer(int timer, u_int interval)
+{
+ curr_timer = timer;
+
+ if (timer == 1) {
+ gus_write8(0x46, 256 - interval); /* Set counter for timer 1 */
+ gus_write8(0x45, 0x04); /* Enable timer 1 IRQ */
+ gus_timer_command(0x04, 0x01); /* Start timer 1 */
+ } else {
+ gus_write8(0x47, 256 - interval); /* Set counter for timer 2 */
+ gus_write8(0x45, 0x08); /* Enable timer 2 IRQ */
+ gus_timer_command(0x04, 0x02); /* Start timer 2 */
+ }
- default:;
- }
+ gus_timer_enabled = 0;
+}
- status = gus_look8 (0x49); /*
- * Get Sampling IRQ Status
- */
- if (status & 0x40) /*
- * Sampling Irq pending
- */
- {
- DMAbuf_inputintr (gus_devnum);
+static u_int
+gus_tmr_start(int dev, u_int usecs_per_tick)
+{
+ int timer_no, resolution;
+ int divisor;
+
+ if (usecs_per_tick > (256 * 80)) {
+ timer_no = 2;
+ resolution = 320; /* usec */
+ } else {
+ timer_no = 1;
+ resolution = 80;/* usec */
}
+ divisor = (usecs_per_tick + (resolution / 2)) / resolution;
+
+ arm_timer(timer_no, divisor);
+
+ return divisor * resolution;
+}
+
+static void
+gus_tmr_disable(int dev)
+{
+ gus_write8(0x45, 0); /* Disable both timers */
+ gus_timer_enabled = 0;
}
+static void
+gus_tmr_restart(int dev)
+{
+ if (curr_timer == 1)
+ gus_write8(0x45, 0x04); /* Start timer 1 again */
+ else
+ gus_write8(0x45, 0x08); /* Start timer 2 again */
+}
+
+static struct sound_lowlev_timer gus_tmr =
+{
+ 0,
+ gus_tmr_start,
+ gus_tmr_disable,
+ gus_tmr_restart
+};
+
+static void
+gus_tmr_install(int io_base)
+{
+ select_addr = io_base;
+ data_addr = io_base + 1;
+
+ sound_timer_init(&gus_tmr, "GUS");
+}
+#endif
#endif
diff --git a/sys/i386/isa/sound/hex2hex.h b/sys/i386/isa/sound/hex2hex.h
index ecd7b4c4239c..5c909174780d 100644
--- a/sys/i386/isa/sound/hex2hex.h
+++ b/sys/i386/isa/sound/hex2hex.h
@@ -81,7 +81,7 @@ int hex2hex(char *source, char *target, char *varline)
}
fprintf(outf, "/*\n *\t Computer generated file. Do not edit.\n */\n");
- fprintf(outf, "%s[] = {\n", varline);
+ fprintf(outf, "static unsigned char %s[] = {\n", varline);
for (i=0;i<l;i++)
{
diff --git a/sys/i386/isa/sound/ics2101.c b/sys/i386/isa/sound/ics2101.c
index 4147a070fd8e..4df8bdef006f 100644
--- a/sys/i386/isa/sound/ics2101.c
+++ b/sys/i386/isa/sound/ics2101.c
@@ -1,10 +1,10 @@
/*
* 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
@@ -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,240 +24,210 @@
* 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 <i386/isa/sound/sound_config.h>
-#include "ultrasound.h"
-#include "gus_hw.h"
+#if defined(CONFIG_GUS)
+
+#include <i386/isa/sound/ultrasound.h>
+#include <i386/isa/sound/gus_hw.h>
#define MIX_DEVS (SOUND_MASK_MIC|SOUND_MASK_LINE| \
SOUND_MASK_SYNTH| \
SOUND_MASK_CD | SOUND_MASK_VOLUME)
+extern sound_os_info *gus_osp;
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 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)
+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--;
+ /*
+ * Experimental volume scaling by Risto Kankkunen. This should give
+ * smoother volume response than just a plain multiplication.
+ */
+ int e;
+
+ RANGE(vol, 0, 100);
+ vol = (31 * vol + 50) / 100;
+ e = 0;
+ if (vol) {
+ while (vol < 16) {
+ vol <<= 1;
+ e--;
}
- vol -= 16;
- e += 7;
+ vol -= 16;
+ e += 7;
}
- return ((e << 4) + vol);
-#else
- return ((vol * 127) + 50) / 100;
-#endif
+ return ((e << 4) + vol);
}
static void
-write_mix (int dev, int chn, int vol)
+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;
+ 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);
+ flags = splhigh();
+ outb(u_MixSelect, ctrl_addr);
+ outb(u_MixData, selector[dev]);
+ outb(u_MixSelect, attn_addr);
+ outb(u_MixData, (unsigned char) vol);
+ splx(flags);
}
static int
-set_volumes (int dev, int vol)
+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;
+ int left = vol & 0x00ff;
+ int right = (vol >> 8) & 0x00ff;
+
+ RANGE (left, 0, 100);
+ RANGE (right, 0, 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)
+ics2101_mixer_ioctl(int dev, unsigned int cmd, ioctl_arg 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);
- }
+ 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 *(int *) arg = set_volumes(DEV_MIC, (*(int *) arg));
+ break;
+
+ case SOUND_MIXER_CD:
+ return *(int *) arg = set_volumes(DEV_CD, (*(int *) arg));
+ break;
+
+ case SOUND_MIXER_LINE:
+ return *(int *) arg = set_volumes(DEV_LINE, (*(int *) arg));
+ break;
+
+ case SOUND_MIXER_SYNTH:
+ return *(int *) arg = set_volumes(DEV_GF1, (*(int *) arg));
+ break;
+
+ case SOUND_MIXER_VOLUME:
+ return *(int *) arg = set_volumes(DEV_VOL, (*(int *) arg));
+ break;
+
+ default:
+ return -(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 *(int *) arg = MIX_DEVS;
+ break;
+
+ case SOUND_MIXER_STEREODEVS:
+ return *(int *) arg = SOUND_MASK_LINE | SOUND_MASK_CD |
+ SOUND_MASK_SYNTH | SOUND_MASK_VOLUME | SOUND_MASK_MIC;
+ break;
+
+ case SOUND_MIXER_RECMASK:
+ return *(int *) arg = SOUND_MASK_MIC | SOUND_MASK_LINE;
+ break;
+
+ case SOUND_MIXER_CAPS:
+ return *(int *) arg = 0;
+ break;
+
+ case SOUND_MIXER_MIC:
+ return *(int *) arg = volumes[DEV_MIC];
+ break;
+
+ case SOUND_MIXER_LINE:
+ return *(int *) arg = volumes[DEV_LINE];
+ break;
+
+ case SOUND_MIXER_CD:
+ return *(int *) arg = volumes[DEV_CD];
+ break;
+
+ case SOUND_MIXER_VOLUME:
+ return *(int *) arg = volumes[DEV_VOL];
+ break;
+
+ case SOUND_MIXER_SYNTH:
+ return *(int *) arg = volumes[DEV_GF1];
+ break;
+
+ default:
+ return -(EINVAL);
+ }
}
-
- return RET_ERROR (EINVAL);
+ return -(EINVAL);
}
static struct mixer_operations ics2101_mixer_operations =
{
- ics2101_mixer_ioctl
+ "ICS2101 Multimedia Mixer",
+ ics2101_mixer_ioctl
};
-long
-ics2101_mixer_init (long mem_start)
+void
+ics2101_mixer_init()
{
- int i;
+ int i;
- if (num_mixers < MAX_MIXER_DEV)
- {
- mixer_devs[num_mixers++] = &ics2101_mixer_operations;
+ 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.
- */
+ /*
+ * 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;
+ 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);
+ 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/sys/i386/isa/sound/local.h b/sys/i386/isa/sound/local.h
index 533d60a22662..e42e79059f16 100644
--- a/sys/i386/isa/sound/local.h
+++ b/sys/i386/isa/sound/local.h
@@ -1,27 +1,174 @@
-/* Generated by configure. Don't edit!!!! */
-
-#define KERNEL_SOUNDCARD
-#undef EXCLUDE_PAS
-#undef EXCLUDE_SB
-#undef EXCLUDE_ADLIB
-#undef EXCLUDE_GUS
-#define EXCLUDE_MPU401
-#define EXCLUDE_UART6850
-#define EXCLUDE_PSS
-#undef EXCLUDE_GUS16
-#undef EXCLUDE_GUSMAX
-#undef EXCLUDE_MSS
-#undef EXCLUDE_SBPRO
-#undef EXCLUDE_SB16
-#undef EXCLUDE_AUDIO
-#undef EXCLUDE_MIDI
-#undef EXCLUDE_YM3812
-#undef EXCLUDE_SEQUENCER
-
-#define DSP_BUFFSIZE 32768
-#define SELECTED_SOUND_OPTIONS 0xffffff8f
-#define SOUND_VERSION_STRING "2.90-2"
-#define SOUND_CONFIG_DATE "Thu Sep 29 15:33:39 PDT 1994"
-#define SOUND_CONFIG_BY "swallace"
-#define SOUND_CONFIG_HOST "pal-r32-a07b.slip.nts.uci.edu"
-#define SOUND_CONFIG_DOMAIN ""
+/*
+ * local.h
+ *
+ * This file was generated by configure. But then HAND-EDITED. It will
+ * probably disappear in future revisions once the configuration process
+ * will become more like that of standard bsd code.
+ * lr 970714
+ *
+ */
+
+/* build hex2hex /tmp/foo.x trix_boot.h trix_boot */
+
+/*
+ * make everything conditioned on NSND>0 so as to detect errors
+ * because of missing "controller snd0" statement
+ */
+#define ALLOW_BUFFER_MAPPING 1
+
+#include "snd.h"
+#if NSND > 0
+#define CONFIGURE_SOUNDCARD
+
+#define CONFIG_SEQUENCER
+
+#include "gus.h"
+#if NGUS != 0 && !defined(CONFIG_GUS)
+#define CONFIG_GUS
+#define CONFIG_GUSMAX
+#endif
+
+#include "sscape.h"
+#if NSSCAPE != 0 && !defined(CONFIG_SSCAPE)
+#define CONFIG_SSCAPE
+#endif
+
+#include "trix.h"
+#if NTRIX > 0
+#define INCLUDE_TRIX_BOOT
+#define CONFIG_TRIX /* can use NTRIX > 0 instead */
+#define CONFIG_YM3812
+#endif
+
+#if defined(CONFIG_GUSMAX) || ( NSSCAPE > 0 ) || ( NTRIX > 0 )
+#define CONFIG_AD1848
+#endif
+
+#if defined(CONFIG_SEQUENCER) && (NTRIX == 0)
+#define CONFIG_MIDI
+#endif
+
+#include "sb.h"
+#if NSB > 0
+#define CONFIG_SB
+#endif
+
+#include "mss.h"
+#if NMSS != 0
+#define CONFIG_AD1848
+#define CONFIG_MSS
+#undef CONFIG_CS4232
+#endif
+
+#include "sbxvi.h"
+#if NSBXVI != 0 && !defined(CONFIG_SB16)
+#define CONFIG_SB16
+#define CONFIG_SBPRO /* FIXME: Also needs to be a sep option */
+#endif
+
+#include "sbmidi.h"
+#if NSBMIDI != 0 && !defined(CONFIG_SB16MIDI)
+#define CONFIG_SB16MIDI
+#endif
+
+#include "awe.h"
+#if NAWE != 0 && !defined(CONFIG_AWE32)
+#define CONFIG_AWE32
+#endif
+
+#include "pas.h"
+#if NPAS != 0 && !defined(CONFIG_PAS)
+#define CONFIG_PAS
+#endif
+
+#include "mpu.h"
+#if NMPU != 0 && !defined(CONFIG_MPU401)
+#define CONFIG_MPU401
+#endif
+
+#include "opl.h"
+#if NOPL != 0 && !defined(CONFIG_YM3812)
+#define CONFIG_YM3812
+#endif
+
+#define ALLOW_POLL
+
+/* #undef CONFIG_PAS */
+/* #undef CONFIG_ADLIB */
+/* #define CONFIG_GUS */
+/* #undef CONFIG_MPU401 */
+#undef CONFIG_UART6850
+#undef CONFIG_PSS
+#undef CONFIG_GUS16
+/* #undef CONFIG_MSS */
+/* #undef CONFIG_SSCAPE */
+#undef CONFIG_MAD16
+/* #undef CONFIG_CS4232 */
+#undef CONFIG_MAUI
+#undef CONFIG_PNP
+/* #undef CONFIG_SBPRO */
+/* #undef CONFIG_SB16 */
+#undef CONFIG_AEDSP16
+#define CONFIG_AUDIO /* obvious ? */
+
+#define CONFIG_MPU_EMU
+
+#define DSP_BUFFSIZE 32768*2
+/* #define SELECTED_SOUND_OPTIONS 0x0188090a */
+
+#ifndef TRIX_SB_BASE
+#define TRIX_SB_BASE 0x220
+#endif
+
+#ifndef TRIX_SB_IRQ
+#define TRIX_SB_IRQ 7
+#endif
+
+#ifndef TRIX_SB_DMA
+#define TRIX_SB_DMA 1
+#endif
+
+#ifndef TRIX_BASE
+#define TRIX_BASE 0x530
+#endif
+
+#ifndef TRIX_IRQ
+#define TRIX_IRQ 9
+#endif
+
+#ifndef TRIX_DMA
+#define TRIX_DMA 3
+#endif
+
+#ifndef TRIX_DMA2
+#define TRIX_DMA2 1
+#endif
+
+#ifndef GUS_BASE
+#define GUS_BASE 0x220
+#endif
+
+#ifndef GUS_IRQ
+#define GUS_IRQ 12
+#endif
+
+#ifndef GUS_MIDI_IRQ
+#define GUS_MIDI_IRQ GUS_IRQ
+#endif
+
+#ifndef GUS_DMA
+#define GUS_DMA 4
+#endif
+
+#ifndef GUS_DMA2
+#define GUS_DMA2 4
+#endif
+
+#define SOUND_CONFIG_DATE "Wed Aug 6 22:58:35 PDT 1997"
+#define SOUND_CONFIG_BY "Amancio Hasty"
+#define SOUND_CONFIG_HOST "rah"
+#define SOUND_CONFIG_DOMAIN "star-gate.com"
+
+#else /* NSND = 0 */
+#undef CONFIGURE_SOUNDCARD
+#endif
diff --git a/sys/i386/isa/sound/midi_ctrl.h b/sys/i386/isa/sound/midi_ctrl.h
index 616b5914c6e2..8b68c7d91db3 100644
--- a/sys/i386/isa/sound/midi_ctrl.h
+++ b/sys/i386/isa/sound/midi_ctrl.h
@@ -1,9 +1,9 @@
static unsigned char ctrl_def_values[128] =
{
- 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, /* 0 to 7 */
- 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, /* 8 to 15 */
- 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, /* 16 to 23 */
- 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, /* 24 to 31 */
+ 0x40,0x40,0x40,0x40, 0x40,0x40,0x40,0x40, /* 0 to 7 */
+ 0x40,0x40,0x40,0x40, 0x40,0x40,0x40,0x40, /* 8 to 15 */
+ 0x40,0x40,0x40,0x40, 0x40,0x40,0x40,0x40, /* 16 to 23 */
+ 0x40,0x40,0x40,0x40, 0x40,0x40,0x40,0x40, /* 24 to 31 */
0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, /* 32 to 39 */
0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, /* 40 to 47 */
diff --git a/sys/i386/isa/sound/midi_synth.c b/sys/i386/isa/sound/midi_synth.c
index fd6d8bde62cd..86032e3db16d 100644
--- a/sys/i386/isa/sound/midi_synth.c
+++ b/sys/i386/isa/sound/midi_synth.c
@@ -1,10 +1,10 @@
/*
* sound/midi_synth.c
- *
+ *
* High level midi sequencer manager for dumb MIDI interfaces.
- *
+ *
* 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,451 +24,650 @@
* 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"
+#define USE_SEQ_MACROS
+#define USE_SIMPLE_MACROS
-#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_MIDI)
+#include <i386/isa/sound/sound_config.h>
+
+#if defined(CONFIGURE_SOUNDCARD) /* && defined(CONFIG_MIDI) */
#define _MIDI_SYNTH_C_
-DEFINE_WAIT_QUEUE (sysex_sleeper, sysex_sleep_flag);
+static int *sysex_sleeper = NULL;
+static volatile struct snd_wait sysex_sleep_flag = {0};
-#include "midi_synth.h"
+#include <i386/isa/sound/midi_synth.h>
static int midi2synth[MAX_MIDI_DEV];
+static int sysex_state[MAX_MIDI_DEV] =
+{0};
static unsigned char prev_out_status[MAX_MIDI_DEV];
+#ifndef CONFIG_SEQUENCER
+#define STORE(cmd)
+#else
+#define STORE(cmd) { \
+ int len; \
+ unsigned char obuf[8]; \
+ cmd; \
+ seq_input_event(obuf, len); \
+}
+#endif
+
+#define _seqbuf obuf
+#define _seqbufptr 0
+#define _SEQ_ADVBUF(x) len=x
+
+void
+do_midi_msg(int synthno, unsigned char *msg, int mlen)
+{
+ switch (msg[0] & 0xf0) {
+ case 0x90:
+ if (msg[2] != 0) {
+ STORE(SEQ_START_NOTE(synthno, msg[0] & 0x0f, msg[1], msg[2]));
+ break;
+ }
+ msg[2] = 64;
+
+ case 0x80:
+ STORE(SEQ_STOP_NOTE(synthno, msg[0] & 0x0f, msg[1], msg[2]));
+ break;
+
+ case 0xA0:
+ STORE(SEQ_KEY_PRESSURE(synthno, msg[0] & 0x0f, msg[1], msg[2]));
+ break;
+
+ case 0xB0:
+ STORE(SEQ_CONTROL(synthno, msg[0] & 0x0f, msg[1], msg[2]));
+ break;
+
+ case 0xC0:
+ STORE(SEQ_SET_PATCH(synthno, msg[0] & 0x0f, msg[1]));
+ break;
+
+ case 0xD0:
+ STORE(SEQ_CHN_PRESSURE(synthno, msg[0] & 0x0f, msg[1]));
+ break;
+
+ case 0xE0:
+ STORE(SEQ_BENDER(synthno, msg[0] & 0x0f,
+ (msg[1] % 0x7f) | ((msg[2] & 0x7f) << 7)));
+ break;
+
+ default:
+ /*
+ * printf ("MPU: Unknown midi channel message %02x\n",
+ * msg[0]);
+ */
+ ;
+ }
+}
+
static void
-midi_outc (int midi_dev, int data)
+midi_outc(int midi_dev, int data)
{
- int timeout;
-
- for (timeout = 0; timeout < 32000; timeout++)
- if (midi_devs[midi_dev]->putc (midi_dev, (unsigned char) (data & 0xff)))
- {
- if (data & 0x80) /*
- * Status byte
- */
- prev_out_status[midi_dev] =
- (unsigned char) (data & 0xff); /*
- * Store for running status
- */
- return; /*
- * Mission complete
- */
- }
-
- /*
- * Sorry! No space on buffers.
- */
- printk ("Midi send timed out\n");
+ int timeout;
+
+ for (timeout = 0; timeout < 32000; timeout++)
+ if (midi_devs[midi_dev]->putc(midi_dev, (unsigned char) (data & 0xff))) {
+ if (data & 0x80) /* Status byte */
+ prev_out_status[midi_dev] =
+ (unsigned char) (data & 0xff); /* Store for running
+ * status */
+ return; /* Mission complete */
+ }
+ /*
+ * Sorry! No space on buffers.
+ */
+ printf("Midi send timed out\n");
}
static int
-prefix_cmd (int midi_dev, unsigned char status)
+prefix_cmd(int midi_dev, unsigned char status)
{
- if (midi_devs[midi_dev]->prefix_cmd == NULL)
- return 1;
+ if ((char *) midi_devs[midi_dev]->prefix_cmd == NULL)
+ return 1;
- return midi_devs[midi_dev]->prefix_cmd (midi_dev, status);
+ return midi_devs[midi_dev]->prefix_cmd(midi_dev, status);
}
static void
-midi_synth_input (int dev, unsigned char data)
+midi_synth_input(int orig_dev, unsigned char data)
{
- int orig_dev;
+ int dev;
+ struct midi_input_info *inc;
- if (dev < 0 || dev > num_synths)
- return;
+ static unsigned char len_tab[] = /* # of data bytes following a status */
+ {
+ 2, /* 8x */
+ 2, /* 9x */
+ 2, /* Ax */
+ 2, /* Bx */
+ 1, /* Cx */
+ 1, /* Dx */
+ 2, /* Ex */
+ 0 /* Fx */
+ };
+
+ if (orig_dev < 0 || orig_dev > num_midis)
+ return;
- if (data == 0xfe) /* Ignore active sensing */
- return;
+ if (data == 0xfe) /* Ignore active sensing */
+ return;
- orig_dev = midi2synth[dev];
+ dev = midi2synth[orig_dev];
+ inc = &midi_devs[orig_dev]->in_info;
+
+ switch (inc->m_state) {
+ case MST_INIT:
+ if (data & 0x80) { /* MIDI status byte */
+ if ((data & 0xf0) == 0xf0) { /* Common message */
+ switch (data) {
+ case 0xf0: /* Sysex */
+ inc->m_state = MST_SYSEX;
+ break; /* Sysex */
+
+ case 0xf1: /* MTC quarter frame */
+ case 0xf3: /* Song select */
+ inc->m_state = MST_DATA;
+ inc->m_ptr = 1;
+ inc->m_left = 1;
+ inc->m_buf[0] = data;
+ break;
+
+ case 0xf2: /* Song position pointer */
+ inc->m_state = MST_DATA;
+ inc->m_ptr = 1;
+ inc->m_left = 2;
+ inc->m_buf[0] = data;
+ break;
+
+ default:
+ inc->m_buf[0] = data;
+ inc->m_ptr = 1;
+ do_midi_msg(dev, inc->m_buf, inc->m_ptr);
+ inc->m_ptr = 0;
+ inc->m_left = 0;
+ }
+ } else {
+ inc->m_state = MST_DATA;
+ inc->m_ptr = 1;
+ inc->m_left = len_tab[(data >> 4) - 8];
+ inc->m_buf[0] = inc->m_prev_status = data;
+ }
+ } else if (inc->m_prev_status & 0x80) { /* Ignore if no previous
+ * status (yet) *//* Data byte (use running status) */
+ inc->m_state = MST_DATA;
+ inc->m_ptr = 2;
+ inc->m_left = len_tab[(data >> 4) - 8] - 1;
+ inc->m_buf[0] = inc->m_prev_status;
+ inc->m_buf[1] = data;
+ }
+ break; /* MST_INIT */
+
+ case MST_DATA:
+ inc->m_buf[inc->m_ptr++] = data;
+ if (--inc->m_left <= 0) {
+ inc->m_state = MST_INIT;
+ do_midi_msg(dev, inc->m_buf, inc->m_ptr);
+ inc->m_ptr = 0;
+ }
+ break; /* MST_DATA */
+
+ case MST_SYSEX:
+ if (data == 0xf7) { /* Sysex end */
+ inc->m_state = MST_INIT;
+ inc->m_left = 0;
+ inc->m_ptr = 0;
+ }
+ break; /* MST_SYSEX */
+ default:
+ printf("MIDI%d: Unexpected state %d (%02x)\n", orig_dev, inc->m_state,
+ (int) data);
+ inc->m_state = MST_INIT;
+ }
}
static void
-midi_synth_output (int dev)
+leave_sysex(int dev)
{
- /*
- * Currently NOP
- */
+ int orig_dev = synth_devs[dev]->midi_dev;
+ int timeout = 0;
+
+ if (!sysex_state[dev])
+ return;
+
+ sysex_state[dev] = 0;
+
+ while (!midi_devs[orig_dev]->putc(orig_dev, 0xf7) && timeout < 1000)
+ timeout++;
+
+ sysex_state[dev] = 0;
+}
+
+static void
+midi_synth_output(int dev)
+{
+ /*
+ * Currently NOP
+ */
}
int
-midi_synth_ioctl (int dev,
- unsigned int cmd, unsigned int arg)
+midi_synth_ioctl(int dev, unsigned int cmd, ioctl_arg arg)
{
- /*
- * int orig_dev = synth_devs[dev]->midi_dev;
- */
+ /*
+ * int orig_dev = synth_devs[dev]->midi_dev;
+ */
- switch (cmd)
- {
+ switch (cmd) {
case SNDCTL_SYNTH_INFO:
- IOCTL_TO_USER ((char *) arg, 0, synth_devs[dev]->info,
- sizeof (struct synth_info));
-
- return 0;
- break;
+ bcopy(synth_devs[dev]->info, &(((char *) arg)[0]), sizeof(struct synth_info));
+ return 0;
+ break;
case SNDCTL_SYNTH_MEMAVL:
- return 0x7fffffff;
- break;
+ return 0x7fffffff;
+ break;
default:
- return RET_ERROR (EINVAL);
+ return -(EINVAL);
}
}
int
-midi_synth_kill_note (int dev, int channel, int note, int velocity)
+midi_synth_kill_note(int dev, int channel, int note, int velocity)
{
- int orig_dev = synth_devs[dev]->midi_dev;
- int msg, chn;
+ int orig_dev = synth_devs[dev]->midi_dev;
+ int msg, chn;
- if (note < 0 || note > 127)
- return 0;
- if (channel < 0 || channel > 15)
- return 0;
- if (velocity < 0)
- velocity = 0;
- if (velocity > 127)
- velocity = 127;
-
- msg = prev_out_status[orig_dev] & 0xf0;
- chn = prev_out_status[orig_dev] & 0x0f;
-
- if (chn == channel && ((msg == 0x90 && velocity == 64) || msg == 0x80))
- { /*
- * Use running status
- */
- if (!prefix_cmd (orig_dev, note))
+ if (note < 0 || note > 127)
+ return 0;
+ if (channel < 0 || channel > 15)
return 0;
+ RANGE (velocity, 0, 127 ) ;
+ leave_sysex(dev);
- midi_outc (orig_dev, note);
-
- if (msg == 0x90) /*
- * Running status = Note on
- */
- midi_outc (orig_dev, 0);/*
- * Note on with velocity 0 == note
- * off
- */
- else
- midi_outc (orig_dev, velocity);
- }
- else
- {
- if (velocity == 64)
- {
- if (!prefix_cmd (orig_dev, 0x90 | (channel & 0x0f)))
- return 0;
- midi_outc (orig_dev, 0x90 | (channel & 0x0f)); /*
- * Note on
- */
- midi_outc (orig_dev, note);
- midi_outc (orig_dev, 0); /*
- * Zero G
- */
- }
- else
- {
- if (!prefix_cmd (orig_dev, 0x80 | (channel & 0x0f)))
+ msg = prev_out_status[orig_dev] & 0xf0;
+ chn = prev_out_status[orig_dev] & 0x0f;
+
+ if (chn == channel && ((msg == 0x90 && velocity == 64) || msg == 0x80)) { /* Use running status */
+ if (!prefix_cmd(orig_dev, note))
return 0;
- midi_outc (orig_dev, 0x80 | (channel & 0x0f)); /*
- * Note off
- */
- midi_outc (orig_dev, note);
- midi_outc (orig_dev, velocity);
+
+ midi_outc(orig_dev, note);
+
+ if (msg == 0x90)/* Running status = Note on */
+ midi_outc(orig_dev, 0); /* Note on with velocity 0 == note off */
+ else
+ midi_outc(orig_dev, velocity);
+ } else {
+ if (velocity == 64) {
+ if (!prefix_cmd(orig_dev, 0x90 | (channel & 0x0f)))
+ return 0;
+ midi_outc(orig_dev, 0x90 | (channel & 0x0f)); /* Note on */
+ midi_outc(orig_dev, note);
+ midi_outc(orig_dev, 0); /* Zero G */
+ } else {
+ if (!prefix_cmd(orig_dev, 0x80 | (channel & 0x0f)))
+ return 0;
+ midi_outc(orig_dev, 0x80 | (channel & 0x0f)); /* Note off */
+ midi_outc(orig_dev, note);
+ midi_outc(orig_dev, velocity);
}
}
- return 0;
+ return 0;
}
int
-midi_synth_set_instr (int dev, int channel, int instr_no)
+midi_synth_set_instr(int dev, int channel, int instr_no)
{
- int orig_dev = synth_devs[dev]->midi_dev;
+ int orig_dev = synth_devs[dev]->midi_dev;
- if (instr_no < 0 || instr_no > 127)
- return 0;
- if (channel < 0 || channel > 15)
- return 0;
+ if (instr_no < 0 || instr_no > 127)
+ return 0;
+ if (channel < 0 || channel > 15)
+ return 0;
- if (!prefix_cmd (orig_dev, 0xc0 | (channel & 0x0f)))
- return 0;
- midi_outc (orig_dev, 0xc0 | (channel & 0x0f)); /*
- * Program change
- */
- midi_outc (orig_dev, instr_no);
+ leave_sysex(dev);
- return 0;
+ if (!prefix_cmd(orig_dev, 0xc0 | (channel & 0x0f)))
+ return 0;
+ midi_outc(orig_dev, 0xc0 | (channel & 0x0f)); /* Program change */
+ midi_outc(orig_dev, instr_no);
+
+ return 0;
}
int
-midi_synth_start_note (int dev, int channel, int note, int velocity)
+midi_synth_start_note(int dev, int channel, int note, int velocity)
{
- int orig_dev = synth_devs[dev]->midi_dev;
- int msg, chn;
+ int orig_dev = synth_devs[dev]->midi_dev;
+ int msg, chn;
- if (note < 0 || note > 127)
- return 0;
- if (channel < 0 || channel > 15)
- return 0;
- if (velocity < 0)
- velocity = 0;
- if (velocity > 127)
- velocity = 127;
-
- msg = prev_out_status[orig_dev] & 0xf0;
- chn = prev_out_status[orig_dev] & 0x0f;
-
- if (chn == channel && msg == 0x90)
- { /*
- * Use running status
- */
- if (!prefix_cmd (orig_dev, note))
+ if (note < 0 || note > 127)
return 0;
- midi_outc (orig_dev, note);
- midi_outc (orig_dev, velocity);
- }
- else
- {
- if (!prefix_cmd (orig_dev, 0x90 | (channel & 0x0f)))
+ if (channel < 0 || channel > 15)
return 0;
- midi_outc (orig_dev, 0x90 | (channel & 0x0f)); /*
- * Note on
- */
- midi_outc (orig_dev, note);
- midi_outc (orig_dev, velocity);
+ RANGE (velocity, 0, 127 );
+ leave_sysex(dev);
+
+ msg = prev_out_status[orig_dev] & 0xf0;
+ chn = prev_out_status[orig_dev] & 0x0f;
+
+ if (chn == channel && msg == 0x90) { /* Use running status */
+ if (!prefix_cmd(orig_dev, note))
+ return 0;
+ midi_outc(orig_dev, note);
+ midi_outc(orig_dev, velocity);
+ } else {
+ if (!prefix_cmd(orig_dev, 0x90 | (channel & 0x0f)))
+ return 0;
+ midi_outc(orig_dev, 0x90 | (channel & 0x0f)); /* Note on */
+ midi_outc(orig_dev, note);
+ midi_outc(orig_dev, velocity);
}
- return 0;
+ return 0;
}
void
-midi_synth_reset (int dev)
+midi_synth_reset(int dev)
{
+
+ leave_sysex(dev);
}
int
-midi_synth_open (int dev, int mode)
+midi_synth_open(int dev, int mode)
{
- int orig_dev = synth_devs[dev]->midi_dev;
- int err;
+ int orig_dev = synth_devs[dev]->midi_dev;
+ int err;
+ unsigned long flags;
+ struct midi_input_info *inc;
+
+ if (orig_dev < 0 || orig_dev > num_midis)
+ return -(ENXIO);
+
+ midi2synth[orig_dev] = dev;
+ sysex_state[dev] = 0;
+ prev_out_status[orig_dev] = 0;
+
+ if ((err = midi_devs[orig_dev]->open(orig_dev, mode,
+ midi_synth_input, midi_synth_output)) < 0)
+ return err;
- if (orig_dev < 0 || orig_dev > num_midis)
- return RET_ERROR (ENXIO);
+ inc = &midi_devs[orig_dev]->in_info;
- midi2synth[orig_dev] = dev;
- prev_out_status[orig_dev] = 0;
+ flags = splhigh();
+ inc->m_busy = 0;
+ inc->m_state = MST_INIT;
+ inc->m_ptr = 0;
+ inc->m_left = 0;
+ inc->m_prev_status = 0x00;
+ splx(flags);
- if ((err = midi_devs[orig_dev]->open (orig_dev, mode,
- midi_synth_input, midi_synth_output)) < 0)
- return err;
+ sysex_sleep_flag.aborting = 0;
+ sysex_sleep_flag.mode = WK_NONE;
- return 1;
+ return 1;
}
void
-midi_synth_close (int dev)
+midi_synth_close(int dev)
{
- int orig_dev = synth_devs[dev]->midi_dev;
+ int orig_dev = synth_devs[dev]->midi_dev;
- /*
- * Shut up the synths by sending just single active sensing message.
- */
- midi_devs[orig_dev]->putc (orig_dev, 0xfe);
+ leave_sysex(dev);
- midi_devs[orig_dev]->close (orig_dev);
+ /*
+ * Shut up the synths by sending just single active sensing message.
+ */
+ midi_devs[orig_dev]->putc(orig_dev, 0xfe);
+
+ midi_devs[orig_dev]->close(orig_dev);
}
void
-midi_synth_hw_control (int dev, unsigned char *event)
+midi_synth_hw_control(int dev, unsigned char *event)
{
}
int
-midi_synth_load_patch (int dev, int format, snd_rw_buf * addr,
- int offs, int count, int pmgr_flag)
+midi_synth_load_patch(int dev, int format, snd_rw_buf * addr,
+ int offs, int count, int pmgr_flag)
{
- int orig_dev = synth_devs[dev]->midi_dev;
+ int orig_dev = synth_devs[dev]->midi_dev;
- struct sysex_info sysex;
- int i;
- unsigned long left, src_offs, eox_seen = 0;
- int first_byte = 1;
+ struct sysex_info sysex;
+ int i;
+ unsigned long left, src_offs, eox_seen = 0;
+ int first_byte = 1;
+ int hdr_size = (unsigned long) &sysex.data[0] - (unsigned long) &sysex;
- if (!prefix_cmd (orig_dev, 0xf0))
- return 0;
+ leave_sysex(dev);
- if (format != SYSEX_PATCH)
- {
- printk ("MIDI Error: Invalid patch format (key) 0x%x\n", format);
- return RET_ERROR (EINVAL);
- }
+ if (!prefix_cmd(orig_dev, 0xf0))
+ return 0;
- if (count < sizeof (struct sysex_info))
- {
- printk ("MIDI Error: Patch header too short\n");
- return RET_ERROR (EINVAL);
+ if (format != SYSEX_PATCH) {
+ printf("MIDI Error: Invalid patch format (key) 0x%x\n", format);
+ return -(EINVAL);
}
+ if (count < hdr_size) {
+ printf("MIDI Error: Patch header too short\n");
+ return -(EINVAL);
+ }
+ count -= hdr_size;
- count -= sizeof (struct sysex_info);
+ /*
+ * Copy the header from user space but ignore the first bytes which
+ * have been transferred already.
+ */
- /*
- * Copy the header from user space but ignore the first bytes which have
- * been transferred already.
- */
- COPY_FROM_USER (&((char *) &sysex)[offs], addr, offs, sizeof (struct sysex_info) - offs);
+ if (uiomove(&((char *) &sysex)[offs], hdr_size - offs, addr)) {
+ printf("sb: Bad copyin()!\n");
+ };
- if (count < sysex.len)
- {
- printk ("MIDI Warning: Sysex record too short (%d<%d)\n",
- count, (int) sysex.len);
- sysex.len = count;
+ if (count < sysex.len) {
+ printf("MIDI Warning: Sysex record too short (%d<%d)\n",
+ count, (int) sysex.len);
+ sysex.len = count;
}
+ left = sysex.len;
+ src_offs = 0;
- left = sysex.len;
- src_offs = 0;
+ sysex_sleep_flag.aborting = 0;
+ sysex_sleep_flag.mode = WK_NONE;
- RESET_WAIT_QUEUE (sysex_sleeper, sysex_sleep_flag);
-
- for (i = 0; i < left && !PROCESS_ABORTING (sysex_sleeper, sysex_sleep_flag); i++)
- {
- unsigned char data;
+ for (i = 0; i < left && !(sysex_sleep_flag.aborting); i++) {
+ unsigned char data;
- GET_BYTE_FROM_USER (data, addr, sizeof (struct sysex_info) + i);
+ uiomove((char *) &(data), 1, addr);
- if (first_byte && data != 0xf0)
- midi_outc (orig_dev, 0xf0); /* Sysex start */
+ eox_seen = (i > 0 && data & 0x80); /* End of sysex */
- eox_seen = (data == 0xf7);/*
- * Last byte was end of sysex
- */
+ if (eox_seen && data != 0xf7)
+ data = 0xf7;
- if (i == 0)
- {
- if (data != 0xf0) /*
- * Sysex start
- */
- return RET_ERROR (EINVAL);
+ if (i == 0) {
+ if (data != 0xf0) {
+ printf("Error: Sysex start missing\n");
+ return -(EINVAL);
+ }
}
+ while (!midi_devs[orig_dev]->putc(orig_dev,
+ (unsigned char) (data & 0xff)) &&
+ !(sysex_sleep_flag.aborting)) {
+ int chn;
- while (!midi_devs[orig_dev]->putc (orig_dev, (unsigned char) (data & 0xff)) &&
- !PROCESS_ABORTING (sysex_sleeper, sysex_sleep_flag))
- DO_SLEEP (sysex_sleeper, sysex_sleep_flag, 1); /* Wait for timeout */
- if (!first_byte && data & 0x80)
- return 0;
- first_byte = 0;
+ sysex_sleeper = &chn;
+ DO_SLEEP(chn, sysex_sleep_flag, 1);
+
+ }; /* Wait for timeout */
+
+ if (!first_byte && data & 0x80)
+ return 0;
+ first_byte = 0;
}
- if (!eox_seen)
- midi_outc (orig_dev, 0xf7);
- return 0;
+ if (!eox_seen)
+ midi_outc(orig_dev, 0xf7);
+ return 0;
}
void
-midi_synth_panning (int dev, int channel, int pressure)
+midi_synth_panning(int dev, int channel, int pressure)
{
}
void
-midi_synth_aftertouch (int dev, int channel, int pressure)
+midi_synth_aftertouch(int dev, int channel, int pressure)
{
- int orig_dev = synth_devs[dev]->midi_dev;
- int msg, chn;
+ int orig_dev = synth_devs[dev]->midi_dev;
+ int msg, chn;
- if (pressure < 0 || pressure > 127)
- return;
- if (channel < 0 || channel > 15)
- return;
+ if (pressure < 0 || pressure > 127)
+ return;
+ if (channel < 0 || channel > 15)
+ return;
- msg = prev_out_status[orig_dev] & 0xf0;
- chn = prev_out_status[orig_dev] & 0x0f;
+ leave_sysex(dev);
- if (msg != 0xd0 || chn != channel) /*
- * Test for running status
- */
- {
- if (!prefix_cmd (orig_dev, 0xd0 | (channel & 0x0f)))
+ msg = prev_out_status[orig_dev] & 0xf0;
+ chn = prev_out_status[orig_dev] & 0x0f;
+
+ if (msg != 0xd0 || chn != channel) { /* Test for running status */
+ if (!prefix_cmd(orig_dev, 0xd0 | (channel & 0x0f)))
+ return;
+ midi_outc(orig_dev, 0xd0 | (channel & 0x0f)); /* Channel pressure */
+ } else if (!prefix_cmd(orig_dev, pressure))
return;
- midi_outc (orig_dev, 0xd0 | (channel & 0x0f)); /*
- * Channel pressure
- */
- }
- else if (!prefix_cmd (orig_dev, pressure))
- return;
- midi_outc (orig_dev, pressure);
+
+ midi_outc(orig_dev, pressure);
}
void
-midi_synth_controller (int dev, int channel, int ctrl_num, int value)
+midi_synth_controller(int dev, int channel, int ctrl_num, int value)
{
- int orig_dev = synth_devs[dev]->midi_dev;
- int chn, msg;
+ int orig_dev = synth_devs[dev]->midi_dev;
+ int chn, msg;
- if (ctrl_num < 1 || ctrl_num > 127)
- return; /* NOTE! Controller # 0 ignored */
- if (channel < 0 || channel > 15)
- return;
+ if (ctrl_num < 1 || ctrl_num > 127)
+ return; /* NOTE! Controller # 0 ignored */
+ if (channel < 0 || channel > 15)
+ return;
- msg = prev_out_status[orig_dev] & 0xf0;
- chn = prev_out_status[orig_dev] & 0x0f;
+ leave_sysex(dev);
- if (msg != 0xb0 || chn != channel)
- {
- if (!prefix_cmd (orig_dev, 0xb0 | (channel & 0x0f)))
+ msg = prev_out_status[orig_dev] & 0xf0;
+ chn = prev_out_status[orig_dev] & 0x0f;
+
+ if (msg != 0xb0 || chn != channel) {
+ if (!prefix_cmd(orig_dev, 0xb0 | (channel & 0x0f)))
+ return;
+ midi_outc(orig_dev, 0xb0 | (channel & 0x0f));
+ } else if (!prefix_cmd(orig_dev, ctrl_num))
return;
- midi_outc (orig_dev, 0xb0 | (channel & 0x0f));
- }
- else if (!prefix_cmd (orig_dev, ctrl_num))
- return;
- midi_outc (orig_dev, ctrl_num);
- midi_outc (orig_dev, value & 0x7f);
+ midi_outc(orig_dev, ctrl_num);
+ midi_outc(orig_dev, value & 0x7f);
}
int
-midi_synth_patchmgr (int dev, struct patmgr_info *rec)
+midi_synth_patchmgr(int dev, struct patmgr_info * rec)
{
- return RET_ERROR (EINVAL);
+ return -(EINVAL);
}
void
-midi_synth_bender (int dev, int channel, int value)
+midi_synth_bender(int dev, int channel, int value)
{
- int orig_dev = synth_devs[dev]->midi_dev;
- int msg, prev_chn;
+ int orig_dev = synth_devs[dev]->midi_dev;
+ int msg, prev_chn;
- if (channel < 0 || channel > 15)
- return;
+ if (channel < 0 || channel > 15)
+ return;
+
+ if (value < 0 || value > 16383)
+ return;
- if (value < 0 || value > 16383)
- return;
+ leave_sysex(dev);
- msg = prev_out_status[orig_dev] & 0xf0;
- prev_chn = prev_out_status[orig_dev] & 0x0f;
+ msg = prev_out_status[orig_dev] & 0xf0;
+ prev_chn = prev_out_status[orig_dev] & 0x0f;
- if (msg != 0xd0 || prev_chn != channel) /*
- * * Test for running status */
- {
- if (!prefix_cmd (orig_dev, 0xe0 | (channel & 0x0f)))
+ if (msg != 0xd0 || prev_chn != channel) { /* Test for running status */
+ if (!prefix_cmd(orig_dev, 0xe0 | (channel & 0x0f)))
+ return;
+ midi_outc(orig_dev, 0xe0 | (channel & 0x0f));
+ } else if (!prefix_cmd(orig_dev, value & 0x7f))
return;
- midi_outc (orig_dev, 0xe0 | (channel & 0x0f));
- }
- else if (!prefix_cmd (orig_dev, value & 0x7f))
- return;
- midi_outc (orig_dev, value & 0x7f);
- midi_outc (orig_dev, (value >> 7) & 0x7f);
+ midi_outc(orig_dev, value & 0x7f);
+ midi_outc(orig_dev, (value >> 7) & 0x7f);
+}
+
+void
+midi_synth_setup_voice(int dev, int voice, int channel)
+{
}
+int
+midi_synth_send_sysex(int dev, unsigned char *bytes, int len)
+{
+ int orig_dev = synth_devs[dev]->midi_dev;
+ int i;
+
+ for (i = 0; i < len; i++) {
+ switch (bytes[i]) {
+ case 0xf0: /* Start sysex */
+ if (!prefix_cmd(orig_dev, 0xf0))
+ return 0;
+ sysex_state[dev] = 1;
+ break;
+
+ case 0xf7: /* End sysex */
+ if (!sysex_state[dev]) /* Orphan sysex end */
+ return 0;
+ sysex_state[dev] = 0;
+ break;
+
+ default:
+ if (!sysex_state[dev])
+ return 0;
+
+ if (bytes[i] & 0x80) { /* Error. Another message before sysex end */
+ bytes[i] = 0xf7; /* Sysex end */
+ sysex_state[dev] = 0;
+ }
+ }
+
+ if (!midi_devs[orig_dev]->putc(orig_dev, bytes[i])) {
+ /*
+ * Hardware leve buffer is full. Abort the sysex message.
+ */
+
+ int timeout = 0;
+
+ bytes[i] = 0xf7;
+ sysex_state[dev] = 0;
+
+ while (!midi_devs[orig_dev]->putc(orig_dev, bytes[i]) &&
+ timeout < 1000)
+ timeout++;
+ }
+ if (!sysex_state[dev])
+ return 0;
+ }
+
+ return 0;
+}
#endif
diff --git a/sys/i386/isa/sound/midi_synth.h b/sys/i386/isa/sound/midi_synth.h
index 04075e294ca6..80e627be4ce1 100644
--- a/sys/i386/isa/sound/midi_synth.h
+++ b/sys/i386/isa/sound/midi_synth.h
@@ -1,5 +1,5 @@
int midi_synth_ioctl (int dev,
- unsigned int cmd, unsigned int arg);
+ unsigned int cmd, ioctl_arg arg);
int midi_synth_kill_note (int dev, int channel, int note, int velocity);
int midi_synth_set_instr (int dev, int channel, int instr_no);
int midi_synth_start_note (int dev, int channel, int note, int volume);
@@ -14,7 +14,8 @@ void midi_synth_aftertouch (int dev, int channel, int pressure);
void midi_synth_controller (int dev, int channel, int ctrl_num, int value);
int midi_synth_patchmgr (int dev, struct patmgr_info *rec);
void midi_synth_bender (int dev, int chn, int value);
-
+void midi_synth_setup_voice (int dev, int voice, int chn);
+int midi_synth_send_sysex(int dev, unsigned char *bytes,int len);
#ifndef _MIDI_SYNTH_C_
static struct synth_info std_synth_info =
@@ -40,6 +41,9 @@ static struct synth_operations std_midi_synth =
midi_synth_panning,
NULL,
midi_synth_patchmgr,
- midi_synth_bender
+ midi_synth_bender,
+ NULL, /* alloc_voice */
+ midi_synth_setup_voice,
+ midi_synth_send_sysex
};
#endif
diff --git a/sys/i386/isa/sound/midibuf.c b/sys/i386/isa/sound/midibuf.c
index ae0ddc3ea54b..e452e0a35f21 100644
--- a/sys/i386/isa/sound/midibuf.c
+++ b/sys/i386/isa/sound/midibuf.c
@@ -1,10 +1,10 @@
/*
* sound/midibuf.c
- *
+ *
* Device file manager for /dev/midi#
- *
+ *
* 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,420 +24,406 @@
* 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"
+#include <i386/isa/sound/sound_config.h>
-#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_MIDI)
+
+#if defined(CONFIG_MIDI)
/*
* Don't make MAX_QUEUE_SIZE larger than 4000
*/
#define MAX_QUEUE_SIZE 4000
+int
+MIDIbuf_poll (int dev, struct fileinfo *file, int events, select_table * wait);
+
+void
+drain_midi_queue(int dev);
+
+static int *midi_sleeper[MAX_MIDI_DEV] = {NULL};
+static volatile struct snd_wait midi_sleep_flag[MAX_MIDI_DEV] = { {0}};
+static int *input_sleeper[MAX_MIDI_DEV] = {NULL};
+static volatile struct snd_wait input_sleep_flag[MAX_MIDI_DEV] = { {0}};
-DEFINE_WAIT_QUEUES (midi_sleeper[MAX_MIDI_DEV], midi_sleep_flag[MAX_MIDI_DEV]);
-DEFINE_WAIT_QUEUES (input_sleeper[MAX_MIDI_DEV], input_sleep_flag[MAX_MIDI_DEV]);
-
-struct midi_buf
- {
- int len, head, tail;
- unsigned char queue[MAX_QUEUE_SIZE];
- };
-
-struct midi_parms
- {
- int prech_timeout; /*
- * Timeout before the first ch
- */
- };
-
-static struct midi_buf *midi_out_buf[MAX_MIDI_DEV] =
-{NULL};
-static struct midi_buf *midi_in_buf[MAX_MIDI_DEV] =
-{NULL};
+struct midi_buf {
+ int len, head, tail;
+ u_char queue[MAX_QUEUE_SIZE];
+};
+
+struct midi_parms {
+ int prech_timeout; /* Timeout before the first ch */
+};
+
+static struct midi_buf *midi_out_buf[MAX_MIDI_DEV] = {NULL};
+static struct midi_buf *midi_in_buf[MAX_MIDI_DEV] = {NULL};
static struct midi_parms parms[MAX_MIDI_DEV];
-static void midi_poll (unsigned long dummy);
+static void midi_poll(void *dummy);
-DEFINE_TIMER (poll_timer, midi_poll);
static volatile int open_devs = 0;
#define DATA_AVAIL(q) (q->len)
#define SPACE_AVAIL(q) (MAX_QUEUE_SIZE - q->len)
#define QUEUE_BYTE(q, data) \
- if (SPACE_AVAIL(q)) \
- { \
- unsigned long flags; \
- DISABLE_INTR(flags); \
+ if (SPACE_AVAIL(q)) { \
+ u_long flags; \
+ flags = splhigh(); \
q->queue[q->tail] = (data); \
q->len++; q->tail = (q->tail+1) % MAX_QUEUE_SIZE; \
- RESTORE_INTR(flags); \
+ splx(flags); \
}
#define REMOVE_BYTE(q, data) \
- if (DATA_AVAIL(q)) \
- { \
- unsigned long flags; \
- DISABLE_INTR(flags); \
+ if (DATA_AVAIL(q)) { \
+ u_long flags; \
+ flags = splhigh(); \
data = q->queue[q->head]; \
q->len--; q->head = (q->head+1) % MAX_QUEUE_SIZE; \
- RESTORE_INTR(flags); \
+ splx(flags); \
}
void
-drain_midi_queue (int dev)
+drain_midi_queue(int dev)
{
- /*
- * Give the Midi driver time to drain its output queues
- */
+ /*
+ * Give the Midi driver time to drain its output queues
+ */
+
+ if (midi_devs[dev]->buffer_status != NULL)
+ while (!(PROCESS_ABORTING (midi_sleep_flag[dev])) &&
+ midi_devs[dev]->buffer_status(dev)) {
+ int chn;
+
+ midi_sleeper[dev] = &chn;
+ DO_SLEEP(chn, midi_sleep_flag[dev], hz / 10);
- if (midi_devs[dev]->buffer_status != NULL)
- while (!PROCESS_ABORTING (midi_sleeper[dev], midi_sleep_flag[dev]) &&
- midi_devs[dev]->buffer_status (dev))
- DO_SLEEP (midi_sleeper[dev], midi_sleep_flag[dev], HZ / 10);
+ };
}
static void
-midi_input_intr (int dev, unsigned char data)
+midi_input_intr(int dev, u_char data)
{
- if (midi_in_buf[dev] == NULL)
- return;
-
- if (data == 0xfe) /*
- * Active sensing
- */
- return; /*
- * Ignore
- */
-
- if (SPACE_AVAIL (midi_in_buf[dev]))
- {
- QUEUE_BYTE (midi_in_buf[dev], data);
- if (SOMEONE_WAITING (input_sleeper[dev], input_sleep_flag[dev]))
- WAKE_UP (input_sleeper[dev], input_sleep_flag[dev]);
- }
-
+ if (midi_in_buf[dev] == NULL)
+ return;
+
+ if (data == 0xfe) /* Active sensing */
+ return; /* Ignore */
+
+ if (SPACE_AVAIL(midi_in_buf[dev])) {
+ QUEUE_BYTE(midi_in_buf[dev], data);
+ if ((input_sleep_flag[dev].mode & WK_SLEEP)) {
+ input_sleep_flag[dev].mode = WK_WAKEUP;
+ wakeup(input_sleeper[dev]);
+ };
+ }
}
static void
-midi_output_intr (int dev)
+midi_output_intr(int dev)
{
- /*
- * Currently NOP
- */
+ /*
+ * Currently NOP
+ */
}
static void
-midi_poll (unsigned long dummy)
+midi_poll(void *dummy)
{
- unsigned long flags;
- int dev;
-
- DISABLE_INTR (flags);
- if (open_devs)
- {
- for (dev = 0; dev < num_midis; dev++)
- if (midi_out_buf[dev] != NULL)
- {
- while (DATA_AVAIL (midi_out_buf[dev]) &&
- midi_devs[dev]->putc (dev,
- midi_out_buf[dev]->queue[midi_out_buf[dev]->head]))
- {
- midi_out_buf[dev]->head = (midi_out_buf[dev]->head + 1) % MAX_QUEUE_SIZE;
- midi_out_buf[dev]->len--;
- }
-
- if (DATA_AVAIL (midi_out_buf[dev]) < 100 &&
- SOMEONE_WAITING (midi_sleeper[dev], midi_sleep_flag[dev]))
- WAKE_UP (midi_sleeper[dev], midi_sleep_flag[dev]);
- }
- ACTIVATE_TIMER (poll_timer, midi_poll, 1); /*
- * Come back later
- */
- }
- RESTORE_INTR (flags);
+ u_long flags;
+ int dev;
+
+ flags = splhigh();
+ if (open_devs) {
+ for (dev = 0; dev < num_midis; dev++)
+ if (midi_out_buf[dev] != NULL) {
+ while (DATA_AVAIL(midi_out_buf[dev]) &&
+ midi_devs[dev]->putc(dev,
+ midi_out_buf[dev]->queue[midi_out_buf[dev]->head])) {
+ midi_out_buf[dev]->head = (midi_out_buf[dev]->head + 1) % MAX_QUEUE_SIZE;
+ midi_out_buf[dev]->len--;
+ }
+
+ if (DATA_AVAIL(midi_out_buf[dev]) < 100 &&
+ (midi_sleep_flag[dev].mode & WK_SLEEP)) {
+ midi_sleep_flag[dev].mode = WK_WAKEUP;
+ wakeup(midi_sleeper[dev]);
+ };
+ }
+ timeout( midi_poll, 0, 1);; /* Come back later */
+ }
+ splx(flags);
}
int
-MIDIbuf_open (int dev, struct fileinfo *file)
+MIDIbuf_open(int dev, struct fileinfo * file)
{
- int mode, err;
- unsigned long flags;
+ int mode, err;
- dev = dev >> 4;
- mode = file->mode & O_ACCMODE;
-
- if (num_midis > MAX_MIDI_DEV)
- {
- printk ("Sound: FATAL ERROR: Too many midi interfaces\n");
- num_midis = MAX_MIDI_DEV;
- }
-
- if (dev < 0 || dev >= num_midis)
- {
- printk ("Sound: Nonexistent MIDI interface %d\n", dev);
- return RET_ERROR (ENXIO);
- }
-
- /*
- * Interrupts disabled. Be careful
- */
+ dev = dev >> 4;
+ mode = file->mode & O_ACCMODE;
+
+ if (num_midis > MAX_MIDI_DEV) {
+ printf("Sound: FATAL ERROR: Too many midi interfaces\n");
+ num_midis = MAX_MIDI_DEV;
+ }
+ if (dev < 0 || dev >= num_midis) {
+ printf("Sound: Nonexistent MIDI interface %d\n", dev);
+ return -(ENXIO);
+ }
+ /*
+ * Interrupts disabled. Be careful
+ */
- DISABLE_INTR (flags);
- if ((err = midi_devs[dev]->open (dev, mode,
- midi_input_intr, midi_output_intr)) < 0)
- {
- RESTORE_INTR (flags);
- return err;
- }
-
- parms[dev].prech_timeout = 0;
-
- RESET_WAIT_QUEUE (midi_sleeper[dev], midi_sleep_flag[dev]);
- RESET_WAIT_QUEUE (input_sleeper[dev], input_sleep_flag[dev]);
-
- midi_in_buf[dev] = (struct midi_buf *) KERNEL_MALLOC (sizeof (struct midi_buf));
-
- if (midi_in_buf[dev] == NULL)
- {
- printk ("midi: Can't allocate buffer\n");
- midi_devs[dev]->close (dev);
- RESTORE_INTR (flags);
- return RET_ERROR (EIO);
- }
- midi_in_buf[dev]->len = midi_in_buf[dev]->head = midi_in_buf[dev]->tail = 0;
-
- midi_out_buf[dev] = (struct midi_buf *) KERNEL_MALLOC (sizeof (struct midi_buf));
-
- if (midi_out_buf[dev] == NULL)
- {
- printk ("midi: Can't allocate buffer\n");
- midi_devs[dev]->close (dev);
- KERNEL_FREE (midi_in_buf[dev]);
- midi_in_buf[dev] = NULL;
- RESTORE_INTR (flags);
- return RET_ERROR (EIO);
- }
- midi_out_buf[dev]->len = midi_out_buf[dev]->head = midi_out_buf[dev]->tail = 0;
- if (!open_devs)
- ACTIVATE_TIMER (poll_timer, midi_poll, 1); /*
- * Come back later
- */
- open_devs++;
- RESTORE_INTR (flags);
-
- return err;
+ if ((err = midi_devs[dev]->open(dev, mode,
+ midi_input_intr, midi_output_intr)) < 0) {
+ return err;
+ }
+ parms[dev].prech_timeout = 0;
+
+ midi_in_buf[dev] = (struct midi_buf *) malloc(sizeof(struct midi_buf), M_TEMP, M_WAITOK);
+
+ if (midi_in_buf[dev] == NULL) {
+ printf("midi: Can't allocate buffer\n");
+ midi_devs[dev]->close(dev);
+ return -(EIO);
+ }
+ midi_in_buf[dev]->len = midi_in_buf[dev]->head = midi_in_buf[dev]->tail = 0;
+
+ midi_out_buf[dev] = (struct midi_buf *) malloc(sizeof(struct midi_buf), M_TEMP, M_WAITOK);
+
+ if (midi_out_buf[dev] == NULL) {
+ printf("midi: Can't allocate buffer\n");
+ midi_devs[dev]->close(dev);
+ free(midi_in_buf[dev], M_TEMP);
+ midi_in_buf[dev] = NULL;
+ return -(EIO);
+ }
+ midi_out_buf[dev]->len = midi_out_buf[dev]->head = midi_out_buf[dev]->tail = 0;
+ open_devs++;
+
+ {
+ midi_sleep_flag[dev].aborting = 0;
+ midi_sleep_flag[dev].mode = WK_NONE;
+ };
+ {
+ input_sleep_flag[dev].aborting = 0;
+ input_sleep_flag[dev].mode = WK_NONE;
+ };
+
+ if (open_devs < 2) { /* This was first open */
+ {
+ };
+
+ timeout( midi_poll, 0, 1);; /* Start polling */
+ }
+ return err;
}
void
-MIDIbuf_release (int dev, struct fileinfo *file)
+MIDIbuf_release(int dev, struct fileinfo * file)
{
- int mode;
- unsigned long flags;
+ int mode;
+ u_long flags;
- dev = dev >> 4;
- mode = file->mode & O_ACCMODE;
+ dev = dev >> 4;
+ mode = file->mode & O_ACCMODE;
- DISABLE_INTR (flags);
+ if (dev < 0 || dev >= num_midis)
+ return;
- /*
- * Wait until the queue is empty
- */
+ flags = splhigh();
+
+ /*
+ * Wait until the queue is empty
+ */
- if (mode != OPEN_READ)
- {
- midi_devs[dev]->putc (dev, 0xfe); /*
- * Active sensing to shut the
- * devices
- */
-
- while (!PROCESS_ABORTING (midi_sleeper[dev], midi_sleep_flag[dev]) &&
- DATA_AVAIL (midi_out_buf[dev]))
- DO_SLEEP (midi_sleeper[dev], midi_sleep_flag[dev], 0); /*
- * Sync
- */
-
- drain_midi_queue (dev); /*
- * Ensure the output queues are empty
- */
- }
-
- midi_devs[dev]->close (dev);
- KERNEL_FREE (midi_in_buf[dev]);
- KERNEL_FREE (midi_out_buf[dev]);
- midi_in_buf[dev] = NULL;
- midi_out_buf[dev] = NULL;
- open_devs--;
- RESTORE_INTR (flags);
+ if (mode != OPEN_READ) {
+ midi_devs[dev]->putc(dev, 0xfe); /* Active sensing to
+ * shut the devices */
+
+ while (!(PROCESS_ABORTING (midi_sleep_flag[dev])) &&
+ DATA_AVAIL(midi_out_buf[dev])) {
+ int chn;
+ midi_sleeper[dev] = &chn;
+ DO_SLEEP(chn, midi_sleep_flag[dev], 0);
+
+ }; /* Sync */
+
+ drain_midi_queue(dev); /* Ensure the output queues are empty */
+ }
+ splx(flags);
+
+ midi_devs[dev]->close(dev);
+
+ free(midi_in_buf[dev], M_TEMP);
+ free(midi_out_buf[dev], M_TEMP);
+ midi_in_buf[dev] = NULL;
+ midi_out_buf[dev] = NULL;
+ if (open_devs < 2) {
+ };
+ open_devs--;
}
int
-MIDIbuf_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
+MIDIbuf_write(int dev, struct fileinfo * file, snd_rw_buf * buf, int count)
{
- unsigned long flags;
- int c, n, i;
- unsigned char tmp_data;
+ u_long flags;
+ int c, n, i;
+ u_char tmp_data;
- dev = dev >> 4;
+ dev = dev >> 4;
- if (!count)
- return 0;
+ if (!count)
+ return 0;
- DISABLE_INTR (flags);
+ flags = splhigh();
- c = 0;
+ c = 0;
- while (c < count)
- {
- n = SPACE_AVAIL (midi_out_buf[dev]);
+ while (c < count) {
+ n = SPACE_AVAIL(midi_out_buf[dev]);
- if (n == 0) /*
- * No space just now. We have to sleep
- */
- {
- DO_SLEEP (midi_sleeper[dev], midi_sleep_flag[dev], 0);
- if (PROCESS_ABORTING (midi_sleeper[dev], midi_sleep_flag[dev]))
- {
- RESTORE_INTR (flags);
- return RET_ERROR (EINTR);
- }
-
- n = SPACE_AVAIL (midi_out_buf[dev]);
- }
+ if (n == 0) { /* No space just now. We have to sleep */
- if (n > (count - c))
- n = count - c;
+ {
+ int chn;
- for (i = 0; i < n; i++)
- {
- COPY_FROM_USER (&tmp_data, buf, c, 1);
- QUEUE_BYTE (midi_out_buf[dev], tmp_data);
- c++;
+ midi_sleeper[dev] = &chn;
+ DO_SLEEP(chn, midi_sleep_flag[dev], 0);
+ };
+
+ if (PROCESS_ABORTING(midi_sleep_flag[dev])) {
+ splx(flags);
+ return -(EINTR);
+ }
+ n = SPACE_AVAIL(midi_out_buf[dev]);
+ }
+ if (n > (count - c))
+ n = count - c;
+
+ for (i = 0; i < n; i++) {
+
+ if (uiomove((char *) &tmp_data, 1, buf)) {
+ printf("sb: Bad copyin()!\n");
+ };
+ QUEUE_BYTE(midi_out_buf[dev], tmp_data);
+ c++;
+ }
}
- }
- RESTORE_INTR (flags);
+ splx(flags);
- return c;
+ return c;
}
int
-MIDIbuf_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
+MIDIbuf_read(int dev, struct fileinfo * file, snd_rw_buf * buf, int count)
{
- int n, c = 0;
- unsigned long flags;
- unsigned char tmp_data;
+ int n, c = 0;
+ u_long flags;
+ u_char tmp_data;
- dev = dev >> 4;
+ dev = dev >> 4;
- DISABLE_INTR (flags);
-
- if (!DATA_AVAIL (midi_in_buf[dev])) /*
- * No data yet, wait
- */
- {
- DO_SLEEP (input_sleeper[dev], input_sleep_flag[dev],
- parms[dev].prech_timeout);
- if (PROCESS_ABORTING (input_sleeper[dev], input_sleep_flag[dev]))
- c = RET_ERROR (EINTR); /*
- * The user is getting restless
- */
- }
-
- if (c == 0 && DATA_AVAIL (midi_in_buf[dev])) /*
- * Got some bytes
- */
- {
- n = DATA_AVAIL (midi_in_buf[dev]);
- if (n > count)
- n = count;
- c = 0;
-
- while (c < n)
- {
- REMOVE_BYTE (midi_in_buf[dev], tmp_data);
- COPY_TO_USER (buf, c, &tmp_data, 1);
- c++;
- }
- }
+ flags = splhigh();
+
+ if (!DATA_AVAIL(midi_in_buf[dev])) { /* No data yet, wait */
- RESTORE_INTR (flags);
+ {
+ int chn;
- return c;
+
+ input_sleeper[dev] = &chn;
+ DO_SLEEP(chn, input_sleep_flag[dev],
+ parms[dev].prech_timeout);
+
+ };
+ if (PROCESS_ABORTING(input_sleep_flag[dev]))
+ c = -(EINTR); /* The user is getting restless */
+ }
+ if (c == 0 && DATA_AVAIL(midi_in_buf[dev])) { /* Got some bytes */
+ n = DATA_AVAIL(midi_in_buf[dev]);
+ if (n > count)
+ n = count;
+ c = 0;
+
+ while (c < n) {
+ REMOVE_BYTE(midi_in_buf[dev], tmp_data);
+
+ if (uiomove((char *) &tmp_data, 1, buf)) {
+ printf("sb: Bad copyout()!\n");
+ };
+ c++;
+ }
+ }
+ splx(flags);
+
+ return c;
}
int
-MIDIbuf_ioctl (int dev, struct fileinfo *file,
- unsigned int cmd, unsigned int arg)
+MIDIbuf_ioctl(int dev, struct fileinfo * file, u_int cmd, ioctl_arg arg)
{
- int val;
+ int val;
- dev = dev >> 4;
+ dev = dev >> 4;
- switch (cmd)
- {
+ if (((cmd >> 8) & 0xff) == 'C') {
+ if (midi_devs[dev]->coproc) /* Coprocessor ioctl */
+ return midi_devs[dev]->coproc->ioctl(midi_devs[dev]->coproc->devc, cmd, arg, 0);
+ else
+ printf("/dev/midi%d: No coprocessor for this device\n", dev);
- case SNDCTL_MIDI_PRETIME:
- val = IOCTL_IN (arg);
- if (val < 0)
- val = 0;
+ return -(ENXIO);
+ } else
+ switch (cmd) {
- val = (HZ * val) / 10;
- parms[dev].prech_timeout = val;
- return IOCTL_OUT (arg, val);
- break;
+ case SNDCTL_MIDI_PRETIME:
+ val = (int) (*(int *) arg);
+ if (val < 0)
+ val = 0;
- default:
- return midi_devs[dev]->ioctl (dev, cmd, arg);
- }
+ val = (hz * val) / 10;
+ parms[dev].prech_timeout = val;
+ return *(int *) arg = val;
+ break;
+
+ default:
+ return midi_devs[dev]->ioctl(dev, cmd, arg);
+ }
}
-#ifdef ALLOW_SELECT
+#ifdef ALLOW_POLL
int
-MIDIbuf_select (int dev, struct fileinfo *file, int sel_type, select_table * wait)
+MIDIbuf_poll (int dev, struct fileinfo *file, int events, select_table * wait)
{
- dev = dev >> 4;
+ int revents = 0;
- switch (sel_type)
- {
- case SEL_IN:
- if (!DATA_AVAIL (midi_in_buf[dev]))
- {
- input_sleep_flag[dev].mode = WK_SLEEP;
- select_wait (&input_sleeper[dev], wait);
- return 0;
- }
- return 1;
- break;
+ dev = dev >> 4;
- case SEL_OUT:
- if (SPACE_AVAIL (midi_out_buf[dev]))
- {
- midi_sleep_flag[dev].mode = WK_SLEEP;
- select_wait (&midi_sleeper[dev], wait);
- return 0;
- }
- return 1;
- break;
+ if (events & (POLLIN | POLLRDNORM))
+ if (!DATA_AVAIL (midi_in_buf[dev]))
+ selrecord(wait, &selinfo[dev]);
+ else
+ revents |= events & (POLLIN | POLLRDNORM);
- case SEL_EX:
- return 0;
- }
+ if (events & (POLLOUT | POLLWRNORM))
+ if (SPACE_AVAIL (midi_out_buf[dev]))
+ selrecord(wait, &selinfo[dev]);
+ else
+ revents |= events & (POLLOUT | POLLWRNORM);
- return 0;
+ return revents;
}
#endif /* ALLOW_SELECT */
-long
-MIDIbuf_init (long mem_start)
-{
- return mem_start;
-}
+
#endif
diff --git a/sys/i386/isa/sound/mpu401.c b/sys/i386/isa/sound/mpu401.c
index 40be06638ac5..60b0c292221d 100644
--- a/sys/i386/isa/sound/mpu401.c
+++ b/sys/i386/isa/sound/mpu401.c
@@ -1,10 +1,10 @@
/*
* sound/mpu401.c
- *
+ *
* The low level driver for Roland MPU-401 compatible Midi 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,90 +24,91 @@
* 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: Riccardo Facchetti 24 Mar 1995 - Added the Audio Excel DSP 16
+ * initialization routine.
*/
#define USE_SEQ_MACROS
#define USE_SIMPLE_MACROS
-#include "sound_config.h"
+#include <i386/isa/sound/sound_config.h>
-#ifdef CONFIGURE_SOUNDCARD
-
-#if !defined(EXCLUDE_MPU401) && !defined(EXCLUDE_MIDI)
+#if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI)
+#include <i386/isa/sound/coproc.h>
static int init_sequence[20]; /* NOTE! pos 0 = len, start pos 1. */
+
+#ifdef CONFIG_SEQUENCER
static int timer_mode = TMR_INTERNAL, timer_caps = TMR_INTERNAL;
-struct mpu_config
- {
- int base; /*
- * I/O base
- */
- int irq;
- int opened; /*
- * Open mode
- */
- int devno;
- int synthno;
- int uart_mode;
- int initialized;
- int mode;
+#endif
+
+struct mpu_config {
+ int base; /* I/O base */
+ int irq;
+ int opened; /* Open mode */
+ int devno;
+ int synthno;
+ int uart_mode;
+ int initialized;
+ int mode;
#define MODE_MIDI 1
#define MODE_SYNTH 2
- unsigned char version, revision;
- unsigned int capabilities;
+ u_char version, revision;
+ u_int capabilities;
#define MPU_CAP_INTLG 0x10000000
#define MPU_CAP_SYNC 0x00000010
#define MPU_CAP_FSK 0x00000020
#define MPU_CAP_CLS 0x00000040
#define MPU_CAP_SMPTE 0x00000080
#define MPU_CAP_2PORT 0x00000001
- int timer_flag;
+ int timer_flag;
#define MBUF_MAX 10
#define BUFTEST(dc) if (dc->m_ptr >= MBUF_MAX || dc->m_ptr < 0) \
- {printk("MPU: Invalid buffer pointer %d/%d, s=%d\n", dc->m_ptr, dc->m_left, dc->m_state);dc->m_ptr--;}
- int m_busy;
- unsigned char m_buf[MBUF_MAX];
- int m_ptr;
- int m_state;
- int m_left;
- unsigned char last_status;
- void (*inputintr) (int dev, unsigned char data);
- unsigned short controls[32];
- };
+ {printf("MPU: Invalid buffer pointer %d/%d, s=%d\n", dc->m_ptr, dc->m_left, dc->m_state);dc->m_ptr--;}
+ int m_busy;
+ u_char m_buf[MBUF_MAX];
+ int m_ptr;
+ int m_state;
+ int m_left;
+ u_char last_status;
+ void (*inputintr) (int dev, u_char data);
+ int shared_irq;
+ sound_os_info *osp;
+};
#define DATAPORT(base) (base)
#define COMDPORT(base) (base+1)
#define STATPORT(base) (base+1)
-#define mpu401_status(base) INB(STATPORT(base))
-#define input_avail(base) (!(mpu401_status(base)&INPUT_AVAIL))
-#define output_ready(base) (!(mpu401_status(base)&OUTPUT_READY))
-#define write_command(base, cmd) OUTB(cmd, COMDPORT(base))
-#define read_data(base) INB(DATAPORT(base))
+#define mpu401_status(devc) inb( STATPORT(devc->base))
+#define input_avail(devc) (!(mpu401_status(devc)&INPUT_AVAIL))
+#define output_ready(devc) (!(mpu401_status(devc)&OUTPUT_READY))
+#define write_command(devc, cmd) outb( COMDPORT(devc->base), cmd)
+#define read_data(devc) inb( DATAPORT(devc->base))
-#define write_data(base, byte) OUTB(byte, DATAPORT(base))
+#define write_data(devc, byte) outb( DATAPORT(devc->base), byte)
#define OUTPUT_READY 0x40
#define INPUT_AVAIL 0x80
-#define MPU_ACK 0xF7
+#define MPU_ACK 0xFE
#define MPU_RESET 0xFF
#define UART_MODE_ON 0x3F
-static struct mpu_config dev_conf[MAX_MIDI_DEV] =
-{
- {0}};
+static struct mpu_config dev_conf[MAX_MIDI_DEV] = { {0}};
static int n_mpu_devs = 0;
-static int irq2dev[16];
+static volatile int irq2dev[17] =
+ {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
+
+static int reset_mpu401(struct mpu_config * devc);
+static void set_uart_mode(int dev, struct mpu_config * devc, int arg);
-static int reset_mpu401 (struct mpu_config *devc);
-static void set_uart_mode (int dev, struct mpu_config *devc, int arg);
-static void mpu_timer_init (int midi_dev);
-static void mpu_timer_interrupt (void);
-static void timer_ext_event (struct mpu_config *devc, int event, int parm);
+static void mpu_timer_init(int midi_dev);
+static void mpu_timer_interrupt(void);
+static void timer_ext_event(struct mpu_config * devc, int event, int parm);
static struct synth_info mpu_synth_info_proto =
{"MPU-401 MIDI interface", 0, SYNTH_TYPE_MIDI, 0, 0, 128, 0, 128, SYNTH_CAP_INPUT};
@@ -128,119 +129,57 @@ static struct synth_info mpu_synth_info[MAX_MIDI_DEV];
#define ST_SONGSEL 103 /* Song select */
#define ST_SONGPOS 104 /* Song position pointer */
-static unsigned char len_tab[] =/* # of data bytes following a status
- */
+static u_char len_tab[] =/* # of data bytes following a status */
{
- 2, /* 8x */
- 2, /* 9x */
- 2, /* Ax */
- 2, /* Bx */
- 1, /* Cx */
- 1, /* Dx */
- 2, /* Ex */
- 0 /* Fx */
+ 2, /* 8x */
+ 2, /* 9x */
+ 2, /* Ax */
+ 2, /* Bx */
+ 1, /* Cx */
+ 1, /* Dx */
+ 2, /* Ex */
+ 0 /* Fx */
};
+#ifndef CONFIG_SEQUENCER
+#define STORE(cmd)
+#else
#define STORE(cmd) \
-if (devc->opened & OPEN_READ) \
{ \
int len; \
- unsigned char obuf[8]; \
+ u_char obuf[8]; \
cmd; \
seq_input_event(obuf, len); \
}
+#endif
+
#define _seqbuf obuf
#define _seqbufptr 0
#define _SEQ_ADVBUF(x) len=x
-static void
-do_midi_msg (struct mpu_config *devc, unsigned char *msg, int mlen)
-{
- switch (msg[0] & 0xf0)
- {
- case 0x90:
- if (msg[2] != 0)
- {
- STORE (SEQ_START_NOTE (devc->synthno, msg[0] & 0x0f, msg[1], msg[2]));
- break;
- }
- msg[2] = 64;
-
- case 0x80:
- STORE (SEQ_STOP_NOTE (devc->synthno, msg[0] & 0x0f, msg[1], msg[2]));
- break;
-
- case 0xA0:
- STORE (SEQ_KEY_PRESSURE (devc->synthno, msg[0] & 0x0f, msg[1], msg[2]));
- break;
-
- case 0xB0:
- /*
- * Fix the controller value (combine MSB and LSB)
- */
- if (msg[1] < 64)
- {
- int ctrl = msg[1];
-
- if (ctrl < 32)
- {
- devc->controls[ctrl] = (msg[2] & 0x7f) << 7;
- }
- else
- {
- ctrl -= 32;
- devc->controls[ctrl] =
- (devc->controls[ctrl] & ~0x7f) | (msg[2] & 0x7f);
- }
- STORE (SEQ_CONTROL (devc->synthno, msg[0] & 0x0f,
- msg[1], devc->controls[ctrl]));
- }
- else
- STORE (SEQ_CONTROL (devc->synthno, msg[0] & 0x0f, msg[1], msg[2]));
- break;
-
- case 0xC0:
- STORE (SEQ_SET_PATCH (devc->synthno, msg[0] & 0x0f, msg[1]));
- break;
-
- case 0xD0:
- STORE (SEQ_CHN_PRESSURE (devc->synthno, msg[0] & 0x0f, msg[1]));
- break;
-
- case 0xE0:
- STORE (SEQ_BENDER (devc->synthno, msg[0] & 0x0f,
- (msg[1] % 0x7f) | ((msg[2] & 0x7f) << 7)));
- break;
-
- default:
- printk ("MPU: Unknown midi channel message %02x\n", msg[0]);
- }
-}
-
static int
-mpu_input_scanner (struct mpu_config *devc, unsigned char midic)
+mpu_input_scanner(struct mpu_config * devc, u_char midic)
{
- switch (devc->m_state)
- {
+
+ switch (devc->m_state) {
case ST_INIT:
- switch (midic)
- {
+ switch (midic) {
case 0xf8:
- /* Timer overflow */
- break;
+ /* Timer overflow */
+ break;
case 0xfc:
- printk ("<all end>");
- break;
+ printf("<all end>");
+ break;
case 0xfd:
- if (devc->timer_flag)
- mpu_timer_interrupt ();
- break;
+ if (devc->timer_flag)
+ mpu_timer_interrupt();
+ break;
case 0xfe:
- return MPU_ACK;
- break;
+ return MPU_ACK;
+ break;
case 0xf0:
case 0xf1:
@@ -250,1472 +189,1440 @@ mpu_input_scanner (struct mpu_config *devc, unsigned char midic)
case 0xf5:
case 0xf6:
case 0xf7:
- printk ("<Trk data rq #%d>", midic & 0x0f);
- break;
+ printf("<Trk data rq #%d>", midic & 0x0f);
+ break;
case 0xf9:
- printk ("<conductor rq>");
- break;
+ printf("<conductor rq>");
+ break;
case 0xff:
- devc->m_state = ST_SYSMSG;
- break;
+ devc->m_state = ST_SYSMSG;
+ break;
default:
- if (midic <= 0xef)
- {
- /* printk("mpu time: %d ", midic); */
- devc->m_state = ST_TIMED;
- }
- else
- printk ("<MPU: Unknown event %02x> ", midic);
+ if (midic <= 0xef) {
+ /* printf("mpu time: %d ", midic); */
+ devc->m_state = ST_TIMED;
+ } else
+ printf("<MPU: Unknown event %02x> ", midic);
}
- break;
+ break;
case ST_TIMED:
- {
- int msg = (midic & 0xf0) >> 4;
-
- devc->m_state = ST_DATABYTE;
- if (msg < 8) /* Data byte */
- {
- /* printk("midi msg (running status) "); */
- msg = (devc->last_status & 0xf0) >> 4;
- msg -= 8;
- devc->m_left = len_tab[msg] - 1;
-
- devc->m_ptr = 2;
- devc->m_buf[0] = devc->last_status;
- devc->m_buf[1] = midic;
-
- if (devc->m_left <= 0)
- {
+ {
+ int msg = ((int) (midic & 0xf0) >> 4);
+
+ devc->m_state = ST_DATABYTE;
+
+ if (msg < 8) { /* Data byte */
+ /* printf("midi msg (running status) "); */
+ msg = ((int) (devc->last_status & 0xf0) >> 4);
+ msg -= 8;
+ devc->m_left = len_tab[msg] - 1;
+
+ devc->m_ptr = 2;
+ devc->m_buf[0] = devc->last_status;
+ devc->m_buf[1] = midic;
+
+ if (devc->m_left <= 0) {
+ devc->m_state = ST_INIT;
+ do_midi_msg(devc->synthno, devc->m_buf, devc->m_ptr);
+ devc->m_ptr = 0;
+ }
+ } else if (msg == 0xf) { /* MPU MARK */
devc->m_state = ST_INIT;
- do_midi_msg (devc, devc->m_buf, devc->m_ptr);
- devc->m_ptr = 0;
- }
- }
- else if (msg == 0xf) /* MPU MARK */
- {
- devc->m_state = ST_INIT;
-
- switch (midic)
- {
- case 0xf8:
- /* printk("NOP "); */
- break;
-
- case 0xf9:
- /* printk("meas end "); */
- break;
- case 0xfc:
- /* printk("data end "); */
- break;
-
- default:
- printk ("Unknown MPU mark %02x\n", midic);
- }
- }
- else
- {
- devc->last_status = midic;
- /* printk("midi msg "); */
- msg -= 8;
- devc->m_left = len_tab[msg];
-
- devc->m_ptr = 1;
- devc->m_buf[0] = midic;
-
- if (devc->m_left <= 0)
- {
- devc->m_state = ST_INIT;
- do_midi_msg (devc, devc->m_buf, devc->m_ptr);
- devc->m_ptr = 0;
- }
- }
- }
- break;
+ switch (midic) {
+ case 0xf8:
+ /* printf("NOP "); */
+ break;
+
+ case 0xf9:
+ /* printf("meas end "); */
+ break;
+
+ case 0xfc:
+ /* printf("data end "); */
+ break;
+
+ default:
+ printf("Unknown MPU mark %02x\n", midic);
+ }
+ } else {
+ devc->last_status = midic;
+ /* printf ("midi msg "); */
+ msg -= 8;
+ devc->m_left = len_tab[msg];
+
+ devc->m_ptr = 1;
+ devc->m_buf[0] = midic;
+
+ if (devc->m_left <= 0) {
+ devc->m_state = ST_INIT;
+ do_midi_msg(devc->synthno, devc->m_buf, devc->m_ptr);
+ devc->m_ptr = 0;
+ }
+ }
+ }
+ break;
case ST_SYSMSG:
- switch (midic)
- {
+ switch (midic) {
case 0xf0:
- printk ("<SYX>");
- devc->m_state = ST_SYSEX;
- break;
+ printf("<SYX>");
+ devc->m_state = ST_SYSEX;
+ break;
case 0xf1:
- devc->m_state = ST_MTC;
- break;
+ devc->m_state = ST_MTC;
+ break;
case 0xf2:
- devc->m_state = ST_SONGPOS;
- devc->m_ptr = 0;
- break;
+ devc->m_state = ST_SONGPOS;
+ devc->m_ptr = 0;
+ break;
case 0xf3:
- devc->m_state = ST_SONGSEL;
- break;
+ devc->m_state = ST_SONGSEL;
+ break;
case 0xf6:
- /* printk("tune_request\n"); */
- devc->m_state = ST_INIT;
+ /* printf("tune_request\n"); */
+ devc->m_state = ST_INIT;
+ /* XXX do we need a break here ? - lr 970710 */
- /*
- * Real time messages
- */
+ /*
+ * Real time messages
+ */
case 0xf8:
- /* midi clock */
- devc->m_state = ST_INIT;
- timer_ext_event (devc, TMR_CLOCK, 0);
- break;
+ /* midi clock */
+ devc->m_state = ST_INIT;
+ timer_ext_event(devc, TMR_CLOCK, 0);
+ break;
case 0xfA:
- devc->m_state = ST_INIT;
- timer_ext_event (devc, TMR_START, 0);
- break;
+ devc->m_state = ST_INIT;
+ timer_ext_event(devc, TMR_START, 0);
+ break;
case 0xFB:
- devc->m_state = ST_INIT;
- timer_ext_event (devc, TMR_CONTINUE, 0);
- break;
+ devc->m_state = ST_INIT;
+ timer_ext_event(devc, TMR_CONTINUE, 0);
+ break;
case 0xFC:
- devc->m_state = ST_INIT;
- timer_ext_event (devc, TMR_STOP, 0);
- break;
+ devc->m_state = ST_INIT;
+ timer_ext_event(devc, TMR_STOP, 0);
+ break;
case 0xFE:
- /* active sensing */
- devc->m_state = ST_INIT;
- break;
+ /* active sensing */
+ devc->m_state = ST_INIT;
+ break;
case 0xff:
- /* printk("midi hard reset"); */
- devc->m_state = ST_INIT;
- break;
+ /* printf("midi hard reset"); */
+ devc->m_state = ST_INIT;
+ break;
default:
- printk ("unknown MIDI sysmsg %0x\n", midic);
- devc->m_state = ST_INIT;
+ printf("unknown MIDI sysmsg %0x\n", midic);
+ devc->m_state = ST_INIT;
}
- break;
+ break;
case ST_MTC:
- devc->m_state = ST_INIT;
- printk ("MTC frame %x02\n", midic);
- break;
+ devc->m_state = ST_INIT;
+ printf("MTC frame %x02\n", midic);
+ break;
case ST_SYSEX:
- if (midic == 0xf7)
- {
- printk ("<EOX>");
- devc->m_state = ST_INIT;
- }
- else
- printk ("%02x ", midic);
- break;
+ if (midic == 0xf7) {
+ printf("<EOX>");
+ devc->m_state = ST_INIT;
+ } else
+ printf("%02x ", midic);
+ break;
case ST_SONGPOS:
- BUFTEST (devc);
- devc->m_buf[devc->m_ptr++] = midic;
- if (devc->m_ptr == 2)
- {
- devc->m_state = ST_INIT;
- devc->m_ptr = 0;
- timer_ext_event (devc, TMR_SPP,
- ((devc->m_buf[1] & 0x7f) << 7) |
- (devc->m_buf[0] & 0x7f));
+ BUFTEST(devc);
+ devc->m_buf[devc->m_ptr++] = midic;
+ if (devc->m_ptr == 2) {
+ devc->m_state = ST_INIT;
+ devc->m_ptr = 0;
+ timer_ext_event(devc, TMR_SPP,
+ ((devc->m_buf[1] & 0x7f) << 7) | (devc->m_buf[0] & 0x7f));
}
- break;
+ break;
case ST_DATABYTE:
- BUFTEST (devc);
- devc->m_buf[devc->m_ptr++] = midic;
- if ((--devc->m_left) <= 0)
- {
- devc->m_state = ST_INIT;
- do_midi_msg (devc, devc->m_buf, devc->m_ptr);
- devc->m_ptr = 0;
+ BUFTEST(devc);
+ devc->m_buf[devc->m_ptr++] = midic;
+ if ((--devc->m_left) <= 0) {
+ devc->m_state = ST_INIT;
+ do_midi_msg(devc->synthno, devc->m_buf, devc->m_ptr);
+ devc->m_ptr = 0;
}
- break;
+ break;
default:
- printk ("Bad state %d ", devc->m_state);
- devc->m_state = ST_INIT;
+ printf("Bad state %d ", devc->m_state);
+ devc->m_state = ST_INIT;
}
- return 1;
+ return 1;
}
static void
-mpu401_input_loop (struct mpu_config *devc)
+mpu401_input_loop(struct mpu_config * devc)
{
- unsigned long flags;
- int busy;
+ u_long flags;
+ int n, busy;
- DISABLE_INTR (flags);
- busy = devc->m_busy;
- devc->m_busy = 1;
- RESTORE_INTR (flags);
+ flags = splhigh();
+ busy = devc->m_busy;
+ devc->m_busy = 1;
+ splx(flags);
- if (busy)
- return;
+ if (busy) /* Already inside the scanner */
+ return;
- while (input_avail (devc->base))
- {
- unsigned char c = read_data (devc->base);
+ n = 50;
- if (devc->mode == MODE_SYNTH)
- {
- mpu_input_scanner (devc, c);
- }
- else if (devc->opened & OPEN_READ && devc->inputintr != NULL)
- devc->inputintr (devc->devno, c);
+ while (input_avail(devc) && n-- > 0) {
+ u_char c = read_data(devc);
+
+ if (devc->mode == MODE_SYNTH) {
+ mpu_input_scanner(devc, c);
+ } else if (devc->opened & OPEN_READ && devc->inputintr != NULL)
+ devc->inputintr(devc->devno, c);
}
- devc->m_busy = 0;
+ devc->m_busy = 0;
}
void
-mpuintr (int irq)
+mpuintr(int irq)
{
- struct mpu_config *devc;
- int dev;
-
-#ifdef linux
- sti ();
-#endif
+ struct mpu_config *devc;
+ int dev;
- if (irq < 1 || irq > 15)
- {
- printk ("MPU-401: Interrupt #%d?\n", irq);
- return;
- }
+ /*
+ * FreeBSD (and some others) pass unit number to the interrupt
+ * handler. In this case we have to scan the table for first handler.
+ */
- dev = irq2dev[irq];
- if (dev == -1)
- {
- printk ("MPU-401: Interrupt #%d?\n", irq);
- return;
- }
+ if (irq < 1 || irq > 15) {
+ dev = -1;
+ } else
+ dev = irq2dev[irq];
- devc = &dev_conf[dev];
+ if (dev == -1) {
+ int origirq = irq;
- if (devc->base != 0 && (devc->opened & OPEN_READ || devc->mode == MODE_SYNTH))
- if (input_avail (devc->base))
- mpu401_input_loop (devc);
+ for (irq = 0; irq <= 16; irq++)
+ if (irq2dev[irq] != -1)
+ break;
+ if (irq > 15) {
+ printf("MPU-401: Bogus interrupt #%d?\n", origirq);
+ return;
+ }
+ dev = irq2dev[irq];
+ devc = &dev_conf[dev];
+ } else
+ devc = &dev_conf[dev];
+
+ if (input_avail(devc))
+ if (devc->base != 0 && (devc->opened & OPEN_READ || devc->mode == MODE_SYNTH))
+ mpu401_input_loop(devc);
+ else {
+ /* Dummy read (just to acknowledge the interrupt) */
+ read_data(devc);
+ }
}
static int
-mpu401_open (int dev, int mode,
- void (*input) (int dev, unsigned char data),
- void (*output) (int dev)
-)
+mpu401_open(int dev, int mode,
+ void (*input) (int dev, u_char data), void (*output) (int dev))
{
- int err;
- struct mpu_config *devc;
+ int err;
+ struct mpu_config *devc;
- if (dev < 0 || dev >= num_midis)
- return RET_ERROR (ENXIO);
+ if (dev < 0 || dev >= num_midis)
+ return -(ENXIO);
- devc = &dev_conf[dev];
+ devc = &dev_conf[dev];
- if (devc->opened)
- {
- printk ("MPU-401: Midi busy\n");
- return RET_ERROR (EBUSY);
+ if (devc->opened) {
+ printf("MPU-401: Midi busy\n");
+ return -(EBUSY);
}
+ /*
+ * Verify that the device is really running. Some devices (such as
+ * Ensoniq SoundScape don't work before the on board processor (OBP)
+ * is initialized by downloadin it's microcode.
+ */
+
+ if (!devc->initialized) {
+ if (mpu401_status(devc) == 0xff) { /* Bus float */
+ printf("MPU-401: Device not initialized properly\n");
+ return -(EIO);
+ }
+ reset_mpu401(devc);
+ }
+ irq2dev[devc->irq] = dev;
- irq2dev[devc->irq] = dev;
- if ((err = snd_set_irq_handler (devc->irq, mpuintr) < 0))
- return err;
+ if (midi_devs[dev]->coproc)
+ if ((err = midi_devs[dev]->coproc->
+ open(midi_devs[dev]->coproc->devc, COPR_MIDI)) < 0) {
+ printf("MPU-401: Can't access coprocessor device\n");
- set_uart_mode (dev, devc, 1);
- devc->mode = MODE_MIDI;
- devc->synthno = 0;
+ return err;
+ }
+ set_uart_mode(dev, devc, 1);
+ devc->mode = MODE_MIDI;
+ devc->synthno = 0;
- mpu401_input_loop (devc);
+ mpu401_input_loop(devc);
- devc->inputintr = input;
- devc->opened = mode;
+ devc->inputintr = input;
+ devc->opened = mode;
- return 0;
+ return 0;
}
static void
-mpu401_close (int dev)
+mpu401_close(int dev)
{
- struct mpu_config *devc;
+ struct mpu_config *devc;
- devc = &dev_conf[dev];
+ devc = &dev_conf[dev];
- if (devc->uart_mode)
- reset_mpu401 (devc); /*
- * This disables the UART mode
- */
- devc->mode = 0;
+ if (devc->uart_mode)
+ reset_mpu401(devc); /* This disables the UART mode */
+ devc->mode = 0;
- snd_release_irq (devc->irq);
- devc->inputintr = NULL;
- irq2dev[devc->irq] = -1;
- devc->opened = 0;
+ devc->inputintr = NULL;
+
+ if (midi_devs[dev]->coproc)
+ midi_devs[dev]->coproc->close(midi_devs[dev]->coproc->devc, COPR_MIDI);
+ devc->opened = 0;
}
static int
-mpu401_out (int dev, unsigned char midi_byte)
+mpu401_out(int dev, u_char midi_byte)
{
- int timeout;
- unsigned long flags;
+ int timeout;
+ u_long flags;
- struct mpu_config *devc;
+ struct mpu_config *devc;
- devc = &dev_conf[dev];
+ devc = &dev_conf[dev];
-#if 0
- /*
- * Test for input since pending input seems to block the output.
- */
+ /*
+ * Sometimes it takes about 13000 loops before the output becomes
+ * ready (After reset). Normally it takes just about 10 loops.
+ */
- if (input_avail (devc->base))
- mpu401_input_loop (devc);
-#endif
- /*
- * Sometimes it takes about 13000 loops before the output becomes ready
- * (After reset). Normally it takes just about 10 loops.
- */
-
- for (timeout = 30000; timeout > 0 && !output_ready (devc->base); timeout--); /*
- * Wait
- */
-
- DISABLE_INTR (flags);
- if (!output_ready (devc->base))
- {
- printk ("MPU-401: Send data timeout\n");
- RESTORE_INTR (flags);
- return 0;
- }
+ for (timeout = 3000; timeout > 0 && !output_ready(devc); timeout--);
- write_data (devc->base, midi_byte);
- RESTORE_INTR (flags);
- return 1;
+ flags = splhigh();
+ if (!output_ready(devc)) {
+ printf("MPU-401: Send data timeout\n");
+ splx(flags);
+ return 0;
+ }
+ write_data(devc, midi_byte);
+ splx(flags);
+ return 1;
}
static int
-mpu401_command (int dev, mpu_command_rec * cmd)
+mpu401_command(int dev, mpu_command_rec * cmd)
{
- int i, timeout, ok;
- int ret = 0;
- unsigned long flags;
- struct mpu_config *devc;
-
- devc = &dev_conf[dev];
-
- if (devc->uart_mode) /*
- * Not possible in UART mode
- */
- {
- printk ("MPU-401 commands not possible in the UART mode\n");
- return RET_ERROR (EINVAL);
- }
+ int i, timeout, ok;
+ int ret = 0;
+ u_long flags;
+ struct mpu_config *devc;
+
+ devc = &dev_conf[dev];
- /*
- * Test for input since pending input seems to block the output.
- */
- if (input_avail (devc->base))
- mpu401_input_loop (devc);
-
- /*
- * Sometimes it takes about 30000 loops before the output becomes ready
- * (After reset). Normally it takes just about 10 loops.
- */
-
- for (timeout = 500000; timeout > 0 && !output_ready (devc->base); timeout--);
-
- DISABLE_INTR (flags);
- if (!output_ready (devc->base))
- {
- printk ("MPU-401: Command (0x%x) timeout\n", (int) cmd->cmd);
- RESTORE_INTR (flags);
- return RET_ERROR (EIO);
+ if (devc->uart_mode) { /* Not possible in UART mode */
+ printf("MPU-401 commands not possible in the UART mode\n");
+ return -(EINVAL);
}
+ /*
+ * Test for input since pending input seems to block the output.
+ */
+ if (input_avail(devc))
+ mpu401_input_loop(devc);
+
+ /*
+ * Sometimes it takes about 30000 loops before the output becomes
+ * ready (After reset). Normally it takes just about 10 loops.
+ */
+
+ timeout = 30000;
+retry:
+ if (timeout-- <= 0) {
+ printf("MPU-401: Command (0x%x) timeout\n", (int) cmd->cmd);
+ return -(EIO);
+ }
+ flags = splhigh();
- write_command (devc->base, cmd->cmd);
- ok = 0;
- for (timeout = 500000; timeout > 0 && !ok; timeout--)
- if (input_avail (devc->base))
- if (mpu_input_scanner (devc, read_data (devc->base)) == MPU_ACK)
- ok = 1;
-
- if (!ok)
- {
- RESTORE_INTR (flags);
- printk ("MPU: No ACK to command (0x%x)\n", (int) cmd->cmd);
- return RET_ERROR (EIO);
+ if (!output_ready(devc)) {
+ splx(flags);
+ goto retry;
}
+ write_command(devc, cmd->cmd);
+ ok = 0;
+ for (timeout = 50000; timeout > 0 && !ok; timeout--)
+ if (input_avail(devc))
+ if (devc->opened && devc->mode == MODE_SYNTH) {
+ if (mpu_input_scanner(devc, read_data(devc)) == MPU_ACK)
+ ok = 1;
+ } else {/* Device is not currently open. Use simplier method */
+ if (read_data(devc) == MPU_ACK)
+ ok = 1;
+ }
- if (cmd->nr_args)
- for (i = 0; i < cmd->nr_args; i++)
- {
- for (timeout = 30000; timeout > 0 && !output_ready (devc->base); timeout--);
-
- if (!mpu401_out (dev, cmd->data[i]))
- {
- RESTORE_INTR (flags);
- printk ("MPU: Command (0x%x), parm send failed.\n", (int) cmd->cmd);
- return RET_ERROR (EIO);
- }
- }
-
- ret = 0;
- cmd->data[0] = 0;
-
- if (cmd->nr_returns)
- for (i = 0; i < cmd->nr_returns; i++)
- {
- ok = 0;
- for (timeout = 5000; timeout > 0 && !ok; timeout--)
- if (input_avail (devc->base))
- {
- cmd->data[i] = read_data (devc->base);
- ok = 1;
+ if (!ok) {
+ splx(flags);
+ /* printf ("MPU: No ACK to command (0x%x)\n", (int) cmd->cmd); */
+ return -(EIO);
+ }
+ if (cmd->nr_args)
+ for (i = 0; i < cmd->nr_args; i++) {
+ for (timeout = 3000; timeout > 0 && !output_ready(devc); timeout--);
+ if (!mpu401_out(dev, cmd->data[i])) {
+ splx(flags);
+ printf("MPU: Command (0x%x), parm send failed.\n", (int) cmd->cmd);
+ return -(EIO);
}
+ }
- if (!ok)
- {
- RESTORE_INTR (flags);
- printk ("MPU: No response(%d) to command (0x%x)\n", i, (int) cmd->cmd);
- return RET_ERROR (EIO);
- }
- }
+ ret = 0;
+ cmd->data[0] = 0;
+
+ if (cmd->nr_returns)
+ for (i = 0; i < cmd->nr_returns; i++) {
+ ok = 0;
+ for (timeout = 5000; timeout > 0 && !ok; timeout--)
+ if (input_avail(devc)) {
+ cmd->data[i] = read_data(devc);
+ ok = 1;
+ }
+ if (!ok) {
+ splx(flags);
+ /* printf ("MPU: No response(%d) to command (0x%x)\n",
+ * i, (int) cmd->cmd);
+ */
+ return -(EIO);
+ }
+ }
- RESTORE_INTR (flags);
+ splx(flags);
- return ret;
+ return ret;
}
static int
-exec_cmd (int dev, int cmd, int data)
+mpu_cmd(int dev, int cmd, int data)
{
- int ret;
+ int ret;
- static mpu_command_rec rec;
+ static mpu_command_rec rec;
- rec.cmd = cmd & 0xff;
- rec.nr_args = ((cmd & 0xf0) == 0xE0);
- rec.nr_returns = ((cmd & 0xf0) == 0xA0);
- rec.data[0] = data & 0xff;
+ rec.cmd = cmd & 0xff;
+ rec.nr_args = ((cmd & 0xf0) == 0xE0);
+ rec.nr_returns = ((cmd & 0xf0) == 0xA0);
+ rec.data[0] = data & 0xff;
- if ((ret = mpu401_command (dev, &rec)) < 0)
- return ret;
- return (unsigned char) rec.data[0];
+ if ((ret = mpu401_command(dev, &rec)) < 0) {
+ return ret;
+ }
+ return (u_char) rec.data[0];
}
static int
-mpu401_prefix_cmd (int dev, unsigned char status)
+mpu401_prefix_cmd(int dev, u_char status)
{
- struct mpu_config *devc = &dev_conf[dev];
-
- if (devc->uart_mode)
- return 1;
+ struct mpu_config *devc = &dev_conf[dev];
- if (status < 0xf0)
- {
- if (exec_cmd (dev, 0xD0, 0) < 0)
- return 0;
-
- return 1;
- }
-
- switch (status)
- {
- case 0xF0:
- if (exec_cmd (dev, 0xDF, 0) < 0)
- return 0;
+ if (devc->uart_mode)
+ return 1;
- return 1;
- break;
+ if (status < 0xf0) {
+ if (mpu_cmd(dev, 0xD0, 0) < 0) {
+ return 0;
+ }
+ return 1;
+ }
+ switch (status) {
+ case 0xF0:
+ if (mpu_cmd(dev, 0xDF, 0) < 0) {
+ return 0;
+ }
+ return 1;
+ break;
- default:
- return 0;
- }
+ default:
+ return 0;
+ }
- return 0;
}
static int
-mpu401_start_read (int dev)
+mpu401_start_read(int dev)
{
- return 0;
+ return 0;
}
static int
-mpu401_end_read (int dev)
+mpu401_end_read(int dev)
{
- return 0;
+ return 0;
}
static int
-mpu401_ioctl (int dev, unsigned cmd, unsigned arg)
+mpu401_ioctl(int dev, u_int cmd, ioctl_arg arg)
{
- struct mpu_config *devc;
+ struct mpu_config *devc;
- devc = &dev_conf[dev];
+ devc = &dev_conf[dev];
- switch (cmd)
- {
+ switch (cmd) {
case 1:
- IOCTL_FROM_USER ((char *) &init_sequence, (char *) arg, 0, sizeof (init_sequence));
- return 0;
- break;
+ bcopy(&(((char *) arg)[0]), (char *) init_sequence, sizeof(init_sequence));
+ return 0;
+ break;
case SNDCTL_MIDI_MPUMODE:
- if (devc->version == 0)
- {
- printk ("MPU-401: Intelligent mode not supported by the HW\n");
- return RET_ERROR (EINVAL);
+ if (!(devc->capabilities & MPU_CAP_INTLG)) { /* No intelligent mode */
+ printf("MPU-401: Intelligent mode not supported by the HW\n");
+ return -(EINVAL);
}
- set_uart_mode (dev, devc, !IOCTL_IN (arg));
- return 0;
- break;
+ set_uart_mode(dev, devc, !(*(int *) arg));
+ return 0;
+ break;
case SNDCTL_MIDI_MPUCMD:
- {
- int ret;
- mpu_command_rec rec;
-
- IOCTL_FROM_USER ((char *) &rec, (char *) arg, 0, sizeof (rec));
+ {
+ int ret;
+ mpu_command_rec rec;
- if ((ret = mpu401_command (dev, &rec)) < 0)
- return ret;
+ bcopy(&(((char *) arg)[0]), (char *) &rec, sizeof(rec));
- IOCTL_TO_USER ((char *) arg, 0, (char *) &rec, sizeof (rec));
- return 0;
- }
- break;
+ if ((ret = mpu401_command(dev, &rec)) < 0)
+ return ret;
+ bcopy((char *) &rec, &(((char *) arg)[0]), sizeof(rec));
+ return 0;
+ }
+ break;
default:
- return RET_ERROR (EINVAL);
+ return -(EINVAL);
}
}
static void
-mpu401_kick (int dev)
+mpu401_kick(int dev)
{
}
static int
-mpu401_buffer_status (int dev)
+mpu401_buffer_status(int dev)
{
- return 0; /*
- * No data in buffers
- */
+ return 0; /* No data in buffers */
}
static int
-mpu_synth_ioctl (int dev,
- unsigned int cmd, unsigned int arg)
+mpu_synth_ioctl(int dev,
+ u_int cmd, ioctl_arg arg)
{
- int midi_dev;
- struct mpu_config *devc;
+ int midi_dev;
+ struct mpu_config *devc;
- midi_dev = synth_devs[dev]->midi_dev;
+ midi_dev = synth_devs[dev]->midi_dev;
- if (midi_dev < 0 || midi_dev > num_midis)
- return RET_ERROR (ENXIO);
+ if (midi_dev < 0 || midi_dev > num_midis)
+ return -(ENXIO);
- devc = &dev_conf[midi_dev];
+ devc = &dev_conf[midi_dev];
- switch (cmd)
- {
+ switch (cmd) {
case SNDCTL_SYNTH_INFO:
- IOCTL_TO_USER ((char *) arg, 0, &mpu_synth_info[midi_dev],
- sizeof (struct synth_info));
-
- return 0;
- break;
+ bcopy(&mpu_synth_info[midi_dev], &(((char *) arg)[0]), sizeof(struct synth_info));
+ return 0;
+ break;
case SNDCTL_SYNTH_MEMAVL:
- return 0x7fffffff;
- break;
+ return 0x7fffffff;
+ break;
default:
- return RET_ERROR (EINVAL);
+ return -(EINVAL);
}
}
static int
-mpu_synth_open (int dev, int mode)
+mpu_synth_open(int dev, int mode)
{
- int midi_dev, err;
- struct mpu_config *devc;
+ int midi_dev, err;
+ struct mpu_config *devc;
- midi_dev = synth_devs[dev]->midi_dev;
+ midi_dev = synth_devs[dev]->midi_dev;
- if (midi_dev < 0 || midi_dev > num_midis)
- return RET_ERROR (ENXIO);
-
- devc = &dev_conf[midi_dev];
-
- if (devc->opened)
- {
- printk ("MPU-401: Midi busy\n");
- return RET_ERROR (EBUSY);
+ if (midi_dev < 0 || midi_dev > num_midis) {
+ return -(ENXIO);
+ }
+ devc = &dev_conf[midi_dev];
+
+ /*
+ * Verify that the device is really running. Some devices (such as
+ * Ensoniq SoundScape don't work before the on board processor (OBP)
+ * is initialized by downloadin it's microcode.
+ */
+
+ if (!devc->initialized) {
+ if (mpu401_status(devc) == 0xff) { /* Bus float */
+ printf("MPU-401: Device not initialized properly\n");
+ return -(EIO);
+ }
+ reset_mpu401(devc);
}
+ if (devc->opened) {
+ printf("MPU-401: Midi busy\n");
+ return -(EBUSY);
+ }
+ devc->mode = MODE_SYNTH;
+ devc->synthno = dev;
- devc->opened = mode;
- devc->mode = MODE_SYNTH;
- devc->synthno = dev;
+ devc->inputintr = NULL;
+ irq2dev[devc->irq] = midi_dev;
- devc->inputintr = NULL;
- irq2dev[devc->irq] = midi_dev;
- if ((err = snd_set_irq_handler (devc->irq, mpuintr) < 0))
- return err;
+ if (midi_devs[midi_dev]->coproc)
+ if ((err = midi_devs[midi_dev]->coproc->
+ open(midi_devs[midi_dev]->coproc->devc, COPR_MIDI)) < 0) {
+ printf("MPU-401: Can't access coprocessor device\n");
- reset_mpu401 (devc);
+ return err;
+ }
+ devc->opened = mode;
+ reset_mpu401(devc);
- if (mode & OPEN_READ)
- {
- exec_cmd (midi_dev, 0x34, 0); /* Return timing bytes in stop mode */
- exec_cmd (midi_dev, 0x8B, 0); /* Enable data in stop mode */
+ if (mode & OPEN_READ) {
+ mpu_cmd(midi_dev, 0x8B, 0); /* Enable data in stop mode */
+ mpu_cmd(midi_dev, 0x34, 0); /* Return timing bytes in stop mode */
}
-
- return 0;
+ return 0;
}
static void
-mpu_synth_close (int dev)
+mpu_synth_close(int dev)
{
- int midi_dev;
- struct mpu_config *devc;
+ int midi_dev;
+ struct mpu_config *devc;
- midi_dev = synth_devs[dev]->midi_dev;
+ midi_dev = synth_devs[dev]->midi_dev;
- devc = &dev_conf[midi_dev];
- exec_cmd (midi_dev, 0x15, 0); /* Stop recording, playback and MIDI */
- exec_cmd (midi_dev, 0x8a, 0); /* Disable data in stopped mode */
+ devc = &dev_conf[midi_dev];
+ mpu_cmd(midi_dev, 0x15, 0); /* Stop recording, playback and MIDI */
+ mpu_cmd(midi_dev, 0x8a, 0); /* Disable data in stopped mode */
- devc->opened = 0;
- devc->mode = 0;
- snd_release_irq (devc->irq);
- devc->inputintr = NULL;
- irq2dev[devc->irq] = -1;
+ devc->inputintr = NULL;
+
+ if (midi_devs[midi_dev]->coproc)
+ midi_devs[midi_dev]->coproc->close(midi_devs[midi_dev]->coproc->devc, COPR_MIDI);
+ devc->opened = 0;
+ devc->mode = 0;
}
#define MIDI_SYNTH_NAME "MPU-401 UART Midi"
#define MIDI_SYNTH_CAPS SYNTH_CAP_INPUT
-#include "midi_synth.h"
+#include <i386/isa/sound/midi_synth.h>
static struct synth_operations mpu401_synth_proto =
{
- NULL,
- 0,
- SYNTH_TYPE_MIDI,
- 0,
- mpu_synth_open,
- mpu_synth_close,
- mpu_synth_ioctl,
- midi_synth_kill_note,
- midi_synth_start_note,
- midi_synth_set_instr,
- midi_synth_reset,
- midi_synth_hw_control,
- midi_synth_load_patch,
- midi_synth_aftertouch,
- midi_synth_controller,
- midi_synth_panning,
- NULL,
- midi_synth_patchmgr,
- midi_synth_bender
+ NULL,
+ 0,
+ SYNTH_TYPE_MIDI,
+ 0,
+ mpu_synth_open,
+ mpu_synth_close,
+ mpu_synth_ioctl,
+ midi_synth_kill_note,
+ midi_synth_start_note,
+ midi_synth_set_instr,
+ midi_synth_reset,
+ midi_synth_hw_control,
+ midi_synth_load_patch,
+ midi_synth_aftertouch,
+ midi_synth_controller,
+ midi_synth_panning,
+ NULL,
+ midi_synth_patchmgr,
+ midi_synth_bender,
+ NULL, /* alloc */
+ midi_synth_setup_voice,
+ midi_synth_send_sysex
};
-static struct synth_operations mpu401_synth_operations[MAX_MIDI_DEV];
+static struct synth_operations *mpu401_synth_operations[MAX_MIDI_DEV];
static struct midi_operations mpu401_midi_proto =
{
- {"MPU-401 Midi", 0, MIDI_CAP_MPU401, SNDCARD_MPU401},
- NULL,
- mpu401_open,
- mpu401_close,
- mpu401_ioctl,
- mpu401_out,
- mpu401_start_read,
- mpu401_end_read,
- mpu401_kick,
- NULL,
- mpu401_buffer_status,
- mpu401_prefix_cmd
+ {"MPU-401 Midi", 0, MIDI_CAP_MPU401, SNDCARD_MPU401},
+ NULL,
+ {0},
+ mpu401_open,
+ mpu401_close,
+ mpu401_ioctl,
+ mpu401_out,
+ mpu401_start_read,
+ mpu401_end_read,
+ mpu401_kick,
+ NULL,
+ mpu401_buffer_status,
+ mpu401_prefix_cmd
};
static struct midi_operations mpu401_midi_operations[MAX_MIDI_DEV];
static void
-mpu401_chk_version (struct mpu_config *devc)
+mpu401_chk_version(struct mpu_config * devc)
{
- int tmp;
+ int tmp;
- devc->version = devc->revision = 0;
+ devc->version = devc->revision = 0;
- if ((tmp = exec_cmd (num_midis, 0xAC, 0)) < 0)
- return;
- devc->version = tmp;
+ if ((tmp = mpu_cmd(num_midis, 0xAC, 0)) < 0)
+ return;
- if ((tmp = exec_cmd (num_midis, 0xAD, 0)) < 0)
- return;
- devc->revision = tmp;
-}
+ if ((tmp & 0xf0) > 0x20)/* Why it's larger than 2.x ??? */
+ return;
-long
-attach_mpu401 (long mem_start, struct address_info *hw_config)
-{
- int i;
- unsigned long flags;
- char revision_char;
+ devc->version = tmp;
- struct mpu_config *devc;
+ if ((tmp = mpu_cmd(num_midis, 0xAD, 0)) < 0) {
+ devc->version = 0;
+ return;
+ }
+ devc->revision = tmp;
+}
- for (i = 0; i < 16; i++)
- irq2dev[i] = -1;
+void
+attach_mpu401(struct address_info * hw_config)
+{
+ u_long flags;
+ char revision_char;
- if (num_midis >= MAX_MIDI_DEV)
- {
- printk ("MPU-401: Too many midi devices detected\n");
- return mem_start;
- }
+ struct mpu_config *devc;
- devc = &dev_conf[num_midis];
-
- devc->base = hw_config->io_base;
- devc->irq = hw_config->irq;
- devc->opened = 0;
- devc->uart_mode = 0;
- devc->initialized = 0;
- devc->version = 0;
- devc->revision = 0;
- devc->capabilities = 0;
- devc->timer_flag = 0;
- devc->m_busy = 0;
- devc->m_state = ST_INIT;
-
- for (i = 0; i < 32; i++)
- devc->controls[i] = 0x2000;
-
- if (!reset_mpu401 (devc))
- return mem_start;
-
- DISABLE_INTR (flags);
- mpu401_chk_version (devc);
- if (devc->version == 0)
- mpu401_chk_version (devc);
- RESTORE_INTR (flags);
-
- if (devc->version == 0)
- {
- memcpy ((char *) &mpu401_synth_operations[num_midis],
- (char *) &std_midi_synth,
- sizeof (struct synth_operations));
+ if (num_midis >= MAX_MIDI_DEV) {
+ printf("MPU-401: Too many midi devices detected\n");
+ return ;
}
- else
- {
- devc->capabilities |= MPU_CAP_INTLG; /* Supports intelligent mode */
- memcpy ((char *) &mpu401_synth_operations[num_midis],
- (char *) &mpu401_synth_proto,
- sizeof (struct synth_operations));
+ devc = &dev_conf[num_midis];
+
+ devc->base = hw_config->io_base;
+ devc->osp = hw_config->osp;
+ devc->irq = hw_config->irq;
+ devc->opened = 0;
+ devc->uart_mode = 0;
+ devc->initialized = 0;
+ devc->version = 0;
+ devc->revision = 0;
+ devc->capabilities = 0;
+ devc->timer_flag = 0;
+ devc->m_busy = 0;
+ devc->m_state = ST_INIT;
+ devc->shared_irq = hw_config->always_detect;
+ devc->irq = hw_config->irq;
+
+ if (devc->irq < 0) {
+ devc->irq *= -1;
+ devc->shared_irq = 1;
}
+ irq2dev[devc->irq] = num_midis;
- memcpy ((char *) &mpu401_midi_operations[num_midis],
- (char *) &mpu401_midi_proto,
- sizeof (struct midi_operations));
+ if (!hw_config->always_detect) {
+ /* Verify the hardware again */
+ if (!reset_mpu401(devc))
+ return ;
- mpu401_midi_operations[num_midis].converter =
- &mpu401_synth_operations[num_midis];
+ if (!devc->shared_irq)
+ if (snd_set_irq_handler(devc->irq, mpuintr, devc->osp) < 0) {
+ return ;
+ }
+ flags = splhigh();
+ mpu401_chk_version(devc);
+ if (devc->version == 0)
+ mpu401_chk_version(devc);
+ splx(flags);
+ };
+
+ if (devc->version != 0)
+ if (mpu_cmd(num_midis, 0xC5, 0) >= 0) /* Set timebase OK */
+ if (mpu_cmd(num_midis, 0xE0, 120) >= 0) /* Set tempo OK */
+ devc->capabilities |= MPU_CAP_INTLG; /* Supports intelligent
+ * mode */
+
+ mpu401_synth_operations[num_midis] = (struct synth_operations *) malloc(sizeof(struct synth_operations), M_DEVBUF, M_NOWAIT);
+
+ if (!mpu401_synth_operations[num_midis])
+ panic("SOUND: Cannot allocate memory\n");
+
+ if (mpu401_synth_operations[num_midis] == NULL) {
+ printf("mpu401: Can't allocate memory\n");
+ return ;
+ }
+ if (!(devc->capabilities & MPU_CAP_INTLG)) { /* No intelligent mode */
+ bcopy((char *) &std_midi_synth, (char *) mpu401_synth_operations[num_midis], sizeof(struct synth_operations));
+ } else {
+ bcopy((char *) &mpu401_synth_proto, (char *) mpu401_synth_operations[num_midis], sizeof(struct synth_operations));
+ }
- memcpy ((char *) &mpu_synth_info[num_midis],
- (char *) &mpu_synth_info_proto,
- sizeof (struct synth_info));
+ bcopy((char *) &mpu401_midi_proto, (char *) &mpu401_midi_operations[num_midis], sizeof(struct midi_operations));
- n_mpu_devs++;
+ mpu401_midi_operations[num_midis].converter =
+ mpu401_synth_operations[num_midis];
- if (devc->version == 0x20 && devc->revision >= 0x07) /* MusicQuest interface */
- {
- int ports = (devc->revision & 0x08) ? 32 : 16;
+ bcopy((char *) &mpu_synth_info_proto, (char *) &mpu_synth_info[num_midis], sizeof(struct synth_info));
- devc->capabilities |= MPU_CAP_SYNC | MPU_CAP_SMPTE |
- MPU_CAP_CLS | MPU_CAP_2PORT;
+ n_mpu_devs++;
- revision_char = (devc->revision == 0x7f) ? 'M' : ' ';
- printk (" <MQX-%d%c MIDI Interface>",
- ports,
- revision_char);
-#ifndef SCO
- sprintf (mpu_synth_info[num_midis].name,
- "MQX-%d%c MIDI Interface #%d",
- ports,
- revision_char,
- n_mpu_devs);
-#endif
- }
- else
- {
-
- revision_char = devc->revision ? devc->revision + '@' : ' ';
- if (devc->revision > ('Z' - '@'))
- revision_char = '+';
-
- devc->capabilities |= MPU_CAP_SYNC | MPU_CAP_FSK;
-
- printk (" <MPU-401 MIDI Interface %d.%d%c>",
- (devc->version & 0xf0) >> 4,
- devc->version & 0x0f,
- revision_char);
-#ifndef SCO
- sprintf (mpu_synth_info[num_midis].name,
- "MPU-401 %d.%d%c Midi interface #%d",
- (devc->version & 0xf0) >> 4,
- devc->version & 0x0f,
- revision_char,
- n_mpu_devs);
-#endif
- }
+ if (devc->version == 0x20 && devc->revision >= 0x07) { /* MusicQuest interface */
+ int ports = (devc->revision & 0x08) ? 32 : 16;
-#ifndef SCO
- strcpy (mpu401_midi_operations[num_midis].info.name,
- mpu_synth_info[num_midis].name);
-#endif
+ devc->capabilities |= MPU_CAP_SYNC | MPU_CAP_SMPTE |
+ MPU_CAP_CLS | MPU_CAP_2PORT;
- mpu401_synth_operations[num_midis].midi_dev = devc->devno = num_midis;
- mpu401_synth_operations[devc->devno].info =
- &mpu_synth_info[devc->devno];
+ revision_char = (devc->revision == 0x7f) ? 'M' : ' ';
+ sprintf(mpu_synth_info[num_midis].name,
+ "MQX-%d%c MIDI Interface #%d",
+ ports,
+ revision_char,
+ n_mpu_devs);
+ } else {
- if (devc->capabilities & MPU_CAP_INTLG) /* Has timer */
- mpu_timer_init (num_midis);
+ revision_char = devc->revision ? devc->revision + '@' : ' ';
+ if ((int) devc->revision > ('Z' - '@'))
+ revision_char = '+';
- midi_devs[num_midis++] = &mpu401_midi_operations[devc->devno];
- return mem_start;
-}
+ devc->capabilities |= MPU_CAP_SYNC | MPU_CAP_FSK;
-static int
-reset_mpu401 (struct mpu_config *devc)
-{
- unsigned long flags;
- int ok, timeout, n;
- int timeout_limit;
-
- /*
- * Send the RESET command. Try again if no success at the first time.
- * (If the device is in the UART mode, it will not ack the reset cmd).
- */
+ sprintf(mpu_synth_info[num_midis].name,
+ "MPU-401 %d.%d%c Midi interface #%d",
+ (int) (devc->version & 0xf0) >> 4,
+ devc->version & 0x0f,
+ revision_char,
+ n_mpu_devs);
+ }
- ok = 0;
+ strcpy(mpu401_midi_operations[num_midis].info.name,
+ mpu_synth_info[num_midis].name);
- timeout_limit = devc->initialized ? 30000 : 100000;
- devc->initialized = 1;
+ conf_printf(mpu_synth_info[num_midis].name, hw_config);
- for (n = 0; n < 2 && !ok; n++)
- {
- for (timeout = timeout_limit; timeout > 0 && !ok; timeout--)
- ok = output_ready (devc->base);
+ mpu401_synth_operations[num_midis]->midi_dev = devc->devno = num_midis;
+ mpu401_synth_operations[devc->devno]->info =
+ &mpu_synth_info[devc->devno];
- write_command (devc->base, MPU_RESET); /*
- * Send MPU-401 RESET Command
- */
+ if (devc->capabilities & MPU_CAP_INTLG) /* Intelligent mode */
+ mpu_timer_init(num_midis);
- /*
- * Wait at least 25 msec. This method is not accurate so let's make the
- * loop bit longer. Cannot sleep since this is called during boot.
- */
+ irq2dev[devc->irq] = num_midis;
+ midi_devs[num_midis++] = &mpu401_midi_operations[devc->devno];
+ return ;
+}
- for (timeout = timeout_limit * 2; timeout > 0 && !ok; timeout--)
- {
- DISABLE_INTR (flags);
- if (input_avail (devc->base))
- if (read_data (devc->base) == MPU_ACK)
- ok = 1;
- RESTORE_INTR (flags);
+static int
+reset_mpu401(struct mpu_config * devc)
+{
+ u_long flags;
+ int ok, timeout, n;
+ int timeout_limit;
+
+ /*
+ * Send the RESET command. Try again if no success at the first time.
+ * (If the device is in the UART mode, it will not ack the reset
+ * cmd).
+ */
+
+ ok = 0;
+
+ timeout_limit = devc->initialized ? 30000 : 100000;
+ devc->initialized = 1;
+
+ for (n = 0; n < 2 && !ok; n++) {
+ for (timeout = timeout_limit; timeout > 0 && !ok; timeout--)
+ ok = output_ready(devc);
+
+ write_command(devc, MPU_RESET); /* Send MPU-401 RESET Command */
+
+ /*
+ * Wait at least 25 msec. This method is not accurate so
+ * let's make the loop bit longer. Cannot sleep since this is
+ * called during boot.
+ */
+
+ for (timeout = timeout_limit * 2; timeout > 0 && !ok; timeout--) {
+ flags = splhigh();
+ if ( (input_avail(devc)) && (read_data(devc) == MPU_ACK) )
+ ok = 1;
+ splx(flags);
}
}
- devc->m_state = ST_INIT;
- devc->m_ptr = 0;
- devc->m_left = 0;
- devc->last_status = 0;
- devc->uart_mode = 0;
+ devc->m_state = ST_INIT;
+ devc->m_ptr = 0;
+ devc->m_left = 0;
+ devc->last_status = 0;
+ devc->uart_mode = 0;
- return ok;
+ return ok;
}
static void
-set_uart_mode (int dev, struct mpu_config *devc, int arg)
+set_uart_mode(int dev, struct mpu_config * devc, int arg)
{
-
- if (!arg && devc->version == 0)
- return;
-
- if ((devc->uart_mode == 0) == (arg == 0))
- return; /* Already set */
-
- reset_mpu401 (devc); /* This exits the uart mode */
-
- if (arg)
- {
- if (exec_cmd (dev, UART_MODE_ON, 0) < 0)
- {
- printk ("MPU%d: Can't enter UART mode\n", devc->devno);
- devc->uart_mode = 0;
- return;
- }
+ if (!arg && (devc->capabilities & MPU_CAP_INTLG))
+ return;
+ if ((devc->uart_mode == 0) == (arg == 0))
+ return; /* Already set */
+ reset_mpu401(devc); /* This exits the uart mode */
+
+ if (arg && (mpu_cmd(dev, UART_MODE_ON, 0) < 0) ) {
+ printf("MPU%d: Can't enter UART mode\n", devc->devno);
+ devc->uart_mode = 0;
+ return;
}
- devc->uart_mode = arg;
-
+ devc->uart_mode = arg;
}
int
-probe_mpu401 (struct address_info *hw_config)
+probe_mpu401(struct address_info * hw_config)
{
- int ok = 0;
- struct mpu_config tmp_devc;
+ int ok = 0;
+ struct mpu_config tmp_devc;
+
+ tmp_devc.base = hw_config->io_base;
+ tmp_devc.irq = hw_config->irq;
+ tmp_devc.initialized = 0;
+ tmp_devc.opened = 0;
+ tmp_devc.osp = hw_config->osp;
+
+#if defined(CONFIG_AEDSP16) && defined(AEDSP16_MPU401)
+ /*
+ * Initialize Audio Excel DSP 16 to MPU-401, before any operation.
+ */
+ InitAEDSP16_MPU401(hw_config);
+#endif
- tmp_devc.base = hw_config->io_base;
- tmp_devc.irq = hw_config->irq;
- tmp_devc.initialized = 0;
+ if (hw_config->always_detect)
+ return 1;
- ok = reset_mpu401 (&tmp_devc);
+ if (inb(hw_config->io_base + 1) == 0xff) {
+ DDB(printf("MPU401: Port %x looks dead.\n", hw_config->io_base));
+ return 0; /* Just bus float? */
+ }
+ ok = reset_mpu401(&tmp_devc);
- return ok;
+ if (!ok) {
+ DDB(printf("MPU401: Reset failed on port %x\n", hw_config->io_base));
+ }
+ return ok;
}
-/*****************************************************
+
+/*
* Timer stuff
- ****************************************************/
+ */
-#if !defined(EXCLUDE_SEQUENCER)
+#if defined(CONFIG_SEQUENCER)
static volatile int timer_initialized = 0, timer_open = 0, tmr_running = 0;
static volatile int curr_tempo, curr_timebase, hw_timebase;
static int max_timebase = 8; /* 8*24=192 ppqn */
-static volatile unsigned long next_event_time;
-static volatile unsigned long curr_ticks, curr_clocks;
-static unsigned long prev_event_time;
+static volatile u_long next_event_time;
+static volatile u_long curr_ticks, curr_clocks;
+static u_long prev_event_time;
static int metronome_mode;
-static unsigned long
-clocks2ticks (unsigned long clocks)
+static u_long
+clocks2ticks(u_long clocks)
{
- /*
- * The MPU-401 supports just a limited set of possible timebase values.
- * Since the applications require more choices, the driver has to
- * program the HW to do it's best and to convert between the HW and
- * actual timebases.
- */
-
- return ((clocks * curr_timebase) + (hw_timebase / 2)) / hw_timebase;
+ /*
+ * The MPU-401 supports just a limited set of possible timebase
+ * values. Since the applications require more choices, the driver
+ * has to program the HW to do it's best and to convert between the
+ * HW and actual timebases.
+ */
+
+ return ((clocks * curr_timebase) + (hw_timebase / 2)) / hw_timebase;
}
static void
-set_timebase (int midi_dev, int val)
+set_timebase(int midi_dev, int val)
{
- int hw_val;
-
- if (val < 48)
- val = 48;
- if (val > 1000)
- val = 1000;
-
- hw_val = val;
- hw_val = (hw_val + 23) / 24;
- if (hw_val > max_timebase)
- hw_val = max_timebase;
-
- if (exec_cmd (midi_dev, 0xC0 | (hw_val & 0x0f), 0) < 0)
- {
- printk ("MPU: Can't set HW timebase to %d\n", hw_val * 24);
- return;
- }
- hw_timebase = hw_val * 24;
- curr_timebase = val;
+ int hw_val;
+ if (val < 48)
+ val = 48;
+ if (val > 1000)
+ val = 1000;
+
+ hw_val = val;
+ hw_val = (hw_val + 12) / 24;
+ if (hw_val > max_timebase)
+ hw_val = max_timebase;
+
+ if (mpu_cmd(midi_dev, 0xC0 | (hw_val & 0x0f), 0) < 0) {
+ printf("MPU: Can't set HW timebase to %d\n", hw_val * 24);
+ return;
+ }
+ hw_timebase = hw_val * 24;
+ curr_timebase = val;
}
static void
-tmr_reset (void)
+tmr_reset(void)
{
- unsigned long flags;
+ u_long flags;
- DISABLE_INTR (flags);
- next_event_time = 0xffffffff;
- prev_event_time = 0;
- curr_ticks = curr_clocks = 0;
- RESTORE_INTR (flags);
+ flags = splhigh();
+ next_event_time = 0xffffffff;
+ prev_event_time = 0;
+ curr_ticks = curr_clocks = 0;
+ splx(flags);
}
static void
-set_timer_mode (int midi_dev)
+set_timer_mode(int midi_dev)
{
- if (timer_mode & TMR_MODE_CLS)
- exec_cmd (midi_dev, 0x3c, 0); /* Use CLS sync */
- else if (timer_mode & TMR_MODE_SMPTE)
- exec_cmd (midi_dev, 0x3d, 0); /* Use SMPTE sync */
-
- if (timer_mode & TMR_INTERNAL)
- {
- exec_cmd (midi_dev, 0x80, 0); /* Use MIDI sync */
- }
- else
- {
- if (timer_mode & (TMR_MODE_MIDI | TMR_MODE_CLS))
- {
- exec_cmd (midi_dev, 0x82, 0); /* Use MIDI sync */
- exec_cmd (midi_dev, 0x91, 0); /* Enable ext MIDI ctrl */
- }
- else if (timer_mode & TMR_MODE_FSK)
- exec_cmd (midi_dev, 0x81, 0); /* Use FSK sync */
+ if (timer_mode & TMR_MODE_CLS)
+ mpu_cmd(midi_dev, 0x3c, 0); /* Use CLS sync */
+ else if (timer_mode & TMR_MODE_SMPTE)
+ mpu_cmd(midi_dev, 0x3d, 0); /* Use SMPTE sync */
+
+ if (timer_mode & TMR_INTERNAL)
+ mpu_cmd(midi_dev, 0x80, 0); /* Use MIDI sync */
+ else {
+ if (timer_mode & (TMR_MODE_MIDI | TMR_MODE_CLS)) {
+ mpu_cmd(midi_dev, 0x82, 0); /* Use MIDI sync */
+ mpu_cmd(midi_dev, 0x91, 0); /* Enable ext MIDI ctrl */
+ } else if (timer_mode & TMR_MODE_FSK)
+ mpu_cmd(midi_dev, 0x81, 0); /* Use FSK sync */
}
}
static void
-stop_metronome (int midi_dev)
+stop_metronome(int midi_dev)
{
- exec_cmd (midi_dev, 0x84, 0); /* Disable metronome */
+ mpu_cmd(midi_dev, 0x84, 0); /* Disable metronome */
}
static void
-setup_metronome (int midi_dev)
+setup_metronome(int midi_dev)
{
- int numerator, denominator;
- int clks_per_click, num_32nds_per_beat;
- int beats_per_measure;
-
- numerator = ((unsigned) metronome_mode >> 24) & 0xff;
- denominator = ((unsigned) metronome_mode >> 16) & 0xff;
- clks_per_click = ((unsigned) metronome_mode >> 8) & 0xff;
- num_32nds_per_beat = (unsigned) metronome_mode & 0xff;
- beats_per_measure = (numerator * 4) >> denominator;
-
- if (!metronome_mode)
- exec_cmd (midi_dev, 0x84, 0); /* Disable metronome */
- else
- {
- exec_cmd (midi_dev, 0xE4, clks_per_click);
- exec_cmd (midi_dev, 0xE6, beats_per_measure);
- exec_cmd (midi_dev, 0x83, 0); /* Enable metronome without accents */
+ int numerator, denominator;
+ int clks_per_click, num_32nds_per_beat;
+ int beats_per_measure;
+
+ numerator = ((u_int) metronome_mode >> 24) & 0xff;
+ denominator = ((u_int) metronome_mode >> 16) & 0xff;
+ clks_per_click = ((u_int) metronome_mode >> 8) & 0xff;
+ num_32nds_per_beat = (u_int) metronome_mode & 0xff;
+ beats_per_measure = (numerator * 4) >> denominator;
+
+ if (!metronome_mode)
+ mpu_cmd(midi_dev, 0x84, 0); /* Disable metronome */
+ else {
+ mpu_cmd(midi_dev, 0xE4, clks_per_click);
+ mpu_cmd(midi_dev, 0xE6, beats_per_measure);
+ mpu_cmd(midi_dev, 0x83, 0); /* Enable metronome without
+ * accents */
}
}
static int
-start_timer (int midi_dev)
+mpu_start_timer(int midi_dev)
{
- tmr_reset ();
- set_timer_mode (midi_dev);
-
- if (tmr_running)
- return TIMER_NOT_ARMED; /* Already running */
-
- if (timer_mode & TMR_INTERNAL)
- {
- exec_cmd (midi_dev, 0x02, 0); /* Send MIDI start */
- tmr_running = 1;
- return TIMER_NOT_ARMED;
- }
- else
- {
- exec_cmd (midi_dev, 0x35, 0); /* Enable mode messages to PC */
- exec_cmd (midi_dev, 0x38, 0); /* Enable sys common messages to PC */
- exec_cmd (midi_dev, 0x39, 0); /* Enable real time messages to PC */
- exec_cmd (midi_dev, 0x97, 0); /* Enable system exclusive messages to PC */
+ tmr_reset();
+ set_timer_mode(midi_dev);
+
+ if (tmr_running)
+ return TIMER_NOT_ARMED; /* Already running */
+
+ if (timer_mode & TMR_INTERNAL) {
+ mpu_cmd(midi_dev, 0x02, 0); /* Send MIDI start */
+ tmr_running = 1;
+ return TIMER_NOT_ARMED;
+ } else {
+ mpu_cmd(midi_dev, 0x35, 0); /* Enable mode messages to PC */
+ mpu_cmd(midi_dev, 0x38, 0); /* Enable sys common messages to PC */
+ mpu_cmd(midi_dev, 0x39, 0); /* Enable real time messages to PC */
+ mpu_cmd(midi_dev, 0x97, 0); /* Enable system exclusive
+ * messages to PC */
}
- return TIMER_ARMED;
+ return TIMER_ARMED;
}
static int
-mpu_timer_open (int dev, int mode)
+mpu_timer_open(int dev, int mode)
{
- int midi_dev = sound_timer_devs[dev]->devlink;
+ int midi_dev = sound_timer_devs[dev]->devlink;
- if (timer_open)
- return RET_ERROR (EBUSY);
+ if (timer_open)
+ return -(EBUSY);
- tmr_reset ();
- curr_tempo = 50;
- exec_cmd (midi_dev, 0xE0, 50);
- curr_timebase = hw_timebase = 120;
- set_timebase (midi_dev, 120);
- timer_open = 1;
- metronome_mode = 0;
- set_timer_mode (midi_dev);
+ tmr_reset();
+ curr_tempo = 50;
+ mpu_cmd(midi_dev, 0xE0, 50);
+ curr_timebase = hw_timebase = 120;
+ set_timebase(midi_dev, 120);
+ timer_open = 1;
+ metronome_mode = 0;
+ set_timer_mode(midi_dev);
- exec_cmd (midi_dev, 0xe7, 0x04); /* Send all clocks to host */
- exec_cmd (midi_dev, 0x95, 0); /* Enable clock to host */
+ mpu_cmd(midi_dev, 0xe7, 0x04); /* Send all clocks to host */
+ mpu_cmd(midi_dev, 0x95, 0); /* Enable clock to host */
- return 0;
+ return 0;
}
static void
-mpu_timer_close (int dev)
+mpu_timer_close(int dev)
{
- int midi_dev = sound_timer_devs[dev]->devlink;
-
- timer_open = tmr_running = 0;
- exec_cmd (midi_dev, 0x15, 0); /* Stop all */
- exec_cmd (midi_dev, 0x94, 0); /* Disable clock to host */
- exec_cmd (midi_dev, 0x8c, 0); /* Disable measure end messages to host */
- stop_metronome (midi_dev);
+ int midi_dev = sound_timer_devs[dev]->devlink;
+
+ timer_open = tmr_running = 0;
+ mpu_cmd(midi_dev, 0x15, 0); /* Stop all */
+ mpu_cmd(midi_dev, 0x94, 0); /* Disable clock to host */
+ mpu_cmd(midi_dev, 0x8c, 0); /* Disable measure end messages to
+ * host */
+ stop_metronome(midi_dev);
}
static int
-mpu_timer_event (int dev, unsigned char *event)
+mpu_timer_event(int dev, u_char *event)
{
- unsigned char command = event[1];
- unsigned long parm = *(unsigned int *) &event[4];
- int midi_dev = sound_timer_devs[dev]->devlink;
+ u_char command = event[1];
+ u_long parm = *(u_int *) &event[4];
+ int midi_dev = sound_timer_devs[dev]->devlink;
- switch (command)
- {
+ switch (command) {
case TMR_WAIT_REL:
- parm += prev_event_time;
+ parm += prev_event_time;
case TMR_WAIT_ABS:
- if (parm > 0)
- {
- long time;
+ if (parm > 0) {
+ long time;
- if (parm <= curr_ticks) /* It's the time */
- return TIMER_NOT_ARMED;
+ if (parm <= curr_ticks) /* It's the time */
+ return TIMER_NOT_ARMED;
- time = parm;
- next_event_time = prev_event_time = time;
+ time = parm;
+ next_event_time = prev_event_time = time;
- return TIMER_ARMED;
+ return TIMER_ARMED;
}
- break;
+ break;
case TMR_START:
- if (tmr_running)
+ if (tmr_running)
+ break;
+ return mpu_start_timer(midi_dev);
break;
- return start_timer (midi_dev);
- break;
case TMR_STOP:
- exec_cmd (midi_dev, 0x01, 0); /* Send MIDI stop */
- stop_metronome (midi_dev);
- tmr_running = 0;
- break;
+ mpu_cmd(midi_dev, 0x01, 0); /* Send MIDI stop */
+ stop_metronome(midi_dev);
+ tmr_running = 0;
+ break;
case TMR_CONTINUE:
- if (tmr_running)
+ if (tmr_running)
+ break;
+ mpu_cmd(midi_dev, 0x03, 0); /* Send MIDI continue */
+ setup_metronome(midi_dev);
+ tmr_running = 1;
break;
- exec_cmd (midi_dev, 0x03, 0); /* Send MIDI continue */
- setup_metronome (midi_dev);
- tmr_running = 1;
- break;
case TMR_TEMPO:
- if (parm)
- {
- if (parm < 8)
- parm = 8;
- if (parm > 250)
- parm = 250;
-
- if (exec_cmd (midi_dev, 0xE0, parm) < 0)
- printk ("MPU: Can't set tempo to %d\n", (int) parm);
- curr_tempo = parm;
+ if (parm) {
+ if (parm < 8)
+ parm = 8;
+ if (parm > 250)
+ parm = 250;
+
+ if (mpu_cmd(midi_dev, 0xE0, parm) < 0)
+ printf("MPU: Can't set tempo to %d\n", (int) parm);
+ curr_tempo = parm;
}
- break;
+ break;
case TMR_ECHO:
- seq_copy_to_input (event, 8);
- break;
+ seq_copy_to_input(event, 8);
+ break;
case TMR_TIMESIG:
- if (metronome_mode) /* Metronome enabled */
- {
- metronome_mode = parm;
- setup_metronome (midi_dev);
+ if (metronome_mode) { /* Metronome enabled */
+ metronome_mode = parm;
+ setup_metronome(midi_dev);
}
- break;
+ break;
default:;
}
- return TIMER_NOT_ARMED;
+ return TIMER_NOT_ARMED;
}
-static unsigned long
-mpu_timer_get_time (int dev)
+static u_long
+mpu_timer_get_time(int dev)
{
- if (!timer_open)
- return 0;
+ if (!timer_open)
+ return 0;
- return curr_ticks;
+ return curr_ticks;
}
static int
-mpu_timer_ioctl (int dev,
- unsigned int command, unsigned int arg)
+mpu_timer_ioctl(int dev, u_int command, ioctl_arg arg)
{
- int midi_dev = sound_timer_devs[dev]->devlink;
+ int midi_dev = sound_timer_devs[dev]->devlink;
- switch (command)
- {
+ switch (command) {
case SNDCTL_TMR_SOURCE:
- {
- int parm = IOCTL_IN (arg) & timer_caps;
-
- if (parm != 0)
- {
- timer_mode = parm;
+ {
+ int parm = (int) (*(int *) arg) & timer_caps;
- if (timer_mode & TMR_MODE_CLS)
- exec_cmd (midi_dev, 0x3c, 0); /* Use CLS sync */
- else if (timer_mode & TMR_MODE_SMPTE)
- exec_cmd (midi_dev, 0x3d, 0); /* Use SMPTE sync */
- }
+ if (parm != 0) {
+ timer_mode = parm;
- return IOCTL_OUT (arg, timer_mode);
- }
- break;
+ if (timer_mode & TMR_MODE_CLS)
+ mpu_cmd(midi_dev, 0x3c, 0); /* Use CLS sync */
+ else if (timer_mode & TMR_MODE_SMPTE)
+ mpu_cmd(midi_dev, 0x3d, 0); /* Use SMPTE sync */
+ }
+ return *(int *) arg = timer_mode;
+ }
+ break;
case SNDCTL_TMR_START:
- if (tmr_running)
+ mpu_start_timer(midi_dev);
return 0;
- start_timer (midi_dev);
- return 0;
- break;
+ break;
case SNDCTL_TMR_STOP:
- tmr_running = 0;
- exec_cmd (midi_dev, 0x01, 0); /* Send MIDI stop */
- stop_metronome (midi_dev);
- return 0;
- break;
+ tmr_running = 0;
+ mpu_cmd(midi_dev, 0x01, 0); /* Send MIDI stop */
+ stop_metronome(midi_dev);
+ return 0;
+ break;
case SNDCTL_TMR_CONTINUE:
- if (tmr_running)
+ if (tmr_running)
+ return 0;
+ tmr_running = 1;
+ mpu_cmd(midi_dev, 0x03, 0); /* Send MIDI continue */
return 0;
- tmr_running = 1;
- exec_cmd (midi_dev, 0x03, 0); /* Send MIDI continue */
- return 0;
- break;
+ break;
case SNDCTL_TMR_TIMEBASE:
- {
- int val = IOCTL_IN (arg);
+ {
+ int val = (int) (*(int *) arg);
- if (val)
- set_timebase (midi_dev, val);
+ if (val)
+ set_timebase(midi_dev, val);
- return IOCTL_OUT (arg, curr_timebase);
- }
- break;
+ return *(int *) arg = curr_timebase;
+ }
+ break;
case SNDCTL_TMR_TEMPO:
- {
- int val = IOCTL_IN (arg);
- int ret;
-
- if (val)
- {
- if (val < 8)
- val = 8;
- if (val > 250)
- val = 250;
- if ((ret = exec_cmd (midi_dev, 0xE0, val)) < 0)
- {
- printk ("MPU: Can't set tempo to %d\n", (int) val);
- return ret;
- }
-
- curr_tempo = val;
- }
-
- return IOCTL_OUT (arg, curr_tempo);
- }
- break;
+ {
+ int val = (int) (*(int *) arg);
+ int ret;
+
+ if (val) {
+ RANGE (val, 8 , 250 );
+ if ((ret = mpu_cmd(midi_dev, 0xE0, val)) < 0) {
+ printf("MPU: Can't set tempo to %d\n", (int) val);
+ return ret;
+ }
+ curr_tempo = val;
+ }
+ return *(int *) arg = curr_tempo;
+ }
+ break;
case SNDCTL_SEQ_CTRLRATE:
- if (IOCTL_IN (arg) != 0) /* Can't change */
- return RET_ERROR (EINVAL);
+ if ((*(int *) arg) != 0) /* Can't change */
+ return -(EINVAL);
- return IOCTL_OUT (arg, ((curr_tempo * curr_timebase) + 30) / 60);
- break;
+ return *(int *) arg = ((curr_tempo * curr_timebase) + 30) / 60;
+ break;
case SNDCTL_TMR_METRONOME:
- metronome_mode = IOCTL_IN (arg);
- setup_metronome (midi_dev);
- return 0;
- break;
+ metronome_mode = (int) (*(int *) arg);
+ setup_metronome(midi_dev);
+ return 0;
+ break;
- default:
+ default:;
}
- return RET_ERROR (EINVAL);
+ return -(EINVAL);
}
static void
-mpu_timer_arm (int dev, long time)
+mpu_timer_arm(int dev, long time)
{
- if (time < 0)
- time = curr_ticks + 1;
- else if (time <= curr_ticks) /* It's the time */
- return;
+ if (time < 0)
+ time = curr_ticks + 1;
+ else if (time <= curr_ticks) /* It's the time */
+ return;
- next_event_time = prev_event_time = time;
+ next_event_time = prev_event_time = time;
- return;
+ return;
}
static struct sound_timer_operations mpu_timer =
{
- {"MPU-401 Timer", 0},
- 10, /* Priority */
- 0, /* Local device link */
- mpu_timer_open,
- mpu_timer_close,
- mpu_timer_event,
- mpu_timer_get_time,
- mpu_timer_ioctl,
- mpu_timer_arm
+ {"MPU-401 Timer", 0},
+ 10, /* Priority */
+ 0, /* Local device link */
+ mpu_timer_open,
+ mpu_timer_close,
+ mpu_timer_event,
+ mpu_timer_get_time,
+ mpu_timer_ioctl,
+ mpu_timer_arm
};
static void
-mpu_timer_interrupt (void)
+mpu_timer_interrupt(void)
{
- if (!timer_open)
- return;
+ if (!timer_open)
+ return;
- if (!tmr_running)
- return;
+ if (!tmr_running)
+ return;
- curr_clocks++;
- curr_ticks = clocks2ticks (curr_clocks);
+ curr_clocks++;
+ curr_ticks = clocks2ticks(curr_clocks);
- if (curr_ticks >= next_event_time)
- {
- next_event_time = 0xffffffff;
- sequencer_timer ();
+ if (curr_ticks >= next_event_time) {
+ next_event_time = 0xffffffff;
+ sequencer_timer(0);
}
}
static void
-timer_ext_event (struct mpu_config *devc, int event, int parm)
+timer_ext_event(struct mpu_config * devc, int event, int parm)
{
- int midi_dev = devc->devno;
+ int midi_dev = devc->devno;
- if (!devc->timer_flag)
- return;
+ if (!devc->timer_flag)
+ return;
- switch (event)
- {
+ switch (event) {
case TMR_CLOCK:
- printk ("<MIDI clk>");
- break;
+ printf("<MIDI clk>");
+ break;
case TMR_START:
- printk ("Ext MIDI start\n");
- if (!tmr_running)
- if (timer_mode & TMR_EXTERNAL)
- {
- tmr_running = 1;
- setup_metronome (midi_dev);
- next_event_time = 0;
- STORE (SEQ_START_TIMER ());
- }
- break;
+ printf("Ext MIDI start\n");
+ if (!tmr_running)
+ if (timer_mode & TMR_EXTERNAL) {
+ tmr_running = 1;
+ setup_metronome(midi_dev);
+ next_event_time = 0;
+ STORE(SEQ_START_TIMER());
+ }
+ break;
case TMR_STOP:
- printk ("Ext MIDI stop\n");
- if (timer_mode & TMR_EXTERNAL)
- {
- tmr_running = 0;
- stop_metronome (midi_dev);
- STORE (SEQ_STOP_TIMER ());
+ printf("Ext MIDI stop\n");
+ if (timer_mode & TMR_EXTERNAL) {
+ tmr_running = 0;
+ stop_metronome(midi_dev);
+ STORE(SEQ_STOP_TIMER());
}
- break;
+ break;
case TMR_CONTINUE:
- printk ("Ext MIDI continue\n");
- if (timer_mode & TMR_EXTERNAL)
- {
- tmr_running = 1;
- setup_metronome (midi_dev);
- STORE (SEQ_CONTINUE_TIMER ());
+ printf("Ext MIDI continue\n");
+ if (timer_mode & TMR_EXTERNAL) {
+ tmr_running = 1;
+ setup_metronome(midi_dev);
+ STORE(SEQ_CONTINUE_TIMER());
}
- break;
+ break;
case TMR_SPP:
- printk ("Songpos: %d\n", parm);
- if (timer_mode & TMR_EXTERNAL)
- {
- STORE (SEQ_SONGPOS (parm));
+ printf("Songpos: %d\n", parm);
+ if (timer_mode & TMR_EXTERNAL) {
+ STORE(SEQ_SONGPOS(parm));
}
- break;
+ break;
}
}
static void
-mpu_timer_init (int midi_dev)
+mpu_timer_init(int midi_dev)
{
- struct mpu_config *devc;
- int n;
+ struct mpu_config *devc;
+ int n;
- devc = &dev_conf[midi_dev];
+ devc = &dev_conf[midi_dev];
- if (timer_initialized)
- return; /* There is already a similar timer */
+ if (timer_initialized)
+ return; /* There is already a similar timer */
- timer_initialized = 1;
+ timer_initialized = 1;
- mpu_timer.devlink = midi_dev;
- dev_conf[midi_dev].timer_flag = 1;
+ mpu_timer.devlink = midi_dev;
+ dev_conf[midi_dev].timer_flag = 1;
-#if 1
- if (num_sound_timers >= MAX_TIMER_DEV)
- n = 0; /* Overwrite the system timer */
- else
- n = num_sound_timers++;
-#else
- n = 0;
-#endif
- sound_timer_devs[n] = &mpu_timer;
-
- if (devc->version < 0x20) /* Original MPU-401 */
- timer_caps = TMR_INTERNAL | TMR_EXTERNAL | TMR_MODE_FSK | TMR_MODE_MIDI;
- else
- {
- /*
- * The version number 2.0 is used (at least) by the
- * MusicQuest cards and the Roland Super-MPU.
- *
- * MusicQuest has given a special meaning to the bits of the
- * revision number. The Super-MPU returns 0.
- */
-
- if (devc->revision)
- timer_caps |= TMR_EXTERNAL | TMR_MODE_MIDI;
-
- if (devc->revision & 0x02)
- timer_caps |= TMR_MODE_CLS;
-
-#if 0
- if (devc->revision & 0x04)
- timer_caps |= TMR_MODE_SMPTE;
-#endif
+ if (num_sound_timers >= MAX_TIMER_DEV)
+ n = 0; /* Overwrite the system timer */
+ else
+ n = num_sound_timers++;
+ sound_timer_devs[n] = &mpu_timer;
- if (devc->revision & 0x40)
- max_timebase = 10; /* Has the 216 and 240 ppqn modes */
- }
+ if (devc->version < 0x20) /* Original MPU-401 */
+ timer_caps = TMR_INTERNAL | TMR_EXTERNAL | TMR_MODE_FSK | TMR_MODE_MIDI;
+ else {
+ /*
+ * The version number 2.0 is used (at least) by the
+ * MusicQuest cards and the Roland Super-MPU.
+ *
+ * MusicQuest has given a special meaning to the bits of the
+ * revision number. The Super-MPU returns 0.
+ */
- timer_mode = (TMR_INTERNAL | TMR_MODE_MIDI) & timer_caps;
+ if (devc->revision)
+ timer_caps |= TMR_EXTERNAL | TMR_MODE_MIDI;
-}
+ if (devc->revision & 0x02)
+ timer_caps |= TMR_MODE_CLS;
-#endif
+
+ if (devc->revision & 0x40)
+ max_timebase = 10; /* Has the 216 and 240 ppqn modes */
+ }
+ timer_mode = (TMR_INTERNAL | TMR_MODE_MIDI) & timer_caps;
+}
#endif
diff --git a/sys/i386/isa/sound/opl3.c b/sys/i386/isa/sound/opl3.c
index 0acd0c6203a0..fbc439883524 100644
--- a/sys/i386/isa/sound/opl3.c
+++ b/sys/i386/isa/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.
- *
+ *
*/
/*
@@ -33,291 +33,280 @@
/*
* hooft@chem.ruu.nl
*/
+#include <i386/isa/sound/sound_config.h>
-#include "sound_config.h"
-#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_YM3812)
+#if defined(CONFIG_YM3812)
-#include "opl3.h"
+#include <i386/isa/sound/opl3.h>
+#include <machine/clock.h>
#define MAX_VOICE 18
-#define OFFS_4OP 11 /*
- * * * Definitions for the operators OP3 and
- * * OP4 * * begin here */
-
-static int opl3_enabled = 0;
-static int left_address = 0x388, right_address = 0x388, both_address = 0;
+#define OFFS_4OP 11
+
+struct voice_info {
+ u_char keyon_byte;
+ long bender;
+ long bender_range;
+ u_long orig_freq;
+ u_long current_freq;
+ int volume;
+ int mode;
+};
-static int nr_voices = 9;
-static int logical_voices[MAX_VOICE] =
-{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17};
+typedef struct opl_devinfo {
+ int left_io, right_io;
+ int nr_voice;
+ int lv_map[MAX_VOICE];
-struct voice_info
- {
- unsigned char keyon_byte;
- long bender;
- long bender_range;
- unsigned long orig_freq;
- unsigned long current_freq;
- int mode;
- };
+ struct voice_info voc[MAX_VOICE];
+ struct voice_alloc_info *v_alloc;
+ struct channel_info *chn_info;
-static struct voice_info voices[MAX_VOICE];
-static struct voice_alloc_info *voice_alloc;
-static struct channel_info *chn_info;
+ struct sbi_instrument i_map[SBFM_MAXINSTR];
+ struct sbi_instrument *act_i[MAX_VOICE];
-static struct sbi_instrument *instrmap;
-static struct sbi_instrument *active_instrument[MAX_VOICE] =
-{NULL};
+ struct synth_info fm_info;
-static struct synth_info fm_info =
-{"OPL-2", 0, SYNTH_TYPE_FM, FM_TYPE_ADLIB, 0, 9, 0, SBFM_MAXINSTR, 0};
+ int busy;
+ int model;
+ u_char cmask;
-static int already_initialized = 0;
+ int is_opl4;
+ sound_os_info *osp;
+}
+ opl_devinfo;
-static int opl3_ok = 0;
-static int opl3_busy = 0;
-static int fm_model = 0; /*
+static struct opl_devinfo *devc = NULL;
- * * * * 0=no fm, 1=mono, 2=SB Pro 1, 3=SB
- * Pro 2 * * */
+static int detected_model;
-static int store_instr (int instr_no, struct sbi_instrument *instr);
-static void freq_to_fnum (int freq, int *block, int *fnum);
-static void opl3_command (int io_addr, unsigned int addr, unsigned int val);
-static int opl3_kill_note (int dev, int voice, int note, int velocity);
-static unsigned char connection_mask = 0x00;
+static int store_instr(int instr_no, struct sbi_instrument * instr);
+static void freq_to_fnum(int freq, int *block, int *fnum);
+static void opl3_command(int io_addr, u_int addr, u_int val);
+static int opl3_kill_note(int dev, int voice, int note, int velocity);
void
-enable_opl3_mode (int left, int right, int both)
+enable_opl3_mode(int left, int right, int both)
{
- if (opl3_enabled)
- return;
-
- opl3_enabled = 1;
- left_address = left;
- right_address = right;
- both_address = both;
- fm_info.capabilities = SYNTH_CAP_OPL3;
- fm_info.synth_subtype = FM_TYPE_OPL3;
+ /* NOP */
}
static void
-enter_4op_mode (void)
+enter_4op_mode(void)
{
- int i;
- static int voices_4op[MAX_VOICE] =
- {0, 1, 2, 9, 10, 11, 6, 7, 8, 15, 16, 17};
-
- connection_mask = 0x3f; /* Connect all possible 4 OP voices */
- opl3_command (right_address, CONNECTION_SELECT_REGISTER, 0x3f);
-
- for (i = 0; i < 3; i++)
- physical_voices[i].voice_mode = 4;
- for (i = 3; i < 6; i++)
- physical_voices[i].voice_mode = 0;
-
- for (i = 9; i < 12; i++)
- physical_voices[i].voice_mode = 4;
- for (i = 12; i < 15; i++)
- physical_voices[i].voice_mode = 0;
-
- for (i = 0; i < 12; i++)
- logical_voices[i] = voices_4op[i];
- voice_alloc->max_voice = nr_voices = 12;
+ int i;
+ static int v4op[MAX_VOICE] =
+ {0, 1, 2, 9, 10, 11, 6, 7, 8, 15, 16, 17};
+
+ devc->cmask = 0x3f; /* Connect all possible 4 OP voice operators */
+ opl3_command(devc->right_io, CONNECTION_SELECT_REGISTER, 0x3f);
+
+ for (i = 0; i < 3; i++)
+ pv_map[i].voice_mode = 4;
+ for (i = 3; i < 6; i++)
+ pv_map[i].voice_mode = 0;
+
+ for (i = 9; i < 12; i++)
+ pv_map[i].voice_mode = 4;
+ for (i = 12; i < 15; i++)
+ pv_map[i].voice_mode = 0;
+
+ for (i = 0; i < 12; i++)
+ devc->lv_map[i] = v4op[i];
+ devc->v_alloc->max_voice = devc->nr_voice = 12;
}
static int
-opl3_ioctl (int dev,
- unsigned int cmd, unsigned int arg)
+opl3_ioctl(int dev,
+ u_int cmd, ioctl_arg arg)
{
- switch (cmd)
- {
+ switch (cmd) {
case SNDCTL_FM_LOAD_INSTR:
- {
- struct sbi_instrument ins;
-
- IOCTL_FROM_USER ((char *) &ins, (char *) arg, 0, sizeof (ins));
+ {
+ struct sbi_instrument ins;
- if (ins.channel < 0 || ins.channel >= SBFM_MAXINSTR)
- {
- printk ("FM Error: Invalid instrument number %d\n", ins.channel);
- return RET_ERROR (EINVAL);
- }
+ bcopy(&(((char *) arg)[0]), (char *) &ins, sizeof(ins));
- pmgr_inform (dev, PM_E_PATCH_LOADED, ins.channel, 0, 0, 0);
- return store_instr (ins.channel, &ins);
- }
- break;
+ if (ins.channel < 0 || ins.channel >= SBFM_MAXINSTR) {
+ printf("FM Error: Invalid instrument number %d\n", ins.channel);
+ return -(EINVAL);
+ }
+ pmgr_inform(dev, PM_E_PATCH_LOADED, ins.channel, 0, 0, 0);
+ return store_instr(ins.channel, &ins);
+ }
+ break;
case SNDCTL_SYNTH_INFO:
- fm_info.nr_voices = (nr_voices == 12) ? 6 : nr_voices;
-
- IOCTL_TO_USER ((char *) arg, 0, &fm_info, sizeof (fm_info));
- return 0;
- break;
+ devc->fm_info.nr_voices = (devc->nr_voice == 12) ? 6 : devc->nr_voice;
+ bcopy(&devc->fm_info, &(((char *) arg)[0]), sizeof(devc->fm_info));
+ return 0;
+ break;
case SNDCTL_SYNTH_MEMAVL:
- return 0x7fffffff;
- break;
+ return 0x7fffffff;
+ break;
case SNDCTL_FM_4OP_ENABLE:
- if (opl3_enabled)
- enter_4op_mode ();
- return 0;
- break;
+ if (devc->model == 2)
+ enter_4op_mode();
+ return 0;
+ break;
default:
- return RET_ERROR (EINVAL);
+ return -(EINVAL);
}
}
int
-opl3_detect (int ioaddr)
+opl3_detect(int ioaddr, sound_os_info * osp)
{
- /*
- * 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.
- */
-
- unsigned char stat1, stat2;
- int i;
-
- if (already_initialized)
- {
- return 0; /*
- * Do avoid duplicate initializations
- */
+ /*
+ * This function returns 1 if the FM chip 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.
+ */
+
+ u_char stat1, stat2, signature;
+ int i;
+
+ if (devc != NULL)
+ return 0;
+
+ devc = (struct opl_devinfo *) malloc(sizeof(*devc), M_DEVBUF, M_NOWAIT);
+ if (!devc)
+ panic("SOUND: Cannot allocate memory\n");
+
+ if (devc == NULL) {
+ printf("OPL3: Can't allocate memory for device control structure\n");
+ return 0;
}
+ devc->osp = osp;
- if (opl3_enabled)
- ioaddr = left_address;
-
- opl3_command (ioaddr, TIMER_CONTROL_REGISTER, TIMER1_MASK | TIMER2_MASK); /*
- * Reset
- * timers
- * 1
- * and
- * 2
- */
- opl3_command (ioaddr, TIMER_CONTROL_REGISTER, IRQ_RESET); /*
- * Reset the
- * IRQ of FM
- * * chicp
- */
-
- stat1 = INB (ioaddr); /*
- * Read status register
- */
-
- if ((stat1 & 0xE0) != 0x00)
- {
- return 0; /*
- * Should be 0x00
- */
+ /* Reset timers 1 and 2 */
+ opl3_command(ioaddr, TIMER_CONTROL_REGISTER, TIMER1_MASK | TIMER2_MASK);
+
+ /* Reset the IRQ of the FM chip */
+ opl3_command(ioaddr, TIMER_CONTROL_REGISTER, IRQ_RESET);
+
+ signature = stat1 = inb(ioaddr); /* Status register */
+
+ if ((stat1 & 0xE0) != 0x00) {
+ return 0; /* Should be 0x00 */
}
+ opl3_command(ioaddr, TIMER1_REGISTER, 0xff); /* Set timer1 to 0xff */
+
+ opl3_command(ioaddr, TIMER_CONTROL_REGISTER,
+ TIMER2_MASK | TIMER1_START); /* Unmask and start timer 1 */
+
+
+ DELAY(150); /* Now we have to delay at least 80 usec */
+
+ stat2 = inb(ioaddr); /* Read status after timers have expired */
- opl3_command (ioaddr, TIMER1_REGISTER, 0xff); /*
- * Set timer 1 to
- * 0xff
- */
- opl3_command (ioaddr, TIMER_CONTROL_REGISTER,
- TIMER2_MASK | TIMER1_START); /*
- * Unmask and start timer 1
- */
-
- /*
- * Now we have to delay at least 80 msec
- */
-
- for (i = 0; i < 50; i++)
- tenmicrosec (); /*
- * To be sure
- */
-
- stat2 = INB (ioaddr); /*
- * Read status after timers have expired
- */
-
- /*
- * Stop the timers
- */
-
- opl3_command (ioaddr, TIMER_CONTROL_REGISTER, TIMER1_MASK | TIMER2_MASK); /*
- * Reset
- * timers
- * 1
- * and
- * 2
- */
- opl3_command (ioaddr, TIMER_CONTROL_REGISTER, IRQ_RESET); /*
- * Reset the
- * IRQ of FM
- * * chicp
- */
-
- if ((stat2 & 0xE0) != 0xc0)
- {
- return 0; /*
- * There is no YM3812
- */
+ /*
+ * Stop the timers
+ */
+
+ /* Reset timers 1 and 2 */
+ opl3_command(ioaddr, TIMER_CONTROL_REGISTER, TIMER1_MASK | TIMER2_MASK);
+ /* Reset the IRQ of the FM chip */
+ opl3_command(ioaddr, TIMER_CONTROL_REGISTER, IRQ_RESET);
+
+ if ((stat2 & 0xE0) != 0xc0) {
+ return 0; /* There is no YM3812 */
}
+ /*
+ * There is a FM chicp in this address. Detect the type (OPL2 to
+ * OPL4)
+ */
- /*
- * There is a FM chicp in this address. Now set some default values.
- */
+ if (signature == 0x06) {/* OPL2 */
+ detected_model = 2;
+ } else if (signature == 0x00) { /* OPL3 or OPL4 */
+ u_char tmp;
- for (i = 0; i < 9; i++)
- opl3_command (ioaddr, KEYON_BLOCK + i, 0); /*
- * Note off
- */
+ detected_model = 3;
- opl3_command (ioaddr, TEST_REGISTER, ENABLE_WAVE_SELECT);
- opl3_command (ioaddr, PERCUSSION_REGISTER, 0x00); /*
- * Melodic mode.
- */
+ /*
+ * Detect availability of OPL4 (_experimental_). Works
+ * propably only after a cold boot. In addition the OPL4 port
+ * of the chip may not be connected to the PC bus at all.
+ */
- return 1;
+ opl3_command(ioaddr + 2, OPL3_MODE_REGISTER, 0x00);
+ opl3_command(ioaddr + 2, OPL3_MODE_REGISTER, OPL3_ENABLE | OPL4_ENABLE);
+
+ if ((tmp = inb(ioaddr)) == 0x02) { /* Have a OPL4 */
+ detected_model = 4;
+ }
+ if (!0) { /* OPL4 port is free */ /* XXX check here lr970711 */
+ int tmp;
+
+ outb(ioaddr - 8, 0x02); /* Select OPL4 ID register */
+ DELAY(10);
+ tmp = inb(ioaddr - 7); /* Read it */
+ DELAY(10);
+
+ if (tmp == 0x20) { /* OPL4 should return 0x20 here */
+ detected_model = 4;
+
+ outb(ioaddr - 8, 0xF8); /* Select OPL4 FM mixer control */
+ DELAY(10);
+ outb(ioaddr - 7, 0x1B); /* Write value */
+ DELAY(10);
+ } else
+ detected_model = 3;
+ }
+ opl3_command(ioaddr + 2, OPL3_MODE_REGISTER, 0);
+
+ }
+ for (i = 0; i < 9; i++)
+ opl3_command(ioaddr, KEYON_BLOCK + i, 0); /* Note off */
+
+ opl3_command(ioaddr, TEST_REGISTER, ENABLE_WAVE_SELECT);
+ opl3_command(ioaddr, PERCUSSION_REGISTER, 0x00); /* Melodic mode. */
+
+ return 1;
}
static int
-opl3_kill_note (int dev, int voice, int note, int velocity)
+opl3_kill_note(int dev, int voice, int note, int velocity)
{
- struct physical_voice_info *map;
+ struct physical_voice_info *map;
- if (voice < 0 || voice >= nr_voices)
- return 0;
+ if (voice < 0 || voice >= devc->nr_voice)
+ return 0;
- voice_alloc->map[voice] = 0;
+ devc->v_alloc->map[voice] = 0;
- map = &physical_voices[logical_voices[voice]];
+ map = &pv_map[devc->lv_map[voice]];
- DEB (printk ("Kill note %d\n", voice));
+ DEB(printf("Kill note %d\n", voice));
- if (map->voice_mode == 0)
- return 0;
+ if (map->voice_mode == 0)
+ return 0;
- opl3_command (map->ioaddr, KEYON_BLOCK + map->voice_num, voices[voice].keyon_byte & ~0x20);
+ opl3_command(map->ioaddr, KEYON_BLOCK + map->voice_num,
+ devc->voc[voice].keyon_byte & ~0x20);
- voices[voice].keyon_byte = 0;
- voices[voice].bender = 0;
- voices[voice].bender_range = 200; /*
- * 200 cents = 2 semitones
- */
- voices[voice].orig_freq = 0;
- voices[voice].current_freq = 0;
- voices[voice].mode = 0;
+ devc->voc[voice].keyon_byte = 0;
+ devc->voc[voice].bender = 0;
+ devc->voc[voice].volume = 64;
+ devc->voc[voice].bender_range = 200; /* 200 cents = 2 semitones */
+ devc->voc[voice].orig_freq = 0;
+ devc->voc[voice].current_freq = 0;
+ devc->voc[voice].mode = 0;
- return 0;
+ return 0;
}
#define HIHAT 0
@@ -329,27 +318,28 @@ opl3_kill_note (int dev, int voice, int note, int velocity)
#define DEFAULT TOMTOM
static int
-store_instr (int instr_no, struct sbi_instrument *instr)
+store_instr(int instr_no, struct sbi_instrument * instr)
{
- if (instr->key != FM_PATCH && (instr->key != OPL3_PATCH || !opl3_enabled))
- printk ("FM warning: Invalid patch format field (key) 0x%x\n", instr->key);
- memcpy ((char *) &(instrmap[instr_no]), (char *) instr, sizeof (*instr));
+ if (instr->key !=FM_PATCH && (instr->key !=OPL3_PATCH || devc->model != 2))
+ printf("FM warning: Invalid patch format field (key) 0x%x\n",
+ instr->key);
+ bcopy((char *) instr, (char *) &(devc->i_map[instr_no]), sizeof(*instr));
- return 0;
+ return 0;
}
static int
-opl3_set_instr (int dev, int voice, int instr_no)
+opl3_set_instr(int dev, int voice, int instr_no)
{
- if (voice < 0 || voice >= nr_voices)
- return 0;
+ if (voice < 0 || voice >= devc->nr_voice)
+ return 0;
- if (instr_no < 0 || instr_no >= SBFM_MAXINSTR)
- return 0;
+ if (instr_no < 0 || instr_no >= SBFM_MAXINSTR)
+ return 0;
- active_instrument[voice] = &instrmap[instr_no];
- return 0;
+ devc->act_i[voice] = &devc->i_map[instr_no];
+ return 0;
}
/*
@@ -362,563 +352,464 @@ opl3_set_instr (int dev, int voice, int instr_no)
* it saves a lot of log() calculations. (RH)
*/
char fm_volume_table[128] =
-{-64, -48, -40, -35, -32, -29, -27, -26, /*
- * 0 - 7
- */
- -24, -23, -21, -20, -19, -18, -18, -17, /*
- * 8 - 15
- */
- -16, -15, -15, -14, -13, -13, -12, -12, /*
- * 16 - 23
- */
- -11, -11, -10, -10, -10, -9, -9, -8, /*
- * 24 - 31
- */
- -8, -8, -7, -7, -7, -6, -6, -6,/*
- * 32 - 39
- */
- -5, -5, -5, -5, -4, -4, -4, -4,/*
- * 40 - 47
- */
- -3, -3, -3, -3, -2, -2, -2, -2,/*
- * 48 - 55
- */
- -2, -1, -1, -1, -1, 0, 0, 0, /*
- * 56 - 63
- */
- 0, 0, 0, 1, 1, 1, 1, 1, /*
- * 64 - 71
- */
- 1, 2, 2, 2, 2, 2, 2, 2, /*
- * 72 - 79
- */
- 3, 3, 3, 3, 3, 3, 3, 4, /*
- * 80 - 87
- */
- 4, 4, 4, 4, 4, 4, 4, 5, /*
- * 88 - 95
- */
- 5, 5, 5, 5, 5, 5, 5, 5, /*
- * 96 - 103
- */
- 6, 6, 6, 6, 6, 6, 6, 6, /*
- * 104 - 111
- */
- 6, 7, 7, 7, 7, 7, 7, 7, /*
- * 112 - 119
- */
- 7, 7, 7, 8, 8, 8, 8, 8}; /*
-
-
- * * * * 120 - 127 */
+{
+ -64, -48, -40, -35, -32, -29, -27, -26,
+ -24, -23, -21, -20, -19, -18, -18, -17,
+ -16, -15, -15, -14, -13, -13, -12, -12,
+ -11, -11, -10, -10, -10, -9, -9, -8,
+ -8, -8, -7, -7, -7, -6, -6, -6,
+ -5, -5, -5, -5, -4, -4, -4, -4,
+ -3, -3, -3, -3, -2, -2, -2, -2,
+ -2, -1, -1, -1, -1, 0, 0, 0,
+ 0, 0, 0, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2,
+ 3, 3, 3, 3, 3, 3, 3, 4,
+ 4, 4, 4, 4, 4, 4, 4, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5,
+ 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 8, 8, 8, 8, 8};
static void
-calc_vol (unsigned char *regbyte, int volume)
+calc_vol(u_char *regbyte, int volume, int main_vol)
{
- int level = (~*regbyte & 0x3f);
+ int level = (~*regbyte & 0x3f);
- if (level)
- level += fm_volume_table[volume];
+ if (main_vol > 127)
+ main_vol = 127;
- if (level > 0x3f)
- level = 0x3f;
- if (level < 0)
- level = 0;
+ volume = (volume * main_vol) / 127;
- *regbyte = (*regbyte & 0xc0) | (~level & 0x3f);
+ if (level)
+ level += fm_volume_table[volume];
+
+ RANGE (level, 0, 0x3f );
+
+ *regbyte = (*regbyte & 0xc0) | (~level & 0x3f);
}
static void
-set_voice_volume (int voice, int volume)
+set_voice_volume(int voice, int volume, int main_vol)
{
- unsigned char vol1, vol2, vol3, vol4;
- struct sbi_instrument *instr;
- struct physical_voice_info *map;
+ u_char vol1, vol2, vol3, vol4;
+ struct sbi_instrument *instr;
+ struct physical_voice_info *map;
- if (voice < 0 || voice >= nr_voices)
- return;
+ if (voice < 0 || voice >= devc->nr_voice)
+ return;
- map = &physical_voices[logical_voices[voice]];
+ map = &pv_map[devc->lv_map[voice]];
- instr = active_instrument[voice];
+ instr = devc->act_i[voice];
- if (!instr)
- instr = &instrmap[0];
+ if (!instr)
+ instr = &devc->i_map[0];
- if (instr->channel < 0)
- return;
+ if (instr->channel < 0)
+ return;
- if (voices[voice].mode == 0)
- return;
+ if (devc->voc[voice].mode == 0)
+ return;
- if (voices[voice].mode == 2)
- { /*
- * 2 OP voice
- */
+ if (devc->voc[voice].mode == 2) {
- vol1 = instr->operators[2];
- vol2 = instr->operators[3];
+ vol1 = instr->operators[2];
+ vol2 = instr->operators[3];
- if ((instr->operators[10] & 0x01))
- { /*
- * Additive synthesis
- */
- calc_vol (&vol1, volume);
- calc_vol (&vol2, volume);
- }
- else
- { /*
- * FM synthesis
- */
- calc_vol (&vol2, volume);
+ if ((instr->operators[10] & 0x01)) {
+ calc_vol(&vol1, volume, main_vol);
}
+ calc_vol(&vol2, volume, main_vol);
- opl3_command (map->ioaddr, KSL_LEVEL + map->op[0], vol1); /*
- * Modulator
- * volume
- */
- opl3_command (map->ioaddr, KSL_LEVEL + map->op[1], vol2); /*
- * Carrier
- * volume
- */
- }
- else
- { /*
- * 4 OP voice
- */
- int connection;
+ opl3_command(map->ioaddr, KSL_LEVEL + map->op[0], vol1);
+ opl3_command(map->ioaddr, KSL_LEVEL + map->op[1], vol2);
+ } else { /* 4 OP voice */
+ int connection;
- vol1 = instr->operators[2];
- vol2 = instr->operators[3];
- vol3 = instr->operators[OFFS_4OP + 2];
- vol4 = instr->operators[OFFS_4OP + 3];
+ vol1 = instr->operators[2];
+ vol2 = instr->operators[3];
+ vol3 = instr->operators[OFFS_4OP + 2];
+ vol4 = instr->operators[OFFS_4OP + 3];
- /*
- * The connection method for 4 OP voices is defined by the rightmost
- * bits at the offsets 10 and 10+OFFS_4OP
- */
+ /*
+ * The connection method for 4 OP devc->voc is defined by the
+ * rightmost bits at the offsets 10 and 10+OFFS_4OP
+ */
- connection = ((instr->operators[10] & 0x01) << 1) | (instr->operators[10 + OFFS_4OP] & 0x01);
+ connection = ((instr->operators[10] & 0x01) << 1) | (instr->operators[10 + OFFS_4OP] & 0x01);
- switch (connection)
- {
+ switch (connection) {
case 0:
- calc_vol (&vol4, volume); /*
- * Just the OP 4 is carrier
- */
- break;
+ calc_vol(&vol4, volume, main_vol);
+ break;
case 1:
- calc_vol (&vol2, volume);
- calc_vol (&vol4, volume);
- break;
+ calc_vol(&vol2, volume, main_vol);
+ calc_vol(&vol4, volume, main_vol);
+ break;
case 2:
- calc_vol (&vol1, volume);
- calc_vol (&vol4, volume);
- break;
+ calc_vol(&vol1, volume, main_vol);
+ calc_vol(&vol4, volume, main_vol);
+ break;
case 3:
- calc_vol (&vol1, volume);
- calc_vol (&vol3, volume);
- calc_vol (&vol4, volume);
- break;
-
- default: /*
- * Why ??
- */ ;
+ calc_vol(&vol1, volume, main_vol);
+ calc_vol(&vol3, volume, main_vol);
+ calc_vol(&vol4, volume, main_vol);
+ break;
+
+ default:;
}
- opl3_command (map->ioaddr, KSL_LEVEL + map->op[0], vol1);
- opl3_command (map->ioaddr, KSL_LEVEL + map->op[1], vol2);
- opl3_command (map->ioaddr, KSL_LEVEL + map->op[2], vol3);
- opl3_command (map->ioaddr, KSL_LEVEL + map->op[3], vol4);
+ opl3_command(map->ioaddr, KSL_LEVEL + map->op[0], vol1);
+ opl3_command(map->ioaddr, KSL_LEVEL + map->op[1], vol2);
+ opl3_command(map->ioaddr, KSL_LEVEL + map->op[2], vol3);
+ opl3_command(map->ioaddr, KSL_LEVEL + map->op[3], vol4);
}
}
static int
-opl3_start_note (int dev, int voice, int note, int volume)
+opl3_start_note(int dev, int voice, int note, int volume)
{
- unsigned char data, fpc;
- int block, fnum, freq, voice_mode;
- struct sbi_instrument *instr;
- struct physical_voice_info *map;
+ u_char data, fpc;
+ int block, fnum, freq, voice_mode;
+ struct sbi_instrument *instr;
+ struct physical_voice_info *map;
- if (voice < 0 || voice >= nr_voices)
- return 0;
+ if (voice < 0 || voice >= devc->nr_voice)
+ return 0;
- map = &physical_voices[logical_voices[voice]];
+ map = &pv_map[devc->lv_map[voice]];
- if (map->voice_mode == 0)
- return 0;
+ if (map->voice_mode == 0)
+ return 0;
- if (note == 255) /*
- * Just change the volume
- */
- {
- set_voice_volume (voice, volume);
- return 0;
+ if (note == 255) { /* Just change the volume */
+ set_voice_volume(voice, volume, devc->voc[voice].volume);
+ return 0;
}
-
- /*
- * Kill previous note before playing
- */
- opl3_command (map->ioaddr, KSL_LEVEL + map->op[1], 0xff); /*
- * Carrier
- * volume to
- * min
- */
- opl3_command (map->ioaddr, KSL_LEVEL + map->op[0], 0xff); /*
- * Modulator
- * volume to
- */
-
- if (map->voice_mode == 4)
- {
- opl3_command (map->ioaddr, KSL_LEVEL + map->op[2], 0xff);
- opl3_command (map->ioaddr, KSL_LEVEL + map->op[3], 0xff);
+ /*
+ * Kill previous note before playing
+ */
+ opl3_command(map->ioaddr, KSL_LEVEL + map->op[1], 0xff); /* Carrier volume to min */
+ opl3_command(map->ioaddr, KSL_LEVEL + map->op[0], 0xff); /* Modulator volume to */
+
+ if (map->voice_mode == 4) {
+ opl3_command(map->ioaddr, KSL_LEVEL + map->op[2], 0xff);
+ opl3_command(map->ioaddr, KSL_LEVEL + map->op[3], 0xff);
}
+ opl3_command(map->ioaddr, KEYON_BLOCK + map->voice_num, 0x00); /* Note off */
- opl3_command (map->ioaddr, KEYON_BLOCK + map->voice_num, 0x00); /*
- * Note
- * off
- */
-
- instr = active_instrument[voice];
+ instr = devc->act_i[voice];
- if (!instr)
- instr = &instrmap[0];
+ if (!instr)
+ instr = &devc->i_map[0];
- if (instr->channel < 0)
- {
- printk (
- "OPL3: Initializing voice %d with undefined instrument\n",
+ if (instr->channel < 0) {
+ printf( "OPL3: Initializing voice %d with undefined instrument\n",
voice);
- return 0;
+ return 0;
}
+ if (map->voice_mode == 2 && instr->key == OPL3_PATCH)
+ return 0; /* Cannot play */
- if (map->voice_mode == 2 && instr->key == OPL3_PATCH)
- return 0; /*
- * Cannot play
- */
+ voice_mode = map->voice_mode;
- voice_mode = map->voice_mode;
+ if (voice_mode == 4) {
+ int voice_shift;
- if (voice_mode == 4)
- {
- int voice_shift;
+ voice_shift = (map->ioaddr == devc->left_io) ? 0 : 3;
+ voice_shift += map->voice_num;
- voice_shift = (map->ioaddr == left_address) ? 0 : 3;
- voice_shift += map->voice_num;
+ if (instr->key != OPL3_PATCH) { /* Just 2 OP patch */
+ voice_mode = 2;
+ devc->cmask &= ~(1 << voice_shift);
+ } else
+ devc->cmask |= (1 << voice_shift);
- if (instr->key != OPL3_PATCH) /*
- * Just 2 OP patch
- */
- {
- voice_mode = 2;
- connection_mask &= ~(1 << voice_shift);
- }
- else
- {
- connection_mask |= (1 << voice_shift);
- }
-
- opl3_command (right_address, CONNECTION_SELECT_REGISTER, connection_mask);
+ opl3_command(devc->right_io, CONNECTION_SELECT_REGISTER, devc->cmask);
}
-
- /*
- * Set Sound Characteristics
- */
- opl3_command (map->ioaddr, AM_VIB + map->op[0], instr->operators[0]);
- opl3_command (map->ioaddr, AM_VIB + map->op[1], instr->operators[1]);
-
- /*
- * Set Attack/Decay
- */
- opl3_command (map->ioaddr, ATTACK_DECAY + map->op[0], instr->operators[4]);
- opl3_command (map->ioaddr, ATTACK_DECAY + map->op[1], instr->operators[5]);
-
- /*
- * Set Sustain/Release
- */
- opl3_command (map->ioaddr, SUSTAIN_RELEASE + map->op[0], instr->operators[6]);
- opl3_command (map->ioaddr, SUSTAIN_RELEASE + map->op[1], instr->operators[7]);
-
- /*
- * Set Wave Select
- */
- opl3_command (map->ioaddr, WAVE_SELECT + map->op[0], instr->operators[8]);
- opl3_command (map->ioaddr, WAVE_SELECT + map->op[1], instr->operators[9]);
-
- /*
- * Set Feedback/Connection
- */
- fpc = instr->operators[10];
- if (!(fpc & 0x30))
- fpc |= 0x30; /*
- * Ensure that at least one chn is enabled
- */
- opl3_command (map->ioaddr, FEEDBACK_CONNECTION + map->voice_num,
- fpc);
-
- /*
- * If the voice is a 4 OP one, initialize the operators 3 and 4 also
- */
-
- if (voice_mode == 4)
- {
-
- /*
- * Set Sound Characteristics
- */
- opl3_command (map->ioaddr, AM_VIB + map->op[2], instr->operators[OFFS_4OP + 0]);
- opl3_command (map->ioaddr, AM_VIB + map->op[3], instr->operators[OFFS_4OP + 1]);
-
- /*
- * Set Attack/Decay
- */
- opl3_command (map->ioaddr, ATTACK_DECAY + map->op[2], instr->operators[OFFS_4OP + 4]);
- opl3_command (map->ioaddr, ATTACK_DECAY + map->op[3], instr->operators[OFFS_4OP + 5]);
-
- /*
- * Set Sustain/Release
- */
- opl3_command (map->ioaddr, SUSTAIN_RELEASE + map->op[2], instr->operators[OFFS_4OP + 6]);
- opl3_command (map->ioaddr, SUSTAIN_RELEASE + map->op[3], instr->operators[OFFS_4OP + 7]);
-
- /*
- * Set Wave Select
- */
- opl3_command (map->ioaddr, WAVE_SELECT + map->op[2], instr->operators[OFFS_4OP + 8]);
- opl3_command (map->ioaddr, WAVE_SELECT + map->op[3], instr->operators[OFFS_4OP + 9]);
-
- /*
- * Set Feedback/Connection
- */
- fpc = instr->operators[OFFS_4OP + 10];
- if (!(fpc & 0x30))
- fpc |= 0x30; /*
- * Ensure that at least one chn is enabled
- */
- opl3_command (map->ioaddr, FEEDBACK_CONNECTION + map->voice_num + 3, fpc);
+ /*
+ * Set Sound Characteristics
+ */
+ opl3_command(map->ioaddr, AM_VIB + map->op[0], instr->operators[0]);
+ opl3_command(map->ioaddr, AM_VIB + map->op[1], instr->operators[1]);
+
+ /*
+ * Set Attack/Decay
+ */
+ opl3_command(map->ioaddr, ATTACK_DECAY + map->op[0], instr->operators[4]);
+ opl3_command(map->ioaddr, ATTACK_DECAY + map->op[1], instr->operators[5]);
+
+ /*
+ * Set Sustain/Release
+ */
+ opl3_command(map->ioaddr,SUSTAIN_RELEASE + map->op[0], instr->operators[6]);
+ opl3_command(map->ioaddr,SUSTAIN_RELEASE + map->op[1], instr->operators[7]);
+
+ /*
+ * Set Wave Select
+ */
+ opl3_command(map->ioaddr, WAVE_SELECT + map->op[0], instr->operators[8]);
+ opl3_command(map->ioaddr, WAVE_SELECT + map->op[1], instr->operators[9]);
+
+ /*
+ * Set Feedback/Connection
+ */
+ fpc = instr->operators[10];
+ if (!(fpc & 0x30))
+ fpc |= 0x30; /* Ensure that at least one chn is enabled */
+ opl3_command(map->ioaddr, FEEDBACK_CONNECTION + map->voice_num, fpc);
+
+ /*
+ * If the voice is a 4 OP one, initialize the operators 3 and 4 also
+ */
+
+ if (voice_mode == 4) {
+
+ /*
+ * Set Sound Characteristics
+ */
+ opl3_command(map->ioaddr, AM_VIB + map->op[2],
+ instr->operators[OFFS_4OP + 0]);
+ opl3_command(map->ioaddr, AM_VIB + map->op[3],
+ instr->operators[OFFS_4OP + 1]);
+
+ /*
+ * Set Attack/Decay
+ */
+ opl3_command(map->ioaddr, ATTACK_DECAY + map->op[2],
+ instr->operators[OFFS_4OP + 4]);
+ opl3_command(map->ioaddr, ATTACK_DECAY + map->op[3],
+ instr->operators[OFFS_4OP + 5]);
+
+ /*
+ * Set Sustain/Release
+ */
+ opl3_command(map->ioaddr, SUSTAIN_RELEASE + map->op[2],
+ instr->operators[OFFS_4OP + 6]);
+ opl3_command(map->ioaddr, SUSTAIN_RELEASE + map->op[3],
+ instr->operators[OFFS_4OP + 7]);
+
+ /*
+ * Set Wave Select
+ */
+ opl3_command(map->ioaddr, WAVE_SELECT + map->op[2],
+ instr->operators[OFFS_4OP + 8]);
+ opl3_command(map->ioaddr, WAVE_SELECT + map->op[3],
+ instr->operators[OFFS_4OP + 9]);
+
+ /*
+ * Set Feedback/Connection
+ */
+ fpc = instr->operators[OFFS_4OP + 10];
+ if (!(fpc & 0x30))
+ fpc |= 0x30; /* Ensure that at least one chn is enabled */
+ opl3_command(map->ioaddr,FEEDBACK_CONNECTION + map->voice_num + 3, fpc);
}
+ devc->voc[voice].mode = voice_mode;
- voices[voice].mode = voice_mode;
-
- set_voice_volume (voice, volume);
+ set_voice_volume(voice, volume, devc->voc[voice].volume);
- freq = voices[voice].orig_freq = note_to_freq (note) / 1000;
+ freq = devc->voc[voice].orig_freq = note_to_freq(note) / 1000;
- /*
- * Since the pitch bender may have been set before playing the note, we
- * have to calculate the bending now.
- */
+ /*
+ * Since the pitch bender may have been set before playing the note,
+ * we have to calculate the bending now.
+ */
- freq = compute_finetune (voices[voice].orig_freq, voices[voice].bender, voices[voice].bender_range);
- voices[voice].current_freq = freq;
+ freq = compute_finetune(devc->voc[voice].orig_freq,
+ devc->voc[voice].bender, devc->voc[voice].bender_range);
+ devc->voc[voice].current_freq = freq;
- freq_to_fnum (freq, &block, &fnum);
+ freq_to_fnum(freq, &block, &fnum);
- /*
- * Play note
- */
+ /*
+ * Play note
+ */
- data = fnum & 0xff; /*
- * Least significant bits of fnumber
- */
- opl3_command (map->ioaddr, FNUM_LOW + map->voice_num, data);
+ data = fnum & 0xff; /* Least significant bits of fnumber */
+ opl3_command(map->ioaddr, FNUM_LOW + map->voice_num, data);
- data = 0x20 | ((block & 0x7) << 2) | ((fnum >> 8) & 0x3);
- voices[voice].keyon_byte = data;
- opl3_command (map->ioaddr, KEYON_BLOCK + map->voice_num, data);
- if (voice_mode == 4)
- opl3_command (map->ioaddr, KEYON_BLOCK + map->voice_num + 3, data);
+ data = 0x20 | ((block & 0x7) << 2) | ((fnum >> 8) & 0x3);
+ devc->voc[voice].keyon_byte = data;
+ opl3_command(map->ioaddr, KEYON_BLOCK + map->voice_num, data);
+ if (voice_mode == 4)
+ opl3_command(map->ioaddr, KEYON_BLOCK + map->voice_num + 3, data);
- return 0;
+ return 0;
}
static void
-freq_to_fnum (int freq, int *block, int *fnum)
+freq_to_fnum(int freq, int *block, int *fnum)
{
- int f, octave;
-
- /*
- * Converts the note frequency to block and fnum values for the FM chip
- */
- /*
- * First try to compute the block -value (octave) where the note belongs
- */
-
- f = freq;
-
- octave = 5;
-
- if (f == 0)
- octave = 0;
- else if (f < 261)
- {
- while (f < 261)
- {
- octave--;
- f <<= 1;
+ int f, octave;
+
+ /*
+ * Converts the note frequency to block and fnum values for the FM
+ * chip
+ */
+ /*
+ * First try to compute the block -value (octave) where the note
+ * belongs
+ */
+
+ f = freq;
+
+ octave = 5;
+
+ if (f == 0)
+ octave = 0;
+ else if (f < 261) {
+ while (f < 261) {
+ octave--;
+ f <<= 1;
}
- }
- else if (f > 493)
- {
- while (f > 493)
- {
- octave++;
- f >>= 1;
+ } else if (f > 493) {
+ while (f > 493) {
+ octave++;
+ f >>= 1;
}
}
+ if (octave > 7)
+ octave = 7;
- if (octave > 7)
- octave = 7;
-
- *fnum = freq * (1 << (20 - octave)) / 49716;
- *block = octave;
+ *fnum = freq * (1 << (20 - octave)) / 49716;
+ *block = octave;
}
static void
-opl3_command (int io_addr, unsigned int addr, unsigned int val)
+opl3_command(int io_addr, u_int addr, u_int val)
{
- int i;
-
- /*
- * The original 2-OP synth requires a quite long delay after writing to a
- * register. The OPL-3 survives with just two INBs
- */
-
- OUTB ((unsigned char) (addr & 0xff), io_addr); /*
- * Select register
- *
- */
-
- if (!opl3_enabled)
- tenmicrosec ();
- else
- for (i = 0; i < 2; i++)
- INB (io_addr);
-
- OUTB ((unsigned char) (val & 0xff), io_addr + 1); /*
- * Write to register
- *
- */
-
- if (!opl3_enabled)
- {
- tenmicrosec ();
- tenmicrosec ();
- tenmicrosec ();
- }
- else
- for (i = 0; i < 2; i++)
- INB (io_addr);
+ int i;
+
+ /*
+ * The original 2-OP synth requires a quite long delay after writing
+ * to a register. The OPL-3 survives with just two INBs
+ */
+
+ outb(io_addr, (u_char) (addr & 0xff));
+
+ if (!devc->model != 2)
+ DELAY(10);
+ else
+ for (i = 0; i < 2; i++)
+ inb(io_addr);
+
+ outb(io_addr + 1, (u_char) (val & 0xff));
+
+ if (devc->model != 2)
+ DELAY(30);
+ else
+ for (i = 0; i < 2; i++)
+ inb(io_addr);
}
static void
-opl3_reset (int dev)
+opl3_reset(int dev)
{
- int i;
+ int i;
- for (i = 0; i < nr_voices; i++)
- {
- opl3_command (physical_voices[logical_voices[i]].ioaddr,
- KSL_LEVEL + physical_voices[logical_voices[i]].op[0], 0xff);
+ for (i = 0; i < 18; i++)
+ devc->lv_map[i] = i;
- opl3_command (physical_voices[logical_voices[i]].ioaddr,
- KSL_LEVEL + physical_voices[logical_voices[i]].op[1], 0xff);
+ for (i = 0; i < devc->nr_voice; i++) {
+ opl3_command(pv_map[devc->lv_map[i]].ioaddr,
+ KSL_LEVEL + pv_map[devc->lv_map[i]].op[0], 0xff);
- if (physical_voices[logical_voices[i]].voice_mode == 4)
- {
- opl3_command (physical_voices[logical_voices[i]].ioaddr,
- KSL_LEVEL + physical_voices[logical_voices[i]].op[2], 0xff);
+ opl3_command(pv_map[devc->lv_map[i]].ioaddr,
+ KSL_LEVEL + pv_map[devc->lv_map[i]].op[1], 0xff);
- opl3_command (physical_voices[logical_voices[i]].ioaddr,
- KSL_LEVEL + physical_voices[logical_voices[i]].op[3], 0xff);
- }
+ if (pv_map[devc->lv_map[i]].voice_mode == 4) {
+ opl3_command(pv_map[devc->lv_map[i]].ioaddr,
+ KSL_LEVEL + pv_map[devc->lv_map[i]].op[2], 0xff);
- opl3_kill_note (dev, i, 0, 64);
+ opl3_command(pv_map[devc->lv_map[i]].ioaddr,
+ KSL_LEVEL + pv_map[devc->lv_map[i]].op[3], 0xff);
+ }
+ opl3_kill_note(dev, i, 0, 64);
}
- if (opl3_enabled)
- {
- voice_alloc->max_voice = nr_voices = 18;
-
- for (i = 0; i < 18; i++)
- logical_voices[i] = i;
+ if (devc->model == 2) {
+ devc->v_alloc->max_voice = devc->nr_voice = 18;
- for (i = 0; i < 18; i++)
- physical_voices[i].voice_mode = 2;
+ for (i = 0; i < 18; i++)
+ pv_map[i].voice_mode = 2;
}
-
}
static int
-opl3_open (int dev, int mode)
+opl3_open(int dev, int mode)
{
- if (!opl3_ok)
- return RET_ERROR (ENXIO);
- if (opl3_busy)
- return RET_ERROR (EBUSY);
- opl3_busy = 1;
-
- connection_mask = 0x00; /*
- * Just 2 OP voices
- */
- if (opl3_enabled)
- opl3_command (right_address, CONNECTION_SELECT_REGISTER, connection_mask);
- return 0;
+ int i;
+
+ if (devc->busy)
+ return -(EBUSY);
+ devc->busy = 1;
+
+ devc->v_alloc->max_voice = devc->nr_voice = (devc->model == 2) ? 18 : 9;
+ devc->v_alloc->timestamp = 0;
+
+ for (i = 0; i < 18; i++) {
+ devc->v_alloc->map[i] = 0;
+ devc->v_alloc->alloc_times[i] = 0;
+ }
+
+ devc->cmask = 0x00; /* Just 2 OP mode */
+ if (devc->model == 2)
+ opl3_command(devc->right_io, CONNECTION_SELECT_REGISTER, devc->cmask);
+ return 0;
}
static void
-opl3_close (int dev)
+opl3_close(int dev)
{
- opl3_busy = 0;
- voice_alloc->max_voice = nr_voices = opl3_enabled ? 18 : 9;
- fm_info.nr_drums = 0;
- fm_info.perc_mode = 0;
+ devc->busy = 0;
+ devc->v_alloc->max_voice = devc->nr_voice = (devc->model == 2) ? 18 : 9;
+
+ devc->fm_info.nr_drums = 0;
+ devc->fm_info.perc_mode = 0;
- opl3_reset (dev);
+ opl3_reset(dev);
}
static void
-opl3_hw_control (int dev, unsigned char *event)
+opl3_hw_control(int dev, u_char *event)
{
}
static int
-opl3_load_patch (int dev, int format, snd_rw_buf * addr,
- int offs, int count, int pmgr_flag)
+opl3_load_patch(int dev, int format, snd_rw_buf * addr,
+ int offs, int count, int pmgr_flag)
{
- struct sbi_instrument ins;
+ struct sbi_instrument ins;
- if (count < sizeof (ins))
- {
- printk ("FM Error: Patch record too short\n");
- return RET_ERROR (EINVAL);
+ if (count < sizeof(ins)) {
+ printf("FM Error: Patch record too short\n");
+ return -(EINVAL);
}
+ if (uiomove(&((char *) &ins)[offs], sizeof(ins) - offs, addr)) {
+ printf("sb: Bad copyin()!\n");
+ };
- COPY_FROM_USER (&((char *) &ins)[offs], (char *) addr, offs, sizeof (ins) - offs);
-
- if (ins.channel < 0 || ins.channel >= SBFM_MAXINSTR)
- {
- printk ("FM Error: Invalid instrument number %d\n", ins.channel);
- return RET_ERROR (EINVAL);
+ if (ins.channel < 0 || ins.channel >= SBFM_MAXINSTR) {
+ printf("FM Error: Invalid instrument number %d\n", ins.channel);
+ return -(EINVAL);
}
- ins.key = format;
+ ins.key = format;
- return store_instr (ins.channel, &ins);
+ return store_instr(ins.channel, &ins);
}
static void
-opl3_panning (int dev, int voice, int pressure)
+opl3_panning(int dev, int voice, int pressure)
{
}
static void
-opl3_volume_method (int dev, int mode)
+opl3_volume_method(int dev, int mode)
{
}
@@ -929,297 +820,313 @@ opl3_volume_method (int dev, int mode)
opl3_command (map->ioaddr, AM_VIB + map->op[cell-1], tmp);}
static void
-opl3_aftertouch (int dev, int voice, int pressure)
+opl3_aftertouch(int dev, int voice, int pressure)
{
- int tmp;
- struct sbi_instrument *instr;
- struct physical_voice_info *map;
+ int tmp;
+ struct sbi_instrument *instr;
+ struct physical_voice_info *map;
- if (voice < 0 || voice >= nr_voices)
- return;
+ if (voice < 0 || voice >= devc->nr_voice)
+ return;
- map = &physical_voices[logical_voices[voice]];
+ map = &pv_map[devc->lv_map[voice]];
- DEB (printk ("Aftertouch %d\n", voice));
+ DEB(printf("Aftertouch %d\n", voice));
- if (map->voice_mode == 0)
- return;
+ if (map->voice_mode == 0)
+ return;
- /*
- * Adjust the amount of vibrato depending the pressure
- */
+ /*
+ * Adjust the amount of vibrato depending the pressure
+ */
- instr = active_instrument[voice];
+ instr = devc->act_i[voice];
- if (!instr)
- instr = &instrmap[0];
+ if (!instr)
+ instr = &devc->i_map[0];
- if (voices[voice].mode == 4)
- {
- int connection = ((instr->operators[10] & 0x01) << 1) | (instr->operators[10 + OFFS_4OP] & 0x01);
+ if (devc->voc[voice].mode == 4) {
+ int connection = ((instr->operators[10] & 0x01) << 1) | (instr->operators[10 + OFFS_4OP] & 0x01);
- switch (connection)
- {
+ switch (connection) {
case 0:
- SET_VIBRATO (4);
- break;
+ SET_VIBRATO(4);
+ break;
case 1:
- SET_VIBRATO (2);
- SET_VIBRATO (4);
- break;
+ SET_VIBRATO(2);
+ SET_VIBRATO(4);
+ break;
case 2:
- SET_VIBRATO (1);
- SET_VIBRATO (4);
- break;
+ SET_VIBRATO(1);
+ SET_VIBRATO(4);
+ break;
case 3:
- SET_VIBRATO (1);
- SET_VIBRATO (3);
- SET_VIBRATO (4);
- break;
+ SET_VIBRATO(1);
+ SET_VIBRATO(3);
+ SET_VIBRATO(4);
+ break;
}
- /*
- * Not implemented yet
- */
- }
- else
- {
- SET_VIBRATO (1);
-
- if ((instr->operators[10] & 0x01)) /*
- * Additive synthesis
- */
- SET_VIBRATO (2);
+ /*
+ * Not implemented yet
+ */
+ } else {
+ SET_VIBRATO(1);
+
+ if ((instr->operators[10] & 0x01)) /* Additive synthesis */
+ SET_VIBRATO(2);
}
}
#undef SET_VIBRATO
static void
-bend_pitch (int dev, int voice, int value)
+bend_pitch(int dev, int voice, int value)
{
- unsigned char data;
- int block, fnum, freq;
- struct physical_voice_info *map;
-
- map = &physical_voices[logical_voices[voice]];
-
- if (map->voice_mode == 0)
- return;
-
- voices[voice].bender = value;
- if (!value)
- return;
- if (!(voices[voice].keyon_byte & 0x20))
- return; /*
- * Not keyed on
- */
-
- freq = compute_finetune (voices[voice].orig_freq, voices[voice].bender, voices[voice].bender_range);
- voices[voice].current_freq = freq;
-
- freq_to_fnum (freq, &block, &fnum);
-
- data = fnum & 0xff; /*
- * Least significant bits of fnumber
- */
- 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
- *
- */
- voices[voice].keyon_byte = data;
- opl3_command (map->ioaddr, KEYON_BLOCK + map->voice_num, data);
+ u_char data;
+ int block, fnum, freq;
+ struct physical_voice_info *map;
+
+ map = &pv_map[devc->lv_map[voice]];
+
+ if (map->voice_mode == 0)
+ return;
+
+ devc->voc[voice].bender = value;
+ if (!value)
+ return;
+ if (!(devc->voc[voice].keyon_byte & 0x20))
+ return; /* Not keyed on */
+
+ freq = compute_finetune(devc->voc[voice].orig_freq, devc->voc[voice].bender, devc->voc[voice].bender_range);
+ devc->voc[voice].current_freq = freq;
+
+ freq_to_fnum(freq, &block, &fnum);
+
+ data = fnum & 0xff; /* Least significant bits of fnumber */
+ 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 */
+ devc->voc[voice].keyon_byte = data;
+ opl3_command(map->ioaddr, KEYON_BLOCK + map->voice_num, data);
}
static void
-opl3_controller (int dev, int voice, int ctrl_num, int value)
+opl3_controller(int dev, int voice, int ctrl_num, int value)
{
- if (voice < 0 || voice >= nr_voices)
- return;
+ if (voice < 0 || voice >= devc->nr_voice)
+ return;
- switch (ctrl_num)
- {
+ switch (ctrl_num) {
case CTRL_PITCH_BENDER:
- bend_pitch (dev, voice, value);
- break;
+ bend_pitch(dev, voice, value);
+ break;
case CTRL_PITCH_BENDER_RANGE:
- voices[voice].bender_range = value;
- break;
+ devc->voc[voice].bender_range = value;
+ break;
+
+ case CTL_MAIN_VOLUME:
+ devc->voc[voice].volume = value / 128;
+ break;
}
}
static int
-opl3_patchmgr (int dev, struct patmgr_info *rec)
+opl3_patchmgr(int dev, struct patmgr_info * rec)
{
- return RET_ERROR (EINVAL);
+ return -(EINVAL);
}
static void
-opl3_bender (int dev, int voice, int value)
+opl3_bender(int dev, int voice, int value)
{
- if (voice < 0 || voice >= nr_voices)
- return;
+ if (voice < 0 || voice >= devc->nr_voice)
+ return;
- bend_pitch (dev, voice, value);
+ bend_pitch(dev, voice, value - 8192);
}
static int
-opl3_alloc_voice (int dev, int chn, int note, struct voice_alloc_info *alloc)
+opl3_alloc_voice(int dev, int chn, int note, struct voice_alloc_info * alloc)
{
- int i, p, avail_voices;
- struct sbi_instrument *instr;
- int is4op;
- int instr_no;
-
- if (chn < 0 || chn > 15)
- instr_no = 0;
- else
- instr_no = chn_info[chn].pgm_num;
-
- instr = &instrmap[instr_no];
- if (instr->channel < 0 || /* Instrument not loaded */
- nr_voices != 12) /* Not in 4 OP mode */
- is4op = 0;
- else if (nr_voices == 12) /* 4 OP mode */
- is4op = (instr->key == OPL3_PATCH);
- else
- is4op = 0;
-
- if (is4op)
- {
- p = 0;
- avail_voices = 6;
- }
- else
- {
- if (nr_voices == 12) /* 4 OP mode. Use the '2 OP only' voices first */
- p = 6;
- else
- p = 0;
- avail_voices = nr_voices;
+ int i, p, best, first, avail, best_time = 0x7fffffff;
+ struct sbi_instrument *instr;
+ int is4op;
+ int instr_no;
+
+ if (chn < 0 || chn > 15)
+ instr_no = 0;
+ else
+ instr_no = devc->chn_info[chn].pgm_num;
+
+ instr = &devc->i_map[instr_no];
+ if (instr->channel < 0 || /* Instrument not loaded */
+ devc->nr_voice != 12) /* Not in 4 OP mode */
+ is4op = 0;
+ else if (devc->nr_voice == 12) /* 4 OP mode */
+ is4op = (instr->key == OPL3_PATCH);
+ else
+ is4op = 0;
+
+ if (is4op) {
+ first = p = 0;
+ avail = 6;
+ } else {
+ if (devc->nr_voice == 12) /* 4 OP mode. Use the '2 OP
+ * only' operators first */
+ first = p = 6;
+ else
+ first = p = 0;
+ avail = devc->nr_voice;
}
- /*
- * Now try to find a free voice
- */
+ /*
+ * Now try to find a free voice
+ */
+ best = first;
- for (i = 0; i < avail_voices; i++)
- {
- if (alloc->map[p] == 0)
- {
- return p;
+ for (i = 0; i < avail; i++) {
+ if (alloc->map[p] == 0) {
+ return p;
}
- p = (p + 1) % nr_voices;
+ if (alloc->alloc_times[p] < best_time) { /* Find oldest playing note */
+ best_time = alloc->alloc_times[p];
+ best = p;
+ }
+ p = (p + 1) % avail;
}
- /*
- * Insert some kind of priority mechanism here.
- */
+ /*
+ * Insert some kind of priority mechanism here.
+ */
+
+ if (best < 0)
+ best = 0;
+ if (best > devc->nr_voice)
+ best -= devc->nr_voice;
- printk ("OPL3: Out of free voices\n");
- return 0; /* All voices in use. Select the first one. */
+ return best; /* All devc->voc in use. Select the first
+ * one. */
+}
+
+static void
+opl3_setup_voice(int dev, int voice, int chn)
+{
+ struct channel_info *info =
+ &synth_devs[dev]->chn_info[chn];
+
+ opl3_set_instr(dev, voice, info->pgm_num);
+
+ devc->voc[voice].bender = info->bender_value;
+ devc->voc[voice].volume = info->controllers[CTL_MAIN_VOLUME];
}
static struct synth_operations opl3_operations =
{
- &fm_info,
- 0,
- SYNTH_TYPE_FM,
- FM_TYPE_ADLIB,
- opl3_open,
- opl3_close,
- opl3_ioctl,
- opl3_kill_note,
- opl3_start_note,
- opl3_set_instr,
- opl3_reset,
- opl3_hw_control,
- opl3_load_patch,
- opl3_aftertouch,
- opl3_controller,
- opl3_panning,
- opl3_volume_method,
- opl3_patchmgr,
- opl3_bender,
- opl3_alloc_voice
+ NULL,
+ 0,
+ SYNTH_TYPE_FM,
+ FM_TYPE_ADLIB,
+ opl3_open,
+ opl3_close,
+ opl3_ioctl,
+ opl3_kill_note,
+ opl3_start_note,
+ opl3_set_instr,
+ opl3_reset,
+ opl3_hw_control,
+ opl3_load_patch,
+ opl3_aftertouch,
+ opl3_controller,
+ opl3_panning,
+ opl3_volume_method,
+ opl3_patchmgr,
+ opl3_bender,
+ opl3_alloc_voice,
+ opl3_setup_voice
};
-long
-opl3_init (long mem_start)
+void
+opl3_init(int ioaddr, sound_os_info * osp)
{
- int i;
-
- PERMANENT_MALLOC (struct sbi_instrument *, instrmap,
- SBFM_MAXINSTR * sizeof (*instrmap), mem_start);
-
- if (num_synths >= MAX_SYNTH_DEV)
- printk ("OPL3 Error: Too many synthesizers\n");
- else
- {
- synth_devs[num_synths++] = &opl3_operations;
- voice_alloc = &opl3_operations.alloc;
- chn_info = &opl3_operations.chn_info[0];
+ int i;
+
+ if (num_synths >= MAX_SYNTH_DEV) {
+ printf("OPL3 Error: Too many synthesizers\n");
+ return ;
+ }
+ if (devc == NULL) {
+ printf("OPL3: Device control structure not initialized.\n");
+ return ;
+ }
+ bzero((char *) devc, sizeof(*devc));
+ devc->osp = osp;
+
+ devc->nr_voice = 9;
+ strcpy(devc->fm_info.name, "OPL2-");
+
+ devc->fm_info.device = 0;
+ devc->fm_info.synth_type = SYNTH_TYPE_FM;
+ devc->fm_info.synth_subtype = FM_TYPE_ADLIB;
+ devc->fm_info.perc_mode = 0;
+ devc->fm_info.nr_voices = 9;
+ devc->fm_info.nr_drums = 0;
+ devc->fm_info.instr_bank_size = SBFM_MAXINSTR;
+ devc->fm_info.capabilities = 0;
+ devc->left_io = ioaddr;
+ devc->right_io = ioaddr + 2;
+
+ if (detected_model <= 2)
+ devc->model = 1;
+ else {
+ devc->model = 2;
+ if (detected_model == 4)
+ devc->is_opl4 = 1;
}
- fm_model = 0;
- opl3_ok = 1;
- if (opl3_enabled)
- {
- printk (" <Yamaha OPL-3 FM>");
- fm_model = 2;
- voice_alloc->max_voice = nr_voices = 18;
- fm_info.nr_drums = 0;
- fm_info.capabilities |= SYNTH_CAP_OPL3;
-#ifndef SCO
- strcpy (fm_info.name, "Yamaha OPL-3");
-#endif
+ opl3_operations.info = &devc->fm_info;
+
+ synth_devs[num_synths++] = &opl3_operations;
+ devc->v_alloc = &opl3_operations.alloc;
+ devc->chn_info = &opl3_operations.chn_info[0];
- for (i = 0; i < 18; i++)
- if (physical_voices[i].ioaddr == USE_LEFT)
- physical_voices[i].ioaddr = left_address;
+ if (devc->model == 2) {
+ if (devc->is_opl4)
+ conf_printf2("Yamaha OPL4/OPL3 FM", ioaddr, 0, -1, -1);
else
- physical_voices[i].ioaddr = right_address;
-
-
- opl3_command (right_address, OPL3_MODE_REGISTER, OPL3_ENABLE); /*
- * Enable
- * OPL-3
- * mode
- */
- opl3_command (right_address, CONNECTION_SELECT_REGISTER, 0x00); /*
- * Select
- * all
- * 2-OP
- * *
- * voices
- */
- }
- else
- {
- printk (" <Yamaha 2-OP FM>");
- fm_model = 1;
- voice_alloc->max_voice = nr_voices = 9;
- fm_info.nr_drums = 0;
-
- for (i = 0; i < 18; i++)
- physical_voices[i].ioaddr = left_address;
+ conf_printf2("Yamaha OPL3 FM", ioaddr, 0, -1, -1);
+
+ devc->v_alloc->max_voice = devc->nr_voice = 18;
+ devc->fm_info.nr_drums = 0;
+ devc->fm_info.capabilities |= SYNTH_CAP_OPL3;
+ strcpy(devc->fm_info.name, "Yamaha OPL-3");
+
+ for (i = 0; i < 18; i++)
+ if (pv_map[i].ioaddr == USE_LEFT)
+ pv_map[i].ioaddr = devc->left_io;
+ else
+ pv_map[i].ioaddr = devc->right_io;
+
+ opl3_command(devc->right_io, OPL3_MODE_REGISTER, OPL3_ENABLE);
+ opl3_command(devc->right_io, CONNECTION_SELECT_REGISTER, 0x00);
+ } else {
+ conf_printf2("Yamaha OPL2 FM", ioaddr, 0, -1, -1);
+ devc->v_alloc->max_voice = devc->nr_voice = 9;
+ devc->fm_info.nr_drums = 0;
+
+ for (i = 0; i < 18; i++)
+ pv_map[i].ioaddr = devc->left_io;
};
- already_initialized = 1;
- for (i = 0; i < SBFM_MAXINSTR; i++)
- instrmap[i].channel = -1;
+ for (i = 0; i < SBFM_MAXINSTR; i++)
+ devc->i_map[i].channel = -1;
- return mem_start;
+ return ;
}
#endif
diff --git a/sys/i386/isa/sound/opl3.h b/sys/i386/isa/sound/opl3.h
index ea7901fc60a5..afa8d16459e7 100644
--- a/sys/i386/isa/sound/opl3.h
+++ b/sys/i386/isa/sound/opl3.h
@@ -80,6 +80,7 @@
#define OPL3_MODE_REGISTER 0x05 /* Right side */
#define OPL3_ENABLE 0x01
+#define OPL4_ENABLE 0x02
#define KBD_SPLIT_REGISTER 0x08 /* Left side */
#define COMPOSITE_SINE_WAVE_MODE 0x80 /* Don't use with OPL-3? */
@@ -101,12 +102,12 @@
*
* AM/VIB/EG/KSR/Multiple (0x20 to 0x35)
*/
- #define AM_VIB 0x20
- #define TREMOLO_ON 0x80
- #define VIBRATO_ON 0x40
- #define SUSTAIN_ON 0x20
- #define KSR 0x10 /* Key scaling rate */
- #define MULTIPLE_MASK 0x0f /* Frequency multiplier */
+#define AM_VIB 0x20
+#define TREMOLO_ON 0x80
+#define VIBRATO_ON 0x40
+#define SUSTAIN_ON 0x20
+#define KSR 0x10 /* Key scaling rate */
+#define MULTIPLE_MASK 0x0f /* Frequency multiplier */
/*
* KSL/Total level (0x40 to 0x55)
@@ -230,7 +231,7 @@ struct physical_voice_info {
#define USE_LEFT 0
#define USE_RIGHT 1
-static struct physical_voice_info physical_voices[18] =
+static struct physical_voice_info pv_map[18] =
{
/* No Mode Side OP1 OP2 OP3 OP4 */
/* --------------------------------------------------- */
diff --git a/sys/i386/isa/sound/os.h b/sys/i386/isa/sound/os.h
index 0b0ac6295c2f..104906917ec4 100644
--- a/sys/i386/isa/sound/os.h
+++ b/sys/i386/isa/sound/os.h
@@ -1,306 +1,99 @@
-#ifndef _OS_H_
-#define _OS_H_
/*
- * OS specific settings for 386BSD
- *
- * This chould be used as an example when porting the driver to a new
- * operating systems.
+ * os.h -- only included by sound_config.h right after local.h
*
- * What you should do is to rewrite the soundcard.c and os.h (this file).
- * You should create a new subdirectory and put these two files there.
- * In addition you have to do a makefile.<OS>.
- *
- * If you have to make changes to other than these two files, please contact me
- * before making the changes. It's possible that I have already made the
- * change.
*/
-/*
- * Insert here the includes required by your kernel.
- */
-
-#include "param.h"
-#include "systm.h"
-#include "ioctl.h"
-#include "tty.h"
-#include "proc.h"
-#include "user.h"
-#include "conf.h"
-#include "file.h"
-#include "uio.h"
-/* #include "kernel.h" */
-#include "syslog.h"
-#include "errno.h"
-#include "malloc.h"
-#include "buf.h"
-#include "i386/isa/isa_device.h"
+#ifndef _OS_H_
+#define _OS_H_
-/* These few lines are used by 386BSD (only??). */
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/conf.h>
+#include <sys/fcntl.h>
+#include <sys/filio.h>
+#include <sys/uio.h>
+#include <sys/kernel.h>
+#include <sys/poll.h>
+#include <sys/malloc.h>
+#include <sys/buf.h>
+#include <sys/signalvar.h>
#if NSND > 0
-#define KERNEL_SOUNDCARD
-#else
-#undef KERNEL_SOUNDCARD
-#endif
-
-/*
- * Rest of the file is compiled only if the driver is really required.
- */
-#ifdef CONFIGURE_SOUNDCARD
-
-/*
- * select() is currently implemented in Linux specific way. Don't enable.
- * I don't remember what the SHORT_BANNERS means so forget it.
- */
-
-#undef ALLOW_SELECT
-#define SHORT_BANNERS
-
-/* The soundcard.h could be in a nonstandard place so inclyde it here. */
-#include "soundcard.h"
-
-/*
- * Here is the first portability problem. Every OS has it's own way to
- * pass a pointer to the buffer in read() and write() calls. In Linux it's
- * just a char*. In BSD it's struct uio. This parameter is passed to
- * all functions called from read() or write(). Since nothing can be
- * assumed about this structure, the driver uses set of macros for
- * accessing the user buffer.
- *
- * The driver reads/writes bytes in the user buffer sequentially which
- * means that calls like uiomove() can be used.
- *
- * snd_rw_buf is the type which is passed to the device file specific
- * read() and write() calls.
- *
- * The following macros are used to move date to and from the
- * user buffer. These macros should be used only when the
- * target or source parameter has snd_rw_buf type.
- * The offs parameter is a offset relative to the beginning of
- * the user buffer. In Linux the offset is required but for example
- * BSD passes the offset info in the uio structure. It could be usefull
- * if these macros verify that the offs parameter and the value in
- * the snd_rw_buf structure are equal.
- */
+#include <machine/soundcard.h>
+#undef DELAY
+#define DELAY(x) tenmicrosec(x)
typedef struct uio snd_rw_buf;
-/*
- * Move bytes from the buffer which the application given in a
- * write() call.
- * offs is position relative to the beginning of the buffer in
- * user space. The count is number of bytes to be moved.
- */
-#define COPY_FROM_USER(target, source, offs, count) \
- if (uiomove(target, count, source)) { \
- printf ("sb: Bad copyin()!\n"); \
- } else
-/* Like COPY_FOM_USER but for writes. */
-#define COPY_TO_USER(target, offs, source, count) \
- if (uiomove(source, count, target)) { \
- printf ("sb: Bad copyout()!\n"); \
- } else
-/*
- * The following macros are like COPY_*_USER but work just with one byte (8bit),
- * short (16 bit) or long (32 bit) at a time.
- * The same restrictions apply than for COPY_*_USER
- */
-#define GET_BYTE_FROM_USER(target, addr, offs) {uiomove((char*)&(target), 1, addr);}
-#define GET_SHORT_FROM_USER(target, addr, offs) {uiomove((char*)&(target), 2, addr);}
-#define GET_WORD_FROM_USER(target, addr, offs) {uiomove((char*)&(target), 4, addr);}
-#define PUT_WORD_TO_USER(addr, offs, data) {uiomove((char*)&(data), 4, addr);}
+struct snd_wait {
+ int mode;
+ int aborting;
+};
-/*
- * The way how the ioctl arguments are passed is another nonportable thing.
- * In Linux the argument is just a pointer directly to the user segment. On
- * 386bsd the data is already moved to the kernel space. The following
- * macros should handle the difference.
- */
-/*
- * IOCTL_FROM_USER is used to copy a record pointed by the argument to
- * a buffer in the kernel space. On 386bsd it can be done just by calling
- * memcpy. With Linux a memcpy_from_fs should be called instead.
- * Parameters of the following macros are like in the COPY_*_USER macros.
- */
+unsigned long get_time(void);
-/*
- * When the ioctl argument points to a record or array (longer than 32 bits),
- * the macros IOCTL_*_USER are used. It's assumed that the source and target
- * parameters are direct memory addresses.
- */
-#define IOCTL_FROM_USER(target, source, offs, count) {memcpy(target, &((source)[offs]), count);}
-#define IOCTL_TO_USER(target, offs, source, count) {memcpy(&((target)[offs]), source, count);}
-/* The following macros are used if the ioctl argument points to 32 bit int */
-#define IOCTL_IN(arg) (*(int*)arg)
-#define IOCTL_OUT(arg, ret) *(int*)arg = ret
+#endif /* NSND > 0 */
+#endif /* _OS_H_ */
-/*
- * When the driver displays something to the console, printk() will be called.
- * The name can be changed here.
- */
-#define printk printf
-
-/*
- * The following macros define an interface to the process management.
- */
+typedef caddr_t ioctl_arg;
-struct snd_wait {
- int mode; int aborting;
- };
+typedef struct sound_os_info {
+ int unit;
+} sound_os_info;
-/*
- * DEFINE_WAIT_QUEUE is used where a wait queue is required. It must define
- * a structure which can be passed as a parameter to a sleep(). The second
- * parameter is name of a flag variable (must be defined as int).
- */
-#define DEFINE_WAIT_QUEUE(qname, flag) static int *qname = NULL; \
- static volatile struct snd_wait flag = {0}
-/* Like the above but defines an array of wait queues and flags */
-#define DEFINE_WAIT_QUEUES(qname, flag) static int *qname = {NULL}; \
- static volatile struct snd_wait flag = {{0}}
-#define RESET_WAIT_QUEUE(q, f) {f.aborting = 0;f.mode = WK_NONE;}
-#define SET_ABORT_FLAG(q, f) f.aborting = 1
-#define TIMED_OUT(q, f) (f.mode & WK_TIMEOUT)
-#define SOMEONE_WAITING(q, f) (f.mode & WK_SLEEP)
/*
- * This driver handles interrupts little bit nonstandard way. The following
- * macro is used to test if the current process has received a signal which
- * is aborts the process. This macro is called from close() to see if the
- * buffers should be discarded. If this kind info is not available, a constant
- * 1 or 0 could be returned (1 should be better than 0).
- * I'm not sure if the following is correct for 386BSD.
- */
-#define PROCESS_ABORTING(q, f) (f.aborting | curproc->p_sig)
-
-/*
- * The following macro calls sleep. It should be implemented such that
- * the process is resumed if it receives a signal. The following is propably
- * not the way how it should be done on 386bsd.
- * The on_what parameter is a wait_queue defined with DEFINE_WAIT_QUEUE(),
+ * The following macro calls tsleep. It should be implemented such that
+ * the process is resumed if it receives a signal.
+ * The q parameter is a wait_queue defined with DEFINE_WAIT_QUEUE(),
* and the second is a workarea parameter. The third is a timeout
* in ticks. Zero means no timeout.
*/
#define DO_SLEEP(q, f, time_limit) \
{ \
- int flag, chn; \
+ int flag; \
f.mode = WK_SLEEP; \
- q = &chn; \
- flag=tsleep(&chn, (PRIBIO-5)|PCATCH, "sndint", time_limit); \
- if(flag == ERESTART) f.aborting = 1;\
- else f.aborting = 0;\
+ flag=tsleep(&q, (PRIBIO-5)|PCATCH, "sndint", time_limit); \
f.mode &= ~WK_SLEEP; \
+ if (flag == EWOULDBLOCK) { \
+ f.mode |= WK_TIMEOUT; \
+ f.aborting = 0; \
+ } else \
+ f.aborting = flag; \
}
-/* An the following wakes up a process */
-#define WAKE_UP(q, f) {f.mode = WK_WAKEUP;wakeup(q);}
-
-/*
- * Timing macros. This driver assumes that there is a timer running in the
- * kernel. The timer should return a value which is increased once at every
- * timer tick. The macro HZ should return the number of such ticks/sec.
- */
-
-#ifndef HZ
-extern int hz;
-#define HZ hz
-#endif
-
-/*
- * GET_TIME() returns current value of the counter incremented at timer
- * ticks. This can overflow, so the timeout might be real big...
- *
- */
-unsigned long get_time(void);
-#define GET_TIME() get_time()
-/*#define GET_TIME() (lbolt) /* Returns current time (1/HZ secs since boot) */
-
-/*
- * The following three macros are called before and after atomic
- * code sequences. The flags parameter has always type of unsigned long.
- * The macro DISABLE_INTR() should ensure that all interrupts which
- * may invoke any part of the driver (timer, soundcard interrupts) are
- * disabled.
- * RESTORE_INTR() should return the interrupt status back to the
- * state when DISABLE_INTR() was called. The flags parameter is
- * a variable which can carry 32 bits of state information between
- * DISABLE_INTR() and RESTORE_INTR() calls.
- */
-#define DISABLE_INTR(flags) flags = splhigh()
-#define RESTORE_INTR(flags) splx(flags)
-
-/*
- * INB() and OUTB() should be obvious. NOTE! The order of
- * paratemeters of OUTB() is different than on some other
- * operating systems.
- */
-
-#define INB inb
-/*
- * The outb(0, 0x80) is just for slowdown. It's bit unsafe since
- * this address could be used for something usefull.
- */
-#define OUTB(addr, data) {outb(data, addr);outb(0, 0x80);}
-
-/* memcpy() was not defined og 386bsd. Lets define it here */
-#define memcpy(d, s, c) bcopy(s, d, c)
-
-/*
- * When a error (such as EINVAL) is returned by a function,
- * the following macro is used. The driver assumes that a
- * error is signalled by returning a negative value.
- */
-
-#define RET_ERROR(err) -(err)
-/*
- KERNEL_MALLOC() allocates requested number of memory and
- KERNEL_FREE is used to free it.
- These macros are never called from interrupt, in addition the
- nbytes will never be more than 4096 bytes. Generally the driver
- will allocate memory in blocks of 4k. If the kernel has just a
- page level memory allocation, 4K can be safely used as the size
- (the nbytes parameter can be ignored).
-*/
-#define KERNEL_MALLOC(nbytes) malloc(nbytes, M_TEMP, M_WAITOK)
-#define KERNEL_FREE(addr) free(addr, M_TEMP)
-
-/*
- * The macro PERMANENT_MALLOC(typecast, mem_ptr, size, linux_ptr)
- * returns size bytes of
- * (kernel virtual) memory which will never get freed by the driver.
- * This macro is called only during boot. The linux_ptr is a linux specific
- * parameter which should be ignored in other operating systems.
- * The mem_ptr is a pointer variable where the macro assigns pointer to the
- * memory area. The type is the type of the mem_ptr.
- */
-#define PERMANENT_MALLOC(typecast, mem_ptr, size, linux_ptr) \
- {mem_ptr = (typecast)malloc(size, M_DEVBUF, M_NOWAIT); \
- if (!mem_ptr)panic("SOUND: Cannot allocate memory\n");}
-
-/*
- * The macro DEFINE_TIMER defines variables for the ACTIVATE_TIMER if
- * required. The name is the variable/name to be used and the proc is
- * the procedure to be called when the timer expires.
- */
-
-#define DEFINE_TIMER(name, proc)
+#define DO_SLEEP1(q, f, time_limit) \
+ { \
+ int flag; \
+ f.mode = WK_SLEEP; \
+ flag=tsleep(&q, (PRIBIO-5)|PCATCH, "snd1", time_limit); \
+ f.mode &= ~WK_SLEEP; \
+ if (flag == EWOULDBLOCK) { \
+ f.mode |= WK_TIMEOUT; \
+ f.aborting = 0; \
+ } else \
+ f.aborting = flag; \
+ }
-/*
- * The ACTIVATE_TIMER requests system to call 'proc' after 'time' ticks.
- */
+#define DO_SLEEP2(q, f, time_limit) \
+ { \
+ int flag; \
+ f.mode = WK_SLEEP; \
+ flag=tsleep(&q, (PRIBIO-5)|PCATCH, "snd2", time_limit); \
+ f.mode &= ~WK_SLEEP; \
+ if (flag == EWOULDBLOCK) { \
+ f.mode |= WK_TIMEOUT; \
+ f.aborting = 0; \
+ } else \
+ f.aborting = flag; \
+ }
-#define ACTIVATE_TIMER(name, proc, time) \
- timeout(proc, 0, time);
-/*
- * The rest of this file is not complete yet. The functions using these
- * macros will not work
- */
-#define ALLOC_DMA_CHN(chn) (0)
-#define RELEASE_DMA_CHN(chn) (0)
-#define DMA_MODE_READ 0
-#define DMA_MODE_WRITE 1
-#define RELEASE_IRQ(irq_no)
+#define PROCESS_ABORTING( f) (f.aborting || CURSIG(curproc))
+#define TIMED_OUT( f) (f.mode & WK_TIMEOUT)
-#endif
+#ifdef ALLOW_POLL
+typedef struct proc select_table;
+extern struct selinfo selinfo[];
#endif
diff --git a/sys/i386/isa/sound/pas2_card.c b/sys/i386/isa/sound/pas2_card.c
index 1bfd73fcc404..79acf57d45f5 100644
--- a/sys/i386/isa/sound/pas2_card.c
+++ b/sys/i386/isa/sound/pas2_card.c
@@ -1,11 +1,10 @@
-#define _PAS2_CARD_C_
/*
* 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
@@ -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,15 +24,15 @@
* 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 <i386/isa/sound/sound_config.h>
-#include "sound_config.h"
-
-#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_PAS)
+#if defined(CONFIG_PAS)
+#define _PAS2_CARD_C_
#define DEFINE_TRANSLATIONS
-#include "pas.h"
+#include <i386/isa/sound/pas_hw.h>
/*
* The Address Translation code is used to convert I/O register addresses to
@@ -44,12 +43,14 @@ int translat_code;
static int pas_intr_mask = 0;
static int pas_irq = 0;
-static char pas_model;
+sound_os_info *pas_osp;
+
+char pas_model;
static char *pas_model_names[] =
{"", "Pro AudioSpectrum+", "CDPC", "Pro AudioSpectrum 16", "Pro AudioSpectrum 16D"};
/*
- * pas_read() and pas_write() are equivalents of INB() and OUTB()
+ * pas_read() and pas_write() are equivalents of inb and outb
*/
/*
* These routines perform the I/O address translation required
@@ -57,89 +58,72 @@ static char *pas_model_names[] =
/*
* to support other than the default base address
*/
+extern void mix_write(u_char data, int ioaddr);
-unsigned char
-pas_read (int ioaddr)
+u_char
+pas_read(int ioaddr)
{
- return INB (ioaddr ^ translat_code);
+ return inb(ioaddr ^ translat_code);
}
void
-pas_write (unsigned char data, int ioaddr)
+pas_write(u_char data, int ioaddr)
{
- OUTB (data, ioaddr ^ translat_code);
+ outb(ioaddr ^ translat_code, data);
}
void
-pas2_msg (char *foo)
+pas2_msg(char *foo)
{
- printk (" PAS2: %s.\n", foo);
+ printf(" PAS2: %s.\n", foo);
}
/******************* Begin of the Interrupt Handler ********************/
void
-pasintr (int unused)
+pasintr(int irq)
{
- int status;
+ int status;
- status = pas_read (INTERRUPT_STATUS);
- pas_write (status, INTERRUPT_STATUS); /*
- * Clear interrupt
- */
+ status = pas_read(INTERRUPT_STATUS);
+ pas_write(status, INTERRUPT_STATUS); /* Clear interrupt */
- if (status & I_S_PCM_SAMPLE_BUFFER_IRQ)
- {
-#ifndef EXCLUDE_AUDIO
- pas_pcm_interrupt (status, 1);
-#endif
- status &= ~I_S_PCM_SAMPLE_BUFFER_IRQ;
- }
- if (status & I_S_MIDI_IRQ)
- {
-#ifndef EXCLUDE_MIDI
-#ifdef EXCLUDE_PRO_MIDI
- pas_midi_interrupt ();
+ if (status & I_S_PCM_SAMPLE_BUFFER_IRQ) {
+#ifdef CONFIG_AUDIO
+ pas_pcm_interrupt(status, 1);
#endif
+ status &= ~I_S_PCM_SAMPLE_BUFFER_IRQ;
+ }
+ if (status & I_S_MIDI_IRQ) {
+#ifdef CONFIG_MIDI
+ pas_midi_interrupt();
#endif
- status &= ~I_S_MIDI_IRQ;
- }
-
+ status &= ~I_S_MIDI_IRQ;
+ }
}
int
-pas_set_intr (int mask)
+pas_set_intr(int mask)
{
- int err;
-
- if (!mask)
- return 0;
+ if (!mask)
+ return 0;
- if (!pas_intr_mask)
- {
- if ((err = snd_set_irq_handler (pas_irq, pasintr)) < 0)
- return err;
- }
- pas_intr_mask |= mask;
+ pas_intr_mask |= mask;
- pas_write (pas_intr_mask, INTERRUPT_MASK);
- return 0;
+ pas_write(pas_intr_mask, INTERRUPT_MASK);
+ return 0;
}
int
-pas_remove_intr (int mask)
+pas_remove_intr(int mask)
{
- if (!mask)
- return 0;
+ if (!mask)
+ return 0;
- pas_intr_mask &= ~mask;
- pas_write (pas_intr_mask, INTERRUPT_MASK);
+ pas_intr_mask &= ~mask;
+ pas_write(pas_intr_mask, INTERRUPT_MASK);
- if (!pas_intr_mask)
- {
- snd_release_irq (pas_irq);
- }
- return 0;
+ return 0;
}
/******************* End of the Interrupt handler **********************/
@@ -147,261 +131,231 @@ pas_remove_intr (int mask)
/******************* Begin of the Initialization Code ******************/
int
-config_pas_hw (struct address_info *hw_config)
+config_pas_hw(struct address_info * hw_config)
{
- char ok = 1;
- unsigned int_ptrs; /* scsi/sound interrupt pointers */
-
- pas_irq = hw_config->irq;
-
- pas_write (0x00, INTERRUPT_MASK);
-
- pas_write (0x36, SAMPLE_COUNTER_CONTROL); /*
- * Local timer control *
- * register
- */
-
- pas_write (0x36, SAMPLE_RATE_TIMER); /*
- * Sample rate timer (16 bit)
- */
- pas_write (0, SAMPLE_RATE_TIMER);
-
- pas_write (0x74, SAMPLE_COUNTER_CONTROL); /*
- * Local timer control *
- * register
- */
-
- pas_write (0x74, SAMPLE_BUFFER_COUNTER); /*
- * Sample count register (16
- * * bit)
- */
- pas_write (0, SAMPLE_BUFFER_COUNTER);
-
- pas_write (F_F_PCM_BUFFER_COUNTER | F_F_PCM_RATE_COUNTER | F_F_MIXER_UNMUTE | 1, FILTER_FREQUENCY);
- pas_write (P_C_PCM_DMA_ENABLE | P_C_PCM_MONO | P_C_PCM_DAC_MODE | P_C_MIXER_CROSS_L_TO_L | P_C_MIXER_CROSS_R_TO_R, PCM_CONTROL);
- pas_write (S_M_PCM_RESET | S_M_FM_RESET | S_M_SB_RESET | S_M_MIXER_RESET /*
- * |
- * S_M_OPL3_DUAL_MONO
- */ , SERIAL_MIXER);
-
- pas_write (I_C_1_BOOT_RESET_ENABLE, IO_CONFIGURATION_1);
-
- if (pas_irq < 0 || pas_irq > 15)
- {
- printk ("PAS2: Invalid IRQ %d", pas_irq);
- ok = 0;
- }
- else
- {
- int_ptrs = pas_read (IO_CONFIGURATION_3);
- int_ptrs |= I_C_3_PCM_IRQ_translate[pas_irq] & 0xf;
- pas_write (int_ptrs, IO_CONFIGURATION_3);
- if (!I_C_3_PCM_IRQ_translate[pas_irq])
- {
- printk ("PAS2: Invalid IRQ %d", pas_irq);
- ok = 0;
+ char ok = 1;
+ u_int int_ptrs; /* scsi/sound interrupt pointers */
+
+ pas_irq = hw_config->irq;
+
+ pas_write(0x00, INTERRUPT_MASK);
+
+ pas_write(0x36, SAMPLE_COUNTER_CONTROL); /* Local timer control *
+ * register */
+
+ pas_write(0x36, SAMPLE_RATE_TIMER); /* Sample rate timer (16 bit) */
+ pas_write(0, SAMPLE_RATE_TIMER);
+
+ pas_write(0x74, SAMPLE_COUNTER_CONTROL); /* Local timer control *
+ * register */
+
+ pas_write(0x74, SAMPLE_BUFFER_COUNTER); /* Sample count register (16 *
+ * bit) */
+ pas_write(0, SAMPLE_BUFFER_COUNTER);
+
+ pas_write(F_F_PCM_BUFFER_COUNTER | F_F_PCM_RATE_COUNTER | F_F_MIXER_UNMUTE | 1, FILTER_FREQUENCY);
+ pas_write(P_C_PCM_DMA_ENABLE | P_C_PCM_MONO | P_C_PCM_DAC_MODE | P_C_MIXER_CROSS_L_TO_L | P_C_MIXER_CROSS_R_TO_R, PCM_CONTROL);
+ pas_write(S_M_PCM_RESET | S_M_FM_RESET | S_M_SB_RESET | S_M_MIXER_RESET /* | S_M_OPL3_DUAL_MONO */ , SERIAL_MIXER);
+
+ pas_write(I_C_1_BOOT_RESET_ENABLE
+#ifdef PAS_JOYSTICK_ENABLE
+ | I_C_1_JOYSTICK_ENABLE
+#endif
+ ,IO_CONFIGURATION_1);
+
+ if (pas_irq < 0 || pas_irq > 15) {
+ printf("PAS2: Invalid IRQ %d", pas_irq);
+ ok = 0;
+ } else {
+ int_ptrs = pas_read(IO_CONFIGURATION_3);
+ int_ptrs |= I_C_3_PCM_IRQ_translate[pas_irq] & 0xf;
+ pas_write(int_ptrs, IO_CONFIGURATION_3);
+ if (!I_C_3_PCM_IRQ_translate[pas_irq]) {
+ printf("PAS2: Invalid IRQ %d", pas_irq);
+ ok = 0;
+ } else {
+ if (snd_set_irq_handler(pas_irq, pasintr, hw_config->osp) < 0)
+ ok = 0;
+ }
}
- }
-
- if (hw_config->dma < 0 || hw_config->dma > 7)
- {
- printk ("PAS2: Invalid DMA selection %d", hw_config->dma);
- ok = 0;
- }
- else
- {
- pas_write (I_C_2_PCM_DMA_translate[hw_config->dma], IO_CONFIGURATION_2);
- if (!I_C_2_PCM_DMA_translate[hw_config->dma])
- {
- printk ("PAS2: Invalid DMA selection %d", hw_config->dma);
- ok = 0;
+
+ if (hw_config->dma < 0 || hw_config->dma > 7) {
+ printf("PAS2: Invalid DMA selection %d", hw_config->dma);
+ ok = 0;
+ } else {
+ pas_write(I_C_2_PCM_DMA_translate[hw_config->dma], IO_CONFIGURATION_2);
+ if (!I_C_2_PCM_DMA_translate[hw_config->dma]) {
+ printf("PAS2: Invalid DMA selection %d", hw_config->dma);
+ ok = 0;
+ } else {
+ if (0) {
+ printf("pas2_card.c: Can't allocate DMA channel\n");
+ 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.
- */
+ /*
+ * 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(0xa8, 0x05);
+ outb(0xa9, 0x60);
#endif
#ifdef BROKEN_BUS_CLOCK
- pas_write (S_C_1_PCS_ENABLE | S_C_1_PCS_STEREO | S_C_1_PCS_REALSOUND | S_C_1_FM_EMULATE_CLOCK, SYSTEM_CONFIGURATION_1);
+ pas_write(S_C_1_PCS_ENABLE | S_C_1_PCS_STEREO | S_C_1_PCS_REALSOUND | S_C_1_FM_EMULATE_CLOCK, SYSTEM_CONFIGURATION_1);
#else
- /*
- * pas_write(S_C_1_PCS_ENABLE, SYSTEM_CONFIGURATION_1);
- */
- pas_write (S_C_1_PCS_ENABLE | S_C_1_PCS_STEREO | S_C_1_PCS_REALSOUND, SYSTEM_CONFIGURATION_1);
+ /*
+ * pas_write(S_C_1_PCS_ENABLE, SYSTEM_CONFIGURATION_1);
+ */
+ pas_write(S_C_1_PCS_ENABLE | S_C_1_PCS_STEREO | S_C_1_PCS_REALSOUND, SYSTEM_CONFIGURATION_1);
#endif
- pas_write (0x18, SYSTEM_CONFIGURATION_3); /*
- * ???
- */
+ pas_write(0x18, SYSTEM_CONFIGURATION_3); /* ??? */
- pas_write (F_F_MIXER_UNMUTE | 0x01, FILTER_FREQUENCY); /*
- * Sets mute
- * off and *
- * selects
- * filter
- * rate * of
- * 17.897 kHz
- */
+ pas_write(F_F_MIXER_UNMUTE | 0x01, FILTER_FREQUENCY); /* Sets mute off and *
+ * selects filter rate *
+ * of 17.897 kHz */
+ pas_write(8, PRESCALE_DIVIDER);
- if (pas_model == PAS_16 || pas_model == PAS_16D)
- pas_write (8, PRESCALE_DIVIDER);
- else
- pas_write (0, PRESCALE_DIVIDER);
+ mix_write(P_M_MV508_ADDRESS | 5, PARALLEL_MIXER);
+ mix_write(5, PARALLEL_MIXER);
- pas_write (P_M_MV508_ADDRESS | 5, PARALLEL_MIXER);
- pas_write (5, PARALLEL_MIXER);
+#if defined(CONFIG_SB_EMULATION) && defined(CONFIG_SB)
-#if !defined(EXCLUDE_SB_EMULATION) || !defined(EXCLUDE_SB)
+ {
+ struct address_info *sb_config;
+
+ if ((sb_config = sound_getconf(SNDCARD_SB))) {
+ u_char irq_dma;
+
+ /*
+ * Turn on Sound Blaster compatibility
+ */
+ /*
+ * bit 1 = SB emulation
+ */
+ /*
+ * bit 0 = MPU401 emulation (CDPC only :-( )
+ */
+ pas_write(0x02, COMPATIBILITY_ENABLE);
+
+ /*
+ * "Emulation address"
+ */
+ pas_write((sb_config->io_base >> 4) & 0x0f, EMULATION_ADDRESS);
+
+ if (!E_C_SB_DMA_translate[sb_config->dma])
+ printf("\n\nPAS16 Warning: Invalid SB DMA %d\n\n",
+ sb_config->dma);
+
+ if (!E_C_SB_IRQ_translate[sb_config->irq])
+ printf("\n\nPAS16 Warning: Invalid SB IRQ %d\n\n",
+ sb_config->irq);
+
+ irq_dma = E_C_SB_DMA_translate[sb_config->dma] |
+ E_C_SB_IRQ_translate[sb_config->irq];
+
+ pas_write(irq_dma, EMULATION_CONFIGURATION);
+ }
+ }
+#else
+ pas_write(0x00, COMPATIBILITY_ENABLE);
+#endif
- {
- struct address_info *sb_config;
+ if (!ok)
+ pas2_msg("Driver not enabled");
- if ((sb_config = sound_getconf (SNDCARD_SB)))
- {
- unsigned char irq_dma;
+ return ok;
+}
- /*
- * Turn on Sound Blaster compatibility
- */
- /*
- * bit 1 = SB emulation
- */
- /*
- * bit 0 = MPU401 emulation (CDPC only :-( )
- */
- pas_write (0x02, COMPATIBILITY_ENABLE);
+int
+detect_pas_hw(struct address_info * hw_config)
+{
+ u_char board_id, foo;
/*
- * "Emulation address"
+ * WARNING: Setting an option like W:1 or so that disables warm boot
+ * reset of the card will screw up this detect code something fierce.
+ * Adding code to handle this means possibly interfering with other
+ * cards on the bus if you have something on base port 0x388. SO be
+ * forewarned.
*/
- 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);
+ outb(MASTER_DECODE, 0xBC); /* Talk to first board */
+ outb(MASTER_DECODE, hw_config->io_base >> 2); /* Set base address */
+ translat_code = PAS_DEFAULT_BASE ^ hw_config->io_base;
+ pas_write(1, WAIT_STATE); /* One wait-state */
- if (!E_C_SB_IRQ_translate[sb_config->irq])
- printk ("\n\nPAS16 Warning: Invalid SB IRQ %d\n\n",
- sb_config->irq);
+ board_id = pas_read(INTERRUPT_MASK);
- irq_dma = E_C_SB_DMA_translate[sb_config->dma] |
- E_C_SB_IRQ_translate[sb_config->irq];
+ if (board_id == 0xff)
+ return 0;
- pas_write (irq_dma, EMULATION_CONFIGURATION);
- }
- }
-#endif
+ /*
+ * We probably have a PAS-series board, now check for a PAS2-series
+ * board by trying to change the board revision bits. PAS2-series
+ * hardware won't let you do this - the bits are read-only.
+ */
- if (!ok)
- pas2_msg ("Driver not enabled");
+ foo = board_id ^ 0xe0;
- return ok;
-}
+ pas_write(foo, INTERRUPT_MASK);
+ foo = inb(INTERRUPT_MASK);
+ pas_write(board_id, INTERRUPT_MASK);
-int
-detect_pas_hw (struct address_info *hw_config)
-{
- unsigned char board_id, foo;
-
- /*
- * WARNING: Setting an option like W:1 or so that disables warm boot reset
- * of the card will screw up this detect code something fierce. Adding code
- * to handle this means possibly interfering with other cards on the bus if
- * you have something on base port 0x388. SO be forewarned.
- */
-
- OUTB (0xBC, MASTER_DECODE); /*
- * Talk to first board
- */
- OUTB (hw_config->io_base >> 2, MASTER_DECODE); /*
- * Set base address
- */
- translat_code = PAS_DEFAULT_BASE ^ hw_config->io_base;
- pas_write (1, WAIT_STATE); /*
- * One wait-state
- */
-
- board_id = pas_read (INTERRUPT_MASK);
-
- if (board_id == 0xff)
- return 0;
-
- /*
- * We probably have a PAS-series board, now check for a PAS2-series board
- * by trying to change the board revision bits. PAS2-series hardware won't
- * let you do this - the bits are read-only.
- */
-
- foo = board_id ^ 0xe0;
-
- pas_write (foo, INTERRUPT_MASK);
- foo = INB (INTERRUPT_MASK);
- pas_write (board_id, INTERRUPT_MASK);
-
- if (board_id != foo) /*
- * Not a PAS2
- */
- return 0;
-
- pas_model = O_M_1_to_card[pas_read (OPERATION_MODE_1) & 0x0f];
-
- return pas_model;
+ if (board_id != foo) /* Not a PAS2 */
+ return 0;
+
+ pas_model = pas_read(CHIP_REV);
+
+ return pas_model;
}
-long
-attach_pas_card (long mem_start, struct address_info *hw_config)
+void
+attach_pas_card(struct address_info * hw_config)
{
- pas_irq = hw_config->irq;
+ pas_irq = hw_config->irq;
+ pas_osp = hw_config->osp;
- if (detect_pas_hw (hw_config))
- {
+ if (detect_pas_hw(hw_config)) {
- if ((pas_model = O_M_1_to_card[pas_read (OPERATION_MODE_1) & 0x0f]))
- {
- printk (" <%s rev %d>", pas_model_names[(int) pas_model], pas_read (BOARD_REV_ID));
- }
+ if ((pas_model = pas_read(CHIP_REV))) {
+ char temp[100];
- if (config_pas_hw (hw_config))
- {
+ sprintf(temp,
+ "%s rev %d", pas_model_names[(int) pas_model],
+ pas_read(BOARD_REV_ID));
+ conf_printf(temp, hw_config);
+ }
+ if (config_pas_hw(hw_config)) {
-#ifndef EXCLUDE_AUDIO
- mem_start = pas_pcm_init (mem_start, hw_config);
+#ifdef CONFIG_AUDIO
+ pas_pcm_init(hw_config);
#endif
-#if !defined(EXCLUDE_SB_EMULATION) && !defined(EXCLUDE_SB)
+#if defined(CONFIG_SB_EMULATION) && defined(CONFIG_SB)
- sb_dsp_disable_midi (); /*
- * The SB emulation don't support *
- * midi
- */
+ sb_dsp_disable_midi(); /* The SB emulation don't
+ * support * midi */
#endif
-#ifndef EXCLUDE_YM3812
- enable_opl3_mode (0x388, 0x38a, 0);
-#endif
-#ifndef EXCLUDE_MIDI
-#ifdef EXCLUDE_PRO_MIDI
- mem_start = pas_midi_init (mem_start);
+#ifdef CONFIG_MIDI
+ pas_midi_init();
#endif
-#endif
-
- pas_init_mixer ();
+ pas_init_mixer();
+ }
}
- }
-
- return mem_start;
}
int
-probe_pas (struct address_info *hw_config)
+probe_pas(struct address_info * hw_config)
{
- return detect_pas_hw (hw_config);
+ pas_osp = hw_config->osp;
+ return detect_pas_hw(hw_config);
}
#endif
diff --git a/sys/i386/isa/sound/pas2_midi.c b/sys/i386/isa/sound/pas2_midi.c
index 1c6bf5937a03..006b7d4c8087 100644
--- a/sys/i386/isa/sound/pas2_midi.c
+++ b/sys/i386/isa/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,315 +24,262 @@
* 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"
+#include <i386/isa/sound/sound_config.h>
-#ifdef CONFIGURE_SOUNDCARD
-
-#include "pas.h"
-
-#if !defined(EXCLUDE_PAS) && !defined(EXCLUDE_MIDI) && defined(EXCLUDE_PRO_MIDI)
+#if defined(CONFIG_PAS) && defined(CONFIG_MIDI)
+#include <i386/isa/sound/pas_hw.h>
static int midi_busy = 0, input_opened = 0;
static int my_dev;
static volatile int ofifo_bytes = 0;
-static unsigned char tmp_queue[256];
+static u_char tmp_queue[256];
static volatile int qlen;
-static volatile unsigned char qhead, qtail;
+static volatile u_char qhead, qtail;
-static void (*midi_input_intr) (int dev, unsigned char data);
+static void (*midi_input_intr) (int dev, u_char data);
static int
-pas_midi_open (int dev, int mode,
- void (*input) (int dev, unsigned char data),
- void (*output) (int dev)
+pas_midi_open(int dev, int mode,
+ void (*input) (int dev, u_char data),
+ void (*output) (int dev)
)
{
- int err;
- unsigned long flags;
- unsigned char ctrl;
-
-
- if (midi_busy)
- {
- printk ("PAS2: Midi busy\n");
- return RET_ERROR (EBUSY);
- }
-
- /*
- * Reset input and output FIFO pointers
- */
- pas_write (M_C_RESET_INPUT_FIFO | M_C_RESET_OUTPUT_FIFO,
- MIDI_CONTROL);
-
- DISABLE_INTR (flags);
-
- if ((err = pas_set_intr (I_M_MIDI_IRQ_ENABLE)) < 0)
- return err;
-
- /*
- * Enable input available and output FIFO empty interrupts
- */
-
- ctrl = 0;
- input_opened = 0;
- midi_input_intr = input;
-
- if (mode == OPEN_READ || mode == OPEN_READWRITE)
- {
- ctrl |= M_C_ENA_INPUT_IRQ;/*
- * Enable input
- */
- input_opened = 1;
- }
-
- if (mode == OPEN_WRITE || mode == OPEN_READWRITE)
- {
- ctrl |= M_C_ENA_OUTPUT_IRQ | /*
- * Enable output
- */
- M_C_ENA_OUTPUT_HALF_IRQ;
- }
-
- pas_write (ctrl,
- MIDI_CONTROL);
-
- /*
- * Acknowledge any pending interrupts
- */
-
- pas_write (0xff, MIDI_STATUS);
- ofifo_bytes = 0;
-
- RESTORE_INTR (flags);
-
- midi_busy = 1;
- qlen = qhead = qtail = 0;
- return 0;
+ int err;
+ u_long flags;
+ u_char ctrl;
+
+
+ if (midi_busy) {
+ printf("PAS2: Midi busy\n");
+ return -(EBUSY);
+ }
+ /*
+ * Reset input and output FIFO pointers
+ */
+ pas_write(M_C_RESET_INPUT_FIFO | M_C_RESET_OUTPUT_FIFO,
+ MIDI_CONTROL);
+
+ flags = splhigh();
+
+ if ((err = pas_set_intr(I_M_MIDI_IRQ_ENABLE)) < 0)
+ return err;
+
+ /*
+ * Enable input available and output FIFO empty interrupts
+ */
+
+ ctrl = 0;
+ input_opened = 0;
+ midi_input_intr = input;
+
+ if (mode == OPEN_READ || mode == OPEN_READWRITE) {
+ ctrl |= M_C_ENA_INPUT_IRQ; /* Enable input */
+ input_opened = 1;
+ }
+ if (mode == OPEN_WRITE || mode == OPEN_READWRITE) {
+ ctrl |= M_C_ENA_OUTPUT_IRQ | /* Enable output */
+ M_C_ENA_OUTPUT_HALF_IRQ;
+ }
+ pas_write(ctrl,
+ MIDI_CONTROL);
+
+ /*
+ * Acknowledge any pending interrupts
+ */
+
+ pas_write(0xff, MIDI_STATUS);
+ ofifo_bytes = 0;
+
+ splx(flags);
+
+ midi_busy = 1;
+ qlen = qhead = qtail = 0;
+ return 0;
}
static void
-pas_midi_close (int dev)
+pas_midi_close(int dev)
{
- /*
- * Reset FIFO pointers, disable intrs
- */
- pas_write (M_C_RESET_INPUT_FIFO | M_C_RESET_OUTPUT_FIFO, MIDI_CONTROL);
+ /*
+ * Reset FIFO pointers, disable intrs
+ */
+ pas_write(M_C_RESET_INPUT_FIFO | M_C_RESET_OUTPUT_FIFO, MIDI_CONTROL);
- pas_remove_intr (I_M_MIDI_IRQ_ENABLE);
- midi_busy = 0;
+ pas_remove_intr(I_M_MIDI_IRQ_ENABLE);
+ midi_busy = 0;
}
static int
-dump_to_midi (unsigned char midi_byte)
+dump_to_midi(u_char midi_byte)
{
- int fifo_space, x;
-
- fifo_space = ((x = pas_read (MIDI_FIFO_STATUS)) >> 4) & 0x0f;
+ int fifo_space, x;
- if (fifo_space == 15 || (fifo_space < 2 && ofifo_bytes > 13)) /*
- * Fifo
- * full
- */
- {
- return 0; /*
- * Upper layer will call again
- */
- }
+ fifo_space = ((x = pas_read(MIDI_FIFO_STATUS)) >> 4) & 0x0f;
- ofifo_bytes++;
+ if (fifo_space == 15 || (fifo_space < 2 && ofifo_bytes > 13)) { /* Fifo full */
+ return 0; /* Upper layer will call again */
+ }
+ ofifo_bytes++;
- pas_write (midi_byte, MIDI_DATA);
+ pas_write(midi_byte, MIDI_DATA);
- return 1;
+ return 1;
}
static int
-pas_midi_out (int dev, unsigned char midi_byte)
+pas_midi_out(int dev, u_char midi_byte)
{
- unsigned long flags;
+ u_long flags;
- /*
- * Drain the local queue first
- */
+ /*
+ * Drain the local queue first
+ */
- DISABLE_INTR (flags);
+ flags = splhigh();
- while (qlen && dump_to_midi (tmp_queue[qhead]))
- {
- qlen--;
- qhead++;
- }
+ while (qlen && dump_to_midi(tmp_queue[qhead])) {
+ qlen--;
+ qhead++;
+ }
- RESTORE_INTR (flags);
+ splx(flags);
- /*
- * Output the byte if the local queue is empty.
- */
+ /*
+ * Output the byte if the local queue is empty.
+ */
- if (!qlen)
- if (dump_to_midi (midi_byte))
- return 1; /*
- * OK
- */
+ if (!qlen)
+ if (dump_to_midi(midi_byte))
+ return 1; /* OK */
- /*
- * Put to the local queue
- */
+ /*
+ * Put to the local queue
+ */
- if (qlen >= 256)
- return 0; /*
- * Local queue full
- */
+ if (qlen >= 256)
+ return 0; /* Local queue full */
- DISABLE_INTR (flags);
+ flags = splhigh();
- tmp_queue[qtail] = midi_byte;
- qlen++;
- qtail++;
+ tmp_queue[qtail] = midi_byte;
+ qlen++;
+ qtail++;
- RESTORE_INTR (flags);
+ splx(flags);
- return 1;
+ return 1;
}
static int
-pas_midi_start_read (int dev)
+pas_midi_start_read(int dev)
{
- return 0;
+ return 0;
}
static int
-pas_midi_end_read (int dev)
+pas_midi_end_read(int dev)
{
- return 0;
+ return 0;
}
static int
-pas_midi_ioctl (int dev, unsigned cmd, unsigned arg)
+pas_midi_ioctl(int dev, u_int cmd, ioctl_arg arg)
{
- return RET_ERROR (EINVAL);
+ return -(EINVAL);
}
static void
-pas_midi_kick (int dev)
+pas_midi_kick(int dev)
{
- ofifo_bytes = 0;
+ ofifo_bytes = 0;
}
static int
-pas_buffer_status (int dev)
+pas_buffer_status(int dev)
{
- return !qlen;
+ return qlen;
}
#define MIDI_SYNTH_NAME "Pro Audio Spectrum Midi"
#define MIDI_SYNTH_CAPS SYNTH_CAP_INPUT
-#include "midi_synth.h"
+#include <i386/isa/sound/midi_synth.h>
static struct midi_operations pas_midi_operations =
{
- {"Pro Audio Spectrum", 0, 0, SNDCARD_PAS},
- &std_midi_synth,
- pas_midi_open,
- pas_midi_close,
- pas_midi_ioctl,
- pas_midi_out,
- pas_midi_start_read,
- pas_midi_end_read,
- pas_midi_kick,
- NULL, /*
- * command
- */
- pas_buffer_status,
- NULL
+ {"Pro Audio Spectrum", 0, 0, SNDCARD_PAS},
+ &std_midi_synth,
+ {0},
+ pas_midi_open,
+ pas_midi_close,
+ pas_midi_ioctl,
+ pas_midi_out,
+ pas_midi_start_read,
+ pas_midi_end_read,
+ pas_midi_kick,
+ NULL, /* command */
+ pas_buffer_status,
+ NULL
};
-long
-pas_midi_init (long mem_start)
+void
+pas_midi_init()
{
- if (num_midis >= MAX_MIDI_DEV)
- {
- printk ("Sound: Too many midi devices detected\n");
- return mem_start;
- }
-
- std_midi_synth.midi_dev = my_dev = num_midis;
- midi_devs[num_midis++] = &pas_midi_operations;
- return mem_start;
+ if (num_midis >= MAX_MIDI_DEV) {
+ printf("Sound: Too many midi devices detected\n");
+ return;
+ }
+ std_midi_synth.midi_dev = my_dev = num_midis;
+ midi_devs[num_midis++] = &pas_midi_operations;
+ return;
}
void
-pas_midi_interrupt (void)
+pas_midi_interrupt(void)
{
- unsigned char stat;
- int i, incount;
- unsigned long flags;
-
- stat = pas_read (MIDI_STATUS);
-
- if (stat & M_S_INPUT_AVAIL) /*
- * Input byte available
- */
- {
- incount = pas_read (MIDI_FIFO_STATUS) & 0x0f; /*
- * Input FIFO count
- */
- if (!incount)
- incount = 16;
-
- for (i = 0; i < incount; i++)
- if (input_opened)
- {
- midi_input_intr (my_dev, pas_read (MIDI_DATA));
- }
- else
- pas_read (MIDI_DATA); /*
- * Flush
- */
- }
-
- if (stat & (M_S_OUTPUT_EMPTY | M_S_OUTPUT_HALF_EMPTY))
- {
- if (!(stat & M_S_OUTPUT_EMPTY))
- {
- ofifo_bytes = 8;
- }
- else
- {
- ofifo_bytes = 0;
+ u_char stat;
+ int i, incount;
+ u_long flags;
+
+ stat = pas_read(MIDI_STATUS);
+
+ if (stat & M_S_INPUT_AVAIL) { /* Input byte available */
+ incount = pas_read(MIDI_FIFO_STATUS) & 0x0f; /* Input FIFO count */
+ if (!incount)
+ incount = 16;
+
+ for (i = 0; i < incount; i++)
+ if (input_opened) {
+ midi_input_intr(my_dev, pas_read(MIDI_DATA));
+ } else
+ pas_read(MIDI_DATA); /* Flush */
}
+ if (stat & (M_S_OUTPUT_EMPTY | M_S_OUTPUT_HALF_EMPTY)) {
+ if (!(stat & M_S_OUTPUT_EMPTY)) {
+ ofifo_bytes = 8;
+ } else {
+ ofifo_bytes = 0;
+ }
- DISABLE_INTR (flags);
+ flags = splhigh();
- while (qlen && dump_to_midi (tmp_queue[qhead]))
- {
- qlen--;
- qhead++;
- }
+ while (qlen && dump_to_midi(tmp_queue[qhead])) {
+ qlen--;
+ qhead++;
+ }
- RESTORE_INTR (flags);
- }
-
- if (stat & M_S_FRAMING_ERROR)
- printk ("MIDI framing error\n");
-
- if (stat & M_S_OUTPUT_OVERRUN)
- {
- printk ("MIDI output overrun %x,%x,%d \n", pas_read (MIDI_FIFO_STATUS), stat, ofifo_bytes);
- ofifo_bytes = 100;
- }
-
- pas_write (stat, MIDI_STATUS);/*
- * Acknowledge interrupts
- */
+ splx(flags);
+ }
+ if (stat & M_S_OUTPUT_OVERRUN) {
+ printf("MIDI output overrun %x,%x,%d \n", pas_read(MIDI_FIFO_STATUS), stat, ofifo_bytes);
+ ofifo_bytes = 100;
+ }
+ pas_write(stat, MIDI_STATUS); /* Acknowledge interrupts */
}
#endif
-
-#endif
diff --git a/sys/i386/isa/sound/pas2_mixer.c b/sys/i386/isa/sound/pas2_mixer.c
index c125b47c181a..4831bd20ae37 100644
--- a/sys/i386/isa/sound/pas2_mixer.c
+++ b/sys/i386/isa/sound/pas2_mixer.c
@@ -1,12 +1,10 @@
-#define _PAS2_MIXER_C_
-
/*
* 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 +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
@@ -26,27 +24,24 @@
* 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"
+#define _PAS2_MIXER_C_
-#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_PAS)
+#include <i386/isa/sound/sound_config.h>
-#include "pas.h"
+#if defined(CONFIG_PAS)
-#define TRACE(what) /*
- * * * (what) */
+#include <i386/isa/sound/pas_hw.h>
-extern int translat_code;
-
-static int rec_devices = (SOUND_MASK_MIC); /*
+#define TRACE(what) /* (what) */
+extern int translat_code;
+extern char pas_model;
+extern sound_os_info *pas_osp;
- * * * * Default *
- * recording * source
- *
- * * */
+static int rec_devices = (SOUND_MASK_MIC); /* Default recording source */
static int mode_control = 0;
#define POSSIBLE_RECORDING_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_SPEAKER | SOUND_MASK_LINE | SOUND_MASK_MIC | \
@@ -57,342 +52,271 @@ static int mode_control = 0;
SOUND_MASK_VOLUME | SOUND_MASK_BASS | SOUND_MASK_TREBLE | SOUND_MASK_RECLEV | \
SOUND_MASK_MUTE | SOUND_MASK_ENHANCE | SOUND_MASK_LOUD)
-static unsigned short levels[SOUND_MIXER_NRDEVICES] =
+static u_short levels[SOUND_MIXER_NRDEVICES] =
{
- 0x3232, /*
- * Master Volume
- */
- 0x3232, /*
- * Bass
- */
- 0x3232, /*
- * Treble
- */
- 0x5050, /*
- * FM
- */
- 0x4b4b, /*
- * PCM
- */
- 0x3232, /*
- * PC Speaker
- */
- 0x4b4b, /*
- * Ext Line
- */
- 0x4b4b, /*
- * Mic
- */
- 0x4b4b, /*
- * CD
- */
- 0x6464, /*
- * Recording monitor
- */
- 0x4b4b, /*
- * SB PCM
- */
- 0x6464}; /*
-
-
- * * * * Recording level */
+ 0x3232, /* Master Volume */
+ 0x3232, /* Bass */
+ 0x3232, /* Treble */
+ 0x5050, /* FM */
+ 0x4b4b, /* PCM */
+ 0x3232, /* PC Speaker */
+ 0x4b4b, /* Ext Line */
+ 0x4b4b, /* Mic */
+ 0x4b4b, /* CD */
+ 0x6464, /* Recording monitor */
+ 0x4b4b, /* SB PCM */
+ 0x6464 /* Recording level */
+};
-static int
-mixer_output (int right_vol, int left_vol, int div, int bits,
- int mixer /*
- * Input or output mixer
- */ )
+void
+mix_write(u_char data, int ioaddr)
{
- int left = left_vol * div / 100;
- int right = right_vol * div / 100;
-
- /*
- * The Revision D cards have a problem with their MVA508 interface. The
- * kludge-o-rama fix is to make a 16-bit quantity with identical LSB and
- * MSBs out of the output byte and to do a 16-bit out to the mixer port -
- * 1. We don't need to do this because the call to pas_write more than
- * compensates for the timing problems.
- */
-
- if (bits & P_M_MV508_MIXER)
- { /*
- * Select input or output mixer
- */
- left |= mixer;
- right |= mixer;
- }
-
- if (bits == P_M_MV508_BASS || bits == P_M_MV508_TREBLE)
- { /*
- * Bass and trebble are mono devices
- */
- pas_write (P_M_MV508_ADDRESS | bits, PARALLEL_MIXER);
- pas_write (left, PARALLEL_MIXER);
- right_vol = left_vol;
- }
- else
- {
- pas_write (P_M_MV508_ADDRESS | P_M_MV508_LEFT | bits, PARALLEL_MIXER);
- pas_write (left, PARALLEL_MIXER);
- pas_write (P_M_MV508_ADDRESS | P_M_MV508_RIGHT | bits, PARALLEL_MIXER);
- pas_write (right, PARALLEL_MIXER);
- }
-
- return (left_vol | (right_vol << 8));
+ /*
+ * The Revision D cards have a problem with their MVA508 interface.
+ * The kludge-o-rama fix is to make a 16-bit quantity with identical
+ * LSB and MSBs out of the output byte and to do a 16-bit out to the
+ * mixer port - 1. We need to do this because it isn't timing problem
+ * but chip access sequence problem.
+ */
+
+ if (pas_model == PAS_16D) {
+ outw((ioaddr ^ translat_code) - 1, data | (data << 8));
+ outb(0, 0x80);
+ } else
+ pas_write(data, ioaddr);
}
-void
-set_mode (int new_mode)
-{
- pas_write (P_M_MV508_ADDRESS | P_M_MV508_MODE, PARALLEL_MIXER);
- pas_write (new_mode, PARALLEL_MIXER);
+static int
+mixer_output(int right_vol, int left_vol, int div, int bits,
+ int mixer)
+{ /* Input or output mixer */
+ int left = left_vol * div / 100;
+ int right = right_vol * div / 100;
+
- mode_control = new_mode;
+ if (bits & P_M_MV508_MIXER) { /* Select input or output mixer */
+ left |= mixer;
+ right |= mixer;
+ }
+ if (bits == P_M_MV508_BASS || bits == P_M_MV508_TREBLE) { /* Bass and treble are
+ * mono devices */
+ mix_write(P_M_MV508_ADDRESS | bits, PARALLEL_MIXER);
+ mix_write(left, PARALLEL_MIXER);
+ right_vol = left_vol;
+ } else {
+ mix_write(P_M_MV508_ADDRESS | P_M_MV508_LEFT | bits, PARALLEL_MIXER);
+ mix_write(left, PARALLEL_MIXER);
+ mix_write(P_M_MV508_ADDRESS | P_M_MV508_RIGHT | bits, PARALLEL_MIXER);
+ mix_write(right, PARALLEL_MIXER);
+ }
+
+ return (left_vol | (right_vol << 8));
}
-static int
-pas_mixer_set (int whichDev, unsigned int level)
+static void
+set_mode(int new_mode)
{
- int left, right, devmask, changed, i, mixer = 0;
-
- TRACE (printk ("static int pas_mixer_set(int whichDev = %d, unsigned int level = %X)\n", whichDev, level));
-
- left = level & 0x7f;
- right = (level & 0x7f00) >> 8;
-
- if (whichDev < SOUND_MIXER_NRDEVICES)
- if ((1 << whichDev) & rec_devices)
- mixer = P_M_MV508_INPUTMIX;
- else
- mixer = P_M_MV508_OUTPUTMIX;
-
- switch (whichDev)
- {
- case SOUND_MIXER_VOLUME: /*
- * Master volume (0-63)
- */
- levels[whichDev] = mixer_output (right, left, 63, P_M_MV508_MASTER_A, 0);
- break;
-
- /*
- * Note! Bass and Treble are mono devices. Will use just the left
- * channel.
- */
- case SOUND_MIXER_BASS: /*
- * Bass (0-12)
- */
- levels[whichDev] = mixer_output (right, left, 12, P_M_MV508_BASS, 0);
- break;
- case SOUND_MIXER_TREBLE: /*
- * Treble (0-12)
- */
- levels[whichDev] = mixer_output (right, left, 12, P_M_MV508_TREBLE, 0);
- break;
-
- case SOUND_MIXER_SYNTH: /*
- * Internal synthesizer (0-31)
- */
- levels[whichDev] = mixer_output (right, left, 31, P_M_MV508_MIXER | P_M_MV508_FM, mixer);
- break;
- case SOUND_MIXER_PCM: /*
- * PAS PCM (0-31)
- */
- levels[whichDev] = mixer_output (right, left, 31, P_M_MV508_MIXER | P_M_MV508_PCM, mixer);
- break;
- case SOUND_MIXER_ALTPCM: /*
- * SB PCM (0-31)
- */
- levels[whichDev] = mixer_output (right, left, 31, P_M_MV508_MIXER | P_M_MV508_SB, mixer);
- break;
- case SOUND_MIXER_SPEAKER: /*
- * PC speaker (0-31)
- */
- levels[whichDev] = mixer_output (right, left, 31, P_M_MV508_MIXER | P_M_MV508_SPEAKER, mixer);
- break;
- case SOUND_MIXER_LINE: /*
- * External line (0-31)
- */
- levels[whichDev] = mixer_output (right, left, 31, P_M_MV508_MIXER | P_M_MV508_LINE, mixer);
- break;
- case SOUND_MIXER_CD: /*
- * CD (0-31)
- */
- levels[whichDev] = mixer_output (right, left, 31, P_M_MV508_MIXER | P_M_MV508_CDROM, mixer);
- break;
- case SOUND_MIXER_MIC: /*
- * External microphone (0-31)
- */
- levels[whichDev] = mixer_output (right, left, 31, P_M_MV508_MIXER | P_M_MV508_MIC, mixer);
- break;
- case SOUND_MIXER_IMIX: /*
- * Recording monitor (0-31) (Only available *
- * on the Output Mixer)
- */
- levels[whichDev] = mixer_output (right, left, 31, P_M_MV508_MIXER | P_M_MV508_IMIXER,
- P_M_MV508_OUTPUTMIX);
- break;
- case SOUND_MIXER_RECLEV: /*
- * Recording level (0-15)
- */
- levels[whichDev] = mixer_output (right, left, 15, P_M_MV508_MASTER_B, 0);
- break;
-
- case SOUND_MIXER_MUTE:
- return 0;
- break;
-
- case SOUND_MIXER_ENHANCE:
- i = 0;
- level &= 0x7f;
- if (level)
- i = (level / 20) - 1;
-
- mode_control &= ~P_M_MV508_ENHANCE_BITS;
- mode_control |= P_M_MV508_ENHANCE_BITS;
- set_mode (mode_control);
-
- if (i)
- i = (i + 1) * 20;
- return i;
- break;
-
- case SOUND_MIXER_LOUD:
- mode_control &= ~P_M_MV508_LOUDNESS;
- if (level)
- mode_control |= P_M_MV508_LOUDNESS;
- set_mode (mode_control);
- return !!level; /*
- * 0 or 1
- */
- break;
-
- case SOUND_MIXER_RECSRC:
- devmask = level & POSSIBLE_RECORDING_DEVICES;
-
- changed = devmask ^ rec_devices;
- rec_devices = devmask;
-
- for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
- if (changed & (1 << i))
- {
- pas_mixer_set (i, levels[i]);
- }
- return rec_devices;
- break;
-
- default:
- return RET_ERROR (EINVAL);
- }
-
- return (levels[whichDev]);
-}
+ mix_write(P_M_MV508_ADDRESS | P_M_MV508_MODE, PARALLEL_MIXER);
+ mix_write(new_mode, PARALLEL_MIXER);
-/*****/
+ mode_control = new_mode;
+}
static int
-getmixer (int dev, int chn)
+pas_mixer_set(int whichDev, u_int level)
{
- if (chn == P_M_MV508_RIGHT)
- {
- return (levels[dev] >> 8) & 0x7f;
- }
- else
- {
- return levels[dev] & 0x7f;
- }
+ int left, right, devmask, changed, i, mixer = 0;
+
+ TRACE(printf("static int pas_mixer_set(int whichDev = %d, u_int level = %X)\n", whichDev, level));
+
+ left = level & 0x7f;
+ right = (level & 0x7f00) >> 8;
+
+ if (whichDev < SOUND_MIXER_NRDEVICES)
+ if ((1 << whichDev) & rec_devices)
+ mixer = P_M_MV508_INPUTMIX;
+ else
+ mixer = P_M_MV508_OUTPUTMIX;
+
+ switch (whichDev) {
+ case SOUND_MIXER_VOLUME: /* Master volume (0-63) */
+ levels[whichDev] = mixer_output(right, left, 63, P_M_MV508_MASTER_A, 0);
+ break;
+
+ /*
+ * Note! Bass and Treble are mono devices. Will use just the
+ * left channel.
+ */
+ case SOUND_MIXER_BASS: /* Bass (0-12) */
+ levels[whichDev] = mixer_output(right, left, 12, P_M_MV508_BASS, 0);
+ break;
+ case SOUND_MIXER_TREBLE: /* Treble (0-12) */
+ levels[whichDev] = mixer_output(right, left, 12, P_M_MV508_TREBLE, 0);
+ break;
+
+ case SOUND_MIXER_SYNTH:/* Internal synthesizer (0-31) */
+ levels[whichDev] = mixer_output(right, left, 31, P_M_MV508_MIXER | P_M_MV508_FM, mixer);
+ break;
+ case SOUND_MIXER_PCM: /* PAS PCM (0-31) */
+ levels[whichDev] = mixer_output(right, left, 31, P_M_MV508_MIXER | P_M_MV508_PCM, mixer);
+ break;
+ case SOUND_MIXER_ALTPCM: /* SB PCM (0-31) */
+ levels[whichDev] = mixer_output(right, left, 31, P_M_MV508_MIXER | P_M_MV508_SB, mixer);
+ break;
+ case SOUND_MIXER_SPEAKER: /* PC speaker (0-31) */
+ levels[whichDev] = mixer_output(right, left, 31, P_M_MV508_MIXER | P_M_MV508_SPEAKER, mixer);
+ break;
+ case SOUND_MIXER_LINE: /* External line (0-31) */
+ levels[whichDev] = mixer_output(right, left, 31, P_M_MV508_MIXER | P_M_MV508_LINE, mixer);
+ break;
+ case SOUND_MIXER_CD: /* CD (0-31) */
+ levels[whichDev] = mixer_output(right, left, 31, P_M_MV508_MIXER | P_M_MV508_CDROM, mixer);
+ break;
+ case SOUND_MIXER_MIC: /* External microphone (0-31) */
+ levels[whichDev] = mixer_output(right, left, 31, P_M_MV508_MIXER | P_M_MV508_MIC, mixer);
+ break;
+ case SOUND_MIXER_IMIX: /* Recording monitor (0-31) (Output mixer
+ * only) */
+ levels[whichDev] = mixer_output(right, left, 31, P_M_MV508_MIXER | P_M_MV508_IMIXER,
+ P_M_MV508_OUTPUTMIX);
+ break;
+ case SOUND_MIXER_RECLEV: /* Recording level (0-15) */
+ levels[whichDev] = mixer_output(right, left, 15, P_M_MV508_MASTER_B, 0);
+ break;
+
+ case SOUND_MIXER_MUTE:
+ return 0;
+ break;
+
+ case SOUND_MIXER_ENHANCE:
+ i = 0;
+ level &= 0x7f;
+ if (level)
+ i = (level / 20) - 1;
+
+ mode_control &= ~P_M_MV508_ENHANCE_BITS;
+ mode_control |= P_M_MV508_ENHANCE_BITS;
+ set_mode(mode_control);
+
+ if (i)
+ i = (i + 1) * 20;
+ return i;
+ break;
+
+ case SOUND_MIXER_LOUD:
+ mode_control &= ~P_M_MV508_LOUDNESS;
+ if (level)
+ mode_control |= P_M_MV508_LOUDNESS;
+ set_mode(mode_control);
+ return !!level; /* 0 or 1 */
+ break;
+
+ case SOUND_MIXER_RECSRC:
+ devmask = level & POSSIBLE_RECORDING_DEVICES;
+
+ changed = devmask ^ rec_devices;
+ rec_devices = devmask;
+
+ for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
+ if (changed & (1 << i)) {
+ pas_mixer_set(i, levels[i]);
+ }
+ return rec_devices;
+ break;
+
+ default:
+ return -(EINVAL);
+ }
+
+ return (levels[whichDev]);
}
+/*****/
+
static void
-pas_mixer_reset (void)
+pas_mixer_reset(void)
{
- int foo;
+ int foo;
- TRACE (printk ("pas2_mixer.c: void pas_mixer_reset(void)\n"));
+ TRACE(printf("pas2_mixer.c: void pas_mixer_reset(void)\n"));
- for (foo = 0; foo < SOUND_MIXER_NRDEVICES; foo++)
- pas_mixer_set (foo, levels[foo]);
+ for (foo = 0; foo < SOUND_MIXER_NRDEVICES; foo++)
+ pas_mixer_set(foo, levels[foo]);
- set_mode (P_M_MV508_LOUDNESS | P_M_MV508_ENHANCE_40);
+ set_mode(P_M_MV508_LOUDNESS | P_M_MV508_ENHANCE_40);
}
int
-pas_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg)
+pas_mixer_ioctl(int dev, u_int cmd, ioctl_arg arg)
{
- TRACE (printk ("pas2_mixer.c: int pas_mixer_ioctl(unsigned int cmd = %X, unsigned int arg = %X)\n", cmd, arg));
-
- if (((cmd >> 8) & 0xff) == 'M')
- {
- if (cmd & IOC_IN)
- return IOCTL_OUT (arg, pas_mixer_set (cmd & 0xff, IOCTL_IN (arg)));
- else
- { /*
- * Read parameters
- */
-
- switch (cmd & 0xff)
- {
-
- case SOUND_MIXER_RECSRC:
- return IOCTL_OUT (arg, rec_devices);
- break;
-
- case SOUND_MIXER_STEREODEVS:
- return IOCTL_OUT (arg, SUPPORTED_MIXER_DEVICES & ~(SOUND_MASK_BASS | SOUND_MASK_TREBLE));
- break;
-
- case SOUND_MIXER_DEVMASK:
- return IOCTL_OUT (arg, SUPPORTED_MIXER_DEVICES);
- break;
-
- case SOUND_MIXER_RECMASK:
- return IOCTL_OUT (arg, POSSIBLE_RECORDING_DEVICES & SUPPORTED_MIXER_DEVICES);
- break;
-
- case SOUND_MIXER_CAPS:
- return IOCTL_OUT (arg, 0); /*
- * No special capabilities
- */
- break;
-
- case SOUND_MIXER_MUTE:
- return IOCTL_OUT (arg, 0); /*
- * No mute yet
- */
- break;
-
- case SOUND_MIXER_ENHANCE:
- if (!(mode_control & P_M_MV508_ENHANCE_BITS))
- return IOCTL_OUT (arg, 0);
- return IOCTL_OUT (arg, ((mode_control & P_M_MV508_ENHANCE_BITS) + 1) * 20);
- break;
-
- case SOUND_MIXER_LOUD:
- if (mode_control & P_M_MV508_LOUDNESS)
- return IOCTL_OUT (arg, 1);
- return IOCTL_OUT (arg, 0);
- break;
-
- default:
- return IOCTL_OUT (arg, levels[cmd & 0xff]);
- }
+ TRACE(printf("pas2_mixer.c: int pas_mixer_ioctl(u_int cmd = %X, u_int arg = %X)\n", cmd, arg));
+
+ if (((cmd >> 8) & 0xff) == 'M') {
+ if (cmd & IOC_IN)
+ return *(int *) arg = pas_mixer_set(cmd & 0xff, (*(int *) arg));
+ else { /* Read parameters */
+
+ switch (cmd & 0xff) {
+
+ case SOUND_MIXER_RECSRC:
+ return *(int *) arg = rec_devices;
+ break;
+
+ case SOUND_MIXER_STEREODEVS:
+ return *(int *) arg = SUPPORTED_MIXER_DEVICES & ~(SOUND_MASK_BASS | SOUND_MASK_TREBLE);
+ break;
+
+ case SOUND_MIXER_DEVMASK:
+ return *(int *) arg = SUPPORTED_MIXER_DEVICES;
+ break;
+
+ case SOUND_MIXER_RECMASK:
+ return *(int *) arg = POSSIBLE_RECORDING_DEVICES & SUPPORTED_MIXER_DEVICES;
+ break;
+
+ case SOUND_MIXER_CAPS:
+ return *(int *) arg = 0; /* No special
+ * capabilities */
+ break;
+
+ case SOUND_MIXER_MUTE:
+ return *(int *) arg = 0; /* No mute yet */
+ break;
+
+ case SOUND_MIXER_ENHANCE:
+ if (!(mode_control & P_M_MV508_ENHANCE_BITS))
+ return *(int *) arg = 0;
+ return *(int *) arg = ((mode_control & P_M_MV508_ENHANCE_BITS) + 1) * 20;
+ break;
+
+ case SOUND_MIXER_LOUD:
+ if (mode_control & P_M_MV508_LOUDNESS)
+ return *(int *) arg = 1;
+ return *(int *) arg = 0;
+ break;
+
+ default:
+ return *(int *) arg = levels[cmd & 0xff];
+ }
+ }
}
- }
- return RET_ERROR (EINVAL);
+ return -(EINVAL);
}
static struct mixer_operations pas_mixer_operations =
{
- pas_mixer_ioctl
+ "Pro Audio Spectrum 16",
+ pas_mixer_ioctl
};
int
-pas_init_mixer (void)
+pas_init_mixer(void)
{
- pas_mixer_reset ();
+ pas_mixer_reset();
- if (num_mixers < MAX_MIXER_DEV)
- mixer_devs[num_mixers++] = &pas_mixer_operations;
- return 1;
+ if (num_mixers < MAX_MIXER_DEV)
+ mixer_devs[num_mixers++] = &pas_mixer_operations;
+ return 1;
}
#endif
diff --git a/sys/i386/isa/sound/pas2_pcm.c b/sys/i386/isa/sound/pas2_pcm.c
index e4c9a63c384c..fd4d5c084ecb 100644
--- a/sys/i386/isa/sound/pas2_pcm.c
+++ b/sys/i386/isa/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,19 +25,16 @@
* 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"
+#include <i386/isa/sound/sound_config.h>
-#ifdef CONFIGURE_SOUNDCARD
+#if defined(CONFIG_PAS) && defined(CONFIG_AUDIO)
+#include <i386/isa/sound/pas_hw.h>
-#include "pas.h"
-#if !defined(EXCLUDE_PAS) && !defined(EXCLUDE_AUDIO)
-
-#define TRACE(WHAT) /*
- * * * (WHAT) */
+#define TRACE(WHAT) /* * * (WHAT) */
#define PAS_PCM_INTRBITS (0x08)
/*
@@ -48,406 +45,405 @@
#define PCM_DAC 1
#define PCM_ADC 2
-static unsigned long pcm_speed = 0; /* sampling rate */
-static unsigned char pcm_channels = 1; /* channels (1 or 2) */
-static unsigned char pcm_bits = 8; /* bits/sample (8 or 16) */
-static unsigned char pcm_filter = 0; /* filter FLAG */
-static unsigned char pcm_mode = PCM_NON;
-static unsigned long pcm_count = 0;
-static unsigned short pcm_bitsok = 8; /* mask of OK bits */
+static u_long pcm_speed = 0; /* sampling rate */
+static u_char pcm_channels = 1; /* channels (1 or 2) */
+static u_char pcm_bits = 8; /* bits/sample (8 or 16) */
+static u_char pcm_filter = 0; /* filter FLAG */
+static u_char pcm_mode = PCM_NON;
+static u_long pcm_count = 0;
+static u_short pcm_bitsok = 8; /* mask of OK bits */
static int my_devnum = 0;
+static int open_mode = 0;
int
-pcm_set_speed (int arg)
+pcm_set_speed(int arg)
{
- int foo, tmp;
- unsigned long flags;
+ int foo, tmp;
+ u_long flags;
- if (arg > 44100)
- arg = 44100;
- if (arg < 5000)
- arg = 5000;
+ if (arg > 44100)
+ arg = 44100;
+ if (arg < 5000)
+ arg = 5000;
- foo = (1193180 + (arg / 2)) / arg;
- arg = 1193180 / foo;
+ foo = (1193180 + (arg / 2)) / arg;
+ arg = 1193180 / foo;
- if (pcm_channels & 2)
- foo = foo >> 1;
+ if (pcm_channels & 2)
+ foo = foo >> 1;
- pcm_speed = arg;
+ pcm_speed = arg;
- tmp = pas_read (FILTER_FREQUENCY);
+ tmp = pas_read(FILTER_FREQUENCY);
- /*
- * Set anti-aliasing filters according to sample rate. You reall *NEED*
- * to enable this feature for all normal recording unless you want to
- * experiment with aliasing effects.
- * These filters apply to the selected "recording" source.
- * I (pfw) don't know the encoding of these 5 bits. The values shown
- * come from the SDK found on ftp.uwp.edu:/pub/msdos/proaudio/.
-*/
+ /*
+ * Set anti-aliasing filters according to sample rate. You reall
+ * *NEED* to enable this feature for all normal recording unless you
+ * want to experiment with aliasing effects. These filters apply to
+ * the selected "recording" source. I (pfw) don't know the encoding
+ * of these 5 bits. The values shown come from the SDK found on
+ * ftp.uwp.edu:/pub/msdos/proaudio/.
+ */
#if !defined NO_AUTO_FILTER_SET
- tmp &= 0xe0;
- if (pcm_speed >= 2 * 17897)
- tmp |= 0x21;
- else if (pcm_speed >= 2 * 15909)
- tmp |= 0x22;
- else if (pcm_speed >= 2 * 11931)
- tmp |= 0x29;
- else if (pcm_speed >= 2 * 8948)
- tmp |= 0x31;
- else if (pcm_speed >= 2 * 5965)
- tmp |= 0x39;
- else if (pcm_speed >= 2 * 2982)
- tmp |= 0x24;
- pcm_filter = tmp;
+ tmp &= 0xe0;
+ if (pcm_speed >= 2 * 17897)
+ tmp |= 0x21;
+ else if (pcm_speed >= 2 * 15909)
+ tmp |= 0x22;
+ else if (pcm_speed >= 2 * 11931)
+ tmp |= 0x29;
+ else if (pcm_speed >= 2 * 8948)
+ tmp |= 0x31;
+ else if (pcm_speed >= 2 * 5965)
+ tmp |= 0x39;
+ else if (pcm_speed >= 2 * 2982)
+ tmp |= 0x24;
+ pcm_filter = tmp;
#endif
- DISABLE_INTR (flags);
+ flags = splhigh();
- pas_write (tmp & ~(F_F_PCM_RATE_COUNTER | F_F_PCM_BUFFER_COUNTER), FILTER_FREQUENCY);
- pas_write (S_C_C_SAMPLE_RATE | S_C_C_LSB_THEN_MSB | S_C_C_SQUARE_WAVE, SAMPLE_COUNTER_CONTROL);
- pas_write (foo & 0xff, SAMPLE_RATE_TIMER);
- pas_write ((foo >> 8) & 0xff, SAMPLE_RATE_TIMER);
- pas_write (tmp, FILTER_FREQUENCY);
+ pas_write(tmp & ~(F_F_PCM_RATE_COUNTER | F_F_PCM_BUFFER_COUNTER), FILTER_FREQUENCY);
+ pas_write(S_C_C_SAMPLE_RATE | S_C_C_LSB_THEN_MSB | S_C_C_SQUARE_WAVE, SAMPLE_COUNTER_CONTROL);
+ pas_write(foo & 0xff, SAMPLE_RATE_TIMER);
+ pas_write((foo >> 8) & 0xff, SAMPLE_RATE_TIMER);
+ pas_write(tmp, FILTER_FREQUENCY);
- RESTORE_INTR (flags);
+ splx(flags);
- return pcm_speed;
+ return pcm_speed;
}
int
-pcm_set_channels (int arg)
+pcm_set_channels(int arg)
{
- if ((arg != 1) && (arg != 2))
- return pcm_channels;
+ if ((arg != 1) && (arg != 2))
+ return pcm_channels;
- if (arg != pcm_channels)
- {
- pas_write (pas_read (PCM_CONTROL) ^ P_C_PCM_MONO, PCM_CONTROL);
+ if (arg != pcm_channels) {
+ pas_write(pas_read(PCM_CONTROL) ^ P_C_PCM_MONO, PCM_CONTROL);
- pcm_channels = arg;
- pcm_set_speed (pcm_speed);/*
- * The speed must be reinitialized
- */
- }
-
- return pcm_channels;
+ pcm_channels = arg;
+ pcm_set_speed(pcm_speed); /* The speed must be
+ * reinitialized */
+ }
+ return pcm_channels;
}
int
-pcm_set_bits (int arg)
+pcm_set_bits(int arg)
{
- if ((arg & pcm_bitsok) != arg)
- return pcm_bits;
+ if ((arg & pcm_bitsok) != arg)
+ return pcm_bits;
- if (arg != pcm_bits)
- {
- pas_write (pas_read (SYSTEM_CONFIGURATION_2) ^ S_C_2_PCM_16_BIT, SYSTEM_CONFIGURATION_2);
+ if (arg != pcm_bits) {
+ pas_write(pas_read(SYSTEM_CONFIGURATION_2) ^ S_C_2_PCM_16_BIT, SYSTEM_CONFIGURATION_2);
- pcm_bits = arg;
- }
-
- return pcm_bits;
+ pcm_bits = arg;
+ }
+ return pcm_bits;
}
static int
-pas_pcm_ioctl (int dev, unsigned int cmd, unsigned int arg, int local)
+pas_pcm_ioctl(int dev, u_int cmd, ioctl_arg arg, int local)
{
- TRACE (printk ("pas2_pcm.c: static int pas_pcm_ioctl(unsigned int cmd = %X, unsigned int arg = %X)\n", cmd, arg));
-
- switch (cmd)
- {
- case SOUND_PCM_WRITE_RATE:
- if (local)
- return pcm_set_speed (arg);
- return IOCTL_OUT (arg, pcm_set_speed (IOCTL_IN (arg)));
- break;
-
- case SOUND_PCM_READ_RATE:
- if (local)
- return pcm_speed;
- return IOCTL_OUT (arg, pcm_speed);
- break;
-
- case SNDCTL_DSP_STEREO:
- if (local)
- return pcm_set_channels (arg + 1) - 1;
- return IOCTL_OUT (arg, pcm_set_channels (IOCTL_IN (arg) + 1) - 1);
- break;
-
- case SOUND_PCM_WRITE_CHANNELS:
- if (local)
- return pcm_set_channels (arg);
- return IOCTL_OUT (arg, pcm_set_channels (IOCTL_IN (arg)));
- break;
-
- case SOUND_PCM_READ_CHANNELS:
- if (local)
- return pcm_channels;
- return IOCTL_OUT (arg, pcm_channels);
- break;
-
- case SNDCTL_DSP_SETFMT:
- if (local)
- return pcm_set_bits (arg);
- return IOCTL_OUT (arg, pcm_set_bits (IOCTL_IN (arg)));
- break;
+ TRACE(printf("pas2_pcm.c: static int pas_pcm_ioctl(u_int cmd = %X, u_int arg = %X)\n", cmd, arg));
+
+ switch (cmd) {
+ case SOUND_PCM_WRITE_RATE:
+ if (local)
+ return pcm_set_speed((int) arg);
+ return *(int *) arg = pcm_set_speed((*(int *) arg));
+ break;
+
+ case SOUND_PCM_READ_RATE:
+ if (local)
+ return pcm_speed;
+ return *(int *) arg = pcm_speed;
+ break;
+
+ case SNDCTL_DSP_STEREO:
+ if (local)
+ return pcm_set_channels((int) arg + 1) - 1;
+ return *(int *) arg = pcm_set_channels((*(int *) arg) + 1) - 1;
+ break;
+
+ case SOUND_PCM_WRITE_CHANNELS:
+ if (local)
+ return pcm_set_channels((int) arg);
+ return *(int *) arg = pcm_set_channels((*(int *) arg));
+ break;
+
+ case SOUND_PCM_READ_CHANNELS:
+ if (local)
+ return pcm_channels;
+ return *(int *) arg = pcm_channels;
+ break;
+
+ case SNDCTL_DSP_SETFMT:
+ if (local)
+ return pcm_set_bits((int) arg);
+ return *(int *) arg = pcm_set_bits((*(int *) arg));
+ break;
+
+ case SOUND_PCM_READ_BITS:
+ if (local)
+ return pcm_bits;
+ return *(int *) arg = pcm_bits;
+
+ case SOUND_PCM_WRITE_FILTER: /* NOT YET IMPLEMENTED */
+ if ((*(int *) arg) > 1)
+ return -(EINVAL);
+ pcm_filter = (*(int *) arg);
+ break;
+
+ case SOUND_PCM_READ_FILTER:
+ return *(int *) arg = pcm_filter;
+ break;
- case SOUND_PCM_READ_BITS:
- if (local)
- return pcm_bits;
- return IOCTL_OUT (arg, pcm_bits);
-
- case SOUND_PCM_WRITE_FILTER: /*
- * NOT YET IMPLEMENTED
- */
- if (IOCTL_IN (arg) > 1)
- return IOCTL_OUT (arg, RET_ERROR (EINVAL));
- break;
-
- pcm_filter = IOCTL_IN (arg);
- case SOUND_PCM_READ_FILTER:
- return IOCTL_OUT (arg, pcm_filter);
- break;
-
- default:
- return RET_ERROR (EINVAL);
- }
+ default:
+ return -(EINVAL);
+ }
- return RET_ERROR (EINVAL);
+ return -(EINVAL);
}
static void
-pas_pcm_reset (int dev)
+pas_pcm_reset(int dev)
{
- TRACE (printk ("pas2_pcm.c: static void pas_pcm_reset(void)\n"));
+ TRACE(printf("pas2_pcm.c: static void pas_pcm_reset(void)\n"));
- pas_write (pas_read (PCM_CONTROL) & ~P_C_PCM_ENABLE, PCM_CONTROL);
+ pas_write(pas_read(PCM_CONTROL) & ~P_C_PCM_ENABLE, PCM_CONTROL);
}
static int
-pas_pcm_open (int dev, int mode)
+pas_pcm_open(int dev, int mode)
{
- int err;
+ int err;
- TRACE (printk ("pas2_pcm.c: static int pas_pcm_open(int mode = %X)\n", mode));
+ TRACE(printf("pas2_pcm.c: static int pas_pcm_open(int mode = %X)\n", mode));
- if ((err = pas_set_intr (PAS_PCM_INTRBITS)) < 0)
- return err;
+ if ((err = pas_set_intr(PAS_PCM_INTRBITS)) < 0)
+ return err;
- if (DMAbuf_open_dma (dev) < 0)
- {
- pas_remove_intr (PAS_PCM_INTRBITS);
- return RET_ERROR (EBUSY);
- }
- pcm_count = 0;
+ pcm_count = 0;
+ open_mode = mode;
- return 0;
+ return 0;
}
static void
-pas_pcm_close (int dev)
+pas_pcm_close(int dev)
{
- unsigned long flags;
+ u_long flags;
+
+ TRACE(printf("pas2_pcm.c: static void pas_pcm_close(void)\n"));
- TRACE (printk ("pas2_pcm.c: static void pas_pcm_close(void)\n"));
+ flags = splhigh();
- DISABLE_INTR (flags);
+ pas_pcm_reset(dev);
+ pas_remove_intr(PAS_PCM_INTRBITS);
+ pcm_mode = PCM_NON;
- pas_pcm_reset (dev);
- DMAbuf_close_dma (dev);
- pas_remove_intr (PAS_PCM_INTRBITS);
- pcm_mode = PCM_NON;
+ open_mode = 0;
- RESTORE_INTR (flags);
+ splx(flags);
}
static void
-pas_pcm_output_block (int dev, unsigned long buf, int count,
- int intrflag, int restart_dma)
+pas_pcm_output_block(int dev, u_long buf, int count,
+ int intrflag, int restart_dma)
{
- unsigned long flags, cnt;
+ u_long flags, cnt;
- TRACE (printk ("pas2_pcm.c: static void pas_pcm_output_block(char *buf = %P, int count = %X)\n", buf, count));
+ TRACE(printf("pas2_pcm.c: static void pas_pcm_output_block(char *buf = %P, int count = %X)\n", buf, count));
- cnt = count;
- if (audio_devs[dev]->dmachan > 3)
- cnt >>= 1;
+ cnt = count;
+ if (audio_devs[dev]->dmachan1 > 3)
+ cnt >>= 1;
- if (audio_devs[dev]->flags & DMA_AUTOMODE &&
- intrflag &&
- cnt == pcm_count)
- return; /*
- * Auto mode on. No need to react
- */
+ if (audio_devs[dev]->flags & DMA_AUTOMODE &&
+ intrflag &&
+ cnt == pcm_count)
+ return; /* Auto mode on. No need to react */
- DISABLE_INTR (flags);
+ flags = splhigh();
- pas_write (pas_read (PCM_CONTROL) & ~P_C_PCM_ENABLE,
- PCM_CONTROL);
+ 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, 1);
- if (audio_devs[dev]->dmachan > 3)
- count >>= 1;
+ if (audio_devs[dev]->dmachan1 > 3)
+ count >>= 1;
- if (count != pcm_count)
- {
- pas_write (pas_read (FILTER_FREQUENCY) & ~F_F_PCM_BUFFER_COUNTER, FILTER_FREQUENCY);
- pas_write (S_C_C_SAMPLE_BUFFER | S_C_C_LSB_THEN_MSB | S_C_C_SQUARE_WAVE, SAMPLE_COUNTER_CONTROL);
- pas_write (count & 0xff, SAMPLE_BUFFER_COUNTER);
- pas_write ((count >> 8) & 0xff, SAMPLE_BUFFER_COUNTER);
- pas_write (pas_read (FILTER_FREQUENCY) | F_F_PCM_BUFFER_COUNTER, FILTER_FREQUENCY);
+ if (count != pcm_count) {
+ pas_write(pas_read(FILTER_FREQUENCY) & ~F_F_PCM_BUFFER_COUNTER, FILTER_FREQUENCY);
+ pas_write(S_C_C_SAMPLE_BUFFER | S_C_C_LSB_THEN_MSB | S_C_C_SQUARE_WAVE, SAMPLE_COUNTER_CONTROL);
+ pas_write(count & 0xff, SAMPLE_BUFFER_COUNTER);
+ pas_write((count >> 8) & 0xff, SAMPLE_BUFFER_COUNTER);
+ pas_write(pas_read(FILTER_FREQUENCY) | F_F_PCM_BUFFER_COUNTER, FILTER_FREQUENCY);
- pcm_count = count;
- }
- pas_write (pas_read (FILTER_FREQUENCY) | F_F_PCM_BUFFER_COUNTER | F_F_PCM_RATE_COUNTER, FILTER_FREQUENCY);
- pas_write (pas_read (PCM_CONTROL) | P_C_PCM_ENABLE | P_C_PCM_DAC_MODE, PCM_CONTROL);
+ pcm_count = count;
+ }
+ pas_write(pas_read(FILTER_FREQUENCY) | F_F_PCM_BUFFER_COUNTER | F_F_PCM_RATE_COUNTER, FILTER_FREQUENCY);
+#ifdef NO_TRIGGER
+ pas_write(pas_read(PCM_CONTROL) | P_C_PCM_ENABLE | P_C_PCM_DAC_MODE, PCM_CONTROL);
+#endif
- pcm_mode = PCM_DAC;
+ pcm_mode = PCM_DAC;
- RESTORE_INTR (flags);
+ splx(flags);
}
static void
-pas_pcm_start_input (int dev, unsigned long buf, int count,
- int intrflag, int restart_dma)
+pas_pcm_start_input(int dev, u_long buf, int count,
+ int intrflag, int restart_dma)
{
- unsigned long flags;
- int cnt;
+ u_long flags;
+ int cnt;
+
+ TRACE(printf("pas2_pcm.c: static void pas_pcm_start_input(char *buf = %P, int count = %X)\n", buf, count));
+
+ cnt = count;
+ if (audio_devs[dev]->dmachan1 > 3)
+ cnt >>= 1;
- TRACE (printk ("pas2_pcm.c: static void pas_pcm_start_input(char *buf = %P, int count = %X)\n", buf, count));
+ if (audio_devs[my_devnum]->flags & DMA_AUTOMODE &&
+ intrflag &&
+ cnt == pcm_count)
+ return; /* Auto mode on. No need to react */
- cnt = count;
- if (audio_devs[dev]->dmachan > 3)
- cnt >>= 1;
+ flags = splhigh();
- if (audio_devs[my_devnum]->flags & DMA_AUTOMODE &&
- intrflag &&
- cnt == pcm_count)
- return; /*
- * Auto mode on. No need to react
- */
+ if (restart_dma)
+ DMAbuf_start_dma(dev, buf, count, 0);
- DISABLE_INTR (flags);
+ if (audio_devs[dev]->dmachan1 > 3)
+ count >>= 1;
+
+ if (count != pcm_count) {
+ pas_write(pas_read(FILTER_FREQUENCY) & ~F_F_PCM_BUFFER_COUNTER, FILTER_FREQUENCY);
+ pas_write(S_C_C_SAMPLE_BUFFER | S_C_C_LSB_THEN_MSB | S_C_C_SQUARE_WAVE, SAMPLE_COUNTER_CONTROL);
+ pas_write(count & 0xff, SAMPLE_BUFFER_COUNTER);
+ pas_write((count >> 8) & 0xff, SAMPLE_BUFFER_COUNTER);
+ pas_write(pas_read(FILTER_FREQUENCY) | F_F_PCM_BUFFER_COUNTER, FILTER_FREQUENCY);
+
+ pcm_count = count;
+ }
+ pas_write(pas_read(FILTER_FREQUENCY) | F_F_PCM_BUFFER_COUNTER | F_F_PCM_RATE_COUNTER, FILTER_FREQUENCY);
+#ifdef NO_TRIGGER
+ pas_write((pas_read(PCM_CONTROL) | P_C_PCM_ENABLE) & ~P_C_PCM_DAC_MODE, PCM_CONTROL);
+#endif
- if (restart_dma)
- DMAbuf_start_dma (dev, buf, count, DMA_MODE_READ);
+ pcm_mode = PCM_ADC;
- if (audio_devs[dev]->dmachan > 3)
- count >>= 1;
+ splx(flags);
+}
+#ifndef NO_TRIGGER
+static void
+pas_audio_trigger (int dev, int state)
+{
+ unsigned long flags;
- if (count != pcm_count)
- {
- pas_write (pas_read (FILTER_FREQUENCY) & ~F_F_PCM_BUFFER_COUNTER, FILTER_FREQUENCY);
- pas_write (S_C_C_SAMPLE_BUFFER | S_C_C_LSB_THEN_MSB | S_C_C_SQUARE_WAVE, SAMPLE_COUNTER_CONTROL);
- pas_write (count & 0xff, SAMPLE_BUFFER_COUNTER);
- pas_write ((count >> 8) & 0xff, SAMPLE_BUFFER_COUNTER);
- pas_write (pas_read (FILTER_FREQUENCY) | F_F_PCM_BUFFER_COUNTER, FILTER_FREQUENCY);
+ flags = splhigh();
- pcm_count = count;
- }
- pas_write (pas_read (FILTER_FREQUENCY) | F_F_PCM_BUFFER_COUNTER | F_F_PCM_RATE_COUNTER, FILTER_FREQUENCY);
- pas_write ((pas_read (PCM_CONTROL) | P_C_PCM_ENABLE) & ~P_C_PCM_DAC_MODE, PCM_CONTROL);
+ state &= open_mode;
- pcm_mode = PCM_ADC;
+ if (state & PCM_ENABLE_OUTPUT)
+ pas_write (pas_read (0xF8A) | 0x40 | 0x10, 0xF8A);
+ else if (state & PCM_ENABLE_INPUT)
+ pas_write ((pas_read (0xF8A) | 0x40) & ~0x10, 0xF8A);
+ else
+ pas_write (pas_read (0xF8A) & ~0x40, 0xF8A);
- RESTORE_INTR (flags);
+ splx(flags);
}
+#endif
static int
-pas_pcm_prepare_for_input (int dev, int bsize, int bcount)
+pas_pcm_prepare_for_input(int dev, int bsize, int bcount)
{
- return 0;
+ return 0;
}
static int
-pas_pcm_prepare_for_output (int dev, int bsize, int bcount)
+pas_pcm_prepare_for_output(int dev, int bsize, int bcount)
{
- return 0;
+ return 0;
}
static struct audio_operations pas_pcm_operations =
{
- "Pro Audio Spectrum",
- DMA_AUTOMODE,
- AFMT_U8 | AFMT_S16_LE,
- NULL,
- 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,
- NULL,
- NULL
+ "Pro Audio Spectrum",
+ DMA_AUTOMODE,
+ AFMT_U8 | AFMT_S16_LE,
+ NULL,
+ 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,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ pas_audio_trigger
};
-long
-pas_pcm_init (long mem_start, struct address_info *hw_config)
+void
+pas_pcm_init(struct address_info * hw_config)
{
- TRACE (printk ("pas2_pcm.c: long pas_pcm_init(long mem_start = %X)\n", mem_start));
-
- pcm_bitsok = 8;
- if (pas_read (OPERATION_MODE_1) & O_M_1_PCM_TYPE)
- pcm_bitsok |= 16;
+ pcm_bitsok = 8;
+ if (pas_read(OPERATION_MODE_1) & O_M_1_PCM_TYPE)
+ pcm_bitsok |= 16;
- pcm_set_speed (DSP_DEFAULT_SPEED);
+ pcm_set_speed(DSP_DEFAULT_SPEED);
- if (num_audiodevs < MAX_AUDIO_DEV)
- {
- audio_devs[my_devnum = num_audiodevs++] = &pas_pcm_operations;
- audio_devs[my_devnum]->dmachan = hw_config->dma;
- audio_devs[my_devnum]->buffcount = 1;
- audio_devs[my_devnum]->buffsize = 2 * DSP_BUFFSIZE;
- }
- else
- printk ("PAS2: Too many PCM devices available\n");
+ if (num_audiodevs < MAX_AUDIO_DEV) {
+ audio_devs[my_devnum = num_audiodevs++] = &pas_pcm_operations;
+ audio_devs[my_devnum]->dmachan1 = hw_config->dma;
+ audio_devs[my_devnum]->buffsize = DSP_BUFFSIZE;
+ } else
+ printf("PAS2: Too many PCM devices available\n");
- return mem_start;
+ return;
}
void
-pas_pcm_interrupt (unsigned char status, int cause)
+pas_pcm_interrupt(u_char status, int cause)
{
- if (cause == 1) /*
- * PCM buffer done
- */
- {
- /*
- * Halt the PCM first. Otherwise we don't have time to start a new
- * block before the PCM chip proceeds to the next sample
- */
-
- if (!(audio_devs[my_devnum]->flags & DMA_AUTOMODE))
- {
- pas_write (pas_read (PCM_CONTROL) & ~P_C_PCM_ENABLE,
- PCM_CONTROL);
- }
-
- switch (pcm_mode)
- {
-
- case PCM_DAC:
- DMAbuf_outputintr (my_devnum, 1);
- break;
-
- case PCM_ADC:
- DMAbuf_inputintr (my_devnum);
- break;
-
- default:
- printk ("PAS: Unexpected PCM interrupt\n");
+ if (cause == 1) { /* PCM buffer done */
+ /*
+ * Halt the PCM first. Otherwise we don't have time to start
+ * a new block before the PCM chip proceeds to the next
+ * sample
+ */
+
+ if (!(audio_devs[my_devnum]->flags & DMA_AUTOMODE)) {
+ pas_write(pas_read(PCM_CONTROL) & ~P_C_PCM_ENABLE,
+ PCM_CONTROL);
+ }
+ switch (pcm_mode) {
+
+ case PCM_DAC:
+ DMAbuf_outputintr(my_devnum, 1);
+ break;
+
+ case PCM_ADC:
+ DMAbuf_inputintr(my_devnum);
+ break;
+
+ default:
+ printf("PAS: Unexpected PCM interrupt\n");
+ }
}
- }
}
#endif
-
-#endif
diff --git a/sys/i386/isa/sound/patmgr.c b/sys/i386/isa/sound/patmgr.c
index a77626609106..60f0ed639d90 100644
--- a/sys/i386/isa/sound/patmgr.c
+++ b/sys/i386/isa/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,241 +24,244 @@
* 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
-#include "sound_config.h"
+#include <i386/isa/sound/sound_config.h>
-#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_SEQUENCER)
+#if defined(CONFIG_SEQUENCER)
-DEFINE_WAIT_QUEUES (server_procs[MAX_SYNTH_DEV],
- server_wait_flag[MAX_SYNTH_DEV]);
+static int *server_procs[MAX_SYNTH_DEV] = {NULL};
+static volatile struct snd_wait server_wait_flag[MAX_SYNTH_DEV] = { {0}};
-static struct patmgr_info *mbox[MAX_SYNTH_DEV] =
-{NULL};
-static volatile int msg_direction[MAX_SYNTH_DEV] =
-{0};
+static struct patmgr_info *mbox[MAX_SYNTH_DEV] = {NULL};
+static volatile int msg_direction[MAX_SYNTH_DEV] = {0};
-static int pmgr_opened[MAX_SYNTH_DEV] =
-{0};
+static int pmgr_opened[MAX_SYNTH_DEV] = {0};
#define A_TO_S 1
#define S_TO_A 2
-DEFINE_WAIT_QUEUE (appl_proc, appl_wait_flag);
+static int *appl_proc = NULL;
+static volatile struct snd_wait appl_wait_flag =
+{0};
int
-pmgr_open (int dev)
+pmgr_open(int dev)
{
- if (dev < 0 || dev >= num_synths)
- return RET_ERROR (ENXIO);
+ if (dev < 0 || dev >= num_synths)
+ return -(ENXIO);
- if (pmgr_opened[dev])
- return RET_ERROR (EBUSY);
- pmgr_opened[dev] = 1;
+ if (pmgr_opened[dev])
+ return -(EBUSY);
+ pmgr_opened[dev] = 1;
- RESET_WAIT_QUEUE (server_procs[dev], server_wait_flag[dev]);
+ server_wait_flag[dev].aborting = 0;
+ server_wait_flag[dev].mode = WK_NONE;
- return 0;
+ return 0;
}
void
-pmgr_release (int dev)
+pmgr_release(int dev)
{
- if (mbox[dev]) /*
- * Killed in action. Inform the client
- */
- {
+ if (mbox[dev]) { /* Killed in action. Inform the client */
- mbox[dev]->key = PM_ERROR;
- mbox[dev]->parm1 = RET_ERROR (EIO);
+ mbox[dev]->key = PM_ERROR;
+ mbox[dev]->parm1 = -(EIO);
- if (SOMEONE_WAITING (appl_proc, appl_wait_flag))
- WAKE_UP (appl_proc, appl_wait_flag);
+ if ((appl_wait_flag.mode & WK_SLEEP)) {
+ appl_wait_flag.mode = WK_WAKEUP;
+ wakeup(appl_proc);
+ };
}
-
- pmgr_opened[dev] = 0;
+ pmgr_opened[dev] = 0;
}
int
-pmgr_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
+pmgr_read(int dev, struct fileinfo * file, snd_rw_buf * buf, int count)
{
- unsigned long flags;
- int ok = 0;
+ u_long flags;
+ int ok = 0;
- if (count != sizeof (struct patmgr_info))
- {
- printk ("PATMGR%d: Invalid read count\n", dev);
- return RET_ERROR (EIO);
+ if (count != sizeof(struct patmgr_info)) {
+ printf("PATMGR%d: Invalid read count\n", dev);
+ return -(EIO);
}
+ while (!ok && !(server_wait_flag[dev].aborting)) {
+ flags = splhigh();
- while (!ok && !PROCESS_ABORTING (server_procs[dev], server_wait_flag[dev]))
- {
- DISABLE_INTR (flags);
+ while (!(mbox[dev] && msg_direction[dev] == A_TO_S) &&
+ !(server_wait_flag[dev].aborting)) {
- while (!(mbox[dev] && msg_direction[dev] == A_TO_S) &&
- !PROCESS_ABORTING (server_procs[dev], server_wait_flag[dev]))
- {
- DO_SLEEP (server_procs[dev], server_wait_flag[dev], 0);
- }
+ int chn;
+ server_procs[dev] = &chn;
+ DO_SLEEP(chn, server_wait_flag[dev], 0);
- if (mbox[dev] && msg_direction[dev] == A_TO_S)
- {
- COPY_TO_USER (buf, 0, (char *) mbox[dev], count);
- msg_direction[dev] = 0;
- ok = 1;
}
- RESTORE_INTR (flags);
+ if (mbox[dev] && msg_direction[dev] == A_TO_S) {
+
+ if (uiomove((char *) mbox[dev], count, buf)) {
+ printf("sb: Bad copyout()!\n");
+ };
+ msg_direction[dev] = 0;
+ ok = 1;
+ }
+ splx(flags);
}
- if (!ok)
- return RET_ERROR (EINTR);
- return count;
+ if (!ok)
+ return -(EINTR);
+ return count;
}
int
-pmgr_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
+pmgr_write(int dev, struct fileinfo * file, snd_rw_buf * buf, int count)
{
- unsigned long flags;
+ u_long flags;
- if (count < 4)
- {
- printk ("PATMGR%d: Write count < 4\n", dev);
- return RET_ERROR (EIO);
+ if (count < 4) {
+ printf("PATMGR%d: Write count < 4\n", dev);
+ return -(EIO);
}
+ if (uiomove((char *) mbox[dev], 4, buf)) {
+ printf("sb: Bad copyin()!\n");
+ };
- COPY_FROM_USER (mbox[dev], buf, 0, 4);
-
- if (*(unsigned char *) mbox[dev] == SEQ_FULLSIZE)
- {
- int tmp_dev;
+ if (*(u_char *) mbox[dev] == SEQ_FULLSIZE) {
+ int tmp_dev;
- tmp_dev = ((unsigned short *) mbox[dev])[2];
- if (tmp_dev != dev)
- return RET_ERROR (ENXIO);
+ tmp_dev = ((u_short *) mbox[dev])[2];
+ if (tmp_dev != dev)
+ return -(ENXIO);
- return synth_devs[dev]->load_patch (dev, *(unsigned short *) mbox[dev],
- buf, 4, count, 1);
+ return synth_devs[dev]->load_patch(dev, *(u_short *) mbox[dev],
+ buf, 4, count, 1);
}
-
- if (count != sizeof (struct patmgr_info))
- {
- printk ("PATMGR%d: Invalid write count\n", dev);
- return RET_ERROR (EIO);
+ if (count != sizeof(struct patmgr_info)) {
+ printf("PATMGR%d: Invalid write count\n", dev);
+ return -(EIO);
}
+ /*
+ * If everything went OK, there should be a preallocated buffer in
+ * the mailbox and a client waiting.
+ */
- /*
- * If everything went OK, there should be a preallocated buffer in the
- * mailbox and a client waiting.
- */
+ flags = splhigh();
- DISABLE_INTR (flags);
+ if (mbox[dev] && !msg_direction[dev]) {
- if (mbox[dev] && !msg_direction[dev])
- {
- COPY_FROM_USER (&((char *) mbox[dev])[4], buf, 4, count - 4);
- msg_direction[dev] = S_TO_A;
+ if (uiomove(&((char *) mbox[dev])[4], count - 4, buf)) {
+ printf("sb: Bad copyin()!\n");
+ };
+ msg_direction[dev] = S_TO_A;
- if (SOMEONE_WAITING (appl_proc, appl_wait_flag))
- {
- WAKE_UP (appl_proc, appl_wait_flag);
+ if ((appl_wait_flag.mode & WK_SLEEP)) {
+ appl_wait_flag.mode = WK_WAKEUP;
+ wakeup(appl_proc);
}
}
+ splx(flags);
- RESTORE_INTR (flags);
-
- return count;
+ return count;
}
int
-pmgr_access (int dev, struct patmgr_info *rec)
+pmgr_access(int dev, struct patmgr_info * rec)
{
- unsigned long flags;
- int err = 0;
-
- DISABLE_INTR (flags);
-
- if (mbox[dev])
- printk (" PATMGR: Server %d mbox full. Why?\n", dev);
- else
- {
- rec->key = PM_K_COMMAND;
- mbox[dev] = rec;
- msg_direction[dev] = A_TO_S;
-
- if (SOMEONE_WAITING (server_procs[dev], server_wait_flag[dev]))
- {
- WAKE_UP (server_procs[dev], server_wait_flag[dev]);
- }
+ u_long flags;
+ int err = 0;
- DO_SLEEP (appl_proc, appl_wait_flag, 0);
+ flags = splhigh();
- if (msg_direction[dev] != S_TO_A)
- {
- rec->key = PM_ERROR;
- rec->parm1 = RET_ERROR (EIO);
- }
- else if (rec->key == PM_ERROR)
- {
- err = rec->parm1;
- if (err > 0)
- err = -err;
+ if (mbox[dev])
+ printf(" PATMGR: Server %d mbox full. Why?\n", dev);
+ else {
+ int flag, chn;
+
+ rec->key = PM_K_COMMAND;
+ mbox[dev] = rec;
+ msg_direction[dev] = A_TO_S;
+
+ if ((server_wait_flag[dev].mode & WK_SLEEP)) {
+ server_wait_flag[dev].mode = WK_WAKEUP;
+ wakeup(server_procs[dev]);
}
- mbox[dev] = NULL;
- msg_direction[dev] = 0;
+
+ appl_proc = &chn;
+ DO_SLEEP(chn, appl_wait_flag, 0);
+
+ if (msg_direction[dev] != S_TO_A) {
+ rec->key = PM_ERROR;
+ rec->parm1 = -(EIO);
+ } else if (rec->key == PM_ERROR) {
+ err = rec->parm1;
+ if (err > 0)
+ err = -err;
+ }
+ mbox[dev] = NULL;
+ msg_direction[dev] = 0;
}
- RESTORE_INTR (flags);
+ splx(flags);
- return err;
+ return err;
}
int
-pmgr_inform (int dev, int event, unsigned long p1, unsigned long p2,
- unsigned long p3, unsigned long p4)
+pmgr_inform(int dev, int event, u_long p1, u_long p2, u_long p3, u_long p4)
{
- unsigned long flags;
- int err = 0;
+ u_long flags;
+ int err = 0;
- if (!pmgr_opened[dev])
- return 0;
+ struct patmgr_info *tmp_mbox;
+
+ if (!pmgr_opened[dev])
+ return 0;
+
+ tmp_mbox = (struct patmgr_info *) malloc(sizeof(struct patmgr_info), M_TEMP, M_WAITOK);
- DISABLE_INTR (flags);
-
- if (mbox[dev])
- printk (" PATMGR: Server %d mbox full. Why?\n", dev);
- else
- {
- mbox[dev] =
- (struct patmgr_info *) KERNEL_MALLOC (sizeof (struct patmgr_info));
-
- mbox[dev]->key = PM_K_EVENT;
- mbox[dev]->command = event;
- mbox[dev]->parm1 = p1;
- mbox[dev]->parm2 = p2;
- mbox[dev]->parm3 = p3;
- msg_direction[dev] = A_TO_S;
-
- if (SOMEONE_WAITING (server_procs[dev], server_wait_flag[dev]))
- {
- WAKE_UP (server_procs[dev], server_wait_flag[dev]);
+ if (tmp_mbox == NULL) {
+ printf("pmgr: Couldn't allocate memory for a message\n");
+ return 0;
+ }
+ flags = splhigh();
+
+ if (mbox[dev])
+ printf(" PATMGR: Server %d mbox full. Why?\n", dev);
+ else {
+ int flag, chn;
+
+ mbox[dev] = tmp_mbox;
+ mbox[dev]->key = PM_K_EVENT;
+ mbox[dev]->command = event;
+ mbox[dev]->parm1 = p1;
+ mbox[dev]->parm2 = p2;
+ mbox[dev]->parm3 = p3;
+ msg_direction[dev] = A_TO_S;
+
+ if ((server_wait_flag[dev].mode & WK_SLEEP)) {
+ server_wait_flag[dev].mode = WK_WAKEUP;
+ wakeup(server_procs[dev]);
}
- DO_SLEEP (appl_proc, appl_wait_flag, 0);
- if (mbox[dev])
- KERNEL_FREE (mbox[dev]);
- mbox[dev] = NULL;
- msg_direction[dev] = 0;
+
+ appl_proc = &chn;
+ DO_SLEEP(chn, appl_wait_flag, 0);
+
+ mbox[dev] = NULL;
+ msg_direction[dev] = 0;
}
- RESTORE_INTR (flags);
+ splx(flags);
+ free(tmp_mbox, M_TEMP);
- return err;
+ return err;
}
#endif
diff --git a/sys/i386/isa/sound/pcm86.c b/sys/i386/isa/sound/pcm86.c
index aa7e3d77ef21..ff55d5fb2d1a 100644
--- a/sys/i386/isa/sound/pcm86.c
+++ b/sys/i386/isa/sound/pcm86.c
@@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: pcm86.c,v 2.4 1996/01/24 19:53:34 abtk Exp $
+ * $Id: pcm86.c,v 1.4 1997/06/03 10:25:41 kato Exp $
*/
/*
@@ -1070,10 +1070,14 @@ fifo_send_mono_16be(pcm_data *buf, int count, int uflag)
}
d = ((d0 * (pcm_s.chipspeed - pcm_s.acc)) + (d1 * pcm_s.acc))
/ pcm_s.chipspeed;
+/* outb(pcm_s.iobase + 12, d & 0xff);
+ outb(pcm_s.iobase + 12, (d >> 8) & 0xff);
outb(pcm_s.iobase + 12, d & 0xff);
+ outb(pcm_s.iobase + 12, (d >> 8) & 0xff); */
outb(pcm_s.iobase + 12, (d >> 8) & 0xff);
outb(pcm_s.iobase + 12, d & 0xff);
outb(pcm_s.iobase + 12, (d >> 8) & 0xff);
+ outb(pcm_s.iobase + 12, d & 0xff);
pcm_s.acc += pcm_s.speed;
}
diff --git a/sys/i386/isa/sound/pss.c b/sys/i386/isa/sound/pss.c
index 6a0e7a8327ff..17acfb2b4172 100644
--- a/sys/i386/isa/sound/pss.c
+++ b/sys/i386/isa/sound/pss.c
@@ -1,924 +1,693 @@
-/* Marc.Hoffman@analog.com
-
- This is a pss driver.
-
- it is based on Greg.Yukna@analog.com @file{host} for DOG
-
- Unfortunately I can't distribute the ld file needed to
- make the pss card to emulate the SB stuff.
-
- I have provided a simple interface to the PSS unlike the
- DOG version. to download a new algorithim just cat it to
- /dev/pss 14,9.
-
- You really need to rebuild this with the synth.ld file
-
- get the <synth>.ld from your dos directory maybe
- voyetra\dsp001.ld
-
- ld2inc < synth.ld > synth-ld.h
- (make config does the same).
-
- rebuild
-
- Okay if you blow things away no problem just
-
- main(){ioctl(open("/dev/pss"),SNDCTL_PSS_RESET)};
-
- and everything will be okay.
-
- At first I was going to wory about applications that were using
- the sound stuff and disallow the use of /dev/pss. But for
- now I figured it doesn't matter.
-
- And if you change algos all the other applications running die off
- due to DMA problems. Yeah just pull the plug and watch em die.
-
- If the registers get hosed
- main(){ioctl(open("/dev/pss"),SNDCTL_PSS_SETUP_REGISTERS)};
-
- Probably everything else can be done via mmap
-
- Oh if you want to develope code for the ADSP-21xx or Program the
- 1848 just send me mail and I will hook you up.
-
- marc.hoffman@analog.com
-
- */
-#include "sound_config.h"
-
-#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_PSS)
-
-#ifndef PSS_MSS_BASE
-#define PSS_MSS_BASE 0
-#endif
-
-#ifndef PSS_MPU_BASE
-#define PSS_MPU_BASE 0
-#endif
-
-#ifndef PSS_MPU_IRQ
-#define PSS_MPU_IRQ 0
-#endif
-
-#undef DEB
-#define DEB(x) x
-
-#include "pss.h"
-
-static int pss_ok = 0;
-static int sb_ok = 0;
-
-static int pss_base;
-static int pss_irq;
-static int pss_dma;
-
-static int gamePort = 0;
-
-static int sbInt;
-static int cdPol;
-static int cdAddr = 0; /* 0x340; */
-static int cdInt = 10;
-
-/* Define these by hand in local.h */
-static int wssAddr = PSS_MSS_BASE;
-static int midiAddr = PSS_MPU_BASE;
-static int midiInt = PSS_MPU_IRQ;
-
-static int SoundPortAddress;
-static int SoundPortData;
-static int speaker = 1;
-
-
-static struct pss_speaker default_speaker =
-{0, 0, 0, PSS_STEREO};
-
-DEFINE_WAIT_QUEUE (pss_sleeper, pss_sleep_flag);
-
+/*
+ * sound/pss.c
+ *
+ * The low level driver for the Personal Sound System (ECHO ESC614).
+ *
+ * Copyright by Hannu Savolainen 1993
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer. 2.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <i386/isa/sound/sound_config.h>
+
+#if defined(CONFIG_PSS) && defined(CONFIG_AUDIO)
+
+/*
+ * PSS registers.
+ */
+#define REG(x) (devc->base+x)
+#define PSS_DATA 0
+#define PSS_STATUS 2
+#define PSS_CONTROL 2
+#define PSS_ID 4
+#define PSS_IRQACK 4
+#define PSS_PIO 0x1a
+
+/*
+ * Config registers
+ */
+#define CONF_PSS 0x10
+#define CONF_WSS 0x12
+#define CONF_SB 0x13
+#define CONF_CDROM 0x16
+#define CONF_MIDI 0x18
+
+/*
+ * Status bits.
+ */
+#define PSS_FLAG3 0x0800
+#define PSS_FLAG2 0x0400
+#define PSS_FLAG1 0x1000
+#define PSS_FLAG0 0x0800
+#define PSS_WRITE_EMPTY 0x8000
+#define PSS_READ_FULL 0x4000
+
+#include "coproc.h"
+
+#ifdef PSS_HAVE_LD
#include "synth-ld.h"
+#else
+static int pss_synthLen = 0;
+static u_char pss_synth[1] =
+{0};
-static int pss_download_boot (unsigned char *block, int size);
-static int pss_reset_dsp (void);
+#endif
-static inline void
-pss_outpw (unsigned short port, unsigned short value)
-{
- __asm__ __volatile__ ("outw %w0, %w1"
- : /* no outputs */
- :"a" (value), "d" (port));
-}
+typedef struct pss_config {
+ int base;
+ int irq;
+ int dma;
+ sound_os_info *osp;
+} pss_config;
-static inline unsigned int
-pss_inpw (unsigned short port)
-{
- unsigned int _v;
- __asm__ __volatile__ ("inw %w1,%w0"
- :"=a" (_v):"d" (port), "0" (0));
+static pss_config pss_data;
+static pss_config *devc = &pss_data;
- return _v;
-}
+static int pss_initialized = 0;
+static int nonstandard_microcode = 0;
-static void
-PSS_write (int data)
+int
+probe_pss(struct address_info * hw_config)
{
- int i, limit;
-
- limit = GET_TIME () + 10; /* The timeout is 0.1 secods */
- /*
- * Note! the i<5000000 is an emergency exit. The dsp_command() is sometimes
- * called while interrupts are disabled. This means that the timer is
- * disabled also. However the timeout situation is a abnormal condition.
- * Normally the DSP should be ready to accept commands after just couple of
- * loops.
- */
-
- for (i = 0; i < 5000000 && GET_TIME () < limit; i++)
- {
- if (pss_inpw (pss_base + PSS_STATUS) & PSS_WRITE_EMPTY)
- {
- pss_outpw (pss_base + PSS_DATA, data);
- return;
+ u_short id;
+ int irq, dma;
+
+ devc->base = hw_config->io_base;
+ irq = devc->irq = hw_config->irq;
+ dma = devc->dma = hw_config->dma;
+ devc->osp = hw_config->osp;
+
+ /* these are the possible addresses */
+ if (devc->base != 0x220 && devc->base != 0x240 &&
+ devc->base != 0x230 && devc->base != 0x250)
+ return 0;
+
+ /* these are the possible irqs */
+ if (irq != 3 && irq != 5 && irq != 7 && irq != 9 &&
+ irq != 10 && irq != 11 && irq != 12)
+ return 0;
+
+ /* and these are the possible dmas */
+ if (dma != 5 && dma != 6 && dma != 7)
+ return 0;
+
+ id = inb(REG(PSS_ID));
+
+ /* XXX the following test cannot possibly succeed! - lr970714 */
+ if ((id >> 8) != 'E') {
+ /*
+ * printf ("No PSS signature detected at 0x%x (0x%x)\n",
+ * devc->base, id);
+ */
+ return 0;
}
- }
- printk ("PSS: DSP Command (%04x) Timeout.\n", data);
- printk ("IRQ conflict???\n");
+ return 1;
}
-
-static void
-pss_setaddr (int addr, int configAddr)
-{
- int val;
-
- val = pss_inpw (configAddr);
- val &= ADDR_MASK;
- val |= (addr << 4);
- pss_outpw (configAddr, val);
-}
-
-/*_____ pss_checkint
- This function tests an interrupt number to see if
- it is availible. It takes the interrupt button
- as it's argument and returns TRUE if the interrupt
- is ok.
-*/
static int
-pss_checkint (int intNum)
+set_irq(pss_config * devc, int dev, int irq)
{
- int val;
- int ret;
- int i;
-
- /*_____ Set the interrupt bits */
- switch (intNum)
- {
- case 3:
- val = pss_inpw (pss_base + PSS_CONFIG);
- val &= INT_MASK;
- val |= INT_3_BITS;
- pss_outpw (pss_base + PSS_CONFIG, val);
- break;
- case 5:
- val = pss_inpw (pss_base + PSS_CONFIG);
- val &= INT_MASK;
- val |= INT_5_BITS;
- pss_outpw (pss_base + PSS_CONFIG, val);
- break;
- case 7:
- val = pss_inpw (pss_base + PSS_CONFIG);
- val &= INT_MASK;
- val |= INT_7_BITS;
- pss_outpw (pss_base + PSS_CONFIG, val);
- break;
- case 9:
- val = pss_inpw (pss_base + PSS_CONFIG);
- val &= INT_MASK;
- val |= INT_9_BITS;
- pss_outpw (pss_base + PSS_CONFIG, val);
- break;
- case 10:
- val = pss_inpw (pss_base + PSS_CONFIG);
- val &= INT_MASK;
- val |= INT_10_BITS;
- pss_outpw (pss_base + PSS_CONFIG, val);
- break;
- case 11:
- val = pss_inpw (pss_base + PSS_CONFIG);
- val &= INT_MASK;
- val |= INT_11_BITS;
- pss_outpw (pss_base + PSS_CONFIG, val);
- break;
- case 12:
- val = pss_inpw (pss_base + PSS_CONFIG);
- val &= INT_MASK;
- val |= INT_12_BITS;
- pss_outpw (pss_base + PSS_CONFIG, val);
- break;
- default:
- printk ("unknown interupt selected. %d\n", intNum);
- return 0;
- }
-
- /*_____ Set the interrupt test bit */
- val = pss_inpw (pss_base + PSS_CONFIG);
- val |= INT_TEST_BIT;
- pss_outpw (pss_base + PSS_CONFIG, val);
-
- /*_____ Check if the interrupt is in use */
- /*_____ Do it a few times in case there is a delay */
- ret = 0;
- for (i = 0; i < 5; i++)
- {
- val = pss_inpw (pss_base + PSS_CONFIG);
- if (val & INT_TEST_PASS)
+ static u_short irq_bits[16] =
{
- ret = 1;
- break;
- }
- }
- /*_____ Clear the Test bit and the interrupt bits */
- val = pss_inpw (pss_base + PSS_CONFIG);
- val &= INT_TEST_BIT_MASK;
- val &= INT_MASK;
- pss_outpw (pss_base + PSS_CONFIG, val);
- return (ret);
-}
+ 0x0000, 0x0000, 0x0000, 0x0008,
+ 0x0000, 0x0010, 0x0000, 0x0018,
+ 0x0000, 0x0020, 0x0028, 0x0030,
+ 0x0038, 0x0000, 0x0000, 0x0000
+ };
-/*____ pss_setint
- This function sets the correct bits in the
- configuration register to
- enable the chosen interrupt.
-*/
-static void
-pss_setint (int intNum, int configAddress)
-{
- int val;
-
- switch (intNum)
- {
- case 0:
- val = pss_inpw (configAddress);
- val &= INT_MASK;
- pss_outpw (configAddress, val);
- break;
- case 3:
- val = pss_inpw (configAddress);
- val &= INT_MASK;
- val |= INT_3_BITS;
- pss_outpw (configAddress, val);
- break;
- case 5:
- val = pss_inpw (configAddress);
- val &= INT_MASK;
- val |= INT_5_BITS;
- pss_outpw (configAddress, val);
- break;
- case 7:
- val = pss_inpw (configAddress);
- val &= INT_MASK;
- val |= INT_7_BITS;
- pss_outpw (configAddress, val);
- break;
- case 9:
- val = pss_inpw (configAddress);
- val &= INT_MASK;
- val |= INT_9_BITS;
- pss_outpw (configAddress, val);
- break;
- case 10:
- val = pss_inpw (configAddress);
- val &= INT_MASK;
- val |= INT_10_BITS;
- pss_outpw (configAddress, val);
- break;
- case 11:
- val = pss_inpw (configAddress);
- val &= INT_MASK;
- val |= INT_11_BITS;
- pss_outpw (configAddress, val);
- break;
- case 12:
- val = pss_inpw (configAddress);
- val &= INT_MASK;
- val |= INT_12_BITS;
- pss_outpw (configAddress, val);
- break;
- default:
- printk ("pss_setint unkown int\n");
- }
-}
+ u_short tmp, bits;
+ if (irq < 0 || irq > 15)
+ return 0;
-/*____ pss_setsbint
- This function sets the correct bits in the
- SoundBlaster configuration PSS register to
- enable the chosen interrupt.
- It takes a interrupt button as its argument.
-*/
-static void
-pss_setsbint (int intNum)
-{
- int val;
- int sbConfigAddress;
-
- sbConfigAddress = pss_base + SB_CONFIG;
- switch (intNum)
- {
- case 3:
- val = pss_inpw (sbConfigAddress);
- val &= INT_MASK;
- val |= INT_3_BITS;
- pss_outpw (sbConfigAddress, val);
- break;
- case 5:
- val = pss_inpw (sbConfigAddress);
- val &= INT_MASK;
- val |= INT_5_BITS;
- pss_outpw (sbConfigAddress, val);
- break;
- case 7:
- val = pss_inpw (sbConfigAddress);
- val &= INT_MASK;
- val |= INT_7_BITS;
- pss_outpw (sbConfigAddress, val);
- break;
- default:
- printk ("pss_setsbint: unknown_int\n");
- }
-}
-
-/*____ pss_setsbdma
- This function sets the correct bits in the
- SoundBlaster configuration PSS register to
- enable the chosen DMA channel.
- It takes a DMA button as its argument.
-*/
-static void
-pss_setsbdma (int dmaNum)
-{
- int val;
- int sbConfigAddress;
-
- sbConfigAddress = pss_base + SB_CONFIG;
-
- switch (dmaNum)
- {
- case 1:
- val = pss_inpw (sbConfigAddress);
- val &= DMA_MASK;
- val |= DMA_1_BITS;
- pss_outpw (sbConfigAddress, val);
- break;
- default:
- printk ("Personal Sound System ERROR! pss_setsbdma: unknown_dma\n");
- }
-}
+ tmp = inb(REG(dev)) & ~0x38; /* Load confreg, mask IRQ bits out */
-/*____ pss_setwssdma
- This function sets the correct bits in the
- WSS configuration PSS register to
- enable the chosen DMA channel.
- It takes a DMA button as its argument.
-*/
-static void
-pss_setwssdma (int dmaNum)
-{
- int val;
- int wssConfigAddress;
-
- wssConfigAddress = pss_base + PSS_WSS_CONFIG;
-
- switch (dmaNum)
- {
- case 0:
- val = pss_inpw (wssConfigAddress);
- val &= DMA_MASK;
- val |= DMA_0_BITS;
- pss_outpw (wssConfigAddress, val);
- break;
- case 1:
- val = pss_inpw (wssConfigAddress);
- val &= DMA_MASK;
- val |= DMA_1_BITS;
- pss_outpw (wssConfigAddress, val);
- break;
- case 3:
- val = pss_inpw (wssConfigAddress);
- val &= DMA_MASK;
- val |= DMA_3_BITS;
- pss_outpw (wssConfigAddress, val);
- break;
- default:
- printk ("Personal Sound System ERROR! pss_setwssdma: unknown_dma\n");
- }
+ if ((bits = irq_bits[irq]) == 0 && irq != 0) {
+ printf("PSS: Invalid IRQ %d\n", irq);
+ return 0;
+ }
+ outw(REG(dev), tmp | bits);
+ return 1;
}
-
-/*_____ SetSpeakerOut
- This function sets the Volume, Bass, Treble and Mode of
- the speaker out channel.
- */
-void
-pss_setspeaker (struct pss_speaker *spk)
+static int
+set_io_base(pss_config * devc, int dev, int base)
{
- PSS_write (SET_MASTER_COMMAND);
- if (spk->volume > PHILLIPS_VOL_MAX)
- spk->volume = PHILLIPS_VOL_MAX;
- if (spk->volume < PHILLIPS_VOL_MIN)
- spk->volume = PHILLIPS_VOL_MIN;
-
- PSS_write (MASTER_VOLUME_LEFT
- | (PHILLIPS_VOL_CONSTANT + spk->volume / PHILLIPS_VOL_STEP));
- PSS_write (SET_MASTER_COMMAND);
- PSS_write (MASTER_VOLUME_RIGHT
- | (PHILLIPS_VOL_CONSTANT + spk->volume / PHILLIPS_VOL_STEP));
-
- if (spk->bass > PHILLIPS_BASS_MAX)
- spk->bass = PHILLIPS_BASS_MAX;
- if (spk->bass < PHILLIPS_BASS_MIN)
- spk->bass = PHILLIPS_BASS_MIN;
- PSS_write (SET_MASTER_COMMAND);
- PSS_write (MASTER_BASS
- | (PHILLIPS_BASS_CONSTANT + spk->bass / PHILLIPS_BASS_STEP));
-
- if (spk->treb > PHILLIPS_TREBLE_MAX)
- spk->treb = PHILLIPS_TREBLE_MAX;
- if (spk->treb < PHILLIPS_TREBLE_MIN)
- spk->treb = PHILLIPS_TREBLE_MIN;
- PSS_write (SET_MASTER_COMMAND);
- PSS_write (MASTER_TREBLE
- | (PHILLIPS_TREBLE_CONSTANT + spk->treb / PHILLIPS_TREBLE_STEP));
-
- PSS_write (SET_MASTER_COMMAND);
- PSS_write (MASTER_SWITCH | spk->mode);
-}
+ u_short tmp = inb(REG(dev)) & 0x003f;
+ u_short bits = (base & 0x0ffc) << 4;
-static void
-pss_init1848 (void)
-{
- /*_____ Wait for 1848 to init */
- while (INB (SoundPortAddress) & SP_IN_INIT);
+ outw(REG(dev), bits | tmp);
- /*_____ Wait for 1848 to autocal */
- OUTB (SoundPortAddress, SP_TEST_AND_INIT);
- while (INB (SoundPortData) & AUTO_CAL_IN_PROG);
+ return 1;
}
static int
-pss_configure_registers_to_look_like_sb (void)
+set_dma(pss_config * devc, int dev, int dma)
{
- pss_setaddr (wssAddr, pss_base + PSS_WSS_CONFIG);
-
- SoundPortAddress = wssAddr + 4;
- SoundPortData = wssAddr + 5;
-
- DEB (printk ("Turning Game Port %s.\n",
- gamePort ? "On" : "Off"));
-
- /*_____ Turn on the Game port */
- if (gamePort)
- pss_outpw (pss_base + PSS_STATUS,
- pss_inpw (pss_base + PSS_STATUS) | GAME_BIT);
- else
- pss_outpw (pss_base + PSS_STATUS,
- pss_inpw (pss_base + PSS_STATUS) & GAME_BIT_MASK);
-
-
- DEB (printk ("PSS attaching base %x irq %d dma %d\n",
- pss_base, pss_irq, pss_dma));
+ static u_short dma_bits[8] =
+ {
+ 0x0001, 0x0002, 0x0000, 0x0003,
+ 0x0000, 0x0005, 0x0006, 0x0007
+ };
- /* Check if sb is enabled if it is check the interrupt */
- pss_outpw (pss_base + SB_CONFIG, 0);
+ u_short tmp, bits;
- if (pss_irq != 0)
- {
- DEB (printk ("PSS Emulating Sound Blaster ADDR %04x\n", pss_base));
- DEB (printk ("PSS SBC: attaching base %x irq %d dma %d\n",
- SBC_BASE, SBC_IRQ, SBC_DMA));
+ if (dma < 0 || dma > 7)
+ return 0;
- if (pss_checkint (SBC_IRQ) == 0)
- {
- printk ("PSS! attach: int_error\n");
- return 0;
- }
+ tmp = inb(REG(dev)) & ~0x07; /* Load confreg, mask DMA bits out */
- pss_setsbint (SBC_IRQ);
- pss_setsbdma (SBC_DMA);
- sb_ok = 1;
- }
- else
- {
- sb_ok = 0;
- printk ("PSS: sound blaster error init\n");
- }
-
- /* Check if cd is enabled if it is check the interrupt */
- pss_outpw (pss_base + CD_CONFIG, 0);
-
- if (cdAddr != 0)
- {
- DEB (printk ("PSS:CD drive %x irq: %d", cdAddr, cdInt));
- if (cdInt != 0)
- {
- if (pss_checkint (cdInt) == 0)
- {
- printk ("Can't allocate cdInt %d\n", cdInt);
- }
- else
- {
- int val;
-
- printk ("CD poll ");
- pss_setaddr (cdAddr, pss_base + CD_CONFIG);
- pss_setint (cdInt, pss_base + CD_CONFIG);
-
- /* set the correct bit in the
- configuration register to
- set the irq polarity for the CD-Rom.
- NOTE: This bit is in the address config
- field, It must be configured after setting
- the CD-ROM ADDRESS!!! */
- val = pss_inpw (pss_base + CD_CONFIG);
- pss_outpw (pss_base + CD_CONFIG, 0);
- val &= CD_POL_MASK;
- if (cdPol)
- val |= CD_POL_BIT;
- pss_outpw (pss_base + CD_CONFIG, val);
- }
- }
- }
-
- /* Check if midi is enabled if it is check the interrupt */
- pss_outpw (pss_base + MIDI_CONFIG, 0);
- if (midiAddr != 0)
- {
- printk ("midi init %x %d\n", midiAddr, midiInt);
- if (pss_checkint (midiInt) == 0)
- {
- printk ("midi init int error %x %d\n", midiAddr, midiInt);
+ if ((bits = dma_bits[dma]) == 0 && dma != 4) {
+ printf("PSS: Invalid DMA %d\n", dma);
+ return 0;
}
- else
- {
- pss_setaddr (midiAddr, pss_base + MIDI_CONFIG);
- pss_setint (midiInt, pss_base + MIDI_CONFIG);
- }
- }
- return 1;
+ outw(REG(dev), tmp | bits);
+ return 1;
}
-long
-attach_pss (long mem_start, struct address_info *hw_config)
+static int
+pss_reset_dsp(pss_config * devc)
{
- if (pss_ok)
- {
- if (hw_config)
- {
- printk (" <PSS-ESC614>");
- }
-
- return mem_start;
- }
+ u_long i, limit = get_time() + 10;
- pss_ok = 1;
+ outw(REG(PSS_CONTROL), 0x2000);
- if (pss_configure_registers_to_look_like_sb () == 0)
- return mem_start;
+ for (i = 0; i < 32768 && get_time() < limit; i++)
+ inb(REG(PSS_CONTROL));
- if (sb_ok)
- if (pss_synthLen
- && pss_download_boot (pss_synth, pss_synthLen))
- {
- if (speaker)
- pss_setspeaker (&default_speaker);
- pss_ok = 1;
- }
- else
- pss_reset_dsp ();
+ outw(REG(PSS_CONTROL), 0x0000);
- return mem_start;
+ return 1;
}
-int
-probe_pss (struct address_info *hw_config)
-{
- pss_base = hw_config->io_base;
- pss_irq = hw_config->irq;
- pss_dma = hw_config->dma;
-
- if ((pss_inpw (pss_base + 4) & 0xff00) == 0x4500)
- {
- attach_pss (0, hw_config);
- return 1;
- }
- printk (" fail base %x irq %d dma %d\n", pss_base, pss_irq, pss_dma);
- return 0;
-}
-
-
static int
-pss_reattach (void)
+pss_put_dspword(pss_config * devc, u_short word)
{
- pss_ok = 0;
- attach_pss (0, 0);
- return 1;
+ int i, val;
+
+ for (i = 0; i < 327680; i++) {
+ val = inb(REG(PSS_STATUS));
+ if (val & PSS_WRITE_EMPTY) {
+ outw(REG(PSS_DATA), word);
+ return 1;
+ }
+ }
+ return 0;
}
static int
-pss_reset_dsp ()
+pss_get_dspword(pss_config * devc, u_short *word)
{
- unsigned long i, limit = GET_TIME () + 10;
-
- pss_outpw (pss_base + PSS_CONTROL, 0x2000);
-
- for (i = 0; i < 32768 && GET_TIME () < limit; i++)
- pss_inpw (pss_base + PSS_CONTROL);
-
- pss_outpw (pss_base + PSS_CONTROL, 0x0000);
+ int i, val;
+
+ for (i = 0; i < 327680; i++) {
+ val = inb(REG(PSS_STATUS));
+ if (val & PSS_READ_FULL) {
+ *word = inb(REG(PSS_DATA));
+ return 1;
+ }
+ }
- return 1;
+ return 0;
}
-
static int
-pss_download_boot (unsigned char *block, int size)
+pss_download_boot(pss_config * devc, u_char *block, int size, int flags)
{
- int i, limit, val, count;
-
- printk ("PSS: downloading boot code synth.ld... ");
-
- /*_____ Warn DSP software that a boot is coming */
- pss_outpw (pss_base + PSS_DATA, 0x00fe);
+ int i, limit, val, count;
- limit = GET_TIME () + 10;
+ if (flags & CPF_FIRST) {
+ /* _____ Warn DSP software that a boot is coming */
+ outw(REG(PSS_DATA), 0x00fe);
- for (i = 0; i < 32768 && GET_TIME () < limit; i++)
- if (pss_inpw (pss_base + PSS_DATA) == 0x5500)
- break;
+ limit = get_time() + 10;
- pss_outpw (pss_base + PSS_DATA, *block++);
+ for (i = 0; i < 32768 && get_time() < limit; i++)
+ if (inb(REG(PSS_DATA)) == 0x5500)
+ break;
- pss_reset_dsp ();
- printk ("start ");
+ outw(REG(PSS_DATA), *block++);
- count = 1;
- while (1)
- {
- int j;
-
- for (j = 0; j < 327670; j++)
- {
- /*_____ Wait for BG to appear */
- if (pss_inpw (pss_base + PSS_STATUS) & PSS_FLAG3)
- break;
+ pss_reset_dsp(devc);
+ }
+ count = 1;
+ while (1) {
+ int j;
+
+ for (j = 0; j < 327670; j++) {
+ /* _____ Wait for BG to appear */
+ if (inb(REG(PSS_STATUS)) & PSS_FLAG3)
+ break;
+ }
+
+ if (j == 327670) {
+ /* It's ok we timed out when the file was empty */
+ if (count >= size && flags & CPF_LAST)
+ break;
+ else {
+ printf("\nPSS: DownLoad timeout problems, byte %d=%d\n",
+ count, size);
+ return 0;
+ }
+ }
+ /* _____ Send the next byte */
+ outw(REG(PSS_DATA), *block++);
+ count++;
}
- if (j == 327670)
- {
- /* It's ok we timed out when the file was empty */
- if (count >= size)
- break;
- else
- {
- printk ("\nPSS: DownLoad timeout problems, byte %d=%d\n",
- count, size);
- return 0;
- }
+ if (flags & CPF_LAST) {
+ /* _____ Why */
+ outw(REG(PSS_DATA), 0);
+
+ limit = get_time() + 10;
+ for (i = 0; i < 32768 && get_time() < limit; i++)
+ val = inb(REG(PSS_STATUS));
+
+ limit = get_time() + 10;
+ for (i = 0; i < 32768 && get_time() < limit; i++) {
+ val = inb(REG(PSS_STATUS));
+ if (val & 0x4000)
+ break;
+ }
+
+ /* now read the version */
+ for (i = 0; i < 32000; i++) {
+ val = inb(REG(PSS_STATUS));
+ if (val & PSS_READ_FULL)
+ break;
+ }
+ if (i == 32000)
+ return 0;
+
+ val = inb(REG(PSS_DATA));
+ /*
+ * printf("<PSS: microcode version %d.%d loaded>", val/16,
+ * val % 16);
+ */
}
- /*_____ Send the next byte */
- pss_outpw (pss_base + PSS_DATA, *block++);
- count++;
- }
-
- /*_____ Why */
- pss_outpw (pss_base + PSS_DATA, 0);
-
- limit = GET_TIME () + 10;
- for (i = 0; i < 32768 && GET_TIME () < limit; i++)
- val = pss_inpw (pss_base + PSS_STATUS);
-
- printk ("downloaded\n");
-
- limit = GET_TIME () + 10;
- for (i = 0; i < 32768 && GET_TIME () < limit; i++)
- {
- val = pss_inpw (pss_base + PSS_STATUS);
- if (val & 0x4000)
- break;
- }
-
- /* now read the version */
- for (i = 0; i < 32000; i++)
- {
- val = pss_inpw (pss_base + PSS_STATUS_REG);
- if (val & PSS_READ_FULL)
- break;
- }
- if (i == 32000)
- return 0;
-
- val = pss_inpw (pss_base + PSS_DATA_REG);
-
- return 1;
+ return 1;
}
+void
+attach_pss(struct address_info * hw_config)
+{
+ u_short id;
+ char tmp[100];
-/* The following is a simple device driver for the pss.
- All I really care about is comunication to and from the pss.
-
- The ability to reinitialize the <synth.ld> This will be
- default when release is choosen.
-
- SNDCTL_PSS_DOWNLOAD:
+ devc->base = hw_config->io_base;
+ devc->irq = hw_config->irq;
+ devc->dma = hw_config->dma;
+ devc->osp = hw_config->osp;
- Okay we need to creat new minor numbers for the
- DOWNLOAD functionality.
+ if (!probe_pss(hw_config))
+ return;
- 14,0x19 -- /dev/pssld where a read operation would output the
- current ld to user space
- where a write operation would effectively
- download a new ld.
+ id = inb(REG(PSS_ID)) & 0x00ff;
- 14,0x09 -- /dev/psecho would open up a comunication path to the
- esc614 asic. Given the ability to send
- messages to the asic and recive messages too.
+ /*
+ * Disable all emulations. Will be enabled later (if required).
+ */
+ outw(REG(CONF_PSS), 0x0000);
+ outw(REG(CONF_WSS), 0x0000);
+ outw(REG(CONF_SB), 0x0000);
+ outw(REG(CONF_MIDI), 0x0000);
+ outw(REG(CONF_CDROM), 0x0000);
+
+#if YOU_REALLY_WANT_TO_ALLOCATE_THESE_RESOURCES
+ if (0) {
+ printf("pss.c: Can't allocate DMA channel\n");
+ return;
+ }
+ if (!set_irq(devc, CONF_PSS, devc->irq)) {
+ printf("PSS: IRQ error\n");
+ return;
+ }
+ if (!set_dma(devc, CONF_PSS, devc->dma)) {
+ printf("PSS: DRQ error\n");
+ return;
+ }
+#endif
- All messages would get read and written in the
- same manner. It would be up to the application
- and the ld to maintain a relationship
- of what the messages mean.
-
- for this device we need to implement select. */
-#define CODE_BUFFER_LEN (64*1024)
-static char *code_buffer;
-static int code_length;
+ pss_initialized = 1;
+ sprintf(tmp, "ECHO-PSS Rev. %d", id);
+ conf_printf(tmp, hw_config);
-static int lock_pss = 0;
+ return;
+}
int
-pss_open (int dev, struct fileinfo *file)
+probe_pss_mpu(struct address_info * hw_config)
{
- int mode;
-
- DEB (printk ("pss_open\n"));
-
- if (pss_ok == 0)
- return RET_ERROR (EIO);
+ int timeout;
- if (lock_pss)
- return 0;
+ if (!pss_initialized)
+ return 0;
- lock_pss = 1;
+ if (0) {
+ printf("PSS: MPU I/O port conflict\n");
+ return 0;
+ }
+ if (!set_io_base(devc, CONF_MIDI, hw_config->io_base)) {
+ printf("PSS: MIDI base error.\n");
+ return 0;
+ }
+ if (!set_irq(devc, CONF_MIDI, hw_config->irq)) {
+ printf("PSS: MIDI IRQ error.\n");
+ return 0;
+ }
+ if (!pss_synthLen) {
+ printf("PSS: Can't enable MPU. MIDI synth microcode not available.\n");
+ return 0;
+ }
+ if (!pss_download_boot(devc, pss_synth, pss_synthLen, CPF_FIRST | CPF_LAST)) {
+ printf("PSS: Unable to load MIDI synth microcode to DSP.\n");
+ return 0;
+ }
+ /*
+ * Finally wait until the DSP algorithm has initialized itself and
+ * deactivates receive interrupt.
+ */
- dev = dev >> 4;
- mode = file->mode & O_ACCMODE;
- if (mode == O_WRONLY)
- {
- printk ("pss-open for WRONLY\n");
- code_length = 0;
- }
+ for (timeout = 900000; timeout > 0; timeout--) {
+ if ((inb(hw_config->io_base + 1) & 0x80) == 0) /* Input data avail */
+ inb(hw_config->io_base); /* Discard it */
+ else
+ break; /* No more input */
+ }
- RESET_WAIT_QUEUE (pss_sleeper, pss_sleep_flag);
- return 1;
+#if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI)
+ return probe_mpu401(hw_config);
+#else
+ return 0
+#endif
}
-void
-pss_release (int dev, struct fileinfo *file)
+static int
+pss_coproc_open(void *dev_info, int sub_device)
{
- int mode;
-
- DEB (printk ("pss_release\n"));
- if (pss_ok == 0)
- return RET_ERROR (EIO);
-
- dev = dev >> 4;
- mode = file->mode & O_ACCMODE;
- if (mode == O_WRONLY && code_length > 0)
- {
-#ifdef linux
- /* This just allows interrupts while the conversion is running */
- __asm__ ("sti");
-#endif
- if (!pss_download_boot (code_buffer, code_length))
- {
- pss_reattach ();
+ switch (sub_device) {
+ case COPR_MIDI:
+
+ if (pss_synthLen == 0) {
+ printf("PSS: MIDI synth microcode not available.\n");
+ return -(EIO);
+ }
+ if (nonstandard_microcode)
+ if (!pss_download_boot(devc, pss_synth, pss_synthLen, CPF_FIRST | CPF_LAST)) {
+ printf("PSS: Unable to load MIDI synth microcode to DSP.\n");
+ return -(EIO);
+ }
+ nonstandard_microcode = 0;
+ break;
+
+ default:;
}
- }
- lock_pss = 0;
+ return 0;
}
-int
-pss_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
+static void
+pss_coproc_close(void *dev_info, int sub_device)
{
- int c, p;
-
- DEB (printk ("pss_read\n"));
- if (pss_ok == 0)
- return RET_ERROR (EIO);
-
- dev = dev >> 4;
- p = 0;
- c = count;
-
- return count - c;
+ return;
}
-int
-pss_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
+static void
+pss_coproc_reset(void *dev_info)
{
- DEB (printk ("pss_write\n"));
- if (pss_ok == 0)
- return RET_ERROR (EIO);
- dev = dev >> 4;
-
- if (count) /* Flush output */
- {
- COPY_FROM_USER (&code_buffer[code_length], buf, 0, count);
- code_length += count;
- }
- return count;
+ if (pss_synthLen)
+ if (!pss_download_boot(devc, pss_synth, pss_synthLen, CPF_FIRST | CPF_LAST)) {
+ printf("PSS: Unable to load MIDI synth microcode to DSP.\n");
+ }
+ nonstandard_microcode = 0;
}
-
-int
-pss_ioctl (int dev, struct fileinfo *file,
- unsigned int cmd, unsigned int arg)
+static int
+download_boot_block(void *dev_info, copr_buffer * buf)
{
- DEB (printk ("pss_ioctl dev=%d cmd=%x\n", dev, cmd));
- if (pss_ok == 0)
- return RET_ERROR (EIO);
-
- dev = dev >> 4;
-
- switch (cmd)
- {
- case SNDCTL_PSS_RESET:
- pss_reattach ();
- return 1;
-
- case SNDCTL_PSS_SETUP_REGISTERS:
- pss_configure_registers_to_look_like_sb ();
- return 1;
+ if (buf->len <= 0 || buf->len > sizeof(buf->data))
+ return -(EINVAL);
- case SNDCTL_PSS_SPEAKER:
- {
- struct pss_speaker params;
- COPY_FROM_USER (&params, (char *) arg, 0, sizeof (struct pss_speaker));
+ if (!pss_download_boot(devc, buf->data, buf->len, buf->flags)) {
+ printf("PSS: Unable to load microcode block to DSP.\n");
+ return -(EIO);
+ }
+ nonstandard_microcode = 1; /* The MIDI microcode has been
+ * overwritten */
- pss_setspeaker (&params);
return 0;
- }
- default:
- return RET_ERROR (EIO);
- }
}
-/* This is going to be used to implement
- waiting on messages sent from the DSP and to the
- DSP when comunication is used via the pss directly.
+static int
+pss_coproc_ioctl(void *dev_info, u_int cmd, ioctl_arg arg, int local)
+{
+ /* printf("PSS coproc ioctl %x %x %d\n", cmd, arg, local); */
+
+ switch (cmd) {
+ case SNDCTL_COPR_RESET:
+ pss_coproc_reset(dev_info);
+ return 0;
+ break;
+
+ case SNDCTL_COPR_LOAD:
+ {
+ copr_buffer *buf;
+ int err;
+
+ buf = (copr_buffer *) malloc(sizeof(copr_buffer), M_TEMP, M_WAITOK);
+ if (buf == NULL)
+ return -(ENOSPC);
+
+ bcopy(&(((char *) arg)[0]), (char *) buf, sizeof(*buf));
+ err = download_boot_block(dev_info, buf);
+ free(buf, M_TEMP);
+ return err;
+ }
+ break;
+
+ case SNDCTL_COPR_RDATA:
+ {
+ copr_debug_buf buf;
+ u_long flags;
+ u_short tmp;
+
+ bcopy(&(((char *) arg)[0]), (char *) &buf, sizeof(buf));
+
+ flags = splhigh();
+ if (!pss_put_dspword(devc, 0x00d0)) {
+ splx(flags);
+ return -(EIO);
+ }
+ if (!pss_put_dspword(devc, (u_short) (buf.parm1 & 0xffff))) {
+ splx(flags);
+ return -(EIO);
+ }
+ if (!pss_get_dspword(devc, &tmp)) {
+ splx(flags);
+ return -(EIO);
+ }
+ buf.parm1 = tmp;
+ splx(flags);
+
+ bcopy(&buf, &(((char *) arg)[0]), sizeof(buf));
+ return 0;
+ }
+ break;
+
+ case SNDCTL_COPR_WDATA:
+ {
+ copr_debug_buf buf;
+ u_long flags;
+ u_short tmp;
+
+ bcopy(&(((char *) arg)[0]), (char *) &buf, sizeof(buf));
+
+ flags = splhigh();
+ if (!pss_put_dspword(devc, 0x00d1)) {
+ splx(flags);
+ return -(EIO);
+ }
+ if (!pss_put_dspword(devc, (u_short) (buf.parm1 & 0xffff))) {
+ splx(flags);
+ return -(EIO);
+ }
+ tmp = (u_int) buf.parm2 & 0xffff;
+ if (!pss_put_dspword(devc, tmp)) {
+ splx(flags);
+ return -(EIO);
+ }
+ splx(flags);
+ return 0;
+ }
+ break;
+
+ case SNDCTL_COPR_WCODE:
+ {
+ copr_debug_buf buf;
+ u_long flags;
+ u_short tmp;
+
+ bcopy(&(((char *) arg)[0]), (char *) &buf, sizeof(buf));
+
+ flags = splhigh();
+ if (!pss_put_dspword(devc, 0x00d3)) {
+ splx(flags);
+ return -(EIO);
+ }
+ if (!pss_put_dspword(devc, (u_short) (buf.parm1 & 0xffff))) {
+ splx(flags);
+ return -(EIO);
+ }
+ tmp = ((u_int) buf.parm2 >> 8) & 0xffff;
+ if (!pss_put_dspword(devc, tmp)) {
+ splx(flags);
+ return -(EIO);
+ }
+ tmp = (u_int) buf.parm2 & 0x00ff;
+ if (!pss_put_dspword(devc, tmp)) {
+ splx(flags);
+ return -(EIO);
+ }
+ splx(flags);
+ return 0;
+ }
+ break;
+
+ case SNDCTL_COPR_RCODE:
+ {
+ copr_debug_buf buf;
+ u_long flags;
+ u_short tmp;
+
+ bcopy(&(((char *) arg)[0]), (char *) &buf, sizeof(buf));
+
+ flags = splhigh();
+ if (!pss_put_dspword(devc, 0x00d2)) {
+ splx(flags);
+ return -(EIO);
+ }
+ if (!pss_put_dspword(devc, (u_short) (buf.parm1 & 0xffff))) {
+ splx(flags);
+ return -(EIO);
+ }
+ if (!pss_get_dspword(devc, &tmp)) { /* Read msb */
+ splx(flags);
+ return -(EIO);
+ }
+ buf.parm1 = tmp << 8;
+
+ if (!pss_get_dspword(devc, &tmp)) { /* Read lsb */
+ splx(flags);
+ return -(EIO);
+ }
+ buf.parm1 |= tmp & 0x00ff;
+
+ splx(flags);
+
+ bcopy(&buf, &(((char *) arg)[0]), sizeof(buf));
+ return 0;
+ }
+ break;
+
+ default:
+ return -(EINVAL);
+ }
- We need to find out if the pss can generate a diffrent
- interupt other than the one it has been setup for.
+ return -(EINVAL);
+}
- This way we can carry on a conversation with the pss
- on a seprate chanel. This would be usefull for debugging. */
+static coproc_operations pss_coproc_operations =
+{
+ "ADSP-2115",
+ pss_coproc_open,
+ pss_coproc_close,
+ pss_coproc_ioctl,
+ pss_coproc_reset,
+ &pss_data
+};
-pss_select (int dev, struct fileinfo * file, int sel_type, select_table * wait)
+void
+attach_pss_mpu(struct address_info * hw_config)
{
- return 0;
- if (pss_ok == 0)
- return RET_ERROR (EIO);
+ int prev_devs;
+
+#if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI)
+ prev_devs = num_midis;
+ attach_mpu401(hw_config);
- dev = dev >> 4;
+ if (num_midis == (prev_devs + 1)) /* The MPU driver installed
+ * itself */
+ midi_devs[prev_devs]->coproc = &pss_coproc_operations;
+#endif
+}
- switch (sel_type)
- {
- case SEL_IN:
- select_wait (&pss_sleeper, wait);
- return 0;
- break;
+int
+probe_pss_mss(struct address_info * hw_config)
+{
+ int timeout;
- case SEL_OUT:
- select_wait (&pss_sleeper, wait);
- return 0;
- break;
+ if (!pss_initialized)
+ return 0;
- case SEL_EX:
- return 0;
- }
+ if (0) {
+ printf("PSS: WSS I/O port conflict\n");
+ return 0;
+ }
+ if (!set_io_base(devc, CONF_WSS, hw_config->io_base)) {
+ printf("PSS: WSS base error.\n");
+ return 0;
+ }
+ if (!set_irq(devc, CONF_WSS, hw_config->irq)) {
+ printf("PSS: WSS IRQ error.\n");
+ return 0;
+ }
+ if (!set_dma(devc, CONF_WSS, hw_config->dma)) {
+ printf("PSS: WSS DRQ error\n");
+ return 0;
+ }
+ /*
+ * For some reason the card returns 0xff in the WSS status register
+ * immediately after boot. Propably MIDI+SB emulation algorithm
+ * downloaded to the ADSP2115 spends some time initializing the card.
+ * Let's try to wait until it finishes this task.
+ */
+ for (timeout = 0;
+ timeout < 100000 && (inb(hw_config->io_base + 3) & 0x3f) != 0x04;
+ timeout++);
- return 0;
+ return probe_mss(hw_config);
}
-long
-pss_init (long mem_start)
+void
+attach_pss_mss(struct address_info * hw_config)
{
- DEB (printk ("pss_init\n"));
- if (pss_ok)
- {
- code_buffer = mem_start;
- mem_start += CODE_BUFFER_LEN;
- }
- return mem_start;
+ int prev_devs;
+ long ret;
+
+ prev_devs = num_audiodevs;
+ attach_mss(hw_config);
+
+ /* Check if The MSS driver installed itself */
+ if (num_audiodevs == (prev_devs + 1))
+ audio_devs[prev_devs]->coproc = &pss_coproc_operations;
}
#endif
diff --git a/sys/i386/isa/sound/sb16_dsp.c b/sys/i386/isa/sound/sb16_dsp.c
index e3078bca7bf7..1e94e1529026 100644
--- a/sys/i386/isa/sound/sb16_dsp.c
+++ b/sys/i386/isa/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,543 +26,486 @@
* 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
- */
-#include "sound_config.h"
+#include <i386/isa/sound/sound_config.h>
#include "sb.h"
-#include "sb_mixer.h"
+#include <i386/isa/sound/sb_mixer.h>
+#include <i386/isa/sound/sbcard.h>
-#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_SB16) && !defined(EXCLUDE_SB) && !defined(EXCLUDE_AUDIO) && !defined(EXCLUDE_SBPRO)
+#if defined(CONFIG_SB16) && (NSB > 0) && defined(CONFIG_AUDIO) && defined(CONFIG_SBPRO)
-extern int sbc_base;
-
-static int sb16_dsp_ok = 0;/*
+extern sound_os_info *sb_osp;
+extern int sbc_base;
- * * * * Set to 1 after successful *
- * * initialization */
+static int sb16_dsp_ok = 0;
static int dsp_16bit = 0;
static int dsp_stereo = 0;
-static int dsp_current_speed = 8000; /*
-
-
- * * * * DSP_DEFAULT_SPEED; */
+static int dsp_current_speed = 8000;
static int dsp_busy = 0;
static int dma16, dma8;
-static unsigned long dsp_count = 0;
-
-static int irq_mode = IMODE_NONE; /*
-
+static int trigger_bits = 0;
+static u_long dsp_count = 0;
- * * * * IMODE_INPUT, IMODE_OUTPUT
- * or * * IMODE_NONE */
+static int irq_mode = IMODE_NONE;
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, u_long buf, int count, int intrflag, int dma_restart);
+static void sb16_dsp_start_input(int dev, u_long buf, int count, int intrflag, int dma_restart);
+static int sb16_dsp_ioctl(int dev, u_int cmd, ioctl_arg 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 void sb16_dsp_trigger(int dev, int bits);
+static int dsp_set_speed(int);
+static int dsp_set_stereo(int);
+static void dsp_cleanup(void);
static struct audio_operations sb16_dsp_operations =
{
- "SoundBlaster 16",
- DMA_AUTOMODE,
- AFMT_U8 | AFMT_S16_LE,
- NULL,
- sb16_dsp_open,
- sb16_dsp_close,
- sb16_dsp_output_block,
- sb16_dsp_start_input,
- sb16_dsp_ioctl,
- sb16_dsp_prepare_for_input,
- sb16_dsp_prepare_for_output,
- sb16_dsp_reset,
- sb16_dsp_halt,
- NULL,
- NULL
+ "SoundBlaster 16",
+ DMA_AUTOMODE,
+ AFMT_U8 | AFMT_S16_LE,
+ NULL,
+ sb16_dsp_open,
+ sb16_dsp_close,
+ sb16_dsp_output_block,
+ sb16_dsp_start_input,
+ sb16_dsp_ioctl,
+ sb16_dsp_prepare_for_input,
+ sb16_dsp_prepare_for_output,
+ sb16_dsp_reset,
+ sb16_dsp_halt,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ sb16_dsp_trigger
};
static int
-sb_dsp_command01 (unsigned char val)
+sb_dsp_command01(u_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)
+ printf("SB16 sb_dsp_command01 Timeout\n");
+ return sb_dsp_command(val);
}
static int
-dsp_set_speed (int mode)
+dsp_set_speed(int mode)
{
- DEB (printk ("dsp_set_speed(%d)\n", mode));
- if (mode)
- {
- if (mode < 5000)
- mode = 5000;
- if (mode > 44100)
- mode = 44100;
- dsp_current_speed = mode;
+ DEB(printf("dsp_set_speed(%d)\n", mode));
+ if (mode) {
+ RANGE (mode, 5000, 44100);
+ dsp_current_speed = mode;
}
- return mode;
+ return mode;
}
static int
-dsp_set_stereo (int mode)
+dsp_set_stereo(int mode)
{
- DEB (printk ("dsp_set_stereo(%d)\n", mode));
-
- dsp_stereo = mode;
-
- return mode;
+ DEB(printf("dsp_set_stereo(%d)\n", mode));
+ dsp_stereo = mode;
+ return mode;
}
static int
-dsp_set_bits (int arg)
+dsp_set_bits(int arg)
{
- DEB (printk ("dsp_set_bits(%d)\n", arg));
+ DEB(printf("dsp_set_bits(%d)\n", arg));
- if (arg)
- switch (arg)
- {
- case 8:
- dsp_16bit = 0;
- break;
- case 16:
- dsp_16bit = 1;
- break;
- default:
- dsp_16bit = 0;
- }
- return dsp_16bit ? 16 : 8;
+ if (arg)
+ dsp_16bit = (arg == 16) ? 1 : 0 ;
+ 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, u_int cmd, ioctl_arg arg, int local)
{
- switch (cmd)
- {
+ switch (cmd) {
case SOUND_PCM_WRITE_RATE:
- if (local)
- return dsp_set_speed (arg);
- return IOCTL_OUT (arg, dsp_set_speed (IOCTL_IN (arg)));
+ if (local)
+ return dsp_set_speed((int) arg);
+ return *(int *) arg = dsp_set_speed((*(int *) arg));
case SOUND_PCM_READ_RATE:
- if (local)
- return dsp_current_speed;
- return IOCTL_OUT (arg, dsp_current_speed);
+ if (local)
+ return dsp_current_speed;
+ return *(int *) 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)));
+ if (local)
+ return dsp_set_stereo((int) arg);
+ return *(int *) arg = dsp_set_stereo((*(int *) 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);
+ if (local)
+ return dsp_set_stereo((int) arg - 1) + 1;
+ return *(int *) arg = dsp_set_stereo((*(int *) arg) - 1) + 1;
case SOUND_PCM_READ_CHANNELS:
- if (local)
- return dsp_stereo + 1;
- return IOCTL_OUT (arg, dsp_stereo + 1);
+ if (local)
+ return dsp_stereo + 1;
+ return *(int *) arg = dsp_stereo + 1;
case SNDCTL_DSP_SETFMT:
- if (local)
- return dsp_set_bits (arg);
- return IOCTL_OUT (arg, dsp_set_bits (IOCTL_IN (arg)));
+ if (local)
+ return dsp_set_bits((int) arg);
+ return *(int *) arg = dsp_set_bits((*(int *) 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));
+ if (local)
+ return dsp_16bit ? 16 : 8;
+ return *(int *) arg = dsp_16bit ? 16 : 8;
+
+ case SOUND_PCM_WRITE_FILTER: /* NOT YET IMPLEMENTED */
+ if ((*(int *) arg) > 1)
+ return *(int *) arg = -(EINVAL);
+
+ case FIOASYNC:
+ if (local)
+ return 1;
+ return *(int *) arg = 1;
+
+ case FIONBIO:
+ if (local)
+ return 1;
+ return *(int *) arg = 1;
+
default:
- return RET_ERROR (EINVAL);
+ return -(EINVAL);
}
- return RET_ERROR (EINVAL);
+ return -(EINVAL);
}
static int
-sb16_dsp_open (int dev, int mode)
+sb16_dsp_open(int dev, int mode)
{
- int retval;
-
- DEB (printk ("sb16_dsp_open()\n"));
- if (!sb16_dsp_ok)
- {
- printk ("SB16 Error: SoundBlaster board not installed\n");
- return RET_ERROR (ENXIO);
- }
-
- if (intr_active)
- return RET_ERROR (EBUSY);
-
- retval = sb_get_irq ();
- if (retval < 0)
- return retval;
+ int retval;
- sb_reset_dsp ();
-
- if (ALLOC_DMA_CHN (dma8))
- {
- printk ("SB16: Unable to grab DMA%d\n", dma8);
- sb_free_irq ();
- return RET_ERROR (EBUSY);
+ DEB(printf("sb16_dsp_open()\n"));
+ if (!sb16_dsp_ok) {
+ printf("SB16 Error: SoundBlaster board not installed\n");
+ return -(ENXIO);
}
+ if (intr_active)
+ return -(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);
- }
+ sb_reset_dsp();
- irq_mode = IMODE_NONE;
- dsp_busy = 1;
+ irq_mode = IMODE_NONE;
+ dsp_busy = 1;
+ trigger_bits = 0;
- return 0;
+ return 0;
}
static void
-sb16_dsp_close (int dev)
+sb16_dsp_close(int dev)
{
- unsigned long flags;
+ u_long flags;
- DEB (printk ("sb16_dsp_close()\n"));
- sb_dsp_command01 (0xd9);
- sb_dsp_command01 (0xd5);
+ DEB(printf("sb16_dsp_close()\n"));
+ sb_dsp_command01(0xd9);
+ sb_dsp_command01(0xd5);
- DISABLE_INTR (flags);
- RELEASE_DMA_CHN (dma8);
+ flags = splhigh();
- if (dma16 != dma8)
- RELEASE_DMA_CHN (dma16);
- sb_free_irq ();
- dsp_cleanup ();
- dsp_busy = 0;
- RESTORE_INTR (flags);
+ audio_devs[dev]->dmachan1 = dma8;
+
+ dsp_cleanup();
+ dsp_busy = 0;
+ splx(flags);
}
static void
-sb16_dsp_output_block (int dev, unsigned long buf, int count, int intrflag, int dma_restart)
+sb16_dsp_output_block(int dev, u_long buf, int count, int intrflag, int dma_restart)
{
- unsigned long flags, cnt;
-
- cnt = count;
- if (dsp_16bit)
- cnt >>= 1;
- cnt--;
-
-#ifdef DEB_DMARES
- printk ("output_block: %x %d %d\n", buf, count, intrflag);
- if (intrflag)
- {
- int pos, chan = audio_devs[dev]->dmachan;
-
- 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 (audio_devs[dev]->flags & DMA_AUTOMODE &&
- intrflag &&
- cnt == dsp_count)
- {
- irq_mode = IMODE_OUTPUT;
- intr_active = 1;
- return; /*
- * Auto mode on. No need to react
- */
+ u_long flags, cnt;
+
+ cnt = count;
+ if (dsp_16bit)
+ cnt >>= 1;
+ cnt--;
+ if (audio_devs[dev]->flags & DMA_AUTOMODE && intrflag && cnt==dsp_count) {
+ irq_mode = IMODE_OUTPUT;
+ intr_active = 1;
+ return; /* Auto mode on. No need to react */
}
- DISABLE_INTR (flags);
+ flags = splhigh();
+
+ if (dma_restart) {
- 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, 1);
}
- 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));
-
- dsp_count = cnt;
- irq_mode = IMODE_OUTPUT;
- intr_active = 1;
- RESTORE_INTR (flags);
+
+
+ sb_dsp_command(0x41);
+ sb_dsp_command((u_char) ((dsp_current_speed >> 8) & 0xff));
+ sb_dsp_command((u_char) (dsp_current_speed & 0xff));
+ sb_dsp_command((u_char) (dsp_16bit ? 0xb6 : 0xc6));
+ dsp_count = cnt;
+ sb_dsp_command((u_char) ((dsp_stereo ? 0x20 : 0) +
+ (dsp_16bit ? 0x10 : 0)));
+ sb_dsp_command((u_char) (cnt & 0xff));
+ sb_dsp_command((u_char) (cnt >> 8));
+
+ irq_mode = IMODE_OUTPUT;
+ intr_active = 1;
+ splx(flags);
}
static void
-sb16_dsp_start_input (int dev, unsigned long buf, int count, int intrflag, int dma_restart)
+sb16_dsp_start_input(int dev, u_long buf, int count, int intrflag, int dma_restart)
{
- unsigned long flags, cnt;
-
- cnt = count;
- if (dsp_16bit)
- cnt >>= 1;
- cnt--;
-
-#ifdef DEB_DMARES
- printk ("start_input: %x %d %d\n", buf, count, intrflag);
- if (intrflag)
- {
- int pos, chan = audio_devs[dev]->dmachan;
-
- 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 (audio_devs[dev]->flags & DMA_AUTOMODE &&
- intrflag &&
- cnt == dsp_count)
- {
- irq_mode = IMODE_INPUT;
- intr_active = 1;
- return; /*
- * Auto mode on. No need to react
- */
- }
- DISABLE_INTR (flags);
+ u_long flags, cnt;
+
+ cnt = count;
+ if (dsp_16bit)
+ cnt >>= 1;
+ cnt--;
- if (dma_restart)
- {
- sb_reset_dsp ();
- DMAbuf_start_dma (dev, buf, count, DMA_MODE_READ);
+ if (audio_devs[dev]->flags & DMA_AUTOMODE && intrflag && cnt == dsp_count) {
+ irq_mode = IMODE_INPUT;
+ intr_active = 1;
+ return; /* Auto mode on. No need to react */
}
+ flags = splhigh();
- 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));
-
- dsp_count = cnt;
- irq_mode = IMODE_INPUT;
- intr_active = 1;
- RESTORE_INTR (flags);
+ if (dma_restart) {
+ sb_reset_dsp();
+ DMAbuf_start_dma(dev, buf, count, 0);
+ }
+ sb_dsp_command(0x42);
+ sb_dsp_command((u_char) ((dsp_current_speed >> 8) & 0xff));
+ sb_dsp_command((u_char) (dsp_current_speed & 0xff));
+ sb_dsp_command((u_char) (dsp_16bit ? 0xbe : 0xce));
+ dsp_count = cnt;
+ sb_dsp_command((u_char) ((dsp_stereo ? 0x20 : 0) +
+ (dsp_16bit ? 0x10 : 0)));
+ sb_dsp_command01((u_char) (cnt & 0xff));
+ sb_dsp_command((u_char) (cnt >> 8));
+
+ irq_mode = IMODE_INPUT;
+ intr_active = 1;
+ splx(flags);
}
static int
-sb16_dsp_prepare_for_input (int dev, int bsize, int bcount)
+sb16_dsp_prepare_for_input(int dev, int bsize, int bcount)
{
- audio_devs[my_dev]->dmachan = dsp_16bit ? dma16 : dma8;
- dsp_count = 0;
- dsp_cleanup ();
- return 0;
+ audio_devs[my_dev]->dmachan2 = dsp_16bit ? dma16 : dma8;
+ dsp_count = 0;
+ dsp_cleanup();
+ if (dsp_16bit)
+ sb_dsp_command(0xd5); /* Halt DMA until trigger() is called */
+ else
+ sb_dsp_command(0xd0); /* Halt DMA until trigger() is called */
+
+ trigger_bits = 0;
+ return 0;
}
static int
-sb16_dsp_prepare_for_output (int dev, int bsize, int bcount)
+sb16_dsp_prepare_for_output(int dev, int bsize, int bcount)
{
- audio_devs[my_dev]->dmachan = dsp_16bit ? dma16 : dma8;
- dsp_count = 0;
- dsp_cleanup ();
- return 0;
+ int fudge = dsp_16bit ? dma16 : dma8;
+
+ isa_dma_release( audio_devs[my_dev]->dmachan1 );
+ isa_dma_acquire(fudge);
+
+ audio_devs[my_dev]->dmachan1 = fudge;
+ dsp_count = 0;
+ dsp_cleanup();
+ if (dsp_16bit)
+ sb_dsp_command(0xd5); /* Halt DMA until trigger() is called */
+ else
+ sb_dsp_command(0xd0); /* Halt DMA until trigger() is called */
+
+ trigger_bits = 0;
+ return 0;
+}
+
+static void
+sb16_dsp_trigger(int dev, int bits)
+{
+ if (bits != 0)
+ bits = 1;
+
+ if (bits == trigger_bits) /* No change */
+ return;
+
+ trigger_bits = bits;
+
+ if (!bits)
+ sb_dsp_command(0xd0); /* Halt DMA */
+ else if (bits & irq_mode)
+ sb_dsp_command(0xd4); /* Continue DMA */
}
static void
-dsp_cleanup (void)
+dsp_cleanup(void)
{
- irq_mode = IMODE_NONE;
- intr_active = 0;
+ irq_mode = IMODE_NONE;
+ intr_active = 0;
}
static void
-sb16_dsp_reset (int dev)
+sb16_dsp_reset(int dev)
{
- unsigned long flags;
+ u_long flags;
- DISABLE_INTR (flags);
+ flags = splhigh();
- sb_reset_dsp ();
- dsp_cleanup ();
+ sb_reset_dsp();
+ dsp_cleanup();
- RESTORE_INTR (flags);
+ splx(flags);
}
static void
-sb16_dsp_halt (int dev)
+sb16_dsp_halt(int dev)
{
- if (dsp_16bit)
- {
- sb_dsp_command01 (0xd9);
- sb_dsp_command01 (0xd5);
- }
- else
- {
- sb_dsp_command01 (0xda);
- sb_dsp_command01 (0xd0);
+
+ if (dsp_16bit) {
+ sb_dsp_command01(0xd9);
+ sb_dsp_command01(0xd5);
+ } else {
+ sb_dsp_command01(0xda);
+ sb_dsp_command01(0xd0);
}
+
+
}
static void
-set_irq_hw (int level)
+set_irq_hw(int level)
{
- int ival;
+ int ival;
- switch (level)
- {
+ switch (level) {
case 5:
- ival = 2;
- break;
+ ival = 2;
+ break;
case 7:
- ival = 4;
- break;
+ ival = 4;
+ break;
case 9:
- ival = 1;
- break;
+ ival = 1;
+ break;
case 10:
- ival = 8;
- break;
+ ival = 8;
+ break;
default:
- printk ("SB16_IRQ_LEVEL %d does not exist\n", level);
- return;
+ printf("SB16_IRQ_LEVEL %d does not exist\n", level);
+ return;
}
- sb_setmixer (IRQ_NR, ival);
+ sb_setmixer(IRQ_NR, ival);
}
-long
-sb16_dsp_init (long mem_start, struct address_info *hw_config)
+void
+sb16_dsp_init(struct address_info * hw_config)
{
- extern int sbc_major, sbc_minor;
+ if (sbc_major < 4)
+ return; /* Not a SB16 */
- if (sbc_major < 4)
- return mem_start; /* Not a SB16 */
+ sprintf(sb16_dsp_operations.name, "SoundBlaster 16 %d.%d",
+ sbc_major, sbc_minor);
-#ifndef SCO
- sprintf (sb16_dsp_operations.name, "SoundBlaster 16 %d.%d", sbc_major, sbc_minor);
-#endif
+ conf_printf(sb16_dsp_operations.name, hw_config);
- printk (" <%s>", sb16_dsp_operations.name);
+ if (num_audiodevs < MAX_AUDIO_DEV) {
+ audio_devs[my_dev = num_audiodevs++] = &sb16_dsp_operations;
+ audio_devs[my_dev]->dmachan1 = dma8;
+ audio_devs[my_dev]->buffsize = DSP_BUFFSIZE;
- if (num_audiodevs < MAX_AUDIO_DEV)
- {
- audio_devs[my_dev = num_audiodevs++] = &sb16_dsp_operations;
- audio_devs[my_dev]->dmachan = hw_config->dma;
- audio_devs[my_dev]->buffcount = 1;
- audio_devs[my_dev]->buffsize = DSP_BUFFSIZE;
- }
- else
- printk ("SB: Too many DSP devices available\n");
- sb16_dsp_ok = 1;
- return mem_start;
+ } else
+ printf("SB: Too many DSP devices available\n");
+ sb16_dsp_ok = 1;
+ return;
}
int
-sb16_dsp_detect (struct address_info *hw_config)
+sb16_dsp_detect(struct address_info * hw_config)
{
- struct address_info *sb_config;
- extern int sbc_major;
+ struct address_info *sb_config;
- if (sb16_dsp_ok)
- return 1; /* Can't drive two cards */
+ if (sb16_dsp_ok)
+ return 1; /* Can't drive two cards */
- if (!(sb_config = sound_getconf (SNDCARD_SB)))
- {
- printk ("SB16 Error: Plain SB not configured\n");
- return 0;
+ if (!(sb_config = sound_getconf(SNDCARD_SB))) {
+ printf("SB16 Error: Plain SB not configured\n");
+ return 0;
}
+ /*
+ * sb_setmixer(OPSW,0xf); if(sb_getmixer(OPSW)!=0xf) return 0;
+ */
- /*
- * sb_setmixer(OPSW,0xf); if(sb_getmixer(OPSW)!=0xf) return 0;
- */
-
- if (!sb_reset_dsp ())
- return 0;
-
- if (sbc_major < 4) /* Set by the plain SB driver */
- return 0; /* Not a SB16 */
-
- 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);
+ if (!sb_reset_dsp())
return 0;
- }
- dma16 = hw_config->dma;
- dma8 = sb_config->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", sb_config->irq, hw_config->dma));
-
- /*
- * dsp_showmessage(0xe3,99);
- */
- sb16_dsp_ok = 1;
- return 1;
+ if (sbc_major < 4) /* Set by the plain SB driver */
+ return 0; /* Not a SB16 */
+
+ if (hw_config->dma < 4)
+ if (hw_config->dma != sb_config->dma) {
+ printf("SB16 Error: Invalid DMA channel %d/%d\n",
+ sb_config->dma, hw_config->dma);
+ return 0;
+ }
+ dma16 = hw_config->dma;
+ dma8 = sb_config->dma;
+ /* hw_config->irq = 0; sb_config->irq;
+ hw_config->io_base = sb_config->io_base;
+ */
+ set_irq_hw(sb_config->irq);
+
+ sb_setmixer(DMA_NR, (1 << hw_config->dma) | (1 << sb_config->dma));
+
+ DEB(printf("SoundBlaster 16: IRQ %d DMA %d OK\n",
+ sb_config->irq, hw_config->dma));
+
+ /*
+ * dsp_showmessage(0xe3,99);
+ */
+ sb16_dsp_ok = 1;
+ return 1;
}
void
-sb16_dsp_interrupt (int unused)
+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;
+ int data;
- case IMODE_INPUT:
- intr_active = 0;
- DMAbuf_inputintr (my_dev);
- break;
+ data = inb(DSP_DATA_AVL16); /* Interrupt acknowledge */
- default:
- printk ("SoundBlaster: Unexpected interrupt\n");
- }
-}
+ if (intr_active)
+ switch (irq_mode) {
+ case IMODE_OUTPUT:
+ DMAbuf_outputintr(my_dev, 1);
+ break;
+ case IMODE_INPUT:
+ DMAbuf_inputintr(my_dev);
+ break;
+
+ default:
+ printf("SoundBlaster: Unexpected interrupt\n");
+ }
+}
#endif
diff --git a/sys/i386/isa/sound/sb16_midi.c b/sys/i386/isa/sound/sb16_midi.c
index 7a3fdb1a3be6..e7b508469099 100644
--- a/sys/i386/isa/sound/sb16_midi.c
+++ b/sys/i386/isa/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,14 +24,13 @@
* 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"
+#include <i386/isa/sound/sound_config.h>
+#include <i386/isa/sound/sbcard.h>
-#ifdef CONFIGURE_SOUNDCARD
-
-#if !defined(EXCLUDE_SB) && !defined(EXCLUDE_SB16) && !defined(EXCLUDE_MIDI)
+#if defined(CONFIG_SB) && defined(CONFIG_SB16) && defined(CONFIG_MIDI)
#include "sb.h"
@@ -39,12 +38,14 @@
#define COMDPORT (sb16midi_base+1)
#define STATPORT (sb16midi_base+1)
-#define sb16midi_status() INB(STATPORT)
+extern sound_os_info *sb_osp;
+
+#define sb16midi_status() inb( STATPORT)
#define input_avail() (!(sb16midi_status()&INPUT_AVAIL))
#define output_ready() (!(sb16midi_status()&OUTPUT_READY))
-#define sb16midi_cmd(cmd) OUTB(cmd, COMDPORT)
-#define sb16midi_read() INB(DATAPORT)
-#define sb16midi_write(byte) OUTB(byte, DATAPORT)
+#define sb16midi_cmd(cmd) outb( COMDPORT, cmd)
+#define sb16midi_read() inb( DATAPORT)
+#define sb16midi_write(byte) outb( DATAPORT, byte)
#define OUTPUT_READY 0x40
#define INPUT_AVAIL 0x80
@@ -58,247 +59,241 @@ static int sb16midi_detected = 0;
static int my_dev;
extern int sbc_base;
-static int reset_sb16midi (void);
-static void (*midi_input_intr) (int dev, unsigned char data);
+static int reset_sb16midi(void);
+static void (*midi_input_intr) (int dev, u_char data);
+static volatile u_char input_byte;
static void
-sb16midi_input_loop (void)
+sb16midi_input_loop(void)
{
- while (input_avail ())
- {
- unsigned char c = sb16midi_read ();
-
- if (sb16midi_opened & OPEN_READ)
- midi_input_intr (my_dev, c);
- }
+ while (input_avail()) {
+ u_char c = sb16midi_read();
+
+ if (c == MPU_ACK)
+ input_byte = c;
+ else if (sb16midi_opened & OPEN_READ && midi_input_intr)
+ midi_input_intr(my_dev, c);
+ }
}
void
-sb16midiintr (int unit)
+sb16midiintr(int unit)
{
- if (input_avail ())
- sb16midi_input_loop ();
+ if (input_avail())
+ sb16midi_input_loop();
}
static int
-sb16midi_open (int dev, int mode,
- void (*input) (int dev, unsigned char data),
- void (*output) (int dev)
+sb16midi_open(int dev, int mode,
+ void (*input) (int dev, u_char data),
+ void (*output) (int dev)
)
{
- if (sb16midi_opened)
- {
- return RET_ERROR (EBUSY);
- }
-
- sb16midi_input_loop ();
+ if (sb16midi_opened) {
+ return -(EBUSY);
+ }
+ sb16midi_input_loop();
- midi_input_intr = input;
- sb16midi_opened = mode;
+ midi_input_intr = input;
+ sb16midi_opened = mode;
- return 0;
+ return 0;
}
static void
-sb16midi_close (int dev)
+sb16midi_close(int dev)
{
- sb16midi_opened = 0;
+ sb16midi_opened = 0;
}
static int
-sb16midi_out (int dev, unsigned char midi_byte)
+sb16midi_out(int dev, u_char midi_byte)
{
- int timeout;
- unsigned long flags;
+ int timeout;
+ u_long flags;
- /*
- * Test for input since pending input seems to block the output.
- */
+ /*
+ * Test for input since pending input seems to block the output.
+ */
- DISABLE_INTR (flags);
+ flags = splhigh();
- if (input_avail ())
- sb16midi_input_loop ();
+ if (input_avail())
+ sb16midi_input_loop();
- RESTORE_INTR (flags);
+ splx(flags);
- /*
- * Sometimes it takes about 13000 loops before the output becomes ready
- * (After reset). Normally it takes just about 10 loops.
- */
+ /*
+ * Sometimes it takes about 13000 loops before the output becomes
+ * ready (After reset). Normally it takes just about 10 loops.
+ */
- for (timeout = 30000; timeout > 0 && !output_ready (); timeout--); /*
- * Wait
- */
+ for (timeout = 30000; timeout > 0 && !output_ready(); timeout--); /* Wait */
- if (!output_ready ())
- {
- printk ("MPU-401: Timeout\n");
- return 0;
- }
-
- sb16midi_write (midi_byte);
- return 1;
+ if (!output_ready()) {
+ printf("MPU-401: Timeout\n");
+ return 0;
+ }
+ sb16midi_write(midi_byte);
+ return 1;
}
static int
-sb16midi_start_read (int dev)
+sb16midi_start_read(int dev)
{
- return 0;
+ return 0;
}
static int
-sb16midi_end_read (int dev)
+sb16midi_end_read(int dev)
{
- return 0;
+ return 0;
}
static int
-sb16midi_ioctl (int dev, unsigned cmd, unsigned arg)
+sb16midi_ioctl(int dev, u_int cmd, ioctl_arg arg)
{
- return RET_ERROR (EINVAL);
+ return -(EINVAL);
}
static void
-sb16midi_kick (int dev)
+sb16midi_kick(int dev)
{
}
static int
-sb16midi_buffer_status (int dev)
+sb16midi_buffer_status(int dev)
{
- return 0; /*
- * No data in buffers
- */
+ return 0; /* No data in buffers */
}
#define MIDI_SYNTH_NAME "SoundBlaster 16 Midi"
#define MIDI_SYNTH_CAPS SYNTH_CAP_INPUT
-#include "midi_synth.h"
+#include <i386/isa/sound/midi_synth.h>
static struct midi_operations sb16midi_operations =
{
- {"SoundBlaster 16 Midi", 0, 0, SNDCARD_SB16MIDI},
- &std_midi_synth,
- sb16midi_open,
- sb16midi_close,
- sb16midi_ioctl,
- sb16midi_out,
- sb16midi_start_read,
- sb16midi_end_read,
- sb16midi_kick,
- NULL,
- sb16midi_buffer_status,
- NULL
+ {"SoundBlaster 16 Midi", 0, 0, SNDCARD_SB16MIDI},
+ &std_midi_synth,
+ {0},
+ sb16midi_open,
+ sb16midi_close,
+ sb16midi_ioctl,
+ sb16midi_out,
+ sb16midi_start_read,
+ sb16midi_end_read,
+ sb16midi_kick,
+ NULL,
+ sb16midi_buffer_status,
+ NULL
};
-long
-attach_sb16midi (long mem_start, struct address_info *hw_config)
+void
+attach_sb16midi(struct address_info * hw_config)
{
- int ok, timeout;
- unsigned long flags;
-
- sb16midi_base = hw_config->io_base;
-
- if (!sb16midi_detected)
- return RET_ERROR (EIO);
-
- DISABLE_INTR (flags);
- for (timeout = 30000; timeout < 0 && !output_ready (); timeout--); /*
- * Wait
- */
- sb16midi_cmd (UART_MODE_ON);
-
- ok = 0;
- for (timeout = 50000; timeout > 0 && !ok; timeout--)
- if (input_avail ())
- if (sb16midi_read () == MPU_ACK)
- ok = 1;
-
- RESTORE_INTR (flags);
-
- if (num_midis >= MAX_MIDI_DEV)
- {
- printk ("Sound: Too many midi devices detected\n");
- return mem_start;
- }
-
- printk (" <SoundBlaster MPU-401>");
-
- std_midi_synth.midi_dev = my_dev = num_midis;
- midi_devs[num_midis++] = &sb16midi_operations;
- return mem_start;
+ int ok, timeout;
+ u_long flags;
+
+ sb16midi_base = hw_config->io_base;
+
+ if (!sb16midi_detected)
+ return;
+
+ flags = splhigh();
+ for (timeout = 30000; timeout < 0 && !output_ready(); timeout--); /* Wait */
+ input_byte = 0;
+ sb16midi_cmd(UART_MODE_ON);
+
+ ok = 0;
+ for (timeout = 50000; timeout > 0 && !ok; timeout--)
+ if (input_byte == MPU_ACK)
+ ok = 1;
+ else if (input_avail())
+ if (sb16midi_read() == MPU_ACK)
+ ok = 1;
+
+ splx(flags);
+
+ if (num_midis >= MAX_MIDI_DEV) {
+ printf("Sound: Too many midi devices detected\n");
+ return;
+ }
+
+ conf_printf("SoundBlaster MPU-401", hw_config);
+ std_midi_synth.midi_dev = my_dev = num_midis;
+ midi_devs[num_midis++] = &sb16midi_operations;
+ return;
}
static int
-reset_sb16midi (void)
+reset_sb16midi(void)
{
- unsigned long flags;
- int ok, timeout, n;
+ int ok, timeout, n;
- /*
- * Send the RESET command. Try again if no success at the first time.
- */
+ /*
+ * Send the RESET command. Try again if no success at the first time.
+ */
- ok = 0;
+ if (inb(STATPORT) == 0xff)
+ return 0;
- DISABLE_INTR (flags);
+ ok = 0;
- for (n = 0; n < 2 && !ok; n++)
- {
- for (timeout = 30000; timeout < 0 && !output_ready (); timeout--); /*
- * Wait
- */
- sb16midi_cmd (MPU_RESET); /*
- * Send MPU-401 RESET Command
- */
+ /* flags = splhigh(); */
- /*
- * Wait at least 25 msec. This method is not accurate so let's make the
- * loop bit longer. Cannot sleep since this is called during boot.
- */
+ for (n = 0; n < 2 && !ok; n++) {
+ for (timeout = 30000; timeout < 0 && !output_ready(); timeout--); /* Wait */
+ input_byte = 0;
+ sb16midi_cmd(MPU_RESET); /* Send MPU-401 RESET Command */
- for (timeout = 50000; timeout > 0 && !ok; timeout--)
- if (input_avail ())
- if (sb16midi_read () == MPU_ACK)
- ok = 1;
+ /*
+ * Wait at least 25 msec. This method is not accurate so
+ * let's make the loop bit longer. Cannot sleep since this is
+ * called during boot.
+ */
- }
+ for (timeout = 50000; timeout > 0 && !ok; timeout--)
+ if (input_byte == MPU_ACK) /* Interrupt */
+ ok = 1;
+ else if (input_avail())
+ if (sb16midi_read() == MPU_ACK)
+ ok = 1;
- sb16midi_opened = 0;
- if (ok)
- sb16midi_input_loop (); /*
- * Flush input before enabling interrupts
- */
+ }
- RESTORE_INTR (flags);
+ sb16midi_opened = 0;
+ if (ok)
+ sb16midi_input_loop(); /* Flush input before enabling
+ * interrupts */
- return ok;
+ /* splx(flags); */
+
+ return ok;
}
int
-probe_sb16midi (struct address_info *hw_config)
+probe_sb16midi(struct address_info * hw_config)
{
- int ok = 0;
- int i;
- extern int sbc_major;
+ int ok = 0;
+ struct address_info *sb_config;
- if (sbc_major < 4)
- return 0; /* Not a SB16 */
+ if (sbc_major < 4)
+ return 0; /* Not a SB16 */
- sb16midi_base = hw_config->io_base;
+ if (!(sb_config = sound_getconf(SNDCARD_SB))) {
+ printf("SB16 Error: Plain SB not configured\n");
+ return 0;
+ }
- if (sb_get_irq () < 0)
- return 0;
+ sb16midi_base = hw_config->io_base;
- ok = reset_sb16midi ();
+ ok = reset_sb16midi();
- sb16midi_detected = ok;
- return ok;
+ sb16midi_detected = ok;
+ return ok;
}
#endif
-#endif
diff --git a/sys/i386/isa/sound/sb_card.c b/sys/i386/isa/sound/sb_card.c
index f7588e1ca172..37da6b4a5958 100644
--- a/sys/i386/isa/sound/sb_card.c
+++ b/sys/i386/isa/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,29 +24,44 @@
* 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: Riccardo Facchetti 24 Mar 1995 - Added the Audio Excel DSP 16
+ * initialization routine.
*
+ * Major code cleanup - Luigi Rizzo (luigi@iet.unipi.it) 970711
*/
-#include "sound_config.h"
+#include <i386/isa/sound/sound_config.h>
-#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_SB)
+#if NSB > 0
+#include <i386/isa/sound/sbcard.h>
-long
-attach_sb_card (long mem_start, struct address_info *hw_config)
+void
+attach_sb_card(struct address_info * hw_config)
{
-#if !defined(EXCLUDE_AUDIO) || !defined(EXCLUDE_MIDI)
- if (!sb_dsp_detect (hw_config))
- return mem_start;
- mem_start = sb_dsp_init (mem_start, hw_config);
+#if defined(CONFIG_AUDIO) || defined(CONFIG_MIDI)
+
+#if 0
+ /* why do a detect during the attach ? XXX */
+ if (!sb_dsp_detect(hw_config))
+ return ;
+#endif
+ sb_dsp_init(hw_config);
#endif
- return mem_start;
+ return ;
}
int
-probe_sb (struct address_info *hw_config)
+probe_sb(struct address_info * hw_config)
{
- return sb_dsp_detect (hw_config);
-}
+#if defined(CONFIG_AEDSP16) && defined(AEDSP16_SBPRO)
+ /*
+ * Initialize Audio Excel DSP 16 to SBPRO.
+ */
+ InitAEDSP16_SBPRO(hw_config);
+#endif
+ return sb_dsp_detect(hw_config);
+}
#endif
diff --git a/sys/i386/isa/sound/sb_dsp.c b/sys/i386/isa/sound/sb_dsp.c
index 37be35c4cfca..67c66f765858 100644
--- a/sys/i386/isa/sound/sb_dsp.c
+++ b/sys/i386/isa/sound/sb_dsp.c
@@ -1,10 +1,10 @@
/*
* sound/sb_dsp.c
- *
+ *
* The low level driver for the SoundBlaster DSP chip (SB1.0 to 2.1, SB Pro).
- *
+ *
* 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
@@ -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,24 +24,39 @@
* 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
- *
+ *
+ * Modified: Hunyue Yau Jan 6 1994 Added code to support Sound Galaxy NX
+ * Pro
+ *
+ * JRA Gibson April 1995 Code added for MV ProSonic/Jazz 16 in 16 bit mode
*/
-#include "sound_config.h"
+#include <i386/isa/sound/sound_config.h>
-#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_SB)
+#if (NSB > 0)
+
+#ifdef SM_WAVE
+#define JAZZ16
+#endif
+
+#include <i386/isa/sound/sbcard.h>
+#include <i386/isa/sound/sb_mixer.h>
+#include <machine/clock.h>
-#include "sb.h"
-#include "sb_mixer.h"
#undef SB_TEST_IRQ
+/*
+ * XXX note -- only one sb-like device is supported until these
+ * variables are put in a struct sb_unit[] array
+ */
+
int sbc_base = 0;
-static int sbc_irq = 0;
+int sbc_irq = 0;
static int open_mode = 0; /* Read, write or both */
+int Jazz16_detected = 0;
+int sb_no_recording = 0;
+static int dsp_count = 0;
+static int trigger_bits;
/*
* The DSP channel can be used either for input or output. Variable
@@ -51,813 +66,1037 @@ static int open_mode = 0; /* Read, write or both */
* 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 init */
static int midi_disabled = 0;
int sb_dsp_highspeed = 0;
-int sbc_major = 1, sbc_minor = 0; /*
-
-
- * * * * DSP version */
+int sbc_major = 1, 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;
int sb_midi_mode = NORMAL_MIDI;
-int sb_midi_busy = 0; /*
+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; /* or IMODE_INPUT or IMODE_OUTPUT */
- * * * * 1 if the process has output
- * to * * MIDI */
-int sb_dsp_busy = 0;
+static int dma8 = 1;
-volatile int sb_irq_mode = IMODE_NONE; /*
+#ifdef JAZZ16 /* 16 bit support for JAZZ16 */
+static int dsp_16bit = 0;
+static int dma16 = 5;
- * * * * IMODE_INPUT, *
- * IMODE_OUTPUT * * or *
- * IMODE_NONE */
-static volatile int irq_ok = 0;
+static int dsp_set_bits(int arg);
+static int initialize_ProSonic16(void);
+#endif /* end of 16 bit support for JAZZ16 */
int sb_duplex_midi = 0;
static int my_dev = 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);
+static int dsp_speed(int);
+static int dsp_set_stereo(int mode);
+static void sb_dsp_reset(int dev);
+sound_os_info *sb_osp = NULL;
-#if !defined(EXCLUDE_MIDI) || !defined(EXCLUDE_AUDIO)
+#if defined(CONFIG_MIDI) || defined(CONFIG_AUDIO)
/*
* Common code for the midi and pcm functions
*/
int
-sb_dsp_command (unsigned char val)
+sb_dsp_command(u_char val)
{
- int i;
- unsigned long limit;
-
- 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
- * called while interrupts are disabled. This means that the timer is
- * disabled also. However the timeout situation is a abnormal condition.
- * Normally the DSP should be ready to accept commands after just couple of
- * loops.
- */
-
- for (i = 0; i < 500000 && GET_TIME () < limit; i++)
- {
- if ((INB (DSP_STATUS) & 0x80) == 0)
- {
- OUTB (val, DSP_COMMAND);
- return 1;
+ int i;
+ u_long limit;
+
+ 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 called while interrupts are disabled. This means that
+ * the timer is disabled also. However the timeout situation is a
+ * abnormal condition. Normally the DSP should be ready to accept
+ * commands after just couple of loops.
+ */
+
+ for (i = 0; i < 500000 && get_time() < limit; i++) {
+ if ((inb(DSP_STATUS) & 0x80) == 0) {
+ outb(DSP_COMMAND, val);
+ return 1;
}
}
- printk ("SoundBlaster: DSP Command(%x) Timeout.\n", val);
- printk ("IRQ conflict???\n");
- return 0;
+ printf("SoundBlaster: DSP Command(0x%02x) timeout. IRQ conflict ?\n", val);
+ return 0;
}
void
-sbintr (int unit)
+sbintr(int irq)
{
- int status;
-
-#ifndef EXCLUDE_SBPRO
- if (sb16)
- {
- unsigned char src = sb_getmixer (IRQ_STAT); /*
-
-
- * * * * Interrupt
- * source * *
- * register */
-
-#ifndef EXCLUDE_SB16
- if (src & 3)
- sb16_dsp_interrupt (unit);
-
-#ifndef EXCLUDE_MIDI
- if (src & 4)
- sb16midiintr (unit); /*
- * SB MPU401 interrupt
- */
-#endif
-
-#endif
-
- if (!(src & 1))
- return; /*
- * Not a DSP interupt
- */
+ int status;
+
+#ifdef CONFIG_SBPRO
+ if (sb16) {
+ u_char src = sb_getmixer(IRQ_STAT); /* Interrupt source register */
+#ifdef CONFIG_SB16
+ if (src & 3)
+ sb16_dsp_interrupt(irq);
+#ifdef CONFIG_MIDI
+ if (src & 4)
+ sb16midiintr(irq); /* SB MPU401 interrupt */
+#endif /* CONFIG_MIDI */
+#endif /* CONFIG_SB16 */
+ if (!(src & 1))
+ return; /* Not a DSP interupt */
}
+#endif /* CONFIG_SBPRO */
+
+ status = inb(DSP_DATA_AVAIL); /* Clear interrupt */
+
+ if (sb_intr_active)
+ switch (sb_irq_mode) {
+ case IMODE_OUTPUT:
+ sb_intr_active = 0;
+ DMAbuf_outputintr(my_dev, 1);
+ break;
+
+ case IMODE_INPUT:
+ sb_intr_active = 0;
+ DMAbuf_inputintr(my_dev);
+ /*
+ * A complete buffer has been input. Let's start new one
+ */
+ break;
+
+ case IMODE_INIT:
+ sb_intr_active = 0;
+ break;
+
+ case IMODE_MIDI:
+#ifdef CONFIG_MIDI
+ sb_midi_interrupt(irq);
#endif
+ break;
- status = INB (DSP_DATA_AVAIL);/*
- * Clear interrupt
- */
-
- if (sb_intr_active)
- switch (sb_irq_mode)
- {
- case IMODE_OUTPUT:
- sb_intr_active = 0;
- DMAbuf_outputintr (my_dev, 1);
- break;
-
- case IMODE_INPUT:
- sb_intr_active = 0;
- DMAbuf_inputintr (my_dev);
- /*
- * A complete buffer has been input. Let's start new one
- */
- break;
-
- case IMODE_INIT:
- sb_intr_active = 0;
- irq_ok = 1;
- break;
-
- case IMODE_MIDI:
-#ifndef EXCLUDE_MIDI
- sb_midi_interrupt (unit);
-#endif
- break;
-
- default:
- printk ("SoundBlaster: Unexpected interrupt\n");
- }
+ default:
+ printf("SoundBlaster: Unexpected interrupt\n");
+ }
}
-static int sb_irq_usecount = 0;
int
-sb_get_irq (void)
+sb_reset_dsp(void)
{
- int ok;
-
- if (!sb_irq_usecount)
- if ((ok = snd_set_irq_handler (sbc_irq, sbintr)) < 0)
- return ok;
+ int loopc;
- sb_irq_usecount++;
-
- return 0;
-}
+ outb(DSP_RESET, 1);
+ DELAY(10);
+ outb(DSP_RESET, 0);
+ DELAY(30);
-void
-sb_free_irq (void)
-{
- if (!sb_irq_usecount)
- return;
- sb_irq_usecount--;
+ for (loopc = 0; loopc < 100 && !(inb(DSP_DATA_AVAIL) & 0x80); loopc++)
+ DELAY(10);
- if (!sb_irq_usecount)
- snd_release_irq (sbc_irq);
-}
+ if (inb(DSP_READ) != 0xAA) {
+ printf("sb_reset_dsp failed\n");
+ return 0; /* Sorry */
+ }
-int
-sb_reset_dsp (void)
-{
- int loopc;
-
- OUTB (1, DSP_RESET);
- tenmicrosec ();
- OUTB (0, DSP_RESET);
- tenmicrosec ();
- tenmicrosec ();
- tenmicrosec ();
-
- for (loopc = 0; loopc < 1000 && !(INB (DSP_DATA_AVAIL) & 0x80); loopc++); /*
- * Wait
- * for
- * data
- * *
- * available
- * status
- */
-
- if (INB (DSP_READ) != 0xAA)
- return 0; /*
- * Sorry
- */
-
- return 1;
+ return 1;
}
#endif
-#ifndef EXCLUDE_AUDIO
+#ifdef CONFIG_AUDIO
-static void
-dsp_speaker (char state)
+void
+dsp_speaker(char state)
{
- if (state)
- sb_dsp_command (DSP_CMD_SPKON);
- else
- sb_dsp_command (DSP_CMD_SPKOFF);
+ if (state)
+ sb_dsp_command(DSP_CMD_SPKON);
+ else
+ sb_dsp_command(DSP_CMD_SPKOFF);
}
static int
-dsp_speed (int speed)
+dsp_speed(int speed)
{
- unsigned char tconst;
- unsigned long flags;
- int max_speed = 44100;
-
- if (speed < 4000)
- speed = 4000;
-
- /*
- * Older SB models don't support higher speeds than 22050.
- */
-
- if (sbc_major < 2 ||
- (sbc_major == 2 && sbc_minor == 0))
- max_speed = 22050;
+ u_char tconst;
+ u_long flags;
+ int max_speed = 44100;
+
+printf("dsp_speed %d\n", speed); /* XXX lr 970601 */
+ if (speed < 4000)
+ speed = 4000;
+
+ /*
+ * Older SB models don't support higher speeds than 22050.
+ */
+
+ if (sbc_major < 2 || (sbc_major == 2 && sbc_minor == 0))
+ max_speed = 22050;
+
+ /*
+ * SB models earlier than SB Pro have low limit for the input speed.
+ */
+ if (open_mode != OPEN_WRITE) /* Recording is possible */
+ if (sbc_major < 3) /* Limited input speed with these cards */
+ if (sbc_major == 2 && sbc_minor > 0)
+ max_speed = 15000;
+ else
+ max_speed = 13000;
+
+ if (speed > max_speed)
+ speed = max_speed; /* Invalid speed */
+
+ /*
+ * Logitech SoundMan Games and Jazz16 cards can support 44.1kHz
+ * stereo
+ */
+#if !defined (SM_GAMES)
+ /*
+ * Max. stereo speed is 22050
+ */
+ if (dsp_stereo && speed > 22050 && Jazz16_detected == 0)
+ speed = 22050;
+#endif
- /*
- * 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;
- /*
- * Max. stereo speed is 22050
- */
-
- if ((speed > 22050) && sb_midi_busy)
- {
- printk ("SB Warning: High speed DSP not possible simultaneously with MIDI output\n");
- speed = 22050;
+ if ((speed > 22050) && sb_midi_busy) {
+ printf("SB Warning: High speed DSP not possible simultaneously with MIDI output\n");
+ speed = 22050;
}
+ if (dsp_stereo)
+ speed *= 2;
- if (dsp_stereo)
- speed *= 2;
+ /*
+ * Now the speed should be valid
+ */
- /*
- * Now the speed should be valid
- */
+ if (speed > 22050) { /* High speed mode */
+ int tmp;
- if (speed > 22050)
- { /*
- * High speed mode
- */
- int tmp;
+ tconst = (u_char) ((65536 - ((256000000 + speed / 2) / speed)) >> 8);
+ sb_dsp_highspeed = 1;
- tconst = (unsigned char) ((65536 -
- ((256000000 + speed / 2) / speed)) >> 8);
- sb_dsp_highspeed = 1;
+ flags = splhigh();
+ if (sb_dsp_command(DSP_CMD_TCONST))
+ sb_dsp_command(tconst);
+ splx(flags);
- DISABLE_INTR (flags);
- if (sb_dsp_command (0x40))
- sb_dsp_command (tconst);
- RESTORE_INTR (flags);
+ tmp = 65536 - (tconst << 8);
+ speed = (256000000 + tmp / 2) / tmp;
+ } else {
+ int tmp;
- tmp = 65536 - (tconst << 8);
- speed = (256000000 + tmp / 2) / tmp;
- }
- else
- {
- int tmp;
+ sb_dsp_highspeed = 0;
+ tconst = (256 - ((1000000 + speed / 2) / speed)) & 0xff;
- sb_dsp_highspeed = 0;
- tconst = (256 - ((1000000 + speed / 2) / speed)) & 0xff;
+ flags = splhigh();
+ if (sb_dsp_command(DSP_CMD_TCONST)) /* Set time constant */
+ sb_dsp_command(tconst);
+ splx(flags);
- DISABLE_INTR (flags);
- if (sb_dsp_command (0x40))/*
- * Set time constant
- */
- sb_dsp_command (tconst);
- RESTORE_INTR (flags);
-
- tmp = 256 - tconst;
- speed = (1000000 + tmp / 2) / tmp;
+ tmp = 256 - tconst;
+ speed = (1000000 + tmp / 2) / tmp;
}
- if (dsp_stereo)
- speed /= 2;
+ if (dsp_stereo)
+ speed /= 2;
- dsp_current_speed = speed;
- return speed;
+ dsp_current_speed = speed;
+printf("dsp_speed done %d\n", speed);
+ return speed;
}
static int
-dsp_set_stereo (int mode)
+dsp_set_stereo(int mode)
{
- dsp_stereo = 0;
+ dsp_stereo = 0;
-#ifdef EXCLUDE_SBPRO
- return 0;
+#ifndef CONFIG_SBPRO
+ return 0;
#else
- if (sbc_major < 3 || sb16)
- return 0; /*
- * Sorry no stereo
- */
+ if (sbc_major < 3 || sb16)
+ return 0; /* Sorry no stereo */
- if (mode && sb_midi_busy)
- {
- printk ("SB Warning: Stereo DSP not possible simultaneously with MIDI output\n");
- return 0;
+ if (mode && sb_midi_busy) {
+ printf("SB Warning: Stereo DSP not possible simultaneously with MIDI output\n");
+ return 0;
}
-
- dsp_stereo = !!mode;
- return dsp_stereo;
+ dsp_stereo = !!mode;
+ return dsp_stereo;
#endif
}
static void
-sb_dsp_output_block (int dev, unsigned long buf, int count,
- int intrflag, int restart_dma)
+sb_dsp_output_block(int dev, u_long buf, int count,
+ int intrflag, int restart_dma)
{
- unsigned long flags;
-
- if (!sb_irq_mode)
- dsp_speaker (ON);
-
- sb_irq_mode = IMODE_OUTPUT;
- DMAbuf_start_dma (dev, buf, count, DMA_MODE_WRITE);
-
- if (audio_devs[dev]->dmachan > 3)
- count >>= 1;
- count--;
-
- if (sb_dsp_highspeed)
- {
- DISABLE_INTR (flags);
- 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
- */
- }
- else
- printk ("SB Error: Unable to start (high speed) DAC\n");
- RESTORE_INTR (flags);
- }
- else
- {
- DISABLE_INTR (flags);
- if (sb_dsp_command (0x14))/*
- * 8-bit DAC (DMA)
- */
- {
- sb_dsp_command ((unsigned char) (count & 0xff));
- sb_dsp_command ((unsigned char) ((count >> 8) & 0xff));
- }
- else
- printk ("SB Error: Unable to start DAC\n");
- RESTORE_INTR (flags);
+ u_long flags;
+
+ if (!sb_irq_mode)
+ dsp_speaker(ON);
+
+ DMAbuf_start_dma(dev, buf, count, 1);
+
+ sb_irq_mode = 0;
+
+ if (audio_devs[dev]->dmachan1 > 3)
+ count >>= 1;
+ count--;
+ dsp_count = count;
+
+ sb_irq_mode = IMODE_OUTPUT;
+ if (sb_dsp_highspeed) {
+ flags = splhigh();
+ if (sb_dsp_command(DSP_CMD_HSSIZE)) { /* High speed size */
+ sb_dsp_command((u_char) (dsp_count & 0xff));
+ sb_dsp_command((u_char) ((dsp_count >> 8) & 0xff));
+ sb_dsp_command(DSP_CMD_HSDAC); /* High speed 8 bit DAC */
+ } else
+ printf("SB Error: Unable to start (high speed) DAC\n");
+ splx(flags);
+ } else {
+ flags = splhigh();
+ if (sb_dsp_command(DSP_CMD_DAC8)) { /* 8-bit DAC (DMA) */
+ sb_dsp_command((u_char) (dsp_count & 0xff));
+ sb_dsp_command((u_char) ((dsp_count >> 8) & 0xff));
+ } else
+ printf("SB Error: Unable to start DAC\n");
+ splx(flags);
}
- sb_intr_active = 1;
+ sb_intr_active = 1;
}
static void
-sb_dsp_start_input (int dev, unsigned long buf, int count, int intrflag,
- int restart_dma)
+sb_dsp_start_input(int dev, u_long buf, int count, int intrflag,
+ int restart_dma)
{
- /*
- * Start a DMA input to the buffer pointed by dmaqtail
- */
+ u_long flags;
- unsigned long flags;
-
- if (!sb_irq_mode)
- dsp_speaker (OFF);
+ if (sb_no_recording) {
+ printf("SB Error: This device doesn't support recording\n");
+ return;
+ }
+ /*
+ * Start a DMA input to the buffer pointed by dmaqtail
+ */
+
+ if (!sb_irq_mode)
+ dsp_speaker(OFF);
+
+ DMAbuf_start_dma(dev, buf, count, 0);
+ sb_irq_mode = 0;
+
+ if (audio_devs[dev]->dmachan1 > 3)
+ count >>= 1;
+ count--;
+ dsp_count = count;
+
+ sb_irq_mode = IMODE_INPUT;
+ if (sb_dsp_highspeed) {
+ flags = splhigh();
+ if (sb_dsp_command(DSP_CMD_HSSIZE)) { /* High speed size */
+ sb_dsp_command((u_char) (dsp_count & 0xff));
+ sb_dsp_command((u_char) ((dsp_count >> 8) & 0xff));
+ sb_dsp_command(DSP_CMD_HSADC); /* High speed 8 bit ADC */
+ } else
+ printf("SB Error: Unable to start (high speed) ADC\n");
+ splx(flags);
+ } else {
+ flags = splhigh();
+ if (sb_dsp_command(DSP_CMD_ADC8)) { /* 8-bit ADC (DMA) */
+ sb_dsp_command((u_char) (dsp_count & 0xff));
+ sb_dsp_command((u_char) ((dsp_count >> 8) & 0xff));
+ } else
+ printf("SB Error: Unable to start ADC\n");
+ splx(flags);
+ }
- sb_irq_mode = IMODE_INPUT;
- DMAbuf_start_dma (dev, buf, count, DMA_MODE_READ);
+ sb_intr_active = 1;
+}
- if (audio_devs[dev]->dmachan > 3)
- count >>= 1;
- count--;
+static void
+sb_dsp_trigger(int dev, int bits)
+{
+ if (bits == trigger_bits)
+ return;
- if (sb_dsp_highspeed)
- {
- DISABLE_INTR (flags);
- 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
- */
- }
- else
- printk ("SB Error: Unable to start (high speed) ADC\n");
- RESTORE_INTR (flags);
- }
- else
- {
- DISABLE_INTR (flags);
- if (sb_dsp_command (0x24))/*
- * 8-bit ADC (DMA)
- */
- {
- sb_dsp_command ((unsigned char) (count & 0xff));
- sb_dsp_command ((unsigned char) ((count >> 8) & 0xff));
- }
- else
- printk ("SB Error: Unable to start ADC\n");
- RESTORE_INTR (flags);
- }
+ if (!bits)
+ sb_dsp_command(0xd0); /* Halt DMA */
+ else if (bits & sb_irq_mode)
+ sb_dsp_command(0xd4); /* Continue DMA */
- sb_intr_active = 1;
+ trigger_bits = bits;
}
static void
-dsp_cleanup (void)
+dsp_cleanup(void)
{
- sb_intr_active = 0;
+ sb_intr_active = 0;
}
static int
-sb_dsp_prepare_for_input (int dev, int bsize, int bcount)
+sb_dsp_prepare_for_input(int dev, int bsize, int bcount)
{
- dsp_cleanup ();
- dsp_speaker (OFF);
+ dsp_cleanup();
+ dsp_speaker(OFF);
- 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
- */
+ if (sbc_major == 3) { /* SB Pro */
+#ifdef JAZZ16
+ /*
+ * Select correct dma channel for 16/8 bit acccess
+ */
+ audio_devs[my_dev]->dmachan1 = dsp_16bit ? dma16 : dma8;
+ if (dsp_stereo)
+ sb_dsp_command(dsp_16bit ? 0xac : 0xa8);
+ else
+ sb_dsp_command(dsp_16bit ? 0xa4 : 0xa0);
+#else
+ /*
+ * 8 bit only cards use this
+ */
+ if (dsp_stereo)
+ sb_dsp_command(0xa8);
+ else
+ sb_dsp_command(0xa0);
+#endif
+ dsp_speed(dsp_current_speed); /* Speed must be recalculated
+ * if #channels * changes */
}
- return 0;
+ trigger_bits = 0;
+ sb_dsp_command(DSP_CMD_DMAHALT); /* Halt DMA */
+ return 0;
}
static int
-sb_dsp_prepare_for_output (int dev, int bsize, int bcount)
+sb_dsp_prepare_for_output(int dev, int bsize, int bcount)
{
- dsp_cleanup ();
- dsp_speaker (ON);
+ dsp_cleanup();
+ dsp_speaker(ON);
-#ifndef EXCLUDE_SBPRO
- if (sbc_major == 3) /*
- * SB Pro
- */
- {
- sb_mixer_set_stereo (dsp_stereo);
- dsp_speed (dsp_current_speed); /*
- * Speed must be recalculated if
- * #channels * changes
- */
+#ifdef CONFIG_SBPRO
+ if (sbc_major == 3) { /* SB Pro */
+#ifdef JAZZ16
+ /*
+ * 16 bit specific instructions
+ */
+ audio_devs[my_dev]->dmachan1 = dsp_16bit ? dma16 : dma8;
+ if (Jazz16_detected != 2) /* SM Wave */
+ sb_mixer_set_stereo(dsp_stereo);
+ if (dsp_stereo)
+ sb_dsp_command(dsp_16bit ? 0xac : 0xa8);
+ else
+ sb_dsp_command(dsp_16bit ? 0xa4 : 0xa0);
+#else
+ sb_mixer_set_stereo(dsp_stereo);
+#endif
+ dsp_speed(dsp_current_speed); /* Speed must be recalculated
+ * if #channels * changes */
}
#endif
- return 0;
+ trigger_bits = 0;
+ sb_dsp_command(DSP_CMD_DMAHALT); /* Halt DMA */
+ return 0;
}
static void
-sb_dsp_halt_xfer (int dev)
+sb_dsp_halt_xfer(int dev)
{
}
static int
-verify_irq (void)
+sb_dsp_open(int dev, int mode)
{
-#if 0
- DEFINE_WAIT_QUEUE (testq, testf);
+ int retval;
- irq_ok = 0;
-
- if (sb_get_irq () == -1)
- {
- printk ("*** SB Error: Irq %d already in use\n", sbc_irq);
- return 0;
+ if (!sb_dsp_ok) {
+ printf("SB Error: SoundBlaster board not installed\n");
+ return -(ENXIO);
}
-
-
- sb_irq_mode = IMODE_INIT;
-
- sb_dsp_command (0xf2); /*
- * This should cause immediate interrupt
- */
-
- DO_SLEEP (testq, testf, HZ / 5);
-
- sb_free_irq ();
-
- if (!irq_ok)
- {
- printk ("SB Warning: IRQ%d test not passed!", sbc_irq);
- irq_ok = 1;
+ if (sb_no_recording && mode & OPEN_READ) {
+ printf("SB Warning: Recording not supported by this device\n");
}
-#else
- irq_ok = 1;
+ if (sb_intr_active || (sb_midi_busy && sb_midi_mode == UART_MIDI)) {
+ printf("SB: PCM not possible during MIDI input\n");
+ return -(EBUSY);
+ }
+ /*
+ * Allocate 8 bit dma
+ */
+#ifdef JAZZ16
+ audio_devs[my_dev]->dmachan1 = dma8;
+ /*
+ * Allocate 16 bit dma
+ */
+ if (Jazz16_detected != 0)
+ if (dma16 != dma8) {
+ if (0) {
+ return -(EBUSY);
+ }
+ }
#endif
- return irq_ok;
-}
-static int
-sb_dsp_open (int dev, int mode)
-{
- int retval;
-
- if (!sb_dsp_ok)
- {
- printk ("SB Error: SoundBlaster board not installed\n");
- return RET_ERROR (ENXIO);
- }
+ sb_irq_mode = IMODE_NONE;
- if (sb_intr_active || (sb_midi_busy && sb_midi_mode == UART_MIDI))
- {
- printk ("SB: PCM not possible during MIDI input\n");
- return RET_ERROR (EBUSY);
- }
+ sb_dsp_busy = 1;
+ open_mode = mode;
- if (!irq_verified)
- {
- verify_irq ();
- irq_verified = 1;
- }
- else if (!irq_ok)
- printk ("SB Warning: Incorrect IRQ setting %d\n",
- sbc_irq);
+ return 0;
+}
- retval = sb_get_irq ();
- if (retval)
- return retval;
+static void
+sb_dsp_close(int dev)
+{
+#ifdef JAZZ16
+ /*
+ * Release 16 bit dma channel
+ */
+ if (Jazz16_detected) {
+ audio_devs[my_dev]->dmachan1 = dma8;
- if (DMAbuf_open_dma (dev) < 0)
- {
- sb_free_irq ();
- printk ("SB: DMA Busy\n");
- return RET_ERROR (EBUSY);
}
+#endif
- sb_irq_mode = IMODE_NONE;
-
- sb_dsp_busy = 1;
- open_mode = mode;
-
- return 0;
+ dsp_cleanup();
+ dsp_speaker(OFF);
+ sb_dsp_busy = 0;
+ sb_dsp_highspeed = 0;
+ open_mode = 0;
}
-static void
-sb_dsp_close (int dev)
+#ifdef JAZZ16
+/*
+ * Function dsp_set_bits() only required for 16 bit cards
+ */
+static int
+dsp_set_bits(int arg)
{
- DMAbuf_close_dma (dev);
- sb_free_irq ();
- dsp_cleanup ();
- dsp_speaker (OFF);
- sb_dsp_busy = 0;
- sb_dsp_highspeed = 0;
- open_mode = 0;
+ if (arg)
+ if (Jazz16_detected == 0)
+ dsp_16bit = 0;
+ else
+ switch (arg) {
+ case 8:
+ dsp_16bit = 0;
+ break;
+ case 16:
+ dsp_16bit = 1;
+ break;
+ default:
+ dsp_16bit = 0;
+ }
+ return dsp_16bit ? 16 : 8;
}
+#endif /* ifdef JAZZ16 */
+
static int
-sb_dsp_ioctl (int dev, unsigned int cmd, unsigned int arg, int local)
+sb_dsp_ioctl(int dev, u_int cmd, ioctl_arg arg, int local)
{
- switch (cmd)
- {
+ switch (cmd) {
case SOUND_PCM_WRITE_RATE:
- if (local)
- return dsp_speed (arg);
- return IOCTL_OUT (arg, dsp_speed (IOCTL_IN (arg)));
- break;
+ if (local)
+ return dsp_speed((int) arg);
+ return *(int *) arg = dsp_speed((*(int *) arg));
+ break;
case SOUND_PCM_READ_RATE:
- if (local)
- return dsp_current_speed;
- return IOCTL_OUT (arg, dsp_current_speed);
- break;
+ if (local)
+ return dsp_current_speed;
+ return *(int *) arg = dsp_current_speed;
+ break;
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);
- break;
+ if (local)
+ return dsp_set_stereo((int) arg - 1) + 1;
+ return *(int *) arg = dsp_set_stereo((*(int *) arg) - 1) + 1;
+ break;
case SOUND_PCM_READ_CHANNELS:
- if (local)
- return dsp_stereo + 1;
- return IOCTL_OUT (arg, dsp_stereo + 1);
- break;
+ if (local)
+ return dsp_stereo + 1;
+ return *(int *) arg = dsp_stereo + 1;
+ break;
case SNDCTL_DSP_STEREO:
- if (local)
- return dsp_set_stereo (arg);
- return IOCTL_OUT (arg, dsp_set_stereo (IOCTL_IN (arg)));
- break;
+ if (local)
+ return dsp_set_stereo((int) arg);
+ return *(int *) arg = dsp_set_stereo((*(int *) arg));
+ break;
+
+#ifdef JAZZ16
+ /*
+ * Word size specific cases here.
+ * SNDCTL_DSP_SETFMT=SOUND_PCM_WRITE_BITS
+ */
+ case SNDCTL_DSP_SETFMT:
+ if (local)
+ return dsp_set_bits((int) arg);
+ return *(int *) arg = dsp_set_bits((*(int *) arg));
+ break;
+ case SOUND_PCM_READ_BITS:
+ if (local)
+ return dsp_16bit ? 16 : 8;
+ return *(int *) arg = dsp_16bit ? 16 : 8;
+ break;
+#else
case SOUND_PCM_WRITE_BITS:
case SOUND_PCM_READ_BITS:
- if (local)
- return 8;
- return IOCTL_OUT (arg, 8);/*
- * Only 8 bits/sample supported
- */
- break;
+ if (local)
+ return 8;
+ return *(int *) (int) arg = 8; /* Only 8 bits/sample supported */
+ break;
+#endif /* ifdef JAZZ16 */
case SOUND_PCM_WRITE_FILTER:
case SOUND_PCM_READ_FILTER:
- return RET_ERROR (EINVAL);
- break;
+ return -(EINVAL);
+ break;
- default:
- return RET_ERROR (EINVAL);
+ default:;
}
- return RET_ERROR (EINVAL);
+ return -(EINVAL);
}
static void
-sb_dsp_reset (int dev)
+sb_dsp_reset(int dev)
{
- unsigned long flags;
+ u_long flags;
- DISABLE_INTR (flags);
+ flags = splhigh();
- sb_reset_dsp ();
- dsp_speed (dsp_current_speed);
- dsp_cleanup ();
+ sb_reset_dsp();
+ dsp_speed(dsp_current_speed);
+ dsp_cleanup();
- RESTORE_INTR (flags);
+ splx(flags);
}
#endif
-int
-sb_dsp_detect (struct address_info *hw_config)
+
+#ifdef JAZZ16
+
+/*
+ * Initialization of a Media Vision ProSonic 16 Soundcard. The function
+ * initializes a ProSonic 16 like PROS.EXE does for DOS. It sets the base
+ * address, the DMA-channels, interrupts and enables the joystickport.
+ *
+ * Also used by Jazz 16 (same card, different name)
+ *
+ * written 1994 by Rainer Vranken E-Mail:
+ * rvranken@polaris.informatik.uni-essen.de
+ */
+
+u_int
+get_sb_byte(void)
{
- sbc_base = hw_config->io_base;
- sbc_irq = hw_config->irq;
+ int i;
- if (sb_dsp_ok)
- return 0; /*
- * Already initialized
- */
+ for (i = 1000; i; i--)
+ if (inb(DSP_DATA_AVAIL) & 0x80) {
+ return inb(DSP_READ);
+ }
+ return 0xffff;
+}
- if (!sb_reset_dsp ())
- return 0;
+#ifdef SM_WAVE
+/*
+ * Logitech Soundman Wave detection and initialization by Hannu Savolainen.
+ *
+ * There is a microcontroller (8031) in the SM Wave card for MIDI emulation.
+ * it's located at address MPU_BASE+4. MPU_BASE+7 is a SM Wave specific
+ * control register for MC reset, SCSI, OPL4 and DSP (future expansion)
+ * address decoding. Otherwise the SM Wave is just a ordinary MV Jazz16 based
+ * soundcard.
+ */
- return 1; /*
- * Detected
- */
+static void
+smw_putmem(int base, int addr, u_char val)
+{
+ u_long flags;
+
+ flags = splhigh();
+
+ outb(base + 1, addr & 0xff); /* Low address bits */
+ outb(base + 2, addr >> 8); /* High address bits */
+ outb(base, val); /* Data */
+
+ splx(flags);
}
-#ifndef EXCLUDE_AUDIO
-static struct audio_operations sb_dsp_operations =
+static u_char
+smw_getmem(int base, int addr)
{
- "SoundBlaster",
- NOTHING_SPECIAL,
- AFMT_U8, /* Just 8 bits. Poor old SB */
- NULL,
- sb_dsp_open,
- sb_dsp_close,
- sb_dsp_output_block,
- sb_dsp_start_input,
- sb_dsp_ioctl,
- sb_dsp_prepare_for_input,
- sb_dsp_prepare_for_output,
- sb_dsp_reset,
- sb_dsp_halt_xfer,
- NULL, /* local_qlen */
- NULL /* copy_from_user */
-};
+ u_long flags;
+ u_char val;
+
+ flags = splhigh();
+
+ outb(base + 1, addr & 0xff); /* Low address bits */
+ outb(base + 2, addr >> 8); /* High address bits */
+ val = inb(base); /* Data */
+
+ splx(flags);
+ return val;
+}
+
+#ifdef SMW_MIDI0001_INCLUDED
+#include </sys/i386/isa/sound/smw-midi0001.h>
+#else
+u_char *smw_ucode = NULL;
+int smw_ucodeLen = 0;
#endif
-long
-sb_dsp_init (long mem_start, struct address_info *hw_config)
+static int
+initialize_smw(int mpu_base)
{
- int i;
- int mixer_type = 0;
- sbc_major = sbc_minor = 0;
- sb_dsp_command (0xe1); /*
- * Get version
- */
+ int mp_base = mpu_base + 4; /* Microcontroller base */
+ int i;
+ u_char control;
+
+
+ /*
+ * Reset the microcontroller so that the RAM can be accessed
+ */
+
+ control = inb(mpu_base + 7);
+ outb(mpu_base + 7, control | 3); /* Set last two bits to 1 (?) */
+ outb(mpu_base + 7, (control & 0xfe) | 2); /* xxxxxxx0 resets the mc */
+ DELAY(3000); /* Wait at least 1ms */
+
+ outb(mpu_base + 7, control & 0xfc); /* xxxxxx00 enables RAM */
+
+ /*
+ * Detect microcontroller by probing the 8k RAM area
+ */
+ smw_putmem(mp_base, 0, 0x00);
+ smw_putmem(mp_base, 1, 0xff);
+ DELAY(10);
+
+ if (smw_getmem(mp_base, 0) != 0x00 || smw_getmem(mp_base, 1) != 0xff) {
+ printf("\nSM Wave: No microcontroller RAM detected (%02x, %02x)\n",
+ smw_getmem(mp_base, 0), smw_getmem(mp_base, 1));
+ return 0; /* No RAM */
+ }
+ /*
+ * There is RAM so assume it's really a SM Wave
+ */
+
+ if (smw_ucodeLen > 0) {
+ if (smw_ucodeLen != 8192) {
+ printf("\nSM Wave: Invalid microcode (MIDI0001.BIN) length\n");
+ return 1;
+ }
+ /*
+ * Download microcode
+ */
- for (i = 1000; i; i--)
- {
- if (INB (DSP_DATA_AVAIL) & 0x80)
- { /*
- * wait for Data Ready
- */
- if (sbc_major == 0)
- sbc_major = INB (DSP_READ);
- else
- {
- sbc_minor = INB (DSP_READ);
- break;
+ for (i = 0; i < 8192; i++)
+ smw_putmem(mp_base, i, smw_ucode[i]);
+
+ /*
+ * Verify microcode
+ */
+
+ for (i = 0; i < 8192; i++)
+ if (smw_getmem(mp_base, i) != smw_ucode[i]) {
+ printf("SM Wave: Microcode verification failed\n");
+ return 0;
}
+ }
+ control = 0;
+#ifdef SMW_SCSI_IRQ
+ /*
+ * Set the SCSI interrupt (IRQ2/9, IRQ3 or IRQ10). The SCSI interrupt
+ * is disabled by default.
+ *
+ * Btw the Zilog 5380 SCSI controller is located at MPU base + 0x10.
+ */
+ {
+ static u_char scsi_irq_bits[] =
+ {0, 0, 3, 1, 0, 0, 0, 0, 0, 3, 2, 0, 0, 0, 0, 0};
+
+ control |= scsi_irq_bits[SMW_SCSI_IRQ] << 6;
+ }
+#endif
+
+#ifdef SMW_OPL4_ENABLE
+ /*
+ * Make the OPL4 chip visible on the PC bus at 0x380.
+ *
+ * There is no need to enable this feature since VoxWare doesn't support
+ * OPL4 yet. Also there is no RAM in SM Wave so enabling OPL4 is
+ * pretty useless.
+ */
+ control |= 0x10; /* Uses IRQ12 if bit 0x20 == 0 */
+ /* control |= 0x20; Uncomment this if you want to use IRQ7 */
+#endif
+
+ outb(mpu_base + 7, control | 0x03); /* xxxxxx11 restarts */
+ return 1;
+}
+
+#endif
+
+static int
+initialize_ProSonic16(void)
+{
+ int x;
+ static u_char int_translat[16] =
+ {0, 0, 2, 3, 0, 1, 0, 4, 0, 2, 5, 0, 0, 0, 0, 6},
+ dma_translat[8] =
+ {0, 1, 0, 2, 0, 3, 0, 4};
+
+ struct address_info *mpu_config;
+
+ int mpu_base, mpu_irq;
+
+ if ((mpu_config = sound_getconf(SNDCARD_MPU401))) {
+ mpu_base = mpu_config->io_base;
+ mpu_irq = mpu_config->irq;
+ } else {
+ mpu_base = mpu_irq = 0;
+ }
+
+ outb(0x201, 0xAF); /* ProSonic/Jazz16 wakeup */
+ DELAY(15000); /* wait at least 10 milliseconds */
+ outb(0x201, 0x50);
+ outb(0x201, (sbc_base & 0x70) | ((mpu_base & 0x30) >> 4));
+
+ if (sb_reset_dsp()) { /* OK. We have at least a SB */
+
+ /* Check the version number of ProSonic (I guess) */
+
+ if (!sb_dsp_command(0xFA))
+ return 1;
+ if (get_sb_byte() != 0x12)
+ return 1;
+
+ if (sb_dsp_command(0xFB) && /* set DMA-channels and Interrupts */
+ sb_dsp_command((dma_translat[JAZZ_DMA16]<<4)|dma_translat[dma8]) &&
+ sb_dsp_command((int_translat[mpu_irq]<<4)|int_translat[sbc_irq])) {
+ Jazz16_detected = 1;
+ if (mpu_base == 0)
+ printf("Jazz16: No MPU401 devices configured - MIDI port not initialized\n");
+
+#ifdef SM_WAVE
+ if (mpu_base != 0)
+ if (initialize_smw(mpu_base))
+ Jazz16_detected = 2;
+#endif
+ sb_dsp_disable_midi();
}
+ return 1; /* There was at least a SB */
}
+ return 0; /* No SB or ProSonic16 detected */
+}
+
+#endif /* ifdef JAZZ16 */
+
+int
+sb_dsp_detect(struct address_info * hw_config)
+{
+ sbc_base = hw_config->io_base;
+ sbc_irq = hw_config->irq;
+ sb_osp = hw_config->osp;
- if (sbc_major == 2 || sbc_major == 3)
- sb_duplex_midi = 1;
- if (sbc_major == 4)
- sb16 = 1;
+ if (sb_dsp_ok)
+ return 0; /* Already initialized */
+ dma8 = hw_config->dma;
-#ifndef EXCLUDE_SBPRO
- if (sbc_major >= 3)
- mixer_type = sb_mixer_init (sbc_major);
+#ifdef JAZZ16
+ dma16 = JAZZ_DMA16;
+
+ if (!initialize_ProSonic16())
+ return 0;
+#else
+ if (!sb_reset_dsp())
+ return 0;
#endif
-#ifndef EXCLUDE_YM8312
+ return 1; /* Detected */
+}
+
+#ifdef CONFIG_AUDIO
+static struct audio_operations sb_dsp_operations =
+{
+ "SoundBlaster",
+ NOTHING_SPECIAL,
+ AFMT_U8, /* Just 8 bits. Poor old SB */
+ NULL,
+ sb_dsp_open,
+ sb_dsp_close,
+ sb_dsp_output_block,
+ sb_dsp_start_input,
+ sb_dsp_ioctl,
+ sb_dsp_prepare_for_input,
+ sb_dsp_prepare_for_output,
+ sb_dsp_reset,
+ sb_dsp_halt_xfer,
+ NULL, /* local_qlen */
+ NULL, /* copy_from_user */
+ NULL,
+ NULL,
+ sb_dsp_trigger
+};
- if (sbc_major > 3 ||
- (sbc_major == 3 && INB (0x388) == 0x00)) /* Should be 0x06 if not OPL-3 */
- enable_opl3_mode (OPL3_LEFT, OPL3_RIGHT, OPL3_BOTH);
#endif
- if (sbc_major >= 3)
- {
-#ifndef SCO
-# ifdef __SGNXPRO__
- if (mixer_type == 2)
- {
- sprintf (sb_dsp_operations.name, "Sound Galaxy NX Pro %d.%d", sbc_major, sbc_minor);
- }
- else
-# endif
- {
- sprintf (sb_dsp_operations.name, "SoundBlaster Pro %d.%d", sbc_major, sbc_minor);
- }
+void
+sb_dsp_init(struct address_info * hw_config)
+{
+ int i;
+ char *fmt = NULL ;
+
+#ifdef CONFIG_SBPRO
+ int mixer_type = 0;
+
#endif
+
+ sb_osp = hw_config->osp;
+ sbc_major = sbc_minor = 0;
+ sb_dsp_command(DSP_CMD_GETVER); /* Get version */
+
+ for (i = 10000; i; i--) { /* perhaps wait longer on a fast machine ? */
+ if (inb(DSP_DATA_AVAIL) & 0x80) { /* wait for Data Ready */
+ if (sbc_major == 0)
+ sbc_major = inb(DSP_READ);
+ else {
+ sbc_minor = inb(DSP_READ);
+ break;
+ }
+ } else
+ DELAY(20);
}
- else
- {
-#ifndef SCO
- sprintf (sb_dsp_operations.name, "SoundBlaster %d.%d", sbc_major, sbc_minor);
-#endif
+
+ if (sbc_major == 0) {
+ printf("\n\nFailed to get SB version (%x) - possible I/O conflict\n\n",
+ inb(DSP_DATA_AVAIL));
+ sbc_major = 1;
}
+ if (sbc_major == 2 || sbc_major == 3)
+ sb_duplex_midi = 1;
- printk (" <%s>", sb_dsp_operations.name);
+ if (sbc_major == 4)
+ sb16 = 1;
-#ifndef EXCLUDE_AUDIO
-#if !defined(EXCLUDE_SB16) && !defined(EXCLUDE_SBPRO)
- if (!sb16) /*
- * There is a better driver for SB16
- */
-#endif
- if (num_audiodevs < MAX_AUDIO_DEV)
- {
- audio_devs[my_dev = num_audiodevs++] = &sb_dsp_operations;
- audio_devs[my_dev]->buffcount = DSP_BUFFCOUNT;
- audio_devs[my_dev]->buffsize = DSP_BUFFSIZE;
- audio_devs[my_dev]->dmachan = hw_config->dma;
- }
- else
- printk ("SB: Too many DSP devices available\n");
+ if (sbc_major == 3 && sbc_minor == 1) {
+ int ess_major = 0, ess_minor = 0;
+
+ /*
+ * Try to detect ESS chips.
+ */
+
+ sb_dsp_command(DSP_CMD_GETID); /* Return identification bytes. */
+
+ for (i = 1000; i; i--) {
+ if (inb(DSP_DATA_AVAIL) & 0x80) { /* wait for Data Ready */
+ if (ess_major == 0)
+ ess_major = inb(DSP_READ);
+ else {
+ ess_minor = inb(DSP_READ);
+ break;
+ }
+ }
+ }
+
+ if (ess_major == 0x48 && (ess_minor & 0xf0) == 0x80)
+ printf("Hmm... Could this be an ESS488 based card (rev %d)\n",
+ ess_minor & 0x0f);
+ else if (ess_major == 0x68 && (ess_minor & 0xf0) == 0x80)
+ printf("Hmm... Could this be an ESS688 based card (rev %d)\n",
+ ess_minor & 0x0f);
+ }
+ if (snd_set_irq_handler(sbc_irq, sbintr, sb_osp) < 0)
+ printf("sb_dsp: Can't allocate IRQ\n");;
+
+#ifdef CONFIG_SBPRO
+ if (sbc_major >= 3)
+ mixer_type = sb_mixer_init(sbc_major);
+#else
+ if (sbc_major >= 3)
+ printf("\nNOTE! SB Pro support required with your soundcard!\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 (sbc_major);
+
+#ifdef CONFIG_AUDIO
+ if (sbc_major >= 3) {
+ if (Jazz16_detected) {
+ if (Jazz16_detected == 2)
+ fmt = "SoundMan Wave %d.%d";
+ else
+ fmt = "MV Jazz16 %d.%d";
+ sb_dsp_operations.format_mask |= AFMT_S16_LE; /* 16 bits */
+ } else
+#ifdef __SGNXPRO__
+ if (mixer_type == 2)
+ fmt = "Sound Galaxy NX Pro %d.%d" ;
+ else
+#endif /* __SGNXPRO__ */
+ if (sbc_major == 4)
+ fmt = "SoundBlaster 16 %d.%d";
+ else
+ fmt = "SoundBlaster Pro %d.%d";
+ } else {
+ fmt = "SoundBlaster %d.%d" ;
+ }
+
+ sprintf(sb_dsp_operations.name, fmt, sbc_major, sbc_minor);
+ conf_printf(sb_dsp_operations.name, hw_config);
+
+#if defined(CONFIG_SB16) && defined(CONFIG_SBPRO)
+ if (!sb16) /* There is a better driver for SB16 */
+#endif /* CONFIG_SB16 && CONFIG_SBPRO */
+ if (num_audiodevs < MAX_AUDIO_DEV) {
+ audio_devs[my_dev = num_audiodevs++] = &sb_dsp_operations;
+ audio_devs[my_dev]->buffsize = DSP_BUFFSIZE;
+ dma8 = audio_devs[my_dev]->dmachan1 = hw_config->dma;
+ audio_devs[my_dev]->dmachan2 = -1;
+#ifdef JAZZ16
+ /*
+ * Allocate 16 bit dma
+ */
+ if (Jazz16_detected != 0)
+ if (dma16 != dma8) {
+ if (0) {
+ printf("Jazz16: Can't allocate 16 bit DMA channel\n");
+ }
+ }
+#endif /* JAZZ16 */
+ } else
+ printf("SB: Too many DSP devices available\n");
+#else
+ conf_printf("SoundBlaster (configured without audio support)", hw_config);
#endif
- sb_dsp_ok = 1;
- return mem_start;
+#ifdef CONFIG_MIDI
+ if (!midi_disabled && !sb16) {
+ /*
+ * Midi don't work in the SB emulation mode of PAS,
+ * SB16 has better midi interface
+ */
+ sb_midi_init(sbc_major);
+ }
+#endif /* CONFIG_MIDI */
+ sb_dsp_ok = 1;
}
void
-sb_dsp_disable_midi (void)
+sb_dsp_disable_midi(void)
{
- midi_disabled = 1;
+ midi_disabled = 1;
}
-
#endif
diff --git a/sys/i386/isa/sound/sb_midi.c b/sys/i386/isa/sound/sb_midi.c
index a78225ed2732..a1d50bdc1357 100644
--- a/sys/i386/isa/sound/sb_midi.c
+++ b/sys/i386/isa/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,14 +24,14 @@
* 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"
+#include <i386/isa/sound/sound_config.h>
-#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_SB) && !defined(EXCLUDE_MIDI)
+#if (NSND > 0) && defined(CONFIG_SB) && defined(CONFIG_MIDI)
-#include "sb.h"
+#include <i386/isa/sound/sbcard.h>
#undef SB_TEST_IRQ
/*
@@ -46,12 +46,7 @@ extern int sb_dsp_ok; /* Set to 1 atfer successful initialization */
extern int sbc_base;
extern int sb_midi_mode;
-extern int sb_midi_busy; /*
-
-
- * * * * 1 if the process has output to MIDI
- *
- */
+extern int sb_midi_busy; /* 1 if the process has output to MIDI */
extern int sb_dsp_busy;
extern int sb_dsp_highspeed;
@@ -61,192 +56,156 @@ extern int sb_intr_active;
int input_opened = 0;
static int my_dev;
-void (*midi_input_intr) (int dev, unsigned char data);
+extern sound_os_info *sb_osp;
+
+void (*midi_input_intr) (int dev, u_char data);
static int
-sb_midi_open (int dev, int mode,
- void (*input) (int dev, unsigned char data),
- void (*output) (int dev)
-)
+sb_midi_open(int dev, int mode, void (*input) (int dev, u_char data),
+ void (*output) (int dev))
{
- int ret;
+ int ret;
- if (!sb_dsp_ok)
- {
- printk ("SB Error: MIDI hardware not installed\n");
- return RET_ERROR (ENXIO);
+ if (!sb_dsp_ok) {
+ printf("SB Error: MIDI hardware not installed\n");
+ return -(ENXIO);
}
+ if (sb_midi_busy)
+ return -(EBUSY);
- if (sb_midi_busy)
- return RET_ERROR (EBUSY);
-
- if (mode != OPEN_WRITE && !sb_duplex_midi)
- {
- if (num_midis == 1)
- printk ("SoundBlaster: Midi input not currently supported\n");
- return RET_ERROR (EPERM);
+ if (mode != OPEN_WRITE && !sb_duplex_midi) {
+ if (num_midis == 1)
+ printf("SoundBlaster: Midi input not currently supported\n");
+ return -(EPERM);
}
-
- sb_midi_mode = NORMAL_MIDI;
- if (mode != OPEN_WRITE)
- {
- if (sb_dsp_busy || sb_intr_active)
- return RET_ERROR (EBUSY);
- sb_midi_mode = UART_MIDI;
+ sb_midi_mode = NORMAL_MIDI;
+ if (mode != OPEN_WRITE) {
+ if (sb_dsp_busy || sb_intr_active)
+ return -(EBUSY);
+ sb_midi_mode = UART_MIDI;
}
-
- if (sb_dsp_highspeed)
- {
- printk ("SB Error: Midi output not possible during stereo or high speed audio\n");
- return RET_ERROR (EBUSY);
+ if (sb_dsp_highspeed) {
+ printf("SB Error: Midi output not possible during stereo or high speed audio\n");
+ return -(EBUSY);
}
+ if (sb_midi_mode == UART_MIDI) {
+ sb_irq_mode = IMODE_MIDI;
- if (sb_midi_mode == UART_MIDI)
- {
- sb_irq_mode = IMODE_MIDI;
-
- sb_reset_dsp ();
-
- if (!sb_dsp_command (0x35))
- return RET_ERROR (EIO); /*
- * Enter the UART mode
- */
- sb_intr_active = 1;
-
- if ((ret = sb_get_irq ()) < 0)
- {
- sb_reset_dsp ();
- return 0; /*
- * IRQ not free
- */
- }
- input_opened = 1;
- midi_input_intr = input;
- }
+ sb_reset_dsp();
+
+ if (!sb_dsp_command(0x35))
+ return -(EIO); /* Enter the UART mode */
+ sb_intr_active = 1;
- sb_midi_busy = 1;
+ input_opened = 1;
+ midi_input_intr = input;
+ }
+ sb_midi_busy = 1;
- return 0;
+ return 0;
}
static void
-sb_midi_close (int dev)
+sb_midi_close(int dev)
{
- if (sb_midi_mode == UART_MIDI)
- {
- sb_reset_dsp (); /*
- * The only way to kill the UART mode
- */
- sb_free_irq ();
+ if (sb_midi_mode == UART_MIDI) {
+ sb_reset_dsp(); /* The only way to kill the UART mode */
}
- sb_intr_active = 0;
- sb_midi_busy = 0;
- input_opened = 0;
+ sb_intr_active = 0;
+ sb_midi_busy = 0;
+ input_opened = 0;
}
static int
-sb_midi_out (int dev, unsigned char midi_byte)
+sb_midi_out(int dev, u_char midi_byte)
{
- unsigned long flags;
-
- if (sb_midi_mode == NORMAL_MIDI)
- {
- DISABLE_INTR (flags);
- if (sb_dsp_command (0x38))
- sb_dsp_command (midi_byte);
- else
- printk ("SB Error: Unable to send a MIDI byte\n");
- RESTORE_INTR (flags);
- }
- else
- sb_dsp_command (midi_byte); /*
- * UART write
- */
-
- return 1;
+ u_long flags;
+
+ if (sb_midi_mode == NORMAL_MIDI) {
+ flags = splhigh();
+ if (sb_dsp_command(0x38))
+ sb_dsp_command(midi_byte);
+ else
+ printf("SB Error: Unable to send a MIDI byte\n");
+ splx(flags);
+ } else
+ sb_dsp_command(midi_byte); /* UART write */
+
+ return 1;
}
static int
-sb_midi_start_read (int dev)
+sb_midi_start_read(int dev)
{
- if (sb_midi_mode != UART_MIDI)
- {
- printk ("SoundBlaster: MIDI input not implemented.\n");
- return RET_ERROR (EPERM);
+ if (sb_midi_mode != UART_MIDI) {
+ printf("SoundBlaster: MIDI input not implemented.\n");
+ return -(EPERM);
}
- return 0;
+ return 0;
}
static int
-sb_midi_end_read (int dev)
+sb_midi_end_read(int dev)
{
- if (sb_midi_mode == UART_MIDI)
- {
- sb_reset_dsp ();
- sb_intr_active = 0;
+ if (sb_midi_mode == UART_MIDI) {
+ sb_reset_dsp();
+ sb_intr_active = 0;
}
- return 0;
+ return 0;
}
static int
-sb_midi_ioctl (int dev, unsigned cmd, unsigned arg)
+sb_midi_ioctl(int dev, u_int cmd, ioctl_arg arg)
{
- return RET_ERROR (EPERM);
+ return -(EPERM);
}
void
-sb_midi_interrupt (int dummy)
+sb_midi_interrupt(int dummy)
{
- unsigned long flags;
- unsigned char data;
+ u_long flags;
+ u_char data;
- DISABLE_INTR (flags);
+ flags = splhigh();
- data = INB (DSP_READ);
- if (input_opened)
- midi_input_intr (my_dev, data);
+ data = inb(DSP_READ);
+ if (input_opened)
+ midi_input_intr(my_dev, data);
- RESTORE_INTR (flags);
+ splx(flags);
}
#define MIDI_SYNTH_NAME "SoundBlaster Midi"
#define MIDI_SYNTH_CAPS 0
-#include "midi_synth.h"
+#include <i386/isa/sound/midi_synth.h>
static struct midi_operations sb_midi_operations =
{
- {"SoundBlaster", 0, 0, SNDCARD_SB},
- &std_midi_synth,
- sb_midi_open,
- sb_midi_close,
- sb_midi_ioctl,
- sb_midi_out,
- sb_midi_start_read,
- sb_midi_end_read,
- NULL, /*
- * Kick
- */
- NULL, /*
- * command
- */
- NULL, /*
- * buffer_status
- */
- NULL
+ {"SoundBlaster", 0, 0, SNDCARD_SB},
+ &std_midi_synth,
+ {0},
+ sb_midi_open,
+ sb_midi_close,
+ sb_midi_ioctl,
+ sb_midi_out,
+ sb_midi_start_read,
+ sb_midi_end_read,
+ NULL, /* Kick */
+ NULL, /* command */
+ NULL, /* buffer_status */
+ NULL
};
void
-sb_midi_init (int model)
+sb_midi_init(int model)
{
- if (num_midis >= MAX_MIDI_DEV)
- {
- printk ("Sound: Too many midi devices detected\n");
- return;
+ if (num_midis >= MAX_MIDI_DEV) {
+ printf("Sound: Too many midi devices detected\n");
+ return;
}
-
- std_midi_synth.midi_dev = num_midis;
- my_dev = num_midis;
- midi_devs[num_midis++] = &sb_midi_operations;
+ std_midi_synth.midi_dev = num_midis;
+ my_dev = num_midis;
+ midi_devs[num_midis++] = &sb_midi_operations;
}
#endif
diff --git a/sys/i386/isa/sound/sb_mixer.c b/sys/i386/isa/sound/sb_mixer.c
index 312a15c76fb9..14db176fbaf5 100644
--- a/sys/i386/isa/sound/sb_mixer.c
+++ b/sys/i386/isa/sound/sb_mixer.c
@@ -1,11 +1,10 @@
-
/*
* sound/sb_mixer.c
- *
+ *
* The low level mixer driver for the SoundBlaster Pro and SB16 cards.
- *
+ *
* 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
@@ -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,23 +24,24 @@
* 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.
- *
+ *
+ * Modified: Hunyue Yau Jan 6 1994 Added code to support the Sound Galaxy
+ * NX Pro mixer.
+ *
*/
-#include "sound_config.h"
+#include <i386/isa/sound/sound_config.h>
-#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_SB) && !defined(EXCLUDE_SBPRO)
+#if (NSB > 0) && defined(CONFIG_SBPRO)
#define __SB_MIXER_C__
-#include "sb.h"
-#include "sb_mixer.h"
+#include <i386/isa/sound/sbcard.h>
+#include <i386/isa/sound/sb_mixer.h>
#undef SB_TEST_IRQ
extern int sbc_base;
+extern int Jazz16_detected;
+extern sound_os_info *sb_osp;
static int mixer_initialized = 0;
@@ -53,401 +53,477 @@ static int mixer_caps;
static mixer_tab *iomap;
void
-sb_setmixer (unsigned int port, unsigned int value)
+sb_setmixer(u_int port, u_int value)
{
- unsigned long flags;
-
- DISABLE_INTR (flags);
- OUTB ((unsigned char) (port & 0xff), MIXER_ADDR); /*
- * Select register
- */
- tenmicrosec ();
- OUTB ((unsigned char) (value & 0xff), MIXER_DATA);
- tenmicrosec ();
- RESTORE_INTR (flags);
+ u_long flags;
+
+ flags = splhigh(); /* XXX ouch... */
+ outb(MIXER_ADDR, (u_char) (port & 0xff)); /* Select register */
+ DELAY(10);
+ outb(MIXER_DATA, (u_char) (value & 0xff));
+ DELAY(10);
+ splx(flags);
}
int
-sb_getmixer (unsigned int port)
+sb_getmixer(u_int port)
{
- int val;
- unsigned long flags;
-
- DISABLE_INTR (flags);
- OUTB ((unsigned char) (port & 0xff), MIXER_ADDR); /*
- * Select register
- */
- tenmicrosec ();
- val = INB (MIXER_DATA);
- tenmicrosec ();
- RESTORE_INTR (flags);
-
- return val;
+ int val;
+ u_long flags;
+
+ flags = splhigh();
+ outb(MIXER_ADDR, (u_char) (port & 0xff)); /* Select register */
+ DELAY(10);
+ val = inb(MIXER_DATA);
+ DELAY(10);
+ splx(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)));
+ sb_setmixer(OUT_FILTER, ((sb_getmixer(OUT_FILTER) & ~STEREO_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.
+ * 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)
+detect_mixer(void)
{
-#ifdef __SGNXPRO__
- int oldbass, oldtreble;
+#ifdef __SGNXPRO__
+ int oldbass, oldtreble;
+ extern int sbc_major;
#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
- * it?)
- */
- sb_setmixer (FM_VOL, 0xff);
- sb_setmixer (VOC_VOL, 0x33);
-
- if (sb_getmixer (FM_VOL) != 0xff)
- return 0; /*
- * No match
- */
- if (sb_getmixer (VOC_VOL) != 0x33)
- return 0;
+ int retcode = 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);
+ /*
+ * 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 it?)
+ */
+ sb_setmixer(FM_VOL, 0xff);
+ sb_setmixer(VOC_VOL, 0x33);
- sb_setmixer (BASS_LVL, 0xaa);
- sb_setmixer (TREBLE_LVL, 0x55);
+ if (sb_getmixer(FM_VOL) != 0xff)
+ return 0; /* No match */
+ if (sb_getmixer(VOC_VOL) != 0x33)
+ return 0;
- if ((sb_getmixer (BASS_LVL) != 0xaa) ||
- (sb_getmixer (TREBLE_LVL) != 0x55))
- {
- retcode = 1; /* 1 == Only SB Pro detected */
+#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);
+
+ /*
+ * If the SB version is 3.X (SB Pro), assume we have a SG NX Pro 16.
+ * In this case it's good idea to disable the Disney Sound Source
+ * compatibility mode. It's useless and just causes noise every time
+ * the LPT-port is accessed.
+ *
+ * Also place the card into WSS mode.
+ */
+ if (sbc_major == 3) {
+ outb(sbc_base + 0x1c, 0x01);
+ outb(sbc_base + 0x1a, 0x00);
}
- 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;
+ return retcode;
+}
+
+static void
+change_bits(u_char *regval, int dev, int chn, int newval)
+{
+ u_char mask;
+ int shift;
+
+ mask = (1 << (*iomap)[dev][chn].nbits) - 1;
+ newval = (int) ((newval * mask) + 50) / 100; /* Scale it */
+
+ 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 */
}
+static int
+sb_mixer_get(int dev)
+{
+ if (!((1 << dev) & supported_devices))
+ return -(EINVAL);
+
+ return levels[dev];
+}
+
+#ifdef JAZZ16
+static char smw_mix_regs[] =/* Left mixer registers */
+{
+ 0x0b, /* SOUND_MIXER_VOLUME */
+ 0x0d, /* SOUND_MIXER_BASS */
+ 0x0d, /* SOUND_MIXER_TREBLE */
+ 0x05, /* SOUND_MIXER_SYNTH */
+ 0x09, /* SOUND_MIXER_PCM */
+ 0x00, /* SOUND_MIXER_SPEAKER */
+ 0x03, /* SOUND_MIXER_LINE */
+ 0x01, /* SOUND_MIXER_MIC */
+ 0x07, /* SOUND_MIXER_CD */
+ 0x00, /* SOUND_MIXER_IMIX */
+ 0x00, /* SOUND_MIXER_ALTPCM */
+ 0x00, /* SOUND_MIXER_RECLEV */
+ 0x00, /* SOUND_MIXER_IGAIN */
+ 0x00, /* SOUND_MIXER_OGAIN */
+ 0x00, /* SOUND_MIXER_LINE1 */
+ 0x00, /* SOUND_MIXER_LINE2 */
+ 0x00 /* SOUND_MIXER_LINE3 */
+};
+
static void
-change_bits (unsigned char *regval, int dev, int chn, int newval)
+smw_mixer_init(void)
{
- unsigned char mask;
- int shift;
-
- mask = (1 << (*iomap)[dev][chn].nbits) - 1;
- newval = (int) ((newval * mask) + 50) / 100; /*
- * Scale it
- */
-
- 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
- */
+ int i;
+
+ sb_setmixer(0x00, 0x18);/* Mute unused (Telephone) line */
+ sb_setmixer(0x10, 0x38);/* Config register 2 */
+
+ supported_devices = 0;
+ for (i = 0; i < sizeof(smw_mix_regs); i++)
+ if (smw_mix_regs[i] != 0)
+ supported_devices |= (1 << i);
+
+ supported_rec_devices = supported_devices &
+ ~(SOUND_MASK_BASS | SOUND_MASK_TREBLE | SOUND_MASK_PCM |
+ SOUND_MASK_VOLUME);
}
static int
-sb_mixer_get (int dev)
+smw_mixer_set(int dev, int value)
{
- if (!((1 << dev) & supported_devices))
- return RET_ERROR (EINVAL);
+ int left = value & 0x000000ff;
+ int right = (value & 0x0000ff00) >> 8;
+ int reg, val;
+
+ if (left > 100)
+ left = 100;
+ if (right > 100)
+ right = 100;
+
+ if (dev > 31)
+ return -(EINVAL);
+
+ if (!(supported_devices & (1 << dev))) /* Not supported */
+ return -(EINVAL);
+
+ switch (dev) {
+ case SOUND_MIXER_VOLUME:
+ sb_setmixer(0x0b, 96 - (96 * left / 100)); /* 96=mute, 0=max */
+ sb_setmixer(0x0c, 96 - (96 * right / 100));
+ break;
+
+ case SOUND_MIXER_BASS:
+ case SOUND_MIXER_TREBLE:
+ levels[dev] = left | (right << 8);
+
+ /* Set left bass and treble values */
+ val = ((levels[SOUND_MIXER_TREBLE] & 0xff) * 16 / 100) << 4;
+ val |= ((levels[SOUND_MIXER_BASS] & 0xff) * 16 / 100) & 0x0f;
+ sb_setmixer(0x0d, val);
+
+ /* Set right bass and treble values */
+ val = (((levels[SOUND_MIXER_TREBLE] >> 8) & 0xff) * 16 / 100) << 4;
+ val |= (((levels[SOUND_MIXER_BASS] >> 8) & 0xff) * 16 / 100) & 0x0f;
+ sb_setmixer(0x0e, val);
+ break;
+
+ default:
+ reg = smw_mix_regs[dev];
+ if (reg == 0)
+ return -(EINVAL);
+ sb_setmixer(reg, (24 - (24 * left / 100)) | 0x20); /* 24=mute, 0=max */
+ sb_setmixer(reg + 1, (24 - (24 * right / 100)) | 0x40);
+ }
- return levels[dev];
+ levels[dev] = left | (right << 8);
+ return left | (right << 8);
}
+#endif
+
static int
-sb_mixer_set (int dev, int value)
+sb_mixer_set(int dev, int value)
{
- int left = value & 0x000000ff;
- int right = (value & 0x0000ff00) >> 8;
+ int left = value & 0x000000ff;
+ int right = (value & 0x0000ff00) >> 8;
- int regoffs;
- unsigned char val;
+ int regoffs;
+ u_char val;
- if (left > 100)
- left = 100;
- if (right > 100)
- right = 100;
+#ifdef JAZZ16
+ if (Jazz16_detected == 2)
+ return smw_mixer_set(dev, value);
+#endif
- if (dev > 31)
- return RET_ERROR (EINVAL);
+ if (left > 100)
+ left = 100;
+ if (right > 100)
+ right = 100;
- if (!(supported_devices & (1 << dev))) /*
- * Not supported
- */
- return RET_ERROR (EINVAL);
+ if (dev > 31)
+ return -(EINVAL);
- regoffs = (*iomap)[dev][LEFT_CHN].regno;
+ if (!(supported_devices & (1 << dev))) /* Not supported */
+ return -(EINVAL);
- if (regoffs == 0)
- return RET_ERROR (EINVAL);
+ regoffs = (*iomap)[dev][LEFT_CHN].regno;
- val = sb_getmixer (regoffs);
- change_bits (&val, dev, LEFT_CHN, left);
+ if (regoffs == 0)
+ return -(EINVAL);
- levels[dev] = left | (left << 8);
+ val = sb_getmixer(regoffs);
+ change_bits(&val, dev, LEFT_CHN, left);
- if ((*iomap)[dev][RIGHT_CHN].regno != regoffs) /*
- * Change register
- */
- {
- sb_setmixer (regoffs, val); /*
- * Save the old one
- */
- regoffs = (*iomap)[dev][RIGHT_CHN].regno;
+ levels[dev] = left | (left << 8);
- if (regoffs == 0)
- return left | (left << 8); /*
- * Just left channel present
- */
+ if ((*iomap)[dev][RIGHT_CHN].regno != regoffs) { /* Change register */
+ sb_setmixer(regoffs, val); /* Save the old one */
+ regoffs = (*iomap)[dev][RIGHT_CHN].regno;
- val = sb_getmixer (regoffs); /*
- * Read the new one
- */
+ if (regoffs == 0)
+ return left | (left << 8); /* Just left channel present */
+
+ val = sb_getmixer(regoffs); /* Read the new one */
}
+ change_bits(&val, dev, RIGHT_CHN, right);
- change_bits (&val, dev, RIGHT_CHN, right);
- sb_setmixer (regoffs, val);
+ 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;
+ u_char regimageL, regimageR;
- devmask = mask & supported_rec_devices;
+ devmask = mask & supported_rec_devices;
- switch (mixer_model)
- {
+ switch (mixer_model) {
case 3:
- if (devmask != SOUND_MASK_MIC &&
- devmask != SOUND_MASK_LINE &&
- devmask != SOUND_MASK_CD)
- { /*
- * More than one devices selected. Drop the *
- * previous selection
- */
- devmask &= ~recmask;
+ if (devmask != SOUND_MASK_MIC && devmask != SOUND_MASK_LINE &&
+ devmask != SOUND_MASK_CD) {
+ /*
+ * More than one devices selected. Drop the previous
+ * selection
+ */
+ devmask &= ~recmask;
}
-
- if (devmask != SOUND_MASK_MIC &&
- devmask != SOUND_MASK_LINE &&
- devmask != SOUND_MASK_CD)
- { /*
- * More than one devices selected. Default to
- * * mic
- */
- devmask = SOUND_MASK_MIC;
+ if (devmask != SOUND_MASK_MIC && devmask != SOUND_MASK_LINE &&
+ devmask != SOUND_MASK_CD) {
+ /* More than one devices selected. Default to mic */
+ devmask = SOUND_MASK_MIC;
}
-
-
- if (devmask ^ recmask) /*
- * Input source changed
- */
- {
- switch (devmask)
- {
+ if (devmask ^ recmask) { /* Input source changed */
+ switch (devmask) {
case SOUND_MASK_MIC:
- set_recsrc (SRC_MIC);
- break;
+ set_recsrc(SRC_MIC);
+ break;
case SOUND_MASK_LINE:
- set_recsrc (SRC_LINE);
- break;
+ set_recsrc(SRC_LINE);
+ break;
case SOUND_MASK_CD:
- set_recsrc (SRC_CD);
- break;
+ set_recsrc(SRC_CD);
+ break;
default:
- set_recsrc (SRC_MIC);
+ set_recsrc(SRC_MIC);
}
}
-
- break;
+ break;
case 4:
- if (!devmask)
- devmask = SOUND_MASK_MIC;
-
- regimageL = regimageR = 0;
- for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
- if ((1 << i) & devmask)
- {
- regimageL |= sb16_recmasks_L[i];
- regimageR |= sb16_recmasks_R[i];
- }
- sb_setmixer (SB16_IMASK_L, regimageL);
- sb_setmixer (SB16_IMASK_R, regimageR);
- break;
+ if (!devmask)
+ devmask = SOUND_MASK_MIC;
+
+ regimageL = regimageR = 0;
+ for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
+ if ((1 << i) & devmask) {
+ regimageL |= sb16_recmasks_L[i];
+ regimageR |= sb16_recmasks_R[i];
+ }
+ sb_setmixer(SB16_IMASK_L, regimageL);
+ sb_setmixer(SB16_IMASK_R, regimageR);
+ break;
}
- recmask = devmask;
- return recmask;
+ recmask = devmask;
+ return recmask;
}
static int
-sb_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg)
+sb_mixer_ioctl(int dev, u_int cmd, ioctl_arg arg)
{
- if (((cmd >> 8) & 0xff) == 'M')
- {
- if (cmd & IOC_IN)
- switch (cmd & 0xff)
- {
- case SOUND_MIXER_RECSRC:
- return IOCTL_OUT (arg, set_recmask (IOCTL_IN (arg)));
- break;
-
- default:
- return IOCTL_OUT (arg, sb_mixer_set (cmd & 0xff, IOCTL_IN (arg)));
- }
- else
- switch (cmd & 0xff) /*
- * Return parameters
- */
- {
-
- case SOUND_MIXER_RECSRC:
- return IOCTL_OUT (arg, recmask);
- break;
-
- case SOUND_MIXER_DEVMASK:
- return IOCTL_OUT (arg, supported_devices);
- break;
-
- case SOUND_MIXER_STEREODEVS:
- return IOCTL_OUT (arg, supported_devices &
- ~(SOUND_MASK_MIC | SOUND_MASK_SPEAKER));
- break;
-
- case SOUND_MIXER_RECMASK:
- return IOCTL_OUT (arg, supported_rec_devices);
- break;
-
- case SOUND_MIXER_CAPS:
- return IOCTL_OUT (arg, mixer_caps);
- break;
-
- default:
- return IOCTL_OUT (arg, sb_mixer_get (cmd & 0xff));
- }
- }
- else
- return RET_ERROR (EINVAL);
+ if (((cmd >> 8) & 0xff) == 'M') {
+ if (cmd & IOC_IN)
+ switch (cmd & 0xff) {
+ case SOUND_MIXER_RECSRC:
+ return *(int *) arg = set_recmask((*(int *) arg));
+ break;
+
+ default:
+ return *(int *) arg = sb_mixer_set(cmd & 0xff, (*(int *) arg));
+ }
+ else
+ switch (cmd & 0xff) { /* Return parameters */
+
+ case SOUND_MIXER_RECSRC:
+ return *(int *) arg = recmask;
+ break;
+
+ case SOUND_MIXER_DEVMASK:
+ return *(int *) arg = supported_devices;
+ break;
+
+ case SOUND_MIXER_STEREODEVS:
+ if (Jazz16_detected)
+ return *(int *) arg = supported_devices;
+ else
+ return *(int *) arg = supported_devices & ~(SOUND_MASK_MIC | SOUND_MASK_SPEAKER);
+ break;
+
+ case SOUND_MIXER_RECMASK:
+ return *(int *) arg = supported_rec_devices;
+ break;
+
+ case SOUND_MIXER_CAPS:
+ return *(int *) arg = mixer_caps;
+ break;
+
+ default:
+ return *(int *) arg = sb_mixer_get(cmd & 0xff);
+ }
+ } else
+ return -(EINVAL);
}
static struct mixer_operations sb_mixer_operations =
{
- sb_mixer_ioctl
+ "SoundBlaster",
+ sb_mixer_ioctl
};
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);
+ for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
+ sb_mixer_set(i, levels[i]);
+ set_recmask(SOUND_MASK_MIC);
}
/*
- * Returns a code depending on whether a SG NX Pro was detected.
- * 1 == Plain SB Pro
- * 2 == SG NX Pro detected.
- * 3 == SB16
- *
+ * Returns a code depending on whether a SG NX Pro was detected. 1 == Plain
+ * SB Pro 2 == SG NX Pro detected. 3 == SB16
+ *
* Used to update message.
*/
int
-sb_mixer_init (int major_model)
+sb_mixer_init(int major_model)
{
- int mixer_type = 0;
+ int mixer_type = 0;
- sb_setmixer (0x00, 0); /* Reset mixer */
+ sb_setmixer(0x00, 0); /* Reset mixer */
- if (!(mixer_type = detect_mixer ()))
- return 0; /* No mixer. Why? */
+ if (!(mixer_type = detect_mixer()))
+ return 0; /* No mixer. Why? */
- mixer_initialized = 1;
- mixer_model = major_model;
+ mixer_initialized = 1;
+ mixer_model = major_model;
- switch (major_model)
- {
+ switch (major_model) {
case 3:
- mixer_caps = SOUND_CAP_EXCL_INPUT;
+ mixer_caps = SOUND_CAP_EXCL_INPUT;
+
+#ifdef JAZZ16
+ if (Jazz16_detected == 2) { /* SM Wave */
+ supported_devices = 0;
+ supported_rec_devices = 0;
+ iomap = &sbpro_mix;
+ smw_mixer_init();
+ mixer_type = 1;
+ } else
+#endif
#ifdef __SGNXPRO__
- if (mixer_type == 2) /* A SGNXPRO was detected */
- {
- supported_devices = SGNXPRO_MIXER_DEVICES;
- supported_rec_devices = SGNXPRO_RECORDING_DEVICES;
- iomap = &sgnxpro_mix;
- }
- else
+ if (mixer_type == 2) { /* A SGNXPRO was detected */
+ supported_devices = SGNXPRO_MIXER_DEVICES;
+ supported_rec_devices = SGNXPRO_RECORDING_DEVICES;
+ iomap = &sgnxpro_mix;
+ } else
#endif
{
- supported_devices = SBPRO_MIXER_DEVICES;
- supported_rec_devices = SBPRO_RECORDING_DEVICES;
- iomap = &sbpro_mix;
- mixer_type = 1;
+ supported_devices = SBPRO_MIXER_DEVICES;
+ supported_rec_devices = SBPRO_RECORDING_DEVICES;
+ iomap = &sbpro_mix;
+ mixer_type = 1;
}
- break;
+ break;
case 4:
- mixer_caps = 0;
- supported_devices = SB16_MIXER_DEVICES;
- supported_rec_devices = SB16_RECORDING_DEVICES;
- iomap = &sb16_mix;
- mixer_type = 3;
- break;
+ mixer_caps = 0;
+ supported_devices = SB16_MIXER_DEVICES;
+ supported_rec_devices = SB16_RECORDING_DEVICES;
+ iomap = &sb16_mix;
+ mixer_type = 3;
+ break;
default:
- printk ("SB Warning: Unsupported mixer type\n");
- return 0;
- }
+ printf("SB Warning: Unsupported mixer type\n");
+ return 0;
+ }
- if (num_mixers < MAX_MIXER_DEV)
- mixer_devs[num_mixers++] = &sb_mixer_operations;
- sb_mixer_reset ();
- return mixer_type;
+ if (num_mixers < MAX_MIXER_DEV)
+ mixer_devs[num_mixers++] = &sb_mixer_operations;
+ sb_mixer_reset();
+ return mixer_type;
}
#endif
diff --git a/sys/i386/isa/sound/sb_mixer.h b/sys/i386/isa/sound/sb_mixer.h
index 1a5fc8adfd36..155d6c78f4e1 100644
--- a/sys/i386/isa/sound/sb_mixer.h
+++ b/sys/i386/isa/sound/sb_mixer.h
@@ -24,10 +24,9 @@
* 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.
+ *
+ * Modified: Hunyue Yau Jan 6 1994 Added defines for the Sound Galaxy NX Pro
+ * mixer.
*
*/
@@ -39,10 +38,10 @@
#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?
+/*
+ * 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 )
@@ -51,7 +50,8 @@
SOUND_MASK_CD)
#define SB16_MIXER_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_SPEAKER | SOUND_MASK_LINE | SOUND_MASK_MIC | \
- SOUND_MASK_CD | SOUND_MASK_RECLEV | \
+ SOUND_MASK_CD | \
+ SOUND_MASK_IGAIN | SOUND_MASK_OGAIN | \
SOUND_MASK_VOLUME | SOUND_MASK_BASS | SOUND_MASK_TREBLE)
/*
@@ -60,7 +60,7 @@
* NOTE! RECORD_SRC == IN_FILTER
*/
-/*
+/*
* Mixer registers of SB Pro
*/
#define VOC_VOL 0x04
@@ -79,7 +79,7 @@
#define OPSW 0x3c
/*
- * Additional registers on the SG NX Pro
+ * Additional registers on the SG NX Pro
*/
#define COVOX_VOL 0x42
#define TREBLE_LVL 0x44
@@ -103,9 +103,9 @@
#define RIGHT_CHN 1
struct mixer_def {
- unsigned int regno: 8;
- unsigned int bitoffs:4;
- unsigned int nbits:4;
+ unsigned int regno:8;
+ unsigned int bitoffs:4;
+ unsigned int nbits:4;
};
@@ -116,102 +116,136 @@ typedef struct mixer_def mixer_ent;
{{reg_l, bit_l, len_l}, {reg_r, bit_r, len_r}}
#ifdef __SB_MIXER_C__
-mixer_tab sbpro_mix = {
-MIX_ENT(SOUND_MIXER_VOLUME, 0x22, 7, 4, 0x22, 3, 4),
-MIX_ENT(SOUND_MIXER_BASS, 0x00, 0, 0, 0x00, 0, 0),
-MIX_ENT(SOUND_MIXER_TREBLE, 0x00, 0, 0, 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, 0x00, 0, 0, 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)
+mixer_tab sbpro_mix = {
+ MIX_ENT(SOUND_MIXER_VOLUME, 0x22, 7, 4, 0x22, 3, 4),
+ MIX_ENT(SOUND_MIXER_BASS, 0x00, 0, 0, 0x00, 0, 0),
+ MIX_ENT(SOUND_MIXER_TREBLE, 0x00, 0, 0, 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, 0x00, 0, 0, 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)
};
#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)
+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),
+ MIX_ENT(SOUND_MIXER_IGAIN, 0x00, 0, 0, 0x00, 0, 0),
+ MIX_ENT(SOUND_MIXER_OGAIN, 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),
-MIX_ENT(SOUND_MIXER_TREBLE, 0x44, 7, 4, 0x45, 7, 4),
-MIX_ENT(SOUND_MIXER_SYNTH, 0x34, 7, 5, 0x35, 7, 5),
-MIX_ENT(SOUND_MIXER_PCM, 0x32, 7, 5, 0x33, 7, 5),
-MIX_ENT(SOUND_MIXER_SPEAKER, 0x3b, 7, 2, 0x00, 0, 0),
-MIX_ENT(SOUND_MIXER_LINE, 0x38, 7, 5, 0x39, 7, 5),
-MIX_ENT(SOUND_MIXER_MIC, 0x3a, 7, 5, 0x00, 0, 0),
-MIX_ENT(SOUND_MIXER_CD, 0x36, 7, 5, 0x37, 7, 5),
-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, 0x3f, 7, 2, 0x40, 7, 2)
+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),
+ MIX_ENT(SOUND_MIXER_TREBLE, 0x44, 7, 4, 0x45, 7, 4),
+ MIX_ENT(SOUND_MIXER_SYNTH, 0x34, 7, 5, 0x35, 7, 5),
+ MIX_ENT(SOUND_MIXER_PCM, 0x32, 7, 5, 0x33, 7, 5),
+ MIX_ENT(SOUND_MIXER_SPEAKER, 0x3b, 7, 2, 0x00, 0, 0),
+ MIX_ENT(SOUND_MIXER_LINE, 0x38, 7, 5, 0x39, 7, 5),
+ MIX_ENT(SOUND_MIXER_MIC, 0x3a, 7, 5, 0x00, 0, 0),
+ MIX_ENT(SOUND_MIXER_CD, 0x36, 7, 5, 0x37, 7, 5),
+ 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, 0x3f, 7, 2, 0x40, 7, 2), /* Obsolete. Use IGAIN */
+ MIX_ENT(SOUND_MIXER_IGAIN, 0x3f, 7, 2, 0x40, 7, 2),
+ MIX_ENT(SOUND_MIXER_OGAIN, 0x41, 7, 2, 0x42, 7, 2)
};
+#ifdef SM_GAMES /* Master volume is lower and PCM & FM
+ * volumes higher than with SB Pro. This
+ * improves the sound quality */
+
+static unsigned short levels[SOUND_MIXER_NRDEVICES] =
+{
+ 0x2020, /* Master Volume */
+ 0x4b4b, /* Bass */
+ 0x4b4b, /* Treble */
+ 0x6464, /* FM */
+ 0x6464, /* PCM */
+ 0x4b4b, /* PC Speaker */
+ 0x4b4b, /* Ext Line */
+ 0x0000, /* Mic */
+ 0x4b4b, /* CD */
+ 0x4b4b, /* Recording monitor */
+ 0x4b4b, /* SB PCM */
+ 0x4b4b, /* Recording level */
+ 0x4b4b, /* Input gain */
+0x4b4b}; /* Output gain */
+
+#else /* If the user selected just plain SB Pro */
+
static unsigned short levels[SOUND_MIXER_NRDEVICES] =
{
- 0x5a5a, /* Master Volume */
- 0x3232, /* Bass */
- 0x3232, /* Treble */
- 0x4b4b, /* FM */
- 0x4b4b, /* PCM */
- 0x4b4b, /* PC Speaker */
- 0x4b4b, /* Ext Line */
- 0x0000, /* Mic */
- 0x4b4b, /* CD */
- 0x4b4b, /* Recording monitor */
- 0x4b4b, /* SB PCM */
- 0x4b4b}; /* Recording level */
+ 0x5a5a, /* Master Volume */
+ 0x4b4b, /* Bass */
+ 0x4b4b, /* Treble */
+ 0x4b4b, /* FM */
+ 0x4b4b, /* PCM */
+ 0x4b4b, /* PC Speaker */
+ 0x4b4b, /* Ext Line */
+ 0x1010, /* Mic */
+ 0x4b4b, /* CD */
+ 0x4b4b, /* Recording monitor */
+ 0x4b4b, /* SB PCM */
+ 0x4b4b, /* Recording level */
+ 0x4b4b, /* Input gain */
+0x4b4b}; /* Output gain */
+#endif /* SM_GAMES */
static unsigned char sb16_recmasks_L[SOUND_MIXER_NRDEVICES] =
{
- 0x00, /* SOUND_MIXER_VOLUME */
- 0x00, /* SOUND_MIXER_BASS */
- 0x00, /* SOUND_MIXER_TREBLE */
- 0x40, /* SOUND_MIXER_SYNTH */
- 0x00, /* SOUND_MIXER_PCM */
- 0x00, /* SOUND_MIXER_SPEAKER */
- 0x10, /* SOUND_MIXER_LINE */
- 0x01, /* SOUND_MIXER_MIC */
- 0x04, /* SOUND_MIXER_CD */
- 0x00, /* SOUND_MIXER_IMIX */
- 0x00, /* SOUND_MIXER_ALTPCM */
- 0x00 /* SOUND_MIXER_RECLEV */
+ 0x00, /* SOUND_MIXER_VOLUME */
+ 0x00, /* SOUND_MIXER_BASS */
+ 0x00, /* SOUND_MIXER_TREBLE */
+ 0x40, /* SOUND_MIXER_SYNTH */
+ 0x00, /* SOUND_MIXER_PCM */
+ 0x00, /* SOUND_MIXER_SPEAKER */
+ 0x10, /* SOUND_MIXER_LINE */
+ 0x01, /* SOUND_MIXER_MIC */
+ 0x04, /* SOUND_MIXER_CD */
+ 0x00, /* SOUND_MIXER_IMIX */
+ 0x00, /* SOUND_MIXER_ALTPCM */
+ 0x00, /* SOUND_MIXER_RECLEV */
+ 0x00, /* SOUND_MIXER_IGAIN */
+ 0x00 /* SOUND_MIXER_OGAIN */
};
static unsigned char sb16_recmasks_R[SOUND_MIXER_NRDEVICES] =
{
- 0x00, /* SOUND_MIXER_VOLUME */
- 0x00, /* SOUND_MIXER_BASS */
- 0x00, /* SOUND_MIXER_TREBLE */
- 0x20, /* SOUND_MIXER_SYNTH */
- 0x00, /* SOUND_MIXER_PCM */
- 0x00, /* SOUND_MIXER_SPEAKER */
- 0x08, /* SOUND_MIXER_LINE */
- 0x01, /* SOUND_MIXER_MIC */
- 0x02, /* SOUND_MIXER_CD */
- 0x00, /* SOUND_MIXER_IMIX */
- 0x00, /* SOUND_MIXER_ALTPCM */
- 0x00 /* SOUND_MIXER_RECLEV */
+ 0x00, /* SOUND_MIXER_VOLUME */
+ 0x00, /* SOUND_MIXER_BASS */
+ 0x00, /* SOUND_MIXER_TREBLE */
+ 0x20, /* SOUND_MIXER_SYNTH */
+ 0x00, /* SOUND_MIXER_PCM */
+ 0x00, /* SOUND_MIXER_SPEAKER */
+ 0x08, /* SOUND_MIXER_LINE */
+ 0x01, /* SOUND_MIXER_MIC */
+ 0x02, /* SOUND_MIXER_CD */
+ 0x00, /* SOUND_MIXER_IMIX */
+ 0x00, /* SOUND_MIXER_ALTPCM */
+ 0x00, /* SOUND_MIXER_RECLEV */
+ 0x00, /* SOUND_MIXER_IGAIN */
+ 0x00 /* SOUND_MIXER_OGAIN */
};
/*
- * Recording sources (SB Pro)
+ * Recording sources (SB Pro)
*/
#define SRC_MIC 1 /* Select Microphone recording source */
diff --git a/sys/i386/isa/sound/sequencer.c b/sys/i386/isa/sound/sequencer.c
index 45f06c1edfbf..d6bd72d3f305 100644
--- a/sys/i386/isa/sound/sequencer.c
+++ b/sys/i386/isa/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,16 +24,21 @@
* 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
-#include "sound_config.h"
+#include <i386/isa/sound/sound_config.h>
+
+#if NSND > 0
-#ifdef CONFIGURE_SOUNDCARD
+#ifdef CONFIG_SEQUENCER
-#ifndef EXCLUDE_SEQUENCER
+#include <i386/isa/sound/midi_ctrl.h>
+void seq_drain_midi_queues(void);
+int
+sequencer_poll (int dev, struct fileinfo *file, int events, select_table * wait);
static int sequencer_ok = 0;
static struct sound_timer_operations *tmr;
static int tmr_no = -1; /* Currently selected timer */
@@ -47,1289 +52,1313 @@ static int max_mididev = 0;
static int max_synthdev = 0;
/*
- * The seq_mode gives the operating mode of the sequencer:
- * 1 = level1 (the default)
- * 2 = level2 (extended capabilites)
+ * The seq_mode gives the operating mode of the sequencer: 1 = level1 (the
+ * default) 2 = level2 (extended capabilites)
*/
#define SEQ_1 1
#define SEQ_2 2
static int seq_mode = SEQ_1;
-DEFINE_WAIT_QUEUE (seq_sleeper, seq_sleep_flag);
-DEFINE_WAIT_QUEUE (midi_sleeper, midi_sleep_flag);
+static int *seq_sleeper = NULL;
+static volatile struct snd_wait seq_sleep_flag = {0};
+static int *midi_sleeper = NULL;
+static volatile struct snd_wait midi_sleep_flag = {0};
-static int midi_opened[MAX_MIDI_DEV] =
-{0};
-static int midi_written[MAX_MIDI_DEV] =
-{0};
+static int midi_opened[MAX_MIDI_DEV] = {0};
+static int midi_written[MAX_MIDI_DEV] = {0};
-unsigned long prev_input_time = 0;
+u_long prev_input_time = 0;
int prev_event_time;
-unsigned long seq_time = 0;
+u_long seq_time = 0;
-#include "tuning.h"
+#include <i386/isa/sound/tuning.h>
#define EV_SZ 8
#define IEV_SZ 8
-static unsigned char *queue = NULL;
-static unsigned char *iqueue = NULL;
+static u_char *queue = NULL;
+static u_char *iqueue = NULL;
static volatile int qhead = 0, qtail = 0, qlen = 0;
static volatile int iqhead = 0, iqtail = 0, iqlen = 0;
static volatile int seq_playing = 0;
-static int sequencer_busy = 0;
+static volatile int sequencer_busy = 0;
static int output_treshold;
static int pre_event_timeout;
-static unsigned synth_open_mask;
+static u_int synth_open_mask;
-static int seq_queue (unsigned char *note);
-static void seq_startplay (void);
-static int seq_sync (void);
-static void seq_reset (void);
+static int seq_queue(u_char *note, char nonblock);
+static void seq_startplay(void);
+static int seq_sync(void);
+static void seq_reset(void);
static int pmgr_present[MAX_SYNTH_DEV] =
{0};
+static struct callout_handle sequencertimeout_ch
+ = CALLOUT_HANDLE_INITIALIZER(&sequencertimeout_ch);
#if MAX_SYNTH_DEV > 15
#error Too many synthesizer devices enabled.
#endif
+/*
+ * sound_timer stuff -- originally in soundcard.c
+ *
+ * A negative value means a relative timeout in |count| ticks.
+ * A positive value is used for what ?
+ *
+ * In any case, this is only used in sequencer.c
+ */
+
+static int timer_running = 0;
+
+void
+request_sound_timer(int count)
+{
+ static int current = 0;
+ int tmp = count;
+
+ if (count < 0)
+ sequencertimeout_ch = timeout(sequencer_timer, 0, -count);
+ else {
+
+ if (count < current)
+ current = 0; /* Timer restarted */
+
+ count = count - current;
+ current = tmp;
+ if (!count)
+ count = 1;
+ sequencertimeout_ch = timeout(sequencer_timer, 0, count);
+ }
+ timer_running = 1;
+}
+
+void
+sound_stop_timer(void)
+{
+ if (timer_running)
+ untimeout( sequencer_timer, 0, sequencertimeout_ch);
+ timer_running = 0;
+}
+
int
-sequencer_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
+sequencer_read(int dev, struct fileinfo * file, snd_rw_buf * buf, int count)
{
- int c = count, p = 0;
- int ev_len;
- unsigned long flags;
+ int c = count, p = 0;
+ int ev_len;
+ u_long flags;
- dev = dev >> 4;
+ dev = dev >> 4;
- ev_len = seq_mode == SEQ_1 ? 4 : 8;
+ ev_len = seq_mode == SEQ_1 ? 4 : 8;
- if (dev) /*
- * Patch manager device
- */
- return pmgr_read (dev - 1, file, buf, count);
+ if (dev) /* Patch manager device */
+ return pmgr_read(dev - 1, file, buf, count);
- DISABLE_INTR (flags);
- if (!iqlen)
- {
- DO_SLEEP (midi_sleeper, midi_sleep_flag, pre_event_timeout);
+ flags = splhigh();
+ if (!iqlen) {
+ int flag, chn;
- if (!iqlen)
- {
- RESTORE_INTR (flags);
- return 0;
+
+ midi_sleeper = &chn;
+ DO_SLEEP(chn, midi_sleep_flag, pre_event_timeout);
+
+ if (!iqlen) {
+ splx(flags);
+ return 0;
}
}
+ while (iqlen && c >= ev_len) {
- while (iqlen && c >= ev_len)
- {
-
- COPY_TO_USER (buf, p, &iqueue[iqhead * IEV_SZ], ev_len);
- p += ev_len;
- c -= ev_len;
+ if (uiomove((char *) &iqueue[iqhead * IEV_SZ], ev_len, buf))
+ printf("sb: Bad copyout()!\n");
+ p += ev_len;
+ c -= ev_len;
- iqhead = (iqhead + 1) % SEQ_MAX_QUEUE;
- iqlen--;
+ iqhead = (iqhead + 1) % SEQ_MAX_QUEUE;
+ iqlen--;
}
- RESTORE_INTR (flags);
+ splx(flags);
- return count - c;
+ return count - c;
}
static void
-sequencer_midi_output (int dev)
+sequencer_midi_output(int dev)
{
- /*
- * Currently NOP
- */
+ /*
+ * Currently NOP
+ */
}
void
-seq_copy_to_input (unsigned char *event, int len)
+seq_copy_to_input(u_char *event, int len)
{
- unsigned long flags;
+ u_long flags;
- /*
- * Verify that the len is valid for the current mode.
- */
+ /*
+ * Verify that the len is valid for the current mode.
+ */
- if (len != 4 && len != 8)
- return;
- if ((seq_mode == SEQ_1) != (len == 4))
- return;
+ if (len != 4 && len != 8)
+ return;
+ if ((seq_mode == SEQ_1) != (len == 4))
+ return;
- if (iqlen >= (SEQ_MAX_QUEUE - 1))
- return; /* Overflow */
+ if (iqlen >= (SEQ_MAX_QUEUE - 1))
+ return; /* Overflow */
- DISABLE_INTR (flags);
- memcpy (&iqueue[iqtail * IEV_SZ], event, len);
- iqlen++;
- iqtail = (iqtail + 1) % SEQ_MAX_QUEUE;
+ flags = splhigh();
+ bcopy(event, &iqueue[iqtail * IEV_SZ], len);
+ iqlen++;
+ iqtail = (iqtail + 1) % SEQ_MAX_QUEUE;
- if (SOMEONE_WAITING (midi_sleeper, midi_sleep_flag))
- {
- WAKE_UP (midi_sleeper, midi_sleep_flag);
+ if ((midi_sleep_flag.mode & WK_SLEEP)) {
+ midi_sleep_flag.mode = WK_WAKEUP;
+ wakeup(midi_sleeper);
}
- RESTORE_INTR (flags);
+ splx(flags);
}
static void
-sequencer_midi_input (int dev, unsigned char data)
+sequencer_midi_input(int dev, u_char data)
{
- unsigned int tstamp;
- unsigned char event[4];
+ u_int tstamp;
+ u_char event[4];
- if (data == 0xfe) /* Ignore active sensing */
- return;
+ if (data == 0xfe) /* Ignore active sensing */
+ return;
- tstamp = GET_TIME () - seq_time;
- if (tstamp != prev_input_time)
- {
- tstamp = (tstamp << 8) | SEQ_WAIT;
+ tstamp = get_time() - seq_time;
+ if (tstamp != prev_input_time) {
+ tstamp = (tstamp << 8) | SEQ_WAIT;
- seq_copy_to_input ((unsigned char *) &tstamp, 4);
- prev_input_time = tstamp;
+ seq_copy_to_input((u_char *) &tstamp, 4);
+ prev_input_time = tstamp;
}
+ event[0] = SEQ_MIDIPUTC;
+ event[1] = data;
+ event[2] = dev;
+ event[3] = 0;
- event[0] = SEQ_MIDIPUTC;
- event[1] = data;
- event[2] = dev;
- event[3] = 0;
-
- seq_copy_to_input (event, 4);
+ seq_copy_to_input(event, 4);
}
void
-seq_input_event (unsigned char *event, int len)
+seq_input_event(u_char *event, int len)
{
- unsigned long this_time;
+ u_long this_time;
- if (seq_mode == SEQ_2)
- this_time = tmr->get_time (tmr_no);
- else
- this_time = GET_TIME () - seq_time;
+ if (seq_mode == SEQ_2)
+ this_time = tmr->get_time(tmr_no);
+ else
+ this_time = get_time() - seq_time;
- if (this_time != prev_input_time)
- {
- unsigned char tmp_event[8];
+ if (this_time != prev_input_time) {
+ u_char tmp_event[8];
- tmp_event[0] = EV_TIMING;
- tmp_event[1] = TMR_WAIT_ABS;
- tmp_event[2] = 0;
- tmp_event[3] = 0;
- *(unsigned long *) &tmp_event[4] = this_time;
+ tmp_event[0] = EV_TIMING;
+ tmp_event[1] = TMR_WAIT_ABS;
+ tmp_event[2] = 0;
+ tmp_event[3] = 0;
+ *(u_long *) &tmp_event[4] = this_time;
- seq_copy_to_input (tmp_event, 8);
- prev_input_time = this_time;
+ seq_copy_to_input(tmp_event, 8);
+ prev_input_time = this_time;
}
-
- seq_copy_to_input (event, len);
+ seq_copy_to_input(event, len);
}
int
-sequencer_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
+sequencer_write(int dev, struct fileinfo * file, snd_rw_buf * buf, int count)
{
- unsigned char event[EV_SZ], ev_code;
- int p = 0, c, ev_size;
- int err;
- int mode = file->mode & O_ACCMODE;
+ u_char event[EV_SZ], ev_code;
+ int p = 0, c, ev_size;
+ int err;
+ int mode = file->mode & O_ACCMODE;
- dev = dev >> 4;
+ dev = dev >> 4;
- DEB (printk ("sequencer_write(dev=%d, count=%d)\n", dev, count));
+ DEB(printf("sequencer_write(dev=%d, count=%d)\n", dev, count));
- if (mode == OPEN_READ)
- return RET_ERROR (EIO);
+ if (mode == OPEN_READ)
+ return -(EIO);
- if (dev) /*
- * Patch manager device
- */
- return pmgr_write (dev - 1, file, buf, count);
+ if (dev)
+ return pmgr_write(dev - 1, file, buf, count);
- c = count;
+ c = count;
- while (c >= 4)
- {
- COPY_FROM_USER (event, buf, p, 4);
- ev_code = event[0];
+ while (c >= 4) {
- if (ev_code == SEQ_FULLSIZE)
- {
- int err;
+ if (uiomove((char *) event, 4, buf))
+ printf("sb: Bad copyin()!\n");
+ ev_code = event[0];
- dev = *(unsigned short *) &event[2];
- if (dev < 0 || dev >= max_synthdev)
- return RET_ERROR (ENXIO);
+ if (ev_code == SEQ_FULLSIZE) {
+ int err;
- if (!(synth_open_mask & (1 << dev)))
- return RET_ERROR (ENXIO);
+ dev = *(u_short *) &event[2];
+ if (dev < 0 || dev >= max_synthdev)
+ return -(ENXIO);
- err = synth_devs[dev]->load_patch (dev, *(short *) &event[0], buf, p + 4, c, 0);
- if (err < 0)
- return err;
+ if (!(synth_open_mask & (1 << dev)))
+ return -(ENXIO);
- return err;
- }
+ err = synth_devs[dev]->load_patch(dev,
+ *(short *) &event[0], buf, p + 4, c, 0);
+ if (err < 0)
+ return err;
- if (ev_code >= 128)
- {
- if (seq_mode == SEQ_2 && ev_code == SEQ_EXTENDED)
- {
- printk ("Sequencer: Invalid level 2 event %x\n", ev_code);
- return RET_ERROR (EINVAL);
+ return err;
+ }
+ if (ev_code >= 128) {
+ if (seq_mode == SEQ_2 && ev_code == SEQ_EXTENDED) {
+ printf("Sequencer: Invalid level 2 event %x\n", ev_code);
+ return -(EINVAL);
}
+ ev_size = 8;
- ev_size = 8;
-
- if (c < ev_size)
- {
- if (!seq_playing)
- seq_startplay ();
- return count - c;
+ if (c < ev_size) {
+ if (!seq_playing)
+ seq_startplay();
+ return count - c;
}
-
- COPY_FROM_USER (&event[4], buf, p + 4, 4);
-
- }
- else
- {
- if (seq_mode == SEQ_2)
- {
- printk ("Sequencer: 4 byte event in level 2 mode\n");
- return RET_ERROR (EINVAL);
+ if (uiomove((char *) &event[4], 4, buf))
+ printf("sb: Bad copyin()!\n");
+ } else {
+ if (seq_mode == SEQ_2) {
+ printf("Sequencer: 4 byte event in level 2 mode\n");
+ return -(EINVAL);
}
- ev_size = 4;
+ ev_size = 4;
}
- if (event[0] == SEQ_MIDIPUTC)
- {
+ if (event[0] == SEQ_MIDIPUTC) {
- if (!midi_opened[event[2]])
- {
- int mode;
- int dev = event[2];
+ if (!midi_opened[event[2]]) {
+ int mode;
+ int dev = event[2];
- if (dev >= max_mididev)
- {
- printk ("Sequencer Error: Nonexistent MIDI device %d\n", dev);
- return RET_ERROR (ENXIO);
+ if (dev >= max_mididev) {
+ printf("Sequencer Error: Nonexistent MIDI device %d\n",dev);
+ return -(ENXIO);
}
+ mode = file->mode & O_ACCMODE;
- mode = file->mode & O_ACCMODE;
-
- if ((err = midi_devs[dev]->open (dev, mode,
- sequencer_midi_input, sequencer_midi_output)) < 0)
- {
- seq_reset ();
- printk ("Sequencer Error: Unable to open Midi #%d\n", dev);
- return err;
+ if ((err = midi_devs[dev]->open(dev, mode,
+ sequencer_midi_input, sequencer_midi_output)) < 0) {
+ seq_reset();
+ printf("Sequencer Error: Unable to open Midi #%d\n", dev);
+ return err;
}
-
- midi_opened[dev] = 1;
+ midi_opened[dev] = 1;
}
-
}
+ if (!seq_queue(event, 0)) {
+ int processed = count - c;
- if (!seq_queue (event))
- {
+ if (!seq_playing)
+ seq_startplay();
- if (!seq_playing)
- seq_startplay ();
- return count - c;
+ if (!processed && 0)
+ return -(EAGAIN);
+ else
+ return processed;
}
-
- p += ev_size;
- c -= ev_size;
+ p += ev_size;
+ c -= ev_size;
}
- if (!seq_playing)
- seq_startplay ();
+ if (!seq_playing)
+ seq_startplay();
- return count;
+ return count; /* This will "eat" chunks shorter than 4 bytes
+ * (if written alone) Should we really do that ?
+ */
}
static int
-seq_queue (unsigned char *note)
+seq_queue(u_char *note, char nonblock)
{
- /*
- * Test if there is space in the queue
- */
+ /*
+ * Test if there is space in the queue
+ */
- if (qlen >= SEQ_MAX_QUEUE)
- if (!seq_playing)
- seq_startplay (); /*
- * Give chance to drain the queue
- */
+ if (qlen >= SEQ_MAX_QUEUE)
+ if (!seq_playing)
+ seq_startplay(); /* Give chance to drain the queue */
- if (qlen >= SEQ_MAX_QUEUE && !SOMEONE_WAITING (seq_sleeper, seq_sleep_flag))
- {
- /*
- * Sleep until there is enough space on the queue
- */
- DO_SLEEP (seq_sleeper, seq_sleep_flag, 0);
- }
+ if (!nonblock && qlen >= SEQ_MAX_QUEUE &&
+ !(seq_sleep_flag.mode & WK_SLEEP)) {
+ /*
+ * Sleep until there is enough space on the queue
+ */
+
+ int chn;
- if (qlen >= SEQ_MAX_QUEUE)
- return 0; /*
- * To be sure
- */
- memcpy (&queue[qtail * EV_SZ], note, EV_SZ);
+ seq_sleeper = &chn;
+ DO_SLEEP(chn, seq_sleep_flag, 0);
- qtail = (qtail + 1) % SEQ_MAX_QUEUE;
- qlen++;
+ }
+ if (qlen >= SEQ_MAX_QUEUE)
+ return 0; /* To be sure */
+ bcopy(note, &queue[qtail * EV_SZ], EV_SZ);
- return 1;
+ qtail = (qtail + 1) % SEQ_MAX_QUEUE;
+ qlen++;
+
+ return 1;
}
static int
-extended_event (unsigned char *q)
+extended_event(u_char *q)
{
- int dev = q[2];
+ int dev = q[2];
- if (dev < 0 || dev >= max_synthdev)
- return RET_ERROR (ENXIO);
+ if (dev < 0 || dev >= max_synthdev)
+ return -(ENXIO);
- if (!(synth_open_mask & (1 << dev)))
- return RET_ERROR (ENXIO);
+ if (!(synth_open_mask & (1 << dev)))
+ return -(ENXIO);
- switch (q[1])
- {
+ switch (q[1]) {
case SEQ_NOTEOFF:
- synth_devs[dev]->kill_note (dev, q[3], q[4], q[5]);
- break;
+ synth_devs[dev]->kill_note(dev, q[3], q[4], q[5]);
+ break;
case SEQ_NOTEON:
- if (q[4] > 127 && q[4] != 255)
- return 0;
+ if (q[4] > 127 && q[4] != 255)
+ return 0;
- synth_devs[dev]->start_note (dev, q[3], q[4], q[5]);
- break;
+ synth_devs[dev]->start_note(dev, q[3], q[4], q[5]);
+ break;
case SEQ_PGMCHANGE:
- synth_devs[dev]->set_instr (dev, q[3], q[4]);
- break;
+ synth_devs[dev]->set_instr(dev, q[3], q[4]);
+ break;
case SEQ_AFTERTOUCH:
- synth_devs[dev]->aftertouch (dev, q[3], q[4]);
- break;
+ synth_devs[dev]->aftertouch(dev, q[3], q[4]);
+ break;
case SEQ_BALANCE:
- synth_devs[dev]->panning (dev, q[3], (char) q[4]);
- break;
+ synth_devs[dev]->panning(dev, q[3], (char) q[4]);
+ break;
case SEQ_CONTROLLER:
- synth_devs[dev]->controller (dev, q[3], q[4], *(short *) &q[5]);
- break;
+ synth_devs[dev]->controller(dev, q[3], q[4], *(short *) &q[5]);
+ break;
case SEQ_VOLMODE:
- if (synth_devs[dev]->volume_method != NULL)
- synth_devs[dev]->volume_method (dev, q[3]);
- break;
+ if (synth_devs[dev]->volume_method != NULL)
+ synth_devs[dev]->volume_method(dev, q[3]);
+ break;
default:
- return RET_ERROR (EINVAL);
+ return -(EINVAL);
}
- return 0;
+ return 0;
}
static int
-find_voice (int dev, int chn, int note)
+find_voice(int dev, int chn, int note)
{
- unsigned short key;
- int i;
+ u_short key;
+ int i;
- key = (chn << 8) | (note + 1);
+ key = (chn << 8) | (note + 1);
- for (i = 0; i < synth_devs[dev]->alloc.max_voice; i++)
- if (synth_devs[dev]->alloc.map[i] == key)
- return i;
+ for (i = 0; i < synth_devs[dev]->alloc.max_voice; i++)
+ if (synth_devs[dev]->alloc.map[i] == key)
+ return i;
- return -1;
+ return -1;
}
static int
-alloc_voice (int dev, int chn, int note)
+alloc_voice(int dev, int chn, int note)
{
- unsigned short key;
- int voice;
+ u_short key;
+ int voice;
- key = (chn << 8) | (note + 1);
+ key = (chn << 8) | (note + 1);
- voice = synth_devs[dev]->alloc_voice (dev, chn, note,
- &synth_devs[dev]->alloc);
- synth_devs[dev]->alloc.map[voice] = key;
- return voice;
+ voice = synth_devs[dev]->alloc_voice(dev, chn, note,
+ &synth_devs[dev]->alloc);
+ synth_devs[dev]->alloc.map[voice] = key;
+ synth_devs[dev]->alloc.alloc_times[voice] =
+ synth_devs[dev]->alloc.timestamp++;
+ return voice;
}
static void
-seq_chn_voice_event (unsigned char *event)
+seq_chn_voice_event(u_char *event)
{
- unsigned char dev = event[1];
- unsigned char cmd = event[2];
- unsigned char chn = event[3];
- unsigned char note = event[4];
- unsigned char parm = event[5];
- int voice = -1;
-
- if ((int) dev > max_synthdev)
- return;
- if (!(synth_open_mask & (1 << dev)))
- return;
- if (!synth_devs[dev])
- return;
-
- if (seq_mode == SEQ_2)
- if (synth_devs[dev]->alloc_voice)
- voice = find_voice (dev, chn, note);
-
- if (cmd == MIDI_NOTEON && parm == 0)
- {
- cmd = MIDI_NOTEOFF;
- parm = 64;
- }
+ u_char dev = event[1];
+ u_char cmd = event[2];
+ u_char chn = event[3];
+ u_char note = event[4];
+ u_char parm = event[5];
+ int voice = -1;
+
+ if ((int) dev > max_synthdev)
+ return;
+ if (!(synth_open_mask & (1 << dev)))
+ return;
+ if (!synth_devs[dev])
+ return;
- switch (cmd)
- {
+ if (seq_mode == SEQ_2) {
+ if (synth_devs[dev]->alloc_voice)
+ voice = find_voice(dev, chn, note);
+
+ if (cmd == MIDI_NOTEON && parm == 0) {
+ cmd = MIDI_NOTEOFF;
+ parm = 64;
+ }
+ }
+ switch (cmd) {
case MIDI_NOTEON:
- if (note > 127)
- return;
+ if (note > 127 && note != 255) /* Not a seq2 feature */
+ return;
- if (voice == -1 && seq_mode == SEQ_2 && synth_devs[dev]->alloc_voice)
- {
- voice = alloc_voice (dev, chn, note);
+ if (voice == -1 && seq_mode == SEQ_2 && synth_devs[dev]->alloc_voice) {
+ /* Internal synthesizer (FM, GUS, etc) */
+ voice = alloc_voice(dev, chn, note);
}
+ if (voice == -1)
+ voice = chn;
+
+ if (seq_mode == SEQ_2 && (int) dev < num_synths) {
+ /*
+ * The MIDI channel 10 is a percussive channel. Use
+ * the note number to select the proper patch (128 to
+ * 255) to play.
+ */
- if (voice == -1)
- voice = chn;
+ if (chn == 9) {
+ synth_devs[dev]->set_instr(dev, voice, 128 + note);
+ note = 60; /* Middle C */
- if (seq_mode == SEQ_2)
- {
- synth_devs[dev]->set_instr (dev, voice,
- synth_devs[dev]->chn_info[chn].pgm_num);
+ }
}
-
- synth_devs[dev]->start_note (dev, voice, note, parm);
- break;
+ if (seq_mode == SEQ_2)
+ synth_devs[dev]->setup_voice(dev, voice, chn);
+ synth_devs[dev]->start_note(dev, voice, note, parm);
+ break;
case MIDI_NOTEOFF:
- if (voice == -1)
- voice = chn;
- synth_devs[dev]->kill_note (dev, voice, note, parm);
- break;
+ if (voice == -1)
+ voice = chn;
+ synth_devs[dev]->kill_note(dev, voice, note, parm);
+ break;
case MIDI_KEY_PRESSURE:
- /* To be implemented */
- break;
+ if (voice == -1)
+ voice = chn;
+ synth_devs[dev]->aftertouch(dev, voice, parm);
+ break;
default:;
}
}
static void
-seq_chn_common_event (unsigned char *event)
+seq_chn_common_event(u_char *event)
{
- unsigned char dev = event[1];
- unsigned char cmd = event[2];
- unsigned char chn = event[3];
- unsigned char p1 = event[4];
-
- /* unsigned char p2 = event[5]; */
- unsigned short w14 = *(short *) &event[6];
-
- if ((int) dev > max_synthdev)
- return;
- if (!(synth_open_mask & (1 << dev)))
- return;
- if (!synth_devs[dev])
- return;
-
- switch (cmd)
- {
+ u_char dev = event[1];
+ u_char cmd = event[2];
+ u_char chn = event[3];
+ u_char p1 = event[4];
+
+ /* u_char p2 = event[5]; */
+ u_short w14 = *(short *) &event[6];
+
+ if ((int) dev > max_synthdev)
+ return;
+ if (!(synth_open_mask & (1 << dev)))
+ return;
+ if (!synth_devs[dev])
+ return;
+
+ switch (cmd) {
case MIDI_PGM_CHANGE:
- if (seq_mode == SEQ_2)
- {
- synth_devs[dev]->chn_info[chn].pgm_num = p1;
- }
- else
- synth_devs[dev]->set_instr (dev, chn, p1);
- break;
+ if (seq_mode == SEQ_2) {
+ synth_devs[dev]->chn_info[chn].pgm_num = p1;
+ if ((int) dev >= num_synths)
+ synth_devs[dev]->set_instr(dev, chn, p1);
+ } else
+ synth_devs[dev]->set_instr(dev, chn, p1);
+
+ break;
case MIDI_CTL_CHANGE:
- if (p1 == CTRL_MAIN_VOLUME)
- {
- w14 = (unsigned short) (((int) w14 * 16383) / 100);
- p1 = CTL_MAIN_VOLUME;
- }
- if (p1 == CTRL_EXPRESSION)
- {
- w14 *= 128;
- p1 = CTL_EXPRESSION;
- }
+ if (seq_mode == SEQ_2) {
+ if (chn > 15 || p1 > 127)
+ break;
- if (seq_mode == SEQ_2)
- {
- if (chn > 15 || p1 > 127)
- break;
-
- synth_devs[dev]->chn_info[chn].controllers[p1] = w14 & 0xff;
-
- if (dev < num_synths)
- {
- int val = w14 & 0xff;
-
- if (p1 < 64) /* Combine MSB and LSB */
- {
- val = ((synth_devs[dev]->
- chn_info[chn].controllers[p1 & ~32] & 0x7f) << 7)
- | (synth_devs[dev]->
- chn_info[chn].controllers[p1 | 32] & 0x7f);
- p1 &= ~32;
+ synth_devs[dev]->chn_info[chn].controllers[p1] = w14 & 0x7f;
+
+ if (p1 < 32) /* Setting MSB should clear LSB to 0 */
+ synth_devs[dev]->chn_info[chn].controllers[p1 + 32] = 0;
+
+ if ((int) dev < num_synths) {
+ int val = w14 & 0x7f;
+ int i, key;
+
+ if (p1 < 64) { /* Combine MSB and LSB */
+ val = ((synth_devs[dev]->
+ chn_info[chn].controllers[p1 & ~32] & 0x7f) << 7)
+ | (synth_devs[dev]->
+ chn_info[chn].controllers[p1 | 32] & 0x7f);
+ p1 &= ~32;
}
- else
- val = synth_devs[dev]->chn_info[chn].controllers[p1];
+ /* Handle all playing notes on this channel */
- synth_devs[dev]->controller (dev, chn, p1, val);
- }
- else
- synth_devs[dev]->controller (dev, chn, p1, w14);
- }
- else
- synth_devs[dev]->controller (dev, chn, p1, w14);
- break;
+ key = ((int) chn << 8);
+
+ for (i = 0; i < synth_devs[dev]->alloc.max_voice; i++)
+ if ((synth_devs[dev]->alloc.map[i] & 0xff00) == key)
+ synth_devs[dev]->controller(dev, i, p1, val);
+ } else
+ synth_devs[dev]->controller(dev, chn, p1, w14);
+ } else /* Mode 1 */
+ synth_devs[dev]->controller(dev, chn, p1, w14);
+ break;
case MIDI_PITCH_BEND:
- synth_devs[dev]->bender (dev, chn, w14);
- break;
+ if (seq_mode == SEQ_2) {
+ synth_devs[dev]->chn_info[chn].bender_value = w14;
+
+ if ((int) dev < num_synths) { /* Handle all playing
+ * notes on this channel */
+ int i, key;
+
+ key = (chn << 8);
+
+ for (i = 0; i < synth_devs[dev]->alloc.max_voice; i++)
+ if ((synth_devs[dev]->alloc.map[i] & 0xff00) == key)
+ synth_devs[dev]->bender(dev, i, w14);
+ } else
+ synth_devs[dev]->bender(dev, chn, w14);
+ } else /* MODE 1 */
+ synth_devs[dev]->bender(dev, chn, w14);
+ break;
default:;
}
}
static int
-seq_timing_event (unsigned char *event)
+seq_timing_event(u_char *event)
{
- unsigned char cmd = event[1];
- unsigned int parm = *(int *) &event[4];
+ u_char cmd = event[1];
+ u_int parm = *(int *) &event[4];
- if (seq_mode == SEQ_2)
- {
- int ret;
+ if (seq_mode == SEQ_2) {
+ int ret;
- if ((ret = tmr->event (tmr_no, event)) == TIMER_ARMED)
- {
- if ((SEQ_MAX_QUEUE - qlen) >= output_treshold)
- {
- unsigned long flags;
-
- DISABLE_INTR (flags);
- if (SOMEONE_WAITING (seq_sleeper, seq_sleep_flag))
- {
- WAKE_UP (seq_sleeper, seq_sleep_flag);
+ if ((ret = tmr->event(tmr_no, event)) == TIMER_ARMED) {
+ if ((SEQ_MAX_QUEUE - qlen) >= output_treshold) {
+ u_long flags;
+
+ flags = splhigh();
+ if ((seq_sleep_flag.mode & WK_SLEEP)) {
+ seq_sleep_flag.mode = WK_WAKEUP;
+ wakeup(seq_sleeper);
}
- RESTORE_INTR (flags);
+ splx(flags);
}
}
- return ret;
+ return ret;
}
-
- switch (cmd)
- {
+ switch (cmd) {
case TMR_WAIT_REL:
- parm += prev_event_time;
+ parm += prev_event_time;
- /*
- * NOTE! No break here. Execution of TMR_WAIT_REL continues in the
- * next case (TMR_WAIT_ABS)
- */
+ /*
+ * NOTE! No break here. Execution of TMR_WAIT_REL continues
+ * in the next case (TMR_WAIT_ABS)
+ */
case TMR_WAIT_ABS:
- if (parm > 0)
- {
- long time;
+ if (parm > 0) {
+ long time;
- seq_playing = 1;
- time = parm;
- prev_event_time = time;
+ seq_playing = 1;
+ time = parm;
+ prev_event_time = time;
- request_sound_timer (time);
+ request_sound_timer(time);
- if ((SEQ_MAX_QUEUE - qlen) >= output_treshold)
- {
- unsigned long flags;
+ if ((SEQ_MAX_QUEUE - qlen) >= output_treshold) {
+ u_long flags;
- DISABLE_INTR (flags);
- if (SOMEONE_WAITING (seq_sleeper, seq_sleep_flag))
- {
- WAKE_UP (seq_sleeper, seq_sleep_flag);
+ flags = splhigh();
+ if ((seq_sleep_flag.mode & WK_SLEEP)) {
+ seq_sleep_flag.mode = WK_WAKEUP;
+ wakeup(seq_sleeper);
}
- RESTORE_INTR (flags);
+ splx(flags);
}
-
- return TIMER_ARMED;
+ return TIMER_ARMED;
}
- break;
+ break;
case TMR_START:
- seq_time = GET_TIME ();
- prev_input_time = 0;
- prev_event_time = 0;
- break;
+ seq_time = get_time();
+ prev_input_time = 0;
+ prev_event_time = 0;
+ break;
case TMR_STOP:
- break;
+ break;
case TMR_CONTINUE:
- break;
+ break;
case TMR_TEMPO:
- break;
+ break;
case TMR_ECHO:
- if (seq_mode == SEQ_2)
- seq_copy_to_input (event, 8);
- else
- {
- parm = (parm << 8 | SEQ_ECHO);
- seq_copy_to_input ((unsigned char *) &parm, 4);
+ if (seq_mode == SEQ_2)
+ seq_copy_to_input(event, 8);
+ else {
+ parm = (parm << 8 | SEQ_ECHO);
+ seq_copy_to_input((u_char *) &parm, 4);
}
- break;
+ break;
default:;
}
- return TIMER_NOT_ARMED;
+ return TIMER_NOT_ARMED;
}
static void
-seq_local_event (unsigned char *event)
+seq_local_event(u_char *event)
{
- /* unsigned char cmd = event[1]; */
+ u_char cmd = event[1];
+ u_int parm = *((u_int *) &event[4]);
+
+ switch (cmd) {
+ case LOCL_STARTAUDIO:
+#ifdef CONFIG_AUDIO
+ DMAbuf_start_devices(parm);
+#endif
+ break;
- printk ("seq_local_event() called. WHY????????\n");
+ default:;
+ }
}
static void
-seq_startplay (void)
+seq_sysex_message(u_char *event)
{
- int this_one;
- unsigned long *delay;
- unsigned char *q;
-
- while (qlen > 0)
- {
+ int dev = event[1];
+ int i, l = 0;
+ u_char *buf = &event[2];
- seq_playing = 1;
+ if ((int) dev > max_synthdev)
+ return;
+ if (!(synth_open_mask & (1 << dev)))
+ return;
+ if (!synth_devs[dev])
+ return;
+ if (!synth_devs[dev]->send_sysex)
+ return;
- qhead = ((this_one = qhead) + 1) % SEQ_MAX_QUEUE;
- qlen--;
+ l = 0;
+ for (i = 0; i < 6 && buf[i] != 0xff; i++)
+ l = i + 1;
- q = &queue[this_one * EV_SZ];
+ if (l > 0)
+ synth_devs[dev]->send_sysex(dev, buf, l);
+}
- switch (q[0])
- {
- case SEQ_NOTEOFF:
- if (synth_open_mask & (1 << 0))
+static int
+play_event(u_char *q)
+{
+ /*
+ * NOTE! This routine returns 0 = normal event played. 1 = Timer
+ * armed. Suspend playback until timer callback. 2 = MIDI output
+ * buffer full. Restore queue and suspend until timer
+ */
+ u_long *delay;
+
+ switch (q[0]) {
+ case SEQ_NOTEOFF:
+ if (synth_open_mask & (1 << 0))
if (synth_devs[0])
- synth_devs[0]->kill_note (0, q[1], 255, q[3]);
- break;
+ synth_devs[0]->kill_note(0, q[1], 255, q[3]);
+ break;
- case SEQ_NOTEON:
- if (q[4] < 128 || q[4] == 255)
+ case SEQ_NOTEON:
+ if (q[4] < 128 || q[4] == 255)
if (synth_open_mask & (1 << 0))
- if (synth_devs[0])
- synth_devs[0]->start_note (0, q[1], q[2], q[3]);
- break;
-
- case SEQ_WAIT:
- delay = (unsigned long *) q; /*
- * Bytes 1 to 3 are containing the *
- * delay in GET_TIME()
- */
- *delay = (*delay >> 8) & 0xffffff;
-
- if (*delay > 0)
- {
- long time;
-
- seq_playing = 1;
- time = *delay;
- prev_event_time = time;
-
- request_sound_timer (time);
-
- if ((SEQ_MAX_QUEUE - qlen) >= output_treshold)
- {
- unsigned long flags;
-
- DISABLE_INTR (flags);
- if (SOMEONE_WAITING (seq_sleeper, seq_sleep_flag))
- {
- WAKE_UP (seq_sleeper, seq_sleep_flag);
- }
- RESTORE_INTR (flags);
+ if (synth_devs[0])
+ synth_devs[0]->start_note(0, q[1], q[2], q[3]);
+ break;
+
+ case SEQ_WAIT:
+ delay = (u_long *) q; /* Bytes 1 to 3 are
+ * containing the * delay in
+ * get_time() */
+ *delay = (*delay >> 8) & 0xffffff;
+
+ if (*delay > 0) {
+ long time;
+
+ seq_playing = 1;
+ time = *delay;
+ prev_event_time = time;
+
+ request_sound_timer(time);
+
+ if ((SEQ_MAX_QUEUE - qlen) >= output_treshold) {
+ u_long flags;
+
+ flags = splhigh();
+ if ((seq_sleep_flag.mode & WK_SLEEP)) {
+ seq_sleep_flag.mode = WK_WAKEUP;
+ wakeup(seq_sleeper);
}
- /*
- * The timer is now active and will reinvoke this function
- * after the timer expires. Return to the caller now.
- */
- return;
+ splx(flags);
}
- break;
+ /*
+ * The timer is now active and will reinvoke this
+ * function after the timer expires. Return to the
+ * caller now.
+ */
+ return 1;
+ }
+ break;
- case SEQ_PGMCHANGE:
- if (synth_open_mask & (1 << 0))
+ case SEQ_PGMCHANGE:
+ if (synth_open_mask & (1 << 0))
if (synth_devs[0])
- synth_devs[0]->set_instr (0, q[1], q[2]);
- break;
-
- case SEQ_SYNCTIMER: /*
- * Reset timer
- */
- seq_time = GET_TIME ();
- prev_input_time = 0;
- prev_event_time = 0;
- break;
-
- case SEQ_MIDIPUTC: /*
- * Put a midi character
- */
- if (midi_opened[q[2]])
- {
- int dev;
-
- dev = q[2];
-
- if (!midi_devs[dev]->putc (dev, q[1]))
- {
- /*
- * Output FIFO is full. Wait one timer cycle and try again.
- */
-
- qlen++;
- qhead = this_one; /*
- * Restore queue
- */
- seq_playing = 1;
- request_sound_timer (-1);
- return;
- }
- else
+ synth_devs[0]->set_instr(0, q[1], q[2]);
+ break;
+
+ case SEQ_SYNCTIMER: /* Reset timer */
+ seq_time = get_time();
+ prev_input_time = 0;
+ prev_event_time = 0;
+ break;
+
+ case SEQ_MIDIPUTC: /* Put a midi character */
+ if (midi_opened[q[2]]) {
+ int dev;
+
+ dev = q[2];
+
+ if (!midi_devs[dev]->putc(dev, q[1])) {
+ /*
+ * Output FIFO is full. Wait one timer cycle and try again.
+ */
+
+ seq_playing = 1;
+ request_sound_timer(-1);
+ return 2;
+ } else
midi_written[dev] = 1;
- }
- break;
-
- case SEQ_ECHO:
- seq_copy_to_input (q, 4); /*
- * Echo back to the process
- */
- break;
-
- case SEQ_PRIVATE:
- if ((int) q[1] < max_synthdev)
- synth_devs[q[1]]->hw_control (q[1], q);
- break;
-
- case SEQ_EXTENDED:
- extended_event (q);
- break;
-
- case EV_CHN_VOICE:
- seq_chn_voice_event (q);
- break;
-
- case EV_CHN_COMMON:
- seq_chn_common_event (q);
- break;
-
- case EV_TIMING:
- if (seq_timing_event (q) == TIMER_ARMED)
- {
- return;
- }
- break;
+ }
+ break;
+
+ case SEQ_ECHO:
+ seq_copy_to_input(q, 4); /* Echo back to the process */
+ break;
+
+ case SEQ_PRIVATE:
+ if ((int) q[1] < max_synthdev)
+ synth_devs[q[1]]->hw_control(q[1], q);
+ break;
+
+ case SEQ_EXTENDED:
+ extended_event(q);
+ break;
+
+ case EV_CHN_VOICE:
+ seq_chn_voice_event(q);
+ break;
- case EV_SEQ_LOCAL:
- seq_local_event (q);
- break;
+ case EV_CHN_COMMON:
+ seq_chn_common_event(q);
+ break;
- default:;
+ case EV_TIMING:
+ if (seq_timing_event(q) == TIMER_ARMED) {
+ return 1;
}
+ break;
+ case EV_SEQ_LOCAL:
+ seq_local_event(q);
+ break;
+
+ case EV_SYSEX:
+ seq_sysex_message(q);
+ break;
+
+ default:;
}
- seq_playing = 0;
+ return 0;
+}
- if ((SEQ_MAX_QUEUE - qlen) >= output_treshold)
- {
- unsigned long flags;
+static void
+seq_startplay(void)
+{
+ u_long flags;
+ int this_one, action;
- DISABLE_INTR (flags);
- if (SOMEONE_WAITING (seq_sleeper, seq_sleep_flag))
- {
- WAKE_UP (seq_sleeper, seq_sleep_flag);
+ while (qlen > 0) {
+
+ flags = splhigh();
+ qhead = ((this_one = qhead) + 1) % SEQ_MAX_QUEUE;
+ qlen--;
+ splx(flags);
+
+ seq_playing = 1;
+
+ if ((action = play_event(&queue[this_one * EV_SZ]))) {
+ /*
+ * Suspend playback. Next timer routine invokes this routine again
+ */
+ if (action == 2) {
+ qlen++;
+ qhead = this_one;
+ }
+ return;
}
- RESTORE_INTR (flags);
}
+ seq_playing = 0;
+
+ if ((SEQ_MAX_QUEUE - qlen) >= output_treshold) {
+ u_long flags;
+
+ flags = splhigh();
+ if ((seq_sleep_flag.mode & WK_SLEEP)) {
+ seq_sleep_flag.mode = WK_WAKEUP;
+ wakeup(seq_sleeper);
+ }
+ splx(flags);
+ }
}
static void
-reset_controllers (int dev, unsigned char *controller, int update_dev)
+reset_controllers(int dev, u_char *controller, int update_dev)
{
-#include "midi_ctrl.h"
- int i;
+ int i;
- for (i = 0; i < 128; i++)
- controller[i] = ctrl_def_values[i];
+ for (i = 0; i < 128; i++)
+ controller[i] = ctrl_def_values[i];
}
static void
-setup_mode2 (void)
+setup_mode2(void)
{
- int dev;
-
- max_synthdev = num_synths;
+ int dev;
- for (dev = 0; dev < num_midis; dev++)
- if (midi_devs[dev]->converter != NULL)
- {
- synth_devs[max_synthdev++] =
- midi_devs[dev]->converter;
- }
+ max_synthdev = num_synths;
- for (dev = 0; dev < max_synthdev; dev++)
- {
- int chn;
+ for (dev = 0; dev < num_midis; dev++)
+ if (midi_devs[dev]->converter != NULL)
+ synth_devs[max_synthdev++] = midi_devs[dev]->converter;
+ for (dev = 0; dev < max_synthdev; dev++) {
+ int chn;
- for (chn = 0; chn < 16; chn++)
- {
- synth_devs[dev]->chn_info[chn].pgm_num = 0;
- reset_controllers (dev,
- synth_devs[dev]->chn_info[chn].controllers,
- 0);
+ for (chn = 0; chn < 16; chn++) {
+ synth_devs[dev]->chn_info[chn].pgm_num = 0;
+ reset_controllers(dev,
+ synth_devs[dev]->chn_info[chn].controllers, 0);
+ synth_devs[dev]->chn_info[chn].bender_value = (1<<7); /* Neutral */
}
}
- max_mididev = 0;
- seq_mode = SEQ_2;
+ max_mididev = 0;
+ seq_mode = SEQ_2;
}
int
-sequencer_open (int dev, struct fileinfo *file)
+sequencer_open(int dev, struct fileinfo * file)
{
- int retval, mode, i;
- int level, tmp;
+ int retval, mode, i;
+ int level, tmp;
+ u_long flags;
- level = ((dev & 0x0f) == SND_DEV_SEQ2) ? 2 : 1;
+ level = ((dev & 0x0f) == SND_DEV_SEQ2) ? 2 : 1;
- 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(printf("sequencer_open(dev=%d)\n", dev));
- if (!sequencer_ok)
- {
- printk ("Soundcard: Sequencer not initialized\n");
- return RET_ERROR (ENXIO);
+ if (!sequencer_ok) {
+ printf("Soundcard: Sequencer not initialized\n");
+ return -(ENXIO);
}
+ if (dev) { /* Patch manager device */
+ int err;
- if (dev) /*
- * Patch manager device
- */
- {
- int err;
+ printf("Patch manager interface is currently broken. Sorry\n");
+ return -(ENXIO);
- dev--;
+ dev--;
- if (dev >= MAX_SYNTH_DEV)
- return RET_ERROR (ENXIO);
- if (pmgr_present[dev])
- return RET_ERROR (EBUSY);
- if ((err = pmgr_open (dev)) < 0)
- return err; /*
- * Failed
- */
+ if (dev >= MAX_SYNTH_DEV)
+ return -(ENXIO);
+ if (pmgr_present[dev])
+ return -(EBUSY);
+ if ((err = pmgr_open(dev)) < 0)
+ return err;
- pmgr_present[dev] = 1;
- return err;
+ pmgr_present[dev] = 1;
+ return err;
}
-
- if (sequencer_busy)
- {
- printk ("Sequencer busy\n");
- return RET_ERROR (EBUSY);
+ flags = splhigh();
+ if (sequencer_busy) {
+ printf("Sequencer busy\n");
+ splx(flags);
+ return -(EBUSY);
}
+ sequencer_busy = 1;
+ splx(flags);
- max_mididev = num_midis;
- max_synthdev = num_synths;
- pre_event_timeout = 0;
- seq_mode = SEQ_1;
+ max_mididev = num_midis;
+ max_synthdev = num_synths;
+ pre_event_timeout = 0;
+ seq_mode = SEQ_1;
- if (pending_timer != -1)
- {
- tmr_no = pending_timer;
- pending_timer = -1;
+ if (pending_timer != -1) {
+ tmr_no = pending_timer;
+ pending_timer = -1;
}
-
- if (tmr_no == -1) /* Not selected yet */
- {
- int i, best;
-
- best = -1;
- for (i = 0; i < num_sound_timers; i++)
- if (sound_timer_devs[i]->priority > best)
- {
- tmr_no = i;
- best = sound_timer_devs[i]->priority;
- }
-
- if (tmr_no == -1) /* Should not be */
- tmr_no = 0;
+ if (tmr_no == -1) { /* Not selected yet */
+ int i, best;
+
+ best = -1;
+ for (i = 0; i < num_sound_timers; i++)
+ if (sound_timer_devs[i]->priority > best) {
+ tmr_no = i;
+ best = sound_timer_devs[i]->priority;
+ }
+ if (tmr_no == -1) /* Should not be */
+ tmr_no = 0;
}
+ tmr = sound_timer_devs[tmr_no];
- tmr = sound_timer_devs[tmr_no];
-
- if (level == 2)
- {
- printk ("Using timer #%d\n", tmr_no);
- if (tmr == NULL)
- {
- printk ("sequencer: No timer for level 2\n");
- return RET_ERROR (ENXIO);
+ if (level == 2) {
+ if (tmr == NULL) {
+ printf("sequencer: No timer for level 2\n");
+ sequencer_busy = 0;
+ return -(ENXIO);
}
- setup_mode2 ();
+ setup_mode2();
}
+ if (seq_mode == SEQ_1 && (mode == OPEN_READ || mode == OPEN_READWRITE))
+ if (!max_mididev) {
+ printf("Sequencer: No Midi devices. Input not possible\n");
+ sequencer_busy = 0;
+ return -(ENXIO);
+ }
+ if (!max_synthdev && !max_mididev)
+ return -(ENXIO);
- if (seq_mode == SEQ_1 && (mode == OPEN_READ || mode == OPEN_READWRITE))
- if (!max_mididev)
- {
- printk ("Sequencer: No Midi devices. Input not possible\n");
- return RET_ERROR (ENXIO);
- }
+ synth_open_mask = 0;
- if (!max_synthdev && !max_mididev)
- return RET_ERROR (ENXIO);
+ for (i = 0; i < max_mididev; i++) {
+ midi_opened[i] = 0;
+ midi_written[i] = 0;
+ }
- synth_open_mask = 0;
+ /*
+ * if (mode == OPEN_WRITE || mode == OPEN_READWRITE)
+ */
+ for (i = 0; i < max_synthdev; i++) /* Open synth devices */
+ if ((tmp = synth_devs[i]->open(i, mode)) < 0) {
+ printf("Sequencer: Warning! Cannot open synth device #%d (%d)\n",
+ i, tmp);
+ if (synth_devs[i]->midi_dev)
+ printf("(Maps to MIDI dev #%d)\n", synth_devs[i]->midi_dev);
+ } else {
+ synth_open_mask |= (1 << i);
+ if (synth_devs[i]->midi_dev) /* Is a midi interface */
+ midi_opened[synth_devs[i]->midi_dev] = 1;
+ }
- for (i = 0; i < max_mididev; i++)
- {
- midi_opened[i] = 0;
- midi_written[i] = 0;
- }
+ seq_time = get_time();
+ prev_input_time = 0;
+ prev_event_time = 0;
- /*
- * if (mode == OPEN_WRITE || mode == OPEN_READWRITE)
- */
- for (i = 0; i < max_synthdev; i++) /*
- * Open synth devices
- */
- if ((tmp = synth_devs[i]->open (i, mode)) < 0)
- {
- printk ("Sequencer: Warning! Cannot open synth device #%d (%d)\n", i, tmp);
- if (synth_devs[i]->midi_dev)
- printk ("(Maps to midi dev #%d\n", synth_devs[i]->midi_dev);
- }
- else
- {
- synth_open_mask |= (1 << i);
- if (synth_devs[i]->midi_dev) /*
- * Is a midi interface
- */
- midi_opened[synth_devs[i]->midi_dev] = 1;
- }
-
- seq_time = GET_TIME ();
- prev_input_time = 0;
- prev_event_time = 0;
-
- if (seq_mode == SEQ_1 && (mode == OPEN_READ || mode == OPEN_READWRITE))
- { /*
- * Initialize midi input devices
- */
- for (i = 0; i < max_mididev; i++)
- if (!midi_opened[i])
- {
- if ((retval = midi_devs[i]->open (i, mode,
+ if (seq_mode == SEQ_1 && (mode == OPEN_READ || mode == OPEN_READWRITE)) {
+ /* Initialize midi input devices */
+ for (i = 0; i < max_mididev; i++)
+ if (!midi_opened[i]) {
+ if ((retval = midi_devs[i]->open(i, mode,
sequencer_midi_input, sequencer_midi_output)) >= 0)
- midi_opened[i] = 1;
- }
+ midi_opened[i] = 1;
+ }
}
-
- if (seq_mode == SEQ_2)
- {
- tmr->open (tmr_no, seq_mode);
+ if (seq_mode == SEQ_2) {
+ tmr->open(tmr_no, seq_mode);
}
+ seq_sleep_flag.aborting = 0;
+ seq_sleep_flag.mode = WK_NONE;
+ midi_sleep_flag.aborting = 0;
+ midi_sleep_flag.mode = WK_NONE;
+ 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)
+seq_drain_midi_queues(void)
{
- int i, n;
+ int i, n;
- /*
- * Give the Midi drivers time to drain their output queues
- */
+ /*
+ * Give the Midi drivers time to drain their output queues
+ */
- n = 1;
+ n = 1;
+
+ while (!(seq_sleep_flag.aborting) && n) {
+ n = 0;
+
+ for (i = 0; i < max_mididev; i++)
+ if (midi_opened[i] && midi_written[i])
+ if (midi_devs[i]->buffer_status != NULL)
+ if (midi_devs[i]->buffer_status(i))
+ n++;
+
+ /*
+ * Let's have a delay
+ */
+ if (n) {
+ int chn;
+
+ seq_sleeper = &chn;
+ DO_SLEEP(chn, seq_sleep_flag, hz / 10);
- while (!PROCESS_ABORTING (midi_sleeper, midi_sleep_flag) && n)
- {
- n = 0;
-
- for (i = 0; i < max_mididev; i++)
- if (midi_opened[i] && midi_written[i])
- if (midi_devs[i]->buffer_status != NULL)
- if (midi_devs[i]->buffer_status (i))
- n++;
-
- /*
- * Let's have a delay
- */
- if (n)
- {
- DO_SLEEP (seq_sleeper, seq_sleep_flag, HZ / 10);
}
}
}
void
-sequencer_release (int dev, struct fileinfo *file)
+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(printf("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 (if we don't have nonblock)
+ */
- /*
- * * Wait until the queue is empty
- */
-
- if (mode != OPEN_READ)
- 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
- */
-
- for (i = 0; i < max_synthdev; i++)
- if (synth_open_mask & (1 << i)) /*
- * Actually opened
- */
- if (synth_devs[i])
- {
- synth_devs[i]->close (i);
-
- if (synth_devs[i]->midi_dev)
- midi_opened[synth_devs[i]->midi_dev] = 0;
+ if (mode != OPEN_READ && !0)
+ while (!(seq_sleep_flag.aborting) && qlen) {
+ seq_sync();
}
- for (i = 0; i < num_synths; i++)
- if (pmgr_present[i])
- pmgr_inform (i, PM_E_CLOSED, 0, 0, 0, 0);
+ 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 */
+
+ for (i = 0; i < max_synthdev; i++)
+ if (synth_open_mask & (1 << i)) /* Actually opened */
+ if (synth_devs[i]) {
+ synth_devs[i]->close(i);
- for (i = 0; i < max_mididev; i++)
- if (midi_opened[i])
- midi_devs[i]->close (i);
+ if (synth_devs[i]->midi_dev)
+ midi_opened[synth_devs[i]->midi_dev] = 0;
+ }
+ for (i = 0; i < num_synths; i++)
+ if (pmgr_present[i])
+ pmgr_inform(i, PM_E_CLOSED, 0, 0, 0, 0);
- if (seq_mode == SEQ_2)
- tmr->close (tmr_no);
+ for (i = 0; i < max_mididev; i++)
+ if (midi_opened[i])
+ midi_devs[i]->close(i);
- sequencer_busy = 0;
+ if (seq_mode == SEQ_2)
+ tmr->close(tmr_no);
+
+ sequencer_busy = 0;
}
static int
-seq_sync (void)
+seq_sync(void)
{
- if (qlen && !seq_playing && !PROCESS_ABORTING (seq_sleeper, seq_sleep_flag))
- seq_startplay ();
+ u_long flags;
+
+ if (qlen && !seq_playing && !(seq_sleep_flag.aborting))
+ seq_startplay();
+
+ flags = splhigh();
+ if (qlen && !(seq_sleep_flag.mode & WK_SLEEP)) {
+ int chn;
+
+ seq_sleeper = &chn;
+ DO_SLEEP(chn, seq_sleep_flag, 0);
- if (qlen && !SOMEONE_WAITING (seq_sleeper, seq_sleep_flag)) /*
- * Queue not
- * empty
- */
- {
- DO_SLEEP (seq_sleeper, seq_sleep_flag, 0);
}
+ splx(flags);
- return qlen;
+ return qlen;
}
static void
-midi_outc (int dev, unsigned char data)
+midi_outc(int dev, u_char data)
{
- /*
- * NOTE! Calls sleep(). Don't call this from interrupt.
- */
-
- int n;
-
- /*
- * This routine sends one byte to the Midi channel.
- */
- /*
- * If the output Fifo is full, it waits until there
- */
- /*
- * is space in the queue
- */
-
- n = 300; /*
- * Timeout in jiffies
- */
-
- while (n && !midi_devs[dev]->putc (dev, data))
- {
- DO_SLEEP (seq_sleeper, seq_sleep_flag, 4);
- n--;
+ /*
+ * NOTE! Calls sleep(). Don't call this from interrupt.
+ */
+
+ int n;
+ u_long flags;
+
+ /*
+ * This routine sends one byte to the Midi channel. If the output
+ * Fifo is full, it waits until there is space in the queue
+ */
+
+ n = 3 * hz; /* Timeout */
+
+ flags = splhigh();
+ while (n && !midi_devs[dev]->putc(dev, data)) {
+ int chn;
+ seq_sleeper = &chn;
+ DO_SLEEP(chn, seq_sleep_flag, 4);
+
+ n--;
}
+ splx(flags);
}
static void
-seq_reset (void)
+seq_reset(void)
{
- /*
- * NOTE! Calls sleep(). Don't call this from interrupt.
- */
+ /*
+ * NOTE! Calls sleep(). Don't call this from interrupt.
+ */
- int i;
+ int i;
+ int chn;
+ u_long flags;
- int chn;
+ sound_stop_timer();
+ seq_time = get_time();
+ prev_input_time = 0;
+ prev_event_time = 0;
- sound_stop_timer ();
- seq_time = GET_TIME ();
- prev_input_time = 0;
- prev_event_time = 0;
+ qlen = qhead = qtail = 0;
+ iqlen = iqhead = iqtail = 0;
+
+ for (i = 0; i < max_synthdev; i++)
+ if (synth_open_mask & (1 << i))
+ if (synth_devs[i])
+ synth_devs[i]->reset(i);
+
+ if (seq_mode == SEQ_2) {
+ for (chn = 0; chn < 16; chn++)
+ for (i = 0; i < max_synthdev; i++)
+ if ( (synth_open_mask & (1 << i)) && (synth_devs[i]) ) {
+ synth_devs[i]->controller(i, chn,123,0);/* All notes off */
+ synth_devs[i]->controller(i, chn,121,0);/* Reset all ctl */
+ synth_devs[i]->bender(i, chn, 1 << 13); /* Bender off */
+ }
- qlen = qhead = qtail = 0;
- iqlen = iqhead = iqtail = 0;
+ } else { /* seq_mode == SEQ_1 */
+ for (i = 0; i < max_mididev; i++)
+ if (midi_written[i]) {
+ /* Midi used. Some notes may still be playing */
+ /*
+ * Sending just a ACTIVE SENSING message
+ * should be enough to stop all playing
+ * notes. Since there are devices not
+ * recognizing the active sensing, we have to
+ * send some all notes off messages also.
+ */
+ midi_outc(i, 0xfe);
+
+ for (chn = 0; chn < 16; chn++) {
+ midi_outc(i, (u_char) (0xb0 + (chn & 0x0f))); /* control change */
+ midi_outc(i, 0x7b); /* All notes off */
+ midi_outc(i, 0); /* Dummy parameter */
+ }
- for (i = 0; i < max_synthdev; i++)
- if (synth_open_mask & (1 << i))
- if (synth_devs[i])
- synth_devs[i]->reset (i);
+ midi_devs[i]->close(i);
- if (seq_mode == SEQ_2)
- {
- for (i = 0; i < max_synthdev; i++)
- if (synth_open_mask & (1 << i))
- if (synth_devs[i])
- for (chn = 0; chn < 16; chn++)
- synth_devs[i]->controller (i, chn, 0xfe, 0); /* All notes off */
- }
- else
- {
- for (i = 0; i < max_mididev; i++)
- if (midi_written[i]) /*
- * Midi used. Some notes may still be playing
- */
- {
- /*
- * Sending just a ACTIVE SENSING message should be enough to stop all
- * playing notes. Since there are devices not recognizing the
- * active sensing, we have to send some all notes off messages also.
- */
- midi_outc (i, 0xfe);
-
- for (chn = 0; chn < 16; chn++)
- {
- midi_outc (i,
- (unsigned char) (0xb0 + (chn & 0xff))); /*
- * Channel
- * msg
- */
- midi_outc (i, 0x7b); /*
- * All notes off
- */
- midi_outc (i, 0); /*
- * Dummy parameter
- */
- }
-
- midi_devs[i]->close (i);
-
- midi_written[i] = 0;
- midi_opened[i] = 0;
- }
+ midi_written[i] = 0;
+ midi_opened[i] = 0;
+ }
}
- seq_playing = 0;
+ seq_playing = 0;
- if (SOMEONE_WAITING (seq_sleeper, seq_sleep_flag))
- printk ("Sequencer Warning: Unexpected sleeping process\n");
+ flags = splhigh();
+ if ((seq_sleep_flag.mode & WK_SLEEP)) {
+ seq_sleep_flag.mode = WK_WAKEUP;
+ wakeup(seq_sleeper);
+ }
+ splx(flags);
}
static void
-seq_panic (void)
+seq_panic(void)
{
- /*
- * This routine is called by the application in case the user
- * wants to reset the system to the default state.
- */
-
- seq_reset ();
-
- /*
- * Since some of the devices don't recognize the active sensing and
- * all notes off messages, we have to shut all notes manually.
- *
- * TO BE IMPLEMENTED LATER
- */
-
- /*
- * Also return the controllers to their default states
- */
+ /*
+ * This routine is called by the application in case the user wants
+ * to reset the system to the default state.
+ */
+
+ seq_reset();
+
+ /*
+ * Since some of the devices don't recognize the active sensing and
+ * all notes off messages, we have to shut all notes manually.
+ *
+ * TO BE IMPLEMENTED LATER
+ */
+
+ /*
+ * Also return the controllers to their default states
+ */
}
int
-sequencer_ioctl (int dev, struct fileinfo *file,
- unsigned int cmd, unsigned int arg)
+sequencer_ioctl(int dev, struct fileinfo * file,
+ u_int cmd, ioctl_arg arg)
{
- int midi_dev, orig_dev;
- int mode = file->mode & O_ACCMODE;
+ int midi_dev, orig_dev;
+ int mode = file->mode & O_ACCMODE;
- orig_dev = dev = dev >> 4;
+ orig_dev = dev = dev >> 4;
- switch (cmd)
- {
+ switch (cmd) {
case SNDCTL_TMR_TIMEBASE:
case SNDCTL_TMR_TEMPO:
case SNDCTL_TMR_START:
@@ -1337,525 +1366,457 @@ sequencer_ioctl (int dev, struct fileinfo *file,
case SNDCTL_TMR_CONTINUE:
case SNDCTL_TMR_METRONOME:
case SNDCTL_TMR_SOURCE:
- if (dev) /* Patch manager */
- return RET_ERROR (EIO);
+ if (dev) /* Patch manager */
+ return -(EIO);
- if (seq_mode != SEQ_2)
- return RET_ERROR (EINVAL);
- return tmr->ioctl (tmr_no, cmd, arg);
- break;
+ if (seq_mode != SEQ_2)
+ return -(EINVAL);
+ return tmr->ioctl(tmr_no, cmd, arg);
+ break;
case SNDCTL_TMR_SELECT:
- if (dev) /* Patch manager */
- return RET_ERROR (EIO);
+ if (dev) /* Patch manager */
+ return -(EIO);
- if (seq_mode != SEQ_2)
- return RET_ERROR (EINVAL);
- pending_timer = IOCTL_IN (arg);
+ if (seq_mode != SEQ_2)
+ return -(EINVAL);
+ pending_timer = (*(int *) arg);
- if (pending_timer < 0 || pending_timer >= num_sound_timers)
- {
- pending_timer = -1;
- return RET_ERROR (EINVAL);
+ if (pending_timer < 0 || pending_timer >= num_sound_timers) {
+ pending_timer = -1;
+ return -(EINVAL);
}
-
- return IOCTL_OUT (arg, pending_timer);
- break;
+ return *(int *) arg = pending_timer;
+ break;
case SNDCTL_SEQ_PANIC:
- seq_panic ();
- break;
+ seq_panic();
+ break;
case SNDCTL_SEQ_SYNC:
- if (dev) /*
- * Patch manager
- */
- return RET_ERROR (EIO);
-
- if (mode == OPEN_READ)
- return 0;
- while (qlen && !PROCESS_ABORTING (seq_sleeper, seq_sleep_flag))
- seq_sync ();
- if (qlen)
- return RET_ERROR (EINTR);
- else
- return 0;
- break;
+ if (dev) /* Patch manager */
+ return -(EIO);
+
+ if (mode == OPEN_READ)
+ return 0;
+ while (qlen && !(seq_sleep_flag.aborting))
+ seq_sync();
+ if (qlen)
+ return -(EINTR);
+ else
+ return 0;
+ break;
case SNDCTL_SEQ_RESET:
- if (dev) /*
- * Patch manager
- */
- return RET_ERROR (EIO);
+ if (dev) /* Patch manager */
+ return -(EIO);
- seq_reset ();
- return 0;
- break;
+ seq_reset();
+ return 0;
+ break;
case SNDCTL_SEQ_TESTMIDI:
- if (dev) /*
- * Patch manager
- */
- return RET_ERROR (EIO);
+ if (dev) /* Patch manager */
+ return -(EIO);
- midi_dev = IOCTL_IN (arg);
- if (midi_dev >= max_mididev)
- return RET_ERROR (ENXIO);
+ midi_dev = (*(int *) arg);
+ if (midi_dev >= max_mididev)
+ return -(ENXIO);
- if (!midi_opened[midi_dev])
- {
- int err, mode;
+ if (!midi_opened[midi_dev]) {
+ int err, mode;
- mode = file->mode & O_ACCMODE;
- if ((err = midi_devs[midi_dev]->open (midi_dev, mode,
- sequencer_midi_input,
- sequencer_midi_output)) < 0)
- return err;
+ mode = file->mode & O_ACCMODE;
+ if ((err = midi_devs[midi_dev]->open(midi_dev, mode,
+ sequencer_midi_input, sequencer_midi_output)) < 0)
+ return err;
}
+ midi_opened[midi_dev] = 1;
- midi_opened[midi_dev] = 1;
-
- return 0;
- break;
+ return 0;
+ break;
case SNDCTL_SEQ_GETINCOUNT:
- if (dev) /*
- * Patch manager
- */
- return RET_ERROR (EIO);
+ if (dev) /* Patch manager */
+ return -(EIO);
- if (mode == OPEN_WRITE)
- return 0;
- return IOCTL_OUT (arg, iqlen);
- break;
+ if (mode == OPEN_WRITE)
+ return 0;
+ return *(int *) arg = iqlen;
+ break;
case SNDCTL_SEQ_GETOUTCOUNT:
- if (mode == OPEN_READ)
- return 0;
- return IOCTL_OUT (arg, SEQ_MAX_QUEUE - qlen);
- break;
+ if (mode == OPEN_READ)
+ return 0;
+ return *(int *) arg = SEQ_MAX_QUEUE - qlen;
+ break;
case SNDCTL_SEQ_CTRLRATE:
- if (dev) /* Patch manager */
- return RET_ERROR (EIO);
+ if (dev) /* Patch manager */
+ return -(EIO);
- /*
- * If *arg == 0, just return the current rate
- */
- if (seq_mode == SEQ_2)
- return tmr->ioctl (tmr_no, cmd, arg);
+ /*
+ * If *arg == 0, just return the current rate
+ */
+ if (seq_mode == SEQ_2)
+ return tmr->ioctl(tmr_no, cmd, arg);
- if (IOCTL_IN (arg) != 0)
- return RET_ERROR (EINVAL);
+ if ((*(int *) arg) != 0)
+ return -(EINVAL);
- return IOCTL_OUT (arg, HZ);
- break;
+ return *(int *) arg = hz;
+ break;
case SNDCTL_SEQ_RESETSAMPLES:
- dev = IOCTL_IN (arg);
- if (dev < 0 || dev >= num_synths)
- return RET_ERROR (ENXIO);
-
- if (!(synth_open_mask & (1 << dev)) && !orig_dev)
- return RET_ERROR (EBUSY);
+ {
+ int err;
- if (!orig_dev && pmgr_present[dev])
- pmgr_inform (dev, PM_E_PATCH_RESET, 0, 0, 0, 0);
+ dev = (*(int *) arg);
+ if (dev < 0 || dev >= num_synths)
+ return -(ENXIO);
+ if (!(synth_open_mask & (1 << dev)) && !orig_dev)
+ return -(EBUSY);
+ if (!orig_dev && pmgr_present[dev])
+ pmgr_inform(dev, PM_E_PATCH_RESET, 0, 0, 0, 0);
- return synth_devs[dev]->ioctl (dev, cmd, arg);
- break;
+ err = synth_devs[dev]->ioctl(dev, cmd, arg);
+ return err;
+ }
+ break;
case SNDCTL_SEQ_NRSYNTHS:
- return IOCTL_OUT (arg, max_synthdev);
- break;
+ return *(int *) arg = max_synthdev;
+ break;
case SNDCTL_SEQ_NRMIDIS:
- return IOCTL_OUT (arg, max_mididev);
- break;
+ return *(int *) arg = max_mididev;
+ break;
case SNDCTL_SYNTH_MEMAVL:
- {
- int dev = IOCTL_IN (arg);
+ {
+ int dev = (*(int *) arg);
- if (dev < 0 || dev >= num_synths)
- return RET_ERROR (ENXIO);
+ if (dev < 0 || dev >= num_synths)
+ return -(ENXIO);
- if (!(synth_open_mask & (1 << dev)) && !orig_dev)
- return RET_ERROR (EBUSY);
+ if (!(synth_open_mask & (1 << dev)) && !orig_dev)
+ return -(EBUSY);
- return IOCTL_OUT (arg, synth_devs[dev]->ioctl (dev, cmd, arg));
- }
- break;
+ return *(int *) arg = synth_devs[dev]->ioctl(dev, cmd, arg);
+ }
+ break;
case SNDCTL_FM_4OP_ENABLE:
- {
- int dev = IOCTL_IN (arg);
+ {
+ int dev = (*(int *) arg);
- if (dev < 0 || dev >= num_synths)
- return RET_ERROR (ENXIO);
+ if (dev < 0 || dev >= num_synths)
+ return -(ENXIO);
- if (!(synth_open_mask & (1 << dev)))
- return RET_ERROR (ENXIO);
+ if (!(synth_open_mask & (1 << dev)))
+ return -(ENXIO);
- synth_devs[dev]->ioctl (dev, cmd, arg);
- return 0;
- }
- break;
+ synth_devs[dev]->ioctl(dev, cmd, arg);
+ return 0;
+ }
+ break;
case SNDCTL_SYNTH_INFO:
- {
- struct synth_info inf;
- int dev;
+ {
+ struct synth_info inf;
+ int dev;
+
+ bcopy(&(((char *) arg)[0]), (char *) &inf, sizeof(inf));
+ dev = inf.device;
+
+ if (dev < 0 || dev >= max_synthdev)
+ return -(ENXIO);
+
+ if (!(synth_open_mask & (1 << dev)) && !orig_dev)
+ return -(EBUSY);
- IOCTL_FROM_USER ((char *) &inf, (char *) arg, 0, sizeof (inf));
- dev = inf.device;
+ return synth_devs[dev]->ioctl(dev, cmd, arg);
+ }
+ break;
+
+ case SNDCTL_SEQ_OUTOFBAND:
+ {
+ struct seq_event_rec event;
+ u_long flags;
- if (dev < 0 || dev >= max_synthdev)
- return RET_ERROR (ENXIO);
+ bcopy(&(((char *) arg)[0]), (char *) &event, sizeof(event));
- if (!(synth_open_mask & (1 << dev)) && !orig_dev)
- return RET_ERROR (EBUSY);
+ flags = splhigh();
+ play_event(event.arr);
+ splx(flags);
- return synth_devs[dev]->ioctl (dev, cmd, arg);
- }
- break;
+ return 0;
+ }
+ break;
case SNDCTL_MIDI_INFO:
- {
- struct midi_info inf;
- int dev;
+ {
+ struct midi_info inf;
+ int dev;
- IOCTL_FROM_USER ((char *) &inf, (char *) arg, 0, sizeof (inf));
- dev = inf.device;
+ bcopy(&(((char *) arg)[0]), (char *) &inf, sizeof(inf));
+ dev = inf.device;
- if (dev < 0 || dev >= max_mididev)
- return RET_ERROR (ENXIO);
+ if (dev < 0 || dev >= max_mididev)
+ return -(ENXIO);
- IOCTL_TO_USER ((char *) arg, 0, (char *) &(midi_devs[dev]->info), sizeof (inf));
- return 0;
- }
- break;
+ bcopy((char *) &(midi_devs[dev]->info), &(((char *) arg)[0]), sizeof(inf));
+ return 0;
+ }
+ break;
case SNDCTL_PMGR_IFACE:
- {
- struct patmgr_info *inf;
- int dev, err;
-
- inf = (struct patmgr_info *) KERNEL_MALLOC (sizeof (*inf));
-
- IOCTL_FROM_USER ((char *) inf, (char *) arg, 0, sizeof (*inf));
- dev = inf->device;
-
- if (dev < 0 || dev >= num_synths)
- {
- KERNEL_FREE (inf);
- return RET_ERROR (ENXIO);
- }
-
- if (!synth_devs[dev]->pmgr_interface)
- {
- KERNEL_FREE (inf);
- return RET_ERROR (ENXIO);
- }
-
- if ((err = synth_devs[dev]->pmgr_interface (dev, inf)) == -1)
- {
- KERNEL_FREE (inf);
- return err;
- }
+ {
+ struct patmgr_info *inf;
+ int dev, err;
- IOCTL_TO_USER ((char *) arg, 0, (char *) inf, sizeof (*inf));
- KERNEL_FREE (inf);
- return 0;
- }
- break;
+ if ((inf = (struct patmgr_info *) malloc(sizeof(*inf), M_TEMP, M_WAITOK)) == NULL) {
+ printf("patmgr: Can't allocate memory for a message\n");
+ return -(EIO);
+ }
+ bcopy(&(((char *) arg)[0]), (char *) inf, sizeof(*inf));
+ dev = inf->device;
+
+ if (dev < 0 || dev >= num_synths) {
+ free(inf, M_TEMP);
+ return -(ENXIO);
+ }
+ if (!synth_devs[dev]->pmgr_interface) {
+ free(inf, M_TEMP);
+ return -(ENXIO);
+ }
+ if ((err = synth_devs[dev]->pmgr_interface(dev, inf)) == -1) {
+ free(inf, M_TEMP);
+ return err;
+ }
+ bcopy((char *) inf, &(((char *) arg)[0]), sizeof(*inf));
+ free(inf, M_TEMP);
+ return 0;
+ }
+ break;
case SNDCTL_PMGR_ACCESS:
- {
- struct patmgr_info *inf;
- int dev, err;
-
- inf = (struct patmgr_info *) KERNEL_MALLOC (sizeof (*inf));
-
- IOCTL_FROM_USER ((char *) inf, (char *) arg, 0, sizeof (*inf));
- dev = inf->device;
-
- if (dev < 0 || dev >= num_synths)
- {
- KERNEL_FREE (inf);
- return RET_ERROR (ENXIO);
- }
-
- if (!pmgr_present[dev])
- {
- KERNEL_FREE (inf);
- return RET_ERROR (ESRCH);
- }
-
- if ((err = pmgr_access (dev, inf)) < 0)
- {
- KERNEL_FREE (inf);
- return err;
- }
+ {
+ struct patmgr_info *inf;
+ int dev, err;
- IOCTL_TO_USER ((char *) arg, 0, (char *) inf, sizeof (*inf));
- KERNEL_FREE (inf);
- return 0;
- }
- break;
-
- case SNDCTL_SEQ_TRESHOLD:
- {
- int tmp = IOCTL_IN (arg);
-
- if (dev) /*
- * Patch manager
- */
- return RET_ERROR (EIO);
-
- if (tmp < 1)
- tmp = 1;
- if (tmp >= SEQ_MAX_QUEUE)
- tmp = SEQ_MAX_QUEUE - 1;
- output_treshold = tmp;
- return 0;
- }
- break;
+ if ((inf = (struct patmgr_info *) malloc(sizeof(*inf), M_TEMP, M_WAITOK)) == NULL) {
+ printf("patmgr: Can't allocate memory for a message\n");
+ return -(EIO);
+ }
+ bcopy(&(((char *) arg)[0]), (char *) inf, sizeof(*inf));
+ dev = inf->device;
+
+ if (dev < 0 || dev >= num_synths) {
+ free(inf, M_TEMP);
+ return -(ENXIO);
+ }
+ if (!pmgr_present[dev]) {
+ free(inf, M_TEMP);
+ return -(ESRCH);
+ }
+ if ((err = pmgr_access(dev, inf)) < 0) {
+ free(inf, M_TEMP);
+ return err;
+ }
+ bcopy((char *) inf, &(((char *) arg)[0]), sizeof(*inf));
+ free(inf, M_TEMP);
+ return 0;
+ }
+ break;
+
+ case SNDCTL_SEQ_THRESHOLD:
+ {
+ int tmp = (*(int *) arg);
+
+ if (dev)/* Patch manager */
+ return -(EIO);
+
+ if (tmp < 1)
+ tmp = 1;
+ if (tmp >= SEQ_MAX_QUEUE)
+ tmp = SEQ_MAX_QUEUE - 1;
+ output_treshold = tmp;
+ return 0;
+ }
+ break;
case SNDCTL_MIDI_PRETIME:
- {
- int val = IOCTL_IN (arg);
+ {
+ int val = (*(int *) arg);
- if (val < 0)
- val = 0;
+ if (val < 0)
+ val = 0;
- val = (HZ * val) / 10;
- pre_event_timeout = val;
- return IOCTL_OUT (arg, val);
- }
- break;
+ val = (hz * val) / 10;
+ pre_event_timeout = val;
+ return *(int *) arg = val;
+ }
+ break;
default:
- if (dev) /*
- * Patch manager
- */
- return RET_ERROR (EIO);
-
- if (mode == OPEN_READ)
- return RET_ERROR (EIO);
-
- if (!synth_devs[0])
- return RET_ERROR (ENXIO);
- if (!(synth_open_mask & (1 << 0)))
- return RET_ERROR (ENXIO);
- return synth_devs[0]->ioctl (0, cmd, arg);
- break;
+ if (dev) /* Patch manager */
+ return -(EIO);
+
+ if (mode == OPEN_READ)
+ return -(EIO);
+
+ if (!synth_devs[0])
+ return -(ENXIO);
+ if (!(synth_open_mask & (1 << 0)))
+ return -(ENXIO);
+ return synth_devs[0]->ioctl(0, cmd, arg);
+ break;
}
- return RET_ERROR (EINVAL);
+ return -(EINVAL);
}
-#ifdef ALLOW_SELECT
+#ifdef ALLOW_POLL
int
-sequencer_select (int dev, struct fileinfo *file, int sel_type, select_table * wait)
+sequencer_poll (int dev, struct fileinfo *file, int events, select_table * wait)
{
unsigned long flags;
+ int revents = 0;
dev = dev >> 4;
+ flags = splhigh();
- switch (sel_type)
- {
- case SEL_IN:
- if (!iqlen)
- {
- DISABLE_INTR (flags);
- midi_sleep_flag.mode = WK_SLEEP;
- select_wait (&midi_sleeper, wait);
- RESTORE_INTR (flags);
- return 0;
- }
- return 1;
- break;
- case SEL_OUT:
- if (qlen >= SEQ_MAX_QUEUE)
- {
- DISABLE_INTR (flags);
- seq_sleep_flag.mode = WK_SLEEP;
- select_wait (&seq_sleeper, wait);
- RESTORE_INTR (flags);
- return 0;
- }
- return 1;
- break;
+ if (events & (POLLIN | POLLRDNORM))
+ if (!iqlen)
+ selrecord(wait, &selinfo[dev]);
+ else {
+ revents |= events & (POLLIN | POLLRDNORM);
+ midi_sleep_flag.mode &= ~WK_SLEEP;
+ }
- case SEL_EX:
- return 0;
+ if (events & (POLLOUT | POLLWRNORM))
+ if (qlen >= SEQ_MAX_QUEUE)
+ selrecord(wait, &selinfo[dev]);
+ else {
+ revents |= events & (POLLOUT | POLLWRNORM);
+ seq_sleep_flag.mode &= ~WK_SLEEP;
}
- return 0;
+ splx(flags);
+
+ return (revents);
}
#endif
+
void
-sequencer_timer (void)
+sequencer_timer(void *dummy)
{
- seq_startplay ();
+ seq_startplay();
}
int
-note_to_freq (int note_num)
+note_to_freq(int note_num)
{
- /*
- * This routine converts a midi note to a frequency (multiplied by 1000)
- */
+ /*
+ * This routine converts a midi note to a frequency (multiplied by
+ * 1000)
+ */
- int note, octave, note_freq;
- int notes[] =
- {
- 261632, 277189, 293671, 311132, 329632, 349232,
- 369998, 391998, 415306, 440000, 466162, 493880
- };
+ int note, octave, note_freq;
+ int notes[] =
+ {
+ 261632, 277189, 293671, 311132, 329632, 349232,
+ 369998, 391998, 415306, 440000, 466162, 493880
+ };
#define BASE_OCTAVE 5
- octave = note_num / 12;
- note = note_num % 12;
+ octave = note_num / 12;
+ note = note_num % 12;
- note_freq = notes[note];
+ note_freq = notes[note];
- if (octave < BASE_OCTAVE)
- note_freq >>= (BASE_OCTAVE - octave);
- else if (octave > BASE_OCTAVE)
- note_freq <<= (octave - BASE_OCTAVE);
+ if (octave < BASE_OCTAVE)
+ note_freq >>= (BASE_OCTAVE - octave);
+ else if (octave > BASE_OCTAVE)
+ note_freq <<= (octave - BASE_OCTAVE);
- /*
- * note_freq >>= 1;
- */
+ /*
+ * note_freq >>= 1;
+ */
- return note_freq;
+ return note_freq;
}
-unsigned long
-compute_finetune (unsigned long base_freq, int bend, int range)
+u_long
+compute_finetune(u_long base_freq, int bend, int range)
{
- unsigned long amount;
- int negative, semitones, cents, multiplier = 1;
+ u_long amount;
+ int negative, semitones, cents, multiplier = 1;
- if (!bend)
- return base_freq;
- if (!range)
- return base_freq;
+ if (!bend)
+ return base_freq;
+ if (!range)
+ return base_freq;
- if (!base_freq)
- return base_freq;
+ if (!base_freq)
+ return base_freq;
- if (range >= 8192)
- range = 8191;
+ if (range >= 8192)
+ range = 8192;
- bend = bend * range / 8192;
- if (!bend)
- return base_freq;
+ bend = bend * range / 8192;
+ if (!bend)
+ return base_freq;
- negative = bend < 0 ? 1 : 0;
+ negative = bend < 0 ? 1 : 0;
- if (bend < 0)
- bend *= -1;
- if (bend > range)
- bend = range;
+ if (bend < 0)
+ bend *= -1;
+ if (bend > range)
+ bend = range;
- /*
- if (bend > 2399)
- bend = 2399;
- */
- while (bend > 2399)
- {
- multiplier *= 4;
- bend -= 2400;
+ /*
+ * if (bend > 2399) bend = 2399;
+ */
+ while (bend > 2399) {
+ multiplier *= 4;
+ bend -= 2400;
}
- semitones = bend / 100;
- cents = bend % 100;
+ semitones = bend / 100;
+ cents = bend % 100;
- amount = (int) (semitone_tuning[semitones] * multiplier * cent_tuning[cents])
- / 10000;
+ amount = (int) (semitone_tuning[semitones] * multiplier * cent_tuning[cents])
+ / 10000;
- if (negative)
- return (base_freq * 10000) / amount; /*
- * Bend down
- */
- else
- return (base_freq * amount) / 10000; /*
- * Bend up
- */
-}
-
-
-long
-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);
-
- return mem_start;
-}
-
-#else
-/*
- * Stub version
- */
-int
-sequencer_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
-{
- return RET_ERROR (EIO);
+ if (negative)
+ return (base_freq * 10000) / amount; /* Bend down */
+ else
+ return (base_freq * amount) / 10000; /* Bend up */
}
-int
-sequencer_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
-{
- return RET_ERROR (EIO);
-}
-
-int
-sequencer_open (int dev, struct fileinfo *file)
-{
- return RET_ERROR (ENXIO);
-}
void
-sequencer_release (int dev, struct fileinfo *file)
+sequencer_init()
{
-}
-int
-sequencer_ioctl (int dev, struct fileinfo *file,
- unsigned int cmd, unsigned int arg)
-{
- return RET_ERROR (EIO);
-}
-int
-sequencer_lseek (int dev, struct fileinfo *file, off_t offset, int orig)
-{
- return RET_ERROR (EIO);
-}
+ sequencer_ok = 1;
-long
-sequencer_init (long mem_start)
-{
- return mem_start;
-}
+ queue = (u_char *) malloc(SEQ_MAX_QUEUE * EV_SZ, M_DEVBUF, M_NOWAIT);
+ if (!queue)
+ panic("SOUND: Cannot allocate memory\n");
-int
-sequencer_select (int dev, struct fileinfo *file, int sel_type, select_table * wait)
-{
- return RET_ERROR (EIO);
+ iqueue = (u_char *) malloc(SEQ_MAX_QUEUE * IEV_SZ, M_DEVBUF, M_NOWAIT);
+ if (!iqueue)
+ panic("SOUND: Cannot allocate memory\n");
}
#endif
-
#endif
diff --git a/sys/i386/isa/sound/sound.doc b/sys/i386/isa/sound/sound.doc
index f6db243c407b..d1d0ff7c2861 100644
--- a/sys/i386/isa/sound/sound.doc
+++ b/sys/i386/isa/sound/sound.doc
@@ -1,62 +1,97 @@
+$Id: sound.doc,v 1.8 1997/02/22 09:38:15 peter Exp $
+
Instructions on using audio on a FreeBSD 2.1 (or 2.0-current) system.
See also /sys/i386/conf/LINT.
+To enable sound driver support, the controller sound code must be included
+in your config file:
+
+# SB = SoundBlaster; PAS = ProAudioSpectrum; GUS = Gravis UltraSound
+# Controls all sound devices
+controller snd0
+
+Uncomment one or more of these device entries, depending on what type of
+sound card you have:
+
+# ProAudioSpectrum PCM and Midi - for PAS
+#device pas0 at isa? port 0x388 irq 10 drq 6 vector pasintr
+
+# SoundBlaster DSP driver - for SB, SB Pro, SB16, PAS(emulating SB)
+#device sb0 at isa? port 0x220 irq 7 drq 1 vector sbintr
+
+# SoundBlaster 16 DSP driver - for SB16 - requires sb0 device
+#device sbxvi0 at isa? drq 5
+
+# SoundBlaster 16 MIDI - for SB16 - requires sb0 device
+#device sbmidi0 at isa? port 0x300
+
+# Gravis UltraSound - for GUS, GUS16, GUSMAX
+# For cards that use 2 DMA Channels:
+# drq = Write DMA Channel, flags = Read DMA Channel
+#device gus0 at isa? port 0x220 irq 11 drq 1 flags 0x3 vector gusintr
+
+# Gravis UltraSound 16 bit option - for GUS16 - requires gus0
+#device gusxvi0 at isa? port 0x530 irq 7 drq 3 vector adintr
+
+# MS Sound System (AD1848 Based Boards)
+#device mss0 at isa? port 0x530 irq 10 drq 1 vector adintr
+
+# Yamaha OPL-2/OPL-3 FM - for SB, SB Pro, SB16, PAS
+#device opl0 at isa? port 0x388
+
+# MPU-401 - for MPU-401 standalone card
+#device mpu0 at isa? port 0x330 irq 6 drq 0
+
+# 6850 UART Midi
+#device uart0 at isa? port 0x330 irq 5 vector "m6850intr"
+
You may add one or more of the following depending on what you do and don't
want compiled into your kernel. Note: Excluding things with EXCLUDE_...
is NOT recommended unless you really know what you're doing.
- options "AUDIO_MPU401" # INCLUDE MPU401 support
- options AUDIO_GUS # INCLUDE GUS support
- options AUDIO_SBPRO # INCLUDE SB Pro support
- options "AUDIO_SB16" # INCLUDE SB 16 support
- options "AUDIO_YM3812" # INCLUDE AdLib support
- options AUDIO_PAS # INCLUDE Pro Audio Studio support
- options AUDIO_SB # INCLUDE SB support
- options AUDIO_MSS # INCLUDE MSS support
- options EXCLUDE_AUDIO # NO digital audio support
- options EXCLUDE_SEQUENCER # NO sequencer support
- options EXCLUDE_GUS_IODETECT # NO GUS io detection
- options EXCLUDE_SB_EMULATION # NO PAS SB emulation support
- options "EXCLUDE_OPL3" # NO OPL3 chip support
- options EXCLUDE_PRO_MIDI # NO PAS MIDI support
- options EXCLUDE_CHIP_MIDI # NO MIDI chip support
- options EXCLUDE_MIDI # NO MIDI support whatsoever
-
-To enable sound card support, you need to uncomment and add one or more of
-the following lines to your kernel configuration file according to the
-directions below:
-
-#device snd5 at isa? port 0x330 irq 6 vector mpuintr
-#device snd4 at isa? port 0x220 irq 15 drq 6 vector gusintr
-#device snd3 at isa? port 0x388 irq 10 drq 6 vector pasintr
-#device snd2 at isa? port 0x220 irq 7 drq 1 vector sbintr
-#device snd6 at isa? port 0x220 irq 7 drq 5 vector sbintr
-#device snd10 at isa? port 0x530 irq 10 drq 1 vector adintr
-#device snd7 at isa? port 0x300
-#device snd1 at isa? port 0x388
-
-Note for PAS user: you should change snd1 line to
-#device snd1 at isa? port 0x38a
-(next stereo port) to avoid conflict with snd3
-
- Unit numbers are:
- 1 for Yamaha FM synth
- 2 for SB/SB Pro DSP
- 3 for PAS PCM and Midi
- 4 for GUS
- 5 for MPU-401 (there is separate driver for the SB16)
- 6 for SB16 (DSP)
- 7 for SB16 Midi (MPU-401 emulation)
- 10 for Microsoft Windows Sound System (AD1846)
-
- If you have ProAudioSpectrum, uncomment units 3, 2 and 1
- If you have SoundBlaster 1.0 to 2.0 or SB Pro, uncomment 2 and 1.
- If you have SoundBlaster 16, uncomment 2, 1, 6 and 7.
- (use the same IRQ for the cards 2, 6 and 7. The DMA of the
- card 2 is the 8 bit one and the DMA of the card 6 is the 16 bit one.
- the port address of the card 7 is the Midi I/O address of the SB16.
- If you have GravisUltrasound, uncomment 4
- If you have MPU-401, uncomment 5
+#options EXCLUDE_AUDIO # NO digital audio support
+#options EXCLUDE_SEQUENCER # NO sequencer support
+#options EXCLUDE_MIDI # NO MIDI support whatsoever
+#options EXCLUDE_SBPRO # EXCLUDE SB Pro support
+#options EXCLUDE_SB_EMULATION # NO PAS SB emulation support
+#options EXCLUDE_GUS_IODETECT # NO GUS io detection
+#options EXCLUDE_PRO_MIDI # NO PAS MIDI support
+
+Other Options:
+
+#options SYMPHONY_PAS
+ Adds some code to make pas work with Symphony chipsets. Only use
+ this if your pas doesn't work and you have a Symphony chipset.
+
+#options BROKEN_BUS_CLOCK
+ Some systems with the OPTI chipset and a PAS will require you to
+ use this option. Symptoms are that you will hear a lot of clicking and
+ popping sounds, like a geiger counter, coming out of the PAS even when
+ it is not playing anything.
+
+#options MOZART_PORT
+ Adds support for Mozart (OAK OTI-601). (Part of the MSS driver)
+
+#options OPTI_MAD16_PORT
+ Adds support for the OPTI MAD16 Chip. (Part of the MSS driver)
+ If your soundcard has a chip labeled "OPTi 82C929" then try this.
+
+#options __SGNXPRO__
+ Adds support for the SG NX Pro mixer. (Part of the SB driver)
+
+#options JAZZ16
+ Adds support for the MV Jazz16 (ProSonic etc). (Part of the SB Driver)
+
+#options SM_WAVE
+ Adds support for the SoundMan Wave (Part of the SB Driver)
+ Note: You will need to do some work to get this to work.
+ See i386/isa/sound/configure.c
+
+#options SM_GAMES
+ Adds support for the Logitech SoundMan Games (Part of the SB Driver)
+
+#options PAS_JOYSTICK_ENABLE
+ Enables the gameport on the ProAudio Spectrum
NOTE: The MPU-401 driver may or may not work, and is unfortunately
unverifiable since no one I know has one. If you can test this,
@@ -66,21 +101,19 @@ Please check your documentation (or verify with any provided DOS utilities
that may have come with your card) and set the IRQ or address fields
accordingly.
-Also: Some systems with the OPTI chipset will require you to #define
-BROKEN_BUS_CLOCK in /sys/i386/sound/pas2_card.c. Symptoms are that
-you will hear a lot of clicking and popping sounds, like a geiger counter,
-coming out of the PAS even when is not playing anything.
Also: You can configure more then one card on a single DMA using
-ALLOW_CONFLICT_DMA.
+the conflicts keyword in your configuration file. This is useful for boards
+with more then one type of emulation.
+
Probing problems: Since the SB16 uses the same IRQ and addresses for
-the different drivers, some of the snd dirvers will not be probed because
+the different drivers, some of the snd drivers will not be probed because
the kernel thinks there is a conflict. This can be worked-around by
-setting the ALLOW_CONFLICT_IOADDR or ALLOW_CONFLICT_IRQ options.
+using the "conflicts" keyword on the sb16's device line.
+
-Warning: Setting the ALLOW_* options will will bypass checks for ALL drivers,
-so be careful when you use them!
+For further information, contact multimedia@freebsd.org
- Jordan Hubbard (jkh@freefall.cdrom.com)
- Steven Wallace (swallace@freefall.cdrom.com)
diff --git a/sys/i386/isa/sound/sound_calls.h b/sys/i386/isa/sound/sound_calls.h
index eccd9b67336e..5f3a067754d3 100644
--- a/sys/i386/isa/sound/sound_calls.h
+++ b/sys/i386/isa/sound/sound_calls.h
@@ -4,18 +4,22 @@
int DMAbuf_open(int dev, int mode);
int DMAbuf_release(int dev, int mode);
-int DMAbuf_getwrbuffer(int dev, char **buf, int *size);
-int DMAbuf_getrdbuffer(int dev, char **buf, int *len);
+int DMAbuf_getwrbuffer(int dev, char **buf, int *size, int dontblock);
+int DMAbuf_getrdbuffer(int dev, char **buf, int *len, int dontblock);
int DMAbuf_rmchars(int dev, int buff_no, int c);
int DMAbuf_start_output(int dev, int buff_no, int l);
-int DMAbuf_ioctl(int dev, unsigned int cmd, unsigned int arg, int local);
-long DMAbuf_init(long mem_start);
-int DMAbuf_start_dma (int dev, unsigned long physaddr, int count, int dma_mode);
-int DMAbuf_open_dma (int chan);
-void DMAbuf_close_dma (int chan);
-void DMAbuf_reset_dma (int chan);
+int DMAbuf_ioctl(int dev, u_int cmd, ioctl_arg arg, int local);
+void DMAbuf_init(void);
+int DMAbuf_start_dma (int dev, u_long physaddr, int count, int dma_mode);
+int DMAbuf_open_dma (int dev);
+void DMAbuf_close_dma (int dev);
+void DMAbuf_reset_dma (int dev);
void DMAbuf_inputintr(int dev);
void DMAbuf_outputintr(int dev, int underflow_flag);
+void DMAbuf_start_devices(u_int devmask);
+#ifdef ALLOW_POLL
+int DMAbuf_select(int dev, struct fileinfo *file, int sel_type, select_table * wait);
+#endif
/*
* System calls for /dev/dsp and /dev/audio
@@ -26,9 +30,13 @@ int audio_write (int dev, struct fileinfo *file, snd_rw_buf *buf, int count);
int audio_open (int dev, struct fileinfo *file);
void audio_release (int dev, struct fileinfo *file);
int audio_ioctl (int dev, struct fileinfo *file,
- unsigned int cmd, unsigned int arg);
+ u_int cmd, ioctl_arg arg);
int audio_lseek (int dev, struct fileinfo *file, off_t offset, int orig);
-long audio_init (long mem_start);
+/* long audio_init (void); */
+
+#ifdef ALLOW_SELECT
+int audio_poll(int dev, struct fileinfo *file, int events, select_table * wait);
+#endif
/*
* System calls for the /dev/sequencer
@@ -39,18 +47,15 @@ int sequencer_write (int dev, struct fileinfo *file, snd_rw_buf *buf, int count)
int sequencer_open (int dev, struct fileinfo *file);
void sequencer_release (int dev, struct fileinfo *file);
int sequencer_ioctl (int dev, struct fileinfo *file,
- unsigned int cmd, unsigned int arg);
+ u_int cmd, ioctl_arg arg);
int sequencer_lseek (int dev, struct fileinfo *file, off_t offset, int orig);
-long sequencer_init (long mem_start);
-void sequencer_timer(void);
+void sequencer_init (void);
+void sequencer_timer(void *dummy);
int note_to_freq(int note_num);
-unsigned long compute_finetune(unsigned long base_freq, int bend, int range);
-void seq_input_event(unsigned char *event, int len);
-void seq_copy_to_input (unsigned char *event, int len);
+u_long compute_finetune(u_long base_freq, int bend, int range);
+void seq_input_event(u_char *event, int len);
+void seq_copy_to_input (u_char *event, int len);
-#ifdef ALLOW_SELECT
-int sequencer_select(int dev, struct fileinfo *file, int sel_type, select_table * wait);
-#endif
/*
* System calls for the /dev/midi
@@ -61,75 +66,49 @@ int MIDIbuf_write (int dev, struct fileinfo *file, snd_rw_buf *buf, int count);
int MIDIbuf_open (int dev, struct fileinfo *file);
void MIDIbuf_release (int dev, struct fileinfo *file);
int MIDIbuf_ioctl (int dev, struct fileinfo *file,
- unsigned int cmd, unsigned int arg);
+ u_int cmd, ioctl_arg arg);
int MIDIbuf_lseek (int dev, struct fileinfo *file, off_t offset, int orig);
-void MIDIbuf_bytes_received(int dev, unsigned char *buf, int count);
-long MIDIbuf_init(long mem_start);
-
-#ifdef ALLOW_SELECT
-int MIDIbuf_select(int dev, struct fileinfo *file, int sel_type, select_table * wait);
-#endif
-
-/*
- * System calls for the generic midi interface.
- *
- */
-
-long CMIDI_init (long mem_start);
-int CMIDI_open (int dev, struct fileinfo *file);
-int CMIDI_write (int dev, struct fileinfo *file, snd_rw_buf *buf, int count);
-int CMIDI_read (int dev, struct fileinfo *file, snd_rw_buf *buf, int count);
-int CMIDI_close (int dev, struct fileinfo *file);
+void MIDIbuf_bytes_received(int dev, u_char *buf, int count);
/*
*
* Misc calls from various sources
*/
-/* From pro_midi.c */
-
-long pro_midi_attach(long mem_start);
-int pro_midi_open(int dev, int mode);
-void pro_midi_close(int dev);
-int pro_midi_write(int dev, snd_rw_buf *uio);
-int pro_midi_read(int dev, snd_rw_buf *uio);
-
/* From soundcard.c */
-long soundcard_init(long mem_start);
-void tenmicrosec(void);
+void soundcard_init(void);
+void tenmicrosec(int);
void request_sound_timer (int count);
void sound_stop_timer(void);
int snd_ioctl_return(int *addr, int value);
-int snd_set_irq_handler (int interrupt_level, void(*hndlr)(int));
-void snd_release_irq(int vect);
+int snd_set_irq_handler (int int_lvl, void(*hndlr)(int), sound_os_info *osp);
void sound_dma_malloc(int dev);
void sound_dma_free(int dev);
+void conf_printf(char *name, struct address_info *hw_config);
+void conf_printf2(char *name, int base, int irq, int dma, int dma2);
/* From sound_switch.c */
int 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);
int sound_open_sw (int dev, struct fileinfo *file);
void sound_release_sw (int dev, struct fileinfo *file);
-int sound_ioctl_sw (int dev, struct fileinfo *file,
- unsigned int cmd, unsigned long arg);
+int sound_ioctl_sw (int dev, struct fileinfo *file, u_int cmd, ioctl_arg arg);
/* From sb_dsp.c */
int sb_dsp_detect (struct address_info *hw_config);
-long sb_dsp_init (long mem_start, struct address_info *hw_config);
+void sb_dsp_init (struct address_info *hw_config);
void sb_dsp_disable_midi(void);
-int sb_get_irq(void);
-void sb_free_irq(void);
-int sb_dsp_command (unsigned char val);
+int sb_dsp_command (u_char val);
int sb_reset_dsp (void);
/* From sb16_dsp.c */
-void sb16_dsp_interrupt (int unused);
-long sb16_dsp_init(long mem_start, struct address_info *hw_config);
+void sb16_dsp_interrupt (int irq);
+void sb16_dsp_init(struct address_info *hw_config);
int sb16_dsp_detect(struct address_info *hw_config);
/* From sb16_midi.c */
void sb16midiintr (int unit);
-long attach_sb16midi(long mem_start, struct address_info * hw_config);
+void attach_sb16midi(struct address_info * hw_config);
int probe_sb16midi(struct address_info *hw_config);
void sb_midi_interrupt(int dummy);
@@ -137,70 +116,76 @@ void sb_midi_interrupt(int dummy);
void sb_midi_init(int model);
/* From sb_mixer.c */
-void sb_setmixer (unsigned int port, unsigned int value);
-int sb_getmixer (unsigned int port);
+void sb_setmixer (u_int port, u_int value);
+int sb_getmixer (u_int port);
void sb_mixer_set_stereo(int mode);
int sb_mixer_init(int major_model);
/* From opl3.c */
-int opl3_detect (int ioaddr);
-long opl3_init(long mem_start);
+int opl3_detect (int ioaddr, sound_os_info *osp);
+void opl3_init(int ioaddr, sound_os_info *osp);
/* From sb_card.c */
-long attach_sb_card(long mem_start, struct address_info *hw_config);
+void attach_sb_card(struct address_info *hw_config);
int probe_sb(struct address_info *hw_config);
+/* From awe_wave.c */
+void attach_awe_obsolete(struct address_info *hw_config);
+int probe_awe_obsolete(struct address_info *hw_config);
+
/* From adlib_card.c */
-long attach_adlib_card(long mem_start, struct address_info *hw_config);
+void attach_adlib_card(struct address_info *hw_config);
int probe_adlib(struct address_info *hw_config);
/* From pas_card.c */
-long attach_pas_card(long mem_start, struct address_info *hw_config);
+void attach_pas_card(struct address_info *hw_config);
int probe_pas(struct address_info *hw_config);
int pas_set_intr(int mask);
int pas_remove_intr(int mask);
-unsigned char pas_read(int ioaddr);
-void pas_write(unsigned char data, int ioaddr);
+u_char pas_read(int ioaddr);
+void pas_write(u_char data, int ioaddr);
/* From pas_audio.c */
-void pas_pcm_interrupt(unsigned char status, int cause);
-long pas_pcm_init(long mem_start, struct address_info *hw_config);
+void pas_pcm_interrupt(u_char status, int cause);
+void pas_pcm_init(struct address_info *hw_config);
/* From pas_mixer.c */
int pas_init_mixer(void);
/* From pas_midi.c */
-long pas_midi_init(long mem_start);
+void pas_midi_init(void);
void pas_midi_interrupt(void);
/* From gus_card.c */
-long attach_gus_card(long mem_start, struct address_info * hw_config);
+void attach_gus_card(struct address_info * hw_config);
int probe_gus(struct address_info *hw_config);
int gus_set_midi_irq(int num);
-void gusintr(int);
-long attach_gus_db16(long mem_start, struct address_info * hw_config);
+/*void gusintr(int irq); */
+void attach_gus_db16(struct address_info * hw_config);
int probe_gus_db16(struct address_info *hw_config);
/* From gus_wave.c */
int gus_wave_detect(int baseaddr);
-long gus_wave_init(long mem_start, int irq, int dma);
+void gus_wave_init(struct address_info *hw_config);
void gus_voice_irq(void);
-unsigned char gus_read8 (int reg);
-void gus_write8(int reg, unsigned int data);
+u_char gus_read8 (int reg);
+void gus_write8(int reg, u_int data);
void guswave_dma_irq(void);
void gus_delay(void);
-int gus_default_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg);
+int gus_default_mixer_ioctl (int dev, u_int cmd, ioctl_arg arg);
+void gus_timer_command (u_int addr, u_int val);
/* From gus_midi.c */
-long gus_midi_init(long mem_start);
+void gus_midi_init(void);
void gus_midi_interrupt(int dummy);
/* From mpu401.c */
-long attach_mpu401(long mem_start, struct address_info * hw_config);
+void attach_mpu401(struct address_info * hw_config);
int probe_mpu401(struct address_info *hw_config);
+void mpuintr(int irq);
/* From uart6850.c */
-long attach_uart6850(long mem_start, struct address_info * hw_config);
+void attach_uart6850(struct address_info * hw_config);
int probe_uart6850(struct address_info *hw_config);
/* From opl3.c */
@@ -212,32 +197,87 @@ void pmgr_release(int dev);
int pmgr_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count);
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);
+int pmgr_inform(int dev, int event, u_long parm1, u_long parm2,
+ u_long parm3, u_long parm4);
/* From ics2101.c */
-long ics2101_mixer_init(long mem_start);
+void ics2101_mixer_init(void);
/* From sound_timer.c */
-void sound_timer_init(int io_base);
void sound_timer_interrupt(void);
+void sound_timer_syncinterval(u_int new_usecs);
/* From ad1848.c */
-void ad1848_init (char *name, int io_base, int irq, int dma_playback, int dma_capture);
-int ad1848_detect (int io_base);
-void ad1848_interrupt (int dev);
-long attach_ms_sound(long mem_start, struct address_info * hw_config);
-int probe_ms_sound(struct address_info *hw_config);
+void ad1848_init (char *name, int io_base, int irq, int dma_playback, int dma_capture, int share_dma, sound_os_info *osp);
+
+int ad1848_detect (int io_base, int *flags, sound_os_info *osp);
+#define AD_F_CS4231 0x0001 /* Returned if a CS4232 (or compatible) detected */
+#define AD_F_CS4248 0x0001 /* Returned if a CS4248 (or compatible) detected */
+
+void ad1848_interrupt (int irq);
+void attach_mss(struct address_info * hw_config);
+int probe_mss(struct address_info *hw_config);
+void attach_pnp_ad1848(struct address_info * hw_config);
+int probe_pnp_ad1848(struct address_info *hw_config);
/* From pss.c */
int probe_pss (struct address_info *hw_config);
-long attach_pss (long mem_start, struct address_info *hw_config);
+void attach_pss (struct address_info *hw_config);
+int probe_pss_mpu (struct address_info *hw_config);
+void attach_pss_mpu (struct address_info *hw_config);
+int probe_pss_mss (struct address_info *hw_config);
+void attach_pss_mss (struct address_info *hw_config);
+
+/* From sscape.c */
+int probe_sscape (struct address_info *hw_config);
+void attach_sscape (struct address_info *hw_config);
+int probe_ss_mss(struct address_info *hw_config);
+void attach_ss_mss(struct address_info * hw_config);
int pss_read (int dev, struct fileinfo *file, snd_rw_buf *buf, int count);
int pss_write (int dev, struct fileinfo *file, snd_rw_buf *buf, int count);
int pss_open (int dev, struct fileinfo *file);
void pss_release (int dev, struct fileinfo *file);
int pss_ioctl (int dev, struct fileinfo *file,
- unsigned int cmd, unsigned int arg);
+ u_int cmd, ioctl_arg arg);
int pss_lseek (int dev, struct fileinfo *file, off_t offset, int orig);
-long pss_init(long mem_start);
+void pss_init(void);
+
+/* From aedsp16.c */
+int InitAEDSP16_SBPRO(struct address_info *hw_config);
+int InitAEDSP16_MSS(struct address_info *hw_config);
+int InitAEDSP16_MPU401(struct address_info *hw_config);
+
+/* From midi_synth.c */
+void do_midi_msg (int synthno, u_char *msg, int mlen);
+
+/* From trix.c */
+void attach_trix_wss (struct address_info *hw_config);
+int probe_trix_wss (struct address_info *hw_config);
+void attach_trix_sb (struct address_info *hw_config);
+int probe_trix_sb (struct address_info *hw_config);
+void attach_trix_mpu (struct address_info *hw_config);
+int probe_trix_mpu (struct address_info *hw_config);
+
+/* From mad16.c */
+void attach_mad16 (struct address_info *hw_config);
+int probe_mad16 (struct address_info *hw_config);
+void attach_mad16_mpu (struct address_info *hw_config);
+int probe_mad16_mpu (struct address_info *hw_config);
+int mad16_sb_dsp_detect (struct address_info *hw_config);
+void mad16_sb_dsp_init (struct address_info *hw_config);
+
+/* From cs4232.c */
+
+int probe_cs4232 (struct address_info *hw_config);
+void attach_cs4232 (struct address_info *hw_config);
+int probe_cs4232_mpu (struct address_info *hw_config);
+void attach_cs4232_mpu (struct address_info *hw_config);
+
+/* From maui.c */
+void attach_maui(struct address_info * hw_config);
+int probe_maui(struct address_info *hw_config);
+
+/* From sound_pnp.c */
+void sound_pnp_init(void);
+void sound_pnp_disconnect(void);
diff --git a/sys/i386/isa/sound/sound_config.h b/sys/i386/isa/sound/sound_config.h
index 6c53c8cdd0cd..a802763a805d 100644
--- a/sys/i386/isa/sound/sound_config.h
+++ b/sys/i386/isa/sound/sound_config.h
@@ -2,8 +2,7 @@
*
* A driver for Soundcards, misc configuration parameters.
*
- *
- * Copyright by Hannu Savolainen 1993
+ * Copyright by Hannu Savolainen 1995
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -28,33 +27,27 @@
*
*/
-#include "local.h"
-
-#if defined(ISC) || defined(SCO) || defined(SVR42)
-#define GENERIC_SYSV
-#endif
-
/*
- * Disable the AD1848 driver if there are no other drivers requiring it.
+ * many variables should be reduced to a range. Here define a macro
*/
-#if defined(EXCLUDE_GUS16) && defined(EXCLUDE_MSS) && defined(EXCLUDE_PSS) && defined(EXCLUDE_GUSMAX)
-#define EXCLUDE_AD1848
-#endif
-
+#define RANGE(var, low, high) (var) = \
+ ((var)<(low)?(low) : (var)>(high)?(high) : (var))
+
#undef CONFIGURE_SOUNDCARD
#undef DYNAMIC_BUFFER
-#ifdef KERNEL_SOUNDCARD
+#include <i386/isa/sound/local.h>
+
#define CONFIGURE_SOUNDCARD
#define DYNAMIC_BUFFER
#undef LOADABLE_SOUNDCARD
-#endif
-#ifdef EXCLUDE_SEQUENCER
-#define EXCLUDE_MIDI
-#define EXCLUDE_YM3812
-#define EXCLUDE_OPL3
+#include <i386/isa/sound/os.h>
+#include <i386/isa/sound/soundvers.h>
+
+#if defined(ISC) || defined(SCO) || defined(SVR42)
+#define GENERIC_SYSV
#endif
#ifndef SND_DEFAULT_ENABLE
@@ -63,80 +56,6 @@
#ifdef CONFIGURE_SOUNDCARD
-/* ****** IO-address, DMA and IRQ settings ****
-
-If your card has nonstandard I/O address or IRQ number, change defines
- for the following settings in your kernel Makefile */
-
-#ifndef SBC_BASE
-#define SBC_BASE 0x220 /* 0x220 is the factory default. */
-#endif
-
-#ifndef SBC_IRQ
-#define SBC_IRQ 7 /* IQR7 is the factory default. */
-#endif
-
-#ifndef SBC_DMA
-#define SBC_DMA 1
-#endif
-
-#ifndef SB16_DMA
-#define SB16_DMA 6
-#endif
-
-#ifndef SB16MIDI_BASE
-#define SB16MIDI_BASE 0x300
-#endif
-
-#ifndef PAS_BASE
-#define PAS_BASE 0x388
-#endif
-
-#ifndef PAS_IRQ
-#define PAS_IRQ 5
-#endif
-
-#ifndef PAS_DMA
-#define PAS_DMA 3
-#endif
-
-#ifndef GUS_BASE
-#define GUS_BASE 0x220
-#endif
-
-#ifndef GUS_IRQ
-#define GUS_IRQ 15
-#endif
-
-#ifndef GUS_MIDI_IRQ
-#define GUS_MIDI_IRQ GUS_IRQ
-#endif
-
-#ifndef GUS_DMA
-#define GUS_DMA 6
-#endif
-
-#ifndef MPU_BASE
-#define MPU_BASE 0x330
-#endif
-
-#ifndef MPU_IRQ
-#define MPU_IRQ 6
-#endif
-
-/* Echo Personal Sound System */
-#ifndef PSS_BASE
-#define PSS_BASE 0x220 /* 0x240 or */
-#endif
-
-#ifndef PSS_IRQ
-#define PSS_IRQ 7
-#endif
-
-#ifndef PSS_DMA
-#define PSS_DMA 1
-#endif
-
#ifndef MAX_REALTIME_FACTOR
#define MAX_REALTIME_FACTOR 4
#endif
@@ -150,20 +69,36 @@ If your card has nonstandard I/O address or IRQ number, change defines
4k for SB.
If you change the DSP_BUFFSIZE, don't modify this file.
- Use the make config command instead. */
+ Use the make config command instead. Seems to allow only 4K, 16K,
+ 32K, 64K.
+ */
#ifndef DSP_BUFFSIZE
-#define DSP_BUFFSIZE (4096)
+#define DSP_BUFFSIZE (32760)
#endif
#ifndef DSP_BUFFCOUNT
-#define DSP_BUFFCOUNT 2 /* 2 is recommended. */
+#define DSP_BUFFCOUNT 1 /* 1 is recommended. */
#endif
-#define DMA_AUTOINIT 0x10
+#define DMA_AUTOINIT 0x10 /* XXX never used */
#define FM_MONO 0x388 /* This is the I/O address used by AdLib */
+#ifndef AWE32_BASE
+#define AWE32_BASE 0x620 /* Default = 0x620-3, 0xA20-3, 0xE20-3 */
+#endif
+
+#ifndef PAS_BASE
+#define PAS_BASE 0x388
+#endif
+
+#ifdef JAZZ16
+#ifndef JAZZ_DMA16
+#define JAZZ_DMA16 5
+#endif
+#endif
+
/* SEQ_MAX_QUEUE is the maximum number of sequencer events buffered by the
driver. (There is no need to alter this) */
#define SEQ_MAX_QUEUE 1024
@@ -181,6 +116,7 @@ If your card has nonstandard I/O address or IRQ number, change defines
*/
#define SND_NDEVS 256 /* Number of supported devices */
+
#define SND_DEV_CTL 0 /* Control port /dev/mixer */
#define SND_DEV_SEQ 1 /* Sequencer output /dev/sequencer (FM
synthesizer and MIDI output) */
@@ -190,7 +126,7 @@ If your card has nonstandard I/O address or IRQ number, change defines
#define SND_DEV_DSP16 5 /* Like /dev/dsp but 16 bits/sample */
#define SND_DEV_STATUS 6 /* /dev/sndstat */
/* #7 not in use now. Was in 2.4. Free for use after v3.0. */
-#define SND_DEV_SEQ2 8 /* /dev/sequecer, level 2 interface */
+#define SND_DEV_SEQ2 8 /* /dev/sequencer, level 2 interface */
#define SND_DEV_SNDPROC 9 /* /dev/sndproc for programmable devices */
#define SND_DEV_PSS SND_DEV_SNDPROC
@@ -200,34 +136,44 @@ If your card has nonstandard I/O address or IRQ number, change defines
#define OFF 0
#define MAX_AUDIO_DEV 5
-#define MAX_MIXER_DEV 2
+#define MAX_MIXER_DEV 5
#define MAX_SYNTH_DEV 3
#define MAX_MIDI_DEV 6
#define MAX_TIMER_DEV 3
struct fileinfo {
- int mode; /* Open mode */
- };
+ int mode; /* Open mode */
+ int flags;
+ int dummy; /* Reference to file-flags. OS-dependent. */
+};
struct address_info {
int io_base;
int irq;
int dma;
+ int dma2;
+ int always_detect; /* 1=Trust me, it's there */
+ char *name;
+ sound_os_info *osp; /* OS specific info */
+ int card_subtype; /* Driver specific. Usually 0 */
};
#define SYNTH_MAX_VOICES 32
struct voice_alloc_info {
- int max_voice;
- int used_voices;
- int ptr; /* For device specific use */
- unsigned short map[SYNTH_MAX_VOICES]; /* (ch << 8) | (note+1) */
- };
+ int max_voice;
+ int used_voices;
+ int ptr; /* For device specific use */
+ unsigned short map[SYNTH_MAX_VOICES]; /* (ch << 8) | (note+1) */
+ int timestamp;
+ int alloc_times[SYNTH_MAX_VOICES];
+};
struct channel_info {
- int pgm_num;
- unsigned char controllers[128];
- };
+ int pgm_num;
+ int bender_value;
+ unsigned char controllers[128];
+};
/*
* Process wakeup reasons
@@ -238,21 +184,22 @@ struct channel_info {
#define WK_SIGNAL 0x04
#define WK_SLEEP 0x08
-#define OPEN_READ 1
-#define OPEN_WRITE 2
-#define OPEN_READWRITE 3
+#define OPEN_READ PCM_ENABLE_INPUT
+#define OPEN_WRITE PCM_ENABLE_OUTPUT
+#define OPEN_READWRITE (OPEN_READ|OPEN_WRITE)
-#include "os.h"
-#include "sound_calls.h"
-#include "dev_table.h"
+#include <i386/isa/sound/sound_calls.h>
+#include <i386/isa/sound/dev_table.h>
#ifndef DEB
#define DEB(x)
+#endif
+#ifndef DDB
+/* #define DDB(x) x XXX */
+#define DDB(x)
+#endif
#define TIMER_ARMED 121234
#define TIMER_NOT_ARMED 1
-#define FUTURE_VERSION
-#endif
-
#endif
diff --git a/sys/i386/isa/sound/sound_switch.c b/sys/i386/isa/sound/sound_switch.c
index fe73aea93e07..763a10ca1201 100644
--- a/sys/i386/isa/sound/sound_switch.c
+++ b/sys/i386/isa/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,27 +24,14 @@
* 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"
+#include <i386/isa/sound/sound_config.h>
-#ifdef CONFIGURE_SOUNDCARD
+#if NSND > 0
-struct sbc_device
- {
- int usecount;
- };
-
-static struct sbc_device sbc_devices[SND_NDEVS] =
-{
- {0}};
-
-static int in_use = 0; /*
-
-
- * * * * Total # of open device files
- * (excluding * * * minor 0) */
+#define SNDSTAT_BUF_SIZE 4000
/*
* /dev/sndstatus -device
@@ -54,475 +41,459 @@ static int status_len, status_ptr;
static int status_busy = 0;
static int
-put_status (char *s)
+put_status(char *s)
{
- int l;
+ int l = strlen(s);
- for (l = 0; l < 256, s[l]; l++); /*
- * l=strlen(s);
- */
+ if (status_len + l >= SNDSTAT_BUF_SIZE)
+ return 0;
- if (status_len + l >= 4000)
- return 0;
+ bcopy(s, &status_buf[status_len], l);
+ status_len += l;
- memcpy (&status_buf[status_len], s, l);
- status_len += l;
-
- return 1;
+ return 1;
}
+/*
+ * in principle, we never overflow the buffer. But... if radix=2 ...
+ * and if smaller... lr970711
+ */
+
static int
-put_status_int (unsigned int val, int radix)
+put_status_int(u_int val, int radix)
{
- int l, v;
+ int l, v;
+ static char hx[] = "0123456789abcdef";
+ char buf[33]; /* int is 32 bit+null, in base 2 */
- static char hx[] = "0123456789abcdef";
- char buf[11];
+ if (radix < 2 || radix > 16) /* better than panic */
+ return put_status("???");
- if (!val)
- return put_status ("0");
+ if (!val)
+ return put_status("0");
- l = 0;
- buf[10] = 0;
+ l = 0;
+ buf[10] = 0;
- while (val)
- {
- v = val % radix;
- val = val / radix;
+ while (val) {
+ 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;
+ if (status_len + l >= SNDSTAT_BUF_SIZE)
+ return 0;
- memcpy (&status_buf[status_len], &buf[10 - l], l);
- status_len += l;
+ bcopy(&buf[10 - l], &status_buf[status_len], l);
+ status_len += l;
- return 1;
+ return 1;
}
static void
-init_status (void)
+init_status(void)
{
- /*
- * Write the status information to the status_buf and update status_len.
- * There is a limit of 4000 bytes for the data.
- */
-
- int i;
-
- status_ptr = 0;
-
- put_status ("Sound Driver:" SOUND_VERSION_STRING
- " (" SOUND_CONFIG_DATE " " SOUND_CONFIG_BY "@"
- SOUND_CONFIG_HOST "." SOUND_CONFIG_DOMAIN ")"
- "\n");
-
- if (!put_status ("Config options: "))
- return;
- if (!put_status_int (SELECTED_SOUND_OPTIONS, 16))
- return;
-
- if (!put_status ("\n\nInstalled drivers: \n"))
- return;
-
- for (i = 0; i < (num_sound_drivers - 1); i++)
- {
- if (!put_status ("Type "))
- return;
- if (!put_status_int (sound_drivers[i].card_type, 10))
- return;
- if (!put_status (": "))
- return;
- if (!put_status (sound_drivers[i].name))
- return;
+ /*
+ * Write the status information to the status_buf and update
+ * status_len. There is a limit of SNDSTAT_BUF_SIZE bytes for the data.
+ * put_status handles this and returns 0 in case of failure. Since
+ * it never oveflows the buffer, we do not care to check.
+ */
+
+ int i;
+
+ status_ptr = 0;
+
+#ifdef SOUND_UNAME_A
+ put_status("VoxWare Sound Driver:" SOUND_VERSION_STRING
+ " (" SOUND_CONFIG_DATE " " SOUND_CONFIG_BY ",\n"
+ SOUND_UNAME_A ")\n");
+#else
+ put_status("VoxWare Sound Driver:" SOUND_VERSION_STRING
+ " (" SOUND_CONFIG_DATE " " SOUND_CONFIG_BY "@"
+ SOUND_CONFIG_HOST "." SOUND_CONFIG_DOMAIN ")\n");
+#endif
- if (!put_status ("\n"))
+ put_status("Config options: ") ;
+ /* put_status_int(SELECTED_SOUND_OPTIONS, 16) ; */
+ put_status("\n\nInstalled drivers: \n") ;
+
+ for (i = 0; i < num_sound_drivers; i++)
+ if (sound_drivers[i].card_type != 0) {
+ put_status("Type ") ;
+ put_status_int(sound_drivers[i].card_type, 10);
+ put_status(": ") ;
+ put_status(sound_drivers[i].name) ;
+ put_status("\n") ;
+ }
+ put_status("\n\nCard config: \n") ;
+
+ for (i = 0; i < num_sound_cards; i++)
+ if (snd_installed_cards[i].card_type != 0) {
+ int drv, tmp;
+
+ if (!snd_installed_cards[i].enabled)
+ put_status("(") ;
+
+ if ((drv = snd_find_driver(snd_installed_cards[i].card_type)) != -1)
+ put_status(sound_drivers[drv].name) ;
+
+ put_status(" at 0x") ;
+ put_status_int(snd_installed_cards[i].config.io_base, 16);
+
+ put_status(" irq ") ;
+ tmp = snd_installed_cards[i].config.irq;
+ if (tmp < 0)
+ tmp = -tmp;
+ put_status_int(tmp, 10) ;
+
+ if (snd_installed_cards[i].config.dma != -1) {
+ put_status(" drq ") ;
+ put_status_int(snd_installed_cards[i].config.dma, 10) ;
+ if (snd_installed_cards[i].config.dma2 != -1) {
+ put_status(",") ;
+ put_status_int(snd_installed_cards[i].config.dma2, 10) ;
+ }
+ }
+ if (!snd_installed_cards[i].enabled)
+ put_status(")") ;
+
+ put_status("\n") ;
+ }
+ if (!sound_started) {
+ put_status("\n\n***** Sound driver not started *****\n\n");
return;
}
+#ifndef CONFIG_AUDIO
+ put_status("\nAudio devices: NOT ENABLED IN CONFIG\n") ;
+#else
+ put_status("\nAudio devices:\n") ;
- if (!put_status ("\n\nCard config: \n"))
- return;
-
- for (i = 0; i < (num_sound_cards - 1); i++)
- {
- int drv;
-
- if (!snd_installed_cards[i].enabled)
- if (!put_status ("("))
- return;
-
- /*
- * if (!put_status_int(snd_installed_cards[i].card_type, 10)) return;
- * if (!put_status (": ")) return;
- */
-
- if ((drv = snd_find_driver (snd_installed_cards[i].card_type)) != -1)
- if (!put_status (sound_drivers[drv].name))
- return;
-
- if (!put_status (" at 0x"))
- return;
- if (!put_status_int (snd_installed_cards[i].config.io_base, 16))
- return;
- if (!put_status (" irq "))
- return;
- if (!put_status_int (snd_installed_cards[i].config.irq, 10))
- return;
- if (!put_status (" drq "))
- return;
- if (!put_status_int (snd_installed_cards[i].config.dma, 10))
- return;
+ for (i = 0; i < num_audiodevs; i++) {
+ put_status_int(i, 10) ;
+ put_status(": ") ;
+ put_status(audio_devs[i]->name) ;
- if (!snd_installed_cards[i].enabled)
- if (!put_status (")"))
- return;
+ if (audio_devs[i]->flags & DMA_DUPLEX)
+ put_status(" (DUPLEX)") ;
- if (!put_status ("\n"))
- return;
+ put_status("\n") ;
}
+#endif
- if (!put_status ("\nPCM devices:\n"))
- return;
+#ifndef CONFIG_SEQUENCER
+ put_status("\nSynth devices: NOT ENABLED IN CONFIG\n");
+#else
+ put_status("\nSynth devices:\n") ;
- for (i = 0; i < num_audiodevs; i++)
- {
- if (!put_status_int (i, 10))
- return;
- if (!put_status (": "))
- return;
- if (!put_status (audio_devs[i]->name))
- return;
- if (!put_status ("\n"))
- return;
+ for (i = 0; i < num_synths; i++) {
+ put_status_int(i, 10) ;
+ put_status(": ") ;
+ put_status(synth_devs[i]->info->name) ;
+ put_status("\n") ;
}
+#endif
- if (!put_status ("\nSynth devices:\n"))
- return;
+#ifndef CONFIG_MIDI
+ put_status("\nMidi devices: NOT ENABLED IN CONFIG\n") ;
+#else
+ put_status("\nMidi devices:\n") ;
- 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;
+ for (i = 0; i < num_midis; i++) {
+ put_status_int(i, 10) ;
+ put_status(": ") ;
+ put_status(midi_devs[i]->info.name) ;
+ put_status("\n") ;
}
+#endif
- if (!put_status ("\nMidi devices:\n"))
- return;
+ put_status("\nTimers:\n");
- 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;
+ for (i = 0; i < num_sound_timers; i++) {
+ put_status_int(i, 10);
+ put_status(": ");
+ put_status(sound_timer_devs[i]->info.name);
+ put_status("\n");
}
- if (!put_status ("\nMIDI Timers:\n"))
- return;
+ put_status("\nMixers:\n");
- for (i = 0; i < num_sound_timers; i++)
- {
- if (!put_status_int (i, 10))
- return;
- if (!put_status (": "))
- return;
- if (!put_status (sound_timer_devs[i]->info.name))
- return;
- if (!put_status ("\n"))
- return;
+ for (i = 0; i < num_mixers; i++) {
+ put_status_int(i, 10);
+ put_status(": ");
+ put_status(mixer_devs[i]->name);
+ put_status("\n");
}
-
- if (!put_status ("\n"))
- return;
- if (!put_status_int (num_mixers, 10))
- return;
- if (!put_status (" mixer(s) installed\n"))
- return;
}
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.
- */
- int l, c;
+ /*
+ * Return at most 'count' bytes from the status_buf.
+ */
+ int l, c;
- l = count;
- c = status_len - status_ptr;
+ l = count;
+ c = status_len - status_ptr;
- if (l > c)
- l = c;
- if (l <= 0)
- return 0;
+ if (l > c)
+ l = c;
+ if (l <= 0)
+ return 0;
- COPY_TO_USER (buf, 0, &status_buf[status_ptr], l);
- status_ptr += l;
- return l;
+ if (uiomove(&status_buf[status_ptr], l, buf)) {
+ printf("sb: Bad copyout()!\n");
+ };
+ 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));
+ DEB(printf("sound_read_sw(dev=%d, count=%d)\n", dev, count));
- switch (dev & 0x0f)
- {
+ switch (dev & 0x0f) {
case SND_DEV_STATUS:
- return read_status (buf, count);
- break;
+ return read_status(buf, count);
+ break;
+#ifdef CONFIG_AUDIO
case SND_DEV_DSP:
case SND_DEV_DSP16:
case SND_DEV_AUDIO:
- return audio_read (dev, file, buf, count);
- break;
+ return audio_read(dev, file, buf, count);
+ break;
+#endif
+#ifdef CONFIG_SEQUENCER
case SND_DEV_SEQ:
case SND_DEV_SEQ2:
- return sequencer_read (dev, file, buf, count);
- break;
-
-#ifndef EXCLUDE_MIDI
- case SND_DEV_MIDIN:
- return MIDIbuf_read (dev, file, buf, count);
+ return sequencer_read(dev, file, buf, count);
+ break;
#endif
-#ifndef EXCLUDE_PSS
- case SND_DEV_PSS:
- return pss_read (dev, file, buf, count);
+#ifdef CONFIG_MIDI
+ case SND_DEV_MIDIN:
+ return MIDIbuf_read(dev, file, buf, count);
#endif
default:
- printk ("Sound: Undefined minor device %d\n", dev);
+ printf("Sound: Undefined minor device %d\n", dev);
}
- return RET_ERROR (EPERM);
+ return -(EPERM);
}
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));
+ DEB(printf("sound_write_sw(dev=%d, count=%d)\n", dev, count));
- switch (dev & 0x0f)
- {
+ switch (dev & 0x0f) {
+#ifdef CONFIG_SEQUENCER
case SND_DEV_SEQ:
case SND_DEV_SEQ2:
- return sequencer_write (dev, file, buf, count);
- break;
+ return sequencer_write(dev, file, buf, count);
+ break;
+#endif
+#ifdef CONFIG_AUDIO
case SND_DEV_DSP:
case SND_DEV_DSP16:
case SND_DEV_AUDIO:
- return audio_write (dev, file, buf, count);
- break;
-
-#ifndef EXCLUDE_MIDI
- case SND_DEV_MIDIN:
- return MIDIbuf_write (dev, file, buf, count);
+ return audio_write(dev, file, buf, count);
+ break;
#endif
-#ifndef EXCLUDE_PSS
- case SND_DEV_PSS:
- return pss_write (dev, file, buf, count);
+#ifdef CONFIG_MIDI
+ case SND_DEV_MIDIN:
+ return MIDIbuf_write(dev, file, buf, count);
#endif
default:
- return RET_ERROR (EPERM);
+ return -(EPERM);
}
- return count;
+ return count;
}
int
-sound_open_sw (int dev, struct fileinfo *file)
+sound_open_sw(int dev, struct fileinfo * file)
{
- int retval;
+ int retval;
- DEB (printk ("sound_open_sw(dev=%d) : usecount=%d\n", dev, sbc_devices[dev].usecount));
+ DEB(printf("sound_open_sw(dev=%d)\n", dev));
- if ((dev >= SND_NDEVS) || (dev < 0))
- {
- printk ("Invalid minor device %d\n", dev);
- return RET_ERROR (ENXIO);
+ if ((dev >= SND_NDEVS) || (dev < 0)) {
+ printf("Invalid minor device %d\n", dev);
+ return -(ENXIO);
}
-
- switch (dev & 0x0f)
- {
+ switch (dev & 0x0f) {
case SND_DEV_STATUS:
- if (status_busy)
- return RET_ERROR (EBUSY);
- status_busy = 1;
- if ((status_buf = (char *) KERNEL_MALLOC (4000)) == NULL)
- return RET_ERROR (EIO);
- status_len = status_ptr = 0;
- init_status ();
- break;
+ if (status_busy)
+ return -(EBUSY);
+ status_busy = 1;
+ if ((status_buf = (char *) malloc(SNDSTAT_BUF_SIZE, M_TEMP, M_WAITOK)) == NULL)
+ return -(EIO);
+ status_len = status_ptr = 0;
+ init_status();
+ break;
case SND_DEV_CTL:
- return 0;
- break;
+ return 0;
+ break;
+#ifdef CONFIG_SEQUENCER
case SND_DEV_SEQ:
case SND_DEV_SEQ2:
- if ((retval = sequencer_open (dev, file)) < 0)
- return retval;
- break;
-
-#ifndef EXCLUDE_MIDI
- case SND_DEV_MIDIN:
- if ((retval = MIDIbuf_open (dev, file)) < 0)
- return retval;
- break;
+ if ((retval = sequencer_open(dev, file)) < 0)
+ return retval;
+ break;
#endif
-#ifndef EXCLUDE_PSS
- case SND_DEV_PSS:
- if ((retval = pss_open (dev, file)) < 0)
- return retval;
- break;
+#ifdef CONFIG_MIDI
+ case SND_DEV_MIDIN:
+ if ((retval = MIDIbuf_open(dev, file)) < 0)
+ return retval;
+ break;
#endif
+#ifdef CONFIG_AUDIO
case SND_DEV_DSP:
case SND_DEV_DSP16:
case SND_DEV_AUDIO:
- if ((retval = audio_open (dev, file)) < 0)
- return retval;
- break;
+ if ((retval = audio_open(dev, file)) < 0)
+ return retval;
+ break;
+#endif
default:
- printk ("Invalid minor device %d\n", dev);
- return RET_ERROR (ENXIO);
+ printf("Invalid minor device %d\n", dev);
+ return -(ENXIO);
}
- sbc_devices[dev].usecount++;
- in_use++;
-
- return 0;
+ return 0;
}
void
-sound_release_sw (int dev, struct fileinfo *file)
+sound_release_sw(int dev, struct fileinfo * file)
{
- DEB (printk ("sound_release_sw(dev=%d)\n", dev));
+ DEB(printf("sound_release_sw(dev=%d)\n", dev));
- switch (dev & 0x0f)
- {
+ switch (dev & 0x0f) {
case SND_DEV_STATUS:
- if (status_buf)
- KERNEL_FREE (status_buf);
- status_buf = NULL;
- status_busy = 0;
- break;
+ if (status_buf)
+ free(status_buf, M_TEMP);
+ status_buf = NULL;
+ status_busy = 0;
+ break;
case SND_DEV_CTL:
- break;
+ break;
+#ifdef CONFIG_SEQUENCER
case SND_DEV_SEQ:
case SND_DEV_SEQ2:
- sequencer_release (dev, file);
- break;
-
-#ifndef EXCLUDE_MIDI
- case SND_DEV_MIDIN:
- MIDIbuf_release (dev, file);
- break;
+ sequencer_release(dev, file);
+ break;
#endif
-#ifndef EXCLUDE_PSS
- case SND_DEV_PSS:
- pss_release (dev, file);
- break;
+#ifdef CONFIG_MIDI
+ case SND_DEV_MIDIN:
+ MIDIbuf_release(dev, file);
+ break;
#endif
+#ifdef CONFIG_AUDIO
case SND_DEV_DSP:
case SND_DEV_DSP16:
case SND_DEV_AUDIO:
- audio_release (dev, file);
- break;
+ audio_release(dev, file);
+ break;
+#endif
default:
- printk ("Sound error: Releasing unknown device 0x%02x\n", dev);
+ printf("Sound error: Releasing unknown device 0x%02x\n", dev);
}
-
- sbc_devices[dev].usecount--;
- in_use--;
}
int
-sound_ioctl_sw (int dev, struct fileinfo *file,
- unsigned int cmd, unsigned long arg)
+sound_ioctl_sw(int dev, struct fileinfo * file, u_int cmd, ioctl_arg arg)
{
- DEB (printk ("sound_ioctl_sw(dev=%d, cmd=0x%x, arg=0x%x)\n", dev, cmd, arg));
-
- if ((dev & 0x0f) != SND_DEV_CTL && num_mixers > 0)
- if ((cmd >> 8) & 0xff == 'M') /*
- * Mixer ioctl
- */
- return mixer_devs[0]->ioctl (0, cmd, arg);
+ DEB(printf("sound_ioctl_sw(dev=%d, cmd=0x%x, arg=0x%x)\n", dev, cmd, arg));
+
+ if (((cmd >> 8) & 0xff) == 'M' && num_mixers > 0) /* Mixer ioctl */
+ if ((dev & 0x0f) != SND_DEV_CTL) {
+ int dtype = dev & 0x0f;
+ int mixdev;
+
+ switch (dtype) {
+#ifdef CONFIG_AUDIO
+ case SND_DEV_DSP:
+ case SND_DEV_DSP16:
+ case SND_DEV_AUDIO:
+ mixdev = audio_devs[dev >> 4]->mixer_dev;
+ if (mixdev < 0 || mixdev >= num_mixers)
+ return -(ENXIO);
+ return mixer_devs[mixdev]->ioctl(mixdev, cmd, arg);
+ break;
+#endif
- switch (dev & 0x0f)
- {
+ default:
+ return mixer_devs[0]->ioctl(0, cmd, arg);
+ }
+ }
+ switch (dev & 0x0f) {
case SND_DEV_CTL:
- if (!num_mixers)
- return RET_ERROR (ENXIO);
+ if (!num_mixers)
+ return -(ENXIO);
- dev = dev >> 4;
+ dev = dev >> 4;
- if (dev >= num_mixers)
- return RET_ERROR (ENXIO);
+ if (dev >= num_mixers)
+ return -(ENXIO);
- return mixer_devs[dev]->ioctl (dev, cmd, arg);
- break;
+ return mixer_devs[dev]->ioctl(dev, cmd, arg);
+ break;
+#ifdef CONFIG_SEQUENCER
case SND_DEV_SEQ:
case SND_DEV_SEQ2:
- return sequencer_ioctl (dev, file, cmd, arg);
- break;
+ return sequencer_ioctl(dev, file, cmd, arg);
+ break;
+#endif
+#ifdef CONFIG_AUDIO
case SND_DEV_DSP:
case SND_DEV_DSP16:
case SND_DEV_AUDIO:
- return audio_ioctl (dev, file, cmd, arg);
- break;
-
-#ifndef EXCLUDE_MIDI
- case SND_DEV_MIDIN:
- return MIDIbuf_ioctl (dev, file, cmd, arg);
- break;
+ return audio_ioctl(dev, file, cmd, arg);
+ break;
#endif
-#ifndef EXCLUDE_PSS
- case SND_DEV_PSS:
- return pss_ioctl (dev, file, cmd, arg);
- break;
+#ifdef CONFIG_MIDI
+ case SND_DEV_MIDIN:
+ return MIDIbuf_ioctl(dev, file, cmd, arg);
+ break;
#endif
default:
- return RET_ERROR (EPERM);
- break;
+ return -(EPERM);
+ break;
}
- return RET_ERROR (EPERM);
+ return -(EPERM);
}
#endif
diff --git a/sys/i386/isa/sound/sound_timer.c b/sys/i386/isa/sound/sound_timer.c
index c6544c82a7ee..8450b2d73503 100644
--- a/sys/i386/isa/sound/sound_timer.c
+++ b/sys/i386/isa/sound/sound_timer.c
@@ -1,11 +1,8 @@
/*
* sound/sound_timer.c
- *
- * Timer for the level 2 interface of the /dev/sequencer. Uses the
- * 80 and 320 usec timers of OPL-3 (PAS16 only) and GUS.
- *
+ *
* 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 +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
@@ -25,381 +22,322 @@
* 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
-#include "sound_config.h"
+#include <i386/isa/sound/sound_config.h>
-#ifdef CONFIGURE_SOUNDCARD
+#if NSND > 0
-#if !defined(EXCLUDE_SEQUENCER) && (!defined(EXCLUDE_GUS) || (!defined(EXCLUDE_PAS) && !defined(EXCLUDE_YM3812)))
+#if defined(CONFIG_SEQUENCER)
static volatile int initialized = 0, opened = 0, tmr_running = 0;
static volatile time_t tmr_offs, tmr_ctr;
-static volatile unsigned long ticks_offs;
+static volatile u_long ticks_offs;
static volatile int curr_tempo, curr_timebase;
-static volatile unsigned long curr_ticks;
-static volatile unsigned long next_event_time;
-static unsigned long prev_event_time;
-static volatile int select_addr, data_addr;
-static volatile int curr_timer = 0;
-static volatile unsigned long usecs_per_tmr; /* Length of the current interval */
+static volatile u_long curr_ticks;
+static volatile u_long next_event_time;
+static u_long prev_event_time;
+static volatile u_long usecs_per_tmr; /* Length of the current interval */
+static struct sound_lowlev_timer *tmr = NULL;
-static void
-timer_command (unsigned int addr, unsigned int val)
+static u_long
+tmr2ticks(int tmr_value)
{
- int i;
+ /*
+ * Convert timer ticks to MIDI ticks
+ */
- OUTB ((unsigned char) (addr & 0xff), select_addr);
+ u_long tmp;
+ u_long scale;
- for (i = 0; i < 2; i++)
- INB (select_addr);
+ tmp = tmr_value * usecs_per_tmr; /* Convert to usecs */
- OUTB ((unsigned char) (val & 0xff), data_addr);
+ scale = (60 * 1000000) / (curr_tempo * curr_timebase); /* usecs per MIDI tick */
- for (i = 0; i < 2; i++)
- INB (select_addr);
+ return (tmp + (scale / 2)) / scale;
}
static void
-arm_timer (int timer, unsigned int interval)
-{
-
- curr_timer = timer;
-
- if (timer == 1)
- {
- gus_write8 (0x46, 256 - interval); /* Set counter for timer 1 */
- gus_write8 (0x45, 0x04); /* Enable timer 1 IRQ */
- timer_command (0x04, 0x01); /* Start timer 1 */
- }
- else
- {
- gus_write8 (0x47, 256 - interval); /* Set counter for timer 2 */
- gus_write8 (0x45, 0x08); /* Enable timer 2 IRQ */
- timer_command (0x04, 0x02); /* Start timer 2 */
- }
-}
-
-static unsigned long
-tmr2ticks (int tmr_value)
+reprogram_timer(void)
{
- /*
- * Convert timer ticks to MIDI ticks
- */
-
- unsigned long tmp;
- unsigned long scale;
+ u_long usecs_per_tick;
- tmp = tmr_value * usecs_per_tmr; /* Convert to usecs */
+ usecs_per_tick = (60 * 1000000) / (curr_tempo * curr_timebase);
- scale = (60 * 1000000) / (curr_tempo * curr_timebase); /* usecs per MIDI tick */
+ /*
+ * Don't kill the system by setting too high timer rate
+ */
+ if (usecs_per_tick < 2000)
+ usecs_per_tick = 2000;
- return (tmp + (scale / 2)) / scale;
+ usecs_per_tmr = tmr->tmr_start(tmr->dev, usecs_per_tick);
}
-static void
-reprogram_timer (void)
+void
+sound_timer_syncinterval(u_int new_usecs)
{
- unsigned long usecs_per_tick;
- int timer_no, resolution;
- int divisor;
-
- usecs_per_tick = (60 * 1000000) / (curr_tempo * curr_timebase);
-
- /*
- * Don't kill the system by setting too high timer rate
- */
- if (usecs_per_tick < 2000)
- usecs_per_tick = 2000;
-
- if (usecs_per_tick > (256 * 80))
- {
- timer_no = 2;
- resolution = 320; /* usec */
- }
- else
- {
- timer_no = 1;
- resolution = 80; /* usec */
- }
-
- divisor = (usecs_per_tick + (resolution / 2)) / resolution;
- usecs_per_tmr = divisor * resolution;
-
- arm_timer (timer_no, divisor);
+ /*
+ * This routine is called by the hardware level if the clock
+ * frequency has changed for some reason.
+ */
+ tmr_offs = tmr_ctr;
+ ticks_offs += tmr2ticks(tmr_ctr);
+ tmr_ctr = 0;
+
+ usecs_per_tmr = new_usecs;
}
static void
-tmr_reset (void)
+tmr_reset(void)
{
- unsigned long flags;
-
- DISABLE_INTR (flags);
- tmr_offs = 0;
- ticks_offs = 0;
- tmr_ctr = 0;
- next_event_time = 0xffffffff;
- prev_event_time = 0;
- curr_ticks = 0;
- RESTORE_INTR (flags);
+ u_long flags;
+
+ flags = splhigh();
+ tmr_offs = 0;
+ ticks_offs = 0;
+ tmr_ctr = 0;
+ next_event_time = 0xffffffff;
+ prev_event_time = 0;
+ curr_ticks = 0;
+ splx(flags);
}
static int
-timer_open (int dev, int mode)
+timer_open(int dev, int mode)
{
- if (opened)
- return RET_ERROR (EBUSY);
+ if (opened)
+ return -(EBUSY);
- tmr_reset ();
- curr_tempo = 60;
- curr_timebase = HZ;
- opened = 1;
- reprogram_timer ();
+ tmr_reset();
+ curr_tempo = 60;
+ curr_timebase = hz;
+ opened = 1;
+ reprogram_timer();
- return 0;
+ return 0;
}
static void
-timer_close (int dev)
+timer_close(int dev)
{
- opened = tmr_running = 0;
- gus_write8 (0x45, 0); /* Disable both timers */
+ opened = tmr_running = 0;
+ tmr->tmr_disable(tmr->dev);
}
static int
-timer_event (int dev, unsigned char *event)
+timer_event(int dev, u_char *event)
{
- unsigned char cmd = event[1];
- unsigned long parm = *(int *) &event[4];
+ u_char cmd = event[1];
+ u_long parm = *(int *) &event[4];
- switch (cmd)
- {
+ switch (cmd) {
case TMR_WAIT_REL:
- parm += prev_event_time;
+ parm += prev_event_time;
case TMR_WAIT_ABS:
- if (parm > 0)
- {
- long time;
+ if (parm > 0) {
+ long time;
- if (parm <= curr_ticks) /* It's the time */
- return TIMER_NOT_ARMED;
+ if (parm <= curr_ticks) /* It's the time */
+ return TIMER_NOT_ARMED;
- time = parm;
- next_event_time = prev_event_time = time;
+ time = parm;
+ next_event_time = prev_event_time = time;
- return TIMER_ARMED;
+ return TIMER_ARMED;
}
- break;
+ break;
case TMR_START:
- tmr_reset ();
- tmr_running = 1;
- reprogram_timer ();
- break;
+ tmr_reset();
+ tmr_running = 1;
+ reprogram_timer();
+ break;
case TMR_STOP:
- tmr_running = 0;
- break;
+ tmr_running = 0;
+ break;
case TMR_CONTINUE:
- tmr_running = 1;
- reprogram_timer ();
- break;
+ tmr_running = 1;
+ reprogram_timer();
+ break;
case TMR_TEMPO:
- if (parm)
- {
- if (parm < 8)
- parm = 8;
- if (parm > 250)
- parm = 250;
- tmr_offs = tmr_ctr;
- ticks_offs += tmr2ticks (tmr_ctr);
- tmr_ctr = 0;
- curr_tempo = parm;
- reprogram_timer ();
+ if (parm) {
+ if (parm < 8)
+ parm = 8;
+ if (parm > 250)
+ parm = 250;
+ tmr_offs = tmr_ctr;
+ ticks_offs += tmr2ticks(tmr_ctr);
+ tmr_ctr = 0;
+ curr_tempo = parm;
+ reprogram_timer();
}
- break;
+ break;
case TMR_ECHO:
- seq_copy_to_input (event, 8);
- break;
+ seq_copy_to_input(event, 8);
+ break;
default:;
}
- return TIMER_NOT_ARMED;
+ return TIMER_NOT_ARMED;
}
-static unsigned long
-timer_get_time (int dev)
+static u_long
+timer_get_time(int dev)
{
- if (!opened)
- return 0;
+ if (!opened)
+ return 0;
- return curr_ticks;
+ return curr_ticks;
}
static int
-timer_ioctl (int dev,
- unsigned int cmd, unsigned int arg)
+timer_ioctl(int dev, u_int cmd, ioctl_arg arg)
{
- switch (cmd)
- {
+ switch (cmd) {
case SNDCTL_TMR_SOURCE:
- return IOCTL_OUT (arg, TMR_INTERNAL);
- break;
+ return *(int *) arg = TMR_INTERNAL;
+ break;
case SNDCTL_TMR_START:
- tmr_reset ();
- tmr_running = 1;
- return 0;
- break;
+ tmr_reset();
+ tmr_running = 1;
+ return 0;
+ break;
case SNDCTL_TMR_STOP:
- tmr_running = 0;
- return 0;
- break;
+ tmr_running = 0;
+ return 0;
+ break;
case SNDCTL_TMR_CONTINUE:
- tmr_running = 1;
- return 0;
- break;
+ tmr_running = 1;
+ return 0;
+ break;
case SNDCTL_TMR_TIMEBASE:
- {
- int val = IOCTL_IN (arg);
-
- if (val)
- {
- if (val < 1)
- val = 1;
- if (val > 1000)
- val = 1000;
- curr_timebase = val;
- }
-
- return IOCTL_OUT (arg, curr_timebase);
- }
- break;
+ {
+ int val = (*(int *) arg);
+
+ if (val) {
+ if (val < 1)
+ val = 1;
+ if (val > 1000)
+ val = 1000;
+ curr_timebase = val;
+ }
+ return *(int *) arg = curr_timebase;
+ }
+ break;
case SNDCTL_TMR_TEMPO:
- {
- int val = IOCTL_IN (arg);
-
- if (val)
- {
- if (val < 8)
- val = 8;
- if (val > 250)
- val = 250;
- tmr_offs = tmr_ctr;
- ticks_offs += tmr2ticks (tmr_ctr);
- tmr_ctr = 0;
- curr_tempo = val;
- reprogram_timer ();
- }
-
- return IOCTL_OUT (arg, curr_tempo);
- }
- break;
+ {
+ int val = (*(int *) arg);
+
+ if (val) {
+ if (val < 8)
+ val = 8;
+ if (val > 250)
+ val = 250;
+ tmr_offs = tmr_ctr;
+ ticks_offs += tmr2ticks(tmr_ctr);
+ tmr_ctr = 0;
+ curr_tempo = val;
+ reprogram_timer();
+ }
+ return *(int *) arg = curr_tempo;
+ }
+ break;
case SNDCTL_SEQ_CTRLRATE:
- if (IOCTL_IN (arg) != 0) /* Can't change */
- return RET_ERROR (EINVAL);
+ if ((*(int *) arg) != 0) /* Can't change */
+ return -(EINVAL);
- return IOCTL_OUT (arg, ((curr_tempo * curr_timebase) + 30) / 60);
- break;
+ return *(int *) arg = ((curr_tempo * curr_timebase) + 30) / 60;
+ break;
case SNDCTL_TMR_METRONOME:
- /* NOP */
- break;
+ /* NOP */
+ break;
- default:
+ default:;
}
- return RET_ERROR (EINVAL);
+ return -(EINVAL);
}
static void
-timer_arm (int dev, long time)
+timer_arm(int dev, long time)
{
- if (time < 0)
- time = curr_ticks + 1;
- else if (time <= curr_ticks) /* It's the time */
- return;
+ if (time < 0)
+ time = curr_ticks + 1;
+ else if (time <= curr_ticks) /* It's the time */
+ return;
- next_event_time = prev_event_time = time;
+ next_event_time = prev_event_time = time;
- return;
+ return;
}
static struct sound_timer_operations sound_timer =
{
- {"OPL-3/GUS Timer", 0},
- 1, /* Priority */
- 0, /* Local device link */
- timer_open,
- timer_close,
- timer_event,
- timer_get_time,
- timer_ioctl,
- timer_arm
+ {"GUS Timer", 0},
+ 1, /* Priority */
+ 0, /* Local device link */
+ timer_open,
+ timer_close,
+ timer_event,
+ timer_get_time,
+ timer_ioctl,
+ timer_arm
};
void
-sound_timer_interrupt (void)
+sound_timer_interrupt(void)
{
- gus_write8 (0x45, 0); /* Ack IRQ */
- timer_command (4, 0x80); /* Reset IRQ flags */
+ if (!opened)
+ return;
- if (!opened)
- return;
+ tmr->tmr_restart(tmr->dev);
- if (curr_timer == 1)
- gus_write8 (0x45, 0x04); /* Start timer 1 again */
- else
- gus_write8 (0x45, 0x08); /* Start timer 2 again */
+ if (!tmr_running)
+ return;
- if (!tmr_running)
- return;
+ tmr_ctr++;
+ curr_ticks = ticks_offs + tmr2ticks(tmr_ctr);
- tmr_ctr++;
- curr_ticks = ticks_offs + tmr2ticks (tmr_ctr);
-
- if (curr_ticks >= next_event_time)
- {
- next_event_time = 0xffffffff;
- sequencer_timer ();
+ if (curr_ticks >= next_event_time) {
+ next_event_time = 0xffffffff;
+ sequencer_timer(0);
}
}
void
-sound_timer_init (int io_base)
+sound_timer_init(struct sound_lowlev_timer * t, char *name)
{
- int n;
+ int n;
- if (initialized)
- return; /* There is already a similar timer */
+ if (initialized || t == NULL)
+ return; /* There is already a similar timer */
- select_addr = io_base;
- data_addr = io_base + 1;
+ initialized = 1;
+ tmr = t;
- initialized = 1;
+ if (num_sound_timers >= MAX_TIMER_DEV)
+ n = 0; /* Overwrite the system timer */
+ else
+ n = num_sound_timers++;
-#if 1
- if (num_sound_timers >= MAX_TIMER_DEV)
- n = 0; /* Overwrite the system timer */
- else
- n = num_sound_timers++;
-#else
- n = 0;
-#endif
+ strcpy(sound_timer.info.name, name);
- sound_timer_devs[n] = &sound_timer;
+ sound_timer_devs[n] = &sound_timer;
}
#endif
diff --git a/sys/i386/isa/sound/soundcard.c b/sys/i386/isa/sound/soundcard.c
index b9e6ee5f1b70..a83df9377eba 100644
--- a/sys/i386/isa/sound/soundcard.c
+++ b/sys/i386/isa/sound/soundcard.c
@@ -4,398 +4,601 @@
* Soundcard driver for 386BSD.
*
* Copyright by Hannu Savolainen 1993
- *
+ *
* Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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"
+#include <i386/isa/sound/sound_config.h>
-#ifdef CONFIGURE_SOUNDCARD
+#if NSND > 0 /* from "snd.h" */
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+#include <vm/vm_extern.h>
+#include <sys/mman.h>
-#include "dev_table.h"
+#include <i386/isa/sound/dev_table.h>
+#include <i386/isa/isa_device.h>
+#include <i386/isa/isa.h>
-u_int snd1mask;
-u_int snd2mask;
-u_int snd3mask;
-u_int snd4mask;
-u_int snd5mask;
-u_int snd6mask;
-u_int snd7mask;
-u_int snd8mask;
-u_int snd9mask;
-#define FIX_RETURN(ret) {if ((ret)<0) return -(ret); else return 0;}
+/*
+** Register definitions for DMA controller 1 (channels 0..3):
+*/
+#define DMA1_CHN(c) (IO_DMA1 + 1*(2*(c))) /* addr reg for channel c */
+#define DMA1_SMSK (IO_DMA1 + 1*10) /* single mask register */
+#define DMA1_MODE (IO_DMA1 + 1*11) /* mode register */
+#define DMA1_FFC (IO_DMA1 + 1*12) /* clear first/last FF */
-static int timer_running = 0;
+/*
+** Register definitions for DMA controller 2 (channels 4..7):
+*/
+#define DMA2_CHN(c) (IO_DMA2 + 2*(2*(c))) /* addr reg for channel c */
+#define DMA2_SMSK (IO_DMA2 + 2*10) /* single mask register */
+#define DMA2_MODE (IO_DMA2 + 2*11) /* mode register */
+#define DMA2_FFC (IO_DMA2 + 2*12) /* clear first/last FF */
+
+
+#define FIX_RETURN(ret) {if ((ret)<0) return -(ret); else return 0;}
-static int soundcards_installed = 0; /* Number of installed
- * soundcards */
+static int soundcards_installed = 0; /* Number of installed soundcards */
static int soundcard_configured = 0;
static struct fileinfo files[SND_NDEVS];
+struct selinfo selinfo[SND_NDEVS >> 4];
+
+int
+MIDIbuf_poll (int dev, struct fileinfo *file, int events, select_table * wait);
+
+int
+audio_poll(int dev, struct fileinfo * file, int events, select_table * wait);
+
+int
+sequencer_poll (int dev, struct fileinfo *file, int events, select_table * wait);
+
+void sndintr __P((int unit));
+int sndprobe __P((struct isa_device *));
+int sndattach __P((struct isa_device *));
+int sndmmap __P((dev_t dev, int offset, int nprot ));
+
+static d_open_t sndopen;
+static d_close_t sndclose;
+static d_ioctl_t sndioctl;
+static d_read_t sndread;
+static d_write_t sndwrite;
+static d_poll_t sndpoll;
+
+static char driver_name[] = "snd";
+
+#define CDEV_MAJOR 30
+static struct cdevsw snd_cdevsw = {
+ sndopen, sndclose, sndread, sndwrite,
+ sndioctl, nxstop, nxreset, nxdevtotty,
+ sndpoll, sndmmap, nxstrategy, driver_name,
+ NULL, -1,
+};
+
+
+
+
+static void sound_mem_init(void);
+
+/*
+ * for each "device XXX" entry in the config file, we have
+ * a struct isa_driver which is linked into isa_devtab_null[]
+ *
+ * XXX It is a bit stupid to call the generic routine so many times and
+ * switch then to the specific one, but the alternative way would be
+ * to replicate some code in the probe/attach routines.
+ */
-int sndprobe (struct isa_device *dev);
-int sndattach (struct isa_device *dev);
-int sndopen (dev_t dev, int flags);
-int sndclose (dev_t dev, int flags);
-int sndioctl (dev_t dev, int cmd, caddr_t arg, int mode);
-int sndread (int dev, struct uio *uio);
-int sndwrite (int dev, struct uio *uio);
-int sndselect (int dev, int rw);
-static void sound_mem_init(void);
-
-unsigned long
+struct isa_driver opldriver = {sndprobe, sndattach, "opl"};
+struct isa_driver trixdriver = {sndprobe, sndattach, "trix"};
+struct isa_driver trixsbdriver = {sndprobe, sndattach, "trixsb"};
+struct isa_driver sbdriver = {sndprobe, sndattach, "sb"};
+struct isa_driver sbxvidriver = {sndprobe, sndattach, "sbxvi"};
+struct isa_driver sbmididriver = {sndprobe, sndattach, "sbmidi"};
+struct isa_driver awedriver = {sndprobe, sndattach, "awe"};
+struct isa_driver pasdriver = {sndprobe, sndattach, "pas"};
+struct isa_driver mpudriver = {sndprobe, sndattach, "mpu"};
+struct isa_driver gusdriver = {sndprobe, sndattach, "gus"};
+struct isa_driver gusxvidriver = {sndprobe, sndattach, "gusxvi"};
+struct isa_driver gusmaxdriver = {sndprobe, sndattach, "gusmax"};
+struct isa_driver uartdriver = {sndprobe, sndattach, "uart"};
+struct isa_driver mssdriver = {sndprobe, sndattach, "mss"};
+struct isa_driver sscapedriver = {sndprobe, sndattach, "sscape"};
+struct isa_driver sscape_mssdriver = {sndprobe, sndattach, "sscape_mss"};
+
+short ipri_to_irq(u_short ipri);
+
+u_long
get_time(void)
{
- extern struct timeval time;
- struct timeval timecopy;
- int x;
-
- x = splclock();
- timecopy = time;
- splx(x);
- return timecopy.tv_usec/(1000000/HZ) +
- (unsigned long)timecopy.tv_sec*HZ;
+ struct timeval timecopy;
+ int x;
+
+ x = splclock();
+ timecopy = time;
+ splx(x);
+ return timecopy.tv_usec / (1000000 / hz) +
+ (u_long) timecopy.tv_sec * hz;
}
int
-sndread (int dev, struct uio *buf)
+sndmmap( dev_t dev, int offset, int nprot )
{
- int count = buf->uio_resid;
+ int unit;
+ struct dma_buffparms * dmap;
+
+ dev = minor(dev) >> 4;
+ if (dev > 0 ) return (-1);
- dev = minor (dev);
+ dmap = audio_devs[dev]->dmap_out;
- FIX_RETURN (sound_read_sw (dev, &files[dev], buf, count));
+ if (nprot & PROT_EXEC)
+ return( -1 );
+ dmap->mapping_flags |= DMA_MAP_MAPPED ;
+ return( i386_btop(vtophys(dmap->raw_buf) + offset) );
}
-int
-sndwrite (int dev, struct uio *buf)
-{
- int count = buf->uio_resid;
- dev = minor (dev);
+static int
+sndread(dev_t dev, struct uio * buf, int flag)
+{
+ int count = buf->uio_resid;
- FIX_RETURN (sound_write_sw (dev, &files[dev], buf, count));
+ dev = minor(dev);
+ FIX_RETURN(sound_read_sw(dev, &files[dev], buf, count));
}
-int
-sndopen (dev_t dev, int flags)
+
+static int
+sndwrite(dev_t dev, struct uio * buf, int flag)
{
- int retval;
+ int count = buf->uio_resid;
- dev = minor (dev);
+ dev = minor(dev);
+ FIX_RETURN(sound_write_sw(dev, &files[dev], buf, count));
+}
- if (!soundcard_configured && dev)
- {
- printk ("SoundCard Error: The soundcard system has not been configured\n");
- FIX_RETURN (-ENODEV);
+static int
+sndopen(dev_t dev, int flags, int mode, struct proc * p)
+{
+ int retval;
+ struct fileinfo tmp_file;
+
+ dev = minor(dev);
+ if (!soundcard_configured && dev) {
+ printf("SoundCard Error: soundcard system has not been configured\n");
+ return ENODEV ;
}
+ tmp_file.mode = 0;
+
+ if (flags & FREAD && flags & FWRITE)
+ tmp_file.mode = OPEN_READWRITE;
+ else if (flags & FREAD)
+ tmp_file.mode = OPEN_READ;
+ else if (flags & FWRITE)
+ tmp_file.mode = OPEN_WRITE;
- files[dev].mode = 0;
+ selinfo[dev >> 4].si_pid = 0;
+ selinfo[dev >> 4].si_flags = 0;
+ if ((retval = sound_open_sw(dev, &tmp_file)) < 0)
+ FIX_RETURN(retval);
- if (flags & FREAD && flags & FWRITE)
- files[dev].mode = OPEN_READWRITE;
- else if (flags & FREAD)
- files[dev].mode = OPEN_READ;
- else if (flags & FWRITE)
- files[dev].mode = OPEN_WRITE;
+ bcopy((char *) &tmp_file, (char *) &files[dev], sizeof(tmp_file));
- FIX_RETURN(sound_open_sw (dev, &files[dev]));
+ FIX_RETURN(retval);
}
-int
-sndclose (dev_t dev, int flags)
+
+static int
+sndclose(dev_t dev, int flags, int mode, struct proc * p)
{
+ dev = minor(dev);
+ sound_release_sw(dev, &files[dev]);
- dev = minor (dev);
+ return 0 ;
+}
- sound_release_sw(dev, &files[dev]);
- FIX_RETURN (0);
+static int
+sndioctl(dev_t dev, int cmd, caddr_t arg, int mode, struct proc * p)
+{
+ dev = minor(dev);
+ FIX_RETURN(sound_ioctl_sw(dev, &files[dev], cmd, arg));
}
int
-sndioctl (dev_t dev, int cmd, caddr_t arg, int mode)
+sndpoll(dev_t dev, int events, struct proc * p)
{
- dev = minor (dev);
+ dev = minor(dev);
+ dev = minor(dev);
+
+ /* printf ("snd_select(dev=%d, rw=%d, pid=%d)\n", dev, rw, p->p_pid); */
+#ifdef ALLOW_POLL
+ switch (dev & 0x0f) {
+#ifdef CONFIG_SEQUENCER
+ case SND_DEV_SEQ:
+ case SND_DEV_SEQ2:
+ return sequencer_poll(dev, &files[dev], events, p);
+ break;
+#endif
+
+#ifdef CONFIG_MIDI
+ case SND_DEV_MIDIN:
+ return MIDIbuf_poll(dev, &files[dev], events, p);
+ break;
+#endif
+
+#ifdef CONFIG_AUDIO
+ case SND_DEV_DSP:
+ case SND_DEV_DSP16:
+ case SND_DEV_AUDIO:
+
+ return audio_poll(dev, &files[dev], events, p);
+ break;
+#endif
- FIX_RETURN (sound_ioctl_sw (dev, &files[dev], cmd, (unsigned int) arg));
+ default:
+ return 0;
+ }
+
+#endif /* ALLOW_POLL */
+ DEB(printf("sound_ioctl(dev=%d, cmd=0x%x, arg=0x%x)\n", dev, cmd, arg));
+
+ return 0 ;
}
-int
-sndselect (int dev, int rw)
+/* XXX this should become ffs(ipri), perhaps -1 lr 970705 */
+short
+ipri_to_irq(u_short ipri)
{
- dev = minor (dev);
+ /*
+ * Converts the ipri (bitmask) to the corresponding irq number
+ */
+ int irq;
- DEB (printk ("sound_ioctl(dev=%d, cmd=0x%x, arg=0x%x)\n", dev, cmd, arg));
+ for (irq = 0; irq < 16; irq++)
+ if (ipri == (1 << irq))
+ return irq;
- FIX_RETURN (0);
+ return -1; /* Invalid argument */
}
-static short
-ipri_to_irq (unsigned short ipri)
+static int
+driver_to_voxunit(struct isa_driver * driver)
{
- /*
- * Converts the ipri (bitmask) to the corresponding irq number
- */
- int irq;
+ /*
+ * converts a sound driver pointer into the equivalent VoxWare device
+ * unit number
+ */
+ if (driver == &opldriver)
+ return (SNDCARD_ADLIB);
+ else if (driver == &sbdriver)
+ return (SNDCARD_SB);
+ else if (driver == &pasdriver)
+ return (SNDCARD_PAS);
+ else if (driver == &gusdriver)
+ return (SNDCARD_GUS);
+ else if (driver == &mpudriver)
+ return (SNDCARD_MPU401);
+ else if (driver == &sbxvidriver)
+ return (SNDCARD_SB16);
+ else if (driver == &sbmididriver)
+ return (SNDCARD_SB16MIDI);
+ else if(driver == &awedriver)
+ return(SNDCARD_AWE32);
+ else if (driver == &uartdriver)
+ return (SNDCARD_UART6850);
+ else if (driver == &gusdriver)
+ return (SNDCARD_GUS16);
+ else if (driver == &mssdriver)
+ return (SNDCARD_MSS);
+ else if (driver == &sscapedriver)
+ return(SNDCARD_SSCAPE);
+ else if (driver == &sscape_mssdriver)
+ return(SNDCARD_SSCAPE_MSS);
+ else if (driver == &trixdriver)
+ return (SNDCARD_TRXPRO);
+ else if (driver == &trixsbdriver)
+ return (SNDCARD_TRXPRO_SB);
+ else
+ return (0);
+}
- for (irq = 0; irq < 16; irq++)
- if (ipri == (1 << irq))
- return irq;
+/*
+ * very dirty: tmp_osp is allocated in sndprobe, and used at the next
+ * call in sndattach
+ */
- return -1; /* Invalid argument */
-}
+static sound_os_info *temp_osp;
+
+/*
+ * sndprobe is called for each isa_device. From here, a voxware unit
+ * number is determined, and the appropriate probe routine is selected.
+ * The parameters from the config line are passed to the hw_config struct.
+ */
int
-sndprobe (struct isa_device *dev)
+sndprobe(struct isa_device * dev)
{
- struct address_info hw_config;
-
- hw_config.io_base = dev->id_iobase;
- hw_config.irq = ipri_to_irq (dev->id_irq);
- hw_config.dma = dev->id_drq;
-
- return sndtable_probe (dev->id_unit, &hw_config);
+ struct address_info hw_config;
+ int unit;
+
+ temp_osp = (sound_os_info *)malloc(sizeof(sound_os_info),
+ M_DEVBUF, M_NOWAIT);
+ if (!temp_osp)
+ panic("SOUND: Cannot allocate memory\n");
+
+ /*
+ * get config info from the kernel config. These may be overridden
+ * by the local autoconfiguration routines though (e.g. pnp stuff).
+ */
+
+ hw_config.io_base = dev->id_iobase;
+ hw_config.irq = ipri_to_irq(dev->id_irq);
+ hw_config.dma = dev->id_drq;
+
+ /*
+ * misuse the flags field for read dma. Note that, to use 0 as
+ * read dma channel, one of the high bits should be set. lr970705 XXX
+ */
+
+ if (dev->id_flags != 0)
+ hw_config.dma2 = dev->id_flags & 0x7;
+ else
+ hw_config.dma2 = -1;
+
+ hw_config.always_detect = 0;
+ hw_config.name = NULL;
+ hw_config.card_subtype = 0;
+
+ temp_osp->unit = dev->id_unit;
+ hw_config.osp = temp_osp;
+ unit = driver_to_voxunit(dev->id_driver);
+
+ if (sndtable_probe(unit, &hw_config)) {
+ dev->id_iobase = hw_config.io_base;
+ dev->id_irq = hw_config.irq == -1 ? 0 : (1 << hw_config.irq);
+ dev->id_drq = hw_config.dma;
+
+ if (hw_config.dma != hw_config.dma2 && ( hw_config.dma2 != -1))
+ dev->id_flags = hw_config.dma2 | 0x100; /* XXX lr */
+ else
+ dev->id_flags = 0;
+ return TRUE;
+ }
+ return 0;
}
int
-sndattach (struct isa_device *dev)
+sndattach(struct isa_device * dev)
{
- int i;
- static int midi_initialized = 0;
- static int seq_initialized = 0;
- static int generic_midi_initialized = 0;
- unsigned long mem_start = 0xefffffff;
- struct address_info hw_config;
-
- hw_config.io_base = dev->id_iobase;
- hw_config.irq = ipri_to_irq (dev->id_irq);
- hw_config.dma = dev->id_drq;
-
- if (dev->id_unit) /* Card init */
- if (!sndtable_init_card (dev->id_unit, &hw_config))
- {
- printf (" <Driver not configured>");
+ int unit;
+ static int midi_initialized = 0;
+ static int seq_initialized = 0;
+ struct address_info hw_config;
+
+ unit = driver_to_voxunit(dev->id_driver);
+ hw_config.io_base = dev->id_iobase;
+ hw_config.irq = ipri_to_irq(dev->id_irq);
+ hw_config.dma = dev->id_drq;
+
+ /* misuse the flags field for read dma */
+ if (dev->id_flags != 0)
+ hw_config.dma2 = dev->id_flags & 0x7;
+ else
+ hw_config.dma2 = -1;
+
+ hw_config.card_subtype = 0;
+ hw_config.osp = temp_osp;
+
+ if (!unit)
return FALSE;
- }
- /*
- * Init the high level sound driver
- */
-
- if (!(soundcards_installed = sndtable_get_cardcount ()))
- {
- printf (" <No such hardware>");
- return FALSE; /* No cards detected */
+ if (!(sndtable_init_card(unit, &hw_config))) { /* init card */
+ printf(" <Driver not configured>");
+ return FALSE;
}
+ /*
+ * Init the high level sound driver
+ */
- printf("\n");
-
-#ifndef EXCLUDE_AUDIO
- if (num_audiodevs) /* Audio devices present */
- {
- mem_start = DMAbuf_init (mem_start);
- mem_start = audio_init (mem_start);
- sound_mem_init ();
+ if (!(soundcards_installed = sndtable_get_cardcount())) {
+ DDB(printf("No drivers actually installed\n"));
+ return FALSE; /* No cards detected */
}
+ printf("\n");
- soundcard_configured = 1;
+#ifdef CONFIG_AUDIO
+ if (num_audiodevs) { /* Audio devices present */
+ DMAbuf_init();
+ sound_mem_init();
+ }
+ soundcard_configured = 1;
#endif
- if (num_midis && !midi_initialized)
- {
- midi_initialized = 1;
- mem_start = MIDIbuf_init (mem_start);
+ if (num_midis && !midi_initialized)
+ midi_initialized = 1;
+
+ if ((num_midis + num_synths) && !seq_initialized) {
+ seq_initialized = 1;
+ sequencer_init();
}
- if ((num_midis + num_synths) && !seq_initialized)
{
- seq_initialized = 1;
- mem_start = sequencer_init (mem_start);
+ dev_t dev;
+
+ dev = makedev(CDEV_MAJOR, 0);
+ cdevsw_add(&dev, &snd_cdevsw, NULL);
}
- return TRUE;
+
+ return TRUE;
}
-void
-tenmicrosec (void)
+
+#ifdef CONFIG_AUDIO
+
+static void
+alloc_dmap(int dev, int chan, struct dma_buffparms * dmap)
{
- int i;
+ char *tmpbuf;
+ int i;
+
+ tmpbuf = contigmalloc(audio_devs[dev]->buffsize, M_DEVBUF, M_NOWAIT,
+ 0ul, 0xfffffful, 1ul, chan & 4 ? 0x20000ul : 0x10000ul);
+ if (tmpbuf == NULL)
+ printf("soundcard buffer alloc failed \n");
+
+ if (tmpbuf == NULL) {
+ printf("snd: Unable to allocate %d bytes of buffer\n",
+ 2 * (int) audio_devs[dev]->buffsize);
+ return;
+ }
+ dmap->raw_buf = tmpbuf;
+ /*
+ * Use virtual address as the physical address, since isa_dmastart
+ * performs the phys address computation.
+ */
+
+ dmap->raw_buf_phys = (u_long) tmpbuf;
+ for (i = 0; i < audio_devs[dev]->buffsize; i++) *tmpbuf++ = 0x80;
- for (i = 0; i < 16; i++)
- inb (0x80);
}
-void
-request_sound_timer (int count)
+static void
+sound_mem_init(void)
{
- static int current = 0;
- int tmp = count;
-
- if (count < 0)
- timeout (sequencer_timer, 0, -count);
- else
- {
+ int dev;
+ static u_long dsp_init_mask = 0;
+
+ for (dev = 0; dev < num_audiodevs; dev++) /* Enumerate devices */
+ if (!(dsp_init_mask & (1 << dev))) /* Not already done */
+ if (audio_devs[dev]->dmachan1 >= 0) {
+ dsp_init_mask |= (1 << dev);
+ audio_devs[dev]->buffsize = DSP_BUFFSIZE;
+ /* Now allocate the buffers */
+ alloc_dmap(dev, audio_devs[dev]->dmachan1,
+ audio_devs[dev]->dmap_out);
+ if (audio_devs[dev]->flags & DMA_DUPLEX)
+ alloc_dmap(dev, audio_devs[dev]->dmachan2,
+ audio_devs[dev]->dmap_in);
+ } /* for dev */
+}
- if (count < current)
- current = 0; /* Timer restarted */
+#endif
- count = count - current;
- current = tmp;
+int
+snd_ioctl_return(int *addr, int value)
+{
+ if (value < 0)
+ return value; /* Error */
+ suword(addr, value);
+ return 0;
+}
- if (!count)
- count = 1;
+#define MAX_UNIT 50
+typedef void (*irq_proc_t) (int irq);
+static irq_proc_t irq_proc[MAX_UNIT] = {NULL};
+static int irq_irq[MAX_UNIT] = {0};
- timeout (sequencer_timer, 0, count);
+int
+snd_set_irq_handler(int int_lvl, void (*hndlr) (int), sound_os_info * osp)
+{
+ if (osp->unit >= MAX_UNIT) {
+ printf("Sound error: Unit number too high (%d)\n", osp->unit);
+ return 0;
}
- timer_running = 1;
+ irq_proc[osp->unit] = hndlr;
+ irq_irq[osp->unit] = int_lvl;
+ return 1;
}
void
-sound_stop_timer (void)
+sndintr(int unit)
{
- if (timer_running)
- untimeout (sequencer_timer, 0);
- timer_running = 0;
+ if ( (unit >= MAX_UNIT) || (irq_proc[unit] == NULL) )
+ return;
+
+ irq_proc[unit] (irq_irq[unit]); /* Call the installed handler */
}
-#ifndef EXCLUDE_AUDIO
-static void
-sound_mem_init (void)
+void
+conf_printf(char *name, struct address_info * hw_config)
{
- int i, dev;
- unsigned long dma_pagesize;
- static unsigned long dsp_init_mask = 0;
-
- for (dev = 0; dev < num_audiodevs; dev++) /* Enumerate devices */
- if (!(dsp_init_mask & (1 << dev))) /* Not already done */
- if (sound_buffcounts[dev] > 0 && sound_dsp_dmachan[dev] > 0)
- {
- dsp_init_mask |= (1 << dev);
-
- if (sound_dma_automode[dev])
- {
- sound_dma_automode[dev] = 0; /* Not possible with 386BSD */
- }
-
-#if 0
- if (sound_buffcounts[dev] == 1)
- {
- sound_buffcounts[dev] = 2;
- sound_buffsizes[dev] /= 2;
- }
-
- if (sound_buffsizes[dev] > 65536) /* Larger is not possible (yet) */
- sound_buffsizes[dev] = 65536;
-
- if (sound_dsp_dmachan[dev] > 3 && sound_buffsizes[dev] > 65536)
- dma_pagesize = 131072; /* 128k */
- else
- dma_pagesize = 65536;
-
- /* More sanity checks */
-
- if (sound_buffsizes[dev] > dma_pagesize)
- sound_buffsizes[dev] = dma_pagesize;
- sound_buffsizes[dev] &= 0xfffff000; /* Truncate to n*4k */
- if (sound_buffsizes[dev] < 4096)
- sound_buffsizes[dev] = 4096;
-#else
- dma_pagesize = 4096;
- sound_buffsizes[dev] = 4096;
- sound_buffcounts[dev] = 16; /* 16*4k -> 64k */
-#endif
+ if (!trace_init)
+ return;
- /* Now allocate the buffers */
-
- for (snd_raw_count[dev] = 0; snd_raw_count[dev] < sound_buffcounts[dev]; snd_raw_count[dev]++)
- {
- /*
- * The DMA buffer allocation algorithm hogs memory. We allocate
- * a memory area which is two times the requires size. This
- * guarantees that it contains at least one valid DMA buffer.
- *
- * This really needs some kind of finetuning.
- */
- char *tmpbuf = malloc (2*sound_buffsizes[dev], M_DEVBUF, M_NOWAIT);
- unsigned long addr, rounded, start, end;
-
- if (tmpbuf == NULL)
- {
- printk ("snd: Unable to allocate %d bytes of buffer\n",
- 2 * sound_buffsizes[dev]);
- return;
- }
-
- addr = kvtop (tmpbuf);
- /*
- * Align the start address if required
- */
- start = (addr & ~(dma_pagesize - 1));
- end = ((addr+sound_buffsizes[dev]-1) & ~(dma_pagesize - 1));
-
- if (start != end)
- rounded = end;
- else
- rounded = addr; /* Fits to the same DMA page */
-
- snd_raw_buf[dev][snd_raw_count[dev]] =
- &tmpbuf[rounded - addr]; /* Compute offset */
- /*
- * Use virtual address as the physical address, since
- * isa_dmastart performs the phys address computation.
- */
- snd_raw_buf_phys[dev][snd_raw_count[dev]] =
- (unsigned long) snd_raw_buf[dev][snd_raw_count[dev]];
- }
- } /* for dev */
+ printf("<%s> ", name);
+ if (hw_config->io_base != -1 )
+ printf("at 0x%03x", hw_config->io_base);
-}
+ if (hw_config->irq != -1 )
+ printf(" irq %d", hw_config->irq);
-#endif
+ if (hw_config->dma != -1 || hw_config->dma2 != -1) {
+ printf(" dma %d", hw_config->dma);
+ if (hw_config->dma2 != -1)
+ printf(",%d", hw_config->dma2);
+ }
-struct isa_driver snddriver =
-{sndprobe, sndattach, "snd"};
-int
-snd_ioctl_return (int *addr, int value)
-{
- if (value < 0)
- return value; /* Error */
- suword (addr, value);
- return 0;
}
-int
-snd_set_irq_handler (int interrupt_level, void(*hndlr)(int))
+void
+conf_printf2(char *name, int base, int irq, int dma, int dma2)
{
- return 1;
+ if (!trace_init)
+ return;
+
+ printf("<%s> at 0x%03x", name, base);
+
+ if (irq)
+ printf(" irq %d", irq);
+
+ if (dma != -1 || dma2 != -1) {
+ printf(" dma %d", dma);
+ if (dma2 != -1)
+ printf(",%d", dma2);
+ }
+
+
}
-void
-snd_release_irq(int vect)
+
+void tenmicrosec (int j)
{
+ int i, k;
+ for (k = 0; k < j/10 ; k++) {
+ for (i = 0; i < 16; i++)
+ inb (0x80);
+ }
}
-#endif
+#endif /* NSND > 0 */
+
+
+
+
diff --git a/sys/i386/isa/sound/soundvers.h b/sys/i386/isa/sound/soundvers.h
index ca892e8259da..66ca10db2b49 100644
--- a/sys/i386/isa/sound/soundvers.h
+++ b/sys/i386/isa/sound/soundvers.h
@@ -1 +1,2 @@
-#define SOUND_VERSION_STRING "3.0-beta-950506"
+#define SOUND_VERSION_STRING "3.5-alpha15-970902"
+#define SOUND_INTERNAL_VERSION 0x030518
diff --git a/sys/i386/isa/sound/sscape.c b/sys/i386/isa/sound/sscape.c
index 9204b188aab8..bfd5abe8afd1 100644
--- a/sys/i386/isa/sound/sscape.c
+++ b/sys/i386/isa/sound/sscape.c
@@ -1,10 +1,10 @@
/*
* sound/sscape.c
- *
+ *
* Low level driver for Ensoniq Soundscape
- *
+ *
* 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
@@ -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,17 +24,19 @@
* 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"
+#include <i386/isa/sound/sound_config.h>
-#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_SSCAPE)
+#if NSSCAPE > 0
-#include "coproc.h"
+#include <i386/isa/sound/coproc.h>
+
+#define EXCLUDE_NATIVE_PCM
/*
- * I/O ports
+ * I/O ports
*/
#define MIDI_DATA 0
#define MIDI_CTRL 1
@@ -46,7 +48,7 @@
#define ODIE_DATA 5
/*
- * Indirect registers
+ * Indirect registers
*/
#define GA_INTSTAT_REG 0
#define GA_INTENA_REG 1
@@ -75,6 +77,10 @@
#define CMD_GET_BOARD_TYPE 0x82
#define CMD_SET_CONTROL 0x88
#define CMD_GET_CONTROL 0x89
+#define CTL_MASTER_VOL 0
+#define CTL_MIC_MODE 2
+#define CTL_SYNTH_VOL 4
+#define CTL_WAVE_VOL 7
#define CMD_SET_MT32 0x96
#define CMD_GET_MT32 0x97
#define CMD_SET_EXTMIDI 0x9b
@@ -82,748 +88,689 @@
#define CMD_ACK 0x80
-typedef struct sscape_info
- {
- int base, irq, dma;
- int ok; /* Properly detected */
- int dma_allocated;
- int my_audiodev;
- int opened;
- }
+typedef struct sscape_info {
+ int base, irq, dma;
+ int ok; /* Properly detected */
+ int failed;
+ int dma_allocated;
+ int my_audiodev;
+ int opened;
+ sound_os_info *osp;
+}
-sscape_info;
+ sscape_info;
static struct sscape_info dev_info =
{0};
static struct sscape_info *devc = &dev_info;
-DEFINE_WAIT_QUEUE (sscape_sleeper, sscape_sleep_flag);
+static int *sscape_sleeper = NULL;
+static volatile struct snd_wait sscape_sleep_flag =
+{0};
-#ifdef REVEAL_SPEA
-/* Spea and Reveal have assigned interrupt bits differently than Ensoniq */
-static char valid_interrupts[] =
+/* Some older cards have assigned interrupt bits differently than new ones */
+static char valid_interrupts_old[] =
{9, 7, 5, 15};
-#else
-static char valid_interrupts[] =
+static char valid_interrupts_new[] =
{9, 5, 7, 10};
+static char *valid_interrupts = valid_interrupts_new;
+
+#ifdef REVEAL_SPEA
+static char old_hardware = 1;
+
+#else
+static char old_hardware = 0;
+
#endif
-static unsigned char
-sscape_read (struct sscape_info *devc, int reg)
+static u_char
+sscape_read(struct sscape_info * devc, int reg)
{
- unsigned long flags;
- unsigned char val;
-
- DISABLE_INTR (flags);
- OUTB (reg, PORT (ODIE_ADDR));
- val = INB (PORT (ODIE_DATA));
- RESTORE_INTR (flags);
- return val;
+ u_long flags;
+ u_char val;
+
+ flags = splhigh();
+ outb(PORT(ODIE_ADDR), reg);
+ val = inb(PORT(ODIE_DATA));
+ splx(flags);
+ return val;
}
static void
-sscape_write (struct sscape_info *devc, int reg, int data)
+sscape_write(struct sscape_info * devc, int reg, int data)
{
- unsigned long flags;
+ u_long flags;
- DISABLE_INTR (flags);
- OUTB (reg, PORT (ODIE_ADDR));
- OUTB (data, PORT (ODIE_DATA));
- RESTORE_INTR (flags);
+ flags = splhigh();
+ outb(PORT(ODIE_ADDR), reg);
+ outb(PORT(ODIE_DATA), data);
+ splx(flags);
}
static void
-host_open (struct sscape_info *devc)
+host_open(struct sscape_info * devc)
{
- OUTB (0x00, PORT (HOST_CTRL)); /* Put the board to the host mode */
+ outb(PORT(HOST_CTRL), 0x00); /* Put the board to the host mode */
}
static void
-host_close (struct sscape_info *devc)
+host_close(struct sscape_info * devc)
{
- OUTB (0x03, PORT (HOST_CTRL)); /* Put the board to the MIDI mode */
+ outb(PORT(HOST_CTRL), 0x03); /* Put the board to the MIDI mode */
}
static int
-host_write (struct sscape_info *devc, unsigned char *data, int count)
+host_write(struct sscape_info * devc, u_char *data, int count)
{
- unsigned long flags;
- int i, timeout;
+ u_long flags;
+ int i, timeout_val;
- DISABLE_INTR (flags);
+ flags = splhigh();
- /*
- * Send the command and data bytes
- */
+ /*
+ * Send the command and data bytes
+ */
- for (i = 0; i < count; i++)
- {
- for (timeout = 10000; timeout > 0; timeout--)
- if (INB (PORT (HOST_CTRL)) & TX_READY)
- break;
+ for (i = 0; i < count; i++) {
+ for (timeout_val = 10000; timeout_val > 0; timeout_val--)
+ if (inb(PORT(HOST_CTRL)) & TX_READY)
+ break;
- if (timeout <= 0)
- {
- RESTORE_INTR (flags);
- return 0;
+ if (timeout_val <= 0) {
+ splx(flags);
+ return 0;
+ }
+ outb(PORT(HOST_DATA), data[i]);
}
- OUTB (data[i], PORT (HOST_DATA));
- }
-
- RESTORE_INTR (flags);
+ splx(flags);
- return 1;
+ return 1;
}
static int
-host_read (struct sscape_info *devc)
+host_read(struct sscape_info * devc)
{
- unsigned long flags;
- int timeout;
- unsigned char data;
+ u_long flags;
+ int timeout_val;
+ u_char data;
- DISABLE_INTR (flags);
+ flags = splhigh();
- /*
- * Read a byte
- */
+ /*
+ * Read a byte
+ */
- for (timeout = 10000; timeout > 0; timeout--)
- if (INB (PORT (HOST_CTRL)) & RX_READY)
- break;
-
- if (timeout <= 0)
- {
- RESTORE_INTR (flags);
- return -1;
- }
+ for (timeout_val = 10000; timeout_val > 0; timeout_val--)
+ if (inb(PORT(HOST_CTRL)) & RX_READY)
+ break;
- data = INB (PORT (HOST_DATA));
+ if (timeout_val <= 0) {
+ splx(flags);
+ return -1;
+ }
+ data = inb(PORT(HOST_DATA));
- RESTORE_INTR (flags);
+ splx(flags);
- return data;
+ return data;
}
static int
-host_command1 (struct sscape_info *devc, int cmd)
+host_command1(struct sscape_info * devc, int cmd)
{
- unsigned char buf[10];
+ u_char buf[10];
- buf[0] = (unsigned char) (cmd & 0xff);
+ buf[0] = (u_char) (cmd & 0xff);
- return host_write (devc, buf, 1);
+ return host_write(devc, buf, 1);
}
static int
-host_command2 (struct sscape_info *devc, int cmd, int parm1)
+host_command2(struct sscape_info * devc, int cmd, int parm1)
{
- unsigned char buf[10];
+ u_char buf[10];
- buf[0] = (unsigned char) (cmd & 0xff);
- buf[1] = (unsigned char) (parm1 & 0xff);
+ buf[0] = (u_char) (cmd & 0xff);
+ buf[1] = (u_char) (parm1 & 0xff);
- return host_write (devc, buf, 2);
+ return host_write(devc, buf, 2);
}
static int
-host_command3 (struct sscape_info *devc, int cmd, int parm1, int parm2)
+host_command3(struct sscape_info * devc, int cmd, int parm1, int parm2)
{
- unsigned char buf[10];
+ u_char buf[10];
- buf[0] = (unsigned char) (cmd & 0xff);
- buf[1] = (unsigned char) (parm1 & 0xff);
- buf[2] = (unsigned char) (parm2 & 0xff);
+ buf[0] = (u_char) (cmd & 0xff);
+ buf[1] = (u_char) (parm1 & 0xff);
+ buf[2] = (u_char) (parm2 & 0xff);
- return host_write (devc, buf, 3);
+ return host_write(devc, buf, 3);
}
static void
-set_mt32 (struct sscape_info *devc, int value)
+set_mt32(struct sscape_info * devc, int value)
{
- host_open (devc);
- host_command2 (devc, CMD_SET_MT32,
- value ? 1 : 0);
- if (host_read (devc) != CMD_ACK)
- {
- printk ("SNDSCAPE: Setting MT32 mode failed\n");
- }
- host_close (devc);
+ host_open(devc);
+ host_command2(devc, CMD_SET_MT32,
+ value ? 1 : 0);
+ if (host_read(devc) != CMD_ACK) {
+ printf("SNDSCAPE: Setting MT32 mode failed\n");
+ }
+ host_close(devc);
+}
+
+static void
+set_control(struct sscape_info * devc, int ctrl, int value)
+{
+ host_open(devc);
+ host_command3(devc, CMD_SET_CONTROL, ctrl, value);
+ if (host_read(devc) != CMD_ACK) {
+ printf("SNDSCAPE: Setting control (%d) failed\n", ctrl);
+ }
+ host_close(devc);
}
static int
-get_board_type (struct sscape_info *devc)
+get_board_type(struct sscape_info * devc)
{
- int tmp;
-
- host_open (devc);
- if (!host_command1 (devc, CMD_GET_BOARD_TYPE))
- tmp = -1;
- else
- tmp = host_read (devc);
- host_close (devc);
- return tmp;
+ int tmp;
+
+ host_open(devc);
+ if (!host_command1(devc, CMD_GET_BOARD_TYPE))
+ tmp = -1;
+ else
+ tmp = host_read(devc);
+ host_close(devc);
+ return tmp;
}
void
-sscapeintr (INT_HANDLER_PARMS (irq, dummy))
+sscapeintr(int irq)
{
- unsigned char bits, tmp;
- static int debug = 0;
+ u_char bits, tmp;
+ static int debug = 0;
- printk ("sscapeintr(0x%02x)\n", (bits = sscape_read (devc, GA_INTSTAT_REG)));
- if (SOMEONE_WAITING (sscape_sleeper, sscape_sleep_flag))
- {
- WAKE_UP (sscape_sleeper, sscape_sleep_flag);
+ DEB(printf("sscapeintr(0x%02x)\n", (bits = sscape_read(devc, GA_INTSTAT_REG))));
+ if ((sscape_sleep_flag.mode & WK_SLEEP)) {
+ sscape_sleep_flag.mode = WK_WAKEUP;
+ wakeup(sscape_sleeper);
}
-
- if (bits & 0x02) /* Host interface interrupt */
- {
- printk ("SSCAPE: Host interrupt, data=%02x\n", host_read (devc));
+ if (bits & 0x02) { /* Host interface interrupt */
+ printf("SSCAPE: Host interrupt, data=%02x\n", host_read(devc));
}
-
-#if (!defined(EXCLUDE_MPU401) || !defined(EXCLUDE_MPU_EMU)) && !defined(EXCLUDE_MIDI)
- if (bits & 0x01)
- {
- mpuintr (INT_HANDLER_CALL (irq));
- if (debug++ > 10) /* Temporary debugging hack */
- {
- sscape_write (devc, GA_INTENA_REG, 0x00); /* Disable all interrupts */
+#if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI)
+ if (bits & 0x01) {
+ mpuintr(irq);
+ if (debug++ > 10) { /* Temporary debugging hack */
+ sscape_write(devc, GA_INTENA_REG, 0x00); /* Disable all interr. */
}
}
#endif
- /*
+ /*
* Acknowledge interrupts (toggle the interrupt bits)
- */
-
- tmp = sscape_read (devc, GA_INTENA_REG);
- sscape_write (devc, GA_INTENA_REG, (~bits & 0x0e) | (tmp & 0xf1));
+ */
+ tmp = sscape_read(devc, GA_INTENA_REG);
+ sscape_write(devc, GA_INTENA_REG, (~bits & 0x0e) | (tmp & 0xf1));
}
-static void
-sscape_enable_intr (struct sscape_info *devc, unsigned intr_bits)
-{
- unsigned char temp, orig;
-
- temp = orig = sscape_read (devc, GA_INTENA_REG);
- temp |= intr_bits;
- temp |= 0x80; /* Master IRQ enable */
-
- if (temp == orig)
- return; /* No change */
-
- sscape_write (devc, GA_INTENA_REG, temp);
-}
-
-static void
-sscape_disable_intr (struct sscape_info *devc, unsigned intr_bits)
-{
- unsigned char temp, orig;
-
- temp = orig = sscape_read (devc, GA_INTENA_REG);
- temp &= ~intr_bits;
- if ((temp & ~0x80) == 0x00)
- temp = 0x00; /* Master IRQ disable */
- if (temp == orig)
- return; /* No change */
-
- sscape_write (devc, GA_INTENA_REG, temp);
-}
static void
-do_dma (struct sscape_info *devc, int dma_chan, unsigned long buf, int blk_size, int mode)
+do_dma(struct sscape_info * devc, int dma_chan, u_long buf, int blk_size, int mode)
{
- unsigned char temp;
+ u_char temp;
- if (dma_chan != SSCAPE_DMA_A)
- {
- printk ("SSCAPE: Tried to use DMA channel != A. Why?\n");
- return;
+ if (dma_chan != SSCAPE_DMA_A) {
+ printf("SSCAPE: Tried to use DMA channel != A. Why?\n");
+ return;
}
+ DMAbuf_start_dma(devc->my_audiodev, buf, blk_size, mode);
- DMAbuf_start_dma (devc->my_audiodev,
- buf,
- blk_size, mode);
-
- temp = devc->dma << 4; /* Setup DMA channel select bits */
- if (devc->dma <= 3)
- temp |= 0x80; /* 8 bit DMA channel */
+ temp = devc->dma << 4; /* Setup DMA channel select bits */
+ if (devc->dma <= 3)
+ temp |= 0x80; /* 8 bit DMA channel */
- temp |= 1; /* Trigger DMA */
- sscape_write (devc, GA_DMAA_REG, temp);
- temp &= 0xfe; /* Clear DMA trigger */
- sscape_write (devc, GA_DMAA_REG, temp);
+ temp |= 1; /* Trigger DMA */
+ sscape_write(devc, GA_DMAA_REG, temp);
+ temp &= 0xfe; /* Clear DMA trigger */
+ sscape_write(devc, GA_DMAA_REG, temp);
}
static int
-verify_mpu (struct sscape_info *devc)
+verify_mpu(struct sscape_info * devc)
{
- /*
+ /*
* The SoundScape board could be in three modes (MPU, 8250 and host).
* If the card is not in the MPU mode, enabling the MPU driver will
* cause infinite loop (the driver believes that there is always some
* received data in the buffer.
- *
+ *
* Detect this by looking if there are more than 10 received MIDI bytes
* (0x00) in the buffer.
- */
+ */
- int i;
+ int i;
- for (i = 0; i < 10; i++)
- {
- if (INB (devc->base + HOST_CTRL) & 0x80)
- return 1;
+ for (i = 0; i < 10; i++) {
+ if (inb(devc->base + HOST_CTRL) & 0x80)
+ return 1;
- if (INB (devc->base) != 0x00)
- return 1;
+ if (inb(devc->base) != 0x00)
+ return 1;
}
- printk ("SoundScape: The device is not in the MPU-401 mode\n");
- return 0;
+ printf("SoundScape: The device is not in the MPU-401 mode\n");
+ return 0;
}
static int
-sscape_coproc_open (void *dev_info, int sub_device)
+sscape_coproc_open(void *dev_info, int sub_device)
{
- if (sub_device == COPR_MIDI)
- {
- set_mt32 (devc, 0);
- if (!verify_mpu (devc))
- return RET_ERROR (EIO);
+ if (sub_device == COPR_MIDI) {
+ set_mt32(devc, 0);
+ if (!verify_mpu(devc))
+ return -(EIO);
}
-
- return 0;
+ sscape_sleep_flag.aborting = 0;
+ sscape_sleep_flag.mode = WK_NONE;
+ return 0;
}
static void
-sscape_coproc_close (void *dev_info, int sub_device)
+sscape_coproc_close(void *dev_info, int sub_device)
{
- struct sscape_info *devc = dev_info;
- unsigned long flags;
+ struct sscape_info *devc = dev_info;
+ u_long flags;
- DISABLE_INTR (flags);
- if (devc->dma_allocated)
- {
- sscape_write (devc, GA_DMAA_REG, 0x20); /* DMA channel disabled */
-#ifndef EXCLUDE_NATIVE_PCM
- DMAbuf_close_dma (devc->my_audiodev);
+ flags = splhigh();
+ if (devc->dma_allocated) {
+ sscape_write(devc, GA_DMAA_REG, 0x20); /* DMA channel disabled */
+#ifdef CONFIG_NATIVE_PCM
#endif
- devc->dma_allocated = 0;
+ devc->dma_allocated = 0;
}
- RESET_WAIT_QUEUE (sscape_sleeper, sscape_sleep_flag);
- RESTORE_INTR (flags);
+ sscape_sleep_flag.aborting = 0;
+ sscape_sleep_flag.mode = WK_NONE;
+ splx(flags);
- return;
+ return;
}
static void
-sscape_coproc_reset (void *dev_info)
+sscape_coproc_reset(void *dev_info)
{
}
static int
-sscape_download_boot (struct sscape_info *devc, unsigned char *block, int size, int flag)
+sscape_download_boot(struct sscape_info * devc, u_char *block, int size, int flag)
{
- unsigned long flags;
- unsigned char temp;
- int done, timeout;
-
- if (flag & CPF_FIRST)
- {
- /*
- * First block. Have to allocate DMA and to reset the board
- * before continuing.
- */
-
- DISABLE_INTR (flags);
- if (devc->dma_allocated == 0)
- {
-#ifndef EXCLUDE_NATIVE_PCM
- if (DMAbuf_open_dma (devc->my_audiodev) < 0)
- {
- RESTORE_INTR (flags);
- return 0;
- }
-#endif
-
- devc->dma_allocated = 1;
+ u_long flags;
+ u_char temp;
+ int done, timeout_val;
+
+ if (flag & CPF_FIRST) {
+ /*
+ * First block. Have to allocate DMA and to reset the board
+ * before continuing.
+ */
+
+ flags = splhigh();
+ if (devc->dma_allocated == 0) {
+ devc->dma_allocated = 1;
}
- RESTORE_INTR (flags);
+ splx(flags);
- sscape_write (devc, GA_HMCTL_REG,
- (temp = sscape_read (devc, GA_HMCTL_REG)) & 0x3f); /*Reset */
+ sscape_write(devc, GA_HMCTL_REG,
+ (temp = sscape_read(devc, GA_HMCTL_REG)) & 0x3f); /* Reset */
- for (timeout = 10000; timeout > 0; timeout--)
- sscape_read (devc, GA_HMCTL_REG); /* Delay */
+ for (timeout_val = 10000; timeout_val > 0; timeout_val--)
+ sscape_read(devc, GA_HMCTL_REG); /* Delay */
- /* Take board out of reset */
- sscape_write (devc, GA_HMCTL_REG,
- (temp = sscape_read (devc, GA_HMCTL_REG)) | 0x80);
+ /* Take board out of reset */
+ sscape_write(devc, GA_HMCTL_REG,
+ (temp = sscape_read(devc, GA_HMCTL_REG)) | 0x80);
}
-
- /*
+ /*
* Transfer one code block using DMA
- */
- memcpy (audio_devs[devc->my_audiodev]->dmap->raw_buf[0], block, size);
-
- DISABLE_INTR (flags);
-/******** INTERRUPTS DISABLED NOW ********/
- do_dma (devc, SSCAPE_DMA_A,
- audio_devs[devc->my_audiodev]->dmap->raw_buf_phys[0],
- size, DMA_MODE_WRITE);
-
- /*
- * Wait until transfer completes.
- */
- RESET_WAIT_QUEUE (sscape_sleeper, sscape_sleep_flag);
- done = 0;
- timeout = 100;
- while (!done && timeout-- > 0)
- {
- int resid;
+ */
+ bcopy(block, audio_devs[devc->my_audiodev]->dmap_out->raw_buf, size);
+
+ flags = splhigh();
+ /******** INTERRUPTS DISABLED NOW ********/
+ do_dma(devc, SSCAPE_DMA_A,
+ audio_devs[devc->my_audiodev]->dmap_out->raw_buf_phys,
+ size, 1);
+
+ /*
+ * Wait until transfer completes.
+ */
+ sscape_sleep_flag.aborting = 0;
+ sscape_sleep_flag.mode = WK_NONE;
+ done = 0;
+ timeout_val = 100;
+ while (!done && timeout_val-- > 0) {
+ int resid;
+ int chn;
+ sscape_sleeper = &chn;
+ DO_SLEEP(chn, sscape_sleep_flag, 1);
- DO_SLEEP (sscape_sleeper, sscape_sleep_flag, 1);
- clear_dma_ff (devc->dma);
- if ((resid = get_dma_residue (devc->dma)) == 0)
done = 1;
}
- RESTORE_INTR (flags);
- if (!done)
- return 0;
+ splx(flags);
+ if (!done)
+ return 0;
- if (flag & CPF_LAST)
- {
- /*
- * Take the board out of reset
- */
- OUTB (0x00, PORT (HOST_CTRL));
- OUTB (0x00, PORT (MIDI_CTRL));
-
- temp = sscape_read (devc, GA_HMCTL_REG);
- temp |= 0x40;
- sscape_write (devc, GA_HMCTL_REG, temp); /* Kickstart the board */
-
- /*
- * Wait until the ODB wakes up
- */
-
- DISABLE_INTR (flags);
- done = 0;
- timeout = 5 * HZ;
- while (!done && timeout-- > 0)
- {
- DO_SLEEP (sscape_sleeper, sscape_sleep_flag, 1);
- if (INB (PORT (HOST_DATA)) == 0xff) /* OBP startup acknowledge */
+ if (flag & CPF_LAST) {
+ /*
+ * Take the board out of reset
+ */
+ outb(PORT(HOST_CTRL), 0x00);
+ outb(PORT(MIDI_CTRL), 0x00);
+
+ temp = sscape_read(devc, GA_HMCTL_REG);
+ temp |= 0x40;
+ sscape_write(devc, GA_HMCTL_REG, temp); /* Kickstart the board */
+
+ /*
+ * Wait until the ODB wakes up
+ */
+
+ flags = splhigh();
+ done = 0;
+ timeout_val = 5 * hz;
+ while (!done && timeout_val-- > 0) {
+ int chn;
+
+ sscape_sleeper = &chn;
+ DO_SLEEP(chn, sscape_sleep_flag, 1);
+
+ if (inb(PORT(HOST_DATA)) == 0xff) /* OBP startup acknowledge */
done = 1;
}
- RESTORE_INTR (flags);
- if (!done)
- {
- printk ("SoundScape: The OBP didn't respond after code download\n");
- return 0;
+ splx(flags);
+ if (!done) {
+ printf("SoundScape: The OBP didn't respond after code download\n");
+ return 0;
}
+ flags = splhigh();
+ done = 0;
+ timeout_val = 5 * hz;
+ while (!done && timeout_val-- > 0) {
+ int chn;
- DISABLE_INTR (flags);
- done = 0;
- timeout = 5 * HZ;
- while (!done && timeout-- > 0)
- {
- DO_SLEEP (sscape_sleeper, sscape_sleep_flag, 1);
- if (INB (PORT (HOST_DATA)) == 0xfe) /* Host startup acknowledge */
+ sscape_sleeper = &chn;
+ DO_SLEEP(chn, sscape_sleep_flag, 1);
+
+ if (inb(PORT(HOST_DATA)) == 0xfe) /* Host startup acknowledge */
done = 1;
}
- RESTORE_INTR (flags);
- if (!done)
- {
- printk ("SoundScape: OBP Initialization failed.\n");
- return 0;
+ splx(flags);
+ if (!done) {
+ printf("SoundScape: OBP Initialization failed.\n");
+ return 0;
}
+ printf("SoundScape board of type %d initialized OK\n",
+ get_board_type(devc));
- printk ("SoundScape board of type %d initialized OK\n",
- get_board_type (devc));
+ set_control(devc, CTL_MASTER_VOL, 100);
+ set_control(devc, CTL_SYNTH_VOL, 100);
#ifdef SSCAPE_DEBUG3
- /*
- * Temporary debugging aid. Print contents of the registers after
- * downloading the code.
- */
- {
- int i;
+ /*
+ * Temporary debugging aid. Print contents of the registers
+ * after downloading the code.
+ */
+ {
+ int i;
- for (i = 0; i < 13; i++)
- printk ("I%d = %02x (new value)\n", i, sscape_read (devc, i));
- }
+ for (i = 0; i < 13; i++)
+ printf("I%d = %02x (new value)\n", i, sscape_read(devc, i));
+ }
#endif
}
-
- return 1;
+ return 1;
}
static int
-download_boot_block (void *dev_info, copr_buffer * buf)
+download_boot_block(void *dev_info, copr_buffer * buf)
{
- if (buf->len <= 0 || buf->len > sizeof (buf->data))
- return RET_ERROR (EINVAL);
+ if (buf->len <= 0 || buf->len > sizeof(buf->data))
+ return -(EINVAL);
- if (!sscape_download_boot (devc, buf->data, buf->len, buf->flags))
- {
- printk ("SSCAPE: Unable to load microcode block to the OBP.\n");
- return RET_ERROR (EIO);
+ if (!sscape_download_boot(devc, buf->data, buf->len, buf->flags)) {
+ printf("SSCAPE: Unable to load microcode block to the OBP.\n");
+ return -(EIO);
}
-
- return 0;
+ return 0;
}
static int
-sscape_coproc_ioctl (void *dev_info, unsigned int cmd, unsigned int arg, int local)
+sscape_coproc_ioctl(void *dev_info, u_int cmd, ioctl_arg arg, int local)
{
- switch (cmd)
- {
+ switch (cmd) {
case SNDCTL_COPR_RESET:
- sscape_coproc_reset (dev_info);
- return 0;
- break;
+ sscape_coproc_reset(dev_info);
+ return 0;
+ break;
case SNDCTL_COPR_LOAD:
- {
- copr_buffer *buf;
- int err;
-
- buf = (copr_buffer *) KERNEL_MALLOC (sizeof (copr_buffer));
- IOCTL_FROM_USER ((char *) buf, (char *) arg, 0, sizeof (*buf));
- err = download_boot_block (dev_info, buf);
- KERNEL_FREE (buf);
- return err;
- }
- break;
+ {
+ copr_buffer *buf;
+ int err;
+
+ buf = (copr_buffer *) malloc(sizeof(copr_buffer), M_TEMP, M_WAITOK);
+ if (buf == NULL)
+ return -(ENOSPC);
+ bcopy(&(((char *) arg)[0]), (char *) buf, sizeof(*buf));
+ err = download_boot_block(dev_info, buf);
+ free(buf, M_TEMP);
+ return err;
+ }
+ break;
default:
- return RET_ERROR (EINVAL);
+ return -(EINVAL);
}
- return RET_ERROR (EINVAL);
}
static coproc_operations sscape_coproc_operations =
{
- "SoundScape M68K",
- sscape_coproc_open,
- sscape_coproc_close,
- sscape_coproc_ioctl,
- sscape_coproc_reset,
- &dev_info
+ "SoundScape M68K",
+ sscape_coproc_open,
+ sscape_coproc_close,
+ sscape_coproc_ioctl,
+ sscape_coproc_reset,
+ &dev_info
};
static int
-sscape_audio_open (int dev, int mode)
+sscape_audio_open(int dev, int mode)
{
- unsigned long flags;
- sscape_info *devc = (sscape_info *) audio_devs[dev]->devc;
+ u_long flags;
+ sscape_info *devc = (sscape_info *) audio_devs[dev]->devc;
- DISABLE_INTR (flags);
- if (devc->opened)
- {
- RESTORE_INTR (flags);
- return RET_ERROR (EBUSY);
+ flags = splhigh();
+ if (devc->opened) {
+ splx(flags);
+ return -(EBUSY);
}
-
- if (devc->dma_allocated == 0)
+ devc->opened = 1;
+ splx(flags);
+#ifdef SSCAPE_DEBUG4
+ /*
+ * Temporary debugging aid. Print contents of the registers when the
+ * device is opened.
+ */
{
- int err;
-
- if ((err = DMAbuf_open_dma (devc->my_audiodev)) < 0)
- {
- RESTORE_INTR (flags);
- return err;
- }
+ int i;
- devc->dma_allocated = 1;
+ for (i = 0; i < 13; i++)
+ printf("I%d = %02x\n", i, sscape_read(devc, i));
}
-
- devc->opened = 1;
- RESTORE_INTR (flags);
-#ifdef SSCAPE_DEBUG4
- /*
- * Temporary debugging aid. Print contents of the registers
- * when the device is opened.
- */
- {
- int i;
-
- for (i = 0; i < 13; i++)
- printk ("I%d = %02x\n", i, sscape_read (devc, i));
- }
#endif
- return 0;
+ return 0;
}
static void
-sscape_audio_close (int dev)
+sscape_audio_close(int dev)
{
- unsigned long flags;
- sscape_info *devc = (sscape_info *) audio_devs[dev]->devc;
+ u_long flags;
+ sscape_info *devc = (sscape_info *) audio_devs[dev]->devc;
- DEB (printk ("sscape_audio_close(void)\n"));
+ DEB(printf("sscape_audio_close(void)\n"));
- DISABLE_INTR (flags);
+ flags = splhigh();
- if (devc->dma_allocated)
- {
- sscape_write (devc, GA_DMAA_REG, 0x20); /* DMA channel disabled */
- DMAbuf_close_dma (dev);
- devc->dma_allocated = 0;
- }
- devc->opened = 0;
+ devc->opened = 0;
- RESTORE_INTR (flags);
+ splx(flags);
}
static int
-set_speed (sscape_info * devc, int arg)
+set_speed(sscape_info * devc, int arg)
{
- return 8000;
+ return 8000;
}
static int
-set_channels (sscape_info * devc, int arg)
+set_channels(sscape_info * devc, int arg)
{
- return 1;
+ return 1;
}
static int
-set_format (sscape_info * devc, int arg)
+set_format(sscape_info * devc, int arg)
{
- return AFMT_U8;
+ return AFMT_U8;
}
static int
-sscape_audio_ioctl (int dev, unsigned int cmd, unsigned int arg, int local)
+sscape_audio_ioctl(int dev, u_int cmd, ioctl_arg arg, int local)
{
- sscape_info *devc = (sscape_info *) audio_devs[dev]->devc;
+ sscape_info *devc = (sscape_info *) audio_devs[dev]->devc;
- switch (cmd)
- {
+ switch (cmd) {
case SOUND_PCM_WRITE_RATE:
- if (local)
- return set_speed (devc, arg);
- return IOCTL_OUT (arg, set_speed (devc, IOCTL_IN (arg)));
+ if (local)
+ return set_speed(devc, (int) arg);
+ return *(int *) arg = set_speed(devc, (*(int *) arg));
case SOUND_PCM_READ_RATE:
- if (local)
- return 8000;
- return IOCTL_OUT (arg, 8000);
+ if (local)
+ return 8000;
+ return *(int *) arg = 8000;
case SNDCTL_DSP_STEREO:
- if (local)
- return set_channels (devc, arg + 1) - 1;
- return IOCTL_OUT (arg, set_channels (devc, IOCTL_IN (arg) + 1) - 1);
+ if (local)
+ return set_channels(devc, (int) arg + 1) - 1;
+ return *(int *) arg = set_channels(devc, (*(int *) arg) + 1) - 1;
case SOUND_PCM_WRITE_CHANNELS:
- if (local)
- return set_channels (devc, arg);
- return IOCTL_OUT (arg, set_channels (devc, IOCTL_IN (arg)));
+ if (local)
+ return set_channels(devc, (int) arg);
+ return *(int *) arg = set_channels(devc, (*(int *) arg));
case SOUND_PCM_READ_CHANNELS:
- if (local)
- return 1;
- return IOCTL_OUT (arg, 1);
+ if (local)
+ return 1;
+ return *(int *) arg = 1;
case SNDCTL_DSP_SAMPLESIZE:
- if (local)
- return set_format (devc, arg);
- return IOCTL_OUT (arg, set_format (devc, IOCTL_IN (arg)));
+ if (local)
+ return set_format(devc, (int) arg);
+ return *(int *) arg = set_format(devc, (*(int *) arg));
case SOUND_PCM_READ_BITS:
- if (local)
- return 8;
- return IOCTL_OUT (arg, 8);
+ if (local)
+ return 8;
+ return *(int *) arg = 8;
default:;
}
- return RET_ERROR (EINVAL);
+ return -(EINVAL);
}
static void
-sscape_audio_output_block (int dev, unsigned long buf, int count, int intrflag, int dma_restart)
+sscape_audio_output_block(int dev, u_long buf, int count, int intrflag, int dma_restart)
{
}
static void
-sscape_audio_start_input (int dev, unsigned long buf, int count, int intrflag, int dma_restart)
+sscape_audio_start_input(int dev, u_long buf, int count, int intrflag, int dma_restart)
{
}
static int
-sscape_audio_prepare_for_input (int dev, int bsize, int bcount)
+sscape_audio_prepare_for_input(int dev, int bsize, int bcount)
{
- return 0;
+ return 0;
}
static int
-sscape_audio_prepare_for_output (int dev, int bsize, int bcount)
+sscape_audio_prepare_for_output(int dev, int bsize, int bcount)
{
- return 0;
+ return 0;
}
static void
-sscape_audio_halt (int dev)
+sscape_audio_halt(int dev)
{
}
static void
-sscape_audio_reset (int dev)
+sscape_audio_reset(int dev)
{
- sscape_audio_halt (dev);
+ sscape_audio_halt(dev);
}
static struct audio_operations sscape_audio_operations =
{
- "Ensoniq SoundScape channel A",
- 0,
- AFMT_U8 | AFMT_S16_LE,
- NULL,
- sscape_audio_open,
- sscape_audio_close,
- sscape_audio_output_block,
- sscape_audio_start_input,
- sscape_audio_ioctl,
- sscape_audio_prepare_for_input,
- sscape_audio_prepare_for_output,
- sscape_audio_reset,
- sscape_audio_halt,
- NULL,
- NULL
+ "Not functional",
+ 0,
+ AFMT_U8 | AFMT_S16_LE,
+ NULL,
+ sscape_audio_open,
+ sscape_audio_close,
+ sscape_audio_output_block,
+ sscape_audio_start_input,
+ sscape_audio_ioctl,
+ sscape_audio_prepare_for_input,
+ sscape_audio_prepare_for_output,
+ sscape_audio_reset,
+ sscape_audio_halt,
+ NULL,
+ NULL
};
-long
-attach_sscape (long mem_start, struct address_info *hw_config)
+static int sscape_detected = 0;
+
+void
+attach_sscape(struct address_info * hw_config)
{
- int my_dev;
+ int my_dev;
#ifndef SSCAPE_REGS
- /*
+ /*
* Config register values for Spea/V7 Media FX and Ensoniq S-2000.
- * These values are card
- * dependent. If you have another SoundScape based card, you have to
- * find the correct values. Do the following:
- * - Compile this driver with SSCAPE_DEBUG1 defined.
- * - Shut down and power off your machine.
- * - Boot with DOS so that the SSINIT.EXE program is run.
- * - Warm boot to {Linux|SYSV|BSD} and write down the lines displayed
- * when detecting the SoundScape.
- * - Modify the following list to use the values printed during boot.
- * Undefine the SSCAPE_DEBUG1
- */
+ * These values are card dependent. If you have another SoundScape
+ * based card, you have to find the correct values. Do the following:
+ * - Compile this driver with SSCAPE_DEBUG1 defined. - Shut down and
+ * power off your machine. - Boot with DOS so that the SSINIT.EXE
+ * program is run. - Warm boot to {Linux|SYSV|BSD} and write down the
+ * lines displayed when detecting the SoundScape. - Modify the
+ * following list to use the values printed during boot. Undefine the
+ * SSCAPE_DEBUG1
+ */
#define SSCAPE_REGS { \
/* I0 */ 0x00, \
0xf0, /* Note! Ignored. Set always to 0xf0 */ \
@@ -833,288 +780,279 @@ attach_sscape (long mem_start, struct address_info *hw_config)
0x10, \
0x00, \
0x2e, /* I7 MEM config A. Likely to vary between models */ \
- 0x00, /* I8 MEM config A. Likely to vary between models */ \
+ 0x00, /* I8 MEM config B. Likely to vary between models */ \
/* I9 */ 0x40 /* Ignored */ \
}
#endif
- unsigned long flags;
- static unsigned char regs[10] = SSCAPE_REGS;
+ u_long flags;
+ static u_char regs[10] = SSCAPE_REGS;
- int i, irq_bits = 0xff;
+ int i, irq_bits = 0xff;
- if (!probe_sscape (hw_config))
- return mem_start;
+ if (sscape_detected != hw_config->io_base)
+ return;
- printk (" <Ensoniq Soundscape>");
+ if (old_hardware) {
+ valid_interrupts = valid_interrupts_old;
+ conf_printf("Ensoniq Soundscape (old)", hw_config);
+ } else
+ conf_printf("Ensoniq Soundscape", hw_config);
- for (i = 0; i < sizeof (valid_interrupts); i++)
- if (hw_config->irq == valid_interrupts[i])
- {
- irq_bits = i;
- break;
- }
-
- if (hw_config->irq > 15 || (regs[4] = irq_bits == 0xff))
- {
- printk ("Invalid IRQ%d\n", hw_config->irq);
- return mem_start;
+ for (i = 0; i < sizeof(valid_interrupts); i++)
+ if (hw_config->irq == valid_interrupts[i]) {
+ irq_bits = i;
+ break;
+ }
+ if (hw_config->irq > 15 || (regs[4] = irq_bits == 0xff)) {
+ printf("Invalid IRQ%d\n", hw_config->irq);
+ return;
}
+ flags = splhigh();
+
+ for (i = 1; i < 10; i++)
+ switch (i) {
+ case 1: /* Host interrupt enable */
+ sscape_write(devc, i, 0xf0); /* All interrupts enabled */
+ break;
+
+ case 2: /* DMA A status/trigger register */
+ case 3: /* DMA B status/trigger register */
+ sscape_write(devc, i, 0x20); /* DMA channel disabled */
+ break;
+
+ case 4: /* Host interrupt config reg */
+ sscape_write(devc, i, 0xf0 | (irq_bits << 2) | irq_bits);
+ break;
+
+ case 5: /* Don't destroy CD-ROM DMA config bits (0xc0) */
+ sscape_write(devc, i, (regs[i] & 0x3f) |
+ (sscape_read(devc, i) & 0xc0));
+ break;
+
+ case 6: /* CD-ROM config. Don't touch. */
+ break;
+
+ case 9: /* Master control reg. Don't modify CR-ROM
+ * bits. Disable SB emul */
+ sscape_write(devc, i, (sscape_read(devc, i) & 0xf0) | 0x00);
+ break;
+
+ default:
+ sscape_write(devc, i, regs[i]);
+ }
- DISABLE_INTR (flags);
-
- for (i = 1; i < 10; i++)
- switch (i)
- {
- case 1: /* Host interrupt enable */
- sscape_write (devc, i, 0xf0); /* All interrupts enabled */
- break;
-
- case 2: /* DMA A status/trigger register */
- case 3: /* DMA B status/trigger register */
- sscape_write (devc, i, 0x20); /* DMA channel disabled */
- break;
-
- case 4: /* Host interrupt config reg */
- sscape_write (devc, i, 0xf0 | (irq_bits << 2) | irq_bits);
- break;
-
- case 5: /* Don't destroy CD-ROM DMA config bits (0xc0) */
- sscape_write (devc, i, (regs[i] & 0x3f) |
- (sscape_read (devc, i) & 0x0c));
- break;
-
- case 6: /* CD-ROM config. Don't touch. */
- break;
-
- case 9: /* Master control reg. Don't modify CR-ROM bits. Disable SB emul */
- sscape_write (devc, i,
- (sscape_read (devc, i) & 0xf0) | 0x00);
- break;
-
- default:
- sscape_write (devc, i, regs[i]);
- }
-
- RESTORE_INTR (flags);
+ splx(flags);
#ifdef SSCAPE_DEBUG2
- /*
+ /*
* Temporary debugging aid. Print contents of the registers after
* changing them.
- */
- {
- int i;
+ */
+ {
+ int i;
- for (i = 0; i < 13; i++)
- printk ("I%d = %02x (new value)\n", i, sscape_read (devc, i));
- }
+ for (i = 0; i < 13; i++)
+ printf("I%d = %02x (new value)\n", i, sscape_read(devc, i));
+ }
#endif
-#if !defined(EXCLUDE_MIDI) && !defined(EXCLUDE_MPU_EMU)
- hw_config->always_detect = 1;
- if (probe_mpu401 (hw_config))
+#if defined(CONFIG_MIDI) && defined(CONFIG_MPU_EMU)
+ if (probe_mpu401(hw_config))
+ hw_config->always_detect = 1;
{
- int prev_devs;
+ int prev_devs;
- prev_devs = num_midis;
- mem_start = attach_mpu401 (mem_start, hw_config);
+ prev_devs = num_midis;
+ attach_mpu401(hw_config);
- if (num_midis == (prev_devs + 1)) /* The MPU driver installed itself */
- midi_devs[prev_devs]->coproc = &sscape_coproc_operations;
+ if (num_midis == (prev_devs + 1)) /* The MPU driver
+ * installed itself */
+ midi_devs[prev_devs]->coproc = &sscape_coproc_operations;
}
#endif
#ifndef EXCLUDE_NATIVE_PCM
- /* Not supported yet */
-
-#ifndef EXCLUDE_AUDIO
- if (num_audiodevs < MAX_AUDIO_DEV)
- {
- audio_devs[my_dev = num_audiodevs++] = &sscape_audio_operations;
- audio_devs[my_dev]->dmachan = hw_config->dma;
- audio_devs[my_dev]->buffcount = 1;
- audio_devs[my_dev]->buffsize = DSP_BUFFSIZE;
- audio_devs[my_dev]->devc = devc;
- devc->my_audiodev = my_dev;
- devc->opened = 0;
- audio_devs[my_dev]->coproc = &sscape_coproc_operations;
- if (snd_set_irq_handler (hw_config->irq, sscapeintr, "SoundScape") < 0)
- printk ("Error: Can't allocate IRQ for SoundScape\n");
-
- sscape_write (devc, GA_INTENA_REG, 0x80); /* Master IRQ enable */
- }
- else
- printk ("SoundScape: More than enough audio devices detected\n");
+ /* Not supported yet */
+
+#ifdef CONFIG_AUDIO
+ if (num_audiodevs < MAX_AUDIO_DEV) {
+ audio_devs[my_dev = num_audiodevs++] = &sscape_audio_operations;
+ audio_devs[my_dev]->dmachan1 = hw_config->dma;
+ audio_devs[my_dev]->buffsize = DSP_BUFFSIZE;
+ audio_devs[my_dev]->devc = devc;
+ devc->my_audiodev = my_dev;
+ devc->opened = 0;
+ audio_devs[my_dev]->coproc = &sscape_coproc_operations;
+ if (snd_set_irq_handler(hw_config->irq, sscapeintr, devc->osp) < 0)
+ printf("Error: Can't allocate IRQ for SoundScape\n");
+ sscape_write(devc, GA_INTENA_REG, 0x80); /* Master IRQ enable */
+ } else
+ printf("SoundScape: More than enough audio devices detected\n");
#endif
#endif
- devc->ok = 1;
- return mem_start;
+ devc->ok = 1;
+ devc->failed = 0;
+ return;
}
int
-probe_sscape (struct address_info *hw_config)
+probe_sscape(struct address_info * hw_config)
{
- unsigned char save;
-
- devc->base = hw_config->io_base;
- devc->irq = hw_config->irq;
- devc->dma = hw_config->dma;
-
- /*
- * First check that the address register of "ODIE" is
- * there and that it has exactly 4 writeable bits.
- * First 4 bits
- */
- if ((save = INB (PORT (ODIE_ADDR))) & 0xf0)
- return 0;
+ u_char save;
- OUTB (0x00, PORT (ODIE_ADDR));
- if (INB (PORT (ODIE_ADDR)) != 0x00)
- return 0;
+ devc->failed = 1;
+ devc->base = hw_config->io_base;
+ devc->irq = hw_config->irq;
+ devc->dma = hw_config->dma;
+ devc->osp = hw_config->osp;
- OUTB (0xff, PORT (ODIE_ADDR));
- if (INB (PORT (ODIE_ADDR)) != 0x0f)
- return 0;
+ if (sscape_detected != 0 && sscape_detected != hw_config->io_base)
+ return 0;
+
+ /*
+ * First check that the address register of "ODIE" is there and that
+ * it has exactly 4 writeable bits. First 4 bits
+ */
+ if ((save = inb(PORT(ODIE_ADDR))) & 0xf0)
+ return 0;
+
+ outb(PORT(ODIE_ADDR), 0x00);
+ if (inb(PORT(ODIE_ADDR)) != 0x00)
+ return 0;
+
+ outb(PORT(ODIE_ADDR), 0xff);
+ if (inb(PORT(ODIE_ADDR)) != 0x0f)
+ return 0;
- OUTB (save, PORT (ODIE_ADDR));
+ outb(PORT(ODIE_ADDR), save);
- /*
+ /*
* Now verify that some indirect registers return zero on some bits.
- * This may break the driver with some future revisions of "ODIE" but...
- */
+ * This may break the driver with some future revisions of "ODIE"
+ * but...
+ */
- if (sscape_read (devc, 0) & 0x0c)
- return 0;
+ if (sscape_read(devc, 0) & 0x0c)
+ return 0;
- if (sscape_read (devc, 1) & 0x0f)
- return 0;
+ if (sscape_read(devc, 1) & 0x0f)
+ return 0;
- if (sscape_read (devc, 5) & 0x0f)
- return 0;
+ if (sscape_read(devc, 5) & 0x0f)
+ return 0;
#ifdef SSCAPE_DEBUG1
- /*
+ /*
* Temporary debugging aid. Print contents of the registers before
* changing them.
- */
- {
- int i;
+ */
+ {
+ int i;
- for (i = 0; i < 13; i++)
- printk ("I%d = %02x (old value)\n", i, sscape_read (devc, i));
- }
+ for (i = 0; i < 13; i++)
+ printf("I%d = %02x (old value)\n", i, sscape_read(devc, i));
+ }
#endif
- return 1;
+ if (old_hardware) { /* Check that it's really an old Spea/Reveal card. */
+ u_char tmp;
+ int cc;
+
+ if (!((tmp = sscape_read(devc, GA_HMCTL_REG)) & 0xc0)) {
+ sscape_write(devc, GA_HMCTL_REG, tmp | 0x80);
+ for (cc = 0; cc < 200000; ++cc)
+ inb(devc->base + ODIE_ADDR);
+ } else
+ old_hardware = 0;
+ }
+ if (0) {
+ printf("sscape.c: Can't allocate DMA channel\n");
+ return 0;
+ }
+ sscape_detected = hw_config->io_base;
+
+ return 1;
}
int
-probe_ss_ms_sound (struct address_info *hw_config)
+probe_ss_mss(struct address_info * hw_config)
{
- int i, irq_bits = 0xff;
+ int i, irq_bits = 0xff;
- if (devc->ok == 0)
- {
- printk ("SoundScape: Invalid initialization order.\n");
- return 0;
- }
+ if (devc->failed)
+ return 0;
- for (i = 0; i < sizeof (valid_interrupts); i++)
- if (hw_config->irq == valid_interrupts[i])
- {
- irq_bits = i;
- break;
- }
-#ifdef REVEAL_SPEA
- {
- int tmp, status = 0;
- int cc;
-
- if (!((tmp = sscape_read (devc, GA_HMCTL_REG)) & 0xc0))
- {
- sscape_write (devc, GA_HMCTL_REG, tmp | 0x80);
- for (cc = 0; cc < 200000; ++cc)
- INB (devc->base + ODIE_ADDR);
- }
- }
-#endif
-
- if (hw_config->irq > 15 || irq_bits == 0xff)
- {
- printk ("SoundScape: Invalid MSS IRQ%d\n", hw_config->irq);
- return 0;
+ if (devc->ok == 0) {
+ printf("SoundScape: Invalid initialization order.\n");
+ return 0;
}
-
- return ad1848_detect (hw_config->io_base);
+ for (i = 0; i < sizeof(valid_interrupts); i++)
+ if (hw_config->irq == valid_interrupts[i]) {
+ irq_bits = i;
+ break;
+ }
+ if (hw_config->irq > 15 || irq_bits == 0xff) {
+ printf("SoundScape: Invalid MSS IRQ%d\n", hw_config->irq);
+ return 0;
+ }
+ return ad1848_detect(hw_config->io_base, NULL, hw_config->osp);
}
-long
-attach_ss_ms_sound (long mem_start, struct address_info *hw_config)
+void
+attach_ss_mss(struct address_info * hw_config)
{
- /*
- * This routine configures the SoundScape card for use with the
- * Win Sound System driver. The AD1848 codec interface uses the CD-ROM
+ /*
+ * This routine configures the SoundScape card for use with the Win
+ * Sound System driver. The AD1848 codec interface uses the CD-ROM
* config registers of the "ODIE".
- */
-
- int i, irq_bits = 0xff;
+ */
-#ifdef EXCLUDE_NATIVE_PCM
- int prev_devs = num_audiodevs;
+ int i, irq_bits = 0xff;
+#ifndef CONFIG_NATIVE_PCM
+ int prev_devs = num_audiodevs;
#endif
- /*
+ /*
* Setup the DMA polarity.
- */
- sscape_write (devc, GA_DMACFG_REG, 0x50);
+ */
+ sscape_write(devc, GA_DMACFG_REG, 0x50);
- /*
+ /*
* Take the gate-arry off of the DMA channel.
- */
- sscape_write (devc, GA_DMAB_REG, 0x20);
+ */
+ sscape_write(devc, GA_DMAB_REG, 0x20);
- /*
+ /*
* Init the AD1848 (CD-ROM) config reg.
- */
-
- for (i = 0; i < sizeof (valid_interrupts); i++)
- if (hw_config->irq == valid_interrupts[i])
- {
- irq_bits = i;
- break;
- }
-
- sscape_write (devc, GA_CDCFG_REG, 0x89 | (hw_config->dma << 4) |
- (irq_bits << 1));
-
- if (hw_config->irq == devc->irq)
- printk ("SoundScape: Warning! The WSS mode can't share IRQ with MIDI\n");
+ */
- ad1848_init ("SoundScape", hw_config->io_base,
- hw_config->irq,
- hw_config->dma,
- hw_config->dma);
-
-#ifdef EXCLUDE_NATIVE_PCM
- if (num_audiodevs == (prev_devs + 1)) /* The AD1848 driver installed itself */
- audio_devs[prev_devs]->coproc = &sscape_coproc_operations;
-#endif
-#ifdef SSCAPE_DEBUG5
- /*
- * Temporary debugging aid. Print contents of the registers
- * after the AD1848 device has been initialized.
- */
- {
- int i;
-
- for (i = 0; i < 13; i++)
- printk ("I%d = %02x\n", i, sscape_read (devc, i));
- }
+ for (i = 0; i < sizeof(valid_interrupts); i++)
+ if (hw_config->irq == valid_interrupts[i]) {
+ irq_bits = i;
+ break;
+ }
+ sscape_write(devc, GA_CDCFG_REG, 0x89 | (hw_config->dma << 4) |
+ (irq_bits << 1));
+
+ if (hw_config->irq == devc->irq)
+ printf("SoundScape: Warning! WSS mode can't share IRQ with MIDI\n");
+
+ ad1848_init("SoundScape", hw_config->io_base,
+ hw_config->irq,
+ hw_config->dma,
+ hw_config->dma,
+ 0,
+ devc->osp);
+
+#ifndef CONFIG_NATIVE_PCM
+ /* Check if the AD1848 driver installed itself */
+ if (num_audiodevs == (prev_devs + 1))
+ audio_devs[prev_devs]->coproc = &sscape_coproc_operations;
#endif
- return mem_start;
+ return;
}
#endif
diff --git a/sys/i386/isa/sound/sys_timer.c b/sys/i386/isa/sound/sys_timer.c
index 1000045a42d5..a605dfc2f4e3 100644
--- a/sys/i386/isa/sound/sys_timer.c
+++ b/sys/i386/isa/sound/sys_timer.c
@@ -1,11 +1,11 @@
/*
* sound/sys_timer.c
- *
- * The default timer for the Level 2 sequencer interface
- * Uses the (100HZ) timer of kernel.
- *
+ *
+ * The default timer for the Level 2 sequencer interface.
+ * Uses the (100hz) timer of kernel.
+ *
* 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,280 +25,252 @@
* 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
-#include "sound_config.h"
+#include <i386/isa/sound/sound_config.h>
-#ifdef CONFIGURE_SOUNDCARD
+#if NSND > 0
-#ifndef EXCLUDE_SEQUENCER
+#if defined(CONFIG_SEQUENCER)
static volatile int opened = 0, tmr_running = 0;
static volatile time_t tmr_offs, tmr_ctr;
-static volatile unsigned long ticks_offs;
+static volatile u_long ticks_offs;
static volatile int curr_tempo, curr_timebase;
-static volatile unsigned long curr_ticks;
-static volatile unsigned long next_event_time;
-static unsigned long prev_event_time;
+static volatile u_long curr_ticks;
+static volatile u_long next_event_time;
+static u_long prev_event_time;
-static void poll_def_tmr (unsigned long dummy);
+static void poll_def_tmr(void *dummy);
-DEFINE_TIMER (def_tmr, poll_def_tmr);
-
-static unsigned long
-tmr2ticks (int tmr_value)
+static u_long
+tmr2ticks(int tmr_value)
{
- /*
- * Convert system timer ticks (HZ) to MIDI ticks
- */
-
- unsigned long tmp;
- unsigned long scale;
-
- tmp = (tmr_value * 1000) / HZ;/* Convert to msecs */
+ /*
+ * Convert system timer ticks (hz) to MIDI ticks (divide # of MIDI
+ * ticks/minute by # of system ticks/minute).
+ */
- scale = (60 * 1000) / (curr_tempo * curr_timebase); /* msecs per MIDI tick */
-
- return (tmp + (scale / 2)) / scale;
+ return ((tmr_value * curr_tempo * curr_timebase) + (30 * hz)) / (60 * hz);
}
static void
-poll_def_tmr (unsigned long dummy)
+poll_def_tmr(void *dummy)
{
- if (opened)
- {
- ACTIVATE_TIMER (def_tmr, poll_def_tmr, 1);
+ if (opened) {
- if (tmr_running)
- {
- tmr_ctr++;
- curr_ticks = ticks_offs + tmr2ticks (tmr_ctr);
+ timeout( poll_def_tmr, 0, 1);;
+
+ if (tmr_running) {
+ tmr_ctr++;
+ curr_ticks = ticks_offs + tmr2ticks(tmr_ctr);
- if (curr_ticks >= next_event_time)
- {
- next_event_time = 0xffffffff;
- sequencer_timer ();
+ if (curr_ticks >= next_event_time) {
+ next_event_time = 0xffffffff;
+ sequencer_timer(0);
}
}
}
}
static void
-tmr_reset (void)
+tmr_reset(void)
{
- unsigned long flags;
-
- DISABLE_INTR (flags);
- tmr_offs = 0;
- ticks_offs = 0;
- tmr_ctr = 0;
- next_event_time = 0xffffffff;
- prev_event_time = 0;
- curr_ticks = 0;
- RESTORE_INTR (flags);
+ u_long flags;
+
+ flags = splhigh();
+ tmr_offs = 0;
+ ticks_offs = 0;
+ tmr_ctr = 0;
+ next_event_time = 0xffffffff;
+ prev_event_time = 0;
+ curr_ticks = 0;
+ splx(flags);
}
static int
-def_tmr_open (int dev, int mode)
+def_tmr_open(int dev, int mode)
{
- if (opened)
- return RET_ERROR (EBUSY);
+ if (opened)
+ return -(EBUSY);
- tmr_reset ();
- curr_tempo = 60;
- curr_timebase = HZ;
- opened = 1;
+ tmr_reset();
+ curr_tempo = 60;
+ curr_timebase = hz;
+ opened = 1;
- ACTIVATE_TIMER (def_tmr, poll_def_tmr, 1);
+ timeout( poll_def_tmr, 0, 1);;
- return 0;
+ return 0;
}
static void
-def_tmr_close (int dev)
+def_tmr_close(int dev)
{
- opened = tmr_running = 0;
+ opened = tmr_running = 0;
}
static int
-def_tmr_event (int dev, unsigned char *event)
+def_tmr_event(int dev, u_char *event)
{
- unsigned char cmd = event[1];
- unsigned long parm = *(int *) &event[4];
+ u_char cmd = event[1];
+ u_long parm = *(int *) &event[4];
- switch (cmd)
- {
+ switch (cmd) {
case TMR_WAIT_REL:
- parm += prev_event_time;
+ parm += prev_event_time;
case TMR_WAIT_ABS:
- if (parm > 0)
- {
- long time;
+ if (parm > 0) {
+ long time;
- if (parm <= curr_ticks) /* It's the time */
- return TIMER_NOT_ARMED;
+ if (parm <= curr_ticks) /* It's the time */
+ return TIMER_NOT_ARMED;
- time = parm;
- next_event_time = prev_event_time = time;
+ time = parm;
+ next_event_time = prev_event_time = time;
- return TIMER_ARMED;
+ return TIMER_ARMED;
}
- break;
+ break;
case TMR_START:
- tmr_reset ();
- tmr_running = 1;
- break;
+ tmr_reset();
+ tmr_running = 1;
+ break;
case TMR_STOP:
- tmr_running = 0;
- break;
+ tmr_running = 0;
+ break;
case TMR_CONTINUE:
- tmr_running = 1;
- break;
+ tmr_running = 1;
+ break;
case TMR_TEMPO:
- if (parm)
- {
- if (parm < 8)
- parm = 8;
- if (parm > 250)
- parm = 250;
- tmr_offs = tmr_ctr;
- ticks_offs += tmr2ticks (tmr_ctr);
- tmr_ctr = 0;
- curr_tempo = parm;
+ if (parm) {
+ RANGE (parm, 8, 360) ;
+ tmr_offs = tmr_ctr;
+ ticks_offs += tmr2ticks(tmr_ctr);
+ tmr_ctr = 0;
+ curr_tempo = parm;
}
- break;
+ break;
case TMR_ECHO:
- seq_copy_to_input (event, 8);
- break;
+ seq_copy_to_input(event, 8);
+ break;
default:;
}
- return TIMER_NOT_ARMED;
+ return TIMER_NOT_ARMED;
}
-static unsigned long
-def_tmr_get_time (int dev)
+static u_long
+def_tmr_get_time(int dev)
{
- if (!opened)
- return 0;
+ if (!opened)
+ return 0;
- return curr_ticks;
+ return curr_ticks;
}
static int
-def_tmr_ioctl (int dev,
- unsigned int cmd, unsigned int arg)
+def_tmr_ioctl(int dev, u_int cmd, ioctl_arg arg)
{
- switch (cmd)
- {
+ switch (cmd) {
case SNDCTL_TMR_SOURCE:
- return IOCTL_OUT (arg, TMR_INTERNAL);
- break;
+ return *(int *) arg = TMR_INTERNAL;
+ break;
case SNDCTL_TMR_START:
- tmr_reset ();
- tmr_running = 1;
- return 0;
- break;
+ tmr_reset();
+ tmr_running = 1;
+ return 0;
+ break;
case SNDCTL_TMR_STOP:
- tmr_running = 0;
- return 0;
- break;
+ tmr_running = 0;
+ return 0;
+ break;
case SNDCTL_TMR_CONTINUE:
- tmr_running = 1;
- return 0;
- break;
+ tmr_running = 1;
+ return 0;
+ break;
case SNDCTL_TMR_TIMEBASE:
- {
- int val = IOCTL_IN (arg);
-
- if (val)
- {
- if (val < 1)
- val = 1;
- if (val > 1000)
- val = 1000;
- curr_timebase = val;
- }
-
- return IOCTL_OUT (arg, curr_timebase);
- }
- break;
+ {
+ int val = (*(int *) arg);
- case SNDCTL_TMR_TEMPO:
- {
- int val = IOCTL_IN (arg);
-
- if (val)
- {
- if (val < 8)
- val = 8;
- if (val > 250)
- val = 250;
- tmr_offs = tmr_ctr;
- ticks_offs += tmr2ticks (tmr_ctr);
- tmr_ctr = 0;
- curr_tempo = val;
- }
+ if (val) {
+ RANGE (val, 1, 1000) ;
+ curr_timebase = val;
+ }
+ return *(int *) arg = curr_timebase;
+ }
+ break;
- return IOCTL_OUT (arg, curr_tempo);
- }
- break;
+ case SNDCTL_TMR_TEMPO:
+ {
+ int val = (*(int *) arg);
+
+ if (val) {
+ RANGE (val, 8, 250) ;
+ tmr_offs = tmr_ctr;
+ ticks_offs += tmr2ticks(tmr_ctr);
+ tmr_ctr = 0;
+ curr_tempo = val;
+ }
+ return *(int *) arg = curr_tempo;
+ }
+ break;
case SNDCTL_SEQ_CTRLRATE:
- if (IOCTL_IN (arg) != 0) /* Can't change */
- return RET_ERROR (EINVAL);
+ if ((*(int *) arg) != 0) /* Can't change */
+ return -(EINVAL);
- return IOCTL_OUT (arg, ((curr_tempo * curr_timebase) + 30) / 60);
- break;
+ return *(int *) arg = ((curr_tempo * curr_timebase) + 30) / 60;
+ break;
case SNDCTL_TMR_METRONOME:
- /* NOP */
- break;
+ /* NOP */
+ break;
default:;
}
- return RET_ERROR (EINVAL);
+ return -(EINVAL);
}
static void
-def_tmr_arm (int dev, long time)
+def_tmr_arm(int dev, long time)
{
- if (time < 0)
- time = curr_ticks + 1;
- else if (time <= curr_ticks) /* It's the time */
- return;
+ if (time < 0)
+ time = curr_ticks + 1;
+ else if (time <= curr_ticks) /* It's the time */
+ return;
- next_event_time = prev_event_time = time;
+ next_event_time = prev_event_time = time;
- return;
+ return;
}
struct sound_timer_operations default_sound_timer =
{
- {"System Timer", 0},
- 0, /* Priority */
- 0, /* Local device link */
- def_tmr_open,
- def_tmr_close,
- def_tmr_event,
- def_tmr_get_time,
- def_tmr_ioctl,
- def_tmr_arm
+ {"System clock", 0},
+ 0, /* Priority */
+ 0, /* Local device link */
+ def_tmr_open,
+ def_tmr_close,
+ def_tmr_event,
+ def_tmr_get_time,
+ def_tmr_ioctl,
+ def_tmr_arm
};
#endif
-#endif
+#endif /* NSND > 0 */
diff --git a/sys/i386/isa/sound/trix.c b/sys/i386/isa/sound/trix.c
index 6e3db0fa7c90..818ad5ffb374 100644
--- a/sys/i386/isa/sound/trix.c
+++ b/sys/i386/isa/sound/trix.c
@@ -1,11 +1,10 @@
/*
* sound/trix.c
- *
- * Low level driver for the MediaTriX AudioTriX Pro
- * (MT-0002-PC Control Chip)
- *
+ *
+ * Low level driver for the MediaTriX AudioTriX Pro (MT-0002-PC Control Chip)
+ *
* Copyright by Hannu Savolainen 1995
- *
+ *
* 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,299 +24,345 @@
* 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"
+#include <i386/isa/sound/sound_config.h>
-#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_TRIX)
+#if NTRIX > 0
#ifdef INCLUDE_TRIX_BOOT
-#include "trix_boot.h"
+#include <i386/isa/sound/trix_boot.h>
+#endif
+
+#if (NSB > 0)
+extern int sb_no_recording;
#endif
static int kilroy_was_here = 0; /* Don't detect twice */
static int sb_initialized = 0;
-static int mpu_initialized = 0;
-static unsigned char
-trix_read (int addr)
+static sound_os_info *trix_osp = NULL;
+
+static u_char
+trix_read(int addr)
{
- OUTB ((unsigned char) addr, 0x390); /* MT-0002-PC ASIC address */
- return INB (0x391); /* MT-0002-PC ASIC data */
+ outb(0x390, (u_char) addr); /* MT-0002-PC ASIC address */
+ return inb(0x391); /* MT-0002-PC ASIC data */
}
static void
-trix_write (int addr, int data)
+trix_write(int addr, int data)
{
- OUTB ((unsigned char) addr, 0x390); /* MT-0002-PC ASIC address */
- OUTB ((unsigned char) data, 0x391); /* MT-0002-PC ASIC data */
+ outb(0x390, (u_char) addr); /* MT-0002-PC ASIC address */
+ outb(0x391, (u_char) data); /* MT-0002-PC ASIC data */
}
static void
-download_boot (int base)
+download_boot(int base)
{
- int i = 0, n = sizeof (trix_boot);
-
- trix_write (0xf8, 0x00); /* ??????? */
- OUTB (0x01, base + 6); /* Clear the internal data pointer */
- OUTB (0x00, base + 6); /* Restart */
-
- /*
- * Write the boot code to the RAM upload/download register.
- * Each write increments the internal data pointer.
- */
- OUTB (0x01, base + 6); /* Clear the internal data pointer */
- OUTB (0x1A, 0x390); /* Select RAM download/upload port */
-
- for (i = 0; i < n; i++)
- OUTB (trix_boot[i], 0x391);
- for (i = n; i < 10016; i++) /* Clear up to first 16 bytes of data RAM */
- OUTB (0x00, 0x391);
- OUTB (0x00, base + 6); /* Reset */
- OUTB (0x50, 0x390); /* ?????? */
+#ifdef INCLUDE_TRIX_BOOT
+ int i = 0, n = sizeof(trix_boot);
+
+ trix_write(0xf8, 0x00); /* ??????? */
+ outb(base + 6, 0x01); /* Clear the internal data pointer */
+ outb(base + 6, 0x00); /* Restart */
+
+ /*
+ * Write the boot code to the RAM upload/download register. Each
+ * write increments the internal data pointer.
+ */
+ outb(base + 6, 0x01); /* Clear the internal data pointer */
+ outb(0x390, 0x1A); /* Select RAM download/upload port */
+
+ for (i = 0; i < n; i++)
+ outb(0x391, trix_boot[i]);
+ for (i = n; i < 10016; i++) /* Clear up to first 16 bytes of data RAM */
+ outb(0x391, 0x00);
+ outb(base + 6, 0x00); /* Reset */
+ outb(0x390, 0x50); /* ?????? */
+#endif
+
}
static int
-trix_set_wss_port (struct address_info *hw_config)
+trix_set_wss_port(struct address_info * hw_config)
{
- unsigned char addr_bits;
+ u_char addr_bits;
- if (kilroy_was_here) /* Already initialized */
- return 0;
+ if (0) {
+ printf("AudioTriX: Config port I/O conflict\n");
+ return 0;
+ }
+ if (kilroy_was_here) /* Already initialized */
+ return 0;
- kilroy_was_here = 1;
+ if (trix_read(0x15) != 0x71) { /* No asic signature */
+ DDB(printf("No AudioTriX ASIC signature found\n"));
+ return 0;
+ }
- if (trix_read (0x15) != 0x71) /* No asic signature */
- return 0;
+ kilroy_was_here = 1;
- /*
- * Disable separate wave playback and recording DMA channels since
- * the driver doesn't support duplex mode yet.
- */
+ /*
+ * Reset some registers.
+ */
- trix_write (0x13, trix_read (0x13) & ~0x80);
- trix_write (0x14, trix_read (0x14) & ~0x80);
+ trix_write(0x13, 0);
+ trix_write(0x14, 0);
- /*
+ /*
* Configure the ASIC to place the codec to the proper I/O location
- */
+ */
- switch (hw_config->io_base)
- {
+ switch (hw_config->io_base) {
case 0x530:
- addr_bits = 0;
- break;
+ addr_bits = 0;
+ break;
case 0x604:
- addr_bits = 1;
- break;
+ addr_bits = 1;
+ break;
case 0xE80:
- addr_bits = 2;
- break;
+ addr_bits = 2;
+ break;
case 0xF40:
- addr_bits = 3;
- break;
+ addr_bits = 3;
+ break;
default:
- return 0;
+ return 0;
}
- trix_write (0x19, (trix_read (0x19) & 0x03) | addr_bits);
- return 1;
+ trix_write(0x19, (trix_read(0x19) & 0x03) | addr_bits);
+ return 1;
}
/*
- * Probe and attach routines for the Windows Sound System mode of
- * AudioTriX Pro
+ * Probe and attach routines for the Windows Sound System mode of AudioTriX
+ * Pro
*/
int
-probe_trix_wss (struct address_info *hw_config)
+probe_trix_wss(struct address_info * hw_config)
{
- /*
- * Check if the IO port returns valid signature. The original MS Sound
- * system returns 0x04 while some cards (AudioTriX Pro for example)
- * return 0x00.
- */
- if (!trix_set_wss_port (hw_config))
- return 0;
-
- if ((INB (hw_config->io_base + 3) & 0x3f) != 0x00)
- {
- DDB (printk ("No MSS signature detected on port 0x%x\n", hw_config->io_base));
- return 0;
+ /*
+ * Check if the IO port returns valid signature. The original MS
+ * Sound system returns 0x04 while some cards (AudioTriX Pro for
+ * example) return 0x00.
+ */
+
+ if (0) {
+ printf("AudioTriX: MSS I/O port conflict\n");
+ return 0;
}
+ trix_osp = hw_config->osp;
- if (hw_config->irq > 11)
- {
- printk ("AudioTriX: Bad WSS IRQ %d\n", hw_config->irq);
- return 0;
- }
+ if (!trix_set_wss_port(hw_config))
+ return 0;
- if (hw_config->dma != 0 && hw_config->dma != 1 && hw_config->dma != 3)
- {
- printk ("AudioTriX: Bad WSS DMA %d\n", hw_config->dma);
- return 0;
+ if ((inb(hw_config->io_base + 3) & 0x3f) != 0x00) {
+ DDB(printf("No MSS signature detected on port 0x%x\n",
+ hw_config->io_base));
+ return 0;
}
-
- /*
+ if (hw_config->irq > 11) {
+ printf("AudioTriX: Bad WSS IRQ %d\n", hw_config->irq);
+ return 0;
+ }
+ if (hw_config->dma != 0 && hw_config->dma != 1 && hw_config->dma != 3) {
+ printf("AudioTriX: Bad WSS DMA %d\n", hw_config->dma);
+ return 0;
+ }
+ if (hw_config->dma2 != -1)
+ if (hw_config->dma2 != 0 && hw_config->dma2 != 1 && hw_config->dma2 != 3) {
+ printf("AudioTriX: Bad capture DMA %d\n", hw_config->dma2);
+ return 0;
+ }
+ /*
* Check that DMA0 is not in use with a 8 bit board.
- */
+ */
- if (hw_config->dma == 0 && INB (hw_config->io_base + 3) & 0x80)
- {
- printk ("AudioTriX: Can't use DMA0 with a 8 bit card\n");
- return 0;
+ if (hw_config->dma == 0 && inb(hw_config->io_base + 3) & 0x80) {
+ printf("AudioTriX: Can't use DMA0 with a 8 bit card\n");
+ return 0;
}
-
- if (hw_config->irq > 7 && hw_config->irq != 9 && INB (hw_config->io_base + 3) & 0x80)
- {
- printk ("AudioTriX: Can't use IRQ%d with a 8 bit card\n", hw_config->irq);
- return 0;
+ if (hw_config->irq > 7 && hw_config->irq != 9 && inb(hw_config->io_base + 3) & 0x80) {
+ printf("AudioTriX: Can't use IRQ%d with a 8 bit card\n", hw_config->irq);
+ return 0;
}
-
- return ad1848_detect (hw_config->io_base + 4);
+ return ad1848_detect(hw_config->io_base + 4, NULL, hw_config->osp);
}
-long
-attach_trix_wss (long mem_start, struct address_info *hw_config)
+void
+attach_trix_wss(struct address_info * hw_config)
{
- static unsigned char interrupt_bits[12] =
- {-1, -1, -1, -1, -1, -1, -1, 0x08, -1, 0x10, 0x18, 0x20};
- char bits;
+ static u_char interrupt_bits[12] =
+ {-1, -1, -1, -1, -1, -1, -1, 0x08, -1, 0x10, 0x18, 0x20};
+ char bits;
- static unsigned char dma_bits[4] =
- {1, 2, 0, 3};
+ static u_char dma_bits[4] =
+ {1, 2, 0, 3};
- int config_port = hw_config->io_base + 0, version_port = hw_config->io_base + 3;
+ int config_port = hw_config->io_base + 0,
+ version_port = hw_config->io_base + 3;
+ int dma1 = hw_config->dma, dma2 = hw_config->dma2;
- if (!kilroy_was_here)
- return mem_start;
+ trix_osp = hw_config->osp;
- /*
+ if (!kilroy_was_here) {
+ DDB(printf("AudioTriX: Attach called but not probed yet???\n"));
+ return ;
+ }
+ /*
* Set the IRQ and DMA addresses.
- */
+ */
+
+ bits = interrupt_bits[hw_config->irq];
+ if (bits == -1) {
+ printf("AudioTriX: Bad IRQ (%d)\n", hw_config->irq);
+ return ;
+ }
+ outb(config_port, bits | 0x40);
+ if ((inb(version_port) & 0x40) == 0)
+ printf("[IRQ Conflict?]");
- bits = interrupt_bits[hw_config->irq];
- if (bits == -1)
- return mem_start;
+ if (hw_config->dma2 == -1) { /* Single DMA mode */
+ bits |= dma_bits[dma1];
+ dma2 = dma1;
+ } else {
+ u_char tmp;
- OUTB (bits | 0x40, config_port);
- if ((INB (version_port) & 0x40) == 0)
- printk ("[IRQ Conflict?]");
+ tmp = trix_read(0x13) & ~30;
+ trix_write(0x13, tmp | 0x80 | (dma1 << 4));
- OUTB (bits | dma_bits[hw_config->dma], config_port); /* Write IRQ+DMA setup */
+ tmp = trix_read(0x14) & ~30;
+ trix_write(0x14, tmp | 0x80 | (dma2 << 4));
+ }
+
+ outb(config_port, bits);/* Write IRQ+DMA setup */
- ad1848_init ("AudioTriX Pro", hw_config->io_base + 4,
- hw_config->irq,
- hw_config->dma,
- hw_config->dma);
- return mem_start;
+ ad1848_init("AudioTriX Pro", hw_config->io_base + 4,
+ hw_config->irq,
+ dma1,
+ dma2,
+ 0,
+ hw_config->osp);
+ return ;
}
int
-probe_trix_sb (struct address_info *hw_config)
+probe_trix_sb(struct address_info * hw_config)
{
-
- int tmp;
- unsigned char conf;
- static char irq_translate[] =
- {-1, -1, -1, 0, 1, 2, -1, 3};
+ int tmp;
+ u_char conf;
+ static char irq_translate[] = {-1, -1, -1, 0, 1, 2, -1, 3};
#ifndef INCLUDE_TRIX_BOOT
- return 0; /* No boot code -> no fun */
+ return 0; /* No boot code -> no fun */
#endif
- if (!kilroy_was_here)
- return 0; /* AudioTriX Pro has not been detected earlier */
+ if (!kilroy_was_here)
+ return 0; /* AudioTriX Pro has not been detected earlier */
- if (sb_initialized)
- return 0;
+ if (sb_initialized)
+ return 0;
- if (hw_config->io_base & 0xffffff8f != 0x200)
- return 0;
+ if ((hw_config->io_base & 0xffffff8f) != 0x200)
+ return 0;
- tmp = hw_config->irq;
- if (tmp > 7)
- return 0;
- if (irq_translate[tmp] == -1)
- return 0;
+ tmp = hw_config->irq;
+ if (tmp > 7)
+ return 0;
+ if (irq_translate[tmp] == -1)
+ return 0;
- tmp = hw_config->dma;
- if (tmp != 1 && tmp != 3)
- return 0;
+ tmp = hw_config->dma;
+ if (tmp != 1 && tmp != 3)
+ return 0;
- conf = 0x84; /* DMA and IRQ enable */
- conf |= hw_config->io_base & 0x70; /* I/O address bits */
- conf |= irq_translate[hw_config->irq];
- if (hw_config->dma == 3)
- conf |= 0x08;
- trix_write (0x1b, conf);
+ conf = 0x84; /* DMA and IRQ enable */
+ conf |= hw_config->io_base & 0x70; /* I/O address bits */
+ conf |= irq_translate[hw_config->irq];
+ if (hw_config->dma == 3)
+ conf |= 0x08;
+ trix_write(0x1b, conf);
- download_boot (hw_config->io_base);
- sb_initialized = 1;
+ download_boot(hw_config->io_base);
+ sb_initialized = 1;
- return 1;
+ return 1;
}
-long
-attach_trix_sb (long mem_start, struct address_info *hw_config)
+void
+attach_trix_sb(struct address_info * hw_config)
{
- printk (" <AudioTriX>");
- return mem_start;
+#if (NSB > 0)
+ sb_dsp_disable_midi();
+ sb_no_recording = 1;
+#endif
+ conf_printf("AudioTriX (SB)", hw_config);
}
-long
-attach_trix_mpu (long mem_start, struct address_info *hw_config)
+void
+attach_trix_mpu(struct address_info * hw_config)
{
- return attach_mpu401 (mem_start, hw_config);
+#if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI)
+ attach_mpu401(hw_config);
+#endif
}
int
-probe_trix_mpu (struct address_info *hw_config)
+probe_trix_mpu(struct address_info * hw_config)
{
- unsigned char conf;
- static char irq_bits[] =
- {-1, -1, -1, 1, 2, 3, -1, 4, -1, 5};
-
- if (!kilroy_was_here)
- return 0; /* AudioTriX Pro has not been detected earlier */
-
- if (!sb_initialized)
- return 0;
-
- if (mpu_initialized)
- return 0;
+#if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI)
+ u_char conf;
+ static char irq_bits[] = {-1, -1, -1, 1, 2, 3, -1, 4, -1, 5};
- if (hw_config->irq > 9)
- return 0;
-
- if (irq_bits[hw_config->irq] == -1)
- return 0;
-
- switch (hw_config->io_base)
- {
+ if (!kilroy_was_here) {
+ DDB(printf("Trix: WSS and SB modes must be initialized before MPU\n"));
+ return 0; /* AudioTriX Pro has not been detected earlier */
+ }
+ if (!sb_initialized) {
+ DDB(printf("Trix: SB mode must be initialized before MPU\n"));
+ return 0;
+ }
+ if (mpu_initialized) {
+ DDB(printf("Trix: MPU mode already initialized\n"));
+ return 0;
+ }
+ if (hw_config->irq > 9) {
+ printf("AudioTriX: Bad MPU IRQ %d\n", hw_config->irq);
+ return 0;
+ }
+ if (irq_bits[hw_config->irq] == -1) {
+ printf("AudioTriX: Bad MPU IRQ %d\n", hw_config->irq);
+ return 0;
+ }
+ switch (hw_config->io_base) {
case 0x330:
- conf = 0x00;
- break;
+ conf = 0x00;
+ break;
case 0x370:
- conf = 0x04;
- break;
+ conf = 0x04;
+ break;
case 0x3b0:
- conf = 0x08;
- break;
+ conf = 0x08;
+ break;
case 0x3f0:
- conf = 0x0c;
- break;
+ conf = 0x0c;
+ break;
default:
- return 0; /* Invalid port */
+ return 0; /* Invalid port */
}
- conf |= irq_bits[hw_config->irq] << 4;
+ conf |= irq_bits[hw_config->irq] << 4;
- trix_write (0x19, (trix_read (0x19) & 0x83) | conf);
+ trix_write(0x19, (trix_read(0x19) & 0x83) | conf);
- mpu_initialized = 1;
+ mpu_initialized = 1;
- return probe_mpu401 (hw_config);
+ return probe_mpu401(hw_config);
+#else
+ return 0;
+#endif
}
#endif
diff --git a/sys/i386/isa/sound/uart6850.c b/sys/i386/isa/sound/uart6850.c
index ca6313521270..c9d5c396249e 100644
--- a/sys/i386/isa/sound/uart6850.c
+++ b/sys/i386/isa/sound/uart6850.c
@@ -1,11 +1,11 @@
/*
* sound/uart6850.c
- *
+ *
* Copyright by Hannu Savolainen 1993
- *
- * Mon Nov 22 22:38:35 MET 1993 marco@driq.home.usn.nl:
- * added 6850 support, used with COVOX SoundMaster II and custom cards.
- *
+ *
+ * Mon Nov 22 22:38:35 MET 1993 marco@driq.home.usn.nl: added 6850 support, used
+ * with COVOX SoundMaster II and custom cards.
+ *
* 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,39 +25,32 @@
* 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"
+#include <i386/isa/sound/sound_config.h>
-#ifdef CONFIGURE_SOUNDCARD
+#if NSND > 0
-#if !defined(EXCLUDE_UART6850) && !defined(EXCLUDE_MIDI)
+#if 1
+/* #if defined(CONFIG_UART6850) && defined(CONFIG_MIDI) */
-#define DATAPORT (uart6850_base) /*
- * * * Midi6850 Data I/O Port on IBM
- * */
-#define COMDPORT (uart6850_base+1) /*
- * * * Midi6850 Command Port on IBM */
-#define STATPORT (uart6850_base+1) /*
- * * * Midi6850 Status Port on IBM */
+#define DATAPORT (uart6850_base) /* * * Midi6850 Data I/O Port on IBM */
+#define COMDPORT (uart6850_base+1) /* * * Midi6850 Command Port on IBM */
+#define STATPORT (uart6850_base+1) /* * * Midi6850 Status Port on IBM */
-#define uart6850_status() INB(STATPORT)
-#define input_avail() ((uart6850_status()&INPUT_AVAIL))
-#define output_ready() ((uart6850_status()&OUTPUT_READY))
-#define uart6850_cmd(cmd) OUTB(cmd, COMDPORT)
-#define uart6850_read() INB(DATAPORT)
-#define uart6850_write(byte) OUTB(byte, DATAPORT)
+#define uart6850_status() inb( STATPORT)
+#define input_avail() (uart6850_status()&INPUT_AVAIL)
+#define output_ready() (uart6850_status()&OUTPUT_READY)
+#define uart6850_cmd(cmd) outb( COMDPORT, cmd)
+#define uart6850_read() inb( DATAPORT)
+#define uart6850_write(byte) outb( DATAPORT, byte)
-#define OUTPUT_READY 0x02 /*
- * * * Mask for Data Read Ready Bit */
-#define INPUT_AVAIL 0x01 /*
- * * * Mask for Data Send Ready Bit */
+#define OUTPUT_READY 0x02 /* * * Mask for Data Read Ready Bit */
+#define INPUT_AVAIL 0x01 /* * * Mask for Data Send Ready Bit */
-#define UART_RESET 0x95 /*
- * * * 6850 Total Reset Command */
-#define UART_MODE_ON 0x03 /*
- * * * 6850 Send/Receive UART Mode */
+#define UART_RESET 0x95 /* * * 6850 Total Reset Command */
+#define UART_MODE_ON 0x03 /* * * 6850 Send/Receive UART Mode */
static int uart6850_opened = 0;
static int uart6850_base = 0x330;
@@ -65,39 +58,37 @@ static int uart6850_irq;
static int uart6850_detected = 0;
static int my_dev;
-static int reset_uart6850 (void);
-static void (*midi_input_intr) (int dev, unsigned char data);
+static int reset_uart6850(void);
+static void (*midi_input_intr) (int dev, u_char data);
+static void poll_uart6850(u_long dummy);
+
+static sound_os_info *uart6850_osp;
static void
-uart6850_input_loop (void)
+uart6850_input_loop(void)
{
- int count;
+ int count;
- count = 10;
+ count = 10;
- while (count) /*
- * Not timed out
- */
- if (input_avail ())
- {
- unsigned char c = uart6850_read ();
+ while (count) /* Not timed out */
+ if (input_avail()) {
+ u_char c = uart6850_read();
- count = 100;
+ count = 100;
- if (uart6850_opened & OPEN_READ)
- midi_input_intr (my_dev, c);
- }
- else
- while (!input_avail () && count)
- count--;
+ if (uart6850_opened & OPEN_READ)
+ midi_input_intr(my_dev, c);
+ } else
+ while (!input_avail() && count)
+ count--;
}
void
-m6850intr (int unit)
+m6850intr(int irq)
{
- printk ("M");
- if (input_avail ())
- uart6850_input_loop ();
+ if (input_avail())
+ uart6850_input_loop();
}
/*
@@ -106,218 +97,199 @@ m6850intr (int unit)
*/
static void
-poll_uart6850 (unsigned long dummy)
+poll_uart6850(u_long dummy)
{
- unsigned long flags;
+ u_long flags;
- DEFINE_TIMER (uart6850_timer, poll_uart6850);
+ if (!(uart6850_opened & OPEN_READ))
+ return; /* Device has been closed */
- if (!(uart6850_opened & OPEN_READ))
- return; /*
- * No longer required
- */
+ flags = splhigh();
- DISABLE_INTR (flags);
+ if (input_avail())
+ uart6850_input_loop();
- if (input_avail ())
- uart6850_input_loop ();
- ACTIVATE_TIMER (uart6850_timer, poll_uart6850, 1); /*
- * Come back later
- */
+ timeout((timeout_func_t) poll_uart6850, 0, 1);; /* Come back later */
- RESTORE_INTR (flags);
+ splx(flags);
}
static int
-uart6850_open (int dev, int mode,
- void (*input) (int dev, unsigned char data),
- void (*output) (int dev)
+uart6850_open(int dev, int mode,
+ void (*input) (int dev, u_char data),
+ void (*output) (int dev)
)
{
- if (uart6850_opened)
- {
- printk ("Midi6850: Midi busy\n");
- return RET_ERROR (EBUSY);
+ if (uart6850_opened) {
+ printf("Midi6850: Midi busy\n");
+ return -(EBUSY);
}
+ uart6850_cmd(UART_RESET);
- uart6850_cmd (UART_RESET);
-
- uart6850_input_loop ();
+ uart6850_input_loop();
- midi_input_intr = input;
- uart6850_opened = mode;
- poll_uart6850 (0); /*
- * Enable input polling
- */
+ midi_input_intr = input;
+ uart6850_opened = mode;
+ poll_uart6850(0); /* Enable input polling */
- return 0;
+ return 0;
}
static void
-uart6850_close (int dev)
+uart6850_close(int dev)
{
- uart6850_cmd (UART_MODE_ON);
+ uart6850_cmd(UART_MODE_ON);
- uart6850_opened = 0;
+ uart6850_opened = 0;
}
static int
-uart6850_out (int dev, unsigned char midi_byte)
+uart6850_out(int dev, u_char midi_byte)
{
- int timeout;
- unsigned long flags;
+ int timeout;
+ u_long flags;
- /*
- * Test for input since pending input seems to block the output.
- */
+ /*
+ * Test for input since pending input seems to block the output.
+ */
- DISABLE_INTR (flags);
+ flags = splhigh();
- if (input_avail ())
- uart6850_input_loop ();
+ if (input_avail())
+ uart6850_input_loop();
- RESTORE_INTR (flags);
+ splx(flags);
- /*
- * Sometimes it takes about 13000 loops before the output becomes ready
- * (After reset). Normally it takes just about 10 loops.
- */
+ /*
+ * Sometimes it takes about 13000 loops before the output becomes
+ * ready (After reset). Normally it takes just about 10 loops.
+ */
- for (timeout = 30000; timeout > 0 && !output_ready (); timeout--); /*
- * Wait
- */
+ for (timeout = 30000; timeout > 0 && !output_ready(); timeout--); /* Wait */
- if (!output_ready ())
- {
- printk ("Midi6850: Timeout\n");
- return 0;
+ if (!output_ready()) {
+ printf("Midi6850: Timeout\n");
+ return 0;
}
-
- uart6850_write (midi_byte);
- return 1;
+ uart6850_write(midi_byte);
+ return 1;
}
static int
-uart6850_command (int dev, unsigned char *midi_byte)
+uart6850_command(int dev, u_char *midi_byte)
{
- return 1;
+ return 1;
}
static int
-uart6850_start_read (int dev)
+uart6850_start_read(int dev)
{
- return 0;
+ return 0;
}
static int
-uart6850_end_read (int dev)
+uart6850_end_read(int dev)
{
- return 0;
+ return 0;
}
static int
-uart6850_ioctl (int dev, unsigned cmd, unsigned arg)
+uart6850_ioctl(int dev, u_int cmd, ioctl_arg arg)
{
- return RET_ERROR (EINVAL);
+ return -(EINVAL);
}
static void
-uart6850_kick (int dev)
+uart6850_kick(int dev)
{
}
static int
-uart6850_buffer_status (int dev)
+uart6850_buffer_status(int dev)
{
- return 0; /*
- * No data in buffers
- */
+ return 0; /* No data in buffers */
}
#define MIDI_SYNTH_NAME "6850 UART Midi"
#define MIDI_SYNTH_CAPS SYNTH_CAP_INPUT
-#include "midi_synth.h"
+#include <i386/isa/sound/midi_synth.h>
static struct midi_operations uart6850_operations =
{
- {"6850 UART", 0, 0, SNDCARD_UART6850},
- &std_midi_synth,
- uart6850_open,
- uart6850_close,
- uart6850_ioctl,
- uart6850_out,
- uart6850_start_read,
- uart6850_end_read,
- uart6850_kick,
- uart6850_command,
- uart6850_buffer_status
+ {"6850 UART", 0, 0, SNDCARD_UART6850},
+ &std_midi_synth,
+ {0},
+ uart6850_open,
+ uart6850_close,
+ uart6850_ioctl,
+ uart6850_out,
+ uart6850_start_read,
+ uart6850_end_read,
+ uart6850_kick,
+ uart6850_command,
+ uart6850_buffer_status
};
-long
-attach_uart6850 (long mem_start, struct address_info *hw_config)
+void
+attach_uart6850(struct address_info * hw_config)
{
- int ok, timeout;
- unsigned long flags;
+ int ok, timeout;
+ u_long flags;
- if (num_midis >= MAX_MIDI_DEV)
- {
- printk ("Sound: Too many midi devices detected\n");
- return mem_start;
+ if (num_midis >= MAX_MIDI_DEV) {
+ printf("Sound: Too many midi devices detected\n");
+ return ;
}
+ uart6850_base = hw_config->io_base;
+ uart6850_osp = hw_config->osp;
+ uart6850_irq = hw_config->irq;
- uart6850_base = hw_config->io_base;
- uart6850_irq = hw_config->irq;
-
- if (!uart6850_detected)
- return RET_ERROR (EIO);
+ if (!uart6850_detected)
+ return ;
- DISABLE_INTR (flags);
+ flags = splhigh();
- for (timeout = 30000; timeout < 0 && !output_ready (); timeout--); /*
- * Wait
- */
- uart6850_cmd (UART_MODE_ON);
+ for (timeout = 30000; timeout < 0 && !output_ready(); timeout--); /* Wait */
+ uart6850_cmd(UART_MODE_ON);
- ok = 1;
+ ok = 1;
- RESTORE_INTR (flags);
+ splx(flags);
- printk (" <6850 Midi Interface>");
+ conf_printf("6850 Midi Interface", hw_config);
- std_midi_synth.midi_dev = my_dev = num_midis;
- midi_devs[num_midis++] = &uart6850_operations;
- return mem_start;
+ std_midi_synth.midi_dev = my_dev = num_midis;
+ midi_devs[num_midis++] = &uart6850_operations;
+ return ;
}
static int
-reset_uart6850 (void)
+reset_uart6850(void)
{
- uart6850_read ();
- return 1; /*
- * OK
- */
+ uart6850_read();
+ return 1; /* OK */
}
int
-probe_uart6850 (struct address_info *hw_config)
+probe_uart6850(struct address_info * hw_config)
{
- int ok = 0;
+ int ok = 0;
- uart6850_base = hw_config->io_base;
- uart6850_irq = hw_config->irq;
+ uart6850_osp = hw_config->osp;
+ uart6850_base = hw_config->io_base;
+ uart6850_irq = hw_config->irq;
- if (snd_set_irq_handler (uart6850_irq, m6850intr) < 0)
- return 0;
+ if (snd_set_irq_handler(uart6850_irq, m6850intr, uart6850_osp) < 0)
+ return 0;
- ok = reset_uart6850 ();
+ ok = reset_uart6850();
- uart6850_detected = ok;
- return ok;
+ uart6850_detected = ok;
+ return ok;
}
#endif
-
#endif
diff --git a/sys/i386/isa/sound/ulaw.h b/sys/i386/isa/sound/ulaw.h
index be9f92d9984a..6a25ab455955 100644
--- a/sys/i386/isa/sound/ulaw.h
+++ b/sys/i386/isa/sound/ulaw.h
@@ -1,69 +1,71 @@
static unsigned char ulaw_dsp[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 2,
- 5, 9, 13, 17, 21, 25, 29, 33,
- 37, 41, 45, 49, 53, 57, 61, 65,
- 68, 70, 72, 74, 76, 78, 80, 82,
- 84, 86, 88, 90, 92, 94, 96, 98,
- 100, 101, 102, 103, 104, 105, 106, 107,
- 108, 109, 110, 111, 112, 113, 114, 115,
- 115, 116, 116, 117, 117, 118, 118, 119,
- 119, 120, 120, 121, 121, 122, 122, 123,
- 123, 123, 124, 124, 124, 124, 125, 125,
- 125, 125, 126, 126, 126, 126, 127, 127,
- 127, 127, 127, 127, 128, 128, 128, 128,
- 128, 128, 128, 128, 128, 128, 128, 128,
- 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255,
- 252, 248, 244, 240, 236, 232, 228, 224,
- 220, 216, 212, 208, 204, 200, 196, 192,
- 189, 187, 185, 183, 181, 179, 177, 175,
- 173, 171, 169, 167, 165, 163, 161, 159,
- 157, 156, 155, 154, 153, 152, 151, 150,
- 149, 148, 147, 146, 145, 144, 143, 142,
- 142, 141, 141, 140, 140, 139, 139, 138,
- 138, 137, 137, 136, 136, 135, 135, 134,
- 134, 134, 133, 133, 133, 133, 132, 132,
- 132, 132, 131, 131, 131, 131, 130, 130,
- 130, 130, 130, 130, 129, 129, 129, 129,
- 129, 129, 129, 129, 128, 128, 128, 128,
+ 3, 7, 11, 15, 19, 23, 27, 31,
+ 35, 39, 43, 47, 51, 55, 59, 63,
+ 66, 68, 70, 72, 74, 76, 78, 80,
+ 82, 84, 86, 88, 90, 92, 94, 96,
+ 98, 99, 100, 101, 102, 103, 104, 105,
+ 106, 107, 108, 109, 110, 111, 112, 113,
+ 113, 114, 114, 115, 115, 116, 116, 117,
+ 117, 118, 118, 119, 119, 120, 120, 121,
+ 121, 121, 122, 122, 122, 122, 123, 123,
+ 123, 123, 124, 124, 124, 124, 125, 125,
+ 125, 125, 125, 125, 126, 126, 126, 126,
+ 126, 126, 126, 126, 127, 127, 127, 127,
+ 127, 127, 127, 127, 127, 127, 127, 127,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 253, 249, 245, 241, 237, 233, 229, 225,
+ 221, 217, 213, 209, 205, 201, 197, 193,
+ 190, 188, 186, 184, 182, 180, 178, 176,
+ 174, 172, 170, 168, 166, 164, 162, 160,
+ 158, 157, 156, 155, 154, 153, 152, 151,
+ 150, 149, 148, 147, 146, 145, 144, 143,
+ 143, 142, 142, 141, 141, 140, 140, 139,
+ 139, 138, 138, 137, 137, 136, 136, 135,
+ 135, 135, 134, 134, 134, 134, 133, 133,
+ 133, 133, 132, 132, 132, 132, 131, 131,
+ 131, 131, 131, 131, 130, 130, 130, 130,
+ 130, 130, 130, 130, 129, 129, 129, 129,
+ 129, 129, 129, 129, 129, 129, 129, 129,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
};
+#ifndef DSP_ULAW_NOT_WANTED
static unsigned char dsp_ulaw[] = {
- 31, 31, 31, 32, 32, 32, 32, 33,
- 33, 33, 33, 34, 34, 34, 34, 35,
- 35, 35, 35, 36, 36, 36, 36, 37,
- 37, 37, 37, 38, 38, 38, 38, 39,
- 39, 39, 39, 40, 40, 40, 40, 41,
- 41, 41, 41, 42, 42, 42, 42, 43,
- 43, 43, 43, 44, 44, 44, 44, 45,
- 45, 45, 45, 46, 46, 46, 46, 47,
- 47, 47, 47, 48, 48, 49, 49, 50,
- 50, 51, 51, 52, 52, 53, 53, 54,
- 54, 55, 55, 56, 56, 57, 57, 58,
- 58, 59, 59, 60, 60, 61, 61, 62,
- 62, 63, 63, 64, 65, 66, 67, 68,
- 69, 70, 71, 72, 73, 74, 75, 76,
- 77, 78, 79, 81, 83, 85, 87, 89,
- 91, 93, 95, 99, 103, 107, 111, 119,
- 255, 247, 239, 235, 231, 227, 223, 221,
- 219, 217, 215, 213, 211, 209, 207, 206,
- 205, 204, 203, 202, 201, 200, 199, 198,
- 197, 196, 195, 194, 193, 192, 191, 191,
- 190, 190, 189, 189, 188, 188, 187, 187,
- 186, 186, 185, 185, 184, 184, 183, 183,
- 182, 182, 181, 181, 180, 180, 179, 179,
- 178, 178, 177, 177, 176, 176, 175, 175,
- 175, 175, 174, 174, 174, 174, 173, 173,
- 173, 173, 172, 172, 172, 172, 171, 171,
- 171, 171, 170, 170, 170, 170, 169, 169,
- 169, 169, 168, 168, 168, 168, 167, 167,
- 167, 167, 166, 166, 166, 166, 165, 165,
- 165, 165, 164, 164, 164, 164, 163, 163,
- 163, 163, 162, 162, 162, 162, 161, 161,
- 161, 161, 160, 160, 160, 160, 159, 159,
+ 0, 0, 0, 0, 0, 1, 1, 1,
+ 1, 2, 2, 2, 2, 3, 3, 3,
+ 3, 4, 4, 4, 4, 5, 5, 5,
+ 5, 6, 6, 6, 6, 7, 7, 7,
+ 7, 8, 8, 8, 8, 9, 9, 9,
+ 9, 10, 10, 10, 10, 11, 11, 11,
+ 11, 12, 12, 12, 12, 13, 13, 13,
+ 13, 14, 14, 14, 14, 15, 15, 15,
+ 15, 16, 16, 17, 17, 18, 18, 19,
+ 19, 20, 20, 21, 21, 22, 22, 23,
+ 23, 24, 24, 25, 25, 26, 26, 27,
+ 27, 28, 28, 29, 29, 30, 30, 31,
+ 31, 32, 33, 34, 35, 36, 37, 38,
+ 39, 40, 41, 42, 43, 44, 45, 46,
+ 47, 49, 51, 53, 55, 57, 59, 61,
+ 63, 66, 70, 74, 78, 84, 92, 104,
+ 254, 231, 219, 211, 205, 201, 197, 193,
+ 190, 188, 186, 184, 182, 180, 178, 176,
+ 175, 174, 173, 172, 171, 170, 169, 168,
+ 167, 166, 165, 164, 163, 162, 161, 160,
+ 159, 159, 158, 158, 157, 157, 156, 156,
+ 155, 155, 154, 154, 153, 153, 152, 152,
+ 151, 151, 150, 150, 149, 149, 148, 148,
+ 147, 147, 146, 146, 145, 145, 144, 144,
+ 143, 143, 143, 143, 142, 142, 142, 142,
+ 141, 141, 141, 141, 140, 140, 140, 140,
+ 139, 139, 139, 139, 138, 138, 138, 138,
+ 137, 137, 137, 137, 136, 136, 136, 136,
+ 135, 135, 135, 135, 134, 134, 134, 134,
+ 133, 133, 133, 133, 132, 132, 132, 132,
+ 131, 131, 131, 131, 130, 130, 130, 130,
+ 129, 129, 129, 129, 128, 128, 128, 128,
};
+#endif /* !DSP_ULAW_NOT_WANTED */
diff --git a/sys/i386/isa/sound/ultrasound.h b/sys/i386/isa/sound/ultrasound.h
index 40e2443e6f65..5c63b037fb0f 100644
--- a/sys/i386/isa/sound/ultrasound.h
+++ b/sys/i386/isa/sound/ultrasound.h
@@ -40,8 +40,8 @@
* byte 1 - Synthesizer device number (0-N)
* byte 2 - Command (see below)
* byte 3 - Voice number (0-31)
- * bytes 4 and 5 - parameter P1 (unsigned short)
- * bytes 6 and 7 - parameter P2 (unsigned short)
+ * bytes 4 and 5 - parameter P1 (u_short)
+ * bytes 6 and 7 - parameter P2 (u_short)
*
* Commands:
* Each command affects one voice defined in byte 3.
@@ -90,32 +90,48 @@
* GUS API macros
*/
-#define _GUS_CMD(chn, voice, cmd, p1, p2) \
- {_SEQ_NEEDBUF(8); _seqbuf[_seqbufptr] = SEQ_PRIVATE;\
- _seqbuf[_seqbufptr+1] = (chn); _seqbuf[_seqbufptr+2] = cmd;\
- _seqbuf[_seqbufptr+3] = voice;\
- *(unsigned short*)&_seqbuf[_seqbufptr+4] = p1;\
- *(unsigned short*)&_seqbuf[_seqbufptr+6] = p2;\
- _SEQ_ADVBUF(8);}
+#define _GUS_CMD(chn, voice, cmd, p1, p2) {\
+ _SEQ_NEEDBUF(8); _seqbuf[_seqbufptr] = SEQ_PRIVATE;\
+ _seqbuf[_seqbufptr+1] = (chn); _seqbuf[_seqbufptr+2] = cmd;\
+ _seqbuf[_seqbufptr+3] = voice;\
+ *(u_short*)&_seqbuf[_seqbufptr+4] = p1;\
+ *(u_short*)&_seqbuf[_seqbufptr+6] = p2;\
+ _SEQ_ADVBUF(8);}
-#define GUS_NUMVOICES(chn, p1) _GUS_CMD(chn, 0, _GUS_NUMVOICES, (p1), 0)
-#define GUS_VOICESAMPLE(chn, voice, p1) _GUS_CMD(chn, voice, _GUS_VOICESAMPLE, (p1), 0) /* OBSOLETE */
-#define GUS_VOICEON(chn, voice, p1) _GUS_CMD(chn, voice, _GUS_VOICEON, (p1), 0)
-#define GUS_VOICEOFF(chn, voice) _GUS_CMD(chn, voice, _GUS_VOICEOFF, 0, 0)
-#define GUS_VOICEFADE(chn, voice) _GUS_CMD(chn, voice, _GUS_VOICEFADE, 0, 0)
-#define GUS_VOICEMODE(chn, voice, p1) _GUS_CMD(chn, voice, _GUS_VOICEMODE, (p1), 0)
-#define GUS_VOICEBALA(chn, voice, p1) _GUS_CMD(chn, voice, _GUS_VOICEBALA, (p1), 0)
-#define GUS_VOICEFREQ(chn, voice, p) _GUS_CMD(chn, voice, _GUS_VOICEFREQ, \
- (p) & 0xffff, ((p) >> 16) & 0xffff)
-#define GUS_VOICEVOL(chn, voice, p1) _GUS_CMD(chn, voice, _GUS_VOICEVOL, (p1), 0)
-#define GUS_VOICEVOL2(chn, voice, p1) _GUS_CMD(chn, voice, _GUS_VOICEVOL2, (p1), 0)
-#define GUS_RAMPRANGE(chn, voice, low, high) _GUS_CMD(chn, voice, _GUS_RAMPRANGE, (low), (high))
-#define GUS_RAMPRATE(chn, voice, p1, p2) _GUS_CMD(chn, voice, _GUS_RAMPRATE, (p1), (p2))
-#define GUS_RAMPMODE(chn, voice, p1) _GUS_CMD(chn, voice, _GUS_RAMPMODE, (p1), 0)
-#define GUS_RAMPON(chn, voice, p1) _GUS_CMD(chn, voice, _GUS_RAMPON, (p1), 0)
-#define GUS_RAMPOFF(chn, voice) _GUS_CMD(chn, voice, _GUS_RAMPOFF, 0, 0)
-#define GUS_VOLUME_SCALE(chn, voice, p1, p2) _GUS_CMD(chn, voice, _GUS_VOLUME_SCALE, (p1), (p2))
-#define GUS_VOICE_POS(chn, voice, p) _GUS_CMD(chn, voice, _GUS_VOICE_POS, \
- (p) & 0xffff, ((p) >> 16) & 0xffff)
+#define GUS_NUMVOICES(chn, p1) _GUS_CMD(chn, 0, _GUS_NUMVOICES, (p1), 0)
+#define GUS_VOICESAMPLE(chn, voice, p1) \
+ _GUS_CMD(chn, voice, _GUS_VOICESAMPLE, (p1), 0) /* OBSOLETE */
+#define GUS_VOICEON(chn, voice, p1) \
+ _GUS_CMD(chn, voice, _GUS_VOICEON, (p1), 0)
+#define GUS_VOICEOFF(chn, voice) \
+ _GUS_CMD(chn, voice, _GUS_VOICEOFF, 0, 0)
+#define GUS_VOICEFADE(chn, voice) \
+ _GUS_CMD(chn, voice, _GUS_VOICEFADE, 0, 0)
+#define GUS_VOICEMODE(chn, voice, p1) \
+ _GUS_CMD(chn, voice, _GUS_VOICEMODE, (p1), 0)
+#define GUS_VOICEBALA(chn, voice, p1) \
+ _GUS_CMD(chn, voice, _GUS_VOICEBALA, (p1), 0)
+#define GUS_VOICEFREQ(chn, voice, p) \
+ _GUS_CMD(chn, voice, _GUS_VOICEFREQ, \
+ (p) & 0xffff, ((p) >> 16) & 0xffff)
+#define GUS_VOICEVOL(chn, voice, p1) \
+ _GUS_CMD(chn, voice, _GUS_VOICEVOL, (p1), 0)
+#define GUS_VOICEVOL2(chn, voice, p1) \
+ _GUS_CMD(chn, voice, _GUS_VOICEVOL2, (p1), 0)
+#define GUS_RAMPRANGE(chn, voice, low, high) \
+ _GUS_CMD(chn, voice, _GUS_RAMPRANGE, (low), (high))
+#define GUS_RAMPRATE(chn, voice, p1, p2) \
+ _GUS_CMD(chn, voice, _GUS_RAMPRATE, (p1), (p2))
+#define GUS_RAMPMODE(chn, voice, p1) \
+ _GUS_CMD(chn, voice, _GUS_RAMPMODE, (p1), 0)
+#define GUS_RAMPON(chn, voice, p1) \
+ _GUS_CMD(chn, voice, _GUS_RAMPON, (p1), 0)
+#define GUS_RAMPOFF(chn, voice) \
+ _GUS_CMD(chn, voice, _GUS_RAMPOFF, 0, 0)
+#define GUS_VOLUME_SCALE(chn, voice, p1, p2) \
+ _GUS_CMD(chn, voice, _GUS_VOLUME_SCALE, (p1), (p2))
+#define GUS_VOICE_POS(chn, voice, p) \
+ _GUS_CMD(chn, voice, _GUS_VOICE_POS, \
+ (p) & 0xffff, ((p) >> 16) & 0xffff)
#endif