memory.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. /*
  2. * memory.c: memory initialisation code.
  3. *
  4. * Copyright (C) 1998 Harald Koerfgen, Frieder Streffer and Paul M. Antoine
  5. * Copyright (C) 2000, 2002 Maciej W. Rozycki
  6. */
  7. #include <linux/config.h>
  8. #include <linux/init.h>
  9. #include <linux/kernel.h>
  10. #include <linux/mm.h>
  11. #include <linux/bootmem.h>
  12. #include <linux/types.h>
  13. #include <asm/addrspace.h>
  14. #include <asm/bootinfo.h>
  15. #include <asm/dec/machtype.h>
  16. #include <asm/dec/prom.h>
  17. #include <asm/page.h>
  18. #include <asm/sections.h>
  19. volatile unsigned long mem_err = 0; /* So we know an error occurred */
  20. /*
  21. * Probe memory in 4MB chunks, waiting for an error to tell us we've fallen
  22. * off the end of real memory. Only suitable for the 2100/3100's (PMAX).
  23. */
  24. #define CHUNK_SIZE 0x400000
  25. static inline void pmax_setup_memory_region(void)
  26. {
  27. volatile unsigned char *memory_page, dummy;
  28. char old_handler[0x80];
  29. extern char genexcept_early;
  30. /* Install exception handler */
  31. memcpy(&old_handler, (void *)(KSEG0 + 0x80), 0x80);
  32. memcpy((void *)(KSEG0 + 0x80), &genexcept_early, 0x80);
  33. /* read unmapped and uncached (KSEG1)
  34. * DECstations have at least 4MB RAM
  35. * Assume less than 480MB of RAM, as this is max for 5000/2xx
  36. * FIXME this should be replaced by the first free page!
  37. */
  38. for (memory_page = (unsigned char *) KSEG1 + CHUNK_SIZE;
  39. (mem_err== 0) && (memory_page < ((unsigned char *) KSEG1+0x1E000000));
  40. memory_page += CHUNK_SIZE) {
  41. dummy = *memory_page;
  42. }
  43. memcpy((void *)(KSEG0 + 0x80), &old_handler, 0x80);
  44. add_memory_region(0, (unsigned long)memory_page - KSEG1 - CHUNK_SIZE,
  45. BOOT_MEM_RAM);
  46. }
  47. /*
  48. * Use the REX prom calls to get hold of the memory bitmap, and thence
  49. * determine memory size.
  50. */
  51. static inline void rex_setup_memory_region(void)
  52. {
  53. int i, bitmap_size;
  54. unsigned long mem_start = 0, mem_size = 0;
  55. memmap *bm;
  56. /* some free 64k */
  57. bm = (memmap *)KSEG0ADDR(0x28000);
  58. bitmap_size = rex_getbitmap(bm);
  59. for (i = 0; i < bitmap_size; i++) {
  60. /* FIXME: very simplistically only add full sets of pages */
  61. if (bm->bitmap[i] == 0xff)
  62. mem_size += (8 * bm->pagesize);
  63. else if (!mem_size)
  64. mem_start += (8 * bm->pagesize);
  65. else {
  66. add_memory_region(mem_start, mem_size, BOOT_MEM_RAM);
  67. mem_start += mem_size + (8 * bm->pagesize);
  68. mem_size = 0;
  69. }
  70. }
  71. if (mem_size)
  72. add_memory_region(mem_start, mem_size, BOOT_MEM_RAM);
  73. }
  74. void __init prom_meminit(u32 magic)
  75. {
  76. if (!prom_is_rex(magic))
  77. pmax_setup_memory_region();
  78. else
  79. rex_setup_memory_region();
  80. }
  81. unsigned long __init prom_free_prom_memory(void)
  82. {
  83. unsigned long addr, end;
  84. /*
  85. * Free everything below the kernel itself but leave
  86. * the first page reserved for the exception handlers.
  87. */
  88. #if defined(CONFIG_DECLANCE) || defined(CONFIG_DECLANCE_MODULE)
  89. /*
  90. * Leave 128 KB reserved for Lance memory for
  91. * IOASIC DECstations.
  92. *
  93. * XXX: save this address for use in dec_lance.c?
  94. */
  95. if (IOASIC)
  96. end = __pa(&_text) - 0x00020000;
  97. else
  98. #endif
  99. end = __pa(&_text);
  100. addr = PAGE_SIZE;
  101. while (addr < end) {
  102. ClearPageReserved(virt_to_page(__va(addr)));
  103. set_page_count(virt_to_page(__va(addr)), 1);
  104. free_page((unsigned long)__va(addr));
  105. addr += PAGE_SIZE;
  106. }
  107. printk("Freeing unused PROM memory: %ldk freed\n",
  108. (end - PAGE_SIZE) >> 10);
  109. return end - PAGE_SIZE;
  110. }