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

📄 driverentry.cpp

📁 The PCI Local bus concept was developed to break the PC data I/O bottleneck and clearly opens the d
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*

DriverEntry.cpp

Sheldon Instruments, Inc.

Abstract:

	Update of the SI-DDK using WDM.

Revision History:

	01Dec1998 - created by Robert Updike
	15Mar2000 - added ForwardAndWait function Robert Updike
	16Mar2000 - added support functions for the device queue Robert Updike
	20Mar2000 - added IRP_MJ_CLEANUP to DriverEntry Robert Updike

*/

#include "driver.h"

#define NUM_OF_MAP_REGS		16000

NTSTATUS Sheldon_PnPAddDevice(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT pdo);
VOID Sheldon_Unload(IN PDRIVER_OBJECT fdo);

/*

Function name:

	DriverEntry

Routine Description:

    Installable driver initialization entry point.
    This entry point is called directly by the I/O system.

Arguments:

    DriverObject - pointer to the driver object

    RegistryPath - pointer to a unicode string representing the path
                   to driver-specific key in the registry

Return Value:

    STATUS_SUCCESS if successful,
    STATUS_UNSUCCESSFUL otherwise

*/
extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, \
								IN PUNICODE_STRING RegistryPath)
{
	NTSTATUS ntStatus = STATUS_SUCCESS;
	PDEVICE_OBJECT deviceObject = NULL;

	KdPrint(("SIWDM - Entering DriverEntry(), RegistryPath =\n	%ws\n", RegistryPath->Buffer));

	// Create dispatch points for create, close, unload
	DriverObject->MajorFunction[IRP_MJ_CREATE] = Sheldon_Create;
	DriverObject->MajorFunction[IRP_MJ_CLEANUP] = Sheldon_Cleanup;
	DriverObject->MajorFunction[IRP_MJ_CLOSE] = Sheldon_Close;
	DriverObject->DriverUnload = Sheldon_Unload;

	// User mode DeviceIoControl() calls will be routed here
	DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = Sheldon_ProcessIOCTL;

	// User mode ReadFile()/WriteFile() calls will be routed here
	DriverObject->MajorFunction[IRP_MJ_WRITE] = Sheldon_Write;
	DriverObject->MajorFunction[IRP_MJ_READ] = Sheldon_Read;

	// routines for handling system PNP and power management requests
	DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = Sheldon_ProcessSysControlIrp;
	DriverObject->MajorFunction[IRP_MJ_PNP] = Sheldon_ProcessPnPIrp;
	DriverObject->MajorFunction[IRP_MJ_POWER] = Sheldon_ProcessPowerIrp;

	// The Functional Device Object (FDO) will not be created for PNP devices until 
	// this routine is called upon device plug-in.
	DriverObject->DriverExtension->AddDevice = Sheldon_PnPAddDevice;

	// The mechanism for handling read and write requests for a device that uses
	// interrupts includes a Start I/O routine, an interrupt service routine, and
	// a deferred procedure call routine that finishes handling interrupts.  These are
	// declared in ReadWrite.cpp and accessed through the Device Io Control calls.

	KdPrint(("SIWDM - Exiting DriverEntry (%x)\n", ntStatus));

	return ntStatus;
}

/*

Function name:

	Sheldon_PnPAddDevice

Routine Description:

    Creates a new functional device object.

Arguments:

    DriverObject - pointer to the driver object

    pdo - pointer to the physical device object

Return Value:

    STATUS_SUCCESS if successful,
    STATUS_UNSUCCESSFUL otherwise

*/
NTSTATUS Sheldon_PnPAddDevice(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT pdo)
{
	KdPrint(("SIWDM - Entering Sheldon_PnPAddDevice\n"));

	NTSTATUS ntStatus;
	PDEVICE_OBJECT fdo;
	PDEVICE_DESCRIPTION DeviceDescription;

	UNICODE_STRING devname;
	UNICODE_STRING linkname;
	WCHAR namebuf[32];
	WCHAR linkbuf[32];
	static LONG devcount = -1;

	_snwprintf(namebuf, arraysize(namebuf), L"\\Device\\SIWDM%d", InterlockedIncrement(&devcount));
	RtlInitUnicodeString(&devname, namebuf);

	_snwprintf(linkbuf, arraysize(linkbuf), L"\\DosDevices\\SIWDM%d", devcount);
	RtlInitUnicodeString(&linkname, linkbuf);

	ntStatus = IoCreateDevice(DriverObject, sizeof(DEVICE_EXTENSION), &devname, FILE_DEVICE_UNKNOWN, 0, FALSE, &fdo);

	if(!NT_SUCCESS(ntStatus))
	{
		KdPrint(("SIWDM - Shelon_PnPAddDevice: IoCreateDevice failed (%x)\n", ntStatus));
		return ntStatus;
	}

	ntStatus = IoCreateUnprotectedSymbolicLink(&linkname, &devname);

	PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;

	InitializeQueue(&pdx->dqReadWrite, Sheldon_StartIo);

	__try
	{
		pdx->DeviceObject = fdo;
		pdx->usage = 1;
		KeInitializeEvent(&pdx->evRemove, NotificationEvent, FALSE);
		pdx->removing = FALSE;
		pdx->Timeout_ms = INITIAL_TIMEOUT;
		pdx->state = STOPPED;

		// Now register the PCI DMA controller

		// First create a Device Description for the Busmastering capability
		DeviceDescription = (PDEVICE_DESCRIPTION)ExAllocatePool(PagedPool, sizeof(DEVICE_DESCRIPTION));
		RtlZeroMemory(DeviceDescription, sizeof(DEVICE_DESCRIPTION));

		DeviceDescription->Version = DEVICE_DESCRIPTION_VERSION;
		DeviceDescription->Master = TRUE;
  		DeviceDescription->ScatterGather = TRUE;
		DeviceDescription->Dma32BitAddresses = TRUE;
		DeviceDescription->IgnoreCount = FALSE;
		DeviceDescription->InterfaceType = PCIBus;
		DeviceDescription->DmaWidth = Width32Bits;
		DeviceDescription->MaximumLength = AMCC_MAX_TRANSFER_SIZE;

		// Now pass this description for both the read and the write adapters
		pdx->ReadTransfer.NumberOfMapRegisters = NUM_OF_MAP_REGS;
		pdx->ReadTransfer.Adapter = IoGetDmaAdapter(pdo, DeviceDescription, &pdx->ReadTransfer.NumberOfMapRegisters);
		pdx->WriteTransfer.NumberOfMapRegisters = NUM_OF_MAP_REGS;
		pdx->WriteTransfer.Adapter = IoGetDmaAdapter(pdo, DeviceDescription, &pdx->WriteTransfer.NumberOfMapRegisters);

		// don't need this now, because we have the adapter objects
		ExFreePool(DeviceDescription);

		if(pdx->WriteTransfer.Adapter == NULL || pdx->ReadTransfer.Adapter == NULL) 
		{
			KdPrint(("SIWDM - SheldonPnPAddDevice: Read or Write DMA Adapter returned a NULL\n"));
			ntStatus = STATUS_ADAPTER_HARDWARE_ERROR;
			__leave;
		}

		pdx->LowerDeviceObject = IoAttachDeviceToDeviceStack(fdo, pdo);
		if(!pdx->LowerDeviceObject)
		{								 
			KdPrint(("SIWDM - Sheldon_PnPAddDevice: IoAttachDeviceToDeviceStack failed\n"));
			ntStatus = STATUS_DEVICE_REMOVED;
			__leave;
		}

		KdPrint(("SIWDM - Sheldon_PnPAddDevice: Lower Device Object 0x%x\n", pdx->LowerDeviceObject));
		fdo->Flags &= ~DO_DEVICE_INITIALIZING;
	}
	__finally
	{
		if(!NT_SUCCESS(ntStatus))
		{
			if(pdx->LowerDeviceObject)
				IoDetachDevice(pdx->LowerDeviceObject);

			IoDeleteDevice(fdo);
		}
	}

	KdPrint(("SIWDM - Exiting Sheldon_PnPAddDevice (%x)\n", ntStatus));

	return ntStatus;
}

/*

Function name:

	Sheldon_Unload

Routine Description:

    Free all the allocated resources, etc.

Arguments:

    DriverObject - pointer to a driver object

Return Value:

*/
VOID Sheldon_Unload(IN PDRIVER_OBJECT DriverObject)
{
	KdPrint(("SIWDM - Entering DriverUnload: DriverObject %8.8lX\n", DriverObject));

	// Any global resources allocated in DriverEntry should be released here.

	KdPrint(("SIWDM - Exiting DriverUnload\n"));
}

/*

Function name:

	CompleteRequest

Routine Description:

	Mark I/O request complete.

Arguments:

	Irp -  I/O request being serviced

	ntStatus - NTSTATUS of the IRP

	info - number of bytes to be returned

Return Value:

	NT status code

*/
NTSTATUS CompleteRequest(IN PIRP Irp, IN NTSTATUS ntStatus, IN ULONG info)
{
	KdPrint(("SIWDM - Entering CompleteRequest\n"));

	Irp->IoStatus.Status = ntStatus;
	Irp->IoStatus.Information = info;
	IoCompleteRequest(Irp, IO_NO_INCREMENT);

	KdPrint(("SIWDM - Exiting CompleteRequest\n"));

	return ntStatus;
}		

/*

Function name:

	LockDevice

Routine Description:

	Locks the device object.

Arguments:

	fdo - pointer to a functional device object to be locked

Return Value:

	TRUE - if the device object was successfully locked,
	FALSE - the device object is being deleted

*/
BOOLEAN LockDevice(IN PDEVICE_OBJECT fdo)
{
	KdPrint(("SIWDM - LockDevice wrapper\n"));

	return LockDevice((PDEVICE_EXTENSION) fdo->DeviceExtension);
}

/*

Function name:

	LockDevice

Routine Description:

	Locks the device object.  The usage variable in the device extension should be greater
	than one or the removing flag in the device extension should be set before calling this
	function.

Arguments:

	pdx - pointer to the device extension of the functional device object to be locked

Return Value:

	TRUE - if the device object was successfully locked,
	FALSE - the device object is being deleted

*/
BOOLEAN LockDevice(PDEVICE_EXTENSION pdx)
{
	KdPrint(("SIWDM - Entering LockDevice\n"));

	LONG usage = InterlockedIncrement(&pdx->usage);

	// removing device
	if(pdx->removing)
	{
		if(InterlockedDecrement(&pdx->usage) == 0)
			KeSetEvent(&pdx->evRemove, 0, FALSE);

		return FALSE;
	}

	KdPrint(("SIWDM - Exiting LockDevice\n"));

	return TRUE;
}

/*

Function name:

	UnlockDevice

Routine Description:

	Unlocks the device object.

Arguments:

	fdo - pointer to a functional device object to be unlocked

Return Value:

*/
VOID UnlockDevice(PDEVICE_OBJECT fdo)
{
	KdPrint(("SIWDM - UnlockDevice wrapper\n"));

	UnlockDevice((PDEVICE_EXTENSION) fdo->DeviceExtension);
}

/*

Function name:

	UnlockDevice

Routine Description:

	Unlocks the device object.  The usage variable in the device extension should be greater
	than or equal to one or the removing flag in the device extension should be set if usage
	equals one before calling this function.

Arguments:

	pdx - pointer to the device extension of the functional device object to be unlocked

Return Value:

*/
VOID UnlockDevice(PDEVICE_EXTENSION pdx)
{
	LONG usage = InterlockedDecrement(&pdx->usage);

	KdPrint(("SIWDM - Entering UnlockDevice\n"));

	// removing device
	if(usage == 0)
		KeSetEvent(&pdx->evRemove, 0, FALSE);

	KdPrint(("SIWDM - Exiting UnlockDevice\n"));
}

/*

Function name:

	UnlockDeviceAndWait

Routine Description:

	Unlocks the device object and waits for the event to complete.

Arguments:

	pdx - pointer to the device extension of the functional device object to be unlocked

Return Value:

*/
VOID UnlockDeviceAndWait(PDEVICE_EXTENSION pdx)
{
	KdPrint(("SIWDM - Entering UnlockDeviceAndWait\n"));
	pdx->removing = TRUE;
	UnlockDevice(pdx);
	UnlockDevice(pdx);
	KeWaitForSingleObject(&pdx->evRemove, Executive, KernelMode, FALSE, NULL);
	KdPrint(("SIWDM - Exiting UnlockDeviceAndWait\n"));
}	

/*

Function name:

	OnRequestComplete

Routine Description:

	This is the completion routine forwarded to other drivers.

Arguments:

	fdo - pointer to a functional device object

	Irp - pointer to the IO request packet

	Event - pointer to the event

Return Value:

	STATUS_MORE_PROCESSING_REQUIRED

*/
NTSTATUS OnRequestComplete(IN PDEVICE_OBJECT fdo, IN PIRP Irp, IN PKEVENT Event)
{
	// This would be necessary if the driver was not freeing the IRP itself.

	//if(Irp->PendingReturned)
	//	IoMarkIrpPending(Irp);

	KeSetEvent(Event, 1, FALSE);

	return STATUS_MORE_PROCESSING_REQUIRED;
}

/*

Function name:

	ForwardAndWait

Routine Description:

	Forwards the request to lower level drivers and waits for completion.

Arguments:

	pdx - pointer to the device extension

	Irp - pointer to the IO request packet

Return Value:

	NTSTATUS code of Irp returned by other drivers.

*/
NTSTATUS ForwardAndWait(PDEVICE_EXTENSION pdx, PIRP Irp)
{
	KEVENT event;

	KdPrint(("SIWDM - Entering ForwardAndWait\n"));

	KeInitializeEvent(&event, NotificationEvent, FALSE);

	IoCopyCurrentIrpStackLocationToNext(Irp);
	IoSetCompletionRoutine(Irp, (PIO_COMPLETION_ROUTINE) OnRequestComplete,
		(PVOID) &event, TRUE, TRUE, TRUE);

	IoCallDriver(pdx->LowerDeviceObject, Irp);
	KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);

	KdPrint(("SIWDM - Exiting ForwardAndWait\n"));
	return Irp->IoStatus.Status;
}

/*

Function name:

	AbortRequests

Routine Description:

	Begin rejecting new requests to the queue.

Arguments:

	pdq -  Address of queue object

	ntStatus - Status to which fail new requests

Return Value:

*/
VOID AbortRequests(PDEVQUEUE pdq, NTSTATUS ntStatus)
{
	KdPrint(("SIWDM - AbortRequests\n"));

	pdq->abortstatus = ntStatus;
	CleanupRequests(pdq, NULL, ntStatus);
}

⌨️ 快捷键说明

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