1 // SPDX-License-Identifier: MIT
2 /* utility to create the register check tables
3 * this includes inlined list.h safe for userspace.
5 * Copyright 2009 Jerome Glisse
6 * Copyright 2009 Red Hat Inc.
13 #include <sys/types.h>
20 #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
22 * container_of - cast a member of a structure out to the containing structure
23 * @ptr: the pointer to the member.
24 * @type: the type of the container struct this is embedded in.
25 * @member: the name of the member within the struct.
28 #define container_of(ptr, type, member) ({ \
29 const typeof(((type *)0)->member)*__mptr = (ptr); \
30 (type *)((char *)__mptr - offsetof(type, member)); })
33 * Simple doubly linked list implementation.
35 * Some of the internal functions ("__xxx") are useful when
36 * manipulating whole lists rather than single entries, as
37 * sometimes we already know the next/prev entries and we can
38 * generate better code by using them directly rather than
39 * using the generic single-entry routines.
43 struct list_head
*next
, *prev
;
47 static inline void INIT_LIST_HEAD(struct list_head
*list
)
54 * Insert a new entry between two known consecutive entries.
56 * This is only for internal list manipulation where we know
57 * the prev/next entries already!
59 #ifndef CONFIG_DEBUG_LIST
60 static inline void __list_add(struct list_head
*new,
61 struct list_head
*prev
, struct list_head
*next
)
69 extern void __list_add(struct list_head
*new,
70 struct list_head
*prev
, struct list_head
*next
);
74 * list_add_tail - add a new entry
75 * @new: new entry to be added
76 * @head: list head to add it before
78 * Insert a new entry before the specified head.
79 * This is useful for implementing queues.
81 static inline void list_add_tail(struct list_head
*new, struct list_head
*head
)
83 __list_add(new, head
->prev
, head
);
87 * list_entry - get the struct for this entry
88 * @ptr: the &struct list_head pointer.
89 * @type: the type of the struct this is embedded in.
90 * @member: the name of the list_head within the struct.
92 #define list_entry(ptr, type, member) \
93 container_of(ptr, type, member)
96 * list_for_each_entry - iterate over list of given type
97 * @pos: the type * to use as a loop cursor.
98 * @head: the head for your list.
99 * @member: the name of the list_head within the struct.
101 #define list_for_each_entry(pos, head, member) \
102 for (pos = list_entry((head)->next, typeof(*pos), member); \
103 &pos->member != (head); \
104 pos = list_entry(pos->member.next, typeof(*pos), member))
107 struct list_head list
;
112 struct list_head offsets
;
119 static struct offset
*offset_new(unsigned o
)
121 struct offset
*offset
;
123 offset
= (struct offset
*)malloc(sizeof(struct offset
));
125 INIT_LIST_HEAD(&offset
->list
);
131 static void table_offset_add(struct table
*t
, struct offset
*offset
)
133 list_add_tail(&offset
->list
, &t
->offsets
);
136 static void table_init(struct table
*t
)
138 INIT_LIST_HEAD(&t
->offsets
);
144 static void table_print(struct table
*t
)
146 unsigned nlloop
, i
, j
, n
, c
, id
;
148 nlloop
= (t
->nentry
+ 3) / 4;
150 printf("static const unsigned %s_reg_safe_bm[%d] = {\n", t
->gpu_prefix
,
152 for (i
= 0, id
= 0; i
< nlloop
; i
++) {
157 for (j
= 0; j
< n
; j
++) {
162 printf("0x%08X,", t
->table
[id
++]);
169 static int table_build(struct table
*t
)
171 struct offset
*offset
;
174 t
->nentry
= ((t
->offset_max
>> 2) + 31) / 32;
175 t
->table
= (unsigned *)malloc(sizeof(unsigned) * t
->nentry
);
176 if (t
->table
== NULL
)
178 memset(t
->table
, 0xff, sizeof(unsigned) * t
->nentry
);
179 list_for_each_entry(offset
, &t
->offsets
, list
) {
180 i
= (offset
->offset
>> 2) / 32;
181 m
= (offset
->offset
>> 2) & 31;
188 static char gpu_name
[10];
189 static int parser_auth(struct table
*t
, const char *filename
)
200 struct offset
*offset
;
205 (&mask_rex
, "(0x[0-9a-fA-F]*) *([_a-zA-Z0-9]*)", REG_EXTENDED
)) {
206 fprintf(stderr
, "Failed to compile regular expression\n");
209 file
= fopen(filename
, "r");
211 fprintf(stderr
, "Failed to open: %s\n", filename
);
214 fseek(file
, 0, SEEK_END
);
216 fseek(file
, 0, SEEK_SET
);
219 if (fgets(buf
, 1024, file
) == NULL
) {
224 /* first line will contain the last register
226 sscanf(buf
, "%9s %9s", gpu_name
, last_reg_s
);
227 t
->gpu_prefix
= gpu_name
;
228 last_reg
= strtol(last_reg_s
, NULL
, 16);
231 if (fgets(buf
, 1024, file
) == NULL
) {
236 if (ftell(file
) == end
)
239 r
= regexec(&mask_rex
, buf
, 4, match
, 0);
240 if (r
== REG_NOMATCH
) {
243 "Error matching regular expression %d in %s\n",
248 buf
[match
[0].rm_eo
] = 0;
249 buf
[match
[1].rm_eo
] = 0;
250 buf
[match
[2].rm_eo
] = 0;
251 o
= strtol(&buf
[match
[1].rm_so
], NULL
, 16);
252 offset
= offset_new(o
);
253 table_offset_add(t
, offset
);
254 if (o
> t
->offset_max
)
260 if (t
->offset_max
< last_reg
)
261 t
->offset_max
= last_reg
;
262 return table_build(t
);
265 int main(int argc
, char *argv
[])
270 fprintf(stderr
, "Usage: %s <authfile>\n", argv
[0]);
274 if (parser_auth(&t
, argv
[1])) {
275 fprintf(stderr
, "Failed to parse file %s\n", argv
[1]);