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