]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - sim/common/dv-pal.c
This commit was generated by cvs2svn to track changes on a CVS vendor
[thirdparty/binutils-gdb.git] / sim / common / dv-pal.c
1 /* The common simulator framework for GDB, the GNU Debugger.
2
3 Copyright 2002 Free Software Foundation, Inc.
4
5 Contributed by Andrew Cagney and Red Hat.
6
7 This file is part of GDB.
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330,
22 Boston, MA 02111-1307, USA. */
23
24
25 #include "hw-main.h"
26 #include "sim-io.h"
27
28 /* NOTE: pal is naughty and grubs around looking at things outside of
29 its immediate domain */
30 #include "hw-tree.h"
31
32 #ifdef HAVE_STRING_H
33 #include <string.h>
34 #else
35 #ifdef HAVE_STRINGS_H
36 #include <strings.h>
37 #endif
38 #endif
39
40 #ifdef HAVE_UNISTD_H
41 #include <unistd.h>
42 #endif
43 #ifdef HAVE_STDLIB_H
44 #include <stdlib.h>
45 #endif
46
47 /* DEVICE
48
49
50 pal - glue logic device containing assorted junk
51
52
53 DESCRIPTION
54
55
56 Typical hardware dependant hack. This device allows the firmware
57 to gain access to all the things the firmware needs (but the OS
58 doesn't).
59
60 The pal contains the following registers:
61
62 |0 reset register (write, 8bit)
63 |4 processor id register (read, 8bit)
64 |8 interrupt register (8 - port, 9 - level) (write, 16bit)
65 |12 processor count register (read, 8bit)
66
67 |16 tty input fifo register (read, 8bit)
68 |20 tty input status register (read, 8bit)
69 |24 tty output fifo register (write, 8bit)
70 |28 tty output status register (read, 8bit)
71
72 |32 countdown register (read/write, 32bit, big-endian)
73 |36 countdown value register (read, 32bit, big-endian)
74 |40 timer register (read/write, 32bit, big-endian)
75 |44 timer value register (read, 32bit, big-endian)
76
77 RESET (write): halts the simulator. The value written to the
78 register is used as an exit status.
79
80 PROCESSOR ID (read): returns the processor identifier (0 .. N-1) of
81 the processor performing the read.
82
83 INTERRUPT (write): This register must be written using a two byte
84 store. The low byte specifies a port and the upper byte specifies
85 the a level. LEVEL is driven on the specified port. 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
90 being asserted.
91
92 PROCESSOR COUNT (read): returns the total number of processors
93 active in the current simulation.
94
95 TTY INPUT FIFO (read): if the TTY input status register indicates a
96 character is available by being nonzero, returns the next available
97 character from the pal's tty input port.
98
99 TTY OUTPUT FIFO (write): if the TTY output status register
100 indicates the output fifo is not full by being nonzero, outputs the
101 character written to the tty's output port.
102
103 COUNDOWN (read/write): The countdown registers provide a
104 non-repeating timed interrupt source. Writing a 32 bit big-endian
105 zero value to this register clears the countdown timer. Writing a
106 non-zero 32 bit big-endian value to this register sets the
107 countdown timer to expire in VALUE ticks (ticks is target
108 dependant). Reading the countdown register returns the last value
109 writen.
110
111 COUNTDOWN VALUE (read): Reading this 32 bit big-endian register
112 returns the number of ticks remaining until the countdown timer
113 expires.
114
115 TIMER (read/write): The timer registers provide a periodic timed
116 interrupt source. Writing a 32 bit big-endian zero value to this
117 register clears the periodic timer. Writing a 32 bit non-zero
118 value to this register sets the periodic timer to triger every
119 VALUE ticks (ticks is target dependant). Reading the timer
120 register returns the last value written.
121
122 TIMER VALUE (read): Reading this 32 bit big-endian register returns
123 the number of ticks until the next periodic interrupt.
124
125
126 PROPERTIES
127
128
129 reg = <address> <size> (required)
130
131 Specify the address (within the parent bus) that this device is to
132 be located.
133
134 poll? = <boolean>
135
136 If present and true, indicates that the device should poll its
137 input.
138
139
140 PORTS
141
142
143 int[0..NR_PROCESSORS] (output)
144
145 Driven as a result of a write to the interrupt-port /
146 interrupt-level register pair.
147
148
149 countdown
150
151 Driven whenever the countdown counter reaches zero.
152
153
154 timer
155
156 Driven whenever the timer counter reaches zero.
157
158
159 BUGS
160
161
162 At present the common simulator framework does not support input
163 polling.
164
165 */
166
167
168 enum {
169 hw_pal_reset_register = 0x0,
170 hw_pal_cpu_nr_register = 0x4,
171 hw_pal_int_register = 0x8,
172 hw_pal_nr_cpu_register = 0xa,
173 hw_pal_read_fifo = 0x10,
174 hw_pal_read_status = 0x14,
175 hw_pal_write_fifo = 0x18,
176 hw_pal_write_status = 0x1a,
177 hw_pal_countdown = 0x20,
178 hw_pal_countdown_value = 0x24,
179 hw_pal_timer = 0x28,
180 hw_pal_timer_value = 0x2c,
181 hw_pal_address_mask = 0x3f,
182 };
183
184
185 typedef struct _hw_pal_console_buffer {
186 char buffer;
187 int status;
188 } hw_pal_console_buffer;
189
190 typedef struct _hw_pal_counter {
191 struct hw_event *handler;
192 signed64 start;
193 unsigned32 delta;
194 int periodic_p;
195 } hw_pal_counter;
196
197
198 typedef struct _hw_pal_device {
199 hw_pal_console_buffer input;
200 hw_pal_console_buffer output;
201 hw_pal_counter countdown;
202 hw_pal_counter timer;
203 struct hw *disk;
204 do_hw_poll_read_method *reader;
205 } hw_pal_device;
206
207 enum {
208 COUNTDOWN_PORT,
209 TIMER_PORT,
210 INT_PORT,
211 };
212
213 static const struct hw_port_descriptor hw_pal_ports[] = {
214 { "countdown", COUNTDOWN_PORT, 0, output_port, },
215 { "timer", TIMER_PORT, 0, output_port, },
216 { "int", INT_PORT, MAX_NR_PROCESSORS, output_port, },
217 { NULL }
218 };
219
220
221 /* countdown and simple timer */
222
223 static void
224 do_counter_event (struct hw *me,
225 void *data)
226 {
227 hw_pal_counter *counter = (hw_pal_counter *) data;
228 if (counter->periodic_p)
229 {
230 HW_TRACE ((me, "timer expired"));
231 counter->start = hw_event_queue_time (me);
232 hw_port_event (me, TIMER_PORT, 1);
233 hw_event_queue_schedule (me, counter->delta, do_counter_event, counter);
234 }
235 else
236 {
237 HW_TRACE ((me, "countdown expired"));
238 counter->delta = 0;
239 hw_port_event (me, COUNTDOWN_PORT, 1);
240 }
241 }
242
243 static void
244 do_counter_read (struct hw *me,
245 hw_pal_device *pal,
246 const char *reg,
247 hw_pal_counter *counter,
248 unsigned32 *word,
249 unsigned nr_bytes)
250 {
251 unsigned32 val;
252 if (nr_bytes != 4)
253 hw_abort (me, "%s - bad read size must be 4 bytes", reg);
254 val = counter->delta;
255 HW_TRACE ((me, "read - %s %ld", reg, (long) val));
256 *word = H2BE_4 (val);
257 }
258
259 static void
260 do_counter_value (struct hw *me,
261 hw_pal_device *pal,
262 const char *reg,
263 hw_pal_counter *counter,
264 unsigned32 *word,
265 unsigned nr_bytes)
266 {
267 unsigned32 val;
268 if (nr_bytes != 4)
269 hw_abort (me, "%s - bad read size must be 4 bytes", reg);
270 if (counter->delta != 0)
271 val = (counter->start + counter->delta
272 - hw_event_queue_time (me));
273 else
274 val = 0;
275 HW_TRACE ((me, "read - %s %ld", reg, (long) val));
276 *word = H2BE_4 (val);
277 }
278
279 static void
280 do_counter_write (struct hw *me,
281 hw_pal_device *pal,
282 const char *reg,
283 hw_pal_counter *counter,
284 const unsigned32 *word,
285 unsigned nr_bytes)
286 {
287 if (nr_bytes != 4)
288 hw_abort (me, "%s - bad write size must be 4 bytes", reg);
289 if (counter->handler != NULL)
290 {
291 hw_event_queue_deschedule (me, counter->handler);
292 counter->handler = NULL;
293 }
294 counter->delta = BE2H_4 (*word);
295 counter->start = hw_event_queue_time (me);
296 HW_TRACE ((me, "write - %s %ld", reg, (long) counter->delta));
297 if (counter->delta > 0)
298 hw_event_queue_schedule (me, counter->delta, do_counter_event, counter);
299 }
300
301
302
303
304 /* check the console for an available character */
305 static void
306 scan_hw_pal (struct hw *me)
307 {
308 hw_pal_device *hw_pal = (hw_pal_device *)hw_data (me);
309 char c;
310 int count;
311 count = do_hw_poll_read (me, hw_pal->reader, 0/*STDIN*/, &c, sizeof(c));
312 switch (count)
313 {
314 case HW_IO_NOT_READY:
315 case HW_IO_EOF:
316 hw_pal->input.buffer = 0;
317 hw_pal->input.status = 0;
318 break;
319 default:
320 hw_pal->input.buffer = c;
321 hw_pal->input.status = 1;
322 }
323 }
324
325 /* write the character to the hw_pal */
326
327 static void
328 write_hw_pal (struct hw *me,
329 char val)
330 {
331 hw_pal_device *hw_pal = (hw_pal_device *) hw_data (me);
332 sim_io_write_stdout (hw_system (me), &val, 1);
333 hw_pal->output.buffer = val;
334 hw_pal->output.status = 1;
335 }
336
337
338 /* Reads/writes */
339
340 static unsigned
341 hw_pal_io_read_buffer (struct hw *me,
342 void *dest,
343 int space,
344 unsigned_word addr,
345 unsigned nr_bytes)
346 {
347 hw_pal_device *hw_pal = (hw_pal_device *) hw_data (me);
348 unsigned_1 *byte = (unsigned_1 *) dest;
349 memset (dest, 0, nr_bytes);
350 switch (addr & hw_pal_address_mask)
351 {
352
353 case hw_pal_cpu_nr_register:
354 #ifdef CPU_INDEX
355 *byte = CPU_INDEX (hw_system_cpu (me));
356 #else
357 *byte = 0;
358 #endif
359 HW_TRACE ((me, "read - cpu-nr %d\n", *byte));
360 break;
361
362 case hw_pal_nr_cpu_register:
363 if (hw_tree_find_property (me, "/openprom/options/smp") == NULL)
364 {
365 *byte = 1;
366 HW_TRACE ((me, "read - nr-cpu %d (not defined)\n", *byte));
367 }
368 else
369 {
370 *byte = hw_tree_find_integer_property (me, "/openprom/options/smp");
371 HW_TRACE ((me, "read - nr-cpu %d\n", *byte));
372 }
373 break;
374
375 case hw_pal_read_fifo:
376 *byte = hw_pal->input.buffer;
377 HW_TRACE ((me, "read - input-fifo %d\n", *byte));
378 break;
379
380 case hw_pal_read_status:
381 scan_hw_pal (me);
382 *byte = hw_pal->input.status;
383 HW_TRACE ((me, "read - input-status %d\n", *byte));
384 break;
385
386 case hw_pal_write_fifo:
387 *byte = hw_pal->output.buffer;
388 HW_TRACE ((me, "read - output-fifo %d\n", *byte));
389 break;
390
391 case hw_pal_write_status:
392 *byte = hw_pal->output.status;
393 HW_TRACE ((me, "read - output-status %d\n", *byte));
394 break;
395
396 case hw_pal_countdown:
397 do_counter_read (me, hw_pal, "countdown",
398 &hw_pal->countdown, dest, nr_bytes);
399 break;
400
401 case hw_pal_countdown_value:
402 do_counter_value (me, hw_pal, "countdown-value",
403 &hw_pal->countdown, dest, nr_bytes);
404 break;
405
406 case hw_pal_timer:
407 do_counter_read (me, hw_pal, "timer",
408 &hw_pal->timer, dest, nr_bytes);
409 break;
410
411 case hw_pal_timer_value:
412 do_counter_value (me, hw_pal, "timer-value",
413 &hw_pal->timer, dest, nr_bytes);
414 break;
415
416 default:
417 HW_TRACE ((me, "read - ???\n"));
418 break;
419
420 }
421 return nr_bytes;
422 }
423
424
425 static unsigned
426 hw_pal_io_write_buffer (struct hw *me,
427 const void *source,
428 int space,
429 unsigned_word addr,
430 unsigned nr_bytes)
431 {
432 hw_pal_device *hw_pal = (hw_pal_device*) hw_data (me);
433 unsigned_1 *byte = (unsigned_1 *) source;
434
435 switch (addr & hw_pal_address_mask)
436 {
437
438 case hw_pal_reset_register:
439 hw_halt (me, sim_exited, byte[0]);
440 break;
441
442 case hw_pal_int_register:
443 hw_port_event (me,
444 INT_PORT + byte[0], /*port*/
445 (nr_bytes > 1 ? byte[1] : 0)); /* val */
446 break;
447
448 case hw_pal_read_fifo:
449 hw_pal->input.buffer = byte[0];
450 HW_TRACE ((me, "write - input-fifo %d\n", byte[0]));
451 break;
452
453 case hw_pal_read_status:
454 hw_pal->input.status = byte[0];
455 HW_TRACE ((me, "write - input-status %d\n", byte[0]));
456 break;
457
458 case hw_pal_write_fifo:
459 write_hw_pal (me, byte[0]);
460 HW_TRACE ((me, "write - output-fifo %d\n", byte[0]));
461 break;
462
463 case hw_pal_write_status:
464 hw_pal->output.status = byte[0];
465 HW_TRACE ((me, "write - output-status %d\n", byte[0]));
466 break;
467
468 case hw_pal_countdown:
469 do_counter_write (me, hw_pal, "countdown",
470 &hw_pal->countdown, source, nr_bytes);
471 break;
472
473 case hw_pal_timer:
474 do_counter_write (me, hw_pal, "timer",
475 &hw_pal->timer, source, nr_bytes);
476 break;
477
478 }
479 return nr_bytes;
480 }
481
482
483 /* instances of the hw_pal struct hw */
484
485 #if NOT_YET
486 static void
487 hw_pal_instance_delete_callback(hw_instance *instance)
488 {
489 /* nothing to delete, the hw_pal is attached to the struct hw */
490 return;
491 }
492 #endif
493
494 #if NOT_YET
495 static int
496 hw_pal_instance_read_callback (hw_instance *instance,
497 void *buf,
498 unsigned_word len)
499 {
500 DITRACE (pal, ("read - %s (%ld)", (const char*) buf, (long int) len));
501 return sim_io_read_stdin (buf, len);
502 }
503 #endif
504
505 #if NOT_YET
506 static int
507 hw_pal_instance_write_callback (hw_instance *instance,
508 const void *buf,
509 unsigned_word len)
510 {
511 int i;
512 const char *chp = buf;
513 hw_pal_device *hw_pal = hw_instance_data (instance);
514 DITRACE (pal, ("write - %s (%ld)", (const char*) buf, (long int) len));
515 for (i = 0; i < len; i++)
516 write_hw_pal (hw_pal, chp[i]);
517 sim_io_flush_stdoutput ();
518 return i;
519 }
520 #endif
521
522 #if NOT_YET
523 static const hw_instance_callbacks hw_pal_instance_callbacks = {
524 hw_pal_instance_delete_callback,
525 hw_pal_instance_read_callback,
526 hw_pal_instance_write_callback,
527 };
528 #endif
529
530 #if 0
531 static hw_instance *
532 hw_pal_create_instance (struct hw *me,
533 const char *path,
534 const char *args)
535 {
536 return hw_create_instance_from (me, NULL,
537 hw_data (me),
538 path, args,
539 &hw_pal_instance_callbacks);
540 }
541 #endif
542
543
544 static void
545 hw_pal_attach_address (struct hw *me,
546 int level,
547 int space,
548 address_word addr,
549 address_word nr_bytes,
550 struct hw *client)
551 {
552 hw_pal_device *pal = (hw_pal_device*) hw_data (me);
553 pal->disk = client;
554 }
555
556
557 #if 0
558 static hw_callbacks const hw_pal_callbacks = {
559 { generic_hw_init_address, },
560 { hw_pal_attach_address, }, /* address */
561 { hw_pal_io_read_buffer_callback,
562 hw_pal_io_write_buffer_callback, },
563 { NULL, }, /* DMA */
564 { NULL, NULL, hw_pal_interrupt_ports }, /* interrupt */
565 { generic_hw_unit_decode,
566 generic_hw_unit_encode,
567 generic_hw_address_to_attach_address,
568 generic_hw_size_to_attach_size },
569 hw_pal_create_instance,
570 };
571 #endif
572
573
574 static void
575 hw_pal_finish (struct hw *hw)
576 {
577 /* create the descriptor */
578 hw_pal_device *hw_pal = HW_ZALLOC (hw, hw_pal_device);
579 hw_pal->output.status = 1;
580 hw_pal->output.buffer = '\0';
581 hw_pal->input.status = 0;
582 hw_pal->input.buffer = '\0';
583 set_hw_data (hw, hw_pal);
584 set_hw_attach_address (hw, hw_pal_attach_address);
585 set_hw_io_read_buffer (hw, hw_pal_io_read_buffer);
586 set_hw_io_write_buffer (hw, hw_pal_io_write_buffer);
587 set_hw_ports (hw, hw_pal_ports);
588 /* attach ourselves */
589 do_hw_attach_regs (hw);
590 /* If so configured, enable polled input */
591 if (hw_find_property (hw, "poll?") != NULL
592 && hw_find_boolean_property (hw, "poll?"))
593 {
594 hw_pal->reader = sim_io_poll_read;
595 }
596 else
597 {
598 hw_pal->reader = sim_io_read;
599 }
600 /* tag the periodic timer */
601 hw_pal->timer.periodic_p = 1;
602 }
603
604
605 const struct hw_descriptor dv_pal_descriptor[] = {
606 { "pal", hw_pal_finish, },
607 { NULL },
608 };