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