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