Ejemplo n.º 1
0
void
CNdasEventMonitor::OnLogicalDeviceAlarmedByPnP(
	__in INdasLogicalUnit* pNdasLogicalUnit, 
	__in ULONG NewAdapterStatus)
{
	NDAS_LOCATION ndasLocation;
	COMVERIFY(pNdasLogicalUnit->get_Id(&ndasLocation));

	XTLTRACE2(NDASSVC_EVENTMON, TRACE_LEVEL_INFORMATION,
		"Alarm Event, ndasLocation=%08X, logicalUnit=%p\n", 
		ndasLocation, pNdasLogicalUnit);

	if (0 == ndasLocation) 
	{
		XTLTRACE2(NDASSVC_EVENTMON, TRACE_LEVEL_ERROR,
			"Invalid SCSI Location\n");
		XTLASSERT(FALSE);
		return;
	}

	XTLTRACE2(NDASSVC_EVENTMON, TRACE_LEVEL_INFORMATION,
		"Logical device alarmed by PnP, ndasLocation=%08X, adapterStatus=%08X.\n", 
		ndasLocation, NewAdapterStatus);

	// Determine whether an alarm will be issued.
	// Only viable alarm will be published
	ULONG currentAdapterStatus;
	COMVERIFY(pNdasLogicalUnit->get_AdapterStatus(&currentAdapterStatus));

	if (pIsViableAlarmStatus(currentAdapterStatus, NewAdapterStatus))
	{
		CNdasEventPublisher& epub = pGetNdasEventPublisher();

		if (ADAPTERINFO_ISSTATUS(NewAdapterStatus, NDASSCSI_ADAPTER_STATUS_STOPPED) &&
			ADAPTERINFO_ISSTATUSFLAG(NewAdapterStatus, NDAS_DEVICE_ALARM_STATUSFLAG_ABNORMAL_TERMINAT))
		{
			//
			// Notify abnormal removal of the LU device.
			//
			OnLogicalDeviceDisconnected(pNdasLogicalUnit);
		}
		else
		{
			NDAS_LOGICALDEVICE_ID logicalUnitId;
			COMVERIFY(pNdasLogicalUnit->get_Id(&logicalUnitId));
			(void) epub.LogicalDeviceAlarmed(
				logicalUnitId, 
				pGetSignificantAlarm(currentAdapterStatus, NewAdapterStatus));
		}
	}

	COMVERIFY(pNdasLogicalUnit->put_AdapterStatus(NewAdapterStatus));
}
Ejemplo n.º 2
0
BOOLEAN
LsBusCtlQueryAlarmStatus(
	ULONG SlotNo,
	PULONG AlarmStatus)
{
	BOOLEAN						BRet ;
	BUSENUM_QUERY_INFORMATION	Query;
	BUSENUM_INFORMATION	Information;

	//
	//	Query AccessRight to LanscsiBus
	//
	Query.InfoClass = INFORMATION_PDO;
	Query.Size		= sizeof(Query) ;
	Query.SlotNo	= SlotNo;

	BRet = LsBusCtlQueryInformation(
				&Query,
				sizeof(Query),
				&Information,
				sizeof(Information));
	if(BRet == FALSE) {
		return FALSE;
	}

//	if(Information.UnitDisk.StatusFlags & ADAPTERINFO_STATUS_RECONNECTFAILED) {
//		*AlarmStatus = ALARM_STATUS_FAIL_RECONNECT;
//	} else 
	if(ADAPTERINFO_ISSTATUSFLAG(Information.PdoInfo.AdapterStatus, ADAPTERINFO_STATUSFLAG_RECONNECTPENDING)) {
		*AlarmStatus = ALARM_STATUS_START_RECONNECT;
	} else {
		*AlarmStatus = ALARM_STATUS_NORMAL;
	}

	return BRet;
}
Ejemplo n.º 3
0
BOOL 
CNdasEventMonitor::OnLogicalDeviceAlarmed(DWORD nWaitIndex)
{
	ximeta::CAutoLock autolock(this);

	PCNdasLogicalDevice pLogDevice = NULL;

	if (nWaitIndex < m_vLogDevices.size()) {
		pLogDevice = m_vLogDevices[nWaitIndex];
	} else {
		_ASSERTE(FALSE);
		return FALSE;
	}

	if (NULL == pLogDevice) {
		_ASSERTE(FALSE);
		return FALSE;
	}

	CNdasScsiLocation ndasScsiLocation = pLogDevice->GetNdasScsiLocation();

	DPInfo(_FT("Alarm Event from %s: %s\n"),
		ndasScsiLocation.ToString(),
		pLogDevice->ToString());

	if (ndasScsiLocation.IsInvalid()) {
		DBGPRT_ERR(_FT("Invalid SCSI Location\n"));
		_ASSERTE(FALSE);
		return FALSE;
	}

	//
	// reset the event to prevent consecutive same event pulse
	//
	// should return TRUE
	BOOL fSuccess = ::ResetEvent(pLogDevice->GetAlarmEvent());
	_ASSERTE(fSuccess);

	ULONG ulAdapterStatus;

	fSuccess = ::LsBusCtlQueryStatus(
		ndasScsiLocation.SlotNo,
		&ulAdapterStatus);

	if (!fSuccess) {
		DPErrorEx(_FT("Unable to get alarm status, Ignored: "));
		return TRUE;
	}

	if(pLogDevice->GetAdapterStatus() != ulAdapterStatus)
	{
		pLogDevice->SetAdapterStatus(ulAdapterStatus);

		CNdasEventPublisher* pEventPublisher = pGetNdasEventPublisher();

		(VOID) pEventPublisher->LogicalDeviceAlarmed(pLogDevice->GetLogicalDeviceId(), ulAdapterStatus);
	}

	if(ADAPTERINFO_ISSTATUSFLAG(ulAdapterStatus, ADAPTERINFO_STATUSFLAG_MEMBER_FAULT))
		pLogDevice->SetAllUnitDevicesFault();

	return TRUE;
}
Ejemplo n.º 4
0
NTSTATUS
Bus_IoCtl (
    IN  PDEVICE_OBJECT  DeviceObject,
    IN  PIRP            Irp
    )
/*++
Routine Description:

    Handle user mode PlugIn, UnPlug and device Eject requests.

Arguments:

   DeviceObject - pointer to a device object.

   Irp - pointer to an I/O Request Packet.

Return Value:

   NT status code

--*/
{
    PIO_STACK_LOCATION      irpStack;
    NTSTATUS                status;
    ULONG                   inlen, outlen;
    PFDO_DEVICE_DATA        fdoData;
    PVOID                   buffer;

    PAGED_CODE ();

	//
	// It is not safe to call IOCTL in raised IRQL.
	//

	ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
    
    fdoData = (PFDO_DEVICE_DATA) DeviceObject->DeviceExtension;

    //
    // We only take Device Control requests for the FDO.
    // That is the bus itself.
    //

    if (!fdoData->IsFDO) {
    
        //
        // These commands are only allowed to go to the FDO.
        //   
        status = STATUS_INVALID_DEVICE_REQUEST;
        Irp->IoStatus.Status = status;
        IoCompleteRequest (Irp, IO_NO_INCREMENT);
        return status;

    }

    //
    // Check to see whether the bus is removed
    //
    
    if (fdoData->DevicePnPState == Deleted) {
        Irp->IoStatus.Status = status = STATUS_NO_SUCH_DEVICE;
        IoCompleteRequest (Irp, IO_NO_INCREMENT);
        return status;
    }

    Bus_IncIoCount (fdoData);
    
    irpStack = IoGetCurrentIrpStackLocation (Irp);

    buffer			= Irp->AssociatedIrp.SystemBuffer;  
    inlen			= irpStack->Parameters.DeviceIoControl.InputBufferLength;
    outlen			= irpStack->Parameters.DeviceIoControl.OutputBufferLength;

    status = STATUS_INVALID_PARAMETER;

	Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("%d called\n", irpStack->Parameters.DeviceIoControl.IoControlCode));
    switch (irpStack->Parameters.DeviceIoControl.IoControlCode) 
	{

	case IOCTL_NDASBUS_ADD_TARGET:
	{
		PPDO_DEVICE_DATA	pdoData;

		Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_NDASBUS_ADD_TARGET inlen %d, outlen %d, sizeof(NDASBUS_ADD_TARGET_DATA) %d\n", inlen, outlen, sizeof(NDASBUS_ADD_TARGET_DATA)));

		if ((inlen == outlen) &&
			(sizeof(NDASBUS_ADD_TARGET_DATA) <= inlen)) 
		{
			ULONG						ulSize;
			PNDASBUS_ADD_TARGET_DATA	addTargetData = buffer;
			BOOLEAN						accepted;
			
			Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_NDASBUS_ADD_TARGET called\n"));
			Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_NDASBUS_ADD_TARGET Target Type %d\n", addTargetData->ucTargetType));

			status = STATUS_SUCCESS;
			
			//
			// Check structure size
			//
			if(VerifySizeOfAddTargetData(addTargetData, &ulSize) == 0) {
				status = STATUS_INVALID_PARAMETER;
				break;
			}
			if(ulSize != inlen) 
			{
				Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("ADD_TARGET: Size mismatch. Req %d, in %d\n", ulSize, inlen));
				status = STATUS_UNSUCCESSFUL;
				break;
			}

			//
			//	Check to see if acceptable structure.
			//

			accepted = TRUE;
			switch(addTargetData->ucTargetType) 
			{
			case NDASSCSI_TYPE_DISK_NORMAL: 
			case NDASSCSI_TYPE_DVD: 
			case NDASSCSI_TYPE_VDVD: 
			case NDASSCSI_TYPE_MO:

				if(addTargetData->ulNumberOfUnitDiskList != 1)
					accepted = FALSE;
				break;

			case NDASSCSI_TYPE_DISK_MIRROR:

				if(2 != addTargetData->ulNumberOfUnitDiskList)
					accepted = FALSE;

				break;

			case NDASSCSI_TYPE_DISK_AGGREGATION:

				if (addTargetData->ulNumberOfUnitDiskList < 2 || 
					addTargetData->ulNumberOfUnitDiskList > MAX_NR_UNITDISK_FOR_AGGR)
					accepted = FALSE;
				break;

			case NDASSCSI_TYPE_DISK_RAID0:
				switch(addTargetData->ulNumberOfUnitDiskList)
				{
				case 2:
				case 4:
				case 8:
					break;
				default: // do not accept
					accepted = FALSE;
					break;
				}
				break;
			case NDASSCSI_TYPE_DISK_RAID1R3:
				{
					ULONG						ulDiskCount;
					ulDiskCount = addTargetData->ulNumberOfUnitDiskList - 
						addTargetData->RAID_Info.nSpareDisk;
					if (2 != ulDiskCount) 
						accepted = FALSE;
				}
				break;
			case NDASSCSI_TYPE_DISK_RAID4R3:
				{
					ULONG						ulDiskCount;
					ulDiskCount = addTargetData->ulNumberOfUnitDiskList - 
						addTargetData->RAID_Info.nSpareDisk;
					switch(ulDiskCount)
				{
				case 3: // 2 + 1
				case 5: // 4 + 1
				case 9: // 8 + 1
					break;
				default: // do not accept
					accepted = FALSE;
					break;
				}
				break;
				}				
			default:
				Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("ADD_TARGET: Bad Disk Type.\n"));
				accepted = FALSE;
				break;
			}
			if(accepted == FALSE) {
				Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("ADD_TARGET: Invaild type.\n"));
				status = STATUS_UNSUCCESSFUL;
				break;
			}
						
#if DBG
			NDBusIoctlLogError(	fdoData->Self,
				NDASBUS_IO_TRY_TO_ADDTARGET,
				IOCTL_NDASBUS_ADD_TARGET,
				addTargetData->ulSlotNo);
#endif
			// Find Pdo Data...
			pdoData = LookupPdoData(fdoData, addTargetData->ulSlotNo);
			if(pdoData == NULL) 
			{
				Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR,
					("no pdo\n"));
				status = STATUS_UNSUCCESSFUL;
				NDBusIoctlLogError(	fdoData->Self,
									NDASBUS_IO_PDO_NOT_FOUND,
									IOCTL_NDASBUS_ADD_TARGET,
									addTargetData->ulSlotNo);
				break;
			}

			//
			// Save the add target information to the PDO extension
			//

			pdoData->LanscsiAdapterPDO.AddDevInfo = ExAllocatePoolWithTag(NonPagedPool, inlen, BUSENUM_POOL_TAG);
			
			if(pdoData->LanscsiAdapterPDO.AddDevInfo == NULL) 
			{
				Irp->IoStatus.Information = 0;
				status = STATUS_INSUFFICIENT_RESOURCES;
				break;
			}
			else 
			{
				RtlCopyMemory(pdoData->LanscsiAdapterPDO.AddDevInfo, addTargetData, inlen);
				status = STATUS_SUCCESS;
			}

			pdoData->LanscsiAdapterPDO.AddDevInfoLength = inlen;

			//
			// Init PDO status
			//

			pdoData->LanscsiAdapterPDO.LastAdapterStatus = NDASSCSI_ADAPTERINFO_STATUS_INIT;
			pdoData->LanscsiAdapterPDO.DeviceMode = addTargetData->DeviceMode;

			//
			//	Notify to NDASSCSI
			//
			Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_NDASBUS_ADD_TARGET SetEvent AddTargetEvent!\n"));
			KeSetEvent(&pdoData->LanscsiAdapterPDO.AddTargetEvent, IO_NO_INCREMENT, FALSE);

			//
			//	Register Target
			//
			if(pdoData->Persistent) {
				status = LSBus_RegisterTarget(fdoData, addTargetData);
				if(!NT_SUCCESS(status)) {
					ExFreePoolWithTag(pdoData->LanscsiAdapterPDO.AddDevInfo, BUSENUM_POOL_TAG);
					pdoData->LanscsiAdapterPDO.AddDevInfo = NULL;
					Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("ADD_TARGET: LSBus_RegisterTarget() failed. STATUS=%08lx\n", status));
					status = STATUS_INTERNAL_DB_ERROR;
					NDBusIoctlLogError(	fdoData->Self,
										NDASBUS_IO_REGISTER_TARGET_FAIL,
										IOCTL_NDASBUS_ADD_TARGET,
										addTargetData->ulSlotNo);
				} else {
					Bus_KdPrint(fdoData, BUS_DBG_IOCTL_INFO, ("ADD_TARGET: Successfully registered.\n"));
				}
			}

			ObDereferenceObject(pdoData->Self);

			Irp->IoStatus.Information = outlen;
		}        
		else
		{
			Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR,
								("IOCTL_NDASBUS_ADD_TARGET length mismatch!!!"
								" inlen %d, outlen %d, sizeof(NDASBUS_ADD_TARGET_DATA) %d\n",
								inlen, outlen, sizeof(NDASBUS_ADD_TARGET_DATA)));
		}

	}
		break;

	case IOCTL_NDASBUS_REMOVE_TARGET:
	{
	    PPDO_DEVICE_DATA	pdoData;
		PNDASBUS_REMOVE_TARGET_DATA	removeTarget;

        Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_NDASBUS_REMOVE_TARGET called\n"));

        if (sizeof (NDASBUS_REMOVE_TARGET_DATA) != inlen)
			break;

		removeTarget = (PNDASBUS_REMOVE_TARGET_DATA)buffer;
		pdoData = LookupPdoData(fdoData, removeTarget->ulSlotNo);
		if(pdoData == NULL) {
			Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR,
						("no pdo\n"));
			status = STATUS_UNSUCCESSFUL;
			NDBusIoctlLogError(	fdoData->Self,
				NDASBUS_IO_PDO_NOT_FOUND,
				IOCTL_NDASBUS_REMOVE_TARGET,
				removeTarget->ulSlotNo);
			break;
		}

		//
		//	redirect to the NDAS SCSI Device
		//
		status = LSBus_IoctlToNdasScsiDevice(
				pdoData,
				NDASSCSI_IOCTL_REMOVE_TARGET,
				buffer,
				sizeof(NDASBUS_REMOVE_TARGET_DATA),
				NULL,
				0
			);

		if(NT_SUCCESS(status) && pdoData->Persistent) {

			status = LSBus_UnregisterTarget(fdoData, removeTarget->ulSlotNo, removeTarget->ulTargetId);
			if(!NT_SUCCESS(status)) {
				Bus_KdPrint(fdoData, BUS_DBG_IOCTL_INFO, (	"REMOVE_TARGET: Removed  Target instance,"
															" but LSBus_UnregisterTarget() failed.\n"));
				status = STATUS_INTERNAL_DB_ERROR;
				NDBusIoctlLogError(	fdoData->Self,
					NDASBUS_IO_UNREGISTER_TARGET_FAIL,
					IOCTL_NDASBUS_REMOVE_TARGET,
					removeTarget->ulSlotNo);
			}
#if DBG
			else {
				Bus_KdPrint(fdoData, BUS_DBG_IOCTL_INFO, ("REMOVE_TARGET: LSBus_UnregisterTarget() succeeded.\n"));
			}
#endif
		}

		ObDereferenceObject(pdoData->Self);

        Irp->IoStatus.Information = 0;
		break;
	}

	case IOCTL_NDASBUS_STARTSTOP_REGISTRARENUM:{
		PULONG	onOff = (PULONG)buffer;

		Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, (
			"STARTSTOP_REGISTRARENUM: inlen %d, outlen %d OnOff %u\n", inlen, outlen, *onOff));

		KeEnterCriticalRegion();
		ExAcquireFastMutexUnsafe(&fdoData->RegMutex);

		if(*onOff != 0) {

			//
			//	Save old state.
			//	Activate the registrar's enumeration
			//

			*onOff = fdoData->StartStopRegistrarEnum;
			fdoData->StartStopRegistrarEnum = TRUE;
		} else {

			//
			//	Save old state.
			//	Deactivate the registrar's enumeration
			//

			*onOff = fdoData->StartStopRegistrarEnum;
			fdoData->StartStopRegistrarEnum = FALSE;
		}

		//
		//	Clean up non-enumerated entries.
		//
		LSBus_CleanupNDASDeviceRegistryUnsafe(fdoData);

		ExReleaseFastMutexUnsafe(&fdoData->RegMutex);
		KeLeaveCriticalRegion();

		Irp->IoStatus.Information = sizeof(ULONG);
		status = STATUS_SUCCESS;

		break;
	}

	case IOCTL_NDASBUS_REGISTER_DEVICE:
	{

		Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, (
							"REGISTER_DEVICE: inlen %d, outlen %d,"
							" sizeof(NDASBUS_PLUGIN_HARDWARE_EX2) %d\n",
							inlen, outlen, sizeof(NDASBUS_PLUGIN_HARDWARE_EX2)));
		if ((inlen == outlen)) {

			PNDASBUS_PLUGIN_HARDWARE_EX2	PlugIn = buffer;

			Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("REGISTER_DEVICE: entered\n"));

			status = LSBus_RegisterDevice(fdoData, PlugIn);

			Irp->IoStatus.Information = 0;
		}
		else
			Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR,
									("REGISTER_DEVICE: length mismatch!!!"
									" inlen %d, outlen %d, sizeof(NDASBUS_PLUGIN_HARDWARE_EX2) %d\n",
									inlen, outlen, sizeof(NDASBUS_PLUGIN_HARDWARE_EX2)));

	}
		break;
	case IOCTL_NDASBUS_REGISTER_TARGET:
	{

		Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, (
									"REGISTER_TARGET: inlen %d, outlen %d,"
									" sizeof(NDASBUS_ADD_TARGET_DATA) %d\n",
									inlen, outlen, sizeof(NDASBUS_ADD_TARGET_DATA)));
		if ((inlen == outlen)) {

			PNDASBUS_ADD_TARGET_DATA	AddTargetData = buffer;

			Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("REGISTER_TARGET: entered\n"));

			status = LSBus_RegisterTarget(fdoData, AddTargetData);

			Irp->IoStatus.Information = 0;
		}
		else {
			Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, (
									"REGISTER_TARGET: length mismatch!!!"
									" inlen %d, outlen %d, sizeof(NDASBUS_ADD_TARGET_DATA) %d\n",
									inlen, outlen, sizeof(NDASBUS_ADD_TARGET_DATA)));
		}

	}
		break;
	case IOCTL_NDASBUS_UNREGISTER_DEVICE:
	{
		Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, (
									"UNREGISTER_DEVICE: inlen %d, outlen %d,"
									" sizeof(NDASBUS_UNREGISTER_NDASDEV) %d\n",
									inlen, outlen, sizeof(NDASBUS_UNREGISTER_NDASDEV)));
		if ((inlen == outlen)) {

			PNDASBUS_UNREGISTER_NDASDEV	UnregDev = buffer;

			Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("UNREGISTER_DEVICE: entered\n"));

			status = LSBus_UnregisterDevice(fdoData, UnregDev->SlotNo);

			Irp->IoStatus.Information = 0;
		}
		else {
			Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, (
									"UNREGISTER_DEVICE: length mismatch!!!"
									" inlen %d, outlen %d, sizeof(NDASBUS_ADD_TARGET_DATA) %d\n",
									inlen, outlen, sizeof(NDASBUS_UNREGISTER_NDASDEV)));
		}
	}
	break;
	case IOCTL_NDASBUS_UNREGISTER_TARGET:
	{
		Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, (
									"UNREGISTER_TARGET: inlen %d, outlen %d,"
									" sizeof(NDASBUS_UNREGISTER_TARGET) %d\n",
									inlen, outlen, sizeof(NDASBUS_UNREGISTER_TARGET)));
		if ((inlen == outlen)) {

			PNDASBUS_UNREGISTER_TARGET	UnregTarget = buffer;

			Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("UNREGISTER_TARGET: entered\n"));

			status = LSBus_UnregisterTarget(fdoData, UnregTarget->SlotNo, UnregTarget->TargetId);

			Irp->IoStatus.Information = 0;
		}
		else {
			Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, (
									"UNREGISTER_TARGET: length mismatch!!!"
									" inlen %d, outlen %d, sizeof(NDASBUS_UNREGISTER_TARGET) %d\n",
									inlen, outlen, sizeof(NDASBUS_UNREGISTER_TARGET)));
		}
	}
	break;
	case IOCTL_NDASBUS_SETPDOINFO:
		{
	    PPDO_DEVICE_DATA	pdoData;
		PNDASBUS_SETPDOINFO	SetPdoInfo;
		KIRQL				oldIrql;
		PVOID				sectionHandle;
		BOOLEAN				acceptStatus;

        Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_NDASBUS_SETPDOINFO called\n"));

        if (sizeof (NDASBUS_SETPDOINFO) != inlen)
			break;

		acceptStatus = TRUE;
		SetPdoInfo = (PNDASBUS_SETPDOINFO)buffer;
		pdoData = LookupPdoData(fdoData, SetPdoInfo->SlotNo);
		if(pdoData == NULL) {
			Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR,
						("no pdo\n"));
			status = STATUS_UNSUCCESSFUL;
			NDBusIoctlLogError(	fdoData->Self,
				NDASBUS_IO_PDO_NOT_FOUND,
				IOCTL_NDASBUS_SETPDOINFO,
				SetPdoInfo->SlotNo);
			break;
		}

		//
		//	lock the code section of this function to acquire spinlock in raised IRQL.
		//
	    sectionHandle = MmLockPagableCodeSection(Bus_IoCtl);

		KeAcquireSpinLock(&pdoData->LanscsiAdapterPDO.LSDevDataSpinLock, &oldIrql);

		Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("!!!!!!!!!!!!!!!!!!  SETPDOINFO: PDO %p: %08lx %08lx %08lx\n",
										pdoData->Self, SetPdoInfo->AdapterStatus,
										SetPdoInfo->SupportedFeatures,
										SetPdoInfo->EnabledFeatures));


		//
		// Deny the status change if the current status is STATUS_STOPPED except for RESETSTATUS flag.
		//

		if(ADAPTERINFO_ISSTATUS(pdoData->LanscsiAdapterPDO.LastAdapterStatus, NDASSCSI_ADAPTERINFO_STATUS_STOPPED)) {

				Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("SETPDOINFO: 'An event occured after 'Stopped' event\n"));

				if(ADAPTERINFO_ISSTATUSFLAG(SetPdoInfo->AdapterStatus, NDASSCSI_ADAPTERINFO_STATUSFLAG_RESETSTATUS)) {
					Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("SETPDOINFO: Reset-status event accepted.\n"));
				} else {
					acceptStatus = FALSE;
				}
		} else {
			if(pdoData->LanscsiAdapterPDO.AddDevInfo == NULL) {
				acceptStatus = FALSE;
				Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("!!!!!!!!!!!!!!!!!! SETPDOINFO: AddTarget is not occured. Too early to set status.\n"));
			}
		}

		//
		// Mask off RESETSTATUS.
		// NDAS service does not need to know it.
		//

		SetPdoInfo->AdapterStatus &= ~NDASSCSI_ADAPTERINFO_STATUSFLAG_RESETSTATUS;

		//
		// Set status values to the corresponding physical device object.
		// Save to the extension
		//

		if(acceptStatus) {
			PNDASBUS_PDOEVENT_ENTRY	pdoEventEntry;

			pdoEventEntry = NdasBusCreatePdoStatusItem(SetPdoInfo->AdapterStatus);
			if(pdoEventEntry) {
				NdasBusQueuePdoStatusItem(&pdoData->LanscsiAdapterPDO, pdoEventEntry);
			}
#if DBG
			else {
				Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("SETPDOINFO: Could not allocate PDO status entry.\n"));
			}
#endif

			pdoData->LanscsiAdapterPDO.LastAdapterStatus = SetPdoInfo->AdapterStatus;
			pdoData->LanscsiAdapterPDO.SupportedFeatures = SetPdoInfo->SupportedFeatures;
			pdoData->LanscsiAdapterPDO.EnabledFeatures = SetPdoInfo->EnabledFeatures;

			//
			//	Queue plugout worker if the NDAS SCSI stop abnormally.
			// Notify the NDAS service of abnormal termination
			//
			if(ADAPTERINFO_ISSTATUS(SetPdoInfo->AdapterStatus, NDASSCSI_ADAPTERINFO_STATUS_STOPPED) &&
				ADAPTERINFO_ISSTATUSFLAG(SetPdoInfo->AdapterStatus, NDASSCSI_ADAPTERINFO_STATUSFLAG_ABNORMAL_TERMINAT)) {

				Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("SETPDOINFO: Queueing Unplug worker!!!!!!!!\n"));

				status = QueueUnplugWorker(fdoData, SetPdoInfo->SlotNo);

				//
				// Set disconnection event
				//

				KeSetEvent(pdoData->LanscsiAdapterPDO.DisconEventToService, IO_DISK_INCREMENT, FALSE);
			} else {
				//
				// Notify the adapter status change
				//
				KeSetEvent(pdoData->LanscsiAdapterPDO.AlarmEventToService, IO_DISK_INCREMENT, FALSE);
			}
		}

		KeReleaseSpinLock(&pdoData->LanscsiAdapterPDO.LSDevDataSpinLock, oldIrql);


		//
		//	Release the code section.
		//

	    MmUnlockPagableImageSection(sectionHandle);

		status = STATUS_SUCCESS;
		ObDereferenceObject(pdoData->Self);

        Irp->IoStatus.Information = outlen;
	}
		break;

	case IOCTL_NDASBUS_QUERY_NODE_ALIVE: 
		{

		PPDO_DEVICE_DATA		pdoData;
		BOOLEAN					bAlive;
		PNDASBUS_NODE_ALIVE_IN	pNodeAliveIn;
		NDASBUS_NODE_ALIVE_OUT	nodeAliveOut;

		// Check Parameter.
		if(inlen != sizeof(NDASBUS_NODE_ALIVE_IN) || 
			outlen != sizeof(NDASBUS_NODE_ALIVE_OUT)) {
			status = STATUS_UNKNOWN_REVISION;
			break;
		}
		
		pNodeAliveIn = (PNDASBUS_NODE_ALIVE_IN)Irp->AssociatedIrp.SystemBuffer;  
		
		Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_NOISE,
			("FDO: IOCTL_NDASBUS_QUERY_NODE_ALIVE SlotNumber = %d\n",
			pNodeAliveIn->SlotNo));
		
		pdoData = LookupPdoData(fdoData, pNodeAliveIn->SlotNo);

		if(pdoData == NULL) {
//			Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_TRACE,
//				("[LanScsiBus]Bus_IoCtl: IOCTL_NDASBUS_QUERY_NODE_ALIVE No pdo\n"));

			bAlive = FALSE;
		} else {
			bAlive = TRUE;
		}

		// For Result...
		nodeAliveOut.SlotNo = pNodeAliveIn->SlotNo;
		nodeAliveOut.bAlive = bAlive;
		// Get Adapter Status.
		if(bAlive == TRUE)
		{
			if(	ADAPTERINFO_ISSTATUS(pdoData->LanscsiAdapterPDO.LastAdapterStatus, NDASSCSI_ADAPTERINFO_STATUS_STOPPING)) {

				nodeAliveOut.bHasError = TRUE;
				Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR,
					("IOCTL_NDASBUS_QUERY_NODE_ALIVE Adapter has Error 0x%x\n", nodeAliveOut.bHasError));
			} else {
				nodeAliveOut.bHasError = FALSE;
			}

		}

		if(pdoData)
			ObDereferenceObject(pdoData->Self);

		RtlCopyMemory(
			Irp->AssociatedIrp.SystemBuffer,
			&nodeAliveOut,
			sizeof(NDASBUS_NODE_ALIVE_OUT)
			);
		
		Irp->IoStatus.Information = sizeof(NDASBUS_NODE_ALIVE_OUT);
		status = STATUS_SUCCESS;
		}
		break;

	//
	//	added by hootch 01172004
	//
	case IOCTL_NDASBUS_UPGRADETOWRITE:
		{
		PPDO_DEVICE_DATA				pdoData;

		Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_NDASBUS_UPGRADETOWRITE called\n"));
		// Check Parameter.
		if(inlen != sizeof(NDASBUS_UPGRADE_TO_WRITE)) {
			Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR,
				("IOCTL_NDASBUS_UPGRADETOWRITE: Invalid input buffer length\n"));
			status = STATUS_UNKNOWN_REVISION;
			break;
		}

		pdoData = LookupPdoData(fdoData, ((PNDASBUS_UPGRADE_TO_WRITE)buffer)->SlotNo);
		if(pdoData == NULL) {
			Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR,
				("IOCTL_NDASBUS_UPGRADETOWRITE: No pdo for Slotno:%d\n", ((PNDASBUS_UPGRADE_TO_WRITE)buffer)->SlotNo));
			status = STATUS_NO_SUCH_DEVICE;
			NDBusIoctlLogError(	fdoData->Self,
				NDASBUS_IO_PDO_NOT_FOUND,
				IOCTL_NDASBUS_UPGRADETOWRITE,
				((PNDASBUS_UPGRADE_TO_WRITE)buffer)->SlotNo);
		} else {
			//
			//	redirect to the NDASSCSI Device
			//
			status = LSBus_IoctlToNdasScsiDevice(
					pdoData,
					NDASSCSI_IOCTL_UPGRADETOWRITE,
					buffer,
					inlen,
					buffer,
					outlen
				);

			ObDereferenceObject(pdoData->Self);
		}
		Irp->IoStatus.Information = 0;
	}
		break;

	case IOCTL_NDASBUS_REDIRECT_NDASSCSI:
		{
		PPDO_DEVICE_DATA				pdoData;
		PNDASBUS_REDIRECT_NDASSCSI		redirectIoctl;

		Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_NDASBUS_REDIRECT_NDASSCSI called\n"));
		// Check Parameter.
		if(inlen < sizeof(NDASBUS_REDIRECT_NDASSCSI)) {
			Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR,
				("IOCTL_NDASBUS_REDIRECT_NDASSCSI: Invalid input buffer length\n"));
			status = STATUS_UNKNOWN_REVISION;
			break;
		}

		redirectIoctl = (PNDASBUS_REDIRECT_NDASSCSI)buffer;

		pdoData = LookupPdoData(fdoData, redirectIoctl->SlotNo);
		if(pdoData == NULL) {
			Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR,
				("IOCTL_NDASBUS_REDIRECT_NDASSCSI: No pdo for Slotno:%d\n", redirectIoctl->SlotNo));
			status = STATUS_NO_SUCH_DEVICE;
		} else {
			//
			//	redirect to the NDASSCSI Device
			//
			status = LSBus_IoctlToNdasScsiDevice(
					pdoData,
					redirectIoctl->IoctlCode,
					redirectIoctl->IoctlData,
					redirectIoctl->IoctlDataSize,
					redirectIoctl->IoctlData,
					redirectIoctl->IoctlDataSize
				);

			ObDereferenceObject(pdoData->Self);
		}
		Irp->IoStatus.Information = 0;
	}
		break;

	case IOCTL_NDASBUS_QUERY_NDASSCSIINFO:
		{
		PPDO_DEVICE_DATA				pdoData;

		Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_NDASBUS_QUERY_NDASSCSIINFO called\n"));
		// Check Parameter.
		if(inlen < FIELD_OFFSET(NDASSCSI_QUERY_INFO_DATA, QueryData) ) {
			Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR,
				("IOCTL_NDASBUS_QUERY_NDASSCSIINFO: Invalid input buffer length too small.\n"));
			status = STATUS_UNKNOWN_REVISION;
			break;
		}
		pdoData = LookupPdoData(fdoData, ((PNDASSCSI_QUERY_INFO_DATA)buffer)->NdasScsiAddress.SlotNo);

		if(pdoData == NULL) {
			Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR,
				("IOCTL_NDASBUS_QUERY_NDASSCSIINFO No pdo\n"));
			status = STATUS_NO_SUCH_DEVICE;
			NDBusIoctlLogError(	fdoData->Self,
				NDASBUS_IO_PDO_NOT_FOUND,
				IOCTL_NDASBUS_QUERY_NDASSCSIINFO,
				((PNDASSCSI_QUERY_INFO_DATA)buffer)->NdasScsiAddress.SlotNo);
		} else {
			//
			//	redirect to the NDASSCSI Device
			//
			status = LSBus_IoctlToNdasScsiDevice(
					pdoData,
					NDASSCSI_IOCTL_QUERYINFO_EX,
					buffer,
					inlen,
					buffer,
					outlen
				);

			ObDereferenceObject(pdoData->Self);
		}
        Irp->IoStatus.Information = outlen;
		}
		break;

	case IOCTL_NDASBUS_QUERY_INFORMATION:
		{

//		PPDO_DEVICE_DATA				pdoData;
		NDASBUS_QUERY_INFORMATION		Query;
		PNDASBUS_INFORMATION			Information;
		LONG							BufferLenNeeded;

		// Check Parameter.
		if(	inlen < sizeof(NDASBUS_QUERY_INFORMATION) /*|| 
			outlen < sizeof(NDASBUS_INFORMATION) */) {
			status = STATUS_UNKNOWN_REVISION;
			break;
		}

		RtlCopyMemory(&Query, buffer, sizeof(NDASBUS_QUERY_INFORMATION));
		Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_TRACE,
			("FDO: IOCTL_NDASBUS_QUERY_INFORMATION QueryType : %d  SlotNumber = %d\n",
			Query.InfoClass, Query.SlotNo));

		Information = (PNDASBUS_INFORMATION)buffer;
		ASSERT(Information);
		Information->InfoClass = Query.InfoClass;
		status = LSBus_QueryInformation(fdoData, IoIs32bitProcess(Irp), &Query, Information, outlen, &BufferLenNeeded);
		if(NT_SUCCESS(status)) {
			Information->Size = BufferLenNeeded;
			Irp->IoStatus.Information = BufferLenNeeded;
		} else {
			Irp->IoStatus.Information = BufferLenNeeded;
		}
		}
		break;

	case IOCTL_NDASBUS_PLUGIN_HARDWARE_EX2:
		{
			ULONG	structLen;		// Without variable length field
			ULONG	wholeStructLen; // With variable length field
			ULONG	inputWholeStructLen;

			//
			// Check 32 bit thunking request
            //
			if(IoIs32bitProcess(Irp)) {
				structLen = FIELD_OFFSET(NDASBUS_PLUGIN_HARDWARE_EX2_32, HardwareIDs);
				wholeStructLen = sizeof(NDASBUS_PLUGIN_HARDWARE_EX2_32);
				inputWholeStructLen = ((PNDASBUS_PLUGIN_HARDWARE_EX2_32) buffer)->Size;
			} else {
				structLen = FIELD_OFFSET(NDASBUS_PLUGIN_HARDWARE_EX2, HardwareIDs);
				wholeStructLen = sizeof(NDASBUS_PLUGIN_HARDWARE_EX2);
				inputWholeStructLen = ((PNDASBUS_PLUGIN_HARDWARE_EX2) buffer)->Size;
			}

			if ((inlen == outlen) &&
				//
				// Make sure it has at least two nulls and the size 
				// field is set to the declared size of the struct
				//
				((structLen + sizeof(UNICODE_NULL) * 2) <=
				inlen) &&

				//
				// The size field should be set to the sizeof the struct as declared
				// and *not* the size of the struct plus the multi_sz
				//
				(wholeStructLen == inputWholeStructLen)) {

				Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("PlugIn called\n"));

				status= Bus_PlugInDeviceEx2((PNDASBUS_PLUGIN_HARDWARE_EX2)buffer,
											inlen,
											fdoData,
											IoIs32bitProcess(Irp),
											Irp->RequestorMode, FALSE);

				Irp->IoStatus.Information = outlen;

			}
		}
        break;

	case IOCTL_NDASBUS_GETVERSION:
		{
			if (outlen >= sizeof(NDASBUS_GET_VERSION)) {
				PNDASBUS_GET_VERSION version = (PNDASBUS_GET_VERSION)buffer;

				Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_NDASBUS_GETVERSION: called\n"));

			try {
				version->VersionMajor = VER_FILEMAJORVERSION;
				version->VersionMinor = VER_FILEMINORVERSION;
				version->VersionBuild = VER_FILEBUILD;
				version->VersionPrivate = VER_FILEBUILD_QFE;

					Irp->IoStatus.Information = sizeof(NDASBUS_GET_VERSION);
					status = STATUS_SUCCESS;

				} except (EXCEPTION_EXECUTE_HANDLER) {

					status = GetExceptionCode();
					Irp->IoStatus.Information = 0;
				}

			}
		}			
		break;

    case IOCTL_NDASBUS_UNPLUG_HARDWARE:
		{
			if ((sizeof (NDASBUS_UNPLUG_HARDWARE) == inlen) &&
				(inlen == outlen) &&
				(((PNDASBUS_UNPLUG_HARDWARE)buffer)->Size == inlen)) {

				Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("UnPlug called\n"));

				status= Bus_UnPlugDevice(
						(PNDASBUS_UNPLUG_HARDWARE)buffer, fdoData);
				Irp->IoStatus.Information = outlen;

			}
		}
        break;

    case IOCTL_NDASBUS_EJECT_HARDWARE:
		{
			if ((sizeof (NDASBUS_EJECT_HARDWARE) == inlen) &&
				(inlen == outlen) &&
				(((PNDASBUS_EJECT_HARDWARE)buffer)->Size == inlen)) {

				Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("Eject called\n"));

				status= Bus_EjectDevice((PNDASBUS_EJECT_HARDWARE)buffer, fdoData);

				Irp->IoStatus.Information = outlen;
			}
		}
		break;

	case IOCTL_NDASBUS_DVD_GET_STATUS:
		{
			PPDO_DEVICE_DATA		pdoData;
			PNDASBUS_DVD_STATUS		pDvdStatusData;


			// Check Parameter.
			if((inlen != outlen)
				|| (sizeof(NDASBUS_DVD_STATUS) >  inlen))
			{
				status = STATUS_UNSUCCESSFUL ;
				break;
			}
			
			pDvdStatusData = (PNDASBUS_DVD_STATUS)Irp->AssociatedIrp.SystemBuffer;  
			
			Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR,
				("FDO: IOCTL_NDASBUS_DVD_GET_STATUS SlotNumber = %d\n",
				pDvdStatusData->SlotNo));	

			pdoData = LookupPdoData(fdoData, pDvdStatusData->SlotNo);
			
			if(pdoData == NULL) {
				Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR,
					("IOCTL_NDASBUS_DVD_GET_STATUS No pdo\n"));
				status = STATUS_UNSUCCESSFUL;
				NDBusIoctlLogError(	fdoData->Self,
					NDASBUS_IO_PDO_NOT_FOUND,
					IOCTL_NDASBUS_DVD_GET_STATUS,
					pDvdStatusData->SlotNo);
				break;	
			} else {

				if(pdoData->LanscsiAdapterPDO.Flags & LSDEVDATA_FLAG_LURDESC) {
					//
					//	A LUR descriptor is set.
					//
					if(((PLURELATION_DESC)pdoData->LanscsiAdapterPDO.AddDevInfo)->DevType != NDASSCSI_TYPE_DVD)
				{
					Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR,
						("IOCTL_NDASBUS_DVD_GET_STATUS  No DVD Device\n"));
					status = STATUS_UNSUCCESSFUL;
					break;
				}
				} else {
					//
					//	ADD_TARGET_DATA is set.
					//
					if(((PNDASBUS_ADD_TARGET_DATA)pdoData->LanscsiAdapterPDO.AddDevInfo)->ucTargetType != NDASSCSI_TYPE_DVD)
					{
						Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR,
							("IOCTL_NDASBUS_DVD_GET_STATUS  No DVD Device\n"));
						status = STATUS_UNSUCCESSFUL;
						break;
					}
				}
				//
				//	redirect to the NDASSCSI Device
				//
				status = LSBus_IoctlToNdasScsiDevice(
						pdoData,
						NDASSCSI_IOCTL_GET_DVD_STATUS,
						buffer,
						inlen,
						buffer,
						outlen
					);

				ObDereferenceObject(pdoData->Self);
				status = STATUS_SUCCESS;
				Irp->IoStatus.Information = outlen;
			}					
		}
		break;
    default:
        break; // default status is STATUS_INVALID_PARAMETER
    }
Ejemplo n.º 5
0
void
CNdasEventMonitor::OnLogicalDeviceAlarmed(INdasLogicalUnit* pNdasLogicalUnit)
{
	NDAS_LOCATION ndasLocation;
	COMVERIFY(pNdasLogicalUnit->get_Id(&ndasLocation));

	NDAS_LOGICALUNIT_ADDRESS ndasLogicalUnitAddress;
	COMVERIFY(pNdasLogicalUnit->get_LogicalUnitAddress(&ndasLogicalUnitAddress));

	XTLTRACE2(NDASSVC_EVENTMON, TRACE_LEVEL_INFORMATION,
		"Alarm Event, ndasLocation=%d, logicalUnit=%p\n", 
		ndasLocation, pNdasLogicalUnit);

	if (0 == ndasLocation) 
	{
		XTLTRACE2(NDASSVC_EVENTMON, TRACE_LEVEL_ERROR,
			"Invalid SCSI Location\n");
		XTLASSERT(FALSE);
		return;
	}

	ULONG newAdapterStatus;

	while(TRUE)
	{
		BOOL success = ::NdasBusCtlQueryEvent(
			ndasLocation,
			&newAdapterStatus);

		if (!success) 
		{
			if (::GetLastError() == ERROR_NO_MORE_ITEMS) 
			{
				XTLTRACE2(NDASSVC_EVENTMON, TRACE_LEVEL_INFORMATION,
					"No more events, ignored, ndasLocation=%d\n", 
					ndasLocation);
			} 
			else 
			{
				XTLTRACE2(NDASSVC_EVENTMON, TRACE_LEVEL_ERROR,
					"Query status failed on alarm, ignored, ndasLocation=%d\n", 
					ndasLocation);
			}
			return;
		}

		XTLTRACE2(NDASSVC_EVENTMON, TRACE_LEVEL_INFORMATION,
			"Logical device alarmed, ndasLocation=%d, adapterStatus=%08X.\n", 
			ndasLocation, newAdapterStatus);

		// Determine whether an alarm will be issued.
		// Only viable alarm will be published
		ULONG currentAdapterStatus;
		COMVERIFY(pNdasLogicalUnit->get_AdapterStatus(&currentAdapterStatus));

		if (pIsViableAlarmStatus(currentAdapterStatus, newAdapterStatus))
		{
			CNdasEventPublisher& epub = pGetNdasEventPublisher();
			NDAS_LOGICALDEVICE_ID logicalUnitId;
			COMVERIFY(pNdasLogicalUnit->get_Id(&logicalUnitId));
			(void) epub.LogicalDeviceAlarmed(
				logicalUnitId, 
				pGetSignificantAlarm(currentAdapterStatus, newAdapterStatus));
		}

		COMVERIFY(pNdasLogicalUnit->put_AdapterStatus(newAdapterStatus));

		if (!ADAPTERINFO_ISSTATUSFLAG(
			newAdapterStatus, 
			NDASSCSI_ADAPTER_STATUSFLAG_NEXT_EVENT_EXIST)) 
		{
			break;
		}
	}
}
Ejemplo n.º 6
0
	NTSTATUS
Bus_IoCtl (
    IN  PDEVICE_OBJECT  DeviceObject,
    IN  PIRP            Irp
    )
/*++
Routine Description:

    Handle user mode PlugIn, UnPlug and device Eject requests.

Arguments:

   DeviceObject - pointer to a device object.

   Irp - pointer to an I/O Request Packet.

Return Value:

   NT status code

--*/
{
    PIO_STACK_LOCATION      irpStack;
    NTSTATUS                status;
    ULONG                   inlen, outlen;
    PFDO_DEVICE_DATA        fdoData;
    PVOID                   buffer;

    PAGED_CODE ();
    
    fdoData = (PFDO_DEVICE_DATA) DeviceObject->DeviceExtension;

    //
    // We only take Device Control requests for the FDO.
    // That is the bus itself.
    //

    if (!fdoData->IsFDO) {
    
        //
        // These commands are only allowed to go to the FDO.
        //   
        status = STATUS_INVALID_DEVICE_REQUEST;
        Irp->IoStatus.Status = status;
        IoCompleteRequest (Irp, IO_NO_INCREMENT);
        return status;

    }

    //
    // Check to see whether the bus is removed
    //
    
    if (fdoData->DevicePnPState == Deleted) {
        Irp->IoStatus.Status = status = STATUS_NO_SUCH_DEVICE;
        IoCompleteRequest (Irp, IO_NO_INCREMENT);
        return status;
    }
    
    Bus_IncIoCount (fdoData);
    
    irpStack = IoGetCurrentIrpStackLocation (Irp);

    buffer			= Irp->AssociatedIrp.SystemBuffer;  
    inlen			= irpStack->Parameters.DeviceIoControl.InputBufferLength;
    outlen			= irpStack->Parameters.DeviceIoControl.OutputBufferLength;

    status = STATUS_INVALID_PARAMETER;

	Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("%d called\n", irpStack->Parameters.DeviceIoControl.IoControlCode));
    switch (irpStack->Parameters.DeviceIoControl.IoControlCode) 
	{

	case IOCTL_LANSCSI_ADD_TARGET:
	{
		PPDO_DEVICE_DATA	pdoData;

		Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_LANSCSI_ADD_TARGET inlen %d, outlen %d, sizeof(LANSCSI_ADD_TARGET_DATA) %d\n", inlen, outlen, sizeof(LANSCSI_ADD_TARGET_DATA)));

		if ((inlen == outlen) &&
			(sizeof(LANSCSI_ADD_TARGET_DATA) <= inlen)) 
		{
			ULONG						ulSize;
			PLANSCSI_ADD_TARGET_DATA	addTargetData = buffer;
			
			Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_LANSCSI_ADD_TARGET called\n"));
			Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_LANSCSI_ADD_TARGET Target Type %d\n", addTargetData->ucTargetType));

			// Check Parameter.
			status = STATUS_SUCCESS;
			switch(addTargetData->ucTargetType) 
			{
			case DISK_TYPE_NORMAL: 
			case DISK_TYPE_DVD: 
			case DISK_TYPE_VDVD: 
			case DISK_TYPE_MO:

				ulSize = sizeof(LANSCSI_ADD_TARGET_DATA);
				if(addTargetData->ulNumberOfUnitDiskList != 1)
				{
					ulSize = 0;	// Exit when Check if(ulSize != inlen)...
				}

				break;

			case DISK_TYPE_MIRROR:

				ulSize = sizeof(LANSCSI_ADD_TARGET_DATA) + sizeof(LSBUS_UNITDISK);
					
				if(2 != addTargetData->ulNumberOfUnitDiskList)
				{
					ulSize = 0;	// Exit when Check if(ulSize != inlen)...
				}

				break;

			case DISK_TYPE_AGGREGATION:

				ulSize = sizeof(LANSCSI_ADD_TARGET_DATA) + 
					sizeof(LSBUS_UNITDISK) * (addTargetData->ulNumberOfUnitDiskList - 1);

				if (addTargetData->ulNumberOfUnitDiskList < 2 || 
					addTargetData->ulNumberOfUnitDiskList > MAX_NR_TC_PER_TARGET) 
				{
					ulSize = 0;	// Exit when Check if(ulSize != inlen)...
				}
				
				break;

			case DISK_TYPE_BIND_RAID0:
				ulSize = sizeof(LANSCSI_ADD_TARGET_DATA) + 
					sizeof(LSBUS_UNITDISK) * (addTargetData->ulNumberOfUnitDiskList - 1);
				switch(addTargetData->ulNumberOfUnitDiskList)
				{
				case 2:
				case 4:
				case 8:
					break;
				default: // do not accept
					ulSize = 0;
					break;
				}
				break;
			case DISK_TYPE_BIND_RAID1:
				{
					ULONG						ulDiskCount;
					ulDiskCount = addTargetData->ulNumberOfUnitDiskList - 
						addTargetData->RAID_Info.nSpareDisk;
					ulSize = sizeof(LANSCSI_ADD_TARGET_DATA) + 
						sizeof(LSBUS_UNITDISK) * (addTargetData->ulNumberOfUnitDiskList - 1);
					if (2 != ulDiskCount) 
					{
						ulSize = 0;	// Exit when Check if(ulSize != inlen)...
					}
				}
				break;
			case DISK_TYPE_BIND_RAID4:
				{
					ULONG						ulDiskCount;
					ulDiskCount = addTargetData->ulNumberOfUnitDiskList - 
						addTargetData->RAID_Info.nSpareDisk;
					ulSize = sizeof(LANSCSI_ADD_TARGET_DATA) + 
						sizeof(LSBUS_UNITDISK) * (addTargetData->ulNumberOfUnitDiskList - 1);
				
					switch(ulDiskCount)
					{
					case 3: // 2 + 1
					case 5: // 4 + 1
					case 9: // 8 + 1
						break;
					default: // do not accept
						ulSize = 0;
						break;
					}
					break;
				}				
			default:
				Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("ADD_TARGET: Bad Disk Type.\n"));
				status = STATUS_UNSUCCESSFUL;
				break;
			}
			if(!NT_SUCCESS(status)) {
				Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("ADD_TARGET: Invaild type.\n"));
				status = STATUS_UNSUCCESSFUL;
				break;
			}

			// Check Size.
			if(ulSize != inlen) 
			{
				Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("ADD_TARGET: Size mismatch. Req %d, in %d\n", ulSize, inlen));
				status = STATUS_UNSUCCESSFUL;
				break;
			}
#if DBG
			NDBusIoctlLogError(	fdoData->Self,
				NDASBUS_IO_TRY_TO_ADDTARGET,
				IOCTL_LANSCSI_ADD_TARGET,
				addTargetData->ulSlotNo);
#endif
			// Find Pdo Data...
			pdoData = LookupPdoData(fdoData, addTargetData->ulSlotNo);
			if(pdoData == NULL) 
			{
				Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR,
					("no pdo\n"));
				status = STATUS_UNSUCCESSFUL;
				NDBusIoctlLogError(	fdoData->Self,
									NDASBUS_IO_PDO_NOT_FOUND,
									IOCTL_LANSCSI_ADD_TARGET,
									addTargetData->ulSlotNo);
				break;
			}

			pdoData->LanscsiAdapterPDO.AddDevInfo = ExAllocatePool(NonPagedPool, inlen);

			if(pdoData->LanscsiAdapterPDO.AddDevInfo == NULL) 
			{
				status = STATUS_INSUFFICIENT_RESOURCES;
			}
			else 
			{
				RtlCopyMemory(pdoData->LanscsiAdapterPDO.AddDevInfo, addTargetData, inlen);
				status = STATUS_SUCCESS;
			}

			pdoData->LanscsiAdapterPDO.AddDevInfoLength = inlen;

			//
			//	Notify to LanscsiMiniport
			//
			Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_LANSCSI_ADD_TARGET SetEvent AddTargetEvent!\n"));
			KeSetEvent(&pdoData->LanscsiAdapterPDO.AddTargetEvent, IO_NO_INCREMENT, FALSE);

			//
			//	Register Target
			//
			if(pdoData->Persistent) {
				status = LSBus_RegisterTarget(fdoData, addTargetData);
				if(!NT_SUCCESS(status)) {
					Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("ADD_TARGET: LSBus_RegisterTarget() failed. STATUS=%08lx\n", status));
					status = STATUS_INTERNAL_DB_ERROR;
					NDBusIoctlLogError(	fdoData->Self,
										NDASBUS_IO_REGISTER_TARGET_FAIL,
										IOCTL_LANSCSI_ADD_TARGET,
										addTargetData->ulSlotNo);
				} else {
					Bus_KdPrint(fdoData, BUS_DBG_IOCTL_INFO, ("ADD_TARGET: Successfully registered.\n"));
				}
			}

			ObDereferenceObject(pdoData->Self);

			Irp->IoStatus.Information = outlen;
		}        
		else
		{
			Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR,
								("IOCTL_LANSCSI_ADD_TARGET length mismatch!!!"
								" inlen %d, outlen %d, sizeof(LANSCSI_ADD_TARGET_DATA) %d\n",
								inlen, outlen, sizeof(LANSCSI_ADD_TARGET_DATA)));
		}

	}
		break;

	case IOCTL_LANSCSI_REMOVE_TARGET:
	{
	    PPDO_DEVICE_DATA	pdoData;
		PLANSCSI_REMOVE_TARGET_DATA	removeTarget;

        Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_LANSCSI_REMOVE_TARGET called\n"));

        if (sizeof (LANSCSI_REMOVE_TARGET_DATA) != inlen)
			break;

		removeTarget = (PLANSCSI_REMOVE_TARGET_DATA)buffer;
		pdoData = LookupPdoData(fdoData, removeTarget->ulSlotNo);
		if(pdoData == NULL) {
			Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR,
						("no pdo\n"));
			status = STATUS_UNSUCCESSFUL;
			NDBusIoctlLogError(	fdoData->Self,
				NDASBUS_IO_PDO_NOT_FOUND,
				IOCTL_LANSCSI_ADD_TARGET,
				removeTarget->ulSlotNo);
			break;
		}

		//
		//	redirect to the NDAS SCSI Device
		//
		status = LSBus_IoctlToLSMPDevice(
				pdoData,
				LANSCSIMINIPORT_IOCTL_REMOVE_TARGET,
				buffer,
				sizeof(LANSCSI_REMOVE_TARGET_DATA),
				NULL,
				0
			);

		if(NT_SUCCESS(status) && pdoData->Persistent) {

			status = LSBus_UnregisterTarget(fdoData, removeTarget->ulSlotNo, removeTarget->ulTargetId);
			if(!NT_SUCCESS(status)) {
				Bus_KdPrint(fdoData, BUS_DBG_IOCTL_INFO, (	"REMOVE_TARGET: Removed  Target instance,"
															" but LSBus_UnregisterTarget() failed.\n"));
				status = STATUS_INTERNAL_DB_ERROR;
				NDBusIoctlLogError(	fdoData->Self,
					NDASBUS_IO_UNREGISTER_TARGET_FAIL,
					IOCTL_LANSCSI_REMOVE_TARGET,
					removeTarget->ulSlotNo);
			}
#if DBG
			else {
				Bus_KdPrint(fdoData, BUS_DBG_IOCTL_INFO, ("REMOVE_TARGET: LSBus_UnregisterTarget() succeeded.\n"));
			}
#endif
		}

		ObDereferenceObject(pdoData->Self);

        Irp->IoStatus.Information = 0;
		break;
	}

	case IOCTL_LANSCSI_RECOVER_TARGET:
	{
	    PPDO_DEVICE_DATA	pdoData;

        Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_LANSCSI_RECOVER_TARGET called\n"));

        if (sizeof (LANSCSI_RECOVER_TARGET_DATA) != inlen)
			break;

		pdoData = LookupPdoData(fdoData, ((PLANSCSI_RECOVER_TARGET_DATA)buffer)->ulSlotNo);
		if(pdoData == NULL) {
			Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR,
						("no pdo\n"));
			status = STATUS_UNSUCCESSFUL;
			NDBusIoctlLogError(	fdoData->Self,
				NDASBUS_IO_PDO_NOT_FOUND,
				IOCTL_LANSCSI_ADD_TARGET,
				((PLANSCSI_RECOVER_TARGET_DATA)buffer)->ulSlotNo);
			break;
		}

		//
		//	redirect to the LanscsiMiniport Device
		//
		status = LSBus_IoctlToLSMPDevice(
				pdoData,
				LANSCSIMINIPORT_IOCTL_RECOVER_TARGET,
				buffer,
				sizeof(LANSCSI_RECOVER_TARGET_DATA),
				NULL,
				0
			);

		ObDereferenceObject(pdoData->Self);

        Irp->IoStatus.Information = outlen;
		break;
	}

	case IOCTL_LANSCSI_STARTSTOP_REGISTRARENUM:{
		PULONG	onOff = (PULONG)buffer;

		Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, (
			"STARTSTOP_REGISTRARENUM: inlen %d, outlen %d OnOff %u\n", inlen, outlen, *onOff));

		ExAcquireFastMutex(&fdoData->RegMutex);

		if(*onOff != 0) {

			//
			//	Save old state.
			//	Activate the registrar's enumeration
			//

			*onOff = fdoData->StartStopRegistrarEnum;
			fdoData->StartStopRegistrarEnum = TRUE;
		} else {

			//
			//	Save old state.
			//	Deactivate the registrar's enumeration
			//

			*onOff = fdoData->StartStopRegistrarEnum;
			fdoData->StartStopRegistrarEnum = FALSE;
		}
		ExReleaseFastMutex(&fdoData->RegMutex);

		Irp->IoStatus.Information = sizeof(ULONG);
		status = STATUS_SUCCESS;

		break;
	}

	case IOCTL_LANSCSI_REGISTER_DEVICE:
	{

		Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, (
							"REGISTER_DEVICE: inlen %d, outlen %d,"
							" sizeof(LANSCSI_ADD_TARGET_DATA) %d\n",
							inlen, outlen, sizeof(LANSCSI_ADD_TARGET_DATA)));
		if ((inlen == outlen)) {

			PBUSENUM_PLUGIN_HARDWARE_EX2	PlugIn = buffer;

			Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("REGISTER_DEVICE: entered\n"));

			status = LSBus_RegisterDevice(fdoData, PlugIn);

			Irp->IoStatus.Information = 0;
		}
		else
			Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR,
									("REGISTER_DEVICE: length mismatch!!!"
									" inlen %d, outlen %d, sizeof(LANSCSI_ADD_TARGET_DATA) %d\n",
									inlen, outlen, sizeof(LANSCSI_ADD_TARGET_DATA)));

	}
		break;
	case IOCTL_LANSCSI_REGISTER_TARGET:
	{

		Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, (
									"REGISTER_TARGET: inlen %d, outlen %d,"
									" sizeof(LANSCSI_ADD_TARGET_DATA) %d\n",
									inlen, outlen, sizeof(LANSCSI_ADD_TARGET_DATA)));
		if ((inlen == outlen)) {

			PLANSCSI_ADD_TARGET_DATA	AddTargetData = buffer;

			Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("REGISTER_TARGET: entered\n"));

			status = LSBus_RegisterTarget(fdoData, AddTargetData);

			Irp->IoStatus.Information = 0;
		}
		else {
			Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, (
									"REGISTER_TARGET: length mismatch!!!"
									" inlen %d, outlen %d, sizeof(LANSCSI_ADD_TARGET_DATA) %d\n",
									inlen, outlen, sizeof(LANSCSI_ADD_TARGET_DATA)));
		}

	}
		break;
	case IOCTL_LANSCSI_UNREGISTER_DEVICE:
	{
		Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, (
									"UNREGISTER_DEVICE: inlen %d, outlen %d,"
									" sizeof(LANSCSI_ADD_TARGET_DATA) %d\n",
									inlen, outlen, sizeof(LANSCSI_ADD_TARGET_DATA)));
		if ((inlen == outlen)) {

			PLANSCSI_UNREGISTER_NDASDEV	UnregDev = buffer;

			Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("UNREGISTER_DEVICE: entered\n"));

			status = LSBus_UnregisterDevice(fdoData, UnregDev->SlotNo);

			Irp->IoStatus.Information = 0;
		}
		else {
			Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, (
									"UNREGISTER_DEVICE: length mismatch!!!"
									" inlen %d, outlen %d, sizeof(LANSCSI_ADD_TARGET_DATA) %d\n",
									inlen, outlen, sizeof(LANSCSI_ADD_TARGET_DATA)));
		}
	}
	break;
	case IOCTL_LANSCSI_UNREGISTER_TARGET:
	{
		Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, (
									"UNREGISTER_TARGET: inlen %d, outlen %d,"
									" sizeof(LANSCSI_ADD_TARGET_DATA) %d\n",
									inlen, outlen, sizeof(LANSCSI_ADD_TARGET_DATA)));
		if ((inlen == outlen)) {

			PLANSCSI_UNREGISTER_TARGET	UnregTarget = buffer;

			Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("UNREGISTER_TARGET: entered\n"));

			status = LSBus_UnregisterTarget(fdoData, UnregTarget->SlotNo, UnregTarget->TargetId);

			Irp->IoStatus.Information = 0;
		}
		else {
			Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, (
									"UNREGISTER_TARGET: length mismatch!!!"
									" inlen %d, outlen %d, sizeof(LANSCSI_ADD_TARGET_DATA) %d\n",
									inlen, outlen, sizeof(LANSCSI_ADD_TARGET_DATA)));
		}
	}
	break;
	case IOCTL_LANSCSI_SETPDOINFO:
		{
	    PPDO_DEVICE_DATA	pdoData;
		PBUSENUM_SETPDOINFO	SetPdoInfo;
		KIRQL				oldIrql;
		PVOID				sectionHandle;

        Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_LANSCSI_SETPDOINFO called\n"));

        if (sizeof (BUSENUM_SETPDOINFO) != inlen)
			break;

		SetPdoInfo = (PBUSENUM_SETPDOINFO)buffer;
		pdoData = LookupPdoData(fdoData, SetPdoInfo->SlotNo);
		if(pdoData == NULL) {
			Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR,
						("no pdo\n"));
			status = STATUS_UNSUCCESSFUL;
			NDBusIoctlLogError(	fdoData->Self,
				NDASBUS_IO_PDO_NOT_FOUND,
				IOCTL_LANSCSI_ADD_TARGET,
				SetPdoInfo->SlotNo);
			break;
		}

		//
		//	lock the code section of this function to acquire spinlock in raised IRQL.
		//
	    sectionHandle = MmLockPagableCodeSection(Bus_IoCtl);

		KeAcquireSpinLock(&pdoData->LanscsiAdapterPDO.LSDevDataSpinLock, &oldIrql);

        Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("!!!!!!!!!!!!!!!!!!  IOCTL_LANSCSI_SETPDOINFO: %08lx %08lx %08lx\n",
										SetPdoInfo->AdapterStatus, SetPdoInfo->DesiredAccess, SetPdoInfo->GrantedAccess));


		//
		//	Set status values to the corresponding physical device object.
		//

		if(ADAPTERINFO_ISSTATUS(SetPdoInfo->AdapterStatus, ADAPTERINFO_STATUS_STOPPING) &&
			ADAPTERINFO_ISSTATUS(pdoData->LanscsiAdapterPDO.AdapterStatus, ADAPTERINFO_STATUS_STOPPED)) {

				Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("SETPDOINFO: 'Stopping' event occured after 'Stopped' event\n",
					SetPdoInfo->AdapterStatus, SetPdoInfo->DesiredAccess, SetPdoInfo->GrantedAccess));

		} else {
			pdoData->LanscsiAdapterPDO.AdapterStatus = SetPdoInfo->AdapterStatus;
			pdoData->LanscsiAdapterPDO.DesiredAccess = SetPdoInfo->DesiredAccess;
			pdoData->LanscsiAdapterPDO.GrantedAccess = SetPdoInfo->GrantedAccess;
		}

		//
		//	Queue plugout worker if the NDAS SCSI stop abnormally.
		//
		if(ADAPTERINFO_ISSTATUS(SetPdoInfo->AdapterStatus, ADAPTERINFO_STATUS_STOPPED) &&
			ADAPTERINFO_ISSTATUSFLAG(SetPdoInfo->AdapterStatus, ADAPTERINFO_STATUSFLAG_ABNORMAL_TERMINAT)) {

			Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("SETPDOINFO: Queueing Unplug worker!!!!!!!!\n",
					SetPdoInfo->AdapterStatus, SetPdoInfo->DesiredAccess, SetPdoInfo->GrantedAccess));

			status = QueueUnplugWorker(fdoData, SetPdoInfo->SlotNo);
		}

		KeReleaseSpinLock(&pdoData->LanscsiAdapterPDO.LSDevDataSpinLock, oldIrql);


		//
		//	Release the code section.
		//

	    MmUnlockPagableImageSection(sectionHandle);

		status = STATUS_SUCCESS;
		ObDereferenceObject(pdoData->Self);

        Irp->IoStatus.Information = outlen;
	}
		break;

	case IOCTL_BUSENUM_QUERY_NODE_ALIVE: 
		{

		PPDO_DEVICE_DATA		pdoData;
		BOOLEAN					bAlive;
		PBUSENUM_NODE_ALIVE_IN	pNodeAliveIn;
		BUSENUM_NODE_ALIVE_OUT	nodeAliveOut;

		// Check Parameter.
		if(inlen != sizeof(BUSENUM_NODE_ALIVE_IN) || 
			outlen != sizeof(BUSENUM_NODE_ALIVE_OUT)) {
			status = STATUS_UNKNOWN_REVISION;
			break;
		}
		
		pNodeAliveIn = (PBUSENUM_NODE_ALIVE_IN)Irp->AssociatedIrp.SystemBuffer;  
		
		Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_NOISE,
			("FDO: IOCTL_BUSENUM_QUERY_NODE_ALIVE SlotNumber = %d\n",
			pNodeAliveIn->SlotNo));
		
		pdoData = LookupPdoData(fdoData, pNodeAliveIn->SlotNo);

		if(pdoData == NULL) {
//			Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_TRACE,
//				("[LanScsiBus]Bus_IoCtl: IOCTL_BUSENUM_QUERY_NODE_ALIVE No pdo\n"));
			
			bAlive = FALSE;
		} else {
			//
			// Check this PDO would be removed...
			//
			if(pdoData->Present == TRUE) 
				bAlive = TRUE;
			else
				bAlive = FALSE;
		}

		// For Result...
		nodeAliveOut.SlotNo = pNodeAliveIn->SlotNo;
		nodeAliveOut.bAlive = bAlive;
		// Get Adapter Status.
		if(bAlive == TRUE)
		{
			if(	ADAPTERINFO_ISSTATUS(pdoData->LanscsiAdapterPDO.AdapterStatus, ADAPTERINFO_STATUS_IN_ERROR) ||
				ADAPTERINFO_ISSTATUS(pdoData->LanscsiAdapterPDO.AdapterStatus, ADAPTERINFO_STATUS_STOPPING) /*||
				ADAPTERINFO_ISSTATUSFLAG(pdoData->LanscsiAdapterPDO.AdapterStatus, ADAPTERINFO_STATUSFLAG_MEMBER_FAULT) */
				) {

				nodeAliveOut.bHasError = TRUE;
				Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR,
					("IOCTL_BUSENUM_QUERY_NODE_ALIVE Adapter has Error 0x%x\n", nodeAliveOut.bHasError));
			} else {
				nodeAliveOut.bHasError = FALSE;
			}

		}

		if(pdoData)
			ObDereferenceObject(pdoData->Self);

		RtlCopyMemory(
			Irp->AssociatedIrp.SystemBuffer,
			&nodeAliveOut,
			sizeof(BUSENUM_NODE_ALIVE_OUT)
			);
		
		Irp->IoStatus.Information = sizeof(BUSENUM_NODE_ALIVE_OUT);
		status = STATUS_SUCCESS;
		}
		break;

	//
	//	added by hootch 01172004
	//
	case IOCTL_LANSCSI_UPGRADETOWRITE:
		{
		PPDO_DEVICE_DATA				pdoData;

		Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_LANSCSI_UPGRADETOWRITE called\n"));
		// Check Parameter.
		if(inlen != sizeof(BUSENUM_UPGRADE_TO_WRITE)) {
			Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR,
				("IOCTL_LANSCSI_UPGRADETOWRITE: Invalid input buffer length\n"));
			status = STATUS_UNKNOWN_REVISION;
			break;
		}

		pdoData = LookupPdoData(fdoData, ((PBUSENUM_UPGRADE_TO_WRITE)buffer)->SlotNo);
		if(pdoData == NULL) {
			Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR,
				("IOCTL_LANSCSI_UPGRADETOWRITE: No pdo for Slotno:%d\n", ((PBUSENUM_UPGRADE_TO_WRITE)buffer)->SlotNo));
			status = STATUS_NO_SUCH_DEVICE;
			NDBusIoctlLogError(	fdoData->Self,
				NDASBUS_IO_PDO_NOT_FOUND,
				IOCTL_LANSCSI_ADD_TARGET,
				((PBUSENUM_UPGRADE_TO_WRITE)buffer)->SlotNo);
		} else {
			//
			//	redirect to the LanscsiMiniport Device
			//
			status = LSBus_IoctlToLSMPDevice(
					pdoData,
					LANSCSIMINIPORT_IOCTL_UPGRADETOWRITE,
					buffer,
					inlen,
					buffer,
					outlen
				);

			ObDereferenceObject(pdoData->Self);
		}
		Irp->IoStatus.Information = 0;
	}
		break;

	case IOCTL_LANSCSI_REDIRECT_NDASSCSI:
		{
		PPDO_DEVICE_DATA				pdoData;
		PBUSENUM_REDIRECT_NDASSCSI		redirectIoctl;

		Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_LANSCSI_REDIRECT_NDASSCSI called\n"));
		// Check Parameter.
		if(inlen < sizeof(BUSENUM_REDIRECT_NDASSCSI)) {
			Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR,
				("IOCTL_LANSCSI_REDIRECT_NDASSCSI: Invalid input buffer length\n"));
			status = STATUS_UNKNOWN_REVISION;
			break;
		}

		redirectIoctl = (PBUSENUM_REDIRECT_NDASSCSI)buffer;

		pdoData = LookupPdoData(fdoData, redirectIoctl->SlotNo);
		if(pdoData == NULL) {
			Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR,
				("IOCTL_LANSCSI_REDIRECT_NDASSCSI: No pdo for Slotno:%d\n", redirectIoctl->SlotNo));
			status = STATUS_NO_SUCH_DEVICE;
		} else {
			//
			//	redirect to the LanscsiMiniport Device
			//
			status = LSBus_IoctlToLSMPDevice(
					pdoData,
					redirectIoctl->IoctlCode,
					redirectIoctl->IoctlData,
					redirectIoctl->IoctlDataSize,
					redirectIoctl->IoctlData,
					redirectIoctl->IoctlDataSize
				);

			ObDereferenceObject(pdoData->Self);
		}
		Irp->IoStatus.Information = 0;
	}
		break;

	case IOCTL_LANSCSI_QUERY_LSMPINFORMATION:
		{
		PPDO_DEVICE_DATA				pdoData;

		Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_LANSCSI_QUERY_LSMPINFORMATION called\n"));
		// Check Parameter.
		if(inlen < FIELD_OFFSET(LSMPIOCTL_QUERYINFO, QueryData) ) {
			Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR,
				("IOCTL_LANSCSI_QUERY_LSMPINFORMATION: Invalid input buffer length too small.\n"));
			status = STATUS_UNKNOWN_REVISION;
			break;
		}
		pdoData = LookupPdoData(fdoData, ((PLSMPIOCTL_QUERYINFO)buffer)->SlotNo);

		if(pdoData == NULL) {
			Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR,
				("IOCTL_LANSCSI_QUERY_LSMPINFORMATION No pdo\n"));
			status = STATUS_NO_SUCH_DEVICE;
			NDBusIoctlLogError(	fdoData->Self,
				NDASBUS_IO_PDO_NOT_FOUND,
				IOCTL_LANSCSI_ADD_TARGET,
				((PLSMPIOCTL_QUERYINFO)buffer)->SlotNo);
		} else {
			//
			//	redirect to the LanscsiMiniport Device
			//
			status = LSBus_IoctlToLSMPDevice(
					pdoData,
					LANSCSIMINIPORT_IOCTL_QUERYINFO_EX,
					buffer,
					inlen,
					buffer,
					outlen
				);

			ObDereferenceObject(pdoData->Self);
		}
        Irp->IoStatus.Information = outlen;
		}
		break;

	case IOCTL_BUSENUM_QUERY_INFORMATION:
		{

//		PPDO_DEVICE_DATA				pdoData;
		BUSENUM_QUERY_INFORMATION		Query;
		PBUSENUM_INFORMATION			Information;
		LONG							BufferLenNeeded;

		// Check Parameter.
		if(	inlen < sizeof(BUSENUM_QUERY_INFORMATION) /*|| 
			outlen < sizeof(BUSENUM_INFORMATION) */) {
			status = STATUS_UNKNOWN_REVISION;
			break;
		}

		RtlCopyMemory(&Query, buffer, sizeof(BUSENUM_QUERY_INFORMATION));
		Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_TRACE,
			("FDO: IOCTL_BUSENUM_QUERY_INFORMATION QueryType : %d  SlotNumber = %d\n",
			Query.InfoClass, Query.SlotNo));

		Information = (PBUSENUM_INFORMATION)buffer;
		ASSERT(Information);
		Information->InfoClass = Query.InfoClass;
		status = LSBus_QueryInformation(fdoData, &Query, Information, outlen, &BufferLenNeeded);
		if(NT_SUCCESS(status)) {
			Information->Size = BufferLenNeeded;
			Irp->IoStatus.Information = BufferLenNeeded;
		} else {
			Irp->IoStatus.Information = BufferLenNeeded;
		}
		}
		break;

	case IOCTL_BUSENUM_PLUGIN_HARDWARE_EX:
		{
			if ((inlen == outlen) &&
				//
				// Make sure it has at least two nulls and the size 
				// field is set to the declared size of the struct
				//
				((sizeof (BUSENUM_PLUGIN_HARDWARE_EX) + sizeof(UNICODE_NULL) * 2) <=
				inlen) &&

				//
				// The size field should be set to the sizeof the struct as declared
				// and *not* the size of the struct plus the multi_sz
				//
				(sizeof (BUSENUM_PLUGIN_HARDWARE_EX) ==
				((PBUSENUM_PLUGIN_HARDWARE_EX) buffer)->Size)) {

				Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("PlugIn called\n"));

				status= Bus_PlugInDeviceEx((PBUSENUM_PLUGIN_HARDWARE_EX)buffer,
											inlen, fdoData, Irp->RequestorMode);
	           
				Irp->IoStatus.Information = outlen;

			}
		}
        break;

	case IOCTL_BUSENUM_PLUGIN_HARDWARE_EX2:
		{
			if ((inlen == outlen) &&
				//
				// Make sure it has at least two nulls and the size 
				// field is set to the declared size of the struct
				//
				((sizeof (BUSENUM_PLUGIN_HARDWARE_EX2) + sizeof(UNICODE_NULL) * 2) <=
				inlen) &&

				//
				// The size field should be set to the sizeof the struct as declared
				// and *not* the size of the struct plus the multi_sz
				//
				(sizeof (BUSENUM_PLUGIN_HARDWARE_EX2) ==
				((PBUSENUM_PLUGIN_HARDWARE_EX2) buffer)->Size)) {

				Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("PlugIn called\n"));

				status= Bus_PlugInDeviceEx2((PBUSENUM_PLUGIN_HARDWARE_EX2)buffer,
											inlen, fdoData, Irp->RequestorMode, FALSE);

				Irp->IoStatus.Information = outlen;

			}
		}
        break;

	case IOCTL_LANSCSI_GETVERSION:
		{
			if (outlen >= sizeof(BUSENUM_GET_VERSION)) {
				PBUSENUM_GET_VERSION version = (PBUSENUM_GET_VERSION)buffer;

				Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_LANSCSI_GETVERSION: called\n"));

			try {
				version->VersionMajor = VER_FILEMAJORVERSION;
				version->VersionMinor = VER_FILEMINORVERSION;
				version->VersionBuild = VER_FILEBUILD;
				version->VersionPrivate = VER_FILEBUILD_QFE;

					Irp->IoStatus.Information = sizeof(BUSENUM_GET_VERSION);
					status = STATUS_SUCCESS;

				} except (EXCEPTION_EXECUTE_HANDLER) {

					status = GetExceptionCode();
					Irp->IoStatus.Information = 0;
				}

			}
		}			
		break;

    case IOCTL_BUSENUM_UNPLUG_HARDWARE:
		{
			if ((sizeof (BUSENUM_UNPLUG_HARDWARE) == inlen) &&
				(inlen == outlen) &&
				(((PBUSENUM_UNPLUG_HARDWARE)buffer)->Size == inlen)) {

				Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("UnPlug called\n"));

				status= Bus_UnPlugDevice(
						(PBUSENUM_UNPLUG_HARDWARE)buffer, fdoData);
				Irp->IoStatus.Information = outlen;

			}
		}
        break;

    case IOCTL_BUSENUM_EJECT_HARDWARE:
		{
			if ((sizeof (BUSENUM_EJECT_HARDWARE) == inlen) &&
				(inlen == outlen) &&
				(((PBUSENUM_EJECT_HARDWARE)buffer)->Size == inlen)) {

				Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("Eject called\n"));

				status= Bus_EjectDevice((PBUSENUM_EJECT_HARDWARE)buffer, fdoData);

				Irp->IoStatus.Information = outlen;
			}
		}
		break;

	case IOCTL_DVD_GET_STATUS:
		{
			PPDO_DEVICE_DATA		pdoData;
			PBUSENUM_DVD_STATUS		pDvdStatusData;


			// Check Parameter.
			if((inlen != outlen)
				|| (sizeof(BUSENUM_DVD_STATUS) >  inlen))
			{
				status = STATUS_UNSUCCESSFUL ;
				break;
			}
			
			pDvdStatusData = (PBUSENUM_DVD_STATUS)Irp->AssociatedIrp.SystemBuffer;  
			
			Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR,
				("FDO: IOCTL_DVD_GET_STATUS SlotNumber = %d\n",
				pDvdStatusData->SlotNo));	

			pdoData = LookupPdoData(fdoData, pDvdStatusData->SlotNo);
			
			if(pdoData == NULL) {
				Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR,
					("IOCTL_DVD_GET_STATUS No pdo\n"));
				status = STATUS_UNSUCCESSFUL;
				NDBusIoctlLogError(	fdoData->Self,
					NDASBUS_IO_PDO_NOT_FOUND,
					IOCTL_LANSCSI_ADD_TARGET,
					pDvdStatusData->SlotNo);
				break;
			} else {

				if(pdoData->LanscsiAdapterPDO.Flags & LSDEVDATA_FLAG_LURDESC) {
					//
					//	A LUR descriptor is set.
					//
					if(((PLURELATION_DESC)pdoData->LanscsiAdapterPDO.AddDevInfo)->DevType != DISK_TYPE_DVD)
				{
					Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR,
						("IOCTL_DVD_GET_STATUS  No DVD Device\n"));
					status = STATUS_UNSUCCESSFUL;
					break;
				}
				} else {
					//
					//	ADD_TARGET_DATA is set.
					//
					if(((PLANSCSI_ADD_TARGET_DATA)pdoData->LanscsiAdapterPDO.AddDevInfo)->ucTargetType != DISK_TYPE_DVD)
					{
						Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR,
							("IOCTL_DVD_GET_STATUS  No DVD Device\n"));
						status = STATUS_UNSUCCESSFUL;
						break;
					}
				}
				//
				//	redirect to the LanscsiMiniport Device
				//
				status = LSBus_IoctlToLSMPDevice(
						pdoData,
						LANSCSIMINIPORT_IOCTL_GET_DVD_STATUS,
						buffer,
						inlen,
						buffer,
						outlen
					);

				ObDereferenceObject(pdoData->Self);
				status = STATUS_SUCCESS;
				Irp->IoStatus.Information = outlen;
			}					
		}
		break;
    default:
        break; // default status is STATUS_INVALID_PARAMETER
    }
Ejemplo n.º 7
0
BOOL
CNdasLogicalDevice::Recover()
{
	BOOL fSuccess(FALSE);

	ximeta::CAutoLock autolock(this);

	DBGPRT_INFO(_FT("Recovering %s\n"), ToString());

	switch(GetType())
	{
	case NDAS_LOGICALDEVICE_TYPE_DISK_RAID1:
	case NDAS_LOGICALDEVICE_TYPE_DISK_RAID4:
		break;
	default:
		return FALSE;
	}

	if (m_status == NDAS_LOGICALDEVICE_STATUS_NOT_INITIALIZED) {
		::SetLastError(NDASHLPSVC_ERROR_NDAS_LOGICALDEVICE_NOT_INITIALIZED);
		return FALSE;
	}

	if (m_status != NDAS_LOGICALDEVICE_STATUS_MOUNTED) 
	{
		::SetLastError(NDASHLPSVC_ERROR_NDAS_LOGICALDEVICE_NOT_MOUNTED);
		return FALSE;
	}

	// Do not recover if any NDAS unit device is not alive
	DWORD ldSequence = 0;
	for(ldSequence = 0; ldSequence < m_logicalDeviceGroup.nUnitDevices; ldSequence++)
	{
		if(NDAS_UNITDEVICE_STATUS_MOUNTED != m_pUnitDevices[ldSequence]->GetStatus())
		{
			::SetLastError(NDASHLPSVC_ERROR_NDAS_UNITDEVICE_NOT_MOUNTED);
			return FALSE;
		}
	}

	if(IsAnyUnitDevicesFault())
	{
		::SetLastError(NDASHLPSVC_ERROR_NDAS_UNITDEVICE_NOT_MOUNTED);
		return FALSE;
	}

	ULONG ulStatus;

	fSuccess = ::LsBusCtlQueryStatus(		
		m_NdasScsiLocation.SlotNo,
		&ulStatus);

	if (!fSuccess) {
		DBGPRT_ERR_EX(_FT("Unable to get status"));
		return FALSE;
	}

	// Do not recover if NDAS logical device is not under emergency
	// Do not recover if NDAS logical device is already recovering
	if(!ADAPTERINFO_ISSTATUSFLAG(ulStatus, ADAPTERINFO_STATUSFLAG_MEMBER_FAULT))
	{
		DBGPRT_ERR_EX(_FT("Not in emergency mode or already recovering"));
		return FALSE;
	}


	//
	// LsBusCtl is overhauled only to use SlotNo for RemoveTargetData
	//

	//
	// Remove target ejects the disk and the volume.
	//

	fSuccess = LsBusCtlRecoverTarget(m_NdasScsiLocation.SlotNo);
	if (!fSuccess) {
		DBGPRT_WARN_EX(_FT("LsBusCtlRemoveTarget failed: "));
	}

	DBGPRT_INFO(_FT("Started recovering successfully at slot %s.\n"),
		CNdasScsiLocation(m_NdasScsiLocation).ToString());

	return TRUE;

}