1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-15 10:17:20 +00:00

Pre 3.0 branch cleanup sos#2: sound

Superceded by the snd driver...
This commit is contained in:
Søren Schmidt 1998-12-27 14:21:37 +00:00
parent 45dfc9d01f
commit 50bac46f45
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=42086
88 changed files with 10 additions and 37504 deletions

View File

@ -2,7 +2,7 @@
# LINT -- config file for checking all the sources, tries to pull in
# as much of the source tree as it can.
#
# $Id: LINT,v 1.517 1998/12/27 13:40:55 phk Exp $
# $Id: LINT,v 1.518 1998/12/27 13:55:47 sos Exp $
#
# NB: You probably don't want to try running a kernel built from this
# file. Instead, you should start from GENERIC, and add options from
@ -1142,28 +1142,6 @@ device en0
device en1
options NATM #native ATM
#
# Audio drivers: `snd', `sb', `pas', `gus', `pca'
#
# snd: Voxware sound support code
# sb: SoundBlaster PCM - SoundBlaster, SB Pro, SB16, ProAudioSpectrum
# sbxvi: SoundBlaster 16
# sbmidi: SoundBlaster 16 MIDI interface
# pas: ProAudioSpectrum PCM and MIDI
# gus: Gravis Ultrasound - Ultrasound, Ultrasound 16, Ultrasound MAX
# gusxvi: Gravis Ultrasound 16-bit PCM (do not use)
# mss: Microsoft Sound System
# css: Crystal Sound System (CSS 423x PnP)
# sscape: Ensoniq Soundscape MIDI interface
# sscape_mss: Ensoniq Soundscape PCM (requires sscape)
# opl: Yamaha OPL-2 and OPL-3 FM - SB, SB Pro, SB 16, ProAudioSpectrum
# uart: stand-alone 6850 UART for MIDI
# mpu: Roland MPU-401 stand-alone card
#
# Beware! The addresses specified below are also hard-coded in
# i386/isa/sound/sound_config.h. If you change the values here, you
# must also change the values in the include file.
#
# pcm: PCM audio through various sound cards.
#
# This is the work in progress from Luigi Rizzo. This has support for
@ -1181,48 +1159,8 @@ options NATM #native ATM
# This driver will use the new PnP code if it's available.
#
# pca: PCM audio through your PC speaker
#
# If you have a GUS-MAX card and want to use the CS4231 codec on the
# card the drqs for the gus max must be 8 bit (1, 2, or 3).
#
# If you would like to use the full duplex option on the gus, then define
# flags to be the ``read dma channel''.
#
# options BROKEN_BUS_CLOCK #PAS-16 isn't working and OPTI chipset
# options SYMPHONY_PAS #PAS-16 isn't working and SYMPHONY chipset
# options EXCLUDE_SBPRO #PAS-16
# options SBC_IRQ=5 #PAS-16. Must match irq on sb0 line.
# PAS16: The order of the pas0/sb0/opl0 is important since the
# sb emulation is enabled in the pas-16 attach.
#
# To overide the GUS defaults use:
# options GUS_DMA2
# options GUS_DMA
# options GUS_IRQ
#
# The i386/isa/sound/sound.doc has more information.
# Controls all "VOXWARE" driver sound devices. See Luigi's driver
# below for an alternate which may work better for some cards.
#
controller snd0
device pas0 at isa? port 0x388 irq 10 drq 6
device sb0 at isa? port 0x220 irq 5 drq 1
device sbxvi0 at isa? drq 5
device sbmidi0 at isa? port 0x330
device awe0 at isa? port 0x620
device gus0 at isa? port 0x220 irq 12 drq 1
#device gus0 at isa? port 0x220 irq 12 drq 1 flags 0x3
device mss0 at isa? port 0x530 irq 10 drq 1
device css0 at isa? port 0x534 irq 5 drq 1 flags 0x08
device sscape0 at isa? port 0x330 irq 9 drq 0
device trix0 at isa? port 0x330 irq 6 drq 0
device sscape_mss0 at isa? port 0x534 irq 5 drq 1
device opl0 at isa? port 0x388
device mpu0 at isa? port 0x330 irq 6 drq 0
device uart0 at isa? port 0x330 irq 5
# Luigi's snd code (use INSTEAD of snd0 and all VOXWARE drivers!).
# Luigi's snd code.
# You may also wish to enable the pnp controller with this, for pnp
# sound cards.
#

View File

@ -1,7 +1,7 @@
# This file tells config what files go into building a kernel,
# files marked standard are always included.
#
# $Id: files.i386,v 1.212 1998/12/27 13:40:56 phk Exp $
# $Id: files.i386,v 1.213 1998/12/27 13:55:48 sos Exp $
#
# The long compile-with and dependency lines are required because of
# limitations in config: backslash-newline doesn't work in strings, and
@ -165,67 +165,6 @@ i386/isa/snd/dmabuf.c optional pcm device-driver
i386/isa/snd/ad1848.c optional pcm device-driver
i386/isa/snd/sb_dsp.c optional pcm device-driver
i386/isa/snd/clones.c optional pcm device-driver
i386/isa/sound/dev_table.c optional snd device-driver
i386/isa/sound/soundcard.c optional snd device-driver
i386/isa/sound/sound_switch.c optional snd device-driver
i386/isa/sound/audio.c optional snd device-driver
i386/isa/sound/dmabuf.c optional snd device-driver
i386/isa/sound/sys_timer.c optional snd device-driver
i386/isa/sound/sequencer.c optional snd device-driver
i386/isa/sound/patmgr.c optional snd device-driver
i386/isa/sound/adlib_card.c optional opl device-driver
i386/isa/sound/opl3.c optional opl device-driver
i386/isa/sound/gus_card.c optional gus device-driver
i386/isa/sound/gus_midi.c optional gus device-driver
i386/isa/sound/gus_vol.c optional gus device-driver
i386/isa/sound/gus_wave.c optional gus device-driver
i386/isa/sound/ics2101.c optional gus device-driver
i386/isa/sound/sound_timer.c optional gus device-driver
i386/isa/sound/sound_timer.c optional css device-driver
i386/isa/sound/sound_timer.c optional mss device-driver
i386/isa/sound/midi_synth.c optional gus device-driver
i386/isa/sound/midibuf.c optional gus device-driver
i386/isa/sound/ad1848.c optional gusxvi device-driver
i386/isa/sound/ad1848.c optional gus device-driver
i386/isa/sound/ad1848.c optional mss device-driver
i386/isa/sound/ad1848.c optional css device-driver
i386/isa/sound/sound_timer.c optional mss device-driver
i386/isa/sound/midi_synth.c optional mss device-driver
i386/isa/sound/midibuf.c optional mss device-driver
i386/isa/sound/mpu401.c optional mpu device-driver
i386/isa/sound/midi_synth.c optional mpu device-driver
i386/isa/sound/midibuf.c optional mpu device-driver
i386/isa/sound/pas2_card.c optional pas device-driver
i386/isa/sound/pas2_midi.c optional pas device-driver
i386/isa/sound/pas2_mixer.c optional pas device-driver
i386/isa/sound/pas2_pcm.c optional pas device-driver
i386/isa/sound/midi_synth.c optional pas device-driver
i386/isa/sound/midibuf.c optional pas device-driver
i386/isa/sound/sb_card.c optional sb device-driver
i386/isa/sound/sb_dsp.c optional sb device-driver
i386/isa/sound/sb_midi.c optional sb device-driver
i386/isa/sound/sb_mixer.c optional sb device-driver
i386/isa/sound/midi_synth.c optional sb device-driver
i386/isa/sound/midibuf.c optional sb device-driver
i386/isa/sound/sb16_dsp.c optional sbxvi device-driver
i386/isa/sound/sb16_midi.c optional sbmidi device-driver
i386/isa/sound/uart6850.c optional uart device-driver
i386/isa/sound/midi_synth.c optional uart device-driver
i386/isa/sound/midi_synth.c optional css device-driver
i386/isa/sound/midibuf.c optional uart device-driver
i386/isa/sound/midibuf.c optional css device-driver
i386/isa/sound/trix.c optional trix device-driver
i386/isa/sound/adlib_card.c optional trix device-driver
i386/isa/sound/opl3.c optional trix device-driver
i386/isa/sound/ad1848.c optional trix device-driver
i386/isa/sound/sound_timer.c optional trix device-driver
i386/isa/sound/sscape.c optional sscape device-driver
i386/isa/sound/ad1848.c optional sscape device-driver
i386/isa/sound/sound_timer.c optional sscape device-driver
i386/isa/sound/mpu401.c optional sscape device-driver
i386/isa/sound/midi_synth.c optional sscape device-driver
i386/isa/sound/midibuf.c optional sscape device-driver
i386/isa/sound/cs4232.c optional css device-driver
i386/isa/spigot.c optional spigot device-driver
i386/isa/spkr.c optional speaker device-driver
i386/isa/stallion.c optional stl device-driver
@ -309,5 +248,4 @@ gnu/i386/fpemul/wm_shrx.s optional gpl_math_emulate
gnu/i386/fpemul/wm_sqrt.s optional gpl_math_emulate
gnu/i386/isa/dgb.c optional dgb device-driver
gnu/i386/isa/dgm.c optional dgm device-driver
gnu/i386/isa/sound/awe_wave.c optional awe device-driver
pci/ide_pci.c optional wd device-driver

View File

@ -1,4 +1,4 @@
# $Id: options.i386,v 1.96 1998/12/19 23:07:51 msmith Exp $
# $Id: options.i386,v 1.97 1998/12/27 13:36:44 phk Exp $
DISABLE_PSE
IDE_DELAY
@ -100,10 +100,5 @@ FDC_DEBUG opt_fdc.h
FDC_PRINT_BOGUS_CHIPTYPE opt_fdc.h
FDC_YE opt_fdc.h
# voxware options
GUS_DMA2 opt_sound.h
GUS_DMA opt_sound.h
GUS_IRQ opt_sound.h
# Video spigot
SPIGOT_UNSECURE opt_spigot.h

View File

@ -2,7 +2,7 @@
# LINT -- config file for checking all the sources, tries to pull in
# as much of the source tree as it can.
#
# $Id: LINT,v 1.517 1998/12/27 13:40:55 phk Exp $
# $Id: LINT,v 1.518 1998/12/27 13:55:47 sos Exp $
#
# NB: You probably don't want to try running a kernel built from this
# file. Instead, you should start from GENERIC, and add options from
@ -1142,28 +1142,6 @@ device en0
device en1
options NATM #native ATM
#
# Audio drivers: `snd', `sb', `pas', `gus', `pca'
#
# snd: Voxware sound support code
# sb: SoundBlaster PCM - SoundBlaster, SB Pro, SB16, ProAudioSpectrum
# sbxvi: SoundBlaster 16
# sbmidi: SoundBlaster 16 MIDI interface
# pas: ProAudioSpectrum PCM and MIDI
# gus: Gravis Ultrasound - Ultrasound, Ultrasound 16, Ultrasound MAX
# gusxvi: Gravis Ultrasound 16-bit PCM (do not use)
# mss: Microsoft Sound System
# css: Crystal Sound System (CSS 423x PnP)
# sscape: Ensoniq Soundscape MIDI interface
# sscape_mss: Ensoniq Soundscape PCM (requires sscape)
# opl: Yamaha OPL-2 and OPL-3 FM - SB, SB Pro, SB 16, ProAudioSpectrum
# uart: stand-alone 6850 UART for MIDI
# mpu: Roland MPU-401 stand-alone card
#
# Beware! The addresses specified below are also hard-coded in
# i386/isa/sound/sound_config.h. If you change the values here, you
# must also change the values in the include file.
#
# pcm: PCM audio through various sound cards.
#
# This is the work in progress from Luigi Rizzo. This has support for
@ -1181,48 +1159,8 @@ options NATM #native ATM
# This driver will use the new PnP code if it's available.
#
# pca: PCM audio through your PC speaker
#
# If you have a GUS-MAX card and want to use the CS4231 codec on the
# card the drqs for the gus max must be 8 bit (1, 2, or 3).
#
# If you would like to use the full duplex option on the gus, then define
# flags to be the ``read dma channel''.
#
# options BROKEN_BUS_CLOCK #PAS-16 isn't working and OPTI chipset
# options SYMPHONY_PAS #PAS-16 isn't working and SYMPHONY chipset
# options EXCLUDE_SBPRO #PAS-16
# options SBC_IRQ=5 #PAS-16. Must match irq on sb0 line.
# PAS16: The order of the pas0/sb0/opl0 is important since the
# sb emulation is enabled in the pas-16 attach.
#
# To overide the GUS defaults use:
# options GUS_DMA2
# options GUS_DMA
# options GUS_IRQ
#
# The i386/isa/sound/sound.doc has more information.
# Controls all "VOXWARE" driver sound devices. See Luigi's driver
# below for an alternate which may work better for some cards.
#
controller snd0
device pas0 at isa? port 0x388 irq 10 drq 6
device sb0 at isa? port 0x220 irq 5 drq 1
device sbxvi0 at isa? drq 5
device sbmidi0 at isa? port 0x330
device awe0 at isa? port 0x620
device gus0 at isa? port 0x220 irq 12 drq 1
#device gus0 at isa? port 0x220 irq 12 drq 1 flags 0x3
device mss0 at isa? port 0x530 irq 10 drq 1
device css0 at isa? port 0x534 irq 5 drq 1 flags 0x08
device sscape0 at isa? port 0x330 irq 9 drq 0
device trix0 at isa? port 0x330 irq 6 drq 0
device sscape_mss0 at isa? port 0x534 irq 5 drq 1
device opl0 at isa? port 0x388
device mpu0 at isa? port 0x330 irq 6 drq 0
device uart0 at isa? port 0x330 irq 5
# Luigi's snd code (use INSTEAD of snd0 and all VOXWARE drivers!).
# Luigi's snd code.
# You may also wish to enable the pnp controller with this, for pnp
# sound cards.
#

View File

@ -2,7 +2,7 @@
# LINT -- config file for checking all the sources, tries to pull in
# as much of the source tree as it can.
#
# $Id: LINT,v 1.517 1998/12/27 13:40:55 phk Exp $
# $Id: LINT,v 1.518 1998/12/27 13:55:47 sos Exp $
#
# NB: You probably don't want to try running a kernel built from this
# file. Instead, you should start from GENERIC, and add options from
@ -1142,28 +1142,6 @@ device en0
device en1
options NATM #native ATM
#
# Audio drivers: `snd', `sb', `pas', `gus', `pca'
#
# snd: Voxware sound support code
# sb: SoundBlaster PCM - SoundBlaster, SB Pro, SB16, ProAudioSpectrum
# sbxvi: SoundBlaster 16
# sbmidi: SoundBlaster 16 MIDI interface
# pas: ProAudioSpectrum PCM and MIDI
# gus: Gravis Ultrasound - Ultrasound, Ultrasound 16, Ultrasound MAX
# gusxvi: Gravis Ultrasound 16-bit PCM (do not use)
# mss: Microsoft Sound System
# css: Crystal Sound System (CSS 423x PnP)
# sscape: Ensoniq Soundscape MIDI interface
# sscape_mss: Ensoniq Soundscape PCM (requires sscape)
# opl: Yamaha OPL-2 and OPL-3 FM - SB, SB Pro, SB 16, ProAudioSpectrum
# uart: stand-alone 6850 UART for MIDI
# mpu: Roland MPU-401 stand-alone card
#
# Beware! The addresses specified below are also hard-coded in
# i386/isa/sound/sound_config.h. If you change the values here, you
# must also change the values in the include file.
#
# pcm: PCM audio through various sound cards.
#
# This is the work in progress from Luigi Rizzo. This has support for
@ -1181,48 +1159,8 @@ options NATM #native ATM
# This driver will use the new PnP code if it's available.
#
# pca: PCM audio through your PC speaker
#
# If you have a GUS-MAX card and want to use the CS4231 codec on the
# card the drqs for the gus max must be 8 bit (1, 2, or 3).
#
# If you would like to use the full duplex option on the gus, then define
# flags to be the ``read dma channel''.
#
# options BROKEN_BUS_CLOCK #PAS-16 isn't working and OPTI chipset
# options SYMPHONY_PAS #PAS-16 isn't working and SYMPHONY chipset
# options EXCLUDE_SBPRO #PAS-16
# options SBC_IRQ=5 #PAS-16. Must match irq on sb0 line.
# PAS16: The order of the pas0/sb0/opl0 is important since the
# sb emulation is enabled in the pas-16 attach.
#
# To overide the GUS defaults use:
# options GUS_DMA2
# options GUS_DMA
# options GUS_IRQ
#
# The i386/isa/sound/sound.doc has more information.
# Controls all "VOXWARE" driver sound devices. See Luigi's driver
# below for an alternate which may work better for some cards.
#
controller snd0
device pas0 at isa? port 0x388 irq 10 drq 6
device sb0 at isa? port 0x220 irq 5 drq 1
device sbxvi0 at isa? drq 5
device sbmidi0 at isa? port 0x330
device awe0 at isa? port 0x620
device gus0 at isa? port 0x220 irq 12 drq 1
#device gus0 at isa? port 0x220 irq 12 drq 1 flags 0x3
device mss0 at isa? port 0x530 irq 10 drq 1
device css0 at isa? port 0x534 irq 5 drq 1 flags 0x08
device sscape0 at isa? port 0x330 irq 9 drq 0
device trix0 at isa? port 0x330 irq 6 drq 0
device sscape_mss0 at isa? port 0x534 irq 5 drq 1
device opl0 at isa? port 0x388
device mpu0 at isa? port 0x330 irq 6 drq 0
device uart0 at isa? port 0x330 irq 5
# Luigi's snd code (use INSTEAD of snd0 and all VOXWARE drivers!).
# Luigi's snd code.
# You may also wish to enable the pnp controller with this, for pnp
# sound cards.
#

View File

@ -1,7 +1,7 @@
# This file tells config what files go into building a kernel,
# files marked standard are always included.
#
# $Id: files.i386,v 1.212 1998/12/27 13:40:56 phk Exp $
# $Id: files.i386,v 1.213 1998/12/27 13:55:48 sos Exp $
#
# The long compile-with and dependency lines are required because of
# limitations in config: backslash-newline doesn't work in strings, and
@ -165,67 +165,6 @@ i386/isa/snd/dmabuf.c optional pcm device-driver
i386/isa/snd/ad1848.c optional pcm device-driver
i386/isa/snd/sb_dsp.c optional pcm device-driver
i386/isa/snd/clones.c optional pcm device-driver
i386/isa/sound/dev_table.c optional snd device-driver
i386/isa/sound/soundcard.c optional snd device-driver
i386/isa/sound/sound_switch.c optional snd device-driver
i386/isa/sound/audio.c optional snd device-driver
i386/isa/sound/dmabuf.c optional snd device-driver
i386/isa/sound/sys_timer.c optional snd device-driver
i386/isa/sound/sequencer.c optional snd device-driver
i386/isa/sound/patmgr.c optional snd device-driver
i386/isa/sound/adlib_card.c optional opl device-driver
i386/isa/sound/opl3.c optional opl device-driver
i386/isa/sound/gus_card.c optional gus device-driver
i386/isa/sound/gus_midi.c optional gus device-driver
i386/isa/sound/gus_vol.c optional gus device-driver
i386/isa/sound/gus_wave.c optional gus device-driver
i386/isa/sound/ics2101.c optional gus device-driver
i386/isa/sound/sound_timer.c optional gus device-driver
i386/isa/sound/sound_timer.c optional css device-driver
i386/isa/sound/sound_timer.c optional mss device-driver
i386/isa/sound/midi_synth.c optional gus device-driver
i386/isa/sound/midibuf.c optional gus device-driver
i386/isa/sound/ad1848.c optional gusxvi device-driver
i386/isa/sound/ad1848.c optional gus device-driver
i386/isa/sound/ad1848.c optional mss device-driver
i386/isa/sound/ad1848.c optional css device-driver
i386/isa/sound/sound_timer.c optional mss device-driver
i386/isa/sound/midi_synth.c optional mss device-driver
i386/isa/sound/midibuf.c optional mss device-driver
i386/isa/sound/mpu401.c optional mpu device-driver
i386/isa/sound/midi_synth.c optional mpu device-driver
i386/isa/sound/midibuf.c optional mpu device-driver
i386/isa/sound/pas2_card.c optional pas device-driver
i386/isa/sound/pas2_midi.c optional pas device-driver
i386/isa/sound/pas2_mixer.c optional pas device-driver
i386/isa/sound/pas2_pcm.c optional pas device-driver
i386/isa/sound/midi_synth.c optional pas device-driver
i386/isa/sound/midibuf.c optional pas device-driver
i386/isa/sound/sb_card.c optional sb device-driver
i386/isa/sound/sb_dsp.c optional sb device-driver
i386/isa/sound/sb_midi.c optional sb device-driver
i386/isa/sound/sb_mixer.c optional sb device-driver
i386/isa/sound/midi_synth.c optional sb device-driver
i386/isa/sound/midibuf.c optional sb device-driver
i386/isa/sound/sb16_dsp.c optional sbxvi device-driver
i386/isa/sound/sb16_midi.c optional sbmidi device-driver
i386/isa/sound/uart6850.c optional uart device-driver
i386/isa/sound/midi_synth.c optional uart device-driver
i386/isa/sound/midi_synth.c optional css device-driver
i386/isa/sound/midibuf.c optional uart device-driver
i386/isa/sound/midibuf.c optional css device-driver
i386/isa/sound/trix.c optional trix device-driver
i386/isa/sound/adlib_card.c optional trix device-driver
i386/isa/sound/opl3.c optional trix device-driver
i386/isa/sound/ad1848.c optional trix device-driver
i386/isa/sound/sound_timer.c optional trix device-driver
i386/isa/sound/sscape.c optional sscape device-driver
i386/isa/sound/ad1848.c optional sscape device-driver
i386/isa/sound/sound_timer.c optional sscape device-driver
i386/isa/sound/mpu401.c optional sscape device-driver
i386/isa/sound/midi_synth.c optional sscape device-driver
i386/isa/sound/midibuf.c optional sscape device-driver
i386/isa/sound/cs4232.c optional css device-driver
i386/isa/spigot.c optional spigot device-driver
i386/isa/spkr.c optional speaker device-driver
i386/isa/stallion.c optional stl device-driver
@ -309,5 +248,4 @@ gnu/i386/fpemul/wm_shrx.s optional gpl_math_emulate
gnu/i386/fpemul/wm_sqrt.s optional gpl_math_emulate
gnu/i386/isa/dgb.c optional dgb device-driver
gnu/i386/isa/dgm.c optional dgm device-driver
gnu/i386/isa/sound/awe_wave.c optional awe device-driver
pci/ide_pci.c optional wd device-driver

View File

@ -1,4 +1,4 @@
# $Id: options.i386,v 1.96 1998/12/19 23:07:51 msmith Exp $
# $Id: options.i386,v 1.97 1998/12/27 13:36:44 phk Exp $
DISABLE_PSE
IDE_DELAY
@ -100,10 +100,5 @@ FDC_DEBUG opt_fdc.h
FDC_PRINT_BOGUS_CHIPTYPE opt_fdc.h
FDC_YE opt_fdc.h
# voxware options
GUS_DMA2 opt_sound.h
GUS_DMA opt_sound.h
GUS_IRQ opt_sound.h
# Video spigot
SPIGOT_UNSECURE opt_spigot.h

View File

@ -1,121 +0,0 @@
#ifndef _ULTRASOUND_H_
#define _ULTRASOUND_H_
/*
* Copyright by Hannu Savolainen 1993
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
/*
* ultrasound.h - Macros for programming the Gravis Ultrasound
* These macros are extremely device dependent
* and not portable.
*/
/*
* Private events for Gravis Ultrasound (GUS)
*
* Format:
* byte 0 - SEQ_PRIVATE (0xfe)
* byte 1 - Synthesizer device number (0-N)
* byte 2 - Command (see below)
* byte 3 - Voice number (0-31)
* bytes 4 and 5 - parameter P1 (unsigned short)
* bytes 6 and 7 - parameter P2 (unsigned short)
*
* Commands:
* Each command affects one voice defined in byte 3.
* Unused parameters (P1 and/or P2 *MUST* be initialized to zero).
* _GUS_NUMVOICES - Sets max. number of concurrent voices (P1=14-31, default 16)
* _GUS_VOICESAMPLE- ************ OBSOLETE *************
* _GUS_VOICEON - Starts voice (P1=voice mode)
* _GUS_VOICEOFF - Stops voice (no parameters)
* _GUS_VOICEFADE - Stops the voice smoothly.
* _GUS_VOICEMODE - Alters the voice mode, don't start or stop voice (P1=voice mode)
* _GUS_VOICEBALA - Sets voice balance (P1, 0=left, 7=middle and 15=right, default 7)
* _GUS_VOICEFREQ - Sets voice (sample) playback frequency (P1=Hz)
* _GUS_VOICEVOL - Sets voice volume (P1=volume, 0xfff=max, 0xeff=half, 0x000=off)
* _GUS_VOICEVOL2 - Sets voice volume (P1=volume, 0xfff=max, 0xeff=half, 0x000=off)
* (Like GUS_VOICEVOL but doesn't change the hw
* volume. It just updates volume in the voice table).
*
* _GUS_RAMPRANGE - Sets limits for volume ramping (P1=low volume, P2=high volume)
* _GUS_RAMPRATE - Sets the speed for volume ramping (P1=scale, P2=rate)
* _GUS_RAMPMODE - Sets the volume ramping mode (P1=ramping mode)
* _GUS_RAMPON - Starts volume ramping (no parameters)
* _GUS_RAMPOFF - Stops volume ramping (no parameters)
* _GUS_VOLUME_SCALE - Changes the volume calculation constants
* for all voices.
*/
#define _GUS_NUMVOICES 0x00
#define _GUS_VOICESAMPLE 0x01 /* OBSOLETE */
#define _GUS_VOICEON 0x02
#define _GUS_VOICEOFF 0x03
#define _GUS_VOICEMODE 0x04
#define _GUS_VOICEBALA 0x05
#define _GUS_VOICEFREQ 0x06
#define _GUS_VOICEVOL 0x07
#define _GUS_RAMPRANGE 0x08
#define _GUS_RAMPRATE 0x09
#define _GUS_RAMPMODE 0x0a
#define _GUS_RAMPON 0x0b
#define _GUS_RAMPOFF 0x0c
#define _GUS_VOICEFADE 0x0d
#define _GUS_VOLUME_SCALE 0x0e
#define _GUS_VOICEVOL2 0x0f
#define _GUS_VOICE_POS 0x10
/*
* GUS API macros
*/
#define _GUS_CMD(chn, voice, cmd, p1, p2) \
{_SEQ_NEEDBUF(8); _seqbuf[_seqbufptr] = SEQ_PRIVATE;\
_seqbuf[_seqbufptr+1] = (chn); _seqbuf[_seqbufptr+2] = cmd;\
_seqbuf[_seqbufptr+3] = voice;\
*(unsigned short*)&_seqbuf[_seqbufptr+4] = p1;\
*(unsigned short*)&_seqbuf[_seqbufptr+6] = p2;\
_SEQ_ADVBUF(8);}
#define GUS_NUMVOICES(chn, p1) _GUS_CMD(chn, 0, _GUS_NUMVOICES, (p1), 0)
#define GUS_VOICESAMPLE(chn, voice, p1) _GUS_CMD(chn, voice, _GUS_VOICESAMPLE, (p1), 0) /* OBSOLETE */
#define GUS_VOICEON(chn, voice, p1) _GUS_CMD(chn, voice, _GUS_VOICEON, (p1), 0)
#define GUS_VOICEOFF(chn, voice) _GUS_CMD(chn, voice, _GUS_VOICEOFF, 0, 0)
#define GUS_VOICEFADE(chn, voice) _GUS_CMD(chn, voice, _GUS_VOICEFADE, 0, 0)
#define GUS_VOICEMODE(chn, voice, p1) _GUS_CMD(chn, voice, _GUS_VOICEMODE, (p1), 0)
#define GUS_VOICEBALA(chn, voice, p1) _GUS_CMD(chn, voice, _GUS_VOICEBALA, (p1), 0)
#define GUS_VOICEFREQ(chn, voice, p) _GUS_CMD(chn, voice, _GUS_VOICEFREQ, \
(p) & 0xffff, ((p) >> 16) & 0xffff)
#define GUS_VOICEVOL(chn, voice, p1) _GUS_CMD(chn, voice, _GUS_VOICEVOL, (p1), 0)
#define GUS_VOICEVOL2(chn, voice, p1) _GUS_CMD(chn, voice, _GUS_VOICEVOL2, (p1), 0)
#define GUS_RAMPRANGE(chn, voice, low, high) _GUS_CMD(chn, voice, _GUS_RAMPRANGE, (low), (high))
#define GUS_RAMPRATE(chn, voice, p1, p2) _GUS_CMD(chn, voice, _GUS_RAMPRATE, (p1), (p2))
#define GUS_RAMPMODE(chn, voice, p1) _GUS_CMD(chn, voice, _GUS_RAMPMODE, (p1), 0)
#define GUS_RAMPON(chn, voice, p1) _GUS_CMD(chn, voice, _GUS_RAMPON, (p1), 0)
#define GUS_RAMPOFF(chn, voice) _GUS_CMD(chn, voice, _GUS_RAMPOFF, 0, 0)
#define GUS_VOLUME_SCALE(chn, voice, p1, p2) _GUS_CMD(chn, voice, _GUS_VOLUME_SCALE, (p1), (p2))
#define GUS_VOICE_POS(chn, voice, p) _GUS_CMD(chn, voice, _GUS_VOICE_POS, \
(p) & 0xffff, ((p) >> 16) & 0xffff)
#endif

View File

@ -1,200 +0,0 @@
Changelog for version 3.5-alpha7
--------------------------------
Since 3.5-alpha6
- Changed all #ifndef EXCLUDE_xx stuff to #ifdef CONFIG_xx. Modified
configure to handle this.
- Removed initialization messages from the
modularized version. They can be enabled by using init_trace=1 in
the insmod command line (insmod sound init_trace=1).
- More AIX stuff.
- Added support for syncronizing dsp/audio devices with /dev/sequencer.
- mmap() support for dsp/audio devices.
Since 3.5-alpha5
- AIX port.
- Changed some xxx_PATCH macros in soundcard.h to work with
big endian machines.
Since 3.5-alpha4
- Removed the 'setfx' stuff from the version distributed with kernel
sources.
Since 3.5-alpha3
- Moved stuff from the 'setfx' program to the AudioTriX Pro driver.
Since 3.5-alpha2
- Modifications to makefile and configure.c. Unnecessary sources
are no longer compiled. Newly created local.h is also copied to
/etc/soundconf. "make oldconfig" reads /etc/soundconf and produces
new local.h which is compatible with current version of the driver.
- Some fixes to the SB16 support.
- Fixed random protection fault in gus_wave.c
Since 3.5-alpha1
- Modified to work with Linux-1.3.33 and leater
- Some minor changes
Since 3.0.2
- Support for CS4232 based PnP cards (AcerMagic S23 etc).
- Full duplex support for some CS4231, CS4232 and AD1845 based cards
(GUA MAX, AudioTrix Pro, AcerMagic S23 and many MAD16/Mozart cards
having a codec mentioned above).
- Almost fully rewritten loadable modules support.
- Fixed some bugs.
- Huge amount of testing (more testing is still required).
- mmap() support (works with some cards). Requires much more testing.
- Sample/patch/program loading for TB Maui/Tropez. No initialization
since TB doesn't allow me to release that code.
- Using CS4231 compatible codecs as timer for /dev/music.
Since 3.0.1
- Added allocation of I/O ports, DMA channels and interrupts
to the initialization code. This may break modules support since
the driver may not free some resources on unload. Should be fixed soon.
Since 3.0
- Some important bug fixes.
- select() for /dev/dsp and /dev/audio (Linux only).
(To use select() with read, you have to call read() to start
the recording. Calling write() kills recording immediately so
use select() carefully when you are writing a half duplex app.
Full duplex mode is not implemented yet.) Select works also with
/dev/sequencer and /dev/music. Maybe with /dev/midi## too.
Since 3.0-beta2
- Minor fixes.
- Added Readme.cards
Since 3.0-beta1
- Minor fixes to the modules support.
- Eliminated call to sb_free_irq() in ad1848.c
- Rewritten MAD16&Mozart support (not tested with MAD16 Pro).
- Fix to DMA initialization of PSS cards.
- Some fixes to ad1848/cs42xx mixer support (GUS MAX, MSS, etc.)
- Fixed some bugs in the PSS driver which caused I/O errors with
the MSS mode (/dev/dsp).
Since 3.0-950506
- Recording with GUS MAX fixed. It works when the driver is configured
to use two DMA channels with GUS MAX (16 bit ones recommended).
Since 3.0-94xxxx
- Too many changes
Since 3.0-940818
- Fixes for Linux 1.1.4x.
- Disables Disney Sound System with SG NX Pro 16 (less noise).
Since 2.90-2
- Fixes to soundcard.h
- Non blocking mode to /dev/sequencer
- Experimental detection code for Ensoniq Soundscape.
Since 2.90
- Minor and major bug fixes
Since pre-3.0-940712
- GUS MAX support
- Partially working MSS/WSS support (could work with some cards).
- Hardware u-Law and A-Law support with AD1848/CS4248 and CS4231 codecs
(GUS MAX, GUS16, WSS etc). Hardware ADPCM is possible with GUS16 and
GUS MAX, but it doesn't work yet.
Since pre-3.0-940426
- AD1848/CS4248/CS4231 codec support (MSS, GUS MAX, Aztec, Orchid etc).
This codec chip is used in various soundcards. This version is developed
for the 16 bit daughtercard of GUS. It should work with other cards also
if the following requirements are met:
- The I/O, IRQ and DMA settings are jumper selectable or
the card is initialized by booting DOS before booting Linux (etc.).
- You add the IO, IRQ and DMA settings manually to the local.h.
(Just define GUS16_BASE, GUS16_IRQ and GUS16_DMA). Note that
the base address bust be the base address of the codec chip not the
card itself. For the GUS16 these are the same but most MSS compatible
cards have the codec located at card_base+4.
- Some minor changes
Since 2.5 (******* MAJOR REWRITE ***********)
This version is based on v2.3. I have tried to maintain two versions
together so that this one should have the same features than v2.5.
Something may still be missing. If you notice such things, please let me
know.
The Readme.v30 contains more details.
- /dev/midi## devices.
- /dev/sequencer2
Since 2.5-beta2
- Some fine tuning to the GUS v3.7 mixer code.
- Fixed speed limits for the plain SB (1.0 to 2.0).
Since 2.5-beta
- Fixed OPL-3 detection with SB. Caused problems with PAS16.
- GUS v3.7 mixer support.
Since 2.4
- Mixer support for Sound Galaxy NX Pro (define __SGNXPRO__ on your local.h).
- Fixed truncated sound on /dev/dsp when the device is closed.
- Linear volume mode for GUS
- Pitch bends larger than +/- 2 octaves.
- MIDI recording for SB and SB Pro. (Untested).
- Some other fixes.
- SB16 MIDI and DSP drivers only initialized if SB16 actually installed.
- Implemented better detection for OPL-3. This should be useful if you
have an old SB Pro (the non-OPL-3 one) or a SB 2.0 clone which has a OPL-3.
- SVR4.2 support by Ian Hartas. Initial ALPHA TEST version (untested).
Since 2.3b
- Fixed bug which made it impossible to make long recordings to disk.
Recording was not restarted after a buffer overflow situation.
- Limited mixer support for GUS.
- Numerous improvements to the GUS driver by Andrew Robinson. Including
some click removal etc.
Since 2.3
- Fixed some minor bugs in the SB16 driver.
Since 2.2b
- Full SB16 DSP support. 8/16 bit, mono/stereo
- The SCO and FreeBSD versions should be in sync now. There are some
problems with SB16 and GUS in the freebsd versions.
The DMA buffer allocation of the SCO version has been polished but
there could still be some problems. At least it hogs memory.
The DMA channel
configuration method used in the sco/System is a hack.
- Support for the MPU emulation of the SB16.
- Some big arrays are now allocated boot time. This makes the bss segment
smaller which makes it possible to use the full driver with
NetBSD. These arrays are not allocated if no suitable soundcard is available.
- Fixed a bug in the compute_and_set_volume in gus_wave.c
- Fixed the too fast mono playback problem of SB Pro and PAS16.
Since 2.2
- Stereo recording for SB Pro. Somehow it was missing and nobody
had noticed it earlier.
- Minor polishing.
- Interpreting of boot time arguments (sound=) for Linux.
- Breakup of sb_dsp.c. Parts of the code has been moved to
sb_mixer.c and sb_midi.c
Since 2.1
- Preliminary support for SB16.
- The SB16 mixer is supported in its native mode.
- Digitized voice capability up to 44.1 kHz/8 bit/mono
(16 bit and stereo support coming in the next release).
- Fixed some bugs in the digitized voice driver for PAS16.
- Proper initialization of the SB emulation of latest PAS16 models.
- Significantly improved /dev/dsp and /dev/audio support.
- Now supports half duplex mode. It's now possible to record and
playback without closing and reopening the device.
- It's possible to use smaller buffers than earlier. There is a new
ioctl(fd, SNDCTL_DSP_SUBDIVIDE, &n) where n should be 1, 2 or 4.
This call instructs the driver to use smaller buffers. The default
buffer size (0.5 to 1.0 seconds) is divided by n. Should be called
immediately after opening the device.
Since 2.0
Just cosmetic changes.

View File

@ -1,25 +0,0 @@
/*
* Copyright by Hannu Savolainen 1993
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/

View File

@ -1,86 +0,0 @@
VoxWare v2.90 release notes
--------------------------
This version includes some hidden features which
are described in the file experimental.txt
Some of these features are not enabled by default. Look at
experimental.txt for more info.
I just decided to release this version with some
incompletely implemented features disabled since
there are some new features required by a popular
application. In addition there is also support
for the GUS MAX and the 16 bit sampling option of GUS.
The MSS/WSS support works now. At least with SG NX Pro 16.
********* IMPORTANT *****************************************
Linux 1.0 or later is required to by this driver version.
Don't distribute binaries which use /dev/sequencer and are
compiled with the soundcard.h of this version. They will
not work with version 2.x of the driver.
*************************************************************
You will need the snd-util-2.5.tar.gz and snd-data-0.1.tar.Z
packages to use this driver. They should be in the same
ftp site or BBS from where you got this driver. For
example at nic.funet.fi:pub/OS/Linux/*.
If you are looking for the installation instructions, please
look at linux/Readme.
Compatibility with the earlier versions
---------------------------------------
This version is backward compatible with the version 2.X. All programs
compiled with sys/soundcard.h of v2.X should work without problems.
PROGRAMS COMPILED WITH THE sys/soundcard.h OF THIS VERSION WILL NOT
WORK WITH v2.X DRIVER. BE CAREFUL WHEN DISTRIBUTING BINARIES COMPILED
FOR THIS VERSION.
Contributors
------------
This driver contains code by several contributors. In addition several other
persons have given useful suggestions. The following is a list of major
contributors. (I could have forgotten some names.)
Craig Metz 1/2 of the PAS16 Mixer and PCM support
Rob Hooft Volume computation algorithm for the FM synth.
Mika Liljeberg uLaw encoding and decoding routines
Greg Lee Volume computation algorithm for the GUS and
lot's of valuable suggestions.
Andy Warner ISC port
Jim Lowe FreeBSD port
Anders Baekgaard Bughunting and valuable suggestions.
Joerg Schubert SB16 DSP support.
Andrew Robinson Improvements to the GUS driver
Megens SA MIDI recording for SB and SB Pro.
Mikael Nordqvist Linear volume support for GUS.
Mikael Nordqvist Linear volume support for GUS.
Ian Hartas SVR4.2 port
Markus Aroharju and
Risto Kankkunen Major contributions to the mixer support
of GUS v3.7.
Hunyue Yau Mixer support for SG NX Pro.
Marc Hoffman PSS support.
Regards,
Hannu Savolainen
hannu@voxware.pp.fi
Snail mail: Hannu Savolainen
Hiekkalaiturintie 3 A 8
00980 Helsinki
Finland
FAX: +358 0 341 6272 (answers if I have my machine (mgetty) on).
NOTE! I probably don't answer to Snail mail or FAX messages. Sending answer
to each of them is simply too expensive and time consuming. However I
try to reply every email message I get (within a week). If you don't
get response, please check how your address is written in the message
header. I can't answer if I don't have a valid reply address.

View File

@ -1,165 +0,0 @@
GUSPNP15 8/6//97
ftp://rah.star-gate.com/pub/guspnp.tar.gz
This sound driver is for FreeBSD 3.0-current .
Major enhancement we now support mapping the dma buffer to user
space for write operations only. This features is useful for
games like xquake . So far the mmap features seems to work
with the GUS PnP Pro and with the SB16.
For xquake you will need:
1. a few mods to the linux loadable module so just download it and
replace yours:
cd /sys/i386/
tar -xzf linux_ioctl.tar.gz
cd /usr/src/lkm/linux
make
make install
modunload -i 0 (if you have the linux up and running)
linux
ftp://rah.star-gate.com/linux_ioctl.tar.gz
2. Install the linux lib 2.4 package:
pkg_add linux_lib-2.4.tgz
ftp://ftp.freebsd.org/pub/FreeBSD/packages-current/emulators/linux_lib-2.4.tgz
If you don't have xquake you can get it from:
3. ftp://ftp.freebsd.org/pub/idgames/idstuff/unsup/intel_linux_quake101.tgz
A simple test program mmap_test.c is provided in the sound driver directory.
So copy it to your home directory or favorite place and compile it.
cc -o mmap_test mmap_test.c
record a sample session:
cat /dev/dsp >smpl
now run mmap_test . You will hear a loud pop thats a test program
then the sample stream will loop .
Phew, now back to sound driver land 8)
This is a minor sound driver release for the GUS PnP Pro , GUS MAX,
AudioTrix Pro , SB16 and SB16 PnP. There is also an experimental
AWE sub model.
Included Luigi's clean up work . Tnks!
Randall Hopper's SB16 speed setting fix . Tnks!
Fixed signal handling throught out the sound driver. The problem
first surfaced with the SB16 not generating an interrupt on the
last dma request and SB afficionados quickly pointed out the
bug in the driver. I had to put back the auto dma feature for
xquake :(
NOTE YOU DON'T NEED THE PNP DRIVER FOR THE GUS PNP SINCE THE DRIVER
HAS BUILTIN PNP SUPPORT FOR THE GUS.
My P133 Bios supports PnP. To first figured out what my SB16 PnP
was being configured to I booted win95 and checked out what Win95
ended up with . Alternatively, if you want to you can also down
load Sujal Patel's PnP driver:
ftp://rah.start-gate.com/pub/FreeBSD-ISA_PnP_June8.tar.gz
follow the instructions on how to configure your PnP soundcard or
ISA device.
Lugi also has Sujal's PnP driver .
---
http://www.iet.unipi.it/~luigi/pnp.c
http://www.iet.unipi.it/~luigi/pnp.h
the two main files. Follow Sujal Patel's instructions
for installing pnp support.
http://www.iet.unipi.it/~luigi/pnpinfo.tgz
---
This is my kernel configuration for my SB16 PnP:
controller snd0
device sb0 at isa? port 0x220 irq 10 conflicts drq 3
device sbxvi0 at isa? port? irq? drq 5 conflicts
device opl0 at isa? port 0x388 conflicts
device sbmidi0 at isa? port 0x300 irq? conflicts
----
The difference between a GUS PnP and a GUS PnP PRO is that the Pro
comes with 512kb. I went out an got a 1mb 60ns 30pin simm and installed
it on my GUS PnP. I own a GUS PnP and a GUS PnP PRO.
To unpack:
cd /
mv /sys/i386/isa/sound /sys/i386/isa/sound.old
cd /sys/i386/isa/
tar -xzf guspnp15.tar.gz
cd /sys/i386/conf
Edit the kernel config file in /sys/i386/conf
IF YOU HAVE A GUS MAX or GUS add the option NOGUSPNP to the config file
OPTIONS NOGUSPNP
THEN follow the instructions for NONPNP CONFIGURATION
PNP CONFIGURATION
To configure your guspnp PRO if you have a motherboard which supports
PnP:
controller snd0
device gus0 at isa?
NONPNP CONFIGURATION
To configure your guspnp PRO if your motherboard does NOT support
PnP:
device gus0 at isa? port 0x220 irq 11 drq 1 flags 0x3
the gus pnp is fully software configurable and the above configuration
is setup for full duplex audio. The dma channel settings are:
drq 1 --- DMA channel for playback
flags 0x3 --- DMAN channel for recording
In the event that you have to configure a GUS PnP manually or a GUS MAX:
Available IRQs for the GUS are:
3, 5, 7, 9, 11, 12, 15
Available DMA channels for the GUS are:
1, 3, 5, 6, 7
config <kernel-file>
cd /sys/compile/<kernel-file>
make
make install
THERE IS NO NEED TO BOOT TO DOS TO CONFIGURE YOUR GUS PNP.
THE DRIVER HAS BUILTIN SUPPORT FOR PNP WHICH I GOT
FROM THE GRAVIS DRIVER DEVELOPMENT KIT
Many thanks to Brian Litzinger <brian@MediaCity.com> for
porting the sound driver 3.5 to 2.2-current. Well, thats a while
ago hence the reference to 2.2.
Have fun,
Amancio

View File

@ -1,248 +0,0 @@
VoxWare v3.5-alpha5 release notes
---------------------------------
IMPORTANT! This version of the driver is compatible only with Linux versions
1.3.33 and later. It may work with earlier ones as a loadable
module but...
Also this is an ALPHA test version which has not been tested
with all cards. At least AEDSP16 support will not work. PAS16
and PSS supports have not been tested. /dev/dsp and /dev/audio
playback with standard GUS sounds scrambled. 16 bit mode of
SB16 doesn't work.
Please read the SOUND-HOWTO (available from sunsite.unc.edu and other Linux ftp
sites). It contains much more information than this file.
*****************************************************************
* NEW! VoxWare home page is http://personal.eunet.fi/pp/voxware *
* The file Readme.cards contains card specific instructions *
* about configuring various cards. *
*****************************************************************
There are some programming information (little bit old) in the
Hacker's Guide
(ftp://nic.funet.fi/pub/OS/Linux/ALPHA/sound/snd-sdk-doc-0.1.ps.gz).
Believe me: The file is really there. The directory is just hidden and
you have to cd into it before the file is visible. Note: This directory
was accidently removed some time ago but it's now back.
I have got many patches from various persons during last year. Some of
them are still on my mailbox and they should be included in versions
after v3.0 (I will not add aditional features before v3.0 is ready).
====================================================
- THIS VERSION ____REQUIRES____ Linux 1.3.33 OR LATER.
====================================================
- THIS VERSION MAY NOT WORK WITH Linux VERSIONS RELEASED
AFTER end of Nov 1995. If this version doesn't compile with
your kernel version, please use the sound driver version
included in your kernel.
You will need the snd-util-3.0.tar.gz and snd-data-0.1.tar.Z
packages to use this driver. They should be in the same
ftp site or BBS from where you got this driver. For
example at nic.funet.fi:pub/OS/Linux/*.
If you are looking for the installation instructions, please
look at linux/Readme.
Supported soundcards
--------------------
Gravis Ultrasound (GUS)
GUS MAX
GUS with the 16 bit sampling daughtercard
PAS16
Windows Sound System compatible soundcards
ECHO-PSS (cards based on the PSS architecture by Analog Devices.
Including Orchid SW32, Cardinal DSP16 among others).
(NOTE! WSS mode may not work (DMA channel setup problem)).
MediaTriX AudioTriX Pro (OPL4 and the optional effect daughtercard
require special initialization. There is a program (setfx) in
the snd-util-3.0.tar.gz package which does it).
Ensoniq SoundScape (works but needs some improvements)
MV Jazz16 based soundcards (ProSonic, 3D etc).
SoundMan Wave (recording may not work, mixer support is limited)
Mozart (OAK OTI-601 interface chip) based soundcards.
MAD16 (an interface chip by OPTi) based soundcards (TB Tropez ???).
(NOTE! The MAD16 looks similar to the Mozart chip. It could be a good
idea to configure MAD16 cards as Mozart ones. The MAD16 driver doesn't set
up MPU401 which the Mozart one does.
CS4232 based cards such as AcerMagic S23.
In addition all Sound Blaster models and clones (up to AWE32) work if
you want to use them.
The Emu synthesizer chip of AWE32 is not and will not be supported. The same is
true with the ASP chip also. Creative Technology will not release detailed
information about them so it's not possible to support them.
If you want to get support for AWE32 or ASP, please contact Creative Labs.
Ask _politely_ if they are going to support Linux. Maybe they change
their policy if there is enough demand.
===========================================================================
If your card is compatible with SB, MPU401 or Windows Sound System, it
may work with the driver even if it's not listed in the above list. In this
case it may require initialization using DOS. Just start DOS and cold
boot to Linux (etc.) by hitting ctrl-alt-del.
===========================================================================
Compatibility with the earlier versions
---------------------------------------
There have been some changes in soundcard.h after v2.5 of the driver
(v2.90 is compatible with this one). Binaries compiled with this version
of soundcard.h will not work with v2.0 and earlier.
Contributors
------------
This driver contains code by several contributors. In addition several other
persons have given usefull suggestions. The following is a list of major
contributors. (I could have forgotten some names.)
Craig Metz 1/2 of the PAS16 Mixer and PCM support
Rob Hooft Volume computation algorithm for the FM synth.
Mika Liljeberg uLaw encoding and decoding routines
Andy Fingerhut New ulaw conversion tables (ulaw.h)
Jeff Tranter Linux SOUND HOWTO document
Greg Lee Volume computation algorithm for the GUS and
lot's of valuable suggestions.
Andy Warner ISC port
Jim Lowe,
Amancio Hasty Jr FreeBSD/NetBSD port
Anders Baekgaard Bughunting and valuable suggestions.
Joerg Schubert SB16 DSP support.
Andrew Robinson Improvements to the GUS driver
Megens SA MIDI recording for SB and SB Pro.
Mikael Nordqvist Linear volume support for GUS and
nonblocking /dev/sequencer.
Ian Hartas SVR4.2 port
Markus Aroharju and
Risto Kankkunen Major contributions to the mixer support
of GUS v3.7.
Hunyue Yau Mixer support for SG NX Pro.
Marc Hoffman PSS support.
Rainer Vranken Initialization for Jazz16 (ProSonic, MV3D, SM Wave).
Peter Trattler Initial version of loadable module support for Linux.
JRA Gibson 16 bit mode for Jazz16
Davor Jadrijevic MAD16 support
Gregor Hoffleit Mozart support
Riccardo Facchetti Audio Excel DSP 16 (aedsp16) support
There are propably many other names missing. If you have sent me some
patches and your name is not in the above list, please inform me.
Sponsors etc.
-------------
The following companies have greatly helped development of this driver
in form of a free copy of their product:
Novell, Inc. UnixWare personal edition + SDK
The Santa Cruz Operation, Inc. A SCO OpenServer + SDK
Ensoniq Corp, a SoundScape card and extensive amount of assistance
MediaTriX Peripherals Inc, a AudioTriX Pro card + SDK
Acer, Inc. a pair of AcerMagic S23 cards.
In addition the following companies have provided me sufficial amount
of technical information at least some of their products (free or $$$):
Advanced Gravis Computer Technology Ltd.
Media Vision Inc.
Analog Devices Inc.
Logitech Inc.
Aztech Labs Inc.
Crystal Semiconductor Corporation,
Integrated Circuit Systems Inc.
OAK Technology
OPTi
Ad Lib Inc. ($$)
Music Quest Inc. ($$)
Creative Labs ($$$)
If you have some problems
=========================
Read the sound HOWTO (sunsite.unc.edu:/pub/Linux/docs/...?).
Also look at the home page (http://personal.eunet.fi/pp/voxware). It may
contain info about some recent bug fixes.
It's likely that you have some problems when trying to use the sound driver
first time. Soundcards don't have standard configuration so there are no
good default configuration to use. Please try to use same I/O, DMA and IRQ
values for the soundcard than with DOS.
If you get an error message when trying to use the driver, please look
at /var/adm/messages for more verbose error message.
In general the easiest way to diagnoze problems is to do "cat /dev/sndstat".
If you get an error message, there are some problems with the driver setup:
- "No such file or directory" tells that the device files for
the sound driver are missing. Use the script at the end of
linux/drivers/sound/Readme.linux to create them.
- "No such device" telss that the sound driver is not in the kernel.
You have to reconfigure and recompile the kernel to have the sound
driver. Compiling the driver doesn't help alone. You have to boot
with the newly compiled one before the driver becomes active.
The Linux-HOWTO should help in this step.
The following errors are likely with /dev/dsp and /dev/audio.
- "No such device or address". This error message should not happen
with /dev/sndstat but it's possible with the other sound devices.
This error indicates that there are no suitable hardware for the
device file or the sound driver has been compiled without support for
this particular device. For example /dev/audio and /dev/dsp will not
work if "digitized voice support" was not enabled during "make config".
- "Device or resource busy". Propably the IRQ (or DMA) channel
required by the soundcard is in use by some other device/driver.
- "I/O error". Almost certainly (99%) it's an IRQ or DMA conflict.
Look at the kernel messages in /var/adm/notice for more info.
- "Invalid argument". The application is calling ioctl()
with impossible parameters. Check that the application is
for sound driver version 2.X or later.
In general the printout of of /dev/sndstat should tell what is the problem.
It's possible that there are bugs in the sound driver but 99% of the problems
reported to me are caused by somehow incorrect setup during "make config".
For owners of TI TM4000M notebooks
----------------------------------
There appears to be some kind of conflict between the sound support
(MV Jazz), mouse port and VoxWare. You could try to configure kernel
with the C&T 82C710 mouse port support disabled.
Hannu
Regards,
Hannu Savolainen
hannu@voxware.pp.fi
(or Hannu.Savolainen@cctap.carel.fi in case the above bounces)
Snail mail: Hannu Savolainen
Hiekkalaiturintie 3 A 8
00980 Helsinki
Finland
NOTE! I propably don't answer to Snail mail or FAX messages. Sending answer
to each of them is simply too expensive and time consuming. However I
try to reply every email message I get (within a week). If you don't
get response, please check how your address is written in the message
header. I can't answer if I don't have a valid reply address.
VoxWare home page is http://personal.eunet.fi/pp/voxware

View File

@ -1,6 +0,0 @@
Informations about Audio Excel DSP 16 can be found in the source
file aedsp16.c
Please, read the head of the source before using it. It contain useful
informations.
Riccardo

View File

@ -1,845 +0,0 @@
Configuring VoxWare 3.0 (for Linux) with some most common soundcards
====================================================================
NOTE! This document may contain some error. Please inform me
if you find any mistakes.
Read this before trying to configure the driver
-----------------------------------------------
There are currently many cards that work with VoxWare. Some of the cards
have native support while the others work since they emulate some other
cards (usually SB, MSS/WSS and/or MPU401). The following cards have native
support in VoxWare. Detailed instructions for configuring these cards
will be given later in this document.
Pro Audio Spectrum 16 (PAS16) and compatibles:
Pro Audio Spectrum 16
Pro Audio Studio 16
Logitech Sound Man 16
NOTE! The original Pro Audio Spectrum as well as the PAS+ are not
and will not be supported by VoxWare.
Media Vision Jazz16 based cards
Pro Sonic 16
Logitech SoundMan Wave
(Other Jazz based cards should work but I don't have any reports
about them).
Sound Blasters
SB 1.0 to 2.0
SB Pro
SB 16
NOTE! The ASP chip and the EMU synth of the AWE32 is not supported
since their manufacturer doesn't release information about
the card. However both the AB16ASP and the AWE32 work with
VoxWare just like a SB16. Also see the comment about some
unsupported cards at the end of this file.
SB16 compatible cards by other manufacturers than Creative.
You have been fooled since there are no SB16 compatible
cards in the market (July95). It's likely that your card
is compatible just with SB Pro but there is also a non SB
compatible 16 bit mode. Usually it's MSS/WSS but could also
be a proprietary one like MV Jazz16.
Gravis Ultrasound (GUS)
GUS
GUS + the 16 bit option
GUS MAX
GUS ACE (No MIDI port and audio recording)
MPU-401 and compatibles
The driver works both with the full (intelligent mode) MPU-401
cards (such as MPU IPC-T and MQX-32M) and with the UART only
dumb MIDI ports. MPU-401 is currently the most common MIDI
interface. Most soundcards are compatible with it. However
don't enable MPU401 mode blindly. Many cards having native support
in VoxWare have their own MPU401 driver. Enabling the standard one
will cause a conflict with these cards. So look if your card is
in the list of supported cards before enabling MPU401.
Windows Sound System (MSS/WSS)
Even Microsoft has discontinued their own Sound System card, they
managed to make a standard. MSS compatible cards are based on a
codec chip which is easily available from at least two manufacturers
(AD1848 by Analog Devices and CS4231/CS4248 by Crystal Semiconductor).
Currently most soundcards are based on one of the MSS compatible codec
chip. The CS4231 is used in the high quality cards such as GUS MAX,
MediaTriX AudioTriX Pro and TB Tropez (GUS MAX is not MSS compatible).
Having a AD1848, CS4248 or CS4231 codec chip on the card is a good
sign. Even if the card is not MSS compatible, it could be easy to write
support for it to VoxWare. Note also that most MSS compatible cards
require special boot time initialization which may not be present
in VoxWare. Also some MSS compatible cards have native support in
VoxWare. Enabling the MSS support with these cards is likely to
cause a conflict. So check if your card is listed in this file before
enabling the MSS support.
6850 UART MIDI
This UART chip is used in the MIDI interface of some (rare)
soundcards. It's supported by VoxWare in case you need it.
Yamaha FM synthesizers (OPL2, OPL3 and OPL4)
Most soundcards have a FM synthesizer chip. The OPL2 is a 2
operator chip used in the original AdLib card. Currently it's used
only in the cheapest (8 bit mono) cards. The OPL3 is a 4 operator
FM chip which provides better sound quality and/or more available
voices than the OPL2. The OPL4 is a new chip which has a OPL3 and
a wave table synthesizer packed on the same chip. VoxWare supports
just the OPL3 mode directly. Most cards having a OPL4 (like
SM Wave and AudioTriX Pro) support the OPL4 mode using MPU401
emulation. Writing a native OPL4 support to VoxWare is difficult
since Yamaha doesn't give information about their sample ROM chip.
Enable the generic OPL2/OPL3 FM synthesizer support if your
card has a FM chip made by Yamaha. Don't enable it if your card
has a software (TRS) based FM emulator.
PSS based cards (AD1848 + ADSP-2115 + Echo ESC614 ASIC)
Analog Devices and Echo Speech have together defined a soundcard
architecture based on the above chips. The DSP chip is used
for emulation of SB Pro, FM and General MIDI/MT32.
There are several cards based on this architecture. The most known
ones are Orchid SW32 and Cardinal DSP16.
VoxWare supports downloading DSP algorithms to these cards.
MediaTriX AudioTriX Pro
The ATP card is built around a CS4231 codec and a OPL4 synthesizer
chips. The OPL4 mode is supported by a microcontroller running a
General MIDI emulator. There is also a SB 1.5 compatible playback mode.
Ensoniq SoundScape and compatibles
Ensoniq has designed a soundcard architecture based on the
OTTO synthesizer chip used in their professional MIDI synthesizers.
Several companies (including Ensoniq, Reveal and Spea) are selling
cards based on this architecture.
MAD16 and Mozart based cards
The Mozart (OAK OTI-601) and MAD16 Pro (OPTi 82C929) interface
chips are used in many different soundcards, including some
cards by Reveal and Turtle Beach (Tropez). Purpose of these
chips is to connect other audio components to the PC bus. The
interface chip performs address decoding for the other chips.
Audio Excell DSP16
Support for this card is made by Riccardo Faccetti
(riccardo@cdc8g5.cdc.polimi.it). See aedsp16.c for more info.
Crystal CS4232 based cards such as AcerMagic S23
CS4232 is a PnP multimedia chip which contains a CS3231A codec,
SB and MPU401 emulations. There is support for OPL3 too.
(Unfortunately the MPU401 mode doesn't work).
Turtle Beach Maui and Tropez
VoxWare supports sample, parch and program loading commands
described in the Maui/Tropez User's manual. There is no initialization
code for Maui so it must be initialized using DOS. Audio side of Tropez
is based on the MAD16 chip (see above).
Jumpers and software configuration
----------------------------------
Some of the earliest soundcards were jumper configurable. You have to
configure VoxWare to configure VoxWare use I/O, IRQ and DMA settings
that match the jumpers. Just few 8 bit cards are fully jumper
configurable (SB 1.x/2.x, SB Pro and clones).
Some cards made by Aztech have an EEPROM which contains the
config info. These cards behave much like hardware jumpered cards.
Most cards have jumper for the base I/O address but other parameters
are software configurable. Sometimes there are few other jumpers too.
Latest cards are fully software configurable or they are PnP ISA
compatible. There are no jumpers on the board.
VoxWare handles software configurable cards automaticly. Just configure
the driver to use I/O, IRQ and DMA settings which are known to work.
You could usually use the same values than with DOS and/or Windows.
Using different settings is possible but not recommended since it may cause
some trouble (for example when warm booting from an OS to another or
when installing new hardware to the machine).
VoxWare sets the soft configurable parameters of the card automaticly
during boot. Usually you don't need to run any extra initialization
programs when booting Linux but there are some exceptions. See the
card specific instructions (below) for more info.
The drawback of software configuration is that the driver needs to know
how the card must be initialized. It cannot initialize unknown cards
even if they are otherwise compatible with some other cards (like SB,
MPU401 or Windows Sound System).
What if your card was not listed above?
---------------------------------------
The first thing to do is to look at the major IC chips on the card.
Many of the latest soundcards are based on some standard chips. If you
are lucky, all of them could be supported by VoxWare. The most common ones
are the OPTi MAD16, Mozart, SoundScape (Ensoniq) and the PSS architectures
listed above. Also look at the end of this file for list of unsupported
cards and the ones which could be supported later.
The last resort is to send _exact_ name and model information of the card
to me together with a list of the major IC chips (manufactured, model) to
me. I could then try to check if your card looks like something familiar.
There are much more cards in the word than listed above. The first thing to
do with these cards is to check if they emulate some other card/interface
such as SB, MSS and/or MPU401. In this case there is a chance to get the
card to work by booting DOS before starting Linux (boot DOS, hit ctrl-alt-del
and boot Linux without hard resetting the machine). In this method the
DOS based driver initializes the hardware to use a known I/O, IRQ and DMA
settings. If VoxWare is configured to use the same settings, everything should
work OK.
Configuring VoxWare (with Linux)
================================
VoxWare sound driver is currently a part of Linux kernel distribution. The
driver files are located in directory /usr/src/linux/drivers/sound.
****************************************************************************
* VoxWare MUST BE CONFIGURED AND COMPILED WITH THE KERNEL. TRYING *
* TO COMPILE IT ALONE WILL _NOT_ WORK. *
* *
* ALWAYS USE THE SOUND DRIVER VERSION WHICH IS DISTRIBUTED WITH *
* THE KERNEL SOURCE PACKAGE YOU ARE USING. SOME ALPHA AND BETA TEST *
* VERSIONS CAN BE INSTALLED FROM A SEPARATELY DISTRIBUTED PACKAGE *
* BUT CHECK THAT THE PACKAGE IS NOT MUCH OLDER (OR NEWER) THAN THE *
* KERNEL YOU ARE USING. IT'S POSSIBLE THAT THE KERNEL/DRIVER *
* INTERFACE CHANGES BETWEEN KERNEL RELEASES WHICH MAY CAUSE SOME *
* INCOMPATIBILITY PROBLEMS. *
* *
* IN CASE YOU INSTALL A SEPARATELY DISTRIBUTED SOUND DRIVER VERSION, *
* BE SURE TO REMOVE OR RENAME THE OLD SOUND DRIVER DIRECTORY BEFORE *
* INSTALLING THE NEW ONE. LEAVING OLD FILES TO THE SOUND DRIVER *
* DIRECTORY _WILL_ CAUSE PROBLEMS WHEN THE DRIVER IS USED OR *
* COMPILED. *
****************************************************************************
To configure the driver, run "make config" in the kernel source directory
(/usr/src/linux). Answer y to the question about Sound card support (after
questions about mouse, CD-ROM, ftape, etc. supports). Sound config options
will then be asked after some additional questions.
After configuring the kernel and sound driver, run "make dep" and compile
the kernel following instructions in the kernel README.
The sound driver configuration dialog
-------------------------------------
All config information of the sound driver is written to file
linux/drivers/sound/local.h. You may save the old version is this file and
use it again in case you want to use the same config later. In this case
just answer n to each question made by the sound config program and put
the original local.h back before running "make dep".
Don't do this if the version number of the sound driver has changed. In this
case you have to enter the configuration information again.
If you already have the sound driver installed, consult printout of
"cat /dev/sndstat" when configuring the driver again. It gives the I/O,
IRQ and DMA settings you have used earlier.
The sound config program (linux/drivers/sound/configure) starts by making
some yes/no questions. Be careful when answering to these questions since
answering y to a question may prevent some later ones from being asked. For
example don't answer y to the first question (PAS16) if you don't really
have a PAS16. Don't enable more cards than you really need since they
just consume memory. Also some drivers (like MPU401) may conflict with your
SCSI controller and prevent kernel from booting. If you card was in the list
of supported cards (above), please look at the card specific config
instructions (later in this file) before starting to configure. Some cards
must be configured in way which is not obvious.
So here is the beginning of the config dialog. Answer 'y' or 'n' to these
questions. The default answer is shown so that (y/n) means 'y' by default and
(n/y) means 'n'. To use the default value, just hit ENTER. But be careful
since using the default _doesn't_ guarantee anything.
Note also that all questions may not be asked. The configuration program
may disable some questions dependig on the earlier choices. It may also
select some options automaticly as well.
"ProAudioSpectrum 16 support",
- Answer 'y'_ONLY_ if you have a Pro Audio Spectrum _16_,
ProAudio Studio 16 or Logitech SoundMan 16 (be sure that
you read the above list correctly). Don't answer 'y' if you
have some other card made by Media Vision or Logitech since they
are not PAS16 compatible.
"SoundBlaster support",
- Answer 'y' if you have an original SB card made by Creative Labs
or a full 100% hardware compatible clone (like Thunderboard or
SM Games). If your card was in the list of supported cards (above),
please look at the card specific instructions later in this file
before answering this question. For an unknown card you may answer
'y' if the card claims to be SB compatible.
Don't enable SB if you have a MAD16 or Mozart compatible card.
"Generic OPL2/OPL3 FM synthesizer support",
- Answer 'y' if your card has a FM chip made by Yamaha (OPL2/OPL3/OPL4).
Answering 'y' is usually a safe and recommended choice. However some
cards may have software (TSR) FM emulation. Enabling FM support
with these cards may cause trouble. However I don't currently know
such cards.
"Gravis Ultrasound support",
- Answer 'y' if you have GUS or GUS MAX. Answer 'n' if you don't
have GUS since the GUS driver consumes much memory.
Currently I don't have experiences with the GUS ACE so I don't
know what to answer with it.
"MPU-401 support (NOT for SB16)",
- Be careful with this question. The MPU401 interface is supported
by almost any soundcard today. However some natively supported cards
have their own driver for MPU401. Enabling the MPU401 option with
these cards wil cause a conflict. Also enabling MPU401 on a system
that doesn't really have a MPU401 could cause some trouble. If your
card was in the list of supported cards (above), please look at
the card specific instructions later in this file.
It's safe to answer 'y' if you have a true MPU401 MIDI interface
card.
"6850 UART Midi support",
- It's safe to answer 'n' to this question in all cases. The 6850
UART interface is so rarely used.
"PSS (ECHO-ADI2111) support",
- Answer 'y' only if you have Orchid SW32, Cardinal DSP16 or some
other card based on the PSS chipset (AD1848 codec + ADSP-2115
DSP chip + Echo ESC614 ASIC CHIP).
"16 bit sampling option of GUS (_NOT_ GUS MAX)",
- Answer 'y' if you have installed the 16 bit sampling daughtercard
to your GUS. Answer 'n' if you have GUS MAX. Enabling this option
disables GUS MAX support.
"GUS MAX support",
- Answer 'y' only if you have a GUS MAX.
"Microsoft Sound System support",
- Again think carefully before answering 'y' to this question. It's
safe to answer 'y' in case you have the original Windows Sound
System card made by Microsoft or Aztech SG 16 Pro (or NX16 Pro).
Also you may answer 'y' in case your card was not listed earlier
in this file. For cards having native support in VoxWare, consult
the card specific instructions later in this file. Some drivers
have their own MSS support and enabling this option wil cause a
conflict.
"Ensoniq Soundscape support",
- Answer 'y' if you have a soundcard based on the Ensoniq SoundScape
chipset. Suach cards are being manufactured at least by Ensoniq,
Spea and Reveal (note that Reveal makes other cards also).
"MediaTriX AudioTriX Pro support",
- Answer 'y' if you have the AudioTriX Pro.
"Support for MAD16 and/or Mozart based cards",
- Answer y if your card has a Mozart (OAK OTI-601) or MAD16
(OPTi 82C928 or 82C929) audio interface chip. These chips are
currently quite common so it's possible that many no-name cards
have one of them. In addition the MAD16 chip is used in some
cards made by known manufacturers such as Turtle Beach (Tropez),
Reveal (some models) and Diamond (latest ones).
"SoundBlaster Pro support",
- Enable this option if your card is SB Pro or SB16. Enable it
also with any SB Pro clones. Answering 'n' saves some amount of
memory but 'y' is the safe alterative.
"SoundBlaster 16 support",
- Enable if you have a SB16 (including the AWE32).
"Audio Excel DSP 16 initialization support",
- Don't know much about this card. Look at aedsp16.c for more info.
Then the configuration program asks some y/n questions about the higher
level services. It's recommended to answer 'y' to each of these questions.
Answer 'n' only if you know you will not need the option.
"/dev/dsp and /dev/audio supports (usually required)",
- Answering 'n' disables /dev/dsp and /dev/audio. Answer 'y'.
"MIDI interface support",
- Answering 'n' disables /dev/midi## devices and access to any
MIDI ports using /dev/sequencer and /dev/music. This option
also affects any MPU401 and/or General MIDI compatible devices.
"FM synthesizer (YM3812/OPL-3) support",
- Answer 'y' here.
"/dev/sequencer support",
- Answering 'n' disables /dev/sequencer and /dev/music.
Entering the I/O, IRQ and DMA config parameters
-----------------------------------------------
After the above questions the configuration program prompts for the
card specific configuration information. Usually just a set of
I/O address, IRQ and DMA numbers are asked. With some cards the program
asks for some files to be used during initialization of the card. For example
many cards have a DSP chip or microprocessor which must be initialized by
downloading a program (microcode) file to the card. In some cases this file
is written to a .h file by the config program and then included to the driver
during compile.
Instructions for answering these questions are given in the next section.
Card specific information
=========================
This section gives additional instructions about configuring some cards.
Please refer manual of your card for valid I/O, IRQ and DMA numbers. Using
the same settings with DOS/Windows and VoxWare is recommended. Using
different values could cause some problems when switching between
different operating systems.
SoundBlasters (the original ones by Creative)
---------------------------------------------
It's possible to configure these cards to use different I/O, IRQ and
DMA settings. Since the available settings have changed between various
models, you have to consult manual of your card for the proper ones. It's
a good idea to use the same values than with DOS/Windows. With SB and SB Pro
it's the only choice. SB16 has software selectable IRQ and DMA channels but
using different values with DOS and Linux is likely to cause troubles. The
DOS driver is not able to reset the card properly after warm boot from Linux
if Linux has used different IRQ or DMA values.
The original (steam) Sound Blaster (versions 1.x and 2.x) use always
DMA1. There is no way to change it.
The SB16 needs two DMA channels. A 8 bit one (1 or 3) is required for
8 bit operation and a 16 bit one (5, 6 or 7) for the 16 bit mode. In theory
it's possible to use just one (8 bit) DMA channel by answering the 8 bit
one when the configuration program asks for the 16 bit one. This may work
in some systems but is likely to cause terrible noise on some other systems.
NOTE! Don't enable the SM Games option (asked by the configuration program)
if you are not 101% sure that your card is a Logitech Soundman Games
(not a SM Wave or SM16).
SB Clones
---------
First of all: There are no SB16 clones. There are SB Pro clones with a
16 bit mode which is not SB16 compatible. The most likely alternative is that
the 16 bit mode means MSS/WSS.
There are just few fully 100% hardware SB or SB Pro compatible cards.
I know just Thunderboard and SM Games. Other cards require some kind of
hardware initialization before they become SB compatible. Check if your card
was listed in the beginning of this file. In this case you should follow
instructions for your card later in this file.
For other not fully SB clones yoy may try initialization using DOS in
the following way:
- Boot DOS so that the card specific driver gets run.
- Hit ctrl-alt-del (or use loadlin) to boot Linux. Don't
switch off power or press the reset button.
- If you use the same I/O, IRQ and DMA settings in Linux, the
card should work.
If your card is both SB and MSS compatible, I recommend using the MSS mode.
Most cards of this kind are not able to work in the SB and the MSS mode
simultaneously. Using the MSS mode provides 16 bit recording and playback.
ProAudioSpectrum 16 and compatibles
-----------------------------------
There are nothing special with these cards. Just don't enable any
other cards in case you don't have them also. The PAS16 has
a SB mode so the driver config program will prompt for the SB settings
do. Use I/O 0x220 and DMA1 for the SB mode. Ensure that you assign different
IRQ numbers for the SB and PAS16 modes.
With PAS16 you can use two audio device files at the same time. /dev/dsp (and
/dev/audio) is connected to the 8/16 bit native codec and the /dev/dsp1 (and
/dev/audio1) is connected to the SB emulation (8 bit mono only).
Gravis Ultrasound
-----------------
There are many different revisions of the Ultrasound card (GUS). The
earliest ones (pre 3.7) don't have a hardware mixer. With these cards
the driver uses a software emulation for synth and pcm playbacks. It's
also possible to switch some of the inputs (line in, mic) off by setting
mixer volume of the channel level below 10%. For recording you have
to select the channel as a recording source and to use volume above 10%.
GUS 3.7 has a hardware mixer.
GUS MAX and the 16 bit sampling daughtercard have a CS4231 codec chip which
also contains a mixer.
Configuring GUS is simple. Just enable the GUS support and GUS MAX or
the 16 bit daughtercard if you have them. Note that enabling the daughter
card disables GUS MAX driver.
With just the standard GUS enabled the configuration program prompts
for the I/O, IRQ and DMA numbers for the card. Use the same values than
with DOS.
With the daughter card option enabled you will be prompted for the I/O,
IRQ and DMA numbers for the daughter card. You have to use different I/O
and DMA values than for the standard GUS. The daughter card permits
simultaneous recording and playback. Use /dev/dsp (the daughtercard) for
recording and /dev/dsp1 (GUS GF1) for playback.
GUS MAX uses the same I/O address and IRQ settings than the original GUS
(GUS MAX = GUS + a CS4231 codec). In addition an extra DMA channel may be used.
Using two DMA channels permits simultaneous playback using two devices
(dev/dsp0 and /dev/dsp1). The second DMA channel is required for
full duplex audio.
To enable the second DMA channels, give a valid DMA channel when the config
program asks for the GUS MAX DMA (entering -1 disables the second DMA).
Using 16 bit DMA channels (5,6 or 7) is recommended.
If you have problems in recording with GUS MAX, you could try to use
just one 8 bit DMA channel. Recording will not work with one DMA
channel if it's a 16 bit one.
MPU401 and Windows Sound System
-------------------------------
Again. Don't enable these options in case your card is listed
somewhere else in this file.
Configuring these cards is obvious (or it should be). With MSS
you should propably enable the OPL3 synth also since
most MSS compatible cards have it. However check that this is true
before enabling OPL3.
VoxWare supports more than one MPU401 compatible cards at the same time
but the config program asks config info for just the first of them.
Adding the second or third MPU interfaces must be done manually by
editing sound/local.h (after running the config program). Add defines for
MPU2_BASE & MPU2_IRQ (and MPU3_BASE & MPU3_IRQ) to the file.
CAUTION!
The default I/O base of Adaptec AHA-1542 SCSI controller is 0x330 which
is also the default of the MPU401 driver. Don't configure the sound driver to
use 0x330 as the MPU401 base if you have a AHA1542. The kernel will not boot
if you make this mistake.
PSS
---
Even the PSS cards are compatible with SB, MSS and MPU401, you must not
enable these options when configuring the driver. The configuration
program handles these options itself. (You may use the SB, MPU and MSS options
together with PSS if you have another card on the system).
The PSS driver enables MSS and MPU401 modes of the card. SB is not enabled
since it doesn't work concurrently with MSS. The driver loads also a
DSP algorithm which is used to for the general MIDI emulation. The
algorithm file (.ld) is read by the config program and written to a
file included when the pss.c is compiled. For this reason the config
program asks if you want to download the file. Use the genmidi.ld file
distributed with the DOS/Windows drivers of the card (don't use the mt32.ld).
With some cards the file is called 'synth.ld'. You must have access to
the file when configuring the driver. The easiest way is to mount the DOS
partition containing the file with Linux.
It's possible to load your own DSP algorithms and run them with the card.
Look at the directory sound/pss_test for more info (in the VoxWare-3.0.tar.gz)
package.
AudioTriX Pro
-------------
You have to enable the OPL3 and SB (not SB Pro or SB16) drivers in addition
to the native AudioTriX driver. Don't enable MSS or MPU drivers.
Configuring ATP is little bit tricky since it uses so many I/O, IRQ and
DMA numbers. Using the same values than with DOS/Win is a good idea. Don't
attemp to use the same IRQ or DMA channels twice.
The SB mode of ATP is implemented so the the ATP driver just enables SB
in the proper address. The SB driver handles the rest. Yoy have to configure
both the SB driver and the SB mode of ATP to use the same IRQ, DMA and I/O
settings.
Also the ATP has a microcontroller for the General MIDI emulation (OPL4).
For this reason the driver asks for the name of a file containing the
microcode (TRXPRO.HEX). This file is usually located in the directory
where the DOS drivers were installed. You must have access to this file
when configuring the driver.
If you have the effects daughtercard, it must be initialized by running
the setfx program of snd-util-3.0.tar.gz package. This step is not required
when using the (future) binary distribution version of the driver.
Ensoniq SoundScape
------------------
The SoundScape driver handles initialization of MSS and MPU supports
itself so you don't need to enable other drivers than SoundScape
(enable also the /dev/dsp, /dev/sequencer and MIDI supports).
SoundScape driver uses the MSS compatible codec of the card. It's important
to note that /dev/dsp0 (/dev/dsp is linked to /dev/dsp0 by default)
doesn't work with SoundScape (yet). The 'ssinit' program needs /dev/dsp0 so
that's the reason why it's there. It's possible that 'primary' pcm channel
becomes supported later. Currently the card's firmware doesn't contain
support for it.
With 3.0 of VoxWare you have to change your system to use /dev/dsp1 by default
so execute: cd /dev;rm dsp;ln -s dsp1 dsp after you have installed VoxWare
3.0 (first time).
The configuration program asks two DMA channels and two interrupts. One IRQ
and one DMA is used by the MSS codec. The second IRQ is required for the
MPU401 mode (you have to use different IRQs for both purposes).
The second DMA channel is required for initialization of the microcontroller.
You have to use separate DMA channels.
The SoundScape card has a Motorola microcontroller which must initialized
_after_ boot (the driver doesn't initialize it during boot).
The initialization is done by running the 'ssinit' program which is
distributed in the snd-util-3.0.tar.gz package. You have to edit two
defines in the ssinit.c and then compile the program. You may run ssinit
manually (after each boot) or add it to /etc/rc.d/rc.local.
The ssinit program needs the microcode file that comes with the DOS/Windows
driver of the card. You will need to use version 1.30.00 or later
of the microcode file (sndscape.co0 or sndscape.co1 depending on
your card model). THE OLD sndscape.cod WILL NOT WORK. IT WILL HANG YOUR
MACHINE. The only way to get the new microcode file is to download
and install the DOS/Windows driver from ftp://ftp.ensoniq.com/pub.
Then you have to select the proper microcode file to use: soundscape.co0
is the right one for most cards and sndscape.co1 is for few (older) cards
made by Reveal and/or Spea. The driver has capability to detect the card
version during boot. Look at the boot log messages in /var/adm/messages
and locate the sound driver initialization message for the SoundScape
card. If the driver displays string <Ensoniq Soundscape (old)>, you have
an old card and you will need to use sndscape.co1. For other cards use
soundscape.co0.
Check /var/adm/messages after running ssinit. The driver prints
the board version after downloading the microcode file. That version
number must match the number in the name of the microcode file (extension).
Running ssinit with a wrong version of the sndscape.co? file is not
dangerous as long as you don't try to use a file called sndscape.cod.
If you have initialized the card using a wrong microcode file (sounds
are terrible), just modify ssinit.c to use another microcode file and try
again. It's possible to use an earlier version of sndscape.co[01] but it
may sound wierd.
Btw, The driver may complain something about "sscapeintr()" after
running ssinit. You should just ignore these messages.
MAD16 (Pro) and Mozart
----------------------
You need to enable just the MAD16 /Mozart support when configuring
the driver. _Don't_ enable SB, MPU401 or MSS. However you will need the
/dev/audio, /dev/sequencer and MIDI supports.
Mozart and OPTi 82C928 (the original MAD16) chips don't support
MPU401 mode so enter just 0 when the configuration program asks the
MPU/MIDI I/O base. The MAD16 Pro (OPTi 82C929) has MPU401 mode.
TB Tropez is based on the 82C929 chip. It has two MIDI ports.
The one connected to the MAD16 chip is the second one (there is a second
MIDI connector/pins somewhere??). If you have not connected the second MIDI
port, just disable the MIDI port of MAD16. The 'Maui' compatible synth of
Tropez is jumper configurable and not connected to the MAD16 chip.
It can be used by enabling the stand alone MPU401 support but you have
to initialize it by using the MS-DOS SNDSETUP program.
There are some other OPTi chips which may be used in soundcards such as
82C930 and MAC32. These chips are not supported by VoxWare yet. Please
contact me if you have a soundcard which uses these chips.
Some MAD16 based cards may cause feedback, whistle or terrible noise if the
line3 mixer channel is turned too high.
If you have a MAD16 card which have an OPL4 (FM + Wave table) synthesizer
chip (_not_ an OPL3), you have to apped line containing #define MAD16_OPL4
to the file linux/dirvers/sound/local.h (after running make config).
MV Jazz (ProSonic)
------------------
The Jazz16 driver is just a hack made to the SB Pro driver. However it works
fairly well. You have to enable SB, SB Pro (_not_ SB16) and MPU401 supports
when configuring the driver. The configuration program asks later if you
want support for MV Jazz16 based cards (after asking SB base address). Answer
'y' here and the driver asks the second (16 bit) DMA channel.
The Jazz16 driver uses the MPU401 driver in a way which will cause
problems if you have another MPU401 compatible card. In this case you must
give address of the Jazz16 based MPU401 interface when the config
program prompts for the MPU401 information. Then look at the MPU401
spesific section for instructions about configuring more than one MPU401 cards.
Logitech Soundman Wave
----------------------
Read the above MV Jazz spesific instructions first.
The Logitech SoundMan Wave (don't confuse with the SM16 or SM Games) is
a MV Jazz based card which has an additional OPL4 based wave table
synthesizer. The OPL4 chip is handled by an on board microcontroller
which must be initialized during boot. The config program asks if
you have a SM Wave immediately after asking the second DMA channel of jazz16.
If you answer 'y', the config program will ask name of the file containing
code to be loaded to the microcontroller. The file is usually called
MIDI0001.BIN and it's located in the DOS/Windows driver directory. The file
may also be called as TSUNAMI.BIN or something else (older cards?).
The OPL4 synth will be inaccessible without loading the microcontroller code.
Also remember to enable MPU401 support if you want to use the OPL4 mode.
NOTE! Don't answer 'y' when the driver asks about SM Games support
(the next question after the MIDI0001.BIN name). However
aneswering 'y' is not dangerous.
Sound Galaxies
--------------
There are many different Sound Galaxy cards made by Aztech. The 8 bit
ones are fully SB or SB Pro compatible and there should be no problems
with them.
The older 16 bit cards (SG Pro16, SG NX Pro16, Nova and Lyra) have
an EEPROM chip for storing the configuration data. There is a microcontroller
which initializes the card to match the EEPROM settigs when the machine
is powered on. These cards actually behave just like they have jumpers
for all of the settings. Configure VoxWare for MSS, MPU, SB/SB Pro and OPL3
supports with these cards.
The config program asks if you want support for the mixer of
SG NX Pro. Answer 'y' to these questions if you have one of the above 8 or
16 bit Aztech cards.
There are some new Sound Galaxies in the market. I have no experience with
them so read the card's manual carefully.
Reveal cards
------------
There are several different cards made/marketed by Reveal. Some of them
are compatible with SoundScape and some use the MAD16 chip. You may have
to look at the card and try to identify origin of the card.
Diamond
-------
The oldest (Sierra Aria based) soundcards made by Diamond are not supported
(they may work if the card is initialized using DOS). The recent (LX?)
models are based on the MAD16 chip which is supported by VoxWare.
Audio Excel DSP16
-----------------
See comments in aedsp16.c.
PCMCIA cards
------------
Sorry, can't help. Some cards may work and some don't.
TI TM4000M notebooks
--------------------
These computers have a built in sound support based on the Jazz chipset.
Look at the instructions for MV Jazz (above). It's also important to note
that there is something wrong with the mouse port and sound at least on
some TM models. Don't enable the "C&T 82C710 mouse port support" when
configuring Linux. Having it enabled is likely to cause mysterious problems
and kernel failures when sound is used.
Others?
-------
Since there are so many different soundcards, it's likely that I have
forgotten to mention many of them. Please inform me if you know yet another
card which works with Linux, please inform me (or is anybody else
willing to maintain a database of supported cards (just like in XF86)?).
Cards not supported yet
=======================
First of all. There is an easy way to make most soundcards to work
with Linux. Just use the DOS based driver to initialize the card
to a _known_ state. Then ctrl-alt-del to Linux. If Linux is configured
to use the sama I/O, IRQ and DMA numbers than DOS, the card could work.
Don't get fooled with SB compatibility. Most cards are compatible with
SB but that may require a TSR which is not possible with Linux. If
the card is compatible with MSS, it's a better choise. Some cards
don't work in the SB and MSS modes at the same time.
There are some cards which will be supported by VoxWare sooner or later
(currently at least cards based on the ESS chipset). Such cards are
so common that there is some idea in writing the driver. Check the
VoxWare home page (http://personal.eunet.fi/pp/voxware) for latest
information.
Then there are cards which are no longer manufactured and/or which
are relatively rarely used (such as the 8 bit ProAudioSpectrum
models). It's extremely unlikely that such cards never get supported.
Adding support for a new card requires much work and increases time
required in maintaining the driver (some changes need to be done
to all low level drivers and be tested too, maybe with multiple
operating systems). For this reason I have made a desicion to not support
obsolete cards. It's possible that someone else makes a separately
distributed driver (diffs) for the card. Version v4.0 will be much more
modular so making separately distributed drivers will be easier with it.
(The bad news is that v4.0 will not be available before late -96).
Writing a driver for a new card is not possible if there are no
programming information available about the card. If you don't
find your new card from this file, look from the home page
(http://personal.eunet.fi/pp/voxware). Then please contact
manufacturer of the card and ask if they have (or are willing to)
released technical details of the card. Do this before contacting me. I
can only answer 'no' if there are no programming information available.
Some companies don't give low level technical information about their
products to public or at least their require signing a NDA.
I have also made decicion to not accept code based on reverse engineering
to VoxWare. There are three main reasons: First I don't want to break
relationships to sound card manufacturers. The second reason is that
maintaining and supporting a driver withoun any specs will be a pain. The
third reason is that why shoud we help such companies in selling their
products to Linux users when they don't want to sell to Linux users
at all?
Unfortunately many of the leading soundcard manufacturers are not willing
to co-operate with Linux/Unix community. For example: Creative Technology
doesn't give information about the ASP chip and the Emu synth chip of AWE32
and SB32. Turtle Beach don't give information about any of their
products. MediaVision requires NDA before they are willing to
give information about the Jazz16 chip (fortunately Logitech gave
the info about SM Wave).
So at least the above three companies are out until they are willing to
release documentation about their products (the situation is the
same with many DOS based freeware/shareware games and utilities). If
you want to use Linux/Unix with their cards, please don't try to push
me. It's a better idea to contact the manufacturer and explain that
you want to use your card with Linux/Unix. You could also try to sell
your card to somebody else and then buy a card that is supported by VoxWare.
However it's possible that things change and a driver gets written
for some of the banned cards. Please, don't send me messages asking if
there is any plans to write a driver for the cards mentioned above. I
will put any news to the VoxWare www home page (see below).
There are some common audio chipsets that are supported yet. For example
the ESS chips and Sierra Aria. It's likely that these architectures
get some support in future but I can't make any promises. Just look
at the home page for latest info.
Information about unsupported soundcards and chipsets is welcome as well
as free copies of soundcards, SDKs and operating systems.
If you have any corrections and/or comments, please contact me.
Hannu Savolainen
hannu@voxware.pp.fi
VoxWare www home page: http://personal.eunet.fi/pp/voxware

View File

@ -1,99 +0,0 @@
Building a loadable sound driver
================================
Loadable module support in version 3.5 of VoxWare is mostly rewritten since
the previous version (3.0.1). This means that some things have changed.
To compile the sound driver as a loadable module you have to perform
the following steps:
1) Install modules-1.2.8.tar.gz package (or later if available).
2a) Check that symbol remap_page_range is defined in linux/init/ksyms.c.
Insert a line containing "X(remap_page_range)," if required. The driver will
not load if this line is missing.
2b) Recompile kernel with soundcard support disabled.
3) Boot the new kernel.
4) cd to the sound driver source directory (this directory). It's no
longer required that the sound driver sources are installed in the
kernel source tree (linux/drivers/sound). When installing a separately
distributed sound driver you may install the sources for example to
/usr/src/sound.
5) Execute make in the sound driver source directory. Enter
configuration parameters as described in Readme.cards. Then just wait until
the driver is compiled OK.
6) Copy sound.o to the directory where insmod expects to find it.
("make install" copies it to /lib/modules/misc).
7) Use command "insmod sound" to load the driver.
8) The sound driver can be removed using command "rmmod sound".
Parameters accepted by the loadable sound driver
================================================
Setting DMA buffer size
-----------------------
The driver allocates a DMA buffer (or two for full duplex devices)
every time the audio device (/dev/dsp or /dev/audio) is opened
and frees it when the device is closed. Size of this buffer is defined
when the driver is configured (the last question). The buffer size
can be redefined when loading the driver if required (note that this is
an optional feature which is not normally required). The buffer size
is redefined by adding dma_pagesize= parameter to the insmod command line.
For example:
insmod sound dma_buffsize=32768
Minimum buffer size is 4096 and the maximum depends on the DMA channe.
For 8 bit channels (0 to 3) the limit is 64k and for 16 bit ones (5 to 7)
it's 128k. Driver selects a suitable buffer size automaticly in case
you try to spesify an invalid size.
Q: What is the right DMA buffer size?
A: It depends on the sampling rate, machine speed and the load of the system.
Large buffers are required on slow machines, when recording/playing CD-quality
audio or when there are other processes running on the same system. Also
recording to hard disk is likely to require large buffers.
Very small buffers are sufficient when you are just playing 8kHz audio files
on an empty P133 system. Using a 128k byffer just wastes 120k (or 250k)
of valuable physical RAM memory.
The right buffer sice can be easily found by making some experiments
with the dma_buffsize= parameter. I use usually 16k buffers on a DX4/100 system
and 64k on an old 386 system.
NOTE! DMA buffers are used only by /dev/audio# and /dev/dsp# devices.
Other device files don't use them but there are two exceptions:
GUS driver uses DMA buffers when loading samples to the card.
Ensoniq SoundScape driver uses them when doanloading the microcode
file (sndscape.co[012]) to the card. Using large buffers doesn't
increase performance in these cases.
Configuring device parameters when loading the driver
-----------------------------------------------------
The loadable version of the sound driver accepts now the same
sound= parameter that has been available in the LILO command line.
In this way it's possible to change I/O port, IRQ and DMA addresses
and to enable/disable various cards at load time. Normally
the driver uses the configuration parameters entered when compiling
and configuring the driver.
Look at Readme.linux for more info.
NOTE! This method is not normally required. You should use it only when
you have to use different configuration than normally. The sound=
command line parameter is error phrone and not recommended.
Debugging and tracing
---------------------
Modularized sound driver doesn't display messages during initialization as
the kernel compiled one does. This feature can be turned on by adding
init_trace=1 to the insmod command line.
For example:
insmod sound init_trace=1

View File

@ -1,140 +0,0 @@
VoxWare v3.0
------------
All features of v2.90-2 should work as earlier. There could be some
omissions but they are unintentional. I started this version thread
after v2.3 so all features implemented before it are there.
New features
============
There are now two new device interfaces. The /dev/midi## is a raw
tty like interface to MIDI ports. There is a device file for each MIDI
port on your system. They are named (/dev/midi00 to /dev/midiNN).
The second addition is the /dev/music which is higher level interface
than the old /dev/sequencer. It's intended for writing device independent
applications like sequencers.
/dev/midi##
-----------
This interface should be usefull for applications like MIDI sysex librarians.
There are (currently) no timing features so making music could be impossible.
There are as many /dev/midi## devices as there are MIDI ports in the system.
The /dev/midi00 is connected to the first one, /dev/midi01 to the second etc.
These devices work like tty devices in raw mode. Everything written to them is
sent out to the MIDI port. There is currently an extra delay of at most
1/100th of sec but it will be removed later.
The reading algorithm is little bit more complicated. There are two different
cases:
1) There is at least one byte in the input buffer.
The read returns as many bytes as it can without waiting for more bytes.
For example when a process reads 100 bytes and there are 10 bytes in the
buffer, the read returns just 10 bytes.
2) The input buffer is empty when the process calls read.
The read waits for the first byte and then continues as in case 1. By
default it waits infinitely but there is an ioctl for setting a timeout
for this. The ioctl(fd, SNDCTL_MIDI_PRETIME, &time) changes the timeout.
The time is given in 1/10th of seconds (10 means one second).
Other ioctl calls:
ioctl(fd, SNDCTL_MIDI_MPUMODE, &mode) is available for full MPU-401
compatible devices such as MPU-IPC-T, MQ PC Midi Card or MQX-32.
It's not available for the so called MPU UART ports of some soundcards
(PAS16, SB16 etc). By default the MIDI port is in UART mode after open.
If this ioctl is called with mode=1, the interface is put to the intelligent
(coprocessor) mode. NOTE! The MIDI port will be reset when this ioctl is called.
It could have some strange effects if not called immediately after open. This
vall returns EINVAL if the midi port doesn't support the MPU-401 intelligent
mode.
ioctl(fd, SNDCTL_MIDI_MPUCMD, &cmdstruct) is valid only if the MIDI port
is put to the coprocessor mode using ioctl(SNDCTL_MIDI_MPUMODE). It's used to
send commands to a MPU-401 compatible MIDI cards. Please refer to the
MPU-401 Technical Reference Manual (or Music Quest Technical Reference
Manual) for descriptions of the commands.
The argument of SNDCTL_MIDI_MPUCOMMAND is of type mpu_command_rec. It
has the following fields:
typedef struct {
unsigned char cmd;
char nr_args, nr_returns;
unsigned char data[30];
} mpu_command_rec;
where:
cmd Contains the command number.
nr_args Number of arguments of the command.
MUST BE INITIALIZED BEFORE CALL
nr_returns Number of bytes returned by the command.
MUST BE INITIALIZED BEFORE CALL
data Buffer for the command arguments and returned
data.
Be extremely carefull with the nr_args and nr_returns fields. They
must match the command. An incorrect value will put the card and
the driver out of sync. Refer to the MPU-401/MQX-32M documentation for further
datails.
/dev/music (/dev/sequencer2)
----------------------------
This device file works much like the /dev/sequencer which has been present
since the beginning. The main differences are the following:
- /dev/sequencer makes the MIDI ports to look like the synth devices. In fact
the result is somewhere between the MIDI specification and the synth devices of
/dev/sequencer. Both kind of devices are accessed using the SEQ_START_NOTE()
like macros. The voice number parameters of the API macros have been redefined
to denote MIDI channels. This means that the driver allocates voices for
the channels automaticly (this is a responsibility/right of an application
with /dev/sequencer). The result is that a SEQ_START_NOTE() macro has
similar effects for a synth channel than on a MIDI port. This kind of
solution provides better device independence than the /dev/sequencer. The
drawback is that the new interface doesn't permit so low level access to the
device as the /dev/sequencer does. An application developer must choose between
these two interfaces. I think the old /dev/sequencer is better for applications
like module players while the new one is better for making generic sequencer
programs.
- There are no separate MIDI devices with the /dev/sequencer2. The
ioctl(SNDCTL_SEQ_NRMIDIS) returns always zero. Instead the MIDI ports are
shown as synth devices. ioctl(SNDCTL_SEQ_NRSYNTHS) on /dev/sequencer2 will
return sum of internal synthesizers (GUS, OPL3) and MIDI ports in the systems.
- The new interface is used much like the ordinary /dev/sequencer. The
event format is new so you have to use the API macros defined in the
sys/soundcard.h. The interface is will propably change before the final 3.0
release but using the API macros should ensure compatibility in source level.
The new event format is not recognized by version 2.X so don't try to
distribute binaries compiled with soundcard.h of v3.X.
- The basic API useage is similar to the current one. There are some new
macros but the older ones should work as earlier. The most important
incompatibility is that the /dev/sequencer2 driver allocates voices itself.
The other one is that the application must send SEQ_START_TIMER() as its
first event. Otherwise the timer is not started and the application waits
infinitely.
There are several new features but I don't document them here. There are
some info in the soundcard.h (near the end). I have also included some
sample code in the directory v30. Full documentation will
appear in the Hacker's Guide later.
Don't hesitate to contact me in case you have questions or comments.
Hannu Savolainen
hannu@voxware.pp.fi

File diff suppressed because it is too large Load Diff

View File

@ -1,142 +0,0 @@
/*
* sound/ad1848_mixer.h
*
* Definitions for the mixer of AD1848 and compatible codecs.
*
* Copyright by Hannu Savolainen 1994
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. 2.
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* The AD1848 codec has generic input lines called Line, Aux1 and Aux2.
* Soundcard manufacturers have connected actual inputs (CD, synth, line,
* etc) to these inputs in different order. Therefore it's difficult
* to assign mixer channels to to these inputs correctly. The following
* contains two alternative mappings. The first one is for GUS MAX and
* the second is just a generic one (line1, line2 and line3).
* (Actually this is not a mapping but rather some kind of interleaving
* solution).
*/
#define GUSMAX_MIXER
#ifdef GUSMAX_MIXER
#define MODE1_REC_DEVICES (SOUND_MASK_LINE | SOUND_MASK_MIC | \
SOUND_MASK_CD|SOUND_MASK_IMIX)
#define MODE1_MIXER_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_MIC | \
SOUND_MASK_CD | \
SOUND_MASK_IGAIN | \
SOUND_MASK_PCM|SOUND_MASK_IMIX)
#define MODE2_MIXER_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_LINE | SOUND_MASK_MIC | \
SOUND_MASK_CD | SOUND_MASK_SPEAKER | \
SOUND_MASK_IGAIN | \
SOUND_MASK_PCM | SOUND_MASK_IMIX)
#else /* Generic mapping */
#define MODE1_REC_DEVICES (SOUND_MASK_LINE3 | SOUND_MASK_MIC | \
SOUND_MASK_LINE1|SOUND_MASK_IMIX)
#define MODE1_MIXER_DEVICES (SOUND_MASK_LINE1 | SOUND_MASK_MIC | \
SOUND_MASK_LINE2 | \
SOUND_MASK_IGAIN | \
SOUND_MASK_PCM | SOUND_MASK_IMIX)
#define MODE2_MIXER_DEVICES (SOUND_MASK_LINE1 | SOUND_MASK_LINE2 | SOUND_MASK_MIC | \
SOUND_MASK_LINE3 | SOUND_MASK_SPEAKER | \
SOUND_MASK_IGAIN | \
SOUND_MASK_PCM | SOUND_MASK_IMIX)
#endif
struct mixer_def {
unsigned int regno: 7;
unsigned int polarity:1; /* 0=normal, 1=reversed */
unsigned int bitpos:4;
unsigned int nbits:4;
};
static char mix_cvt[101] = {
0, 0,3,7,10,13,16,19,21,23,26,28,30,32,34,35,37,39,40,42,
43,45,46,47,49,50,51,52,53,55,56,57,58,59,60,61,62,63,64,65,
65,66,67,68,69,70,70,71,72,73,73,74,75,75,76,77,77,78,79,79,
80,81,81,82,82,83,84,84,85,85,86,86,87,87,88,88,89,89,90,90,
91,91,92,92,93,93,94,94,95,95,96,96,96,97,97,98,98,98,99,99,
100
};
typedef struct mixer_def mixer_ent;
/*
* Most of the mixer entries work in backwards. Setting the polarity field
* makes them to work correctly.
*
* The channel numbering used by individual soundcards is not fixed. Some
* cards have assigned different meanings for the AUX1, AUX2 and LINE inputs.
* The current version doesn't try to compensate this.
*/
#define MIX_ENT(name, reg_l, pola_l, pos_l, len_l, reg_r, pola_r, pos_r, len_r) \
{{reg_l, pola_l, pos_l, len_l}, {reg_r, pola_r, pos_r, len_r}}
mixer_ent mix_devices[32][2] = { /* As used in GUS MAX */
MIX_ENT(SOUND_MIXER_VOLUME, 0, 0, 0, 0, 0, 0, 0, 0),
MIX_ENT(SOUND_MIXER_BASS, 0, 0, 0, 0, 0, 0, 0, 0),
MIX_ENT(SOUND_MIXER_TREBLE, 0, 0, 0, 0, 0, 0, 0, 0),
MIX_ENT(SOUND_MIXER_SYNTH, 4, 1, 0, 5, 5, 1, 0, 5),
MIX_ENT(SOUND_MIXER_PCM, 6, 1, 0, 6, 7, 1, 0, 6),
MIX_ENT(SOUND_MIXER_SPEAKER, 26, 1, 0, 4, 0, 0, 0, 0),
MIX_ENT(SOUND_MIXER_LINE, 18, 1, 0, 5, 19, 1, 0, 5),
MIX_ENT(SOUND_MIXER_MIC, 0, 0, 5, 1, 1, 0, 5, 1),
MIX_ENT(SOUND_MIXER_CD, 2, 1, 0, 5, 3, 1, 0, 5),
MIX_ENT(SOUND_MIXER_IMIX, 13, 1, 2, 6, 0, 0, 0, 0),
MIX_ENT(SOUND_MIXER_ALTPCM, 0, 0, 0, 0, 0, 0, 0, 0),
MIX_ENT(SOUND_MIXER_RECLEV, 0, 0, 0, 0, 0, 0, 0, 0),
MIX_ENT(SOUND_MIXER_IGAIN, 0, 0, 0, 4, 1, 0, 0, 4),
MIX_ENT(SOUND_MIXER_OGAIN, 0, 0, 0, 0, 0, 0, 0, 0),
MIX_ENT(SOUND_MIXER_LINE1, 2, 1, 0, 5, 3, 1, 0, 5),
MIX_ENT(SOUND_MIXER_LINE2, 4, 1, 0, 5, 5, 1, 0, 5),
MIX_ENT(SOUND_MIXER_LINE3, 18, 1, 0, 5, 19, 1, 0, 5)
};
static unsigned short default_mixer_levels[SOUND_MIXER_NRDEVICES] =
{
0x5a5a, /* Master Volume */
0x3232, /* Bass */
0x3232, /* Treble */
0x4b4b, /* FM */
0x4040, /* PCM */
0x4b4b, /* PC Speaker */
/* 0x2020, Ext Line */
0x0000, /* Ext Line */
0x4040, /* Mic */
0x4b4b, /* CD */
0x0000, /* Recording monitor */
0x4b4b, /* SB PCM */
0x4b4b, /* Recording level */
0x2525, /* Input gain */
0x0000, /* Output gain */
/* 0x4040, Line1 */
0x0000, /* Line1 */
0x0000, /* Line2 */
0x1515, /* Line3 (usually line in)*/
};
#define LEFT_CHN 0
#define RIGHT_CHN 1

View File

@ -1,46 +0,0 @@
/*
* sound/adlib_card.c
*
* Detection routine for the AdLib card.
*
* Copyright by Hannu Savolainen 1993
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. 2.
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#include <i386/isa/sound/sound_config.h>
#if defined(CONFIG_YM3812)
void
attach_adlib_card(struct address_info * hw_config)
{
opl3_init(hw_config->io_base, hw_config->osp);
}
int
probe_adlib(struct address_info * hw_config)
{
return opl3_detect(hw_config->io_base, hw_config->osp);
}
#endif

View File

@ -1,73 +0,0 @@
static unsigned char alaw_linear[] = {
45, 214, 122, 133, 0, 255, 107, 149,
86, 171, 126, 129, 0, 255, 117, 138,
13, 246, 120, 135, 0, 255, 99, 157,
70, 187, 124, 131, 0, 255, 113, 142,
61, 198, 123, 132, 0, 255, 111, 145,
94, 163, 127, 128, 0, 255, 119, 136,
29, 230, 121, 134, 0, 255, 103, 153,
78, 179, 125, 130, 0, 255, 115, 140,
37, 222, 122, 133, 0, 255, 105, 151,
82, 175, 126, 129, 0, 255, 116, 139,
5, 254, 120, 135, 0, 255, 97, 159,
66, 191, 124, 131, 0, 255, 112, 143,
53, 206, 123, 132, 0, 255, 109, 147,
90, 167, 127, 128, 0, 255, 118, 137,
21, 238, 121, 134, 0, 255, 101, 155,
74, 183, 125, 130, 0, 255, 114, 141,
49, 210, 123, 133, 0, 255, 108, 148,
88, 169, 127, 129, 0, 255, 118, 138,
17, 242, 121, 135, 0, 255, 100, 156,
72, 185, 125, 131, 0, 255, 114, 142,
64, 194, 124, 132, 0, 255, 112, 144,
96, 161, 128, 128, 1, 255, 120, 136,
33, 226, 122, 134, 0, 255, 104, 152,
80, 177, 126, 130, 0, 255, 116, 140,
41, 218, 122, 133, 0, 255, 106, 150,
84, 173, 126, 129, 0, 255, 117, 139,
9, 250, 120, 135, 0, 255, 98, 158,
68, 189, 124, 131, 0, 255, 113, 143,
57, 202, 123, 132, 0, 255, 110, 146,
92, 165, 127, 128, 0, 255, 119, 137,
25, 234, 121, 134, 0, 255, 102, 154,
76, 181, 125, 130, 0, 255, 115, 141,
};
#ifndef LINEAR_ALAW_NOT_WANTED
static unsigned char linear_alaw[] = {
252, 172, 172, 172, 172, 80, 80, 80,
80, 208, 208, 208, 208, 16, 16, 16,
16, 144, 144, 144, 144, 112, 112, 112,
112, 240, 240, 240, 240, 48, 48, 48,
48, 176, 176, 176, 176, 64, 64, 64,
64, 192, 192, 192, 192, 0, 0, 0,
0, 128, 128, 128, 128, 96, 96, 96,
96, 224, 224, 224, 224, 32, 32, 32,
160, 160, 88, 88, 216, 216, 24, 24,
152, 152, 120, 120, 248, 248, 56, 56,
184, 184, 72, 72, 200, 200, 8, 8,
136, 136, 104, 104, 232, 232, 40, 40,
168, 86, 214, 22, 150, 118, 246, 54,
182, 70, 198, 6, 134, 102, 230, 38,
166, 222, 158, 254, 190, 206, 142, 238,
210, 242, 194, 226, 218, 250, 202, 234,
235, 203, 251, 219, 227, 195, 243, 211,
175, 239, 143, 207, 191, 255, 159, 223,
167, 39, 231, 103, 135, 7, 199, 71,
183, 55, 247, 119, 151, 23, 215, 87,
87, 169, 169, 41, 41, 233, 233, 105,
105, 137, 137, 9, 9, 201, 201, 73,
73, 185, 185, 57, 57, 249, 249, 121,
121, 153, 153, 25, 25, 217, 217, 89,
89, 89, 161, 161, 161, 161, 33, 33,
33, 33, 225, 225, 225, 225, 97, 97,
97, 97, 129, 129, 129, 129, 1, 1,
1, 1, 193, 193, 193, 193, 65, 65,
65, 65, 177, 177, 177, 177, 49, 49,
49, 49, 241, 241, 241, 241, 113, 113,
113, 113, 145, 145, 145, 145, 17, 17,
17, 17, 209, 209, 209, 209, 81, 253,
};
#endif /* !LINEAR_ALAW_NOT_WANTED */

View File

@ -1,467 +0,0 @@
/*
* sound/audio.c
*
* Device file manager for /dev/audio
*
* Copyright by Hannu Savolainen 1993
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. 2.
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#include <i386/isa/sound/sound_config.h>
#ifdef CONFIG_AUDIO
#include <i386/isa/sound/ulaw.h>
#include <i386/isa/sound/coproc.h>
#define ON 1
#define OFF 0
int
DMAbuf_poll(int dev, struct fileinfo * file, int events, select_table * wait);
int
audio_poll(int dev, struct fileinfo * file, int events, select_table * wait);
static int wr_buff_no[MAX_AUDIO_DEV];
/* != -1, if there is a incomplete output block in the queue. */
static int wr_buff_size[MAX_AUDIO_DEV], wr_buff_ptr[MAX_AUDIO_DEV];
static int audio_mode[MAX_AUDIO_DEV];
static int dev_nblock[MAX_AUDIO_DEV]; /* 1 if in noblocking mode */
#define AM_NONE 0
#define AM_WRITE 1
#define AM_READ 2
static char *wr_dma_buf[MAX_AUDIO_DEV];
static int audio_format[MAX_AUDIO_DEV];
static int local_conversion[MAX_AUDIO_DEV];
#if defined(NO_INLINE_ASM) || !defined(__i386__)
static void
translate_bytes(const u_char *table, u_char *buff, int n);
#else
extern __inline void
translate_bytes(const void *table, void *buff, int n);
#endif
static int
set_format(int dev, int fmt)
{
if (fmt != AFMT_QUERY) {
local_conversion[dev] = 0;
if (!(audio_devs[dev]->format_mask & fmt)) /* Not supported */
if (fmt == AFMT_MU_LAW) {
fmt = AFMT_U8;
local_conversion[dev] = AFMT_MU_LAW;
} else
fmt = AFMT_U8; /* This is always supported */
audio_format[dev] = DMAbuf_ioctl(dev, SNDCTL_DSP_SETFMT,
(ioctl_arg) fmt, 1);
}
if (local_conversion[dev]) /* This shadows the HW format */
return local_conversion[dev];
return audio_format[dev];
}
int
audio_open(int dev, struct fileinfo * file)
{
int ret;
int bits;
int dev_type = dev & 0x0f;
int mode = file->mode & O_ACCMODE;
dev = dev >> 4;
bits = (dev_type == SND_DEV_DSP16) ? 16 : 8 ;
if ((ret = DMAbuf_open(dev, mode)) < 0)
return ret;
if (audio_devs[dev]->coproc)
if ((ret = audio_devs[dev]->coproc->
open(audio_devs[dev]->coproc->devc, COPR_PCM)) < 0) {
audio_release(dev, file);
printf("Sound: Can't access coprocessor device\n");
return ret;
}
local_conversion[dev] = 0;
if (DMAbuf_ioctl(dev, SNDCTL_DSP_SETFMT, (ioctl_arg) bits, 1) != bits) {
audio_release(dev, file);
return -(ENXIO);
}
set_format(dev, (dev_type == SND_DEV_AUDIO) ? AFMT_MU_LAW : bits ) ;
wr_buff_no[dev] = -1;
audio_mode[dev] = AM_NONE;
wr_buff_size[dev] = wr_buff_ptr[dev] = 0;
dev_nblock[dev] = 0;
return ret;
}
void
audio_release(int dev, struct fileinfo * file)
{
int mode;
dev = dev >> 4;
mode = file->mode & O_ACCMODE;
if (wr_buff_no[dev] >= 0) {
DMAbuf_start_output(dev, wr_buff_no[dev], wr_buff_ptr[dev]);
wr_buff_no[dev] = -1;
}
if (audio_devs[dev]->coproc)
audio_devs[dev]->coproc->close(audio_devs[dev]->coproc->devc,COPR_PCM);
DMAbuf_release(dev, mode);
audio_devs[dev]->dmap_out->mapping_flags &= ~DMA_MAP_MAPPED ;
}
#if defined(NO_INLINE_ASM) || !defined(__i386__)
static void
translate_bytes(const u_char *table, u_char *buff, int n)
{
u_long i;
if (n <= 0)
return;
for (i = 0; i < n; ++i)
buff[i] = table[buff[i]];
}
#else
extern __inline void
translate_bytes(const void *table, void *buff, int n)
{
if (n > 0) {
__asm__("cld\n"
"1:\tlodsb\n\t"
"xlatb\n\t"
"stosb\n\t"
"loop 1b\n\t":
:"b"(table), "c"(n), "D"(buff), "S"(buff)
:"bx", "cx", "di", "si", "ax");
}
}
#endif
int
audio_write(int dev, struct fileinfo * file, snd_rw_buf * buf, int count)
{
int c, p, l;
int err;
dev = dev >> 4;
p = 0;
c = count;
if ((audio_mode[dev] & AM_READ) &&
!(audio_devs[dev]->flags & DMA_DUPLEX)) { /* Direction change */
wr_buff_no[dev] = -1;
}
if (audio_devs[dev]->flags & DMA_DUPLEX)
audio_mode[dev] |= AM_WRITE;
else
audio_mode[dev] = AM_WRITE;
if (!count) { /* Flush output */
if (wr_buff_no[dev] >= 0) {
DMAbuf_start_output(dev, wr_buff_no[dev], wr_buff_ptr[dev]);
wr_buff_no[dev] = -1;
}
return 0;
}
while (c) { /* Perform output blocking */
if (wr_buff_no[dev] < 0) {
/* There is no incomplete buffers */
if ((wr_buff_no[dev] = DMAbuf_getwrbuffer(dev,
&wr_dma_buf[dev], &wr_buff_size[dev],
dev_nblock[dev])) < 0) {
/* Handle nonblocking mode */
if (dev_nblock[dev] && wr_buff_no[dev] == -(EAGAIN))
return p; /* No more space. Return # of accepted bytes */
return wr_buff_no[dev];
}
wr_buff_ptr[dev] = 0;
}
l = c;
if (l > (wr_buff_size[dev] - wr_buff_ptr[dev]))
l = (wr_buff_size[dev] - wr_buff_ptr[dev]);
if (!audio_devs[dev]->copy_from_user) { /* No device specific
* copy routine */
if (uiomove(&wr_dma_buf[dev][wr_buff_ptr[dev]], l, buf)) {
printf("sb: Bad copyin()!\n");
};
} else
audio_devs[dev]->copy_from_user(dev,
wr_dma_buf[dev], wr_buff_ptr[dev], buf, p, l);
/*
* Insert local processing here
*/
if (local_conversion[dev] == AFMT_MU_LAW) {
translate_bytes(ulaw_dsp,
(u_char *) &wr_dma_buf[dev][wr_buff_ptr[dev]], l);
}
c -= l;
p += l;
wr_buff_ptr[dev] += l;
if (wr_buff_ptr[dev] >= wr_buff_size[dev]) {
if ((err = DMAbuf_start_output(dev, wr_buff_no[dev],
wr_buff_ptr[dev])) < 0) {
return err;
}
wr_buff_no[dev] = -1;
}
}
return count;
}
int
audio_read(int dev, struct fileinfo * file, snd_rw_buf * buf, int count)
{
int c, p, l;
char *dmabuf;
int buff_no;
dev = dev >> 4;
p = 0;
c = count;
if ((audio_mode[dev] & AM_WRITE) &&
!(audio_devs[dev]->flags & DMA_DUPLEX)) {
if (wr_buff_no[dev] >= 0) {
DMAbuf_start_output(dev, wr_buff_no[dev], wr_buff_ptr[dev]);
if (!(audio_devs[dev]->flags & DMA_DUPLEX))
wr_buff_no[dev] = -1;
}
}
if (audio_devs[dev]->flags & DMA_DUPLEX)
audio_mode[dev] |= AM_READ;
else
audio_mode[dev] = AM_READ;
while (c) {
if ((buff_no = DMAbuf_getrdbuffer(dev, &dmabuf, &l,
dev_nblock[dev])) < 0) {
/*
* Nonblocking mode handling. Return current # of bytes
*/
if (dev_nblock[dev] && buff_no == -(EAGAIN))
return p;
return buff_no;
}
if (l > c)
l = c;
/*
* Insert any local processing here.
*/
if (local_conversion[dev] == AFMT_MU_LAW) {
translate_bytes(dsp_ulaw, (u_char *) dmabuf, l);
}
if (uiomove(dmabuf, l, buf)) {
printf("sb: Bad copyout()!\n");
};
DMAbuf_rmchars(dev, buff_no, l);
p += l;
c -= l;
}
return count - c;
}
int
audio_ioctl(int dev, struct fileinfo * file, u_int cmd, ioctl_arg arg)
{
dev = dev >> 4;
if (((cmd >> 8) & 0xff) == 'C') {
if (audio_devs[dev]->coproc) /* Coprocessor ioctl */
return audio_devs[dev]->coproc->ioctl(audio_devs[dev]->coproc->devc, cmd, arg, 0);
else
printf("/dev/dsp%d: No coprocessor for this device\n", dev);
return -(ENXIO);
} else
switch (cmd) {
case SNDCTL_DSP_SYNC:
if (wr_buff_no[dev] >= 0) {
DMAbuf_start_output(dev, wr_buff_no[dev], wr_buff_ptr[dev]);
wr_buff_no[dev] = -1;
}
return DMAbuf_ioctl(dev, cmd, arg, 0);
break;
case SNDCTL_DSP_POST:
if (wr_buff_no[dev] >= 0) {
DMAbuf_start_output(dev, wr_buff_no[dev], wr_buff_ptr[dev]);
wr_buff_no[dev] = -1;
}
return 0;
break;
case SNDCTL_DSP_RESET:
wr_buff_no[dev] = -1;
audio_mode[dev] = AM_NONE;
return DMAbuf_ioctl(dev, cmd, arg, 0);
break;
case SNDCTL_DSP_GETFMTS:
return *(int *) arg = audio_devs[dev]->format_mask;
break;
case SNDCTL_DSP_SETFMT:
return *(int *) arg = set_format(dev, (*(int *) arg));
case SNDCTL_DSP_GETISPACE:
if ((audio_mode[dev] & AM_WRITE) &&
!(audio_devs[dev]->flags & DMA_DUPLEX))
return -(EBUSY);
else {
audio_buf_info info;
int err = DMAbuf_ioctl(dev, cmd, (ioctl_arg) & info, 1);
if (err < 0)
return err;
bcopy((char *) &info, &(((char *) arg)[0]), sizeof(info));
return 0;
}
case SNDCTL_DSP_GETOSPACE:
if ((audio_mode[dev] & AM_READ) &&
!(audio_devs[dev]->flags & DMA_DUPLEX))
return -(EBUSY);
else {
audio_buf_info info;
int err = DMAbuf_ioctl(dev, cmd, (ioctl_arg) & info, 1);
if (err < 0)
return err;
if (wr_buff_no[dev] != -1)
info.bytes += wr_buff_size[dev] - wr_buff_ptr[dev];
bcopy((char *) &info, &(((char *) arg)[0]), sizeof(info));
return 0;
}
case SNDCTL_DSP_NONBLOCK:
dev_nblock[dev] = 1;
return 0;
break;
case SNDCTL_DSP_GETCAPS:
{
int info = 1; /* Revision level of this ioctl() */
if (audio_devs[dev]->flags & DMA_DUPLEX)
info |= DSP_CAP_DUPLEX;
if (audio_devs[dev]->coproc)
info |= DSP_CAP_COPROC;
if (audio_devs[dev]->local_qlen) /* Dev. has hidden buffs */
info |= DSP_CAP_BATCH;
if (audio_devs[dev]->trigger) /* Supports SETTRIGGER */
info |= DSP_CAP_TRIGGER;
info |= DSP_CAP_MMAP;
bcopy((char *) &info, &(((char *) arg)[0]), sizeof(info));
return 0;
}
break;
case FIOASYNC:
return *(int *) arg = 1;
case FIONBIO:
return *(int *) arg = 1;
default:
return DMAbuf_ioctl(dev, cmd, arg, 0);
}
}
#ifdef ALLOW_POLL
/*
* XXX should we use spltty() in the select calls ? - lr970714
*
*/
int
audio_poll(int dev, struct fileinfo * file, int events, select_table * wait)
{
dev = dev >> 4;
if (events & (POLLIN | POLLRDNORM)) {
if ((audio_mode[dev] & AM_WRITE) &&
!(audio_devs[dev]->flags & DMA_DUPLEX))
return 0; /* Not recording */
return (DMAbuf_poll(dev, file, events, wait));
}
if (events & (POLLOUT | POLLWRNORM)) {
if ((audio_mode[dev] & AM_READ) &&
!(audio_devs[dev]->flags & DMA_DUPLEX))
return 0; /* Wrong direction */
if (wr_buff_no[dev] != -1)
return 1; /* There is space in the current buffer */
return ( DMAbuf_poll(dev, file, events, wait) );
}
return 0;
}
#endif /* ALLOW_POLL */
#endif

View File

@ -1,12 +0,0 @@
/*
* Definitions for various on board processors on the soundcards. For
* example DSP processors.
*/
/*
* Coprocessor access types
*/
#define COPR_CUSTOM 0x0001 /* Custom applications */
#define COPR_MIDI 0x0002 /* MIDI (MPU-401) emulation */
#define COPR_PCM 0x0004 /* Digitized voice applications */
#define COPR_SYNTH 0x0008 /* Music synthesis */

View File

@ -1,204 +0,0 @@
/*
* sound/cs4232.c
*
* The low level driver for Crystal CS4232 based cards. The CS4232 is a PnP
* compatible chip which contains a CS4231A codec, SB emulation, a MPU401
* compatible MIDI port, joystick and synthesizer and IDE CD-ROM interfaces.
* This is just a temporary driver until full PnP support gets inplemented.
* Just the WSS codec, FM synth and the MIDI ports are supported. Other
* interfaces are left uninitialized.
*
* Copyright by Hannu Savolainen 1995
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. 2.
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#include <i386/isa/sound/sound_config.h>
#if defined(CONFIG_CS4232)
#define KEY_PORT 0x279 /* Same as LPT1 status port */
#define CSN_NUM 0x99 /* Just a random number */
#define CS_OUT(a) outb( KEY_PORT, a)
#define CS_OUT2(a, b) {CS_OUT(a);CS_OUT(b);}
#define CS_OUT3(a, b, c) {CS_OUT(a);CS_OUT(b);CS_OUT(c);}
static int mpu_base = 0, mpu_irq = 0;
static int mpu_detected = 0;
int
probe_cs4232_mpu(struct address_info * hw_config)
{
/*
* Just write down the config values.
*/
mpu_base = hw_config->io_base;
mpu_irq = hw_config->irq;
return 0;
}
void
attach_cs4232_mpu(struct address_info * hw_config)
{
}
static unsigned char crystal_key[] = /* A 32 byte magic key sequence */
{
0x96, 0x35, 0x9a, 0xcd, 0xe6, 0xf3, 0x79, 0xbc,
0x5e, 0xaf, 0x57, 0x2b, 0x15, 0x8a, 0xc5, 0xe2,
0xf1, 0xf8, 0x7c, 0x3e, 0x9f, 0x4f, 0x27, 0x13,
0x09, 0x84, 0x42, 0xa1, 0xd0, 0x68, 0x34, 0x1a
};
int
probe_cs4232(struct address_info * hw_config)
{
int i;
int base = hw_config->io_base, irq = hw_config->irq;
int dma1 = hw_config->dma, dma2 = hw_config->dma2;
/*
* Verify that the I/O port range is free.
*/
if (0) {
printf("cs4232.c: I/O port 0x%03x not free\n", base);
return 0;
}
/*
* This version of the driver doesn't use the PnP method when
* configuring the card but a simplified method defined by Crystal.
* This means that just one CS4232 compatible device can exist on the
* system. Also this method conflicts with possible PnP support in
* the OS. For this reason driver is just a temporary kludge.
*/
/*
* Wake up the card by sending a 32 byte Crystal key to the key port.
*/
for (i = 0; i < 32; i++)
CS_OUT(crystal_key[i]);
/*
* Now set the CSN (Card Select Number).
*/
CS_OUT2(0x06, CSN_NUM);
/*
* Ensure that there is no other codec using the same address.
*/
CS_OUT2(0x15, 0x00); /* Select logical device 0 (WSS/SB/FM) */
CS_OUT2(0x33, 0x00); /* Inactivate logical dev 0 */
/*
* Then set some config bytes. First logical device 0
*/
CS_OUT2(0x15, 0x00); /* Select logical device 0 (WSS/SB/FM) */
CS_OUT3(0x47, (base >> 8) & 0xff, base & 0xff); /* WSSbase */
if (0) /* Not free */
CS_OUT3(0x48, 0x00, 0x00) /* FMbase off */
else
CS_OUT3(0x48, 0x03, 0x88); /* FMbase 0x388 */
CS_OUT3(0x42, 0x00, 0x00); /* SBbase off */
CS_OUT2(0x22, irq); /* SB+WSS IRQ */
CS_OUT2(0x2a, dma1); /* SB+WSS DMA */
if (dma2 != -1)
CS_OUT2(0x25, dma2) /* WSS DMA2 */
else
CS_OUT2(0x25, 4); /* No WSS DMA2 */
CS_OUT2(0x33, 0x01); /* Activate logical dev 0 */
/*
* Initialize logical device 3 (MPU)
*/
#if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI)
if (mpu_base != 0 && mpu_irq != 0) {
CS_OUT2(0x15, 0x03); /* Select logical device 3 (MPU) */
CS_OUT3(0x47, (mpu_base >> 8) & 0xff, mpu_base & 0xff); /* MPUbase */
CS_OUT2(0x22, mpu_irq); /* MPU IRQ */
CS_OUT2(0x33, 0x01); /* Activate logical dev 3 */
}
#endif
/*
* Finally activate the chip
*/
CS_OUT(0x79);
/*
* Then try to detect the codec part of the chip
*/
return ad1848_detect(hw_config->io_base, NULL, hw_config->osp);
}
void
attach_cs4232(struct address_info * hw_config)
{
int base = hw_config->io_base, irq = hw_config->irq;
int dma1 = hw_config->dma, dma2 = hw_config->dma2;
if (dma2 == -1)
dma2 = dma1;
ad1848_init("CS4232", base,
irq,
dma1, /* Playback DMA */
dma2, /* Capture DMA */
0,
hw_config->osp);
#if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI)
if (mpu_base != 0 && mpu_irq != 0) {
static struct address_info hw_config2 =
{0}; /* Ensure it's initialized */
hw_config2.io_base = mpu_base;
hw_config2.irq = mpu_irq;
hw_config2.dma = -1;
hw_config2.dma2 = -1;
hw_config2.always_detect = 0;
hw_config2.name = NULL;
hw_config2.card_subtype = 0;
hw_config2.osp = hw_config->osp;
if (probe_mpu401(&hw_config2)) {
mpu_detected = 1;
attach_mpu401(&hw_config2);
} else {
mpu_base = mpu_irq = 0;
}
}
#endif
}
#endif

View File

@ -1,303 +0,0 @@
/*
* sound/dev_table.c
*
* Device call tables.
*
* Copyright by Hannu Savolainen 1993
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
* 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.
*
*/
#define _DEV_TABLE_C_
#include <i386/isa/sound/sound_config.h>
#if NSND > 0
int sound_started = 0;
int sndtable_get_cardcount(void);
int snd_find_driver(int type);
static void sndtable_init(void);
int sndtable_probe(int unit, struct address_info * hw_config);
int sndtable_init_card(int unit, struct address_info * hw_config);
static int sndtable_identify_card(char *name);
static void sound_chconf(int card_type, int ioaddr, int irq, int dma);
static void start_services(void);
static void start_cards(void);
struct address_info *sound_getconf(int card_type);
int
snd_find_driver(int type)
{
int i, n = num_sound_drivers;
for (i = 0; i < n; i++)
if (sound_drivers[i].card_type == type)
return i;
return -1;
}
static void
start_services()
{
int soundcards_installed;
if (!(soundcards_installed = sndtable_get_cardcount()))
return ; /* No cards detected */
#ifdef CONFIG_AUDIO
if (num_audiodevs) /* Audio devices present */
DMAbuf_init();
#endif
#ifdef CONFIG_MIDI
if (num_midis)
/* MIDIbuf_init(0) */;
#endif
#ifdef CONFIG_SEQUENCER
if (num_midis + num_synths)
sequencer_init();
#endif
}
static void
start_cards()
{
int drv, i, n = num_sound_cards;
struct card_info *ci = snd_installed_cards ;
sound_started = 1;
if (trace_init)
printf("Sound initialization started\n");
/*
* Check the number of cards actually defined in the table
*/
for (i = 0; i < n && snd_installed_cards[i].card_type; i++)
num_sound_cards = i + 1;
for (i = 0; i < n && ci->card_type; ci++, i++)
if (ci->enabled) {
if ((drv = snd_find_driver(ci->card_type)) == -1) {
ci->enabled = 0; /* Mark as not detected */
continue;
}
ci->config.card_subtype = sound_drivers[drv].card_subtype;
if (sound_drivers[drv].probe(&(ci->config)))
sound_drivers[drv].attach(&(ci->config));
else
ci->enabled = 0; /* Mark as not detected */
}
if (trace_init)
printf("Sound initialization complete\n");
}
static void
sndtable_init()
{
start_cards();
}
/*
* sndtable_probe probes a specific device. unit is the voxware unit number.
*/
int
sndtable_probe(int unit, struct address_info * hw_config)
{
int i, sel = -1, n = num_sound_cards;
struct card_info *ci = snd_installed_cards ;
DDB(printf("-- sndtable_probe(%d)\n", unit));
/*
* for some reason unit 0 always succeeds ?
*/
if (!unit)
return TRUE;
sound_started = 1;
for (i=0; i<n && sel== -1 && ci->card_type; ci++, i++)
if ( (ci->enabled) && (ci->card_type == unit) ) {
/* DDB(printf("-- found card %d\n", i) ); */
sel = i; /* and break */
}
/*
* not found. Creates a new entry in the table for this unit.
*/
if (sel == -1 && num_sound_cards < max_sound_cards) {
int i;
i = sel = (num_sound_cards++);
DDB(printf("-- installing card %d\n", i) );
ci = &snd_installed_cards[sel] ;
ci->card_type = unit;
ci->enabled = 1;
}
/* DDB(printf("-- installed card %d\n", sel) ); */
if (sel != -1) {
int drv;
ci->config.io_base = hw_config->io_base;
ci->config.irq = hw_config->irq;
ci->config.dma = hw_config->dma;
ci->config.dma2 = hw_config->dma2;
ci->config.name = hw_config->name;
ci->config.always_detect = hw_config->always_detect;
ci->config.card_subtype = hw_config->card_subtype;
ci->config.osp = hw_config->osp;
if ((drv = snd_find_driver(ci->card_type)) == -1) {
ci->enabled = 0;
DDB(printf("Failed to find driver\n"));
return FALSE;
}
DDB(printf("-- Driver name '%s' probe 0x%08x\n",
sound_drivers[drv].name, sound_drivers[drv].probe));
hw_config->card_subtype =
ci->config.card_subtype = sound_drivers[drv].card_subtype;
if (sound_drivers[drv].probe(hw_config)) {
DDB(printf("-- Hardware probed OK\n"));
return TRUE;
}
DDB(printf("-- Failed to find hardware\n"));
ci->enabled = 0; /* mark as not detected */
return FALSE;
}
return FALSE;
}
int
sndtable_init_card(int unit, struct address_info * hw_config)
{
int i, n = num_sound_cards;
struct card_info *ci = snd_installed_cards ;
DDB(printf("sndtable_init_card(%d) entered\n", unit));
if (!unit) {
sndtable_init() ;
return TRUE;
}
for (i = 0; i < n && ci->card_type; ci++, i++)
if (ci->card_type == unit) {
int drv;
ci->config.io_base = hw_config->io_base;
ci->config.irq = hw_config->irq;
ci->config.dma = hw_config->dma;
ci->config.dma2 = hw_config->dma2;
ci->config.name = hw_config->name;
ci->config.always_detect = hw_config->always_detect;
ci->config.card_subtype = hw_config->card_subtype;
ci->config.osp = hw_config->osp;
if ((drv = snd_find_driver(ci->card_type)) == -1)
ci->enabled = 0; /* Mark not fnd */
else {
DDB(printf("Located card - calling attach routine\n"));
sound_drivers[drv].attach(hw_config) ;
DDB(printf("attach routine finished\n"));
}
start_services();
return TRUE;
}
DDB(printf("sndtable_init_card: No card defined with type=%d, num cards: %d\n",
unit, num_sound_cards));
return FALSE;
}
int
sndtable_get_cardcount(void)
{
return num_audiodevs + num_mixers + num_synths + num_midis;
}
static int
sndtable_identify_card(char *name)
{
int i, n = num_sound_drivers;
if (name == NULL)
return 0;
for (i = 0; i < n; i++)
if (sound_drivers[i].driver_id != NULL) {
char *id = sound_drivers[i].driver_id;
int j;
for (j = 0; j < 80 && name[j] == id[j]; j++)
if (id[j] == 0 && name[j] == 0) /* Match */
return sound_drivers[i].card_type;
}
return 0;
}
static void
sound_chconf(int card_type, int ioaddr, int irq, int dma)
{
int j, ptr = -1, n = num_sound_cards;
for (j = 0; j < n && ptr == -1 && snd_installed_cards[j].card_type; j++)
if (snd_installed_cards[j].card_type == card_type &&
!snd_installed_cards[j].enabled) /* Not already found */
ptr = j;
if (ptr != -1) {
snd_installed_cards[ptr].enabled = 1;
if (ioaddr)
snd_installed_cards[ptr].config.io_base = ioaddr;
if (irq)
snd_installed_cards[ptr].config.irq = irq;
if (dma)
snd_installed_cards[ptr].config.dma = dma;
snd_installed_cards[ptr].config.dma2 = -1;
}
}
struct address_info *
sound_getconf(int card_type)
{
int j, ptr = -1, n = num_sound_cards;
for (j = 0; j < n && ptr == -1 && snd_installed_cards[j].card_type; j++)
if (snd_installed_cards[j].card_type == card_type)
ptr = j;
if (ptr == -1)
return (struct address_info *) NULL;
return &snd_installed_cards[ptr].config;
}
#endif

View File

@ -1,594 +0,0 @@
/*
* dev_table.h
*
* Global definitions for device call tables
*
* Copyright by Hannu Savolainen 1993
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. 2.
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#ifndef _DEV_TABLE_H_
#define _DEV_TABLE_H_
/*
* NOTE! NOTE! NOTE! NOTE!
*
* If you modify this file, please check the dev_table.c also.
*
* NOTE! NOTE! NOTE! NOTE!
*/
extern int sound_started;
struct driver_info {
char *driver_id;
int card_subtype; /* Driver specific. Usually 0 */
int card_type; /* From soundcard.h */
char *name;
void (*attach) (struct address_info * hw_config);
int (*probe) (struct address_info * hw_config);
};
struct card_info {
int card_type; /* Link (search key) to the driver list */
struct address_info config;
int enabled;
};
typedef struct pnp_sounddev {
int id;
void (*setup) (void *dev);
char *driver_name;
} pnp_sounddev;
/*
* Device specific parameters (used only by dmabuf.c)
*/
#define MAX_SUB_BUFFERS (32*MAX_REALTIME_FACTOR)
#define DMODE_NONE 0
#define DMODE_OUTPUT 1
#define DMODE_INPUT 2
struct dma_buffparms {
int dma_mode; /* DMODE_INPUT, DMODE_OUTPUT or DMODE_NONE */
char *raw_buf; /* Pointers to raw buffers */
u_long raw_buf_phys;
/*
* Device state tables
*/
u_long flags;
#define DMA_BUSY 0x00000001
#define DMA_RESTART 0x00000002
#define DMA_ACTIVE 0x00000004
#define DMA_STARTED 0x00000008
#define DMA_ALLOC_DONE 0x00000020
int open_mode;
/*
* Queue parameters.
*/
int qlen;
int qhead;
int qtail;
int nbufs;
int counts[MAX_SUB_BUFFERS];
int subdivision;
int fragment_size;
int max_fragments;
int bytes_in_use;
int underrun_count;
int byte_counter;
int mapping_flags;
#define DMA_MAP_MAPPED 0x00000001
char neutral_byte;
int dma_chan;
};
/*
* Structure for use with various microcontrollers and DSP processors in the
* recent soundcards.
*/
typedef struct coproc_operations {
char name[32];
int (*open) (void *devc, int sub_device);
void (*close) (void *devc, int sub_device);
int (*ioctl) (void *devc, u_int cmd, ioctl_arg arg, int local);
void (*reset) (void *devc);
void *devc; /* Driver specific info */
} coproc_operations;
struct audio_operations {
char name[32];
int flags;
#define NOTHING_SPECIAL 0
#define NEEDS_RESTART 1
#define DMA_AUTOMODE 2
#define DMA_DUPLEX 4
int format_mask; /* Bitmask for supported audio formats */
void *devc; /* Driver specific info */
int (*open) (int dev, int mode);
void (*close) (int dev);
void (*output_block) (int dev, unsigned long buf,
int count, int intrflag, int dma_restart);
void (*start_input) (int dev, unsigned long buf,
int count, int intrflag, int dma_restart);
int (*ioctl) (int dev, u_int cmd, ioctl_arg arg, int local);
int (*prepare_for_input) (int dev, int bufsize, int nbufs);
int (*prepare_for_output) (int dev, int bufsize, int nbufs);
void (*reset) (int dev);
void (*halt_xfer) (int dev);
int (*local_qlen) (int dev);
void (*copy_from_user) (int dev, char *localbuf, int localoffs,
snd_rw_buf * userbuf, int useroffs, int len);
void (*halt_input) (int dev);
void (*halt_output) (int dev);
void (*trigger) (int dev, int bits);
long buffsize;
int dmachan1, dmachan2;
struct dma_buffparms *dmap_in, *dmap_out;
struct coproc_operations *coproc;
int mixer_dev;
int enable_bits;
int open_mode;
int go;
int otherside;
int busy;
};
struct mixer_operations {
char name[32];
int (*ioctl) (int dev, unsigned int cmd, ioctl_arg arg);
};
struct synth_operations {
struct synth_info *info;
int midi_dev;
int synth_type;
int synth_subtype;
int (*open) (int dev, int mode);
void (*close) (int dev);
int (*ioctl) (int dev, unsigned int cmd, ioctl_arg arg);
int (*kill_note) (int dev, int voice, int note, int velocity);
int (*start_note) (int dev, int voice, int note, int velocity);
int (*set_instr) (int dev, int voice, int instr);
void (*reset) (int dev);
void (*hw_control) (int dev, unsigned char *event);
int (*load_patch) (int dev, int format, snd_rw_buf * addr,
int offs, int count, int pmgr_flag);
void (*aftertouch) (int dev, int voice, int pressure);
void (*controller) (int dev, int voice, int ctrl_num, int value);
void (*panning) (int dev, int voice, int value);
void (*volume_method) (int dev, int mode);
int (*pmgr_interface) (int dev, struct patmgr_info * info);
void (*bender) (int dev, int chn, int value);
int (*alloc_voice) (int dev, int chn, int note, struct voice_alloc_info * alloc);
void (*setup_voice) (int dev, int voice, int chn);
int (*send_sysex) (int dev, unsigned char *bytes, int len);
struct voice_alloc_info alloc;
struct channel_info chn_info[16];
};
struct midi_input_info { /* MIDI input scanner variables */
#define MI_MAX 10
int m_busy;
unsigned char m_buf[MI_MAX];
unsigned char m_prev_status; /* For running status */
int m_ptr;
#define MST_INIT 0
#define MST_DATA 1
#define MST_SYSEX 2
int m_state;
int m_left;
};
struct midi_operations {
struct midi_info info;
struct synth_operations *converter;
struct midi_input_info in_info;
int (*open) (int dev, int mode,
void (*inputintr) (int dev, unsigned char data),
void (*outputintr) (int dev) );
void (*close) (int dev);
int (*ioctl) (int dev, unsigned int cmd, ioctl_arg arg);
int (*putc) (int dev, unsigned char data);
int (*start_read) (int dev);
int (*end_read) (int dev);
void (*kick) (int dev);
int (*command) (int dev, unsigned char *data);
int (*buffer_status) (int dev);
int (*prefix_cmd) (int dev, unsigned char status);
struct coproc_operations *coproc;
};
struct sound_lowlev_timer {
int dev;
u_int (*tmr_start) (int dev, unsigned int usecs);
void (*tmr_disable) (int dev);
void (*tmr_restart) (int dev);
};
struct sound_timer_operations {
struct sound_timer_info info;
int priority;
int devlink;
int (*open) (int dev, int mode);
void (*close) (int dev);
int (*event) (int dev, unsigned char *ev);
u_long (*get_time) (int dev);
int (*ioctl) (int dev, unsigned int cmd, ioctl_arg arg);
void (*arm_timer) (int dev, long time);
};
#ifdef _DEV_TABLE_C_
struct audio_operations *audio_devs[MAX_AUDIO_DEV] = {NULL};
int num_audiodevs = 0;
struct mixer_operations *mixer_devs[MAX_MIXER_DEV] = {NULL};
int num_mixers = 0;
struct synth_operations *synth_devs[MAX_SYNTH_DEV + MAX_MIDI_DEV] = {NULL};
int num_synths = 0;
struct midi_operations *midi_devs[MAX_MIDI_DEV] = {NULL};
int num_midis = 0;
#ifdef CONFIG_SEQUENCER
extern struct sound_timer_operations default_sound_timer;
struct sound_timer_operations *sound_timer_devs[MAX_TIMER_DEV] =
{&default_sound_timer, NULL};
int num_sound_timers = 1;
#else
struct sound_timer_operations *sound_timer_devs[MAX_TIMER_DEV] = {NULL};
int num_sound_timers = 0;
#endif
/*
* List of low level drivers compiled into the kernel.
*
* remember, each entry contains:
char *driver_id;
int card_subtype; (Driver specific. Usually 0)
int card_type; (From soundcard.h)
char *name;
void (*attach) (struct address_info * hw_config);
int (*probe) (struct address_info * hw_config);
*
*/
struct driver_info sound_drivers[] = {
#ifdef CONFIG_PSS
{"PSSECHO", 0, SNDCARD_PSS, "Echo Personal Sound System PSS (ESC614)",
attach_pss, probe_pss},
{"PSSMPU", 0, SNDCARD_PSS_MPU, "PSS-MPU",
attach_pss_mpu, probe_pss_mpu},
{"PSSMSS", 0, SNDCARD_PSS_MSS, "PSS-MSS",
attach_pss_mss, probe_pss_mss},
#endif
#ifdef CONFIG_MSS
/* XXX changed type from 0 to 1 -lr 970705 */
{"MSS", 1, SNDCARD_MSS, "MS Sound System",
attach_mss, probe_mss},
/* MSS without IRQ/DMA config registers (for DEC Alphas) */
{"PCXBJ", 1, SNDCARD_PSEUDO_MSS, "MS Sound System (AXP)",
attach_mss, probe_mss},
#endif
#ifdef CONFIG_MAD16
{"MAD16", 0, SNDCARD_MAD16, "MAD16/Mozart (MSS)",
attach_mad16, probe_mad16},
{"MAD16MPU", 0, SNDCARD_MAD16_MPU, "MAD16/Mozart (MPU)",
attach_mad16_mpu, probe_mad16_mpu},
#endif
#ifdef CONFIG_CS4232
{"CS4232", 0, SNDCARD_CS4232, "CS4232",
attach_cs4232, probe_cs4232},
{"CS4232MPU", 0, SNDCARD_CS4232_MPU, "CS4232 MIDI",
attach_cs4232_mpu, probe_cs4232_mpu},
#endif
#ifdef CONFIG_YM3812
{"OPL3", 0, SNDCARD_ADLIB, "OPL-2/OPL-3 FM",
attach_adlib_card, probe_adlib},
#endif
#ifdef CONFIG_PAS
{"PAS16", 0, SNDCARD_PAS, "ProAudioSpectrum",
attach_pas_card, probe_pas},
#endif
#if defined(CONFIG_MPU401) && defined(CONFIG_MIDI)
{"MPU401", 0, SNDCARD_MPU401, "Roland MPU-401",
attach_mpu401, probe_mpu401},
#endif
#if defined(CONFIG_MAUI)
{"MAUI", 0, SNDCARD_MAUI, "TB Maui",
attach_maui, probe_maui},
#endif
#if defined(CONFIG_UART6850) && defined(CONFIG_MIDI)
{"MIDI6850", 0, SNDCARD_UART6850, "6860 UART Midi",
attach_uart6850, probe_uart6850},
#endif
#ifdef CONFIG_SB
{"SBLAST", 0, SNDCARD_SB, "SoundBlaster",
attach_sb_card, probe_sb},
#endif
#if defined(CONFIG_SB) && defined(CONFIG_SB16)
#ifdef CONFIG_AUDIO
{"SB16", 0, SNDCARD_SB16, "SoundBlaster16",
sb16_dsp_init, sb16_dsp_detect},
#endif
#ifdef CONFIG_AWE32
{"AWE32", 0, SNDCARD_AWE32, "AWE32 Synth",
attach_awe, probe_awe},
#endif
#ifdef CONFIG_MIDI
{"SB16MIDI", 0, SNDCARD_SB16MIDI, "SB16 MIDI",
attach_sb16midi, probe_sb16midi},
#endif
#endif
#ifdef CONFIG_GUS16
{"GUS16", 0, SNDCARD_GUS16, "Ultrasound 16-bit opt.",
attach_gus_db16, probe_gus_db16},
#endif
#ifdef CONFIG_GUS
{"GUS", 0, SNDCARD_GUS, "Gravis Ultrasound",
attach_gus_card, probe_gus},
#endif
#ifdef CONFIG_SSCAPE
{"SSCAPE", 0, SNDCARD_SSCAPE, "Ensoniq Soundscape",
attach_sscape, probe_sscape},
{"SSCAPEMSS", 0, SNDCARD_SSCAPE_MSS, "MS Sound System (SoundScape)",
attach_ss_mss, probe_ss_mss},
#endif
#if NTRIX > 0
{"TRXPRO", 0, SNDCARD_TRXPRO, "MediaTriX AudioTriX Pro",
attach_trix_wss, probe_trix_wss},
{"TRXPROSB", 0, SNDCARD_TRXPRO_SB, "AudioTriX (SB mode)",
attach_trix_sb, probe_trix_sb},
{"TRXPROMPU", 0, SNDCARD_TRXPRO_MPU, "AudioTriX MIDI",
attach_trix_mpu, probe_trix_mpu},
#endif
#ifdef CONFIG_PNP
{"AD1848", 0, 500, "PnP MSS",
attach_pnp_ad1848, probe_pnp_ad1848},
#endif
{NULL, 0, 0, "*?*", NULL, NULL}
};
int num_sound_drivers =
sizeof(sound_drivers) / sizeof(struct driver_info);
int max_sound_drivers =
sizeof(sound_drivers) / sizeof(struct driver_info);
#define FULL_SOUND
#ifndef FULL_SOUND
/*
* List of devices actually configured in the system.
*
* Note! The detection order is significant. Don't change it.
*
* remember, the list contains
*
* int card_type; (Link (search key) to the driver list)
* struct address_info config;
* io_base, irq, dma, dma2,
* always_detect, char *name, struct... *osp
* int enabled;
* void *for_driver_use;
*
*/
struct card_info snd_installed_cards[] = {
#ifdef CONFIG_PSS
{SNDCARD_PSS, {PSS_BASE, 0, -1, -1}, SND_DEFAULT_ENABLE},
#ifdef PSS_MPU_BASE
{SNDCARD_PSS_MPU, {PSS_MPU_BASE, PSS_MPU_IRQ, 0, -1}, SND_DEFAULT_ENABLE},
#endif
#ifdef PSS_MSS_BASE
{SNDCARD_PSS_MSS, {PSS_MSS_BASE, PSS_MSS_IRQ, PSS_MSS_DMA, -1}, SND_DEFAULT_ENABLE},
#endif
#endif /* config PSS */
#if NTRIX > 0
{SNDCARD_TRXPRO, {TRIX_BASE, TRIX_IRQ, TRIX_DMA, TRIX_DMA2}, SND_DEFAULT_ENABLE},
#ifdef TRIX_SB_BASE
{SNDCARD_TRXPRO_SB, {TRIX_SB_BASE, TRIX_SB_IRQ, TRIX_SB_DMA, -1}, SND_DEFAULT_ENABLE},
#endif
#ifdef TRIX_MPU_BASE
{SNDCARD_TRXPRO_MPU, {TRIX_MPU_BASE, TRIX_MPU_IRQ, 0, -1}, SND_DEFAULT_ENABLE},
#endif
#endif /* NTRIX > 0 */
#ifdef CONFIG_SSCAPE
{SNDCARD_SSCAPE, {SSCAPE_BASE, SSCAPE_IRQ, SSCAPE_DMA, -1}, SND_DEFAULT_ENABLE},
{SNDCARD_SSCAPE_MSS, {SSCAPE_MSS_BASE, SSCAPE_MSS_IRQ, SSCAPE_MSS_DMA, -1}, SND_DEFAULT_ENABLE},
#endif
#ifdef CONFIG_MAD16
{SNDCARD_MAD16, {MAD16_BASE, MAD16_IRQ, MAD16_DMA, MAD16_DMA2}, SND_DEFAULT_ENABLE},
#ifdef MAD16_MPU_BASE
{SNDCARD_MAD16_MPU, {MAD16_MPU_BASE, MAD16_MPU_IRQ, 0, -1}, SND_DEFAULT_ENABLE},
#endif
#endif /* CONFIG_MAD16 */
#ifdef CONFIG_CS4232
#ifdef CS4232_MPU_BASE
{SNDCARD_CS4232_MPU, {CS4232_MPU_BASE, CS4232_MPU_IRQ, 0, -1}, SND_DEFAULT_ENABLE},
#endif
{SNDCARD_CS4232, {CS4232_BASE, CS4232_IRQ, CS4232_DMA, CS4232_DMA2}, SND_DEFAULT_ENABLE},
#endif
#ifdef CONFIG_MSS
#ifdef PSEUDO_MSS
{SNDCARD_MSS, {MSS_BASE, MSS_IRQ, MSS_DMA, -1}, SND_DEFAULT_ENABLE},
#else
{SNDCARD_PSEUDO_MSS, {MSS_BASE, MSS_IRQ, MSS_DMA, -1}, SND_DEFAULT_ENABLE},
#endif
#ifdef MSS2_BASE
{SNDCARD_MSS, {MSS2_BASE, MSS2_IRQ, MSS2_DMA, -1}, SND_DEFAULT_ENABLE},
#endif
#endif /* CONFIG_MSS */
#ifdef CONFIG_PAS
{SNDCARD_PAS, {PAS_BASE, PAS_IRQ, PAS_DMA, -1}, SND_DEFAULT_ENABLE},
#endif
#ifdef CONFIG_SB
#ifndef SBC_DMA
#define SBC_DMA 1
#endif
{SNDCARD_SB, {SBC_BASE, SBC_IRQ, SBC_DMA, -1}, SND_DEFAULT_ENABLE},
#endif
#if defined(CONFIG_MAUI)
{SNDCARD_MAUI, {MAUI_BASE, MAUI_IRQ, 0, -1}, SND_DEFAULT_ENABLE},
#endif
#if defined(CONFIG_MPU401) && defined(CONFIG_MIDI)
{SNDCARD_MPU401, {MPU_BASE, MPU_IRQ, 0, -1}, SND_DEFAULT_ENABLE},
#ifdef MPU2_BASE
{SNDCARD_MPU401, {MPU2_BASE, MPU2_IRQ, 0, -1}, SND_DEFAULT_ENABLE},
#endif
#ifdef MPU3_BASE
{SNDCARD_MPU401, {MPU3_BASE, MPU2_IRQ, 0, -1}, SND_DEFAULT_ENABLE},
#endif
#endif
#if defined(CONFIG_UART6850) && defined(CONFIG_MIDI)
{SNDCARD_UART6850, {U6850_BASE, U6850_IRQ, 0, -1}, SND_DEFAULT_ENABLE},
#endif
#if defined(CONFIG_SB) && defined(CONFIG_SB16)
#ifdef CONFIG_AUDIO
{SNDCARD_SB16, {SBC_BASE, SBC_IRQ, SB16_DMA, -1}, SND_DEFAULT_ENABLE},
#endif
#ifdef CONFIG_MIDI
{SNDCARD_SB16MIDI, {SB16MIDI_BASE, SBC_IRQ, 0, -1}, SND_DEFAULT_ENABLE},
#endif
#ifdef CONFIG_AWE32
{SNDCARD_AWE32,{AWE32_BASE, 0, 0, -1}, SND_DEFAULT_ENABLE},
#endif
#endif
#ifdef CONFIG_GUS
#ifdef CONFIG_GUS16
{SNDCARD_GUS16, {GUS16_BASE, GUS16_IRQ, GUS16_DMA, -1}, SND_DEFAULT_ENABLE},
#endif
{SNDCARD_GUS, {GUS_BASE, GUS_IRQ, GUS_DMA, GUS_DMA2}, SND_DEFAULT_ENABLE},
#endif
#ifdef CONFIG_YM3812
{SNDCARD_ADLIB, {FM_MONO, 0, 0, -1}, SND_DEFAULT_ENABLE},
#endif
/* Define some expansion space */
{0, {0}, 0},
{0, {0}, 0},
{0, {0}, 0},
{0, {0}, 0},
{0, {0}, 0}
};
int num_sound_cards = sizeof(snd_installed_cards) / sizeof(struct card_info);
int max_sound_cards = sizeof(snd_installed_cards) / sizeof(struct card_info);
#else
int num_sound_cards = 0;
struct card_info snd_installed_cards[20] = {{0}};
int max_sound_cards = 20;
#endif
#ifdef MODULE
int trace_init = 0;
#else
int trace_init = 1;
#endif
#else
extern struct audio_operations *audio_devs[MAX_AUDIO_DEV];
extern int num_audiodevs;
extern struct mixer_operations *mixer_devs[MAX_MIXER_DEV];
extern int num_mixers;
extern struct synth_operations *synth_devs[MAX_SYNTH_DEV + MAX_MIDI_DEV];
extern int num_synths;
extern struct midi_operations *midi_devs[MAX_MIDI_DEV];
extern int num_midis;
extern struct sound_timer_operations *sound_timer_devs[MAX_TIMER_DEV];
extern int num_sound_timers;
extern struct driver_info sound_drivers[];
extern int num_sound_drivers;
extern int max_sound_drivers;
extern struct card_info snd_installed_cards[];
extern int num_sound_cards;
extern int max_sound_cards;
extern int trace_init;
void sndtable_init(void);
int sndtable_get_cardcount(void);
struct address_info *sound_getconf(int card_type);
void sound_chconf(int card_type, int ioaddr, int irq, int dma);
int snd_find_driver(int type);
int sndtable_identify_card(char *name);
void sound_setup(char *str, int *ints);
int sound_alloc_dmap(int dev, struct dma_buffparms * dmap, int chan);
void sound_free_dmap(int dev, struct dma_buffparms * dmap);
extern int soud_map_buffer(int dev, struct dma_buffparms * dmap, buffmem_desc * info);
void install_pnp_sounddrv(struct pnp_sounddev * drv);
int sndtable_probe(int unit, struct address_info * hw_config);
int sndtable_init_card(int unit, struct address_info * hw_config);
void sound_timer_init(struct sound_lowlev_timer * t, char *name);
int
sound_start_dma(int dev, struct dma_buffparms * dmap, int chan,
unsigned long physaddr,
int count, int dma_mode, int autoinit);
void sound_dma_intr(int dev, struct dma_buffparms * dmap, int chan);
#endif /* _DEV_TABLE_C_ */
#endif /* _DEV_TABLE_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -1,49 +0,0 @@
#ifdef SEQUENCER_C
/*
* Copyright by Hannu Savolainen 1993
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
unsigned short finetune_table[128] =
{
/* 0 */ 9439, 9447, 9456, 9464, 9473, 9481, 9490, 9499,
/* 8 */ 9507, 9516, 9524, 9533, 9542, 9550, 9559, 9567,
/* 16 */ 9576, 9585, 9593, 9602, 9611, 9619, 9628, 9637,
/* 24 */ 9645, 9654, 9663, 9672, 9680, 9689, 9698, 9707,
/* 32 */ 9715, 9724, 9733, 9742, 9750, 9759, 9768, 9777,
/* 40 */ 9786, 9795, 9803, 9812, 9821, 9830, 9839, 9848,
/* 48 */ 9857, 9866, 9874, 9883, 9892, 9901, 9910, 9919,
/* 56 */ 9928, 9937, 9946, 9955, 9964, 9973, 9982, 9991,
/* 64 */ 10000, 10009, 10018, 10027, 10036, 10045, 10054, 10063,
/* 72 */ 10072, 10082, 10091, 10100, 10109, 10118, 10127, 10136,
/* 80 */ 10145, 10155, 10164, 10173, 10182, 10191, 10201, 10210,
/* 88 */ 10219, 10228, 10237, 10247, 10256, 10265, 10274, 10284,
/* 96 */ 10293, 10302, 10312, 10321, 10330, 10340, 10349, 10358,
/* 104 */ 10368, 10377, 10386, 10396, 10405, 10415, 10424, 10433,
/* 112 */ 10443, 10452, 10462, 10471, 10481, 10490, 10499, 10509,
/* 120 */ 10518, 10528, 10537, 10547, 10556, 10566, 10576, 10585
};
#else
extern unsigned short finetune_table[128];
#endif

View File

@ -1,188 +0,0 @@
/*
* sound/gus_card.c
*
* Detection routine for the Gravis Ultrasound.
*
* Copyright by Hannu Savolainen 1993
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. 2.
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#include <i386/isa/sound/sound_config.h>
#if defined(CONFIG_GUS)
#include <i386/isa/sound/gus_hw.h>
#include <i386/isa/sound/iwdefs.h>
int gus_base, gus_irq, gus_dma;
extern int gus_wave_volume;
extern int gus_pcm_volume;
extern int have_gus_max;
extern int gus_timer_enabled;
static sound_os_info *gus_osp;
#ifndef NOGUSPNP
int IwaveOpen(char voices, char mode, struct address_info * hw);
#endif
void
attach_gus_card(struct address_info * hw_config)
{
int io_addr;
gus_osp = hw_config->osp;
snd_set_irq_handler(hw_config->irq, gusintr, hw_config->osp);
if (gus_wave_detect(hw_config->io_base)) {
/* Try first the default */
gus_wave_init(hw_config);
/* 0x10c-> is MAX */
if (hw_config->dma2 != -1 && hw_config->dma2 != hw_config->dma)
if (0)
printf("gus_card.c: Can't allocate DMA channel2\n");
#ifdef CONFIG_MIDI
gus_midi_init();
#endif
return ;
}
#ifndef EXCLUDE_GUS_IODETECT
/*
* Look at the possible base addresses (0x2X0, X=1, 2, 3, 4, 5, 6)
*/
for (io_addr = 0x210; io_addr <= 0x260; io_addr += 0x10)
if ( (io_addr != hw_config->io_base) /* Already tested */
&& (gus_wave_detect(io_addr)) ) {
hw_config->io_base = io_addr;
printf(" WARNING! GUS found at %x, config was %x ",
io_addr, hw_config->io_base);
gus_wave_init(hw_config);
/* 0x10c-> is MAX */
if (hw_config->dma2 != -1 && hw_config->dma2 != hw_config->dma)
if (0)
printf("gus_card.c: Can't allocate DMA channel2\n");
#ifdef CONFIG_MIDI
gus_midi_init();
#endif
return ;
}
#endif
}
int
probe_gus(struct address_info * hw_config)
{
int io_addr;
gus_osp = hw_config->osp;
#ifndef NOGUSPNP
IwaveOpen((char) 32, (char) GUS_MODE, hw_config);
#endif
if (gus_wave_detect(hw_config->io_base))
return 1;
printf("oops I didnt find gus \n");
#undef EXCLUDE_GUS_IODETECT
#ifndef EXCLUDE_GUS_IODETECT
/*
* Look at the possible base addresses (0x2X0, X=1, 2, 3, 4, 5, 6)
*/
for (io_addr = 0x210; io_addr <= 0x260; io_addr += 0x10)
if ( (io_addr != hw_config->io_base) /* Already tested */
&& (gus_wave_detect(io_addr)) ) {
hw_config->io_base = io_addr;
return 1;
}
#endif
return 0;
}
void
gusintr(int irq)
{
u_char src;
#ifdef CONFIG_GUSMAX
if (have_gus_max)
ad1848_interrupt(irq);
#endif
for (;;) {
if (!(src = inb(u_IrqStatus)))
return;
if (src & DMA_TC_IRQ)
guswave_dma_irq();
#ifdef CONFIG_MIDI
if (src & (MIDI_TX_IRQ | MIDI_RX_IRQ))
gus_midi_interrupt(0);
#endif
if (src & (GF1_TIMER1_IRQ | GF1_TIMER2_IRQ)) {
#ifdef CONFIG_SEQUENCER
if (gus_timer_enabled)
sound_timer_interrupt();
gus_write8(0x45, 0); /* Ack IRQ */
gus_timer_command(4, 0x80); /* Reset IRQ flags */
#else
gus_write8(0x45, 0); /* Stop timers */
#endif
}
if (src & (WAVETABLE_IRQ | ENVELOPE_IRQ))
gus_voice_irq();
}
}
#endif
/*
* Some extra code for the 16 bit sampling option
*/
#if defined(CONFIG_GUS16)
int
probe_gus_db16(struct address_info * hw_config)
{
return ad1848_detect(hw_config->io_base, NULL, hw_config->osp);
}
void
attach_gus_db16(struct address_info * hw_config)
{
gus_pcm_volume = 100;
gus_wave_volume = 90;
ad1848_init("GUS 16 bit sampling", hw_config->io_base,
hw_config->irq,
hw_config->dma,
hw_config->dma, 0,
hw_config->osp);
}
#endif

View File

@ -1,50 +0,0 @@
/*
* I/O addresses
*/
#define u_Base (gus_base + 0x000)
#define u_Mixer u_Base
#define u_Status (gus_base + 0x006)
#define u_TimerControl (gus_base + 0x008)
#define u_TimerData (gus_base + 0x009)
#define u_IRQDMAControl (gus_base + 0x00b)
#define u_MidiControl (gus_base + 0x100)
#define MIDI_RESET 0x03
#define MIDI_ENABLE_XMIT 0x20
#define MIDI_ENABLE_RCV 0x80
#define u_MidiStatus u_MidiControl
#define MIDI_RCV_FULL 0x01
#define MIDI_XMIT_EMPTY 0x02
#define MIDI_FRAME_ERR 0x10
#define MIDI_OVERRUN 0x20
#define MIDI_IRQ_PEND 0x80
#define u_MidiData (gus_base + 0x101)
#define u_Voice (gus_base + 0x102)
#define u_Command (gus_base + 0x103)
#define u_DataLo (gus_base + 0x104)
#define u_DataHi (gus_base + 0x105)
#define u_MixData (gus_base + 0x106) /* Rev. 3.7+ mixing */
#define u_MixSelect (gus_base + 0x506) /* registers. */
#define u_IrqStatus u_Status
# define MIDI_TX_IRQ 0x01 /* pending MIDI xmit IRQ */
# define MIDI_RX_IRQ 0x02 /* pending MIDI recv IRQ */
# define GF1_TIMER1_IRQ 0x04 /* general purpose timer */
# define GF1_TIMER2_IRQ 0x08 /* general purpose timer */
# define WAVETABLE_IRQ 0x20 /* pending wavetable IRQ */
# define ENVELOPE_IRQ 0x40 /* pending volume envelope IRQ */
# define DMA_TC_IRQ 0x80 /* pending dma tc IRQ */
#define ICS2101 1
# define ICS_MIXDEVS 6
# define DEV_MIC 0
# define DEV_LINE 1
# define DEV_CD 2
# define DEV_GF1 3
# define DEV_UNUSED 4
# define DEV_VOL 5
# define CHN_LEFT 0
# define CHN_RIGHT 1
#define CS4231 2
#define u_DRAMIO (gus_base + 0x107)

View File

@ -1,18 +0,0 @@
static unsigned short gus_linearvol[128] = {
0x0000, 0x08ff, 0x09ff, 0x0a80, 0x0aff, 0x0b40, 0x0b80, 0x0bc0,
0x0bff, 0x0c20, 0x0c40, 0x0c60, 0x0c80, 0x0ca0, 0x0cc0, 0x0ce0,
0x0cff, 0x0d10, 0x0d20, 0x0d30, 0x0d40, 0x0d50, 0x0d60, 0x0d70,
0x0d80, 0x0d90, 0x0da0, 0x0db0, 0x0dc0, 0x0dd0, 0x0de0, 0x0df0,
0x0dff, 0x0e08, 0x0e10, 0x0e18, 0x0e20, 0x0e28, 0x0e30, 0x0e38,
0x0e40, 0x0e48, 0x0e50, 0x0e58, 0x0e60, 0x0e68, 0x0e70, 0x0e78,
0x0e80, 0x0e88, 0x0e90, 0x0e98, 0x0ea0, 0x0ea8, 0x0eb0, 0x0eb8,
0x0ec0, 0x0ec8, 0x0ed0, 0x0ed8, 0x0ee0, 0x0ee8, 0x0ef0, 0x0ef8,
0x0eff, 0x0f04, 0x0f08, 0x0f0c, 0x0f10, 0x0f14, 0x0f18, 0x0f1c,
0x0f20, 0x0f24, 0x0f28, 0x0f2c, 0x0f30, 0x0f34, 0x0f38, 0x0f3c,
0x0f40, 0x0f44, 0x0f48, 0x0f4c, 0x0f50, 0x0f54, 0x0f58, 0x0f5c,
0x0f60, 0x0f64, 0x0f68, 0x0f6c, 0x0f70, 0x0f74, 0x0f78, 0x0f7c,
0x0f80, 0x0f84, 0x0f88, 0x0f8c, 0x0f90, 0x0f94, 0x0f98, 0x0f9c,
0x0fa0, 0x0fa4, 0x0fa8, 0x0fac, 0x0fb0, 0x0fb4, 0x0fb8, 0x0fbc,
0x0fc0, 0x0fc4, 0x0fc8, 0x0fcc, 0x0fd0, 0x0fd4, 0x0fd8, 0x0fdc,
0x0fe0, 0x0fe4, 0x0fe8, 0x0fec, 0x0ff0, 0x0ff4, 0x0ff8, 0x0ffc
};

View File

@ -1,274 +0,0 @@
/*
* sound/gus2_midi.c
*
* The low level driver for the GUS Midi Interface.
*
* Copyright by Hannu Savolainen 1993
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. 2.
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#include <i386/isa/sound/sound_config.h>
#if defined(CONFIG_GUS) && defined(CONFIG_MIDI)
#include <i386/isa/sound/gus_hw.h>
static int midi_busy = 0, input_opened = 0;
static int my_dev;
static int output_used = 0;
static volatile unsigned char gus_midi_control;
static void (*midi_input_intr) (int dev, unsigned char data);
static unsigned char tmp_queue[256];
static volatile int qlen;
static volatile unsigned char qhead, qtail;
extern int gus_base, gus_irq, gus_dma;
extern sound_os_info *gus_osp;
#define GUS_MIDI_STATUS() inb( u_MidiStatus)
static int
gus_midi_open(int dev, int mode,
void (*input) (int dev, unsigned char data),
void (*output) (int dev)
)
{
if (midi_busy) {
printf("GUS: Midi busy\n");
return -(EBUSY);
}
outb(u_MidiControl, MIDI_RESET);
gus_delay();
gus_midi_control = 0;
input_opened = 0;
if (mode == OPEN_READ || mode == OPEN_READWRITE) {
gus_midi_control |= MIDI_ENABLE_RCV;
input_opened = 1;
}
if (mode == OPEN_WRITE || mode == OPEN_READWRITE) {
gus_midi_control |= MIDI_ENABLE_XMIT;
}
outb(u_MidiControl, gus_midi_control); /* Enable */
midi_busy = 1;
qlen = qhead = qtail = output_used = 0;
midi_input_intr = input;
return 0;
}
static int
dump_to_midi(unsigned char midi_byte)
{
unsigned long flags;
int ok = 0;
output_used = 1;
flags = splhigh();
if (GUS_MIDI_STATUS() & MIDI_XMIT_EMPTY) {
ok = 1;
outb(u_MidiData, midi_byte);
} else {
/*
* Enable Midi xmit interrupts (again)
*/
gus_midi_control |= MIDI_ENABLE_XMIT;
outb(u_MidiControl, gus_midi_control);
}
splx(flags);
return ok;
}
static void
gus_midi_close(int dev)
{
/*
* Reset FIFO pointers, disable intrs
*/
outb(u_MidiControl, MIDI_RESET);
midi_busy = 0;
}
static int
gus_midi_out(int dev, unsigned char midi_byte)
{
unsigned long flags;
/*
* Drain the local queue first
*/
flags = splhigh();
while (qlen && dump_to_midi(tmp_queue[qhead])) {
qlen--;
qhead++;
}
splx(flags);
/*
* Output the byte if the local queue is empty.
*/
if (!qlen)
if (dump_to_midi(midi_byte))
return 1; /* OK */
/*
* Put to the local queue
*/
if (qlen >= 256)
return 0; /* Local queue full */
flags = splhigh();
tmp_queue[qtail] = midi_byte;
qlen++;
qtail++;
splx(flags);
return 1;
}
static int
gus_midi_start_read(int dev)
{
return 0;
}
static int
gus_midi_end_read(int dev)
{
return 0;
}
static int
gus_midi_ioctl(int dev, unsigned cmd, ioctl_arg arg)
{
return -(EINVAL);
}
static void
gus_midi_kick(int dev)
{
}
static int
gus_midi_buffer_status(int dev)
{
unsigned long flags;
if (!output_used)
return 0;
flags = splhigh();
if (qlen && dump_to_midi(tmp_queue[qhead])) {
qlen--;
qhead++;
}
splx(flags);
return (qlen > 0) | !(GUS_MIDI_STATUS() & MIDI_XMIT_EMPTY);
}
#define MIDI_SYNTH_NAME "Gravis Ultrasound Midi"
#define MIDI_SYNTH_CAPS SYNTH_CAP_INPUT
#include <i386/isa/sound/midi_synth.h>
static struct midi_operations gus_midi_operations =
{
{"Gravis UltraSound Midi", 0, 0, SNDCARD_GUS},
&std_midi_synth,
{0},
gus_midi_open,
gus_midi_close,
gus_midi_ioctl,
gus_midi_out,
gus_midi_start_read,
gus_midi_end_read,
gus_midi_kick,
NULL, /* command */
gus_midi_buffer_status,
NULL
};
void
gus_midi_init()
{
if (num_midis >= MAX_MIDI_DEV) {
printf("Sound: Too many midi devices detected\n");
return;
}
outb(u_MidiControl, MIDI_RESET);
std_midi_synth.midi_dev = my_dev = num_midis;
midi_devs[num_midis++] = &gus_midi_operations;
return;
}
void
gus_midi_interrupt(int dummy)
{
unsigned char stat, data;
unsigned long flags;
flags = splhigh();
stat = GUS_MIDI_STATUS();
if (stat & MIDI_RCV_FULL) {
data = inb(u_MidiData);
if (input_opened)
midi_input_intr(my_dev, data);
}
if (stat & MIDI_XMIT_EMPTY) {
while (qlen && dump_to_midi(tmp_queue[qhead])) {
qlen--;
qhead++;
}
if (!qlen) {
/*
* Disable Midi output interrupts, since no data in
* the buffer
*/
gus_midi_control &= ~MIDI_ENABLE_XMIT;
outb(u_MidiControl, gus_midi_control);
}
}
splx(flags);
}
#endif

View File

@ -1,138 +0,0 @@
/*
* gus_vol.c - Compute volume for GUS.
*
* Greg Lee 1993.
*/
#include <i386/isa/sound/sound_config.h>
#ifdef CONFIG_GUS
#include <i386/isa/sound/gus_linearvol.h>
#define GUS_VOLUME gus_wave_volume
extern int gus_wave_volume;
unsigned short gus_adagio_vol(int vel, int mainv, int xpn, int voicev);
unsigned short gus_linear_vol(int vol, int mainvol);
/*
* Calculate gus volume from note velocity, main volume, expression, and
* intrinsic patch volume given in patch library. Expression is multiplied
* in, so it emphasizes differences in note velocity, while main volume is
* added in -- I don't know whether this is right, but it seems reasonable to
* me. (In the previous stage, main volume controller messages were changed
* to expression controller messages, if they were found to be used for
* dynamic volume adjustments, so here, main volume can be assumed to be
* constant throughout a song.)
*
* Intrinsic patch volume is added in, but if over 64 is also multiplied in, so
* we can give a big boost to very weak voices like nylon guitar and the
* basses. The normal value is 64. Strings are assigned lower values.
*/
unsigned short
gus_adagio_vol(int vel, int mainv, int xpn, int voicev)
{
int i, m, n, x;
/*
* A voice volume of 64 is considered neutral, so adjust the main
* volume if something other than this neutral value was assigned in
* the patch library.
*/
x = 256 + 6 * (voicev - 64);
/*
* Boost expression by voice volume above neutral.
*/
if (voicev > 65)
xpn += voicev - 64;
xpn += (voicev - 64) / 2;
/*
* Combine multiplicative and level components.
*/
x = vel * xpn * 6 + (voicev / 4) * x;
#ifdef GUS_VOLUME
/*
* Further adjustment by installation-specific master volume control
* (default 60).
*/
x = (x * GUS_VOLUME * GUS_VOLUME) / 10000;
#endif
#ifdef GUS_USE_CHN_MAIN_VOLUME
/*
* Experimental support for the channel main volume
*/
mainv = (mainv / 2) + 64; /* Scale to 64 to 127 */
x = (x * mainv * mainv) / 16384;
#endif
if (x < 2)
return (0);
else if (x >= 65535)
return ((15 << 8) | 255);
/*
* Convert to gus's logarithmic form with 4 bit exponent i and 8 bit
* mantissa m.
*/
n = x;
i = 7;
if (n < 128) {
while (i > 0 && n < (1 << i))
i--;
} else
while (n > 255) {
n >>= 1;
i++;
}
/*
* Mantissa is part of linear volume not expressed in exponent.
* (This is not quite like real logs -- I wonder if it's right.)
*/
m = x - (1 << i);
/*
* Adjust mantissa to 8 bits.
*/
if (m > 0) {
if (i > 8)
m >>= i - 8;
else if (i < 8)
m <<= 8 - i;
}
return ((i << 8) + m);
}
/*
* Volume-values are interpreted as linear values. Volume is based on the
* value supplied with SEQ_START_NOTE(), channel main volume (if compiled in)
* and the volume set by the mixer-device (default 60%).
*/
unsigned short
gus_linear_vol(int vol, int mainvol)
{
int mixer_mainvol;
RANGE (vol, 0, 127) ;
#ifdef GUS_VOLUME
mixer_mainvol = GUS_VOLUME;
#else
mixer_mainvol = 100;
#endif
#ifdef GUS_USE_CHN_MAIN_VOLUME
RANGE (mainvol, 0, 127);
#else
mainvol = 127;
#endif
return gus_linearvol[(((vol * mainvol) / 127) * mixer_mainvol) / 100];
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,97 +0,0 @@
/*
* This file is a part of configure.c
*
* hex2hex reads an input file in Intel HEX format and produces
* an (unsigned char) array which contains the bytes and writes it to the
* output file using C syntax
*/
#define MAX_SIZE (256*1024)
#define ABANDON(why) { \
fprintf(stderr, "%s: " why "\n", source); \
fclose(inf);fclose(outf);return 0; \
}
int hex2hex(char *source, char *target, char *varline)
{
FILE *inf, *outf;
int i,l, c;
unsigned char buf[MAX_SIZE];
if ((inf=fopen(source, "r"))==NULL)
{
perror(source);
return 0;
}
if ((outf=fopen(target, "w"))==NULL)
{
perror(target);
fclose(inf);
return 0;
}
l=0;
while ((c=getc(inf))!=EOF)
{
if (c == ':') /* Sync with beginning of line */
{
int n, check;
unsigned char sum;
int addr;
int linetype;
if (fscanf(inf, "%02x", &n) != 1)
ABANDON("File format error");
sum = n;
if (fscanf(inf, "%04x", &addr) != 1)
ABANDON("File format error");
sum += addr/256;
sum += addr%256;
if (fscanf(inf, "%02x", &linetype) != 1)
ABANDON("File format error");
sum += linetype;
if (linetype != 0)
continue;
for (i=0;i<n;i++)
{
if (fscanf(inf, "%02x", &c) != 1)
ABANDON("File format error");
if (addr >= MAX_SIZE)
ABANDON("File too large");
buf[addr++] = c;
if (addr > l)
l = addr;
sum += c;
}
if (fscanf(inf, "%02x", &check) != 1)
ABANDON("File format error");
sum = ~sum + 1;
if (check != sum)
ABANDON("Line checksum error");
}
}
fprintf(outf, "/*\n *\t Computer generated file. Do not edit.\n */\n");
fprintf(outf, "static unsigned char %s[] = {\n", varline);
for (i=0;i<l;i++)
{
if (i) fprintf(outf, ",");
if (i && !(i % 16)) fprintf(outf, "\n");
fprintf(outf, "0x%02x", buf[i]);
}
fprintf(outf, "\n};\n\n");
fclose(inf);
fclose(outf);
return 1;
}

View File

@ -1,233 +0,0 @@
/*
* sound/ics2101.c
*
* Driver for the ICS2101 mixer of GUS v3.7.
*
* Copyright by Hannu Savolainen 1994
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. 2.
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#include <i386/isa/sound/sound_config.h>
#if defined(CONFIG_GUS)
#include <i386/isa/sound/ultrasound.h>
#include <i386/isa/sound/gus_hw.h>
#define MIX_DEVS (SOUND_MASK_MIC|SOUND_MASK_LINE| \
SOUND_MASK_SYNTH| \
SOUND_MASK_CD | SOUND_MASK_VOLUME)
extern sound_os_info *gus_osp;
extern int gus_base;
static int volumes[ICS_MIXDEVS];
static int left_fix[ICS_MIXDEVS] = {1, 1, 1, 2, 1, 2};
static int right_fix[ICS_MIXDEVS] = {2, 2, 2, 1, 2, 1};
static int
scale_vol(int vol)
{
/*
* Experimental volume scaling by Risto Kankkunen. This should give
* smoother volume response than just a plain multiplication.
*/
int e;
RANGE(vol, 0, 100);
vol = (31 * vol + 50) / 100;
e = 0;
if (vol) {
while (vol < 16) {
vol <<= 1;
e--;
}
vol -= 16;
e += 7;
}
return ((e << 4) + vol);
}
static void
write_mix(int dev, int chn, int vol)
{
int *selector;
unsigned long flags;
int ctrl_addr = dev << 3;
int attn_addr = dev << 3;
vol = scale_vol(vol);
if (chn == CHN_LEFT) {
selector = left_fix;
ctrl_addr |= 0x00;
attn_addr |= 0x02;
} else {
selector = right_fix;
ctrl_addr |= 0x01;
attn_addr |= 0x03;
}
flags = splhigh();
outb(u_MixSelect, ctrl_addr);
outb(u_MixData, selector[dev]);
outb(u_MixSelect, attn_addr);
outb(u_MixData, (unsigned char) vol);
splx(flags);
}
static int
set_volumes(int dev, int vol)
{
int left = vol & 0x00ff;
int right = (vol >> 8) & 0x00ff;
RANGE (left, 0, 100);
RANGE (right, 0, 100);
write_mix(dev, CHN_LEFT, left);
write_mix(dev, CHN_RIGHT, right);
vol = left + (right << 8);
volumes[dev] = vol;
return vol;
}
static int
ics2101_mixer_ioctl(int dev, unsigned int cmd, ioctl_arg arg)
{
if (((cmd >> 8) & 0xff) == 'M') {
if (cmd & IOC_IN)
switch (cmd & 0xff) {
case SOUND_MIXER_RECSRC:
return gus_default_mixer_ioctl(dev, cmd, arg);
break;
case SOUND_MIXER_MIC:
return *(int *) arg = set_volumes(DEV_MIC, (*(int *) arg));
break;
case SOUND_MIXER_CD:
return *(int *) arg = set_volumes(DEV_CD, (*(int *) arg));
break;
case SOUND_MIXER_LINE:
return *(int *) arg = set_volumes(DEV_LINE, (*(int *) arg));
break;
case SOUND_MIXER_SYNTH:
return *(int *) arg = set_volumes(DEV_GF1, (*(int *) arg));
break;
case SOUND_MIXER_VOLUME:
return *(int *) arg = set_volumes(DEV_VOL, (*(int *) arg));
break;
default:
return -(EINVAL);
}
else
switch (cmd & 0xff) { /* Return parameters */
case SOUND_MIXER_RECSRC:
return gus_default_mixer_ioctl(dev, cmd, arg);
break;
case SOUND_MIXER_DEVMASK:
return *(int *) arg = MIX_DEVS;
break;
case SOUND_MIXER_STEREODEVS:
return *(int *) arg = SOUND_MASK_LINE | SOUND_MASK_CD |
SOUND_MASK_SYNTH | SOUND_MASK_VOLUME | SOUND_MASK_MIC;
break;
case SOUND_MIXER_RECMASK:
return *(int *) arg = SOUND_MASK_MIC | SOUND_MASK_LINE;
break;
case SOUND_MIXER_CAPS:
return *(int *) arg = 0;
break;
case SOUND_MIXER_MIC:
return *(int *) arg = volumes[DEV_MIC];
break;
case SOUND_MIXER_LINE:
return *(int *) arg = volumes[DEV_LINE];
break;
case SOUND_MIXER_CD:
return *(int *) arg = volumes[DEV_CD];
break;
case SOUND_MIXER_VOLUME:
return *(int *) arg = volumes[DEV_VOL];
break;
case SOUND_MIXER_SYNTH:
return *(int *) arg = volumes[DEV_GF1];
break;
default:
return -(EINVAL);
}
}
return -(EINVAL);
}
static struct mixer_operations ics2101_mixer_operations =
{
"ICS2101 Multimedia Mixer",
ics2101_mixer_ioctl
};
void
ics2101_mixer_init()
{
int i;
if (num_mixers < MAX_MIXER_DEV) {
mixer_devs[num_mixers++] = &ics2101_mixer_operations;
/*
* Some GUS v3.7 cards had some channels flipped. Disable the
* flipping feature if the model id is other than 5.
*/
if (inb(u_MixSelect) != 5) {
for (i = 0; i < ICS_MIXDEVS; i++)
left_fix[i] = 1;
for (i = 0; i < ICS_MIXDEVS; i++)
right_fix[i] = 2;
}
set_volumes(DEV_GF1, 0x5a5a);
set_volumes(DEV_CD, 0x5a5a);
set_volumes(DEV_MIC, 0x0000);
set_volumes(DEV_LINE, 0x5a5a);
set_volumes(DEV_VOL, 0x5a5a);
set_volumes(DEV_UNUSED, 0x0000);
}
}
#endif

View File

@ -1,712 +0,0 @@
/*#######################################################################*/
/* FILE : iwdefs.h*/
/**/
/* REMARKS: This file contains all defines used by DDK functions. It*/
/* should be included by all applications and should be*/
/* referenced by programmers to make their code easy to read*/
/* and understand.*/
/**/
/* UPDATE: 3/21/95*/
/* 7/10/95 --- added #def DRAM_HOLES*/
/*#######################################################################*/
#ifndef IWDEFS
#define IWDEFS
/*#######################################################################*/
/**/
/* Macros for use in loading Synth Addr Regs*/
/**/
/*#######################################################################*/
#define ADDR_HIGH(x) (short)(x>>7)
#define ADDR_LOW(x) (short)(x<<9)
/*#######################################################################*/
/**/
/* Defines for DMA Controllers*/
/**/
/*#######################################################################*/
/* DMA Controler #1 (8-bit controller) */
#define DMA1_STAT 0x08 /* read status register */
#define DMA1_WCMD 0x08 /* write command register */
#define DMA1_WREQ 0x09 /* write request register */
#define DMA1_SNGL 0x0A /* write single bit register */
#define DMA1_MODE 0x0B /* write mode register */
#define DMA1_CLRFF 0x0C /* clear byte ptr flip/flop */
#define DMA1_MCLR 0x0D /* master clear register */
#define DMA1_CLRM 0x0E /* clear mask register */
#define DMA1_WRTALL 0x0F /* write all mask register */
/* DMA Controler #2 (16-bit controller) */
#define DMA2_STAT 0xD0 /* read status register */
#define DMA2_WCMD 0xD0 /* write command register */
#define DMA2_WREQ 0xD2 /* write request register */
#define DMA2_SNGL 0xD4 /* write single bit register */
#define DMA2_MODE 0xD6 /* write mode register */
#define DMA2_CLRFF 0xD8 /* clear byte ptr flip/flop */
#define DMA2_MCLR 0xDA /* master clear register */
#define DMA2_CLRM 0xDC /* clear mask register */
#define DMA2_WRTALL 0xDE /* write all mask register */
#define DMA0_ADDR 0x00 /* chan 0 base adddress */
#define DMA0_CNT 0x01 /* chan 0 base count */
#define DMA1_ADDR 0x02 /* chan 1 base adddress */
#define DMA1_CNT 0x03 /* chan 1 base count */
#define DMA2_ADDR 0x04 /* chan 2 base adddress */
#define DMA2_CNT 0x05 /* chan 2 base count */
#define DMA3_ADDR 0x06 /* chan 3 base adddress */
#define DMA3_CNT 0x07 /* chan 3 base count */
#define DMA4_ADDR 0xC0 /* chan 4 base adddress */
#define DMA4_CNT 0xC2 /* chan 4 base count */
#define DMA5_ADDR 0xC4 /* chan 5 base adddress */
#define DMA5_CNT 0xC6 /* chan 5 base count */
#define DMA6_ADDR 0xC8 /* chan 6 base adddress */
#define DMA6_CNT 0xCA /* chan 6 base count */
#define DMA7_ADDR 0xCC /* chan 7 base adddress */
#define DMA7_CNT 0xCE /* chan 7 base count */
#define DMA0_PAGE 0x87 /* chan 0 page register (refresh)*/
#define DMA1_PAGE 0x83 /* chan 1 page register */
#define DMA2_PAGE 0x81 /* chan 2 page register */
#define DMA3_PAGE 0x82 /* chan 3 page register */
#define DMA4_PAGE 0x8F /* chan 4 page register (unusable)*/
#define DMA5_PAGE 0x8B /* chan 5 page register */
#define DMA6_PAGE 0x89 /* chan 6 page register */
#define DMA7_PAGE 0x8A /* chan 7 page register */
/*#######################################################################*/
/**/
/* Defines for register UISR (Interrupt Status)*/
/**/
/*#######################################################################*/
#define MIDI_TX_IRQ 0x01
#define MIDI_RX_IRQ 0x02
#define ALIB_TIMER1_IRQ 0x04
#define ALIB_TIMER2_IRQ 0x08
#define _UASBCI 0x45 /* UASBCI index */
#define SAMPLE_CONTROL 0x49 /* Not used by IW */
#define SET_VOICES 0x0E
#define WAVETABLE_IRQ 0x20
#define ENVELOPE_IRQ 0x40
#define DMA_TC_IRQ 0x80
/*#######################################################################*/
/**/
/* Synthesizer-related defines*/
/**/
/*#######################################################################*/
#define GEN_INDEX 0x03 /* IGIDX offset into p3xr */
#define VOICE_SELECT 0x02 /* SVSR offset into p3xr */
#define VOICE_IRQS 0x8F /* SVII index (read) */
#define _URSTI 0x4C /* URSTI index */
#define GF1_SET 0x01 /* URSTI[0] */
#define GF1_OUT_ENABLE 0x02 /* URSTI[1] */
#define GF1_IRQ_ENABLE 0x04 /* URSTI[2] */
#define GF1_RESET 0xFE /* URSTI[0]=0 */
#define VOICE_VOLUME_IRQ 0x04 /* SVII[2] */
#define VOICE_WAVE_IRQ 0x08 /* SVII[3] */
#define VC_IRQ_ENABLE 0x20 /* SACI[5] or SVCI[5]*/
#define VOICE_NUMBER 0x1F /* Mask for SVII[4:0] */
#define VC_IRQ_PENDING 0x80 /* SACI[7] or SVCI[7] */
#define VC_DIRECT 0x40 /* SACI[6] or SVCI[6]*/
#define VC_DATA_WIDTH 0x04 /* SACI[2] */
#define VOICE_STOP 0x02 /* SACI[1] */
#define VOICE_STOPPED 0x01 /* SACI[0] */
#define VOLUME_STOP 0x02 /* SVCI[1] */
#define VOLUME_STOPPED 0x01 /* SVCI[0] */
#define VC_ROLLOVER 0x04 /* SVCI[2] */
#define VC_LOOP_ENABLE 0x08 /* SVCI[3] or SACI[3]*/
#define VC_BI_LOOP 0x10 /* SVCI[4] or SACI[4]*/
#define VOICE_OFFSET 0x20 /* SMSI[5] */
#define VOLUME_RATE0 0x00 /* SVRI[7:6]=(0,0) */
#define VOLUME_RATE1 0x40 /* SVRI[7:6]=(0,1) */
#define VOLUME_RATE2 0x80 /* SVRI[7:6]=(1,0) */
#define VOLUME_RATE3 0xC0 /* SVRI[7:6]=(1,1) */
/*#######################################################################*/
/**/
/* Power-Mode Control Defines*/
/**/
/*#######################################################################*/
#define SHUT_DOWN 0x7E /* shuts InterWave down */
#define POWER_UP 0xFE /* enables all modules */
#define CODEC_PWR_UP 0x81 /* enables Codec Analog Ckts */
#define CODEC_PWR_DOWN 0x01 /* disables Codec Analog Ckts */
#define CODEC_REC_UP 0x82 /* Enables Record Path */
#define CODEC_REC_DOWN 0x02 /* Disables Record Path */
#define CODEC_PLAY_UP 0x84 /* Enables Playback Path */
#define CODEC_PLAY_DOWN 0x04 /* Disables Playback Path */
#define CODEC_IRQ_ENABLE 0x02 /* CEXTI[2] */
#define CODEC_TIMER_IRQ 0x40 /* CSR3I[6] */
#define CODEC_REC_IRQ 0x20 /* CSR3I[5] */
#define CODEC_PLAY_IRQ 0x10 /* CSR3I[4] */
#define CODEC_INT 0x01 /* CSR1R[0] */
#define MONO_INPUT 0x80 /* CMONOI[7] */
#define MONO_OUTPUT 0x40 /* CMONOI[6] */
#define MIDI_UP 0x88 /* Enables MIDI ports */
#define MIDI_DOWN 0x08 /* Disables MIDI ports */
#define SYNTH_UP 0x90 /* Enables Synthesizer */
#define SYNTH_DOWN 0x10 /* Disables Synthesizer */
#define LMC_UP 0xA0 /* Enables LM Module */
#define LMC_DOWN 0x20 /* Disbales LM Module */
#define XTAL24_UP 0xC0 /* Enables 24MHz Osc */
#define XTAL24_DOWN 0x40 /* Disables 24MHz Osc */
#define _PPWRI 0xF2 /* PPWRI index */
#define PLAY 0x0F
#define REC 0x1F
#define LEFT_AUX1_INPUT 0x02
#define RIGHT_AUX1_INPUT 0x03
#define LEFT_AUX2_INPUT 0x04
#define RIGHT_AUX2_INPUT 0x05
#define LEFT_LINE_IN 0x12
#define RIGHT_LINE_IN 0x13
#define LEFT_LINE_OUT 0x19
#define RIGHT_LINE_OUT 0x1B
#define LEFT_SOURCE 0x00
#define RIGHT_SOURCE 0x01
#define LINE_IN 0x00
#define AUX1_IN 0x40
#define MIC_IN 0x80
#define MIX_IN 0xC0
#define LEFT_DAC 0x06
#define RIGHT_DAC 0x07
#define LEFT_MIC_IN 0x16
#define RIGHT_MIC_IN 0x17
#define _CUPCTI 0x0E
#define _CLPCTI 0x0F
#define _CURCTI 0x1E
#define _CLRCTI 0x1F
#define _CLAX1I 0x02
#define _CRAX1I 0x03
#define _CLAX2I 0x04
#define _CRAX2I 0x05
#define _CLLICI 0x12
#define _CRLICI 0x13
#define _CLOAI 0x19
#define _CROAI 0x1B
#define _CLICI 0x00
#define _CRICI 0x01
#define _CLDACI 0x06
#define _CRDACI 0x07
#define _CPVFI 0x1D
/*#######################################################################*/
/**/
/* Defines for DMA transfer related operations*/
/**/
/*#######################################################################*/
#define MAX_DMA 0x07
#define DMA_DECREMENT 0x20
#define AUTO_INIT 0x10
#define DMA_READ 0x01
#define DMA_WRITE 0x02
#define AUTO_READ 0x03
#define AUTO_WRITE 0x04
#define IDMA_INV 0x0400
#define IDMA_WIDTH_16 0x0100
/*#######################################################################*/
/**/
/* Bits for dma flags within a DMA structure.*/
/**/
/*#######################################################################*/
#define DMA_USED 0x0001
#define DMA_SPLIT 0x0004 /* DMA Controller Page Crossover*/
#define CODEC_DMA 0x0008 /* Indicates a Codec DMA*/
#define DMA_WAIT 0x0020 /* Wait for DMA xfer to complete*/
#define DMA_DOWN 0x0040 /* DMA xfer from PC to InterWave*/
#define DRAM_HOLES 0x8000 /* Indicates Non-contiguous RAM configuration*/
#define DMA_UP 0xFFBF /* DMA xfer from InterWave to PC */
/*#######################################################################*/
/**/
/* Bits for DMA Control Register (LDMACI)*/
/**/
/*#######################################################################*/
#define _LDMACI 0x41 /* Index */
#define DMA_INV 0x80
#define DMA_IRQ_ENABLE 0x20
#define DMA_IRQ_PENDING 0x40 /* on reads of LDMACI[6] */
#define DMA_DATA_16 0x40 /* on writes to LDMACI[6] */
#define DMA_WIDTH_16 0x04 /* 1=16-bit, 0=8-bit (DMA channel) */
#define DMA_RATE 0x18 /* 00=fastest,...,11=slowest */
#define DMA_UPLOAD 0x02 /* From LM to PC */
#define DMA_ENABLE 0x01
/*#######################################################################*/
/**/
/* DMA Transfer Rates*/
/**/
/*#######################################################################*/
#define DMA_R0 0xE7 /* Fastest (use ANDing to set) */
#define DMA_R1 0x08
#define DMA_R2 0x10
#define DMA_R3 0x18 /* Slowest */
/*#######################################################################*/
/**/
/* Interrupt Controller Defines*/
/**/
/*#######################################################################*/
#define IW_HANDLERS_ON 0x80 /* Flag for when IVT is modified */
#define EOI 0x20
#define OCR1 0x20 /* 8259-1 Operation Control Reg. */
#define IMR1 0x21 /* 8259-1 Interrupt Mask Reg. */
#define OCR2 0xA0 /* 8259-2 Operation Control Reg. */
#define IMR2 0xA1 /* 8259-2 Interrupt Mask Reg. */
#define IRQ0_UNMASK 0xFE /* Mask to clear bit 0 in IMR */
#define IRQ1_UNMASK 0xFD
#define IRQ2_UNMASK 0xFB
#define IRQ3_UNMASK 0xF7
#define IRQ4_UNMASK 0xEF
#define IRQ5_UNMASK 0xDF
#define IRQ6_UNMASK 0xBF
#define IRQ7_UNMASK 0x7F
#define IRQ8_UNMASK 0xFE /* Mask to clear bit 0 in IMR */
#define IRQ9_UNMASK 0xFD
#define IRQ10_UNMASK 0xFB
#define IRQ11_UNMASK 0xF7
#define IRQ12_UNMASK 0xEF
#define IRQ13_UNMASK 0xDF
#define IRQ14_UNMASK 0xBF
#define IRQ15_UNMASK 0x7F
#define IRQ0_EOI 0x60 /* Spec EOI for IRQ0 */
#define IRQ1_EOI 0x61
#define IRQ2_EOI 0x62
#define IRQ3_EOI 0x63
#define IRQ4_EOI 0x64
#define IRQ5_EOI 0x65
#define IRQ6_EOI 0x66
#define IRQ7_EOI 0x67
#define IRQ8_EOI 0x60 /* Spec EOI for IRQ8 */
#define IRQ9_EOI 0x61
#define IRQ10_EOI 0x62
#define IRQ11_EOI 0x63
#define IRQ12_EOI 0x64
#define IRQ13_EOI 0x65
#define IRQ14_EOI 0x66
#define IRQ15_EOI 0x67
/*#######################################################################*/
/**/
/* Generic defines*/
/**/
/*#######################################################################*/
/**/
#define MEMBANK0 0L /* Addr of Memory Bank 0*/
#define MEMBANK1 4194304L /* Addr of Memory Bank 1*/
#define MEMBANK2 8388608L /* Addr of Memory Bank 2*/
#define MEMBANK3 12582912L /* Addr of Memory Bank 3*/
#define IRQ_UNAVAIL 0x0000
#define IRQ_AVAIL 0x0001
#define IRQ_USED 0x0002
#define MAX_IRQ 16
#define NEXT_OFFSET 0L
#define PREV_OFFSET 4L
#define SIZE_OFFSET 8L
#define MEM_HEADER_SIZE 12L
#define GF1_POOL (usigned long)(256L*1024L)
#define GUS_MODE 0x00 /* SGMI[0]=0*/
#define ENH_MODE 0x01 /* SGMI[0]=1*/
#define ENABLE_LFOS 0x02 /* SGMI[1]*/
#define NO_WAVETABLE 0x04 /* SGMI[2]*/
#define RAM_TEST 0x08 /* SGMI[3]*/
#define TRUE 1
#define FALSE 0
#define ON 1
#define OFF 0
#define AUDIO 0
#define EXT 1
#define GAME 2
#define EMULATION 3
#define MPU401 4
#define AUDIO_EXT 2
#define ALLOC_FAILURE 0xFFFFFFFFL
#define MEM_EXHAUSTED 0xFFFFFFFFL
#define RAM_MAX 16777216L
#define RAM_STEP 65536L
#define BANK_MAX 4194304L
#define ILLEGAL_SIZE -1
#define MEM_INIT 1
#define NO_NEXT 0xFFFFFFFFL
#define NO_PREV NO_NEXT
#define DMA_BAD_ADDR -1
#define DMA_ON -1
#define DMA_OK 1
#define MIDI_TX_IRQ 0x01
#define MIDI_RX_IRQ 0x02
#define ALIB_TIMER1_IRQ 0x04
#define ALIB_TIMER2_IRQ 0x08
#define WAVETABLE_IRQ 0x20
#define ENVELOPE_IRQ 0x40
#define DMA_TC_IRQ 0x80
#define DMA_SET_MASK 0x04
#define PNP_DATA_RDY 1 /* PRESSI[0] */
#define IWAVE_ABSENT 2
#define IWAVE_OPEN 4
#define IWAVE_OK 5
#define BAD_VOICES -1
#define PNP_ABSENT 0xFF /* No PNP cards in system */
#define DPMI_INT 0x31
#define _PCCCI 0x02
#define _PCSNI 0x06
#define _PIDXR 0x279
#define _PNPWRP 0xA79
#define _LDSALI 0x42
#define _LDSAHI 0x50
#define _LMALI 0x43
#define _LMAHI 0x44
#define _LMCFI 0x52
#define _LMCI 0x53
#define _LDIBI 0x58
#define _LDICI 0x57
#define _LMSBAI 0x51
#define _SVCI_RD 0x8D
#define _SVCI_WR 0x0D
#define _SACI_RD 0x80
#define _SACI_WR 0x00
#define _SALI_RD 0x8B
#define _SALI_WR 0x0B
#define _SAHI_RD 0x8A
#define _SAHI_WR 0x0A
#define _SASHI_RD 0x82
#define _SASHI_WR 0x02
#define _SASLI_RD 0x83
#define _SASLI_WR 0x03
#define _SAEHI_RD 0x84
#define _SAEHI_WR 0x04
#define _SAELI_RD 0x85
#define _SAELI_WR 0x05
#define _SVRI_RD 0x86
#define _SVRI_WR 0x06
#define _SVSI_RD 0x87
#define _SVSI_WR 0x07
#define _SVEI_RD 0x88
#define _SVEI_WR 0x08
#define _SVLI_RD 0x89
#define _SVLI_WR 0x09
#define _SROI_RD 0x8C
#define _SROI_WR 0x0C
#define _SLOI_RD 0x93
#define _SLOI_WR 0x13
#define _SMSI_RD 0x95
#define _SMSI_WR 0x15
#define _SGMI_RD 0x99
#define _SGMI_WR 0x19
#define _SFCI_RD 0x81
#define _SFCI_WR 0x01
#define _SUAI_RD 0x90
#define _SUAI_WR 0x10
#define _SVII 0x8F
#define _CMODEI 0x0C /* index for CMODEI */
#define _CFIG3I 0x11
#define _CFIG2I 0x10
#define _CLTIMI 0x14
#define _CUTIMI 0x15
#define _CSR3I 0x18 /* Index to CSR3I (Interrupt Status) */
#define _CEXTI 0x0A /* Index to External Control Register */
#define _CFIG1I 0x09 /* Index to Codec Conf Reg 1 */
#define _CSR2I 0x0B /* Index to Codec Stat Reg 2 */
#define _CPDFI 0x08 /* Index to Play Data Format Reg */
#define _CRDFI 0x1C /* Index to Rec Data Format Reg */
#define _CLMICI 0x16 /* Index to Left Mic Input Ctrl Register */
#define _CRMICI 0x17 /* Index to Right Mic Input Ctrl Register */
#define _CLCI 0x0D /* Index to Loopback Ctrl Register */
#define _IVERI 0x5B /* Index to register IVERI */
#define CODEC_MODE1 0x00
#define CODEC_MODE2 0x40
#define CODEC_MODE3 0x6C /* Enhanced Mode */
#define CODEC_STATUS1 0x01
#define CODEC_STATUS2 0x0B /* Index to CSR2I */
#define CODEC_STATUS3 0x18 /* Index to CSR3I */
#define PLAYBACK 0x01 /* Enable playback path CFIG1I[0]=1*/
#define RECORD 0x02 /* Enable Record path CFIG1I[1]=1*/
#define TIMER_ENABLE 0x40 /* CFIG2I[6] */
#define CODEC_MCE 0x40 /* CIDXR[6] */
#define CALIB_IN_PROGRESS 0x20 /* CSR2I[5] */
#define CODEC_INIT 0x80 /* CIDXR[7] */
#define BIT16_BIG 0xC0 /* 16-bit signed, big endian */
#define IMA_ADPCM 0xA0 /* IMA-compliant ADPCM */
#define BIT8_ALAW 0x60 /* 8-bit A-law */
#define BIT16_LITTLE 0x40 /* 16-bit signed, lillte endian */
#define BIT8_ULAW 0x20 /* 8-bit u-law */
#define BIT8_LINEAR 0x00 /* 8-bit unsigned */
#define REC_DFORMAT 0x1C
#define PLAY_DFORMAT 0x08
#define DMA_ACCESS 0x00
#define PIO_ACCESS 0xC0
#define DMA_SIMPLEX 0x04
#define STEREO 0x10 /* CxDFI[4] */
#define XTAL1 0x00 /* CxDFI[4]=0 selects 24.5Mhz XTAL */
#define XTAL2 0x01 /* CxDFI[4]=1 selects 16.9Mhz XTAL */
#define AUTOCALIB 0x08 /* CFIG1I[3] */
#define ROM_IO 0x02 /* ROM I/O cycles - LMCI[1]=1 */
#define DRAM_IO 0x4D /* DRAM I/O cycles - LMCI[1]=0 */
#define AUTOI 0x01 /* LMCI[0]=1 */
#define _PLDNI 0x07
#define ACTIVATE_DEV 0x30
#define _PWAKEI 0x03 /* Index for PWAKEI */
#define _PISOCI 0x01 /* Index for PISOCI */
#define _PSECI 0xF1 /* Index for PSECI */
#define RANGE_IOCHK 0x31 /* PURCI or PRRCI Index */
#define MIDI_RESET 0x03
#define IO_OK 5 /* No IO conflict flag */
#define IO_CONFLICT 6 /* IO Conflict detected */
#define IO_0x55 0x01
#define IO_0xAA 0xFE
/*#######################################################################*/
/**/
/* Defines for Sound Handlers in "iw".*/
/**/
/*#######################################################################*/
#define PLAY_DMA_HANDLER 0x01
#define REC_DMA_HANDLER 0x02
#define MIDI_TX_HANDLER 0x03
#define MIDI_RX_HANDLER 0x04
#define TIMER1_HANDLER 0x05
#define TIMER2_HANDLER 0x06
#define WAVE_HANDLER 0x07
#define VOLUME_HANDLER 0x08
#define CODEC_TIMER_HANDLER 0x09
#define CODEC_PLAY_HANDLER 0x0A
#define CODEC_REC_HANDLER 0x0B
#define AUX_HANDLER 0x0C
/*#######################################################################*/
/**/
/* Mapping for System Control Regs.*/
/**/
/*#######################################################################*/
#define UMCR 0x00010000 /* Mix Control Reg.*/
#define UISR 0x00020006 /* IRQ Stat Reg. (read) */
#define U2X6R 0x00030006 /* SB 2X6 reg */
#define UACWR 0x00040008 /* AdLib Command Write Reg */
#define UASRR 0x00050008 /* AdLib Stat Read Reg */
#define UADR 0x00060009 /* AdLib Data Register */
#define UACRR 0x0007000A /* AdLib Cmd Read Reg */
#define UASWR 0x0008000A /* AdLib Stat Write Reg */
#define UHRDP 0x0009000B /* Hidden Reg Data Port */
#define UI2XCR 0x000A000C /* SB IRQ 2xC Reg */
#define U2XCR 0x000B000D /* SB 2xC Reg. (No IRQ) */
#define U2XER 0x000C000E /* SB 2xE Reg. */
#define URCR 0x000D000F /* Reg Control Register */
#define USRR 0x000E000F /* Status Read Register */
#define UDCI 0x000F000B /* DMA Channel Control Reg */
#define UICI 0x0010000B /* Interrupt Ctrl Reg */
#define UGP1I 0x0011010B /* GP Reg 1 (Back Door) */
#define UGP2I 0x0012020B /* GP Reg 2 (Back Door) */
#define UGPA1I 0x0013030B /* GP reg 1 Address */
#define UGPA2I 0x0014040B /* GP reg 2 Address */
#define UCLRII 0x0015050B /* Clear Interrupt Reg */
#define UJMPI 0x0016060B /* Jumper Register */
#define UGP1II 0x0017000B /* Gen. Purp Reg 1(Emulation) */
#define UGP2II 0x0018000B /* Gen. Purp Reg 2(Emulation) */
#define GGCR 0x00190201 /* Game Control Register */
#define GMCR 0x001A0000 /* MIDI Control Register */
#define GMSR 0x001B0000 /* MIDI Status Reg. */
#define GMTDR 0x001C0001 /* MIDI xmit data reg */
#define GMRDR 0x001D0001 /* MIDI rcv data reg */
#define SVSR 0x001E0002 /* Synth Voice Select Reg */
#define IGIDXR 0x001F0003 /* General Index Register */
#define I16DP 0x00200004 /* General 16-bit Data Port */
#define I8DP 0x00210005 /* General 8-bit Data Port */
/*#######################################################################*/
/**/
/* Synth defines*/
/**/
/*#######################################################################*/
#define SACI 0x00220005 /* Synth Addr Control */
#define SFCI 0x00230104 /* Synth Freq Control */
#define SASHI 0x00240204 /* Synth Addr Start High */
#define SASLI 0x00250304 /* Synth Addr Start Low */
#define SAEHI 0x00260404 /* Synth Addr End High */
#define SAELI 0x00270504 /* Synth Addr End Low */
#define SVRI 0x00280605 /* Synth Volume Rate */
#define SVSI 0x00290705 /* Synth Volume Start */
#define SVEI 0x002A0805 /* Synth Volume End */
#define SVLI 0x002B0904 /* Synth Volume Level */
#define SAHI 0x002C0A04 /* Synth Address High */
#define SALI 0x002D0B04 /* Synth Address Low */
#define SROI 0x002E0C04 /* Synth Right Offset */
#define SVCI 0x002F0D05 /* Synth Volume Control */
#define SAVI 0x00300E05 /* Synth Active Voices */
#define SVII 0x00318F05 /* Synth Voice IRQ */
#define SUAI 0x00321005 /* Synth Upper Addr */
#define SEAHI 0x00331104 /* Synth Effect Addr High */
#define SEALI 0x00341204 /* Synth Effect Addr Low */
#define SLOI 0x00351304 /* Synth Left Offset */
#define SEASI 0x00361405 /* Synth Effects Accum Sel */
#define SMSI 0x00371505 /* Synth Mode Select */
#define SEVI 0x00381604 /* Synth Effect Volume */
#define SFLFOI 0x00391705 /* Synth Freq LFO */
#define SVLFOI 0x003A1805 /* Synth Vol LFO */
#define SGMI 0x003B1905 /* Synth Global Mode */
#define SLFOBI 0x003C1A04 /* Synth LFO Base Address */
#define SROFI 0x003D1B04
#define SLOFI 0x003E1C04
#define SEVFI 0x003F1D04
#define SVIRI 0x00409F05 /* Synth Voice Read IRQ */
#define LDMACI 0x00414105 /* DMA Control Reg. */
#define LDSALI 0x00424204 /* LMC DMA Start Addr. Low Reg. */
#define LMALI 0x00434304 /* LMC Addr Low (I/O) */
#define LMAHI 0x00444405 /* LMC Addr High (I/O) */
#define UASBCI 0x00454505 /* Adlib-SB Control */
#define UAT1I 0x00464605 /* AdLib Timer 1 Count */
#define UAT2I 0x00474705 /* AdLib Timer 2 Count */
#define USCI 0x00484905 /* Sample Control Reg */
#define GJTDI 0x00494B05
#define URSTI 0x004A4C05
#define LDSAHI 0x004B5005
#define LMSBAI 0x004C5104
#define LMCFI 0x004D5204
#define LMCI 0x004E5305
#define LMRFAI 0x004F5404
#define LMPFAI 0x00505504
#define LMSFI 0x00515604
#define LDICI 0x00525704
#define LDIBI 0x00535804
#define ICMPTI 0x00545905
#define IDECI 0x00555A05
#define IVERI 0x00565B05
#define IEMUAI 0x00575C05
#define IEMUBI 0x00585D05
#define GMRFAI 0x00595E05
#define ITCI 0x005A5F05
#define IEIRQI 0x005B6005
#define LMBDR 0x005C0007
/*##########################################################*/
/* Mnemonics for Codec Registers*/
/*##########################################################*/
#define CIDXR 0x005D0000
#define CDATAP 0x005E0001
#define CSR1R 0x005F0002
#define CPDR 0x00600003
#define CRDR 0x00610003
#define CLICI 0x00620001
#define CRICI 0x00630101
#define CLAX1I 0x00640201
#define CRAX1I 0x00650301
#define CLAX2I 0x00660401
#define CRAX2I 0x00670501
#define CLDACI 0x00680601
#define CRDACI 0x00690701
#define CPDFI 0x006A0801
#define CFIG1I 0x006B0901
#define CEXTI 0x006C0A01
#define CSR2I 0x006D0B01
#define CMODEI 0x006E0C01
#define CLCI 0x006F0D01
#define CUPCTI 0x00700E01
#define CLPCTI 0x00710F01
#define CFIG2I 0x00721001
#define CFIG3I 0x00731101
#define CLLICI 0x00741201
#define CRLICI 0x00751301
#define CLTIMI 0x00761401
#define CUTIMI 0x00771501
#define CLMICI 0x00781601
#define CRMICI 0x00791701
#define CSR3I 0x007A1801
#define CLOAI 0x007B1901
#define CMONOI 0x007C1A01
#define CROAI 0x007D1B01
#define CRDFI 0x007E1C01
#define CPVFI 0x007F1D01
#define CURCTI 0x00801E01
#define CLRCTI 0x00811F01
/*##########################################################*/
/* Mnemonics for PnP Registers*/
/*##########################################################*/
#define PCSNBR 0x00820201
#define PIDXR 0x00830279
#define PNPWRP 0x00840A79
#define PNPRDP 0x00850000
#define PSRPAI 0x00860000
#define PISOCI 0x00870100
#define PCCCI 0x00880200
#define PWAKEI 0x00890300
#define PRESDI 0x008A0400
#define PRESSI 0x008B0500
#define PCSNI 0x008C0600
#define PLDNI 0x008D0700
#define PUACTI 0x008E3000
#define PURCI 0x008F3100
#define P2X0HI 0x00906000
#define P2X0LI 0x00916100
#define P3X0HI 0x00926200
#define P3X0LI 0x00936300
#define PHCAI 0x00946400
#define PLCAI 0x00956500
#define PUI1SI 0x00967000
#define PUI1TI 0x00977100
#define PUI2SI 0x00987200
#define PUI2TI 0x00997300
#define PUD1SI 0x009A7400
#define PUD2SI 0x009B7500
#define PSEENI 0x009CF000
#define PSECI 0x009DF100
#define PPWRI 0x009EF200
#define PRACTI 0x009F3001
#define PRRCI 0x00A03101
#define PRAHI 0x00A16001
#define PRALI 0x00A26101
#define PATAHI 0x00A36201
#define PATALI 0x00A46301
#define PRISI 0x00A57001
#define PRITI 0x00A67101
#define PRDSI 0x00A77401
#define PGACTI 0x00A83002
#define PGRCI 0x00A93102
#define P201HI 0x00AA6002
#define P201LI 0x00AB6102
#define PSACTI 0x00AC3003
#define PSRCI 0x00AD3103
#define P388HI 0x00AE6003
#define P388LI 0x00AF6103
#define PSBISI 0x00B07003
#define PSBITI 0x00B17103
#define PMACTI 0x00B23004
#define PMRCI 0x00B33104
#define P401HI 0x00B46004
#define P401LI 0x00B56104
#define PMISI 0x00B67004
#define PMITI 0x00B77104
typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef unsigned short PORT;
typedef unsigned long DWORD;
typedef unsigned long ADDRESS;
typedef int BOOL;
typedef int FLAG;
typedef struct
{
short flags; /* InterWave stat flags */
PORT pcodar; /* Base Port for Codec */
PORT pcdrar; /* Base Port for Ext Device */
PORT p2xr; /* Compatibility Base Port */
PORT p3xr; /* MIDI and Synth Base Port */
PORT p401ar; /* Gen Purpose Reg. 1 address */
PORT p201ar; /* Game Ctrl normally at 0x201 */
PORT pataar; /* Base Address for ATAPI I/O Space */
PORT p388ar; /* Base Port for AdLib. It should be 388h */
PORT pnprdp; /* PNP read data port */
PORT igidxr; /* Gen Index Reg at P3XR+0x03 */
PORT i16dp; /* 16-bit data port at P3XR+0x04 */
PORT i8dp; /* 8-bit data port at P3XR+0x05 */
PORT svsr; /* Synth Voice Select at P3XR+0x02 */
PORT cdatap; /* Codec Indexed Data Port at PCODAR+0x01 */
PORT csr1r; /* Codec Stat Reg 1 at PCODAR+0x02 */
PORT cxdr; /* Play or Record Data Reg at PCODAR+0x03 */
PORT gmxr; /* GMCR or GMSR at P3XR+0x00 */
PORT gmxdr; /* GMTDR or GMRDR at P3XR+0x01 */
PORT lmbdr; /* LMBDR at P3XR+0x07 */
BYTE csn; /* Card Select Number */
BYTE cmode; /* Codec Operation Mode */
int dma1_chan; /* DMA channel 1 (local DMA & codec rec) */
int dma2_chan; /* DMA channel 2 (codec play) */
int ext_chan; /* Ext Dev DMA channel */
BYTE voices; /* Number of active voices */
DWORD vendor; /* Vendor ID and Product Identifier */
int synth_irq; /* Synth IRQ number */
int midi_irq; /* MIDI IRQ number */
int ext_irq; /* Ext Dev IRQ */
int mpu_irq; /* MPU401 Dev IRQ */
int emul_irq; /* Sound Blaster/AdLib Dev IRQ */
ADDRESS free_mem; /* Address of First Free LM Block */
DWORD reserved_mem; /* Amount of LM reserved by app. */
BYTE smode; /* Synth Mode */
WORD size_mem; /* Total LM in Kbytes */
} IWAVE;
#endif

View File

@ -1,188 +0,0 @@
/*
* local.h
*
* This file was generated by configure. But then HAND-EDITED. It will
* probably disappear in future revisions once the configuration process
* will become more like that of standard bsd code.
* lr 970714
*
*/
/* build hex2hex /tmp/foo.x trix_boot.h trix_boot */
/*
* make everything conditioned on NSND>0 so as to detect errors
* because of missing "controller snd0" statement
*/
#define ALLOW_BUFFER_MAPPING 1
#include "snd.h"
#if NSND > 0
#include "opt_sound.h"
#define CONFIGURE_SOUNDCARD
#define CONFIG_SEQUENCER
#include "gus.h"
#if NGUS != 0 && !defined(CONFIG_GUS)
#define CONFIG_GUS
#define CONFIG_GUSMAX
#endif
#include "sscape.h"
#if NSSCAPE != 0 && !defined(CONFIG_SSCAPE)
#define CONFIG_SSCAPE
#endif
#include "trix.h"
#if NTRIX > 0
#define INCLUDE_TRIX_BOOT
#define CONFIG_TRIX /* can use NTRIX > 0 instead */
#define CONFIG_YM3812
#endif
#if defined(CONFIG_GUSMAX) || ( NSSCAPE > 0 ) || ( NTRIX > 0 )
#define CONFIG_AD1848
#endif
#if defined(CONFIG_SEQUENCER) && (NTRIX == 0)
#define CONFIG_MIDI
#endif
#include "sb.h"
#if NSB > 0
#define CONFIG_SB
#endif
#include "mss.h"
#if NMSS != 0
#define CONFIG_AD1848
#define CONFIG_MSS
#undef CONFIG_CS4232
#endif
#include "css.h"
#if NCSS != 0
#define CONFIG_AD1848
#undef CONFIG_MSS
#define CONFIG_CS4232
#endif
#include "sbxvi.h"
#if NSBXVI != 0 && !defined(CONFIG_SB16)
#define CONFIG_SB16
#define CONFIG_SBPRO /* FIXME: Also needs to be a sep option */
#endif
#include "sbmidi.h"
#if NSBMIDI != 0 && !defined(CONFIG_SB16MIDI)
#define CONFIG_SB16MIDI
#endif
#include "awe.h"
#if NAWE != 0 && !defined(CONFIG_AWE32)
#define CONFIG_AWE32
#endif
#include "pas.h"
#if NPAS != 0 && !defined(CONFIG_PAS)
#define CONFIG_PAS
#endif
#include "mpu.h"
#if NMPU != 0 && !defined(CONFIG_MPU401)
#define CONFIG_MPU401
#endif
#include "opl.h"
#if NOPL != 0 && !defined(CONFIG_YM3812)
#define CONFIG_YM3812
#endif
#define ALLOW_POLL
/* #undef CONFIG_PAS */
/* #undef CONFIG_ADLIB */
/* #define CONFIG_GUS */
/* #undef CONFIG_MPU401 */
#undef CONFIG_UART6850
#undef CONFIG_PSS
#undef CONFIG_GUS16
/* #undef CONFIG_MSS */
/* #undef CONFIG_SSCAPE */
#undef CONFIG_MAD16
/* #undef CONFIG_CS4232 */
#undef CONFIG_MAUI
#undef CONFIG_PNP
/* #undef CONFIG_SBPRO */
/* #undef CONFIG_SB16 */
#undef CONFIG_AEDSP16
#define CONFIG_AUDIO /* obvious ? */
#define CONFIG_MPU_EMU
#ifdef PC98
#define DSP_BUFFSIZE 61440
#else
#define DSP_BUFFSIZE 32768*2
#endif
/* #define SELECTED_SOUND_OPTIONS 0x0188090a */
#ifndef TRIX_SB_BASE
#define TRIX_SB_BASE 0x220
#endif
#ifndef TRIX_SB_IRQ
#define TRIX_SB_IRQ 7
#endif
#ifndef TRIX_SB_DMA
#define TRIX_SB_DMA 1
#endif
#ifndef TRIX_BASE
#define TRIX_BASE 0x530
#endif
#ifndef TRIX_IRQ
#define TRIX_IRQ 9
#endif
#ifndef TRIX_DMA
#define TRIX_DMA 3
#endif
#ifndef TRIX_DMA2
#define TRIX_DMA2 1
#endif
#ifndef GUS_BASE
#define GUS_BASE 0x220
#endif
#ifndef GUS_IRQ
#define GUS_IRQ 12
#endif
#ifndef GUS_MIDI_IRQ
#define GUS_MIDI_IRQ GUS_IRQ
#endif
#ifndef GUS_DMA
#define GUS_DMA 4
#endif
#ifndef GUS_DMA2
#define GUS_DMA2 4
#endif
#define SOUND_CONFIG_DATE "Wed Aug 6 22:58:35 PDT 1997"
#define SOUND_CONFIG_BY "Amancio Hasty"
#define SOUND_CONFIG_HOST "rah"
#define SOUND_CONFIG_DOMAIN "star-gate.com"
#else /* NSND = 0 */
#undef CONFIGURE_SOUNDCARD
#endif

View File

@ -1,524 +0,0 @@
/*
* sound/mad16.c
*
* Initialization code for OPTi MAD16 compatible audio chips. Including
*
* OPTi 82C928 MAD16 (replaced by C929) OAK OTI-601D Mozart
* OPTi 82C929 MAD16 Pro
*
* These audio interface chips don't prduce sound themselves. They just connect
* some other components (OPL-[234] and a WSS compatible codec) to the PC bus
* and perform I/O, DMA and IRQ address decoding. There is also a UART for
* the MPU-401 mode (not 82C928/Mozart). The Mozart chip appears to be
* compatible with the 82C928 (can anybody confirm this?).
*
* NOTE! If you want to set CD-ROM address and/or joystick enable, define
* MAD16_CONF in local.h as combination of the following bits:
*
* 0x01 - joystick disabled
*
* CD-ROM type selection (select just one): 0x00 - none 0x02 - Sony 31A
* 0x04 - Mitsumi 0x06 - Panasonic (type "LaserMate", not
* "SoundBlaster") 0x08 - Secondary IDE (address 0x170) 0x0a - Primary
* IDE (address 0x1F0)
*
* For example Mitsumi with joystick disabled = 0x04|0x01 = 0x05 For example
* LaserMate (for use with sbpcd) plus joystick = 0x06
*
* MAD16_CDSEL: This defaults to CD I/O 0x340, no IRQ and DMA3 (DMA5 with
* Mitsumi or IDE). If you like to change these, define MAD16_CDSEL with the
* following bits:
*
* CD-ROM port: 0x00=340, 0x40=330, 0x80=360 or 0xc0=320 OPL4 select: 0x20=OPL4,
* 0x00=OPL3 CD-ROM irq: 0x00=disabled, 0x04=IRQ5, 0x08=IRQ7, 0x0a=IRQ3,
* 0x10=IRQ9, 0x14=IRQ10 and 0x18=IRQ11.
*
* CD-ROM DMA (Sony or Panasonic): 0x00=DMA3, 0x01=DMA2, 0x02=DMA1 or
* 0x03=disabled or CD-ROM DMA (Mitsumi or IDE): 0x00=DMA5, 0x01=DMA6,
* 0x02=DMA7 or 0x03=disabled
*
* For use with sbpcd, address 0x340, set MAD16_CDSEL to 0x03 or 0x23.
*
* Copyright by Hannu Savolainen 1995
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. 2.
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#include <i386/isa/sound/sound_config.h>
#if defined(CONFIG_MAD16)
static int already_initialized = 0;
#define C928 1
#define MOZART 2
#define C929 3
/*
* Registers
*
* The MAD16 occupies I/O ports 0xf8d to 0xf93 (fixed locations). All ports are
* inactive by default. They can be activated by writing 0xE2 or 0xE3 to the
* password register. The password is valid only until the next I/O read or
* write.
*/
#define MC1_PORT 0xf8d /* SB address, CDROM interface type, joystick */
#define MC2_PORT 0xf8e /* CDROM address, IRQ, DMA, plus OPL4 bit */
#define MC3_PORT 0xf8f
#define PASSWD_REG 0xf8f
#define MC4_PORT 0xf90
#define MC5_PORT 0xf91
#define MC6_PORT 0xf92
#define MC7_PORT 0xf93
static int board_type = C928;
static sound_os_info *mad16_osp;
#ifndef DDB
#define DDB(x)
#endif
static unsigned char
mad_read(int port)
{
unsigned long flags;
unsigned char tmp;
flags = splhigh();
switch (board_type) { /* Output password */
case C928:
case MOZART:
outb(PASSWD_REG, 0xE2);
break;
case C929:
outb(PASSWD_REG, 0xE3);
break;
}
tmp = inb(port);
splx(flags);
return tmp;
}
static void
mad_write(int port, int value)
{
unsigned long flags;
flags = splhigh();
switch (board_type) { /* Output password */
case C928:
case MOZART:
outb(PASSWD_REG, 0xE2);
break;
case C929:
outb(PASSWD_REG, 0xE3);
break;
}
outb(port, (unsigned char) (value & 0xff));
splx(flags);
}
static int
detect_mad16(void)
{
unsigned char tmp, tmp2;
/*
* Check that reading a register doesn't return bus float (0xff) when
* the card is accessed using password. This may fail in case the
* card is in low power mode. Normally at least the power saving mode
* bit should be 0.
*/
if ((tmp = mad_read(MC1_PORT)) == 0xff) {
DDB(printf("MC1_PORT returned 0xff\n"));
return 0;
}
/*
* Now check that the gate is closed on first I/O after writing the
* password. (This is how a MAD16 compatible card works).
*/
if ((tmp2 = inb(MC1_PORT)) == tmp) { /* It didn't close */
DDB(printf("MC1_PORT didn't close after read (0x%02x)\n", tmp2));
return 0;
}
mad_write(MC1_PORT, tmp ^ 0x80); /* Togge a bit */
if ((tmp2 = mad_read(MC1_PORT)) != (tmp ^ 0x80)) { /* Compare the bit */
mad_write(MC1_PORT, tmp); /* Restore */
DDB(printf("Bit revert test failed (0x%02x, 0x%02x)\n", tmp, tmp2));
return 0;
}
mad_write(MC1_PORT, tmp); /* Restore */
return 1; /* Bingo */
}
int
probe_mad16(struct address_info * hw_config)
{
int i;
static int valid_ports[] =
{0x530, 0xe80, 0xf40, 0x604};
unsigned char tmp;
unsigned char cs4231_mode = 0;
int ad_flags = 0;
if (already_initialized)
return 0;
mad16_osp = hw_config->osp;
/*
* Check that all ports return 0xff (bus float) when no password is
* written to the password register.
*/
DDB(printf("--- Detecting MAD16 / Mozart ---\n"));
/*
* Then try to detect with the old password
*/
board_type = C928;
DDB(printf("Detect using password = 0xE2\n"));
if (!detect_mad16()) { /* No luck. Try different model */
board_type = C929;
DDB(printf("Detect using password = 0xE3\n"));
if (!detect_mad16())
return 0;
DDB(printf("mad16.c: 82C929 detected\n"));
} else {
unsigned char model;
if (((model = mad_read(MC3_PORT)) & 0x03) == 0x03) {
DDB(printf("mad16.c: Mozart detected\n"));
board_type = MOZART;
} else {
DDB(printf("mad16.c: 82C928 detected???\n"));
board_type = C928;
}
}
for (i = 0xf8d; i <= 0xf93; i++)
DDB(printf("port %03x = %03x\n", i, mad_read(i)));
/*
* Set the WSS address
*/
tmp = 0x80; /* Enable WSS, Disable SB */
for (i = 0; i < 5; i++) {
if (i > 3) { /* Not a valid port */
printf("MAD16/Mozart: Bad WSS base address 0x%x\n", hw_config->io_base);
return 0;
}
if (valid_ports[i] == hw_config->io_base) {
tmp |= i << 4; /* WSS port select bits */
break;
}
}
/*
* Set optional CD-ROM and joystick settings.
*/
#ifdef MAD16_CONF
tmp |= ((MAD16_CONF) & 0x0f); /* CD-ROM and joystick bits */
#endif
mad_write(MC1_PORT, tmp);
#if defined(MAD16_CONF) && defined(MAD16_CDSEL)
tmp = MAD16_CDSEL;
#else
tmp = 0x03;
#endif
#ifdef MAD16_OPL4
tmp |= 0x20; /* Enable OPL4 access */
#endif
mad_write(MC2_PORT, tmp);
mad_write(MC3_PORT, 0xf0); /* Disable SB */
if (!ad1848_detect(hw_config->io_base + 4, &ad_flags, mad16_osp))
return 0;
if (ad_flags & (AD_F_CS4231 | AD_F_CS4248))
cs4231_mode = 0x02; /* CS4248/CS4231 sync delay switch */
if (board_type == C929) {
mad_write(MC4_PORT, 0xa2);
mad_write(MC5_PORT, 0xA5 | cs4231_mode);
mad_write(MC6_PORT, 0x03); /* Disable MPU401 */
} else {
mad_write(MC4_PORT, 0x02);
mad_write(MC5_PORT, 0x30 | cs4231_mode);
}
for (i = 0xf8d; i <= 0xf93; i++)
DDB(printf("port %03x after init = %03x\n", i, mad_read(i)));
/*
* Verify the WSS parameters
*/
if (0) {
printf("MSS: I/O port conflict\n");
return 0;
}
/*
* Check if the IO port returns valid signature. The original MS
* Sound system returns 0x04 while some cards (AudioTriX Pro for
* example) return 0x00.
*/
if ((inb(hw_config->io_base + 3) & 0x3f) != 0x04 &&
(inb(hw_config->io_base + 3) & 0x3f) != 0x00) {
DDB(printf("No MSS signature detected on port 0x%x (0x%x)\n",
hw_config->io_base, inb(hw_config->io_base + 3)));
return 0;
}
if (hw_config->irq > 11) {
printf("MSS: Bad IRQ %d\n", hw_config->irq);
return 0;
}
if (hw_config->dma != 0 && hw_config->dma != 1 && hw_config->dma != 3) {
printf("MSS: Bad DMA %d\n", hw_config->dma);
return 0;
}
/*
* Check that DMA0 is not in use with a 8 bit board.
*/
if (hw_config->dma == 0 && inb(hw_config->io_base + 3) & 0x80) {
printf("MSS: Can't use DMA0 with a 8 bit card/slot\n");
return 0;
}
if (hw_config->irq > 7 && hw_config->irq != 9 && inb(hw_config->io_base + 3) & 0x80) {
printf("MSS: Can't use IRQ%d with a 8 bit card/slot\n", hw_config->irq);
return 0;
}
return 1;
}
void
attach_mad16(struct address_info * hw_config)
{
static char interrupt_bits[12] =
{
-1, -1, -1, -1, -1, -1, -1, 0x08, -1, 0x10, 0x18, 0x20
};
char bits;
static char dma_bits[4] =
{
1, 2, 0, 3
};
int config_port = hw_config->io_base + 0, version_port = hw_config->io_base + 3;
int ad_flags = 0, dma = hw_config->dma, dma2 = hw_config->dma2;
unsigned char dma2_bit = 0;
already_initialized = 1;
if (!ad1848_detect(hw_config->io_base + 4, &ad_flags, mad16_osp))
return;
/*
* Set the IRQ and DMA addresses.
*/
bits = interrupt_bits[hw_config->irq];
if (bits == -1)
return;
outb(config_port, bits | 0x40);
if ((inb(version_port) & 0x40) == 0)
printf("[IRQ Conflict?]");
/*
* Handle the capture DMA channel
*/
if (ad_flags & AD_F_CS4231 && dma2 != -1 && dma2 != dma) {
if ((dma == 0 && dma2 == 1) ||
(dma == 1 && dma2 == 0) ||
(dma == 3 && dma2 == 0)) {
dma2_bit = 0x04; /* Enable capture DMA */
} else {
printf("MAD16: Invalid capture DMA\n");
dma2 = dma;
}
} else
dma2 = dma;
outb(config_port, bits | dma_bits[dma] | dma2_bit); /* Write IRQ+DMA setup */
ad1848_init("MAD16 WSS", hw_config->io_base + 4,
hw_config->irq,
dma,
dma2, 0,
hw_config->osp);
}
void
attach_mad16_mpu(struct address_info * hw_config)
{
if (board_type < C929) {/* Early chip. No MPU support. Just SB MIDI */
#ifdef CONFIG_MIDI
if (mad_read(MC1_PORT) & 0x20)
hw_config->io_base = 0x240;
else
hw_config->io_base = 0x220;
return mad16_sb_dsp_init(hw_config);
#else
return 0;
#endif
}
#if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI)
if (!already_initialized)
return;
attach_mpu401(hw_config);
#endif
}
int
probe_mad16_mpu(struct address_info * hw_config)
{
#if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI)
static int mpu_attached = 0;
static int valid_ports[] =
{0x330, 0x320, 0x310, 0x300};
static short valid_irqs[] =
{9, 10, 5, 7};
unsigned char tmp;
int i; /* A variable with secret power */
if (!already_initialized) /* The MSS port must be initialized
* first */
return 0;
if (mpu_attached) /* Don't let them call this twice */
return 0;
mpu_attached = 1;
if (board_type < C929) {/* Early chip. No MPU support. Just SB MIDI */
#ifdef CONFIG_MIDI
unsigned char tmp;
tmp = mad_read(MC3_PORT);
/*
* MAD16 SB base is defined by the WSS base. It cannot be
* changed alone. Ignore configured I/O base. Use the active
* setting.
*/
if (mad_read(MC1_PORT) & 0x20)
hw_config->io_base = 0x240;
else
hw_config->io_base = 0x220;
switch (hw_config->irq) {
case 5:
tmp = (tmp & 0x3f) | 0x80;
break;
case 7:
tmp = (tmp & 0x3f);
break;
case 11:
tmp = (tmp & 0x3f) | 0x40;
break;
default:
printf("mad16/Mozart: Invalid MIDI IRQ\n");
return 0;
}
mad_write(MC3_PORT, tmp | 0x04);
return mad16_sb_dsp_detect(hw_config);
#else
return 0;
#endif
}
tmp = 0x83; /* MPU-401 enable */
/*
* Set the MPU base bits
*/
for (i = 0; i < 5; i++) {
if (i > 3) { /* Out of array bounds */
printf("MAD16 / Mozart: Invalid MIDI port 0x%x\n", hw_config->io_base);
return 0;
}
if (valid_ports[i] == hw_config->io_base) {
tmp |= i << 5;
break;
}
}
/*
* Set the MPU IRQ bits
*/
for (i = 0; i < 5; i++) {
if (i > 3) { /* Out of array bounds */
printf("MAD16 / Mozart: Invalid MIDI IRQ %d\n", hw_config->irq);
return 0;
}
if (valid_irqs[i] == hw_config->irq) {
tmp |= i << 3;
break;
}
}
mad_write(MC6_PORT, tmp); /* Write MPU401 config */
return probe_mpu401(hw_config);
#else
return 0;
#endif
}
/* That's all folks */
#endif

View File

@ -1,91 +0,0 @@
/*
* Initialization code for OPTI MAD16 interface chip by
* Davor Jadrijevic <davor@emard.pub.hr>
* (Included by ad1848.c when MAD16 support is enabled)
*
* It looks like MAD16 is similar than the Mozart chip (OAK OTI-601).
* It could be even possible that these chips are exactly the same. Can
* anybody confirm this?
*/
static void wr_a_mad16(int base, int v, int a)
{
OUTB(a, base + 0xf);
OUTB(v, base + 0x11);
}
static void wr_b_mad16(int base, int v, int a)
{
OUTB(a, base + 0xf);
OUTB(v, base + 0xd);
}
/*
static int rd_a_mad16(int base, int a)
{
OUTB(a, base + 0xf);
return INB(base + 0x11);
}
*/
static int rd_b_mad16(int base, int a)
{
OUTB(a, base + 0xf);
return INB(base + 0xd);
}
/*
static int rd_0_mad16(int base, int a)
{
OUTB(a, base + 0xf);
return INB(base + 0xf);
}
static void wr_ad(int base, int v, int a)
{
OUTB(a, base + 4);
OUTB(v, base + 5);
}
static int rd_ad(int base, int a)
{
OUTB(a, base + 4);
return INB(base + 5);
}
*/
static int mad16init(int adr)
{
int j;
long i;
static int ad1848_bases[] =
{ 0x220, -1, -1, 0x240, -1, -1, -1, -1, 0x530, 0xE80, 0xF40, 0x604, 0 };
int mad16_base = 0xf80, ad1848_base;
for(j = 0; (j < 16) && (ad1848_bases[j] != 0); j++)
if(adr == ad1848_bases[j])
break;
if( (ad1848_base = ad1848_bases[j]) < 0x530)
{
printk("Unknown MAD16 setting 0x%3X\n", adr);
return -1;
}
/* printk("OPTi MAD16 WSS at 0x%3X\n", ad1848_base); */
rd_b_mad16(mad16_base, 0xe2);
wr_a_mad16(mad16_base, 0x1a, 0xe2);
wr_b_mad16(mad16_base, j * 16 + 1, 0xe2);
wr_a_mad16(mad16_base, 0x1a, 0xe2);
for( i = 0; i < 10000; i++)
if( (INB(ad1848_base+4) & 0x80) == 0 )
break;
return 0;
};

View File

@ -1,285 +0,0 @@
/*
* sound/mad16_sb_midi.c
*
* The low level driver for MAD16 SoundBlaster-DS-chip-based MIDI.
*
* Copyright by Hannu Savolainen 1993, Aaron Ucko 1995
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. 2.
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#include <i386/isa/sound/sound_config.h>
#if defined(CONFIG_MAD16) && defined(CONFIG_MIDI)
#define sbc_base mad16_sb_base
#include <i386/isa/sound/sb_card.h>
static int input_opened = 0;
static int my_dev;
static int mad16_sb_base = 0x220;
static int mad16_sb_irq = 0;
static int mad16_sb_dsp_ok = 0;
static sound_os_info *midi_osp;
int mad16_sb_midi_mode = NORMAL_MIDI;
int mad16_sb_midi_busy = 0;
int mad16_sb_duplex_midi = 0;
volatile int mad16_sb_intr_active = 0;
void (*midi_input_intr) (int dev, unsigned char data);
static void mad16_sb_midi_init(int model);
static int
mad16_sb_dsp_command(unsigned char val)
{
int i;
unsigned long limit;
limit = get_time() + hz / 10; /* The timeout is 0.1 secods */
/*
* Note! the i<500000 is an emergency exit. The
* mad16_sb_dsp_command() is sometimes called while interrupts are
* disabled. This means that the timer is disabled also. However the
* timeout situation is a abnormal condition. Normally the DSP should
* be ready to accept commands after just couple of loops.
*/
for (i = 0; i < 500000 && get_time() < limit; i++) {
if ((inb(DSP_STATUS) & 0x80) == 0) {
outb(DSP_COMMAND, val);
return 1;
}
}
printf("MAD16 (SBP mode): DSP Command(%x) Timeout.\n", val);
printf("IRQ conflict???\n");
return 0;
}
void
mad16_sbintr(int irq)
{
int status;
unsigned long flags;
unsigned char data;
status = inb(DSP_DATA_AVAIL); /* Clear interrupt */
flags = splhigh();
data = inb(DSP_READ);
if (input_opened)
midi_input_intr(my_dev, data);
splx(flags);
}
static int
mad16_sb_reset_dsp(void)
{
int loopc;
outb(DSP_RESET, 1);
DELAY(10);
outb(DSP_RESET, 0);
DELAY(30);
for (loopc = 0; loopc < 100 && !(inb(DSP_DATA_AVAIL) & 0x80); loopc++)
DELAY(10);
/* Wait for data available status */
if (inb(DSP_READ) != 0xAA)
return 0; /* Sorry */
return 1;
}
int
mad16_sb_dsp_detect(struct address_info * hw_config)
{
mad16_sb_base = hw_config->io_base;
mad16_sb_irq = hw_config->irq;
midi_osp = hw_config->osp;
if (mad16_sb_dsp_ok)
return 0; /* Already initialized */
if (!mad16_sb_reset_dsp())
return 0;
return 1; /* Detected */
}
void
mad16_sb_dsp_init(struct address_info * hw_config)
/*
* this function now just verifies the reported version and calls
* mad16_sb_midi_init -- everything else is done elsewhere
*/
{
midi_osp = hw_config->osp;
if (snd_set_irq_handler(mad16_sb_irq, mad16_sbintr, midi_osp) < 0) {
printf("MAD16 SB MIDI: IRQ not free\n");
return;
}
conf_printf("MAD16 MIDI (SB mode)", hw_config);
mad16_sb_midi_init(2);
mad16_sb_dsp_ok = 1;
return;
}
static int
mad16_sb_midi_open(int dev, int mode,
void (*input) (int dev, unsigned char data),
void (*output) (int dev)
)
{
if (!mad16_sb_dsp_ok) {
printf("MAD16_SB Error: MIDI hardware not installed\n");
return -(ENXIO);
}
if (mad16_sb_midi_busy)
return -(EBUSY);
if (mode != OPEN_WRITE && !mad16_sb_duplex_midi) {
if (num_midis == 1)
printf("MAD16 (SBP mode): Midi input not currently supported\n");
return -(EPERM);
}
mad16_sb_midi_mode = NORMAL_MIDI;
if (mode != OPEN_WRITE) {
if (mad16_sb_intr_active)
return -(EBUSY);
mad16_sb_midi_mode = UART_MIDI;
}
if (mad16_sb_midi_mode == UART_MIDI) {
mad16_sb_reset_dsp();
if (!mad16_sb_dsp_command(0x35))
return -(EIO); /* Enter the UART mode */
mad16_sb_intr_active = 1;
input_opened = 1;
midi_input_intr = input;
}
mad16_sb_midi_busy = 1;
return 0;
}
static void
mad16_sb_midi_close(int dev)
{
if (mad16_sb_midi_mode == UART_MIDI) {
mad16_sb_reset_dsp(); /* The only way to kill the UART mode */
}
mad16_sb_intr_active = 0;
mad16_sb_midi_busy = 0;
input_opened = 0;
}
static int
mad16_sb_midi_out(int dev, unsigned char midi_byte)
{
unsigned long flags;
if (mad16_sb_midi_mode == NORMAL_MIDI) {
flags = splhigh();
if (mad16_sb_dsp_command(0x38))
mad16_sb_dsp_command(midi_byte);
else
printf("MAD16_SB Error: Unable to send a MIDI byte\n");
splx(flags);
} else
mad16_sb_dsp_command(midi_byte); /* UART write */
return 1;
}
static int
mad16_sb_midi_start_read(int dev)
{
if (mad16_sb_midi_mode != UART_MIDI) {
printf("MAD16 (SBP mode): MIDI input not implemented.\n");
return -(EPERM);
}
return 0;
}
static int
mad16_sb_midi_end_read(int dev)
{
if (mad16_sb_midi_mode == UART_MIDI) {
mad16_sb_reset_dsp();
mad16_sb_intr_active = 0;
}
return 0;
}
static int
mad16_sb_midi_ioctl(int dev, unsigned cmd, ioctl_arg arg)
{
return -(EPERM);
}
#define MIDI_SYNTH_NAME "pseudo-SoundBlaster Midi"
#define MIDI_SYNTH_CAPS 0
#include <i386/isa/sound/midi_synth.h>
static struct midi_operations mad16_sb_midi_operations =
{
{"MAD16 (SBP mode)", 0, 0, SNDCARD_MAD16},
&std_midi_synth,
{0},
mad16_sb_midi_open,
mad16_sb_midi_close,
mad16_sb_midi_ioctl,
mad16_sb_midi_out,
mad16_sb_midi_start_read,
mad16_sb_midi_end_read,
NULL, /* Kick */
NULL, /* command */
NULL, /* buffer_status */
NULL
};
static void
mad16_sb_midi_init(int model)
{
if (num_midis >= MAX_MIDI_DEV) {
printf("Sound: Too many midi devices detected\n");
return;
}
std_midi_synth.midi_dev = num_midis;
my_dev = num_midis;
midi_devs[num_midis++] = &mad16_sb_midi_operations;
}
#endif

View File

@ -1,225 +0,0 @@
/*
* sound/maui.c
*
* The low level driver for Turtle Beach Maui and Tropez.
*
* Copyright by Hannu Savolainen 1995
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. 2.
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#define USE_SEQ_MACROS
#define USE_SIMPLE_MACROS
#include <i386/isa/sound/sound_config.h>
#if defined(CONFIG_MAUI)
static int maui_base = 0x330;
static volatile int irq_ok = 0;
static sound_os_info *maui_osp;
#define HOST_DATA_PORT (maui_base + 2)
#define HOST_STAT_PORT (maui_base + 3)
#define HOST_CTRL_PORT (maui_base + 3)
#define STAT_TX_INTR 0x40
#define STAT_TX_AVAIL 0x20
#define STAT_TX_IENA 0x10
#define STAT_RX_INTR 0x04
#define STAT_RX_AVAIL 0x02
#define STAT_RX_IENA 0x01
static int (*orig_load_patch) (int dev, int format, snd_rw_buf * addr,
int offs, int count, int pmgr_flag) = NULL;
static int
maui_read(void)
{
int timeout;
for (timeout = 0; timeout < 1000000; timeout++)
if (inb(HOST_STAT_PORT) & STAT_RX_AVAIL)
return inb(HOST_DATA_PORT);
printf("Maui: Receive timeout\n");
return -1;
}
static int
maui_write(u_char data)
{
int timeout;
for (timeout = 0; timeout < 10000000; timeout++) {
if (inb(HOST_STAT_PORT) & STAT_TX_AVAIL) {
outb(HOST_DATA_PORT, data);
return 1;
}
}
printf("Maui: Write timeout\n");
return 0;
}
void
mauiintr(int irq)
{
irq_ok = 1;
}
int
maui_load_patch(int dev, int format, snd_rw_buf * addr,
int offs, int count, int pmgr_flag)
{
struct sysex_info header;
u_long left, src_offs;
int hdr_size = (u_long) &header.data[0] - (u_long) &header;
int i;
if (format == SYSEX_PATCH) /* Handled by midi_synth.c */
return orig_load_patch(dev, format, addr, offs, count, pmgr_flag);
if (format != MAUI_PATCH) {
printf("Maui: Unknown patch format\n");
}
if (count < hdr_size) {
printf("Maui error: Patch header too short\n");
return -(EINVAL);
}
count -= hdr_size;
/*
* Copy the header from user space but ignore the first bytes which
* have been transferred already.
*/
if (uiomove(&((char *) &header)[offs], hdr_size - offs, addr)) {
printf("sb: Bad copyin()!\n");
};
if (count < header.len) {
printf("Maui warning: Host command record too short (%d<%d)\n",
count, (int) header.len);
header.len = count;
}
left = header.len;
src_offs = 0;
for (i = 0; i < left; i++) {
u_char data;
uiomove((char *) &(data), 1, addr);
if (i == 0 && !(data & 0x80))
return -(EINVAL);
if (maui_write(data) == -1)
return -(EIO);
}
if ((i = maui_read()) != 0x80) {
if (i != -1)
printf("Maui: Error status %02x\n", i);
return -(EIO);
}
return 0;
}
int
probe_maui(struct address_info * hw_config)
{
int i;
int tmp1, tmp2;
maui_base = hw_config->io_base;
maui_osp = hw_config->osp;
if (snd_set_irq_handler(hw_config->irq, mauiintr, maui_osp) < 0)
return 0;
if (!maui_write(0xCF)) {/* Report hardware version */
/* snd_release_irq(hw_config->irq); */
return 0;
}
if ((tmp1 = maui_read()) == -1 || (tmp2 = maui_read()) == -1) {
/* snd_release_irq(hw_config->irq); */
return 0;
}
printf("WaveFront hardware version %d.%d\n", tmp1, tmp2);
if (!maui_write(0x9F)) /* Report firmware version */
return 0;
if ((tmp1 = maui_read()) == -1 || (tmp2 = maui_read()) == -1)
return 0;
printf("WaveFront firmware version %d.%d\n", tmp1, tmp2);
if (!maui_write(0x85)) /* Report free DRAM */
return 0;
tmp1 = 0;
for (i = 0; i < 4; i++) {
tmp1 |= maui_read() << (7 * i);
}
printf("Available DRAM %dk\n", tmp1 / 1024);
for (i = 0; i < 1000; i++)
if (probe_mpu401(hw_config))
break;
return probe_mpu401(hw_config);
}
void
attach_maui(struct address_info * hw_config)
{
int this_dev = num_midis;
conf_printf("Maui", hw_config);
hw_config->irq *= -1;
attach_mpu401(hw_config);
if (num_midis > this_dev) { /* The MPU401 driver installed itself */
struct synth_operations *synth;
/*
* Intercept patch loading calls so that they canbe handled
* by the Maui driver.
*/
synth = midi_devs[this_dev]->converter;
if (synth != NULL) {
orig_load_patch = synth->load_patch;
synth->load_patch = &maui_load_patch;
} else
printf("Maui: Can't install patch loader\n");
}
return;
}
#endif

View File

@ -1,22 +0,0 @@
static unsigned char ctrl_def_values[128] =
{
0x40,0x40,0x40,0x40, 0x40,0x40,0x40,0x40, /* 0 to 7 */
0x40,0x40,0x40,0x40, 0x40,0x40,0x40,0x40, /* 8 to 15 */
0x40,0x40,0x40,0x40, 0x40,0x40,0x40,0x40, /* 16 to 23 */
0x40,0x40,0x40,0x40, 0x40,0x40,0x40,0x40, /* 24 to 31 */
0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, /* 32 to 39 */
0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, /* 40 to 47 */
0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, /* 48 to 55 */
0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, /* 56 to 63 */
0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, /* 64 to 71 */
0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, /* 72 to 79 */
0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, /* 80 to 87 */
0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, /* 88 to 95 */
0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, /* 96 to 103 */
0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, /* 104 to 111 */
0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, /* 112 to 119 */
0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, /* 120 to 127 */
};

View File

@ -1,675 +0,0 @@
/*
* sound/midi_synth.c
*
* High level midi sequencer manager for dumb MIDI interfaces.
*
* Copyright by Hannu Savolainen 1993
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
* 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.
*
*/
#define USE_SEQ_MACROS
#define USE_SIMPLE_MACROS
#include <stddef.h>
#include <i386/isa/sound/sound_config.h>
#if defined(CONFIGURE_SOUNDCARD) /* && defined(CONFIG_MIDI) */
#define _MIDI_SYNTH_C_
static int *sysex_sleeper = NULL;
static volatile struct snd_wait sysex_sleep_flag = {0};
#include <i386/isa/sound/midi_synth.h>
static int midi2synth[MAX_MIDI_DEV];
static int sysex_state[MAX_MIDI_DEV] =
{0};
static unsigned char prev_out_status[MAX_MIDI_DEV];
#ifndef CONFIG_SEQUENCER
#define STORE(cmd)
#else
#define STORE(cmd) { \
int len; \
unsigned char obuf[8]; \
cmd; \
seq_input_event(obuf, len); \
}
#endif
#define _seqbuf obuf
#define _seqbufptr 0
#define _SEQ_ADVBUF(x) len=x
void
do_midi_msg(int synthno, unsigned char *msg, int mlen)
{
switch (msg[0] & 0xf0) {
case 0x90:
if (msg[2] != 0) {
STORE(SEQ_START_NOTE(synthno, msg[0] & 0x0f, msg[1], msg[2]));
break;
}
msg[2] = 64;
case 0x80:
STORE(SEQ_STOP_NOTE(synthno, msg[0] & 0x0f, msg[1], msg[2]));
break;
case 0xA0:
STORE(SEQ_KEY_PRESSURE(synthno, msg[0] & 0x0f, msg[1], msg[2]));
break;
case 0xB0:
STORE(SEQ_CONTROL(synthno, msg[0] & 0x0f, msg[1], msg[2]));
break;
case 0xC0:
STORE(SEQ_SET_PATCH(synthno, msg[0] & 0x0f, msg[1]));
break;
case 0xD0:
STORE(SEQ_CHN_PRESSURE(synthno, msg[0] & 0x0f, msg[1]));
break;
case 0xE0:
STORE(SEQ_BENDER(synthno, msg[0] & 0x0f,
(msg[1] % 0x7f) | ((msg[2] & 0x7f) << 7)));
break;
default:
/*
* printf ("MPU: Unknown midi channel message %02x\n",
* msg[0]);
*/
;
}
}
static void
midi_outc(int midi_dev, int data)
{
int timeout;
for (timeout = 0; timeout < 32000; timeout++)
if (midi_devs[midi_dev]->putc(midi_dev, (unsigned char) (data & 0xff))) {
if (data & 0x80) /* Status byte */
prev_out_status[midi_dev] =
(unsigned char) (data & 0xff); /* Store for running
* status */
return; /* Mission complete */
}
/*
* Sorry! No space on buffers.
*/
printf("Midi send timed out\n");
}
static int
prefix_cmd(int midi_dev, unsigned char status)
{
if ((char *) midi_devs[midi_dev]->prefix_cmd == NULL)
return 1;
return midi_devs[midi_dev]->prefix_cmd(midi_dev, status);
}
static void
midi_synth_input(int orig_dev, unsigned char data)
{
int dev;
struct midi_input_info *inc;
static unsigned char len_tab[] = /* # of data bytes following a status */
{
2, /* 8x */
2, /* 9x */
2, /* Ax */
2, /* Bx */
1, /* Cx */
1, /* Dx */
2, /* Ex */
0 /* Fx */
};
if (orig_dev < 0 || orig_dev > num_midis)
return;
if (data == 0xfe) /* Ignore active sensing */
return;
dev = midi2synth[orig_dev];
inc = &midi_devs[orig_dev]->in_info;
switch (inc->m_state) {
case MST_INIT:
if (data & 0x80) { /* MIDI status byte */
if ((data & 0xf0) == 0xf0) { /* Common message */
switch (data) {
case 0xf0: /* Sysex */
inc->m_state = MST_SYSEX;
break; /* Sysex */
case 0xf1: /* MTC quarter frame */
case 0xf3: /* Song select */
inc->m_state = MST_DATA;
inc->m_ptr = 1;
inc->m_left = 1;
inc->m_buf[0] = data;
break;
case 0xf2: /* Song position pointer */
inc->m_state = MST_DATA;
inc->m_ptr = 1;
inc->m_left = 2;
inc->m_buf[0] = data;
break;
default:
inc->m_buf[0] = data;
inc->m_ptr = 1;
do_midi_msg(dev, inc->m_buf, inc->m_ptr);
inc->m_ptr = 0;
inc->m_left = 0;
}
} else {
inc->m_state = MST_DATA;
inc->m_ptr = 1;
inc->m_left = len_tab[(data >> 4) - 8];
inc->m_buf[0] = inc->m_prev_status = data;
}
} else if (inc->m_prev_status & 0x80) { /* Ignore if no previous
* status (yet) *//* Data byte (use running status) */
inc->m_state = MST_DATA;
inc->m_ptr = 2;
inc->m_left = len_tab[(data >> 4) - 8] - 1;
inc->m_buf[0] = inc->m_prev_status;
inc->m_buf[1] = data;
}
break; /* MST_INIT */
case MST_DATA:
inc->m_buf[inc->m_ptr++] = data;
if (--inc->m_left <= 0) {
inc->m_state = MST_INIT;
do_midi_msg(dev, inc->m_buf, inc->m_ptr);
inc->m_ptr = 0;
}
break; /* MST_DATA */
case MST_SYSEX:
if (data == 0xf7) { /* Sysex end */
inc->m_state = MST_INIT;
inc->m_left = 0;
inc->m_ptr = 0;
}
break; /* MST_SYSEX */
default:
printf("MIDI%d: Unexpected state %d (%02x)\n", orig_dev, inc->m_state,
(int) data);
inc->m_state = MST_INIT;
}
}
static void
leave_sysex(int dev)
{
int orig_dev = synth_devs[dev]->midi_dev;
int timeout = 0;
if (!sysex_state[dev])
return;
sysex_state[dev] = 0;
while (!midi_devs[orig_dev]->putc(orig_dev, 0xf7) && timeout < 1000)
timeout++;
sysex_state[dev] = 0;
}
static void
midi_synth_output(int dev)
{
/*
* Currently NOP
*/
}
int
midi_synth_ioctl(int dev, unsigned int cmd, ioctl_arg arg)
{
/*
* int orig_dev = synth_devs[dev]->midi_dev;
*/
switch (cmd) {
case SNDCTL_SYNTH_INFO:
bcopy(synth_devs[dev]->info, &(((char *) arg)[0]), sizeof(struct synth_info));
return 0;
break;
case SNDCTL_SYNTH_MEMAVL:
return 0x7fffffff;
break;
default:
return -(EINVAL);
}
}
int
midi_synth_kill_note(int dev, int channel, int note, int velocity)
{
int orig_dev = synth_devs[dev]->midi_dev;
int msg, chn;
if (note < 0 || note > 127)
return 0;
if (channel < 0 || channel > 15)
return 0;
RANGE (velocity, 0, 127 ) ;
leave_sysex(dev);
msg = prev_out_status[orig_dev] & 0xf0;
chn = prev_out_status[orig_dev] & 0x0f;
if (chn == channel && ((msg == 0x90 && velocity == 64) || msg == 0x80)) { /* Use running status */
if (!prefix_cmd(orig_dev, note))
return 0;
midi_outc(orig_dev, note);
if (msg == 0x90)/* Running status = Note on */
midi_outc(orig_dev, 0); /* Note on with velocity 0 == note off */
else
midi_outc(orig_dev, velocity);
} else {
if (velocity == 64) {
if (!prefix_cmd(orig_dev, 0x90 | (channel & 0x0f)))
return 0;
midi_outc(orig_dev, 0x90 | (channel & 0x0f)); /* Note on */
midi_outc(orig_dev, note);
midi_outc(orig_dev, 0); /* Zero G */
} else {
if (!prefix_cmd(orig_dev, 0x80 | (channel & 0x0f)))
return 0;
midi_outc(orig_dev, 0x80 | (channel & 0x0f)); /* Note off */
midi_outc(orig_dev, note);
midi_outc(orig_dev, velocity);
}
}
return 0;
}
int
midi_synth_set_instr(int dev, int channel, int instr_no)
{
int orig_dev = synth_devs[dev]->midi_dev;
if (instr_no < 0 || instr_no > 127)
return 0;
if (channel < 0 || channel > 15)
return 0;
leave_sysex(dev);
if (!prefix_cmd(orig_dev, 0xc0 | (channel & 0x0f)))
return 0;
midi_outc(orig_dev, 0xc0 | (channel & 0x0f)); /* Program change */
midi_outc(orig_dev, instr_no);
return 0;
}
int
midi_synth_start_note(int dev, int channel, int note, int velocity)
{
int orig_dev = synth_devs[dev]->midi_dev;
int msg, chn;
if (note < 0 || note > 127)
return 0;
if (channel < 0 || channel > 15)
return 0;
RANGE (velocity, 0, 127 );
leave_sysex(dev);
msg = prev_out_status[orig_dev] & 0xf0;
chn = prev_out_status[orig_dev] & 0x0f;
if (chn == channel && msg == 0x90) { /* Use running status */
if (!prefix_cmd(orig_dev, note))
return 0;
midi_outc(orig_dev, note);
midi_outc(orig_dev, velocity);
} else {
if (!prefix_cmd(orig_dev, 0x90 | (channel & 0x0f)))
return 0;
midi_outc(orig_dev, 0x90 | (channel & 0x0f)); /* Note on */
midi_outc(orig_dev, note);
midi_outc(orig_dev, velocity);
}
return 0;
}
void
midi_synth_reset(int dev)
{
leave_sysex(dev);
}
int
midi_synth_open(int dev, int mode)
{
int orig_dev = synth_devs[dev]->midi_dev;
int err;
unsigned long flags;
struct midi_input_info *inc;
if (orig_dev < 0 || orig_dev > num_midis)
return -(ENXIO);
midi2synth[orig_dev] = dev;
sysex_state[dev] = 0;
prev_out_status[orig_dev] = 0;
if ((err = midi_devs[orig_dev]->open(orig_dev, mode,
midi_synth_input, midi_synth_output)) < 0)
return err;
inc = &midi_devs[orig_dev]->in_info;
flags = splhigh();
inc->m_busy = 0;
inc->m_state = MST_INIT;
inc->m_ptr = 0;
inc->m_left = 0;
inc->m_prev_status = 0x00;
splx(flags);
sysex_sleep_flag.aborting = 0;
sysex_sleep_flag.mode = WK_NONE;
return 1;
}
void
midi_synth_close(int dev)
{
int orig_dev = synth_devs[dev]->midi_dev;
leave_sysex(dev);
/*
* Shut up the synths by sending just single active sensing message.
*/
midi_devs[orig_dev]->putc(orig_dev, 0xfe);
midi_devs[orig_dev]->close(orig_dev);
}
void
midi_synth_hw_control(int dev, unsigned char *event)
{
}
int
midi_synth_load_patch(int dev, int format, snd_rw_buf * addr,
int offs, int count, int pmgr_flag)
{
int orig_dev = synth_devs[dev]->midi_dev;
struct sysex_info sysex;
int i;
unsigned long left, src_offs, eox_seen = 0;
int first_byte = 1;
int hdr_size = offsetof(struct sysex_info, data);
leave_sysex(dev);
if (!prefix_cmd(orig_dev, 0xf0))
return 0;
if (format != SYSEX_PATCH) {
printf("MIDI Error: Invalid patch format (key) 0x%x\n", format);
return -(EINVAL);
}
if (count < hdr_size) {
printf("MIDI Error: Patch header too short\n");
return -(EINVAL);
}
count -= hdr_size;
/*
* Copy the header from user space but ignore the first bytes which
* have been transferred already.
*/
if (uiomove(&((char *) &sysex)[offs], hdr_size - offs, addr)) {
printf("sb: Bad copyin()!\n");
};
if (count < sysex.len) {
printf("MIDI Warning: Sysex record too short (%d<%d)\n",
count, (int) sysex.len);
sysex.len = count;
}
left = sysex.len;
src_offs = 0;
sysex_sleep_flag.aborting = 0;
sysex_sleep_flag.mode = WK_NONE;
for (i = 0; i < left && !(sysex_sleep_flag.aborting); i++) {
unsigned char data;
uiomove((char *) &(data), 1, addr);
eox_seen = (i > 0 && data & 0x80); /* End of sysex */
if (eox_seen && data != 0xf7)
data = 0xf7;
if (i == 0) {
if (data != 0xf0) {
printf("Error: Sysex start missing\n");
return -(EINVAL);
}
}
while (!midi_devs[orig_dev]->putc(orig_dev,
(unsigned char) (data & 0xff)) &&
!(sysex_sleep_flag.aborting)) {
int chn;
sysex_sleeper = &chn;
DO_SLEEP(chn, sysex_sleep_flag, 1);
}; /* Wait for timeout */
if (!first_byte && data & 0x80)
return 0;
first_byte = 0;
}
if (!eox_seen)
midi_outc(orig_dev, 0xf7);
return 0;
}
void
midi_synth_panning(int dev, int channel, int pressure)
{
}
void
midi_synth_aftertouch(int dev, int channel, int pressure)
{
int orig_dev = synth_devs[dev]->midi_dev;
int msg, chn;
if (pressure < 0 || pressure > 127)
return;
if (channel < 0 || channel > 15)
return;
leave_sysex(dev);
msg = prev_out_status[orig_dev] & 0xf0;
chn = prev_out_status[orig_dev] & 0x0f;
if (msg != 0xd0 || chn != channel) { /* Test for running status */
if (!prefix_cmd(orig_dev, 0xd0 | (channel & 0x0f)))
return;
midi_outc(orig_dev, 0xd0 | (channel & 0x0f)); /* Channel pressure */
} else if (!prefix_cmd(orig_dev, pressure))
return;
midi_outc(orig_dev, pressure);
}
void
midi_synth_controller(int dev, int channel, int ctrl_num, int value)
{
int orig_dev = synth_devs[dev]->midi_dev;
int chn, msg;
if (ctrl_num < 1 || ctrl_num > 127)
return; /* NOTE! Controller # 0 ignored */
if (channel < 0 || channel > 15)
return;
leave_sysex(dev);
msg = prev_out_status[orig_dev] & 0xf0;
chn = prev_out_status[orig_dev] & 0x0f;
if (msg != 0xb0 || chn != channel) {
if (!prefix_cmd(orig_dev, 0xb0 | (channel & 0x0f)))
return;
midi_outc(orig_dev, 0xb0 | (channel & 0x0f));
} else if (!prefix_cmd(orig_dev, ctrl_num))
return;
midi_outc(orig_dev, ctrl_num);
midi_outc(orig_dev, value & 0x7f);
}
int
midi_synth_patchmgr(int dev, struct patmgr_info * rec)
{
return -(EINVAL);
}
void
midi_synth_bender(int dev, int channel, int value)
{
int orig_dev = synth_devs[dev]->midi_dev;
int msg, prev_chn;
if (channel < 0 || channel > 15)
return;
if (value < 0 || value > 16383)
return;
leave_sysex(dev);
msg = prev_out_status[orig_dev] & 0xf0;
prev_chn = prev_out_status[orig_dev] & 0x0f;
if (msg != 0xd0 || prev_chn != channel) { /* Test for running status */
if (!prefix_cmd(orig_dev, 0xe0 | (channel & 0x0f)))
return;
midi_outc(orig_dev, 0xe0 | (channel & 0x0f));
} else if (!prefix_cmd(orig_dev, value & 0x7f))
return;
midi_outc(orig_dev, value & 0x7f);
midi_outc(orig_dev, (value >> 7) & 0x7f);
}
void
midi_synth_setup_voice(int dev, int voice, int channel)
{
}
int
midi_synth_send_sysex(int dev, unsigned char *bytes, int len)
{
int orig_dev = synth_devs[dev]->midi_dev;
int i;
for (i = 0; i < len; i++) {
switch (bytes[i]) {
case 0xf0: /* Start sysex */
if (!prefix_cmd(orig_dev, 0xf0))
return 0;
sysex_state[dev] = 1;
break;
case 0xf7: /* End sysex */
if (!sysex_state[dev]) /* Orphan sysex end */
return 0;
sysex_state[dev] = 0;
break;
default:
if (!sysex_state[dev])
return 0;
if (bytes[i] & 0x80) { /* Error. Another message before sysex end */
bytes[i] = 0xf7; /* Sysex end */
sysex_state[dev] = 0;
}
}
if (!midi_devs[orig_dev]->putc(orig_dev, bytes[i])) {
/*
* Hardware leve buffer is full. Abort the sysex message.
*/
int timeout = 0;
bytes[i] = 0xf7;
sysex_state[dev] = 0;
while (!midi_devs[orig_dev]->putc(orig_dev, bytes[i]) &&
timeout < 1000)
timeout++;
}
if (!sysex_state[dev])
return 0;
}
return 0;
}
#endif

View File

@ -1,49 +0,0 @@
int midi_synth_ioctl (int dev,
unsigned int cmd, ioctl_arg arg);
int midi_synth_kill_note (int dev, int channel, int note, int velocity);
int midi_synth_set_instr (int dev, int channel, int instr_no);
int midi_synth_start_note (int dev, int channel, int note, int volume);
void midi_synth_reset (int dev);
int midi_synth_open (int dev, int mode);
void midi_synth_close (int dev);
void midi_synth_hw_control (int dev, unsigned char *event);
int midi_synth_load_patch (int dev, int format, snd_rw_buf * addr,
int offs, int count, int pmgr_flag);
void midi_synth_panning (int dev, int channel, int pressure);
void midi_synth_aftertouch (int dev, int channel, int pressure);
void midi_synth_controller (int dev, int channel, int ctrl_num, int value);
int midi_synth_patchmgr (int dev, struct patmgr_info *rec);
void midi_synth_bender (int dev, int chn, int value);
void midi_synth_setup_voice (int dev, int voice, int chn);
int midi_synth_send_sysex(int dev, unsigned char *bytes,int len);
#ifndef _MIDI_SYNTH_C_
static struct synth_info std_synth_info =
{MIDI_SYNTH_NAME, 0, SYNTH_TYPE_MIDI, 0, 0, 128, 0, 128, MIDI_SYNTH_CAPS};
static struct synth_operations std_midi_synth =
{
&std_synth_info,
0,
SYNTH_TYPE_MIDI,
0,
midi_synth_open,
midi_synth_close,
midi_synth_ioctl,
midi_synth_kill_note,
midi_synth_start_note,
midi_synth_set_instr,
midi_synth_reset,
midi_synth_hw_control,
midi_synth_load_patch,
midi_synth_aftertouch,
midi_synth_controller,
midi_synth_panning,
NULL,
midi_synth_patchmgr,
midi_synth_bender,
NULL, /* alloc_voice */
midi_synth_setup_voice,
midi_synth_send_sysex
};
#endif

View File

@ -1,429 +0,0 @@
/*
* sound/midibuf.c
*
* Device file manager for /dev/midi#
*
* Copyright by Hannu Savolainen 1993
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. 2.
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#include <i386/isa/sound/sound_config.h>
#if defined(CONFIG_MIDI)
/*
* Don't make MAX_QUEUE_SIZE larger than 4000
*/
#define MAX_QUEUE_SIZE 4000
int
MIDIbuf_poll (int dev, struct fileinfo *file, int events, select_table * wait);
static void
drain_midi_queue(int dev);
static int *midi_sleeper[MAX_MIDI_DEV] = {NULL};
static volatile struct snd_wait midi_sleep_flag[MAX_MIDI_DEV] = { {0}};
static int *input_sleeper[MAX_MIDI_DEV] = {NULL};
static volatile struct snd_wait input_sleep_flag[MAX_MIDI_DEV] = { {0}};
struct midi_buf {
int len, head, tail;
u_char queue[MAX_QUEUE_SIZE];
};
struct midi_parms {
int prech_timeout; /* Timeout before the first ch */
};
static struct midi_buf *midi_out_buf[MAX_MIDI_DEV] = {NULL};
static struct midi_buf *midi_in_buf[MAX_MIDI_DEV] = {NULL};
static struct midi_parms parms[MAX_MIDI_DEV];
static void midi_poll(void *dummy);
static volatile int open_devs = 0;
#define DATA_AVAIL(q) (q->len)
#define SPACE_AVAIL(q) (MAX_QUEUE_SIZE - q->len)
#define QUEUE_BYTE(q, data) \
if (SPACE_AVAIL(q)) { \
u_long flags; \
flags = splhigh(); \
q->queue[q->tail] = (data); \
q->len++; q->tail = (q->tail+1) % MAX_QUEUE_SIZE; \
splx(flags); \
}
#define REMOVE_BYTE(q, data) \
if (DATA_AVAIL(q)) { \
u_long flags; \
flags = splhigh(); \
data = q->queue[q->head]; \
q->len--; q->head = (q->head+1) % MAX_QUEUE_SIZE; \
splx(flags); \
}
static void
drain_midi_queue(int dev)
{
/*
* Give the Midi driver time to drain its output queues
*/
if (midi_devs[dev]->buffer_status != NULL)
while (!(PROCESS_ABORTING (midi_sleep_flag[dev])) &&
midi_devs[dev]->buffer_status(dev)) {
int chn;
midi_sleeper[dev] = &chn;
DO_SLEEP(chn, midi_sleep_flag[dev], hz / 10);
};
}
static void
midi_input_intr(int dev, u_char data)
{
if (midi_in_buf[dev] == NULL)
return;
if (data == 0xfe) /* Active sensing */
return; /* Ignore */
if (SPACE_AVAIL(midi_in_buf[dev])) {
QUEUE_BYTE(midi_in_buf[dev], data);
if ((input_sleep_flag[dev].mode & WK_SLEEP)) {
input_sleep_flag[dev].mode = WK_WAKEUP;
wakeup(input_sleeper[dev]);
};
}
}
static void
midi_output_intr(int dev)
{
/*
* Currently NOP
*/
}
static void
midi_poll(void *dummy)
{
u_long flags;
int dev;
flags = splhigh();
if (open_devs) {
for (dev = 0; dev < num_midis; dev++)
if (midi_out_buf[dev] != NULL) {
while (DATA_AVAIL(midi_out_buf[dev]) &&
midi_devs[dev]->putc(dev,
midi_out_buf[dev]->queue[midi_out_buf[dev]->head])) {
midi_out_buf[dev]->head = (midi_out_buf[dev]->head + 1) % MAX_QUEUE_SIZE;
midi_out_buf[dev]->len--;
}
if (DATA_AVAIL(midi_out_buf[dev]) < 100 &&
(midi_sleep_flag[dev].mode & WK_SLEEP)) {
midi_sleep_flag[dev].mode = WK_WAKEUP;
wakeup(midi_sleeper[dev]);
};
}
timeout( midi_poll, 0, 1);; /* Come back later */
}
splx(flags);
}
int
MIDIbuf_open(int dev, struct fileinfo * file)
{
int mode, err;
dev = dev >> 4;
mode = file->mode & O_ACCMODE;
if (num_midis > MAX_MIDI_DEV) {
printf("Sound: FATAL ERROR: Too many midi interfaces\n");
num_midis = MAX_MIDI_DEV;
}
if (dev < 0 || dev >= num_midis) {
printf("Sound: Nonexistent MIDI interface %d\n", dev);
return -(ENXIO);
}
/*
* Interrupts disabled. Be careful
*/
if ((err = midi_devs[dev]->open(dev, mode,
midi_input_intr, midi_output_intr)) < 0) {
return err;
}
parms[dev].prech_timeout = 0;
midi_in_buf[dev] = (struct midi_buf *) malloc(sizeof(struct midi_buf), M_TEMP, M_WAITOK);
if (midi_in_buf[dev] == NULL) {
printf("midi: Can't allocate buffer\n");
midi_devs[dev]->close(dev);
return -(EIO);
}
midi_in_buf[dev]->len = midi_in_buf[dev]->head = midi_in_buf[dev]->tail = 0;
midi_out_buf[dev] = (struct midi_buf *) malloc(sizeof(struct midi_buf), M_TEMP, M_WAITOK);
if (midi_out_buf[dev] == NULL) {
printf("midi: Can't allocate buffer\n");
midi_devs[dev]->close(dev);
free(midi_in_buf[dev], M_TEMP);
midi_in_buf[dev] = NULL;
return -(EIO);
}
midi_out_buf[dev]->len = midi_out_buf[dev]->head = midi_out_buf[dev]->tail = 0;
open_devs++;
{
midi_sleep_flag[dev].aborting = 0;
midi_sleep_flag[dev].mode = WK_NONE;
};
{
input_sleep_flag[dev].aborting = 0;
input_sleep_flag[dev].mode = WK_NONE;
};
if (open_devs < 2) { /* This was first open */
{
};
timeout( midi_poll, 0, 1);; /* Start polling */
}
return err;
}
void
MIDIbuf_release(int dev, struct fileinfo * file)
{
int mode;
u_long flags;
dev = dev >> 4;
mode = file->mode & O_ACCMODE;
if (dev < 0 || dev >= num_midis)
return;
flags = splhigh();
/*
* Wait until the queue is empty
*/
if (mode != OPEN_READ) {
midi_devs[dev]->putc(dev, 0xfe); /* Active sensing to
* shut the devices */
while (!(PROCESS_ABORTING (midi_sleep_flag[dev])) &&
DATA_AVAIL(midi_out_buf[dev])) {
int chn;
midi_sleeper[dev] = &chn;
DO_SLEEP(chn, midi_sleep_flag[dev], 0);
}; /* Sync */
drain_midi_queue(dev); /* Ensure the output queues are empty */
}
splx(flags);
midi_devs[dev]->close(dev);
free(midi_in_buf[dev], M_TEMP);
free(midi_out_buf[dev], M_TEMP);
midi_in_buf[dev] = NULL;
midi_out_buf[dev] = NULL;
if (open_devs < 2) {
};
open_devs--;
}
int
MIDIbuf_write(int dev, struct fileinfo * file, snd_rw_buf * buf, int count)
{
u_long flags;
int c, n, i;
u_char tmp_data;
dev = dev >> 4;
if (!count)
return 0;
flags = splhigh();
c = 0;
while (c < count) {
n = SPACE_AVAIL(midi_out_buf[dev]);
if (n == 0) { /* No space just now. We have to sleep */
{
int chn;
midi_sleeper[dev] = &chn;
DO_SLEEP(chn, midi_sleep_flag[dev], 0);
};
if (PROCESS_ABORTING(midi_sleep_flag[dev])) {
splx(flags);
return -(EINTR);
}
n = SPACE_AVAIL(midi_out_buf[dev]);
}
if (n > (count - c))
n = count - c;
for (i = 0; i < n; i++) {
if (uiomove((char *) &tmp_data, 1, buf)) {
printf("sb: Bad copyin()!\n");
};
QUEUE_BYTE(midi_out_buf[dev], tmp_data);
c++;
}
}
splx(flags);
return c;
}
int
MIDIbuf_read(int dev, struct fileinfo * file, snd_rw_buf * buf, int count)
{
int n, c = 0;
u_long flags;
u_char tmp_data;
dev = dev >> 4;
flags = splhigh();
if (!DATA_AVAIL(midi_in_buf[dev])) { /* No data yet, wait */
{
int chn;
input_sleeper[dev] = &chn;
DO_SLEEP(chn, input_sleep_flag[dev],
parms[dev].prech_timeout);
};
if (PROCESS_ABORTING(input_sleep_flag[dev]))
c = -(EINTR); /* The user is getting restless */
}
if (c == 0 && DATA_AVAIL(midi_in_buf[dev])) { /* Got some bytes */
n = DATA_AVAIL(midi_in_buf[dev]);
if (n > count)
n = count;
c = 0;
while (c < n) {
REMOVE_BYTE(midi_in_buf[dev], tmp_data);
if (uiomove((char *) &tmp_data, 1, buf)) {
printf("sb: Bad copyout()!\n");
};
c++;
}
}
splx(flags);
return c;
}
int
MIDIbuf_ioctl(int dev, struct fileinfo * file, u_int cmd, ioctl_arg arg)
{
int val;
dev = dev >> 4;
if (((cmd >> 8) & 0xff) == 'C') {
if (midi_devs[dev]->coproc) /* Coprocessor ioctl */
return midi_devs[dev]->coproc->ioctl(midi_devs[dev]->coproc->devc, cmd, arg, 0);
else
printf("/dev/midi%d: No coprocessor for this device\n", dev);
return -(ENXIO);
} else
switch (cmd) {
case SNDCTL_MIDI_PRETIME:
val = (int) (*(int *) arg);
if (val < 0)
val = 0;
val = (hz * val) / 10;
parms[dev].prech_timeout = val;
return *(int *) arg = val;
break;
default:
return midi_devs[dev]->ioctl(dev, cmd, arg);
}
}
#ifdef ALLOW_POLL
int
MIDIbuf_poll (int dev, struct fileinfo *file, int events, select_table * wait)
{
int revents = 0;
dev = dev >> 4;
if (events & (POLLIN | POLLRDNORM))
if (!DATA_AVAIL (midi_in_buf[dev]))
selrecord(wait, &selinfo[dev]);
else
revents |= events & (POLLIN | POLLRDNORM);
if (events & (POLLOUT | POLLWRNORM))
if (SPACE_AVAIL (midi_out_buf[dev]))
selrecord(wait, &selinfo[dev]);
else
revents |= events & (POLLOUT | POLLWRNORM);
return revents;
}
#endif /* ALLOW_SELECT */
#endif

View File

@ -1,265 +0,0 @@
/*
* This is a simple program which demonstrates use of mmapped DMA buffer
* of the sound driver directly from application program.
*
* This sample program works (currently) only with Linux, FreeBSD and BSD/OS
* (FreeBSD and BSD/OS require OSS version 3.8-beta16 or later.
*
* Note! Don't use mmapped DMA buffers (direct audio) unless you have
* very good reasons to do it. Programs using this feature will not
* work with all soundcards. GUS (GF1) is one of them (GUS MAX works).
*
* This program requires version 3.5-beta7 or later of OSS
* (3.8-beta16 or later in FreeBSD and BSD/OS).
*/
#ifndef lint
static const char rcsid[] =
"$Id$";
#endif /* not lint */
#include <err.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <machine/soundcard.h>
#include <sys/time.h>
int
main()
{
int fd, sz, fsz, tmp, nfrag;
int caps;
int sd, sl=0, sp;
unsigned char data[500000], *dp = data;
caddr_t buf;
struct timeval tim;
unsigned char *op;
struct audio_buf_info info;
int frag = 0xffff000c; /* Max # fragments of 2^13=8k bytes */
fd_set writeset;
close(0);
if ((fd=open("/dev/dsp", O_RDWR, 0))==-1)
err(1, "/dev/dsp");
/*
* Then setup sampling parameters. Just sampling rate in this case.
*/
tmp = 8000;
ioctl(fd, SNDCTL_DSP_SPEED, &tmp);
/*
* Load some test data.
*/
sl = sp = 0;
if ((sd=open("smpl", O_RDONLY, 0))!=-1)
{
sl = read(sd, data, sizeof(data));
printf("%d bytes read from file.\n", sl);
close(sd);
}
else warn("smpl");
if (ioctl(fd, SNDCTL_DSP_GETCAPS, &caps)==-1)
{
warn("sorry but your sound driver is too old");
err(1, "/dev/dsp");
}
/*
* Check that the device has capability to do this. Currently just
* CS4231 based cards will work.
*
* The application should also check for DSP_CAP_MMAP bit but this
* version of driver doesn't have it yet.
*/
/* ioctl(fd, SNDCTL_DSP_SETSYNCRO, 0); */
/*
* You need version 3.5-beta7 or later of the sound driver before next
* two lines compile. There is no point to modify this program to
* compile with older driver versions since they don't have working
* mmap() support.
*/
if (!(caps & DSP_CAP_TRIGGER) ||
!(caps & DSP_CAP_MMAP))
errx(1, "sorry but your soundcard can't do this");
/*
* Select the fragment size. This is propably important only when
* the program uses select(). Fragment size defines how often
* select call returns.
*/
ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &frag);
/*
* Compute total size of the buffer. It's important to use this value
* in mmap() call.
*/
if (ioctl(fd, SNDCTL_DSP_GETOSPACE, &info)==-1)
err(1, "GETOSPACE");
sz = info.fragstotal * info.fragsize;
fsz = info.fragsize;
/*
* Call mmap().
*
* IMPORTANT NOTE!!!!!!!!!!!
*
* Full duplex audio devices have separate input and output buffers.
* It is not possible to map both of them at the same mmap() call. The buffer
* is selected based on the prot argument in the following way:
*
* - PROT_READ (alone) selects the input buffer.
* - PROT_WRITE (alone) selects the output buffer.
* - PROT_WRITE|PROT_READ together select the output buffer. This combination
* is required in BSD to make the buffer accessible. With just PROT_WRITE
* every attempt to access the returned buffer will result in segmentation/bus
* error. PROT_READ|PROT_WRITE is also permitted in Linux with OSS version
* 3.8-beta16 and later (earlier versions don't accept it).
*
* Non duplex devices have just one buffer. When an application wants to do both
* input and output it's recommended that the device is closed and re-opened when
* switching between modes. PROT_READ|PROT_WRITE can be used to open the buffer
* for both input and output (with OSS 3.8-beta16 and later) but the result may be
* unpredictable.
*/
if ((buf=mmap(NULL, sz, PROT_WRITE | PROT_READ, MAP_FILE|MAP_SHARED, fd, 0))==(caddr_t)-1)
err(1, "mmap (write)");
printf("mmap (out) returned %08x\n", buf);
op=buf;
/*
* op contains now a pointer to the DMA buffer
*/
/*
* Then it's time to start the engine. The driver doesn't allow read() and/or
* write() when the buffer is mapped. So the only way to start operation is
* to togle device's enable bits. First set them off. Setting them on enables
* recording and/or playback.
*/
tmp = 0;
ioctl(fd, SNDCTL_DSP_SETTRIGGER, &tmp);
/*
* It might be usefull to write some data to the buffer before starting.
*/
tmp = PCM_ENABLE_OUTPUT;
ioctl(fd, SNDCTL_DSP_SETTRIGGER, &tmp);
/*
* The machine is up and running now. Use SNDCTL_DSP_GETOPTR to get the
* buffer status.
*
* NOTE! The driver empties each buffer fragmen after they have been
* played. This prevents looping sound if there are some performance problems
* in the application side. For similar reasons it recommended that the
* application uses some amout of play ahead. It can rewrite the unplayed
* data later if necessary.
*/
nfrag = 0;
while (1)
{
struct count_info count;
int extra;
FD_ZERO(&writeset);
FD_SET(fd, &writeset);
tim.tv_sec = 10;
tim.tv_usec= 0;
select(fd+1, &writeset, &writeset, NULL, NULL);
/*
* SNDCTL_DSP_GETOPTR (and GETIPTR as well) return three items. The
* bytes field returns number of bytes played since start. It can be used
* as a real time clock.
*
* The blocks field returns number of fragment transitions (interrupts) since
* previous GETOPTR call. It can be used as a method to detect underrun
* situations.
*
* The ptr field is the DMA pointer inside the buffer area (in bytes from
* the beginning of total buffer area).
*/
if (ioctl(fd, SNDCTL_DSP_GETOPTR, &count)==-1)
err(1, "GETOPTR");
if (count.ptr < 0 ) count.ptr = 0;
nfrag += count.blocks;
#ifdef VERBOSE
printf("\rTotal: %09d, Fragment: %03d, Ptr: %06d",
count.bytes, nfrag, count.ptr);
fflush(stdout);
#endif
/*
* Caution! This version doesn't check for bounds of the DMA
* memory area. It's possible that the returned pointer value is not aligned
* to fragment boundaries. It may be several samples behind the boundary
* in case there was extra delay between the actual hardware interrupt and
* the time when DSP_GETOPTR was called.
*
* Don't just call memcpy() with length set to 'fragment_size' without
* first checking that the transfer really fits to the buffer area.
* A mistake of just one byte causes seg fault. It may be easiest just
* to align the returned pointer value to fragment boundary before using it.
*
* It would be very good idea to write few extra samples to next fragment
* too. Otherwise several (uninitialized) samples from next fragment
* will get played before your program gets chance to initialize them.
* Take in count the fact thaat there are other processes batling about
* the same CPU. This effect is likely to be very annoying if fragment
* size is decreased too much.
*/
/*
* Just a minor clarification to the above. The following line alings
* the pointer to fragment boundaries. Note! Don't trust that fragment
* size is always a power of 2. It may not be so in future.
*/
count.ptr = ((count.ptr+16)/fsz )*fsz;
#ifdef VERBOSE
printf(" memcpy(%6d, %4d)", (dp-data), fsz);
fflush(stdout);
#endif
/*
* Set few bytes in the beginning of next fragment too.
*/
if ((count.ptr+fsz+16) < sz) /* Last fragment? */
extra = 16;
else
extra = 0;
memcpy(op+count.ptr, dp, (fsz+extra));
dp += fsz;
if (dp > (data+sl-fsz))
dp = data;
}
exit(0);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,261 +0,0 @@
/*
* opl3.h - Definitions of the OPL-3 registers
*
* Copyright by Hannu Savolainen 1993
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
/*
* The OPL-3 mode is switched on by writing 0x01, to the offset 5
* of the right side.
*
* Another special register at the right side is at offset 4. It contains
* a bit mask defining which voices are used as 4 OP voices.
*
* The percussive mode is implemented in the left side only.
*
* With the above exeptions the both sides can be operated independently.
*
* A 4 OP voice can be created by setting the corresponding
* bit at offset 4 of the right side.
*
* For example setting the rightmost bit (0x01) changes the
* first voice on the right side to the 4 OP mode. The fourth
* voice is made inaccessible.
*
* If a voice is set to the 2 OP mode, it works like 2 OP modes
* of the original YM3812 (AdLib). In addition the voice can
* be connected the left, right or both stereo channels. It can
* even be left unconnected. This works with 4 OP voices also.
*
* The stereo connection bits are located in the FEEDBACK_CONNECTION
* register of the voice (0xC0-0xC8). In 4 OP voices these bits are
* in the second half of the voice.
*/
/*
* Register numbers for the global registers
*/
#define TEST_REGISTER 0x01
#define ENABLE_WAVE_SELECT 0x20
#define TIMER1_REGISTER 0x02
#define TIMER2_REGISTER 0x03
#define TIMER_CONTROL_REGISTER 0x04 /* Left side */
#define IRQ_RESET 0x80
#define TIMER1_MASK 0x40
#define TIMER2_MASK 0x20
#define TIMER1_START 0x01
#define TIMER2_START 0x02
#define CONNECTION_SELECT_REGISTER 0x04 /* Right side */
#define RIGHT_4OP_0 0x01
#define RIGHT_4OP_1 0x02
#define RIGHT_4OP_2 0x04
#define LEFT_4OP_0 0x08
#define LEFT_4OP_1 0x10
#define LEFT_4OP_2 0x20
#define OPL3_MODE_REGISTER 0x05 /* Right side */
#define OPL3_ENABLE 0x01
#define OPL4_ENABLE 0x02
#define KBD_SPLIT_REGISTER 0x08 /* Left side */
#define COMPOSITE_SINE_WAVE_MODE 0x80 /* Don't use with OPL-3? */
#define KEYBOARD_SPLIT 0x40
#define PERCUSSION_REGISTER 0xbd /* Left side only */
#define TREMOLO_DEPTH 0x80
#define VIBRATO_DEPTH 0x40
#define PERCUSSION_ENABLE 0x20
#define BASSDRUM_ON 0x10
#define SNAREDRUM_ON 0x08
#define TOMTOM_ON 0x04
#define CYMBAL_ON 0x02
#define HIHAT_ON 0x01
/*
* Offsets to the register banks for operators. To get the
* register number just add the operator offset to the bank offset
*
* AM/VIB/EG/KSR/Multiple (0x20 to 0x35)
*/
#define AM_VIB 0x20
#define TREMOLO_ON 0x80
#define VIBRATO_ON 0x40
#define SUSTAIN_ON 0x20
#define KSR 0x10 /* Key scaling rate */
#define MULTIPLE_MASK 0x0f /* Frequency multiplier */
/*
* KSL/Total level (0x40 to 0x55)
*/
#define KSL_LEVEL 0x40
#define KSL_MASK 0xc0 /* Envelope scaling bits */
#define TOTAL_LEVEL_MASK 0x3f /* Strength (volume) of OP */
/*
* Attack / Decay rate (0x60 to 0x75)
*/
#define ATTACK_DECAY 0x60
#define ATTACK_MASK 0xf0
#define DECAY_MASK 0x0f
/*
* Sustain level / Release rate (0x80 to 0x95)
*/
#define SUSTAIN_RELEASE 0x80
#define SUSTAIN_MASK 0xf0
#define RELEASE_MASK 0x0f
/*
* Wave select (0xE0 to 0xF5)
*/
#define WAVE_SELECT 0xe0
/*
* Offsets to the register banks for voices. Just add to the
* voice number to get the register number.
*
* F-Number low bits (0xA0 to 0xA8).
*/
#define FNUM_LOW 0xa0
/*
* F-number high bits / Key on / Block (octave) (0xB0 to 0xB8)
*/
#define KEYON_BLOCK 0xb0
#define KEYON_BIT 0x20
#define BLOCKNUM_MASK 0x1c
#define FNUM_HIGH_MASK 0x03
/*
* Feedback / Connection (0xc0 to 0xc8)
*
* These registers have two new bits when the OPL-3 mode
* is selected. These bits controls connecting the voice
* to the stereo channels. For 4 OP voices this bit is
* defined in the second half of the voice (add 3 to the
* register offset).
*
* For 4 OP voices the connection bit is used in the
* both halfs (gives 4 ways to connect the operators).
*/
#define FEEDBACK_CONNECTION 0xc0
#define FEEDBACK_MASK 0x0e /* Valid just for 1st OP of a voice */
#define CONNECTION_BIT 0x01
/*
* In the 4 OP mode there is four possible configurations how the
* operators can be connected together (in 2 OP modes there is just
* AM or FM). The 4 OP connection mode is defined by the rightmost
* bit of the FEEDBACK_CONNECTION (0xC0-0xC8) on the both halfs.
*
* First half Second half Mode
*
* +---+
* v |
* 0 0 >+-1-+--2--3--4-->
*
*
*
* +---+
* | |
* 0 1 >+-1-+--2-+
* |->
* >--3----4-+
*
* +---+
* | |
* 1 0 >+-1-+-----+
* |->
* >--2--3--4-+
*
* +---+
* | |
* 1 1 >+-1-+--+
* |
* >--2--3-+->
* |
* >--4----+
*/
#define STEREO_BITS 0x30 /* OPL-3 only */
#define VOICE_TO_LEFT 0x10
#define VOICE_TO_RIGHT 0x20
/*
* Definition table for the physical voices
*/
struct physical_voice_info {
unsigned char voice_num;
unsigned char voice_mode; /* 0=unavailable, 2=2 OP, 4=4 OP */
unsigned short ioaddr; /* I/O port (left or right side) */
unsigned char op[4]; /* Operator offsets */
};
/*
* There is 18 possible 2 OP voices
* (9 in the left and 9 in the right).
* The first OP is the modulator and 2nd is the carrier.
*
* The first three voices in the both sides may be connected
* with another voice to a 4 OP voice. For example voice 0
* can be connected with voice 3. The operators of voice 3 are
* used as operators 3 and 4 of the new 4 OP voice.
* In this case the 2 OP voice number 0 is the 'first half' and
* voice 3 is the second.
*/
#define USE_LEFT 0
#define USE_RIGHT 1
static struct physical_voice_info pv_map[18] =
{
/* No Mode Side OP1 OP2 OP3 OP4 */
/* --------------------------------------------------- */
{ 0, 2, USE_LEFT, {0x00, 0x03, 0x08, 0x0b}},
{ 1, 2, USE_LEFT, {0x01, 0x04, 0x09, 0x0c}},
{ 2, 2, USE_LEFT, {0x02, 0x05, 0x0a, 0x0d}},
{ 3, 2, USE_LEFT, {0x08, 0x0b, 0x00, 0x00}},
{ 4, 2, USE_LEFT, {0x09, 0x0c, 0x00, 0x00}},
{ 5, 2, USE_LEFT, {0x0a, 0x0d, 0x00, 0x00}},
{ 6, 2, USE_LEFT, {0x10, 0x13, 0x00, 0x00}}, /* Used by percussive voices */
{ 7, 2, USE_LEFT, {0x11, 0x14, 0x00, 0x00}}, /* if the percussive mode */
{ 8, 2, USE_LEFT, {0x12, 0x15, 0x00, 0x00}}, /* is selected */
{ 0, 2, USE_RIGHT, {0x00, 0x03, 0x08, 0x0b}},
{ 1, 2, USE_RIGHT, {0x01, 0x04, 0x09, 0x0c}},
{ 2, 2, USE_RIGHT, {0x02, 0x05, 0x0a, 0x0d}},
{ 3, 2, USE_RIGHT, {0x08, 0x0b, 0x00, 0x00}},
{ 4, 2, USE_RIGHT, {0x09, 0x0c, 0x00, 0x00}},
{ 5, 2, USE_RIGHT, {0x0a, 0x0d, 0x00, 0x00}},
{ 6, 2, USE_RIGHT, {0x10, 0x13, 0x00, 0x00}},
{ 7, 2, USE_RIGHT, {0x11, 0x14, 0x00, 0x00}},
{ 8, 2, USE_RIGHT, {0x12, 0x15, 0x00, 0x00}}
};

View File

@ -1,99 +0,0 @@
/*
* os.h -- only included by sound_config.h right after local.h
*
*/
#ifndef _OS_H_
#define _OS_H_
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/proc.h>
#include <sys/conf.h>
#include <sys/fcntl.h>
#include <sys/filio.h>
#include <sys/uio.h>
#include <sys/kernel.h>
#include <sys/poll.h>
#include <sys/malloc.h>
#include <sys/buf.h>
#include <sys/signalvar.h>
#include <machine/soundcard.h>
#include <i386/isa/isa_device.h>
#undef DELAY
#define DELAY(x) tenmicrosec(x)
typedef struct uio snd_rw_buf;
struct snd_wait {
int mode;
int aborting;
};
unsigned long get_time(void);
#endif /* _OS_H_ */
typedef caddr_t ioctl_arg;
typedef struct sound_os_info {
int unit;
} sound_os_info;
/*
* The following macro calls tsleep. It should be implemented such that
* the process is resumed if it receives a signal.
* The q parameter is a wait_queue defined with DEFINE_WAIT_QUEUE(),
* and the second is a workarea parameter. The third is a timeout
* in ticks. Zero means no timeout.
*/
#define DO_SLEEP(q, f, time_limit) \
{ \
int flag; \
f.mode = WK_SLEEP; \
flag=tsleep(&q, (PRIBIO-5)|PCATCH, "sndint", time_limit); \
f.mode &= ~WK_SLEEP; \
if (flag == EWOULDBLOCK) { \
f.mode |= WK_TIMEOUT; \
f.aborting = 0; \
} else \
f.aborting = flag; \
}
#define DO_SLEEP1(q, f, time_limit) \
{ \
int flag; \
f.mode = WK_SLEEP; \
flag=tsleep(&q, (PRIBIO-5)|PCATCH, "snd1", time_limit); \
f.mode &= ~WK_SLEEP; \
if (flag == EWOULDBLOCK) { \
f.mode |= WK_TIMEOUT; \
f.aborting = 0; \
} else \
f.aborting = flag; \
}
#define DO_SLEEP2(q, f, time_limit) \
{ \
int flag; \
f.mode = WK_SLEEP; \
flag=tsleep(&q, (PRIBIO-5)|PCATCH, "snd2", time_limit); \
f.mode &= ~WK_SLEEP; \
if (flag == EWOULDBLOCK) { \
f.mode |= WK_TIMEOUT; \
f.aborting = 0; \
} else \
f.aborting = flag; \
}
#define PROCESS_ABORTING( f) (f.aborting || CURSIG(curproc))
#define TIMED_OUT( f) (f.mode & WK_TIMEOUT)
#ifdef ALLOW_POLL
typedef struct proc select_table;
extern struct selinfo selinfo[];
#endif

View File

@ -1,361 +0,0 @@
/*
* sound/pas2_card.c
*
* Detection routine for the Pro Audio Spectrum cards.
*
* Copyright by Hannu Savolainen 1993
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. 2.
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#include <i386/isa/sound/sound_config.h>
#if defined(CONFIG_PAS)
#define _PAS2_CARD_C_
#define DEFINE_TRANSLATIONS
#include <i386/isa/sound/pas_hw.h>
/*
* The Address Translation code is used to convert I/O register addresses to
* be relative to the given base -register
*/
int translat_code;
static int pas_intr_mask = 0;
static int pas_irq = 0;
static sound_os_info *pas_osp;
char pas_model;
static char *pas_model_names[] =
{"", "Pro AudioSpectrum+", "CDPC", "Pro AudioSpectrum 16", "Pro AudioSpectrum 16D"};
/*
* pas_read() and pas_write() are equivalents of inb and outb
*/
/*
* These routines perform the I/O address translation required
*/
/*
* to support other than the default base address
*/
extern void mix_write(u_char data, int ioaddr);
u_char
pas_read(int ioaddr)
{
return inb(ioaddr ^ translat_code);
}
void
pas_write(u_char data, int ioaddr)
{
outb(ioaddr ^ translat_code, data);
}
static void
pas2_msg(char *foo)
{
printf(" PAS2: %s.\n", foo);
}
/******************* Begin of the Interrupt Handler ********************/
void
pasintr(int irq)
{
int status;
status = pas_read(INTERRUPT_STATUS);
pas_write(status, INTERRUPT_STATUS); /* Clear interrupt */
if (status & I_S_PCM_SAMPLE_BUFFER_IRQ) {
#ifdef CONFIG_AUDIO
pas_pcm_interrupt(status, 1);
#endif
status &= ~I_S_PCM_SAMPLE_BUFFER_IRQ;
}
if (status & I_S_MIDI_IRQ) {
#ifdef CONFIG_MIDI
pas_midi_interrupt();
#endif
status &= ~I_S_MIDI_IRQ;
}
}
int
pas_set_intr(int mask)
{
if (!mask)
return 0;
pas_intr_mask |= mask;
pas_write(pas_intr_mask, INTERRUPT_MASK);
return 0;
}
int
pas_remove_intr(int mask)
{
if (!mask)
return 0;
pas_intr_mask &= ~mask;
pas_write(pas_intr_mask, INTERRUPT_MASK);
return 0;
}
/******************* End of the Interrupt handler **********************/
/******************* Begin of the Initialization Code ******************/
static int
config_pas_hw(struct address_info * hw_config)
{
char ok = 1;
u_int int_ptrs; /* scsi/sound interrupt pointers */
pas_irq = hw_config->irq;
pas_write(0x00, INTERRUPT_MASK);
pas_write(0x36, SAMPLE_COUNTER_CONTROL); /* Local timer control *
* register */
pas_write(0x36, SAMPLE_RATE_TIMER); /* Sample rate timer (16 bit) */
pas_write(0, SAMPLE_RATE_TIMER);
pas_write(0x74, SAMPLE_COUNTER_CONTROL); /* Local timer control *
* register */
pas_write(0x74, SAMPLE_BUFFER_COUNTER); /* Sample count register (16 *
* bit) */
pas_write(0, SAMPLE_BUFFER_COUNTER);
pas_write(F_F_PCM_BUFFER_COUNTER | F_F_PCM_RATE_COUNTER | F_F_MIXER_UNMUTE | 1, FILTER_FREQUENCY);
pas_write(P_C_PCM_DMA_ENABLE | P_C_PCM_MONO | P_C_PCM_DAC_MODE | P_C_MIXER_CROSS_L_TO_L | P_C_MIXER_CROSS_R_TO_R, PCM_CONTROL);
pas_write(S_M_PCM_RESET | S_M_FM_RESET | S_M_SB_RESET | S_M_MIXER_RESET /* | S_M_OPL3_DUAL_MONO */ , SERIAL_MIXER);
pas_write(I_C_1_BOOT_RESET_ENABLE
#ifdef PAS_JOYSTICK_ENABLE
| I_C_1_JOYSTICK_ENABLE
#endif
,IO_CONFIGURATION_1);
if (pas_irq < 0 || pas_irq > 15) {
printf("PAS2: Invalid IRQ %d", pas_irq);
ok = 0;
} else {
int_ptrs = pas_read(IO_CONFIGURATION_3);
int_ptrs |= I_C_3_PCM_IRQ_translate[pas_irq] & 0xf;
pas_write(int_ptrs, IO_CONFIGURATION_3);
if (!I_C_3_PCM_IRQ_translate[pas_irq]) {
printf("PAS2: Invalid IRQ %d", pas_irq);
ok = 0;
} else {
if (snd_set_irq_handler(pas_irq, pasintr, hw_config->osp) < 0)
ok = 0;
}
}
if (hw_config->dma < 0 || hw_config->dma > 7) {
printf("PAS2: Invalid DMA selection %d", hw_config->dma);
ok = 0;
} else {
pas_write(I_C_2_PCM_DMA_translate[hw_config->dma], IO_CONFIGURATION_2);
if (!I_C_2_PCM_DMA_translate[hw_config->dma]) {
printf("PAS2: Invalid DMA selection %d", hw_config->dma);
ok = 0;
} else {
if (0) {
printf("pas2_card.c: Can't allocate DMA channel\n");
ok = 0;
}
}
}
/*
* This fixes the timing problems of the PAS due to the Symphony
* chipset as per Media Vision. Only define this if your PAS doesn't
* work correctly.
*/
#ifdef SYMPHONY_PAS
outb(0xa8, 0x05);
outb(0xa9, 0x60);
#endif
#ifdef BROKEN_BUS_CLOCK
pas_write(S_C_1_PCS_ENABLE | S_C_1_PCS_STEREO | S_C_1_PCS_REALSOUND | S_C_1_FM_EMULATE_CLOCK, SYSTEM_CONFIGURATION_1);
#else
/*
* pas_write(S_C_1_PCS_ENABLE, SYSTEM_CONFIGURATION_1);
*/
pas_write(S_C_1_PCS_ENABLE | S_C_1_PCS_STEREO | S_C_1_PCS_REALSOUND, SYSTEM_CONFIGURATION_1);
#endif
pas_write(0x18, SYSTEM_CONFIGURATION_3); /* ??? */
pas_write(F_F_MIXER_UNMUTE | 0x01, FILTER_FREQUENCY); /* Sets mute off and *
* selects filter rate *
* of 17.897 kHz */
pas_write(8, PRESCALE_DIVIDER);
mix_write(P_M_MV508_ADDRESS | 5, PARALLEL_MIXER);
mix_write(5, PARALLEL_MIXER);
#if defined(CONFIG_SB_EMULATION) && defined(CONFIG_SB)
{
struct address_info *sb_config;
if ((sb_config = sound_getconf(SNDCARD_SB))) {
u_char irq_dma;
/*
* Turn on Sound Blaster compatibility
*/
/*
* bit 1 = SB emulation
*/
/*
* bit 0 = MPU401 emulation (CDPC only :-( )
*/
pas_write(0x02, COMPATIBILITY_ENABLE);
/*
* "Emulation address"
*/
pas_write((sb_config->io_base >> 4) & 0x0f, EMULATION_ADDRESS);
if (!E_C_SB_DMA_translate[sb_config->dma])
printf("\n\nPAS16 Warning: Invalid SB DMA %d\n\n",
sb_config->dma);
if (!E_C_SB_IRQ_translate[sb_config->irq])
printf("\n\nPAS16 Warning: Invalid SB IRQ %d\n\n",
sb_config->irq);
irq_dma = E_C_SB_DMA_translate[sb_config->dma] |
E_C_SB_IRQ_translate[sb_config->irq];
pas_write(irq_dma, EMULATION_CONFIGURATION);
}
}
#else
pas_write(0x00, COMPATIBILITY_ENABLE);
#endif
if (!ok)
pas2_msg("Driver not enabled");
return ok;
}
static int
detect_pas_hw(struct address_info * hw_config)
{
u_char board_id, foo;
/*
* WARNING: Setting an option like W:1 or so that disables warm boot
* reset of the card will screw up this detect code something fierce.
* Adding code to handle this means possibly interfering with other
* cards on the bus if you have something on base port 0x388. SO be
* forewarned.
*/
outb(MASTER_DECODE, 0xBC); /* Talk to first board */
outb(MASTER_DECODE, hw_config->io_base >> 2); /* Set base address */
translat_code = PAS_DEFAULT_BASE ^ hw_config->io_base;
pas_write(1, WAIT_STATE); /* One wait-state */
board_id = pas_read(INTERRUPT_MASK);
if (board_id == 0xff)
return 0;
/*
* We probably have a PAS-series board, now check for a PAS2-series
* board by trying to change the board revision bits. PAS2-series
* hardware won't let you do this - the bits are read-only.
*/
foo = board_id ^ 0xe0;
pas_write(foo, INTERRUPT_MASK);
foo = inb(INTERRUPT_MASK);
pas_write(board_id, INTERRUPT_MASK);
if (board_id != foo) /* Not a PAS2 */
return 0;
pas_model = pas_read(CHIP_REV);
return pas_model;
}
void
attach_pas_card(struct address_info * hw_config)
{
pas_irq = hw_config->irq;
pas_osp = hw_config->osp;
if (detect_pas_hw(hw_config)) {
if ((pas_model = pas_read(CHIP_REV))) {
char temp[100];
snprintf(temp, sizeof(temp),
"%s rev %d", pas_model_names[(int) pas_model],
pas_read(BOARD_REV_ID));
conf_printf(temp, hw_config);
}
if (config_pas_hw(hw_config)) {
#ifdef CONFIG_AUDIO
pas_pcm_init(hw_config);
#endif
#if defined(CONFIG_SB_EMULATION) && defined(CONFIG_SB)
sb_dsp_disable_midi(); /* The SB emulation don't
* support * midi */
#endif
#ifdef CONFIG_MIDI
pas_midi_init();
#endif
pas_init_mixer();
}
}
}
int
probe_pas(struct address_info * hw_config)
{
pas_osp = hw_config->osp;
return detect_pas_hw(hw_config);
}
#endif

View File

@ -1,285 +0,0 @@
/*
* sound/pas2_midi.c
*
* The low level driver for the PAS Midi Interface.
*
* Copyright by Hannu Savolainen 1993
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. 2.
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#include <i386/isa/sound/sound_config.h>
#if defined(CONFIG_PAS) && defined(CONFIG_MIDI)
#include <i386/isa/sound/pas_hw.h>
static int midi_busy = 0, input_opened = 0;
static int my_dev;
static volatile int ofifo_bytes = 0;
static u_char tmp_queue[256];
static volatile int qlen;
static volatile u_char qhead, qtail;
static void (*midi_input_intr) (int dev, u_char data);
static int
pas_midi_open(int dev, int mode,
void (*input) (int dev, u_char data),
void (*output) (int dev)
)
{
int err;
u_long flags;
u_char ctrl;
if (midi_busy) {
printf("PAS2: Midi busy\n");
return -(EBUSY);
}
/*
* Reset input and output FIFO pointers
*/
pas_write(M_C_RESET_INPUT_FIFO | M_C_RESET_OUTPUT_FIFO,
MIDI_CONTROL);
flags = splhigh();
if ((err = pas_set_intr(I_M_MIDI_IRQ_ENABLE)) < 0)
return err;
/*
* Enable input available and output FIFO empty interrupts
*/
ctrl = 0;
input_opened = 0;
midi_input_intr = input;
if (mode == OPEN_READ || mode == OPEN_READWRITE) {
ctrl |= M_C_ENA_INPUT_IRQ; /* Enable input */
input_opened = 1;
}
if (mode == OPEN_WRITE || mode == OPEN_READWRITE) {
ctrl |= M_C_ENA_OUTPUT_IRQ | /* Enable output */
M_C_ENA_OUTPUT_HALF_IRQ;
}
pas_write(ctrl,
MIDI_CONTROL);
/*
* Acknowledge any pending interrupts
*/
pas_write(0xff, MIDI_STATUS);
ofifo_bytes = 0;
splx(flags);
midi_busy = 1;
qlen = qhead = qtail = 0;
return 0;
}
static void
pas_midi_close(int dev)
{
/*
* Reset FIFO pointers, disable intrs
*/
pas_write(M_C_RESET_INPUT_FIFO | M_C_RESET_OUTPUT_FIFO, MIDI_CONTROL);
pas_remove_intr(I_M_MIDI_IRQ_ENABLE);
midi_busy = 0;
}
static int
dump_to_midi(u_char midi_byte)
{
int fifo_space, x;
fifo_space = ((x = pas_read(MIDI_FIFO_STATUS)) >> 4) & 0x0f;
if (fifo_space == 15 || (fifo_space < 2 && ofifo_bytes > 13)) { /* Fifo full */
return 0; /* Upper layer will call again */
}
ofifo_bytes++;
pas_write(midi_byte, MIDI_DATA);
return 1;
}
static int
pas_midi_out(int dev, u_char midi_byte)
{
u_long flags;
/*
* Drain the local queue first
*/
flags = splhigh();
while (qlen && dump_to_midi(tmp_queue[qhead])) {
qlen--;
qhead++;
}
splx(flags);
/*
* Output the byte if the local queue is empty.
*/
if (!qlen)
if (dump_to_midi(midi_byte))
return 1; /* OK */
/*
* Put to the local queue
*/
if (qlen >= 256)
return 0; /* Local queue full */
flags = splhigh();
tmp_queue[qtail] = midi_byte;
qlen++;
qtail++;
splx(flags);
return 1;
}
static int
pas_midi_start_read(int dev)
{
return 0;
}
static int
pas_midi_end_read(int dev)
{
return 0;
}
static int
pas_midi_ioctl(int dev, u_int cmd, ioctl_arg arg)
{
return -(EINVAL);
}
static void
pas_midi_kick(int dev)
{
ofifo_bytes = 0;
}
static int
pas_buffer_status(int dev)
{
return qlen;
}
#define MIDI_SYNTH_NAME "Pro Audio Spectrum Midi"
#define MIDI_SYNTH_CAPS SYNTH_CAP_INPUT
#include <i386/isa/sound/midi_synth.h>
static struct midi_operations pas_midi_operations =
{
{"Pro Audio Spectrum", 0, 0, SNDCARD_PAS},
&std_midi_synth,
{0},
pas_midi_open,
pas_midi_close,
pas_midi_ioctl,
pas_midi_out,
pas_midi_start_read,
pas_midi_end_read,
pas_midi_kick,
NULL, /* command */
pas_buffer_status,
NULL
};
void
pas_midi_init()
{
if (num_midis >= MAX_MIDI_DEV) {
printf("Sound: Too many midi devices detected\n");
return;
}
std_midi_synth.midi_dev = my_dev = num_midis;
midi_devs[num_midis++] = &pas_midi_operations;
return;
}
void
pas_midi_interrupt(void)
{
u_char stat;
int i, incount;
u_long flags;
stat = pas_read(MIDI_STATUS);
if (stat & M_S_INPUT_AVAIL) { /* Input byte available */
incount = pas_read(MIDI_FIFO_STATUS) & 0x0f; /* Input FIFO count */
if (!incount)
incount = 16;
for (i = 0; i < incount; i++)
if (input_opened) {
midi_input_intr(my_dev, pas_read(MIDI_DATA));
} else
pas_read(MIDI_DATA); /* Flush */
}
if (stat & (M_S_OUTPUT_EMPTY | M_S_OUTPUT_HALF_EMPTY)) {
if (!(stat & M_S_OUTPUT_EMPTY)) {
ofifo_bytes = 8;
} else {
ofifo_bytes = 0;
}
flags = splhigh();
while (qlen && dump_to_midi(tmp_queue[qhead])) {
qlen--;
qhead++;
}
splx(flags);
}
if (stat & M_S_OUTPUT_OVERRUN) {
printf("MIDI output overrun %x,%x,%d \n", pas_read(MIDI_FIFO_STATUS), stat, ofifo_bytes);
ofifo_bytes = 100;
}
pas_write(stat, MIDI_STATUS); /* Acknowledge interrupts */
}
#endif

View File

@ -1,322 +0,0 @@
/*
* sound/pas2_mixer.c
*
* Mixer routines for the Pro Audio Spectrum cards.
*
* Copyright by Hannu Savolainen 1993
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
* 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.
*
*/
#define _PAS2_MIXER_C_
#include <i386/isa/sound/sound_config.h>
#if defined(CONFIG_PAS)
#include <i386/isa/sound/pas_hw.h>
#define TRACE(what) /* (what) */
extern int translat_code;
extern char pas_model;
extern sound_os_info *pas_osp;
static int rec_devices = (SOUND_MASK_MIC); /* Default recording source */
static int mode_control = 0;
#define POSSIBLE_RECORDING_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_SPEAKER | SOUND_MASK_LINE | SOUND_MASK_MIC | \
SOUND_MASK_CD | SOUND_MASK_ALTPCM)
#define SUPPORTED_MIXER_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_SPEAKER | SOUND_MASK_LINE | SOUND_MASK_MIC | \
SOUND_MASK_CD | SOUND_MASK_ALTPCM | SOUND_MASK_IMIX | \
SOUND_MASK_VOLUME | SOUND_MASK_BASS | SOUND_MASK_TREBLE | SOUND_MASK_RECLEV | \
SOUND_MASK_MUTE | SOUND_MASK_ENHANCE | SOUND_MASK_LOUD)
static u_short levels[SOUND_MIXER_NRDEVICES] =
{
0x3232, /* Master Volume */
0x3232, /* Bass */
0x3232, /* Treble */
0x5050, /* FM */
0x4b4b, /* PCM */
0x3232, /* PC Speaker */
0x4b4b, /* Ext Line */
0x4b4b, /* Mic */
0x4b4b, /* CD */
0x6464, /* Recording monitor */
0x4b4b, /* SB PCM */
0x6464 /* Recording level */
};
void
mix_write(u_char data, int ioaddr)
{
/*
* The Revision D cards have a problem with their MVA508 interface.
* The kludge-o-rama fix is to make a 16-bit quantity with identical
* LSB and MSBs out of the output byte and to do a 16-bit out to the
* mixer port - 1. We need to do this because it isn't timing problem
* but chip access sequence problem.
*/
if (pas_model == PAS_16D) {
outw((ioaddr ^ translat_code) - 1, data | (data << 8));
outb(0, 0x80);
} else
pas_write(data, ioaddr);
}
static int
mixer_output(int right_vol, int left_vol, int div, int bits,
int mixer)
{ /* Input or output mixer */
int left = left_vol * div / 100;
int right = right_vol * div / 100;
if (bits & P_M_MV508_MIXER) { /* Select input or output mixer */
left |= mixer;
right |= mixer;
}
if (bits == P_M_MV508_BASS || bits == P_M_MV508_TREBLE) { /* Bass and treble are
* mono devices */
mix_write(P_M_MV508_ADDRESS | bits, PARALLEL_MIXER);
mix_write(left, PARALLEL_MIXER);
right_vol = left_vol;
} else {
mix_write(P_M_MV508_ADDRESS | P_M_MV508_LEFT | bits, PARALLEL_MIXER);
mix_write(left, PARALLEL_MIXER);
mix_write(P_M_MV508_ADDRESS | P_M_MV508_RIGHT | bits, PARALLEL_MIXER);
mix_write(right, PARALLEL_MIXER);
}
return (left_vol | (right_vol << 8));
}
static void
set_mode(int new_mode)
{
mix_write(P_M_MV508_ADDRESS | P_M_MV508_MODE, PARALLEL_MIXER);
mix_write(new_mode, PARALLEL_MIXER);
mode_control = new_mode;
}
static int
pas_mixer_set(int whichDev, u_int level)
{
int left, right, devmask, changed, i, mixer = 0;
TRACE(printf("static int pas_mixer_set(int whichDev = %d, u_int level = %X)\n", whichDev, level));
left = level & 0x7f;
right = (level & 0x7f00) >> 8;
if (whichDev < SOUND_MIXER_NRDEVICES)
if ((1 << whichDev) & rec_devices)
mixer = P_M_MV508_INPUTMIX;
else
mixer = P_M_MV508_OUTPUTMIX;
switch (whichDev) {
case SOUND_MIXER_VOLUME: /* Master volume (0-63) */
levels[whichDev] = mixer_output(right, left, 63, P_M_MV508_MASTER_A, 0);
break;
/*
* Note! Bass and Treble are mono devices. Will use just the
* left channel.
*/
case SOUND_MIXER_BASS: /* Bass (0-12) */
levels[whichDev] = mixer_output(right, left, 12, P_M_MV508_BASS, 0);
break;
case SOUND_MIXER_TREBLE: /* Treble (0-12) */
levels[whichDev] = mixer_output(right, left, 12, P_M_MV508_TREBLE, 0);
break;
case SOUND_MIXER_SYNTH:/* Internal synthesizer (0-31) */
levels[whichDev] = mixer_output(right, left, 31, P_M_MV508_MIXER | P_M_MV508_FM, mixer);
break;
case SOUND_MIXER_PCM: /* PAS PCM (0-31) */
levels[whichDev] = mixer_output(right, left, 31, P_M_MV508_MIXER | P_M_MV508_PCM, mixer);
break;
case SOUND_MIXER_ALTPCM: /* SB PCM (0-31) */
levels[whichDev] = mixer_output(right, left, 31, P_M_MV508_MIXER | P_M_MV508_SB, mixer);
break;
case SOUND_MIXER_SPEAKER: /* PC speaker (0-31) */
levels[whichDev] = mixer_output(right, left, 31, P_M_MV508_MIXER | P_M_MV508_SPEAKER, mixer);
break;
case SOUND_MIXER_LINE: /* External line (0-31) */
levels[whichDev] = mixer_output(right, left, 31, P_M_MV508_MIXER | P_M_MV508_LINE, mixer);
break;
case SOUND_MIXER_CD: /* CD (0-31) */
levels[whichDev] = mixer_output(right, left, 31, P_M_MV508_MIXER | P_M_MV508_CDROM, mixer);
break;
case SOUND_MIXER_MIC: /* External microphone (0-31) */
levels[whichDev] = mixer_output(right, left, 31, P_M_MV508_MIXER | P_M_MV508_MIC, mixer);
break;
case SOUND_MIXER_IMIX: /* Recording monitor (0-31) (Output mixer
* only) */
levels[whichDev] = mixer_output(right, left, 31, P_M_MV508_MIXER | P_M_MV508_IMIXER,
P_M_MV508_OUTPUTMIX);
break;
case SOUND_MIXER_RECLEV: /* Recording level (0-15) */
levels[whichDev] = mixer_output(right, left, 15, P_M_MV508_MASTER_B, 0);
break;
case SOUND_MIXER_MUTE:
return 0;
break;
case SOUND_MIXER_ENHANCE:
i = 0;
level &= 0x7f;
if (level)
i = (level / 20) - 1;
mode_control &= ~P_M_MV508_ENHANCE_BITS;
mode_control |= P_M_MV508_ENHANCE_BITS;
set_mode(mode_control);
if (i)
i = (i + 1) * 20;
return i;
break;
case SOUND_MIXER_LOUD:
mode_control &= ~P_M_MV508_LOUDNESS;
if (level)
mode_control |= P_M_MV508_LOUDNESS;
set_mode(mode_control);
return !!level; /* 0 or 1 */
break;
case SOUND_MIXER_RECSRC:
devmask = level & POSSIBLE_RECORDING_DEVICES;
changed = devmask ^ rec_devices;
rec_devices = devmask;
for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
if (changed & (1 << i)) {
pas_mixer_set(i, levels[i]);
}
return rec_devices;
break;
default:
return -(EINVAL);
}
return (levels[whichDev]);
}
/*****/
static void
pas_mixer_reset(void)
{
int foo;
TRACE(printf("pas2_mixer.c: void pas_mixer_reset(void)\n"));
for (foo = 0; foo < SOUND_MIXER_NRDEVICES; foo++)
pas_mixer_set(foo, levels[foo]);
set_mode(P_M_MV508_LOUDNESS | P_M_MV508_ENHANCE_40);
}
static int
pas_mixer_ioctl(int dev, u_int cmd, ioctl_arg arg)
{
TRACE(printf("pas2_mixer.c: int pas_mixer_ioctl(u_int cmd = %X, u_int arg = %X)\n", cmd, arg));
if (((cmd >> 8) & 0xff) == 'M') {
if (cmd & IOC_IN)
return *(int *) arg = pas_mixer_set(cmd & 0xff, (*(int *) arg));
else { /* Read parameters */
switch (cmd & 0xff) {
case SOUND_MIXER_RECSRC:
return *(int *) arg = rec_devices;
break;
case SOUND_MIXER_STEREODEVS:
return *(int *) arg = SUPPORTED_MIXER_DEVICES & ~(SOUND_MASK_BASS | SOUND_MASK_TREBLE);
break;
case SOUND_MIXER_DEVMASK:
return *(int *) arg = SUPPORTED_MIXER_DEVICES;
break;
case SOUND_MIXER_RECMASK:
return *(int *) arg = POSSIBLE_RECORDING_DEVICES & SUPPORTED_MIXER_DEVICES;
break;
case SOUND_MIXER_CAPS:
return *(int *) arg = 0; /* No special
* capabilities */
break;
case SOUND_MIXER_MUTE:
return *(int *) arg = 0; /* No mute yet */
break;
case SOUND_MIXER_ENHANCE:
if (!(mode_control & P_M_MV508_ENHANCE_BITS))
return *(int *) arg = 0;
return *(int *) arg = ((mode_control & P_M_MV508_ENHANCE_BITS) + 1) * 20;
break;
case SOUND_MIXER_LOUD:
if (mode_control & P_M_MV508_LOUDNESS)
return *(int *) arg = 1;
return *(int *) arg = 0;
break;
default:
return *(int *) arg = levels[cmd & 0xff];
}
}
}
return -(EINVAL);
}
static struct mixer_operations pas_mixer_operations =
{
"Pro Audio Spectrum 16",
pas_mixer_ioctl
};
int
pas_init_mixer(void)
{
pas_mixer_reset();
if (num_mixers < MAX_MIXER_DEV)
mixer_devs[num_mixers++] = &pas_mixer_operations;
return 1;
}
#endif

View File

@ -1,449 +0,0 @@
#define _PAS2_PCM_C_
/*
* sound/pas2_pcm.c
*
* The low level driver for the Pro Audio Spectrum ADC/DAC.
*
* Copyright by Hannu Savolainen 1993
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. 2.
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#include <i386/isa/sound/sound_config.h>
#if defined(CONFIG_PAS) && defined(CONFIG_AUDIO)
#include <i386/isa/sound/pas_hw.h>
#define TRACE(WHAT) /* * * (WHAT) */
#define PAS_PCM_INTRBITS (0x08)
/*
* Sample buffer timer interrupt enable
*/
#define PCM_NON 0
#define PCM_DAC 1
#define PCM_ADC 2
static u_long pcm_speed = 0; /* sampling rate */
static u_char pcm_channels = 1; /* channels (1 or 2) */
static u_char pcm_bits = 8; /* bits/sample (8 or 16) */
static u_char pcm_filter = 0; /* filter FLAG */
static u_char pcm_mode = PCM_NON;
static u_long pcm_count = 0;
static u_short pcm_bitsok = 8; /* mask of OK bits */
static int my_devnum = 0;
static int open_mode = 0;
static int
pcm_set_speed(int arg)
{
int foo, tmp;
u_long flags;
if (arg > 44100)
arg = 44100;
if (arg < 5000)
arg = 5000;
foo = (1193180 + (arg / 2)) / arg;
arg = 1193180 / foo;
if (pcm_channels & 2)
foo = foo >> 1;
pcm_speed = arg;
tmp = pas_read(FILTER_FREQUENCY);
/*
* Set anti-aliasing filters according to sample rate. You reall
* *NEED* to enable this feature for all normal recording unless you
* want to experiment with aliasing effects. These filters apply to
* the selected "recording" source. I (pfw) don't know the encoding
* of these 5 bits. The values shown come from the SDK found on
* ftp.uwp.edu:/pub/msdos/proaudio/.
*/
#if !defined NO_AUTO_FILTER_SET
tmp &= 0xe0;
if (pcm_speed >= 2 * 17897)
tmp |= 0x21;
else if (pcm_speed >= 2 * 15909)
tmp |= 0x22;
else if (pcm_speed >= 2 * 11931)
tmp |= 0x29;
else if (pcm_speed >= 2 * 8948)
tmp |= 0x31;
else if (pcm_speed >= 2 * 5965)
tmp |= 0x39;
else if (pcm_speed >= 2 * 2982)
tmp |= 0x24;
pcm_filter = tmp;
#endif
flags = splhigh();
pas_write(tmp & ~(F_F_PCM_RATE_COUNTER | F_F_PCM_BUFFER_COUNTER), FILTER_FREQUENCY);
pas_write(S_C_C_SAMPLE_RATE | S_C_C_LSB_THEN_MSB | S_C_C_SQUARE_WAVE, SAMPLE_COUNTER_CONTROL);
pas_write(foo & 0xff, SAMPLE_RATE_TIMER);
pas_write((foo >> 8) & 0xff, SAMPLE_RATE_TIMER);
pas_write(tmp, FILTER_FREQUENCY);
splx(flags);
return pcm_speed;
}
static int
pcm_set_channels(int arg)
{
if ((arg != 1) && (arg != 2))
return pcm_channels;
if (arg != pcm_channels) {
pas_write(pas_read(PCM_CONTROL) ^ P_C_PCM_MONO, PCM_CONTROL);
pcm_channels = arg;
pcm_set_speed(pcm_speed); /* The speed must be
* reinitialized */
}
return pcm_channels;
}
static int
pcm_set_bits(int arg)
{
if ((arg & pcm_bitsok) != arg)
return pcm_bits;
if (arg != pcm_bits) {
pas_write(pas_read(SYSTEM_CONFIGURATION_2) ^ S_C_2_PCM_16_BIT, SYSTEM_CONFIGURATION_2);
pcm_bits = arg;
}
return pcm_bits;
}
static int
pas_pcm_ioctl(int dev, u_int cmd, ioctl_arg arg, int local)
{
TRACE(printf("pas2_pcm.c: static int pas_pcm_ioctl(u_int cmd = %X, u_int arg = %X)\n", cmd, arg));
switch (cmd) {
case SOUND_PCM_WRITE_RATE:
if (local)
return pcm_set_speed((int) arg);
return *(int *) arg = pcm_set_speed((*(int *) arg));
break;
case SOUND_PCM_READ_RATE:
if (local)
return pcm_speed;
return *(int *) arg = pcm_speed;
break;
case SNDCTL_DSP_STEREO:
if (local)
return pcm_set_channels((int) arg + 1) - 1;
return *(int *) arg = pcm_set_channels((*(int *) arg) + 1) - 1;
break;
case SOUND_PCM_WRITE_CHANNELS:
if (local)
return pcm_set_channels((int) arg);
return *(int *) arg = pcm_set_channels((*(int *) arg));
break;
case SOUND_PCM_READ_CHANNELS:
if (local)
return pcm_channels;
return *(int *) arg = pcm_channels;
break;
case SNDCTL_DSP_SETFMT:
if (local)
return pcm_set_bits((int) arg);
return *(int *) arg = pcm_set_bits((*(int *) arg));
break;
case SOUND_PCM_READ_BITS:
if (local)
return pcm_bits;
return *(int *) arg = pcm_bits;
case SOUND_PCM_WRITE_FILTER: /* NOT YET IMPLEMENTED */
if ((*(int *) arg) > 1)
return -(EINVAL);
pcm_filter = (*(int *) arg);
break;
case SOUND_PCM_READ_FILTER:
return *(int *) arg = pcm_filter;
break;
default:
return -(EINVAL);
}
return -(EINVAL);
}
static void
pas_pcm_reset(int dev)
{
TRACE(printf("pas2_pcm.c: static void pas_pcm_reset(void)\n"));
pas_write(pas_read(PCM_CONTROL) & ~P_C_PCM_ENABLE, PCM_CONTROL);
}
static int
pas_pcm_open(int dev, int mode)
{
int err;
TRACE(printf("pas2_pcm.c: static int pas_pcm_open(int mode = %X)\n", mode));
if ((err = pas_set_intr(PAS_PCM_INTRBITS)) < 0)
return err;
pcm_count = 0;
open_mode = mode;
return 0;
}
static void
pas_pcm_close(int dev)
{
u_long flags;
TRACE(printf("pas2_pcm.c: static void pas_pcm_close(void)\n"));
flags = splhigh();
pas_pcm_reset(dev);
pas_remove_intr(PAS_PCM_INTRBITS);
pcm_mode = PCM_NON;
open_mode = 0;
splx(flags);
}
static void
pas_pcm_output_block(int dev, u_long buf, int count,
int intrflag, int restart_dma)
{
u_long flags, cnt;
TRACE(printf("pas2_pcm.c: static void pas_pcm_output_block(char *buf = %P, int count = %X)\n", buf, count));
cnt = count;
if (audio_devs[dev]->dmachan1 > 3)
cnt >>= 1;
if (audio_devs[dev]->flags & DMA_AUTOMODE &&
intrflag &&
cnt == pcm_count)
return; /* Auto mode on. No need to react */
flags = splhigh();
pas_write(pas_read(PCM_CONTROL) & ~P_C_PCM_ENABLE,
PCM_CONTROL);
if (restart_dma)
DMAbuf_start_dma(dev, buf, count, 1);
if (audio_devs[dev]->dmachan1 > 3)
count >>= 1;
if (count != pcm_count) {
pas_write(pas_read(FILTER_FREQUENCY) & ~F_F_PCM_BUFFER_COUNTER, FILTER_FREQUENCY);
pas_write(S_C_C_SAMPLE_BUFFER | S_C_C_LSB_THEN_MSB | S_C_C_SQUARE_WAVE, SAMPLE_COUNTER_CONTROL);
pas_write(count & 0xff, SAMPLE_BUFFER_COUNTER);
pas_write((count >> 8) & 0xff, SAMPLE_BUFFER_COUNTER);
pas_write(pas_read(FILTER_FREQUENCY) | F_F_PCM_BUFFER_COUNTER, FILTER_FREQUENCY);
pcm_count = count;
}
pas_write(pas_read(FILTER_FREQUENCY) | F_F_PCM_BUFFER_COUNTER | F_F_PCM_RATE_COUNTER, FILTER_FREQUENCY);
#ifdef NO_TRIGGER
pas_write(pas_read(PCM_CONTROL) | P_C_PCM_ENABLE | P_C_PCM_DAC_MODE, PCM_CONTROL);
#endif
pcm_mode = PCM_DAC;
splx(flags);
}
static void
pas_pcm_start_input(int dev, u_long buf, int count,
int intrflag, int restart_dma)
{
u_long flags;
int cnt;
TRACE(printf("pas2_pcm.c: static void pas_pcm_start_input(char *buf = %P, int count = %X)\n", buf, count));
cnt = count;
if (audio_devs[dev]->dmachan1 > 3)
cnt >>= 1;
if (audio_devs[my_devnum]->flags & DMA_AUTOMODE &&
intrflag &&
cnt == pcm_count)
return; /* Auto mode on. No need to react */
flags = splhigh();
if (restart_dma)
DMAbuf_start_dma(dev, buf, count, 0);
if (audio_devs[dev]->dmachan1 > 3)
count >>= 1;
if (count != pcm_count) {
pas_write(pas_read(FILTER_FREQUENCY) & ~F_F_PCM_BUFFER_COUNTER, FILTER_FREQUENCY);
pas_write(S_C_C_SAMPLE_BUFFER | S_C_C_LSB_THEN_MSB | S_C_C_SQUARE_WAVE, SAMPLE_COUNTER_CONTROL);
pas_write(count & 0xff, SAMPLE_BUFFER_COUNTER);
pas_write((count >> 8) & 0xff, SAMPLE_BUFFER_COUNTER);
pas_write(pas_read(FILTER_FREQUENCY) | F_F_PCM_BUFFER_COUNTER, FILTER_FREQUENCY);
pcm_count = count;
}
pas_write(pas_read(FILTER_FREQUENCY) | F_F_PCM_BUFFER_COUNTER | F_F_PCM_RATE_COUNTER, FILTER_FREQUENCY);
#ifdef NO_TRIGGER
pas_write((pas_read(PCM_CONTROL) | P_C_PCM_ENABLE) & ~P_C_PCM_DAC_MODE, PCM_CONTROL);
#endif
pcm_mode = PCM_ADC;
splx(flags);
}
#ifndef NO_TRIGGER
static void
pas_audio_trigger (int dev, int state)
{
unsigned long flags;
flags = splhigh();
state &= open_mode;
if (state & PCM_ENABLE_OUTPUT)
pas_write (pas_read (0xF8A) | 0x40 | 0x10, 0xF8A);
else if (state & PCM_ENABLE_INPUT)
pas_write ((pas_read (0xF8A) | 0x40) & ~0x10, 0xF8A);
else
pas_write (pas_read (0xF8A) & ~0x40, 0xF8A);
splx(flags);
}
#endif
static int
pas_pcm_prepare_for_input(int dev, int bsize, int bcount)
{
return 0;
}
static int
pas_pcm_prepare_for_output(int dev, int bsize, int bcount)
{
return 0;
}
static struct audio_operations pas_pcm_operations =
{
"Pro Audio Spectrum",
DMA_AUTOMODE,
AFMT_U8 | AFMT_S16_LE,
NULL,
pas_pcm_open,
pas_pcm_close,
pas_pcm_output_block,
pas_pcm_start_input,
pas_pcm_ioctl,
pas_pcm_prepare_for_input,
pas_pcm_prepare_for_output,
pas_pcm_reset,
pas_pcm_reset,
NULL,
NULL,
NULL,
NULL,
pas_audio_trigger
};
void
pas_pcm_init(struct address_info * hw_config)
{
pcm_bitsok = 8;
if (pas_read(OPERATION_MODE_1) & O_M_1_PCM_TYPE)
pcm_bitsok |= 16;
pcm_set_speed(DSP_DEFAULT_SPEED);
if (num_audiodevs < MAX_AUDIO_DEV) {
audio_devs[my_devnum = num_audiodevs++] = &pas_pcm_operations;
audio_devs[my_devnum]->dmachan1 = hw_config->dma;
audio_devs[my_devnum]->buffsize = DSP_BUFFSIZE;
} else
printf("PAS2: Too many PCM devices available\n");
return;
}
void
pas_pcm_interrupt(u_char status, int cause)
{
if (cause == 1) { /* PCM buffer done */
/*
* Halt the PCM first. Otherwise we don't have time to start
* a new block before the PCM chip proceeds to the next
* sample
*/
if (!(audio_devs[my_devnum]->flags & DMA_AUTOMODE)) {
pas_write(pas_read(PCM_CONTROL) & ~P_C_PCM_ENABLE,
PCM_CONTROL);
}
switch (pcm_mode) {
case PCM_DAC:
DMAbuf_outputintr(my_devnum, 1);
break;
case PCM_ADC:
DMAbuf_inputintr(my_devnum);
break;
default:
printf("PAS: Unexpected PCM interrupt\n");
}
}
}
#endif

View File

@ -1,250 +0,0 @@
/* */
/* Port addresses and bit fields for the Media Vision Pro AudioSpectrum second generation sound cards. */
/* */
/* Feel free to use this header file in any application you create that has support for the Media Vision */
/* Pro AudioSpectrum second generation sound cards. Other uses prohibited without prior permission. */
/* */
/* - cmetz@thor.tjhsst.edu */
/* */
/* Notes: */
/* */
/* * All of these ports go into the MVD101 multimedia controller chip, which then signals the other chips to do */
/* the actual work. Many ports like the FM ones functionally attach directly to the destination chip though */
/* they don't actually have a direct connection. */
/* */
/* * The PAS2 series cards have an MVD101 multimedia controller chip, the original PAS cards don't. The original */
/* PAS cards are pretty defunct now, so no attempt is made here to support them. */
/* */
/* * The PAS2 series cards are all really different at the hardware level, though the MVD101 hides some of the */
/* incompatibilities, there still are differences that need to be accounted for. */
/* */
/* Card CD-ROM interface PCM chip Mixer chip FM chip */
/* PAS Plus Sony proprietary (Crystal?) 8-bit DAC National OPL3 */
/* PAS 16 Zilog SCSI MVA416 16-bit Codec MVA508 OPL3 */
/* CDPC Sony proprietary Sony 16-bit Codec National OPL3 */
/* Fusion CD 16 Sony proprietary MVA416 16-bit Codec MVA508 OPL3 */
/* Fusion CD Sony proprietary (Crystal?) 8-bit DAC National OPL3 */
/* */
#define PAS_DEFAULT_BASE 0x388
/* Symbolic Name Value R W Subsystem Description */
#define SPEAKER_CONTROL 0x61 /* W PC speaker Control register */
#define SPEAKER_CONTROL_GHOST 0x738B /* R W PC speaker Control ghost register */
#define SPEAKER_TIMER_CONTROL 0x43 /* W PC speaker Timer control register */
#define SPEAKER_TIMER_CONTROL_GHOST 0x778B /* R W PC speaker Timer control register ghost */
#define SPEAKER_TIMER_DATA 0x42 /* W PC speaker Timer data register */
#define SPEAKER_TIMER_DATA_GHOST 0x138A /* R W PC speaker Timer data register ghost */
#define WARM_BOOT 0x41 /* W Control Used to detect system warm boot */
#define WARM_BOOT_GHOST 0x7789 /* ? W Control Use to get the card to fake warm boot */
#define MASTER_DECODE 0x9A01 /* W Control Address >> 2 of card base address */
#define PRESCALE_DIVIDER 0xBF8A /* R W PCM Ration between Codec clock and master clock */
#define WAIT_STATE 0xBF88 /* R W Control Four-bit bus wait-state count (~140ns ea.) */
#define BOARD_REV_ID 0x2789 /* R Control Extended Board Revision ID */
#define CHIP_REV 0xFF88 /* R 0=PAS, 1=PAS+, 2=CDPC, 3=PAS16C, 4=PAS16D */
#define SYSTEM_CONFIGURATION_1 0x8388 /* R W Control */
#define S_C_1_PCS_ENABLE 0x01 /* R W PC speaker 1=enable, 0=disable PC speaker emulation */
#define S_C_1_PCM_CLOCK_SELECT 0x02 /* R W PCM 1=14.31818Mhz/12, 0=28.224Mhz master clock */
#define S_C_1_FM_EMULATE_CLOCK 0x04 /* R W FM 1=use 28.224Mhz/2, 0=use 14.31818Mhz clock */
#define S_C_1_PCS_STEREO 0x10 /* R W PC speaker 1=enable PC speaker stereo effect, 0=disable */
#define S_C_1_PCS_REALSOUND 0x20 /* R W PC speaker 1=enable RealSound enhancement, 0=disable */
#define S_C_1_FORCE_EXT_RESET 0x40 /* R W Control Force external reset */
#define S_C_1_FORCE_INT_RESET 0x80 /* R W Control Force internal reset */
#define SYSTEM_CONFIGURATION_2 0x8389 /* R W Control */
#define S_C_2_PCM_OVERSAMPLING 0x03 /* R W PCM 00=0x, 01=2x, 10=4x, 11=reserved */
#define S_C_2_PCM_16_BIT 0x04 /* R W PCM 1=16-bit, 0=8-bit samples */
#define SYSTEM_CONFIGURATION_3 0x838A /* R W Control */
#define S_C_3_PCM_CLOCK_SELECT 0x02 /* R W PCM 1=use 1.008Mhz clock for PCM, 0=don't */
#define SYSTEM_CONFIGURATION_4 0x838B /* R W Control CD-ROM interface controls */
#define IO_CONFIGURATION_1 0xF388 /* R W Control */
#define I_C_1_BOOT_RESET_ENABLE 0x80 /* R W Control 1=reset board on warm boot, 0=don't */
#define I_C_1_JOYSTICK_ENABLE 0x40 /* R W Control 1=enable joystick port, 0=don't */
#define IO_CONFIGURATION_2 0xF389 /* R W Control */
#define I_C_2_PCM_DMA_DISABLED 0x00 /* R W PCM PCM DMA disabled */
#define IO_CONFIGURATION_3 0xF38A /* R W Control */
#define I_C_3_PCM_IRQ_DISABLED 0x00 /* R W PCM PCM IRQ disabled */
#define COMPATIBILITY_ENABLE 0xF788 /* R W Control */
#define C_E_MPU401_ENABLE 0x01 /* R W MIDI 1=enable, 0=disable MPU401 MIDI emulation */
#define C_E_SB_ENABLE 0x02 /* R W PCM 1=enable, 0=disable Sound Blaster emulation */
#define C_E_SB_ACTIVE 0x04 /* R PCM "Sound Blaster Interrupt active" */
#define C_E_MPU401_ACTIVE 0x08 /* R MIDI "MPU UART mode active" */
#define C_E_PCM_COMPRESSION 0x10 /* R W PCM 1=enable, 0=disabled compression */
#define EMULATION_ADDRESS 0xF789 /* R W Control */
#define E_A_SB_BASE 0x0f /* R W PCM bits A4-A7 for SB base port */
#define E_A_MPU401_BASE 0xf0 /* R W MIDI bits A4-A7 for MPU401 base port */
#define EMULATION_CONFIGURATION 0xFB8A /* R W ***** Only valid on newer PAS2 cards (?) ***** */
#define E_C_MPU401_IRQ 0x07 /* R W MIDI MPU401 emulation IRQ */
#define E_C_SB_IRQ 0x38 /* R W PCM SB emulation IRQ */
#define E_C_SB_DMA 0xC0 /* R W PCM SB emulation DMA */
#define OPERATION_MODE_1 0xEF8B /* R Control */
#define O_M_1_CDROM_TYPE 0x03 /* R CD-ROM 3=SCSI, 2=Sony, 0=no CD-ROM interface */
#define O_M_1_FM_TYPE 0x04 /* R FM 1=sterero, 0=mono FM chip */
#define O_M_1_PCM_TYPE 0x08 /* R PCM 1=16-bit Codec, 0=8-bit DAC */
#define OPERATION_MODE_2 0xFF8B /* R Control */
#define O_M_2_PCS_ENABLED 0x02 /* R PC speaker PC speaker emulation 1=enabled, 0=disabled */
#define O_M_2_BUS_TIMING 0x10 /* R Control 1=AT bus timing, 0=XT bus timing */
#define O_M_2_BOARD_REVISION 0xe0 /* R Control Board revision */
#define INTERRUPT_MASK 0x0B8B /* R W Control */
#define I_M_FM_LEFT_IRQ_ENABLE 0x01 /* R W FM Enable FM left interrupt */
#define I_M_FM_RIGHT_IRQ_ENABLE 0x02 /* R W FM Enable FM right interrupt */
#define I_M_PCM_RATE_IRQ_ENABLE 0x04 /* R W PCM Enable Sample Rate interrupt */
#define I_M_PCM_BUFFER_IRQ_ENABLE 0x08 /* R W PCM Enable Sample Buffer interrupt */
#define I_M_MIDI_IRQ_ENABLE 0x10 /* R W MIDI Enable MIDI interrupt */
#define I_M_BOARD_REV 0xE0 /* R Control Board revision */
#define INTERRUPT_STATUS 0x0B89 /* R W Control */
#define I_S_FM_LEFT_IRQ 0x01 /* R W FM Left FM Interrupt Pending */
#define I_S_FM_RIGHT_IRQ 0x02 /* R W FM Right FM Interrupt Pending */
#define I_S_PCM_SAMPLE_RATE_IRQ 0x04 /* R W PCM Sample Rate Interrupt Pending */
#define I_S_PCM_SAMPLE_BUFFER_IRQ 0x08 /* R W PCM Sample Buffer Interrupt Pending */
#define I_S_MIDI_IRQ 0x10 /* R W MIDI MIDI Interrupt Pending */
#define I_S_PCM_CHANNEL 0x20 /* R W PCM 1=right, 0=left */
#define I_S_RESET_ACTIVE 0x40 /* R W Control Reset is active (Timed pulse not finished) */
#define I_S_PCM_CLIPPING 0x80 /* R W PCM Clipping has occurred */
#define FILTER_FREQUENCY 0x0B8A /* R W Control */
#define F_F_FILTER_DISABLED 0x00 /* R W Mixer No filter */
#if 0
struct { /* R W Mixer Filter translation */
unsigned int freq:24;
unsigned int value:8;
} F_F_FILTER_translate[] =
{ { 73500, 0x01 }, /* 73500Hz - divide by 16 */
{ 65333, 0x02 }, /* 65333Hz - divide by 18 */
{ 49000, 0x09 }, /* 49000Hz - divide by 24 */
{ 36750, 0x11 }, /* 36750Hz - divide by 32 */
{ 24500, 0x19 }, /* 24500Hz - divide by 48 */
{ 18375, 0x07 }, /* 18375Hz - divide by 64 */
{ 12783, 0x0f }, /* 12783Hz - divide by 92 */
{ 12250, 0x04 }, /* 12250Hz - divide by 96 */
{ 9188, 0x17 }, /* 9188Hz - divide by 128 */
{ 6125, 0x1f }, /* 6125Hz - divide by 192 */
};
#endif
#define F_F_MIXER_UNMUTE 0x20 /* R W Mixer 1=disable, 0=enable board mute */
#define F_F_PCM_RATE_COUNTER 0x40 /* R W PCM 1=enable, 0=disable sample rate counter */
#define F_F_PCM_BUFFER_COUNTER 0x80 /* R W PCM 1=enable, 0=disable sample buffer counter */
#define PAS_NONE 0
#define PAS_PLUS 1
#define PAS_CDPC 2
#define PAS_16 3
#define PAS_16D 4
#ifdef DEFINE_TRANSLATIONS
static unsigned char I_C_2_PCM_DMA_translate[] = /* R W PCM PCM DMA channel value translations */
{ 4, 1, 2, 3, 0, 5, 6, 7 };
static unsigned char I_C_3_PCM_IRQ_translate[] = /* R W PCM PCM IRQ level value translation */
{ 0, 0, 1, 2, 3, 4, 5, 6, 0, 1, 7, 8, 9, 0, 10, 11 };
#ifdef unused
static unsigned char E_C_MPU401_IRQ_translate[] = /* R W MIDI MPU401 emulation IRQ value translation */
{ 0x00, 0x00, 0x01, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x01, 0x05, 0x06, 0x07 };
#endif
static unsigned char E_C_SB_IRQ_translate[] = /* R W PCM SB emulation IRQ translate */
{ 0x00, 0x00, 0x08, 0x10, 0x00, 0x18, 0x00, 0x20, 0x00, 0x08, 0x28, 0x30, 0x38, 0, 0 };
static unsigned char E_C_SB_DMA_translate[] = /* R W PCM SB emulation DMA translate */
{ 0x00, 0x40, 0x80, 0xC0, 0, 0, 0, 0 };
#ifdef unused
static unsigned char O_M_1_to_card[] = /* R W Control Translate (OM1 & 0x0f) to card type */
{ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 4, 0, 2, 3 };
#endif
#endif
#define PARALLEL_MIXER 0x078B /* W Mixer Documented for MVD101 as FM Mono Right decode?? */
#define P_M_MV508_ADDRESS 0x80 /* W Mixer MVD508 Address/mixer select */
#define P_M_MV508_DATA 0x00
#define P_M_MV508_LEFT 0x20 /* W Mixer MVD508 Left channel select */
#define P_M_MV508_RIGHT 0x40 /* W Mixer MVD508 Right channel select */
#define P_M_MV508_BOTH 0x00 /* W Mixer MVD508 Both channel select */
#define P_M_MV508_MIXER 0x10 /* W Mixer MVD508 Select a mixer (rather than a volume) */
#define P_M_MV508_VOLUME 0x00
#define P_M_MV508_INPUTMIX 0x20 /* W Mixer MVD508 Select mixer A */
#define P_M_MV508_OUTPUTMIX 0x00 /* W Mixer MVD508 Select mixer B */
#define P_M_MV508_MASTER_A 0x01 /* W Mixer MVD508 Master volume control A (output) */
#define P_M_MV508_MASTER_B 0x02 /* W Mixer MVD508 Master volume control B (DSP input) */
#define P_M_MV508_BASS 0x03 /* W Mixer MVD508 Bass control */
#define P_M_MV508_TREBLE 0x04 /* W Mixer MVD508 Treble control */
#define P_M_MV508_MODE 0x05 /* W Mixer MVD508 Master mode control */
#define P_M_MV508_LOUDNESS 0x04 /* W Mixer MVD508 Mode control - Loudness filter */
#define P_M_MV508_ENHANCE_BITS 0x03
#define P_M_MV508_ENHANCE_NONE 0x00 /* W Mixer MVD508 Mode control - No stereo enhancement */
#define P_M_MV508_ENHANCE_40 0x01 /* W Mixer MVD508 Mode control - 40% stereo enhancement */
#define P_M_MV508_ENHANCE_60 0x02 /* W Mixer MVD508 Mode control - 60% stereo enhancement */
#define P_M_MV508_ENHANCE_80 0x03 /* W Mixer MVD508 Mode control - 80% stereo enhancement */
#define P_M_MV508_FM 0x00 /* W Mixer MVD508 Channel 0 - FM */
#define P_M_MV508_IMIXER 0x01 /* W Mixer MVD508 Channel 1 - Input mixer (rec monitor) */
#define P_M_MV508_LINE 0x02 /* W Mixer MVD508 Channel 2 - Line in */
#define P_M_MV508_CDROM 0x03 /* W Mixer MVD508 Channel 3 - CD-ROM */
#define P_M_MV508_MIC 0x04 /* W Mixer MVD508 Channel 4 - Microphone */
#define P_M_MV508_PCM 0x05 /* W Mixer MVD508 Channel 5 - PCM */
#define P_M_MV508_SPEAKER 0x06 /* W Mixer MVD508 Channel 6 - PC Speaker */
#define P_M_MV508_SB 0x07 /* W Mixer MVD508 Channel 7 - SB DSP */
#define SERIAL_MIXER 0xB88 /* R W Control Serial mixer control (used other ways) */
#define S_M_PCM_RESET 0x01 /* R W PCM Codec/DSP reset */
#define S_M_FM_RESET 0x02 /* R W FM FM chip reset */
#define S_M_SB_RESET 0x04 /* R W PCM SB emulation chip reset */
#define S_M_MIXER_RESET 0x10 /* R W Mixer Mixer chip reset */
#define S_M_INTEGRATOR_ENABLE 0x40 /* R W Speaker Enable PC speaker integrator (FORCE RealSound) */
#define S_M_OPL3_DUAL_MONO 0x80 /* R W FM Set the OPL-3 to dual mono mode */
#define PCM_CONTROL 0xF8A /* R W PCM PCM Control Register */
#define P_C_MIXER_CROSS_FIELD 0x0f
#define P_C_MIXER_CROSS_R_TO_R 0x01 /* R W Mixer Connect Right to Right */
#define P_C_MIXER_CROSS_L_TO_R 0x02 /* R W Mixer Connect Left to Right */
#define P_C_MIXER_CROSS_R_TO_L 0x04 /* R W Mixer Connect Right to Left */
#define P_C_MIXER_CROSS_L_TO_L 0x08 /* R W Mixer Connect Left to Left */
#define P_C_PCM_DAC_MODE 0x10 /* R W PCM Playback (DAC) mode */
#define P_C_PCM_ADC_MODE 0x00 /* R W PCM Record (ADC) mode */
#define P_C_PCM_MONO 0x20 /* R W PCM Mono mode */
#define P_C_PCM_STEREO 0x00 /* R W PCM Stereo mode */
#define P_C_PCM_ENABLE 0x40 /* R W PCM Enable PCM engine */
#define P_C_PCM_DMA_ENABLE 0x80 /* R W PCM Enable DRQ */
#define SAMPLE_COUNTER_CONTROL 0x138B /* R W PCM Sample counter control register */
#define S_C_C_SQUARE_WAVE 0x04 /* R W PCM Square wave generator (use for sample rate) */
#define S_C_C_RATE 0x06 /* R W PCM Rate generator (use for sample buffer count) */
#define S_C_C_LSB_THEN_MSB 0x30 /* R W PCM Change all 16 bits, LSB first, then MSB */
/* MVD101 and SDK documentations have S_C_C_SAMPLE_RATE and S_C_C_SAMPLE_BUFFER transposed. Only one works :-) */
#define S_C_C_SAMPLE_RATE 0x00 /* R W PCM Select sample rate timer */
#define S_C_C_SAMPLE_BUFFER 0x40 /* R W PCM Select sample buffer counter */
#define S_C_C_PC_SPEAKER 0x80 /* R W PCM Select PC speaker counter */
#define SAMPLE_RATE_TIMER 0x1388 /* W PCM Sample rate timer register (PCM wait interval) */
#define SAMPLE_BUFFER_COUNTER 0x1389 /* R W PCM Sample buffer counter (DMA buffer size) */
#define MIDI_CONTROL 0x178b /* R W MIDI Midi control register */
#define M_C_ENA_TSTAMP_IRQ 0x01 /* R W MIDI Enable Time Stamp Interrupts */
#define M_C_ENA_TME_COMP_IRQ 0x02 /* R W MIDI Enable time compare interrupts */
#define M_C_ENA_INPUT_IRQ 0x04 /* R W MIDI Enable input FIFO interrupts */
#define M_C_ENA_OUTPUT_IRQ 0x08 /* R W MIDI Enable output FIFO interrupts */
#define M_C_ENA_OUTPUT_HALF_IRQ 0x10 /* R W MIDI Enable output FIFO half full interrupts */
#define M_C_RESET_INPUT_FIFO 0x20 /* R W MIDI Reset input FIFO pointer */
#define M_C_RESET_OUTPUT_FIFO 0x40 /* R W MIDI Reset output FIFO pointer */
#define M_C_ENA_THRU_MODE 0x80 /* R W MIDI Echo input to output (THRU) */
#define MIDI_STATUS 0x1B88 /* R W MIDI Midi (interrupt) status register */
#define M_S_TIMESTAMP 0x01 /* R W MIDI Midi time stamp interrupt occurred */
#define M_S_COMPARE 0x02 /* R W MIDI Midi compare time interrupt occurred */
#define M_S_INPUT_AVAIL 0x04 /* R W MIDI Midi input data available interrupt occurred */
#define M_S_OUTPUT_EMPTY 0x08 /* R W MIDI Midi output FIFO empty interrupt occurred */
#define M_S_OUTPUT_HALF_EMPTY 0x10 /* R W MIDI Midi output FIFO half empty interrupt occurred */
#define M_S_INPUT_OVERRUN 0x20 /* R W MIDI Midi input overrun error occurred */
#define M_S_OUTPUT_OVERRUN 0x40 /* R W MIDI Midi output overrun error occurred */
#define M_S_FRAMING_ERROR 0x80 /* R W MIDI Midi input framing error occurred */
#define MIDI_FIFO_STATUS 0x1B89 /* R W MIDI Midi fifo status */
#define MIDI_DATA 0x178A /* R W MIDI Midi data register */
#define MIDI_INPUT_AVAILABLE 0x0f /* RW MIDI */

View File

@ -1,236 +0,0 @@
/* */
/* Port addresses and bit fields for the Media Vision Pro AudioSpectrum second generation sound cards. */
/* */
/* Feel free to use this header file in any application you create that has support for the Media Vision */
/* Pro AudioSpectrum second generation sound cards. Other uses prohibited without prior permission. */
/* */
/* - cmetz@thor.tjhsst.edu */
/* */
/* Notes: */
/* */
/* * All of these ports go into the MVD101 multimedia controller chip, which then signals the other chips to do */
/* the actual work. Many ports like the FM ones functionally attach directly to the destination chip though */
/* they don't actually have a direct connection. */
/* */
/* * The PAS2 series cards have an MVD101 multimedia controller chip, the original PAS cards don't. The original */
/* PAS cards are pretty defunct now, so no attempt is made here to support them. */
/* */
/* * The PAS2 series cards are all really different at the hardware level, though the MVD101 hides some of the */
/* incompatibilities, there still are differences that need to be accounted for. */
/* */
/* Card CD-ROM interface PCM chip Mixer chip FM chip */
/* PAS Plus Sony proprietary (Crystal?) 8-bit DAC National OPL3 */
/* PAS 16 Zilog SCSI MVA416 16-bit Codec MVA508 OPL3 */
/* CDPC Sony proprietary Sony 16-bit Codec National OPL3 */
/* Fusion CD 16 Sony proprietary MVA416 16-bit Codec MVA508 OPL3 */
/* Fusion CD Sony proprietary (Crystal?) 8-bit DAC National OPL3 */
/* */
#define PAS_DEFAULT_BASE 0x388
/* Symbolic Name Value R W Subsystem Description */
#define SPEAKER_CONTROL 0x61 /* W PC speaker Control register */
#define SPEAKER_CONTROL_GHOST 0x738B /* R W PC speaker Control ghost register */
#define SPEAKER_TIMER_CONTROL 0x43 /* W PC speaker Timer control register */
#define SPEAKER_TIMER_CONTROL_GHOST 0x778B /* R W PC speaker Timer control register ghost */
#define SPEAKER_TIMER_DATA 0x42 /* W PC speaker Timer data register */
#define SPEAKER_TIMER_DATA_GHOST 0x138A /* R W PC speaker Timer data register ghost */
#define WARM_BOOT 0x41 /* W Control Used to detect system warm boot */
#define WARM_BOOT_GHOST 0x7789 /* ? W Control Use to get the card to fake warm boot */
#define MASTER_DECODE 0x9A01 /* W Control Address >> 2 of card base address */
#define PRESCALE_DIVIDER 0xBF8A /* R W PCM Ration between Codec clock and master clock */
#define WAIT_STATE 0xBF88 /* R W Control Four-bit bus wait-state count (~140ns ea.) */
#define BOARD_REV_ID 0x2789 /* R Control Extended Board Revision ID */
#define CHIP_REV 0xFF88 /* R 0=PAS, 1=PAS+, 2=CDPC, 3=PAS16C, 4=PAS16D */
#define SYSTEM_CONFIGURATION_1 0x8388 /* R W Control */
# define S_C_1_PCS_ENABLE 0x01 /* R W PC speaker 1=enable, 0=disable PC speaker emulation */
# define S_C_1_PCM_CLOCK_SELECT 0x02 /* R W PCM 1=14.31818Mhz/12, 0=28.224Mhz master clock */
# define S_C_1_FM_EMULATE_CLOCK 0x04 /* R W FM 1=use 28.224Mhz/2, 0=use 14.31818Mhz clock */
# define S_C_1_PCS_STEREO 0x10 /* R W PC speaker 1=enable PC speaker stereo effect, 0=disable */
# define S_C_1_PCS_REALSOUND 0x20 /* R W PC speaker 1=enable RealSound enhancement, 0=disable */
# define S_C_1_FORCE_EXT_RESET 0x40 /* R W Control Force external reset */
# define S_C_1_FORCE_INT_RESET 0x80 /* R W Control Force internal reset */
#define SYSTEM_CONFIGURATION_2 0x8389 /* R W Control */
# define S_C_2_PCM_OVERSAMPLING 0x03 /* R W PCM 00=0x, 01=2x, 10=4x, 11=reserved */
# define S_C_2_PCM_16_BIT 0x04 /* R W PCM 1=16-bit, 0=8-bit samples */
#define SYSTEM_CONFIGURATION_3 0x838A /* R W Control */
# define S_C_3_PCM_CLOCK_SELECT 0x02 /* R W PCM 1=use 1.008Mhz clock for PCM, 0=don't */
#define SYSTEM_CONFIGURATION_4 0x838B /* R W Control CD-ROM interface controls */
#define IO_CONFIGURATION_1 0xF388 /* R W Control */
# define I_C_1_BOOT_RESET_ENABLE 0x80 /* R W Control 1=reset board on warm boot, 0=don't */
# define I_C_1_JOYSTICK_ENABLE 0x40 /* R W Control 1=enable joystick port, 0=don't */
#define IO_CONFIGURATION_2 0xF389 /* R W Control */
# define I_C_2_PCM_DMA_DISABLED 0x00 /* R W PCM PCM DMA disabled */
#define IO_CONFIGURATION_3 0xF38A /* R W Control */
# define I_C_3_PCM_IRQ_DISABLED 0x00 /* R W PCM PCM IRQ disabled */
#define COMPATIBILITY_ENABLE 0xF788 /* R W Control */
# define C_E_MPU401_ENABLE 0x01 /* R W MIDI 1=enable, 0=disable MPU401 MIDI emulation */
# define C_E_SB_ENABLE 0x02 /* R W PCM 1=enable, 0=disable Sound Blaster emulation */
# define C_E_SB_ACTIVE 0x04 /* R PCM "Sound Blaster Interrupt active" */
# define C_E_MPU401_ACTIVE 0x08 /* R MIDI "MPU UART mode active" */
# define C_E_PCM_COMPRESSION 0x10 /* R W PCM 1=enable, 0=disabled compression */
#define EMULATION_ADDRESS 0xF789 /* R W Control */
# define E_A_SB_BASE 0x0f /* R W PCM bits A4-A7 for SB base port */
# define E_A_MPU401_BASE 0xf0 /* R W MIDI bits A4-A7 for MPU401 base port */
#define EMULATION_CONFIGURATION 0xFB8A /* R W ***** Only valid on newer PAS2 cards (?) ***** */
# define E_C_MPU401_IRQ 0x07 /* R W MIDI MPU401 emulation IRQ */
# define E_C_SB_IRQ 0x38 /* R W PCM SB emulation IRQ */
# define E_C_SB_DMA 0xC0 /* R W PCM SB emulation DMA */
#define OPERATION_MODE_1 0xEF8B /* R Control */
# define O_M_1_CDROM_TYPE 0x03 /* R CD-ROM 3=SCSI, 2=Sony, 0=no CD-ROM interface */
# define O_M_1_FM_TYPE 0x04 /* R FM 1=sterero, 0=mono FM chip */
# define O_M_1_PCM_TYPE 0x08 /* R PCM 1=16-bit Codec, 0=8-bit DAC */
#define OPERATION_MODE_2 0xFF8B /* R Control */
# define O_M_2_PCS_ENABLED 0x02 /* R PC speaker PC speaker emulation 1=enabled, 0=disabled */
# define O_M_2_BUS_TIMING 0x10 /* R Control 1=AT bus timing, 0=XT bus timing */
# define O_M_2_BOARD_REVISION 0xe0 /* R Control Board revision */
#define INTERRUPT_MASK 0x0B8B /* R W Control */
# define I_M_FM_LEFT_IRQ_ENABLE 0x01 /* R W FM Enable FM left interrupt */
# define I_M_FM_RIGHT_IRQ_ENABLE 0x02 /* R W FM Enable FM right interrupt */
# define I_M_PCM_RATE_IRQ_ENABLE 0x04 /* R W PCM Enable Sample Rate interrupt */
# define I_M_PCM_BUFFER_IRQ_ENABLE 0x08 /* R W PCM Enable Sample Buffer interrupt */
# define I_M_MIDI_IRQ_ENABLE 0x10 /* R W MIDI Enable MIDI interrupt */
# define I_M_BOARD_REV 0xE0 /* R Control Board revision */
#define INTERRUPT_STATUS 0x0B89 /* R W Control */
# define I_S_FM_LEFT_IRQ 0x01 /* R W FM Left FM Interrupt Pending */
# define I_S_FM_RIGHT_IRQ 0x02 /* R W FM Right FM Interrupt Pending */
# define I_S_PCM_SAMPLE_RATE_IRQ 0x04 /* R W PCM Sample Rate Interrupt Pending */
# define I_S_PCM_SAMPLE_BUFFER_IRQ 0x08 /* R W PCM Sample Buffer Interrupt Pending */
# define I_S_MIDI_IRQ 0x10 /* R W MIDI MIDI Interrupt Pending */
# define I_S_PCM_CHANNEL 0x20 /* R W PCM 1=right, 0=left */
# define I_S_RESET_ACTIVE 0x40 /* R W Control Reset is active (Timed pulse not finished) */
# define I_S_PCM_CLIPPING 0x80 /* R W PCM Clipping has occurred */
#define FILTER_FREQUENCY 0x0B8A /* R W Control */
# define F_F_FILTER_DISABLED 0x00 /* R W Mixer No filter */
# define F_F_MIXER_UNMUTE 0x20 /* R W Mixer 1=disable, 0=enable board mute */
# define F_F_PCM_RATE_COUNTER 0x40 /* R W PCM 1=enable, 0=disable sample rate counter */
# define F_F_PCM_BUFFER_COUNTER 0x80 /* R W PCM 1=enable, 0=disable sample buffer counter */
#define PAS_NONE 0
#define PAS_PLUS 1
#define PAS_CDPC 2
#define PAS_16 3
#define PAS_16D 4
#ifdef DEFINE_TRANSLATIONS
unsigned char I_C_2_PCM_DMA_translate[] = /* R W PCM PCM DMA channel value translations */
{ 4, 1, 2, 3, 0, 5, 6, 7 };
unsigned char I_C_3_PCM_IRQ_translate[] = /* R W PCM PCM IRQ level value translation */
{ 0, 0, 1, 2, 3, 4, 5, 6, 0, 1, 7, 8, 9, 0, 10, 11 };
unsigned char E_C_MPU401_IRQ_translate[] = /* R W MIDI MPU401 emulation IRQ value translation */
{ 0x00, 0x00, 0x01, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x01, 0x05, 0x06, 0x07 };
unsigned char E_C_SB_IRQ_translate[] = /* R W PCM SB emulation IRQ translate */
{ 0x00, 0x00, 0x08, 0x10, 0x00, 0x18, 0x00, 0x20, 0x00, 0x08, 0x28, 0x30, 0x38, 0, 0 };
unsigned char E_C_SB_DMA_translate[] = /* R W PCM SB emulation DMA translate */
{ 0x00, 0x40, 0x80, 0xC0, 0, 0, 0, 0 };
unsigned char O_M_1_to_card[] = /* R W Control Translate (OM1 & 0x0f) to card type */
{ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 4, 0, 2, 3 };
#else
extern unsigned char I_C_2_PCM_DMA_translate[]; /* R W PCM PCM DMA channel value translations */
extern unsigned char I_C_3_PCM_IRQ_translate[]; /* R W PCM PCM IRQ level value translation */
extern unsigned char E_C_MPU401_IRQ_translate[]; /* R W MIDI MPU401 emulation IRQ value translation */
extern unsigned char E_C_SB_IRQ_translate[]; /* R W PCM SB emulation IRQ translate */
extern unsigned char E_C_SB_DMA_translate[]; /* R W PCM SB emulation DMA translate */
extern unsigned char O_M_1_to_card[]; /* R W Control Translate (OM1 & 0x0f) to card type */
#endif
#define PARALLEL_MIXER 0x078B /* W Mixer Documented for MVD101 as FM Mono Right decode?? */
# define P_M_MV508_ADDRESS 0x80 /* W Mixer MVD508 Address/mixer select */
# define P_M_MV508_DATA 0x00
# define P_M_MV508_LEFT 0x20 /* W Mixer MVD508 Left channel select */
# define P_M_MV508_RIGHT 0x40 /* W Mixer MVD508 Right channel select */
# define P_M_MV508_BOTH 0x00 /* W Mixer MVD508 Both channel select */
# define P_M_MV508_MIXER 0x10 /* W Mixer MVD508 Select a mixer (rather than a volume) */
# define P_M_MV508_VOLUME 0x00
# define P_M_MV508_INPUTMIX 0x20 /* W Mixer MVD508 Select mixer A */
# define P_M_MV508_OUTPUTMIX 0x00 /* W Mixer MVD508 Select mixer B */
# define P_M_MV508_MASTER_A 0x01 /* W Mixer MVD508 Master volume control A (output) */
# define P_M_MV508_MASTER_B 0x02 /* W Mixer MVD508 Master volume control B (DSP input) */
# define P_M_MV508_BASS 0x03 /* W Mixer MVD508 Bass control */
# define P_M_MV508_TREBLE 0x04 /* W Mixer MVD508 Treble control */
# define P_M_MV508_MODE 0x05 /* W Mixer MVD508 Master mode control */
# define P_M_MV508_LOUDNESS 0x04 /* W Mixer MVD508 Mode control - Loudness filter */
# define P_M_MV508_ENHANCE_BITS 0x03
# define P_M_MV508_ENHANCE_NONE 0x00 /* W Mixer MVD508 Mode control - No stereo enhancement */
# define P_M_MV508_ENHANCE_40 0x01 /* W Mixer MVD508 Mode control - 40% stereo enhancement */
# define P_M_MV508_ENHANCE_60 0x02 /* W Mixer MVD508 Mode control - 60% stereo enhancement */
# define P_M_MV508_ENHANCE_80 0x03 /* W Mixer MVD508 Mode control - 80% stereo enhancement */
# define P_M_MV508_FM 0x00 /* W Mixer MVD508 Channel 0 - FM */
# define P_M_MV508_IMIXER 0x01 /* W Mixer MVD508 Channel 1 - Input mixer (rec monitor) */
# define P_M_MV508_LINE 0x02 /* W Mixer MVD508 Channel 2 - Line in */
# define P_M_MV508_CDROM 0x03 /* W Mixer MVD508 Channel 3 - CD-ROM */
# define P_M_MV508_MIC 0x04 /* W Mixer MVD508 Channel 4 - Microphone */
# define P_M_MV508_PCM 0x05 /* W Mixer MVD508 Channel 5 - PCM */
# define P_M_MV508_SPEAKER 0x06 /* W Mixer MVD508 Channel 6 - PC Speaker */
# define P_M_MV508_SB 0x07 /* W Mixer MVD508 Channel 7 - SB DSP */
#define SERIAL_MIXER 0xB88 /* R W Control Serial mixer control (used other ways) */
# define S_M_PCM_RESET 0x01 /* R W PCM Codec/DSP reset */
# define S_M_FM_RESET 0x02 /* R W FM FM chip reset */
# define S_M_SB_RESET 0x04 /* R W PCM SB emulation chip reset */
# define S_M_MIXER_RESET 0x10 /* R W Mixer Mixer chip reset */
# define S_M_INTEGRATOR_ENABLE 0x40 /* R W Speaker Enable PC speaker integrator (FORCE RealSound) */
# define S_M_OPL3_DUAL_MONO 0x80 /* R W FM Set the OPL-3 to dual mono mode */
#define PCM_CONTROL 0xF8A /* R W PCM PCM Control Register */
# define P_C_MIXER_CROSS_FIELD 0x0f
# define P_C_MIXER_CROSS_R_TO_R 0x01 /* R W Mixer Connect Right to Right */
# define P_C_MIXER_CROSS_L_TO_R 0x02 /* R W Mixer Connect Left to Right */
# define P_C_MIXER_CROSS_R_TO_L 0x04 /* R W Mixer Connect Right to Left */
# define P_C_MIXER_CROSS_L_TO_L 0x08 /* R W Mixer Connect Left to Left */
# define P_C_PCM_DAC_MODE 0x10 /* R W PCM Playback (DAC) mode */
# define P_C_PCM_ADC_MODE 0x00 /* R W PCM Record (ADC) mode */
# define P_C_PCM_MONO 0x20 /* R W PCM Mono mode */
# define P_C_PCM_STEREO 0x00 /* R W PCM Stereo mode */
# define P_C_PCM_ENABLE 0x40 /* R W PCM Enable PCM engine */
# define P_C_PCM_DMA_ENABLE 0x80 /* R W PCM Enable DRQ */
#define SAMPLE_COUNTER_CONTROL 0x138B /* R W PCM Sample counter control register */
# define S_C_C_SQUARE_WAVE 0x04 /* R W PCM Square wave generator (use for sample rate) */
# define S_C_C_RATE 0x06 /* R W PCM Rate generator (use for sample buffer count) */
# define S_C_C_LSB_THEN_MSB 0x30 /* R W PCM Change all 16 bits, LSB first, then MSB */
/* MVD101 and SDK documentations have S_C_C_SAMPLE_RATE and S_C_C_SAMPLE_BUFFER transposed. Only one works :-) */
# define S_C_C_SAMPLE_RATE 0x00 /* R W PCM Select sample rate timer */
# define S_C_C_SAMPLE_BUFFER 0x40 /* R W PCM Select sample buffer counter */
# define S_C_C_PC_SPEAKER 0x80 /* R W PCM Select PC speaker counter */
#define SAMPLE_RATE_TIMER 0x1388 /* W PCM Sample rate timer register (PCM wait interval) */
#define SAMPLE_BUFFER_COUNTER 0x1389 /* R W PCM Sample buffer counter (DMA buffer size) */
#define MIDI_CONTROL 0x178b /* R W MIDI Midi control register */
# define M_C_ENA_TSTAMP_IRQ 0x01 /* R W MIDI Enable Time Stamp Interrupts */
# define M_C_ENA_TME_COMP_IRQ 0x02 /* R W MIDI Enable time compare interrupts */
# define M_C_ENA_INPUT_IRQ 0x04 /* R W MIDI Enable input FIFO interrupts */
# define M_C_ENA_OUTPUT_IRQ 0x08 /* R W MIDI Enable output FIFO interrupts */
# define M_C_ENA_OUTPUT_HALF_IRQ 0x10 /* R W MIDI Enable output FIFO half full interrupts */
# define M_C_RESET_INPUT_FIFO 0x20 /* R W MIDI Reset input FIFO pointer */
# define M_C_RESET_OUTPUT_FIFO 0x40 /* R W MIDI Reset output FIFO pointer */
# define M_C_ENA_THRU_MODE 0x80 /* R W MIDI Echo input to output (THRU) */
#define MIDI_STATUS 0x1B88 /* R W MIDI Midi (interrupt) status register */
# define M_S_TIMESTAMP 0x01 /* R W MIDI Midi time stamp interrupt occurred */
# define M_S_COMPARE 0x02 /* R W MIDI Midi compare time interrupt occurred */
# define M_S_INPUT_AVAIL 0x04 /* R W MIDI Midi input data available interrupt occurred */
# define M_S_OUTPUT_EMPTY 0x08 /* R W MIDI Midi output FIFO empty interrupt occurred */
# define M_S_OUTPUT_HALF_EMPTY 0x10 /* R W MIDI Midi output FIFO half empty interrupt occurred */
# define M_S_INPUT_OVERRUN 0x20 /* R W MIDI Midi input overrun error occurred */
# define M_S_OUTPUT_OVERRUN 0x40 /* R W MIDI Midi output overrun error occurred */
# define M_S_FRAMING_ERROR 0x80 /* R W MIDI Midi input framing error occurred */
#define MIDI_FIFO_STATUS 0x1B89 /* R W MIDI Midi fifo status */
#define MIDI_DATA 0x178A /* R W MIDI Midi data register */
#define MIDI_INPUT_AVAILABLE 0x0f /* RW MIDI */

View File

@ -1,267 +0,0 @@
/*
* sound/patmgr.c
*
* The patch maneger interface for the /dev/sequencer
*
* Copyright by Hannu Savolainen 1993
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
* 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.
*
*/
#define PATMGR_C
#include <i386/isa/sound/sound_config.h>
#if defined(CONFIG_SEQUENCER)
static int *server_procs[MAX_SYNTH_DEV] = {NULL};
static volatile struct snd_wait server_wait_flag[MAX_SYNTH_DEV] = { {0}};
static struct patmgr_info *mbox[MAX_SYNTH_DEV] = {NULL};
static volatile int msg_direction[MAX_SYNTH_DEV] = {0};
static int pmgr_opened[MAX_SYNTH_DEV] = {0};
#define A_TO_S 1
#define S_TO_A 2
static int *appl_proc = NULL;
static volatile struct snd_wait appl_wait_flag =
{0};
int
pmgr_open(int dev)
{
if (dev < 0 || dev >= num_synths)
return -(ENXIO);
if (pmgr_opened[dev])
return -(EBUSY);
pmgr_opened[dev] = 1;
server_wait_flag[dev].aborting = 0;
server_wait_flag[dev].mode = WK_NONE;
return 0;
}
void
pmgr_release(int dev)
{
if (mbox[dev]) { /* Killed in action. Inform the client */
mbox[dev]->key = PM_ERROR;
mbox[dev]->parm1 = -(EIO);
if ((appl_wait_flag.mode & WK_SLEEP)) {
appl_wait_flag.mode = WK_WAKEUP;
wakeup(appl_proc);
};
}
pmgr_opened[dev] = 0;
}
int
pmgr_read(int dev, struct fileinfo * file, snd_rw_buf * buf, int count)
{
u_long flags;
int ok = 0;
if (count != sizeof(struct patmgr_info)) {
printf("PATMGR%d: Invalid read count\n", dev);
return -(EIO);
}
while (!ok && !(server_wait_flag[dev].aborting)) {
flags = splhigh();
while (!(mbox[dev] && msg_direction[dev] == A_TO_S) &&
!(server_wait_flag[dev].aborting)) {
int chn;
server_procs[dev] = &chn;
DO_SLEEP(chn, server_wait_flag[dev], 0);
}
if (mbox[dev] && msg_direction[dev] == A_TO_S) {
if (uiomove((char *) mbox[dev], count, buf)) {
printf("sb: Bad copyout()!\n");
};
msg_direction[dev] = 0;
ok = 1;
}
splx(flags);
}
if (!ok)
return -(EINTR);
return count;
}
int
pmgr_write(int dev, struct fileinfo * file, snd_rw_buf * buf, int count)
{
u_long flags;
if (count < 4) {
printf("PATMGR%d: Write count < 4\n", dev);
return -(EIO);
}
if (uiomove((char *) mbox[dev], 4, buf)) {
printf("sb: Bad copyin()!\n");
};
if (*(u_char *) mbox[dev] == SEQ_FULLSIZE) {
int tmp_dev;
tmp_dev = ((u_short *) mbox[dev])[2];
if (tmp_dev != dev)
return -(ENXIO);
return synth_devs[dev]->load_patch(dev, *(u_short *) mbox[dev],
buf, 4, count, 1);
}
if (count != sizeof(struct patmgr_info)) {
printf("PATMGR%d: Invalid write count\n", dev);
return -(EIO);
}
/*
* If everything went OK, there should be a preallocated buffer in
* the mailbox and a client waiting.
*/
flags = splhigh();
if (mbox[dev] && !msg_direction[dev]) {
if (uiomove(&((char *) mbox[dev])[4], count - 4, buf)) {
printf("sb: Bad copyin()!\n");
};
msg_direction[dev] = S_TO_A;
if ((appl_wait_flag.mode & WK_SLEEP)) {
appl_wait_flag.mode = WK_WAKEUP;
wakeup(appl_proc);
}
}
splx(flags);
return count;
}
int
pmgr_access(int dev, struct patmgr_info * rec)
{
u_long flags;
int err = 0;
flags = splhigh();
if (mbox[dev])
printf(" PATMGR: Server %d mbox full. Why?\n", dev);
else {
int chn;
rec->key = PM_K_COMMAND;
mbox[dev] = rec;
msg_direction[dev] = A_TO_S;
if ((server_wait_flag[dev].mode & WK_SLEEP)) {
server_wait_flag[dev].mode = WK_WAKEUP;
wakeup(server_procs[dev]);
}
appl_proc = &chn;
DO_SLEEP(chn, appl_wait_flag, 0);
if (msg_direction[dev] != S_TO_A) {
rec->key = PM_ERROR;
rec->parm1 = -(EIO);
} else if (rec->key == PM_ERROR) {
err = rec->parm1;
if (err > 0)
err = -err;
}
mbox[dev] = NULL;
msg_direction[dev] = 0;
}
splx(flags);
return err;
}
int
pmgr_inform(int dev, int event, u_long p1, u_long p2, u_long p3, u_long p4)
{
u_long flags;
int err = 0;
struct patmgr_info *tmp_mbox;
if (!pmgr_opened[dev])
return 0;
tmp_mbox = (struct patmgr_info *) malloc(sizeof(struct patmgr_info), M_TEMP, M_WAITOK);
if (tmp_mbox == NULL) {
printf("pmgr: Couldn't allocate memory for a message\n");
return 0;
}
flags = splhigh();
if (mbox[dev])
printf(" PATMGR: Server %d mbox full. Why?\n", dev);
else {
int chn;
mbox[dev] = tmp_mbox;
mbox[dev]->key = PM_K_EVENT;
mbox[dev]->command = event;
mbox[dev]->parm1 = p1;
mbox[dev]->parm2 = p2;
mbox[dev]->parm3 = p3;
msg_direction[dev] = A_TO_S;
if ((server_wait_flag[dev].mode & WK_SLEEP)) {
server_wait_flag[dev].mode = WK_WAKEUP;
wakeup(server_procs[dev]);
}
appl_proc = &chn;
DO_SLEEP(chn, appl_wait_flag, 0);
mbox[dev] = NULL;
msg_direction[dev] = 0;
}
splx(flags);
free(tmp_mbox, M_TEMP);
return err;
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,693 +0,0 @@
/*
* sound/pss.c
*
* The low level driver for the Personal Sound System (ECHO ESC614).
*
* Copyright by Hannu Savolainen 1993
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. 2.
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#include <i386/isa/sound/sound_config.h>
#if defined(CONFIG_PSS) && defined(CONFIG_AUDIO)
/*
* PSS registers.
*/
#define REG(x) (devc->base+x)
#define PSS_DATA 0
#define PSS_STATUS 2
#define PSS_CONTROL 2
#define PSS_ID 4
#define PSS_IRQACK 4
#define PSS_PIO 0x1a
/*
* Config registers
*/
#define CONF_PSS 0x10
#define CONF_WSS 0x12
#define CONF_SB 0x13
#define CONF_CDROM 0x16
#define CONF_MIDI 0x18
/*
* Status bits.
*/
#define PSS_FLAG3 0x0800
#define PSS_FLAG2 0x0400
#define PSS_FLAG1 0x1000
#define PSS_FLAG0 0x0800
#define PSS_WRITE_EMPTY 0x8000
#define PSS_READ_FULL 0x4000
#include "coproc.h"
#ifdef PSS_HAVE_LD
#include "synth-ld.h"
#else
static int pss_synthLen = 0;
static u_char pss_synth[1] =
{0};
#endif
typedef struct pss_config {
int base;
int irq;
int dma;
sound_os_info *osp;
} pss_config;
static pss_config pss_data;
static pss_config *devc = &pss_data;
static int pss_initialized = 0;
static int nonstandard_microcode = 0;
int
probe_pss(struct address_info * hw_config)
{
u_short id;
int irq, dma;
devc->base = hw_config->io_base;
irq = devc->irq = hw_config->irq;
dma = devc->dma = hw_config->dma;
devc->osp = hw_config->osp;
/* these are the possible addresses */
if (devc->base != 0x220 && devc->base != 0x240 &&
devc->base != 0x230 && devc->base != 0x250)
return 0;
/* these are the possible irqs */
if (irq != 3 && irq != 5 && irq != 7 && irq != 9 &&
irq != 10 && irq != 11 && irq != 12)
return 0;
/* and these are the possible dmas */
if (dma != 5 && dma != 6 && dma != 7)
return 0;
id = inb(REG(PSS_ID));
/* XXX the following test cannot possibly succeed! - lr970714 */
if ((id >> 8) != 'E') {
/*
* printf ("No PSS signature detected at 0x%x (0x%x)\n",
* devc->base, id);
*/
return 0;
}
return 1;
}
static int
set_irq(pss_config * devc, int dev, int irq)
{
static u_short irq_bits[16] =
{
0x0000, 0x0000, 0x0000, 0x0008,
0x0000, 0x0010, 0x0000, 0x0018,
0x0000, 0x0020, 0x0028, 0x0030,
0x0038, 0x0000, 0x0000, 0x0000
};
u_short tmp, bits;
if (irq < 0 || irq > 15)
return 0;
tmp = inb(REG(dev)) & ~0x38; /* Load confreg, mask IRQ bits out */
if ((bits = irq_bits[irq]) == 0 && irq != 0) {
printf("PSS: Invalid IRQ %d\n", irq);
return 0;
}
outw(REG(dev), tmp | bits);
return 1;
}
static int
set_io_base(pss_config * devc, int dev, int base)
{
u_short tmp = inb(REG(dev)) & 0x003f;
u_short bits = (base & 0x0ffc) << 4;
outw(REG(dev), bits | tmp);
return 1;
}
static int
set_dma(pss_config * devc, int dev, int dma)
{
static u_short dma_bits[8] =
{
0x0001, 0x0002, 0x0000, 0x0003,
0x0000, 0x0005, 0x0006, 0x0007
};
u_short tmp, bits;
if (dma < 0 || dma > 7)
return 0;
tmp = inb(REG(dev)) & ~0x07; /* Load confreg, mask DMA bits out */
if ((bits = dma_bits[dma]) == 0 && dma != 4) {
printf("PSS: Invalid DMA %d\n", dma);
return 0;
}
outw(REG(dev), tmp | bits);
return 1;
}
static int
pss_reset_dsp(pss_config * devc)
{
u_long i, limit = get_time() + 10;
outw(REG(PSS_CONTROL), 0x2000);
for (i = 0; i < 32768 && get_time() < limit; i++)
inb(REG(PSS_CONTROL));
outw(REG(PSS_CONTROL), 0x0000);
return 1;
}
static int
pss_put_dspword(pss_config * devc, u_short word)
{
int i, val;
for (i = 0; i < 327680; i++) {
val = inb(REG(PSS_STATUS));
if (val & PSS_WRITE_EMPTY) {
outw(REG(PSS_DATA), word);
return 1;
}
}
return 0;
}
static int
pss_get_dspword(pss_config * devc, u_short *word)
{
int i, val;
for (i = 0; i < 327680; i++) {
val = inb(REG(PSS_STATUS));
if (val & PSS_READ_FULL) {
*word = inb(REG(PSS_DATA));
return 1;
}
}
return 0;
}
static int
pss_download_boot(pss_config * devc, u_char *block, int size, int flags)
{
int i, limit, val, count;
if (flags & CPF_FIRST) {
/* _____ Warn DSP software that a boot is coming */
outw(REG(PSS_DATA), 0x00fe);
limit = get_time() + 10;
for (i = 0; i < 32768 && get_time() < limit; i++)
if (inb(REG(PSS_DATA)) == 0x5500)
break;
outw(REG(PSS_DATA), *block++);
pss_reset_dsp(devc);
}
count = 1;
while (1) {
int j;
for (j = 0; j < 327670; j++) {
/* _____ Wait for BG to appear */
if (inb(REG(PSS_STATUS)) & PSS_FLAG3)
break;
}
if (j == 327670) {
/* It's ok we timed out when the file was empty */
if (count >= size && flags & CPF_LAST)
break;
else {
printf("\nPSS: DownLoad timeout problems, byte %d=%d\n",
count, size);
return 0;
}
}
/* _____ Send the next byte */
outw(REG(PSS_DATA), *block++);
count++;
}
if (flags & CPF_LAST) {
/* _____ Why */
outw(REG(PSS_DATA), 0);
limit = get_time() + 10;
for (i = 0; i < 32768 && get_time() < limit; i++)
val = inb(REG(PSS_STATUS));
limit = get_time() + 10;
for (i = 0; i < 32768 && get_time() < limit; i++) {
val = inb(REG(PSS_STATUS));
if (val & 0x4000)
break;
}
/* now read the version */
for (i = 0; i < 32000; i++) {
val = inb(REG(PSS_STATUS));
if (val & PSS_READ_FULL)
break;
}
if (i == 32000)
return 0;
val = inb(REG(PSS_DATA));
/*
* printf("<PSS: microcode version %d.%d loaded>", val/16,
* val % 16);
*/
}
return 1;
}
void
attach_pss(struct address_info * hw_config)
{
u_short id;
char tmp[100];
devc->base = hw_config->io_base;
devc->irq = hw_config->irq;
devc->dma = hw_config->dma;
devc->osp = hw_config->osp;
if (!probe_pss(hw_config))
return;
id = inb(REG(PSS_ID)) & 0x00ff;
/*
* Disable all emulations. Will be enabled later (if required).
*/
outw(REG(CONF_PSS), 0x0000);
outw(REG(CONF_WSS), 0x0000);
outw(REG(CONF_SB), 0x0000);
outw(REG(CONF_MIDI), 0x0000);
outw(REG(CONF_CDROM), 0x0000);
#if YOU_REALLY_WANT_TO_ALLOCATE_THESE_RESOURCES
if (0) {
printf("pss.c: Can't allocate DMA channel\n");
return;
}
if (!set_irq(devc, CONF_PSS, devc->irq)) {
printf("PSS: IRQ error\n");
return;
}
if (!set_dma(devc, CONF_PSS, devc->dma)) {
printf("PSS: DRQ error\n");
return;
}
#endif
pss_initialized = 1;
snprintf(tmp, sizeof(tmp), "ECHO-PSS Rev. %d", id);
conf_printf(tmp, hw_config);
return;
}
int
probe_pss_mpu(struct address_info * hw_config)
{
int timeout;
if (!pss_initialized)
return 0;
if (0) {
printf("PSS: MPU I/O port conflict\n");
return 0;
}
if (!set_io_base(devc, CONF_MIDI, hw_config->io_base)) {
printf("PSS: MIDI base error.\n");
return 0;
}
if (!set_irq(devc, CONF_MIDI, hw_config->irq)) {
printf("PSS: MIDI IRQ error.\n");
return 0;
}
if (!pss_synthLen) {
printf("PSS: Can't enable MPU. MIDI synth microcode not available.\n");
return 0;
}
if (!pss_download_boot(devc, pss_synth, pss_synthLen, CPF_FIRST | CPF_LAST)) {
printf("PSS: Unable to load MIDI synth microcode to DSP.\n");
return 0;
}
/*
* Finally wait until the DSP algorithm has initialized itself and
* deactivates receive interrupt.
*/
for (timeout = 900000; timeout > 0; timeout--) {
if ((inb(hw_config->io_base + 1) & 0x80) == 0) /* Input data avail */
inb(hw_config->io_base); /* Discard it */
else
break; /* No more input */
}
#if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI)
return probe_mpu401(hw_config);
#else
return 0
#endif
}
static int
pss_coproc_open(void *dev_info, int sub_device)
{
switch (sub_device) {
case COPR_MIDI:
if (pss_synthLen == 0) {
printf("PSS: MIDI synth microcode not available.\n");
return -(EIO);
}
if (nonstandard_microcode)
if (!pss_download_boot(devc, pss_synth, pss_synthLen, CPF_FIRST | CPF_LAST)) {
printf("PSS: Unable to load MIDI synth microcode to DSP.\n");
return -(EIO);
}
nonstandard_microcode = 0;
break;
default:;
}
return 0;
}
static void
pss_coproc_close(void *dev_info, int sub_device)
{
return;
}
static void
pss_coproc_reset(void *dev_info)
{
if (pss_synthLen)
if (!pss_download_boot(devc, pss_synth, pss_synthLen, CPF_FIRST | CPF_LAST)) {
printf("PSS: Unable to load MIDI synth microcode to DSP.\n");
}
nonstandard_microcode = 0;
}
static int
download_boot_block(void *dev_info, copr_buffer * buf)
{
if (buf->len <= 0 || buf->len > sizeof(buf->data))
return -(EINVAL);
if (!pss_download_boot(devc, buf->data, buf->len, buf->flags)) {
printf("PSS: Unable to load microcode block to DSP.\n");
return -(EIO);
}
nonstandard_microcode = 1; /* The MIDI microcode has been
* overwritten */
return 0;
}
static int
pss_coproc_ioctl(void *dev_info, u_int cmd, ioctl_arg arg, int local)
{
/* printf("PSS coproc ioctl %x %x %d\n", cmd, arg, local); */
switch (cmd) {
case SNDCTL_COPR_RESET:
pss_coproc_reset(dev_info);
return 0;
break;
case SNDCTL_COPR_LOAD:
{
copr_buffer *buf;
int err;
buf = (copr_buffer *) malloc(sizeof(copr_buffer), M_TEMP, M_WAITOK);
if (buf == NULL)
return -(ENOSPC);
bcopy(&(((char *) arg)[0]), (char *) buf, sizeof(*buf));
err = download_boot_block(dev_info, buf);
free(buf, M_TEMP);
return err;
}
break;
case SNDCTL_COPR_RDATA:
{
copr_debug_buf buf;
u_long flags;
u_short tmp;
bcopy(&(((char *) arg)[0]), (char *) &buf, sizeof(buf));
flags = splhigh();
if (!pss_put_dspword(devc, 0x00d0)) {
splx(flags);
return -(EIO);
}
if (!pss_put_dspword(devc, (u_short) (buf.parm1 & 0xffff))) {
splx(flags);
return -(EIO);
}
if (!pss_get_dspword(devc, &tmp)) {
splx(flags);
return -(EIO);
}
buf.parm1 = tmp;
splx(flags);
bcopy(&buf, &(((char *) arg)[0]), sizeof(buf));
return 0;
}
break;
case SNDCTL_COPR_WDATA:
{
copr_debug_buf buf;
u_long flags;
u_short tmp;
bcopy(&(((char *) arg)[0]), (char *) &buf, sizeof(buf));
flags = splhigh();
if (!pss_put_dspword(devc, 0x00d1)) {
splx(flags);
return -(EIO);
}
if (!pss_put_dspword(devc, (u_short) (buf.parm1 & 0xffff))) {
splx(flags);
return -(EIO);
}
tmp = (u_int) buf.parm2 & 0xffff;
if (!pss_put_dspword(devc, tmp)) {
splx(flags);
return -(EIO);
}
splx(flags);
return 0;
}
break;
case SNDCTL_COPR_WCODE:
{
copr_debug_buf buf;
u_long flags;
u_short tmp;
bcopy(&(((char *) arg)[0]), (char *) &buf, sizeof(buf));
flags = splhigh();
if (!pss_put_dspword(devc, 0x00d3)) {
splx(flags);
return -(EIO);
}
if (!pss_put_dspword(devc, (u_short) (buf.parm1 & 0xffff))) {
splx(flags);
return -(EIO);
}
tmp = ((u_int) buf.parm2 >> 8) & 0xffff;
if (!pss_put_dspword(devc, tmp)) {
splx(flags);
return -(EIO);
}
tmp = (u_int) buf.parm2 & 0x00ff;
if (!pss_put_dspword(devc, tmp)) {
splx(flags);
return -(EIO);
}
splx(flags);
return 0;
}
break;
case SNDCTL_COPR_RCODE:
{
copr_debug_buf buf;
u_long flags;
u_short tmp;
bcopy(&(((char *) arg)[0]), (char *) &buf, sizeof(buf));
flags = splhigh();
if (!pss_put_dspword(devc, 0x00d2)) {
splx(flags);
return -(EIO);
}
if (!pss_put_dspword(devc, (u_short) (buf.parm1 & 0xffff))) {
splx(flags);
return -(EIO);
}
if (!pss_get_dspword(devc, &tmp)) { /* Read msb */
splx(flags);
return -(EIO);
}
buf.parm1 = tmp << 8;
if (!pss_get_dspword(devc, &tmp)) { /* Read lsb */
splx(flags);
return -(EIO);
}
buf.parm1 |= tmp & 0x00ff;
splx(flags);
bcopy(&buf, &(((char *) arg)[0]), sizeof(buf));
return 0;
}
break;
default:
return -(EINVAL);
}
return -(EINVAL);
}
static coproc_operations pss_coproc_operations =
{
"ADSP-2115",
pss_coproc_open,
pss_coproc_close,
pss_coproc_ioctl,
pss_coproc_reset,
&pss_data
};
void
attach_pss_mpu(struct address_info * hw_config)
{
int prev_devs;
#if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI)
prev_devs = num_midis;
attach_mpu401(hw_config);
if (num_midis == (prev_devs + 1)) /* The MPU driver installed
* itself */
midi_devs[prev_devs]->coproc = &pss_coproc_operations;
#endif
}
int
probe_pss_mss(struct address_info * hw_config)
{
int timeout;
if (!pss_initialized)
return 0;
if (0) {
printf("PSS: WSS I/O port conflict\n");
return 0;
}
if (!set_io_base(devc, CONF_WSS, hw_config->io_base)) {
printf("PSS: WSS base error.\n");
return 0;
}
if (!set_irq(devc, CONF_WSS, hw_config->irq)) {
printf("PSS: WSS IRQ error.\n");
return 0;
}
if (!set_dma(devc, CONF_WSS, hw_config->dma)) {
printf("PSS: WSS DRQ error\n");
return 0;
}
/*
* For some reason the card returns 0xff in the WSS status register
* immediately after boot. Propably MIDI+SB emulation algorithm
* downloaded to the ADSP2115 spends some time initializing the card.
* Let's try to wait until it finishes this task.
*/
for (timeout = 0;
timeout < 100000 && (inb(hw_config->io_base + 3) & 0x3f) != 0x04;
timeout++);
return probe_mss(hw_config);
}
void
attach_pss_mss(struct address_info * hw_config)
{
int prev_devs;
long ret;
prev_devs = num_audiodevs;
attach_mss(hw_config);
/* Check if The MSS driver installed itself */
if (num_audiodevs == (prev_devs + 1))
audio_devs[prev_devs]->coproc = &pss_coproc_operations;
}
#endif

View File

@ -1,371 +0,0 @@
/******************************************************************************
def.h
Version 1.3 11/2/93
Copyright (c) 1993 Analog Devices Inc. All rights reserved
******************************************************************************/
/* Port offsets from base port for Sound Blaster DSP */
#define DSP_PORT_CMSD0 0x00 /* C/MS music voice 1-6 data port, write only */
#define DSP_PORT_CMSR0 0x01 /* C/MS music voice 1-6 register port, write only */
#define DSP_PORT_CMSD1 0x02 /* C/MS music voice 7-12 data port, write only */
#define DSP_PORT_CMSR1 0x03 /* C/MS music voice 7-12 register port, write only */
#define DSP_PORT_STATUS 0x04 /* DSP Status bits, read only */
#define DSP_PORT_CONTROL 0x04 /* DSP Control bits, write only */
#define DSP_PORT_DATA_LSB 0x05 /* Read or write LSB of 16 bit data */
#define DSP_PORT_RESET 0x06 /* DSP Reset, write only */
#define DSP_PORT_07h 0x07 /* reserved port */
#define DSP_PORT_FMD0 0x08 /* FM music data/status port, read/write */
#define DSP_PORT_FMR0 0x09 /* FM music data/status port, write only */
#define DSP_PORT_RDDATA 0x0A /* DSP Read data, read only reading signals DSP */
#define DSP_PORT_0Bh 0x0B /* reserved port */
#define DSP_PORT_WRDATA 0x0C /* DSP Write data or command, write */
#define DSP_PORT_WRBUSY 0x0C /* DSP Write buffer status (bit 7), read */
#define DSP_PORT_0Dh 0x0D /* reserved port */
#define DSP_PORT_DATAAVAIL 0x0E /* DSP Data available status (bit 7), read only */
#define DSP_PORT_INTERFACE 0x0E /* Sets DMA Channel and Interrupt, write only */
#define DSP_PORT_0Fh 0x0F /* reserved port (used on Pro cards) */
#define ADDR_MASK 0x003f
#define INT_MASK 0xffc7
#define INT_3_BITS 0x0008
#define INT_5_BITS 0x0010
#define INT_7_BITS 0x0018
#define INT_9_BITS 0x0020
#define INT_10_BITS 0x0028
#define INT_11_BITS 0x0030
#define INT_12_BITS 0x0038
#define GAME_BIT 0x0400
#define GAME_BIT_MASK 0xfbff
#define INT_TEST_BIT 0x0200
#define INT_TEST_PASS 0x0100
#define INT_TEST_BIT_MASK 0xFDFF
#define DMA_MASK 0xfff8
#define DMA_0_BITS 0x0001
#define DMA_1_BITS 0x0002
#define DMA_3_BITS 0x0003
#define DMA_5_BITS 0x0004
#define DMA_6_BITS 0x0005
#define DMA_7_BITS 0x0006
#define DMA_TEST_BIT 0x0080
#define DMA_TEST_PASS 0x0040
#define DMA_TEST_BIT_MASK 0xFF7F
/* Echo DSP Flags */
#define DSP_FLAG3 0x10
#define DSP_FLAG2 0x08
#define DSP_FLAG1 0x80
#define DSP_FLAG0 0x40
#define PSS_CONFIG 0x10
#define PSS_WSS_CONFIG 0x12
#define SB_CONFIG 0x14
#define MIDI_CONFIG 0x18
#define CD_CONFIG 0x16
#define UART_CONFIG 0x1a
#define PSS_DATA 0x00
#define PSS_STATUS 0x02
#define PSS_CONTROL 0x02
#define PSS_ID_VERS 0x04
#define PSS_FLAG3 0x0800
#define PSS_FLAG2 0x0400
#define PSS_FLAG1 0x1000
#define PSS_FLAG0 0x0800
/*_____ WSS defines */
#define WSS_BASE_ADDRESS 0x530
#define WSS_CONFIG 0x0
#define WSS_VERSION 0x03
#define WSS_SP0 0x04
#define WSS_SP1 0x05
#define WSS_SP2 0x06
#define WSS_SP3 0x07
/*_____ SoundPort register addresses */
#define SP_LIN_SOURCE_CTRL 0x00
#define SP_RIN_SOURCE_CTRL 0x01
#define SP_LIN_GAIN_CTRL 0x10
#define SP_RIN_GAIN_CTRL 0x11
#define SP_LAUX1_CTRL 0x02
#define SP_RAUX1_CTRL 0x03
#define SP_LAUX2_CTRL 0x04
#define SP_RAUX2_CTRL 0x05
#define SP_LOUT_CTRL 0x06
#define SP_ROUT_CTRL 0x07
#define SP_CLK_FORMAT 0x48
#define SP_INT_CONF 0x09
#define SP_INT_CONF_MCE 0x49
#define SP_PIN_CTRL 0x0a
#define SP_TEST_INIT 0x0b
#define SP_MISC_CTRL 0x0c
#define SP_MIX_CTRL 0x0d
#define SP_DMA_UCNT 0x0e
#define SP_DMA_LCNT 0x0f
/*_____ Gain constants */
#define GAIN_0 0x00
#define GAIN_1_5 0x01
#define GAIN_3 0x02
#define GAIN_4_5 0x03
#define GAIN_6 0x04
#define GAIN_7_5 0x05
#define GAIN_9 0x06
#define GAIN_10_5 0x07
#define GAIN_12 0x08
#define GAIN_13_5 0x09
#define GAIN_15 0x0a
#define GAIN_16_5 0x0b
#define GAIN_18 0x0c
#define GAIN_19_5 0x0d
#define GAIN_21 0x0e
#define GAIN_22_5 0x0f
#define MUTE 0XFFFF
/*_____ Attenuation constants */
#define ATTEN_0 0x00
#define ATTEN_1_5 0x01
#define ATTEN_3 0x02
#define ATTEN_4_5 0x03
#define ATTEN_6 0x04
#define ATTEN_7_5 0x05
#define ATTEN_9 0x06
#define ATTEN_10_5 0x07
#define ATTEN_12 0x08
#define ATTEN_13_5 0x09
#define ATTEN_15 0x0a
#define ATTEN_16_5 0x0b
#define ATTEN_18 0x0c
#define ATTEN_19_5 0x0d
#define ATTEN_21 0x0e
#define ATTEN_22_5 0x0f
#define PSS_WRITE_EMPTY 0x8000
#define CD_POL_MASK 0xFFBF
#define CD_POL_BIT 0x0040
/******************************************************************************
host.h
Version 1.2 9/27/93
Copyright (c) 1993 Analog Devices Inc. All rights reserved
******************************************************************************/
#define SB_WRITE_FULL 0x80
#define SB_READ_FULL 0x80
#define SB_WRITE_STATUS 0x0C
#define SB_READ_STATUS 0x0E
#define SB_READ_DATA 0x0A
#define SB_WRITE_DATA 0x0C
#define PSS_DATA_REG 0x00
#define PSS_STATUS_REG 0x02
#define PSS_WRITE_EMPTY 0x8000
#define PSS_READ_FULL 0x4000
/*_____ 1848 Sound Port bit defines */
#define SP_IN_INIT 0x80
#define MODE_CHANGE_ENABLE 0x40
#define MODE_CHANGE_MASK 0xbf
#define TRANSFER_DISABLE 0x20
#define TRANSFER_DISABLE_MASK 0xdf
#define ADDRESS_MASK 0xf0
/*_____ Status bits */
#define INTERRUPT_STATUS 0x01
#define PLAYBACK_READY 0x02
#define PLAYBACK_LEFT 0x04
/*_____ pbright is not left */
#define PLAYBACK_UPPER 0x08
/*_____ bplower is not upper */
#define SAMPLE_OVERRUN 0x10
#define SAMPLE_UNDERRUN 0x10
#define CAPTURE_READY 0x20
#define CAPTURE_LEFT 0x40
/*_____ cpright is not left */
#define CAPTURE_UPPER 0x08
/*_____ cplower is not upper */
/*_____ Input & Output regs bits */
#define LINE_INPUT 0x80
#define AUX_INPUT 0x40
#define MIC_INPUT 0x80
#define MIXED_DAC_INPUT 0xC0
#define INPUT_GAIN_MASK 0xf0
#define INPUT_MIC_GAIN_ENABLE 0x20
#define INPUT_MIC_GAIN_MASK 0xdf
#define INPUT_SOURCE_MASK 0x3f
#define AUX_INPUT_ATTEN_MASK 0xf0
#define AUX_INPUT_MUTE 0x80
#define AUX_INPUT_MUTE_MASK 0x7f
#define OUTPUT_MUTE 0x80
#define OUTPUT_MUTE_MASK 0x7f
#define OUTPUT_ATTEN_MASK 0xc0
/*_____ Clock and Data format reg bits */
#define CLOCK_SELECT_MASK 0xfe
#define CLOCK_XTAL2 0x01
#define CLOCK_XTAL1 0x00
#define CLOCK_FREQ_MASK 0xf1
#define STEREO_MONO_MASK 0xef
#define STEREO 0x10
#define AUDIO_MONO 0x00
#define LINEAR_COMP_MASK 0xdf
#define LINEAR 0x00
#define COMPANDED 0x20
#define FORMAT_MASK 0xbf
#define PCM 0x00
#define ULAW 0x00
#define TWOS_COMP 0x40
#define ALAW 0x40
/*_____ Interface Configuration reg bits */
#define PLAYBACK_ENABLE 0x01
#define PLAYBACK_ENABLE_MASK 0xfe
#define CAPTURE_ENABLE 0x02
#define CAPTURE_ENABLE_MASK 0xfd
#define SINGLE_DMA 0x04
#define SINGLE_DMA_MASK 0xfb
#define DUAL_DMA 0x00
#define AUTO_CAL_ENABLE 0x08
#define AUTO_CAL_DISABLE_MASK 0xf7
#define PLAYBACK_PIO_ENABLE 0x40
#define PLAYBACK_DMA_MASK 0xbf
#define CAPTURE_PIO_ENABLE 0x80
#define CAPTURE_DMA_MASK 0x7f
/*_____ Pin control bits */
#define INTERRUPT_ENABLE 0x02
#define INTERRUPT_MASK 0xfd
/*_____ Test and init reg bits */
#define OVERRANGE_LEFT_MASK 0xfc
#define OVERRANGE_RIGHT_MASK 0xf3
#define DATA_REQUEST_STATUS 0x10
#define AUTO_CAL_IN_PROG 0x20
#define PLAYBACK_UNDERRUN 0x40
#define CAPTURE_UNDERRUN 0x80
/*_____ Miscellaneous Control reg bits */
#define ID_MASK 0xf0
/*_____ Digital Mix Control reg bits */
#define DIGITAL_MIX1_MUTE_MASK 0xfe
#define MIX_ATTEN_MASK 0x03
/*_____ 1848 Sound Port reg defines */
#define SP_LEFT_INPUT_CONTROL 0x0
#define SP_RIGHT_INPUT_CONTROL 0x1
#define SP_LEFT_AUX1_CONTROL 0x2
#define SP_RIGHT_AUX1_CONTROL 0x3
#define SP_LEFT_AUX2_CONTROL 0x4
#define SP_RIGHT_AUX2_CONTROL 0x5
#define SP_LEFT_OUTPUT_CONTROL 0x6
#define SP_RIGHT_OUTPUT_CONTROL 0x7
#define SP_CLOCK_DATA_FORMAT 0x8
#define SP_INTERFACE_CONFIG 0x9
#define SP_PIN_CONTROL 0xA
#define SP_TEST_AND_INIT 0xB
#define SP_MISC_INFO 0xC
#define SP_DIGITAL_MIX 0xD
#define SP_UPPER_BASE_COUNT 0xE
#define SP_LOWER_BASE_COUNT 0xF
#define HOST_SP_ADDR (0x534)
#define HOST_SP_DATA (0x535)
/******************************************************************************
phillips.h
Version 1.2 9/27/93
Copyright (c) 1993 Analog Devices Inc. All rights reserved
******************************************************************************/
/*_____ Phillips control SW defines */
/*_____ Settings and ranges */
#define VOLUME_MAX 6
#define VOLUME_MIN (-64)
#define VOLUME_RANGE 70
#define VOLUME_STEP 2
#define BASS_MAX 15
#define BASS_MIN (-12)
#define BASS_STEP 2
#define BASS_RANGE 27
#define TREBLE_MAX 12
#define TREBLE_MIN (-12)
#define TREBLE_STEP 2
#define TREBLE_RANGE 24
#define VOLUME_CONSTANT 252
#define BASS_CONSTANT 246
#define TREBLE_CONSTANT 246
/*_____ Software commands */
#define SET_MASTER_COMMAND 0x0010
#define MASTER_VOLUME_LEFT 0x0000
#define MASTER_VOLUME_RIGHT 0x0100
#define MASTER_BASS 0x0200
#define MASTER_TREBLE 0x0300
#define MASTER_SWITCH 0x0800
#define STEREO_MODE 0x00ce
#define PSEUDO_MODE 0x00d6
#define SPATIAL_MODE 0x00de
#define MONO_MODE 0x00c6
#define PSS_STEREO 0x00ce
#define PSS_PSEUDO 0x00d6
#define PSS_SPATIAL 0x00de
#define PSS_MONO 0x00c6
#define PHILLIPS_VOL_MIN -64
#define PHILLIPS_VOL_MAX 6
#define PHILLIPS_VOL_DELTA 70
#define PHILLIPS_VOL_INITIAL -20
#define PHILLIPS_VOL_CONSTANT 252
#define PHILLIPS_VOL_STEP 2
#define PHILLIPS_BASS_MIN -12
#define PHILLIPS_BASS_MAX 15
#define PHILLIPS_BASS_DELTA 27
#define PHILLIPS_BASS_INITIAL 0
#define PHILLIPS_BASS_CONSTANT 246
#define PHILLIPS_BASS_STEP 2
#define PHILLIPS_TREBLE_MIN -12
#define PHILLIPS_TREBLE_MAX 12
#define PHILLIPS_TREBLE_DELTA 24
#define PHILLIPS_TREBLE_INITIAL 0
#define PHILLIPS_TREBLE_CONSTANT 246
#define PHILLIPS_TREBLE_STEP 2

View File

@ -1,535 +0,0 @@
/*
* sound/sb16_dsp.c
*
* The low level driver for the SoundBlaster DSP chip.
*
* (C) 1993 J. Schubert (jsb@sth.ruhr-uni-bochum.de)
*
* based on SB-driver by (C) Hannu Savolainen
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
* 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.
*
*/
#define DEB(x)
#define DEB1(x)
#include <i386/isa/sound/sound_config.h>
#include "sb.h"
#include <i386/isa/sound/sb_mixer.h>
#include <i386/isa/sound/sbcard.h>
#if defined(CONFIG_SB16) && (NSB > 0) && defined(CONFIG_AUDIO) && defined(CONFIG_SBPRO)
extern sound_os_info *sb_osp;
extern int sbc_base;
static int sb16_dsp_ok = 0;
static int dsp_16bit = 0;
static int dsp_stereo = 0;
static int dsp_current_speed = 8000;
static int dsp_busy = 0;
static int dma16, dma8;
static int trigger_bits = 0;
static u_long dsp_count = 0;
static int irq_mode = IMODE_NONE;
static int my_dev = 0;
static volatile int intr_active = 0;
static int sb16_dsp_open(int dev, int mode);
static void sb16_dsp_close(int dev);
static void sb16_dsp_output_block(int dev, u_long buf, int count, int intrflag, int dma_restart);
static void sb16_dsp_start_input(int dev, u_long buf, int count, int intrflag, int dma_restart);
static int sb16_dsp_ioctl(int dev, u_int cmd, ioctl_arg arg, int local);
static int sb16_dsp_prepare_for_input(int dev, int bsize, int bcount);
static int sb16_dsp_prepare_for_output(int dev, int bsize, int bcount);
static void sb16_dsp_reset(int dev);
static void sb16_dsp_halt(int dev);
static void sb16_dsp_trigger(int dev, int bits);
static int dsp_set_speed(int);
static int dsp_set_stereo(int);
static void dsp_cleanup(void);
static struct audio_operations sb16_dsp_operations =
{
"SoundBlaster 16",
DMA_AUTOMODE,
AFMT_U8 | AFMT_S16_LE,
NULL,
sb16_dsp_open,
sb16_dsp_close,
sb16_dsp_output_block,
sb16_dsp_start_input,
sb16_dsp_ioctl,
sb16_dsp_prepare_for_input,
sb16_dsp_prepare_for_output,
sb16_dsp_reset,
sb16_dsp_halt,
NULL,
NULL,
NULL,
NULL,
sb16_dsp_trigger
};
static int
sb_dsp_command01(u_char val)
{
int i = 1 << 16;
while (--i & (!inb(DSP_STATUS) & 0x80));
if (!i)
printf("SB16 sb_dsp_command01 Timeout\n");
return sb_dsp_command(val);
}
static int
dsp_set_speed(int mode)
{
DEB(printf("dsp_set_speed(%d)\n", mode));
if (mode) {
RANGE (mode, 5000, 44100);
dsp_current_speed = mode;
}
return mode;
}
static int
dsp_set_stereo(int mode)
{
DEB(printf("dsp_set_stereo(%d)\n", mode));
dsp_stereo = mode;
return mode;
}
static int
dsp_set_bits(int arg)
{
DEB(printf("dsp_set_bits(%d)\n", arg));
if (arg)
dsp_16bit = (arg == 16) ? 1 : 0 ;
return dsp_16bit ? 16 : 8;
}
static int
sb16_dsp_ioctl(int dev, u_int cmd, ioctl_arg arg, int local)
{
switch (cmd) {
case SOUND_PCM_WRITE_RATE:
if (local)
return dsp_set_speed((int) arg);
return *(int *) arg = dsp_set_speed((*(int *) arg));
case SOUND_PCM_READ_RATE:
if (local)
return dsp_current_speed;
return *(int *) arg = dsp_current_speed;
case SNDCTL_DSP_STEREO:
if (local)
return dsp_set_stereo((int) arg);
return *(int *) arg = dsp_set_stereo((*(int *) arg));
case SOUND_PCM_WRITE_CHANNELS:
if (local)
return dsp_set_stereo((int) arg - 1) + 1;
return *(int *) arg = dsp_set_stereo((*(int *) arg) - 1) + 1;
case SOUND_PCM_READ_CHANNELS:
if (local)
return dsp_stereo + 1;
return *(int *) arg = dsp_stereo + 1;
case SNDCTL_DSP_SETFMT:
if (local)
return dsp_set_bits((int) arg);
return *(int *) arg = dsp_set_bits((*(int *) arg));
case SOUND_PCM_READ_BITS:
if (local)
return dsp_16bit ? 16 : 8;
return *(int *) arg = dsp_16bit ? 16 : 8;
case SOUND_PCM_WRITE_FILTER: /* NOT YET IMPLEMENTED */
if ((*(int *) arg) > 1)
return *(int *) arg = -(EINVAL);
case FIOASYNC:
if (local)
return 1;
return *(int *) arg = 1;
case FIONBIO:
if (local)
return 1;
return *(int *) arg = 1;
default:
return -(EINVAL);
}
return -(EINVAL);
}
static int
sb16_dsp_open(int dev, int mode)
{
DEB(printf("sb16_dsp_open()\n"));
if (!sb16_dsp_ok) {
printf("SB16 Error: SoundBlaster board not installed\n");
return -(ENXIO);
}
if (intr_active)
return -(EBUSY);
sb_reset_dsp();
irq_mode = IMODE_NONE;
dsp_busy = 1;
trigger_bits = 0;
return 0;
}
static void
sb16_dsp_close(int dev)
{
u_long flags;
DEB(printf("sb16_dsp_close()\n"));
sb_dsp_command01(0xd9);
sb_dsp_command01(0xd5);
flags = splhigh();
audio_devs[dev]->dmachan1 = dma8;
dsp_cleanup();
dsp_busy = 0;
splx(flags);
}
static void
sb16_dsp_output_block(int dev, u_long buf, int count, int intrflag, int dma_restart)
{
u_long flags, cnt;
cnt = count;
if (dsp_16bit)
cnt >>= 1;
cnt--;
if (audio_devs[dev]->flags & DMA_AUTOMODE && intrflag && cnt==dsp_count) {
irq_mode = IMODE_OUTPUT;
intr_active = 1;
return; /* Auto mode on. No need to react */
}
flags = splhigh();
if (dma_restart) {
sb16_dsp_halt(dev);
DMAbuf_start_dma(dev, buf, count, 1);
}
sb_dsp_command(0x41);
sb_dsp_command((u_char) ((dsp_current_speed >> 8) & 0xff));
sb_dsp_command((u_char) (dsp_current_speed & 0xff));
sb_dsp_command((u_char) (dsp_16bit ? 0xb6 : 0xc6));
dsp_count = cnt;
sb_dsp_command((u_char) ((dsp_stereo ? 0x20 : 0) +
(dsp_16bit ? 0x10 : 0)));
sb_dsp_command((u_char) (cnt & 0xff));
sb_dsp_command((u_char) (cnt >> 8));
irq_mode = IMODE_OUTPUT;
intr_active = 1;
splx(flags);
}
static void
sb16_dsp_start_input(int dev, u_long buf, int count, int intrflag, int dma_restart)
{
u_long flags, cnt;
cnt = count;
if (dsp_16bit)
cnt >>= 1;
cnt--;
if (audio_devs[dev]->flags & DMA_AUTOMODE && intrflag && cnt == dsp_count) {
irq_mode = IMODE_INPUT;
intr_active = 1;
return; /* Auto mode on. No need to react */
}
flags = splhigh();
if (dma_restart) {
sb_reset_dsp();
DMAbuf_start_dma(dev, buf, count, 0);
}
sb_dsp_command(0x42);
sb_dsp_command((u_char) ((dsp_current_speed >> 8) & 0xff));
sb_dsp_command((u_char) (dsp_current_speed & 0xff));
sb_dsp_command((u_char) (dsp_16bit ? 0xbe : 0xce));
dsp_count = cnt;
sb_dsp_command((u_char) ((dsp_stereo ? 0x20 : 0) +
(dsp_16bit ? 0x10 : 0)));
sb_dsp_command01((u_char) (cnt & 0xff));
sb_dsp_command((u_char) (cnt >> 8));
irq_mode = IMODE_INPUT;
intr_active = 1;
splx(flags);
}
static int
sb16_dsp_prepare_for_input(int dev, int bsize, int bcount)
{
int fudge;
struct dma_buffparms *dmap = audio_devs[dev]->dmap_in;
audio_devs[my_dev]->dmachan2 = dsp_16bit ? dma16 : dma8;
fudge = audio_devs[my_dev]->dmachan2 ;
if (dmap->dma_chan != fudge ) {
isa_dma_release( dmap->dma_chan);
isa_dma_acquire(fudge);
dmap->dma_chan = fudge;
}
dsp_count = 0;
dsp_cleanup();
if (dsp_16bit)
sb_dsp_command(0xd5); /* Halt DMA until trigger() is called */
else
sb_dsp_command(0xd0); /* Halt DMA until trigger() is called */
trigger_bits = 0;
return 0;
}
static int
sb16_dsp_prepare_for_output(int dev, int bsize, int bcount)
{
int fudge = dsp_16bit ? dma16 : dma8;
struct dma_buffparms *dmap = audio_devs[dev]->dmap_out;
if (dmap->dma_chan != fudge ) {
isa_dma_release( dmap->dma_chan);
isa_dma_acquire(fudge);
dmap->dma_chan = fudge;
}
audio_devs[my_dev]->dmachan1 = fudge;
dsp_count = 0;
dsp_cleanup();
if (dsp_16bit)
sb_dsp_command(0xd5); /* Halt DMA until trigger() is called */
else
sb_dsp_command(0xd0); /* Halt DMA until trigger() is called */
trigger_bits = 0;
return 0;
}
static void
sb16_dsp_trigger(int dev, int bits)
{
if (bits != 0)
bits = 1;
if (bits == trigger_bits) /* No change */
return;
trigger_bits = bits;
if (!bits)
sb_dsp_command(0xd0); /* Halt DMA */
else if (bits & irq_mode)
sb_dsp_command(0xd4); /* Continue DMA */
}
static void
dsp_cleanup(void)
{
irq_mode = IMODE_NONE;
intr_active = 0;
}
static void
sb16_dsp_reset(int dev)
{
u_long flags;
flags = splhigh();
sb_reset_dsp();
dsp_cleanup();
splx(flags);
}
static void
sb16_dsp_halt(int dev)
{
if (dsp_16bit) {
sb_dsp_command01(0xd9);
sb_dsp_command01(0xd5);
} else {
sb_dsp_command01(0xda);
sb_dsp_command01(0xd0);
}
}
static void
set_irq_hw(int level)
{
int ival;
switch (level) {
case 5:
ival = 2;
break;
case 7:
ival = 4;
break;
case 9:
ival = 1;
break;
case 10:
ival = 8;
break;
default:
printf("SB16_IRQ_LEVEL %d does not exist\n", level);
return;
}
sb_setmixer(IRQ_NR, ival);
}
void
sb16_dsp_init(struct address_info * hw_config)
{
if (sbc_major < 4)
return; /* Not a SB16 */
snprintf(sb16_dsp_operations.name, sizeof(sb16_dsp_operations.name),
"SoundBlaster 16 %d.%d", sbc_major, sbc_minor);
conf_printf(sb16_dsp_operations.name, hw_config);
if (num_audiodevs < MAX_AUDIO_DEV) {
audio_devs[my_dev = num_audiodevs++] = &sb16_dsp_operations;
audio_devs[my_dev]->dmachan1 = dma8;
audio_devs[my_dev]->buffsize = DSP_BUFFSIZE;
} else
printf("SB: Too many DSP devices available\n");
sb16_dsp_ok = 1;
return;
}
int
sb16_dsp_detect(struct address_info * hw_config)
{
struct address_info *sb_config;
if (sb16_dsp_ok)
return 1; /* Can't drive two cards */
if (!(sb_config = sound_getconf(SNDCARD_SB))) {
printf("SB16 Error: Plain SB not configured\n");
return 0;
}
/*
* sb_setmixer(OPSW,0xf); if(sb_getmixer(OPSW)!=0xf) return 0;
*/
if (!sb_reset_dsp())
return 0;
if (sbc_major < 4) /* Set by the plain SB driver */
return 0; /* Not a SB16 */
if (hw_config->dma < 4)
if (hw_config->dma != sb_config->dma) {
printf("SB16 Error: Invalid DMA channel %d/%d\n",
sb_config->dma, hw_config->dma);
return 0;
}
dma16 = hw_config->dma;
dma8 = sb_config->dma;
/* hw_config->irq = 0; sb_config->irq;
hw_config->io_base = sb_config->io_base;
*/
set_irq_hw(sb_config->irq);
sb_setmixer(DMA_NR, (1 << hw_config->dma) | (1 << sb_config->dma));
DEB(printf("SoundBlaster 16: IRQ %d DMA %d OK\n",
sb_config->irq, hw_config->dma));
/*
* dsp_showmessage(0xe3,99);
*/
sb16_dsp_ok = 1;
return 1;
}
void
sb16_dsp_interrupt(int unused)
{
int data;
data = inb(DSP_DATA_AVL16); /* Interrupt acknowledge */
if (intr_active)
switch (irq_mode) {
case IMODE_OUTPUT:
DMAbuf_outputintr(my_dev, 1);
break;
case IMODE_INPUT:
DMAbuf_inputintr(my_dev);
break;
default:
printf("SoundBlaster: Unexpected interrupt\n");
}
}
#endif

View File

@ -1,299 +0,0 @@
/*
* sound/sb16_midi.c
*
* The low level driver for the MPU-401 UART emulation of the SB16.
*
* Copyright by Hannu Savolainen 1993
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. 2.
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#include <i386/isa/sound/sound_config.h>
#include <i386/isa/sound/sbcard.h>
#if defined(CONFIG_SB) && defined(CONFIG_SB16) && defined(CONFIG_MIDI)
#include "sb.h"
#define DATAPORT (sb16midi_base)
#define COMDPORT (sb16midi_base+1)
#define STATPORT (sb16midi_base+1)
extern sound_os_info *sb_osp;
#define sb16midi_status() inb( STATPORT)
#define input_avail() (!(sb16midi_status()&INPUT_AVAIL))
#define output_ready() (!(sb16midi_status()&OUTPUT_READY))
#define sb16midi_cmd(cmd) outb( COMDPORT, cmd)
#define sb16midi_read() inb( DATAPORT)
#define sb16midi_write(byte) outb( DATAPORT, byte)
#define OUTPUT_READY 0x40
#define INPUT_AVAIL 0x80
#define MPU_ACK 0xFE
#define MPU_RESET 0xFF
#define UART_MODE_ON 0x3F
static int sb16midi_opened = 0;
static int sb16midi_base = 0x330;
static int sb16midi_detected = 0;
static int my_dev;
extern int sbc_base;
static int reset_sb16midi(void);
static void (*midi_input_intr) (int dev, u_char data);
static volatile u_char input_byte;
static void
sb16midi_input_loop(void)
{
while (input_avail()) {
u_char c = sb16midi_read();
if (c == MPU_ACK)
input_byte = c;
else if (sb16midi_opened & OPEN_READ && midi_input_intr)
midi_input_intr(my_dev, c);
}
}
void
sb16midiintr(int unit)
{
if (input_avail())
sb16midi_input_loop();
}
static int
sb16midi_open(int dev, int mode,
void (*input) (int dev, u_char data),
void (*output) (int dev)
)
{
if (sb16midi_opened) {
return -(EBUSY);
}
sb16midi_input_loop();
midi_input_intr = input;
sb16midi_opened = mode;
return 0;
}
static void
sb16midi_close(int dev)
{
sb16midi_opened = 0;
}
static int
sb16midi_out(int dev, u_char midi_byte)
{
int timeout;
u_long flags;
/*
* Test for input since pending input seems to block the output.
*/
flags = splhigh();
if (input_avail())
sb16midi_input_loop();
splx(flags);
/*
* Sometimes it takes about 13000 loops before the output becomes
* ready (After reset). Normally it takes just about 10 loops.
*/
for (timeout = 30000; timeout > 0 && !output_ready(); timeout--); /* Wait */
if (!output_ready()) {
printf("MPU-401: Timeout\n");
return 0;
}
sb16midi_write(midi_byte);
return 1;
}
static int
sb16midi_start_read(int dev)
{
return 0;
}
static int
sb16midi_end_read(int dev)
{
return 0;
}
static int
sb16midi_ioctl(int dev, u_int cmd, ioctl_arg arg)
{
return -(EINVAL);
}
static void
sb16midi_kick(int dev)
{
}
static int
sb16midi_buffer_status(int dev)
{
return 0; /* No data in buffers */
}
#define MIDI_SYNTH_NAME "SoundBlaster 16 Midi"
#define MIDI_SYNTH_CAPS SYNTH_CAP_INPUT
#include <i386/isa/sound/midi_synth.h>
static struct midi_operations sb16midi_operations =
{
{"SoundBlaster 16 Midi", 0, 0, SNDCARD_SB16MIDI},
&std_midi_synth,
{0},
sb16midi_open,
sb16midi_close,
sb16midi_ioctl,
sb16midi_out,
sb16midi_start_read,
sb16midi_end_read,
sb16midi_kick,
NULL,
sb16midi_buffer_status,
NULL
};
void
attach_sb16midi(struct address_info * hw_config)
{
int ok, timeout;
u_long flags;
sb16midi_base = hw_config->io_base;
if (!sb16midi_detected)
return;
flags = splhigh();
for (timeout = 30000; timeout < 0 && !output_ready(); timeout--); /* Wait */
input_byte = 0;
sb16midi_cmd(UART_MODE_ON);
ok = 0;
for (timeout = 50000; timeout > 0 && !ok; timeout--)
if (input_byte == MPU_ACK)
ok = 1;
else if (input_avail())
if (sb16midi_read() == MPU_ACK)
ok = 1;
splx(flags);
if (num_midis >= MAX_MIDI_DEV) {
printf("Sound: Too many midi devices detected\n");
return;
}
conf_printf("SoundBlaster MPU-401", hw_config);
std_midi_synth.midi_dev = my_dev = num_midis;
midi_devs[num_midis++] = &sb16midi_operations;
return;
}
static int
reset_sb16midi(void)
{
int ok, timeout, n;
/*
* Send the RESET command. Try again if no success at the first time.
*/
if (inb(STATPORT) == 0xff)
return 0;
ok = 0;
/* flags = splhigh(); */
for (n = 0; n < 2 && !ok; n++) {
for (timeout = 30000; timeout < 0 && !output_ready(); timeout--); /* Wait */
input_byte = 0;
sb16midi_cmd(MPU_RESET); /* Send MPU-401 RESET Command */
/*
* Wait at least 25 msec. This method is not accurate so
* let's make the loop bit longer. Cannot sleep since this is
* called during boot.
*/
for (timeout = 50000; timeout > 0 && !ok; timeout--)
if (input_byte == MPU_ACK) /* Interrupt */
ok = 1;
else if (input_avail())
if (sb16midi_read() == MPU_ACK)
ok = 1;
}
sb16midi_opened = 0;
if (ok)
sb16midi_input_loop(); /* Flush input before enabling
* interrupts */
/* splx(flags); */
return ok;
}
int
probe_sb16midi(struct address_info * hw_config)
{
int ok = 0;
struct address_info *sb_config;
if (sbc_major < 4)
return 0; /* Not a SB16 */
if (!(sb_config = sound_getconf(SNDCARD_SB))) {
printf("SB16 Error: Plain SB not configured\n");
return 0;
}
sb16midi_base = hw_config->io_base;
ok = reset_sb16midi();
sb16midi_detected = ok;
return ok;
}
#endif

View File

@ -1,67 +0,0 @@
/*
* sound/sb_card.c
*
* Detection routine for the SoundBlaster cards.
*
* Copyright by Hannu Savolainen 1993
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. 2.
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Modified: Riccardo Facchetti 24 Mar 1995 - Added the Audio Excel DSP 16
* initialization routine.
*
* Major code cleanup - Luigi Rizzo (luigi@iet.unipi.it) 970711
*/
#include <i386/isa/sound/sound_config.h>
#if NSB > 0
#include <i386/isa/sound/sbcard.h>
void
attach_sb_card(struct address_info * hw_config)
{
#if defined(CONFIG_AUDIO) || defined(CONFIG_MIDI)
#if 0
/* why do a detect during the attach ? XXX */
if (!sb_dsp_detect(hw_config))
return ;
#endif
sb_dsp_init(hw_config);
#endif
return ;
}
int
probe_sb(struct address_info * hw_config)
{
#if defined(CONFIG_AEDSP16) && defined(AEDSP16_SBPRO)
/*
* Initialize Audio Excel DSP 16 to SBPRO.
*/
InitAEDSP16_SBPRO(hw_config);
#endif
return sb_dsp_detect(hw_config);
}
#endif

View File

@ -1,43 +0,0 @@
#ifdef PC98
#define DSP_RESET (sbc_base + 0x600)
#define DSP_READ (sbc_base + 0xA00)
#define DSP_WRITE (sbc_base + 0xC00)
#define DSP_COMMAND (sbc_base + 0xC00)
#define DSP_STATUS (sbc_base + 0xC00)
#define DSP_DATA_AVAIL (sbc_base + 0xE00)
#define DSP_DATA_AVL16 (sbc_base + 0xF00)
#define MIXER_ADDR (sbc_base + 0x400)
#define MIXER_DATA (sbc_base + 0x500)
#define OPL3_LEFT (sbc_base + 0x000)
#define OPL3_RIGHT (sbc_base + 0x200)
#define OPL3_BOTH (sbc_base + 0x800)
#else
#define DSP_RESET (sbc_base + 0x6)
#define DSP_READ (sbc_base + 0xA)
#define DSP_WRITE (sbc_base + 0xC)
#define DSP_COMMAND (sbc_base + 0xC)
#define DSP_STATUS (sbc_base + 0xC)
#define DSP_DATA_AVAIL (sbc_base + 0xE)
#define DSP_DATA_AVL16 (sbc_base + 0xF)
#define MIXER_ADDR (sbc_base + 0x4)
#define MIXER_DATA (sbc_base + 0x5)
#define OPL3_LEFT (sbc_base + 0x0)
#define OPL3_RIGHT (sbc_base + 0x2)
#define OPL3_BOTH (sbc_base + 0x8)
#endif
/* DSP Commands */
#define DSP_CMD_SPKON 0xD1
#define DSP_CMD_SPKOFF 0xD3
#define DSP_CMD_DMAON 0xD0
#define DSP_CMD_DMAOFF 0xD4
#define IMODE_NONE 0
#define IMODE_OUTPUT 1
#define IMODE_INPUT 2
#define IMODE_INIT 3
#define IMODE_MIDI 4
#define NORMAL_MIDI 0
#define UART_MIDI 1

File diff suppressed because it is too large Load Diff

View File

@ -1,211 +0,0 @@
/*
* sound/sb_dsp.c
*
* The low level driver for the SoundBlaster DS chips.
*
* Copyright by Hannu Savolainen 1993
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. 2.
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#include <i386/isa/sound/sound_config.h>
#if (NSND > 0) && defined(CONFIG_SB) && defined(CONFIG_MIDI)
#include <i386/isa/sound/sbcard.h>
#undef SB_TEST_IRQ
/*
* The DSP channel can be used either for input or output. Variable
* 'sb_irq_mode' will be set when the program calls read or write first time
* after open. Current version doesn't support mode changes without closing
* and reopening the device. Support for this feature may be implemented in a
* future version of this driver.
*/
extern int sb_dsp_ok; /* Set to 1 atfer successful initialization */
extern int sbc_base;
extern int sb_midi_mode;
extern int sb_midi_busy; /* 1 if the process has output to MIDI */
extern int sb_dsp_busy;
extern int sb_dsp_highspeed;
extern volatile int sb_irq_mode;
extern int sb_duplex_midi;
extern int sb_intr_active;
static int input_opened = 0;
static int my_dev;
extern sound_os_info *sb_osp;
static void (*midi_input_intr) (int dev, u_char data);
static int
sb_midi_open(int dev, int mode, void (*input) (int dev, u_char data),
void (*output) (int dev))
{
int ret;
if (!sb_dsp_ok) {
printf("SB Error: MIDI hardware not installed\n");
return -(ENXIO);
}
if (sb_midi_busy)
return -(EBUSY);
if (mode != OPEN_WRITE && !sb_duplex_midi) {
if (num_midis == 1)
printf("SoundBlaster: Midi input not currently supported\n");
return -(EPERM);
}
sb_midi_mode = NORMAL_MIDI;
if (mode != OPEN_WRITE) {
if (sb_dsp_busy || sb_intr_active)
return -(EBUSY);
sb_midi_mode = UART_MIDI;
}
if (sb_dsp_highspeed) {
printf("SB Error: Midi output not possible during stereo or high speed audio\n");
return -(EBUSY);
}
if (sb_midi_mode == UART_MIDI) {
sb_irq_mode = IMODE_MIDI;
sb_reset_dsp();
if (!sb_dsp_command(0x35))
return -(EIO); /* Enter the UART mode */
sb_intr_active = 1;
input_opened = 1;
midi_input_intr = input;
}
sb_midi_busy = 1;
return 0;
}
static void
sb_midi_close(int dev)
{
if (sb_midi_mode == UART_MIDI) {
sb_reset_dsp(); /* The only way to kill the UART mode */
}
sb_intr_active = 0;
sb_midi_busy = 0;
input_opened = 0;
}
static int
sb_midi_out(int dev, u_char midi_byte)
{
u_long flags;
if (sb_midi_mode == NORMAL_MIDI) {
flags = splhigh();
if (sb_dsp_command(0x38))
sb_dsp_command(midi_byte);
else
printf("SB Error: Unable to send a MIDI byte\n");
splx(flags);
} else
sb_dsp_command(midi_byte); /* UART write */
return 1;
}
static int
sb_midi_start_read(int dev)
{
if (sb_midi_mode != UART_MIDI) {
printf("SoundBlaster: MIDI input not implemented.\n");
return -(EPERM);
}
return 0;
}
static int
sb_midi_end_read(int dev)
{
if (sb_midi_mode == UART_MIDI) {
sb_reset_dsp();
sb_intr_active = 0;
}
return 0;
}
static int
sb_midi_ioctl(int dev, u_int cmd, ioctl_arg arg)
{
return -(EPERM);
}
void
sb_midi_interrupt(int dummy)
{
u_long flags;
u_char data;
flags = splhigh();
data = inb(DSP_READ);
if (input_opened)
midi_input_intr(my_dev, data);
splx(flags);
}
#define MIDI_SYNTH_NAME "SoundBlaster Midi"
#define MIDI_SYNTH_CAPS 0
#include <i386/isa/sound/midi_synth.h>
static struct midi_operations sb_midi_operations =
{
{"SoundBlaster", 0, 0, SNDCARD_SB},
&std_midi_synth,
{0},
sb_midi_open,
sb_midi_close,
sb_midi_ioctl,
sb_midi_out,
sb_midi_start_read,
sb_midi_end_read,
NULL, /* Kick */
NULL, /* command */
NULL, /* buffer_status */
NULL
};
void
sb_midi_init(int model)
{
if (num_midis >= MAX_MIDI_DEV) {
printf("Sound: Too many midi devices detected\n");
return;
}
std_midi_synth.midi_dev = num_midis;
my_dev = num_midis;
midi_devs[num_midis++] = &sb_midi_operations;
}
#endif

View File

@ -1,529 +0,0 @@
/*
* sound/sb_mixer.c
*
* The low level mixer driver for the SoundBlaster Pro and SB16 cards.
*
* Copyright by Hannu Savolainen 1994
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. 2.
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Modified: Hunyue Yau Jan 6 1994 Added code to support the Sound Galaxy
* NX Pro mixer.
*
*/
#include <i386/isa/sound/sound_config.h>
#if (NSB > 0) && defined(CONFIG_SBPRO)
#define __SB_MIXER_C__
#include <i386/isa/sound/sbcard.h>
#include <i386/isa/sound/sb_mixer.h>
#undef SB_TEST_IRQ
extern int sbc_base;
extern int Jazz16_detected;
extern sound_os_info *sb_osp;
static int mixer_initialized = 0;
static int supported_rec_devices;
static int supported_devices;
static int recmask = 0;
static int mixer_model;
static int mixer_caps;
static mixer_tab *iomap;
void
sb_setmixer(u_int port, u_int value)
{
u_long flags;
flags = splhigh(); /* XXX ouch... */
outb(MIXER_ADDR, (u_char) (port & 0xff)); /* Select register */
DELAY(10);
outb(MIXER_DATA, (u_char) (value & 0xff));
DELAY(10);
splx(flags);
}
int
sb_getmixer(u_int port)
{
int val;
u_long flags;
flags = splhigh();
outb(MIXER_ADDR, (u_char) (port & 0xff)); /* Select register */
DELAY(10);
val = inb(MIXER_DATA);
DELAY(10);
splx(flags);
return val;
}
void
sb_mixer_set_stereo(int mode)
{
if (!mixer_initialized)
return;
sb_setmixer(OUT_FILTER, ((sb_getmixer(OUT_FILTER) & ~STEREO_DAC)
| (mode ? STEREO_DAC : MONO_DAC)));
}
/*
* Returns:
* 0 No mixer detected.
* 1 Only a plain Sound Blaster Pro style mixer detected.
* 2 The Sound Galaxy NX Pro mixer detected.
*/
static int
detect_mixer(void)
{
#ifdef __SGNXPRO__
int oldbass, oldtreble;
extern int sbc_major;
#endif
int retcode = 1;
/*
* Detect the mixer by changing parameters of two volume channels. If
* the values read back match with the values written, the mixer is
* there (is it?)
*/
sb_setmixer(FM_VOL, 0xff);
sb_setmixer(VOC_VOL, 0x33);
if (sb_getmixer(FM_VOL) != 0xff)
return 0; /* No match */
if (sb_getmixer(VOC_VOL) != 0x33)
return 0;
#ifdef __SGNXPRO__
/*
* Attempt to detect the SG NX Pro by check for valid bass/treble
* registers.
*/
oldbass = sb_getmixer(BASS_LVL);
oldtreble = sb_getmixer(TREBLE_LVL);
sb_setmixer(BASS_LVL, 0xaa);
sb_setmixer(TREBLE_LVL, 0x55);
if ((sb_getmixer(BASS_LVL) != 0xaa) ||
(sb_getmixer(TREBLE_LVL) != 0x55)) {
retcode = 1; /* 1 == Only SB Pro detected */
} else
retcode = 2; /* 2 == SG NX Pro detected */
/*
* Restore register in either case since SG NX Pro has EEPROM with
* 'preferred' values stored.
*/
sb_setmixer(BASS_LVL, oldbass);
sb_setmixer(TREBLE_LVL, oldtreble);
/*
* If the SB version is 3.X (SB Pro), assume we have a SG NX Pro 16.
* In this case it's good idea to disable the Disney Sound Source
* compatibility mode. It's useless and just causes noise every time
* the LPT-port is accessed.
*
* Also place the card into WSS mode.
*/
if (sbc_major == 3) {
outb(sbc_base + 0x1c, 0x01);
outb(sbc_base + 0x1a, 0x00);
}
#endif
return retcode;
}
static void
change_bits(u_char *regval, int dev, int chn, int newval)
{
u_char mask;
int shift;
mask = (1 << (*iomap)[dev][chn].nbits) - 1;
newval = (int) ((newval * mask) + 50) / 100; /* Scale it */
shift = (*iomap)[dev][chn].bitoffs - (*iomap)[dev][LEFT_CHN].nbits + 1;
*regval &= ~(mask << shift); /* Filter out the previous value */
*regval |= (newval & mask) << shift; /* Set the new value */
}
static int
sb_mixer_get(int dev)
{
if (!((1 << dev) & supported_devices))
return -(EINVAL);
return levels[dev];
}
#ifdef JAZZ16
static char smw_mix_regs[] =/* Left mixer registers */
{
0x0b, /* SOUND_MIXER_VOLUME */
0x0d, /* SOUND_MIXER_BASS */
0x0d, /* SOUND_MIXER_TREBLE */
0x05, /* SOUND_MIXER_SYNTH */
0x09, /* SOUND_MIXER_PCM */
0x00, /* SOUND_MIXER_SPEAKER */
0x03, /* SOUND_MIXER_LINE */
0x01, /* SOUND_MIXER_MIC */
0x07, /* SOUND_MIXER_CD */
0x00, /* SOUND_MIXER_IMIX */
0x00, /* SOUND_MIXER_ALTPCM */
0x00, /* SOUND_MIXER_RECLEV */
0x00, /* SOUND_MIXER_IGAIN */
0x00, /* SOUND_MIXER_OGAIN */
0x00, /* SOUND_MIXER_LINE1 */
0x00, /* SOUND_MIXER_LINE2 */
0x00 /* SOUND_MIXER_LINE3 */
};
static void
smw_mixer_init(void)
{
int i;
sb_setmixer(0x00, 0x18);/* Mute unused (Telephone) line */
sb_setmixer(0x10, 0x38);/* Config register 2 */
supported_devices = 0;
for (i = 0; i < sizeof(smw_mix_regs); i++)
if (smw_mix_regs[i] != 0)
supported_devices |= (1 << i);
supported_rec_devices = supported_devices &
~(SOUND_MASK_BASS | SOUND_MASK_TREBLE | SOUND_MASK_PCM |
SOUND_MASK_VOLUME);
}
static int
smw_mixer_set(int dev, int value)
{
int left = value & 0x000000ff;
int right = (value & 0x0000ff00) >> 8;
int reg, val;
if (left > 100)
left = 100;
if (right > 100)
right = 100;
if (dev > 31)
return -(EINVAL);
if (!(supported_devices & (1 << dev))) /* Not supported */
return -(EINVAL);
switch (dev) {
case SOUND_MIXER_VOLUME:
sb_setmixer(0x0b, 96 - (96 * left / 100)); /* 96=mute, 0=max */
sb_setmixer(0x0c, 96 - (96 * right / 100));
break;
case SOUND_MIXER_BASS:
case SOUND_MIXER_TREBLE:
levels[dev] = left | (right << 8);
/* Set left bass and treble values */
val = ((levels[SOUND_MIXER_TREBLE] & 0xff) * 16 / 100) << 4;
val |= ((levels[SOUND_MIXER_BASS] & 0xff) * 16 / 100) & 0x0f;
sb_setmixer(0x0d, val);
/* Set right bass and treble values */
val = (((levels[SOUND_MIXER_TREBLE] >> 8) & 0xff) * 16 / 100) << 4;
val |= (((levels[SOUND_MIXER_BASS] >> 8) & 0xff) * 16 / 100) & 0x0f;
sb_setmixer(0x0e, val);
break;
default:
reg = smw_mix_regs[dev];
if (reg == 0)
return -(EINVAL);
sb_setmixer(reg, (24 - (24 * left / 100)) | 0x20); /* 24=mute, 0=max */
sb_setmixer(reg + 1, (24 - (24 * right / 100)) | 0x40);
}
levels[dev] = left | (right << 8);
return left | (right << 8);
}
#endif
static int
sb_mixer_set(int dev, int value)
{
int left = value & 0x000000ff;
int right = (value & 0x0000ff00) >> 8;
int regoffs;
u_char val;
#ifdef JAZZ16
if (Jazz16_detected == 2)
return smw_mixer_set(dev, value);
#endif
if (left > 100)
left = 100;
if (right > 100)
right = 100;
if (dev > 31)
return -(EINVAL);
if (!(supported_devices & (1 << dev))) /* Not supported */
return -(EINVAL);
regoffs = (*iomap)[dev][LEFT_CHN].regno;
if (regoffs == 0)
return -(EINVAL);
val = sb_getmixer(regoffs);
change_bits(&val, dev, LEFT_CHN, left);
levels[dev] = left | (left << 8);
if ((*iomap)[dev][RIGHT_CHN].regno != regoffs) { /* Change register */
sb_setmixer(regoffs, val); /* Save the old one */
regoffs = (*iomap)[dev][RIGHT_CHN].regno;
if (regoffs == 0)
return left | (left << 8); /* Just left channel present */
val = sb_getmixer(regoffs); /* Read the new one */
}
change_bits(&val, dev, RIGHT_CHN, right);
sb_setmixer(regoffs, val);
levels[dev] = left | (right << 8);
return left | (right << 8);
}
static void
set_recsrc(int src)
{
sb_setmixer(RECORD_SRC, (sb_getmixer(RECORD_SRC) & ~7) | (src & 0x7));
}
static int
set_recmask(int mask)
{
int devmask, i;
u_char regimageL, regimageR;
devmask = mask & supported_rec_devices;
switch (mixer_model) {
case 3:
if (devmask != SOUND_MASK_MIC && devmask != SOUND_MASK_LINE &&
devmask != SOUND_MASK_CD) {
/*
* More than one devices selected. Drop the previous
* selection
*/
devmask &= ~recmask;
}
if (devmask != SOUND_MASK_MIC && devmask != SOUND_MASK_LINE &&
devmask != SOUND_MASK_CD) {
/* More than one devices selected. Default to mic */
devmask = SOUND_MASK_MIC;
}
if (devmask ^ recmask) { /* Input source changed */
switch (devmask) {
case SOUND_MASK_MIC:
set_recsrc(SRC_MIC);
break;
case SOUND_MASK_LINE:
set_recsrc(SRC_LINE);
break;
case SOUND_MASK_CD:
set_recsrc(SRC_CD);
break;
default:
set_recsrc(SRC_MIC);
}
}
break;
case 4:
if (!devmask)
devmask = SOUND_MASK_MIC;
regimageL = regimageR = 0;
for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
if ((1 << i) & devmask) {
regimageL |= sb16_recmasks_L[i];
regimageR |= sb16_recmasks_R[i];
}
sb_setmixer(SB16_IMASK_L, regimageL);
sb_setmixer(SB16_IMASK_R, regimageR);
break;
}
recmask = devmask;
return recmask;
}
static int
sb_mixer_ioctl(int dev, u_int cmd, ioctl_arg arg)
{
if (((cmd >> 8) & 0xff) == 'M') {
if (cmd & IOC_IN)
switch (cmd & 0xff) {
case SOUND_MIXER_RECSRC:
return *(int *) arg = set_recmask((*(int *) arg));
break;
default:
return *(int *) arg = sb_mixer_set(cmd & 0xff, (*(int *) arg));
}
else
switch (cmd & 0xff) { /* Return parameters */
case SOUND_MIXER_RECSRC:
return *(int *) arg = recmask;
break;
case SOUND_MIXER_DEVMASK:
return *(int *) arg = supported_devices;
break;
case SOUND_MIXER_STEREODEVS:
if (Jazz16_detected)
return *(int *) arg = supported_devices;
else
return *(int *) arg = supported_devices & ~(SOUND_MASK_MIC | SOUND_MASK_SPEAKER);
break;
case SOUND_MIXER_RECMASK:
return *(int *) arg = supported_rec_devices;
break;
case SOUND_MIXER_CAPS:
return *(int *) arg = mixer_caps;
break;
default:
return *(int *) arg = sb_mixer_get(cmd & 0xff);
}
} else
return -(EINVAL);
}
static struct mixer_operations sb_mixer_operations =
{
"SoundBlaster",
sb_mixer_ioctl
};
static void
sb_mixer_reset(void)
{
int i;
for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
sb_mixer_set(i, levels[i]);
set_recmask(SOUND_MASK_MIC);
}
/*
* Returns a code depending on whether a SG NX Pro was detected. 1 == Plain
* SB Pro 2 == SG NX Pro detected. 3 == SB16
*
* Used to update message.
*/
int
sb_mixer_init(int major_model)
{
int mixer_type = 0;
sb_setmixer(0x00, 0); /* Reset mixer */
if (!(mixer_type = detect_mixer()))
return 0; /* No mixer. Why? */
mixer_initialized = 1;
mixer_model = major_model;
switch (major_model) {
case 3:
mixer_caps = SOUND_CAP_EXCL_INPUT;
#ifdef JAZZ16
if (Jazz16_detected == 2) { /* SM Wave */
supported_devices = 0;
supported_rec_devices = 0;
iomap = &sbpro_mix;
smw_mixer_init();
mixer_type = 1;
} else
#endif
#ifdef __SGNXPRO__
if (mixer_type == 2) { /* A SGNXPRO was detected */
supported_devices = SGNXPRO_MIXER_DEVICES;
supported_rec_devices = SGNXPRO_RECORDING_DEVICES;
iomap = &sgnxpro_mix;
} else
#endif
{
supported_devices = SBPRO_MIXER_DEVICES;
supported_rec_devices = SBPRO_RECORDING_DEVICES;
iomap = &sbpro_mix;
mixer_type = 1;
}
break;
case 4:
mixer_caps = 0;
supported_devices = SB16_MIXER_DEVICES;
supported_rec_devices = SB16_RECORDING_DEVICES;
iomap = &sb16_mix;
mixer_type = 3;
break;
default:
printf("SB Warning: Unsupported mixer type\n");
return 0;
}
if (num_mixers < MAX_MIXER_DEV)
mixer_devs[num_mixers++] = &sb_mixer_operations;
sb_mixer_reset();
return mixer_type;
}
#endif

View File

@ -1,255 +0,0 @@
/*
* sound/sb_mixer.h
*
* Definitions for the SB Pro and SB16 mixers
*
* Copyright by Hannu Savolainen 1993
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. 2.
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Modified: Hunyue Yau Jan 6 1994 Added defines for the Sound Galaxy NX Pro
* mixer.
*
*/
#define SBPRO_RECORDING_DEVICES (SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD)
/* Same as SB Pro, unless I find otherwise */
#define SGNXPRO_RECORDING_DEVICES SBPRO_RECORDING_DEVICES
#define SBPRO_MIXER_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_LINE | SOUND_MASK_MIC | \
SOUND_MASK_CD | SOUND_MASK_VOLUME)
/*
* SG NX Pro has treble and bass settings on the mixer. The 'speaker' channel
* is the COVOX/DisneySoundSource emulation volume control on the mixer. It
* does NOT control speaker volume. Should have own mask eventually?
*/
#define SGNXPRO_MIXER_DEVICES (SBPRO_MIXER_DEVICES|SOUND_MASK_BASS| \
SOUND_MASK_TREBLE|SOUND_MASK_SPEAKER )
#define SB16_RECORDING_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_LINE | SOUND_MASK_MIC | \
SOUND_MASK_CD)
#define SB16_MIXER_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_SPEAKER | SOUND_MASK_LINE | SOUND_MASK_MIC | \
SOUND_MASK_CD | \
SOUND_MASK_IGAIN | SOUND_MASK_OGAIN | \
SOUND_MASK_VOLUME | SOUND_MASK_BASS | SOUND_MASK_TREBLE)
/*
* Mixer registers
*
* NOTE! RECORD_SRC == IN_FILTER
*/
/*
* Mixer registers of SB Pro
*/
#define VOC_VOL 0x04
#define MIC_VOL 0x0A
#define MIC_MIX 0x0A
#define RECORD_SRC 0x0C
#define IN_FILTER 0x0C
#define OUT_FILTER 0x0E
#define MASTER_VOL 0x22
#define FM_VOL 0x26
#define CD_VOL 0x28
#define LINE_VOL 0x2E
#define IRQ_NR 0x80
#define DMA_NR 0x81
#define IRQ_STAT 0x82
#define OPSW 0x3c
/*
* Additional registers on the SG NX Pro
*/
#define COVOX_VOL 0x42
#define TREBLE_LVL 0x44
#define BASS_LVL 0x46
#define FREQ_HI (1 << 3)/* Use High-frequency ANFI filters */
#define FREQ_LOW 0 /* Use Low-frequency ANFI filters */
#define FILT_ON 0 /* Yes, 0 to turn it on, 1 for off */
#define FILT_OFF (1 << 5)
#define MONO_DAC 0x00
#define STEREO_DAC 0x02
/*
* Mixer registers of SB16
*/
#define SB16_IMASK_L 0x3d
#define SB16_IMASK_R 0x3e
#define LEFT_CHN 0
#define RIGHT_CHN 1
struct mixer_def {
unsigned int regno:8;
unsigned int bitoffs:4;
unsigned int nbits:4;
};
typedef struct mixer_def mixer_tab[32][2];
typedef struct mixer_def mixer_ent;
#define MIX_ENT(name, reg_l, bit_l, len_l, reg_r, bit_r, len_r) \
{{reg_l, bit_l, len_l}, {reg_r, bit_r, len_r}}
#ifdef __SB_MIXER_C__
mixer_tab sbpro_mix = {
MIX_ENT(SOUND_MIXER_VOLUME, 0x22, 7, 4, 0x22, 3, 4),
MIX_ENT(SOUND_MIXER_BASS, 0x00, 0, 0, 0x00, 0, 0),
MIX_ENT(SOUND_MIXER_TREBLE, 0x00, 0, 0, 0x00, 0, 0),
MIX_ENT(SOUND_MIXER_SYNTH, 0x26, 7, 4, 0x26, 3, 4),
MIX_ENT(SOUND_MIXER_PCM, 0x04, 7, 4, 0x04, 3, 4),
MIX_ENT(SOUND_MIXER_SPEAKER, 0x00, 0, 0, 0x00, 0, 0),
MIX_ENT(SOUND_MIXER_LINE, 0x2e, 7, 4, 0x2e, 3, 4),
MIX_ENT(SOUND_MIXER_MIC, 0x0a, 2, 3, 0x00, 0, 0),
MIX_ENT(SOUND_MIXER_CD, 0x28, 7, 4, 0x28, 3, 4),
MIX_ENT(SOUND_MIXER_IMIX, 0x00, 0, 0, 0x00, 0, 0),
MIX_ENT(SOUND_MIXER_ALTPCM, 0x00, 0, 0, 0x00, 0, 0),
MIX_ENT(SOUND_MIXER_RECLEV, 0x00, 0, 0, 0x00, 0, 0)
};
#ifdef __SGNXPRO__
mixer_tab sgnxpro_mix = {
MIX_ENT(SOUND_MIXER_VOLUME, 0x22, 7, 4, 0x22, 3, 4),
MIX_ENT(SOUND_MIXER_BASS, 0x46, 2, 3, 0x00, 0, 0),
MIX_ENT(SOUND_MIXER_TREBLE, 0x44, 2, 3, 0x00, 0, 0),
MIX_ENT(SOUND_MIXER_SYNTH, 0x26, 7, 4, 0x26, 3, 4),
MIX_ENT(SOUND_MIXER_PCM, 0x04, 7, 4, 0x04, 3, 4),
MIX_ENT(SOUND_MIXER_SPEAKER, 0x42, 2, 3, 0x00, 0, 0),
MIX_ENT(SOUND_MIXER_LINE, 0x2e, 7, 4, 0x2e, 3, 4),
MIX_ENT(SOUND_MIXER_MIC, 0x0a, 2, 3, 0x00, 0, 0),
MIX_ENT(SOUND_MIXER_CD, 0x28, 7, 4, 0x28, 3, 4),
MIX_ENT(SOUND_MIXER_IMIX, 0x00, 0, 0, 0x00, 0, 0),
MIX_ENT(SOUND_MIXER_ALTPCM, 0x00, 0, 0, 0x00, 0, 0),
MIX_ENT(SOUND_MIXER_RECLEV, 0x00, 0, 0, 0x00, 0, 0),
MIX_ENT(SOUND_MIXER_IGAIN, 0x00, 0, 0, 0x00, 0, 0),
MIX_ENT(SOUND_MIXER_OGAIN, 0x00, 0, 0, 0x00, 0, 0)
};
#endif
mixer_tab sb16_mix = {
MIX_ENT(SOUND_MIXER_VOLUME, 0x30, 7, 5, 0x31, 7, 5),
MIX_ENT(SOUND_MIXER_BASS, 0x46, 7, 4, 0x47, 7, 4),
MIX_ENT(SOUND_MIXER_TREBLE, 0x44, 7, 4, 0x45, 7, 4),
MIX_ENT(SOUND_MIXER_SYNTH, 0x34, 7, 5, 0x35, 7, 5),
MIX_ENT(SOUND_MIXER_PCM, 0x32, 7, 5, 0x33, 7, 5),
MIX_ENT(SOUND_MIXER_SPEAKER, 0x3b, 7, 2, 0x00, 0, 0),
MIX_ENT(SOUND_MIXER_LINE, 0x38, 7, 5, 0x39, 7, 5),
MIX_ENT(SOUND_MIXER_MIC, 0x3a, 7, 5, 0x00, 0, 0),
MIX_ENT(SOUND_MIXER_CD, 0x36, 7, 5, 0x37, 7, 5),
MIX_ENT(SOUND_MIXER_IMIX, 0x00, 0, 0, 0x00, 0, 0),
MIX_ENT(SOUND_MIXER_ALTPCM, 0x00, 0, 0, 0x00, 0, 0),
MIX_ENT(SOUND_MIXER_RECLEV, 0x3f, 7, 2, 0x40, 7, 2), /* Obsolete. Use IGAIN */
MIX_ENT(SOUND_MIXER_IGAIN, 0x3f, 7, 2, 0x40, 7, 2),
MIX_ENT(SOUND_MIXER_OGAIN, 0x41, 7, 2, 0x42, 7, 2)
};
#ifdef SM_GAMES /* Master volume is lower and PCM & FM
* volumes higher than with SB Pro. This
* improves the sound quality */
static unsigned short levels[SOUND_MIXER_NRDEVICES] =
{
0x2020, /* Master Volume */
0x4b4b, /* Bass */
0x4b4b, /* Treble */
0x6464, /* FM */
0x6464, /* PCM */
0x4b4b, /* PC Speaker */
0x4b4b, /* Ext Line */
0x0000, /* Mic */
0x4b4b, /* CD */
0x4b4b, /* Recording monitor */
0x4b4b, /* SB PCM */
0x4b4b, /* Recording level */
0x4b4b, /* Input gain */
0x4b4b}; /* Output gain */
#else /* If the user selected just plain SB Pro */
static unsigned short levels[SOUND_MIXER_NRDEVICES] =
{
0x5a5a, /* Master Volume */
0x4b4b, /* Bass */
0x4b4b, /* Treble */
0x4b4b, /* FM */
0x4b4b, /* PCM */
0x4b4b, /* PC Speaker */
0x4b4b, /* Ext Line */
0x1010, /* Mic */
0x4b4b, /* CD */
0x4b4b, /* Recording monitor */
0x4b4b, /* SB PCM */
0x4b4b, /* Recording level */
0x4b4b, /* Input gain */
0x4b4b}; /* Output gain */
#endif /* SM_GAMES */
static unsigned char sb16_recmasks_L[SOUND_MIXER_NRDEVICES] =
{
0x00, /* SOUND_MIXER_VOLUME */
0x00, /* SOUND_MIXER_BASS */
0x00, /* SOUND_MIXER_TREBLE */
0x40, /* SOUND_MIXER_SYNTH */
0x00, /* SOUND_MIXER_PCM */
0x00, /* SOUND_MIXER_SPEAKER */
0x10, /* SOUND_MIXER_LINE */
0x01, /* SOUND_MIXER_MIC */
0x04, /* SOUND_MIXER_CD */
0x00, /* SOUND_MIXER_IMIX */
0x00, /* SOUND_MIXER_ALTPCM */
0x00, /* SOUND_MIXER_RECLEV */
0x00, /* SOUND_MIXER_IGAIN */
0x00 /* SOUND_MIXER_OGAIN */
};
static unsigned char sb16_recmasks_R[SOUND_MIXER_NRDEVICES] =
{
0x00, /* SOUND_MIXER_VOLUME */
0x00, /* SOUND_MIXER_BASS */
0x00, /* SOUND_MIXER_TREBLE */
0x20, /* SOUND_MIXER_SYNTH */
0x00, /* SOUND_MIXER_PCM */
0x00, /* SOUND_MIXER_SPEAKER */
0x08, /* SOUND_MIXER_LINE */
0x01, /* SOUND_MIXER_MIC */
0x02, /* SOUND_MIXER_CD */
0x00, /* SOUND_MIXER_IMIX */
0x00, /* SOUND_MIXER_ALTPCM */
0x00, /* SOUND_MIXER_RECLEV */
0x00, /* SOUND_MIXER_IGAIN */
0x00 /* SOUND_MIXER_OGAIN */
};
/*
* Recording sources (SB Pro)
*/
#define SRC_MIC 1 /* Select Microphone recording source */
#define SRC_CD 3 /* Select CD recording source */
#define SRC_LINE 7 /* Use Line-in for recording source */
#endif

View File

@ -1,54 +0,0 @@
/*
* file: sbcard.h
*/
extern int sbc_major, sbc_minor ;
/*
* sound blaster registers
*/
#define DSP_RESET (sbc_base + 0x6)
#define DSP_READ (sbc_base + 0xA)
#define DSP_WRITE (sbc_base + 0xC)
#define DSP_COMMAND (sbc_base + 0xC)
#define DSP_STATUS (sbc_base + 0xC)
#define DSP_DATA_AVAIL (sbc_base + 0xE)
#define DSP_DATA_AVL16 (sbc_base + 0xF)
#define MIXER_ADDR (sbc_base + 0x4)
#define MIXER_DATA (sbc_base + 0x5)
#define OPL3_LEFT (sbc_base + 0x0)
#define OPL3_RIGHT (sbc_base + 0x2)
#define OPL3_BOTH (sbc_base + 0x8)
/*
* DSP Commands. There are many, and in many cases they are used explicitly
*/
#define DSP_CMD_SPKON 0xD1
#define DSP_CMD_SPKOFF 0xD3
#define DSP_CMD_DMAON 0xD0 /* ??? the comment says Halt DMA */
#define DSP_CMD_DMAOFF 0xD4 /* ??? comment says continue dma */
#define DSP_CMD_DMAHALT 0xD0
#define DSP_CMD_TCONST 0x40 /* set time constant */
#define DSP_CMD_HSSIZE 0x48 /* high speed dma count */
#define DSP_CMD_HSDAC 0x91 /* high speed dac */
#define DSP_CMD_HSADC 0x99 /* high speed adc */
#define DSP_CMD_DAC8 0x14 /* 8-bit dac (dma count) */
#define DSP_CMD_ADC8 0x24 /* 8-bit adc (dma count) */
#define DSP_CMD_GETVER 0xE1
#define DSP_CMD_GETID 0xE7 /* return id bytes */
#if 0 /*** unknown ***/
#endif
#define IMODE_NONE 0
#define IMODE_OUTPUT PCM_ENABLE_OUTPUT
#define IMODE_INPUT PCM_ENABLE_INPUT
#define IMODE_INIT 3
#define IMODE_MIDI 4
#define NORMAL_MIDI 0
#define UART_MIDI 1

File diff suppressed because it is too large Load Diff

View File

@ -1,120 +0,0 @@
$Id: sound.doc,v 1.8 1997/02/22 09:38:15 peter Exp $
Instructions on using audio on a FreeBSD 2.1 (or 2.0-current) system.
See also /sys/i386/conf/LINT.
To enable sound driver support, the controller sound code must be included
in your config file:
# SB = SoundBlaster; PAS = ProAudioSpectrum; GUS = Gravis UltraSound
# Controls all sound devices
controller snd0
Uncomment one or more of these device entries, depending on what type of
sound card you have:
# ProAudioSpectrum PCM and Midi - for PAS
#device pas0 at isa? port 0x388 irq 10 drq 6
# SoundBlaster DSP driver - for SB, SB Pro, SB16, PAS(emulating SB)
#device sb0 at isa? port 0x220 irq 7 drq 1
# SoundBlaster 16 DSP driver - for SB16 - requires sb0 device
#device sbxvi0 at isa? drq 5
# SoundBlaster 16 MIDI - for SB16 - requires sb0 device
#device sbmidi0 at isa? port 0x300
# Gravis UltraSound - for GUS, GUS16, GUSMAX
# For cards that use 2 DMA Channels:
# drq = Write DMA Channel, flags = Read DMA Channel
#device gus0 at isa? port 0x220 irq 11 drq 1 flags 0x3
# Gravis UltraSound 16 bit option - for GUS16 - requires gus0
#device gusxvi0 at isa? port 0x530 irq 7 drq 3
# MS Sound System (AD1848 Based Boards)
#device mss0 at isa? port 0x530 irq 10 drq 1
# Yamaha OPL-2/OPL-3 FM - for SB, SB Pro, SB16, PAS
#device opl0 at isa? port 0x388
# MPU-401 - for MPU-401 standalone card
#device mpu0 at isa? port 0x330 irq 6 drq 0
# 6850 UART Midi
#device uart0 at isa? port 0x330 irq 5
You may add one or more of the following depending on what you do and don't
want compiled into your kernel. Note: Excluding things with EXCLUDE_...
is NOT recommended unless you really know what you're doing.
#options EXCLUDE_AUDIO # NO digital audio support
#options EXCLUDE_SEQUENCER # NO sequencer support
#options EXCLUDE_MIDI # NO MIDI support whatsoever
#options EXCLUDE_SBPRO # EXCLUDE SB Pro support
#options EXCLUDE_SB_EMULATION # NO PAS SB emulation support
#options EXCLUDE_GUS_IODETECT # NO GUS io detection
#options EXCLUDE_PRO_MIDI # NO PAS MIDI support
Other Options:
#options SYMPHONY_PAS
Adds some code to make pas work with Symphony chipsets. Only use
this if your pas doesn't work and you have a Symphony chipset.
#options BROKEN_BUS_CLOCK
Some systems with the OPTI chipset and a PAS will require you to
use this option. Symptoms are that you will hear a lot of clicking and
popping sounds, like a geiger counter, coming out of the PAS even when
it is not playing anything.
#options MOZART_PORT
Adds support for Mozart (OAK OTI-601). (Part of the MSS driver)
#options OPTI_MAD16_PORT
Adds support for the OPTI MAD16 Chip. (Part of the MSS driver)
If your soundcard has a chip labeled "OPTi 82C929" then try this.
#options __SGNXPRO__
Adds support for the SG NX Pro mixer. (Part of the SB driver)
#options JAZZ16
Adds support for the MV Jazz16 (ProSonic etc). (Part of the SB Driver)
#options SM_WAVE
Adds support for the SoundMan Wave (Part of the SB Driver)
Note: You will need to do some work to get this to work.
See i386/isa/sound/configure.c
#options SM_GAMES
Adds support for the Logitech SoundMan Games (Part of the SB Driver)
#options PAS_JOYSTICK_ENABLE
Enables the gameport on the ProAudio Spectrum
NOTE: The MPU-401 driver may or may not work, and is unfortunately
unverifiable since no one I know has one. If you can test this,
please let me know! Also note that you will have to change these
settings if your soundcard is set for a non-standard address or IRQ.
Please check your documentation (or verify with any provided DOS utilities
that may have come with your card) and set the IRQ or address fields
accordingly.
Also: You can configure more then one card on a single DMA using
the conflicts keyword in your configuration file. This is useful for boards
with more then one type of emulation.
Probing problems: Since the SB16 uses the same IRQ and addresses for
the different drivers, some of the snd drivers will not be probed because
the kernel thinks there is a conflict. This can be worked-around by
using the "conflicts" keyword on the sb16's device line.
For further information, contact multimedia@freebsd.org
- Jordan Hubbard (jkh@freefall.cdrom.com)
- Steven Wallace (swallace@freefall.cdrom.com)
- Sujal Patel (smpatel@wam.umd.edu)

View File

@ -1,288 +0,0 @@
/*
* DMA buffer calls
*/
int DMAbuf_open(int dev, int mode);
int DMAbuf_release(int dev, int mode);
int DMAbuf_getwrbuffer(int dev, char **buf, int *size, int dontblock);
int DMAbuf_getrdbuffer(int dev, char **buf, int *len, int dontblock);
int DMAbuf_rmchars(int dev, int buff_no, int c);
int DMAbuf_start_output(int dev, int buff_no, int l);
int DMAbuf_ioctl(int dev, u_int cmd, ioctl_arg arg, int local);
void DMAbuf_init(void);
int DMAbuf_start_dma (int dev, u_long physaddr, int count, int dma_mode);
int DMAbuf_open_dma (int dev);
void DMAbuf_close_dma (int dev);
void DMAbuf_reset_dma (int dev);
void DMAbuf_inputintr(int dev);
void DMAbuf_outputintr(int dev, int underflow_flag);
void DMAbuf_start_devices(u_int devmask);
#ifdef ALLOW_POLL
int DMAbuf_select(int dev, struct fileinfo *file, int sel_type, select_table * wait);
#endif
/*
* System calls for /dev/dsp and /dev/audio
*/
int audio_read (int dev, struct fileinfo *file, snd_rw_buf *buf, int count);
int audio_write (int dev, struct fileinfo *file, snd_rw_buf *buf, int count);
int audio_open (int dev, struct fileinfo *file);
void audio_release (int dev, struct fileinfo *file);
int audio_ioctl (int dev, struct fileinfo *file,
u_int cmd, ioctl_arg arg);
int audio_lseek (int dev, struct fileinfo *file, off_t offset, int orig);
/* long audio_init (void); */
#ifdef ALLOW_SELECT
int audio_poll(int dev, struct fileinfo *file, int events, select_table * wait);
#endif
/*
* System calls for the /dev/sequencer
*/
int sequencer_read (int dev, struct fileinfo *file, snd_rw_buf *buf, int count);
int sequencer_write (int dev, struct fileinfo *file, snd_rw_buf *buf, int count);
int sequencer_open (int dev, struct fileinfo *file);
void sequencer_release (int dev, struct fileinfo *file);
int sequencer_ioctl (int dev, struct fileinfo *file,
u_int cmd, ioctl_arg arg);
int sequencer_lseek (int dev, struct fileinfo *file, off_t offset, int orig);
void sequencer_init (void);
void sequencer_timer(void *dummy);
int note_to_freq(int note_num);
u_long compute_finetune(u_long base_freq, int bend, int range);
void seq_input_event(u_char *event, int len);
void seq_copy_to_input (u_char *event, int len);
/*
* System calls for the /dev/midi
*/
int MIDIbuf_read (int dev, struct fileinfo *file, snd_rw_buf *buf, int count);
int MIDIbuf_write (int dev, struct fileinfo *file, snd_rw_buf *buf, int count);
int MIDIbuf_open (int dev, struct fileinfo *file);
void MIDIbuf_release (int dev, struct fileinfo *file);
int MIDIbuf_ioctl (int dev, struct fileinfo *file,
u_int cmd, ioctl_arg arg);
int MIDIbuf_lseek (int dev, struct fileinfo *file, off_t offset, int orig);
void MIDIbuf_bytes_received(int dev, u_char *buf, int count);
/*
*
* Misc calls from various sources
*/
/* From soundcard.c */
void soundcard_init(void);
void tenmicrosec(int);
void request_sound_timer (int count);
void sound_stop_timer(void);
int snd_ioctl_return(int *addr, int value);
int snd_set_irq_handler (int int_lvl, void(*hndlr)(int), sound_os_info *osp);
void sound_dma_malloc(int dev);
void sound_dma_free(int dev);
void conf_printf(char *name, struct address_info *hw_config);
void conf_printf2(char *name, int base, int irq, int dma, int dma2);
/* From sound_switch.c */
int sound_read_sw (int dev, struct fileinfo *file, snd_rw_buf *buf, int count);
int sound_write_sw (int dev, struct fileinfo *file, snd_rw_buf *buf, int count);
int sound_open_sw (int dev, struct fileinfo *file);
void sound_release_sw (int dev, struct fileinfo *file);
int sound_ioctl_sw (int dev, struct fileinfo *file, u_int cmd, ioctl_arg arg);
/* From sb_dsp.c */
int sb_dsp_detect (struct address_info *hw_config);
void sb_dsp_init (struct address_info *hw_config);
void sb_dsp_disable_midi(void);
int sb_dsp_command (u_char val);
ointhand2_t sbintr;
int sb_reset_dsp (void);
/* From sb16_dsp.c */
void sb16_dsp_interrupt (int irq);
void sb16_dsp_init(struct address_info *hw_config);
int sb16_dsp_detect(struct address_info *hw_config);
/* From sb16_midi.c */
void sb16midiintr (int unit);
void attach_sb16midi(struct address_info * hw_config);
int probe_sb16midi(struct address_info *hw_config);
void sb_midi_interrupt(int dummy);
/* From sb_midi.c */
void sb_midi_init(int model);
/* From sb_mixer.c */
void sb_setmixer (u_int port, u_int value);
int sb_getmixer (u_int port);
void sb_mixer_set_stereo(int mode);
int sb_mixer_init(int major_model);
/* From opl3.c */
int opl3_detect (int ioaddr, sound_os_info *osp);
void opl3_init(int ioaddr, sound_os_info *osp);
/* From sb_card.c */
void attach_sb_card(struct address_info *hw_config);
int probe_sb(struct address_info *hw_config);
/* From awe_wave.c */
void attach_awe(struct address_info *hw_config);
int probe_awe(struct address_info *hw_config);
/* From adlib_card.c */
void attach_adlib_card(struct address_info *hw_config);
int probe_adlib(struct address_info *hw_config);
/* From pas_card.c */
void attach_pas_card(struct address_info *hw_config);
int probe_pas(struct address_info *hw_config);
ointhand2_t pasintr;
int pas_set_intr(int mask);
int pas_remove_intr(int mask);
u_char pas_read(int ioaddr);
void pas_write(u_char data, int ioaddr);
/* From pas_audio.c */
void pas_pcm_interrupt(u_char status, int cause);
void pas_pcm_init(struct address_info *hw_config);
/* From pas_mixer.c */
int pas_init_mixer(void);
/* From pas_midi.c */
void pas_midi_init(void);
void pas_midi_interrupt(void);
/* From gus_card.c */
void attach_gus_card(struct address_info * hw_config);
int probe_gus(struct address_info *hw_config);
int gus_set_midi_irq(int num);
ointhand2_t gusintr;
void attach_gus_db16(struct address_info * hw_config);
int probe_gus_db16(struct address_info *hw_config);
/* From gus_wave.c */
int gus_wave_detect(int baseaddr);
void gus_wave_init(struct address_info *hw_config);
void gus_voice_irq(void);
u_char gus_read8 (int reg);
void gus_write8(int reg, u_int data);
void guswave_dma_irq(void);
void gus_delay(void);
int gus_default_mixer_ioctl (int dev, u_int cmd, ioctl_arg arg);
void gus_timer_command (u_int addr, u_int val);
/* From gus_midi.c */
void gus_midi_init(void);
void gus_midi_interrupt(int dummy);
/* From mpu401.c */
void attach_mpu401(struct address_info * hw_config);
int probe_mpu401(struct address_info *hw_config);
void mpuintr(int irq);
/* From uart6850.c */
void attach_uart6850(struct address_info * hw_config);
ointhand2_t m6850intr;
int probe_uart6850(struct address_info *hw_config);
/* From opl3.c */
void enable_opl3_mode(int left, int right, int both);
/* From patmgr.c */
int pmgr_open(int dev);
void pmgr_release(int dev);
int pmgr_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count);
int pmgr_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count);
int pmgr_access(int dev, struct patmgr_info *rec);
int pmgr_inform(int dev, int event, u_long parm1, u_long parm2,
u_long parm3, u_long parm4);
/* From ics2101.c */
void ics2101_mixer_init(void);
/* From sound_timer.c */
void sound_timer_interrupt(void);
void sound_timer_syncinterval(u_int new_usecs);
/* From ad1848.c */
void ad1848_init (char *name, int io_base, int irq, int dma_playback, int dma_capture, int share_dma, sound_os_info *osp);
ointhand2_t adintr;
int ad1848_detect (int io_base, int *flags, sound_os_info *osp);
#define AD_F_CS4231 0x0001 /* Returned if a CS4232 (or compatible) detected */
#define AD_F_CS4248 0x0001 /* Returned if a CS4248 (or compatible) detected */
void ad1848_interrupt (int irq);
void attach_mss(struct address_info * hw_config);
int probe_mss(struct address_info *hw_config);
void attach_pnp_ad1848(struct address_info * hw_config);
int probe_pnp_ad1848(struct address_info *hw_config);
/* From pss.c */
int probe_pss (struct address_info *hw_config);
void attach_pss (struct address_info *hw_config);
int probe_pss_mpu (struct address_info *hw_config);
void attach_pss_mpu (struct address_info *hw_config);
int probe_pss_mss (struct address_info *hw_config);
void attach_pss_mss (struct address_info *hw_config);
/* From sscape.c */
int probe_sscape (struct address_info *hw_config);
void attach_sscape (struct address_info *hw_config);
int probe_ss_mss(struct address_info *hw_config);
void attach_ss_mss(struct address_info * hw_config);
ointhand2_t sscapeintr;
int pss_read (int dev, struct fileinfo *file, snd_rw_buf *buf, int count);
int pss_write (int dev, struct fileinfo *file, snd_rw_buf *buf, int count);
int pss_open (int dev, struct fileinfo *file);
void pss_release (int dev, struct fileinfo *file);
int pss_ioctl (int dev, struct fileinfo *file,
u_int cmd, ioctl_arg arg);
int pss_lseek (int dev, struct fileinfo *file, off_t offset, int orig);
void pss_init(void);
/* From aedsp16.c */
int InitAEDSP16_SBPRO(struct address_info *hw_config);
int InitAEDSP16_MSS(struct address_info *hw_config);
int InitAEDSP16_MPU401(struct address_info *hw_config);
/* From midi_synth.c */
void do_midi_msg (int synthno, u_char *msg, int mlen);
/* From trix.c */
void attach_trix_wss (struct address_info *hw_config);
int probe_trix_wss (struct address_info *hw_config);
void attach_trix_sb (struct address_info *hw_config);
int probe_trix_sb (struct address_info *hw_config);
void attach_trix_mpu (struct address_info *hw_config);
int probe_trix_mpu (struct address_info *hw_config);
/* From mad16.c */
void attach_mad16 (struct address_info *hw_config);
int probe_mad16 (struct address_info *hw_config);
void attach_mad16_mpu (struct address_info *hw_config);
int probe_mad16_mpu (struct address_info *hw_config);
int mad16_sb_dsp_detect (struct address_info *hw_config);
void mad16_sb_dsp_init (struct address_info *hw_config);
/* From cs4232.c */
int probe_cs4232 (struct address_info *hw_config);
void attach_cs4232 (struct address_info *hw_config);
int probe_cs4232_mpu (struct address_info *hw_config);
void attach_cs4232_mpu (struct address_info *hw_config);
/* From maui.c */
void attach_maui(struct address_info * hw_config);
int probe_maui(struct address_info *hw_config);
/* From sound_pnp.c */
void sound_pnp_init(void);
void sound_pnp_disconnect(void);

View File

@ -1,205 +0,0 @@
/* sound_config.h
*
* A driver for Soundcards, misc configuration parameters.
*
* Copyright by Hannu Savolainen 1995
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
/*
* many variables should be reduced to a range. Here define a macro
*/
#define RANGE(var, low, high) (var) = \
((var)<(low)?(low) : (var)>(high)?(high) : (var))
#undef CONFIGURE_SOUNDCARD
#undef DYNAMIC_BUFFER
#include <i386/isa/sound/local.h>
#define CONFIGURE_SOUNDCARD
#define DYNAMIC_BUFFER
#undef LOADABLE_SOUNDCARD
#include <i386/isa/sound/os.h>
#include <i386/isa/sound/soundvers.h>
#if defined(ISC) || defined(SCO) || defined(SVR42)
#define GENERIC_SYSV
#endif
#ifndef SND_DEFAULT_ENABLE
#define SND_DEFAULT_ENABLE 1
#endif
#ifdef CONFIGURE_SOUNDCARD
#ifndef MAX_REALTIME_FACTOR
#define MAX_REALTIME_FACTOR 4
#endif
/************* PCM DMA buffer sizes *******************/
/* If you are using high playback or recording speeds, the default buffersize
is too small. DSP_BUFFSIZE must be 64k or less.
A rule of thumb is 64k for PAS16, 32k for PAS+, 16k for SB Pro and
4k for SB.
If you change the DSP_BUFFSIZE, don't modify this file.
Use the make config command instead. Seems to allow only 4K, 16K,
32K, 64K.
*/
#ifndef DSP_BUFFSIZE
#define DSP_BUFFSIZE (32760)
#endif
#ifndef DSP_BUFFCOUNT
#define DSP_BUFFCOUNT 1 /* 1 is recommended. */
#endif
#define DMA_AUTOINIT 0x10 /* XXX never used */
#define FM_MONO 0x388 /* This is the I/O address used by AdLib */
#ifndef AWE32_BASE
#define AWE32_BASE 0x620 /* Default = 0x620-3, 0xA20-3, 0xE20-3 */
#endif
#ifndef PAS_BASE
#define PAS_BASE 0x388
#endif
#ifdef JAZZ16
#ifndef JAZZ_DMA16
#define JAZZ_DMA16 5
#endif
#endif
/* SEQ_MAX_QUEUE is the maximum number of sequencer events buffered by the
driver. (There is no need to alter this) */
#define SEQ_MAX_QUEUE 1024
#define SBFM_MAXINSTR (256) /* Size of the FM Instrument bank */
/* 128 instruments for general MIDI setup and 16 unassigned */
/*
* Minor numbers for the sound driver.
*
* Unfortunately Creative called the codec chip of SB as a DSP. For this
* reason the /dev/dsp is reserved for digitized audio use. There is a
* device for true DSP processors but it will be called something else.
* In v3.0 it's /dev/sndproc but this could be a temporary solution.
*/
#define SND_NDEVS 256 /* Number of supported devices */
#define SND_DEV_CTL 0 /* Control port /dev/mixer */
#define SND_DEV_SEQ 1 /* Sequencer output /dev/sequencer (FM
synthesizer and MIDI output) */
#define SND_DEV_MIDIN 2 /* Raw midi access */
#define SND_DEV_DSP 3 /* Digitized voice /dev/dsp */
#define SND_DEV_AUDIO 4 /* Sparc compatible /dev/audio */
#define SND_DEV_DSP16 5 /* Like /dev/dsp but 16 bits/sample */
#define SND_DEV_STATUS 6 /* /dev/sndstat */
/* #7 not in use now. Was in 2.4. Free for use after v3.0. */
#define SND_DEV_SEQ2 8 /* /dev/sequencer, level 2 interface */
#define SND_DEV_SNDPROC 9 /* /dev/sndproc for programmable devices */
#define SND_DEV_PSS SND_DEV_SNDPROC
#define DSP_DEFAULT_SPEED 8000
#define ON 1
#define OFF 0
#define MAX_AUDIO_DEV 5
#define MAX_MIXER_DEV 5
#define MAX_SYNTH_DEV 3
#define MAX_MIDI_DEV 6
#define MAX_TIMER_DEV 3
struct fileinfo {
int mode; /* Open mode */
int flags;
int dummy; /* Reference to file-flags. OS-dependent. */
};
struct address_info {
int io_base;
int irq;
int dma;
int dma2;
int always_detect; /* 1=Trust me, it's there */
char *name;
sound_os_info *osp; /* OS specific info */
int card_subtype; /* Driver specific. Usually 0 */
};
#define SYNTH_MAX_VOICES 32
struct voice_alloc_info {
int max_voice;
int used_voices;
int ptr; /* For device specific use */
unsigned short map[SYNTH_MAX_VOICES]; /* (ch << 8) | (note+1) */
int timestamp;
int alloc_times[SYNTH_MAX_VOICES];
};
struct channel_info {
int pgm_num;
int bender_value;
unsigned char controllers[128];
};
/*
* Process wakeup reasons
*/
#define WK_NONE 0x00
#define WK_WAKEUP 0x01
#define WK_TIMEOUT 0x02
#define WK_SIGNAL 0x04
#define WK_SLEEP 0x08
#define OPEN_READ PCM_ENABLE_INPUT
#define OPEN_WRITE PCM_ENABLE_OUTPUT
#define OPEN_READWRITE (OPEN_READ|OPEN_WRITE)
#include <i386/isa/sound/sound_calls.h>
#include <i386/isa/sound/dev_table.h>
#ifndef DEB
#define DEB(x)
#endif
#ifndef DDB
/* #define DDB(x) x XXX */
#define DDB(x)
#endif
#define TIMER_ARMED 121234
#define TIMER_NOT_ARMED 1
#endif

View File

@ -1,186 +0,0 @@
/*
* sound/sound_pnp.c
*
* PnP soundcard support (Linux spesific)
*
* Copyright by Hannu Savolainen 1995
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. 2.
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#include <i386/isa/sound/sound_config.h>
/*
* XXX check what to use in place of CONFIG_PNP
*/
#if (NSND > 0) && defined(CONFIG_PNP)
#include <linux/pnp.h>
static struct pnp_sounddev *pnp_devs[20] = { NULL };
static int max_pnpdevs = 20;
static int nr_pnpdevs = 0;
static int pnp_sig = 0;
void
install_pnp_sounddrv(struct pnp_sounddev * drv)
{
if (nr_pnpdevs < max_pnpdevs) {
pnp_devs[nr_pnpdevs++] = drv;
} else
printf("Sound: More than 20 PnP drivers defined\n");
}
void
cs4232_pnp(void *parm)
{
struct pnp_dev *dev = (struct pnp_dev *) parm;
char *name;
int portmask = 0x00, irqmask = 0x01, dmamask = 0x03;
int opl3_driver, wss_driver;
printf("CS4232 driver waking up\n");
if (dev->card && dev->card->name)
name = dev->card->name;
else
name = "PnP WSS";
if ((wss_driver = sndtable_identify_card("AD1848")))
portmask |= 0x01; /* MSS */
else
printf("Sound: MSS/WSS device detected but no driver enabled\n");
if ((opl3_driver = sndtable_identify_card("OPL3")))
portmask |= 0x02; /* OPL3 */
else
printf("Sound: OPL3/4 device detected but no driver enabled\n");
printf("WSS driver %d, OPL3 driver %d\n", wss_driver, opl3_driver);
if (!portmask) /* No drivers available */
return;
if (!pnp_allocate_device(pnp_sig, dev, portmask, irqmask, dmamask, 0x00))
printf("Device activation failed\n");
else {
struct address_info hw_config;
int wss_base, opl3_base;
int irq;
int dma1, dma2;
printf("Device activation OK\n");
wss_base = pnp_get_port(dev, 0);
opl3_base = pnp_get_port(dev, 1);
irq = pnp_get_irq(dev, 0);
dma1 = pnp_get_dma(dev, 0);
dma2 = pnp_get_dma(dev, 1);
printf("I/O0 %03x\n", wss_base);
printf("I/O1 %03x\n", opl3_base);
printf("IRQ %d\n", irq);
printf("DMA0 %d\n", dma1);
printf("DMA1 %d\n", dma2);
if (opl3_base && opl3_driver) {
hw_config.io_base = opl3_base;
hw_config.irq = 0;
hw_config.dma = -1;
hw_config.dma2 = -1;
hw_config.always_detect = 0;
hw_config.name = "";
hw_config.osp = NULL;
hw_config.card_subtype = 0;
if (sndtable_probe(opl3_driver, &hw_config))
sndtable_init_card(opl3_driver, &hw_config);
}
if (wss_base && wss_driver) {
hw_config.io_base = wss_base;
hw_config.irq = irq;
hw_config.dma = dma1;
hw_config.dma2 = (dma2 == NO_DMA) ? dma1 : dma2;
hw_config.always_detect = 0;
hw_config.name = name;
hw_config.osp = NULL;
hw_config.card_subtype = 0;
if (sndtable_probe(wss_driver, &hw_config))
sndtable_init_card(wss_driver, &hw_config);
}
}
}
static int
pnp_activate(int id, struct pnp_dev * dev)
{
int i;
for (i = 0; i < nr_pnpdevs; i++)
if (pnp_devs[i]->id == id) {
printf("PnP dev: %08x, %s\n", id, pnp_devid2asc(id));
pnp_devs[i]->setup((void *) dev);
return 1;
}
return 0;
}
void
sound_pnp_init(void)
{
static struct pnp_sounddev cs4232_dev =
{PNP_DEVID('C', 'S', 'C', 0x0000), cs4232_pnp, "CS4232"};
struct pnp_dev *dev;
install_pnp_sounddrv(&cs4232_dev);
dev = NULL;
if ((pnp_sig = pnp_connect("sound")) == -1) {
printf("Sound: Can't connect to kernel PnP services.\n");
return;
}
while ((dev = pnp_get_next_device(pnp_sig, dev)) != NULL) {
if (!pnp_activate(dev->key, dev)) {
/* Scan all compatible devices */
int i;
for (i = 0; i < dev->ncompat; i++)
if (pnp_activate(dev->compat_keys[i], dev))
break;
}
}
}
void
sound_pnp_disconnect(void)
{
pnp_disconnect(pnp_sig);
}
#endif

View File

@ -1,499 +0,0 @@
/*
* sound/sound_switch.c
*
* The system call switch
*
* Copyright by Hannu Savolainen 1993
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. 2.
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#include <i386/isa/sound/sound_config.h>
#if NSND > 0
#define SNDSTAT_BUF_SIZE 4000
/*
* /dev/sndstatus -device
*/
static char *status_buf = NULL;
static int status_len, status_ptr;
static int status_busy = 0;
static int
put_status(char *s)
{
int l = strlen(s);
if (status_len + l >= SNDSTAT_BUF_SIZE)
return 0;
bcopy(s, &status_buf[status_len], l);
status_len += l;
return 1;
}
/*
* in principle, we never overflow the buffer. But... if radix=2 ...
* and if smaller... lr970711
*/
static int
put_status_int(u_int val, int radix)
{
int l, v;
static char hx[] = "0123456789abcdef";
char buf[33]; /* int is 32 bit+null, in base 2 */
if (radix < 2 || radix > 16) /* better than panic */
return put_status("???");
if (!val)
return put_status("0");
l = 0;
buf[10] = 0;
while (val) {
v = val % radix;
val = val / radix;
buf[9 - l] = hx[v];
l++;
}
if (status_len + l >= SNDSTAT_BUF_SIZE)
return 0;
bcopy(&buf[10 - l], &status_buf[status_len], l);
status_len += l;
return 1;
}
static void
init_status(void)
{
/*
* Write the status information to the status_buf and update
* status_len. There is a limit of SNDSTAT_BUF_SIZE bytes for the data.
* put_status handles this and returns 0 in case of failure. Since
* it never oveflows the buffer, we do not care to check.
*/
int i;
status_ptr = 0;
#ifdef SOUND_UNAME_A
put_status("VoxWare Sound Driver:" SOUND_VERSION_STRING
" (" SOUND_CONFIG_DATE " " SOUND_CONFIG_BY ",\n"
SOUND_UNAME_A ")\n");
#else
put_status("VoxWare Sound Driver:" SOUND_VERSION_STRING
" (" SOUND_CONFIG_DATE " " SOUND_CONFIG_BY "@"
SOUND_CONFIG_HOST "." SOUND_CONFIG_DOMAIN ")\n");
#endif
put_status("Config options: ") ;
/* put_status_int(SELECTED_SOUND_OPTIONS, 16) ; */
put_status("\n\nInstalled drivers: \n") ;
for (i = 0; i < num_sound_drivers; i++)
if (sound_drivers[i].card_type != 0) {
put_status("Type ") ;
put_status_int(sound_drivers[i].card_type, 10);
put_status(": ") ;
put_status(sound_drivers[i].name) ;
put_status("\n") ;
}
put_status("\n\nCard config: \n") ;
for (i = 0; i < num_sound_cards; i++)
if (snd_installed_cards[i].card_type != 0) {
int drv, tmp;
if (!snd_installed_cards[i].enabled)
put_status("(") ;
if ((drv = snd_find_driver(snd_installed_cards[i].card_type)) != -1)
put_status(sound_drivers[drv].name) ;
put_status(" at 0x") ;
put_status_int(snd_installed_cards[i].config.io_base, 16);
put_status(" irq ") ;
tmp = snd_installed_cards[i].config.irq;
if (tmp < 0)
tmp = -tmp;
put_status_int(tmp, 10) ;
if (snd_installed_cards[i].config.dma != -1) {
put_status(" drq ") ;
put_status_int(snd_installed_cards[i].config.dma, 10) ;
if (snd_installed_cards[i].config.dma2 != -1) {
put_status(",") ;
put_status_int(snd_installed_cards[i].config.dma2, 10) ;
}
}
if (!snd_installed_cards[i].enabled)
put_status(")") ;
put_status("\n") ;
}
if (!sound_started) {
put_status("\n\n***** Sound driver not started *****\n\n");
return;
}
#ifndef CONFIG_AUDIO
put_status("\nAudio devices: NOT ENABLED IN CONFIG\n") ;
#else
put_status("\nAudio devices:\n") ;
for (i = 0; i < num_audiodevs; i++) {
put_status_int(i, 10) ;
put_status(": ") ;
put_status(audio_devs[i]->name) ;
if (audio_devs[i]->flags & DMA_DUPLEX)
put_status(" (DUPLEX)") ;
put_status("\n") ;
}
#endif
#ifndef CONFIG_SEQUENCER
put_status("\nSynth devices: NOT ENABLED IN CONFIG\n");
#else
put_status("\nSynth devices:\n") ;
for (i = 0; i < num_synths; i++) {
put_status_int(i, 10) ;
put_status(": ") ;
put_status(synth_devs[i]->info->name) ;
put_status("\n") ;
}
#endif
#ifndef CONFIG_MIDI
put_status("\nMidi devices: NOT ENABLED IN CONFIG\n") ;
#else
put_status("\nMidi devices:\n") ;
for (i = 0; i < num_midis; i++) {
put_status_int(i, 10) ;
put_status(": ") ;
put_status(midi_devs[i]->info.name) ;
put_status("\n") ;
}
#endif
put_status("\nTimers:\n");
for (i = 0; i < num_sound_timers; i++) {
put_status_int(i, 10);
put_status(": ");
put_status(sound_timer_devs[i]->info.name);
put_status("\n");
}
put_status("\nMixers:\n");
for (i = 0; i < num_mixers; i++) {
put_status_int(i, 10);
put_status(": ");
put_status(mixer_devs[i]->name);
put_status("\n");
}
}
static int
read_status(snd_rw_buf * buf, int count)
{
/*
* Return at most 'count' bytes from the status_buf.
*/
int l, c;
l = count;
c = status_len - status_ptr;
if (l > c)
l = c;
if (l <= 0)
return 0;
if (uiomove(&status_buf[status_ptr], l, buf)) {
printf("sb: Bad copyout()!\n");
};
status_ptr += l;
return l;
}
int
sound_read_sw(int dev, struct fileinfo * file, snd_rw_buf * buf, int count)
{
DEB(printf("sound_read_sw(dev=%d, count=%d)\n", dev, count));
switch (dev & 0x0f) {
case SND_DEV_STATUS:
return read_status(buf, count);
break;
#ifdef CONFIG_AUDIO
case SND_DEV_DSP:
case SND_DEV_DSP16:
case SND_DEV_AUDIO:
return audio_read(dev, file, buf, count);
break;
#endif
#ifdef CONFIG_SEQUENCER
case SND_DEV_SEQ:
case SND_DEV_SEQ2:
return sequencer_read(dev, file, buf, count);
break;
#endif
#ifdef CONFIG_MIDI
case SND_DEV_MIDIN:
return MIDIbuf_read(dev, file, buf, count);
#endif
default:
printf("Sound: Undefined minor device %d\n", dev);
}
return -(EPERM);
}
int
sound_write_sw(int dev, struct fileinfo * file, snd_rw_buf * buf, int count)
{
DEB(printf("sound_write_sw(dev=%d, count=%d)\n", dev, count));
switch (dev & 0x0f) {
#ifdef CONFIG_SEQUENCER
case SND_DEV_SEQ:
case SND_DEV_SEQ2:
return sequencer_write(dev, file, buf, count);
break;
#endif
#ifdef CONFIG_AUDIO
case SND_DEV_DSP:
case SND_DEV_DSP16:
case SND_DEV_AUDIO:
return audio_write(dev, file, buf, count);
break;
#endif
#ifdef CONFIG_MIDI
case SND_DEV_MIDIN:
return MIDIbuf_write(dev, file, buf, count);
#endif
default:
return -(EPERM);
}
return count;
}
int
sound_open_sw(int dev, struct fileinfo * file)
{
int retval;
DEB(printf("sound_open_sw(dev=%d)\n", dev));
if ((dev >= SND_NDEVS) || (dev < 0)) {
printf("Invalid minor device %d\n", dev);
return -(ENXIO);
}
switch (dev & 0x0f) {
case SND_DEV_STATUS:
if (status_busy)
return -(EBUSY);
status_busy = 1;
if ((status_buf = (char *) malloc(SNDSTAT_BUF_SIZE, M_TEMP, M_WAITOK)) == NULL)
return -(EIO);
status_len = status_ptr = 0;
init_status();
break;
case SND_DEV_CTL:
return 0;
break;
#ifdef CONFIG_SEQUENCER
case SND_DEV_SEQ:
case SND_DEV_SEQ2:
if ((retval = sequencer_open(dev, file)) < 0)
return retval;
break;
#endif
#ifdef CONFIG_MIDI
case SND_DEV_MIDIN:
if ((retval = MIDIbuf_open(dev, file)) < 0)
return retval;
break;
#endif
#ifdef CONFIG_AUDIO
case SND_DEV_DSP:
case SND_DEV_DSP16:
case SND_DEV_AUDIO:
if ((retval = audio_open(dev, file)) < 0)
return retval;
break;
#endif
default:
printf("Invalid minor device %d\n", dev);
return -(ENXIO);
}
return 0;
}
void
sound_release_sw(int dev, struct fileinfo * file)
{
DEB(printf("sound_release_sw(dev=%d)\n", dev));
switch (dev & 0x0f) {
case SND_DEV_STATUS:
if (status_buf)
free(status_buf, M_TEMP);
status_buf = NULL;
status_busy = 0;
break;
case SND_DEV_CTL:
break;
#ifdef CONFIG_SEQUENCER
case SND_DEV_SEQ:
case SND_DEV_SEQ2:
sequencer_release(dev, file);
break;
#endif
#ifdef CONFIG_MIDI
case SND_DEV_MIDIN:
MIDIbuf_release(dev, file);
break;
#endif
#ifdef CONFIG_AUDIO
case SND_DEV_DSP:
case SND_DEV_DSP16:
case SND_DEV_AUDIO:
audio_release(dev, file);
break;
#endif
default:
printf("Sound error: Releasing unknown device 0x%02x\n", dev);
}
}
int
sound_ioctl_sw(int dev, struct fileinfo * file, u_int cmd, ioctl_arg arg)
{
DEB(printf("sound_ioctl_sw(dev=%d, cmd=0x%x, arg=0x%x)\n", dev, cmd, arg));
if (((cmd >> 8) & 0xff) == 'M' && num_mixers > 0) /* Mixer ioctl */
if ((dev & 0x0f) != SND_DEV_CTL) {
int dtype = dev & 0x0f;
int mixdev;
switch (dtype) {
#ifdef CONFIG_AUDIO
case SND_DEV_DSP:
case SND_DEV_DSP16:
case SND_DEV_AUDIO:
mixdev = audio_devs[dev >> 4]->mixer_dev;
if (mixdev < 0 || mixdev >= num_mixers)
return -(ENXIO);
return mixer_devs[mixdev]->ioctl(mixdev, cmd, arg);
break;
#endif
default:
return mixer_devs[0]->ioctl(0, cmd, arg);
}
}
switch (dev & 0x0f) {
case SND_DEV_CTL:
if (!num_mixers)
return -(ENXIO);
dev = dev >> 4;
if (dev >= num_mixers)
return -(ENXIO);
return mixer_devs[dev]->ioctl(dev, cmd, arg);
break;
#ifdef CONFIG_SEQUENCER
case SND_DEV_SEQ:
case SND_DEV_SEQ2:
return sequencer_ioctl(dev, file, cmd, arg);
break;
#endif
#ifdef CONFIG_AUDIO
case SND_DEV_DSP:
case SND_DEV_DSP16:
case SND_DEV_AUDIO:
return audio_ioctl(dev, file, cmd, arg);
break;
#endif
#ifdef CONFIG_MIDI
case SND_DEV_MIDIN:
return MIDIbuf_ioctl(dev, file, cmd, arg);
break;
#endif
default:
return -(EPERM);
break;
}
return -(EPERM);
}
#endif

View File

@ -1,344 +0,0 @@
/*
* sound/sound_timer.c
*
* Copyright by Hannu Savolainen 1993
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. 2.
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#define SEQUENCER_C
#include <i386/isa/sound/sound_config.h>
#if NSND > 0
#if defined(CONFIG_SEQUENCER)
static volatile int initialized = 0, opened = 0, tmr_running = 0;
static volatile time_t tmr_offs, tmr_ctr;
static volatile u_long ticks_offs;
static volatile int curr_tempo, curr_timebase;
static volatile u_long curr_ticks;
static volatile u_long next_event_time;
static u_long prev_event_time;
static volatile u_long usecs_per_tmr; /* Length of the current interval */
static struct sound_lowlev_timer *tmr = NULL;
static u_long
tmr2ticks(int tmr_value)
{
/*
* Convert timer ticks to MIDI ticks
*/
u_long tmp;
u_long scale;
tmp = tmr_value * usecs_per_tmr; /* Convert to usecs */
scale = (60 * 1000000) / (curr_tempo * curr_timebase); /* usecs per MIDI tick */
return (tmp + (scale / 2)) / scale;
}
static void
reprogram_timer(void)
{
u_long usecs_per_tick;
usecs_per_tick = (60 * 1000000) / (curr_tempo * curr_timebase);
/*
* Don't kill the system by setting too high timer rate
*/
if (usecs_per_tick < 2000)
usecs_per_tick = 2000;
usecs_per_tmr = tmr->tmr_start(tmr->dev, usecs_per_tick);
}
void
sound_timer_syncinterval(u_int new_usecs)
{
/*
* This routine is called by the hardware level if the clock
* frequency has changed for some reason.
*/
tmr_offs = tmr_ctr;
ticks_offs += tmr2ticks(tmr_ctr);
tmr_ctr = 0;
usecs_per_tmr = new_usecs;
}
static void
tmr_reset(void)
{
u_long flags;
flags = splhigh();
tmr_offs = 0;
ticks_offs = 0;
tmr_ctr = 0;
next_event_time = 0xffffffff;
prev_event_time = 0;
curr_ticks = 0;
splx(flags);
}
static int
timer_open(int dev, int mode)
{
if (opened)
return -(EBUSY);
tmr_reset();
curr_tempo = 60;
curr_timebase = hz;
opened = 1;
reprogram_timer();
return 0;
}
static void
timer_close(int dev)
{
opened = tmr_running = 0;
tmr->tmr_disable(tmr->dev);
}
static int
timer_event(int dev, u_char *event)
{
u_char cmd = event[1];
u_long parm = *(int *) &event[4];
switch (cmd) {
case TMR_WAIT_REL:
parm += prev_event_time;
case TMR_WAIT_ABS:
if (parm > 0) {
long time;
if (parm <= curr_ticks) /* It's the time */
return TIMER_NOT_ARMED;
time = parm;
next_event_time = prev_event_time = time;
return TIMER_ARMED;
}
break;
case TMR_START:
tmr_reset();
tmr_running = 1;
reprogram_timer();
break;
case TMR_STOP:
tmr_running = 0;
break;
case TMR_CONTINUE:
tmr_running = 1;
reprogram_timer();
break;
case TMR_TEMPO:
if (parm) {
if (parm < 8)
parm = 8;
if (parm > 250)
parm = 250;
tmr_offs = tmr_ctr;
ticks_offs += tmr2ticks(tmr_ctr);
tmr_ctr = 0;
curr_tempo = parm;
reprogram_timer();
}
break;
case TMR_ECHO:
seq_copy_to_input(event, 8);
break;
default:;
}
return TIMER_NOT_ARMED;
}
static u_long
timer_get_time(int dev)
{
if (!opened)
return 0;
return curr_ticks;
}
static int
timer_ioctl(int dev, u_int cmd, ioctl_arg arg)
{
switch (cmd) {
case SNDCTL_TMR_SOURCE:
return *(int *) arg = TMR_INTERNAL;
break;
case SNDCTL_TMR_START:
tmr_reset();
tmr_running = 1;
return 0;
break;
case SNDCTL_TMR_STOP:
tmr_running = 0;
return 0;
break;
case SNDCTL_TMR_CONTINUE:
tmr_running = 1;
return 0;
break;
case SNDCTL_TMR_TIMEBASE:
{
int val = (*(int *) arg);
if (val) {
if (val < 1)
val = 1;
if (val > 1000)
val = 1000;
curr_timebase = val;
}
return *(int *) arg = curr_timebase;
}
break;
case SNDCTL_TMR_TEMPO:
{
int val = (*(int *) arg);
if (val) {
if (val < 8)
val = 8;
if (val > 250)
val = 250;
tmr_offs = tmr_ctr;
ticks_offs += tmr2ticks(tmr_ctr);
tmr_ctr = 0;
curr_tempo = val;
reprogram_timer();
}
return *(int *) arg = curr_tempo;
}
break;
case SNDCTL_SEQ_CTRLRATE:
if ((*(int *) arg) != 0) /* Can't change */
return -(EINVAL);
return *(int *) arg = ((curr_tempo * curr_timebase) + 30) / 60;
break;
case SNDCTL_TMR_METRONOME:
/* NOP */
break;
default:;
}
return -(EINVAL);
}
static void
timer_arm(int dev, long time)
{
if (time < 0)
time = curr_ticks + 1;
else if (time <= curr_ticks) /* It's the time */
return;
next_event_time = prev_event_time = time;
return;
}
static struct sound_timer_operations sound_timer =
{
{"GUS Timer", 0},
1, /* Priority */
0, /* Local device link */
timer_open,
timer_close,
timer_event,
timer_get_time,
timer_ioctl,
timer_arm
};
void
sound_timer_interrupt(void)
{
if (!opened)
return;
tmr->tmr_restart(tmr->dev);
if (!tmr_running)
return;
tmr_ctr++;
curr_ticks = ticks_offs + tmr2ticks(tmr_ctr);
if (curr_ticks >= next_event_time) {
next_event_time = 0xffffffff;
sequencer_timer(0);
}
}
void
sound_timer_init(struct sound_lowlev_timer * t, char *name)
{
int n;
if (initialized || t == NULL)
return; /* There is already a similar timer */
initialized = 1;
tmr = t;
if (num_sound_timers >= MAX_TIMER_DEV)
n = 0; /* Overwrite the system timer */
else
n = num_sound_timers++;
snprintf(sound_timer.info.name, sizeof(sound_timer.info.name), "%s", name);
sound_timer_devs[n] = &sound_timer;
}
#endif
#endif

View File

@ -1,684 +0,0 @@
/*
* sound/386bsd/soundcard.c
*
* Soundcard driver for 386BSD.
*
* Copyright by Hannu Savolainen 1993
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. 2.
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* 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 "opt_devfs.h"
#include <i386/isa/sound/sound_config.h>
#ifdef DEVFS
#include <sys/devfsext.h>
#endif /* DEVFS */
#if NSND > 0 /* from "snd.h" */
#include "uart.h"
#include <vm/vm.h>
#include <vm/pmap.h>
#include <sys/mman.h>
#include <i386/isa/isa_device.h>
/*
** Register definitions for DMA controller 1 (channels 0..3):
*/
#define DMA1_CHN(c) (IO_DMA1 + 1*(2*(c))) /* addr reg for channel c */
#define DMA1_SMSK (IO_DMA1 + 1*10) /* single mask register */
#define DMA1_MODE (IO_DMA1 + 1*11) /* mode register */
#define DMA1_FFC (IO_DMA1 + 1*12) /* clear first/last FF */
/*
** Register definitions for DMA controller 2 (channels 4..7):
*/
#define DMA2_CHN(c) (IO_DMA2 + 2*(2*(c))) /* addr reg for channel c */
#define DMA2_SMSK (IO_DMA2 + 2*10) /* single mask register */
#define DMA2_MODE (IO_DMA2 + 2*11) /* mode register */
#define DMA2_FFC (IO_DMA2 + 2*12) /* clear first/last FF */
#define FIX_RETURN(ret) {if ((ret)<0) return -(ret); else return 0;}
static int soundcards_installed = 0; /* Number of installed soundcards */
static int soundcard_configured = 0;
static struct fileinfo files[SND_NDEVS];
struct selinfo selinfo[SND_NDEVS >> 4];
int
MIDIbuf_poll (int dev, struct fileinfo *file, int events, select_table * wait);
int
audio_poll(int dev, struct fileinfo * file, int events, select_table * wait);
int
sequencer_poll (int dev, struct fileinfo *file, int events, select_table * wait);
static int sndprobe __P((struct isa_device *));
static int sndattach __P((struct isa_device *));
static int sndmmap __P((dev_t dev, int offset, int nprot ));
static d_open_t sndopen;
static d_close_t sndclose;
static d_ioctl_t sndioctl;
static d_read_t sndread;
static d_write_t sndwrite;
static d_poll_t sndpoll;
static char driver_name[] = "snd";
#define CDEV_MAJOR 30
static struct cdevsw snd_cdevsw = {
sndopen, sndclose, sndread, sndwrite,
sndioctl, nostop, noreset, nodevtotty,
sndpoll, sndmmap, nostrategy, driver_name,
NULL, -1,
};
static void sound_mem_init(void);
/*
* for each "device XXX" entry in the config file, we have
* a struct isa_driver which is linked into isa_devtab_null[]
*
* XXX It is a bit stupid to call the generic routine so many times and
* switch then to the specific one, but the alternative way would be
* to replicate some code in the probe/attach routines.
*/
struct isa_driver opldriver = {sndprobe, sndattach, "opl"};
struct isa_driver trixdriver = {sndprobe, sndattach, "trix"};
struct isa_driver trixsbdriver = {sndprobe, sndattach, "trixsb"};
struct isa_driver sbdriver = {sndprobe, sndattach, "sb"};
struct isa_driver sbxvidriver = {sndprobe, sndattach, "sbxvi"};
struct isa_driver sbmididriver = {sndprobe, sndattach, "sbmidi"};
struct isa_driver awedriver = {sndprobe, sndattach, "awe"};
struct isa_driver pasdriver = {sndprobe, sndattach, "pas"};
struct isa_driver mpudriver = {sndprobe, sndattach, "mpu"};
struct isa_driver gusdriver = {sndprobe, sndattach, "gus"};
struct isa_driver gusxvidriver = {sndprobe, sndattach, "gusxvi"};
struct isa_driver gusmaxdriver = {sndprobe, sndattach, "gusmax"};
struct isa_driver uartdriver = {sndprobe, sndattach, "uart"};
struct isa_driver mssdriver = {sndprobe, sndattach, "mss"};
struct isa_driver cssdriver = {sndprobe, sndattach, "css"};
struct isa_driver sscapedriver = {sndprobe, sndattach, "sscape"};
struct isa_driver sscape_mssdriver = {sndprobe, sndattach, "sscape_mss"};
short ipri_to_irq(u_short ipri);
static ointhand2_t sndintr;
u_long
get_time(void)
{
struct timeval timecopy;
getmicrotime(&timecopy);
return timecopy.tv_usec / (1000000 / hz) +
(u_long) timecopy.tv_sec * hz;
}
static int
sndmmap( dev_t dev, int offset, int nprot )
{
struct dma_buffparms * dmap;
dev = minor(dev) >> 4;
if (dev > 0 ) return (-1);
dmap = audio_devs[dev]->dmap_out;
if (nprot & PROT_EXEC)
return( -1 );
dmap->mapping_flags |= DMA_MAP_MAPPED ;
return( i386_btop(vtophys(dmap->raw_buf) + offset) );
}
static int
sndread(dev_t dev, struct uio * buf, int flag)
{
int count = buf->uio_resid;
dev = minor(dev);
FIX_RETURN(sound_read_sw(dev, &files[dev], buf, count));
}
static int
sndwrite(dev_t dev, struct uio * buf, int flag)
{
int count = buf->uio_resid;
dev = minor(dev);
FIX_RETURN(sound_write_sw(dev, &files[dev], buf, count));
}
static int
sndopen(dev_t dev, int flags, int mode, struct proc * p)
{
int retval;
struct fileinfo tmp_file;
dev = minor(dev);
if (!soundcard_configured && dev) {
printf("SoundCard Error: soundcard system has not been configured\n");
return ENODEV ;
}
tmp_file.mode = 0;
if (flags & FREAD && flags & FWRITE)
tmp_file.mode = OPEN_READWRITE;
else if (flags & FREAD)
tmp_file.mode = OPEN_READ;
else if (flags & FWRITE)
tmp_file.mode = OPEN_WRITE;
selinfo[dev >> 4].si_pid = 0;
selinfo[dev >> 4].si_flags = 0;
if ((retval = sound_open_sw(dev, &tmp_file)) < 0)
FIX_RETURN(retval);
bcopy((char *) &tmp_file, (char *) &files[dev], sizeof(tmp_file));
FIX_RETURN(retval);
}
static int
sndclose(dev_t dev, int flags, int mode, struct proc * p)
{
dev = minor(dev);
sound_release_sw(dev, &files[dev]);
return 0 ;
}
static int
sndioctl(dev_t dev, u_long cmd, caddr_t arg, int mode, struct proc * p)
{
dev = minor(dev);
FIX_RETURN(sound_ioctl_sw(dev, &files[dev], cmd, arg));
}
int
sndpoll(dev_t dev, int events, struct proc * p)
{
dev = minor(dev);
dev = minor(dev);
/* printf ("snd_select(dev=%d, rw=%d, pid=%d)\n", dev, rw, p->p_pid); */
#ifdef ALLOW_POLL
switch (dev & 0x0f) {
#ifdef CONFIG_SEQUENCER
case SND_DEV_SEQ:
case SND_DEV_SEQ2:
return sequencer_poll(dev, &files[dev], events, p);
break;
#endif
#ifdef CONFIG_MIDI
case SND_DEV_MIDIN:
return MIDIbuf_poll(dev, &files[dev], events, p);
break;
#endif
#ifdef CONFIG_AUDIO
case SND_DEV_DSP:
case SND_DEV_DSP16:
case SND_DEV_AUDIO:
return audio_poll(dev, &files[dev], events, p);
break;
#endif
default:
return 0;
}
#endif /* ALLOW_POLL */
DEB(printf("sound_ioctl(dev=%d, cmd=0x%x, arg=0x%x)\n", dev, cmd, arg));
return 0 ;
}
/* XXX this should become ffs(ipri), perhaps -1 lr 970705 */
short
ipri_to_irq(u_short ipri)
{
/*
* Converts the ipri (bitmask) to the corresponding irq number
*/
int irq;
for (irq = 0; irq < 16; irq++)
if (ipri == (1 << irq))
return irq;
return -1; /* Invalid argument */
}
static int
driver_to_voxunit(struct isa_driver * driver)
{
/*
* converts a sound driver pointer into the equivalent VoxWare device
* unit number
*/
if (driver == &opldriver)
return (SNDCARD_ADLIB);
else if (driver == &sbdriver)
return (SNDCARD_SB);
else if (driver == &pasdriver)
return (SNDCARD_PAS);
else if (driver == &gusdriver)
return (SNDCARD_GUS);
else if (driver == &mpudriver)
return (SNDCARD_MPU401);
else if (driver == &sbxvidriver)
return (SNDCARD_SB16);
else if (driver == &sbmididriver)
return (SNDCARD_SB16MIDI);
else if(driver == &awedriver)
return(SNDCARD_AWE32);
else if (driver == &uartdriver)
return (SNDCARD_UART6850);
else if (driver == &gusdriver)
return (SNDCARD_GUS16);
else if (driver == &mssdriver)
return (SNDCARD_MSS);
else if (driver == &cssdriver)
return (SNDCARD_CS4232);
else if (driver == &sscapedriver)
return(SNDCARD_SSCAPE);
else if (driver == &sscape_mssdriver)
return(SNDCARD_SSCAPE_MSS);
else if (driver == &trixdriver)
return (SNDCARD_TRXPRO);
else if (driver == &trixsbdriver)
return (SNDCARD_TRXPRO_SB);
else
return (0);
}
/*
* very dirty: tmp_osp is allocated in sndprobe, and used at the next
* call in sndattach
*/
static sound_os_info *temp_osp;
/*
* sndprobe is called for each isa_device. From here, a voxware unit
* number is determined, and the appropriate probe routine is selected.
* The parameters from the config line are passed to the hw_config struct.
*/
static int
sndprobe(struct isa_device * dev)
{
struct address_info hw_config;
int unit;
temp_osp = (sound_os_info *)malloc(sizeof(sound_os_info),
M_DEVBUF, M_NOWAIT);
if (!temp_osp)
panic("SOUND: Cannot allocate memory\n");
/*
* get config info from the kernel config. These may be overridden
* by the local autoconfiguration routines though (e.g. pnp stuff).
*/
hw_config.io_base = dev->id_iobase;
hw_config.irq = ipri_to_irq(dev->id_irq);
hw_config.dma = dev->id_drq;
/*
* misuse the flags field for read dma. Note that, to use 0 as
* read dma channel, one of the high bits should be set. lr970705 XXX
*/
if (dev->id_flags != 0)
hw_config.dma2 = dev->id_flags & 0x7;
else
hw_config.dma2 = -1;
hw_config.always_detect = 0;
hw_config.name = NULL;
hw_config.card_subtype = 0;
temp_osp->unit = dev->id_unit;
hw_config.osp = temp_osp;
unit = driver_to_voxunit(dev->id_driver);
if (sndtable_probe(unit, &hw_config)) {
dev->id_iobase = hw_config.io_base;
dev->id_irq = hw_config.irq == -1 ? 0 : (1 << hw_config.irq);
dev->id_drq = hw_config.dma;
if (hw_config.dma != hw_config.dma2 && ( hw_config.dma2 != -1))
dev->id_flags = hw_config.dma2 | 0x100; /* XXX lr */
else
dev->id_flags = 0;
return TRUE;
}
return 0;
}
static int
sndattach(struct isa_device * dev)
{
int unit;
static int midi_initialized = 0;
static int seq_initialized = 0;
struct address_info hw_config;
char *dname;
void *tmp;
/*
* Associate interrupt handlers with devices. XXX this may be incomplete.
*/
dname = dev->id_driver->name;
#if defined(CONFIG_AD1848)
if (strcmp(dname, "css") == 0 || strcmp(dname, "gusxvi") == 0 ||
strcmp(dname, "mss") == 0)
dev->id_ointr = adintr;
#endif
#ifdef CONFIG_GUS
if (strcmp(dname, "gus") == 0)
dev->id_ointr = gusintr;
#endif
#ifdef CONFIG_PAS
if (strcmp(dname, "pas") == 0)
dev->id_ointr = pasintr;
#endif
#if NSB > 0 && (defined(CONFIG_MIDI) || defined(CONFIG_AUDIO))
if (strcmp(dname, "sb") == 0)
dev->id_ointr = sbintr;
#endif
if (strcmp(dname, "sscape_mss") == 0)
dev->id_ointr = sndintr;
#if NSSCAPE > 0
if (strcmp(dname, "sscape") == 0 || strcmp(dname, "trix") == 0)
dev->id_ointr = sscapeintr;
#endif
#if NUART > 0
if (strcmp(dname, "uart0") == 0)
dev->id_ointr = m6850intr;
#endif
unit = driver_to_voxunit(dev->id_driver);
hw_config.io_base = dev->id_iobase;
hw_config.irq = ipri_to_irq(dev->id_irq);
hw_config.dma = dev->id_drq;
/* misuse the flags field for read dma */
if (dev->id_flags != 0)
hw_config.dma2 = dev->id_flags & 0x7;
else
hw_config.dma2 = -1;
hw_config.card_subtype = 0;
hw_config.osp = temp_osp;
if (!unit)
return FALSE;
if (!(sndtable_init_card(unit, &hw_config))) { /* init card */
printf(" <Driver not configured>");
return FALSE;
}
/*
* Init the high level sound driver
*/
if (!(soundcards_installed = sndtable_get_cardcount())) {
DDB(printf("No drivers actually installed\n"));
return FALSE; /* No cards detected */
}
printf("\n");
#ifdef CONFIG_AUDIO
if (num_audiodevs) { /* Audio devices present */
DMAbuf_init();
sound_mem_init();
}
soundcard_configured = 1;
#endif
if (num_midis && !midi_initialized)
midi_initialized = 1;
if ((num_midis + num_synths) && !seq_initialized) {
seq_initialized = 1;
sequencer_init();
}
{
dev_t dev;
dev = makedev(CDEV_MAJOR, 0);
cdevsw_add(&dev, &snd_cdevsw, NULL);
}
#ifdef DEVFS
#define GID_SND GID_GAMES
#define UID_SND UID_ROOT
#define PERM_SND 0660
/*
* make links to first successfully probed device, don't do it if
* duplicate creation of same node failed (ie. bad cookie returned)
*/
if (dev->id_driver == &opldriver){
tmp = devfs_add_devswf(&snd_cdevsw, (dev->id_unit << 4) | SND_DEV_SEQ,
DV_CHR, UID_SND, GID_SND, PERM_SND,
"sequencer%r", dev->id_unit);
if (tmp) devfs_makelink(tmp, "sequencer");
} else if (dev->id_driver == &mpudriver ||
dev->id_driver == &sbmididriver ||
dev->id_driver == &uartdriver){
tmp = devfs_add_devswf(&snd_cdevsw, (dev->id_unit << 4) | SND_DEV_MIDIN,
DV_CHR, UID_SND, GID_SND, PERM_SND,
"midi%r", dev->id_unit);
if (tmp) devfs_makelink(tmp, "midi");
} else {
tmp = devfs_add_devswf(&snd_cdevsw, (dev->id_unit << 4) | SND_DEV_DSP,
DV_CHR, UID_SND, GID_SND, PERM_SND,
"dsp%r", dev->id_unit);
if (tmp) devfs_makelink(tmp, "dsp");
tmp = devfs_add_devswf(&snd_cdevsw, (dev->id_unit << 4) | SND_DEV_DSP16,
DV_CHR, UID_SND, GID_SND, PERM_SND,
"dspW%r", dev->id_unit);
if (tmp) devfs_makelink(tmp, "dspW");
tmp = devfs_add_devswf(&snd_cdevsw, (dev->id_unit << 4) | SND_DEV_AUDIO,
DV_CHR, UID_SND, GID_SND, PERM_SND,
"audio%r", dev->id_unit);
if (tmp) devfs_makelink(tmp, "audio");
tmp = devfs_add_devswf(&snd_cdevsw, (dev->id_unit << 4) | SND_DEV_CTL,
DV_CHR, UID_SND, GID_SND, PERM_SND,
"mixer%r", dev->id_unit);
if (tmp) devfs_makelink(tmp, "mixer");
tmp = devfs_add_devswf(&snd_cdevsw, (dev->id_unit << 4) | SND_DEV_STATUS,
DV_CHR, UID_SND, GID_SND, PERM_SND,
"sndstat%r", dev->id_unit);
if (tmp) devfs_makelink(tmp, "sndstat");
}
#endif /* DEVFS */
return TRUE;
}
#ifdef CONFIG_AUDIO
static void
alloc_dmap(int dev, int chan, struct dma_buffparms * dmap)
{
char *tmpbuf;
int i;
tmpbuf = contigmalloc(audio_devs[dev]->buffsize, M_DEVBUF, M_NOWAIT,
0ul, 0xfffffful, 1ul, chan & 4 ? 0x20000ul : 0x10000ul);
if (tmpbuf == NULL)
printf("soundcard buffer alloc failed \n");
if (tmpbuf == NULL) {
printf("snd: Unable to allocate %d bytes of buffer\n",
2 * (int) audio_devs[dev]->buffsize);
return;
}
dmap->raw_buf = tmpbuf;
/*
* Use virtual address as the physical address, since isa_dmastart
* performs the phys address computation.
*/
dmap->raw_buf_phys = (uintptr_t) tmpbuf;
for (i = 0; i < audio_devs[dev]->buffsize; i++) *tmpbuf++ = 0x80;
}
static void
sound_mem_init(void)
{
int dev;
static u_long dsp_init_mask = 0;
for (dev = 0; dev < num_audiodevs; dev++) /* Enumerate devices */
if (!(dsp_init_mask & (1 << dev))) /* Not already done */
if (audio_devs[dev]->dmachan1 >= 0) {
dsp_init_mask |= (1 << dev);
audio_devs[dev]->buffsize = DSP_BUFFSIZE;
/* Now allocate the buffers */
alloc_dmap(dev, audio_devs[dev]->dmachan1,
audio_devs[dev]->dmap_out);
if (audio_devs[dev]->flags & DMA_DUPLEX)
alloc_dmap(dev, audio_devs[dev]->dmachan2,
audio_devs[dev]->dmap_in);
} /* for dev */
}
#endif
int
snd_ioctl_return(int *addr, int value)
{
if (value < 0)
return value; /* Error */
suword(addr, value);
return 0;
}
#define MAX_UNIT 50
typedef void (*irq_proc_t) (int irq);
static irq_proc_t irq_proc[MAX_UNIT] = {NULL};
static int irq_irq[MAX_UNIT] = {0};
int
snd_set_irq_handler(int int_lvl, void (*hndlr) (int), sound_os_info * osp)
{
if (osp->unit >= MAX_UNIT) {
printf("Sound error: Unit number too high (%d)\n", osp->unit);
return 0;
}
irq_proc[osp->unit] = hndlr;
irq_irq[osp->unit] = int_lvl;
return 1;
}
static void
sndintr(int unit)
{
if ( (unit >= MAX_UNIT) || (irq_proc[unit] == NULL) )
return;
irq_proc[unit] (irq_irq[unit]); /* Call the installed handler */
}
void
conf_printf(char *name, struct address_info * hw_config)
{
if (!trace_init)
return;
printf("snd0: <%s> ", name);
#if 0
if (hw_config->io_base != -1 )
printf("at 0x%03x", hw_config->io_base);
if (hw_config->irq != -1 )
printf(" irq %d", hw_config->irq);
if (hw_config->dma != -1 || hw_config->dma2 != -1) {
printf(" dma %d", hw_config->dma);
if (hw_config->dma2 != -1)
printf(",%d", hw_config->dma2);
}
#endif
}
void
conf_printf2(char *name, int base, int irq, int dma, int dma2)
{
if (!trace_init)
return;
printf("snd0: <%s> ", name);
#if 0
if (hw_config->io_base != -1 )
printf("at 0x%03x", hw_config->io_base);
if (irq)
printf(" irq %d", irq);
if (dma != -1 || dma2 != -1) {
printf(" dma %d", dma);
if (dma2 != -1)
printf(",%d", dma2);
}
#endif
}
void tenmicrosec (int j)
{
int i, k;
for (k = 0; k < j/10 ; k++) {
for (i = 0; i < 16; i++)
inb (0x80);
}
}
#endif /* NSND > 0 */

View File

@ -1,2 +0,0 @@
#define SOUND_VERSION_STRING "3.5-alpha15-970902"
#define SOUND_INTERNAL_VERSION 0x030518

File diff suppressed because it is too large Load Diff

View File

@ -1,276 +0,0 @@
/*
* sound/sys_timer.c
*
* The default timer for the Level 2 sequencer interface.
* Uses the (100hz) timer of kernel.
*
* Copyright by Hannu Savolainen 1993
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
* 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.
*
*/
#define SEQUENCER_C
#include <i386/isa/sound/sound_config.h>
#if NSND > 0
#if defined(CONFIG_SEQUENCER)
static volatile int opened = 0, tmr_running = 0;
static volatile time_t tmr_offs, tmr_ctr;
static volatile u_long ticks_offs;
static volatile int curr_tempo, curr_timebase;
static volatile u_long curr_ticks;
static volatile u_long next_event_time;
static u_long prev_event_time;
static void poll_def_tmr(void *dummy);
static u_long
tmr2ticks(int tmr_value)
{
/*
* Convert system timer ticks (hz) to MIDI ticks (divide # of MIDI
* ticks/minute by # of system ticks/minute).
*/
return ((tmr_value * curr_tempo * curr_timebase) + (30 * hz)) / (60 * hz);
}
static void
poll_def_tmr(void *dummy)
{
if (opened) {
timeout( poll_def_tmr, 0, 1);;
if (tmr_running) {
tmr_ctr++;
curr_ticks = ticks_offs + tmr2ticks(tmr_ctr);
if (curr_ticks >= next_event_time) {
next_event_time = 0xffffffff;
sequencer_timer(0);
}
}
}
}
static void
tmr_reset(void)
{
u_long flags;
flags = splhigh();
tmr_offs = 0;
ticks_offs = 0;
tmr_ctr = 0;
next_event_time = 0xffffffff;
prev_event_time = 0;
curr_ticks = 0;
splx(flags);
}
static int
def_tmr_open(int dev, int mode)
{
if (opened)
return -(EBUSY);
tmr_reset();
curr_tempo = 60;
curr_timebase = hz;
opened = 1;
timeout( poll_def_tmr, 0, 1);;
return 0;
}
static void
def_tmr_close(int dev)
{
opened = tmr_running = 0;
}
static int
def_tmr_event(int dev, u_char *event)
{
u_char cmd = event[1];
u_long parm = *(int *) &event[4];
switch (cmd) {
case TMR_WAIT_REL:
parm += prev_event_time;
case TMR_WAIT_ABS:
if (parm > 0) {
long time;
if (parm <= curr_ticks) /* It's the time */
return TIMER_NOT_ARMED;
time = parm;
next_event_time = prev_event_time = time;
return TIMER_ARMED;
}
break;
case TMR_START:
tmr_reset();
tmr_running = 1;
break;
case TMR_STOP:
tmr_running = 0;
break;
case TMR_CONTINUE:
tmr_running = 1;
break;
case TMR_TEMPO:
if (parm) {
RANGE (parm, 8, 360) ;
tmr_offs = tmr_ctr;
ticks_offs += tmr2ticks(tmr_ctr);
tmr_ctr = 0;
curr_tempo = parm;
}
break;
case TMR_ECHO:
seq_copy_to_input(event, 8);
break;
default:;
}
return TIMER_NOT_ARMED;
}
static u_long
def_tmr_get_time(int dev)
{
if (!opened)
return 0;
return curr_ticks;
}
static int
def_tmr_ioctl(int dev, u_int cmd, ioctl_arg arg)
{
switch (cmd) {
case SNDCTL_TMR_SOURCE:
return *(int *) arg = TMR_INTERNAL;
break;
case SNDCTL_TMR_START:
tmr_reset();
tmr_running = 1;
return 0;
break;
case SNDCTL_TMR_STOP:
tmr_running = 0;
return 0;
break;
case SNDCTL_TMR_CONTINUE:
tmr_running = 1;
return 0;
break;
case SNDCTL_TMR_TIMEBASE:
{
int val = (*(int *) arg);
if (val) {
RANGE (val, 1, 1000) ;
curr_timebase = val;
}
return *(int *) arg = curr_timebase;
}
break;
case SNDCTL_TMR_TEMPO:
{
int val = (*(int *) arg);
if (val) {
RANGE (val, 8, 250) ;
tmr_offs = tmr_ctr;
ticks_offs += tmr2ticks(tmr_ctr);
tmr_ctr = 0;
curr_tempo = val;
}
return *(int *) arg = curr_tempo;
}
break;
case SNDCTL_SEQ_CTRLRATE:
if ((*(int *) arg) != 0) /* Can't change */
return -(EINVAL);
return *(int *) arg = ((curr_tempo * curr_timebase) + 30) / 60;
break;
case SNDCTL_TMR_METRONOME:
/* NOP */
break;
default:;
}
return -(EINVAL);
}
static void
def_tmr_arm(int dev, long time)
{
if (time < 0)
time = curr_ticks + 1;
else if (time <= curr_ticks) /* It's the time */
return;
next_event_time = prev_event_time = time;
return;
}
struct sound_timer_operations default_sound_timer =
{
{"System clock", 0},
0, /* Priority */
0, /* Local device link */
def_tmr_open,
def_tmr_close,
def_tmr_event,
def_tmr_get_time,
def_tmr_ioctl,
def_tmr_arm
};
#endif
#endif /* NSND > 0 */

View File

@ -1,368 +0,0 @@
/*
* sound/trix.c
*
* Low level driver for the MediaTriX AudioTriX Pro (MT-0002-PC Control Chip)
*
* Copyright by Hannu Savolainen 1995
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. 2.
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#include <i386/isa/sound/sound_config.h>
#if NTRIX > 0
#ifdef INCLUDE_TRIX_BOOT
#include <i386/isa/sound/trix_boot.h>
#endif
#if (NSB > 0)
extern int sb_no_recording;
#endif
static int kilroy_was_here = 0; /* Don't detect twice */
static int sb_initialized = 0;
static sound_os_info *trix_osp = NULL;
static u_char
trix_read(int addr)
{
outb(0x390, (u_char) addr); /* MT-0002-PC ASIC address */
return inb(0x391); /* MT-0002-PC ASIC data */
}
static void
trix_write(int addr, int data)
{
outb(0x390, (u_char) addr); /* MT-0002-PC ASIC address */
outb(0x391, (u_char) data); /* MT-0002-PC ASIC data */
}
static void
download_boot(int base)
{
#ifdef INCLUDE_TRIX_BOOT
int i = 0, n = sizeof(trix_boot);
trix_write(0xf8, 0x00); /* ??????? */
outb(base + 6, 0x01); /* Clear the internal data pointer */
outb(base + 6, 0x00); /* Restart */
/*
* Write the boot code to the RAM upload/download register. Each
* write increments the internal data pointer.
*/
outb(base + 6, 0x01); /* Clear the internal data pointer */
outb(0x390, 0x1A); /* Select RAM download/upload port */
for (i = 0; i < n; i++)
outb(0x391, trix_boot[i]);
for (i = n; i < 10016; i++) /* Clear up to first 16 bytes of data RAM */
outb(0x391, 0x00);
outb(base + 6, 0x00); /* Reset */
outb(0x390, 0x50); /* ?????? */
#endif
}
static int
trix_set_wss_port(struct address_info * hw_config)
{
u_char addr_bits;
if (0) {
printf("AudioTriX: Config port I/O conflict\n");
return 0;
}
if (kilroy_was_here) /* Already initialized */
return 0;
if (trix_read(0x15) != 0x71) { /* No asic signature */
DDB(printf("No AudioTriX ASIC signature found\n"));
return 0;
}
kilroy_was_here = 1;
/*
* Reset some registers.
*/
trix_write(0x13, 0);
trix_write(0x14, 0);
/*
* Configure the ASIC to place the codec to the proper I/O location
*/
switch (hw_config->io_base) {
case 0x530:
addr_bits = 0;
break;
case 0x604:
addr_bits = 1;
break;
case 0xE80:
addr_bits = 2;
break;
case 0xF40:
addr_bits = 3;
break;
default:
return 0;
}
trix_write(0x19, (trix_read(0x19) & 0x03) | addr_bits);
return 1;
}
/*
* Probe and attach routines for the Windows Sound System mode of AudioTriX
* Pro
*/
int
probe_trix_wss(struct address_info * hw_config)
{
/*
* Check if the IO port returns valid signature. The original MS
* Sound system returns 0x04 while some cards (AudioTriX Pro for
* example) return 0x00.
*/
if (0) {
printf("AudioTriX: MSS I/O port conflict\n");
return 0;
}
trix_osp = hw_config->osp;
if (!trix_set_wss_port(hw_config))
return 0;
if ((inb(hw_config->io_base + 3) & 0x3f) != 0x00) {
DDB(printf("No MSS signature detected on port 0x%x\n",
hw_config->io_base));
return 0;
}
if (hw_config->irq > 11) {
printf("AudioTriX: Bad WSS IRQ %d\n", hw_config->irq);
return 0;
}
if (hw_config->dma != 0 && hw_config->dma != 1 && hw_config->dma != 3) {
printf("AudioTriX: Bad WSS DMA %d\n", hw_config->dma);
return 0;
}
if (hw_config->dma2 != -1)
if (hw_config->dma2 != 0 && hw_config->dma2 != 1 && hw_config->dma2 != 3) {
printf("AudioTriX: Bad capture DMA %d\n", hw_config->dma2);
return 0;
}
/*
* Check that DMA0 is not in use with a 8 bit board.
*/
if (hw_config->dma == 0 && inb(hw_config->io_base + 3) & 0x80) {
printf("AudioTriX: Can't use DMA0 with a 8 bit card\n");
return 0;
}
if (hw_config->irq > 7 && hw_config->irq != 9 && inb(hw_config->io_base + 3) & 0x80) {
printf("AudioTriX: Can't use IRQ%d with a 8 bit card\n", hw_config->irq);
return 0;
}
return ad1848_detect(hw_config->io_base + 4, NULL, hw_config->osp);
}
void
attach_trix_wss(struct address_info * hw_config)
{
static u_char interrupt_bits[12] =
{-1, -1, -1, -1, -1, -1, -1, 0x08, -1, 0x10, 0x18, 0x20};
char bits;
static u_char dma_bits[4] =
{1, 2, 0, 3};
int config_port = hw_config->io_base + 0,
version_port = hw_config->io_base + 3;
int dma1 = hw_config->dma, dma2 = hw_config->dma2;
trix_osp = hw_config->osp;
if (!kilroy_was_here) {
DDB(printf("AudioTriX: Attach called but not probed yet???\n"));
return ;
}
/*
* Set the IRQ and DMA addresses.
*/
bits = interrupt_bits[hw_config->irq];
if (bits == -1) {
printf("AudioTriX: Bad IRQ (%d)\n", hw_config->irq);
return ;
}
outb(config_port, bits | 0x40);
if ((inb(version_port) & 0x40) == 0)
printf("[IRQ Conflict?]");
if (hw_config->dma2 == -1) { /* Single DMA mode */
bits |= dma_bits[dma1];
dma2 = dma1;
} else {
u_char tmp;
tmp = trix_read(0x13) & ~30;
trix_write(0x13, tmp | 0x80 | (dma1 << 4));
tmp = trix_read(0x14) & ~30;
trix_write(0x14, tmp | 0x80 | (dma2 << 4));
}
outb(config_port, bits);/* Write IRQ+DMA setup */
ad1848_init("AudioTriX Pro", hw_config->io_base + 4,
hw_config->irq,
dma1,
dma2,
0,
hw_config->osp);
return ;
}
int
probe_trix_sb(struct address_info * hw_config)
{
int tmp;
u_char conf;
static char irq_translate[] = {-1, -1, -1, 0, 1, 2, -1, 3};
#ifndef INCLUDE_TRIX_BOOT
return 0; /* No boot code -> no fun */
#endif
if (!kilroy_was_here)
return 0; /* AudioTriX Pro has not been detected earlier */
if (sb_initialized)
return 0;
if ((hw_config->io_base & 0xffffff8f) != 0x200)
return 0;
tmp = hw_config->irq;
if (tmp > 7)
return 0;
if (irq_translate[tmp] == -1)
return 0;
tmp = hw_config->dma;
if (tmp != 1 && tmp != 3)
return 0;
conf = 0x84; /* DMA and IRQ enable */
conf |= hw_config->io_base & 0x70; /* I/O address bits */
conf |= irq_translate[hw_config->irq];
if (hw_config->dma == 3)
conf |= 0x08;
trix_write(0x1b, conf);
download_boot(hw_config->io_base);
sb_initialized = 1;
return 1;
}
void
attach_trix_sb(struct address_info * hw_config)
{
#if (NSB > 0)
sb_dsp_disable_midi();
sb_no_recording = 1;
#endif
conf_printf("AudioTriX (SB)", hw_config);
}
void
attach_trix_mpu(struct address_info * hw_config)
{
#if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI)
attach_mpu401(hw_config);
#endif
}
int
probe_trix_mpu(struct address_info * hw_config)
{
#if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI)
u_char conf;
static char irq_bits[] = {-1, -1, -1, 1, 2, 3, -1, 4, -1, 5};
if (!kilroy_was_here) {
DDB(printf("Trix: WSS and SB modes must be initialized before MPU\n"));
return 0; /* AudioTriX Pro has not been detected earlier */
}
if (!sb_initialized) {
DDB(printf("Trix: SB mode must be initialized before MPU\n"));
return 0;
}
if (mpu_initialized) {
DDB(printf("Trix: MPU mode already initialized\n"));
return 0;
}
if (hw_config->irq > 9) {
printf("AudioTriX: Bad MPU IRQ %d\n", hw_config->irq);
return 0;
}
if (irq_bits[hw_config->irq] == -1) {
printf("AudioTriX: Bad MPU IRQ %d\n", hw_config->irq);
return 0;
}
switch (hw_config->io_base) {
case 0x330:
conf = 0x00;
break;
case 0x370:
conf = 0x04;
break;
case 0x3b0:
conf = 0x08;
break;
case 0x3f0:
conf = 0x0c;
break;
default:
return 0; /* Invalid port */
}
conf |= irq_bits[hw_config->irq] << 4;
trix_write(0x19, (trix_read(0x19) & 0x83) | conf);
mpu_initialized = 1;
return probe_mpu401(hw_config);
#else
return 0;
#endif
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,29 +0,0 @@
#ifdef SEQUENCER_C
unsigned short semitone_tuning[24] =
{
/* 0 */ 10000, 10595, 11225, 11892, 12599, 13348, 14142, 14983,
/* 8 */ 15874, 16818, 17818, 18877, 20000, 21189, 22449, 23784,
/* 16 */ 25198, 26697, 28284, 29966, 31748, 33636, 35636, 37755
};
unsigned short cent_tuning[100] =
{
/* 0 */ 10000, 10006, 10012, 10017, 10023, 10029, 10035, 10041,
/* 8 */ 10046, 10052, 10058, 10064, 10070, 10075, 10081, 10087,
/* 16 */ 10093, 10099, 10105, 10110, 10116, 10122, 10128, 10134,
/* 24 */ 10140, 10145, 10151, 10157, 10163, 10169, 10175, 10181,
/* 32 */ 10187, 10192, 10198, 10204, 10210, 10216, 10222, 10228,
/* 40 */ 10234, 10240, 10246, 10251, 10257, 10263, 10269, 10275,
/* 48 */ 10281, 10287, 10293, 10299, 10305, 10311, 10317, 10323,
/* 56 */ 10329, 10335, 10341, 10347, 10353, 10359, 10365, 10371,
/* 64 */ 10377, 10383, 10389, 10395, 10401, 10407, 10413, 10419,
/* 72 */ 10425, 10431, 10437, 10443, 10449, 10455, 10461, 10467,
/* 80 */ 10473, 10479, 10485, 10491, 10497, 10503, 10509, 10515,
/* 88 */ 10521, 10528, 10534, 10540, 10546, 10552, 10558, 10564,
/* 96 */ 10570, 10576, 10582, 10589
};
#else
extern unsigned short semitone_tuning[24];
extern unsigned short cent_tuning[100];
#endif

View File

@ -1,296 +0,0 @@
/*
* sound/uart6850.c
*
* Copyright by Hannu Savolainen 1993
*
* Mon Nov 22 22:38:35 MET 1993 marco@driq.home.usn.nl: added 6850 support, used
* with COVOX SoundMaster II and custom cards.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. 2.
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#include <i386/isa/sound/sound_config.h>
#if NSND > 0
#if 1
/* #if defined(CONFIG_UART6850) && defined(CONFIG_MIDI) */
#define DATAPORT (uart6850_base) /* * * Midi6850 Data I/O Port on IBM */
#define COMDPORT (uart6850_base+1) /* * * Midi6850 Command Port on IBM */
#define STATPORT (uart6850_base+1) /* * * Midi6850 Status Port on IBM */
#define uart6850_status() inb( STATPORT)
#define input_avail() (uart6850_status()&INPUT_AVAIL)
#define output_ready() (uart6850_status()&OUTPUT_READY)
#define uart6850_cmd(cmd) outb( COMDPORT, cmd)
#define uart6850_read() inb( DATAPORT)
#define uart6850_write(byte) outb( DATAPORT, byte)
#define OUTPUT_READY 0x02 /* * * Mask for Data Read Ready Bit */
#define INPUT_AVAIL 0x01 /* * * Mask for Data Send Ready Bit */
#define UART_RESET 0x95 /* * * 6850 Total Reset Command */
#define UART_MODE_ON 0x03 /* * * 6850 Send/Receive UART Mode */
static int uart6850_opened = 0;
static int uart6850_base = 0x330;
static int uart6850_irq;
static int uart6850_detected = 0;
static int my_dev;
static int reset_uart6850(void);
static void (*midi_input_intr) (int dev, u_char data);
static void poll_uart6850(void *dummy);
static sound_os_info *uart6850_osp;
static void
uart6850_input_loop(void)
{
int count;
count = 10;
while (count) /* Not timed out */
if (input_avail()) {
u_char c = uart6850_read();
count = 100;
if (uart6850_opened & OPEN_READ)
midi_input_intr(my_dev, c);
} else
while (!input_avail() && count)
count--;
}
void
m6850intr(int irq)
{
if (input_avail())
uart6850_input_loop();
}
/*
* It looks like there is no input interrupts in the UART mode. Let's try
* polling.
*/
static void
poll_uart6850(void * dummy)
{
u_long flags;
if (!(uart6850_opened & OPEN_READ))
return; /* Device has been closed */
flags = splhigh();
if (input_avail())
uart6850_input_loop();
timeout( poll_uart6850, 0, 1); /* Come back later */
splx(flags);
}
static int
uart6850_open(int dev, int mode,
void (*input) (int dev, u_char data),
void (*output) (int dev)
)
{
if (uart6850_opened) {
printf("Midi6850: Midi busy\n");
return -(EBUSY);
}
uart6850_cmd(UART_RESET);
uart6850_input_loop();
midi_input_intr = input;
uart6850_opened = mode;
poll_uart6850(0); /* Enable input polling */
return 0;
}
static void
uart6850_close(int dev)
{
uart6850_cmd(UART_MODE_ON);
uart6850_opened = 0;
}
static int
uart6850_out(int dev, u_char midi_byte)
{
int timeout;
u_long flags;
/*
* Test for input since pending input seems to block the output.
*/
flags = splhigh();
if (input_avail())
uart6850_input_loop();
splx(flags);
/*
* Sometimes it takes about 13000 loops before the output becomes
* ready (After reset). Normally it takes just about 10 loops.
*/
for (timeout = 30000; timeout > 0 && !output_ready(); timeout--); /* Wait */
if (!output_ready()) {
printf("Midi6850: Timeout\n");
return 0;
}
uart6850_write(midi_byte);
return 1;
}
static int
uart6850_command(int dev, u_char *midi_byte)
{
return 1;
}
static int
uart6850_start_read(int dev)
{
return 0;
}
static int
uart6850_end_read(int dev)
{
return 0;
}
static int
uart6850_ioctl(int dev, u_int cmd, ioctl_arg arg)
{
return -(EINVAL);
}
static void
uart6850_kick(int dev)
{
}
static int
uart6850_buffer_status(int dev)
{
return 0; /* No data in buffers */
}
#define MIDI_SYNTH_NAME "6850 UART Midi"
#define MIDI_SYNTH_CAPS SYNTH_CAP_INPUT
#include <i386/isa/sound/midi_synth.h>
static struct midi_operations uart6850_operations =
{
{"6850 UART", 0, 0, SNDCARD_UART6850},
&std_midi_synth,
{0},
uart6850_open,
uart6850_close,
uart6850_ioctl,
uart6850_out,
uart6850_start_read,
uart6850_end_read,
uart6850_kick,
uart6850_command,
uart6850_buffer_status
};
void
attach_uart6850(struct address_info * hw_config)
{
int ok, timeout;
u_long flags;
if (num_midis >= MAX_MIDI_DEV) {
printf("Sound: Too many midi devices detected\n");
return ;
}
uart6850_base = hw_config->io_base;
uart6850_osp = hw_config->osp;
uart6850_irq = hw_config->irq;
if (!uart6850_detected)
return ;
flags = splhigh();
for (timeout = 30000; timeout < 0 && !output_ready(); timeout--); /* Wait */
uart6850_cmd(UART_MODE_ON);
ok = 1;
splx(flags);
conf_printf("6850 Midi Interface", hw_config);
std_midi_synth.midi_dev = my_dev = num_midis;
midi_devs[num_midis++] = &uart6850_operations;
return ;
}
static int
reset_uart6850(void)
{
uart6850_read();
return 1; /* OK */
}
int
probe_uart6850(struct address_info * hw_config)
{
int ok = 0;
uart6850_osp = hw_config->osp;
uart6850_base = hw_config->io_base;
uart6850_irq = hw_config->irq;
if (snd_set_irq_handler(uart6850_irq, m6850intr, uart6850_osp) < 0)
return 0;
ok = reset_uart6850();
uart6850_detected = ok;
return ok;
}
#endif
#endif

View File

@ -1,71 +0,0 @@
static unsigned char ulaw_dsp[] = {
3, 7, 11, 15, 19, 23, 27, 31,
35, 39, 43, 47, 51, 55, 59, 63,
66, 68, 70, 72, 74, 76, 78, 80,
82, 84, 86, 88, 90, 92, 94, 96,
98, 99, 100, 101, 102, 103, 104, 105,
106, 107, 108, 109, 110, 111, 112, 113,
113, 114, 114, 115, 115, 116, 116, 117,
117, 118, 118, 119, 119, 120, 120, 121,
121, 121, 122, 122, 122, 122, 123, 123,
123, 123, 124, 124, 124, 124, 125, 125,
125, 125, 125, 125, 126, 126, 126, 126,
126, 126, 126, 126, 127, 127, 127, 127,
127, 127, 127, 127, 127, 127, 127, 127,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
253, 249, 245, 241, 237, 233, 229, 225,
221, 217, 213, 209, 205, 201, 197, 193,
190, 188, 186, 184, 182, 180, 178, 176,
174, 172, 170, 168, 166, 164, 162, 160,
158, 157, 156, 155, 154, 153, 152, 151,
150, 149, 148, 147, 146, 145, 144, 143,
143, 142, 142, 141, 141, 140, 140, 139,
139, 138, 138, 137, 137, 136, 136, 135,
135, 135, 134, 134, 134, 134, 133, 133,
133, 133, 132, 132, 132, 132, 131, 131,
131, 131, 131, 131, 130, 130, 130, 130,
130, 130, 130, 130, 129, 129, 129, 129,
129, 129, 129, 129, 129, 129, 129, 129,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
};
#ifndef DSP_ULAW_NOT_WANTED
static unsigned char dsp_ulaw[] = {
0, 0, 0, 0, 0, 1, 1, 1,
1, 2, 2, 2, 2, 3, 3, 3,
3, 4, 4, 4, 4, 5, 5, 5,
5, 6, 6, 6, 6, 7, 7, 7,
7, 8, 8, 8, 8, 9, 9, 9,
9, 10, 10, 10, 10, 11, 11, 11,
11, 12, 12, 12, 12, 13, 13, 13,
13, 14, 14, 14, 14, 15, 15, 15,
15, 16, 16, 17, 17, 18, 18, 19,
19, 20, 20, 21, 21, 22, 22, 23,
23, 24, 24, 25, 25, 26, 26, 27,
27, 28, 28, 29, 29, 30, 30, 31,
31, 32, 33, 34, 35, 36, 37, 38,
39, 40, 41, 42, 43, 44, 45, 46,
47, 49, 51, 53, 55, 57, 59, 61,
63, 66, 70, 74, 78, 84, 92, 104,
254, 231, 219, 211, 205, 201, 197, 193,
190, 188, 186, 184, 182, 180, 178, 176,
175, 174, 173, 172, 171, 170, 169, 168,
167, 166, 165, 164, 163, 162, 161, 160,
159, 159, 158, 158, 157, 157, 156, 156,
155, 155, 154, 154, 153, 153, 152, 152,
151, 151, 150, 150, 149, 149, 148, 148,
147, 147, 146, 146, 145, 145, 144, 144,
143, 143, 143, 143, 142, 142, 142, 142,
141, 141, 141, 141, 140, 140, 140, 140,
139, 139, 139, 139, 138, 138, 138, 138,
137, 137, 137, 137, 136, 136, 136, 136,
135, 135, 135, 135, 134, 134, 134, 134,
133, 133, 133, 133, 132, 132, 132, 132,
131, 131, 131, 131, 130, 130, 130, 130,
129, 129, 129, 129, 128, 128, 128, 128,
};
#endif /* !DSP_ULAW_NOT_WANTED */

View File

@ -1,137 +0,0 @@
#ifndef _ULTRASOUND_H_
#define _ULTRASOUND_H_
/*
* Copyright by Hannu Savolainen 1993
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
/*
* ultrasound.h - Macros for programming the Gravis Ultrasound
* These macros are extremely device dependent
* and not portable.
*/
/*
* Private events for Gravis Ultrasound (GUS)
*
* Format:
* byte 0 - SEQ_PRIVATE (0xfe)
* byte 1 - Synthesizer device number (0-N)
* byte 2 - Command (see below)
* byte 3 - Voice number (0-31)
* bytes 4 and 5 - parameter P1 (u_short)
* bytes 6 and 7 - parameter P2 (u_short)
*
* Commands:
* Each command affects one voice defined in byte 3.
* Unused parameters (P1 and/or P2 *MUST* be initialized to zero).
* _GUS_NUMVOICES - Sets max. number of concurrent voices (P1=14-31, default 16)
* _GUS_VOICESAMPLE- ************ OBSOLETE *************
* _GUS_VOICEON - Starts voice (P1=voice mode)
* _GUS_VOICEOFF - Stops voice (no parameters)
* _GUS_VOICEFADE - Stops the voice smoothly.
* _GUS_VOICEMODE - Alters the voice mode, don't start or stop voice (P1=voice mode)
* _GUS_VOICEBALA - Sets voice balence (P1, 0=left, 7=middle and 15=right, default 7)
* _GUS_VOICEFREQ - Sets voice (sample) playback frequency (P1=Hz)
* _GUS_VOICEVOL - Sets voice volume (P1=volume, 0xfff=max, 0xeff=half, 0x000=off)
* _GUS_VOICEVOL2 - Sets voice volume (P1=volume, 0xfff=max, 0xeff=half, 0x000=off)
* (Like GUS_VOICEVOL but doesn't change the hw
* volume. It just updates volume in the voice table).
*
* _GUS_RAMPRANGE - Sets limits for volume ramping (P1=low volume, P2=high volume)
* _GUS_RAMPRATE - Sets the speed for volume ramping (P1=scale, P2=rate)
* _GUS_RAMPMODE - Sets the volume ramping mode (P1=ramping mode)
* _GUS_RAMPON - Starts volume ramping (no parameters)
* _GUS_RAMPOFF - Stops volume ramping (no parameters)
* _GUS_VOLUME_SCALE - Changes the volume calculation constants
* for all voices.
*/
#define _GUS_NUMVOICES 0x00
#define _GUS_VOICESAMPLE 0x01 /* OBSOLETE */
#define _GUS_VOICEON 0x02
#define _GUS_VOICEOFF 0x03
#define _GUS_VOICEMODE 0x04
#define _GUS_VOICEBALA 0x05
#define _GUS_VOICEFREQ 0x06
#define _GUS_VOICEVOL 0x07
#define _GUS_RAMPRANGE 0x08
#define _GUS_RAMPRATE 0x09
#define _GUS_RAMPMODE 0x0a
#define _GUS_RAMPON 0x0b
#define _GUS_RAMPOFF 0x0c
#define _GUS_VOICEFADE 0x0d
#define _GUS_VOLUME_SCALE 0x0e
#define _GUS_VOICEVOL2 0x0f
#define _GUS_VOICE_POS 0x10
/*
* GUS API macros
*/
#define _GUS_CMD(chn, voice, cmd, p1, p2) {\
_SEQ_NEEDBUF(8); _seqbuf[_seqbufptr] = SEQ_PRIVATE;\
_seqbuf[_seqbufptr+1] = (chn); _seqbuf[_seqbufptr+2] = cmd;\
_seqbuf[_seqbufptr+3] = voice;\
*(u_short*)&_seqbuf[_seqbufptr+4] = p1;\
*(u_short*)&_seqbuf[_seqbufptr+6] = p2;\
_SEQ_ADVBUF(8);}
#define GUS_NUMVOICES(chn, p1) _GUS_CMD(chn, 0, _GUS_NUMVOICES, (p1), 0)
#define GUS_VOICESAMPLE(chn, voice, p1) \
_GUS_CMD(chn, voice, _GUS_VOICESAMPLE, (p1), 0) /* OBSOLETE */
#define GUS_VOICEON(chn, voice, p1) \
_GUS_CMD(chn, voice, _GUS_VOICEON, (p1), 0)
#define GUS_VOICEOFF(chn, voice) \
_GUS_CMD(chn, voice, _GUS_VOICEOFF, 0, 0)
#define GUS_VOICEFADE(chn, voice) \
_GUS_CMD(chn, voice, _GUS_VOICEFADE, 0, 0)
#define GUS_VOICEMODE(chn, voice, p1) \
_GUS_CMD(chn, voice, _GUS_VOICEMODE, (p1), 0)
#define GUS_VOICEBALA(chn, voice, p1) \
_GUS_CMD(chn, voice, _GUS_VOICEBALA, (p1), 0)
#define GUS_VOICEFREQ(chn, voice, p) \
_GUS_CMD(chn, voice, _GUS_VOICEFREQ, \
(p) & 0xffff, ((p) >> 16) & 0xffff)
#define GUS_VOICEVOL(chn, voice, p1) \
_GUS_CMD(chn, voice, _GUS_VOICEVOL, (p1), 0)
#define GUS_VOICEVOL2(chn, voice, p1) \
_GUS_CMD(chn, voice, _GUS_VOICEVOL2, (p1), 0)
#define GUS_RAMPRANGE(chn, voice, low, high) \
_GUS_CMD(chn, voice, _GUS_RAMPRANGE, (low), (high))
#define GUS_RAMPRATE(chn, voice, p1, p2) \
_GUS_CMD(chn, voice, _GUS_RAMPRATE, (p1), (p2))
#define GUS_RAMPMODE(chn, voice, p1) \
_GUS_CMD(chn, voice, _GUS_RAMPMODE, (p1), 0)
#define GUS_RAMPON(chn, voice, p1) \
_GUS_CMD(chn, voice, _GUS_RAMPON, (p1), 0)
#define GUS_RAMPOFF(chn, voice) \
_GUS_CMD(chn, voice, _GUS_RAMPOFF, 0, 0)
#define GUS_VOLUME_SCALE(chn, voice, p1, p2) \
_GUS_CMD(chn, voice, _GUS_VOLUME_SCALE, (p1), (p2))
#define GUS_VOICE_POS(chn, voice, p) \
_GUS_CMD(chn, voice, _GUS_VOICE_POS, \
(p) & 0xffff, ((p) >> 16) & 0xffff)
#endif