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

嵌入式Linux

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  *
  3.  * Module Name: bm_osl.c
  4.  *   $Revision: 17 $
  5.  *
  6.  *****************************************************************************/
  7. /*
  8.  *  Copyright (C) 2000, 2001 Andrew Grover
  9.  *
  10.  *  This program is free software; you can redistribute it and/or modify
  11.  *  it under the terms of the GNU General Public License as published by
  12.  *  the Free Software Foundation; either version 2 of the License, or
  13.  *  (at your option) any later version.
  14.  *
  15.  *  This program is distributed in the hope that it will be useful,
  16.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  *  GNU General Public License for more details.
  19.  *
  20.  *  You should have received a copy of the GNU General Public License
  21.  *  along with this program; if not, write to the Free Software
  22.  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  23.  */
  24. #include <linux/kernel.h>
  25. #include <linux/module.h>
  26. #include <linux/init.h>
  27. #include <linux/types.h>
  28. #include <linux/proc_fs.h>
  29. #include <linux/spinlock.h>
  30. #include <linux/poll.h>
  31. #include <asm/uaccess.h>
  32. #include <acpi.h>
  33. #include "bm.h"
  34. MODULE_AUTHOR("Andrew Grover");
  35. MODULE_DESCRIPTION("ACPI Component Architecture (CA) - ACPI Bus Manager");
  36. MODULE_LICENSE("GPL");
  37. /*****************************************************************************
  38.  *                               Types & Defines
  39.  *****************************************************************************/
  40. typedef struct
  41. {
  42. BM_HANDLE device_handle;
  43. char *device_type;
  44. char *device_instance;
  45. u32 event_type;
  46. u32 event_data;
  47. struct list_head list;
  48. } BM_OSL_EVENT;
  49. #define BM_PROC_ROOT "acpi"
  50. #define BM_PROC_EVENT "event"
  51. #define BM_PROC_DEVICES "devices"
  52. #define BM_MAX_STRING_LENGTH 80
  53. /****************************************************************************
  54.  *                                  Globals
  55.  ****************************************************************************/
  56. struct proc_dir_entry *bm_proc_root = NULL;
  57. static struct proc_dir_entry *bm_proc_event = NULL;
  58. #ifdef ACPI_DEBUG
  59. static u32 save_dbg_layer;
  60. static u32 save_dbg_level;
  61. #endif /*ACPI_DEBUG*/
  62. extern BM_NODE_LIST node_list;
  63. static spinlock_t bm_osl_event_lock = SPIN_LOCK_UNLOCKED;
  64. static LIST_HEAD(bm_event_list);
  65. static DECLARE_WAIT_QUEUE_HEAD(bm_event_wait_queue);
  66. static int event_is_open = 0;
  67. /****************************************************************************
  68.  *                                 Functions
  69.  ****************************************************************************/
  70. /****************************************************************************
  71.  *
  72.  * FUNCTION: bm_osl_generate_event
  73.  *
  74.  * DESCRIPTION: Generates an event for user-space consumption by writing
  75.  *              the event data to the 'event' file.
  76.  *
  77.  ****************************************************************************/
  78. acpi_status
  79. bm_osl_generate_event (
  80. BM_HANDLE device_handle,
  81. char *device_type,
  82. char *device_instance,
  83. u32 event_type,
  84. u32 event_data)
  85. {
  86. BM_OSL_EVENT *event = NULL;
  87. u32 flags = 0;
  88. /* drop event on the floor if no one's listening */
  89. if (!event_is_open)
  90. return (AE_OK);
  91. /*
  92.  * Allocate a new event structure.
  93.  */
  94. event = acpi_os_callocate(sizeof(BM_OSL_EVENT));
  95. if (!event)
  96. goto alloc_error;
  97. event->device_type = acpi_os_callocate(strlen(device_type)
  98. + sizeof(char));
  99. if (!event->device_type)
  100. goto alloc_error;
  101. event->device_instance = acpi_os_callocate(strlen(device_instance)
  102. + sizeof(char));
  103. if (!event->device_instance)
  104. goto alloc_error;
  105. /*
  106.  * Set event data.
  107.  */
  108. event->device_handle = device_handle;
  109. strcpy(event->device_type, device_type);
  110. strcpy(event->device_instance, device_instance);
  111. event->event_type = event_type;
  112. event->event_data = event_data;
  113. /*
  114.  * Add to the end of our event list.
  115.  */
  116. spin_lock_irqsave(&bm_osl_event_lock, flags);
  117. list_add_tail(&event->list, &bm_event_list);
  118. spin_unlock_irqrestore(&bm_osl_event_lock, flags);
  119. /*
  120.  * Signal waiting threads (if any).
  121.  */
  122. wake_up_interruptible(&bm_event_wait_queue);
  123. return(AE_OK);
  124. alloc_error:
  125. if (event->device_instance)
  126. acpi_os_free(event->device_instance);
  127. if (event->device_type)
  128. acpi_os_free(event->device_type);
  129. if (event)
  130. acpi_os_free(event);
  131. return (AE_NO_MEMORY);
  132. }
  133. static int bm_osl_open_event(struct inode *inode, struct file *file)
  134. {
  135. spin_lock_irq (&bm_osl_event_lock);
  136. if(event_is_open)
  137. goto out_busy;
  138. event_is_open = 1;
  139. spin_unlock_irq (&bm_osl_event_lock);
  140. return 0;
  141. out_busy:
  142. spin_unlock_irq (&bm_osl_event_lock);
  143. return -EBUSY;
  144. }
  145. static int bm_osl_close_event(struct inode *inode, struct file *file)
  146. {
  147. event_is_open = 0;
  148. return 0;
  149. }
  150. /****************************************************************************
  151.  *
  152.  * FUNCTION: bm_osl_read_event
  153.  *
  154.  * DESCRIPTION: Handles reads to the 'event' file by blocking user-mode
  155.  *              threads until data (an event) is generated.
  156.  *
  157.  ****************************************************************************/
  158. static ssize_t
  159. bm_osl_read_event(
  160. struct file *file,
  161. char *buf,
  162. size_t count,
  163. loff_t *ppos)
  164. {
  165. BM_OSL_EVENT *event = NULL;
  166. unsigned long flags = 0;
  167. static char str[BM_MAX_STRING_LENGTH];
  168. static int chars_remaining = 0;
  169. static char  *ptr;
  170. if (!chars_remaining) {
  171. DECLARE_WAITQUEUE(wait, current);
  172. if (list_empty(&bm_event_list)) {
  173. if (file->f_flags & O_NONBLOCK)
  174. return -EAGAIN;
  175. set_current_state(TASK_INTERRUPTIBLE);
  176. add_wait_queue(&bm_event_wait_queue, &wait);
  177. if (list_empty(&bm_event_list)) {
  178. schedule();
  179. }
  180. remove_wait_queue(&bm_event_wait_queue, &wait);
  181. set_current_state(TASK_RUNNING);
  182. if (signal_pending(current)) {
  183. return -ERESTARTSYS;
  184. }
  185. }
  186. spin_lock_irqsave(&bm_osl_event_lock, flags);
  187. event = list_entry(bm_event_list.next, BM_OSL_EVENT, list);
  188. list_del(&event->list);
  189. spin_unlock_irqrestore(&bm_osl_event_lock, flags);
  190. chars_remaining = sprintf(str, "%s %s %08x %08xn",
  191. event->device_type, event->device_instance,
  192. event->event_type, event->event_data);
  193. ptr = str;
  194. acpi_os_free(event->device_type);
  195. acpi_os_free(event->device_instance);
  196. acpi_os_free(event);
  197. }
  198. if (chars_remaining < count)
  199. count = chars_remaining;
  200. if (copy_to_user(buf, ptr, count))
  201. return -EFAULT;
  202. *ppos += count;
  203. chars_remaining -= count;
  204. ptr += count;
  205. return count;
  206. }
  207. /****************************************************************************
  208.  *
  209.  * FUNCTION: bm_osl_poll_event
  210.  *
  211.  * DESCRIPTION: Handles poll() of the 'event' file by blocking user-mode 
  212.  *              threads until data (an event) is generated.
  213.  *
  214.  ****************************************************************************/
  215. static unsigned int
  216. bm_osl_poll_event(
  217. struct file *file, 
  218. poll_table *wait)
  219. {
  220. poll_wait(file, &bm_event_wait_queue, wait);
  221. if (!list_empty(&bm_event_list))
  222. return POLLIN | POLLRDNORM;
  223. return 0;
  224. }
  225. struct file_operations proc_event_operations = {
  226. open: bm_osl_open_event,
  227. read: bm_osl_read_event,
  228. release: bm_osl_close_event,
  229. poll: bm_osl_poll_event,
  230. };
  231. /****************************************************************************
  232.  *
  233.  * FUNCTION:    bm_osl_init
  234.  *
  235.  ****************************************************************************/
  236. int
  237. bm_osl_init(void)
  238. {
  239. acpi_status status = AE_OK;
  240. status = acpi_subsystem_status();
  241. if (ACPI_FAILURE(status))
  242. return -ENODEV;
  243. bm_proc_root = proc_mkdir(BM_PROC_ROOT, NULL);
  244. if (!bm_proc_root) {
  245. return(AE_ERROR);
  246. }
  247. bm_proc_event = create_proc_entry(BM_PROC_EVENT, S_IRUSR, bm_proc_root);
  248. if (bm_proc_event) {
  249. bm_proc_event->proc_fops = &proc_event_operations;
  250. }
  251. status = bm_initialize();
  252. return (ACPI_SUCCESS(status)) ? 0 : -ENODEV;
  253. }
  254. /****************************************************************************
  255.  *
  256.  * FUNCTION:    bm_osl_cleanup
  257.  *
  258.  ****************************************************************************/
  259. void
  260. bm_osl_cleanup(void)
  261. {
  262. bm_terminate();
  263. if (bm_proc_event) {
  264. remove_proc_entry(BM_PROC_EVENT, bm_proc_root);
  265. bm_proc_event = NULL;
  266. }
  267. if (bm_proc_root) {
  268. remove_proc_entry(BM_PROC_ROOT, NULL);
  269. bm_proc_root = NULL;
  270. }
  271. return;
  272. }
  273. module_init(bm_osl_init);
  274. module_exit(bm_osl_cleanup);
  275. /****************************************************************************
  276.  *                                  Symbols
  277.  ****************************************************************************/
  278. /* bm.c */
  279. EXPORT_SYMBOL(bm_get_node);
  280. /* bmdriver.c */
  281. EXPORT_SYMBOL(bm_get_device_power_state);
  282. EXPORT_SYMBOL(bm_set_device_power_state);
  283. EXPORT_SYMBOL(bm_get_device_info);
  284. EXPORT_SYMBOL(bm_get_device_status);
  285. EXPORT_SYMBOL(bm_get_device_context);
  286. EXPORT_SYMBOL(bm_register_driver);
  287. EXPORT_SYMBOL(bm_unregister_driver);
  288. /* bmsearch.c */
  289. EXPORT_SYMBOL(bm_search);
  290. /* bmrequest.c */
  291. EXPORT_SYMBOL(bm_request);
  292. /* bmutils.c */
  293. EXPORT_SYMBOL(bm_extract_package_data);
  294. EXPORT_SYMBOL(bm_evaluate_object);
  295. EXPORT_SYMBOL(bm_evaluate_simple_integer);
  296. EXPORT_SYMBOL(bm_evaluate_reference_list);
  297. EXPORT_SYMBOL(bm_copy_to_buffer);
  298. EXPORT_SYMBOL(bm_cast_buffer);
  299. /* bm_proc.c */
  300. EXPORT_SYMBOL(bm_osl_generate_event);
  301. EXPORT_SYMBOL(bm_proc_root);