/* handle interrupt for specified sub device; DmaMode == DEV_WRITE_S*/ PRIVATE void handle_int_write(int sub_dev_nr) { sub_dev_t *sub_dev_ptr; int r; sub_dev_ptr = &sub_dev[sub_dev_nr]; dprint("Finished playing dma[%d] ", sub_dev_ptr->DmaReadNext); sub_dev_ptr->DmaReadNext = (sub_dev_ptr->DmaReadNext + 1) % sub_dev_ptr->NrOfDmaFragments; sub_dev_ptr->DmaLength -= 1; if (sub_dev_ptr->BufLength != 0) { /* Data in extra buf, copy to Dma buf */ dprint(" buf[%d] -> dma[%d] ", sub_dev_ptr->BufReadNext, sub_dev_ptr->DmaFillNext); memcpy(sub_dev_ptr->DmaPtr + sub_dev_ptr->DmaFillNext * sub_dev_ptr->FragSize, sub_dev_ptr->ExtraBuf + sub_dev_ptr->BufReadNext * sub_dev_ptr->FragSize, sub_dev_ptr->FragSize); sub_dev_ptr->BufReadNext = (sub_dev_ptr->BufReadNext + 1) % sub_dev_ptr->NrOfExtraBuffers; sub_dev_ptr->DmaFillNext = (sub_dev_ptr->DmaFillNext + 1) % sub_dev_ptr->NrOfDmaFragments; sub_dev_ptr->BufLength -= 1; sub_dev_ptr->DmaLength += 1; } /* space became available, possibly copy new data from user */ data_from_user(sub_dev_ptr); if(sub_dev_ptr->DmaLength == 0) { /* Dma buffer empty, stop Dma transfer */ sub_dev_ptr->OutOfData = TRUE; /* we're out of data */ dprint("No more work...!\n"); if (!sub_dev_ptr->Opened) { close_sub_dev(sub_dev_ptr->Nr); dprint("Stopping sub device %d\n", sub_dev_ptr->Nr); return; } dprint("Pausing sub device %d\n",sub_dev_ptr->Nr); drv_pause(sub_dev_ptr->Nr); return; } dprint("\n"); /* confirm and reenable interrupt from this sub dev */ drv_reenable_int(sub_dev_nr); #if 0 /* reenable irq_hook*/ if ((r=sys_irqenable(&irq_hook_id)) != OK) { error("%s Couldn't enable IRQ\n", drv.DriverName); } #endif }
/* all IO-ctl's sent to the upper driver are passed to this function */ int drv_io_ctl(int request, void * val, int * len, int sub_dev) { int status; switch(request) { case DSPIORATE: status = set_sample_rate(*((u32_t *) val), sub_dev); break; case DSPIOSTEREO: status = set_stereo(*((u32_t *) val), sub_dev); break; case DSPIOBITS: status = set_bits(*((u32_t *) val), sub_dev); break; case DSPIOSIZE: status = set_frag_size(*((u32_t *) val), sub_dev); break; case DSPIOSIGN: status = set_sign(*((u32_t *) val), sub_dev); break; case DSPIOMAX: status = get_max_frag_size(val, len, sub_dev); break; case DSPIORESET: status = reset(sub_dev); break; case DSPIOFREEBUF: status = free_buf(val, len, sub_dev); break; case DSPIOSAMPLESINBUF: status = get_samples_in_buf(val, len, sub_dev); break; case DSPIOPAUSE: status = drv_pause(sub_dev); break; case DSPIORESUME: status = drv_resume(sub_dev); break; case MIXIOGETVOLUME: status = get_set_volume(val, len, sub_dev, 0); break; case MIXIOSETVOLUME: status = get_set_volume(val, len, sub_dev, 1); break; default: status = EINVAL; break; } return status; }