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

📄 pnp.cpp

📁 这是一个用PLX9052PCI控制芯片桥接PCI的示范程序.
💻 CPP
📖 第 1 页 / 共 2 页
字号:
				}		//PCI Bar 0
				else
				{		//PCI Bar 2, 8155 Mem map
					pdx->PdcPhysicalMemBase = ResourceRaw->u.Memory.Start;
					pdx->PdcMemCount = ResourceRaw->u.Memory.Length;
					pdx->PdcMemBase = (ULONG *)MmMapIoSpace(pdx->PdcPhysicalMemBase,
						pdx->PdcMemCount,MmNonCached);
					DebugPrint("The MEM Base SJA1000 is %x;Count is %x.",pdx->PdcMemBase,pdx->PdcMemCount);
					if (pdx->PdcMemBase == NULL)
					{
						DebugPrint("ERROR - Unable to map SJA1000.\n");
						return STATUS_INSUFFICIENT_RESOURCES;
					}
					GotPdcMem = TRUE;
				}			//PCI Bar 2, 8155 Mem map
				break;
			//其他资源一般没有,可默认处理
/*			case CmResourceTypeNull:
				DebugPrint("Type: Null (unsupported)");
				break;
			case CmResourceTypeDma:
				DebugPrint("Type: DMA (unsupported)");
				break;
			case CmResourceTypeDeviceSpecific:
				DebugPrint("Type: Device Specific (unsupported)");
				break;
			case CmResourceTypeBusNumber:
				DebugPrint("Type: Bus Number (unsupported)\n");
				break;
			// NonArbitrated & ConfigData are currently #defined as the same number
			case CmResourceTypeConfigData:
				DebugPrint("Type: Non-Arbitrated or Config Data (unsupported)");
				break;
			case CmResourceTypeDevicePrivate:
				DebugPrint(" Type: Device Private Data (unsupported)");
				break;
			case CmResourceTypePcCardConfig:
				DebugPrint("Type: PC Card Configuration (unsupported)");
				break;
			case CmResourceTypeMfCardConfig:
				DebugPrint("Type: Multi-function Card Configuration (unsupported)");
				break;
*/
			default:
				DebugPrint("Type: ?Unknown Resource Type?");
				break;
        }
    }

    // Make sure BAR 0 exists or the device can't be started
	if (!GotBaseMem)
	{
		DebugPrint("PCI9052Demo: ERROR - BAR 0 address not configured, unable to load driver.");
		return STATUS_INSUFFICIENT_RESOURCES;	
	}
	if (!GotPdcMem)
	{
		if(pdx->MemBase)
		{
			MmUnmapIoSpace(pdx->MemBase,pdx->MemCount);		//Free Base Memory.
			DebugPrint("PCI9052Demo: ERROR - CanMemBase.");
		}
		return STATUS_INSUFFICIENT_RESOURCES;
	}
	//连接中断
    if (GotInterrupt)
    {
		DebugPrint("Get Interrupt.");
        // 首先Disable the PCI interrupt
		DisablePciInterrupt(pdx);
		//连接中断
		status = IoConnectInterrupt(&pdx->pInterruptObject,(PKSERVICE_ROUTINE)OnInterrupt,
						(PVOID)pdx,NULL,vector,IrqL,IrqL,mode,irqshare,affinity,FALSE);	//(PVOID)
		DebugPrint("OK, I haved Connect Interruput!");
		if (!NT_SUCCESS(status))
		{
			pdx->pInterruptObject = NULL;
			return status;
		}
		else
        {	// Re-enable the PCI Interrupt
			DebugPrint("OK, Let's enable interrupt.");
			if (pdx->pInterruptObject == NULL)
			{
				DebugPrint("Interrupt object is NULL.");
			}
			//同步Enable interrupt.
			KeSynchronizeExecution(pdx->pInterruptObject,(PKSYNCHRONIZE_ROUTINE)EnablePciInterrupt,pdx);
			DebugPrint("Have Enabled Interrupt.");
		}
    }
    else
    {
        DebugPrint("PCI9052Demo: No interrupt found.");
		//Free haved mapped memories.
		MmUnmapIoSpace(pdx->MemBase,pdx->MemCount);
		MmUnmapIoSpace(pdx->PdcMemBase,pdx->PdcMemCount);
        pdx->pInterruptObject = NULL;
    }

	pdx->GotResource=TRUE;
	DebugPrint("Start Device end.");
    return STATUS_SUCCESS;
}												//StartDevice

/******************************************************************************
 *
 * Function   :  HandleStopDevice
 *
 * Description:  Handle the IRP_MN_STOP_DEVICE PnP request
 *
 ******************************************************************************/
NTSTATUS PnpStopDevice(IN PDEVICE_OBJECT fdo,
					   IN PIRP pIrp)
{	

    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;
	KeResetEvent(&pdx->StoppingEvent);
	UnlockDevice(pdx);	//必须UnlockDevice两次
	UnlockDevice(pdx);
	
	KeWaitForSingleObject( &pdx->StoppingEvent, Executive, KernelMode, FALSE, NULL);
	DebugPrint("PnpStopDevice: All pending I/O completed");
	pdx->bStopping = FALSE;

	pdx->GotResource = FALSE;

	DebugPrint("PCI9052Demo is being stopped...");
	
	//等待全部的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->MemBase)
		MmUnmapIoSpace(pdx->MemBase,pdx->MemCount);
	if(pdx->PdcMemBase)
		MmUnmapIoSpace(pdx->PdcMemBase,pdx->PdcMemCount);
	pdx->MemBase=NULL;
	pdx->MemCount=0;
	pdx->PdcMemBase=NULL;
	pdx->PdcMemCount=0;

	// Bump usage count back up again
	LockDevice(pdx);
	LockDevice(pdx);

	DebugPrint("PCI9052Demo is stopped.");
}												//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);

//	DebugPrint("PCI9052Demo: 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;
    }
//	DebugPrint("PCI9052Demo is locked.");
    return TRUE;
}												//LockDevice

/******************************************************************************
 *
 * Function   :  UnlockDevice
 *
 * Description:  Unlock a device.
 *
 ******************************************************************************/
VOID UnlockDevice(IN DEVICE_EXTENSION *pdx)
{												//UnlockDevice
	LONG UsageCount = InterlockedDecrement(&pdx->UsageCount);
	
//	DebugPrint("PCI9052Demo is unlocking...");

    KdPrint(("PCI9052Demo: UNLOCKING... (usage = %d)\n", UsageCount));

    if (UsageCount == 0)
    {
        // Stopping device
		KeSetEvent(&pdx->StoppingEvent,0,FALSE);
    }
//	DebugPrint("PCI9052Demo 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);
    }

    DebugPrint("PCI9052Demo: Deleting device object...");

    // Delete the functional device object
    IoDeleteDevice(fdo);

	DebugPrint("PCI9052Demo is removed.");

    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 RegInterrupt;
	ULONG Address;

	LockDevice(pdx);

	Address=(ULONG)pdx->MemBase;
	RegInterrupt = READ_REGISTER_ULONG((ULONG *)(Address + 0x4c));
	RegInterrupt |= 0x40;
	WRITE_REGISTER_ULONG((ULONG *)(Address +0x4c),RegInterrupt);

	UnlockDevice(pdx);

	return TRUE;
}												//EnablePciInterrupt

/*********************************************************************
*
* Function   :  DisablePciInterrupt
*
* Description:  Disables the PLX Chip PCI Interrupt
*
**********************************************************************/
BOOLEAN DisablePciInterrupt(IN PDEVICE_EXTENSION pdx)
{												//DisablePciInterrupt
    ULONG RegInterrupt;
	ULONG Address;

	LockDevice(pdx);
	Address=(ULONG)pdx->MemBase;
    RegInterrupt = READ_REGISTER_ULONG((ULONG *)(Address + 0x4c));
//	DebugPrint("The interrupt register is 0x%x.",RegInterrupt);
	RegInterrupt &= ~(0x40);
    WRITE_REGISTER_ULONG((ULONG *)(Address +0x4c),RegInterrupt);
//	DebugPrint("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);

	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
        KeWaitForSingleObject((PVOID)&event,Executive,KernelMode,FALSE,NULL);

        return pIrp->IoStatus.Status;
    }
	DebugPrint("ForwardAndWait End.");
    return pIrp->IoStatus.Status;	//status;
}													// ForwardAndWait


⌨️ 快捷键说明

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