/*! ****************************************************************************** @Function SysLocateDevices @Description specifies devices in the systems memory map @Input psSysData - sys data @Return PVRSRV_ERROR : ******************************************************************************/ static PVRSRV_ERROR SysLocateDevices(SYS_DATA *psSysData) { IMG_UINT32 ui32AtlasRegBaseAddr, ui32SGXRegBaseAddr, ui32SGXMemBaseAddr; IMG_UINT32 ui32IRQ; IMG_UINT32 ui32DeviceID = SYS_SGX_DEV_DEVICE_ID; #if defined(NO_HARDWARE) IMG_CPU_PHYADDR sCpuPAddr; #endif #ifdef __linux__ SYS_SPECIFIC_DATA *psSysSpecData = (SYS_SPECIFIC_DATA *) psSysData->pvSysSpecificData; #endif #if !defined(__linux__) || defined(NO_HARDWARE) PVRSRV_ERROR eError; #endif #ifdef __linux__ ui32AtlasRegBaseAddr = OSPCIAddrRangeStart(psSysSpecData->hSGXPCI, SYS_ATLAS_REG_PCI_BASENUM); ui32SGXRegBaseAddr = OSPCIAddrRangeStart(psSysSpecData->hSGXPCI, SYS_SGX_REG_PCI_BASENUM); ui32SGXMemBaseAddr = OSPCIAddrRangeStart(psSysSpecData->hSGXPCI, SYS_SGX_MEM_PCI_BASENUM); if (OSPCIIRQ(psSysSpecData->hSGXPCI, &ui32IRQ) != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"SysLocateDevices: Couldn't get IRQ")); return PVRSRV_ERROR_INVALID_DEVICE; } PVR_TRACE(("IRQ: %d", ui32IRQ)); #else /* __linux__ */ PCICONFIG_SPACE sPCISpace; PVR_UNREFERENCED_PARAMETER(psSysData); eError = FindPCIDevice(SYS_SGX_DEV_VENDOR_ID, SYS_SGX_DEV_DEVICE_ID, &sPCISpace); if (eError == PVRSRV_OK) { /* Get the regions from base address register 0, 1, 2 */ ui32AtlasRegBaseAddr = sPCISpace.u.aui32PCISpace[SYS_ATLAS_REG_PCI_OFFSET]; ui32SGXRegBaseAddr = sPCISpace.u.aui32PCISpace[SYS_SGX_REG_PCI_OFFSET]; ui32SGXMemBaseAddr = sPCISpace.u.aui32PCISpace[SYS_SGX_MEM_PCI_OFFSET]; } else { #if defined (SYS_SGX_DEV1_DEVICE_ID) ui32DeviceID = SYS_SGX_DEV1_DEVICE_ID; eError = FindPCIDevice(SYS_SGX_DEV_VENDOR_ID, SYS_SGX_DEV1_DEVICE_ID, &sPCISpace); if (eError == PVRSRV_OK) { /* Get the regions from base address register 0, 1, 2 */ ui32AtlasRegBaseAddr = sPCISpace.u.aui32PCISpace[SYS_ATLAS_REG_PCI_OFFSET]; ui32SGXRegBaseAddr = sPCISpace.u.aui32PCISpace[SYS_SGX_REG_PCI_OFFSET]; ui32SGXMemBaseAddr = sPCISpace.u.aui32PCISpace[SYS_SGX_MEM_PCI_OFFSET]; } else #endif { PVR_DPF((PVR_DBG_ERROR,"Couldn't find PCI device")); return PVRSRV_ERROR_INVALID_DEVICE; } } PVR_DPF((PVR_DBG_MESSAGE,"Found - DevID %04X Ven Id 0x%04X SSDevId %04X SSVenId %04X", sPCISpace.u.aui16PCISpace[SYS_SGX_DEV_ID_16_PCI_OFFSET], sPCISpace.u.aui16PCISpace[SYS_SGX_VEN_ID_16_PCI_OFFSET], sPCISpace.u.aui16PCISpace[SYS_SGX_SSDEV_ID_16_PCI_OFFSET], sPCISpace.u.aui16PCISpace[SYS_SGX_SSVEN_ID_16_PCI_OFFSET])); ui32IRQ = (IMG_UINT32)sPCISpace.u.aui8PCISpace[SYS_SGX_IRQ_8_PCI_OFFSET]; #endif /* __linux__ */ /* Atlas registers */ gsSOCRegsCpuPBase.uiAddr = ui32AtlasRegBaseAddr; /* SGX Device: */ gsSGXDeviceMap.ui32Flags = 0x0; #if defined(NO_HARDWARE) /* No hardware registers */ eError = OSBaseAllocContigMemory(SYS_SGX_REG_SIZE, &gsSGXRegsCPUVAddr, &sCpuPAddr); if(eError != PVRSRV_OK) { return eError; } SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_REG_MEM); gsSGXDeviceMap.sRegsCpuPBase = sCpuPAddr; OSMemSet(gsSGXRegsCPUVAddr, 0, SYS_SGX_REG_SIZE); #if defined(__linux__) /* Indicate the registers are already mapped */ gsSGXDeviceMap.pvRegsCpuVBase = gsSGXRegsCPUVAddr; #else /* * FIXME: Could we just use the virtual address returned by * OSBaseAllocContigMemory? */ gsSGXDeviceMap.pvRegsCpuVBase = IMG_NULL; #endif #else /* defined(NO_HARDWARE) */ /* Hardware registers */ gsSGXDeviceMap.sRegsSysPBase.uiAddr = ui32SGXRegBaseAddr + SYS_SGX_REG_OFFSET; #endif /* defined(NO_HARDWARE) */ /* Common register setup */ gsSGXDeviceMap.sRegsCpuPBase = SysSysPAddrToCpuPAddr(gsSGXDeviceMap.sRegsSysPBase); gsSGXDeviceMap.ui32RegsSize = SYS_SGX_REG_SIZE; /* Local Device Memory Region: (present) */ gsSGXDeviceMap.sLocalMemSysPBase.uiAddr = ui32SGXMemBaseAddr; gsSGXDeviceMap.sLocalMemDevPBase = SysSysPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, gsSGXDeviceMap.sLocalMemSysPBase); gsSGXDeviceMap.sLocalMemCpuPBase = SysSysPAddrToCpuPAddr(gsSGXDeviceMap.sLocalMemSysPBase); #if defined (SYS_SGX_DEV1_DEVICE_ID) if(ui32DeviceID == SYS_SGX_DEV1_DEVICE_ID) { gsSGXDeviceMap.ui32LocalMemSize = SYS_SGX_DEV1_LOCALMEM_FOR_SGX_RESERVE_SIZE; } else #endif { gsSGXDeviceMap.ui32LocalMemSize = SYS_SGX_DEV_LOCALMEM_FOR_SGX_RESERVE_SIZE; } #if defined(SGX_FEATURE_HOST_PORT) /* HostPort: */ gsSGXDeviceMap.ui32Flags |= SGX_HOSTPORT_PRESENT; gsSGXDeviceMap.sHPSysPBase.uiAddr = ui32SGXMemBaseAddr + 0x10000000; gsSGXDeviceMap.sHPCpuPBase = SysSysPAddrToCpuPAddr(gsSGXDeviceMap.sHPSysPBase); gsSGXDeviceMap.ui32HPSize = SYS_SGX_HP_SIZE; #endif /* device interrupt IRQ */ gsSGXDeviceMap.ui32IRQ = ui32IRQ; #if defined(PDUMP) { /* Initialise memory region name for pdumping. * This could just as well be SGXMEM on the RefPCI Test Chip system * since it uses LMA. But since there will only be 1 device we can * represent it as UMA in the pdump. */ static IMG_CHAR pszPDumpDevName[] = "SGXMEM"; gsSGXDeviceMap.pszPDumpDevName = pszPDumpDevName; } #endif return PVRSRV_OK; }
enum PVRSRV_ERROR MMU_Initialise(struct PVRSRV_DEVICE_NODE *psDeviceNode, struct MMU_CONTEXT **ppsMMUContext, struct IMG_DEV_PHYADDR *psPDDevPAddr) { u32 *pui32Tmp; u32 i; void *pvPDCpuVAddr; struct IMG_DEV_PHYADDR sPDDevPAddr; struct IMG_CPU_PHYADDR sCpuPAddr; struct IMG_SYS_PHYADDR sSysPAddr; struct MMU_CONTEXT *psMMUContext; void *hPDOSMemHandle; struct SYS_DATA *psSysData; struct PVRSRV_SGXDEV_INFO *psDevInfo; PVR_DPF(PVR_DBG_MESSAGE, "MMU_Initialise"); if (SysAcquireData(&psSysData) != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "MMU_Initialise: ERROR call to SysAcquireData failed"); return PVRSRV_ERROR_GENERIC; } if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct MMU_CONTEXT), (void **) &psMMUContext, NULL) != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "MMU_Initialise: ERROR call to OSAllocMem failed"); return PVRSRV_ERROR_GENERIC; } OSMemSet(psMMUContext, 0, sizeof(struct MMU_CONTEXT)); psDevInfo = (struct PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice; psMMUContext->psDevInfo = psDevInfo; psMMUContext->psDeviceNode = psDeviceNode; if (psDeviceNode->psLocalDevMemArena == NULL) { if (OSAllocPages (PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY, SGX_MMU_PAGE_SIZE, SGX_MMU_PAGE_SIZE, &pvPDCpuVAddr, &hPDOSMemHandle) != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "MMU_Initialise: " "ERROR call to OSAllocPages failed"); goto err1; } if (pvPDCpuVAddr) sCpuPAddr = OSMapLinToCPUPhys(pvPDCpuVAddr); else sCpuPAddr = OSMemHandleToCpuPAddr(hPDOSMemHandle, 0); sPDDevPAddr = SysCpuPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr); } else { if (RA_Alloc(psDeviceNode->psLocalDevMemArena, SGX_MMU_PAGE_SIZE, NULL, 0, SGX_MMU_PAGE_SIZE, &(sSysPAddr.uiAddr)) != IMG_TRUE) { PVR_DPF(PVR_DBG_ERROR, "MMU_Initialise: " "ERROR call to RA_Alloc failed"); goto err1; } sCpuPAddr = SysSysPAddrToCpuPAddr(sSysPAddr); sPDDevPAddr = SysSysPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sSysPAddr); pvPDCpuVAddr = (void __force *) OSMapPhysToLin(sCpuPAddr, SGX_MMU_PAGE_SIZE, PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY, &hPDOSMemHandle); if (!pvPDCpuVAddr) { PVR_DPF(PVR_DBG_ERROR, "MMU_Initialise: " "ERROR failed to map page tables"); goto err2; } } PDUMPCOMMENT("Alloc page directory"); PDUMPMALLOCPAGETABLE(pvPDCpuVAddr, PDUMP_PD_UNIQUETAG); if (pvPDCpuVAddr) { pui32Tmp = (u32 *) pvPDCpuVAddr; } else { PVR_DPF(PVR_DBG_ERROR, "MMU_Initialise: pvPDCpuVAddr invalid"); goto err3; } for (i = 0; i < SGX_MMU_PD_SIZE; i++) pui32Tmp[i] = 0; PDUMPCOMMENT("Page directory contents"); PDUMPPAGETABLE(pvPDCpuVAddr, SGX_MMU_PAGE_SIZE, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG); psMMUContext->pvPDCpuVAddr = pvPDCpuVAddr; psMMUContext->sPDDevPAddr = sPDDevPAddr; psMMUContext->hPDOSMemHandle = hPDOSMemHandle; *ppsMMUContext = psMMUContext; *psPDDevPAddr = sPDDevPAddr; psMMUContext->psNext = (struct MMU_CONTEXT *) psDevInfo->pvMMUContextList; psDevInfo->pvMMUContextList = (void *) psMMUContext; return PVRSRV_OK; err3: if (psDeviceNode->psLocalDevMemArena) OSUnMapPhysToLin((void __iomem __force *)pvPDCpuVAddr, SGX_MMU_PAGE_SIZE, PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY, hPDOSMemHandle); err2: if (!psDeviceNode->psLocalDevMemArena) OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY, SGX_MMU_PAGE_SIZE, pvPDCpuVAddr, hPDOSMemHandle); else RA_Free(psDeviceNode->psLocalDevMemArena, sSysPAddr.uiAddr, IMG_FALSE); err1: OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct MMU_CONTEXT), psMMUContext, NULL); return PVRSRV_ERROR_GENERIC; }