rtas.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693
  1. /*
  2. *
  3. * Procedures for interfacing to the RTAS on CHRP machines.
  4. *
  5. * Peter Bergner, IBM March 2001.
  6. * Copyright (C) 2001 IBM.
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License
  10. * as published by the Free Software Foundation; either version
  11. * 2 of the License, or (at your option) any later version.
  12. */
  13. #include <stdarg.h>
  14. #include <linux/kernel.h>
  15. #include <linux/types.h>
  16. #include <linux/spinlock.h>
  17. #include <linux/module.h>
  18. #include <linux/init.h>
  19. #include <linux/delay.h>
  20. #include <asm/prom.h>
  21. #include <asm/rtas.h>
  22. #include <asm/semaphore.h>
  23. #include <asm/machdep.h>
  24. #include <asm/page.h>
  25. #include <asm/param.h>
  26. #include <asm/system.h>
  27. #include <asm/delay.h>
  28. #include <asm/uaccess.h>
  29. #include <asm/lmb.h>
  30. struct rtas_t rtas = {
  31. .lock = SPIN_LOCK_UNLOCKED
  32. };
  33. EXPORT_SYMBOL(rtas);
  34. DEFINE_SPINLOCK(rtas_data_buf_lock);
  35. char rtas_data_buf[RTAS_DATA_BUF_SIZE] __cacheline_aligned;
  36. unsigned long rtas_rmo_buf;
  37. /*
  38. * If non-NULL, this gets called when the kernel terminates.
  39. * This is done like this so rtas_flash can be a module.
  40. */
  41. void (*rtas_flash_term_hook)(int);
  42. EXPORT_SYMBOL(rtas_flash_term_hook);
  43. /*
  44. * call_rtas_display_status and call_rtas_display_status_delay
  45. * are designed only for very early low-level debugging, which
  46. * is why the token is hard-coded to 10.
  47. */
  48. void call_rtas_display_status(unsigned char c)
  49. {
  50. struct rtas_args *args = &rtas.args;
  51. unsigned long s;
  52. if (!rtas.base)
  53. return;
  54. spin_lock_irqsave(&rtas.lock, s);
  55. args->token = 10;
  56. args->nargs = 1;
  57. args->nret = 1;
  58. args->rets = (rtas_arg_t *)&(args->args[1]);
  59. args->args[0] = (int)c;
  60. enter_rtas(__pa(args));
  61. spin_unlock_irqrestore(&rtas.lock, s);
  62. }
  63. void call_rtas_display_status_delay(unsigned char c)
  64. {
  65. static int pending_newline = 0; /* did last write end with unprinted newline? */
  66. static int width = 16;
  67. if (c == '\n') {
  68. while (width-- > 0)
  69. call_rtas_display_status(' ');
  70. width = 16;
  71. mdelay(500);
  72. pending_newline = 1;
  73. } else {
  74. if (pending_newline) {
  75. call_rtas_display_status('\r');
  76. call_rtas_display_status('\n');
  77. }
  78. pending_newline = 0;
  79. if (width--) {
  80. call_rtas_display_status(c);
  81. udelay(10000);
  82. }
  83. }
  84. }
  85. void rtas_progress(char *s, unsigned short hex)
  86. {
  87. struct device_node *root;
  88. int width, *p;
  89. char *os;
  90. static int display_character, set_indicator;
  91. static int display_width, display_lines, *row_width, form_feed;
  92. static DEFINE_SPINLOCK(progress_lock);
  93. static int current_line;
  94. static int pending_newline = 0; /* did last write end with unprinted newline? */
  95. if (!rtas.base)
  96. return;
  97. if (display_width == 0) {
  98. display_width = 0x10;
  99. if ((root = find_path_device("/rtas"))) {
  100. if ((p = (unsigned int *)get_property(root,
  101. "ibm,display-line-length", NULL)))
  102. display_width = *p;
  103. if ((p = (unsigned int *)get_property(root,
  104. "ibm,form-feed", NULL)))
  105. form_feed = *p;
  106. if ((p = (unsigned int *)get_property(root,
  107. "ibm,display-number-of-lines", NULL)))
  108. display_lines = *p;
  109. row_width = (unsigned int *)get_property(root,
  110. "ibm,display-truncation-length", NULL);
  111. }
  112. display_character = rtas_token("display-character");
  113. set_indicator = rtas_token("set-indicator");
  114. }
  115. if (display_character == RTAS_UNKNOWN_SERVICE) {
  116. /* use hex display if available */
  117. if (set_indicator != RTAS_UNKNOWN_SERVICE)
  118. rtas_call(set_indicator, 3, 1, NULL, 6, 0, hex);
  119. return;
  120. }
  121. spin_lock(&progress_lock);
  122. /*
  123. * Last write ended with newline, but we didn't print it since
  124. * it would just clear the bottom line of output. Print it now
  125. * instead.
  126. *
  127. * If no newline is pending and form feed is supported, clear the
  128. * display with a form feed; otherwise, print a CR to start output
  129. * at the beginning of the line.
  130. */
  131. if (pending_newline) {
  132. rtas_call(display_character, 1, 1, NULL, '\r');
  133. rtas_call(display_character, 1, 1, NULL, '\n');
  134. pending_newline = 0;
  135. } else {
  136. current_line = 0;
  137. if (form_feed)
  138. rtas_call(display_character, 1, 1, NULL,
  139. (char)form_feed);
  140. else
  141. rtas_call(display_character, 1, 1, NULL, '\r');
  142. }
  143. if (row_width)
  144. width = row_width[current_line];
  145. else
  146. width = display_width;
  147. os = s;
  148. while (*os) {
  149. if (*os == '\n' || *os == '\r') {
  150. /* If newline is the last character, save it
  151. * until next call to avoid bumping up the
  152. * display output.
  153. */
  154. if (*os == '\n' && !os[1]) {
  155. pending_newline = 1;
  156. current_line++;
  157. if (current_line > display_lines-1)
  158. current_line = display_lines-1;
  159. spin_unlock(&progress_lock);
  160. return;
  161. }
  162. /* RTAS wants CR-LF, not just LF */
  163. if (*os == '\n') {
  164. rtas_call(display_character, 1, 1, NULL, '\r');
  165. rtas_call(display_character, 1, 1, NULL, '\n');
  166. } else {
  167. /* CR might be used to re-draw a line, so we'll
  168. * leave it alone and not add LF.
  169. */
  170. rtas_call(display_character, 1, 1, NULL, *os);
  171. }
  172. if (row_width)
  173. width = row_width[current_line];
  174. else
  175. width = display_width;
  176. } else {
  177. width--;
  178. rtas_call(display_character, 1, 1, NULL, *os);
  179. }
  180. os++;
  181. /* if we overwrite the screen length */
  182. if (width <= 0)
  183. while ((*os != 0) && (*os != '\n') && (*os != '\r'))
  184. os++;
  185. }
  186. spin_unlock(&progress_lock);
  187. }
  188. EXPORT_SYMBOL(rtas_progress); /* needed by rtas_flash module */
  189. int rtas_token(const char *service)
  190. {
  191. int *tokp;
  192. if (rtas.dev == NULL)
  193. return RTAS_UNKNOWN_SERVICE;
  194. tokp = (int *) get_property(rtas.dev, service, NULL);
  195. return tokp ? *tokp : RTAS_UNKNOWN_SERVICE;
  196. }
  197. #ifdef CONFIG_RTAS_ERROR_LOGGING
  198. /*
  199. * Return the firmware-specified size of the error log buffer
  200. * for all rtas calls that require an error buffer argument.
  201. * This includes 'check-exception' and 'rtas-last-error'.
  202. */
  203. int rtas_get_error_log_max(void)
  204. {
  205. static int rtas_error_log_max;
  206. if (rtas_error_log_max)
  207. return rtas_error_log_max;
  208. rtas_error_log_max = rtas_token ("rtas-error-log-max");
  209. if ((rtas_error_log_max == RTAS_UNKNOWN_SERVICE) ||
  210. (rtas_error_log_max > RTAS_ERROR_LOG_MAX)) {
  211. printk (KERN_WARNING "RTAS: bad log buffer size %d\n",
  212. rtas_error_log_max);
  213. rtas_error_log_max = RTAS_ERROR_LOG_MAX;
  214. }
  215. return rtas_error_log_max;
  216. }
  217. EXPORT_SYMBOL(rtas_get_error_log_max);
  218. char rtas_err_buf[RTAS_ERROR_LOG_MAX];
  219. int rtas_last_error_token;
  220. /** Return a copy of the detailed error text associated with the
  221. * most recent failed call to rtas. Because the error text
  222. * might go stale if there are any other intervening rtas calls,
  223. * this routine must be called atomically with whatever produced
  224. * the error (i.e. with rtas.lock still held from the previous call).
  225. */
  226. static char *__fetch_rtas_last_error(char *altbuf)
  227. {
  228. struct rtas_args err_args, save_args;
  229. u32 bufsz;
  230. char *buf = NULL;
  231. if (rtas_last_error_token == -1)
  232. return NULL;
  233. bufsz = rtas_get_error_log_max();
  234. err_args.token = rtas_last_error_token;
  235. err_args.nargs = 2;
  236. err_args.nret = 1;
  237. err_args.args[0] = (rtas_arg_t)__pa(rtas_err_buf);
  238. err_args.args[1] = bufsz;
  239. err_args.args[2] = 0;
  240. save_args = rtas.args;
  241. rtas.args = err_args;
  242. enter_rtas(__pa(&rtas.args));
  243. err_args = rtas.args;
  244. rtas.args = save_args;
  245. /* Log the error in the unlikely case that there was one. */
  246. if (unlikely(err_args.args[2] == 0)) {
  247. if (altbuf) {
  248. buf = altbuf;
  249. } else {
  250. buf = rtas_err_buf;
  251. if (mem_init_done)
  252. buf = kmalloc(RTAS_ERROR_LOG_MAX, GFP_ATOMIC);
  253. }
  254. if (buf)
  255. memcpy(buf, rtas_err_buf, RTAS_ERROR_LOG_MAX);
  256. }
  257. return buf;
  258. }
  259. #define get_errorlog_buffer() kmalloc(RTAS_ERROR_LOG_MAX, GFP_KERNEL)
  260. #else /* CONFIG_RTAS_ERROR_LOGGING */
  261. #define __fetch_rtas_last_error(x) NULL
  262. #define get_errorlog_buffer() NULL
  263. #endif
  264. int rtas_call(int token, int nargs, int nret, int *outputs, ...)
  265. {
  266. va_list list;
  267. int i;
  268. unsigned long s;
  269. struct rtas_args *rtas_args;
  270. char *buff_copy = NULL;
  271. int ret;
  272. if (token == RTAS_UNKNOWN_SERVICE)
  273. return -1;
  274. /* Gotta do something different here, use global lock for now... */
  275. spin_lock_irqsave(&rtas.lock, s);
  276. rtas_args = &rtas.args;
  277. rtas_args->token = token;
  278. rtas_args->nargs = nargs;
  279. rtas_args->nret = nret;
  280. rtas_args->rets = (rtas_arg_t *)&(rtas_args->args[nargs]);
  281. va_start(list, outputs);
  282. for (i = 0; i < nargs; ++i)
  283. rtas_args->args[i] = va_arg(list, rtas_arg_t);
  284. va_end(list);
  285. for (i = 0; i < nret; ++i)
  286. rtas_args->rets[i] = 0;
  287. enter_rtas(__pa(rtas_args));
  288. /* A -1 return code indicates that the last command couldn't
  289. be completed due to a hardware error. */
  290. if (rtas_args->rets[0] == -1)
  291. buff_copy = __fetch_rtas_last_error(NULL);
  292. if (nret > 1 && outputs != NULL)
  293. for (i = 0; i < nret-1; ++i)
  294. outputs[i] = rtas_args->rets[i+1];
  295. ret = (nret > 0)? rtas_args->rets[0]: 0;
  296. /* Gotta do something different here, use global lock for now... */
  297. spin_unlock_irqrestore(&rtas.lock, s);
  298. if (buff_copy) {
  299. log_error(buff_copy, ERR_TYPE_RTAS_LOG, 0);
  300. if (mem_init_done)
  301. kfree(buff_copy);
  302. }
  303. return ret;
  304. }
  305. /* Given an RTAS status code of 990n compute the hinted delay of 10^n
  306. * (last digit) milliseconds. For now we bound at n=5 (100 sec).
  307. */
  308. unsigned int rtas_extended_busy_delay_time(int status)
  309. {
  310. int order = status - 9900;
  311. unsigned long ms;
  312. if (order < 0)
  313. order = 0; /* RTC depends on this for -2 clock busy */
  314. else if (order > 5)
  315. order = 5; /* bound */
  316. /* Use microseconds for reasonable accuracy */
  317. for (ms = 1; order > 0; order--)
  318. ms *= 10;
  319. return ms;
  320. }
  321. int rtas_error_rc(int rtas_rc)
  322. {
  323. int rc;
  324. switch (rtas_rc) {
  325. case -1: /* Hardware Error */
  326. rc = -EIO;
  327. break;
  328. case -3: /* Bad indicator/domain/etc */
  329. rc = -EINVAL;
  330. break;
  331. case -9000: /* Isolation error */
  332. rc = -EFAULT;
  333. break;
  334. case -9001: /* Outstanding TCE/PTE */
  335. rc = -EEXIST;
  336. break;
  337. case -9002: /* No usable slot */
  338. rc = -ENODEV;
  339. break;
  340. default:
  341. printk(KERN_ERR "%s: unexpected RTAS error %d\n",
  342. __FUNCTION__, rtas_rc);
  343. rc = -ERANGE;
  344. break;
  345. }
  346. return rc;
  347. }
  348. int rtas_get_power_level(int powerdomain, int *level)
  349. {
  350. int token = rtas_token("get-power-level");
  351. int rc;
  352. if (token == RTAS_UNKNOWN_SERVICE)
  353. return -ENOENT;
  354. while ((rc = rtas_call(token, 1, 2, level, powerdomain)) == RTAS_BUSY)
  355. udelay(1);
  356. if (rc < 0)
  357. return rtas_error_rc(rc);
  358. return rc;
  359. }
  360. int rtas_set_power_level(int powerdomain, int level, int *setlevel)
  361. {
  362. int token = rtas_token("set-power-level");
  363. unsigned int wait_time;
  364. int rc;
  365. if (token == RTAS_UNKNOWN_SERVICE)
  366. return -ENOENT;
  367. while (1) {
  368. rc = rtas_call(token, 2, 2, setlevel, powerdomain, level);
  369. if (rc == RTAS_BUSY)
  370. udelay(1);
  371. else if (rtas_is_extended_busy(rc)) {
  372. wait_time = rtas_extended_busy_delay_time(rc);
  373. udelay(wait_time * 1000);
  374. } else
  375. break;
  376. }
  377. if (rc < 0)
  378. return rtas_error_rc(rc);
  379. return rc;
  380. }
  381. int rtas_get_sensor(int sensor, int index, int *state)
  382. {
  383. int token = rtas_token("get-sensor-state");
  384. unsigned int wait_time;
  385. int rc;
  386. if (token == RTAS_UNKNOWN_SERVICE)
  387. return -ENOENT;
  388. while (1) {
  389. rc = rtas_call(token, 2, 2, state, sensor, index);
  390. if (rc == RTAS_BUSY)
  391. udelay(1);
  392. else if (rtas_is_extended_busy(rc)) {
  393. wait_time = rtas_extended_busy_delay_time(rc);
  394. udelay(wait_time * 1000);
  395. } else
  396. break;
  397. }
  398. if (rc < 0)
  399. return rtas_error_rc(rc);
  400. return rc;
  401. }
  402. int rtas_set_indicator(int indicator, int index, int new_value)
  403. {
  404. int token = rtas_token("set-indicator");
  405. unsigned int wait_time;
  406. int rc;
  407. if (token == RTAS_UNKNOWN_SERVICE)
  408. return -ENOENT;
  409. while (1) {
  410. rc = rtas_call(token, 3, 1, NULL, indicator, index, new_value);
  411. if (rc == RTAS_BUSY)
  412. udelay(1);
  413. else if (rtas_is_extended_busy(rc)) {
  414. wait_time = rtas_extended_busy_delay_time(rc);
  415. udelay(wait_time * 1000);
  416. }
  417. else
  418. break;
  419. }
  420. if (rc < 0)
  421. return rtas_error_rc(rc);
  422. return rc;
  423. }
  424. void rtas_restart(char *cmd)
  425. {
  426. if (rtas_flash_term_hook)
  427. rtas_flash_term_hook(SYS_RESTART);
  428. printk("RTAS system-reboot returned %d\n",
  429. rtas_call(rtas_token("system-reboot"), 0, 1, NULL));
  430. for (;;);
  431. }
  432. void rtas_power_off(void)
  433. {
  434. if (rtas_flash_term_hook)
  435. rtas_flash_term_hook(SYS_POWER_OFF);
  436. /* allow power on only with power button press */
  437. printk("RTAS power-off returned %d\n",
  438. rtas_call(rtas_token("power-off"), 2, 1, NULL, -1, -1));
  439. for (;;);
  440. }
  441. void rtas_halt(void)
  442. {
  443. if (rtas_flash_term_hook)
  444. rtas_flash_term_hook(SYS_HALT);
  445. /* allow power on only with power button press */
  446. printk("RTAS power-off returned %d\n",
  447. rtas_call(rtas_token("power-off"), 2, 1, NULL, -1, -1));
  448. for (;;);
  449. }
  450. /* Must be in the RMO region, so we place it here */
  451. static char rtas_os_term_buf[2048];
  452. void rtas_os_term(char *str)
  453. {
  454. int status;
  455. if (RTAS_UNKNOWN_SERVICE == rtas_token("ibm,os-term"))
  456. return;
  457. snprintf(rtas_os_term_buf, 2048, "OS panic: %s", str);
  458. do {
  459. status = rtas_call(rtas_token("ibm,os-term"), 1, 1, NULL,
  460. __pa(rtas_os_term_buf));
  461. if (status == RTAS_BUSY)
  462. udelay(1);
  463. else if (status != 0)
  464. printk(KERN_EMERG "ibm,os-term call failed %d\n",
  465. status);
  466. } while (status == RTAS_BUSY);
  467. }
  468. asmlinkage int ppc_rtas(struct rtas_args __user *uargs)
  469. {
  470. struct rtas_args args;
  471. unsigned long flags;
  472. char *buff_copy, *errbuf = NULL;
  473. int nargs;
  474. if (!capable(CAP_SYS_ADMIN))
  475. return -EPERM;
  476. if (copy_from_user(&args, uargs, 3 * sizeof(u32)) != 0)
  477. return -EFAULT;
  478. nargs = args.nargs;
  479. if (nargs > ARRAY_SIZE(args.args)
  480. || args.nret > ARRAY_SIZE(args.args)
  481. || nargs + args.nret > ARRAY_SIZE(args.args))
  482. return -EINVAL;
  483. /* Copy in args. */
  484. if (copy_from_user(args.args, uargs->args,
  485. nargs * sizeof(rtas_arg_t)) != 0)
  486. return -EFAULT;
  487. buff_copy = get_errorlog_buffer();
  488. spin_lock_irqsave(&rtas.lock, flags);
  489. rtas.args = args;
  490. enter_rtas(__pa(&rtas.args));
  491. args = rtas.args;
  492. args.rets = &args.args[nargs];
  493. /* A -1 return code indicates that the last command couldn't
  494. be completed due to a hardware error. */
  495. if (args.rets[0] == -1)
  496. errbuf = __fetch_rtas_last_error(buff_copy);
  497. spin_unlock_irqrestore(&rtas.lock, flags);
  498. if (buff_copy) {
  499. if (errbuf)
  500. log_error(errbuf, ERR_TYPE_RTAS_LOG, 0);
  501. kfree(buff_copy);
  502. }
  503. /* Copy out args. */
  504. if (copy_to_user(uargs->args + nargs,
  505. args.args + nargs,
  506. args.nret * sizeof(rtas_arg_t)) != 0)
  507. return -EFAULT;
  508. return 0;
  509. }
  510. /* This version can't take the spinlock, because it never returns */
  511. struct rtas_args rtas_stop_self_args = {
  512. /* The token is initialized for real in setup_system() */
  513. .token = RTAS_UNKNOWN_SERVICE,
  514. .nargs = 0,
  515. .nret = 1,
  516. .rets = &rtas_stop_self_args.args[0],
  517. };
  518. void rtas_stop_self(void)
  519. {
  520. struct rtas_args *rtas_args = &rtas_stop_self_args;
  521. local_irq_disable();
  522. BUG_ON(rtas_args->token == RTAS_UNKNOWN_SERVICE);
  523. printk("cpu %u (hwid %u) Ready to die...\n",
  524. smp_processor_id(), hard_smp_processor_id());
  525. enter_rtas(__pa(rtas_args));
  526. panic("Alas, I survived.\n");
  527. }
  528. /*
  529. * Call early during boot, before mem init or bootmem, to retrieve the RTAS
  530. * informations from the device-tree and allocate the RMO buffer for userland
  531. * accesses.
  532. */
  533. void __init rtas_initialize(void)
  534. {
  535. unsigned long rtas_region = RTAS_INSTANTIATE_MAX;
  536. /* Get RTAS dev node and fill up our "rtas" structure with infos
  537. * about it.
  538. */
  539. rtas.dev = of_find_node_by_name(NULL, "rtas");
  540. if (rtas.dev) {
  541. u32 *basep, *entryp;
  542. u32 *sizep;
  543. basep = (u32 *)get_property(rtas.dev, "linux,rtas-base", NULL);
  544. sizep = (u32 *)get_property(rtas.dev, "rtas-size", NULL);
  545. if (basep != NULL && sizep != NULL) {
  546. rtas.base = *basep;
  547. rtas.size = *sizep;
  548. entryp = (u32 *)get_property(rtas.dev, "linux,rtas-entry", NULL);
  549. if (entryp == NULL) /* Ugh */
  550. rtas.entry = rtas.base;
  551. else
  552. rtas.entry = *entryp;
  553. } else
  554. rtas.dev = NULL;
  555. }
  556. if (!rtas.dev)
  557. return;
  558. /* If RTAS was found, allocate the RMO buffer for it and look for
  559. * the stop-self token if any
  560. */
  561. #ifdef CONFIG_PPC64
  562. if (_machine == PLATFORM_PSERIES_LPAR)
  563. rtas_region = min(lmb.rmo_size, RTAS_INSTANTIATE_MAX);
  564. #endif
  565. rtas_rmo_buf = lmb_alloc_base(RTAS_RMOBUF_MAX, PAGE_SIZE, rtas_region);
  566. #ifdef CONFIG_HOTPLUG_CPU
  567. rtas_stop_self_args.token = rtas_token("stop-self");
  568. #endif /* CONFIG_HOTPLUG_CPU */
  569. #ifdef CONFIG_RTAS_ERROR_LOGGING
  570. rtas_last_error_token = rtas_token("rtas-last-error");
  571. #endif
  572. }
  573. EXPORT_SYMBOL(rtas_token);
  574. EXPORT_SYMBOL(rtas_call);
  575. EXPORT_SYMBOL(rtas_data_buf);
  576. EXPORT_SYMBOL(rtas_data_buf_lock);
  577. EXPORT_SYMBOL(rtas_extended_busy_delay_time);
  578. EXPORT_SYMBOL(rtas_get_sensor);
  579. EXPORT_SYMBOL(rtas_get_power_level);
  580. EXPORT_SYMBOL(rtas_set_power_level);
  581. EXPORT_SYMBOL(rtas_set_indicator);