Copy function ../ppc/device_table.c:generic_device_init_address() to
[deliverable/binutils-gdb.git] / sim / common / dv-pal.c
1 /* This file is part of the program psim.
2
3 Copyright (C) 1994-1996,1998, 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 2 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, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19 */
20
21
22 #include "sim-main.h"
23 #include "hw-base.h"
24
25 /* NOTE: pal is naughty and grubs around looking at things outside of
26 its immediate domain */
27 #include "hw-tree.h"
28
29 #ifdef HAVE_STRING_H
30 #include <string.h>
31 #else
32 #ifdef HAVE_STRINGS_H
33 #include <strings.h>
34 #endif
35 #endif
36
37 #ifdef HAVE_UNISTD_H
38 #include <unistd.h>
39 #endif
40 #ifdef HAVE_STDLIB_H
41 #include <stdlib.h>
42 #endif
43
44 /* DEVICE
45
46
47 pal - glue logic device containing assorted junk
48
49
50 DESCRIPTION
51
52
53 Typical hardware dependant hack. This device allows the firmware
54 to gain access to all the things the firmware needs (but the OS
55 doesn't).
56
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:
61
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)
71
72 Reset register (write) halts the simulator exiting with the
73 value written.
74
75 Processor id register (read) returns the processor number (0
76 .. N-1) of the processor performing the read.
77
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
85 be asserted.
86
87 Processor count register (read) returns the total number of
88 processors active in the current simulation.
89
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.
93
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.
97
98
99 PROPERTIES
100
101
102 reg = <address> <size> (required)
103
104 Specify the address (within the parent bus) that this device is to
105 live.
106
107
108 PORTS
109
110
111 int[0..NR_PROCESSORS] (output)
112
113 Driven as a result of a write to the interrupt-port /
114 interrupt-level register pair.
115
116
117 */
118
119
120 enum {
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,
130 };
131
132
133 typedef struct _hw_pal_console_buffer {
134 char buffer;
135 int status;
136 } hw_pal_console_buffer;
137
138 typedef struct _hw_pal_device {
139 hw_pal_console_buffer input;
140 hw_pal_console_buffer output;
141 struct hw *disk;
142 } hw_pal_device;
143
144
145 /* check the console for an available character */
146 static void
147 scan_hw_pal (struct hw *me)
148 {
149 #if 0
150 hw_pal_struct hw *hw_pal = (hw_pal_struct hw *) hw_data (me);
151 #endif
152 char c;
153 int count;
154 count = sim_io_read_stdin (hw_system (me), &c, sizeof(c));
155 #if 0
156 switch (count)
157 {
158 case sim_io_not_ready:
159 case sim_io_eof:
160 hw_pal->input.buffer = 0;
161 hw_pal->input.status = 0;
162 break;
163 default:
164 hw_pal->input.buffer = c;
165 hw_pal->input.status = 1;
166 }
167 #endif
168 }
169
170 /* write the character to the hw_pal */
171 static void
172 write_hw_pal (struct hw *me,
173 char val)
174 {
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;
179 }
180
181
182 static unsigned
183 hw_pal_io_read_buffer (struct hw *me,
184 void *dest,
185 int space,
186 unsigned_word addr,
187 unsigned nr_bytes,
188 sim_cpu *cpu,
189 sim_cia cia)
190 {
191 hw_pal_device *hw_pal = (hw_pal_device *) hw_data (me);
192 unsigned_1 val;
193 switch (addr & hw_pal_address_mask)
194 {
195 case hw_pal_cpu_nr_register:
196 #ifdef CPU_INDEX
197 val = CPU_INDEX (cpu);
198 #else
199 val = 0;
200 #endif
201 HW_TRACE ((me, "read - cpu-nr %d\n", val));
202 break;
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));
206 break;
207 case hw_pal_read_fifo:
208 val = hw_pal->input.buffer;
209 HW_TRACE ((me, "read - input-fifo %d\n", val));
210 break;
211 case hw_pal_read_status:
212 scan_hw_pal (me);
213 val = hw_pal->input.status;
214 HW_TRACE ((me, "read - input-status %d\n", val));
215 break;
216 case hw_pal_write_fifo:
217 val = hw_pal->output.buffer;
218 HW_TRACE ((me, "read - output-fifo %d\n", val));
219 break;
220 case hw_pal_write_status:
221 val = hw_pal->output.status;
222 HW_TRACE ((me, "read - output-status %d\n", val));
223 break;
224 default:
225 val = 0;
226 HW_TRACE ((me, "read - ???\n"));
227 }
228 memset (dest, 0, nr_bytes);
229 *(unsigned_1*)dest = val;
230 return nr_bytes;
231 }
232
233
234 static unsigned
235 hw_pal_io_write_buffer (struct hw *me,
236 const void *source,
237 int space,
238 unsigned_word addr,
239 unsigned nr_bytes,
240 sim_cpu *cpu,
241 sim_cia cia)
242 {
243 hw_pal_device *hw_pal = (hw_pal_device*) hw_data (me);
244 unsigned_1 *byte = (unsigned_1*) source;
245
246 switch (addr & hw_pal_address_mask)
247 {
248 case hw_pal_reset_register:
249 sim_engine_halt (NULL, cpu, NULL, cia, sim_exited, byte[0]);
250 break;
251 case hw_pal_int_register:
252 hw_port_event (me,
253 byte[0], /*port*/
254 (nr_bytes > 1 ? byte[1] : 0), /* val */
255 cpu, cia);
256 break;
257 case hw_pal_read_fifo:
258 hw_pal->input.buffer = byte[0];
259 HW_TRACE ((me, "write - input-fifo %d\n", byte[0]));
260 break;
261 case hw_pal_read_status:
262 hw_pal->input.status = byte[0];
263 HW_TRACE ((me, "write - input-status %d\n", byte[0]));
264 break;
265 case hw_pal_write_fifo:
266 write_hw_pal (me, byte[0]);
267 HW_TRACE ((me, "write - output-fifo %d\n", byte[0]));
268 break;
269 case hw_pal_write_status:
270 hw_pal->output.status = byte[0];
271 HW_TRACE ((me, "write - output-status %d\n", byte[0]));
272 break;
273 }
274 return nr_bytes;
275 }
276
277
278 /* instances of the hw_pal struct hw */
279
280 #if NOT_YET
281 static void
282 hw_pal_instance_delete_callback(hw_instance *instance)
283 {
284 /* nothing to delete, the hw_pal is attached to the struct hw */
285 return;
286 }
287 #endif
288
289 #if NOT_YET
290 static int
291 hw_pal_instance_read_callback (hw_instance *instance,
292 void *buf,
293 unsigned_word len)
294 {
295 DITRACE (pal, ("read - %s (%ld)", (const char*) buf, (long int) len));
296 return sim_io_read_stdin (buf, len);
297 }
298 #endif
299
300 #if NOT_YET
301 static int
302 hw_pal_instance_write_callback (hw_instance *instance,
303 const void *buf,
304 unsigned_word len)
305 {
306 int i;
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 ();
313 return i;
314 }
315 #endif
316
317 #if NOT_YET
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,
322 };
323 #endif
324
325 #if 0
326 static hw_instance *
327 hw_pal_create_instance (struct hw *me,
328 const char *path,
329 const char *args)
330 {
331 return hw_create_instance_from (me, NULL,
332 hw_data (me),
333 path, args,
334 &hw_pal_instance_callbacks);
335 }
336 #endif
337
338 static const struct hw_port_descriptor hw_pal_ports[] = {
339 { "int", 0, MAX_NR_PROCESSORS },
340 { NULL }
341 };
342
343
344 static void
345 hw_pal_attach_address (struct hw *me,
346 int level,
347 int space,
348 address_word addr,
349 address_word nr_bytes,
350 struct hw *client)
351 {
352 hw_pal_device *pal = (hw_pal_device*) hw_data (me);
353 pal->disk = client;
354 }
355
356
357 #if 0
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, },
363 { NULL, }, /* DMA */
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,
370 };
371 #endif
372
373
374 static void
375 hw_pal_finish (struct hw *hw)
376 {
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);
390 }
391
392
393 const struct hw_device_descriptor dv_pal_descriptor[] = {
394 { "pal", hw_pal_finish, },
395 { NULL },
396 };
This page took 0.071898 seconds and 5 git commands to generate.