1 /* This file is part of the program psim.
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.
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.
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.
25 #ifndef STATIC_INLINE_CORE
26 #define STATIC_INLINE_CORE STATIC_INLINE
31 #include "device_tree.h"
35 typedef struct _core_mapping core_mapping;
36 struct _core_mapping {
42 device_io_read_buffer_callback *reader;
43 device_io_write_buffer_callback *writer;
54 core_mapping *default_map;
65 core_map map[nr_core_map_types];
72 core *new_core = ZALLOC(core);
77 STATIC_INLINE_CORE void
78 core_init(core *memory)
80 core_map_types access_type;
82 access_type < nr_core_map_types;
84 core_map *map = memory->map + access_type;
85 /* blow away old mappings */
86 core_mapping *curr = map->first;
87 while (curr != NULL) {
88 core_mapping *tbd = curr;
90 if (tbd->free_buffer) {
91 ASSERT(tbd->buffer != NULL);
97 /* blow away the default */
98 if (map->default_map != NULL) {
99 ASSERT(map->default_map->buffer == NULL);
100 zfree(map->default_map);
102 map->default_map = NULL;
108 /* the core has three sub mappings that the more efficient
109 read/write fixed quantity functions use */
111 INLINE_CORE core_map *
112 core_readable(core *memory)
114 return memory->map + core_read_map;
117 INLINE_CORE core_map *
118 core_writeable(core *memory)
120 return memory->map + core_write_map;
123 INLINE_CORE core_map *
124 core_executable(core *memory)
126 return memory->map + core_execute_map;
131 STATIC_INLINE_CORE core_mapping *
132 new_core_mapping(attach_type attach,
136 const device *device,
140 core_mapping *new_mapping = ZALLOC(core_mapping);
143 case attach_callback:
144 new_mapping->device = device;
145 new_mapping->reader = device->callback->io_read_buffer;
146 new_mapping->writer = device->callback->io_write_buffer;
148 case attach_raw_memory:
149 new_mapping->buffer = buffer;
150 new_mapping->free_buffer = free_buffer;
153 error("new_core_mapping() - internal error - unknown attach type %d\n",
157 new_mapping->space = space;
158 new_mapping->base = addr;
159 new_mapping->nr_bytes = nr_bytes;
160 new_mapping->bound = addr + (nr_bytes - 1);
165 STATIC_INLINE_CORE void
166 core_map_attach(core_map *access_map,
170 unsigned nr_bytes, /* host limited */
171 const device *device, /*callback/default*/
172 void *buffer, /*raw_memory*/
173 int free_buffer) /*raw_memory*/
175 if (attach == attach_default) {
176 if (access_map->default_map != NULL)
177 error("core_map_attach() default mapping already in place\n");
178 ASSERT(buffer == NULL);
179 access_map->default_map = new_core_mapping(attach,
180 space, addr, nr_bytes,
181 device, buffer, free_buffer);
184 /* find the insertion point for this additional mapping and insert */
185 core_mapping *next_mapping;
186 core_mapping **last_mapping;
188 /* actually do occasionally get a zero size map */
190 error("core_map_attach() size == 0\n");
192 /* find the insertion point (between last/next) */
193 next_mapping = access_map->first;
194 last_mapping = &access_map->first;
195 while(next_mapping != NULL && next_mapping->bound < addr) {
196 /* assert: next_mapping->base > all bases before next_mapping */
197 /* assert: next_mapping->bound >= all bounds before next_mapping */
198 last_mapping = &next_mapping->next;
199 next_mapping = next_mapping->next;
202 /* check insertion point correct */
203 if (next_mapping != NULL && next_mapping->base < (addr + (nr_bytes - 1))) {
204 error("core_map_attach() map overlap\n");
207 /* create/insert the new mapping */
208 *last_mapping = new_core_mapping(attach,
209 space, addr, nr_bytes,
210 device, buffer, free_buffer);
211 (*last_mapping)->next = next_mapping;
217 core_attach(core *memory,
222 unsigned nr_bytes, /* host limited */
223 const device *device) /*callback/default*/
225 core_map_types access_map;
228 ASSERT(attach == attach_default || nr_bytes > 0);
229 if (attach == attach_raw_memory)
230 buffer = zalloc(nr_bytes);
232 access_map < nr_core_map_types;
234 switch (access_map) {
236 if (access & access_read)
237 core_map_attach(memory->map + access_map,
239 space, addr, nr_bytes,
240 device, buffer, !free_buffer);
244 if (access & access_write)
245 core_map_attach(memory->map + access_map,
247 space, addr, nr_bytes,
248 device, buffer, !free_buffer);
251 case core_execute_map:
252 if (access & access_exec)
253 core_map_attach(memory->map + access_map,
255 space, addr, nr_bytes,
256 device, buffer, !free_buffer);
260 error("core_attach() internal error\n");
264 ASSERT(free_buffer > 0); /* must attach to at least one thing */
268 STATIC_INLINE_CORE core_mapping *
269 core_map_find_mapping(core_map *map,
274 int abort) /*either 0 or 1 - helps inline */
276 core_mapping *mapping = map->first;
277 ASSERT((addr & (nr_bytes - 1)) == 0); /* must be aligned */
278 ASSERT((addr + (nr_bytes - 1)) >= addr); /* must not wrap */
279 while (mapping != NULL) {
280 if (addr >= mapping->base
281 && (addr + (nr_bytes - 1)) <= mapping->bound)
283 mapping = mapping->next;
285 if (map->default_map != NULL)
286 return map->default_map;
288 error("core_find_mapping() - access to unmaped address, attach a default map to handle this - addr=0x%x nr_bytes=0x%x processor=0x%x cia=0x%x\n",
289 addr, nr_bytes, processor, cia);
294 STATIC_INLINE_CORE void *
295 core_translate(core_mapping *mapping,
298 return mapping->buffer + addr - mapping->base;
303 core_map_read_buffer(core_map *map,
310 for (count = 0; count < len; count++) {
311 unsigned_word raddr = addr + count;
312 core_mapping *mapping =
313 core_map_find_mapping(map,
320 if (mapping->reader != NULL) {
321 if (mapping->reader(mapping->device,
324 raddr - mapping->base,
331 byte = *(unsigned_1*)core_translate(mapping,
333 ((unsigned_1*)buffer)[count] = T2H_1(byte);
340 core_map_write_buffer(core_map *map,
347 for (count = 0; count < len; count++) {
348 unsigned_word raddr = addr + count;
349 core_mapping *mapping = core_map_find_mapping(map,
356 byte = H2T_1(((unsigned_1*)buffer)[count]);
357 if (mapping->writer != NULL) {
358 if (mapping->writer(mapping->device,
361 raddr - mapping->base,
368 *(unsigned_1*)core_translate(mapping, raddr) = byte;
375 /* Top level core(root) device: core@garbage
377 The core device captures incomming dma requests and changes them to
378 outgoing io requests. */
380 STATIC_INLINE_CORE void
381 core_init_callback(const device *me,
384 core *memory = (core*)me->data;
390 STATIC_INLINE_CORE void
391 core_attach_address_callback(const device *me,
398 const device *who) /*callback/default*/
400 core *memory = (core*)me->data;
401 unsigned_word device_address;
402 DTRACE_ATTACH_ADDRESS(core);
404 error("core_attach_address_callback() invalid address space\n");
415 STATIC_INLINE_CORE unsigned
416 core_dma_read_buffer_callback(const device *me,
422 core *memory = (core*)me->data;
423 DTRACE_DMA_READ_BUFFER(core);
424 return core_map_read_buffer(core_readable(memory),
431 STATIC_INLINE_CORE unsigned
432 core_dma_write_buffer_callback(const device *me,
437 int violate_read_only_section)
439 core *memory = (core*)me->data;
440 core_map *map = (violate_read_only_section
441 ? core_readable(memory)
442 : core_writeable(memory));
443 DTRACE_DMA_WRITE_BUFFER(core);
444 return core_map_write_buffer(map,
451 static device_callbacks const core_callbacks = {
453 core_attach_address_callback,
454 unimp_device_detach_address,
455 unimp_device_io_read_buffer,
456 unimp_device_io_write_buffer,
457 core_dma_read_buffer_callback,
458 core_dma_write_buffer_callback,
459 unimp_device_attach_interrupt,
460 unimp_device_detach_interrupt,
461 unimp_device_interrupt,
462 unimp_device_interrupt_ack,
467 INLINE_CORE const device *
468 core_device_create(core *memory)
470 return device_create_from("core", "/", memory, &core_callbacks, NULL);
475 /* define the read/write 1/2/4/8/word functions */
497 #endif /* _CORE_C_ */