Fix whitespace snafu in tc-riscv.c
[binutils-gdb.git] / sim / ppc / hw_pal.c
blobf8585084b37131e6bcb35e1d1ba31266e3fb67c9
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 3 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, see <http://www.gnu.org/licenses/>.
21 #ifndef _HW_PAL_C_
22 #define _HW_PAL_C_
24 #ifndef STATIC_INLINE_HW_PAL
25 #define STATIC_INLINE_HW_PAL STATIC_INLINE
26 #endif
28 #include "device_table.h"
30 #include "cpu.h"
32 #include <string.h>
33 #include <unistd.h>
34 #include <stdlib.h>
37 /* DEVICE
40 pal - glue logic device containing assorted junk
43 DESCRIPTION
46 Typical hardware dependant hack. This device allows the firmware
47 to gain access to all the things the firmware needs (but the OS
48 doesn't).
50 The pal contains the following registers. Except for the interrupt
51 level register, each of the below is 8 bytes in size and must be
52 accessed using correct alignment. For 16 and 32 bit accesses the
53 bytes not directed to the register are ignored:
55 |0 reset register (write)
56 |4 processor id register (read)
57 |8 interrupt port (write)
58 |9 interrupt level (write)
59 |12 processor count register (read)
60 |16 tty input fifo register (read)
61 |20 tty input status register (read)
62 |24 tty output fifo register (write)
63 |28 tty output status register (read)
65 Reset register (write) halts the simulator exiting with the
66 value written.
68 Processor id register (read) returns the processor number (0
69 .. N-1) of the processor performing the read.
71 The interrupt registers should be accessed as a pair (using a 16 or
72 32 bit store). The low byte specifies the interrupt port while the
73 high byte specifies the level to drive that port at. By
74 convention, the pal's interrupt ports (int0, int1, ...) are wired
75 up to the corresponding processor's level sensative external
76 interrupt pin. Eg: A two byte write to address 8 of 0x0102
77 (big-endian) will result in processor 2's external interrupt pin to
78 be asserted.
80 Processor count register (read) returns the total number of
81 processors active in the current simulation.
83 TTY input fifo register (read), if the TTY input status register
84 indicates a character is available by being nonzero, returns the
85 next available character from the pal's tty input port.
87 Similarly, the TTY output fifo register (write), if the TTY output
88 status register indicates the output fifo is not full by being
89 nonzero, outputs the character written to the tty's output port.
92 PROPERTIES
95 reg = <address> <size> (required)
97 Specify the address (within the parent bus) that this device is to
98 live.
104 enum {
105 hw_pal_reset_register = 0x0,
106 hw_pal_cpu_nr_register = 0x4,
107 hw_pal_int_register = 0x8,
108 hw_pal_nr_cpu_register = 0xa,
109 hw_pal_read_fifo = 0x10,
110 hw_pal_read_status = 0x14,
111 hw_pal_write_fifo = 0x18,
112 hw_pal_write_status = 0x1a,
113 hw_pal_address_mask = 0x1f,
117 typedef struct _hw_pal_console_buffer {
118 char buffer;
119 int status;
120 } hw_pal_console_buffer;
122 typedef struct _hw_pal_device {
123 hw_pal_console_buffer input;
124 hw_pal_console_buffer output;
125 device *disk;
126 } hw_pal_device;
129 /* check the console for an available character */
130 static void
131 scan_hw_pal(hw_pal_device *hw_pal)
133 char c;
134 int count;
135 count = sim_io_read_stdin(&c, sizeof(c));
136 switch (count) {
137 case sim_io_not_ready:
138 case sim_io_eof:
139 hw_pal->input.buffer = 0;
140 hw_pal->input.status = 0;
141 break;
142 default:
143 hw_pal->input.buffer = c;
144 hw_pal->input.status = 1;
148 /* write the character to the hw_pal */
149 static void
150 write_hw_pal(hw_pal_device *hw_pal,
151 char val)
153 sim_io_write_stdout(&val, 1);
154 hw_pal->output.buffer = val;
155 hw_pal->output.status = 1;
159 static unsigned
160 hw_pal_io_read_buffer_callback(device *me,
161 void *dest,
162 int space,
163 unsigned_word addr,
164 unsigned nr_bytes,
165 cpu *processor,
166 unsigned_word cia)
168 hw_pal_device *hw_pal = (hw_pal_device*)device_data(me);
169 unsigned_1 val;
170 switch (addr & hw_pal_address_mask) {
171 case hw_pal_cpu_nr_register:
172 val = cpu_nr(processor);
173 DTRACE(pal, ("read - cpu-nr %d\n", val));
174 break;
175 case hw_pal_nr_cpu_register:
176 val = tree_find_integer_property(me, "/openprom/options/smp");
177 DTRACE(pal, ("read - nr-cpu %d\n", val));
178 break;
179 case hw_pal_read_fifo:
180 val = hw_pal->input.buffer;
181 DTRACE(pal, ("read - input-fifo %d\n", val));
182 break;
183 case hw_pal_read_status:
184 scan_hw_pal(hw_pal);
185 val = hw_pal->input.status;
186 DTRACE(pal, ("read - input-status %d\n", val));
187 break;
188 case hw_pal_write_fifo:
189 val = hw_pal->output.buffer;
190 DTRACE(pal, ("read - output-fifo %d\n", val));
191 break;
192 case hw_pal_write_status:
193 val = hw_pal->output.status;
194 DTRACE(pal, ("read - output-status %d\n", val));
195 break;
196 default:
197 val = 0;
198 DTRACE(pal, ("read - ???\n"));
200 memset(dest, 0, nr_bytes);
201 *(unsigned_1*)dest = val;
202 return nr_bytes;
206 static unsigned
207 hw_pal_io_write_buffer_callback(device *me,
208 const void *source,
209 int space,
210 unsigned_word addr,
211 unsigned nr_bytes,
212 cpu *processor,
213 unsigned_word cia)
215 hw_pal_device *hw_pal = (hw_pal_device*)device_data(me);
216 unsigned_1 *byte = (unsigned_1*)source;
218 switch (addr & hw_pal_address_mask) {
219 case hw_pal_reset_register:
220 cpu_halt(processor, cia, was_exited, byte[0]);
221 break;
222 case hw_pal_int_register:
223 device_interrupt_event(me,
224 byte[0], /*port*/
225 (nr_bytes > 1 ? byte[1] : 0), /* val */
226 processor, cia);
227 break;
228 case hw_pal_read_fifo:
229 hw_pal->input.buffer = byte[0];
230 DTRACE(pal, ("write - input-fifo %d\n", byte[0]));
231 break;
232 case hw_pal_read_status:
233 hw_pal->input.status = byte[0];
234 DTRACE(pal, ("write - input-status %d\n", byte[0]));
235 break;
236 case hw_pal_write_fifo:
237 write_hw_pal(hw_pal, byte[0]);
238 DTRACE(pal, ("write - output-fifo %d\n", byte[0]));
239 break;
240 case hw_pal_write_status:
241 hw_pal->output.status = byte[0];
242 DTRACE(pal, ("write - output-status %d\n", byte[0]));
243 break;
245 return nr_bytes;
249 /* instances of the hw_pal device */
251 static void
252 hw_pal_instance_delete_callback(device_instance *instance)
254 /* nothing to delete, the hw_pal is attached to the device */
255 return;
258 static int
259 hw_pal_instance_read_callback(device_instance *instance,
260 void *buf,
261 unsigned_word len)
263 DITRACE(pal, ("read - %s (%ld)", (const char*)buf, (long int)len));
264 return sim_io_read_stdin(buf, len);
267 static int
268 hw_pal_instance_write_callback(device_instance *instance,
269 const void *buf,
270 unsigned_word len)
272 int i;
273 const char *chp = buf;
274 hw_pal_device *hw_pal = device_instance_data(instance);
275 DITRACE(pal, ("write - %s (%ld)", (const char*)buf, (long int)len));
276 for (i = 0; i < len; i++)
277 write_hw_pal(hw_pal, chp[i]);
278 sim_io_flush_stdoutput();
279 return i;
282 static const device_instance_callbacks hw_pal_instance_callbacks = {
283 hw_pal_instance_delete_callback,
284 hw_pal_instance_read_callback,
285 hw_pal_instance_write_callback,
288 static device_instance *
289 hw_pal_create_instance(device *me,
290 const char *path,
291 const char *args)
293 return device_create_instance_from(me, NULL,
294 device_data(me),
295 path, args,
296 &hw_pal_instance_callbacks);
299 static const device_interrupt_port_descriptor hw_pal_interrupt_ports[] = {
300 { "int", 0, MAX_NR_PROCESSORS },
301 { NULL }
305 static void
306 hw_pal_attach_address(device *me,
307 attach_type attach,
308 int space,
309 unsigned_word addr,
310 unsigned nr_bytes,
311 access_type access,
312 device *client)
314 hw_pal_device *pal = (hw_pal_device*)device_data(me);
315 pal->disk = client;
319 static device_callbacks const hw_pal_callbacks = {
320 { generic_device_init_address, },
321 { hw_pal_attach_address, }, /* address */
322 { hw_pal_io_read_buffer_callback,
323 hw_pal_io_write_buffer_callback, },
324 { NULL, }, /* DMA */
325 { NULL, NULL, hw_pal_interrupt_ports }, /* interrupt */
326 { generic_device_unit_decode,
327 generic_device_unit_encode,
328 generic_device_address_to_attach_address,
329 generic_device_size_to_attach_size },
330 hw_pal_create_instance,
334 static void *
335 hw_pal_create(const char *name,
336 const device_unit *unit_address,
337 const char *args)
339 /* create the descriptor */
340 hw_pal_device *hw_pal = ZALLOC(hw_pal_device);
341 hw_pal->output.status = 1;
342 hw_pal->output.buffer = '\0';
343 hw_pal->input.status = 0;
344 hw_pal->input.buffer = '\0';
345 return hw_pal;
349 const device_descriptor hw_pal_device_descriptor[] = {
350 { "pal", hw_pal_create, &hw_pal_callbacks },
351 { NULL },
354 #endif /* _HW_PAL_C_ */