1 /**********************************************************************
3 * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
9 * This program is distributed in the hope it will be useful but, except
10 * as otherwise stated in writing, without any warranty; without even the
11 * implied warranty of merchantability or fitness for a particular purpose.
12 * See the GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
18 * The full GNU General Public License is included in this distribution in
19 * the file called "COPYING".
21 * Contact Information:
22 * Imagination Technologies Ltd. <gpl-support@imgtec.com>
23 * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
25 ******************************************************************************/
27 #ifndef AUTOCONF_INCLUDED
28 #include <linux/config.h>
31 #include <linux/version.h>
34 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22))
35 #include <asm/system.h>
38 #include <linux/pagemap.h>
39 #include <linux/hugetlb.h>
40 #include <linux/slab.h>
41 #include <linux/vmalloc.h>
42 #include <linux/delay.h>
43 #include <linux/pci.h>
45 #include <linux/string.h>
46 #include <linux/sched.h>
47 #include <linux/interrupt.h>
48 #include <asm/hardirq.h>
49 #include <linux/timer.h>
50 #include <linux/capability.h>
51 #include <asm/uaccess.h>
53 #include "img_types.h"
54 #include "services_headers.h"
63 #define EVENT_OBJECT_TIMEOUT_MS (100)
65 extern PVRSRV_LINUX_MUTEX gPVRSRVLock;
67 #define HOST_ALLOC_MEM_USING_KMALLOC ((IMG_HANDLE)0)
68 #define HOST_ALLOC_MEM_USING_VMALLOC ((IMG_HANDLE)1)
70 #if !defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
71 PVRSRV_ERROR OSAllocMem(IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size,
72 IMG_PVOID * ppvCpuVAddr, IMG_HANDLE * phBlockAlloc)
74 PVRSRV_ERROR _OSAllocMem(IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size,
75 IMG_PVOID * ppvCpuVAddr, IMG_HANDLE * phBlockAlloc,
76 IMG_CHAR * pszFilename, IMG_UINT32 ui32Line)
79 PVR_UNREFERENCED_PARAMETER(ui32Flags);
81 #if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
82 *ppvCpuVAddr = _KMallocWrapper(ui32Size, pszFilename, ui32Line);
84 *ppvCpuVAddr = KMallocWrapper(ui32Size);
89 *phBlockAlloc = HOST_ALLOC_MEM_USING_KMALLOC;
93 return PVRSRV_ERROR_OUT_OF_MEMORY;
96 #if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
98 _VMallocWrapper(ui32Size, PVRSRV_HAP_CACHED, pszFilename,
101 *ppvCpuVAddr = VMallocWrapper(ui32Size, PVRSRV_HAP_CACHED);
104 return PVRSRV_ERROR_OUT_OF_MEMORY;
107 *phBlockAlloc = HOST_ALLOC_MEM_USING_VMALLOC;
113 #if !defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
114 PVRSRV_ERROR OSFreeMem(IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size,
115 IMG_PVOID pvCpuVAddr, IMG_HANDLE hBlockAlloc)
117 PVRSRV_ERROR _OSFreeMem(IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size,
118 IMG_PVOID pvCpuVAddr, IMG_HANDLE hBlockAlloc,
119 IMG_CHAR * pszFilename, IMG_UINT32 ui32Line)
122 PVR_UNREFERENCED_PARAMETER(ui32Flags);
123 PVR_UNREFERENCED_PARAMETER(ui32Size);
125 if (hBlockAlloc == HOST_ALLOC_MEM_USING_VMALLOC) {
126 #if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
127 _VFreeWrapper(pvCpuVAddr, pszFilename, ui32Line);
129 VFreeWrapper(pvCpuVAddr);
132 #if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
133 _KFreeWrapper(pvCpuVAddr, pszFilename, ui32Line);
135 KFreeWrapper(pvCpuVAddr);
143 OSAllocPages(IMG_UINT32 ui32AllocFlags,
145 IMG_VOID ** ppvCpuVAddr, IMG_HANDLE * phOSMemHandle)
147 LinuxMemArea *psLinuxMemArea;
151 if (ui32AllocFlags & PVRSRV_HAP_SINGLE_PROCESS) {
152 ui32AllocFlags &= ~PVRSRV_HAP_SINGLE_PROCESS;
153 ui32AllocFlags |= PVRSRV_HAP_MULTI_PROCESS;
157 switch (ui32AllocFlags & PVRSRV_HAP_MAPTYPE_MASK) {
158 case PVRSRV_HAP_KERNEL_ONLY:
161 NewVMallocLinuxMemArea(ui32Size, ui32AllocFlags);
162 if (!psLinuxMemArea) {
163 return PVRSRV_ERROR_OUT_OF_MEMORY;
167 case PVRSRV_HAP_SINGLE_PROCESS:
171 NewAllocPagesLinuxMemArea(ui32Size, ui32AllocFlags);
172 if (!psLinuxMemArea) {
173 return PVRSRV_ERROR_OUT_OF_MEMORY;
175 PVRMMapRegisterArea("Import Arena", psLinuxMemArea,
180 case PVRSRV_HAP_MULTI_PROCESS:
183 #if defined(VIVT_CACHE) || defined(__sh__)
185 ui32AllocFlags &= ~PVRSRV_HAP_CACHED;
188 NewVMallocLinuxMemArea(ui32Size, ui32AllocFlags);
189 if (!psLinuxMemArea) {
190 return PVRSRV_ERROR_OUT_OF_MEMORY;
192 PVRMMapRegisterArea("Import Arena", psLinuxMemArea,
197 PVR_DPF((PVR_DBG_ERROR, "OSAllocPages: invalid flags 0x%x\n",
200 *phOSMemHandle = (IMG_HANDLE) 0;
201 return PVRSRV_ERROR_INVALID_PARAMS;
204 *ppvCpuVAddr = LinuxMemAreaToCpuVAddr(psLinuxMemArea);
205 *phOSMemHandle = psLinuxMemArea;
207 LinuxMemAreaRegister(psLinuxMemArea);
213 OSFreePages(IMG_UINT32 ui32AllocFlags, IMG_UINT32 ui32Bytes,
214 IMG_VOID * pvCpuVAddr, IMG_HANDLE hOSMemHandle)
216 LinuxMemArea *psLinuxMemArea;
217 PVR_UNREFERENCED_PARAMETER(pvCpuVAddr);
219 psLinuxMemArea = (LinuxMemArea *) hOSMemHandle;
221 switch (ui32AllocFlags & PVRSRV_HAP_MAPTYPE_MASK) {
222 case PVRSRV_HAP_KERNEL_ONLY:
224 case PVRSRV_HAP_SINGLE_PROCESS:
225 case PVRSRV_HAP_MULTI_PROCESS:
226 if (PVRMMapRemoveRegisteredArea(psLinuxMemArea) != PVRSRV_OK) {
227 PVR_DPF((PVR_DBG_ERROR,
228 "OSFreePages(ui32AllocFlags=0x%08X, ui32Bytes=%ld, "
229 "pvCpuVAddr=%p, hOSMemHandle=%p) FAILED!",
230 ui32AllocFlags, ui32Bytes, pvCpuVAddr,
232 return PVRSRV_ERROR_GENERIC;
236 PVR_DPF((PVR_DBG_ERROR, "%s: invalid flags 0x%x\n",
237 __FUNCTION__, ui32AllocFlags));
238 return PVRSRV_ERROR_INVALID_PARAMS;
241 LinuxMemAreaDeepFree(psLinuxMemArea);
247 OSGetSubMemHandle(IMG_HANDLE hOSMemHandle,
248 IMG_UINT32 ui32ByteOffset,
249 IMG_UINT32 ui32Bytes,
250 IMG_UINT32 ui32Flags, IMG_HANDLE * phOSMemHandleRet)
252 LinuxMemArea *psParentLinuxMemArea, *psLinuxMemArea;
253 PVRSRV_ERROR eError = PVRSRV_OK;
255 psParentLinuxMemArea = (LinuxMemArea *) hOSMemHandle;
258 NewSubLinuxMemArea(psParentLinuxMemArea, ui32ByteOffset, ui32Bytes);
259 if (!psLinuxMemArea) {
260 *phOSMemHandleRet = NULL;
261 return PVRSRV_ERROR_OUT_OF_MEMORY;
263 *phOSMemHandleRet = psLinuxMemArea;
265 if (ui32Flags & PVRSRV_HAP_KERNEL_ONLY) {
269 if (psParentLinuxMemArea->eAreaType == LINUX_MEM_AREA_IO) {
270 eError = PVRMMapRegisterArea("Physical", psLinuxMemArea, 0);
271 if (eError != PVRSRV_OK) {
272 goto failed_register_area;
274 } else if (psParentLinuxMemArea->eAreaType ==
275 LINUX_MEM_AREA_ALLOC_PAGES) {
276 eError = PVRMMapRegisterArea("Import Arena", psLinuxMemArea, 0);
277 if (eError != PVRSRV_OK) {
278 goto failed_register_area;
284 failed_register_area:
285 *phOSMemHandleRet = NULL;
286 LinuxMemAreaDeepFree(psLinuxMemArea);
291 OSReleaseSubMemHandle(IMG_VOID * hOSMemHandle, IMG_UINT32 ui32Flags)
293 LinuxMemArea *psParentLinuxMemArea, *psLinuxMemArea;
296 psLinuxMemArea = (LinuxMemArea *) hOSMemHandle;
297 PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_SUB_ALLOC);
299 psParentLinuxMemArea =
300 psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea;
302 if (!(ui32Flags & PVRSRV_HAP_KERNEL_ONLY)
303 && (psParentLinuxMemArea->eAreaType == LINUX_MEM_AREA_IO
304 || psParentLinuxMemArea->eAreaType ==
305 LINUX_MEM_AREA_ALLOC_PAGES)
307 eError = PVRMMapRemoveRegisteredArea(psLinuxMemArea);
308 if (eError != PVRSRV_OK) {
312 LinuxMemAreaDeepFree(psLinuxMemArea);
318 OSMemHandleToCpuPAddr(IMG_VOID * hOSMemHandle, IMG_UINT32 ui32ByteOffset)
320 PVR_ASSERT(hOSMemHandle);
322 return LinuxMemAreaToCpuPAddr(hOSMemHandle, ui32ByteOffset);
325 IMG_VOID OSMemCopy(IMG_VOID * pvDst, IMG_VOID * pvSrc, IMG_UINT32 ui32Size)
327 #if defined(USE_UNOPTIMISED_MEMCPY)
328 unsigned char *Src, *Dst;
331 Src = (unsigned char *)pvSrc;
332 Dst = (unsigned char *)pvDst;
333 for (i = 0; i < ui32Size; i++) {
337 memcpy(pvDst, pvSrc, ui32Size);
341 IMG_VOID OSMemSet(IMG_VOID * pvDest, IMG_UINT8 ui8Value, IMG_UINT32 ui32Size)
343 #if defined(USE_UNOPTIMISED_MEMSET)
347 Buff = (unsigned char *)pvDest;
348 for (i = 0; i < ui32Size; i++) {
352 memset(pvDest, (int)ui8Value, (size_t) ui32Size);
356 IMG_CHAR *OSStringCopy(IMG_CHAR * pszDest, const IMG_CHAR * pszSrc)
358 return (strcpy(pszDest, pszSrc));
361 IMG_INT32 OSSNPrintf(IMG_CHAR * pStr, IMG_UINT32 ui32Size,
362 const IMG_CHAR * pszFormat, ...)
367 va_start(argList, pszFormat);
368 iCount = vsnprintf(pStr, (size_t) ui32Size, pszFormat, argList);
374 IMG_VOID OSBreakResourceLock(PVRSRV_RESOURCE * psResource, IMG_UINT32 ui32ID)
376 volatile IMG_UINT32 *pui32Access =
377 (volatile IMG_UINT32 *)&psResource->ui32Lock;
380 if (psResource->ui32ID == ui32ID) {
381 psResource->ui32ID = 0;
384 PVR_DPF((PVR_DBG_MESSAGE,
385 "OSBreakResourceLock: Resource is not locked for this process."));
388 PVR_DPF((PVR_DBG_MESSAGE,
389 "OSBreakResourceLock: Resource is not locked"));
393 PVRSRV_ERROR OSCreateResource(PVRSRV_RESOURCE * psResource)
395 psResource->ui32ID = 0;
396 psResource->ui32Lock = 0;
401 PVRSRV_ERROR OSDestroyResource(PVRSRV_RESOURCE * psResource)
403 OSBreakResourceLock(psResource, psResource->ui32ID);
408 PVRSRV_ERROR OSInitEnvData(IMG_PVOID * ppvEnvSpecificData)
413 (PVRSRV_OS_PAGEABLE_HEAP, sizeof(ENV_DATA),
414 (IMG_VOID *) & psEnvData, IMG_NULL) != PVRSRV_OK) {
415 return PVRSRV_ERROR_GENERIC;
419 (PVRSRV_OS_PAGEABLE_HEAP,
420 PVRSRV_MAX_BRIDGE_IN_SIZE + PVRSRV_MAX_BRIDGE_OUT_SIZE,
421 &psEnvData->pvBridgeData, IMG_NULL) != PVRSRV_OK) {
422 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(ENV_DATA), psEnvData,
424 return PVRSRV_ERROR_GENERIC;
427 psEnvData->bMISRInstalled = IMG_FALSE;
428 psEnvData->bLISRInstalled = IMG_FALSE;
430 *ppvEnvSpecificData = psEnvData;
435 PVRSRV_ERROR OSDeInitEnvData(IMG_PVOID pvEnvSpecificData)
437 ENV_DATA *psEnvData = (ENV_DATA *) pvEnvSpecificData;
439 PVR_ASSERT(!psEnvData->bMISRInstalled);
440 PVR_ASSERT(!psEnvData->bLISRInstalled);
442 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0x1000, psEnvData->pvBridgeData,
445 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(ENV_DATA), pvEnvSpecificData,
451 IMG_VOID OSReleaseThreadQuanta(IMG_VOID)
456 IMG_UINT32 OSClockus(IMG_VOID)
458 unsigned long time, j = jiffies;
460 time = j * (1000000 / HZ);
465 IMG_VOID OSWaitus(IMG_UINT32 ui32Timeus)
470 IMG_UINT32 OSGetCurrentProcessIDKM(IMG_VOID)
472 if (in_interrupt()) {
475 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
476 return current->pgrp;
478 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24))
479 return task_tgid_nr(current);
481 return current->tgid;
486 IMG_UINT32 OSGetPageSize(IMG_VOID)
489 IMG_UINT32 ui32ReturnValue = PAGE_SIZE;
491 return (ui32ReturnValue);
497 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0))
498 static irqreturn_t DeviceISRWrapper(int irq, void *dev_id
499 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19))
500 , struct pt_regs *regs
504 PVRSRV_DEVICE_NODE *psDeviceNode;
505 IMG_BOOL bStatus = IMG_FALSE;
507 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19))
508 PVR_UNREFERENCED_PARAMETER(regs);
510 psDeviceNode = (PVRSRV_DEVICE_NODE *) dev_id;
512 PVR_DPF((PVR_DBG_ERROR, "DeviceISRWrapper: invalid params\n"));
516 bStatus = PVRSRVDeviceLISR(psDeviceNode);
519 SYS_DATA *psSysData = psDeviceNode->psSysData;
520 ENV_DATA *psEnvData = (ENV_DATA *) psSysData->pvEnvSpecificData;
522 tasklet_schedule(&psEnvData->sMISRTasklet);
526 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
527 return bStatus ? IRQ_HANDLED : IRQ_NONE;
531 static irqreturn_t SystemISRWrapper(int irq, void *dev_id
532 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19))
533 , struct pt_regs *regs
538 IMG_BOOL bStatus = IMG_FALSE;
540 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19))
541 PVR_UNREFERENCED_PARAMETER(regs);
543 psSysData = (SYS_DATA *) dev_id;
545 PVR_DPF((PVR_DBG_ERROR, "SystemISRWrapper: invalid params\n"));
549 bStatus = PVRSRVSystemLISR(psSysData);
552 ENV_DATA *psEnvData = (ENV_DATA *) psSysData->pvEnvSpecificData;
554 tasklet_schedule(&psEnvData->sMISRTasklet);
558 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
559 return bStatus ? IRQ_HANDLED : IRQ_NONE;
563 PVRSRV_ERROR OSInstallDeviceLISR(IMG_VOID * pvSysData,
565 IMG_CHAR * pszISRName, IMG_VOID * pvDeviceNode)
567 SYS_DATA *psSysData = (SYS_DATA *) pvSysData;
568 ENV_DATA *psEnvData = (ENV_DATA *) psSysData->pvEnvSpecificData;
570 if (psEnvData->bLISRInstalled) {
571 PVR_DPF((PVR_DBG_ERROR,
572 "OSInstallDeviceLISR: An ISR has already been installed: IRQ %d cookie %x",
573 psEnvData->ui32IRQ, psEnvData->pvISRCookie));
574 return PVRSRV_ERROR_GENERIC;
577 PVR_TRACE(("Installing device LISR %s on IRQ %d with cookie %x",
578 pszISRName, ui32Irq, pvDeviceNode));
580 if (request_irq(ui32Irq, DeviceISRWrapper,
581 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22))
586 , pszISRName, pvDeviceNode)) {
587 PVR_DPF((PVR_DBG_ERROR,
588 "OSInstallDeviceLISR: Couldn't install device LISR on IRQ %d",
591 return PVRSRV_ERROR_GENERIC;
594 psEnvData->ui32IRQ = ui32Irq;
595 psEnvData->pvISRCookie = pvDeviceNode;
596 psEnvData->bLISRInstalled = IMG_TRUE;
601 PVRSRV_ERROR OSUninstallDeviceLISR(IMG_VOID * pvSysData)
603 SYS_DATA *psSysData = (SYS_DATA *) pvSysData;
604 ENV_DATA *psEnvData = (ENV_DATA *) psSysData->pvEnvSpecificData;
606 if (!psEnvData->bLISRInstalled) {
607 PVR_DPF((PVR_DBG_ERROR,
608 "OSUninstallDeviceLISR: No LISR has been installed"));
609 return PVRSRV_ERROR_GENERIC;
612 PVR_TRACE(("Uninstalling device LISR on IRQ %d with cookie %x",
613 psEnvData->ui32IRQ, psEnvData->pvISRCookie));
615 free_irq(psEnvData->ui32IRQ, psEnvData->pvISRCookie);
617 psEnvData->bLISRInstalled = IMG_FALSE;
622 PVRSRV_ERROR OSInstallSystemLISR(IMG_VOID * pvSysData, IMG_UINT32 ui32Irq)
624 SYS_DATA *psSysData = (SYS_DATA *) pvSysData;
625 ENV_DATA *psEnvData = (ENV_DATA *) psSysData->pvEnvSpecificData;
627 if (psEnvData->bLISRInstalled) {
628 PVR_DPF((PVR_DBG_ERROR,
629 "OSInstallSystemLISR: An LISR has already been installed: IRQ %d cookie %x",
630 psEnvData->ui32IRQ, psEnvData->pvISRCookie));
631 return PVRSRV_ERROR_GENERIC;
634 PVR_TRACE(("Installing system LISR on IRQ %d with cookie %x", ui32Irq,
637 if (request_irq(ui32Irq, SystemISRWrapper,
638 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22))
643 , "PowerVR", pvSysData)) {
644 PVR_DPF((PVR_DBG_ERROR,
645 "OSInstallSystemLISR: Couldn't install system LISR on IRQ %d",
648 return PVRSRV_ERROR_GENERIC;
651 psEnvData->ui32IRQ = ui32Irq;
652 psEnvData->pvISRCookie = pvSysData;
653 psEnvData->bLISRInstalled = IMG_TRUE;
658 PVRSRV_ERROR OSUninstallSystemLISR(IMG_VOID * pvSysData)
660 SYS_DATA *psSysData = (SYS_DATA *) pvSysData;
661 ENV_DATA *psEnvData = (ENV_DATA *) psSysData->pvEnvSpecificData;
663 if (!psEnvData->bLISRInstalled) {
664 PVR_DPF((PVR_DBG_ERROR,
665 "OSUninstallSystemLISR: No LISR has been installed"));
666 return PVRSRV_ERROR_GENERIC;
669 PVR_TRACE(("Uninstalling system LISR on IRQ %d with cookie %x",
670 psEnvData->ui32IRQ, psEnvData->pvISRCookie));
672 free_irq(psEnvData->ui32IRQ, psEnvData->pvISRCookie);
674 psEnvData->bLISRInstalled = IMG_FALSE;
679 static void MISRWrapper(unsigned long data)
683 psSysData = (SYS_DATA *) data;
685 PVRSRVMISR(psSysData);
688 PVRSRV_ERROR OSInstallMISR(IMG_VOID * pvSysData)
690 SYS_DATA *psSysData = (SYS_DATA *) pvSysData;
691 ENV_DATA *psEnvData = (ENV_DATA *) psSysData->pvEnvSpecificData;
693 if (psEnvData->bMISRInstalled) {
694 PVR_DPF((PVR_DBG_ERROR,
695 "OSInstallMISR: An MISR has already been installed"));
696 return PVRSRV_ERROR_GENERIC;
699 PVR_TRACE(("Installing MISR with cookie %x", pvSysData));
701 tasklet_init(&psEnvData->sMISRTasklet, MISRWrapper,
702 (unsigned long)pvSysData);
704 psEnvData->bMISRInstalled = IMG_TRUE;
709 PVRSRV_ERROR OSUninstallMISR(IMG_VOID * pvSysData)
711 SYS_DATA *psSysData = (SYS_DATA *) pvSysData;
712 ENV_DATA *psEnvData = (ENV_DATA *) psSysData->pvEnvSpecificData;
714 if (!psEnvData->bMISRInstalled) {
715 PVR_DPF((PVR_DBG_ERROR,
716 "OSUninstallMISR: No MISR has been installed"));
717 return PVRSRV_ERROR_GENERIC;
720 PVR_TRACE(("Uninstalling MISR"));
722 tasklet_kill(&psEnvData->sMISRTasklet);
724 psEnvData->bMISRInstalled = IMG_FALSE;
729 PVRSRV_ERROR OSScheduleMISR(IMG_VOID * pvSysData)
731 SYS_DATA *psSysData = (SYS_DATA *) pvSysData;
732 ENV_DATA *psEnvData = (ENV_DATA *) psSysData->pvEnvSpecificData;
734 if (psEnvData->bMISRInstalled) {
735 tasklet_schedule(&psEnvData->sMISRTasklet);
743 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22))
744 #define OS_TAS(p) xchg((p), 1)
746 #define OS_TAS(p) tas(p)
748 PVRSRV_ERROR OSLockResource(PVRSRV_RESOURCE * psResource, IMG_UINT32 ui32ID)
750 PVRSRV_ERROR eError = PVRSRV_OK;
752 if (!OS_TAS(&psResource->ui32Lock))
753 psResource->ui32ID = ui32ID;
755 eError = PVRSRV_ERROR_GENERIC;
760 PVRSRV_ERROR OSUnlockResource(PVRSRV_RESOURCE * psResource, IMG_UINT32 ui32ID)
762 volatile IMG_UINT32 *pui32Access =
763 (volatile IMG_UINT32 *)&psResource->ui32Lock;
764 PVRSRV_ERROR eError = PVRSRV_OK;
767 if (psResource->ui32ID == ui32ID) {
768 psResource->ui32ID = 0;
771 PVR_DPF((PVR_DBG_ERROR,
772 "OSUnlockResource: Resource %p is not locked with expected value.",
774 PVR_DPF((PVR_DBG_MESSAGE, "Should be %x is actually %x",
775 ui32ID, psResource->ui32ID));
776 eError = PVRSRV_ERROR_GENERIC;
779 PVR_DPF((PVR_DBG_ERROR,
780 "OSUnlockResource: Resource %p is not locked",
782 eError = PVRSRV_ERROR_GENERIC;
788 IMG_BOOL OSIsResourceLocked(PVRSRV_RESOURCE * psResource, IMG_UINT32 ui32ID)
790 volatile IMG_UINT32 *pui32Access =
791 (volatile IMG_UINT32 *)&psResource->ui32Lock;
793 return (*(volatile IMG_UINT32 *)pui32Access == 1)
794 && (psResource->ui32ID == ui32ID)
795 ? IMG_TRUE : IMG_FALSE;
798 IMG_CPU_PHYADDR OSMapLinToCPUPhys(IMG_VOID * pvLinAddr)
800 IMG_CPU_PHYADDR CpuPAddr;
802 CpuPAddr.uiAddr = (IMG_UINTPTR_T) VMallocToPhys(pvLinAddr);
807 IMG_VOID *OSMapPhysToLin(IMG_CPU_PHYADDR BasePAddr,
808 IMG_UINT32 ui32Bytes,
809 IMG_UINT32 ui32MappingFlags,
810 IMG_HANDLE * phOSMemHandle)
813 *phOSMemHandle = (IMG_HANDLE) 0;
816 if (ui32MappingFlags & PVRSRV_HAP_KERNEL_ONLY) {
817 IMG_VOID *pvIORemapCookie;
819 IORemapWrapper(BasePAddr, ui32Bytes, ui32MappingFlags);
820 if (pvIORemapCookie == IMG_NULL) {
823 return pvIORemapCookie;
825 PVR_DPF((PVR_DBG_ERROR,
826 "OSMapPhysToLin should only be used with PVRSRV_HAP_KERNEL_ONLY "
827 " (Use OSReservePhys otherwise)"));
828 *phOSMemHandle = (IMG_HANDLE) 0;
837 OSUnMapPhysToLin(IMG_VOID * pvLinAddr, IMG_UINT32 ui32Bytes,
838 IMG_UINT32 ui32MappingFlags, IMG_HANDLE hPageAlloc)
840 PVR_TRACE(("%s: unmapping %d bytes from 0x%08x", __FUNCTION__,
841 ui32Bytes, pvLinAddr));
843 PVR_UNREFERENCED_PARAMETER(hPageAlloc);
845 if (ui32MappingFlags & PVRSRV_HAP_KERNEL_ONLY) {
846 IOUnmapWrapper(pvLinAddr);
849 PVR_DPF((PVR_DBG_ERROR,
850 "OSUnMapPhysToLin should only be used with PVRSRV_HAP_KERNEL_ONLY "
851 " (Use OSUnReservePhys otherwise)"));
860 RegisterExternalMem(IMG_SYS_PHYADDR * pBasePAddr,
861 IMG_VOID * pvCPUVAddr,
862 IMG_UINT32 ui32Bytes,
863 IMG_BOOL bPhysContig,
864 IMG_UINT32 ui32MappingFlags, IMG_HANDLE * phOSMemHandle)
866 LinuxMemArea *psLinuxMemArea;
868 switch (ui32MappingFlags & PVRSRV_HAP_MAPTYPE_MASK) {
869 case PVRSRV_HAP_KERNEL_ONLY:
872 NewExternalKVLinuxMemArea(pBasePAddr, pvCPUVAddr,
873 ui32Bytes, bPhysContig,
876 if (!psLinuxMemArea) {
877 return PVRSRV_ERROR_GENERIC;
881 case PVRSRV_HAP_SINGLE_PROCESS:
884 NewExternalKVLinuxMemArea(pBasePAddr, pvCPUVAddr,
885 ui32Bytes, bPhysContig,
888 if (!psLinuxMemArea) {
889 return PVRSRV_ERROR_GENERIC;
891 PVRMMapRegisterArea("Physical", psLinuxMemArea,
895 case PVRSRV_HAP_MULTI_PROCESS:
898 #if defined(VIVT_CACHE) || defined(__sh__)
900 ui32MappingFlags &= ~PVRSRV_HAP_CACHED;
903 NewExternalKVLinuxMemArea(pBasePAddr, pvCPUVAddr,
904 ui32Bytes, bPhysContig,
907 if (!psLinuxMemArea) {
908 return PVRSRV_ERROR_GENERIC;
910 PVRMMapRegisterArea("Physical", psLinuxMemArea,
915 PVR_DPF((PVR_DBG_ERROR, "OSRegisterMem : invalid flags 0x%x\n",
917 *phOSMemHandle = (IMG_HANDLE) 0;
918 return PVRSRV_ERROR_GENERIC;
921 *phOSMemHandle = (IMG_HANDLE) psLinuxMemArea;
923 LinuxMemAreaRegister(psLinuxMemArea);
929 OSRegisterMem(IMG_CPU_PHYADDR BasePAddr,
930 IMG_VOID * pvCPUVAddr,
931 IMG_UINT32 ui32Bytes,
932 IMG_UINT32 ui32MappingFlags, IMG_HANDLE * phOSMemHandle)
934 IMG_SYS_PHYADDR SysPAddr = SysCpuPAddrToSysPAddr(BasePAddr);
936 return RegisterExternalMem(&SysPAddr, pvCPUVAddr, ui32Bytes, IMG_TRUE,
937 ui32MappingFlags, phOSMemHandle);
940 PVRSRV_ERROR OSRegisterDiscontigMem(IMG_SYS_PHYADDR * pBasePAddr,
941 IMG_VOID * pvCPUVAddr, IMG_UINT32 ui32Bytes,
942 IMG_UINT32 ui32MappingFlags,
943 IMG_HANDLE * phOSMemHandle)
945 return RegisterExternalMem(pBasePAddr, pvCPUVAddr, ui32Bytes, IMG_FALSE,
946 ui32MappingFlags, phOSMemHandle);
950 OSUnRegisterMem(IMG_VOID * pvCpuVAddr,
951 IMG_UINT32 ui32Bytes,
952 IMG_UINT32 ui32MappingFlags, IMG_HANDLE hOSMemHandle)
954 LinuxMemArea *psLinuxMemArea = (LinuxMemArea *) hOSMemHandle;
956 PVR_UNREFERENCED_PARAMETER(pvCpuVAddr);
958 switch (ui32MappingFlags & PVRSRV_HAP_MAPTYPE_MASK) {
959 case PVRSRV_HAP_KERNEL_ONLY:
961 case PVRSRV_HAP_SINGLE_PROCESS:
962 case PVRSRV_HAP_MULTI_PROCESS:
964 if (PVRMMapRemoveRegisteredArea(psLinuxMemArea) !=
966 PVR_DPF((PVR_DBG_ERROR,
967 "%s(%p, %d, 0x%08X, %p) FAILED!",
968 __FUNCTION__, pvCpuVAddr, ui32Bytes,
969 ui32MappingFlags, hOSMemHandle));
970 return PVRSRV_ERROR_GENERIC;
976 PVR_DPF((PVR_DBG_ERROR,
977 "OSUnRegisterMem : invalid flags 0x%x",
979 return PVRSRV_ERROR_INVALID_PARAMS;
983 LinuxMemAreaDeepFree(psLinuxMemArea);
988 PVRSRV_ERROR OSUnRegisterDiscontigMem(IMG_VOID * pvCpuVAddr,
989 IMG_UINT32 ui32Bytes,
990 IMG_UINT32 ui32Flags,
991 IMG_HANDLE hOSMemHandle)
993 return OSUnRegisterMem(pvCpuVAddr, ui32Bytes, ui32Flags, hOSMemHandle);
997 OSReservePhys(IMG_CPU_PHYADDR BasePAddr,
998 IMG_UINT32 ui32Bytes,
999 IMG_UINT32 ui32MappingFlags,
1000 IMG_VOID ** ppvCpuVAddr, IMG_HANDLE * phOSMemHandle)
1002 LinuxMemArea *psLinuxMemArea;
1006 if (ui32MappingFlags & PVRSRV_HAP_SINGLE_PROCESS) {
1007 ui32MappingFlags &= ~PVRSRV_HAP_SINGLE_PROCESS;
1008 ui32MappingFlags |= PVRSRV_HAP_MULTI_PROCESS;
1012 switch (ui32MappingFlags & PVRSRV_HAP_MAPTYPE_MASK) {
1013 case PVRSRV_HAP_KERNEL_ONLY:
1017 NewIORemapLinuxMemArea(BasePAddr, ui32Bytes,
1019 if (!psLinuxMemArea) {
1020 return PVRSRV_ERROR_GENERIC;
1024 case PVRSRV_HAP_SINGLE_PROCESS:
1028 NewIOLinuxMemArea(BasePAddr, ui32Bytes,
1030 if (!psLinuxMemArea) {
1031 return PVRSRV_ERROR_GENERIC;
1033 PVRMMapRegisterArea("Physical", psLinuxMemArea,
1037 case PVRSRV_HAP_MULTI_PROCESS:
1040 #if defined(VIVT_CACHE) || defined(__sh__)
1042 ui32MappingFlags &= ~PVRSRV_HAP_CACHED;
1045 NewIORemapLinuxMemArea(BasePAddr, ui32Bytes,
1047 if (!psLinuxMemArea) {
1048 return PVRSRV_ERROR_GENERIC;
1050 PVRMMapRegisterArea("Physical", psLinuxMemArea,
1055 PVR_DPF((PVR_DBG_ERROR, "OSMapPhysToLin : invalid flags 0x%x\n",
1057 *ppvCpuVAddr = NULL;
1058 *phOSMemHandle = (IMG_HANDLE) 0;
1059 return PVRSRV_ERROR_GENERIC;
1062 *phOSMemHandle = (IMG_HANDLE) psLinuxMemArea;
1063 *ppvCpuVAddr = LinuxMemAreaToCpuVAddr(psLinuxMemArea);
1065 LinuxMemAreaRegister(psLinuxMemArea);
1071 OSUnReservePhys(IMG_VOID * pvCpuVAddr,
1072 IMG_UINT32 ui32Bytes,
1073 IMG_UINT32 ui32MappingFlags, IMG_HANDLE hOSMemHandle)
1075 LinuxMemArea *psLinuxMemArea;
1076 PVR_UNREFERENCED_PARAMETER(pvCpuVAddr);
1078 psLinuxMemArea = (LinuxMemArea *) hOSMemHandle;
1080 switch (ui32MappingFlags & PVRSRV_HAP_MAPTYPE_MASK) {
1081 case PVRSRV_HAP_KERNEL_ONLY:
1083 case PVRSRV_HAP_SINGLE_PROCESS:
1084 case PVRSRV_HAP_MULTI_PROCESS:
1086 if (PVRMMapRemoveRegisteredArea(psLinuxMemArea) !=
1088 PVR_DPF((PVR_DBG_ERROR,
1089 "%s(%p, %d, 0x%08X, %p) FAILED!",
1090 __FUNCTION__, pvCpuVAddr, ui32Bytes,
1091 ui32MappingFlags, hOSMemHandle));
1092 return PVRSRV_ERROR_GENERIC;
1098 PVR_DPF((PVR_DBG_ERROR,
1099 "OSUnMapPhysToLin : invalid flags 0x%x",
1101 return PVRSRV_ERROR_INVALID_PARAMS;
1105 LinuxMemAreaDeepFree(psLinuxMemArea);
1110 PVRSRV_ERROR OSBaseAllocContigMemory(IMG_UINT32 ui32Size,
1111 IMG_CPU_VIRTADDR * pvLinAddr,
1112 IMG_CPU_PHYADDR * psPhysAddr)
1114 #if !defined(NO_HARDWARE)
1115 PVR_UNREFERENCED_PARAMETER(ui32Size);
1116 PVR_UNREFERENCED_PARAMETER(pvLinAddr);
1117 PVR_UNREFERENCED_PARAMETER(psPhysAddr);
1118 PVR_DPF((PVR_DBG_ERROR, "%s: Not available", __FUNCTION__));
1120 return PVRSRV_ERROR_OUT_OF_MEMORY;
1122 void *pvKernLinAddr;
1124 #if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
1125 pvKernLinAddr = _KMallocWrapper(ui32Size, __FILE__, __LINE__);
1127 pvKernLinAddr = KMallocWrapper(ui32Size);
1129 if (!pvKernLinAddr) {
1130 return PVRSRV_ERROR_OUT_OF_MEMORY;
1133 *pvLinAddr = pvKernLinAddr;
1135 psPhysAddr->uiAddr = virt_to_phys(pvKernLinAddr);
1141 PVRSRV_ERROR OSBaseFreeContigMemory(IMG_UINT32 ui32Size,
1142 IMG_CPU_VIRTADDR pvLinAddr,
1143 IMG_CPU_PHYADDR psPhysAddr)
1145 #if !defined(NO_HARDWARE)
1146 PVR_UNREFERENCED_PARAMETER(ui32Size);
1147 PVR_UNREFERENCED_PARAMETER(pvLinAddr);
1148 PVR_UNREFERENCED_PARAMETER(psPhysAddr);
1150 PVR_DPF((PVR_DBG_WARNING, "%s: Not available", __FUNCTION__));
1152 PVR_UNREFERENCED_PARAMETER(ui32Size);
1153 PVR_UNREFERENCED_PARAMETER(psPhysAddr);
1155 KFreeWrapper(pvLinAddr);
1160 IMG_UINT32 OSReadHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset)
1162 #if !defined(NO_HARDWARE)
1163 return (IMG_UINT32) readl(pvLinRegBaseAddr + ui32Offset);
1165 return *(IMG_UINT32 *) (pvLinRegBaseAddr + ui32Offset);
1169 IMG_VOID OSWriteHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset,
1170 IMG_UINT32 ui32Value)
1172 #if !defined(NO_HARDWARE)
1173 writel(ui32Value, pvLinRegBaseAddr + ui32Offset);
1175 *(IMG_UINT32 *) (pvLinRegBaseAddr + ui32Offset) = ui32Value;
1179 #if defined(CONFIG_PCI) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14))
1181 PVRSRV_PCI_DEV_HANDLE OSPCISetDev(IMG_VOID * pvPCICookie,
1182 HOST_PCI_INIT_FLAGS eFlags)
1186 PVR_PCI_DEV *psPVRPCI;
1188 PVR_TRACE(("OSPCISetDev"));
1191 (PVRSRV_OS_PAGEABLE_HEAP, sizeof(*psPVRPCI),
1192 (IMG_VOID *) & psPVRPCI, IMG_NULL) != PVRSRV_OK) {
1193 PVR_DPF((PVR_DBG_ERROR,
1194 "OSPCISetDev: Couldn't allocate PVR PCI structure"));
1198 psPVRPCI->psPCIDev = (struct pci_dev *)pvPCICookie;
1199 psPVRPCI->ePCIFlags = eFlags;
1201 err = pci_enable_device(psPVRPCI->psPCIDev);
1203 PVR_DPF((PVR_DBG_ERROR,
1204 "OSPCISetDev: Couldn't enable device (%d)", err));
1208 if (psPVRPCI->ePCIFlags & HOST_PCI_INIT_FLAG_BUS_MASTER)
1209 pci_set_master(psPVRPCI->psPCIDev);
1211 for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
1212 psPVRPCI->abPCIResourceInUse[i] = IMG_FALSE;
1215 return (PVRSRV_PCI_DEV_HANDLE) psPVRPCI;
1218 PVRSRV_PCI_DEV_HANDLE OSPCIAcquireDev(IMG_UINT16 ui16VendorID,
1219 IMG_UINT16 ui16DeviceID,
1220 HOST_PCI_INIT_FLAGS eFlags)
1222 struct pci_dev *psPCIDev;
1224 psPCIDev = pci_get_device(ui16VendorID, ui16DeviceID, NULL);
1225 if (psPCIDev == NULL) {
1226 PVR_DPF((PVR_DBG_ERROR,
1227 "OSPCIAcquireDev: Couldn't acquire device"));
1231 return OSPCISetDev((IMG_VOID *) psPCIDev, eFlags);
1234 PVRSRV_ERROR OSPCIIRQ(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 * pui32IRQ)
1236 PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *) hPVRPCI;
1238 *pui32IRQ = psPVRPCI->psPCIDev->irq;
1243 enum HOST_PCI_ADDR_RANGE_FUNC {
1244 HOST_PCI_ADDR_RANGE_FUNC_LEN,
1245 HOST_PCI_ADDR_RANGE_FUNC_START,
1246 HOST_PCI_ADDR_RANGE_FUNC_END,
1247 HOST_PCI_ADDR_RANGE_FUNC_REQUEST,
1248 HOST_PCI_ADDR_RANGE_FUNC_RELEASE
1251 static IMG_UINT32 OSPCIAddrRangeFunc(enum HOST_PCI_ADDR_RANGE_FUNC eFunc,
1252 PVRSRV_PCI_DEV_HANDLE hPVRPCI,
1253 IMG_UINT32 ui32Index)
1255 PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *) hPVRPCI;
1257 if (ui32Index >= DEVICE_COUNT_RESOURCE) {
1258 PVR_DPF((PVR_DBG_ERROR,
1259 "OSPCIAddrRangeFunc: Index out of range"));
1265 case HOST_PCI_ADDR_RANGE_FUNC_LEN:
1266 return pci_resource_len(psPVRPCI->psPCIDev, ui32Index);
1267 case HOST_PCI_ADDR_RANGE_FUNC_START:
1268 return pci_resource_start(psPVRPCI->psPCIDev, ui32Index);
1269 case HOST_PCI_ADDR_RANGE_FUNC_END:
1270 return pci_resource_end(psPVRPCI->psPCIDev, ui32Index);
1271 case HOST_PCI_ADDR_RANGE_FUNC_REQUEST:
1276 pci_request_region(psPVRPCI->psPCIDev, ui32Index,
1279 PVR_DPF((PVR_DBG_ERROR,
1280 "OSPCIAddrRangeFunc: pci_request_region_failed (%d)",
1284 psPVRPCI->abPCIResourceInUse[ui32Index] = IMG_TRUE;
1287 case HOST_PCI_ADDR_RANGE_FUNC_RELEASE:
1288 if (psPVRPCI->abPCIResourceInUse[ui32Index]) {
1289 pci_release_region(psPVRPCI->psPCIDev, ui32Index);
1290 psPVRPCI->abPCIResourceInUse[ui32Index] = IMG_FALSE;
1294 PVR_DPF((PVR_DBG_ERROR,
1295 "OSPCIAddrRangeFunc: Unknown function"));
1302 IMG_UINT32 OSPCIAddrRangeLen(PVRSRV_PCI_DEV_HANDLE hPVRPCI,
1303 IMG_UINT32 ui32Index)
1305 return OSPCIAddrRangeFunc(HOST_PCI_ADDR_RANGE_FUNC_LEN, hPVRPCI,
1309 IMG_UINT32 OSPCIAddrRangeStart(PVRSRV_PCI_DEV_HANDLE hPVRPCI,
1310 IMG_UINT32 ui32Index)
1312 return OSPCIAddrRangeFunc(HOST_PCI_ADDR_RANGE_FUNC_START, hPVRPCI,
1316 IMG_UINT32 OSPCIAddrRangeEnd(PVRSRV_PCI_DEV_HANDLE hPVRPCI,
1317 IMG_UINT32 ui32Index)
1319 return OSPCIAddrRangeFunc(HOST_PCI_ADDR_RANGE_FUNC_END, hPVRPCI,
1323 PVRSRV_ERROR OSPCIRequestAddrRange(PVRSRV_PCI_DEV_HANDLE hPVRPCI,
1324 IMG_UINT32 ui32Index)
1326 return OSPCIAddrRangeFunc(HOST_PCI_ADDR_RANGE_FUNC_REQUEST, hPVRPCI,
1328 0 ? PVRSRV_ERROR_GENERIC : PVRSRV_OK;
1331 PVRSRV_ERROR OSPCIReleaseAddrRange(PVRSRV_PCI_DEV_HANDLE hPVRPCI,
1332 IMG_UINT32 ui32Index)
1334 return OSPCIAddrRangeFunc(HOST_PCI_ADDR_RANGE_FUNC_RELEASE, hPVRPCI,
1336 0 ? PVRSRV_ERROR_GENERIC : PVRSRV_OK;
1339 PVRSRV_ERROR OSPCIReleaseDev(PVRSRV_PCI_DEV_HANDLE hPVRPCI)
1341 PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *) hPVRPCI;
1344 PVR_TRACE(("OSPCIReleaseDev"));
1346 for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
1347 if (psPVRPCI->abPCIResourceInUse[i]) {
1348 PVR_TRACE(("OSPCIReleaseDev: Releasing Address range %d", i));
1349 pci_release_region(psPVRPCI->psPCIDev, i);
1350 psPVRPCI->abPCIResourceInUse[i] = IMG_FALSE;
1354 pci_disable_device(psPVRPCI->psPCIDev);
1356 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(*psPVRPCI),
1357 (IMG_VOID *) psPVRPCI, IMG_NULL);
1362 PVRSRV_ERROR OSPCISuspendDev(PVRSRV_PCI_DEV_HANDLE hPVRPCI)
1364 PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *) hPVRPCI;
1368 PVR_TRACE(("OSPCISuspendDev"));
1370 for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
1371 if (psPVRPCI->abPCIResourceInUse[i]) {
1372 pci_release_region(psPVRPCI->psPCIDev, i);
1376 err = pci_save_state(psPVRPCI->psPCIDev);
1378 PVR_DPF((PVR_DBG_ERROR,
1379 "OSPCISuspendDev: pci_save_state_failed (%d)", err));
1380 return PVRSRV_ERROR_GENERIC;
1383 pci_disable_device(psPVRPCI->psPCIDev);
1386 pci_set_power_state(psPVRPCI->psPCIDev,
1387 pci_choose_state(psPVRPCI->psPCIDev,
1393 PVR_DPF((PVR_DBG_WARNING,
1394 "OSPCISuspendDev: device doesn't support PCI PM"));
1397 PVR_DPF((PVR_DBG_ERROR,
1398 "OSPCISuspendDev: can't enter requested power state"));
1401 PVR_DPF((PVR_DBG_ERROR,
1402 "OSPCISuspendDev: pci_set_power_state failed (%d)",
1410 PVRSRV_ERROR OSPCIResumeDev(PVRSRV_PCI_DEV_HANDLE hPVRPCI)
1412 PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *) hPVRPCI;
1416 PVR_TRACE(("OSPCIResumeDev"));
1419 pci_set_power_state(psPVRPCI->psPCIDev,
1420 pci_choose_state(psPVRPCI->psPCIDev, PMSG_ON));
1425 PVR_DPF((PVR_DBG_WARNING,
1426 "OSPCIResumeDev: device doesn't support PCI PM"));
1429 PVR_DPF((PVR_DBG_ERROR,
1430 "OSPCIResumeDev: can't enter requested power state"));
1431 return PVRSRV_ERROR_GENERIC;
1433 PVR_DPF((PVR_DBG_ERROR,
1434 "OSPCIResumeDev: pci_set_power_state failed (%d)",
1436 return PVRSRV_ERROR_GENERIC;
1439 err = pci_restore_state(psPVRPCI->psPCIDev);
1441 PVR_DPF((PVR_DBG_ERROR,
1442 "OSPCIResumeDev: pci_restore_state failed (%d)", err));
1443 return PVRSRV_ERROR_GENERIC;
1446 err = pci_enable_device(psPVRPCI->psPCIDev);
1448 PVR_DPF((PVR_DBG_ERROR,
1449 "OSPCIResumeDev: Couldn't enable device (%d)", err));
1450 return PVRSRV_ERROR_GENERIC;
1453 if (psPVRPCI->ePCIFlags & HOST_PCI_INIT_FLAG_BUS_MASTER)
1454 pci_set_master(psPVRPCI->psPCIDev);
1456 for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
1457 if (psPVRPCI->abPCIResourceInUse[i]) {
1459 pci_request_region(psPVRPCI->psPCIDev, i,
1462 PVR_DPF((PVR_DBG_ERROR,
1463 "OSPCIResumeDev: pci_request_region_failed (region %d, error %d)",
1475 typedef struct TIMER_CALLBACK_DATA_TAG {
1476 PFN_TIMER_FUNC pfnTimerFunc;
1478 struct timer_list sTimer;
1479 IMG_UINT32 ui32Delay;
1481 } TIMER_CALLBACK_DATA;
1483 static IMG_VOID OSTimerCallbackWrapper(IMG_UINT32 ui32Data)
1485 TIMER_CALLBACK_DATA *psTimerCBData = (TIMER_CALLBACK_DATA *) ui32Data;
1487 if (!psTimerCBData->bActive)
1490 psTimerCBData->pfnTimerFunc(psTimerCBData->pvData);
1492 mod_timer(&psTimerCBData->sTimer, psTimerCBData->ui32Delay + jiffies);
1495 IMG_HANDLE OSAddTimer(PFN_TIMER_FUNC pfnTimerFunc, IMG_VOID * pvData,
1496 IMG_UINT32 ui32MsTimeout)
1498 TIMER_CALLBACK_DATA *psTimerCBData;
1500 if (!pfnTimerFunc) {
1501 PVR_DPF((PVR_DBG_ERROR, "OSAddTimer: passed invalid callback"));
1505 if (OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
1506 sizeof(TIMER_CALLBACK_DATA),
1507 (IMG_VOID **) & psTimerCBData, IMG_NULL) != PVRSRV_OK) {
1508 PVR_DPF((PVR_DBG_ERROR,
1509 "OSAddTimer: failed to allocate memory for TIMER_CALLBACK_DATA"));
1513 psTimerCBData->pfnTimerFunc = pfnTimerFunc;
1514 psTimerCBData->pvData = pvData;
1515 psTimerCBData->bActive = IMG_FALSE;
1517 psTimerCBData->ui32Delay = ((HZ * ui32MsTimeout) < 1000)
1518 ? 1 : ((HZ * ui32MsTimeout) / 1000);
1520 init_timer(&psTimerCBData->sTimer);
1522 psTimerCBData->sTimer.function = OSTimerCallbackWrapper;
1523 psTimerCBData->sTimer.data = (IMG_UINT32) psTimerCBData;
1524 psTimerCBData->sTimer.expires = psTimerCBData->ui32Delay + jiffies;
1526 return (IMG_HANDLE) psTimerCBData;
1529 PVRSRV_ERROR OSRemoveTimer(IMG_HANDLE hTimer)
1531 TIMER_CALLBACK_DATA *psTimerCBData = (TIMER_CALLBACK_DATA *) hTimer;
1533 OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(TIMER_CALLBACK_DATA),
1534 psTimerCBData, IMG_NULL);
1539 PVRSRV_ERROR OSEnableTimer(IMG_HANDLE hTimer)
1541 TIMER_CALLBACK_DATA *psTimerCBData = (TIMER_CALLBACK_DATA *) hTimer;
1543 psTimerCBData->bActive = IMG_TRUE;
1545 add_timer(&psTimerCBData->sTimer);
1550 PVRSRV_ERROR OSDisableTimer(IMG_HANDLE hTimer)
1552 TIMER_CALLBACK_DATA *psTimerCBData = (TIMER_CALLBACK_DATA *) hTimer;
1554 psTimerCBData->bActive = IMG_FALSE;
1556 del_timer_sync(&psTimerCBData->sTimer);
1561 PVRSRV_ERROR OSEventObjectCreate(const IMG_CHAR * pszName,
1562 PVRSRV_EVENTOBJECT * psEventObject)
1565 PVRSRV_ERROR eError = PVRSRV_OK;
1567 if (psEventObject) {
1570 strncpy(psEventObject->szName, pszName,
1571 EVENTOBJNAME_MAXLENGTH);
1574 static IMG_UINT16 ui16NameIndex = 0;
1575 snprintf(psEventObject->szName, EVENTOBJNAME_MAXLENGTH,
1576 "PVRSRV_EVENTOBJECT_%d", ui16NameIndex++);
1579 if (LinuxEventObjectListCreate(&psEventObject->hOSEventKM) !=
1581 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
1585 PVR_DPF((PVR_DBG_ERROR,
1586 "OSEventObjectCreate: psEventObject is not a valid pointer"));
1587 eError = PVRSRV_ERROR_GENERIC;
1594 PVRSRV_ERROR OSEventObjectDestroy(PVRSRV_EVENTOBJECT * psEventObject)
1596 PVRSRV_ERROR eError = PVRSRV_OK;
1598 if (psEventObject) {
1599 if (psEventObject->hOSEventKM) {
1600 LinuxEventObjectListDestroy(psEventObject->hOSEventKM);
1602 PVR_DPF((PVR_DBG_ERROR,
1603 "OSEventObjectDestroy: hOSEventKM is not a valid pointer"));
1604 eError = PVRSRV_ERROR_INVALID_PARAMS;
1607 PVR_DPF((PVR_DBG_ERROR,
1608 "OSEventObjectDestroy: psEventObject is not a valid pointer"));
1609 eError = PVRSRV_ERROR_INVALID_PARAMS;
1615 PVRSRV_ERROR OSEventObjectWait(IMG_HANDLE hOSEventKM)
1617 PVRSRV_ERROR eError = PVRSRV_OK;
1621 LinuxEventObjectWait(hOSEventKM, EVENT_OBJECT_TIMEOUT_MS);
1623 PVR_DPF((PVR_DBG_ERROR,
1624 "OSEventObjectWait: hOSEventKM is not a valid handle"));
1625 eError = PVRSRV_ERROR_INVALID_PARAMS;
1631 PVRSRV_ERROR OSEventObjectOpen(PVRSRV_EVENTOBJECT * psEventObject,
1632 IMG_HANDLE * phOSEvent)
1634 PVRSRV_ERROR eError = PVRSRV_OK;
1636 if (psEventObject) {
1637 if (LinuxEventObjectAdd(psEventObject->hOSEventKM, phOSEvent) !=
1639 PVR_DPF((PVR_DBG_ERROR, "LinuxEventObjectAdd: failed"));
1640 eError = PVRSRV_ERROR_INVALID_PARAMS;
1644 PVR_DPF((PVR_DBG_ERROR,
1645 "OSEventObjectCreate: psEventObject is not a valid pointer"));
1646 eError = PVRSRV_ERROR_INVALID_PARAMS;
1652 PVRSRV_ERROR OSEventObjectClose(PVRSRV_EVENTOBJECT * psEventObject,
1653 IMG_HANDLE hOSEventKM)
1655 PVRSRV_ERROR eError = PVRSRV_OK;
1657 if (psEventObject) {
1658 if (LinuxEventObjectDelete
1659 (psEventObject->hOSEventKM, hOSEventKM) != PVRSRV_OK) {
1660 PVR_DPF((PVR_DBG_ERROR,
1661 "LinuxEventObjectDelete: failed"));
1662 eError = PVRSRV_ERROR_INVALID_PARAMS;
1666 PVR_DPF((PVR_DBG_ERROR,
1667 "OSEventObjectDestroy: psEventObject is not a valid pointer"));
1668 eError = PVRSRV_ERROR_INVALID_PARAMS;
1675 PVRSRV_ERROR OSEventObjectSignal(IMG_HANDLE hOSEventKM)
1677 PVRSRV_ERROR eError = PVRSRV_OK;
1680 eError = LinuxEventObjectSignal(hOSEventKM);
1682 PVR_DPF((PVR_DBG_ERROR,
1683 "OSEventObjectSignal: hOSEventKM is not a valid handle"));
1684 eError = PVRSRV_ERROR_INVALID_PARAMS;
1690 IMG_BOOL OSProcHasPrivSrvInit(IMG_VOID)
1692 return capable(CAP_SYS_MODULE) != 0;
1695 PVRSRV_ERROR OSCopyToUser(IMG_PVOID pvProcess,
1697 IMG_VOID * pvSrc, IMG_UINT32 ui32Bytes)
1699 PVR_UNREFERENCED_PARAMETER(pvProcess);
1701 if (copy_to_user(pvDest, pvSrc, ui32Bytes) == 0)
1704 return PVRSRV_ERROR_GENERIC;
1707 PVRSRV_ERROR OSCopyFromUser(IMG_PVOID pvProcess,
1709 IMG_VOID * pvSrc, IMG_UINT32 ui32Bytes)
1711 PVR_UNREFERENCED_PARAMETER(pvProcess);
1713 if (copy_from_user(pvDest, pvSrc, ui32Bytes) == 0)
1716 return PVRSRV_ERROR_GENERIC;
1719 IMG_BOOL OSAccessOK(IMG_VERIFY_TEST eVerification, IMG_VOID * pvUserPtr,
1720 IMG_UINT32 ui32Bytes)
1724 if (eVerification == PVR_VERIFY_READ)
1725 linuxType = VERIFY_READ;
1726 else if (eVerification == PVR_VERIFY_WRITE)
1727 linuxType = VERIFY_WRITE;
1729 PVR_DPF((PVR_DBG_ERROR, "%s: Unknown eVerification",
1731 return PVRSRV_ERROR_GENERIC;
1733 return (IMG_BOOL) access_ok(linuxType, pvUserPtr, ui32Bytes);
1736 typedef enum _eWrapMemType_ {
1738 WRAP_TYPE_GET_USER_PAGES,
1739 WRAP_TYPE_FIND_VMA_PAGES,
1740 WRAP_TYPE_FIND_VMA_PFN
1743 typedef struct _sWrapMemInfo_ {
1746 struct page **ppsPages;
1747 IMG_SYS_PHYADDR *psPhysAddr;
1751 unsigned long ulStartAddr;
1752 unsigned long ulBeyondEndAddr;
1753 struct vm_area_struct *psVMArea;
1757 static void CheckPagesContiguous(sWrapMemInfo * psInfo)
1760 IMG_UINT32 ui32AddrChk;
1762 BUG_ON(psInfo == IMG_NULL);
1764 psInfo->iContiguous = 1;
1766 for (ui = 0, ui32AddrChk = psInfo->psPhysAddr[0].uiAddr;
1767 ui < psInfo->iNumPages; ui++, ui32AddrChk += PAGE_SIZE) {
1768 if (psInfo->psPhysAddr[ui].uiAddr != ui32AddrChk) {
1769 psInfo->iContiguous = 0;
1775 static struct page *CPUVAddrToPage(struct vm_area_struct *psVMArea,
1776 unsigned long ulCPUVAddr)
1778 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,10))
1783 struct mm_struct *psMM = psVMArea->vm_mm;
1784 unsigned long ulPFN;
1785 spinlock_t *psPTLock;
1786 struct page *psPage;
1788 psPGD = pgd_offset(psMM, ulCPUVAddr);
1789 if (pgd_none(*psPGD) || pgd_bad(*psPGD))
1792 psPUD = pud_offset(psPGD, ulCPUVAddr);
1793 if (pud_none(*psPUD) || pud_bad(*psPUD))
1796 psPMD = pmd_offset(psPUD, ulCPUVAddr);
1797 if (pmd_none(*psPMD) || pmd_bad(*psPMD))
1802 psPTE = pte_offset_map_lock(psMM, psPMD, ulCPUVAddr, &psPTLock);
1803 if (pte_none(*psPTE) || !pte_present(*psPTE) || !pte_write(*psPTE))
1806 ulPFN = pte_pfn(*psPTE);
1807 if (!pfn_valid(ulPFN))
1810 psPage = pfn_to_page(ulPFN);
1815 pte_unmap_unlock(psPTE, psPTLock);
1823 PVRSRV_ERROR OSReleasePhysPageAddr(IMG_HANDLE hOSWrapMem)
1825 sWrapMemInfo *psInfo = (sWrapMemInfo *) hOSWrapMem;
1828 BUG_ON(psInfo == IMG_NULL);
1831 switch (psInfo->eType) {
1832 case WRAP_TYPE_FIND_VMA_PAGES:
1834 case WRAP_TYPE_FIND_VMA_PFN:
1836 struct vm_area_struct *psVMArea;
1838 down_read(¤t->mm->mmap_sem);
1840 psVMArea = find_vma(current->mm, psInfo->ulStartAddr);
1841 if (psVMArea == NULL) {
1843 ": OSCpuVToPageListRelease: Couldn't find memory region containing start address %lx",
1844 psInfo->ulStartAddr);
1846 up_read(¤t->mm->mmap_sem);
1850 if (psInfo->psVMArea != psVMArea) {
1852 ": OSCpuVToPageListRelease: vm_area_struct has a different address from the one used in ImportMem (%p != %p)",
1853 psVMArea, psInfo->psVMArea);
1856 if (psInfo->ulStartAddr < psVMArea->vm_start) {
1858 ": OSCpuVToPageListRelease: Start address %lx is outside of the region returned by find_vma",
1859 psInfo->ulStartAddr);
1862 if (psInfo->ulBeyondEndAddr > psVMArea->vm_end) {
1864 ": OSCpuVToPageListRelease: End address %lx is outside of the region returned by find_vma",
1865 psInfo->ulBeyondEndAddr);
1868 if ((psVMArea->vm_flags & (VM_IO | VM_RESERVED)) !=
1869 (VM_IO | VM_RESERVED)) {
1871 ": OSCpuVToPageListRelease: Memory region does not represent memory mapped I/O (VMA flags: 0x%lx)",
1872 psVMArea->vm_flags);
1875 if ((psVMArea->vm_flags & (VM_READ | VM_WRITE)) !=
1876 (VM_READ | VM_WRITE)) {
1878 ": OSCpuVToPageListRelease: OSWrapMemReleasePages: No read/write access to memory region (VMA flags: 0x%lx)",
1879 psVMArea->vm_flags);
1882 up_read(¤t->mm->mmap_sem);
1890 switch (psInfo->eType) {
1891 case WRAP_TYPE_CLEANUP:
1893 case WRAP_TYPE_FIND_VMA_PFN:
1895 case WRAP_TYPE_GET_USER_PAGES:
1897 for (ui = 0; ui < psInfo->iNumPages; ui++) {
1898 struct page *psPage = psInfo->ppsPages[ui];
1900 if (!PageReserved(psPage)) ;
1902 SetPageDirty(psPage);
1904 page_cache_release(psPage);
1908 case WRAP_TYPE_FIND_VMA_PAGES:
1910 for (ui = 0; ui < psInfo->iNumPages; ui++) {
1911 put_page_testzero(psInfo->ppsPages[ui]);
1918 ": OSCpuVToPageListRelease: Unknown wrap type (%d)",
1920 return PVRSRV_ERROR_GENERIC;
1924 if (psInfo->ppsPages != IMG_NULL) {
1925 kfree(psInfo->ppsPages);
1928 if (psInfo->psPhysAddr != IMG_NULL) {
1929 kfree(psInfo->psPhysAddr);
1937 PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_VOID * pvCPUVAddr,
1938 IMG_UINT32 ui32Bytes,
1939 IMG_SYS_PHYADDR * psSysPAddr,
1940 IMG_HANDLE * phOSWrapMem)
1942 unsigned long ulStartAddrOrig = (unsigned long)pvCPUVAddr;
1943 unsigned long ulAddrRangeOrig = (unsigned long)ui32Bytes;
1944 unsigned long ulBeyondEndAddrOrig = ulStartAddrOrig + ulAddrRangeOrig;
1945 unsigned long ulStartAddr;
1946 unsigned long ulAddrRange;
1947 unsigned long ulBeyondEndAddr;
1948 unsigned long ulAddr;
1949 int iNumPagesMapped;
1951 struct vm_area_struct *psVMArea;
1952 sWrapMemInfo *psInfo;
1954 ulStartAddr = ulStartAddrOrig & PAGE_MASK;
1955 ulBeyondEndAddr = PAGE_ALIGN(ulBeyondEndAddrOrig);
1956 ulAddrRange = ulBeyondEndAddr - ulStartAddr;
1958 psInfo = kmalloc(sizeof(*psInfo), GFP_KERNEL);
1959 if (psInfo == NULL) {
1961 ": OSCpuVToPageList: Couldn't allocate information structure");
1962 return PVRSRV_ERROR_OUT_OF_MEMORY;
1964 memset(psInfo, 0, sizeof(*psInfo));
1967 psInfo->ulStartAddr = ulStartAddrOrig;
1968 psInfo->ulBeyondEndAddr = ulBeyondEndAddrOrig;
1971 psInfo->iNumPages = ulAddrRange >> PAGE_SHIFT;
1972 psInfo->iPageOffset = ulStartAddrOrig & ~PAGE_MASK;
1974 psInfo->psPhysAddr =
1975 kmalloc(psInfo->iNumPages * sizeof(*psInfo->psPhysAddr),
1977 if (psInfo->psPhysAddr == NULL) {
1979 ": OSCpuVToPageList: Couldn't allocate page array");
1984 kmalloc(psInfo->iNumPages * sizeof(*psInfo->ppsPages), GFP_KERNEL);
1985 if (psInfo->ppsPages == NULL) {
1987 ": OSCpuVToPageList: Couldn't allocate page array");
1991 down_read(¤t->mm->mmap_sem);
1993 get_user_pages(current, current->mm, ulStartAddr, psInfo->iNumPages,
1994 1, 0, psInfo->ppsPages, NULL);
1995 up_read(¤t->mm->mmap_sem);
1997 if (iNumPagesMapped >= 0) {
1999 if (iNumPagesMapped != psInfo->iNumPages) {
2001 ": OSCpuVToPageList: Couldn't map all the pages needed (wanted: %d, got %d)",
2002 psInfo->iNumPages, iNumPagesMapped);
2004 for (ui = 0; ui < iNumPagesMapped; ui++) {
2005 page_cache_release(psInfo->ppsPages[ui]);
2011 for (ui = 0; ui < psInfo->iNumPages; ui++) {
2012 IMG_CPU_PHYADDR CPUPhysAddr;
2014 CPUPhysAddr.uiAddr =
2015 page_to_pfn(psInfo->ppsPages[ui]) << PAGE_SHIFT;
2016 psInfo->psPhysAddr[ui] =
2017 SysCpuPAddrToSysPAddr(CPUPhysAddr);
2018 psSysPAddr[ui] = psInfo->psPhysAddr[ui];
2022 psInfo->eType = WRAP_TYPE_GET_USER_PAGES;
2028 ": OSCpuVToPageList: get_user_pages failed (%d), trying something else",
2031 down_read(¤t->mm->mmap_sem);
2033 psVMArea = find_vma(current->mm, ulStartAddrOrig);
2034 if (psVMArea == NULL) {
2036 ": OSCpuVToPageList: Couldn't find memory region containing start address %lx",
2039 goto error_release_mmap_sem;
2042 psInfo->psVMArea = psVMArea;
2045 if (ulStartAddrOrig < psVMArea->vm_start) {
2047 ": OSCpuVToPageList: Start address %lx is outside of the region returned by find_vma",
2049 goto error_release_mmap_sem;
2052 if (ulBeyondEndAddrOrig > psVMArea->vm_end) {
2054 ": OSCpuVToPageList: End address %lx is outside of the region returned by find_vma",
2055 ulBeyondEndAddrOrig);
2056 goto error_release_mmap_sem;
2059 if ((psVMArea->vm_flags & (VM_IO | VM_RESERVED)) !=
2060 (VM_IO | VM_RESERVED)) {
2062 ": OSCpuVToPageList: Memory region does not represent memory mapped I/O (VMA flags: 0x%lx)",
2063 psVMArea->vm_flags);
2064 goto error_release_mmap_sem;
2067 if ((psVMArea->vm_flags & (VM_READ | VM_WRITE)) != (VM_READ | VM_WRITE)) {
2069 ": OSCpuVToPageList: No read/write access to memory region (VMA flags: 0x%lx)",
2070 psVMArea->vm_flags);
2071 goto error_release_mmap_sem;
2074 for (ulAddr = ulStartAddrOrig, ui = 0; ulAddr < ulBeyondEndAddrOrig;
2075 ulAddr += PAGE_SIZE, ui++) {
2076 struct page *psPage;
2078 BUG_ON(ui >= psInfo->iNumPages);
2080 psPage = CPUVAddrToPage(psVMArea, ulAddr);
2081 if (psPage == NULL) {
2085 ": OSCpuVToPageList: Couldn't lookup page structure for address 0x%lx, trying something else",
2088 for (uj = 0; uj < ui; uj++) {
2089 put_page_testzero(psInfo->ppsPages[uj]);
2094 psInfo->ppsPages[ui] = psPage;
2097 BUG_ON(ui > psInfo->iNumPages);
2098 if (ui == psInfo->iNumPages) {
2100 for (ui = 0; ui < psInfo->iNumPages; ui++) {
2101 struct page *psPage = psInfo->ppsPages[ui];
2102 IMG_CPU_PHYADDR CPUPhysAddr;
2104 CPUPhysAddr.uiAddr = page_to_pfn(psPage) << PAGE_SHIFT;
2106 psInfo->psPhysAddr[ui] =
2107 SysCpuPAddrToSysPAddr(CPUPhysAddr);
2108 psSysPAddr[ui] = psInfo->psPhysAddr[ui];
2111 psInfo->eType = WRAP_TYPE_FIND_VMA_PAGES;
2113 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,10))
2115 if ((psVMArea->vm_flags & VM_PFNMAP) == 0) {
2117 ": OSCpuVToPageList: Region isn't a raw PFN mapping. Giving up.");
2118 goto error_release_mmap_sem;
2121 for (ulAddr = ulStartAddrOrig, ui = 0;
2122 ulAddr < ulBeyondEndAddrOrig; ulAddr += PAGE_SIZE, ui++) {
2123 IMG_CPU_PHYADDR CPUPhysAddr;
2125 CPUPhysAddr.uiAddr =
2126 ((ulAddr - psVMArea->vm_start) +
2127 (psVMArea->vm_pgoff << PAGE_SHIFT)) & PAGE_MASK;
2129 psInfo->psPhysAddr[ui] =
2130 SysCpuPAddrToSysPAddr(CPUPhysAddr);
2131 psSysPAddr[ui] = psInfo->psPhysAddr[ui];
2133 BUG_ON(ui != psInfo->iNumPages);
2135 psInfo->eType = WRAP_TYPE_FIND_VMA_PFN;
2138 ": OSCpuVToPageList: Region can't be locked down");
2141 ": OSCpuVToPageList: Raw PFN mappings not supported. Giving up.");
2142 goto error_release_mmap_sem;
2146 up_read(¤t->mm->mmap_sem);
2149 CheckPagesContiguous(psInfo);
2151 *phOSWrapMem = (IMG_HANDLE) psInfo;
2155 error_release_mmap_sem:
2156 up_read(¤t->mm->mmap_sem);
2158 psInfo->eType = WRAP_TYPE_CLEANUP;
2159 OSReleasePhysPageAddr((IMG_HANDLE) psInfo);
2160 return PVRSRV_ERROR_GENERIC;