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

📄 skeleton.c

📁 PCI驱动开发框架
💻 C
📖 第 1 页 / 共 3 页
字号:
	ioBuf     = irp->AssociatedIrp.SystemBuffer;	inBufLen  = irpStack->Parameters.DeviceIoControl.InputBufferLength;	outBufLen = irpStack->Parameters.DeviceIoControl.OutputBufferLength;	ioctlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;        switch (ioctlCode) {	  default:            KdPrint(("SKELETON.SYS(StartIo): unexpected IRP_MJ_DEVICE_CONTROL\n"));            status = STATUS_INVALID_PARAMETER;            break;        }	if (status != STATUS_PENDING) {	    irp->IoStatus.Status = status;	    IoCompleteRequest(irp, IO_VIDEO_INCREMENT);	    IoStartNextPacket(devObj, TRUE);	}	return;      default:	KdPrint(("SKELETON.SYS(StartIo): unexpected major function\n"));	irp->IoStatus.Status = STATUS_INVALID_PARAMETER;	IoCompleteRequest(irp, IO_NO_INCREMENT);	IoStartNextPacket(devObj, TRUE);	return;    }    skelDev->OperationType = irpStack->MajorFunction;    skelDev->IrpSystemBuffer = irp->AssociatedIrp.SystemBuffer;    if (skelDev->OperationType == IRP_MJ_READ) {	skelDev->IrpBufLen = irpStack->Parameters.Read.Length;    } else {	skelDev->IrpBufLen  = irpStack->Parameters.Write.Length;    }    if (skelDev->IrpBufLen == 0 || irp->MdlAddress == NULL) {	irp->IoStatus.Status = STATUS_INVALID_PARAMETER;	IoCompleteRequest(irp, IO_NO_INCREMENT);	IoStartNextPacket(devObj, TRUE);    }	    skelDev->VirtualAddress = MmGetMdlVirtualAddress(irp->MdlAddress);    if (skelDev->TimerStarted) {	KeCancelTimer(&skelDev->DeviceCheckTimer);	skelDev->TimerStarted = FALSE;    }    writeOp = (skelDev->OperationType == IRP_MJ_READ) ? FALSE : TRUE;    KeFlushIoBuffers(irp->mdlAddress, !writeOp, TRUE);    status = IoAllocateAdapterChannel(skelDev->AdaptorObj, devObj,				      skelDev->DmaMapRegisters, ProgramDMA, devObj);    KdPrint(("SKELETON.SYS(StartIo): Exiting irp %p\n", irp));    if (!NT_SUCCESS(status)) {	KdPrint(("SKELETON.SYS: Unable to allocate adaptor channel for DMA\n"));	irp->IoStatus.Status = status;	IoCompleteRequest(irp, IO_NO_INCREMENT);	return;    }}/* *---------------------------------------------------------------------- * TransferDPC -- * *	This routine is called at DISPATCH_LEVEL by the system at the *	ServiceInterrupt(). * *	This routine is protected against interrupts since it was queued *	by an interrupt, and the next DMA related interrupt won't occur *	until something else happens. * *	This routine is called when a DMA transfer has not been completed. *	It sets everything up to continue the tranfer. *---------------------------------------------------------------------- */static VOIDTransferDPC(IN PKDPC Dpc, IN PVOID Context, IN PVOID Arg1, IN PVOID Arg2){    PDEVICE_OBJECT devObj = Context;    PSKELETON_DEVICE skelDev = devObj->DeviceExtension;    PIRP irp;    BOOLEAN writeOp;    KdPrint(("SKELETON.SYS(TransferDPC): Finished irp %p\n",	     devObj->CurrentIrp));    CancelTransferTimeout(devObj);    irp = devObj->CurrentIrp;    writeOp = (skelDev->OperationType == IRP_MJ_WRITE) ? TRUE : FALSE;    IoFlushAdapterBuffers(NULL, irp->MdlAddress,			  skelDev->MapRegisterBase,			  skelDev->VirtualAddress, skelDev->IrpBufLen, writeOp);    IoFreeMapRegisters(skelDev->AdaptorObj, skelDev->MapRegisterBase, 		       skelDev->DmaMapRegisters);    if (skelDev->OperationType == IRP_MJ_READ) {	KeFlushIoBuffers(irp->MdlAddress, TRUE, TRUE);    }    irp->IoStatus.Status = skelDev->IrpStatus;    if (skelDev->IrpStatus == STATUS_SUCCESS) {	irp->IoStatus.Information = skelDev->IrpBytesTransferred;    }    IoCompleteRequest(irp, IO_VIDEO_INCREMENT);    IoStartNextPacket(devObj, TRUE);    skelDev->DpcRequested = FALSE;    return;}/* *---------------------------------------------------------------------- * ServiceTimeoutUtil -- * *	Utility routine for ServiceTimeout.  Runs code that is  *	sensitive to interrupts. *---------------------------------------------------------------------- */static BOOLEANServiceTimeoutUtil(IN PCONTEXT Context){    PSKELETON_DEVICE skelDev = (PSKELETON_DEVICE) Context;    return TRUE;}/* *---------------------------------------------------------------------- * ServiceTimeout -- * *	Service a timeout.  Is this a routine to check on the board *	if nothing happens after a little while?  If so, *	ddk/src/multimedia/soundlib/wave.c does something similar. * * Results: *	None *---------------------------------------------------------------------- */voidServiceTimeout(PDEVICE_OBJECT devObj){    PSKELETON_DEVICE skelDev = devObj->DeviceExtension;    KeSynchronizeExecution(skelDev->KIntrObj, ServiceTimeoutUtil, skelDev);    skelDev->IrpStatus = STATUS_UNSUCCESSFUL;    skelDev->IrpBytesTransferred = 0L;    skelDev->RequestDpc = TRUE;    KdPrint(("SKELETON.SYS: ServiceTimeout calling TransferDPC\n"));    TransferDPC(NULL, devObj, NULL, NULL);}/* *---------------------------------------------------------------------- * TimeoutDPC -- * *	This routine gets called when a timeout occurs.  We then *	need to check plxDev->TransferDone to see if the transfer *	finished before this timer went off.  If is did, then we *	can just ignore this DPC call.  If not, we need to clear *	everything up, fail the request, and move on. * * Results: *	None *---------------------------------------------------------------------- */static VOIDTimeoutDPC(IN PKDPC Dpc, IN PVOID Context, IN PVOID Param1, IN PVOID Param2){    PDEVICE_OBJECT devObj = Context;    PSKELETON_DEVICE skelDev = devObj->DeviceExtension;    skelDev->TimerStarted = FALSE;    if (! skelDev->TransferDone) {	/*	 * XXX: Clean up the hardware here if necessary.	 */	ServiceTimeout(devObj);    }}/* *---------------------------------------------------------------------- * OpenDevice -- * *	Open the device.  We will allow multiple opens to the device. * * 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;    }    len = mappedLen.LowPart;    /*     * If the address is in io space, just return the address, otherwise     * go through the mapping mechanism     */    if (inIoSpace) {        *((PVOID *) ioBuf) = (PVOID) physicalAddrBase.LowPart;    } else {        /*         * initialize view base that will receive the physical mapped         * address after the MapViewOfSection call.         */        viewBase = physicalAddrBase;        /*         * Let ZwMapViewOfSection pick an address         */        virtualAddr = NULL;        /*         * Map the section         */        status =	    ZwMapViewOfSection(physicalMemHandle, (HANDLE) -1, &virtualAddr,			       0L, len, &viewBase, &len, ViewShare, 0,			       PAGE_READWRITE | PAGE_NOCACHE);        if (!NT_SUCCESS(status)) {            KdPrint(("SKELETON.SYS: ZwMapViewOfSection failed\n"));            goto close_handle;        }        /*         * Mapping the section above rounded the physical address down to the         * nearest 64 K boundary. Now return a virtual address that sits where         * we want by adding in the offset from the beginning of the section.         */        (ULONG) virtualAddr += (ULONG)physicalAddrBase.LowPart -                                  (ULONG)viewBase.LowPart;        *((PVOID *) ioBuf) = virtualAddr;    }    status = STATUS_SUCCESS;close_handle:    ZwClose(physicalMemHandle);done:    return status;}/* *---------------------------------------------------------------------- * UnmapMemory -- * *	Unmaps board's memory from the process's address space. * * Results: *	STATUS_SUCCESS *	STATUS_BUFFER_TOO_SMALL, *---------------------------------------------------------------------- */static NTSTATUS

⌨️ 快捷键说明

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