abcmem.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. #include "common.h"
  2. #include "io.h"
  3. #include "abcio.h"
  4. #include "sys.h"
  5. #include "console.h"
  6. #include "config.h"
  7. #include "roms.h"
  8. /* Configure ABC memory map */
  9. struct data_len {
  10. const char *data;
  11. size_t len;
  12. };
  13. struct abc_mem_init {
  14. int addr;
  15. uint32_t flags;
  16. enum sysvar_enum enable;
  17. struct data_len dl;
  18. };
  19. #define RD ABCMEMMAP_RD
  20. #define WR ABCMEMMAP_WR
  21. #define K 1024
  22. #define DD(x) { (x), sizeof(x) }
  23. #define END { -1, 0, sysvar_null, { NULL, 0 } }
  24. /* ---- ABC80 memory configurations ---- */
  25. /* Not really NV, but matches NVRAM in some expansions */
  26. static char __dram_bss __aligned(512) abc80_nvram[2][2*K];
  27. /* 16K external memory to expand to 512K */
  28. static char __dram_bss __aligned(512) abc80_extmem[16*K];
  29. static const struct abc_mem_init mem_init_abc80[] = {
  30. /* Put these here in case someone wants to enable both */
  31. { 20*K, RD|WR, config_abc_mem_abc80_nvram_20k, DD(abc80_nvram[0]) },
  32. { 22*K, RD|WR, config_abc_mem_abc80_nvram_22k, DD(abc80_nvram[1]) },
  33. { 16*K, RD, config_abc_mem_abc80_smartaid3, DD(rom_abc80_smartaid3) },
  34. { 16*K, RD, config_abc_mem_abc80_superbasic, DD(rom_abc80_superbasic16k) },
  35. { 20*K, RD, config_abc_mem_abc80_abc80l, DD(rom_abc80_abc80l) },
  36. { 28*K, RD, config_abc_mem_abc80_superbasic, DD(rom_abc80_superbasic28k) },
  37. { 32*K, RD|WR, config_abc_mem_abc80_ram, DD(abc80_extmem) },
  38. END
  39. };
  40. static const struct abc_mem_init mem_init_abc80_nvram_20k[] = {
  41. { 24*K, RD, config_abc_mem_abc80_ufddos, DD(rom_abc80_nvram_20k_ufddos80) },
  42. { 28*K, RD, config_abc_mem_abc80_pun80_28k, DD(rom_abc80_nvram_20k_print80_28) },
  43. { 29*K, RD, config_abc_mem_abc80_pun80_29k, DD(rom_abc80_nvram_20k_print80_29) },
  44. { 30*K, RD, config_abc_mem_abc80_pun80_30k, DD(rom_abc80_nvram_20k_print80_30) },
  45. END
  46. };
  47. static const struct abc_mem_init mem_init_abc80_nvram_22k[] = {
  48. { 24*K, RD, config_abc_mem_abc80_ufddos, DD(rom_abc80_nvram_22k_ufddos80) },
  49. { 28*K, RD, config_abc_mem_abc80_pun80_28k, DD(rom_abc80_nvram_22k_print80_28) },
  50. { 29*K, RD, config_abc_mem_abc80_pun80_29k, DD(rom_abc80_nvram_22k_print80_29) },
  51. { 30*K, RD, config_abc_mem_abc80_pun80_30k, DD(rom_abc80_nvram_22k_print80_30) },
  52. END
  53. };
  54. static const struct abc_mem_init mem_init_abc80_no_nvram[] = {
  55. { 24*K, RD, config_abc_mem_abc80_ufddos, DD(rom_abc80_no_nvram_ufddos80) },
  56. { 28*K, RD, config_abc_mem_abc80_pun80_28k, DD(rom_abc80_no_nvram_print80_28) },
  57. { 29*K, RD, config_abc_mem_abc80_pun80_29k, DD(rom_abc80_no_nvram_print80_29) },
  58. { 30*K, RD, config_abc_mem_abc80_pun80_30k, DD(rom_abc80_no_nvram_print80_30) },
  59. END
  60. };
  61. /* ---- ABC800 memory configurations ---- */
  62. static const struct abc_mem_init mem_init_abc800[] = {
  63. { 24*K, RD, config_abc_mem_abc800_ufddos, DD(rom_abc800_ufddos) },
  64. END
  65. };
  66. #define ABC_PAGE_SHIFT 9
  67. #define ABC_PAGE_SIZE (1U << ABC_PAGE_SHIFT)
  68. #define ABC_PAGE_MASK (0xffff & ~(ABC_PAGE_SIZE-1))
  69. #define ABC_PAGE_COUNT (0x10000 >> ABC_PAGE_SHIFT)
  70. static void abc_map_list(uint32_t *memmap, const struct abc_mem_init *mem)
  71. {
  72. while (mem->addr >= 0) {
  73. bool enabled = !mem->enable || getvar_bool(mem->enable);
  74. const void *data = mem->dl.data;
  75. size_t len = mem->dl.len;
  76. if (!len)
  77. continue; /* Empty range, skip */
  78. uint32_t addr = mem->addr;
  79. bool bad = ((addr | len) & ~ABC_PAGE_MASK) ||
  80. len > 0x10000 - addr ||
  81. (size_t)data & (ABC_PAGE_SIZE-1);
  82. con_printf("abcmem: %s memory range @ 0x%04x len 0x%04x\n",
  83. bad ? "invalid" : !enabled ? "ignoring" :
  84. data ? "mapping" : "unmapping",
  85. addr, len);
  86. if (enabled) {
  87. uint32_t *pg = &memmap[addr >> ABC_PAGE_SHIFT];
  88. uint32_t flags = mem->flags;
  89. if (!data) {
  90. /* Mapped range */
  91. for (uint32_t bytes = 0; bytes < len; bytes += ABC_PAGE_SIZE)
  92. *pg++ = ((size_t)(data + bytes) & SDRAM_MASK) | flags;
  93. } else {
  94. /* Unmapped range - set to 0 for clarity */
  95. memset(pg, 0, len >> (ABC_PAGE_SHIFT-2));
  96. }
  97. }
  98. mem++;
  99. }
  100. }
  101. void __cold abc_init_memmap(void)
  102. {
  103. uint32_t *memmap = calloc(sizeof(uint32_t), ABC_PAGE_COUNT);
  104. const struct abc_mem_init *mem;
  105. if (!memmap) {
  106. con_printf("abcmem: memory map initialization failure\n");
  107. return;
  108. }
  109. if (is_abc800()) {
  110. abc_map_list(memmap, mem_init_abc800);
  111. } else {
  112. /* Put 22K first so UFD-DOS/PUN80 memory always is put at the end */
  113. if (getvar_bool(config_abc_mem_abc80_nvram_22k))
  114. abc_map_list(memmap, mem_init_abc80_nvram_22k);
  115. else if (getvar_bool(config_abc_mem_abc80_nvram_20k))
  116. abc_map_list(memmap, mem_init_abc80_nvram_20k);
  117. else
  118. abc_map_list(memmap, mem_init_abc80_no_nvram);
  119. abc_map_list(memmap, mem_init_abc80);
  120. }
  121. /* Install memory map into hardware registers */
  122. memcpy((void *)&ABCMEMMAP_PAGE(0), memmap,
  123. ABC_PAGE_COUNT*sizeof(uint32_t));
  124. free(memmap);
  125. }