More changes for GO32 canadian cross builds
[deliverable/binutils-gdb.git] / sim / ppc / device_table.c
CommitLineData
cb7a6892
MM
1/* This file is part of the program psim.
2
d6103e8e 3 Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au>
cb7a6892
MM
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19 */
20
21
93fac324
MM
22#ifndef _DEVICE_TABLE_C_
23#define _DEVICE_TABLE_C_
cb7a6892 24
93fac324
MM
25#ifndef STATIC_INLINE_DEVICE_TABLE
26#define STATIC_INLINE_DEVICE_TABLE STATIC_INLINE
cb7a6892
MM
27#endif
28
cb7a6892 29#include <stdio.h>
cb7a6892 30#include <fcntl.h>
dec38dac
MM
31#include <signal.h>
32#include <stdarg.h>
979c3c25 33#include <ctype.h>
cb7a6892 34
93fac324
MM
35#include "device_table.h"
36
cb7a6892
MM
37#include "events.h"
38
c494cadd
MM
39#ifdef HAVE_UNISTD_H
40#include <unistd.h>
41#endif
42
43#ifdef HAVE_STDLIB_H
44#include <stdlib.h>
45#endif
46
47#ifdef HAVE_STRING_H
48#include <string.h>
49#else
50#ifdef HAVE_STRINGS_H
51#include <strings.h>
52#endif
53#endif
54
dec38dac
MM
55#include "cpu.h"
56
57#include "bfd.h"
cb7a6892
MM
58
59/* Helper functions */
60
dec38dac
MM
61/* Generic device init: Attaches the device of size <nr_bytes> (taken
62 from <name>@<int>,<nr_bytes>) to its parent at address zero and
63 with read/write access. */
64
d6103e8e
MM
65typedef struct _reg_spec {
66 unsigned32 base;
67 unsigned32 size;
68} reg_spec;
69
70void
71generic_device_init_address(device *me,
72 psim *system)
cb7a6892 73{
d6103e8e
MM
74 const device_property *reg = device_find_array_property(me, "reg");
75 const reg_spec *spec = reg->array;
76 int nr_entries = reg->sizeof_array / sizeof(reg_spec);
77
78 if ((reg->sizeof_array % sizeof(reg_spec)) != 0)
79 error("devices/%s reg property is of wrong size\n", device_name(me));
80
81 while (nr_entries > 0) {
82 device_attach_address(device_parent(me),
83 device_name(me),
84 attach_callback,
85 0 /*space*/,
86 BE2H_4(spec->base),
87 BE2H_4(spec->size),
88 access_read_write_exec,
89 me);
90 spec++;
91 nr_entries--;
92 }
cb7a6892
MM
93}
94
d6103e8e
MM
95int
96generic_device_unit_decode(device *me,
97 const char *unit,
98 device_unit *phys)
99{
100 memset(phys, 0, sizeof(device_unit));
101 if (unit == NULL)
102 return 0;
103 else {
104 char *pos = (char*)unit; /* force for strtoul() */
105 while (1) {
106 char *old_pos = pos;
107 long int val = strtoul(pos, &pos, 0);
108 if (old_pos == pos && *pos == '\0')
109 return phys->nr_cells;
110 if (old_pos == pos && *pos != '\0')
111 return -1;
112 if (phys->nr_cells == 4)
113 return -1;
114 phys->cells[phys->nr_cells] = val;
115 phys->nr_cells++;
116 }
117 }
118}
119
120int
121generic_device_unit_encode(device *me,
122 const device_unit *phys,
123 char *buf,
124 int sizeof_buf)
125{
126 int i;
127 int len;
128 char *pos = buf; /* force for strtoul() */
129 for (i = 0; i < phys->nr_cells; i++) {
130 if (pos != buf) {
131 strcat(pos, ",");
132 pos = strchr(pos, '\0');
133 }
134 sprintf(pos, "0x%lx", (unsigned long)phys->cells[i]);
135 pos = strchr(pos, '\0');
136 }
137 len = pos - buf;
138 if (len >= sizeof_buf)
139 error("generic_unit_encode - buffer overflow\n");
140 return len;
141}
cb7a6892 142
1dc7c0ed 143/* DMA a file into memory */
93fac324
MM
144STATIC_INLINE_DEVICE_TABLE int
145dma_file(device *me,
1dc7c0ed
MM
146 const char *file_name,
147 unsigned_word addr)
148{
149 int count;
150 int inc;
151 FILE *image;
152 char buf[1024];
153
154 /* get it open */
155 image = fopen(file_name, "r");
156 if (image == NULL)
157 return -1;
158
159 /* read it in slowly */
160 count = 0;
161 while (1) {
93fac324
MM
162 inc = fread(buf, 1, sizeof(buf), image);
163 if (feof(image) || ferror(image))
1dc7c0ed 164 break;
93fac324
MM
165 if (device_dma_write_buffer(device_parent(me),
166 buf,
167 0 /*address-space*/,
168 addr+count,
169 inc /*nr-bytes*/,
170 1 /*violate ro*/) != inc) {
1dc7c0ed
MM
171 fclose(image);
172 return -1;
173 }
174 count += inc;
175 }
176
177 /* close down again */
178 fclose(image);
179
180 return count;
181}
182
183
dec38dac
MM
184\f
185/* inimplemented versions of each function */
cb7a6892 186
93fac324
MM
187void
188unimp_device_init(device *me,
dec38dac
MM
189 psim *system)
190{
93fac324 191 error("device_init_callback for %s not implemented\n", device_name(me));
dec38dac 192}
cb7a6892 193
93fac324
MM
194void
195unimp_device_attach_address(device *me,
dec38dac
MM
196 const char *name,
197 attach_type type,
5b4d72dd 198 int space,
dec38dac
MM
199 unsigned_word addr,
200 unsigned nr_bytes,
201 access_type access,
93fac324 202 device *who) /*callback/default*/
dec38dac 203{
93fac324 204 error("device_attach_address_callback for %s not implemented\n", device_name(me));
dec38dac 205}
cb7a6892 206
93fac324
MM
207void
208unimp_device_detach_address(device *me,
dec38dac
MM
209 const char *name,
210 attach_type type,
5b4d72dd 211 int space,
dec38dac
MM
212 unsigned_word addr,
213 unsigned nr_bytes,
214 access_type access,
93fac324 215 device *who) /*callback/default*/
dec38dac 216{
93fac324 217 error("device_detach_address_callback for %s not implemented\n", device_name(me));
dec38dac 218}
cb7a6892 219
93fac324
MM
220unsigned
221unimp_device_io_read_buffer(device *me,
dec38dac 222 void *dest,
5b4d72dd 223 int space,
dec38dac
MM
224 unsigned_word addr,
225 unsigned nr_bytes,
226 cpu *processor,
227 unsigned_word cia)
228{
93fac324 229 error("device_io_read_buffer_callback for %s not implemented\n", device_name(me));
dec38dac
MM
230 return 0;
231}
cb7a6892 232
93fac324
MM
233unsigned
234unimp_device_io_write_buffer(device *me,
dec38dac 235 const void *source,
5b4d72dd 236 int space,
dec38dac
MM
237 unsigned_word addr,
238 unsigned nr_bytes,
239 cpu *processor,
240 unsigned_word cia)
241{
93fac324 242 error("device_io_write_buffer_callback for %s not implemented\n", device_name(me));
dec38dac
MM
243 return 0;
244}
245
93fac324
MM
246unsigned
247unimp_device_dma_read_buffer(device *me,
dec38dac 248 void *target,
5b4d72dd 249 int space,
dec38dac
MM
250 unsigned_word addr,
251 unsigned nr_bytes)
252{
93fac324 253 error("device_dma_read_buffer_callback for %s not implemented\n", device_name(me));
dec38dac
MM
254 return 0;
255}
256
93fac324
MM
257unsigned
258unimp_device_dma_write_buffer(device *me,
dec38dac 259 const void *source,
5b4d72dd 260 int space,
dec38dac
MM
261 unsigned_word addr,
262 unsigned nr_bytes,
263 int violate_read_only_section)
264{
93fac324 265 error("device_dma_write_buffer_callback for %s not implemented\n", device_name(me));
dec38dac
MM
266 return 0;
267}
268
93fac324 269void
d6103e8e
MM
270unimp_device_interrupt_event(device *me,
271 int my_port,
272 device *source,
273 int source_port,
274 int level,
275 cpu *processor,
276 unsigned_word cia)
dec38dac 277{
d6103e8e
MM
278 error("unimp_device_interrupt_event for %s unimplemented\n",
279 device_name(me));
dec38dac
MM
280}
281
93fac324 282void
d6103e8e
MM
283unimp_device_child_interrupt_event(device *me,
284 device *parent,
285 device *source,
286 int source_port,
287 int level,
288 cpu *processor,
289 unsigned_word cia)
dec38dac 290{
d6103e8e
MM
291 error("unimp_device_child_interrupt_event_callback for %s unimplemented\n",
292 device_name(me));
293}
294
295int
296unimp_device_unit_decode(device *me,
297 const char *unit,
298 device_unit *address)
299{
300 error("unimp_device_unit_decode_callback for %s unimplemented\n",
301 device_name(me));
302 return 0;
dec38dac
MM
303}
304
d6103e8e
MM
305int
306unimp_device_unit_encode(device *me,
307 const device_unit *unit_address,
308 char *buf,
309 int sizeof_buf)
310{
311 error("unimp_device_unit_encode_callback for %s unimplemented\n",
312 device_name(me));
313 return 0;
314}
315
316void *
317unimp_device_instance_create(device *me,
318 const char *args)
dec38dac 319{
d6103e8e
MM
320 error("unimp_device_instance_create_callback for %s unimplemented\n",
321 device_name(me));
322 return 0;
dec38dac
MM
323}
324
93fac324 325void
d6103e8e
MM
326unimp_device_instance_delete(device_instance *instance)
327{
328 error("unimp_device_instance_delete_callback for %s unimplemented\n",
329 device_instance_name(instance));
330}
331
332int
333unimp_device_instance_read(device_instance *instance,
334 void *buf,
335 unsigned_word len)
336{
337 error("unimp_device_instance_read_callback for %s unimplemented\n",
338 device_instance_name(instance));
339 return 0;
340}
341
342int
343unimp_device_instance_write(device_instance *instance,
344 const void *buf,
345 unsigned_word len)
dec38dac 346{
d6103e8e
MM
347 error("unimp_device_instance_write_callback for %s unimplemented\n",
348 device_instance_name(instance));
349 return 0;
dec38dac
MM
350}
351
d6103e8e
MM
352int
353unimp_device_instance_seek(device_instance *instance,
354 unsigned_word pos_hi,
355 unsigned_word pos_lo)
356{
357 error("unimp_device_instance_seek_callback for %s unimplemented\n",
358 device_instance_name(instance));
359 return 0;
360}
361
362
93fac324
MM
363void
364unimp_device_ioctl(device *me,
dec38dac
MM
365 psim *system,
366 cpu *processor,
367 unsigned_word cia,
93fac324 368 va_list ap)
dec38dac 369{
93fac324 370 error("device_ioctl_callback for %s not implemented\n", device_name(me));
dec38dac
MM
371}
372
373
374\f
375/* ignore/passthrough versions of each function */
376
93fac324
MM
377void
378ignore_device_init(device *me,
dec38dac
MM
379 psim *system)
380{
381 /*null*/
382}
383
93fac324
MM
384void
385passthrough_device_attach_address(device *me,
386 const char *name,
387 attach_type attach,
388 int space,
389 unsigned_word addr,
390 unsigned nr_bytes,
391 access_type access,
392 device *who) /*callback/default*/
dec38dac 393{
93fac324
MM
394 device_attach_address(device_parent(me), name, attach,
395 space, addr, nr_bytes,
396 access,
397 who);
dec38dac
MM
398}
399
93fac324
MM
400void
401passthrough_device_detach_address(device *me,
402 const char *name,
403 attach_type attach,
404 int space,
405 unsigned_word addr,
d6103e8e
MM
406 unsigned nr_bytes,
407 access_type access,
408 device *who) /*callback/default*/
dec38dac 409{
93fac324
MM
410 device_detach_address(device_parent(me), name, attach,
411 space, addr, nr_bytes, access,
412 who);
dec38dac
MM
413}
414
93fac324
MM
415unsigned
416passthrough_device_dma_read_buffer(device *me,
d6103e8e
MM
417 void *dest,
418 int space,
419 unsigned_word addr,
420 unsigned nr_bytes)
dec38dac 421{
93fac324
MM
422 return device_dma_read_buffer(device_parent(me), dest,
423 space, addr, nr_bytes);
dec38dac
MM
424}
425
93fac324
MM
426unsigned
427passthrough_device_dma_write_buffer(device *me,
dec38dac 428 const void *source,
5b4d72dd 429 int space,
dec38dac
MM
430 unsigned_word addr,
431 unsigned nr_bytes,
432 int violate_read_only_section)
433{
93fac324
MM
434 return device_dma_write_buffer(device_parent(me), source,
435 space, addr,
436 nr_bytes,
437 violate_read_only_section);
dec38dac
MM
438}
439
d6103e8e
MM
440int
441ignore_device_unit_decode(device *me,
442 const char *unit,
443 device_unit *phys)
dec38dac 444{
d6103e8e
MM
445 memset(phys, 0, sizeof(device_unit));
446 return 0;
dec38dac
MM
447}
448
449
93fac324 450static const device_callbacks passthrough_callbacks = {
d6103e8e 451 ignore_device_init,
93fac324
MM
452 ignore_device_init,
453 passthrough_device_attach_address,
454 passthrough_device_detach_address,
455 unimp_device_io_read_buffer,
456 unimp_device_io_write_buffer,
457 passthrough_device_dma_read_buffer,
458 passthrough_device_dma_write_buffer,
d6103e8e
MM
459 unimp_device_interrupt_event,
460 unimp_device_child_interrupt_event,
461 generic_device_unit_decode,
462 generic_device_unit_encode,
463 unimp_device_instance_create,
464 unimp_device_instance_delete,
465 unimp_device_instance_read,
466 unimp_device_instance_write,
467 unimp_device_instance_seek,
93fac324
MM
468 unimp_device_ioctl,
469};
470
471
dec38dac 472\f
1dc7c0ed 473/* Simple console device: console@<address>,16
dec38dac
MM
474
475 Input characters are taken from the keyboard, output characters
476 sent to the terminal. Echoing of characters is not disabled.
477
478 The device has four registers:
479
480 0x0: read
481 0x4: read-status
482 0x8: write
483 0xC: write-status
484
485 Where a nonzero status register indicates that the device is ready
486 (input fifo contains a character or output fifo has space). */
cb7a6892
MM
487
488typedef struct _console_buffer {
489 char buffer;
490 int status;
491 event_entry_tag event_tag;
492} console_buffer;
493
494typedef struct _console_device {
cb7a6892
MM
495 console_buffer input;
496 console_buffer output;
497} console_device;
498
499typedef enum {
500 console_read_buffer = 0,
501 console_read_status = 4,
502 console_write_buffer = 8,
503 console_write_status = 12,
504 console_offset_mask = 0xc,
505 console_size = 16,
506} console_offsets;
507
d6103e8e
MM
508static int console_use_stdio = WITH_STDIO;
509
510/* check the console for an available character */
511static void
512scan_console(console_device *console)
513{ /* check for input */
514 int flags;
515 int status;
516
517 /* Use stdio if desired. */
518 if (console_use_stdio) {
519 int ch = getchar ();
520 if (ch == EOF) {
521 console->input.status = 0;
522 console->input.buffer = '\0';
523 } else {
524 console->input.status = 1;
525 console->input.buffer = ch;
526 }
527 return;
528 }
529
530 /* get the old status */
531 flags = fcntl(0, F_GETFL, 0);
532 if (flags == -1) {
533 perror("console");
534 return;
535 }
536
537 /* temp, disable blocking IO */
538 status = fcntl(0, F_SETFL, flags | O_NDELAY);
539 if (status == -1) {
540 perror("console");
541 return;
542 }
543 /* try for input */
544 status = read(0, &console->input.buffer, 1);
545 if (status == 1) {
546 console->input.status = 1;
547 }
548 else {
549 console->input.status = 0;
550 }
551 /* return to regular vewing */
552 flags = fcntl(0, F_SETFL, flags);
553 if (flags == -1) {
554 perror("console");
555 return;
556 }
557}
558
559/* write the character to the console */
560static void
561write_console(console_device *console,
562 char val)
563{
564 DTRACE(console, ("<%c:%d>", val, val));
565 if (console_use_stdio)
566 putchar (val);
567 else
568 printf_filtered("%c", val) ;
569 console->output.buffer = val;
570 console->output.status = 1;
571}
cb7a6892 572
93fac324
MM
573static unsigned
574console_io_read_buffer_callback(device *me,
dec38dac 575 void *dest,
5b4d72dd 576 int space,
dec38dac
MM
577 unsigned_word addr,
578 unsigned nr_bytes,
579 cpu *processor,
580 unsigned_word cia)
cb7a6892 581{
93fac324 582 console_device *console = (console_device*)device_data(me);
dec38dac 583 unsigned_1 val;
cb7a6892 584
dec38dac 585 /* determine what was read */
cb7a6892 586
d6103e8e 587 switch ((int)addr & console_offset_mask) {
cb7a6892
MM
588
589 case console_read_buffer:
dec38dac
MM
590 val = console->input.buffer;
591 break;
cb7a6892
MM
592
593 case console_read_status:
d6103e8e 594 scan_console(console);
dec38dac
MM
595 val = console->input.status;
596 break;
cb7a6892
MM
597
598 case console_write_buffer:
dec38dac
MM
599 val = console->output.buffer;
600 break;
cb7a6892
MM
601
602 case console_write_status:
dec38dac
MM
603 val = console->output.status;
604 break;
cb7a6892
MM
605
606 default:
607 error("console_read_callback() internal error\n");
dec38dac
MM
608 val = 0;
609 break;
cb7a6892
MM
610
611 }
612
1dc7c0ed 613 memset(dest, 0, nr_bytes);
dec38dac
MM
614 *(unsigned_1*)dest = val;
615 return nr_bytes;
cb7a6892
MM
616}
617
93fac324
MM
618static unsigned
619console_io_write_buffer_callback(device *me,
dec38dac 620 const void *source,
5b4d72dd 621 int space,
dec38dac
MM
622 unsigned_word addr,
623 unsigned nr_bytes,
624 cpu *processor,
625 unsigned_word cia)
cb7a6892 626{
93fac324 627 console_device *console = (console_device*)device_data(me);
1dc7c0ed 628 unsigned_1 val = *(unsigned_1*)source;
cb7a6892 629
d6103e8e
MM
630 switch ((int)addr & console_offset_mask) {
631
dec38dac
MM
632 case console_read_buffer:
633 console->input.buffer = val;
634 break;
d6103e8e 635
dec38dac
MM
636 case console_read_status:
637 console->input.status = val;
638 break;
d6103e8e 639
cb7a6892 640 case console_write_buffer:
d6103e8e
MM
641 write_console(console, val);
642 if (console_use_stdio)
643 fflush (stdout);
cb7a6892 644 break;
d6103e8e 645
cb7a6892 646 case console_write_status:
dec38dac 647 console->output.status = val;
cb7a6892 648 break;
d6103e8e 649
dec38dac
MM
650 default:
651 error("console_write_callback() internal error\n");
d6103e8e 652
cb7a6892 653 }
dec38dac
MM
654
655 return nr_bytes;
cb7a6892
MM
656}
657
d6103e8e
MM
658/* instances of the console device */
659static void *
660console_instance_create_callback(device *me,
661 const char *args)
662{
663 /* make life easier, attach the console data to the instance */
664 return device_data(me);
665}
666
667static void
668console_instance_delete_callback(device_instance *instance)
669{
670 /* nothing to delete, the console is attached to the device */
671 return;
672}
673
674static int
675console_instance_read_callback(device_instance *instance,
676 void *buf,
677 unsigned_word len)
678{
679 console_device *console = device_instance_data(instance);
680 if (console_use_stdio) {
681 char *p = fgets (buf, len, stdin);
682 if (!p)
683 return ferror (stdin) ? -1 : -2;
684
685 return strlen (p);
686 }
687
688 if (!console->input.status)
689 scan_console(console);
690 if (console->input.status) {
691 *(char*)buf = console->input.buffer;
692 console->input.status = 0;
693 return 1;
694 }
695 else {
696 return -2; /* not ready */
697 }
698}
699
700static int
701console_instance_write_callback(device_instance *instance,
702 const void *buf,
703 unsigned_word len)
704{
705 int i;
706 const char *chp = buf;
707 console_device *console = device_instance_data(instance);
708 for (i = 0; i < len; i++)
709 write_console(console, chp[i]);
710 if (console_use_stdio && len)
711 fflush (stdout);
712 return i;
713}
dec38dac
MM
714
715static device_callbacks const console_callbacks = {
d6103e8e
MM
716 generic_device_init_address,
717 ignore_device_init,
dec38dac
MM
718 unimp_device_attach_address,
719 unimp_device_detach_address,
720 console_io_read_buffer_callback,
721 console_io_write_buffer_callback,
722 unimp_device_dma_read_buffer,
723 unimp_device_dma_write_buffer,
d6103e8e
MM
724 unimp_device_interrupt_event,
725 unimp_device_child_interrupt_event,
726 unimp_device_unit_decode,
727 unimp_device_unit_encode,
728 console_instance_create_callback,
729 console_instance_delete_callback,
730 console_instance_read_callback,
731 console_instance_write_callback,
732 unimp_device_instance_seek,
dec38dac 733 unimp_device_ioctl,
cb7a6892
MM
734};
735
cb7a6892 736
93fac324 737static void *
dec38dac 738console_create(const char *name,
d6103e8e
MM
739 const device_unit *unit_address,
740 const char *args,
93fac324 741 device *parent)
dec38dac 742{
cb7a6892
MM
743 /* create the descriptor */
744 console_device *console = ZALLOC(console_device);
cb7a6892
MM
745 console->output.status = 1;
746 console->output.buffer = '\0';
747 console->input.status = 0;
748 console->input.buffer = '\0';
93fac324 749 return console;
cb7a6892
MM
750}
751
cb7a6892 752
dec38dac 753\f
d6103e8e 754/* ICU device: icu@<address>
cb7a6892 755
d6103e8e
MM
756 <address> : read - processor nr
757 <address> : write - interrupt processor nr
758 <address> + 4 : read - nr processors
759
760 Single byte registers that control a simple ICU.
cb7a6892
MM
761
762 Illustrates passing of events to parent device. Passing of
d6103e8e 763 interrupts to an interrupt destination. */
cb7a6892 764
cb7a6892 765
93fac324
MM
766static unsigned
767icu_io_read_buffer_callback(device *me,
dec38dac 768 void *dest,
5b4d72dd
MM
769 int space,
770 unsigned_word addr,
dec38dac
MM
771 unsigned nr_bytes,
772 cpu *processor,
773 unsigned_word cia)
cb7a6892 774{
1dc7c0ed 775 memset(dest, 0, nr_bytes);
d6103e8e
MM
776 switch (addr & 4) {
777 case 0:
778 *(unsigned_1*)dest = cpu_nr(processor);
779 break;
780 case 4:
781 *(unsigned_1*)dest =
782 device_find_integer_property(me, "/openprom/options/smp");
783 break;
784 }
dec38dac 785 return nr_bytes;
cb7a6892
MM
786}
787
dec38dac 788
93fac324
MM
789static unsigned
790icu_io_write_buffer_callback(device *me,
dec38dac 791 const void *source,
5b4d72dd
MM
792 int space,
793 unsigned_word addr,
dec38dac
MM
794 unsigned nr_bytes,
795 cpu *processor,
796 unsigned_word cia)
cb7a6892 797{
dec38dac 798 unsigned_1 val = H2T_1(*(unsigned_1*)source);
cb7a6892
MM
799 /* tell the parent device that the interrupt lines have changed.
800 For this fake ICU. The interrupt lines just indicate the cpu to
801 interrupt next */
d6103e8e
MM
802 device_interrupt_event(me,
803 val, /*my_port*/
804 val, /*val*/
805 processor, cia);
dec38dac 806 return nr_bytes;
cb7a6892
MM
807}
808
d6103e8e
MM
809static void
810icu_do_interrupt(event_queue *queue,
811 void *data)
812{
813 cpu *target = (cpu*)data;
814 /* try to interrupt the processor. If the attempt fails, try again
815 on the next tick */
816 if (!external_interrupt(target))
817 event_queue_schedule(queue, 1, icu_do_interrupt, target);
818}
819
820
821static void
822icu_interrupt_event_callback(device *me,
823 int my_port,
824 device *source,
825 int source_port,
826 int level,
827 cpu *processor,
828 unsigned_word cia)
829{
830 /* the interrupt controller can't interrupt a cpu at any time.
831 Rather it must synchronize with the system clock before
832 performing an interrupt on the given processor */
833 psim *system = cpu_system(processor);
834 cpu *target = psim_cpu(system, my_port);
835 if (target != NULL) {
836 event_queue *events = cpu_event_queue(target);
837 event_queue_schedule(events, 1, icu_do_interrupt, target);
838 }
839}
dec38dac
MM
840
841static device_callbacks const icu_callbacks = {
d6103e8e
MM
842 generic_device_init_address,
843 ignore_device_init,
dec38dac
MM
844 unimp_device_attach_address,
845 unimp_device_detach_address,
846 icu_io_read_buffer_callback,
847 icu_io_write_buffer_callback,
848 unimp_device_dma_read_buffer,
849 unimp_device_dma_write_buffer,
d6103e8e
MM
850 icu_interrupt_event_callback,
851 unimp_device_child_interrupt_event,
852 unimp_device_unit_decode,
853 unimp_device_unit_encode,
854 unimp_device_instance_create,
855 unimp_device_instance_delete,
856 unimp_device_instance_read,
857 unimp_device_instance_write,
858 unimp_device_instance_seek,
dec38dac
MM
859 unimp_device_ioctl,
860};
861
862
863\f
864/* HALT device: halt@0x<address>,4
865
866 With real hardware, the processor operation is normally terminated
867 through a reset. This device illustrates how a reset device could
868 be attached to an address */
869
870
93fac324
MM
871static unsigned
872halt_io_read_buffer_callback(device *me,
dec38dac 873 void *dest,
5b4d72dd
MM
874 int space,
875 unsigned_word addr,
dec38dac
MM
876 unsigned nr_bytes,
877 cpu *processor,
878 unsigned_word cia)
879{
880 cpu_halt(processor, cia, was_exited, 0);
881 return 0;
882}
883
884
93fac324
MM
885static unsigned
886halt_io_write_buffer_callback(device *me,
dec38dac 887 const void *source,
5b4d72dd 888 int space,
dec38dac
MM
889 unsigned_word addr,
890 unsigned nr_bytes,
891 cpu *processor,
892 unsigned_word cia)
893{
1dc7c0ed 894 cpu_halt(processor, cia, was_exited, *(unsigned_1*)source);
dec38dac
MM
895 return 0;
896}
897
898
899static device_callbacks const halt_callbacks = {
d6103e8e
MM
900 generic_device_init_address,
901 ignore_device_init,
dec38dac
MM
902 unimp_device_attach_address,
903 unimp_device_detach_address,
904 halt_io_read_buffer_callback,
905 halt_io_write_buffer_callback,
906 unimp_device_dma_read_buffer,
907 unimp_device_dma_write_buffer,
d6103e8e
MM
908 unimp_device_interrupt_event,
909 unimp_device_child_interrupt_event,
910 unimp_device_unit_decode,
911 unimp_device_unit_encode,
912 unimp_device_instance_create,
913 unimp_device_instance_delete,
914 unimp_device_instance_read,
915 unimp_device_instance_write,
916 unimp_device_instance_seek,
dec38dac
MM
917 unimp_device_ioctl,
918};
919
920
921\f
d6103e8e 922/* Register init device: register@<nothing>
dec38dac 923
93fac324 924 Properties attached to the register device specify the name/value
979c3c25
MM
925 initialization pair for cpu registers.
926
d6103e8e
MM
927 A specific processor can be initialized by creating a property with
928 a name like `0.pc'.
929
930 Properties are normally processed old-to-new and this function
931 needs to allow older (first in) properties to override new (last
932 in) ones. The suport function do_register_init() manages this. */
dec38dac 933
93fac324 934static void
d6103e8e
MM
935do_register_init(device *me,
936 psim *system,
937 const device_property *prop)
938{
939 if (prop != NULL) {
940 const char *name = prop->name;
941 unsigned32 value = device_find_integer_property(me, name);
942 int processor;
943
944 do_register_init(me, system, device_next_property(prop));
945
946 if (strchr(name, '.') == NULL) {
947 processor = -1;
948 DTRACE(register, ("%s=0x%lx\n", name, (unsigned long)value));
949 }
950 else {
951 char *end;
952 processor = strtoul(name, &end, 0);
953 ASSERT(end[0] == '.');
954 name = end+1;
955 DTRACE(register, ("%d.%s=0x%lx\n", processor, name,
956 (unsigned long)value));
957 }
958 psim_write_register(system, processor, /* all processors */
959 &value,
960 name,
961 cooked_transfer);
979c3c25 962 }
93fac324 963}
d6103e8e 964
93fac324
MM
965
966static void
d6103e8e
MM
967register_init_data_callback(device *me,
968 psim *system)
dec38dac 969{
d6103e8e
MM
970 const device_property *prop = device_find_property(me, NULL);
971 do_register_init(me, system, prop);
dec38dac
MM
972}
973
974
975static device_callbacks const register_callbacks = {
d6103e8e
MM
976 ignore_device_init,
977 register_init_data_callback,
dec38dac
MM
978 unimp_device_attach_address,
979 unimp_device_detach_address,
980 unimp_device_io_read_buffer,
981 unimp_device_io_write_buffer,
982 unimp_device_dma_read_buffer,
983 unimp_device_dma_write_buffer,
d6103e8e
MM
984 unimp_device_interrupt_event,
985 unimp_device_child_interrupt_event,
986 unimp_device_unit_decode,
987 unimp_device_unit_encode,
988 unimp_device_instance_create,
989 unimp_device_instance_delete,
990 unimp_device_instance_read,
991 unimp_device_instance_write,
992 unimp_device_instance_seek,
dec38dac
MM
993 unimp_device_ioctl,
994};
995
996
997\f
d6103e8e
MM
998/* Trace device:
999
1000 Properties attached to the trace device are names and values for
1001 the various trace variables. When initialized trace goes through
1002 the propertie and sets the global trace variables so that they
1003 match what was specified in the device tree. */
1004
1005static void
1006trace_init_data_callback(device *me,
1007 psim *system)
1008{
1009 const device_property *prop = device_find_property(me, NULL);
1010 while (prop != NULL) {
1011 const char *name = prop->name;
1012 unsigned32 value = device_find_integer_property(me, name);
1013 trace_option(name, value);
1014 prop = device_next_property(prop);
1015 }
1016}
1017
1018
1019static device_callbacks const trace_callbacks = {
1020 ignore_device_init,
1021 trace_init_data_callback,
1022 unimp_device_attach_address,
1023 unimp_device_detach_address,
1024 unimp_device_io_read_buffer,
1025 unimp_device_io_write_buffer,
1026 unimp_device_dma_read_buffer,
1027 unimp_device_dma_write_buffer,
1028 unimp_device_interrupt_event,
1029 unimp_device_child_interrupt_event,
1030 unimp_device_unit_decode,
1031 unimp_device_unit_encode,
1032 unimp_device_instance_create,
1033 unimp_device_instance_delete,
1034 unimp_device_instance_read,
1035 unimp_device_instance_write,
1036 unimp_device_instance_seek,
1037 unimp_device_ioctl,
1038};
1039
1040
1041\f
1042/* VEA VM:
1043
1044 vm@<stack-base>
1045 stack-base =
1046 nr-bytes =
dec38dac
MM
1047
1048 A VEA mode device. This sets its self up as the default memory
1049 device capturing all accesses (reads/writes) to currently unmapped
1050 addresses. If the unmaped access falls within unallocated stack or
1051 heap address ranges then memory is allocated and the access is
1052 allowed to continue.
1053
1054 During init phase, this device expects to receive `attach' requests
1055 from its children for the text/data/bss memory areas. Typically,
1056 this would be done by the binary device.
1057
1058 STACK: The location of the stack in memory is specified as part of
1059 the devices name. Unmaped accesses that fall within the stack
1060 space result in the allocated stack being grown downwards so that
1061 it includes the page of the culprit access.
1062
1063 HEAP: During initialization, the vm device monitors all `attach'
1064 operations from its children using this to determine the initial
1065 location of the heap. The heap is then extended by system calls
1066 that frob the heap upper bound variable (see system.c). */
1067
1068
1069typedef struct _vm_device {
1070 /* area of memory valid for stack addresses */
1071 unsigned_word stack_base; /* min possible stack value */
1072 unsigned_word stack_bound;
1073 unsigned_word stack_lower_limit;
1074 /* area of memory valid for heap addresses */
1075 unsigned_word heap_base;
1076 unsigned_word heap_bound;
1077 unsigned_word heap_upper_limit;
1078} vm_device;
1079
1080
93fac324 1081static void
d6103e8e
MM
1082vm_init_address_callback(device *me,
1083 psim *system)
dec38dac 1084{
93fac324 1085 vm_device *vm = (vm_device*)device_data(me);
dec38dac
MM
1086
1087 /* revert the stack/heap variables to their defaults */
d6103e8e
MM
1088 vm->stack_base = device_find_integer_property(me, "stack-base");
1089 vm->stack_bound = (vm->stack_base
1090 + device_find_integer_property(me, "nr-bytes"));
dec38dac
MM
1091 vm->stack_lower_limit = vm->stack_bound;
1092 vm->heap_base = 0;
1093 vm->heap_bound = 0;
1094 vm->heap_upper_limit = 0;
1095
1096 /* establish this device as the default memory handler */
93fac324
MM
1097 device_attach_address(device_parent(me),
1098 device_name(me),
1099 attach_default,
1100 0 /*address space - ignore*/,
1101 0 /*addr - ignore*/,
1102 0 /*nr_bytes - ignore*/,
1103 access_read_write /*access*/,
1104 me);
dec38dac
MM
1105}
1106
1107
93fac324
MM
1108static void
1109vm_attach_address(device *me,
dec38dac 1110 const char *name,
5b4d72dd
MM
1111 attach_type attach,
1112 int space,
dec38dac
MM
1113 unsigned_word addr,
1114 unsigned nr_bytes,
1115 access_type access,
93fac324 1116 device *who) /*callback/default*/
dec38dac 1117{
93fac324 1118 vm_device *vm = (vm_device*)device_data(me);
dec38dac
MM
1119 /* update end of bss if necessary */
1120 if (vm->heap_base < addr + nr_bytes) {
1121 vm->heap_base = addr + nr_bytes;
1122 vm->heap_bound = addr + nr_bytes;
1123 vm->heap_upper_limit = addr + nr_bytes;
1124 }
93fac324
MM
1125 device_attach_address(device_parent(me),
1126 "vm@0x0,0", /* stop remap */
1127 attach_raw_memory,
1128 0 /*address space*/,
1129 addr,
1130 nr_bytes,
1131 access,
1132 me);
dec38dac
MM
1133}
1134
1135
93fac324
MM
1136STATIC_INLINE_DEVICE_TABLE unsigned
1137add_vm_space(device *me,
dec38dac
MM
1138 unsigned_word addr,
1139 unsigned nr_bytes,
1140 cpu *processor,
1141 unsigned_word cia)
1142{
93fac324 1143 vm_device *vm = (vm_device*)device_data(me);
dec38dac
MM
1144 unsigned_word block_addr;
1145 unsigned block_nr_bytes;
1146
1147 /* an address in the stack area, allocate just down to the addressed
1148 page */
1149 if (addr >= vm->stack_base && addr < vm->stack_lower_limit) {
1150 block_addr = FLOOR_PAGE(addr);
1151 block_nr_bytes = vm->stack_lower_limit - block_addr;
1152 vm->stack_lower_limit = block_addr;
1153 }
1154 /* an address in the heap area, allocate all of the required heap */
1155 else if (addr >= vm->heap_upper_limit && addr < vm->heap_bound) {
1156 block_addr = vm->heap_upper_limit;
1157 block_nr_bytes = vm->heap_bound - vm->heap_upper_limit;
1158 vm->heap_upper_limit = vm->heap_bound;
1159 }
1160 /* oops - an invalid address - abort the cpu */
1161 else if (processor != NULL) {
1162 cpu_halt(processor, cia, was_signalled, SIGSEGV);
1163 return 0;
1164 }
1165 /* 2*oops - an invalid address and no processor */
1166 else {
1167 return 0;
1168 }
1169
1170 /* got the parameters, allocate the space */
93fac324
MM
1171 device_attach_address(device_parent(me),
1172 "vm@0x0,0", /* stop remap */
1173 attach_raw_memory,
1174 0 /*address space*/,
1175 block_addr,
1176 block_nr_bytes,
1177 access_read_write,
1178 me);
dec38dac
MM
1179 return block_nr_bytes;
1180}
1181
1182
93fac324
MM
1183static unsigned
1184vm_io_read_buffer_callback(device *me,
dec38dac 1185 void *dest,
5b4d72dd 1186 int space,
dec38dac
MM
1187 unsigned_word addr,
1188 unsigned nr_bytes,
1189 cpu *processor,
1190 unsigned_word cia)
1191{
1192 if (add_vm_space(me, addr, nr_bytes, processor, cia) >= nr_bytes) {
1dc7c0ed 1193 memset(dest, 0, nr_bytes); /* always initialized to zero */
dec38dac
MM
1194 return nr_bytes;
1195 }
1196 else
1197 return 0;
1198}
1199
1200
93fac324
MM
1201static unsigned
1202vm_io_write_buffer_callback(device *me,
dec38dac 1203 const void *source,
5b4d72dd 1204 int space,
dec38dac
MM
1205 unsigned_word addr,
1206 unsigned nr_bytes,
1207 cpu *processor,
1208 unsigned_word cia)
1209{
1210 if (add_vm_space(me, addr, nr_bytes, processor, cia) >= nr_bytes) {
93fac324
MM
1211 return device_dma_write_buffer(device_parent(me), source,
1212 space, addr,
1213 nr_bytes,
1214 0/*violate_read_only*/);
dec38dac
MM
1215 }
1216 else
1217 return 0;
1218}
1219
1220
8e20a3ac 1221static void
93fac324 1222vm_ioctl_callback(device *me,
dec38dac
MM
1223 psim *system,
1224 cpu *processor,
1225 unsigned_word cia,
93fac324 1226 va_list ap)
dec38dac
MM
1227{
1228 /* While the caller is notified that the heap has grown by the
1229 requested amount, the heap is infact extended out to a page
1230 boundary. */
93fac324 1231 vm_device *vm = (vm_device*)device_data(me);
dec38dac
MM
1232 unsigned_word new_break = ALIGN_8(cpu_registers(processor)->gpr[3]);
1233 unsigned_word old_break = vm->heap_bound;
1234 signed_word delta = new_break - old_break;
1235 if (delta > 0)
1236 vm->heap_bound = ALIGN_PAGE(new_break);
1237 cpu_registers(processor)->gpr[0] = 0;
1238 cpu_registers(processor)->gpr[3] = new_break;
1239}
1240
1241
1242static device_callbacks const vm_callbacks = {
d6103e8e
MM
1243 vm_init_address_callback,
1244 ignore_device_init,
dec38dac 1245 vm_attach_address,
93fac324 1246 passthrough_device_detach_address,
dec38dac
MM
1247 vm_io_read_buffer_callback,
1248 vm_io_write_buffer_callback,
1249 unimp_device_dma_read_buffer,
93fac324 1250 passthrough_device_dma_write_buffer,
d6103e8e
MM
1251 unimp_device_interrupt_event,
1252 unimp_device_child_interrupt_event,
1253 generic_device_unit_decode,
1254 generic_device_unit_encode,
1255 unimp_device_instance_create,
1256 unimp_device_instance_delete,
1257 unimp_device_instance_read,
1258 unimp_device_instance_write,
1259 unimp_device_instance_seek,
dec38dac
MM
1260 vm_ioctl_callback,
1261};
1262
1263
93fac324 1264static void *
dec38dac 1265vea_vm_create(const char *name,
d6103e8e
MM
1266 const device_unit *address,
1267 const char *args,
93fac324 1268 device *parent)
dec38dac
MM
1269{
1270 vm_device *vm = ZALLOC(vm_device);
93fac324 1271 return vm;
dec38dac
MM
1272}
1273
1274
1275\f
d6103e8e 1276/* Memory init device: memory@0x<addr>
dec38dac
MM
1277
1278 This strange device is used create sections of memory */
1279
93fac324 1280static void
d6103e8e
MM
1281memory_init_address_callback(device *me,
1282 psim *system)
1283{
1284 const device_property *reg = device_find_array_property(me, "reg");
1285 const reg_spec *spec = reg->array;
1286 int nr_entries = reg->sizeof_array / sizeof(*spec);
1287
1288 if ((reg->sizeof_array % sizeof(*spec)) != 0)
1289 error("devices/%s reg property of incorrect size\n", device_name(me));
1290 while (nr_entries > 0) {
1291 device_attach_address(device_parent(me),
1292 device_name(me),
1293 attach_raw_memory,
1294 0 /*address space*/,
1295 BE2H_4(spec->base),
1296 BE2H_4(spec->size),
1297 access_read_write_exec,
1298 me);
1299 spec++;
1300 nr_entries--;
5b4d72dd 1301 }
d6103e8e 1302}
dec38dac 1303
d6103e8e
MM
1304static void *
1305memory_instance_create_callback(device *me,
1306 const char *args)
1307{
1308 return me; /* for want of any thing better */
dec38dac
MM
1309}
1310
d6103e8e
MM
1311static void
1312memory_instance_delete_callback(device_instance *instance)
1313{
1314 return;
1315}
dec38dac
MM
1316
1317static device_callbacks const memory_callbacks = {
d6103e8e
MM
1318 memory_init_address_callback,
1319 ignore_device_init,
dec38dac
MM
1320 unimp_device_attach_address,
1321 unimp_device_detach_address,
1322 unimp_device_io_read_buffer,
1323 unimp_device_io_write_buffer,
1324 unimp_device_dma_read_buffer,
1325 unimp_device_dma_write_buffer,
d6103e8e
MM
1326 unimp_device_interrupt_event,
1327 unimp_device_child_interrupt_event,
1328 unimp_device_unit_decode,
1329 unimp_device_unit_encode,
1330 memory_instance_create_callback,
1331 memory_instance_delete_callback,
1332 unimp_device_instance_read,
1333 unimp_device_instance_write,
1334 unimp_device_instance_seek,
dec38dac
MM
1335 unimp_device_ioctl,
1336};
1337
1338
dec38dac
MM
1339\f
1340/* IOBUS device: iobus@<address>
1341
1342 Simple bus on which some IO devices live */
1343
93fac324
MM
1344static void
1345iobus_attach_address_callback(device *me,
dec38dac
MM
1346 const char *name,
1347 attach_type type,
5b4d72dd 1348 int space,
dec38dac
MM
1349 unsigned_word addr,
1350 unsigned nr_bytes,
1351 access_type access,
93fac324 1352 device *who) /*callback/default*/
dec38dac
MM
1353{
1354 unsigned_word iobus_addr;
1355 /* sanity check */
1356 if (type == attach_default)
1357 error("iobus_attach_address_callback() no default for %s/%s\n",
93fac324 1358 device_name(me), name);
5b4d72dd
MM
1359 if (space != 0)
1360 error("iobus_attach_address_callback() no space for %s/%s\n",
93fac324 1361 device_name(me), name);
dec38dac 1362 /* get the bus address */
d6103e8e 1363 if (device_unit_address(me)->nr_cells != 1)
dec38dac 1364 error("iobus_attach_address_callback() invalid address for %s\n",
93fac324 1365 device_name(me));
d6103e8e 1366 iobus_addr = device_unit_address(me)->cells[0];
93fac324
MM
1367 device_attach_address(device_parent(me),
1368 device_name(me),
1369 type,
1370 0 /*space*/,
1371 iobus_addr + addr,
1372 nr_bytes,
1373 access,
1374 who);
dec38dac
MM
1375}
1376
1377
dec38dac 1378static device_callbacks const iobus_callbacks = {
d6103e8e 1379 ignore_device_init,
dec38dac
MM
1380 ignore_device_init,
1381 iobus_attach_address_callback,
1382 unimp_device_detach_address,
1383 unimp_device_io_read_buffer,
1384 unimp_device_io_write_buffer,
1385 unimp_device_dma_read_buffer,
1386 unimp_device_dma_write_buffer,
d6103e8e
MM
1387 unimp_device_interrupt_event,
1388 unimp_device_child_interrupt_event,
1389 generic_device_unit_decode,
1390 generic_device_unit_encode,
1391 unimp_device_instance_create,
1392 unimp_device_instance_delete,
1393 unimp_device_instance_read,
1394 unimp_device_instance_write,
1395 unimp_device_instance_seek,
dec38dac 1396 unimp_device_ioctl,
cb7a6892
MM
1397};
1398
dec38dac
MM
1399
1400\f
1401/* FILE device: file@0x<address>,<file-name>
1402 (later - file@0x<address>,<size>,<file-offset>,<file-name>)
1403
1404 Specifies a file to read directly into memory starting at <address> */
1405
1406
93fac324 1407static void
d6103e8e
MM
1408file_init_data_callback(device *me,
1409 psim *system)
cb7a6892 1410{
1dc7c0ed 1411 int count;
d6103e8e
MM
1412 const char *file_name = device_find_string_property(me, "file-name");
1413 unsigned_word addr = device_find_integer_property(me, "real-address");
1dc7c0ed
MM
1414 /* load the file */
1415 count = dma_file(me, file_name, addr);
1416 if (count < 0)
d6103e8e
MM
1417 error("device_table/%s - Problem loading file %s\n",
1418 device_name(me), file_name);
dec38dac 1419}
cb7a6892 1420
cb7a6892 1421
dec38dac 1422static device_callbacks const file_callbacks = {
d6103e8e
MM
1423 ignore_device_init,
1424 file_init_data_callback,
dec38dac
MM
1425 unimp_device_attach_address,
1426 unimp_device_detach_address,
1427 unimp_device_io_read_buffer,
1428 unimp_device_io_write_buffer,
1429 unimp_device_dma_read_buffer,
1430 unimp_device_dma_write_buffer,
d6103e8e
MM
1431 unimp_device_interrupt_event,
1432 unimp_device_child_interrupt_event,
1433 unimp_device_unit_decode,
1434 unimp_device_unit_encode,
1435 unimp_device_instance_create,
1436 unimp_device_instance_delete,
1437 unimp_device_instance_read,
1438 unimp_device_instance_write,
1439 unimp_device_instance_seek,
dec38dac
MM
1440 unimp_device_ioctl,
1441};
1442
1443
93fac324 1444\f
d6103e8e
MM
1445/* DATA device: data@<address>
1446
1447 <data> - property containing the value to store
1448 <real-address> - address to store data at
93fac324 1449
d6103e8e 1450 Store <data> at <address> using approperiate byte order */
93fac324
MM
1451
1452static void
d6103e8e
MM
1453data_init_data_callback(device *me,
1454 psim *system)
93fac324 1455{
d6103e8e
MM
1456 unsigned_word addr = device_find_integer_property(me, "real-address");
1457 const device_property *data = device_find_property(me, "data");
1458 if (data == NULL)
1459 error("devices/data - missing data property\n");
1460 switch (data->type) {
1461 case integer_property:
1462 {
1463 unsigned32 buf = device_find_integer_property(me, "data");
1464 H2T(buf);
1465 if (device_dma_write_buffer(device_parent(me),
1466 &buf,
1467 0 /*address-space*/,
1468 addr,
1469 sizeof(buf), /*nr-bytes*/
1470 1 /*violate ro*/) != sizeof(buf))
1471 error("devices/%s - Problem storing integer 0x%x at 0x%lx\n",
1472 device_name(me), (long)buf, (unsigned long)addr);
1473 }
93fac324 1474 break;
d6103e8e
MM
1475 default:
1476 error("devices/%s - write of this data is not yet implemented\n", device_name(me));
93fac324
MM
1477 break;
1478 }
93fac324
MM
1479}
1480
1481
1482static device_callbacks const data_callbacks = {
d6103e8e
MM
1483 ignore_device_init,
1484 data_init_data_callback,
93fac324
MM
1485 unimp_device_attach_address,
1486 unimp_device_detach_address,
1487 unimp_device_io_read_buffer,
1488 unimp_device_io_write_buffer,
1489 unimp_device_dma_read_buffer,
1490 unimp_device_dma_write_buffer,
d6103e8e
MM
1491 unimp_device_interrupt_event,
1492 unimp_device_child_interrupt_event,
1493 unimp_device_unit_decode,
1494 unimp_device_unit_encode,
1495 unimp_device_instance_create,
1496 unimp_device_instance_delete,
1497 unimp_device_instance_read,
1498 unimp_device_instance_write,
1499 unimp_device_instance_seek,
93fac324
MM
1500 unimp_device_ioctl,
1501};
1502
1503
dec38dac 1504\f
d6103e8e
MM
1505/* HTAB:
1506
1507 htab@<real-address>
1508 real-address =
1509 nr-bytes =
1510
1511 pte@<real-address>
1512 real-address =
1513 virtual-address =
1514 nr-bytes =
1515 wimg =
1516 pp =
1517
1518 pte@<real-address>
1519 real-address =
1520 file-name =
1521 wimg =
1522 pp =
1523
dec38dac
MM
1524 HTAB defines the location (in physical memory) of a HASH table.
1525 PTE (as a child of HTAB) defines a mapping that is to be entered
1526 into that table.
1527
1528 NB: All the work in this device is done during init by the PTE.
1529 The pte, looks up its parent to determine the address of the HTAB
1530 and then uses DMA calls to establish the required mapping. */
1531
93fac324
MM
1532STATIC_INLINE_DEVICE_TABLE void
1533htab_decode_hash_table(device *parent,
1534 unsigned32 *htaborg,
1535 unsigned32 *htabmask)
1536{
1537 unsigned_word htab_ra;
1538 unsigned htab_nr_bytes;
1539 unsigned n;
1540 /* determine the location/size of the hash table */
1541 if (parent == NULL
d6103e8e
MM
1542 || strcmp(device_name(parent), "htab") != 0)
1543 error("devices/htab - missing htab parent device\n");
1544 htab_ra = device_find_integer_property(parent, "real-address");
1545 htab_nr_bytes = device_find_integer_property(parent, "nr-bytes");
93fac324
MM
1546 for (n = htab_nr_bytes; n > 1; n = n / 2) {
1547 if (n % 2 != 0)
1548 error("devices/%s - htab size 0x%x not a power of two\n",
1549 device_name(parent), htab_nr_bytes);
1550 }
1551 *htaborg = htab_ra;
1552 *htabmask = MASKED32(htab_nr_bytes - 1, 7, 31-6);
1553 if ((htab_ra & INSERTED32(*htabmask, 7, 15)) != 0) {
1554 error("devices/%s - htaborg 0x%x not aligned to htabmask 0x%x\n",
1555 device_name(parent), *htaborg, *htabmask);
1556 }
979c3c25
MM
1557 DTRACE(htab, ("htab - htaborg=0x%lx htabmask=0x%lx\n",
1558 (unsigned long)*htaborg, (unsigned long)*htabmask));
93fac324
MM
1559}
1560
93fac324
MM
1561STATIC_INLINE void
1562htab_map_page(device *me,
1563 unsigned_word ra,
1564 unsigned64 va,
1565 unsigned wimg,
1566 unsigned pp,
1567 unsigned32 htaborg,
1568 unsigned32 htabmask)
1569{
1570 unsigned64 vpn = va << 12;
1571 unsigned32 vsid = INSERTED32(EXTRACTED64(vpn, 0, 23), 0, 23);
1572 unsigned32 page = INSERTED32(EXTRACTED64(vpn, 24, 39), 0, 15);
1573 unsigned32 hash = INSERTED32(EXTRACTED32(vsid, 5, 23)
1574 ^ EXTRACTED32(page, 0, 15),
1575 7, 31-6);
1576 int h;
1577 for (h = 0; h < 2; h++) {
1578 unsigned32 pteg = (htaborg | (hash & htabmask));
1579 int pti;
1580 for (pti = 0; pti < 8; pti++, pteg += 8) {
979c3c25
MM
1581 unsigned32 current_target_pte0;
1582 unsigned32 current_pte0;
93fac324 1583 if (device_dma_read_buffer(device_parent(me),
979c3c25 1584 &current_target_pte0,
93fac324
MM
1585 0, /*space*/
1586 pteg,
979c3c25 1587 sizeof(current_target_pte0)) != 4)
93fac324
MM
1588 error("htab_init_callback() failed to read a pte at 0x%x\n",
1589 pteg);
979c3c25
MM
1590 current_pte0 = T2H_4(current_target_pte0);
1591 if (!MASKED32(current_pte0, 0, 0)) {
93fac324
MM
1592 /* empty pte fill it */
1593 unsigned32 pte0 = (MASK32(0, 0)
1594 | INSERTED32(EXTRACTED32(vsid, 0, 23), 1, 24)
1595 | INSERTED32(h, 25, 25)
1596 | INSERTED32(EXTRACTED32(page, 0, 5), 26, 31));
979c3c25 1597 unsigned32 target_pte0 = H2T_4(pte0);
93fac324
MM
1598 unsigned32 pte1 = (INSERTED32(EXTRACTED32(ra, 0, 19), 0, 19)
1599 | INSERTED32(wimg, 25, 28)
1600 | INSERTED32(pp, 30, 31));
979c3c25 1601 unsigned32 target_pte1 = H2T_4(pte1);
93fac324 1602 if (device_dma_write_buffer(device_parent(me),
979c3c25 1603 &target_pte0,
93fac324
MM
1604 0, /*space*/
1605 pteg,
979c3c25 1606 sizeof(target_pte0),
93fac324
MM
1607 1/*ro?*/) != 4
1608 || device_dma_write_buffer(device_parent(me),
979c3c25 1609 &target_pte1,
93fac324
MM
1610 0, /*space*/
1611 pteg + 4,
979c3c25 1612 sizeof(target_pte1),
93fac324
MM
1613 1/*ro?*/) != 4)
1614 error("htab_init_callback() failed to write a pte a 0x%x\n",
1615 pteg);
1616 DTRACE(htab, ("map - va=0x%lx ra=0x%lx &pte0=0x%lx pte0=0x%lx pte1=0x%lx\n",
1617 (unsigned long)va, (unsigned long)ra,
1618 (unsigned long)pteg,
1619 (unsigned long)pte0, (unsigned long)pte1));
1620 return;
1621 }
1622 }
1623 /* re-hash */
1624 hash = MASKED32(~hash, 0, 18);
1625 }
1626}
1627
1628STATIC_INLINE_DEVICE_TABLE void
1629htab_map_region(device *me,
1630 unsigned_word pte_ra,
1631 unsigned_word pte_va,
1632 unsigned nr_bytes,
1633 unsigned wimg,
1634 unsigned pp,
1635 unsigned32 htaborg,
1636 unsigned32 htabmask)
1637{
1638 unsigned_word ra;
1639 unsigned64 va;
1640 /* go through all pages and create a pte for each */
1641 for (ra = pte_ra, va = (signed_word)pte_va;
1642 ra < pte_ra + nr_bytes;
1643 ra += 0x1000, va += 0x1000) {
1644 htab_map_page(me, ra, va, wimg, pp, htaborg, htabmask);
1645 }
1646}
1647
1648typedef struct _htab_binary_sizes {
1649 unsigned_word text_ra;
1650 unsigned_word text_base;
1651 unsigned_word text_bound;
1652 unsigned_word data_ra;
1653 unsigned_word data_base;
1654 unsigned data_bound;
1655 device *me;
1656} htab_binary_sizes;
1657
1658STATIC_INLINE_DEVICE_TABLE void
1659htab_sum_binary(bfd *abfd,
1660 sec_ptr sec,
1661 PTR data)
1662{
1663 htab_binary_sizes *sizes = (htab_binary_sizes*)data;
1664 unsigned_word size = bfd_get_section_size_before_reloc (sec);
1665 unsigned_word vma = bfd_get_section_vma (abfd, sec);
1666
1667 /* skip the section if no memory to allocate */
1668 if (! (bfd_get_section_flags(abfd, sec) & SEC_ALLOC))
1669 return;
1670
1671 if ((bfd_get_section_flags (abfd, sec) & SEC_CODE)
1672 || (bfd_get_section_flags (abfd, sec) & SEC_READONLY)) {
1673 if (sizes->text_bound < vma + size)
1674 sizes->text_bound = ALIGN_PAGE(vma + size);
1675 if (sizes->text_base > vma)
1676 sizes->text_base = FLOOR_PAGE(vma);
1677 }
1678 else if ((bfd_get_section_flags (abfd, sec) & SEC_DATA)
1679 || (bfd_get_section_flags (abfd, sec) & SEC_ALLOC)) {
1680 if (sizes->data_bound < vma + size)
1681 sizes->data_bound = ALIGN_PAGE(vma + size);
1682 if (sizes->data_base > vma)
1683 sizes->data_base = FLOOR_PAGE(vma);
1684 }
1685}
1686
1687STATIC_INLINE_DEVICE_TABLE void
1688htab_dma_binary(bfd *abfd,
1689 sec_ptr sec,
1690 PTR data)
1691{
1692 htab_binary_sizes *sizes = (htab_binary_sizes*)data;
1693 void *section_init;
1694 unsigned_word section_vma;
1695 unsigned_word section_size;
1696 unsigned_word section_ra;
1697 device *me = sizes->me;
1698
1699 /* skip the section if no memory to allocate */
1700 if (! (bfd_get_section_flags(abfd, sec) & SEC_ALLOC))
1701 return;
1702
1703 /* check/ignore any sections of size zero */
1704 section_size = bfd_get_section_size_before_reloc(sec);
1705 if (section_size == 0)
1706 return;
1707
1708 /* if nothing to load, ignore this one */
1709 if (! (bfd_get_section_flags(abfd, sec) & SEC_LOAD))
1710 return;
1711
1712 /* find where it is to go */
1713 section_vma = bfd_get_section_vma(abfd, sec);
1714 section_ra = 0;
1715 if ((bfd_get_section_flags (abfd, sec) & SEC_CODE)
1716 || (bfd_get_section_flags (abfd, sec) & SEC_READONLY))
1717 section_ra = (section_vma - sizes->text_base + sizes->text_ra);
1718 else if ((bfd_get_section_flags (abfd, sec) & SEC_DATA))
1719 section_ra = (section_vma - sizes->data_base + sizes->data_ra);
1720 else
1721 return; /* just ignore it */
1722
1723 DTRACE(htab,
1724 ("load - name=%-7s vma=0x%.8lx size=%6ld ra=0x%.8lx flags=%3lx(%s%s%s%s%s )\n",
1725 bfd_get_section_name(abfd, sec),
1726 (long)section_vma,
1727 (long)section_size,
1728 (long)section_ra,
1729 (long)bfd_get_section_flags(abfd, sec),
1730 bfd_get_section_flags(abfd, sec) & SEC_LOAD ? " LOAD" : "",
1731 bfd_get_section_flags(abfd, sec) & SEC_CODE ? " CODE" : "",
1732 bfd_get_section_flags(abfd, sec) & SEC_DATA ? " DATA" : "",
1733 bfd_get_section_flags(abfd, sec) & SEC_ALLOC ? " ALLOC" : "",
1734 bfd_get_section_flags(abfd, sec) & SEC_READONLY ? " READONLY" : ""
1735 ));
1736
1737 /* dma in the sections data */
1738 section_init = zalloc(section_size);
1739 if (!bfd_get_section_contents(abfd,
1740 sec,
1741 section_init, 0,
1742 section_size)) {
1743 bfd_perror("devices/pte");
1744 error("devices/%s - no data loaded\n", device_name(me));
1745 }
1746 if (device_dma_write_buffer(device_parent(me),
1747 section_init,
1748 0 /*space*/,
1749 section_ra,
1750 section_size,
1751 1 /*violate_read_only*/)
1752 != section_size)
1753 error("devices/%s - broken dma transfer\n", device_name(me));
1754 zfree(section_init); /* only free if load */
1755}
1756
93fac324
MM
1757STATIC_INLINE_DEVICE_TABLE void
1758htab_map_binary(device *me,
1759 unsigned_word ra,
1760 unsigned wimg,
1761 unsigned pp,
d6103e8e 1762 const char *file_name,
93fac324
MM
1763 unsigned32 htaborg,
1764 unsigned32 htabmask)
1765{
1766 htab_binary_sizes sizes;
1767 bfd *image;
1768 sizes.text_base = -1;
1769 sizes.data_base = -1;
1770 sizes.text_bound = 0;
1771 sizes.data_bound = 0;
1772 sizes.me = me;
1773
1774 /* open the file */
1775 image = bfd_openr(file_name, NULL);
1776 if (image == NULL) {
1777 bfd_perror("devices/pte");
1778 error("devices/%s - the file %s not loaded\n", device_name(me), file_name);
1779 }
1780
1781 /* check it is valid */
1782 if (!bfd_check_format(image, bfd_object)) {
1783 bfd_close(image);
1784 error("devices/%s - the file %s has an invalid binary format\n",
1785 device_name(me), file_name);
1786 }
1787
1788 /* determine the size of each of the files regions */
1789 bfd_map_over_sections (image, htab_sum_binary, (PTR) &sizes);
1790
1791 /* determine the real addresses of the sections */
1792 sizes.text_ra = ra;
1793 sizes.data_ra = ALIGN_PAGE(sizes.text_ra +
1794 (sizes.text_bound - sizes.text_base));
1795
1796 DTRACE(htab, ("text map - base=0x%lx bound=0x%lx ra=0x%lx\n",
979c3c25
MM
1797 (unsigned long)sizes.text_base,
1798 (unsigned long)sizes.text_bound,
1799 (unsigned long)sizes.text_ra));
93fac324 1800 DTRACE(htab, ("data map - base=0x%lx bound=0x%lx ra=0x%lx\n",
979c3c25
MM
1801 (unsigned long)sizes.data_base,
1802 (unsigned long)sizes.data_bound,
1803 (unsigned long)sizes.data_ra));
93fac324
MM
1804
1805 /* set up virtual memory maps for each of the regions */
1806 htab_map_region(me, sizes.text_ra, sizes.text_base,
1807 sizes.text_bound - sizes.text_base,
1808 wimg, pp,
1809 htaborg, htabmask);
1810 htab_map_region(me, sizes.data_ra, sizes.data_base,
1811 sizes.data_bound - sizes.data_base,
1812 wimg, pp,
1813 htaborg, htabmask);
1814
1815 /* dma the sections into physical memory */
1816 bfd_map_over_sections (image, htab_dma_binary, (PTR) &sizes);
1817}
1818
1819static void
d6103e8e
MM
1820htab_init_data_callback(device *me,
1821 psim *system)
dec38dac 1822{
1dc7c0ed
MM
1823 if (WITH_TARGET_WORD_BITSIZE != 32)
1824 error("devices/htab: only 32bit targets currently suported\n");
93fac324 1825
dec38dac 1826 /* only the pte does work */
d6103e8e 1827 if (strcmp(device_name(me), "pte") == 0) {
93fac324
MM
1828 unsigned32 htaborg;
1829 unsigned32 htabmask;
1dc7c0ed 1830
93fac324 1831 htab_decode_hash_table(device_parent(me), &htaborg, &htabmask);
1dc7c0ed 1832
d6103e8e
MM
1833 if (device_find_property(me, "file-name") != NULL) {
1834 /* map in a binary */
1835 unsigned32 pte_ra = device_find_integer_property(me, "real-address");
1836 unsigned pte_wimg = device_find_integer_property(me, "wimg");
1837 unsigned pte_pp = device_find_integer_property(me, "pp");
1838 const char *file_name = device_find_string_property(me, "file-name");
1839 DTRACE(htab, ("pte - ra=0x%lx, wimg=%ld, pp=%ld, file-name=%s\n",
979c3c25
MM
1840 (unsigned long)pte_ra,
1841 (unsigned long)pte_wimg,
1842 (long)pte_pp,
1843 file_name));
93fac324
MM
1844 htab_map_binary(me, pte_ra, pte_wimg, pte_pp, file_name,
1845 htaborg, htabmask);
1846 }
1847 else {
d6103e8e
MM
1848 /* handle a normal mapping definition */
1849 /* so that 0xff...0 is make 0xffffff00 */
1850 signed32 pte_va = device_find_integer_property(me, "virtual-address");
1851 unsigned32 pte_ra = device_find_integer_property(me, "real-address");
1852 unsigned pte_nr_bytes = device_find_integer_property(me, "nr-bytes");
1853 unsigned pte_wimg = device_find_integer_property(me, "wimg");
1854 unsigned pte_pp = device_find_integer_property(me, "pp");
1855 DTRACE(htab, ("pte - ra=0x%lx, wimg=%ld, pp=%ld, va=0x%lx, nr_bytes=%ld\n",
1856 (unsigned long)pte_ra,
1857 (long)pte_wimg,
1858 (long)pte_pp,
1859 (unsigned long)pte_va,
1860 (long)pte_nr_bytes));
1861 htab_map_region(me, pte_ra, pte_va, pte_nr_bytes, pte_wimg, pte_pp,
1862 htaborg, htabmask);
1dc7c0ed 1863 }
dec38dac 1864 }
cb7a6892
MM
1865}
1866
dec38dac
MM
1867
1868static device_callbacks const htab_callbacks = {
d6103e8e
MM
1869 ignore_device_init,
1870 htab_init_data_callback,
dec38dac
MM
1871 unimp_device_attach_address,
1872 unimp_device_detach_address,
1873 unimp_device_io_read_buffer,
1874 unimp_device_io_write_buffer,
93fac324
MM
1875 passthrough_device_dma_read_buffer,
1876 passthrough_device_dma_write_buffer,
d6103e8e
MM
1877 unimp_device_interrupt_event,
1878 unimp_device_child_interrupt_event,
1879 generic_device_unit_decode,
1880 generic_device_unit_encode,
1881 unimp_device_instance_create,
1882 unimp_device_instance_delete,
1883 unimp_device_instance_read,
1884 unimp_device_instance_write,
1885 unimp_device_instance_seek,
dec38dac
MM
1886 unimp_device_ioctl,
1887};
cb7a6892
MM
1888
1889
dec38dac 1890\f
93fac324 1891/* Load device: binary
cb7a6892 1892
93fac324
MM
1893 Single property the name of which specifies the file (understood by
1894 BFD) that is to be DMAed into memory as part of init */
cb7a6892 1895
93fac324 1896STATIC_INLINE_DEVICE_TABLE void
5b4d72dd
MM
1897update_for_binary_section(bfd *abfd,
1898 asection *the_section,
1899 PTR obj)
cb7a6892 1900{
dec38dac
MM
1901 unsigned_word section_vma;
1902 unsigned_word section_size;
1903 access_type access;
1904 device *me = (device*)obj;
1905
1906 /* skip the section if no memory to allocate */
1907 if (! (bfd_get_section_flags(abfd, the_section) & SEC_ALLOC))
1908 return;
1909
1910 /* check/ignore any sections of size zero */
1911 section_size = bfd_get_section_size_before_reloc(the_section);
1912 if (section_size == 0)
1913 return;
1914
1915 /* find where it is to go */
1916 section_vma = bfd_get_section_vma(abfd, the_section);
1917
5b4d72dd 1918 DTRACE(binary,
c5addc19 1919 ("name=%-7s, vma=0x%.8lx, size=%6ld, flags=%3lx(%s%s%s%s%s )\n",
5b4d72dd 1920 bfd_get_section_name(abfd, the_section),
c5addc19
MM
1921 (long)section_vma,
1922 (long)section_size,
1923 (long)bfd_get_section_flags(abfd, the_section),
5b4d72dd
MM
1924 bfd_get_section_flags(abfd, the_section) & SEC_LOAD ? " LOAD" : "",
1925 bfd_get_section_flags(abfd, the_section) & SEC_CODE ? " CODE" : "",
1926 bfd_get_section_flags(abfd, the_section) & SEC_DATA ? " DATA" : "",
1927 bfd_get_section_flags(abfd, the_section) & SEC_ALLOC ? " ALLOC" : "",
1928 bfd_get_section_flags(abfd, the_section) & SEC_READONLY ? " READONLY" : ""
1929 ));
dec38dac
MM
1930
1931 /* determine the devices access */
1932 access = access_read;
1933 if (bfd_get_section_flags(abfd, the_section) & SEC_CODE)
1934 access |= access_exec;
1935 if (!(bfd_get_section_flags(abfd, the_section) & SEC_READONLY))
1936 access |= access_write;
1937
1938 /* if a map, pass up a request to create the memory in core */
93fac324
MM
1939 if (strncmp(device_name(me), "map-binary", strlen("map-binary")) == 0)
1940 device_attach_address(device_parent(me),
1941 device_name(me),
1942 attach_raw_memory,
1943 0 /*address space*/,
1944 section_vma,
1945 section_size,
1946 access,
1947 me);
dec38dac
MM
1948
1949 /* if a load dma in the required data */
1950 if (bfd_get_section_flags(abfd, the_section) & SEC_LOAD) {
1951 void *section_init = zalloc(section_size);
1952 if (!bfd_get_section_contents(abfd,
1953 the_section,
1954 section_init, 0,
1955 section_size)) {
1956 bfd_perror("core:load_section()");
1957 error("load of data failed");
1958 return;
1959 }
93fac324
MM
1960 if (device_dma_write_buffer(device_parent(me),
1961 section_init,
1962 0 /*space*/,
1963 section_vma,
1964 section_size,
1965 1 /*violate_read_only*/)
dec38dac 1966 != section_size)
93fac324 1967 error("data_init_callback() broken transfer for %s\n", device_name(me));
dec38dac
MM
1968 zfree(section_init); /* only free if load */
1969 }
cb7a6892
MM
1970}
1971
dec38dac 1972
93fac324 1973static void
d6103e8e
MM
1974binary_init_data_callback(device *me,
1975 psim *system)
cb7a6892 1976{
d6103e8e
MM
1977 /* get the file name */
1978 const char *file_name = device_find_string_property(me, "file-name");
dec38dac
MM
1979 bfd *image;
1980
dec38dac
MM
1981 /* open the file */
1982 image = bfd_openr(file_name, NULL);
1983 if (image == NULL) {
1dc7c0ed 1984 bfd_perror("devices/binary");
93fac324 1985 error("devices/%s - the file %s not loaded\n", device_name(me), file_name);
dec38dac
MM
1986 }
1987
1988 /* check it is valid */
1989 if (!bfd_check_format(image, bfd_object)) {
dec38dac 1990 bfd_close(image);
93fac324
MM
1991 error("devices/%s - the file %s has an invalid binary format\n",
1992 device_name(me), file_name);
dec38dac
MM
1993 }
1994
1995 /* and the data sections */
1996 bfd_map_over_sections(image,
5b4d72dd 1997 update_for_binary_section,
dec38dac
MM
1998 (PTR)me);
1999
2000 bfd_close(image);
cb7a6892
MM
2001}
2002
2003
dec38dac 2004static device_callbacks const binary_callbacks = {
d6103e8e
MM
2005 ignore_device_init,
2006 binary_init_data_callback,
dec38dac
MM
2007 unimp_device_attach_address,
2008 unimp_device_detach_address,
2009 unimp_device_io_read_buffer,
2010 unimp_device_io_write_buffer,
2011 unimp_device_dma_read_buffer,
2012 unimp_device_dma_write_buffer,
d6103e8e
MM
2013 unimp_device_interrupt_event,
2014 unimp_device_child_interrupt_event,
2015 unimp_device_unit_decode,
2016 unimp_device_unit_encode,
2017 unimp_device_instance_create,
2018 unimp_device_instance_delete,
2019 unimp_device_instance_read,
2020 unimp_device_instance_write,
2021 unimp_device_instance_seek,
dec38dac 2022 unimp_device_ioctl,
cb7a6892
MM
2023};
2024
dec38dac
MM
2025
2026\f
2027/* Stack device: stack@<type>
2028
2029 Has a single IOCTL to create a stack frame of the specified type.
2030 If <type> is elf or xcoff then a corresponding stack is created.
2031 Any other value of type is ignored.
2032
2033 The IOCTL takes the additional arguments:
2034
2035 unsigned_word stack_end -- where the stack should come down from
2036 char **argv -- ...
2037 char **envp -- ...
2038
2039 */
2040
93fac324 2041STATIC_INLINE_DEVICE_TABLE int
dec38dac
MM
2042sizeof_argument_strings(char **arg)
2043{
2044 int sizeof_strings = 0;
2045
2046 /* robust */
2047 if (arg == NULL)
2048 return 0;
2049
2050 /* add up all the string sizes (padding as we go) */
2051 for (; *arg != NULL; arg++) {
2052 int len = strlen(*arg) + 1;
2053 sizeof_strings += ALIGN_8(len);
2054 }
2055
2056 return sizeof_strings;
2057}
2058
93fac324 2059STATIC_INLINE_DEVICE_TABLE int
dec38dac
MM
2060number_of_arguments(char **arg)
2061{
2062 int nr;
2063 if (arg == NULL)
2064 return 0;
2065 for (nr = 0; *arg != NULL; arg++, nr++);
2066 return nr;
2067}
2068
93fac324 2069STATIC_INLINE_DEVICE_TABLE int
dec38dac
MM
2070sizeof_arguments(char **arg)
2071{
2072 return ALIGN_8((number_of_arguments(arg) + 1) * sizeof(unsigned_word));
2073}
2074
93fac324 2075STATIC_INLINE_DEVICE_TABLE void
dec38dac
MM
2076write_stack_arguments(psim *system,
2077 char **arg,
2078 unsigned_word start_block,
2079 unsigned_word end_block,
2080 unsigned_word start_arg,
2081 unsigned_word end_arg)
2082{
5b4d72dd 2083 DTRACE(stack,
c5addc19
MM
2084 ("write_stack_arguments(system=0x%lx, arg=0x%lx, start_block=0x%lx, end_block=0x%lx, start_arg=0x%lx, end_arg=0x%lx)\n",
2085 (long)system, (long)arg, (long)start_block, (long)end_block, (long)start_arg, (long)end_arg));
dec38dac
MM
2086 if (arg == NULL)
2087 error("write_arguments: character array NULL\n");
2088 /* only copy in arguments, memory is already zero */
2089 for (; *arg != NULL; arg++) {
2090 int len = strlen(*arg)+1;
2091 unsigned_word target_start_block;
5b4d72dd 2092 DTRACE(stack,
c5addc19
MM
2093 ("write_stack_arguments() write %s=%s at %s=0x%lx %s=0x%lx %s=0x%lx\n",
2094 "**arg", *arg, "start_block", (long)start_block,
2095 "len", (long)len, "start_arg", (long)start_arg));
dec38dac
MM
2096 if (psim_write_memory(system, 0, *arg,
2097 start_block, len,
2098 0/*violate_readonly*/) != len)
2099 error("write_stack_arguments() - write of **arg (%s) at 0x%x failed\n",
2100 *arg, start_block);
2101 target_start_block = H2T_word(start_block);
2102 if (psim_write_memory(system, 0, &target_start_block,
2103 start_arg, sizeof(target_start_block),
2104 0) != sizeof(target_start_block))
2105 error("write_stack_arguments() - write of *arg failed\n");
2106 start_block += ALIGN_8(len);
2107 start_arg += sizeof(start_block);
2108 }
2109 start_arg += sizeof(start_block); /*the null at the end*/
2110 if (start_block != end_block
2111 || ALIGN_8(start_arg) != end_arg)
2112 error("write_stack_arguments - possible corruption\n");
5b4d72dd
MM
2113 DTRACE(stack,
2114 ("write_stack_arguments() = void\n"));
dec38dac
MM
2115}
2116
93fac324 2117STATIC_INLINE_DEVICE_TABLE void
dec38dac
MM
2118create_elf_stack_frame(psim *system,
2119 unsigned_word bottom_of_stack,
2120 char **argv,
2121 char **envp)
2122{
2123 /* fixme - this is over aligned */
2124
2125 /* information block */
2126 const unsigned sizeof_envp_block = sizeof_argument_strings(envp);
2127 const unsigned_word start_envp_block = bottom_of_stack - sizeof_envp_block;
2128 const unsigned sizeof_argv_block = sizeof_argument_strings(argv);
2129 const unsigned_word start_argv_block = start_envp_block - sizeof_argv_block;
2130
2131 /* auxiliary vector - contains only one entry */
2132 const unsigned sizeof_aux_entry = 2*sizeof(unsigned_word); /* magic */
2133 const unsigned_word start_aux = start_argv_block - ALIGN_8(sizeof_aux_entry);
2134
2135 /* environment points (including null sentinal) */
2136 const unsigned sizeof_envp = sizeof_arguments(envp);
2137 const unsigned_word start_envp = start_aux - sizeof_envp;
2138
2139 /* argument pointers (including null sentinal) */
2140 const int argc = number_of_arguments(argv);
2141 const unsigned sizeof_argv = sizeof_arguments(argv);
2142 const unsigned_word start_argv = start_envp - sizeof_argv;
2143
2144 /* link register save address - alligned to a 16byte boundary */
2145 const unsigned_word top_of_stack = ((start_argv
2146 - 2 * sizeof(unsigned_word))
2147 & ~0xf);
2148
2149 /* install arguments on stack */
2150 write_stack_arguments(system, envp,
2151 start_envp_block, bottom_of_stack,
2152 start_envp, start_aux);
2153 write_stack_arguments(system, argv,
2154 start_argv_block, start_envp_block,
2155 start_argv, start_envp);
2156
2157 /* set up the registers */
2158 psim_write_register(system, -1,
2159 &top_of_stack, "sp", cooked_transfer);
2160 psim_write_register(system, -1,
2161 &argc, "r3", cooked_transfer);
2162 psim_write_register(system, -1,
2163 &start_argv, "r4", cooked_transfer);
2164 psim_write_register(system, -1,
2165 &start_envp, "r5", cooked_transfer);
2166 psim_write_register(system, -1,
2167 &start_aux, "r6", cooked_transfer);
2168}
2169
93fac324 2170STATIC_INLINE_DEVICE_TABLE void
dec38dac
MM
2171create_aix_stack_frame(psim *system,
2172 unsigned_word bottom_of_stack,
2173 char **argv,
2174 char **envp)
cb7a6892 2175{
dec38dac
MM
2176 unsigned_word core_envp;
2177 unsigned_word core_argv;
2178 unsigned_word core_argc;
2179 unsigned_word core_aux;
2180 unsigned_word top_of_stack;
2181
2182 /* cheat - create an elf stack frame */
2183 create_elf_stack_frame(system, bottom_of_stack, argv, envp);
2184
2185 /* extract argument addresses from registers */
2186 psim_read_register(system, 0, &top_of_stack, "r1", cooked_transfer);
2187 psim_read_register(system, 0, &core_argc, "r3", cooked_transfer);
2188 psim_read_register(system, 0, &core_argv, "r4", cooked_transfer);
2189 psim_read_register(system, 0, &core_envp, "r5", cooked_transfer);
2190 psim_read_register(system, 0, &core_aux, "r6", cooked_transfer);
2191
2192 /* extract arguments from registers */
2193 error("create_aix_stack_frame() - what happens next?\n");
2194}
2195
2196
cb7a6892 2197
8e20a3ac 2198static void
93fac324 2199stack_ioctl_callback(device *me,
dec38dac
MM
2200 psim *system,
2201 cpu *processor,
2202 unsigned_word cia,
93fac324 2203 va_list ap)
dec38dac 2204{
dec38dac 2205 unsigned_word stack_pointer;
93fac324 2206 const char *stack_type;
dec38dac
MM
2207 char **argv;
2208 char **envp;
dec38dac
MM
2209 stack_pointer = va_arg(ap, unsigned_word);
2210 argv = va_arg(ap, char **);
2211 envp = va_arg(ap, char **);
5b4d72dd 2212 DTRACE(stack,
c5addc19 2213 ("stack_ioctl_callback(me=0x%lx:%s, system=0x%lx, processor=0x%lx, cia=0x%lx, argv=0x%lx, envp=0x%lx)\n",
93fac324 2214 (long)me, device_name(me), (long)system, (long)processor, (long)cia, (long)argv, (long)envp));
d6103e8e
MM
2215 stack_type = device_find_string_property(me, "stack-type");
2216 if (strcmp(stack_type, "elf") == 0)
2217 create_elf_stack_frame(system, stack_pointer, argv, envp);
2218 else if (strcmp(stack_type, "xcoff") == 0)
2219 create_aix_stack_frame(system, stack_pointer, argv, envp);
5b4d72dd
MM
2220 DTRACE(stack,
2221 ("stack_ioctl_callback() = void\n"));
cb7a6892
MM
2222}
2223
dec38dac 2224static device_callbacks const stack_callbacks = {
d6103e8e 2225 ignore_device_init,
dec38dac
MM
2226 ignore_device_init,
2227 unimp_device_attach_address,
2228 unimp_device_detach_address,
2229 unimp_device_io_read_buffer,
2230 unimp_device_io_write_buffer,
2231 unimp_device_dma_read_buffer,
2232 unimp_device_dma_write_buffer,
d6103e8e
MM
2233 unimp_device_interrupt_event,
2234 unimp_device_child_interrupt_event,
2235 unimp_device_unit_decode,
2236 unimp_device_unit_encode,
2237 unimp_device_instance_create,
2238 unimp_device_instance_delete,
2239 unimp_device_instance_read,
2240 unimp_device_instance_write,
2241 unimp_device_instance_seek,
dec38dac 2242 stack_ioctl_callback,
cb7a6892
MM
2243};
2244
2245
dec38dac 2246\f
93fac324
MM
2247device_descriptor device_table[] = {
2248 { "console", console_create, &console_callbacks },
5b4d72dd 2249 { "memory", NULL, &memory_callbacks },
d6103e8e 2250 { "eeprom", NULL, &memory_callbacks },
93fac324 2251 { "vm", vea_vm_create, &vm_callbacks },
dec38dac
MM
2252 { "halt", NULL, &halt_callbacks },
2253 { "icu", NULL, &icu_callbacks },
2254 { "register", NULL, &register_callbacks },
2255 { "iobus", NULL, &iobus_callbacks },
2256 { "file", NULL, &file_callbacks },
93fac324 2257 { "data", NULL, &data_callbacks },
dec38dac
MM
2258 { "htab", NULL, &htab_callbacks },
2259 { "pte", NULL, &htab_callbacks }, /* yep - uses htab's table */
2260 { "stack", NULL, &stack_callbacks },
dec38dac
MM
2261 { "load-binary", NULL, &binary_callbacks },
2262 { "map-binary", NULL, &binary_callbacks },
d6103e8e
MM
2263 /* standard OpenBoot devices */
2264 { "aliases", NULL, &passthrough_callbacks },
93fac324 2265 { "options", NULL, &passthrough_callbacks },
93fac324 2266 { "chosen", NULL, &passthrough_callbacks },
d6103e8e
MM
2267 { "packages", NULL, &passthrough_callbacks },
2268 { "cpus", NULL, &passthrough_callbacks },
2269 { "openprom", NULL, &passthrough_callbacks },
2270 { "init", NULL, &passthrough_callbacks },
2271 { "trace", NULL, &trace_callbacks },
dec38dac 2272 { NULL },
cb7a6892
MM
2273};
2274
93fac324 2275#endif /* _DEVICE_TABLE_C_ */
This page took 0.164637 seconds and 4 git commands to generate.