power.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:3k
源码类别:

Linux/Unix编程

开发平台:

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;
  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 void machine_alt_power_off(void);
  31. static void (*poweroff_method)(void) = machine_alt_power_off;
  32. extern int serial_console;
  33. void machine_power_off(void)
  34. {
  35. if (!serial_console) {
  36. #ifdef CONFIG_PCI
  37. if (power_reg != 0UL) {
  38. /* Both register bits seem to have the
  39.  * same effect, so until I figure out
  40.  * what the difference is...
  41.  */
  42. writel(POWER_COURTESY_OFF | POWER_SYSTEM_OFF, power_reg);
  43. } else
  44. #endif /* CONFIG_PCI */
  45. if (poweroff_method != NULL) {
  46. poweroff_method();
  47. /* not reached */
  48. }
  49. }
  50. machine_halt();
  51. }
  52. #ifdef CONFIG_PCI
  53. static int powerd(void *__unused)
  54. {
  55. static char *envp[] = { "HOME=/", "TERM=linux", "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };
  56. char *argv[] = { "/sbin/shutdown", "-h", "now", NULL };
  57. daemonize();
  58. sprintf(current->comm, "powerd");
  59. again:
  60. while (button_pressed == 0) {
  61. spin_lock_irq(&current->sigmask_lock);
  62. flush_signals(current);
  63. spin_unlock_irq(&current->sigmask_lock);
  64. interruptible_sleep_on(&powerd_wait);
  65. }
  66. /* Ok, down we go... */
  67. if (execve("/sbin/shutdown", argv, envp) < 0) {
  68. printk("powerd: shutdown execution failedn");
  69. button_pressed = 0;
  70. goto again;
  71. }
  72. return 0;
  73. }
  74. void __init power_init(void)
  75. {
  76. struct linux_ebus *ebus;
  77. struct linux_ebus_device *edev;
  78. static int invoked;
  79. if (invoked)
  80. return;
  81. invoked = 1;
  82. for_each_ebus(ebus) {
  83. for_each_ebusdev(edev, ebus) {
  84. if (!strcmp(edev->prom_name, "power"))
  85. goto found;
  86. }
  87. }
  88. return;
  89. found:
  90. power_reg = (unsigned long)ioremap(edev->resource[0].start, 0x4);
  91. printk("power: Control reg at %016lx ... ", power_reg);
  92. poweroff_method = machine_halt; /* able to use the standard poweroff */
  93. if (edev->irqs[0] != PCI_IRQ_NONE) {
  94. if (kernel_thread(powerd, 0, CLONE_FS) < 0) {
  95. printk("Failed to start power daemon.n");
  96. return;
  97. }
  98. printk("powerd running.n");
  99. if (request_irq(edev->irqs[0],
  100. power_handler, SA_SHIRQ, "power",
  101. (void *) power_reg) < 0)
  102. printk("power: Error, cannot register IRQ handler.n");
  103. } else {
  104. printk("not using powerd.n");
  105. }
  106. }
  107. #endif /* CONFIG_PCI */