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

📄 skeleton.c

📁 pci的驱动程序编程基本框架,在此基础上编程非常方便,实现了由PCI进行DMA传送数据功能
💻 C
📖 第 1 页 / 共 2 页
字号:
    }    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 NTSTATUSUnmapMemory(IN PDEVICE_OBJECT devObj, IN OUT PVOID ioBuf,	  IN ULONG inBufLen, IN ULONG outBufLen){    if (inBufLen < sizeof(PVOID)) {	KdPrint(("SKELETON.SYS(UnmapMemory): Insufficient input buffer\n"));	return STATUS_BUFFER_TOO_SMALL;    }    KdPrint(("SKELETON.SYS: memory unmapped\n"));    return ZwUnmapViewOfSection((HANDLE) -1, *((PVOID *) ioBuf));}/* *---------------------------------------------------------------------- * ResetBoard -- * *	Does a hard reset of the board * *---------------------------------------------------------------------- */static VOIDResetBoard(PSKELETON_DEVICE skelDev){    PUCHAR	 		    base;    /*     * Reset the board     */    base = skelDev->FrameBase;    *((unsigned long *)(base + 0x7f0000)) = 0;    KeStallExecutionProcessor(500);    /*     * Enable the board     */    *((unsigned long *)(base + 0x7f0000)) = LITTLE_ENDIAN_32(1);}/* *---------------------------------------------------------------------- * CreateDevice -- * *	Create a Skeleton device * *---------------------------------------------------------------------- */static NTSTATUSCreateDevice(IN PDRIVER_OBJECT drvObj, IN PUNICODE_STRING regPath,	     ULONG busId, ULONG slotId, IN PPCI_COMMON_CONFIG pciData){    PDEVICE_OBJECT		    devObj = NULL;    WCHAR			    devNameBuf[] = L"\\Device\\Skeleton0";    UNICODE_STRING		    devNameUniStr;    WCHAR			    devLinkBuf[] = L"\\DosDevices\\SKELETON0";    UNICODE_STRING		    devLinkUniStr;    NTSTATUS			    status;    INTERFACE_TYPE		    interfaceType;    ULONG			    busNumber;    PCM_RESOURCE_LIST		    resourceList;    PCM_PARTIAL_RESOURCE_LIST	    partialResourceList;    PCM_PARTIAL_RESOURCE_DESCRIPTOR partialDescriptor;    PHYSICAL_ADDRESS		    xlatedAddr;    PHYSICAL_ADDRESS		    start;    ULONG			    length;    ULONG			    addressSpace;    PSKELETON_DEVICE		    skelDev;    ULONG			    i, j;    BOOLEAN			    b;    int				    found;    DEVICE_DESCRIPTION		    devDesc;    static WCHAR		    devNum = 0;        devNameBuf[sizeof(devNameBuf) - 2] = L'0' + devNum;    devLinkBuf[sizeof(devLinkBuf) - 2] = L'0' + devNum;    devNum++;    RtlInitUnicodeString(&devNameUniStr, devNameBuf);    status = IoCreateDevice(drvObj, sizeof(SKELETON_DEVICE), &devNameUniStr,			    FILE_DEVICE_SKELETON, 0, FALSE, &devObj);    devObj->Flags |= DO_DIRECT_IO;    /*     * 1. Create dispatch points for device control, create, close.     * 2. Create a symbolic link, i.e. a nmae that a Win32 app can     *    specify to open the device.  If this fails, delete the     *    device object.     */    if (! NT_SUCCESS(status)) {        KdPrint(("SKELETON.SYS: IoCreateDevice failed\n"));	return status;    }    RtlInitUnicodeString(&devLinkUniStr, devLinkBuf);    status = IoCreateSymbolicLink(&devLinkUniStr, &devNameUniStr);    if (!NT_SUCCESS(status)) {	KdPrint(("SKELETON.SYS: IoCreateSymbolicLink failed\n"));	goto error;    }    resourceList = NULL;    status = HalAssignSlotResources(regPath, NULL, drvObj, devObj,				    PCIBus, busId, slotId,				    &resourceList);    if (!NT_SUCCESS(status)) {	KdPrint(("SKELETON.SYS: HalAssignSlotResources failed\n"));	goto error;    }    /*     * Now, we hopefully have an address for the card on the bus,     * but who knows for sure.  We need to translate the returned     * address and map the address space into kernel space.     */    skelDev = devObj->DeviceExtension;    skelDev->BusId = busId;    skelDev->SlotId = slotId;    found = 0;    for (i = 0; i < resourceList->Count; i++) {	interfaceType = resourceList->List[i].InterfaceType;	busNumber = resourceList->List[i].BusNumber;	partialResourceList = &resourceList->List[i].PartialResourceList;	for (j = 0; j < partialResourceList->Count; j++) {	    partialDescriptor = &partialResourceList->PartialDescriptors[j];	    if (partialDescriptor->Type == CmResourceTypeMemory) {		addressSpace = 0; /* Memory */		start = partialDescriptor->u.Memory.Start;		length = partialDescriptor->u.Memory.Length;		b = HalTranslateBusAddress(interfaceType, busNumber,					   start,					   &skelDev->FrameMemType,					   &xlatedAddr);		if (!b) {		    KdPrint(("SKELETON.SYS: HalTranslateBusAddress failed\n"));		    status = STATUS_UNSUCCESSFUL;		    goto error;		}		skelDev->MemStart = xlatedAddr;		skelDev->MemLength = length;		if (skelDev->FrameMemType == 0) {		    skelDev->FrameBase = MmMapIoSpace(xlatedAddr, length, FALSE);		} else {		    skelDev->FrameBase = (PUCHAR) xlatedAddr.LowPart;		}		found++;	    } else if (partialDescriptor->Type == CmResourceTypeInterrupt) {		/*		 * Get the system interrupt vector for IoConnectInterrupt		 */		ULONG level    = partialDescriptor->u.Interrupt.Level;		ULONG vector   = partialDescriptor->u.Interrupt.Vector;		ULONG affinity = partialDescriptor->u.Interrupt.Affinity;		skelDev->KIntrVector =		    HalGetInterruptVector(PCIBus, busId, level, vector,					  &skelDev->KIrql,					  &skelDev->KIntrAffinity);		devDesc.Version = DEVICE_DESCRIPTION_VERSION;		devDesc.Master = TRUE;		devDesc.ScatterGather = TRUE;		devDesc.DemandMode = FALSE;		devDesc.AutoInitialize = FALSE;		devDesc.Dma32BitAddresses = TRUE;		devDesc.IgnoreCount = FALSE;		devDesc.Reserved1 = FALSE;		devDesc.Reserved2 = FALSE;		devDesc.BusNumber = busId;		devDesc.DmaChannel = 0; /* ? */		devDesc.InterfaceType = PCIBus;		devDesc.DmaWidth = Width32Bits;		devDesc.DmaSpeed = Compatible;		devDesc.MaximumLength = 255 * 1024;		devDesc.DmaPort = 0;		skelDev->AdaptorObj = 		    HalGetAdapter(&devDesc, &skelDev->DmaMapRegisters);		found++;	    }	}    }    if (found != 2) {	KdPrint(("SKELETON.SYS: Failed to find frame buffer address or interrupt\n"));	status = STATUS_UNSUCCESSFUL;	goto error;    }    /*     * Enable Memory Space and Bus Master control bits     */    pciData->Command = 6;    HalSetBusDataByOffset(PCIConfiguration, busId, slotId,			  &pciData->Command,			  offsetof(PCI_COMMON_CONFIG, Command),			  sizeof(pciData->Command));    ResetBoard(skelDev);    /*     * 1. Initialize the device mutex     * 2. Initialize the device spin lock to protect the DPC routine     *    for callers to SynchronizeDPC.     * 3. Initialize the DPC data and register with Io system     * 4. Connect the interrupt     */    ExInitializeFastMutex(&skelDev->IrpMutex);    KeInitializeSpinLock(&skelDev->DeviceSpinLock);    KeInitializeTimer(&skelDev->DeviceCheckTimer);    KeInitializeTimer(&skelDev->StartIoTimer);    skelDev->TimerStarted = FALSE;#if 0    KeInitializeDpc(&skelDev->TimerDpc, TimeoutDPC, devObj);    skelDev->DpcRequested = FALSE;    IoInitializeDpcRequest(devObj, TransferDPC);#endif    status = IoConnectInterrupt(&skelDev->KIntrObj, ServiceInterrupt,				devObj, NULL,				skelDev->KIntrVector,				skelDev->KIrql, skelDev->KIrql,				LevelSensitive,				TRUE, /* ShareVector */				skelDev->KIntrAffinity, FALSE);    if (!NT_SUCCESS(status)) {	KdPrint(("SKELETON.SYS: Unable to connect interrupt\n"));	status = STATUS_UNSUCCESSFUL;	goto error;    }    if (0) {  error:	IoDeleteDevice(devObj);    } else {	ExFreePool(resourceList);    }    return status;}/* *---------------------------------------------------------------------- * * ProbePCI * *	Attempt to find all Skeleton adapters in PCI address space * * Return Value: *	STATUS_SUCCESSFUL if everything went OK, STATUS_UNSUCCESSFUL *	if not. * *---------------------------------------------------------------------- */static NTSTATUSProbePCI(IN PDRIVER_OBJECT drvObj, IN PUNICODE_STRING regPath){    PCI_SLOT_NUMBER     slotNumber;    PPCI_COMMON_CONFIG  pciData;    UCHAR               buf[PCI_COMMON_HDR_LENGTH];    ULONG               i, f, j, bus;    BOOLEAN             flag;    UCHAR               vendorString[5] = {0};    UCHAR               deviceString[5] = {0};    NTSTATUS		status;    ULONG		total = 0;    pciData = (PPCI_COMMON_CONFIG) buf;    slotNumber.u.bits.Reserved = 0;    flag = TRUE;    for (bus = 0; flag; bus++) {        for (i = 0; i < PCI_MAX_DEVICES  &&  flag; i++) {            slotNumber.u.bits.DeviceNumber = i;            for (f = 0; f < PCI_MAX_FUNCTION; f++) {                slotNumber.u.bits.FunctionNumber = f;                j = HalGetBusData(PCIConfiguration, bus, slotNumber.u.AsULONG,                    pciData, PCI_COMMON_HDR_LENGTH);                if (j == 0) {                    /* out of buses */                    flag = FALSE;                    break;                }                if (pciData->VendorID == PCI_INVALID_VENDORID) {                    /* skip to next slot */                    break;                }#if 0                KdPrint(("PciData: ------------------------\n"			 "  Bus: %d\n"			 "  Device: %d\n"			 "  Function: %d\n"			 "  Vendor Id: %x\n"			 "  Device Id: %x\n"			 "  Command: %x\n"			 "  Status: %x\n"			 "  Rev Id: %x\n"			 "  Pro`gIf: %x\n"			 "  SubClass: %x\n"			 "  BaseClass: %x\n"			 "  CacheLine: %x\n"			 "  Latency: %x\n"			 "  Header Type: %x\n"			 "  BIST: %x\n"			 "  Base Reg[0]: %x\n"			 "  Base Reg[1]: %x\n"			 "  Base Reg[2]: %x\n"			 "  Base Reg[3]: %x\n"			 "  Base Reg[4]: %x\n"			 "  Base Reg[5]: %x\n"			 "  Rom Base: %x\n"			 "  Interrupt Line: %x\n"			 "  Interrupt Pin: %x\n"			 "  Min Grant: %x\n"			 "  Max Latency: %x\n",			 bus,			 i,			 f,			 pciData->VendorID,			 pciData->DeviceID,			 pciData->Command,			 pciData->Status,			 pciData->RevisionID,			 pciData->ProgIf,			 pciData->SubClass,			 pciData->BaseClass,			 pciData->CacheLineSize,			 pciData->LatencyTimer,			 pciData->HeaderType,			 pciData->BIST,			 pciData->u.type0.BaseAddresses[0],			 pciData->u.type0.BaseAddresses[1],			 pciData->u.type0.BaseAddresses[2],			 pciData->u.type0.BaseAddresses[3],			 pciData->u.type0.BaseAddresses[4],			 pciData->u.type0.BaseAddresses[5],			 pciData->u.type0.ROMBaseAddress,			 pciData->u.type0.InterruptLine,			 pciData->u.type0.MinimumGrant,			 pciData->u.type0.MaximumLatency));#endif		/*		 * If we find the Skeleton id, create a device		 */		if (pciData->VendorID == 0x115b && pciData->DeviceID == 0) {		    status = CreateDevice(drvObj, regPath, bus,					  slotNumber.u.AsULONG, pciData);		    if (NT_SUCCESS(status)) {			total++;		    }                }            }        }    }    if (total > 0) {	return STATUS_SUCCESS;    } else {	return STATUS_NO_SUCH_DEVICE;    }}/* *---------------------------------------------------------------------- * ServiceInterrupt -- * *	Service an interrupt from the Skeleton board * * Results: *	TRUE if the interrupt was handled, FALSE otherwise. *---------------------------------------------------------------------- */static BOOLEANServiceInterrupt(IN PKINTERRUPT Interrupt, IN PVOID ServiceContext){    PDEVICE_OBJECT devObj = (PDEVICE_OBJECT) ServiceContext;    PSKELETON_DEVICE skelDev;    skelDev = devObj->DeviceExtension;    /*     * Change this to TRUE when this routine does something     */    return FALSE;}/* * Overrides for Emacs to get consistency. * Emacs will notice this stuff at the end of the file and automatically * adjust the settings for this buffer only.  This must remain at the end * of the file. * --------------------------------------------------------------------------- * Local variables: * tab-width: 8 * c-brace-imaginary-offset: 0 * c-brace-offset: -4 * c-argdecl-indent: 4 * c-label-offset: -2 * c-continued-statement-offset: 4 * c-continued-brace-offset: 0 * c-indent-level: 4 * End: */

⌨️ 快捷键说明

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