123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154 |
- #include "common.h"
- #include "io.h"
- #include "abcio.h"
- #include "sys.h"
- #include "console.h"
- #include "config.h"
- #include "roms.h"
- /* Configure ABC memory map */
- struct rom {
- const char *data;
- size_t len;
- const char *name;
- };
- struct abc_mem_init {
- int addr;
- uint32_t flags;
- enum sysvar_enum enable;
- struct rom r;
- };
- /* Convenience aliases */
- #define MAPS ABCMEMMAP_MAPS
- #define PAGE_SHIFT ABCMEMMAP_PAGE_SHIFT
- #define PAGE_SIZE ABCMEMMAP_PAGE_SIZE
- #define PAGE_MASK ABCMEMMAP_PAGE_MASK
- #define PAGE_COUNT ABCMEMMAP_PAGE_COUNT
- #define PERMAP (PAGE_COUNT / MAPS)
- #define RD ABCMEMMAP_RD
- #define WR ABCMEMMAP_WR
- #define XM ABCMEMMAP_XM
- #define K 1024
- #define R(x) { (x), sizeof(x), #x }
- #define END { -1, 0, sysvar_null, { NULL, 0, NULL } }
- /* ---- ABC80 memory configurations ---- */
- /* Not really NV, but matches NVRAM in some expansions */
- static char __dram_bss __aligned(PAGE_SIZE) abc80_nvram[2][2*K];
- /* 16K external memory to expand to 512K */
- static char __dram_bss __aligned(PAGE_SIZE) abc80_extmem[16*K];
- static const struct abc_mem_init mem_init_abc80[] = {
- /* Put these here in case someone wants to enable both */
- { 20*K, RD|WR, config_abc_mem_abc80_nvram_20k, R(abc80_nvram[0]) },
- { 22*K, RD|WR, config_abc_mem_abc80_nvram_22k, R(abc80_nvram[1]) },
- { 16*K, RD, config_abc_mem_abc80_smartaid3, R(rom_abc80_smartaid3) },
- { 16*K, RD, config_abc_mem_abc80_superbasic, R(rom_abc80_superbasic16k) },
- { 20*K, RD, config_abc_mem_abc80_abc80l, R(rom_abc80_abc80l) },
- { 28*K, RD, config_abc_mem_abc80_superbasic, R(rom_abc80_superbasic28k) },
- { 32*K, RD|WR, config_abc_mem_abc80_ram, R(abc80_extmem) },
- END
- };
- static const struct abc_mem_init mem_init_abc80_nvram_20k[] = {
- { 24*K, RD, config_abc_mem_abc80_ufddos, R(rom_abc80_nvram_20k_ufddos80) },
- { 28*K, RD, config_abc_mem_abc80_pun80_28k, R(rom_abc80_nvram_20k_print80_28) },
- { 29*K, RD, config_abc_mem_abc80_pun80_29k, R(rom_abc80_nvram_20k_print80_29) },
- { 30*K, RD, config_abc_mem_abc80_pun80_30k, R(rom_abc80_nvram_20k_print80_30) },
- END
- };
- static const struct abc_mem_init mem_init_abc80_nvram_22k[] = {
- { 24*K, RD, config_abc_mem_abc80_ufddos, R(rom_abc80_nvram_22k_ufddos80) },
- { 28*K, RD, config_abc_mem_abc80_pun80_28k, R(rom_abc80_nvram_22k_print80_28) },
- { 29*K, RD, config_abc_mem_abc80_pun80_29k, R(rom_abc80_nvram_22k_print80_29) },
- { 30*K, RD, config_abc_mem_abc80_pun80_30k, R(rom_abc80_nvram_22k_print80_30) },
- END
- };
- static const struct abc_mem_init mem_init_abc80_no_nvram[] = {
- { 24*K, RD, config_abc_mem_abc80_ufddos, R(rom_abc80_no_nvram_ufddos80) },
- { 28*K, RD, config_abc_mem_abc80_pun80_28k, R(rom_abc80_no_nvram_print80_28) },
- { 29*K, RD, config_abc_mem_abc80_pun80_29k, R(rom_abc80_no_nvram_print80_29) },
- { 30*K, RD, config_abc_mem_abc80_pun80_30k, R(rom_abc80_no_nvram_print80_30) },
- END
- };
- /* ---- ABC800 memory configurations ---- */
- static const struct abc_mem_init mem_init_abc800[] = {
- { 24*K, RD, config_abc_mem_abc800_ufddos, R(rom_abc800_ufddos) },
- END
- };
- static void abc_map_list(uint32_t *memmap, const struct abc_mem_init *mem)
- {
- while (mem->addr >= 0) {
- bool enabled = !mem->enable || getvar_bool(mem->enable);
- const void *data = mem->r.data;
- size_t len = mem->r.len;
- if (!len)
- continue; /* Empty range, skip */
- uint32_t addr = mem->addr;
- bool bad = ((addr | len) & ~PAGE_MASK) ||
- (len > 0x10000 - addr) ||
- ((size_t)data & (PAGE_SIZE-1));
- con_printf("abcmem: %s %s @ 0x%04x len 0x%04x\n",
- mem->r.name ? mem->r.name : "(none)",
- bad ? "invalid" :
- !enabled ? "disabled" :
- data ? "mapping" : "unmapping",
- addr, len);
- if (enabled) {
- uint32_t *pg = &memmap[addr >> PAGE_SHIFT];
- uint32_t flags = mem->flags;
- if (data) {
- /* Mapped range */
- size_t pgv = (size_t)data | flags;
- for (uint32_t bytes = 0; bytes < len; bytes += PAGE_SIZE)
- *pg++ = pgv + bytes;
- } else {
- /* Unmapped range - set to 0 for clarity */
- memset(pg, 0, len >> (PAGE_SHIFT-2));
- }
- }
- mem++;
- }
- }
- void __cold abc_init_memmap(void)
- {
- static uint32_t memmap[MAPS][PERMAP]; /* Too big to fit on stack */
- const struct abc_mem_init *mem;
- memset(memmap, 0, sizeof memmap);
- /*
- * Currently the only map that gets populated is map 0; the
- * remaining map(s) get cleared by the memset() above.
- */
- if (is_abc800()) {
- abc_map_list(memmap[0], mem_init_abc800);
- } else {
- /* Put 22K first so UFD-DOS/PUN80 memory always is put at the end */
- if (getvar_bool(config_abc_mem_abc80_nvram_22k))
- abc_map_list(memmap[0], mem_init_abc80_nvram_22k);
- else if (getvar_bool(config_abc_mem_abc80_nvram_20k))
- abc_map_list(memmap[0], mem_init_abc80_nvram_20k);
- else
- abc_map_list(memmap[0], mem_init_abc80_no_nvram);
- abc_map_list(memmap[0], mem_init_abc80);
- }
- /* Install memory map into hardware registers */
- memcpy((void *)&ABCMEMMAP_PAGE(0), memmap, sizeof memmap);
- }
|