304 lines
7.9 KiB
C
304 lines
7.9 KiB
C
|
/*
|
||
|
* sound/dev_table.c
|
||
|
*
|
||
|
* Device call tables.
|
||
|
*
|
||
|
* Copyright by Hannu Savolainen 1993
|
||
|
*
|
||
|
* Redistribution and use in source and binary forms, with or without
|
||
|
* modification, are permitted provided that the following conditions are
|
||
|
* met: 1. Redistributions of source code must retain the above copyright
|
||
|
* notice, this list of conditions and the following disclaimer. 2.
|
||
|
* Redistributions in binary form must reproduce the above copyright notice,
|
||
|
* this list of conditions and the following disclaimer in the documentation
|
||
|
* and/or other materials provided with the distribution.
|
||
|
*
|
||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
|
||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||
|
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
|
||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||
|
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||
|
* SUCH DAMAGE.
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
#define _DEV_TABLE_C_
|
||
|
#include <i386/isa/sound/sound_config.h>
|
||
|
|
||
|
#if NSND > 0
|
||
|
|
||
|
int sound_started = 0;
|
||
|
|
||
|
int sndtable_get_cardcount(void);
|
||
|
int snd_find_driver(int type);
|
||
|
static void sndtable_init(void);
|
||
|
int sndtable_probe(int unit, struct address_info * hw_config);
|
||
|
int sndtable_init_card(int unit, struct address_info * hw_config);
|
||
|
static int sndtable_identify_card(char *name);
|
||
|
static void sound_chconf(int card_type, int ioaddr, int irq, int dma);
|
||
|
static void start_services(void);
|
||
|
static void start_cards(void);
|
||
|
struct address_info *sound_getconf(int card_type);
|
||
|
|
||
|
int
|
||
|
snd_find_driver(int type)
|
||
|
{
|
||
|
int i, n = num_sound_drivers;
|
||
|
|
||
|
for (i = 0; i < n; i++)
|
||
|
if (sound_drivers[i].card_type == type)
|
||
|
return i;
|
||
|
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
start_services()
|
||
|
{
|
||
|
int soundcards_installed;
|
||
|
|
||
|
if (!(soundcards_installed = sndtable_get_cardcount()))
|
||
|
return ; /* No cards detected */
|
||
|
|
||
|
#ifdef CONFIG_AUDIO
|
||
|
if (num_audiodevs) /* Audio devices present */
|
||
|
DMAbuf_init();
|
||
|
#endif
|
||
|
|
||
|
#ifdef CONFIG_MIDI
|
||
|
if (num_midis)
|
||
|
/* MIDIbuf_init(0) */;
|
||
|
#endif
|
||
|
|
||
|
#ifdef CONFIG_SEQUENCER
|
||
|
if (num_midis + num_synths)
|
||
|
sequencer_init();
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
start_cards()
|
||
|
{
|
||
|
int drv, i, n = num_sound_cards;
|
||
|
struct card_info *ci = snd_installed_cards ;
|
||
|
|
||
|
sound_started = 1;
|
||
|
if (trace_init)
|
||
|
printf("Sound initialization started\n");
|
||
|
|
||
|
/*
|
||
|
* Check the number of cards actually defined in the table
|
||
|
*/
|
||
|
|
||
|
for (i = 0; i < n && snd_installed_cards[i].card_type; i++)
|
||
|
num_sound_cards = i + 1;
|
||
|
|
||
|
for (i = 0; i < n && ci->card_type; ci++, i++)
|
||
|
if (ci->enabled) {
|
||
|
if ((drv = snd_find_driver(ci->card_type)) == -1) {
|
||
|
ci->enabled = 0; /* Mark as not detected */
|
||
|
continue;
|
||
|
}
|
||
|
ci->config.card_subtype = sound_drivers[drv].card_subtype;
|
||
|
|
||
|
if (sound_drivers[drv].probe(&(ci->config)))
|
||
|
sound_drivers[drv].attach(&(ci->config));
|
||
|
else
|
||
|
ci->enabled = 0; /* Mark as not detected */
|
||
|
}
|
||
|
if (trace_init)
|
||
|
printf("Sound initialization complete\n");
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
sndtable_init()
|
||
|
{
|
||
|
start_cards();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* sndtable_probe probes a specific device. unit is the voxware unit number.
|
||
|
*/
|
||
|
|
||
|
int
|
||
|
sndtable_probe(int unit, struct address_info * hw_config)
|
||
|
{
|
||
|
int i, sel = -1, n = num_sound_cards;
|
||
|
struct card_info *ci = snd_installed_cards ;
|
||
|
|
||
|
DDB(printf("-- sndtable_probe(%d)\n", unit));
|
||
|
|
||
|
|
||
|
/*
|
||
|
* for some reason unit 0 always succeeds ?
|
||
|
*/
|
||
|
if (!unit)
|
||
|
return TRUE;
|
||
|
|
||
|
sound_started = 1;
|
||
|
|
||
|
for (i=0; i<n && sel== -1 && ci->card_type; ci++, i++)
|
||
|
if ( (ci->enabled) && (ci->card_type == unit) ) {
|
||
|
/* DDB(printf("-- found card %d\n", i) ); */
|
||
|
sel = i; /* and break */
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* not found. Creates a new entry in the table for this unit.
|
||
|
*/
|
||
|
if (sel == -1 && num_sound_cards < max_sound_cards) {
|
||
|
int i;
|
||
|
|
||
|
i = sel = (num_sound_cards++);
|
||
|
DDB(printf("-- installing card %d\n", i) );
|
||
|
|
||
|
ci = &snd_installed_cards[sel] ;
|
||
|
ci->card_type = unit;
|
||
|
ci->enabled = 1;
|
||
|
}
|
||
|
/* DDB(printf("-- installed card %d\n", sel) ); */
|
||
|
if (sel != -1) {
|
||
|
int drv;
|
||
|
|
||
|
ci->config.io_base = hw_config->io_base;
|
||
|
ci->config.irq = hw_config->irq;
|
||
|
ci->config.dma = hw_config->dma;
|
||
|
ci->config.dma2 = hw_config->dma2;
|
||
|
ci->config.name = hw_config->name;
|
||
|
ci->config.always_detect = hw_config->always_detect;
|
||
|
ci->config.card_subtype = hw_config->card_subtype;
|
||
|
ci->config.osp = hw_config->osp;
|
||
|
|
||
|
if ((drv = snd_find_driver(ci->card_type)) == -1) {
|
||
|
ci->enabled = 0;
|
||
|
DDB(printf("Failed to find driver\n"));
|
||
|
return FALSE;
|
||
|
}
|
||
|
DDB(printf("-- Driver name '%s' probe 0x%08x\n",
|
||
|
sound_drivers[drv].name, sound_drivers[drv].probe));
|
||
|
|
||
|
hw_config->card_subtype =
|
||
|
ci->config.card_subtype = sound_drivers[drv].card_subtype;
|
||
|
|
||
|
if (sound_drivers[drv].probe(hw_config)) {
|
||
|
DDB(printf("-- Hardware probed OK\n"));
|
||
|
return TRUE;
|
||
|
}
|
||
|
DDB(printf("-- Failed to find hardware\n"));
|
||
|
ci->enabled = 0; /* mark as not detected */
|
||
|
return FALSE;
|
||
|
}
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
int
|
||
|
sndtable_init_card(int unit, struct address_info * hw_config)
|
||
|
{
|
||
|
int i, n = num_sound_cards;
|
||
|
struct card_info *ci = snd_installed_cards ;
|
||
|
|
||
|
DDB(printf("sndtable_init_card(%d) entered\n", unit));
|
||
|
|
||
|
if (!unit) {
|
||
|
sndtable_init() ;
|
||
|
return TRUE;
|
||
|
}
|
||
|
for (i = 0; i < n && ci->card_type; ci++, i++)
|
||
|
if (ci->card_type == unit) {
|
||
|
int drv;
|
||
|
|
||
|
ci->config.io_base = hw_config->io_base;
|
||
|
ci->config.irq = hw_config->irq;
|
||
|
ci->config.dma = hw_config->dma;
|
||
|
ci->config.dma2 = hw_config->dma2;
|
||
|
ci->config.name = hw_config->name;
|
||
|
ci->config.always_detect = hw_config->always_detect;
|
||
|
ci->config.card_subtype = hw_config->card_subtype;
|
||
|
ci->config.osp = hw_config->osp;
|
||
|
|
||
|
if ((drv = snd_find_driver(ci->card_type)) == -1)
|
||
|
ci->enabled = 0; /* Mark not fnd */
|
||
|
else {
|
||
|
DDB(printf("Located card - calling attach routine\n"));
|
||
|
sound_drivers[drv].attach(hw_config) ;
|
||
|
DDB(printf("attach routine finished\n"));
|
||
|
}
|
||
|
start_services();
|
||
|
return TRUE;
|
||
|
}
|
||
|
DDB(printf("sndtable_init_card: No card defined with type=%d, num cards: %d\n",
|
||
|
unit, num_sound_cards));
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
int
|
||
|
sndtable_get_cardcount(void)
|
||
|
{
|
||
|
return num_audiodevs + num_mixers + num_synths + num_midis;
|
||
|
}
|
||
|
|
||
|
static int
|
||
|
sndtable_identify_card(char *name)
|
||
|
{
|
||
|
int i, n = num_sound_drivers;
|
||
|
|
||
|
if (name == NULL)
|
||
|
return 0;
|
||
|
|
||
|
for (i = 0; i < n; i++)
|
||
|
if (sound_drivers[i].driver_id != NULL) {
|
||
|
char *id = sound_drivers[i].driver_id;
|
||
|
int j;
|
||
|
|
||
|
for (j = 0; j < 80 && name[j] == id[j]; j++)
|
||
|
if (id[j] == 0 && name[j] == 0) /* Match */
|
||
|
return sound_drivers[i].card_type;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
sound_chconf(int card_type, int ioaddr, int irq, int dma)
|
||
|
{
|
||
|
int j, ptr = -1, n = num_sound_cards;
|
||
|
|
||
|
for (j = 0; j < n && ptr == -1 && snd_installed_cards[j].card_type; j++)
|
||
|
if (snd_installed_cards[j].card_type == card_type &&
|
||
|
!snd_installed_cards[j].enabled) /* Not already found */
|
||
|
ptr = j;
|
||
|
|
||
|
if (ptr != -1) {
|
||
|
snd_installed_cards[ptr].enabled = 1;
|
||
|
if (ioaddr)
|
||
|
snd_installed_cards[ptr].config.io_base = ioaddr;
|
||
|
if (irq)
|
||
|
snd_installed_cards[ptr].config.irq = irq;
|
||
|
if (dma)
|
||
|
snd_installed_cards[ptr].config.dma = dma;
|
||
|
snd_installed_cards[ptr].config.dma2 = -1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
struct address_info *
|
||
|
sound_getconf(int card_type)
|
||
|
{
|
||
|
int j, ptr = -1, n = num_sound_cards;
|
||
|
|
||
|
for (j = 0; j < n && ptr == -1 && snd_installed_cards[j].card_type; j++)
|
||
|
if (snd_installed_cards[j].card_type == card_type)
|
||
|
ptr = j;
|
||
|
|
||
|
if (ptr == -1)
|
||
|
return (struct address_info *) NULL;
|
||
|
|
||
|
return &snd_installed_cards[ptr].config;
|
||
|
}
|
||
|
|
||
|
#endif
|