/* Copyright (c) 2013-2017 GomSpace A/S. All rights reserved. */ #include #include #include #include #include static const gs_vmem_t * g_vmem_map; gs_error_t gs_vmem_set_map(const gs_vmem_t * map) { g_vmem_map = map; return GS_OK; } const gs_vmem_t * gs_vmem_get_map(void) { return g_vmem_map; } gs_error_t gs_vmem_list(FILE * out) { const gs_vmem_t * mem = g_vmem_map; if (mem) { unsigned int found = 0; for (; mem->name; ++mem) { if (found == 0) { fprintf(out, "%-20s %-10s %-6s %-6s %s\r\n", "name", "virt.", "phys.", "size", "size"); } fprintf(out, "%-20s %p 0x%04x 0x%04x %5u\r\n", mem->name, mem->virtmem.p, (unsigned int) mem->physmem.u, (unsigned int) mem->size, (unsigned int) mem->size); ++found; } if (found) { return GS_OK; } } return GS_ERROR_NOT_FOUND; } const gs_vmem_t * gs_vmem_get_by_name(const char * name) { if (name) { const gs_vmem_t * mem = g_vmem_map; if (mem) { for (; mem->name; ++mem) { if (strcasecmp(name, mem->name) == 0) { return mem; } } } } return NULL; } gs_error_t gs_vmem_lock_by_name(const char * name, bool on) { const gs_vmem_t * mem = gs_vmem_get_by_name(name); if (mem) { if (mem->drv && mem->drv->lock) { return (mem->drv->lock)(mem, on); } return GS_ERROR_NOT_SUPPORTED; } return GS_ERROR_NOT_FOUND; } gs_error_t gs_vmem_lock_all(bool on) { const gs_vmem_t * mem = g_vmem_map; if (mem) { unsigned int locked = 0; for (; mem->name; ++mem) { if (mem->drv && mem->drv->lock) { (mem->drv->lock)(mem, on); ++locked; } } if (locked) { return GS_OK; } } return GS_ERROR_NOT_FOUND; } /** @note NO LOGGING - currently the log system uses this interface, and logging can therefor create circular/forever loops. */ void * gs_vmem_cpy(void* to, const void* from, size_t size) { /* Search memories */ const gs_vmem_t *vmem_from = NULL; const gs_vmem_t *vmem_to = NULL; const gs_vmem_t *mem = g_vmem_map; const gs_address_t _to = {.p = to}; const gs_address_t _from = {.p = (void*) from}; if (mem) { while(mem->size != 0) { //printf("0x%lx 0x%lx %"PRIu32" %lu %lu\r\n", mem->start, mem->physmem_start, mem->size, to, from); if ((_to.u >= mem->virtmem.u) && (_to.u < mem->virtmem.u + mem->size)) { vmem_to = mem; } if ((_from.u >= mem->virtmem.u) && (_from.u < mem->virtmem.u + mem->size)) { vmem_from = mem; } mem++; } } // VMEM -> VMEM if (vmem_to && vmem_from) { printf("%s: VMEM to VMEM is not supported\r\n", __FUNCTION__); return NULL; } // RAM -> VMEM if (vmem_to) { if ((vmem_to->drv == NULL) || (vmem_to->drv->write == NULL)) { printf("%s: Writting to VMEM %p is not supported\r\n", __FUNCTION__, to); return NULL; } gs_address_t physaddr = {.u = (_to.u - vmem_to->virtmem.u) + vmem_to->physmem.u}; //printf("Copying from ram 0x%lx to physaddr 0x%lx %u\r\n", from, physaddr, (unsigned int) size); vmem_to->drv->write(vmem_to, physaddr.p, from, size); return to; } // VMEM -> RAM if (vmem_from) { if (vmem_from->drv == NULL || (vmem_from->drv->read == NULL)) { printf("%s: Reading from VMEM %p is not supported\r\n", __FUNCTION__, from); return NULL; } gs_address_t physaddr = {.u = (_from.u - vmem_from->virtmem.u) + vmem_from->physmem.u}; //printf("Copying from mem physaddr 0x%lx to 0x%lx %u\r\n", physaddr, to, (unsigned int) size); vmem_from->drv->read(vmem_from, to, physaddr.p, size); return to; } // RAM -> RAM (no VMEM mapping found) return memcpy(to, from, size); }