diff options
Diffstat (limited to 'sys/i386/isa/sound/dev_table.c')
-rw-r--r-- | sys/i386/isa/sound/dev_table.c | 303 |
1 files changed, 303 insertions, 0 deletions
diff --git a/sys/i386/isa/sound/dev_table.c b/sys/i386/isa/sound/dev_table.c new file mode 100644 index 0000000..3061170 --- /dev/null +++ b/sys/i386/isa/sound/dev_table.c @@ -0,0 +1,303 @@ +/* + * 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 |