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. Except for the interrupt
58 level register, each of the below is 8 bytes in size and must be
59 accessed using correct alignment. For 16 and 32 bit accesses the
60 bytes not directed to the register are ignored:
62 |0 reset register (write)
63 |4 processor id register (read)
64 |8 interrupt port (write)
65 |9 interrupt level (write)
66 |12 processor count register (read)
67 |16 tty input fifo register (read)
68 |20 tty input status register (read)
69 |24 tty output fifo register (write)
70 |28 tty output status register (read)
72 Reset register (write) halts the simulator exiting with the
75 Processor id register (read) returns the processor number (0
76 .. N-1) of the processor performing the read.
78 The interrupt registers should be accessed as a pair (using a 16 or
79 32 bit store). The low byte specifies the interrupt port while the
80 high byte specifies the level to drive that port at. By
81 convention, the pal's interrupt ports (int0, int1, ...) are wired
82 up to the corresponding processor's level sensative external
83 interrupt pin. Eg: A two byte write to address 8 of 0x0102
84 (big-endian) will result in processor 2's external interrupt pin to
87 Processor count register (read) returns the total number of
88 processors active in the current simulation.
90 TTY input fifo register (read), if the TTY input status register
91 indicates a character is available by being nonzero, returns the
92 next available character from the pal's tty input port.
94 Similarly, the TTY output fifo register (write), if the TTY output
95 status register indicates the output fifo is not full by being
96 nonzero, outputs the character written to the tty's output port.
102 reg = <address> <size> (required)
104 Specify the address (within the parent bus) that this device is to
111 int[0..NR_PROCESSORS] (output)
113 Driven as a result of a write to the interrupt-port /
114 interrupt-level register pair.
121 hw_pal_reset_register
= 0x0,
122 hw_pal_cpu_nr_register
= 0x4,
123 hw_pal_int_register
= 0x8,
124 hw_pal_nr_cpu_register
= 0xa,
125 hw_pal_read_fifo
= 0x10,
126 hw_pal_read_status
= 0x14,
127 hw_pal_write_fifo
= 0x18,
128 hw_pal_write_status
= 0x1a,
129 hw_pal_address_mask
= 0x1f,
133 typedef struct _hw_pal_console_buffer
{
136 } hw_pal_console_buffer
;
138 typedef struct _hw_pal_device
{
139 hw_pal_console_buffer input
;
140 hw_pal_console_buffer output
;
145 /* check the console for an available character */
147 scan_hw_pal (struct hw
*me
)
150 hw_pal_struct hw
*hw_pal
= (hw_pal_struct hw
*) hw_data (me
);
154 count
= sim_io_read_stdin (hw_system (me
), &c
, sizeof(c
));
158 case sim_io_not_ready
:
160 hw_pal
->input
.buffer
= 0;
161 hw_pal
->input
.status
= 0;
164 hw_pal
->input
.buffer
= c
;
165 hw_pal
->input
.status
= 1;
170 /* write the character to the hw_pal */
172 write_hw_pal (struct hw
*me
,
175 hw_pal_device
*hw_pal
= (hw_pal_device
*) hw_data (me
);
176 sim_io_write_stdout (hw_system (me
), &val
, 1);
177 hw_pal
->output
.buffer
= val
;
178 hw_pal
->output
.status
= 1;
183 hw_pal_io_read_buffer (struct hw
*me
,
191 hw_pal_device
*hw_pal
= (hw_pal_device
*) hw_data (me
);
193 switch (addr
& hw_pal_address_mask
)
195 case hw_pal_cpu_nr_register
:
197 val
= CPU_INDEX (cpu
);
201 HW_TRACE ((me
, "read - cpu-nr %d\n", val
));
203 case hw_pal_nr_cpu_register
:
204 val
= hw_tree_find_integer_property (me
, "/openprom/options/smp");
205 HW_TRACE ((me
, "read - nr-cpu %d\n", val
));
207 case hw_pal_read_fifo
:
208 val
= hw_pal
->input
.buffer
;
209 HW_TRACE ((me
, "read - input-fifo %d\n", val
));
211 case hw_pal_read_status
:
213 val
= hw_pal
->input
.status
;
214 HW_TRACE ((me
, "read - input-status %d\n", val
));
216 case hw_pal_write_fifo
:
217 val
= hw_pal
->output
.buffer
;
218 HW_TRACE ((me
, "read - output-fifo %d\n", val
));
220 case hw_pal_write_status
:
221 val
= hw_pal
->output
.status
;
222 HW_TRACE ((me
, "read - output-status %d\n", val
));
226 HW_TRACE ((me
, "read - ???\n"));
228 memset (dest
, 0, nr_bytes
);
229 *(unsigned_1
*)dest
= val
;
235 hw_pal_io_write_buffer (struct hw
*me
,
243 hw_pal_device
*hw_pal
= (hw_pal_device
*) hw_data (me
);
244 unsigned_1
*byte
= (unsigned_1
*) source
;
246 switch (addr
& hw_pal_address_mask
)
248 case hw_pal_reset_register
:
249 sim_engine_halt (NULL
, cpu
, NULL
, cia
, sim_exited
, byte
[0]);
251 case hw_pal_int_register
:
254 (nr_bytes
> 1 ? byte
[1] : 0), /* val */
257 case hw_pal_read_fifo
:
258 hw_pal
->input
.buffer
= byte
[0];
259 HW_TRACE ((me
, "write - input-fifo %d\n", byte
[0]));
261 case hw_pal_read_status
:
262 hw_pal
->input
.status
= byte
[0];
263 HW_TRACE ((me
, "write - input-status %d\n", byte
[0]));
265 case hw_pal_write_fifo
:
266 write_hw_pal (me
, byte
[0]);
267 HW_TRACE ((me
, "write - output-fifo %d\n", byte
[0]));
269 case hw_pal_write_status
:
270 hw_pal
->output
.status
= byte
[0];
271 HW_TRACE ((me
, "write - output-status %d\n", byte
[0]));
278 /* instances of the hw_pal struct hw */
282 hw_pal_instance_delete_callback(hw_instance
*instance
)
284 /* nothing to delete, the hw_pal is attached to the struct hw */
291 hw_pal_instance_read_callback (hw_instance
*instance
,
295 DITRACE (pal
, ("read - %s (%ld)", (const char*) buf
, (long int) len
));
296 return sim_io_read_stdin (buf
, len
);
302 hw_pal_instance_write_callback (hw_instance
*instance
,
307 const char *chp
= buf
;
308 hw_pal_device
*hw_pal
= hw_instance_data (instance
);
309 DITRACE (pal
, ("write - %s (%ld)", (const char*) buf
, (long int) len
));
310 for (i
= 0; i
< len
; i
++)
311 write_hw_pal (hw_pal
, chp
[i
]);
312 sim_io_flush_stdoutput ();
318 static const hw_instance_callbacks hw_pal_instance_callbacks
= {
319 hw_pal_instance_delete_callback
,
320 hw_pal_instance_read_callback
,
321 hw_pal_instance_write_callback
,
327 hw_pal_create_instance (struct hw
*me
,
331 return hw_create_instance_from (me
, NULL
,
334 &hw_pal_instance_callbacks
);
338 static const struct hw_port_descriptor hw_pal_ports
[] = {
339 { "int", 0, MAX_NR_PROCESSORS
},
345 hw_pal_attach_address (struct hw
*me
,
349 address_word nr_bytes
,
352 hw_pal_device
*pal
= (hw_pal_device
*) hw_data (me
);
358 static hw_callbacks
const hw_pal_callbacks
= {
359 { generic_hw_init_address
, },
360 { hw_pal_attach_address
, }, /* address */
361 { hw_pal_io_read_buffer_callback
,
362 hw_pal_io_write_buffer_callback
, },
364 { NULL
, NULL
, hw_pal_interrupt_ports
}, /* interrupt */
365 { generic_hw_unit_decode
,
366 generic_hw_unit_encode
,
367 generic_hw_address_to_attach_address
,
368 generic_hw_size_to_attach_size
},
369 hw_pal_create_instance
,
375 hw_pal_finish (struct hw
*hw
)
377 /* create the descriptor */
378 hw_pal_device
*hw_pal
= HW_ZALLOC (hw
, hw_pal_device
);
379 hw_pal
->output
.status
= 1;
380 hw_pal
->output
.buffer
= '\0';
381 hw_pal
->input
.status
= 0;
382 hw_pal
->input
.buffer
= '\0';
383 set_hw_data (hw
, hw_pal
);
384 set_hw_attach_address (hw
, hw_pal_attach_address
);
385 set_hw_io_read_buffer (hw
, hw_pal_io_read_buffer
);
386 set_hw_io_write_buffer (hw
, hw_pal_io_write_buffer
);
387 set_hw_ports (hw
, hw_pal_ports
);
388 /* attach ourselves */
389 do_hw_attach_regs (me
);
393 const struct hw_device_descriptor dv_pal_descriptor
[] = {
394 { "pal", hw_pal_finish
, },