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