/* handle interrupt for specified sub device; DmaMode == DEV_READ_S */ PRIVATE void handle_int_read(int sub_dev_nr) { sub_dev_t *sub_dev_ptr; int r,i; sub_dev_ptr = &sub_dev[sub_dev_nr]; dprint("Device filled dma[%d]\n", sub_dev_ptr->DmaFillNext); sub_dev_ptr->DmaLength += 1; sub_dev_ptr->DmaFillNext = (sub_dev_ptr->DmaFillNext + 1) % sub_dev_ptr->NrOfDmaFragments; /* possibly copy data to user (if it is waiting for us) */ data_to_user(sub_dev_ptr); if (sub_dev_ptr->DmaLength == sub_dev_ptr->NrOfDmaFragments) { /* if dma buffer full */ if (sub_dev_ptr->BufLength == sub_dev_ptr->NrOfExtraBuffers) { error("All buffers full, we have a problem.\n"); drv_stop(sub_dev_nr); /* stop the sub device */ sub_dev_ptr->DmaBusy = FALSE; sub_dev_ptr->ReviveStatus = 0; /* no data for user, this is a sad story */ sub_dev_ptr->ReadyToRevive = TRUE; /* wake user up */ return; } else { /* dma full, still room in extra buf; copy from dma to extra buf */ dprint("dma full: going to copy buf[%d] <- dma[%d]\n", sub_dev_ptr->BufFillNext, sub_dev_ptr->DmaReadNext); memcpy(sub_dev_ptr->ExtraBuf + sub_dev_ptr->BufFillNext * sub_dev_ptr->FragSize, sub_dev_ptr->DmaPtr + sub_dev_ptr->DmaReadNext * sub_dev_ptr->FragSize, sub_dev_ptr->FragSize); sub_dev_ptr->DmaLength -= 1; sub_dev_ptr->DmaReadNext = (sub_dev_ptr->DmaReadNext + 1) % sub_dev_ptr->NrOfDmaFragments; sub_dev_ptr->BufFillNext = (sub_dev_ptr->BufFillNext + 1) % sub_dev_ptr->NrOfExtraBuffers; } } /* confirm interrupt, and reenable interrupt from this sub dev*/ drv_reenable_int(sub_dev_ptr->Nr); #if 0 /* reenable irq_hook*/ if ((r=sys_irqenable(&irq_hook_id)) != OK) { error("%s: Couldn't reenable IRQ", drv.DriverName); } #endif }
PRIVATE void msg_sig_stop(void) { int i; char irq; for (i = 0; i < drv.NrOfSubDevices; i++) { drv_stop(i); /* stop all sub devices */ } if (irq_hook_set) { if (sys_irqdisable(&irq_hook_id) != OK) { error("Could not disable IRQ\n"); } /* get irq from device driver*/ if (drv_get_irq(&irq) != OK) { error("Msg SIG_STOP Couldn't get IRQ"); } /* remove the policy */ if (sys_irqrmpolicy(irq, &irq_hook_id) != OK) { error("%s: Could not disable IRQ\n",drv.DriverName); } } }
PRIVATE int close_sub_dev(int sub_dev_nr) { sub_dev_t *sub_dev_ptr; sub_dev_ptr = &sub_dev[sub_dev_nr]; if (sub_dev_ptr->DmaMode == DEV_WRITE_S && !sub_dev_ptr->OutOfData) { /* do nothing, still data in buffers that has to be transferred */ sub_dev_ptr->Opened = FALSE; /* keep DMA busy */ return OK; } if (sub_dev_ptr->DmaMode == NO_DMA) { /* do nothing, there is no dma going on */ sub_dev_ptr->Opened = FALSE; return OK; } sub_dev_ptr->Opened = FALSE; sub_dev_ptr->DmaBusy = FALSE; /* stop the device */ drv_stop(sub_dev_ptr->Nr); /* free the buffers */ free(sub_dev_ptr->DmaBuf); free(sub_dev_ptr->ExtraBuf); }
static int reset(int chan) { drv_stop(chan); sub_dev[chan].OutOfData = 1; return OK; }