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