/* This file is part of the program psim.
- Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
+ Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
#ifndef _CORE_C_
#define _CORE_C_
-#ifndef STATIC_INLINE_CORE
-#define STATIC_INLINE_CORE STATIC_INLINE
-#endif
-
-
#include "basics.h"
-#include "device_tree.h"
+#include "device_table.h"
#include "corefile.h"
-
typedef struct _core_mapping core_mapping;
struct _core_mapping {
- /* ram map */
- int free_buffer;
- void *buffer;
- /* device map */
- const device *device;
- device_io_read_buffer_callback *reader;
- device_io_write_buffer_callback *writer;
/* common */
+ int level;
int space;
unsigned_word base;
unsigned_word bound;
unsigned nr_bytes;
+ /* memory map */
+ void *free_buffer;
+ void *buffer;
+ /* callback map */
+ device *device;
+ /* growth */
core_mapping *next;
};
struct _core_map {
core_mapping *first;
- core_mapping *default_map;
};
typedef enum {
};
-INLINE_CORE core *
+INLINE_CORE\
+(core *)
core_create(void)
{
- core *new_core = ZALLOC(core);
- return new_core;
+ return ZALLOC(core);
}
-STATIC_INLINE_CORE void
+INLINE_CORE\
+(core *)
+core_from_device(device *root)
+{
+ root = device_root(root);
+ ASSERT(strcmp(device_name(root), "core") == 0);
+ return device_data(root);
+}
+
+
+INLINE_CORE\
+(void)
core_init(core *memory)
{
core_map_types access_type;
while (curr != NULL) {
core_mapping *tbd = curr;
curr = curr->next;
- if (tbd->free_buffer) {
+ if (tbd->free_buffer != NULL) {
ASSERT(tbd->buffer != NULL);
- zfree(tbd->buffer);
+ zfree(tbd->free_buffer);
}
zfree(tbd);
}
map->first = NULL;
- /* blow away the default */
- if (map->default_map != NULL) {
- ASSERT(map->default_map->buffer == NULL);
- zfree(map->default_map);
- }
- map->default_map = NULL;
}
}
/* the core has three sub mappings that the more efficient
read/write fixed quantity functions use */
-INLINE_CORE core_map *
+INLINE_CORE\
+(core_map *)
core_readable(core *memory)
{
return memory->map + core_read_map;
}
-INLINE_CORE core_map *
+INLINE_CORE\
+(core_map *)
core_writeable(core *memory)
{
return memory->map + core_write_map;
}
-INLINE_CORE core_map *
+INLINE_CORE\
+(core_map *)
core_executable(core *memory)
{
return memory->map + core_execute_map;
-STATIC_INLINE_CORE core_mapping *
+STATIC_INLINE_CORE\
+(core_mapping *)
new_core_mapping(attach_type attach,
int space,
unsigned_word addr,
unsigned nr_bytes,
- const device *device,
+ device *device,
void *buffer,
- int free_buffer)
+ void *free_buffer)
{
core_mapping *new_mapping = ZALLOC(core_mapping);
- switch (attach) {
- case attach_default:
- case attach_callback:
- new_mapping->device = device;
- new_mapping->reader = device->callback->io_read_buffer;
- new_mapping->writer = device->callback->io_write_buffer;
- break;
- case attach_raw_memory:
- new_mapping->buffer = buffer;
- new_mapping->free_buffer = free_buffer;
- break;
- default:
- error("new_core_mapping() - internal error - unknown attach type %d\n",
- attach);
- }
/* common */
+ new_mapping->level = attach;
new_mapping->space = space;
new_mapping->base = addr;
new_mapping->nr_bytes = nr_bytes;
new_mapping->bound = addr + (nr_bytes - 1);
+ if (attach == attach_raw_memory) {
+ new_mapping->buffer = buffer;
+ new_mapping->free_buffer = free_buffer;
+ }
+ else if (attach >= attach_callback) {
+ new_mapping->device = device;
+ }
+ else {
+ error("new_core_mapping() - internal error - unknown attach type %d\n",
+ attach);
+ }
return new_mapping;
}
-STATIC_INLINE_CORE void
+STATIC_INLINE_CORE\
+(void)
core_map_attach(core_map *access_map,
attach_type attach,
int space,
unsigned_word addr,
unsigned nr_bytes, /* host limited */
- const device *device, /*callback/default*/
+ device *client, /*callback/default*/
void *buffer, /*raw_memory*/
- int free_buffer) /*raw_memory*/
+ void *free_buffer) /*raw_memory*/
{
- if (attach == attach_default) {
- if (access_map->default_map != NULL)
- error("core_map_attach() default mapping already in place\n");
- ASSERT(buffer == NULL);
- access_map->default_map = new_core_mapping(attach,
- space, addr, nr_bytes,
- device, buffer, free_buffer);
+ /* find the insertion point for this additional mapping and insert */
+ core_mapping *next_mapping;
+ core_mapping **last_mapping;
+
+ /* actually do occasionally get a zero size map */
+ if (nr_bytes == 0) {
+ device_error(client, "called on core_map_attach() with size zero");
}
- else {
- /* find the insertion point for this additional mapping and insert */
- core_mapping *next_mapping;
- core_mapping **last_mapping;
-
- /* actually do occasionally get a zero size map */
- if (nr_bytes == 0)
- error("core_map_attach() size == 0\n");
-
- /* find the insertion point (between last/next) */
- next_mapping = access_map->first;
- last_mapping = &access_map->first;
- while(next_mapping != NULL && next_mapping->bound < addr) {
- /* assert: next_mapping->base > all bases before next_mapping */
- /* assert: next_mapping->bound >= all bounds before next_mapping */
- last_mapping = &next_mapping->next;
- next_mapping = next_mapping->next;
- }
- /* check insertion point correct */
- if (next_mapping != NULL && next_mapping->base < (addr + (nr_bytes - 1))) {
- error("core_map_attach() map overlap\n");
- }
+ /* find the insertion point (between last/next) */
+ next_mapping = access_map->first;
+ last_mapping = &access_map->first;
+ while(next_mapping != NULL
+ && (next_mapping->level < attach
+ || (next_mapping->level == attach
+ && next_mapping->bound < addr))) {
+ /* provided levels are the same */
+ /* assert: next_mapping->base > all bases before next_mapping */
+ /* assert: next_mapping->bound >= all bounds before next_mapping */
+ last_mapping = &next_mapping->next;
+ next_mapping = next_mapping->next;
+ }
- /* create/insert the new mapping */
- *last_mapping = new_core_mapping(attach,
- space, addr, nr_bytes,
- device, buffer, free_buffer);
- (*last_mapping)->next = next_mapping;
+ /* check insertion point correct */
+ ASSERT(next_mapping == NULL || next_mapping->level >= attach);
+ if (next_mapping != NULL && next_mapping->level == attach
+ && next_mapping->base < (addr + (nr_bytes - 1))) {
+ device_error(client, "map overlap when attaching %d:0x%lx (%ld)",
+ space, (long)addr, (long)nr_bytes);
}
+
+ /* create/insert the new mapping */
+ *last_mapping = new_core_mapping(attach,
+ space, addr, nr_bytes,
+ client, buffer, free_buffer);
+ (*last_mapping)->next = next_mapping;
}
-INLINE_CORE void
+INLINE_CORE\
+(void)
core_attach(core *memory,
attach_type attach,
int space,
access_type access,
unsigned_word addr,
unsigned nr_bytes, /* host limited */
- const device *device) /*callback/default*/
+ device *client) /*callback/default*/
{
core_map_types access_map;
- int free_buffer = 0;
- void *buffer = NULL;
- ASSERT(attach == attach_default || nr_bytes > 0);
- if (attach == attach_raw_memory)
- buffer = zalloc(nr_bytes);
+ void *buffer;
+ void *free_buffer;
+ if (attach == attach_raw_memory) {
+ /* Padd out the raw buffer to ensure that ADDR starts on a
+ correctly aligned boundary */
+ int padding = (addr % sizeof (unsigned64));
+ free_buffer = zalloc(nr_bytes + padding);
+ buffer = (char*)free_buffer + padding;
+ }
+ else {
+ buffer = NULL;
+ free_buffer = &buffer; /* marker for assertion */
+ }
for (access_map = 0;
access_map < nr_core_map_types;
access_map++) {
core_map_attach(memory->map + access_map,
attach,
space, addr, nr_bytes,
- device, buffer, !free_buffer);
- free_buffer ++;
+ client, buffer, free_buffer);
+ free_buffer = NULL;
break;
case core_write_map:
if (access & access_write)
core_map_attach(memory->map + access_map,
attach,
space, addr, nr_bytes,
- device, buffer, !free_buffer);
- free_buffer ++;
+ client, buffer, free_buffer);
+ free_buffer = NULL;
break;
case core_execute_map:
if (access & access_exec)
core_map_attach(memory->map + access_map,
attach,
space, addr, nr_bytes,
- device, buffer, !free_buffer);
- free_buffer ++;
+ client, buffer, free_buffer);
+ free_buffer = NULL;
break;
default:
error("core_attach() internal error\n");
break;
}
}
- ASSERT(free_buffer > 0); /* must attach to at least one thing */
+ /* allocated buffer must attach to at least one thing */
+ ASSERT(free_buffer == NULL);
}
-STATIC_INLINE_CORE core_mapping *
+STATIC_INLINE_CORE\
+(core_mapping *)
core_map_find_mapping(core_map *map,
unsigned_word addr,
unsigned nr_bytes,
return mapping;
mapping = mapping->next;
}
- if (map->default_map != NULL)
- return map->default_map;
if (abort)
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",
addr, nr_bytes, processor, cia);
}
-STATIC_INLINE_CORE void *
+STATIC_INLINE_CORE\
+(void *)
core_translate(core_mapping *mapping,
- unsigned_word addr)
+ unsigned_word addr)
{
- return mapping->buffer + addr - mapping->base;
+ return (void *)(((char *)mapping->buffer) + addr - mapping->base);
}
-INLINE_CORE unsigned
+INLINE_CORE\
+(unsigned)
core_map_read_buffer(core_map *map,
void *buffer,
unsigned_word addr,
unsigned len)
{
- unsigned count;
- unsigned_1 byte;
- for (count = 0; count < len; count++) {
+ unsigned count = 0;
+ while (count < len) {
unsigned_word raddr = addr + count;
core_mapping *mapping =
core_map_find_mapping(map,
0); /*dont-abort*/
if (mapping == NULL)
break;
- if (mapping->reader != NULL) {
- if (mapping->reader(mapping->device,
- &byte,
- mapping->space,
- raddr - mapping->base,
- 1, /* nr_bytes */
- 0, /*processor*/
- 0 /*cpu*/) != 1)
+ if (mapping->device != NULL) {
+ int nr_bytes = len - count;
+ if (raddr + nr_bytes - 1> mapping->bound)
+ nr_bytes = mapping->bound - raddr + 1;
+ if (device_io_read_buffer(mapping->device,
+ (unsigned_1*)buffer + count,
+ mapping->space,
+ raddr,
+ nr_bytes,
+ 0, /*processor*/
+ 0 /*cpu*/) != nr_bytes)
break;
+ count += nr_bytes;
+ }
+ else {
+ ((unsigned_1*)buffer)[count] =
+ *(unsigned_1*)core_translate(mapping, raddr);
+ count += 1;
}
- else
- byte = *(unsigned_1*)core_translate(mapping,
- raddr);
- ((unsigned_1*)buffer)[count] = T2H_1(byte);
}
return count;
}
-INLINE_CORE unsigned
+INLINE_CORE\
+(unsigned)
core_map_write_buffer(core_map *map,
const void *buffer,
unsigned_word addr,
unsigned len)
{
- unsigned count;
- unsigned_1 byte;
- for (count = 0; count < len; count++) {
+ unsigned count = 0;
+ while (count < len) {
unsigned_word raddr = addr + count;
core_mapping *mapping = core_map_find_mapping(map,
raddr, 1,
0); /*dont-abort*/
if (mapping == NULL)
break;
- byte = H2T_1(((unsigned_1*)buffer)[count]);
- if (mapping->writer != NULL) {
- if (mapping->writer(mapping->device,
- &byte,
- mapping->space,
- raddr - mapping->base,
- 1, /*nr_bytes*/
- 0, /*processor*/
- 0 /*cpu*/) != 1)
+ if (mapping->device != NULL) {
+ int nr_bytes = len - count;
+ if (raddr + nr_bytes - 1 > mapping->bound)
+ nr_bytes = mapping->bound - raddr + 1;
+ if (device_io_write_buffer(mapping->device,
+ (unsigned_1*)buffer + count,
+ mapping->space,
+ raddr,
+ nr_bytes,
+ 0, /*processor*/
+ 0 /*cpu*/) != nr_bytes)
break;
+ count += nr_bytes;
+ }
+ else {
+ *(unsigned_1*)core_translate(mapping, raddr) =
+ ((unsigned_1*)buffer)[count];
+ count += 1;
}
- else
- *(unsigned_1*)core_translate(mapping, raddr) = byte;
}
return count;
}
-
-/* Top level core(root) device: core@garbage
-
- The core device captures incomming dma requests and changes them to
- outgoing io requests. */
-
-STATIC_INLINE_CORE void
-core_init_callback(const device *me,
- psim *system)
-{
- core *memory = (core*)me->data;
- DTRACE_INIT(core);
- core_init(memory);
-}
-
-
-STATIC_INLINE_CORE void
-core_attach_address_callback(const device *me,
- const char *name,
- attach_type attach,
- int space,
- unsigned_word addr,
- unsigned nr_bytes,
- access_type access,
- const device *who) /*callback/default*/
-{
- core *memory = (core*)me->data;
- unsigned_word device_address;
- DTRACE_ATTACH_ADDRESS(core);
- if (space != 0)
- error("core_attach_address_callback() invalid address space\n");
- core_attach(memory,
- attach,
- space,
- access,
- addr,
- nr_bytes,
- who);
-}
-
-
-STATIC_INLINE_CORE unsigned
-core_dma_read_buffer_callback(const device *me,
- void *dest,
- int space,
- unsigned_word addr,
- unsigned nr_bytes)
-{
- core *memory = (core*)me->data;
- DTRACE_DMA_READ_BUFFER(core);
- return core_map_read_buffer(core_readable(memory),
- dest,
- addr,
- nr_bytes);
-}
-
-
-STATIC_INLINE_CORE unsigned
-core_dma_write_buffer_callback(const device *me,
- const void *source,
- int space,
- unsigned_word addr,
- unsigned nr_bytes,
- int violate_read_only_section)
-{
- core *memory = (core*)me->data;
- core_map *map = (violate_read_only_section
- ? core_readable(memory)
- : core_writeable(memory));
- DTRACE_DMA_WRITE_BUFFER(core);
- return core_map_write_buffer(map,
- source,
- addr,
- nr_bytes);
-}
-
-
-static device_callbacks const core_callbacks = {
- core_init_callback,
- core_attach_address_callback,
- unimp_device_detach_address,
- unimp_device_io_read_buffer,
- unimp_device_io_write_buffer,
- core_dma_read_buffer_callback,
- core_dma_write_buffer_callback,
- unimp_device_attach_interrupt,
- unimp_device_detach_interrupt,
- unimp_device_interrupt,
- unimp_device_interrupt_ack,
- unimp_device_ioctl,
-};
-
-
-INLINE_CORE const device *
-core_device_create(core *memory)
-{
- return device_create_from("core", "/", memory, &core_callbacks, NULL);
-}
-
-
-
/* define the read/write 1/2/4/8/word functions */
-#undef N
#define N 1
-#include "core_n.h"
-
+#include "corefile-n.h"
#undef N
-#define N 2
-#include "core_n.h"
+#define N 2
+#include "corefile-n.h"
#undef N
-#define N 4
-#include "core_n.h"
+#define N 4
+#include "corefile-n.h"
#undef N
-#define N 8
-#include "core_n.h"
+#define N 8
+#include "corefile-n.h"
#undef N
+
#define N word
-#include "core_n.h"
+#include "corefile-n.h"
+#undef N
#endif /* _CORE_C_ */