Automatic date update in version.in
[binutils-gdb.git] / sim / common / dv-pal.c
blobdd251ab221971b579361894982035d32663bc00e
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. */
23 #include "defs.h"
25 #include <stdlib.h>
26 #include <string.h>
27 #include <unistd.h>
29 #include "sim-main.h"
30 #include "hw-main.h"
31 #include "sim-io.h"
33 /* NOTE: pal is naughty and grubs around looking at things outside of
34 its immediate domain */
35 #include "hw-tree.h"
37 /* DEVICE
40 pal - glue logic device containing assorted junk
43 DESCRIPTION
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).
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
80 being asserted.
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
99 writen.
101 COUNTDOWN VALUE (read): Reading this 32 bit big-endian register
102 returns the number of ticks remaining until the countdown timer
103 expires.
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.
116 PROPERTIES
119 reg = <address> <size> (required)
121 Specify the address (within the parent bus) that this device is to
122 be located.
124 poll? = <boolean>
126 If present and true, indicates that the device should poll its
127 input.
130 PORTS
133 int[0..NR_PROCESSORS] (output)
135 Driven as a result of a write to the interrupt-port /
136 interrupt-level register pair.
139 countdown
141 Driven whenever the countdown counter reaches zero.
144 timer
146 Driven whenever the timer counter reaches zero.
149 BUGS
152 At present the common simulator framework does not support input
153 polling.
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,
175 typedef struct _hw_pal_console_buffer {
176 char buffer;
177 int status;
178 } hw_pal_console_buffer;
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;
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;
197 enum {
198 COUNTDOWN_PORT,
199 TIMER_PORT,
200 INT_PORT,
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 }
211 /* countdown and simple timer */
213 static void
214 do_counter_event (struct hw *me,
215 void *data)
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);
225 else
227 HW_TRACE ((me, "countdown expired"));
228 counter->delta = 0;
229 hw_port_event (me, COUNTDOWN_PORT, 1);
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)
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);
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)
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);
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)
277 if (nr_bytes != 4)
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 */
295 static void
296 scan_hw_pal (struct hw *me)
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)
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;
315 /* write the character to the hw_pal */
317 static void
318 write_hw_pal (struct hw *me,
319 char val)
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;
328 /* Reads/writes */
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)
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));
346 break;
348 case hw_pal_nr_cpu_register:
349 if (hw_tree_find_property (me, "/openprom/options/smp") == NULL)
351 *byte = 1;
352 HW_TRACE ((me, "read - nr-cpu %d (not defined)\n", *byte));
354 else
356 *byte = hw_tree_find_integer_property (me, "/openprom/options/smp");
357 HW_TRACE ((me, "read - nr-cpu %d\n", *byte));
359 break;
361 case hw_pal_read_fifo:
362 *byte = hw_pal->input.buffer;
363 HW_TRACE ((me, "read - input-fifo %d\n", *byte));
364 break;
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;
372 case hw_pal_write_fifo:
373 *byte = hw_pal->output.buffer;
374 HW_TRACE ((me, "read - output-fifo %d\n", *byte));
375 break;
377 case hw_pal_write_status:
378 *byte = hw_pal->output.status;
379 HW_TRACE ((me, "read - output-status %d\n", *byte));
380 break;
382 case hw_pal_countdown:
383 do_counter_read (me, hw_pal, "countdown",
384 &hw_pal->countdown, dest, nr_bytes);
385 break;
387 case hw_pal_countdown_value:
388 do_counter_value (me, hw_pal, "countdown-value",
389 &hw_pal->countdown, dest, nr_bytes);
390 break;
392 case hw_pal_timer:
393 do_counter_read (me, hw_pal, "timer",
394 &hw_pal->timer, dest, nr_bytes);
395 break;
397 case hw_pal_timer_value:
398 do_counter_value (me, hw_pal, "timer-value",
399 &hw_pal->timer, dest, nr_bytes);
400 break;
402 default:
403 HW_TRACE ((me, "read - ???\n"));
404 break;
407 return nr_bytes;
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)
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]);
426 break;
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;
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;
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;
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;
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;
454 case hw_pal_countdown:
455 do_counter_write (me, hw_pal, "countdown",
456 &hw_pal->countdown, source, nr_bytes);
457 break;
459 case hw_pal_timer:
460 do_counter_write (me, hw_pal, "timer",
461 &hw_pal->timer, source, nr_bytes);
462 break;
465 return nr_bytes;
469 /* instances of the hw_pal struct hw */
471 #if NOT_YET
472 static void
473 hw_pal_instance_delete_callback (hw_instance *instance)
475 /* nothing to delete, the hw_pal is attached to the struct hw */
476 return;
478 #endif
480 #if NOT_YET
481 static int
482 hw_pal_instance_read_callback (hw_instance *instance,
483 void *buf,
484 unsigned_word len)
486 DITRACE (pal, ("read - %s (%ld)", (const char*) buf, (long int) len));
487 return sim_io_read_stdin (buf, len);
489 #endif
491 #if NOT_YET
492 static int
493 hw_pal_instance_write_callback (hw_instance *instance,
494 const void *buf,
495 unsigned_word len)
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;
506 #endif
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,
514 #endif
516 #if 0
517 static hw_instance *
518 hw_pal_create_instance (struct hw *me,
519 const char *path,
520 const char *args)
522 return hw_create_instance_from (me, NULL,
523 hw_data (me),
524 path, args,
525 &hw_pal_instance_callbacks);
527 #endif
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)
538 hw_pal_device *pal = (hw_pal_device*) hw_data (me);
539 pal->disk = client;
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,
557 #endif
560 static void
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;
582 else
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, },
593 { NULL, NULL },