📄 pnp.cpp
字号:
pdx->bStopping = TRUE;
KeResetEvent(&pdx->StoppingEvent);
UnlockDevice(pdx); //必须UnlockDevice两次
UnlockDevice(pdx);
KeWaitForSingleObject( &pdx->StoppingEvent, Executive, KernelMode, FALSE, NULL);
KdPrint((DBG_NAME "PnpStopDevice: All pending I/O completed\n"));
pdx->bStopping = FALSE;
pdx->GotResource = FALSE;
KdPrint((DBG_NAME "PDC4000 is being stopped...\n"));
//等待全部的IRP释放后再释放资源
// Free all interrupt resources
if (pdx->pInterruptObject != NULL)
{
KeSynchronizeExecution(pdx->pInterruptObject,
(PKSYNCHRONIZE_ROUTINE)DisablePciInterrupt,(PVOID)pdx);
IoDisconnectInterrupt(pdx->pInterruptObject);
pdx->pInterruptObject = NULL;
}
//Free all the mem map.
if(pdx->LocalRegisterMemBase)
MmUnmapIoSpace(pdx->LocalRegisterMemBase, pdx->LocalRegisterMemCount);
if(pdx->PdcMemBase0)
MmUnmapIoSpace(pdx->PdcMemBase0, pdx->PdcMemCount0);
pdx->LocalRegisterMemBase = NULL;
pdx->LocalRegisterMemCount = 0;
pdx->PdcMemBase0 = NULL;
pdx->PdcMemCount0 = 0;
//Release DMA Common Buffer
(*pdx->DmaInfo[0].pDmaAdapterObject->DmaOperations->FreeCommonBuffer)
(pdx->DmaInfo[0].pDmaAdapterObject,
pdx->DmaInfo[0].lCommonBufferSize,
pdx->DmaInfo[0].paCommonBuffer,
pdx->DmaInfo[0].vaCommonBuffer,
FALSE);
// Bump usage count back up again
LockDevice(pdx);
LockDevice(pdx);
KdPrint((DBG_NAME "PDC4000 is stopped.\n"));
} //StopDevice
#pragma code_seg() // end PAGE section
/******************************************************************************
*
* Function : LockDevice
*
* Description: Lock a device for operation, return FALSE if device is being
* removed.
*
******************************************************************************/
BOOLEAN LockDevice(IN DEVICE_EXTENSION *pdx)
{ //LockDevice
// Increment use count on our device object
InterlockedIncrement(&pdx->UsageCount);
// KdPrint((DBG_NAME "PDC4000: Locking..."));
/*
If device is about to be removed, restore the use count and return FALSE.
If a race exists with HandleRemoveDevice (maybe running on another CPU),
the sequence we've followed is guaranteed to avoid a mistaken deletion of
the device object. If we test "removing" after HandleRemoveDevice sets
it, we'll restore the use count and return FALSE. In the meantime, if
HandleRemoveDevice decremented count to 0 before we did our increment,
its thread will have set the remove event. Otherwise, we'll decrement to
0 and set the event. Either way, HandleRemoveDevice will wake up to
finish removing the device, and we'll return FALSE to our caller.
If, on the other hand, we test "removing" before HandleRemoveDevice sets
it, we'll have already incremented the use count past 1 and will return
TRUE. Our caller will eventually call UnlockDevice, which will decrement
the use count and might set the event HandleRemoveDevice is waiting on at
that point.
*/
if (pdx->bStopping)
{
// Stopping device
if (InterlockedDecrement(&pdx->UsageCount) == 0)
KeSetEvent(&pdx->StoppingEvent,0,FALSE);
return FALSE;
}
// KdPrint((DBG_NAME "PDC4000 is locked."));
return TRUE;
} //LockDevice
/******************************************************************************
*
* Function : UnlockDevice
*
* Description: Unlock a device.
*
******************************************************************************/
VOID UnlockDevice(IN DEVICE_EXTENSION *pdx)
{ //UnlockDevice
LONG UsageCount = InterlockedDecrement(&pdx->UsageCount);
// KdPrint((DBG_NAME "PDC4000 is unlocking..."));
// KdPrint(("PDC4000: UNLOCKING... (usage = %d)\n", UsageCount));
if (UsageCount == 0)
{
// Stopping device
KeSetEvent(&pdx->StoppingEvent,0,FALSE);
}
// KdPrint((DBG_NAME "PDC4000 is unlocked."));
} //UnlockDevice
/******************************************************************************
*
* 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
StopDevice(fdo);
// Let lower-level drivers handle this request & ignore the result
status = DefaultPnpHandler(fdo,pIrp);
IoSetDeviceInterfaceState(&pdx->InterfaceName, FALSE);
RtlFreeUnicodeString(&pdx->InterfaceName);
// Detach device from the device object stack
if (pdx->pLowerDeviceObject)
{
IoDetachDevice(pdx->pLowerDeviceObject);
}
KdPrint((DBG_NAME "Deleting device object...\n"));
// Delete the functional device object
IoDeleteDevice(fdo);
KdPrint((DBG_NAME "PDC4000 is removed.\n"));
return status;
} //HandleRemoveDevice
/***********************************************************
*
* Function : CompleteRequestInfo
*
* Description : Complete the request with infomation.
*
************************************************************/
#pragma code_seg("PAGE") // start PAGE section
NTSTATUS CompleteRequestInfo(IN PIRP Irp,
IN NTSTATUS status,
IN ULONG_PTR info)
{ // CompleteRequestInfo
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = info;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
} // CompleteRequestInfo
/***********************************************************
*
* Function : CompleteRequestInfo
*
* Description : Complete the request without infomation.
*
************************************************************/
NTSTATUS CompleteRequest(IN PIRP Irp,
IN NTSTATUS status)
{ // CompleteRequest
Irp->IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
} // CompleteRequest
/******************************************************************************
*
* 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
#pragma code_seg() // end PAGE section
/*********************************************************************
*
* Function : EnablePciInterrupt
*
* Description: Enables the PLX Chip PCI Interrupt
*
**********************************************************************/
BOOLEAN EnablePciInterrupt(IN PDEVICE_EXTENSION pdx)
{ //EnablePciInterrupt
ULONG lRegInterrupt;
ULONG lAddress;
LockDevice(pdx);
lAddress=(ULONG)pdx->LocalRegisterMemBase;
lRegInterrupt = READ_REGISTER_ULONG((ULONG *)(lAddress + PCI9054_INT_CTRL_STAT));
lRegInterrupt |= 0x100;
WRITE_REGISTER_ULONG((ULONG *)(lAddress + PCI9054_INT_CTRL_STAT), lRegInterrupt);
UnlockDevice(pdx);
return TRUE;
} //EnablePciInterrupt
/*********************************************************************
*
* Function : DisablePciInterrupt
*
* Description: Disables the PLX Chip PCI Interrupt
*
**********************************************************************/
BOOLEAN DisablePciInterrupt(IN PDEVICE_EXTENSION pdx)
{ //DisablePciInterrupt
ULONG lRegInterrupt;
ULONG lAddress;
LockDevice(pdx);
lAddress=(ULONG)pdx->LocalRegisterMemBase;
lRegInterrupt = READ_REGISTER_ULONG((ULONG *)(lAddress + PCI9054_INT_CTRL_STAT));
// KdPrint((DBG_NAME "The interrupt register is 0x%x.",RegInterrupt);
lRegInterrupt &= ~(0x40);
WRITE_REGISTER_ULONG((ULONG *)(lAddress +0x4c), lRegInterrupt);
// KdPrint((DBG_NAME "The interrupt register is 0x%x.",RegInterrupt);
UnlockDevice(pdx);
return TRUE;
} //DisablePciInterrupt
/******************************************************************************
*
* Function : ForwardAndWait
*
* Description: Forward request to lower level and await completion, used
* in PnP's IRP_MN_START_DEVICE
*
******************************************************************************/
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. It's a little known fact that the
// kernel stack *can* be paged, but only while someone is waiting in user
// mode for an event to finish. Since neither we nor a completion routine
// can be in the forbidden state, it's okay to put the event object on the
// stack.
KeInitializeEvent(&event,NotificationEvent,FALSE);
KdPrint((DBG_NAME "ForwardAndWait Start.\n"));
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
KeWaitForSingleObject((PVOID)&event,Executive,KernelMode,FALSE,NULL);
return pIrp->IoStatus.Status;
}
KdPrint((DBG_NAME "ForwardAndWait End.\n"));
return pIrp->IoStatus.Status; //status;
} // ForwardAndWait
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -