prom.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. /*
  2. * Copyright (C) Paul Mackerras 1997.
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License
  6. * as published by the Free Software Foundation; either version
  7. * 2 of the License, or (at your option) any later version.
  8. */
  9. #include <stdarg.h>
  10. #include <stddef.h>
  11. #include "string.h"
  12. #include "stdio.h"
  13. #include "prom.h"
  14. int (*prom)(void *);
  15. phandle chosen_handle;
  16. ihandle stdout;
  17. int call_prom(const char *service, int nargs, int nret, ...)
  18. {
  19. int i;
  20. struct prom_args {
  21. const char *service;
  22. int nargs;
  23. int nret;
  24. unsigned int args[12];
  25. } args;
  26. va_list list;
  27. args.service = service;
  28. args.nargs = nargs;
  29. args.nret = nret;
  30. va_start(list, nret);
  31. for (i = 0; i < nargs; i++)
  32. args.args[i] = va_arg(list, unsigned int);
  33. va_end(list);
  34. for (i = 0; i < nret; i++)
  35. args.args[nargs+i] = 0;
  36. if (prom(&args) < 0)
  37. return -1;
  38. return (nret > 0)? args.args[nargs]: 0;
  39. }
  40. int call_prom_ret(const char *service, int nargs, int nret,
  41. unsigned int *rets, ...)
  42. {
  43. int i;
  44. struct prom_args {
  45. const char *service;
  46. int nargs;
  47. int nret;
  48. unsigned int args[12];
  49. } args;
  50. va_list list;
  51. args.service = service;
  52. args.nargs = nargs;
  53. args.nret = nret;
  54. va_start(list, rets);
  55. for (i = 0; i < nargs; i++)
  56. args.args[i] = va_arg(list, unsigned int);
  57. va_end(list);
  58. for (i = 0; i < nret; i++)
  59. args.args[nargs+i] = 0;
  60. if (prom(&args) < 0)
  61. return -1;
  62. if (rets != (void *) 0)
  63. for (i = 1; i < nret; ++i)
  64. rets[i-1] = args.args[nargs+i];
  65. return (nret > 0)? args.args[nargs]: 0;
  66. }
  67. int write(void *handle, void *ptr, int nb)
  68. {
  69. return call_prom("write", 3, 1, handle, ptr, nb);
  70. }
  71. /*
  72. * Older OF's require that when claiming a specific range of addresses,
  73. * we claim the physical space in the /memory node and the virtual
  74. * space in the chosen mmu node, and then do a map operation to
  75. * map virtual to physical.
  76. */
  77. static int need_map = -1;
  78. static ihandle chosen_mmu;
  79. static phandle memory;
  80. /* returns true if s2 is a prefix of s1 */
  81. static int string_match(const char *s1, const char *s2)
  82. {
  83. for (; *s2; ++s2)
  84. if (*s1++ != *s2)
  85. return 0;
  86. return 1;
  87. }
  88. static int check_of_version(void)
  89. {
  90. phandle oprom, chosen;
  91. char version[64];
  92. oprom = finddevice("/openprom");
  93. if (oprom == (phandle) -1)
  94. return 0;
  95. if (getprop(oprom, "model", version, sizeof(version)) <= 0)
  96. return 0;
  97. version[sizeof(version)-1] = 0;
  98. printf("OF version = '%s'\r\n", version);
  99. if (!string_match(version, "Open Firmware, 1.")
  100. && !string_match(version, "FirmWorks,3."))
  101. return 0;
  102. chosen = finddevice("/chosen");
  103. if (chosen == (phandle) -1) {
  104. chosen = finddevice("/chosen@0");
  105. if (chosen == (phandle) -1) {
  106. printf("no chosen\n");
  107. return 0;
  108. }
  109. }
  110. if (getprop(chosen, "mmu", &chosen_mmu, sizeof(chosen_mmu)) <= 0) {
  111. printf("no mmu\n");
  112. return 0;
  113. }
  114. memory = (ihandle) call_prom("open", 1, 1, "/memory");
  115. if (memory == (ihandle) -1) {
  116. memory = (ihandle) call_prom("open", 1, 1, "/memory@0");
  117. if (memory == (ihandle) -1) {
  118. printf("no memory node\n");
  119. return 0;
  120. }
  121. }
  122. printf("old OF detected\r\n");
  123. return 1;
  124. }
  125. void *claim(unsigned long virt, unsigned long size, unsigned long align)
  126. {
  127. int ret;
  128. unsigned int result;
  129. if (need_map < 0)
  130. need_map = check_of_version();
  131. if (align || !need_map)
  132. return (void *) call_prom("claim", 3, 1, virt, size, align);
  133. ret = call_prom_ret("call-method", 5, 2, &result, "claim", memory,
  134. align, size, virt);
  135. if (ret != 0 || result == -1)
  136. return (void *) -1;
  137. ret = call_prom_ret("call-method", 5, 2, &result, "claim", chosen_mmu,
  138. align, size, virt);
  139. /* 0x12 == coherent + read/write */
  140. ret = call_prom("call-method", 6, 1, "map", chosen_mmu,
  141. 0x12, size, virt, virt);
  142. return (void *) virt;
  143. }