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