abcmem.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  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 rom {
  10. const char *data;
  11. size_t len;
  12. const char *name;
  13. };
  14. struct abc_mem_init {
  15. int addr;
  16. uint32_t flags;
  17. enum sysvar_enum enable;
  18. struct rom r;
  19. };
  20. /* Convenience aliases */
  21. #define MAPS ABCMEMMAP_MAPS
  22. #define PAGE_SHIFT ABCMEMMAP_PAGE_SHIFT
  23. #define PAGE_SIZE ABCMEMMAP_PAGE_SIZE
  24. #define PAGE_MASK ABCMEMMAP_PAGE_MASK
  25. #define PAGE_COUNT ABCMEMMAP_PAGE_COUNT
  26. #define PERMAP (PAGE_COUNT / MAPS)
  27. #define RD ABCMEMMAP_RD
  28. #define WR ABCMEMMAP_WR
  29. #define XM ABCMEMMAP_XM
  30. #define K 1024
  31. #define R(x) { (x), sizeof(x), #x }
  32. #define END { -1, 0, sysvar_null, { NULL, 0, NULL } }
  33. /* ---- ABC80 memory configurations ---- */
  34. /* Not really NV, but matches NVRAM in some expansions */
  35. static char __dram_bss __aligned(PAGE_SIZE) abc80_nvram[2][2*K];
  36. /* ABC800MAC RAM */
  37. static char __dram_bss __aligned(PAGE_SIZE) abc800mac_ram[64*K];
  38. /* 16K external memory to expand to 512K */
  39. static char __dram_bss __aligned(PAGE_SIZE) abc80_extmem[16*K];
  40. static const struct abc_mem_init mem_init_abc80[] = {
  41. /* Put these here in case someone wants to enable both */
  42. { 20*K, RD|WR, config_abc_mem_abc80_nvram_20k, R(abc80_nvram[0]) },
  43. { 22*K, RD|WR, config_abc_mem_abc80_nvram_22k, R(abc80_nvram[1]) },
  44. { 16*K, RD, config_abc_mem_abc80_smartaid3, R(rom_abc80_smartaid3) },
  45. { 16*K, RD, config_abc_mem_abc80_superbasic, R(rom_abc80_superbasic16k) },
  46. { 20*K, RD, config_abc_mem_abc80_abc80l, R(rom_abc80_abc80l) },
  47. { 28*K, RD, config_abc_mem_abc80_superbasic, R(rom_abc80_superbasic28k) },
  48. { 32*K, RD|WR, config_abc_mem_abc80_ram, R(abc80_extmem) },
  49. END
  50. };
  51. static const struct abc_mem_init mem_init_abc80_nvram_20k[] = {
  52. { 24*K, RD, config_abc_mem_abc80_ufddos, R(rom_abc80_nvram_20k_ufddos80) },
  53. { 28*K, RD, config_abc_mem_abc80_pun80_28k, R(rom_abc80_nvram_20k_print80_28) },
  54. { 29*K, RD, config_abc_mem_abc80_pun80_29k, R(rom_abc80_nvram_20k_print80_29) },
  55. { 30*K, RD, config_abc_mem_abc80_pun80_30k, R(rom_abc80_nvram_20k_print80_30) },
  56. END
  57. };
  58. static const struct abc_mem_init mem_init_abc80_nvram_22k[] = {
  59. { 24*K, RD, config_abc_mem_abc80_ufddos, R(rom_abc80_nvram_22k_ufddos80) },
  60. { 28*K, RD, config_abc_mem_abc80_pun80_28k, R(rom_abc80_nvram_22k_print80_28) },
  61. { 29*K, RD, config_abc_mem_abc80_pun80_29k, R(rom_abc80_nvram_22k_print80_29) },
  62. { 30*K, RD, config_abc_mem_abc80_pun80_30k, R(rom_abc80_nvram_22k_print80_30) },
  63. END
  64. };
  65. static const struct abc_mem_init mem_init_abc80_no_nvram[] = {
  66. { 24*K, RD, config_abc_mem_abc80_ufddos, R(rom_abc80_no_nvram_ufddos80) },
  67. { 28*K, RD, config_abc_mem_abc80_pun80_28k, R(rom_abc80_no_nvram_print80_28) },
  68. { 29*K, RD, config_abc_mem_abc80_pun80_29k, R(rom_abc80_no_nvram_print80_29) },
  69. { 30*K, RD, config_abc_mem_abc80_pun80_30k, R(rom_abc80_no_nvram_print80_30) },
  70. END
  71. };
  72. /* ---- ABC800 memory configurations ---- */
  73. static const struct abc_mem_init mem_init_abc800[] = {
  74. { 24*K, RD, config_abc_mem_abc800_ufddos, R(rom_abc800_ufddos) },
  75. END
  76. };
  77. static const struct abc_mem_init mem_init_abc800mac[] = {
  78. { 0, RD|WR, 0, R(abc800mac_ram) },
  79. END
  80. };
  81. static void abc_map_list(uint32_t *memmap, const struct abc_mem_init *mem)
  82. {
  83. while (mem->addr >= 0) {
  84. bool enabled = !mem->enable || getvar_bool(mem->enable);
  85. const void *data = mem->r.data;
  86. size_t len = mem->r.len;
  87. if (!len)
  88. continue; /* Empty range, skip */
  89. uint32_t addr = mem->addr;
  90. bool bad = ((addr | len) & ~PAGE_MASK) ||
  91. (len > 0x10000 - addr) ||
  92. ((size_t)data & (PAGE_SIZE-1));
  93. con_printf("abcmem: %s %s @ 0x%04x len 0x%04x\n",
  94. mem->r.name ? mem->r.name : "(none)",
  95. bad ? "invalid" :
  96. !enabled ? "disabled" :
  97. data ? "mapping" : "unmapping",
  98. addr, len);
  99. if (enabled) {
  100. uint32_t *pg = &memmap[addr >> PAGE_SHIFT];
  101. uint32_t flags = mem->flags;
  102. if (data) {
  103. /* Mapped range */
  104. size_t pgv = (size_t)data | flags;
  105. for (uint32_t bytes = 0; bytes < len; bytes += PAGE_SIZE)
  106. *pg++ = pgv + bytes;
  107. } else {
  108. /* Unmapped range - set to 0 for clarity */
  109. memset(pg, 0, len >> (PAGE_SHIFT-2));
  110. }
  111. }
  112. mem++;
  113. }
  114. }
  115. static void abc_init_memmap800(uint32_t memmap[MAPS][PERMAP])
  116. {
  117. abc_map_list(memmap[0], mem_init_abc800);
  118. abc_map_list(memmap[1], mem_init_abc800mac);
  119. /* XXX: enable abc800mac if desired */
  120. ABC_MAP_CFG = 0;
  121. }
  122. static void abc_init_memmap80(uint32_t memmap[MAPS][PERMAP])
  123. {
  124. /* Put 22K first so UFD-DOS/PUN80 memory always is put at the end */
  125. if (getvar_bool(config_abc_mem_abc80_nvram_22k))
  126. abc_map_list(memmap[0], mem_init_abc80_nvram_22k);
  127. else if (getvar_bool(config_abc_mem_abc80_nvram_20k))
  128. abc_map_list(memmap[0], mem_init_abc80_nvram_20k);
  129. else
  130. abc_map_list(memmap[0], mem_init_abc80_no_nvram);
  131. abc_map_list(memmap[0], mem_init_abc80);
  132. /* XXX: Until such time as SAM is supported... */
  133. ABC_MAP_CFG = 0;
  134. }
  135. void __cold abc_init_memmap(void)
  136. {
  137. static uint32_t memmap[MAPS][PERMAP]; /* Too big to fit on stack */
  138. memset(memmap, 0, sizeof memmap);
  139. /*
  140. * Currently the only map that gets populated is map 0; the
  141. * remaining map(s) get cleared by the memset() above.
  142. */
  143. if (is_abc800())
  144. abc_init_memmap800(memmap);
  145. else
  146. abc_init_memmap80(memmap);
  147. /* Install memory map into hardware registers */
  148. memcpy((void *)&ABCMEMMAP_PAGE(0), memmap, sizeof memmap);
  149. }