예제 #1
0
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(4, ("Entered\n"));
	UNREFERENCED_PARAMETER(DeviceObject);

	if(completionSrb->DataBuffer) 
	{
		KDPrint(2, ("Unexpected IRP completion!!! "
			"Maybe completion SRB did not reach NDASSCSI's StartIo routine.\n"));
		ASSERT(completionSrb->DataBuffer);

		InterlockedDecrement(&HwDeviceExtension->RequestExecuting);
		LsuDecrementTdiClientInProgress();

		InitializeListHead(&shippedCcb->ListEntry);
		LsCcbSetStatusFlag(shippedCcb, CCBSTATUS_FLAG_TIMER_COMPLETE);
		ExInterlockedInsertTailList(
				&HwDeviceExtension->CcbTimerCompletionList,
				&shippedCcb->ListEntry,
				&HwDeviceExtension->CcbTimerCompletionListSpinLock
				);

		completionSrb->DataBuffer = NULL;
	} else {
		//
		//	Free the CCB if it is not going to the timer completion routine
		//	and allocated from the system pool by NDASSCSI.
		//
		if(Context->ShippedCcbAllocatedFromPool)
			LsCcbPostCompleteCcb(shippedCcb);
	}

	// Free resources
	ExFreePoolWithTag(completionSrb, NDSC_PTAG_SRB);
	ExFreePoolWithTag(Context, NDSC_PTAG_CMPDATA);
	IoFreeIrp(Irp);

	return STATUS_MORE_PROCESSING_REQUIRED;
}
예제 #2
0
NTSTATUS
NdasDluSrbIoctlSendCCBWithComp(
	IN PNDAS_LOGICALUNIT_EXTENSION	LogicalUnitExtension,
	IN PNDAS_DLU_EXTENSION			NdasDluLuExtension,
	IN PSCSI_REQUEST_BLOCK			Srb,
	IN UINT32						CcbOpCode,
	IN PVOID						CmdBuffer,
	IN ULONG						CmdBufferLen
){
	NTSTATUS	status;
	PCCB		ccb;


	//
	//	Query to the LUR
	//

	status = LsCcbAllocate(&ccb);
	if(!NT_SUCCESS(status)) {
		Srb->SrbStatus = SRB_STATUS_ERROR;
		KDPrint(1,("LsCcbAllocate() failed.\n"));
		return STATUS_SUCCESS;
	}

	LSCCB_INITIALIZE(ccb);
	ccb->OperationCode = CcbOpCode;
	LsCcbSetFlag(ccb, CCB_FLAG_ALLOCATED);
	ccb->Srb = Srb;
	ccb->DataBufferLength = CmdBufferLen;
	ccb->DataBuffer = CmdBuffer;
	LsCcbSetCompletionRoutine(ccb, NdasDluCcbCompletion, LogicalUnitExtension);

	InterlockedIncrement(&NdasDluLuExtension->RequestExecuting);
	LsuIncrementTdiClientInProgress();
	status = LurRequest(
		NdasDluLuExtension->LUR,
		ccb
		);
	if(!NT_SUCCESS(status)) {
		LsCcbFree(ccb);
		Srb->SrbStatus = SRB_STATUS_ERROR;
		LsuDecrementTdiClientInProgress();
		KDPrint(1,("LurRequest() failed.\n"));
		return STATUS_SUCCESS;
	}


	return STATUS_PENDING;
}
예제 #3
0
//
//	Open a device parameter registry.
//
NTSTATUS
DrOpenDeviceRegistry(
		PDEVICE_OBJECT	DeviceObject,
		HANDLE			*DeviceParamReg,
		ACCESS_MASK		AccessMask
	){
    HANDLE				regKey;
    NTSTATUS			status;

    //
    // Create or open the key.
    //
    status = IoOpenDeviceRegistryKey(
								DeviceObject,
								PLUGPLAY_REGKEY_DEVICE,
								AccessMask,
								&regKey);
    if(!NT_SUCCESS(status)) {
		KDPrint(1, ("IoOpenDeviceRegistryKey() failed. NTSTATUS:%08lx\n", status));
        regKey = NULL;
    }

	*DeviceParamReg = regKey;

    return status;
}
예제 #4
0
VOID
NdasMiniLogError(
	IN PMINIPORT_DEVICE_EXTENSION HwDeviceExtension,
	IN PSCSI_REQUEST_BLOCK Srb OPTIONAL,
	IN UCHAR PathId,
	IN UCHAR TargetId,
	IN UCHAR Lun,
	IN ULONG ErrorCode,
	IN ULONG UniqueId
){
	PDEVICE_OBJECT DeviceObject = HwDeviceExtension->ScsiportFdoObject;
	LSU_ERROR_LOG_ENTRY errorLogEntry;

	UNREFERENCED_PARAMETER(Srb);

	if(HwDeviceExtension == NULL) {
		KDPrint(2, ("HwDeviceExtension NULL!! \n"));
		return;
	}
	if(DeviceObject == NULL) {
		KDPrint(2, ("DeviceObject NULL!! \n"));
		return;
	}

	//
    // Save the error log data in the log entry.
    //

	errorLogEntry.ErrorCode = ErrorCode;
	errorLogEntry.MajorFunctionCode = IRP_MJ_SCSI;
	errorLogEntry.IoctlCode = 0;
    errorLogEntry.UniqueId = UniqueId;
	errorLogEntry.SequenceNumber = 0;
	errorLogEntry.ErrorLogRetryCount = 0;
	errorLogEntry.Parameter2 = HwDeviceExtension->SlotNumber;
	errorLogEntry.DumpDataEntry = 4;
	errorLogEntry.DumpData[0] = TargetId;
	errorLogEntry.DumpData[1] = Lun;
	errorLogEntry.DumpData[2] = PathId;
	errorLogEntry.DumpData[3] = ErrorCode;

	LsuWriteLogErrorEntry(DeviceObject, &errorLogEntry);

	return;
}
예제 #5
0
//////////////////////////////////////////////////////////////////////////
//
//	Registry primitives.
//
NTSTATUS
DrReadKeyValue(
		HANDLE	RegKey,
		PWCHAR	KeyName,
		ULONG	KeyType,
		PVOID	Buffer,
		ULONG	BufferLength,
		PULONG	BufferLengthNeeded
) {
	PKEY_VALUE_PARTIAL_INFORMATION	keyValue;
	NTSTATUS						status;
	ULONG							outLength;
	UNICODE_STRING					valueName;

	outLength = 0;
	keyValue = (PKEY_VALUE_PARTIAL_INFORMATION)ExAllocatePoolWithTag(PagedPool, 512, DEVREG_POOTAG_KEYINFO);
	if(keyValue == NULL)
		return STATUS_INSUFFICIENT_RESOURCES;
	RtlInitUnicodeString(&valueName, KeyName);
	status = ZwQueryValueKey(RegKey, &valueName, KeyValuePartialInformation, keyValue, 512, &outLength);
	if(BufferLengthNeeded) {
		*BufferLengthNeeded = keyValue->DataLength;
	}
	if(!NT_SUCCESS(status)) {
		KDPrint(1, ("ZwQueryValueKey() failed. ValueKeyName:%ws\n", KeyName));
		ExFreePool(keyValue);
		return	status;
	}
	if(keyValue->Type != KeyType) {
		KDPrint(1, ("Wrong value key type. ValueKeyName:%ws\n", KeyName));
		ExFreePool(keyValue);
		return	status;
	}
	if(BufferLength < keyValue->DataLength) {
		KDPrint(1, ("Buffer too small. ValueKeyName:%ws\n", KeyName));
		ExFreePool(keyValue);
		return STATUS_BUFFER_TOO_SMALL;
	}

	RtlCopyMemory(Buffer, keyValue->Data, keyValue->DataLength);

	ExFreePool(keyValue);
	return STATUS_SUCCESS;
}
예제 #6
0
NTSTATUS
RemoveDeviceFromMiniport(
		IN PMINIPORT_DEVICE_EXTENSION	HwDeviceExtension,
		IN PMINIPORT_LU_EXTENSION		LuExtension,
		IN PSCSI_REQUEST_BLOCK			Srb,
		IN ULONG						CurSrbSequence
	) {
	NDSC_WORKITEM_INIT			WorkitemCtx;
	NTSTATUS					status;
	PCCB						Ccb;

	//
	//	initilize Ccb in srb.
	//
	KDPrint(1, ("Entered.\n"));
	status = LSCcbAllocate(&Ccb);
	if(!NT_SUCCESS(status)) {
		KDPrint(1, ("failed.\n"));
		return status;
	}
	LSCcbInitialize(
					Srb,
					HwDeviceExtension,
					CurSrbSequence,
					Ccb
				);
	InterlockedIncrement(&HwDeviceExtension->RequestExecuting);
	LsuIncrementTdiClientInProgress();
	LSCcbSetCompletionRoutine(Ccb, NdscAdapterCompletion, HwDeviceExtension);
	LSCcbSetNextStackLocation(Ccb);

	//
	//	Queue a workitem
	//
	NDSC_INIT_WORKITEM(&WorkitemCtx, RemoveDeviceFromMiniport_Worker, Ccb, LuExtension, NULL, HwDeviceExtension);
	status = MiniQueueWorkItem(&_NdscGlobals, HwDeviceExtension->ScsiportFdoObject, &WorkitemCtx);
	if(NT_SUCCESS(status)) {
		status = STATUS_PENDING;
	}

	return status;
}
예제 #7
0
//
//	Complement Windows 2000's IoGetDeviceProperty()
//
NTSTATUS
DrGetDeviceProperty(
	IN PDEVICE_OBJECT  DeviceObject,
    IN DEVICE_REGISTRY_PROPERTY  DeviceProperty,
    IN ULONG	BufferLength,
    OUT PVOID	PropertyBuffer,
    OUT PULONG  ResultLength,
	IN BOOLEAN	Win2K
) {
	NTSTATUS	status;

	ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);

	if(!DeviceObject)
		return STATUS_INVALID_PARAMETER;
	if(Win2K) {
		status = DrGetDeviceProperty_ExtW2K(
							DeviceObject,
							DeviceProperty,
							BufferLength,
							PropertyBuffer,
							ResultLength
			);
	} else {

		__try {

			status = IoGetDeviceProperty(
							DeviceObject,
							DeviceProperty,
							BufferLength,
							PropertyBuffer,
							ResultLength
						);

		}  __except (EXCEPTION_EXECUTE_HANDLER) {

			status = GetExceptionCode();
			KDPrint(1, ("IoGetDeviceProperty() Exception: %08lx\n", status));

		}

	}


	return status;
}
예제 #8
0
NTSTATUS
NdasDluSendSrbIoCompletion(
    IN PDEVICE_OBJECT  DeviceObject,
    IN PIRP  Irp,
    IN PVOID  Context
){
	PMINISENDSRB_CONTEXT sendSrb = (PMINISENDSRB_CONTEXT)Context;

	UNREFERENCED_PARAMETER(DeviceObject);

	KDPrint(1,("STATUS=%08lx\n", Irp->IoStatus.Status));

	//
	//	get the result
	//
	if(Irp->IoStatus.Status == STATUS_SUCCESS) {
		if(sendSrb->UserBuffer && sendSrb->UserBufferLen)
			RtlCopyMemory(
					sendSrb->UserBuffer,
					(PUCHAR)&sendSrb->SrbIoctl + sizeof(SRB_IO_CONTROL),
					sendSrb->UserBufferLen);
	}
	// Free the IRP resources
	if(Irp->AssociatedIrp.SystemBuffer)
		ExFreePool(Irp->AssociatedIrp.SystemBuffer);
	if( Irp->MdlAddress != NULL ) {
		MmUnlockPages( Irp->MdlAddress );
		IoFreeMdl( Irp->MdlAddress );
		Irp->MdlAddress = NULL;
	}
	// Free the IRP
	IoFreeIrp(Irp);
	ExFreePool(sendSrb);

	return STATUS_MORE_PROCESSING_REQUIRED;
}
예제 #9
0
NTSTATUS
NdasDluIoctlDeviceLock(
	IN PNDAS_LOGICALUNIT_EXTENSION	LogicalUnitExtension,
	IN PNDAS_DLU_EXTENSION			DluLuExtension,
	IN PNDSCIOCTL_DEVICELOCK		DeviceLockControl,
	IN PSCSI_REQUEST_BLOCK			Srb
){
	NTSTATUS				status;
	PLURN_DEVLOCK_CONTROL	lurnDeviceLock;
	PCCB					ccb;
	PNDAS_DLU_EXTENSION		ndasDluExtension = NdasDluGetExtension(LogicalUnitExtension);


	//
	//	Create a CCB
	//
	status = LsCcbAllocate(&ccb);
	if(!NT_SUCCESS(status)) {
		Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
		KDPrint(1,("LsCcbAllocate() failed.\n"));
		return status;
	}
	lurnDeviceLock = (PLURN_DEVLOCK_CONTROL)ExAllocatePoolWithTag(NonPagedPool, sizeof(LURN_DEVLOCK_CONTROL), NDAS_DLU_PTAG_IOCTL);
	if(!lurnDeviceLock) {
		Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
		KDPrint(1,("ExAllocatePoolWithTag() failed.\n"));
		return STATUS_INSUFFICIENT_RESOURCES;
	}

	LSCCB_INITIALIZE(ccb);
	ccb->OperationCode = CCB_OPCODE_DEVLOCK;
	ccb->DataBuffer = lurnDeviceLock;
	ccb->DataBufferLength = sizeof(LURN_DEVLOCK_CONTROL);
	LsCcbSetFlag(ccb, CCB_FLAG_ALLOCATED|CCB_FLAG_DATABUF_ALLOCATED);

	//	Ioctl Srb will complete asynchronously.
	ccb->Srb = Srb;
	InterlockedIncrement(&DluLuExtension->RequestExecuting);

	//
	// Increment in-progress count
	//

	LsuIncrementTdiClientInProgress();
	LsCcbSetCompletionRoutine(ccb, NdasDluCcbCompletion, LogicalUnitExtension);

	//
	// Set up request
	//

	lurnDeviceLock->LockId = DeviceLockControl->LockId;
	lurnDeviceLock->LockOpCode = DeviceLockControl->LockOpCode;
	lurnDeviceLock->AdvancedLock	= DeviceLockControl->AdvancedLock;
	lurnDeviceLock->AddressRangeValid	= DeviceLockControl->AddressRangeValid;
	lurnDeviceLock->RequireLockAcquisition	= DeviceLockControl->RequireLockAcquisition;
	lurnDeviceLock->StartingAddress = DeviceLockControl->StartingAddress;
	lurnDeviceLock->ContentionTimeOut = DeviceLockControl->ContentionTimeOut;
	RtlCopyMemory(lurnDeviceLock->LockData, DeviceLockControl->LockData, 
		NDSCLOCK_LOCKDATA_LENGTH);
	ASSERT(NDSCLOCK_LOCKDATA_LENGTH == LURNDEVLOCK_LOCKDATA_LENGTH);

	//
	// Send the request
	//

	status = LurRequest(
		ndasDluExtension->LUR,
		ccb
		);
	if(!NT_SUCCESS(status)) {
		KDPrint(1,("LurnRequest() failed.\n"));
		LsCcbFree(ccb);
		ExFreePoolWithTag(lurnDeviceLock, NDSC_PTAG_IOCTL);
		status = STATUS_SUCCESS;
		Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
	} else {
		status = STATUS_PENDING;
	}

	return status;
}
예제 #10
0
NTSTATUS
NdasDluSrbIoctlQueryInfo(
		PNDAS_LOGICALUNIT_EXTENSION	LogicalUnitExtension,
		PNDAS_DLU_EXTENSION			DluLuExtension,
		PSCSI_REQUEST_BLOCK			Srb,
		PNDASSCSI_QUERY_INFO_DATA	QueryInfo,
		ULONG						OutputBufferLength,
		PUCHAR						OutputBuffer,
		PULONG						SrbIoctlReturnCode,
		PUCHAR						SrbStatus
) {
	NTSTATUS	status;
	PCCB		Ccb;
//	KIRQL		oldIrql;


	UNREFERENCED_PARAMETER(LogicalUnitExtension);
	UNREFERENCED_PARAMETER(DluLuExtension);

	*SrbIoctlReturnCode = SRB_STATUS_SUCCESS;
	*SrbStatus = SRB_STATUS_SUCCESS;
	status = STATUS_SUCCESS;
	switch(QueryInfo->InfoClass) {

	case NdscPrimaryUnitDiskInformation: {
		PNDSCIOCTL_PRIMUNITDISKINFO	primUnitDisk = (PNDSCIOCTL_PRIMUNITDISKINFO)OutputBuffer;
		PLUR_QUERY					lurQuery;
		PLURN_PRIMARYINFORMATION	lurPrimaryInfo;
		PBYTE						lurBuffer;

		KDPrint(1,("NdscPrimaryUnitDiskInformation\n"));

		if(OutputBufferLength < sizeof(NDSCIOCTL_PRIMUNITDISKINFO)) {
			KDPrint(1,("Too small output buffer\n"));
			*SrbStatus = SRB_STATUS_INVALID_REQUEST;
			status = STATUS_BUFFER_TOO_SMALL;
			if (OutputBufferLength > sizeof(UINT32)) 
				primUnitDisk->Length					= sizeof(NDSCIOCTL_PRIMUNITDISKINFO);
			break;
		}

		//
		//	Query to the LUR
		//
		status = LsCcbAllocate(&Ccb);
		if(!NT_SUCCESS(status)) {
			KDPrint(1,("LsCcbAllocate() failed.\n"));
			*SrbStatus = SRB_STATUS_INVALID_REQUEST;
			status = STATUS_INSUFFICIENT_RESOURCES;
			break;
		}

		lurBuffer = ExAllocatePoolWithTag(
							NonPagedPool,
							SIZE_OF_LURQUERY(0, sizeof(LURN_PRIMARYINFORMATION)),
							LURN_IOCTL_POOL_TAG);
		if(lurBuffer == NULL) {
			KDPrint(1,("LsCcbAllocate() failed.\n"));
			*SrbStatus = SRB_STATUS_INVALID_REQUEST;
			status = STATUS_INSUFFICIENT_RESOURCES;
			break;
		}

		//
		// Set up asynchronous CCB
		//

		LSCCB_INITIALIZE(Ccb);
		Ccb->Srb = Srb;
		Ccb->OperationCode = CCB_OPCODE_QUERY;
		LsCcbSetFlag(Ccb, CCB_FLAG_ALLOCATED|CCB_FLAG_DATABUF_ALLOCATED);
		Ccb->DataBuffer = lurBuffer;
		Ccb->DataBufferLength = sizeof(LURN_PRIMARYINFORMATION);
		LsCcbSetCompletionRoutine(Ccb, NdasDluCcbCompletion, DluLuExtension);
		InterlockedIncrement(&DluLuExtension->RequestExecuting);
		LsuIncrementTdiClientInProgress();

		lurQuery = (PLUR_QUERY)lurBuffer;
		lurQuery->InfoClass			= LurPrimaryLurnInformation;
		lurQuery->Length			= SIZE_OF_LURQUERY(0, sizeof(LURN_PRIMARYINFORMATION));
		lurQuery->QueryDataLength	= 0;

		lurPrimaryInfo = (PLURN_PRIMARYINFORMATION)LUR_QUERY_INFORMATION(lurQuery);

		if(DluLuExtension->LUR == NULL) {
			LsuDecrementTdiClientInProgress();
			InterlockedDecrement(&DluLuExtension->RequestExecuting);
			ExFreePoolWithTag(lurBuffer, LURN_IOCTL_POOL_TAG);
			LsCcbFree(Ccb);

			*SrbStatus = SRB_STATUS_INVALID_REQUEST;
			status = STATUS_INVALID_PARAMETER;
			break;
		}

		status = LurRequest(
							DluLuExtension->LUR,
							Ccb
						);
		if(!NT_SUCCESS(status)) {
			LsuDecrementTdiClientInProgress();
			InterlockedDecrement(&DluLuExtension->RequestExecuting);
			ExFreePoolWithTag(lurBuffer, LURN_IOCTL_POOL_TAG);
			LsCcbFree(Ccb);

			KDPrint(1,("LurRequest() failed.\n"));
			*SrbStatus = SRB_STATUS_INVALID_REQUEST;
			status = STATUS_INVALID_PARAMETER;
			break;
		}
		status = STATUS_PENDING;
		break;
		}

	case NdscLurInformation: {
		PNDSCIOCTL_LURINFO	info = (PNDSCIOCTL_LURINFO)OutputBuffer;
		PLUR_QUERY			lurQuery;
		UINT32				lurnEnumInfoLen;
		UINT32				nodeCount;

		KDPrint(1,("NdscLurInformation\n"));

		if(OutputBufferLength < FIELD_OFFSET(NDSCIOCTL_LURINFO, Lurns)) {
			KDPrint(2,("LurInfo: Buffer size %d is less than required %d bytes\n", OutputBufferLength, FIELD_OFFSET(NDSCIOCTL_LURINFO, Lurns)));
			*SrbStatus = SRB_STATUS_INVALID_REQUEST;
			status = STATUS_INVALID_PARAMETER;
			break;
		}

		//
		//	allocate a CCB
		//
		status = LsCcbAllocate(&Ccb);
		if(!NT_SUCCESS(status)) {
			KDPrint(1,("LsCcbAllocate() failed.\n"));
			*SrbStatus = SRB_STATUS_INVALID_REQUEST;
			break;
		}

		//
		//	initialize query CCB
		//
		LSCCB_INITIALIZE(Ccb);
		Ccb->Srb = Srb;
		Ccb->OperationCode = CCB_OPCODE_QUERY;
		LsCcbSetFlag(Ccb, CCB_FLAG_ALLOCATED|CCB_FLAG_DATABUF_ALLOCATED);

		if (DluLuExtension->LUR) {
			nodeCount = DluLuExtension->LUR->NodeCount;
		} else {
			nodeCount = 0;
			ASSERT(FALSE);
		}

		lurnEnumInfoLen = FIELD_OFFSET(LURN_ENUM_INFORMATION, Lurns) + sizeof(LURN_INFORMATION) * nodeCount;
		// Allocate memory and initialize it.
		LUR_QUERY_INITIALIZE(lurQuery, LurEnumerateLurn, 0, lurnEnumInfoLen);
		if(!lurQuery) {
			LsCcbFree(Ccb);

			KDPrint(1,("allocating DataBuffer failed.\n"));
			*SrbStatus = SRB_STATUS_INVALID_REQUEST;
			status = STATUS_INSUFFICIENT_RESOURCES;
			break;
		}

		Ccb->DataBuffer = lurQuery;
		Ccb->DataBufferLength = lurQuery->Length;

		//
		// Set completion routine
		//

		LsCcbSetCompletionRoutine(Ccb, NdasDluCcbCompletion, DluLuExtension);
		InterlockedIncrement(&DluLuExtension->RequestExecuting);
		LsuIncrementTdiClientInProgress();

		//
		//	send the CCB down
		//
		status = LurRequest(
							DluLuExtension->LUR,
							Ccb
						);
		if(!NT_SUCCESS(status)) {
			InterlockedDecrement(&DluLuExtension->RequestExecuting);
			LsuDecrementTdiClientInProgress();
			LsCcbFree(Ccb);

			KDPrint(1,("LurRequest() failed.\n"));
			ExFreePoolWithTag(lurQuery, NDSC_PTAG_IOCTL);
			*SrbStatus = SRB_STATUS_INVALID_REQUEST;
			status = STATUS_INVALID_PARAMETER;
			break;
		}
		status = STATUS_PENDING;
		break;
		}
	case NdscSystemBacl:
	case NdscUserBacl: {
		ULONG			requiredBufLen;
		PNDAS_BLOCK_ACL	ndasBacl = (PNDAS_BLOCK_ACL)OutputBuffer;
		PLSU_BLOCK_ACL	targetBacl;


		KDPrint(1,("NdscSystemBacl/UserBacl: going to default LuExtention 0.\n"));
		if(DluLuExtension->LUR == NULL) {
			*SrbStatus = SRB_STATUS_INVALID_REQUEST;
			status = STATUS_INVALID_PARAMETER;
			break;
		}

		if(QueryInfo->InfoClass == NdscSystemBacl)
			targetBacl = &DluLuExtension->LUR->SystemBacl;
		else
			targetBacl = &DluLuExtension->LUR->UserBacl;

		status = LsuConvertLsuBaclToNdasBacl(
								ndasBacl, 
								OutputBufferLength,
								&requiredBufLen,
								targetBacl);

		if(status == STATUS_BUFFER_TOO_SMALL) {
			//
			//	Set required field.
			//
			if(OutputBufferLength >= FIELD_OFFSET(NDAS_BLOCK_ACL, BlockACECnt)) {
				ndasBacl->Length = requiredBufLen;
			}
			//
			//	Set error code to the srb ioctl, but return success
			//
			*SrbIoctlReturnCode = SRB_STATUS_DATA_OVERRUN;

		} else if(!NT_SUCCESS(status)) {
			*SrbStatus = SRB_STATUS_ERROR;
			break;
		}

		*SrbStatus = SRB_STATUS_SUCCESS;
		status = STATUS_SUCCESS;
		break;
	}
	default:
		KDPrint(1,("Invalid Information Class!!\n"));
		*SrbStatus = SRB_STATUS_INVALID_REQUEST;
		status = STATUS_INVALID_PARAMETER;
	}

	return status;
}
예제 #11
0
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;
}
예제 #12
0
VOID
UpdatePdoInfoInLSBus(
		PMINIPORT_DEVICE_EXTENSION	HwDeviceExtension,
		UINT32						AdapterStatus
	) {
	PBUSENUM_SETPDOINFO			BusSet;
	UINT32						DesiredAccess;
	UINT32						GrantedAccess;

	ASSERT(HwDeviceExtension);

	//
	//	Query to the LUR
	//
	if(HwDeviceExtension->LURs[0]) {
		KDPrint(3,("going to default LuExtention 0.\n"));
		DesiredAccess = HwDeviceExtension->LURs[0]->DesiredAccess;
		GrantedAccess = HwDeviceExtension->LURs[0]->GrantedAccess;
	} else {
		KDPrint(1,("No LUR available..\n"));
		DesiredAccess = GrantedAccess = 0;
		return;
	}

	//
	//	Send to LSBus
	//
	BusSet = (PBUSENUM_SETPDOINFO)ExAllocatePoolWithTag(NonPagedPool, sizeof(BUSENUM_SETPDOINFO), LSMP_PTAG_IOCTL);
	if(BusSet == NULL) {
		return;
	}

	BusSet->Size			= sizeof(BUSENUM_SETPDOINFO);
	BusSet->SlotNo			= HwDeviceExtension->SlotNumber;
	BusSet->AdapterStatus	= AdapterStatus;
	BusSet->DesiredAccess	= DesiredAccess;
	BusSet->GrantedAccess	= GrantedAccess;

	if(KeGetCurrentIrql() == PASSIVE_LEVEL) {
		IoctlToLanscsiBus(
						IOCTL_LANSCSI_SETPDOINFO,
						BusSet,
						sizeof(BUSENUM_SETPDOINFO),
						NULL,
						0,
						NULL);
		if(HwDeviceExtension->AlarmEventToService) {
			KeSetEvent(HwDeviceExtension->AlarmEventToService, IO_NO_INCREMENT, FALSE);
		}
		ExFreePoolWithTag(BusSet, LSMP_PTAG_IOCTL);

	} else {

		//
		//	IoctlToLanscsiBus_Worker() will free memory of BusSet.
		//
		IoctlToLanscsiBusByWorker(
						HwDeviceExtension->ScsiportFdoObject,
						IOCTL_LANSCSI_SETPDOINFO,
						BusSet,
						sizeof(BUSENUM_SETPDOINFO),
						HwDeviceExtension->AlarmEventToService
					);
	}
}
예제 #13
0
//
// query scsiport PDO
//
ULONG
GetScsiAdapterPdoEnumInfo(
	IN PMINIPORT_DEVICE_EXTENSION	HwDeviceExtension,
	IN ULONG						SystemIoBusNumber,
	OUT PLONG						AddTargetDataLength,
	OUT PLANSCSI_ADD_TARGET_DATA	*AddTargetData
) {
	NTSTATUS						status;
	BUSENUM_QUERY_INFORMATION		BusQuery;
	PBUSENUM_INFORMATION			BusInfo;
	LONG							BufferNeeded;
	LONG							addTargetDataLength;
	PLANSCSI_ADD_TARGET_DATA		addTargetData;

	KDPrint(1,("SystemIoBusNumber:%d\n", SystemIoBusNumber));
	ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);

	BusQuery.Size = sizeof(BUSENUM_QUERY_INFORMATION);
	BusQuery.InfoClass = INFORMATION_PDOENUM;
	BusQuery.SlotNo = SystemIoBusNumber;

	//
	//	Get a buffer length needed.
	//
	status = IoctlToLanscsiBus(
						IOCTL_BUSENUM_QUERY_INFORMATION,
						&BusQuery,
						sizeof(BUSENUM_QUERY_INFORMATION),
						NULL,
						0,
						&BufferNeeded
					);
	if(status != STATUS_BUFFER_TOO_SMALL || BufferNeeded <= 0) {
		KDPrint(1,("IoctlToLanscsiBus() Failed.\n"));
		return SP_RETURN_NOT_FOUND;
	}

	//
	//
	//
	BusInfo= (PBUSENUM_INFORMATION)ExAllocatePoolWithTag(NonPagedPool, BufferNeeded, LSMP_PTAG_IOCTL);
	status = IoctlToLanscsiBus(
						IOCTL_BUSENUM_QUERY_INFORMATION,
						&BusQuery,
						sizeof(BUSENUM_QUERY_INFORMATION),
						BusInfo,
						BufferNeeded,
						&BufferNeeded
					);
	if(!NT_SUCCESS(status)) {
		ExFreePoolWithTag(BusInfo, LSMP_PTAG_IOCTL);
		return SP_RETURN_NOT_FOUND;
	}

	ASSERT(BusInfo->PdoEnumInfo.DisconEventToService);
	ASSERT(BusInfo->PdoEnumInfo.AlarmEventToService);
	HwDeviceExtension->MaxBlocksPerRequest	= BusInfo->PdoEnumInfo.MaxBlocksPerRequest;
	HwDeviceExtension->DisconEventToService	= BusInfo->PdoEnumInfo.DisconEventToService;
	HwDeviceExtension->AlarmEventToService	= BusInfo->PdoEnumInfo.AlarmEventToService;

	KDPrint(1,("MaxBlocksPerRequest:%d DisconEventToService:%p AlarmEventToService:%p\n",
						BusInfo->PdoEnumInfo.MaxBlocksPerRequest,
						BusInfo->PdoEnumInfo.DisconEventToService,
						BusInfo->PdoEnumInfo.AlarmEventToService
		));

	//
	//	copy LANSCSI_ADD_TARGET_DATA
	//
	addTargetDataLength = sizeof(LANSCSI_ADD_TARGET_DATA) + (BusInfo->PdoEnumInfo.AddTargetData.ulNumberOfUnitDiskList - 1) * sizeof(LSBUS_UNITDISK);
	addTargetData = (PLANSCSI_ADD_TARGET_DATA)ExAllocatePoolWithTag(NonPagedPool, addTargetDataLength, LSMP_PTAG_IOCTL);
	if(addTargetData == NULL) {
		ExFreePoolWithTag(BusInfo,LSMP_PTAG_IOCTL);
		return SP_RETURN_NOT_FOUND;
	}

	RtlCopyMemory(addTargetData, &BusInfo->PdoEnumInfo.AddTargetData, addTargetDataLength);
	*AddTargetData = addTargetData;
	*AddTargetDataLength = addTargetDataLength;

	ExFreePoolWithTag(BusInfo,LSMP_PTAG_IOCTL);
	return SP_RETURN_FOUND;
}
예제 #14
0
NTSTATUS
LurProcessWrite (
	PLURELATION	Lur,
	PCCB		WriteCommand
	)
{
	NTSTATUS	status;
	UINT64		writeAddr;
	UINT32		writeLen;


	//	Check to see if the write check (NDAS chip 2.0 bug patch) is required.
	//	Anyway this option is activated only when HW is 2.0 rev.0.
	//

	if (Lur->LurFlags & LURFLAG_WRITE_CHECK_REQUIRED) {

		LsCcbSetFlag(WriteCommand, CCB_FLAG_WRITE_CHECK);

	} else {

		LsCcbResetFlag(WriteCommand, CCB_FLAG_WRITE_CHECK);
	}

	if (WriteCommand->CdbLength == 10 || 
		WriteCommand->CdbLength == 16) {

		LsCcbGetAddressAndLength( &WriteCommand->SrbCdb, &writeAddr, &writeLen );
	
	} else {

		NDAS_ASSERT(FALSE);
		return STATUS_NOT_SUPPORTED;
	}

	if (writeAddr < Lur->MaxChildrenSectorCount && (writeAddr + writeLen) > Lur->UnitBlocks ) {

		NDAS_ASSERT(FALSE);

		WriteCommand->CcbStatus = CCB_STATUS_INVALID_COMMAND;
		LsCcbCompleteCcb( WriteCommand );
		status = STATUS_SUCCESS;
	}

	do {

		//	Layer 0
		//	User BACL

		status = FilterWriteByBACL( Lur,
									&Lur->UserBacl,
									(Lur->EnabledNdasFeatures & NDASFEATURE_RO_FAKE_WRITE) != 0,
									writeAddr,
									writeLen,
									WriteCommand );

		if (status != STATUS_NO_MORE_ENTRIES) {

			// If an BACE found, break here no matter what status
			// it returns. If not, go to the next layer
		
			break;
		}

		//	Layer 1
		//	out-of-bound access

		if (writeAddr > Lur->EndingBlockAddr) {

			NDAS_ASSERT(FALSE);

			//	If OOB write is neither enabled nor writable device access mode,
			//	deny it.

			if (!(Lur->EnabledNdasFeatures & NDASFEATURE_OOB_WRITE) &&
				!(Lur->DeviceMode & NDASACCRIGHT_WRITE)) {

				//	Complete the write command with an error.

				WriteCommand->CcbStatus = CCB_STATUS_INVALID_COMMAND;

				LsCcbCompleteCcb(WriteCommand);
				status = STATUS_SUCCESS;

				break;
			}

			//	If the write command is in safety area,
			//	deny it.

			if (writeAddr <= Lur->EndingBlockAddr + 256) {

				//	Complete the write command with an error.

				WriteCommand->CcbStatus = CCB_STATUS_INVALID_COMMAND;
				LsCcbCompleteCcb(WriteCommand);
				status = STATUS_SUCCESS;

				break;
			}

			// Turn off write-check for OOB access

			LsCcbResetFlag(WriteCommand, CCB_FLAG_WRITE_CHECK);			
			status = LurnRequest(LUR_GETROOTNODE(Lur), WriteCommand);

			break;
		}

		//	Layer 2
		//	Device mode

		if (Lur->DeviceMode == DEVMODE_SHARED_READONLY) {

			NDAS_ASSERT(FALSE);
		
			if (Lur->EnabledNdasFeatures & NDASFEATURE_RO_FAKE_WRITE) {

				//	Complete the write command

				KDPrint(1, ("Readonly fake write: command %p\n", WriteCommand));
				WriteCommand->CcbStatus = CCB_STATUS_SUCCESS;
				LsCcbCompleteCcb(WriteCommand);
				status = STATUS_SUCCESS;

				break;
			}

			WriteCommand->CcbStatus = CCB_STATUS_INVALID_COMMAND;
			LsCcbCompleteCcb(WriteCommand);
			status = STATUS_SUCCESS;

			break;

		} else if (Lur->DeviceMode ==  DEVMODE_SHARED_READWRITE) {

			//	If secondary, return write operation without actual write.
			//	If secondary wants to write, insert writable BACE.

			if (Lur->EnabledNdasFeatures & NDASFEATURE_SECONDARY) {

				NDAS_ASSERT(FALSE);

				//	Complete the write command

				KDPrint( 1, ("Secondary fake write: command %p\n", WriteCommand) );
				
				WriteCommand->CcbStatus = CCB_STATUS_SUCCESS;
				LsCcbCompleteCcb(WriteCommand);
				status = STATUS_SUCCESS;

				break;
			}

		} else if(Lur->DeviceMode == DEVMODE_EXCLUSIVE_READWRITE) {

			//	Nothing to do

		} else if(Lur->DeviceMode == DEVMODE_SUPER_READWRITE) {

			//	Nothing to do

		} else {

			//	Complete the write command

			WriteCommand->CcbStatus = CCB_STATUS_INVALID_COMMAND;
			LsCcbCompleteCcb(WriteCommand);
			status = STATUS_SUCCESS;

			break;
		}

		//	Layer 3
		//	Disk DIB BACL

		status = FilterWriteByBACL( Lur,
									&Lur->SystemBacl,
									(Lur->EnabledNdasFeatures & NDASFEATURE_RO_FAKE_WRITE) != 0,
									writeAddr,
									writeLen,
									WriteCommand );

		if (status == STATUS_NO_MORE_ENTRIES) {

			//	No BACL filtered. Just write it.

			status = LurnRequest( LUR_GETROOTNODE(Lur), WriteCommand );
		}

	} while(0);

	return status;
}
예제 #15
0
NTSTATUS
DrGetDevicePropertyInstallState(
	IN PDEVICE_OBJECT  DeviceObject,
    IN ULONG  BufferLength,
    OUT PVOID  PropertyBuffer,
    OUT PULONG  ResultLength
) {
	NTSTATUS		status;
	HANDLE			devparamRegKey;
	HANDLE			devInstRegKey;
	UNICODE_STRING valueName;
	UCHAR			keyValueBuffer[KVLEN_PARTIAL];
	PKEY_VALUE_PARTIAL_INFORMATION  keyValue;
	ULONG			resultLength;
	PULONG			configFlags;
	DEVICE_INSTALL_STATE deviceInstallState;
	PVOID			Object;
	UCHAR					ObjectNameBuffer[512];
	POBJECT_NAME_INFORMATION ObjectNameInfo;
	OBJECT_ATTRIBUTES		objectAttributes;


	//
	//	init
	//
	devInstRegKey = NULL;
	devparamRegKey = NULL;
	keyValue = (PKEY_VALUE_PARTIAL_INFORMATION)keyValueBuffer;
	if(BufferLength < sizeof(DEVICE_INSTALL_STATE)) {
		return STATUS_INSUFFICIENT_RESOURCES;
	}

	//
	//	open the device registry's parameter key
	//
	status = IoOpenDeviceRegistryKey(
					DeviceObject,
					PLUGPLAY_REGKEY_DEVICE,
					KEY_QUERY_VALUE|KEY_ENUMERATE_SUB_KEYS,
					&devparamRegKey
				);
	if(!NT_SUCCESS(status)) {
		devInstRegKey = NULL;
		goto cleanup;
	}
	status = ObReferenceObjectByHandle(
							devparamRegKey,
							GENERIC_READ,
							NULL,
							KernelMode,
							&Object,
							NULL
					);
	if(!NT_SUCCESS(status)) {
		goto cleanup;
	}

	ObjectNameInfo = (POBJECT_NAME_INFORMATION)ObjectNameBuffer;
	status = ObQueryNameString(Object, ObjectNameInfo, sizeof(ObjectNameBuffer), &resultLength );
	ObDereferenceObject(Object);
	if(!NT_SUCCESS(status) || ObjectNameInfo->Name.Buffer == NULL) {
		goto cleanup;
	}
	KDPrint(1, ("Device parameter path: %ws. len=%d\n", ObjectNameInfo->Name.Buffer,ObjectNameInfo->Name.Length));

	ASSERT(ObjectNameInfo->Name.Length < sizeof(ObjectNameBuffer) - 20);
	// trim down to the first parent.
	for(; ObjectNameInfo->Name.Length > 1; ObjectNameInfo->Name.Length-=sizeof(WCHAR) ) {
		if( ObjectNameInfo->Name.Buffer[ObjectNameInfo->Name.Length/sizeof(WCHAR) - 1] == '\\') {
			ObjectNameInfo->Name.Length-=sizeof(WCHAR);
			KDPrint(1, ("Trimed at the index %d\n", ObjectNameInfo->Name.Length));
			break;
		}
	}

	KDPrint(1, ("Device parameter path: %ws. len=%d\n", ObjectNameInfo->Name.Buffer,ObjectNameInfo->Name.Length));
	if(ObjectNameInfo->Name.Length <= 1) {
		goto cleanup;
	}

	//
	//	Open device registry.
	//
	InitializeObjectAttributes(
					&objectAttributes,
					&ObjectNameInfo->Name,
					OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE,
					NULL,
					NULL
				);
	status = ZwOpenKey(&devInstRegKey, KEY_QUERY_VALUE|KEY_ENUMERATE_SUB_KEYS, &objectAttributes);
	if(!NT_SUCCESS(status)) {
		goto cleanup;
	}

	//
	//	Query the value of CONFIGFLAGS
	//
	RtlInitUnicodeString(&valueName, REGSTR_VAL_CONFIGFLAGS);
	status = ZwQueryValueKey(
			devInstRegKey,
			&valueName,
			KeyValuePartialInformation,
			keyValue,
			KVLEN_PARTIAL,
			&resultLength
		);
	if(!NT_SUCCESS(status)) {
		goto cleanup;
	}
	if(keyValue->Type != REG_DWORD) {
		goto cleanup;
	}
	if(keyValue->DataLength != sizeof(ULONG)) {
		goto cleanup;
	}

	//
	//	determine deviceInstallState
	//
	// TODO: If the device object is root device,
	//			always return InstallStateInstalled.
	//
	configFlags = (PULONG)keyValue->Data;
	if ((*configFlags) & CONFIGFLAG_REINSTALL) {

		deviceInstallState = InstallStateNeedsReinstall;

	} else if ((*configFlags) & CONFIGFLAG_FAILEDINSTALL) {

		deviceInstallState = InstallStateFailedInstall;

	} else if ((*configFlags) & CONFIGFLAG_FINISH_INSTALL) {

		deviceInstallState = InstallStateFinishInstall;
	} else {

		deviceInstallState = InstallStateInstalled;
	}

	//
	//	set the result
	//
	(*(PDEVICE_INSTALL_STATE)PropertyBuffer) = deviceInstallState;
	*ResultLength = sizeof(DEVICE_INSTALL_STATE);

cleanup:
	if(devInstRegKey)
		ZwClose(devInstRegKey);
	if(devparamRegKey)
		ZwClose(devparamRegKey);

	return status;
}
예제 #16
0
NTSTATUS
DrDeleteAllSubKeys(
		HANDLE				ParentKey
	) {

	NTSTATUS					status;
	PKEY_BASIC_INFORMATION		keyInfo;
	ULONG						outLength;
	ULONG						idxKey;
	OBJECT_ATTRIBUTES			objectAttributes;
	UNICODE_STRING				objectName;
	HANDLE						childKey;

	keyInfo = (PKEY_BASIC_INFORMATION)ExAllocatePoolWithTag(PagedPool, 512, DEVREG_POOTAG_KEYINFO);
	if(!keyInfo) {
		KDPrint(1, ("ExAllocatePoolWithTag(KEY_BASIC_INFORMATION) failed.\n"));
		return STATUS_INSUFFICIENT_RESOURCES;
	}

	status = STATUS_SUCCESS;
	for(idxKey = 0 ; idxKey < DEVREG_MAX_REGISTRY_KEY; idxKey ++) {
		status = ZwEnumerateKey(
						ParentKey,
						idxKey,
						KeyBasicInformation,
						keyInfo,
						512,
						&outLength
						);

		if(status == STATUS_NO_MORE_ENTRIES) {
			KDPrint(1, ("No more entries.\n"));
			status = STATUS_SUCCESS;
			break;
		}
		if(status != STATUS_SUCCESS) {
			ASSERT(status != STATUS_BUFFER_OVERFLOW && status != STATUS_BUFFER_TOO_SMALL);
			KDPrint(1, ("ZwEnumerateKey() failed. NTSTATUS:%08lx\n", status));
			ExFreePool(keyInfo);
			return STATUS_SUCCESS;
		}


		//
		//	Open a sub key
		//
		objectName.Length = objectName.MaximumLength = (USHORT)keyInfo->NameLength;
		objectName.Buffer = keyInfo->Name;
		InitializeObjectAttributes(		&objectAttributes,
										&objectName,
										OBJ_KERNEL_HANDLE,
										ParentKey,
										NULL
								);
		status = ZwOpenKey(&childKey, KEY_ALL_ACCESS, &objectAttributes);
		if(!NT_SUCCESS(status)) {
			KDPrint(1, ("ZwOpenKey() failed. NTSTATUS:%08lx\n", status));
			continue;
		}

		//
		//	Delete all subkeys
		//
		status = DrDeleteAllSubKeys(childKey);
		if(!NT_SUCCESS(status)) {
			KDPrint(1, ("Recursive DrDeleteAllSubKeys() failed. NTSTATUS:%08lx\n", status));
			ZwClose(childKey);
			continue;
		}

		//
		//	Delete NDAS device instance.
		//
		status = ZwDeleteKey(childKey);
#if DBG
		if(!NT_SUCCESS(status)) {
			KDPrint(1, ("ZwDeleteKey() failed. NTSTATUS:%08lx\n", status));
		}
#endif
		ZwClose(childKey);

		//
		//	One key was deleted, decrement key index.
		//

		idxKey--;

	}

	ExFreePool(keyInfo);
	return STATUS_SUCCESS;
}
예제 #17
0
VOID
CcbStatusToSrbStatus(PCCB Ccb, PSCSI_REQUEST_BLOCK Srb) {

	Srb->DataTransferLength -= Ccb->ResidualDataLength;

	switch(Ccb->CcbStatus) {
		case CCB_STATUS_SUCCESS:

			Srb->SrbStatus = SRB_STATUS_SUCCESS;
			Srb->ScsiStatus = SCSISTAT_GOOD;
			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_LOST_LOCK:
		case CCB_STATUS_COMMAND_FAILED:

			Srb->SrbStatus = SRB_STATUS_ERROR | SRB_STATUS_AUTOSENSE_VALID;
			Srb->ScsiStatus = SCSISTAT_CHECK_CONDITION;
			break;

		case CCB_STATUS_COMMMAND_DONE_SENSE2:
			Srb->SrbStatus =  SRB_STATUS_BUSY  | SRB_STATUS_AUTOSENSE_VALID ;
			Srb->DataTransferLength = 0;
			Srb->ScsiStatus = SCSISTAT_GOOD;
			break;

		case CCB_STATUS_COMMMAND_DONE_SENSE:
			Srb->SrbStatus =  SRB_STATUS_ERROR | SRB_STATUS_AUTOSENSE_VALID ;
			Srb->DataTransferLength = 0;
			Srb->ScsiStatus = SCSISTAT_CHECK_CONDITION;
			break;

		case CCB_STATUS_RESET:

			Srb->SrbStatus = SRB_STATUS_BUS_RESET;
			Srb->ScsiStatus = SCSISTAT_GOOD;
			break;

		case CCB_STATUS_DATA_OVERRUN:
			Srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
			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(2,("CCB_STATUS_BUSY\n"));
			break;

			//
			//	Stop one LUR
			//
		case CCB_STATUS_STOP: {
			Srb->SrbStatus = SRB_STATUS_BUS_RESET;
			Srb->ScsiStatus = SCSISTAT_GOOD;
			Srb->DataTransferLength = 0;
			KDPrint(2,("CCB_STATUS_STOP. Stopping!\n"));
			break;
		}
		default:
			ASSERT(FALSE);
			// Error in Connection...
			// CCB_STATUS_UNKNOWN_STATUS, CCB_STATUS_RESET, and so on.
			Srb->SrbStatus = SRB_STATUS_ERROR;
			Srb->ScsiStatus = SCSISTAT_GOOD;
			Srb->DataTransferLength = 0;
	}
}
예제 #18
0
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;
}
예제 #19
0
static
NTSTATUS
NdscCopyQueryOutputToSrb(
	PMINIPORT_DEVICE_EXTENSION	HwDeviceExtension,
	ULONG						CcbBufferLength,
	PUCHAR						CcbBuffer,
	ULONG						SrbIoctlBufferLength,
	PUCHAR						SrbIoctlBuffer
){
	NTSTATUS		status;
	PLUR_QUERY		lurQuery;

	lurQuery = (PLUR_QUERY)CcbBuffer;
	if(CcbBufferLength < FIELD_OFFSET(LUR_QUERY, QueryDataLength)) {
		return STATUS_INVALID_PARAMETER;
	}

	status = STATUS_SUCCESS;
	switch(lurQuery->InfoClass) {
		case LurPrimaryLurnInformation: { // NdscPrimaryUnitDiskInformation
			PLURN_PRIMARYINFORMATION	lurPrimaryInfo = (PLURN_PRIMARYINFORMATION)LUR_QUERY_INFORMATION(lurQuery);
			PNDSCIOCTL_PRIMUNITDISKINFO	primUnitDisk = (PNDSCIOCTL_PRIMUNITDISKINFO)SrbIoctlBuffer;

			if(CcbBufferLength < sizeof(LURN_PRIMARYINFORMATION)) {
				return STATUS_INVALID_PARAMETER;
			}
			if(SrbIoctlBufferLength < sizeof(NDSCIOCTL_PRIMUNITDISKINFO)) {
				return STATUS_INVALID_PARAMETER;
			}

			//
			//	Set length.
			//
			primUnitDisk->Length					= sizeof(NDSCIOCTL_PRIMUNITDISKINFO);
			primUnitDisk->UnitDisk.Length			= sizeof(NDSC_UNITDISK);
			//
			//	Adapter information
			//
			primUnitDisk->EnabledTime.QuadPart		=	HwDeviceExtension->EnabledTime.QuadPart;

			//
			// LUR information ( Scsi LU information )
			//
			primUnitDisk->Lur.Length		= sizeof(NDSC_LUR);
			primUnitDisk->Lur.DevType		= HwDeviceExtension->LURs[0]->DevType;
			primUnitDisk->Lur.TargetId		= HwDeviceExtension->LURs[0]->LurId[1];
			primUnitDisk->Lur.Lun			= HwDeviceExtension->LURs[0]->LurId[2];
			primUnitDisk->Lur.LurnCnt		= HwDeviceExtension->LURs[0]->NodeCount;
			primUnitDisk->Lur.DeviceMode	= HwDeviceExtension->LURs[0]->DeviceMode;
			primUnitDisk->Lur.SupportedFeatures	= HwDeviceExtension->LURs[0]->SupportedNdasFeatures;
			primUnitDisk->Lur.EnabledFeatures	= HwDeviceExtension->LURs[0]->EnabledNdasFeatures;

			//
			//	Unit device
			//

			primUnitDisk->UnitDisk.UnitDiskId		= lurPrimaryInfo->PrimaryLurn.UnitDiskId;
			primUnitDisk->UnitDisk.Connections		= lurPrimaryInfo->PrimaryLurn.Connections;
			primUnitDisk->UnitDisk.GrantedAccess	= lurPrimaryInfo->PrimaryLurn.AccessRight;
			RtlCopyMemory(
				primUnitDisk->UnitDisk.UserID,
				&lurPrimaryInfo->PrimaryLurn.UserID,
				sizeof(primUnitDisk->UnitDisk.UserID)
				);
			RtlCopyMemory(
				primUnitDisk->UnitDisk.Password,
				&lurPrimaryInfo->PrimaryLurn.Password,
				sizeof(primUnitDisk->UnitDisk.Password)
				);

#if 0
			RtlCopyMemory(	&primUnitDisk->UnitDisk.NetDiskAddress,
				&lurPrimaryInfo->PrimaryLurn.NetDiskAddress,
				sizeof(TA_LSTRANS_ADDRESS)
				);

			RtlCopyMemory(	&primUnitDisk->UnitDisk.BindingAddress,
				&lurPrimaryInfo->PrimaryLurn.BindingAddress,
				sizeof(TA_LSTRANS_ADDRESS)
				);

#else

			primUnitDisk->UnitDisk.NetDiskAddress.TAAddressCount = 1;
			primUnitDisk->UnitDisk.NetDiskAddress.Address[0].AddressLength 
				= lurPrimaryInfo->PrimaryLurn.NdasNetDiskAddress.AddressLength;
			primUnitDisk->UnitDisk.NetDiskAddress.Address[0].AddressType = 
				lurPrimaryInfo->PrimaryLurn.NdasNetDiskAddress.AddressType;
			
			RtlCopyMemory( &primUnitDisk->UnitDisk.NetDiskAddress.Address[0].Address,
						   &lurPrimaryInfo->PrimaryLurn.NdasNetDiskAddress.Address[0], 
					   	   lurPrimaryInfo->PrimaryLurn.NdasNetDiskAddress.AddressLength );

			primUnitDisk->UnitDisk.BindingAddress.TAAddressCount = 1;
			primUnitDisk->UnitDisk.BindingAddress.Address[0].AddressLength 
				= lurPrimaryInfo->PrimaryLurn.NdasBindingAddress.AddressLength;
			primUnitDisk->UnitDisk.BindingAddress.Address[0].AddressType = 
				lurPrimaryInfo->PrimaryLurn.NdasBindingAddress.AddressType;
			
			RtlCopyMemory( &primUnitDisk->UnitDisk.BindingAddress.Address[0].Address,
						   &lurPrimaryInfo->PrimaryLurn.NdasBindingAddress.Address[0], 
					   	   lurPrimaryInfo->PrimaryLurn.NdasBindingAddress.AddressLength );

#endif

			primUnitDisk->UnitDisk.UnitBlocks		= (UINT32)lurPrimaryInfo->PrimaryLurn.UnitBlocks;
			primUnitDisk->UnitDisk.SlotNo			= HwDeviceExtension->SlotNumber;
			RtlCopyMemory(primUnitDisk->NDSC_ID, lurPrimaryInfo->PrimaryLurn.PrimaryId, LURN_PRIMARY_ID_LENGTH);

			KDPrint(2,("NDSC_ID: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
				primUnitDisk->NDSC_ID[0], primUnitDisk->NDSC_ID[1], primUnitDisk->NDSC_ID[2], primUnitDisk->NDSC_ID[3], 
				primUnitDisk->NDSC_ID[4], primUnitDisk->NDSC_ID[5], primUnitDisk->NDSC_ID[6], primUnitDisk->NDSC_ID[7], 
				primUnitDisk->NDSC_ID[8], primUnitDisk->NDSC_ID[9], primUnitDisk->NDSC_ID[10], primUnitDisk->NDSC_ID[11], 
				primUnitDisk->NDSC_ID[12], primUnitDisk->NDSC_ID[13], primUnitDisk->NDSC_ID[14], primUnitDisk->NDSC_ID[15])
				);
		break;
		}
		case LurEnumerateLurn: { // NdscLurInformation
			PLURN_ENUM_INFORMATION	lurnEnumInfo = (PLURN_ENUM_INFORMATION)LUR_QUERY_INFORMATION(lurQuery);
			PNDSCIOCTL_LURINFO		info = (PNDSCIOCTL_LURINFO)SrbIoctlBuffer;
			NDAS_DEV_ACCESSMODE		deviceMode;
			NDAS_FEATURES			supportedNdasFeatures, enabledNdasFeatures;
			PNDSC_LURN_FULL			unitDisk;
			ULONG					idx_lurn;
			PLURN_INFORMATION		lurnInformation;
			ULONG					returnLength;
			UINT32				nodeCount;

			if(CcbBufferLength < sizeof(LURN_PRIMARYINFORMATION)) {
				return STATUS_INVALID_PARAMETER;
			}
			if(SrbIoctlBufferLength < FIELD_OFFSET(NDSCIOCTL_LURINFO, Reserved1)) {
				return STATUS_INVALID_PARAMETER;
			}

			if (HwDeviceExtension->LURs[0]) {
				ASSERT(HwDeviceExtension->LURs[0]->NodeCount >= 1);
				deviceMode = HwDeviceExtension->LURs[0]->DeviceMode;
				supportedNdasFeatures = HwDeviceExtension->LURs[0]->SupportedNdasFeatures;
				enabledNdasFeatures = HwDeviceExtension->LURs[0]->EnabledNdasFeatures;
				nodeCount = HwDeviceExtension->LURs[0]->NodeCount;
			} else {
				deviceMode = 0;
				supportedNdasFeatures = 0;
				enabledNdasFeatures = 0;
				nodeCount = 0;
			}

			//
			//	Adapter information
			//

			info->Length			=	FIELD_OFFSET(NDSCIOCTL_LURINFO, Lurns) +
										sizeof(NDSC_LURN_FULL) *
										nodeCount;

			// return length check
			returnLength = FIELD_OFFSET(NDSCIOCTL_LURINFO, Lurns);
			if(SrbIoctlBufferLength < returnLength) {
				return STATUS_BUFFER_TOO_SMALL;
			}

			info->EnabledTime.QuadPart					=	HwDeviceExtension->EnabledTime.QuadPart;
			info->Lur.Length		= sizeof(NDSC_LUR);
			info->Lur.DevType		= HwDeviceExtension->LURs[0]->DevType;
			info->Lur.TargetId		= HwDeviceExtension->LURs[0]->LurId[1];
			info->Lur.Lun			= HwDeviceExtension->LURs[0]->LurId[2];
			info->Lur.LurnCnt		= HwDeviceExtension->LURs[0]->NodeCount;
			info->LurnCnt		= info->Lur.LurnCnt;
			info->Lur.DeviceMode = deviceMode;
			info->Lur.SupportedFeatures = supportedNdasFeatures;
			info->Lur.EnabledFeatures = enabledNdasFeatures;

			//
			//	Set return values for each LURN.
			//
			for(idx_lurn = 0; idx_lurn < info->LurnCnt; idx_lurn++) {

				//
				//	Add one LURN to return bytes and check the user buffer size.
				//
				returnLength += sizeof(NDSC_LURN_FULL);
				if(SrbIoctlBufferLength < returnLength) {
					status = STATUS_BUFFER_TOO_SMALL;
					// Do not exit. Must return full length.
					continue;
				}

				unitDisk = info->Lurns + idx_lurn;
				lurnInformation = lurnEnumInfo->Lurns + idx_lurn;

				unitDisk->Length = sizeof(NDSC_LURN_FULL);
				unitDisk->UnitDiskId = lurnInformation->UnitDiskId;
				unitDisk->Connections = lurnInformation->Connections;
				unitDisk->AccessRight = lurnInformation->AccessRight;
				unitDisk->UnitBlocks = lurnInformation->UnitBlocks;
				unitDisk->StatusFlags = lurnInformation->StatusFlags;
				unitDisk->LurnId = lurnInformation->LurnId;
				unitDisk->LurnType = lurnInformation->LurnType;
				unitDisk->StatusFlags = lurnInformation->StatusFlags;

				RtlCopyMemory(
					unitDisk->UserID,
					&lurnInformation->UserID,
					sizeof(unitDisk->UserID)
					);

				RtlCopyMemory(
					unitDisk->Password,
					&lurnInformation->Password,
					sizeof(unitDisk->Password)
					);

#if 0
				RtlCopyMemory(	&unitDisk->NetDiskAddress,
					&lurnInformation->NetDiskAddress,
					sizeof(TA_LSTRANS_ADDRESS)
					);
				RtlCopyMemory(	&unitDisk->BindingAddress,
					&lurnInformation->BindingAddress,
					sizeof(TA_LSTRANS_ADDRESS)
					);
#else

			unitDisk->NetDiskAddress.TAAddressCount = 1;
			unitDisk->NetDiskAddress.Address[0].AddressLength 
				= lurnInformation->NdasNetDiskAddress.AddressLength;
			unitDisk->NetDiskAddress.Address[0].AddressType = 
				lurnInformation->NdasNetDiskAddress.AddressType;
			
			RtlCopyMemory( &unitDisk->NetDiskAddress.Address[0].Address,
						   &lurnInformation->NdasNetDiskAddress.Address[0], 
					   	   lurnInformation->NdasNetDiskAddress.AddressLength );

			unitDisk->BindingAddress.TAAddressCount = 1;
			unitDisk->BindingAddress.Address[0].AddressLength 
				= lurnInformation->NdasBindingAddress.AddressLength;
			unitDisk->BindingAddress.Address[0].AddressType = 
				lurnInformation->NdasBindingAddress.AddressType;
			
			RtlCopyMemory( &unitDisk->BindingAddress.Address[0].Address,
						   &lurnInformation->NdasBindingAddress.Address[0], 
					   	   lurnInformation->NdasBindingAddress.AddressLength );

#endif

			}
			break;
		 }

		default:
			status = STATUS_INVALID_PARAMETER;
		break;
	}

	return status;
}
예제 #20
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;
}
예제 #21
0
NTSTATUS
NdasDluSendIoctlSrb(
		IN PDEVICE_OBJECT	DeviceObject,
		IN ULONG			IoctlCode,
		IN PVOID			InputBuffer,
		IN LONG				InputBufferLength,
		OUT PVOID			OutputBuffer,
		IN LONG				OutputBufferLength
	) {

    PIRP				irp;
    KEVENT				event;
	PSRB_IO_CONTROL		psrbIoctl;
	LONG				srbIoctlLength;
	PVOID				srbIoctlBuffer;
	LONG				srbIoctlBufferLength;
    NTSTATUS			status;
    PIO_STACK_LOCATION	irpStack;
    SCSI_REQUEST_BLOCK	srb;
    LARGE_INTEGER		startingOffset;
    IO_STATUS_BLOCK		ioStatusBlock;

	ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);

	psrbIoctl	= NULL;
	irp = NULL;

	//
	//	build an SRB for the miniport
	//
	srbIoctlBufferLength = (InputBufferLength>OutputBufferLength)?InputBufferLength:OutputBufferLength;
	srbIoctlLength = sizeof(SRB_IO_CONTROL) +  srbIoctlBufferLength;

	psrbIoctl = (PSRB_IO_CONTROL)ExAllocatePoolWithTag(NonPagedPool , srbIoctlLength, NDAS_DLU_PTAG_SRB_IOCTL);
	if(psrbIoctl == NULL) {
		KDPrint(1, ("STATUS_INSUFFICIENT_RESOURCES\n"));
		status = STATUS_INSUFFICIENT_RESOURCES;
		goto cleanup;
	}

	RtlZeroMemory(psrbIoctl, srbIoctlLength);
	psrbIoctl->HeaderLength = sizeof(SRB_IO_CONTROL);
	RtlCopyMemory(psrbIoctl->Signature, NDASSCSI_IOCTL_SIGNATURE, 8);
	psrbIoctl->Timeout = 10;
	psrbIoctl->ControlCode = IoctlCode;
	psrbIoctl->Length = srbIoctlBufferLength;

	srbIoctlBuffer = (PUCHAR)psrbIoctl + sizeof(SRB_IO_CONTROL);
	RtlCopyMemory(srbIoctlBuffer, InputBuffer, InputBufferLength);

    //
    // Initialize the notification event.
    //

    KeInitializeEvent(&event,
                        NotificationEvent,
                        FALSE);
	startingOffset.QuadPart = 1;

    //
    // Build IRP for this request.
    // Note we do this synchronously for two reasons.  If it was done
    // asynchronously then the completion code would have to make a special
    // check to deallocate the buffer.  Second if a completion routine were
    // used then an additional IRP stack location would be needed.
    //

    irp = IoBuildSynchronousFsdRequest(
                IRP_MJ_SCSI,
                DeviceObject,
                psrbIoctl,
                srbIoctlLength,
                &startingOffset,
                &event,
                &ioStatusBlock);

    irpStack = IoGetNextIrpStackLocation(irp);

    if (irp == NULL) {
        KDPrint(1,("STATUS_INSUFFICIENT_RESOURCES\n"));

		status = STATUS_INSUFFICIENT_RESOURCES;
		goto cleanup;
    }

    //
    // Set major and minor codes.
    //

    irpStack->MajorFunction = IRP_MJ_SCSI;
    irpStack->MinorFunction = 1;

    //
    // Fill in SRB fields.
    //

    irpStack->Parameters.Others.Argument1 = &srb;

    //
    // Zero out the srb.
    //

    RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK));

    srb.PathId = 0;
    srb.TargetId = 0;
    srb.Lun = 0;

    srb.Function = SRB_FUNCTION_IO_CONTROL;
    srb.Length = sizeof(SCSI_REQUEST_BLOCK);

    srb.SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_NO_QUEUE_FREEZE;

	srb.QueueAction = SRB_SIMPLE_TAG_REQUEST;
	srb.QueueTag = SP_UNTAGGED;

    srb.OriginalRequest = irp;

    //
    // Set timeout to requested value.
    //

    srb.TimeOutValue = psrbIoctl->Timeout;

    //
    // Set the data buffer.
    //

    srb.DataBuffer = psrbIoctl;
    srb.DataTransferLength = srbIoctlLength;

    //
    // Flush the data buffer for output. This will insure that the data is
    // written back to memory.  Since the data-in flag is the the port driver
    // will flush the data again for input which will ensure the data is not
    // in the cache.
    //
/*
    KeFlushIoBuffers(irp->MdlAddress, FALSE, TRUE);
*/
    status = IoCallDriver( DeviceObject, irp );

    //
    // Wait for request to complete.
    //
    if (status == STATUS_PENDING) {

        (VOID)KeWaitForSingleObject( 
									&event,
                                     Executive,
                                     KernelMode,
                                     FALSE,
                                     (PLARGE_INTEGER)NULL 
									 );

        status = ioStatusBlock.Status;
    }

	//
	//	get the result
	//
	if(status == STATUS_SUCCESS) {
		if(OutputBuffer && OutputBufferLength)
			RtlCopyMemory(OutputBuffer, srbIoctlBuffer, OutputBufferLength);
			KDPrint(1,("Ioctl(%08lx) succeeded!\n", IoctlCode));
	}

cleanup:
	if(psrbIoctl)
		ExFreePool(psrbIoctl);

    return status;
}
예제 #22
0
NTSTATUS
LsuConfigureIdeDisk(
	IN PLANSCSI_SESSION	LSS,
	IN UCHAR			UdmaRestrict,
	OUT PULONG			PduFlags,
	OUT PBOOLEAN		Dma,
	OUT PULONG			BlockBytes
){
	NTSTATUS			status;
	struct hd_driveid	info;
	ULONG				pduFlags;
	BOOLEAN				setDmaMode;
	ULONG				blockBytes;
	LANSCSI_PDUDESC		pduDesc;
	UCHAR				pduResponse;

	//
	//	Get identify
	//

	status = LsuGetIdentify(LSS, &info);
	if(!NT_SUCCESS(status)) {
		KDPrint(1, ("LsuGetIdentify(1) failed. NTSTATUS: %08lx.\n", status));
		return status;
	}

	//
	// IO mode: DMA/PIO Mode.
	//
	KDPrintM(DBG_OTHER_INFO, ("Major 0x%x, Minor 0x%x, Capa 0x%x\n",
							info.major_rev_num,
							info.minor_rev_num,
							info.capability));
	KDPrintM(DBG_OTHER_INFO, ("DMA 0x%x, U-DMA 0x%x\n",
							info.dma_mword,
							info.dma_ultra));

	//
	//	determine IO mode ( UltraDMA, DMA, and PIO ) according to hardware versions and disk capacity.
	//
	setDmaMode = FALSE;
	pduFlags = 0;
	blockBytes = 512;

	do {
		UCHAR	DmaFeature;
		UCHAR	DmaMode;

		DmaFeature = 0;
		DmaMode = 0;

		//
		// Ultra DMA if NDAS chip is 2.0 or higher.
		//
		/*
			We don't support UDMA for 2.0 rev 0 due to the bug.
			The bug : Written data using UDMA will be corrupted
		*/
		if (
			(info.dma_ultra & 0x00ff) &&
			(
				(LANSCSIIDE_VERSION_2_0 < LSS->HWVersion) ||
				((LANSCSIIDE_VERSION_2_0 == LSS->HWVersion) && (0 != LSS->HWRevision))
			))
		{
			// Find Fastest Mode.
			if(info.dma_ultra & 0x0001)
				DmaMode = 0;
			if(info.dma_ultra & 0x0002)
				DmaMode = 1;
			if(info.dma_ultra & 0x0004)
				DmaMode = 2;
			//	if Cable80, try higher Ultra Dma Mode.
#ifdef __DETECT_CABLE80__
			if(info.hw_config & 0x2000) {
#endif
				if(info.dma_ultra & 0x0008)
					DmaMode = 3;
				if(info.dma_ultra & 0x0010)
					DmaMode = 4;
				if(info.dma_ultra & 0x0020)
					DmaMode = 5;
				if(info.dma_ultra & 0x0040)
					DmaMode = 6;
				if(info.dma_ultra & 0x0080)
					DmaMode = 7;

				//
				// If the ndas device is version 2.0 revision 100Mbps,
				// Restrict UDMA to mode 2.
				//

				if (LSS->HWVersion == LANSCSIIDE_VERSION_2_0 && 
					LSS->HWRevision == LANSCSIIDE_VER20_REV_100M) {

					if(DmaMode > 2)
						DmaMode = 2;
				}

				//
				// Restrict UDMA mode when requested.
				//

				if(UdmaRestrict != 0xff) {
					if(DmaMode > UdmaRestrict) {
						DmaMode = UdmaRestrict;
						KDPrintM(DBG_LURN_INFO, ("UDMA restriction applied. UDMA=%d\n", (ULONG)DmaMode));
					}
				}

#ifdef __DETECT_CABLE80__
			}
#endif
			KDPrintM(DBG_OTHER_INFO, ("Ultra DMA %d detected.\n", (int)DmaMode));
			DmaFeature = DmaMode | 0x40;	// Ultra DMA mode.
			pduFlags |= PDUDESC_FLAG_DMA|PDUDESC_FLAG_UDMA;

			// Set Ultra DMA mode if needed
			if(!(info.dma_ultra & (0x0100 << DmaMode))) {
				setDmaMode = TRUE;
			}

		//
		//	detect DMA
		//	Lower 8 bits of dma_mword represent supported dma modes.
		//
		} else if(info.dma_mword & 0x00ff) {
			if(info.dma_mword & 0x0001)
				DmaMode = 0;
			if(info.dma_mword & 0x0002)
				DmaMode = 1;
			if(info.dma_mword & 0x0004)
				DmaMode = 2;

			KDPrintM(DBG_OTHER_INFO, ("DMA mode %d detected.\n", (int)DmaMode));
			DmaFeature = DmaMode | 0x20;
			pduFlags |= PDUDESC_FLAG_DMA;

			// Set DMA mode if needed
			if(!(info.dma_mword & (0x0100 << DmaMode))) {
				setDmaMode = TRUE;
			}

		}

		// Set DMA mode if needed.
		if(setDmaMode) {
			LSS_INITIALIZE_PDUDESC(LSS, &pduDesc, IDE_COMMAND, WIN_SETFEATURES, 0, 0, 0, 0, NULL, NULL);
			pduDesc.Feature = SETFEATURES_XFER;
			pduDesc.BlockCount = DmaFeature;
			status = LspRequest(LSS, &pduDesc, &pduResponse);
			if(!NT_SUCCESS(status)) {
				KDPrintM(DBG_OTHER_ERROR, ("Set Feature Failed...\n"));
				return status;
			}
			if(pduResponse != LANSCSI_RESPONSE_SUCCESS) {
				KDPrintM(DBG_OTHER_ERROR, ("SETFEATURES: PduResponse=%x\n", (ULONG)pduResponse));
				return STATUS_UNSUCCESSFUL;
			}

			// identify.
			status = LsuGetIdentify(LSS, &info);
			if(!NT_SUCCESS(status)) {
				KDPrint(1, ("LsuGetIdentify(2) failed. NTSTATUS: %08lx.\n", status));
				return status;
			}
			KDPrintM(DBG_OTHER_INFO, ("After Set Feature DMA 0x%x, U-DMA 0x%x\n",
							info.dma_mword,
							info.dma_ultra));
		}
		if(pduFlags & PDUDESC_FLAG_DMA) {
			break;
		}
		//
		//	PIO.
		//
		KDPrintM(DBG_OTHER_ERROR, ("NetDisk does not support DMA mode. Turn to PIO mode.\n"));
		pduFlags |= PDUDESC_FLAG_PIO;

	} while(0);


	//
	// Bytes of sector
	//

	blockBytes = AtaGetBytesPerBlock(&info);

	//
	// LBA support
	//

	if(!(info.capability & 0x02)) {
		pduFlags &= ~PDUDESC_FLAG_LBA;
		ASSERT(FALSE);
	} else {
		pduFlags |= PDUDESC_FLAG_LBA;
	}

	//
	// LBA48 support
	//

	if(info.command_set_2 & 0x0400 || info.cfs_enable_2 & 0x0400) {	// Support LBA48bit
		pduFlags |= PDUDESC_FLAG_LBA48;

		//
		//	If LBA48 is on, LBA is also on.
		//

		pduFlags |= PDUDESC_FLAG_LBA;
	}

	KDPrint(1, ("LBA support: LBA %d, LBA48 %d\n",
		(pduFlags & PDUDESC_FLAG_LBA) != 0,
		(pduFlags & PDUDESC_FLAG_LBA48) != 0
		));


	//
	//	Set return values
	//

	if(PduFlags) {
		*PduFlags = pduFlags;
	}
	if(Dma) {
		if(pduFlags & (PDUDESC_FLAG_DMA|PDUDESC_FLAG_UDMA)) {
			*Dma = TRUE;
		} else {
			*Dma = FALSE;
		}
	}
	if(BlockBytes) {
		*BlockBytes = blockBytes;
	}

	return status;
}
예제 #23
0
NTSTATUS
NdasDluSendIoctlSrbAsynch(
		IN PDEVICE_OBJECT	DeviceObject,
		IN ULONG			IoctlCode,
		IN PVOID			InputBuffer,
		IN LONG				InputBufferLength,
		OUT PVOID			OutputBuffer,
		IN LONG				OutputBufferLength
){

    PIRP				irp;
	PMINISENDSRB_CONTEXT	context = NULL;
 	PSRB_IO_CONTROL		psrbIoctl;
	PSCSI_REQUEST_BLOCK	srb;
	LONG				srbIoctlLength;
	PVOID				srbIoctlBuffer;
	LONG				srbIoctlBufferLength;
    NTSTATUS			status;
    PIO_STACK_LOCATION	irpStack;
    LARGE_INTEGER		startingOffset;
    IO_STATUS_BLOCK		ioStatusBlock;

	ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);

	psrbIoctl	= NULL;
	irp = NULL;

	//
	//	build an SRB for the miniport
	//
	srbIoctlBufferLength = (InputBufferLength>OutputBufferLength)?InputBufferLength:OutputBufferLength;
	srbIoctlLength = sizeof(SRB_IO_CONTROL) +  srbIoctlBufferLength;

	context = (PMINISENDSRB_CONTEXT)ExAllocatePoolWithTag(NonPagedPool,
					FIELD_OFFSET(MINISENDSRB_CONTEXT, SrbIoctl) + srbIoctlLength,
					NDAS_DLU_PTAG_SRB_CMPDATA);
	if(context == NULL) {
		KDPrint(1, ("STATUS_INSUFFICIENT_RESOURCES\n"));
		status = STATUS_INSUFFICIENT_RESOURCES;
		goto cleanup;
	}

	context->UserBuffer = OutputBuffer;
	context->UserBufferLen = OutputBufferLength;
	srb = &context->Srb;
	psrbIoctl = &context->SrbIoctl;

	RtlZeroMemory(psrbIoctl, srbIoctlLength);
	psrbIoctl->HeaderLength = sizeof(SRB_IO_CONTROL);
	RtlCopyMemory(psrbIoctl->Signature, NDASSCSI_IOCTL_SIGNATURE, 8);
	psrbIoctl->Timeout = 10;
	psrbIoctl->ControlCode = IoctlCode;
	psrbIoctl->Length = srbIoctlBufferLength;

	srbIoctlBuffer = (PUCHAR)psrbIoctl + sizeof(SRB_IO_CONTROL);
	RtlCopyMemory(srbIoctlBuffer, InputBuffer, InputBufferLength);

	startingOffset.QuadPart = 1;

    //
    // Build IRP for this request.
    // Note we do this synchronously for two reasons.  If it was done
    // asynchronously then the completion code would have to make a special
    // check to deallocate the buffer.  Second if a completion routine were
    // used then an additional IRP stack location would be needed.
    //

    irp = IoBuildAsynchronousFsdRequest(
                 IRP_MJ_SCSI,
                DeviceObject,
                psrbIoctl,
                srbIoctlLength,
                &startingOffset,
                &ioStatusBlock);

	context->Irp = irp;
	IoSetCompletionRoutine(irp, NdasDluSendSrbIoCompletion, context, TRUE, TRUE, TRUE);
    irpStack = IoGetNextIrpStackLocation(irp);

    if (irp == NULL) {
        KDPrint(1,("STATUS_INSUFFICIENT_RESOURCES\n"));

		status = STATUS_INSUFFICIENT_RESOURCES;
		goto cleanup;
    }

    //
    // Set major and minor codes.
    //

    irpStack->MajorFunction = IRP_MJ_SCSI;
    irpStack->MinorFunction = 1;

    //
    // Fill in SRB fields.
    //

    irpStack->Parameters.Others.Argument1 = srb;

    //
    // Zero out the srb.
    //

    RtlZeroMemory(srb, sizeof(SCSI_REQUEST_BLOCK));

    srb->PathId = 0;
    srb->TargetId = 0;
    srb->Lun = 0;

    srb->Function = SRB_FUNCTION_IO_CONTROL;
    srb->Length = sizeof(SCSI_REQUEST_BLOCK);

    srb->SrbFlags = SRB_FLAGS_DATA_OUT | SRB_FLAGS_NO_QUEUE_FREEZE;

	srb->QueueAction = SRB_SIMPLE_TAG_REQUEST;
	srb->QueueTag = SP_UNTAGGED;

    srb->OriginalRequest = irp;

    //
    // Set timeout to requested value.
    //

    srb->TimeOutValue = psrbIoctl->Timeout;

    //
    // Set the data buffer.
    //

    srb->DataBuffer = psrbIoctl;
    srb->DataTransferLength = srbIoctlLength;

    //
    // Flush the data buffer for output. This will insure that the data is
    // written back to memory.  Since the data-in flag is the the port driver
    // will flush the data again for input which will ensure the data is not
    // in the cache.
    //
/*
    KeFlushIoBuffers(irp->MdlAddress, FALSE, TRUE);
*/
    status = IoCallDriver( DeviceObject, irp );

	return status;

cleanup:
	if(context)
		ExFreePool(context);

    return status;
}
예제 #24
0
//////////////////////////////////////////////////////////////////////////
//
//	Event log
//
static
VOID
_WriteLogErrorEntry(
	IN PDEVICE_OBJECT			DeviceObject,
	IN PLSU_ERROR_LOG_ENTRY		LogEntry
){
	PIO_ERROR_LOG_PACKET errorLogEntry;
	WCHAR					strBuff[16];
	NTSTATUS				status;
	ULONG					stringOffset;
	ULONG_PTR				stringLen;
	ULONG					idx_dump;

	//
	//	Parameter to unicode string
	//
	ASSERT(LogEntry->DumpDataEntry <= LSU_MAX_ERRLOG_DATA_ENTRIES);
	ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);

	status = RtlStringCchPrintfW(strBuff, 16, L"%u", LogEntry->Parameter2);
	if(!NT_SUCCESS(status)) {
		KDPrint(1, ("RtlStringCchVPrintfW() failed.\n"));
		return;
	}

	status = RtlStringCchLengthW(strBuff, 16, &stringLen);
	if(!NT_SUCCESS(status)) {
		KDPrint(1, ("RtlStringCchLengthW() failed.\n"));
		return;
	}

	//
	//	Translate unicode length into byte length including NULL termination.
	//

	stringLen = ( stringLen + 1 ) * sizeof(WCHAR);
	stringOffset = FIELD_OFFSET(IO_ERROR_LOG_PACKET, DumpData) + LogEntry->DumpDataEntry * sizeof(ULONG);


	errorLogEntry = (PIO_ERROR_LOG_PACKET)
					IoAllocateErrorLogEntry(
									DeviceObject,
									(sizeof(IO_ERROR_LOG_PACKET) +
									(LogEntry->DumpDataEntry * sizeof(ULONG)) +
									(UCHAR)stringLen));
	if(errorLogEntry == NULL) {
		KDPrint(1, ("Could not allocate error log entry.\n"));
		ASSERT(FALSE);
		return ;
	}

	errorLogEntry->ErrorCode = LogEntry->ErrorCode;
	errorLogEntry->MajorFunctionCode = LogEntry->MajorFunctionCode;
	errorLogEntry->IoControlCode = LogEntry->IoctlCode;
	errorLogEntry->EventCategory;
	errorLogEntry->SequenceNumber = LogEntry->SequenceNumber;
	errorLogEntry->RetryCount = (UCHAR) LogEntry->ErrorLogRetryCount;
	errorLogEntry->UniqueErrorValue = LogEntry->UniqueId;
	errorLogEntry->FinalStatus = STATUS_SUCCESS;
	errorLogEntry->DumpDataSize = LogEntry->DumpDataEntry * sizeof(ULONG);
	for(idx_dump=0; idx_dump < LogEntry->DumpDataEntry; idx_dump++) {
		errorLogEntry->DumpData[idx_dump] = LogEntry->DumpData[idx_dump];
	}

	errorLogEntry->NumberOfStrings = 1;
	errorLogEntry->StringOffset = (USHORT)stringOffset;
	RtlCopyMemory((PUCHAR)errorLogEntry + stringOffset, strBuff, stringLen);

	IoWriteErrorLogEntry(errorLogEntry);

	return;
}
예제 #25
0
UCHAR
NdasDluSrbIoctlGetDVDSTatus(
		PNDAS_LOGICALUNIT_EXTENSION	LogicalUnitExtension,
		PNDAS_DLU_EXTENSION			DluLuExtension,
		ULONG						OutputBufferLength,
		PUCHAR						OutputBuffer,
		PNTSTATUS					NtStatus
		
) {
	UCHAR				status;
	PCCB				Ccb;
	NTSTATUS			ntStatus;


	PNDASBUS_DVD_STATUS DvdStatusInfo = (PNDASBUS_DVD_STATUS)OutputBuffer; 
	BYTE				LurBuffer[sizeof(LURN_DVD_STATUS)];
	PLURN_DVD_STATUS	pDvdStatusHeader;


	UNREFERENCED_PARAMETER(LogicalUnitExtension);

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

	if(OutputBufferLength < sizeof(NDASBUS_DVD_STATUS)) {
		KDPrint(1,("Too small output buffer\n"));
		*NtStatus = STATUS_BUFFER_TOO_SMALL;
		status = SRB_STATUS_INVALID_REQUEST;
		return status;
	}

	//
	//	Query to the LUR
	//
	ntStatus = LsCcbAllocate(&Ccb);
	if(!NT_SUCCESS(ntStatus)) {
		KDPrint(1,("LsCcbAllocate() failed.\n"));
		*NtStatus = STATUS_INSUFFICIENT_RESOURCES;
		status = SRB_STATUS_INVALID_REQUEST;
		return status;
	}

	Ccb->OperationCode = CCB_OPCODE_DVD_STATUS;
	LsCcbSetFlag(Ccb, CCB_FLAG_SYNCHRONOUS|CCB_FLAG_ALLOCATED);
	Ccb->DataBuffer = LurBuffer;
	Ccb->DataBufferLength = sizeof(LURN_DVD_STATUS);
	
	pDvdStatusHeader = (PLURN_DVD_STATUS)LurBuffer;
	pDvdStatusHeader->Length = sizeof(LURN_DVD_STATUS);

	ntStatus = LurRequest(
						DluLuExtension->LUR,
						Ccb
					);

	if(!NT_SUCCESS(ntStatus)) {
		LsCcbFree(Ccb);

		KDPrint(1,("LurnRequest() failed.\n"));
		*NtStatus = STATUS_INSUFFICIENT_RESOURCES;
		status = SRB_STATUS_INVALID_REQUEST;
		return status;
	}
		
	//
	//	Set return values.
	//
	KDPrint(1,("Last Access Time :%I64d\n",pDvdStatusHeader->Last_Access_Time.QuadPart));
	KDPrint(1,("Result  %d\n",pDvdStatusHeader->Status));
	DvdStatusInfo->Status = pDvdStatusHeader->Status;
	*NtStatus = STATUS_SUCCESS;
	return SRB_STATUS_SUCCESS;
}
예제 #26
0
//
//	General ioctl to NDASBUS
//
NTSTATUS
IoctlToLanscsiBus(
	IN ULONG		IoControlCode,
    IN PVOID		InputBuffer  OPTIONAL,
    IN ULONG		InputBufferLength,
    OUT PVOID		OutputBuffer  OPTIONAL,
    IN ULONG		OutputBufferLength,
	OUT PULONG		BufferNeeded
)
{
	NTSTATUS			ntStatus;
	PWSTR				symbolicLinkList;
    UNICODE_STRING		objectName;
	PFILE_OBJECT		fileObject;
	PDEVICE_OBJECT		deviceObject;
	PIRP				irp;
    KEVENT				event;
    IO_STATUS_BLOCK		ioStatus;


	KDPrint(3,("IoControlCode = %x\n", IoControlCode));

	ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);

	ntStatus = IoGetDeviceInterfaces(
		&GUID_NDAS_BUS_ENUMERATOR_INTERFACE_CLASS,
		NULL,
		0,
		&symbolicLinkList
		);
	
	if(!NT_SUCCESS(ntStatus)) {
		KDPrint(2,("IoGetDeviceInterfaces ntStatus = 0x%x\n", ntStatus));
		return ntStatus;
	}
	
	ASSERT(symbolicLinkList != NULL);

	KDPrint(2,("symbolicLinkList = %ws\n", symbolicLinkList));

    RtlInitUnicodeString(&objectName, symbolicLinkList);
	ntStatus = IoGetDeviceObjectPointer(
					&objectName,
					FILE_ALL_ACCESS,
					&fileObject,
					&deviceObject
					);

	if(!NT_SUCCESS(ntStatus)) {
		KDPrint(2,("ntStatus = 0x%x\n", ntStatus));
		ExFreePool(symbolicLinkList);
		return ntStatus;
	}
	
    KeInitializeEvent(&event, NotificationEvent, FALSE);

	irp = IoBuildDeviceIoControlRequest(
			IoControlCode,
			deviceObject,
			InputBuffer,
			InputBufferLength,
			OutputBuffer,
			OutputBufferLength,
			FALSE,
			&event,
			&ioStatus
			);
	
    if (irp == NULL) {
		KDPrint(2,("irp NULL\n"));
		ExFreePool(symbolicLinkList);
		ObDereferenceObject(fileObject); 
		return ntStatus;
	}
	KDPrint(3,("Before Done...ioStatus.Status = 0x%08x Information = %d\n", ioStatus.Status, ioStatus.Information));

	ntStatus = IoCallDriver(deviceObject, irp);
    if (ntStatus == STATUS_PENDING)
    {
		KDPrint(2,("IoCallDriver STATUS_PENDING\n"));
		KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
        ntStatus = ioStatus.Status;
    } else if(NT_SUCCESS(ntStatus)) {
		ntStatus = ioStatus.Status;
    }

	if(BufferNeeded)
		*BufferNeeded = (ULONG)ioStatus.Information;

	ExFreePool(symbolicLinkList);
	ObDereferenceObject(fileObject);
	
	KDPrint(2,("Done...ioStatus.Status = 0x%08x Information = %d\n", ioStatus.Status, ioStatus.Information));
	
	return ntStatus;
}
예제 #27
0
NTSTATUS
NdasDluDiskClassControl(
	IN PNDAS_LOGICALUNIT_EXTENSION	LogicalUnitExtension,
	IN PNDAS_DLU_EXTENSION			NdasDluLuExtension,
	IN PSCSI_REQUEST_BLOCK			Srb
){
	//
	// The request is an I/O control request. The SRB DataBuffer points 
	// to an SRB_IO_CONTROL header followed by the data area. The value 
	// in DataBuffer can be used by the driver, regardless of the value 
	// of MapBuffers field. If the HBA miniport driver supports this 
	// request, it should execute the request and notify the OS-specific 
	// port driver when it has completed it, using the normal mechanism 
	// of NdasPortNotification with RequestComplete and NextLuRequest. 
	// Only the Function, SrbFlags, TimeOutValue, DataBuffer, 
	// DataTransferLength and SrbExtension are valid. 
	//
	NTSTATUS		status;
	PSRB_IO_CONTROL srbIoControl;
	PUCHAR			srbIoctlBuffer;
	LONG			srbIoctlBufferLength;

	status = STATUS_SUCCESS;

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

	//
	// Get the Ioctl buffer. If this is a send message request, it gets
	// fixed up to be an I2O message later.
	//
	srbIoControl = (PSRB_IO_CONTROL) Srb->DataBuffer;
	srbIoctlBuffer = ((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL);
	srbIoctlBufferLength = srbIoControl->Length;

#define IOCTL_SCSI_MINIPORT_READ_SMART_LOG          ((FILE_DEVICE_SCSI << 16) + 0x050b)
#define IOCTL_SCSI_MINIPORT_WRITE_SMART_LOG         ((FILE_DEVICE_SCSI << 16) + 0x050c)

	switch (srbIoControl->ControlCode)
	{
	//
	// support for Self-Monitoring Analysis and Reporting Technology (SMART)
	//
	case IOCTL_SCSI_MINIPORT_IDENTIFY:
	case IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS:
	case IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS:
	case IOCTL_SCSI_MINIPORT_ENABLE_SMART:
	case IOCTL_SCSI_MINIPORT_DISABLE_SMART:
	case IOCTL_SCSI_MINIPORT_RETURN_STATUS:
	case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE:
	case IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES:
	case IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS:
	case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTO_OFFLINE:
	case IOCTL_SCSI_MINIPORT_READ_SMART_LOG:
	case IOCTL_SCSI_MINIPORT_WRITE_SMART_LOG:
		status = NdasDluSrbIoctlSendCCBWithComp(
						LogicalUnitExtension,
						NdasDluLuExtension,
						Srb,
						CCB_OPCODE_SMART,
						srbIoctlBuffer,
						srbIoctlBufferLength);
		break;
	case IOCTL_SCSI_MINIPORT_SMART_VERSION:
		{
			PGETVERSIONINPARAMS getVersion;

			getVersion = (PGETVERSIONINPARAMS)srbIoctlBuffer;

			//
			// SMART 1.03
			//
			getVersion->bVersion = 1;
			getVersion->bRevision = 1;
			getVersion->bReserved = 0;

			//
			// TODO: Add CAP_ATAPI_ID_CMD
			//
			getVersion->fCapabilities = CAP_ATA_ID_CMD | CAP_SMART_CMD;
			//
			// Regardless of unit number, we exposes the logical unit
			// as a pseudo ATA primary master
			//
			getVersion->bIDEDeviceMap = 1;

			Srb->SrbStatus = SRB_STATUS_SUCCESS;
			Srb->DataTransferLength = 
				sizeof(SRB_IO_CONTROL) +
				sizeof(GETVERSIONINPARAMS);
		}
		break;
		//
		// Cluster Support
		//
	case IOCTL_SCSI_MINIPORT_NOT_QUORUM_CAPABLE:
	case IOCTL_SCSI_MINIPORT_NOT_CLUSTER_CAPABLE:
	default:
		Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
		Srb->DataTransferLength = 0;
		break;
	}

	return status;
}
예제 #28
0
//
// query scsiport PDO
//
ULONG
GetScsiAdapterPdoEnumInfo(
	IN PMINIPORT_DEVICE_EXTENSION	HwDeviceExtension,
	IN ULONG						SystemIoBusNumber,
	OUT PLONG						AddDevInfoLength,
	OUT PVOID						*AddDevInfo,
	OUT PULONG						AddDevInfoFlags
) {
	NTSTATUS						status;
	NDASBUS_QUERY_INFORMATION		BusQuery;
	PNDASBUS_INFORMATION			BusInfo;
	LONG							BufferNeeded;

	KDPrint(2,("SystemIoBusNumber:%d\n", SystemIoBusNumber));
	ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);

	BusQuery.Size = sizeof(NDASBUS_QUERY_INFORMATION);
	BusQuery.InfoClass = INFORMATION_PDOENUM;
	BusQuery.SlotNo = SystemIoBusNumber;

	//
	//	Get a buffer length needed.
	//
	status = IoctlToLanscsiBus(
						IOCTL_NDASBUS_QUERY_INFORMATION,
						&BusQuery,
						sizeof(NDASBUS_QUERY_INFORMATION),
						NULL,
						0,
						&BufferNeeded
					);
	if(status != STATUS_BUFFER_TOO_SMALL || BufferNeeded <= 0) {
		KDPrint(2,("IoctlToLanscsiBus() Failed.\n"));
		return SP_RETURN_NOT_FOUND;
	}

	//
	//
	//
	BusInfo= (PNDASBUS_INFORMATION)ExAllocatePoolWithTag(NonPagedPool, BufferNeeded, NDSC_PTAG_IOCTL);
	if(BusInfo == NULL)
		return SP_RETURN_ERROR;
	status = IoctlToLanscsiBus(
						IOCTL_NDASBUS_QUERY_INFORMATION,
						&BusQuery,
						sizeof(NDASBUS_QUERY_INFORMATION),
						BusInfo,
						BufferNeeded,
						&BufferNeeded
					);
	if(!NT_SUCCESS(status)) {
		ExFreePoolWithTag(BusInfo, NDSC_PTAG_IOCTL);
		return SP_RETURN_NOT_FOUND;
	}

	HwDeviceExtension->AdapterMaxDataTransferLength = BusInfo->PdoEnumInfo.MaxRequestLength;
	if(HwDeviceExtension->AdapterMaxDataTransferLength == 0) {
		HwDeviceExtension->AdapterMaxDataTransferLength = NDAS_MAX_TRANSFER_LENGTH;
	}

	HwDeviceExtension->EnumFlags			= BusInfo->PdoEnumInfo.Flags;
	*AddDevInfoFlags						= BusInfo->PdoEnumInfo.Flags;

	KDPrint(2,("MaxRequestLength:%d\n",
						BusInfo->PdoEnumInfo.MaxRequestLength));

	if(BusInfo->PdoEnumInfo.Flags & PDOENUM_FLAG_LURDESC) {
		ULONG				LurDescLen;
		PLURELATION_DESC	lurDesc;
		PLURELATION_DESC	lurDescOrig;

		lurDescOrig = (PLURELATION_DESC)BusInfo->PdoEnumInfo.AddDevInfo;
		LurDescLen = lurDescOrig->Length;
		//
		//	Verify sanity
		//
		if(lurDescOrig->Type != LUR_DESC_STRUCT_TYPE) {
			ExFreePoolWithTag(BusInfo,NDSC_PTAG_IOCTL);
			KDPrint(2,("LurDescOrig has invalid type: %04x\n", lurDescOrig->Type));
			return SP_RETURN_NOT_FOUND;
		}
		if(lurDescOrig->CntEcrKeyLength > NDAS_CONTENTENCRYPT_KEY_LENGTH) {
			ExFreePoolWithTag(BusInfo,NDSC_PTAG_IOCTL);
			KDPrint(2,("LurDescOrig has invalid key length: %d\n", lurDescOrig->CntEcrKeyLength));
			return SP_RETURN_NOT_FOUND;
		}

		//
		//	Allocate pool for the LUREALTION descriptor
		//	copy LUREALTION descriptor
		//
		lurDesc = (PLURELATION_DESC)ExAllocatePoolWithTag(NonPagedPool, LurDescLen, NDSC_PTAG_ENUMINFO);
		if(lurDesc == NULL) {
			ExFreePoolWithTag(BusInfo,NDSC_PTAG_IOCTL);
			return SP_RETURN_NOT_FOUND;
		}

		RtlCopyMemory(lurDesc, &BusInfo->PdoEnumInfo.AddDevInfo, LurDescLen);
		*AddDevInfo = lurDesc;
		*AddDevInfoLength = LurDescLen;
	}
	else {
		ASSERT(FALSE);
		return SP_RETURN_NOT_FOUND;
	}

	ExFreePoolWithTag(BusInfo,NDSC_PTAG_IOCTL);
	return SP_RETURN_FOUND;
}
예제 #29
0
NTSTATUS
NdasDluSrbControl(
	   IN PNDAS_LOGICALUNIT_EXTENSION	LogicalUnitExtension,
	   IN PSCSI_REQUEST_BLOCK			Srb
	)
{
    PSRB_IO_CONTROL	srbIoControl;
    PUCHAR			srbIoctlBuffer;
	LONG			srbIoctlBufferLength;
    ULONG			controlCode;
    NTSTATUS		status;
    UCHAR			srbStatus;
	PNDAS_DLU_EXTENSION			ndasDluExtension = NdasDluGetExtension(LogicalUnitExtension);

	//
    // Start off being paranoid.
    //
    if (Srb->DataBuffer == NULL) {
		KDPrint(1,("DataBuffer is NULL\n"));
		Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
        return STATUS_INVALID_PARAMETER;
    }
	status = STATUS_MORE_PROCESSING_REQUIRED;
	srbStatus = SRB_STATUS_SUCCESS;

	//
    // Extract the io_control
    //
    srbIoControl = (PSRB_IO_CONTROL)Srb->DataBuffer;

	//
	// Based on the signature, determine if this is Disk class ioctl or our own's those.
	//

	if (strncmp(srbIoControl->Signature, NDASSCSI_IOCTL_SIGNATURE, 8) == 0) {
		//
		// NDAS MINIPORT own's.
		// Continue to the parsing and execution in this function.
		//

	} else if(strncmp(srbIoControl->Signature, "SCSIDISK", 8) == 0) {
#if 1
		//
		// Disk class request
		// Complete the SRB in the disk class ioctl function.
		//

		return NdasDluDiskClassControl(LogicalUnitExtension, ndasDluExtension, Srb);
#else
		KDPrint(1,("Disk class control disabled.\n"));
		Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
		return STATUS_INVALID_PARAMETER;
#endif
	} else {

		KDPrint(1,("Signature mismatch %8s, %8s\n", srbIoControl->Signature, NDASSCSI_IOCTL_SIGNATURE));
		Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
        return STATUS_INVALID_PARAMETER;
    }

    //
    // Get the control code.
    // 
    controlCode = srbIoControl->ControlCode;

    //
    // Get the Ioctl buffer. If this is a send message request, it gets
    // fixed up to be an I2O message later.
    //
    srbIoctlBuffer = ((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL);
	srbIoctlBufferLength = srbIoControl->Length;

    //
    // Based on the control code, figure out what to do.
    //
    switch (controlCode) {
		case NDASSCSI_IOCTL_GET_DVD_STATUS:
			{
				srbStatus = NdasDluSrbIoctlGetDVDSTatus(
								LogicalUnitExtension,
								ndasDluExtension,
								srbIoctlBufferLength,
								srbIoctlBuffer,
								&srbIoControl->ReturnCode
								);
				if(srbStatus == SRB_STATUS_SUCCESS) {
					KDPrint(4,("NDASSCSI_IOCTL_QUERYINFO_EX: Successful.\n"));
					status = STATUS_SUCCESS;
				} else {
					status = STATUS_UNSUCCESSFUL;
				}								
			}
			break;
		case NDASSCSI_IOCTL_GET_SLOT_NO:
            KDPrint(2,("Get Slot No. Slot number is %d\n", ndasDluExtension->LogicalUnitAddress));

			if(srbIoctlBufferLength < sizeof(ULONG)) {
				srbIoControl->ReturnCode = SRB_STATUS_DATA_OVERRUN;
				srbStatus = SRB_STATUS_DATA_OVERRUN;
				status = STATUS_UNSUCCESSFUL;
				break;
			}

			*(PULONG)srbIoctlBuffer = ndasDluExtension->LogicalUnitAddress;
			srbIoControl->ReturnCode = SRB_STATUS_SUCCESS;

			srbStatus = SRB_STATUS_SUCCESS;
			status = STATUS_SUCCESS;
            break;

		case NDASSCSI_IOCTL_QUERYINFO_EX: {
			PNDASSCSI_QUERY_INFO_DATA	QueryInfo;
			PUCHAR tmpBuffer;
            KDPrint(5, ("Query information EX.\n"));

			QueryInfo = (PNDASSCSI_QUERY_INFO_DATA)srbIoctlBuffer;

			tmpBuffer = ExAllocatePoolWithTag(NonPagedPool, srbIoctlBufferLength, NDAS_DLU_PTAG_IOCTL);
			if(tmpBuffer == NULL) {
				ASSERT(FALSE);
	            KDPrint(1,("NDASSCSI_IOCTL_QUERYINFO_EX: SRB_STATUS_DATA_OVERRUN. BufferLength:%d\n", srbIoctlBufferLength));
				srbStatus = SRB_STATUS_DATA_OVERRUN;
				break;
			}

			status = NdasDluSrbIoctlQueryInfo(
							LogicalUnitExtension,
							ndasDluExtension,
							Srb,
							QueryInfo,
							srbIoctlBufferLength,
							tmpBuffer,
							&srbIoControl->ReturnCode,
							&srbStatus
						);

			//
			// tmpBuffer only lives up to the end of current scope.
			//
			// When NdasDluSrbIoctlQueryInfo returns STATUS_PENDING,
			// we cannot touch srbIoctlBuffer at all because srbIoctlBuffer
			// is being touch by the completion routine.
			//
			// Other cases, we have to copy from the temporarily output buffer 
			// (tmpBuffer) to the final output buffer (srbIoctlBuffer)
			//
			if (STATUS_PENDING != status)
			{
				RtlCopyMemory(srbIoctlBuffer, tmpBuffer, srbIoctlBufferLength);
			}

			ExFreePoolWithTag(tmpBuffer, NDAS_DLU_PTAG_IOCTL);

			break;
		}
		case NDASSCSI_IOCTL_UPGRADETOWRITE: {
			PLURN_UPDATE		LurnUpdate;
			PCCB				Ccb;

			//
			//	Set a CCB
			//
			status = LsCcbAllocate(&Ccb);
			if(!NT_SUCCESS(status)) {
				srbStatus = SRB_STATUS_INVALID_REQUEST;
				KDPrint(1,("NDASSCSI_IOCTL_UPGRADETOWRITE: LsCcbAllocate() failed.\n"));
				break;
			}
			LurnUpdate = (PLURN_UPDATE)ExAllocatePoolWithTag(NonPagedPool, sizeof(LURN_UPDATE), NDAS_DLU_PTAG_IOCTL);
			if(!LurnUpdate) {
				srbStatus = SRB_STATUS_INVALID_REQUEST;
				KDPrint(1,("NDASSCSI_IOCTL_UPGRADETOWRITE: ExAllocatePoolWithTag() failed.\n"));
				status = STATUS_INSUFFICIENT_RESOURCES;
				break;
			}

			LSCCB_INITIALIZE(Ccb);
			Ccb->OperationCode = CCB_OPCODE_UPDATE;
			Ccb->DataBuffer = LurnUpdate;
			Ccb->DataBufferLength = sizeof(LURN_UPDATE);
			LsCcbSetFlag(Ccb, CCB_FLAG_ALLOCATED|CCB_FLAG_DATABUF_ALLOCATED);

			//	Ioctl Srb will complete asynchronously.
			Ccb->Srb = Srb;
			InterlockedIncrement(&ndasDluExtension->RequestExecuting);
			LsuIncrementTdiClientInProgress();
			LsCcbSetCompletionRoutine(Ccb, NdasDluCcbCompletion, LogicalUnitExtension);

			LurnUpdate->UpdateClass = LURN_UPDATECLASS_WRITEACCESS_USERID;

			status = LurRequest(
								ndasDluExtension->LUR,
								Ccb
							);
			if(!NT_SUCCESS(status)) {
				KDPrint(1,("NDASSCSI_IOCTL_UPGRADETOWRITE:  LurnRequest() failed.\n"));

				NdasDluLogError(
						LogicalUnitExtension,
						Srb,
						Srb->PathId,
						Srb->TargetId,
						Srb->Lun,
						NDASSCSI_IO_UPGRADEIOCTL_FAIL,
						EVTLOG_UNIQUEID(EVTLOG_MODULE_IOCTL, EVTLOG_FAIL_UPGRADEIOCTL, 0)
					);
				LsuDecrementTdiClientInProgress();
				LsCcbFree(Ccb);
				ExFreePoolWithTag(LurnUpdate, NDSC_PTAG_IOCTL);
				status = STATUS_SUCCESS;
				srbStatus = SRB_STATUS_INVALID_REQUEST;
			} else {
				status = STATUS_PENDING;
			}
			break;
		}

		case NDASSCSI_IOCTL_NOOP: {
			PCCB	Ccb;

			//
			//	Query to the LUR
			//
			status = LsCcbAllocate(&Ccb);
			if(!NT_SUCCESS(status)) {
				srbStatus = SRB_STATUS_ERROR;
				status = STATUS_SUCCESS;
				KDPrint(1,("LsCcbAllocate() failed.\n"));
				break;
			}

			LSCCB_INITIALIZE(Ccb);
			Ccb->OperationCode = CCB_OPCODE_NOOP;
			LsCcbSetFlag(Ccb, CCB_FLAG_ALLOCATED);
			Ccb->Srb = Srb;
			LsCcbSetCompletionRoutine(Ccb, NdasDluCcbCompletion, LogicalUnitExtension);

			InterlockedIncrement(&ndasDluExtension->RequestExecuting);
			LsuIncrementTdiClientInProgress();
			status = LurRequest(
								ndasDluExtension->LUR,
								Ccb
							);
			if(!NT_SUCCESS(status)) {
				LsuDecrementTdiClientInProgress();
				LsCcbFree(Ccb);
				srbStatus = SRB_STATUS_ERROR;
				status = STATUS_SUCCESS;
				KDPrint(1,("LurRequest() failed.\n"));
				break;
			}

			srbStatus = SRB_STATUS_SUCCESS;
			status = STATUS_PENDING;
		break;
		}
		case NDASSCSI_IOCTL_ADD_USERBACL: {
			PNDAS_BLOCK_ACE	bace = (PNDAS_BLOCK_ACE)srbIoctlBuffer; // input
			PBLOCKACE_ID	blockAceId = (PBLOCKACE_ID)srbIoctlBuffer; // output
			UCHAR			lsuAccessMode;
			PLSU_BLOCK_ACE	lsuBace;

			UINT64	blockStartAddr;
			UINT64	blockEndAddr;

			if(srbIoctlBufferLength < sizeof(NDAS_BLOCK_ACE)) {
				srbStatus = SRB_STATUS_DATA_OVERRUN;
				status = STATUS_UNSUCCESSFUL;
				break;
			}

			if(ndasDluExtension->LUR == NULL) {
				srbStatus = SRB_STATUS_INVALID_REQUEST;
				status = STATUS_INVALID_PARAMETER;
				break;
			}

			lsuAccessMode = 0;
			if(bace->AccessMode & NBACE_ACCESS_READ) {
				lsuAccessMode |= LSUBACE_ACCESS_READ;
			}
			if(bace->AccessMode & NBACE_ACCESS_WRITE) {
				lsuAccessMode |= LSUBACE_ACCESS_WRITE;
			}

			if (bace->IsByteAddress) {

				blockStartAddr = bace->StartingOffset / ndasDluExtension->LUR->BlockBytes;
				blockEndAddr = (bace->StartingOffset + bace->Length) / ndasDluExtension->LUR->BlockBytes - 1;

			} else {

				blockStartAddr = bace->BlockStartAddr;
				blockEndAddr = bace->BlockEndAddr;
			}

			lsuBace = LsuCreateBlockAce( lsuAccessMode, blockStartAddr, blockEndAddr );

			if(lsuBace == NULL) {
				srbStatus = SRB_STATUS_DATA_OVERRUN;
				status = STATUS_UNSUCCESSFUL;
				break;
			}

			// Set returned BACE ID.
			*blockAceId = lsuBace->BlockAceId;

			LsuInsertAce(&ndasDluExtension->LUR->UserBacl, lsuBace);

			srbStatus = SRB_STATUS_SUCCESS;
			status = STATUS_SUCCESS;
			break;
		}
		case NDASSCSI_IOCTL_REMOVE_USERBACL: {
			PNDSCIOCTL_REMOVE_USERBACL ioctlRemoveUserAcl = (PNDSCIOCTL_REMOVE_USERBACL)srbIoctlBuffer;
			BLOCKACE_ID	blockAceId;
			PLSU_BLOCK_ACE	lsuBacl;

			if(srbIoctlBufferLength < sizeof(NDSCIOCTL_REMOVE_USERBACL)) {
				srbStatus = SRB_STATUS_DATA_OVERRUN;
				status = STATUS_UNSUCCESSFUL;
				break;
			}

			blockAceId = ioctlRemoveUserAcl->NdasBlockAceId; // input

			if(ndasDluExtension->LUR == NULL) {
				srbStatus = SRB_STATUS_INVALID_REQUEST;
				status = STATUS_INVALID_PARAMETER;
				break;
			}
			if(blockAceId == 0) {
				KDPrint(1,("REMOVE_USERBACL: Zero block ACE ID.\n"));
				srbStatus = SRB_STATUS_INVALID_REQUEST;
				status = STATUS_INVALID_PARAMETER;
				break;
			}

			lsuBacl = LsuRemoveAceById(&ndasDluExtension->LUR->UserBacl, blockAceId);
			if(lsuBacl == NULL) {
				KDPrint(1,("REMOVE_USERBACL: Invalid block ACE ID.\n"));
				srbStatus = SRB_STATUS_INVALID_REQUEST;
				status = STATUS_INVALID_PARAMETER;
				break;
			}

			LsuFreeBlockAce(lsuBacl);

			srbStatus = SRB_STATUS_SUCCESS;
			status = STATUS_SUCCESS;
			break;
		}
		case NDASSCSI_IOCTL_DEVICE_LOCK: {

			if(srbIoctlBufferLength < sizeof(NDSCIOCTL_DEVICELOCK)) {
				srbStatus = SRB_STATUS_DATA_OVERRUN;
				status = STATUS_UNSUCCESSFUL;
				break;
			}

			if(ndasDluExtension->LUR == NULL) {
				srbStatus = SRB_STATUS_INVALID_REQUEST;
				status = STATUS_INVALID_PARAMETER;
				break;
			}

			status = NdasDluIoctlDeviceLock(
										LogicalUnitExtension,
										ndasDluExtension,
										(PNDSCIOCTL_DEVICELOCK)srbIoctlBuffer,
										Srb);
			srbStatus = Srb->SrbStatus;
			break;
		}
        default:

            KDPrint(2,("Control Code (%x)\n", controlCode));
            srbStatus = SRB_STATUS_INVALID_REQUEST;
			status = STATUS_MORE_PROCESSING_REQUIRED;
    }

	Srb->SrbStatus = srbStatus;

    return status;
}
예제 #30
0
VOID
UpdatePdoInfoInLSBus(
		PMINIPORT_DEVICE_EXTENSION	HwDeviceExtension,
		UINT32						AdapterStatus
	) {
	PNDASBUS_SETPDOINFO		busSet;
	NDAS_FEATURES			supportedFeatures, enabledFeatures;

	ASSERT(HwDeviceExtension);

	//
	//	Query to the LUR
	//
	if(HwDeviceExtension->LURs[0]) {
		KDPrint(4,("going to default LuExtention 0.\n"));
		supportedFeatures = HwDeviceExtension->LURs[0]->SupportedNdasFeatures;
		enabledFeatures = HwDeviceExtension->LURs[0]->EnabledNdasFeatures;
	} else {
		KDPrint(2,("No LUR available..\n"));
		supportedFeatures = enabledFeatures = 0;
		return;
	}

	KDPrint(2,("Set AdapterStatus=%x Supp=%x Enab=%x\n",
					AdapterStatus,
					supportedFeatures,
					enabledFeatures));

	//
	//	Send to LSBus
	//
	busSet = (PNDASBUS_SETPDOINFO)ExAllocatePoolWithTag(NonPagedPool, sizeof(NDASBUS_SETPDOINFO), NDSC_PTAG_IOCTL);
	if(busSet == NULL) {
		return;
	}

	busSet->Size			= sizeof(NDASBUS_SETPDOINFO);
	busSet->SlotNo			= HwDeviceExtension->SlotNumber;
	busSet->AdapterStatus	= AdapterStatus;
	busSet->SupportedFeatures	= supportedFeatures;
	busSet->EnabledFeatures	= enabledFeatures;

	if(KeGetCurrentIrql() == PASSIVE_LEVEL) {
		IoctlToLanscsiBus(
						IOCTL_NDASBUS_SETPDOINFO,
						busSet,
						sizeof(NDASBUS_SETPDOINFO),
						NULL,
						0,
						NULL);
		ExFreePoolWithTag(busSet, NDSC_PTAG_IOCTL);

	} else {

		//
		//	IoctlToLanscsiBus_Worker() will free memory of BusSet.
		//
		IoctlToLanscsiBusByWorker(
						HwDeviceExtension->ScsiportFdoObject,
						IOCTL_NDASBUS_SETPDOINFO,
						busSet,
						sizeof(NDASBUS_SETPDOINFO)
					);
	}
}