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