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

嵌入式Linux

开发平台:

Unix_Linux

  1. /* $Id: power.c,v 1.9.2.1 2001/12/11 01:57:49 davem Exp $
  2.  * power.c: Power management driver.
  3.  *
  4.  * Copyright (C) 1999 David S. Miller (davem@redhat.com)
  5.  */
  6. #include <linux/config.h>
  7. #include <linux/kernel.h>
  8. #include <linux/init.h>
  9. #include <linux/sched.h>
  10. #include <linux/signal.h>
  11. #include <linux/delay.h>
  12. #include <asm/ebus.h>
  13. #define __KERNEL_SYSCALLS__
  14. #include <linux/unistd.h>
  15. #ifdef CONFIG_PCI
  16. static unsigned long power_reg = 0UL;
  17. #define POWER_SYSTEM_OFF (1 << 0)
  18. #define POWER_COURTESY_OFF (1 << 1)
  19. static DECLARE_WAIT_QUEUE_HEAD(powerd_wait);
  20. static int button_pressed = 0;
  21. static void power_handler(int irq, void *dev_id, struct pt_regs *regs)
  22. {
  23. if (button_pressed == 0) {
  24. wake_up(&powerd_wait);
  25. button_pressed = 1;
  26. }
  27. }
  28. #endif /* CONFIG_PCI */
  29. extern void machine_halt(void);
  30. extern int serial_console;
  31. void machine_power_off(void)
  32. {
  33. #ifdef CONFIG_PCI
  34. if (power_reg != 0UL && !serial_console) {
  35. /* Both register bits seem to have the
  36.  * same effect, so until I figure out
  37.  * what the difference is...
  38.  */
  39. writel(POWER_COURTESY_OFF | POWER_SYSTEM_OFF, power_reg);
  40. }
  41. #endif /* CONFIG_PCI */
  42. machine_halt();
  43. }
  44. #ifdef CONFIG_PCI
  45. static int powerd(void *__unused)
  46. {
  47. static char *envp[] = { "HOME=/", "TERM=linux", "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };
  48. char *argv[] = { "/sbin/shutdown", "-h", "now", NULL };
  49. daemonize();
  50. sprintf(current->comm, "powerd");
  51. again:
  52. while (button_pressed == 0) {
  53. spin_lock_irq(&current->sigmask_lock);
  54. flush_signals(current);
  55. spin_unlock_irq(&current->sigmask_lock);
  56. interruptible_sleep_on(&powerd_wait);
  57. }
  58. /* Ok, down we go... */
  59. if (execve("/sbin/shutdown", argv, envp) < 0) {
  60. printk("powerd: shutdown execution failedn");
  61. button_pressed = 0;
  62. goto again;
  63. }
  64. return 0;
  65. }
  66. void __init power_init(void)
  67. {
  68. struct linux_ebus *ebus;
  69. struct linux_ebus_device *edev;
  70. static int invoked = 0;
  71. if (invoked)
  72. return;
  73. invoked = 1;
  74. for_each_ebus(ebus) {
  75. for_each_ebusdev(edev, ebus) {
  76. if (!strcmp(edev->prom_name, "power"))
  77. goto found;
  78. }
  79. }
  80. return;
  81. found:
  82. power_reg = (unsigned long)ioremap(edev->resource[0].start, 0x4);
  83. printk("power: Control reg at %016lx ... ", power_reg);
  84. if (edev->irqs[0] != PCI_IRQ_NONE) {
  85. if (kernel_thread(powerd, 0, CLONE_FS) < 0) {
  86. printk("Failed to start power daemon.n");
  87. return;
  88. }
  89. printk("powerd running.n");
  90. if (request_irq(edev->irqs[0],
  91. power_handler, SA_SHIRQ, "power",
  92. (void *) power_reg) < 0)
  93. printk("power: Error, cannot register IRQ handler.n");
  94. } else {
  95. printk("not using powerd.n");
  96. }
  97. }
  98. #endif /* CONFIG_PCI */