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