1 /* This file is part of the program psim.
3 Copyright (C) 1994-1996,1998, Andrew Cagney <cagney@highland.com.au>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 /* NOTE: pal is naughty and grubs around looking at things outside of
26 its immediate domain */
47 pal - glue logic device containing assorted junk
53 Typical hardware dependant hack. This device allows the firmware
54 to gain access to all the things the firmware needs (but the OS
57 The pal contains the following registers:
59 |0 reset register (write, 8bit)
60 |4 processor id register (read, 8bit)
61 |8 interrupt register (8 - port, 9 - level) (write, 16bit)
62 |12 processor count register (read, 8bit)
64 |16 tty input fifo register (read, 8bit)
65 |20 tty input status register (read, 8bit)
66 |24 tty output fifo register (write, 8bit)
67 |28 tty output status register (read, 8bit)
69 |32 countdown register (read/write, 32bit, big-endian)
70 |36 countdown value register (read, 32bit, big-endian)
71 |40 timer register (read/write, 32bit, big-endian)
72 |44 timer value register (read, 32bit, big-endian)
74 RESET (write): halts the simulator. The value written to the
75 register is used as an exit status.
77 PROCESSOR ID (read): returns the processor identifier (0 .. N-1) of
78 the processor performing the read.
80 INTERRUPT (write): This register must be written using a two byte
81 store. The low byte specifies a port and the upper byte specifies
82 the a level. LEVEL is driven on the specified port. By
83 convention, the pal's interrupt ports (int0, int1, ...) are wired
84 up to the corresponding processor's level sensative external
85 interrupt pin. Eg: A two byte write to address 8 of 0x0102
86 (big-endian) will result in processor 2's external interrupt pin
89 PROCESSOR COUNT (read): returns the total number of processors
90 active in the current simulation.
92 TTY INPUT FIFO (read): if the TTY input status register indicates a
93 character is available by being nonzero, returns the next available
94 character from the pal's tty input port.
96 TTY OUTPUT FIFO (write): if the TTY output status register
97 indicates the output fifo is not full by being nonzero, outputs the
98 character written to the tty's output port.
100 COUNDOWN (read/write): The countdown registers provide a
101 non-repeating timed interrupt source. Writing a 32 bit big-endian
102 zero value to this register clears the countdown timer. Writing a
103 non-zero 32 bit big-endian value to this register sets the
104 countdown timer to expire in VALUE ticks (ticks is target
105 dependant). Reading the countdown register returns the last value
108 COUNTDOWN VALUE (read): Reading this 32 bit big-endian register
109 returns the number of ticks remaining until the countdown timer
112 TIMER (read/write): The timer registers provide a periodic timed
113 interrupt source. Writing a 32 bit big-endian zero value to this
114 register clears the periodic timer. Writing a 32 bit non-zero
115 value to this register sets the periodic timer to triger every
116 VALUE ticks (ticks is target dependant). Reading the timer
117 register returns the last value written.
119 TIMER VALUE (read): Reading this 32 bit big-endian register returns
120 the number of ticks until the next periodic interrupt.
126 reg = <address> <size> (required)
128 Specify the address (within the parent bus) that this device is to
133 If present and true, indicates that the device should poll its
140 int[0..NR_PROCESSORS] (output)
142 Driven as a result of a write to the interrupt-port /
143 interrupt-level register pair.
148 Driven whenever the countdown counter reaches zero.
153 Driven whenever the timer counter reaches zero.
159 At present the common simulator framework does not support input
166 hw_pal_reset_register
= 0x0,
167 hw_pal_cpu_nr_register
= 0x4,
168 hw_pal_int_register
= 0x8,
169 hw_pal_nr_cpu_register
= 0xa,
170 hw_pal_read_fifo
= 0x10,
171 hw_pal_read_status
= 0x14,
172 hw_pal_write_fifo
= 0x18,
173 hw_pal_write_status
= 0x1a,
174 hw_pal_countdown
= 0x20,
175 hw_pal_countdown_value
= 0x24,
177 hw_pal_timer_value
= 0x2c,
178 hw_pal_address_mask
= 0x3f,
182 typedef struct _hw_pal_console_buffer
{
185 } hw_pal_console_buffer
;
187 typedef struct _hw_pal_counter
{
188 struct hw_event
*handler
;
195 typedef struct _hw_pal_device
{
196 hw_pal_console_buffer input
;
197 hw_pal_console_buffer output
;
198 hw_pal_counter countdown
;
199 hw_pal_counter timer
;
201 do_hw_poll_read_method
*reader
;
210 static const struct hw_port_descriptor hw_pal_ports
[] = {
211 { "countdown", COUNTDOWN_PORT
, 0, output_port
, },
212 { "timer", TIMER_PORT
, 0, output_port
, },
213 { "int", INT_PORT
, MAX_NR_PROCESSORS
, output_port
, },
218 /* countdown and simple timer */
221 do_counter_event (struct hw
*me
,
224 hw_pal_counter
*counter
= (hw_pal_counter
*) data
;
225 if (counter
->periodic_p
)
227 HW_TRACE ((me
, "timer expired"));
228 counter
->start
= hw_event_queue_time (me
);
229 hw_port_event (me
, TIMER_PORT
, 1);
230 hw_event_queue_schedule (me
, counter
->delta
, do_counter_event
, counter
);
234 HW_TRACE ((me
, "countdown expired"));
236 hw_port_event (me
, COUNTDOWN_PORT
, 1);
241 do_counter_read (struct hw
*me
,
244 hw_pal_counter
*counter
,
250 hw_abort (me
, "%s - bad read size must be 4 bytes", reg
);
251 val
= counter
->delta
;
252 HW_TRACE ((me
, "read - %s %ld", reg
, (long) val
));
253 *word
= H2BE_4 (val
);
257 do_counter_value (struct hw
*me
,
260 hw_pal_counter
*counter
,
266 hw_abort (me
, "%s - bad read size must be 4 bytes", reg
);
267 if (counter
->delta
!= 0)
268 val
= (counter
->start
+ counter
->delta
269 - hw_event_queue_time (me
));
272 HW_TRACE ((me
, "read - %s %ld", reg
, (long) val
));
273 *word
= H2BE_4 (val
);
277 do_counter_write (struct hw
*me
,
280 hw_pal_counter
*counter
,
281 const unsigned32
*word
,
285 hw_abort (me
, "%s - bad write size must be 4 bytes", reg
);
286 if (counter
->handler
!= NULL
)
288 hw_event_queue_deschedule (me
, counter
->handler
);
289 counter
->handler
= NULL
;
291 counter
->delta
= BE2H_4 (*word
);
292 counter
->start
= hw_event_queue_time (me
);
293 HW_TRACE ((me
, "write - %s %ld", reg
, (long) counter
->delta
));
294 if (counter
->delta
> 0)
295 hw_event_queue_schedule (me
, counter
->delta
, do_counter_event
, counter
);
301 /* check the console for an available character */
303 scan_hw_pal (struct hw
*me
)
305 hw_pal_device
*hw_pal
= (hw_pal_device
*)hw_data (me
);
308 count
= do_hw_poll_read (me
, hw_pal
->reader
, 0/*STDIN*/, &c
, sizeof(c
));
311 case HW_IO_NOT_READY
:
313 hw_pal
->input
.buffer
= 0;
314 hw_pal
->input
.status
= 0;
317 hw_pal
->input
.buffer
= c
;
318 hw_pal
->input
.status
= 1;
322 /* write the character to the hw_pal */
325 write_hw_pal (struct hw
*me
,
328 hw_pal_device
*hw_pal
= (hw_pal_device
*) hw_data (me
);
329 sim_io_write_stdout (hw_system (me
), &val
, 1);
330 hw_pal
->output
.buffer
= val
;
331 hw_pal
->output
.status
= 1;
338 hw_pal_io_read_buffer (struct hw
*me
,
344 hw_pal_device
*hw_pal
= (hw_pal_device
*) hw_data (me
);
345 unsigned_1
*byte
= (unsigned_1
*) dest
;
346 memset (dest
, 0, nr_bytes
);
347 switch (addr
& hw_pal_address_mask
)
350 case hw_pal_cpu_nr_register
:
352 *byte
= CPU_INDEX (hw_system_cpu (me
));
356 HW_TRACE ((me
, "read - cpu-nr %d\n", *byte
));
359 case hw_pal_nr_cpu_register
:
360 if (hw_tree_find_property (me
, "/openprom/options/smp") == NULL
)
363 HW_TRACE ((me
, "read - nr-cpu %d (not defined)\n", *byte
));
367 *byte
= hw_tree_find_integer_property (me
, "/openprom/options/smp");
368 HW_TRACE ((me
, "read - nr-cpu %d\n", *byte
));
372 case hw_pal_read_fifo
:
373 *byte
= hw_pal
->input
.buffer
;
374 HW_TRACE ((me
, "read - input-fifo %d\n", *byte
));
377 case hw_pal_read_status
:
379 *byte
= hw_pal
->input
.status
;
380 HW_TRACE ((me
, "read - input-status %d\n", *byte
));
383 case hw_pal_write_fifo
:
384 *byte
= hw_pal
->output
.buffer
;
385 HW_TRACE ((me
, "read - output-fifo %d\n", *byte
));
388 case hw_pal_write_status
:
389 *byte
= hw_pal
->output
.status
;
390 HW_TRACE ((me
, "read - output-status %d\n", *byte
));
393 case hw_pal_countdown
:
394 do_counter_read (me
, hw_pal
, "countdown",
395 &hw_pal
->countdown
, dest
, nr_bytes
);
398 case hw_pal_countdown_value
:
399 do_counter_value (me
, hw_pal
, "countdown-value",
400 &hw_pal
->countdown
, dest
, nr_bytes
);
404 do_counter_read (me
, hw_pal
, "timer",
405 &hw_pal
->timer
, dest
, nr_bytes
);
408 case hw_pal_timer_value
:
409 do_counter_value (me
, hw_pal
, "timer-value",
410 &hw_pal
->timer
, dest
, nr_bytes
);
414 HW_TRACE ((me
, "read - ???\n"));
423 hw_pal_io_write_buffer (struct hw
*me
,
429 hw_pal_device
*hw_pal
= (hw_pal_device
*) hw_data (me
);
430 unsigned_1
*byte
= (unsigned_1
*) source
;
432 switch (addr
& hw_pal_address_mask
)
435 case hw_pal_reset_register
:
436 hw_halt (me
, sim_exited
, byte
[0]);
439 case hw_pal_int_register
:
441 INT_PORT
+ byte
[0], /*port*/
442 (nr_bytes
> 1 ? byte
[1] : 0)); /* val */
445 case hw_pal_read_fifo
:
446 hw_pal
->input
.buffer
= byte
[0];
447 HW_TRACE ((me
, "write - input-fifo %d\n", byte
[0]));
450 case hw_pal_read_status
:
451 hw_pal
->input
.status
= byte
[0];
452 HW_TRACE ((me
, "write - input-status %d\n", byte
[0]));
455 case hw_pal_write_fifo
:
456 write_hw_pal (me
, byte
[0]);
457 HW_TRACE ((me
, "write - output-fifo %d\n", byte
[0]));
460 case hw_pal_write_status
:
461 hw_pal
->output
.status
= byte
[0];
462 HW_TRACE ((me
, "write - output-status %d\n", byte
[0]));
465 case hw_pal_countdown
:
466 do_counter_write (me
, hw_pal
, "countdown",
467 &hw_pal
->countdown
, source
, nr_bytes
);
471 do_counter_write (me
, hw_pal
, "timer",
472 &hw_pal
->timer
, source
, nr_bytes
);
480 /* instances of the hw_pal struct hw */
484 hw_pal_instance_delete_callback(hw_instance
*instance
)
486 /* nothing to delete, the hw_pal is attached to the struct hw */
493 hw_pal_instance_read_callback (hw_instance
*instance
,
497 DITRACE (pal
, ("read - %s (%ld)", (const char*) buf
, (long int) len
));
498 return sim_io_read_stdin (buf
, len
);
504 hw_pal_instance_write_callback (hw_instance
*instance
,
509 const char *chp
= buf
;
510 hw_pal_device
*hw_pal
= hw_instance_data (instance
);
511 DITRACE (pal
, ("write - %s (%ld)", (const char*) buf
, (long int) len
));
512 for (i
= 0; i
< len
; i
++)
513 write_hw_pal (hw_pal
, chp
[i
]);
514 sim_io_flush_stdoutput ();
520 static const hw_instance_callbacks hw_pal_instance_callbacks
= {
521 hw_pal_instance_delete_callback
,
522 hw_pal_instance_read_callback
,
523 hw_pal_instance_write_callback
,
529 hw_pal_create_instance (struct hw
*me
,
533 return hw_create_instance_from (me
, NULL
,
536 &hw_pal_instance_callbacks
);
542 hw_pal_attach_address (struct hw
*me
,
546 address_word nr_bytes
,
549 hw_pal_device
*pal
= (hw_pal_device
*) hw_data (me
);
555 static hw_callbacks
const hw_pal_callbacks
= {
556 { generic_hw_init_address
, },
557 { hw_pal_attach_address
, }, /* address */
558 { hw_pal_io_read_buffer_callback
,
559 hw_pal_io_write_buffer_callback
, },
561 { NULL
, NULL
, hw_pal_interrupt_ports
}, /* interrupt */
562 { generic_hw_unit_decode
,
563 generic_hw_unit_encode
,
564 generic_hw_address_to_attach_address
,
565 generic_hw_size_to_attach_size
},
566 hw_pal_create_instance
,
572 hw_pal_finish (struct hw
*hw
)
574 /* create the descriptor */
575 hw_pal_device
*hw_pal
= HW_ZALLOC (hw
, hw_pal_device
);
576 hw_pal
->output
.status
= 1;
577 hw_pal
->output
.buffer
= '\0';
578 hw_pal
->input
.status
= 0;
579 hw_pal
->input
.buffer
= '\0';
580 set_hw_data (hw
, hw_pal
);
581 set_hw_attach_address (hw
, hw_pal_attach_address
);
582 set_hw_io_read_buffer (hw
, hw_pal_io_read_buffer
);
583 set_hw_io_write_buffer (hw
, hw_pal_io_write_buffer
);
584 set_hw_ports (hw
, hw_pal_ports
);
585 /* attach ourselves */
586 do_hw_attach_regs (hw
);
587 /* If so configured, enable polled input */
588 if (hw_find_property (hw
, "poll?") != NULL
589 && hw_find_boolean_property (hw
, "poll?"))
591 hw_pal
->reader
= sim_io_poll_read
;
595 hw_pal
->reader
= sim_io_read
;
597 /* tag the periodic timer */
598 hw_pal
->timer
.periodic_p
= 1;
602 const struct hw_descriptor dv_pal_descriptor
[] = {
603 { "pal", hw_pal_finish
, },