1 /* The common simulator framework for GDB, the GNU Debugger.
3 Copyright 2002-2023 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. */
35 /* NOTE: pal is naughty and grubs around looking at things outside of
36 its immediate domain */
42 pal - glue logic device containing assorted junk
48 Typical hardware dependant hack. This device allows the firmware
49 to gain access to all the things the firmware needs (but the OS
52 The pal contains the following registers:
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)
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)
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)
69 RESET (write): halts the simulator. The value written to the
70 register is used as an exit status.
72 PROCESSOR ID (read): returns the processor identifier (0 .. N-1) of
73 the processor performing the read.
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
84 PROCESSOR COUNT (read): returns the total number of processors
85 active in the current simulation.
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.
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.
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
103 COUNTDOWN VALUE (read): Reading this 32 bit big-endian register
104 returns the number of ticks remaining until the countdown timer
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.
114 TIMER VALUE (read): Reading this 32 bit big-endian register returns
115 the number of ticks until the next periodic interrupt.
121 reg = <address> <size> (required)
123 Specify the address (within the parent bus) that this device is to
128 If present and true, indicates that the device should poll its
135 int[0..NR_PROCESSORS] (output)
137 Driven as a result of a write to the interrupt-port /
138 interrupt-level register pair.
143 Driven whenever the countdown counter reaches zero.
148 Driven whenever the timer counter reaches zero.
154 At present the common simulator framework does not support input
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,
172 hw_pal_timer_value
= 0x2c,
173 hw_pal_address_mask
= 0x3f,
177 typedef struct _hw_pal_console_buffer
{
180 } hw_pal_console_buffer
;
182 typedef struct _hw_pal_counter
{
183 struct hw_event
*handler
;
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
;
196 do_hw_poll_read_method
*reader
;
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
, },
213 /* countdown and simple timer */
216 do_counter_event (struct hw
*me
,
219 hw_pal_counter
*counter
= (hw_pal_counter
*) data
;
220 if (counter
->periodic_p
)
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
);
229 HW_TRACE ((me
, "countdown expired"));
231 hw_port_event (me
, COUNTDOWN_PORT
, 1);
236 do_counter_read (struct hw
*me
,
239 hw_pal_counter
*counter
,
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
);
252 do_counter_value (struct hw
*me
,
255 hw_pal_counter
*counter
,
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
));
267 HW_TRACE ((me
, "read - %s %ld", reg
, (long) val
));
268 *word
= H2BE_4 (val
);
272 do_counter_write (struct hw
*me
,
275 hw_pal_counter
*counter
,
276 const uint32_t *word
,
280 hw_abort (me
, "%s - bad write size must be 4 bytes", reg
);
281 if (counter
->handler
!= NULL
)
283 hw_event_queue_deschedule (me
, counter
->handler
);
284 counter
->handler
= NULL
;
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
);
296 /* check the console for an available character */
298 scan_hw_pal (struct hw
*me
)
300 hw_pal_device
*hw_pal
= (hw_pal_device
*)hw_data (me
);
303 count
= do_hw_poll_read (me
, hw_pal
->reader
, 0/*STDIN*/, &c
, sizeof (c
));
306 case HW_IO_NOT_READY
:
308 hw_pal
->input
.buffer
= 0;
309 hw_pal
->input
.status
= 0;
312 hw_pal
->input
.buffer
= c
;
313 hw_pal
->input
.status
= 1;
317 /* write the character to the hw_pal */
320 write_hw_pal (struct hw
*me
,
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;
333 hw_pal_io_read_buffer (struct hw
*me
,
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
)
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
));
350 case hw_pal_nr_cpu_register
:
351 if (hw_tree_find_property (me
, "/openprom/options/smp") == NULL
)
354 HW_TRACE ((me
, "read - nr-cpu %d (not defined)\n", *byte
));
358 *byte
= hw_tree_find_integer_property (me
, "/openprom/options/smp");
359 HW_TRACE ((me
, "read - nr-cpu %d\n", *byte
));
363 case hw_pal_read_fifo
:
364 *byte
= hw_pal
->input
.buffer
;
365 HW_TRACE ((me
, "read - input-fifo %d\n", *byte
));
368 case hw_pal_read_status
:
370 *byte
= hw_pal
->input
.status
;
371 HW_TRACE ((me
, "read - input-status %d\n", *byte
));
374 case hw_pal_write_fifo
:
375 *byte
= hw_pal
->output
.buffer
;
376 HW_TRACE ((me
, "read - output-fifo %d\n", *byte
));
379 case hw_pal_write_status
:
380 *byte
= hw_pal
->output
.status
;
381 HW_TRACE ((me
, "read - output-status %d\n", *byte
));
384 case hw_pal_countdown
:
385 do_counter_read (me
, hw_pal
, "countdown",
386 &hw_pal
->countdown
, dest
, nr_bytes
);
389 case hw_pal_countdown_value
:
390 do_counter_value (me
, hw_pal
, "countdown-value",
391 &hw_pal
->countdown
, dest
, nr_bytes
);
395 do_counter_read (me
, hw_pal
, "timer",
396 &hw_pal
->timer
, dest
, nr_bytes
);
399 case hw_pal_timer_value
:
400 do_counter_value (me
, hw_pal
, "timer-value",
401 &hw_pal
->timer
, dest
, nr_bytes
);
405 HW_TRACE ((me
, "read - ???\n"));
414 hw_pal_io_write_buffer (struct hw
*me
,
420 hw_pal_device
*hw_pal
= (hw_pal_device
*) hw_data (me
);
421 unsigned_1
*byte
= (unsigned_1
*) source
;
423 switch (addr
& hw_pal_address_mask
)
426 case hw_pal_reset_register
:
427 hw_halt (me
, sim_exited
, byte
[0]);
430 case hw_pal_int_register
:
432 INT_PORT
+ byte
[0], /*port*/
433 (nr_bytes
> 1 ? byte
[1] : 0)); /* val */
436 case hw_pal_read_fifo
:
437 hw_pal
->input
.buffer
= byte
[0];
438 HW_TRACE ((me
, "write - input-fifo %d\n", byte
[0]));
441 case hw_pal_read_status
:
442 hw_pal
->input
.status
= byte
[0];
443 HW_TRACE ((me
, "write - input-status %d\n", byte
[0]));
446 case hw_pal_write_fifo
:
447 write_hw_pal (me
, byte
[0]);
448 HW_TRACE ((me
, "write - output-fifo %d\n", byte
[0]));
451 case hw_pal_write_status
:
452 hw_pal
->output
.status
= byte
[0];
453 HW_TRACE ((me
, "write - output-status %d\n", byte
[0]));
456 case hw_pal_countdown
:
457 do_counter_write (me
, hw_pal
, "countdown",
458 &hw_pal
->countdown
, source
, nr_bytes
);
462 do_counter_write (me
, hw_pal
, "timer",
463 &hw_pal
->timer
, source
, nr_bytes
);
471 /* instances of the hw_pal struct hw */
475 hw_pal_instance_delete_callback (hw_instance
*instance
)
477 /* nothing to delete, the hw_pal is attached to the struct hw */
484 hw_pal_instance_read_callback (hw_instance
*instance
,
488 DITRACE (pal
, ("read - %s (%ld)", (const char*) buf
, (long int) len
));
489 return sim_io_read_stdin (buf
, len
);
495 hw_pal_instance_write_callback (hw_instance
*instance
,
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 ();
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
,
520 hw_pal_create_instance (struct hw
*me
,
524 return hw_create_instance_from (me
, NULL
,
527 &hw_pal_instance_callbacks
);
533 hw_pal_attach_address (struct hw
*me
,
537 address_word nr_bytes
,
540 hw_pal_device
*pal
= (hw_pal_device
*) hw_data (me
);
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
, },
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
,
563 hw_pal_finish (struct hw
*hw
)
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?"))
582 hw_pal
->reader
= sim_io_poll_read
;
586 hw_pal
->reader
= sim_io_read
;
588 /* tag the periodic timer */
589 hw_pal
->timer
.periodic_p
= 1;
593 const struct hw_descriptor dv_pal_descriptor
[] = {
594 { "pal", hw_pal_finish
, },