1 /* The common simulator framework for GDB, the GNU Debugger.
3 Copyright 2002-2015 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/>. */
26 /* NOTE: pal is naughty and grubs around looking at things outside of
27 its immediate domain */
48 pal - glue logic device containing assorted junk
54 Typical hardware dependant hack. This device allows the firmware
55 to gain access to all the things the firmware needs (but the OS
58 The pal contains the following registers:
60 |0 reset register (write, 8bit)
61 |4 processor id register (read, 8bit)
62 |8 interrupt register (8 - port, 9 - level) (write, 16bit)
63 |12 processor count register (read, 8bit)
65 |16 tty input fifo register (read, 8bit)
66 |20 tty input status register (read, 8bit)
67 |24 tty output fifo register (write, 8bit)
68 |28 tty output status register (read, 8bit)
70 |32 countdown register (read/write, 32bit, big-endian)
71 |36 countdown value register (read, 32bit, big-endian)
72 |40 timer register (read/write, 32bit, big-endian)
73 |44 timer value register (read, 32bit, big-endian)
75 RESET (write): halts the simulator. The value written to the
76 register is used as an exit status.
78 PROCESSOR ID (read): returns the processor identifier (0 .. N-1) of
79 the processor performing the read.
81 INTERRUPT (write): This register must be written using a two byte
82 store. The low byte specifies a port and the upper byte specifies
83 the a level. LEVEL is driven on the specified port. By
84 convention, the pal's interrupt ports (int0, int1, ...) are wired
85 up to the corresponding processor's level sensative external
86 interrupt pin. Eg: A two byte write to address 8 of 0x0102
87 (big-endian) will result in processor 2's external interrupt pin
90 PROCESSOR COUNT (read): returns the total number of processors
91 active in the current simulation.
93 TTY INPUT FIFO (read): if the TTY input status register indicates a
94 character is available by being nonzero, returns the next available
95 character from the pal's tty input port.
97 TTY OUTPUT FIFO (write): if the TTY output status register
98 indicates the output fifo is not full by being nonzero, outputs the
99 character written to the tty's output port.
101 COUNDOWN (read/write): The countdown registers provide a
102 non-repeating timed interrupt source. Writing a 32 bit big-endian
103 zero value to this register clears the countdown timer. Writing a
104 non-zero 32 bit big-endian value to this register sets the
105 countdown timer to expire in VALUE ticks (ticks is target
106 dependant). Reading the countdown register returns the last value
109 COUNTDOWN VALUE (read): Reading this 32 bit big-endian register
110 returns the number of ticks remaining until the countdown timer
113 TIMER (read/write): The timer registers provide a periodic timed
114 interrupt source. Writing a 32 bit big-endian zero value to this
115 register clears the periodic timer. Writing a 32 bit non-zero
116 value to this register sets the periodic timer to triger every
117 VALUE ticks (ticks is target dependant). Reading the timer
118 register returns the last value written.
120 TIMER VALUE (read): Reading this 32 bit big-endian register returns
121 the number of ticks until the next periodic interrupt.
127 reg = <address> <size> (required)
129 Specify the address (within the parent bus) that this device is to
134 If present and true, indicates that the device should poll its
141 int[0..NR_PROCESSORS] (output)
143 Driven as a result of a write to the interrupt-port /
144 interrupt-level register pair.
149 Driven whenever the countdown counter reaches zero.
154 Driven whenever the timer counter reaches zero.
160 At present the common simulator framework does not support input
167 hw_pal_reset_register = 0x0,
168 hw_pal_cpu_nr_register = 0x4,
169 hw_pal_int_register = 0x8,
170 hw_pal_nr_cpu_register = 0xa,
171 hw_pal_read_fifo = 0x10,
172 hw_pal_read_status = 0x14,
173 hw_pal_write_fifo = 0x18,
174 hw_pal_write_status = 0x1a,
175 hw_pal_countdown = 0x20,
176 hw_pal_countdown_value = 0x24,
178 hw_pal_timer_value = 0x2c,
179 hw_pal_address_mask = 0x3f,
183 typedef struct _hw_pal_console_buffer {
186 } hw_pal_console_buffer;
188 typedef struct _hw_pal_counter {
189 struct hw_event *handler;
196 typedef struct _hw_pal_device {
197 hw_pal_console_buffer input;
198 hw_pal_console_buffer output;
199 hw_pal_counter countdown;
200 hw_pal_counter timer;
202 do_hw_poll_read_method *reader;
211 static const struct hw_port_descriptor hw_pal_ports[] = {
212 { "countdown", COUNTDOWN_PORT, 0, output_port, },
213 { "timer", TIMER_PORT, 0, output_port, },
214 { "int", INT_PORT, MAX_NR_PROCESSORS, output_port, },
219 /* countdown and simple timer */
222 do_counter_event (struct hw *me,
225 hw_pal_counter *counter = (hw_pal_counter *) data;
226 if (counter->periodic_p)
228 HW_TRACE ((me, "timer expired"));
229 counter->start = hw_event_queue_time (me);
230 hw_port_event (me, TIMER_PORT, 1);
231 hw_event_queue_schedule (me, counter->delta, do_counter_event, counter);
235 HW_TRACE ((me, "countdown expired"));
237 hw_port_event (me, COUNTDOWN_PORT, 1);
242 do_counter_read (struct hw *me,
245 hw_pal_counter *counter,
251 hw_abort (me, "%s - bad read size must be 4 bytes", reg);
252 val = counter->delta;
253 HW_TRACE ((me, "read - %s %ld", reg, (long) val));
254 *word = H2BE_4 (val);
258 do_counter_value (struct hw *me,
261 hw_pal_counter *counter,
267 hw_abort (me, "%s - bad read size must be 4 bytes", reg);
268 if (counter->delta != 0)
269 val = (counter->start + counter->delta
270 - hw_event_queue_time (me));
273 HW_TRACE ((me, "read - %s %ld", reg, (long) val));
274 *word = H2BE_4 (val);
278 do_counter_write (struct hw *me,
281 hw_pal_counter *counter,
282 const unsigned32 *word,
286 hw_abort (me, "%s - bad write size must be 4 bytes", reg);
287 if (counter->handler != NULL)
289 hw_event_queue_deschedule (me, counter->handler);
290 counter->handler = NULL;
292 counter->delta = BE2H_4 (*word);
293 counter->start = hw_event_queue_time (me);
294 HW_TRACE ((me, "write - %s %ld", reg, (long) counter->delta));
295 if (counter->delta > 0)
296 hw_event_queue_schedule (me, counter->delta, do_counter_event, counter);
302 /* check the console for an available character */
304 scan_hw_pal (struct hw *me)
306 hw_pal_device *hw_pal = (hw_pal_device *)hw_data (me);
309 count = do_hw_poll_read (me, hw_pal->reader, 0/*STDIN*/, &c, sizeof (c));
312 case HW_IO_NOT_READY:
314 hw_pal->input.buffer = 0;
315 hw_pal->input.status = 0;
318 hw_pal->input.buffer = c;
319 hw_pal->input.status = 1;
323 /* write the character to the hw_pal */
326 write_hw_pal (struct hw *me,
329 hw_pal_device *hw_pal = (hw_pal_device *) hw_data (me);
330 sim_io_write_stdout (hw_system (me), &val, 1);
331 hw_pal->output.buffer = val;
332 hw_pal->output.status = 1;
339 hw_pal_io_read_buffer (struct hw *me,
345 hw_pal_device *hw_pal = (hw_pal_device *) hw_data (me);
346 unsigned_1 *byte = (unsigned_1 *) dest;
347 memset (dest, 0, nr_bytes);
348 switch (addr & hw_pal_address_mask)
351 case hw_pal_cpu_nr_register:
353 *byte = CPU_INDEX (hw_system_cpu (me));
357 HW_TRACE ((me, "read - cpu-nr %d\n", *byte));
360 case hw_pal_nr_cpu_register:
361 if (hw_tree_find_property (me, "/openprom/options/smp") == NULL)
364 HW_TRACE ((me, "read - nr-cpu %d (not defined)\n", *byte));
368 *byte = hw_tree_find_integer_property (me, "/openprom/options/smp");
369 HW_TRACE ((me, "read - nr-cpu %d\n", *byte));
373 case hw_pal_read_fifo:
374 *byte = hw_pal->input.buffer;
375 HW_TRACE ((me, "read - input-fifo %d\n", *byte));
378 case hw_pal_read_status:
380 *byte = hw_pal->input.status;
381 HW_TRACE ((me, "read - input-status %d\n", *byte));
384 case hw_pal_write_fifo:
385 *byte = hw_pal->output.buffer;
386 HW_TRACE ((me, "read - output-fifo %d\n", *byte));
389 case hw_pal_write_status:
390 *byte = hw_pal->output.status;
391 HW_TRACE ((me, "read - output-status %d\n", *byte));
394 case hw_pal_countdown:
395 do_counter_read (me, hw_pal, "countdown",
396 &hw_pal->countdown, dest, nr_bytes);
399 case hw_pal_countdown_value:
400 do_counter_value (me, hw_pal, "countdown-value",
401 &hw_pal->countdown, dest, nr_bytes);
405 do_counter_read (me, hw_pal, "timer",
406 &hw_pal->timer, dest, nr_bytes);
409 case hw_pal_timer_value:
410 do_counter_value (me, hw_pal, "timer-value",
411 &hw_pal->timer, dest, nr_bytes);
415 HW_TRACE ((me, "read - ???\n"));
424 hw_pal_io_write_buffer (struct hw *me,
430 hw_pal_device *hw_pal = (hw_pal_device*) hw_data (me);
431 unsigned_1 *byte = (unsigned_1 *) source;
433 switch (addr & hw_pal_address_mask)
436 case hw_pal_reset_register:
437 hw_halt (me, sim_exited, byte[0]);
440 case hw_pal_int_register:
442 INT_PORT + byte[0], /*port*/
443 (nr_bytes > 1 ? byte[1] : 0)); /* val */
446 case hw_pal_read_fifo:
447 hw_pal->input.buffer = byte[0];
448 HW_TRACE ((me, "write - input-fifo %d\n", byte[0]));
451 case hw_pal_read_status:
452 hw_pal->input.status = byte[0];
453 HW_TRACE ((me, "write - input-status %d\n", byte[0]));
456 case hw_pal_write_fifo:
457 write_hw_pal (me, byte[0]);
458 HW_TRACE ((me, "write - output-fifo %d\n", byte[0]));
461 case hw_pal_write_status:
462 hw_pal->output.status = byte[0];
463 HW_TRACE ((me, "write - output-status %d\n", byte[0]));
466 case hw_pal_countdown:
467 do_counter_write (me, hw_pal, "countdown",
468 &hw_pal->countdown, source, nr_bytes);
472 do_counter_write (me, hw_pal, "timer",
473 &hw_pal->timer, source, nr_bytes);
481 /* instances of the hw_pal struct hw */
485 hw_pal_instance_delete_callback (hw_instance *instance)
487 /* nothing to delete, the hw_pal is attached to the struct hw */
494 hw_pal_instance_read_callback (hw_instance *instance,
498 DITRACE (pal, ("read - %s (%ld)", (const char*) buf, (long int) len));
499 return sim_io_read_stdin (buf, len);
505 hw_pal_instance_write_callback (hw_instance *instance,
510 const char *chp = buf;
511 hw_pal_device *hw_pal = hw_instance_data (instance);
512 DITRACE (pal, ("write - %s (%ld)", (const char*) buf, (long int) len));
513 for (i = 0; i < len; i++)
514 write_hw_pal (hw_pal, chp[i]);
515 sim_io_flush_stdoutput ();
521 static const hw_instance_callbacks hw_pal_instance_callbacks = {
522 hw_pal_instance_delete_callback,
523 hw_pal_instance_read_callback,
524 hw_pal_instance_write_callback,
530 hw_pal_create_instance (struct hw *me,
534 return hw_create_instance_from (me, NULL,
537 &hw_pal_instance_callbacks);
543 hw_pal_attach_address (struct hw *me,
547 address_word nr_bytes,
550 hw_pal_device *pal = (hw_pal_device*) hw_data (me);
556 static hw_callbacks const hw_pal_callbacks = {
557 { generic_hw_init_address, },
558 { hw_pal_attach_address, }, /* address */
559 { hw_pal_io_read_buffer_callback,
560 hw_pal_io_write_buffer_callback, },
562 { NULL, NULL, hw_pal_interrupt_ports }, /* interrupt */
563 { generic_hw_unit_decode,
564 generic_hw_unit_encode,
565 generic_hw_address_to_attach_address,
566 generic_hw_size_to_attach_size },
567 hw_pal_create_instance,
573 hw_pal_finish (struct hw *hw)
575 /* create the descriptor */
576 hw_pal_device *hw_pal = HW_ZALLOC (hw, hw_pal_device);
577 hw_pal->output.status = 1;
578 hw_pal->output.buffer = '\0';
579 hw_pal->input.status = 0;
580 hw_pal->input.buffer = '\0';
581 set_hw_data (hw, hw_pal);
582 set_hw_attach_address (hw, hw_pal_attach_address);
583 set_hw_io_read_buffer (hw, hw_pal_io_read_buffer);
584 set_hw_io_write_buffer (hw, hw_pal_io_write_buffer);
585 set_hw_ports (hw, hw_pal_ports);
586 /* attach ourselves */
587 do_hw_attach_regs (hw);
588 /* If so configured, enable polled input */
589 if (hw_find_property (hw, "poll?") != NULL
590 && hw_find_boolean_property (hw, "poll?"))
592 hw_pal->reader = sim_io_poll_read;
596 hw_pal->reader = sim_io_read;
598 /* tag the periodic timer */
599 hw_pal->timer.periodic_p = 1;
603 const struct hw_descriptor dv_pal_descriptor[] = {
604 { "pal", hw_pal_finish, },