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