VOID SoundInDeferred( IN PKDPC pDpc, IN OUT PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp, IN PVOID Context ) /*++ Routine Description: Dpc routine for wave input device Collect the data from the DMA buffer and pass it to the application's buffer(s). Arguments: Return Value: None. --*/ { PLOCAL_DEVICE_INFO pLDI; PGLOBAL_DEVICE_INFO pGDI; pLDI = (PLOCAL_DEVICE_INFO)pDeviceObject->DeviceExtension; pGDI = pLDI->pGlobalInfo; // // Acquire the spin lock before we mess with the list // GlobalEnter(pGDI); // // Fill in any buffers we can // dprintf4(pGDI->NextHalf == LowerHalf ? "dpc():L" : "dpc():U"); // // Zero bytes taken out of new buffer // if( pGDI->DMABuffer[pGDI->NextHalf].nBytes == DMA_BUFFER_SIZE / 2) pGDI->DMABuffer[pGDI->NextHalf].nBytes = 0; // // Request input without posting the last buffer // sndFlush(pGDI, pGDI->NextHalf); sndFillInputBuffers(pLDI, pGDI->NextHalf); // // Restart this buffer's DMA // sndReStartDMA(pGDI, pGDI->NextHalf); // // Move on to next half // pGDI->NextHalf = UpperHalf + LowerHalf - pGDI->NextHalf; // // Release the spin lock // GlobalLeave(pGDI); return; DBG_UNREFERENCED_PARAMETER(pDpc); DBG_UNREFERENCED_PARAMETER(Context); DBG_UNREFERENCED_PARAMETER(pIrp); }
NTSTATUS sndWaveRecord( IN OUT PLOCAL_DEVICE_INFO pLDI, IN OUT PIRP pIrp, IN PIO_STACK_LOCATION pIrpStack ) /*++ Routine Description: Add another buffer for recording. The wave header is the buffer parameter to the IOCTL. This routine just adds the buffer to the queue (of Irps) and returns - setting pending status. Arguments: pLDI - our local device information pIrp - The IO request packet we're processing pIrpStack - the current stack location Return Value: Irp Status. --*/ { NTSTATUS Status; Status = STATUS_PENDING; // // confirm we are doing this on an input device! // if (pLDI->DeviceType != WAVE_IN) { dprintf1("Attempt to record on output device"); return STATUS_NOT_SUPPORTED; } // // Inform debuggers that 0 length buffers are rather strange // if (pIrpStack->Parameters.Read.Length == 0) { dprintf1("Wave play buffer is zero length"); } // // Set return data length to 0 for now // pIrp->IoStatus.Information = 0; // // Put the request in the queue. // // // Acquire the spin lock // GlobalEnter(pLDI->pGlobalInfo); // // Set Irp status. Before we try and process it // pIrp->IoStatus.Status = STATUS_PENDING; Status = STATUS_PENDING; IoMarkIrpPending(pIrp); // // Add our buffer to the queue // InsertTailList(&pLDI->QueueHead, &pIrp->Tail.Overlay.ListEntry); dprintf5("irp added"); // // See if we can satisfy some requests straight away // if (pLDI->State == WAVE_DD_RECORDING) { sndFillInputBuffers(pLDI, UpperHalf + LowerHalf - pLDI->pGlobalInfo->NextHalf); } // // Ok to release the spin lock now // GlobalLeave(pLDI->pGlobalInfo); // // Mark this request as pending completion. // The Dpc deferred procedure call routine does the rest. // return Status; }
NTSTATUS sndClose( IN OUT PLOCAL_DEVICE_INFO pLDI ) /*++ Routine Description: Close the requested device Note - we close immediately, there is no waiting for the device. Arguments: pLDI - pointer to our local device info Return Value: STATUS_SUCCESS if OK otherwise STATUS_INTERNAL_ERROR --*/ { NTSTATUS Status = STATUS_SUCCESS; PGLOBAL_DEVICE_INFO pGDI; pGDI = pLDI->pGlobalInfo; // // Acquire the spin lock // GlobalEnter(pGDI) // // Call the device reset function to complete any // pending i/o requests and terminate any current // requests in progress // switch (pLDI->DeviceType) { case WAVE_IN: case WAVE_OUT: // // Check this is valid call // ASSERT(pLDI->DeviceBusy == 2); pGDI->Usage = SoundInterruptUsageIdle; if (pLDI->DeviceType) { // // Restore the line in input if necessary // sndSetInputVolume(pGDI); } break; default: dprintf1("Bogus device type for close request"); Status = STATUS_INTERNAL_ERROR; break; } // // return the device to it's idle state // if (Status == STATUS_SUCCESS) { pLDI->DeviceBusy = FALSE; dprintf3("Device closed"); } #ifdef MIPSSND_TAIL_BUG // Since the Device is now closed we can set the Output Volume // just in case someone wants to play CDs or listen to Linein sndSetOutputVolume( pGDI ); #endif // MIPSSND_TAIL_BUG // // Release the spin lock // GlobalLeave(pGDI); return Status; }
NTSTATUS sndCleanUp( IN OUT PLOCAL_DEVICE_INFO pLDI ) /*++ Routine Description: Clean up the requested device Arguments: pLDI - pointer to our local device info Return Value: STATUS_SUCCESS if OK otherwise STATUS_INTERNAL_ERROR --*/ { NTSTATUS Status = STATUS_SUCCESS; PGLOBAL_DEVICE_INFO pGDI; pGDI = pLDI->pGlobalInfo; // // Acquire the spin lock // GlobalEnter(pGDI) if (pLDI->DeviceType == WAVE_IN || pLDI->DeviceType == WAVE_OUT) { // // Check this is valid call // ASSERT(pLDI->DeviceBusy == TRUE); // // Call the device reset function to complete any // pending i/o requests and terminate any current // requests in progress // switch (pLDI->DeviceType) { case WAVE_IN: sndStopWaveInput(pLDI); // // Reset position to start and free any pending Irps. // sndFreeQ(pLDI, &pLDI->QueueHead, STATUS_CANCELLED); pLDI->SampleNumber = 0; break; case WAVE_OUT: // // If anything is in the queue then free it. // beware that the final block of a request may still be // being dma'd when we get this call. We now kill this as well // because we've changed such that the if the application thinks // all the requests are complete then they are complete. // if (pGDI->DMABusy) { #ifdef MIPSSND_TAIL_BUG // // Turn off the headphone and Lineout to avoid end clicks // sndMute(pGDI); // We could also mute by turning of the headphone // But mute using volume "sounds" better. // sndHeadphoneControl(pGDI, OFF); // sndLineoutControl(pGDI, OFF); #endif // MIPSSND_TAIL_BUG sndStopDMA(pGDI); } sndResetOutput(pLDI); if (pGDI->pIrpPause) { pGDI->pIrpPause->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest(pGDI->pIrpPause, IO_SOUND_INCREMENT); pGDI->pIrpPause = NULL; } break; } // // return the device to it's idle state // if (Status == STATUS_SUCCESS) { pLDI->State = 0; pLDI->DeviceBusy = 2; dprintf3("Device closing"); } } if ( pLDI->DeviceType != WAVE_IN && pLDI->DeviceType != WAVE_OUT ){ dprintf1("Bogus device type for cleanup request"); Status = STATUS_INTERNAL_ERROR; } #ifdef MIPSSND_TAIL_BUG // Since the Device is now closed we can set the Output Volume // just in case someone wants to play CDs or listen to Linein sndSetOutputVolume( pGDI ); #endif // MIPSSND_TAIL_BUG // // Release the spin lock // GlobalLeave(pGDI); return Status; }
int FAMGMultiGrid::Construct() { FAMGGrid *g, *cg; int level, nnc, nn, ilu, cgilu, leave; DOUBLE coarsefrac = 0.0, t, time, cgtime; FAMGLeaveInfo myleaveinfo; // read parameter const int cgnodes = FAMGGetParameter()->Getcgnodes(); #ifdef ModelP const int cgminnodespe = FAMGGetParameter()->Getcgminnodespe(); #endif const int cglevels = FAMGGetParameter()->Getcglevels(); const double mincoarse = FAMGGetParameter()->Getmincoarse(); const int gamma = FAMGGetParameter()->Getgamma(); if ((strcmp("ilut",FAMGGetParameter()->Getpresmoother()) == 0) || (strcmp("ilut",FAMGGetParameter()->Getpostsmoother()) == 0)) { ilu = 1; } else ilu = 0; if (strcmp("ilut",FAMGGetParameter()->Getcgsmoother()) == 0) { cgilu = 1; } else cgilu = 0; g = grid[0]; #ifdef FAMG_SPARSE_BLOCK g->SmoothTV(); #else g->SmoothTV(); #endif FAMGMarkHeap(FAMG_FROM_TOP); // release in Deconstruct for(level = 0; level < FAMGMAXGRIDS-1; level++) { time = CURRENT_TIME; // g->SmoothTV(); #ifdef ModelP nn = g->GetNrMasterVectors(); // we are interested only in the master vectors #else nn = g->GetN(); #endif leave = 0; myleaveinfo.coarsefrac = coarsefrac; myleaveinfo.cgnodes = nn; #ifdef ModelP myleaveinfo.cgminnodespe = nn; GlobalLeave( &myleaveinfo ); #endif #ifdef XFERTIMING XFERTIMING_algtime = 0.0; XFERTIMING_algtime_start = CURRENT_TIME; #endif if( myleaveinfo.coarsefrac > mincoarse ) { leave = 1; #ifdef ModelP if( me==master ) #endif cout << "FAMG finished; coarsening rate " << 1.0/myleaveinfo.coarsefrac << " < " << 1.0/mincoarse << endl; } if( level >= cglevels ) { leave = 1; #ifdef ModelP if( me==master ) #endif cout << "FAMG finished; levels " << level << " >= " << cglevels << endl; } if( myleaveinfo.cgnodes <= cgnodes ) { leave = 1; #ifdef ModelP if( me==master ) #endif cout << "FAMG finished; cg nodes " << myleaveinfo.cgnodes << " <= " << cgnodes << endl; } #ifdef ModelP if( myleaveinfo.cgminnodespe < cgminnodespe ) { leave = 1; if( me==master ) cout << "FAMG finished; min cg nodes per PE " << myleaveinfo.cgminnodespe << " <= " << cgminnodespe << endl; } #endif if (leave) break; if (gamma < 1) return 0; // ModelP: simple return because gamma is known to all processors #ifdef ModelP //prv(-level,0); g->ConstructOverlap(); //prv(-level,0); assert(g->GetNrMasterVectors() == nn ); #endif g->Stencil(); #ifdef FAMG_ILU if(ilu) { if (g->ILUTDecomp(0)) RETURN(1); } #endif #ifdef FAMG_SPARSE_BLOCK if (g->ConstructDiagonalInverse()) RETURN(1); #endif if (g->ConstructTransfer()) RETURN(1); #ifdef FAMG_SPARSE_BLOCK // if (g->ConstructDiagonalLump()) // RETURN(1); #endif cgtime = CURRENT_TIME; nnc = (g->GetN())-(g->GetNF()); cg = (FAMGGrid *) FAMGGetMem(sizeof(FAMGGrid),FAMG_FROM_TOP); if(cg == NULL) RETURN(1); if(cg->Init(nnc,*g)) RETURN(1); if(cg->Construct(g)) RETURN(1); grid[n] = cg; g = cg; n++; //printf("after Galerkin:\n"); //prm(0,0);prm(0,1); prim(0); //prm(-1,0); //prv(-level-1,0); // for debugging: print some consistent and inconsistent matrices: //GRID *tmpgrid = cg->GetugGrid(); //int tmplevel = GLEVEL(tmpgrid); //MATDATA_DESC *tmpA = ((FAMGugMatrix*)cg->GetMatrix())->GetMatDesc(); //MATDATA_DESC *tmpACons = ((FAMGugMatrix*)cg->GetConsMatrix())->GetMatDesc(); //prvGeom(tmplevel,0); primGeom(tmplevel+1); prmGeom(tmplevel,MD_SCALCMP(tmpA)); //if (dmatcopy(MYMG(tmpgrid),tmplevel,tmplevel,ALL_VECTORS,tmpACons,tmpA) != NUM_OK) assert(0); //if (l_matrix_consistent(tmpgrid,tmpACons,MAT_CONS) != NUM_OK) assert(0); //prvGeom(tmplevel,0); primGeom(tmplevel+1); prmGeom(tmplevel,MD_SCALCMP(tmpACons)); t = CURRENT_TIME; time = t - time; cgtime = t - cgtime; #ifdef XFERTIMING XFERTIMING_algtime += t - XFERTIMING_algtime_start; #endif #ifdef ModelP cout << me << ": "; nnc = cg->GetNrMasterVectors(); // we are interested only in the master vectors #endif coarsefrac = (double)nnc/nn; if( nnc <= 0 ) coarsefrac = 0.000000999; // dummy cout << "amglevel " << -level << " coarsening rate " << 1.0/coarsefrac << " time "<<time<<' '<<cgtime; #ifdef XFERTIMING cout << ' '<<XFERTIMING_algtime; #endif cout << endl; } if(level == FAMGMAXGRIDS-1) { ostrstream ostr; ostr << __FILE__ << ", line " << __LINE__ << ": maximum number of levels reached. " << endl; FAMGWarning(ostr); } g->Stencil(); #ifdef FAMG_ILU if(cgilu) { if (g->ILUTDecomp(1)) RETURN(1); } #endif return 0; }
NTSTATUS sndIoctlGetState( IN OUT PLOCAL_DEVICE_INFO pLDI, IN PIRP pIrp, IN PIO_STACK_LOCATION IrpStack ) /*++ Routine Description: Get the current state of the device and return it to the caller. This code is COMMON for : Wave out Wave in Arguments: pLDI - Pointer to our own device data pIrp - Pointer to the IO Request Packet IrpStack - Pointer to current stack location Return Value: Status to put into request packet by caller. --*/ { PULONG pState; if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(ULONG)) { dprintf1("Supplied buffer too small for requested data"); return STATUS_BUFFER_TOO_SMALL; } // // say how much we're sending back // pIrp->IoStatus.Information = sizeof(ULONG); // // cast the buffer address to the pointer type we want // pState = (PULONG)pIrp->AssociatedIrp.SystemBuffer; // // fill in the info // GlobalEnter(pLDI->pGlobalInfo); // // We don't bother to maintain the WAVE_DD_IDLE state internally // for Wave output // if (pLDI->State == WAVE_DD_PLAYING && pLDI->DeviceType == WAVE_OUT && !pLDI->pGlobalInfo->DMABusy) { *pState = WAVE_DD_IDLE; } else { *pState = pLDI->State; } GlobalLeave(pLDI->pGlobalInfo); return STATUS_SUCCESS; }
NTSTATUS sndIoctlSetState( IN OUT PLOCAL_DEVICE_INFO pLDI, IN PIRP pIrp, IN PIO_STACK_LOCATION IrpStack ) /*++ Routine Description: Set the current state of the device and return it to the caller. This code is COMMON for : Wave out Wave in Arguments: pLDI - Pointer to our own device data pIrp - Pointer to the IO Request Packet IrpStack - Pointer to current stack location Return Value: Status to put into request packet by caller. --*/ { PULONG pState; NTSTATUS Status = STATUS_SUCCESS; if (IrpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(ULONG)) { dprintf1("Supplied buffer too small for expected data"); return STATUS_BUFFER_TOO_SMALL; } // // say how much we're sending back // pIrp->IoStatus.Information = 0; // // cast the buffer address to the pointer type we want // pState = (PULONG)pIrp->AssociatedIrp.SystemBuffer; // // Acquire the spin lock // GlobalEnter(pLDI->pGlobalInfo); // // See if we are an input or output device // switch (pLDI->DeviceType) { case WAVE_IN: Status = sndSetWaveInputState(pLDI, *pState); break; case WAVE_OUT: Status = sndSetWaveOutputState(pLDI, *pState, pIrp); break; default: dprintf1("Bogus device type"); Status = STATUS_INTERNAL_ERROR; break; } // // Release the spin lock // GlobalLeave(pLDI->pGlobalInfo); return Status; }