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

📄 readwrite.cpp

📁 Programming the Microsoft Windows driver model.2nd 随书光盘。内有很多作者送的实用工具和随书源码。WDM编程
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// Read/Write request processors for pktdma driver

// Copyright (C) 1999 by Walter Oney

// All rights reserved



#include "stddcls.h"

#include "driver.h"

#include "s5933.h"



VOID OnCancelReadWrite(PDEVICE_OBJECT fdo, PIRP Irp);

IO_ALLOCATION_ACTION AdapterControl(PDEVICE_OBJECT fdo, PIRP Irp, PVOID regbase, PDEVICE_EXTENSION pdx);

VOID StartTransfer(PDEVICE_EXTENSION pdx, PHYSICAL_ADDRESS address, BOOLEAN isread);



///////////////////////////////////////////////////////////////////////////////



#pragma LOCKEDCODE



IO_ALLOCATION_ACTION AdapterControl(PDEVICE_OBJECT fdo, PIRP junk, PVOID regbase, PDEVICE_EXTENSION pdx)

	{							// AdapterControl

	PIRP Irp = GetCurrentIrp(&pdx->dqReadWrite);

	PMDL mdl = Irp->MdlAddress;

	BOOLEAN isread = IoGetCurrentIrpStackLocation(Irp)->MajorFunction == IRP_MJ_READ;

	pdx->regbase = regbase;

	KeFlushIoBuffers(mdl, isread, TRUE);

	PHYSICAL_ADDRESS address = (*pdx->AdapterObject->DmaOperations->MapTransfer)

		(pdx->AdapterObject, mdl, regbase, pdx->vaddr, &pdx->xfer, !isread);



	StartTransfer(pdx, address, isread);



	return DeallocateObjectKeepRegisters;

	}							// AdapterControl



///////////////////////////////////////////////////////////////////////////////



#pragma PAGEDCODE



NTSTATUS DispatchCleanup(PDEVICE_OBJECT fdo, PIRP Irp)

	{							// DispatchCleanup

	PAGED_CODE();

	KdPrint((DRIVERNAME " - IRP_MJ_CLEANUP\n"));

	PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;

	PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);

	CleanupRequests(&pdx->dqReadWrite, stack->FileObject, STATUS_CANCELLED);

	return CompleteRequest(Irp, STATUS_SUCCESS, 0);

	}							// DispatchCleanup



///////////////////////////////////////////////////////////////////////////////



#pragma PAGEDCODE



NTSTATUS DispatchCreate(PDEVICE_OBJECT fdo, PIRP Irp)

	{							// DispatchCreate

	PAGED_CODE();

	KdPrint((DRIVERNAME " - IRP_MJ_CREATE\n"));

	PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;



	PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);



	NTSTATUS status = STATUS_SUCCESS;

	InterlockedIncrement(&pdx->handles);

	return CompleteRequest(Irp, status, 0);

	}							// DispatchCreate





///////////////////////////////////////////////////////////////////////////////



#pragma PAGEDCODE



NTSTATUS DispatchClose(PDEVICE_OBJECT fdo, PIRP Irp)

	{							// DispatchClose

	PAGED_CODE();

	KdPrint((DRIVERNAME " - IRP_MJ_CLOSE\n"));

	PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;

	PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);

	InterlockedDecrement(&pdx->handles);

	return CompleteRequest(Irp, STATUS_SUCCESS, 0);

	}							// DispatchClose



///////////////////////////////////////////////////////////////////////////////



#pragma PAGEDCODE



NTSTATUS DispatchReadWrite(PDEVICE_OBJECT fdo, PIRP Irp)

	{							// DispatchReadWrite

	PAGED_CODE();

	PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;

	

	PMDL mdl = Irp->MdlAddress;

	if (!mdl)

		return CompleteRequest(Irp, STATUS_SUCCESS, 0);



	if ((ULONG_PTR) MmGetMdlVirtualAddress(mdl) & fdo->AlignmentRequirement)

		return CompleteRequest(Irp, STATUS_INVALID_PARAMETER, 0);



	IoMarkIrpPending(Irp);

	StartPacket(&pdx->dqReadWrite, fdo, Irp, OnCancelReadWrite);

	return STATUS_PENDING;

	}							// DispatchReadWrite



#pragma LOCKEDCODE



VOID OnCancelReadWrite(IN PDEVICE_OBJECT fdo, IN PIRP Irp)

	{							// OnCancelReadWrite

	PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;

	CancelRequest(&pdx->dqReadWrite, Irp);

	}							// OnCancelReadWrite



///////////////////////////////////////////////////////////////////////////////



#pragma LOCKEDCODE



VOID DpcForIsr(PKDPC Dpc, PDEVICE_OBJECT fdo, PIRP junk, PDEVICE_EXTENSION pdx)

	{							// DpcForIsr

	NTSTATUS status;

	PIRP Irp = GetCurrentIrp(&pdx->dqReadWrite);

	BOOLEAN isread = IoGetCurrentIrpStackLocation(Irp)->MajorFunction == IRP_MJ_READ;

	PMDL mdl = Irp->MdlAddress;



	(*pdx->AdapterObject->DmaOperations->FlushAdapterBuffers)

		(pdx->AdapterObject, mdl, pdx->regbase, pdx->vaddr, pdx->xfer, !isread);



	pdx->nbytes -= pdx->xfer;

	pdx->numxfer += pdx->xfer;



	// Fetch accumulated interrupt bits and test for an error



	ULONG intcsr = InterlockedExchange((PLONG) &pdx->intcsr, 0);

	if (intcsr & (INTCSR_MASTER_ABORT | INTCSR_TARGET_ABORT))

		status = STATUS_DATA_ERROR;

	else

		status = AreRequestsBeingAborted(&pdx->dqReadWrite);



	if (pdx->nbytes && NT_SUCCESS(status))

		{						// start next stage of transfer

		pdx->vaddr = (PVOID) ((PUCHAR) pdx->vaddr + pdx->xfer);

		pdx->xfer = pdx->nbytes;

		ULONG nregs = ADDRESS_AND_SIZE_TO_SPAN_PAGES(pdx->vaddr, pdx->nbytes);

		if (nregs > pdx->nMapRegistersAllocated)

			{

			nregs = pdx->nMapRegistersAllocated;

			pdx->xfer = nregs * PAGE_SIZE;

			}

		PHYSICAL_ADDRESS address =(*pdx->AdapterObject->DmaOperations->MapTransfer)

			(pdx->AdapterObject, mdl, pdx->regbase, pdx->vaddr, &pdx->xfer, !isread);



		StartTransfer(pdx, address, isread);

		}						// start next stage of transfer



	else

		{						// request is complete

		ULONG numxfer = pdx->numxfer;

		(*pdx->AdapterObject->DmaOperations->FreeMapRegisters)

			(pdx->AdapterObject, pdx->regbase, pdx->nMapRegistersAllocated);

		StartNextPacket(&pdx->dqReadWrite, fdo);

		CompleteRequest(Irp, status, numxfer);

		IoReleaseRemoveLock(&pdx->RemoveLock, Irp);

		}						// request is complete

	}							// DpcForIsr



///////////////////////////////////////////////////////////////////////////////



#pragma LOCKEDCODE



VOID InterlockedOr(PULONG target, ULONG mask)

	{							// InterlockedOr

#if _X86_

	_asm mov eax, target

	_asm mov ecx, mask

	_asm _emit 0xF0				; lock prefix

	_asm or [eax], ecx

#else // not _X86_

	ULONG prevval = target;

	while (TRUE)

		{

		ULONG newval = InterlockedCompareExchange(target, (prevval | mask), prevval);

		if (newval == prevval)

			break;

		prevval = newval;

		}

#endif // not _X86_

	}							// InterlockedOr



///////////////////////////////////////////////////////////////////////////////



#pragma LOCKEDCODE



BOOLEAN OnInterrupt(PKINTERRUPT InterruptObject, PDEVICE_EXTENSION pdx)

	{							// OnInterrupt



	// Read interrupt control/status register and see if an interrupt is pending.

	// If not, return FALSE immediately.



	ULONG intcsr = READ_PORT_ULONG((PULONG) (pdx->portbase + INTCSR));

	if (!(intcsr & INTCSR_INTERRUPT_PENDING))

		return FALSE;



	// Disable bus-mastering



	ULONG mcsr = READ_PORT_ULONG((PULONG) (pdx->portbase + MCSR));

	WRITE_PORT_ULONG((PULONG) (pdx->portbase + MCSR), mcsr & ~(MCSR_WRITE_ENABLE | MCSR_READ_ENABLE));



	intcsr &= ~(INTCSR_WTCI_ENABLE | INTCSR_RTCI_ENABLE); // will take effect when we rewrite INTCSR later on



	// Process pending interrupts. We're expecting an interrupt due to a transfer count

	// going to zero, but we might be getting a master or target abort instead



	while (intcsr & INTCSR_INTERRUPT_PENDING)

		{						// clear all interrupts



		InterlockedOr(&pdx->intcsr, intcsr); // merge new interrupts with old



		// Interrupt flags on the S5933 are cleared by writing a "1" bit to them,

		// so clear all the interrupts we just examined.



		WRITE_PORT_ULONG((PULONG) (pdx->portbase + INTCSR), intcsr);



		// Check for additional interrupts

		

		intcsr = READ_PORT_ULONG((PULONG) (pdx->portbase + INTCSR));

		}						// clear all interrupts



	// Request a DPC if necessary



	if (pdx->busy)

		{

		pdx->busy = FALSE;

		IoRequestDpc(pdx->DeviceObject, NULL, pdx);

		}



	return TRUE;

	}							// OnInterrupt



///////////////////////////////////////////////////////////////////////////////



#pragma PAGEDCODE



VOID ResetDevice(PDEVICE_EXTENSION pdx)

	{							// ResetDevice

	PAGED_CODE();



	// Reset the device



	WRITE_PORT_ULONG((PULONG) (pdx->portbase + MCSR), MCSR_RESET);



	// Reset signals to the S5933 itself don't need to be written back as zero. The

	// add-on function reset flag must, however, be cleared. Delay a short period of

	// time to allow the reset to occur, then write back a zero to the add-on reset bit



	LARGE_INTEGER timeout;

	timeout.QuadPart = -10 * 10000; // i.e., 10 milliseconds



	KeDelayExecutionThread(KernelMode, FALSE, &timeout);

	WRITE_PORT_ULONG((PULONG) (pdx->portbase + MCSR), 0);

⌨️ 快捷键说明

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