1 /* The common simulator framework for GDB, the GNU Debugger.
3 Copyright 2002-2024 Free Software Foundation, Inc.
5 Contributed by Andrew Cagney and Red Hat.
7 This file is part of GDB.
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.
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.
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/>. */
22 /* This must come before any other includes. */
33 /* NOTE: pal is naughty and grubs around looking at things outside of
34 its immediate domain */
40 pal - glue logic device containing assorted junk
46 Typical hardware dependant hack. This device allows the firmware
47 to gain access to all the things the firmware needs (but the OS
50 The pal contains the following registers:
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)
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)
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)
67 RESET (write): halts the simulator. The value written to the
68 register is used as an exit status.
70 PROCESSOR ID (read): returns the processor identifier (0 .. N-1) of
71 the processor performing the read.
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
82 PROCESSOR COUNT (read): returns the total number of processors
83 active in the current simulation.
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.
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.
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
101 COUNTDOWN VALUE (read): Reading this 32 bit big-endian register
102 returns the number of ticks remaining until the countdown timer
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.
112 TIMER VALUE (read): Reading this 32 bit big-endian register returns
113 the number of ticks until the next periodic interrupt.
119 reg = <address> <size> (required)
121 Specify the address (within the parent bus) that this device is to
126 If present and true, indicates that the device should poll its
133 int[0..NR_PROCESSORS] (output)
135 Driven as a result of a write to the interrupt-port /
136 interrupt-level register pair.
141 Driven whenever the countdown counter reaches zero.
146 Driven whenever the timer counter reaches zero.
152 At present the common simulator framework does not support input
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,
170 hw_pal_timer_value
= 0x2c,
171 hw_pal_address_mask
= 0x3f,
175 typedef struct _hw_pal_console_buffer
{
178 } hw_pal_console_buffer
;
180 typedef struct _hw_pal_counter
{
181 struct hw_event
*handler
;
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
;
194 do_hw_poll_read_method
*reader
;
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
, },
211 /* countdown and simple timer */
214 do_counter_event (struct hw
*me
,
217 hw_pal_counter
*counter
= (hw_pal_counter
*) data
;
218 if (counter
->periodic_p
)
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
);
227 HW_TRACE ((me
, "countdown expired"));
229 hw_port_event (me
, COUNTDOWN_PORT
, 1);
234 do_counter_read (struct hw
*me
,
237 hw_pal_counter
*counter
,
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
);
250 do_counter_value (struct hw
*me
,
253 hw_pal_counter
*counter
,
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
));
265 HW_TRACE ((me
, "read - %s %ld", reg
, (long) val
));
266 *word
= H2BE_4 (val
);
270 do_counter_write (struct hw
*me
,
273 hw_pal_counter
*counter
,
274 const uint32_t *word
,
278 hw_abort (me
, "%s - bad write size must be 4 bytes", reg
);
279 if (counter
->handler
!= NULL
)
281 hw_event_queue_deschedule (me
, counter
->handler
);
282 counter
->handler
= NULL
;
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
);
294 /* check the console for an available character */
296 scan_hw_pal (struct hw
*me
)
298 hw_pal_device
*hw_pal
= (hw_pal_device
*)hw_data (me
);
301 count
= do_hw_poll_read (me
, hw_pal
->reader
, 0/*STDIN*/, &c
, sizeof (c
));
304 case HW_IO_NOT_READY
:
306 hw_pal
->input
.buffer
= 0;
307 hw_pal
->input
.status
= 0;
310 hw_pal
->input
.buffer
= c
;
311 hw_pal
->input
.status
= 1;
315 /* write the character to the hw_pal */
318 write_hw_pal (struct hw
*me
,
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;
331 hw_pal_io_read_buffer (struct hw
*me
,
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
)
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
));
348 case hw_pal_nr_cpu_register
:
349 if (hw_tree_find_property (me
, "/openprom/options/smp") == NULL
)
352 HW_TRACE ((me
, "read - nr-cpu %d (not defined)\n", *byte
));
356 *byte
= hw_tree_find_integer_property (me
, "/openprom/options/smp");
357 HW_TRACE ((me
, "read - nr-cpu %d\n", *byte
));
361 case hw_pal_read_fifo
:
362 *byte
= hw_pal
->input
.buffer
;
363 HW_TRACE ((me
, "read - input-fifo %d\n", *byte
));
366 case hw_pal_read_status
:
368 *byte
= hw_pal
->input
.status
;
369 HW_TRACE ((me
, "read - input-status %d\n", *byte
));
372 case hw_pal_write_fifo
:
373 *byte
= hw_pal
->output
.buffer
;
374 HW_TRACE ((me
, "read - output-fifo %d\n", *byte
));
377 case hw_pal_write_status
:
378 *byte
= hw_pal
->output
.status
;
379 HW_TRACE ((me
, "read - output-status %d\n", *byte
));
382 case hw_pal_countdown
:
383 do_counter_read (me
, hw_pal
, "countdown",
384 &hw_pal
->countdown
, dest
, nr_bytes
);
387 case hw_pal_countdown_value
:
388 do_counter_value (me
, hw_pal
, "countdown-value",
389 &hw_pal
->countdown
, dest
, nr_bytes
);
393 do_counter_read (me
, hw_pal
, "timer",
394 &hw_pal
->timer
, dest
, nr_bytes
);
397 case hw_pal_timer_value
:
398 do_counter_value (me
, hw_pal
, "timer-value",
399 &hw_pal
->timer
, dest
, nr_bytes
);
403 HW_TRACE ((me
, "read - ???\n"));
412 hw_pal_io_write_buffer (struct hw
*me
,
418 hw_pal_device
*hw_pal
= (hw_pal_device
*) hw_data (me
);
419 unsigned_1
*byte
= (unsigned_1
*) source
;
421 switch (addr
& hw_pal_address_mask
)
424 case hw_pal_reset_register
:
425 hw_halt (me
, sim_exited
, byte
[0]);
428 case hw_pal_int_register
:
430 INT_PORT
+ byte
[0], /*port*/
431 (nr_bytes
> 1 ? byte
[1] : 0)); /* val */
434 case hw_pal_read_fifo
:
435 hw_pal
->input
.buffer
= byte
[0];
436 HW_TRACE ((me
, "write - input-fifo %d\n", byte
[0]));
439 case hw_pal_read_status
:
440 hw_pal
->input
.status
= byte
[0];
441 HW_TRACE ((me
, "write - input-status %d\n", byte
[0]));
444 case hw_pal_write_fifo
:
445 write_hw_pal (me
, byte
[0]);
446 HW_TRACE ((me
, "write - output-fifo %d\n", byte
[0]));
449 case hw_pal_write_status
:
450 hw_pal
->output
.status
= byte
[0];
451 HW_TRACE ((me
, "write - output-status %d\n", byte
[0]));
454 case hw_pal_countdown
:
455 do_counter_write (me
, hw_pal
, "countdown",
456 &hw_pal
->countdown
, source
, nr_bytes
);
460 do_counter_write (me
, hw_pal
, "timer",
461 &hw_pal
->timer
, source
, nr_bytes
);
469 /* instances of the hw_pal struct hw */
473 hw_pal_instance_delete_callback (hw_instance
*instance
)
475 /* nothing to delete, the hw_pal is attached to the struct hw */
482 hw_pal_instance_read_callback (hw_instance
*instance
,
486 DITRACE (pal
, ("read - %s (%ld)", (const char*) buf
, (long int) len
));
487 return sim_io_read_stdin (buf
, len
);
493 hw_pal_instance_write_callback (hw_instance
*instance
,
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 ();
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
,
518 hw_pal_create_instance (struct hw
*me
,
522 return hw_create_instance_from (me
, NULL
,
525 &hw_pal_instance_callbacks
);
531 hw_pal_attach_address (struct hw
*me
,
535 address_word nr_bytes
,
538 hw_pal_device
*pal
= (hw_pal_device
*) hw_data (me
);
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
, },
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
,
561 hw_pal_finish (struct hw
*hw
)
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?"))
580 hw_pal
->reader
= sim_io_poll_read
;
584 hw_pal
->reader
= sim_io_read
;
586 /* tag the periodic timer */
587 hw_pal
->timer
.periodic_p
= 1;
591 const struct hw_descriptor dv_pal_descriptor
[] = {
592 { "pal", hw_pal_finish
, },