Index: ObsoleteFiles.inc =================================================================== --- ObsoleteFiles.inc +++ ObsoleteFiles.inc @@ -52,6 +52,15 @@ # xargs -n1 | sort | uniq -d; # done +# 2022xxxx: ISA sound card drivers removed +OLD_FILES+=usr/share/man/man4/snd_ad1816.4 +OLD_FILES+=usr/share/man/man4/snd_ess.4 +OLD_FILES+=usr/share/man/man4/snd_gusc.4 +OLD_FILES+=usr/share/man/man4/snd_mss.4 +OLD_FILES+=usr/share/man/man4/snd_sb16.4 +OLD_FILES+=usr/share/man/man4/snd_sb8.4 +OLD_FILES+=usr/share/man/man4/snd_sbc.4 + # 20220318: snd_ds1 and snd_maestro drivers removed OLD_FILES+=usr/share/man/man4/snd_ds1.4.gz OLD_FILES+=usr/share/man/man4/snd_maestro.4.gz Index: share/man/man4/Makefile =================================================================== --- share/man/man4/Makefile +++ share/man/man4/Makefile @@ -499,7 +499,6 @@ smbus.4 \ smp.4 \ smsc.4 \ - snd_ad1816.4 \ snd_als4000.4 \ snd_atiixp.4 \ snd_cmi.4 \ @@ -510,16 +509,12 @@ snd_envy24.4 \ snd_envy24ht.4 \ snd_es137x.4 \ - snd_ess.4 \ snd_fm801.4 \ - snd_gusc.4 \ snd_hda.4 \ snd_hdspe.4 \ snd_ich.4 \ snd_maestro3.4 \ - snd_mss.4 \ snd_neomagic.4 \ - snd_sbc.4 \ snd_solo.4 \ snd_spicds.4 \ snd_t4dwave.4 \ @@ -739,8 +734,6 @@ MLINKS+=smp.4 SMP.4 MLINKS+=smsc.4 if_smsc.4 MLINKS+=snd_envy24.4 snd_ak452x.4 -MLINKS+=snd_sbc.4 snd_sb16.4 \ - snd_sbc.4 snd_sb8.4 MLINKS+=${_spkr.4} ${_speaker.4} MLINKS+=splash.4 screensaver.4 MLINKS+=ste.4 if_ste.4 Index: share/man/man4/pcm.4 =================================================================== --- share/man/man4/pcm.4 +++ share/man/man4/pcm.4 @@ -75,8 +75,6 @@ .Pp .Bl -bullet -compact .It -.Xr snd_ad1816 4 -.It .Xr snd_ai2s 4 (enabled by default on powerpc) .It .Xr snd_als4000 4 @@ -101,12 +99,8 @@ .It .Xr snd_es137x 4 (enabled by default on amd64, i386) .It -.Xr snd_ess 4 -.It .Xr snd_fm801 4 .It -.Xr snd_gusc 4 -.It .Xr snd_hda 4 (enabled by default on amd64, i386) .It .Xr snd_hdspe 4 @@ -115,16 +109,8 @@ .It .Xr snd_maestro3 4 .It -.Xr snd_mss 4 -.It .Xr snd_neomagic 4 .It -snd_sb16 -.It -snd_sb8 -.It -.Xr snd_sbc 4 -.It .Xr snd_solo 4 .It .Xr snd_spicds 4 @@ -698,7 +684,6 @@ A device node is not created properly. .El .Sh SEE ALSO -.Xr snd_ad1816 4 , .Xr snd_ai2s 4 , .Xr snd_als4000 4 , .Xr snd_atiixp 4 , @@ -711,16 +696,12 @@ .Xr snd_envy24 4 , .Xr snd_envy24ht 4 , .Xr snd_es137x 4 , -.Xr snd_ess 4 , .Xr snd_fm801 4 , -.Xr snd_gusc 4 , .Xr snd_hda 4 , .Xr snd_hdspe 4 , .Xr snd_ich 4 , .Xr snd_maestro3 4 , -.Xr snd_mss 4 , .Xr snd_neomagic 4 , -.Xr snd_sbc 4 , .Xr snd_solo 4 , .Xr snd_spicds 4 , .Xr snd_t4dwave 4 , Index: share/man/man4/snd_ad1816.4 =================================================================== --- share/man/man4/snd_ad1816.4 +++ /dev/null @@ -1,84 +0,0 @@ -.\" Copyright (c) 2004 Atte Peltomaki -.\" All rights reserved. -.\" -.\" 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. -.\" -.\" $FreeBSD$ -.\" -.Dd March 19, 2022 -.Dt SND_AD1816 4 -.Os -.Sh NAME -.Nm snd_ad1816 -.Nd "Analog Devices AD1816 ISA bridge device driver" -.Sh DEPRECATION NOTICE -This driver is scheduled for removal prior to the release of -.Fx 14.0 . -.Sh SYNOPSIS -To compile this driver into the kernel, place the following lines in your -kernel configuration file: -.Bd -ragged -offset indent -.Cd "device sound" -.Cd "device snd_ad1816" -.Ed -.Pp -Alternatively, to load the driver as a module at boot time, place the -following line in -.Xr loader.conf 5 : -.Bd -literal -offset indent -snd_ad1816_load="YES" -.Ed -.Pp -Non-PnP cards require the following lines in -.Xr device.hints 5 : -.Bd -literal -offset indent -hint.pcm.0.at="isa" -hint.pcm.0.irq="10" -hint.pcm.0.drq="1" -hint.pcm.0.flags="0x0" -.Ed -.Sh DESCRIPTION -The -.Nm -bridge driver allows the generic audio driver -.Xr sound 4 -to attach to the AD1816 sound card. -.Sh HARDWARE -The -.Nm -driver supports the following sound cards: -.Pp -.Bl -bullet -compact -.It -Analog Devices AD1816 -.El -.Sh SEE ALSO -.Xr sound 4 -.Sh HISTORY -The -.Nm -device driver first appeared in -.Fx 4.0 . -.Sh AUTHORS -.An Cameron Grant Aq Mt cg@FreeBSD.org -.An Luigi Rizzo Aq Mt luigi@FreeBSD.org -.An "Hannu Savolainen" Index: share/man/man4/snd_ess.4 =================================================================== --- share/man/man4/snd_ess.4 +++ /dev/null @@ -1,75 +0,0 @@ -.\" Copyright (c) 2004 Atte Peltomaki -.\" All rights reserved. -.\" -.\" 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. -.\" -.\" $FreeBSD$ -.\" -.Dd March 19, 2022 -.Dt SND_ESS 4 -.Os -.Sh NAME -.Nm snd_ess -.Nd "Ensoniq ESS ISA PnP/non-PnP bridge device driver" -.Sh DEPRECATION NOTICE -This driver is scheduled for removal prior to the release of -.Fx 14.0 . -.Sh SYNOPSIS -To compile this driver into the kernel, place the following lines in your -kernel configuration file: -.Bd -ragged -offset indent -.Cd "device sound" -.Cd "device snd_ess" -.Cd "device snd_sbc" -.Ed -.Pp -Alternatively, to load the driver as a module at boot time, place the -following line in -.Xr loader.conf 5 : -.Bd -literal -offset indent -snd_ess_load="YES" -.Ed -.Sh DESCRIPTION -The -.Nm -bridge driver allows the generic audio driver -.Xr sound 4 -to attach to the ESS ISA sound cards. -.Sh HARDWARE -The -.Nm -driver supports the following sound cards: -.Pp -.Bl -bullet -compact -.It -Ensoniq ESS ISA PnP/non-PnP -.El -.Sh SEE ALSO -.Xr sound 4 -.Sh HISTORY -The -.Nm -device driver first appeared in -.Fx 4.1 . -.Sh AUTHORS -.An Cameron Grant Aq Mt cg@FreeBSD.org -.An Luigi Rizzo Aq Mt luigi@FreeBSD.org Index: share/man/man4/snd_gusc.4 =================================================================== --- share/man/man4/snd_gusc.4 +++ /dev/null @@ -1,100 +0,0 @@ -.\" -.\" Copyright (c) 1999 Seigo Tanimura -.\" All rights reserved. -.\" -.\" 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. -.\" -.\" $FreeBSD$ -.\" -.Dd March 19, 2022 -.Dt SND_GUSC 4 -.Os -.Sh NAME -.Nm snd_gusc -.Nd Gravis UltraSound ISA bridge device driver -.Sh DEPRECATION NOTICE -This driver is scheduled for removal prior to the release of -.Fx 14.0 . -.Sh SYNOPSIS -To compile this driver into the kernel, place the following lines in your -kernel configuration file: -.Bd -ragged -offset indent -.Cd "device sound" -.Cd "device snd_gusc" -.Ed -.Pp -Alternatively, to load the driver as a module at boot time, place the -following line in -.Xr loader.conf 5 : -.Bd -literal -offset indent -snd_gusc_load="YES" -.Ed -.Pp -Non-PnP cards require the following lines in -.Xr device.hints 5 : -.Bd -literal -offset indent -hint.gusc.0.at="isa" -hint.gusc.0.port="0x220" -hint.gusc.0.irq="5" -hint.gusc.0.drq="1" -hint.gusc.0.flags="0x13" -.Ed -.Sh DESCRIPTION -The -.Nm -bridge driver allows the generic audio driver -.Xr sound 4 -to attach to Gravis UltraSound sound cards. -.Pp -The value of flags specifies the secondary DMA channel. -If the secondary -DMA channel is C, set the flags to (C | 0x10). -For a sound card without the -secondary DMA channel, the flags should be set to zero. -.Sh HARDWARE -The -.Nm -driver supports the following sound cards: -.Pp -.Bl -bullet -compact -.It -Gravis UltraSound MAX -.It -Gravis UltraSound PnP -.El -.Sh DIAGNOSTICS -.Bl -diag -.It xxx: gus pcm not attached, out of memory -There are not enough memory to drive the device. -.El -.Sh SEE ALSO -.Xr sound 4 -.Sh HISTORY -The -.Nm -device driver first appeared in -.Fx 4.0 . -.Sh AUTHORS -.An Ville-Pertti Keinonen Aq Mt will@iki.fi -.An Seigo Tanimura Aq Mt tanimura@r.dl.itc.u-tokyo.ac.jp -.Sh BUGS -Recording pcm sound data is not supported yet. Index: share/man/man4/snd_mss.4 =================================================================== --- share/man/man4/snd_mss.4 +++ /dev/null @@ -1,119 +0,0 @@ -.\" Copyright (c) 2005 Joel Dahl -.\" All rights reserved. -.\" -.\" 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. -.\" -.\" $FreeBSD$ -.\" -.Dd March 19, 2022 -.Dt SND_MSS 4 -.Os -.Sh NAME -.Nm snd_mss -.Nd "Microsoft Sound System ISA PnP/non-PnP bridge device driver" -.Sh DEPRECATION NOTICE -This driver is scheduled for removal prior to the release of -.Fx 14.0 . -.Sh SYNOPSIS -To compile this driver into the kernel, place the following lines in your -kernel configuration file: -.Bd -ragged -offset indent -.Cd "device sound" -.Cd "device snd_mss" -.Ed -.Pp -Alternatively, to load the driver as a module at boot time, place the -following line in -.Xr loader.conf 5 : -.Bd -literal -offset indent -snd_mss_load="YES" -.Ed -.Pp -Non-PnP cards require the following lines in -.Xr device.hints 5 : -.Bd -literal -offset indent -hint.pcm.0.at="isa" -hint.pcm.0.irq="10" -hint.pcm.0.drq="1" -hint.pcm.0.flags="0x0" -.Ed -.Sh DESCRIPTION -The -.Nm -bridge driver allows the generic audio driver, -.Xr sound 4 , -to attach to the supported audio devices. -.Sh HARDWARE -The -.Nm -driver supports the following audio devices: -.Pp -.Bl -bullet -compact -.It -AD1845 -.It -AD1848 -.It -Aztech 2320 -.It -CMedia CMI8330 -.It -Crystal Semiconductor CS4231 -.It -Crystal Semiconductor CS4232 -.It -Crystal Semiconductor CS4234 -.It -Crystal Semiconductor CS4235 -.It -Crystal Semiconductor CS4236 -.It -Crystal Semiconductor CS4237 -.It -ENSONIQ SoundscapeVIVO ENS4081 -.It -NeoMagic 256AV (non-AC97) -.It -OPTi 924 -.It -OPTi 925 -.It -OPTi 930 -.It -OPTi 931 -.It -OPTi 933 -.It -Yamaha OPL-SA2 -.It -Yamaha OPL-SA3 -.El -.Sh SEE ALSO -.Xr sound 4 -.Sh HISTORY -The -.Nm -device driver first appeared in -.Fx 2.2.6 . -.Sh AUTHORS -This manual page was written by -.An Joel Dahl Aq Mt joel@FreeBSD.org . Index: share/man/man4/snd_sbc.4 =================================================================== --- share/man/man4/snd_sbc.4 +++ /dev/null @@ -1,135 +0,0 @@ -.\" -.\" Copyright (c) 1999 Seigo Tanimura -.\" All rights reserved. -.\" -.\" 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. -.\" -.\" $FreeBSD$ -.\" -.Dd March 19, 2022 -.Dt SND_SBC 4 -.Os -.Sh NAME -.Nm snd_sbc , -.Nm snd_sb16 , -.Nm snd_sb8 -.Nd Creative Sound Blaster ISA and compatible bridge device driver -.Sh DEPRECATION NOTICE -This driver is scheduled for removal prior to the release of -.Fx 14.0 . -.Sh SYNOPSIS -To compile this driver into the kernel, place the following lines in your -kernel configuration file: -.Bd -ragged -offset indent -.Cd "device sound" -.Cd "device snd_sbc" -.Cd "device snd_sb16" -.Cd "device snd_sb8" -.Ed -.Pp -Alternatively, to load the driver as a module at boot time, place the -following lines in -.Xr loader.conf 5 : -.Bd -literal -offset indent -snd_sbc_load="YES" -snd_sb16_load="YES" -snd_sb8_load="YES" -.Ed -.Pp -Non-PnP cards require the following lines in -.Xr device.hints 5 : -.Bd -literal -offset indent -hint.sbc.0.at="isa" -hint.sbc.0.port="0x220" -hint.sbc.0.irq="5" -hint.sbc.0.drq="1" -hint.sbc.0.flags="0x15" -.Ed -.Sh DESCRIPTION -The -.Nm -bridge driver allows the generic audio driver -.Xr sound 4 -to attach to Creative Sound Blaster ISA (mostly SB16 or SB8, known as -SoundBlaster Pro) compatible audio cards. -.Pp -The value of flags specifies the secondary DMA channel. -If the secondary -DMA channel is C, set the flags to (C | 0x10). -For a sound card without the -secondary DMA channel, the flags should be set to zero. -.Sh HARDWARE -The -.Nm -driver supports the following sound cards: -.Pp -.Bl -bullet -compact -.It -Avance Asound 110 -.It -Avance Logic ALS100+ -.It -Avance Logic ALS120 -.It -Creative SB16 -.It -Creative SB32 -.It -Creative AWE64 -.It -Creative AWE64 Gold -.It -Creative ViBRA16C -.It -Creative ViBRA16X -.It -ESS ES1681 -.It -ESS ES1688 -.It -ESS ES1868 -.It -ESS ES1869 -.It -ESS ES1878 -.It -ESS ES1879 -.It -ESS ES1888 -.El -.Sh DIAGNOSTICS -.Bl -diag -.It sb_dspwr(XX) timed out. -A command to the DSP has timed out. -Check the I/O port configuration. -.It bad irq XX (5/7/9/10 valid) -The IRQ given to the driver is not valid. -.El -.Sh SEE ALSO -.Xr sound 4 -.Sh HISTORY -The -.Nm -device driver first appeared in -.Fx 4.0 . -.Sh AUTHORS -.An Seigo Tanimura Aq Mt tanimura@r.dl.itc.u-tokyo.ac.jp Index: share/man/man4/snd_solo.4 =================================================================== --- share/man/man4/snd_solo.4 +++ share/man/man4/snd_solo.4 @@ -50,11 +50,6 @@ .It ESS Solo-1E (ES1946 Chipset) .El -.Pp -Note that older ESS ISA cards with ES18xx chipset are supported via -.Xr snd_ess 4 -and/or -.Xr snd_sbc 4 . .Sh SEE ALSO .Xr sound 4 .Sh HISTORY Index: sys/conf/NOTES =================================================================== --- sys/conf/NOTES +++ sys/conf/NOTES @@ -2034,7 +2034,6 @@ # zero if don't know what to put in (and you don't, # since this is unsupported at the moment...). # -# snd_ad1816: Analog Devices AD1816 ISA PnP/non-PnP. # snd_als4000: Avance Logic ALS4000 PCI. # snd_atiixp: ATI IXP 200/300/400 PCI. # snd_cmi: CMedia CMI8338/CMI8738 PCI. @@ -2046,10 +2045,7 @@ # snd_envy24: VIA Envy24 and compatible, needs snd_spicds. # snd_envy24ht: VIA Envy24HT and compatible, needs snd_spicds. # snd_es137x: Ensoniq AudioPCI ES137x PCI. -# snd_ess: Ensoniq ESS ISA PnP/non-PnP, to be used in -# conjunction with snd_sbc. # snd_fm801: Forte Media FM801 PCI. -# snd_gusc: Gravis UltraSound ISA PnP/non-PnP. # snd_hda: Intel High Definition Audio (Controller) and # compatible. # snd_hdspe: RME HDSPe AIO and RayDAT. @@ -2057,14 +2053,7 @@ # embedded in a chipset, for example nVidia # nForce controllers. # snd_maestro3: ESS Technology Maestro-3/Allegro PCI. -# snd_mss: Microsoft Sound System ISA PnP/non-PnP. # snd_neomagic: Neomagic 256 AV/ZX PCI. -# snd_sb16: Creative SoundBlaster16, to be used in -# conjunction with snd_sbc. -# snd_sb8: Creative SoundBlaster (pre-16), to be used in -# conjunction with snd_sbc. -# snd_sbc: Creative SoundBlaster ISA PnP/non-PnP. -# Supports ESS and Avance ISA chips as well. # snd_solo: ESS Solo-1x PCI. # snd_spicds: SPI codec driver, needed by Envy24/Envy24HT drivers. # snd_t4dwave: Trident 4DWave DX/NX PCI, Sis 7018 PCI and Acer Labs @@ -2074,7 +2063,6 @@ # snd_via82c686: VIA VT82C686A PCI. # snd_vibes: S3 Sonicvibes PCI. -device snd_ad1816 device snd_als4000 device snd_atiixp device snd_cmi @@ -2085,18 +2073,12 @@ device snd_envy24 device snd_envy24ht device snd_es137x -device snd_ess device snd_fm801 -device snd_gusc device snd_hda device snd_hdspe device snd_ich device snd_maestro3 -device snd_mss device snd_neomagic -device snd_sb16 -device snd_sb8 -device snd_sbc device snd_solo device snd_spicds device snd_t4dwave Index: sys/conf/files =================================================================== --- sys/conf/files +++ sys/conf/files @@ -3089,14 +3089,6 @@ dev/snp/snp.c optional snp dev/sound/clone.c optional sound dev/sound/unit.c optional sound -dev/sound/isa/ad1816.c optional snd_ad1816 isa -dev/sound/isa/ess.c optional snd_ess isa -dev/sound/isa/gusc.c optional snd_gusc isa -dev/sound/isa/mss.c optional snd_mss isa -dev/sound/isa/sb16.c optional snd_sb16 isa -dev/sound/isa/sb8.c optional snd_sb8 isa -dev/sound/isa/sbc.c optional snd_sbc isa -dev/sound/isa/sndbuf_dma.c optional sound isa dev/sound/pci/als4000.c optional snd_als4000 pci dev/sound/pci/atiixp.c optional snd_atiixp pci dev/sound/pci/cmi.c optional snd_cmi pci Index: sys/dev/sound/driver.c =================================================================== --- sys/dev/sound/driver.c +++ sys/dev/sound/driver.c @@ -58,7 +58,6 @@ DECLARE_MODULE(snd_driver, snd_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE); MODULE_VERSION(snd_driver, 1); -MODULE_DEPEND(snd_driver, snd_ad1816, 1, 1, 1); MODULE_DEPEND(snd_driver, snd_als4000, 1, 1, 1); MODULE_DEPEND(snd_driver, snd_atiixp, 1, 1, 1); MODULE_DEPEND(snd_driver, snd_cmi, 1, 1, 1); @@ -69,17 +68,11 @@ MODULE_DEPEND(snd_driver, snd_envy24, 1, 1, 1); MODULE_DEPEND(snd_driver, snd_envy24ht, 1, 1, 1); MODULE_DEPEND(snd_driver, snd_es137x, 1, 1, 1); -MODULE_DEPEND(snd_driver, snd_ess, 1, 1, 1); MODULE_DEPEND(snd_driver, snd_fm801, 1, 1, 1); -MODULE_DEPEND(snd_driver, snd_gusc, 1, 1, 1); MODULE_DEPEND(snd_driver, snd_hda, 1, 1, 1); MODULE_DEPEND(snd_driver, snd_ich, 1, 1, 1); MODULE_DEPEND(snd_driver, snd_maestro3, 1, 1, 1); -MODULE_DEPEND(snd_driver, snd_mss, 1, 1, 1); MODULE_DEPEND(snd_driver, snd_neomagic, 1, 1, 1); -MODULE_DEPEND(snd_driver, snd_sb16, 1, 1, 1); -MODULE_DEPEND(snd_driver, snd_sb8, 1, 1, 1); -MODULE_DEPEND(snd_driver, snd_sbc, 1, 1, 1); MODULE_DEPEND(snd_driver, snd_solo, 1, 1, 1); MODULE_DEPEND(snd_driver, snd_spicds, 1, 1, 1); MODULE_DEPEND(snd_driver, snd_t4dwave, 1, 1, 1); Index: sys/dev/sound/isa/ad1816.h =================================================================== --- sys/dev/sound/isa/ad1816.h +++ /dev/null @@ -1,96 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * Copyright (c) 1997 Luigi Rizzo - * All rights reserved. - * - * 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. - * - * $FreeBSD$ - */ - -/* - * This file contains information and macro definitions for - * the ad1816 chip - */ - -/* AD1816 register macros */ - -#define AD1816_ALE 0 /* indirect reg access */ -#define AD1816_INT 1 /* interrupt status */ -#define AD1816_LOW 2 /* indirect low byte */ -#define AD1816_HIGH 3 /* indirect high byte */ - -#if 0 -#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 */ -#endif - -/* 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 8 /* playback config */ -#define AD1816_CAPT 9 /* capture config */ - -#define AD1816_BUSY 0x80 /* chip is busy */ -#define AD1816_ALEMASK 0x3F /* mask for indirect adr. */ - -#if 0 -#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 */ -#endif - -#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 */ - -#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) Index: sys/dev/sound/isa/ad1816.c =================================================================== --- sys/dev/sound/isa/ad1816.c +++ /dev/null @@ -1,687 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * Copyright (c) 1999 Cameron Grant - * Copyright (c) 1997,1998 Luigi Rizzo - * Copyright (c) 1994,1995 Hannu Savolainen - * All rights reserved. - * - * 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 HAVE_KERNEL_OPTION_HEADERS -#include "opt_snd.h" -#endif - -#include -#include - -#include - -#include "mixer_if.h" - -SND_DECLARE_FILE("$FreeBSD$"); - -struct ad1816_info; - -struct ad1816_chinfo { - struct ad1816_info *parent; - struct pcm_channel *channel; - struct snd_dbuf *buffer; - int dir, blksz; -}; - -struct ad1816_info { - struct resource *io_base; /* primary I/O address for the board */ - int io_rid; - struct resource *irq; - int irq_rid; - struct resource *drq1; /* play */ - int drq1_rid; - struct resource *drq2; /* rec */ - int drq2_rid; - void *ih; - bus_dma_tag_t parent_dmat; - struct mtx *lock; - - unsigned int bufsize; - struct ad1816_chinfo pch, rch; -}; - -static u_int32_t ad1816_fmt[] = { - SND_FORMAT(AFMT_U8, 1, 0), - SND_FORMAT(AFMT_U8, 2, 0), - SND_FORMAT(AFMT_S16_LE, 1, 0), - SND_FORMAT(AFMT_S16_LE, 2, 0), - SND_FORMAT(AFMT_MU_LAW, 1, 0), - SND_FORMAT(AFMT_MU_LAW, 2, 0), - SND_FORMAT(AFMT_A_LAW, 1, 0), - SND_FORMAT(AFMT_A_LAW, 2, 0), - 0 -}; - -static struct pcmchan_caps ad1816_caps = {4000, 55200, ad1816_fmt, 0}; - -#define AD1816_MUTE 31 /* value for mute */ - -static void -ad1816_lock(struct ad1816_info *ad1816) -{ - snd_mtxlock(ad1816->lock); -} - -static void -ad1816_unlock(struct ad1816_info *ad1816) -{ - snd_mtxunlock(ad1816->lock); -} - -static int -port_rd(struct resource *port, int off) -{ - if (port) - return bus_space_read_1(rman_get_bustag(port), - rman_get_bushandle(port), - off); - else - return -1; -} - -static void -port_wr(struct resource *port, int off, u_int8_t data) -{ - if (port) - bus_space_write_1(rman_get_bustag(port), - rman_get_bushandle(port), - off, data); -} - -static int -io_rd(struct ad1816_info *ad1816, int reg) -{ - return port_rd(ad1816->io_base, reg); -} - -static void -io_wr(struct ad1816_info *ad1816, int reg, u_int8_t data) -{ - port_wr(ad1816->io_base, reg, data); -} - -static void -ad1816_intr(void *arg) -{ - struct ad1816_info *ad1816 = (struct ad1816_info *)arg; - unsigned char c, served = 0; - - ad1816_lock(ad1816); - /* get interrupt status */ - c = io_rd(ad1816, AD1816_INT); - - /* check for stray interrupts */ - if (c & ~(AD1816_INTRCI | AD1816_INTRPI)) { - printf("pcm: stray int (%x)\n", c); - c &= AD1816_INTRCI | AD1816_INTRPI; - } - /* check for capture interrupt */ - if (sndbuf_runsz(ad1816->rch.buffer) && (c & AD1816_INTRCI)) { - ad1816_unlock(ad1816); - chn_intr(ad1816->rch.channel); - ad1816_lock(ad1816); - served |= AD1816_INTRCI; /* cp served */ - } - /* check for playback interrupt */ - if (sndbuf_runsz(ad1816->pch.buffer) && (c & AD1816_INTRPI)) { - ad1816_unlock(ad1816); - chn_intr(ad1816->pch.channel); - ad1816_lock(ad1816); - 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("pcm: int without reason (%x)\n", c); - c = 0; - } else c &= ~served; - io_wr(ad1816, AD1816_INT, c); - c = io_rd(ad1816, AD1816_INT); - if (c != 0) printf("pcm: int clear failed (%x)\n", c); - ad1816_unlock(ad1816); -} - -static int -ad1816_wait_init(struct ad1816_info *ad1816, int x) -{ - int n = 0; /* to shut up the compiler... */ - - for (; x--;) - if ((n = (io_rd(ad1816, AD1816_ALE) & AD1816_BUSY)) == 0) DELAY(10); - else return n; - printf("ad1816_wait_init failed 0x%02x.\n", n); - return -1; -} - -static unsigned short -ad1816_read(struct ad1816_info *ad1816, unsigned int reg) -{ - u_short x = 0; - - if (ad1816_wait_init(ad1816, 100) == -1) return 0; - io_wr(ad1816, AD1816_ALE, 0); - io_wr(ad1816, AD1816_ALE, (reg & AD1816_ALEMASK)); - if (ad1816_wait_init(ad1816, 100) == -1) return 0; - x = (io_rd(ad1816, AD1816_HIGH) << 8) | io_rd(ad1816, AD1816_LOW); - return x; -} - -static void -ad1816_write(struct ad1816_info *ad1816, unsigned int reg, unsigned short data) -{ - if (ad1816_wait_init(ad1816, 100) == -1) return; - io_wr(ad1816, AD1816_ALE, (reg & AD1816_ALEMASK)); - io_wr(ad1816, AD1816_LOW, (data & 0x000000ff)); - io_wr(ad1816, AD1816_HIGH, (data & 0x0000ff00) >> 8); -} - -/* -------------------------------------------------------------------- */ - -static int -ad1816mix_init(struct snd_mixer *m) -{ - mix_setdevs(m, AD1816_MIXER_DEVICES); - mix_setrecdevs(m, AD1816_REC_DEVICES); - return 0; -} - -static int -ad1816mix_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right) -{ - struct ad1816_info *ad1816 = mix_getdevinfo(m); - u_short reg = 0; - - /* 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; - - ad1816_lock(ad1816); - switch (dev) { - case SOUND_MIXER_VOLUME: /* Register 14 master volume */ - ad1816_write(ad1816, 14, reg); - break; - - case SOUND_MIXER_CD: /* Register 15 cd */ - case SOUND_MIXER_LINE1: - ad1816_write(ad1816, 15, reg); - break; - - case SOUND_MIXER_SYNTH: /* Register 16 synth */ - ad1816_write(ad1816, 16, reg); - break; - - case SOUND_MIXER_PCM: /* Register 4 pcm */ - ad1816_write(ad1816, 4, reg); - break; - - case SOUND_MIXER_LINE: - case SOUND_MIXER_LINE3: /* Register 18 line in */ - ad1816_write(ad1816, 18, reg); - break; - - case SOUND_MIXER_MIC: /* Register 19 mic volume */ - ad1816_write(ad1816, 19, reg & ~0xff); /* mic is mono */ - break; - - case SOUND_MIXER_IGAIN: - /* and now to something completely different ... */ - ad1816_write(ad1816, 20, ((ad1816_read(ad1816, 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; - } - ad1816_unlock(ad1816); - - left = ((AD1816_MUTE - left) * 100) / AD1816_MUTE; - right = ((AD1816_MUTE - right) * 100) / AD1816_MUTE; - - return left | (right << 8); -} - -static u_int32_t -ad1816mix_setrecsrc(struct snd_mixer *m, u_int32_t src) -{ - struct ad1816_info *ad1816 = mix_getdevinfo(m); - int dev; - - switch (src) { - case SOUND_MASK_LINE: - case SOUND_MASK_LINE3: - dev = 0x00; - break; - - case SOUND_MASK_CD: - case SOUND_MASK_LINE1: - dev = 0x20; - break; - - case SOUND_MASK_MIC: - default: - dev = 0x50; - src = SOUND_MASK_MIC; - } - - dev |= dev << 8; - ad1816_lock(ad1816); - ad1816_write(ad1816, 20, (ad1816_read(ad1816, 20) & ~0x7070) | dev); - ad1816_unlock(ad1816); - return src; -} - -static kobj_method_t ad1816mixer_methods[] = { - KOBJMETHOD(mixer_init, ad1816mix_init), - KOBJMETHOD(mixer_set, ad1816mix_set), - KOBJMETHOD(mixer_setrecsrc, ad1816mix_setrecsrc), - KOBJMETHOD_END -}; -MIXER_DECLARE(ad1816mixer); - -/* -------------------------------------------------------------------- */ -/* channel interface */ -static void * -ad1816chan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir) -{ - struct ad1816_info *ad1816 = devinfo; - struct ad1816_chinfo *ch = (dir == PCMDIR_PLAY)? &ad1816->pch : &ad1816->rch; - - ch->dir = dir; - ch->parent = ad1816; - ch->channel = c; - ch->buffer = b; - if (sndbuf_alloc(ch->buffer, ad1816->parent_dmat, 0, ad1816->bufsize) != 0) - return NULL; - - sndbuf_dmasetup(ch->buffer, (dir == PCMDIR_PLAY) ? ad1816->drq1 : - ad1816->drq2); - if (SND_DMA(ch->buffer)) - sndbuf_dmasetdir(ch->buffer, dir); - - return ch; -} - -static int -ad1816chan_setformat(kobj_t obj, void *data, u_int32_t format) -{ - struct ad1816_chinfo *ch = data; - struct ad1816_info *ad1816 = ch->parent; - int fmt = AD1816_U8, reg; - - ad1816_lock(ad1816); - if (ch->dir == PCMDIR_PLAY) { - reg = AD1816_PLAY; - ad1816_write(ad1816, 8, 0x0000); /* reset base and current counter */ - ad1816_write(ad1816, 9, 0x0000); /* for playback and capture */ - } else { - reg = AD1816_CAPT; - ad1816_write(ad1816, 10, 0x0000); - ad1816_write(ad1816, 11, 0x0000); - } - switch (AFMT_ENCODING(format)) { - case AFMT_A_LAW: - fmt = AD1816_ALAW; - break; - - case AFMT_MU_LAW: - fmt = AD1816_MULAW; - break; - - case AFMT_S16_LE: - fmt = AD1816_S16LE; - break; - - case AFMT_S16_BE: - fmt = AD1816_S16BE; - break; - - case AFMT_U8: - fmt = AD1816_U8; - break; - } - if (AFMT_CHANNEL(format) > 1) fmt |= AD1816_STEREO; - io_wr(ad1816, reg, fmt); - ad1816_unlock(ad1816); -#if 0 - return format; -#else - return 0; -#endif -} - -static u_int32_t -ad1816chan_setspeed(kobj_t obj, void *data, u_int32_t speed) -{ - struct ad1816_chinfo *ch = data; - struct ad1816_info *ad1816 = ch->parent; - - RANGE(speed, 4000, 55200); - ad1816_lock(ad1816); - ad1816_write(ad1816, (ch->dir == PCMDIR_PLAY)? 2 : 3, speed); - ad1816_unlock(ad1816); - return speed; -} - -static u_int32_t -ad1816chan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize) -{ - struct ad1816_chinfo *ch = data; - - ch->blksz = blocksize; - return ch->blksz; -} - -static int -ad1816chan_trigger(kobj_t obj, void *data, int go) -{ - struct ad1816_chinfo *ch = data; - struct ad1816_info *ad1816 = ch->parent; - int wr, reg; - - if (!PCMTRIG_COMMON(go)) - return 0; - - sndbuf_dma(ch->buffer, go); - wr = (ch->dir == PCMDIR_PLAY); - reg = wr? AD1816_PLAY : AD1816_CAPT; - ad1816_lock(ad1816); - switch (go) { - case PCMTRIG_START: - /* start only if not already running */ - if (!(io_rd(ad1816, reg) & AD1816_ENABLE)) { - int cnt = ((ch->blksz) >> 2) - 1; - ad1816_write(ad1816, wr? 8 : 10, cnt); /* count */ - ad1816_write(ad1816, wr? 9 : 11, 0); /* reset cur cnt */ - ad1816_write(ad1816, 1, ad1816_read(ad1816, 1) | - (wr? 0x8000 : 0x4000)); /* enable int */ - /* enable playback */ - io_wr(ad1816, reg, io_rd(ad1816, reg) | AD1816_ENABLE); - if (!(io_rd(ad1816, reg) & AD1816_ENABLE)) - printf("ad1816: failed to start %s DMA!\n", - wr? "play" : "rec"); - } - break; - - case PCMTRIG_STOP: - case PCMTRIG_ABORT: /* XXX check this... */ - /* we don't test here if it is running... */ - if (wr) { - ad1816_write(ad1816, 1, ad1816_read(ad1816, 1) & - ~(wr? 0x8000 : 0x4000)); - /* disable int */ - io_wr(ad1816, reg, io_rd(ad1816, reg) & ~AD1816_ENABLE); - /* disable playback */ - if (io_rd(ad1816, reg) & AD1816_ENABLE) - printf("ad1816: failed to stop %s DMA!\n", - wr? "play" : "rec"); - ad1816_write(ad1816, wr? 8 : 10, 0); /* reset base cnt */ - ad1816_write(ad1816, wr? 9 : 11, 0); /* reset cur cnt */ - } - break; - } - ad1816_unlock(ad1816); - return 0; -} - -static u_int32_t -ad1816chan_getptr(kobj_t obj, void *data) -{ - struct ad1816_chinfo *ch = data; - return sndbuf_dmaptr(ch->buffer); -} - -static struct pcmchan_caps * -ad1816chan_getcaps(kobj_t obj, void *data) -{ - return &ad1816_caps; -} - -static kobj_method_t ad1816chan_methods[] = { - KOBJMETHOD(channel_init, ad1816chan_init), - KOBJMETHOD(channel_setformat, ad1816chan_setformat), - KOBJMETHOD(channel_setspeed, ad1816chan_setspeed), - KOBJMETHOD(channel_setblocksize, ad1816chan_setblocksize), - KOBJMETHOD(channel_trigger, ad1816chan_trigger), - KOBJMETHOD(channel_getptr, ad1816chan_getptr), - KOBJMETHOD(channel_getcaps, ad1816chan_getcaps), - KOBJMETHOD_END -}; -CHANNEL_DECLARE(ad1816chan); - -/* -------------------------------------------------------------------- */ - -static void -ad1816_release_resources(struct ad1816_info *ad1816, device_t dev) -{ - if (ad1816->irq) { - if (ad1816->ih) - bus_teardown_intr(dev, ad1816->irq, ad1816->ih); - bus_release_resource(dev, SYS_RES_IRQ, ad1816->irq_rid, ad1816->irq); - ad1816->irq = NULL; - } - if (ad1816->drq1) { - isa_dma_release(rman_get_start(ad1816->drq1)); - bus_release_resource(dev, SYS_RES_DRQ, ad1816->drq1_rid, ad1816->drq1); - ad1816->drq1 = NULL; - } - if (ad1816->drq2) { - isa_dma_release(rman_get_start(ad1816->drq2)); - bus_release_resource(dev, SYS_RES_DRQ, ad1816->drq2_rid, ad1816->drq2); - ad1816->drq2 = NULL; - } - if (ad1816->io_base) { - bus_release_resource(dev, SYS_RES_IOPORT, ad1816->io_rid, ad1816->io_base); - ad1816->io_base = NULL; - } - if (ad1816->parent_dmat) { - bus_dma_tag_destroy(ad1816->parent_dmat); - ad1816->parent_dmat = 0; - } - if (ad1816->lock) - snd_mtxfree(ad1816->lock); - - free(ad1816, M_DEVBUF); -} - -static int -ad1816_alloc_resources(struct ad1816_info *ad1816, device_t dev) -{ - int ok = 1, pdma, rdma; - - if (!ad1816->io_base) - ad1816->io_base = bus_alloc_resource_any(dev, - SYS_RES_IOPORT, &ad1816->io_rid, RF_ACTIVE); - if (!ad1816->irq) - ad1816->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, - &ad1816->irq_rid, RF_ACTIVE); - if (!ad1816->drq1) - ad1816->drq1 = bus_alloc_resource_any(dev, SYS_RES_DRQ, - &ad1816->drq1_rid, RF_ACTIVE); - if (!ad1816->drq2) - ad1816->drq2 = bus_alloc_resource_any(dev, SYS_RES_DRQ, - &ad1816->drq2_rid, RF_ACTIVE); - - if (!ad1816->io_base || !ad1816->drq1 || !ad1816->irq) ok = 0; - - if (ok) { - pdma = rman_get_start(ad1816->drq1); - isa_dma_acquire(pdma); - isa_dmainit(pdma, ad1816->bufsize); - if (ad1816->drq2) { - rdma = rman_get_start(ad1816->drq2); - isa_dma_acquire(rdma); - isa_dmainit(rdma, ad1816->bufsize); - } else - rdma = pdma; - if (pdma == rdma) - pcm_setflags(dev, pcm_getflags(dev) | SD_F_SIMPLEX); - } - - return ok; -} - -static int -ad1816_init(struct ad1816_info *ad1816, device_t dev) -{ - ad1816_write(ad1816, 1, 0x2); /* disable interrupts */ - ad1816_write(ad1816, 32, 0x90F0); /* SoundSys Mode, split fmt */ - - ad1816_write(ad1816, 5, 0x8080); /* FM volume mute */ - ad1816_write(ad1816, 6, 0x8080); /* I2S1 volume mute */ - ad1816_write(ad1816, 7, 0x8080); /* I2S0 volume mute */ - ad1816_write(ad1816, 17, 0x8888); /* VID Volume mute */ - ad1816_write(ad1816, 20, 0x5050); /* recsrc mic, agc off */ - /* adc gain is set to 0 */ - - return 0; -} - -static int -ad1816_probe(device_t dev) -{ - char *s = NULL; - u_int32_t logical_id = isa_get_logicalid(dev); - - switch (logical_id) { - case 0x80719304: /* ADS7180 */ - s = "AD1816"; - break; - case 0x50719304: /* ADS7150 */ - s = "AD1815"; - break; - } - - if (s) { - device_set_desc(dev, s); - return BUS_PROBE_DEFAULT; - } - return ENXIO; -} - -static int -ad1816_attach(device_t dev) -{ - struct ad1816_info *ad1816; - char status[SND_STATUSLEN], status2[SND_STATUSLEN]; - - gone_in_dev(dev, 14, "ISA sound driver"); - ad1816 = malloc(sizeof(*ad1816), M_DEVBUF, M_WAITOK | M_ZERO); - ad1816->lock = snd_mtxcreate(device_get_nameunit(dev), - "snd_ad1816 softc"); - ad1816->io_rid = 2; - ad1816->irq_rid = 0; - ad1816->drq1_rid = 0; - ad1816->drq2_rid = 1; - ad1816->bufsize = pcm_getbuffersize(dev, 4096, DSP_BUFFSIZE, 65536); - - if (!ad1816_alloc_resources(ad1816, dev)) goto no; - ad1816_init(ad1816, dev); - if (mixer_init(dev, &ad1816mixer_class, ad1816)) goto no; - - snd_setup_intr(dev, ad1816->irq, 0, ad1816_intr, ad1816, &ad1816->ih); - if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(dev), /*alignment*/2, - /*boundary*/0, - /*lowaddr*/BUS_SPACE_MAXADDR_24BIT, - /*highaddr*/BUS_SPACE_MAXADDR, - /*filter*/NULL, /*filterarg*/NULL, - /*maxsize*/ad1816->bufsize, /*nsegments*/1, - /*maxsegz*/0x3ffff, - /*flags*/0, /*lockfunc*/NULL, /*lockarg*/NULL, - &ad1816->parent_dmat) != 0) { - device_printf(dev, "unable to create dma tag\n"); - goto no; - } - if (ad1816->drq2) - snprintf(status2, SND_STATUSLEN, ":%jd", rman_get_start(ad1816->drq2)); - else - status2[0] = '\0'; - - snprintf(status, SND_STATUSLEN, "at io 0x%jx irq %jd drq %jd%s bufsz %u %s", - rman_get_start(ad1816->io_base), - rman_get_start(ad1816->irq), - rman_get_start(ad1816->drq1), - status2, - ad1816->bufsize, - PCM_KLDSTRING(snd_ad1816)); - - if (pcm_register(dev, ad1816, 1, 1)) goto no; - pcm_addchan(dev, PCMDIR_REC, &ad1816chan_class, ad1816); - pcm_addchan(dev, PCMDIR_PLAY, &ad1816chan_class, ad1816); - pcm_setstatus(dev, status); - - return 0; -no: - ad1816_release_resources(ad1816, dev); - - return ENXIO; - -} - -static int -ad1816_detach(device_t dev) -{ - int r; - struct ad1816_info *ad1816; - - r = pcm_unregister(dev); - if (r) - return r; - - ad1816 = pcm_getdevinfo(dev); - ad1816_release_resources(ad1816, dev); - return 0; -} - -static device_method_t ad1816_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, ad1816_probe), - DEVMETHOD(device_attach, ad1816_attach), - DEVMETHOD(device_detach, ad1816_detach), - { 0, 0 } -}; - -static driver_t ad1816_driver = { - "pcm", - ad1816_methods, - PCM_SOFTC_SIZE, -}; - -DRIVER_MODULE(snd_ad1816, isa, ad1816_driver, pcm_devclass, 0, 0); -DRIVER_MODULE(snd_ad1816, acpi, ad1816_driver, pcm_devclass, 0, 0); -MODULE_DEPEND(snd_ad1816, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER); -MODULE_VERSION(snd_ad1816, 1); Index: sys/dev/sound/isa/ess.c =================================================================== --- sys/dev/sound/isa/ess.c +++ /dev/null @@ -1,1015 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * Copyright (c) 1999 Cameron Grant - * Copyright (c) 1997,1998 Luigi Rizzo - * - * Derived from files in the Voxware 3.5 distribution, - * Copyright by Hannu Savolainen 1994, under the same copyright - * conditions. - * All rights reserved. - * - * 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 HAVE_KERNEL_OPTION_HEADERS -#include "opt_snd.h" -#endif - -#include - -#include -#include - -#include - -#include "mixer_if.h" - -SND_DECLARE_FILE("$FreeBSD$"); - -#define ESS_BUFFSIZE (4096) -#define ABS(x) (((x) < 0)? -(x) : (x)) - -/* audio2 never generates irqs and sounds very noisy */ -#undef ESS18XX_DUPLEX - -/* more accurate clocks and split audio1/audio2 rates */ -#define ESS18XX_NEWSPEED - -static u_int32_t ess_pfmt[] = { - SND_FORMAT(AFMT_U8, 1, 0), - SND_FORMAT(AFMT_U8, 2, 0), - SND_FORMAT(AFMT_S8, 1, 0), - SND_FORMAT(AFMT_S8, 2, 0), - SND_FORMAT(AFMT_S16_LE, 1, 0), - SND_FORMAT(AFMT_S16_LE, 2, 0), - SND_FORMAT(AFMT_U16_LE, 1, 0), - SND_FORMAT(AFMT_U16_LE, 2, 0), - 0 -}; - -static struct pcmchan_caps ess_playcaps = {6000, 48000, ess_pfmt, 0}; - -static u_int32_t ess_rfmt[] = { - SND_FORMAT(AFMT_U8, 1, 0), - SND_FORMAT(AFMT_U8, 2, 0), - SND_FORMAT(AFMT_S8, 1, 0), - SND_FORMAT(AFMT_S8, 2, 0), - SND_FORMAT(AFMT_S16_LE, 1, 0), - SND_FORMAT(AFMT_S16_LE, 2, 0), - SND_FORMAT(AFMT_U16_LE, 1, 0), - SND_FORMAT(AFMT_U16_LE, 2, 0), - 0 -}; - -static struct pcmchan_caps ess_reccaps = {6000, 48000, ess_rfmt, 0}; - -struct ess_info; - -struct ess_chinfo { - struct ess_info *parent; - struct pcm_channel *channel; - struct snd_dbuf *buffer; - int dir, hwch, stopping, run; - u_int32_t fmt, spd, blksz; -}; - -struct ess_info { - device_t parent_dev; - struct resource *io_base; /* I/O address for the board */ - struct resource *irq; - struct resource *drq1; - struct resource *drq2; - void *ih; - bus_dma_tag_t parent_dmat; - - unsigned int bufsize; - int type; - unsigned int duplex:1, newspeed:1; - u_long bd_flags; /* board-specific flags */ - struct ess_chinfo pch, rch; -}; - -#if 0 -static int ess_rd(struct ess_info *sc, int reg); -static void ess_wr(struct ess_info *sc, int reg, u_int8_t val); -static int ess_dspready(struct ess_info *sc); -static int ess_cmd(struct ess_info *sc, u_char val); -static int ess_cmd1(struct ess_info *sc, u_char cmd, int val); -static int ess_get_byte(struct ess_info *sc); -static void ess_setmixer(struct ess_info *sc, u_int port, u_int value); -static int ess_getmixer(struct ess_info *sc, u_int port); -static int ess_reset_dsp(struct ess_info *sc); - -static int ess_write(struct ess_info *sc, u_char reg, int val); -static int ess_read(struct ess_info *sc, u_char reg); - -static void ess_intr(void *arg); -static int ess_setupch(struct ess_info *sc, int ch, int dir, int spd, u_int32_t fmt, int len); -static int ess_start(struct ess_chinfo *ch); -static int ess_stop(struct ess_chinfo *ch); -#endif - -/* - * Common code for the midi and pcm functions - * - * ess_cmd write a single byte to the CMD port. - * ess_cmd1 write a CMD + 1 byte arg - * ess_cmd2 write a CMD + 2 byte arg - * ess_get_byte returns a single byte from the DSP data port - * - * ess_write is actually ess_cmd1 - * ess_read access ext. regs via ess_cmd(0xc0, reg) followed by ess_get_byte - */ - -static void -ess_lock(struct ess_info *sc) { - sbc_lock(device_get_softc(sc->parent_dev)); -} - -static void -ess_unlock(struct ess_info *sc) { - sbc_unlock(device_get_softc(sc->parent_dev)); -} - -static int -port_rd(struct resource *port, int off) -{ - return bus_space_read_1(rman_get_bustag(port), - rman_get_bushandle(port), - off); -} - -static void -port_wr(struct resource *port, int off, u_int8_t data) -{ - bus_space_write_1(rman_get_bustag(port), - rman_get_bushandle(port), - off, data); -} - -static int -ess_rd(struct ess_info *sc, int reg) -{ - return port_rd(sc->io_base, reg); -} - -static void -ess_wr(struct ess_info *sc, int reg, u_int8_t val) -{ - port_wr(sc->io_base, reg, val); -} - -static int -ess_dspready(struct ess_info *sc) -{ - return ((ess_rd(sc, SBDSP_STATUS) & 0x80) == 0); -} - -static int -ess_dspwr(struct ess_info *sc, u_char val) -{ - int i; - - for (i = 0; i < 1000; i++) { - if (ess_dspready(sc)) { - ess_wr(sc, SBDSP_CMD, val); - return 1; - } - if (i > 10) DELAY((i > 100)? 1000 : 10); - } - printf("ess_dspwr(0x%02x) timed out.\n", val); - return 0; -} - -static int -ess_cmd(struct ess_info *sc, u_char val) -{ -#if 0 - printf("ess_cmd: %x\n", val); -#endif - return ess_dspwr(sc, val); -} - -static int -ess_cmd1(struct ess_info *sc, u_char cmd, int val) -{ -#if 0 - printf("ess_cmd1: %x, %x\n", cmd, val); -#endif - if (ess_dspwr(sc, cmd)) { - return ess_dspwr(sc, val & 0xff); - } else return 0; -} - -static void -ess_setmixer(struct ess_info *sc, u_int port, u_int value) -{ - DEB(printf("ess_setmixer: reg=%x, val=%x\n", port, value);) - ess_wr(sc, SB_MIX_ADDR, (u_char) (port & 0xff)); /* Select register */ - DELAY(10); - ess_wr(sc, SB_MIX_DATA, (u_char) (value & 0xff)); - DELAY(10); -} - -static int -ess_getmixer(struct ess_info *sc, u_int port) -{ - int val; - ess_wr(sc, SB_MIX_ADDR, (u_char) (port & 0xff)); /* Select register */ - DELAY(10); - val = ess_rd(sc, SB_MIX_DATA); - DELAY(10); - - return val; -} - -static int -ess_get_byte(struct ess_info *sc) -{ - int i; - - for (i = 1000; i > 0; i--) { - if (ess_rd(sc, DSP_DATA_AVAIL) & 0x80) - return ess_rd(sc, DSP_READ); - else - DELAY(20); - } - return -1; -} - -static int -ess_write(struct ess_info *sc, u_char reg, int val) -{ - return ess_cmd1(sc, reg, val); -} - -static int -ess_read(struct ess_info *sc, u_char reg) -{ - return (ess_cmd(sc, 0xc0) && ess_cmd(sc, reg))? ess_get_byte(sc) : -1; -} - -static int -ess_reset_dsp(struct ess_info *sc) -{ - ess_wr(sc, SBDSP_RST, 3); - DELAY(100); - ess_wr(sc, SBDSP_RST, 0); - if (ess_get_byte(sc) != 0xAA) { - DEB(printf("ess_reset_dsp 0x%lx failed\n", - rman_get_start(sc->io_base))); - return ENXIO; /* Sorry */ - } - ess_cmd(sc, 0xc6); - return 0; -} - -static void -ess_release_resources(struct ess_info *sc, device_t dev) -{ - if (sc->irq) { - if (sc->ih) - bus_teardown_intr(dev, sc->irq, sc->ih); - bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq); - sc->irq = NULL; - } - if (sc->drq1) { - isa_dma_release(rman_get_start(sc->drq1)); - bus_release_resource(dev, SYS_RES_DRQ, 0, sc->drq1); - sc->drq1 = NULL; - } - if (sc->drq2) { - isa_dma_release(rman_get_start(sc->drq2)); - bus_release_resource(dev, SYS_RES_DRQ, 1, sc->drq2); - sc->drq2 = NULL; - } - if (sc->io_base) { - bus_release_resource(dev, SYS_RES_IOPORT, 0, sc->io_base); - sc->io_base = NULL; - } - if (sc->parent_dmat) { - bus_dma_tag_destroy(sc->parent_dmat); - sc->parent_dmat = 0; - } - free(sc, M_DEVBUF); -} - -static int -ess_alloc_resources(struct ess_info *sc, device_t dev) -{ - int rid; - - rid = 0; - if (!sc->io_base) - sc->io_base = bus_alloc_resource_any(dev, SYS_RES_IOPORT, - &rid, RF_ACTIVE); - rid = 0; - if (!sc->irq) - sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, - &rid, RF_ACTIVE); - rid = 0; - if (!sc->drq1) - sc->drq1 = bus_alloc_resource_any(dev, SYS_RES_DRQ, - &rid, RF_ACTIVE); - rid = 1; - if (!sc->drq2) - sc->drq2 = bus_alloc_resource_any(dev, SYS_RES_DRQ, - &rid, RF_ACTIVE); - - if (sc->io_base && sc->drq1 && sc->irq) { - isa_dma_acquire(rman_get_start(sc->drq1)); - isa_dmainit(rman_get_start(sc->drq1), sc->bufsize); - - if (sc->drq2) { - isa_dma_acquire(rman_get_start(sc->drq2)); - isa_dmainit(rman_get_start(sc->drq2), sc->bufsize); - } - - return 0; - } else return ENXIO; -} - -static void -ess_intr(void *arg) -{ - struct ess_info *sc = (struct ess_info *)arg; - int src, pirq, rirq; - - ess_lock(sc); - src = 0; - if (ess_getmixer(sc, 0x7a) & 0x80) - src |= 2; - if (ess_rd(sc, 0x0c) & 0x01) - src |= 1; - - pirq = (src & sc->pch.hwch)? 1 : 0; - rirq = (src & sc->rch.hwch)? 1 : 0; - - if (pirq) { - if (sc->pch.run) { - ess_unlock(sc); - chn_intr(sc->pch.channel); - ess_lock(sc); - } - if (sc->pch.stopping) { - sc->pch.run = 0; - sndbuf_dma(sc->pch.buffer, PCMTRIG_STOP); - sc->pch.stopping = 0; - if (sc->pch.hwch == 1) - ess_write(sc, 0xb8, ess_read(sc, 0xb8) & ~0x01); - else - ess_setmixer(sc, 0x78, ess_getmixer(sc, 0x78) & ~0x03); - } - } - - if (rirq) { - if (sc->rch.run) { - ess_unlock(sc); - chn_intr(sc->rch.channel); - ess_lock(sc); - } - if (sc->rch.stopping) { - sc->rch.run = 0; - sndbuf_dma(sc->rch.buffer, PCMTRIG_STOP); - sc->rch.stopping = 0; - /* XXX: will this stop audio2? */ - ess_write(sc, 0xb8, ess_read(sc, 0xb8) & ~0x01); - } - } - - if (src & 2) - ess_setmixer(sc, 0x7a, ess_getmixer(sc, 0x7a) & ~0x80); - if (src & 1) - ess_rd(sc, DSP_DATA_AVAIL); - ess_unlock(sc); -} - -/* utility functions for ESS */ -static u_int8_t -ess_calcspeed8(int *spd) -{ - int speed = *spd; - u_int32_t t; - - 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; - } - *spd = speed; - return t & 0x000000ff; -} - -static u_int8_t -ess_calcspeed9(int *spd) -{ - int speed, s0, s1, use0; - u_int8_t t0, t1; - - /* rate = source / (256 - divisor) */ - /* divisor = 256 - (source / rate) */ - speed = *spd; - t0 = 128 - (793800 / speed); - s0 = 793800 / (128 - t0); - - t1 = 128 - (768000 / speed); - s1 = 768000 / (128 - t1); - t1 |= 0x80; - - use0 = (ABS(speed - s0) < ABS(speed - s1))? 1 : 0; - - *spd = use0? s0 : s1; - return use0? t0 : t1; -} - -static u_int8_t -ess_calcfilter(int spd) -{ - int cutoff; - - /* cutoff = 7160000 / (256 - divisor) */ - /* divisor = 256 - (7160000 / cutoff) */ - cutoff = (spd * 9 * 82) / 20; - return (256 - (7160000 / cutoff)); -} - -static int -ess_setupch(struct ess_info *sc, int ch, int dir, int spd, u_int32_t fmt, int len) -{ - int play = (dir == PCMDIR_PLAY)? 1 : 0; - int b16 = (fmt & AFMT_16BIT)? 1 : 0; - int stereo = (AFMT_CHANNEL(fmt) > 1)? 1 : 0; - int unsign = (fmt == AFMT_U8 || fmt == AFMT_U16_LE)? 1 : 0; - u_int8_t spdval, fmtval; - - spdval = (sc->newspeed)? ess_calcspeed9(&spd) : ess_calcspeed8(&spd); - len = -len; - - if (ch == 1) { - KASSERT((dir == PCMDIR_PLAY) || (dir == PCMDIR_REC), ("ess_setupch: dir1 bad")); - /* transfer length low */ - ess_write(sc, 0xa4, len & 0x00ff); - /* transfer length high */ - ess_write(sc, 0xa5, (len & 0xff00) >> 8); - /* autoinit, dma dir */ - ess_write(sc, 0xb8, 0x04 | (play? 0x00 : 0x0a)); - /* mono/stereo */ - ess_write(sc, 0xa8, (ess_read(sc, 0xa8) & ~0x03) | (stereo? 0x01 : 0x02)); - /* demand mode, 4 bytes/xfer */ - ess_write(sc, 0xb9, 0x02); - /* sample rate */ - ess_write(sc, 0xa1, spdval); - /* filter cutoff */ - ess_write(sc, 0xa2, ess_calcfilter(spd)); - /* setup dac/adc */ - if (play) - ess_write(sc, 0xb6, unsign? 0x80 : 0x00); - /* mono, b16: signed, load signal */ - ess_write(sc, 0xb7, 0x51 | (unsign? 0x00 : 0x20)); - /* setup fifo */ - ess_write(sc, 0xb7, 0x90 | (unsign? 0x00 : 0x20) | - (b16? 0x04 : 0x00) | - (stereo? 0x08 : 0x40)); - /* irq control */ - ess_write(sc, 0xb1, (ess_read(sc, 0xb1) & 0x0f) | 0x50); - /* drq control */ - ess_write(sc, 0xb2, (ess_read(sc, 0xb2) & 0x0f) | 0x50); - } else if (ch == 2) { - KASSERT(dir == PCMDIR_PLAY, ("ess_setupch: dir2 bad")); - /* transfer length low */ - ess_setmixer(sc, 0x74, len & 0x00ff); - /* transfer length high */ - ess_setmixer(sc, 0x76, (len & 0xff00) >> 8); - /* autoinit, 4 bytes/req */ - ess_setmixer(sc, 0x78, 0x90); - fmtval = b16 | (stereo << 1) | (unsign << 2); - /* enable irq, set format */ - ess_setmixer(sc, 0x7a, 0x40 | fmtval); - if (sc->newspeed) { - /* sample rate */ - ess_setmixer(sc, 0x70, spdval); - /* filter cutoff */ - ess_setmixer(sc, 0x72, ess_calcfilter(spd)); - } - } - - return 0; -} -static int -ess_start(struct ess_chinfo *ch) -{ - struct ess_info *sc = ch->parent; - int play = (ch->dir == PCMDIR_PLAY)? 1 : 0; - - ess_lock(sc); - ess_setupch(sc, ch->hwch, ch->dir, ch->spd, ch->fmt, ch->blksz); - ch->stopping = 0; - if (ch->hwch == 1) - ess_write(sc, 0xb8, ess_read(sc, 0xb8) | 0x01); - else - ess_setmixer(sc, 0x78, ess_getmixer(sc, 0x78) | 0x03); - if (play) - ess_cmd(sc, DSP_CMD_SPKON); - ess_unlock(sc); - return 0; -} - -static int -ess_stop(struct ess_chinfo *ch) -{ - struct ess_info *sc = ch->parent; - int play = (ch->dir == PCMDIR_PLAY)? 1 : 0; - - ess_lock(sc); - ch->stopping = 1; - if (ch->hwch == 1) - ess_write(sc, 0xb8, ess_read(sc, 0xb8) & ~0x04); - else - ess_setmixer(sc, 0x78, ess_getmixer(sc, 0x78) & ~0x10); - if (play) - ess_cmd(sc, DSP_CMD_SPKOFF); - ess_unlock(sc); - return 0; -} - -/* -------------------------------------------------------------------- */ -/* channel interface for ESS18xx */ -static void * -esschan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir) -{ - struct ess_info *sc = devinfo; - struct ess_chinfo *ch = (dir == PCMDIR_PLAY)? &sc->pch : &sc->rch; - - ch->parent = sc; - ch->channel = c; - ch->buffer = b; - if (sndbuf_alloc(ch->buffer, sc->parent_dmat, 0, sc->bufsize) != 0) - return NULL; - ch->dir = dir; - ch->hwch = 1; - if ((dir == PCMDIR_PLAY) && (sc->duplex)) - ch->hwch = 2; - sndbuf_dmasetup(ch->buffer, (ch->hwch == 1)? sc->drq1 : sc->drq2); - return ch; -} - -static int -esschan_setformat(kobj_t obj, void *data, u_int32_t format) -{ - struct ess_chinfo *ch = data; - - ch->fmt = format; - return 0; -} - -static u_int32_t -esschan_setspeed(kobj_t obj, void *data, u_int32_t speed) -{ - struct ess_chinfo *ch = data; - struct ess_info *sc = ch->parent; - - ch->spd = speed; - if (sc->newspeed) - ess_calcspeed9(&ch->spd); - else - ess_calcspeed8(&ch->spd); - return ch->spd; -} - -static u_int32_t -esschan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize) -{ - struct ess_chinfo *ch = data; - - ch->blksz = blocksize; - return ch->blksz; -} - -static int -esschan_trigger(kobj_t obj, void *data, int go) -{ - struct ess_chinfo *ch = data; - - if (!PCMTRIG_COMMON(go)) - return 0; - - switch (go) { - case PCMTRIG_START: - ch->run = 1; - sndbuf_dma(ch->buffer, go); - ess_start(ch); - break; - - case PCMTRIG_STOP: - case PCMTRIG_ABORT: - default: - ess_stop(ch); - break; - } - return 0; -} - -static u_int32_t -esschan_getptr(kobj_t obj, void *data) -{ - struct ess_chinfo *ch = data; - - return sndbuf_dmaptr(ch->buffer); -} - -static struct pcmchan_caps * -esschan_getcaps(kobj_t obj, void *data) -{ - struct ess_chinfo *ch = data; - - return (ch->dir == PCMDIR_PLAY)? &ess_playcaps : &ess_reccaps; -} - -static kobj_method_t esschan_methods[] = { - KOBJMETHOD(channel_init, esschan_init), - KOBJMETHOD(channel_setformat, esschan_setformat), - KOBJMETHOD(channel_setspeed, esschan_setspeed), - KOBJMETHOD(channel_setblocksize, esschan_setblocksize), - KOBJMETHOD(channel_trigger, esschan_trigger), - KOBJMETHOD(channel_getptr, esschan_getptr), - KOBJMETHOD(channel_getcaps, esschan_getcaps), - KOBJMETHOD_END -}; -CHANNEL_DECLARE(esschan); - -/************************************************************/ - -static int -essmix_init(struct snd_mixer *m) -{ - struct ess_info *sc = mix_getdevinfo(m); - - mix_setrecdevs(m, SOUND_MASK_CD | SOUND_MASK_MIC | SOUND_MASK_LINE | - SOUND_MASK_IMIX); - - mix_setdevs(m, SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_LINE | - SOUND_MASK_MIC | SOUND_MASK_CD | SOUND_MASK_VOLUME | - SOUND_MASK_LINE1 | SOUND_MASK_SPEAKER); - - ess_setmixer(sc, 0, 0); /* reset */ - - return 0; -} - -static int -essmix_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right) -{ - struct ess_info *sc = mix_getdevinfo(m); - int preg = 0, rreg = 0, l, r; - - l = (left * 15) / 100; - r = (right * 15) / 100; - switch (dev) { - case SOUND_MIXER_SYNTH: - preg = 0x36; - rreg = 0x6b; - break; - - case SOUND_MIXER_PCM: - preg = 0x14; - rreg = 0x7c; - break; - - case SOUND_MIXER_LINE: - preg = 0x3e; - rreg = 0x6e; - break; - - case SOUND_MIXER_MIC: - preg = 0x1a; - rreg = 0x68; - break; - - case SOUND_MIXER_LINE1: - preg = 0x3a; - rreg = 0x6c; - break; - - case SOUND_MIXER_CD: - preg = 0x38; - rreg = 0x6a; - break; - - case SOUND_MIXER_SPEAKER: - preg = 0x3c; - break; - - case SOUND_MIXER_VOLUME: - l = left? (left * 63) / 100 : 64; - r = right? (right * 63) / 100 : 64; - ess_setmixer(sc, 0x60, l); - ess_setmixer(sc, 0x62, r); - left = (l == 64)? 0 : (l * 100) / 63; - right = (r == 64)? 0 : (r * 100) / 63; - return left | (right << 8); - } - - if (preg) - ess_setmixer(sc, preg, (l << 4) | r); - if (rreg) - ess_setmixer(sc, rreg, (l << 4) | r); - - left = (l * 100) / 15; - right = (r * 100) / 15; - - return left | (right << 8); -} - -static u_int32_t -essmix_setrecsrc(struct snd_mixer *m, u_int32_t src) -{ - struct ess_info *sc = mix_getdevinfo(m); - u_char recdev; - - switch (src) { - case SOUND_MASK_CD: - recdev = 0x02; - break; - - case SOUND_MASK_LINE: - recdev = 0x06; - break; - - case SOUND_MASK_IMIX: - recdev = 0x05; - break; - - case SOUND_MASK_MIC: - default: - recdev = 0x00; - src = SOUND_MASK_MIC; - break; - } - - ess_setmixer(sc, 0x1c, recdev); - - return src; -} - -static kobj_method_t essmixer_methods[] = { - KOBJMETHOD(mixer_init, essmix_init), - KOBJMETHOD(mixer_set, essmix_set), - KOBJMETHOD(mixer_setrecsrc, essmix_setrecsrc), - KOBJMETHOD_END -}; -MIXER_DECLARE(essmixer); - -/************************************************************/ - -static int -ess_probe(device_t dev) -{ - uintptr_t func, ver, r, f; - - /* The parent device has already been probed. */ - r = BUS_READ_IVAR(device_get_parent(dev), dev, 0, &func); - if (func != SCF_PCM) - return (ENXIO); - - r = BUS_READ_IVAR(device_get_parent(dev), dev, 1, &ver); - f = (ver & 0xffff0000) >> 16; - if (!(f & BD_F_ESS)) - return (ENXIO); - - device_set_desc(dev, "ESS 18xx DSP"); - - return 0; -} - -static int -ess_attach(device_t dev) -{ - struct ess_info *sc; - char status[SND_STATUSLEN], buf[64]; - int ver; - - gone_in_dev(dev, 14, "ISA sound driver"); - sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO); - sc->parent_dev = device_get_parent(dev); - sc->bufsize = pcm_getbuffersize(dev, 4096, ESS_BUFFSIZE, 65536); - if (ess_alloc_resources(sc, dev)) - goto no; - if (ess_reset_dsp(sc)) - goto no; - if (mixer_init(dev, &essmixer_class, sc)) - goto no; - - sc->duplex = 0; - sc->newspeed = 0; - ver = (ess_getmixer(sc, 0x40) << 8) | ess_rd(sc, SB_MIX_DATA); - snprintf(buf, sizeof buf, "ESS %x DSP", ver); - device_set_desc_copy(dev, buf); - if (bootverbose) - device_printf(dev, "ESS%x detected", ver); - - switch (ver) { - case 0x1869: - case 0x1879: -#ifdef ESS18XX_DUPLEX - sc->duplex = sc->drq2? 1 : 0; -#endif -#ifdef ESS18XX_NEWSPEED - sc->newspeed = 1; -#endif - break; - } - if (bootverbose) - printf("%s%s\n", sc->duplex? ", duplex" : "", - sc->newspeed? ", newspeed" : ""); - - if (sc->newspeed) - ess_setmixer(sc, 0x71, 0x22); - - snd_setup_intr(dev, sc->irq, 0, ess_intr, sc, &sc->ih); - if (!sc->duplex) - pcm_setflags(dev, pcm_getflags(dev) | SD_F_SIMPLEX); - - if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(dev), /*alignment*/2, - /*boundary*/0, - /*lowaddr*/BUS_SPACE_MAXADDR_24BIT, - /*highaddr*/BUS_SPACE_MAXADDR, - /*filter*/NULL, /*filterarg*/NULL, - /*maxsize*/sc->bufsize, /*nsegments*/1, - /*maxsegz*/0x3ffff, - /*flags*/0, /*lockfunc*/NULL, /*lockarg*/NULL, - &sc->parent_dmat) != 0) { - device_printf(dev, "unable to create dma tag\n"); - goto no; - } - - if (sc->drq2) - snprintf(buf, SND_STATUSLEN, ":%jd", rman_get_start(sc->drq2)); - else - buf[0] = '\0'; - - snprintf(status, SND_STATUSLEN, "at io 0x%jx irq %jd drq %jd%s bufsz %u %s", - rman_get_start(sc->io_base), rman_get_start(sc->irq), - rman_get_start(sc->drq1), buf, sc->bufsize, - PCM_KLDSTRING(snd_ess)); - - if (pcm_register(dev, sc, 1, 1)) - goto no; - pcm_addchan(dev, PCMDIR_REC, &esschan_class, sc); - pcm_addchan(dev, PCMDIR_PLAY, &esschan_class, sc); - pcm_setstatus(dev, status); - - return 0; - -no: - ess_release_resources(sc, dev); - return ENXIO; -} - -static int -ess_detach(device_t dev) -{ - int r; - struct ess_info *sc; - - r = pcm_unregister(dev); - if (r) - return r; - - sc = pcm_getdevinfo(dev); - ess_release_resources(sc, dev); - return 0; -} - -static int -ess_resume(device_t dev) -{ - struct ess_info *sc; - - sc = pcm_getdevinfo(dev); - - if (ess_reset_dsp(sc)) { - device_printf(dev, "unable to reset DSP at resume\n"); - return ENXIO; - } - - if (mixer_reinit(dev)) { - device_printf(dev, "unable to reinitialize mixer at resume\n"); - return ENXIO; - } - - return 0; -} - -static device_method_t ess_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, ess_probe), - DEVMETHOD(device_attach, ess_attach), - DEVMETHOD(device_detach, ess_detach), - DEVMETHOD(device_resume, ess_resume), - { 0, 0 } -}; - -static driver_t ess_driver = { - "pcm", - ess_methods, - PCM_SOFTC_SIZE, -}; - -DRIVER_MODULE(snd_ess, sbc, ess_driver, pcm_devclass, 0, 0); -MODULE_DEPEND(snd_ess, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER); -MODULE_DEPEND(snd_ess, snd_sbc, 1, 1, 1); -MODULE_VERSION(snd_ess, 1); - -/************************************************************/ - -static devclass_t esscontrol_devclass; - -static struct isa_pnp_id essc_ids[] = { - {0x06007316, "ESS Control"}, - {0} -}; - -static int -esscontrol_probe(device_t dev) -{ - int i; - - i = ISA_PNP_PROBE(device_get_parent(dev), dev, essc_ids); - if (i == 0) - device_quiet(dev); - return i; -} - -static int -esscontrol_attach(device_t dev) -{ -#ifdef notyet - struct resource *io; - int rid, i, x; - - rid = 0; - io = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE); - x = 0; - for (i = 0; i < 0x100; i++) { - port_wr(io, 0, i); - x = port_rd(io, 1); - if ((i & 0x0f) == 0) - printf("%3.3x: ", i); - printf("%2.2x ", x); - if ((i & 0x0f) == 0x0f) - printf("\n"); - } - bus_release_resource(dev, SYS_RES_IOPORT, 0, io); - io = NULL; -#endif - - return 0; -} - -static int -esscontrol_detach(device_t dev) -{ - return 0; -} - -static device_method_t esscontrol_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, esscontrol_probe), - DEVMETHOD(device_attach, esscontrol_attach), - DEVMETHOD(device_detach, esscontrol_detach), - { 0, 0 } -}; - -static driver_t esscontrol_driver = { - "esscontrol", - esscontrol_methods, - 1, -}; - -DRIVER_MODULE(esscontrol, isa, esscontrol_driver, esscontrol_devclass, 0, 0); -DRIVER_MODULE(esscontrol, acpi, esscontrol_driver, esscontrol_devclass, 0, 0); -ISA_PNP_INFO(essc_ids); Index: sys/dev/sound/isa/gusc.c =================================================================== --- sys/dev/sound/isa/gusc.c +++ /dev/null @@ -1,676 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * Copyright (c) 1999 Seigo Tanimura - * Copyright (c) 1999 Ville-Pertti Keinonen - * All rights reserved. - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef HAVE_KERNEL_OPTION_HEADERS -#include "opt_snd.h" -#endif - -#include -#include -#include "bus_if.h" - -#include -#include - -SND_DECLARE_FILE("$FreeBSD$"); - -#define LOGICALID_NOPNP 0 -#define LOGICALID_PCM 0x0000561e -#define LOGICALID_OPL 0x0300561e -#define LOGICALID_MIDI 0x0400561e - -/* PnP IDs */ -static struct isa_pnp_id gusc_ids[] = { - {LOGICALID_PCM, "GRV0000 Gravis UltraSound PnP PCM"}, /* GRV0000 */ - {LOGICALID_OPL, "GRV0003 Gravis UltraSound PnP OPL"}, /* GRV0003 */ - {LOGICALID_MIDI, "GRV0004 Gravis UltraSound PnP MIDI"}, /* GRV0004 */ -}; - -/* Interrupt handler. */ -struct gusc_ihandler { - void (*intr)(void *); - void *arg; -}; - -/* Here is the parameter structure per a device. */ -struct gusc_softc { - device_t dev; /* device */ - int io_rid[3]; /* io port rids */ - struct resource *io[3]; /* io port resources */ - int io_alloced[3]; /* io port alloc flag */ - int irq_rid; /* irq rids */ - struct resource *irq; /* irq resources */ - int irq_alloced; /* irq alloc flag */ - int drq_rid[2]; /* drq rids */ - struct resource *drq[2]; /* drq resources */ - int drq_alloced[2]; /* drq alloc flag */ - - /* Interrupts are shared (XXX non-PnP only?) */ - struct gusc_ihandler midi_intr; - struct gusc_ihandler pcm_intr; -}; - -typedef struct gusc_softc *sc_p; - -static int gusc_probe(device_t dev); -static int gusc_attach(device_t dev); -static int gusisa_probe(device_t dev); -static void gusc_intr(void *); -static struct resource *gusc_alloc_resource(device_t bus, device_t child, int type, int *rid, - rman_res_t start, rman_res_t end, rman_res_t count, u_int flags); -static int gusc_release_resource(device_t bus, device_t child, int type, int rid, - struct resource *r); - -static device_t find_masterdev(sc_p scp); -static int alloc_resource(sc_p scp); -static int release_resource(sc_p scp); - -static devclass_t gusc_devclass; - -static int -gusc_probe(device_t dev) -{ - device_t child; - u_int32_t logical_id; - char *s; - struct sndcard_func *func; - int ret; - - logical_id = isa_get_logicalid(dev); - s = NULL; - - /* Check isapnp ids */ - if (logical_id != 0 && (ret = ISA_PNP_PROBE(device_get_parent(dev), dev, gusc_ids)) != 0) - return (ret); - else { - if (logical_id == 0) - return gusisa_probe(dev); - } - - switch (logical_id) { - case LOGICALID_PCM: - s = "Gravis UltraSound Plug & Play PCM"; - func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO); - if (func == NULL) - return (ENOMEM); - func->func = SCF_PCM; - child = device_add_child(dev, "pcm", -1); - device_set_ivars(child, func); - break; - case LOGICALID_OPL: - s = "Gravis UltraSound Plug & Play OPL"; - func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO); - if (func == NULL) - return (ENOMEM); - func->func = SCF_SYNTH; - child = device_add_child(dev, "midi", -1); - device_set_ivars(child, func); - break; - case LOGICALID_MIDI: - s = "Gravis UltraSound Plug & Play MIDI"; - func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO); - if (func == NULL) - return (ENOMEM); - func->func = SCF_MIDI; - child = device_add_child(dev, "midi", -1); - device_set_ivars(child, func); - break; - } - - if (s != NULL) { - device_set_desc(dev, s); - return (0); - } - - return (ENXIO); -} - -static void -port_wr(struct resource *r, int i, unsigned char v) -{ - bus_space_write_1(rman_get_bustag(r), rman_get_bushandle(r), i, v); -} - -static int -port_rd(struct resource *r, int i) -{ - return bus_space_read_1(rman_get_bustag(r), rman_get_bushandle(r), i); -} - -/* - * Probe for an old (non-PnP) GUS card on the ISA bus. - */ - -static int -gusisa_probe(device_t dev) -{ - device_t child; - struct resource *res, *res2; - int base, rid, rid2, s, flags; - unsigned char val; - - base = isa_get_port(dev); - flags = device_get_flags(dev); - rid = 1; - res = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, base + 0x100, - base + 0x107, 8, RF_ACTIVE); - - if (res == NULL) - return ENXIO; - - res2 = NULL; - - /* - * Check for the presence of some GUS card. Reset the card, - * then see if we can access the memory on it. - */ - - port_wr(res, 3, 0x4c); - port_wr(res, 5, 0); - DELAY(30 * 1000); - - port_wr(res, 3, 0x4c); - port_wr(res, 5, 1); - DELAY(30 * 1000); - - s = splhigh(); - - /* Write to DRAM. */ - - port_wr(res, 3, 0x43); /* Register select */ - port_wr(res, 4, 0); /* Low addr */ - port_wr(res, 5, 0); /* Med addr */ - - port_wr(res, 3, 0x44); /* Register select */ - port_wr(res, 4, 0); /* High addr */ - port_wr(res, 7, 0x55); /* DRAM */ - - /* Read from DRAM. */ - - port_wr(res, 3, 0x43); /* Register select */ - port_wr(res, 4, 0); /* Low addr */ - port_wr(res, 5, 0); /* Med addr */ - - port_wr(res, 3, 0x44); /* Register select */ - port_wr(res, 4, 0); /* High addr */ - val = port_rd(res, 7); /* DRAM */ - - splx(s); - - if (val != 0x55) - goto fail; - - rid2 = 0; - res2 = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid2, base, base, 1, - RF_ACTIVE); - - if (res2 == NULL) - goto fail; - - s = splhigh(); - port_wr(res2, 0x0f, 0x20); - val = port_rd(res2, 0x0f); - splx(s); - - if (val == 0xff || (val & 0x06) == 0) - val = 0; - else { - val = port_rd(res2, 0x506); /* XXX Out of range. */ - if (val == 0xff) - val = 0; - } - - bus_release_resource(dev, SYS_RES_IOPORT, rid2, res2); - bus_release_resource(dev, SYS_RES_IOPORT, rid, res); - - if (val >= 10) { - struct sndcard_func *func; - - /* Looks like a GUS MAX. Set the rest of the resources. */ - - bus_set_resource(dev, SYS_RES_IOPORT, 2, base + 0x10c, 8); - - if (flags & DV_F_DUAL_DMA) - bus_set_resource(dev, SYS_RES_DRQ, 1, - flags & DV_F_DRQ_MASK, 1); - - /* We can support the CS4231 and MIDI devices. */ - - func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO); - if (func == NULL) - return ENOMEM; - func->func = SCF_MIDI; - child = device_add_child(dev, "midi", -1); - device_set_ivars(child, func); - - func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO); - if (func == NULL) - printf("xxx: gus pcm not attached, out of memory\n"); - else { - func->func = SCF_PCM; - child = device_add_child(dev, "pcm", -1); - device_set_ivars(child, func); - } - device_set_desc(dev, "Gravis UltraSound MAX"); - return 0; - } else { - /* - * TODO: Support even older GUS cards. MIDI should work on - * all models. - */ - return ENXIO; - } - -fail: - bus_release_resource(dev, SYS_RES_IOPORT, rid, res); - return ENXIO; -} - -static int -gusc_attach(device_t dev) -{ - sc_p scp; - void *ih; - - gone_in_dev(dev, 14, "ISA sound driver"); - scp = device_get_softc(dev); - - bzero(scp, sizeof(*scp)); - - scp->dev = dev; - if (alloc_resource(scp)) { - release_resource(scp); - return (ENXIO); - } - - if (scp->irq != NULL) - snd_setup_intr(dev, scp->irq, 0, gusc_intr, scp, &ih); - bus_generic_attach(dev); - - return (0); -} - -/* - * Handle interrupts on GUS devices until there aren't any left. - */ -static void -gusc_intr(void *arg) -{ - sc_p scp = (sc_p)arg; - int did_something; - - do { - did_something = 0; - if (scp->pcm_intr.intr != NULL && - (port_rd(scp->io[2], 2) & 1)) { - (*scp->pcm_intr.intr)(scp->pcm_intr.arg); - did_something = 1; - } - if (scp->midi_intr.intr != NULL && - (port_rd(scp->io[1], 0) & 0x80)) { - (*scp->midi_intr.intr)(scp->midi_intr.arg); - did_something = 1; - } - } while (did_something != 0); -} - -static struct resource * -gusc_alloc_resource(device_t bus, device_t child, int type, int *rid, - rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) -{ - sc_p scp; - int *alloced, rid_max, alloced_max; - struct resource **res; - - scp = device_get_softc(bus); - switch (type) { - case SYS_RES_IOPORT: - alloced = scp->io_alloced; - res = scp->io; - rid_max = 2; - alloced_max = 2; /* pcm + midi (more to include synth) */ - break; - case SYS_RES_IRQ: - alloced = &scp->irq_alloced; - res = &scp->irq; - rid_max = 0; - alloced_max = 2; /* pcm and midi share the single irq. */ - break; - case SYS_RES_DRQ: - alloced = scp->drq_alloced; - res = scp->drq; - rid_max = 1; - alloced_max = 1; - break; - default: - return (NULL); - } - - if (*rid > rid_max || alloced[*rid] == alloced_max) - return (NULL); - - alloced[*rid]++; - return (res[*rid]); -} - -static int -gusc_release_resource(device_t bus, device_t child, int type, int rid, - struct resource *r) -{ - sc_p scp; - int *alloced, rid_max; - - scp = device_get_softc(bus); - switch (type) { - case SYS_RES_IOPORT: - alloced = scp->io_alloced; - rid_max = 2; - break; - case SYS_RES_IRQ: - alloced = &scp->irq_alloced; - rid_max = 0; - break; - case SYS_RES_DRQ: - alloced = scp->drq_alloced; - rid_max = 1; - break; - default: - return (1); - } - - if (rid > rid_max || alloced[rid] == 0) - return (1); - - alloced[rid]--; - return (0); -} - -static int -gusc_setup_intr(device_t dev, device_t child, struct resource *irq, int flags, - driver_filter_t *filter, - driver_intr_t *intr, void *arg, void **cookiep) -{ - sc_p scp = (sc_p)device_get_softc(dev); - devclass_t devclass; - - if (filter != NULL) { - printf("gusc.c: we cannot use a filter here\n"); - return (EINVAL); - } - devclass = device_get_devclass(child); - if (strcmp(devclass_get_name(devclass), "midi") == 0) { - scp->midi_intr.intr = intr; - scp->midi_intr.arg = arg; - return 0; - } else if (strcmp(devclass_get_name(devclass), "pcm") == 0) { - scp->pcm_intr.intr = intr; - scp->pcm_intr.arg = arg; - return 0; - } - return bus_generic_setup_intr(dev, child, irq, flags, - filter, - intr, arg, cookiep); -} - -static device_t -find_masterdev(sc_p scp) -{ - int i, units; - devclass_t devclass; - device_t dev; - - devclass = device_get_devclass(scp->dev); - units = devclass_get_maxunit(devclass); - dev = NULL; - for (i = 0 ; i < units ; i++) { - dev = devclass_get_device(devclass, i); - if (isa_get_vendorid(dev) == isa_get_vendorid(scp->dev) - && isa_get_logicalid(dev) == LOGICALID_PCM - && isa_get_serial(dev) == isa_get_serial(scp->dev)) - break; - } - if (i == units) - return (NULL); - - return (dev); -} - -static int io_range[3] = {0x10, 0x8 , 0x4 }; -static int io_offset[3] = {0x0 , 0x100, 0x10c}; -static int -alloc_resource(sc_p scp) -{ - int i, base, lid, flags; - device_t dev; - - flags = 0; - if (isa_get_vendorid(scp->dev)) - lid = isa_get_logicalid(scp->dev); - else { - lid = LOGICALID_NOPNP; - flags = device_get_flags(scp->dev); - } - switch(lid) { - case LOGICALID_PCM: - case LOGICALID_NOPNP: /* XXX Non-PnP */ - if (lid == LOGICALID_NOPNP) - base = isa_get_port(scp->dev); - else - base = 0; - for (i = 0 ; i < nitems(scp->io); i++) { - if (scp->io[i] == NULL) { - scp->io_rid[i] = i; - if (base == 0) - scp->io[i] = - bus_alloc_resource_anywhere(scp->dev, - SYS_RES_IOPORT, - &scp->io_rid[i], - io_range[i], - RF_ACTIVE); - else - scp->io[i] = bus_alloc_resource(scp->dev, SYS_RES_IOPORT, &scp->io_rid[i], - base + io_offset[i], - base + io_offset[i] + io_range[i] - 1 - , io_range[i], RF_ACTIVE); - if (scp->io[i] == NULL) - return (1); - scp->io_alloced[i] = 0; - } - } - if (scp->irq == NULL) { - scp->irq_rid = 0; - scp->irq = - bus_alloc_resource_any(scp->dev, SYS_RES_IRQ, - &scp->irq_rid, - RF_ACTIVE|RF_SHAREABLE); - if (scp->irq == NULL) - return (1); - scp->irq_alloced = 0; - } - for (i = 0 ; i < nitems(scp->drq); i++) { - if (scp->drq[i] == NULL) { - scp->drq_rid[i] = i; - if (base == 0 || i == 0) - scp->drq[i] = - bus_alloc_resource_any( - scp->dev, SYS_RES_DRQ, - &scp->drq_rid[i], - RF_ACTIVE); - else if ((flags & DV_F_DUAL_DMA) != 0) - /* XXX The secondary drq is specified in the flag. */ - scp->drq[i] = bus_alloc_resource(scp->dev, SYS_RES_DRQ, &scp->drq_rid[i], - flags & DV_F_DRQ_MASK, - flags & DV_F_DRQ_MASK, 1, RF_ACTIVE); - if (scp->drq[i] == NULL) - return (1); - scp->drq_alloced[i] = 0; - } - } - break; - case LOGICALID_OPL: - if (scp->io[0] == NULL) { - scp->io_rid[0] = 0; - scp->io[0] = bus_alloc_resource_anywhere(scp->dev, - SYS_RES_IOPORT, - &scp->io_rid[0], - io_range[0], - RF_ACTIVE); - if (scp->io[0] == NULL) - return (1); - scp->io_alloced[0] = 0; - } - break; - case LOGICALID_MIDI: - if (scp->io[0] == NULL) { - scp->io_rid[0] = 0; - scp->io[0] = bus_alloc_resource_anywhere(scp->dev, - SYS_RES_IOPORT, - &scp->io_rid[0], - io_range[0], - RF_ACTIVE); - if (scp->io[0] == NULL) - return (1); - scp->io_alloced[0] = 0; - } - if (scp->irq == NULL) { - /* The irq is shared with pcm audio. */ - dev = find_masterdev(scp); - if (dev == NULL) - return (1); - scp->irq_rid = 0; - scp->irq = BUS_ALLOC_RESOURCE(dev, NULL, SYS_RES_IRQ, &scp->irq_rid, - 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE); - if (scp->irq == NULL) - return (1); - scp->irq_alloced = 0; - } - break; - } - return (0); -} - -static int -release_resource(sc_p scp) -{ - int i, lid; - device_t dev; - - if (isa_get_vendorid(scp->dev)) - lid = isa_get_logicalid(scp->dev); - else - lid = LOGICALID_NOPNP; - - switch(lid) { - case LOGICALID_PCM: - case LOGICALID_NOPNP: /* XXX Non-PnP */ - for (i = 0 ; i < nitems(scp->io); i++) { - if (scp->io[i] != NULL) { - bus_release_resource(scp->dev, SYS_RES_IOPORT, scp->io_rid[i], scp->io[i]); - scp->io[i] = NULL; - } - } - if (scp->irq != NULL) { - bus_release_resource(scp->dev, SYS_RES_IRQ, scp->irq_rid, scp->irq); - scp->irq = NULL; - } - for (i = 0 ; i < nitems(scp->drq); i++) { - if (scp->drq[i] != NULL) { - bus_release_resource(scp->dev, SYS_RES_DRQ, scp->drq_rid[i], scp->drq[i]); - scp->drq[i] = NULL; - } - } - break; - case LOGICALID_OPL: - if (scp->io[0] != NULL) { - bus_release_resource(scp->dev, SYS_RES_IOPORT, scp->io_rid[0], scp->io[0]); - scp->io[0] = NULL; - } - break; - case LOGICALID_MIDI: - if (scp->io[0] != NULL) { - bus_release_resource(scp->dev, SYS_RES_IOPORT, scp->io_rid[0], scp->io[0]); - scp->io[0] = NULL; - } - if (scp->irq != NULL) { - /* The irq is shared with pcm audio. */ - dev = find_masterdev(scp); - if (dev == NULL) - return (1); - BUS_RELEASE_RESOURCE(dev, NULL, SYS_RES_IOPORT, scp->irq_rid, scp->irq); - scp->irq = NULL; - } - break; - } - return (0); -} - -static device_method_t gusc_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, gusc_probe), - DEVMETHOD(device_attach, gusc_attach), - DEVMETHOD(device_detach, bus_generic_detach), - DEVMETHOD(device_shutdown, bus_generic_shutdown), - DEVMETHOD(device_suspend, bus_generic_suspend), - DEVMETHOD(device_resume, bus_generic_resume), - - /* Bus interface */ - DEVMETHOD(bus_alloc_resource, gusc_alloc_resource), - DEVMETHOD(bus_release_resource, gusc_release_resource), - DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), - DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), - DEVMETHOD(bus_setup_intr, gusc_setup_intr), - DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), - - DEVMETHOD_END -}; - -static driver_t gusc_driver = { - "gusc", - gusc_methods, - sizeof(struct gusc_softc), -}; - -/* - * gusc can be attached to an isa bus. - */ -DRIVER_MODULE(snd_gusc, isa, gusc_driver, gusc_devclass, 0, 0); -DRIVER_MODULE(snd_gusc, acpi, gusc_driver, gusc_devclass, 0, 0); -MODULE_DEPEND(snd_gusc, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER); -MODULE_VERSION(snd_gusc, 1); -ISA_PNP_INFO(gusc_ids); Index: sys/dev/sound/isa/mss.h =================================================================== --- sys/dev/sound/isa/mss.h +++ /dev/null @@ -1,411 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * Copyright (c) 1999 Doug Rabson - * Copyright (c) 1997 Luigi Rizzo - * All rights reserved. - * - * 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. - * - * $FreeBSD$ - */ - -/* - * 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. - - * - */ - -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]; - -#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) - -/* - * The four visible registers of the MSS : - * - */ - -#define MSS_INDEX (0 + 4) -#define MSS_IDXBUSY 0x80 /* readonly, set when busy */ -#define MSS_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 MSS_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 MSS_IDXMASK 0x1f /* mask for indirect address */ - -#define MSS_IDATA (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 MSS_STATUS (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. - */ -#if 0 -#define io_Polled_IO(d) ((d)->io_base+3+4) - /* - * this register is used in case of polled i/o - */ -#endif - -/* - * 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 -#define BD_F_MSS_OFFSET 0x0008 /* offset mss writes by -4 */ -#define BD_F_DUPLEX 0x0010 -#define BD_F_924PNP 0x0020 /* OPTi924 is in PNP mode */ - -/* - * 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 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, one for the OPTI931 and one for the - * OPTi930. 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 ) - -mixer_ent opti930_devices[32][2] = { -MIX_ENT(SOUND_MIXER_VOLUME, 22, 1, 0, 4, 23, 1, 0, 4), -MIX_NONE(SOUND_MIXER_BASS), -MIX_NONE(SOUND_MIXER_TREBLE), -MIX_ENT(SOUND_MIXER_SYNTH, 4, 1, 0, 4, 5, 1, 0, 4), -MIX_ENT(SOUND_MIXER_PCM, 6, 1, 1, 5, 7, 1, 1, 5), -MIX_ENT(SOUND_MIXER_LINE, 18, 1, 1, 4, 19, 1, 1, 4), -MIX_NONE(SOUND_MIXER_SPEAKER), -MIX_ENT(SOUND_MIXER_MIC, 21, 1, 0, 4, 22, 1, 0, 4), -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_NONE(SOUND_MIXER_IGAIN), -MIX_NONE(SOUND_MIXER_OGAIN), -MIX_NONE(SOUND_MIXER_LINE1), -MIX_NONE(SOUND_MIXER_LINE2), -MIX_NONE(SOUND_MIXER_LINE3), -}; - -#define OPTI930_MIXER_DEVICES \ - (SOUND_MASK_VOLUME | SOUND_MASK_SYNTH | SOUND_MASK_PCM | \ - SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD ) - -/* - * 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 ) - -/* - * Register definitions for the Yamaha OPL3-SA[23x]. - */ -#define OPL3SAx_POWER 0x01 /* Power Management (R/W) */ -#define OPL3SAx_POWER_PDX 0x01 /* Set to 1 to halt oscillator */ -#define OPL3SAx_POWER_PDN 0x02 /* Set to 1 to power down */ -#define OPL3SAx_POWER_PSV 0x04 /* Set to 1 to power save */ -#define OPL3SAx_POWER_ADOWN 0x20 /* Analog power (?) */ - -#define OPL3SAx_SYSTEM 0x02 /* System control (R/W) */ -#define OPL3SAx_SYSTEM_VZE 0x01 /* I2S audio routing */ -#define OPL3SAx_SYSTEM_IDSEL 0x03 /* SB compat version select */ -#define OPL3SAx_SYSTEM_SBHE 0x80 /* 0 for AT bus, 1 for XT bus */ - -#define OPL3SAx_IRQCONF 0x03 /* Interrupt configuration (R/W */ -#define OPL3SAx_IRQCONF_WSSA 0x01 /* WSS interrupts through IRQA */ -#define OPL3SAx_IRQCONF_SBA 0x02 /* WSS interrupts through IRQA */ -#define OPL3SAx_IRQCONF_MPUA 0x04 /* WSS interrupts through IRQA */ -#define OPL3SAx_IRQCONF_OPL3A 0x08 /* WSS interrupts through IRQA */ -#define OPL3SAx_IRQCONF_WSSB 0x10 /* WSS interrupts through IRQB */ -#define OPL3SAx_IRQCONF_SBB 0x20 /* WSS interrupts through IRQB */ -#define OPL3SAx_IRQCONF_MPUB 0x40 /* WSS interrupts through IRQB */ -#define OPL3SAx_IRQCONF_OPL3B 0x80 /* WSS interrupts through IRQB */ - -#define OPL3SAx_IRQSTATUSA 0x04 /* Interrupt (IRQ-A) Status (RO) */ -#define OPL3SAx_IRQSTATUSB 0x05 /* Interrupt (IRQ-B) Status (RO) */ -#define OPL3SAx_IRQSTATUS_PI 0x01 /* Playback Flag of CODEC */ -#define OPL3SAx_IRQSTATUS_CI 0x02 /* Recording Flag of CODEC */ -#define OPL3SAx_IRQSTATUS_TI 0x04 /* Timer Flag of CODEC */ -#define OPL3SAx_IRQSTATUS_SB 0x08 /* SB compat Playback Interrupt Flag */ -#define OPL3SAx_IRQSTATUS_MPU 0x10 /* MPU401 Interrupt Flag */ -#define OPL3SAx_IRQSTATUS_OPL3 0x20 /* Internal FM Timer Flag */ -#define OPL3SAx_IRQSTATUS_MV 0x40 /* HW Volume Interrupt Flag */ -#define OPL3SAx_IRQSTATUS_PI 0x01 /* Playback Flag of CODEC */ -#define OPL3SAx_IRQSTATUS_CI 0x02 /* Recording Flag of CODEC */ -#define OPL3SAx_IRQSTATUS_TI 0x04 /* Timer Flag of CODEC */ -#define OPL3SAx_IRQSTATUS_SB 0x08 /* SB compat Playback Interrupt Flag */ -#define OPL3SAx_IRQSTATUS_MPU 0x10 /* MPU401 Interrupt Flag */ -#define OPL3SAx_IRQSTATUS_OPL3 0x20 /* Internal FM Timer Flag */ -#define OPL3SAx_IRQSTATUS_MV 0x40 /* HW Volume Interrupt Flag */ - -#define OPL3SAx_DMACONF 0x06 /* DMA configuration (R/W) */ -#define OPL3SAx_DMACONF_WSSPA 0x01 /* WSS Playback on DMA-A */ -#define OPL3SAx_DMACONF_WSSRA 0x02 /* WSS Recording on DMA-A */ -#define OPL3SAx_DMACONF_SBA 0x02 /* SB Playback on DMA-A */ -#define OPL3SAx_DMACONF_WSSPB 0x10 /* WSS Playback on DMA-A */ -#define OPL3SAx_DMACONF_WSSRB 0x20 /* WSS Recording on DMA-A */ -#define OPL3SAx_DMACONF_SBB 0x20 /* SB Playback on DMA-A */ - -#define OPL3SAx_VOLUMEL 0x07 /* Master Volume Left (R/W) */ -#define OPL3SAx_VOLUMEL_MVL 0x0f /* Attenuation level */ -#define OPL3SAx_VOLUMEL_MVLM 0x80 /* Mute */ - -#define OPL3SAx_VOLUMER 0x08 /* Master Volume Right (R/W) */ -#define OPL3SAx_VOLUMER_MVR 0x0f /* Attenuation level */ -#define OPL3SAx_VOLUMER_MVRM 0x80 /* Mute */ - -#define OPL3SAx_MIC 0x09 /* MIC Volume (R/W) */ -#define OPL3SAx_VOLUMER_MCV 0x1f /* Attenuation level */ -#define OPL3SAx_VOLUMER_MICM 0x80 /* Mute */ - -#define OPL3SAx_MISC 0x0a /* Miscellaneous */ -#define OPL3SAx_MISC_VER 0x07 /* Version */ -#define OPL3SAx_MISC_MODE 0x08 /* SB or WSS mode */ -#define OPL3SAx_MISC_MCSW 0x10 /* */ -#define OPL3SAx_MISC_VEN 0x80 /* Enable hardware volume control */ - -#define OPL3SAx_WSSDMA 0x0b /* WSS DMA Counter (RW) (4 regs) */ - -#define OPL3SAx_WSSIRQSCAN 0x0f /* WSS Interrupt Scan out/in (R/W) */ -#define OPL3SAx_WSSIRQSCAN_SPI 0x01 -#define OPL3SAx_WSSIRQSCAN_SCI 0x02 -#define OPL3SAx_WSSIRQSCAN_STI 0x04 - -#define OPL3SAx_SBSTATE 0x10 /* SB compat Internal State (R/W) */ -#define OPL3SAx_SBSTATE_SBPDR 0x01 /* SB Power Down Request */ -#define OPL3SAx_SBSTATE_SE 0x02 /* Scan Enable */ -#define OPL3SAx_SBSTATE_SM 0x04 /* Scan Mode */ -#define OPL3SAx_SBSTATE_SS 0x08 /* Scan Select */ -#define OPL3SAx_SBSTATE_SBPDA 0x80 /* SB Power Down Acknowledge */ - -#define OPL3SAx_SBDATA 0x11 /* SB compat State Scan Data (R/W) */ - -#define OPL3SAx_DIGITALPOWER 0x12 /* Digital Partial Power Down (R/W) */ -#define OPL3SAx_DIGITALPOWER_PnP 0x01 -#define OPL3SAx_DIGITALPOWER_SB 0x02 -#define OPL3SAx_DIGITALPOWER_WSSP 0x04 -#define OPL3SAx_DIGITALPOWER_WSSR 0x08 -#define OPL3SAx_DIGITALPOWER_FM 0x10 -#define OPL3SAx_DIGITALPOWER_MCLK0 0x20 -#define OPL3SAx_DIGITALPOWER_MPU 0x40 -#define OPL3SAx_DIGITALPOWER_JOY 0x80 - -#define OPL3SAx_ANALOGPOWER 0x13 /* Analog Partial Power Down (R/W) */ -#define OPL3SAx_ANALOGPOWER_WIDE 0x01 -#define OPL3SAx_ANALOGPOWER_SBDAC 0x02 -#define OPL3SAx_ANALOGPOWER_DA 0x04 -#define OPL3SAx_ANALOGPOWER_AD 0x08 -#define OPL3SAx_ANALOGPOWER_FMDAC 0x10 - -#define OPL3SAx_WIDE 0x14 /* Enhanced control(WIDE) (R/W) */ -#define OPL3SAx_WIDE_WIDEL 0x07 /* Wide level on Left Channel */ -#define OPL3SAx_WIDE_WIDER 0x70 /* Wide level on Right Channel */ - -#define OPL3SAx_BASS 0x15 /* Enhanced control(BASS) (R/W) */ -#define OPL3SAx_BASS_BASSL 0x07 /* Bass level on Left Channel */ -#define OPL3SAx_BASS_BASSR 0x70 /* Bass level on Right Channel */ - -#define OPL3SAx_TREBLE 0x16 /* Enhanced control(TREBLE) (R/W) */ -#define OPL3SAx_TREBLE_TREBLEL 0x07 /* Treble level on Left Channel */ -#define OPL3SAx_TREBLE_TREBLER 0x70 /* Treble level on Right Channel */ - -#define OPL3SAx_HWVOL 0x17 /* HW Volume IRQ Configuration (R/W) */ -#define OPL3SAx_HWVOL_IRQA 0x10 /* HW Volume IRQ on IRQ-A */ -#define OPL3SAx_HWVOL_IRQB 0x20 /* HW Volume IRQ on IRQ-B */ Index: sys/dev/sound/isa/mss.c =================================================================== --- sys/dev/sound/isa/mss.c +++ /dev/null @@ -1,2290 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * Copyright (c) 2001 George Reid - * Copyright (c) 1999 Cameron Grant - * Copyright (c) 1997,1998 Luigi Rizzo - * Copyright (c) 1994,1995 Hannu Savolainen - * All rights reserved. - * - * 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 HAVE_KERNEL_OPTION_HEADERS -#include "opt_snd.h" -#endif - -#include - -SND_DECLARE_FILE("$FreeBSD$"); - -/* board-specific include files */ -#include -#include -#include - -#include - -#include "mixer_if.h" - -#define MSS_DEFAULT_BUFSZ (4096) -#define MSS_INDEXED_REGS 0x20 -#define OPL_INDEXED_REGS 0x19 - -struct mss_info; - -struct mss_chinfo { - struct mss_info *parent; - struct pcm_channel *channel; - struct snd_dbuf *buffer; - int dir; - u_int32_t fmt, blksz; -}; - -struct mss_info { - struct resource *io_base; /* primary I/O address for the board */ - int io_rid; - struct resource *conf_base; /* and the opti931 also has a config space */ - int conf_rid; - struct resource *irq; - int irq_rid; - struct resource *drq1; /* play */ - int drq1_rid; - struct resource *drq2; /* rec */ - int drq2_rid; - void *ih; - bus_dma_tag_t parent_dmat; - struct mtx *lock; - - char mss_indexed_regs[MSS_INDEXED_REGS]; - char opl_indexed_regs[OPL_INDEXED_REGS]; - int bd_id; /* used to hold board-id info, eg. sb version, - * mss codec type, etc. etc. - */ - int opti_offset; /* offset from config_base for opti931 */ - u_long bd_flags; /* board-specific flags */ - int optibase; /* base address for OPTi9xx config */ - struct resource *indir; /* Indirect register index address */ - int indir_rid; - int password; /* password for opti9xx cards */ - int passwdreg; /* password register */ - unsigned int bufsize; - struct mss_chinfo pch, rch; -}; - -static int mss_probe(device_t dev); -static int mss_attach(device_t dev); - -static driver_intr_t mss_intr; - -/* prototypes for local functions */ -static int mss_detect(device_t dev, struct mss_info *mss); -static int opti_detect(device_t dev, struct mss_info *mss); -static char *ymf_test(device_t dev, struct mss_info *mss); -static void ad_unmute(struct mss_info *mss); - -/* mixer set funcs */ -static int mss_mixer_set(struct mss_info *mss, int dev, int left, int right); -static int mss_set_recsrc(struct mss_info *mss, int mask); - -/* io funcs */ -static int ad_wait_init(struct mss_info *mss, int x); -static int ad_read(struct mss_info *mss, int reg); -static void ad_write(struct mss_info *mss, int reg, u_char data); -static void ad_write_cnt(struct mss_info *mss, int reg, u_short data); -static void ad_enter_MCE(struct mss_info *mss); -static void ad_leave_MCE(struct mss_info *mss); - -/* OPTi-specific functions */ -static void opti_write(struct mss_info *mss, u_char reg, - u_char data); -static u_char opti_read(struct mss_info *mss, u_char reg); -static int opti_init(device_t dev, struct mss_info *mss); - -/* io primitives */ -static void conf_wr(struct mss_info *mss, u_char reg, u_char data); -static u_char conf_rd(struct mss_info *mss, u_char reg); - -static int pnpmss_probe(device_t dev); -static int pnpmss_attach(device_t dev); - -static driver_intr_t opti931_intr; - -static u_int32_t mss_fmt[] = { - SND_FORMAT(AFMT_U8, 1, 0), - SND_FORMAT(AFMT_U8, 2, 0), - SND_FORMAT(AFMT_S16_LE, 1, 0), - SND_FORMAT(AFMT_S16_LE, 2, 0), - SND_FORMAT(AFMT_MU_LAW, 1, 0), - SND_FORMAT(AFMT_MU_LAW, 2, 0), - SND_FORMAT(AFMT_A_LAW, 1, 0), - SND_FORMAT(AFMT_A_LAW, 2, 0), - 0 -}; -static struct pcmchan_caps mss_caps = {4000, 48000, mss_fmt, 0}; - -static u_int32_t guspnp_fmt[] = { - SND_FORMAT(AFMT_U8, 1, 0), - SND_FORMAT(AFMT_U8, 2, 0), - SND_FORMAT(AFMT_S16_LE, 1, 0), - SND_FORMAT(AFMT_S16_LE, 2, 0), - SND_FORMAT(AFMT_A_LAW, 1, 0), - SND_FORMAT(AFMT_A_LAW, 2, 0), - 0 -}; -static struct pcmchan_caps guspnp_caps = {4000, 48000, guspnp_fmt, 0}; - -static u_int32_t opti931_fmt[] = { - SND_FORMAT(AFMT_U8, 1, 0), - SND_FORMAT(AFMT_U8, 2, 0), - SND_FORMAT(AFMT_S16_LE, 1, 0), - SND_FORMAT(AFMT_S16_LE, 2, 0), - 0 -}; -static struct pcmchan_caps opti931_caps = {4000, 48000, opti931_fmt, 0}; - -#define MD_AD1848 0x91 -#define MD_AD1845 0x92 -#define MD_CS42XX 0xA1 -#define MD_CS423X 0xA2 -#define MD_OPTI930 0xB0 -#define MD_OPTI931 0xB1 -#define MD_OPTI925 0xB2 -#define MD_OPTI924 0xB3 -#define MD_GUSPNP 0xB8 -#define MD_GUSMAX 0xB9 -#define MD_YM0020 0xC1 -#define MD_VIVO 0xD1 - -#define DV_F_TRUE_MSS 0x00010000 /* mss _with_ base regs */ - -#define FULL_DUPLEX(x) ((x)->bd_flags & BD_F_DUPLEX) - -static void -mss_lock(struct mss_info *mss) -{ - snd_mtxlock(mss->lock); -} - -static void -mss_unlock(struct mss_info *mss) -{ - snd_mtxunlock(mss->lock); -} - -static int -port_rd(struct resource *port, int off) -{ - if (port) - return bus_space_read_1(rman_get_bustag(port), - rman_get_bushandle(port), - off); - else - return -1; -} - -static void -port_wr(struct resource *port, int off, u_int8_t data) -{ - if (port) - bus_space_write_1(rman_get_bustag(port), - rman_get_bushandle(port), - off, data); -} - -static int -io_rd(struct mss_info *mss, int reg) -{ - if (mss->bd_flags & BD_F_MSS_OFFSET) reg -= 4; - return port_rd(mss->io_base, reg); -} - -static void -io_wr(struct mss_info *mss, int reg, u_int8_t data) -{ - if (mss->bd_flags & BD_F_MSS_OFFSET) reg -= 4; - port_wr(mss->io_base, reg, data); -} - -static void -conf_wr(struct mss_info *mss, u_char reg, u_char value) -{ - port_wr(mss->conf_base, 0, reg); - port_wr(mss->conf_base, 1, value); -} - -static u_char -conf_rd(struct mss_info *mss, u_char reg) -{ - port_wr(mss->conf_base, 0, reg); - return port_rd(mss->conf_base, 1); -} - -static void -opti_wr(struct mss_info *mss, u_char reg, u_char value) -{ - port_wr(mss->conf_base, mss->opti_offset + 0, reg); - port_wr(mss->conf_base, mss->opti_offset + 1, value); -} - -static u_char -opti_rd(struct mss_info *mss, u_char reg) -{ - port_wr(mss->conf_base, mss->opti_offset + 0, reg); - return port_rd(mss->conf_base, mss->opti_offset + 1); -} - -static void -gus_wr(struct mss_info *mss, u_char reg, u_char value) -{ - port_wr(mss->conf_base, 3, reg); - port_wr(mss->conf_base, 5, value); -} - -static u_char -gus_rd(struct mss_info *mss, u_char reg) -{ - port_wr(mss->conf_base, 3, reg); - return port_rd(mss->conf_base, 5); -} - -static void -mss_release_resources(struct mss_info *mss, device_t dev) -{ - if (mss->irq) { - if (mss->ih) - bus_teardown_intr(dev, mss->irq, mss->ih); - bus_release_resource(dev, SYS_RES_IRQ, mss->irq_rid, - mss->irq); - mss->irq = NULL; - } - if (mss->drq2) { - if (mss->drq2 != mss->drq1) { - isa_dma_release(rman_get_start(mss->drq2)); - bus_release_resource(dev, SYS_RES_DRQ, mss->drq2_rid, - mss->drq2); - } - mss->drq2 = NULL; - } - if (mss->drq1) { - isa_dma_release(rman_get_start(mss->drq1)); - bus_release_resource(dev, SYS_RES_DRQ, mss->drq1_rid, - mss->drq1); - mss->drq1 = NULL; - } - if (mss->io_base) { - bus_release_resource(dev, SYS_RES_IOPORT, mss->io_rid, - mss->io_base); - mss->io_base = NULL; - } - if (mss->conf_base) { - bus_release_resource(dev, SYS_RES_IOPORT, mss->conf_rid, - mss->conf_base); - mss->conf_base = NULL; - } - if (mss->indir) { - bus_release_resource(dev, SYS_RES_IOPORT, mss->indir_rid, - mss->indir); - mss->indir = NULL; - } - if (mss->parent_dmat) { - bus_dma_tag_destroy(mss->parent_dmat); - mss->parent_dmat = 0; - } - if (mss->lock) snd_mtxfree(mss->lock); - - free(mss, M_DEVBUF); -} - -static int -mss_alloc_resources(struct mss_info *mss, device_t dev) -{ - int pdma, rdma, ok = 1; - if (!mss->io_base) - mss->io_base = bus_alloc_resource_any(dev, SYS_RES_IOPORT, - &mss->io_rid, RF_ACTIVE); - if (!mss->irq) - mss->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, - &mss->irq_rid, RF_ACTIVE); - if (!mss->drq1) - mss->drq1 = bus_alloc_resource_any(dev, SYS_RES_DRQ, - &mss->drq1_rid, - RF_ACTIVE); - if (mss->conf_rid >= 0 && !mss->conf_base) - mss->conf_base = bus_alloc_resource_any(dev, SYS_RES_IOPORT, - &mss->conf_rid, - RF_ACTIVE); - if (mss->drq2_rid >= 0 && !mss->drq2) - mss->drq2 = bus_alloc_resource_any(dev, SYS_RES_DRQ, - &mss->drq2_rid, - RF_ACTIVE); - - if (!mss->io_base || !mss->drq1 || !mss->irq) ok = 0; - if (mss->conf_rid >= 0 && !mss->conf_base) ok = 0; - if (mss->drq2_rid >= 0 && !mss->drq2) ok = 0; - - if (ok) { - pdma = rman_get_start(mss->drq1); - isa_dma_acquire(pdma); - isa_dmainit(pdma, mss->bufsize); - mss->bd_flags &= ~BD_F_DUPLEX; - if (mss->drq2) { - rdma = rman_get_start(mss->drq2); - isa_dma_acquire(rdma); - isa_dmainit(rdma, mss->bufsize); - mss->bd_flags |= BD_F_DUPLEX; - } else mss->drq2 = mss->drq1; - } - return ok; -} - -/* - * 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. - */ - -static 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 */ -} - -/* -------------------------------------------------------------------- */ -/* only one source can be set... */ -static int -mss_set_recsrc(struct mss_info *mss, int mask) -{ - u_char recdev; - - 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(mss, 0, (ad_read(mss, 0) & 0x3f) | recdev); - ad_write(mss, 1, (ad_read(mss, 1) & 0x3f) | recdev); - return mask; -} - -/* there are differences in the mixer depending on the actual sound card. */ -static int -mss_mixer_set(struct mss_info *mss, int dev, int left, int right) -{ - int regoffs; - mixer_tab *mix_d; - u_char old, val; - - switch (mss->bd_id) { - case MD_OPTI931: - mix_d = &opti931_devices; - break; - case MD_OPTI930: - mix_d = &opti930_devices; - break; - default: - mix_d = &mix_devices; - } - - if ((*mix_d)[dev][LEFT_CHN].nbits == 0) { - DEB(printf("nbits = 0 for dev %d\n", dev)); - return -1; - } - - if ((*mix_d)[dev][RIGHT_CHN].nbits == 0) right = left; /* mono */ - - /* Set the left channel */ - - regoffs = (*mix_d)[dev][LEFT_CHN].regno; - old = val = ad_read(mss, regoffs); - /* if volume is 0, mute chan. Otherwise, unmute. */ - if (regoffs != 0) val = (left == 0)? old | 0x80 : old & 0x7f; - change_bits(mix_d, &val, dev, LEFT_CHN, left); - ad_write(mss, 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(mss, regoffs); - if (regoffs != 1) val = (right == 0)? old | 0x80 : old & 0x7f; - change_bits(mix_d, &val, dev, RIGHT_CHN, right); - ad_write(mss, regoffs, val); - - DEB(printf("RIGHT: dev %d reg %d old 0x%02x new 0x%02x\n", - dev, regoffs, old, val)); - } - return 0; /* success */ -} - -/* -------------------------------------------------------------------- */ - -static int -mssmix_init(struct snd_mixer *m) -{ - struct mss_info *mss = mix_getdevinfo(m); - - mix_setdevs(m, MODE2_MIXER_DEVICES); - mix_setrecdevs(m, MSS_REC_DEVICES); - switch(mss->bd_id) { - case MD_OPTI930: - mix_setdevs(m, OPTI930_MIXER_DEVICES); - break; - - case MD_OPTI931: - mix_setdevs(m, OPTI931_MIXER_DEVICES); - mss_lock(mss); - ad_write(mss, 20, 0x88); - ad_write(mss, 21, 0x88); - mss_unlock(mss); - break; - - case MD_AD1848: - mix_setdevs(m, MODE1_MIXER_DEVICES); - break; - - case MD_GUSPNP: - case MD_GUSMAX: - /* this is only necessary in mode 3 ... */ - mss_lock(mss); - ad_write(mss, 22, 0x88); - ad_write(mss, 23, 0x88); - mss_unlock(mss); - break; - } - return 0; -} - -static int -mssmix_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right) -{ - struct mss_info *mss = mix_getdevinfo(m); - - mss_lock(mss); - mss_mixer_set(mss, dev, left, right); - mss_unlock(mss); - - return left | (right << 8); -} - -static u_int32_t -mssmix_setrecsrc(struct snd_mixer *m, u_int32_t src) -{ - struct mss_info *mss = mix_getdevinfo(m); - - mss_lock(mss); - src = mss_set_recsrc(mss, src); - mss_unlock(mss); - return src; -} - -static kobj_method_t mssmix_mixer_methods[] = { - KOBJMETHOD(mixer_init, mssmix_init), - KOBJMETHOD(mixer_set, mssmix_set), - KOBJMETHOD(mixer_setrecsrc, mssmix_setrecsrc), - KOBJMETHOD_END -}; -MIXER_DECLARE(mssmix_mixer); - -/* -------------------------------------------------------------------- */ - -static int -ymmix_init(struct snd_mixer *m) -{ - struct mss_info *mss = mix_getdevinfo(m); - - mssmix_init(m); - mix_setdevs(m, mix_getdevs(m) | SOUND_MASK_VOLUME | SOUND_MASK_MIC - | SOUND_MASK_BASS | SOUND_MASK_TREBLE); - /* Set master volume */ - mss_lock(mss); - conf_wr(mss, OPL3SAx_VOLUMEL, 7); - conf_wr(mss, OPL3SAx_VOLUMER, 7); - mss_unlock(mss); - - return 0; -} - -static int -ymmix_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right) -{ - struct mss_info *mss = mix_getdevinfo(m); - int t, l, r; - - mss_lock(mss); - switch (dev) { - case SOUND_MIXER_VOLUME: - if (left) t = 15 - (left * 15) / 100; - else t = 0x80; /* mute */ - conf_wr(mss, OPL3SAx_VOLUMEL, t); - if (right) t = 15 - (right * 15) / 100; - else t = 0x80; /* mute */ - conf_wr(mss, OPL3SAx_VOLUMER, t); - break; - - case SOUND_MIXER_MIC: - t = left; - if (left) t = 31 - (left * 31) / 100; - else t = 0x80; /* mute */ - conf_wr(mss, OPL3SAx_MIC, t); - break; - - case SOUND_MIXER_BASS: - l = (left * 7) / 100; - r = (right * 7) / 100; - t = (r << 4) | l; - conf_wr(mss, OPL3SAx_BASS, t); - break; - - case SOUND_MIXER_TREBLE: - l = (left * 7) / 100; - r = (right * 7) / 100; - t = (r << 4) | l; - conf_wr(mss, OPL3SAx_TREBLE, t); - break; - - default: - mss_mixer_set(mss, dev, left, right); - } - mss_unlock(mss); - - return left | (right << 8); -} - -static u_int32_t -ymmix_setrecsrc(struct snd_mixer *m, u_int32_t src) -{ - struct mss_info *mss = mix_getdevinfo(m); - mss_lock(mss); - src = mss_set_recsrc(mss, src); - mss_unlock(mss); - return src; -} - -static kobj_method_t ymmix_mixer_methods[] = { - KOBJMETHOD(mixer_init, ymmix_init), - KOBJMETHOD(mixer_set, ymmix_set), - KOBJMETHOD(mixer_setrecsrc, ymmix_setrecsrc), - KOBJMETHOD_END -}; -MIXER_DECLARE(ymmix_mixer); - -/* -------------------------------------------------------------------- */ -/* - * XXX This might be better off in the gusc driver. - */ -static void -gusmax_setup(struct mss_info *mss, device_t dev, struct resource *alt) -{ - static const unsigned char irq_bits[16] = { - 0, 0, 0, 3, 0, 2, 0, 4, 0, 1, 0, 5, 6, 0, 0, 7 - }; - static const unsigned char dma_bits[8] = { - 0, 1, 0, 2, 0, 3, 4, 5 - }; - device_t parent = device_get_parent(dev); - unsigned char irqctl, dmactl; - int s; - - s = splhigh(); - - port_wr(alt, 0x0f, 0x05); - port_wr(alt, 0x00, 0x0c); - port_wr(alt, 0x0b, 0x00); - - port_wr(alt, 0x0f, 0x00); - - irqctl = irq_bits[isa_get_irq(parent)]; - /* Share the IRQ with the MIDI driver. */ - irqctl |= 0x40; - dmactl = dma_bits[isa_get_drq(parent)]; - if (device_get_flags(parent) & DV_F_DUAL_DMA) - dmactl |= dma_bits[device_get_flags(parent) & DV_F_DRQ_MASK] - << 3; - - /* - * Set the DMA and IRQ control latches. - */ - port_wr(alt, 0x00, 0x0c); - port_wr(alt, 0x0b, dmactl | 0x80); - port_wr(alt, 0x00, 0x4c); - port_wr(alt, 0x0b, irqctl); - - port_wr(alt, 0x00, 0x0c); - port_wr(alt, 0x0b, dmactl); - port_wr(alt, 0x00, 0x4c); - port_wr(alt, 0x0b, irqctl); - - port_wr(mss->conf_base, 2, 0); - port_wr(alt, 0x00, 0x0c); - port_wr(mss->conf_base, 2, 0); - - splx(s); -} - -static int -mss_init(struct mss_info *mss, device_t dev) -{ - u_char r6, r9; - struct resource *alt; - int rid, tmp; - - mss->bd_flags |= BD_F_MCE_BIT; - switch(mss->bd_id) { - case MD_OPTI931: - /* - * The 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. - */ - mss->opti_offset = - (rman_get_start(mss->conf_base) & ~3) + 2 - - rman_get_start(mss->conf_base); - BVDDB(printf("mss_init: opti_offset=%d\n", mss->opti_offset)); - opti_wr(mss, 4, 0xd6); /* fifo empty, OPL3, audio enable, SB3.2 */ - ad_write(mss, 10, 2); /* enable interrupts */ - opti_wr(mss, 6, 2); /* MCIR6: mss enable, sb disable */ - opti_wr(mss, 5, 0x28); /* MCIR5: codec in exp. mode,fifo */ - break; - - case MD_GUSPNP: - case MD_GUSMAX: - gus_wr(mss, 0x4c /* _URSTI */, 0);/* Pull reset */ - DELAY(1000 * 30); - /* release reset and enable DAC */ - gus_wr(mss, 0x4c /* _URSTI */, 3); - DELAY(1000 * 30); - /* end of reset */ - - rid = 0; - alt = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, - RF_ACTIVE); - if (alt == NULL) { - printf("XXX couldn't init GUS PnP/MAX\n"); - break; - } - port_wr(alt, 0, 0xC); /* enable int and dma */ - if (mss->bd_id == MD_GUSMAX) - gusmax_setup(mss, dev, alt); - bus_release_resource(dev, SYS_RES_IOPORT, rid, alt); - - /* - * unmute left & right line. Need to go in mode3, unmute, - * and back to mode 2 - */ - tmp = ad_read(mss, 0x0c); - ad_write(mss, 0x0c, 0x6c); /* special value to enter mode 3 */ - ad_write(mss, 0x19, 0); /* unmute left */ - ad_write(mss, 0x1b, 0); /* unmute right */ - ad_write(mss, 0x0c, tmp); /* restore old mode */ - - /* send codec interrupts on irq1 and only use that one */ - gus_wr(mss, 0x5a, 0x4f); - - /* enable access to hidden regs */ - tmp = gus_rd(mss, 0x5b /* IVERI */); - gus_wr(mss, 0x5b, tmp | 1); - BVDDB(printf("GUS: silicon rev %c\n", 'A' + ((tmp & 0xf) >> 4))); - break; - - case MD_YM0020: - conf_wr(mss, OPL3SAx_DMACONF, 0xa9); /* dma-b rec, dma-a play */ - r6 = conf_rd(mss, OPL3SAx_DMACONF); - r9 = conf_rd(mss, OPL3SAx_MISC); /* version */ - BVDDB(printf("Yamaha: ver 0x%x DMA config 0x%x\n", r6, r9);) - /* yamaha - set volume to max */ - conf_wr(mss, OPL3SAx_VOLUMEL, 0); - conf_wr(mss, OPL3SAx_VOLUMER, 0); - conf_wr(mss, OPL3SAx_DMACONF, FULL_DUPLEX(mss)? 0xa9 : 0x8b); - break; - } - if (FULL_DUPLEX(mss) && mss->bd_id != MD_OPTI931) - ad_write(mss, 12, ad_read(mss, 12) | 0x40); /* mode 2 */ - ad_enter_MCE(mss); - ad_write(mss, 9, FULL_DUPLEX(mss)? 0 : 4); - ad_leave_MCE(mss); - ad_write(mss, 10, 2); /* int enable */ - io_wr(mss, MSS_STATUS, 0); /* Clear interrupt status */ - /* the following seem required on the CS4232 */ - ad_unmute(mss); - 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(void *arg) -{ - struct mss_info *mss = arg; - u_char c = 0, served = 0; - int i; - - DEB(printf("mss_intr\n")); - mss_lock(mss); - ad_read(mss, 11); /* fake read of status bits */ - - /* loop until there are interrupts, but no more than 10 times. */ - for (i = 10; i > 0 && io_rd(mss, MSS_STATUS) & 1; i--) { - /* get exact reason for full-duplex boards */ - c = FULL_DUPLEX(mss)? ad_read(mss, 24) : 0x30; - c &= ~served; - if (sndbuf_runsz(mss->pch.buffer) && (c & 0x10)) { - served |= 0x10; - mss_unlock(mss); - chn_intr(mss->pch.channel); - mss_lock(mss); - } - if (sndbuf_runsz(mss->rch.buffer) && (c & 0x20)) { - served |= 0x20; - mss_unlock(mss); - chn_intr(mss->rch.channel); - mss_lock(mss); - } - /* now ack the interrupt */ - if (FULL_DUPLEX(mss)) ad_write(mss, 24, ~c); /* ack selectively */ - else io_wr(mss, MSS_STATUS, 0); /* Clear interrupt status */ - } - if (i == 10) { - BVDDB(printf("mss_intr: irq, but not from mss\n")); - } else if (served == 0) { - BVDDB(printf("mss_intr: unexpected irq with reason %x\n", c)); - /* - * this should not happen... I have no idea what to do now. - * maybe should do a sanity check and restart dmas ? - */ - io_wr(mss, MSS_STATUS, 0); /* Clear interrupt status */ - } - mss_unlock(mss); -} - -/* - * AD_WAIT_INIT waits if we are initializing the board and - * we cannot modify its settings - */ -static int -ad_wait_init(struct mss_info *mss, int x) -{ - int arg = x, n = 0; /* to shut up the compiler... */ - for (; x > 0; x--) - if ((n = io_rd(mss, MSS_INDEX)) & MSS_IDXBUSY) DELAY(10); - else return n; - printf("AD_WAIT_INIT FAILED %d 0x%02x\n", arg, n); - return n; -} - -static int -ad_read(struct mss_info *mss, int reg) -{ - int x; - - ad_wait_init(mss, 201000); - x = io_rd(mss, MSS_INDEX) & ~MSS_IDXMASK; - io_wr(mss, MSS_INDEX, (u_char)(reg & MSS_IDXMASK) | x); - x = io_rd(mss, MSS_IDATA); - /* printf("ad_read %d, %x\n", reg, x); */ - return x; -} - -static void -ad_write(struct mss_info *mss, int reg, u_char data) -{ - int x; - - /* printf("ad_write %d, %x\n", reg, data); */ - ad_wait_init(mss, 1002000); - x = io_rd(mss, MSS_INDEX) & ~MSS_IDXMASK; - io_wr(mss, MSS_INDEX, (u_char)(reg & MSS_IDXMASK) | x); - io_wr(mss, MSS_IDATA, data); -} - -static void -ad_write_cnt(struct mss_info *mss, int reg, u_short cnt) -{ - ad_write(mss, reg+1, cnt & 0xff); - ad_write(mss, reg, cnt >> 8); /* upper base must be last */ -} - -static void -wait_for_calibration(struct mss_info *mss) -{ - int 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 - */ - - t = ad_wait_init(mss, 1000000); - if (t & MSS_IDXBUSY) printf("mss: Auto calibration timed out(1).\n"); - - /* - * The calibration mode for chips that support it is set so that - * we never see ACI go on. - */ - if (mss->bd_id == MD_GUSMAX || mss->bd_id == MD_GUSPNP) { - for (t = 100; t > 0 && (ad_read(mss, 11) & 0x20) == 0; t--); - } else { - /* - * XXX This should only be enabled for cards that *really* - * need it. Are there any? - */ - for (t = 100; t > 0 && (ad_read(mss, 11) & 0x20) == 0; t--) DELAY(100); - } - for (t = 100; t > 0 && ad_read(mss, 11) & 0x20; t--) DELAY(100); -} - -static void -ad_unmute(struct mss_info *mss) -{ - ad_write(mss, 6, ad_read(mss, 6) & ~I6_MUTE); - ad_write(mss, 7, ad_read(mss, 7) & ~I6_MUTE); -} - -static void -ad_enter_MCE(struct mss_info *mss) -{ - int prev; - - mss->bd_flags |= BD_F_MCE_BIT; - ad_wait_init(mss, 203000); - prev = io_rd(mss, MSS_INDEX); - prev &= ~MSS_TRD; - io_wr(mss, MSS_INDEX, prev | MSS_MCE); -} - -static void -ad_leave_MCE(struct mss_info *mss) -{ - u_char prev; - - if ((mss->bd_flags & BD_F_MCE_BIT) == 0) { - DEB(printf("--- hey, leave_MCE: MCE bit was not set!\n")); - return; - } - - ad_wait_init(mss, 1000000); - - mss->bd_flags &= ~BD_F_MCE_BIT; - - prev = io_rd(mss, MSS_INDEX); - prev &= ~MSS_TRD; - io_wr(mss, MSS_INDEX, prev & ~MSS_MCE); /* Clear the MCE bit */ - wait_for_calibration(mss); -} - -static int -mss_speed(struct mss_chinfo *ch, int speed) -{ - struct mss_info *mss = ch->parent; - /* - * 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. - * - */ - ad_enter_MCE(mss); - if (mss->bd_id == MD_AD1845) { /* Use alternate speed select regs */ - ad_write(mss, 22, (speed >> 8) & 0xff); /* Speed MSB */ - ad_write(mss, 23, speed & 0xff); /* Speed LSB */ - /* XXX must also do something in I27 for the ad1845 */ - } else { - int i, sel = 0; /* assume entry 0 does not contain -1 */ - static int speeds[] = - {8000, 5512, 16000, 11025, 27429, 18900, 32000, 22050, - -1, 37800, -1, 44100, 48000, 33075, 9600, 6615}; - - for (i = 1; i < 16; i++) - if (speeds[i] > 0 && - abs(speed-speeds[i]) < abs(speed-speeds[sel])) sel = i; - speed = speeds[sel]; - ad_write(mss, 8, (ad_read(mss, 8) & 0xf0) | sel); - ad_wait_init(mss, 10000); - } - ad_leave_MCE(mss); - - return speed; -} - -/* - * 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(struct mss_chinfo *ch, u_int32_t format) -{ - struct mss_info *mss = ch->parent; - int i, arg = AFMT_ENCODING(format); - - /* - * 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}; - - ch->fmt = format; - for (i = 0; i < 8; i++) if (arg == fmts[i]) break; - arg = i << 1; - if (AFMT_CHANNEL(format) > 1) arg |= 1; - arg <<= 4; - ad_enter_MCE(mss); - ad_write(mss, 8, (ad_read(mss, 8) & 0x0f) | arg); - ad_wait_init(mss, 10000); - if (ad_read(mss, 12) & 0x40) { /* mode2? */ - ad_write(mss, 28, arg); /* capture mode */ - ad_wait_init(mss, 10000); - } - ad_leave_MCE(mss); - return format; -} - -static int -mss_trigger(struct mss_chinfo *ch, int go) -{ - struct mss_info *mss = ch->parent; - u_char m; - int retry, wr, cnt, ss; - - ss = 1; - ss <<= (AFMT_CHANNEL(ch->fmt) > 1)? 1 : 0; - ss <<= (ch->fmt & AFMT_16BIT)? 1 : 0; - - wr = (ch->dir == PCMDIR_PLAY)? 1 : 0; - m = ad_read(mss, 9); - switch (go) { - case PCMTRIG_START: - cnt = (ch->blksz / ss) - 1; - - DEB(if (m & 4) printf("OUCH! reg 9 0x%02x\n", m);); - m |= wr? I9_PEN : I9_CEN; /* enable DMA */ - ad_write_cnt(mss, (wr || !FULL_DUPLEX(mss))? 14 : 30, cnt); - break; - - case PCMTRIG_STOP: - case PCMTRIG_ABORT: /* XXX check this... */ - m &= ~(wr? I9_PEN : I9_CEN); /* Stop DMA */ -#if 0 - /* - * 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. - */ - ad_write_cnt(mss, (wr || !FULL_DUPLEX(mss))? 14 : 30, 0); -#endif - } - /* on the OPTi931 the enable bit seems hard to set... */ - for (retry = 10; retry > 0; retry--) { - ad_write(mss, 9, m); - if (ad_read(mss, 9) == m) break; - } - if (retry == 0) BVDDB(printf("stop dma, failed to set bit 0x%02x 0x%02x\n", \ - m, ad_read(mss, 9))); - return 0; -} - -/* - * the opti931 seems to miss interrupts when working in full - * duplex, so we try some heuristics to catch them. - */ -static void -opti931_intr(void *arg) -{ - struct mss_info *mss = (struct mss_info *)arg; - u_char masked = 0, i11, mc11, c = 0; - u_char reason; /* b0 = playback, b1 = capture, b2 = timer */ - int loops = 10; - -#if 0 - reason = io_rd(mss, MSS_STATUS); - if (!(reason & 1)) {/* no int, maybe a shared line ? */ - DEB(printf("intr: flag 0, mcir11 0x%02x\n", ad_read(mss, 11))); - return; - } -#endif - mss_lock(mss); - i11 = ad_read(mss, 11); /* XXX what's for ? */ - again: - - c = mc11 = FULL_DUPLEX(mss)? opti_rd(mss, 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) BVDDB(printf("irq reset failed, mc11 0x%02x, 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 = io_rd(mss, MSS_STATUS); - if (reason & 1) { - DEB(printf("one more try...\n");) - if (--loops) goto again; - else BVDDB(printf("intr, but mc11 not set\n");) - } - if (loops == 0) BVDDB(printf("intr, nothing in mcir11 0x%02x\n", mc11)); - mss_unlock(mss); - return; - } - - if (sndbuf_runsz(mss->rch.buffer) && (mc11 & 8)) { - mss_unlock(mss); - chn_intr(mss->rch.channel); - mss_lock(mss); - } - if (sndbuf_runsz(mss->pch.buffer) && (mc11 & 4)) { - mss_unlock(mss); - chn_intr(mss->pch.channel); - mss_lock(mss); - } - opti_wr(mss, 11, ~mc11); /* ack */ - if (--loops) goto again; - mss_unlock(mss); - DEB(printf("xxx too many loops\n");) -} - -/* -------------------------------------------------------------------- */ -/* channel interface */ -static void * -msschan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir) -{ - struct mss_info *mss = devinfo; - struct mss_chinfo *ch = (dir == PCMDIR_PLAY)? &mss->pch : &mss->rch; - - ch->parent = mss; - ch->channel = c; - ch->buffer = b; - ch->dir = dir; - if (sndbuf_alloc(ch->buffer, mss->parent_dmat, 0, mss->bufsize) != 0) - return NULL; - sndbuf_dmasetup(ch->buffer, (dir == PCMDIR_PLAY)? mss->drq1 : mss->drq2); - return ch; -} - -static int -msschan_setformat(kobj_t obj, void *data, u_int32_t format) -{ - struct mss_chinfo *ch = data; - struct mss_info *mss = ch->parent; - - mss_lock(mss); - mss_format(ch, format); - mss_unlock(mss); - return 0; -} - -static u_int32_t -msschan_setspeed(kobj_t obj, void *data, u_int32_t speed) -{ - struct mss_chinfo *ch = data; - struct mss_info *mss = ch->parent; - u_int32_t r; - - mss_lock(mss); - r = mss_speed(ch, speed); - mss_unlock(mss); - - return r; -} - -static u_int32_t -msschan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize) -{ - struct mss_chinfo *ch = data; - - ch->blksz = blocksize; - sndbuf_resize(ch->buffer, 2, ch->blksz); - - return ch->blksz; -} - -static int -msschan_trigger(kobj_t obj, void *data, int go) -{ - struct mss_chinfo *ch = data; - struct mss_info *mss = ch->parent; - - if (!PCMTRIG_COMMON(go)) - return 0; - - sndbuf_dma(ch->buffer, go); - mss_lock(mss); - mss_trigger(ch, go); - mss_unlock(mss); - return 0; -} - -static u_int32_t -msschan_getptr(kobj_t obj, void *data) -{ - struct mss_chinfo *ch = data; - return sndbuf_dmaptr(ch->buffer); -} - -static struct pcmchan_caps * -msschan_getcaps(kobj_t obj, void *data) -{ - struct mss_chinfo *ch = data; - - switch(ch->parent->bd_id) { - case MD_OPTI931: - return &opti931_caps; - break; - - case MD_GUSPNP: - case MD_GUSMAX: - return &guspnp_caps; - break; - - default: - return &mss_caps; - break; - } -} - -static kobj_method_t msschan_methods[] = { - KOBJMETHOD(channel_init, msschan_init), - KOBJMETHOD(channel_setformat, msschan_setformat), - KOBJMETHOD(channel_setspeed, msschan_setspeed), - KOBJMETHOD(channel_setblocksize, msschan_setblocksize), - KOBJMETHOD(channel_trigger, msschan_trigger), - KOBJMETHOD(channel_getptr, msschan_getptr), - KOBJMETHOD(channel_getcaps, msschan_getcaps), - KOBJMETHOD_END -}; -CHANNEL_DECLARE(msschan); - -/* -------------------------------------------------------------------- */ - -/* - * 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(device_t dev) -{ - u_char tmp, tmpx; - int flags, irq, drq, result = ENXIO, setres = 0; - struct mss_info *mss; - - if (isa_get_logicalid(dev)) return ENXIO; /* not yet */ - - mss = (struct mss_info *)malloc(sizeof *mss, M_DEVBUF, M_NOWAIT | M_ZERO); - if (!mss) return ENXIO; - - mss->io_rid = 0; - mss->conf_rid = -1; - mss->irq_rid = 0; - mss->drq1_rid = 0; - mss->drq2_rid = -1; - mss->io_base = bus_alloc_resource_anywhere(dev, SYS_RES_IOPORT, - &mss->io_rid, 8, RF_ACTIVE); - if (!mss->io_base) { - BVDDB(printf("mss_probe: no address given, try 0x%x\n", 0x530)); - mss->io_rid = 0; - /* XXX verify this */ - setres = 1; - bus_set_resource(dev, SYS_RES_IOPORT, mss->io_rid, - 0x530, 8); - mss->io_base = bus_alloc_resource_anywhere(dev, SYS_RES_IOPORT, - &mss->io_rid, - 8, RF_ACTIVE); - } - if (!mss->io_base) goto no; - - /* got irq/dma regs? */ - flags = device_get_flags(dev); - irq = isa_get_irq(dev); - drq = isa_get_drq(dev); - - if (!(device_get_flags(dev) & DV_F_TRUE_MSS)) 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. - */ - - device_set_desc(dev, "MSS"); - tmpx = tmp = io_rd(mss, 3); - if (tmp == 0xff) { /* Bus float */ - BVDDB(printf("I/O addr inactive (%x), try pseudo_mss\n", tmp)); - device_set_flags(dev, flags & ~DV_F_TRUE_MSS); - goto mss_probe_end; - } - tmp &= 0x3f; - if (!(tmp == 0x04 || tmp == 0x0f || tmp == 0x00 || tmp == 0x05)) { - BVDDB(printf("No MSS signature detected on port 0x%jx (0x%x)\n", - rman_get_start(mss->io_base), tmpx)); - goto no; - } - if (irq > 11) { - printf("MSS: Bad IRQ %d\n", irq); - goto no; - } - if (!(drq == 0 || drq == 1 || drq == 3)) { - printf("MSS: Bad DMA %d\n", drq); - goto no; - } - if (tmpx & 0x80) { - /* 8-bit board: only drq1/3 and irq7/9 */ - if (drq == 0) { - printf("MSS: Can't use DMA0 with a 8 bit card/slot\n"); - goto no; - } - if (!(irq == 7 || irq == 9)) { - printf("MSS: Can't use IRQ%d with a 8 bit card/slot\n", - irq); - goto no; - } - } - mss_probe_end: - result = mss_detect(dev, mss); - no: - mss_release_resources(mss, dev); -#if 0 - if (setres) ISA_DELETE_RESOURCE(device_get_parent(dev), dev, - SYS_RES_IOPORT, mss->io_rid); /* XXX ? */ -#endif - return result; -} - -static int -mss_detect(device_t dev, struct mss_info *mss) -{ - int i; - u_char tmp = 0, tmp1, tmp2; - char *name, *yamaha; - - if (mss->bd_id != 0) { - device_printf(dev, "presel bd_id 0x%04x -- %s\n", mss->bd_id, - device_get_desc(dev)); - return 0; - } - - name = "AD1848"; - mss->bd_id = MD_AD1848; /* AD1848 or CS4248 */ - - if (opti_detect(dev, mss)) { - switch (mss->bd_id) { - case MD_OPTI924: - name = "OPTi924"; - break; - case MD_OPTI930: - name = "OPTi930"; - break; - } - printf("Found OPTi device %s\n", name); - if (opti_init(dev, mss) == 0) goto gotit; - } - - /* - * 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 ((tmp = io_rd(mss, MSS_INDEX)) & MSS_IDXBUSY) DELAY(10000); - else break; - - if (i >= 10) { /* Not an AD1848 */ - BVDDB(printf("mss_detect, busy still set (0x%02x)\n", tmp)); - goto no; - } - /* - * 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(mss, 0, 0xaa); - ad_write(mss, 1, 0x45);/* 0x55 with bit 0x10 clear */ - tmp1 = ad_read(mss, 0); - tmp2 = ad_read(mss, 1); - if (tmp1 != 0xaa || tmp2 != 0x45) { - BVDDB(printf("mss_detect error - IREG (%x/%x)\n", tmp1, tmp2)); - goto no; - } - - ad_write(mss, 0, 0x45); - ad_write(mss, 1, 0xaa); - tmp1 = ad_read(mss, 0); - tmp2 = ad_read(mss, 1); - if (tmp1 != 0x45 || tmp2 != 0xaa) { - BVDDB(printf("mss_detect error - IREG2 (%x/%x)\n", tmp1, tmp2)); - goto no; - } - - /* - * The indirect register I12 has some read only bits. Lets try to - * change them. - */ - - tmp = ad_read(mss, 12); - ad_write(mss, 12, (~tmp) & 0x0f); - tmp1 = ad_read(mss, 12); - - if ((tmp & 0x0f) != (tmp1 & 0x0f)) { - BVDDB(printf("mss_detect - I12 (0x%02x was 0x%02x)\n", tmp1, tmp)); - goto no; - } - - /* - * 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(mss, 12, 0); /* Mode2=disabled */ -#if 0 - for (i = 0; i < 16; i++) { - if ((tmp1 = ad_read(mss, i)) != (tmp2 = ad_read(mss, 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. (which makes this test pointless - cg) - */ - break; /* return 0; */ - } - } -#endif - /* - * 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(mss, 12, 0x40); /* Set mode2, clear 0x80 */ - - tmp1 = ad_read(mss, 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) goto gotit; - /* - * 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(mss, 16, 0); /* Set I16 to known value */ - ad_write(mss, 0, 0x45); - if ((tmp1 = ad_read(mss, 16)) == 0x45) goto gotit; - - ad_write(mss, 0, 0xaa); - if ((tmp1 = ad_read(mss, 16)) == 0xaa) { /* Rotten bits? */ - BVDDB(printf("mss_detect error - step H(%x)\n", tmp1)); - goto no; - } - /* Verify that some bits of I25 are read only. */ - tmp1 = ad_read(mss, 25); /* Original bits */ - ad_write(mss, 25, ~tmp1); /* Invert all bits */ - if ((ad_read(mss, 25) & 0xe7) == (tmp1 & 0xe7)) { - int id; - - /* It's at least CS4231 */ - name = "CS4231"; - mss->bd_id = MD_CS42XX; - - /* - * 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(mss, 25) & 0xe7; - /* - * b7-b5 = version number; - * 100 : all CS4231 - * 101 : CS4231A - * - * b2-b0 = chip id; - */ - switch (id) { - case 0xa0: - name = "CS4231A"; - mss->bd_id = MD_CS42XX; - break; - - case 0xa2: - name = "CS4232"; - mss->bd_id = MD_CS42XX; - break; - - case 0xb2: - /* strange: the 4231 data sheet says b4-b3 are XX - * so this should be the same as 0xa2 - */ - name = "CS4232A"; - mss->bd_id = MD_CS42XX; - 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(mss, 23); - - ad_write(mss, 23, ~tmp); - if (ad_read(mss, 23) != tmp) { /* AD1845 ? */ - name = "AD1845"; - mss->bd_id = MD_AD1845; - } - ad_write(mss, 23, tmp); /* Restore */ - - yamaha = ymf_test(dev, mss); - if (yamaha) { - mss->bd_id = MD_YM0020; - name = yamaha; - } - break; - - case 0x83: /* CS4236 */ - case 0x03: /* CS4236 on Intel PR440FX motherboard XXX */ - name = "CS4236"; - mss->bd_id = MD_CS42XX; - break; - - default: /* Assume CS4231 */ - BVDDB(printf("unknown id 0x%02x, assuming CS4231\n", id);) - mss->bd_id = MD_CS42XX; - } - } - ad_write(mss, 25, tmp1); /* Restore bits */ -gotit: - BVDDB(printf("mss_detect() - Detected %s\n", name)); - device_set_desc(dev, name); - device_set_flags(dev, - ((device_get_flags(dev) & ~DV_F_DEV_MASK) | - ((mss->bd_id << DV_F_DEV_SHIFT) & DV_F_DEV_MASK))); - return 0; -no: - return ENXIO; -} - -static int -opti_detect(device_t dev, struct mss_info *mss) -{ - int c; - static const struct opticard { - int boardid; - int passwdreg; - int password; - int base; - int indir_reg; - } cards[] = { - { MD_OPTI930, 0, 0xe4, 0xf8f, 0xe0e }, /* 930 */ - { MD_OPTI924, 3, 0xe5, 0xf8c, 0, }, /* 924 */ - { 0 }, - }; - mss->conf_rid = 3; - mss->indir_rid = 4; - for (c = 0; cards[c].base; c++) { - mss->optibase = cards[c].base; - mss->password = cards[c].password; - mss->passwdreg = cards[c].passwdreg; - mss->bd_id = cards[c].boardid; - - if (cards[c].indir_reg) - mss->indir = bus_alloc_resource(dev, SYS_RES_IOPORT, - &mss->indir_rid, cards[c].indir_reg, - cards[c].indir_reg+1, 1, RF_ACTIVE); - - mss->conf_base = bus_alloc_resource(dev, SYS_RES_IOPORT, - &mss->conf_rid, mss->optibase, mss->optibase+9, - 9, RF_ACTIVE); - - if (opti_read(mss, 1) != 0xff) { - return 1; - } else { - if (mss->indir) - bus_release_resource(dev, SYS_RES_IOPORT, mss->indir_rid, mss->indir); - mss->indir = NULL; - if (mss->conf_base) - bus_release_resource(dev, SYS_RES_IOPORT, mss->conf_rid, mss->conf_base); - mss->conf_base = NULL; - } - } - return 0; -} - -static char * -ymf_test(device_t dev, struct mss_info *mss) -{ - static int ports[] = {0x370, 0x310, 0x538}; - int p, i, j, version; - static char *chipset[] = { - NULL, /* 0 */ - "OPL3-SA2 (YMF711)", /* 1 */ - "OPL3-SA3 (YMF715)", /* 2 */ - "OPL3-SA3 (YMF715)", /* 3 */ - "OPL3-SAx (YMF719)", /* 4 */ - "OPL3-SAx (YMF719)", /* 5 */ - "OPL3-SAx (YMF719)", /* 6 */ - "OPL3-SAx (YMF719)", /* 7 */ - }; - - for (p = 0; p < 3; p++) { - mss->conf_rid = 1; - mss->conf_base = bus_alloc_resource(dev, - SYS_RES_IOPORT, - &mss->conf_rid, - ports[p], ports[p] + 1, 2, - RF_ACTIVE); - if (!mss->conf_base) return 0; - - /* Test the index port of the config registers */ - i = port_rd(mss->conf_base, 0); - port_wr(mss->conf_base, 0, OPL3SAx_DMACONF); - j = (port_rd(mss->conf_base, 0) == OPL3SAx_DMACONF)? 1 : 0; - port_wr(mss->conf_base, 0, i); - if (!j) { - bus_release_resource(dev, SYS_RES_IOPORT, - mss->conf_rid, mss->conf_base); - mss->conf_base = NULL; - continue; - } - version = conf_rd(mss, OPL3SAx_MISC) & 0x07; - return chipset[version]; - } - return NULL; -} - -static int -mss_doattach(device_t dev, struct mss_info *mss) -{ - int pdma, rdma, flags = device_get_flags(dev); - char status[SND_STATUSLEN], status2[SND_STATUSLEN]; - - mss->lock = snd_mtxcreate(device_get_nameunit(dev), "snd_mss softc"); - mss->bufsize = pcm_getbuffersize(dev, 4096, MSS_DEFAULT_BUFSZ, 65536); - if (!mss_alloc_resources(mss, dev)) goto no; - mss_init(mss, dev); - pdma = rman_get_start(mss->drq1); - rdma = rman_get_start(mss->drq2); - if (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 pdma_bits[4] = {1, 2, -1, 3}; - static char valid_rdma[4] = {1, 0, -1, 0}; - char bits; - - if (!mss->irq || (bits = interrupt_bits[rman_get_start(mss->irq)]) == -1) - goto no; - io_wr(mss, 0, bits | 0x40); /* config port */ - if ((io_rd(mss, 3) & 0x40) == 0) device_printf(dev, "IRQ Conflict?\n"); - /* Write IRQ+DMA setup */ - if (pdma_bits[pdma] == -1) goto no; - bits |= pdma_bits[pdma]; - if (pdma != rdma) { - if (rdma == valid_rdma[pdma]) bits |= 4; - else { - printf("invalid dual dma config %d:%d\n", pdma, rdma); - goto no; - } - } - io_wr(mss, 0, bits); - printf("drq/irq conf %x\n", io_rd(mss, 0)); - } - mixer_init(dev, (mss->bd_id == MD_YM0020)? &ymmix_mixer_class : &mssmix_mixer_class, mss); - switch (mss->bd_id) { - case MD_OPTI931: - snd_setup_intr(dev, mss->irq, 0, opti931_intr, mss, &mss->ih); - break; - default: - snd_setup_intr(dev, mss->irq, 0, mss_intr, mss, &mss->ih); - } - if (pdma == rdma) - pcm_setflags(dev, pcm_getflags(dev) | SD_F_SIMPLEX); - if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(dev), /*alignment*/2, - /*boundary*/0, - /*lowaddr*/BUS_SPACE_MAXADDR_24BIT, - /*highaddr*/BUS_SPACE_MAXADDR, - /*filter*/NULL, /*filterarg*/NULL, - /*maxsize*/mss->bufsize, /*nsegments*/1, - /*maxsegz*/0x3ffff, /*flags*/0, - /*lockfunc*/NULL, /*lockarg*/NULL, - &mss->parent_dmat) != 0) { - device_printf(dev, "unable to create dma tag\n"); - goto no; - } - - if (pdma != rdma) - snprintf(status2, SND_STATUSLEN, ":%d", rdma); - else - status2[0] = '\0'; - - snprintf(status, SND_STATUSLEN, "at io 0x%jx irq %jd drq %d%s bufsz %u", - rman_get_start(mss->io_base), rman_get_start(mss->irq), pdma, status2, mss->bufsize); - - if (pcm_register(dev, mss, 1, 1)) goto no; - pcm_addchan(dev, PCMDIR_REC, &msschan_class, mss); - pcm_addchan(dev, PCMDIR_PLAY, &msschan_class, mss); - pcm_setstatus(dev, status); - - return 0; -no: - mss_release_resources(mss, dev); - return ENXIO; -} - -static int -mss_detach(device_t dev) -{ - int r; - struct mss_info *mss; - - r = pcm_unregister(dev); - if (r) - return r; - - mss = pcm_getdevinfo(dev); - mss_release_resources(mss, dev); - - return 0; -} - -static int -mss_attach(device_t dev) -{ - struct mss_info *mss; - int flags = device_get_flags(dev); - - gone_in_dev(dev, 14, "ISA sound driver"); - mss = (struct mss_info *)malloc(sizeof *mss, M_DEVBUF, M_NOWAIT | M_ZERO); - if (!mss) return ENXIO; - - mss->io_rid = 0; - mss->conf_rid = -1; - mss->irq_rid = 0; - mss->drq1_rid = 0; - mss->drq2_rid = -1; - if (flags & DV_F_DUAL_DMA) { - bus_set_resource(dev, SYS_RES_DRQ, 1, - flags & DV_F_DRQ_MASK, 1); - mss->drq2_rid = 1; - } - mss->bd_id = (device_get_flags(dev) & DV_F_DEV_MASK) >> DV_F_DEV_SHIFT; - if (mss->bd_id == MD_YM0020) ymf_test(dev, mss); - return mss_doattach(dev, mss); -} - -/* - * mss_resume() is the code to allow a laptop to resume using the sound - * card. - * - * This routine re-sets the state of the board to the state before going - * to sleep. According to the yamaha docs this is the right thing to do, - * but getting DMA restarted appears to be a bit of a trick, so the device - * has to be closed and re-opened to be re-used, but there is no skipping - * problem, and volume, bass/treble and most other things are restored - * properly. - * - */ - -static int -mss_resume(device_t dev) -{ - /* - * Restore the state taken below. - */ - struct mss_info *mss; - int i; - - mss = pcm_getdevinfo(dev); - - if(mss->bd_id == MD_YM0020 || mss->bd_id == MD_CS423X) { - /* This works on a Toshiba Libretto 100CT. */ - for (i = 0; i < MSS_INDEXED_REGS; i++) - ad_write(mss, i, mss->mss_indexed_regs[i]); - for (i = 0; i < OPL_INDEXED_REGS; i++) - conf_wr(mss, i, mss->opl_indexed_regs[i]); - mss_intr(mss); - } - - if (mss->bd_id == MD_CS423X) { - /* Needed on IBM Thinkpad 600E */ - mss_lock(mss); - mss_format(&mss->pch, mss->pch.channel->format); - mss_speed(&mss->pch, mss->pch.channel->speed); - mss_unlock(mss); - } - - return 0; - -} - -/* - * mss_suspend() is the code that gets called right before a laptop - * suspends. - * - * This code saves the state of the sound card right before shutdown - * so it can be restored above. - * - */ - -static int -mss_suspend(device_t dev) -{ - int i; - struct mss_info *mss; - - mss = pcm_getdevinfo(dev); - - if(mss->bd_id == MD_YM0020 || mss->bd_id == MD_CS423X) - { - /* this stops playback. */ - conf_wr(mss, 0x12, 0x0c); - for(i = 0; i < MSS_INDEXED_REGS; i++) - mss->mss_indexed_regs[i] = ad_read(mss, i); - for(i = 0; i < OPL_INDEXED_REGS; i++) - mss->opl_indexed_regs[i] = conf_rd(mss, i); - mss->opl_indexed_regs[0x12] = 0x0; - } - return 0; -} - -static device_method_t mss_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, mss_probe), - DEVMETHOD(device_attach, mss_attach), - DEVMETHOD(device_detach, mss_detach), - DEVMETHOD(device_suspend, mss_suspend), - DEVMETHOD(device_resume, mss_resume), - { 0, 0 } -}; - -static driver_t mss_driver = { - "pcm", - mss_methods, - PCM_SOFTC_SIZE, -}; - -DRIVER_MODULE(snd_mss, isa, mss_driver, pcm_devclass, 0, 0); -MODULE_DEPEND(snd_mss, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER); -MODULE_VERSION(snd_mss, 1); - -static int -azt2320_mss_mode(struct mss_info *mss, device_t dev) -{ - struct resource *sbport; - int i, ret, rid; - - rid = 0; - ret = -1; - sbport = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE); - if (sbport) { - for (i = 0; i < 1000; i++) { - if ((port_rd(sbport, SBDSP_STATUS) & 0x80)) - DELAY((i > 100) ? 1000 : 10); - else { - port_wr(sbport, SBDSP_CMD, 0x09); - break; - } - } - for (i = 0; i < 1000; i++) { - if ((port_rd(sbport, SBDSP_STATUS) & 0x80)) - DELAY((i > 100) ? 1000 : 10); - else { - port_wr(sbport, SBDSP_CMD, 0x00); - ret = 0; - break; - } - } - DELAY(1000); - bus_release_resource(dev, SYS_RES_IOPORT, rid, sbport); - } - return ret; -} - -static struct isa_pnp_id pnpmss_ids[] = { - {0x0000630e, "CS423x"}, /* CSC0000 */ - {0x0001630e, "CS423x-PCI"}, /* CSC0100 */ - {0x01000000, "CMI8330"}, /* @@@0001 */ - {0x2100a865, "Yamaha OPL-SAx"}, /* YMH0021 */ - {0x1110d315, "ENSONIQ SoundscapeVIVO"}, /* ENS1011 */ - {0x1093143e, "OPTi931"}, /* OPT9310 */ - {0x5092143e, "OPTi925"}, /* OPT9250 XXX guess */ - {0x0000143e, "OPTi924"}, /* OPT0924 */ - {0x1022b839, "Neomagic 256AV (non-ac97)"}, /* NMX2210 */ - {0x01005407, "Aztech 2320"}, /* AZT0001 */ -#if 0 - {0x0000561e, "GusPnP"}, /* GRV0000 */ -#endif - {0}, -}; - -static int -pnpmss_probe(device_t dev) -{ - u_int32_t lid, vid; - - lid = isa_get_logicalid(dev); - vid = isa_get_vendorid(dev); - if (lid == 0x01000000 && vid != 0x0100a90d) /* CMI0001 */ - return ENXIO; - return ISA_PNP_PROBE(device_get_parent(dev), dev, pnpmss_ids); -} - -static int -pnpmss_attach(device_t dev) -{ - struct mss_info *mss; - - mss = malloc(sizeof(*mss), M_DEVBUF, M_WAITOK | M_ZERO); - mss->io_rid = 0; - mss->conf_rid = -1; - mss->irq_rid = 0; - mss->drq1_rid = 0; - mss->drq2_rid = 1; - mss->bd_id = MD_CS42XX; - - switch (isa_get_logicalid(dev)) { - case 0x0000630e: /* CSC0000 */ - case 0x0001630e: /* CSC0100 */ - mss->bd_flags |= BD_F_MSS_OFFSET; - mss->bd_id = MD_CS423X; - break; - - case 0x2100a865: /* YHM0021 */ - mss->io_rid = 1; - mss->conf_rid = 4; - mss->bd_id = MD_YM0020; - break; - - case 0x1110d315: /* ENS1011 */ - mss->io_rid = 1; - mss->bd_id = MD_VIVO; - break; - - case 0x1093143e: /* OPT9310 */ - mss->bd_flags |= BD_F_MSS_OFFSET; - mss->conf_rid = 3; - mss->bd_id = MD_OPTI931; - break; - - case 0x5092143e: /* OPT9250 XXX guess */ - mss->io_rid = 1; - mss->conf_rid = 3; - mss->bd_id = MD_OPTI925; - break; - - case 0x0000143e: /* OPT0924 */ - mss->password = 0xe5; - mss->passwdreg = 3; - mss->optibase = 0xf0c; - mss->io_rid = 2; - mss->conf_rid = 3; - mss->bd_id = MD_OPTI924; - mss->bd_flags |= BD_F_924PNP; - if(opti_init(dev, mss) != 0) { - free(mss, M_DEVBUF); - return ENXIO; - } - break; - - case 0x1022b839: /* NMX2210 */ - mss->io_rid = 1; - break; - - case 0x01005407: /* AZT0001 */ - /* put into MSS mode first (snatched from NetBSD) */ - if (azt2320_mss_mode(mss, dev) == -1) { - free(mss, M_DEVBUF); - return ENXIO; - } - - mss->bd_flags |= BD_F_MSS_OFFSET; - mss->io_rid = 2; - break; - -#if 0 - case 0x0000561e: /* GRV0000 */ - mss->bd_flags |= BD_F_MSS_OFFSET; - mss->io_rid = 2; - mss->conf_rid = 1; - mss->drq1_rid = 1; - mss->drq2_rid = 0; - mss->bd_id = MD_GUSPNP; - break; -#endif - case 0x01000000: /* @@@0001 */ - mss->drq2_rid = -1; - break; - - /* Unknown MSS default. We could let the CSC0000 stuff match too */ - default: - mss->bd_flags |= BD_F_MSS_OFFSET; - break; - } - return mss_doattach(dev, mss); -} - -static int -opti_init(device_t dev, struct mss_info *mss) -{ - int flags = device_get_flags(dev); - int basebits = 0; - - if (!mss->conf_base) { - bus_set_resource(dev, SYS_RES_IOPORT, mss->conf_rid, - mss->optibase, 0x9); - - mss->conf_base = bus_alloc_resource(dev, SYS_RES_IOPORT, - &mss->conf_rid, mss->optibase, mss->optibase+0x9, - 0x9, RF_ACTIVE); - } - - if (!mss->conf_base) - return ENXIO; - - if (!mss->io_base) - mss->io_base = bus_alloc_resource_anywhere(dev, SYS_RES_IOPORT, - &mss->io_rid, 8, RF_ACTIVE); - - if (!mss->io_base) /* No hint specified, use 0x530 */ - mss->io_base = bus_alloc_resource(dev, SYS_RES_IOPORT, - &mss->io_rid, 0x530, 0x537, 8, RF_ACTIVE); - - if (!mss->io_base) - return ENXIO; - - switch (rman_get_start(mss->io_base)) { - case 0x530: - basebits = 0x0; - break; - case 0xe80: - basebits = 0x10; - break; - case 0xf40: - basebits = 0x20; - break; - case 0x604: - basebits = 0x30; - break; - default: - printf("opti_init: invalid MSS base address!\n"); - return ENXIO; - } - - switch (mss->bd_id) { - case MD_OPTI924: - opti_write(mss, 1, 0x80 | basebits); /* MSS mode */ - opti_write(mss, 2, 0x00); /* Disable CD */ - opti_write(mss, 3, 0xf0); /* Disable SB IRQ */ - opti_write(mss, 4, 0xf0); - opti_write(mss, 5, 0x00); - opti_write(mss, 6, 0x02); /* MPU stuff */ - break; - - case MD_OPTI930: - opti_write(mss, 1, 0x00 | basebits); - opti_write(mss, 3, 0x00); /* Disable SB IRQ/DMA */ - opti_write(mss, 4, 0x52); /* Empty FIFO */ - opti_write(mss, 5, 0x3c); /* Mode 2 */ - opti_write(mss, 6, 0x02); /* Enable MSS */ - break; - } - - if (mss->bd_flags & BD_F_924PNP) { - u_int32_t irq = isa_get_irq(dev); - u_int32_t drq = isa_get_drq(dev); - bus_set_resource(dev, SYS_RES_IRQ, 0, irq, 1); - bus_set_resource(dev, SYS_RES_DRQ, mss->drq1_rid, drq, 1); - if (flags & DV_F_DUAL_DMA) { - bus_set_resource(dev, SYS_RES_DRQ, 1, - flags & DV_F_DRQ_MASK, 1); - mss->drq2_rid = 1; - } - } - - /* OPTixxx has I/DRQ registers */ - - device_set_flags(dev, device_get_flags(dev) | DV_F_TRUE_MSS); - - return 0; -} - -static void -opti_write(struct mss_info *mss, u_char reg, u_char val) -{ - port_wr(mss->conf_base, mss->passwdreg, mss->password); - - switch(mss->bd_id) { - case MD_OPTI924: - if (reg > 7) { /* Indirect register */ - port_wr(mss->conf_base, mss->passwdreg, reg); - port_wr(mss->conf_base, mss->passwdreg, - mss->password); - port_wr(mss->conf_base, 9, val); - return; - } - port_wr(mss->conf_base, reg, val); - break; - - case MD_OPTI930: - port_wr(mss->indir, 0, reg); - port_wr(mss->conf_base, mss->passwdreg, mss->password); - port_wr(mss->indir, 1, val); - break; - } -} - -u_char -opti_read(struct mss_info *mss, u_char reg) -{ - port_wr(mss->conf_base, mss->passwdreg, mss->password); - - switch(mss->bd_id) { - case MD_OPTI924: - if (reg > 7) { /* Indirect register */ - port_wr(mss->conf_base, mss->passwdreg, reg); - port_wr(mss->conf_base, mss->passwdreg, mss->password); - return(port_rd(mss->conf_base, 9)); - } - return(port_rd(mss->conf_base, reg)); - break; - - case MD_OPTI930: - port_wr(mss->indir, 0, reg); - port_wr(mss->conf_base, mss->passwdreg, mss->password); - return port_rd(mss->indir, 1); - break; - } - return -1; -} - -static device_method_t pnpmss_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, pnpmss_probe), - DEVMETHOD(device_attach, pnpmss_attach), - DEVMETHOD(device_detach, mss_detach), - DEVMETHOD(device_suspend, mss_suspend), - DEVMETHOD(device_resume, mss_resume), - { 0, 0 } -}; - -static driver_t pnpmss_driver = { - "pcm", - pnpmss_methods, - PCM_SOFTC_SIZE, -}; - -DRIVER_MODULE(snd_pnpmss, isa, pnpmss_driver, pcm_devclass, 0, 0); -DRIVER_MODULE(snd_pnpmss, acpi, pnpmss_driver, pcm_devclass, 0, 0); -MODULE_DEPEND(snd_pnpmss, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER); -MODULE_VERSION(snd_pnpmss, 1); - -static int -guspcm_probe(device_t dev) -{ - struct sndcard_func *func; - - func = device_get_ivars(dev); - if (func == NULL || func->func != SCF_PCM) - return ENXIO; - - device_set_desc(dev, "GUS CS4231"); - return 0; -} - -static int -guspcm_attach(device_t dev) -{ - device_t parent = device_get_parent(dev); - struct mss_info *mss; - int base, flags; - unsigned char ctl; - - mss = (struct mss_info *)malloc(sizeof *mss, M_DEVBUF, M_NOWAIT | M_ZERO); - if (mss == NULL) - return ENOMEM; - - mss->bd_flags = BD_F_MSS_OFFSET; - mss->io_rid = 2; - mss->conf_rid = 1; - mss->irq_rid = 0; - mss->drq1_rid = 1; - mss->drq2_rid = -1; - - if (isa_get_logicalid(parent) == 0) - mss->bd_id = MD_GUSMAX; - else { - mss->bd_id = MD_GUSPNP; - mss->drq2_rid = 0; - goto skip_setup; - } - - flags = device_get_flags(parent); - if (flags & DV_F_DUAL_DMA) - mss->drq2_rid = 0; - - mss->conf_base = bus_alloc_resource_anywhere(dev, SYS_RES_IOPORT, - &mss->conf_rid, - 8, RF_ACTIVE); - - if (mss->conf_base == NULL) { - mss_release_resources(mss, dev); - return ENXIO; - } - - base = isa_get_port(parent); - - ctl = 0x40; /* CS4231 enable */ - if (isa_get_drq(dev) > 3) - ctl |= 0x10; /* 16-bit dma channel 1 */ - if ((flags & DV_F_DUAL_DMA) != 0 && (flags & DV_F_DRQ_MASK) > 3) - ctl |= 0x20; /* 16-bit dma channel 2 */ - ctl |= (base >> 4) & 0x0f; /* 2X0 -> 3XC */ - port_wr(mss->conf_base, 6, ctl); - -skip_setup: - return mss_doattach(dev, mss); -} - -static device_method_t guspcm_methods[] = { - DEVMETHOD(device_probe, guspcm_probe), - DEVMETHOD(device_attach, guspcm_attach), - DEVMETHOD(device_detach, mss_detach), - { 0, 0 } -}; - -static driver_t guspcm_driver = { - "pcm", - guspcm_methods, - PCM_SOFTC_SIZE, -}; - -DRIVER_MODULE(snd_guspcm, gusc, guspcm_driver, pcm_devclass, 0, 0); -MODULE_DEPEND(snd_guspcm, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER); -MODULE_VERSION(snd_guspcm, 1); -ISA_PNP_INFO(pnpmss_ids); Index: sys/dev/sound/isa/sb16.c =================================================================== --- sys/dev/sound/isa/sb16.c +++ /dev/null @@ -1,912 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * Copyright (c) 1999 Cameron Grant - * Copyright (c) 1997,1998 Luigi Rizzo - * - * Derived from files in the Voxware 3.5 distribution, - * Copyright by Hannu Savolainen 1994, under the same copyright - * conditions. - * All rights reserved. - * - * 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 HAVE_KERNEL_OPTION_HEADERS -#include "opt_snd.h" -#endif - -#include - -#include -#include - -#include - -#include "mixer_if.h" - -SND_DECLARE_FILE("$FreeBSD$"); - -#define SB16_BUFFSIZE 4096 -#define PLAIN_SB16(x) ((((x)->bd_flags) & (BD_F_SB16|BD_F_SB16X)) == BD_F_SB16) - -static u_int32_t sb16_fmt8[] = { - SND_FORMAT(AFMT_U8, 1, 0), - SND_FORMAT(AFMT_U8, 2, 0), - 0 -}; -static struct pcmchan_caps sb16_caps8 = {5000, 45000, sb16_fmt8, 0}; - -static u_int32_t sb16_fmt16[] = { - SND_FORMAT(AFMT_S16_LE, 1, 0), - SND_FORMAT(AFMT_S16_LE, 2, 0), - 0 -}; -static struct pcmchan_caps sb16_caps16 = {5000, 45000, sb16_fmt16, 0}; - -static u_int32_t sb16x_fmt[] = { - SND_FORMAT(AFMT_U8, 1, 0), - SND_FORMAT(AFMT_U8, 2, 0), - SND_FORMAT(AFMT_S16_LE, 1, 0), - SND_FORMAT(AFMT_S16_LE, 2, 0), - 0 -}; -static struct pcmchan_caps sb16x_caps = {5000, 49000, sb16x_fmt, 0}; - -struct sb_info; - -struct sb_chinfo { - struct sb_info *parent; - struct pcm_channel *channel; - struct snd_dbuf *buffer; - int dir, run, dch; - u_int32_t fmt, spd, blksz; -}; - -struct sb_info { - struct resource *io_base; /* I/O address for the board */ - struct resource *irq; - struct resource *drq1; - struct resource *drq2; - void *ih; - bus_dma_tag_t parent_dmat; - - unsigned int bufsize; - int bd_id; - u_long bd_flags; /* board-specific flags */ - int prio, prio16; - struct sb_chinfo pch, rch; - device_t parent_dev; -}; - -#if 0 -static void sb_lock(struct sb_info *sb); -static void sb_unlock(struct sb_info *sb); -static int sb_rd(struct sb_info *sb, int reg); -static void sb_wr(struct sb_info *sb, int reg, u_int8_t val); -static int sb_cmd(struct sb_info *sb, u_char val); -/* static int sb_cmd1(struct sb_info *sb, u_char cmd, int val); */ -static int sb_cmd2(struct sb_info *sb, u_char cmd, int val); -static u_int sb_get_byte(struct sb_info *sb); -static void sb_setmixer(struct sb_info *sb, u_int port, u_int value); -static int sb_getmixer(struct sb_info *sb, u_int port); -static int sb_reset_dsp(struct sb_info *sb); - -static void sb_intr(void *arg); -#endif - -/* - * Common code for the midi and pcm functions - * - * sb_cmd write a single byte to the CMD port. - * sb_cmd1 write a CMD + 1 byte arg - * sb_cmd2 write a CMD + 2 byte arg - * sb_get_byte returns a single byte from the DSP data port - */ - -static void -sb_lock(struct sb_info *sb) { - sbc_lock(device_get_softc(sb->parent_dev)); -} - -static void -sb_lockassert(struct sb_info *sb) { - sbc_lockassert(device_get_softc(sb->parent_dev)); -} - -static void -sb_unlock(struct sb_info *sb) { - sbc_unlock(device_get_softc(sb->parent_dev)); -} - -static int -port_rd(struct resource *port, int off) -{ - return bus_space_read_1(rman_get_bustag(port), rman_get_bushandle(port), off); -} - -static void -port_wr(struct resource *port, int off, u_int8_t data) -{ - bus_space_write_1(rman_get_bustag(port), rman_get_bushandle(port), off, data); -} - -static int -sb_rd(struct sb_info *sb, int reg) -{ - return port_rd(sb->io_base, reg); -} - -static void -sb_wr(struct sb_info *sb, int reg, u_int8_t val) -{ - port_wr(sb->io_base, reg, val); -} - -static int -sb_dspwr(struct sb_info *sb, u_char val) -{ - int i; - - for (i = 0; i < 1000; i++) { - if ((sb_rd(sb, SBDSP_STATUS) & 0x80)) - DELAY((i > 100)? 1000 : 10); - else { - sb_wr(sb, SBDSP_CMD, val); - return 1; - } - } - if (curthread->td_intr_nesting_level == 0) - printf("sb_dspwr(0x%02x) timed out.\n", val); - return 0; -} - -static int -sb_cmd(struct sb_info *sb, u_char val) -{ -#if 0 - printf("sb_cmd: %x\n", val); -#endif - return sb_dspwr(sb, val); -} - -/* -static int -sb_cmd1(struct sb_info *sb, u_char cmd, int val) -{ -#if 0 - printf("sb_cmd1: %x, %x\n", cmd, val); -#endif - if (sb_dspwr(sb, cmd)) { - return sb_dspwr(sb, val & 0xff); - } else return 0; -} -*/ - -static int -sb_cmd2(struct sb_info *sb, u_char cmd, int val) -{ - int r; - -#if 0 - printf("sb_cmd2: %x, %x\n", cmd, val); -#endif - sb_lockassert(sb); - r = 0; - if (sb_dspwr(sb, cmd)) { - if (sb_dspwr(sb, val & 0xff)) { - if (sb_dspwr(sb, (val >> 8) & 0xff)) { - r = 1; - } - } - } - - return r; -} - -/* - * in the SB, there is a set of indirect "mixer" registers with - * address at offset 4, data at offset 5 - */ -static void -sb_setmixer(struct sb_info *sb, u_int port, u_int value) -{ - sb_lock(sb); - sb_wr(sb, SB_MIX_ADDR, (u_char) (port & 0xff)); /* Select register */ - DELAY(10); - sb_wr(sb, SB_MIX_DATA, (u_char) (value & 0xff)); - DELAY(10); - sb_unlock(sb); -} - -static int -sb_getmixer(struct sb_info *sb, u_int port) -{ - int val; - - sb_lockassert(sb); - sb_wr(sb, SB_MIX_ADDR, (u_char) (port & 0xff)); /* Select register */ - DELAY(10); - val = sb_rd(sb, SB_MIX_DATA); - DELAY(10); - - return val; -} - -static u_int -sb_get_byte(struct sb_info *sb) -{ - int i; - - for (i = 1000; i > 0; i--) { - if (sb_rd(sb, DSP_DATA_AVAIL) & 0x80) - return sb_rd(sb, DSP_READ); - else - DELAY(20); - } - return 0xffff; -} - -static int -sb_reset_dsp(struct sb_info *sb) -{ - u_char b; - - sb_lockassert(sb); - sb_wr(sb, SBDSP_RST, 3); - DELAY(100); - sb_wr(sb, SBDSP_RST, 0); - b = sb_get_byte(sb); - if (b != 0xAA) { - DEB(printf("sb_reset_dsp 0x%lx failed\n", - rman_get_start(sb->io_base))); - return ENXIO; /* Sorry */ - } - return 0; -} - -/************************************************************/ - -struct sb16_mixent { - int reg; - int bits; - int ofs; - int stereo; -}; - -static const struct sb16_mixent sb16_mixtab[32] = { - [SOUND_MIXER_VOLUME] = { 0x30, 5, 3, 1 }, - [SOUND_MIXER_PCM] = { 0x32, 5, 3, 1 }, - [SOUND_MIXER_SYNTH] = { 0x34, 5, 3, 1 }, - [SOUND_MIXER_CD] = { 0x36, 5, 3, 1 }, - [SOUND_MIXER_LINE] = { 0x38, 5, 3, 1 }, - [SOUND_MIXER_MIC] = { 0x3a, 5, 3, 0 }, - [SOUND_MIXER_SPEAKER] = { 0x3b, 5, 3, 0 }, - [SOUND_MIXER_IGAIN] = { 0x3f, 2, 6, 1 }, - [SOUND_MIXER_OGAIN] = { 0x41, 2, 6, 1 }, - [SOUND_MIXER_TREBLE] = { 0x44, 4, 4, 1 }, - [SOUND_MIXER_BASS] = { 0x46, 4, 4, 1 }, - [SOUND_MIXER_LINE1] = { 0x52, 5, 3, 1 } -}; - -static int -sb16mix_init(struct snd_mixer *m) -{ - struct sb_info *sb = mix_getdevinfo(m); - - mix_setdevs(m, 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_LINE1 | - SOUND_MASK_VOLUME | SOUND_MASK_BASS | SOUND_MASK_TREBLE); - - mix_setrecdevs(m, SOUND_MASK_SYNTH | SOUND_MASK_LINE | - SOUND_MASK_LINE1 | SOUND_MASK_MIC | SOUND_MASK_CD); - - sb_setmixer(sb, 0x3c, 0x1f); /* make all output active */ - - sb_setmixer(sb, 0x3d, 0); /* make all inputs-l off */ - sb_setmixer(sb, 0x3e, 0); /* make all inputs-r off */ - - return 0; -} - -static int -rel2abs_volume(int x, int max) -{ - int temp; - - temp = ((x * max) + 50) / 100; - if (temp > max) - temp = max; - else if (temp < 0) - temp = 0; - return (temp); -} - -static int -sb16mix_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right) -{ - struct sb_info *sb = mix_getdevinfo(m); - const struct sb16_mixent *e; - int max; - - e = &sb16_mixtab[dev]; - max = (1 << e->bits) - 1; - - left = rel2abs_volume(left, max); - right = rel2abs_volume(right, max); - - sb_setmixer(sb, e->reg, left << e->ofs); - if (e->stereo) - sb_setmixer(sb, e->reg + 1, right << e->ofs); - else - right = left; - - left = (left * 100) / max; - right = (right * 100) / max; - - return left | (right << 8); -} - -static u_int32_t -sb16mix_setrecsrc(struct snd_mixer *m, u_int32_t src) -{ - struct sb_info *sb = mix_getdevinfo(m); - u_char recdev_l, recdev_r; - - recdev_l = 0; - recdev_r = 0; - if (src & SOUND_MASK_MIC) { - recdev_l |= 0x01; /* mono mic */ - recdev_r |= 0x01; - } - - if (src & SOUND_MASK_CD) { - recdev_l |= 0x04; /* l cd */ - recdev_r |= 0x02; /* r cd */ - } - - if (src & SOUND_MASK_LINE) { - recdev_l |= 0x10; /* l line */ - recdev_r |= 0x08; /* r line */ - } - - if (src & SOUND_MASK_SYNTH) { - recdev_l |= 0x40; /* l midi */ - recdev_r |= 0x20; /* r midi */ - } - - sb_setmixer(sb, SB16_IMASK_L, recdev_l); - sb_setmixer(sb, SB16_IMASK_R, recdev_r); - - /* Switch on/off FM tuner source */ - if (src & SOUND_MASK_LINE1) - sb_setmixer(sb, 0x4a, 0x0c); - else - sb_setmixer(sb, 0x4a, 0x00); - - /* - * 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 mic -- permanently. - */ - sb_setmixer(sb, SB16_OMASK, 0x1f & ~1); - - return src; -} - -static kobj_method_t sb16mix_mixer_methods[] = { - KOBJMETHOD(mixer_init, sb16mix_init), - KOBJMETHOD(mixer_set, sb16mix_set), - KOBJMETHOD(mixer_setrecsrc, sb16mix_setrecsrc), - KOBJMETHOD_END -}; -MIXER_DECLARE(sb16mix_mixer); - -/************************************************************/ - -static void -sb16_release_resources(struct sb_info *sb, device_t dev) -{ - if (sb->irq) { - if (sb->ih) - bus_teardown_intr(dev, sb->irq, sb->ih); - bus_release_resource(dev, SYS_RES_IRQ, 0, sb->irq); - sb->irq = NULL; - } - if (sb->drq2) { - if (sb->drq2 != sb->drq1) { - isa_dma_release(rman_get_start(sb->drq2)); - bus_release_resource(dev, SYS_RES_DRQ, 1, sb->drq2); - } - sb->drq2 = NULL; - } - if (sb->drq1) { - isa_dma_release(rman_get_start(sb->drq1)); - bus_release_resource(dev, SYS_RES_DRQ, 0, sb->drq1); - sb->drq1 = NULL; - } - if (sb->io_base) { - bus_release_resource(dev, SYS_RES_IOPORT, 0, sb->io_base); - sb->io_base = NULL; - } - if (sb->parent_dmat) { - bus_dma_tag_destroy(sb->parent_dmat); - sb->parent_dmat = 0; - } - free(sb, M_DEVBUF); -} - -static int -sb16_alloc_resources(struct sb_info *sb, device_t dev) -{ - int rid; - - rid = 0; - if (!sb->io_base) - sb->io_base = bus_alloc_resource_any(dev, SYS_RES_IOPORT, - &rid, RF_ACTIVE); - - rid = 0; - if (!sb->irq) - sb->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, - RF_ACTIVE); - - rid = 0; - if (!sb->drq1) - sb->drq1 = bus_alloc_resource_any(dev, SYS_RES_DRQ, &rid, - RF_ACTIVE); - - rid = 1; - if (!sb->drq2) - sb->drq2 = bus_alloc_resource_any(dev, SYS_RES_DRQ, &rid, - RF_ACTIVE); - - if (sb->io_base && sb->drq1 && sb->irq) { - isa_dma_acquire(rman_get_start(sb->drq1)); - isa_dmainit(rman_get_start(sb->drq1), sb->bufsize); - - if (sb->drq2) { - isa_dma_acquire(rman_get_start(sb->drq2)); - isa_dmainit(rman_get_start(sb->drq2), sb->bufsize); - } else { - sb->drq2 = sb->drq1; - pcm_setflags(dev, pcm_getflags(dev) | SD_F_SIMPLEX); - } - return 0; - } else return ENXIO; -} - -/* sbc does locking for us */ -static void -sb_intr(void *arg) -{ - struct sb_info *sb = (struct sb_info *)arg; - int reason, c; - - /* - * The Vibra16X has separate flags for 8 and 16 bit transfers, but - * I have no idea how to tell capture from playback interrupts... - */ - - reason = 0; - sb_lock(sb); - c = sb_getmixer(sb, IRQ_STAT); - if (c & 1) - sb_rd(sb, DSP_DATA_AVAIL); /* 8-bit int ack */ - - if (c & 2) - sb_rd(sb, DSP_DATA_AVL16); /* 16-bit int ack */ - sb_unlock(sb); - - /* - * 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... - */ - - if (sb->bd_flags & BD_F_SB16X) { - if (c & 1) { /* 8-bit format */ - if (sb->pch.fmt & AFMT_8BIT) - reason |= 1; - if (sb->rch.fmt & AFMT_8BIT) - reason |= 2; - } - if (c & 2) { /* 16-bit format */ - if (sb->pch.fmt & AFMT_16BIT) - reason |= 1; - if (sb->rch.fmt & AFMT_16BIT) - reason |= 2; - } - } else { - if (c & 1) { /* 8-bit dma */ - if (sb->pch.dch == 1) - reason |= 1; - if (sb->rch.dch == 1) - reason |= 2; - } - if (c & 2) { /* 16-bit dma */ - if (sb->pch.dch == 2) - reason |= 1; - if (sb->rch.dch == 2) - reason |= 2; - } - } -#if 0 - printf("sb_intr: reason=%d c=0x%x\n", reason, c); -#endif - if ((reason & 1) && (sb->pch.run)) - chn_intr(sb->pch.channel); - - if ((reason & 2) && (sb->rch.run)) - chn_intr(sb->rch.channel); -} - -static int -sb_setup(struct sb_info *sb) -{ - struct sb_chinfo *ch; - u_int8_t v; - int l, pprio; - - sb_lock(sb); - if (sb->bd_flags & BD_F_DMARUN) - sndbuf_dma(sb->pch.buffer, PCMTRIG_STOP); - if (sb->bd_flags & BD_F_DMARUN2) - sndbuf_dma(sb->rch.buffer, PCMTRIG_STOP); - sb->bd_flags &= ~(BD_F_DMARUN | BD_F_DMARUN2); - - sb_reset_dsp(sb); - - if (sb->bd_flags & BD_F_SB16X) { - /* full-duplex doesn't work! */ - pprio = sb->pch.run? 1 : 0; - sndbuf_dmasetup(sb->pch.buffer, pprio? sb->drq1 : sb->drq2); - sb->pch.dch = pprio? 1 : 0; - sndbuf_dmasetup(sb->rch.buffer, pprio? sb->drq2 : sb->drq1); - sb->rch.dch = pprio? 2 : 1; - } else { - if (sb->pch.run && sb->rch.run) { - pprio = (sb->rch.fmt & AFMT_16BIT)? 0 : 1; - sndbuf_dmasetup(sb->pch.buffer, pprio? sb->drq2 : sb->drq1); - sb->pch.dch = pprio? 2 : 1; - sndbuf_dmasetup(sb->rch.buffer, pprio? sb->drq1 : sb->drq2); - sb->rch.dch = pprio? 1 : 2; - } else { - if (sb->pch.run) { - sndbuf_dmasetup(sb->pch.buffer, (sb->pch.fmt & AFMT_16BIT)? sb->drq2 : sb->drq1); - sb->pch.dch = (sb->pch.fmt & AFMT_16BIT)? 2 : 1; - sndbuf_dmasetup(sb->rch.buffer, (sb->pch.fmt & AFMT_16BIT)? sb->drq1 : sb->drq2); - sb->rch.dch = (sb->pch.fmt & AFMT_16BIT)? 1 : 2; - } else if (sb->rch.run) { - sndbuf_dmasetup(sb->pch.buffer, (sb->rch.fmt & AFMT_16BIT)? sb->drq1 : sb->drq2); - sb->pch.dch = (sb->rch.fmt & AFMT_16BIT)? 1 : 2; - sndbuf_dmasetup(sb->rch.buffer, (sb->rch.fmt & AFMT_16BIT)? sb->drq2 : sb->drq1); - sb->rch.dch = (sb->rch.fmt & AFMT_16BIT)? 2 : 1; - } - } - } - - sndbuf_dmasetdir(sb->pch.buffer, PCMDIR_PLAY); - sndbuf_dmasetdir(sb->rch.buffer, PCMDIR_REC); - - /* - printf("setup: [pch = %d, pfmt = %d, pgo = %d] [rch = %d, rfmt = %d, rgo = %d]\n", - sb->pch.dch, sb->pch.fmt, sb->pch.run, sb->rch.dch, sb->rch.fmt, sb->rch.run); - */ - - ch = &sb->pch; - if (ch->run) { - l = ch->blksz; - if (ch->fmt & AFMT_16BIT) - l >>= 1; - l--; - - /* play speed */ - RANGE(ch->spd, 5000, 45000); - sb_cmd(sb, DSP_CMD_OUT16); - sb_cmd(sb, ch->spd >> 8); - sb_cmd(sb, ch->spd & 0xff); - - /* play format, length */ - v = DSP_F16_AUTO | DSP_F16_FIFO_ON | DSP_F16_DAC; - v |= (ch->fmt & AFMT_16BIT)? DSP_DMA16 : DSP_DMA8; - sb_cmd(sb, v); - - v = (AFMT_CHANNEL(ch->fmt) > 1)? DSP_F16_STEREO : 0; - v |= (ch->fmt & AFMT_SIGNED)? DSP_F16_SIGNED : 0; - sb_cmd2(sb, v, l); - sndbuf_dma(ch->buffer, PCMTRIG_START); - sb->bd_flags |= BD_F_DMARUN; - } - - ch = &sb->rch; - if (ch->run) { - l = ch->blksz; - if (ch->fmt & AFMT_16BIT) - l >>= 1; - l--; - - /* record speed */ - RANGE(ch->spd, 5000, 45000); - sb_cmd(sb, DSP_CMD_IN16); - sb_cmd(sb, ch->spd >> 8); - sb_cmd(sb, ch->spd & 0xff); - - /* record format, length */ - v = DSP_F16_AUTO | DSP_F16_FIFO_ON | DSP_F16_ADC; - v |= (ch->fmt & AFMT_16BIT)? DSP_DMA16 : DSP_DMA8; - sb_cmd(sb, v); - - v = (AFMT_CHANNEL(ch->fmt) > 1)? DSP_F16_STEREO : 0; - v |= (ch->fmt & AFMT_SIGNED)? DSP_F16_SIGNED : 0; - sb_cmd2(sb, v, l); - sndbuf_dma(ch->buffer, PCMTRIG_START); - sb->bd_flags |= BD_F_DMARUN2; - } - sb_unlock(sb); - - return 0; -} - -/* channel interface */ -static void * -sb16chan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir) -{ - struct sb_info *sb = devinfo; - struct sb_chinfo *ch = (dir == PCMDIR_PLAY)? &sb->pch : &sb->rch; - - ch->parent = sb; - ch->channel = c; - ch->buffer = b; - ch->dir = dir; - - if (sndbuf_alloc(ch->buffer, sb->parent_dmat, 0, sb->bufsize) != 0) - return NULL; - - return ch; -} - -static int -sb16chan_setformat(kobj_t obj, void *data, u_int32_t format) -{ - struct sb_chinfo *ch = data; - struct sb_info *sb = ch->parent; - - ch->fmt = format; - sb->prio = ch->dir; - sb->prio16 = (ch->fmt & AFMT_16BIT)? 1 : 0; - - return 0; -} - -static u_int32_t -sb16chan_setspeed(kobj_t obj, void *data, u_int32_t speed) -{ - struct sb_chinfo *ch = data; - - ch->spd = speed; - return speed; -} - -static u_int32_t -sb16chan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize) -{ - struct sb_chinfo *ch = data; - - ch->blksz = blocksize; - return ch->blksz; -} - -static int -sb16chan_trigger(kobj_t obj, void *data, int go) -{ - struct sb_chinfo *ch = data; - struct sb_info *sb = ch->parent; - - if (!PCMTRIG_COMMON(go)) - return 0; - - if (go == PCMTRIG_START) - ch->run = 1; - else - ch->run = 0; - - sb_setup(sb); - - return 0; -} - -static u_int32_t -sb16chan_getptr(kobj_t obj, void *data) -{ - struct sb_chinfo *ch = data; - - return sndbuf_dmaptr(ch->buffer); -} - -static struct pcmchan_caps * -sb16chan_getcaps(kobj_t obj, void *data) -{ - struct sb_chinfo *ch = data; - struct sb_info *sb = ch->parent; - - if ((sb->prio == 0) || (sb->prio == ch->dir)) - return &sb16x_caps; - else - return sb->prio16? &sb16_caps8 : &sb16_caps16; -} - -static int -sb16chan_resetdone(kobj_t obj, void *data) -{ - struct sb_chinfo *ch = data; - struct sb_info *sb = ch->parent; - - sb->prio = 0; - - return 0; -} - -static kobj_method_t sb16chan_methods[] = { - KOBJMETHOD(channel_init, sb16chan_init), - KOBJMETHOD(channel_resetdone, sb16chan_resetdone), - KOBJMETHOD(channel_setformat, sb16chan_setformat), - KOBJMETHOD(channel_setspeed, sb16chan_setspeed), - KOBJMETHOD(channel_setblocksize, sb16chan_setblocksize), - KOBJMETHOD(channel_trigger, sb16chan_trigger), - KOBJMETHOD(channel_getptr, sb16chan_getptr), - KOBJMETHOD(channel_getcaps, sb16chan_getcaps), - KOBJMETHOD_END -}; -CHANNEL_DECLARE(sb16chan); - -/************************************************************/ - -static int -sb16_probe(device_t dev) -{ - char buf[64]; - uintptr_t func, ver, r, f; - - /* The parent device has already been probed. */ - r = BUS_READ_IVAR(device_get_parent(dev), dev, 0, &func); - if (func != SCF_PCM) - return (ENXIO); - - r = BUS_READ_IVAR(device_get_parent(dev), dev, 1, &ver); - f = (ver & 0xffff0000) >> 16; - ver &= 0x0000ffff; - if (f & BD_F_SB16) { - snprintf(buf, sizeof buf, "SB16 DSP %d.%02d%s", (int) ver >> 8, (int) ver & 0xff, - (f & BD_F_SB16X)? " (ViBRA16X)" : ""); - device_set_desc_copy(dev, buf); - return 0; - } else - return (ENXIO); -} - -static int -sb16_attach(device_t dev) -{ - struct sb_info *sb; - uintptr_t ver; - char status[SND_STATUSLEN], status2[SND_STATUSLEN]; - - gone_in_dev(dev, 14, "ISA sound driver"); - sb = malloc(sizeof(*sb), M_DEVBUF, M_WAITOK | M_ZERO); - sb->parent_dev = device_get_parent(dev); - BUS_READ_IVAR(sb->parent_dev, dev, 1, &ver); - sb->bd_id = ver & 0x0000ffff; - sb->bd_flags = (ver & 0xffff0000) >> 16; - sb->bufsize = pcm_getbuffersize(dev, 4096, SB16_BUFFSIZE, 65536); - - if (sb16_alloc_resources(sb, dev)) - goto no; - sb_lock(sb); - if (sb_reset_dsp(sb)) { - sb_unlock(sb); - goto no; - } - sb_unlock(sb); - if (mixer_init(dev, &sb16mix_mixer_class, sb)) - goto no; - if (snd_setup_intr(dev, sb->irq, 0, sb_intr, sb, &sb->ih)) - goto no; - - if (sb->bd_flags & BD_F_SB16X) - pcm_setflags(dev, pcm_getflags(dev) | SD_F_SIMPLEX); - - sb->prio = 0; - - if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(dev), /*alignment*/2, - /*boundary*/0, - /*lowaddr*/BUS_SPACE_MAXADDR_24BIT, - /*highaddr*/BUS_SPACE_MAXADDR, - /*filter*/NULL, /*filterarg*/NULL, - /*maxsize*/sb->bufsize, /*nsegments*/1, - /*maxsegz*/0x3ffff, /*flags*/0, - /*lockfunc*/NULL, /*lockarg*/NULL, - &sb->parent_dmat) != 0) { - device_printf(dev, "unable to create dma tag\n"); - goto no; - } - - if (!(pcm_getflags(dev) & SD_F_SIMPLEX)) - snprintf(status2, SND_STATUSLEN, ":%jd", rman_get_start(sb->drq2)); - else - status2[0] = '\0'; - - snprintf(status, SND_STATUSLEN, "at io 0x%jx irq %jd drq %jd%s bufsz %u %s", - rman_get_start(sb->io_base), rman_get_start(sb->irq), - rman_get_start(sb->drq1), status2, sb->bufsize, - PCM_KLDSTRING(snd_sb16)); - - if (pcm_register(dev, sb, 1, 1)) - goto no; - pcm_addchan(dev, PCMDIR_REC, &sb16chan_class, sb); - pcm_addchan(dev, PCMDIR_PLAY, &sb16chan_class, sb); - - pcm_setstatus(dev, status); - - return 0; - -no: - sb16_release_resources(sb, dev); - return ENXIO; -} - -static int -sb16_detach(device_t dev) -{ - int r; - struct sb_info *sb; - - r = pcm_unregister(dev); - if (r) - return r; - - sb = pcm_getdevinfo(dev); - sb16_release_resources(sb, dev); - return 0; -} - -static device_method_t sb16_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, sb16_probe), - DEVMETHOD(device_attach, sb16_attach), - DEVMETHOD(device_detach, sb16_detach), - { 0, 0 } -}; - -static driver_t sb16_driver = { - "pcm", - sb16_methods, - PCM_SOFTC_SIZE, -}; - -DRIVER_MODULE(snd_sb16, sbc, sb16_driver, pcm_devclass, 0, 0); -MODULE_DEPEND(snd_sb16, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER); -MODULE_DEPEND(snd_sb16, snd_sbc, 1, 1, 1); -MODULE_VERSION(snd_sb16, 1); Index: sys/dev/sound/isa/sb8.c =================================================================== --- sys/dev/sound/isa/sb8.c +++ /dev/null @@ -1,803 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * Copyright (c) 1999 Cameron Grant - * Copyright (c) 1997,1998 Luigi Rizzo - * - * Derived from files in the Voxware 3.5 distribution, - * Copyright by Hannu Savolainen 1994, under the same copyright - * conditions. - * All rights reserved. - * - * 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 HAVE_KERNEL_OPTION_HEADERS -#include "opt_snd.h" -#endif - -#include - -#include -#include - -#include - -#include "mixer_if.h" - -SND_DECLARE_FILE("$FreeBSD$"); - -#define SB_DEFAULT_BUFSZ 4096 - -static u_int32_t sb_fmt[] = { - SND_FORMAT(AFMT_U8, 1, 0), - 0 -}; -static struct pcmchan_caps sb200_playcaps = {4000, 23000, sb_fmt, 0}; -static struct pcmchan_caps sb200_reccaps = {4000, 13000, sb_fmt, 0}; -static struct pcmchan_caps sb201_playcaps = {4000, 44100, sb_fmt, 0}; -static struct pcmchan_caps sb201_reccaps = {4000, 15000, sb_fmt, 0}; - -static u_int32_t sbpro_fmt[] = { - SND_FORMAT(AFMT_U8, 1, 0), - SND_FORMAT(AFMT_U8, 2, 0), - 0 -}; -static struct pcmchan_caps sbpro_playcaps = {4000, 44100, sbpro_fmt, 0}; -static struct pcmchan_caps sbpro_reccaps = {4000, 44100, sbpro_fmt, 0}; - -struct sb_info; - -struct sb_chinfo { - struct sb_info *parent; - struct pcm_channel *channel; - struct snd_dbuf *buffer; - int dir; - u_int32_t fmt, spd, blksz; -}; - -struct sb_info { - device_t parent_dev; - struct resource *io_base; /* I/O address for the board */ - struct resource *irq; - struct resource *drq; - void *ih; - bus_dma_tag_t parent_dmat; - - unsigned int bufsize; - int bd_id; - u_long bd_flags; /* board-specific flags */ - struct sb_chinfo pch, rch; -}; - -static int sb_rd(struct sb_info *sb, int reg); -static void sb_wr(struct sb_info *sb, int reg, u_int8_t val); -static int sb_dspready(struct sb_info *sb); -static int sb_cmd(struct sb_info *sb, u_char val); -static int sb_cmd1(struct sb_info *sb, u_char cmd, int val); -static int sb_cmd2(struct sb_info *sb, u_char cmd, int val); -static u_int sb_get_byte(struct sb_info *sb); -static void sb_setmixer(struct sb_info *sb, u_int port, u_int value); -static int sb_getmixer(struct sb_info *sb, u_int port); -static int sb_reset_dsp(struct sb_info *sb); - -static void sb_intr(void *arg); -static int sb_speed(struct sb_chinfo *ch); -static int sb_start(struct sb_chinfo *ch); -static int sb_stop(struct sb_chinfo *ch); - -/* - * Common code for the midi and pcm functions - * - * sb_cmd write a single byte to the CMD port. - * sb_cmd1 write a CMD + 1 byte arg - * sb_cmd2 write a CMD + 2 byte arg - * sb_get_byte returns a single byte from the DSP data port - */ - -static void -sb_lock(struct sb_info *sb) { - sbc_lock(device_get_softc(sb->parent_dev)); -} - -static void -sb_unlock(struct sb_info *sb) { - sbc_unlock(device_get_softc(sb->parent_dev)); -} - -static int -port_rd(struct resource *port, int off) -{ - return bus_space_read_1(rman_get_bustag(port), rman_get_bushandle(port), off); -} - -static void -port_wr(struct resource *port, int off, u_int8_t data) -{ - bus_space_write_1(rman_get_bustag(port), rman_get_bushandle(port), off, data); -} - -static int -sb_rd(struct sb_info *sb, int reg) -{ - return port_rd(sb->io_base, reg); -} - -static void -sb_wr(struct sb_info *sb, int reg, u_int8_t val) -{ - port_wr(sb->io_base, reg, val); -} - -static int -sb_dspready(struct sb_info *sb) -{ - return ((sb_rd(sb, SBDSP_STATUS) & 0x80) == 0); -} - -static int -sb_dspwr(struct sb_info *sb, u_char val) -{ - int i; - - for (i = 0; i < 1000; i++) { - if (sb_dspready(sb)) { - sb_wr(sb, SBDSP_CMD, val); - return 1; - } - if (i > 10) DELAY((i > 100)? 1000 : 10); - } - printf("sb_dspwr(0x%02x) timed out.\n", val); - return 0; -} - -static int -sb_cmd(struct sb_info *sb, u_char val) -{ -#if 0 - printf("sb_cmd: %x\n", val); -#endif - return sb_dspwr(sb, val); -} - -static int -sb_cmd1(struct sb_info *sb, u_char cmd, int val) -{ -#if 0 - printf("sb_cmd1: %x, %x\n", cmd, val); -#endif - if (sb_dspwr(sb, cmd)) { - return sb_dspwr(sb, val & 0xff); - } else return 0; -} - -static int -sb_cmd2(struct sb_info *sb, u_char cmd, int val) -{ -#if 0 - printf("sb_cmd2: %x, %x\n", cmd, val); -#endif - if (sb_dspwr(sb, cmd)) { - return sb_dspwr(sb, val & 0xff) && - sb_dspwr(sb, (val >> 8) & 0xff); - } else return 0; -} - -/* - * in the SB, there is a set of indirect "mixer" registers with - * address at offset 4, data at offset 5 - * - * we don't need to interlock these, the mixer lock will suffice. - */ -static void -sb_setmixer(struct sb_info *sb, u_int port, u_int value) -{ - sb_wr(sb, SB_MIX_ADDR, (u_char) (port & 0xff)); /* Select register */ - DELAY(10); - sb_wr(sb, SB_MIX_DATA, (u_char) (value & 0xff)); - DELAY(10); -} - -static int -sb_getmixer(struct sb_info *sb, u_int port) -{ - int val; - - sb_wr(sb, SB_MIX_ADDR, (u_char) (port & 0xff)); /* Select register */ - DELAY(10); - val = sb_rd(sb, SB_MIX_DATA); - DELAY(10); - - return val; -} - -static u_int -sb_get_byte(struct sb_info *sb) -{ - int i; - - for (i = 1000; i > 0; i--) { - if (sb_rd(sb, DSP_DATA_AVAIL) & 0x80) - return sb_rd(sb, DSP_READ); - else - DELAY(20); - } - return 0xffff; -} - -static int -sb_reset_dsp(struct sb_info *sb) -{ - sb_wr(sb, SBDSP_RST, 3); - DELAY(100); - sb_wr(sb, SBDSP_RST, 0); - if (sb_get_byte(sb) != 0xAA) { - DEB(printf("sb_reset_dsp 0x%lx failed\n", - rman_get_start(sb->io_base))); - return ENXIO; /* Sorry */ - } - return 0; -} - -static void -sb_release_resources(struct sb_info *sb, device_t dev) -{ - if (sb->irq) { - if (sb->ih) - bus_teardown_intr(dev, sb->irq, sb->ih); - bus_release_resource(dev, SYS_RES_IRQ, 0, sb->irq); - sb->irq = NULL; - } - if (sb->drq) { - isa_dma_release(rman_get_start(sb->drq)); - bus_release_resource(dev, SYS_RES_DRQ, 0, sb->drq); - sb->drq = NULL; - } - if (sb->io_base) { - bus_release_resource(dev, SYS_RES_IOPORT, 0, sb->io_base); - sb->io_base = NULL; - } - if (sb->parent_dmat) { - bus_dma_tag_destroy(sb->parent_dmat); - sb->parent_dmat = 0; - } - free(sb, M_DEVBUF); -} - -static int -sb_alloc_resources(struct sb_info *sb, device_t dev) -{ - int rid; - - rid = 0; - if (!sb->io_base) - sb->io_base = bus_alloc_resource_any(dev, SYS_RES_IOPORT, - &rid, RF_ACTIVE); - rid = 0; - if (!sb->irq) - sb->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, - &rid, RF_ACTIVE); - rid = 0; - if (!sb->drq) - sb->drq = bus_alloc_resource_any(dev, SYS_RES_DRQ, - &rid, RF_ACTIVE); - - if (sb->io_base && sb->drq && sb->irq) { - isa_dma_acquire(rman_get_start(sb->drq)); - isa_dmainit(rman_get_start(sb->drq), sb->bufsize); - - return 0; - } else return ENXIO; -} - -/************************************************************/ - -static int -sbpromix_init(struct snd_mixer *m) -{ - struct sb_info *sb = mix_getdevinfo(m); - - mix_setdevs(m, SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_LINE | - SOUND_MASK_MIC | SOUND_MASK_CD | SOUND_MASK_VOLUME); - - mix_setrecdevs(m, SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD); - - sb_setmixer(sb, 0, 1); /* reset mixer */ - - return 0; -} - -static int -sbpromix_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right) -{ - struct sb_info *sb = mix_getdevinfo(m); - int reg, max; - u_char val; - - max = 7; - switch (dev) { - case SOUND_MIXER_PCM: - reg = 0x04; - break; - - case SOUND_MIXER_MIC: - reg = 0x0a; - max = 3; - break; - - case SOUND_MIXER_VOLUME: - reg = 0x22; - break; - - case SOUND_MIXER_SYNTH: - reg = 0x26; - break; - - case SOUND_MIXER_CD: - reg = 0x28; - break; - - case SOUND_MIXER_LINE: - reg = 0x2e; - break; - - default: - return -1; - } - - left = (left * max) / 100; - right = (dev == SOUND_MIXER_MIC)? left : ((right * max) / 100); - - val = (dev == SOUND_MIXER_MIC)? (left << 1) : (left << 5 | right << 1); - sb_setmixer(sb, reg, val); - - left = (left * 100) / max; - right = (right * 100) / max; - - return left | (right << 8); -} - -static u_int32_t -sbpromix_setrecsrc(struct snd_mixer *m, u_int32_t src) -{ - struct sb_info *sb = mix_getdevinfo(m); - u_char recdev; - - if (src == SOUND_MASK_LINE) - recdev = 0x06; - else if (src == SOUND_MASK_CD) - recdev = 0x02; - else { /* default: mic */ - src = SOUND_MASK_MIC; - recdev = 0; - } - sb_setmixer(sb, RECORD_SRC, recdev | (sb_getmixer(sb, RECORD_SRC) & ~0x07)); - - return src; -} - -static kobj_method_t sbpromix_mixer_methods[] = { - KOBJMETHOD(mixer_init, sbpromix_init), - KOBJMETHOD(mixer_set, sbpromix_set), - KOBJMETHOD(mixer_setrecsrc, sbpromix_setrecsrc), - KOBJMETHOD_END -}; -MIXER_DECLARE(sbpromix_mixer); - -/************************************************************/ - -static int -sbmix_init(struct snd_mixer *m) -{ - struct sb_info *sb = mix_getdevinfo(m); - - mix_setdevs(m, SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_CD | SOUND_MASK_VOLUME); - - mix_setrecdevs(m, 0); - - sb_setmixer(sb, 0, 1); /* reset mixer */ - - return 0; -} - -static int -sbmix_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right) -{ - struct sb_info *sb = mix_getdevinfo(m); - int reg, max; - - max = 7; - switch (dev) { - case SOUND_MIXER_VOLUME: - reg = 0x2; - break; - - case SOUND_MIXER_SYNTH: - reg = 0x6; - break; - - case SOUND_MIXER_CD: - reg = 0x8; - break; - - case SOUND_MIXER_PCM: - reg = 0x0a; - max = 3; - break; - - default: - return -1; - } - - left = (left * max) / 100; - - sb_setmixer(sb, reg, left << 1); - - left = (left * 100) / max; - - return left | (left << 8); -} - -static u_int32_t -sbmix_setrecsrc(struct snd_mixer *m, u_int32_t src) -{ - return 0; -} - -static kobj_method_t sbmix_mixer_methods[] = { - KOBJMETHOD(mixer_init, sbmix_init), - KOBJMETHOD(mixer_set, sbmix_set), - KOBJMETHOD(mixer_setrecsrc, sbmix_setrecsrc), - KOBJMETHOD_END -}; -MIXER_DECLARE(sbmix_mixer); - -/************************************************************/ - -static void -sb_intr(void *arg) -{ - struct sb_info *sb = (struct sb_info *)arg; - - sb_lock(sb); - if (sndbuf_runsz(sb->pch.buffer) > 0) { - sb_unlock(sb); - chn_intr(sb->pch.channel); - sb_lock(sb); - } - - if (sndbuf_runsz(sb->rch.buffer) > 0) { - sb_unlock(sb); - chn_intr(sb->rch.channel); - sb_lock(sb); - } - - sb_rd(sb, DSP_DATA_AVAIL); /* int ack */ - sb_unlock(sb); -} - -static int -sb_speed(struct sb_chinfo *ch) -{ - struct sb_info *sb = ch->parent; - int play = (ch->dir == PCMDIR_PLAY)? 1 : 0; - int stereo = (AFMT_CHANNEL(ch->fmt) > 1)? 1 : 0; - int speed, tmp, thresh, max; - u_char tconst; - - if (sb->bd_id >= 0x300) { - thresh = stereo? 11025 : 23000; - max = stereo? 22050 : 44100; - } else if (sb->bd_id > 0x200) { - thresh = play? 23000 : 13000; - max = play? 44100 : 15000; - } else { - thresh = 999999; - max = play? 23000 : 13000; - } - - speed = ch->spd; - if (speed > max) - speed = max; - - sb_lock(sb); - sb->bd_flags &= ~BD_F_HISPEED; - if (speed > thresh) - sb->bd_flags |= BD_F_HISPEED; - - tmp = 65536 - (256000000 / (speed << stereo)); - tconst = tmp >> 8; - - sb_cmd1(sb, 0x40, tconst); /* set time constant */ - - speed = (256000000 / (65536 - tmp)) >> stereo; - - ch->spd = speed; - sb_unlock(sb); - return speed; -} - -static int -sb_start(struct sb_chinfo *ch) -{ - struct sb_info *sb = ch->parent; - int play = (ch->dir == PCMDIR_PLAY)? 1 : 0; - int stereo = (AFMT_CHANNEL(ch->fmt) > 1)? 1 : 0; - int l = ch->blksz; - u_char i; - - l--; - - sb_lock(sb); - if (play) - sb_cmd(sb, DSP_CMD_SPKON); - - if (sb->bd_flags & BD_F_HISPEED) - i = play? 0x90 : 0x98; - else - i = play? 0x1c : 0x2c; - - sb_setmixer(sb, 0x0e, stereo? 2 : 0); - sb_cmd2(sb, 0x48, l); - sb_cmd(sb, i); - - sb->bd_flags |= BD_F_DMARUN; - sb_unlock(sb); - return 0; -} - -static int -sb_stop(struct sb_chinfo *ch) -{ - struct sb_info *sb = ch->parent; - int play = (ch->dir == PCMDIR_PLAY)? 1 : 0; - - sb_lock(sb); - if (sb->bd_flags & BD_F_HISPEED) - sb_reset_dsp(sb); - else { -#if 0 - /* - * NOTE: DSP_CMD_DMAEXIT_8 does not work with old - * soundblaster. - */ - sb_cmd(sb, DSP_CMD_DMAEXIT_8); -#endif - sb_reset_dsp(sb); - } - - if (play) - sb_cmd(sb, DSP_CMD_SPKOFF); /* speaker off */ - sb_unlock(sb); - sb->bd_flags &= ~BD_F_DMARUN; - return 0; -} - -/* channel interface */ -static void * -sbchan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir) -{ - struct sb_info *sb = devinfo; - struct sb_chinfo *ch = (dir == PCMDIR_PLAY)? &sb->pch : &sb->rch; - - ch->parent = sb; - ch->channel = c; - ch->dir = dir; - ch->buffer = b; - if (sndbuf_alloc(ch->buffer, sb->parent_dmat, 0, sb->bufsize) != 0) - return NULL; - sndbuf_dmasetup(ch->buffer, sb->drq); - return ch; -} - -static int -sbchan_setformat(kobj_t obj, void *data, u_int32_t format) -{ - struct sb_chinfo *ch = data; - - ch->fmt = format; - return 0; -} - -static u_int32_t -sbchan_setspeed(kobj_t obj, void *data, u_int32_t speed) -{ - struct sb_chinfo *ch = data; - - ch->spd = speed; - return sb_speed(ch); -} - -static u_int32_t -sbchan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize) -{ - struct sb_chinfo *ch = data; - - ch->blksz = blocksize; - return ch->blksz; -} - -static int -sbchan_trigger(kobj_t obj, void *data, int go) -{ - struct sb_chinfo *ch = data; - - if (!PCMTRIG_COMMON(go)) - return 0; - - sndbuf_dma(ch->buffer, go); - if (go == PCMTRIG_START) - sb_start(ch); - else - sb_stop(ch); - return 0; -} - -static u_int32_t -sbchan_getptr(kobj_t obj, void *data) -{ - struct sb_chinfo *ch = data; - - return sndbuf_dmaptr(ch->buffer); -} - -static struct pcmchan_caps * -sbchan_getcaps(kobj_t obj, void *data) -{ - struct sb_chinfo *ch = data; - int p = (ch->dir == PCMDIR_PLAY)? 1 : 0; - - if (ch->parent->bd_id == 0x200) - return p? &sb200_playcaps : &sb200_reccaps; - if (ch->parent->bd_id < 0x300) - return p? &sb201_playcaps : &sb201_reccaps; - return p? &sbpro_playcaps : &sbpro_reccaps; -} - -static kobj_method_t sbchan_methods[] = { - KOBJMETHOD(channel_init, sbchan_init), - KOBJMETHOD(channel_setformat, sbchan_setformat), - KOBJMETHOD(channel_setspeed, sbchan_setspeed), - KOBJMETHOD(channel_setblocksize, sbchan_setblocksize), - KOBJMETHOD(channel_trigger, sbchan_trigger), - KOBJMETHOD(channel_getptr, sbchan_getptr), - KOBJMETHOD(channel_getcaps, sbchan_getcaps), - KOBJMETHOD_END -}; -CHANNEL_DECLARE(sbchan); - -/************************************************************/ - -static int -sb_probe(device_t dev) -{ - char buf[64]; - uintptr_t func, ver, r, f; - - /* The parent device has already been probed. */ - r = BUS_READ_IVAR(device_get_parent(dev), dev, 0, &func); - if (func != SCF_PCM) - return (ENXIO); - - r = BUS_READ_IVAR(device_get_parent(dev), dev, 1, &ver); - f = (ver & 0xffff0000) >> 16; - ver &= 0x0000ffff; - if ((f & BD_F_ESS) || (ver >= 0x400)) - return (ENXIO); - - snprintf(buf, sizeof buf, "SB DSP %d.%02d", (int) ver >> 8, (int) ver & 0xff); - - device_set_desc_copy(dev, buf); - - return 0; -} - -static int -sb_attach(device_t dev) -{ - struct sb_info *sb; - char status[SND_STATUSLEN]; - uintptr_t ver; - - gone_in_dev(dev, 14, "ISA sound driver"); - sb = malloc(sizeof(*sb), M_DEVBUF, M_WAITOK | M_ZERO); - sb->parent_dev = device_get_parent(dev); - BUS_READ_IVAR(device_get_parent(dev), dev, 1, &ver); - sb->bd_id = ver & 0x0000ffff; - sb->bd_flags = (ver & 0xffff0000) >> 16; - sb->bufsize = pcm_getbuffersize(dev, 4096, SB_DEFAULT_BUFSZ, 65536); - - if (sb_alloc_resources(sb, dev)) - goto no; - if (sb_reset_dsp(sb)) - goto no; - if (mixer_init(dev, (sb->bd_id < 0x300)? &sbmix_mixer_class : &sbpromix_mixer_class, sb)) - goto no; - if (snd_setup_intr(dev, sb->irq, 0, sb_intr, sb, &sb->ih)) - goto no; - - pcm_setflags(dev, pcm_getflags(dev) | SD_F_SIMPLEX); - - if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(dev), /*alignment*/2, - /*boundary*/0, - /*lowaddr*/BUS_SPACE_MAXADDR_24BIT, - /*highaddr*/BUS_SPACE_MAXADDR, - /*filter*/NULL, /*filterarg*/NULL, - /*maxsize*/sb->bufsize, /*nsegments*/1, - /*maxsegz*/0x3ffff, /*flags*/0, - /*lockfunc*/NULL, /*lockarg*/NULL, - &sb->parent_dmat) != 0) { - device_printf(dev, "unable to create dma tag\n"); - goto no; - } - - snprintf(status, SND_STATUSLEN, "at io 0x%jx irq %jd drq %jd bufsz %u %s", - rman_get_start(sb->io_base), rman_get_start(sb->irq), - rman_get_start(sb->drq), sb->bufsize, PCM_KLDSTRING(snd_sb8)); - - if (pcm_register(dev, sb, 1, 1)) - goto no; - pcm_addchan(dev, PCMDIR_REC, &sbchan_class, sb); - pcm_addchan(dev, PCMDIR_PLAY, &sbchan_class, sb); - - pcm_setstatus(dev, status); - - return 0; - -no: - sb_release_resources(sb, dev); - return ENXIO; -} - -static int -sb_detach(device_t dev) -{ - int r; - struct sb_info *sb; - - r = pcm_unregister(dev); - if (r) - return r; - - sb = pcm_getdevinfo(dev); - sb_release_resources(sb, dev); - return 0; -} - -static device_method_t sb_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, sb_probe), - DEVMETHOD(device_attach, sb_attach), - DEVMETHOD(device_detach, sb_detach), - { 0, 0 } -}; - -static driver_t sb_driver = { - "pcm", - sb_methods, - PCM_SOFTC_SIZE, -}; - -DRIVER_MODULE(snd_sb8, sbc, sb_driver, pcm_devclass, 0, 0); -MODULE_DEPEND(snd_sb8, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER); -MODULE_DEPEND(snd_sb8, snd_sbc, 1, 1, 1); -MODULE_VERSION(snd_sb8, 1); Index: sys/dev/sound/isa/sbc.c =================================================================== --- sys/dev/sound/isa/sbc.c +++ /dev/null @@ -1,754 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * Copyright (c) 1999 Seigo Tanimura - * All rights reserved. - * - * 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 HAVE_KERNEL_OPTION_HEADERS -#include "opt_snd.h" -#endif - -#include -#include -#include - -#include - -SND_DECLARE_FILE("$FreeBSD$"); - -#define IO_MAX 3 -#define IRQ_MAX 1 -#define DRQ_MAX 2 -#define INTR_MAX 2 - -struct sbc_softc; - -struct sbc_ihl { - driver_intr_t *intr[INTR_MAX]; - void *intr_arg[INTR_MAX]; - struct sbc_softc *parent; -}; - -/* Here is the parameter structure per a device. */ -struct sbc_softc { - device_t dev; /* device */ - device_t child_pcm, child_midi1, child_midi2; - - int io_rid[IO_MAX]; /* io port rids */ - struct resource *io[IO_MAX]; /* io port resources */ - int io_alloced[IO_MAX]; /* io port alloc flag */ - - int irq_rid[IRQ_MAX]; /* irq rids */ - struct resource *irq[IRQ_MAX]; /* irq resources */ - int irq_alloced[IRQ_MAX]; /* irq alloc flag */ - - int drq_rid[DRQ_MAX]; /* drq rids */ - struct resource *drq[DRQ_MAX]; /* drq resources */ - int drq_alloced[DRQ_MAX]; /* drq alloc flag */ - - struct sbc_ihl ihl[IRQ_MAX]; - - void *ih[IRQ_MAX]; - - struct mtx *lock; - - u_int32_t bd_ver; -}; - -static int sbc_probe(device_t dev); -static int sbc_attach(device_t dev); -static void sbc_intr(void *p); - -static struct resource *sbc_alloc_resource(device_t bus, device_t child, int type, int *rid, - rman_res_t start, rman_res_t end, rman_res_t count, u_int flags); -static int sbc_release_resource(device_t bus, device_t child, int type, int rid, - struct resource *r); -static int sbc_setup_intr(device_t dev, device_t child, struct resource *irq, - int flags, - driver_filter_t *filter, - driver_intr_t *intr, - void *arg, void **cookiep); -static int sbc_teardown_intr(device_t dev, device_t child, struct resource *irq, - void *cookie); - -static int alloc_resource(struct sbc_softc *scp); -static int release_resource(struct sbc_softc *scp); - -static devclass_t sbc_devclass; - -static int io_range[3] = {0x10, 0x2, 0x4}; - -static int sb_rd(struct resource *io, int reg); -static void sb_wr(struct resource *io, int reg, u_int8_t val); -static int sb_dspready(struct resource *io); -static int sb_cmd(struct resource *io, u_char val); -static u_int sb_get_byte(struct resource *io); -static void sb_setmixer(struct resource *io, u_int port, u_int value); - -static void -sbc_lockinit(struct sbc_softc *scp) -{ - scp->lock = snd_mtxcreate(device_get_nameunit(scp->dev), - "snd_sbc softc"); -} - -static void -sbc_lockdestroy(struct sbc_softc *scp) -{ - snd_mtxfree(scp->lock); -} - -void -sbc_lock(struct sbc_softc *scp) -{ - snd_mtxlock(scp->lock); -} - -void -sbc_lockassert(struct sbc_softc *scp) -{ - snd_mtxassert(scp->lock); -} - -void -sbc_unlock(struct sbc_softc *scp) -{ - snd_mtxunlock(scp->lock); -} - -static int -sb_rd(struct resource *io, int reg) -{ - return bus_space_read_1(rman_get_bustag(io), - rman_get_bushandle(io), - reg); -} - -static void -sb_wr(struct resource *io, int reg, u_int8_t val) -{ - bus_space_write_1(rman_get_bustag(io), - rman_get_bushandle(io), - reg, val); -} - -static int -sb_dspready(struct resource *io) -{ - return ((sb_rd(io, SBDSP_STATUS) & 0x80) == 0); -} - -static int -sb_dspwr(struct resource *io, u_char val) -{ - int i; - - for (i = 0; i < 1000; i++) { - if (sb_dspready(io)) { - sb_wr(io, SBDSP_CMD, val); - return 1; - } - if (i > 10) DELAY((i > 100)? 1000 : 10); - } - printf("sb_dspwr(0x%02x) timed out.\n", val); - return 0; -} - -static int -sb_cmd(struct resource *io, u_char val) -{ - return sb_dspwr(io, val); -} - -static void -sb_setmixer(struct resource *io, u_int port, u_int value) -{ - u_long flags; - - flags = spltty(); - sb_wr(io, SB_MIX_ADDR, (u_char) (port & 0xff)); /* Select register */ - DELAY(10); - sb_wr(io, SB_MIX_DATA, (u_char) (value & 0xff)); - DELAY(10); - splx(flags); -} - -static u_int -sb_get_byte(struct resource *io) -{ - int i; - - for (i = 1000; i > 0; i--) { - if (sb_rd(io, DSP_DATA_AVAIL) & 0x80) - return sb_rd(io, DSP_READ); - else - DELAY(20); - } - return 0xffff; -} - -static int -sb_reset_dsp(struct resource *io) -{ - sb_wr(io, SBDSP_RST, 3); - DELAY(100); - sb_wr(io, SBDSP_RST, 0); - return (sb_get_byte(io) == 0xAA)? 0 : ENXIO; -} - -static int -sb_identify_board(struct resource *io) -{ - int ver, essver, rev; - - sb_cmd(io, DSP_CMD_GETVER); /* Get version */ - ver = (sb_get_byte(io) << 8) | sb_get_byte(io); - if (ver < 0x100 || ver > 0x4ff) return 0; - if (ver == 0x0301) { - /* Try to detect ESS chips. */ - sb_cmd(io, DSP_CMD_GETID); /* Return ident. bytes. */ - essver = (sb_get_byte(io) << 8) | sb_get_byte(io); - rev = essver & 0x000f; - essver &= 0xfff0; - if (essver == 0x4880) ver |= 0x1000; - else if (essver == 0x6880) ver = 0x0500 | rev; - } - return ver; -} - -static struct isa_pnp_id sbc_ids[] = { - {0x01008c0e, "Creative ViBRA16C"}, /* CTL0001 */ - {0x31008c0e, "Creative SB16/SB32"}, /* CTL0031 */ - {0x41008c0e, "Creative SB16/SB32"}, /* CTL0041 */ - {0x42008c0e, "Creative SB AWE64"}, /* CTL0042 */ - {0x43008c0e, "Creative ViBRA16X"}, /* CTL0043 */ - {0x44008c0e, "Creative SB AWE64 Gold"}, /* CTL0044 */ - {0x45008c0e, "Creative SB AWE64"}, /* CTL0045 */ - {0x46008c0e, "Creative SB AWE64"}, /* CTL0046 */ - - {0x01000000, "Avance Logic ALS100+"}, /* @@@0001 - ViBRA16X clone */ - {0x01100000, "Avance Asound 110"}, /* @@@1001 */ - {0x01200000, "Avance Logic ALS120"}, /* @@@2001 - ViBRA16X clone */ - - {0x81167316, "ESS ES1681"}, /* ESS1681 */ - {0x02017316, "ESS ES1688"}, /* ESS1688 */ - {0x68097316, "ESS ES1688"}, /* ESS1688 */ - {0x68187316, "ESS ES1868"}, /* ESS1868 */ - {0x03007316, "ESS ES1869"}, /* ESS1869 */ - {0x69187316, "ESS ES1869"}, /* ESS1869 */ - {0xabb0110e, "ESS ES1869 (Compaq OEM)"}, /* CPQb0ab */ - {0xacb0110e, "ESS ES1869 (Compaq OEM)"}, /* CPQb0ac */ - {0x78187316, "ESS ES1878"}, /* ESS1878 */ - {0x79187316, "ESS ES1879"}, /* ESS1879 */ - {0x88187316, "ESS ES1888"}, /* ESS1888 */ - {0x07017316, "ESS ES1888 (DEC OEM)"}, /* ESS0107 */ - {0x06017316, "ESS ES1888 (Dell OEM)"}, /* ESS0106 */ - {0} -}; - -static int -sbc_probe(device_t dev) -{ - char *s = NULL; - u_int32_t lid, vid; - - lid = isa_get_logicalid(dev); - vid = isa_get_vendorid(dev); - if (lid) { - if (lid == 0x01000000 && vid != 0x01009305) /* ALS0001 */ - return ENXIO; - /* Check pnp ids */ - return ISA_PNP_PROBE(device_get_parent(dev), dev, sbc_ids); - } else { - int rid = 0, ver; - struct resource *io; - - io = bus_alloc_resource_anywhere(dev, SYS_RES_IOPORT, &rid, - 16, RF_ACTIVE); - if (!io) goto bad; - if (sb_reset_dsp(io)) goto bad2; - ver = sb_identify_board(io); - if (ver == 0) goto bad2; - switch ((ver & 0x00000f00) >> 8) { - case 1: - device_set_desc(dev, "SoundBlaster 1.0 (not supported)"); - s = NULL; - break; - - case 2: - s = "SoundBlaster 2.0"; - break; - - case 3: - s = (ver & 0x0000f000)? "ESS 488" : "SoundBlaster Pro"; - break; - - case 4: - s = "SoundBlaster 16"; - break; - - case 5: - s = (ver & 0x00000008)? "ESS 688" : "ESS 1688"; - break; - } - if (s) device_set_desc(dev, s); -bad2: bus_release_resource(dev, SYS_RES_IOPORT, rid, io); -bad: return s? 0 : ENXIO; - } -} - -static int -sbc_attach(device_t dev) -{ - char *err = NULL; - struct sbc_softc *scp; - struct sndcard_func *func; - u_int32_t logical_id = isa_get_logicalid(dev); - int flags = device_get_flags(dev); - int f, dh, dl, x, irq, i; - - gone_in_dev(dev, 14, "ISA sound driver"); - if (!logical_id && (flags & DV_F_DUAL_DMA)) { - bus_set_resource(dev, SYS_RES_DRQ, 1, - flags & DV_F_DRQ_MASK, 1); - } - - scp = device_get_softc(dev); - bzero(scp, sizeof(*scp)); - scp->dev = dev; - sbc_lockinit(scp); - err = "alloc_resource"; - if (alloc_resource(scp)) goto bad; - - err = "sb_reset_dsp"; - if (sb_reset_dsp(scp->io[0])) goto bad; - err = "sb_identify_board"; - scp->bd_ver = sb_identify_board(scp->io[0]) & 0x00000fff; - if (scp->bd_ver == 0) goto bad; - f = 0; - if (logical_id == 0x01200000 && scp->bd_ver < 0x0400) scp->bd_ver = 0x0499; - switch ((scp->bd_ver & 0x0f00) >> 8) { - case 1: /* old sound blaster has nothing... */ - break; - - case 2: - f |= BD_F_DUP_MIDI; - if (scp->bd_ver > 0x200) f |= BD_F_MIX_CT1335; - break; - - case 5: - f |= BD_F_ESS; - scp->bd_ver = 0x0301; - case 3: - f |= BD_F_DUP_MIDI | BD_F_MIX_CT1345; - break; - - case 4: - f |= BD_F_SB16 | BD_F_MIX_CT1745; - if (scp->drq[0]) dl = rman_get_start(scp->drq[0]); else dl = -1; - if (scp->drq[1]) dh = rman_get_start(scp->drq[1]); else dh = dl; - if (!logical_id && (dh < dl)) { - struct resource *r; - r = scp->drq[0]; - scp->drq[0] = scp->drq[1]; - scp->drq[1] = r; - dl = rman_get_start(scp->drq[0]); - dh = rman_get_start(scp->drq[1]); - } - /* soft irq/dma configuration */ - x = -1; - irq = rman_get_start(scp->irq[0]); - if (irq == 5) x = 2; - else if (irq == 7) x = 4; - else if (irq == 9) x = 1; - else if (irq == 10) x = 8; - if (x == -1) { - err = "bad irq (5/7/9/10 valid)"; - goto bad; - } - else sb_setmixer(scp->io[0], IRQ_NR, x); - sb_setmixer(scp->io[0], DMA_NR, (1 << dh) | (1 << dl)); - if (bootverbose) { - device_printf(dev, "setting card to irq %d, drq %d", irq, dl); - if (dl != dh) printf(", %d", dh); - printf("\n"); - } - break; - } - - switch (logical_id) { - case 0x43008c0e: /* CTL0043 */ - case 0x01200000: - case 0x01000000: - f |= BD_F_SB16X; - break; - } - scp->bd_ver |= f << 16; - - err = "setup_intr"; - for (i = 0; i < IRQ_MAX; i++) { - scp->ihl[i].parent = scp; - if (snd_setup_intr(dev, scp->irq[i], 0, sbc_intr, &scp->ihl[i], &scp->ih[i])) - goto bad; - } - - /* PCM Audio */ - func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO); - if (func == NULL) goto bad; - func->func = SCF_PCM; - scp->child_pcm = device_add_child(dev, "pcm", -1); - device_set_ivars(scp->child_pcm, func); - - /* Midi Interface */ - func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO); - if (func == NULL) goto bad; - func->func = SCF_MIDI; - scp->child_midi1 = device_add_child(dev, "midi", -1); - device_set_ivars(scp->child_midi1, func); - - /* OPL FM Synthesizer */ - func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO); - if (func == NULL) goto bad; - func->func = SCF_SYNTH; - scp->child_midi2 = device_add_child(dev, "midi", -1); - device_set_ivars(scp->child_midi2, func); - - /* probe/attach kids */ - bus_generic_attach(dev); - - return (0); - -bad: if (err) device_printf(dev, "%s\n", err); - release_resource(scp); - return (ENXIO); -} - -static int -sbc_detach(device_t dev) -{ - struct sbc_softc *scp = device_get_softc(dev); - - sbc_lock(scp); - device_delete_child(dev, scp->child_midi2); - device_delete_child(dev, scp->child_midi1); - device_delete_child(dev, scp->child_pcm); - release_resource(scp); - sbc_lockdestroy(scp); - return bus_generic_detach(dev); -} - -static void -sbc_intr(void *p) -{ - struct sbc_ihl *ihl = p; - int i; - - /* sbc_lock(ihl->parent); */ - i = 0; - while (i < INTR_MAX) { - if (ihl->intr[i] != NULL) ihl->intr[i](ihl->intr_arg[i]); - i++; - } - /* sbc_unlock(ihl->parent); */ -} - -static int -sbc_setup_intr(device_t dev, device_t child, struct resource *irq, int flags, - driver_filter_t *filter, - driver_intr_t *intr, - void *arg, void **cookiep) -{ - struct sbc_softc *scp = device_get_softc(dev); - struct sbc_ihl *ihl = NULL; - int i, ret; - - if (filter != NULL) { - printf("sbc.c: we cannot use a filter here\n"); - return (EINVAL); - } - sbc_lock(scp); - i = 0; - while (i < IRQ_MAX) { - if (irq == scp->irq[i]) ihl = &scp->ihl[i]; - i++; - } - ret = 0; - if (ihl == NULL) ret = EINVAL; - i = 0; - while ((ret == 0) && (i < INTR_MAX)) { - if (ihl->intr[i] == NULL) { - ihl->intr[i] = intr; - ihl->intr_arg[i] = arg; - *cookiep = &ihl->intr[i]; - ret = -1; - } else i++; - } - sbc_unlock(scp); - return (ret > 0)? EINVAL : 0; -} - -static int -sbc_teardown_intr(device_t dev, device_t child, struct resource *irq, - void *cookie) -{ - struct sbc_softc *scp = device_get_softc(dev); - struct sbc_ihl *ihl = NULL; - int i, ret; - - sbc_lock(scp); - i = 0; - while (i < IRQ_MAX) { - if (irq == scp->irq[i]) ihl = &scp->ihl[i]; - i++; - } - ret = 0; - if (ihl == NULL) ret = EINVAL; - i = 0; - while ((ret == 0) && (i < INTR_MAX)) { - if (cookie == &ihl->intr[i]) { - ihl->intr[i] = NULL; - ihl->intr_arg[i] = NULL; - return 0; - } else i++; - } - sbc_unlock(scp); - return (ret > 0)? EINVAL : 0; -} - -static struct resource * -sbc_alloc_resource(device_t bus, device_t child, int type, int *rid, - rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) -{ - struct sbc_softc *scp; - int *alloced, rid_max, alloced_max; - struct resource **res; - - scp = device_get_softc(bus); - switch (type) { - case SYS_RES_IOPORT: - alloced = scp->io_alloced; - res = scp->io; - rid_max = IO_MAX - 1; - alloced_max = 1; - break; - case SYS_RES_DRQ: - alloced = scp->drq_alloced; - res = scp->drq; - rid_max = DRQ_MAX - 1; - alloced_max = 1; - break; - case SYS_RES_IRQ: - alloced = scp->irq_alloced; - res = scp->irq; - rid_max = IRQ_MAX - 1; - alloced_max = INTR_MAX; /* pcm and mpu may share the irq. */ - break; - default: - return (NULL); - } - - if (*rid > rid_max || alloced[*rid] == alloced_max) - return (NULL); - - alloced[*rid]++; - return (res[*rid]); -} - -static int -sbc_release_resource(device_t bus, device_t child, int type, int rid, - struct resource *r) -{ - struct sbc_softc *scp; - int *alloced, rid_max; - - scp = device_get_softc(bus); - switch (type) { - case SYS_RES_IOPORT: - alloced = scp->io_alloced; - rid_max = IO_MAX - 1; - break; - case SYS_RES_DRQ: - alloced = scp->drq_alloced; - rid_max = DRQ_MAX - 1; - break; - case SYS_RES_IRQ: - alloced = scp->irq_alloced; - rid_max = IRQ_MAX - 1; - break; - default: - return (1); - } - - if (rid > rid_max || alloced[rid] == 0) - return (1); - - alloced[rid]--; - return (0); -} - -static int -sbc_read_ivar(device_t bus, device_t dev, int index, uintptr_t * result) -{ - struct sbc_softc *scp = device_get_softc(bus); - struct sndcard_func *func = device_get_ivars(dev); - - switch (index) { - case 0: - *result = func->func; - break; - - case 1: - *result = scp->bd_ver; - break; - - default: - return ENOENT; - } - - return 0; -} - -static int -sbc_write_ivar(device_t bus, device_t dev, - int index, uintptr_t value) -{ - switch (index) { - case 0: - case 1: - return EINVAL; - - default: - return (ENOENT); - } -} - -static int -alloc_resource(struct sbc_softc *scp) -{ - int i; - - for (i = 0 ; i < IO_MAX ; i++) { - if (scp->io[i] == NULL) { - scp->io_rid[i] = i; - scp->io[i] = bus_alloc_resource_anywhere(scp->dev, - SYS_RES_IOPORT, - &scp->io_rid[i], - io_range[i], - RF_ACTIVE); - if (i == 0 && scp->io[i] == NULL) - return (1); - scp->io_alloced[i] = 0; - } - } - for (i = 0 ; i < DRQ_MAX ; i++) { - if (scp->drq[i] == NULL) { - scp->drq_rid[i] = i; - scp->drq[i] = bus_alloc_resource_any(scp->dev, - SYS_RES_DRQ, - &scp->drq_rid[i], - RF_ACTIVE); - if (i == 0 && scp->drq[i] == NULL) - return (1); - scp->drq_alloced[i] = 0; - } - } - for (i = 0 ; i < IRQ_MAX ; i++) { - if (scp->irq[i] == NULL) { - scp->irq_rid[i] = i; - scp->irq[i] = bus_alloc_resource_any(scp->dev, - SYS_RES_IRQ, - &scp->irq_rid[i], - RF_ACTIVE); - if (i == 0 && scp->irq[i] == NULL) - return (1); - scp->irq_alloced[i] = 0; - } - } - return (0); -} - -static int -release_resource(struct sbc_softc *scp) -{ - int i; - - for (i = 0 ; i < IO_MAX ; i++) { - if (scp->io[i] != NULL) { - bus_release_resource(scp->dev, SYS_RES_IOPORT, scp->io_rid[i], scp->io[i]); - scp->io[i] = NULL; - } - } - for (i = 0 ; i < DRQ_MAX ; i++) { - if (scp->drq[i] != NULL) { - bus_release_resource(scp->dev, SYS_RES_DRQ, scp->drq_rid[i], scp->drq[i]); - scp->drq[i] = NULL; - } - } - for (i = 0 ; i < IRQ_MAX ; i++) { - if (scp->irq[i] != NULL) { - if (scp->ih[i] != NULL) - bus_teardown_intr(scp->dev, scp->irq[i], scp->ih[i]); - scp->ih[i] = NULL; - bus_release_resource(scp->dev, SYS_RES_IRQ, scp->irq_rid[i], scp->irq[i]); - scp->irq[i] = NULL; - } - } - return (0); -} - -static device_method_t sbc_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, sbc_probe), - DEVMETHOD(device_attach, sbc_attach), - DEVMETHOD(device_detach, sbc_detach), - DEVMETHOD(device_shutdown, bus_generic_shutdown), - DEVMETHOD(device_suspend, bus_generic_suspend), - DEVMETHOD(device_resume, bus_generic_resume), - - /* Bus interface */ - DEVMETHOD(bus_read_ivar, sbc_read_ivar), - DEVMETHOD(bus_write_ivar, sbc_write_ivar), - DEVMETHOD(bus_alloc_resource, sbc_alloc_resource), - DEVMETHOD(bus_release_resource, sbc_release_resource), - DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), - DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), - DEVMETHOD(bus_setup_intr, sbc_setup_intr), - DEVMETHOD(bus_teardown_intr, sbc_teardown_intr), - - DEVMETHOD_END -}; - -static driver_t sbc_driver = { - "sbc", - sbc_methods, - sizeof(struct sbc_softc), -}; - -/* sbc can be attached to an isa bus. */ -DRIVER_MODULE(snd_sbc, isa, sbc_driver, sbc_devclass, 0, 0); -DRIVER_MODULE(snd_sbc, acpi, sbc_driver, sbc_devclass, 0, 0); -MODULE_DEPEND(snd_sbc, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER); -MODULE_VERSION(snd_sbc, 1); -ISA_PNP_INFO(sbc_ids); Index: sys/dev/sound/isa/sndbuf_dma.c =================================================================== --- sys/dev/sound/isa/sndbuf_dma.c +++ /dev/null @@ -1,109 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * Copyright (c) 1999 Cameron Grant - * All rights reserved. - * - * 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 HAVE_KERNEL_OPTION_HEADERS -#include "opt_snd.h" -#endif - -#include - -#include - -SND_DECLARE_FILE("$FreeBSD$"); - -int -sndbuf_dmasetup(struct snd_dbuf *b, struct resource *drq) -{ - /* should do isa_dma_acquire/isa_dma_release here */ - if (drq == NULL) { - b->dmachan = -1; - } else { - sndbuf_setflags(b, SNDBUF_F_DMA, 1); - b->dmachan = rman_get_start(drq); - } - return 0; -} - -int -sndbuf_dmasetdir(struct snd_dbuf *b, int dir) -{ - KASSERT(b, ("sndbuf_dmasetdir called with b == NULL")); - KASSERT(sndbuf_getflags(b) & SNDBUF_F_DMA, ("sndbuf_dmasetdir called on non-ISA buffer")); - - b->dir = (dir == PCMDIR_PLAY)? ISADMA_WRITE : ISADMA_READ; - return 0; -} - -void -sndbuf_dma(struct snd_dbuf *b, int go) -{ - KASSERT(b, ("sndbuf_dma called with b == NULL")); - KASSERT(sndbuf_getflags(b) & SNDBUF_F_DMA, ("sndbuf_dma called on non-ISA buffer")); - - switch (go) { - case PCMTRIG_START: - /* isa_dmainit(b->chan, size); */ - isa_dmastart(b->dir | ISADMA_RAW, b->buf, b->bufsize, b->dmachan); - break; - - case PCMTRIG_STOP: - case PCMTRIG_ABORT: - isa_dmastop(b->dmachan); - isa_dmadone(b->dir | ISADMA_RAW, b->buf, b->bufsize, b->dmachan); - break; - } - - DEB(printf("buf 0x%p ISA DMA %s, channel %d\n", - b, - (go == PCMTRIG_START)? "started" : "stopped", - b->dmachan)); -} - -int -sndbuf_dmaptr(struct snd_dbuf *b) -{ - int i; - - KASSERT(b, ("sndbuf_dmaptr called with b == NULL")); - KASSERT(sndbuf_getflags(b) & SNDBUF_F_DMA, ("sndbuf_dmaptr called on non-ISA buffer")); - - if (!sndbuf_runsz(b)) - return 0; - i = isa_dmastatus(b->dmachan); - KASSERT(i >= 0, ("isa_dmastatus returned %d", i)); - return b->bufsize - i; -} - -void -sndbuf_dmabounce(struct snd_dbuf *b) -{ - KASSERT(b, ("sndbuf_dmabounce called with b == NULL")); - KASSERT(sndbuf_getflags(b) & SNDBUF_F_DMA, ("sndbuf_dmabounce called on non-ISA buffer")); - - /* tell isa_dma to bounce data in/out */ -} Index: sys/dev/sound/pcm/buffer.h =================================================================== --- sys/dev/sound/pcm/buffer.h +++ sys/dev/sound/pcm/buffer.h @@ -125,12 +125,6 @@ u_int32_t sndbuf_getflags(struct snd_dbuf *b); void sndbuf_setflags(struct snd_dbuf *b, u_int32_t flags, int on); -int sndbuf_dmasetup(struct snd_dbuf *b, struct resource *drq); -int sndbuf_dmasetdir(struct snd_dbuf *b, int dir); -void sndbuf_dma(struct snd_dbuf *b, int go); -int sndbuf_dmaptr(struct snd_dbuf *b); -void sndbuf_dmabounce(struct snd_dbuf *b); - #ifdef OSSV4_EXPERIMENT void sndbuf_getpeaks(struct snd_dbuf *b, int *lp, int *rp); #endif Index: sys/dev/sound/pcm/channel.c =================================================================== --- sys/dev/sound/pcm/channel.c +++ sys/dev/sound/pcm/channel.c @@ -2191,17 +2191,10 @@ int chn_trigger(struct pcm_channel *c, int go) { -#ifdef DEV_ISA - struct snd_dbuf *b = c->bufhard; -#endif struct snddev_info *d = c->parentsnddev; int ret; CHN_LOCKASSERT(c); -#ifdef DEV_ISA - if (SND_DMA(b) && (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD)) - sndbuf_dmabounce(b); -#endif if (!PCMTRIG_COMMON(go)) return (CHANNEL_TRIGGER(c->methods, c->devinfo, go)); Index: sys/modules/sound/driver/Makefile =================================================================== --- sys/modules/sound/driver/Makefile +++ sys/modules/sound/driver/Makefile @@ -6,9 +6,9 @@ # Modules that include binary-only blobs of microcode should be selectable by # MK_SOURCELESS_UCODE option (see below). -SUBDIR= ad1816 als4000 atiixp cs4281 ${_csa} emu10k1 emu10kx -SUBDIR+= envy24 envy24ht es137x ess fm801 hda hdspe ich -SUBDIR+= ${_maestro3} neomagic sb16 sb8 sbc solo spicds t4dwave via8233 +SUBDIR= als4000 atiixp cs4281 ${_csa} emu10k1 emu10kx +SUBDIR+= envy24 envy24ht es137x fm801 hda hdspe ich +SUBDIR+= ${_maestro3} neomagic solo spicds t4dwave via8233 SUBDIR+= via82c686 vibes driver uaudio .if ${MK_SOURCELESS_UCODE} != "no" @@ -17,7 +17,7 @@ .endif .if ${MACHINE_CPUARCH} == "i386" || ${MACHINE_CPUARCH} == "amd64" -SUBDIR+= cmi mss +SUBDIR+= cmi .endif .if ${MACHINE_CPUARCH} == "powerpc" Index: sys/modules/sound/driver/ad1816/Makefile =================================================================== --- sys/modules/sound/driver/ad1816/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# $FreeBSD$ - -.PATH: ${SRCTOP}/sys/dev/sound/isa - -KMOD= snd_ad1816 -SRCS= device_if.h bus_if.h isa_if.h pci_if.h -SRCS+= ad1816.c - -.include Index: sys/modules/sound/driver/ess/Makefile =================================================================== --- sys/modules/sound/driver/ess/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# $FreeBSD$ - -.PATH: ${SRCTOP}/sys/dev/sound/isa - -KMOD= snd_ess -SRCS= device_if.h bus_if.h isa_if.h pci_if.h -SRCS+= ess.c - -.include Index: sys/modules/sound/driver/mss/Makefile =================================================================== --- sys/modules/sound/driver/mss/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# $FreeBSD$ - -.PATH: ${SRCTOP}/sys/dev/sound/isa - -KMOD= snd_mss -SRCS= device_if.h bus_if.h isa_if.h pci_if.h -SRCS+= mss.c gusc.c - -.include Index: sys/modules/sound/driver/sb16/Makefile =================================================================== --- sys/modules/sound/driver/sb16/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# $FreeBSD$ - -.PATH: ${SRCTOP}/sys/dev/sound/isa - -KMOD= snd_sb16 -SRCS= device_if.h bus_if.h isa_if.h pci_if.h -SRCS+= sb16.c - -.include Index: sys/modules/sound/driver/sb8/Makefile =================================================================== --- sys/modules/sound/driver/sb8/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# $FreeBSD$ - -.PATH: ${SRCTOP}/sys/dev/sound/isa - -KMOD= snd_sb8 -SRCS= device_if.h bus_if.h isa_if.h pci_if.h -SRCS+= sb8.c - -.include Index: sys/modules/sound/driver/sbc/Makefile =================================================================== --- sys/modules/sound/driver/sbc/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# $FreeBSD$ - -.PATH: ${SRCTOP}/sys/dev/sound/isa - -KMOD= snd_sbc -SRCS= device_if.h bus_if.h isa_if.h pci_if.h -SRCS+= sbc.c - -EXPORT_SYMS= YES - -.include Index: sys/modules/sound/sound/Makefile =================================================================== --- sys/modules/sound/sound/Makefile +++ sys/modules/sound/sound/Makefile @@ -40,18 +40,6 @@ # sound.ko is always built without isadma support. opt_isa.h: :> ${.TARGET} -.else -.if !defined(KERNBUILDDIR) -SRCS+= sndbuf_dma.c - -opt_isa.h: - echo "#define DEV_ISA 1" > ${.TARGET} -.else -DEV_ISA!= sed -n '/DEV_ISA/p' ${KERNBUILDDIR}/opt_isa.h -.if !empty(DEV_ISA) -SRCS+= sndbuf_dma.c -.endif -.endif .endif .include