mkregtable.c revision 1.3 1 1.2 riastrad /* $NetBSD: mkregtable.c,v 1.3 2021/12/18 23:45:42 riastradh Exp $ */
2 1.2 riastrad
3 1.3 riastrad // SPDX-License-Identifier: MIT
4 1.1 riastrad /* utility to create the register check tables
5 1.1 riastrad * this includes inlined list.h safe for userspace.
6 1.1 riastrad *
7 1.1 riastrad * Copyright 2009 Jerome Glisse
8 1.1 riastrad * Copyright 2009 Red Hat Inc.
9 1.1 riastrad *
10 1.1 riastrad * Authors:
11 1.1 riastrad * Jerome Glisse
12 1.1 riastrad * Dave Airlie
13 1.1 riastrad */
14 1.1 riastrad
15 1.2 riastrad #include <sys/cdefs.h>
16 1.2 riastrad __KERNEL_RCSID(0, "$NetBSD: mkregtable.c,v 1.3 2021/12/18 23:45:42 riastradh Exp $");
17 1.2 riastrad
18 1.1 riastrad #include <sys/types.h>
19 1.1 riastrad #include <stdlib.h>
20 1.1 riastrad #include <string.h>
21 1.1 riastrad #include <stdio.h>
22 1.1 riastrad #include <regex.h>
23 1.1 riastrad #include <libgen.h>
24 1.1 riastrad
25 1.1 riastrad #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
26 1.1 riastrad /**
27 1.1 riastrad * container_of - cast a member of a structure out to the containing structure
28 1.1 riastrad * @ptr: the pointer to the member.
29 1.1 riastrad * @type: the type of the container struct this is embedded in.
30 1.1 riastrad * @member: the name of the member within the struct.
31 1.1 riastrad *
32 1.1 riastrad */
33 1.1 riastrad #define container_of(ptr, type, member) ({ \
34 1.1 riastrad const typeof(((type *)0)->member)*__mptr = (ptr); \
35 1.1 riastrad (type *)((char *)__mptr - offsetof(type, member)); })
36 1.1 riastrad
37 1.1 riastrad /*
38 1.1 riastrad * Simple doubly linked list implementation.
39 1.1 riastrad *
40 1.1 riastrad * Some of the internal functions ("__xxx") are useful when
41 1.1 riastrad * manipulating whole lists rather than single entries, as
42 1.1 riastrad * sometimes we already know the next/prev entries and we can
43 1.1 riastrad * generate better code by using them directly rather than
44 1.1 riastrad * using the generic single-entry routines.
45 1.1 riastrad */
46 1.1 riastrad
47 1.1 riastrad struct list_head {
48 1.1 riastrad struct list_head *next, *prev;
49 1.1 riastrad };
50 1.1 riastrad
51 1.1 riastrad
52 1.1 riastrad static inline void INIT_LIST_HEAD(struct list_head *list)
53 1.1 riastrad {
54 1.1 riastrad list->next = list;
55 1.1 riastrad list->prev = list;
56 1.1 riastrad }
57 1.1 riastrad
58 1.1 riastrad /*
59 1.1 riastrad * Insert a new entry between two known consecutive entries.
60 1.1 riastrad *
61 1.1 riastrad * This is only for internal list manipulation where we know
62 1.1 riastrad * the prev/next entries already!
63 1.1 riastrad */
64 1.1 riastrad #ifndef CONFIG_DEBUG_LIST
65 1.1 riastrad static inline void __list_add(struct list_head *new,
66 1.1 riastrad struct list_head *prev, struct list_head *next)
67 1.1 riastrad {
68 1.1 riastrad next->prev = new;
69 1.1 riastrad new->next = next;
70 1.1 riastrad new->prev = prev;
71 1.1 riastrad prev->next = new;
72 1.1 riastrad }
73 1.1 riastrad #else
74 1.1 riastrad extern void __list_add(struct list_head *new,
75 1.1 riastrad struct list_head *prev, struct list_head *next);
76 1.1 riastrad #endif
77 1.1 riastrad
78 1.1 riastrad /**
79 1.1 riastrad * list_add_tail - add a new entry
80 1.1 riastrad * @new: new entry to be added
81 1.1 riastrad * @head: list head to add it before
82 1.1 riastrad *
83 1.1 riastrad * Insert a new entry before the specified head.
84 1.1 riastrad * This is useful for implementing queues.
85 1.1 riastrad */
86 1.1 riastrad static inline void list_add_tail(struct list_head *new, struct list_head *head)
87 1.1 riastrad {
88 1.1 riastrad __list_add(new, head->prev, head);
89 1.1 riastrad }
90 1.1 riastrad
91 1.1 riastrad /**
92 1.1 riastrad * list_entry - get the struct for this entry
93 1.1 riastrad * @ptr: the &struct list_head pointer.
94 1.1 riastrad * @type: the type of the struct this is embedded in.
95 1.2 riastrad * @member: the name of the list_head within the struct.
96 1.1 riastrad */
97 1.1 riastrad #define list_entry(ptr, type, member) \
98 1.1 riastrad container_of(ptr, type, member)
99 1.1 riastrad
100 1.1 riastrad /**
101 1.1 riastrad * list_for_each_entry - iterate over list of given type
102 1.1 riastrad * @pos: the type * to use as a loop cursor.
103 1.1 riastrad * @head: the head for your list.
104 1.2 riastrad * @member: the name of the list_head within the struct.
105 1.1 riastrad */
106 1.1 riastrad #define list_for_each_entry(pos, head, member) \
107 1.1 riastrad for (pos = list_entry((head)->next, typeof(*pos), member); \
108 1.1 riastrad &pos->member != (head); \
109 1.1 riastrad pos = list_entry(pos->member.next, typeof(*pos), member))
110 1.1 riastrad
111 1.1 riastrad struct offset {
112 1.1 riastrad struct list_head list;
113 1.1 riastrad unsigned offset;
114 1.1 riastrad };
115 1.1 riastrad
116 1.1 riastrad struct table {
117 1.1 riastrad struct list_head offsets;
118 1.1 riastrad unsigned offset_max;
119 1.1 riastrad unsigned nentry;
120 1.1 riastrad unsigned *table;
121 1.1 riastrad char *gpu_prefix;
122 1.1 riastrad };
123 1.1 riastrad
124 1.1 riastrad static struct offset *offset_new(unsigned o)
125 1.1 riastrad {
126 1.1 riastrad struct offset *offset;
127 1.1 riastrad
128 1.1 riastrad offset = (struct offset *)malloc(sizeof(struct offset));
129 1.1 riastrad if (offset) {
130 1.1 riastrad INIT_LIST_HEAD(&offset->list);
131 1.1 riastrad offset->offset = o;
132 1.1 riastrad }
133 1.1 riastrad return offset;
134 1.1 riastrad }
135 1.1 riastrad
136 1.1 riastrad static void table_offset_add(struct table *t, struct offset *offset)
137 1.1 riastrad {
138 1.1 riastrad list_add_tail(&offset->list, &t->offsets);
139 1.1 riastrad }
140 1.1 riastrad
141 1.1 riastrad static void table_init(struct table *t)
142 1.1 riastrad {
143 1.1 riastrad INIT_LIST_HEAD(&t->offsets);
144 1.1 riastrad t->offset_max = 0;
145 1.1 riastrad t->nentry = 0;
146 1.1 riastrad t->table = NULL;
147 1.1 riastrad }
148 1.1 riastrad
149 1.1 riastrad static void table_print(struct table *t)
150 1.1 riastrad {
151 1.1 riastrad unsigned nlloop, i, j, n, c, id;
152 1.1 riastrad
153 1.1 riastrad nlloop = (t->nentry + 3) / 4;
154 1.1 riastrad c = t->nentry;
155 1.1 riastrad printf("static const unsigned %s_reg_safe_bm[%d] = {\n", t->gpu_prefix,
156 1.1 riastrad t->nentry);
157 1.1 riastrad for (i = 0, id = 0; i < nlloop; i++) {
158 1.1 riastrad n = 4;
159 1.1 riastrad if (n > c)
160 1.1 riastrad n = c;
161 1.1 riastrad c -= n;
162 1.1 riastrad for (j = 0; j < n; j++) {
163 1.1 riastrad if (j == 0)
164 1.1 riastrad printf("\t");
165 1.1 riastrad else
166 1.1 riastrad printf(" ");
167 1.1 riastrad printf("0x%08X,", t->table[id++]);
168 1.1 riastrad }
169 1.1 riastrad printf("\n");
170 1.1 riastrad }
171 1.1 riastrad printf("};\n");
172 1.1 riastrad }
173 1.1 riastrad
174 1.1 riastrad static int table_build(struct table *t)
175 1.1 riastrad {
176 1.1 riastrad struct offset *offset;
177 1.1 riastrad unsigned i, m;
178 1.1 riastrad
179 1.1 riastrad t->nentry = ((t->offset_max >> 2) + 31) / 32;
180 1.1 riastrad t->table = (unsigned *)malloc(sizeof(unsigned) * t->nentry);
181 1.1 riastrad if (t->table == NULL)
182 1.1 riastrad return -1;
183 1.1 riastrad memset(t->table, 0xff, sizeof(unsigned) * t->nentry);
184 1.1 riastrad list_for_each_entry(offset, &t->offsets, list) {
185 1.1 riastrad i = (offset->offset >> 2) / 32;
186 1.1 riastrad m = (offset->offset >> 2) & 31;
187 1.1 riastrad m = 1 << m;
188 1.1 riastrad t->table[i] ^= m;
189 1.1 riastrad }
190 1.1 riastrad return 0;
191 1.1 riastrad }
192 1.1 riastrad
193 1.1 riastrad static char gpu_name[10];
194 1.1 riastrad static int parser_auth(struct table *t, const char *filename)
195 1.1 riastrad {
196 1.1 riastrad FILE *file;
197 1.1 riastrad regex_t mask_rex;
198 1.1 riastrad regmatch_t match[4];
199 1.1 riastrad char buf[1024];
200 1.1 riastrad size_t end;
201 1.1 riastrad int len;
202 1.1 riastrad int done = 0;
203 1.1 riastrad int r;
204 1.1 riastrad unsigned o;
205 1.1 riastrad struct offset *offset;
206 1.1 riastrad char last_reg_s[10];
207 1.1 riastrad int last_reg;
208 1.1 riastrad
209 1.1 riastrad if (regcomp
210 1.1 riastrad (&mask_rex, "(0x[0-9a-fA-F]*) *([_a-zA-Z0-9]*)", REG_EXTENDED)) {
211 1.1 riastrad fprintf(stderr, "Failed to compile regular expression\n");
212 1.1 riastrad return -1;
213 1.1 riastrad }
214 1.1 riastrad file = fopen(filename, "r");
215 1.1 riastrad if (file == NULL) {
216 1.1 riastrad fprintf(stderr, "Failed to open: %s\n", filename);
217 1.1 riastrad return -1;
218 1.1 riastrad }
219 1.1 riastrad fseek(file, 0, SEEK_END);
220 1.1 riastrad end = ftell(file);
221 1.1 riastrad fseek(file, 0, SEEK_SET);
222 1.1 riastrad
223 1.1 riastrad /* get header */
224 1.1 riastrad if (fgets(buf, 1024, file) == NULL) {
225 1.1 riastrad fclose(file);
226 1.1 riastrad return -1;
227 1.1 riastrad }
228 1.1 riastrad
229 1.1 riastrad /* first line will contain the last register
230 1.1 riastrad * and gpu name */
231 1.1 riastrad sscanf(buf, "%9s %9s", gpu_name, last_reg_s);
232 1.1 riastrad t->gpu_prefix = gpu_name;
233 1.1 riastrad last_reg = strtol(last_reg_s, NULL, 16);
234 1.1 riastrad
235 1.1 riastrad do {
236 1.1 riastrad if (fgets(buf, 1024, file) == NULL) {
237 1.1 riastrad fclose(file);
238 1.1 riastrad return -1;
239 1.1 riastrad }
240 1.1 riastrad len = strlen(buf);
241 1.1 riastrad if (ftell(file) == end)
242 1.1 riastrad done = 1;
243 1.1 riastrad if (len) {
244 1.1 riastrad r = regexec(&mask_rex, buf, 4, match, 0);
245 1.1 riastrad if (r == REG_NOMATCH) {
246 1.1 riastrad } else if (r) {
247 1.1 riastrad fprintf(stderr,
248 1.1 riastrad "Error matching regular expression %d in %s\n",
249 1.1 riastrad r, filename);
250 1.1 riastrad fclose(file);
251 1.1 riastrad return -1;
252 1.1 riastrad } else {
253 1.1 riastrad buf[match[0].rm_eo] = 0;
254 1.1 riastrad buf[match[1].rm_eo] = 0;
255 1.1 riastrad buf[match[2].rm_eo] = 0;
256 1.1 riastrad o = strtol(&buf[match[1].rm_so], NULL, 16);
257 1.1 riastrad offset = offset_new(o);
258 1.1 riastrad table_offset_add(t, offset);
259 1.1 riastrad if (o > t->offset_max)
260 1.1 riastrad t->offset_max = o;
261 1.1 riastrad }
262 1.1 riastrad }
263 1.1 riastrad } while (!done);
264 1.1 riastrad fclose(file);
265 1.1 riastrad if (t->offset_max < last_reg)
266 1.1 riastrad t->offset_max = last_reg;
267 1.1 riastrad return table_build(t);
268 1.1 riastrad }
269 1.1 riastrad
270 1.1 riastrad int main(int argc, char *argv[])
271 1.1 riastrad {
272 1.1 riastrad struct table t;
273 1.1 riastrad
274 1.1 riastrad if (argc != 2) {
275 1.1 riastrad fprintf(stderr, "Usage: %s <authfile>\n", argv[0]);
276 1.1 riastrad exit(1);
277 1.1 riastrad }
278 1.1 riastrad table_init(&t);
279 1.1 riastrad if (parser_auth(&t, argv[1])) {
280 1.1 riastrad fprintf(stderr, "Failed to parse file %s\n", argv[1]);
281 1.1 riastrad return -1;
282 1.1 riastrad }
283 1.1 riastrad table_print(&t);
284 1.1 riastrad return 0;
285 1.1 riastrad }
286