コード例 #1
0
//
//	Complete all Ccb in a list.
//
VOID
CcbCompleteList(
		PLIST_ENTRY	Head,
		CHAR		CcbStatus,
		USHORT		StatusFlags
	) {
	PLIST_ENTRY	listEntry;
	PCCB		ccb;

	while(1) {
		listEntry = RemoveHeadList(Head);
		if(listEntry==Head)
			break;

		ccb = CONTAINING_RECORD(listEntry, CCB, ListEntry);
		ccb->CcbStatus=CcbStatus;

		//
		//	We do not allow to set CCBSTATUS_FLAG_PENDING and CCBSTATUS_FLAG_COMPLETED except for CcbCompletion function.
		//
		LSCcbSetStatusFlag(ccb, CCBSTATUS_FLAG_TIMER_COMPLETE| (StatusFlags & CCBSTATUS_FLAG_ASSIGNMASK));
		LSCcbCompleteCcb(ccb);
		KDPrintM(DBG_LURN_ERROR, ("Completed Ccb:%p\n", ccb));
	}
}
コード例 #2
0
//
//	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;
}
コード例 #3
0
//
//	Complete a Ccb
//
//	We can set the CCBSTATUS_FLAG_COMPLETED flag only in this function
//
VOID
LSCcbCompleteCcb(
		IN PCCB Ccb
	) {
	LONG		idx_sl;
	NTSTATUS	status;

	ASSERT(Ccb->Type == LSSTRUC_TYPE_CCB);
	ASSERT(Ccb->Length == sizeof(CCB));
	ASSERT(!LSCcbIsStatusFlagOn(Ccb,CCBSTATUS_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));

	LSCcbSetStatusFlag(Ccb, CCBSTATUS_FLAG_COMPLETED);
	LSCcbResetStatusFlag(Ccb, CCBSTATUS_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;
			}
			KDPrintM(DBG_CCB_TRACE, ("Ccb=%p, completion complete.\n", Ccb));
		}
	}

	//
	//	Do post operation
	//
	LSCcbPostCompleteCcb(Ccb);
}
コード例 #4
0
//
//	Complete a Ccb
//
VOID
LSCcbPostCompleteCcb(
		IN PCCB Ccb
	) {
	PKEVENT	event;
	ASSERT(Ccb->Type == LSSTRUC_TYPE_CCB);
	ASSERT(Ccb->Length == sizeof(CCB));
	ASSERT(LSCcbIsStatusFlagOn(Ccb,CCBSTATUS_FLAG_COMPLETED));
	ASSERT(Ccb->AssociateCount == 0);
	ASSERT(Ccb->CcbCurrentStackLocationIndex <= NR_MAX_CCB_STACKLOCATION);
	ASSERT(Ccb->CcbCurrentStackLocation == &Ccb->CcbStackLocation[Ccb->CcbCurrentStackLocationIndex]);

	if(LSCcbIsStatusFlagOn(Ccb,CCBSTATUS_FLAG_POST_COMPLETED)) {
		ASSERT(FALSE);
		return;
	}

	LSCcbSetStatusFlag(Ccb, CCBSTATUS_FLAG_POST_COMPLETED);

	event = Ccb->CompletionEvent;

	if(LSCcbIsFlagOn(Ccb, CCB_FLAG_DATABUF_ALLOCATED) && Ccb->DataBuffer && Ccb->DataBufferLength) {
		ASSERT(LSCcbIsFlagOn(Ccb, CCB_FLAG_ALLOCATED));
		KDPrintM(DBG_CCB_INFO, ("Freeing Ccb->DataBuffer=%p.\n", Ccb->DataBuffer));
		ExFreePool(Ccb->DataBuffer);
	}
	if(LSCcbIsFlagOn(Ccb, CCB_FLAG_ALLOCATED)) {
		KDPrintM(DBG_CCB_TRACE, ("Freeing Ccb=%p.\n", Ccb));
		LSCcbFree(Ccb);
	}

	//  You must not use any data in Ccb after KeSetEvent 
	// because caller will free Ccb after event received
	if(event) {
		KeSetEvent(event, IO_DISK_INCREMENT, FALSE);
	}
}
コード例 #5
0
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;
}
コード例 #6
0
NTSTATUS
RemoveDeviceFromMiniport_Worker(
		IN PDEVICE_OBJECT		DeviceObject,
		IN PNDSC_WORKITEM	WorkitemCtx
	) {
	PMINIPORT_DEVICE_EXTENSION	HwDeviceExtension;
	PMINIPORT_LU_EXTENSION		LuExtension;
	LONG						LURCount;
	KIRQL						oldIrql;
	PLURELATION					Lur;
	PCCB						Ccb;
	NTSTATUS					status;

	ASSERT(WorkitemCtx);
	UNREFERENCED_PARAMETER(DeviceObject);

	KDPrint(1,("Entered.\n"));

	LuExtension			= (PMINIPORT_LU_EXTENSION)WorkitemCtx->Arg1;
	HwDeviceExtension	= (PMINIPORT_DEVICE_EXTENSION)WorkitemCtx->Arg3;
	Ccb					= WorkitemCtx->Ccb;

	ACQUIRE_SPIN_LOCK(&HwDeviceExtension->LanscsiAdapterSpinLock, &oldIrql);

	//
	//	We support only one LUR for now.
	//
	Lur = HwDeviceExtension->LURs[0];
	HwDeviceExtension->LURs[0] = NULL;

	RELEASE_SPIN_LOCK(&HwDeviceExtension->LanscsiAdapterSpinLock, oldIrql);

	if(!Lur) {
		if(Ccb) {
			LSCcbSetStatus(Ccb, CCB_STATUS_NOT_EXIST);
			LSCcbCompleteCcb(Ccb);
		}

		NDScsiLogError(
			HwDeviceExtension,
			NULL,
			0,
			0,
			0,
			NDASSCSI_IO_STOPIOCTL_NO_LUR,
			EVTLOG_UNIQUEID(EVTLOG_MODULE_IOCTL, EVTLOG_FAIL_LURNULL, 0)
			);
		KDPrint(1,("Error! LUR is NULL!\n"));
		return STATUS_SUCCESS;
	}

	//
	//	send stop CCB
	//

	status = SendCcbToLURSync(HwDeviceExtension, Lur, CCB_OPCODE_STOP);
	if(NT_SUCCESS(status)){
		NDScsiLogError(
			HwDeviceExtension,
			NULL,
			0,
			0,
			0,
			NDASSCSI_IO_STOPIOCTL_LUR_ERROR,
			EVTLOG_UNIQUEID(EVTLOG_MODULE_IOCTL, EVTLOG_FAIL_SENDSTOPCCB, 0xffff & status)
			);
		KDPrint(1,("Failed to send stop ccb.\n"));
	}
	LurClose(Lur);
	LURCount = InterlockedDecrement(&HwDeviceExtension->LURCount);
	ASSERT(LURCount == 0);


	//
	//	Dereference the driver object for this LUR
	//

	if(Lur != NULL)
		ObDereferenceObject(_NdscGlobals.DriverObject);

	//
	//	Notify a bus change.
	//
	LSCcbSetStatusFlag(Ccb, CCBSTATUS_FLAG_BUSRESET_REQUIRED);
	LSCcbSetStatus(Ccb, CCB_STATUS_SUCCESS);
	LSCcbCompleteCcb(Ccb);

	return STATUS_SUCCESS;
}
コード例 #7
0
NTSTATUS
AddNewDeviceToMiniport_Worker(
		IN PDEVICE_OBJECT		DeviceObject,
		IN PNDSC_WORKITEM	WorkitemCtx
	) {
	PMINIPORT_DEVICE_EXTENSION	HwDeviceExtension;
	PMINIPORT_LU_EXTENSION		LuExtension;
	PCCB						Ccb;
	PLURELATION_DESC			LurDesc;
	PLURELATION					Lur;
	NTSTATUS					status;
	LONG						LURCount;
	UINT32						DefaultLurFlags;

	ASSERT(WorkitemCtx);
	UNREFERENCED_PARAMETER(DeviceObject);

	LuExtension =(PMINIPORT_LU_EXTENSION) WorkitemCtx->Arg1;
	LurDesc = (PLURELATION_DESC)WorkitemCtx->Arg2;
	HwDeviceExtension = (PMINIPORT_DEVICE_EXTENSION)WorkitemCtx->Arg3;
	Ccb = WorkitemCtx->Ccb;


	//
	//	Get default LUR flags.
	//

	GetDefaultLurFlags(LurDesc, &DefaultLurFlags);

	status = LurCreate(
				LurDesc,
				DefaultLurFlags,
				&Lur,
				0,
				HwDeviceExtension->ScsiportFdoObject,
				LsmpLurnCallback);
	if(NT_SUCCESS(status)) {
		LURCount = InterlockedIncrement(&HwDeviceExtension->LURCount);
		//
		//	We support only one LUR for now.
		//
		ASSERT(LURCount == 1);

		HwDeviceExtension->LURs[0] = Lur;
	}

	//
	//	Free LUR Descriptor
	//
	ExFreePoolWithTag(LurDesc, LSMP_PTAG_IOCTL);

	//
	//	Make a reference to driver object for each LUR creation
	//	to prevent from unloading unexpectedly.
	//	Must be decreased at each LUR deletion.
	//

	ObReferenceObject(_NdscGlobals.DriverObject);

	//
	//	Notify a bus change.
	//
	LSCcbSetStatusFlag(Ccb, CCBSTATUS_FLAG_BUSRESET_REQUIRED);

	LSCcbCompleteCcb(Ccb);

	return status;
}