// // Completion routine for IRP carrying SRB. // NTSTATUS CompletionIrpCompletionRoutine( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PCOMPLETION_DATA Context ) { PMINIPORT_DEVICE_EXTENSION HwDeviceExtension = Context->HwDeviceExtension; PSCSI_REQUEST_BLOCK completionSrb = Context->CompletionSrb; PCCB shippedCcb = Context->ShippedCcb; KDPrint(3,("Entered\n")); UNREFERENCED_PARAMETER(DeviceObject); if(completionSrb->DataBuffer) { PSCSI_REQUEST_BLOCK shippedSrb = (PSCSI_REQUEST_BLOCK)(completionSrb->DataBuffer); KDPrint(1, ("Unexpected IRP completion!!!\n")); ASSERT(shippedCcb); InterlockedDecrement(&HwDeviceExtension->RequestExecuting); InitializeListHead(&shippedCcb->ListEntry); LSCcbSetStatusFlag(shippedCcb, CCBSTATUS_FLAG_TIMER_COMPLETE); ExInterlockedInsertTailList( &HwDeviceExtension->CcbCompletionList, &shippedCcb->ListEntry, &HwDeviceExtension->CcbCompletionListSpinLock ); completionSrb->DataBuffer = NULL; } else { // // Free the CCB if it is not going to the timer completion routine // and allocated from the system pool by lanscsiminiport. // if(Context->ShippedCcbAllocatedFromPool) LSCcbPostCompleteCcb(shippedCcb); } // Free resources ExFreePoolWithTag(completionSrb, LSMP_PTAG_SRB); ExFreePoolWithTag(Context, LSMP_PTAG_CMPDATA); IoFreeIrp(Irp); return STATUS_MORE_PROCESSING_REQUIRED; }
// // Complete a Ccb // VOID LSCcbCompleteCcb( IN PCCB Ccb ) { LONG idx_sl; NTSTATUS status; ASSERT(Ccb->Type == LSSTRUC_TYPE_CCB); ASSERT(Ccb->Length == sizeof(CCB)); ASSERT(!LSCcbIsFlagOn(Ccb,CCB_FLAG_COMPLETED)); ASSERT(Ccb->AssociateCount == 0); ASSERT(Ccb->CcbCurrentStackLocationIndex < NR_MAX_CCB_STACKLOCATION); ASSERT(Ccb->CcbCurrentStackLocation == &Ccb->CcbStackLocation[Ccb->CcbCurrentStackLocationIndex]); KDPrintM(DBG_CCB_TRACE, ("entered with Ccb:%p\n", Ccb)); LSCcbSetFlag(Ccb, CCB_FLAG_COMPLETED); LSCcbResetFlag(Ccb, CCB_FLAG_PENDING); Ccb->CcbCurrentStackLocationIndex++; Ccb->CcbCurrentStackLocation++; // // Call completion routines in order. // for( idx_sl = Ccb->CcbCurrentStackLocationIndex; idx_sl < NR_MAX_CCB_STACKLOCATION; idx_sl++, Ccb->CcbCurrentStackLocation++, Ccb->CcbCurrentStackLocationIndex++ ) { ASSERT(Ccb->CcbCurrentStackLocation <= &Ccb->CcbStackLocation[NR_MAX_CCB_STACKLOCATION - 1]); if(Ccb->CcbCurrentStackLocation->CcbCompletionRoutine) { status = Ccb->CcbCurrentStackLocation->CcbCompletionRoutine(Ccb, Ccb->CcbCurrentStackLocation->CcbCompletionContext); if(status == STATUS_MORE_PROCESSING_REQUIRED) { KDPrintM(DBG_CCB_TRACE, ("Ccb=%p, more processing required.\n", Ccb)); return; } } } // // Do post operation // LSCcbPostCompleteCcb(Ccb); }
VOID MiniTimer( IN PMINIPORT_DEVICE_EXTENSION HwDeviceExtension ) { BOOLEAN BusChanged; MiniCounter ++; BusChanged = FALSE; do { PLIST_ENTRY listEntry; PCCB ccb; PSCSI_REQUEST_BLOCK srb; // Get Completed CCB listEntry = ExInterlockedRemoveHeadList( &HwDeviceExtension->CcbCompletionList, &HwDeviceExtension->CcbCompletionListSpinLock ); if(listEntry == NULL) break; ccb = CONTAINING_RECORD(listEntry, CCB, ListEntry); srb = ccb->Srb; ASSERT(srb); ASSERT(LSCcbIsStatusFlagOn(ccb, CCBSTATUS_FLAG_TIMER_COMPLETE)); KDPrint(1,("completed SRB:%p SCSIOP:%x\n", srb, srb->Cdb[0])); if(LSCcbIsStatusFlagOn(ccb, CCBSTATUS_FLAG_BUSRESET_REQUIRED)) { BusChanged = TRUE; } // // Free a CCB // LSCcbPostCompleteCcb(ccb); ScsiPortNotification( RequestComplete, HwDeviceExtension, srb ); InterlockedDecrement(&HwDeviceExtension->RequestExecuting); } while(1); if(BusChanged) { KDPrint(1,("Bus change detected. RequestExecuting = %d\n", HwDeviceExtension->RequestExecuting)); ScsiPortNotification( BusChangeDetected, HwDeviceExtension, NULL ); } if((MiniCounter % 1000) == 0) KDPrint(4,("RequestExecuting = %d\n", HwDeviceExtension->RequestExecuting)); if(HwDeviceExtension->RequestExecuting != 0) { ScsiPortNotification( RequestTimerCall, HwDeviceExtension, MiniTimer, 1 ); } else { HwDeviceExtension->TimerOn = FALSE; if(ADAPTER_ISSTATUS(HwDeviceExtension,ADAPTER_STATUS_RUNNING)) ScsiPortNotification( RequestTimerCall, HwDeviceExtension, MiniTimer, 1 //1000 ); } ScsiPortNotification( NextRequest, HwDeviceExtension, NULL ); return; }