📄 skeleton.c
字号:
} 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 + -