www.pudn.com > driver.zip > PnPManagement.c


/****************************************************************************** 
 * * File Name: 
 * *      PlugPlay.c 
 * * Description: 
 * *      Plug 'n' Play handler functions 
 * * Revision History: 
 * *      10-11-07 : Silicon Image 1.00 
 *******************************************************************************/ 
 
#define INITGUID			// Initialize WDMIO_GUID in this module 
#include "Sil3124.h" 
#include "GUIDs.h" 
#pragma code_seg("PAGE")	// start PAGE section 
 
/****************************************************************************** 
 * 
 * Function   :  AddDevice 
 * 
 * Description:  Add a new functional device object for a physical one 
 * 
 ******************************************************************************/ 
NTSTATUS AddDevice(IN PDRIVER_OBJECT pDriverObject, 
				   IN PDEVICE_OBJECT pdo) 
{													// AddDevice 
	NTSTATUS			status; 
	POWER_STATE         state; 
	PDEVICE_OBJECT		fdo; 
	PDEVICE_EXTENSION	pdx; 
 
	DebugPrint("AddDevice Start...............Version:1.0.0"); 
 
    //Create a functional device object to represent the hardware we're managing. 
	//Create Device 
	status = IoCreateDevice(pDriverObject, sizeof(DEVICE_EXTENSION), NULL, 
				FILE_DEVICE_UNKNOWN, 0, FALSE, &fdo);	//DeviceCharacteristics be setted 0 
   
 
	if (!NT_SUCCESS(status)) 
	{						// can't create device object 
	     
		DebugPrint("Sil3124 IoCreateDevice failed %x\n",status); 
		return(status); 
	}						// can't create device object 
	 
    pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension; 
 
	// From this point forward, any error will have side effects that need to 
	// be cleaned up. Using a try-finally block allows us to modify the program 
	// easily without losing track of the side effects. 
	__try 
	{ 
		//Initialize device extension 
		pdx->pDeviceObject		   = fdo; 
		pdx->pPhysicalDeviceObject = pdo;	 
 
		KeInitializeEvent(&pdx->StoppingEvent,NotificationEvent,FALSE); 
		pdx->bStopping			   = FALSE; 
 
		pdx->GotResource = FALSE;			 
 
		// Indicate the I/O Manager buffer management method 
		//once initial,can not be changed 
		fdo->Flags |= DO_BUFFERED_IO; 
 //       fdo->Flags |= DO_DIRECT_IO; 
 
		// Initialize DPC object 
		IoInitializeDpcRequest(fdo, DpcForIsr); 
		 
		// Register a device interface 
		status = IoRegisterDeviceInterface(pdo,&GUID_INTERFACE_Sil3124,  
											NULL,&pdx->InterfaceName); 
		if (!NT_SUCCESS(status)) 
		{						// unable to register interface 
			DebugPrint("Sil3124: - IoRegisterDeviceInterface failed - %x.", status); 
			//IoDeleteDevice(fdo); 
			//return(status); 
			__leave; 
		}						// unable to register interface 
 
		// Link our device object into the stack leading to the PDO 
		pdx->pLowerDeviceObject = IoAttachDeviceToDeviceStack(fdo, pdo); 
		if (!pdx->pLowerDeviceObject) 
		{						// can't attach device 
		    DebugPrint("Sil3124: - IoAttachDeviceToDeviceStack failed."); 
			status = STATUS_DEVICE_REMOVED; 
			//return(status); 
			__leave; 
		}						// can't attach device 
		//set deviceInterface state 
		IoSetDeviceInterfaceState(&pdx->InterfaceName, TRUE); 
 
		// Indicate that our initial power state is D0 (fully on). Also indicate that 
		// we have a pagable power handler (otherwise, we'll never get idle shutdown 
		// messages!) 
		pdx->SystemPower = PowerSystemWorking; 
		pdx->DevicePower = PowerDeviceD0; 
		fdo->Flags |= DO_POWER_PAGABLE; 
 
		state.DeviceState = PowerDeviceD0; 
		PoSetPowerState(fdo, DevicePowerState, state); 
 
        DebugPrint("Adddevice End."); 
		// Clear the "initializing" flag so that we can get IRPs 
		fdo->Flags &= ~DO_DEVICE_INITIALIZING; 
 
		 
	}		// finish initialization 
	__finally 
	{			// cleanup side effects 
		if (!NT_SUCCESS(status)) 
		{					// need to cleanup 
			if (pdx->InterfaceName.Buffer) 
				RtlFreeUnicodeString(&pdx->InterfaceName); 
			if (pdx->pLowerDeviceObject) 
				IoDetachDevice(pdx->pLowerDeviceObject); 
			IoDeleteDevice(fdo); 
		}					// need to cleanup 
							// cleanup side effects 
	} 
	 
    return(STATUS_SUCCESS); 
}													// AddDevice 
/****************************************************************************** 
 * 
 * Function   :  DispatchPnp 
 * 
 * Description:  Handle PnP requests 
 * 
 ******************************************************************************/ 
NTSTATUS DispatchPnp(IN PDEVICE_OBJECT fdo, 
					 IN PIRP pIrp) 
{													//DispatchPnp 
    NTSTATUS			status; 
    PIO_STACK_LOCATION	stack; 
	PDEVICE_EXTENSION	pdx; 
 
	DebugPrint("Pnp Start...."); 
 
	pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension; 
 
    stack = IoGetCurrentIrpStackLocation(pIrp); 
 
    // Check minor code 
	//if check no exist,default handling  
    switch (stack->MinorFunction) 
    { 
        case IRP_MN_START_DEVICE:	//must be implemented 
            DebugPrint("IRP_MN_START_DEVICE."); 
            status = PnpStartDevice(fdo,pIrp); 
			//status = DefaultPnpHandler(fdo,pIrp); 
            break; 
 
        case IRP_MN_STOP_DEVICE: 
            DebugPrint("IRP_MN_STOP_DEVICE."); 
            status = PnpStopDevice(fdo,pIrp); 
			//status = DefaultPnpHandler(fdo,pIrp); 
            break; 
 
        case IRP_MN_REMOVE_DEVICE: 
            DebugPrint("IRP_MN_REMOVE_DEVICE."); 
            status = PnpRemoveDevice(fdo,pIrp); 
			//status = DefaultPnpHandler(fdo,pIrp); 
			return status; 
            break; 
 
        case IRP_MN_QUERY_REMOVE_DEVICE: 
            DebugPrint("IRP_MN_QUERY_REMOVE_DEVICE."); 
			status = PnpQueryRemoveDeviceHandler(fdo,pIrp); 
            //status = DefaultPnpHandler(fdo,pIrp); 
			break; 
 
        case IRP_MN_CANCEL_REMOVE_DEVICE: 
            DebugPrint("IRP_MN_CANCEL_REMOVE_DEVICE."); 
            status = DefaultPnpHandler(fdo,pIrp); 
            break; 
 
        case IRP_MN_QUERY_STOP_DEVICE: 
            DebugPrint("IRP_MN_QUERY_STOP_DEVICE."); 
            status = DefaultPnpHandler(fdo,pIrp); 
            break; 
 
        case IRP_MN_CANCEL_STOP_DEVICE: 
            DebugPrint("IRP_MN_CANCEL_STOP_DEVICE."); 
            status = DefaultPnpHandler(fdo,pIrp); 
            break; 
 
        case IRP_MN_QUERY_DEVICE_RELATIONS: 
            DebugPrint("IRP_MN_QUERY_DEVICE_RELATIONS."); 
            status = DefaultPnpHandler(fdo,pIrp); 
            break; 
 
        case IRP_MN_QUERY_INTERFACE: 
            DebugPrint("IRP_MN_QUERY_INTERFACE."); 
            status = DefaultPnpHandler(fdo,pIrp); 
            break; 
 
        case IRP_MN_QUERY_CAPABILITIES: 
            DebugPrint("IRP_MN_QUERY_CAPABILITIES."); 
            status = DefaultPnpHandler(fdo,pIrp); 
			//status = PnpQueryCapabilitiesHandler(fdo,pIrp); 
            break; 
 
        case IRP_MN_QUERY_RESOURCES: 
            DebugPrint("IRP_MN_QUERY_RESOURCES."); 
            status = DefaultPnpHandler(fdo,pIrp); 
            break; 
 
        case IRP_MN_QUERY_RESOURCE_REQUIREMENTS: 
            DebugPrint("IRP_MN_QUERY_RESOURCE_REQUIREMENTS."); 
            status = DefaultPnpHandler(fdo,pIrp); 
            break; 
 
        case IRP_MN_QUERY_DEVICE_TEXT: 
            DebugPrint("IRP_MN_QUERY_DEVICE_TEXT."); 
            status = DefaultPnpHandler(fdo,pIrp); 
            break; 
 
        case IRP_MN_FILTER_RESOURCE_REQUIREMENTS: 
            DebugPrint("IRP_MN_FILTER_RESOURCE_REQUIREMENTS."); 
            status = DefaultPnpHandler(fdo,pIrp); 
            break; 
 
        case IRP_MN_READ_CONFIG: 
            DebugPrint("IRP_MN_READ_CONFIG."); 
            status = DefaultPnpHandler(fdo,pIrp); 
            break; 
 
        case IRP_MN_WRITE_CONFIG: 
            DebugPrint("IRP_MN_WRITE_CONFIG."); 
            status = DefaultPnpHandler(fdo,pIrp); 
            break; 
 
        case IRP_MN_EJECT: 
            DebugPrint("IRP_MN_EJECT."); 
            status = DefaultPnpHandler(fdo,pIrp); 
            break; 
 
        case IRP_MN_SET_LOCK: 
            DebugPrint("IRP_MN_SET_LOCK."); 
            status = DefaultPnpHandler(fdo,pIrp); 
            break; 
 
        case IRP_MN_QUERY_ID: 
            DebugPrint("IRP_MN_QUERY_ID."); 
            status = DefaultPnpHandler(fdo,pIrp); 
            break; 
 
        case IRP_MN_QUERY_PNP_DEVICE_STATE: 
            DebugPrint("IRP_MN_QUERY_PNP_DEVICE_STATE."); 
            status = DefaultPnpHandler(fdo,pIrp); 
            break; 
 
        case IRP_MN_QUERY_BUS_INFORMATION: 
            DebugPrint("IRP_MN_QUERY_BUS_INFORMATION."); 
            status = DefaultPnpHandler(fdo,pIrp); 
            break; 
 
        case IRP_MN_DEVICE_USAGE_NOTIFICATION: 
            DebugPrint("IRP_MN_DEVICE_USAGE_NOTIFICATION."); 
            status = DefaultPnpHandler(fdo,pIrp); 
            break; 
 
        case IRP_MN_SURPRISE_REMOVAL: 
            DebugPrint("IRP_MN_SURPRISE_REMOVAL."); 
            status = DefaultPnpHandler(fdo,pIrp); 
            break; 
 
        default: 
            DebugPrint("Unsupported IRP_MN_Xxx (0x%x).", stack->MinorFunction); 
            status = DefaultPnpHandler(fdo,pIrp); 
            break; 
    } 
 
	DebugPrint("Pnp End."); 
 
    return(status); 
}											//DispatchPnp 
 
/****************************************************************************** 
 * 
 * Function   :  DefaultPnpHandler 
 * 
 * Description:  Handle standard PnP requests 
 * 
 ******************************************************************************/ 
NTSTATUS DefaultPnpHandler(IN PDEVICE_OBJECT fdo, 
						   IN PIRP  pIrp) 
{												//DefaultPnpHandler 
	DebugPrintMsg("PnpDefaultHandler"); 
    IoSkipCurrentIrpStackLocation(pIrp); 
 
    return IoCallDriver(((DEVICE_EXTENSION *)fdo->DeviceExtension)->pLowerDeviceObject, 
								pIrp); 
}												//DefaultPnpHandler 
 
/****************************************************************************** 
 * 
 * Function   :  HandleStartDevice 
 * 
 * Description:  Handle the IRP_MN_START_DEVICE PnP request 
 * 
 ******************************************************************************/ 
NTSTATUS PnpStartDevice(IN PDEVICE_OBJECT fdo, 
						   IN PIRP pIrp ) 
{												//HandleStartDevice 
    NTSTATUS           status; 
    PIO_STACK_LOCATION stack; 
 
     
    //First let all lower-level drivers handle this request.  
	pIrp->IoStatus.Status = STATUS_SUCCESS; 
    status = ForwardAndWait(fdo,pIrp);			//Send IRP to lower driver(Bus Driver) and wait for finishing  
    if (!NT_SUCCESS(status)) 
    { 
        return(CompleteRequest(pIrp, status)); 
    } 
 
    stack = IoGetCurrentIrpStackLocation(pIrp); 
 
    // Assign resources to the devices 
    status = StartDevice(fdo, 
                 &stack->Parameters.StartDevice.AllocatedResources->List[0].PartialResourceList, 
                 &stack->Parameters.StartDevice.AllocatedResourcesTranslated->List[0].PartialResourceList); 
 
    return(CompleteRequestInfo(pIrp,status,0)); 
}													//HandleStartDevice 
/****************************************************************************** 
 * 
 * Function   :  StartDevice 
 * 
 * Description:  Start a device 
 * 
 ******************************************************************************/ 
NTSTATUS StartDevice(IN PDEVICE_OBJECT fdo, 
					 IN PCM_PARTIAL_RESOURCE_LIST ResourceListRaw, 
					 IN PCM_PARTIAL_RESOURCE_LIST ResourceList) 
{													//StartDevice 
    ULONG							i; 
    ULONG                           m;    
    NTSTATUS						status; 
    PDEVICE_EXTENSION				pdx; 
	PUCHAR  MappedAddress; 
 
    PCM_PARTIAL_RESOURCE_DESCRIPTOR	ResourceRaw; 
    PCM_PARTIAL_RESOURCE_DESCRIPTOR	Resource; 
    DEVICE_DESCRIPTION deviceDescription ;          // device descriptor  
 
    pdx         = (PDEVICE_EXTENSION)fdo->DeviceExtension; 
 
    ResourceRaw = ResourceListRaw->PartialDescriptors; 
    Resource    = ResourceList->PartialDescriptors; 
 
    #define MAX_DMA_LENGTH	0x100000	// 0x100000 is 1 MB 
	//initialize the device descriptor  
	// Zero the device descriptor struct before fill  
	RtlZeroMemory(&deviceDescription, sizeof(deviceDescription)); 
 
	deviceDescription.Version = DEVICE_DESCRIPTION_VERSION ; 
    deviceDescription.Master = TRUE ;		    // bus master. 
    deviceDescription.ScatterGather = TRUE ;	    
    deviceDescription.DemandMode = FALSE ;      //Indicates whether to use the system DMA controller's demand mode. Not used for busmaster DMA.  
    deviceDescription.AutoInitialize = FALSE ;	    // We don't use autoinitialize 
    deviceDescription.Dma32BitAddresses = TRUE ; 
    deviceDescription.IgnoreCount = FALSE; 
    deviceDescription.InterfaceType = PCIBus ; 
    deviceDescription.DmaWidth = Width32Bits ; //PCI default width 
    deviceDescription.DmaSpeed = Compatible ; 
    deviceDescription.MaximumLength = MAX_DMA_LENGTH ; 
    //get adapter object 
	pdx->AdapterObject = IoGetDmaAdapter(pdx->pPhysicalDeviceObject,&deviceDescription, 
	    &pdx->MaximumMapRegisters) ; 
	DebugPrint("the # of map register system provide is:%u\n",pdx->MaximumMapRegisters); 
 
	 // If IoGetDmaAdapter fails, it is mostly likely that one of the parameters 
    // supplied in the DEVICE_DESCRIPTION structure is not valid. It can also fail because of insufficient 
    // resource, but not very likely. 
    if (pdx->AdapterObject == NULL) { 
	DebugPrint ("Sil3124: IoGetDmaAdapter failed.\n") ; 
	status = STATUS_DEVICE_CONFIGURATION_ERROR ; 
	return status; 
    } 
 
	DebugPrint("Start Device Start."); 
	DebugPrint("the ResourceListRaw->count is %x\n",ResourceListRaw->Count); 
 
    for (i = 0,m = 0; i < ResourceListRaw->Count; ++i, ++Resource, ++ResourceRaw) 
    { 
        switch (ResourceRaw->Type) 
        { 
		case CmResourceTypePort:        //IO Port Resource 
			DebugPrint("ResourceType:Registers that provide indirect access to the registers of sil3124"); 
				pdx->BaseAddress_Indirect_Access = Resource->u.Port.Start; 
				pdx->IORangeBytes = Resource->u.Port.Length; 
				DebugPrint("Indirect Access Register base address : 0x%x\n",pdx->BaseAddress_Indirect_Access); 
				DebugPrint("Indirect Access register's length :%ubytes\n",pdx->IORangeBytes); 
				if(ResourceRaw->Flags & CM_RESOURCE_PORT_IO) 
				{ 
					DebugPrint("The TaskFile register of channel#0 is accessed in IO address space"); 
				} 
				else  
				{ 
                    DebugPrint("The TaskFile register of channel#0 is accessed in Memory address space"); 
				} 
		 
			break; 
		case CmResourceTypeMemory:        //Memory Resources 
            DebugPrint("ResourceType:Memory Registers that provide access for Global Register and 4 PCI Ports "); 
			switch(m) 
			{ 
			case 0:                    //Base Address 0  Global register base address  
				pdx->BaseAddress_GlobalRegister = Resource->u.Memory.Start; 
				pdx->GlobalRegisterBytes = Resource->u.Memory.Length; 
				DebugPrint("Global register base address  : 0x%x\n",pdx->BaseAddress_GlobalRegister); 
				DebugPrint("Global register's length :%ubytes\n",pdx->GlobalRegisterBytes); 
				if(ResourceRaw->Flags == CM_RESOURCE_MEMORY_READ_WRITE) 
				{ 
					DebugPrint("the global registers could be read & write"); 
				} 
				else  
				{ 
                    DebugPrint("the global registers could be read OR write"); 
				} 
				pdx->Map_GlobalRegister = NULL; 
			 
				break; 
			case 1:                    //Base Address 1  Port register and LRAM base address for 4 ports 
				pdx->BaseAddress_PortRegister = Resource->u.Memory.Start; 
				pdx->PortRegisterBytes = Resource->u.Memory.Length; 
				DebugPrint("Port register base address  : 0x%x\n",pdx->BaseAddress_PortRegister); 
				DebugPrint("Port register's length :%ubytes\n",pdx->PortRegisterBytes); 
				if(ResourceRaw->Flags & CM_RESOURCE_MEMORY_READ_WRITE) 
				{ 
					DebugPrint("the Port registers could be read & write"); 
				} 
				else  
				{ 
                    DebugPrint("the Port registers could be read OR write"); 
				} 
				pdx->Map_PortRegister = NULL; 
			 
				break; 
			} 
			m++; 
			break; 
          
		case CmResourceTypeInterrupt:	//Interrupt Resources 
			    pdx->GotInterrupt = TRUE; 
                pdx->IrqL       = (KIRQL) Resource->u.Interrupt.Level; 
                pdx->vector     = Resource->u.Interrupt.Vector; 
                pdx->affinity   = Resource->u.Interrupt.Affinity; 
				DebugPrint("the Interrupt Flags:%x\n",ResourceRaw->Flags); 
                if (ResourceRaw->Flags == CM_RESOURCE_INTERRUPT_LATCHED) 
                { 
                    pdx->mode = Latched; 
                } 
                else 
                { 
                    pdx->mode = LevelSensitive; 
                } 
				pdx->irqshare = Resource->ShareDisposition == CmResourceShareShared; 
 
				DebugPrint("ResouceType: Interrupt:Vector:0x%x(Translated=0x%x)", 
                         ResourceRaw->u.Interrupt.Vector, pdx->vector); 
				DebugPrint("   IRQL:0x%x(Translated=0x%x)Affinity:0x%x(Translated=0x%x).", 
							ResourceRaw->u.Interrupt.Level, pdx->IrqL, 
							ResourceRaw->u.Interrupt.Affinity, pdx->affinity); 
                break; 
 
			default: 
				DebugPrint("Type: ?Unknown Resource Type?"); 
				break; 
        } 
    } 
 
		//connect to interrupt 
 
    if (pdx->GotInterrupt) 
    { 
		DebugPrint("Get Interrupt."); 
        // firstly,Disable the PCI interrupt 
       //DisablePciInterrupt(pdx); 
		//connect interrupt 
		status = IoConnectInterrupt(&pdx->InterruptObject,(PKSERVICE_ROUTINE)OnInterrupt, 
						(PVOID)pdx,NULL,pdx->vector,pdx->IrqL,pdx->IrqL,pdx->mode,pdx->irqshare,pdx->affinity,FALSE); 
		 
		if (!NT_SUCCESS(status)) 
		{ 
			pdx->InterruptObject = NULL; 
			return status; 
		} 
     DebugPrint("OK, I haved Connect Interruput!"); 
    } 
    else 
    { 
        DebugPrint("Sil3124: No interrupt found."); 
        pdx->InterruptObject = NULL; 
    } 
 
 
	// Initialize DPC object 
	IoInitializeDpcRequest(fdo, DpcForIsr); 
 
	pdx->NeedToHandle =FALSE; 
	DebugPrint("Start Device end."); 
	pdx->GotResource = TRUE; 
 
    return STATUS_SUCCESS; 
}	 
											//StartDevice 
/****************************************************************************** 
 * 
 * Function   :  OnRequestComplete 
 * 
 * Description:  Set an event when a lower driver complete an IRP. 
 * 
 ******************************************************************************/ 
NTSTATUS OnRequestComplete(IN PDEVICE_OBJECT fdo, 
						   IN PIRP pIrp, 
						   IN PKEVENT pKEvent) 
{												//OnRequestComplete 
    KeSetEvent(pKEvent,(KPRIORITY)0,FALSE); 
 
    return(STATUS_MORE_PROCESSING_REQUIRED); 
}												//OnRequestComplete 
 
/****************************************************************************** 
 * 
 * Function   :  HandleStopDevice 
 * 
 * Description:  Handle the IRP_MN_STOP_DEVICE PnP request 
 * 
 ******************************************************************************/ 
NTSTATUS PnpStopDevice(IN PDEVICE_OBJECT fdo, 
					   IN PIRP pIrp) 
{	 
    DebugPrintMsg("PnpStopDeviceHandler"); 
	 
	// Wait for I/O to complete and stop device 
    StopDevice(fdo); 
	 
	return DefaultPnpHandler(fdo,pIrp); 
}												//HandleStopDevice 
 
/****************************************************************************** 
 * 
 * Function   :  StopDevice 
 * 
 * Description:  Stop a device 
 * 
 ******************************************************************************/ 
VOID StopDevice(IN PDEVICE_OBJECT fdo) 
{												//StopDevice 
    DEVICE_EXTENSION *pdx; 
 
    pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension; 
 
	if (!pdx->GotResource) 
		return; 
 
	pdx->bStopping = TRUE; 
	DebugPrintMsg("StopDevice"); 
 
	if( !pdx->GotResource) 
		return; 
	pdx->GotResource = FALSE; 
}												//StopDevice 
 
///////////////////////////////////////////////////////////////////////////// 
//	PnpQueryRemoveDeviceHandler:	Handle PnP query remove device 
 
NTSTATUS PnpQueryRemoveDeviceHandler( IN PDEVICE_OBJECT fdo, IN PIRP Irp) 
{ 
	PDEVICE_EXTENSION pdx=(PDEVICE_EXTENSION)fdo->DeviceExtension; 
	DebugPrintMsg("PnpQueryRemoveDeviceHandler"); 
	if( pdx->OpenHandleCount>0) 
	{ 
		DebugPrint("PnpQueryRemoveDeviceHandler: %d handles still open",pdx->OpenHandleCount); 
		return CompleteRequestInfo( Irp, STATUS_UNSUCCESSFUL, 0); 
	} 
	 
	return DefaultPnpHandler(fdo,Irp); 
} 
 
/****************************************************************************** 
 * 
 * Function   :  PnpRemoveDevice 
 * 
 * Description:  Handle the IRP_MN_REMOVE_DEVICE PnP request 
 * 
 ******************************************************************************/ 
 
NTSTATUS PnpRemoveDevice(IN PDEVICE_OBJECT fdo, 
							IN PIRP pIrp) 
{												//HandleRemoveDevice 
    NTSTATUS          status; 
    DEVICE_EXTENSION  *pdx; 
 
    // Wait for any pending I/O operations to complete 
 
    pdx			   = (PDEVICE_EXTENSION) fdo->DeviceExtension; 
	pIrp->IoStatus.Status = STATUS_SUCCESS;			// flag that we handled this IRP 
 
	DebugPrintMsg("call StopDevice"); 
	StopDevice(fdo); 
 
// disconnect the interrupt							 
	if (pdx->InterruptObject != NULL) 
    { 
  //      KeSynchronizeExecution(pdx->pInterruptObject, 
    //        (PKSYNCHRONIZE_ROUTINE)DisablePciInterrupt,(PVOID)pdx); 
 
        IoDisconnectInterrupt(pdx->InterruptObject); 
        pdx->InterruptObject = NULL; 
    } 
 
	// free the adapter object 
	if(pdx->AdapterObject!=NULL) 
	{ 
		(pdx->AdapterObject->DmaOperations->PutDmaAdapter)(pdx->AdapterObject); 
        pdx->AdapterObject = NULL; 
	} 
	 
    // Let lower-level drivers handle this request & ignore the result 
    status = DefaultPnpHandler(fdo,pIrp); 
 
	IoSetDeviceInterfaceState(&pdx->InterfaceName, FALSE); 
	RtlFreeUnicodeString(&pdx->InterfaceName); 
	DebugPrint("the InterfaceName has been free"); 
 
    // Detach device from the device object stack 
    if (pdx->pLowerDeviceObject) 
    { 
        IoDetachDevice(pdx->pLowerDeviceObject); 
    } 
 
    DebugPrint("Sil3124: Deleting device object..."); 
 
    // Delete the functional device object 
    IoDeleteDevice(fdo); 
 
	DebugPrint("Sil3124 is removed."); 
 
    return status; 
}												//HandleRemoveDevice 
///////////////////////////////////////////////////////////////////////////// 
//	PnpQueryCapabilitiesHandler:	Print pdo device capabilities 
 
#define SetMostPoweredState( SystemState, OurDeviceState)	\ 
	dps = deviceCapabilities->DeviceState[SystemState];		\ 
	if( dps==PowerDeviceUnspecified || dps>OurDeviceState)	\ 
		deviceCapabilities->DeviceState[SystemState] = OurDeviceState 
 
 
NTSTATUS PnpQueryCapabilitiesHandler( IN PDEVICE_OBJECT fdo, IN PIRP Irp) 
{ 
	NTSTATUS status = ForwardAndWait( fdo, Irp); 
	int ds; 
	DEVICE_POWER_STATE dps; 
	if( NT_SUCCESS(status)) 
	{ 
		PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation(Irp); 
		PDEVICE_CAPABILITIES deviceCapabilities; 
		deviceCapabilities = IrpStack->Parameters.DeviceCapabilities.Capabilities; 
#if DBG 
		for(ds=PowerSystemWorking;dsDeviceState[ds]); 
#endif 
		 
 
		SetMostPoweredState( PowerSystemWorking, PowerDeviceD0); 
		SetMostPoweredState( PowerSystemSleeping1, PowerDeviceD3); 
		SetMostPoweredState( PowerSystemSleeping2, PowerDeviceD3); 
		SetMostPoweredState( PowerSystemSleeping3, PowerDeviceD3); 
		SetMostPoweredState( PowerSystemHibernate, PowerDeviceD3); 
		SetMostPoweredState( PowerSystemShutdown, PowerDeviceD3); 
 
#if DBG 
		for(ds=PowerSystemWorking;dsDeviceState[ds]); 
#endif 
	} 
	return CompleteRequestInfo( Irp, status, Irp->IoStatus.Information); 
} 
 
/****************************************************************************** 
 * 
 * Function   :  ForwardAndWait 
 * 
 * Description:  Forward request to lower level and await completion, used 
 *               in PnP's IRP_MN_START_DEVICE 
 * 
 ******************************************************************************/ 
#pragma code_seg()	// end PAGE section 
NTSTATUS ForwardAndWait(PDEVICE_OBJECT fdo,PIRP pIrp) 
{												// ForwardAndWait 
    KEVENT    event; 
    NTSTATUS  status; 
 
    // Initialize a kernel event object to use in waiting for the lower-level 
    // driver to finish processing the object.  
    KeInitializeEvent(&event,NotificationEvent,FALSE); 
 
	DebugPrint("ForwardAndWait Start."); 
 
    IoCopyCurrentIrpStackLocationToNext(pIrp); 
 
    IoSetCompletionRoutine(pIrp,(PIO_COMPLETION_ROUTINE) OnRequestComplete, 
							(PVOID) &event,TRUE,TRUE,TRUE); 
 
    status = IoCallDriver( 
					((DEVICE_EXTENSION *) fdo->DeviceExtension)->pLowerDeviceObject, 
					pIrp); 
 
    if (status == STATUS_PENDING) 
    { 
        // Wait for completion 
		DebugPrintMsg("ForwardIrpAndWait: waiting for completion"); 
        KeWaitForSingleObject((PVOID)&event,Executive,KernelMode,FALSE,NULL); 
 
        return pIrp->IoStatus.Status; 
    } 
	DebugPrint("ForwardAndWait End."); 
    return(pIrp->IoStatus.Status);	//status; 
}													// ForwardAndWait