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