1 /* The common simulator framework for GDB, the GNU Debugger.
3 Copyright 2002 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 2 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, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330,
22 Boston, MA 02111-1307, USA. */
28 /* NOTE: pal is naughty and grubs around looking at things outside of
29 its immediate domain */
50 pal - glue logic device containing assorted junk
56 Typical hardware dependant hack. This device allows the firmware
57 to gain access to all the things the firmware needs (but the OS
60 The pal contains the following registers:
62 |0 reset register (write, 8bit)
63 |4 processor id register (read, 8bit)
64 |8 interrupt register (8 - port, 9 - level) (write, 16bit)
65 |12 processor count register (read, 8bit)
67 |16 tty input fifo register (read, 8bit)
68 |20 tty input status register (read, 8bit)
69 |24 tty output fifo register (write, 8bit)
70 |28 tty output status register (read, 8bit)
72 |32 countdown register (read/write, 32bit, big-endian)
73 |36 countdown value register (read, 32bit, big-endian)
74 |40 timer register (read/write, 32bit, big-endian)
75 |44 timer value register (read, 32bit, big-endian)
77 RESET (write): halts the simulator. The value written to the
78 register is used as an exit status.
80 PROCESSOR ID (read): returns the processor identifier (0 .. N-1) of
81 the processor performing the read.
83 INTERRUPT (write): This register must be written using a two byte
84 store. The low byte specifies a port and the upper byte specifies
85 the a level. LEVEL is driven on the specified port. By
86 convention, the pal's interrupt ports (int0, int1, ...) are wired
87 up to the corresponding processor's level sensative external
88 interrupt pin. Eg: A two byte write to address 8 of 0x0102
89 (big-endian) will result in processor 2's external interrupt pin
92 PROCESSOR COUNT (read): returns the total number of processors
93 active in the current simulation.
95 TTY INPUT FIFO (read): if the TTY input status register indicates a
96 character is available by being nonzero, returns the next available
97 character from the pal's tty input port.
99 TTY OUTPUT FIFO (write): if the TTY output status register
100 indicates the output fifo is not full by being nonzero, outputs the
101 character written to the tty's output port.
103 COUNDOWN (read/write): The countdown registers provide a
104 non-repeating timed interrupt source. Writing a 32 bit big-endian
105 zero value to this register clears the countdown timer. Writing a
106 non-zero 32 bit big-endian value to this register sets the
107 countdown timer to expire in VALUE ticks (ticks is target
108 dependant). Reading the countdown register returns the last value
111 COUNTDOWN VALUE (read): Reading this 32 bit big-endian register
112 returns the number of ticks remaining until the countdown timer
115 TIMER (read/write): The timer registers provide a periodic timed
116 interrupt source. Writing a 32 bit big-endian zero value to this
117 register clears the periodic timer. Writing a 32 bit non-zero
118 value to this register sets the periodic timer to triger every
119 VALUE ticks (ticks is target dependant). Reading the timer
120 register returns the last value written.
122 TIMER VALUE (read): Reading this 32 bit big-endian register returns
123 the number of ticks until the next periodic interrupt.
129 reg = <address> <size> (required)
131 Specify the address (within the parent bus) that this device is to
136 If present and true, indicates that the device should poll its
143 int[0..NR_PROCESSORS] (output)
145 Driven as a result of a write to the interrupt-port /
146 interrupt-level register pair.
151 Driven whenever the countdown counter reaches zero.
156 Driven whenever the timer counter reaches zero.
162 At present the common simulator framework does not support input
169 hw_pal_reset_register
= 0x0,
170 hw_pal_cpu_nr_register
= 0x4,
171 hw_pal_int_register
= 0x8,
172 hw_pal_nr_cpu_register
= 0xa,
173 hw_pal_read_fifo
= 0x10,
174 hw_pal_read_status
= 0x14,
175 hw_pal_write_fifo
= 0x18,
176 hw_pal_write_status
= 0x1a,
177 hw_pal_countdown
= 0x20,
178 hw_pal_countdown_value
= 0x24,
180 hw_pal_timer_value
= 0x2c,
181 hw_pal_address_mask
= 0x3f,
185 typedef struct _hw_pal_console_buffer
{
188 } hw_pal_console_buffer
;
190 typedef struct _hw_pal_counter
{
191 struct hw_event
*handler
;
198 typedef struct _hw_pal_device
{
199 hw_pal_console_buffer input
;
200 hw_pal_console_buffer output
;
201 hw_pal_counter countdown
;
202 hw_pal_counter timer
;
204 do_hw_poll_read_method
*reader
;
213 static const struct hw_port_descriptor hw_pal_ports
[] = {
214 { "countdown", COUNTDOWN_PORT
, 0, output_port
, },
215 { "timer", TIMER_PORT
, 0, output_port
, },
216 { "int", INT_PORT
, MAX_NR_PROCESSORS
, output_port
, },
221 /* countdown and simple timer */
224 do_counter_event (struct hw
*me
,
227 hw_pal_counter
*counter
= (hw_pal_counter
*) data
;
228 if (counter
->periodic_p
)
230 HW_TRACE ((me
, "timer expired"));
231 counter
->start
= hw_event_queue_time (me
);
232 hw_port_event (me
, TIMER_PORT
, 1);
233 hw_event_queue_schedule (me
, counter
->delta
, do_counter_event
, counter
);
237 HW_TRACE ((me
, "countdown expired"));
239 hw_port_event (me
, COUNTDOWN_PORT
, 1);
244 do_counter_read (struct hw
*me
,
247 hw_pal_counter
*counter
,
253 hw_abort (me
, "%s - bad read size must be 4 bytes", reg
);
254 val
= counter
->delta
;
255 HW_TRACE ((me
, "read - %s %ld", reg
, (long) val
));
256 *word
= H2BE_4 (val
);
260 do_counter_value (struct hw
*me
,
263 hw_pal_counter
*counter
,
269 hw_abort (me
, "%s - bad read size must be 4 bytes", reg
);
270 if (counter
->delta
!= 0)
271 val
= (counter
->start
+ counter
->delta
272 - hw_event_queue_time (me
));
275 HW_TRACE ((me
, "read - %s %ld", reg
, (long) val
));
276 *word
= H2BE_4 (val
);
280 do_counter_write (struct hw
*me
,
283 hw_pal_counter
*counter
,
284 const unsigned32
*word
,
288 hw_abort (me
, "%s - bad write size must be 4 bytes", reg
);
289 if (counter
->handler
!= NULL
)
291 hw_event_queue_deschedule (me
, counter
->handler
);
292 counter
->handler
= NULL
;
294 counter
->delta
= BE2H_4 (*word
);
295 counter
->start
= hw_event_queue_time (me
);
296 HW_TRACE ((me
, "write - %s %ld", reg
, (long) counter
->delta
));
297 if (counter
->delta
> 0)
298 hw_event_queue_schedule (me
, counter
->delta
, do_counter_event
, counter
);
304 /* check the console for an available character */
306 scan_hw_pal (struct hw
*me
)
308 hw_pal_device
*hw_pal
= (hw_pal_device
*)hw_data (me
);
311 count
= do_hw_poll_read (me
, hw_pal
->reader
, 0/*STDIN*/, &c
, sizeof(c
));
314 case HW_IO_NOT_READY
:
316 hw_pal
->input
.buffer
= 0;
317 hw_pal
->input
.status
= 0;
320 hw_pal
->input
.buffer
= c
;
321 hw_pal
->input
.status
= 1;
325 /* write the character to the hw_pal */
328 write_hw_pal (struct hw
*me
,
331 hw_pal_device
*hw_pal
= (hw_pal_device
*) hw_data (me
);
332 sim_io_write_stdout (hw_system (me
), &val
, 1);
333 hw_pal
->output
.buffer
= val
;
334 hw_pal
->output
.status
= 1;
341 hw_pal_io_read_buffer (struct hw
*me
,
347 hw_pal_device
*hw_pal
= (hw_pal_device
*) hw_data (me
);
348 unsigned_1
*byte
= (unsigned_1
*) dest
;
349 memset (dest
, 0, nr_bytes
);
350 switch (addr
& hw_pal_address_mask
)
353 case hw_pal_cpu_nr_register
:
355 *byte
= CPU_INDEX (hw_system_cpu (me
));
359 HW_TRACE ((me
, "read - cpu-nr %d\n", *byte
));
362 case hw_pal_nr_cpu_register
:
363 if (hw_tree_find_property (me
, "/openprom/options/smp") == NULL
)
366 HW_TRACE ((me
, "read - nr-cpu %d (not defined)\n", *byte
));
370 *byte
= hw_tree_find_integer_property (me
, "/openprom/options/smp");
371 HW_TRACE ((me
, "read - nr-cpu %d\n", *byte
));
375 case hw_pal_read_fifo
:
376 *byte
= hw_pal
->input
.buffer
;
377 HW_TRACE ((me
, "read - input-fifo %d\n", *byte
));
380 case hw_pal_read_status
:
382 *byte
= hw_pal
->input
.status
;
383 HW_TRACE ((me
, "read - input-status %d\n", *byte
));
386 case hw_pal_write_fifo
:
387 *byte
= hw_pal
->output
.buffer
;
388 HW_TRACE ((me
, "read - output-fifo %d\n", *byte
));
391 case hw_pal_write_status
:
392 *byte
= hw_pal
->output
.status
;
393 HW_TRACE ((me
, "read - output-status %d\n", *byte
));
396 case hw_pal_countdown
:
397 do_counter_read (me
, hw_pal
, "countdown",
398 &hw_pal
->countdown
, dest
, nr_bytes
);
401 case hw_pal_countdown_value
:
402 do_counter_value (me
, hw_pal
, "countdown-value",
403 &hw_pal
->countdown
, dest
, nr_bytes
);
407 do_counter_read (me
, hw_pal
, "timer",
408 &hw_pal
->timer
, dest
, nr_bytes
);
411 case hw_pal_timer_value
:
412 do_counter_value (me
, hw_pal
, "timer-value",
413 &hw_pal
->timer
, dest
, nr_bytes
);
417 HW_TRACE ((me
, "read - ???\n"));
426 hw_pal_io_write_buffer (struct hw
*me
,
432 hw_pal_device
*hw_pal
= (hw_pal_device
*) hw_data (me
);
433 unsigned_1
*byte
= (unsigned_1
*) source
;
435 switch (addr
& hw_pal_address_mask
)
438 case hw_pal_reset_register
:
439 hw_halt (me
, sim_exited
, byte
[0]);
442 case hw_pal_int_register
:
444 INT_PORT
+ byte
[0], /*port*/
445 (nr_bytes
> 1 ? byte
[1] : 0)); /* val */
448 case hw_pal_read_fifo
:
449 hw_pal
->input
.buffer
= byte
[0];
450 HW_TRACE ((me
, "write - input-fifo %d\n", byte
[0]));
453 case hw_pal_read_status
:
454 hw_pal
->input
.status
= byte
[0];
455 HW_TRACE ((me
, "write - input-status %d\n", byte
[0]));
458 case hw_pal_write_fifo
:
459 write_hw_pal (me
, byte
[0]);
460 HW_TRACE ((me
, "write - output-fifo %d\n", byte
[0]));
463 case hw_pal_write_status
:
464 hw_pal
->output
.status
= byte
[0];
465 HW_TRACE ((me
, "write - output-status %d\n", byte
[0]));
468 case hw_pal_countdown
:
469 do_counter_write (me
, hw_pal
, "countdown",
470 &hw_pal
->countdown
, source
, nr_bytes
);
474 do_counter_write (me
, hw_pal
, "timer",
475 &hw_pal
->timer
, source
, nr_bytes
);
483 /* instances of the hw_pal struct hw */
487 hw_pal_instance_delete_callback(hw_instance
*instance
)
489 /* nothing to delete, the hw_pal is attached to the struct hw */
496 hw_pal_instance_read_callback (hw_instance
*instance
,
500 DITRACE (pal
, ("read - %s (%ld)", (const char*) buf
, (long int) len
));
501 return sim_io_read_stdin (buf
, len
);
507 hw_pal_instance_write_callback (hw_instance
*instance
,
512 const char *chp
= buf
;
513 hw_pal_device
*hw_pal
= hw_instance_data (instance
);
514 DITRACE (pal
, ("write - %s (%ld)", (const char*) buf
, (long int) len
));
515 for (i
= 0; i
< len
; i
++)
516 write_hw_pal (hw_pal
, chp
[i
]);
517 sim_io_flush_stdoutput ();
523 static const hw_instance_callbacks hw_pal_instance_callbacks
= {
524 hw_pal_instance_delete_callback
,
525 hw_pal_instance_read_callback
,
526 hw_pal_instance_write_callback
,
532 hw_pal_create_instance (struct hw
*me
,
536 return hw_create_instance_from (me
, NULL
,
539 &hw_pal_instance_callbacks
);
545 hw_pal_attach_address (struct hw
*me
,
549 address_word nr_bytes
,
552 hw_pal_device
*pal
= (hw_pal_device
*) hw_data (me
);
558 static hw_callbacks
const hw_pal_callbacks
= {
559 { generic_hw_init_address
, },
560 { hw_pal_attach_address
, }, /* address */
561 { hw_pal_io_read_buffer_callback
,
562 hw_pal_io_write_buffer_callback
, },
564 { NULL
, NULL
, hw_pal_interrupt_ports
}, /* interrupt */
565 { generic_hw_unit_decode
,
566 generic_hw_unit_encode
,
567 generic_hw_address_to_attach_address
,
568 generic_hw_size_to_attach_size
},
569 hw_pal_create_instance
,
575 hw_pal_finish (struct hw
*hw
)
577 /* create the descriptor */
578 hw_pal_device
*hw_pal
= HW_ZALLOC (hw
, hw_pal_device
);
579 hw_pal
->output
.status
= 1;
580 hw_pal
->output
.buffer
= '\0';
581 hw_pal
->input
.status
= 0;
582 hw_pal
->input
.buffer
= '\0';
583 set_hw_data (hw
, hw_pal
);
584 set_hw_attach_address (hw
, hw_pal_attach_address
);
585 set_hw_io_read_buffer (hw
, hw_pal_io_read_buffer
);
586 set_hw_io_write_buffer (hw
, hw_pal_io_write_buffer
);
587 set_hw_ports (hw
, hw_pal_ports
);
588 /* attach ourselves */
589 do_hw_attach_regs (hw
);
590 /* If so configured, enable polled input */
591 if (hw_find_property (hw
, "poll?") != NULL
592 && hw_find_boolean_property (hw
, "poll?"))
594 hw_pal
->reader
= sim_io_poll_read
;
598 hw_pal
->reader
= sim_io_read
;
600 /* tag the periodic timer */
601 hw_pal
->timer
.periodic_p
= 1;
605 const struct hw_descriptor dv_pal_descriptor
[] = {
606 { "pal", hw_pal_finish
, },