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