summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>1999-09-26 22:20:29 +0000
committerpeter <peter@FreeBSD.org>1999-09-26 22:20:29 +0000
commit303f4da1978732f509bb89dbe59126148f145948 (patch)
treecaf56889ffbda652becf1b0638374f2215613cb2
parentcc8f297f6d23489f5232ad0ad8ea8c4f2a650153 (diff)
downloadFreeBSD-src-303f4da1978732f509bb89dbe59126148f145948.zip
FreeBSD-src-303f4da1978732f509bb89dbe59126148f145948.tar.gz
Bid a fond farewell to these files, they live on various forms in
dev/pcm/* and dev/pcm/isa/*
-rw-r--r--sys/i386/isa/snd/CARDS359
-rw-r--r--sys/i386/isa/snd/README224
-rw-r--r--sys/i386/isa/snd/ad1848.c2339
-rw-r--r--sys/i386/isa/snd/clones.c262
-rw-r--r--sys/i386/isa/snd/dmabuf.c810
-rw-r--r--sys/i386/isa/snd/mss.h304
-rw-r--r--sys/i386/isa/snd/sb_dsp.c1366
-rw-r--r--sys/i386/isa/snd/sbcard.h405
-rw-r--r--sys/i386/isa/snd/sound.c1496
-rw-r--r--sys/i386/isa/snd/sound.h528
-rw-r--r--sys/i386/isa/snd/ulaw.h74
11 files changed, 0 insertions, 8167 deletions
diff --git a/sys/i386/isa/snd/CARDS b/sys/i386/isa/snd/CARDS
deleted file mode 100644
index c8f2815..0000000
--- a/sys/i386/isa/snd/CARDS
+++ /dev/null
@@ -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.
-
-
---------------------------------------------------------------------
diff --git a/sys/i386/isa/snd/README b/sys/i386/isa/snd/README
deleted file mode 100644
index e45bde7..0000000
--- a/sys/i386/isa/snd/README
+++ /dev/null
@@ -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.
diff --git a/sys/i386/isa/snd/ad1848.c b/sys/i386/isa/snd/ad1848.c
deleted file mode 100644
index 9d0a0cf..0000000
--- a/sys/i386/isa/snd/ad1848.c
+++ /dev/null
@@ -1,2339 +0,0 @@
-/*
- * sound/ad1848.c
- *
- * Driver for Microsoft Sound System/Windows Sound System (mss)
- * -compatible boards. This includes:
- *
- * AD1848, CS4248, CS423x, OPTi931, Yamaha OPL/SAx and many others.
- *
- * Copyright Luigi Rizzo, 1997,1998
- * 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
- * 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.
- *
- * Full data sheets in PDF format for the MSS-compatible chips
- * are available at
- *
- * http://www.crystal.com/ for the CS42XX series, or
- * http://www.opti.com/ for the OPTi931
- */
-
-#include <i386/isa/snd/sound.h>
-#if NPCM > 0
-
-/*
- * board-specific include files
- */
-
-#include <i386/isa/snd/mss.h>
-
-/*
- * prototypes for procedures exported in the device descriptor
- */
-
-static int mss_probe(struct isa_device *dev);
-static int mss_attach(struct isa_device *dev);
-
-d_open_t mss_open; /* this is a generic full-duplex open routine */
-static d_close_t mss_close;
-static d_ioctl_t mss_ioctl;
-static irq_proc_t mss_intr;
-static irq_proc_t opti931_intr;
-static snd_callback_t mss_callback;
-
-/*
- * prototypes for local functions
- */
-
-static void mss_reinit(snddev_info *d);
-static int AD_WAIT_INIT(snddev_info *d, int x);
-static int mss_mixer_set(snddev_info *d, int dev, int value);
-static int mss_set_recsrc(snddev_info *d, int mask);
-static void ad1848_mixer_reset(snddev_info *d);
-
-static void opti_write(int io_base, u_char reg, u_char data);
-static u_char opti_read(int io_base, u_char reg);
-static void ad_write(snddev_info *d, int reg, u_char data);
-static void ad_write_cnt(snddev_info *d, int reg, u_short data);
-static int ad_read(snddev_info *d, int reg);
-
-#if NPNP > 0 /* the ad1816 is pnp only */
-/* ad1816 prototypes */
-
-/* IO primitives */
-static int ad1816_wait_init(snddev_info * d, int x);
-static u_short ad1816_read(snddev_info * d, u_int reg);
-static void ad1816_write(snddev_info * d, u_int reg, u_short data);
-/* intr and callback functions */
-static irq_proc_t ad1816_intr;
-static snd_callback_t ad1816_callback;
-/* device specific ioctl calls */
-static d_ioctl_t ad1816_ioctl;
-/* parameter set functions */
-static void ad1816_reinit(snddev_info * d);
-static int ad1816_mixer_set(snddev_info * d, int dev, int value);
-static int ad1816_set_recsrc(snddev_info * d, int mask);
-static void ad1816_mixer_reset(snddev_info * d);
-
-/* ad1816 prototypes end */
-#endif
-
-/*
- * device descriptors for the boards supported by this module.
- */
-snddev_info mss_op_desc = {
- "mss",
-
- SNDCARD_MSS,
- mss_probe,
- mss_attach,
-
- mss_open,
- mss_close,
- NULL /* mss_read */,
- NULL /* mss_write */,
- mss_ioctl,
- sndselect /* mss_select */,
-
- mss_intr,
- mss_callback ,
-
- DSP_BUFFSIZE, /* bufsize */
-
- AFMT_STEREO |
- AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW, /* audio formats */
- /*
- * the enhanced boards also have AFMT_IMA_ADPCM | AFMT_S16_BE
- * but we do not use these modes.
- */
-} ;
-
-/*
- * mss_probe() 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.
- *
- * The base address supplied in the device refers to the old MSS
- * specs where the four 4 registers in io space contain configuration
- * information. Some boards (as an example, early MSS boards)
- * has such a block of registers, whereas others (generally CS42xx)
- * do not. In order to distinguish between the two and do not have
- * to supply two separate probe routines, the flags entry in isa_device
- * has a bit to mark this.
- *
- */
-
-static int
-mss_probe(struct isa_device *dev)
-{
- u_char tmp;
- int irq = ffs(dev->id_irq) - 1;
-
- bzero(&pcm_info[dev->id_unit], sizeof(pcm_info[dev->id_unit]) );
- if (dev->id_iobase == -1) {
- dev->id_iobase = 0x530;
- BVDDB(printf("mss_probe: no address supplied, try default 0x%x\n",
- dev->id_iobase));
- }
- if (snd_conflict(dev->id_iobase))
- return 0 ;
-
- if ( !(dev->id_flags & DV_F_TRUE_MSS) ) /* Has no IRQ/DMA registers */
- goto mss_probe_end;
-
- /*
- * 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.
- */
-
- tmp = inb(dev->id_iobase + 3);
- if (tmp == 0xff) { /* Bus float */
- BVDDB(printf("I/O address inactive (%x), try pseudo_mss\n", tmp));
- dev->id_flags &= ~DV_F_TRUE_MSS ;
- goto mss_probe_end;
- }
- tmp &= 0x3f ;
- if (tmp != 0x04 && tmp != 0x0f && tmp != 0x00) {
- BVDDB(printf("No MSS signature detected on port 0x%x (0x%x)\n",
- dev->id_iobase, inb(dev->id_iobase + 3)));
- return 0;
- }
- if (irq > 11) {
- printf("MSS: Bad IRQ %d\n", irq);
- return 0;
- }
- if (dev->id_drq != 0 && dev->id_drq != 1 && dev->id_drq != 3) {
- printf("MSS: Bad DMA %d\n", dev->id_drq);
- return 0;
- }
- if (inb(dev->id_iobase + 3) & 0x80) {
- /* 8-bit board: only drq1/3 and irq7/9 */
- if (dev->id_drq == 0) {
- printf("MSS: Can't use DMA0 with a 8 bit card/slot\n");
- return 0;
- }
- if (irq != 7 && irq != 9) {
- printf("MSS: Can't use IRQ%d with a 8 bit card/slot\n", irq);
- return 0;
- }
- }
-mss_probe_end:
- return mss_detect(dev) ? 8 : 0 ; /* mss uses 8 regs */
-}
-
-#if NPNP > 0
-static int
-ad1816_attach(struct isa_device *dev)
-{
- snddev_info *d = &(pcm_info[dev->id_unit]);
-
- dev->id_alive = 16; /* number of io ports */
-
- if (FULL_DUPLEX(d))
- d->audio_fmt |= AFMT_FULLDUPLEX;
-
- ad1816_write(d, 1, 0x2);/* disable interrupts */
- ad1816_write(d, 32, 0x90F0); /* SoundSystem Mode, split format */
-
- ad1816_write(d, 5, 0x8080); /* FM volume mute */
- ad1816_write(d, 6, 0x8080); /* I2S1 volume mute */
- ad1816_write(d, 7, 0x8080); /* I2S0 volume mute */
- ad1816_write(d, 17, 0x8888); /* VID Volume mute */
- ad1816_write(d, 20, 0x5050); /* Source select Mic & auto gain ctrl
- * off */
- /* adc gain is set to 0 */
- ad1816_reinit(d);
- ad1816_mixer_reset(d);
- return 0 ;
-}
-#endif /* NPNP */
-
-/*
- * the address passed as io_base for mss_attach is also the old
- * MSS base address (e.g. 0x530). The codec is four locations ahead.
- * Note that the attach routine for PnP devices might support
- * device-specific initializations.
- */
-
-static int
-mss_attach(struct isa_device *dev)
-{
- snddev_info *d = &(pcm_info[dev->id_unit]);
-
- printf("mss_attach <%s>%d at 0x%x irq %d dma %d:%d flags 0x%x\n",
- d->name, dev->id_unit,
- d->io_base, d->irq, d->dbuf_out.chan, d->dbuf_in.chan, dev->id_flags);
-
-#if NPNP > 0
- if (d->bd_id == MD_AD1816)
- return ad1816_attach(dev);
-#endif
- dev->id_alive = 8 ; /* number of io ports */
- /* should be already set but just in case... */
-
- if ( dev->id_flags & DV_F_TRUE_MSS ) {
- /* has IRQ/DMA registers, set IRQ and DMA addr */
- static char interrupt_bits[12] = {
- -1, -1, -1, -1, -1, 0x28, -1, 0x08, -1, 0x10, 0x18, 0x20
- };
- static char dma_bits[4] = { 1, 2, 0, 3 };
- char bits ;
-
- if (d->irq == -1 || (bits = interrupt_bits[d->irq]) == -1) {
- dev->id_irq = 0 ; /* makk invalid irq */
- return 0 ;
- }
-
- outb(dev->id_iobase, bits | 0x40); /* config port */
- if ((inb(dev->id_iobase + 3) & 0x40) == 0) /* version port */
- printf("[IRQ Conflict?]");
-
- /* Write IRQ+DMA setup */
- if ( ! FULL_DUPLEX(d) ) /* single chan dma */
- outb(dev->id_iobase, bits | dma_bits[d->dbuf_out.chan]);
- else {
- if (d->dbuf_out.chan == 0 && d->dbuf_in.chan == 1)
- bits |= 5 ;
- else if (d->dbuf_out.chan == 1 && d->dbuf_in.chan == 0)
- bits |= 6 ;
- else if (d->dbuf_out.chan == 3 && d->dbuf_in.chan == 0)
- bits |= 7 ;
- else {
- printf("invalid dual dma config %d:%d\n",
- d->dbuf_out.chan, d->dbuf_in.chan);
- dev->id_irq = 0 ;
- dev->id_alive = 0 ; /* this makes attach fail. */
- return 0 ;
- }
- outb(dev->id_iobase, bits );
- }
- }
- if (1) { /* machine-specific code for the Toshiba Libretto */
- u_char r6, r9;
- outb( 0x370, 6 /* dma config */ );
- outb( 0x371, 0xa9 /* config: DMA-B for rec, DMA-A for play */);
- r6 = inb( 0x371 /* read */ );
- outb( 0x370, 0xa /* version */ );
- r9 = inb( 0x371 /* read */ );
- DEB(printf("Yamaha: ver 0x%x DMA config 0x%x\n", r6, r9);)
- /*
- * yamaha - set volume to max
- */
- outb( 0x370, 7 /* volume left */ );
- outb( 0x371, 0 /* max level */ );
- outb( 0x370, 8 /* volume right */ );
- outb( 0x371, 0 /* max level */ );
- }
- if ( FULL_DUPLEX(d) )
- d->audio_fmt |= AFMT_FULLDUPLEX ;
- if (d->bd_id == MD_YM0020) {
- DDB(printf("setting up yamaha registers\n"));
- outb(0x370, 6 /* dma config */ ) ;
- if (FULL_DUPLEX(d))
- outb(0x371, 0xa9 ); /* use both dma chans */
- else
- outb(0x371, 0x8b ); /* use low dma chan */
- }
- mss_reinit(d);
- ad1848_mixer_reset(d);
- return 0;
-}
-
-int
-mss_open(dev_t i_dev, int flags, int mode, struct proc * p)
-{
- int unit;
- int dev;
- snddev_info *d;
- u_long s;
-
- dev = minor(i_dev);
- unit = dev >> 4 ;
- dev &= 0xf ;
- d = &pcm_info[unit] ;
-
- s = spltty();
- /*
- * This was meant to support up to 2 open descriptors for the
- * some device, and check proper device usage on open.
- * Unfortunately, the kernel will trap all close() calls but
- * the last one, with the consequence that we cannot really
- * keep track of which channels are busy.
- * So, the correct tests cannot be done :( and we must rely
- * on the locks on concurrent operations of the same type and
- * on some approximate tests...
- */
-
- if (dev == SND_DEV_AUDIO)
- d->flags |= SND_F_BUSY_AUDIO ;
- else if (dev == SND_DEV_DSP)
- d->flags |= SND_F_BUSY_DSP ;
- else if (dev == SND_DEV_DSP16)
- d->flags |= SND_F_BUSY_DSP16 ;
- if ( d->flags & SND_F_BUSY )
- splx(s); /* device was already set, no need to reinit */
- else {
- /*
- * device was idle. Do the necessary initialization,
- * but no need keep interrupts blocked.
- * will not get them
- */
-
- splx(s);
- d->play_speed = d->rec_speed = DSP_DEFAULT_SPEED ;
- d->flags |= SND_F_BUSY ;
-
- d->wsel.si_pid = 0;
- d->wsel.si_flags = 0;
-
- d->rsel.si_pid = 0;
- d->rsel.si_flags = 0;
-
- d->dbuf_out.total = d->dbuf_out.prev_total = 0 ;
- d->dbuf_in.total = d->dbuf_in.prev_total = 0 ;
-
- if (flags & O_NONBLOCK)
- d->flags |= SND_F_NBIO ;
-
- switch (dev) {
- default :
- case SND_DEV_AUDIO :
- d->play_fmt = d->rec_fmt = AFMT_MU_LAW ;
- break ;
- case SND_DEV_DSP :
- d->play_fmt = d->rec_fmt = AFMT_U8 ;
- break ;
- case SND_DEV_DSP16 :
- d->play_fmt = d->rec_fmt = AFMT_S16_LE ;
- break;
- }
- ask_init(d); /* and reset buffers... */
- }
- return 0 ;
-}
-
-static int
-mss_close(dev_t i_dev, int flags, int mode, struct proc * p)
-{
- int unit;
- int dev;
- snddev_info *d;
- u_long s;
-
- dev = minor(i_dev);
- unit = dev >> 4 ;
- dev &= 0xf;
- d = &pcm_info[unit] ;
-
- /*
- * We will only get a single close call when the last reference
- * to the device is gone. But we must handle ourselves references
- * through different devices.
- */
-
- s = spltty();
-
- if (dev == SND_DEV_AUDIO)
- d->flags &= ~SND_F_BUSY_AUDIO ;
- else if (dev == SND_DEV_DSP)
- d->flags &= ~SND_F_BUSY_DSP ;
- else if (dev == SND_DEV_DSP16)
- d->flags &= ~SND_F_BUSY_DSP16 ;
- if ( d->flags & SND_F_BUSY_ANY ) /* still some device open */
- splx(s);
- else { /* last one */
- d->flags |= SND_F_CLOSING ;
- splx(s); /* is this ok here ? */
- snd_flush(d);
- /* Clear interrupt status */
- if ( d->bd_id == MD_AD1816 )
- outb(ad1816_int(d), 0);
- else
- outb(io_Status(d), 0);
- d->flags = 0 ;
- }
- return 0 ;
-}
-
-static int
-mss_ioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct proc * p)
-{
- snddev_info *d;
- int unit;
- int dev;
-
- dev = minor(i_dev);
- unit = dev >> 4 ;
- d = &pcm_info[unit] ;
- /*
- * handle mixer calls first. Reads are in the default handler,
- * so do not bother about them.
- */
- if ( (cmd & MIXER_WRITE(0)) == MIXER_WRITE(0) ) {
- cmd &= 0xff ;
- if (cmd == SOUND_MIXER_RECSRC)
- return mss_set_recsrc(d, *(int *)arg) ;
- else
- return mss_mixer_set(d, cmd, *(int *)arg) ;
- }
-
- return ENOSYS ; /* fallback to the default ioctl handler */
-}
-
-
-/*
- * the callback routine to handle all dma ops etc.
- * With the exception of INIT, all other callbacks are invoked
- * with interrupts disabled.
- */
-
-static int
-mss_callback(snddev_info *d, int reason)
-{
- u_char m;
- int retry, wr, cnt;
-
- DEB(printf("-- mss_callback reason 0x%03x\n", reason));
- wr = reason & SND_CB_WR ;
- reason &= SND_CB_REASON_MASK ;
- switch (reason) {
- case SND_CB_INIT : /* called with int enabled and no pending I/O */
- /*
- * perform all necessary initializations for i/o
- */
- d->rec_fmt = d->play_fmt ; /* no split format on the MSS */
- snd_set_blocksize(d);
- mss_reinit(d);
- reset_dbuf(& (d->dbuf_in), SND_CHAN_RD );
- reset_dbuf(& (d->dbuf_out), SND_CHAN_WR );
- return 1 ;
- break ;
-
- case SND_CB_START :
- cnt = wr ? d->dbuf_out.dl : d->dbuf_in.dl ;
- if (d->play_fmt == AFMT_S16_LE)
- cnt /= 2;
- if (d->flags & SND_F_STEREO)
- cnt /= 2;
- cnt-- ;
-
- DEB(printf("-- (re)start cnt %d\n", cnt));
- m = ad_read(d,9) ;
- DEB( if (m & 4) printf("OUCH! reg 9 0x%02x\n", m); );
- m |= wr ? I9_PEN : I9_CEN ; /* enable DMA */
- /*
- * on the OPTi931 the enable bit seems hard to set...
- */
- for (retry = 10; retry; retry--) {
- ad_write(d, 9, m );
- if (ad_read(d,9) ==m) break;
- }
- if (retry == 0)
- printf("start dma, failed to set bit 0x%02x 0x%02x\n",
- m, ad_read(d, 9) ) ;
- if (wr || ! FULL_DUPLEX(d) )
- ad_write_cnt(d, 14, cnt);
- else
- ad_write_cnt(d, 30, cnt);
-
- break ;
-
- case SND_CB_STOP :
- case SND_CB_ABORT : /* XXX check this... */
- m = ad_read(d,9) ;
- m &= wr ? ~I9_PEN : ~I9_CEN ; /* Stop DMA */
- /*
- * on the OPTi931 the enable bit seems hard to set...
- */
- for (retry = 10; retry ; retry-- ) {
- ad_write(d, 9, m );
- if (ad_read(d,9) ==m) break;
- }
- if (retry == 0)
- printf("start dma, failed to clear bit 0x%02x 0x%02x\n",
- m, ad_read(d, 9) ) ;
-#if 1
- /*
- * try to disable DMA by clearing count registers. Not sure it
- * is needed, and it might cause false interrupts when the
- * DMA is re-enabled later.
- */
- if (wr || ! FULL_DUPLEX(d) )
- ad_write_cnt(d, 14, 0);
- else
- ad_write_cnt(d, 30, 0);
- break;
-#endif
- }
- return 0 ;
-}
-
-/*
- * main irq handler for the CS423x. The OPTi931 code is
- * a separate one.
- * The correct way to operate for a device with multiple internal
- * interrupt sources is to loop on the status register and ack
- * interrupts until all interrupts are served and none are reported. At
- * this point the IRQ line to the ISA IRQ controller should go low
- * and be raised at the next interrupt.
- *
- * Since the ISA IRQ controller is sent EOI _before_ passing control
- * to the isr, it might happen that we serve an interrupt early, in
- * which case the status register at the next interrupt should just
- * say that there are no more interrupts...
- */
-
-static void
-mss_intr(int unit)
-{
- snddev_info *d = &pcm_info[unit];
- u_char c, served = 0;
- int i;
-
- DEB(printf("mss_intr\n"));
- ad_read(d, 11); /* fake read of status bits */
-
- /*
- * loop until there are interrupts, but no more than 10 times.
- */
- for (i=10 ; i && inb(io_Status(d)) & 1 ; i-- ) {
- /* get exact reason for full-duplex boards */
- c = FULL_DUPLEX(d) ? ad_read(d, 24) : 0x30 ;
- c &= ~served ;
- if ( d->dbuf_out.dl && (c & 0x10) ) {
- served |= 0x10 ;
- dsp_wrintr(d);
- }
- if ( d->dbuf_in.dl && (c & 0x20) ) {
- served |= 0x20 ;
- dsp_rdintr(d);
- }
- /*
- * now ack the interrupt
- */
- if ( FULL_DUPLEX(d) )
- ad_write(d, 24, ~c); /* ack selectively */
- else
- outb(io_Status(d), 0); /* Clear interrupt status */
- }
- if (served == 0) {
- printf("How strange... mss_intr with no reason!\n");
- /*
- * this should not happen... I have no idea what to do now.
- * maybe should do a sanity check and restart dmas ?
- */
- outb(io_Status(d), 0); /* Clear interrupt status */
- }
-}
-
-/*
- * the opti931 seems to miss interrupts when working in full
- * duplex, so we try some heuristics to catch them.
- */
-static void
-opti931_intr(int unit)
-{
- snddev_info *d = &pcm_info[unit];
- u_char masked=0, i11, mc11, c=0;
- u_char reason; /* b0 = playback, b1 = capture, b2 = timer */
- int loops = 10;
-
-#if 0
- reason = inb(io_Status(d));
- if ( ! (reason & 1) ) {/* no int, maybe a shared line ? */
- printf("opti931_intr: flag 0, mcir11 0x%02x\n", ad_read(d,11));
- return;
- }
-#endif
- i11 = ad_read(d, 11); /* XXX what's for ? */
-again:
-
- c=mc11 = FULL_DUPLEX(d) ? opti_read(d->conf_base, 11) : 0xc ;
- mc11 &= 0x0c ;
- if (c & 0x10) {
- DEB(printf("Warning: CD interrupt\n");)
- mc11 |= 0x10 ;
- }
- if (c & 0x20) {
- DEB(printf("Warning: MPU interrupt\n");)
- mc11 |= 0x20 ;
- }
- if (mc11 & masked)
- printf("irq reset failed, mc11 0x%02x, masked 0x%02x\n", mc11, masked);
- masked |= mc11 ;
- /*
- * the nice OPTi931 sets the IRQ line before setting the bits in
- * mc11. So, on some occasions I have to retry (max 10 times).
- */
- if ( mc11 == 0 ) { /* perhaps can return ... */
- reason = inb(io_Status(d));
- if (reason & 1) {
- DEB(printf("one more try...\n");)
- if (--loops)
- goto again;
- else
- DDB(printf("opti_intr: irq but mc11 not set!...\n");)
- }
- if (loops==10)
- printf("ouch, intr but nothing in mcir11 0x%02x\n", mc11);
- return;
- }
-
- if ( d->dbuf_in.dl && (mc11 & 8) ) {
- dsp_rdintr(d);
- }
- if ( d->dbuf_out.dl && (mc11 & 4) ) {
- dsp_wrintr(d);
- }
- opti_write(d->conf_base, 11, ~mc11); /* ack */
- if (--loops)
- goto again;
- DEB(printf("xxx too many loops\n");)
-}
-
-/*
- * Second part of the file: functions local to this module.
- * in this section a few routines to access MSS registers
- *
- */
-
-static void
-opti_write(int io_base, u_char reg, u_char value)
-{
- outb(io_base, reg);
- outb(io_base+1, value);
-}
-
-static u_char
-opti_read(int io_base, u_char reg)
-{
- outb(io_base, reg);
- return inb(io_base+1);
-}
-
-static void
-gus_write(int io_base, u_char reg, u_char value)
-{
- outb(io_base + 3, reg);
- outb(io_base + 5, value);
-}
-
-#if 0
-static void
-gus_writew(int io_base, u_char reg, u_short value)
-{
- outb(io_base + 3, reg);
- outb(io_base + 4, value);
-}
-#endif
-
-static u_char
-gus_read(int io_base, u_char reg)
-{
- outb(io_base+3, reg);
- return inb(io_base+5);
-}
-
-#if 0
-static u_short
-gus_readw(int io_base, u_char reg)
-{
- outb(io_base+3, reg);
- return inw(io_base+4);
-}
-#endif
-
-/*
- * AD_WAIT_INIT waits if we are initializing the board and
- * we cannot modify its settings
- */
-static int
-AD_WAIT_INIT(snddev_info *d, int x)
-{
- int arg=x, n = 0; /* to shut up the compiler... */
- for (; x-- ; )
- if ( (n=inb(io_Index_Addr(d))) & IA_BUSY)
- DELAY(10);
- else
- return n ;
- printf("AD_WAIT_INIT FAILED %d 0x%02x\n", arg, n);
- return n ;
-}
-
-static int
-ad_read(snddev_info *d, int reg)
-{
- u_long flags;
- int x;
-
- flags = spltty();
- AD_WAIT_INIT(d, 201);
- x = inb(io_Index_Addr(d)) & ~IA_AMASK ;
- outb(io_Index_Addr(d), (u_char) (reg & IA_AMASK) | x ) ;
- x = inb(io_Indexed_Data(d));
- splx(flags);
- return x;
-}
-
-static void
-ad_write(snddev_info *d, int reg, u_char data)
-{
- u_long flags;
-
- int x ;
- flags = spltty();
- AD_WAIT_INIT(d, 1002);
- x = inb(io_Index_Addr(d)) & ~IA_AMASK ;
- outb(io_Index_Addr(d), (u_char) (reg & IA_AMASK) | x ) ;
- outb(io_Indexed_Data(d), data);
- splx(flags);
-}
-
-static void
-ad_write_cnt(snddev_info *d, int reg, u_short cnt)
-{
- ad_write(d, reg+1, cnt & 0xff );
- ad_write(d, reg, cnt >> 8 ); /* upper base must be last */
-}
-
-static void
-wait_for_calibration(snddev_info *d)
-{
- int n, t;
-
- /*
- * 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
- * 3) Wait until the ACI bit of I11 gets off
- */
-
- n = AD_WAIT_INIT(d, 1000);
- if (n & IA_BUSY)
- printf("mss: Auto calibration timed out(1).\n");
-
- for (t = 100 ; t>0 && (ad_read(d, 11) & 0x20) == 0 ; t--)
- DELAY(100);
- for (t = 100 ; t>0 && ad_read(d, 11) & 0x20 ; t--)
- DELAY(100);
-}
-
-#if 0 /* unused right now... */
-static void
-ad_mute(snddev_info *d)
-{
- ad_write(d, 6, ad_read(d,6) | I6_MUTE);
- ad_write(d, 7, ad_read(d,7) | I6_MUTE);
-}
-
-static void
-ad_unmute(snddev_info *d)
-{
- ad_write(d, 6, ad_read(d,6) & ~I6_MUTE);
- ad_write(d, 7, ad_read(d,7) & ~I6_MUTE);
-}
-#endif
-
-static void
-ad_enter_MCE(snddev_info *d)
-{
- int prev;
-
- d->bd_flags |= BD_F_MCE_BIT;
- AD_WAIT_INIT(d, 203);
- prev = inb(io_Index_Addr(d));
- prev &= ~IA_TRD ;
- outb(io_Index_Addr(d), prev | IA_MCE ) ;
-}
-
-static void
-ad_leave_MCE(snddev_info *d)
-{
- u_long flags;
- u_char prev;
-
- if ( (d->bd_flags & BD_F_MCE_BIT) == 0 ) {
- printf("--- hey, leave_MCE: MCE bit was not set!\n");
- return;
- }
-
- AD_WAIT_INIT(d, 1000);
-
- flags = spltty();
- d->bd_flags &= ~BD_F_MCE_BIT;
-
- prev = inb(io_Index_Addr(d));
- prev &= ~IA_TRD ;
- outb(io_Index_Addr(d), prev & ~IA_MCE ); /* Clear the MCE bit */
- wait_for_calibration(d);
- splx(flags);
-}
-
-/*
- * only one source can be set...
- */
-static int
-mss_set_recsrc(snddev_info *d, int mask)
-{
- u_char recdev;
-
- mask &= d->mix_rec_devs;
- switch (mask) {
- case SOUND_MASK_LINE:
- case SOUND_MASK_LINE3:
- recdev = 0;
- break;
-
- case SOUND_MASK_CD:
- case SOUND_MASK_LINE1:
- recdev = 0x40;
- break;
-
- case SOUND_MASK_IMIX:
- recdev = 0xc0;
- break;
-
- case SOUND_MASK_MIC:
- default:
- mask = SOUND_MASK_MIC;
- recdev = 0x80;
- }
-
- ad_write(d, 0, (ad_read(d, 0) & 0x3f) | recdev);
- ad_write(d, 1, (ad_read(d, 1) & 0x3f) | recdev);
-
- d->mix_recsrc = mask;
- return 0;
-}
-
-/*
- * there are differences in the mixer depending on the actual sound
- * card.
- */
-static int
-mss_mixer_set(snddev_info *d, int dev, int value)
-{
- int left = value & 0x000000ff;
- int right = (value & 0x0000ff00) >> 8;
-
- int regoffs;
- mixer_tab *mix_d = &mix_devices;
-
- u_char old, val;
-
- if (dev > 31)
- return EINVAL;
-
- if (!(d->mix_devs & (1 << dev)))
- return EINVAL;
-
- if (d->bd_id == MD_OPTI931)
- mix_d = &(opti931_devices);
-
- if ((*mix_d)[dev][LEFT_CHN].nbits == 0) {
- DEB(printf("nbits = 0 for dev %d\n", dev) );
- return EINVAL;
- }
-
- if (left > 100)
- left = 100;
- if (right > 100)
- right = 100;
-
-
- if ( (*mix_d)[dev][RIGHT_CHN].nbits == 0) /* Mono control */
- right = left;
-
- d->mix_levels[dev] = left | (right << 8);
-
-#if 0
- /* Scale volumes */
- left = mix_cvt[left];
- right = mix_cvt[right];
-#endif
- /*
- * Set the left channel
- */
-
- regoffs = (*mix_d)[dev][LEFT_CHN].regno;
- old = val = ad_read(d, regoffs);
- /*
- * if volume is 0, mute chan. Otherwise, unmute.
- */
- if (regoffs != 0) /* main input is different */
- val = (left == 0 ) ? old | 0x80 : old & 0x7f ;
-
- change_bits(mix_d, &val, dev, LEFT_CHN, left);
- ad_write(d, regoffs, val);
- DEB(printf("LEFT: dev %d reg %d old 0x%02x new 0x%02x\n",
- dev, regoffs, old, val));
-
- if ((*mix_d)[dev][RIGHT_CHN].nbits != 0) { /* have stereo */
- /*
- * Set the right channel
- */
- regoffs = (*mix_d)[dev][RIGHT_CHN].regno;
- old = val = ad_read(d, regoffs);
- if (regoffs != 1)
- val = (right == 0 ) ? old | 0x80 : old & 0x7f ;
- change_bits(mix_d, &val, dev, RIGHT_CHN, right);
- ad_write(d, regoffs, val);
- DEB(printf("RIGHT: dev %d reg %d old 0x%02x new 0x%02x\n",
- dev, regoffs, old, val));
- }
- return 0; /* success */
-}
-
-static void
-ad1848_mixer_reset(snddev_info *d)
-{
- int i;
-
- if (d->bd_id == MD_OPTI931)
- d->mix_devs = OPTI931_MIXER_DEVICES;
- else if (d->bd_id != MD_AD1848)
- d->mix_devs = MODE2_MIXER_DEVICES;
- else
- d->mix_devs = MODE1_MIXER_DEVICES;
-
- d->mix_rec_devs = MSS_REC_DEVICES;
-
- for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
- if (d->mix_devs & (1 << i))
- mss_mixer_set(d, i, default_mixer_levels[i]);
- mss_set_recsrc(d, SOUND_MASK_MIC);
- /*
- * some device-specific things, mostly mute the mic to
- * the output mixer so as to avoid hisses. In many cases this
- * is the default after reset, this code is here mostly as a
- * reminder that this might be necessary on other boards.
- */
- switch(d->bd_id) {
- case MD_OPTI931:
- ad_write(d, 20, 0x88);
- ad_write(d, 21, 0x88);
- break;
-
- case MD_YM0020:
- /* set master volume to max */
- DDB(printf("set yamaha master volume to max\n"); )
- outb(0x370, 7) ;
- outb(0x371, 0) ;
- outb(0x370, 8) ;
- outb(0x371, 0) ;
- break;
-
- case MD_GUSPNP:
- /* this is only necessary in mode 3 ... */
- ad_write(d, 22, 0x88);
- ad_write(d, 23, 0x88);
- }
-}
-
-/*
- * mss_speed processes the value in play_speed finding the
- * matching one. As a side effect, it returns the value to
- * be written in the speed bits of the codec. It does _NOT_
- * set the speed of the device (but it should!)
- */
-
-static int
-mss_speed(snddev_info *d)
-{
- /*
- * In the CS4231, the low 4 bits of I8 are used to hold the
- * sample rate. Only a fixed number of values is allowed. This
- * table lists them. The speed-setting routines scans the table
- * looking for the closest match. This is the only supported method.
- *
- * In the CS4236, there is an alternate metod (which we do not
- * support yet) which provides almost arbitrary frequency setting.
- * In the AD1845, it looks like the sample rate can be
- * almost arbitrary, and written directly to a register.
- * In the OPTi931, there is a SB command which provides for
- * almost arbitrary frequency setting.
- *
- */
- static int speeds[] = {
- 8000, 5512, 16000, 11025, 27429, 18900, 32000, 22050,
- -1, 37800, -1, 44100, 48000, 33075, 9600, 6615
- };
-
- int arg, i, sel = 0; /* assume entry 0 does not contain -1 */
-
- arg = d->play_speed ;
-
- for (i=1; i < 16 ; i++)
- if (speeds[i] >0 && abs(arg-speeds[i]) < abs(arg-speeds[sel]) )
- sel = i ;
-
- d->play_speed = d->rec_speed = speeds[sel] ;
- return sel ;
-}
-
-/*
- * mss_format checks that the format is supported (or defaults to AFMT_U8)
- * and returns the bit setting for the 1848 register corresponding to
- * the desired format.
- *
- * fixed lr970724
- */
-
-static int
-mss_format(snddev_info *d)
-{
- int i, arg = d->play_fmt ;
-
- /*
- * The data format uses 3 bits (just 2 on the 1848). For each
- * bit setting, the following array returns the corresponding format.
- * The code scans the array looking for a suitable format. In
- * case it is not found, default to AFMT_U8 (not such a good
- * choice, but let's do it for compatibility...).
- */
-
- static int fmts[] = {
- AFMT_U8, AFMT_MU_LAW, AFMT_S16_LE, AFMT_A_LAW,
- -1, AFMT_IMA_ADPCM, AFMT_U16_BE, -1
- };
-
- if ( (arg & d->audio_fmt) == 0 ) /* unsupported fmt, default to AFMT_U8 */
- arg = AFMT_U8 ;
-
- /* ulaw/alaw seems broken on the opti931... */
- if (d->bd_id == MD_OPTI931 || d->bd_id == MD_GUSPNP) {
- if (arg == AFMT_MU_LAW) {
- arg = AFMT_U8 ;
- d->flags |= SND_F_XLAT8 ;
- } else
- d->flags &= ~SND_F_XLAT8 ;
- }
- /*
- * check that arg is one of the supported formats in d->format;
- * otherwise fallback to AFMT_U8
- */
-
- for (i=0 ; i<8 ; i++)
- if (arg == fmts[i]) break;
- if (i==8) { /* not found, default to AFMT_U8 */
- arg = AFMT_U8 ;
- i = 0 ;
- }
- d->play_fmt = d->rec_fmt = arg;
-
- return i ;
-}
-
-/*
- * mss_detect can be used in the probe and the attach routine.
- *
- * We store probe information in pcm_info[unit]. This descriptor
- * is reinitialized just before the attach, so all relevant
- * information is lost, and mss_detect must be run again in
- * the attach routine if necessary.
- */
-
-int
-mss_detect(struct isa_device *dev)
-{
- int i;
- u_char tmp, tmp1, tmp2 ;
- snddev_info *d = &(pcm_info[dev->id_unit]);
- char *name;
-
- d->io_base = dev->id_iobase;
- d->bd_flags |= BD_F_MCE_BIT ;
- if (d->bd_id != 0) {
- printf("preselected bd_id 0x%04x -- %s\n",
- d->bd_id, d->name ? d->name : "???");
- return 1;
- }
-
- name = "AD1848" ;
- d->bd_id = MD_AD1848; /* AD1848 or CS4248 */
-
- /*
- * Check that the I/O address is in use.
- *
- * bit 7 of the base I/O port is known to be 0 after the chip has
- * performed its power on initialization. Just assume this has
- * happened before the OS is starting.
- *
- * If the I/O address is unused, it typically returns 0xff.
- */
-
- for (i=0; i<10; i++)
- if (inb(io_Index_Addr(d)) & IA_BUSY)
- DELAY(10000); /* maybe busy, wait & retry later */
- else
- break ;
- if ((inb(io_Index_Addr(d)) & IA_BUSY) != 0x00) { /* Not a AD1848 */
- BVDDB(printf("mss_detect error, busy still set (0x%02x)\n",
- inb(io_Index_Addr(d))));
- 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.
- */
-
- ad_write(d, 0, 0xaa);
- ad_write(d, 1, 0x45);/* 0x55 with bit 0x10 clear */
- tmp1 = ad_read(d, 0) ;
- tmp2 = ad_read(d, 1) ;
- if ( tmp1 != 0xaa || tmp2 != 0x45) {
- BVDDB(printf("mss_detect error - IREG (0x%02x/0x%02x) want 0xaa/0x45\n",
- tmp1, tmp2));
- return 0;
- }
-
- ad_write(d, 0, 0x45);
- ad_write(d, 1, 0xaa);
- tmp1 = ad_read(d, 0) ;
- tmp2 = ad_read(d, 1) ;
-
- if (tmp1 != 0x45 || tmp2 != 0xaa) {
- BVDDB(printf("mss_detect error - IREG2 (%x/%x)\n", tmp1, tmp2));
- return 0;
- }
-
- /*
- * The indirect register I12 has some read only bits. Lets try to
- * change them.
- */
-
- tmp = ad_read(d, 12);
- ad_write(d, 12, (~tmp) & 0x0f);
- tmp1 = ad_read(d, 12);
-
- if ((tmp & 0x0f) != (tmp1 & 0x0f)) {
- BVDDB(printf("mss_detect error - I12 (0x%02x was 0x%02x)\n",
- tmp1, tmp));
- return 0;
- }
-
- /*
- * NOTE! Last 4 bits of the reg I12 tell the chip revision.
- * 0x01=RevB
- * 0x0A=RevC. also CS4231/CS4231A and OPTi931
- */
-
- BVDDB(printf("mss_detect - chip revision 0x%02x\n", tmp & 0x0f);)
-
- /*
- * The original AD1848/CS4248 has just 16 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 new parts.
- */
-
- ad_write(d, 12, 0); /* Mode2=disabled */
-
- for (i = 0; i < 16; i++)
- if ((tmp1 = ad_read(d, i)) != (tmp2 = ad_read(d, i + 16))) {
- BVDDB(printf("mss_detect warning - 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.
- */
-
- ad_write(d, 12, 0x40); /* Set mode2, clear 0x80 */
-
- tmp1 = ad_read(d, 12);
- if (tmp1 & 0x80) {
- name = "CS4248" ; /* Our best knowledge just now */
- }
- if ((tmp1 & 0xf0) == 0x00) {
- BVDDB(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.
- */
- ad_write(d, 16, 0); /* Set I16 to known value */
-
- ad_write(d, 0, 0x45);
- if ((tmp1 = ad_read(d, 16)) != 0x45) { /* No change -> CS4231? */
-
- ad_write(d, 0, 0xaa);
- if ((tmp1 = ad_read(d, 16)) == 0xaa) { /* Rotten bits? */
- BVDDB(printf("mss_detect error - step H(%x)\n", tmp1));
- return 0;
- }
- /*
- * Verify that some bits of I25 are read only.
- */
-
- tmp1 = ad_read(d, 25); /* Original bits */
- ad_write(d, 25, ~tmp1); /* Invert all bits */
- if ((ad_read(d, 25) & 0xe7) == (tmp1 & 0xe7)) {
- int id;
-
- /*
- * It's at least CS4231
- */
- name = "CS4231" ;
- d->bd_id = MD_CS4231;
-
- /*
- * It could be an AD1845 or CS4231A as well.
- * CS4231 and AD1845 report the same revision info in I25
- * while the CS4231A reports different.
- */
-
- id = ad_read(d, 25) & 0xe7;
- /*
- * b7-b5 = version number;
- * 100 : all CS4231
- * 101 : CS4231A
- *
- * b2-b0 = chip id;
- */
- switch (id) {
-
- case 0xa0:
- name = "CS4231A" ;
- d->bd_id = MD_CS4231A;
- break;
-
- case 0xa2:
- name = "CS4232" ;
- d->bd_id = MD_CS4232;
- break;
-
- case 0xb2:
- /* strange: the 4231 data sheet says b4-b3 are XX
- * so this should be the same as 0xa2
- */
- name = "CS4232A" ;
- d->bd_id = MD_CS4232A;
- 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(d, 23);
-
- ad_write(d, 23, ~tmp);
- if (ad_read(d, 23) != tmp) { /* AD1845 ? */
- name = "AD1845" ;
- d->bd_id = MD_AD1845;
- }
- ad_write(d, 23, tmp); /* Restore */
- DDB(printf("... try to identify the yamaha\n") ;)
- tmp = inb(0x370) ;
- outb(0x370, 6 /* dma config */ ) ;
- if (inb(0x370) != 6 ) /* not a yamaha... restore. */
- outb(0x370, tmp ) ;
- else
- d->bd_id = MD_YM0020 ;
- break;
-
- case 0x83: /* CS4236 */
- case 0x03: /* CS4236 on Intel PR440FX motherboard XXX */
- name = "CS4236";
- d->bd_id = MD_CS4236;
- break ;
-
- default: /* Assume CS4231 */
- BVDDB(printf("unknown id 0x%02x, assuming CS4231\n", id);)
- d->bd_id = MD_CS4231;
- }
- }
- ad_write(d, 25, tmp1); /* Restore bits */
-
- }
- }
- BVDDB(printf("mss_detect() - Detected %s\n", name));
- snprintf(d->name, sizeof(d->name), "%s", name);
- dev->id_flags &= ~DV_F_DEV_MASK ;
- dev->id_flags |= (d->bd_id << DV_F_DEV_SHIFT) & DV_F_DEV_MASK ;
- return 1;
-}
-
-
-/*
- * mss_reinit resets registers of the codec
- */
-static void
-mss_reinit(snddev_info *d)
-{
- u_char r;
-
- r = mss_speed(d) ;
- r |= (mss_format(d) << 5) ;
- if (d->flags & SND_F_STEREO)
- r |= 0x10 ;
- /* XXX check if MCE is necessary... */
- ad_enter_MCE(d);
-
- /*
- * perhaps this is not the place to set mode2, should be done
- * only once at attach time...
- */
- if ( FULL_DUPLEX(d) && d->bd_id != MD_OPTI931)
- /*
- * set mode2 bit for dual dma op. This bit is not implemented
- * on the OPTi931
- */
- ad_write(d, 12, ad_read(d, 12) | 0x40 /* mode 2 on the CS42xx */ );
-
- /*
- * XXX this should really go into mss-speed...
- */
- if (d->bd_id == MD_AD1845) { /* Use alternate speed select regs */
- r &= 0xf0; /* Mask off the rate select bits */
-
- ad_write(d, 22, (d->play_speed >> 8) & 0xff); /* Speed MSB */
- ad_write(d, 23, d->play_speed & 0xff); /* Speed LSB */
- /*
- * XXX must also do something in I27 for the ad1845
- */
- }
-
- ad_write(d, 8, r) ;
- if ( FULL_DUPLEX(d) ) {
-#if 0
- if (d->bd_id == MD_GUSPNP && d->play_fmt == AFMT_MU_LAW) {
- printf("warning, cannot do ulaw rec + play on the GUS\n");
- r = 0 ; /* move to U8 */
- }
-#endif
- ad_write(d, 28, r & 0xf0 ) ; /* capture mode */
- ad_write(d, 9, 0 /* no capture, no playback, dual dma */) ;
- } else
- ad_write(d, 9, 4 /* no capture, no playback, single dma */) ;
- ad_leave_MCE(d);
- /*
- * not sure if this is really needed...
- */
- ad_write_cnt(d, 14, 0 ); /* playback count */
- if ( FULL_DUPLEX(d) )
- ad_write_cnt(d, 30, 0 ); /* rec. count on dual dma */
-
- ad_write(d, 10, 2 /* int enable */) ;
- outb(io_Status(d), 0); /* Clear interrupt status */
- /* the following seem required on the CS4232 */
- ad_write(d, 6, ad_read(d,6) & ~I6_MUTE);
- ad_write(d, 7, ad_read(d,7) & ~I6_MUTE);
-
- snd_set_blocksize(d); /* update blocksize if user did not force it */
-}
-
-/*
- * here we have support for PnP cards
- *
- */
-
-#if NPNP > 0
-
-static char * cs423x_probe(u_long csn, u_long vend_id);
-static void
-cs423x_attach(u_long csn, u_long vend_id, char *name,
- struct isa_device *dev);
-
-static struct pnp_device cs423x = {
- "CS423x/Yamaha/AD1816",
- cs423x_probe,
- cs423x_attach,
- &nsnd, /* use this for all sound cards */
- &tty_imask /* imask */
-};
-DATA_SET (pnpdevice_set, cs423x);
-
-static char *
-cs423x_probe(u_long csn, u_long vend_id)
-{
- char *s = NULL ;
- u_long id = vend_id & 0xff00ffff;
- if ( id == 0x3700630e )
- s = "CS4237" ;
- else if ( id == 0x2500630e )
- s = "CS4235" ;
- else if ( id == 0x3600630e )
- s = "CS4236" ;
- else if ( id == 0x3500630e )
- s = "CS4236B" ;
- else if ( id == 0x3200630e)
- s = "CS4232" ;
- else if ( id == 0x2000a865)
- s = "Yamaha SA2";
- else if ( id == 0x3000a865)
- s = "Yamaha SA3";
- else if ( id == 0x0000a865)
- s = "Yamaha YMF719 OPL-SA3";
- else if (vend_id == 0x8140d315)
- s = "SoundscapeVIVO";
- else if (vend_id == 0x1114b250)
- s = "Terratec Soundsystem BASE 1";
- else if (vend_id == 0x50719304)
- s = "Generic AD1815";
- if (s) {
- struct pnp_cinfo d;
- read_pnp_parms(&d, 0);
- if (d.enable == 0) {
- printf("This is a %s, but LDN 0 is disabled\n", s);
- return NULL ;
- }
- return s;
- }
-
- return NULL ;
-}
-
-extern snddev_info sb_op_desc;
-
-static void
-cs423x_attach(u_long csn, u_long vend_id, char *name,
- struct isa_device *dev)
-{
- struct pnp_cinfo d ;
- snddev_info tmp_d ; /* patched copy of the basic snddev_info */
- int ldn = 0 ;
-
- if (read_pnp_parms ( &d , ldn ) == 0 ) {
- printf("failed to read pnp parms\n");
- return ;
- }
- snddev_last_probed = &tmp_d;
-
- /* AD1816 */
- if (vend_id == 0x1114b250 || vend_id == 0x50719304) {
- dev->id_alive = 16; /* number of io ports ? */
-
- tmp_d = mss_op_desc; /* copy it */
-
- tmp_d.ioctl = ad1816_ioctl;
- tmp_d.isr = ad1816_intr;
- tmp_d.callback = ad1816_callback;
- tmp_d.audio_fmt = AFMT_STEREO | AFMT_U8 |
- AFMT_A_LAW | AFMT_MU_LAW |
- AFMT_S16_LE | AFMT_S16_BE;
-
- dev->id_iobase = d.port[2];
- tmp_d.alt_base = d.port[0]; /* soundblaster comp. but we don't
- * use that */
- tmp_d.bd_id = MD_AD1816;
- strcpy(tmp_d.name, name);
- } else if (d.flags & DV_PNP_SBCODEC) { /* use sb-compatible codec */
- dev->id_alive = 16 ; /* number of io ports ? */
- tmp_d = sb_op_desc ;
- if (vend_id==0x2000a865 || vend_id==0x3000a865 ||
- vend_id==0x0008a865 || vend_id==0x8140d315) {
- /* Yamaha SA2/SA3 or ENSONIQ SoundscapeVIVO ENS4081 */
- dev->id_iobase = d.port[0] ;
- tmp_d.alt_base = d.port[1] ;
- d.irq[1] = 0 ; /* only needed for the VIVO */
- } else {
- dev->id_iobase = d.port[2] ;
- tmp_d.alt_base = d.port[0] - 4;
- }
- d.drq[1] = 4 ; /* disable, it is not used ... */
- } else { /* mss-compatible codec */
- dev->id_alive = 8 ; /* number of io ports ? */
- tmp_d = mss_op_desc ;
- dev->id_iobase = d.port[0] -4 ; /* XXX old mss have 4 bytes before... */
- tmp_d.alt_base = d.port[2];
- switch (vend_id & 0xff00ffff) {
-
- case 0x2000a865: /* Yamaha SA2 */
- case 0x3000a865: /* Yamaha SA3 */
- case 0x0000a865: /* Yamaha TMF719 SA3 */
- dev->id_iobase = d.port[1];
- tmp_d.alt_base = d.port[0];
- tmp_d.conf_base = d.port[4];
- tmp_d.bd_id = MD_YM0020 ;
- break;
-
- case 0x8100d315: /* ENSONIQ SoundscapeVIVO */
- dev->id_iobase = d.port[1];
- tmp_d.alt_base = d.port[0];
- tmp_d.bd_id = MD_VIVO ;
- d.irq[1] = 0 ;
- break;
-
- case 0x3700630e: /* CS4237 */
- tmp_d.bd_id = MD_CS4237 ;
- break;
-
- case 0x2500630e: /* AOpen AW37, CS4235 */
- tmp_d.bd_id = MD_CS4237 ;
- break ;
-
- case 0x3500630e: /* CS4236B */
- case 0x3600630e: /* CS4236 */
- tmp_d.bd_id = MD_CS4236 ;
- break;
-
- default:
- tmp_d.bd_id = MD_CS4232; /* to short-circuit the
- * detect routine */
- break;
- }
- snprintf(tmp_d.name, sizeof(tmp_d.name), "%s", name);
- tmp_d.audio_fmt |= AFMT_FULLDUPLEX ;
- }
-
- write_pnp_parms( &d, ldn );
- enable_pnp_card();
-
- if ( (vend_id & 0x0000ffff) == 0x0000a865 ) {
- /* special volume setting for the Yamaha... */
- outb(tmp_d.conf_base, 7 /* volume, left */);
- outb(tmp_d.conf_base+1, 0 );
- outb(tmp_d.conf_base, 8 /* volume, right */);
- outb(tmp_d.conf_base+1, 0 );
- }
- dev->id_drq = d.drq[0] ; /* primary dma */
- dev->id_irq = (1 << d.irq[0] ) ;
- dev->id_ointr = pcmintr ;
- dev->id_flags = DV_F_DUAL_DMA | (d.drq[1] ) ;
-
- tmp_d.synth_base = d.port[1]; /* XXX check this for yamaha */
- pcmattach(dev);
-}
-
-static char *opti931_probe(u_long csn, u_long vend_id);
-static void opti931_attach(u_long csn, u_long vend_id, char *name,
- struct isa_device *dev);
-static struct pnp_device opti931 = {
- "OPTi931",
- opti931_probe,
- opti931_attach,
- &nsnd, /* use this for all sound cards */
- &tty_imask /* imask */
-};
-DATA_SET (pnpdevice_set, opti931);
-
-static char *
-opti931_probe(u_long csn, u_long vend_id)
-{
- if (vend_id == 0x3109143e) {
- struct pnp_cinfo d;
- read_pnp_parms(&d, 1);
- if (d.enable == 0) {
- printf("This is an OPTi931, but LDN 1 is disabled\n");
- return NULL ;
- }
- return "OPTi931" ;
- }
- return NULL ;
-}
-
-static void
-opti931_attach(u_long csn, u_long vend_id, char *name,
- struct isa_device *dev)
-{
- struct pnp_cinfo d ;
- snddev_info tmp_d ; /* patched copy of the basic snddev_info */
- int p;
-
- read_pnp_parms ( &d , 3 ); /* free resources taken by LDN 3 */
- d.irq[0]=0; /* free irq... */
- d.port[0]=0; /* free address... */
- d.enable = 0 ;
- write_pnp_parms ( &d , 3 );
-
- read_pnp_parms ( &d , 2 ); /* disable LDN 2 */
- d.enable = 0 ;
- write_pnp_parms ( &d , 2 );
-
- read_pnp_parms ( &d , 1 ) ;
- write_pnp_parms( &d, 1 );
- enable_pnp_card();
-
- snddev_last_probed = &tmp_d;
- tmp_d = d.flags & DV_PNP_SBCODEC ? sb_op_desc : mss_op_desc ;
-
- snprintf(tmp_d.name, sizeof(tmp_d.name), "%s", name);
-
- /*
- * My MED3931 v.1.0 allocates 3 bytes for the config space,
- * whereas v.2.0 allocates 4 bytes. What I know for sure is that the
- * upper two ports must be used, and they should end on a boundary
- * of 4 bytes. So I need the following trick...
- */
- p = tmp_d.conf_base = (d.port[3] & ~3) + 2; /* config port */
-
- /*
- * now set default values for both modes.
- */
- dev->id_iobase = d.port[0] - 4 ; /* old mss have 4 bytes before... */
- tmp_d.io_base = dev->id_iobase; /* needed for ad_write to work... */
- tmp_d.alt_base = d.port[2];
- tmp_d.synth_base = d.port[1];
- opti_write(p, 4, 0xd6 /* fifo empty, OPL3, audio enable, SB3.2 */ );
- ad_write (&tmp_d, 10, 2); /* enable interrupts */
-
- if (d.flags & DV_PNP_SBCODEC) { /* sb-compatible codec */
- /*
- * the 931 is not a real SB, it has important pieces of
- * hardware controlled by both the MSS and the SB port...
- */
- printf("--- opti931 in sb mode ---\n");
- opti_write(p, 6, 1); /* MCIR6 mss disable, sb enable */
- /*
- * swap the main and alternate iobase address since we want
- * to work in sb mode.
- */
- dev->id_iobase = d.port[2] ;
- tmp_d.alt_base = d.port[0] - 4;
- dev->id_flags = DV_F_DUAL_DMA | d.drq[1] ;
- } else { /* mss-compatible codec */
- tmp_d.bd_id = MD_OPTI931 ; /* to short-circuit the detect routine */
- opti_write(p, 6 , 2); /* MCIR6: mss enable, sb disable */
- opti_write(p, 5, 0x28); /* MCIR5: codec in exp. mode,fifo */
- dev->id_flags = DV_F_DUAL_DMA | d.drq[1] ;
- tmp_d.audio_fmt |= AFMT_FULLDUPLEX ; /* not really well... */
- tmp_d.isr = opti931_intr;
- }
- dev->id_drq = d.drq[0] ; /* primary dma */
- dev->id_irq = (1 << d.irq[0] ) ;
- dev->id_ointr = pcmintr ;
- pcmattach(dev);
-}
-
-static char *opti925_probe(u_long csn, u_long vend_id);
-static void opti925_attach(u_long csn, u_long vend_id, char *name,
- struct isa_device *dev);
-
-static struct pnp_device opti925 = {
- "opti925",
- opti925_probe,
- opti925_attach,
- &nsnd, /* use this for all sound cards */
- &tty_imask /* imask */
-};
-DATA_SET (pnpdevice_set, opti925);
-
-static char *
-opti925_probe(u_long csn, u_long vend_id)
-{
- if (vend_id == 0x2509143e) {
- struct pnp_cinfo d ;
- read_pnp_parms ( &d , 1 ) ;
- if (d.enable == 0) {
- printf("This is an OPTi925, but LDN 1 is disabled\n");
- return NULL;
- }
- return "OPTi925" ;
- }
- return NULL ;
-}
-
-static void
-opti925_attach(u_long csn, u_long vend_id, char *name,
- struct isa_device *dev)
-{
- struct pnp_cinfo d ;
- snddev_info tmp_d ; /* patched copy of the basic snddev_info */
- int the_irq = 0 ;
-
- tmp_d = mss_op_desc;
- snddev_last_probed = &tmp_d;
-
- read_pnp_parms ( &d , 3 ); /* disable LDN 3 */
- the_irq = d.irq[0];
- d.port[0] = 0 ;
- d.enable = 0 ;
- write_pnp_parms ( &d , 3 );
-
- read_pnp_parms ( &d , 2 ); /* disable LDN 2 */
- d.port[0] = 0 ;
- d.enable = 0 ;
- write_pnp_parms ( &d , 2 );
-
- read_pnp_parms ( &d , 1 ) ;
- d.irq[0] = the_irq ;
- dev->id_iobase = d.port[1];
- tmp_d.alt_base = d.port[0];
- write_pnp_parms ( &d , 1 );
- enable_pnp_card();
-
- tmp_d.conf_base = d.port[3];
-
- dev->id_drq = d.drq[0] ; /* primary dma */
- dev->id_irq = (1 << d.irq[0] ) ;
- dev->id_ointr = pcmintr ;
- dev->id_flags = DV_F_DUAL_DMA | d.drq[1] ;
- tmp_d.audio_fmt |= AFMT_FULLDUPLEX ;
-
- snddev_last_probed->probe(dev); /* not really necessary but doesn't harm */
-
- pcmattach(dev);
-}
-
-#if 0
-static void gus_mem_cfg(snddev_info *tmp);
-#endif
-
-static char *guspnp_probe(u_long csn, u_long vend_id);
-static void guspnp_attach(u_long csn, u_long vend_id, char *name,
- struct isa_device *dev);
-static struct pnp_device guspnp = {
- "GusPnP",
- guspnp_probe,
- guspnp_attach,
- &nsnd, /* use this for all sound cards */
- &tty_imask /* imask */
-};
-DATA_SET (pnpdevice_set, guspnp);
-
-static char *
-guspnp_probe(u_long csn, u_long vend_id)
-{
- if (vend_id == 0x0100561e) {
- struct pnp_cinfo d;
- read_pnp_parms(&d, 0);
- if (d.enable == 0) {
- printf("This is a GusPnP, but LDN 0 is disabled\n");
- return NULL ;
- }
- return "GusPnP" ;
- }
- return NULL ;
-}
-
-static void
-guspnp_attach(u_long csn, u_long vend_id, char *name,
- struct isa_device *dev)
-{
- struct pnp_cinfo d ;
- snddev_info tmp_d ; /* patched copy of the basic snddev_info */
-
- u_char tmp;
-
- read_pnp_parms ( &d , 0 ) ;
-
- /* d.irq[1] = d.irq[0] ; */
- pnp_write ( 0xf2, 0xff ); /* enable power on the guspnp */
-
- write_pnp_parms ( &d , 0 );
- enable_pnp_card();
-
- tmp_d = mss_op_desc ;
- snddev_last_probed = &tmp_d;
-
- dev->id_iobase = d.port[2] - 4 ; /* room for 4 mss registers */
- dev->id_drq = d.drq[1] ; /* XXX PLAY dma */
- dev->id_irq = (1 << d.irq[0] ) ;
- dev->id_ointr = pcmintr ;
- dev->id_flags = DV_F_DUAL_DMA | d.drq[0] ; /* REC dma */
-
- tmp_d.io_base = d.port[2] - 4;
- tmp_d.alt_base = d.port[0]; /* 0x220 */
- tmp_d.conf_base = d.port[1]; /* gus control block... */
- tmp_d.bd_id = MD_GUSPNP ;
-
- /* reset */
- gus_write(tmp_d.conf_base, 0x4c /* _URSTI */, 0 );/* Pull reset */
- DELAY(1000 * 30);
- /* release reset and enable DAC */
- gus_write(tmp_d.conf_base, 0x4c /* _URSTI */, 3 );
- DELAY(1000 * 30);
- /* end of reset */
-
- outb( tmp_d.alt_base, 0xC ); /* enable int and dma */
-
- /*
- * unmute left & right line. Need to go in mode3, unmute,
- * and back to mode 2
- */
- tmp = ad_read(&tmp_d, 0x0c);
- ad_write(&tmp_d, 0x0c, 0x6c ); /* special value to enter mode 3 */
- ad_write(&tmp_d, 0x19, 0 ); /* unmute left */
- ad_write(&tmp_d, 0x1b, 0 ); /* unmute right */
- ad_write(&tmp_d, 0x0c, tmp ); /* restore old mode */
-
- /* send codec interrupts on irq1 and only use that one */
- gus_write(tmp_d.conf_base, 0x5a , 0x4f );
-
- /* enable access to hidden regs */
- tmp = gus_read(tmp_d.conf_base, 0x5b /* IVERI */ );
- gus_write(tmp_d.conf_base, 0x5b , tmp | 1 );
- BVDDB(printf("GUS: silicon rev %c\n", 'A' + ( ( tmp & 0xf ) >> 4) );)
-
- snprintf(tmp_d.name, sizeof(tmp_d.name), "%s", name);
-
- pcmattach(dev);
-}
-
-#if 0
-int
-gus_mem_write(snddev_info *d, int addr, u_char data)
-{
- gus_writew(d->conf_base, 0x43 , addr & 0xffff );
- gus_write(d->conf_base, 0x44 , (addr>>16) & 0xff );
- outb(d->conf_base + 7, data);
-}
-
-u_char
-gus_mem_read(snddev_info *d, int addr)
-{
- gus_writew(d->conf_base, 0x43 , addr & 0xffff );
- gus_write(d->conf_base, 0x44 , (addr>>16) & 0xff );
- return inb(d->conf_base + 7);
-}
-
-void
-gus_mem_cfg(snddev_info *d)
-{
- int base;
- u_char old;
- u_char a, b;
-
- printf("configuring gus memory...\n");
- gus_writew(d->conf_base, 0x52 /* LMCFI */, 1 /* 512K*/);
- old = gus_read(d->conf_base, 0x19);
- gus_write(d->conf_base, 0x19, old | 1); /* enable enhaced mode */
- for (base = 0; base < 1024; base++) {
- a=gus_mem_read(d, base*1024);
- a = ~a ;
- gus_mem_write(d, base*1024, a);
- b=gus_mem_read(d, base*1024);
- if ( b != a )
- break ;
- }
- printf("Have found %d KB ( 0x%x != 0x%x)\n", base, a, b);
-}
-#endif /* gus mem cfg... */
-
-static int
-ad1816_ioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct proc * p)
-{
- snddev_info *d;
- int unit;
- int dev;
-
- dev = minor(i_dev);
- unit = dev >> 4;
- d = &pcm_info[unit];
-
- if ((cmd & MIXER_WRITE(0)) == MIXER_WRITE(0)) {
- cmd &= 0xff;
- if (cmd == SOUND_MIXER_RECSRC)
- return ad1816_set_recsrc(d, *(int *) arg);
- else
- return ad1816_mixer_set(d, cmd, *(int *) arg);
- }
- switch (cmd) { /* driver specific ioctls other than mixer
- * calls */
- /* ad1816 has special features */
- case AIOGCAP: /* get capabilities */
- {
- snd_capabilities *p = (snd_capabilities *) arg;
- p->rate_min = 4000;
- p->rate_max = 55200;
- p->bufsize = d->bufsize;
- p->formats = d->audio_fmt;
- p->mixers = 1;
- p->inputs = d->mix_devs;
- p->left = p->right = 100;
- return 0;
- }
- default:
- {
- return ENOSYS; /* fallback to default */
- }
- break;
- }
-}
-
-static int
-ad1816_callback(snddev_info * d, int reason)
-{
- int wr, cnt;
-
- wr = reason & SND_CB_WR;
- reason &= SND_CB_REASON_MASK;
-
- switch (reason) {
- case SND_CB_INIT:
- ad1816_reinit(d);
- reset_dbuf(&(d->dbuf_in), SND_CHAN_RD);
- reset_dbuf(&(d->dbuf_out), SND_CHAN_WR);
- return 1;
- break;
-
- case SND_CB_START:
- cnt = wr ? d->dbuf_out.dl : d->dbuf_in.dl;
-
- cnt /= 4;
- cnt--;
-
- /* start only if not already running */
- if (wr && !(inb(ad1816_play(d)) & AD1816_ENABLE)) {
- /* set dma counter */
- ad1816_write(d, 8, cnt); /* playback count */
- /* int enable */
- ad1816_write(d, 1, ad1816_read(d, 1) | 0x8000);
- /* enable playback */
- outb(ad1816_play(d), (inb(ad1816_play(d)) | AD1816_ENABLE));
- /* check if we succeeded */
- if (!(inb(ad1816_play(d)) & AD1816_ENABLE)) {
- printf("ad1816: failed to start write (playback) DMA !\n");
- }
- } else if (!wr && !(inb(ad1816_capt(d)) & AD1816_ENABLE)) {
- /* same for capture */
- ad1816_write(d, 10, cnt); /* capture count */
- ad1816_write(d, 1, ad1816_read(d, 1) | 0x4000); /* int */
- outb(ad1816_capt(d), (inb(ad1816_capt(d)) | AD1816_ENABLE)); /* CEN */
- if (!(inb(ad1816_capt(d)) & AD1816_ENABLE)) { /* check */
- printf("ad1816: failed to start read (capture) DMA !\n");
- }
- }
- break;
-
- case SND_CB_STOP:
- case SND_CB_ABORT: /* XXX check this... */
- /* we don't test here if it is running... */
- if (wr) {
- ad1816_write(d, 1, ad1816_read(d, 1) & ~0x8000);
- /* disable int */
- outb(ad1816_play(d), (inb(ad1816_play(d)) & ~AD1816_ENABLE));
- /* disable playback */
- if ((inb(ad1816_play(d)) & AD1816_ENABLE)) {
- printf("ad1816: failed to stop write (playback) DMA !\n");
- }
- ad1816_write(d, 8, 0); /* reset base counter */
- ad1816_write(d, 9, 0); /* reset cur counter */
- } else {
- /* same for capture */
- ad1816_write(d, 1, ad1816_read(d, 1) & ~0x4000);
- outb(ad1816_capt(d), (inb(ad1816_capt(d)) & ~AD1816_ENABLE));
- if ((inb(ad1816_capt(d)) & AD1816_ENABLE)) {
- printf("ad1816: failed to stop read (capture) DMA !\n");
- }
- ad1816_write(d, 10, 0);
- ad1816_write(d, 11, 0);
- }
- break;
- }
-
- return 0;
-}
-
-static void
-ad1816_intr(int unit)
-{
- snddev_info *d = &pcm_info[unit];
- unsigned char c, served = 0;
-
- /* get interupt status */
- c = inb(ad1816_int(d));
-
- /* check for stray interupts */
- if (c & ~(AD1816_INTRCI | AD1816_INTRPI)) {
- printf("ad1816: Stray interrupt 0x%x.\n", c);
- c = c & (AD1816_INTRCI | AD1816_INTRPI);
- outb(ad1816_int(d), c); /* ack it anyway */
- }
- /* check for capture interupt */
- if (d->dbuf_in.dl && (c & AD1816_INTRCI)) {
- outb(ad1816_int(d), c & ~AD1816_INTRCI); /* ack it */
- if (inb(ad1816_int(d)) & AD1816_INTRCI)
- printf("ad1816: Failed to clear cp int !!!\n");
- dsp_rdintr(d);
- served |= AD1816_INTRCI; /* cp served */
- }
- /* check for playback interupt */
- if (d->dbuf_out.dl && (c & AD1816_INTRPI)) {
- outb(ad1816_int(d), c & ~AD1816_INTRPI); /* ack it */
- if ((inb(ad1816_int(d)) & AD1816_INTRPI) != 0)
- printf("ad1816: Failed to clear pb int !!!\n");
- dsp_wrintr(d);
- served |= AD1816_INTRPI; /* pb served */
- }
- if (served == 0) {
- /* this probably means this is not a (working) ad1816 chip, */
- /* or an error in dma handling */
- printf("ad1816: raised an interrupt without reason 0x%x.\n", c);
- outb(ad1816_int(d), 0); /* Clear interrupt status anyway */
- }
-}
-
-static int
-ad1816_wait_init(snddev_info * d, int x)
-{
- int n = 0; /* to shut up the compiler... */
-
- for (; x--;)
- if (((n = (inb(ad1816_ale(d)) & AD1816_BUSY))) == 0)
- DELAY(10);
- else
- return n;
- printf("ad1816_wait_init failed 0x%02x.\n", inb(ad1816_ale(d)));
- return n;
-}
-
-static unsigned short
-ad1816_read(snddev_info * d, unsigned int reg)
-{
- int flags;
- u_short x;
-
- /* we don't want to be blocked here */
- flags = spltty();
- if (ad1816_wait_init(d, 100) == 0) {
- printf("ad1816_read: chip timeout before read.\n");
- return 0;
- }
- outb(ad1816_ale(d), (u_char) 0);
- outb(ad1816_ale(d), (u_char) (reg & AD1816_ALEMASK));
- if (ad1816_wait_init(d, 100) == 0) {
- printf("ad1816_read: chip timeout during read.\n");
- return 0;
- }
- x = (inb(ad1816_high(d)) << 8) | inb(ad1816_low(d));
- splx(flags);
- return x;
-}
-
-static void
-ad1816_write(snddev_info * d, unsigned int reg, unsigned short data)
-{
- int flags;
-
- flags = spltty();
- if (ad1816_wait_init(d, 100) == 0) {
- printf("ad1816_write: chip timeout before write.\n");
- return;
- }
- outb(ad1816_ale(d), (u_char) (reg & AD1816_ALEMASK));
- outb(ad1816_low(d), (u_char) (data & 0x000000ff));
- outb(ad1816_high(d), (u_char) ((data & 0x0000ff00) >> 8));
- splx(flags);
-}
-
-#if 0 /* unused right now..., and untested... */
-static void
-ad1816_mute(snddev_info * d)
-{
- ad1816_write(d, 14, ad1816_read(d, 14) | 0x8000 | 0x80);
-}
-
-static void
-ad1816_unmute(snddev_info * d)
-{
- ad1816_write(d, 14, ad1816_read(d, 14) & ~(0x8000 | 0x80));
-}
-#endif
-
-/* only one rec source is possible */
-
-static int
-ad1816_set_recsrc(snddev_info * d, int mask)
-{
- mask &= d->mix_rec_devs;
-
- switch (mask) {
- case SOUND_MASK_LINE:
- case SOUND_MASK_LINE3:
- ad1816_write(d, 20, (ad1816_read(d, 20) & ~0x7070) | 0x0000);
- break;
-
- case SOUND_MASK_CD:
- case SOUND_MASK_LINE1:
- ad1816_write(d, 20, (ad1816_read(d, 20) & ~0x7070) | 0x2020);
- break;
-
- case SOUND_MASK_MIC:
- default:
- ad1816_write(d, 20, (ad1816_read(d, 20) & ~0x7070) | 0x5050);
- }
-
- d->mix_recsrc = mask;
-
- return 0; /* success */
-}
-
-#define AD1816_MUTE 31 /* value for mute */
-
-static int
-ad1816_mixer_set(snddev_info * d, int dev, int value)
-{
- u_char left = (value & 0x000000ff);
- u_char right = (value & 0x0000ff00) >> 8;
- u_short reg = 0;
-
- if (dev > 31)
- return EINVAL;
-
- if (!(d->mix_devs & (1 << dev)))
- return EINVAL;
-
- if (left > 100)
- left = 100;
- if (right > 100)
- right = 100;
-
- d->mix_levels[dev] = left | (right << 8);
-
- /* Scale volumes */
- left = AD1816_MUTE - (AD1816_MUTE * left) / 100;
- right = AD1816_MUTE - (AD1816_MUTE * right) / 100;
-
- reg = (left << 8) | right;
-
- /* do channel selective muting if volume is zero */
- if (left == AD1816_MUTE)
- reg |= 0x8000;
- if (right == AD1816_MUTE)
- reg |= 0x0080;
-
- switch (dev) {
- case SOUND_MIXER_VOLUME: /* Register 14 master volume */
- ad1816_write(d, 14, reg);
- break;
- case SOUND_MIXER_CD: /* Register 15 cd */
- case SOUND_MIXER_LINE1:
- ad1816_write(d, 15, reg);
- break;
- case SOUND_MIXER_SYNTH: /* Register 16 synth */
- ad1816_write(d, 16, reg);
- break;
- case SOUND_MIXER_PCM: /* Register 4 pcm */
- ad1816_write(d, 4, reg);
- break;
- case SOUND_MIXER_LINE:
- case SOUND_MIXER_LINE3: /* Register 18 line in */
- ad1816_write(d, 18, reg);
- break;
- case SOUND_MIXER_MIC: /* Register 19 mic volume */
- ad1816_write(d, 19, reg & ~0xff); /* mic is mono */
- break;
- case SOUND_MIXER_IGAIN:
- /* and now to something completely different ... */
- ad1816_write(d, 20, ((ad1816_read(d, 20) & ~0x0f0f)
- | (((AD1816_MUTE - left) / 2) << 8) /* four bits of adc gain */
- | ((AD1816_MUTE - right) / 2)));
- break;
- default:
- printf("ad1816_mixer_set(): unknown device.\n");
- break;
- }
-
- return 0; /* success */
-}
-
-static void
-ad1816_mixer_reset(snddev_info * d)
-{
- int i;
-
- d->mix_devs = AD1816_MIXER_DEVICES;
- d->mix_rec_devs = AD1816_REC_DEVICES;
-
- for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
- if (d->mix_devs & (1 << i))
- ad1816_mixer_set(d, i, default_mixer_levels[i]);
- ad1816_set_recsrc(d, SOUND_MASK_MIC);
-}
-
-/* Set the playback and capture rates. */
-
-static int
-ad1816_speed(snddev_info * d)
-{
- RANGE(d->play_speed,4000,55200);
- RANGE(d->rec_speed,4000,55200);
-
- ad1816_write(d, 2, d->play_speed);
- ad1816_write(d, 3, d->rec_speed);
-
- return d->play_speed;
-}
-
-/*
- * ad1816_format checks that the format is supported (or defaults to AFMT_U8)
- * and sets the chip to the desired format.
- */
-
-static int
-ad1816_format(snddev_info * d)
-{
- int oldplay =inb(ad1816_play(d)) & ~AD1816_FORMASK;
- int oldrec = inb(ad1816_capt(d)) & ~AD1816_FORMASK;
- int play = (d->play_fmt & d->audio_fmt) ? d->play_fmt : AFMT_U8;
- int rec = (d->rec_fmt & d->audio_fmt) ? d->rec_fmt : AFMT_U8;
-
- /*
- * check that arg is one of the supported formats in d->format; otherwise
- * fallback to AFMT_U8
- */
-
- switch (play) {
- case AFMT_A_LAW:
- outb(ad1816_play(d), oldplay | AD1816_ALAW);
- break;
- case AFMT_MU_LAW:
- outb(ad1816_play(d), oldplay | AD1816_MULAW);
- break;
- case AFMT_S16_LE:
- outb(ad1816_play(d), oldplay | AD1816_S16LE);
- break;
- case AFMT_S16_BE:
- outb(ad1816_play(d), oldplay | AD1816_S16BE);
- break;
- default:
- /* unlikely to happen */
- printf("ad1816: unknown play format. defaulting to U8.\n");
- case AFMT_U8:
- outb(ad1816_play(d), oldplay | AD1816_U8);
- break;
- }
-
- switch (rec) {
- case AFMT_A_LAW:
- outb(ad1816_capt(d), oldrec | AD1816_ALAW);
- break;
- case AFMT_MU_LAW:
- outb(ad1816_capt(d), oldrec | AD1816_MULAW);
- break;
- case AFMT_S16_LE:
- outb(ad1816_capt(d), oldrec | AD1816_S16LE);
- break;
- case AFMT_S16_BE:
- outb(ad1816_capt(d), oldrec | AD1816_S16BE);
- break;
- default:
- printf("ad1816: unknown capture format. defaulting to U8.\n");
- case AFMT_U8:
- outb(ad1816_capt(d), oldrec | AD1816_U8);
- break;
- }
-
- d->play_fmt = play;
- d->rec_fmt = rec;
-
- return (play);
-}
-
-/*
- * ad1816_reinit resets codec registers
- */
-static void
-ad1816_reinit(snddev_info * d)
-{
- ad1816_write(d, 8, 0x0000); /* reset base and current counter */
- ad1816_write(d, 9, 0x0000); /* for playback and capture */
- ad1816_write(d, 10, 0x0000);
- ad1816_write(d, 11, 0x0000);
-
- if (d->flags & SND_F_STEREO) {
- outb((ad1816_play(d)), AD1816_STEREO); /* set playback to stereo */
- outb((ad1816_capt(d)), AD1816_STEREO); /* set capture to stereo */
- } else {
- outb((ad1816_play(d)), 0x00); /* set playback to mono */
- outb((ad1816_capt(d)), 0x00); /* set capture to mono */
- }
-
- ad1816_format(d);
- ad1816_speed(d);
-
- snd_set_blocksize(d); /* update blocksize if user did not force it */
-}
-
-#endif /* NPNP > 0 */
-#endif /* NPCM > 0 */
diff --git a/sys/i386/isa/snd/clones.c b/sys/i386/isa/snd/clones.c
deleted file mode 100644
index 4927932..0000000
--- a/sys/i386/isa/snd/clones.c
+++ /dev/null
@@ -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 */
diff --git a/sys/i386/isa/snd/dmabuf.c b/sys/i386/isa/snd/dmabuf.c
deleted file mode 100644
index 66f94ac..0000000
--- a/sys/i386/isa/snd/dmabuf.c
+++ /dev/null
@@ -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
- */
diff --git a/sys/i386/isa/snd/mss.h b/sys/i386/isa/snd/mss.h
deleted file mode 100644
index 20ceaaf..0000000
--- a/sys/i386/isa/snd/mss.h
+++ /dev/null
@@ -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)*/
-};
-
diff --git a/sys/i386/isa/snd/sb_dsp.c b/sys/i386/isa/snd/sb_dsp.c
deleted file mode 100644
index 7544dae..0000000
--- a/sys/i386/isa/snd/sb_dsp.c
+++ /dev/null
@@ -1,1366 +0,0 @@
-/*
- * sound/sb_dsp.c
- *
- * driver for the SoundBlaster and clones.
- *
- * Copyright 1997,1998 Luigi Rizzo.
- *
- * Derived from files in the Voxware 3.5 distribution,
- * Copyright by Hannu Savolainen 1994, under the same copyright
- * conditions.
- *
- * 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.
- *
- */
-
-/*
- * use this as a template file for board-specific drivers.
- * The next two lines (and the final #endif) are in all drivers:
- */
-
-#include <i386/isa/snd/sound.h>
-#if NPCM > 0
-
-/*
- * Begin with the board-specific include files...
- */
-
-#define __SB_MIXER_C__ /* XXX warning... */
-#include <i386/isa/snd/sbcard.h>
-
-/*
- * then prototypes of functions which go in the snddev_info
- * (usually static, unless they are shared by other modules)...
- */
-
-static int sb_probe(struct isa_device *dev);
-static int sb_attach(struct isa_device *dev);
-
-static d_open_t sb_dsp_open;
-static d_close_t sb_dsp_close;
-static d_ioctl_t sb_dsp_ioctl;
-static irq_proc_t sb_intr;
-static snd_callback_t sb_callback;
-
-/*
- * and prototypes for other private functions defined in this module.
- */
-
-static void sb_dsp_init(snddev_info *d, struct isa_device *dev);
-static void sb_mix_init(snddev_info *d);
-static int sb_mixer_set(snddev_info *d, int dev, int value);
-static int dsp_speed(snddev_info *d);
-static void sb_mixer_reset(snddev_info *d);
-
-u_int sb_get_byte(int io_base);
-int ess_write(int io_base, u_char reg, int val);
-int ess_read(int io_base, u_char reg);
-
-/*
- * Then put here the descriptors for the various boards supported
- * by this module, properly initialized.
- */
-
-snddev_info sb_op_desc = {
- "basic soundblaster",
-
- SNDCARD_SB,
- sb_probe,
- sb_attach,
-
- sb_dsp_open,
- sb_dsp_close /* sb_close */,
- NULL /* use generic sndread */,
- NULL /* use generic sndwrite */,
- sb_dsp_ioctl,
- sndselect,
-
- sb_intr,
- sb_callback,
-
- DSP_BUFFSIZE, /* bufsize */
-
- AFMT_STEREO | AFMT_U8, /* audio format */
-
-} ;
-
-/*
- * Then the file continues with the body of all functions
- * directly referenced in the descriptor.
- */
-
-/*
- * the probe routine for the SoundBlaster only consists in
- * resetting the dsp and testing if it is there.
- * Version detection etc. will be done at attach time.
- *
- * Remember, ISA probe routines are supposed to return the
- * size of io space used.
- */
-
-static int
-sb_probe(struct isa_device *dev)
-{
- bzero(&pcm_info[dev->id_unit], sizeof(pcm_info[dev->id_unit]) );
- if (dev->id_iobase == -1) {
- dev->id_iobase = 0x220;
- BVDDB(printf("sb_probe: no address supplied, try defaults (0x220,0x240)\n");)
- if (snd_conflict(dev->id_iobase))
- dev->id_iobase = 0x240;
- }
- if (snd_conflict(dev->id_iobase))
- return 0 ;
-
- if (sb_reset_dsp(dev->id_iobase))
- return 16 ; /* the SB uses 16 registers... */
- else
- return 0;
-}
-
-static int
-sb_attach(struct isa_device *dev)
-{
- snddev_info *d = &pcm_info[dev->id_unit] ;
-
- dev->id_alive = 16 ; /* number of io ports */
- /* should be already set but just in case... */
- sb_dsp_init(d, dev);
- return 0 ;
-}
-
-/*
- * here are the main routines from the switches.
- */
-
-/*
- * Unlike MSS, the sb only supports a single open (does not mean
- * that only a single process is using it, since it can fork
- * afterwards, or pass the descriptor to another process).
- *
- */
-static int
-sb_dsp_open(dev_t i_dev, int flags, int mode, struct proc * p)
-{
- snddev_info *d;
- int unit ;
- int dev;
-
- dev = minor(i_dev);
- unit = dev >> 4 ;
- d = &pcm_info[unit] ;
-
- DEB(printf("<%s>%d : open\n", d->name, unit));
-
- if (d->flags & SND_F_BUSY) {
- DEB(printf("<%s>%d open: device busy\n", d->name, unit));
- return EBUSY ;
- }
-
- d->wsel.si_pid = 0;
- d->wsel.si_flags = 0;
-
- d->rsel.si_pid = 0;
- d->rsel.si_flags = 0;
-
- d->dbuf_out.total = d->dbuf_out.prev_total = 0 ;
- d->dbuf_in.total = d->dbuf_in.prev_total = 0 ;
-
- d->flags = 0 ;
- d->bd_flags &= ~BD_F_HISPEED ;
-
- switch ( dev & 0xf ) {
- case SND_DEV_DSP16 :
- if ((d->audio_fmt & AFMT_S16_LE) == 0) {
- printf("sorry, 16-bit not supported on SB %d.%02d\n",
- (d->bd_id >>8) & 0xff, d->bd_id & 0xff);
- return ENXIO;
- }
- d->play_fmt = d->rec_fmt = AFMT_S16_LE ;
- break;
- case SND_DEV_AUDIO :
- d->play_fmt = d->rec_fmt = AFMT_MU_LAW ;
- break ;
- case SND_DEV_DSP :
- d->play_fmt = d->rec_fmt = AFMT_U8 ;
- break ;
- }
- /*
- * since the SB is not simmetric, I use the open mode to select
- * which channel should be privileged, and disable I/O in the
- * other direction.
- * In case the board is opened RW, we don't have enough
- * information on what to do. Temporarily, privilege the
- * playback channel, which is used more often, and set the other
- * one to U8.
- */
- if ( (flags & FREAD) == 0) /* opened write only */
- d->rec_fmt = 0 ;
- else if ( (flags & FWRITE) == 0) /* opened read only */
- d->play_fmt = 0 ;
- else /* opened read/write */
- d->rec_fmt = (d->play_fmt == AFMT_S16_LE) ? AFMT_U8 : AFMT_S16_LE ;
-
- d->flags |= SND_F_BUSY ;
- d->play_speed = d->rec_speed = DSP_DEFAULT_SPEED ;
-
- if (flags & O_NONBLOCK)
- d->flags |= SND_F_NBIO ;
-
- sb_reset_dsp(d->io_base);
- if (d->bd_flags & BD_F_ESS)
- sb_cmd(d->io_base, 0xc6 ); /* enable extended ESS mode */
- ask_init(d);
-
- return 0;
-}
-
-static int
-sb_dsp_close(dev_t i_dev, int flags, int mode, struct proc * p)
-{
- int unit;
- int dev;
- snddev_info *d;
- u_long s;
-
- dev = minor(i_dev);
- unit = dev >> 4 ;
- d = &pcm_info[unit] ;
-
- s = spltty();
- d->flags |= SND_F_CLOSING ;
- splx(s);
- snd_flush(d);
-
- sb_cmd(d->io_base, DSP_CMD_SPKOFF ); /* XXX useless ? */
-
- d->flags = 0 ;
- return 0 ;
-}
-
-static int
-sb_dsp_ioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct proc * p)
-{
- int unit;
- int dev;
- snddev_info *d;
-
- dev = minor(i_dev);
- unit = dev >> 4 ;
- d = &pcm_info[unit] ;
-
- /*
- * handle mixer calls first. Reads are in the default handler,
- * so do not bother about them.
- */
- if ( (cmd & MIXER_WRITE(0)) == MIXER_WRITE(0) )
- return sb_mixer_set(d, cmd & 0xff, *(int *)arg) ;
-
- /*
- * for the remaining functions, use the default handler.
- * ENOSYS means that the default handler should take care
- * of implementing the ioctl.
- */
-
- return ENOSYS ;
-}
-
-static void
-sb_intr(int unit)
-{
- snddev_info *d = &pcm_info[unit];
- int reason = 3, c=1, io_base = d->io_base;
-
- DEB(printf("got sb_intr for unit %d, flags 0x%08lx\n", unit, d->flags));
-
- /*
- * SB < 4.0 is half duplex and has only 1 bit for int source,
- * so we fake it. SB 4.x (SB16) has the int source in a separate
- * register.
- * The Vibra16X has separate flags for 8 and 16 bit transfers, but
- * I have no idea how to tell capture from playback interrupts...
- */
-#define PLAIN_SB16(x) ( ( (x) & (BD_F_SB16|BD_F_SB16X) ) == BD_F_SB16)
-again:
- if (d->bd_flags & BD_F_SB16) {
- c = sb_getmixer(io_base, IRQ_STAT);
- /* this tells us if the source is 8-bit or 16-bit dma. We
- * have to check the io channel to map it to read or write...
- */
- reason = 0 ;
- if ( c & 1 ) { /* 8-bit dma */
- if (d->play_fmt == AFMT_U8 || d->play_fmt == AFMT_MU_LAW )
- reason |= 1;
- if (d->rec_fmt == AFMT_U8 || d->rec_fmt == AFMT_MU_LAW )
- reason |= 2;
- }
- if ( c & 2 ) { /* 16-bit dma */
- if (d->play_fmt == AFMT_S16_LE)
- reason |= 1;
- if (d->rec_fmt == AFMT_S16_LE)
- reason |= 2;
- }
- }
- /* XXX previous location of ack... */
- DEB(printf("sb_intr, flags 0x%08lx reason %d c 0x%x\n",
- d->flags, reason, c));
- if ( reason & 1 ) { /* possibly a write interrupt */
- if ( d->dbuf_out.dl )
- dsp_wrintr(d);
- }
- if ( reason & 2 ) {
- if ( d->dbuf_in.dl )
- dsp_rdintr(d);
- }
- if ( c & 2 )
- inb(DSP_DATA_AVL16); /* 16-bit int ack */
- if (c & 1)
- inb(DSP_DATA_AVAIL); /* 8-bit int ack */
-
- /*
- * the sb16 might have multiple sources etc.
- */
- if ((d->bd_flags & BD_F_SB16) && (c & 3))
- goto again;
-}
-
-/*
- * device-specific function called back from the dma module.
- * The reason of the callback is the second argument.
- * NOTE: during operations, some ioctl can be called to change
- * settings (e.g. speed, channels, format), and the default
- * ioctl handler will just record the change and set the
- * flag SND_F_INIT. The callback routine is in charge of applying
- * the changes at the next convenient time (typically, at the
- * start of operations). For full duplex devices, in some cases the
- * init requires both channels to be idle.
- */
-static int
-sb_callback(snddev_info *d, int reason)
-{
- int rd = reason & SND_CB_RD ;
- snd_dbuf *b = (rd) ? & (d->dbuf_in) : & (d->dbuf_out) ;
- int l = b->dl ;
-
- switch (reason & SND_CB_REASON_MASK) {
- case SND_CB_INIT : /* called with int enabled and no pending io */
- /*
- * set the speed
- */
- dsp_speed(d);
- /*
- * set the desired DMA blocksize (influences select behaviour)
- */
- snd_set_blocksize(d);
- /*
- * since native mulaw is not present, emulate it.
- */
- if ( (d->play_fmt & AFMT_MU_LAW) || (d->rec_fmt & AFMT_MU_LAW) )
- d->flags |= SND_F_XLAT8 ;
- else
- d->flags &= ~SND_F_XLAT8 ;
-
- /*
- * there are too many flavours of SB for my taste... here i try to do
- * the proper initialization for each one.
- */
- if (PLAIN_SB16(d->bd_flags)) {
-
- /* the original SB16 (non-PnP, or PnP, or Vibra16C)
- * can do full duplex using one 16-bit channel
- * and one 8-bit channel. It needs to be programmed to
- * use split format though.
- * I DON'T do this for the Vibra16X because I have no idea
- * of what needs to be done there...
- *
- * I use the following algorithm:
- * 1. check which direction(s) are active;
- * 2. check if we should swap dma channels
- * 3. check if we can do the swap.
- */
- int swap = 1 ; /* default... */
-
- if (d->play_fmt == 0) {
- /* do whatever the read channel wants */
- if ( d->rec_fmt == AFMT_S16_LE && d->dbuf_in.chan > 4 )
- swap = 0;
- if ( d->rec_fmt != AFMT_S16_LE && d->dbuf_in.chan < 4 )
- swap = 0;
- } else {
- /* privilege the write channel */
- if ( d->play_fmt == AFMT_S16_LE && d->dbuf_out.chan > 4 )
- swap = 0;
- if ( d->play_fmt != AFMT_S16_LE && d->dbuf_out.chan < 4 )
- swap = 0;
- if ( d->rec_fmt ) {
- /* check for possible config errors.
- * This cannot happen at open time since even in
- * case of opening rw we privilege the play
- * channel.
- */
- if (d->rec_fmt == d->play_fmt) {
- DDB(printf("sorry, read DMA channel unavailable\n"));
- }
- }
- }
- DEB(printf("sb16: play_fmt %d, rec_fmt %x, swap %d\n",
- d->play_fmt, d->rec_fmt, swap);)
- if (swap) {
- int c = d->dbuf_in.chan ;
- d->dbuf_in.chan = d->dbuf_out.chan;
- d->dbuf_out.chan = c ;
- }
- }
- else if (d->bd_flags & BD_F_ESS) {
- u_char c;
-
- DEB(printf("SND_CB_INIT, play_fmt == 0x%x, rec_fmt == 0x%x\n",
- (int) d->play_fmt, (int) d->rec_fmt));
-
- /* autoinit DMA mode */
- if (d->play_fmt)
- ess_write(d->io_base, 0xb8, 0x04);
- else
- ess_write(d->io_base, 0xb8, 0x0e);
-
- c = (ess_read(d->io_base, 0xa8) & ~0x03) | 0x01;
- if ((d->flags & SND_F_STEREO) == 0)
- c++;
- ess_write(d->io_base, 0xa8, c); /* select mono/stereo */
- ess_write(d->io_base, 0xb9, 2); /* demand 4 bytes/transfer */
-
- switch (d->play_fmt ? d->play_fmt : d->rec_fmt) {
- case AFMT_S16_LE:
- if (d->flags & SND_F_STEREO) {
- /* 16 bit stereo */
- if (d->play_fmt)
- ess_write(d->io_base, 0xb6, 0x00);
- ess_write(d->io_base, 0xb7, 0x71);
- ess_write(d->io_base, 0xb7, 0xbc);
- }
- else {
- /* 16 bit mono */
- if (d->play_fmt)
- ess_write(d->io_base, 0xb6, 0x00);
- ess_write(d->io_base, 0xb7, 0x71);
- ess_write(d->io_base, 0xb7, 0xf4);
- }
- break;
- case AFMT_U8:
- if (d->flags & SND_F_STEREO) {
- /* 8 bit stereo */
- if (d->play_fmt)
- ess_write(d->io_base, 0xb6, 0x80);
- ess_write(d->io_base, 0xb7, 0x51);
- ess_write(d->io_base, 0xb7, 0x98);
- }
- else {
- /* 8 bit mono */
- if (d->play_fmt)
- ess_write(d->io_base, 0xb6, 0x80);
- ess_write(d->io_base, 0xb7, 0x51);
- ess_write(d->io_base, 0xb7, 0xd0);
- }
- break;
- }
- ess_write(d->io_base, 0xb1,
- ess_read(d->io_base, 0xb1) | 0x50);
- ess_write(d->io_base, 0xb2,
- ess_read(d->io_base, 0xb1) | 0x50);
- }
- reset_dbuf(& (d->dbuf_in), SND_CHAN_RD );
- reset_dbuf(& (d->dbuf_out), SND_CHAN_WR );
- break ;
-
- case SND_CB_START : /* called with int disabled */
- if (d->bd_flags & BD_F_SB16) {
- u_char c, c1 ;
-
- if (d->bd_flags & BD_F_SB16X) {
- /* just a guess: on the Vibra16X, the first
- * op started takes the first dma channel,
- * the second one takes the next...
- * The default is to be ready for play.
- */
- DEB(printf("start %s -- now dma %d:%d\n",
- rd ? "rd" : "wr",
- d->dbuf_out.chan, d->dbuf_in.chan););
- /* swap only if both channels are idle
- * play: dl=0, since there is no pause;
- * rec: rl=0
- */
- if ( rd && d->dbuf_out.dl == 0 && d->dbuf_in.rl == 0 ) {
- /* must swap channels, but also save dl */
- int c = d->dbuf_in.chan ;
- int dl = d->dbuf_in.dl ;
- d->dbuf_in.chan = d->dbuf_out.chan;
- d->dbuf_out.chan = c ;
- reset_dbuf(& (d->dbuf_in), SND_CHAN_RD );
- reset_dbuf(& (d->dbuf_out), SND_CHAN_WR );
- d->dbuf_in.dl = dl ;
- printf("swapped -- now dma %d:%d\n",
- d->dbuf_out.chan, d->dbuf_in.chan);
- }
- }
-
- /*
- * XXX note: c1 and l should be set basing on d->rec_fmt,
- * but there is no choice once a 16 or 8-bit channel
- * is assigned. This means that if the application
- * tries to use a bad format, the sound will not be nice.
- */
- if ( b->chan > 4
- || (rd && d->rec_fmt == AFMT_S16_LE)
- || (!rd && d->play_fmt == AFMT_S16_LE)
- ) {
- c = DSP_F16_AUTO | DSP_F16_FIFO_ON | DSP_DMA16 ;
- c1 = DSP_F16_SIGNED ;
- l /= 2 ;
- } else {
- c = DSP_F16_AUTO | DSP_F16_FIFO_ON | DSP_DMA8 ;
- c1 = 0 ;
- }
- c |= (rd) ? DSP_F16_ADC : DSP_F16_DAC ;
- if (d->flags & SND_F_STEREO)
- c1 |= DSP_F16_STEREO ;
-
- sb_cmd(d->io_base, c );
- sb_cmd3(d->io_base, c1 , l - 1) ;
- } else if (d->bd_flags & BD_F_ESS) {
- u_long fmt = rd ? d->rec_fmt : d->play_fmt;
-
- DEB(printf("SND_CB_START: %s (%d)\n", rd ? "rd" : "wr", l));
- if (fmt == AFMT_S16_LE)
- l >>= 1;
- l--;
- if (!rd)
- sb_cmd(d->io_base, DSP_CMD_SPKON);
- ess_write(d->io_base, 0xa4, l);
- ess_write(d->io_base, 0xa5, l >> 8);
- ess_write(d->io_base, 0xb8,
- ess_read(d->io_base, 0xb8) | (rd ? 0x0f : 0x05));
- } else { /* SBPro -- stereo not supported */
- u_char c ;
- if (!rd)
- sb_cmd(d->io_base, DSP_CMD_SPKON);
- /* code for the SB2 and SB3, only MONO */
- if (d->bd_flags & BD_F_HISPEED)
- c = (rd) ? 0x98 : 0x90 ;
- else
- c = (rd) ? 0x2c : 0x1c ;
- if (d->flags & SND_F_STEREO)
- sb_setmixer(d->io_base, 0xe, 2 );
- else
- sb_setmixer(d->io_base, 0xe, 0 );
- /*
- * some ESS extensions -- they can do 16 bits
- */
- if ( (rd && d->rec_fmt == AFMT_S16_LE) ||
- (!rd && d->play_fmt == AFMT_S16_LE) ) {
- c |= 1;
- l /= 2 ;
- }
- sb_cmd3(d->io_base, 0x48 , l - 1) ;
- sb_cmd(d->io_base, c ) ;
- }
- break;
-
- case SND_CB_ABORT : /* XXX */
- case SND_CB_STOP :
- {
- int cmd = DSP_CMD_DMAPAUSE_8 ; /* default: halt 8 bit chan */
- DEB(printf("SND_CB_XXX: reason 0x%x\n", reason));
- if ( b->chan > 4
- || (rd && d->rec_fmt == AFMT_S16_LE)
- || (!rd && d->play_fmt == AFMT_S16_LE)
- )
- cmd = DSP_CMD_DMAPAUSE_16 ;
- if (d->bd_flags & BD_F_HISPEED) {
- sb_reset_dsp(d->io_base);
- if (d->bd_flags & BD_F_ESS)
- sb_cmd(d->io_base, 0xc6 ); /* enable extended ESS mode */
- d->flags |= SND_F_INIT ;
- } else {
- sb_cmd(d->io_base, cmd); /* pause dma. */
- /*
- * The above seems to have the undocumented side effect of
- * blocking the other side as well. If the other
- * channel was active (SB16) I have to re-enable it :(
- */
- if ( (rd && d->dbuf_out.dl) ||
- (!rd && d->dbuf_in.dl) )
- sb_cmd(d->io_base, cmd == DSP_CMD_DMAPAUSE_8 ?
- 0xd6 : 0xd4); /* continue other dma */
- }
- if (d->bd_flags & BD_F_SB16X) {
- /* restore possible swapped channels.
- * The default is to be ready for play.
- * XXX right now, it kills all input on overflow
- */
- if ( rd && d->dbuf_out.dl == 0 ) {
- /* must swap channels ? */
- int c = d->dbuf_in.chan ;
- d->dbuf_in.chan = d->dbuf_out.chan;
- d->dbuf_out.chan = c ;
- reset_dbuf(& (d->dbuf_in), SND_CHAN_RD );
- reset_dbuf(& (d->dbuf_out), SND_CHAN_WR );
- printf("restored -- now dma %d:%d\n",
- d->dbuf_out.chan, d->dbuf_in.chan);
- }
- }
- }
- DEB( sb_cmd(d->io_base, DSP_CMD_SPKOFF) ); /* speaker off */
- break ;
-
- }
- return 0 ;
-}
-
-/*
- * The second part of the file contains all functions specific to
- * the board and (usually) not exported to other modules.
- */
-
-int
-sb_reset_dsp(int io_base)
-{
- int loopc;
-
- outb(io_base + SBDSP_RST, 3);
- DELAY(100);
- outb(io_base + SBDSP_RST, 0);
- for (loopc = 0; loopc<100 && !(inb(DSP_DATA_AVAIL) & 0x80); loopc++)
- DELAY(30);
-
- if (inb(DSP_READ) != 0xAA) {
- DEB(printf("sb_reset_dsp 0x%x failed\n", io_base));
- return 0; /* Sorry */
- }
- return 1;
-}
-
-/*
- * only used in sb_attach from here.
- */
-
-static void
-sb_dsp_init(snddev_info *d, struct isa_device *dev)
-{
- int i, x;
- char *fmt = NULL ;
- int io_base = dev->id_iobase ;
-
- d->bd_id = 0 ;
-
- sb_reset_dsp(io_base);
- sb_cmd(io_base, 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 ( (d->bd_id & 0xff00) == 0)
- d->bd_id = inb(DSP_READ) << 8; /* major */
- else {
- d->bd_id |= inb(DSP_READ); /* minor */
- break;
- }
- } else
- DELAY(20);
- }
-
- /*
- * now do various initializations depending on board id.
- */
-
- fmt = "SoundBlaster %d.%d" ; /* default */
-
- switch ( d->bd_id >> 8 ) {
- case 0 :
- printf("\n\nFailed to get SB version (%x) - possible I/O conflict\n\n",
- inb(DSP_DATA_AVAIL));
- d->bd_id = 0x100;
- case 1 : /* old sound blaster has nothing... */
- break ;
-
- case 2 :
- d->dbuf_in.chan = d->dbuf_out.chan ; /* half duplex */
- d->bd_flags |= BD_F_DUP_MIDI ;
-
- if (d->bd_id == 0x200)
- break ; /* no mixer on the 2.0 */
- d->bd_flags &= ~BD_F_MIX_MASK ;
- d->bd_flags |= BD_F_MIX_CT1335 ;
-
- break ;
- case 4 :
- fmt = "SoundBlaster 16 %d.%d";
- d->audio_fmt |= AFMT_FULLDUPLEX | AFMT_WEIRD | AFMT_S8 | AFMT_S16_LE;
- d->bd_flags |= BD_F_SB16;
- d->bd_flags &= ~BD_F_MIX_MASK ;
- d->bd_flags |= BD_F_MIX_CT1745 ;
-
- /* soft irq/dma configuration */
- x = -1 ;
- if (d->irq == 5) x = 2;
- else if (d->irq == 7) x = 4;
- else if (d->irq == 9) x = 1;
- else if (d->irq == 10) x = 8;
- if (x == -1)
- printf("<%s>%d: bad irq %d (only 5,7,9,10 allowed)\n",
- d->name, dev->id_unit, d->irq);
- else
- sb_setmixer(io_base, IRQ_NR, x);
- if (d->dbuf_out.chan == d->dbuf_in.chan) {
- printf("WARNING: sb: misconfigured secondary DMA channel\n");
- }
- sb_setmixer(io_base, DMA_NR, (1 << d->dbuf_out.chan) | (1 << d->dbuf_in.chan));
- break ;
-
- case 3 :
- d->dbuf_in.chan = d->dbuf_out.chan ; /* half duplex */
- fmt = "SoundBlaster Pro %d.%d";
- d->bd_flags |= BD_F_DUP_MIDI ;
- d->bd_flags &= ~BD_F_MIX_MASK ;
- d->bd_flags |= BD_F_MIX_CT1345 ;
- if (d->bd_id == 0x301) {
- int ess_major = 0, ess_minor = 0;
-
- /*
- * Try to detect ESS chips.
- */
-
- sb_cmd(io_base, DSP_CMD_GETID); /* Return ident. 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;
- }
- } else
- DELAY(20);
- }
-
- if (ess_major == 0x48 && (ess_minor & 0xf0) == 0x80) {
- /* the ESS488 can be treated as an SBPRO */
- printf("ESS488 (rev %d)\n", ess_minor & 0x0f);
- break ;
- }
- else if (ess_major == 0x68 && (ess_minor & 0xf0) == 0x80) {
- int rev = ess_minor & 0xf;
-
- if (rev >= 8)
- printf("ESS1868 (rev %d)\n", rev);
- else
- printf("ESS688 (rev %d)\n", rev);
- d->bd_flags |= BD_F_ESS;
- d->audio_fmt |= AFMT_S16_LE;
-
- /* enable extended ESS mode */
- sb_cmd(d->io_base, 0xc6);
- break;
- } else {
- printf("Unknown card 0x%x 0x%x -- hope it is SBPRO\n",
- ess_major, ess_minor);
- break ;
- }
- }
-
- }
-
- snprintf(d->name, sizeof(d->name),
- fmt, (d->bd_id >> 8) &0xff, d->bd_id & 0xff);
-
- sb_mix_init(d);
-}
-
-static void
-sb_mix_init(snddev_info *d)
-{
- switch (d->bd_flags & BD_F_MIX_MASK) {
- case BD_F_MIX_CT1345 : /* SB 3.0 has 1345 mixer */
-
- d->mix_devs = SBPRO_MIXER_DEVICES ;
- d->mix_rec_devs = SBPRO_RECORDING_DEVICES ;
- d->mix_recsrc = SOUND_MASK_MIC ;
-
- sb_setmixer(d->io_base, 0, 1 ); /* reset mixer */
- sb_setmixer(d->io_base, MIC_VOL , 0x6 ); /* mic volume max */
- sb_setmixer(d->io_base, RECORD_SRC , 0x0 ); /* mic source */
- sb_setmixer(d->io_base, FM_VOL , 0x0 ); /* no midi */
- break ;
-
- case BD_F_MIX_CT1745 : /* SB16 mixer ... */
-
- d->mix_devs = SB16_MIXER_DEVICES ;
- d->mix_rec_devs = SB16_RECORDING_DEVICES ;
- d->mix_recsrc = SOUND_MASK_MIC ;
- }
- sb_mixer_reset(d);
-}
-
-/*
- * Common code for the midi and pcm functions
- *
- * sb_cmd write a single byte to the CMD port.
- * sb_cmd2 write a CMD + 1 byte arg
- * sb_cmd3 write a CMD + 2 byte arg
- * sb_get_byte returns a single byte from the DSP data port
- *
- * ess_write is actually sb_cmd2
- * ess_read access ext. regs via sb_cmd(0xc0, reg) followed by sb_get_byte
- */
-
-int
-sb_cmd(int io_base, u_char val)
-{
- int i;
-
- for (i = 0; i < 1000 ; i++) {
- if ((inb(io_base + SBDSP_STATUS) & 0x80) == 0) {
- outb(io_base + SBDSP_CMD, val);
- return 1;
- }
- if (i > 10)
- DELAY (i > 100 ? 1000 : 10 );
- }
-
- printf("SoundBlaster: DSP Command(0x%02x) timeout. IRQ conflict ?\n", val);
- return 0;
-}
-
-int
-sb_cmd3(int io_base, u_char cmd, int val)
-{
- if (sb_cmd(io_base, cmd)) {
- sb_cmd(io_base, val & 0xff );
- sb_cmd(io_base, (val>>8) & 0xff );
- return 1 ;
- } else
- return 0;
-}
-
-int
-sb_cmd2(int io_base, u_char cmd, int val)
-{
- if (sb_cmd(io_base, cmd)) {
- sb_cmd(io_base, val & 0xff );
- return 1 ;
- } else
- return 0;
-}
-
-/*
- * in the SB, there is a set of indirect "mixer" registers with
- * address at offset 4, data at offset 5
- */
-void
-sb_setmixer(int io_base, u_int port, u_int value)
-{
- u_long flags;
-
- flags = spltty();
- outb(io_base + SB_MIX_ADDR, (u_char) (port & 0xff)); /* Select register */
- DELAY(10);
- outb(io_base + SB_MIX_DATA, (u_char) (value & 0xff));
- DELAY(10);
- splx(flags);
-}
-
-int
-sb_getmixer(int io_base, u_int port)
-{
- int val;
- u_long flags;
-
- flags = spltty();
- outb(io_base + SB_MIX_ADDR, (u_char) (port & 0xff)); /* Select register */
- DELAY(10);
- val = inb(io_base + SB_MIX_DATA);
- DELAY(10);
- splx(flags);
-
- return val;
-}
-
-u_int
-sb_get_byte(int io_base)
-{
- int i;
-
- for (i = 1000; i; i--)
- if (inb(DSP_DATA_AVAIL) & 0x80)
- return inb(DSP_READ);
- else
- DELAY(20);
- return 0xffff;
-}
-
-int
-ess_write(int io_base, u_char reg, int val)
-{
- return sb_cmd2(io_base, reg, val);
-}
-
-int
-ess_read(int io_base, u_char reg)
-{
- if (!sb_cmd(io_base, 0xc0) || !sb_cmd(io_base, reg) )
- return 0xffff ;
- return sb_get_byte(io_base);
-}
-
-
-/*
- * various utility functions for the DSP
- */
-
-/*
- * dsp_speed updates the speed setting from the descriptor. make sure
- * it is called at spltty().
- * Besides, it takes care of stereo setting.
- */
-static int
-dsp_speed(snddev_info *d)
-{
- u_char tconst;
- u_long flags;
- int max_speed = 44100, speed = d->play_speed ;
-
- /*
- * special code for the SB16
- */
- if (d->bd_flags & BD_F_SB16) {
- RANGE (speed, 5000, 45000);
- d->play_speed = d->rec_speed = speed ;
- sb_cmd(d->io_base, 0x41);
- sb_cmd(d->io_base, d->play_speed >> 8 );
- sb_cmd(d->io_base, d->play_speed & 0xff );
- sb_cmd(d->io_base, 0x42);
- sb_cmd(d->io_base, d->rec_speed >> 8 );
- sb_cmd(d->io_base, d->rec_speed & 0xff );
- return speed ;
- }
-
- /*
- * special code for the ESS ...
- */
- if (d->bd_flags & BD_F_ESS) {
- int t;
- RANGE (speed, 5000, 49000);
- if (speed > 22000) {
- t = (795500 + speed / 2) / speed;
- speed = (795500 + t / 2) / t ;
- t = (256 - t ) | 0x80 ;
- } else {
- t = (397700 + speed / 2) / speed;
- speed = (397700 + t / 2) / t ;
- t = 128 - t ;
- }
- ess_write(d->io_base, 0xa1, t); /* set time constant */
- d->play_speed = d->rec_speed = speed ;
- speed = (speed * 9 ) / 20 ;
- t = 256-7160000/(speed*82);
- ess_write(d->io_base,0xa2,t);
- return speed ;
- }
-
- /*
- * This is code for the SB3.x and lower.
- * Only some models can do stereo, and only if not
- * simultaneously using midi.
- * At the moment we do not support either...
- */
-#if 0
- d->flags &= ~SND_F_STEREO;
-#endif
-
- /*
- * here enforce speed limitations.
- */
- if (d->bd_id <= 0x200)
- max_speed = 22050; /* max 22050 on SB 1.X */
-
- /*
- * SB models earlier than SB Pro have low limit for the
- * input rate. Note that this is only for input, but since
- * we do not support separate values for rec & play....
- */
- if (d->bd_id <= 0x200)
- max_speed = 13000;
- else if (d->bd_id < 0x300)
- max_speed = 15000;
-
- RANGE(speed, 4000, max_speed);
-
- if (d->flags & SND_F_STEREO) /* really unused right now... */
- speed *= 2;
-
- /*
- * Now the speed should be valid. Compute the value to be
- * programmed into the board.
- */
-
- if (speed > 22050) { /* High speed mode on 2.01/3.xx */
- int tmp;
-
- tconst = (u_char) ((65536 - ((256000000 + speed / 2) / speed)) >> 8) ;
- d->bd_flags |= BD_F_HISPEED ;
-
- flags = spltty();
- sb_cmd2(d->io_base, 0x40, tconst); /* set time constant */
- splx(flags);
-
- tmp = 65536 - (tconst << 8);
- speed = (256000000 + tmp / 2) / tmp;
- } else {
- int tmp;
-
- d->bd_flags &= ~BD_F_HISPEED ;
- tconst = (256 - ((1000000 + speed / 2) / speed)) & 0xff;
-
- flags = spltty();
- sb_cmd2(d->io_base, 0x40, tconst); /* set time constant */
- splx(flags);
-
- tmp = 256 - tconst;
- speed = (1000000 + tmp / 2) / tmp;
- }
-
- if (d->flags & SND_F_STEREO) /* really unused right now... */
- speed /= 2;
-
- d->play_speed = d->rec_speed = speed;
- return speed;
-}
-
-/*
- * mixer support, originally in sb_mixer.c
- */
-
-static void
-sb_set_recsrc(snddev_info *d, int mask)
-{
- u_char recdev ;
-
- mask &= d->mix_rec_devs;
- switch (d->bd_flags & BD_F_MIX_MASK) {
- case BD_F_MIX_CT1345 :
- if (mask == SOUND_MASK_LINE)
- recdev = 6 ;
- else if (mask == SOUND_MASK_CD)
- recdev = 2 ;
- else { /* default: mic */
- mask = SOUND_MASK_MIC ;
- recdev = 0 ;
- }
- sb_setmixer(d->io_base, RECORD_SRC,
- recdev | (sb_getmixer(d->io_base, RECORD_SRC) & ~7 ));
- break ;
- case BD_F_MIX_CT1745 : /* sb16 */
- if (mask == 0)
- mask = SOUND_MASK_MIC ; /* XXX For compatibility. Bug ? */
- recdev = 0 ;
- if (mask & SOUND_MASK_MIC)
- recdev |= 1 ;
- if (mask & SOUND_MASK_CD)
- recdev |= 6 ; /* l+r cd */
- if (mask & SOUND_MASK_LINE)
- recdev |= 0x18 ; /* l+r line */
- if (mask & SOUND_MASK_SYNTH)
- recdev |= 0x60 ; /* l+r midi */
- sb_setmixer(d->io_base, SB16_IMASK_L, recdev);
- sb_setmixer(d->io_base, SB16_IMASK_R, recdev);
- /*
- * since the same volume controls apply to the input and
- * output sections, the best approach to have a consistent
- * behaviour among cards would be to disable the output path
- * on devices which are used to record.
- * However, since users like to have feedback, we only disable
- * the mike -- permanently.
- */
- sb_setmixer(d->io_base, SB16_OMASK, 0x1f & ~1);
- break ;
- }
- d->mix_recsrc = mask;
-}
-
-static void
-sb_mixer_reset(snddev_info *d)
-{
- int i;
-
- for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
- sb_mixer_set(d, i, levels[i]);
- if (d->bd_flags & BD_F_SB16) {
- sb_setmixer(d->io_base, 0x3c, 0x1f); /* make all output active */
- sb_setmixer(d->io_base, 0x3d, 0); /* make all inputs-l off */
- sb_setmixer(d->io_base, 0x3e, 0); /* make all inputs-r off */
- }
- sb_set_recsrc(d, SOUND_MASK_MIC);
-}
-
-static int
-sb_mixer_set(snddev_info *d, int dev, int value)
-{
- int left = value & 0x000000ff;
- int right = (value & 0x0000ff00) >> 8;
- int regoffs;
- u_char val;
- mixer_tab *iomap;
-
-#ifdef JAZZ16
- if (d->bd_flags & BD_F_JAZZ16 && d->bd_flags & BD_F_JAZZ16_2)
- return smw_mixer_set(dev, value);
-#endif
-
- if (dev == SOUND_MIXER_RECSRC) {
- sb_set_recsrc(d, value);
- return 0 ;
- }
- if (left > 100)
- left = 100;
- if (right > 100)
- right = 100;
-
- if (dev > 31)
- return EINVAL ;
-
- if (!(d->mix_devs & (1 << dev))) /* Not supported */
- return EINVAL;
-
- switch ( d->bd_flags & BD_F_MIX_MASK ) {
- default:
- /* mixer unknown, fail... */
- return EINVAL ;/* XXX change this */
- case BD_F_MIX_CT1345 :
- iomap = &sbpro_mix ;
- break;
- case BD_F_MIX_CT1745 :
- iomap = &sb16_mix ;
- break;
- /* XXX how about the SG NX Pro, iomap = sgnxpro_mix */
- }
- regoffs = (*iomap)[dev][LEFT_CHN].regno;
- if (regoffs == 0)
- return EINVAL;
-
- val = sb_getmixer(d->io_base, regoffs);
-
- change_bits(iomap, &val, dev, LEFT_CHN, left);
-
- d->mix_levels[dev] = left | (left << 8);
-
- if ((*iomap)[dev][RIGHT_CHN].regno != regoffs) { /* Change register */
- sb_setmixer(d->io_base, regoffs, val); /* Save the old one */
- regoffs = (*iomap)[dev][RIGHT_CHN].regno;
-
- if (regoffs == 0)
- return 0 ; /* Just left channel present */
-
- val = sb_getmixer(d->io_base, regoffs); /* Read the new one */
- }
- change_bits(iomap, &val, dev, RIGHT_CHN, right);
-
- sb_setmixer(d->io_base, regoffs, val);
-
- d->mix_levels[dev] = left | (right << 8);
- return 0 ; /* ok */
-}
-
-/*
- * now support for some PnP boards.
- */
-
-#if NPNP > 0
-static char *ess1868_probe(u_long csn, u_long vend_id);
-static void ess1868_attach(u_long csn, u_long vend_id, char *name,
- struct isa_device *dev);
-
-static struct pnp_device ess1868 = {
- "ESS1868",
- ess1868_probe,
- ess1868_attach,
- &nsnd, /* use this for all sound cards */
- &tty_imask /* imask */
-};
-DATA_SET (pnpdevice_set, ess1868);
-
-static char *
-ess1868_probe(u_long csn, u_long vend_id)
-{
- /*
- * pnp X 1 os enable drq0 3 irq0 12 port0 0x240
- */
- if (vend_id == 0x68187316) {
- struct pnp_cinfo d ;
- read_pnp_parms ( &d , 1 ) ;
- if (d.enable == 0) {
- printf("This is an ESS1868, but LDN 1 is disabled\n");
- return NULL;
- }
- return "ESS1868" ;
- }
- return NULL ;
-}
-
-static void
-ess1868_attach(u_long csn, u_long vend_id, char *name,
- struct isa_device *dev)
-{
- struct pnp_cinfo d ;
- snddev_info tmp_d ; /* patched copy of the basic snddev_info */
-
- tmp_d = sb_op_desc;
- snddev_last_probed = &tmp_d;
-
-#if 0
- read_pnp_parms ( &d , 3 ); /* disable LDN 3 */
- d.port[0] = 0 ;
- d.enable = 0 ;
- write_pnp_parms ( &d , 3 );
-
- read_pnp_parms ( &d , 2 ); /* disable LDN 2 */
- d.port[0] = 0 ;
- d.enable = 0 ;
- write_pnp_parms ( &d , 2 );
- read_pnp_parms ( &d , 0 ); /* read config base */
- tmp_d.conf_base = d.port[0];
- write_pnp_parms ( &d , 0 );
-#endif
-
- read_pnp_parms ( &d , 1 ) ;
- dev->id_iobase = d.port[0];
- d.port[1] = 0 ;
- d.port[2] = 0 ;
- write_pnp_parms ( &d , 1 );
- enable_pnp_card();
-
- dev->id_drq = d.drq[0] ; /* primary dma */
- dev->id_irq = (1 << d.irq[0] ) ;
- dev->id_intr = (inthand2_t *)pcmintr ;
- dev->id_flags = 0 /* DV_F_DUAL_DMA | (d.drq[1] ) */;
-
-#if 0
- snddev_last_probed->probe(dev); /* not really necessary but doesn't harm */
-#endif
- pcmattach(dev);
-}
-
-/*
- * A driver for some SB16pnp and compatibles...
- *
- * Avance Asound 100 -- 0x01009305
- * Avance Logic ALS100+ -- 0x10019305
- * Avance Logic ASound Gold ALS120 -- 0x20019305
- * xxx -- 0x2b008c0e
- *
- */
-
-static char *sb16pnp_probe(u_long csn, u_long vend_id);
-static void sb16pnp_attach(u_long csn, u_long vend_id, char *name,
- struct isa_device *dev);
-
-static struct pnp_device sb16pnp = {
- "SB16pnp",
- sb16pnp_probe,
- sb16pnp_attach,
- &nsnd, /* use this for all sound cards */
- &tty_imask /* imask */
-};
-DATA_SET (pnpdevice_set, sb16pnp);
-
-static char *
-sb16pnp_probe(u_long csn, u_long vend_id)
-{
- char *s = NULL ;
-
- /*
- * The SB16/AWExx cards seem to differ in the fourth byte of
- * the vendor id, so I have just masked it for the time being...
- * Reported values are:
- * SB16 Value PnP: 0x2b008c0e
- * SB AWExx PnP: 0x39008c0e 0x9d008c0e 0xc3008c0e
- * Vibra16X: 0xf0008c0e
- */
- if (vend_id == 0xf0008c0e)
- s = "Vibra16X" ;
- else if ( (vend_id & 0xffffff) == (0x9d008c0e & 0xffffff) )
- s = "SB16 PnP";
- else if (vend_id == 0x01009305)
- s = "Avance Asound 100" ;
- else if (vend_id == 0x10019305)
- s = "Avance Logic 100+" ; /* Vibra16X-class */
- else if (vend_id == 0x20019305)
- s = "Avance Logic ALS120" ; /* Vibra16X-class */
- if (s) {
- struct pnp_cinfo d;
- read_pnp_parms(&d, 0);
- if (d.enable == 0) {
- printf("This is a %s, but LDN 0 is disabled\n", s);
- return NULL ;
- }
- return s ;
- }
- return NULL ;
-}
-
-static void
-sb16pnp_attach(u_long csn, u_long vend_id, char *name,
- struct isa_device *dev)
-{
- struct pnp_cinfo d ;
- snddev_info tmp_d ; /* patched copy of the basic snddev_info */
-
- tmp_d = sb_op_desc;
- snddev_last_probed = &tmp_d;
-
- read_pnp_parms ( &d , 0 ) ;
- d.port[1] = 0 ; /* only the first address is used */
- dev->id_iobase = d.port[0];
- tmp_d.synth_base = d.port[2];
- write_pnp_parms ( &d , 0 );
- enable_pnp_card();
-
- dev->id_drq = d.drq[0] ; /* primary dma */
- dev->id_irq = (1 << d.irq[0] ) ;
- dev->id_intr = (inthand2_t *)pcmintr ;
- dev->id_flags = DV_F_DUAL_DMA | (d.drq[1] ) ;
-
- pcm_info[dev->id_unit] = tmp_d; /* pcm_info[] will be reinitialized after */
- snddev_last_probed->probe(dev); /* not really necessary but doesn't harm */
-
- if (vend_id == 0x10019305 || vend_id == 0xf0008c0e
- || vend_id == 0x20019305) {
- /*
- * XXX please add here the vend_id for other vibra16X cards...
- * And remember, must change tmp_d, not
- */
- tmp_d.bd_flags |= BD_F_SB16X ;
- }
- pcmattach(dev);
-}
-#endif /* NPNP */
-
-#endif
diff --git a/sys/i386/isa/snd/sbcard.h b/sys/i386/isa/snd/sbcard.h
deleted file mode 100644
index b05b365..0000000
--- a/sys/i386/isa/snd/sbcard.h
+++ /dev/null
@@ -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 */
-
-
diff --git a/sys/i386/isa/snd/sound.c b/sys/i386/isa/snd/sound.c
deleted file mode 100644
index bf980fd..0000000
--- a/sys/i386/isa/snd/sound.c
+++ /dev/null
@@ -1,1496 +0,0 @@
-/*
- * snd/sound.c
- *
- * Main sound driver for FreeBSD. This file provides the main
- * entry points for probe/attach and all i/o demultiplexing, including
- * default routines for generic devices.
- *
- * (C) 1997 Luigi Rizzo (luigi@iet.unipi.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.
- *
- *
- * For each card type a template "snddev_info" structure contains
- * all the relevant parameters, both for configuration and runtime.
- *
- * In this file we build tables of pointers to the descriptors for
- * the various supported cards. The generic probe routine scans
- * the table(s) looking for a matching entry, then invokes the
- * board-specific probe routine. If successful, a pointer to the
- * correct snddev_info is stored in snddev_last_probed, for subsequent
- * use in the attach routine. The generic attach routine copies
- * the template to a permanent descriptor (pcm_info[unit] and
- * friends), initializes all generic parameters, and calls the
- * board-specific attach routine.
- *
- * On device calls, the generic routines do the checks on unit and
- * device parameters, then call the board-specific routines if
- * available, or try to perform the task using the default code.
- *
- * $FreeBSD$
- *
- */
-
-#include <i386/isa/snd/sound.h>
-
-
-#if NPCM > 0 /* from "pcm.h" via disgusting #include in snd/sound.h */
-
-extern struct isa_driver pcmdriver ;
-#define SNDSTAT_BUF_SIZE 4000
-static char status_buf[SNDSTAT_BUF_SIZE] ;
-static int status_len = 0 ;
-static void init_status(snddev_info *d);
-
-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_mmap_t sndmmap;
-
-#define CDEV_MAJOR 30
-static struct cdevsw snd_cdevsw = {
- /* open */ sndopen,
- /* close */ sndclose,
- /* read */ sndread,
- /* write */ sndwrite,
- /* ioctl */ sndioctl,
- /* poll */ sndselect,
- /* mmap */ sndmmap,
- /* strategy */ nostrategy,
- /* name */ "snd",
- /* maj */ CDEV_MAJOR,
- /* dump */ nodump,
- /* psize */ nopsize,
- /* flags */ 0,
- /* bmaj */ -1
-};
-
-/*
- * descriptors for active devices.
- *
- */
-snddev_info pcm_info[NPCM_MAX] ;
-snddev_info midi_info[NPCM_MAX] ;
-snddev_info synth_info[NPCM_MAX] ;
-
-u_long nsnd = NPCM ; /* total number of sound devices */
-
-/*
- * Hooks for APM support, but code not operational yet.
- */
-
-#include "apm.h"
-#include <i386/include/apm_bios.h>
-#if NAPM > 0
-
-static int
-sound_suspend(void *arg)
-{
- /*
- * I think i can safely do nothing here and
- * reserve all the work for wakeup time
- */
- printf("Called APM sound suspend hook for unit %d\n", (int)arg);
- return 0 ;
-}
-
-static int
-sound_resume(void *arg)
-{
- snddev_info *d = NULL ;
-
- d = &pcm_info[(int)arg] ;
- /*
- * reinitialize card registers.
- * Flush buffers and reinitialize DMA channels.
- * If a write was pending, pretend it is done
- * (and issue any wakeup we need).
- * If a read is pending, restart it.
- */
- if (d->bd_id == MD_YM0020) {
- DDB(printf("setting up yamaha registers\n"));
- outb(0x370, 6 /* dma config */ ) ;
- if (FULL_DUPLEX(d))
- outb(0x371, 0xa9 ); /* use both dma chans */
- else
- outb(0x371, 0x8b ); /* use low dma chan */
- }
- printf("Called APM sound resume hook for unit %d\n", (int)arg);
- return 0 ;
-}
-
-static void
-init_sound_apm(int unit)
-{
- struct apmhook *ap;
-
- ap = malloc(sizeof *ap, M_DEVBUF, M_NOWAIT);
- bzero(ap, sizeof *ap);
-
- ap->ah_fun = sound_resume;
- ap->ah_arg = (void *)unit;
- ap->ah_name = "pcm resume handler";
- ap->ah_order = APM_MID_ORDER;
- apm_hook_establish(APM_HOOK_RESUME, ap);
-
- ap = malloc(sizeof *ap, M_DEVBUF, M_NOWAIT);
- bzero(ap, sizeof *ap);
-
- ap->ah_fun = sound_suspend;
- ap->ah_arg = (void *)unit;
- ap->ah_name = "pcm suspend handler";
- ap->ah_order = APM_MID_ORDER;
- apm_hook_establish(APM_HOOK_SUSPEND, ap);
-}
-#endif /* NAPM */
-
-/*
- * the probe routine can only return an int to the upper layer. Hence,
- * it leaves the pointer to the last successfully
- * probed device descriptor in snddev_last_probed
- */
-snddev_info *snddev_last_probed = NULL ;
-
-static snddev_info *
-generic_snd_probe(struct isa_device * dev, snddev_info **p[], char *s);
-
-/*
- * here are the lists of known cards. Similar cards (e.g. all
- * sb clones, all mss clones, ... are in the same array.
- * All lists of devices of the same type (eg. all pcm, all midi...)
- * are in the same array.
- * Each probe for a device type gets the pointer to the main array
- * and then scans the sublists.
- *
- * XXX should use DATA_SET to create a linker set for sb_devs and other
- * such structures.
- */
-
-extern snddev_info sb_op_desc;
-extern snddev_info mss_op_desc;
-
-static snddev_info *sb_devs[] = { /* all SB clones */
- &sb_op_desc,
- NULL,
-} ;
-
-static snddev_info *mss_devs[] = { /* all MSS clones */
- &mss_op_desc,
- NULL,
-} ;
-
-static snddev_info **pcm_devslist[] = { /* all pcm devices */
- mss_devs,
- sb_devs,
- NULL
-} ;
-
-
-int
-pcmprobe(struct isa_device * dev)
-{
- bzero(&pcm_info[dev->id_unit], sizeof(pcm_info[dev->id_unit]) );
- return generic_snd_probe(dev, pcm_devslist, "pcm") ? 1 : 0 ;
-}
-
-static snddev_info **midi_devslist[] = {/* all midi devices */
- NULL
-} ;
-
-int
-midiprobe(struct isa_device * dev)
-{
- bzero(&midi_info[dev->id_unit], sizeof(midi_info[dev->id_unit]) );
- return 0 ;
- return generic_snd_probe(dev, midi_devslist, "midi") ? 1 : 0 ;
-}
-
-int
-synthprobe(struct isa_device * dev)
-{
- bzero(&synth_info[dev->id_unit], sizeof(synth_info[dev->id_unit]) );
- return 0 ;
-}
-
-/*
- * this is the ISA part of the generic attach routine
- */
-
-int
-pcmattach(struct isa_device * dev)
-{
- snddev_info *d = NULL ;
- int stat = 0;
-
- dev->id_ointr = pcmintr;
-
- if ( (dev->id_unit >= NPCM_MAX) || /* too many devs */
- (snddev_last_probed == NULL) || /* last probe failed */
- (snddev_last_probed->attach==NULL) ) /* no attach routine */
- return 0 ; /* fail */
-
- /*
- * default initialization: copy generic parameters for the routine,
- * initialize from the isa_device structure, and allocate memory.
- * If everything succeeds, then call the attach routine for
- * further initialization.
- */
- pcm_info[dev->id_unit] = *snddev_last_probed ;
- d = &pcm_info[dev->id_unit] ;
-
- d->io_base = dev->id_iobase ;
- d->irq = ffs(dev->id_irq) - 1 ;
- d->dbuf_out.chan = dev->id_drq ;
- if (dev->id_flags != -1 && dev->id_flags & DV_F_DUAL_DMA &&
- (dev->id_flags & DV_F_DRQ_MASK) != 4 ) /* enable dma2 */
- d->dbuf_in.chan = dev->id_flags & DV_F_DRQ_MASK ;
- else
- d->dbuf_in.chan = d->dbuf_out.chan ;
-#if 1 /* does this cause trouble with PnP cards ? */
- if (d->bd_id == 0)
- d->bd_id = (dev->id_flags & DV_F_DEV_MASK) >> DV_F_DEV_SHIFT ;
-#endif
- d->status_ptr = 0;
-
- /*
- * Allocates memory and initializes the dma structs properly. We
- * use independent buffers for each channel. For the time being,
- * this is done independently of the dma setting. In future
- * revisions, if we see that we have a single dma, we might decide
- * to use a single buffer to save memory.
- */
- alloc_dbuf( &(d->dbuf_out), d->bufsize );
- alloc_dbuf( &(d->dbuf_in), d->bufsize );
-
- isa_dma_acquire(d->dbuf_out.chan);
- if (FULL_DUPLEX(d))
- isa_dma_acquire(d->dbuf_in.chan);
-
-
- /*
- * should try and find a suitable value for id_id, otherwise
- * the interrupt is not registered and dispatched properly.
- * This is important for PnP devices, where "dev" is built on
- * the fly and many field are not initialized.
- */
- if (dev->id_driver == NULL) {
- dev->id_driver = &pcmdriver ;
- dev->id_id = isa_compat_nextid();
- }
-
- /*
- * call the generic part of the attach
- */
- pcminit(d, dev->id_unit);
- /*
- * and finally, call the device attach routine
- * XXX I should probably use d->attach(dev)
- */
- stat = snddev_last_probed->attach(dev);
-#if 0
- /*
- * XXX hooks for synt support. Try probe and attach...
- */
- if (d->synth_base && opl3_probe(dev) ) {
- opl3_attach(dev);
- }
-#endif
- snddev_last_probed = NULL ;
-
- return stat ;
-}
-
-/*
- * This is the generic init routine
- */
-int
-pcminit(snddev_info *d, int unit)
-{
- cdevsw_add(&snd_cdevsw);
-
- /*
- * initialize standard parameters for the device. This can be
- * overridden by device-specific configurations but better do
- * here the generic things.
- */
-
- d->magic = MAGIC(unit); /* debugging... */
- d->play_speed = d->rec_speed = 8000 ;
- d->play_blocksize = d->rec_blocksize = 2048 ;
- d->play_fmt = d->rec_fmt = AFMT_MU_LAW ;
-
-#ifndef GID_GAMES
-#define GID_SND UID_ROOT
-#else
-#define GID_SND GID_GAMES /* i am not really sure this is a good one. */
-#endif
-#define UID_SND UID_ROOT
-#define PERM_SND 0660
- /*
- * Make links to first successfully probed unit.
- * Attempts by later devices to make these links will fail.
- */
- make_dev(&snd_cdevsw, (unit << 4) | SND_DEV_DSP,
- UID_SND, GID_SND, PERM_SND, "dsp%r", unit);
- make_dev(&snd_cdevsw, (unit << 4) | SND_DEV_DSP16,
- UID_SND, GID_SND, PERM_SND, "dspW%r", unit);
- make_dev(&snd_cdevsw, (unit << 4) | SND_DEV_AUDIO,
- UID_SND, GID_SND, PERM_SND, "audio%r", unit);
- make_dev(&snd_cdevsw, (unit << 4) | SND_DEV_CTL,
- UID_SND, GID_SND, PERM_SND, "mixer%r", unit);
- make_dev(&snd_cdevsw, (unit << 4) | SND_DEV_STATUS,
- UID_SND, GID_SND, PERM_SND, "sndstat%r", unit);
-
-#if NAPM > 0
- init_sound_apm(unit);
-#endif
- return 0 ;
-}
-
-int midiattach(struct isa_device * dev) { return 0 ; }
-int synthattach(struct isa_device * dev) { return 0 ; }
-
-struct isa_driver pcmdriver = { pcmprobe, pcmattach, "pcm" } ;
-
-struct isa_driver mididriver = { midiprobe, midiattach, "midi" } ;
-struct isa_driver synthdriver = { synthprobe, synthattach, "synth" } ;
-
-void
-pcmintr(int unit)
-{
- DEB(printf("__/\\/ pcmintr -- unit %d\n", unit));
- pcm_info[unit].interrupts++;
- if (pcm_info[unit].isr)
- pcm_info[unit].isr(unit);
-#if 0 /* these do not exist at the moment. */
- if (midi_info[unit].isr)
- midi_info[unit].isr(unit);
- if (synth_info[unit].isr)
- synth_info[unit].isr(unit);
-#endif
-}
-
-static snddev_info *
-generic_snd_probe(struct isa_device * dev, snddev_info **p[], char *s)
-{
- snddev_info **q ;
- struct isa_device saved_dev ;
-
- snddev_last_probed = NULL ;
-
- saved_dev = *dev ; /* the probe routine might alter parameters */
-
- /*
- * XXX todo: should try to match flags with device type.
- */
- for ( ; p[0] != NULL ; p++ )
- for ( q = *p ; q[0] ; q++ )
- if (q[0]->probe && q[0]->probe(dev))
- return (snddev_last_probed = q[0]) ;
- else
- *dev = saved_dev ;
-
- return NULL ;
-}
-
-
-/*
- * a small utility function which, given a device number, returns
- * a pointer to the associated snddev_info struct, and sets the unit
- * number.
- */
-static snddev_info *
-get_snddev_info(dev_t i_dev, int *unit)
-{
- int u;
- snddev_info *d = NULL ;
- int dev;
-
- dev = minor(i_dev);
- u = dev >> 4 ;
- if (unit)
- *unit = u ;
-
- if (u >= NPCM_MAX ||
- ( pcm_info[u].io_base == 0 && (dev & 0x0f) != SND_DEV_STATUS)) {
- int i;
- for (i = 0 ; i < NPCM_MAX ; i++)
- if (pcm_info[i].io_base)
- break ;
- if (i != NPCM_MAX)
- printf("pcm%d: unit not configured, perhaps you want pcm%d ?\n",
- u, i);
- else
- printf("no pcm units configured\b");
- return NULL ;
- }
- switch(dev & 0x0f) {
- case SND_DEV_CTL : /* /dev/mixer handled by pcm */
- case SND_DEV_STATUS : /* /dev/sndstat handled by pcm */
- case SND_DEV_SNDPROC : /* /dev/sndproc handled by pcm */
- case SND_DEV_DSP :
- case SND_DEV_DSP16 :
- case SND_DEV_AUDIO :
- case SND_DEV_SEQ : /* XXX when enabled... */
- d = & pcm_info[u] ;
- break ;
- case SND_DEV_SEQ2 :
- case SND_DEV_MIDIN:
- default:
- printf("unsupported subdevice %d\n", dev & 0xf);
- return NULL ;
- }
- return d ;
-}
-
-/*
- * here are the switches for the main functions. The switches do
- * all necessary checks on the device number to make sure
- * that the device is configured. They also provide some default
- * functionalities so that device-specific drivers have to deal
- * only with special cases.
- */
-
-static int
-sndopen(dev_t i_dev, int flags, int mode, struct proc * p)
-{
- int dev, unit ;
- snddev_info *d;
-
- dev = minor(i_dev);
- d = get_snddev_info(i_dev, &unit);
-
- DEB(printf("open snd%d subdev %d flags 0x%08x mode 0x%08x\n",
- unit, dev & 0xf, flags, mode));
-
- if (d == NULL)
- return (ENXIO) ;
-
- switch(dev & 0x0f) {
- case SND_DEV_SEQ: /* sequencer. Hack... */
-#if 0 /* XXX hook for opl3 support */
- if (d->synth_base)
- return opl3_open(i_dev, flags, mode, p);
- else
-#endif
- return ENXIO ;
-
- case SND_DEV_CTL : /* mixer ... */
- return 0 ; /* always succeed */
-
- case SND_DEV_STATUS : /* implemented right here */
- init_status(&pcm_info[unit]);
- d->status_ptr = 0 ;
- return 0 ;
-
- default:
- if (d->open == NULL) {
- printf("open: unit %d not configured, perhaps you want unit %d ?\n",
- unit, unit+1 );
- return (ENXIO) ;
- } else
- return d->open(i_dev, flags, mode, p);
- }
- return ENXIO ;
-}
-
-static int
-sndclose(dev_t i_dev, int flags, int mode, struct proc * p)
-{
- int dev, unit ;
- snddev_info *d;
-
- dev = minor(i_dev);
- d = get_snddev_info(i_dev, &unit);
-
- DEB(printf("close snd%d subdev %d\n", unit, dev & 0xf));
-
- if (d == NULL)
- return (ENXIO) ;
-
- switch(dev & 0xf) { /* only those for which close makes sense */
- case SND_DEV_SEQ:
-#if 0 /* XXX hook for opl3 support */
- if (d->synth_base)
- return opl3_close(i_dev, flags, mode, p);
- else
-#endif
- return ENXIO ;
-
- case SND_DEV_AUDIO :
- case SND_DEV_DSP :
- case SND_DEV_DSP16 :
- if (d->close)
- return d->close(i_dev, flags, mode, p);
- }
- return 0 ;
-}
-
-static int
-sndread(dev_t i_dev, struct uio * buf, int flag)
-{
- int ret, dev, unit;
- snddev_info *d ;
- u_long s;
-
- dev = minor(i_dev);
-
- d = get_snddev_info(i_dev, &unit);
- DEB(printf("read snd%d subdev %d flag 0x%08x\n", unit, dev & 0xf, flag));
-
- if (d == NULL)
- return ENXIO ;
-
- if ( (dev & 0x0f) == SND_DEV_STATUS ) {
- int l, c;
- u_char *p;
-
- l = buf->uio_resid;
- s=spltty();
- c = status_len - d->status_ptr ;
- if (c < 0) /* should not happen! */
- c = 0 ;
- if (c < l)
- l = c ;
- p = status_buf + d->status_ptr ;
- d->status_ptr += l ;
- splx(s);
- return uiomove(p, l, buf) ;
- }
-
- /*
- * XXX read from the ad1816 with a single DMA channel is unsupported.
- * This is really not the place for machine-dependent functions,
- * a proper device routine will be supplied in the future - luigi
- */
- if ((d->bd_id == MD_AD1816) && (!(FULL_DUPLEX(d))))
- return EIO;
-
- if (d->read) /* device-specific read */
- return d->read(i_dev, buf, flag);
-
- /*
- * the generic read routine. device-specific stuff should only
- * be in the dma-handling procedures.
- */
- s = spltty();
- if ( d->flags & SND_F_READING ) {
- /* another reader is in, deny request */
- splx(s);
- DDB(printf("read denied, another reader is in\n"));
- /*
- * sleep for a while to avoid killing the machine.
- */
- tsleep( (void *)s, PZERO, "sndar", hz ) ;
- return EBUSY ;
- }
- if ( ! FULL_DUPLEX(d) ) { /* half duplex */
- if ( d->flags & SND_F_WRITING ) {
- /* another writer is in, deny request */
- splx(s);
- DDB(printf("read denied, half duplex and a writer is in\n"));
- tsleep( (void *)s, PZERO, "sndaw", hz ) ;
- return EBUSY ;
- }
- while ( d->dbuf_out.dl ) {
- /*
- * we have a pending dma operation, post a read request
- * and wait for the write to complete.
- */
- d->flags |= SND_F_READING ;
- DEB(printf("sndread: sleeping waiting for write to end\n"));
- ret = tsleep( (caddr_t)&(d->dbuf_out),
- PRIBIO | PCATCH , "sndrdw", hz ) ;
- if (ret == ERESTART || ret == EINTR) {
- d->flags &= ~SND_F_READING ;
- splx(s);
- return EINTR ;
- }
- }
- }
- d->flags |= SND_F_READING ;
- splx(s);
-
- return dsp_read_body(d, buf);
-}
-
-static int
-sndwrite(dev_t i_dev, struct uio * buf, int flag)
-{
- int ret, dev, unit;
- snddev_info *d;
- u_long s;
-
- dev = minor(i_dev);
- d = get_snddev_info(i_dev, &unit);
-
- DEB(printf("write snd%d subdev %d flag 0x%08x\n", unit, dev & 0xf, flag));
-
- if (d == NULL)
- return (ENXIO) ;
-
- switch( dev & 0x0f) { /* only writeable devices */
- case SND_DEV_MIDIN: /* XXX is this writable ? */
- case SND_DEV_SEQ :
- case SND_DEV_SEQ2 :
- case SND_DEV_DSP :
- case SND_DEV_DSP16 :
- case SND_DEV_AUDIO :
- break ;
- default:
- return EPERM ; /* for non-writeable devices ; */
- }
- if (d->write)
- return d->write(i_dev, buf, flag);
-
- /*
- * Otherwise, use the generic write routine. device-specific
- * stuff should only be in the dma-handling procedures.
- */
-
- s = spltty();
- if ( d->flags & SND_F_WRITING ) {
- /* another writer is in, deny request */
- splx(s);
- DDB(printf("write denied, another writer is in\n"));
- tsleep( (void *)s, PZERO , "sndaw", hz ) ;
- return EBUSY ;
- }
- if ( ! FULL_DUPLEX(d) ) { /* half duplex */
- if ( d->flags & SND_F_READING ) {
- /* another reader is in, deny request */
- splx(s);
- DDB(printf("write denied, half duplex and a reader is in\n"));
- tsleep( (void *)s, PZERO, "sndar", hz ) ;
- return EBUSY ;
- }
- while ( d->dbuf_in.dl ) {
- /*
- * we have a pending read dma. Post a write request
- * and wait for the read to complete (in fact I could
- * abort the read dma...
- */
- d->flags |= SND_F_WRITING ;
- DEB(printf("sndwrite: sleeping waiting for read to end\n"));
- ret = tsleep( (caddr_t)&(d->dbuf_out),
- PRIBIO | PCATCH , "sndwr", hz ) ;
- if (ret == ERESTART || ret == EINTR) {
- d->flags &= ~SND_F_WRITING ;
- splx(s);
- return EINTR ;
- }
- }
- }
- d->flags |= SND_F_WRITING ;
- splx(s);
-
- return dsp_write_body(d, buf);
-}
-
-/*
- * generic sound ioctl. Functions of the default driver can be
- * overridden by the device-specific ioctl call.
- * If a device-specific call returns ENOSYS (Function not implemented),
- * the default driver is called. Otherwise, the returned value
- * is passed up.
- *
- * The default handler, for many parameters, sets the value in the
- * descriptor, sets SND_F_INIT, and calls the callback function with
- * reason INIT. If successful, the callback returns 1 and the caller
- * can update the parameter.
- */
-
-static int
-sndioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct proc * p)
-{
- int ret = ENOSYS, dev, unit ;
- snddev_info *d;
- u_long s;
-
- dev = minor(i_dev);
- d = get_snddev_info(i_dev, &unit);
-
- if (d == NULL)
- return (ENXIO) ;
-
- if ( (dev & 0x0f) == SND_DEV_SEQ ) {
- /* sequencer. Hack... */
-#if 0
- if (d->synth_base)
- return opl3_ioctl(i_dev, cmd, arg, mode, p) ;
- else
-#endif
- return ENXIO ;
- }
- if (d->ioctl)
- ret = d->ioctl(i_dev, cmd, arg, mode, p);
- if (ret != ENOSYS)
- return ret ;
-
- /*
- * pass control to the default ioctl handler. Set ret to 0 now.
- */
- ret = 0 ;
-
- /*
- * The linux ioctl interface for the sound driver has a thousand
- * different calls, and it is unpractical to put the names in
- * the switch(). So we have some tests before for common routines,
- * such as the ones related to the mixer. But we really ought
- * to redesign the interface!
- *
- * Reading from the mixer just requires to look at the cached
- * copy in d->mix_levels[dev], so this routine should cover
- * practically all needs for mixer reading.
- */
- if ( (cmd & MIXER_READ(0)) == MIXER_READ(0) && (cmd & 0xff) < 32 ) {
- int dev = cmd & 0x1f ;
- if ( d->mix_devs & (1<<dev) ) { /* supported */
- *(int *)arg = d->mix_levels[dev];
- return 0 ;
- } else
- return EINVAL ;
- }
-
- /*
- * all routines are called with int. blocked. Make sure that
- * ints are re-enabled when calling slow or blocking functions!
- */
- s = spltty();
- switch(cmd) {
-
- /*
- * we start with the new ioctl interface.
- */
- case AIONWRITE : /* how many bytes can write ? */
- if (d->dbuf_out.dl) {
- if (d->special_dma)
- d->callback(d, SND_CB_WR | SND_CB_DMAUPDATE) ;
- else
- dsp_wr_dmaupdate(&(d->dbuf_out));
- }
- *(int *)arg = d->dbuf_out.fl;
- break;
-
- case AIOSSIZE : /* set the current blocksize */
- {
- struct snd_size *p = (struct snd_size *)arg;
- if (p->play_size <= 1 && p->rec_size <= 1) { /* means no blocks */
- d->flags &= ~SND_F_HAS_SIZE ;
- } else {
- RANGE (p->play_size, 40, d->dbuf_out.bufsize /4);
- d->play_blocksize = p->play_size & ~3 ;
- RANGE (p->rec_size, 40, d->dbuf_in.bufsize /4);
- d->rec_blocksize = p->rec_size & ~3 ;
- d->flags |= SND_F_HAS_SIZE ;
- }
- }
- splx(s);
- ask_init(d);
- /* FALLTHROUGH */
- case AIOGSIZE : /* get the current blocksize */
- {
- struct snd_size *p = (struct snd_size *)arg;
- p->play_size = d->play_blocksize ;
- p->rec_size = d->rec_blocksize ;
- }
- break ;
-
- case AIOSFMT :
- {
- snd_chan_param *p = (snd_chan_param *)arg;
- d->play_speed = p->play_rate;
- d->rec_speed = p->play_rate; /* XXX one speed allowed */
- if (p->play_format & AFMT_STEREO)
- d->flags |= SND_F_STEREO ;
- else
- d->flags &= ~SND_F_STEREO ;
- d->play_fmt = p->play_format & ~AFMT_STEREO ;
- d->rec_fmt = p->rec_format & ~AFMT_STEREO ;
- }
- splx(s);
- if (!ask_init(d))
- break ; /* could not reinit */
- /* FALLTHROUGH */
-
- case AIOGFMT :
- {
- snd_chan_param *p = (snd_chan_param *)arg;
- p->play_rate = d->play_speed;
- p->rec_rate = d->rec_speed;
- p->play_format = d->play_fmt;
- p->rec_format = d->rec_fmt;
- if (d->flags & SND_F_STEREO) {
- p->play_format |= AFMT_STEREO ;
- p->rec_format |= AFMT_STEREO ;
- }
- }
- break;
-
- case AIOGCAP : /* get capabilities */
- /* this should really be implemented by the driver */
- {
- snd_capabilities *p = (snd_capabilities *)arg;
- p->rate_min = 5000;
- p->rate_max = 48000; /* default */
- p->bufsize = d->bufsize;
- p->formats = d->audio_fmt; /* default */
- p->mixers = 1 ; /* default: one mixer */
- p->inputs = d->mix_devs ;
- p->left = p->right = 255 ;
- }
- break ;
-
- case AIOSTOP:
- if (*(int *)arg == AIOSYNC_PLAY) /* play */
- *(int *)arg = dsp_wrabort(d, 1 /* restart */);
- else if (*(int *)arg == AIOSYNC_CAPTURE)
- *(int *)arg = dsp_rdabort(d, 1 /* restart */);
- else {
- splx(s);
- printf("AIOSTOP: bad channel 0x%x\n", *(int *)arg);
- *(int *)arg = 0 ;
- }
- break ;
-
- case AIOSYNC:
- printf("AIOSYNC chan 0x%03lx pos %lu unimplemented\n",
- ((snd_sync_parm *)arg)->chan,
- ((snd_sync_parm *)arg)->pos);
- break;
- /*
- * here follow the standard ioctls (filio.h etc.)
- */
- case FIONREAD : /* get # bytes to read */
- if ( d->dbuf_in.dl ) {
- if (d->special_dma)
- d->callback(d, SND_CB_RD | SND_CB_DMAUPDATE) ;
- else
- dsp_rd_dmaupdate(&(d->dbuf_in));
- }
- *(int *)arg = d->dbuf_in.rl;
- break;
-
- case FIOASYNC: /*set/clear async i/o */
- DEB( printf("FIOASYNC\n") ; )
- break;
-
- case SNDCTL_DSP_NONBLOCK :
- case FIONBIO : /* set/clear non-blocking i/o */
- if ( *(int *)arg == 0 )
- d->flags &= ~SND_F_NBIO ;
- else
- d->flags |= SND_F_NBIO ;
- break ;
-
- /*
- * Finally, here is the linux-compatible ioctl interface
- */
-#define THE_REAL_SNDCTL_DSP_GETBLKSIZE _IOWR('P', 4, int)
- case THE_REAL_SNDCTL_DSP_GETBLKSIZE:
- case SNDCTL_DSP_GETBLKSIZE:
- *(int *) arg = d->play_blocksize ;
- break ;
-
- case SNDCTL_DSP_SETBLKSIZE :
- {
- int t = *(int *)arg;
- if (t <= 1) { /* means no blocks */
- d->flags &= ~SND_F_HAS_SIZE ;
- } else {
- RANGE (t, 40, d->dbuf_out.bufsize /4);
- d->play_blocksize =
- d->rec_blocksize = t & ~3 ; /* align to multiple of 4 */
- d->flags |= SND_F_HAS_SIZE ;
- }
- }
- splx(s);
- ask_init(d);
- break ;
- case SNDCTL_DSP_RESET:
- DEB(printf("dsp reset\n"));
- dsp_wrabort(d, 1 /* restart */);
- dsp_rdabort(d, 1 /* restart */);
- break ;
-
- case SNDCTL_DSP_SYNC:
- DEB(printf("dsp sync\n"));
- splx(s);
- snd_sync(d, 1, d->dbuf_out.bufsize - 4); /* DMA does not start with <4 bytes */
- break ;
-
- case SNDCTL_DSP_SPEED:
- d->play_speed = d->rec_speed = *(int *)arg ;
- splx(s);
- if (ask_init(d))
- *(int *)arg = d->play_speed ;
- break ;
-
- case SNDCTL_DSP_STEREO:
- if ( *(int *)arg == 0 )
- d->flags &= ~SND_F_STEREO ; /* mono */
- else if ( *(int *)arg == 1 )
- d->flags |= SND_F_STEREO ; /* stereo */
- else {
- printf("dsp stereo: %d is invalid, assuming 1\n", *(int *)arg );
- d->flags |= SND_F_STEREO ; /* stereo */
- }
- splx(s);
- if (ask_init(d))
- *(int *)arg = (d->flags & SND_F_STEREO) ? 1 : 0 ;
- break ;
-
- case SOUND_PCM_WRITE_CHANNELS:
- if ( *(int *)arg == 1)
- d->flags &= ~SND_F_STEREO ; /* mono */
- else if ( *(int *)arg == 2)
- d->flags |= SND_F_STEREO ; /* stereo */
- else {
- ret = EINVAL ;
- break ;
- }
- splx(s);
- if (ask_init(d))
- *(int *)arg = (d->flags & SND_F_STEREO) ? 2 : 1 ;
- break ;
-
- case SOUND_PCM_READ_RATE:
- *(int *)arg = d->play_speed;
- break ;
-
- case SOUND_PCM_READ_CHANNELS:
- *(int *)arg = (d->flags & SND_F_STEREO) ? 2 : 1;
- break ;
-
- case SNDCTL_DSP_GETFMTS: /* returns a mask of supported fmts */
- *(int *)arg = (int)d->audio_fmt ;
- break ;
-
- case SNDCTL_DSP_SETFMT: /* sets _one_ format */
- /*
- * when some card (SB16) is opened RDONLY or WRONLY,
- * only one of the fields is set, the other becomes 0.
- * This makes it possible to select DMA channels at runtime.
- */
- if (d->play_fmt)
- d->play_fmt = *(int *)arg ;
- if (d->rec_fmt)
- d->rec_fmt = *(int *)arg ;
- splx(s);
- if (ask_init(d))
- *(int *)arg = d->play_fmt ;
- break ;
-
- case SNDCTL_DSP_SUBDIVIDE:
- /* XXX watch out, this is RW! */
- DEB(printf("SNDCTL_DSP_SUBDIVIDE yet unimplemented\n");)
- break;
-
- case SNDCTL_DSP_SETFRAGMENT:
- /* XXX watch out, this is RW! */
- DEB(printf("SNDCTL_DSP_SETFRAGMENT 0x%08x\n", *(int *)arg));
- {
- int bytes, count;
- bytes = *(int *)arg & 0xffff ;
- count = ( *(int *)arg >> 16) & 0xffff ;
- if (bytes > 15)
- bytes = 15 ;
- bytes = 1 << bytes ;
- if (bytes <= 1) { /* means no blocks */
- d->flags &= ~SND_F_HAS_SIZE ;
- } else {
- RANGE (bytes, 40, d->dbuf_out.bufsize /4);
- d->play_blocksize =
- d->rec_blocksize = bytes & ~3 ; /* align to multiple of 4 */
- d->flags |= SND_F_HAS_SIZE ;
- }
- splx(s);
- ask_init(d);
-#if 0
- /* XXX todo: set the buffer size to the # of fragments */
- count = d->dbuf_in.bufsize / d->play_blocksize ;
- bytes = ffs(d->play_blocksize) - 1;
- /*
- * don't change arg, since it's fake anyways and some
- * programs might fail if we do.
- */
- *(int *)arg = (count << 16) | bytes ;
-#endif
- }
- break ;
-
- case SNDCTL_DSP_GETISPACE:
- /* return space available in the input queue */
- {
- audio_buf_info *a = (audio_buf_info *)arg;
- snd_dbuf *b = &(d->dbuf_in);
- if (b->dl) {
- if (d->special_dma)
- d->callback(d, SND_CB_RD | SND_CB_DMAUPDATE) ;
- else
- dsp_rd_dmaupdate( b );
- }
- a->bytes = d->dbuf_in.fl ;
- a->fragments = 1 ;
- a->fragstotal = b->bufsize / d->rec_blocksize ;
- a->fragsize = d->rec_blocksize ;
- }
- break ;
-
- case SNDCTL_DSP_GETOSPACE:
- /* return space available in the output queue */
- {
- audio_buf_info *a = (audio_buf_info *)arg;
- snd_dbuf *b = &(d->dbuf_out);
- if (b->dl) {
- if (d->special_dma)
- d->callback(d, SND_CB_WR | SND_CB_DMAUPDATE) ;
- else
- dsp_wr_dmaupdate( b );
- }
- a->bytes = d->dbuf_out.fl ;
- a->fragments = 1 ;
- a->fragstotal = b->bufsize / d->play_blocksize ;
- a->fragsize = d->play_blocksize ;
- }
- break ;
-
- case SNDCTL_DSP_GETIPTR:
- {
- count_info *a = (count_info *)arg;
- snd_dbuf *b = &(d->dbuf_in);
- if (b->dl) {
- if (d->special_dma)
- d->callback(d, SND_CB_RD | SND_CB_DMAUPDATE) ;
- else
- dsp_rd_dmaupdate( b );
- }
- a->bytes = b->total;
- a->blocks = (b->total - b->prev_total +
- d->rec_blocksize -1 ) / d->rec_blocksize ;
- a->ptr = b->fp ; /* XXX not sure... */
- b->prev_total = b->total ;
- }
- break;
-
- case SNDCTL_DSP_GETOPTR:
- {
- count_info *a = (count_info *)arg;
- snd_dbuf *b = &(d->dbuf_out);
- if (b->dl) {
- if (d->special_dma)
- d->callback(d, SND_CB_WR | SND_CB_DMAUPDATE) ;
- else
- dsp_wr_dmaupdate( b );
- }
- a->bytes = b->total;
- a->blocks = (b->total - b->prev_total
- /* +d->play_blocksize -1*/ ) / d->play_blocksize ;
- a->ptr = b->rp ; /* XXX not sure... */
- b->prev_total = b->total ;
- }
- break;
-
- case SNDCTL_DSP_GETCAPS :
- *(int *) arg = 0x0 ; /* revision */
- if (FULL_DUPLEX(d))
- *(int *) arg |= DSP_CAP_DUPLEX ;
- *(int *) arg |= DSP_CAP_REALTIME ;
- break ;
-
- case SOUND_PCM_READ_BITS:
- if (d->play_fmt == AFMT_S16_LE)
- *(int *) arg = 16 ;
- else
- *(int *) arg = 8 ;
- break ;
-
- /*
- * mixer calls
- */
-
- case SOUND_MIXER_READ_DEVMASK :
- case SOUND_MIXER_READ_CAPS :
- case SOUND_MIXER_READ_STEREODEVS :
- *(int *)arg = d->mix_devs;
- break ;
-
- case SOUND_MIXER_READ_RECMASK :
- *(int *)arg = d->mix_rec_devs;
- break ;
-
- case SOUND_MIXER_READ_RECSRC :
- *(int *)arg = d->mix_recsrc ;
- break;
-
- default:
- DEB(printf("default ioctl snd%d subdev %d fn 0x%08x fail\n",
- unit, dev & 0xf, cmd));
- ret = EINVAL;
- break ;
- }
- splx(s);
- return ret ;
-}
-
-/*
- * we use the name 'select', but the new "poll" interface this is
- * really sndpoll. Second arg for poll is not "rw" but "events"
- */
-int
-sndselect(dev_t i_dev, int rw, struct proc * p)
-{
- int dev, unit, c = 1 /* default: success */ ;
- snddev_info *d ;
- u_long flags;
-
- dev = minor(i_dev);
- d = get_snddev_info(i_dev, &unit);
- DEB(printf("sndselect dev 0x%04x rw 0x%08x\n",i_dev, rw));
- if (d == NULL ) /* should not happen! */
- return (ENXIO) ;
- if (d->select == NULL)
- return ( (rw & (POLLIN|POLLOUT|POLLRDNORM|POLLWRNORM)) | POLLHUP);
- else if (d->select != sndselect )
- return d->select(i_dev, rw, p);
- else {
- /* handle it here with the generic code */
- /*
- * if the user selected a block size, then we want to use the
- * device as a block device, and select will return ready when
- * we have a full block.
- * In all other cases, select will return when 1 byte is ready.
- */
- int lim = 1;
-
- int revents = 0 ;
- if (rw & (POLLOUT | POLLWRNORM) ) {
- if ( d->flags & SND_F_HAS_SIZE )
- lim = d->play_blocksize ;
- /* XXX fix the test here for half duplex devices */
- if (1 /* write is compatible with current mode */) {
- flags = spltty();
- if (d->dbuf_out.dl) {
- if (d->special_dma)
- d->callback(d, SND_CB_WR | SND_CB_DMAUPDATE) ;
- else
- dsp_wr_dmaupdate(&(d->dbuf_out));
- }
- c = d->dbuf_out.fl ;
- if (c < lim) /* no space available */
- selrecord(p, & (d->wsel));
- else
- revents |= rw & (POLLOUT | POLLWRNORM);
- splx(flags);
- }
- }
- if (rw & (POLLIN | POLLRDNORM)) {
- if ( d->flags & SND_F_HAS_SIZE )
- lim = d->rec_blocksize ;
- /* XXX fix the test here */
- if (1 /* read is compatible with current mode */) {
- flags = spltty();
- if ( d->dbuf_in.dl == 0 ) /* dma idle, restart it */
- dsp_rdintr(d);
- else {
- if (d->special_dma)
- d->callback(d, SND_CB_RD | SND_CB_DMAUPDATE) ;
- else
- dsp_rd_dmaupdate(&(d->dbuf_in));
- }
- c = d->dbuf_in.rl ;
- if (c < lim) /* no data available */
- selrecord(p, & (d->rsel));
- else
- revents |= rw & (POLLIN | POLLRDNORM);
- splx(flags);
- }
- DEB(printf("sndselect on read: %d >= %d flags 0x%08x\n",
- c, lim, d->flags));
- return c < lim ? 0 : 1 ;
- }
- return revents;
- }
- return ENXIO ; /* notreached */
-}
-
-/*
- * The mmap interface allows access to the play and read buffer,
- * plus the device descriptor.
- * The various blocks are accessible at the following offsets:
- *
- * 0x00000000 ( 0 ) : write buffer ;
- * 0x01000000 (16 MB) : read buffer ;
- * 0x02000000 (32 MB) : device descriptor (dangerous!)
- *
- * WARNING: the mmap routines assume memory areas are aligned. This
- * is true (probably) for the dma buffers, but likely false for the
- * device descriptor. As a consequence, we do not know where it is
- * located in the requested area.
- */
-#include <sys/mman.h>
-#include <vm/vm.h>
-#include <vm/vm_kern.h>
-#include <vm/vm_param.h>
-#include <vm/pmap.h>
-#include <vm/vm_extern.h>
-
-static int
-sndmmap(dev_t dev, vm_offset_t offset, int nprot)
-{
- snddev_info *d = get_snddev_info(dev, NULL);
-
- DEB(printf("sndmmap d 0x%p dev 0x%04x ofs 0x%08x nprot 0x%08x\n",
- d, dev, offset, nprot));
-
- if (d == NULL || nprot & PROT_EXEC)
- return -1 ; /* forbidden */
-
- if (offset >= d->dbuf_out.bufsize && (nprot & PROT_WRITE) )
- return -1 ; /* can only write to the first block */
-
- if (offset < d->dbuf_out.bufsize)
- return i386_btop(vtophys(d->dbuf_out.buf + offset));
- offset -= 1 << 24;
- if ( (offset >= 0) && (offset < d->dbuf_in.bufsize))
- return i386_btop(vtophys(d->dbuf_in.buf + offset));
- offset -= 1 << 24;
- if ( (offset >= 0) && (offset < 0x2000)) {
- return i386_btop(vtophys( ((int)d & ~0xfff) + offset));
- }
- return -1 ;
-}
-
-
-/*
- * ask_init sets the init flag in the device descriptor, and
- * possibly calls the appropriate callback routine, returning 1
- * if the callback was successful. This enables ioctls handler for
- * rw parameters to read back the updated value.
- * Since the init callback can be slow, ask_init() should be called
- * with interrupts enabled.
- */
-
-int
-ask_init(snddev_info *d)
-{
- u_long s;
-
- if ( d->callback == NULL )
- return 0 ;
- s = spltty();
- if ( d->flags & SND_F_PENDING_IO ||
- d->dbuf_out.dl || d->dbuf_in.dl ) {
- /* cannot do it now, record the request and return */
- d->flags |= SND_F_INIT ;
- splx(s);
- return 0 ;
- } else {
- splx(s);
- d->callback(d, SND_CB_INIT );
- return 1;
- }
-}
-
-/*
- * these are the functions for the soundstat device. We copy parameters
- * from the device info structure to static variables, and from there
- * back to the structure when done.
- */
-
-static void
-init_status(snddev_info *d)
-{
- /*
- * Write the status information to the status_buf and update
- * status_len. There is a limit of SNDSTAT_BUF_SIZE bytes for the data.
- */
-
- int i;
-
- if (status_len != 0) /* only do init once */
- return ;
- snprintf(status_buf, sizeof(status_buf),
- "FreeBSD Audio Driver (981002) " __DATE__ " " __TIME__ "\n"
- "Installed devices:\n");
-
- for (i = 0; i < NPCM_MAX; i++) {
- if (pcm_info[i].open)
- snprintf(status_buf + strlen(status_buf),
- sizeof(status_buf) - strlen(status_buf),
- "pcm%d: <%s> at 0x%x irq %d dma %d:%d\n",
- i, pcm_info[i].name, pcm_info[i].io_base,
- pcm_info[i].irq,
- pcm_info[i].dbuf_out.chan, pcm_info[i].dbuf_in.chan);
- if (midi_info[i].open)
- snprintf(status_buf + strlen(status_buf),
- sizeof(status_buf) - strlen(status_buf),
- "midi%d: <%s> at 0x%x irq %d dma %d:%d\n",
- i, midi_info[i].name, midi_info[i].io_base,
- midi_info[i].irq,
- midi_info[i].dbuf_out.chan, midi_info[i].dbuf_in.chan);
- if (pcm_info[i].synth_base) {
- char *s = "???";
- switch (pcm_info[i].synth_type) {
- case 2 : s = "OPL2"; break;
- case 3 : s = "OPL3"; break;
- case 4 : s = "OPL4"; break;
- }
-
- snprintf(status_buf + strlen(status_buf),
- sizeof(status_buf) - strlen(status_buf),
- "sequencer%d: <%s> at 0x%x (not functional)\n",
- i, s, pcm_info[i].synth_base);
- }
- }
- status_len = strlen(status_buf) ;
-}
-
-/*
- * finally, some "libraries"
- */
-
-/*
- * isa_dmastatus1() is a wrapper for isa_dmastatus(), which
- * might return -1 or -2 in some cases (errors). Since for the
- * user code it is more comfortable not to check for these cases,
- * negative values are mapped back to 0 (which is reasonable).
- */
-
-int
-isa_dmastatus1(int channel)
-{
- int r = isa_dmastatus(channel);
- if (r<0) r = 0;
- return r;
-}
-
-/*
- * snd_conflict scans already-attached boards to see if
- * the current address is conflicting with one of the already
- * assigned ones. Returns 1 if a conflict is detected.
- */
-int
-snd_conflict(int io_base)
-{
- int i;
- for (i=0; i< NPCM_MAX ; i++) {
- if ( (io_base == pcm_info[i].io_base ) ||
- (io_base == pcm_info[i].alt_base ) ||
- (io_base == pcm_info[i].conf_base) ||
- (io_base == pcm_info[i].mix_base ) ||
- (io_base == pcm_info[i].midi_base) ||
- (io_base == pcm_info[i].synth_base) ) {
- BVDDB(printf("device at 0x%x already attached as unit %d\n",
- io_base, i);)
- return 1 ;
- }
- }
- return 0;
-}
-
-void
-snd_set_blocksize(snddev_info *d)
-{
- int tmp ;
- /*
- * compute the sample size, and possibly
- * set the blocksize so as to guarantee approx 1/4s
- * between callbacks.
- */
- tmp = 1 ;
- if (d->flags & SND_F_STEREO) tmp += tmp;
- if (d->play_fmt & (AFMT_S16_LE|AFMT_U16_LE)) tmp += tmp;
- d->dbuf_out.sample_size = tmp ;
- tmp = tmp * d->play_speed;
- if ( (d->flags & SND_F_HAS_SIZE) == 0) {
- d->play_blocksize = (tmp / 4) & ~3; /* 0.25s, aligned to 4 */
- RANGE (d->play_blocksize, 1024, (d->bufsize / 4) & ~3);
- }
-
- tmp = 1 ;
- if (d->flags & SND_F_STEREO) tmp += tmp;
- if (d->rec_fmt & (AFMT_S16_LE|AFMT_U16_LE)) tmp += tmp;
- tmp = tmp * d->rec_speed;
- d->dbuf_in.sample_size = tmp ;
- if ( (d->flags & SND_F_HAS_SIZE) == 0) {
- d->rec_blocksize = (tmp / 4) & ~3; /* 0.25s, aligned to 4 */
- RANGE (d->rec_blocksize, 1024, (d->bufsize / 4) & ~3);
- }
-}
-
-/*
- * The various mixers use a variety of bitmasks etc. The Voxware
- * driver had a very nice technique to describe a mixer and interface
- * to it. A table defines, for each channel, which register, bits,
- * offset, polarity to use. This procedure creates the new value
- * using the table and the old value.
- */
-
-void
-change_bits(mixer_tab *t, u_char *regval, int dev, int chn, int newval)
-{
- u_char mask;
- int shift;
-
- DEB(printf("ch_bits dev %d ch %d val %d old 0x%02x "
- "r %d p %d bit %d off %d\n",
- dev, chn, newval, *regval,
- (*t)[dev][chn].regno, (*t)[dev][chn].polarity,
- (*t)[dev][chn].nbits, (*t)[dev][chn].bitoffs ) );
-
- if ( (*t)[dev][chn].polarity == 1) /* reverse */
- newval = 100 - newval ;
-
- mask = (1 << (*t)[dev][chn].nbits) - 1;
- newval = (int) ((newval * mask) + 50) / 100; /* Scale it */
- shift = (*t)[dev][chn].bitoffs /*- (*t)[dev][LEFT_CHN].nbits + 1*/;
-
- *regval &= ~(mask << shift); /* Filter out the previous value */
- *regval |= (newval & mask) << shift; /* Set the new value */
-}
-
-
-/*
- * code for translating between U8 and ULAW. Needed to support
- * /dev/audio on the SoundBlaster. Actually, we would also need
- * ulaw -> 16 bits (for the soundblaster as well, when used in
- * full-duplex)
- */
-
-void
-translate_bytes (u_char *table, u_char *buff, int n)
-{
- u_long i;
-
- if (n <= 0)
- return;
-
- for (i = 0; i < n; ++i)
- buff[i] = table[buff[i]];
-}
-
-#endif /* NPCM > 0 */
diff --git a/sys/i386/isa/snd/sound.h b/sys/i386/isa/snd/sound.h
deleted file mode 100644
index 5d5db4d..0000000
--- a/sys/i386/isa/snd/sound.h
+++ /dev/null
@@ -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
diff --git a/sys/i386/isa/snd/ulaw.h b/sys/i386/isa/snd/ulaw.h
deleted file mode 100644
index 4b9916f..0000000
--- a/sys/i386/isa/snd/ulaw.h
+++ /dev/null
@@ -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 */
OpenPOWER on IntegriCloud