gceSTATUS gckKERNEL_SecurityMapMemory( IN gckKERNEL Kernel, IN gctUINT32 *PhysicalArray, IN gctUINT32 PageCount, OUT gctUINT32 * GPUAddress ) { gceSTATUS status; gcsTA_INTERFACE iface; gcmkHEADER(); iface.command = KERNEL_MAP_MEMORY; #if defined(LINUX) gcmkONERROR(gckOS_GetPhysicalAddress(Kernel->os, PhysicalArray, (gctUINT32 *)&iface.u.MapMemory.physicals)); #endif iface.u.MapMemory.pageCount = PageCount; gcmkONERROR(gckKERNEL_SecurityCallService(Kernel->securityChannel, &iface)); *GPUAddress = iface.u.MapMemory.gpuAddress; gcmkFOOTER_NO(); return gcvSTATUS_OK; OnError: gcmkFOOTER(); return status; }
gceSTATUS gckKERNEL_SecurityExecute( IN gckKERNEL Kernel, IN gctPOINTER Buffer, IN gctUINT32 Bytes ) { gceSTATUS status; gcsTA_INTERFACE iface; gcmkHEADER(); iface.command = KERNEL_EXECUTE; iface.u.Execute.command_buffer = (gctUINT32 *)Buffer; iface.u.Execute.gpu = Kernel->core; iface.u.Execute.command_buffer_length = Bytes; #if defined(LINUX) gcmkONERROR(gckOS_GetPhysicalAddress(Kernel->os, Buffer, (gctUINT32 *)&iface.u.Execute.command_buffer)); #endif gcmkONERROR(gckKERNEL_SecurityCallService(Kernel->securityChannel, &iface)); /* Update queue tail pointer. */ gcmkONERROR(gckHARDWARE_UpdateQueueTail( Kernel->hardware, 0, 0 )); gcmkFOOTER_NO(); return gcvSTATUS_OK; OnError: gcmkFOOTER(); return status; }
/******************************************************************************* ** ** gckVIDMEM_Lock ** ** Lock a video memory node and return it's hardware specific address. ** ** INPUT: ** ** gcuVIDMEM_NODE_PTR Node ** Pointer to a gcuVIDMEM_NODE union. ** ** OUTPUT: ** ** gctUINT32 * Address ** Pointer to a variable that will hold the hardware specific address. */ gceSTATUS gckVIDMEM_Lock( IN gcuVIDMEM_NODE_PTR Node, OUT gctUINT32 * Address ) { gceSTATUS status; gctBOOL acquired = gcvFALSE; gctBOOL locked = gcvFALSE; gckOS os = gcvNULL; gcmkHEADER_ARG("Node=0x%x", Node); /* Verify the arguments. */ gcmkVERIFY_ARGUMENT(Address != gcvNULL); if ((Node == gcvNULL) || (Node->VidMem.memory == gcvNULL) ) { /* Invalid object. */ gcmkONERROR(gcvSTATUS_INVALID_OBJECT); } /**************************** Video Memory ********************************/ if (Node->VidMem.memory->object.type == gcvOBJ_VIDMEM) { /* Increment the lock count. */ Node->VidMem.locked ++; /* Return the address of the node. */ *Address = Node->VidMem.memory->baseAddress + Node->VidMem.offset + Node->VidMem.alignment; gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM, "Locked node 0x%x (%d) @ 0x%08X", Node, Node->VidMem.locked, *Address); } /*************************** Virtual Memory *******************************/ else { /* Verify the gckKERNEL object pointer. */ gcmkVERIFY_OBJECT(Node->Virtual.kernel, gcvOBJ_KERNEL); /* Extract the gckOS object pointer. */ os = Node->Virtual.kernel->os; gcmkVERIFY_OBJECT(os, gcvOBJ_OS); /* Grab the mutex. */ gcmkONERROR(gckOS_AcquireMutex(os, Node->Virtual.mutex, gcvINFINITE)); acquired = gcvTRUE; /* Increment the lock count. */ if (Node->Virtual.locked ++ == 0) { /* Is this node pending for a final unlock? */ #ifdef __QNXNTO__ if (!Node->Virtual.contiguous && Node->Virtual.unlockPending) #else if (!Node->Virtual.contiguous && Node->Virtual.pending) #endif { /* Make sure we have a page table. */ gcmkASSERT(Node->Virtual.pageTable != gcvNULL); /* Remove pending unlock. */ #ifdef __QNXNTO__ Node->Virtual.unlockPending = gcvFALSE; #else Node->Virtual.pending = gcvFALSE; #endif } /* First lock - create a page table. */ gcmkASSERT(Node->Virtual.pageTable == gcvNULL); /* Make sure we mark our node as not flushed. */ #ifdef __QNXNTO__ Node->Virtual.unlockPending = gcvFALSE; #else Node->Virtual.pending = gcvFALSE; #endif /* Lock the allocated pages. */ #ifdef __QNXNTO__ gcmkONERROR( gckOS_LockPages(os, Node->Virtual.physical, Node->Virtual.bytes, Node->Virtual.userPID, &Node->Virtual.logical, &Node->Virtual.pageCount)); #else gcmkONERROR( gckOS_LockPages(os, Node->Virtual.physical, Node->Virtual.bytes, &Node->Virtual.logical, &Node->Virtual.pageCount)); #endif locked = gcvTRUE; if (Node->Virtual.contiguous) { /* Get physical address directly */ gcmkONERROR(gckOS_GetPhysicalAddress(os, Node->Virtual.logical, &Node->Virtual.address)); } else { /* Allocate pages inside the MMU. */ gcmkONERROR( gckMMU_AllocatePages(Node->Virtual.kernel->mmu, Node->Virtual.pageCount, &Node->Virtual.pageTable, &Node->Virtual.address)); /* Map the pages. */ #ifdef __QNXNTO__ gcmkONERROR( gckOS_MapPages(os, Node->Virtual.physical, Node->Virtual.logical, Node->Virtual.pageCount, Node->Virtual.pageTable)); #else gcmkONERROR( gckOS_MapPages(os, Node->Virtual.physical, Node->Virtual.pageCount, Node->Virtual.pageTable)); #endif gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM, "Mapped virtual node 0x%x to 0x%08X", Node, Node->Virtual.address); } } /* Return hardware address. */ *Address = Node->Virtual.address; /* Release the mutex. */ gcmkVERIFY_OK(gckOS_ReleaseMutex(os, Node->Virtual.mutex)); } /* Success. */ gcmkFOOTER_ARG("*Address=%08x", *Address); return gcvSTATUS_OK; OnError: if (locked) { if (Node->Virtual.pageTable != gcvNULL) { /* Free the pages from the MMU. */ gcmkVERIFY_OK( gckMMU_FreePages(Node->Virtual.kernel->mmu, Node->Virtual.pageTable, Node->Virtual.pageCount)); Node->Virtual.pageTable = gcvNULL; } /* Unlock the pages. */ #ifdef __QNXNTO__ gcmkVERIFY_OK( gckOS_UnlockPages(os, Node->Virtual.physical, Node->Virtual.userPID, Node->Virtual.bytes, Node->Virtual.logical)); #else gcmkVERIFY_OK( gckOS_UnlockPages(os, Node->Virtual.physical, Node->Virtual.bytes, Node->Virtual.logical)); #endif } if (acquired) { /* Release the mutex. */ gcmkVERIFY_OK(gckOS_ReleaseMutex(os, Node->Virtual.mutex)); } /* Return the status. */ gcmkFOOTER(); return status; }
gceSTATUS gckKERNEL_MapLogicalToPhysical( IN gckKERNEL Kernel, IN gctHANDLE Process, IN OUT gctPOINTER * Data ) { gctUINT i, oldest; gceSTATUS status; gctUINT32 baseAddress; gcmkHEADER_ARG("Kernel=0x%x Process=0x%x *Data=0x%x", Kernel, Process, gcmOPT_POINTER(Data)); /* Verify the arguments. */ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL); gcmkVERIFY_ARGUMENT(Data != gcvNULL); /* Get base address. */ gcmkONERROR(gckHARDWARE_GetBaseAddress(Kernel->hardware, &baseAddress)); /* Walk all used cache slots. */ for (i = oldest = 0; i < Kernel->cacheSlots; ++i) { if ((Kernel->cache[i].logical == *Data) && (Kernel->cache[i].process == Process) ) { /* Bail out. */ break; } if (i == 0) { /* First slot. */ oldest = i; } /* Test if this cache slot is older. */ else if (Kernel->cache[i].stamp < Kernel->cache[oldest].stamp) { oldest = i; } } /* See if we had a match. */ if (i == Kernel->cacheSlots) { /* See if there is room in the cache. */ if (i < gcmCOUNTOF(Kernel->cache)) { /* Just append to the cache. */ i = Kernel->cacheSlots++; } else { /* Evict the oldest cache line. */ i = oldest; } /* Initialize the cache line. */ Kernel->cache[i].logical = *Data; Kernel->cache[i].process = Process; /* Map the logical address to a DMA address. */ gcmkONERROR(gckOS_GetPhysicalAddress(Kernel->os, *Data, &Kernel->cache[i].dma)); if (baseAddress != 0) { gctBOOL needBase; /* Does this state load need a base address? */ gcmkONERROR(gckHARDWARE_NeedBaseAddress(Kernel->hardware, ((gctUINT32_PTR) Data)[-1], &needBase)); if (needBase) { /* Add the base address. */ Kernel->cache[i].dma += baseAddress; } } } /* Increment time stamp of the cache slot. */ Kernel->cache[i].stamp = Kernel->cacheTimeStamp++; /* Return DMA address. */ *Data = gcmINT2PTR(Kernel->cache[i].dma); /* Success. */ gcmkFOOTER_ARG("*Data=0x%08x", *Data); return gcvSTATUS_OK; OnError: gcmkLOG_ERROR_STATUS(); /* Return the status. */ gcmkFOOTER(); return status; }
static void _DumpCommand( IN gckCOMMAND Command, IN gctPOINTER Pointer, IN gctSIZE_T Bytes ) { gctUINT32_PTR data = (gctUINT32_PTR) Pointer; gctUINT32 address; #ifdef MRVL_DUMP_COMMAND struct file* pDump_Cmd = 0; mm_segment_t old_fs; pDump_Cmd = filp_open("./dump_cmd.bin",O_WRONLY | O_CREAT | O_APPEND,0644); if (pDump_Cmd == 0) { gcmkPRINT("open file dump_cmd.bin failed!\n"); return; } old_fs = get_fs(); set_fs(KERNEL_DS); pDump_Cmd->f_op->write(pDump_Cmd,Pointer,Bytes,&pDump_Cmd->f_pos); set_fs(old_fs); filp_close(pDump_Cmd,0); return; #endif gckOS_GetPhysicalAddress(Command->os, Pointer, &address); gcmkPRINT("@[kernel.command %08X %08X", address, Bytes); while (Bytes >= 8*4) { gcmkPRINT(" %08X %08X %08X %08X %08X %08X %08X %08X", data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7]); data += 8; Bytes -= 32; } switch (Bytes) { case 7*4: gcmkPRINT(" %08X %08X %08X %08X %08X %08X %08X", data[0], data[1], data[2], data[3], data[4], data[5], data[6]); break; case 6*4: gcmkPRINT(" %08X %08X %08X %08X %08X %08X", data[0], data[1], data[2], data[3], data[4], data[5]); break; case 5*4: gcmkPRINT(" %08X %08X %08X %08X %08X", data[0], data[1], data[2], data[3], data[4]); break; case 4*4: gcmkPRINT(" %08X %08X %08X %08X", data[0], data[1], data[2], data[3]); break; case 3*4: gcmkPRINT(" %08X %08X %08X", data[0], data[1], data[2]); break; case 2*4: gcmkPRINT(" %08X %08X", data[0], data[1]); break; case 1*4: gcmkPRINT(" %08X", data[0]); break; } gcmkPRINT("] -- command"); }