NTSTATUS NdscAdapterCompletion( IN PCCB Ccb, IN PMINIPORT_DEVICE_EXTENSION HwDeviceExtension ) { KIRQL oldIrql; static LONG SrbSeq; LONG srbSeqIncremented; PSCSI_REQUEST_BLOCK srb; PCCB abortCcb; NTSTATUS return_status; UINT32 AdapterStatus, AdapterStatusBefore; UINT32 NeedToUpdatePdoInfoInLSBus; BOOLEAN busResetOccured; KDPrint(4,("RequestExecuting = %d\n", HwDeviceExtension->RequestExecuting)); srb = Ccb->Srb; if(!srb) { KDPrint(2,("Ccb:%p CcbStatus %d. No srb assigned.\n", Ccb, Ccb->CcbStatus)); ASSERT(srb); return STATUS_SUCCESS; } // // NDASSCSI completion routine will do post operation to complete CCBs. // return_status = STATUS_MORE_PROCESSING_REQUIRED; // // Set SRB completion sequence for debugging // srbSeqIncremented = InterlockedIncrement(&SrbSeq); #if 0 if(KeGetCurrentIrql() == PASSIVE_LEVEL) { if((srbSeqIncremented%100) == 0) { LARGE_INTEGER interval; KDPrint(2,("Interval for debugging.\n")); interval.QuadPart = - 11 * 10000000; // 10 seconds KeDelayExecutionThread(KernelMode, FALSE, &interval); } } #endif // // Update Adapter status flag // NeedToUpdatePdoInfoInLSBus = FALSE; ACQUIRE_SPIN_LOCK(&HwDeviceExtension->LanscsiAdapterSpinLock, &oldIrql); // Save the bus-reset flag if(ADAPTER_ISSTATUSFLAG(HwDeviceExtension, NDASSCSI_ADAPTER_STATUSFLAG_BUSRESET_PENDING)) { busResetOccured = TRUE; } else { busResetOccured = FALSE; } // Save the current flag AdapterStatusBefore = HwDeviceExtension->AdapterStatus; // Check reconnecting process. if (LsCcbIsStatusFlagOn(Ccb, CCBSTATUS_FLAG_RECONNECTING)) { ADAPTER_SETSTATUSFLAG(HwDeviceExtension, NDASSCSI_ADAPTER_STATUSFLAG_RECONNECT_PENDING); } else { ADAPTER_RESETSTATUSFLAG(HwDeviceExtension, NDASSCSI_ADAPTER_STATUSFLAG_RECONNECT_PENDING); } if (!LsCcbIsStatusFlagOn(Ccb, CCBSTATUS_FLAG_RAID_FLAG_VALID)) { NDAS_ASSERT( Ccb->NdasrStatusFlag8 == 0 ); } else { NDAS_ASSERT( Ccb->NdasrStatusFlag8 == CCBSTATUS_FLAG_RAID_DEGRADED >> 8 || Ccb->NdasrStatusFlag8 == CCBSTATUS_FLAG_RAID_RECOVERING >> 8 || Ccb->NdasrStatusFlag8 == CCBSTATUS_FLAG_RAID_FAILURE >> 8 || Ccb->NdasrStatusFlag8 == CCBSTATUS_FLAG_RAID_NORMAL >> 8 ); } // Update adapter status only when CCBSTATUS_FLAG_RAID_FLAG_VALID is on. // In other case, Ccb has no chance to get flag information from RAID. if (LsCcbIsStatusFlagOn(Ccb, CCBSTATUS_FLAG_RAID_FLAG_VALID)) { // Check to see if the associate member is in error. if (LsCcbIsStatusFlagOn(Ccb, CCBSTATUS_FLAG_RAID_DEGRADED)) { if (!ADAPTER_ISSTATUSFLAG(HwDeviceExtension, NDASSCSI_ADAPTER_STATUSFLAG_MEMBER_FAULT)) { KDPrint(2, ("NDASSCSI_ADAPTER_STATUSFLAG_MEMBER_FAULT is Set\n") ); } ADAPTER_SETSTATUSFLAG( HwDeviceExtension, NDASSCSI_ADAPTER_STATUSFLAG_MEMBER_FAULT ); } else { ADAPTER_RESETSTATUSFLAG( HwDeviceExtension, NDASSCSI_ADAPTER_STATUSFLAG_MEMBER_FAULT ); } // Check recovering process. if (LsCcbIsStatusFlagOn(Ccb, CCBSTATUS_FLAG_RAID_RECOVERING)) { if (!ADAPTER_ISSTATUSFLAG(HwDeviceExtension, NDASSCSI_ADAPTER_STATUSFLAG_RECOVERING)) { KDPrint(2, ("NDASSCSI_ADAPTER_STATUSFLAG_RECOVERING is Set\n") ); } ADAPTER_SETSTATUSFLAG( HwDeviceExtension, NDASSCSI_ADAPTER_STATUSFLAG_RECOVERING ); } else { ADAPTER_RESETSTATUSFLAG( HwDeviceExtension, NDASSCSI_ADAPTER_STATUSFLAG_RECOVERING ); } // Check RAID failure if (LsCcbIsStatusFlagOn(Ccb, CCBSTATUS_FLAG_RAID_FAILURE)) { if (!ADAPTER_ISSTATUSFLAG(HwDeviceExtension, NDASSCSI_ADAPTER_STATUSFLAG_RAID_FAILURE)) { KDPrint(2, ("NDASSCSI_ADAPTER_STATUSFLAG_RAID_FAILURE is Set\n") ); } ADAPTER_SETSTATUSFLAG( HwDeviceExtension, NDASSCSI_ADAPTER_STATUSFLAG_RAID_FAILURE ); } else { ADAPTER_RESETSTATUSFLAG( HwDeviceExtension, NDASSCSI_ADAPTER_STATUSFLAG_RAID_FAILURE ); } // Set RAID normal status if (LsCcbIsStatusFlagOn(Ccb, CCBSTATUS_FLAG_RAID_NORMAL)) { if (!ADAPTER_ISSTATUSFLAG(HwDeviceExtension, NDASSCSI_ADAPTER_STATUSFLAG_RAID_NORMAL)) { KDPrint(2, ("NDASSCSI_ADAPTER_STATUSFLAG_RAID_NORMAL is Set\n") ); } ADAPTER_SETSTATUSFLAG( HwDeviceExtension, NDASSCSI_ADAPTER_STATUSFLAG_RAID_NORMAL ); } else { ADAPTER_RESETSTATUSFLAG( HwDeviceExtension, NDASSCSI_ADAPTER_STATUSFLAG_RAID_NORMAL ); } } // power-recycle occurred. if(LsCcbIsStatusFlagOn(Ccb, CCBSTATUS_FLAG_POWERRECYLE_OCCUR)) { ADAPTER_SETSTATUSFLAG(HwDeviceExtension, NDASSCSI_ADAPTER_STATUSFLAG_POWERRECYCLED); } else { ADAPTER_RESETSTATUSFLAG(HwDeviceExtension, NDASSCSI_ADAPTER_STATUSFLAG_POWERRECYCLED); } if (ADAPTER_ISSTATUSFLAG(HwDeviceExtension, NDASSCSI_ADAPTER_STATUSFLAG_POWERRECYCLED)) { //NDAS_ASSERT( FALSE ); } AdapterStatus = HwDeviceExtension->AdapterStatus; RELEASE_SPIN_LOCK(&HwDeviceExtension->LanscsiAdapterSpinLock, oldIrql); if(AdapterStatus != AdapterStatusBefore) { if( !(AdapterStatusBefore & NDASSCSI_ADAPTER_STATUSFLAG_MEMBER_FAULT) && (AdapterStatus & NDASSCSI_ADAPTER_STATUSFLAG_MEMBER_FAULT) ) { // NDASSCSI_ADAPTER_STATUSFLAG_MEMBER_FAULT on SCSI_PORT_LOG_ERROR_MODULE_COMPLETION(NDASSCSI_IO_MEMBER_FAULT, EVTLOG_MEMBER_IN_ERROR); KDPrint(2,("Ccb:%p CcbStatus %d. Set member fault.\n", Ccb, Ccb->CcbStatus)); } if( (AdapterStatusBefore & NDASSCSI_ADAPTER_STATUSFLAG_MEMBER_FAULT) && !(AdapterStatus & NDASSCSI_ADAPTER_STATUSFLAG_MEMBER_FAULT) ) { // NDASSCSI_ADAPTER_STATUSFLAG_MEMBER_FAULT off SCSI_PORT_LOG_ERROR_MODULE_COMPLETION(NDASSCSI_IO_MEMBER_FAULT_RECOVERED, EVTLOG_MEMBER_RECOVERED); KDPrint(2,("Ccb:%p CcbStatus %d. Reset member fault.\n", Ccb, Ccb->CcbStatus)); } if( !(AdapterStatusBefore & NDASSCSI_ADAPTER_STATUSFLAG_RECONNECT_PENDING) && (AdapterStatus & NDASSCSI_ADAPTER_STATUSFLAG_RECONNECT_PENDING) ) { // NDASSCSI_ADAPTER_STATUSFLAG_RECONNECT_PENDING on SCSI_PORT_LOG_ERROR_MODULE_COMPLETION(NDASSCSI_IO_RECONNECT_START, EVTLOG_START_RECONNECTION); KDPrint(2,("Ccb:%p CcbStatus %d. Start reconnecting\n", Ccb, Ccb->CcbStatus)); } if( (AdapterStatusBefore & NDASSCSI_ADAPTER_STATUSFLAG_RECONNECT_PENDING) && !(AdapterStatus & NDASSCSI_ADAPTER_STATUSFLAG_RECONNECT_PENDING) ) { // NDASSCSI_ADAPTER_STATUSFLAG_RECONNECT_PENDING off SCSI_PORT_LOG_ERROR_MODULE_COMPLETION(NDASSCSI_IO_RECONNECTED, EVTLOG_END_RECONNECTION); KDPrint(2,("Ccb:%p CcbStatus %d. Finish reconnecting\n", Ccb, Ccb->CcbStatus)); } if( !(AdapterStatusBefore & NDASSCSI_ADAPTER_STATUSFLAG_RECOVERING) && (AdapterStatus & NDASSCSI_ADAPTER_STATUSFLAG_RECOVERING) ) { // NDASSCSI_ADAPTER_STATUSFLAG_RECOVERING on SCSI_PORT_LOG_ERROR_MODULE_COMPLETION(NDASSCSI_IO_RECOVERY_START, EVTLOG_START_RECOVERING); KDPrint(2,("Ccb:%p CcbStatus %d. Started recovering\n", Ccb, Ccb->CcbStatus)); } if( (AdapterStatusBefore & NDASSCSI_ADAPTER_STATUSFLAG_RECOVERING) && !(AdapterStatus & NDASSCSI_ADAPTER_STATUSFLAG_RECOVERING) && !(AdapterStatus & (NDASSCSI_ADAPTER_STATUSFLAG_RAID_FAILURE|NDASSCSI_ADAPTER_STATUSFLAG_MEMBER_FAULT)) && (AdapterStatus & NDASSCSI_ADAPTER_STATUSFLAG_RAID_NORMAL)) { // NDASSCSI_ADAPTER_STATUSFLAG_RECOVERING off SCSI_PORT_LOG_ERROR_MODULE_COMPLETION(NDASSCSI_IO_RECOVERED, EVTLOG_END_RECOVERING); KDPrint(2,("Ccb:%p CcbStatus %d. Ended recovering\n", Ccb, Ccb->CcbStatus)); } if ( (AdapterStatus & NDASSCSI_ADAPTER_STATUSFLAG_RAID_FAILURE) && !(AdapterStatusBefore & NDASSCSI_ADAPTER_STATUSFLAG_RAID_FAILURE)) { SCSI_PORT_LOG_ERROR_MODULE_COMPLETION(NDASSCSI_IO_RAID_FAILURE, EVTLOG_RAID_FAILURE); KDPrint(2,("Ccb:%p CcbStatus %d. RAID failure\n", Ccb, Ccb->CcbStatus)); } if( !(AdapterStatusBefore & NDASSCSI_ADAPTER_STATUSFLAG_POWERRECYCLED) && (AdapterStatus & NDASSCSI_ADAPTER_STATUSFLAG_POWERRECYCLED) ) { // NDASSCSI_ADAPTER_STATUSFLAG_POWERRECYCLED on SCSI_PORT_LOG_ERROR_MODULE_COMPLETION(NDASSCSI_IO_DISK_POWERRECYCLE, EVTLOG_DISK_POWERRECYCLED); KDPrint(2,("Ccb:%p CcbStatus %d. Started recovering\n", Ccb, Ccb->CcbStatus)); } NeedToUpdatePdoInfoInLSBus = TRUE; } // // If CCB_OPCODE_UPDATE is successful, update adapter status in LanscsiBus // if(Ccb->OperationCode == CCB_OPCODE_UPDATE) { if(Ccb->CcbStatus == CCB_STATUS_SUCCESS) { SCSI_PORT_LOG_ERROR_MODULE_COMPLETION(NDASSCSI_IO_UPGRADE_SUCC, EVTLOG_SUCCEED_UPGRADE); } else { SCSI_PORT_LOG_ERROR_MODULE_COMPLETION(NDASSCSI_IO_UPGRADE_FAIL, EVTLOG_FAIL_UPGRADE); } NeedToUpdatePdoInfoInLSBus = TRUE; } // // Copy IO control results to the SRB buffer. // // If device lock CCB is successful, copy the result to the SRB. // if(Ccb->OperationCode == CCB_OPCODE_DEVLOCK) { if(Ccb->CcbStatus == CCB_STATUS_SUCCESS) { PSRB_IO_CONTROL srbIoctlHeader; PUCHAR lockIoctlBuffer; PNDSCIOCTL_DEVICELOCK ioCtlAcReDeviceLock; PLURN_DEVLOCK_CONTROL lurnAcReDeviceLock; // // Get the Ioctl buffer. // srbIoctlHeader = (PSRB_IO_CONTROL)srb->DataBuffer; srbIoctlHeader->ReturnCode = SRB_STATUS_SUCCESS; lockIoctlBuffer = (PUCHAR)(srbIoctlHeader + 1); ioCtlAcReDeviceLock = (PNDSCIOCTL_DEVICELOCK)lockIoctlBuffer; lurnAcReDeviceLock = (PLURN_DEVLOCK_CONTROL)Ccb->DataBuffer; // Copy the result RtlCopyMemory( ioCtlAcReDeviceLock->LockData, lurnAcReDeviceLock->LockData, NDSCLOCK_LOCKDATA_LENGTH); } } else if(Ccb->OperationCode == CCB_OPCODE_QUERY) { if(Ccb->CcbStatus == CCB_STATUS_SUCCESS) { PSRB_IO_CONTROL srbIoctlHeader; NTSTATUS copyStatus; srbIoctlHeader = (PSRB_IO_CONTROL)srb->DataBuffer; copyStatus = NdscCopyQueryOutputToSrb( HwDeviceExtension, Ccb->DataBufferLength, Ccb->DataBuffer, srbIoctlHeader->Length, (PUCHAR)(srbIoctlHeader + 1) ); if(copyStatus == STATUS_BUFFER_TOO_SMALL) { srbIoctlHeader->ReturnCode = SRB_STATUS_DATA_OVERRUN; }else if(NT_SUCCESS(copyStatus)) { srbIoctlHeader->ReturnCode = SRB_STATUS_SUCCESS; } else { srbIoctlHeader->ReturnCode = SRB_STATUS_ERROR; } } } KDPrint(4,("CcbStatus %d\n", Ccb->CcbStatus)); // // Translate CcbStatus to SrbStatus // CcbStatusToSrbStatus(Ccb, srb); // // Perform stop process when we get stop status. // if(Ccb->CcbStatus == CCB_STATUS_STOP) { // // Stop in the timer routine. // KDPrint(2, ("Stop status. Stop in the timer routine.\n")); } else { // // Update PDO information on the NDAS bus. // if(NeedToUpdatePdoInfoInLSBus) { KDPrint(2, ("<<<<<<<<<<<<<<<< %08lx -> %08lx ADAPTER STATUS CHANGED" " >>>>>>>>>>>>>>>>\n", AdapterStatusBefore, AdapterStatus)); UpdatePdoInfoInLSBus(HwDeviceExtension, HwDeviceExtension->AdapterStatus); } } // // Process Abort CCB. // abortCcb = Ccb->AbortCcb; if(abortCcb != NULL) { KDPrint(2,("abortSrb\n")); ASSERT(FALSE); srb->SrbStatus = SRB_STATUS_SUCCESS; LsCcbSetStatusFlag(Ccb, CCBSTATUS_FLAG_TIMER_COMPLETE); InitializeListHead(&Ccb->ListEntry); ExInterlockedInsertTailList( &HwDeviceExtension->CcbTimerCompletionList, &Ccb->ListEntry, &HwDeviceExtension->CcbTimerCompletionListSpinLock ); ((PSCSI_REQUEST_BLOCK)abortCcb->Srb)->SrbStatus = SRB_STATUS_ABORTED; LsCcbSetStatusFlag(abortCcb, CCBSTATUS_FLAG_TIMER_COMPLETE); InitializeListHead(&abortCcb->ListEntry); ExInterlockedInsertTailList( &HwDeviceExtension->CcbTimerCompletionList, &abortCcb->ListEntry, &HwDeviceExtension->CcbTimerCompletionListSpinLock ); } else { BOOLEAN criticalSrb; // // We should not use completion IRP method with disable-disconnect flag. // A SRB with DISABLE_DISCONNECT flag causes the SCSI port queue locked. // criticalSrb = (srb->SrbFlags & SRB_FLAGS_DISABLE_DISCONNECT) != 0 || (srb->SrbFlags & SRB_FLAGS_BYPASS_FROZEN_QUEUE) != 0 || (srb->SrbFlags & SRB_FLAGS_BYPASS_LOCKED_QUEUE) != 0; #if DBG if(criticalSrb) { KDPrint(2, ("Critical Srb:%p\n", srb)); } #if 0 NdscPrintSrb("Comp:", srb); #endif #endif // // Make Complete IRP and Send it. // // // In case of HostStatus == CCB_STATUS_SUCCESS_TIMER, CCB will go to the timer to complete. // if( (Ccb->CcbStatus == CCB_STATUS_SUCCESS || Ccb->CcbStatus == CCB_STATUS_DATA_OVERRUN) && !LsCcbIsStatusFlagOn(Ccb, CCBSTATUS_FLAG_TIMER_COMPLETE) && !LsCcbIsStatusFlagOn(Ccb, CCBSTATUS_FLAG_BUSCHANGE) && !busResetOccured && !criticalSrb ) { PDEVICE_OBJECT pDeviceObject = HwDeviceExtension->ScsiportFdoObject; PIRP pCompletionIrp = NULL; PIO_STACK_LOCATION pIoStack; NTSTATUS ntStatus; PSCSI_REQUEST_BLOCK completionSrb = NULL; PCOMPLETION_DATA completionData = NULL; completionSrb = ExAllocatePoolWithTag(NonPagedPool, sizeof(SCSI_REQUEST_BLOCK), NDSC_PTAG_SRB); if(completionSrb == NULL) goto Out; RtlZeroMemory( completionSrb, sizeof(SCSI_REQUEST_BLOCK) ); // Build New IRP. pCompletionIrp = IoAllocateIrp((CCHAR)(pDeviceObject->StackSize + 1), FALSE); if(pCompletionIrp == NULL) { ExFreePoolWithTag(completionSrb, NDSC_PTAG_SRB); goto Out; } completionData = ExAllocatePoolWithTag(NonPagedPool, sizeof(COMPLETION_DATA), NDSC_PTAG_CMPDATA); if(completionData == NULL) { ExFreePoolWithTag(completionSrb, NDSC_PTAG_SRB); IoFreeIrp(pCompletionIrp); pCompletionIrp = NULL; goto Out; } pCompletionIrp->MdlAddress = NULL; // Set IRP stack location. pIoStack = IoGetNextIrpStackLocation(pCompletionIrp); pIoStack->DeviceObject = pDeviceObject; pIoStack->MajorFunction = IRP_MJ_SCSI; pIoStack->Parameters.DeviceIoControl.InputBufferLength = 0; pIoStack->Parameters.DeviceIoControl.OutputBufferLength = 0; pIoStack->Parameters.Scsi.Srb = completionSrb; // Set SRB. completionSrb->Length = sizeof(SCSI_REQUEST_BLOCK); completionSrb->Function = SRB_FUNCTION_EXECUTE_SCSI; completionSrb->PathId = srb->PathId; completionSrb->TargetId = srb->TargetId; completionSrb->Lun = srb->Lun; completionSrb->QueueAction = SRB_SIMPLE_TAG_REQUEST; completionSrb->DataBuffer = Ccb; completionSrb->SrbFlags |= SRB_FLAGS_BYPASS_FROZEN_QUEUE | SRB_FLAGS_NO_QUEUE_FREEZE; completionSrb->OriginalRequest = pCompletionIrp; completionSrb->CdbLength = MAXIMUM_CDB_SIZE; completionSrb->Cdb[0] = SCSIOP_COMPLETE; completionSrb->Cdb[1] = (UCHAR)srbSeqIncremented; completionSrb->TimeOutValue = 20; completionSrb->SrbStatus = SRB_STATUS_SUCCESS; // // Set completion data for the completion IRP. // completionData->HwDeviceExtension = HwDeviceExtension; completionData->CompletionSrb = completionSrb; completionData->ShippedCcb = Ccb; completionData->ShippedCcbAllocatedFromPool = LsCcbIsFlagOn(Ccb, CCB_FLAG_ALLOCATED); Out: KDPrint(5,("Before Completion\n")); IoSetCompletionRoutine( pCompletionIrp, CompletionIrpCompletionRoutine, completionData, TRUE, TRUE, TRUE); ASSERT(HwDeviceExtension->RequestExecuting != 0); #if 0 { LARGE_INTEGER interval; ULONG SrbTimeout; static DebugCount = 0; DebugCount ++; SrbTimeout = ((PSCSI_REQUEST_BLOCK)(Ccb->Srb))->TimeOutValue; if( SrbTimeout>9 && (DebugCount%1000) == 0 ) { KDPrint(2,("Experiment!!!!!!! Delay completion. SrbTimeout:%d\n", SrbTimeout)); interval.QuadPart = - (INT64)SrbTimeout * 11 * 1000000; KeDelayExecutionThread(KernelMode, FALSE, &interval); } } #endif // // call Scsiport FDO. // ntStatus = IoCallDriver(pDeviceObject, pCompletionIrp); ASSERT(NT_SUCCESS(ntStatus)); if(ntStatus!= STATUS_SUCCESS && ntStatus!= STATUS_PENDING) { KDPrint(2,("ntStatus = 0x%x\n", ntStatus)); SCSI_PORT_LOG_ERROR_MODULE_COMPLETION(NDASSCSI_IO_COMPIRP_FAIL, EVTLOG_FAIL_COMPLIRP); KDPrint(2,("IoCallDriver() error. CCB(%p) and SRB(%p) is going to the timer." " CcbStatus:%x CcbFlag:%x\n", Ccb, Ccb->Srb, Ccb->CcbStatus, Ccb->Flags)); InitializeListHead(&Ccb->ListEntry); LsCcbSetStatusFlag(Ccb, CCBSTATUS_FLAG_TIMER_COMPLETE); ExInterlockedInsertTailList( &HwDeviceExtension->CcbTimerCompletionList, &Ccb->ListEntry, &HwDeviceExtension->CcbTimerCompletionListSpinLock ); } } else { KDPrint(2,("CCB(%p) and SRB(%p) is going to the timer." " CcbStatus:%x CcbFlag:%x\n", Ccb, Ccb->Srb, Ccb->CcbStatus, Ccb->Flags)); InitializeListHead(&Ccb->ListEntry); LsCcbSetStatusFlag(Ccb, CCBSTATUS_FLAG_TIMER_COMPLETE); ExInterlockedInsertTailList( &HwDeviceExtension->CcbTimerCompletionList, &Ccb->ListEntry, &HwDeviceExtension->CcbTimerCompletionListSpinLock ); } } return return_status; }
NTSTATUS LanscsiMiniportCompletion( IN PCCB Ccb, IN PMINIPORT_DEVICE_EXTENSION HwDeviceExtension ) { KIRQL oldIrql; static LONG SrbSeq; LONG srbSeqIncremented; PSCSI_REQUEST_BLOCK srb; PCCB abortCcb; NTSTATUS return_status; KDPrint(3,("RequestExecuting = %d\n", HwDeviceExtension->RequestExecuting)); srb = Ccb->Srb; if(!srb) { KDPrint(1,("Ccb:%p CcbStatus %d. No srb assigned.\n", Ccb, Ccb->CcbStatus)); ASSERT(srb); return STATUS_SUCCESS; } // // LanscsiMiniport completion routine will do post operation to complete CCBs. // return_status = STATUS_MORE_PROCESSING_REQUIRED; srbSeqIncremented = InterlockedIncrement(&SrbSeq); // // check to see if this CCB was sent before BusReset occurs. // TODO: we need to calculate the accurate BUSRESET_EFFECT_TICKCOUNT. // ASSERT(Ccb->CreateTime.QuadPart); KDPrint(3,("!!!!! SRB:%p CCB:%p CCB->CreateTime: %I64u!!!!!!\n", srb, Ccb, Ccb->CreateTime.QuadPart)); ACQUIRE_SPIN_LOCK(&HwDeviceExtension->LanscsiAdapterSpinLock, &oldIrql); if( Ccb->CreateTime.QuadPart <= HwDeviceExtension->LastBusResetTime.QuadPart + BUSRESET_EFFECT_TICKCOUNT || ADAPTER_ISSTATUSFLAG(HwDeviceExtension, ADAPTER_STATUSFLAG_BUSRESET_PENDING) ) { ADAPTER_RESETSTATUSFLAG(HwDeviceExtension, ADAPTER_STATUSFLAG_BUSRESET_PENDING); RELEASE_SPIN_LOCK(&HwDeviceExtension->LanscsiAdapterSpinLock, oldIrql); KDPrint(1,("!!!!!! BusReset occured after this CCB has entered." " Make it completed with Timer. CCB->CreateTime: %I64u!!!!!!\n", Ccb->CreateTime.QuadPart)); LSCcbSetStatusFlag(Ccb, CCBSTATUS_FLAG_TIMER_COMPLETE); } else { RELEASE_SPIN_LOCK(&HwDeviceExtension->LanscsiAdapterSpinLock, oldIrql); } // // Check reconnecting process. // Translate CCB to SRB. // if(LSCcbIsStatusFlagOn(Ccb, CCBSTATUS_FLAG_RECONNECTING)) { ACQUIRE_SPIN_LOCK(&HwDeviceExtension->LanscsiAdapterSpinLock, &oldIrql); if(!ADAPTER_ISSTATUSFLAG(HwDeviceExtension, ADAPTER_STATUSFLAG_RECONNECTPENDING)) { UINT32 AdapterStatus; AdapterStatus = ADAPTER_SETSTATUSFLAG(HwDeviceExtension, ADAPTER_STATUSFLAG_RECONNECTPENDING); RELEASE_SPIN_LOCK(&HwDeviceExtension->LanscsiAdapterSpinLock, oldIrql); UpdatePdoInfoInLSBus(HwDeviceExtension, AdapterStatus); KDPrint(1,("Ccb:%p CcbStatus %d. Start reconnecting\n", Ccb, Ccb->CcbStatus)); } else { RELEASE_SPIN_LOCK(&HwDeviceExtension->LanscsiAdapterSpinLock, oldIrql); } } else { // // If CCbStatus != CCB_STATUS_STOP, reconnecting is successful. // if(Ccb->CcbStatus != CCB_STATUS_STOP) { ACQUIRE_SPIN_LOCK(&HwDeviceExtension->LanscsiAdapterSpinLock, &oldIrql); if(ADAPTER_ISSTATUSFLAG(HwDeviceExtension, ADAPTER_STATUSFLAG_RECONNECTPENDING)) { UINT32 AdapterStatus; AdapterStatus = ADAPTER_RESETSTATUSFLAG(HwDeviceExtension, ADAPTER_STATUSFLAG_RECONNECTPENDING); RELEASE_SPIN_LOCK(&HwDeviceExtension->LanscsiAdapterSpinLock, oldIrql); UpdatePdoInfoInLSBus(HwDeviceExtension, AdapterStatus); KDPrint(1,("Ccb:%p CcbStatus %d. Finish reconnecting\n", Ccb, Ccb->CcbStatus)); } else { RELEASE_SPIN_LOCK(&HwDeviceExtension->LanscsiAdapterSpinLock, oldIrql); } } } // // If CCB_OPCODE_UPDATE is successful, update adapter status in LanscsiBus // if(Ccb->OperationCode == CCB_OPCODE_UPDATE && Ccb->CcbStatus == CCB_STATUS_SUCCESS) { UINT32 AdapterStatus; ACQUIRE_SPIN_LOCK(&HwDeviceExtension->LanscsiAdapterSpinLock, &oldIrql); AdapterStatus = HwDeviceExtension->AdapterStatus; RELEASE_SPIN_LOCK(&HwDeviceExtension->LanscsiAdapterSpinLock, oldIrql); UpdatePdoInfoInLSBus(HwDeviceExtension, AdapterStatus); } KDPrint(3,("CcbStatus %d\n", Ccb->CcbStatus)); // // Translate CcbStatus to SrbStatus // switch(Ccb->CcbStatus) { case CCB_STATUS_SUCCESS: srb->SrbStatus = SRB_STATUS_SUCCESS; srb->ScsiStatus = SCSISTAT_GOOD; // // Check to see if the associate member is in error. // if(LSCcbIsStatusFlagOn(Ccb, CCBSTATUS_FLAG_LURN_STOP)) { ACQUIRE_SPIN_LOCK(&HwDeviceExtension->LanscsiAdapterSpinLock, &oldIrql); if(!ADAPTER_ISSTATUSFLAG(HwDeviceExtension, ADAPTER_STATUSFLAG_MEMBER_FAULT)) { UINT32 AdapterStatus; AdapterStatus = ADAPTER_SETSTATUSFLAG(HwDeviceExtension, ADAPTER_STATUSFLAG_MEMBER_FAULT); RELEASE_SPIN_LOCK(&HwDeviceExtension->LanscsiAdapterSpinLock, oldIrql); UpdatePdoInfoInLSBus(HwDeviceExtension, AdapterStatus); KDPrint(1,("Ccb:%p CcbStatus %d. Associate member is in error.\n", Ccb, Ccb->CcbStatus)); // // Send DisconEvent to the service. // TODO: alternate to AlarmEvent. // KeSetEvent(HwDeviceExtension->DisconEventToService, IO_NO_INCREMENT, FALSE); } else { RELEASE_SPIN_LOCK(&HwDeviceExtension->LanscsiAdapterSpinLock, oldIrql); } } break; case CCB_STATUS_NOT_EXIST: srb->SrbStatus = SRB_STATUS_NO_DEVICE; srb->ScsiStatus = SCSISTAT_GOOD; break; case CCB_STATUS_INVALID_COMMAND: srb->SrbStatus = SRB_STATUS_INVALID_REQUEST; srb->ScsiStatus = SCSISTAT_GOOD; break; case CCB_STATUS_COMMAND_FAILED: srb->SrbStatus = SRB_STATUS_ERROR | SRB_STATUS_AUTOSENSE_VALID; srb->ScsiStatus = SCSISTAT_CHECK_CONDITION; srb->DataTransferLength -= Ccb->ResidualDataLength; break; // Added by ILGU HONG 2004_07_05 case CCB_STATUS_COMMMAND_DONE_SENSE: srb->SrbStatus = SRB_STATUS_ERROR | SRB_STATUS_AUTOSENSE_VALID ; srb->DataTransferLength = 0; srb->ScsiStatus = SCSISTAT_GOOD; break; // Added by ILGU HONG 2004_07_05 end case CCB_STATUS_RESET: srb->SrbStatus = SRB_STATUS_BUS_RESET; srb->ScsiStatus = SCSISTAT_GOOD; break; case CCB_STATUS_COMMUNICATION_ERROR: { PSENSE_DATA senseData; srb->SrbStatus = SRB_STATUS_ERROR | SRB_STATUS_AUTOSENSE_VALID; srb->ScsiStatus = SCSISTAT_CHECK_CONDITION; srb->DataTransferLength = 0; senseData = srb->SenseInfoBuffer; senseData->ErrorCode = 0x70; senseData->Valid = 1; //senseData->SegmentNumber = 0; senseData->SenseKey = SCSI_SENSE_HARDWARE_ERROR; //SCSI_SENSE_MISCOMPARE; //senseData->IncorrectLength = 0; //senseData->EndOfMedia = 0; //senseData->FileMark = 0; senseData->AdditionalSenseLength = 0xb; senseData->AdditionalSenseCode = SCSI_ADSENSE_NO_SENSE; senseData->AdditionalSenseCodeQualifier = 0; } break; case CCB_STATUS_BUSY: srb->SrbStatus = SRB_STATUS_BUSY; srb->ScsiStatus = SCSISTAT_GOOD; KDPrint(1,("CCB_STATUS_BUSY\n")); break; // // Stop one LUR // case CCB_STATUS_STOP: { KDPrint(1,("CCB_STATUS_STOP. Stopping!\n")); srb->SrbStatus = SRB_STATUS_NO_DEVICE; srb->ScsiStatus = SCSISTAT_GOOD; MiniStopAdapter(HwDeviceExtension, TRUE); break; } default: // Error in Connection... // CCB_STATUS_UNKNOWN_STATUS, CCB_STATUS_RESET, and so on. srb->SrbStatus = SRB_STATUS_ERROR; srb->ScsiStatus = SCSISTAT_GOOD; } // // Process Abort CCB. // abortCcb = Ccb->AbortCcb; if(abortCcb != NULL) { KDPrint(1,("abortSrb\n")); ASSERT(FALSE); srb->SrbStatus = SRB_STATUS_SUCCESS; LSCcbSetStatusFlag(Ccb, CCBSTATUS_FLAG_TIMER_COMPLETE); InitializeListHead(&Ccb->ListEntry); ExInterlockedInsertTailList( &HwDeviceExtension->CcbCompletionList, &Ccb->ListEntry, &HwDeviceExtension->CcbCompletionListSpinLock ); ((PSCSI_REQUEST_BLOCK)abortCcb->Srb)->SrbStatus = SRB_STATUS_ABORTED; LSCcbSetStatusFlag(abortCcb, CCBSTATUS_FLAG_TIMER_COMPLETE); InitializeListHead(&abortCcb->ListEntry); ExInterlockedInsertTailList( &HwDeviceExtension->CcbCompletionList, &abortCcb->ListEntry, &HwDeviceExtension->CcbCompletionListSpinLock ); } else { // // Make Complete IRP and Send it. // // // In case of HostStatus == CCB_STATUS_SUCCESS_TIMER, CCB will go to the timer to complete. // if( (Ccb->CcbStatus == CCB_STATUS_SUCCESS || Ccb->CcbStatus == CCB_STATUS_INVALID_COMMAND) && !LSCcbIsStatusFlagOn(Ccb, CCBSTATUS_FLAG_TIMER_COMPLETE) && !LSCcbIsStatusFlagOn(Ccb, CCBSTATUS_FLAG_BUSRESET_REQUIRED) ) { PDEVICE_OBJECT pDeviceObject = HwDeviceExtension->ScsiportFdoObject; PIRP pCompletionIrp = NULL; PIO_STACK_LOCATION pIoStack; NTSTATUS ntStatus; PSCSI_REQUEST_BLOCK completionSrb = NULL; PCOMPLETION_DATA completionData = NULL; completionSrb = ExAllocatePoolWithTag(NonPagedPool, sizeof(SCSI_REQUEST_BLOCK), LSMP_PTAG_SRB); if(completionSrb == NULL) goto Out; RtlZeroMemory( completionSrb, sizeof(SCSI_REQUEST_BLOCK) ); // Build New IRP. pCompletionIrp = IoAllocateIrp((CCHAR)(pDeviceObject->StackSize + 1), FALSE); if(pCompletionIrp == NULL) { ExFreePoolWithTag(completionSrb, LSMP_PTAG_SRB); goto Out; } completionData = ExAllocatePoolWithTag(NonPagedPool, sizeof(COMPLETION_DATA), LSMP_PTAG_CMPDATA); if(completionData == NULL) { ExFreePoolWithTag(completionSrb, LSMP_PTAG_SRB); IoFreeIrp(pCompletionIrp); pCompletionIrp = NULL; goto Out; } pCompletionIrp->MdlAddress = NULL; // Set IRP stack location. pIoStack = IoGetNextIrpStackLocation(pCompletionIrp); pIoStack->DeviceObject = pDeviceObject; pIoStack->MajorFunction = IRP_MJ_SCSI; pIoStack->Parameters.DeviceIoControl.InputBufferLength = 0; pIoStack->Parameters.DeviceIoControl.OutputBufferLength = 0; pIoStack->Parameters.Scsi.Srb = completionSrb; // Set SRB. completionSrb->Length = sizeof(SCSI_REQUEST_BLOCK); completionSrb->Function = SRB_FUNCTION_EXECUTE_SCSI; completionSrb->PathId = srb->PathId; completionSrb->TargetId = srb->TargetId; completionSrb->Lun = srb->Lun; completionSrb->QueueAction = SRB_SIMPLE_TAG_REQUEST; completionSrb->DataBuffer = srb; completionSrb->SrbFlags |= SRB_FLAGS_BYPASS_FROZEN_QUEUE | SRB_FLAGS_NO_QUEUE_FREEZE; completionSrb->OriginalRequest = pCompletionIrp; completionSrb->CdbLength = MAXIMUM_CDB_SIZE; completionSrb->Cdb[0] = SCSIOP_COMPLETE; completionSrb->Cdb[1] = (UCHAR)srbSeqIncremented; completionSrb->TimeOutValue = 20; completionSrb->SrbStatus = SRB_STATUS_SUCCESS; // // Set compeltion data for the completion IRP. // completionData->HwDeviceExtension = HwDeviceExtension; completionData->CompletionSrb = completionSrb; completionData->ShippedCcb = Ccb; completionData->ShippedCcbAllocatedFromPool = LSCcbIsFlagOn(Ccb, CCB_FLAG_ALLOCATED); Out: KDPrint(4,("Before Completion\n")); if(pCompletionIrp) { IoSetCompletionRoutine(pCompletionIrp, CompletionIrpCompletionRoutine, completionData, TRUE, TRUE, TRUE); ASSERT(HwDeviceExtension->RequestExecuting != 0); // // call Scsiport FDO. // ntStatus = IoCallDriver(pDeviceObject, pCompletionIrp); ASSERT(NT_SUCCESS(ntStatus)); #if DBG if(ntStatus!= STATUS_SUCCESS && ntStatus!= STATUS_PENDING) { KDPrint(1,("ntStatus = 0x%x\n", ntStatus)); } #endif }else { KDPrint(1,("CompletionIRP NULL. CCB(%p) and SRB(%p) is going to the timer. CcbStatus:%x CcbFlag:%x\n", Ccb, Ccb->Srb, Ccb->CcbStatus, Ccb->Flags)); InitializeListHead(&Ccb->ListEntry); LSCcbSetStatusFlag(Ccb, CCBSTATUS_FLAG_TIMER_COMPLETE); ExInterlockedInsertTailList( &HwDeviceExtension->CcbCompletionList, &Ccb->ListEntry, &HwDeviceExtension->CcbCompletionListSpinLock ); } } else { KDPrint(1,("CCB(%p) and SRB(%p) is going to the timer. CcbStatus:%x CcbFlag:%x\n", Ccb, Ccb->Srb, Ccb->CcbStatus, Ccb->Flags)); InitializeListHead(&Ccb->ListEntry); LSCcbSetStatusFlag(Ccb, CCBSTATUS_FLAG_TIMER_COMPLETE); ExInterlockedInsertTailList( &HwDeviceExtension->CcbCompletionList, &Ccb->ListEntry, &HwDeviceExtension->CcbCompletionListSpinLock ); } } return return_status; }