|
@@ -4,38 +4,73 @@
|
|
|
#include "sys.h"
|
|
|
#include "console.h"
|
|
|
#include "config.h"
|
|
|
+#include "roms.h"
|
|
|
|
|
|
/* Configure ABC memory map */
|
|
|
+struct data_len {
|
|
|
+ const char *data;
|
|
|
+ size_t len;
|
|
|
+};
|
|
|
struct abc_mem_init {
|
|
|
int addr;
|
|
|
- uint16_t len;
|
|
|
- uint8_t flags;
|
|
|
+ uint32_t flags;
|
|
|
enum sysvar_enum enable;
|
|
|
- const char *data; /* May not actually be const, but... */
|
|
|
+ struct data_len dl;
|
|
|
};
|
|
|
-#define RD (ABCMEMMAP_RD >> 24)
|
|
|
-#define WR (ABCMEMMAP_WR >> 24)
|
|
|
+#define RD ABCMEMMAP_RD
|
|
|
+#define WR ABCMEMMAP_WR
|
|
|
+
|
|
|
+#define K 1024
|
|
|
+#define DD(x) { (x), sizeof(x) }
|
|
|
+#define END { -1, 0, sysvar_null, { NULL, 0 } }
|
|
|
|
|
|
-extern const char rom_ufddos80[];
|
|
|
-extern const char rom_ufddos800[];
|
|
|
-extern const char rom_print80_29[];
|
|
|
+/* ---- ABC80 memory configurations ---- */
|
|
|
|
|
|
/* Not really NV, but matches NVRAM in some expansions */
|
|
|
-static char __dram_bss __aligned(512) abc80_nvram[2 << 10];
|
|
|
+static char __dram_bss __aligned(512) abc80_nvram[2][2*K];
|
|
|
|
|
|
/* 16K external memory to expand to 512K */
|
|
|
-static char __dram_bss __aligned(512) abc80_extmem[16 << 10];
|
|
|
+static char __dram_bss __aligned(512) abc80_extmem[16*K];
|
|
|
|
|
|
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 }
|
|
|
+ /* Put these here in case someone wants to enable both */
|
|
|
+ { 20*K, RD|WR, config_abc_mem_abc80_nvram_20k, DD(abc80_nvram[0]) },
|
|
|
+ { 22*K, RD|WR, config_abc_mem_abc80_nvram_22k, DD(abc80_nvram[1]) },
|
|
|
+
|
|
|
+ { 16*K, RD, config_abc_mem_abc80_smartaid3, DD(rom_abc80_smartaid3) },
|
|
|
+ { 16*K, RD, config_abc_mem_abc80_superbasic, DD(rom_abc80_superbasic16k) },
|
|
|
+ { 28*K, RD, config_abc_mem_abc80_superbasic, DD(rom_abc80_superbasic28k) },
|
|
|
+
|
|
|
+ { 32*K, RD|WR, config_abc_mem_abc80_ram, DD(abc80_extmem) },
|
|
|
+ END
|
|
|
+};
|
|
|
+static const struct abc_mem_init mem_init_abc80_nvram_20k[] = {
|
|
|
+ { 24*K, RD, config_abc_mem_abc80_ufddos, DD(rom_abc80_nvram_20k_ufddos80) },
|
|
|
+ { 28*K, RD, config_abc_mem_abc80_pun80_28k, DD(rom_abc80_nvram_20k_print80_28) },
|
|
|
+ { 29*K, RD, config_abc_mem_abc80_pun80_29k, DD(rom_abc80_nvram_20k_print80_29) },
|
|
|
+ { 30*K, RD, config_abc_mem_abc80_pun80_30k, DD(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, DD(rom_abc80_nvram_22k_ufddos80) },
|
|
|
+ { 28*K, RD, config_abc_mem_abc80_pun80_28k, DD(rom_abc80_nvram_22k_print80_28) },
|
|
|
+ { 29*K, RD, config_abc_mem_abc80_pun80_29k, DD(rom_abc80_nvram_22k_print80_29) },
|
|
|
+ { 30*K, RD, config_abc_mem_abc80_pun80_30k, DD(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, DD(rom_abc80_no_nvram_ufddos80) },
|
|
|
+ { 28*K, RD, config_abc_mem_abc80_pun80_28k, DD(rom_abc80_no_nvram_print80_28) },
|
|
|
+ { 29*K, RD, config_abc_mem_abc80_pun80_29k, DD(rom_abc80_no_nvram_print80_29) },
|
|
|
+ { 30*K, RD, config_abc_mem_abc80_pun80_30k, DD(rom_abc80_no_nvram_print80_30) },
|
|
|
+ END
|
|
|
+};
|
|
|
+
|
|
|
+/* ---- ABC800 memory configurations ---- */
|
|
|
+
|
|
|
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 }
|
|
|
+ { 24*K, RD, config_abc_mem_abc800_ufddos, DD(rom_abc800_ufddos) },
|
|
|
+ END
|
|
|
};
|
|
|
|
|
|
#define ABC_PAGE_SHIFT 9
|
|
@@ -43,47 +78,69 @@ static const struct abc_mem_init mem_init_abc800[] = {
|
|
|
#define ABC_PAGE_MASK (0xffff & ~(ABC_PAGE_SIZE-1))
|
|
|
#define ABC_PAGE_COUNT (0x10000 >> ABC_PAGE_SHIFT)
|
|
|
|
|
|
-void __cold abc_init_memmap(void)
|
|
|
+static void abc_map_list(uint32_t *memmap, const struct abc_mem_init *mem)
|
|
|
{
|
|
|
- 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 enabled = !mem->enable || getvar_bool(mem->enable);
|
|
|
+ const void *data = mem->dl.data;
|
|
|
+ size_t len = mem->dl.len;
|
|
|
+
|
|
|
+ if (!len)
|
|
|
+ continue; /* Empty range, skip */
|
|
|
|
|
|
- bool bad = ((mem->addr|mem->len) & ~ABC_PAGE_MASK) || (mem->addr+mem->len > 0x10000);
|
|
|
- bool enabled = !bad && (!mem->enable || getvar_bool(mem->enable));
|
|
|
+ uint32_t addr = mem->addr;
|
|
|
+ bool bad = ((addr | len) & ~ABC_PAGE_MASK) ||
|
|
|
+ len > 0x10000 - addr ||
|
|
|
+ (size_t)data & (ABC_PAGE_SIZE-1);
|
|
|
|
|
|
con_printf("abcmem: %s memory range @ 0x%04x len 0x%04x\n",
|
|
|
bad ? "invalid" : !enabled ? "ignoring" :
|
|
|
- mem->data ? "mapping" : "unmapping",
|
|
|
- mem->addr, mem->len);
|
|
|
+ data ? "mapping" : "unmapping",
|
|
|
+ addr, len);
|
|
|
|
|
|
if (enabled) {
|
|
|
- uint32_t *pg = &memmap[mem->addr >> ABC_PAGE_SHIFT];
|
|
|
- uint32_t flags = mem->flags << 24;
|
|
|
- if (mem->data) {
|
|
|
+ uint32_t *pg = &memmap[addr >> ABC_PAGE_SHIFT];
|
|
|
+ uint32_t flags = mem->flags;
|
|
|
+
|
|
|
+ if (!data) {
|
|
|
/* Mapped range */
|
|
|
- for (unsigned int bytes = 0; bytes < mem->len;
|
|
|
- bytes += ABC_PAGE_SIZE) {
|
|
|
- *pg++ = ((size_t)(mem->data + bytes) & SDRAM_MASK) | flags;
|
|
|
- }
|
|
|
+ for (uint32_t bytes = 0; bytes < len; bytes += ABC_PAGE_SIZE)
|
|
|
+ *pg++ = ((size_t)(data + bytes) & SDRAM_MASK) | flags;
|
|
|
} else {
|
|
|
- /* Unmapped range */
|
|
|
- memset(pg, 0, mem->len >> (ABC_PAGE_SHIFT-2));
|
|
|
+ /* Unmapped range - set to 0 for clarity */
|
|
|
+ memset(pg, 0, len >> (ABC_PAGE_SHIFT-2));
|
|
|
}
|
|
|
}
|
|
|
mem++;
|
|
|
}
|
|
|
+}
|
|
|
+
|
|
|
+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;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (is_abc800()) {
|
|
|
+ abc_map_list(memmap, 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, mem_init_abc80_nvram_22k);
|
|
|
+ else if (getvar_bool(config_abc_mem_abc80_nvram_20k))
|
|
|
+ abc_map_list(memmap, mem_init_abc80_nvram_20k);
|
|
|
+ else
|
|
|
+ abc_map_list(memmap, mem_init_abc80_no_nvram);
|
|
|
+
|
|
|
+ abc_map_list(memmap, mem_init_abc80);
|
|
|
+ }
|
|
|
|
|
|
- memcpy((void *)&ABCMEMMAP_PAGE(0), memmap, ABC_PAGE_COUNT*sizeof(uint32_t));
|
|
|
+ /* Install memory map into hardware registers */
|
|
|
+ memcpy((void *)&ABCMEMMAP_PAGE(0), memmap,
|
|
|
+ ABC_PAGE_COUNT*sizeof(uint32_t));
|
|
|
free(memmap);
|
|
|
}
|