| 
					
				 | 
			
			
				@@ -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); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 |