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