Esempio n. 1
0
int probe_for_sound_blaster(void) {
    unsigned int i;

    if (!init_sndsb())
        return -1;

#if !defined(TARGET_PC98)
    /* we want to know if certain emulation TSRs exist */
    gravis_mega_em_detect(&megaem_info);
    gravis_sbos_detect();
#endif

    /* it's up to us now to tell it certain minor things */
    sndsb_detect_virtualbox();      // whether or not we're running in VirtualBox
    /* sndsb now allows us to keep the EXE small by not referring to extra sound card support */
    sndsb_enable_sb16_support();        // SB16 support
    sndsb_enable_sc400_support();       // SC400 support
    sndsb_enable_ess_audiodrive_support();  // ESS AudioDrive support

#if !defined(TARGET_PC98)
    /* Plug & Play scan */
    if (has_isa_pnp_bios()) {
        const unsigned int devnode_raw_sz = 4096U;
        unsigned char *devnode_raw = malloc(devnode_raw_sz);

        if (devnode_raw != NULL) {
            unsigned char csn,node=0,numnodes=0xFF,data[192];
            unsigned int j,nodesize=0;
            const char *whatis = NULL;

            memset(data,0,sizeof(data));
            if (isa_pnp_bios_get_pnp_isa_cfg(data) == 0) {
                struct isapnp_pnp_isa_cfg *nfo = (struct isapnp_pnp_isa_cfg*)data;
                isapnp_probe_next_csn = nfo->total_csn;
                isapnp_read_data = nfo->isa_pnp_port;
            }

            /* enumerate device nodes reported by the BIOS */
            if (isa_pnp_bios_number_of_sysdev_nodes(&numnodes,&nodesize) == 0 && numnodes != 0xFF && nodesize <= devnode_raw_sz) {
                for (node=0;node != 0xFF;) {
                    struct isa_pnp_device_node far *devn;
                    unsigned char this_node;

                    /* apparently, start with 0. call updates node to
                     * next node number, or 0xFF to signify end */
                    this_node = node;
                    if (isa_pnp_bios_get_sysdev_node(&node,devnode_raw,ISA_PNP_BIOS_GET_SYSDEV_NODE_CTRL_NOW) != 0) break;

                    devn = (struct isa_pnp_device_node far*)devnode_raw;
                    if (isa_pnp_is_sound_blaster_compatible_id(devn->product_id,&whatis)) {
                        if (sndsb_try_isa_pnp_bios(devn->product_id,this_node,devn,devnode_raw_sz) > 0)
                            printf("PnP: Found %s\n",whatis);
                    }
                }
            }

            /* enumerate the ISA bus directly */
            if (isapnp_read_data != 0) {
                for (csn=1;csn < 255;csn++) {
                    isa_pnp_init_key();
                    isa_pnp_wake_csn(csn);

                    isa_pnp_write_address(0x06); /* CSN */
                    if (isa_pnp_read_data() == csn) {
                        /* apparently doing this lets us read back the serial and vendor ID in addition to resource data */
                        /* if we don't, then we only read back the resource data */
                        isa_pnp_init_key();
                        isa_pnp_wake_csn(csn);

                        for (j=0;j < 9;j++) data[j] = isa_pnp_read_config();

                        if (isa_pnp_is_sound_blaster_compatible_id(*((uint32_t*)data),&whatis)) {
                            if (sndsb_try_isa_pnp(*((uint32_t*)data),csn) > 0)
                                printf("PnP: Found %s\n",whatis);
                        }
                    }

                    /* return back to "wait for key" state */
                    isa_pnp_write_data_register(0x02,0x02); /* bit 1: set -> return to Wait For Key state (or else a Pentium Pro system I own eventually locks up and hangs) */
                }
            }

            free(devnode_raw);
        }
    }
#endif

    /* Non-plug & play scan: BLASTER environment variable */
    if (sndsb_try_blaster_var() != NULL) {
        if (!sndsb_init_card(sndsb_card_blaster))
            sndsb_free_card(sndsb_card_blaster);
    }

#if defined(TARGET_PC98)
    /* Non-plug & play scan: Most SB cards exist at xxD2h or xxD4h */
    sndsb_try_base(0xD2);
    sndsb_try_base(0xD4);
#else
    /* Non-plug & play scan: Most SB cards exist at 220h or 240h */
    sndsb_try_base(0x220);
    sndsb_try_base(0x240);
#endif

    /* further probing, for IRQ and DMA and other capabilities */
    for (i=0;i < SNDSB_MAX_CARDS;i++) {
        struct sndsb_ctx *cx = sndsb_index_to_ctx(i);
        if (cx->baseio == 0) continue;

        if (cx->irq < 0)
            sndsb_probe_irq_F2(cx);
        if (cx->irq < 0)
            sndsb_probe_irq_80(cx);
        if (cx->dma8 < 0)
            sndsb_probe_dma8_E2(cx);
        if (cx->dma8 < 0)
            sndsb_probe_dma8_14(cx);

        // having IRQ and DMA changes the ideal playback method and capabilities
        sndsb_update_capabilities(cx);
        sndsb_determine_ideal_dsp_play_method(cx);
    }

    /* add detected cards to soundcard list */
    {
        soundcard_t sc;
        unsigned int i;

        for (i=0;i < SNDSB_MAX_CARDS;i++) {
            struct sndsb_ctx *cx = sndsb_index_to_ctx(i);
            if (cx->baseio == 0) continue;

            sc = soundcardlist_new(&soundblaster_soundcard_template);
            if (sc == NULL) continue;

            sc->p.soundblaster.index = i;
            sc->requirements = soundcard_requirements_isa_dma;
            sc->capabilities = soundcard_caps_mmap_write | soundcard_caps_8bit | soundcard_caps_isa_dma;
            if (cx->irq >= 0) {
                sc->requirements |= soundcard_requirements_irq;
                sc->capabilities |= soundcard_caps_irq;
            }
            if (cx->dsp_play_method >= SNDSB_DSPOUTMETHOD_4xx)
                sc->capabilities |= soundcard_caps_16bit;
            else if (cx->dsp_play_method >= SNDSB_DSPOUTMETHOD_3xx && cx->ess_extensions)
                sc->capabilities |= soundcard_caps_16bit;
        }
    }

    /* OK. done */
    return 0;
}
Esempio n. 2
0
void isa_pnp_wake_csn(unsigned char id) {
	isa_pnp_write_address(3); /* Wake[CSN] */
	isa_pnp_write_data(id); /* isolation state */
}
Esempio n. 3
0
/* NTS: The caller is expected to pnp_wake_scn() then siphon off the device id */
int isa_pnp_sound_blaster_get_resources(uint32_t id,unsigned char csn,struct sndsb_ctx *cx) {
	cx->baseio = 0;
	cx->gameio = 0;
	cx->aweio = 0;
	cx->oplio = 0;
	cx->mpuio = 0;
	cx->dma16 = -1;
	cx->dma8 = -1;
	cx->irq = -1;

	if (ISAPNP_ID_FMATCH(id,'E','S','S')) {
		if (ISAPNP_ID_LMATCH(id,0x0100)) { /* ESS0100 ES688 Plug And Play AudioDrive */
			/* TODO: I don't have any ISA cards of this type, only one integrated into a laptop */
		}
	}
	else if (ISAPNP_ID_FMATCH(id,'C','P','Q')) {
		if (ISAPNP_ID_LMATCH(id,0xB040)) { /* CPQB040 ES1887 (Compaq) */
			/* TODO: I don't have any ISA cards of this type, only one integrated into a laptop */
		}
	}
	else if (ISAPNP_ID_FMATCH(id,'Y','M','H')) {
		if (ISAPNP_ID_LMATCH(id,0x0021)) { /* YMH0021 OPL3-SAx (TODO: Which one? SA2 or SA3) */
			/* TODO: I don't have any ISA cards of this type, only one integrated into a laptop */
		}
	}
	else if (ISAPNP_ID_FMATCH(id,'C','T','L')) {
		/* Creative SB PnP cards are fairly consistent on the resource layout. If you have one that this
		 * code fails to match, feel free to add it here */
		if (	ISAPNP_ID_LMATCH(id,0x0070) || /* CTL0070 Creative ViBRA16C PnP */
			ISAPNP_ID_LMATCH(id,0x00B2) || /* CTL00B2 Creative AWE64 Gold PnP */
			ISAPNP_ID_LMATCH(id,0x00C3) || /* CTL00C3 Creative AWE64 PnP */
			ISAPNP_ID_LMATCH(id,0x00F0)) { /* CTL00F0 Creative ViBRA16X/XV PnP */
			/* For ref (configuration regs):
			 *   IO[0]  = Base I/O port
			 *   IO[1]  = MPU I/O port
			 *   IO[2]  = OPL3 I/O port
			 *   IRQ[0] = Interrupt request line
			 *   DMA[0] = 8-bit DMA channel
			 *   DMA[1] = 16-bit DMA channel
			 */
			isa_pnp_write_address(0x07);	/* log device select */
			isa_pnp_write_data(0x00);	/* main device */

			cx->baseio = isa_pnp_read_io_resource(0);
			if (cx->baseio == 0 || cx->baseio == 0xFFFF) cx->baseio = 0;
			cx->mpuio = isa_pnp_read_io_resource(1);
			if (cx->mpuio == 0 || cx->mpuio == 0xFFFF) cx->mpuio = 0;
			cx->oplio = isa_pnp_read_io_resource(2);
			if (cx->oplio == 0 || cx->oplio == 0xFFFF) cx->oplio = 0;
			cx->dma8 = isa_pnp_read_dma(0);
			if ((cx->dma8&7) == 4) cx->dma8 = -1;
			cx->dma16 = isa_pnp_read_dma(1);
			if ((cx->dma16&7) == 4) cx->dma16 = -1;
			cx->irq = isa_pnp_read_irq(0);
			if ((cx->irq&0xF) == 0) cx->irq = -1;

			/* logical device #1: gameport */
			isa_pnp_write_address(0x07);	/* log device select */
			isa_pnp_write_data(0x01);	/* main device */

			cx->gameio = isa_pnp_read_io_resource(0);
			if (cx->gameio == cx->baseio || cx->gameio == 0 || cx->gameio == 0xFFFF) cx->gameio = 0;

			/* SB AWE: logical device #2: wavetable */
			if (ISAPNP_ID_LMATCH(id,0x00C3) || ISAPNP_ID_LMATCH(id,0x00B2)) {
				isa_pnp_write_address(0x07);	/* log device select */
				isa_pnp_write_data(0x02);	/* main device */

				cx->aweio = isa_pnp_read_io_resource(0);
				if (cx->aweio == cx->baseio || cx->aweio == 0 || cx->aweio == 0xFFFF) cx->aweio = 0;
			}
		}
	}

	if (cx->baseio == 0) return ISAPNPSB_NO_RESOURCES;
	return 1;
}