Merge commit 'v2.6.34-rc6' into x86/cpu
[pandora-kernel.git] / drivers / platform / x86 / wmi.c
1 /*
2  *  ACPI-WMI mapping driver
3  *
4  *  Copyright (C) 2007-2008 Carlos Corbacho <carlos@strangeworlds.co.uk>
5  *
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>
10  *
11  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
12  *
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.
17  *
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.
22  *
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.
26  *
27  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
28  */
29
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>
39
40 ACPI_MODULE_NAME("wmi");
41 MODULE_AUTHOR("Carlos Corbacho");
42 MODULE_DESCRIPTION("ACPI-WMI Mapping Driver");
43 MODULE_LICENSE("GPL");
44
45 #define ACPI_WMI_CLASS "wmi"
46
47 #define PREFIX "ACPI: WMI: "
48
49 static DEFINE_MUTEX(wmi_data_lock);
50
51 struct guid_block {
52         char guid[16];
53         union {
54                 char object_id[2];
55                 struct {
56                         unsigned char notify_id;
57                         unsigned char reserved;
58                 };
59         };
60         u8 instance_count;
61         u8 flags;
62 };
63
64 struct wmi_block {
65         struct list_head list;
66         struct guid_block gblock;
67         acpi_handle handle;
68         wmi_notify_handler handler;
69         void *handler_data;
70         struct device *dev;
71 };
72
73 static struct wmi_block wmi_blocks;
74
75 /*
76  * If the GUID data block is marked as expensive, we must enable and
77  * explicitily disable data collection.
78  */
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 */
83
84 static int acpi_wmi_remove(struct acpi_device *device, int type);
85 static int acpi_wmi_add(struct acpi_device *device);
86 static void acpi_wmi_notify(struct acpi_device *device, u32 event);
87
88 static const struct acpi_device_id wmi_device_ids[] = {
89         {"PNP0C14", 0},
90         {"pnp0c14", 0},
91         {"", 0},
92 };
93 MODULE_DEVICE_TABLE(acpi, wmi_device_ids);
94
95 static struct acpi_driver acpi_wmi_driver = {
96         .name = "wmi",
97         .class = ACPI_WMI_CLASS,
98         .ids = wmi_device_ids,
99         .ops = {
100                 .add = acpi_wmi_add,
101                 .remove = acpi_wmi_remove,
102                 .notify = acpi_wmi_notify,
103                 },
104 };
105
106 /*
107  * GUID parsing functions
108  */
109
110 /**
111  * wmi_parse_hexbyte - Convert a ASCII hex number to a byte
112  * @src:  Pointer to at least 2 characters to convert.
113  *
114  * Convert a two character ASCII hex string to a number.
115  *
116  * Return:  0-255  Success, the byte was parsed correctly
117  *          -1     Error, an invalid character was supplied
118  */
119 static int wmi_parse_hexbyte(const u8 *src)
120 {
121         unsigned int x; /* For correct wrapping */
122         int h;
123
124         /* high part */
125         x = src[0];
126         if (x - '0' <= '9' - '0') {
127                 h = x - '0';
128         } else if (x - 'a' <= 'f' - 'a') {
129                 h = x - 'a' + 10;
130         } else if (x - 'A' <= 'F' - 'A') {
131                 h = x - 'A' + 10;
132         } else {
133                 return -1;
134         }
135         h <<= 4;
136
137         /* low part */
138         x = src[1];
139         if (x - '0' <= '9' - '0')
140                 return h | (x - '0');
141         if (x - 'a' <= 'f' - 'a')
142                 return h | (x - 'a' + 10);
143         if (x - 'A' <= 'F' - 'A')
144                 return h | (x - 'A' + 10);
145         return -1;
146 }
147
148 /**
149  * wmi_swap_bytes - Rearrange GUID bytes to match GUID binary
150  * @src:   Memory block holding binary GUID (16 bytes)
151  * @dest:  Memory block to hold byte swapped binary GUID (16 bytes)
152  *
153  * Byte swap a binary GUID to match it's real GUID value
154  */
155 static void wmi_swap_bytes(u8 *src, u8 *dest)
156 {
157         int i;
158
159         for (i = 0; i <= 3; i++)
160                 memcpy(dest + i, src + (3 - i), 1);
161
162         for (i = 0; i <= 1; i++)
163                 memcpy(dest + 4 + i, src + (5 - i), 1);
164
165         for (i = 0; i <= 1; i++)
166                 memcpy(dest + 6 + i, src + (7 - i), 1);
167
168         memcpy(dest + 8, src + 8, 8);
169 }
170
171 /**
172  * wmi_parse_guid - Convert GUID from ASCII to binary
173  * @src:   36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba
174  * @dest:  Memory block to hold binary GUID (16 bytes)
175  *
176  * N.B. The GUID need not be NULL terminated.
177  *
178  * Return:  'true'   @dest contains binary GUID
179  *          'false'  @dest contents are undefined
180  */
181 static bool wmi_parse_guid(const u8 *src, u8 *dest)
182 {
183         static const int size[] = { 4, 2, 2, 2, 6 };
184         int i, j, v;
185
186         if (src[8]  != '-' || src[13] != '-' ||
187                 src[18] != '-' || src[23] != '-')
188                 return false;
189
190         for (j = 0; j < 5; j++, src++) {
191                 for (i = 0; i < size[j]; i++, src += 2, *dest++ = v) {
192                         v = wmi_parse_hexbyte(src);
193                         if (v < 0)
194                                 return false;
195                 }
196         }
197
198         return true;
199 }
200
201 /*
202  * Convert a raw GUID to the ACII string representation
203  */
204 static int wmi_gtoa(const char *in, char *out)
205 {
206         int i;
207
208         for (i = 3; i >= 0; i--)
209                 out += sprintf(out, "%02X", in[i] & 0xFF);
210
211         out += sprintf(out, "-");
212         out += sprintf(out, "%02X", in[5] & 0xFF);
213         out += sprintf(out, "%02X", in[4] & 0xFF);
214         out += sprintf(out, "-");
215         out += sprintf(out, "%02X", in[7] & 0xFF);
216         out += sprintf(out, "%02X", in[6] & 0xFF);
217         out += sprintf(out, "-");
218         out += sprintf(out, "%02X", in[8] & 0xFF);
219         out += sprintf(out, "%02X", in[9] & 0xFF);
220         out += sprintf(out, "-");
221
222         for (i = 10; i <= 15; i++)
223                 out += sprintf(out, "%02X", in[i] & 0xFF);
224
225         out = '\0';
226         return 0;
227 }
228
229 static bool find_guid(const char *guid_string, struct wmi_block **out)
230 {
231         char tmp[16], guid_input[16];
232         struct wmi_block *wblock;
233         struct guid_block *block;
234         struct list_head *p;
235
236         wmi_parse_guid(guid_string, tmp);
237         wmi_swap_bytes(tmp, guid_input);
238
239         list_for_each(p, &wmi_blocks.list) {
240                 wblock = list_entry(p, struct wmi_block, list);
241                 block = &wblock->gblock;
242
243                 if (memcmp(block->guid, guid_input, 16) == 0) {
244                         if (out)
245                                 *out = wblock;
246                         return 1;
247                 }
248         }
249         return 0;
250 }
251
252 static acpi_status wmi_method_enable(struct wmi_block *wblock, int enable)
253 {
254         struct guid_block *block = NULL;
255         char method[5];
256         struct acpi_object_list input;
257         union acpi_object params[1];
258         acpi_status status;
259         acpi_handle handle;
260
261         block = &wblock->gblock;
262         handle = wblock->handle;
263
264         if (!block)
265                 return AE_NOT_EXIST;
266
267         input.count = 1;
268         input.pointer = params;
269         params[0].type = ACPI_TYPE_INTEGER;
270         params[0].integer.value = enable;
271
272         snprintf(method, 5, "WE%02X", block->notify_id);
273         status = acpi_evaluate_object(handle, method, &input, NULL);
274
275         if (status != AE_OK && status != AE_NOT_FOUND)
276                 return status;
277         else
278                 return AE_OK;
279 }
280
281 /*
282  * Exported WMI functions
283  */
284 /**
285  * wmi_evaluate_method - Evaluate a WMI method
286  * @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba
287  * @instance: Instance index
288  * @method_id: Method ID to call
289  * &in: Buffer containing input for the method call
290  * &out: Empty buffer to return the method results
291  *
292  * Call an ACPI-WMI method
293  */
294 acpi_status wmi_evaluate_method(const char *guid_string, u8 instance,
295 u32 method_id, const struct acpi_buffer *in, struct acpi_buffer *out)
296 {
297         struct guid_block *block = NULL;
298         struct wmi_block *wblock = NULL;
299         acpi_handle handle;
300         acpi_status status;
301         struct acpi_object_list input;
302         union acpi_object params[3];
303         char method[5] = "WM";
304
305         if (!find_guid(guid_string, &wblock))
306                 return AE_ERROR;
307
308         block = &wblock->gblock;
309         handle = wblock->handle;
310
311         if (!(block->flags & ACPI_WMI_METHOD))
312                 return AE_BAD_DATA;
313
314         if (block->instance_count < instance)
315                 return AE_BAD_PARAMETER;
316
317         input.count = 2;
318         input.pointer = params;
319         params[0].type = ACPI_TYPE_INTEGER;
320         params[0].integer.value = instance;
321         params[1].type = ACPI_TYPE_INTEGER;
322         params[1].integer.value = method_id;
323
324         if (in) {
325                 input.count = 3;
326
327                 if (block->flags & ACPI_WMI_STRING) {
328                         params[2].type = ACPI_TYPE_STRING;
329                 } else {
330                         params[2].type = ACPI_TYPE_BUFFER;
331                 }
332                 params[2].buffer.length = in->length;
333                 params[2].buffer.pointer = in->pointer;
334         }
335
336         strncat(method, block->object_id, 2);
337
338         status = acpi_evaluate_object(handle, method, &input, out);
339
340         return status;
341 }
342 EXPORT_SYMBOL_GPL(wmi_evaluate_method);
343
344 /**
345  * wmi_query_block - Return contents of a WMI block
346  * @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba
347  * @instance: Instance index
348  * &out: Empty buffer to return the contents of the data block to
349  *
350  * Return the contents of an ACPI-WMI data block to a buffer
351  */
352 acpi_status wmi_query_block(const char *guid_string, u8 instance,
353 struct acpi_buffer *out)
354 {
355         struct guid_block *block = NULL;
356         struct wmi_block *wblock = NULL;
357         acpi_handle handle, wc_handle;
358         acpi_status status, wc_status = AE_ERROR;
359         struct acpi_object_list input, wc_input;
360         union acpi_object wc_params[1], wq_params[1];
361         char method[5];
362         char wc_method[5] = "WC";
363
364         if (!guid_string || !out)
365                 return AE_BAD_PARAMETER;
366
367         if (!find_guid(guid_string, &wblock))
368                 return AE_ERROR;
369
370         block = &wblock->gblock;
371         handle = wblock->handle;
372
373         if (block->instance_count < instance)
374                 return AE_BAD_PARAMETER;
375
376         /* Check GUID is a data block */
377         if (block->flags & (ACPI_WMI_EVENT | ACPI_WMI_METHOD))
378                 return AE_ERROR;
379
380         input.count = 1;
381         input.pointer = wq_params;
382         wq_params[0].type = ACPI_TYPE_INTEGER;
383         wq_params[0].integer.value = instance;
384
385         /*
386          * If ACPI_WMI_EXPENSIVE, call the relevant WCxx method first to
387          * enable collection.
388          */
389         if (block->flags & ACPI_WMI_EXPENSIVE) {
390                 wc_input.count = 1;
391                 wc_input.pointer = wc_params;
392                 wc_params[0].type = ACPI_TYPE_INTEGER;
393                 wc_params[0].integer.value = 1;
394
395                 strncat(wc_method, block->object_id, 2);
396
397                 /*
398                  * Some GUIDs break the specification by declaring themselves
399                  * expensive, but have no corresponding WCxx method. So we
400                  * should not fail if this happens.
401                  */
402                 wc_status = acpi_get_handle(handle, wc_method, &wc_handle);
403                 if (ACPI_SUCCESS(wc_status))
404                         wc_status = acpi_evaluate_object(handle, wc_method,
405                                 &wc_input, NULL);
406         }
407
408         strcpy(method, "WQ");
409         strncat(method, block->object_id, 2);
410
411         status = acpi_evaluate_object(handle, method, &input, out);
412
413         /*
414          * If ACPI_WMI_EXPENSIVE, call the relevant WCxx method, even if
415          * the WQxx method failed - we should disable collection anyway.
416          */
417         if ((block->flags & ACPI_WMI_EXPENSIVE) && ACPI_SUCCESS(wc_status)) {
418                 wc_params[0].integer.value = 0;
419                 status = acpi_evaluate_object(handle,
420                 wc_method, &wc_input, NULL);
421         }
422
423         return status;
424 }
425 EXPORT_SYMBOL_GPL(wmi_query_block);
426
427 /**
428  * wmi_set_block - Write to a WMI block
429  * @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba
430  * @instance: Instance index
431  * &in: Buffer containing new values for the data block
432  *
433  * Write the contents of the input buffer to an ACPI-WMI data block
434  */
435 acpi_status wmi_set_block(const char *guid_string, u8 instance,
436 const struct acpi_buffer *in)
437 {
438         struct guid_block *block = NULL;
439         struct wmi_block *wblock = NULL;
440         acpi_handle handle;
441         struct acpi_object_list input;
442         union acpi_object params[2];
443         char method[5] = "WS";
444
445         if (!guid_string || !in)
446                 return AE_BAD_DATA;
447
448         if (!find_guid(guid_string, &wblock))
449                 return AE_ERROR;
450
451         block = &wblock->gblock;
452         handle = wblock->handle;
453
454         if (block->instance_count < instance)
455                 return AE_BAD_PARAMETER;
456
457         /* Check GUID is a data block */
458         if (block->flags & (ACPI_WMI_EVENT | ACPI_WMI_METHOD))
459                 return AE_ERROR;
460
461         input.count = 2;
462         input.pointer = params;
463         params[0].type = ACPI_TYPE_INTEGER;
464         params[0].integer.value = instance;
465
466         if (block->flags & ACPI_WMI_STRING) {
467                 params[1].type = ACPI_TYPE_STRING;
468         } else {
469                 params[1].type = ACPI_TYPE_BUFFER;
470         }
471         params[1].buffer.length = in->length;
472         params[1].buffer.pointer = in->pointer;
473
474         strncat(method, block->object_id, 2);
475
476         return acpi_evaluate_object(handle, method, &input, NULL);
477 }
478 EXPORT_SYMBOL_GPL(wmi_set_block);
479
480 /**
481  * wmi_install_notify_handler - Register handler for WMI events
482  * @handler: Function to handle notifications
483  * @data: Data to be returned to handler when event is fired
484  *
485  * Register a handler for events sent to the ACPI-WMI mapper device.
486  */
487 acpi_status wmi_install_notify_handler(const char *guid,
488 wmi_notify_handler handler, void *data)
489 {
490         struct wmi_block *block;
491         acpi_status status;
492
493         if (!guid || !handler)
494                 return AE_BAD_PARAMETER;
495
496         if (!find_guid(guid, &block))
497                 return AE_NOT_EXIST;
498
499         if (block->handler)
500                 return AE_ALREADY_ACQUIRED;
501
502         block->handler = handler;
503         block->handler_data = data;
504
505         status = wmi_method_enable(block, 1);
506
507         return status;
508 }
509 EXPORT_SYMBOL_GPL(wmi_install_notify_handler);
510
511 /**
512  * wmi_uninstall_notify_handler - Unregister handler for WMI events
513  *
514  * Unregister handler for events sent to the ACPI-WMI mapper device.
515  */
516 acpi_status wmi_remove_notify_handler(const char *guid)
517 {
518         struct wmi_block *block;
519         acpi_status status;
520
521         if (!guid)
522                 return AE_BAD_PARAMETER;
523
524         if (!find_guid(guid, &block))
525                 return AE_NOT_EXIST;
526
527         if (!block->handler)
528                 return AE_NULL_ENTRY;
529
530         status = wmi_method_enable(block, 0);
531
532         block->handler = NULL;
533         block->handler_data = NULL;
534
535         return status;
536 }
537 EXPORT_SYMBOL_GPL(wmi_remove_notify_handler);
538
539 /**
540  * wmi_get_event_data - Get WMI data associated with an event
541  *
542  * @event: Event to find
543  * @out: Buffer to hold event data. out->pointer should be freed with kfree()
544  *
545  * Returns extra data associated with an event in WMI.
546  */
547 acpi_status wmi_get_event_data(u32 event, struct acpi_buffer *out)
548 {
549         struct acpi_object_list input;
550         union acpi_object params[1];
551         struct guid_block *gblock;
552         struct wmi_block *wblock;
553         struct list_head *p;
554
555         input.count = 1;
556         input.pointer = params;
557         params[0].type = ACPI_TYPE_INTEGER;
558         params[0].integer.value = event;
559
560         list_for_each(p, &wmi_blocks.list) {
561                 wblock = list_entry(p, struct wmi_block, list);
562                 gblock = &wblock->gblock;
563
564                 if ((gblock->flags & ACPI_WMI_EVENT) &&
565                         (gblock->notify_id == event))
566                         return acpi_evaluate_object(wblock->handle, "_WED",
567                                 &input, out);
568         }
569
570         return AE_NOT_FOUND;
571 }
572 EXPORT_SYMBOL_GPL(wmi_get_event_data);
573
574 /**
575  * wmi_has_guid - Check if a GUID is available
576  * @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba
577  *
578  * Check if a given GUID is defined by _WDG
579  */
580 bool wmi_has_guid(const char *guid_string)
581 {
582         return find_guid(guid_string, NULL);
583 }
584 EXPORT_SYMBOL_GPL(wmi_has_guid);
585
586 /*
587  * sysfs interface
588  */
589 static ssize_t show_modalias(struct device *dev, struct device_attribute *attr,
590                              char *buf)
591 {
592         char guid_string[37];
593         struct wmi_block *wblock;
594
595         wblock = dev_get_drvdata(dev);
596         if (!wblock)
597                 return -ENOMEM;
598
599         wmi_gtoa(wblock->gblock.guid, guid_string);
600
601         return sprintf(buf, "wmi:%s\n", guid_string);
602 }
603 static DEVICE_ATTR(modalias, S_IRUGO, show_modalias, NULL);
604
605 static int wmi_dev_uevent(struct device *dev, struct kobj_uevent_env *env)
606 {
607         char guid_string[37];
608
609         struct wmi_block *wblock;
610
611         if (add_uevent_var(env, "MODALIAS="))
612                 return -ENOMEM;
613
614         wblock = dev_get_drvdata(dev);
615         if (!wblock)
616                 return -ENOMEM;
617
618         wmi_gtoa(wblock->gblock.guid, guid_string);
619
620         strcpy(&env->buf[env->buflen - 1], "wmi:");
621         memcpy(&env->buf[env->buflen - 1 + 4], guid_string, 36);
622         env->buflen += 40;
623
624         return 0;
625 }
626
627 static void wmi_dev_free(struct device *dev)
628 {
629         kfree(dev);
630 }
631
632 static struct class wmi_class = {
633         .name = "wmi",
634         .dev_release = wmi_dev_free,
635         .dev_uevent = wmi_dev_uevent,
636 };
637
638 static int wmi_create_devs(void)
639 {
640         int result;
641         char guid_string[37];
642         struct guid_block *gblock;
643         struct wmi_block *wblock;
644         struct list_head *p;
645         struct device *guid_dev;
646
647         /* Create devices for all the GUIDs */
648         list_for_each(p, &wmi_blocks.list) {
649                 wblock = list_entry(p, struct wmi_block, list);
650
651                 guid_dev = kzalloc(sizeof(struct device), GFP_KERNEL);
652                 if (!guid_dev)
653                         return -ENOMEM;
654
655                 wblock->dev = guid_dev;
656
657                 guid_dev->class = &wmi_class;
658                 dev_set_drvdata(guid_dev, wblock);
659
660                 gblock = &wblock->gblock;
661
662                 wmi_gtoa(gblock->guid, guid_string);
663                 dev_set_name(guid_dev, guid_string);
664
665                 result = device_register(guid_dev);
666                 if (result)
667                         return result;
668
669                 result = device_create_file(guid_dev, &dev_attr_modalias);
670                 if (result)
671                         return result;
672         }
673
674         return 0;
675 }
676
677 static void wmi_remove_devs(void)
678 {
679         struct guid_block *gblock;
680         struct wmi_block *wblock;
681         struct list_head *p;
682         struct device *guid_dev;
683
684         /* Delete devices for all the GUIDs */
685         list_for_each(p, &wmi_blocks.list) {
686                 wblock = list_entry(p, struct wmi_block, list);
687
688                 guid_dev = wblock->dev;
689                 gblock = &wblock->gblock;
690
691                 device_remove_file(guid_dev, &dev_attr_modalias);
692
693                 device_unregister(guid_dev);
694         }
695 }
696
697 static void wmi_class_exit(void)
698 {
699         wmi_remove_devs();
700         class_unregister(&wmi_class);
701 }
702
703 static int wmi_class_init(void)
704 {
705         int ret;
706
707         ret = class_register(&wmi_class);
708         if (ret)
709                 return ret;
710
711         ret = wmi_create_devs();
712         if (ret)
713                 wmi_class_exit();
714
715         return ret;
716 }
717
718 static bool guid_already_parsed(const char *guid_string)
719 {
720         struct guid_block *gblock;
721         struct wmi_block *wblock;
722         struct list_head *p;
723
724         list_for_each(p, &wmi_blocks.list) {
725                 wblock = list_entry(p, struct wmi_block, list);
726                 gblock = &wblock->gblock;
727
728                 if (strncmp(gblock->guid, guid_string, 16) == 0)
729                         return true;
730         }
731         return false;
732 }
733
734 /*
735  * Parse the _WDG method for the GUID data blocks
736  */
737 static __init acpi_status parse_wdg(acpi_handle handle)
738 {
739         struct acpi_buffer out = {ACPI_ALLOCATE_BUFFER, NULL};
740         union acpi_object *obj;
741         struct guid_block *gblock;
742         struct wmi_block *wblock;
743         char guid_string[37];
744         acpi_status status;
745         u32 i, total;
746
747         status = acpi_evaluate_object(handle, "_WDG", NULL, &out);
748
749         if (ACPI_FAILURE(status))
750                 return status;
751
752         obj = (union acpi_object *) out.pointer;
753
754         if (obj->type != ACPI_TYPE_BUFFER)
755                 return AE_ERROR;
756
757         total = obj->buffer.length / sizeof(struct guid_block);
758
759         gblock = kzalloc(obj->buffer.length, GFP_KERNEL);
760         if (!gblock)
761                 return AE_NO_MEMORY;
762
763         memcpy(gblock, obj->buffer.pointer, obj->buffer.length);
764
765         for (i = 0; i < total; i++) {
766                 /*
767                   Some WMI devices, like those for nVidia hooks, have a
768                   duplicate GUID. It's not clear what we should do in this
769                   case yet, so for now, we'll just ignore the duplicate.
770                   Anyone who wants to add support for that device can come
771                   up with a better workaround for the mess then.
772                 */
773                 if (guid_already_parsed(gblock[i].guid) == true) {
774                         wmi_gtoa(gblock[i].guid, guid_string);
775                         printk(KERN_INFO PREFIX "Skipping duplicate GUID %s\n",
776                                 guid_string);
777                         continue;
778                 }
779                 wblock = kzalloc(sizeof(struct wmi_block), GFP_KERNEL);
780                 if (!wblock)
781                         return AE_NO_MEMORY;
782
783                 wblock->gblock = gblock[i];
784                 wblock->handle = handle;
785                 list_add_tail(&wblock->list, &wmi_blocks.list);
786         }
787
788         kfree(out.pointer);
789         kfree(gblock);
790
791         return status;
792 }
793
794 /*
795  * WMI can have EmbeddedControl access regions. In which case, we just want to
796  * hand these off to the EC driver.
797  */
798 static acpi_status
799 acpi_wmi_ec_space_handler(u32 function, acpi_physical_address address,
800                       u32 bits, u64 *value,
801                       void *handler_context, void *region_context)
802 {
803         int result = 0, i = 0;
804         u8 temp = 0;
805
806         if ((address > 0xFF) || !value)
807                 return AE_BAD_PARAMETER;
808
809         if (function != ACPI_READ && function != ACPI_WRITE)
810                 return AE_BAD_PARAMETER;
811
812         if (bits != 8)
813                 return AE_BAD_PARAMETER;
814
815         if (function == ACPI_READ) {
816                 result = ec_read(address, &temp);
817                 (*value) |= ((u64)temp) << i;
818         } else {
819                 temp = 0xff & ((*value) >> i);
820                 result = ec_write(address, temp);
821         }
822
823         switch (result) {
824         case -EINVAL:
825                 return AE_BAD_PARAMETER;
826                 break;
827         case -ENODEV:
828                 return AE_NOT_FOUND;
829                 break;
830         case -ETIME:
831                 return AE_TIME;
832                 break;
833         default:
834                 return AE_OK;
835         }
836 }
837
838 static void acpi_wmi_notify(struct acpi_device *device, u32 event)
839 {
840         struct guid_block *block;
841         struct wmi_block *wblock;
842         struct list_head *p;
843
844         list_for_each(p, &wmi_blocks.list) {
845                 wblock = list_entry(p, struct wmi_block, list);
846                 block = &wblock->gblock;
847
848                 if ((block->flags & ACPI_WMI_EVENT) &&
849                         (block->notify_id == event)) {
850                         if (wblock->handler)
851                                 wblock->handler(event, wblock->handler_data);
852
853                         acpi_bus_generate_netlink_event(
854                                 device->pnp.device_class, dev_name(&device->dev),
855                                 event, 0);
856                         break;
857                 }
858         }
859 }
860
861 static int acpi_wmi_remove(struct acpi_device *device, int type)
862 {
863         acpi_remove_address_space_handler(device->handle,
864                                 ACPI_ADR_SPACE_EC, &acpi_wmi_ec_space_handler);
865
866         return 0;
867 }
868
869 static int __init acpi_wmi_add(struct acpi_device *device)
870 {
871         acpi_status status;
872         int result = 0;
873
874         status = acpi_install_address_space_handler(device->handle,
875                                                     ACPI_ADR_SPACE_EC,
876                                                     &acpi_wmi_ec_space_handler,
877                                                     NULL, NULL);
878         if (ACPI_FAILURE(status))
879                 return -ENODEV;
880
881         status = parse_wdg(device->handle);
882         if (ACPI_FAILURE(status)) {
883                 printk(KERN_ERR PREFIX "Error installing EC region handler\n");
884                 return -ENODEV;
885         }
886
887         return result;
888 }
889
890 static int __init acpi_wmi_init(void)
891 {
892         int result;
893
894         INIT_LIST_HEAD(&wmi_blocks.list);
895
896         if (acpi_disabled)
897                 return -ENODEV;
898
899         result = acpi_bus_register_driver(&acpi_wmi_driver);
900
901         if (result < 0) {
902                 printk(KERN_INFO PREFIX "Error loading mapper\n");
903                 return -ENODEV;
904         }
905
906         result = wmi_class_init();
907         if (result) {
908                 acpi_bus_unregister_driver(&acpi_wmi_driver);
909                 return result;
910         }
911
912         printk(KERN_INFO PREFIX "Mapper loaded\n");
913
914         return result;
915 }
916
917 static void __exit acpi_wmi_exit(void)
918 {
919         struct list_head *p, *tmp;
920         struct wmi_block *wblock;
921
922         wmi_class_exit();
923
924         acpi_bus_unregister_driver(&acpi_wmi_driver);
925
926         list_for_each_safe(p, tmp, &wmi_blocks.list) {
927                 wblock = list_entry(p, struct wmi_block, list);
928
929                 list_del(p);
930                 kfree(wblock);
931         }
932
933         printk(KERN_INFO PREFIX "Mapper unloaded\n");
934 }
935
936 subsys_initcall(acpi_wmi_init);
937 module_exit(acpi_wmi_exit);