📄 pnp.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 + -