#include "common.h" #include "io.h" #include "abcio.h" #include "sys.h" #include "console.h" #include "config.h" /* Configure ABC memory map */ struct abc_mem_init { int addr; uint16_t len; uint8_t flags; enum sysvar_enum enable; const char *data; /* May not actually be const, but... */ }; #define RD (ABCMEMMAP_RD >> 24) #define WR (ABCMEMMAP_WR >> 24) extern const char rom_ufddos80[]; extern const char rom_ufddos800[]; extern const char rom_print80_29[]; /* Not really NV, but matches NVRAM in some expansions */ static char __dram_bss __aligned(512) abc80_nvram[2 << 10]; /* 16K external memory to expand to 512K */ static char __dram_bss __aligned(512) abc80_extmem[16 << 10]; static const struct abc_mem_init mem_init_abc80[] = { { 0x5000, 2 << 10, RD|WR, config_abc_mem_abc80_nvram, abc80_nvram }, { 0x6000, 4 << 10, RD, config_abc_mem_abc80_ufddos, rom_ufddos80 }, { 0x7400, 1 << 10, RD, config_abc_mem_abc80_pun80, rom_print80_29 }, { 0x8000, 16 << 10, RD|WR, config_abc_mem_abc80_ram, abc80_extmem }, { -1, 0, 0, sysvar_null, NULL } }; static const struct abc_mem_init mem_init_abc800[] = { { 0x6000, 4 << 10, RD, config_abc_mem_abc800_ufddos, rom_ufddos800 }, { -1, 0, 0, sysvar_null, NULL } }; #define ABC_PAGE_SHIFT 9 #define ABC_PAGE_SIZE (1U << ABC_PAGE_SHIFT) #define ABC_PAGE_MASK (0xffff & ~(ABC_PAGE_SIZE-1)) #define ABC_PAGE_COUNT (0x10000 >> ABC_PAGE_SHIFT) void __cold abc_init_memmap(void) { uint32_t *memmap = calloc(sizeof(uint32_t), ABC_PAGE_COUNT); const struct abc_mem_init *mem; if (!memmap) { con_printf("abcmem: memory map initialization failure\n"); return; } mem = is_abc800() ? mem_init_abc800 : mem_init_abc80; while (mem->addr >= 0) { if (!mem->len) continue; bool bad = ((mem->addr|mem->len) & ~ABC_PAGE_MASK) || (mem->addr+mem->len > 0x10000); bool enabled = !bad && (!mem->enable || getvar_bool(mem->enable)); con_printf("abcmem: %s memory range @ 0x%04x len 0x%04x\n", bad ? "invalid" : !enabled ? "ignoring" : mem->data ? "mapping" : "unmapping", mem->addr, mem->len); if (enabled) { uint32_t *pg = &memmap[mem->addr >> ABC_PAGE_SHIFT]; uint32_t flags = mem->flags << 24; if (mem->data) { /* Mapped range */ for (unsigned int bytes = 0; bytes < mem->len; bytes += ABC_PAGE_SIZE) { *pg++ = ((size_t)(mem->data + bytes) & SDRAM_MASK) | flags; } } else { /* Unmapped range */ memset(pg, 0, mem->len >> (ABC_PAGE_SHIFT-2)); } } mem++; } memcpy((void *)&ABCMEMMAP_PAGE(0), memmap, ABC_PAGE_COUNT*sizeof(uint32_t)); free(memmap); }