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

📄 pnp.cpp

📁 vc开发的PCI总线加密卡 PCI开发卡主要由PCI9054、93C56、16M晶振和相应的跳线、控制地址数据线等部分组成。PCI9054是PLX公司的PCI主模式桥芯片
💻 CPP
📖 第 1 页 / 共 3 页
字号:
	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 + -