2 * ACPI-WMI mapping driver
4 * Copyright (C) 2007-2008 Carlos Corbacho <carlos@strangeworlds.co.uk>
6 * GUID parsing code from ldm.c is:
7 * Copyright (C) 2001,2002 Richard Russon <ldm@flatcap.org>
8 * Copyright (c) 2001-2007 Anton Altaparmakov
9 * Copyright (C) 2001,2002 Jakob Kemi <jakob.kemi@telia.com>
11 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or (at
16 * your option) any later version.
18 * This program is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 * General Public License for more details.
23 * You should have received a copy of the GNU General Public License along
24 * with this program; if not, write to the Free Software Foundation, Inc.,
25 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
27 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
30 #include <linux/kernel.h>
31 #include <linux/init.h>
32 #include <linux/types.h>
33 #include <linux/device.h>
34 #include <linux/list.h>
35 #include <linux/acpi.h>
36 #include <linux/slab.h>
37 #include <acpi/acpi_bus.h>
38 #include <acpi/acpi_drivers.h>
40 ACPI_MODULE_NAME("wmi");
41 MODULE_AUTHOR("Carlos Corbacho");
42 MODULE_DESCRIPTION("ACPI-WMI Mapping Driver");
43 MODULE_LICENSE("GPL");
45 #define ACPI_WMI_CLASS "wmi"
47 #define PREFIX "ACPI: WMI: "
49 static DEFINE_MUTEX(wmi_data_lock);
56 unsigned char notify_id;
57 unsigned char reserved;
65 struct list_head list;
66 struct guid_block gblock;
68 wmi_notify_handler handler;
73 static struct wmi_block wmi_blocks;
76 * If the GUID data block is marked as expensive, we must enable and
77 * explicitily disable data collection.
79 #define ACPI_WMI_EXPENSIVE 0x1
80 #define ACPI_WMI_METHOD 0x2 /* GUID is a method */
81 #define ACPI_WMI_STRING 0x4 /* GUID takes & returns a string */
82 #define ACPI_WMI_EVENT 0x8 /* GUID is an event */
84 static int debug_event;
85 module_param(debug_event, bool, 0444);
86 MODULE_PARM_DESC(debug_event,
87 "Log WMI Events [0/1]");
89 static int debug_dump_wdg;
90 module_param(debug_dump_wdg, bool, 0444);
91 MODULE_PARM_DESC(debug_dump_wdg,
92 "Dump available WMI interfaces [0/1]");
94 static int acpi_wmi_remove(struct acpi_device *device, int type);
95 static int acpi_wmi_add(struct acpi_device *device);
96 static void acpi_wmi_notify(struct acpi_device *device, u32 event);
98 static const struct acpi_device_id wmi_device_ids[] = {
103 MODULE_DEVICE_TABLE(acpi, wmi_device_ids);
105 static struct acpi_driver acpi_wmi_driver = {
107 .class = ACPI_WMI_CLASS,
108 .ids = wmi_device_ids,
111 .remove = acpi_wmi_remove,
112 .notify = acpi_wmi_notify,
117 * GUID parsing functions
121 * wmi_parse_hexbyte - Convert a ASCII hex number to a byte
122 * @src: Pointer to at least 2 characters to convert.
124 * Convert a two character ASCII hex string to a number.
126 * Return: 0-255 Success, the byte was parsed correctly
127 * -1 Error, an invalid character was supplied
129 static int wmi_parse_hexbyte(const u8 *src)
131 unsigned int x; /* For correct wrapping */
136 if (x - '0' <= '9' - '0') {
138 } else if (x - 'a' <= 'f' - 'a') {
140 } else if (x - 'A' <= 'F' - 'A') {
149 if (x - '0' <= '9' - '0')
150 return h | (x - '0');
151 if (x - 'a' <= 'f' - 'a')
152 return h | (x - 'a' + 10);
153 if (x - 'A' <= 'F' - 'A')
154 return h | (x - 'A' + 10);
159 * wmi_swap_bytes - Rearrange GUID bytes to match GUID binary
160 * @src: Memory block holding binary GUID (16 bytes)
161 * @dest: Memory block to hold byte swapped binary GUID (16 bytes)
163 * Byte swap a binary GUID to match it's real GUID value
165 static void wmi_swap_bytes(u8 *src, u8 *dest)
169 for (i = 0; i <= 3; i++)
170 memcpy(dest + i, src + (3 - i), 1);
172 for (i = 0; i <= 1; i++)
173 memcpy(dest + 4 + i, src + (5 - i), 1);
175 for (i = 0; i <= 1; i++)
176 memcpy(dest + 6 + i, src + (7 - i), 1);
178 memcpy(dest + 8, src + 8, 8);
182 * wmi_parse_guid - Convert GUID from ASCII to binary
183 * @src: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba
184 * @dest: Memory block to hold binary GUID (16 bytes)
186 * N.B. The GUID need not be NULL terminated.
188 * Return: 'true' @dest contains binary GUID
189 * 'false' @dest contents are undefined
191 static bool wmi_parse_guid(const u8 *src, u8 *dest)
193 static const int size[] = { 4, 2, 2, 2, 6 };
196 if (src[8] != '-' || src[13] != '-' ||
197 src[18] != '-' || src[23] != '-')
200 for (j = 0; j < 5; j++, src++) {
201 for (i = 0; i < size[j]; i++, src += 2, *dest++ = v) {
202 v = wmi_parse_hexbyte(src);
212 * Convert a raw GUID to the ACII string representation
214 static int wmi_gtoa(const char *in, char *out)
218 for (i = 3; i >= 0; i--)
219 out += sprintf(out, "%02X", in[i] & 0xFF);
221 out += sprintf(out, "-");
222 out += sprintf(out, "%02X", in[5] & 0xFF);
223 out += sprintf(out, "%02X", in[4] & 0xFF);
224 out += sprintf(out, "-");
225 out += sprintf(out, "%02X", in[7] & 0xFF);
226 out += sprintf(out, "%02X", in[6] & 0xFF);
227 out += sprintf(out, "-");
228 out += sprintf(out, "%02X", in[8] & 0xFF);
229 out += sprintf(out, "%02X", in[9] & 0xFF);
230 out += sprintf(out, "-");
232 for (i = 10; i <= 15; i++)
233 out += sprintf(out, "%02X", in[i] & 0xFF);
239 static bool find_guid(const char *guid_string, struct wmi_block **out)
241 char tmp[16], guid_input[16];
242 struct wmi_block *wblock;
243 struct guid_block *block;
246 wmi_parse_guid(guid_string, tmp);
247 wmi_swap_bytes(tmp, guid_input);
249 list_for_each(p, &wmi_blocks.list) {
250 wblock = list_entry(p, struct wmi_block, list);
251 block = &wblock->gblock;
253 if (memcmp(block->guid, guid_input, 16) == 0) {
262 static acpi_status wmi_method_enable(struct wmi_block *wblock, int enable)
264 struct guid_block *block = NULL;
266 struct acpi_object_list input;
267 union acpi_object params[1];
271 block = &wblock->gblock;
272 handle = wblock->handle;
278 input.pointer = params;
279 params[0].type = ACPI_TYPE_INTEGER;
280 params[0].integer.value = enable;
282 snprintf(method, 5, "WE%02X", block->notify_id);
283 status = acpi_evaluate_object(handle, method, &input, NULL);
285 if (status != AE_OK && status != AE_NOT_FOUND)
292 * Exported WMI functions
295 * wmi_evaluate_method - Evaluate a WMI method
296 * @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba
297 * @instance: Instance index
298 * @method_id: Method ID to call
299 * &in: Buffer containing input for the method call
300 * &out: Empty buffer to return the method results
302 * Call an ACPI-WMI method
304 acpi_status wmi_evaluate_method(const char *guid_string, u8 instance,
305 u32 method_id, const struct acpi_buffer *in, struct acpi_buffer *out)
307 struct guid_block *block = NULL;
308 struct wmi_block *wblock = NULL;
311 struct acpi_object_list input;
312 union acpi_object params[3];
313 char method[5] = "WM";
315 if (!find_guid(guid_string, &wblock))
318 block = &wblock->gblock;
319 handle = wblock->handle;
321 if (!(block->flags & ACPI_WMI_METHOD))
324 if (block->instance_count < instance)
325 return AE_BAD_PARAMETER;
328 input.pointer = params;
329 params[0].type = ACPI_TYPE_INTEGER;
330 params[0].integer.value = instance;
331 params[1].type = ACPI_TYPE_INTEGER;
332 params[1].integer.value = method_id;
337 if (block->flags & ACPI_WMI_STRING) {
338 params[2].type = ACPI_TYPE_STRING;
340 params[2].type = ACPI_TYPE_BUFFER;
342 params[2].buffer.length = in->length;
343 params[2].buffer.pointer = in->pointer;
346 strncat(method, block->object_id, 2);
348 status = acpi_evaluate_object(handle, method, &input, out);
352 EXPORT_SYMBOL_GPL(wmi_evaluate_method);
355 * wmi_query_block - Return contents of a WMI block
356 * @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba
357 * @instance: Instance index
358 * &out: Empty buffer to return the contents of the data block to
360 * Return the contents of an ACPI-WMI data block to a buffer
362 acpi_status wmi_query_block(const char *guid_string, u8 instance,
363 struct acpi_buffer *out)
365 struct guid_block *block = NULL;
366 struct wmi_block *wblock = NULL;
367 acpi_handle handle, wc_handle;
368 acpi_status status, wc_status = AE_ERROR;
369 struct acpi_object_list input, wc_input;
370 union acpi_object wc_params[1], wq_params[1];
372 char wc_method[5] = "WC";
374 if (!guid_string || !out)
375 return AE_BAD_PARAMETER;
377 if (!find_guid(guid_string, &wblock))
380 block = &wblock->gblock;
381 handle = wblock->handle;
383 if (block->instance_count < instance)
384 return AE_BAD_PARAMETER;
386 /* Check GUID is a data block */
387 if (block->flags & (ACPI_WMI_EVENT | ACPI_WMI_METHOD))
391 input.pointer = wq_params;
392 wq_params[0].type = ACPI_TYPE_INTEGER;
393 wq_params[0].integer.value = instance;
396 * If ACPI_WMI_EXPENSIVE, call the relevant WCxx method first to
399 if (block->flags & ACPI_WMI_EXPENSIVE) {
401 wc_input.pointer = wc_params;
402 wc_params[0].type = ACPI_TYPE_INTEGER;
403 wc_params[0].integer.value = 1;
405 strncat(wc_method, block->object_id, 2);
408 * Some GUIDs break the specification by declaring themselves
409 * expensive, but have no corresponding WCxx method. So we
410 * should not fail if this happens.
412 wc_status = acpi_get_handle(handle, wc_method, &wc_handle);
413 if (ACPI_SUCCESS(wc_status))
414 wc_status = acpi_evaluate_object(handle, wc_method,
418 strcpy(method, "WQ");
419 strncat(method, block->object_id, 2);
421 status = acpi_evaluate_object(handle, method, &input, out);
424 * If ACPI_WMI_EXPENSIVE, call the relevant WCxx method, even if
425 * the WQxx method failed - we should disable collection anyway.
427 if ((block->flags & ACPI_WMI_EXPENSIVE) && ACPI_SUCCESS(wc_status)) {
428 wc_params[0].integer.value = 0;
429 status = acpi_evaluate_object(handle,
430 wc_method, &wc_input, NULL);
435 EXPORT_SYMBOL_GPL(wmi_query_block);
438 * wmi_set_block - Write to a WMI block
439 * @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba
440 * @instance: Instance index
441 * &in: Buffer containing new values for the data block
443 * Write the contents of the input buffer to an ACPI-WMI data block
445 acpi_status wmi_set_block(const char *guid_string, u8 instance,
446 const struct acpi_buffer *in)
448 struct guid_block *block = NULL;
449 struct wmi_block *wblock = NULL;
451 struct acpi_object_list input;
452 union acpi_object params[2];
453 char method[5] = "WS";
455 if (!guid_string || !in)
458 if (!find_guid(guid_string, &wblock))
461 block = &wblock->gblock;
462 handle = wblock->handle;
464 if (block->instance_count < instance)
465 return AE_BAD_PARAMETER;
467 /* Check GUID is a data block */
468 if (block->flags & (ACPI_WMI_EVENT | ACPI_WMI_METHOD))
472 input.pointer = params;
473 params[0].type = ACPI_TYPE_INTEGER;
474 params[0].integer.value = instance;
476 if (block->flags & ACPI_WMI_STRING) {
477 params[1].type = ACPI_TYPE_STRING;
479 params[1].type = ACPI_TYPE_BUFFER;
481 params[1].buffer.length = in->length;
482 params[1].buffer.pointer = in->pointer;
484 strncat(method, block->object_id, 2);
486 return acpi_evaluate_object(handle, method, &input, NULL);
488 EXPORT_SYMBOL_GPL(wmi_set_block);
490 static void wmi_dump_wdg(struct guid_block *g)
492 char guid_string[37];
494 wmi_gtoa(g->guid, guid_string);
495 printk(KERN_INFO PREFIX "%s:\n", guid_string);
496 printk(KERN_INFO PREFIX "\tobject_id: %c%c\n",
497 g->object_id[0], g->object_id[1]);
498 printk(KERN_INFO PREFIX "\tnotify_id: %02X\n", g->notify_id);
499 printk(KERN_INFO PREFIX "\treserved: %02X\n", g->reserved);
500 printk(KERN_INFO PREFIX "\tinstance_count: %d\n", g->instance_count);
501 printk(KERN_INFO PREFIX "\tflags: %#x", g->flags);
504 if (g->flags & ACPI_WMI_EXPENSIVE)
505 printk("ACPI_WMI_EXPENSIVE ");
506 if (g->flags & ACPI_WMI_METHOD)
507 printk("ACPI_WMI_METHOD ");
508 if (g->flags & ACPI_WMI_STRING)
509 printk("ACPI_WMI_STRING ");
510 if (g->flags & ACPI_WMI_EVENT)
511 printk("ACPI_WMI_EVENT ");
517 static void wmi_notify_debug(u32 value, void *context)
519 struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
520 union acpi_object *obj;
522 wmi_get_event_data(value, &response);
524 obj = (union acpi_object *)response.pointer;
529 printk(KERN_INFO PREFIX "DEBUG Event ");
531 case ACPI_TYPE_BUFFER:
532 printk("BUFFER_TYPE - length %d\n", obj->buffer.length);
534 case ACPI_TYPE_STRING:
535 printk("STRING_TYPE - %s\n", obj->string.pointer);
537 case ACPI_TYPE_INTEGER:
538 printk("INTEGER_TYPE - %llu\n", obj->integer.value);
540 case ACPI_TYPE_PACKAGE:
541 printk("PACKAGE_TYPE - %d elements\n", obj->package.count);
544 printk("object type 0x%X\n", obj->type);
549 * wmi_install_notify_handler - Register handler for WMI events
550 * @handler: Function to handle notifications
551 * @data: Data to be returned to handler when event is fired
553 * Register a handler for events sent to the ACPI-WMI mapper device.
555 acpi_status wmi_install_notify_handler(const char *guid,
556 wmi_notify_handler handler, void *data)
558 struct wmi_block *block;
561 if (!guid || !handler)
562 return AE_BAD_PARAMETER;
564 if (!find_guid(guid, &block))
567 if (block->handler && block->handler != wmi_notify_debug)
568 return AE_ALREADY_ACQUIRED;
570 block->handler = handler;
571 block->handler_data = data;
573 status = wmi_method_enable(block, 1);
577 EXPORT_SYMBOL_GPL(wmi_install_notify_handler);
580 * wmi_uninstall_notify_handler - Unregister handler for WMI events
582 * Unregister handler for events sent to the ACPI-WMI mapper device.
584 acpi_status wmi_remove_notify_handler(const char *guid)
586 struct wmi_block *block;
587 acpi_status status = AE_OK;
590 return AE_BAD_PARAMETER;
592 if (!find_guid(guid, &block))
595 if (!block->handler || block->handler == wmi_notify_debug)
596 return AE_NULL_ENTRY;
599 block->handler = wmi_notify_debug;
601 status = wmi_method_enable(block, 0);
602 block->handler = NULL;
603 block->handler_data = NULL;
607 EXPORT_SYMBOL_GPL(wmi_remove_notify_handler);
610 * wmi_get_event_data - Get WMI data associated with an event
612 * @event: Event to find
613 * @out: Buffer to hold event data. out->pointer should be freed with kfree()
615 * Returns extra data associated with an event in WMI.
617 acpi_status wmi_get_event_data(u32 event, struct acpi_buffer *out)
619 struct acpi_object_list input;
620 union acpi_object params[1];
621 struct guid_block *gblock;
622 struct wmi_block *wblock;
626 input.pointer = params;
627 params[0].type = ACPI_TYPE_INTEGER;
628 params[0].integer.value = event;
630 list_for_each(p, &wmi_blocks.list) {
631 wblock = list_entry(p, struct wmi_block, list);
632 gblock = &wblock->gblock;
634 if ((gblock->flags & ACPI_WMI_EVENT) &&
635 (gblock->notify_id == event))
636 return acpi_evaluate_object(wblock->handle, "_WED",
642 EXPORT_SYMBOL_GPL(wmi_get_event_data);
645 * wmi_has_guid - Check if a GUID is available
646 * @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba
648 * Check if a given GUID is defined by _WDG
650 bool wmi_has_guid(const char *guid_string)
652 return find_guid(guid_string, NULL);
654 EXPORT_SYMBOL_GPL(wmi_has_guid);
659 static ssize_t show_modalias(struct device *dev, struct device_attribute *attr,
662 char guid_string[37];
663 struct wmi_block *wblock;
665 wblock = dev_get_drvdata(dev);
669 wmi_gtoa(wblock->gblock.guid, guid_string);
671 return sprintf(buf, "wmi:%s\n", guid_string);
673 static DEVICE_ATTR(modalias, S_IRUGO, show_modalias, NULL);
675 static int wmi_dev_uevent(struct device *dev, struct kobj_uevent_env *env)
677 char guid_string[37];
679 struct wmi_block *wblock;
681 if (add_uevent_var(env, "MODALIAS="))
684 wblock = dev_get_drvdata(dev);
688 wmi_gtoa(wblock->gblock.guid, guid_string);
690 strcpy(&env->buf[env->buflen - 1], "wmi:");
691 memcpy(&env->buf[env->buflen - 1 + 4], guid_string, 36);
697 static void wmi_dev_free(struct device *dev)
702 static struct class wmi_class = {
704 .dev_release = wmi_dev_free,
705 .dev_uevent = wmi_dev_uevent,
708 static int wmi_create_devs(void)
711 char guid_string[37];
712 struct guid_block *gblock;
713 struct wmi_block *wblock;
715 struct device *guid_dev;
717 /* Create devices for all the GUIDs */
718 list_for_each(p, &wmi_blocks.list) {
719 wblock = list_entry(p, struct wmi_block, list);
721 guid_dev = kzalloc(sizeof(struct device), GFP_KERNEL);
725 wblock->dev = guid_dev;
727 guid_dev->class = &wmi_class;
728 dev_set_drvdata(guid_dev, wblock);
730 gblock = &wblock->gblock;
732 wmi_gtoa(gblock->guid, guid_string);
733 dev_set_name(guid_dev, guid_string);
735 result = device_register(guid_dev);
739 result = device_create_file(guid_dev, &dev_attr_modalias);
747 static void wmi_remove_devs(void)
749 struct guid_block *gblock;
750 struct wmi_block *wblock;
752 struct device *guid_dev;
754 /* Delete devices for all the GUIDs */
755 list_for_each(p, &wmi_blocks.list) {
756 wblock = list_entry(p, struct wmi_block, list);
758 guid_dev = wblock->dev;
759 gblock = &wblock->gblock;
761 device_remove_file(guid_dev, &dev_attr_modalias);
763 device_unregister(guid_dev);
767 static void wmi_class_exit(void)
770 class_unregister(&wmi_class);
773 static int wmi_class_init(void)
777 ret = class_register(&wmi_class);
781 ret = wmi_create_devs();
788 static bool guid_already_parsed(const char *guid_string)
790 struct guid_block *gblock;
791 struct wmi_block *wblock;
794 list_for_each(p, &wmi_blocks.list) {
795 wblock = list_entry(p, struct wmi_block, list);
796 gblock = &wblock->gblock;
798 if (strncmp(gblock->guid, guid_string, 16) == 0)
805 * Parse the _WDG method for the GUID data blocks
807 static __init acpi_status parse_wdg(acpi_handle handle)
809 struct acpi_buffer out = {ACPI_ALLOCATE_BUFFER, NULL};
810 union acpi_object *obj;
811 struct guid_block *gblock;
812 struct wmi_block *wblock;
813 char guid_string[37];
817 status = acpi_evaluate_object(handle, "_WDG", NULL, &out);
819 if (ACPI_FAILURE(status))
822 obj = (union acpi_object *) out.pointer;
824 if (obj->type != ACPI_TYPE_BUFFER)
827 total = obj->buffer.length / sizeof(struct guid_block);
829 gblock = kmemdup(obj->buffer.pointer, obj->buffer.length, GFP_KERNEL);
833 for (i = 0; i < total; i++) {
835 Some WMI devices, like those for nVidia hooks, have a
836 duplicate GUID. It's not clear what we should do in this
837 case yet, so for now, we'll just ignore the duplicate.
838 Anyone who wants to add support for that device can come
839 up with a better workaround for the mess then.
841 if (guid_already_parsed(gblock[i].guid) == true) {
842 wmi_gtoa(gblock[i].guid, guid_string);
843 printk(KERN_INFO PREFIX "Skipping duplicate GUID %s\n",
848 wmi_dump_wdg(&gblock[i]);
850 wblock = kzalloc(sizeof(struct wmi_block), GFP_KERNEL);
854 wblock->gblock = gblock[i];
855 wblock->handle = handle;
857 wblock->handler = wmi_notify_debug;
858 status = wmi_method_enable(wblock, 1);
860 list_add_tail(&wblock->list, &wmi_blocks.list);
870 * WMI can have EmbeddedControl access regions. In which case, we just want to
871 * hand these off to the EC driver.
874 acpi_wmi_ec_space_handler(u32 function, acpi_physical_address address,
875 u32 bits, u64 *value,
876 void *handler_context, void *region_context)
878 int result = 0, i = 0;
881 if ((address > 0xFF) || !value)
882 return AE_BAD_PARAMETER;
884 if (function != ACPI_READ && function != ACPI_WRITE)
885 return AE_BAD_PARAMETER;
888 return AE_BAD_PARAMETER;
890 if (function == ACPI_READ) {
891 result = ec_read(address, &temp);
892 (*value) |= ((u64)temp) << i;
894 temp = 0xff & ((*value) >> i);
895 result = ec_write(address, temp);
900 return AE_BAD_PARAMETER;
913 static void acpi_wmi_notify(struct acpi_device *device, u32 event)
915 struct guid_block *block;
916 struct wmi_block *wblock;
918 char guid_string[37];
920 list_for_each(p, &wmi_blocks.list) {
921 wblock = list_entry(p, struct wmi_block, list);
922 block = &wblock->gblock;
924 if ((block->flags & ACPI_WMI_EVENT) &&
925 (block->notify_id == event)) {
927 wblock->handler(event, wblock->handler_data);
929 wmi_gtoa(wblock->gblock.guid, guid_string);
930 printk(KERN_INFO PREFIX "DEBUG Event GUID:"
931 " %s\n", guid_string);
934 acpi_bus_generate_netlink_event(
935 device->pnp.device_class, dev_name(&device->dev),
942 static int acpi_wmi_remove(struct acpi_device *device, int type)
944 acpi_remove_address_space_handler(device->handle,
945 ACPI_ADR_SPACE_EC, &acpi_wmi_ec_space_handler);
950 static int __init acpi_wmi_add(struct acpi_device *device)
955 status = acpi_install_address_space_handler(device->handle,
957 &acpi_wmi_ec_space_handler,
959 if (ACPI_FAILURE(status))
962 status = parse_wdg(device->handle);
963 if (ACPI_FAILURE(status)) {
964 printk(KERN_ERR PREFIX "Error installing EC region handler\n");
971 static int __init acpi_wmi_init(void)
975 INIT_LIST_HEAD(&wmi_blocks.list);
980 result = acpi_bus_register_driver(&acpi_wmi_driver);
983 printk(KERN_INFO PREFIX "Error loading mapper\n");
987 result = wmi_class_init();
989 acpi_bus_unregister_driver(&acpi_wmi_driver);
993 printk(KERN_INFO PREFIX "Mapper loaded\n");
998 static void __exit acpi_wmi_exit(void)
1000 struct list_head *p, *tmp;
1001 struct wmi_block *wblock;
1005 acpi_bus_unregister_driver(&acpi_wmi_driver);
1007 list_for_each_safe(p, tmp, &wmi_blocks.list) {
1008 wblock = list_entry(p, struct wmi_block, list);
1014 printk(KERN_INFO PREFIX "Mapper unloaded\n");
1017 subsys_initcall(acpi_wmi_init);
1018 module_exit(acpi_wmi_exit);