freebsd-dev/sys/i386/isa/snd/clones.c

263 lines
7.1 KiB
C
Raw Normal View History

/*
* sound/clones.c
*
* init code for enabling clone cards to work in sb/mss emulation.
*
* Note -- this code is currently unused!
*
* Copyright by Luigi Rizzo - 1997
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met: 1. Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer. 2. Redistributions in binary form must reproduce the
* above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* This file has been written using information from various sources
* in the Voxware 3.5 distribution.
*/
#include <i386/isa/snd/sound.h>
#if NPCM > 0
/*
* Known clones card include:
*
* Trix (emulating MSS)
* MAD16 (emulating MSS)
* OPTi930 -- same as the OPTi931, but no PnP ?
*/
#ifdef JAZZ16
/*
* Initialization of a Media Vision ProSonic 16 Soundcard. The function
* initializes a ProSonic 16 like PROS.EXE does for DOS. It sets the base
* address, the DMA-channels, interrupts and enables the joystickport.
*
* Also used by Jazz 16 (same card, different name)
*
* written 1994 by Rainer Vranken E-Mail:
* rvranken@polaris.informatik.uni-essen.de
*/
#ifdef SM_WAVE
/*
* Logitech Soundman Wave detection and initialization by Hannu Savolainen.
*
* There is a microcontroller (8031) in the SM Wave card for MIDI emulation.
* it's located at address MPU_BASE+4. MPU_BASE+7 is a SM Wave specific
* control register for MC reset, SCSI, OPL4 and DSP (future expansion)
* address decoding. Otherwise the SM Wave is just a ordinary MV Jazz16 based
* soundcard.
*/
static void
smw_putmem(int base, int addr, u_char val)
{
u_long s;
s = spltty();
outb(base + 1, addr & 0xff); /* Low address bits */
outb(base + 2, addr >> 8); /* High address bits */
outb(base, val); /* Data */
splx(s);
}
static u_char
smw_getmem(int base, int addr)
{
u_long s;
u_char val;
s = spltty();
outb(base + 1, addr & 0xff); /* Low address bits */
outb(base + 2, addr >> 8); /* High address bits */
val = inb(base); /* Data */
splx(s);
return val;
}
#ifdef SMW_MIDI0001_INCLUDED
#include </sys/i386/isa/snd/smw-midi0001.h>
#else
u_char *smw_ucode = NULL;
int smw_ucodeLen = 0;
#endif /* SWM_MIDI0001_INCLUDED */
static int
initialize_smw(int mpu_base)
{
int i, mp_base = mpu_base + 4; /* Microcontroller base */
u_char control;
/*
* Reset the microcontroller so that the RAM can be accessed
*/
control = inb(mpu_base + 7);
outb(mpu_base + 7, control | 3); /* Set last two bits to 1 (?) */
outb(mpu_base + 7, (control & 0xfe) | 2); /* xxxxxxx0 resets the mc */
DELAY(3000); /* Wait at least 1ms */
outb(mpu_base + 7, control & 0xfc); /* xxxxxx00 enables RAM */
/*
* Detect microcontroller by probing the 8k RAM area
*/
smw_putmem(mp_base, 0, 0x00);
smw_putmem(mp_base, 1, 0xff);
DELAY(10);
if (smw_getmem(mp_base, 0) != 0x00 || smw_getmem(mp_base, 1) != 0xff) {
printf("\nSM Wave: No microcontroller RAM detected (%02x, %02x)\n",
smw_getmem(mp_base, 0), smw_getmem(mp_base, 1));
return 0; /* No RAM */
}
/*
* There is RAM so assume it's really a SM Wave
*/
if (smw_ucodeLen > 0) {
if (smw_ucodeLen != 8192) {
printf("\nSM Wave: Invalid microcode (MIDI0001.BIN) length\n");
return 1;
}
/*
* Download microcode
*/
for (i = 0; i < 8192; i++)
smw_putmem(mp_base, i, smw_ucode[i]);
/*
* Verify microcode
*/
for (i = 0; i < 8192; i++)
if (smw_getmem(mp_base, i) != smw_ucode[i]) {
printf("SM Wave: Microcode verification failed\n");
return 0;
}
}
control = 0;
#ifdef SMW_SCSI_IRQ
/*
* Set the SCSI interrupt (IRQ2/9, IRQ3 or IRQ10). The SCSI interrupt
* is disabled by default.
*
* Btw the Zilog 5380 SCSI controller is located at MPU base + 0x10.
*/
{
static u_char scsi_irq_bits[] =
{0, 0, 3, 1, 0, 0, 0, 0, 0, 3, 2, 0, 0, 0, 0, 0};
control |= scsi_irq_bits[SMW_SCSI_IRQ] << 6;
}
#endif
#ifdef SMW_OPL4_ENABLE
/*
* Make the OPL4 chip visible on the PC bus at 0x380.
*
* There is no need to enable this feature since VoxWare doesn't support
* OPL4 yet. Also there is no RAM in SM Wave so enabling OPL4 is
* pretty useless.
*/
control |= 0x10; /* Uses IRQ12 if bit 0x20 == 0 */
/* control |= 0x20; Uncomment this if you want to use IRQ7 */
#endif
outb(mpu_base + 7, control | 0x03); /* xxxxxx11 restarts */
return 1;
}
#endif
/*
* this is only called during the probe. Variables are found in
* sb_probed.
*/
static sbdev_info sb_probed ;
static int
initialize_ProSonic16(snddev_info *d)
{
int x;
static u_char int_translat[16] =
{0, 0, 2, 3, 0, 1, 0, 4, 0, 2, 5, 0, 0, 0, 0, 6},
dma_translat[8] =
{0, 1, 0, 2, 0, 3, 0, 4};
struct address_info *mpu_config;
int mpu_base, mpu_irq;
if ((mpu_config = NULL)) {
mpu_base = mpu_config->io_base;
mpu_irq = mpu_config->irq;
} else {
mpu_base = mpu_irq = 0;
}
outb(0x201, 0xAF); /* ProSonic/Jazz16 wakeup */
DELAY(15000); /* wait at least 10 milliseconds */
outb(0x201, 0x50);
outb(0x201, (sb_probed.io_base & 0x70) | ((mpu_base & 0x30) >> 4));
if (sb_reset_dsp(sb_probed.io_base)) { /* OK. We have at least a SB */
/* Check the version number of ProSonic (I guess) */
if (!sb_cmd(sb_probed.io_base, 0xFA))
return 1;
if (sb_get_byte(sb_probed.io_base) != 0x12)
return 1;
if (sb_cmd(sb_probed.io_base, 0xFB) && /* set DMA and irq */
sb_cmd(sb_probed.io_base,
(dma_translat[JAZZ_DMA16]<<4)|dma_translat[sb_probed.dbuf_out.chan]) &&
sb_cmd(sb_probed.io_base,
(int_translat[mpu_irq]<<4)|int_translat[sb_probed.irq])) {
d->bf_flags |= BD_F_JAZZ16 ;
if (mpu_base == 0)
printf("Jazz16: No MPU401 devices configured "
"- MIDI port not initialized\n");
#ifdef SM_WAVE
if (mpu_base != 0)
if (initialize_smw(mpu_base))
d->bf_flags |= BD_F_JAZZ16_2 ;
#endif
/* sb_dsp_disable_midi(); */
}
return 1; /* There was at least a SB */
}
return 0; /* No SB or ProSonic16 detected */
}
#endif /* ifdef JAZZ16 */
#endif /* NPCM */