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

📄 dispatch.cpp

📁 98下的PCI驱动源代码!希望对各位有所帮助 只要稍微修改就可以成为2000的驱动了!
💻 CPP
字号:
/******************************************************************************
 * * File Name:
 * *      Dispatch.cpp
 * * Description:
 * *      This file routes incoming I/O Request packets.
 * *		该文件是处理IRP的。
 * * Revision History:
 * *      03-3-02 : PDC1000 v1.00
 *******************************************************************************/

#include "PDC1000.h"
#include "Ioctl.h"

/******************************************************************************
 *
 * Function   :  DispatchCreate
 *
 * Description:  Handle IRP_MJ_CREATE, which allows applications to open handles
 *               to our device, 相应的是函数CreateFile().
 *
 ******************************************************************************/
NTSTATUS DispatchCreate(IN PDEVICE_OBJECT fdo,
						IN PIRP pIrp)
{											//DispatchCreate
    DebugPrint("PDC1000: CreateFile.");
	//可以在此,做一些初始化工作
    return CompleteRequestInfo(pIrp, STATUS_SUCCESS,0);
}											//DispatchCreate
/******************************************************************************
 *
 * Function   :  DispatchCleanup
 *
 * Description:  Handle the IRP_MJ_CLEANUP IRP.
 *				 在驱动程序被暂停或卸载的时候,需要将IRP栈内所有的IRP清除掉。
 ******************************************************************************/
NTSTATUS DispatchCleanup(IN PDEVICE_OBJECT fdo,
						 IN PIRP  pIrp)
{											//DispatchCleanup
	PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)fdo->DeviceExtension;
	KIRQL OldIrql;

	DebugPrintMsg("DispatchCleanup Start.");

	IoAcquireCancelSpinLock(&OldIrql);

	// Cancel all IRPs in the I/O Manager maintained queue in device object
	PKDEVICE_QUEUE_ENTRY QueueEntry;
	//清除所有的IRP
	while( (QueueEntry=KeRemoveDeviceQueue(&fdo->DeviceQueue)) != NULL)
	{
		PIRP CancelIrp = CONTAINING_RECORD( QueueEntry, IRP, Tail.Overlay.DeviceQueueEntry);
		CancelIrp->Cancel = TRUE;
		CancelIrp->CancelIrql = OldIrql;
		CancelIrp->CancelRoutine = NULL;

		IoReleaseCancelSpinLock(OldIrql);
		DebugPrint("WdmIoDispatchCleanup: Cancelling %x %I",CancelIrp,CancelIrp);
		UnlockDevice(pdx);

		CancelIrp->IoStatus.Status = STATUS_CANCELLED;
		CancelIrp->IoStatus.Information = 0;
		IoCompleteRequest(CancelIrp,IO_NO_INCREMENT);

		IoAcquireCancelSpinLock(&OldIrql);
	}
	IoReleaseCancelSpinLock(OldIrql);

    return CompleteRequestInfo(pIrp,STATUS_SUCCESS,0);
}											//DispatchCleanup

/************************************************************************
 *
 * Function   :  DispatchClose
 *
 * Description:  Handle IRP_MJ_CLOSE, which allows applications to close handles
 *               to our device,相应的是函数CloseHandle().
 *
 ******************************************************************************/
NTSTATUS DispatchClose(IN PDEVICE_OBJECT fdo,
					   IN PIRP  pIrp)
{												//DispatchClose
	DebugPrint("PDC1000: CloseFile.");
	//进行处理
	PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)fdo->DeviceExtension;
	pdx->pWaitEvent = NULL;
	pdx->bSetWaitEvent = NULL;

    return CompleteRequestInfo(pIrp,STATUS_SUCCESS,0);
}												//DispatchClose

/******************************************************************************
 *
 * Function   :  DispatchRead
 *
 * Description:  Handle IRP_MJ_READ, which is not implemented by this driver
 *					ReadFile
 ******************************************************************************/
NTSTATUS DispatchRead(IN PDEVICE_OBJECT fdo,
					  IN PIRP pIrp)
{													//DispatchRead
	DebugPrint("Read Device Start.");
	
	ULONG ReturnedValue;

	NTSTATUS status = STATUS_SUCCESS;

	PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;
	
	ReturnedValue = 0;	//sizeof(CAN_DATA_PACKET);
	
	//将从硬件采集到的数据送给应用程序
	
	//如果不能很快处理,将IRP进行串行化,交给StartIo处理。

	DebugPrint("Read Device End.");
    
	// Just complete the request
    return CompleteRequestInfo(pIrp,status,ReturnedValue);
}													//DispatchRead

/******************************************************************************
 *
 * Function   :  DispatchWrite
 *
 * Description:  Handle the IRP_MJ_WRITE, which is not implemented by this driver
 *					WriteFile
 ******************************************************************************/
NTSTATUS DispatchWrite(IN PDEVICE_OBJECT fdo,
					   IN PIRP pIrp)
{												//DispatchWrite
	DebugPrint("Write File Start.");
	
	PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;


	//将应用程序的数据送到硬件

	//如果不能一次完成或者需要中断协助,将IRP串行化,交给StartIo处理
//	IoMarkIrpPending(pIrp);
//	IoStartPacket(fdo, pIrp, NULL, CancelIrp);
	
	DebugPrint("Write File End.");
	return STATUS_PENDING;
}												//DispatchWrite
 
/******************************************************************************
 *
 * Function   :  DispatchSystemControl
 *
 * Description:  The dispatch routine for WMI IRPs.  It does nothing except
 *               forward the IRP to the next device in the stack.
 *
 ******************************************************************************/
NTSTATUS DispatchSystemControl(IN PDEVICE_OBJECT fdo,
							   IN PIRP pIrp)
{												//DispatchSystemControl
	DebugPrint("PDC1000: SystemControl.");

    IoSkipCurrentIrpStackLocation(pIrp);

    return IoCallDriver(((DEVICE_EXTENSION *)fdo->DeviceExtension)->pLowerDeviceObject,
						pIrp);
}												//DispatchSystemControl

/******************************************************************************
 *
 * Function   :  DispatchIoControl
 *
 * Description:  Processes the IOCTL IRPs sent to this device.
 *
 * Note       :  The Fast Mutex used in this routine is left here because
 *               some multi-CPU systems hang if it is removed.  As of this time
 *               the cause for this is unknown.  Once the cause is determined,
 *               the Fast Mutex will most likely be removed in a future release.
 *               Performance may improve slightly once it is removed since the
 *               DPC_LEVEL won't continuously need to go between PASSIVE and APC.
 *
 ******************************************************************************/
NTSTATUS DispatchIoControl(IN PDEVICE_OBJECT fdo,
						   IN PIRP pIrp)
{										//DispatchIoControl
    ULONG				i;
    NTSTATUS            status;
    PDEVICE_EXTENSION	pdx;
    PIO_STACK_LOCATION  pIrpStack;
	ULONG				ReturnedValue;
	ULONG				PdcAddress;		//The base address of PDC1000

    pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;

    pIrpStack = IoGetCurrentIrpStackLocation(pIrp);


    // Assume a successful return status
    status = STATUS_SUCCESS;

    // Lock device to record usage
	LockDevice(pdx);

	DebugPrint("DeviceIoControl Start.");

    // Handle the PDC1000 specific message
	//处理DeviceIoControl。
    switch (pIrpStack->Parameters.DeviceIoControl.IoControlCode)
    {		//PDC1000 
	case IOCTL_PDC1000_REGISTER_EVENT:		//注册Event变量
		status = ObReferenceObjectByHandle(*(PHANDLE)pIrp->AssociatedIrp.SystemBuffer, 
					EVENT_MODIFY_STATE, *ExEventObjectType,
					pIrp->RequestorMode, (PVOID*)&pdx->pWaitEvent, NULL);
		if (!NT_SUCCESS(status))
		{
			pdx->bSetWaitEvent = FALSE;
			DebugPrint("WARNNING - ObReferenceObjectByHandle failed");
		}
		else 
		{
			pdx->bSetWaitEvent = TRUE;
			DebugPrint("OK - ObReferenceObjectByHandle succeed");
		}
		ReturnedValue = 0;
		break;
	case IOCTL_PDC1000_UNREGISTER_EVENT:	//反注册Event变量
		pdx->pWaitEvent = NULL;
		pdx->bSetWaitEvent = FALSE;
		ReturnedValue = 0;
		break;
	case IOCTL_PDC1000_READ_DATA:	
		unsigned char Num,Buffer;
		
		PdcAddress = (ULONG)pdx->PdcMemBase;

		RtlCopyMemory(&Num, pIrp->AssociatedIrp.SystemBuffer, 1);
		DebugPrint("Input Value is %x.",Num);
		Buffer = READ_REGISTER_UCHAR((unsigned char *)(PdcAddress + Num));
		DebugPrint("Read Data Value is %x.",Buffer);
		RtlCopyMemory( pIrp->AssociatedIrp.SystemBuffer,&Buffer,1);
		ReturnedValue = 1;
		break;
	case IOCTL_PDC1000_WRITE_DATA:
		unsigned char WriteBuffer[2];
		
		PdcAddress = (ULONG)pdx->PdcMemBase;

		RtlCopyMemory(WriteBuffer, pIrp->AssociatedIrp.SystemBuffer, 2);

		WRITE_REGISTER_UCHAR((unsigned char *)(PdcAddress + WriteBuffer[0]), WriteBuffer[1]);
		DebugPrint("Write Data Value is %x.", WriteBuffer[1]);

		ReturnedValue = 0;
		break;
	case IOCTL_PDC1000_SELECT_8155MIO:	
		//通过PCI9052的User0,进行选择
		unsigned char Selected;
		ULONG Address;
		ULONG TempData;
		Address = (ULONG)((PDEVICE_EXTENSION)pdx)->MemBase;
		RtlCopyMemory(&Selected, pIrp->AssociatedIrp.SystemBuffer, 1);

		TempData = READ_REGISTER_ULONG((ULONG *)(Address + 0x50));
		if (Selected == 0x00)
		{
			TempData &= 0xfffffffa;
		}
		else if(Selected == 0x01)
		{
			TempData |= 0x00000006;
		}

		WRITE_REGISTER_ULONG((ULONG *)(Address + 0x50), TempData);

		ReturnedValue = 0;
		break;
	default:
        break;
    }

    UnlockDevice(pdx);

	DebugPrint("DeviceIoControl End.");

    if (status == STATUS_PENDING)
        return STATUS_PENDING;

    return CompleteRequestInfo(pIrp,status,ReturnedValue);
}												//DispatchIoControl
/******************************************************************************
 *
 * Function   :  StartIo
 *
 * Description:  The StartIo Service Routine for PDC1000.
 *
 ******************************************************************************/
VOID StartIo(IN PDEVICE_OBJECT fdo,
			 IN PIRP pIrp)
{												//StartIo
	PDEVICE_EXTENSION pdx			= (PDEVICE_EXTENSION)fdo->DeviceExtension;
	PIO_STACK_LOCATION pIrpStack	= IoGetCurrentIrpStackLocation(pIrp);

	DebugPrint("StartIo Start.");

	NTSTATUS status = STATUS_SUCCESS;

	if (!LockDevice(pdx))
	{
		CompleteRequest(pIrp, STATUS_DELETE_PENDING);
	}

	// Switch on the IRP major function code
	switch(pIrpStack->MajorFunction)
	{
	case IRP_MJ_WRITE:
		
		pdx->TransmitIrpStatus = STATUS_SUCCESS;

		break;
	default:
		status = STATUS_NOT_SUPPORTED;
		break;
	}

	// Complete this IRP
	if(pIrp->Cancel) 
		status = STATUS_CANCELLED;

	// Remove cancel routine
	KIRQL OldIrql;
	IoAcquireCancelSpinLock( &OldIrql);
	IoSetCancelRoutine(pIrp, NULL);
	IoReleaseCancelSpinLock(OldIrql);

	// Unlock device, complete IRP and start next
	UnlockDevice(pdx);

	DebugPrint("StartIo End.");

	CompleteRequestInfo(pIrp, status, 10);
	IoStartNextPacket(fdo, TRUE);

}												//StartIo
/******************************************************************************
 *
 * Function   :  CancelIrp
 *
 * Description:  The CancelIrp Service Routine for PDC1000.
 *
 ******************************************************************************/
VOID CancelIrp(IN PDEVICE_OBJECT fdo,
			   IN PIRP pIrp)
{												//CancelIrp
	PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)fdo->DeviceExtension;
	DebugPrint("WdmIoCancelIrp: Cancelling %x %I",pIrp,pIrp);

	if (pIrp == fdo->CurrentIrp)
	{
		DebugPrintMsg("CancelIrp: IRP running in StartIo");
		// IRP is being processed by IoStartIo.
		// Irp->Cancel flag already set.
		// IoStartIo will detect Cancel flag and cancel IRP in due course
		IoReleaseCancelSpinLock(pIrp->CancelIrql);
	}
	else
	{
		DebugPrintMsg("CancelIrp: IRP in StartIo queue");
		// IRP is still in StartIo device queue.
		// Just dequeue and cancel it.  No need to start next IRP.
		BOOLEAN dequeued = KeRemoveEntryDeviceQueue(
								&fdo->DeviceQueue,
								&pIrp->Tail.Overlay.DeviceQueueEntry);

		IoReleaseCancelSpinLock(pIrp->CancelIrql);

		if (dequeued)
		{
			UnlockDevice(pdx);
			CompleteRequest(pIrp, STATUS_CANCELLED);
		}
	}
}												//CancelIrp
 /******************************************************************************
 *
 * Function   :  OnInterrupt
 *
 * Description:  The Interrupt Service Routine for the PLX device.
 *					//中断处理函数
 *	注意:中断处理函数工作在很高地级别,需要慎重处理
 ******************************************************************************/
BOOLEAN OnInterrupt(IN PKINTERRUPT pInterrupt,
					IN PDEVICE_EXTENSION pdx)//IN PVOID pdx)	
{												//OnInterrupt
    ULONG	RegisterValue;
	ULONG	Address,CanAddress;
	UCHAR	cInterrupt;
	UCHAR	cCommand;

	Address = (ULONG)((PDEVICE_EXTENSION)pdx)->MemBase;

    // Read interrupt status register
	RegisterValue = READ_REGISTER_ULONG((ULONG *)(Address + 0x4c));
    // Check for master PCI interrupt enable
	if ((RegisterValue & 0x40) == 0)
	{
		return FALSE;		//如果不是该设备的中断,必须返回FALSE,否则系统会出问题。
	}

    // Check to see if an interrupt is active
	if (RegisterValue & ((0x4) | (0x20))) //Only LINTi1 is used.
    {		
		if (pdx->pWaitEvent != NULL)
			KeSetEvent(pdx->pWaitEvent, 0, FALSE);	//通知应用程序,中断的到来
		//在此,处理中断

		//如果不能很快处理,则交给Dpc处理,如下:
	/*	PDEVICE_OBJECT fdo	= ((PDEVICE_EXTENSION)pdx)->pDeviceObject;
		if (fdo != NULL)
		{
			PIRP pIrp			= fdo->CurrentIrp;
			if (pIrp != NULL)
			{
				IoRequestDpc(fdo, pIrp, (PVOID)pdx);
			}
		}
	*/
        return TRUE;	//如果是该设备的中断,必须返回TRUE。
    }

    // If we reach here, then the interrupt is not ours
	return FALSE;
}												//OnInterrupt

/******************************************************************************
 *
 * Function   :  DpcForIsr
 *
 * Description:  This routine will be triggered by the ISR to service an interrupt.
 *
 * Note       :  The 9052 supports Edge-triggerable interrupts as well as level
 *               triggered interrupts.  The 9050 only supports level triggered
 *               interrupts.  The interrupt masking code below handles both cases.
 *               If the chip is a 9050, the same code is used but should work
 *               ok since edge triggerable interrupts will always be disabled.
 *
 ******************************************************************************/
VOID DpcForIsr(IN PKDPC pDpc,
			   IN PDEVICE_OBJECT fdo,
			   IN PIRP pIrp, 
			   IN PDEVICE_EXTENSION pdx)
{												//OnInterrupt DpcForIsr
	DebugPrintMsg("DpcForIsr Start.");
	
	if (pIrp->Cancel)
		pdx->TransmitIrpStatus = STATUS_CANCELLED;

	KIRQL OldIrql;

	PIRP Irp = fdo->CurrentIrp;

	//Remove Cancel Routine.
	IoAcquireCancelSpinLock(&OldIrql);
	IoSetCancelRoutine(pIrp,NULL);
	IoReleaseCancelSpinLock(OldIrql);

	UnlockDevice(pdx);

	DebugPrintMsg("DpcForIsr End.");

	IoStartNextPacket(fdo, FALSE);

}												//OnInterrupt DpcForIsr


⌨️ 快捷键说明

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