1 /* This file is part of the program psim.
3 Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au>
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.
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.
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.
22 #ifndef _DEVICE_TABLE_C_
23 #define _DEVICE_TABLE_C_
25 #ifndef STATIC_INLINE_DEVICE_TABLE
26 #define STATIC_INLINE_DEVICE_TABLE STATIC_INLINE
35 #include "device_table.h"
59 /* Helper functions */
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. */
65 typedef struct _reg_spec
{
71 generic_device_init_address(device
*me
,
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
);
78 if ((reg
->sizeof_array
% sizeof(reg_spec
)) != 0)
79 error("devices/%s reg property is of wrong size\n", device_name(me
));
81 while (nr_entries
> 0) {
82 device_attach_address(device_parent(me
),
88 access_read_write_exec
,
96 generic_device_unit_decode(device
*me
,
100 memset(phys
, 0, sizeof(device_unit
));
104 char *pos
= (char*)unit
; /* force for strtoul() */
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')
112 if (phys
->nr_cells
== 4)
114 phys
->cells
[phys
->nr_cells
] = val
;
121 generic_device_unit_encode(device
*me
,
122 const device_unit
*phys
,
128 char *pos
= buf
; /* force for strtoul() */
129 for (i
= 0; i
< phys
->nr_cells
; i
++) {
132 pos
= strchr(pos
, '\0');
134 sprintf(pos
, "0x%lx", (unsigned long)phys
->cells
[i
]);
135 pos
= strchr(pos
, '\0');
138 if (len
>= sizeof_buf
)
139 error("generic_unit_encode - buffer overflow\n");
143 /* DMA a file into memory */
144 STATIC_INLINE_DEVICE_TABLE
int
146 const char *file_name
,
155 image
= fopen(file_name
, "r");
159 /* read it in slowly */
162 inc
= fread(buf
, 1, sizeof(buf
), image
);
163 if (feof(image
) || ferror(image
))
165 if (device_dma_write_buffer(device_parent(me
),
170 1 /*violate ro*/) != inc
) {
177 /* close down again */
185 /* inimplemented versions of each function */
188 unimp_device_init(device
*me
,
191 error("device_init_callback for %s not implemented\n", device_name(me
));
195 unimp_device_attach_address(device
*me
,
202 device
*who
) /*callback/default*/
204 error("device_attach_address_callback for %s not implemented\n", device_name(me
));
208 unimp_device_detach_address(device
*me
,
215 device
*who
) /*callback/default*/
217 error("device_detach_address_callback for %s not implemented\n", device_name(me
));
221 unimp_device_io_read_buffer(device
*me
,
229 error("device_io_read_buffer_callback for %s not implemented\n", device_name(me
));
234 unimp_device_io_write_buffer(device
*me
,
242 error("device_io_write_buffer_callback for %s not implemented\n", device_name(me
));
247 unimp_device_dma_read_buffer(device
*me
,
253 error("device_dma_read_buffer_callback for %s not implemented\n", device_name(me
));
258 unimp_device_dma_write_buffer(device
*me
,
263 int violate_read_only_section
)
265 error("device_dma_write_buffer_callback for %s not implemented\n", device_name(me
));
270 unimp_device_interrupt_event(device
*me
,
278 error("unimp_device_interrupt_event for %s unimplemented\n",
283 unimp_device_child_interrupt_event(device
*me
,
291 error("unimp_device_child_interrupt_event_callback for %s unimplemented\n",
296 unimp_device_unit_decode(device
*me
,
298 device_unit
*address
)
300 error("unimp_device_unit_decode_callback for %s unimplemented\n",
306 unimp_device_unit_encode(device
*me
,
307 const device_unit
*unit_address
,
311 error("unimp_device_unit_encode_callback for %s unimplemented\n",
317 unimp_device_instance_create(device
*me
,
320 error("unimp_device_instance_create_callback for %s unimplemented\n",
326 unimp_device_instance_delete(device_instance
*instance
)
328 error("unimp_device_instance_delete_callback for %s unimplemented\n",
329 device_instance_name(instance
));
333 unimp_device_instance_read(device_instance
*instance
,
337 error("unimp_device_instance_read_callback for %s unimplemented\n",
338 device_instance_name(instance
));
343 unimp_device_instance_write(device_instance
*instance
,
347 error("unimp_device_instance_write_callback for %s unimplemented\n",
348 device_instance_name(instance
));
353 unimp_device_instance_seek(device_instance
*instance
,
354 unsigned_word pos_hi
,
355 unsigned_word pos_lo
)
357 error("unimp_device_instance_seek_callback for %s unimplemented\n",
358 device_instance_name(instance
));
364 unimp_device_ioctl(device
*me
,
370 error("device_ioctl_callback for %s not implemented\n", device_name(me
));
375 /* ignore/passthrough versions of each function */
378 ignore_device_init(device
*me
,
385 passthrough_device_attach_address(device
*me
,
392 device
*who
) /*callback/default*/
394 device_attach_address(device_parent(me
), name
, attach
,
395 space
, addr
, nr_bytes
,
401 passthrough_device_detach_address(device
*me
,
408 device
*who
) /*callback/default*/
410 device_detach_address(device_parent(me
), name
, attach
,
411 space
, addr
, nr_bytes
, access
,
416 passthrough_device_dma_read_buffer(device
*me
,
422 return device_dma_read_buffer(device_parent(me
), dest
,
423 space
, addr
, nr_bytes
);
427 passthrough_device_dma_write_buffer(device
*me
,
432 int violate_read_only_section
)
434 return device_dma_write_buffer(device_parent(me
), source
,
437 violate_read_only_section
);
441 ignore_device_unit_decode(device
*me
,
445 memset(phys
, 0, sizeof(device_unit
));
450 static const device_callbacks passthrough_callbacks
= {
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
,
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
,
473 /* Simple console device: console@<address>,16
475 Input characters are taken from the keyboard, output characters
476 sent to the terminal. Echoing of characters is not disabled.
478 The device has four registers:
485 Where a nonzero status register indicates that the device is ready
486 (input fifo contains a character or output fifo has space). */
488 typedef struct _console_buffer
{
491 event_entry_tag event_tag
;
494 typedef struct _console_device
{
495 console_buffer input
;
496 console_buffer output
;
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,
508 static int console_use_stdio
= WITH_STDIO
;
510 /* check the console for an available character */
512 scan_console(console_device
*console
)
513 { /* check for input */
517 /* Use stdio if desired. */
518 if (console_use_stdio
) {
521 console
->input
.status
= 0;
522 console
->input
.buffer
= '\0';
524 console
->input
.status
= 1;
525 console
->input
.buffer
= ch
;
530 /* get the old status */
531 flags
= fcntl(0, F_GETFL
, 0);
537 /* temp, disable blocking IO */
538 status
= fcntl(0, F_SETFL
, flags
| O_NDELAY
);
544 status
= read(0, &console
->input
.buffer
, 1);
546 console
->input
.status
= 1;
549 console
->input
.status
= 0;
551 /* return to regular vewing */
552 flags
= fcntl(0, F_SETFL
, flags
);
559 /* write the character to the console */
561 write_console(console_device
*console
,
564 DTRACE(console
, ("<%c:%d>", val
, val
));
565 if (console_use_stdio
)
568 printf_filtered("%c", val
) ;
569 console
->output
.buffer
= val
;
570 console
->output
.status
= 1;
574 console_io_read_buffer_callback(device
*me
,
582 console_device
*console
= (console_device
*)device_data(me
);
585 /* determine what was read */
587 switch ((int)addr
& console_offset_mask
) {
589 case console_read_buffer
:
590 val
= console
->input
.buffer
;
593 case console_read_status
:
594 scan_console(console
);
595 val
= console
->input
.status
;
598 case console_write_buffer
:
599 val
= console
->output
.buffer
;
602 case console_write_status
:
603 val
= console
->output
.status
;
607 error("console_read_callback() internal error\n");
613 memset(dest
, 0, nr_bytes
);
614 *(unsigned_1
*)dest
= val
;
619 console_io_write_buffer_callback(device
*me
,
627 console_device
*console
= (console_device
*)device_data(me
);
628 unsigned_1 val
= *(unsigned_1
*)source
;
630 switch ((int)addr
& console_offset_mask
) {
632 case console_read_buffer
:
633 console
->input
.buffer
= val
;
636 case console_read_status
:
637 console
->input
.status
= val
;
640 case console_write_buffer
:
641 write_console(console
, val
);
642 if (console_use_stdio
)
646 case console_write_status
:
647 console
->output
.status
= val
;
651 error("console_write_callback() internal error\n");
658 /* instances of the console device */
660 console_instance_create_callback(device
*me
,
663 /* make life easier, attach the console data to the instance */
664 return device_data(me
);
668 console_instance_delete_callback(device_instance
*instance
)
670 /* nothing to delete, the console is attached to the device */
675 console_instance_read_callback(device_instance
*instance
,
679 console_device
*console
= device_instance_data(instance
);
680 if (console_use_stdio
) {
681 char *p
= fgets (buf
, len
, stdin
);
683 return ferror (stdin
) ? -1 : -2;
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;
696 return -2; /* not ready */
701 console_instance_write_callback(device_instance
*instance
,
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
)
715 static device_callbacks
const console_callbacks
= {
716 generic_device_init_address
,
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
,
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
,
738 console_create(const char *name
,
739 const device_unit
*unit_address
,
743 /* create the descriptor */
744 console_device
*console
= ZALLOC(console_device
);
745 console
->output
.status
= 1;
746 console
->output
.buffer
= '\0';
747 console
->input
.status
= 0;
748 console
->input
.buffer
= '\0';
754 /* ICU device: icu@<address>
756 <address> : read - processor nr
757 <address> : write - interrupt processor nr
758 <address> + 4 : read - nr processors
760 Single byte registers that control a simple ICU.
762 Illustrates passing of events to parent device. Passing of
763 interrupts to an interrupt destination. */
767 icu_io_read_buffer_callback(device
*me
,
775 memset(dest
, 0, nr_bytes
);
778 *(unsigned_1
*)dest
= cpu_nr(processor
);
782 device_find_integer_property(me
, "/openprom/options/smp");
790 icu_io_write_buffer_callback(device
*me
,
798 unsigned_1 val
= H2T_1(*(unsigned_1
*)source
);
799 /* tell the parent device that the interrupt lines have changed.
800 For this fake ICU. The interrupt lines just indicate the cpu to
802 device_interrupt_event(me
,
810 icu_do_interrupt(event_queue
*queue
,
813 cpu
*target
= (cpu
*)data
;
814 /* try to interrupt the processor. If the attempt fails, try again
816 if (!external_interrupt(target
))
817 event_queue_schedule(queue
, 1, icu_do_interrupt
, target
);
822 icu_interrupt_event_callback(device
*me
,
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
);
841 static device_callbacks
const icu_callbacks
= {
842 generic_device_init_address
,
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
,
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
,
864 /* HALT device: halt@0x<address>,4
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 */
872 halt_io_read_buffer_callback(device
*me
,
880 cpu_halt(processor
, cia
, was_exited
, 0);
886 halt_io_write_buffer_callback(device
*me
,
894 cpu_halt(processor
, cia
, was_exited
, *(unsigned_1
*)source
);
899 static device_callbacks
const halt_callbacks
= {
900 generic_device_init_address
,
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
,
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
,
922 /* Register init device: register@<nothing>
924 Properties attached to the register device specify the name/value
925 initialization pair for cpu registers.
927 A specific processor can be initialized by creating a property with
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. */
935 do_register_init(device
*me
,
937 const device_property
*prop
)
940 const char *name
= prop
->name
;
941 unsigned32 value
= device_find_integer_property(me
, name
);
944 do_register_init(me
, system
, device_next_property(prop
));
946 if (strchr(name
, '.') == NULL
) {
948 DTRACE(register, ("%s=0x%lx\n", name
, (unsigned long)value
));
952 processor
= strtoul(name
, &end
, 0);
953 ASSERT(end
[0] == '.');
955 DTRACE(register, ("%d.%s=0x%lx\n", processor
, name
,
956 (unsigned long)value
));
958 psim_write_register(system
, processor
, /* all processors */
967 register_init_data_callback(device
*me
,
970 const device_property
*prop
= device_find_property(me
, NULL
);
971 do_register_init(me
, system
, prop
);
975 static device_callbacks
const register_callbacks
= {
977 register_init_data_callback
,
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
,
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
,
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. */
1006 trace_init_data_callback(device
*me
,
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
);
1019 static device_callbacks
const trace_callbacks
= {
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
,
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.
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.
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.
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). */
1069 typedef 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
;
1082 vm_init_address_callback(device
*me
,
1085 vm_device
*vm
= (vm_device
*)device_data(me
);
1087 /* revert the stack/heap variables to their defaults */
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"));
1091 vm
->stack_lower_limit
= vm
->stack_bound
;
1094 vm
->heap_upper_limit
= 0;
1096 /* establish this device as the default memory handler */
1097 device_attach_address(device_parent(me
),
1100 0 /*address space - ignore*/,
1101 0 /*addr - ignore*/,
1102 0 /*nr_bytes - ignore*/,
1103 access_read_write
/*access*/,
1109 vm_attach_address(device
*me
,
1116 device
*who
) /*callback/default*/
1118 vm_device
*vm
= (vm_device
*)device_data(me
);
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
;
1125 device_attach_address(device_parent(me
),
1126 "vm@0x0,0", /* stop remap */
1128 0 /*address space*/,
1136 STATIC_INLINE_DEVICE_TABLE
unsigned
1137 add_vm_space(device
*me
,
1143 vm_device
*vm
= (vm_device
*)device_data(me
);
1144 unsigned_word block_addr
;
1145 unsigned block_nr_bytes
;
1147 /* an address in the stack area, allocate just down to the addressed
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
;
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
;
1160 /* oops - an invalid address - abort the cpu */
1161 else if (processor
!= NULL
) {
1162 cpu_halt(processor
, cia
, was_signalled
, SIGSEGV
);
1165 /* 2*oops - an invalid address and no processor */
1170 /* got the parameters, allocate the space */
1171 device_attach_address(device_parent(me
),
1172 "vm@0x0,0", /* stop remap */
1174 0 /*address space*/,
1179 return block_nr_bytes
;
1184 vm_io_read_buffer_callback(device
*me
,
1192 if (add_vm_space(me
, addr
, nr_bytes
, processor
, cia
) >= nr_bytes
) {
1193 memset(dest
, 0, nr_bytes
); /* always initialized to zero */
1202 vm_io_write_buffer_callback(device
*me
,
1210 if (add_vm_space(me
, addr
, nr_bytes
, processor
, cia
) >= nr_bytes
) {
1211 return device_dma_write_buffer(device_parent(me
), source
,
1214 0/*violate_read_only*/);
1222 vm_ioctl_callback(device
*me
,
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
1231 vm_device
*vm
= (vm_device
*)device_data(me
);
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
;
1236 vm
->heap_bound
= ALIGN_PAGE(new_break
);
1237 cpu_registers(processor
)->gpr
[0] = 0;
1238 cpu_registers(processor
)->gpr
[3] = new_break
;
1242 static device_callbacks
const vm_callbacks
= {
1243 vm_init_address_callback
,
1246 passthrough_device_detach_address
,
1247 vm_io_read_buffer_callback
,
1248 vm_io_write_buffer_callback
,
1249 unimp_device_dma_read_buffer
,
1250 passthrough_device_dma_write_buffer
,
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
,
1265 vea_vm_create(const char *name
,
1266 const device_unit
*address
,
1270 vm_device
*vm
= ZALLOC(vm_device
);
1276 /* Memory init device: memory@0x<addr>
1278 This strange device is used create sections of memory */
1281 memory_init_address_callback(device
*me
,
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
);
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
),
1294 0 /*address space*/,
1297 access_read_write_exec
,
1305 memory_instance_create_callback(device
*me
,
1308 return me
; /* for want of any thing better */
1312 memory_instance_delete_callback(device_instance
*instance
)
1317 static device_callbacks
const memory_callbacks
= {
1318 memory_init_address_callback
,
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
,
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
,
1340 /* IOBUS device: iobus@<address>
1342 Simple bus on which some IO devices live */
1345 iobus_attach_address_callback(device
*me
,
1352 device
*who
) /*callback/default*/
1354 unsigned_word iobus_addr
;
1356 if (type
== attach_default
)
1357 error("iobus_attach_address_callback() no default for %s/%s\n",
1358 device_name(me
), name
);
1360 error("iobus_attach_address_callback() no space for %s/%s\n",
1361 device_name(me
), name
);
1362 /* get the bus address */
1363 if (device_unit_address(me
)->nr_cells
!= 1)
1364 error("iobus_attach_address_callback() invalid address for %s\n",
1366 iobus_addr
= device_unit_address(me
)->cells
[0];
1367 device_attach_address(device_parent(me
),
1378 static device_callbacks
const iobus_callbacks
= {
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
,
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
,
1401 /* FILE device: file@0x<address>,<file-name>
1402 (later - file@0x<address>,<size>,<file-offset>,<file-name>)
1404 Specifies a file to read directly into memory starting at <address> */
1408 file_init_data_callback(device
*me
,
1412 const char *file_name
= device_find_string_property(me
, "file-name");
1413 unsigned_word addr
= device_find_integer_property(me
, "real-address");
1415 count
= dma_file(me
, file_name
, addr
);
1417 error("device_table/%s - Problem loading file %s\n",
1418 device_name(me
), file_name
);
1422 static device_callbacks
const file_callbacks
= {
1424 file_init_data_callback
,
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
,
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
,
1445 /* DATA device: data@<address>
1447 <data> - property containing the value to store
1448 <real-address> - address to store data at
1450 Store <data> at <address> using approperiate byte order */
1453 data_init_data_callback(device
*me
,
1456 unsigned_word addr
= device_find_integer_property(me
, "real-address");
1457 const device_property
*data
= device_find_property(me
, "data");
1459 error("devices/data - missing data property\n");
1460 switch (data
->type
) {
1461 case integer_property
:
1463 unsigned32 buf
= device_find_integer_property(me
, "data");
1465 if (device_dma_write_buffer(device_parent(me
),
1467 0 /*address-space*/,
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
);
1476 error("devices/%s - write of this data is not yet implemented\n", device_name(me
));
1482 static device_callbacks
const data_callbacks
= {
1484 data_init_data_callback
,
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
,
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
,
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
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. */
1532 STATIC_INLINE_DEVICE_TABLE
void
1533 htab_decode_hash_table(device
*parent
,
1534 unsigned32
*htaborg
,
1535 unsigned32
*htabmask
)
1537 unsigned_word htab_ra
;
1538 unsigned htab_nr_bytes
;
1540 /* determine the location/size of the hash table */
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");
1546 for (n
= htab_nr_bytes
; n
> 1; n
= n
/ 2) {
1548 error("devices/%s - htab size 0x%x not a power of two\n",
1549 device_name(parent
), htab_nr_bytes
);
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
);
1557 DTRACE(htab
, ("htab - htaborg=0x%lx htabmask=0x%lx\n",
1558 (unsigned long)*htaborg
, (unsigned long)*htabmask
));
1562 htab_map_page(device
*me
,
1568 unsigned32 htabmask
)
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),
1577 for (h
= 0; h
< 2; h
++) {
1578 unsigned32 pteg
= (htaborg
| (hash
& htabmask
));
1580 for (pti
= 0; pti
< 8; pti
++, pteg
+= 8) {
1581 unsigned32 current_target_pte0
;
1582 unsigned32 current_pte0
;
1583 if (device_dma_read_buffer(device_parent(me
),
1584 ¤t_target_pte0
,
1587 sizeof(current_target_pte0
)) != 4)
1588 error("htab_init_callback() failed to read a pte at 0x%x\n",
1590 current_pte0
= T2H_4(current_target_pte0
);
1591 if (!MASKED32(current_pte0
, 0, 0)) {
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));
1597 unsigned32 target_pte0
= H2T_4(pte0
);
1598 unsigned32 pte1
= (INSERTED32(EXTRACTED32(ra
, 0, 19), 0, 19)
1599 | INSERTED32(wimg
, 25, 28)
1600 | INSERTED32(pp
, 30, 31));
1601 unsigned32 target_pte1
= H2T_4(pte1
);
1602 if (device_dma_write_buffer(device_parent(me
),
1606 sizeof(target_pte0
),
1608 || device_dma_write_buffer(device_parent(me
),
1612 sizeof(target_pte1
),
1614 error("htab_init_callback() failed to write a pte a 0x%x\n",
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
));
1624 hash
= MASKED32(~hash
, 0, 18);
1628 STATIC_INLINE_DEVICE_TABLE
void
1629 htab_map_region(device
*me
,
1630 unsigned_word pte_ra
,
1631 unsigned_word pte_va
,
1636 unsigned32 htabmask
)
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
);
1648 typedef 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
;
1656 } htab_binary_sizes
;
1658 STATIC_INLINE_DEVICE_TABLE
void
1659 htab_sum_binary(bfd
*abfd
,
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
);
1667 /* skip the section if no memory to allocate */
1668 if (! (bfd_get_section_flags(abfd
, sec
) & SEC_ALLOC
))
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
);
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
);
1687 STATIC_INLINE_DEVICE_TABLE
void
1688 htab_dma_binary(bfd
*abfd
,
1692 htab_binary_sizes
*sizes
= (htab_binary_sizes
*)data
;
1694 unsigned_word section_vma
;
1695 unsigned_word section_size
;
1696 unsigned_word section_ra
;
1697 device
*me
= sizes
->me
;
1699 /* skip the section if no memory to allocate */
1700 if (! (bfd_get_section_flags(abfd
, sec
) & SEC_ALLOC
))
1703 /* check/ignore any sections of size zero */
1704 section_size
= bfd_get_section_size_before_reloc(sec
);
1705 if (section_size
== 0)
1708 /* if nothing to load, ignore this one */
1709 if (! (bfd_get_section_flags(abfd
, sec
) & SEC_LOAD
))
1712 /* find where it is to go */
1713 section_vma
= bfd_get_section_vma(abfd
, sec
);
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
);
1721 return; /* just ignore it */
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
),
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" : ""
1737 /* dma in the sections data */
1738 section_init
= zalloc(section_size
);
1739 if (!bfd_get_section_contents(abfd
,
1743 bfd_perror("devices/pte");
1744 error("devices/%s - no data loaded\n", device_name(me
));
1746 if (device_dma_write_buffer(device_parent(me
),
1751 1 /*violate_read_only*/)
1753 error("devices/%s - broken dma transfer\n", device_name(me
));
1754 zfree(section_init
); /* only free if load */
1757 STATIC_INLINE_DEVICE_TABLE
void
1758 htab_map_binary(device
*me
,
1762 const char *file_name
,
1764 unsigned32 htabmask
)
1766 htab_binary_sizes sizes
;
1768 sizes
.text_base
= -1;
1769 sizes
.data_base
= -1;
1770 sizes
.text_bound
= 0;
1771 sizes
.data_bound
= 0;
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
);
1781 /* check it is valid */
1782 if (!bfd_check_format(image
, bfd_object
)) {
1784 error("devices/%s - the file %s has an invalid binary format\n",
1785 device_name(me
), file_name
);
1788 /* determine the size of each of the files regions */
1789 bfd_map_over_sections (image
, htab_sum_binary
, (PTR
) &sizes
);
1791 /* determine the real addresses of the sections */
1793 sizes
.data_ra
= ALIGN_PAGE(sizes
.text_ra
+
1794 (sizes
.text_bound
- sizes
.text_base
));
1796 DTRACE(htab
, ("text map - base=0x%lx bound=0x%lx ra=0x%lx\n",
1797 (unsigned long)sizes
.text_base
,
1798 (unsigned long)sizes
.text_bound
,
1799 (unsigned long)sizes
.text_ra
));
1800 DTRACE(htab
, ("data map - base=0x%lx bound=0x%lx ra=0x%lx\n",
1801 (unsigned long)sizes
.data_base
,
1802 (unsigned long)sizes
.data_bound
,
1803 (unsigned long)sizes
.data_ra
));
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
,
1810 htab_map_region(me
, sizes
.data_ra
, sizes
.data_base
,
1811 sizes
.data_bound
- sizes
.data_base
,
1815 /* dma the sections into physical memory */
1816 bfd_map_over_sections (image
, htab_dma_binary
, (PTR
) &sizes
);
1820 htab_init_data_callback(device
*me
,
1823 if (WITH_TARGET_WORD_BITSIZE
!= 32)
1824 error("devices/htab: only 32bit targets currently suported\n");
1826 /* only the pte does work */
1827 if (strcmp(device_name(me
), "pte") == 0) {
1829 unsigned32 htabmask
;
1831 htab_decode_hash_table(device_parent(me
), &htaborg
, &htabmask
);
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",
1840 (unsigned long)pte_ra
,
1841 (unsigned long)pte_wimg
,
1844 htab_map_binary(me
, pte_ra
, pte_wimg
, pte_pp
, file_name
,
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
,
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
,
1868 static device_callbacks
const htab_callbacks
= {
1870 htab_init_data_callback
,
1871 unimp_device_attach_address
,
1872 unimp_device_detach_address
,
1873 unimp_device_io_read_buffer
,
1874 unimp_device_io_write_buffer
,
1875 passthrough_device_dma_read_buffer
,
1876 passthrough_device_dma_write_buffer
,
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
,
1891 /* Load device: binary
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 */
1896 STATIC_INLINE_DEVICE_TABLE
void
1897 update_for_binary_section(bfd
*abfd
,
1898 asection
*the_section
,
1901 unsigned_word section_vma
;
1902 unsigned_word section_size
;
1904 device
*me
= (device
*)obj
;
1906 /* skip the section if no memory to allocate */
1907 if (! (bfd_get_section_flags(abfd
, the_section
) & SEC_ALLOC
))
1910 /* check/ignore any sections of size zero */
1911 section_size
= bfd_get_section_size_before_reloc(the_section
);
1912 if (section_size
== 0)
1915 /* find where it is to go */
1916 section_vma
= bfd_get_section_vma(abfd
, the_section
);
1919 ("name=%-7s, vma=0x%.8lx, size=%6ld, flags=%3lx(%s%s%s%s%s )\n",
1920 bfd_get_section_name(abfd
, the_section
),
1923 (long)bfd_get_section_flags(abfd
, the_section
),
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" : ""
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
;
1938 /* if a map, pass up a request to create the memory in core */
1939 if (strncmp(device_name(me
), "map-binary", strlen("map-binary")) == 0)
1940 device_attach_address(device_parent(me
),
1943 0 /*address space*/,
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
,
1956 bfd_perror("core:load_section()");
1957 error("load of data failed");
1960 if (device_dma_write_buffer(device_parent(me
),
1965 1 /*violate_read_only*/)
1967 error("data_init_callback() broken transfer for %s\n", device_name(me
));
1968 zfree(section_init
); /* only free if load */
1974 binary_init_data_callback(device
*me
,
1977 /* get the file name */
1978 const char *file_name
= device_find_string_property(me
, "file-name");
1982 image
= bfd_openr(file_name
, NULL
);
1983 if (image
== NULL
) {
1984 bfd_perror("devices/binary");
1985 error("devices/%s - the file %s not loaded\n", device_name(me
), file_name
);
1988 /* check it is valid */
1989 if (!bfd_check_format(image
, bfd_object
)) {
1991 error("devices/%s - the file %s has an invalid binary format\n",
1992 device_name(me
), file_name
);
1995 /* and the data sections */
1996 bfd_map_over_sections(image
,
1997 update_for_binary_section
,
2004 static device_callbacks
const binary_callbacks
= {
2006 binary_init_data_callback
,
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
,
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
,
2027 /* Stack device: stack@<type>
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.
2033 The IOCTL takes the additional arguments:
2035 unsigned_word stack_end -- where the stack should come down from
2041 STATIC_INLINE_DEVICE_TABLE
int
2042 sizeof_argument_strings(char **arg
)
2044 int sizeof_strings
= 0;
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
);
2056 return sizeof_strings
;
2059 STATIC_INLINE_DEVICE_TABLE
int
2060 number_of_arguments(char **arg
)
2065 for (nr
= 0; *arg
!= NULL
; arg
++, nr
++);
2069 STATIC_INLINE_DEVICE_TABLE
int
2070 sizeof_arguments(char **arg
)
2072 return ALIGN_8((number_of_arguments(arg
) + 1) * sizeof(unsigned_word
));
2075 STATIC_INLINE_DEVICE_TABLE
void
2076 write_stack_arguments(psim
*system
,
2078 unsigned_word start_block
,
2079 unsigned_word end_block
,
2080 unsigned_word start_arg
,
2081 unsigned_word end_arg
)
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
));
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
;
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
));
2096 if (psim_write_memory(system
, 0, *arg
,
2098 0/*violate_readonly*/) != len
)
2099 error("write_stack_arguments() - write of **arg (%s) at 0x%x failed\n",
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
);
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");
2114 ("write_stack_arguments() = void\n"));
2117 STATIC_INLINE_DEVICE_TABLE
void
2118 create_elf_stack_frame(psim
*system
,
2119 unsigned_word bottom_of_stack
,
2123 /* fixme - this is over aligned */
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
;
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
);
2135 /* environment points (including null sentinal) */
2136 const unsigned sizeof_envp
= sizeof_arguments(envp
);
2137 const unsigned_word start_envp
= start_aux
- sizeof_envp
;
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
;
2144 /* link register save address - alligned to a 16byte boundary */
2145 const unsigned_word top_of_stack
= ((start_argv
2146 - 2 * sizeof(unsigned_word
))
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
);
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
);
2170 STATIC_INLINE_DEVICE_TABLE
void
2171 create_aix_stack_frame(psim
*system
,
2172 unsigned_word bottom_of_stack
,
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
;
2182 /* cheat - create an elf stack frame */
2183 create_elf_stack_frame(system
, bottom_of_stack
, argv
, envp
);
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
);
2192 /* extract arguments from registers */
2193 error("create_aix_stack_frame() - what happens next?\n");
2199 stack_ioctl_callback(device
*me
,
2205 unsigned_word stack_pointer
;
2206 const char *stack_type
;
2209 stack_pointer
= va_arg(ap
, unsigned_word
);
2210 argv
= va_arg(ap
, char **);
2211 envp
= va_arg(ap
, char **);
2213 ("stack_ioctl_callback(me=0x%lx:%s, system=0x%lx, processor=0x%lx, cia=0x%lx, argv=0x%lx, envp=0x%lx)\n",
2214 (long)me
, device_name(me
), (long)system
, (long)processor
, (long)cia
, (long)argv
, (long)envp
));
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
);
2221 ("stack_ioctl_callback() = void\n"));
2224 static device_callbacks
const stack_callbacks
= {
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
,
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
,
2242 stack_ioctl_callback
,
2247 device_descriptor device_table
[] = {
2248 { "console", console_create
, &console_callbacks
},
2249 { "memory", NULL
, &memory_callbacks
},
2250 { "eeprom", NULL
, &memory_callbacks
},
2251 { "vm", vea_vm_create
, &vm_callbacks
},
2252 { "halt", NULL
, &halt_callbacks
},
2253 { "icu", NULL
, &icu_callbacks
},
2254 { "register", NULL
, ®ister_callbacks
},
2255 { "iobus", NULL
, &iobus_callbacks
},
2256 { "file", NULL
, &file_callbacks
},
2257 { "data", NULL
, &data_callbacks
},
2258 { "htab", NULL
, &htab_callbacks
},
2259 { "pte", NULL
, &htab_callbacks
}, /* yep - uses htab's table */
2260 { "stack", NULL
, &stack_callbacks
},
2261 { "load-binary", NULL
, &binary_callbacks
},
2262 { "map-binary", NULL
, &binary_callbacks
},
2263 /* standard OpenBoot devices */
2264 { "aliases", NULL
, &passthrough_callbacks
},
2265 { "options", NULL
, &passthrough_callbacks
},
2266 { "chosen", NULL
, &passthrough_callbacks
},
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
},
2275 #endif /* _DEVICE_TABLE_C_ */