예제 #1
0
파일: dosdma.c 프로젝트: Bracket-/psp-ports
void dma_start(dma_buffer * buffer, unsigned long count, unsigned char mode)
{
	/* Disable interrupts */
	int old_ints = disable();
	dma_disable(buffer->channel);
	dma_set_mode(buffer->channel, mode);
	dma_clear_ff(buffer->channel);
	dma_set_addr(buffer->channel, buffer->physical);
	dma_clear_ff(buffer->channel);
	dma_set_count(buffer->channel, count);
	dma_enable(buffer->channel);
	/* Re-enable interrupts */
	if (old_ints)
		enable();
}
예제 #2
0
파일: doswss.c 프로젝트: LighFusion/surreal
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;
}