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 <stdlib.h> 26 #include <string.h> 27 #include <unistd.h> 28 29 #include "sim-main.h" 30 #include "hw-main.h" 31 #include "sim-io.h" 32 33 /* NOTE: pal is naughty and grubs around looking at things outside of 34 its immediate domain */ 35 #include "hw-tree.h" 36 37 /* DEVICE 38 39 40 pal - glue logic device containing assorted junk 41 42 43 DESCRIPTION 44 45 46 Typical hardware dependant hack. This device allows the firmware 47 to gain access to all the things the firmware needs (but the OS 48 doesn't). 49 50 The pal contains the following registers: 51 52 |0 reset register (write, 8bit) 53 |4 processor id register (read, 8bit) 54 |8 interrupt register (8 - port, 9 - level) (write, 16bit) 55 |12 processor count register (read, 8bit) 56 57 |16 tty input fifo register (read, 8bit) 58 |20 tty input status register (read, 8bit) 59 |24 tty output fifo register (write, 8bit) 60 |28 tty output status register (read, 8bit) 61 62 |32 countdown register (read/write, 32bit, big-endian) 63 |36 countdown value register (read, 32bit, big-endian) 64 |40 timer register (read/write, 32bit, big-endian) 65 |44 timer value register (read, 32bit, big-endian) 66 67 RESET (write): halts the simulator. The value written to the 68 register is used as an exit status. 69 70 PROCESSOR ID (read): returns the processor identifier (0 .. N-1) of 71 the processor performing the read. 72 73 INTERRUPT (write): This register must be written using a two byte 74 store. The low byte specifies a port and the upper byte specifies 75 the a level. LEVEL is driven on the specified port. By 76 convention, the pal's interrupt ports (int0, int1, ...) are wired 77 up to the corresponding processor's level sensative external 78 interrupt pin. Eg: A two byte write to address 8 of 0x0102 79 (big-endian) will result in processor 2's external interrupt pin 80 being asserted. 81 82 PROCESSOR COUNT (read): returns the total number of processors 83 active in the current simulation. 84 85 TTY INPUT FIFO (read): if the TTY input status register indicates a 86 character is available by being nonzero, returns the next available 87 character from the pal's tty input port. 88 89 TTY OUTPUT FIFO (write): if the TTY output status register 90 indicates the output fifo is not full by being nonzero, outputs the 91 character written to the tty's output port. 92 93 COUNDOWN (read/write): The countdown registers provide a 94 non-repeating timed interrupt source. Writing a 32 bit big-endian 95 zero value to this register clears the countdown timer. Writing a 96 non-zero 32 bit big-endian value to this register sets the 97 countdown timer to expire in VALUE ticks (ticks is target 98 dependant). Reading the countdown register returns the last value 99 writen. 100 101 COUNTDOWN VALUE (read): Reading this 32 bit big-endian register 102 returns the number of ticks remaining until the countdown timer 103 expires. 104 105 TIMER (read/write): The timer registers provide a periodic timed 106 interrupt source. Writing a 32 bit big-endian zero value to this 107 register clears the periodic timer. Writing a 32 bit non-zero 108 value to this register sets the periodic timer to triger every 109 VALUE ticks (ticks is target dependant). Reading the timer 110 register returns the last value written. 111 112 TIMER VALUE (read): Reading this 32 bit big-endian register returns 113 the number of ticks until the next periodic interrupt. 114 115 116 PROPERTIES 117 118 119 reg = <address> <size> (required) 120 121 Specify the address (within the parent bus) that this device is to 122 be located. 123 124 poll? = <boolean> 125 126 If present and true, indicates that the device should poll its 127 input. 128 129 130 PORTS 131 132 133 int[0..NR_PROCESSORS] (output) 134 135 Driven as a result of a write to the interrupt-port / 136 interrupt-level register pair. 137 138 139 countdown 140 141 Driven whenever the countdown counter reaches zero. 142 143 144 timer 145 146 Driven whenever the timer counter reaches zero. 147 148 149 BUGS 150 151 152 At present the common simulator framework does not support input 153 polling. 154 155 */ 156 157 158 enum { 159 hw_pal_reset_register = 0x0, 160 hw_pal_cpu_nr_register = 0x4, 161 hw_pal_int_register = 0x8, 162 hw_pal_nr_cpu_register = 0xa, 163 hw_pal_read_fifo = 0x10, 164 hw_pal_read_status = 0x14, 165 hw_pal_write_fifo = 0x18, 166 hw_pal_write_status = 0x1a, 167 hw_pal_countdown = 0x20, 168 hw_pal_countdown_value = 0x24, 169 hw_pal_timer = 0x28, 170 hw_pal_timer_value = 0x2c, 171 hw_pal_address_mask = 0x3f, 172 }; 173 174 175 typedef struct _hw_pal_console_buffer { 176 char buffer; 177 int status; 178 } hw_pal_console_buffer; 179 180 typedef struct _hw_pal_counter { 181 struct hw_event *handler; 182 int64_t start; 183 uint32_t delta; 184 int periodic_p; 185 } hw_pal_counter; 186 187 188 typedef struct _hw_pal_device { 189 hw_pal_console_buffer input; 190 hw_pal_console_buffer output; 191 hw_pal_counter countdown; 192 hw_pal_counter timer; 193 struct hw *disk; 194 do_hw_poll_read_method *reader; 195 } hw_pal_device; 196 197 enum { 198 COUNTDOWN_PORT, 199 TIMER_PORT, 200 INT_PORT, 201 }; 202 203 static const struct hw_port_descriptor hw_pal_ports[] = { 204 { "countdown", COUNTDOWN_PORT, 0, output_port, }, 205 { "timer", TIMER_PORT, 0, output_port, }, 206 { "int", INT_PORT, MAX_NR_PROCESSORS, output_port, }, 207 { NULL, 0, 0, 0 } 208 }; 209 210 211 /* countdown and simple timer */ 212 213 static void 214 do_counter_event (struct hw *me, 215 void *data) 216 { 217 hw_pal_counter *counter = (hw_pal_counter *) data; 218 if (counter->periodic_p) 219 { 220 HW_TRACE ((me, "timer expired")); 221 counter->start = hw_event_queue_time (me); 222 hw_port_event (me, TIMER_PORT, 1); 223 hw_event_queue_schedule (me, counter->delta, do_counter_event, counter); 224 } 225 else 226 { 227 HW_TRACE ((me, "countdown expired")); 228 counter->delta = 0; 229 hw_port_event (me, COUNTDOWN_PORT, 1); 230 } 231 } 232 233 static void 234 do_counter_read (struct hw *me, 235 hw_pal_device *pal, 236 const char *reg, 237 hw_pal_counter *counter, 238 uint32_t *word, 239 unsigned nr_bytes) 240 { 241 uint32_t val; 242 if (nr_bytes != 4) 243 hw_abort (me, "%s - bad read size must be 4 bytes", reg); 244 val = counter->delta; 245 HW_TRACE ((me, "read - %s %ld", reg, (long) val)); 246 *word = H2BE_4 (val); 247 } 248 249 static void 250 do_counter_value (struct hw *me, 251 hw_pal_device *pal, 252 const char *reg, 253 hw_pal_counter *counter, 254 uint32_t *word, 255 unsigned nr_bytes) 256 { 257 uint32_t val; 258 if (nr_bytes != 4) 259 hw_abort (me, "%s - bad read size must be 4 bytes", reg); 260 if (counter->delta != 0) 261 val = (counter->start + counter->delta 262 - hw_event_queue_time (me)); 263 else 264 val = 0; 265 HW_TRACE ((me, "read - %s %ld", reg, (long) val)); 266 *word = H2BE_4 (val); 267 } 268 269 static void 270 do_counter_write (struct hw *me, 271 hw_pal_device *pal, 272 const char *reg, 273 hw_pal_counter *counter, 274 const uint32_t *word, 275 unsigned nr_bytes) 276 { 277 if (nr_bytes != 4) 278 hw_abort (me, "%s - bad write size must be 4 bytes", reg); 279 if (counter->handler != NULL) 280 { 281 hw_event_queue_deschedule (me, counter->handler); 282 counter->handler = NULL; 283 } 284 counter->delta = BE2H_4 (*word); 285 counter->start = hw_event_queue_time (me); 286 HW_TRACE ((me, "write - %s %ld", reg, (long) counter->delta)); 287 if (counter->delta > 0) 288 hw_event_queue_schedule (me, counter->delta, do_counter_event, counter); 289 } 290 291 292 293 294 /* check the console for an available character */ 295 static void 296 scan_hw_pal (struct hw *me) 297 { 298 hw_pal_device *hw_pal = (hw_pal_device *)hw_data (me); 299 char c; 300 int count; 301 count = do_hw_poll_read (me, hw_pal->reader, 0/*STDIN*/, &c, sizeof (c)); 302 switch (count) 303 { 304 case HW_IO_NOT_READY: 305 case HW_IO_EOF: 306 hw_pal->input.buffer = 0; 307 hw_pal->input.status = 0; 308 break; 309 default: 310 hw_pal->input.buffer = c; 311 hw_pal->input.status = 1; 312 } 313 } 314 315 /* write the character to the hw_pal */ 316 317 static void 318 write_hw_pal (struct hw *me, 319 char val) 320 { 321 hw_pal_device *hw_pal = (hw_pal_device *) hw_data (me); 322 sim_io_write_stdout (hw_system (me), &val, 1); 323 hw_pal->output.buffer = val; 324 hw_pal->output.status = 1; 325 } 326 327 328 /* Reads/writes */ 329 330 static unsigned 331 hw_pal_io_read_buffer (struct hw *me, 332 void *dest, 333 int space, 334 unsigned_word addr, 335 unsigned nr_bytes) 336 { 337 hw_pal_device *hw_pal = (hw_pal_device *) hw_data (me); 338 unsigned_1 *byte = (unsigned_1 *) dest; 339 memset (dest, 0, nr_bytes); 340 switch (addr & hw_pal_address_mask) 341 { 342 343 case hw_pal_cpu_nr_register: 344 *byte = CPU_INDEX (hw_system_cpu (me)); 345 HW_TRACE ((me, "read - cpu-nr %d\n", *byte)); 346 break; 347 348 case hw_pal_nr_cpu_register: 349 if (hw_tree_find_property (me, "/openprom/options/smp") == NULL) 350 { 351 *byte = 1; 352 HW_TRACE ((me, "read - nr-cpu %d (not defined)\n", *byte)); 353 } 354 else 355 { 356 *byte = hw_tree_find_integer_property (me, "/openprom/options/smp"); 357 HW_TRACE ((me, "read - nr-cpu %d\n", *byte)); 358 } 359 break; 360 361 case hw_pal_read_fifo: 362 *byte = hw_pal->input.buffer; 363 HW_TRACE ((me, "read - input-fifo %d\n", *byte)); 364 break; 365 366 case hw_pal_read_status: 367 scan_hw_pal (me); 368 *byte = hw_pal->input.status; 369 HW_TRACE ((me, "read - input-status %d\n", *byte)); 370 break; 371 372 case hw_pal_write_fifo: 373 *byte = hw_pal->output.buffer; 374 HW_TRACE ((me, "read - output-fifo %d\n", *byte)); 375 break; 376 377 case hw_pal_write_status: 378 *byte = hw_pal->output.status; 379 HW_TRACE ((me, "read - output-status %d\n", *byte)); 380 break; 381 382 case hw_pal_countdown: 383 do_counter_read (me, hw_pal, "countdown", 384 &hw_pal->countdown, dest, nr_bytes); 385 break; 386 387 case hw_pal_countdown_value: 388 do_counter_value (me, hw_pal, "countdown-value", 389 &hw_pal->countdown, dest, nr_bytes); 390 break; 391 392 case hw_pal_timer: 393 do_counter_read (me, hw_pal, "timer", 394 &hw_pal->timer, dest, nr_bytes); 395 break; 396 397 case hw_pal_timer_value: 398 do_counter_value (me, hw_pal, "timer-value", 399 &hw_pal->timer, dest, nr_bytes); 400 break; 401 402 default: 403 HW_TRACE ((me, "read - ???\n")); 404 break; 405 406 } 407 return nr_bytes; 408 } 409 410 411 static unsigned 412 hw_pal_io_write_buffer (struct hw *me, 413 const void *source, 414 int space, 415 unsigned_word addr, 416 unsigned nr_bytes) 417 { 418 hw_pal_device *hw_pal = (hw_pal_device*) hw_data (me); 419 unsigned_1 *byte = (unsigned_1 *) source; 420 421 switch (addr & hw_pal_address_mask) 422 { 423 424 case hw_pal_reset_register: 425 hw_halt (me, sim_exited, byte[0]); 426 break; 427 428 case hw_pal_int_register: 429 hw_port_event (me, 430 INT_PORT + byte[0], /*port*/ 431 (nr_bytes > 1 ? byte[1] : 0)); /* val */ 432 break; 433 434 case hw_pal_read_fifo: 435 hw_pal->input.buffer = byte[0]; 436 HW_TRACE ((me, "write - input-fifo %d\n", byte[0])); 437 break; 438 439 case hw_pal_read_status: 440 hw_pal->input.status = byte[0]; 441 HW_TRACE ((me, "write - input-status %d\n", byte[0])); 442 break; 443 444 case hw_pal_write_fifo: 445 write_hw_pal (me, byte[0]); 446 HW_TRACE ((me, "write - output-fifo %d\n", byte[0])); 447 break; 448 449 case hw_pal_write_status: 450 hw_pal->output.status = byte[0]; 451 HW_TRACE ((me, "write - output-status %d\n", byte[0])); 452 break; 453 454 case hw_pal_countdown: 455 do_counter_write (me, hw_pal, "countdown", 456 &hw_pal->countdown, source, nr_bytes); 457 break; 458 459 case hw_pal_timer: 460 do_counter_write (me, hw_pal, "timer", 461 &hw_pal->timer, source, nr_bytes); 462 break; 463 464 } 465 return nr_bytes; 466 } 467 468 469 /* instances of the hw_pal struct hw */ 470 471 #if NOT_YET 472 static void 473 hw_pal_instance_delete_callback (hw_instance *instance) 474 { 475 /* nothing to delete, the hw_pal is attached to the struct hw */ 476 return; 477 } 478 #endif 479 480 #if NOT_YET 481 static int 482 hw_pal_instance_read_callback (hw_instance *instance, 483 void *buf, 484 unsigned_word len) 485 { 486 DITRACE (pal, ("read - %s (%ld)", (const char*) buf, (long int) len)); 487 return sim_io_read_stdin (buf, len); 488 } 489 #endif 490 491 #if NOT_YET 492 static int 493 hw_pal_instance_write_callback (hw_instance *instance, 494 const void *buf, 495 unsigned_word len) 496 { 497 int i; 498 const char *chp = buf; 499 hw_pal_device *hw_pal = hw_instance_data (instance); 500 DITRACE (pal, ("write - %s (%ld)", (const char*) buf, (long int) len)); 501 for (i = 0; i < len; i++) 502 write_hw_pal (hw_pal, chp[i]); 503 sim_io_flush_stdoutput (); 504 return i; 505 } 506 #endif 507 508 #if NOT_YET 509 static const hw_instance_callbacks hw_pal_instance_callbacks = { 510 hw_pal_instance_delete_callback, 511 hw_pal_instance_read_callback, 512 hw_pal_instance_write_callback, 513 }; 514 #endif 515 516 #if 0 517 static hw_instance * 518 hw_pal_create_instance (struct hw *me, 519 const char *path, 520 const char *args) 521 { 522 return hw_create_instance_from (me, NULL, 523 hw_data (me), 524 path, args, 525 &hw_pal_instance_callbacks); 526 } 527 #endif 528 529 530 static void 531 hw_pal_attach_address (struct hw *me, 532 int level, 533 int space, 534 address_word addr, 535 address_word nr_bytes, 536 struct hw *client) 537 { 538 hw_pal_device *pal = (hw_pal_device*) hw_data (me); 539 pal->disk = client; 540 } 541 542 543 #if 0 544 static hw_callbacks const hw_pal_callbacks = { 545 { generic_hw_init_address, }, 546 { hw_pal_attach_address, }, /* address */ 547 { hw_pal_io_read_buffer_callback, 548 hw_pal_io_write_buffer_callback, }, 549 { NULL, }, /* DMA */ 550 { NULL, NULL, hw_pal_interrupt_ports }, /* interrupt */ 551 { generic_hw_unit_decode, 552 generic_hw_unit_encode, 553 generic_hw_address_to_attach_address, 554 generic_hw_size_to_attach_size }, 555 hw_pal_create_instance, 556 }; 557 #endif 558 559 560 static void 561 hw_pal_finish (struct hw *hw) 562 { 563 /* create the descriptor */ 564 hw_pal_device *hw_pal = HW_ZALLOC (hw, hw_pal_device); 565 hw_pal->output.status = 1; 566 hw_pal->output.buffer = '\0'; 567 hw_pal->input.status = 0; 568 hw_pal->input.buffer = '\0'; 569 set_hw_data (hw, hw_pal); 570 set_hw_attach_address (hw, hw_pal_attach_address); 571 set_hw_io_read_buffer (hw, hw_pal_io_read_buffer); 572 set_hw_io_write_buffer (hw, hw_pal_io_write_buffer); 573 set_hw_ports (hw, hw_pal_ports); 574 /* attach ourselves */ 575 do_hw_attach_regs (hw); 576 /* If so configured, enable polled input */ 577 if (hw_find_property (hw, "poll?") != NULL 578 && hw_find_boolean_property (hw, "poll?")) 579 { 580 hw_pal->reader = sim_io_poll_read; 581 } 582 else 583 { 584 hw_pal->reader = sim_io_read; 585 } 586 /* tag the periodic timer */ 587 hw_pal->timer.periodic_p = 1; 588 } 589 590 591 const struct hw_descriptor dv_pal_descriptor[] = { 592 { "pal", hw_pal_finish, }, 593 { NULL, NULL }, 594 }; 595