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