Exemplo n.º 1
0
//
//	Plug in a NDAS device with a LUR descriptor.
//
NTSTATUS
LSBus_AddTarget(
		PFDO_DEVICE_DATA			FdoData,
		PNDASBUS_ADD_TARGET_DATA	AddTargetData
) {
	PPDO_DEVICE_DATA	pdoData;
	NTSTATUS			status;

	status = STATUS_SUCCESS;
	//
	//	Verify LurDesc
	//	TODO:
	//
	
	// Find Pdo Data...
	pdoData = LookupPdoData(FdoData, AddTargetData->ulSlotNo);
	if(pdoData == NULL) {
		Bus_KdPrint_Cont (FdoData, BUS_DBG_IOCTL_ERROR, ("no pdo for Slot %u\n", AddTargetData->ulSlotNo));
		return STATUS_NOT_FOUND;
	}

	//
	//	Copy AddDevInfo into the PDO.
	//
	if(pdoData->LanscsiAdapterPDO.AddDevInfo) {
		Bus_KdPrint_Cont (FdoData, BUS_DBG_IOCTL_ERROR, ("AddDevInfo already set.\n"));

		status = STATUS_DEVICE_ALREADY_ATTACHED;
		goto cleanup;
	}
	pdoData->LanscsiAdapterPDO.AddDevInfo = ExAllocatePoolWithTag(NonPagedPool, AddTargetData->ulSize, BUSENUM_POOL_TAG);
	if(pdoData->LanscsiAdapterPDO.AddDevInfo == NULL) {
		status = STATUS_INSUFFICIENT_RESOURCES;
		goto cleanup;
	}

	RtlCopyMemory(pdoData->LanscsiAdapterPDO.AddDevInfo, AddTargetData, AddTargetData->ulSize);
	pdoData->LanscsiAdapterPDO.AddDevInfoLength = AddTargetData->ulSize;

	//
	// Init PDO status
	//

	pdoData->LanscsiAdapterPDO.LastAdapterStatus = NDASSCSI_ADAPTERINFO_STATUS_INIT;
	pdoData->LanscsiAdapterPDO.DeviceMode = AddTargetData->DeviceMode;
	InitializeListHead(&pdoData->LanscsiAdapterPDO.NdasPdoEventQueue);

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

cleanup:
	ObDereferenceObject(pdoData->Self);

	return status;
}
Exemplo n.º 2
0
//
//	Plug in a NDAS device with a LUR descriptor.
//
NTSTATUS
LSBus_AddTargetWithLurDesc(
		PFDO_DEVICE_DATA	FdoData,
		PLURELATION_DESC	LurDesc,
		ULONG				SlotNo
) {
	PPDO_DEVICE_DATA	pdoData;
	NTSTATUS			status;

	status = STATUS_SUCCESS;
	//
	//	Verify LurDesc
	//	TODO:
	//
	
	// Find Pdo Data...
	pdoData = LookupPdoData(FdoData, SlotNo);
	if(pdoData == NULL) {
		Bus_KdPrint_Cont (FdoData, BUS_DBG_IOCTL_ERROR, ("no pdo\n"));
		return STATUS_NOT_FOUND;
}

	//
	//	Copy AddDevInfo into the PDO.
	//
	if(pdoData->LanscsiAdapterPDO.AddDevInfo) {
		Bus_KdPrint_Cont (FdoData, BUS_DBG_IOCTL_ERROR, ("AddDevInfo already set.\n"));

		status = STATUS_DEVICE_ALREADY_ATTACHED;
		goto cleanup;
	}
	pdoData->LanscsiAdapterPDO.AddDevInfo = ExAllocatePool(NonPagedPool, LurDesc->Length);
	if(pdoData->LanscsiAdapterPDO.AddDevInfo == NULL) {
		status = STATUS_INSUFFICIENT_RESOURCES;
		goto cleanup;
	} else {
		RtlCopyMemory(pdoData->LanscsiAdapterPDO.AddDevInfo, LurDesc, LurDesc->Length);
		status = STATUS_SUCCESS;
	}
	pdoData->LanscsiAdapterPDO.AddDevInfoLength = LurDesc->Length;
	pdoData->LanscsiAdapterPDO.Flags |= LSDEVDATA_FLAG_LURDESC;

	//
	//	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);

cleanup:
	ObDereferenceObject(pdoData->Self);

	return status;
}
Exemplo n.º 3
0
//
//	Plug in a NDAS device with a LUR descriptor.
//
NTSTATUS
LSBus_AddTarget(
		PFDO_DEVICE_DATA			FdoData,
		PLANSCSI_ADD_TARGET_DATA	AddTargetData
) {
	PPDO_DEVICE_DATA	pdoData;
	NTSTATUS			status;

	status = STATUS_SUCCESS;
	//
	//	Verify LurDesc
	//	TODO:
	//
	
	// Find Pdo Data...
	pdoData = LookupPdoData(FdoData, AddTargetData->ulSlotNo);
	if(pdoData == NULL) {
		Bus_KdPrint_Cont (FdoData, BUS_DBG_IOCTL_ERROR, ("no pdo for Slot %u\n", AddTargetData->ulSlotNo));
		return STATUS_NOT_FOUND;
	}

	//
	//	Copy AddDevInfo into the PDO.
	//
	if(pdoData->LanscsiAdapterPDO.AddDevInfo) {
		Bus_KdPrint_Cont (FdoData, BUS_DBG_IOCTL_ERROR, ("AddDevInfo already set.\n"));

		status = STATUS_DEVICE_ALREADY_ATTACHED;
		goto cleanup;
	}
	pdoData->LanscsiAdapterPDO.AddDevInfo = ExAllocatePool(NonPagedPool, AddTargetData->ulSize);
	if(pdoData->LanscsiAdapterPDO.AddDevInfo == NULL) {
		status = STATUS_INSUFFICIENT_RESOURCES;
		goto cleanup;
	}

	RtlCopyMemory(pdoData->LanscsiAdapterPDO.AddDevInfo, AddTargetData, AddTargetData->ulSize);
	pdoData->LanscsiAdapterPDO.AddDevInfoLength = AddTargetData->ulSize;

	//
	//	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);

cleanup:
	ObDereferenceObject(pdoData->Self);

	return status;
}
Exemplo n.º 4
0
NTSTATUS
Bus_DestroyPdo (
    PDEVICE_OBJECT      Device,
    PPDO_DEVICE_DATA    PdoData
    )
/*++
Routine Description:
    The Plug & Play subsystem has instructed that this PDO should be removed.

    We should therefore
    - Complete any requests queued in the driver
    - If the device is still attached to the system,
    - then complete the request and return.
    - Otherwise, cleanup device specific allocations, memory, events...
    - Call IoDeleteDevice
    - Return from the dispatch routine.

    Note that if the device is still connected to the bus (IE in this case
    the enum application has not yet told us that the toaster device has disappeared)
    then the PDO must remain around, and must be returned during any
    query Device relations IRPS.

--*/

{
    PAGED_CODE ();

    //
    // BusEnum does not queue any irps at this time so we have nothing to do.
    //
    //
    // Free any resources.
    //

    if (PdoData->HardwareIDs) {
        ExFreePool (PdoData->HardwareIDs);
        PdoData->HardwareIDs = NULL;
    }

    if (PdoData->compatible_ids) {
        ExFreePool (PdoData->compatible_ids);
        PdoData->compatible_ids = NULL;
    }
    //FIXME
    if (PdoData->fo){
	    PdoData->fo->FsContext = NULL;
	    PdoData->fo = NULL;
    }
    Bus_KdPrint_Cont(PdoData, BUS_DBG_PNP_INFO,
                        ("\tDeleting PDO: 0x%p\n", Device));
    IoDeleteDevice (Device);
    return STATUS_SUCCESS;
}
Exemplo n.º 5
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
    }
Exemplo n.º 6
0
NTSTATUS
Bus_FDO_PnP (
    __in PDEVICE_OBJECT       DeviceObject,
    __in PIRP                 Irp,
    __in PIO_STACK_LOCATION   IrpStack,
    __in PFDO_DEVICE_DATA     DeviceData
    )
/*++
Routine Description:

    Handle requests from the Plug & Play system for the BUS itself

--*/
{
    NTSTATUS            status;
    ULONG               length, prevcount, numPdosPresent;
    PLIST_ENTRY         entry, listHead, nextEntry;
    PPDO_DEVICE_DATA    pdoData;
    PDEVICE_RELATIONS   relations, oldRelations;

    PAGED_CODE ();

    Bus_IncIoCount (DeviceData);

    switch (IrpStack->MinorFunction) {

    case IRP_MN_START_DEVICE:

        //
        // Send the Irp down and wait for it to come back.
        // Do not touch the hardware until then.
        //
        status = Bus_SendIrpSynchronously (DeviceData->NextLowerDriver, Irp);

        if (NT_SUCCESS(status)) {

            //
            // Initialize your device with the resources provided
            // by the PnP manager to your device.
            //
            status = Bus_StartFdo (DeviceData, Irp);
        }

        //
        // We must now complete the IRP, since we stopped it in the
        // completion routine with MORE_PROCESSING_REQUIRED.
        //

        Irp->IoStatus.Status = status;
        IoCompleteRequest (Irp, IO_NO_INCREMENT);
        Bus_DecIoCount (DeviceData);

        return status;

    case IRP_MN_QUERY_STOP_DEVICE:

        //
        // The PnP manager is trying to stop the device
        // for resource rebalancing. Fail this now if you
        // cannot stop the device in response to STOP_DEVICE.
        //
        SET_NEW_PNP_STATE(DeviceData, StopPending);
        Irp->IoStatus.Status = STATUS_SUCCESS; // You must not fail the IRP.
        break;

    case IRP_MN_CANCEL_STOP_DEVICE:

        //
        // The PnP Manager sends this IRP, at some point after an
        // IRP_MN_QUERY_STOP_DEVICE, to inform the drivers for a
        // device that the device will not be stopped for
        // resource reconfiguration.
        //
        //
        // First check to see whether you have received cancel-stop
        // without first receiving a query-stop. This could happen if
        //  someone above us fails a query-stop and passes down the subsequent
        // cancel-stop.
        //

        if (StopPending == DeviceData->DevicePnPState)
        {
            //
            // We did receive a query-stop, so restore.
            //
            RESTORE_PREVIOUS_PNP_STATE(DeviceData);
            ASSERT(DeviceData->DevicePnPState == Started);
        }
        Irp->IoStatus.Status = STATUS_SUCCESS; // We must not fail the IRP.
        break;

    case IRP_MN_STOP_DEVICE:

        //
        // Stop device means that the resources given during Start device
        // are now revoked. Note: You must not fail this Irp.
        // But before you relieve resources make sure there are no I/O in
        // progress. Wait for the existing ones to be finished.
        // To do that, first we will decrement this very operation.
        // When the counter goes to 1, Stop event is set.
        //

        Bus_DecIoCount(DeviceData);

        KeWaitForSingleObject(
                   &DeviceData->StopEvent,
                   Executive, // Waiting reason of a driver
                   KernelMode, // Waiting in kernel mode
                   FALSE, // No allert
                   NULL); // No timeout

        //
        // Increment the counter back because this IRP has to
        // be sent down to the lower stack.
        //

        Bus_IncIoCount (DeviceData);

        //
        // Free resources given by start device.
        //

        SET_NEW_PNP_STATE(DeviceData, Stopped);

        //
        // We don't need a completion routine so fire and forget.
        //
        // Set the current stack location to the next stack location and
        // call the next device object.
        //

        Irp->IoStatus.Status = STATUS_SUCCESS;
        break;

    case IRP_MN_QUERY_REMOVE_DEVICE:

        //
        // If we were to fail this call then we would need to complete the
        // IRP here.  Since we are not, set the status to SUCCESS and
        // call the next driver.
        //

        SET_NEW_PNP_STATE(DeviceData, RemovePending);

        Irp->IoStatus.Status = STATUS_SUCCESS;
        break;

    case IRP_MN_CANCEL_REMOVE_DEVICE:

        //
        // If we were to fail this call then we would need to complete the
        // IRP here.  Since we are not, set the status to SUCCESS and
        // call the next driver.
        //

        //
        // First check to see whether you have received cancel-remove
        // without first receiving a query-remove. This could happen if
        // someone above us fails a query-remove and passes down the
        // subsequent cancel-remove.
        //

        if (RemovePending == DeviceData->DevicePnPState)
        {
            //
            // We did receive a query-remove, so restore.
            //
            RESTORE_PREVIOUS_PNP_STATE(DeviceData);
        }
        Irp->IoStatus.Status = STATUS_SUCCESS;// You must not fail the IRP.
        break;

    case IRP_MN_SURPRISE_REMOVAL:

        //
        // The device has been unexpectedly removed from the machine
        // and is no longer available for I/O. Bus_RemoveFdo clears
        // all the resources, frees the interface and de-registers
        // with WMI, but it doesn't delete the FDO. That's done
        // later in Remove device query.
        //

        SET_NEW_PNP_STATE(DeviceData, SurpriseRemovePending);
        Bus_RemoveFdo(DeviceData);

        ExAcquireFastMutex (&DeviceData->Mutex);

        listHead = &DeviceData->ListOfPDOs;

        for(entry = listHead->Flink,nextEntry = entry->Flink;
            entry != listHead;
            entry = nextEntry,nextEntry = entry->Flink) {

            pdoData = CONTAINING_RECORD (entry, PDO_DEVICE_DATA, Link);
            RemoveEntryList (&pdoData->Link);
            InitializeListHead (&pdoData->Link);
            pdoData->ParentFdo  = NULL;
            pdoData->ReportedMissing = TRUE;
        }

        ExReleaseFastMutex (&DeviceData->Mutex);

        Irp->IoStatus.Status = STATUS_SUCCESS; // You must not fail the IRP.
        break;

    case IRP_MN_REMOVE_DEVICE:

        //
        // The Plug & Play system has dictated the removal of this device.
        // We have no choice but to detach and delete the device object.
        //

        //
        // Check the state flag to see whether you are surprise removed
        //

        if (DeviceData->DevicePnPState != SurpriseRemovePending)
        {
            Bus_RemoveFdo(DeviceData);
        }

        SET_NEW_PNP_STATE(DeviceData, Deleted);

        //
        // Wait for all outstanding requests to complete.
        // We need two decrements here, one for the increment in
        // the beginning of this function, the other for the 1-biased value of
        // OutstandingIO.
        //

        Bus_DecIoCount (DeviceData);

        //
        // The requestCount is at least one here (is 1-biased)
        //

        Bus_DecIoCount (DeviceData);

        KeWaitForSingleObject (
                &DeviceData->RemoveEvent,
                Executive,
                KernelMode,
                FALSE,
                NULL);

        //
        // Typically the system removes all the  children before
        // removing the parent FDO. If for any reason child Pdos are
        // still present we will destroy them explicitly, with one exception -
        // we will not delete the PDOs that are in SurpriseRemovePending state.
        //

        ExAcquireFastMutex (&DeviceData->Mutex);

        listHead = &DeviceData->ListOfPDOs;

        for(entry = listHead->Flink,nextEntry = entry->Flink;
            entry != listHead;
            entry = nextEntry,nextEntry = entry->Flink) {

            pdoData = CONTAINING_RECORD (entry, PDO_DEVICE_DATA, Link);
            RemoveEntryList (&pdoData->Link);
            if (SurpriseRemovePending == pdoData->DevicePnPState)
            {
                //
                // We will reinitialize the list head so that we
                // wouldn't barf when we try to delink this PDO from
                // the parent's PDOs list, when the system finally
                // removes the PDO. Let's also not forget to set the
                // ReportedMissing flag to cause the deletion of the PDO.
                //
                Bus_KdPrint_Cont(DeviceData, BUS_DBG_PNP_INFO,
                ("\tFound a surprise removed device: 0x%p\n", pdoData->Self));
                InitializeListHead (&pdoData->Link);
                pdoData->ParentFdo  = NULL;
                pdoData->ReportedMissing = TRUE;
                continue;
            }
            DeviceData->NumPDOs--;
            Bus_DestroyPdo (pdoData->Self, pdoData);
        }

        ExReleaseFastMutex (&DeviceData->Mutex);

        //
        // We need to send the remove down the stack before we detach,
        // but we don't need to wait for the completion of this operation
        // (and to register a completion routine).
        //

        Irp->IoStatus.Status = STATUS_SUCCESS;
        IoSkipCurrentIrpStackLocation (Irp);
        status = IoCallDriver (DeviceData->NextLowerDriver, Irp);
        //
        // Detach from the underlying devices.
        //

        IoDetachDevice (DeviceData->NextLowerDriver);

        Bus_KdPrint_Cont(DeviceData, BUS_DBG_PNP_INFO,
                        ("\tDeleting FDO: 0x%p\n", DeviceObject));

        IoDeleteDevice (DeviceObject);

        return status;

    case IRP_MN_QUERY_DEVICE_RELATIONS:

        Bus_KdPrint_Cont (DeviceData, BUS_DBG_PNP_TRACE,
                   ("\tQueryDeviceRelation Type: %s\n",
                    DbgDeviceRelationString(\
                    IrpStack->Parameters.QueryDeviceRelations.Type)));

        if (BusRelations != IrpStack->Parameters.QueryDeviceRelations.Type) {
            //
            // We don't support any other Device Relations
            //
            break;
        }

        //
        // Tell the plug and play system about all the PDOs.
        //
        // There might also be device relations below and above this FDO,
        // so, be sure to propagate the relations from the upper drivers.
        //
        // No Completion routine is needed so long as the status is preset
        // to success.  (PDOs complete plug and play irps with the current
        // IoStatus.Status and IoStatus.Information as the default.)
        //

        ExAcquireFastMutex (&DeviceData->Mutex);

        oldRelations = (PDEVICE_RELATIONS) Irp->IoStatus.Information;
        if (oldRelations) {
            prevcount = oldRelations->Count;
            if (!DeviceData->NumPDOs) {
                //
                // There is a device relations struct already present and we have
                // nothing to add to it, so just call IoSkip and IoCall
                //
                ExReleaseFastMutex (&DeviceData->Mutex);
                break;
            }
        }
        else  {
            prevcount = 0;
        }

        //
        // Calculate the number of PDOs actually present on the bus
        //
        numPdosPresent = 0;
        for (entry = DeviceData->ListOfPDOs.Flink;
             entry != &DeviceData->ListOfPDOs;
             entry = entry->Flink) {
            pdoData = CONTAINING_RECORD (entry, PDO_DEVICE_DATA, Link);
            if (pdoData->Present)
                numPdosPresent++;
        }

        //
        // Need to allocate a new relations structure and add our
        // PDOs to it.
        //

        length = sizeof(DEVICE_RELATIONS) +
                ((numPdosPresent + prevcount) * sizeof (PDEVICE_OBJECT)) -1;

        relations = (PDEVICE_RELATIONS) ExAllocatePoolWithTag (PagedPool,
                                        length, BUSENUM_POOL_TAG);

        if (NULL == relations) {
            //
            // Fail the IRP
            //
            ExReleaseFastMutex (&DeviceData->Mutex);
            Irp->IoStatus.Status = status = STATUS_INSUFFICIENT_RESOURCES;
            IoCompleteRequest (Irp, IO_NO_INCREMENT);
            Bus_DecIoCount (DeviceData);
            return status;

        }

        //
        // Copy in the device objects so far
        //
        if (prevcount) {
            RtlCopyMemory (relations->Objects, oldRelations->Objects,
                                      prevcount * sizeof (PDEVICE_OBJECT));
        }

        relations->Count = prevcount + numPdosPresent;

        //
        // For each PDO present on this bus add a pointer to the device relations
        // buffer, being sure to take out a reference to that object.
        // The Plug & Play system will dereference the object when it is done
        // with it and free the device relations buffer.
        //

        for (entry = DeviceData->ListOfPDOs.Flink;
             entry != &DeviceData->ListOfPDOs;
             entry = entry->Flink) {

            pdoData = CONTAINING_RECORD (entry, PDO_DEVICE_DATA, Link);
            if (pdoData->Present) {
                relations->Objects[prevcount] = pdoData->Self;
                ObReferenceObject (pdoData->Self);
                prevcount++;
            } else {
                pdoData->ReportedMissing = TRUE;
            }
        }

        Bus_KdPrint_Cont (DeviceData, BUS_DBG_PNP_TRACE,
                           ("\t#PDOS present = %d\n\t#PDOs reported = %d\n",
                             DeviceData->NumPDOs, relations->Count));

        //
        // Replace the relations structure in the IRP with the new
        // one.
        //
        if (oldRelations) {
            ExFreePool (oldRelations);
        }
        Irp->IoStatus.Information = (ULONG_PTR) relations;

        ExReleaseFastMutex (&DeviceData->Mutex);

        //
        // Set up and pass the IRP further down the stack
        //
        Irp->IoStatus.Status = STATUS_SUCCESS;
        break;

    default:

        //
        // In the default case we merely call the next driver.
        // We must not modify Irp->IoStatus.Status or complete the IRP.
        //

        break;
    }

    IoSkipCurrentIrpStackLocation (Irp);
    status = IoCallDriver (DeviceData->NextLowerDriver, Irp);
    Bus_DecIoCount (DeviceData);
    return status;
}
Exemplo n.º 7
0
NTSTATUS
Bus_FDO_Power (
    PFDO_DEVICE_DATA    Data,
    PIRP                Irp
    )
/*++
    Handles power Irps sent to the FDO.
    This driver is power policy owner for the bus itself
    (not the devices on the bus).Power handling for the bus FDO
    should be implemented similar to the function driver (toaster.sys)
    power code. We will just print some debug outputs and
    forward this Irp to the next level.

Arguments:

    Data -  Pointer to the FDO device extension.
    Irp  -  Pointer to the irp.

Return Value:

    NT status is returned.

--*/

{
    NTSTATUS            status;
    POWER_STATE         powerState;
    POWER_STATE_TYPE    powerType;
    PIO_STACK_LOCATION  stack;

    stack = IoGetCurrentIrpStackLocation (Irp);
    powerType = stack->Parameters.Power.Type;
    powerState = stack->Parameters.Power.State;

    Bus_IncIoCount (Data);

    //
    // If the device is not stated yet, just pass it down.
    //

    if (Data->DevicePnPState == NotStarted) {
        PoStartNextPowerIrp(Irp);
        IoSkipCurrentIrpStackLocation(Irp);
        status = PoCallDriver(Data->NextLowerDriver, Irp);
        Bus_DecIoCount (Data);
        return status;

    }

    if (stack->MinorFunction == IRP_MN_SET_POWER) {
        Bus_KdPrint_Cont(Data, BUS_DBG_POWER_TRACE,
                     ("\tRequest to set %s state to %s\n",
                     ((powerType == SystemPowerState) ?  "System" : "Device"),
                     ((powerType == SystemPowerState) ? \
                        DbgSystemPowerString(powerState.SystemState) :\
                        DbgDevicePowerString(powerState.DeviceState))));
    }

    PoStartNextPowerIrp (Irp);
    IoSkipCurrentIrpStackLocation(Irp);
    status =  PoCallDriver (Data->NextLowerDriver, Irp);
    Bus_DecIoCount (Data);
    return status;
}
Exemplo n.º 8
0
NTSTATUS
Bus_PDO_Power (
    PPDO_DEVICE_DATA    PdoData,
    PIRP                Irp
    )
/*++
    Handles power Irps sent to the PDOs.
    Typically a bus driver, that is not a power
    policy owner for the device, does nothing
    more than starting the next power IRP and
    completing this one.

Arguments:

    PdoData - Pointer to the PDO device extension.
    Irp     - Pointer to the irp.

Return Value:

    NT status is returned.

--*/

{
    NTSTATUS            status;
    PIO_STACK_LOCATION  stack;
    POWER_STATE         powerState;
    POWER_STATE_TYPE    powerType;

    stack = IoGetCurrentIrpStackLocation (Irp);
    powerType = stack->Parameters.Power.Type;
    powerState = stack->Parameters.Power.State;

    switch (stack->MinorFunction) {
    case IRP_MN_SET_POWER:

        Bus_KdPrint_Cont(PdoData, BUS_DBG_POWER_TRACE,
                     ("\tSetting %s power state to %s\n",
                     ((powerType == SystemPowerState) ?  "System" : "Device"),
                     ((powerType == SystemPowerState) ? \
                        DbgSystemPowerString(powerState.SystemState) : \
                        DbgDevicePowerString(powerState.DeviceState))));

        switch (powerType) {
            case DevicePowerState:
                PoSetPowerState (PdoData->Self, powerType, powerState);
                PdoData->DevicePowerState = powerState.DeviceState;
                status = STATUS_SUCCESS;
                break;

            case SystemPowerState:
                PdoData->SystemPowerState = powerState.SystemState;
                status = STATUS_SUCCESS;
                break;

            default:
                status = STATUS_NOT_SUPPORTED;
                break;
        }
        break;

    case IRP_MN_QUERY_POWER:
        status = STATUS_SUCCESS;
        break;

    case IRP_MN_WAIT_WAKE:
        //
        // We cannot support wait-wake because we are root-enumerated
        // driver, and our parent, the PnP manager, doesn't support wait-wake.
        // If you are a bus enumerated device, and if  your parent bus supports
        // wait-wake,  you should send a wait/wake IRP (PoRequestPowerIrp)
        // in response to this request.
        // If you want to test the wait/wake logic implemented in the function
        // driver (toaster.sys), you could do the following simulation:
        // a) Mark this IRP pending.
        // b) Set a cancel routine.
        // c) Save this IRP in the device extension
        // d) Return STATUS_PENDING.
        // Later on if you suspend and resume your system, your BUS_FDO_POWER
        // will be called to power the bus. In response to IRP_MN_SET_POWER, if the
        // powerstate is PowerSystemWorking, complete this Wake IRP.
        // If the function driver, decides to cancel the wake IRP, your cancel routine
        // will be called. There you just complete the IRP with STATUS_CANCELLED.
        //
    case IRP_MN_POWER_SEQUENCE:
    default:
        status = STATUS_NOT_SUPPORTED;
        break;
    }

    if (status != STATUS_NOT_SUPPORTED) {

        Irp->IoStatus.Status = status;
    }

    PoStartNextPowerIrp(Irp);
    status = Irp->IoStatus.Status;
    IoCompleteRequest (Irp, IO_NO_INCREMENT);

    return status;
}
Exemplo n.º 9
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	pBuffer = 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", pBuffer->ucTargetType));
			
			// Check Parameter.
			switch(pBuffer->ucTargetType) 
			{
			case DISK_TYPE_NORMAL: 
			case DISK_TYPE_DVD: 
			case DISK_TYPE_VDVD: 
			case DISK_TYPE_MO:

				ulSize = sizeof(LANSCSI_ADD_TARGET_DATA);
				if(pBuffer->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 != pBuffer->ulNumberOfUnitDiskList)
				{
					ulSize = 0;	// Exit when Check if(ulSize != inlen)...
				}

				break;

			case DISK_TYPE_AGGREGATION:

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

				if (pBuffer->ulNumberOfUnitDiskList < 2 || 
					pBuffer->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) * (pBuffer->ulNumberOfUnitDiskList - 1);
				switch(pBuffer->ulNumberOfUnitDiskList)
				{
				case 2:
				case 4:
				case 8:
					break;
				default: // do not accept
					ulSize = 0;
					break;
				}
				break;
			case DISK_TYPE_BIND_RAID1:

				ulSize = sizeof(LANSCSI_ADD_TARGET_DATA) + 
					sizeof(LSBUS_UNITDISK) * (pBuffer->ulNumberOfUnitDiskList - 1);
				if (pBuffer->ulNumberOfUnitDiskList < 2 || 
					pBuffer->ulNumberOfUnitDiskList > MAX_NR_TC_PER_TARGET) 
				{
					ulSize = 0;	// Exit when Check if(ulSize != inlen)...
				}
				if (pBuffer->ulNumberOfUnitDiskList % 2) 
				{
					// should be the multiples of 2 
					ulSize = 0;	// Exit when Check if(ulSize != inlen)...
				}

				break;
			case DISK_TYPE_BIND_RAID4:
				ulSize = sizeof(LANSCSI_ADD_TARGET_DATA) + sizeof(LSBUS_UNITDISK) * (pBuffer->ulNumberOfUnitDiskList - 1);
				switch(pBuffer->ulNumberOfUnitDiskList)
				{
				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, ("IOCTL_LANSCSI_ADD_TARGET: Bad Disk Type.\n"));
				status = STATUS_UNSUCCESSFUL;
				break;
			}
						
			// Check Size.
			if(ulSize != inlen) 
			{
				Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_LANSCSI_ADD_TARGET: Size mismatch. Req %d, in %d\n", ulSize, inlen));
				status = STATUS_UNSUCCESSFUL;
				break;
			}

			// Find Pdo Data...
			pdoData = LookupPdoData(fdoData, pBuffer->ulSlotNo);
			if(pdoData == NULL) 
			{
				Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR,
					("no pdo\n"));
				status = STATUS_UNSUCCESSFUL;
				break;
			}


/*
			//
			//	redirect to the LanscsiMiniport Device
			//
			status = LSBus_IoctlToLSMPDevice(
					pdoData,
					LANSCSIMINIPORT_IOCTL_ADD_TARGET,
					buffer,
					sizeof(LANSCSI_ADD_TARGET_DATA),
					NULL, 
					0
				);	
*/
			
			pdoData->LanscsiAdapterPDO.AddDevInfo = ExAllocatePool(NonPagedPool, inlen);
			
			if(pdoData->LanscsiAdapterPDO.AddDevInfo == NULL) 
			{
				status = STATUS_INSUFFICIENT_RESOURCES;
			}
			else 
			{
				RtlCopyMemory(pdoData->LanscsiAdapterPDO.AddDevInfo, pBuffer, 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);

			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;

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

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

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

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

		ObDereferenceObject(pdoData->Self);

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

	case IOCTL_LANSCSI_REGISTER_DEVICE:
	{

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

			PLANSCSI_REGISTER_NDASDEV	RegNdasDev = buffer;

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

			status = LSBus_RegisterDevice(fdoData, RegNdasDev);

			Irp->IoStatus.Information = 0;
		}
		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_UNREGISTER_DEVICE:
	{
		Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_LANSCSI_REGISTER_NDASDEVICE inlen %d, outlen %d, sizeof(LANSCSI_ADD_TARGET_DATA) %d\n", inlen, outlen, sizeof(LANSCSI_ADD_TARGET_DATA)));
		if ((inlen == outlen)) {

			PLANSCSI_UNREGISTER_NDASDEV	UnregNdasDev = buffer;

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

			status = LSBus_UnregisterDevice(fdoData, UnregNdasDev);

			Irp->IoStatus.Information = 0;
		}        
		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)));
	}


	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;
			break;
		}

		//
		//	set information
		//	lock the code section of the function to raise IRQL
		//	because the function is PAGED_CODE.
		//
	    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));
		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;
		}


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

	    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;
		} 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_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;
		} 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_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;
				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
    }
Exemplo n.º 10
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	pBuffer = 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", pBuffer->ucTargetType));
			
			// Check Parameter.
			switch(pBuffer->ucTargetType) {
			case DISK_TYPE_NORMAL: 
				case DISK_TYPE_DVD: 
				case DISK_TYPE_VDVD: 
				case DISK_TYPE_MO:
				ulSize = sizeof(LANSCSI_ADD_TARGET_DATA);
					if(pBuffer->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 != pBuffer->ulNumberOfUnitDiskList)
					ulSize = 0;	// Exit when Check if(ulSize != inlen)...

				break;
			case DISK_TYPE_AGGREGATION:
					ulSize = sizeof(LANSCSI_ADD_TARGET_DATA) + sizeof(LSBUS_UNITDISK) * (pBuffer->ulNumberOfUnitDiskList - 1);
					if(pBuffer->ulNumberOfUnitDiskList < 1 || pBuffer->ulNumberOfUnitDiskList > 0xFFFF)
						ulSize = 0;	// Exit when Check if(ulSize != inlen)...
					
					break;
				case DISK_TYPE_BIND_RAID1:
					ulSize = sizeof(LANSCSI_ADD_TARGET_DATA) + sizeof(LSBUS_UNITDISK) * (pBuffer->ulNumberOfUnitDiskList - 1);
					//				if(pBuffer->ulNumberOfUnitDiskList < 1 || pBuffer->ulNumberOfUnitDiskList > MAX_NR_TC_PER_TARGET)
					if(pBuffer->ulNumberOfUnitDiskList < 2 || pBuffer->ulNumberOfUnitDiskList > 0xFFFF)
						ulSize = 0;	// Exit when Check if(ulSize != inlen)...
					if(pBuffer->ulNumberOfUnitDiskList % 2) // should be the multiples of 2
					ulSize = 0;	// Exit when Check if(ulSize != inlen)...

				break;
			default:
				Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_LANSCSI_ADD_TARGET: Bad Disk Type.\n"));
				status = STATUS_UNSUCCESSFUL;
				break;
			}
						
			// Check Size.
			if(ulSize != inlen) {
				Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_LANSCSI_ADD_TARGET: Size mismatch. Req %d, in %d\n", ulSize, inlen));
				status = STATUS_UNSUCCESSFUL;
				break;
			}

			// Find Pdo Data...
			pdoData = LookupPdoData(fdoData, pBuffer->ulSlotNo);
			if(pdoData == NULL) {
				Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR,
					("no pdo\n"));
				status = STATUS_UNSUCCESSFUL;
				break;
			}


/*
			//
			//	redirect to the LanscsiMiniport Device
			//
			status = LSBus_IoctlToLSMPDevice(
					pdoData,
					LANSCSIMINIPORT_IOCTL_ADD_TARGET,
					buffer,
					sizeof(LANSCSI_ADD_TARGET_DATA),
					NULL, 
					0
				);	
*/
			pdoData->LanscsiAdapterPDO.AddTargetData = ExAllocatePool(NonPagedPool, inlen);
			if(pdoData->LanscsiAdapterPDO.AddTargetData == NULL) {
				status = STATUS_INSUFFICIENT_RESOURCES;
			} else {
				RtlCopyMemory(pdoData->LanscsiAdapterPDO.AddTargetData, pBuffer, inlen);
				status = STATUS_SUCCESS;
			}

			//
			//	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);

			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;

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

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

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

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

		ObDereferenceObject(pdoData->Self);

        Irp->IoStatus.Information = outlen;
		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;
			break;
		}

		//
		//	set information
		//	lock the code section of the function to raise IRQL
		//	because the function is PAGED_CODE.
		//
	    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));
		pdoData->LanscsiAdapterPDO.AdapterStatus = SetPdoInfo->AdapterStatus;
		pdoData->LanscsiAdapterPDO.DesiredAccess = SetPdoInfo->DesiredAccess;
		pdoData->LanscsiAdapterPDO.GrantedAccess = SetPdoInfo->GrantedAccess;

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

	    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\n"));
			status = STATUS_NO_SUCH_DEVICE;
		} 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_QUERY_LSMPINFORMATION:
		{
		PPDO_DEVICE_DATA				pdoData;

		Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_LANSCSI_QUERY_LSMPINFORMATION called\n"));
		// Check Parameter.
		if(inlen < sizeof(LSMPIOCTL_QUERYINFO)) {
			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;
		} 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:
		status = STATUS_INVALID_PARAMETER;
        break;
*/
	// inserted by ILGU
	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);
           
            Irp->IoStatus.Information = outlen;

        }
        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;
	// Added by ILGU HONG 2004_07_05
	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;
				break;	
			} else {

				if(pdoData->LanscsiAdapterPDO.AddTargetData->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;
	// Added by ILGU HONG 2004_07_05 end
#if 0	
	case IOCTL_VDVD_GET_VDVD_HD_INFO :
		{
			PGET_VDVD_HD_INFO pHeader = NULL;
			if((inlen == outlen)
				&& (sizeof(GET_VDVD_HD_INFO) <= inlen))
			{
				XXprint(4,("Called IOCTL_VDVD_GET_VDVD_HD_INFO\n"));
				pHeader = (PGET_VDVD_HD_INFO)buffer;
				switch(pHeader->COM){
				case COM_GET_VDVD_COUNT	:
					{
						if(inlen != sizeof(GET_VDVD_HD_INFO)){
							Irp->IoStatus.Information = outlen;
							status = STATUS_UNSUCCESSFUL;
							break;
						}
						pHeader->COUNT = FindVDVDPdoCount(fdoData);
						XXprint(4,("COM_GET_VDVD_COUNT %d\n",pHeader->COUNT));
						Irp->IoStatus.Information = outlen;
						status = STATUS_SUCCESS;
					}
					break;
				case COM_GET_VDVD_HD_INFO :
					{
						PPDO_DEVICE_DATA	pdoData;
						PDISC_HEADER		pDiscHeader = NULL;
						if(inlen != sizeof(GET_VDVD_HD_INFO)){
							Irp->IoStatus.Information = outlen;
							status = STATUS_UNSUCCESSFUL;
							break;
						}
						pdoData = FindPdoData(fdoData, pHeader->SlotNo);
						if(pdoData == NULL) {
							XXprint(4,("COM_GET_VDVD_HD_INFO : Can't find pdo\n"));
							status = STATUS_UNSUCCESSFUL;
							break;
						}
						pDiscHeader = pdoData->LanscsiAdapter.LogicalTarget[0].Llu[0].Targets[0].TargetConnectionList.pHeader;
						pHeader->DISC[0].DISCS = pDiscHeader->DISCS;
						pHeader->DISC[0].ENABLE_DISCS = pDiscHeader->ENABLE_DISCS;
						pHeader->DISC[0].SlotNo = pHeader->SlotNo;
						XXprint(4,("COM_GET_VDVD_HD_INFO : #of DISC(%d), #of ENABLED(%d), SlotNo(%d)\n",
							pHeader->DISC[0].DISCS,pHeader->DISC[0].ENABLE_DISCS, pHeader->DISC[0].SlotNo));
						Irp->IoStatus.Information = outlen;
						status = STATUS_SUCCESS;
					}
					break;
				case COM_GET_VDVD_HD_INFO_ALL:
					{
						
						int size = sizeof(GET_VDVD_HD_INFO) + (sizeof(VDVD_DISC_HD)*(pHeader->COUNT-1));
						if(inlen != size){
							Irp->IoStatus.Information = outlen;
							status = STATUS_UNSUCCESSFUL;
							break;
						}
						FindVDVDPdoInfo(fdoData,pHeader);
						Irp->IoStatus.Information = outlen;
						status = STATUS_SUCCESS;
					}
					break;
				default:
					Irp->IoStatus.Information = outlen;
					status = STATUS_UNSUCCESSFUL;
					break;
					
				}
			}
			else{
				Irp->IoStatus.Information = outlen;
				status = STATUS_UNSUCCESSFUL;
			}
		}
		break;
	case IOCTL_VDVD_GET_VDVD_DISC_INFO:
		{
			XXprint(4,("Called IOCTL_VDVD_GET_VDVD_DISC_INFO START\n"));
			if((inlen == outlen)
				&& (sizeof(GET_VDVD_DISC_INFO) <= inlen))
			{
				PGET_VDVD_DISC_INFO		pDiscInfo = (PGET_VDVD_DISC_INFO)buffer;
				PTARGET_CONNECTION		TargetConnection;
				XXprint(4,("Called IOCTL_VDVD_GET_VDVD_DISC_INFO\n"));
				
				switch(pDiscInfo->COM)
				{
				case COM_GET_VDVD_DISC_INFO :
					{
						PPDO_DEVICE_DATA	pdoData;
						PJUKE_DISC		pInfo = NULL;						
						
						if(inlen != sizeof(GET_VDVD_DISC_INFO))
						{
							Irp->IoStatus.Information = outlen;
							status = STATUS_UNSUCCESSFUL;
							break;
						}
						pdoData = FindPdoData(fdoData, pDiscInfo->SlotNo);
						if(pdoData == NULL) {
							XXprint(4,("COM_GET_VDVD_DISC_INFO : Can't find pdo\n"));
							status = STATUS_UNSUCCESSFUL;
							break;
						}
						TargetConnection = &(pdoData->LanscsiAdapter.LogicalTarget[0].Llu[0].Targets[0].TargetConnectionList);
						if(pDiscInfo->DiscNo >= TargetConnection->pHeader->DISCS )
						{
							XXprint(4,("COM_GET_VDVD_DISC_INFO : DISC nub is too big!!\n"));
							status = STATUS_UNSUCCESSFUL;
							break;	
						}
						pInfo = &(TargetConnection->pInfos[pDiscInfo->DiscNo]);
						pDiscInfo->DISC[0].LOCATION = pInfo->LOCATION;
						pDiscInfo->DISC[0].START_SEC = pInfo->START_SEC;
						pDiscInfo->DISC[0].NR_SEC = pInfo->NR_SEC;
						pDiscInfo->DISC[0].ENABLED = pInfo->ENABLED;
						Irp->IoStatus.Information = outlen;
						XXprint(4,("COM_GET_VDVD_DISC_INFO : LOCATION(0x%I64x), START_SEC(0x%I64x), ENABLED(%d)\n",
							pDiscInfo->DISC[0].LOCATION, pDiscInfo->DISC[0].START_SEC, pDiscInfo->DISC[0].ENABLED));
						status = STATUS_SUCCESS;						
					}
					break;
				case COM_VDVD_DISC_INFO_ALL:
					{
						PPDO_DEVICE_DATA	pdoData;
						PJUKE_DISC		pInfo = NULL;						
						ULONG			size = sizeof(GET_VDVD_DISC_INFO) + (sizeof(DISC_INFO) * (pDiscInfo->COUNT - 1));
						int				i = 0;
						int				max = 0;
						if(inlen != size)
						{
							Irp->IoStatus.Information = outlen;
							status = STATUS_UNSUCCESSFUL;
							break;
						}
						pdoData = FindPdoData(fdoData, pDiscInfo->SlotNo);
						if(pdoData == NULL) {
							XXprint(4,("COM_VDVD_DISC_INFO_ALL : Can't find pdo\n"));
							status = STATUS_UNSUCCESSFUL;
							break;
						}
						TargetConnection = &(pdoData->LanscsiAdapter.LogicalTarget[0].Llu[0].Targets[0].TargetConnectionList);
						if(pDiscInfo->COUNT > TargetConnection->pHeader->DISCS)
						{
							pDiscInfo->COUNT = TargetConnection->pHeader->DISCS;
						}
						max = pDiscInfo->COUNT;
						for(i = 0; i< max; i++){
							pInfo = &(TargetConnection->pInfos[i]);
							pDiscInfo->DISC[i].LOCATION = pInfo->LOCATION;
							pDiscInfo->DISC[i].START_SEC = pInfo->START_SEC;
							pDiscInfo->DISC[i].NR_SEC = pInfo->NR_SEC;
							pDiscInfo->DISC[i].ENABLED = pInfo->ENABLED;
							XXprint(4,("COM_VDVD_DISC_INFO_ALL(%d) : LOCATION(0x%I64x), START_SEC(0x%I64x), ENABLED(%d)\n",
								i,pDiscInfo->DISC[i].LOCATION, pDiscInfo->DISC[i].START_SEC, pDiscInfo->DISC[i].ENABLED));
							
						}
						Irp->IoStatus.Information = outlen;
						status = STATUS_SUCCESS;												
					}
					break;
				default:
					Irp->IoStatus.Information = outlen;
					status = STATUS_UNSUCCESSFUL;
					break;
				}
			}else{
				Irp->IoStatus.Information = outlen;
				status = STATUS_UNSUCCESSFUL;
			}
		}
		break;
	case IOCTL_VDVD_SET_VDVD_BURN:
		{
			if((inlen == outlen)
				&& (sizeof(SET_DVD_DISC_BURN) == inlen))
			{
				XXprint(4,("IOCTL_VDVD_SET_VDVD_BURN\n"));
				Irp->IoStatus.Information = outlen;
				status = STATUS_SUCCESS;
			}else{
				Irp->IoStatus.Information = outlen;
				status = STATUS_UNSUCCESSFUL;
			}
		}
		break;
	case IOCTL_VDVD_CHANGE_VDVD_DISC:
		{
			PCHANGE_VDVD_DISC pChange = (PCHANGE_VDVD_DISC)buffer;
			if((inlen == outlen)
				&& (sizeof(CHANGE_VDVD_DISC) == inlen))
			{
				XXprint(4,("IOCTL_VDVD_CHANGE_VDVD_DISC\n"));
				switch(pChange->COM)
				{
				case COM_GET_CUR_DISC :
					{
						PPDO_DEVICE_DATA	pdoData;
						
						pdoData = FindPdoData(fdoData, pChange->SlotNo);
						if(pdoData == NULL) {
							XXprint(4,("COM_GET_CUR_DISC : Can't find pdo\n"));
							status = STATUS_UNSUCCESSFUL;
							break;
						}
						KeEnterCriticalRegion();
						pChange->DiscNo = pdoData->LanscsiAdapter.LogicalTarget[0].Llu[0].Targets[0].TargetConnectionList.cur_disc;
						Irp->IoStatus.Information = outlen;
						KeLeaveCriticalRegion();
						status = STATUS_SUCCESS;
					}
					break;
				case COM_SET_CUR_DISC :
					{
						PPDO_DEVICE_DATA	pdoData;
						PTARGET_CONNECTION	TargetConnection;
						pdoData = FindPdoData(fdoData, pChange->SlotNo);
						if(pdoData == NULL) {
							XXprint(4,("COM_GET_CUR_DISC : Can't find pdo\n"));
							status = STATUS_UNSUCCESSFUL;
							break;
						}
						KeEnterCriticalRegion();
						TargetConnection =&(pdoData->LanscsiAdapter.LogicalTarget[0].Llu[0].Targets[0].TargetConnectionList); 
						if(pChange->DiscNo >= TargetConnection->pHeader->DISCS)
						{
							Irp->IoStatus.Information = outlen;
							status = STATUS_UNSUCCESSFUL;
							KeLeaveCriticalRegion();
							break;
						}
						TargetConnection->cur_disc = pChange->DiscNo;
						TargetConnection->IsChanging = TRUE;
						TargetConnection->CHCount = 0;
						Irp->IoStatus.Information = outlen;
						status = STATUS_SUCCESS;
						KeLeaveCriticalRegion();
					}
					break;
				default:
					Irp->IoStatus.Information = outlen;
					status = STATUS_UNSUCCESSFUL;
				}
			}else{
				Irp->IoStatus.Information = outlen;
				status = STATUS_UNSUCCESSFUL;
			}
		}
		break;
#endif // 0 - VDVD	
    default:
        break; // default status is STATUS_INVALID_PARAMETER
    }

	Irp->IoStatus.Status = status;
	if(Irp->UserIosb)
		*Irp->UserIosb = Irp->IoStatus;

	IoCompleteRequest (Irp, IO_NO_INCREMENT);
    Bus_DecIoCount (fdoData);
    return status;
}
Exemplo n.º 11
0
NTSTATUS
Bus_PDO_QueryDeviceText(
    __in PPDO_DEVICE_DATA     DeviceData,
    __in  PIRP   Irp )
/*++

Routine Description:

    The PnP Manager uses this IRP to get a device's
    description or location information. This string
    is displayed in the "found new hardware" pop-up
    window if no INF match is found for the device.
    Bus drivers are also encouraged to return location
    information for their child devices, but this information
    is optional.

Arguments:

    DeviceData - Pointer to the PDO's device extension.
    Irp          - Pointer to the irp.

Return Value:

    NT STATUS

--*/
{
    PWCHAR  buffer;
    USHORT  length;
    PIO_STACK_LOCATION   stack;
    NTSTATUS    status;

    PAGED_CODE ();

    stack = IoGetCurrentIrpStackLocation (Irp);

    switch (stack->Parameters.QueryDeviceText.DeviceTextType) {

    case DeviceTextDescription:

        //
        // Check to see if any filter driver has set any information.
        // If so then remain silent otherwise add your description.
        // This string must be localized to support various languages.
        //

        switch (stack->Parameters.QueryDeviceText.LocaleId) {

        case 0x00000407 : // German
              // Localize the device text.
              // Until we implement let us fallthru to English

        default: // for all other languages, fallthru to English
        case 0x00000409 : // English
            if (!Irp->IoStatus.Information) {
                // 10 for number of digits in the serial number
                length  = (USHORT) \
                (wcslen(VENDORNAME) + 1 + wcslen(MODEL) + 1 + 10) * sizeof(WCHAR);
                buffer = ExAllocatePoolWithTag (PagedPool,
                                            length, BUSENUM_POOL_TAG);
                if (buffer == NULL ) {
                    status = STATUS_INSUFFICIENT_RESOURCES;
                    break;
                }

                RtlStringCchPrintfW(buffer, length/sizeof(WCHAR), L"%ws%ws%02d", VENDORNAME, MODEL,
                                            DeviceData->SerialNo);
                Bus_KdPrint_Cont (DeviceData, BUS_DBG_PNP_TRACE,
                    ("\tDeviceTextDescription :%ws\n", buffer));

                Irp->IoStatus.Information = (ULONG_PTR) buffer;
            }
            status = STATUS_SUCCESS;
            break;
        } // end of LocalID switch
        break;

    case DeviceTextLocationInformation:

        Bus_KdPrint_Cont (DeviceData, BUS_DBG_PNP_TRACE,
            ("\tDeviceTextLocationInformation: Unknown\n"));

    default:
        status = Irp->IoStatus.Status;
        break;
    }

    return status;

}
Exemplo n.º 12
0
NTSTATUS
Bus_PDO_QueryDeviceId(
    __in PPDO_DEVICE_DATA     DeviceData,
    __in  PIRP   Irp )
/*++

Routine Description:

    Bus drivers must handle BusQueryDeviceID requests for their
    child devices (child PDOs). Bus drivers can handle requests
    BusQueryHardwareIDs, BusQueryCompatibleIDs, and BusQueryInstanceID
    for their child devices.

    When returning more than one ID for hardware IDs or compatible IDs,
    a driver should list the IDs in the order of most specific to most
    general to facilitate choosing the best driver match for the device.

    Bus drivers should be prepared to handle this IRP for a child device
    immediately after the device is enumerated.


Arguments:

    DeviceData - Pointer to the PDO's device extension.
    Irp          - Pointer to the irp.

Return Value:

    NT STATUS

--*/
{
    PIO_STACK_LOCATION      stack;
    PWCHAR                  buffer;
    ULONG                   length;
    NTSTATUS                status = STATUS_SUCCESS;
    ULONG_PTR               result;

    PAGED_CODE ();

    stack = IoGetCurrentIrpStackLocation (Irp);

    switch (stack->Parameters.QueryId.IdType) {

    case BusQueryDeviceID:

        //
        // DeviceID is unique string to identify a device.
        // This can be the same as the hardware ids (which requires a multi
        // sz).
        //

        buffer = DeviceData->HardwareIDs;

        while (*(buffer++)) {
            while (*(buffer++)) {
                ;
            }
        }

        status = RtlULongPtrSub((ULONG_PTR)buffer, (ULONG_PTR)DeviceData->HardwareIDs, &result);
        if (!NT_SUCCESS(status)) {
           break;
        }


        length = (ULONG)result;

        buffer = ExAllocatePoolWithTag (PagedPool, length, BUSENUM_POOL_TAG);

        if (!buffer) {
           status = STATUS_INSUFFICIENT_RESOURCES;
           break;
        }

        RtlCopyMemory (buffer, DeviceData->HardwareIDs, length);
        Irp->IoStatus.Information = (ULONG_PTR) buffer;
        break;

    case BusQueryInstanceID:
        //
        // total length = number (10 digits to be safe (2^32)) + null wide char
        //
        length = 11 * sizeof(WCHAR);

        buffer = ExAllocatePoolWithTag (PagedPool, length, BUSENUM_POOL_TAG);
        if (!buffer) {
           status = STATUS_INSUFFICIENT_RESOURCES;
           break;
        }
        RtlStringCchPrintfW(buffer, length/sizeof(WCHAR), L"%02d", DeviceData->SerialNo);
        Bus_KdPrint_Cont (DeviceData, BUS_DBG_PNP_INFO,
                     ("\tInstanceID: %ws\n", buffer));
        Irp->IoStatus.Information = (ULONG_PTR) buffer;
        break;


    case BusQueryHardwareIDs:

        //
        // A device has at least one hardware id.
        // In a list of hardware IDs (multi_sz string) for a device,
        // DeviceId is the most specific and should be first in the list.
        //

        buffer = DeviceData->HardwareIDs;

        while (*(buffer++)) {
            while (*(buffer++)) {
                ;
            }
        }

        status = RtlULongPtrSub((ULONG_PTR)buffer, (ULONG_PTR)DeviceData->HardwareIDs, &result);
        if (!NT_SUCCESS(status)) {
           break;
        }

        length = (ULONG)result;

        buffer = ExAllocatePoolWithTag (PagedPool, length, BUSENUM_POOL_TAG);
        if (!buffer) {
           status = STATUS_INSUFFICIENT_RESOURCES;
           break;
        }

        RtlCopyMemory (buffer, DeviceData->HardwareIDs, length);
        Irp->IoStatus.Information = (ULONG_PTR) buffer;
        break;


    case BusQueryCompatibleIDs:

        //
        // The generic ids for installation of this pdo.
        //

        length = BUSENUM_COMPATIBLE_IDS_LENGTH;
        buffer = ExAllocatePoolWithTag (PagedPool, length, BUSENUM_POOL_TAG);
        if (!buffer) {
           status = STATUS_INSUFFICIENT_RESOURCES;
           break;
        }
        RtlCopyMemory (buffer, BUSENUM_COMPATIBLE_IDS, length);
        Irp->IoStatus.Information = (ULONG_PTR) buffer;
        break;

    default:

        status = Irp->IoStatus.Status;

    }
    return status;

}
Exemplo n.º 13
0
NTSTATUS
Bus_PDO_PnP (
    __in PDEVICE_OBJECT       DeviceObject,
    __in PIRP                 Irp,
    __in PIO_STACK_LOCATION   IrpStack,
    __in PPDO_DEVICE_DATA     DeviceData
    )
/*++
Routine Description:
    Handle requests from the Plug & Play system for the devices on the BUS

--*/
{
    NTSTATUS                status;

    PAGED_CODE ();


    //
    // NB: Because we are a bus enumerator, we have no one to whom we could
    // defer these irps.  Therefore we do not pass them down but merely
    // return them.
    //

    switch (IrpStack->MinorFunction) {

    case IRP_MN_START_DEVICE:

        //
        // Here we do what ever initialization and ``turning on'' that is
        // required to allow others to access this device.
        // Power up the device.
        //
        DeviceData->DevicePowerState = PowerDeviceD0;
        SET_NEW_PNP_STATE(DeviceData, Started);
        status = STATUS_SUCCESS;
        break;

    case IRP_MN_STOP_DEVICE:

        //
        // Here we shut down the device and give up and unmap any resources
        // we acquired for the device.
        //

        SET_NEW_PNP_STATE(DeviceData, Stopped);
        status = STATUS_SUCCESS;
        break;


    case IRP_MN_QUERY_STOP_DEVICE:

        //
        // No reason here why we can't stop the device.
        // If there were a reason we should speak now, because answering success
        // here may result in a stop device irp.
        //

        SET_NEW_PNP_STATE(DeviceData, StopPending);
        status = STATUS_SUCCESS;
        break;

    case IRP_MN_CANCEL_STOP_DEVICE:

        //
        // The stop was canceled.  Whatever state we set, or resources we put
        // on hold in anticipation of the forthcoming STOP device IRP should be
        // put back to normal.  Someone, in the long list of concerned parties,
        // has failed the stop device query.
        //

        //
        // First check to see whether you have received cancel-stop
        // without first receiving a query-stop. This could happen if someone
        // above us fails a query-stop and passes down the subsequent
        // cancel-stop.
        //

        if (StopPending == DeviceData->DevicePnPState)
        {
            //
            // We did receive a query-stop, so restore.
            //
            RESTORE_PREVIOUS_PNP_STATE(DeviceData);
        }
        status = STATUS_SUCCESS;// We must not fail this IRP.
        break;

    case IRP_MN_QUERY_REMOVE_DEVICE:

        //
        // Check to see whether the device can be removed safely.
        // If not fail this request. This is the last opportunity
        // to do so.
        //
        if (DeviceData->ToasterInterfaceRefCount){
            //
            // Somebody is still using our interface.
            // We must fail remove.
            //
            status = STATUS_UNSUCCESSFUL;
            break;
        }

        SET_NEW_PNP_STATE(DeviceData, RemovePending);
        status = STATUS_SUCCESS;
        break;

    case IRP_MN_CANCEL_REMOVE_DEVICE:

        //
        // Clean up a remove that did not go through.
        //

        //
        // First check to see whether you have received cancel-remove
        // without first receiving a query-remove. This could happen if
        // someone above us fails a query-remove and passes down the
        // subsequent cancel-remove.
        //

        if (RemovePending == DeviceData->DevicePnPState)
        {
            //
            // We did receive a query-remove, so restore.
            //
            RESTORE_PREVIOUS_PNP_STATE(DeviceData);
        }
        status = STATUS_SUCCESS; // We must not fail this IRP.
        break;

    case IRP_MN_SURPRISE_REMOVAL:

        //
        // We should stop all access to the device and relinquish all the
        // resources. Let's just mark that it happened and we will do
        // the cleanup later in IRP_MN_REMOVE_DEVICE.
        //

        SET_NEW_PNP_STATE(DeviceData, SurpriseRemovePending);
        status = STATUS_SUCCESS;
        break;

    case IRP_MN_REMOVE_DEVICE:

        //
        // Present is set to true when the pdo is exposed via PlugIn IOCTL.
        // It is set to FALSE when a UnPlug IOCTL is received.
        // We will delete the PDO only after we have reported to the
        // Plug and Play manager that it's missing.
        //

        if (DeviceData->ReportedMissing) {
            PFDO_DEVICE_DATA fdoData;

            SET_NEW_PNP_STATE(DeviceData, Deleted);

            //
            // Remove the PDO from the list and decrement the count of PDO.
            // Don't forget to synchronize access to the FDO data.
            // If the parent FDO is deleted before child PDOs, the ParentFdo
            // pointer will be NULL. This could happen if the child PDO
            // is in a SurpriseRemovePending state when the parent FDO
            // is removed.
            //

            if (DeviceData->ParentFdo) {
                fdoData = FDO_FROM_PDO(DeviceData);
                ExAcquireFastMutex (&fdoData->Mutex);
                RemoveEntryList (&DeviceData->Link);
                fdoData->NumPDOs--;
                ExReleaseFastMutex (&fdoData->Mutex);
            }
            //
            // Free up resources associated with PDO and delete it.
            //
            status = Bus_DestroyPdo(DeviceObject, DeviceData);
            break;

        }
        if (DeviceData->Present) {
            //
            // When the device is disabled, the PDO transitions from
            // RemovePending to NotStarted. We shouldn't delete
            // the PDO because a) the device is still present on the bus,
            // b) we haven't reported missing to the PnP manager.
            //

            SET_NEW_PNP_STATE(DeviceData, NotStarted);
            status = STATUS_SUCCESS;
        } else {
            ASSERT(DeviceData->Present);
            status = STATUS_SUCCESS;
        }
        break;

    case IRP_MN_QUERY_CAPABILITIES:

        //
        // Return the capabilities of a device, such as whether the device
        // can be locked or ejected..etc
        //

        status = Bus_PDO_QueryDeviceCaps(DeviceData, Irp);

        break;

    case IRP_MN_QUERY_ID:

        // Query the IDs of the device

        Bus_KdPrint_Cont (DeviceData, BUS_DBG_PNP_TRACE,
                ("\tQueryId Type: %s\n",
                DbgDeviceIDString(IrpStack->Parameters.QueryId.IdType)));

        status = Bus_PDO_QueryDeviceId(DeviceData, Irp);

        break;

    case IRP_MN_QUERY_DEVICE_RELATIONS:

        Bus_KdPrint_Cont (DeviceData, BUS_DBG_PNP_TRACE,
            ("\tQueryDeviceRelation Type: %s\n",DbgDeviceRelationString(\
                    IrpStack->Parameters.QueryDeviceRelations.Type)));

        status = Bus_PDO_QueryDeviceRelations(DeviceData, Irp);

        break;

    case IRP_MN_QUERY_DEVICE_TEXT:

        status = Bus_PDO_QueryDeviceText(DeviceData, Irp);

        break;

    case IRP_MN_QUERY_RESOURCES:

        status = Bus_PDO_QueryResources(DeviceData, Irp);

        break;

    case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:

        status = Bus_PDO_QueryResourceRequirements(DeviceData, Irp);

        break;

    case IRP_MN_QUERY_BUS_INFORMATION:

        status = Bus_PDO_QueryBusInformation(DeviceData, Irp);

        break;

    case IRP_MN_DEVICE_USAGE_NOTIFICATION:

        //
        // OPTIONAL for bus drivers.
        // This bus drivers any of the bus's descendants
        // (child device, child of a child device, etc.) do not
        // contain a memory file namely paging file, dump file,
        // or hibernation file. So we  fail this Irp.
        //

        status = STATUS_UNSUCCESSFUL;
        break;

    case IRP_MN_EJECT:

        //
        // For the device to be ejected, the device must be in the D3
        // device power state (off) and must be unlocked
        // (if the device supports locking). Any driver that returns success
        // for this IRP must wait until the device has been ejected before
        // completing the IRP.
        //
        DeviceData->Present = FALSE;

        status = STATUS_SUCCESS;
        break;

    case IRP_MN_QUERY_INTERFACE:
        //
        // This request enables a driver to export a direct-call
        // interface to other drivers. A bus driver that exports
        // an interface must handle this request for its child
        // devices (child PDOs).
        //
        status = Bus_PDO_QueryInterface(DeviceData, Irp);
        break;

    case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:

        //
        // OPTIONAL for bus drivers.
        // The PnP Manager sends this IRP to a device
        // stack so filter and function drivers can adjust the
        // resources required by the device, if appropriate.
        //

        //break;

    //case IRP_MN_QUERY_PNP_DEVICE_STATE:

        //
        // OPTIONAL for bus drivers.
        // The PnP Manager sends this IRP after the drivers for
        // a device return success from the IRP_MN_START_DEVICE
        // request. The PnP Manager also sends this IRP when a
        // driver for the device calls IoInvalidateDeviceState.
        //

        // break;

    //case IRP_MN_READ_CONFIG:
    //case IRP_MN_WRITE_CONFIG:

        //
        // Bus drivers for buses with configuration space must handle
        // this request for their child devices. Our devices don't
        // have a config space.
        //

        // break;

    //case IRP_MN_SET_LOCK:

        //
        // Our device is not a lockable device
        // so we don't support this Irp.
        //

        // break;

    default:

        //
        //Bus_KdPrint_Cont (DeviceData, BUS_DBG_PNP_TRACE,("\t Not handled\n"));
        // For PnP requests to the PDO that we do not understand we should
        // return the IRP WITHOUT setting the status or information fields.
        // These fields may have already been set by a filter (eg acpi).
        status = Irp->IoStatus.Status;

        break;
    }

    Irp->IoStatus.Status = status;
    IoCompleteRequest (Irp, IO_NO_INCREMENT);

    return status;
}
Exemplo n.º 14
0
NTSTATUS
Bus_PDO_QueryDeviceCaps(
    __in PPDO_DEVICE_DATA     DeviceData,
    __in  PIRP   Irp )
/*++

Routine Description:

    When a device is enumerated, but before the function and
    filter drivers are loaded for the device, the PnP Manager
    sends an IRP_MN_QUERY_CAPABILITIES request to the parent
    bus driver for the device. The bus driver must set any
    relevant values in the DEVICE_CAPABILITIES structure and
    return it to the PnP Manager.

Arguments:

    DeviceData - Pointer to the PDO's device extension.
    Irp          - Pointer to the irp.

Return Value:

    NT STATUS

--*/
{

    PIO_STACK_LOCATION      stack;
    PDEVICE_CAPABILITIES    deviceCapabilities;
    DEVICE_CAPABILITIES     parentCapabilities;
    NTSTATUS                status;

    PAGED_CODE ();

    stack = IoGetCurrentIrpStackLocation (Irp);

    //
    // Get the packet.
    //
    deviceCapabilities=stack->Parameters.DeviceCapabilities.Capabilities;

    //
    // Set the capabilities.
    //

    if (deviceCapabilities->Version != 1 ||
            deviceCapabilities->Size < sizeof(DEVICE_CAPABILITIES))
    {
       return STATUS_UNSUCCESSFUL;
    }

    //
    // Get the device capabilities of the parent
    //
    status = Bus_GetDeviceCapabilities(
        FDO_FROM_PDO(DeviceData)->NextLowerDriver, &parentCapabilities);
    if (!NT_SUCCESS(status)) {

        Bus_KdPrint_Cont (DeviceData, BUS_DBG_PNP_TRACE,
            ("\tQueryDeviceCaps failed\n"));
        return status;

    }

    //
    // The entries in the DeviceState array are based on the capabilities
    // of the parent devnode. These entries signify the highest-powered
    // state that the device can support for the corresponding system
    // state. A driver can specify a lower (less-powered) state than the
    // bus driver.  For eg: Suppose the toaster bus controller supports
    // D0, D2, and D3; and the Toaster Device supports D0, D1, D2, and D3.
    // Following the above rule, the device cannot specify D1 as one of
    // it's power state. A driver can make the rules more restrictive
    // but cannot loosen them.
    // First copy the parent's S to D state mapping
    //

    RtlCopyMemory(
        deviceCapabilities->DeviceState,
        parentCapabilities.DeviceState,
        (PowerSystemShutdown + 1) * sizeof(DEVICE_POWER_STATE)
        );

    //
    // Adjust the caps to what your device supports.
    // Our device just supports D0 and D3.
    //

    deviceCapabilities->DeviceState[PowerSystemWorking] = PowerDeviceD0;

    if (deviceCapabilities->DeviceState[PowerSystemSleeping1] != PowerDeviceD0)
        deviceCapabilities->DeviceState[PowerSystemSleeping1] = PowerDeviceD1;

    if (deviceCapabilities->DeviceState[PowerSystemSleeping2] != PowerDeviceD0)
        deviceCapabilities->DeviceState[PowerSystemSleeping2] = PowerDeviceD3;

    if (deviceCapabilities->DeviceState[PowerSystemSleeping3] != PowerDeviceD0)
        deviceCapabilities->DeviceState[PowerSystemSleeping3] = PowerDeviceD3;

    // We can wake the system from D1
    deviceCapabilities->DeviceWake = PowerDeviceD1;

    //
    // Specifies whether the device hardware supports the D1 and D2
    // power state. Set these bits explicitly.
    //

    deviceCapabilities->DeviceD1 = TRUE; // Yes we can
    deviceCapabilities->DeviceD2 = FALSE;

    //
    // Specifies whether the device can respond to an external wake
    // signal while in the D0, D1, D2, and D3 state.
    // Set these bits explicitly.
    //

    deviceCapabilities->WakeFromD0 = FALSE;
    deviceCapabilities->WakeFromD1 = TRUE; //Yes we can
    deviceCapabilities->WakeFromD2 = FALSE;
    deviceCapabilities->WakeFromD3 = FALSE;


    // We have no latencies

    deviceCapabilities->D1Latency = 0;
    deviceCapabilities->D2Latency = 0;
    deviceCapabilities->D3Latency = 0;

    // Ejection supported

    deviceCapabilities->EjectSupported = TRUE;

    //
    // This flag specifies whether the device's hardware is disabled.
    // The PnP Manager only checks this bit right after the device is
    // enumerated. Once the device is started, this bit is ignored.
    //
    deviceCapabilities->HardwareDisabled = FALSE;

    //
    // Out simulated device can be physically removed.
    //
    deviceCapabilities->Removable = TRUE;
    //
    // Setting it to TURE prevents the warning dialog from appearing
    // whenever the device is surprise removed.
    //
    deviceCapabilities->SurpriseRemovalOK = TRUE;

    // We don't support system-wide unique IDs.

    deviceCapabilities->UniqueID = FALSE;

    //
    // Specify whether the Device Manager should suppress all
    // installation pop-ups except required pop-ups such as
    // "no compatible drivers found."
    //

    deviceCapabilities->SilentInstall = FALSE;

    //
    // Specifies an address indicating where the device is located
    // on its underlying bus. The interpretation of this number is
    // bus-specific. If the address is unknown or the bus driver
    // does not support an address, the bus driver leaves this
    // member at its default value of 0xFFFFFFFF. In this example
    // the location address is same as instance id.
    //

    deviceCapabilities->Address = DeviceData->SerialNo;

    //
    // UINumber specifies a number associated with the device that can
    // be displayed in the user interface.
    //
    deviceCapabilities->UINumber = DeviceData->SerialNo;

    return STATUS_SUCCESS;

}
Exemplo n.º 15
0
NTSTATUS
Bus_PDO_QueryInterface(
    IN PPDO_DEVICE_DATA     DeviceData,
    IN  PIRP   Irp )
/*++

Routine Description:

    This requests enables a driver to export proprietary interface
    to other drivers. This function and the following 5 routines 
    are meant to show how a typical interface is exported. 
    Note: This and many other routines in this sample are not required if 
    someone is using this sample for just device enumeration purpose.
Arguments:

    DeviceData - Pointer to the PDO's device extension.
    Irp          - Pointer to the irp.

Return Value:

    NT STATUS

--*/
{
	PIO_STACK_LOCATION irpStack;
	PTOASTER_INTERFACE_STANDARD toasterInterfaceStandard;
	GUID *interfaceType;
	NTSTATUS    status = STATUS_SUCCESS;
	
	PAGED_CODE();
	
	Bus_KdPrint_Cont (DeviceData, BUS_DBG_PNP_INFO, 
		("Entered\n"));
	
	irpStack = IoGetCurrentIrpStackLocation(Irp);
	interfaceType = (GUID *) irpStack->Parameters.QueryInterface.InterfaceType;
	
	if (IsEqualGUID(interfaceType, (PVOID) &GUID_LANSCSI_INTERFACE_STANDARD)) {
		
		if (irpStack->Parameters.QueryInterface.Size < 
			sizeof(TOASTER_INTERFACE_STANDARD)
			&& irpStack->Parameters.QueryInterface.Version != 1) {
			return STATUS_INVALID_PARAMETER;
		}
		
		toasterInterfaceStandard = (PTOASTER_INTERFACE_STANDARD) 
			irpStack->Parameters.QueryInterface.Interface;
		
		toasterInterfaceStandard->Context = DeviceData;
		//
		// Fill in the exported functions
		//
		toasterInterfaceStandard->InterfaceReference   = 
			(PINTERFACE_REFERENCE) Bus_InterfaceReference;
		toasterInterfaceStandard->InterfaceDereference = 
			(PINTERFACE_DEREFERENCE) Bus_InterfaceDereference;
		toasterInterfaceStandard->GetCrispinessLevel   = Bus_GetCrispinessLevel;
		toasterInterfaceStandard->SetCrispinessLevel   = Bus_SetCrispinessLevel;
		toasterInterfaceStandard->IsSafetyLockEnabled = Bus_IsSafetyLockEnabled;
		
		//
		// Must take a reference before returning
		//
		Bus_InterfaceReference(DeviceData);
	} else {
		//
		// Interface type not supported
		//
		status = Irp->IoStatus.Status;
	}

	return status;
}