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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * Wdt977 0.02: A Watchdog Device for Netwinder W83977AF chip
  3.  *
  4.  * (c) Copyright 1998 Rebel.com (Woody Suwalski <woody@netwinder.org>)
  5.  *
  6.  * -----------------------
  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.  * -----------------------
  14.  *      14-Dec-2001 Matt Domsch <Matt_Domsch@dell.com>
  15.  *           Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
  16.  */
  17.  
  18. #include <linux/module.h>
  19. #include <linux/config.h>
  20. #include <linux/types.h>
  21. #include <linux/kernel.h>
  22. #include <linux/fs.h>
  23. #include <linux/miscdevice.h>
  24. #include <linux/init.h>
  25. #include <linux/smp_lock.h>
  26. #include <asm/io.h>
  27. #include <asm/system.h>
  28. #include <asm/mach-types.h>
  29. #define WATCHDOG_MINOR 130
  30. static int timeout = 3;
  31. static int timer_alive;
  32. static int testmode;
  33. static int expect_close = 0;
  34. #ifdef CONFIG_WATCHDOG_NOWAYOUT
  35. static int nowayout = 1;
  36. #else
  37. static int nowayout = 0;
  38. #endif
  39. MODULE_PARM(nowayout,"i");
  40. MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
  41. /*
  42.  * Allow only one person to hold it open
  43.  */
  44.  
  45. static int wdt977_open(struct inode *inode, struct file *file)
  46. {
  47. if(timer_alive)
  48. return -EBUSY;
  49. if (nowayout) {
  50. MOD_INC_USE_COUNT;
  51. }
  52. timer_alive++;
  53. //max timeout value = 255 minutes (0xFF). Write 0 to disable WatchDog.
  54. if (timeout>255)
  55.     timeout = 255;
  56. printk(KERN_INFO "Watchdog: active, current timeout %d min.n",timeout);
  57. // unlock the SuperIO chip
  58. outb(0x87,0x370); 
  59. outb(0x87,0x370); 
  60. //select device Aux2 (device=8) and set watchdog regs F2, F3 and F4
  61. //F2 has the timeout in minutes
  62. //F3 could be set to the POWER LED blink (with GP17 set to PowerLed)
  63. //   at timeout, and to reset timer on kbd/mouse activity (not now)
  64. //F4 is used to just clear the TIMEOUT'ed state (bit 0)
  65. outb(0x07,0x370);
  66. outb(0x08,0x371);
  67. outb(0xF2,0x370);
  68. outb(timeout,0x371);
  69. outb(0xF3,0x370);
  70. outb(0x00,0x371); //another setting is 0E for kbd/mouse/LED
  71. outb(0xF4,0x370);
  72. outb(0x00,0x371);
  73. //at last select device Aux1 (dev=7) and set GP16 as a watchdog output
  74. if (!testmode)
  75. {
  76. outb(0x07,0x370);
  77. outb(0x07,0x371);
  78. outb(0xE6,0x370);
  79. outb(0x08,0x371);
  80. }
  81. // lock the SuperIO chip
  82. outb(0xAA,0x370); 
  83. return 0;
  84. }
  85. static int wdt977_release(struct inode *inode, struct file *file)
  86. {
  87. /*
  88.  * Shut off the timer.
  89.  *  Lock it in if it's a module and we set nowayout
  90.  */
  91. lock_kernel();
  92. if (expect_close) {
  93. // unlock the SuperIO chip
  94. outb(0x87,0x370); 
  95. outb(0x87,0x370); 
  96. //select device Aux2 (device=8) and set watchdog regs F2,F3 and F4
  97. //F3 is reset to its default state
  98. //F4 can clear the TIMEOUT'ed state (bit 0) - back to default
  99. //We can not use GP17 as a PowerLed, as we use its usage as a RedLed
  100. outb(0x07,0x370);
  101. outb(0x08,0x371);
  102. outb(0xF2,0x370);
  103. outb(0xFF,0x371);
  104. outb(0xF3,0x370);
  105. outb(0x00,0x371);
  106. outb(0xF4,0x370);
  107. outb(0x00,0x371);
  108. outb(0xF2,0x370);
  109. outb(0x00,0x371);
  110. //at last select device Aux1 (dev=7) and set GP16 as a watchdog output
  111. outb(0x07,0x370);
  112. outb(0x07,0x371);
  113. outb(0xE6,0x370);
  114. outb(0x08,0x371);
  115. // lock the SuperIO chip
  116. outb(0xAA,0x370);
  117. printk(KERN_INFO "Watchdog: shutdown.n");
  118. } else {
  119. printk(KERN_CRIT "WDT device closed unexpectedly.  WDT will not stop!n");
  120. }
  121. timer_alive=0;
  122. unlock_kernel();
  123. return 0;
  124. }
  125. static ssize_t wdt977_write(struct file *file, const char *data, size_t len, loff_t *ppos)
  126. {
  127. if (!nowayout) {
  128. size_t i;
  129. /* In case it was set long ago */
  130. expect_close = 0;
  131. for (i = 0; i != len; i++) {
  132. char c;
  133. if (get_user(c, data + i))
  134. return -EFAULT;
  135. if (c == 'V')
  136. expect_close = 1;
  137. }
  138. }
  139. //max timeout value = 255 minutes (0xFF). Write 0 to disable WatchDog.
  140. if (timeout>255)
  141.     timeout = 255;
  142. /*
  143.  * Refresh the timer.
  144.  */
  145. //we have a hw bug somewhere, so each 977 minute is actually only 30sec
  146. //as such limit the max timeout to half of max of 255 minutes...
  147. // if (timeout>126)
  148. //     timeout = 126;
  149. // unlock the SuperIO chip
  150. outb(0x87,0x370); 
  151. outb(0x87,0x370); 
  152. //select device Aux2 (device=8) and kicks watchdog reg F2
  153. //F2 has the timeout in minutes
  154. outb(0x07,0x370);
  155. outb(0x08,0x371);
  156. outb(0xF2,0x370);
  157. outb(timeout,0x371);
  158. // lock the SuperIO chip
  159. outb(0xAA,0x370); 
  160. return 1;
  161. }
  162. static struct file_operations wdt977_fops=
  163. {
  164. owner: THIS_MODULE,
  165. write: wdt977_write,
  166. open: wdt977_open,
  167. release: wdt977_release,
  168. };
  169. static struct miscdevice wdt977_miscdev=
  170. {
  171. WATCHDOG_MINOR,
  172. "watchdog",
  173. &wdt977_fops
  174. };
  175. static int __init nwwatchdog_init(void)
  176. {
  177. if (!machine_is_netwinder())
  178. return -ENODEV;
  179. misc_register(&wdt977_miscdev);
  180. printk(KERN_INFO "NetWinder Watchdog sleeping.n");
  181. return 0;
  182. }
  183. static void __exit nwwatchdog_exit(void)
  184. {
  185. misc_deregister(&wdt977_miscdev);
  186. }
  187. EXPORT_NO_SYMBOLS;
  188. module_init(nwwatchdog_init);
  189. module_exit(nwwatchdog_exit);
  190. MODULE_LICENSE("GPL");