hw_shm.c revision 1.2 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.1 christos typedef struct _hw_shm_device {
81 1.1 christos unsigned_word physical_address;
82 1.1 christos char *shm_address;
83 1.1 christos unsigned sizeof_memory;
84 1.1 christos key_t key;
85 1.1 christos int id;
86 1.1 christos } hw_shm_device;
87 1.1 christos
88 1.1 christos static void
89 1.1 christos hw_shm_init_data(device *me)
90 1.1 christos {
91 1.1 christos hw_shm_device *shm = (hw_shm_device*)device_data(me);
92 1.1 christos reg_property_spec reg;
93 1.1 christos int i;
94 1.1 christos
95 1.1 christos /* Obtain the Key Value */
96 1.1 christos if (device_find_property(me, "key") == NULL)
97 1.1 christos error("shm_init_data() required key property is missing\n");
98 1.1 christos
99 1.1 christos shm->key = (key_t) device_find_integer_property(me, "key");
100 1.2 christos DTRACE(shm, ("shm key (0x%08jx)\n", (intmax_t)shm->key) );
101 1.1 christos
102 1.1 christos /* Figure out where this memory is in address space and how long it is */
103 1.1 christos if ( !device_find_reg_array_property(me, "reg", 0, ®) )
104 1.1 christos error("hw_shm_init_data() no address registered\n");
105 1.1 christos
106 1.1 christos /* Determine the address and length being as paranoid as possible */
107 1.1 christos shm->physical_address = 0xffffffff;
108 1.1 christos shm->sizeof_memory = 0xffffffff;
109 1.1 christos
110 1.1 christos for ( i=0 ; i<reg.address.nr_cells; i++ ) {
111 1.1 christos if (reg.address.cells[0] == 0 && reg.size.cells[0] == 0)
112 1.1 christos continue;
113 1.1 christos
114 1.1 christos if ( shm->physical_address != 0xffffffff )
115 1.1 christos device_error(me, "Only single celled address ranges supported\n");
116 1.1 christos
117 1.1 christos shm->physical_address = reg.address.cells[i];
118 1.1 christos DTRACE(shm, ("shm physical_address=0x%x\n", shm->physical_address));
119 1.1 christos
120 1.1 christos shm->sizeof_memory = reg.size.cells[i];
121 1.1 christos DTRACE(shm, ("shm length=0x%x\n", shm->sizeof_memory));
122 1.1 christos }
123 1.1 christos
124 1.1 christos if ( shm->physical_address == 0xffffffff )
125 1.1 christos device_error(me, "Address not specified\n" );
126 1.1 christos
127 1.1 christos if ( shm->sizeof_memory == 0xffffffff )
128 1.1 christos device_error(me, "Length not specified\n" );
129 1.1 christos
130 1.1 christos /* Now actually attach to or create the shared memory area */
131 1.1 christos shm->id = shmget(shm->key, shm->sizeof_memory, IPC_CREAT | 0660);
132 1.1 christos if (shm->id == -1)
133 1.1 christos error("hw_shm_init_data() shmget failed\n");
134 1.1 christos
135 1.1 christos shm->shm_address = shmat(shm->id, (char *)0, SHM_RND);
136 1.1 christos if (shm->shm_address == (void *)-1)
137 1.1 christos error("hw_shm_init_data() shmat failed\n");
138 1.1 christos }
139 1.1 christos
140 1.1 christos static void
141 1.1 christos hw_shm_attach_address_callback(device *me,
142 1.1 christos attach_type attach,
143 1.1 christos int space,
144 1.1 christos unsigned_word addr,
145 1.1 christos unsigned nr_bytes,
146 1.1 christos access_type access,
147 1.1 christos device *client) /*callback/default*/
148 1.1 christos {
149 1.1 christos if (space != 0)
150 1.1 christos error("shm_attach_address_callback() invalid address space\n");
151 1.1 christos
152 1.1 christos if (nr_bytes == 0)
153 1.1 christos error("shm_attach_address_callback() invalid size\n");
154 1.1 christos }
155 1.1 christos
156 1.1 christos
157 1.1 christos static unsigned
158 1.1 christos hw_shm_io_read_buffer(device *me,
159 1.1 christos void *dest,
160 1.1 christos int space,
161 1.1 christos unsigned_word addr,
162 1.1 christos unsigned nr_bytes,
163 1.1 christos cpu *processor,
164 1.1 christos unsigned_word cia)
165 1.1 christos {
166 1.1 christos hw_shm_device *shm = (hw_shm_device*)device_data(me);
167 1.1 christos
168 1.1 christos /* do we need to worry about out of range addresses? */
169 1.1 christos
170 1.1 christos DTRACE(shm, ("read %p %x %x %x\n", \
171 1.1 christos shm->shm_address, shm->physical_address, addr, nr_bytes) );
172 1.1 christos
173 1.1 christos memcpy(dest, &shm->shm_address[addr - shm->physical_address], nr_bytes);
174 1.1 christos return nr_bytes;
175 1.1 christos }
176 1.1 christos
177 1.1 christos
178 1.1 christos static unsigned
179 1.1 christos hw_shm_io_write_buffer(device *me,
180 1.1 christos const void *source,
181 1.1 christos int space,
182 1.1 christos unsigned_word addr,
183 1.1 christos unsigned nr_bytes,
184 1.1 christos cpu *processor,
185 1.1 christos unsigned_word cia)
186 1.1 christos {
187 1.1 christos hw_shm_device *shm = (hw_shm_device*)device_data(me);
188 1.1 christos
189 1.1 christos /* do we need to worry about out of range addresses? */
190 1.1 christos
191 1.1 christos DTRACE(shm, ("write %p %x %x %x\n", \
192 1.1 christos shm->shm_address, shm->physical_address, addr, nr_bytes) );
193 1.1 christos
194 1.1 christos memcpy(&shm->shm_address[addr - shm->physical_address], source, nr_bytes);
195 1.1 christos return nr_bytes;
196 1.1 christos }
197 1.1 christos
198 1.1 christos static device_callbacks const hw_shm_callbacks = {
199 1.1 christos { generic_device_init_address, hw_shm_init_data },
200 1.1 christos { hw_shm_attach_address_callback, }, /* address */
201 1.1 christos { hw_shm_io_read_buffer,
202 1.1 christos hw_shm_io_write_buffer }, /* IO */
203 1.1 christos { NULL, }, /* DMA */
204 1.1 christos { NULL, }, /* interrupt */
205 1.1 christos { NULL, }, /* unit */
206 1.1 christos NULL,
207 1.1 christos };
208 1.1 christos
209 1.1 christos static void *
210 1.1 christos hw_shm_create(const char *name,
211 1.1 christos const device_unit *unit_address,
212 1.1 christos const char *args)
213 1.1 christos {
214 1.1 christos hw_shm_device *shm = ZALLOC(hw_shm_device);
215 1.1 christos return shm;
216 1.1 christos }
217 1.1 christos
218 1.1 christos
219 1.1 christos
220 1.1 christos const device_descriptor hw_shm_device_descriptor[] = {
221 1.1 christos { "shm", hw_shm_create, &hw_shm_callbacks },
222 1.1 christos { NULL },
223 1.1 christos };
224 1.1 christos
225 1.1 christos #endif /* _HW_SHM_C_ */
226