int etna_queue_alloc(struct etna_queue *queue, struct _gcsHAL_INTERFACE **cmd_out) { int rv; if(queue == NULL) return ETNA_INVALID_ADDR; if(queue->count == queue->max_count) { /* Queue is full, flush context. Assert that there is a one-to-one relationship * between queue and etna context so that flushing the context flushes this queue. */ assert(queue->ctx->queue == queue); if((rv = etna_flush(queue->ctx)) != ETNA_OK) return rv; assert(queue->count == 0); } struct _gcsQUEUE *cmd = &queue->queue[queue->count++]; cmd->next = PTR_TO_VIV(NULL); /* update next pointer of previous record */ if(queue->last != NULL) { queue->last->next = PTR_TO_VIV(cmd); } queue->last = cmd; *cmd_out = &cmd->iface; return ETNA_OK; }
int etna_queue_free_contiguous(struct etna_queue *queue, size_t bytes, viv_addr_t physical, void *logical) { struct _gcsHAL_INTERFACE *cmd = NULL; int rv; if((rv=etna_queue_alloc(queue, &cmd)) != ETNA_OK) return rv; cmd->command = gcvHAL_FREE_CONTIGUOUS_MEMORY; cmd->u.FreeContiguousMemory.bytes = bytes; cmd->u.FreeContiguousMemory.physical = PTR_TO_VIV((gctPHYS_ADDR)physical); cmd->u.FreeContiguousMemory.logical = PTR_TO_VIV(logical); return ETNA_OK; }
int etna_queue_signal(struct etna_queue *queue, int sig_id, enum viv_where fromWhere) { struct _gcsHAL_INTERFACE *cmd = NULL; int rv; if((rv=etna_queue_alloc(queue, &cmd)) != ETNA_OK) return rv; cmd->command = gcvHAL_SIGNAL; cmd->u.Signal.signal = PTR_TO_VIV((void*)sig_id); cmd->u.Signal.auxSignal = PTR_TO_VIV((void*)0x0); cmd->u.Signal.process = HANDLE_TO_VIV(queue->ctx->conn->process); cmd->u.Signal.fromWhere = convert_where(fromWhere); return ETNA_OK; }
int etna_queue_unmap_user_memory(struct etna_queue *queue, void *memory, size_t size, viv_usermem_t info, viv_addr_t address) { struct _gcsHAL_INTERFACE *cmd = NULL; int rv; if((rv=etna_queue_alloc(queue, &cmd)) != ETNA_OK) return rv; cmd->command = gcvHAL_UNMAP_USER_MEMORY; cmd->u.UnmapUserMemory.memory = PTR_TO_VIV(memory); cmd->u.UnmapUserMemory.size = size; cmd->u.UnmapUserMemory.info = HANDLE_TO_VIV(info); cmd->u.UnmapUserMemory.address = address; return ETNA_OK; }
int etna_create(struct viv_conn *conn, struct etna_ctx **ctx_out) { int rv; if(ctx_out == NULL) return ETNA_INVALID_ADDR; struct etna_ctx *ctx = ETNA_CALLOC_STRUCT(etna_ctx); if(ctx == NULL) return ETNA_OUT_OF_MEMORY; ctx->conn = conn; if(gpu_context_initialize(ctx) != ETNA_OK) { ETNA_FREE(ctx); return ETNA_INTERNAL_ERROR; } /* Create synchronization signal */ if(viv_user_signal_create(conn, 0, &ctx->sig_id) != 0) /* automatic resetting signal */ { #ifdef DEBUG fprintf(stderr, "Cannot create user signal\n"); #endif return ETNA_INTERNAL_ERROR; } #ifdef DEBUG fprintf(stderr, "Created user signal %i\n", ctx->sig_id); #endif /* Allocate command buffers, and create a synchronization signal for each. * Also signal the synchronization signal for the buffers to tell that the buffers are ready for use. */ for(int x=0; x<NUM_COMMAND_BUFFERS; ++x) { ctx->cmdbuf[x] = ETNA_CALLOC_STRUCT(_gcoCMDBUF); if((ctx->cmdbufi[x].bo = etna_bo_new(conn, COMMAND_BUFFER_SIZE, DRM_ETNA_GEM_TYPE_CMD))==NULL) { #ifdef DEBUG fprintf(stderr, "Error allocating host memory for command buffer\n"); #endif return ETNA_OUT_OF_MEMORY; } ctx->cmdbuf[x]->object.type = gcvOBJ_COMMANDBUFFER; #ifdef GCABI_CMDBUF_HAS_PHYSICAL ctx->cmdbuf[x]->physical = PTR_TO_VIV((void*)etna_bo_gpu_address(ctx->cmdbufi[x].bo)); ctx->cmdbuf[x]->bytes = ctx->cmdbufi[x].bytes; #endif ctx->cmdbuf[x]->logical = PTR_TO_VIV((void*)etna_bo_map(ctx->cmdbufi[x].bo)); if(viv_user_signal_create(conn, 0, &ctx->cmdbufi[x].sig_id) != 0 || viv_user_signal_signal(conn, ctx->cmdbufi[x].sig_id, 1) != 0) { #ifdef DEBUG fprintf(stderr, "Cannot create user signal\n"); #endif return ETNA_INTERNAL_ERROR; } #ifdef DEBUG fprintf(stderr, "Allocated buffer %i: phys=%08x log=%08x bytes=%08x [signal %i]\n", x, (uint32_t)buf0_physical, (uint32_t)buf0_logical, buf0_bytes, ctx->cmdbufi[x].sig); #endif } /* Allocate command queue */ if((rv = etna_queue_create(ctx, &ctx->queue)) != ETNA_OK) { #ifdef DEBUG fprintf(stderr, "Error allocating kernel command queue\n"); #endif return rv; } /* Set current buffer to ETNA_NO_BUFFER, to signify that we need to switch to buffer 0 before * queueing of commands can be started. */ ctx->cur_buf = ETNA_NO_BUFFER; *ctx_out = ctx; return ETNA_OK; }
#define munmap my_munmap #define ioctl my_ioctl #endif //#define DEBUG const char *galcore_device[] = {"/dev/gal3d", "/dev/galcore", "/dev/graphics/galcore", NULL}; #define INTERFACE_SIZE (sizeof(gcsHAL_INTERFACE)) /* Call ioctl interface with structure cmd as input and output. * @returns status (VIV_STATUS_xxx) */ int viv_invoke(struct viv_conn *conn, struct _gcsHAL_INTERFACE *cmd) { vivante_ioctl_data_t ic = { #ifdef GCABI_UINT64_IOCTL_DATA .in_buf = PTR_TO_VIV(cmd), .in_buf_size = INTERFACE_SIZE, .out_buf = PTR_TO_VIV(cmd), .out_buf_size = INTERFACE_SIZE #else .in_buf = (void*)cmd, .in_buf_size = INTERFACE_SIZE, .out_buf = (void*)cmd, .out_buf_size = INTERFACE_SIZE #endif }; #ifdef GCABI_HAS_HARDWARE_TYPE cmd->hardwareType = (gceHARDWARE_TYPE)conn->hw_type; #endif if(ioctl(conn->fd, IOCTL_GCHAL_INTERFACE, &ic) < 0) return -1;