1/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */ 2 3/* 4 * Copyright (C) 2014 Rob Clark <robclark@freedesktop.org> 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice (including the next 14 * paragraph) shall be included in all copies or substantial portions of the 15 * Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 * SOFTWARE. 24 * 25 * Authors: 26 * Rob Clark <robclark@freedesktop.org> 27 */ 28 29#include <assert.h> 30#include <err.h> 31#include <stdint.h> 32#include <stdio.h> 33#include <stdlib.h> 34#include <string.h> 35 36#include "rnnutil.h" 37 38static struct rnndomain * 39finddom(struct rnn *rnn, uint32_t regbase) 40{ 41 if (rnndec_checkaddr(rnn->vc, rnn->dom[0], regbase, 0)) 42 return rnn->dom[0]; 43 return rnn->dom[1]; 44} 45 46void 47_rnn_init(struct rnn *rnn, int nocolor) 48{ 49 rnn_init(); 50 51 rnn->db = rnn_newdb(); 52 rnn->vc_nocolor = rnndec_newcontext(rnn->db); 53 rnn->vc_nocolor->colors = &envy_null_colors; 54 if (nocolor) { 55 rnn->vc = rnn->vc_nocolor; 56 } else { 57 rnn->vc = rnndec_newcontext(rnn->db); 58 rnn->vc->colors = &envy_def_colors; 59 } 60} 61 62struct rnn * 63rnn_new(int nocolor) 64{ 65 struct rnn *rnn = calloc(sizeof(*rnn), 1); 66 67 if (!rnn) 68 return NULL; 69 70 _rnn_init(rnn, nocolor); 71 72 return rnn; 73} 74 75static void 76init(struct rnn *rnn, char *file, char *domain) 77{ 78 /* prepare rnn stuff for lookup */ 79 rnn_parsefile(rnn->db, file); 80 rnn_prepdb(rnn->db); 81 rnn->dom[0] = rnn_finddomain(rnn->db, domain); 82 if ((strcmp(domain, "A2XX") == 0) || (strcmp(domain, "A3XX") == 0)) { 83 rnn->dom[1] = rnn_finddomain(rnn->db, "AXXX"); 84 } else { 85 rnn->dom[1] = rnn->dom[0]; 86 } 87 if (!rnn->dom[0] && rnn->dom[1]) { 88 fprintf(stderr, "Could not find domain %s in %s\n", domain, file); 89 } 90 rnn->variant = domain; 91 92 rnndec_varadd(rnn->vc, "chip", domain); 93 if (rnn->vc != rnn->vc_nocolor) 94 rnndec_varadd(rnn->vc_nocolor, "chip", domain); 95 if (rnn->db->estatus) 96 errx(rnn->db->estatus, "failed to parse register database"); 97} 98 99void 100rnn_load_file(struct rnn *rnn, char *file, char *domain) 101{ 102 init(rnn, file, domain); 103} 104 105void 106rnn_load(struct rnn *rnn, const char *gpuname) 107{ 108 if (strstr(gpuname, "a2")) { 109 init(rnn, "adreno/a2xx.xml", "A2XX"); 110 } else if (strstr(gpuname, "a3")) { 111 init(rnn, "adreno/a3xx.xml", "A3XX"); 112 } else if (strstr(gpuname, "a4")) { 113 init(rnn, "adreno/a4xx.xml", "A4XX"); 114 } else if (strstr(gpuname, "a5")) { 115 init(rnn, "adreno/a5xx.xml", "A5XX"); 116 } else if (strstr(gpuname, "a6")) { 117 init(rnn, "adreno/a6xx.xml", "A6XX"); 118 } 119} 120 121uint32_t 122rnn_regbase(struct rnn *rnn, const char *name) 123{ 124 uint32_t regbase = rnndec_decodereg(rnn->vc_nocolor, rnn->dom[0], name); 125 if (!regbase) 126 regbase = rnndec_decodereg(rnn->vc_nocolor, rnn->dom[1], name); 127 return regbase; 128} 129 130const char * 131rnn_regname(struct rnn *rnn, uint32_t regbase, int color) 132{ 133 static char buf[128]; 134 struct rnndecaddrinfo *info; 135 136 info = rnndec_decodeaddr(color ? rnn->vc : rnn->vc_nocolor, 137 finddom(rnn, regbase), regbase, 0); 138 if (info) { 139 strcpy(buf, info->name); 140 free(info->name); 141 free(info); 142 return buf; 143 } 144 return NULL; 145} 146 147struct rnndecaddrinfo * 148rnn_reginfo(struct rnn *rnn, uint32_t regbase) 149{ 150 return rnndec_decodeaddr(rnn->vc, finddom(rnn, regbase), regbase, 0); 151} 152 153const char * 154rnn_enumname(struct rnn *rnn, const char *name, uint32_t val) 155{ 156 return rnndec_decode_enum(rnn->vc, name, val); 157} 158 159static struct rnndelem * 160regelem(struct rnndomain *domain, const char *name) 161{ 162 int i; 163 for (i = 0; i < domain->subelemsnum; i++) { 164 struct rnndelem *elem = domain->subelems[i]; 165 if (!strcmp(elem->name, name)) 166 return elem; 167 } 168 return NULL; 169} 170 171/* Lookup rnndelem by name: */ 172struct rnndelem * 173rnn_regelem(struct rnn *rnn, const char *name) 174{ 175 struct rnndelem *elem = regelem(rnn->dom[0], name); 176 if (elem) 177 return elem; 178 return regelem(rnn->dom[1], name); 179} 180 181static struct rnndelem * 182regoff(struct rnndomain *domain, uint32_t offset) 183{ 184 int i; 185 for (i = 0; i < domain->subelemsnum; i++) { 186 struct rnndelem *elem = domain->subelems[i]; 187 if (elem->offset == offset) 188 return elem; 189 } 190 return NULL; 191} 192 193/* Lookup rnndelem by offset: */ 194struct rnndelem * 195rnn_regoff(struct rnn *rnn, uint32_t offset) 196{ 197 struct rnndelem *elem = regoff(rnn->dom[0], offset); 198 if (elem) 199 return elem; 200 return regoff(rnn->dom[1], offset); 201} 202 203enum rnnttype 204rnn_decodelem(struct rnn *rnn, struct rnntypeinfo *info, uint64_t regval, 205 union rnndecval *val) 206{ 207 val->u = regval; 208 switch (info->type) { 209 case RNN_TTYPE_INLINE_ENUM: 210 case RNN_TTYPE_ENUM: 211 case RNN_TTYPE_HEX: 212 case RNN_TTYPE_INT: 213 case RNN_TTYPE_UINT: 214 case RNN_TTYPE_FLOAT: 215 case RNN_TTYPE_BOOLEAN: 216 return info->type; 217 case RNN_TTYPE_FIXED: 218 case RNN_TTYPE_UFIXED: 219 /* TODO */ 220 default: 221 return RNN_TTYPE_INVALID; 222 } 223} 224