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:
parent
062497b471
commit
0183b33fd6
693
sys/i386/isa/sound/pss.c
Normal file
693
sys/i386/isa/sound/pss.c
Normal 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
371
sys/i386/isa/sound/pss.h
Normal 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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
54
sys/i386/isa/sound/sbcard.h
Normal file
54
sys/i386/isa/sound/sbcard.h
Normal 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
@ -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);
|
||||
|
@ -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
|
||||
|
186
sys/i386/isa/sound/sound_pnp.c
Normal file
186
sys/i386/isa/sound/sound_pnp.c
Normal 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
|
@ -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
|
||||
|
@ -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
@ -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
@ -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 */
|
||||
|
@ -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
|
||||
|
2488
sys/i386/isa/sound/trix_boot.h
Normal file
2488
sys/i386/isa/sound/trix_boot.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
|
@ -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
|
||||
|
137
sys/i386/isa/sound/ultrasound.h
Normal file
137
sys/i386/isa/sound/ultrasound.h
Normal 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
|
Loading…
Reference in New Issue
Block a user