memory.c 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. /* memory.c: Prom routine for acquiring various bits of information
  2. * about RAM on the machine, both virtual and physical.
  3. *
  4. * Copyright (C) 1995, 2008 David S. Miller (davem@davemloft.net)
  5. * Copyright (C) 1997 Michael A. Griffith (grif@acm.org)
  6. */
  7. #include <linux/kernel.h>
  8. #include <linux/sort.h>
  9. #include <linux/init.h>
  10. #include <asm/openprom.h>
  11. #include <asm/sun4prom.h>
  12. #include <asm/oplib.h>
  13. #include <asm/page.h>
  14. static int __init prom_meminit_v0(void)
  15. {
  16. struct linux_mlist_v0 *p;
  17. int index;
  18. index = 0;
  19. for (p = *(romvec->pv_v0mem.v0_available); p; p = p->theres_more) {
  20. sp_banks[index].base_addr = (unsigned long) p->start_adr;
  21. sp_banks[index].num_bytes = p->num_bytes;
  22. index++;
  23. }
  24. return index;
  25. }
  26. static int __init prom_meminit_v2(void)
  27. {
  28. struct linux_prom_registers reg[64];
  29. int node, size, num_ents, i;
  30. node = prom_searchsiblings(prom_getchild(prom_root_node), "memory");
  31. size = prom_getproperty(node, "available", (char *) reg, sizeof(reg));
  32. num_ents = size / sizeof(struct linux_prom_registers);
  33. for (i = 0; i < num_ents; i++) {
  34. sp_banks[i].base_addr = reg[i].phys_addr;
  35. sp_banks[i].num_bytes = reg[i].reg_size;
  36. }
  37. return num_ents;
  38. }
  39. static int __init prom_meminit_sun4(void)
  40. {
  41. #ifdef CONFIG_SUN4
  42. sp_banks[0].base_addr = 0;
  43. sp_banks[0].num_bytes = *(sun4_romvec->memoryavail);
  44. #endif
  45. return 1;
  46. }
  47. static int sp_banks_cmp(const void *a, const void *b)
  48. {
  49. const struct sparc_phys_banks *x = a, *y = b;
  50. if (x->base_addr > y->base_addr)
  51. return 1;
  52. if (x->base_addr < y->base_addr)
  53. return -1;
  54. return 0;
  55. }
  56. /* Initialize the memory lists based upon the prom version. */
  57. void __init prom_meminit(void)
  58. {
  59. int i, num_ents = 0;
  60. switch (prom_vers) {
  61. case PROM_V0:
  62. num_ents = prom_meminit_v0();
  63. break;
  64. case PROM_V2:
  65. case PROM_V3:
  66. num_ents = prom_meminit_v2();
  67. break;
  68. case PROM_SUN4:
  69. num_ents = prom_meminit_sun4();
  70. break;
  71. default:
  72. break;
  73. }
  74. sort(sp_banks, num_ents, sizeof(struct sparc_phys_banks),
  75. sp_banks_cmp, NULL);
  76. /* Sentinel. */
  77. sp_banks[num_ents].base_addr = 0xdeadbeef;
  78. sp_banks[num_ents].num_bytes = 0;
  79. for (i = 0; i < num_ents; i++)
  80. sp_banks[i].num_bytes &= PAGE_MASK;
  81. }