Bring our sound sources up to the level of Amancio's latest-and-greatest.

This corresponds to Voxware 3.5-alpha-<something> and Amancio's guspnp21.
There was a bit of a FUBAR during the commmit, so not all files are
mentioned in this commit's mail.

X-rant:	I have just started to _*HATE*_ CVS...
This commit is contained in:
markm 1997-10-31 17:25:35 +00:00
parent 062497b471
commit 0183b33fd6
25 changed files with 9591 additions and 6550 deletions

693
sys/i386/isa/sound/pss.c Normal file
View File

@ -0,0 +1,693 @@
/*
* 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;
sprintf(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

371
sys/i386/isa/sound/pss.h Normal file
View File

@ -0,0 +1,371 @@
/******************************************************************************
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,12 +1,12 @@
/*
* sound/sb16_dsp.c
*
*
* The low level driver for the SoundBlaster DSP chip.
*
*
* (C) 1993 J. Schubert (jsb@sth.ruhr-uni-bochum.de)
*
*
* based on SB-driver by (C) Hannu Savolainen
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
@ -14,7 +14,7 @@
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
@ -26,568 +26,486 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*
*/
#define DEB(x)
#define DEB1(x)
/*
* #define DEB_DMARES
*/
#include <i386/isa/sound/sound_config.h>
#include <i386/isa/sound/sb_defs.h>
#include "sb.h"
#include <i386/isa/sound/sb_mixer.h>
#include <i386/isa/sound/sbcard.h>
#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_SB16) && !defined(EXCLUDE_SB) && !defined(EXCLUDE_AUDIO) && !defined(EXCLUDE_SBPRO)
#if defined(CONFIG_SB16) && (NSB > 0) && defined(CONFIG_AUDIO) && defined(CONFIG_SBPRO)
extern sound_os_info *sb_osp;
extern int sbc_base;
extern int sbc_major;
extern int sbc_minor;
static int sb16_dsp_ok = 0; /*
* * * * Set to 1 after successful *
* * initialization */
static int sb16_dsp_ok = 0;
static int dsp_16bit = 0;
static int dsp_stereo = 0;
static int dsp_current_speed = 8000; /*
* * * * DSP_DEFAULT_SPEED; */
static int dsp_current_speed = 8000;
static int dsp_busy = 0;
static int dma16, dma8;
static unsigned long dsp_count = 0;
static int trigger_bits = 0;
static u_long dsp_count = 0;
static int irq_mode = IMODE_NONE; /*
* * * * IMODE_INPUT, IMODE_OUTPUT
* or * * IMODE_NONE */
static int irq_mode = IMODE_NONE;
static int my_dev = 0;
static volatile int intr_active = 0;
static int sb16_dsp_open (int dev, int mode);
static void sb16_dsp_close (int dev);
static void sb16_dsp_output_block (int dev, unsigned long buf, int count, int intrflag, int dma_restart);
static void sb16_dsp_start_input (int dev, unsigned long buf, int count, int intrflag, int dma_restart);
static int sb16_dsp_ioctl (int dev, unsigned int cmd, unsigned int arg, int local);
static int sb16_dsp_prepare_for_input (int dev, int bsize, int bcount);
static int sb16_dsp_prepare_for_output (int dev, int bsize, int bcount);
static void sb16_dsp_reset (int dev);
static void sb16_dsp_halt (int dev);
static int dsp_set_speed (int);
static int dsp_set_stereo (int);
static void dsp_cleanup (void);
static int sb16_dsp_open(int dev, int mode);
static void sb16_dsp_close(int dev);
static void sb16_dsp_output_block(int dev, u_long buf, int count, int intrflag, int dma_restart);
static void sb16_dsp_start_input(int dev, u_long buf, int count, int intrflag, int dma_restart);
static int sb16_dsp_ioctl(int dev, u_int cmd, ioctl_arg arg, int local);
static int sb16_dsp_prepare_for_input(int dev, int bsize, int bcount);
static int sb16_dsp_prepare_for_output(int dev, int bsize, int bcount);
static void sb16_dsp_reset(int dev);
static void sb16_dsp_halt(int dev);
static void sb16_dsp_trigger(int dev, int bits);
static int dsp_set_speed(int);
static int dsp_set_stereo(int);
static void dsp_cleanup(void);
static struct audio_operations sb16_dsp_operations =
{
"SoundBlaster 16",
DMA_AUTOMODE,
AFMT_U8 | AFMT_S16_LE,
NULL,
sb16_dsp_open,
sb16_dsp_close,
sb16_dsp_output_block,
sb16_dsp_start_input,
sb16_dsp_ioctl,
sb16_dsp_prepare_for_input,
sb16_dsp_prepare_for_output,
sb16_dsp_reset,
sb16_dsp_halt,
NULL,
NULL
"SoundBlaster 16",
DMA_AUTOMODE,
AFMT_U8 | AFMT_S16_LE,
NULL,
sb16_dsp_open,
sb16_dsp_close,
sb16_dsp_output_block,
sb16_dsp_start_input,
sb16_dsp_ioctl,
sb16_dsp_prepare_for_input,
sb16_dsp_prepare_for_output,
sb16_dsp_reset,
sb16_dsp_halt,
NULL,
NULL,
NULL,
NULL,
sb16_dsp_trigger
};
static int
sb_dsp_command01 (unsigned char val)
sb_dsp_command01(u_char val)
{
int i = 1 << 16;
int i = 1 << 16;
while (--i & (!INB (DSP_STATUS) & 0x80));
if (!i)
printk ("SB16 sb_dsp_command01 Timeout\n");
return sb_dsp_command (val);
while (--i & (!inb(DSP_STATUS) & 0x80));
if (!i)
printf("SB16 sb_dsp_command01 Timeout\n");
return sb_dsp_command(val);
}
static int
dsp_set_speed (int mode)
dsp_set_speed(int mode)
{
DEB (printk ("dsp_set_speed(%d)\n", mode));
if (mode)
{
if (mode < 5000)
mode = 5000;
if (mode > 44100)
mode = 44100;
dsp_current_speed = mode;
DEB(printf("dsp_set_speed(%d)\n", mode));
if (mode) {
RANGE (mode, 5000, 44100);
dsp_current_speed = mode;
}
return mode;
return mode;
}
static int
dsp_set_stereo (int mode)
dsp_set_stereo(int mode)
{
DEB (printk ("dsp_set_stereo(%d)\n", mode));
dsp_stereo = mode;
return mode;
DEB(printf("dsp_set_stereo(%d)\n", mode));
dsp_stereo = mode;
return mode;
}
static int
dsp_set_bits (int arg)
dsp_set_bits(int arg)
{
DEB (printk ("dsp_set_bits(%d)\n", arg));
DEB(printf("dsp_set_bits(%d)\n", arg));
if (arg)
switch (arg)
{
case 8:
dsp_16bit = 0;
break;
case 16:
dsp_16bit = 1;
break;
default:
dsp_16bit = 0;
}
return dsp_16bit ? 16 : 8;
if (arg)
dsp_16bit = (arg == 16) ? 1 : 0 ;
return dsp_16bit ? 16 : 8;
}
static int
sb16_dsp_ioctl (int dev, unsigned int cmd, unsigned int arg, int local)
sb16_dsp_ioctl(int dev, u_int cmd, ioctl_arg arg, int local)
{
switch (cmd)
{
switch (cmd) {
case SOUND_PCM_WRITE_RATE:
if (local)
return dsp_set_speed (arg);
return IOCTL_OUT (arg, dsp_set_speed (IOCTL_IN (arg)));
if (local)
return dsp_set_speed((int) arg);
return *(int *) arg = dsp_set_speed((*(int *) arg));
case SOUND_PCM_READ_RATE:
if (local)
return dsp_current_speed;
return IOCTL_OUT (arg, dsp_current_speed);
if (local)
return dsp_current_speed;
return *(int *) arg = dsp_current_speed;
case SNDCTL_DSP_STEREO:
if (local)
return dsp_set_stereo (arg);
return IOCTL_OUT (arg, dsp_set_stereo (IOCTL_IN (arg)));
if (local)
return dsp_set_stereo((int) arg);
return *(int *) arg = dsp_set_stereo((*(int *) arg));
case SOUND_PCM_WRITE_CHANNELS:
if (local)
return dsp_set_stereo (arg - 1) + 1;
return IOCTL_OUT (arg, dsp_set_stereo (IOCTL_IN (arg) - 1) + 1);
if (local)
return dsp_set_stereo((int) arg - 1) + 1;
return *(int *) arg = dsp_set_stereo((*(int *) arg) - 1) + 1;
case SOUND_PCM_READ_CHANNELS:
if (local)
return dsp_stereo + 1;
return IOCTL_OUT (arg, dsp_stereo + 1);
if (local)
return dsp_stereo + 1;
return *(int *) arg = dsp_stereo + 1;
case SNDCTL_DSP_SETFMT:
if (local)
return dsp_set_bits (arg);
return IOCTL_OUT (arg, dsp_set_bits (IOCTL_IN (arg)));
if (local)
return dsp_set_bits((int) arg);
return *(int *) arg = dsp_set_bits((*(int *) arg));
case SOUND_PCM_READ_BITS:
if (local)
return dsp_16bit ? 16 : 8;
return IOCTL_OUT (arg, dsp_16bit ? 16 : 8);
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;
case SOUND_PCM_WRITE_FILTER: /*
* NOT YET IMPLEMENTED
*/
if (IOCTL_IN (arg) > 1)
return IOCTL_OUT (arg, RET_ERROR (EINVAL));
default:
return RET_ERROR (EINVAL);
return -(EINVAL);
}
return RET_ERROR (EINVAL);
return -(EINVAL);
}
static int
sb16_dsp_open (int dev, int mode)
sb16_dsp_open(int dev, int mode)
{
int retval;
int retval;
DEB (printk ("sb16_dsp_open()\n"));
if (!sb16_dsp_ok)
{
printk ("SB16 Error: SoundBlaster board not installed\n");
return RET_ERROR (ENXIO);
DEB(printf("sb16_dsp_open()\n"));
if (!sb16_dsp_ok) {
printf("SB16 Error: SoundBlaster board not installed\n");
return -(ENXIO);
}
if (intr_active)
return -(EBUSY);
if (intr_active)
return RET_ERROR (EBUSY);
sb_reset_dsp();
retval = sb_get_irq ();
if (retval < 0)
return retval;
irq_mode = IMODE_NONE;
dsp_busy = 1;
trigger_bits = 0;
sb_reset_dsp ();
if (ALLOC_DMA_CHN (dma8, "SB16 (8bit)"))
{
printk ("SB16: Unable to grab DMA%d\n", dma8);
sb_free_irq ();
return RET_ERROR (EBUSY);
}
if (dma16 != dma8)
if (ALLOC_DMA_CHN (dma16, "SB16 (16bit)"))
{
printk ("SB16: Unable to grab DMA%d\n", dma16);
sb_free_irq ();
RELEASE_DMA_CHN (dma8);
return RET_ERROR (EBUSY);
}
irq_mode = IMODE_NONE;
dsp_busy = 1;
return 0;
}
static void
sb16_dsp_close (int dev)
{
unsigned long flags;
DEB (printk ("sb16_dsp_close()\n"));
sb_dsp_command01 (0xd9);
sb_dsp_command01 (0xd5);
DISABLE_INTR (flags);
RELEASE_DMA_CHN (dma8);
if (dma16 != dma8)
RELEASE_DMA_CHN (dma16);
sb_free_irq ();
dsp_cleanup ();
dsp_busy = 0;
RESTORE_INTR (flags);
}
static void
sb16_dsp_output_block (int dev, unsigned long buf, int count, int intrflag, int dma_restart)
{
unsigned long flags, cnt;
cnt = count;
if (dsp_16bit)
cnt >>= 1;
cnt--;
#ifdef DEB_DMARES
printk ("output_block: %x %d %d\n", buf, count, intrflag);
if (intrflag)
{
int pos, chan = audio_devs[dev]->dmachan;
DISABLE_INTR (flags);
clear_dma_ff (chan);
disable_dma (chan);
pos = get_dma_residue (chan);
enable_dma (chan);
RESTORE_INTR (flags);
printk ("dmapos=%d %x\n", pos, pos);
}
#endif
if (audio_devs[dev]->flags & DMA_AUTOMODE &&
intrflag &&
cnt == dsp_count)
{
irq_mode = IMODE_OUTPUT;
intr_active = 1;
return; /*
* Auto mode on. No need to react
*/
}
DISABLE_INTR (flags);
if (dma_restart)
{
sb16_dsp_halt (dev);
DMAbuf_start_dma (dev, buf, count, DMA_MODE_WRITE);
}
sb_dsp_command (0x41);
sb_dsp_command ((unsigned char) ((dsp_current_speed >> 8) & 0xff));
sb_dsp_command ((unsigned char) (dsp_current_speed & 0xff));
sb_dsp_command ((unsigned char) (dsp_16bit ? 0xb6 : 0xc6));
sb_dsp_command ((unsigned char) ((dsp_stereo ? 0x20 : 0) +
(dsp_16bit ? 0x10 : 0)));
sb_dsp_command01 ((unsigned char) (cnt & 0xff));
sb_dsp_command ((unsigned char) (cnt >> 8));
dsp_count = cnt;
irq_mode = IMODE_OUTPUT;
intr_active = 1;
RESTORE_INTR (flags);
}
static void
sb16_dsp_start_input (int dev, unsigned long buf, int count, int intrflag, int dma_restart)
{
unsigned long flags, cnt;
cnt = count;
if (dsp_16bit)
cnt >>= 1;
cnt--;
#ifdef DEB_DMARES
printk ("start_input: %x %d %d\n", buf, count, intrflag);
if (intrflag)
{
int pos, chan = audio_devs[dev]->dmachan;
DISABLE_INTR (flags);
clear_dma_ff (chan);
disable_dma (chan);
pos = get_dma_residue (chan);
enable_dma (chan);
RESTORE_INTR (flags);
printk ("dmapos=%d %x\n", pos, pos);
}
#endif
if (audio_devs[dev]->flags & DMA_AUTOMODE &&
intrflag &&
cnt == dsp_count)
{
irq_mode = IMODE_INPUT;
intr_active = 1;
return; /*
* Auto mode on. No need to react
*/
}
DISABLE_INTR (flags);
if (dma_restart)
{
sb_reset_dsp ();
DMAbuf_start_dma (dev, buf, count, DMA_MODE_READ);
}
sb_dsp_command (0x42);
sb_dsp_command ((unsigned char) ((dsp_current_speed >> 8) & 0xff));
sb_dsp_command ((unsigned char) (dsp_current_speed & 0xff));
sb_dsp_command ((unsigned char) (dsp_16bit ? 0xbe : 0xce));
sb_dsp_command ((unsigned char) ((dsp_stereo ? 0x20 : 0) +
(dsp_16bit ? 0x10 : 0)));
sb_dsp_command01 ((unsigned char) (cnt & 0xff));
sb_dsp_command ((unsigned char) (cnt >> 8));
dsp_count = cnt;
irq_mode = IMODE_INPUT;
intr_active = 1;
RESTORE_INTR (flags);
}
static int
sb16_dsp_prepare_for_input (int dev, int bsize, int bcount)
{
audio_devs[my_dev]->dmachan = dsp_16bit ? dma16 : dma8;
dsp_count = 0;
dsp_cleanup ();
return 0;
}
static int
sb16_dsp_prepare_for_output (int dev, int bsize, int bcount)
{
audio_devs[my_dev]->dmachan = dsp_16bit ? dma16 : dma8;
dsp_count = 0;
dsp_cleanup ();
return 0;
}
static void
dsp_cleanup (void)
{
irq_mode = IMODE_NONE;
intr_active = 0;
}
static void
sb16_dsp_reset (int dev)
{
unsigned long flags;
DISABLE_INTR (flags);
sb_reset_dsp ();
dsp_cleanup ();
RESTORE_INTR (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);
}
DMAbuf_reset_dma (dev);
}
static void
set_irq_hw (int level)
{
int ival;
switch (level)
{
#ifdef PC98
case 5:
ival = 8;
break;
case 3:
ival = 1;
break;
case 10:
ival = 2;
break;
#else
case 5:
ival = 2;
break;
case 7:
ival = 4;
break;
case 9:
ival = 1;
break;
case 10:
ival = 8;
break;
#endif
default:
printk ("SB16_IRQ_LEVEL %d does not exist\n", level);
return;
}
sb_setmixer (IRQ_NR, ival);
}
long
sb16_dsp_init (long mem_start, struct address_info *hw_config)
{
if (sbc_major < 4)
return mem_start; /* Not a SB16 */
sprintf (sb16_dsp_operations.name, "SoundBlaster 16 %d.%d", sbc_major, sbc_minor);
#if defined(__FreeBSD__)
printk ("sbxvi0: <%s>", sb16_dsp_operations.name);
#else
printk (" <%s>", sb16_dsp_operations.name);
#endif
if (num_audiodevs < MAX_AUDIO_DEV)
{
audio_devs[my_dev = num_audiodevs++] = &sb16_dsp_operations;
audio_devs[my_dev]->dmachan = hw_config->dma;
audio_devs[my_dev]->buffcount = 1;
audio_devs[my_dev]->buffsize = DSP_BUFFSIZE;
}
else
printk ("SB: Too many DSP devices available\n");
sb16_dsp_ok = 1;
return mem_start;
}
int
sb16_dsp_detect (struct address_info *hw_config)
{
struct address_info *sb_config;
if (sb16_dsp_ok)
return 0; /* Can't drive two cards */
if (!(sb_config = sound_getconf (SNDCARD_SB)))
{
printk ("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 */
static void
sb16_dsp_close(int dev)
{
u_long flags;
/* cause conflicts */
/* hw_config->io_base = sb_config->io_base; */
/* hw_config->irq = sb_config->irq; */
#ifdef PC98
hw_config->dma = sb_config->dma;
#else
if (hw_config->dma < 4)
if (hw_config->dma != sb_config->dma)
{
printk ("SB16 Error: Invalid DMA channel %d/%d\n",
sb_config->dma, hw_config->dma);
return 0;
}
#endif
DEB(printf("sb16_dsp_close()\n"));
sb_dsp_command01(0xd9);
sb_dsp_command01(0xd5);
dma16 = hw_config->dma;
dma8 = sb_config->dma;
set_irq_hw (sb_config->irq);
#ifdef PC98
sb_setmixer (DMA_NR, hw_config->dma == 0 ? 1 : 2);
#else
sb_setmixer (DMA_NR, (1 << hw_config->dma) | (1 << sb_config->dma));
#endif
flags = splhigh();
DEB (printk ("SoundBlaster 16: IRQ %d DMA %d OK\n", sb_config->irq, hw_config->dma));
audio_devs[dev]->dmachan1 = dma8;
/*
* dsp_showmessage(0xe3,99);
*/
sb16_dsp_ok = 1;
/* return 0x10; */
return -1;
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)
{
audio_devs[my_dev]->dmachan2 = dsp_16bit ? dma16 : dma8;
dsp_count = 0;
dsp_cleanup();
if (dsp_16bit)
sb_dsp_command(0xd5); /* Halt DMA until trigger() is called */
else
sb_dsp_command(0xd0); /* Halt DMA until trigger() is called */
trigger_bits = 0;
return 0;
}
static int
sb16_dsp_prepare_for_output(int dev, int bsize, int bcount)
{
int fudge = dsp_16bit ? dma16 : dma8;
isa_dma_release( audio_devs[my_dev]->dmachan1 );
isa_dma_acquire(fudge);
audio_devs[my_dev]->dmachan1 = fudge;
dsp_count = 0;
dsp_cleanup();
if (dsp_16bit)
sb_dsp_command(0xd5); /* Halt DMA until trigger() is called */
else
sb_dsp_command(0xd0); /* Halt DMA until trigger() is called */
trigger_bits = 0;
return 0;
}
static void
sb16_dsp_trigger(int dev, int bits)
{
if (bits != 0)
bits = 1;
if (bits == trigger_bits) /* No change */
return;
trigger_bits = bits;
if (!bits)
sb_dsp_command(0xd0); /* Halt DMA */
else if (bits & irq_mode)
sb_dsp_command(0xd4); /* Continue DMA */
}
static void
dsp_cleanup(void)
{
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_interrupt (int unused)
sb16_dsp_init(struct address_info * hw_config)
{
int data;
if (sbc_major < 4)
return; /* Not a SB16 */
data = INB (DSP_DATA_AVL16); /*
* Interrupt acknowledge
*/
sprintf(sb16_dsp_operations.name, "SoundBlaster 16 %d.%d",
sbc_major, sbc_minor);
if (intr_active)
switch (irq_mode)
{
case IMODE_OUTPUT:
intr_active = 0;
DMAbuf_outputintr (my_dev, 1);
break;
conf_printf(sb16_dsp_operations.name, hw_config);
case IMODE_INPUT:
intr_active = 0;
DMAbuf_inputintr (my_dev);
break;
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;
default:
printk ("SoundBlaster: Unexpected interrupt\n");
}
} 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,10 +1,10 @@
/*
* sound/sb16_midi.c
*
*
* The low level driver for the MPU-401 UART emulation of the SB16.
*
*
* Copyright by Hannu Savolainen 1993
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
@ -12,7 +12,7 @@
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
@ -24,33 +24,28 @@
* 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>
#ifdef CONFIGURE_SOUNDCARD
#if defined(CONFIG_SB) && defined(CONFIG_SB16) && defined(CONFIG_MIDI)
#if !defined(EXCLUDE_SB) && !defined(EXCLUDE_SB16) && !defined(EXCLUDE_MIDI)
#include "sb.h"
#include <i386/isa/sound/sb_defs.h>
#ifdef PC98
#define DATAPORT (sb16midi_base)
#define COMDPORT (sb16midi_base+0x100)
#define STATPORT (sb16midi_base+0x100)
#else
#define DATAPORT (sb16midi_base)
#define COMDPORT (sb16midi_base+1)
#define STATPORT (sb16midi_base+1)
#endif
#define sb16midi_status() INB(STATPORT)
extern sound_os_info *sb_osp;
#define sb16midi_status() inb( STATPORT)
#define input_avail() (!(sb16midi_status()&INPUT_AVAIL))
#define output_ready() (!(sb16midi_status()&OUTPUT_READY))
#define sb16midi_cmd(cmd) OUTB(cmd, COMDPORT)
#define sb16midi_read() INB(DATAPORT)
#define sb16midi_write(byte) OUTB(byte, DATAPORT)
#define sb16midi_cmd(cmd) outb( COMDPORT, cmd)
#define sb16midi_read() inb( DATAPORT)
#define sb16midi_write(byte) outb( DATAPORT, byte)
#define OUTPUT_READY 0x40
#define INPUT_AVAIL 0x80
@ -58,126 +53,118 @@
#define MPU_RESET 0xFF
#define UART_MODE_ON 0x3F
extern int sbc_major;
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, unsigned char data);
static int reset_sb16midi(void);
static void (*midi_input_intr) (int dev, u_char data);
static volatile u_char input_byte;
static void
sb16midi_input_loop (void)
sb16midi_input_loop(void)
{
while (input_avail ())
{
unsigned char c = sb16midi_read ();
while (input_avail()) {
u_char c = sb16midi_read();
if (sb16midi_opened & OPEN_READ)
midi_input_intr (my_dev, c);
}
if (c == MPU_ACK)
input_byte = c;
else if (sb16midi_opened & OPEN_READ && midi_input_intr)
midi_input_intr(my_dev, c);
}
}
void
sb16midiintr (int unit)
sb16midiintr(int unit)
{
if (input_avail ())
sb16midi_input_loop ();
if (input_avail())
sb16midi_input_loop();
}
static int
sb16midi_open (int dev, int mode,
void (*input) (int dev, unsigned char data),
void (*output) (int dev)
sb16midi_open(int dev, int mode,
void (*input) (int dev, u_char data),
void (*output) (int dev)
)
{
if (sb16midi_opened)
{
return RET_ERROR (EBUSY);
}
if (sb16midi_opened) {
return -(EBUSY);
}
sb16midi_input_loop();
sb16midi_input_loop ();
midi_input_intr = input;
sb16midi_opened = mode;
midi_input_intr = input;
sb16midi_opened = mode;
return 0;
return 0;
}
static void
sb16midi_close (int dev)
sb16midi_close(int dev)
{
sb16midi_opened = 0;
sb16midi_opened = 0;
}
static int
sb16midi_out (int dev, unsigned char midi_byte)
sb16midi_out(int dev, u_char midi_byte)
{
int timeout;
unsigned long flags;
int timeout;
u_long flags;
/*
* Test for input since pending input seems to block the output.
*/
/*
* Test for input since pending input seems to block the output.
*/
DISABLE_INTR (flags);
flags = splhigh();
if (input_avail ())
sb16midi_input_loop ();
if (input_avail())
sb16midi_input_loop();
RESTORE_INTR (flags);
splx(flags);
/*
* Sometimes it takes about 13000 loops before the output becomes ready
* (After reset). Normally it takes just about 10 loops.
*/
/*
* Sometimes it takes about 13000 loops before the output becomes
* ready (After reset). Normally it takes just about 10 loops.
*/
for (timeout = 30000; timeout > 0 && !output_ready (); timeout--); /*
* Wait
*/
for (timeout = 30000; timeout > 0 && !output_ready(); timeout--); /* Wait */
if (!output_ready ())
{
printk ("MPU-401: Timeout\n");
return 0;
}
sb16midi_write (midi_byte);
return 1;
if (!output_ready()) {
printf("MPU-401: Timeout\n");
return 0;
}
sb16midi_write(midi_byte);
return 1;
}
static int
sb16midi_start_read (int dev)
sb16midi_start_read(int dev)
{
return 0;
return 0;
}
static int
sb16midi_end_read (int dev)
sb16midi_end_read(int dev)
{
return 0;
return 0;
}
static int
sb16midi_ioctl (int dev, unsigned cmd, unsigned arg)
sb16midi_ioctl(int dev, u_int cmd, ioctl_arg arg)
{
return RET_ERROR (EINVAL);
return -(EINVAL);
}
static void
sb16midi_kick (int dev)
sb16midi_kick(int dev)
{
}
static int
sb16midi_buffer_status (int dev)
sb16midi_buffer_status(int dev)
{
return 0; /*
* No data in buffers
*/
return 0; /* No data in buffers */
}
#define MIDI_SYNTH_NAME "SoundBlaster 16 Midi"
@ -186,142 +173,127 @@ sb16midi_buffer_status (int dev)
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
{"SoundBlaster 16 Midi", 0, 0, SNDCARD_SB16MIDI},
&std_midi_synth,
{0},
sb16midi_open,
sb16midi_close,
sb16midi_ioctl,
sb16midi_out,
sb16midi_start_read,
sb16midi_end_read,
sb16midi_kick,
NULL,
sb16midi_buffer_status,
NULL
};
long
attach_sb16midi (long mem_start, struct address_info *hw_config)
void
attach_sb16midi(struct address_info * hw_config)
{
int ok, timeout;
unsigned long flags;
int ok, timeout;
u_long flags;
sb16midi_base = hw_config->io_base;
sb16midi_base = hw_config->io_base;
if (!sb16midi_detected)
return RET_ERROR (EIO);
if (!sb16midi_detected)
return;
DISABLE_INTR (flags);
for (timeout = 30000; timeout < 0 && !output_ready (); timeout--); /*
* Wait
*/
sb16midi_cmd (UART_MODE_ON);
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_avail ())
if (sb16midi_read () == MPU_ACK)
ok = 1;
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;
RESTORE_INTR (flags);
splx(flags);
if (num_midis >= MAX_MIDI_DEV)
{
printk ("Sound: Too many midi devices detected\n");
return mem_start;
}
#ifdef __FreeBSD__
printk ("sbmidi0: <SoundBlaster 16 MPU-401>");
#else
printk (" <SoundBlaster 16 MPU-401>");
#endif
std_midi_synth.midi_dev = my_dev = num_midis;
midi_devs[num_midis++] = &sb16midi_operations;
return mem_start;
if (num_midis >= MAX_MIDI_DEV) {
printf("Sound: Too many midi devices detected\n");
return;
}
conf_printf("SoundBlaster MPU-401", hw_config);
std_midi_synth.midi_dev = my_dev = num_midis;
midi_devs[num_midis++] = &sb16midi_operations;
return;
}
static int
reset_sb16midi (void)
reset_sb16midi(void)
{
unsigned long flags;
int ok, timeout, n;
int ok, timeout, n;
/*
* Send the RESET command. Try again if no success at the first time.
*/
/*
* Send the RESET command. Try again if no success at the first time.
*/
ok = 0;
if (inb(STATPORT) == 0xff)
return 0;
DISABLE_INTR (flags);
ok = 0;
for (n = 0; n < 2 && !ok; n++)
{
for (timeout = 30000; timeout < 0 && !output_ready (); timeout--); /*
* Wait
*/
sb16midi_cmd (MPU_RESET); /*
* Send MPU-401 RESET Command
*/
/* flags = splhigh(); */
/*
* Wait at least 25 msec. This method is not accurate so let's make the
* loop bit longer. Cannot sleep since this is called during boot.
*/
for (n = 0; n < 2 && !ok; n++) {
for (timeout = 30000; timeout < 0 && !output_ready(); timeout--); /* Wait */
input_byte = 0;
sb16midi_cmd(MPU_RESET); /* Send MPU-401 RESET Command */
for (timeout = 50000; timeout > 0 && !ok; timeout--)
if (input_avail ())
if (sb16midi_read () == MPU_ACK)
ok = 1;
/*
* Wait at least 25 msec. This method is not accurate so
* let's make the loop bit longer. Cannot sleep since this is
* called during boot.
*/
}
for (timeout = 50000; timeout > 0 && !ok; timeout--)
if (input_byte == MPU_ACK) /* Interrupt */
ok = 1;
else if (input_avail())
if (sb16midi_read() == MPU_ACK)
ok = 1;
sb16midi_opened = 0;
if (ok)
sb16midi_input_loop (); /*
* Flush input before enabling interrupts
*/
}
RESTORE_INTR (flags);
sb16midi_opened = 0;
if (ok)
sb16midi_input_loop(); /* Flush input before enabling
* interrupts */
return ok;
/* splx(flags); */
return ok;
}
int
probe_sb16midi (struct address_info *hw_config)
probe_sb16midi(struct address_info * hw_config)
{
struct address_info *sb_config;
int ok = 0;
int ok = 0;
struct address_info *sb_config;
if (!(sb_config = sound_getconf (SNDCARD_SB)))
{
printk ("SB16 Error: Plain SB not configured\n");
return 0;
}
if (sbc_major < 4)
return 0; /* Not a SB16 */
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;
sb16midi_base = hw_config->io_base;
if (sb_get_irq () < 0)
return 0;
ok = reset_sb16midi();
ok = reset_sb16midi ();
sb16midi_detected = ok;
if (ok) {
/* cause conflicts */
/* hw_config->irq = sb_config->irq; */
return 2;
} else
return 0;
sb16midi_detected = ok;
return ok;
}
#endif
#endif

View File

@ -1,10 +1,10 @@
/*
* sound/sb_card.c
*
*
* Detection routine for the SoundBlaster cards.
*
*
* Copyright by Hannu Savolainen 1993
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
@ -12,7 +12,7 @@
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
@ -24,38 +24,44 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Modified: Riccardo Facchetti 24 Mar 1995 - Added the Audio Excel DSP 16
* initialization routine.
*
* 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 defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_SB)
#if NSB > 0
#include <i386/isa/sound/sbcard.h>
long
attach_sb_card (long mem_start, struct address_info *hw_config)
void
attach_sb_card(struct address_info * hw_config)
{
#if !defined(EXCLUDE_AUDIO) || !defined(EXCLUDE_MIDI)
if (!sb_dsp_detect (hw_config))
return mem_start;
mem_start = sb_dsp_init (mem_start, hw_config);
#if defined(CONFIG_AUDIO) || defined(CONFIG_MIDI)
#if 0
/* why do a detect during the attach ? XXX */
if (!sb_dsp_detect(hw_config))
return ;
#endif
sb_dsp_init(hw_config);
#endif
return mem_start;
return ;
}
int
probe_sb (struct address_info *hw_config)
probe_sb(struct address_info * hw_config)
{
#if !defined(EXCLUDE_AEDSP16) && defined(AEDSP16_SBPRO)
/*
* Initialize Audio Excel DSP 16 to SBPRO.
*/
InitAEDSP16_SBPRO (hw_config);
#endif
return sb_dsp_detect (hw_config);
}
#if defined(CONFIG_AEDSP16) && defined(AEDSP16_SBPRO)
/*
* Initialize Audio Excel DSP 16 to SBPRO.
*/
InitAEDSP16_SBPRO(hw_config);
#endif
return sb_dsp_detect(hw_config);
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +1,10 @@
/*
* sound/sb_dsp.c
*
*
* The low level driver for the SoundBlaster DS chips.
*
*
* Copyright by Hannu Savolainen 1993
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
@ -12,7 +12,7 @@
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
@ -24,14 +24,14 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*
*/
#include <i386/isa/sound/sound_config.h>
#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_SB) && !defined(EXCLUDE_MIDI)
#if (NSND > 0) && defined(CONFIG_SB) && defined(CONFIG_MIDI)
#include <i386/isa/sound/sb_defs.h>
#include <i386/isa/sound/sbcard.h>
#undef SB_TEST_IRQ
/*
@ -46,167 +46,133 @@ extern int sb_dsp_ok; /* Set to 1 atfer successful initialization */
extern int sbc_base;
extern int sb_midi_mode;
extern int sb_midi_busy; /*
* * * * 1 if the process has output to MIDI
*
*/
extern int sb_midi_busy; /* 1 if the process has output to MIDI */
extern int sb_dsp_busy;
extern int sb_dsp_highspeed;
extern volatile int sb_irq_mode;
extern int sb_duplex_midi;
extern int sb_intr_active;
static int input_opened = 0;
int input_opened = 0;
static int my_dev;
void (*midi_input_intr) (int dev, unsigned char data);
extern sound_os_info *sb_osp;
void (*midi_input_intr) (int dev, u_char data);
static int
sb_midi_open (int dev, int mode,
void (*input) (int dev, unsigned char data),
void (*output) (int dev)
)
sb_midi_open(int dev, int mode, void (*input) (int dev, u_char data),
void (*output) (int dev))
{
int ret;
int ret;
if (!sb_dsp_ok)
{
printk ("SB Error: MIDI hardware not installed\n");
return RET_ERROR (ENXIO);
if (!sb_dsp_ok) {
printf("SB Error: MIDI hardware not installed\n");
return -(ENXIO);
}
if (sb_midi_busy)
return -(EBUSY);
if (sb_midi_busy)
return RET_ERROR (EBUSY);
if (mode != OPEN_WRITE && !sb_duplex_midi)
{
if (num_midis == 1)
printk ("SoundBlaster: Midi input not currently supported\n");
return RET_ERROR (EPERM);
if (mode != OPEN_WRITE && !sb_duplex_midi) {
if (num_midis == 1)
printf("SoundBlaster: Midi input not currently supported\n");
return -(EPERM);
}
sb_midi_mode = NORMAL_MIDI;
if (mode != OPEN_WRITE)
{
if (sb_dsp_busy || sb_intr_active)
return RET_ERROR (EBUSY);
sb_midi_mode = UART_MIDI;
sb_midi_mode = NORMAL_MIDI;
if (mode != OPEN_WRITE) {
if (sb_dsp_busy || sb_intr_active)
return -(EBUSY);
sb_midi_mode = UART_MIDI;
}
if (sb_dsp_highspeed)
{
printk ("SB Error: Midi output not possible during stereo or high speed audio\n");
return RET_ERROR (EBUSY);
if (sb_dsp_highspeed) {
printf("SB Error: Midi output not possible during stereo or high speed audio\n");
return -(EBUSY);
}
if (sb_midi_mode == UART_MIDI) {
sb_irq_mode = IMODE_MIDI;
if (sb_midi_mode == UART_MIDI)
{
sb_irq_mode = IMODE_MIDI;
sb_reset_dsp();
sb_reset_dsp ();
if (!sb_dsp_command(0x35))
return -(EIO); /* Enter the UART mode */
sb_intr_active = 1;
if (!sb_dsp_command (0x35))
return RET_ERROR (EIO); /*
* Enter the UART mode
*/
sb_intr_active = 1;
if ((ret = sb_get_irq ()) < 0)
{
sb_reset_dsp ();
return 0; /*
* IRQ not free
*/
}
input_opened = 1;
midi_input_intr = input;
input_opened = 1;
midi_input_intr = input;
}
sb_midi_busy = 1;
sb_midi_busy = 1;
return 0;
return 0;
}
static void
sb_midi_close (int dev)
sb_midi_close(int dev)
{
if (sb_midi_mode == UART_MIDI)
{
sb_reset_dsp (); /*
* The only way to kill the UART mode
*/
sb_free_irq ();
if (sb_midi_mode == UART_MIDI) {
sb_reset_dsp(); /* The only way to kill the UART mode */
}
sb_intr_active = 0;
sb_midi_busy = 0;
input_opened = 0;
sb_intr_active = 0;
sb_midi_busy = 0;
input_opened = 0;
}
static int
sb_midi_out (int dev, unsigned char midi_byte)
sb_midi_out(int dev, u_char midi_byte)
{
unsigned long flags;
u_long flags;
if (sb_midi_mode == NORMAL_MIDI)
{
DISABLE_INTR (flags);
if (sb_dsp_command (0x38))
sb_dsp_command (midi_byte);
else
printk ("SB Error: Unable to send a MIDI byte\n");
RESTORE_INTR (flags);
}
else
sb_dsp_command (midi_byte); /*
* UART write
*/
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;
return 1;
}
static int
sb_midi_start_read (int dev)
sb_midi_start_read(int dev)
{
if (sb_midi_mode != UART_MIDI)
{
printk ("SoundBlaster: MIDI input not implemented.\n");
return RET_ERROR (EPERM);
if (sb_midi_mode != UART_MIDI) {
printf("SoundBlaster: MIDI input not implemented.\n");
return -(EPERM);
}
return 0;
return 0;
}
static int
sb_midi_end_read (int dev)
sb_midi_end_read(int dev)
{
if (sb_midi_mode == UART_MIDI)
{
sb_reset_dsp ();
sb_intr_active = 0;
if (sb_midi_mode == UART_MIDI) {
sb_reset_dsp();
sb_intr_active = 0;
}
return 0;
return 0;
}
static int
sb_midi_ioctl (int dev, unsigned cmd, unsigned arg)
sb_midi_ioctl(int dev, u_int cmd, ioctl_arg arg)
{
return RET_ERROR (EPERM);
return -(EPERM);
}
void
sb_midi_interrupt (int dummy)
sb_midi_interrupt(int dummy)
{
unsigned long flags;
unsigned char data;
u_long flags;
u_char data;
DISABLE_INTR (flags);
flags = splhigh();
data = INB (DSP_READ);
if (input_opened)
midi_input_intr (my_dev, data);
data = inb(DSP_READ);
if (input_opened)
midi_input_intr(my_dev, data);
RESTORE_INTR (flags);
splx(flags);
}
#define MIDI_SYNTH_NAME "SoundBlaster Midi"
@ -215,39 +181,31 @@ sb_midi_interrupt (int dummy)
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
{"SoundBlaster", 0, 0, SNDCARD_SB},
&std_midi_synth,
{0},
sb_midi_open,
sb_midi_close,
sb_midi_ioctl,
sb_midi_out,
sb_midi_start_read,
sb_midi_end_read,
NULL, /* Kick */
NULL, /* command */
NULL, /* buffer_status */
NULL
};
void
sb_midi_init (int model)
sb_midi_init(int model)
{
if (num_midis >= MAX_MIDI_DEV)
{
printk ("Sound: Too many midi devices detected\n");
return;
if (num_midis >= MAX_MIDI_DEV) {
printf("Sound: Too many midi devices detected\n");
return;
}
std_midi_synth.midi_dev = num_midis;
my_dev = num_midis;
midi_devs[num_midis++] = &sb_midi_operations;
std_midi_synth.midi_dev = num_midis;
my_dev = num_midis;
midi_devs[num_midis++] = &sb_midi_operations;
}
#endif

View File

@ -1,11 +1,10 @@
/*
* sound/sb_mixer.c
*
*
* The low level mixer driver for the SoundBlaster Pro and SB16 cards.
*
*
* Copyright by Hannu Savolainen 1994
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
@ -13,7 +12,7 @@
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
@ -25,25 +24,24 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Modified:
* Hunyue Yau Jan 6 1994
* Added code to support the Sound Galaxy NX Pro mixer.
*
*
* Modified: Hunyue Yau Jan 6 1994 Added code to support the Sound Galaxy
* NX Pro mixer.
*
*/
#include <i386/isa/sound/sound_config.h>
#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_SB) && !defined(EXCLUDE_SBPRO)
#if (NSB > 0) && defined(CONFIG_SBPRO)
#define __SB_MIXER_C__
#include <i386/isa/sound/sb_defs.h>
#include <i386/isa/sound/sbcard.h>
#include <i386/isa/sound/sb_mixer.h>
#undef SB_TEST_IRQ
extern int sbc_base;
extern int sbc_major;
extern int Jazz16_detected;
extern sound_os_info *sb_osp;
static int mixer_initialized = 0;
@ -55,533 +53,477 @@ static int mixer_caps;
static mixer_tab *iomap;
void
sb_setmixer (unsigned int port, unsigned int value)
sb_setmixer(u_int port, u_int value)
{
unsigned long flags;
u_long flags;
DISABLE_INTR (flags);
OUTB ((unsigned char) (port & 0xff), MIXER_ADDR); /*
* Select register
*/
tenmicrosec ();
OUTB ((unsigned char) (value & 0xff), MIXER_DATA);
tenmicrosec ();
RESTORE_INTR (flags);
flags = splhigh(); /* XXX ouch... */
outb(MIXER_ADDR, (u_char) (port & 0xff)); /* Select register */
DELAY(10);
outb(MIXER_DATA, (u_char) (value & 0xff));
DELAY(10);
splx(flags);
}
int
sb_getmixer (unsigned int port)
sb_getmixer(u_int port)
{
int val;
unsigned long flags;
int val;
u_long flags;
DISABLE_INTR (flags);
OUTB ((unsigned char) (port & 0xff), MIXER_ADDR); /*
* Select register
*/
tenmicrosec ();
val = INB (MIXER_DATA);
tenmicrosec ();
RESTORE_INTR (flags);
flags = splhigh();
outb(MIXER_ADDR, (u_char) (port & 0xff)); /* Select register */
DELAY(10);
val = inb(MIXER_DATA);
DELAY(10);
splx(flags);
return val;
return val;
}
void
sb_mixer_set_stereo (int mode)
sb_mixer_set_stereo(int mode)
{
if (!mixer_initialized)
return;
if (!mixer_initialized)
return;
sb_setmixer (OUT_FILTER, ((sb_getmixer (OUT_FILTER) & ~STEREO_DAC)
| (mode ? STEREO_DAC : MONO_DAC)));
sb_setmixer(OUT_FILTER, ((sb_getmixer(OUT_FILTER) & ~STEREO_DAC)
| (mode ? STEREO_DAC : MONO_DAC)));
}
/*
* Returns:
* 0 No mixer detected.
* 1 Only a plain Sound Blaster Pro style mixer detected.
* 2 The Sound Galaxy NX Pro mixer detected.
* 0 No mixer detected.
* 1 Only a plain Sound Blaster Pro style mixer detected.
* 2 The Sound Galaxy NX Pro mixer detected.
*/
static int
detect_mixer (void)
detect_mixer(void)
{
#ifdef __SGNXPRO__
int oldbass, oldtreble;
#ifdef __SGNXPRO__
int oldbass, oldtreble;
extern int sbc_major;
#endif
int retcode = 1;
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);
/*
* 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;
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
/*
* Attempt to detect the SG NX Pro by check for valid bass/treble
* registers.
*/
oldbass = sb_getmixer (BASS_LVL);
oldtreble = sb_getmixer (TREBLE_LVL);
*/
oldbass = sb_getmixer(BASS_LVL);
oldtreble = sb_getmixer(TREBLE_LVL);
sb_setmixer (BASS_LVL, 0xaa);
sb_setmixer (TREBLE_LVL, 0x55);
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 ((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.
*
* 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 (0x01, sbc_base + 0x1c);
OUTB (0x00, sbc_base + 0x1a);
*/
if (sbc_major == 3) {
outb(sbc_base + 0x1c, 0x01);
outb(sbc_base + 0x1a, 0x00);
}
#endif
return retcode;
return retcode;
}
static void
change_bits (unsigned char *regval, int dev, int chn, int newval)
change_bits(u_char *regval, int dev, int chn, int newval)
{
unsigned char mask;
int shift;
u_char mask;
int shift;
mask = (1 << (*iomap)[dev][chn].nbits) - 1;
newval = (int) ((newval * mask) + 50) / 100; /*
* Scale it
*/
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;
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
*/
*regval &= ~(mask << shift); /* Filter out the previous value */
*regval |= (newval & mask) << shift; /* Set the new value */
}
static int
sb_mixer_get (int dev)
sb_mixer_get(int dev)
{
if (!((1 << dev) & supported_devices))
return RET_ERROR (EINVAL);
if (!((1 << dev) & supported_devices))
return -(EINVAL);
return levels[dev];
return levels[dev];
}
#ifdef JAZZ16
static char smw_mix_regs[] = /* Left mixer registers */
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 */
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)
smw_mixer_init(void)
{
int i;
int i;
sb_setmixer (0x00, 0x18); /* Mute unused (Telephone) line */
sb_setmixer (0x10, 0x38); /* Config register 2 */
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_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);
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)
smw_mixer_set(int dev, int value)
{
int left = value & 0x000000ff;
int right = (value & 0x0000ff00) >> 8;
int reg, val;
int left = value & 0x000000ff;
int right = (value & 0x0000ff00) >> 8;
int reg, val;
if (left > 100)
left = 100;
if (right > 100)
right = 100;
if (left > 100)
left = 100;
if (right > 100)
right = 100;
if (dev > 31)
return RET_ERROR (EINVAL);
if (dev > 31)
return -(EINVAL);
if (!(supported_devices & (1 << dev))) /* Not supported */
return RET_ERROR (EINVAL);
if (!(supported_devices & (1 << dev))) /* Not supported */
return -(EINVAL);
switch (dev)
{
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;
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);
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 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;
/* 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 RET_ERROR (EINVAL);
sb_setmixer (reg, (24 - (24 * left / 100)) | 0x20); /* 24=mute, 0=max */
sb_setmixer (reg + 1, (24 - (24 * right / 100)) | 0x40);
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);
levels[dev] = left | (right << 8);
return left | (right << 8);
}
#endif
static int
sb_mixer_set (int dev, int value)
sb_mixer_set(int dev, int value)
{
int left = value & 0x000000ff;
int right = (value & 0x0000ff00) >> 8;
int left = value & 0x000000ff;
int right = (value & 0x0000ff00) >> 8;
int regoffs;
unsigned char val;
int regoffs;
u_char val;
#ifdef JAZZ16
if (Jazz16_detected == 2)
return smw_mixer_set (dev, value);
if (Jazz16_detected == 2)
return smw_mixer_set(dev, value);
#endif
if (left > 100)
left = 100;
if (right > 100)
right = 100;
if (left > 100)
left = 100;
if (right > 100)
right = 100;
if (dev > 31)
return RET_ERROR (EINVAL);
if (dev > 31)
return -(EINVAL);
if (!(supported_devices & (1 << dev))) /*
* Not supported
*/
return RET_ERROR (EINVAL);
if (!(supported_devices & (1 << dev))) /* Not supported */
return -(EINVAL);
regoffs = (*iomap)[dev][LEFT_CHN].regno;
regoffs = (*iomap)[dev][LEFT_CHN].regno;
if (regoffs == 0)
return RET_ERROR (EINVAL);
if (regoffs == 0)
return -(EINVAL);
val = sb_getmixer (regoffs);
change_bits (&val, dev, LEFT_CHN, left);
val = sb_getmixer(regoffs);
change_bits(&val, dev, LEFT_CHN, left);
levels[dev] = left | (left << 8);
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 ((*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
*/
if (regoffs == 0)
return left | (left << 8); /* Just left channel present */
val = sb_getmixer (regoffs); /*
* Read the new one
*/
val = sb_getmixer(regoffs); /* Read the new one */
}
change_bits(&val, dev, RIGHT_CHN, right);
change_bits (&val, dev, RIGHT_CHN, right);
sb_setmixer(regoffs, val);
sb_setmixer (regoffs, val);
levels[dev] = left | (right << 8);
return left | (right << 8);
levels[dev] = left | (right << 8);
return left | (right << 8);
}
static void
set_recsrc (int src)
set_recsrc(int src)
{
sb_setmixer (RECORD_SRC, (sb_getmixer (RECORD_SRC) & ~7) | (src & 0x7));
sb_setmixer(RECORD_SRC, (sb_getmixer(RECORD_SRC) & ~7) | (src & 0x7));
}
static int
set_recmask (int mask)
set_recmask(int mask)
{
int devmask, i;
unsigned char regimageL, regimageR;
int devmask, i;
u_char regimageL, regimageR;
devmask = mask & supported_rec_devices;
devmask = mask & supported_rec_devices;
switch (mixer_model)
{
switch (mixer_model) {
case 3:
if (devmask != SOUND_MASK_MIC &&
devmask != SOUND_MASK_LINE &&
devmask != SOUND_MASK_CD)
{ /*
* More than one devices selected. Drop the *
* previous selection
*/
devmask &= ~recmask;
if (devmask != SOUND_MASK_MIC && devmask != SOUND_MASK_LINE &&
devmask != SOUND_MASK_CD) {
/*
* More than one devices selected. Drop the previous
* selection
*/
devmask &= ~recmask;
}
if (devmask != SOUND_MASK_MIC &&
devmask != SOUND_MASK_LINE &&
devmask != SOUND_MASK_CD)
{ /*
* More than one devices selected. Default to
* * mic
*/
devmask = SOUND_MASK_MIC;
if (devmask != SOUND_MASK_MIC && devmask != SOUND_MASK_LINE &&
devmask != SOUND_MASK_CD) {
/* More than one devices selected. Default to mic */
devmask = SOUND_MASK_MIC;
}
if (devmask ^ recmask) /*
* Input source changed
*/
{
switch (devmask)
{
if (devmask ^ recmask) { /* Input source changed */
switch (devmask) {
case SOUND_MASK_MIC:
set_recsrc (SRC_MIC);
break;
set_recsrc(SRC_MIC);
break;
case SOUND_MASK_LINE:
set_recsrc (SRC_LINE);
break;
set_recsrc(SRC_LINE);
break;
case SOUND_MASK_CD:
set_recsrc (SRC_CD);
break;
set_recsrc(SRC_CD);
break;
default:
set_recsrc (SRC_MIC);
set_recsrc(SRC_MIC);
}
}
break;
break;
case 4:
if (!devmask)
devmask = SOUND_MASK_MIC;
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;
regimageL = regimageR = 0;
for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
if ((1 << i) & devmask) {
regimageL |= sb16_recmasks_L[i];
regimageR |= sb16_recmasks_R[i];
}
sb_setmixer(SB16_IMASK_L, regimageL);
sb_setmixer(SB16_IMASK_R, regimageR);
break;
}
recmask = devmask;
return recmask;
recmask = devmask;
return recmask;
}
static int
sb_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg)
sb_mixer_ioctl(int dev, u_int cmd, ioctl_arg arg)
{
if (((cmd >> 8) & 0xff) == 'M')
{
if (cmd & IOC_IN)
switch (cmd & 0xff)
{
case SOUND_MIXER_RECSRC:
return IOCTL_OUT (arg, set_recmask (IOCTL_IN (arg)));
break;
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:
default:
return *(int *) arg = sb_mixer_set(cmd & 0xff, (*(int *) arg));
}
else
switch (cmd & 0xff) { /* Return parameters */
return IOCTL_OUT (arg, sb_mixer_set (cmd & 0xff, IOCTL_IN (arg)));
}
else
switch (cmd & 0xff) /*
* Return parameters
*/
{
case SOUND_MIXER_RECSRC:
return *(int *) arg = recmask;
break;
case SOUND_MIXER_RECSRC:
return IOCTL_OUT (arg, recmask);
break;
case SOUND_MIXER_DEVMASK:
return *(int *) arg = supported_devices;
break;
case SOUND_MIXER_DEVMASK:
return IOCTL_OUT (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_STEREODEVS:
if (Jazz16_detected)
return IOCTL_OUT (arg, supported_devices);
else
return IOCTL_OUT (arg, supported_devices &
~(SOUND_MASK_MIC | SOUND_MASK_SPEAKER));
break;
case SOUND_MIXER_RECMASK:
return *(int *) arg = supported_rec_devices;
break;
case SOUND_MIXER_RECMASK:
return IOCTL_OUT (arg, supported_rec_devices);
break;
case SOUND_MIXER_CAPS:
return *(int *) arg = mixer_caps;
break;
case SOUND_MIXER_CAPS:
return IOCTL_OUT (arg, mixer_caps);
break;
default:
return IOCTL_OUT (arg, sb_mixer_get (cmd & 0xff));
}
}
else
return RET_ERROR (EINVAL);
default:
return *(int *) arg = sb_mixer_get(cmd & 0xff);
}
} else
return -(EINVAL);
}
static struct mixer_operations sb_mixer_operations =
{
"SoundBlaster",
sb_mixer_ioctl
"SoundBlaster",
sb_mixer_ioctl
};
static void
sb_mixer_reset (void)
sb_mixer_reset(void)
{
int i;
int i;
for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
sb_mixer_set (i, levels[i]);
set_recmask (SOUND_MASK_MIC);
for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
sb_mixer_set(i, levels[i]);
set_recmask(SOUND_MASK_MIC);
}
/*
* Returns a code depending on whether a SG NX Pro was detected.
* 1 == Plain SB Pro
* 2 == SG NX Pro detected.
* 3 == SB16
*
* Returns a code depending on whether a SG NX Pro was detected. 1 == Plain
* SB Pro 2 == SG NX Pro detected. 3 == SB16
*
* Used to update message.
*/
int
sb_mixer_init (int major_model)
sb_mixer_init(int major_model)
{
int mixer_type = 0;
int mixer_type = 0;
sb_setmixer (0x00, 0); /* Reset mixer */
sb_setmixer(0x00, 0); /* Reset mixer */
if (!(mixer_type = detect_mixer ()))
return 0; /* No mixer. Why? */
if (!(mixer_type = detect_mixer()))
return 0; /* No mixer. Why? */
mixer_initialized = 1;
mixer_model = major_model;
mixer_initialized = 1;
mixer_model = major_model;
switch (major_model)
{
switch (major_model) {
case 3:
mixer_caps = SOUND_CAP_EXCL_INPUT;
mixer_caps = SOUND_CAP_EXCL_INPUT;
#ifdef JAZZ16
if (Jazz16_detected == 2) /* SM Wave */
{
supported_devices = 0;
supported_rec_devices = 0;
iomap = &sbpro_mix;
smw_mixer_init ();
mixer_type = 1;
}
else
if (Jazz16_detected == 2) { /* SM Wave */
supported_devices = 0;
supported_rec_devices = 0;
iomap = &sbpro_mix;
smw_mixer_init();
mixer_type = 1;
} else
#endif
#ifdef __SGNXPRO__
if (mixer_type == 2) /* A SGNXPRO was detected */
{
supported_devices = SGNXPRO_MIXER_DEVICES;
supported_rec_devices = SGNXPRO_RECORDING_DEVICES;
iomap = &sgnxpro_mix;
}
else
if (mixer_type == 2) { /* A SGNXPRO was detected */
supported_devices = SGNXPRO_MIXER_DEVICES;
supported_rec_devices = SGNXPRO_RECORDING_DEVICES;
iomap = &sgnxpro_mix;
} else
#endif
{
supported_devices = SBPRO_MIXER_DEVICES;
supported_rec_devices = SBPRO_RECORDING_DEVICES;
iomap = &sbpro_mix;
mixer_type = 1;
supported_devices = SBPRO_MIXER_DEVICES;
supported_rec_devices = SBPRO_RECORDING_DEVICES;
iomap = &sbpro_mix;
mixer_type = 1;
}
break;
break;
case 4:
mixer_caps = 0;
supported_devices = SB16_MIXER_DEVICES;
supported_rec_devices = SB16_RECORDING_DEVICES;
iomap = &sb16_mix;
mixer_type = 3;
break;
mixer_caps = 0;
supported_devices = SB16_MIXER_DEVICES;
supported_rec_devices = SB16_RECORDING_DEVICES;
iomap = &sb16_mix;
mixer_type = 3;
break;
default:
printk ("SB Warning: Unsupported mixer type\n");
return 0;
}
printf("SB Warning: Unsupported mixer type\n");
return 0;
}
if (num_mixers < MAX_MIXER_DEV)
mixer_devs[num_mixers++] = &sb_mixer_operations;
sb_mixer_reset ();
return mixer_type;
if (num_mixers < MAX_MIXER_DEV)
mixer_devs[num_mixers++] = &sb_mixer_operations;
sb_mixer_reset();
return mixer_type;
}
#endif

View File

@ -24,10 +24,9 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Modified:
* Hunyue Yau Jan 6 1994
* Added defines for the Sound Galaxy NX Pro mixer.
*
* Modified: Hunyue Yau Jan 6 1994 Added defines for the Sound Galaxy NX Pro
* mixer.
*
*/
@ -39,10 +38,10 @@
#define SBPRO_MIXER_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_LINE | SOUND_MASK_MIC | \
SOUND_MASK_CD | SOUND_MASK_VOLUME)
/* SG NX Pro has treble and bass settings on the mixer. The 'speaker'
* channel is the COVOX/DisneySoundSource emulation volume control
* on the mixer. It does NOT control speaker volume. Should have own
* mask eventually?
/*
* SG NX Pro has treble and bass settings on the mixer. The 'speaker' channel
* is the COVOX/DisneySoundSource emulation volume control on the mixer. It
* does NOT control speaker volume. Should have own mask eventually?
*/
#define SGNXPRO_MIXER_DEVICES (SBPRO_MIXER_DEVICES|SOUND_MASK_BASS| \
SOUND_MASK_TREBLE|SOUND_MASK_SPEAKER )
@ -61,7 +60,7 @@
* NOTE! RECORD_SRC == IN_FILTER
*/
/*
/*
* Mixer registers of SB Pro
*/
#define VOC_VOL 0x04
@ -80,7 +79,7 @@
#define OPSW 0x3c
/*
* Additional registers on the SG NX Pro
* Additional registers on the SG NX Pro
*/
#define COVOX_VOL 0x42
#define TREBLE_LVL 0x44
@ -104,9 +103,9 @@
#define RIGHT_CHN 1
struct mixer_def {
unsigned int regno: 8;
unsigned int bitoffs:4;
unsigned int nbits:4;
unsigned int regno:8;
unsigned int bitoffs:4;
unsigned int nbits:4;
};
@ -117,136 +116,136 @@ typedef struct mixer_def mixer_ent;
{{reg_l, bit_l, len_l}, {reg_r, bit_r, len_r}}
#ifdef __SB_MIXER_C__
static mixer_tab sbpro_mix = {
MIX_ENT(SOUND_MIXER_VOLUME, 0x22, 7, 4, 0x22, 3, 4),
MIX_ENT(SOUND_MIXER_BASS, 0x00, 0, 0, 0x00, 0, 0),
MIX_ENT(SOUND_MIXER_TREBLE, 0x00, 0, 0, 0x00, 0, 0),
MIX_ENT(SOUND_MIXER_SYNTH, 0x26, 7, 4, 0x26, 3, 4),
MIX_ENT(SOUND_MIXER_PCM, 0x04, 7, 4, 0x04, 3, 4),
MIX_ENT(SOUND_MIXER_SPEAKER, 0x00, 0, 0, 0x00, 0, 0),
MIX_ENT(SOUND_MIXER_LINE, 0x2e, 7, 4, 0x2e, 3, 4),
MIX_ENT(SOUND_MIXER_MIC, 0x0a, 2, 3, 0x00, 0, 0),
MIX_ENT(SOUND_MIXER_CD, 0x28, 7, 4, 0x28, 3, 4),
MIX_ENT(SOUND_MIXER_IMIX, 0x00, 0, 0, 0x00, 0, 0),
MIX_ENT(SOUND_MIXER_ALTPCM, 0x00, 0, 0, 0x00, 0, 0),
MIX_ENT(SOUND_MIXER_RECLEV, 0x00, 0, 0, 0x00, 0, 0)
mixer_tab sbpro_mix = {
MIX_ENT(SOUND_MIXER_VOLUME, 0x22, 7, 4, 0x22, 3, 4),
MIX_ENT(SOUND_MIXER_BASS, 0x00, 0, 0, 0x00, 0, 0),
MIX_ENT(SOUND_MIXER_TREBLE, 0x00, 0, 0, 0x00, 0, 0),
MIX_ENT(SOUND_MIXER_SYNTH, 0x26, 7, 4, 0x26, 3, 4),
MIX_ENT(SOUND_MIXER_PCM, 0x04, 7, 4, 0x04, 3, 4),
MIX_ENT(SOUND_MIXER_SPEAKER, 0x00, 0, 0, 0x00, 0, 0),
MIX_ENT(SOUND_MIXER_LINE, 0x2e, 7, 4, 0x2e, 3, 4),
MIX_ENT(SOUND_MIXER_MIC, 0x0a, 2, 3, 0x00, 0, 0),
MIX_ENT(SOUND_MIXER_CD, 0x28, 7, 4, 0x28, 3, 4),
MIX_ENT(SOUND_MIXER_IMIX, 0x00, 0, 0, 0x00, 0, 0),
MIX_ENT(SOUND_MIXER_ALTPCM, 0x00, 0, 0, 0x00, 0, 0),
MIX_ENT(SOUND_MIXER_RECLEV, 0x00, 0, 0, 0x00, 0, 0)
};
#ifdef __SGNXPRO__
static 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)
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
static 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)
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 */
#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 */
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 */
#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 */
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 */
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 */
0x00, /* SOUND_MIXER_VOLUME */
0x00, /* SOUND_MIXER_BASS */
0x00, /* SOUND_MIXER_TREBLE */
0x20, /* SOUND_MIXER_SYNTH */
0x00, /* SOUND_MIXER_PCM */
0x00, /* SOUND_MIXER_SPEAKER */
0x08, /* SOUND_MIXER_LINE */
0x01, /* SOUND_MIXER_MIC */
0x02, /* SOUND_MIXER_CD */
0x00, /* SOUND_MIXER_IMIX */
0x00, /* SOUND_MIXER_ALTPCM */
0x00, /* SOUND_MIXER_RECLEV */
0x00, /* SOUND_MIXER_IGAIN */
0x00 /* SOUND_MIXER_OGAIN */
};
/*
* Recording sources (SB Pro)
* Recording sources (SB Pro)
*/
#define SRC_MIC 1 /* Select Microphone recording source */

View File

@ -0,0 +1,54 @@
/*
* 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

@ -8,16 +8,17 @@ int DMAbuf_getwrbuffer(int dev, char **buf, int *size, int dontblock);
int DMAbuf_getrdbuffer(int dev, char **buf, int *len, int dontblock);
int DMAbuf_rmchars(int dev, int buff_no, int c);
int DMAbuf_start_output(int dev, int buff_no, int l);
int DMAbuf_ioctl(int dev, unsigned int cmd, unsigned int arg, int local);
long DMAbuf_init(long mem_start);
int DMAbuf_start_dma (int dev, unsigned long physaddr, int count, int dma_mode);
int DMAbuf_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_SELECT
int DMAbuf_poll(int dev, struct fileinfo *file, int events, select_table * wait);
int DMAbuf_select(int dev, struct fileinfo *file, int sel_type, select_table * wait);
#endif
/*
@ -29,12 +30,12 @@ int audio_write (int dev, struct fileinfo *file, snd_rw_buf *buf, int count);
int audio_open (int dev, struct fileinfo *file);
void audio_release (int dev, struct fileinfo *file);
int audio_ioctl (int dev, struct fileinfo *file,
unsigned int cmd, unsigned int arg);
u_int cmd, ioctl_arg arg);
int audio_lseek (int dev, struct fileinfo *file, off_t offset, int orig);
long audio_init (long mem_start);
/* long audio_init (void); */
#ifdef ALLOW_SELECT
int audio_poll(int dev, struct fileinfo *file, int events, select_table * wait);
int audio_poll(int dev, struct fileinfo *file, int events, select_table * wait);
#endif
/*
@ -46,18 +47,15 @@ int sequencer_write (int dev, struct fileinfo *file, snd_rw_buf *buf, int count)
int sequencer_open (int dev, struct fileinfo *file);
void sequencer_release (int dev, struct fileinfo *file);
int sequencer_ioctl (int dev, struct fileinfo *file,
unsigned int cmd, unsigned int arg);
u_int cmd, ioctl_arg arg);
int sequencer_lseek (int dev, struct fileinfo *file, off_t offset, int orig);
long sequencer_init (long mem_start);
void sequencer_timer(void *arg);
void sequencer_init (void);
void sequencer_timer(void *dummy);
int note_to_freq(int note_num);
unsigned long compute_finetune(unsigned long base_freq, int bend, int range);
void seq_input_event(unsigned char *event, int len);
void seq_copy_to_input (unsigned char *event, int len);
u_long compute_finetune(u_long base_freq, int bend, int range);
void seq_input_event(u_char *event, int len);
void seq_copy_to_input (u_char *event, int len);
#ifdef ALLOW_SELECT
int sequencer_poll(int dev, struct fileinfo *file, int events, select_table * wait);
#endif
/*
* System calls for the /dev/midi
@ -68,25 +66,9 @@ int MIDIbuf_write (int dev, struct fileinfo *file, snd_rw_buf *buf, int count);
int MIDIbuf_open (int dev, struct fileinfo *file);
void MIDIbuf_release (int dev, struct fileinfo *file);
int MIDIbuf_ioctl (int dev, struct fileinfo *file,
unsigned int cmd, unsigned int arg);
u_int cmd, ioctl_arg arg);
int MIDIbuf_lseek (int dev, struct fileinfo *file, off_t offset, int orig);
void MIDIbuf_bytes_received(int dev, unsigned char *buf, int count);
long MIDIbuf_init(long mem_start);
#ifdef ALLOW_SELECT
int MIDIbuf_poll(int dev, struct fileinfo *file, int events, select_table * wait);
#endif
/*
* System calls for the generic midi interface.
*
*/
long CMIDI_init (long mem_start);
int CMIDI_open (int dev, struct fileinfo *file);
int CMIDI_write (int dev, struct fileinfo *file, snd_rw_buf *buf, int count);
int CMIDI_read (int dev, struct fileinfo *file, snd_rw_buf *buf, int count);
int CMIDI_close (int dev, struct fileinfo *file);
void MIDIbuf_bytes_received(int dev, u_char *buf, int count);
/*
*
@ -94,40 +76,39 @@ int CMIDI_close (int dev, struct fileinfo *file);
*/
/* From soundcard.c */
long soundcard_init(long mem_start);
void tenmicrosec(void);
void soundcard_init(void);
void tenmicrosec(int);
void request_sound_timer (int count);
void sound_stop_timer(void);
int snd_set_irq_handler (int interrupt_level, INT_HANDLER_PROTO(), char *name);
void snd_release_irq(int vect);
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,
unsigned int cmd, unsigned long arg);
int sound_ioctl_sw (int dev, struct fileinfo *file, u_int cmd, ioctl_arg arg);
/* From sb_dsp.c */
int sb_dsp_detect (struct address_info *hw_config);
long sb_dsp_init (long mem_start, struct address_info *hw_config);
void sb_dsp_init (struct address_info *hw_config);
void sb_dsp_disable_midi(void);
int sb_get_irq(void);
void sb_free_irq(void);
int sb_dsp_command (unsigned char val);
int sb_dsp_command (u_char val);
int sb_reset_dsp (void);
/* From sb16_dsp.c */
void sb16_dsp_interrupt (int irq);
long sb16_dsp_init(long mem_start, struct address_info *hw_config);
void sb16_dsp_init(struct address_info *hw_config);
int sb16_dsp_detect(struct address_info *hw_config);
/* From sb16_midi.c */
void sb16midiintr (int unit);
long attach_sb16midi(long mem_start, struct address_info * hw_config);
void attach_sb16midi(struct address_info * hw_config);
int probe_sb16midi(struct address_info *hw_config);
void sb_midi_interrupt(int dummy);
@ -135,73 +116,76 @@ void sb_midi_interrupt(int dummy);
void sb_midi_init(int model);
/* From sb_mixer.c */
void sb_setmixer (unsigned int port, unsigned int value);
int sb_getmixer (unsigned int port);
void sb_setmixer (u_int port, u_int value);
int sb_getmixer (u_int port);
void sb_mixer_set_stereo(int mode);
int sb_mixer_init(int major_model);
/* From opl3.c */
int opl3_detect (int ioaddr);
long opl3_init(long mem_start);
int opl3_detect (int ioaddr, sound_os_info *osp);
void opl3_init(int ioaddr, sound_os_info *osp);
/* From sb_card.c */
long attach_sb_card(long mem_start, struct address_info *hw_config);
void attach_sb_card(struct address_info *hw_config);
int probe_sb(struct address_info *hw_config);
/* From adlib_card.c */
long attach_adlib_card(long mem_start, struct address_info *hw_config);
int probe_adlib(struct address_info *hw_config);
/* from awe_wave.c */
long attach_awe_obsolete(long mem_start, struct address_info *hw_config);
/* From awe_wave.c */
void attach_awe_obsolete(struct address_info *hw_config);
int probe_awe_obsolete(struct address_info *hw_config);
/* From adlib_card.c */
void attach_adlib_card(struct address_info *hw_config);
int probe_adlib(struct address_info *hw_config);
/* From pas_card.c */
long attach_pas_card(long mem_start, struct address_info *hw_config);
void attach_pas_card(struct address_info *hw_config);
int probe_pas(struct address_info *hw_config);
int pas_set_intr(int mask);
int pas_remove_intr(int mask);
unsigned char pas_read(int ioaddr);
void pas_write(unsigned char data, int ioaddr);
u_char pas_read(int ioaddr);
void pas_write(u_char data, int ioaddr);
/* From pas_audio.c */
void pas_pcm_interrupt(unsigned char status, int cause);
long pas_pcm_init(long mem_start, struct address_info *hw_config);
void pas_pcm_interrupt(u_char status, int cause);
void pas_pcm_init(struct address_info *hw_config);
/* From pas_mixer.c */
int pas_init_mixer(void);
/* From pas_midi.c */
long pas_midi_init(long mem_start);
void pas_midi_init(void);
void pas_midi_interrupt(void);
/* From gus_card.c */
long attach_gus_card(long mem_start, struct address_info * hw_config);
void attach_gus_card(struct address_info * hw_config);
int probe_gus(struct address_info *hw_config);
int gus_set_midi_irq(int num);
long attach_gus_db16(long mem_start, struct address_info * hw_config);
/*void gusintr(int irq); */
void attach_gus_db16(struct address_info * hw_config);
int probe_gus_db16(struct address_info *hw_config);
/* From gus_wave.c */
int gus_wave_detect(int baseaddr);
long gus_wave_init(long mem_start, int irq, int dma, int dma_read);
void gus_wave_init(struct address_info *hw_config);
void gus_voice_irq(void);
void gus_write8(int reg, unsigned int data);
u_char gus_read8 (int reg);
void gus_write8(int reg, u_int data);
void guswave_dma_irq(void);
void gus_delay(void);
int gus_default_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg);
int gus_default_mixer_ioctl (int dev, u_int cmd, ioctl_arg arg);
void gus_timer_command (u_int addr, u_int val);
/* From gus_midi.c */
long gus_midi_init(long mem_start);
void gus_midi_init(void);
void gus_midi_interrupt(int dummy);
/* From mpu401.c */
long attach_mpu401(long mem_start, struct address_info * hw_config);
void attach_mpu401(struct address_info * hw_config);
int probe_mpu401(struct address_info *hw_config);
void mpuintr(INT_HANDLER_PARMS(irq, dummy));
void mpuintr(int irq);
/* From uart6850.c */
long attach_uart6850(long mem_start, struct address_info * hw_config);
void attach_uart6850(struct address_info * hw_config);
int probe_uart6850(struct address_info *hw_config);
/* From opl3.c */
@ -213,51 +197,51 @@ void pmgr_release(int dev);
int pmgr_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count);
int pmgr_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count);
int pmgr_access(int dev, struct patmgr_info *rec);
int pmgr_inform(int dev, int event, unsigned long parm1, unsigned long parm2,
unsigned long parm3, unsigned long parm4);
int pmgr_inform(int dev, int event, u_long parm1, u_long parm2,
u_long parm3, u_long parm4);
/* From ics2101.c */
long ics2101_mixer_init(long mem_start);
void ics2101_mixer_init(void);
/* From sound_timer.c */
void sound_timer_init(int io_base);
void sound_timer_interrupt(void);
void sound_timer_syncinterval(u_int new_usecs);
/* From ad1848.c */
void ad1848_init (char *name, int io_base, int irq, int dma_playback, int dma_capture);
int ad1848_detect (int io_base);
void ad1848_interrupt (INT_HANDLER_PARMS(irq, dummy));
long attach_ms_sound(long mem_start, struct address_info * hw_config);
int probe_ms_sound(struct address_info *hw_config);
void ad1848_init (char *name, int io_base, int irq, int dma_playback, int dma_capture, int share_dma, sound_os_info *osp);
int ad1848_detect (int io_base, int *flags, sound_os_info *osp);
#define AD_F_CS4231 0x0001 /* Returned if a CS4232 (or compatible) detected */
#define AD_F_CS4248 0x0001 /* Returned if a CS4248 (or compatible) detected */
void ad1848_interrupt (int irq);
void attach_mss(struct address_info * hw_config);
int probe_mss(struct address_info *hw_config);
void attach_pnp_ad1848(struct address_info * hw_config);
int probe_pnp_ad1848(struct address_info *hw_config);
/* From pss.c */
int probe_pss (struct address_info *hw_config);
long attach_pss (long mem_start, struct address_info *hw_config);
void attach_pss (struct address_info *hw_config);
int probe_pss_mpu (struct address_info *hw_config);
long attach_pss_mpu (long mem_start, struct address_info *hw_config);
void attach_pss_mpu (struct address_info *hw_config);
int probe_pss_mss (struct address_info *hw_config);
long attach_pss_mss (long mem_start, 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);
long attach_sscape (long mem_start, struct address_info *hw_config);
int probe_ss_ms_sound (struct address_info *hw_config);
long attach_ss_ms_sound(long mem_start, struct address_info * hw_config);
void attach_sscape (struct address_info *hw_config);
int probe_ss_mss(struct address_info *hw_config);
void attach_ss_mss(struct address_info * hw_config);
int pss_read (int dev, struct fileinfo *file, snd_rw_buf *buf, int count);
int pss_write (int dev, struct fileinfo *file, snd_rw_buf *buf, int count);
int pss_open (int dev, struct fileinfo *file);
void pss_release (int dev, struct fileinfo *file);
int pss_ioctl (int dev, struct fileinfo *file,
unsigned int cmd, unsigned int arg);
u_int cmd, ioctl_arg arg);
int pss_lseek (int dev, struct fileinfo *file, off_t offset, int orig);
long pss_init(long mem_start);
#ifdef PC98
/* From pcm86.c */
int probe_pcm86(struct address_info *hw_config);
long attach_pcm86(long mem_start, struct address_info *hw_config);
#endif PC98
void pss_init(void);
/* From aedsp16.c */
int InitAEDSP16_SBPRO(struct address_info *hw_config);
@ -265,12 +249,35 @@ 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, unsigned char *msg, int mlen);
void do_midi_msg (int synthno, u_char *msg, int mlen);
/* From trix.c */
long attach_trix_wss (long mem_start, struct address_info *hw_config);
void attach_trix_wss (struct address_info *hw_config);
int probe_trix_wss (struct address_info *hw_config);
long attach_trix_sb (long mem_start, struct address_info *hw_config);
void attach_trix_sb (struct address_info *hw_config);
int probe_trix_sb (struct address_info *hw_config);
long attach_trix_mpu (long mem_start, 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

@ -2,8 +2,7 @@
*
* A driver for Soundcards, misc configuration parameters.
*
*
* Copyright by Hannu Savolainen 1993
* Copyright by Hannu Savolainen 1995
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@ -28,43 +27,27 @@
*
*/
#include <i386/isa/sound/local.h>
#include <i386/isa/sound/os.h>
#include <i386/isa/sound/soundvers.h>
#if !defined(PSS_MPU_BASE) && defined(EXCLUDE_SSCAPE) && defined(EXCLUDE_TRIX)
#define EXCLUDE_MPU_EMU
#endif
#if defined(ISC) || defined(SCO) || defined(SVR42)
#define GENERIC_SYSV
#endif
/*
* Disable the AD1848 driver if there are no other drivers requiring it.
* many variables should be reduced to a range. Here define a macro
*/
#if defined(EXCLUDE_GUS16) && defined(EXCLUDE_MSS) && defined(EXCLUDE_PSS) && defined(EXCLUDE_GUSMAX) && defined(EXCLUDE_SSCAPE) && defined(EXCLUDE_TRIX)
#define EXCLUDE_AD1848
#endif
#ifdef PSS_MSS_BASE
#undef EXCLUDE_AD1848
#endif
#define RANGE(var, low, high) (var) = \
((var)<(low)?(low) : (var)>(high)?(high) : (var))
#undef CONFIGURE_SOUNDCARD
#undef DYNAMIC_BUFFER
#ifdef KERNEL_SOUNDCARD
#include <i386/isa/sound/local.h>
#define CONFIGURE_SOUNDCARD
#define DYNAMIC_BUFFER
#undef LOADABLE_SOUNDCARD
#endif
#ifdef EXCLUDE_SEQUENCER
#define EXCLUDE_MIDI
#define EXCLUDE_YM3812
#define EXCLUDE_OPL3
#include <i386/isa/sound/os.h>
#include <i386/isa/sound/soundvers.h>
#if defined(ISC) || defined(SCO) || defined(SVR42)
#define GENERIC_SYSV
#endif
#ifndef SND_DEFAULT_ENABLE
@ -73,180 +56,6 @@
#ifdef CONFIGURE_SOUNDCARD
/* ****** IO-address, DMA and IRQ settings ****
If your card has nonstandard I/O address or IRQ number, change defines
for the following settings in your kernel Makefile */
#ifndef SBC_BASE
#ifdef PC98
#define SBC_BASE 0x20d2 /* 0x20d2 is the factory default. */
#else
#define SBC_BASE 0x220 /* 0x220 is the factory default. */
#endif
#endif
#ifndef SBC_IRQ
#ifdef PC98
#define SBC_IRQ 10 /* IQR10 is not the factory default on PC9821. */
#else
#define SBC_IRQ 5 /* IQR5 is the factory default. */
#endif
#endif
#ifndef SBC_DMA
#ifdef PC98
#define SBC_DMA 3
#else
#define SBC_DMA 1
#endif
#endif
#ifndef SB16_DMA
#ifdef PC98
#define SB16_DMA 3
#else
#define SB16_DMA 6
#endif
#endif
#ifndef SB16MIDI_BASE
#ifdef PC98
#define SB16MIDI_BASE 0x80d2
#else
#define SB16MIDI_BASE 0x300
#endif
#endif
#ifndef AWE32_BASE
#define AWE32_BASE 0x620 /* Default = 0x620-3, 0xA20-3, 0xE20-3 */
#endif
#ifndef PAS_BASE
#define PAS_BASE 0x388
#endif
#ifndef PAS_IRQ
#define PAS_IRQ 5
#endif
#ifndef PAS_DMA
#define PAS_DMA 3
#endif
#ifndef GUS_BASE
#define GUS_BASE 0x220
#endif
#ifndef GUS_IRQ
#define GUS_IRQ 15
#endif
#ifndef GUS_MIDI_IRQ
#define GUS_MIDI_IRQ GUS_IRQ
#endif
#ifndef GUS_DMA
#define GUS_DMA 6
#endif
#ifndef GUS_DMA_READ
#define GUS_DMA_READ 3
#endif
#ifndef MPU_BASE
#define MPU_BASE 0x330
#endif
#ifndef MPU_IRQ
#define MPU_IRQ 9
#endif
/* Echo Personal Sound System */
#ifndef PSS_BASE
#define PSS_BASE 0x220 /* 0x240 or */
#endif
#ifndef PSS_IRQ
#define PSS_IRQ 7
#endif
#ifndef PSS_DMA
#define PSS_DMA 1
#endif
#ifndef MSS_BASE
#define MSS_BASE 0
#endif
#ifndef MSS_DMA
#define MSS_DMA 0
#endif
#ifndef MSS_IRQ
#define MSS_IRQ 0
#endif
#ifndef GUS16_BASE
#define GUS16_BASE 0
#endif
#ifndef GUS16_DMA
#define GUS16_DMA 0
#endif
#ifndef GUS16_IRQ
#define GUS16_IRQ 0
#endif
#ifndef SSCAPE_BASE
#define SSCAPE_BASE 0
#endif
#ifndef SSCAPE_DMA
#define SSCAPE_DMA 0
#endif
#ifndef SSCAPE_IRQ
#define SSCAPE_IRQ 0
#endif
#ifndef SSCAPE_MSS_BASE
#define SSCAPE_MSS_BASE 0
#endif
#ifndef SSCAPE_MSS_DMA
#define SSCAPE_MSS_DMA 0
#endif
#ifndef SSCAPE_MSS_IRQ
#define SSCAPE_MSS_IRQ 0
#endif
#ifndef TRIX_BASE
#define TRIX_BASE 0x530
#endif
#ifndef TRIX_IRQ
#define TRIX_IRQ 10
#endif
#ifndef TRIX_DMA
#define TRIX_DMA 1
#endif
#ifndef U6850_BASE
#define U6850_BASE 0x330
#endif
#ifndef U6850_IRQ
#define U6850_IRQ 5
#endif
#ifndef U6850_DMA
#define U6850_DMA 1
#endif
#ifndef MAX_REALTIME_FACTOR
#define MAX_REALTIME_FACTOR 4
#endif
@ -260,22 +69,34 @@ If your card has nonstandard I/O address or IRQ number, change defines
4k for SB.
If you change the DSP_BUFFSIZE, don't modify this file.
Use the make config command instead. */
Use the make config command instead. Seems to allow only 4K, 16K,
32K, 64K.
*/
#ifndef DSP_BUFFSIZE
#define DSP_BUFFSIZE (4096)
#define DSP_BUFFSIZE (32760)
#endif
#ifndef DSP_BUFFCOUNT
#define DSP_BUFFCOUNT 2 /* 2 is recommended. */
#define DSP_BUFFCOUNT 1 /* 1 is recommended. */
#endif
#define DMA_AUTOINIT 0x10
#define DMA_AUTOINIT 0x10 /* XXX never used */
#ifdef PC98
#define FM_MONO 0x28d2 /* This is the I/O address used by AdLib */
#else
#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
@ -295,6 +116,7 @@ If your card has nonstandard I/O address or IRQ number, change defines
*/
#define SND_NDEVS 256 /* Number of supported devices */
#define SND_DEV_CTL 0 /* Control port /dev/mixer */
#define SND_DEV_SEQ 1 /* Sequencer output /dev/sequencer (FM
synthesizer and MIDI output) */
@ -304,7 +126,7 @@ If your card has nonstandard I/O address or IRQ number, change defines
#define SND_DEV_DSP16 5 /* Like /dev/dsp but 16 bits/sample */
#define SND_DEV_STATUS 6 /* /dev/sndstat */
/* #7 not in use now. Was in 2.4. Free for use after v3.0. */
#define SND_DEV_SEQ2 8 /* /dev/sequecer, level 2 interface */
#define SND_DEV_SEQ2 8 /* /dev/sequencer, level 2 interface */
#define SND_DEV_SNDPROC 9 /* /dev/sndproc for programmable devices */
#define SND_DEV_PSS SND_DEV_SNDPROC
@ -320,34 +142,38 @@ If your card has nonstandard I/O address or IRQ number, change defines
#define MAX_TIMER_DEV 3
struct fileinfo {
int mode; /* Open mode */
DECLARE_FILE(); /* Reference to file-flags. OS-dependent. */
};
int mode; /* Open mode */
int flags;
int dummy; /* Reference to file-flags. OS-dependent. */
};
struct address_info {
int io_base;
int irq;
int dma; /* write dma channel */
int dma_read; /* read dma channel */
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];
};
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];
};
int pgm_num;
int bender_value;
unsigned char controllers[128];
};
/*
* Process wakeup reasons
@ -358,9 +184,9 @@ struct channel_info {
#define WK_SIGNAL 0x04
#define WK_SLEEP 0x08
#define OPEN_READ 1
#define OPEN_WRITE 2
#define OPEN_READWRITE 3
#define OPEN_READ PCM_ENABLE_INPUT
#define OPEN_WRITE PCM_ENABLE_OUTPUT
#define OPEN_READWRITE (OPEN_READ|OPEN_WRITE)
#include <i386/isa/sound/sound_calls.h>
#include <i386/isa/sound/dev_table.h>
@ -368,9 +194,9 @@ struct channel_info {
#ifndef DEB
#define DEB(x)
#endif
#ifndef AUDIO_DDB
#define AUDIO_DDB(x)
#ifndef DDB
/* #define DDB(x) x XXX */
#define DDB(x)
#endif
#define TIMER_ARMED 121234

View File

@ -0,0 +1,186 @@
/*
* 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,10 +1,10 @@
/*
* sound/sound_switch.c
*
*
* The system call switch
*
*
* Copyright by Hannu Savolainen 1993
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
@ -12,7 +12,7 @@
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
@ -24,27 +24,14 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*
*/
#include <i386/isa/sound/sound_config.h>
#ifdef CONFIGURE_SOUNDCARD
#if NSND > 0
struct sbc_device
{
int usecount;
};
static struct sbc_device sbc_devices[SND_NDEVS] =
{
{0}};
static int in_use = 0; /*
* * * * Total # of open device files
* (excluding * * * minor 0) */
#define SNDSTAT_BUF_SIZE 4000
/*
* /dev/sndstatus -device
@ -54,491 +41,459 @@ static int status_len, status_ptr;
static int status_busy = 0;
static int
put_status (char *s)
put_status(char *s)
{
int l;
int l = strlen(s);
for (l = 0; l < 256, s[l]; l++); /*
* l=strlen(s);
*/
if (status_len + l >= SNDSTAT_BUF_SIZE)
return 0;
if (status_len + l >= 4000)
return 0;
bcopy(s, &status_buf[status_len], l);
status_len += l;
memcpy (&status_buf[status_len], s, l);
status_len += l;
return 1;
return 1;
}
/*
* in principle, we never overflow the buffer. But... if radix=2 ...
* and if smaller... lr970711
*/
static int
put_status_int (unsigned int val, int radix)
put_status_int(u_int val, int radix)
{
int l, v;
int l, v;
static char hx[] = "0123456789abcdef";
char buf[33]; /* int is 32 bit+null, in base 2 */
static char hx[] = "0123456789abcdef";
char buf[11];
if (radix < 2 || radix > 16) /* better than panic */
return put_status("???");
if (!val)
return put_status ("0");
if (!val)
return put_status("0");
l = 0;
buf[10] = 0;
l = 0;
buf[10] = 0;
while (val)
{
v = val % radix;
val = val / radix;
while (val) {
v = val % radix;
val = val / radix;
buf[9 - l] = hx[v];
l++;
buf[9 - l] = hx[v];
l++;
}
if (status_len + l >= 4000)
return 0;
if (status_len + l >= SNDSTAT_BUF_SIZE)
return 0;
memcpy (&status_buf[status_len], &buf[10 - l], l);
status_len += l;
bcopy(&buf[10 - l], &status_buf[status_len], l);
status_len += l;
return 1;
return 1;
}
static void
init_status (void)
init_status(void)
{
/*
* Write the status information to the status_buf and update status_len.
* There is a limit of 4000 bytes for the data.
*/
/*
* 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;
int i;
status_ptr = 0;
status_ptr = 0;
put_status ("VoxWare Sound Driver:" SOUND_VERSION_STRING
" (" SOUND_CONFIG_DATE " " SOUND_CONFIG_BY "@"
SOUND_CONFIG_HOST "." SOUND_CONFIG_DOMAIN ")"
"\n");
if (!put_status ("Config options: "))
return;
if (!put_status_int (SELECTED_SOUND_OPTIONS, 16))
return;
if (!put_status ("\n\nInstalled drivers: \n"))
return;
for (i = 0; i < (num_sound_drivers - 1); i++)
{
if (!put_status ("Type "))
return;
if (!put_status_int (sound_drivers[i].card_type, 10))
return;
if (!put_status (": "))
return;
if (!put_status (sound_drivers[i].name))
return;
if (!put_status ("\n"))
return;
}
if (!put_status ("\n\nCard config: \n"))
return;
for (i = 0; i < (num_sound_cards - 1); i++)
{
int drv;
if (!snd_installed_cards[i].enabled)
if (!put_status ("("))
return;
/*
* if (!put_status_int(snd_installed_cards[i].card_type, 10)) return;
* if (!put_status (": ")) return;
*/
if ((drv = snd_find_driver (snd_installed_cards[i].card_type)) != -1)
if (!put_status (sound_drivers[drv].name))
return;
if (!put_status (" at 0x"))
return;
if (!put_status_int (snd_installed_cards[i].config.io_base, 16))
return;
if (!put_status (" irq "))
return;
if (!put_status_int (snd_installed_cards[i].config.irq, 10))
return;
#ifdef PC98
if (snd_installed_cards[i].config.dma >= 0) {
#endif
if (!put_status (" drq "))
return;
if (!put_status_int (snd_installed_cards[i].config.dma, 10))
return;
#ifdef PC98
}
#endif
if (!snd_installed_cards[i].enabled)
if (!put_status (")"))
return;
if (!put_status ("\n"))
return;
}
#ifdef EXCLUDE_AUDIO
if (!put_status ("\nAudio devices: NOT ENABLED IN CONFIG\n"))
return;
#ifdef SOUND_UNAME_A
put_status("VoxWare Sound Driver:" SOUND_VERSION_STRING
" (" SOUND_CONFIG_DATE " " SOUND_CONFIG_BY ",\n"
SOUND_UNAME_A ")\n");
#else
if (!put_status ("\nAudio devices:\n"))
return;
for (i = 0; i < num_audiodevs; i++)
{
if (!put_status_int (i, 10))
return;
if (!put_status (": "))
return;
if (!put_status (audio_devs[i]->name))
return;
if (!put_status ("\n"))
return;
}
put_status("VoxWare Sound Driver:" SOUND_VERSION_STRING
" (" SOUND_CONFIG_DATE " " SOUND_CONFIG_BY "@"
SOUND_CONFIG_HOST "." SOUND_CONFIG_DOMAIN ")\n");
#endif
#ifdef EXCLUDE_SEQUENCER
if (!put_status ("\nSynth devices: NOT ENABLED IN CONFIG\n"))
return;
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
if (!put_status ("\nSynth devices:\n"))
return;
put_status("\nAudio devices:\n") ;
for (i = 0; i < num_synths; i++)
{
if (!put_status_int (i, 10))
return;
if (!put_status (": "))
return;
if (!put_status (synth_devs[i]->info->name))
return;
if (!put_status ("\n"))
return;
for (i = 0; i < num_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
#ifdef EXCLUDE_MIDI
if (!put_status ("\nMidi devices: NOT ENABLED IN CONFIG\n"))
return;
#ifndef CONFIG_SEQUENCER
put_status("\nSynth devices: NOT ENABLED IN CONFIG\n");
#else
if (!put_status ("\nMidi devices:\n"))
return;
put_status("\nSynth devices:\n") ;
for (i = 0; i < num_midis; i++)
{
if (!put_status_int (i, 10))
return;
if (!put_status (": "))
return;
if (!put_status (midi_devs[i]->info.name))
return;
if (!put_status ("\n"))
return;
for (i = 0; i < num_synths; i++) {
put_status_int(i, 10) ;
put_status(": ") ;
put_status(synth_devs[i]->info->name) ;
put_status("\n") ;
}
#endif
if (!put_status ("\nTimers:\n"))
return;
#ifndef CONFIG_MIDI
put_status("\nMidi devices: NOT ENABLED IN CONFIG\n") ;
#else
put_status("\nMidi devices:\n") ;
for (i = 0; i < num_sound_timers; i++)
{
if (!put_status_int (i, 10))
return;
if (!put_status (": "))
return;
if (!put_status (sound_timer_devs[i]->info.name))
return;
if (!put_status ("\n"))
return;
for (i = 0; i < num_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");
}
if (!put_status ("\nMixers:\n"))
return;
put_status("\nMixers:\n");
for (i = 0; i < num_mixers; i++)
{
if (!put_status_int (i, 10))
return;
if (!put_status (": "))
return;
if (!put_status (mixer_devs[i]->name))
return;
if (!put_status ("\n"))
return;
for (i = 0; i < num_mixers; i++) {
put_status_int(i, 10);
put_status(": ");
put_status(mixer_devs[i]->name);
put_status("\n");
}
}
static int
read_status (snd_rw_buf * buf, int count)
read_status(snd_rw_buf * buf, int count)
{
/*
* Return at most 'count' bytes from the status_buf.
*/
int l, c;
/*
* Return at most 'count' bytes from the status_buf.
*/
int l, c;
l = count;
c = status_len - status_ptr;
l = count;
c = status_len - status_ptr;
if (l > c)
l = c;
if (l <= 0)
return 0;
if (l > c)
l = c;
if (l <= 0)
return 0;
COPY_TO_USER (buf, 0, &status_buf[status_ptr], l);
status_ptr += l;
return l;
if (uiomove(&status_buf[status_ptr], l, buf)) {
printf("sb: Bad copyout()!\n");
};
status_ptr += l;
return l;
}
int
sound_read_sw (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
sound_read_sw(int dev, struct fileinfo * file, snd_rw_buf * buf, int count)
{
DEB (printk ("sound_read_sw(dev=%d, count=%d)\n", dev, count));
DEB(printf("sound_read_sw(dev=%d, count=%d)\n", dev, count));
switch (dev & 0x0f)
{
switch (dev & 0x0f) {
case SND_DEV_STATUS:
return read_status (buf, count);
break;
return read_status(buf, count);
break;
#ifdef CONFIG_AUDIO
case SND_DEV_DSP:
case SND_DEV_DSP16:
case SND_DEV_AUDIO:
return audio_read (dev, file, buf, count);
break;
return audio_read(dev, file, buf, count);
break;
#endif
#ifdef CONFIG_SEQUENCER
case SND_DEV_SEQ:
case SND_DEV_SEQ2:
return sequencer_read (dev, file, buf, count);
break;
return sequencer_read(dev, file, buf, count);
break;
#endif
#ifndef EXCLUDE_MIDI
#ifdef CONFIG_MIDI
case SND_DEV_MIDIN:
return MIDIbuf_read (dev, file, buf, count);
return MIDIbuf_read(dev, file, buf, count);
#endif
default:
printk ("Sound: Undefined minor device %d\n", dev);
printf("Sound: Undefined minor device %d\n", dev);
}
return RET_ERROR (EPERM);
return -(EPERM);
}
int
sound_write_sw (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
sound_write_sw(int dev, struct fileinfo * file, snd_rw_buf * buf, int count)
{
DEB (printk ("sound_write_sw(dev=%d, count=%d)\n", dev, count));
DEB(printf("sound_write_sw(dev=%d, count=%d)\n", dev, count));
switch (dev & 0x0f)
{
switch (dev & 0x0f) {
#ifdef CONFIG_SEQUENCER
case SND_DEV_SEQ:
case SND_DEV_SEQ2:
return sequencer_write (dev, file, buf, count);
break;
return sequencer_write(dev, file, buf, count);
break;
#endif
#ifdef CONFIG_AUDIO
case SND_DEV_DSP:
case SND_DEV_DSP16:
case SND_DEV_AUDIO:
return audio_write (dev, file, buf, count);
break;
return audio_write(dev, file, buf, count);
break;
#endif
#ifndef EXCLUDE_MIDI
#ifdef CONFIG_MIDI
case SND_DEV_MIDIN:
return MIDIbuf_write (dev, file, buf, count);
return MIDIbuf_write(dev, file, buf, count);
#endif
default:
return RET_ERROR (EPERM);
return -(EPERM);
}
return count;
return count;
}
int
sound_open_sw (int dev, struct fileinfo *file)
sound_open_sw(int dev, struct fileinfo * file)
{
int retval;
int retval;
DEB (printk ("sound_open_sw(dev=%d) : usecount=%d\n", dev, sbc_devices[dev].usecount));
DEB(printf("sound_open_sw(dev=%d)\n", dev));
if ((dev >= SND_NDEVS) || (dev < 0))
{
printk ("Invalid minor device %d\n", dev);
return RET_ERROR (ENXIO);
if ((dev >= SND_NDEVS) || (dev < 0)) {
printf("Invalid minor device %d\n", dev);
return -(ENXIO);
}
switch (dev & 0x0f)
{
switch (dev & 0x0f) {
case SND_DEV_STATUS:
if (status_busy)
return RET_ERROR (EBUSY);
status_busy = 1;
if ((status_buf = (char *) KERNEL_MALLOC (4000)) == NULL)
return RET_ERROR (EIO);
status_len = status_ptr = 0;
init_status ();
break;
if (status_busy)
return -(EBUSY);
status_busy = 1;
if ((status_buf = (char *) malloc(SNDSTAT_BUF_SIZE, M_TEMP, M_WAITOK)) == NULL)
return -(EIO);
status_len = status_ptr = 0;
init_status();
break;
case SND_DEV_CTL:
return 0;
break;
return 0;
break;
#ifdef CONFIG_SEQUENCER
case SND_DEV_SEQ:
case SND_DEV_SEQ2:
if ((retval = sequencer_open (dev, file)) < 0)
return retval;
break;
#ifndef EXCLUDE_MIDI
case SND_DEV_MIDIN:
if ((retval = MIDIbuf_open (dev, file)) < 0)
return retval;
break;
if ((retval = sequencer_open(dev, file)) < 0)
return retval;
break;
#endif
#ifdef CONFIG_MIDI
case SND_DEV_MIDIN:
if ((retval = MIDIbuf_open(dev, file)) < 0)
return retval;
break;
#endif
#ifdef CONFIG_AUDIO
case SND_DEV_DSP:
case SND_DEV_DSP16:
case SND_DEV_AUDIO:
if ((retval = audio_open (dev, file)) < 0)
return retval;
break;
if ((retval = audio_open(dev, file)) < 0)
return retval;
break;
#endif
default:
printk ("Invalid minor device %d\n", dev);
return RET_ERROR (ENXIO);
printf("Invalid minor device %d\n", dev);
return -(ENXIO);
}
sbc_devices[dev].usecount++;
in_use++;
return 0;
return 0;
}
void
sound_release_sw (int dev, struct fileinfo *file)
sound_release_sw(int dev, struct fileinfo * file)
{
DEB (printk ("sound_release_sw(dev=%d)\n", dev));
DEB(printf("sound_release_sw(dev=%d)\n", dev));
switch (dev & 0x0f)
{
switch (dev & 0x0f) {
case SND_DEV_STATUS:
if (status_buf)
KERNEL_FREE (status_buf);
status_buf = NULL;
status_busy = 0;
break;
if (status_buf)
free(status_buf, M_TEMP);
status_buf = NULL;
status_busy = 0;
break;
case SND_DEV_CTL:
break;
break;
#ifdef CONFIG_SEQUENCER
case SND_DEV_SEQ:
case SND_DEV_SEQ2:
sequencer_release (dev, file);
break;
#ifndef EXCLUDE_MIDI
case SND_DEV_MIDIN:
MIDIbuf_release (dev, file);
break;
sequencer_release(dev, file);
break;
#endif
#ifdef CONFIG_MIDI
case SND_DEV_MIDIN:
MIDIbuf_release(dev, file);
break;
#endif
#ifdef CONFIG_AUDIO
case SND_DEV_DSP:
case SND_DEV_DSP16:
case SND_DEV_AUDIO:
audio_release (dev, file);
break;
audio_release(dev, file);
break;
#endif
default:
printk ("Sound error: Releasing unknown device 0x%02x\n", dev);
printf("Sound error: Releasing unknown device 0x%02x\n", dev);
}
sbc_devices[dev].usecount--;
in_use--;
}
int
sound_ioctl_sw (int dev, struct fileinfo *file,
unsigned int cmd, unsigned long arg)
sound_ioctl_sw(int dev, struct fileinfo * file, u_int cmd, ioctl_arg arg)
{
DEB (printk ("sound_ioctl_sw(dev=%d, cmd=0x%x, arg=0x%x)\n", dev, cmd, arg));
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;
if (((cmd >> 8) & 0xff) == 'M' && num_mixers > 0) /* Mixer ioctl */
if ((dev & 0x0f) != SND_DEV_CTL) {
int dtype = dev & 0x0f;
int mixdev;
switch (dtype)
{
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 RET_ERROR (ENXIO);
return mixer_devs[mixdev]->ioctl (mixdev, cmd, arg);
break;
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)
{
default:
return mixer_devs[0]->ioctl(0, cmd, arg);
}
}
switch (dev & 0x0f) {
case SND_DEV_CTL:
if (!num_mixers)
return RET_ERROR (ENXIO);
if (!num_mixers)
return -(ENXIO);
dev = dev >> 4;
dev = dev >> 4;
if (dev >= num_mixers)
return RET_ERROR (ENXIO);
if (dev >= num_mixers)
return -(ENXIO);
return mixer_devs[dev]->ioctl (dev, cmd, arg);
break;
return mixer_devs[dev]->ioctl(dev, cmd, arg);
break;
#ifdef CONFIG_SEQUENCER
case SND_DEV_SEQ:
case SND_DEV_SEQ2:
return sequencer_ioctl (dev, file, cmd, arg);
break;
return sequencer_ioctl(dev, file, cmd, arg);
break;
#endif
#ifdef CONFIG_AUDIO
case SND_DEV_DSP:
case SND_DEV_DSP16:
case SND_DEV_AUDIO:
return audio_ioctl (dev, file, cmd, arg);
break;
return audio_ioctl(dev, file, cmd, arg);
break;
#endif
#ifndef EXCLUDE_MIDI
#ifdef CONFIG_MIDI
case SND_DEV_MIDIN:
return MIDIbuf_ioctl (dev, file, cmd, arg);
break;
return MIDIbuf_ioctl(dev, file, cmd, arg);
break;
#endif
default:
return RET_ERROR (EPERM);
break;
return -(EPERM);
break;
}
return RET_ERROR (EPERM);
return -(EPERM);
}
#endif

View File

@ -1,11 +1,8 @@
/*
* sound/sound_timer.c
*
* Timer for the level 2 interface of the /dev/sequencer. Uses the
* 80 and 320 usec timers of OPL-3 (PAS16 only) and GUS.
*
*
* Copyright by Hannu Savolainen 1993
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
@ -13,7 +10,7 @@
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
@ -25,381 +22,322 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*
*/
#define SEQUENCER_C
#include <i386/isa/sound/sound_config.h>
#ifdef CONFIGURE_SOUNDCARD
#if NSND > 0
#if !defined(EXCLUDE_SEQUENCER) && (!defined(EXCLUDE_GUS) || (!defined(EXCLUDE_PAS) && !defined(EXCLUDE_YM3812)))
#if defined(CONFIG_SEQUENCER)
static volatile int initialized = 0, opened = 0, tmr_running = 0;
static volatile time_t tmr_offs, tmr_ctr;
static volatile unsigned long ticks_offs;
static volatile u_long ticks_offs;
static volatile int curr_tempo, curr_timebase;
static volatile unsigned long curr_ticks;
static volatile unsigned long next_event_time;
static unsigned long prev_event_time;
static volatile int select_addr, data_addr;
static volatile int curr_timer = 0;
static volatile unsigned long usecs_per_tmr; /* Length of the current interval */
static volatile u_long curr_ticks;
static volatile u_long next_event_time;
static u_long prev_event_time;
static volatile u_long usecs_per_tmr; /* Length of the current interval */
static struct sound_lowlev_timer *tmr = NULL;
static void
timer_command (unsigned int addr, unsigned int val)
static u_long
tmr2ticks(int tmr_value)
{
int i;
/*
* Convert timer ticks to MIDI ticks
*/
OUTB ((unsigned char) (addr & 0xff), select_addr);
u_long tmp;
u_long scale;
for (i = 0; i < 2; i++)
INB (select_addr);
tmp = tmr_value * usecs_per_tmr; /* Convert to usecs */
OUTB ((unsigned char) (val & 0xff), data_addr);
scale = (60 * 1000000) / (curr_tempo * curr_timebase); /* usecs per MIDI tick */
for (i = 0; i < 2; i++)
INB (select_addr);
return (tmp + (scale / 2)) / scale;
}
static void
arm_timer (int timer, unsigned int interval)
reprogram_timer(void)
{
u_long usecs_per_tick;
curr_timer = timer;
usecs_per_tick = (60 * 1000000) / (curr_tempo * curr_timebase);
if (timer == 1)
{
gus_write8 (0x46, 256 - interval); /* Set counter for timer 1 */
gus_write8 (0x45, 0x04); /* Enable timer 1 IRQ */
timer_command (0x04, 0x01); /* Start timer 1 */
}
else
{
gus_write8 (0x47, 256 - interval); /* Set counter for timer 2 */
gus_write8 (0x45, 0x08); /* Enable timer 2 IRQ */
timer_command (0x04, 0x02); /* Start timer 2 */
}
}
static unsigned long
tmr2ticks (int tmr_value)
{
/*
* Convert timer ticks to MIDI ticks
*/
unsigned long tmp;
unsigned 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)
{
unsigned long usecs_per_tick;
int timer_no, resolution;
int divisor;
usecs_per_tick = (60 * 1000000) / (curr_tempo * curr_timebase);
/*
/*
* Don't kill the system by setting too high timer rate
*/
if (usecs_per_tick < 2000)
usecs_per_tick = 2000;
*/
if (usecs_per_tick < 2000)
usecs_per_tick = 2000;
if (usecs_per_tick > (256 * 80))
{
timer_no = 2;
resolution = 320; /* usec */
}
else
{
timer_no = 1;
resolution = 80; /* usec */
}
usecs_per_tmr = tmr->tmr_start(tmr->dev, usecs_per_tick);
}
divisor = (usecs_per_tick + (resolution / 2)) / resolution;
usecs_per_tmr = divisor * resolution;
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;
arm_timer (timer_no, divisor);
usecs_per_tmr = new_usecs;
}
static void
tmr_reset (void)
tmr_reset(void)
{
unsigned long flags;
u_long flags;
DISABLE_INTR (flags);
tmr_offs = 0;
ticks_offs = 0;
tmr_ctr = 0;
next_event_time = 0xffffffff;
prev_event_time = 0;
curr_ticks = 0;
RESTORE_INTR (flags);
flags = splhigh();
tmr_offs = 0;
ticks_offs = 0;
tmr_ctr = 0;
next_event_time = 0xffffffff;
prev_event_time = 0;
curr_ticks = 0;
splx(flags);
}
static int
timer_open (int dev, int mode)
timer_open(int dev, int mode)
{
if (opened)
return RET_ERROR (EBUSY);
if (opened)
return -(EBUSY);
tmr_reset ();
curr_tempo = 60;
curr_timebase = HZ;
opened = 1;
reprogram_timer ();
tmr_reset();
curr_tempo = 60;
curr_timebase = hz;
opened = 1;
reprogram_timer();
return 0;
return 0;
}
static void
timer_close (int dev)
timer_close(int dev)
{
opened = tmr_running = 0;
gus_write8 (0x45, 0); /* Disable both timers */
opened = tmr_running = 0;
tmr->tmr_disable(tmr->dev);
}
static int
timer_event (int dev, unsigned char *event)
timer_event(int dev, u_char *event)
{
unsigned char cmd = event[1];
unsigned long parm = *(int *) &event[4];
u_char cmd = event[1];
u_long parm = *(int *) &event[4];
switch (cmd)
{
switch (cmd) {
case TMR_WAIT_REL:
parm += prev_event_time;
parm += prev_event_time;
case TMR_WAIT_ABS:
if (parm > 0)
{
long time;
if (parm > 0) {
long time;
if (parm <= curr_ticks) /* It's the time */
return TIMER_NOT_ARMED;
if (parm <= curr_ticks) /* It's the time */
return TIMER_NOT_ARMED;
time = parm;
next_event_time = prev_event_time = time;
time = parm;
next_event_time = prev_event_time = time;
return TIMER_ARMED;
return TIMER_ARMED;
}
break;
break;
case TMR_START:
tmr_reset ();
tmr_running = 1;
reprogram_timer ();
break;
tmr_reset();
tmr_running = 1;
reprogram_timer();
break;
case TMR_STOP:
tmr_running = 0;
break;
tmr_running = 0;
break;
case TMR_CONTINUE:
tmr_running = 1;
reprogram_timer ();
break;
tmr_running = 1;
reprogram_timer();
break;
case TMR_TEMPO:
if (parm)
{
if (parm < 8)
parm = 8;
if (parm > 250)
parm = 250;
tmr_offs = tmr_ctr;
ticks_offs += tmr2ticks (tmr_ctr);
tmr_ctr = 0;
curr_tempo = parm;
reprogram_timer ();
if (parm) {
if (parm < 8)
parm = 8;
if (parm > 250)
parm = 250;
tmr_offs = tmr_ctr;
ticks_offs += tmr2ticks(tmr_ctr);
tmr_ctr = 0;
curr_tempo = parm;
reprogram_timer();
}
break;
break;
case TMR_ECHO:
seq_copy_to_input (event, 8);
break;
seq_copy_to_input(event, 8);
break;
default:;
}
return TIMER_NOT_ARMED;
return TIMER_NOT_ARMED;
}
static unsigned long
timer_get_time (int dev)
static u_long
timer_get_time(int dev)
{
if (!opened)
return 0;
if (!opened)
return 0;
return curr_ticks;
return curr_ticks;
}
static int
timer_ioctl (int dev,
unsigned int cmd, unsigned int arg)
timer_ioctl(int dev, u_int cmd, ioctl_arg arg)
{
switch (cmd)
{
switch (cmd) {
case SNDCTL_TMR_SOURCE:
return IOCTL_OUT (arg, TMR_INTERNAL);
break;
return *(int *) arg = TMR_INTERNAL;
break;
case SNDCTL_TMR_START:
tmr_reset ();
tmr_running = 1;
return 0;
break;
tmr_reset();
tmr_running = 1;
return 0;
break;
case SNDCTL_TMR_STOP:
tmr_running = 0;
return 0;
break;
tmr_running = 0;
return 0;
break;
case SNDCTL_TMR_CONTINUE:
tmr_running = 1;
return 0;
break;
tmr_running = 1;
return 0;
break;
case SNDCTL_TMR_TIMEBASE:
{
int val = IOCTL_IN (arg);
{
int val = (*(int *) arg);
if (val)
{
if (val < 1)
val = 1;
if (val > 1000)
val = 1000;
curr_timebase = val;
}
return IOCTL_OUT (arg, curr_timebase);
}
break;
if (val) {
if (val < 1)
val = 1;
if (val > 1000)
val = 1000;
curr_timebase = val;
}
return *(int *) arg = curr_timebase;
}
break;
case SNDCTL_TMR_TEMPO:
{
int val = IOCTL_IN (arg);
{
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 IOCTL_OUT (arg, curr_tempo);
}
break;
if (val) {
if (val < 8)
val = 8;
if (val > 250)
val = 250;
tmr_offs = tmr_ctr;
ticks_offs += tmr2ticks(tmr_ctr);
tmr_ctr = 0;
curr_tempo = val;
reprogram_timer();
}
return *(int *) arg = curr_tempo;
}
break;
case SNDCTL_SEQ_CTRLRATE:
if (IOCTL_IN (arg) != 0) /* Can't change */
return RET_ERROR (EINVAL);
if ((*(int *) arg) != 0) /* Can't change */
return -(EINVAL);
return IOCTL_OUT (arg, ((curr_tempo * curr_timebase) + 30) / 60);
break;
return *(int *) arg = ((curr_tempo * curr_timebase) + 30) / 60;
break;
case SNDCTL_TMR_METRONOME:
/* NOP */
break;
/* NOP */
break;
default:
default:;
}
return RET_ERROR (EINVAL);
return -(EINVAL);
}
static void
timer_arm (int dev, long time)
timer_arm(int dev, long time)
{
if (time < 0)
time = curr_ticks + 1;
else if (time <= curr_ticks) /* It's the time */
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;
next_event_time = prev_event_time = time;
return;
}
static struct sound_timer_operations sound_timer =
{
{"OPL-3/GUS Timer", 0},
1, /* Priority */
0, /* Local device link */
timer_open,
timer_close,
timer_event,
timer_get_time,
timer_ioctl,
timer_arm
{"GUS Timer", 0},
1, /* Priority */
0, /* Local device link */
timer_open,
timer_close,
timer_event,
timer_get_time,
timer_ioctl,
timer_arm
};
void
sound_timer_interrupt (void)
sound_timer_interrupt(void)
{
gus_write8 (0x45, 0); /* Ack IRQ */
timer_command (4, 0x80); /* Reset IRQ flags */
if (!opened)
return;
if (!opened)
return;
tmr->tmr_restart(tmr->dev);
if (curr_timer == 1)
gus_write8 (0x45, 0x04); /* Start timer 1 again */
else
gus_write8 (0x45, 0x08); /* Start timer 2 again */
if (!tmr_running)
return;
if (!tmr_running)
return;
tmr_ctr++;
curr_ticks = ticks_offs + tmr2ticks(tmr_ctr);
tmr_ctr++;
curr_ticks = ticks_offs + tmr2ticks (tmr_ctr);
if (curr_ticks >= next_event_time)
{
next_event_time = 0xffffffff;
sequencer_timer (NULL);
if (curr_ticks >= next_event_time) {
next_event_time = 0xffffffff;
sequencer_timer(0);
}
}
void
sound_timer_init (int io_base)
sound_timer_init(struct sound_lowlev_timer * t, char *name)
{
int n;
int n;
if (initialized)
return; /* There is already a similar timer */
if (initialized || t == NULL)
return; /* There is already a similar timer */
select_addr = io_base;
data_addr = io_base + 1;
initialized = 1;
tmr = t;
initialized = 1;
if (num_sound_timers >= MAX_TIMER_DEV)
n = 0; /* Overwrite the system timer */
else
n = num_sound_timers++;
#if 1
if (num_sound_timers >= MAX_TIMER_DEV)
n = 0; /* Overwrite the system timer */
else
n = num_sound_timers++;
#else
n = 0;
#endif
strcpy(sound_timer.info.name, name);
sound_timer_devs[n] = &sound_timer;
sound_timer_devs[n] = &sound_timer;
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1 +1,2 @@
#define SOUND_VERSION_STRING "3.0-beta-950506"
#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,11 +1,11 @@
/*
* sound/sys_timer.c
*
* The default timer for the Level 2 sequencer interface
* Uses the (100HZ) timer of kernel.
*
*
* The default timer for the Level 2 sequencer interface.
* Uses the (100hz) timer of kernel.
*
* Copyright by Hannu Savolainen 1993
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
@ -13,7 +13,7 @@
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
@ -25,280 +25,252 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*
*/
#define SEQUENCER_C
#include <i386/isa/sound/sound_config.h>
#ifdef CONFIGURE_SOUNDCARD
#if NSND > 0
#ifndef EXCLUDE_SEQUENCER
#if defined(CONFIG_SEQUENCER)
static volatile int opened = 0, tmr_running = 0;
static volatile time_t tmr_offs, tmr_ctr;
static volatile unsigned long ticks_offs;
static volatile u_long ticks_offs;
static volatile int curr_tempo, curr_timebase;
static volatile unsigned long curr_ticks;
static volatile unsigned long next_event_time;
static unsigned long prev_event_time;
static volatile u_long curr_ticks;
static volatile u_long next_event_time;
static u_long prev_event_time;
static void poll_def_tmr (void *dummy);
static void poll_def_tmr(void *dummy);
DEFINE_TIMER (def_tmr, poll_def_tmr);
static unsigned long
tmr2ticks (int tmr_value)
static u_long
tmr2ticks(int tmr_value)
{
/*
* Convert system timer ticks (HZ) to MIDI ticks
*/
/*
* Convert system timer ticks (hz) to MIDI ticks (divide # of MIDI
* ticks/minute by # of system ticks/minute).
*/
unsigned long tmp;
unsigned long scale;
tmp = (tmr_value * 1000) / HZ; /* Convert to msecs */
scale = (60 * 1000) / (curr_tempo * curr_timebase); /* msecs per MIDI tick */
return (tmp + (scale / 2)) / scale;
return ((tmr_value * curr_tempo * curr_timebase) + (30 * hz)) / (60 * hz);
}
static void
poll_def_tmr (void *dummy)
poll_def_tmr(void *dummy)
{
if (opened)
{
ACTIVATE_TIMER (def_tmr, poll_def_tmr, 1);
if (opened) {
if (tmr_running)
{
tmr_ctr++;
curr_ticks = ticks_offs + tmr2ticks (tmr_ctr);
timeout( poll_def_tmr, 0, 1);;
if (curr_ticks >= next_event_time)
{
next_event_time = 0xffffffff;
sequencer_timer (NULL);
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)
tmr_reset(void)
{
unsigned long flags;
u_long flags;
DISABLE_INTR (flags);
tmr_offs = 0;
ticks_offs = 0;
tmr_ctr = 0;
next_event_time = 0xffffffff;
prev_event_time = 0;
curr_ticks = 0;
RESTORE_INTR (flags);
flags = splhigh();
tmr_offs = 0;
ticks_offs = 0;
tmr_ctr = 0;
next_event_time = 0xffffffff;
prev_event_time = 0;
curr_ticks = 0;
splx(flags);
}
static int
def_tmr_open (int dev, int mode)
def_tmr_open(int dev, int mode)
{
if (opened)
return RET_ERROR (EBUSY);
if (opened)
return -(EBUSY);
tmr_reset ();
curr_tempo = 60;
curr_timebase = HZ;
opened = 1;
tmr_reset();
curr_tempo = 60;
curr_timebase = hz;
opened = 1;
ACTIVATE_TIMER (def_tmr, poll_def_tmr, 1);
timeout( poll_def_tmr, 0, 1);;
return 0;
return 0;
}
static void
def_tmr_close (int dev)
def_tmr_close(int dev)
{
opened = tmr_running = 0;
opened = tmr_running = 0;
}
static int
def_tmr_event (int dev, unsigned char *event)
def_tmr_event(int dev, u_char *event)
{
unsigned char cmd = event[1];
unsigned long parm = *(int *) &event[4];
u_char cmd = event[1];
u_long parm = *(int *) &event[4];
switch (cmd)
{
switch (cmd) {
case TMR_WAIT_REL:
parm += prev_event_time;
parm += prev_event_time;
case TMR_WAIT_ABS:
if (parm > 0)
{
long time;
if (parm > 0) {
long time;
if (parm <= curr_ticks) /* It's the time */
return TIMER_NOT_ARMED;
if (parm <= curr_ticks) /* It's the time */
return TIMER_NOT_ARMED;
time = parm;
next_event_time = prev_event_time = time;
time = parm;
next_event_time = prev_event_time = time;
return TIMER_ARMED;
return TIMER_ARMED;
}
break;
break;
case TMR_START:
tmr_reset ();
tmr_running = 1;
break;
tmr_reset();
tmr_running = 1;
break;
case TMR_STOP:
tmr_running = 0;
break;
tmr_running = 0;
break;
case TMR_CONTINUE:
tmr_running = 1;
break;
tmr_running = 1;
break;
case TMR_TEMPO:
if (parm)
{
if (parm < 8)
parm = 8;
if (parm > 250)
parm = 250;
tmr_offs = tmr_ctr;
ticks_offs += tmr2ticks (tmr_ctr);
tmr_ctr = 0;
curr_tempo = parm;
if (parm) {
RANGE (parm, 8, 360) ;
tmr_offs = tmr_ctr;
ticks_offs += tmr2ticks(tmr_ctr);
tmr_ctr = 0;
curr_tempo = parm;
}
break;
break;
case TMR_ECHO:
seq_copy_to_input (event, 8);
break;
seq_copy_to_input(event, 8);
break;
default:;
}
return TIMER_NOT_ARMED;
return TIMER_NOT_ARMED;
}
static unsigned long
def_tmr_get_time (int dev)
static u_long
def_tmr_get_time(int dev)
{
if (!opened)
return 0;
if (!opened)
return 0;
return curr_ticks;
return curr_ticks;
}
static int
def_tmr_ioctl (int dev,
unsigned int cmd, unsigned int arg)
def_tmr_ioctl(int dev, u_int cmd, ioctl_arg arg)
{
switch (cmd)
{
switch (cmd) {
case SNDCTL_TMR_SOURCE:
return IOCTL_OUT (arg, TMR_INTERNAL);
break;
return *(int *) arg = TMR_INTERNAL;
break;
case SNDCTL_TMR_START:
tmr_reset ();
tmr_running = 1;
return 0;
break;
tmr_reset();
tmr_running = 1;
return 0;
break;
case SNDCTL_TMR_STOP:
tmr_running = 0;
return 0;
break;
tmr_running = 0;
return 0;
break;
case SNDCTL_TMR_CONTINUE:
tmr_running = 1;
return 0;
break;
tmr_running = 1;
return 0;
break;
case SNDCTL_TMR_TIMEBASE:
{
int val = IOCTL_IN (arg);
{
int val = (*(int *) arg);
if (val)
{
if (val < 1)
val = 1;
if (val > 1000)
val = 1000;
curr_timebase = val;
}
return IOCTL_OUT (arg, curr_timebase);
}
break;
if (val) {
RANGE (val, 1, 1000) ;
curr_timebase = val;
}
return *(int *) arg = curr_timebase;
}
break;
case SNDCTL_TMR_TEMPO:
{
int val = IOCTL_IN (arg);
{
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;
}
return IOCTL_OUT (arg, curr_tempo);
}
break;
if (val) {
RANGE (val, 8, 250) ;
tmr_offs = tmr_ctr;
ticks_offs += tmr2ticks(tmr_ctr);
tmr_ctr = 0;
curr_tempo = val;
}
return *(int *) arg = curr_tempo;
}
break;
case SNDCTL_SEQ_CTRLRATE:
if (IOCTL_IN (arg) != 0) /* Can't change */
return RET_ERROR (EINVAL);
if ((*(int *) arg) != 0) /* Can't change */
return -(EINVAL);
return IOCTL_OUT (arg, ((curr_tempo * curr_timebase) + 30) / 60);
break;
return *(int *) arg = ((curr_tempo * curr_timebase) + 30) / 60;
break;
case SNDCTL_TMR_METRONOME:
/* NOP */
break;
/* NOP */
break;
default:;
}
return RET_ERROR (EINVAL);
return -(EINVAL);
}
static void
def_tmr_arm (int dev, long time)
def_tmr_arm(int dev, long time)
{
if (time < 0)
time = curr_ticks + 1;
else if (time <= curr_ticks) /* It's the time */
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;
next_event_time = prev_event_time = time;
return;
}
struct sound_timer_operations default_sound_timer =
{
{"System Timer", 0},
0, /* Priority */
0, /* Local device link */
def_tmr_open,
def_tmr_close,
def_tmr_event,
def_tmr_get_time,
def_tmr_ioctl,
def_tmr_arm
{"System clock", 0},
0, /* Priority */
0, /* Local device link */
def_tmr_open,
def_tmr_close,
def_tmr_event,
def_tmr_get_time,
def_tmr_ioctl,
def_tmr_arm
};
#endif
#endif
#endif /* NSND > 0 */

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -1,13 +1,13 @@
#ifdef SEQUENCER_C
static unsigned short semitone_tuning[24] =
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
};
static unsigned short cent_tuning[100] =
unsigned short cent_tuning[100] =
{
/* 0 */ 10000, 10006, 10012, 10017, 10023, 10029, 10035, 10041,
/* 8 */ 10046, 10052, 10058, 10064, 10070, 10075, 10081, 10087,
@ -23,4 +23,7 @@ static unsigned short cent_tuning[100] =
/* 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,11 +1,11 @@
/*
* sound/uart6850.c
*
*
* Copyright by Hannu Savolainen 1993
*
* Mon Nov 22 22:38:35 MET 1993 marco@driq.home.usn.nl:
* added 6850 support, used with COVOX SoundMaster II and custom cards.
*
*
* Mon Nov 22 22:38:35 MET 1993 marco@driq.home.usn.nl: added 6850 support, used
* with COVOX SoundMaster II and custom cards.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
@ -13,7 +13,7 @@
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
@ -25,39 +25,32 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*
*/
#include <i386/isa/sound/sound_config.h>
#ifdef CONFIGURE_SOUNDCARD
#if NSND > 0
#if !defined(EXCLUDE_UART6850) && !defined(EXCLUDE_MIDI)
#if 1
/* #if defined(CONFIG_UART6850) && defined(CONFIG_MIDI) */
#define DATAPORT (uart6850_base) /*
* * * Midi6850 Data I/O Port on IBM
* */
#define COMDPORT (uart6850_base+1) /*
* * * Midi6850 Command Port on IBM */
#define STATPORT (uart6850_base+1) /*
* * * Midi6850 Status Port on IBM */
#define DATAPORT (uart6850_base) /* * * Midi6850 Data I/O Port on IBM */
#define COMDPORT (uart6850_base+1) /* * * Midi6850 Command Port on IBM */
#define STATPORT (uart6850_base+1) /* * * Midi6850 Status Port on IBM */
#define uart6850_status() INB(STATPORT)
#define input_avail() ((uart6850_status()&INPUT_AVAIL))
#define output_ready() ((uart6850_status()&OUTPUT_READY))
#define uart6850_cmd(cmd) OUTB(cmd, COMDPORT)
#define uart6850_read() INB(DATAPORT)
#define uart6850_write(byte) OUTB(byte, DATAPORT)
#define uart6850_status() inb( STATPORT)
#define input_avail() (uart6850_status()&INPUT_AVAIL)
#define output_ready() (uart6850_status()&OUTPUT_READY)
#define uart6850_cmd(cmd) outb( COMDPORT, cmd)
#define uart6850_read() inb( DATAPORT)
#define uart6850_write(byte) outb( DATAPORT, byte)
#define OUTPUT_READY 0x02 /*
* * * Mask for Data Read Ready Bit */
#define INPUT_AVAIL 0x01 /*
* * * Mask for Data Send Ready Bit */
#define OUTPUT_READY 0x02 /* * * Mask for Data Read Ready Bit */
#define INPUT_AVAIL 0x01 /* * * Mask for Data Send Ready Bit */
#define UART_RESET 0x95 /*
* * * 6850 Total Reset Command */
#define UART_MODE_ON 0x03 /*
* * * 6850 Send/Receive UART Mode */
#define UART_RESET 0x95 /* * * 6850 Total Reset Command */
#define UART_MODE_ON 0x03 /* * * 6850 Send/Receive UART Mode */
static int uart6850_opened = 0;
static int uart6850_base = 0x330;
@ -65,38 +58,37 @@ static int uart6850_irq;
static int uart6850_detected = 0;
static int my_dev;
static int reset_uart6850 (void);
static void (*midi_input_intr) (int dev, unsigned char data);
static int reset_uart6850(void);
static void (*midi_input_intr) (int dev, u_char data);
static void poll_uart6850(u_long dummy);
static sound_os_info *uart6850_osp;
static void
uart6850_input_loop (void)
uart6850_input_loop(void)
{
int count;
int count;
count = 10;
count = 10;
while (count) /*
* Not timed out
*/
if (input_avail ())
{
unsigned char c = uart6850_read ();
while (count) /* Not timed out */
if (input_avail()) {
u_char c = uart6850_read();
count = 100;
count = 100;
if (uart6850_opened & OPEN_READ)
midi_input_intr (my_dev, c);
}
else
while (!input_avail () && count)
count--;
if (uart6850_opened & OPEN_READ)
midi_input_intr(my_dev, c);
} else
while (!input_avail() && count)
count--;
}
void
m6850intr (int unit)
m6850intr(int irq)
{
if (input_avail ())
uart6850_input_loop ();
if (input_avail())
uart6850_input_loop();
}
/*
@ -105,133 +97,118 @@ m6850intr (int unit)
*/
static void
poll_uart6850 (void *dummy)
poll_uart6850(u_long dummy)
{
unsigned long flags;
u_long flags;
DEFINE_TIMER (uart6850_timer, poll_uart6850);
if (!(uart6850_opened & OPEN_READ))
return; /* Device has been closed */
if (!(uart6850_opened & OPEN_READ))
return; /*
* No longer required
*/
flags = splhigh();
DISABLE_INTR (flags);
if (input_avail())
uart6850_input_loop();
if (input_avail ())
uart6850_input_loop ();
ACTIVATE_TIMER (uart6850_timer, poll_uart6850, 1); /*
* Come back later
*/
timeout((timeout_func_t) poll_uart6850, 0, 1);; /* Come back later */
RESTORE_INTR (flags);
splx(flags);
}
static int
uart6850_open (int dev, int mode,
void (*input) (int dev, unsigned char data),
void (*output) (int dev)
uart6850_open(int dev, int mode,
void (*input) (int dev, u_char data),
void (*output) (int dev)
)
{
if (uart6850_opened)
{
printk ("Midi6850: Midi busy\n");
return RET_ERROR (EBUSY);
if (uart6850_opened) {
printf("Midi6850: Midi busy\n");
return -(EBUSY);
}
uart6850_cmd(UART_RESET);
uart6850_cmd (UART_RESET);
uart6850_input_loop();
uart6850_input_loop ();
midi_input_intr = input;
uart6850_opened = mode;
poll_uart6850(0); /* Enable input polling */
midi_input_intr = input;
uart6850_opened = mode;
poll_uart6850 (0); /*
* Enable input polling
*/
return 0;
return 0;
}
static void
uart6850_close (int dev)
uart6850_close(int dev)
{
uart6850_cmd (UART_MODE_ON);
uart6850_cmd(UART_MODE_ON);
uart6850_opened = 0;
uart6850_opened = 0;
}
static int
uart6850_out (int dev, unsigned char midi_byte)
uart6850_out(int dev, u_char midi_byte)
{
int timeout;
unsigned long flags;
int timeout;
u_long flags;
/*
* Test for input since pending input seems to block the output.
*/
/*
* Test for input since pending input seems to block the output.
*/
DISABLE_INTR (flags);
flags = splhigh();
if (input_avail ())
uart6850_input_loop ();
if (input_avail())
uart6850_input_loop();
RESTORE_INTR (flags);
splx(flags);
/*
* Sometimes it takes about 13000 loops before the output becomes ready
* (After reset). Normally it takes just about 10 loops.
*/
/*
* Sometimes it takes about 13000 loops before the output becomes
* ready (After reset). Normally it takes just about 10 loops.
*/
for (timeout = 30000; timeout > 0 && !output_ready (); timeout--); /*
* Wait
*/
for (timeout = 30000; timeout > 0 && !output_ready(); timeout--); /* Wait */
if (!output_ready ())
{
printk ("Midi6850: Timeout\n");
return 0;
if (!output_ready()) {
printf("Midi6850: Timeout\n");
return 0;
}
uart6850_write (midi_byte);
return 1;
uart6850_write(midi_byte);
return 1;
}
static int
uart6850_command (int dev, unsigned char *midi_byte)
uart6850_command(int dev, u_char *midi_byte)
{
return 1;
return 1;
}
static int
uart6850_start_read (int dev)
uart6850_start_read(int dev)
{
return 0;
return 0;
}
static int
uart6850_end_read (int dev)
uart6850_end_read(int dev)
{
return 0;
return 0;
}
static int
uart6850_ioctl (int dev, unsigned cmd, unsigned arg)
uart6850_ioctl(int dev, u_int cmd, ioctl_arg arg)
{
return RET_ERROR (EINVAL);
return -(EINVAL);
}
static void
uart6850_kick (int dev)
uart6850_kick(int dev)
{
}
static int
uart6850_buffer_status (int dev)
uart6850_buffer_status(int dev)
{
return 0; /*
* No data in buffers
*/
return 0; /* No data in buffers */
}
#define MIDI_SYNTH_NAME "6850 UART Midi"
@ -240,88 +217,79 @@ uart6850_buffer_status (int dev)
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
{"6850 UART", 0, 0, SNDCARD_UART6850},
&std_midi_synth,
{0},
uart6850_open,
uart6850_close,
uart6850_ioctl,
uart6850_out,
uart6850_start_read,
uart6850_end_read,
uart6850_kick,
uart6850_command,
uart6850_buffer_status
};
long
attach_uart6850 (long mem_start, struct address_info *hw_config)
void
attach_uart6850(struct address_info * hw_config)
{
int ok, timeout;
unsigned long flags;
int ok, timeout;
u_long flags;
if (num_midis >= MAX_MIDI_DEV)
{
printk ("Sound: Too many midi devices detected\n");
return mem_start;
if (num_midis >= MAX_MIDI_DEV) {
printf("Sound: Too many midi devices detected\n");
return ;
}
uart6850_base = hw_config->io_base;
uart6850_osp = hw_config->osp;
uart6850_irq = hw_config->irq;
uart6850_base = hw_config->io_base;
uart6850_irq = hw_config->irq;
if (!uart6850_detected)
return ;
if (!uart6850_detected)
return RET_ERROR (EIO);
flags = splhigh();
DISABLE_INTR (flags);
for (timeout = 30000; timeout < 0 && !output_ready(); timeout--); /* Wait */
uart6850_cmd(UART_MODE_ON);
for (timeout = 30000; timeout < 0 && !output_ready (); timeout--); /*
* Wait
*/
uart6850_cmd (UART_MODE_ON);
ok = 1;
ok = 1;
splx(flags);
RESTORE_INTR (flags);
conf_printf("6850 Midi Interface", hw_config);
#if defined(__FreeBSD__)
printk ("uart0: <6850 Midi Interface>");
#else
printk (" <6850 Midi Interface>");
#endif
std_midi_synth.midi_dev = my_dev = num_midis;
midi_devs[num_midis++] = &uart6850_operations;
return mem_start;
std_midi_synth.midi_dev = my_dev = num_midis;
midi_devs[num_midis++] = &uart6850_operations;
return ;
}
static int
reset_uart6850 (void)
reset_uart6850(void)
{
uart6850_read ();
return 1; /*
* OK
*/
uart6850_read();
return 1; /* OK */
}
int
probe_uart6850 (struct address_info *hw_config)
probe_uart6850(struct address_info * hw_config)
{
int ok = 0;
int ok = 0;
uart6850_base = hw_config->io_base;
uart6850_irq = hw_config->irq;
uart6850_osp = hw_config->osp;
uart6850_base = hw_config->io_base;
uart6850_irq = hw_config->irq;
if (snd_set_irq_handler (uart6850_irq, m6850intr, "MIDI6850") < 0)
return 0;
if (snd_set_irq_handler(uart6850_irq, m6850intr, uart6850_osp) < 0)
return 0;
ok = reset_uart6850 ();
ok = reset_uart6850();
uart6850_detected = ok;
return ok;
uart6850_detected = ok;
return ok;
}
#endif
#endif

View File

@ -0,0 +1,137 @@
#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