Automatic Copyright Year update after running gdb/copyright.py
[deliverable/binutils-gdb.git] / sim / common / hw-base.c
1 /* The common simulator framework for GDB, the GNU Debugger.
2
3 Copyright 2002-2022 Free Software Foundation, Inc.
4
5 Contributed by Andrew Cagney and Red Hat.
6
7 This file is part of GDB.
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>. */
21
22 /* This must come before any other includes. */
23 #include "defs.h"
24
25 #include "hw-main.h"
26 #include "hw-base.h"
27
28 #include <string.h>
29 #include <stdlib.h>
30 #include <ctype.h>
31
32 #include "hw-config.h"
33
34 struct hw_base_data
35 {
36 int finished_p;
37 const struct hw_descriptor *descriptor;
38 hw_delete_callback *to_delete;
39 };
40
41 static int
42 generic_hw_unit_decode (struct hw *bus,
43 const char *unit,
44 hw_unit *phys)
45 {
46 memset (phys, 0, sizeof (*phys));
47 if (unit == NULL)
48 return 0;
49 else
50 {
51 int nr_cells = 0;
52 const int max_nr_cells = hw_unit_nr_address_cells (bus);
53 while (1)
54 {
55 char *end = NULL;
56 unsigned long val;
57 val = strtoul (unit, &end, 0);
58 /* parse error? */
59 if (unit == end)
60 return -1;
61 /* two many cells? */
62 if (nr_cells >= max_nr_cells)
63 return -1;
64 /* save it */
65 phys->cells[nr_cells] = val;
66 nr_cells++;
67 unit = end;
68 /* more to follow? */
69 if (isspace (*unit) || *unit == '\0')
70 break;
71 if (*unit != ',')
72 return -1;
73 unit++;
74 }
75 if (nr_cells < max_nr_cells)
76 {
77 /* shift everything to correct position */
78 int i;
79
80 for (i = 1; i <= nr_cells; i++)
81 phys->cells[max_nr_cells - i] = phys->cells[nr_cells - i];
82 for (i = 0; i < (max_nr_cells - nr_cells); i++)
83 phys->cells[i] = 0;
84 }
85 phys->nr_cells = max_nr_cells;
86 return max_nr_cells;
87 }
88 }
89
90 static int
91 generic_hw_unit_encode (struct hw *bus,
92 const hw_unit *phys,
93 char *buf,
94 int sizeof_buf)
95 {
96 int i;
97 int len;
98 char *pos = buf;
99 /* skip leading zero's */
100 for (i = 0; i < phys->nr_cells; i++)
101 {
102 if (phys->cells[i] != 0)
103 break;
104 }
105 /* don't output anything if empty */
106 if (phys->nr_cells == 0)
107 {
108 strcpy (pos, "");
109 len = 0;
110 }
111 else if (i == phys->nr_cells)
112 {
113 /* all zero */
114 strcpy (pos, "0");
115 len = 1;
116 }
117 else
118 {
119 for (; i < phys->nr_cells; i++)
120 {
121 if (pos != buf)
122 {
123 strcat (pos, ",");
124 pos = strchr (pos, '\0');
125 }
126 if (phys->cells[i] < 10)
127 sprintf (pos, "%ld", (unsigned long)phys->cells[i]);
128 else
129 sprintf (pos, "0x%lx", (unsigned long)phys->cells[i]);
130 pos = strchr (pos, '\0');
131 }
132 len = pos - buf;
133 }
134 if (len >= sizeof_buf)
135 hw_abort (NULL, "generic_unit_encode - buffer overflow\n");
136 return len;
137 }
138
139 static int
140 generic_hw_unit_address_to_attach_address (struct hw *me,
141 const hw_unit *address,
142 int *attach_space,
143 unsigned_word *attach_address,
144 struct hw *client)
145 {
146 int i;
147 for (i = 0; i < address->nr_cells - 2; i++)
148 {
149 if (address->cells[i] != 0)
150 hw_abort (me, "Only 32bit addresses supported");
151 }
152 if (address->nr_cells >= 2)
153 *attach_space = address->cells[address->nr_cells - 2];
154 else
155 *attach_space = 0;
156 *attach_address = address->cells[address->nr_cells - 1];
157 return 1;
158 }
159
160 static int
161 generic_hw_unit_size_to_attach_size (struct hw *me,
162 const hw_unit *size,
163 unsigned *nr_bytes,
164 struct hw *client)
165 {
166 int i;
167 for (i = 0; i < size->nr_cells - 1; i++)
168 {
169 if (size->cells[i] != 0)
170 hw_abort (me, "Only 32bit sizes supported");
171 }
172 *nr_bytes = size->cells[0];
173 return *nr_bytes;
174 }
175
176
177 /* ignore/passthrough versions of each function */
178
179 static void
180 passthrough_hw_attach_address (struct hw *me,
181 int level,
182 int space,
183 address_word addr,
184 address_word nr_bytes,
185 struct hw *client) /*callback/default*/
186 {
187 if (hw_parent (me) == NULL)
188 hw_abort (client, "hw_attach_address: no parent attach method");
189 hw_attach_address (hw_parent (me), level,
190 space, addr, nr_bytes,
191 client);
192 }
193
194 static void
195 passthrough_hw_detach_address (struct hw *me,
196 int level,
197 int space,
198 address_word addr,
199 address_word nr_bytes,
200 struct hw *client) /*callback/default*/
201 {
202 if (hw_parent (me) == NULL)
203 hw_abort (client, "hw_attach_address: no parent attach method");
204 hw_detach_address (hw_parent (me), level,
205 space, addr, nr_bytes,
206 client);
207 }
208
209 static unsigned
210 panic_hw_io_read_buffer (struct hw *me,
211 void *dest,
212 int space,
213 unsigned_word addr,
214 unsigned nr_bytes)
215 {
216 hw_abort (me, "no io-read method");
217 return 0;
218 }
219
220 static unsigned
221 panic_hw_io_write_buffer (struct hw *me,
222 const void *source,
223 int space,
224 unsigned_word addr,
225 unsigned nr_bytes)
226 {
227 hw_abort (me, "no io-write method");
228 return 0;
229 }
230
231 static unsigned
232 passthrough_hw_dma_read_buffer (struct hw *me,
233 void *dest,
234 int space,
235 unsigned_word addr,
236 unsigned nr_bytes)
237 {
238 if (hw_parent (me) == NULL)
239 hw_abort (me, "no parent dma-read method");
240 return hw_dma_read_buffer (hw_parent (me), dest,
241 space, addr, nr_bytes);
242 }
243
244 static unsigned
245 passthrough_hw_dma_write_buffer (struct hw *me,
246 const void *source,
247 int space,
248 unsigned_word addr,
249 unsigned nr_bytes,
250 int violate_read_only_section)
251 {
252 if (hw_parent (me) == NULL)
253 hw_abort (me, "no parent dma-write method");
254 return hw_dma_write_buffer (hw_parent (me), source,
255 space, addr,
256 nr_bytes,
257 violate_read_only_section);
258 }
259
260 static void
261 ignore_hw_delete (struct hw *me)
262 {
263 /* NOP */
264 }
265
266
267
268
269 static const char *
270 full_name_of_hw (struct hw *leaf,
271 char *buf,
272 unsigned sizeof_buf)
273 {
274 /* get a buffer */
275 if (buf == NULL)
276 {
277 sizeof_buf = 1024;
278 buf = hw_malloc (leaf, sizeof_buf);
279 }
280
281 /* use head recursion to construct the path */
282
283 if (hw_parent (leaf) == NULL)
284 /* root */
285 {
286 if (sizeof_buf < 1)
287 hw_abort (leaf, "buffer overflow");
288 *buf = '\0';
289 }
290 else
291 /* sub node */
292 {
293 char unit[1024];
294 full_name_of_hw (hw_parent (leaf), buf, sizeof_buf);
295 if (hw_unit_encode (hw_parent (leaf),
296 hw_unit_address (leaf),
297 unit + 1,
298 sizeof (unit) - 1)
299 > 0)
300 unit[0] = '@';
301 else
302 unit[0] = '\0';
303 if (strlen (buf) + strlen ("/") + strlen (hw_name (leaf)) + strlen (unit)
304 >= sizeof_buf)
305 hw_abort (leaf, "buffer overflow");
306 strcat (buf, "/");
307 strcat (buf, hw_name (leaf));
308 strcat (buf, unit);
309 }
310
311 return buf;
312 }
313
314 struct hw *
315 hw_create (struct sim_state *sd,
316 struct hw *parent,
317 const char *family,
318 const char *name,
319 const char *unit,
320 const char *args)
321 {
322 /* NOTE: HW must be allocated using ZALLOC, others use HW_ZALLOC */
323 struct hw *hw = ZALLOC (struct hw);
324
325 /* our identity */
326 hw->family_of_hw = hw_strdup (hw, family);
327 hw->name_of_hw = hw_strdup (hw, name);
328 hw->args_of_hw = hw_strdup (hw, args);
329
330 /* a hook into the system */
331 if (sd != NULL)
332 hw->system_of_hw = sd;
333 else if (parent != NULL)
334 hw->system_of_hw = hw_system (parent);
335 else
336 hw_abort (parent, "No system found");
337
338 /* in a tree */
339 if (parent != NULL)
340 {
341 struct hw **sibling = &parent->child_of_hw;
342 while ((*sibling) != NULL)
343 sibling = &(*sibling)->sibling_of_hw;
344 *sibling = hw;
345 hw->parent_of_hw = parent;
346 }
347
348 /* top of tree */
349 if (parent != NULL)
350 {
351 struct hw *root = parent;
352 while (root->parent_of_hw != NULL)
353 root = root->parent_of_hw;
354 hw->root_of_hw = root;
355 }
356
357 /* a unique identifier for the device on the parents bus */
358 if (parent != NULL)
359 {
360 hw_unit_decode (parent, unit, &hw->unit_address_of_hw);
361 }
362
363 /* Determine our path */
364 if (parent != NULL)
365 hw->path_of_hw = full_name_of_hw (hw, NULL, 0);
366 else
367 hw->path_of_hw = "/";
368
369 /* create our base type */
370 hw->base_of_hw = HW_ZALLOC (hw, struct hw_base_data);
371 hw->base_of_hw->finished_p = 0;
372
373 /* our callbacks */
374 set_hw_io_read_buffer (hw, panic_hw_io_read_buffer);
375 set_hw_io_write_buffer (hw, panic_hw_io_write_buffer);
376 set_hw_dma_read_buffer (hw, passthrough_hw_dma_read_buffer);
377 set_hw_dma_write_buffer (hw, passthrough_hw_dma_write_buffer);
378 set_hw_unit_decode (hw, generic_hw_unit_decode);
379 set_hw_unit_encode (hw, generic_hw_unit_encode);
380 set_hw_unit_address_to_attach_address (hw, generic_hw_unit_address_to_attach_address);
381 set_hw_unit_size_to_attach_size (hw, generic_hw_unit_size_to_attach_size);
382 set_hw_attach_address (hw, passthrough_hw_attach_address);
383 set_hw_detach_address (hw, passthrough_hw_detach_address);
384 set_hw_delete (hw, ignore_hw_delete);
385
386 /* locate a descriptor */
387 {
388 const struct hw_descriptor **table;
389 for (table = hw_descriptors;
390 *table != NULL;
391 table++)
392 {
393 const struct hw_descriptor *entry;
394 for (entry = *table;
395 entry->family != NULL;
396 entry++)
397 {
398 if (strcmp (family, entry->family) == 0)
399 {
400 hw->base_of_hw->descriptor = entry;
401 break;
402 }
403 }
404 }
405 if (hw->base_of_hw->descriptor == NULL)
406 {
407 hw_abort (parent, "Unknown device `%s'", family);
408 }
409 }
410
411 /* Attach dummy ports */
412 create_hw_alloc_data (hw);
413 create_hw_property_data (hw);
414 create_hw_port_data (hw);
415 create_hw_event_data (hw);
416 create_hw_handle_data (hw);
417 create_hw_instance_data (hw);
418
419 return hw;
420 }
421
422
423 int
424 hw_finished_p (struct hw *me)
425 {
426 return (me->base_of_hw->finished_p);
427 }
428
429 void
430 hw_finish (struct hw *me)
431 {
432 if (hw_finished_p (me))
433 hw_abort (me, "Attempt to finish finished device");
434
435 /* Fill in the (hopefully) defined address/size cells values */
436 if (hw_find_property (me, "#address-cells") != NULL)
437 me->nr_address_cells_of_hw_unit =
438 hw_find_integer_property (me, "#address-cells");
439 else
440 me->nr_address_cells_of_hw_unit = 2;
441 if (hw_find_property (me, "#size-cells") != NULL)
442 me->nr_size_cells_of_hw_unit =
443 hw_find_integer_property (me, "#size-cells");
444 else
445 me->nr_size_cells_of_hw_unit = 1;
446
447 /* Fill in the (hopefully) defined trace variable */
448 if (hw_find_property (me, "trace?") != NULL)
449 me->trace_of_hw_p = hw_find_boolean_property (me, "trace?");
450 /* allow global variable to define default tracing */
451 else if (! hw_trace_p (me)
452 && hw_find_property (hw_root (me), "global-trace?") != NULL
453 && hw_find_boolean_property (hw_root (me), "global-trace?"))
454 me->trace_of_hw_p = 1;
455
456
457 /* Allow the real device to override any methods */
458 me->base_of_hw->descriptor->to_finish (me);
459 me->base_of_hw->finished_p = 1;
460 }
461
462
463 void
464 hw_delete (struct hw *me)
465 {
466 /* give the object a chance to tidy up */
467 me->base_of_hw->to_delete (me);
468
469 delete_hw_instance_data (me);
470 delete_hw_handle_data (me);
471 delete_hw_event_data (me);
472 delete_hw_port_data (me);
473 delete_hw_property_data (me);
474
475 /* now unlink us from the tree */
476 if (hw_parent (me))
477 {
478 struct hw **sibling = &hw_parent (me)->child_of_hw;
479 while (*sibling != NULL)
480 {
481 if (*sibling == me)
482 {
483 *sibling = me->sibling_of_hw;
484 me->sibling_of_hw = NULL;
485 me->parent_of_hw = NULL;
486 break;
487 }
488 }
489 }
490
491 /* some sanity checks */
492 if (hw_child (me) != NULL)
493 {
494 hw_abort (me, "attempt to delete device with children");
495 }
496 if (hw_sibling (me) != NULL)
497 {
498 hw_abort (me, "attempt to delete device with siblings");
499 }
500
501 /* blow away all memory belonging to the device */
502 delete_hw_alloc_data (me);
503
504 /* finally */
505 free (me);
506 }
507
508 void
509 set_hw_delete (struct hw *hw, hw_delete_callback method)
510 {
511 hw->base_of_hw->to_delete = method;
512 }
513
514
515 /* Go through the devices various reg properties for those that
516 specify attach addresses */
517
518
519 void
520 do_hw_attach_regs (struct hw *hw)
521 {
522 static const char *(reg_property_names[]) = {
523 "attach-addresses",
524 "assigned-addresses",
525 "reg",
526 "alternate-reg" ,
527 NULL
528 };
529 const char **reg_property_name;
530 int nr_valid_reg_properties = 0;
531 for (reg_property_name = reg_property_names;
532 *reg_property_name != NULL;
533 reg_property_name++)
534 {
535 if (hw_find_property (hw, *reg_property_name) != NULL)
536 {
537 reg_property_spec reg;
538 int reg_entry;
539 for (reg_entry = 0;
540 hw_find_reg_array_property (hw, *reg_property_name, reg_entry,
541 &reg);
542 reg_entry++)
543 {
544 unsigned_word attach_address;
545 int attach_space;
546 unsigned attach_size;
547 if (!hw_unit_address_to_attach_address (hw_parent (hw),
548 &reg.address,
549 &attach_space,
550 &attach_address,
551 hw))
552 continue;
553 if (!hw_unit_size_to_attach_size (hw_parent (hw),
554 &reg.size,
555 &attach_size, hw))
556 continue;
557 hw_attach_address (hw_parent (hw),
558 0,
559 attach_space, attach_address, attach_size,
560 hw);
561 nr_valid_reg_properties++;
562 }
563 /* if first option matches don't try for any others */
564 if (reg_property_name == reg_property_names)
565 break;
566 }
567 }
568 }
This page took 0.046419 seconds and 4 git commands to generate.