Bid a fond farewell to these files, they live on various forms in

dev/pcm/* and dev/pcm/isa/*
This commit is contained in:
Peter Wemm 1999-09-26 22:20:29 +00:00
parent 894071bb70
commit a534126855
11 changed files with 0 additions and 8167 deletions

View File

@ -1,359 +0,0 @@
In this file I will try to build a database of cards supported by
this driver. I also include the command to use for manual configuration
of the card in case your BIOS is not PnP-aware. Of course it is
your responsibility to pick up free port ranges and irq and drq
channels.
For PnP cards, I also include the vendor_id and serial numbers of
cards I have encountered. Underscores in the PnP id mean that
(I believe) there is a large variety of values in those positions,
and the code in the audio driver generally masks those bits.
Finally, where available, I have put the URL where you can find the
data sheets of the chip.
To my knowledge, there are the following families of audio cards:
* WSS (also called MSS) and clones:
these are true full duplex cards, have a very nice architecture and
are well documented. Chipsets implementing these functionalities
are made from Crystal, Analog Devices, Yamaha, OPTI.
* SB16 and clones:
these cards have a higly asymmetric architecture, and are not very
well suited to full duplex operation. Made by Creative, Realtek.
There is no documentation on the newer codecs (Vibra16X and ALS100+),
so they are not fully working.
* ESS
ESS builds cards that implement a superset of SB16. They are
often capable of full duplex, but my driver does not support them
other than in full duplex emulation. My fault, since documentation
on these cards _is_ available.
* PCI cards.
There are a quite few PCI audio cards around based on a number of
different chipsets. Some of them are documented (e.g. S3 Sonic
Vibes, Ensoniq ES1370), some are not (e.g. Yamaha YMF724),
work is in progress to support such cards. See the notes below.
Note that CreativeLabs has recently (fall'97) acquired Ensoniq
and the audio division of OPTI, both of which had a PCI audio
chipset. I don't know if there are other manufacturers of PCI
audio cards.
Finally, some people wrote patches for the following chips:
AD1816
MAD16
ESS
--------------------------
CHIPSET:
CS4235: PnP id 0x25__630e
CS4236: PnP id 0x36__630e 0x35__630e
CS4237: PnP id 0x37__630e
MANUFACTURER:
A/Open (or AcerOpen) AW32, AW35, AW37
Also, integrated on the motherboard on some machines.
DATA SHEETS:
http://www.crystal.com/ 4237full.pdf
PNP CONFIG:
pnp 1 0 os enable port0 0x534 port2 0x220 irq0 5 drq0 1 drq1 3
COMMENTS:
Work like a charm. All modes, including full duplex, supported in
MSS mode.
Cards based on the 4237, and possibly the 4236 as well, connect
the CD to AUX2. When used in MODE1/2 (as this driver does)
there is no route in the input mixer from AUX2 to the ADC. So,
to record directly from the CD, the only way is to set the
input to SOUND_MASK_IMIX.
Some machines with the cs4235 in non-pnp mode map the codec at 0x530
instead of 0x534. For those machines you need an unusual config line
device pcm0 at isa ? port 0x52C ...
--------------------------
CHIPSET:
CS4232: PnP id 0x3242630e
MANUFACTURER:
???
DATA SHEETS:
http://www.crystal.com/
PNP CONFIG:
pnp 1 0 os enable port0 0x534 port2 0x220 irq0 5 drq0 1 drq1 3
COMMENTS:
This chip is reported as broken in the OSS documentation. As a
matter of fact, on my Intel Zappa motherboard, I have problems in
make it use the secondary DMA channel. I have it working in
half duplex (both capture and playback) in SB3.2 emulation,
and working in playback mode in MSS emulation.
Also have reports from some user that it works ok.
--------------------------
CHIPSET:
AD1815/1816
MANUFACTURER:
Analog Devices
DOCUMENTATION:
http://www.analog.com
COMMENTS:
This is a chip for ISA-PnP cards, and so should be configured
using the PnP interface. For full function configure port2,
irq0, drq0 and drq1 of ldn0.
The driver is contributed by German Tischler
FORMATS:
ALAW/ULAW/8bit/16bit(le)/16bit(be),8kHz-55.2kHz,full duplex
--------------------------
CHIPSET:
OPTi931: PnP id 0x3109143e
OPTi933: PnP id 0x3109143e (yes, it's the same)
MANUFACTURER:
ExpertColor MED931 (europe)
Shuttle HOT-247 (uses the 933, $15 retail in the US)
DATA SHEETS:
http://www.opti.com/ opti931_21.pdf
PNP CONFIG:
pnp 1 1 os enable port0 0x534 port2 0x220 port3 0xe0d irq0 10 drq0 1 drq1 6
COMMENTS:
The data sheets of this chip are very cryptic and do not match
what the cards I have seem to do. I have it working
in WSS emulation, in full duplex and all modes.
In SB emulation mode the driver does not work yet (maybe I do
not initialize it the right way). It is not a major concern
anyways.
I am strongly convinced of a couple of bugs in the chip. I have
sent email to OPTI but got no reply so far. The bugs are:
- you cannot set both playback and capture format to use
a companded mode (ULAW, ALAW). If you do, the card will screw
up on the capture section.
The driver has a partial fix in software: when using ULAW, it
programs ULAW on the playback section, U8 on the capture, and
does a conversion in software (much like the SBPro). Of course
you lose 4-5 bits of dynamic range in the process.
- in full duplex (and single DMA mode), the card occasionally
misses interrupts, or generates spurious ones, or generates
interrupts before setting the status bits in the registers.
Spurious ints are not problematic since they can be easily
ignored, but missing interrupts are a nightmare to handle...
The only way to have this card work semi-reliably is to use
auto-dma mode (which is the default mode of operation in the
driver).
In any case, these cards are very cheap and widely available and
are a reasonable solution if you cannot find some other decent WSS
device.
-------------------------------
CHIPSET:
SB16: PnP id 0x__008c0e
Vibra16X: PnP id 0xf0008c0e
MANUFACTURER:
CreativeLabs
DATA SHEETS:
http://www.creative.com sbhwpg.pdf or SBHWPG.EXE
ftp://www.creaf.com/pub/creative/devinfo/ctsbhwpg.exe
PNP CONFIG:
pnp 1 0 os enable port0 0x220 irq0 5 drq0 1 drq1 5
COMMENTS:
SB16 really refers to a large number of different cards, starting
from the original, non-PnP SB16, to more modern cards (SB16PnP,
Vibra16C) and other including Wavetable Synthesis (AWE32, AWE64,
etc.). All these cards have different PnP ID. They have
different synthesis devices, which we do not support, so we
are not affected by these differences. Don't worry if the driver
identifies the card as a different SB16 than the one you have.
BEWARE -- all recent (1998 ?) SB16 use a new codec, Vibra16X,
which is sufficiently different from the old one to not work with
this driver in capture mode or in full duplex. Documentation is
not available from Creative. I suggest to stay away from these
cards (and from SB16 in general).
Full duplex support of this card is tricky since one channel can
work in 16-bit and the other in 8-bit mode. You will need to use
the new set of ioctl to use separate data formats on the two
channels (the vat driver does this). Of course, quality in 8-bit
is much lower than in 16-bit.
Full duplex operation is unsupported by Creative. It seems to
work, although on my Vibra16C the command to stop DMA transfer
seems to erroneously affect both channels instead of the one
they are issued for. The driver has a workaround, but I cannot
guarantee that it works for everybody. I have had several
positive reports.
Some docs on how to use this card with the voxware driver
are at http://multiverse.com/~rhh/awedrv
--------------------------
CHIPSET:
ALS100, ALS110, ALS120, ...
Avance Asound 100: PnP id 0x01009305
Avance Asound 100+: PnP id 0x10019305
Avance Logic ALS120: PnP id 0x20019305
MANUFACTURER:
Realtek (also Avance Asound and possibly other names)
Asound Gold (AS007) has an ALS120
DOCUMENTATION:
http://www.realtek.com.tw/cp/cp.html
but not very useful or detailed.
COMMENTS:
These card should be recognised as SB16 clones. Some of them
emulate the Vibra16X, so the comments above apply.
------------------------------
CHIPSET:
Yamaha SA2/SA3 . Both PnP and non-PnP versions.
OPL3-SA2 Sound Chip: PnP id 0x2000a865
OPL/SA3 : PnP id 0x3000a865
MANUFACTURER:
no-name cards, and also used in various laptops, e.g. Toshiba
Libretto and others. I
DATA SHEETS:
http://www.yamaha.com ? YM711.pdf
ftp://ftp.yamahayst.com/pub/Fax_Back_Doc/Sound
http://www.imail.net.tw/qtronix/qumax_product_yamaha.htm
This is a huge file containing a few pages scanned and converted
to pdf. Not very detailed. Luckily, this chipset appears to do a
good (i.e. bug-free) emulation of the WSS, so it is fully
supported by the driver.
pnp 1 0 os enable port0 0x220 port1 0x530 port2 0x388 port3 0x370 irq0 5 drq0 1 drq1 0
this card emulates a WSS or SB. Have reports that it works, although
it has incomplete mixer support (Yamaha defines an additional set
of registers to control some mixer functions, such as the master
output volume -- this is at 0x370 or 0x310). Currently we set
the master volume to 100% for the PnP card. Will put in code to do the
same for the non PnP card as soon as I find out how to tell
the Yamaha from other cards.
Driver reported to work also on
Toshiba DynaBook Portege 300CT with OPL3SA-3(non-PNP), and on the
Libretto50CT (has the non-PnP device).
------------------------
CHIPSET:
ENSONIQ SoundscapeVIVO ENS4081: PnP id 0x8140d315
MANUFACTURER:
Ensoniq Soundscape VIVO
PNP CONFIG:
pnp 1 0 os enable port0 0x220 port1 0x530 irq0 5 drq0 1 drq1 5
COMMENTS:
this card emulates a WSS or SB. Have reports that it works.
-------------------------
CHIPSET:
AMD...
MANUFACTURER:
GusPnP: PnP id 0x0100561e
PNP CONFIG:
pnp 1 0 os enable port0 0x220 port1 0x320 port2 0x32c irq0 5 drq0 7 drq1 5
COMMENTS:
It works in U8 and S16 mode, ulaw support still not working.
The Gus has been discontinued, so support for this card is only
there for historical reasons (the Gus used to be the only card
well supported in full duplex mode).
---- THE FOLLOWING CARDS ARE NOT FULLY SUPPORTED: ----
CHIPSET:
OPTI925: PnP id 0x2509143e
COMMENTS:
there is code to recognize it as a SB clone. I have reports that
it probes ok, but not sure if it works.
-------------------------
CHIPSET:
OPTI924: PnP
COMMENT:
I have this card but it is still unsupported.
-------------------------
CHIPSET:
OPTI930:
should work as an MSS clone, but support for it is not implemented
yet.
CHIPSET:
ESS1868
ESS688
http://www.esstech.com
pnp 1 1 os enable irq0 7 drq0 1 port0 0x220
There used to be documentation for the 1868 on the ESS site
(files ds1868b1.pdf and ds1868b2.pdf) but I am unable to find
it now (980122). I have asked ESS but no reply so far.
partly supported in SB emulation.
(the ESS688 is used on many notebooks. It is probably able to do 8
and 16-bit, half duplex).
-------------------------
CHIPSET:
es1370 (ensoniq)
es1371 (ensoniq)
used on SB64 PCI, Shuttle HOT-255, and maybe others
A driver for this is in the works.
see http://www.ensoniq.com/multimedia/semi_html/index.htm
for documentation. See also http://alsa.jcu.cz/alsa/ for a Linux
driver.
-------------------------
CHIPSET:
YMF724
used on various Yamaha (WaveForce) and other cards.
NOT SUPPORTED.
There is no public docs on this card, the closest thing being
http://www.imail.net.tw/qtronix/driver/qumax/yamaha/ds1e1110.pdf
http://www.imail.net.tw/qtronix/qumax_product_yamaha.htm
which however does not document how the card works in non-legacy
mode and how to make it talk to the AC97 codec.
--------------------------------------------------------------------

View File

@ -1,224 +0,0 @@
--- A new FreeBSD audio driver ---
by Luigi Rizzo (luigi@iet.unipi.it)
This is a new, completely rewritten, audio driver for FreeBSD.
Only "soundcard.h" has remained largely similar to the original
OSS/Voxware header file, mostly for compatibility with existing
applications.
This driver tries to cover those areas where the Voxware 3.0 driver
is mostly lacking: full-duplex, audio applications, modern (mostly
PnP) cards. For backward compatibility, the driver implements most
of the Voxware ioctl() audio calls, so that many applications --
even commercial ones -- will run unmodified with this driver. On
the other hand, at the moment this driver does not support /dev/midi
and /dev/synth, or some ioctl() used in xquake. Do not expect
/dev/synth to be supported anytime soon.
I also have implemented a new software interface with an independent
set of ioctl(), to support some functions which were not easy to
express with the existing software interface (e.g. full duplex on
old SB16 cards). To make an effective use of the new functionalities
you need to recompile applications by replacing the audio module(s).
Such modified driver modules are present in the misc/ directory
for several applications.
This file gives quick information on how to install the driver.
Updated versions of this code will be available at the following URL:
http://www.iet.unipi.it/~luigi/FreeBSD.html
Please READ CAREFULLY this file (and possibly the LaTeX documentation)
to build a working kernel. The configuration is DIFFERENT (and
hopefully much simpler) from the original Voxware driver. The
relevant steps are indicated at "---INSTALLATION---".
CARDS:
The driver supports most clones of WSS, SB16 and SBPro cards.
This includes those based on the Crystal CS423x, OPTI931, GUSPnP,
Yamaha, SB16/32 (both plain ISA, PnP, and the various AWExx).
Many PnP cards are directly recognized, for others you might need
manual configuration. See the file "CARDS" for more details.
APPLICATIONS:
In general, most applications which use /dev/audio or /dev/dsp
work unmodified or with a specially-supplied module.
UNMODIFIED:
- raplayer (Real Audio Player), rvplayer (linux version)
- xboing
- xanim
- various mpeg players (mpg123, amp, ...);
WITH SPECIAL DRIVER MODULE (supplied)
- speak_freely, full duplex (requires removing the definition of
HALF_DUPLEX in the Makefile);
- the realaudio player (3.0, dynamically linked);
- vat, full duplex (the version in ports is already modified);
- timidity, a software midi-to-pcm converter;
NOT WORKING
- xquake (we do not support mmapped buffers yet);
---INSTALLATION---
* add the following lines to your kernel configuration file:
controller pnp0 # this is required for PnP support
device pcm0 at isa ? port? tty irq N drq D flags F
where
N is the IRQ address used by the sound card,
D is the primary DMA channel used by the sound card,
F is used to specify a number of options, in particular:
bit 2..0 secondary DMA channel;
bit 4 set if the board uses two dma channels;
bit 15..8 board type, overrides autodetection; leave it
zero if don't know what to put in (and you don't,
since this is unsupported at the moment...).
The code will probe for common port addresses (0x220, 0x240
for SB and clones, 0x530 for WSS and clones), so you don't need
to specify them if your system uses one of them. In case you
do, note that for WSS cards the code assumes that the board
occupies 8 IO addresses, the first four used to configure
IRQ/DRQ, and the other four to access codec registers. Many
boards (including all the ones I have) do not have registers
to program IRQ and DRQ, so they really start at 0x534... yet
I decided to use the old convention for historical reasons.
You can use multiple sound cards, in which case you need more
lines like
device pcm1 at isa ? port? tty irq N drq D flags F
device pcm2 at isa ? port? tty irq N drq D flags F
...
EXAMPLES: a typical "device" line for the SB16 (full duplex) is
device pcm0 at isa ? port? tty irq 5 drq 1 flags 0x15
The driver will check at the default addresses (or the one you
specify) which type of SoundBlaster you have (1.5, 2.0, 3.X
aka SBPro, 4.X aka SB16) and use the correct commands. You
_do_not_ need to specify different drivers (sb,sbpro,sbxvi) as
it was the case (and a big source of confusion) in the previous
sound driver.
For a WSS-compatible codec (non PnP) working in full duplex using
dma channels 1 and 3, you can specify:
device pcm0 at isa ? port 0x530 tty irq 7 drq 1 flags 0x13
(0x530 is a default if no port address is specified). The
"flags 0x13" specifies that you have a dual dma board with
channel 3 as secondary DMA channel.
* build the kernel using the standard steps
config MYKERNEL
cd /sys/compile/MYKERNEL
make depend
make
* note for PnP cards:
For PnP cards, only the line for "pcm0" is needed (the code
will allocate entries for more cards if found), but IT MUST
INCLUDE ALL FIELDS. You can use the following line:
device pcm0 at isa ? port? tty irq 7 drq 1
NOTE that:
- the parameters for the PnP device(s) will be read from the
configuration of the card(s); they are usually assigned by
the bios, and there is no way (at the moment) to override
them, so if you have a broken (or no) PnP bios your only
chance is to patch the pnp attach code in the driver for your
card (ad1848.c, sb_dsp.c, clones.c) and write there the
parameters you want;
- The driver will assign unit numbers to the PnP cards starting
from the next free one (e.g. 1, 2, ...) same as it is done
with PCI devices which are clones of ISA devices.
The driver assumes a working PnP bios, which will assign correct
addresses and IO and DMA channels to the devices. If you do not
have a PnP-aware BIOS, you must boot with the -c option and assign
addresses manually the first time. The general commands are described in
the pnp README file. For the card-specific commands check in the
file CARDS.
WHAT IF THIS DRIVER DOES NOT WORK:
If the driver does not work with your hardware, I might to help
but I need the following information:
- relevant lines in your config file;
- dmesg output
- possibly, pnpinfo output
Please send all the above in plain text, not as a mime attachment.
Common mistakes:
* you are trying to use /dev/audio0 instead of /dev/audio1
For technical reasons, a PnP device is attached as unit 1 instead
of unit 0 -- most applications are programmed to access the audio
hardware through /dev/audio, /dev/dsp, /dev/mixer which are in turn
symlinks to the correct device entries. Check them and possibly fix
these symlinks in /dev
* you have used a wrong config line
The configuration of this driver is different from the Voxware one.
Please read the information in this file carefully.
* your BIOS is leaving the card disabled.
Some BIOSes do not initialize the card, or leave it disabled. At the
moment, the fix is to use the pnp code booting with "-c" and set the
correct port, irq, drq etc for the card. See the PnP documentation.
* your card is not recognized.
This driver supports a large, but still limited, number of cards,
mostly SB and WSS clones. Other cards may or may not work depending
on how closely they emulate these devices. In case, send me an email
with the info indicated above.
* the mixer does not work well
Different cards have different connections to the mixer, so it might
well be that to control the volume of your CD you have to use the FM
port, etc. Also, on some cards the volume might be lower than you
expect. The mixer code still does not try to exploit the features of
each card, and it just provides basic functionalities.
--- ACKNOWLEDGMENTS ---
Several people helped, directly or indirectly, in the development of
this driver. In particular I would like to thank:
* Hannu Savolainen (the Voxware author) for making his code
available. It was a very good source of technical info;
* Amancio Hasty for continuous support and his work on guspnp code;
* Jim Lowe for his suggestion on the block-mode select;
* Allison Mankin and Brad Karp at ISI-East for supplying a GUS PnP
which allowed me to support this card;
* Eric J. Schwertfeger for donating an ES1868 card for writing the
driver (which i haven't done yet...).
* and many people who had the patience to try the driver
on their cards and report success/failure and useful
information.
It was certainly helpful to have the data sheets for some of the
devices I support available on the net, especially in the (unfortunately
rare) cases where the data sheets matched the actual behavior of
the product. Too bad that no one of the chip/card manufacturers I
have contacted by email regarding missing or inconsistent documentation
on their products did even care to reply to my messages.

File diff suppressed because it is too large Load Diff

View File

@ -1,262 +0,0 @@
/*
* sound/clones.c
*
* init code for enabling clone cards to work in sb/mss emulation.
*
* Note -- this code is currently unused!
*
* Copyright by Luigi Rizzo - 1997
*
* 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.
*
* This file has been written using information from various sources
* in the Voxware 3.5 distribution.
*/
#include <i386/isa/snd/sound.h>
#if NPCM > 0
/*
* Known clones card include:
*
* Trix (emulating MSS)
* MAD16 (emulating MSS)
* OPTi930 -- same as the OPTi931, but no PnP ?
*/
#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
*/
#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.
*/
static void
smw_putmem(int base, int addr, u_char val)
{
u_long s;
s = spltty();
outb(base + 1, addr & 0xff); /* Low address bits */
outb(base + 2, addr >> 8); /* High address bits */
outb(base, val); /* Data */
splx(s);
}
static u_char
smw_getmem(int base, int addr)
{
u_long s;
u_char val;
s = spltty();
outb(base + 1, addr & 0xff); /* Low address bits */
outb(base + 2, addr >> 8); /* High address bits */
val = inb(base); /* Data */
splx(s);
return val;
}
#ifdef SMW_MIDI0001_INCLUDED
#include </sys/i386/isa/snd/smw-midi0001.h>
#else
u_char *smw_ucode = NULL;
int smw_ucodeLen = 0;
#endif /* SWM_MIDI0001_INCLUDED */
static int
initialize_smw(int mpu_base)
{
int i, mp_base = mpu_base + 4; /* Microcontroller base */
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 = 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
/*
* this is only called during the probe. Variables are found in
* sb_probed.
*/
static sbdev_info sb_probed ;
static int
initialize_ProSonic16(snddev_info *d)
{
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 = NULL;
int mpu_base, mpu_irq;
if (mpu_config != NULL) { /* XXX dead code? */
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, (sb_probed.io_base & 0x70) | ((mpu_base & 0x30) >> 4));
if (sb_reset_dsp(sb_probed.io_base)) { /* OK. We have at least a SB */
/* Check the version number of ProSonic (I guess) */
if (!sb_cmd(sb_probed.io_base, 0xFA))
return 1;
if (sb_get_byte(sb_probed.io_base) != 0x12)
return 1;
if (sb_cmd(sb_probed.io_base, 0xFB) && /* set DMA and irq */
sb_cmd(sb_probed.io_base,
(dma_translat[JAZZ_DMA16]<<4)|dma_translat[sb_probed.dbuf_out.chan]) &&
sb_cmd(sb_probed.io_base,
(int_translat[mpu_irq]<<4)|int_translat[sb_probed.irq])) {
d->bf_flags |= BD_F_JAZZ16 ;
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))
d->bf_flags |= BD_F_JAZZ16_2 ;
#endif
/* sb_dsp_disable_midi(); */
}
return 1; /* There was at least a SB */
}
return 0; /* No SB or ProSonic16 detected */
}
#endif /* ifdef JAZZ16 */
#endif /* NPCM */

View File

@ -1,810 +0,0 @@
/*
* snd/dmabuf.c
*
* This file implements the new DMA routines for the sound driver.
* AUTO DMA MODE (ISA DMA SIDE).
*
* Copyright by Luigi Rizzo - 1997-99
*
* 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/snd/sound.h>
#include <i386/isa/snd/ulaw.h>
#define MIN_CHUNK_SIZE 256 /* for uiomove etc. */
#define DMA_ALIGN_THRESHOLD 4
#define DMA_ALIGN_MASK (~ (DMA_ALIGN_THRESHOLD - 1))
static void dsp_wr_dmadone(snddev_info *d);
static void dsp_rd_dmadone(snddev_info *d);
/*
* SOUND OUTPUT
We use a circular buffer to store samples directed to the DAC.
The buffer is split into two variable-size regions, each identified
by an offset in the buffer (rp,fp) and a length (rl,fl):
0 rp,rl fp,fl bufsize
|__________>____________>________|
FREE d READY w FREE
READY: data written from the process and ready to be sent to the DAC;
FREE: free part of the buffer.
Both regions can wrap around the end of the buffer. At initialization,
READY is empty, FREE takes all the available space, and dma is
idle. dl contains the length of the current DMA transfer, dl=0
means that the dma is idle.
The two boundaries (rp,fp) in the buffers are advanced by DMA [d]
and write() [w] operations. The first portion of the READY region
is used for DMA transfers. The transfer is started at rp and with
chunks of length dl. During DMA operations, dsp_wr_dmaupdate()
updates rp, rl and fl tracking the ISA DMA engine as the transfer
makes progress.
When a new block is written, fp advances and rl,fl are updated
accordingly.
The code works as follows: the user write routine dsp_write_body()
fills up the READY region with new data (reclaiming space from the
FREE region) and starts the write DMA engine if inactive. When a
DMA transfer is complete, an interrupt causes dsp_wrintr() to be
called which extends the FREE region and possibly starts the next
transfer.
In some cases, the code tries to track the current status of DMA
operations by calling dsp_wr_dmaupdate() which changes rp, rl and fl.
The sistem tries to make all DMA transfers use the same size,
play_blocksize or rec_blocksize. The size is either selected by
the user, or computed by the system to correspond to about .25s of
audio. The blocksize must be within a range which is currently:
min(5ms, 40 bytes) ... 1/2 buffer size.
When there aren't enough data (write) or space (read), a transfer
is started with a reduced size.
To reduce problems in case of overruns, the routine which fills up
the buffer should initialize (e.g. by repeating the last value) a
reasonably long area after the last block so that no noise is
produced on overruns.
*
*/
/*
* dsp_wr_dmadone() updates pointers and wakes up any process sleeping
* or waiting on a select().
* Must be called at spltty().
*/
static void
dsp_wr_dmadone(snddev_info *d)
{
snd_dbuf *b = & (d->dbuf_out) ;
if (d->special_dma)
d->callback(d, SND_CB_WR | SND_CB_DMAUPDATE) ;
else
dsp_wr_dmaupdate(b);
/*
* XXX here it would be more efficient to record if there
* actually is a sleeping process, but this should still work.
*/
wakeup(b); /* wakeup possible sleepers */
if (b->sel.si_pid &&
( !(d->flags & SND_F_HAS_SIZE) || b->fl >= d->play_blocksize ) )
selwakeup( & b->sel );
}
/*
* dsp_wr_dmaupdate() tracks the status of a (write) dma transfer,
* updating pointers. It must be called at spltty() and the ISA DMA must
* have been started.
*
* NOTE: when we are using auto dma in the device, rl might become
* negative.
*/
void
dsp_wr_dmaupdate(snd_dbuf *b)
{
int tmp, delta;
tmp = b->bufsize - isa_dmastatus1(b->chan) ;
tmp &= DMA_ALIGN_MASK; /* align... */
delta = tmp - b->rp;
if (delta < 0) /* wrapped */
delta += b->bufsize ;
b->rp = tmp;
b->rl -= delta ;
b->fl += delta ;
b->total += delta ;
}
/*
* Write interrupt routine. Can be called from other places (e.g.
* to start a paused transfer), but with interrupts disabled.
*/
void
dsp_wrintr(snddev_info *d)
{
snd_dbuf *b = & (d->dbuf_out) ;
if (b->dl) { /* dma was active */
b->int_count++;
dsp_wr_dmadone(d);
}
DEB(if (b->rl < 0)
printf("dsp_wrintr: dl %d, rp:rl %d:%d, fp:fl %d:%d\n",
b->dl, b->rp, b->rl, b->fp, b->fl));
/*
* start another dma operation only if have ready data in the buffer,
* there is no pending abort, have a full-duplex device, or have a
* half duplex device and there is no pending op on the other side.
*
* Force transfers to be aligned to a boundary of 4, which is
* needed when doing stereo and 16-bit. We could make this
* adaptive, but why bother for now...
*/
if ( b->rl >= DMA_ALIGN_THRESHOLD &&
! (d->flags & SND_F_ABORTING) &&
( FULL_DUPLEX(d) || ! (d->flags & SND_F_READING) ) ) {
int l = min(b->rl, d->play_blocksize ); /* avoid too large transfer */
l &= DMA_ALIGN_MASK ; /* realign things */
/*
* check if we need to reprogram the DMA on the sound card.
* This happens if the size has changed _and_ the new size
* is smaller, or it matches the blocksize.
*/
if (l != b->dl && (b->dl == 0 || l<b->dl || l == d->play_blocksize) ) {
/* for any reason, size has changed. Stop and restart */
DEB(printf("wrintr: bsz change from %d to %d, rp %d rl %d\n",
b->dl, l, b->rp, b->rl));
DEB(printf("wrintr: dl %d -> %d\n", b->dl, l);)
if (b->dl != 0)
d->callback(d, SND_CB_WR | SND_CB_STOP );
/*
* at high speed, it might well be that the count
* changes in the meantime. So we try to update b->rl
*/
if (d->special_dma)
d->callback(d, SND_CB_WR | SND_CB_DMAUPDATE) ;
else
dsp_wr_dmaupdate(b) ;
l = min(b->rl, d->play_blocksize );
l &= DMA_ALIGN_MASK ; /* realign things */
b->dl = l; /* record previous transfer size */
d->callback(d, SND_CB_WR | SND_CB_START );
}
} else {
/* cannot start a new dma transfer */
DEB(printf("cannot start wr-dma flags 0x%08x rp %d rl %d\n",
d->flags, b->rp, b->rl));
if (b->dl > 0) { /* was active */
b->dl = 0;
d->callback(d, SND_CB_WR | SND_CB_STOP ); /* stop dma */
if (d->flags & SND_F_WRITING)
DEB(printf("Race! got wrint while reloading...\n"));
else if (b->rl <= 0) /* XXX added 980110 lr */
reset_dbuf(b, SND_CHAN_WR);
}
/*
* if switching to read, should start the read dma...
*/
if ( !FULL_DUPLEX(d) && (d->flags & SND_F_READING) )
dsp_rdintr(d);
}
}
/*
* user write routine
*
* advance the boundary between READY and FREE, fill the space with
* uiomove(), and possibly start DMA. Do the above until the transfer
* is complete.
*
* To minimize latency in case a pending DMA transfer is about to end,
* we do the transfer in pieces of increasing sizes, extending the
* READY area at every checkpoint. In the (necessary) assumption that
* memory bandwidth is larger than the rate at which the dma consumes
* data, we reduce the latency to something proportional to the length
* of the first piece, while keeping the overhead low and being able
* to feed the DMA with large blocks.
*
* assume d->flags |= SND_F_WRITING ; has been done before
*/
int
dsp_write_body(snddev_info *d, struct uio *buf)
{
int n, l, bsz, ret = 0 ;
long s;
snd_dbuf *b = & (d->dbuf_out) ;
/*
* bsz is the max size for the next transfer. If the dma was idle
* (dl == 0), we want it as large as possible. Otherwise, start with
* a small block to avoid underruns if we are close to the end of
* the previous operation.
*/
bsz = b->dl ? MIN_CHUNK_SIZE : b->bufsize ;
while ( (n = buf->uio_resid) ) {
l = min (n, bsz); /* at most n bytes ... */
s = spltty(); /* no interrupts here ... */
if (d->special_dma)
d->callback(d, SND_CB_WR | SND_CB_DMAUPDATE) ;
else
dsp_wr_dmaupdate(b);
l = min( l, b->fl ); /* no more than avail. space */
DEB(printf("dsp_write_body: prepare %d bytes out of %d\n", l,n));
/*
* at this point, we assume that if l==0 the dma engine
* must be running.
*/
if (l == 0) { /* no space, must sleep */
int timeout;
if (d->flags & SND_F_NBIO) {
/* unless of course we are doing non-blocking i/o */
splx(s);
break;
}
DEB(printf("dsp_write_body: l=0, (fl %d) sleeping\n", b->fl));
if ( b->fl < n )
timeout = hz;
else
timeout = 1 ;
ret = tsleep( (caddr_t)b, PRIBIO|PCATCH, "dspwr", timeout);
if (ret == EINTR)
d->flags |= SND_F_ABORTING ;
splx(s);
if (ret == EINTR || ret == ERESTART)
break ;
continue;
}
splx(s);
/*
* copy data to the buffer, and possibly do format
* conversions (here, from ULAW to U8).
* NOTE: I can use fp here since it is not modified by the
* interrupt routines.
*/
if (b->fp + l > b->bufsize) {
int l1 = b->bufsize - b->fp ;
uiomove(b->buf + b->fp, l1, buf) ;
uiomove(b->buf, l - l1, buf) ;
if (d->flags & SND_F_XLAT8) {
translate_bytes(ulaw_dsp, b->buf + b->fp, l1);
translate_bytes(ulaw_dsp, b->buf , l - l1);
}
} else {
uiomove(b->buf + b->fp, l, buf) ;
if (d->flags & SND_F_XLAT8)
translate_bytes(ulaw_dsp, b->buf + b->fp, l);
}
s = spltty(); /* no interrupts here ... */
b->rl += l ; /* this more ready bytes */
b->fl -= l ; /* this less free bytes */
b->fp += l ;
if (b->fp >= b->bufsize) /* handle wraps */
b->fp -= b->bufsize ;
if ( b->dl == 0 ) /* dma was idle, restart it */
dsp_wrintr(d) ;
splx(s) ;
if (buf->uio_resid == 0 && (b->fp & (b->sample_size - 1)) == 0) {
/*
* If data is correctly aligned, pad the region with
* replicas of the last sample. l0 goes from current to
* the buffer end, l1 is the portion which wraps around.
*/
int l0, l1, i;
l1 = min(/* b->dl */ d->play_blocksize, b->fl);
l0 = min (l1, b->bufsize - b->fp);
l1 = l1 - l0 ;
i = b->fp - b->sample_size;
if (i < 0 ) i += b->bufsize ;
if (b->sample_size == 1) {
u_char *p= (u_char *)(b->buf + i), sample = *p;
for ( ; l0 ; l0--)
*p++ = sample ;
for (p= (u_char *)(b->buf) ; l1 ; l1--)
*p++ = sample ;
} else if (b->sample_size == 2) {
u_short *p= (u_short *)(b->buf + i), sample = *p;
l1 /= 2 ;
l0 /= 2 ;
for ( ; l0 ; l0--)
*p++ = sample ;
for (p= (u_short *)(b->buf) ; l1 ; l1--)
*p++ = sample ;
} else { /* must be 4 ... */
u_long *p= (u_long *)(b->buf + i), sample = *p;
l1 /= 4 ;
l0 /= 4 ;
for ( ; l0 ; l0--)
*p++ = sample ;
for (p= (u_long *)(b->buf) ; l1 ; l1--)
*p++ = sample ;
}
}
bsz = min(b->bufsize, bsz*2);
}
s = spltty(); /* no interrupts here ... */
d->flags &= ~SND_F_WRITING ;
if (d->flags & SND_F_ABORTING) {
d->flags &= ~SND_F_ABORTING;
splx(s);
dsp_wrabort(d, 1 /* restart */);
/* XXX return EINTR ? */
}
splx(s) ;
return ret ;
}
/*
* SOUND INPUT
*
The input part is similar to the output one, with a circular buffer
split in two regions, and boundaries advancing because of read() calls
[r] or dma operation [d]. At initialization, as for the write
routine, READY is empty, and FREE takes all the space.
0 rp,rl fp,fl bufsize
|__________>____________>________|
FREE r READY d FREE
Operation is as follows: upon user read (dsp_read_body()) a DMA read
is started if not already active (marked by b->dl > 0),
then as soon as data are available in the READY region they are
transferred to the user buffer, thus advancing the boundary between FREE
and READY. Upon interrupts, caused by a completion of a DMA transfer,
the READY region is extended and possibly a new transfer is started.
When necessary, dsp_rd_dmaupdate() is called to advance fp (and update
rl,fl accordingly). Upon user reads, rp is advanced and rl,fl are
updated accordingly.
The rules to choose the size of the new DMA area are similar to
the other case, with a preferred constant transfer size equal to
rec_blocksize, and fallback to smaller sizes if no space is available.
*
*/
/*
* dsp_rd_dmadone moves bytes in the input buffer from DMA region to
* READY region. We assume it is called at spltty() and with dl>0
*/
static void
dsp_rd_dmadone(snddev_info *d)
{
snd_dbuf *b = & (d->dbuf_in) ;
if (d->special_dma)
d->callback(d, SND_CB_RD | SND_CB_DMAUPDATE) ;
else
dsp_rd_dmaupdate(b);
wakeup(b) ; /* wakeup possibly sleeping processes */
if (b->sel.si_pid &&
( !(d->flags & SND_F_HAS_SIZE) || b->rl >= d->rec_blocksize ) )
selwakeup( & b->sel );
}
/*
* The following function tracks the status of a (read) dma transfer,
* and moves the boundary between the READY and the DMA regions.
* It works under the following assumptions:
* - the DMA engine is running;
* - the function is called with interrupts blocked.
*/
void
dsp_rd_dmaupdate(snd_dbuf *b)
{
int delta, tmp ;
tmp = b->bufsize - isa_dmastatus1(b->chan) ;
tmp &= DMA_ALIGN_MASK; /* align... */
delta = tmp - b->fp;
if (delta < 0) /* wrapped */
delta += b->bufsize ;
b->fp = tmp;
b->fl -= delta ;
b->rl += delta ;
b->total += delta ;
}
/*
* read interrupt routine. Must be called with interrupts blocked.
*/
void
dsp_rdintr(snddev_info *d)
{
snd_dbuf *b = & (d->dbuf_in) ;
if (b->dl) { /* dma was active */
b->int_count++;
dsp_rd_dmadone(d);
}
DEB(printf("dsp_rdintr: start dl %d, rp:rl %d:%d, fp:fl %d:%d\n",
b->dl, b->rp, b->rl, b->fp, b->fl));
/*
* Restart if have enough free space to absorb overruns;
*/
if ( b->fl > 0x200 &&
(d->flags & (SND_F_ABORTING|SND_F_CLOSING)) == 0 &&
( FULL_DUPLEX(d) || (d->flags & SND_F_WRITING) == 0 ) ) {
int l = min(b->fl - 0x100, d->rec_blocksize);
l &= DMA_ALIGN_MASK ; /* realign sizes */
DEB(printf("rdintr: dl %d -> %d\n", b->dl, l);)
if (l != b->dl) {
/* for any reason, size has changed. Stop and restart */
if (b->dl > 0 )
d->callback(d, SND_CB_RD | SND_CB_STOP );
b->dl = l ;
d->callback(d, SND_CB_RD | SND_CB_START );
}
} else {
if (b->dl > 0) { /* was active */
b->dl = 0;
d->callback(d, SND_CB_RD | SND_CB_STOP);
}
/*
* if switching to write, start write dma engine
*/
if ( ! FULL_DUPLEX(d) && (d->flags & SND_F_WRITING) )
dsp_wrintr(d) ;
DEB(printf("cannot start rd-dma rl %d fl %d\n",
b->rl, b->fl));
}
}
/*
* body of user-read routine
*
* Start DMA if not active; wait for READY not empty.
* Transfer data from READY region using uiomove(), advance boundary
* between FREE and READY. Repeat until transfer is complete.
*
* To avoid excessive latency in freeing up space for the DMA
* engine, transfers are done in blocks of increasing size, so that
* the latency is proportional to the size of the smallest block, but
* we have a low overhead and are able to feed the dma engine with
* large blocks.
*
* When we enter this routine, we assume that d->flags |= SND_F_READING
* was done before.
*
* NOTE: in the current version, read will not return more than
* blocksize bytes at once (unless more are already available), to
* avoid that requests using very large buffers block for too long.
*/
int
dsp_read_body(snddev_info *d, struct uio *buf)
{
int limit, l, n, bsz, ret = 0 ;
long s;
snd_dbuf *b = & (d->dbuf_in) ;
/*
* "limit" serves to return after at most one blocksize of data
* (unless more are already available). Otherwise, things like
* cat /dev/audio would use a 64K buffer and would start returning
* data after a _very_ long time...
* Note -- some applications depend on reads not returning short
* blocks. But I believe these apps are broken, since interrupted
* system calls might return short reads anyways, and the
* application should better check that.
*/
if (buf->uio_resid > d->rec_blocksize)
limit = buf->uio_resid - d->rec_blocksize;
else
limit = 0;
bsz = MIN_CHUNK_SIZE ; /* the current transfer (doubles at each step) */
while ( (n = buf->uio_resid) > limit ) {
DEB(printf("dsp_read_body: start waiting for %d bytes\n", n));
l = min (n, bsz);
s = spltty(); /* no interrupts here ! */
if (d->special_dma)
d->callback(d, SND_CB_RD | SND_CB_DMAUPDATE) ;
else
dsp_rd_dmaupdate(b);
l = min( l, b->rl ); /* no more than avail. data */
if (l == 0) {
int timeout;
/*
* If there is no data ready, then we must sleep (unless
* of course we have doing non-blocking i/o). But also
* consider restarting the DMA engine.
*/
if ( b->dl == 0 ) { /* dma was idle, start it */
if ( d->flags & SND_F_INIT && d->dbuf_out.dl == 0 ) {
/* want to init and there is no pending DMA activity */
splx(s);
d->callback(d, SND_CB_INIT); /* this is slow! */
s = spltty();
}
dsp_rdintr(d);
}
if (d->flags & SND_F_NBIO) {
splx(s);
break;
}
if (n-limit > b->dl)
timeout = hz; /* we need to wait for an int. */
else
timeout = 1; /* maybe data will be ready earlier */
ret = tsleep( (caddr_t)b, PRIBIO | PCATCH , "dsprd", timeout ) ;
if (ret == EINTR)
d->flags |= SND_F_ABORTING ;
splx(s);
if (ret == EINTR || ret == ERESTART)
break ;
continue;
}
splx(s);
/*
* Do any necessary format conversion, and copy to user space.
* NOTE: I _can_ use rp here because it is not modified by the
* interrupt routines.
*/
if (b->rp + l > b->bufsize) { /* handle wraparounds */
int l1 = b->bufsize - b->rp ;
if (d->flags & SND_F_XLAT8) {
translate_bytes(dsp_ulaw, b->buf + b->rp, l1);
translate_bytes(dsp_ulaw, b->buf , l - l1);
}
uiomove(b->buf + b->rp, l1, buf) ;
uiomove(b->buf, l - l1, buf) ;
} else {
if (d->flags & SND_F_XLAT8)
translate_bytes(dsp_ulaw, b->buf + b->rp, l);
uiomove(b->buf + b->rp, l, buf) ;
}
s = spltty(); /* no interrupts here ... */
b->fl += l ; /* this more free bytes */
b->rl -= l ; /* this less ready bytes */
b->rp += l ; /* advance ready pointer */
if (b->rp >= b->bufsize) /* handle wraps */
b->rp -= b->bufsize ;
splx(s) ;
bsz = min(b->bufsize, bsz*2);
}
s = spltty(); /* no interrupts here ... */
d->flags &= ~SND_F_READING ;
if (d->flags & SND_F_ABORTING) {
d->flags &= ~SND_F_ABORTING; /* XXX */
splx(s);
dsp_rdabort(d, 1 /* restart */);
/* XXX return EINTR ? */
}
splx(s) ;
return ret ;
}
/*
* short routine to initialize a dma buffer descriptor (usually
* located in the XXX_desc structure). The first parameter is
* the buffer size, the second one specifies that a 16-bit dma channel
* is used (hence the buffer must be properly aligned).
*/
void
alloc_dbuf(snd_dbuf *b, int size)
{
if (size > 0x10000)
panic("max supported size is 64k");
b->buf = contigmalloc(size, M_DEVBUF, M_NOWAIT,
0ul, 0xfffffful, 1ul, 0x10000ul);
/* should check that malloc does not fail... */
b->rp = b->fp = 0 ;
b->dl = b->rl = 0 ;
b->bufsize = b->fl = size ;
}
/*
* this resets a buffer and starts the isa dma on that channel.
* Must be called when the dma on the card is disabled (e.g. after init).
*/
void
reset_dbuf(snd_dbuf *b, int chan)
{
DEB(printf("reset dbuf for chan %d\n", b->chan));
b->rp = b->fp = 0 ;
b->dl = b->rl = 0 ;
b->fl = b->bufsize ;
if (chan == SND_CHAN_NONE)
return ;
if (chan == SND_CHAN_WR)
chan = B_WRITE | B_RAW ;
else
chan = B_READ | B_RAW ;
if (b->chan != 4 && b->chan < 8) /* XXX hack for pci... */
isa_dmastart( chan , b->buf, b->bufsize, b->chan);
}
/*
* snd_sync waits until the space in the given channel goes above
* a threshold. chan = 1 : play, 2: capture. The threshold is
* checked against fl or rl respectively.
* Assume that the condition can become true, do not check here...
*/
int
snd_sync(snddev_info *d, int chan, int threshold)
{
u_long s;
int ret;
snd_dbuf *b;
b = (chan == 1) ? &(d->dbuf_out ) : &(d->dbuf_in ) ;
for (;;) {
s=spltty();
if (d->special_dma)
d->callback(d, (chan==1? SND_CB_WR:SND_CB_RD) | SND_CB_DMAUPDATE);
else {
if ( chan==1 )
dsp_wr_dmaupdate(b);
else
dsp_rd_dmaupdate(b);
}
if ( (chan == 1 && b->fl <= threshold) ||
(chan == 2 && b->rl <= threshold) ) {
ret = tsleep((caddr_t)b, PRIBIO|PCATCH, "sndsyn", 1);
splx(s);
if (ret == ERESTART || ret == EINTR) {
printf("tsleep returns %d\n", ret);
return -1 ;
}
} else
break;
}
splx(s);
return 0 ;
}
/*
* dsp_wrabort(d) and dsp_rdabort(d) are non-blocking functions
* which abort a pending DMA transfer and flush the buffers.
* They return the number of bytes that has not been transferred.
* The second parameter is used to restart the engine if needed.
*/
int
dsp_wrabort(snddev_info *d, int restart)
{
long s;
int missing = 0;
snd_dbuf *b = & (d->dbuf_out) ;
s = spltty();
if ( b->dl ) {
b->dl = 0 ;
d->flags &= ~ SND_F_WRITING ;
if (d->callback)
d->callback(d, SND_CB_WR | SND_CB_ABORT);
if (!d->special_dma)
isa_dmastop(b->chan) ;
dsp_wr_dmadone(d);
DEB(printf("dsp_wrabort: stopped, %d bytes left\n", b->rl));
}
missing = b->rl;
if (!d->special_dma)
isa_dmadone(B_WRITE, b->buf, b->bufsize, b->chan); /*free chan */
reset_dbuf(b, restart ? SND_CHAN_WR : SND_CHAN_NONE);
splx(s);
return missing;
}
int
dsp_rdabort(snddev_info *d, int restart)
{
long s;
int missing = 0;
snd_dbuf *b = & (d->dbuf_in) ;
s = spltty();
if ( b->dl ) {
b->dl = 0 ;
d->flags &= ~ SND_F_READING ;
if (d->callback)
d->callback(d, SND_CB_RD | SND_CB_ABORT);
if (!d->special_dma)
isa_dmastop(b->chan) ;
dsp_rd_dmadone(d);
}
missing = b->rl ;
if (!d->special_dma)
isa_dmadone(B_READ, b->buf, b->bufsize, b->chan);
reset_dbuf(b, restart ? SND_CHAN_RD : SND_CHAN_NONE);
splx(s);
return missing;
}
/*
* this routine tries to flush the dma transfer. It is called
* on a close. The caller must set SND_F_CLOSING, and insure that
* interrupts are enabled. We immediately abort any read DMA
* operation, and then wait for the play buffer to drain.
*/
int
snd_flush(snddev_info *d)
{
int ret, count=10;
u_long s;
snd_dbuf *b = &(d->dbuf_out) ;
DEB(printf("snd_flush d->flags 0x%08x\n", d->flags));
dsp_rdabort(d, 0 /* no restart */);
/* close write */
while ( b->dl ) {
/*
* still pending output data.
*/
ret = tsleep( (caddr_t)b, PRIBIO|PCATCH, "dmafl1", hz);
if (d->special_dma)
d->callback(d, SND_CB_WR | SND_CB_DMAUPDATE);
else
dsp_wr_dmaupdate(b);
DEB( printf("snd_sync: now rl : fl %d : %d\n", b->rl, b->fl ) );
if (ret == EINTR) {
printf("tsleep returns %d\n", ret);
return -1 ;
}
if ( ret && --count == 0) {
printf("timeout flushing dbuf_out, chan %d cnt 0x%x flags 0x%08lx\n",
b->chan,
b->rl, d->flags);
break;
}
}
s = spltty(); /* should not be necessary... */
d->flags &= ~SND_F_CLOSING ;
dsp_wrabort(d, 0 /* no restart */);
splx(s);
return 0 ;
}
/*
* end of new code for dma buffer handling
*/

View File

@ -1,304 +0,0 @@
/*
* file: mss.h
*
* (C) 1997 Luigi Rizzo (luigi@iet.unipi.it)
*
* This file contains information and macro definitions for
* AD1848-compatible devices, used in the MSS/WSS compatible boards.
*
*/
/*
*
The codec part of the board is seen as a set of 4 registers mapped
at the base address for the board (default 0x534). Note that some
(early) boards implemented 4 additional registers 4 location before
(usually 0x530) to store configuration information. This is a source
of confusion in that one never knows what address to specify. The
(current) convention is to use the old address (0x530) in the kernel
configuration file and consider MSS registers start four location
ahead.
*
*/
/*
* The four visible registers of the MSS :
*
*/
#define io_Index_Addr(d) ((d)->io_base + 4)
#define IA_BUSY 0x80 /* readonly, set when busy */
#define IA_MCE 0x40 /* the MCE bit. */
/*
* the MCE bit must be set whenever the current mode of the
* codec is changed; this in particular is true for the
* Data Format (I8, I28) and Interface Config(I9) registers.
* Only exception are CEN and PEN which can be changed on the fly.
* The DAC output is muted when MCE is set.
*/
#define IA_TRD 0x20 /* Transfer request disable */
/*
* When TRD is set, DMA transfers cease when the INT bit in
* the MSS status reg is set. Must be cleared for automode
* DMA, set otherwise.
*/
#define IA_AMASK 0x1f /* mask for indirect address */
#define io_Indexed_Data(d) ((d)->io_base+1+4)
/*
* data to be transferred to the indirect register addressed
* by index addr. During init and sw. powerdown, cannot be
* written to, and is always read as 0x80 (consistent with the
* busy flag).
*/
#define io_Status(d) ((d)->io_base+2+4)
#define IS_CUL 0x80 /* capture upper/lower */
#define IS_CLR 0x40 /* capture left/right */
#define IS_CRDY 0x20 /* capture ready for programmed i/o */
#define IS_SER 0x10 /* sample error (overrun/underrun) */
#define IS_PUL 0x08 /* playback upper/lower */
#define IS_PLR 0x04 /* playback left/right */
#define IS_PRDY 0x02 /* playback ready for programmed i/o */
#define IS_INT 0x01 /* int status (1 = active) */
/*
* IS_INT is clreared by any write to the status register.
*/
#define io_Polled_IO(d) ((d)->io_base+3+4)
/*
* this register is used in case of polled i/o
*/
/*
* The MSS has a set of 16 (or 32 depending on the model) indirect
* registers accessible through the data port by specifying the
* appropriate address in the address register.
*
* The 16 low registers are uniformly handled in AD1848/CS4248 compatible
* mode (often called MODE1). For the upper 16 registers there are
* some differences among different products, mainly Crystal uses them
* differently from OPTi.
*
*/
/*
* volume registers
*/
#define I6_MUTE 0x80
/*
* register I9 -- interface configuration.
*/
#define I9_PEN 0x01 /* playback enable */
#define I9_CEN 0x02 /* capture enable */
/*
* values used in bd_flags
*/
#define BD_F_MCE_BIT 0x0001
#define BD_F_IRQ_OK 0x0002
#define BD_F_TMR_RUN 0x0004
/* AD1816 register macros */
#define ad1816_ale(d) ((d)->io_base+0) /* indirect reg access */
#define ad1816_int(d) ((d)->io_base+1) /* interupt status */
#define ad1816_low(d) ((d)->io_base+2) /* indirect low byte */
#define ad1816_high(d) ((d)->io_base+3) /* indirect high byte */
/* unused */
#define ad1816_pioD(d) ((d)->io_base+4) /* PIO debug */
#define ad1816_pios(d) ((d)->io_base+5) /* PIO status */
#define ad1816_piod(d) ((d)->io_base+6) /* PIO data */
/* end of unused */
/* values for playback/capture config:
bits: 0 enable/disable
1 pio/dma
2 stereo/mono
3 companded/linearPCM
4-5 format : 00 8bit linear (uncomp)
00 8bit mulaw (comp)
01 16bit le (uncomp)
01 8bit alaw (comp)
11 16bit be (uncomp)
*/
#define ad1816_play(d) ((d)->io_base+8) /* playback config */
#define ad1816_capt(d) ((d)->io_base+9) /* capture config */
#define AD1816_BUSY 0x80 /* chip is busy */
#define AD1816_ALEMASK 0x3F /* mask for indirect adr. */
/* unusud */
#define AD1816_INTRSI 0x01 /* sb intr */
#define AD1816_INTRGI 0x02 /* game intr */
#define AD1816_INTRRI 0x04 /* ring intr */
#define AD1816_INTRDI 0x08 /* dsp intr */
#define AD1816_INTRVI 0x10 /* vol intr */
#define AD1816_INTRTI 0x20 /* timer intr */
/* used again */
#define AD1816_INTRCI 0x40 /* capture intr */
#define AD1816_INTRPI 0x80 /* playback intr */
/* PIO stuff is not supplied here */
/* playback / capture config */
#define AD1816_ENABLE 0x01 /* enable pl/cp */
#define AD1816_PIO 0x02 /* use pio */
#define AD1816_STEREO 0x04
#define AD1816_COMP 0x08 /* data is companded */
#define AD1816_U8 0x00 /* 8 bit linear pcm */
#define AD1816_MULAW 0x08 /* 8 bit mulaw */
#define AD1816_ALAW 0x18 /* 8 bit alaw */
#define AD1816_S16LE 0x10 /* 16 bit linear little endian */
#define AD1816_S16BE 0x30 /* 16 bit linear big endian */
#define AD1816_FORMASK 0x38 /* format mask */
/*
* sound/ad1848_mixer.h
*
* Definitions for the mixer of AD1848 and compatible codecs.
*
* Copyright by Hannu Savolainen 1994
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. 2.
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* The AD1848 codec has generic input lines called Line, Aux1 and Aux2.
* Soundcard manufacturers have connected actual inputs (CD, synth, line,
* etc) to these inputs in different order. Therefore it's difficult
* to assign mixer channels to to these inputs correctly. The following
* contains two alternative mappings. The first one is for GUS MAX and
* the second is just a generic one (line1, line2 and line3).
* (Actually this is not a mapping but rather some kind of interleaving
* solution).
*/
#define MSS_REC_DEVICES \
(SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD|SOUND_MASK_IMIX)
/*
* Table of mixer registers. There is a default table for the
* AD1848/CS423x clones, and one for the OPTI931. As more MSS
* clones come out, there ought to be more tables.
*
* Fields in the table are : polarity, register, offset, bits
*
* The channel numbering used by individual soundcards is not fixed.
* Some cards have assigned different meanings for the AUX1, AUX2
* and LINE inputs. Some have different features...
*
* Following there is a macro ...MIXER_DEVICES which is a bitmap
* of all non-zero fields in the table.
* MODE1_MIXER_DEVICES is the basic mixer of the 1848 in mode 1
* registers I0..I15)
*
*/
mixer_ent mix_devices[32][2] = {
MIX_NONE(SOUND_MIXER_VOLUME),
MIX_NONE(SOUND_MIXER_BASS),
MIX_NONE(SOUND_MIXER_TREBLE),
MIX_ENT(SOUND_MIXER_SYNTH, 2, 1, 0, 5, 3, 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, 0, 5, 1, 1, 0, 5, 1),
MIX_ENT(SOUND_MIXER_CD, 4, 1, 0, 5, 5, 1, 0, 5),
MIX_ENT(SOUND_MIXER_IMIX, 13, 1, 2, 6, 0, 0, 0, 0),
MIX_NONE(SOUND_MIXER_ALTPCM),
MIX_NONE(SOUND_MIXER_RECLEV),
MIX_ENT(SOUND_MIXER_IGAIN, 0, 0, 0, 4, 1, 0, 0, 4),
MIX_NONE(SOUND_MIXER_OGAIN),
MIX_NONE(SOUND_MIXER_LINE1),
MIX_NONE(SOUND_MIXER_LINE2),
MIX_NONE(SOUND_MIXER_LINE3),
};
#define MODE2_MIXER_DEVICES \
(SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_SPEAKER | \
SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD | \
SOUND_MASK_IMIX | SOUND_MASK_IGAIN )
#define MODE1_MIXER_DEVICES \
(SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_MIC | \
SOUND_MASK_CD | SOUND_MASK_IMIX | SOUND_MASK_IGAIN )
/*
* entries for the opti931...
*/
mixer_ent opti931_devices[32][2] = { /* for the opti931 */
MIX_ENT(SOUND_MIXER_VOLUME, 22, 1, 1, 5, 23, 1, 1, 5),
MIX_NONE(SOUND_MIXER_BASS),
MIX_NONE(SOUND_MIXER_TREBLE),
MIX_ENT(SOUND_MIXER_SYNTH, 4, 1, 1, 4, 5, 1, 1, 4),
MIX_ENT(SOUND_MIXER_PCM, 6, 1, 0, 5, 7, 1, 0, 5),
MIX_NONE(SOUND_MIXER_SPEAKER),
MIX_ENT(SOUND_MIXER_LINE, 18, 1, 1, 4, 19, 1, 1, 4),
MIX_ENT(SOUND_MIXER_MIC, 0, 0, 5, 1, 1, 0, 5, 1),
MIX_ENT(SOUND_MIXER_CD, 2, 1, 1, 4, 3, 1, 1, 4),
MIX_NONE(SOUND_MIXER_IMIX),
MIX_NONE(SOUND_MIXER_ALTPCM),
MIX_NONE(SOUND_MIXER_RECLEV),
MIX_ENT(SOUND_MIXER_IGAIN, 0, 0, 0, 4, 1, 0, 0, 4),
MIX_NONE(SOUND_MIXER_OGAIN),
MIX_ENT(SOUND_MIXER_LINE1, 16, 1, 1, 4, 17, 1, 1, 4),
MIX_NONE(SOUND_MIXER_LINE2),
MIX_NONE(SOUND_MIXER_LINE3),
};
#define OPTI931_MIXER_DEVICES \
(SOUND_MASK_VOLUME | SOUND_MASK_SYNTH | SOUND_MASK_PCM | \
SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD | \
SOUND_MASK_IGAIN | SOUND_MASK_LINE1 )
#define AD1816_REC_DEVICES \
(SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD)
#define AD1816_MIXER_DEVICES \
(SOUND_MASK_VOLUME | SOUND_MASK_PCM | SOUND_MASK_SYNTH | \
SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD | SOUND_MASK_IGAIN)
static u_short default_mixer_levels[SOUND_MIXER_NRDEVICES] = {
0x5a5a, /* Master Volume */
0x3232, /* Bass */
0x3232, /* Treble */
0x4b4b, /* FM */
0x4040, /* PCM */
0x4b4b, /* PC Speaker */
0x2020, /* Ext Line */
0x4040, /* Mic */
0x4b4b, /* CD */
0x0000, /* Recording monitor */
0x4b4b, /* SB PCM */
0x4b4b, /* Recording level */
0x2525, /* Input gain */
0x0000, /* Output gain */
/* 0x4040, Line1 */
0x0000, /* Line1 */
0x0000, /* Line2 */
0x1515 /* Line3 (usually line in)*/
};

File diff suppressed because it is too large Load Diff

View File

@ -1,405 +0,0 @@
/*
* file: sbcard.h
*/
typedef struct _sbdev_info {
} sbdev_info ;
extern int sbc_major, sbc_minor ;
/*
* sound blaster registers
*/
#define SBDSP_RST 0x6
#define DSP_READ (io_base + 0xA)
#define DSP_WRITE (io_base + 0xC)
#define SBDSP_CMD 0xC
#define SBDSP_STATUS 0xC
#define DSP_DATA_AVAIL (io_base + 0xE)
#define DSP_DATA_AVL16 (io_base + 0xF)
#define SB_MIX_ADDR 0x4
#define SB_MIX_DATA 0x5
#if 0
#define OPL3_LEFT (io_base + 0x0)
#define OPL3_RIGHT (io_base + 0x2)
#define OPL3_BOTH (io_base + 0x8)
#endif
/*
* DSP Commands. There are many, and in many cases they are used explicitly
*/
/* these are not used except for programmed I/O (not in this driver) */
#define DSP_DAC8 0x10 /* direct DAC output */
#define DSP_ADC8 0x20 /* direct ADC input */
/* these should be used in the SB 1.0 */
#define DSP_CMD_DAC8 0x14 /* single cycle 8-bit dma out */
#define DSP_CMD_ADC8 0x24 /* single cycle 8-bit dma in */
/* these should be used in the SB 2.0 and 2.01 */
#define DSP_CMD_DAC8_AUTO 0x1c /* auto 8-bit dma out */
#define DSP_CMD_ADC8_AUTO 0x2c /* auto 8-bit dma out */
#define DSP_CMD_HSSIZE 0x48 /* high speed dma count */
#define DSP_CMD_HSDAC_AUTO 0x90 /* high speed dac, auto */
#define DSP_CMD_HSADC_AUTO 0x98 /* high speed adc, auto */
/* SBPro commands. Some cards (JAZZ, SMW) also support 16 bits */
/* prepare for dma input */
#define DSP_CMD_DMAMODE(stereo, bit16) (0xA0 | (stereo ? 8:0) | (bit16 ? 4:0))
#define DSP_CMD_DAC2 0x16 /* 2-bit adpcm dma out (cont) */
#define DSP_CMD_DAC2S 0x17 /* 2-bit adpcm dma out (start) */
#define DSP_CMD_DAC2S_AUTO 0x1f /* auto 2-bit adpcm dma out (start) */
/* SB16 commands */
#define DSP_CMD_O16 0xb0
#define DSP_CMD_I16 0xb8
#define DSP_CMD_O8 0xc0
#define DSP_CMD_I8 0xc8
#define DSP_MODE_U8MONO 0x00
#define DSP_MODE_U8STEREO 0x20
#define DSP_MODE_S16MONO 0x10
#define DSP_MODE_S16STEREO 0x30
#define DSP_CMD_SPKON 0xD1
#define DSP_CMD_SPKOFF 0xD3
#define DSP_CMD_SPKR(on) (0xD1 | (on ? 0:2))
#define DSP_CMD_DMAPAUSE_8 0xD0
#define DSP_CMD_DMAPAUSE_16 0xD5
#define DSP_CMD_DMAEXIT_8 0xDA
#define DSP_CMD_DMAEXIT_16 0xD9
#define DSP_CMD_TCONST 0x40 /* set time constant */
#define DSP_CMD_HSDAC 0x91 /* high speed dac */
#define DSP_CMD_HSADC 0x99 /* high speed adc */
#define DSP_CMD_GETVER 0xE1
#define DSP_CMD_GETID 0xE7 /* return id bytes */
#define DSP_CMD_OUT16 0x41 /* send parms for dma out on sb16 */
#define DSP_CMD_IN16 0x42 /* send parms for dma in on sb16 */
#if 0 /*** unknown ***/
#define DSP_CMD_FA 0xFA /* get version from prosonic*/
#define DSP_CMD_FB 0xFB /* set irq/dma for prosonic*/
#endif
/*
* in fact, for the SB16, dma commands are as follows:
*
* cmd, mode, len_low, len_high.
*
* cmd is a combination of DSP_DMA16 or DSP_DMA8 and
*/
#define DSP_DMA16 0xb0
#define DSP_DMA8 0xc0
# define DSP_F16_DAC 0x00
# define DSP_F16_ADC 0x08
# define DSP_F16_AUTO 0x04
# define DSP_F16_FIFO_ON 0x02
/*
* mode is a combination of the following:
*/
#define DSP_F16_STEREO 0x20
#define DSP_F16_SIGNED 0x10
#define IMODE_NONE 0
#define IMODE_OUTPUT PCM_ENABLE_OUTPUT
#define IMODE_INPUT PCM_ENABLE_INPUT
#define IMODE_INIT 3
#define IMODE_MIDI 4
#define NORMAL_MIDI 0
#define UART_MIDI 1
/*
* values used for bd_flags in SoundBlaster driver
*/
#define BD_F_HISPEED 0x0001 /* doing high speed ... */
#define BD_F_JAZZ16 0x0002 /* jazz16 detected */
#define BD_F_JAZZ16_2 0x0004 /* jazz16 type 2 */
#define BD_F_DUP_MIDI 0x0008 /* duplex midi */
#define BD_F_MIX_MASK 0x0070 /* up to 8 mixers (I know of 3) */
#define BD_F_MIX_CT1335 0x0010 /* CT1335 */
#define BD_F_MIX_CT1345 0x0020 /* CT1345 */
#define BD_F_MIX_CT1745 0x0030 /* CT1745 */
#define BD_F_SB16 0x0100 /* this is a SB16 */
#define BD_F_SB16X 0x0200 /* this is a vibra16X or clone */
#define BD_F_MIDIBUSY 0x0400 /* midi busy */
#define BD_F_ESS 0x0800 /* this is an ESS chip */
/*
* on some SB16 cards, at times I swap DMA channels. Remember this
* so that they can be restored later.
*/
#define BD_F_SWAPPED 0x1000 /* have swapped DMA channels */
/*
* sound/sb_mixer.h
*
* Definitions for the SB Pro and SB16 mixers
*
* 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.
*
* Modified: Hunyue Yau Jan 6 1994 Added defines for the Sound Galaxy NX Pro
* mixer.
*
*/
#define SBPRO_RECORDING_DEVICES \
(SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD)
/* Same as SB Pro, unless I find otherwise */
#define SGNXPRO_RECORDING_DEVICES SBPRO_RECORDING_DEVICES
#define SBPRO_MIXER_DEVICES \
(SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_LINE | SOUND_MASK_MIC | \
SOUND_MASK_CD | SOUND_MASK_VOLUME)
/*
* SG NX Pro has treble and bass settings on the mixer. The 'speaker' channel
* is the COVOX/DisneySoundSource emulation volume control on the mixer. It
* does NOT control speaker volume. Should have own mask eventually?
*/
#define SGNXPRO_MIXER_DEVICES \
(SBPRO_MIXER_DEVICES | SOUND_MASK_BASS | \
SOUND_MASK_TREBLE | SOUND_MASK_SPEAKER )
#define SB16_RECORDING_DEVICES \
(SOUND_MASK_SYNTH | SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD)
#define SB16_MIXER_DEVICES \
(SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_SPEAKER | \
SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD | \
SOUND_MASK_IGAIN | SOUND_MASK_OGAIN | \
SOUND_MASK_VOLUME | SOUND_MASK_BASS | SOUND_MASK_TREBLE)
/*
* Mixer registers
*
* NOTE! RECORD_SRC == IN_FILTER
*/
/*
* Mixer registers of SB Pro
*/
#define VOC_VOL 0x04
#define MIC_VOL 0x0A
#define MIC_MIX 0x0A
#define RECORD_SRC 0x0C
#define IN_FILTER 0x0C
#define OUT_FILTER 0x0E
#define MASTER_VOL 0x22
#define FM_VOL 0x26
#define CD_VOL 0x28
#define LINE_VOL 0x2E
#define IRQ_NR 0x80
#define DMA_NR 0x81
#define IRQ_STAT 0x82
/*
* Additional registers on the SG NX Pro
*/
#define COVOX_VOL 0x42
#define TREBLE_LVL 0x44
#define BASS_LVL 0x46
#define FREQ_HI (1 << 3)/* Use High-frequency ANFI filters */
#define FREQ_LOW 0 /* Use Low-frequency ANFI filters */
#define FILT_ON 0 /* Yes, 0 to turn it on, 1 for off */
#define FILT_OFF (1 << 5)
#define MONO_DAC 0x00
#define STEREO_DAC 0x02
/*
* Mixer registers of SB16
*/
#define SB16_IMASK_L 0x3d
#define SB16_IMASK_R 0x3e
#define SB16_OMASK 0x3c
#ifndef __SB_MIXER_C__
mixer_tab sbpro_mix;
mixer_tab sb16_mix;
#ifdef __SGNXPRO__
mixer_tab sgnxpro_mix;
#endif
static u_char sb16_recmasks_L[SOUND_MIXER_NRDEVICES];
static u_char sb16_recmasks_R[SOUND_MIXER_NRDEVICES];
#else /* __SB_MIXER_C__ defined */
mixer_tab sbpro_mix = {
PMIX_ENT(SOUND_MIXER_VOLUME, 0x22, 4, 4, 0x22, 0, 4),
PMIX_ENT(SOUND_MIXER_BASS, 0x00, 0, 0, 0x00, 0, 0),
PMIX_ENT(SOUND_MIXER_TREBLE, 0x00, 0, 0, 0x00, 0, 0),
PMIX_ENT(SOUND_MIXER_SYNTH, 0x26, 4, 4, 0x26, 0, 4),
PMIX_ENT(SOUND_MIXER_PCM, 0x04, 4, 4, 0x04, 0, 4),
PMIX_ENT(SOUND_MIXER_SPEAKER, 0x00, 0, 0, 0x00, 0, 0),
PMIX_ENT(SOUND_MIXER_LINE, 0x2e, 4, 4, 0x2e, 0, 4),
PMIX_ENT(SOUND_MIXER_MIC, 0x0a, 0, 3, 0x00, 0, 0),
PMIX_ENT(SOUND_MIXER_CD, 0x28, 4, 4, 0x28, 0, 4),
PMIX_ENT(SOUND_MIXER_IMIX, 0x00, 0, 0, 0x00, 0, 0),
PMIX_ENT(SOUND_MIXER_ALTPCM, 0x00, 0, 0, 0x00, 0, 0),
PMIX_ENT(SOUND_MIXER_RECLEV, 0x00, 0, 0, 0x00, 0, 0)
};
#ifdef __SGNXPRO__
mixer_tab sgnxpro_mix = {
PMIX_ENT(SOUND_MIXER_VOLUME, 0x22, 4, 4, 0x22, 0, 4),
PMIX_ENT(SOUND_MIXER_BASS, 0x46, 0, 3, 0x00, 0, 0),
PMIX_ENT(SOUND_MIXER_TREBLE, 0x44, 0, 3, 0x00, 0, 0),
PMIX_ENT(SOUND_MIXER_SYNTH, 0x26, 4, 4, 0x26, 0, 4),
PMIX_ENT(SOUND_MIXER_PCM, 0x04, 4, 4, 0x04, 0, 4),
PMIX_ENT(SOUND_MIXER_SPEAKER, 0x42, 0, 3, 0x00, 0, 0),
PMIX_ENT(SOUND_MIXER_LINE, 0x2e, 4, 4, 0x2e, 0, 4),
PMIX_ENT(SOUND_MIXER_MIC, 0x0a, 0, 3, 0x00, 0, 0),
PMIX_ENT(SOUND_MIXER_CD, 0x28, 4, 4, 0x28, 0, 4),
PMIX_ENT(SOUND_MIXER_IMIX, 0x00, 0, 0, 0x00, 0, 0),
PMIX_ENT(SOUND_MIXER_ALTPCM, 0x00, 0, 0, 0x00, 0, 0),
PMIX_ENT(SOUND_MIXER_RECLEV, 0x00, 0, 0, 0x00, 0, 0),
PMIX_ENT(SOUND_MIXER_IGAIN, 0x00, 0, 0, 0x00, 0, 0),
PMIX_ENT(SOUND_MIXER_OGAIN, 0x00, 0, 0, 0x00, 0, 0)
};
#endif
mixer_tab sb16_mix = {
PMIX_ENT(SOUND_MIXER_VOLUME, 0x30, 3, 5, 0x31, 3, 5),
PMIX_ENT(SOUND_MIXER_BASS, 0x46, 4, 4, 0x47, 4, 4),
PMIX_ENT(SOUND_MIXER_TREBLE, 0x44, 4, 4, 0x45, 4, 4),
PMIX_ENT(SOUND_MIXER_SYNTH, 0x34, 3, 5, 0x35, 3, 5),
PMIX_ENT(SOUND_MIXER_PCM, 0x32, 3, 5, 0x33, 3, 5),
PMIX_ENT(SOUND_MIXER_SPEAKER, 0x3b, 6, 2, 0x00, 0, 0),
PMIX_ENT(SOUND_MIXER_LINE, 0x38, 3, 5, 0x39, 3, 5),
PMIX_ENT(SOUND_MIXER_MIC, 0x3a, 3, 5, 0x00, 0, 0),
PMIX_ENT(SOUND_MIXER_CD, 0x36, 3, 5, 0x37, 3, 5),
PMIX_ENT(SOUND_MIXER_IMIX, 0x00, 0, 0, 0x00, 0, 0),
PMIX_ENT(SOUND_MIXER_ALTPCM, 0x00, 0, 0, 0x00, 0, 0),
PMIX_ENT(SOUND_MIXER_RECLEV, 0x3f, 6, 2, 0x40, 6, 2), /* Obsol,Use IGAIN*/
PMIX_ENT(SOUND_MIXER_IGAIN, 0x3f, 6, 2, 0x40, 6, 2),
PMIX_ENT(SOUND_MIXER_OGAIN, 0x41, 6, 2, 0x42, 6, 2)
};
#ifdef SM_GAMES /* Master volume is lower and PCM & FM
* volumes higher than with SB Pro. This
* improves the sound quality */
static u_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 u_short levels[SOUND_MIXER_NRDEVICES] =
{
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 */
#if 0
static u_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_IGAIN */
0x00 /* SOUND_MIXER_OGAIN */
};
static u_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_IGAIN */
0x00 /* SOUND_MIXER_OGAIN */
};
#endif
/*
* Recording sources (SB Pro)
*/
#endif /* __SB_MIXER_C__ */
#define SRC_MIC 1 /* Select Microphone recording source */
#define SRC_CD 3 /* Select CD recording source */
#define SRC_LINE 7 /* Use Line-in for recording source */

File diff suppressed because it is too large Load Diff

View File

@ -1,528 +0,0 @@
/*
* sound.h
*
* include file for kernel sources, sound driver.
*
* 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
* 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.
*
*/
#ifdef KERNEL
#include "pcm.h"
#else
#define NPCM 1
#endif
#if NPCM > 0
/*
* first, include kernel header files.
*/
#ifndef _OS_H_
#define _OS_H_
#ifdef KERNEL
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/ioccom.h>
#include <sys/filio.h>
#include <sys/sockio.h>
#include <sys/fcntl.h>
#include <sys/tty.h>
#include <sys/proc.h>
#include <sys/kernel.h> /* for DATA_SET */
#include <sys/conf.h>
#include <sys/file.h>
#include <sys/uio.h>
#include <sys/syslog.h>
#include <sys/errno.h>
#include <sys/malloc.h>
#include <sys/buf.h>
#include <i386/isa/isa_device.h>
#include <machine/clock.h> /* for DELAY */
/*
* the following assumes that FreeBSD 3.X uses poll(2) instead of select(2).
* This change dates to late 1997.
*/
#include <sys/poll.h>
#define d_select_t d_poll_t
#else
struct isa_device { int dummy ; } ;
#define d_open_t void
#define d_close_t void
#define d_read_t void
#define d_write_t void
#define d_ioctl_t void
#define d_select_t void
#endif /* KERNEL */
typedef void (irq_proc_t) (int irq);
#endif /* _OS_H_ */
/*
* descriptor of a dma buffer. See dmabuf.c for documentation.
* (rp,rl) and (fp,fl) identify the READY and FREE regions of the
* buffer. dl contains the length used for dma transfer, dl>0 also
* means that the channel is busy and there is a DMA transfer in progress.
*/
typedef struct _snd_dbuf {
char *buf;
int bufsize ;
volatile int rp, fp; /* pointers to the ready and free area */
volatile int dl; /* transfer size */
volatile int rl, fl; /* lenght of ready and free areas. */
int int_count;
int chan; /* dma channel */
int sample_size ; /* 1, 2, 4 */
struct selinfo sel;
u_long total; /* total bytes processed */
u_long prev_total; /* copy of the above when GETxPTR called */
} snd_dbuf ;
/*
* descriptor of audio operations ...
*
*/
typedef struct _snddev_info snddev_info ;
typedef int (snd_callback_t)(snddev_info *d, int reason);
struct _snddev_info {
/*
* the first part of the descriptor is filled up from a
* template.
*/
char name[64];
int type ;
int (*probe)(struct isa_device * dev);
int (*attach)(struct isa_device * dev) ;
d_open_t *open ;
d_close_t *close ;
d_read_t *read ;
d_write_t *write ;
d_ioctl_t *ioctl ;
d_select_t *select ;
irq_proc_t *isr ;
snd_callback_t *callback;
int bufsize; /* space used for buffers */
u_long audio_fmt ; /* supported audio formats */
/*
* combinations of the following flags are used as second argument in
* the callback from the dma module to the device-specific routines.
*/
#define SND_CB_RD 0x100 /* read callback */
#define SND_CB_WR 0x200 /* write callback */
#define SND_CB_REASON_MASK 0xff
#define SND_CB_START 0x01 /* start dma op */
#define SND_CB_STOP 0x03 /* stop dma op */
#define SND_CB_ABORT 0x04 /* abort dma op */
#define SND_CB_INIT 0x05 /* init board parameters */
/*
* callback extensions
*/
#define SND_CB_DMADONE 0x10
#define SND_CB_DMAUPDATE 0x11
#define SND_CB_DMASTOP 0x12
/* init can only be called with int enabled and
* no pending DMA activity.
*/
/*
* whereas from here, parameters are set at runtime.
* io_base == 0 means that the board is not configured.
*/
int io_base ; /* primary I/O address for the board */
int alt_base ; /* some codecs are accessible as SB+MSS... */
int conf_base ; /* and the opti931 also has a config space */
int mix_base ; /* base for the mixer... */
int midi_base ; /* base for the midi */
int irq ;
int bd_id ; /* used to hold board-id info, eg. sb version,
* mss codec type, etc. etc.
*/
snd_dbuf dbuf_out, dbuf_in;
int status_ptr; /* used to implement sndstat */
/*
* these parameters describe the operation of the board.
* Generic things like busy flag, speed, etc are here.
*/
volatile u_long flags ; /* 32 bits, used for various purposes. */
/*
* we have separate flags for read and write, although in some
* cases this is probably not necessary (e.g. because we cannot
* know how many processes are using the device, we cannot
* distinguish if open, close, abort are for a write or for a
* read).
*/
/*
* the following flag is used by open-close routines
* to mark the status of the device.
*/
#define SND_F_BUSY 0x0001 /* has been opened */
/*
* Only the last close for a device will propagate to the driver.
* Unfortunately, voxware uses 3 different minor numbers
* (dsp, dsp16 and audio) to access the same unit. So, if
* we want to support multiple opens and still keep track of
* what is happening, we also need a separate flag for each minor
* number. These are below...
*/
#define SND_F_BUSY_AUDIO 0x10000000
#define SND_F_BUSY_DSP 0x20000000
#define SND_F_BUSY_DSP16 0x40000000
#define SND_F_BUSY_ANY 0x70000000
#define SND_F_BUSY_SYNTH 0x80000000
/*
* the next two are used to allow only one pending operation of
* each type.
*/
#define SND_F_READING 0x0004 /* have a pending read */
#define SND_F_WRITING 0x0008 /* have a pending write */
/*
* these mark pending DMA operations. When you have pending dma ops,
* you might get interrupts, so some manipulations of the
* descriptors must be done with interrupts blocked.
*/
#if 0
#define SND_F_RD_DMA 0x0010 /* read-dma active */
#define SND_F_WR_DMA 0x0020 /* write-dma active */
#define SND_F_PENDING_IN (SND_F_READING | SND_F_RD_DMA)
#define SND_F_PENDING_OUT (SND_F_WRITING | SND_F_WR_DMA)
#endif
#define SND_F_PENDING_IO (SND_F_READING | SND_F_WRITING)
/*
* flag used to mark a pending close.
*/
#define SND_F_CLOSING 0x0040 /* a pending close */
/*
* if user has not set block size, then make it adaptive
* (0.25s, or the perhaps last read/write ?)
*/
#define SND_F_HAS_SIZE 0x0080 /* user set block size */
/*
* assorted flags related to operating mode.
*/
#define SND_F_STEREO 0x0100 /* doing stereo */
#define SND_F_NBIO 0x0200 /* do non-blocking i/o */
/*
* the user requested ulaw, but the board does not support it
* natively, so a (software) format conversion is necessary.
* The kernel is not really the place to do this, but since
* many applications expect to use /dev/audio , we do it for
* portability.
*/
#define SND_F_XLAT8 0x0400 /* u-law <--> 8-bit unsigned */
#define SND_F_XLAT16 0x0800 /* u-law <--> 16-bit signed */
/*
* these flags mark a pending abort on a r/w operation.
*/
#define SND_F_ABORTING 0x1000 /* a pending abort */
/*
* this is used to mark that board initialization is needed, e.g.
* because of a change in sampling rate, format, etc. -- It will
* be done at the next convenient time.
*/
#define SND_F_INIT 0x4000 /* changed parameters. need init */
u_long bd_flags; /* board-specific flags */
int play_speed, rec_speed;
int play_blocksize, rec_blocksize; /* blocksize for io and dma ops */
u_long play_fmt, rec_fmt ; /* current audio format */
/*
* mixer parameters
*/
u_long mix_devs; /* existing devices for mixer */
u_long mix_rec_devs; /* possible recording sources */
u_long mix_recsrc; /* current recording source(s) */
u_short mix_levels[32];
#define wsel dbuf_out.sel
#define rsel dbuf_in.sel
u_long interrupts; /* counter of interrupts */
u_long magic;
#define MAGIC(unit) ( 0xa4d10de0 + unit )
int synth_base ; /* base for the synth */
int synth_type ; /* type of synth */
void *device_data ; /* just in case it is needed...*/
int special_dma ;
/* when this is set, dsp_wr_dmaupdate etc.
* are processed using callback extensions.
*/
} ;
/*
* then ioctls and other stuff
*/
#define NPCM_MAX 8 /* Number of supported devices */
/*
* values used in bd_id for the mss boards
*/
#define MD_AD1848 0x91
#define MD_AD1845 0x92
#define MD_AD1816 0x93
#define MD_CS4248 0xA1
#define MD_CS4231 0xA2
#define MD_CS4231A 0xA3
#define MD_CS4232 0xA4
#define MD_CS4232A 0xA5
#define MD_CS4236 0xA6
#define MD_CS4237 0xA7
#define MD_OPTI931 0xB1
#define MD_GUSPNP 0xB8
#define MD_YM0020 0xC1
#define MD_VIVO 0xD1
/*
* TODO: add some card classes rather than specific types.
*/
#include <sys/soundcard.h>
/*
* many variables should be reduced to a range. Here define a macro
*/
#define RANGE(var, low, high) (var) = \
((var)<(low)?(low) : (var)>(high)?(high) : (var))
/*
* finally, all default parameters
*/
#define DSP_BUFFSIZE (65536 - 256) /* XXX */
/*
* the last 256 bytes are room for buggy soundcard to overflow.
*/
#ifdef KERNEL
#include "pnp.h"
#if NPNP > 0
#include <i386/isa/pnp.h> /* XXX pnp support */
#endif
#endif /* KERNEL */
/*
* Minor numbers for the sound driver.
*
* Unfortunately Creative called the codec chip of SB as a DSP. For this
* reason the /dev/dsp is reserved for digitized audio use. There is a
* device for true DSP processors but it will be called something else.
* In v3.0 it's /dev/sndproc but this could be a temporary solution.
*/
#define SND_DEV_CTL 0 /* Control port /dev/mixer */
#define SND_DEV_SEQ 1 /* Sequencer output /dev/sequencer (FM
synthesizer and MIDI output) */
#define SND_DEV_MIDIN 2 /* Raw midi access */
#define SND_DEV_DSP 3 /* Digitized voice /dev/dsp */
#define SND_DEV_AUDIO 4 /* Sparc compatible /dev/audio */
#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/sequencer, level 2 interface */
#define SND_DEV_SNDPROC 9 /* /dev/sndproc for programmable devices */
#define SND_DEV_PSS SND_DEV_SNDPROC
#define DSP_DEFAULT_SPEED 8000
#define ON 1
#define OFF 0
#define SYNTH_MAX_VOICES 32
struct voice_alloc_info {
int max_voice;
int used_voices;
int ptr; /* For device specific use */
u_short map[SYNTH_MAX_VOICES]; /* (ch << 8) | (note+1) */
int timestamp;
int alloc_times[SYNTH_MAX_VOICES];
};
struct channel_info {
int pgm_num;
int bender_value;
u_char controllers[128];
};
/*
* mixer description structure and macros
*/
struct mixer_def {
u_int regno:7;
u_int polarity:1; /* 1 means reversed */
u_int bitoffs:4;
u_int nbits:4;
};
typedef struct mixer_def mixer_ent;
typedef struct mixer_def mixer_tab[32][2];
#ifdef KERNEL
#define FULL_DUPLEX(d) (d->dbuf_out.chan != d->dbuf_in.chan)
#define MIX_ENT(name, reg_l, pol_l, pos_l, len_l, reg_r, pol_r, pos_r, len_r) \
{{reg_l, pol_l, pos_l, len_l}, {reg_r, pol_r, pos_r, len_r}}
#define PMIX_ENT(name, reg_l, pos_l, len_l, reg_r, pos_r, len_r) \
{{reg_l, 0, pos_l, len_l}, {reg_r, 0, pos_r, len_r}}
#define MIX_NONE(name) MIX_ENT(name, 0,0,0,0, 0,0,0,0)
/*
* some macros for debugging purposes
* DDB/DEB to enable/disable debugging stuff
* BVDDB to enable debugging when bootverbose
*/
#define DDB(x) x /* XXX */
#define BVDDB(x) if (bootverbose) x
#ifndef DEB
#define DEB(x)
#endif
extern snddev_info pcm_info[NPCM_MAX] ;
extern snddev_info midi_info[NPCM_MAX] ;
extern snddev_info synth_info[NPCM_MAX] ;
extern u_long nsnd ;
extern snddev_info *snddev_last_probed;
int pcmprobe(struct isa_device * dev);
int midiprobe(struct isa_device * dev);
int synthprobe(struct isa_device * dev);
int pcmattach(struct isa_device * dev);
int pcminit(snddev_info *d, int unit);
int midiattach(struct isa_device * dev);
int synthattach(struct isa_device * dev);
ointhand2_t pcmintr;
/*
* DMA buffer calls
*/
void dsp_wrintr(snddev_info *d);
void dsp_rdintr(snddev_info *d);
int dsp_write_body(snddev_info *d, struct uio *buf);
int dsp_read_body(snddev_info *d, struct uio *buf);
void alloc_dbuf(snd_dbuf *d, int size);
int snd_flush(snddev_info *d);
/* the following parameters are used in snd_sync and reset_dbuf
* to decide whether or not to restart a channel
*/
#define SND_CHAN_NONE 0x0
#define SND_CHAN_WR 0x1
#define SND_CHAN_RD 0x2
void reset_dbuf(snd_dbuf *b, int chan);
int snd_sync(snddev_info *d, int chan, int threshold);
int dsp_wrabort(snddev_info *d, int restart);
int dsp_rdabort(snddev_info *d, int restart);
void dsp_wr_dmaupdate(snd_dbuf *b);
void dsp_rd_dmaupdate(snd_dbuf *b);
d_select_t sndselect;
/*
* library functions (in sound.c)
*/
int ask_init(snddev_info *d);
void translate_bytes(u_char *table, u_char *buff, int n);
void change_bits(mixer_tab *t, u_char *regval, int dev, int chn, int newval);
int snd_conflict(int io_base);
void snd_set_blocksize(snddev_info *d);
int isa_dmastatus1(int channel);
/*
* routines in ad1848.c and sb_dsp.c which others might use
*/
int mss_detect (struct isa_device *dev);
int sb_cmd (int io_base, u_char cmd);
int sb_cmd2 (int io_base, u_char cmd, int val);
int sb_cmd3 (int io_base, u_char cmd, int val);
int sb_reset_dsp (int io_base);
void sb_setmixer (int io_base, u_int port, u_int value);
int sb_getmixer (int io_base, u_int port);
#endif /* KERNEL */
/*
* usage of flags in device config entry (config file)
*/
#define DV_F_DRQ_MASK 0x00000007 /* mask for secondary drq */
#define DV_F_DUAL_DMA 0x00000010 /* set to use secondary dma channel */
#define DV_F_DEV_MASK 0x0000ff00 /* force device type/class */
#define DV_F_DEV_SHIFT 8 /* force device type/class */
/*
* some flags are used in a device-specific manner, so that values can
* be used multiple times.
*/
#define DV_F_TRUE_MSS 0x00010000 /* mss _with_ base regs */
/* almost all modern cards do not have this set of registers,
* so it is better to make this the default behaviour
*/
/*
* the following flags are for PnP cards only and are undocumented
*/
#define DV_PNP_SBCODEC 0x1
#endif

View File

@ -1,74 +0,0 @@
/*
* on entry: ulaw, on exit: unsigned 8 bit.
*/
static unsigned char ulaw_dsp[] = {
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[] = {
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 */