Include ld-lib.exp from ctf-lib.exp
[binutils-gdb.git] / sim / ppc / hw_shm.c
1 /* This file is part of the program psim.
2
3 Copyright (C) 1997,2008, Joel Sherrill <joel@OARcorp.com>
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 3 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, see <http://www.gnu.org/licenses/>.
17
18 */
19
20
21 #ifndef _HW_SHM_C_
22 #define _HW_SHM_C_
23
24 #include "device_table.h"
25
26 #include <string.h>
27 #include <sys/ipc.h>
28 #include <sys/shm.h>
29
30
31 /* DEVICE
32
33
34 shm - map unix shared memory into psim address space
35
36
37 DESCRIPTION
38
39
40 This device implements an area of memory which is mapped into UNIX
41 shared memory.
42
43
44 PROPERTIES
45
46
47 reg = <address> <size> (required)
48
49 Determine where the memory lives in the parents address space.
50 The SHM area is assumed to be of the same length.
51
52 key = <integer> (required)
53
54 This is the key of the unix shared memory area.
55
56 EXAMPLES
57
58
59 Enable tracing of the shm:
60
61 | bash$ psim -t shm-device \
62
63
64 Configure a 512 kilobytes of UNIX shared memory with the key 0x12345678
65 mapped into psim address space at 0x0c000000.
66
67 | -o '/shm@0x0c000000/reg 0x0c000000 0x80000' \
68 | -o '/shm@0x0c000000/key 0x12345678' \
69
70 sim/ppc/run -o '/#address-cells 1' \
71 -o '/shm@0x0c000000/reg 0x0c000000 0x80000' \
72 -o '/shm@0x0c000000/key 0x12345678' ../psim-hello/hello
73
74 BUGS
75
76 None known.
77
78 */
79
80 typedef struct _hw_shm_device {
81 unsigned_word physical_address;
82 char *shm_address;
83 unsigned sizeof_memory;
84 key_t key;
85 int id;
86 } hw_shm_device;
87
88 static void
89 hw_shm_init_data(device *me)
90 {
91 hw_shm_device *shm = (hw_shm_device*)device_data(me);
92 const device_unit *d;
93 reg_property_spec reg;
94 int i;
95
96 /* Obtain the Key Value */
97 if (device_find_property(me, "key") == NULL)
98 error("shm_init_data() required key property is missing\n");
99
100 shm->key = (key_t) device_find_integer_property(me, "key");
101 DTRACE(shm, ("shm key (0x%08x)\n", shm->key) );
102
103 /* Figure out where this memory is in address space and how long it is */
104 if ( !device_find_reg_array_property(me, "reg", 0, &reg) )
105 error("hw_shm_init_data() no address registered\n");
106
107 /* Determine the address and length being as paranoid as possible */
108 shm->physical_address = 0xffffffff;
109 shm->sizeof_memory = 0xffffffff;
110
111 for ( i=0 ; i<reg.address.nr_cells; i++ ) {
112 if (reg.address.cells[0] == 0 && reg.size.cells[0] == 0)
113 continue;
114
115 if ( shm->physical_address != 0xffffffff )
116 device_error(me, "Only single celled address ranges supported\n");
117
118 shm->physical_address = reg.address.cells[i];
119 DTRACE(shm, ("shm physical_address=0x%x\n", shm->physical_address));
120
121 shm->sizeof_memory = reg.size.cells[i];
122 DTRACE(shm, ("shm length=0x%x\n", shm->sizeof_memory));
123 }
124
125 if ( shm->physical_address == 0xffffffff )
126 device_error(me, "Address not specified\n" );
127
128 if ( shm->sizeof_memory == 0xffffffff )
129 device_error(me, "Length not specified\n" );
130
131 /* Now actually attach to or create the shared memory area */
132 shm->id = shmget(shm->key, shm->sizeof_memory, IPC_CREAT | 0660);
133 if (shm->id == -1)
134 error("hw_shm_init_data() shmget failed\n");
135
136 shm->shm_address = shmat(shm->id, (char *)0, SHM_RND);
137 if (shm->shm_address == (void *)-1)
138 error("hw_shm_init_data() shmat failed\n");
139 }
140
141 static void
142 hw_shm_attach_address_callback(device *me,
143 attach_type attach,
144 int space,
145 unsigned_word addr,
146 unsigned nr_bytes,
147 access_type access,
148 device *client) /*callback/default*/
149 {
150 hw_shm_device *shm = (hw_shm_device*)device_data(me);
151
152 if (space != 0)
153 error("shm_attach_address_callback() invalid address space\n");
154
155 if (nr_bytes == 0)
156 error("shm_attach_address_callback() invalid size\n");
157 }
158
159
160 static unsigned
161 hw_shm_io_read_buffer(device *me,
162 void *dest,
163 int space,
164 unsigned_word addr,
165 unsigned nr_bytes,
166 cpu *processor,
167 unsigned_word cia)
168 {
169 hw_shm_device *shm = (hw_shm_device*)device_data(me);
170
171 /* do we need to worry about out of range addresses? */
172
173 DTRACE(shm, ("read %p %x %x %x\n", \
174 shm->shm_address, shm->physical_address, addr, nr_bytes) );
175
176 memcpy(dest, &shm->shm_address[addr - shm->physical_address], nr_bytes);
177 return nr_bytes;
178 }
179
180
181 static unsigned
182 hw_shm_io_write_buffer(device *me,
183 const void *source,
184 int space,
185 unsigned_word addr,
186 unsigned nr_bytes,
187 cpu *processor,
188 unsigned_word cia)
189 {
190 hw_shm_device *shm = (hw_shm_device*)device_data(me);
191
192 /* do we need to worry about out of range addresses? */
193
194 DTRACE(shm, ("write %p %x %x %x\n", \
195 shm->shm_address, shm->physical_address, addr, nr_bytes) );
196
197 memcpy(&shm->shm_address[addr - shm->physical_address], source, nr_bytes);
198 return nr_bytes;
199 }
200
201 static device_callbacks const hw_shm_callbacks = {
202 { generic_device_init_address, hw_shm_init_data },
203 { hw_shm_attach_address_callback, }, /* address */
204 { hw_shm_io_read_buffer,
205 hw_shm_io_write_buffer }, /* IO */
206 { NULL, }, /* DMA */
207 { NULL, }, /* interrupt */
208 { NULL, }, /* unit */
209 NULL,
210 };
211
212 static void *
213 hw_shm_create(const char *name,
214 const device_unit *unit_address,
215 const char *args)
216 {
217 hw_shm_device *shm = ZALLOC(hw_shm_device);
218 return shm;
219 }
220
221
222
223 const device_descriptor hw_shm_device_descriptor[] = {
224 { "shm", hw_shm_create, &hw_shm_callbacks },
225 { NULL },
226 };
227
228 #endif /* _HW_SHM_C_ */