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

📄 ioctl.c

📁 WinBond W83627 看门狗驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
    default:      
        return STATUS_INVALID_PARAMETER;
    }

    if ( InBufferSize < (sizeof(ULONG) + DataBufferSize) )
    {
		DebugPrint (("error in InBufferSize\n"));
        return STATUS_INVALID_PARAMETER;
    }

	pde->PortNumber = *pIOBuffer++;		// PortNumber in IOBuffer union
	
    if (pde->PortMemoryType == 1)
    {
        // Address is in I/O space
        
        switch (IoctlCode)
        {
        case IOCTL_WDT_WRITE_PORT_UCHAR:
            WRITE_PORT_UCHAR(
                (PUCHAR)((ULONG_PTR)pde->PortNumber),
                *(PUCHAR)pIOBuffer );
            break;
        case IOCTL_WDT_WRITE_PORT_USHORT:
            WRITE_PORT_USHORT(
                (PUSHORT)((ULONG_PTR)pde->PortNumber),
                *(PUSHORT)pIOBuffer );
            break;
        case IOCTL_WDT_WRITE_PORT_ULONG:
            WRITE_PORT_ULONG(
                (PULONG)((ULONG_PTR)pde->PortNumber),
                *(PULONG)pIOBuffer );
            break;
        default:      
            return STATUS_INVALID_PARAMETER;
        }
    } 
    else if (pde->PortMemoryType == 0) 
    {
        // Address is in Memory space
        
        switch (IoctlCode)
        {
        case IOCTL_WDT_WRITE_PORT_UCHAR:
            WRITE_REGISTER_UCHAR( 
                    (PUCHAR)((ULONG_PTR)pde->PortNumber),
                    *(PUCHAR)pIOBuffer );
            break;
        case IOCTL_WDT_WRITE_PORT_USHORT:
            WRITE_REGISTER_USHORT(
                    (PUSHORT)((ULONG_PTR)pde->PortNumber),
                    *(PUSHORT)pIOBuffer );
            break;
        case IOCTL_WDT_WRITE_PORT_ULONG:
            WRITE_REGISTER_ULONG(
                    (PULONG)((ULONG_PTR)pde->PortNumber),
                    *(PULONG)pIOBuffer );
            break;
        default:      
            return STATUS_INVALID_PARAMETER;
        }
    }
    else
    {
        return STATUS_UNSUCCESSFUL;
    }

    //
    // Indicate # of bytes written,set Irp->IoStatus.Information
    //
	CompleteIoReq(Irp,STATUS_SUCCESS,DataBufferSize);

    return STATUS_SUCCESS;
}


NTSTATUS
WDTIoctlGetHardwareID(
	IN PDEVICE_EXTENSION pde,
	IN PIRP Irp,
	IN PIO_STACK_LOCATION IrpStack
	)
{
								// NOTE:  Use METHOD_BUFFERED ioctls.
    PULONG pIOBuffer;           // Pointer to transfer buffer
                                //      (treated as an array of longs).
	ULONG OutBufferSize;        // Max data that caller can accept.
	ULONG DataBufferSize;

	// Size of buffer for data to be sent to application
    OutBufferSize = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
	DataBufferSize = sizeof(ULONG);

    // NT copies inbuf here before entry and copies this to outbuf after
    // return, for METHOD_BUFFERED IOCTL's.
    pIOBuffer = (PULONG)Irp->AssociatedIrp.SystemBuffer;

	 if ( OutBufferSize < DataBufferSize )
    {
        return STATUS_INVALID_PARAMETER;
    }	 

	*pIOBuffer = (ULONG)pde->HardwareID;
	
	// set Irp->IoStatus.Information
	CompleteIoReq(Irp,STATUS_SUCCESS,DataBufferSize);

	return STATUS_SUCCESS;

}


NTSTATUS
WDTIoctlGetPortIndex(
	IN PDEVICE_EXTENSION pde,
	IN PIRP Irp,
	IN PIO_STACK_LOCATION IrpStack
	)
{
									// NOTE:  Use METHOD_BUFFERED ioctls.
    PULONG pIOBuffer;           // Pointer to transfer buffer
                                //      (treated as an array of longs).
	ULONG OutBufferSize;        // Max data that caller can accept.
	ULONG DataBufferSize;

	// Size of buffer for data to be sent to application
    OutBufferSize = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
	DataBufferSize = sizeof(ULONG);

    // NT copies inbuf here before entry and copies this to outbuf after
    // return, for METHOD_BUFFERED IOCTL's.
    pIOBuffer = (PULONG)Irp->AssociatedIrp.SystemBuffer;

	 if ( OutBufferSize < DataBufferSize )
    {
        return STATUS_INVALID_PARAMETER;
    }	 

	if(pde->HardwareID == 0x97)
	{
		*pIOBuffer = (ULONG)pde->ShortPortIndex;
	}
	if((pde->HardwareID == 0x52) || (pde->HardwareID ==0x82) || 
		(pde->HardwareID == 0x88) || (pde->HardwareID == 0xA0))
	{
		*pIOBuffer = (ULONG)pde->PortIndex;
	}
	
	// set Irp->IoStatus.Information
	CompleteIoReq(Irp,STATUS_SUCCESS,DataBufferSize);

	return STATUS_SUCCESS;
}


NTSTATUS
WDTIoctlGetPortData(
	IN PDEVICE_EXTENSION pde,
	IN PIRP Irp,
	IN PIO_STACK_LOCATION IrpStack
	)
{
										// NOTE:  Use METHOD_BUFFERED ioctls.
    PULONG pIOBuffer;           // Pointer to transfer buffer
                                //      (treated as an array of longs).
	ULONG OutBufferSize;        // Max data that caller can accept.
	ULONG DataBufferSize;

	// Size of buffer for data to be sent to application
    OutBufferSize = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
	DataBufferSize = sizeof(ULONG);

    // NT copies inbuf here before entry and copies this to outbuf after
    // return, for METHOD_BUFFERED IOCTL's.
    pIOBuffer = (PULONG)Irp->AssociatedIrp.SystemBuffer;

	 if ( OutBufferSize < DataBufferSize )
    {
        return STATUS_INVALID_PARAMETER;
    }	 

	if(pde->HardwareID == 0x97)
	{
		*pIOBuffer = (ULONG)pde->ShortPortData;
	}
	if((pde->HardwareID == 0x52) || (pde->HardwareID ==0x82) || 
		(pde->HardwareID == 0x88) || (pde->HardwareID == 0xA0))
	{
		*pIOBuffer = (ULONG)pde->PortData;
	}
	
	// set Irp->IoStatus.Information
	CompleteIoReq(Irp,STATUS_SUCCESS,DataBufferSize);

	return STATUS_SUCCESS;
}


NTSTATUS
IRQSearchAuto(
	IN PDEVICE_OBJECT fdo,
	IN PIRP Irp,
	IN PIO_STACK_LOCATION IrpStack
	)
{
	NTSTATUS	status;
	PDEVICE_EXTENSION pde = (PDEVICE_EXTENSION)fdo->DeviceExtension;
								// NOTE:  Use METHOD_BUFFERED ioctls.
    PULONG pIOBuffer;           // Pointer to transfer buffer
                                //      (treated as an array of longs).
	ULONG OutBufferSize;        // Max data that caller can accept.
	ULONG DataBufferSize;
	ULONG irq=7;

	// Size of buffer for data to be sent to application
    OutBufferSize = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
	DataBufferSize = sizeof(ULONG);

    // NT copies inbuf here before entry and copies this to outbuf after
    // return, for METHOD_BUFFERED IOCTL's.
    pIOBuffer = (PULONG)Irp->AssociatedIrp.SystemBuffer;

	 if ( OutBufferSize < DataBufferSize )
    {
        return STATUS_INVALID_PARAMETER;
    }
	 
	// Search IRQ automatic.
	for(irq=3;irq<16;irq++)
	{
		if(irq==8 || irq==13)
		{
			continue;
		}
		pde->Irq = irq;
		pde->Irql = (KIRQL)irq;

		// Claim resources
		status = ClaimResources(fdo);
		if(!NT_SUCCESS(status))
		{
			DebugPrint(("Could not ClaimResources\n"));
			*pIOBuffer = IRQ_SEARCH_AUTO_ERROR;
			continue;
		}
		else
		{
			break;
		}
	}

	if(irq > 15)
	{
		*pIOBuffer = IRQ_SEARCH_AUTO_ERROR;
	}
	else
	{
		// Resource conflict not found
		pde->ResourcesClaimed = TRUE;

		// Translate and map resources
		status = TranslateAndMapResources(fdo);
		if(NT_SUCCESS(status))
		{
			// Disconnect from interrupt
			if( pde->ConnectedToInterrupt)
			{
				DebugPrint(("Disconnecting from interrupt\n"));
				IoDisconnectInterrupt( pde->InterruptObject);
				pde->ConnectedToInterrupt = FALSE;
			}

			DisableInterrupt(pde);
			// connect to interrupt again.
			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"));
				*pIOBuffer = IRQ_SEARCH_AUTO_ERROR;
				pde->ConnectedToInterrupt = FALSE;
			}
			else
			{
				DebugPrint(("connect interrupt ok!\n"));
				*pIOBuffer = irq;
				pde->ConnectedToInterrupt = TRUE;
				EnableInterrupt(pde);
			}
		}
		else
		{
			DebugPrint(("Could not translate resources\n"));
			UnclaimResources(fdo);
			pde->ResourcesClaimed = FALSE;
		}
	
	}
	// set Irp->IoStatus.Information
	CompleteIoReq(Irp,STATUS_SUCCESS,DataBufferSize);

	return STATUS_SUCCESS;
}


NTSTATUS
IRQUserSet(
	IN PDEVICE_OBJECT fdo,
	IN PIRP Irp,
	IN PIO_STACK_LOCATION IrpStack
	)
{
	NTSTATUS status = STATUS_SUCCESS;
	PDEVICE_EXTENSION pde = (PDEVICE_EXTENSION)fdo->DeviceExtension;
		                        // NOTE:  Use METHOD_BUFFERED ioctls.
    PULONG pIOBuffer;           // Pointer to transfer buffer
                                //      (treated as an array of longs).
    ULONG InBufferSize;         // Amount of data avail. from caller.
    ULONG OutBufferSize;        // Max data that caller can accept.
    ULONG DataBufferSize;
	
	// Size of buffer containing data from application
    InBufferSize  = IrpStack->Parameters.DeviceIoControl.InputBufferLength;

    // Size of buffer for data to be sent to application
    OutBufferSize = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;

	DataBufferSize = sizeof(ULONG);

    // NT copies inbuf here before entry and copies this to outbuf after
    // return, for METHOD_BUFFERED IOCTL's.
    pIOBuffer = (PULONG)Irp->AssociatedIrp.SystemBuffer;

	if ( OutBufferSize < DataBufferSize )
    {
        return STATUS_INVALID_PARAMETER;
    }
	pde->Irq = *pIOBuffer;
	pde->Irql = (KIRQL)*pIOBuffer;
	
	// Claim resources
	status = ClaimResources(fdo);
	if(NT_SUCCESS(status))
	{
		// Resource conflict not found
		pde->ResourcesClaimed = TRUE;

		// Translate and map resources
		status = TranslateAndMapResources(fdo);
		if(NT_SUCCESS(status))
		{
			// Disconnect from interrupt
			if( pde->ConnectedToInterrupt)
			{
				DebugPrint(("Disconnecting from interrupt\n"));
				IoDisconnectInterrupt( pde->InterruptObject);
				pde->ConnectedToInterrupt = FALSE;
			}

			DisableInterrupt(pde);
			// connect to interrupt again.
		
			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"));
				*pIOBuffer = IRQ_INVALID;
				pde->ConnectedToInterrupt = FALSE;
			}
			else
			{
				*pIOBuffer = IRQ_VALID;
				pde->ConnectedToInterrupt = TRUE;
				EnableInterrupt(pde);
			}
		}
		else
		{
			DebugPrint(("Could not translate resources\n"));
			UnclaimResources(fdo);
			pde->ResourcesClaimed = FALSE;
		}
	}
	else
	{
		*pIOBuffer = IRQ_INVALID;
		DebugPrint(("Could not ClaimResources\n"));
	}
	// set Irp->IoStatus.Information
	CompleteIoReq(Irp,STATUS_SUCCESS,DataBufferSize);

	return STATUS_SUCCESS;
}


//	ClaimResources:	Ask kernel to give is the resources we want

NTSTATUS ClaimResources( IN PDEVICE_OBJECT fdo)
{
	NTSTATUS status = STATUS_SUCCESS;
	PDEVICE_EXTENSION pde;

	ULONG ListSize;
	PCM_RESOURCE_LIST ResourceList;
	PCM_PARTIAL_RESOURCE_DESCRIPTOR resource;
	PCM_FULL_RESOURCE_DESCRIPTOR FullRD;
	BOOLEAN ConflictDetected;
	// Get resource count: either 1 (IOport) or 2 (IOport&IRQ)
	ULONG PartialResourceCount = 1;
	//PartialResourceCount++;
	pde = fdo->DeviceExtension;

	// Get size of required CM_RESOURCE_LIST
	ListSize = FIELD_OFFSET( CM_RESOURCE_LIST, List[0]);

	ListSize += sizeof( CM_FULL_RESOURCE_DESCRIPTOR) +
				((PartialResourceCount-1) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));

	// Allocate CM_RESOURCE_LIST
	ResourceList = (PCM_RESOURCE_LIST)ExAllocatePool( PagedPool, ListSize);
	if( ResourceList==NULL)
	{
		DebugPrint(("Cannot allocate memory for ResourceList"));
		return STATUS_INSUFFICIENT_RESOURCES;
	}
	RtlZeroMemory( ResourceList, ListSize);

	// Only one Full Resource Descriptor needed, for ISA
	ResourceList->Count = 1;

	// Initialise Full Resource Descriptor
	FullRD = &ResourceList->List[0];
	FullRD->InterfaceType = Isa;
	FullRD->BusNumber = 0;

	FullRD->PartialResourceList.Count = PartialResourceCount;

	
	// Initialise Partial Resource Descriptor for Interrupt
	resource = &FullRD->PartialResourceList.PartialDescriptors[0];
	//resource++;
	resource->Type = CmResourceTypeInterrupt;
	resource->ShareDisposition = CmResourceShareDriverExclusive;
	pde->Mode = Latched;
	//resource->Flags = CM_RESOURCE_INTERRUPT_LATCHED;
	resource->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
	resource->u.Interrupt.Level = pde->Irql;
	resource->u.Interrupt.Vector = pde->Irql;
	resource->u.Interrupt.Affinity = 1;


	// Ask for resources for the driver
	//DebugPrint(("Allocating %d resources"),PartialResourceCount);
	//DebugPrint(("fdo->DriverObject %x"),fdo->DriverObject);
	
	status = IoReportResourceUsage( NULL,
						fdo->DriverObject, ResourceList, ListSize,	// Driver resources
						NULL, NULL, 0,	// Device resources
						FALSE, &ConflictDetected);
	// Cope (or override) if resource conflict found
	if( ConflictDetected)
	{
		DebugPrint(("Conflict Detected\n"));
		// NT4 returns STATUS_SUCCESS;  W2000 returns !NT_SUCCESS
		// Free allocated memory
		ExFreePool(ResourceList);
		//return STATUS_SUCCESS;
	}
	return status;
}


//	UnclaimResources:	Release our resources back to the system

void UnclaimResources( IN PDEVICE_OBJECT fdo)
{
	//DebugPrint(("Freeing all allocated resources\n"));
	BOOLEAN ConflictDetected;
	CM_RESOURCE_LIST ResourceList;

	// Release all driver's resources by declaring we have none.
	ResourceList.Count = 0;
	
	IoReportResourceUsage( NULL,
					fdo->DriverObject, &ResourceList, sizeof(ResourceList),	// Driver resources
					NULL, NULL, 0,	// Device resources
					FALSE, &ConflictDetected);
	// ignore return result
}

//	TranslateAndMapResources:	Translate and map our resources

NTSTATUS TranslateAndMapResources( IN PDEVICE_OBJECT fdo)
{
	PDEVICE_EXTENSION pde = (PDEVICE_EXTENSION)fdo->DeviceExtension;

	// Translate IRQ values
	ULONG irq = pde->Irql;
	pde->Vector = HalGetInterruptVector( Isa, 0, irq, irq, &pde->Irql, &pde->Affinity);
	if( pde->Vector==0)
	{
		//DebugPrint(("Create filename: Could not get interrupt vector for IRQ %x\n"), irq);
		return STATUS_INVALID_PARAMETER;
	}
	/*DebugPrint(("Interrupt vector %x IRQL %x Affinity %x Mode %x\n"),
						pde->Vector, pde->Irql, pde->Affinity, pde->Mode);*/
	return STATUS_SUCCESS;
}

⌨️ 快捷键说明

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