Beispiel #1
0
static void WSS_PlayStop(void)
{
	wss.timer_callback = NULL;
	wss_output(FALSE);
	wss_stop_dma();
	VC_PlayStop();
}
Beispiel #2
0
static boolean __wss_reset()
{
	int count;

	/* Disable output */
	wss_output(FALSE);

	/* Now select the test/initialization register */
	count = 10000;
	while (inportb(WSS_ADDR) != WSSR_TEST_INIT) {
		outportb(WSS_ADDR, WSSR_TEST_INIT);
		if (!--count)
			return FALSE;
	}

	count = 10000;
	while (inportb(WSS_DATA) & WSSM_CALIB_IN_PROGRESS) {
		outportb(WSS_ADDR, WSSR_TEST_INIT);
		if (!--count)
			return FALSE;
	}

	/* Enable playback IRQ */
	__wss_regbit_set(WSSR_PIN_CTRL, WSSM_IRQ_ENABLE);
	__wss_outreg(WSSR_IRQ_STATUS, WSSM_PLAYBACK_IRQ);

	/* Clear IRQ status */
	outportb(WSS_STATUS, 0);

	return TRUE;
}
Beispiel #3
0
static BOOL WSS_PlayStart(void)
{
	if (VC_PlayStart())
		return 1;

	/* Set our routine to be called during WSS IRQs */
	buff_tail = 0;
	wss.timer_callback = WSS_Callback;

	/* Start cyclic DMA transfer */
	if (!wss_start_dma(((md_mode & DMODE_16BITS) ? WSSMODE_16BITS | WSSMODE_SIGNED : 0) |
		((md_mode & DMODE_STEREO) ? WSSMODE_STEREO : 0), md_mixfreq))
	{
		_mm_errno = MMERR_DOSWSS_STARTDMA;
		return 1;
	}

	/* Enable speaker output */
	wss_output(TRUE);

	return 0;
}
Beispiel #4
0
static boolean __wss_detect()
{
	/* First find the port number */
	if (!wss.port) {
		static unsigned int wss_ports[] =
		  { 0x32c, 0x530, 0x604, 0xE80, 0xF40 };
		int i;
		for (i = 0; i < 5; i++) {
			wss.port = wss_ports[i];
			if (__wss_ping())
				break;
		}
		if (i < 0) {
			wss.port = 0;
			return FALSE;
		}
	}

	/* Now disable output */
	wss_output(FALSE);

	/* Detect the DMA channel */
	if (!wss.dma) {
		static int __dma[] = { 0, 1, 3 };
		int i;

		/* Enable playback IRQ */
		__wss_regbit_set(WSSR_PIN_CTRL, WSSM_IRQ_ENABLE);
		__wss_outreg(WSSR_IRQ_STATUS, WSSM_PLAYBACK_IRQ);

		/* Start a short DMA transfer and check if DMA count is zero */
		for (i = 0; i < 3; i++) {
			unsigned int timer, status, freq = 44100;

			wss.dma = __dma[i];

			dma_disable(wss.dma);
			dma_set_mode(wss.dma, DMA_MODE_WRITE);
			dma_clear_ff(wss.dma);
			dma_set_count(wss.dma, 10);
			dma_enable(wss.dma);

			/* Clear IRQ status */
			outportb(WSS_STATUS, 0);

			__wss_setformat(__wss_getrate(&freq));
			__wss_outreg(WSSR_COUNT_LOW, 1);
			__wss_outreg(WSSR_COUNT_HIGH, 0);
			/* Tell codec to start transfer */
			__wss_regbit_set(WSSR_IFACE_CTRL, WSSM_PLAYBACK_ENABLE);

			_farsetsel(_dos_ds);
			timer = _farnspeekl(0x46c);

			while (_farnspeekl(0x46c) - timer <= 2)
				if (dma_get_count(wss.dma) == 0)
					break;
			__wss_regbit_reset(WSSR_IFACE_CTRL, WSSM_PLAYBACK_ENABLE);
			dma_disable(wss.dma);

			/* Now check if DMA transfer count is zero and an IRQ is pending */
			status = inportb(WSS_STATUS);
			outportb(WSS_STATUS, 0);
			if ((dma_get_count(wss.dma) == 0) && (status & WSSM_INT))
				break;

			wss.dma = 0;
		}

		if (!wss.dma)
			return FALSE;
	}

	/* Now detect the IRQ number */
	if (!wss.irq) {
		unsigned int i, irqmask, freq = 5510;
		unsigned long timer, delta = 0x7fffffff;

		/* IRQ can be one of 2,3,5,7,10 */
		irq_detect_start(0x04ac, __wss_irq_irqdetect);

		dma_disable(wss.dma);
		dma_set_mode(wss.dma, DMA_MODE_WRITE | DMA_MODE_AUTOINIT);
		dma_clear_ff(wss.dma);
		dma_set_count(wss.dma, 1);
		dma_enable(wss.dma);

		__wss_setformat(__wss_getrate(&freq));

		/* Clear IRQ status */
		outportb(WSS_STATUS, 0);

		__wss_outreg(WSSR_COUNT_LOW, 0);
		__wss_outreg(WSSR_COUNT_HIGH, 0);

		/* Prepare timeout counter */
		_farsetsel(_dos_ds);
		timer = _farnspeekl(0x46c);
		while (timer == _farnspeekl(0x46c));
		timer = _farnspeekl(0x46c);

		/* Reset all IRQ counters */
		irq_detect_clear();

		/* Tell codec to start transfer */
		__wss_regbit_set(WSSR_IFACE_CTRL, WSSM_PLAYBACK_ENABLE);

		/* Now wait 1/18 seconds */
		while (timer == _farnspeekl(0x46c));
		__wss_regbit_reset(WSSR_IFACE_CTRL, WSSM_PLAYBACK_ENABLE);
		dma_disable(wss.dma);

		/* Given frequency 5510Hz, a buffer size of 1 byte and a time interval
		   of 1/18.2 second, we should have received about 302 interrupts */
		for (i = 2; i <= 10; i++) {
			int count = abs(302 - irq_detect_get(i, &irqmask));
			if (count < delta)
				wss.irq = i, delta = count;
		}
		if (delta > 150)
			wss.irq = 0;

		irq_detect_end();
		if (!wss.irq)
			return FALSE;
	}

	return TRUE;
}