/******************************************************************************* ** ** gckVGMMU_Destroy ** ** Destroy a nAQMMU object. ** ** INPUT: ** ** gckVGMMU Mmu ** Pointer to an gckVGMMU object. ** ** OUTPUT: ** ** Nothing. */ gceSTATUS gckVGMMU_Destroy( IN gckVGMMU Mmu ) { gcmkHEADER_ARG("Mmu=0x%x", Mmu); /* Verify the arguments. */ gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU); /* Free the page table. */ gcmkVERIFY_OK(gckOS_FreeContiguous(Mmu->os, Mmu->pageTablePhysical, Mmu->pageTableLogical, Mmu->pageTableSize)); /* Roll back. */ gcmkVERIFY_OK(gckOS_DeleteMutex(Mmu->os, Mmu->mutex)); /* Mark the gckVGMMU object as unknown. */ Mmu->object.type = gcvOBJ_UNKNOWN; /* Free the gckVGMMU object. */ gcmkVERIFY_OK(gckOS_Free(Mmu->os, Mmu)); gcmkFOOTER_NO(); /* Success. */ return gcvSTATUS_OK; }
/******************************************************************************* ** ** gckCOMMAND_Destroy ** ** Destroy an gckCOMMAND object. ** ** INPUT: ** ** gckCOMMAND Command ** Pointer to an gckCOMMAND object to destroy. ** ** OUTPUT: ** ** Nothing. */ gceSTATUS gckCOMMAND_Destroy( IN gckCOMMAND Command ) { gctINT i; gcmkHEADER_ARG("Command=0x%x", Command); /* Verify the arguments. */ gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND); /* Stop the command queue. */ gcmkVERIFY_OK(gckCOMMAND_Stop(Command)); for (i = 0; i < gcdCOMMAND_QUEUES; ++i) { gcmkASSERT(Command->queues[i].signal != gcvNULL); gcmkVERIFY_OK( gckOS_DestroySignal(Command->os, Command->queues[i].signal)); gcmkASSERT(Command->queues[i].logical != gcvNULL); gcmkVERIFY_OK( gckOS_FreeNonPagedMemory(Command->os, Command->pageSize, Command->queues[i].physical, Command->queues[i].logical)); } /* Delete the context switching mutex. */ gcmkVERIFY_OK(gckOS_DeleteMutex(Command->os, Command->mutexContext)); /* Delete the command queue mutex. */ gcmkVERIFY_OK(gckOS_DeleteMutex(Command->os, Command->mutexQueue)); /* Mark object as unknown. */ Command->object.type = gcvOBJ_UNKNOWN; /* Free the gckCOMMAND object. */ gcmkVERIFY_OK(gckOS_Free(Command->os, Command)); /* Success. */ gcmkFOOTER_NO(); return gcvSTATUS_OK; }
/******************************************************************************* ** ** gckVIDMEM_Destroy ** ** Destroy an gckVIDMEM object. ** ** INPUT: ** ** gckVIDMEM Memory ** Pointer to an gckVIDMEM object to destroy. ** ** OUTPUT: ** ** Nothing. */ gceSTATUS gckVIDMEM_Destroy( IN gckVIDMEM Memory ) { gcuVIDMEM_NODE_PTR node, next; gctINT i; gcmkHEADER_ARG("Memory=0x%x", Memory); /* Verify the arguments. */ gcmkVERIFY_OBJECT(Memory, gcvOBJ_VIDMEM); /* Walk all sentinels. */ for (i = 0; i < gcmCOUNTOF(Memory->sentinel); ++i) { /* Bail out of the heap is not used. */ if (Memory->sentinel[i].VidMem.next == gcvNULL) { break; } /* Walk all the nodes until we reach the sentinel. */ for (node = Memory->sentinel[i].VidMem.next; node->VidMem.bytes != 0; node = next) { /* Save pointer to the next node. */ next = node->VidMem.next; /* Free the node. */ gcmkVERIFY_OK(gckOS_Free(Memory->os, node)); } } /* Free the mutex. */ gcmkVERIFY_OK(gckOS_DeleteMutex(Memory->os, Memory->mutex)); /* Mark the object as unknown. */ Memory->object.type = gcvOBJ_UNKNOWN; /* Free the gckVIDMEM object. */ gcmkVERIFY_OK(gckOS_Free(Memory->os, Memory)); /* Success. */ gcmkFOOTER_NO(); return gcvSTATUS_OK; }
/******************************************************************************* ** ** gckVIDMEM_DestroyVirtual ** ** Destroy an gcuVIDMEM_NODE union for virtual memory. ** ** INPUT: ** ** gcuVIDMEM_NODE_PTR Node ** Pointer to a gcuVIDMEM_NODE union. ** ** OUTPUT: ** ** Nothing. */ gceSTATUS gckVIDMEM_DestroyVirtual( IN gcuVIDMEM_NODE_PTR Node ) { gckOS os; gcmkHEADER_ARG("Node=0x%x", Node); /* Verify the arguments. */ gcmkVERIFY_OBJECT(Node->Virtual.kernel, gcvOBJ_KERNEL); /* Extact the gckOS object pointer. */ os = Node->Virtual.kernel->os; gcmkVERIFY_OBJECT(os, gcvOBJ_OS); #ifdef __QNXNTO__ /* Unregister. */ gcmkVERIFY_OK( gckMMU_RemoveNode(Node->Virtual.kernel->mmu, Node)); /* Free virtual memory. */ gcmkVERIFY_OK( gckOS_FreePagedMemory(os, Node->Virtual.physical, Node->Virtual.bytes)); #endif /* Delete the mutex. */ gcmkVERIFY_OK(gckOS_DeleteMutex(os, Node->Virtual.mutex)); if (Node->Virtual.pageTable != gcvNULL) { /* Free the pages. */ gcmkVERIFY_OK(gckMMU_FreePages(Node->Virtual.kernel->mmu, Node->Virtual.pageTable, Node->Virtual.pageCount)); } /* Delete the gcuVIDMEM_NODE union. */ gcmkVERIFY_OK(gckOS_Free(os, Node)); /* Success. */ gcmkFOOTER_NO(); return gcvSTATUS_OK; }
/******************************************************************************* ** ** gckHEAP_Destroy ** ** Destroy a gckHEAP object. ** ** INPUT: ** ** gckHEAP Heap ** Pointer to a gckHEAP object to destroy. ** ** OUTPUT: ** ** Nothing. */ gceSTATUS gckHEAP_Destroy( IN gckHEAP Heap ) { gcskHEAP_PTR heap; #if gcmIS_DEBUG(gcdDEBUG_CODE) gctSIZE_T leaked = 0; #endif gcmkHEADER_ARG("Heap=0x%x", Heap); for (heap = Heap->heap; heap != gcvNULL; heap = Heap->heap) { /* Unlink heap from linked list. */ Heap->heap = heap->next; #if gcmIS_DEBUG(gcdDEBUG_CODE) /* Check for leaked memory. */ leaked += _DumpHeap(heap); #endif /* Free the heap. */ gcmkVERIFY_OK(gckOS_FreeMemory(Heap->os, heap)); } /* Free the mutex. */ gcmkVERIFY_OK(gckOS_DeleteMutex(Heap->os, Heap->mutex)); /* Free the heap structure. */ gcmkVERIFY_OK(gckOS_FreeMemory(Heap->os, Heap)); /* Success. */ #if gcmIS_DEBUG(gcdDEBUG_CODE) gcmkFOOTER_ARG("leaked=%lu", leaked); #else gcmkFOOTER_NO(); #endif return gcvSTATUS_OK; }
/******************************************************************************* ** ** gckVGMMU_Construct ** ** Construct a new gckVGMMU object. ** ** INPUT: ** ** gckVGKERNEL Kernel ** Pointer to an gckVGKERNEL object. ** ** gctSIZE_T MmuSize ** Number of bytes for the page table. ** ** OUTPUT: ** ** gckVGMMU * Mmu ** Pointer to a variable that receives the gckVGMMU object pointer. */ gceSTATUS gckVGMMU_Construct( IN gckVGKERNEL Kernel, IN gctSIZE_T MmuSize, OUT gckVGMMU * Mmu ) { gckOS os; gckVGHARDWARE hardware; gceSTATUS status; gckVGMMU mmu; gctUINT32 * pageTable; gctUINT32 i; gcmkHEADER_ARG("Kernel=0x%x MmuSize=0x%x Mmu=0x%x", Kernel, MmuSize, Mmu); /* Verify the arguments. */ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL); gcmkVERIFY_ARGUMENT(MmuSize > 0); gcmkVERIFY_ARGUMENT(Mmu != gcvNULL); /* Extract the gckOS object pointer. */ os = Kernel->os; gcmkVERIFY_OBJECT(os, gcvOBJ_OS); /* Extract the gckVGHARDWARE object pointer. */ hardware = Kernel->hardware; gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE); /* Allocate memory for the gckVGMMU object. */ status = gckOS_Allocate(os, sizeof(struct _gckVGMMU), (gctPOINTER *) &mmu); if (status < 0) { /* Error. */ gcmkFATAL( "%s(%d): could not allocate gckVGMMU object.", __FUNCTION__, __LINE__ ); gcmkFOOTER(); return status; } /* Initialize the gckVGMMU object. */ mmu->object.type = gcvOBJ_MMU; mmu->os = os; mmu->hardware = hardware; /* Create the mutex. */ status = gckOS_CreateMutex(os, &mmu->mutex); if (status < 0) { /* Roll back. */ mmu->object.type = gcvOBJ_UNKNOWN; gcmkVERIFY_OK(gckOS_Free(os, mmu)); gcmkFOOTER(); /* Error. */ return status; } /* Allocate the page table. */ mmu->pageTableSize = MmuSize; status = gckOS_AllocateContiguous(os, gcvFALSE, &mmu->pageTableSize, &mmu->pageTablePhysical, &mmu->pageTableLogical); if (status < 0) { /* Roll back. */ gcmkVERIFY_OK(gckOS_DeleteMutex(os, mmu->mutex)); mmu->object.type = gcvOBJ_UNKNOWN; gcmkVERIFY_OK(gckOS_Free(os, mmu)); /* Error. */ gcmkFATAL( "%s(%d): could not allocate page table.", __FUNCTION__, __LINE__ ); gcmkFOOTER(); return status; } /* Compute number of entries in page table. */ mmu->entryCount = mmu->pageTableSize / sizeof(gctUINT32); mmu->entry = 0; /* Mark the entire page table as available. */ pageTable = (gctUINT32 *) mmu->pageTableLogical; for (i = 0; i < mmu->entryCount; i++) { pageTable[i] = (gctUINT32)~0; } /* Set page table address. */ status = gckVGHARDWARE_SetMMU(hardware, mmu->pageTableLogical); if (status < 0) { /* Free the page table. */ gcmkVERIFY_OK(gckOS_FreeContiguous(mmu->os, mmu->pageTablePhysical, mmu->pageTableLogical, mmu->pageTableSize)); /* Roll back. */ gcmkVERIFY_OK(gckOS_DeleteMutex(os, mmu->mutex)); mmu->object.type = gcvOBJ_UNKNOWN; gcmkVERIFY_OK(gckOS_Free(os, mmu)); /* Error. */ gcmkFATAL( "%s(%d): could not program page table.", __FUNCTION__, __LINE__ ); gcmkFOOTER(); return status; } /* Return the gckVGMMU object pointer. */ *Mmu = mmu; gcmkTRACE_ZONE( gcvLEVEL_INFO, gcvZONE_MMU, "%s(%d): %u entries at %p.(0x%08X)\n", __FUNCTION__, __LINE__, mmu->entryCount, mmu->pageTableLogical, mmu->pageTablePhysical ); gcmkFOOTER_NO(); /* Success. */ return gcvSTATUS_OK; }
/******************************************************************************* ** ** gckVIDMEM_Construct ** ** Construct a new gckVIDMEM object. ** ** INPUT: ** ** gckOS Os ** Pointer to an gckOS object. ** ** gctUINT32 BaseAddress ** Base address for the video memory heap. ** ** gctSIZE_T Bytes ** Number of bytes in the video memory heap. ** ** gctSIZE_T Threshold ** Minimum number of bytes beyond am allocation before the node is ** split. Can be used as a minimum alignment requirement. ** ** gctSIZE_T BankSize ** Number of bytes per physical memory bank. Used by bank ** optimization. ** ** OUTPUT: ** ** gckVIDMEM * Memory ** Pointer to a variable that will hold the pointer to the gckVIDMEM ** object. */ gceSTATUS gckVIDMEM_Construct( IN gckOS Os, IN gctUINT32 BaseAddress, IN gctSIZE_T Bytes, IN gctSIZE_T Threshold, IN gctSIZE_T BankSize, OUT gckVIDMEM * Memory ) { gckVIDMEM memory = gcvNULL; gceSTATUS status; gcuVIDMEM_NODE_PTR node; gctINT i, banks = 0; gcmkHEADER_ARG("Os=0x%x BaseAddress=%08x Bytes=%lu Threshold=%lu " "BankSize=%lu", Os, BaseAddress, Bytes, Threshold, BankSize); /* Verify the arguments. */ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS); gcmkVERIFY_ARGUMENT(Bytes > 0); gcmkVERIFY_ARGUMENT(Memory != gcvNULL); /* Allocate the gckVIDMEM object. */ gcmkONERROR( gckOS_Allocate(Os, gcmSIZEOF(struct _gckVIDMEM), (gctPOINTER *) &memory)); /* Initialize the gckVIDMEM object. */ memory->object.type = gcvOBJ_VIDMEM; memory->os = Os; /* Set video memory heap information. */ memory->baseAddress = BaseAddress; memory->bytes = Bytes; memory->freeBytes = Bytes; memory->threshold = Threshold; memory->mutex = gcvNULL; BaseAddress = 0; /* Walk all possible banks. */ for (i = 0; i < gcmCOUNTOF(memory->sentinel); ++i) { gctSIZE_T bytes; if (BankSize == 0) { /* Use all bytes for the first bank. */ bytes = Bytes; } else { /* Compute number of bytes for this bank. */ bytes = gcmALIGN(BaseAddress + 1, BankSize) - BaseAddress; if (bytes > Bytes) { /* Make sure we don't exceed the total number of bytes. */ bytes = Bytes; } } if (bytes == 0) { /* Mark heap is not used. */ memory->sentinel[i].VidMem.next = memory->sentinel[i].VidMem.prev = memory->sentinel[i].VidMem.nextFree = memory->sentinel[i].VidMem.prevFree = gcvNULL; continue; } /* Allocate one gcuVIDMEM_NODE union. */ gcmkONERROR( gckOS_Allocate(Os, gcmSIZEOF(gcuVIDMEM_NODE), (gctPOINTER *) &node)); /* Initialize gcuVIDMEM_NODE union. */ node->VidMem.memory = memory; node->VidMem.next = node->VidMem.prev = node->VidMem.nextFree = node->VidMem.prevFree = &memory->sentinel[i]; node->VidMem.offset = BaseAddress; node->VidMem.bytes = bytes; node->VidMem.alignment = 0; node->VidMem.physical = 0; node->VidMem.pool = gcvPOOL_UNKNOWN; node->VidMem.locked = 0; #ifdef __QNXNTO__ node->VidMem.logical = gcvNULL; node->VidMem.handle = 0; #endif /* Initialize the linked list of nodes. */ memory->sentinel[i].VidMem.next = memory->sentinel[i].VidMem.prev = memory->sentinel[i].VidMem.nextFree = memory->sentinel[i].VidMem.prevFree = node; /* Mark sentinel. */ memory->sentinel[i].VidMem.bytes = 0; /* Adjust address for next bank. */ BaseAddress += bytes; Bytes -= bytes; banks ++; } /* Assign all the bank mappings. */ memory->mapping[gcvSURF_RENDER_TARGET] = banks - 1; memory->mapping[gcvSURF_BITMAP] = banks - 1; if (banks > 1) --banks; memory->mapping[gcvSURF_DEPTH] = banks - 1; memory->mapping[gcvSURF_HIERARCHICAL_DEPTH] = banks - 1; if (banks > 1) --banks; memory->mapping[gcvSURF_TEXTURE] = banks - 1; if (banks > 1) --banks; memory->mapping[gcvSURF_VERTEX] = banks - 1; if (banks > 1) --banks; memory->mapping[gcvSURF_INDEX] = banks - 1; if (banks > 1) --banks; memory->mapping[gcvSURF_TILE_STATUS] = banks - 1; if (banks > 1) --banks; memory->mapping[gcvSURF_TYPE_UNKNOWN] = 0; gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM, "[GALCORE] INDEX: bank %d", memory->mapping[gcvSURF_INDEX]); gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM, "[GALCORE] VERTEX: bank %d", memory->mapping[gcvSURF_VERTEX]); gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM, "[GALCORE] TEXTURE: bank %d", memory->mapping[gcvSURF_TEXTURE]); gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM, "[GALCORE] RENDER_TARGET: bank %d", memory->mapping[gcvSURF_RENDER_TARGET]); gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM, "[GALCORE] DEPTH: bank %d", memory->mapping[gcvSURF_DEPTH]); gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM, "[GALCORE] TILE_STATUS: bank %d", memory->mapping[gcvSURF_TILE_STATUS]); /* Allocate the mutex. */ gcmkONERROR(gckOS_CreateMutex(Os, &memory->mutex)); /* Return pointer to the gckVIDMEM object. */ *Memory = memory; /* Success. */ gcmkFOOTER_ARG("*Memory=0x%x", *Memory); return gcvSTATUS_OK; OnError: /* Roll back. */ if (memory != gcvNULL) { if (memory->mutex != gcvNULL) { /* Delete the mutex. */ gcmkVERIFY_OK(gckOS_DeleteMutex(Os, memory->mutex)); } for (i = 0; i < banks; ++i) { /* Free the heap. */ gcmkASSERT(memory->sentinel[i].VidMem.next != gcvNULL); gcmkVERIFY_OK(gckOS_Free(Os, memory->sentinel[i].VidMem.next)); } /* Free the object. */ gcmkVERIFY_OK(gckOS_Free(Os, memory)); } /* Return the status. */ gcmkFOOTER(); return status; }
/******************************************************************************* ** ** gckVIDMEM_ConstructVirtual ** ** Construct a new gcuVIDMEM_NODE union for virtual memory. ** ** INPUT: ** ** gckKERNEL Kernel ** Pointer to an gckKERNEL object. ** ** gctSIZE_T Bytes ** Number of byte to allocate. ** ** OUTPUT: ** ** gcuVIDMEM_NODE_PTR * Node ** Pointer to a variable that receives the gcuVIDMEM_NODE union pointer. */ gceSTATUS gckVIDMEM_ConstructVirtual( IN gckKERNEL Kernel, IN gctBOOL Contiguous, IN gctSIZE_T Bytes, #ifdef __QNXNTO__ IN gctHANDLE Handle, #endif OUT gcuVIDMEM_NODE_PTR * Node ) { gckOS os; gceSTATUS status; gcuVIDMEM_NODE_PTR node = gcvNULL; gcmkHEADER_ARG("Kernel=0x%x Bytes=%lu", Kernel, Bytes); /* Verify the arguments. */ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL); gcmkVERIFY_ARGUMENT(Bytes > 0); gcmkVERIFY_ARGUMENT(Node != gcvNULL); #ifdef __QNXNTO__ gcmkVERIFY_ARGUMENT(Handle != gcvNULL); #endif /* Extract the gckOS object pointer. */ os = Kernel->os; gcmkVERIFY_OBJECT(os, gcvOBJ_OS); /* Allocate an gcuVIDMEM_NODE union. */ gcmkONERROR( gckOS_Allocate(os, gcmSIZEOF(gcuVIDMEM_NODE), (gctPOINTER *) &node)); /* Initialize gcuVIDMEM_NODE union for virtual memory. */ node->Virtual.kernel = Kernel; node->Virtual.contiguous = Contiguous; node->Virtual.locked = 0; node->Virtual.logical = gcvNULL; node->Virtual.pageTable = gcvNULL; node->Virtual.mutex = gcvNULL; #ifdef __QNXNTO__ node->Virtual.next = gcvNULL; node->Virtual.unlockPending = gcvFALSE; node->Virtual.freePending = gcvFALSE; node->Virtual.handle = Handle; #else node->Virtual.pending = gcvFALSE; #endif /* Create the mutex. */ gcmkONERROR( gckOS_CreateMutex(os, &node->Virtual.mutex)); /* Allocate the virtual memory. */ gcmkONERROR( gckOS_AllocatePagedMemoryEx(os, node->Virtual.contiguous, node->Virtual.bytes = Bytes, &node->Virtual.physical)); #ifdef __QNXNTO__ /* Register. */ gckMMU_InsertNode(Kernel->mmu, node); #endif /* Return pointer to the gcuVIDMEM_NODE union. */ *Node = node; gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM, "Created virtual node 0x%x for %u bytes @ 0x%x", node, Bytes, node->Virtual.physical); /* Success. */ gcmkFOOTER_ARG("*Node=0x%x", *Node); return gcvSTATUS_OK; OnError: /* Roll back. */ if (node != gcvNULL) { if (node->Virtual.mutex != gcvNULL) { /* Destroy the mutex. */ gcmkVERIFY_OK(gckOS_DeleteMutex(os, node->Virtual.mutex)); } /* Free the structure. */ gcmkVERIFY_OK(gckOS_Free(os, node)); } /* Return the status. */ gcmkFOOTER(); return status; }
/******************************************************************************* ** ** gckCOMMAND_Construct ** ** Construct a new gckCOMMAND object. ** ** INPUT: ** ** gckKERNEL Kernel ** Pointer to an gckKERNEL object. ** ** OUTPUT: ** ** gckCOMMAND * Command ** Pointer to a variable that will hold the pointer to the gckCOMMAND ** object. */ gceSTATUS gckCOMMAND_Construct( IN gckKERNEL Kernel, OUT gckCOMMAND * Command ) { gckOS os; gckCOMMAND command = gcvNULL; gceSTATUS status; gctINT i; gcmkHEADER_ARG("Kernel=0x%x", Kernel); /* Verify the arguments. */ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL); gcmkVERIFY_ARGUMENT(Command != gcvNULL); /* Extract the gckOS object. */ os = Kernel->os; /* Allocate the gckCOMMAND structure. */ gcmkONERROR( gckOS_Allocate(os, gcmSIZEOF(struct _gckCOMMAND), (gctPOINTER *) &command)); /* Initialize the gckCOMMAND object.*/ command->object.type = gcvOBJ_COMMAND; command->kernel = Kernel; command->os = os; command->mutexQueue = gcvNULL; command->mutexContext = gcvNULL; /* No command queues created yet. */ command->index = 0; for (i = 0; i < gcdCOMMAND_QUEUES; ++i) { command->queues[i].signal = gcvNULL; command->queues[i].logical = gcvNULL; } /* Get the command buffer requirements. */ gcmkONERROR( gckHARDWARE_QueryCommandBuffer(Kernel->hardware, &command->alignment, &command->reservedHead, &command->reservedTail)); /* No contexts available yet. */ command->contextCounter = command->currentContext = 0; /* Create the command queue mutex. */ gcmkONERROR( gckOS_CreateMutex(os, &command->mutexQueue)); /* Create the context switching mutex. */ gcmkONERROR( gckOS_CreateMutex(os, &command->mutexContext)); /* Get the page size from teh OS. */ gcmkONERROR( gckOS_GetPageSize(os, &command->pageSize)); /* Set hardware to pipe 0. */ command->pipeSelect = 0; /* Pre-allocate the command queues. */ for (i = 0; i < gcdCOMMAND_QUEUES; ++i) { gcmkONERROR( gckOS_AllocateNonPagedMemory(os, gcvFALSE, &command->pageSize, &command->queues[i].physical, &command->queues[i].logical)); gcmkONERROR( gckOS_CreateSignal(os, gcvFALSE, &command->queues[i].signal)); gcmkONERROR( gckOS_Signal(os, command->queues[i].signal, gcvTRUE)); } /* No command queue in use yet. */ command->index = -1; command->logical = gcvNULL; command->newQueue = gcvFALSE; command->submit = gcvFALSE; /* Command is not yet running. */ command->running = gcvFALSE; /* Command queue is idle. */ command->idle = gcvTRUE; /* Commit stamp is zero. */ command->commitStamp = 0; /* Return pointer to the gckCOMMAND object. */ *Command = command; /* Success. */ gcmkFOOTER_ARG("*Command=0x%x", *Command); return gcvSTATUS_OK; OnError: /* Roll back. */ if (command != gcvNULL) { if (command->mutexContext != gcvNULL) { gcmkVERIFY_OK(gckOS_DeleteMutex(os, command->mutexContext)); } if (command->mutexQueue != gcvNULL) { gcmkVERIFY_OK(gckOS_DeleteMutex(os, command->mutexQueue)); } for (i = 0; i < gcdCOMMAND_QUEUES; ++i) { if (command->queues[i].signal != gcvNULL) { gcmkVERIFY_OK( gckOS_DestroySignal(os, command->queues[i].signal)); } if (command->queues[i].logical != gcvNULL) { gcmkVERIFY_OK( gckOS_FreeNonPagedMemory(os, command->pageSize, command->queues[i].physical, command->queues[i].logical)); } } gcmkVERIFY_OK(gckOS_Free(os, command)); } /* Return the status. */ gcmkFOOTER(); return status; }