Update copyright year range in header of all files managed by GDB
[binutils-gdb.git] / sim / common / dv-pal.c
blob56692c1dcb84d16c163791898a9c2a437c4db7b6
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. */
23 #include "defs.h"
25 #include <stdlib.h>
26 #include <string.h>
27 #ifdef HAVE_UNISTD_H
28 #include <unistd.h>
29 #endif
31 #include "sim-main.h"
32 #include "hw-main.h"
33 #include "sim-io.h"
35 /* NOTE: pal is naughty and grubs around looking at things outside of
36 its immediate domain */
37 #include "hw-tree.h"
39 /* DEVICE
42 pal - glue logic device containing assorted junk
45 DESCRIPTION
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).
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
82 being asserted.
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
101 writen.
103 COUNTDOWN VALUE (read): Reading this 32 bit big-endian register
104 returns the number of ticks remaining until the countdown timer
105 expires.
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.
118 PROPERTIES
121 reg = <address> <size> (required)
123 Specify the address (within the parent bus) that this device is to
124 be located.
126 poll? = <boolean>
128 If present and true, indicates that the device should poll its
129 input.
132 PORTS
135 int[0..NR_PROCESSORS] (output)
137 Driven as a result of a write to the interrupt-port /
138 interrupt-level register pair.
141 countdown
143 Driven whenever the countdown counter reaches zero.
146 timer
148 Driven whenever the timer counter reaches zero.
151 BUGS
154 At present the common simulator framework does not support input
155 polling.
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,
177 typedef struct _hw_pal_console_buffer {
178 char buffer;
179 int status;
180 } hw_pal_console_buffer;
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;
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;
199 enum {
200 COUNTDOWN_PORT,
201 TIMER_PORT,
202 INT_PORT,
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 }
213 /* countdown and simple timer */
215 static void
216 do_counter_event (struct hw *me,
217 void *data)
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);
227 else
229 HW_TRACE ((me, "countdown expired"));
230 counter->delta = 0;
231 hw_port_event (me, COUNTDOWN_PORT, 1);
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)
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);
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)
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);
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)
279 if (nr_bytes != 4)
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 */
297 static void
298 scan_hw_pal (struct hw *me)
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)
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;
317 /* write the character to the hw_pal */
319 static void
320 write_hw_pal (struct hw *me,
321 char val)
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;
330 /* Reads/writes */
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)
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));
348 break;
350 case hw_pal_nr_cpu_register:
351 if (hw_tree_find_property (me, "/openprom/options/smp") == NULL)
353 *byte = 1;
354 HW_TRACE ((me, "read - nr-cpu %d (not defined)\n", *byte));
356 else
358 *byte = hw_tree_find_integer_property (me, "/openprom/options/smp");
359 HW_TRACE ((me, "read - nr-cpu %d\n", *byte));
361 break;
363 case hw_pal_read_fifo:
364 *byte = hw_pal->input.buffer;
365 HW_TRACE ((me, "read - input-fifo %d\n", *byte));
366 break;
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;
374 case hw_pal_write_fifo:
375 *byte = hw_pal->output.buffer;
376 HW_TRACE ((me, "read - output-fifo %d\n", *byte));
377 break;
379 case hw_pal_write_status:
380 *byte = hw_pal->output.status;
381 HW_TRACE ((me, "read - output-status %d\n", *byte));
382 break;
384 case hw_pal_countdown:
385 do_counter_read (me, hw_pal, "countdown",
386 &hw_pal->countdown, dest, nr_bytes);
387 break;
389 case hw_pal_countdown_value:
390 do_counter_value (me, hw_pal, "countdown-value",
391 &hw_pal->countdown, dest, nr_bytes);
392 break;
394 case hw_pal_timer:
395 do_counter_read (me, hw_pal, "timer",
396 &hw_pal->timer, dest, nr_bytes);
397 break;
399 case hw_pal_timer_value:
400 do_counter_value (me, hw_pal, "timer-value",
401 &hw_pal->timer, dest, nr_bytes);
402 break;
404 default:
405 HW_TRACE ((me, "read - ???\n"));
406 break;
409 return nr_bytes;
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)
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]);
428 break;
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;
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;
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;
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;
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;
456 case hw_pal_countdown:
457 do_counter_write (me, hw_pal, "countdown",
458 &hw_pal->countdown, source, nr_bytes);
459 break;
461 case hw_pal_timer:
462 do_counter_write (me, hw_pal, "timer",
463 &hw_pal->timer, source, nr_bytes);
464 break;
467 return nr_bytes;
471 /* instances of the hw_pal struct hw */
473 #if NOT_YET
474 static void
475 hw_pal_instance_delete_callback (hw_instance *instance)
477 /* nothing to delete, the hw_pal is attached to the struct hw */
478 return;
480 #endif
482 #if NOT_YET
483 static int
484 hw_pal_instance_read_callback (hw_instance *instance,
485 void *buf,
486 unsigned_word len)
488 DITRACE (pal, ("read - %s (%ld)", (const char*) buf, (long int) len));
489 return sim_io_read_stdin (buf, len);
491 #endif
493 #if NOT_YET
494 static int
495 hw_pal_instance_write_callback (hw_instance *instance,
496 const void *buf,
497 unsigned_word len)
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;
508 #endif
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,
516 #endif
518 #if 0
519 static hw_instance *
520 hw_pal_create_instance (struct hw *me,
521 const char *path,
522 const char *args)
524 return hw_create_instance_from (me, NULL,
525 hw_data (me),
526 path, args,
527 &hw_pal_instance_callbacks);
529 #endif
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)
540 hw_pal_device *pal = (hw_pal_device*) hw_data (me);
541 pal->disk = client;
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,
559 #endif
562 static void
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;
584 else
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, },
595 { NULL, NULL },