1 /* This file is part of the program psim.
3 Copyright (C) 1994-1996, 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 #ifndef STATIC_INLINE_HW_PAL
26 #define STATIC_INLINE_HW_PAL STATIC_INLINE
29 #include "device_table.h"
52 pal - glue logic device containing assorted junk
58 Typical hardware dependant hack. This device allows the firmware
59 to gain access to all the things the firmware needs (but the OS
62 The pal contains the following registers. Except for the interrupt
63 level register, each of the below is 8 bytes in size and must be
64 accessed using correct alignment. For 16 and 32 bit accesses the
65 bytes not directed to the register are ignored:
67 |0 reset register (write)
68 |4 processor id register (read)
69 |8 interrupt port (write)
70 |9 interrupt level (write)
71 |12 processor count register (read)
72 |16 tty input fifo register (read)
73 |20 tty input status register (read)
74 |24 tty output fifo register (write)
75 |28 tty output status register (read)
77 Reset register (write) halts the simulator exiting with the
80 Processor id register (read) returns the processor number (0
81 .. N-1) of the processor performing the read.
83 The interrupt registers should be accessed as a pair (using a 16 or
84 32 bit store). The low byte specifies the interrupt port while the
85 high byte specifies the level to drive that port at. 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 to
92 Processor count register (read) returns the total number of
93 processors active in the current simulation.
95 TTY input fifo register (read), if the TTY input status register
96 indicates a character is available by being nonzero, returns the
97 next available character from the pal's tty input port.
99 Similarly, the TTY output fifo register (write), if the TTY output
100 status register indicates the output fifo is not full by being
101 nonzero, outputs the character written to the tty's output port.
107 reg = <address> <size> (required)
109 Specify the address (within the parent bus) that this device is to
117 hw_pal_reset_register
= 0x0,
118 hw_pal_cpu_nr_register
= 0x4,
119 hw_pal_int_register
= 0x8,
120 hw_pal_nr_cpu_register
= 0xa,
121 hw_pal_read_fifo
= 0x10,
122 hw_pal_read_status
= 0x14,
123 hw_pal_write_fifo
= 0x18,
124 hw_pal_write_status
= 0x1a,
125 hw_pal_address_mask
= 0x1f,
129 typedef struct _hw_pal_console_buffer
{
132 } hw_pal_console_buffer
;
134 typedef struct _hw_pal_device
{
135 hw_pal_console_buffer input
;
136 hw_pal_console_buffer output
;
141 /* check the console for an available character */
143 scan_hw_pal(hw_pal_device
*hw_pal
)
147 count
= sim_io_read_stdin(&c
, sizeof(c
));
149 case sim_io_not_ready
:
151 hw_pal
->input
.buffer
= 0;
152 hw_pal
->input
.status
= 0;
155 hw_pal
->input
.buffer
= c
;
156 hw_pal
->input
.status
= 1;
160 /* write the character to the hw_pal */
162 write_hw_pal(hw_pal_device
*hw_pal
,
165 sim_io_write_stdout(&val
, 1);
166 hw_pal
->output
.buffer
= val
;
167 hw_pal
->output
.status
= 1;
172 hw_pal_io_read_buffer_callback(device
*me
,
180 hw_pal_device
*hw_pal
= (hw_pal_device
*)device_data(me
);
182 switch (addr
& hw_pal_address_mask
) {
183 case hw_pal_cpu_nr_register
:
184 val
= cpu_nr(processor
);
185 DTRACE(pal
, ("read - cpu-nr %d\n", val
));
187 case hw_pal_nr_cpu_register
:
188 val
= tree_find_integer_property(me
, "/openprom/options/smp");
189 DTRACE(pal
, ("read - nr-cpu %d\n", val
));
191 case hw_pal_read_fifo
:
192 val
= hw_pal
->input
.buffer
;
193 DTRACE(pal
, ("read - input-fifo %d\n", val
));
195 case hw_pal_read_status
:
197 val
= hw_pal
->input
.status
;
198 DTRACE(pal
, ("read - input-status %d\n", val
));
200 case hw_pal_write_fifo
:
201 val
= hw_pal
->output
.buffer
;
202 DTRACE(pal
, ("read - output-fifo %d\n", val
));
204 case hw_pal_write_status
:
205 val
= hw_pal
->output
.status
;
206 DTRACE(pal
, ("read - output-status %d\n", val
));
210 DTRACE(pal
, ("read - ???\n"));
212 memset(dest
, 0, nr_bytes
);
213 *(unsigned_1
*)dest
= val
;
219 hw_pal_io_write_buffer_callback(device
*me
,
227 hw_pal_device
*hw_pal
= (hw_pal_device
*)device_data(me
);
228 unsigned_1
*byte
= (unsigned_1
*)source
;
230 switch (addr
& hw_pal_address_mask
) {
231 case hw_pal_reset_register
:
232 cpu_halt(processor
, cia
, was_exited
, byte
[0]);
234 case hw_pal_int_register
:
235 device_interrupt_event(me
,
237 (nr_bytes
> 1 ? byte
[1] : 0), /* val */
240 case hw_pal_read_fifo
:
241 hw_pal
->input
.buffer
= byte
[0];
242 DTRACE(pal
, ("write - input-fifo %d\n", byte
[0]));
244 case hw_pal_read_status
:
245 hw_pal
->input
.status
= byte
[0];
246 DTRACE(pal
, ("write - input-status %d\n", byte
[0]));
248 case hw_pal_write_fifo
:
249 write_hw_pal(hw_pal
, byte
[0]);
250 DTRACE(pal
, ("write - output-fifo %d\n", byte
[0]));
252 case hw_pal_write_status
:
253 hw_pal
->output
.status
= byte
[0];
254 DTRACE(pal
, ("write - output-status %d\n", byte
[0]));
261 /* instances of the hw_pal device */
264 hw_pal_instance_delete_callback(device_instance
*instance
)
266 /* nothing to delete, the hw_pal is attached to the device */
271 hw_pal_instance_read_callback(device_instance
*instance
,
275 DITRACE(pal
, ("read - %s (%ld)", (const char*)buf
, (long int)len
));
276 return sim_io_read_stdin(buf
, len
);
280 hw_pal_instance_write_callback(device_instance
*instance
,
285 const char *chp
= buf
;
286 hw_pal_device
*hw_pal
= device_instance_data(instance
);
287 DITRACE(pal
, ("write - %s (%ld)", (const char*)buf
, (long int)len
));
288 for (i
= 0; i
< len
; i
++)
289 write_hw_pal(hw_pal
, chp
[i
]);
290 sim_io_flush_stdoutput();
294 static const device_instance_callbacks hw_pal_instance_callbacks
= {
295 hw_pal_instance_delete_callback
,
296 hw_pal_instance_read_callback
,
297 hw_pal_instance_write_callback
,
300 static device_instance
*
301 hw_pal_create_instance(device
*me
,
305 return device_create_instance_from(me
, NULL
,
308 &hw_pal_instance_callbacks
);
311 static const device_interrupt_port_descriptor hw_pal_interrupt_ports
[] = {
312 { "int", 0, MAX_NR_PROCESSORS
},
318 hw_pal_attach_address(device
*me
,
326 hw_pal_device
*pal
= (hw_pal_device
*)device_data(me
);
331 static device_callbacks
const hw_pal_callbacks
= {
332 { generic_device_init_address
, },
333 { hw_pal_attach_address
, }, /* address */
334 { hw_pal_io_read_buffer_callback
,
335 hw_pal_io_write_buffer_callback
, },
337 { NULL
, NULL
, hw_pal_interrupt_ports
}, /* interrupt */
338 { generic_device_unit_decode
,
339 generic_device_unit_encode
,
340 generic_device_address_to_attach_address
,
341 generic_device_size_to_attach_size
},
342 hw_pal_create_instance
,
347 hw_pal_create(const char *name
,
348 const device_unit
*unit_address
,
351 /* create the descriptor */
352 hw_pal_device
*hw_pal
= ZALLOC(hw_pal_device
);
353 hw_pal
->output
.status
= 1;
354 hw_pal
->output
.buffer
= '\0';
355 hw_pal
->input
.status
= 0;
356 hw_pal
->input
.buffer
= '\0';
361 const device_descriptor hw_pal_device_descriptor
[] = {
362 { "pal", hw_pal_create
, &hw_pal_callbacks
},
366 #endif /* _HW_PAL_C_ */