/* * Intel QV Linux kernel driver * Copyright (c) 2016 - 2017, Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, * version 2, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * */ /* * Module Name: * linuxdriverdevice_i.c * * Abstract: * This file contains implementation for any functions that are * called from nalioctldrv.c and need to be run in kernel mode. * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,12,0) #include #else #include #endif #include #include VOID* _NalAllocateMemory( IN UINT32 ByteCount, IN CHAR* NamedLocator, IN UINT32 LineNumber ) { VOID* Address = kmalloc(ByteCount, GFP_KERNEL); if(Address != NULL) { memset(Address, 0, ByteCount); } return Address; } KVOID* _NalAllocateMemoryNonPaged( IN UINT32 ByteCount, IN UINT32 Alignment, OUT NAL_PHYSICAL_ADDRESS* PhysicalAddress, IN CHAR* NamedLocator, IN UINT32 LineNumber ) { KVOID* Allocation = NULL; NalDebugPrint("PAGE_SIZE = %d\n", PAGE_SIZE); if(ByteCount < Alignment) { ROUNDUP(ByteCount, Alignment); NalDebugPrint("Aligned bytecount = %d\n", ByteCount); } if(ByteCount <= (128 * 1024)) { Allocation = kmalloc(ByteCount, GFP_KERNEL | GFP_DMA); if(Allocation != NULL && PhysicalAddress != NULL) { *PhysicalAddress = (NAL_PHYSICAL_ADDRESS)__pa(Allocation); } } if(Allocation == NULL) { NalDebugPrint("Allocation failed: File: %s, Line %d\n", NamedLocator, LineNumber); } else { memset(Allocation, 0, ByteCount); if(PhysicalAddress != NULL) { NalDebugPrint("Phys Addr: %x", *PhysicalAddress); } NalDebugPrint("\n"); } return Allocation; } KVOID* _NalAllocateMemoryNonPagedEx( IN UINT32 ByteCount, IN UINT32 Alignment, IN UINTN ProcessId, OUT NAL_PHYSICAL_ADDRESS* PhysicalAddress, IN CHAR* NamedLocator, IN UINT32 LineNumber ) { return _NalAllocateMemoryNonPaged(ByteCount,Alignment,PhysicalAddress,NamedLocator,LineNumber); } KVOID* _NalAllocateMemoryNonPagedPci( IN KVOID* PDev, IN UINT32 ByteCount, IN UINT32 Alignment, OUT NAL_PHYSICAL_ADDRESS* PhysicalAddress, IN CHAR* NamedLocator, IN UINT32 LineNumber ) { KVOID* Allocation = NULL; struct pci_dev* LinuxPciDevice = (struct pci_dev*)PDev; dma_addr_t Dma; NalDebugPrint("PAGE_SIZE = %d\n", PAGE_SIZE); if(ByteCount < Alignment) { ROUNDUP(ByteCount, Alignment); NalDebugPrint("Aligned bytecount = %d\n", ByteCount); } if((LinuxPciDevice != NULL) && ByteCount <= NAL_OS_SPEC_MAX_CONTIGUOUS_MEMORY_ALLOCATION) { Allocation = pci_alloc_consistent(LinuxPciDevice,ByteCount, &Dma); *PhysicalAddress = (NAL_PHYSICAL_ADDRESS)Dma; } if(Allocation == NULL) { NalDebugPrint("Allocation failed: File: %s, Line %d\n", NamedLocator, LineNumber); } else { memset(Allocation, 0, ByteCount); if(PhysicalAddress != NULL) { NalDebugPrint("Phys Addr: %x", *PhysicalAddress); } NalDebugPrint("\n"); } return Allocation; } VOID _NalFreeMemory( IN VOID* Address, IN CHAR* NamedLocator, IN UINT32 LineNumber ) { if(Address != NULL) { kfree(Address); } } VOID _NalFreeMemoryNonPaged( IN KVOID* Address, IN CHAR* NamedLocator, IN UINT32 LineNumber ) { if(Address != NULL) { kfree(Address); } } VOID _NalFreeMemoryNonPagedEx( IN KVOID* Address, IN UINTN ProcessId, IN CHAR* NamedLocator, IN UINT32 LineNumber ) { _NalFreeMemoryNonPaged(Address,NamedLocator,LineNumber); } VOID NalFreeMemoryNonPagedPci( IN KVOID* PDev, IN KVOID* Address, IN NAL_PHYSICAL_ADDRESS PhysicalAddress, IN UINT32 Size ) { struct pci_dev* LinuxPciDevice = (struct pci_dev*)PDev; if(PDev != NULL && Address != NULL && PhysicalAddress != 0) { pci_free_consistent(LinuxPciDevice, Size, Address, PhysicalAddress); } } NAL_STATUS NalMmapAddress( IN OUT KVOID** VirtualAddress, IN NAL_PHYSICAL_ADDRESS PhysicalAddress, IN OUT UINT32* Length ) { NAL_STATUS NalStatus = NAL_INVALID_PARAMETER; if(VirtualAddress != NULL && Length != NULL) { *VirtualAddress = ioremap(PhysicalAddress, (UINT64)(*Length)); if(*VirtualAddress != NULL) { NalStatus = NAL_SUCCESS; } else { NalStatus = NAL_MMAP_FAILED; } } return NalStatus; } NAL_STATUS NalUnmapAddress( IN KVOID* VirtualAddress, IN NAL_PHYSICAL_ADDRESS PhysicalAddress, IN UINT32 Length ) { NAL_STATUS NalStatus = NAL_INVALID_PARAMETER; if(VirtualAddress != NULL) { iounmap(VirtualAddress); NalStatus = NAL_SUCCESS; } return NalStatus; } NAL_STATUS NalMmapAddressEx( IN OUT KVOID** VirtualAddress, IN NAL_PHYSICAL_ADDRESS PhysicalAddress, IN OUT UINT32* Length, IN UINTN ProcessId ) { return NalMmapAddress(VirtualAddress, PhysicalAddress, Length); } NAL_STATUS NalUnmapAddressEx( IN KVOID* VirtualAddress, IN NAL_PHYSICAL_ADDRESS PhysicalAddress, IN UINT32 Length, IN UINTN ProcessId ) { return NalUnmapAddress(VirtualAddress, PhysicalAddress, Length); } UINT8 NalReadRegister8( IN KVOID* Address ) { UINT8 Value = 0; if(Address != NULL) { Value = readb((CHAR*)Address); } return Value; } UINT16 NalReadRegister16( IN KVOID* Address ) { UINT16 Value = 0; if(Address != NULL) { Value = readw((CHAR*)Address); } return Value; } UINT32 NalReadRegister32( IN KVOID* Address ) { UINT32 Value = 0; if(Address != NULL) { Value = readl((CHAR*)Address); } return Value; } BOOLEAN NalWriteRegister8( IN KVOID* Address, IN UINT8 Value ) { BOOLEAN Success = FALSE; if(Address != NULL) { writeb(Value, (CHAR*)Address); Success = TRUE; } return Success; } BOOLEAN NalWriteRegister16( IN KVOID* Address, IN UINT16 Value ) { BOOLEAN Success = FALSE; if(Address != NULL) { writew(Value, (CHAR*)Address); Success = TRUE; } return Success; } BOOLEAN NalWriteRegister32( IN KVOID* Address, IN UINT32 Value ) { BOOLEAN Success = FALSE; if(Address != NULL) { writel(Value, (CHAR*)Address); Success = TRUE; } return Success; } NAL_PHYSICAL_ADDRESS NalGetPhysicalMemoryAddress( IN KVOID* VirtualAddress ) { NAL_PHYSICAL_ADDRESS NalPhysical = 0; if(VirtualAddress != NULL) { NalPhysical = __pa(VirtualAddress); } return NalPhysical; } NAL_PHYSICAL_ADDRESS NalGetPhysicalMemoryAddressEx( IN KVOID* VirtualAddress, IN UINTN ProcessId ) { return NalGetPhysicalMemoryAddress(VirtualAddress); } KVOID* NalKMemset( IN KVOID* Dest, IN int Value, IN UINTN Size ) { return memset(Dest, Value, Size); } VOID* NalKtoUMemcpy( IN VOID* Dest, IN KVOID* Source, IN UINTN Size ) { UINTN BytesLeft = 0; BytesLeft = copy_to_user(Dest, Source, Size); return Dest; } KVOID* NalKtoKMemcpy( IN KVOID* Dest, IN KVOID* Source, IN UINTN Size ) { return memcpy(Dest, Source, Size); } KVOID* NalUtoKMemcpy( IN KVOID* Dest, IN VOID* Source, IN UINTN Size ) { UINTN BytesLeft = 0; BytesLeft = copy_from_user(Dest, Source, Size); return Dest; }