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 */
49 pal - glue logic device containing assorted junk
55 Typical hardware dependant hack. This device allows the firmware
56 to gain access to all the things the firmware needs (but the OS
59 The pal contains the following registers. Except for the interrupt
60 level register, each of the below is 8 bytes in size and must be
61 accessed using correct alignment. For 16 and 32 bit accesses the
62 bytes not directed to the register are ignored:
64 |0 reset register (write)
65 |4 processor id register (read)
66 |8 interrupt port (write)
67 |9 interrupt level (write)
68 |12 processor count register (read)
69 |16 tty input fifo register (read)
70 |20 tty input status register (read)
71 |24 tty output fifo register (write)
72 |28 tty output status register (read)
74 Reset register (write) halts the simulator exiting with the
77 Processor id register (read) returns the processor number (0
78 .. N-1) of the processor performing the read.
80 The interrupt registers should be accessed as a pair (using a 16 or
81 32 bit store). The low byte specifies the interrupt port while the
82 high byte specifies the level to drive that port at. 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 to
89 Processor count register (read) returns the total number of
90 processors active in the current simulation.
92 TTY input fifo register (read), if the TTY input status register
93 indicates a character is available by being nonzero, returns the
94 next available character from the pal's tty input port.
96 Similarly, the TTY output fifo register (write), if the TTY output
97 status register indicates the output fifo is not full by being
98 nonzero, outputs the character written to the tty's output port.
104 reg = <address> <size> (required)
106 Specify the address (within the parent bus) that this device is to
114 hw_pal_reset_register
= 0x0,
115 hw_pal_cpu_nr_register
= 0x4,
116 hw_pal_int_register
= 0x8,
117 hw_pal_nr_cpu_register
= 0xa,
118 hw_pal_read_fifo
= 0x10,
119 hw_pal_read_status
= 0x14,
120 hw_pal_write_fifo
= 0x18,
121 hw_pal_write_status
= 0x1a,
122 hw_pal_address_mask
= 0x1f,
126 typedef struct _hw_pal_console_buffer
{
129 } hw_pal_console_buffer
;
131 typedef struct _hw_pal_device
{
132 hw_pal_console_buffer input
;
133 hw_pal_console_buffer output
;
138 /* check the console for an available character */
140 scan_hw_pal (struct hw
*me
)
143 hw_pal_struct hw
*hw_pal
= (hw_pal_struct hw
*) hw_data (me
);
147 count
= sim_io_read_stdin (hw_system (me
), &c
, sizeof(c
));
151 case sim_io_not_ready
:
153 hw_pal
->input
.buffer
= 0;
154 hw_pal
->input
.status
= 0;
157 hw_pal
->input
.buffer
= c
;
158 hw_pal
->input
.status
= 1;
163 /* write the character to the hw_pal */
165 write_hw_pal (struct hw
*me
,
168 hw_pal_device
*hw_pal
= (hw_pal_device
*) hw_data (me
);
169 sim_io_write_stdout (hw_system (me
), &val
, 1);
170 hw_pal
->output
.buffer
= val
;
171 hw_pal
->output
.status
= 1;
176 hw_pal_io_read_buffer (struct hw
*me
,
184 hw_pal_device
*hw_pal
= (hw_pal_device
*) hw_data (me
);
186 switch (addr
& hw_pal_address_mask
)
188 case hw_pal_cpu_nr_register
:
190 val
= CPU_INDEX (cpu
);
194 DTRACE (pal
, ("read - cpu-nr %d\n", val
));
196 case hw_pal_nr_cpu_register
:
197 val
= hw_tree_find_integer_property (me
, "/openprom/options/smp");
198 DTRACE (pal
, ("read - nr-cpu %d\n", val
));
200 case hw_pal_read_fifo
:
201 val
= hw_pal
->input
.buffer
;
202 DTRACE (pal
, ("read - input-fifo %d\n", val
));
204 case hw_pal_read_status
:
206 val
= hw_pal
->input
.status
;
207 DTRACE (pal
, ("read - input-status %d\n", val
));
209 case hw_pal_write_fifo
:
210 val
= hw_pal
->output
.buffer
;
211 DTRACE (pal
, ("read - output-fifo %d\n", val
));
213 case hw_pal_write_status
:
214 val
= hw_pal
->output
.status
;
215 DTRACE (pal
, ("read - output-status %d\n", val
));
219 DTRACE (pal
, ("read - ???\n"));
221 memset (dest
, 0, nr_bytes
);
222 *(unsigned_1
*)dest
= val
;
228 hw_pal_io_write_buffer (struct hw
*me
,
236 hw_pal_device
*hw_pal
= (hw_pal_device
*) hw_data (me
);
237 unsigned_1
*byte
= (unsigned_1
*) source
;
239 switch (addr
& hw_pal_address_mask
)
241 case hw_pal_reset_register
:
242 sim_engine_halt (NULL
, cpu
, NULL
, cia
, sim_exited
, byte
[0]);
244 case hw_pal_int_register
:
247 (nr_bytes
> 1 ? byte
[1] : 0), /* val */
250 case hw_pal_read_fifo
:
251 hw_pal
->input
.buffer
= byte
[0];
252 DTRACE (pal
, ("write - input-fifo %d\n", byte
[0]));
254 case hw_pal_read_status
:
255 hw_pal
->input
.status
= byte
[0];
256 DTRACE (pal
, ("write - input-status %d\n", byte
[0]));
258 case hw_pal_write_fifo
:
259 write_hw_pal (me
, byte
[0]);
260 DTRACE (pal
, ("write - output-fifo %d\n", byte
[0]));
262 case hw_pal_write_status
:
263 hw_pal
->output
.status
= byte
[0];
264 DTRACE (pal
, ("write - output-status %d\n", byte
[0]));
271 /* instances of the hw_pal struct hw */
275 hw_pal_instance_delete_callback(hw_instance
*instance
)
277 /* nothing to delete, the hw_pal is attached to the struct hw */
284 hw_pal_instance_read_callback (hw_instance
*instance
,
288 DITRACE (pal
, ("read - %s (%ld)", (const char*) buf
, (long int) len
));
289 return sim_io_read_stdin (buf
, len
);
295 hw_pal_instance_write_callback (hw_instance
*instance
,
300 const char *chp
= buf
;
301 hw_pal_device
*hw_pal
= hw_instance_data (instance
);
302 DITRACE (pal
, ("write - %s (%ld)", (const char*) buf
, (long int) len
));
303 for (i
= 0; i
< len
; i
++)
304 write_hw_pal (hw_pal
, chp
[i
]);
305 sim_io_flush_stdoutput ();
311 static const hw_instance_callbacks hw_pal_instance_callbacks
= {
312 hw_pal_instance_delete_callback
,
313 hw_pal_instance_read_callback
,
314 hw_pal_instance_write_callback
,
320 hw_pal_create_instance (struct hw
*me
,
324 return hw_create_instance_from (me
, NULL
,
327 &hw_pal_instance_callbacks
);
331 static const struct hw_port_descriptor hw_pal_ports
[] = {
332 { "int", 0, MAX_NR_PROCESSORS
},
338 hw_pal_attach_address (struct hw
*me
,
342 address_word nr_bytes
,
345 hw_pal_device
*pal
= (hw_pal_device
*) hw_data (me
);
351 static hw_callbacks
const hw_pal_callbacks
= {
352 { generic_hw_init_address
, },
353 { hw_pal_attach_address
, }, /* address */
354 { hw_pal_io_read_buffer_callback
,
355 hw_pal_io_write_buffer_callback
, },
357 { NULL
, NULL
, hw_pal_interrupt_ports
}, /* interrupt */
358 { generic_hw_unit_decode
,
359 generic_hw_unit_encode
,
360 generic_hw_address_to_attach_address
,
361 generic_hw_size_to_attach_size
},
362 hw_pal_create_instance
,
368 hw_pal_finish (struct hw
*hw
)
370 /* create the descriptor */
371 hw_pal_device
*hw_pal
= ZALLOC (hw_pal_device
);
372 hw_pal
->output
.status
= 1;
373 hw_pal
->output
.buffer
= '\0';
374 hw_pal
->input
.status
= 0;
375 hw_pal
->input
.buffer
= '\0';
376 set_hw_data (hw
, hw_pal
);
377 set_hw_attach_address (hw
, hw_pal_attach_address
);
378 set_hw_io_read_buffer (hw
, hw_pal_io_read_buffer
);
379 set_hw_io_write_buffer (hw
, hw_pal_io_write_buffer
);
380 set_hw_ports (hw
, hw_pal_ports
);
384 const struct hw_device_descriptor dv_pal_descriptor
[] = {
385 { "pal", hw_pal_finish
, },