static void WSS_PlayStop(void) { wss.timer_callback = NULL; wss_output(FALSE); wss_stop_dma(); VC_PlayStop(); }
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; }
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; }
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; }