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