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