misc.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:7k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /* $Id: misc.c,v 1.20 2001/09/21 03:17:07 kanoj Exp $
  2.  * misc.c:  Miscellaneous prom functions that don't belong
  3.  *          anywhere else.
  4.  *
  5.  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  6.  * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
  7.  */
  8. #include <linux/config.h>
  9. #include <linux/types.h>
  10. #include <linux/kernel.h>
  11. #include <linux/sched.h>
  12. #include <linux/interrupt.h>
  13. #include <linux/delay.h>
  14. #include <asm/openprom.h>
  15. #include <asm/oplib.h>
  16. /* Reset and reboot the machine with the command 'bcommand'. */
  17. void
  18. prom_reboot(char *bcommand)
  19. {
  20. p1275_cmd ("boot", P1275_ARG(0,P1275_ARG_IN_STRING)|
  21.            P1275_INOUT(1,0), bcommand);
  22. }
  23. /* Forth evaluate the expression contained in 'fstring'. */
  24. void
  25. prom_feval(char *fstring)
  26. {
  27. if(!fstring || fstring[0] == 0)
  28. return;
  29. p1275_cmd ("interpret", P1275_ARG(0,P1275_ARG_IN_STRING)|
  30. P1275_INOUT(1,1), fstring);
  31. }
  32. /* We want to do this more nicely some day. */
  33. #ifdef CONFIG_SUN_CONSOLE
  34. extern void (*prom_palette)(int);
  35. extern int serial_console;
  36. #endif
  37. #ifdef CONFIG_SMP
  38. extern void smp_capture(void);
  39. extern void smp_release(void);
  40. #endif
  41. /* Drop into the prom, with the chance to continue with the 'go'
  42.  * prom command.
  43.  */
  44. void
  45. prom_cmdline(void)
  46. {
  47. unsigned long flags;
  48. __save_and_cli(flags);
  49. #ifdef CONFIG_SUN_CONSOLE
  50. if(!serial_console && prom_palette)
  51. prom_palette (1);
  52. #endif
  53. #ifdef CONFIG_SMP
  54. smp_capture();
  55. #endif
  56. p1275_cmd ("enter", P1275_INOUT(0,0));
  57. #ifdef CONFIG_SMP
  58. smp_release();
  59. spin_unlock_wait(&__br_write_locks[BR_GLOBALIRQ_LOCK].lock);
  60. #endif
  61. #ifdef CONFIG_SUN_CONSOLE
  62. if(!serial_console && prom_palette)
  63. prom_palette (0);
  64. #endif
  65. __restore_flags(flags);
  66. }
  67. #ifdef CONFIG_SMP
  68. extern void smp_promstop_others(void);
  69. #endif
  70. /* Drop into the prom, but completely terminate the program.
  71.  * No chance of continuing.
  72.  */
  73. void
  74. prom_halt(void)
  75. {
  76. #ifdef CONFIG_SMP
  77. smp_promstop_others();
  78. udelay(8000);
  79. #endif
  80. again:
  81. p1275_cmd ("exit", P1275_INOUT(0,0));
  82. goto again; /* PROM is out to get me -DaveM */
  83. }
  84. /* Set prom sync handler to call function 'funcp'. */
  85. void
  86. prom_setcallback(callback_func_t funcp)
  87. {
  88. if(!funcp) return;
  89. p1275_cmd ("set-callback", P1275_ARG(0,P1275_ARG_IN_FUNCTION)|
  90.    P1275_INOUT(1,1), funcp);
  91. }
  92. /* Get the idprom and stuff it into buffer 'idbuf'.  Returns the
  93.  * format type.  'num_bytes' is the number of bytes that your idbuf
  94.  * has space for.  Returns 0xff on error.
  95.  */
  96. unsigned char
  97. prom_get_idprom(char *idbuf, int num_bytes)
  98. {
  99. int len;
  100. len = prom_getproplen(prom_root_node, "idprom");
  101. if((len>num_bytes) || (len==-1)) return 0xff;
  102. if(!prom_getproperty(prom_root_node, "idprom", idbuf, num_bytes))
  103. return idbuf[0];
  104. return 0xff;
  105. }
  106. /* Get the major prom version number. */
  107. int
  108. prom_version(void)
  109. {
  110. return PROM_P1275;
  111. }
  112. /* Get the prom plugin-revision. */
  113. int
  114. prom_getrev(void)
  115. {
  116. return prom_rev;
  117. }
  118. /* Get the prom firmware print revision. */
  119. int
  120. prom_getprev(void)
  121. {
  122. return prom_prev;
  123. }
  124. /* Install Linux trap table so PROM uses that instead of it's own. */
  125. void prom_set_trap_table(unsigned long tba)
  126. {
  127. p1275_cmd("SUNW,set-trap-table", P1275_INOUT(1, 0), tba);
  128. }
  129. int mmu_ihandle_cache = 0;
  130. int prom_get_mmu_ihandle(void)
  131. {
  132. int node, ret;
  133. if (mmu_ihandle_cache != 0)
  134. return mmu_ihandle_cache;
  135. node = prom_finddevice("/chosen");
  136. ret = prom_getint(node, "mmu");
  137. if(ret == -1 || ret == 0)
  138. mmu_ihandle_cache = -1;
  139. else
  140. mmu_ihandle_cache = ret;
  141. return ret;
  142. }
  143. static int prom_get_memory_ihandle(void)
  144. {
  145. static int memory_ihandle_cache = 0;
  146. int node, ret;
  147. if (memory_ihandle_cache != 0)
  148. return memory_ihandle_cache;
  149. node = prom_finddevice("/chosen");
  150. ret = prom_getint(node, "memory");
  151. if (ret == -1 || ret == 0)
  152. memory_ihandle_cache = -1;
  153. else
  154. memory_ihandle_cache = ret;
  155. return ret;
  156. }
  157. /* Load explicit I/D TLB entries. */
  158. long prom_itlb_load(unsigned long index,
  159.     unsigned long tte_data,
  160.     unsigned long vaddr)
  161. {
  162. return p1275_cmd("call-method",
  163.  (P1275_ARG(0, P1275_ARG_IN_STRING) |
  164.   P1275_ARG(2, P1275_ARG_IN_64B) |
  165.   P1275_ARG(3, P1275_ARG_IN_64B) |
  166.   P1275_INOUT(5, 1)),
  167.  "SUNW,itlb-load",
  168.  prom_get_mmu_ihandle(),
  169.  /* And then our actual args are pushed backwards. */
  170.  vaddr,
  171.  tte_data,
  172.  index);
  173. }
  174. long prom_dtlb_load(unsigned long index,
  175.     unsigned long tte_data,
  176.     unsigned long vaddr)
  177. {
  178. return p1275_cmd("call-method",
  179.  (P1275_ARG(0, P1275_ARG_IN_STRING) |
  180.   P1275_ARG(2, P1275_ARG_IN_64B) |
  181.   P1275_ARG(3, P1275_ARG_IN_64B) |
  182.   P1275_INOUT(5, 1)),
  183.  "SUNW,dtlb-load",
  184.  prom_get_mmu_ihandle(),
  185.  /* And then our actual args are pushed backwards. */
  186.  vaddr,
  187.  tte_data,
  188.  index);
  189. }
  190. int prom_map(int mode, unsigned long size,
  191.      unsigned long vaddr, unsigned long paddr)
  192. {
  193. int ret = p1275_cmd("call-method",
  194.     (P1275_ARG(0, P1275_ARG_IN_STRING) |
  195.      P1275_ARG(3, P1275_ARG_IN_64B) |
  196.      P1275_ARG(4, P1275_ARG_IN_64B) |
  197.      P1275_ARG(6, P1275_ARG_IN_64B) |
  198.      P1275_INOUT(7, 1)),
  199.     "map",
  200.     prom_get_mmu_ihandle(),
  201.     mode,
  202.     size,
  203.     vaddr,
  204.     0,
  205.     paddr);
  206. if (ret == 0)
  207. ret = -1;
  208. return ret;
  209. }
  210. void prom_unmap(unsigned long size, unsigned long vaddr)
  211. {
  212. p1275_cmd("call-method",
  213.   (P1275_ARG(0, P1275_ARG_IN_STRING) |
  214.    P1275_ARG(2, P1275_ARG_IN_64B) |
  215.    P1275_ARG(3, P1275_ARG_IN_64B) |
  216.    P1275_INOUT(4, 0)),
  217.   "unmap",
  218.   prom_get_mmu_ihandle(),
  219.   size,
  220.   vaddr);
  221. }
  222. /* Set aside physical memory which is not touched or modified
  223.  * across soft resets.
  224.  */
  225. unsigned long prom_retain(char *name,
  226.   unsigned long pa_low, unsigned long pa_high,
  227.   long size, long align)
  228. {
  229. /* XXX I don't think we return multiple values correctly.
  230.  * XXX OBP supposedly returns pa_low/pa_high here, how does
  231.  * XXX it work?
  232.  */
  233. /* If align is zero, the pa_low/pa_high args are passed,
  234.  * else they are not.
  235.  */
  236. if(align == 0)
  237. return p1275_cmd("SUNW,retain",
  238.  (P1275_ARG(0, P1275_ARG_IN_BUF) | P1275_INOUT(5, 2)),
  239.  name, pa_low, pa_high, size, align);
  240. else
  241. return p1275_cmd("SUNW,retain",
  242.  (P1275_ARG(0, P1275_ARG_IN_BUF) | P1275_INOUT(3, 2)),
  243.  name, size, align);
  244. }
  245. /* Get "Unumber" string for the SIMM at the given
  246.  * memory address.  Usually this will be of the form
  247.  * "Uxxxx" where xxxx is a decimal number which is
  248.  * etched into the motherboard next to the SIMM slot
  249.  * in question.
  250.  */
  251. int prom_getunumber(int syndrome_code,
  252.     unsigned long phys_addr,
  253.     char *buf, int buflen)
  254. {
  255. return p1275_cmd("call-method",
  256.  (P1275_ARG(0, P1275_ARG_IN_STRING) |
  257.   P1275_ARG(3, P1275_ARG_OUT_BUF) |
  258.   P1275_ARG(6, P1275_ARG_IN_64B) |
  259.   P1275_INOUT(8, 2)),
  260.  "SUNW,get-unumber", prom_get_memory_ihandle(),
  261.  buflen, buf, P1275_SIZE(buflen),
  262.  0, phys_addr, syndrome_code);
  263. }
  264. /* Power management extensions. */
  265. void prom_sleepself(void)
  266. {
  267. p1275_cmd("SUNW,sleep-self", P1275_INOUT(0, 0));
  268. }
  269. int prom_sleepsystem(void)
  270. {
  271. return p1275_cmd("SUNW,sleep-system", P1275_INOUT(0, 1));
  272. }
  273. int prom_wakeupsystem(void)
  274. {
  275. return p1275_cmd("SUNW,wakeup-system", P1275_INOUT(0, 1));
  276. }
  277. #ifdef CONFIG_SMP
  278. void prom_startcpu(int cpunode, unsigned long pc, unsigned long o0)
  279. {
  280. p1275_cmd("SUNW,start-cpu", P1275_INOUT(3, 0), cpunode, pc, o0);
  281. }
  282. void prom_stopself(void)
  283. {
  284. p1275_cmd("SUNW,stop-self", P1275_INOUT(0, 0));
  285. }
  286. void prom_idleself(void)
  287. {
  288. p1275_cmd("SUNW,idle-self", P1275_INOUT(0, 0));
  289. }
  290. void prom_resumecpu(int cpunode)
  291. {
  292. p1275_cmd("SUNW,resume-cpu", P1275_INOUT(1, 0), cpunode);
  293. }
  294. #endif