⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pnp.c

📁 WinBond W83627 看门狗驱动
💻 C
字号:

/*++

Copyright (c) 2006 EVOC, All Rights Reserved
 
Module Name:

    Pnp.c  

Abstract:   Handler PnP request.


Environment:

    Kernel mode


Author:    mz.yang  may, 2006


Revision History:

--*/

#include "Driver.h"


#pragma code_seg("PAGE") // start PAGE section

NTSTATUS
DefaultPnpHandler(IN PDEVICE_OBJECT fdo,IN PIRP Irp)
/*++

Routine Description:

    Pass down the irps .

Arguments:

	fdo - pointer to a function device object.
	Irp - pointer to an I/O Request Packet.

Return Value:

    NT status code.

--*/
{
    PDEVICE_EXTENSION pde;
	IoSkipCurrentIrpStackLocation(Irp);
    pde=(PDEVICE_EXTENSION)fdo->DeviceExtension;
    return IoCallDriver(pde->StackDeviceObject,Irp);
}

#pragma code_seg() // end PAGE section


NTSTATUS 
OnRequestComplete(IN PDEVICE_OBJECT fdo, IN PIRP Irp, IN PKEVENT pev)
{							// OnRequestComplete
	KeSetEvent(pev, 0, FALSE);
	return STATUS_MORE_PROCESSING_REQUIRED;
}							// OnRequestComplete


#pragma code_seg("PAGE") // start PAGE section

NTSTATUS 
ForwardAndWait(IN PDEVICE_OBJECT fdo, IN PIRP Irp)
{							// ForwardAndWait
	KEVENT event;
	PDEVICE_EXTENSION pde= fdo->DeviceExtension;
	
	KeInitializeEvent(&event, NotificationEvent, FALSE);
	IoCopyCurrentIrpStackLocationToNext(Irp);
	IoSetCompletionRoutine(Irp, (PIO_COMPLETION_ROUTINE) OnRequestComplete,
		(PVOID) &event, TRUE, TRUE, TRUE);
	IoCallDriver(pde->StackDeviceObject, Irp);
	KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
	return Irp->IoStatus.Status;
}							// ForwardAndWait


NTSTATUS
StartDevice(IN PDEVICE_OBJECT fdo,
			PCM_PARTIAL_RESOURCE_LIST list,
			PCM_PARTIAL_RESOURCE_LIST listTrans)
/*++

Routine Description:
    
    Get the resources, map the resources if required
    and initialize the device.    

Arguments:
    
   fdo - pointer to a function device object.

   list - resources list,it have the device resources that not translated.
   
   listTrans - resources list,it have the device resources that translated.
   
Return Value:

    NT status code
    
--*/
{
	PDEVICE_EXTENSION pde;
	BOOLEAN		needmap,haveport;
	PHYSICAL_ADDRESS port;
	ULONG nports,nres,i,j;
	NTSTATUS status=STATUS_SUCCESS;

	PCM_PARTIAL_RESOURCE_DESCRIPTOR resource=list->PartialDescriptors;
	PCM_PARTIAL_RESOURCE_DESCRIPTOR resourceTrans=listTrans->PartialDescriptors;

	pde=fdo->DeviceExtension;
	nres=list->Count;
	j=0;
	for(i=0;i<nres;i++,++resource,++resourceTrans)
	{
		needmap=FALSE;
		haveport=FALSE;
		switch(resource->Type)
		{
			case CmResourceTypePort:
				break;
			case CmResourceTypeInterrupt:
				pde->Irq=(ULONG)resource->u.Interrupt.Level;
				break;
			default:
				break;
		}
		switch(resourceTrans->Type)
		{
		case CmResourceTypePort:
			port=resourceTrans->u.Port.Start;
			nports=resourceTrans->u.Port.Length;
			haveport=TRUE;
			needmap=(resourceTrans->Flags&CM_RESOURCE_PORT_IO)==0;
			break;
			
		case CmResourceTypeInterrupt:
			pde->Irql=(KIRQL)resourceTrans->u.Interrupt.Level;
			pde->Vector=resourceTrans->u.Interrupt.Vector;
			pde->Affinity=resourceTrans->u.Interrupt.Affinity;
			pde->Mode=\
			(resourceTrans->Flags==CM_RESOURCE_INTERRUPT_LATCHED)?Latched:LevelSensitive;
			break;
			
		default:break;
		}
		if(haveport)
		{
		//*********************************//
		}
	}

	// clear and disabel interrupt
	DisableInterrupt(pde);

	// connect to interrupt
	if(pde->Irql)
	status=IoConnectInterrupt(&pde->InterruptObject,(PKSERVICE_ROUTINE)OnInterrupt,
								(PVOID)pde,NULL,pde->Vector,pde->Irql,pde->Irql,pde->Mode,FALSE,
								pde->Affinity,FALSE);

	if(!NT_SUCCESS(status))
	{
		DebugPrint(("connect interrupt error!\n"));
		return status;
	}
	pde->ConnectedToInterrupt=TRUE;

	// enable interrupt
	EnableInterrupt(pde);
	
	DebugPrint(("connect interrupt ok!\n"));

	return status;
}


NTSTATUS
DRV_StartDevice(IN PDEVICE_OBJECT fdo,IN PIRP Irp)
/*++

Routine Description:
    
    Handle PnP start device.

Arguments:
    
	fdo - pointer to a function device object.

	Irp - pointer to an I/O Request Packet.
 
Return Value:

    NT status code
    
--*/
{
	PIO_STACK_LOCATION stack;
    PDEVICE_EXTENSION pde=fdo->DeviceExtension;
	NTSTATUS status;

	if(pde->started)
		return CompleteIoReq(Irp,STATUS_SUCCESS,0);

	Irp->IoStatus.Status = STATUS_SUCCESS;
	
	status=ForwardAndWait(fdo,Irp);
	if(!NT_SUCCESS(status))
	{
		CompleteIoReq(Irp,status,0);
		return status;
	}

	stack=IoGetCurrentIrpStackLocation(Irp);
	/*
	status=StartDevice(fdo , 
					   &stack->Parameters.StartDevice.
						AllocatedResources->List[0].PartialResourceList,
					   &stack->Parameters.StartDevice.\
						AllocatedResourcesTranslated->List[0].PartialResourceList
					  );
	*/
	if(NT_SUCCESS(status))
			pde->started=TRUE;
	CompleteIoReq(Irp,status,0);
	return status;
}


void StopDevice( IN PDEVICE_OBJECT fdo)
/*++

Routine Description:
    
    Stop device.We must release resources and disconnect interrupt.

Arguments:
    
	pde - device object extention.

Return Value:

    void
    
--*/
{
	PDEVICE_EXTENSION pde = fdo->DeviceExtension;

	if( !pde->started)
		return;

	// release resources
	// Disable device Interrupt
	// KeSynchronizeExecution(pde->Interrupt,DisableInterrupt,(PVOID)pde); 
	// Disconnect from Interrupt
	if( pde->ConnectedToInterrupt)
	{
		IoDisconnectInterrupt(pde->InterruptObject);
		pde->ConnectedToInterrupt = FALSE;
		pde->InterruptObject = NULL;
	}

	if(pde->ResourcesClaimed)
	{
		UnclaimResources(fdo);
		pde->ResourcesClaimed = FALSE;
	}

	if(pde->EventCreated)
	{
		ZwClose(pde->hEvent);
		pde->EventCreated = FALSE;
	}

	pde->started =FALSE;

}

NTSTATUS
DRV_QueryStop(IN PDEVICE_OBJECT fdo,IN PIRP Irp)

/*++

  Routine Description: Handle PnP query stop request.

--*/

{
	PDEVICE_EXTENSION pde=fdo->DeviceExtension;

	if(pde->opencount>0)
		return CompleteIoReq(Irp,STATUS_UNSUCCESSFUL,0);

	Irp->IoStatus.Status = STATUS_SUCCESS;
	return DefaultPnpHandler(fdo,Irp);
}

NTSTATUS
DRV_StopDevice(IN PDEVICE_OBJECT fdo,IN PIRP Irp)

/*++

  Routine Description: Handle PnP stop device request.

--*/

{	
	PDEVICE_EXTENSION pde=fdo->DeviceExtension;

	StopDevice(fdo);
	Irp->IoStatus.Status = STATUS_SUCCESS;
	return DefaultPnpHandler(fdo,Irp);
}

NTSTATUS
DRV_QueryRemove(IN PDEVICE_OBJECT fdo,IN PIRP Irp)

/*++

  Routine Description: Handle PnP query remove request.

--*/

{
	PDEVICE_EXTENSION pde=fdo->DeviceExtension;

	if(pde->opencount>0)
		return CompleteIoReq(Irp,STATUS_UNSUCCESSFUL,0);
	Irp->IoStatus.Status = STATUS_SUCCESS;
	return DefaultPnpHandler(fdo,Irp);
}


VOID RemoveDevice(IN PDEVICE_OBJECT fdo)

/*++

  Routine Description: when remove device,we must detach from stack device object.

--*/

{
	PDEVICE_EXTENSION pde=fdo->DeviceExtension;

	if(pde->StackDeviceObject)
		IoDetachDevice(pde->StackDeviceObject);     
	IoDeleteDevice(fdo);								
}


NTSTATUS
DRV_RemoveDevice(IN PDEVICE_OBJECT fdo,IN PIRP Irp)

/*++

	Routine Description: Handle PnP remove device request.

--*/

{
	PDEVICE_EXTENSION pde=fdo->DeviceExtension;
	ULONG	i;
	NTSTATUS status;
	
	StopDevice(fdo);
	Irp->IoStatus.Status = STATUS_SUCCESS;
	status=DefaultPnpHandler(fdo,Irp);
	IoReleaseRemoveLockAndWait(&pde->RemoveLock, Irp);
	RemoveDevice(fdo);
	pde->removing = TRUE;
	
	return status;
}


BOOLEAN
DisableInterrupt(IN PDEVICE_EXTENSION pde)
/*++

Routine Description:
    
    We must clear and disable interrupt before connect to interrupt.

Arguments:
    
	pde - device object extention.

Return Value:

    TRUE:	Routine called success.
	FALE:	Routine called failed.
    
--*/
{
	if((pde->HardwareID == 0x52) || (pde->HardwareID == 0x82) || 
		(pde->HardwareID == 0x88) || (pde->HardwareID == 0xA0))		// W83627HF/THF/EHF/DFG
	{
		// start programming watchdog
		WRITE_PORT_UCHAR( (PVOID)pde->PortIndex, 0x87 );
		WRITE_PORT_UCHAR( (PVOID)pde->PortIndex, 0x87 );

		WRITE_PORT_UCHAR( (PVOID)pde->PortIndex, 0x07 );
		WRITE_PORT_UCHAR( (PVOID)pde->PortData, 0x08 );		// logical device 8

		// Active watch dog device
		WRITE_PORT_UCHAR( (PVOID)pde->PortIndex, 0x30 );
		WRITE_PORT_UCHAR( (PVOID)pde->PortData, 0x01 );	
		
		// clear interrupt
		WRITE_PORT_UCHAR( (PVOID)pde->PortIndex, 0xf6 );	
		WRITE_PORT_UCHAR( (PVOID)pde->PortData, 0x00 );

		// disnable interrupt
		WRITE_PORT_UCHAR( (PVOID)pde->PortIndex, 0xf7 );
		WRITE_PORT_UCHAR( (PVOID)pde->PortData, 0x00 );

		WRITE_PORT_UCHAR( (PVOID)pde->PortIndex, 0xaa );
	}
	if(pde->HardwareID == 0x97)		// W83977F/AF
	{
		// start programming watchdog
		WRITE_PORT_USHORT( (PVOID)pde->ShortPortIndex, 0x87 );
		WRITE_PORT_USHORT( (PVOID)pde->ShortPortIndex, 0x87 );

		WRITE_PORT_USHORT( (PVOID)pde->ShortPortIndex, 0x07 );
		WRITE_PORT_USHORT( (PVOID)pde->ShortPortData, 0x08 );		// logical device 8

		// Active watch dog device
		WRITE_PORT_USHORT( (PVOID)pde->ShortPortIndex, 0x30 );
		WRITE_PORT_USHORT( (PVOID)pde->ShortPortData, 0x01 );	
		
		// clear interrupt
		WRITE_PORT_USHORT( (PVOID)pde->ShortPortIndex, 0xf2 );	
		WRITE_PORT_USHORT( (PVOID)pde->ShortPortData, 0x00 );
		WRITE_PORT_USHORT( (PVOID)pde->ShortPortIndex, 0x72 );
		WRITE_PORT_USHORT( (PVOID)pde->ShortPortData, 0x00 );
		WRITE_PORT_USHORT( (PVOID)pde->ShortPortIndex, 0xf4 );
		WRITE_PORT_USHORT( (PVOID)pde->ShortPortData, 0x00 );

		WRITE_PORT_USHORT( (PVOID)pde->ShortPortIndex, 0xaa );

	}

	return TRUE;
}

 
BOOLEAN
EnableInterrupt(IN PDEVICE_EXTENSION pde)
/*++

Routine Description:
    
    Enable interrupt after connect to interrupt.

Arguments:
    
	pde - device object extention.

Return Value:

    TRUE:	Routine called success.
	FALE:	Routine called failed.
    
--*/

{
	if((pde->HardwareID == 0x52) || (pde->HardwareID == 0x82) || 
		(pde->HardwareID == 0x88) || (pde->HardwareID == 0xA0))		// W83627HF/THF/DHG
	{
		// start programming watchdog
		WRITE_PORT_UCHAR( (PVOID)pde->PortIndex, 0x87 );
		WRITE_PORT_UCHAR( (PVOID)pde->PortIndex, 0x87 );

		WRITE_PORT_UCHAR( (PVOID)pde->PortIndex, 0x07 );
		WRITE_PORT_UCHAR( (PVOID)pde->PortData, 0x08 );		// logical device 8

		// Active watch dog device
		WRITE_PORT_UCHAR( (PVOID)pde->PortIndex, 0x30 );
		WRITE_PORT_UCHAR( (PVOID)pde->PortData, 0x01 );	

		// Enable interrupt,set IRQ
		WRITE_PORT_UCHAR( (PVOID)pde->PortIndex, 0xf7 );
		WRITE_PORT_UCHAR( (PVOID)pde->PortData, (UCHAR)pde->Irq );

		// end watch programing dog
		WRITE_PORT_UCHAR( (PVOID)pde->PortIndex, 0xaa );
	}
	if(pde->HardwareID == 0x97)		// W83977F/AF
	{
		// start programming watchdog
		WRITE_PORT_USHORT( (PVOID)pde->ShortPortIndex, 0x87 );
		WRITE_PORT_USHORT( (PVOID)pde->ShortPortIndex, 0x87 );

		WRITE_PORT_USHORT( (PVOID)pde->ShortPortIndex, 0x07 );
		WRITE_PORT_USHORT( (PVOID)pde->ShortPortData, 0x08 );		// logical device 8

		// Active watch dog device
		WRITE_PORT_USHORT( (PVOID)pde->ShortPortIndex, 0x30 );
		WRITE_PORT_USHORT( (PVOID)pde->ShortPortData, 0x01 );	
		
		// Enable interrupt,set irq.
		WRITE_PORT_USHORT( (PVOID)pde->ShortPortIndex, 0x72 );	
		WRITE_PORT_USHORT( (PVOID)pde->ShortPortData, (USHORT)pde->Irq );

		//WRITE_PORT_USHORT( (PVOID)pde->ShortPortIndex, 0xf4 );
		//WRITE_PORT_USHORT( (PVOID)pde->ShortPortData, 0x00 );

		WRITE_PORT_USHORT( (PVOID)pde->ShortPortIndex, 0xaa );
	}

	return TRUE;
} 

NTSTATUS \
DRV_PnPDispatch(IN PDEVICE_OBJECT fdo,IN PIRP Irp)
/*++

Routine Description:

    The plug and play dispatch routines.

    Most of these the driver will completely ignore.
    In all cases it must pass the IRP to the next lower driver.

Arguments:

   fdo - pointer to a function device object.

   Irp - pointer to an I/O Request Packet.

Return Value:

      NT status code

--*/
{
	PIO_STACK_LOCATION stack;
	PDEVICE_EXTENSION pde;
	NTSTATUS status;
	BOOLEAN  lockHeld = TRUE;

	stack=IoGetCurrentIrpStackLocation(Irp);
	pde=fdo->DeviceExtension;

	status = IoAcquireRemoveLock(&pde->RemoveLock, Irp);
    if (!NT_SUCCESS(status)) 
	{
		DebugPrint(("Acquire RemoveLock failed\n" ));
        CompleteIoReq( Irp, status, 0 );
        return status;
    }

	switch(stack->MinorFunction)
	{
	case IRP_MN_START_DEVICE:
		status=DRV_StartDevice(fdo,Irp);
		break;
	case IRP_MN_QUERY_STOP_DEVICE:
		status=DRV_QueryStop(fdo,Irp);
		break;
	case IRP_MN_SURPRISE_REMOVAL:
	case IRP_MN_STOP_DEVICE:
		status=DRV_StopDevice(fdo,Irp);
		break;
	case IRP_MN_QUERY_REMOVE_DEVICE:
		status=DRV_QueryRemove(fdo,Irp);
		break;
	case IRP_MN_REMOVE_DEVICE:
		status=DRV_RemoveDevice(fdo,Irp);
		//
		// Remove Lock released by RamDiskRemoveDevice
		//
		lockHeld = FALSE;
		break;
	//case IRP_MN_QUERY_CAPABILITIES:
	//	status=PnpQueryCapabilitiesHandler(fdo,Irp);
	//	break;
	default:
		status=DefaultPnpHandler(fdo,Irp);
	}

	//
    // Device Extenion is gone if the current IRP is IRP_MN_REMOVE_DEVICE
    //
    if ( lockHeld == TRUE ) 
	{
        IoReleaseRemoveLock(&pde->RemoveLock, Irp);
    }
	return status;
}

#pragma code_seg() // end PAGE section

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -