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

📄 skeleton.c

📁 pci的驱动程序编程基本框架,在此基础上编程非常方便,实现了由PCI进行DMA传送数据功能
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *---------------------------------------------------------------------- * * Module Name: *	skeleton.c * * Abstract: *	This module contains the code for a skeleton driver that *	can just map a board into user space memory. * * Environment: *	Kernel mode * * Author: *	Gordon Chaffee * *---------------------------------------------------------------------- */#include <ntddk.h>#include <stdarg.h>/* * Skeleton includes */#include "skeleton_nt.h"#include "skeleton_dev.h"/* *---------------------------------------------------------------------- * Static Variables *---------------------------------------------------------------------- */static int nopens;/* * Internally defined routines */static NTSTATUS	CloseDevice(IN PDEVICE_OBJECT devObj, IN PFILE_OBJECT fileObj);static NTSTATUS	Dispatch(IN PDEVICE_OBJECT devObj, IN PIRP Irp);static NTSTATUS	MapMemory(IN PDEVICE_OBJECT, IN OUT PVOID, IN ULONG, IN ULONG);static NTSTATUS	OpenDevice(IN PDEVICE_OBJECT devObj, IN PFILE_OBJECT fileObj);static NTSTATUS	ProbePCI(IN PDRIVER_OBJECT drvObj, IN PUNICODE_STRING regPath);static BOOLEAN  ServiceInterrupt(IN PKINTERRUPT Interrupt,		    IN PVOID ServiceContext);static VOID     StartIo(IN PDEVICE_OBJECT devObj, IN PIRP Irp);static VOID	Unload(IN PDRIVER_OBJECT);static NTSTATUS	UnmapMemory(IN PDEVICE_OBJECT, IN OUT PVOID,		    IN ULONG, IN ULONG);/* *---------------------------------------------------------------------- * Under NT, we can specify the parts of the code that are no longer * needed after initialization with the pragma alloc_text. *----------------------------------------------------------------------  */#if 0#ifdef ALLOC_PRAGMA#    pragma alloc_text(INIT,DriverEntry)#endif#endif/* *---------------------------------------------------------------------- * DriverEntry -- * *	This routine is called at system initialization time to initialize *	this driver. * * Arguments: *	DriverObject    - Supplies the driver object. *	RegistryPath    - Supplies the registry path for this driver. * * Return Value: *	STATUS_SUCCESS          - We could initialize at least one device. *	STATUS_NO_SUCH_DEVICE   - We could not initialize even one device. *      STATUS_UNSUCCESSFUL     - For other errors? *---------------------------------------------------------------------- */NTSTATUSDriverEntry(IN PDRIVER_OBJECT drvObj, IN PUNICODE_STRING regPath){    NTSTATUS status;    KdPrint(("SKELETON.SYS(DriverEntry): Entering\n"));    status = ProbePCI(drvObj, regPath);    if (NT_SUCCESS(status)) {	/*	 * Create dispatch points for device control, create, close.	 */	drvObj->MajorFunction[IRP_MJ_CREATE]		 = Dispatch;	drvObj->MajorFunction[IRP_MJ_CLOSE]		 = Dispatch;	drvObj->MajorFunction[IRP_MJ_DEVICE_CONTROL]	 = Dispatch;	drvObj->MajorFunction[IRP_MJ_READ]		 = Dispatch;	drvObj->MajorFunction[IRP_MJ_WRITE]		 = Dispatch;	drvObj->DriverUnload				 = Unload;	drvObj->DriverStartIo				 = StartIo;    }    KdPrint(("SKELETON.SYS(DriverEntry): Exiting\n"));    return status;}/* *---------------------------------------------------------------------- * Dispatch -- * *	This routine handles all IRPs sent to this device. * * Arguments: *	devObj:		Pointer to the device object *	irp:		Pointer to an I/O request packet * * Results: *	Standard NT result * * Notes: *	We only handle ioctls to map and unmap the skeleton board. *---------------------------------------------------------------------- */static NTSTATUSDispatch(IN PDEVICE_OBJECT devObj, IN PIRP irp){    PIO_STACK_LOCATION	irpStack;    PVOID		ioBuf;    ULONG		inBufLen;    ULONG		outBufLen;    ULONG		ioctlCode;    NTSTATUS		status;    PSKELETON_DEVICE	skelDev;    ULONG		key;    skelDev = devObj->DeviceExtension;    /*     * enter device mutex  to ensure one request at a time     */    ExAcquireFastMutex(&skelDev->IrpMutex);    irp->IoStatus.Status      = STATUS_SUCCESS;    irp->IoStatus.Information = 0;    irpStack = IoGetCurrentIrpStackLocation(irp);    ioBuf = irp->AssociatedIrp.SystemBuffer;    switch (irpStack->MajorFunction) {      case IRP_MJ_CREATE:        KdPrint(("SKELETON.SYS: IRP_MJ_CREATE\n"));	status = OpenDevice(devObj, irpStack->FileObject);        break;      case IRP_MJ_CLOSE:        KdPrint(("SKELETON.SYS: IRP_MJ_CLOSE\n"));	status = CloseDevice(devObj, irpStack->FileObject);        break;      case IRP_MJ_DEVICE_CONTROL:        ioctlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;	inBufLen  = irpStack->Parameters.DeviceIoControl.InputBufferLength;	outBufLen = irpStack->Parameters.DeviceIoControl.OutputBufferLength;        switch (ioctlCode) {	  case IOCTL_SKELETON_MAP_USER_PHYSICAL_MEMORY: /* PV_MMAP */            status = MapMemory(devObj, ioBuf, inBufLen, outBufLen);            if (NT_SUCCESS(status)) {                /*                 * Success! Set the following to sizeof(PVOID) to                 *     indicate we're passing valid data back.                 */                irp->IoStatus.Information = sizeof(PVOID);            } else {                status = STATUS_INVALID_PARAMETER;                KdPrint(("SKELETON.SYS: memory map failed :(\n"));            }            break;	  case IOCTL_SKELETON_UNMAP_USER_PHYSICAL_MEMORY:	    status = UnmapMemory(devObj, ioBuf, inBufLen, outBufLen);            break;	  default:            KdPrint(("SKELETON.SYS: unknown IRP_MJ_DEVICE_CONTROL\n"));            status = STATUS_INVALID_PARAMETER;            break;        }        break;      default:	KdPrint(("SKELETON.SYS: unknown Major Function\n"));	status = STATUS_INVALID_PARAMETER;    }    /*     * Don't get cute and try to use the status field of     * the irp in the return status.  That IRP IS GONE as     * soon as you call IoCompleteRequest.     */    if (status != STATUS_PENDING) {	irp->IoStatus.Status = status;	IoCompleteRequest(irp, IO_VIDEO_INCREMENT);    } else {	IoMarkIrpPending(irp);	IoStartPacket(devObj, irp, &key, NULL);    }    ExReleaseFastMutex(&skelDev->IrpMutex);    return status;}/* *---------------------------------------------------------------------- * Unload -- * *	Just delete the associated device and return * * Arguments: *	drvObj:		Pointer to the driver object * * Results: *	None *---------------------------------------------------------------------- */static VOIDUnload(IN PDRIVER_OBJECT drvObj){    WCHAR		devLinkBuf[]  = L"\\DosDevices\\SKELETON0";    UNICODE_STRING	devLinkUniStr;    WCHAR		devNum;    PDEVICE_OBJECT	devObj, nextDev;    PSKELETON_DEVICE	skelDev;    int			tmp;    CM_RESOURCE_LIST	EmptyList;    BOOLEAN		ResourceConflict;    /*     * For each device that is on the machine:     *     * 1. Delete the symbolic links     * 2. Turn off the board interrupts and disconnect the interrupt.     * 3. Unmap the board memory from system space.     * 4. Unreport the resources that were assigned by HalAssignSlotResources     * 5. Delete the device object     */    for (devNum = 0, devObj = drvObj->DeviceObject; devObj != NULL;	 devObj = nextDev, devNum++) {	devLinkBuf[sizeof(devLinkBuf) - 1] = L'0' + devNum;	RtlInitUnicodeString(&devLinkUniStr, devLinkBuf);	IoDeleteSymbolicLink(&devLinkUniStr);	skelDev = devObj->DeviceExtension;	IoDisconnectInterrupt(skelDev->KIntrObj);	MmUnmapIoSpace(skelDev->FrameBase, skelDev->MemLength);	/* un-report any resources used by the driver and the device */	EmptyList.Count = 0;	IoReportResourceUsage(NULL, drvObj, &EmptyList, sizeof(ULONG),			      drvObj->DeviceObject, &EmptyList, sizeof(ULONG),			      FALSE, &ResourceConflict);	nextDev = devObj->NextDevice;	IoDeleteDevice(devObj);    }    KdPrint(("SKELETON.SYS: unloading\n"));}/* *---------------------------------------------------------------------- * StartIo -- * *	This gets called when we are about to start another graphics *	or DMA operation.  This can occur because another operation *	just completed,	or it can occur because this is the first *	operation.  Either way, we don't expect anything to interfere *	with its operation. * * Results: *	None *---------------------------------------------------------------------- */static VOIDStartIo(IN PDEVICE_OBJECT devObj, IN PIRP irp){    irp->IoStatus.Status = STATUS_SUCCESS;    IoCompleteRequest(irp, IO_VIDEO_INCREMENT);    IoStartNextPacket(devObj, TRUE);    return;}/* *---------------------------------------------------------------------- * OpenDevice -- * *	Open the device.  We will allow multiple opens to the device, *	but all drawing after initialization needs to occur only *	through the driver interface.  Since we only do PutImage and *	GetImage type operations as well as setting and clearing the *	overlay regions in response to Windows changes on the screen, *	this doesn't seem to be a big problem.  We just need to: * *	XXX: Allocate a page when the device the first open is done. *	    This page will be used to hold the settings for open channels. *	    This will only allow a limited number of applications *	    to simultaneously access the device, so this many not be what *	    we want, but this should not be a problem. * *	(1) Allocate some memory for the channel we are opening. *	(2) Have an ioctl for setting the grabbing and capturing *	    position for this open channel.  This is stored in the *	    allocated memory for this channel.  When images are *	    put or captured, the parameters are taken from these values. *	    This lets the I/O manager do all the locking down of memory *	    so that we don't have to send two buffers down with the *	    same ioctl. *	(3) Use the FileObject field of the IO_STACK_LOCATION of the *	    irp to manage which video control block has been allocated for *	    this channel. * * Results: *	A standard NT result *---------------------------------------------------------------------- */static NTSTATUSOpenDevice(IN PDEVICE_OBJECT devObj, IN PFILE_OBJECT fileObj){    PSKELETON_DEVICE skelDev;    KdPrint(("SKELETON.SYS: OpenDevice called\n"));    skelDev = devObj->DeviceExtension;    ++nopens;			/* inc global open */    return STATUS_SUCCESS;}/* *---------------------------------------------------------------------- * CloseDevice -- * *	Close up device and free resources allocated by OpenDevice * * Results: *	A standard NT result *---------------------------------------------------------------------- */static NTSTATUSCloseDevice(IN PDEVICE_OBJECT devObj, IN PFILE_OBJECT fileObj){    PSKELETON_DEVICE skelDev;    skelDev = devObj->DeviceExtension;    nopens--;			/* decrement global open */    return STATUS_SUCCESS;}/* *---------------------------------------------------------------------- * MapMemory -- * *	Given a physical address, maps this address into a user mode *	process's address space * * Arguments: *	devObj		pointer to a device object *	ioBuf		pointer to the I/O buffer *	inBufLen	input buffer length *	outBufLen	output buffer length * * Results: *	STATUS_SUCCESS *	STATUS_UNSUCCESSFUL *	STATUS_BUFFER_TOO_SMALL, *	(other STATUS_* as returned by kernel APIs) *---------------------------------------------------------------------- */static NTSTATUSMapMemory(IN PDEVICE_OBJECT devObj, IN OUT PVOID ioBuf,	  IN ULONG inBufLen, IN ULONG outBufLen){    INTERFACE_TYPE     interfaceType;    ULONG              busNumber;    PHYSICAL_ADDRESS   physicalAddr;    ULONG              len;    UNICODE_STRING     physicalMemUniStr;    OBJECT_ATTRIBUTES  objAttrs;    HANDLE             physicalMemHandle  = NULL;    PVOID              physicalMemSection = NULL;    ULONG              inIoSpace, inIoSpace2;    NTSTATUS           status;    PHYSICAL_ADDRESS   physicalAddrBase;    PHYSICAL_ADDRESS   physicalAddrEnd;    PHYSICAL_ADDRESS   viewBase;    PHYSICAL_ADDRESS   mappedLen;    BOOLEAN            xlateBaseAddr;    BOOLEAN            xlateEndAddr;    PVOID              virtualAddr;    PSKELETON_DEVICE   skelDev;    skelDev = devObj->DeviceExtension;    if (outBufLen < sizeof(PVOID)) {	KdPrint(("SKELETON.SYS(MapMemory): Insufficient output buffer\n"));	status = STATUS_BUFFER_TOO_SMALL;	goto done;    }    /*     * Get a pointer to physical memory...     *     * - Create the name     * - Initialize the data to find the object     * - Open a handle to the oject and check the status     * - Get a pointer to the object     * - Free the handle     */    RtlInitUnicodeString(&physicalMemUniStr, L"\\Device\\PhysicalMemory");    InitializeObjectAttributes(&objAttrs, &physicalMemUniStr,			       OBJ_CASE_INSENSITIVE, (HANDLE) NULL,			       (PSECURITY_DESCRIPTOR) NULL);    status = ZwOpenSection(&physicalMemHandle, SECTION_ALL_ACCESS, &objAttrs);    if (!NT_SUCCESS(status)) {        KdPrint(("SKELETON.SYS: ZwOpenSection failed\n"));        goto done;    }    status =	ObReferenceObjectByHandle(physicalMemHandle, SECTION_ALL_ACCESS,				       (POBJECT_TYPE) NULL, KernelMode,				       &physicalMemSection,				       (POBJECT_HANDLE_INFORMATION) NULL);    if (!NT_SUCCESS(status)) {        KdPrint(("SKELETON.SYS: ObReferenceObjectByHandle failed\n"));        goto close_handle;    }    interfaceType = PCIBus;    busNumber     = skelDev->BusId;    physicalAddr  = skelDev->MemStart;    len           = skelDev->MemLength;    inIoSpace     = skelDev->FrameMemType;    inIoSpace2    = skelDev->FrameMemType;    /*     * Initialize the physical addresses that will be translated     */    physicalAddrEnd = RtlLargeIntegerAdd(physicalAddr,					 RtlConvertUlongToLargeInteger(len));    /*     * Translate the physical addresses.     */    xlateBaseAddr = HalTranslateBusAddress(interfaceType, busNumber,					   physicalAddr, &inIoSpace,					   &physicalAddrBase);    xlateEndAddr = HalTranslateBusAddress(interfaceType, busNumber,					  physicalAddrEnd, &inIoSpace2,    					  &physicalAddrEnd);    if (!(xlateBaseAddr && xlateEndAddr)) {        KdPrint(("SKELETON.SYS: HalTranslatephysicalAddress failed\n"));        status = STATUS_UNSUCCESSFUL;        goto close_handle;    }    /*     * Calculate the length of the memory to be mapped     */    mappedLen = RtlLargeIntegerSubtract(physicalAddrEnd, physicalAddrBase);    /*     * If the mappedlen is zero, somthing very weird happened in the HAL     * since the Length was checked against zero.     */    if (mappedLen.LowPart == 0) {        KdPrint(("SKELETON.SYS: mappedLen.LowPart == 0\n"));        status = STATUS_UNSUCCESSFUL;        goto close_handle;

⌨️ 快捷键说明

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