1/* The common simulator framework for GDB, the GNU Debugger.
2
3   Copyright 2002, 2007, 2008, 2009, 2010, 2011 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
166enum {
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
183typedef struct _hw_pal_console_buffer {
184  char buffer;
185  int status;
186} hw_pal_console_buffer;
187
188typedef 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
196typedef 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
205enum {
206  COUNTDOWN_PORT,
207  TIMER_PORT,
208  INT_PORT,
209};
210
211static 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
221static void
222do_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
241static void
242do_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
257static void
258do_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
277static void
278do_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 */
303static void
304scan_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
325static void
326write_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
338static unsigned
339hw_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
423static unsigned
424hw_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
484static void
485hw_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
493static int
494hw_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
504static int
505hw_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
521static 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
529static hw_instance *
530hw_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
542static void
543hw_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
556static 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
572static void
573hw_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
603const struct hw_descriptor dv_pal_descriptor[] = {
604  { "pal", hw_pal_finish, },
605  { NULL, NULL },
606};
607