1 /* The common simulator framework for GDB, the GNU Debugger.
2 
3    Copyright 2002-2013 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
do_counter_event(struct hw * me,void * data)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
do_counter_read(struct hw * me,hw_pal_device * pal,const char * reg,hw_pal_counter * counter,unsigned32 * word,unsigned nr_bytes)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
do_counter_value(struct hw * me,hw_pal_device * pal,const char * reg,hw_pal_counter * counter,unsigned32 * word,unsigned nr_bytes)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
do_counter_write(struct hw * me,hw_pal_device * pal,const char * reg,hw_pal_counter * counter,const unsigned32 * word,unsigned nr_bytes)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
scan_hw_pal(struct hw * me)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
write_hw_pal(struct hw * me,char val)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
hw_pal_io_read_buffer(struct hw * me,void * dest,int space,unsigned_word addr,unsigned nr_bytes)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
hw_pal_io_write_buffer(struct hw * me,const void * source,int space,unsigned_word addr,unsigned nr_bytes)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
hw_pal_instance_delete_callback(hw_instance * instance)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
hw_pal_instance_read_callback(hw_instance * instance,void * buf,unsigned_word len)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
hw_pal_instance_write_callback(hw_instance * instance,const void * buf,unsigned_word len)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
hw_pal_attach_address(struct hw * me,int level,int space,address_word addr,address_word nr_bytes,struct hw * client)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
hw_pal_finish(struct hw * hw)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 };
607