示例#1
0
/*!
******************************************************************************

 @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;
}