Merge git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-2.6-fixes
[sfrench/cifs-2.6.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 debug_event;
85 module_param(debug_event, bool, 0444);
86 MODULE_PARM_DESC(debug_event,
87                  "Log WMI Events [0/1]");
88
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]");
93
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);
97
98 static const struct acpi_device_id wmi_device_ids[] = {
99         {"PNP0C14", 0},
100         {"pnp0c14", 0},
101         {"", 0},
102 };
103 MODULE_DEVICE_TABLE(acpi, wmi_device_ids);
104
105 static struct acpi_driver acpi_wmi_driver = {
106         .name = "wmi",
107         .class = ACPI_WMI_CLASS,
108         .ids = wmi_device_ids,
109         .ops = {
110                 .add = acpi_wmi_add,
111                 .remove = acpi_wmi_remove,
112                 .notify = acpi_wmi_notify,
113                 },
114 };
115
116 /*
117  * GUID parsing functions
118  */
119
120 /**
121  * wmi_parse_hexbyte - Convert a ASCII hex number to a byte
122  * @src:  Pointer to at least 2 characters to convert.
123  *
124  * Convert a two character ASCII hex string to a number.
125  *
126  * Return:  0-255  Success, the byte was parsed correctly
127  *          -1     Error, an invalid character was supplied
128  */
129 static int wmi_parse_hexbyte(const u8 *src)
130 {
131         unsigned int x; /* For correct wrapping */
132         int h;
133
134         /* high part */
135         x = src[0];
136         if (x - '0' <= '9' - '0') {
137                 h = x - '0';
138         } else if (x - 'a' <= 'f' - 'a') {
139                 h = x - 'a' + 10;
140         } else if (x - 'A' <= 'F' - 'A') {
141                 h = x - 'A' + 10;
142         } else {
143                 return -1;
144         }
145         h <<= 4;
146
147         /* low part */
148         x = src[1];
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);
155         return -1;
156 }
157
158 /**
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)
162  *
163  * Byte swap a binary GUID to match it's real GUID value
164  */
165 static void wmi_swap_bytes(u8 *src, u8 *dest)
166 {
167         int i;
168
169         for (i = 0; i <= 3; i++)
170                 memcpy(dest + i, src + (3 - i), 1);
171
172         for (i = 0; i <= 1; i++)
173                 memcpy(dest + 4 + i, src + (5 - i), 1);
174
175         for (i = 0; i <= 1; i++)
176                 memcpy(dest + 6 + i, src + (7 - i), 1);
177
178         memcpy(dest + 8, src + 8, 8);
179 }
180
181 /**
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)
185  *
186  * N.B. The GUID need not be NULL terminated.
187  *
188  * Return:  'true'   @dest contains binary GUID
189  *          'false'  @dest contents are undefined
190  */
191 static bool wmi_parse_guid(const u8 *src, u8 *dest)
192 {
193         static const int size[] = { 4, 2, 2, 2, 6 };
194         int i, j, v;
195
196         if (src[8]  != '-' || src[13] != '-' ||
197                 src[18] != '-' || src[23] != '-')
198                 return false;
199
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);
203                         if (v < 0)
204                                 return false;
205                 }
206         }
207
208         return true;
209 }
210
211 /*
212  * Convert a raw GUID to the ACII string representation
213  */
214 static int wmi_gtoa(const char *in, char *out)
215 {
216         int i;
217
218         for (i = 3; i >= 0; i--)
219                 out += sprintf(out, "%02X", in[i] & 0xFF);
220
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, "-");
231
232         for (i = 10; i <= 15; i++)
233                 out += sprintf(out, "%02X", in[i] & 0xFF);
234
235         out = '\0';
236         return 0;
237 }
238
239 static bool find_guid(const char *guid_string, struct wmi_block **out)
240 {
241         char tmp[16], guid_input[16];
242         struct wmi_block *wblock;
243         struct guid_block *block;
244         struct list_head *p;
245
246         wmi_parse_guid(guid_string, tmp);
247         wmi_swap_bytes(tmp, guid_input);
248
249         list_for_each(p, &wmi_blocks.list) {
250                 wblock = list_entry(p, struct wmi_block, list);
251                 block = &wblock->gblock;
252
253                 if (memcmp(block->guid, guid_input, 16) == 0) {
254                         if (out)
255                                 *out = wblock;
256                         return 1;
257                 }
258         }
259         return 0;
260 }
261
262 static acpi_status wmi_method_enable(struct wmi_block *wblock, int enable)
263 {
264         struct guid_block *block = NULL;
265         char method[5];
266         struct acpi_object_list input;
267         union acpi_object params[1];
268         acpi_status status;
269         acpi_handle handle;
270
271         block = &wblock->gblock;
272         handle = wblock->handle;
273
274         if (!block)
275                 return AE_NOT_EXIST;
276
277         input.count = 1;
278         input.pointer = params;
279         params[0].type = ACPI_TYPE_INTEGER;
280         params[0].integer.value = enable;
281
282         snprintf(method, 5, "WE%02X", block->notify_id);
283         status = acpi_evaluate_object(handle, method, &input, NULL);
284
285         if (status != AE_OK && status != AE_NOT_FOUND)
286                 return status;
287         else
288                 return AE_OK;
289 }
290
291 /*
292  * Exported WMI functions
293  */
294 /**
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
301  *
302  * Call an ACPI-WMI method
303  */
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)
306 {
307         struct guid_block *block = NULL;
308         struct wmi_block *wblock = NULL;
309         acpi_handle handle;
310         acpi_status status;
311         struct acpi_object_list input;
312         union acpi_object params[3];
313         char method[5] = "WM";
314
315         if (!find_guid(guid_string, &wblock))
316                 return AE_ERROR;
317
318         block = &wblock->gblock;
319         handle = wblock->handle;
320
321         if (!(block->flags & ACPI_WMI_METHOD))
322                 return AE_BAD_DATA;
323
324         if (block->instance_count < instance)
325                 return AE_BAD_PARAMETER;
326
327         input.count = 2;
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;
333
334         if (in) {
335                 input.count = 3;
336
337                 if (block->flags & ACPI_WMI_STRING) {
338                         params[2].type = ACPI_TYPE_STRING;
339                 } else {
340                         params[2].type = ACPI_TYPE_BUFFER;
341                 }
342                 params[2].buffer.length = in->length;
343                 params[2].buffer.pointer = in->pointer;
344         }
345
346         strncat(method, block->object_id, 2);
347
348         status = acpi_evaluate_object(handle, method, &input, out);
349
350         return status;
351 }
352 EXPORT_SYMBOL_GPL(wmi_evaluate_method);
353
354 /**
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
359  *
360  * Return the contents of an ACPI-WMI data block to a buffer
361  */
362 acpi_status wmi_query_block(const char *guid_string, u8 instance,
363 struct acpi_buffer *out)
364 {
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];
371         char method[5];
372         char wc_method[5] = "WC";
373
374         if (!guid_string || !out)
375                 return AE_BAD_PARAMETER;
376
377         if (!find_guid(guid_string, &wblock))
378                 return AE_ERROR;
379
380         block = &wblock->gblock;
381         handle = wblock->handle;
382
383         if (block->instance_count < instance)
384                 return AE_BAD_PARAMETER;
385
386         /* Check GUID is a data block */
387         if (block->flags & (ACPI_WMI_EVENT | ACPI_WMI_METHOD))
388                 return AE_ERROR;
389
390         input.count = 1;
391         input.pointer = wq_params;
392         wq_params[0].type = ACPI_TYPE_INTEGER;
393         wq_params[0].integer.value = instance;
394
395         /*
396          * If ACPI_WMI_EXPENSIVE, call the relevant WCxx method first to
397          * enable collection.
398          */
399         if (block->flags & ACPI_WMI_EXPENSIVE) {
400                 wc_input.count = 1;
401                 wc_input.pointer = wc_params;
402                 wc_params[0].type = ACPI_TYPE_INTEGER;
403                 wc_params[0].integer.value = 1;
404
405                 strncat(wc_method, block->object_id, 2);
406
407                 /*
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.
411                  */
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,
415                                 &wc_input, NULL);
416         }
417
418         strcpy(method, "WQ");
419         strncat(method, block->object_id, 2);
420
421         status = acpi_evaluate_object(handle, method, &input, out);
422
423         /*
424          * If ACPI_WMI_EXPENSIVE, call the relevant WCxx method, even if
425          * the WQxx method failed - we should disable collection anyway.
426          */
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);
431         }
432
433         return status;
434 }
435 EXPORT_SYMBOL_GPL(wmi_query_block);
436
437 /**
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
442  *
443  * Write the contents of the input buffer to an ACPI-WMI data block
444  */
445 acpi_status wmi_set_block(const char *guid_string, u8 instance,
446 const struct acpi_buffer *in)
447 {
448         struct guid_block *block = NULL;
449         struct wmi_block *wblock = NULL;
450         acpi_handle handle;
451         struct acpi_object_list input;
452         union acpi_object params[2];
453         char method[5] = "WS";
454
455         if (!guid_string || !in)
456                 return AE_BAD_DATA;
457
458         if (!find_guid(guid_string, &wblock))
459                 return AE_ERROR;
460
461         block = &wblock->gblock;
462         handle = wblock->handle;
463
464         if (block->instance_count < instance)
465                 return AE_BAD_PARAMETER;
466
467         /* Check GUID is a data block */
468         if (block->flags & (ACPI_WMI_EVENT | ACPI_WMI_METHOD))
469                 return AE_ERROR;
470
471         input.count = 2;
472         input.pointer = params;
473         params[0].type = ACPI_TYPE_INTEGER;
474         params[0].integer.value = instance;
475
476         if (block->flags & ACPI_WMI_STRING) {
477                 params[1].type = ACPI_TYPE_STRING;
478         } else {
479                 params[1].type = ACPI_TYPE_BUFFER;
480         }
481         params[1].buffer.length = in->length;
482         params[1].buffer.pointer = in->pointer;
483
484         strncat(method, block->object_id, 2);
485
486         return acpi_evaluate_object(handle, method, &input, NULL);
487 }
488 EXPORT_SYMBOL_GPL(wmi_set_block);
489
490 static void wmi_dump_wdg(struct guid_block *g)
491 {
492         char guid_string[37];
493
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);
502         if (g->flags) {
503                 printk(" ");
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 ");
512         }
513         printk("\n");
514
515 }
516
517 static void wmi_notify_debug(u32 value, void *context)
518 {
519         struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
520         union acpi_object *obj;
521
522         wmi_get_event_data(value, &response);
523
524         obj = (union acpi_object *)response.pointer;
525
526         if (!obj)
527                 return;
528
529         printk(KERN_INFO PREFIX "DEBUG Event ");
530         switch(obj->type) {
531         case ACPI_TYPE_BUFFER:
532                 printk("BUFFER_TYPE - length %d\n", obj->buffer.length);
533                 break;
534         case ACPI_TYPE_STRING:
535                 printk("STRING_TYPE - %s\n", obj->string.pointer);
536                 break;
537         case ACPI_TYPE_INTEGER:
538                 printk("INTEGER_TYPE - %llu\n", obj->integer.value);
539                 break;
540         case ACPI_TYPE_PACKAGE:
541                 printk("PACKAGE_TYPE - %d elements\n", obj->package.count);
542                 break;
543         default:
544                 printk("object type 0x%X\n", obj->type);
545         }
546 }
547
548 /**
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
552  *
553  * Register a handler for events sent to the ACPI-WMI mapper device.
554  */
555 acpi_status wmi_install_notify_handler(const char *guid,
556 wmi_notify_handler handler, void *data)
557 {
558         struct wmi_block *block;
559         acpi_status status;
560
561         if (!guid || !handler)
562                 return AE_BAD_PARAMETER;
563
564         if (!find_guid(guid, &block))
565                 return AE_NOT_EXIST;
566
567         if (block->handler && block->handler != wmi_notify_debug)
568                 return AE_ALREADY_ACQUIRED;
569
570         block->handler = handler;
571         block->handler_data = data;
572
573         status = wmi_method_enable(block, 1);
574
575         return status;
576 }
577 EXPORT_SYMBOL_GPL(wmi_install_notify_handler);
578
579 /**
580  * wmi_uninstall_notify_handler - Unregister handler for WMI events
581  *
582  * Unregister handler for events sent to the ACPI-WMI mapper device.
583  */
584 acpi_status wmi_remove_notify_handler(const char *guid)
585 {
586         struct wmi_block *block;
587         acpi_status status = AE_OK;
588
589         if (!guid)
590                 return AE_BAD_PARAMETER;
591
592         if (!find_guid(guid, &block))
593                 return AE_NOT_EXIST;
594
595         if (!block->handler || block->handler == wmi_notify_debug)
596                 return AE_NULL_ENTRY;
597
598         if (debug_event) {
599                 block->handler = wmi_notify_debug;
600         } else {
601                 status = wmi_method_enable(block, 0);
602                 block->handler = NULL;
603                 block->handler_data = NULL;
604         }
605         return status;
606 }
607 EXPORT_SYMBOL_GPL(wmi_remove_notify_handler);
608
609 /**
610  * wmi_get_event_data - Get WMI data associated with an event
611  *
612  * @event: Event to find
613  * @out: Buffer to hold event data. out->pointer should be freed with kfree()
614  *
615  * Returns extra data associated with an event in WMI.
616  */
617 acpi_status wmi_get_event_data(u32 event, struct acpi_buffer *out)
618 {
619         struct acpi_object_list input;
620         union acpi_object params[1];
621         struct guid_block *gblock;
622         struct wmi_block *wblock;
623         struct list_head *p;
624
625         input.count = 1;
626         input.pointer = params;
627         params[0].type = ACPI_TYPE_INTEGER;
628         params[0].integer.value = event;
629
630         list_for_each(p, &wmi_blocks.list) {
631                 wblock = list_entry(p, struct wmi_block, list);
632                 gblock = &wblock->gblock;
633
634                 if ((gblock->flags & ACPI_WMI_EVENT) &&
635                         (gblock->notify_id == event))
636                         return acpi_evaluate_object(wblock->handle, "_WED",
637                                 &input, out);
638         }
639
640         return AE_NOT_FOUND;
641 }
642 EXPORT_SYMBOL_GPL(wmi_get_event_data);
643
644 /**
645  * wmi_has_guid - Check if a GUID is available
646  * @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba
647  *
648  * Check if a given GUID is defined by _WDG
649  */
650 bool wmi_has_guid(const char *guid_string)
651 {
652         return find_guid(guid_string, NULL);
653 }
654 EXPORT_SYMBOL_GPL(wmi_has_guid);
655
656 /*
657  * sysfs interface
658  */
659 static ssize_t show_modalias(struct device *dev, struct device_attribute *attr,
660                              char *buf)
661 {
662         char guid_string[37];
663         struct wmi_block *wblock;
664
665         wblock = dev_get_drvdata(dev);
666         if (!wblock)
667                 return -ENOMEM;
668
669         wmi_gtoa(wblock->gblock.guid, guid_string);
670
671         return sprintf(buf, "wmi:%s\n", guid_string);
672 }
673 static DEVICE_ATTR(modalias, S_IRUGO, show_modalias, NULL);
674
675 static int wmi_dev_uevent(struct device *dev, struct kobj_uevent_env *env)
676 {
677         char guid_string[37];
678
679         struct wmi_block *wblock;
680
681         if (add_uevent_var(env, "MODALIAS="))
682                 return -ENOMEM;
683
684         wblock = dev_get_drvdata(dev);
685         if (!wblock)
686                 return -ENOMEM;
687
688         wmi_gtoa(wblock->gblock.guid, guid_string);
689
690         strcpy(&env->buf[env->buflen - 1], "wmi:");
691         memcpy(&env->buf[env->buflen - 1 + 4], guid_string, 36);
692         env->buflen += 40;
693
694         return 0;
695 }
696
697 static void wmi_dev_free(struct device *dev)
698 {
699         kfree(dev);
700 }
701
702 static struct class wmi_class = {
703         .name = "wmi",
704         .dev_release = wmi_dev_free,
705         .dev_uevent = wmi_dev_uevent,
706 };
707
708 static int wmi_create_devs(void)
709 {
710         int result;
711         char guid_string[37];
712         struct guid_block *gblock;
713         struct wmi_block *wblock;
714         struct list_head *p;
715         struct device *guid_dev;
716
717         /* Create devices for all the GUIDs */
718         list_for_each(p, &wmi_blocks.list) {
719                 wblock = list_entry(p, struct wmi_block, list);
720
721                 guid_dev = kzalloc(sizeof(struct device), GFP_KERNEL);
722                 if (!guid_dev)
723                         return -ENOMEM;
724
725                 wblock->dev = guid_dev;
726
727                 guid_dev->class = &wmi_class;
728                 dev_set_drvdata(guid_dev, wblock);
729
730                 gblock = &wblock->gblock;
731
732                 wmi_gtoa(gblock->guid, guid_string);
733                 dev_set_name(guid_dev, guid_string);
734
735                 result = device_register(guid_dev);
736                 if (result)
737                         return result;
738
739                 result = device_create_file(guid_dev, &dev_attr_modalias);
740                 if (result)
741                         return result;
742         }
743
744         return 0;
745 }
746
747 static void wmi_remove_devs(void)
748 {
749         struct guid_block *gblock;
750         struct wmi_block *wblock;
751         struct list_head *p;
752         struct device *guid_dev;
753
754         /* Delete devices for all the GUIDs */
755         list_for_each(p, &wmi_blocks.list) {
756                 wblock = list_entry(p, struct wmi_block, list);
757
758                 guid_dev = wblock->dev;
759                 gblock = &wblock->gblock;
760
761                 device_remove_file(guid_dev, &dev_attr_modalias);
762
763                 device_unregister(guid_dev);
764         }
765 }
766
767 static void wmi_class_exit(void)
768 {
769         wmi_remove_devs();
770         class_unregister(&wmi_class);
771 }
772
773 static int wmi_class_init(void)
774 {
775         int ret;
776
777         ret = class_register(&wmi_class);
778         if (ret)
779                 return ret;
780
781         ret = wmi_create_devs();
782         if (ret)
783                 wmi_class_exit();
784
785         return ret;
786 }
787
788 static bool guid_already_parsed(const char *guid_string)
789 {
790         struct guid_block *gblock;
791         struct wmi_block *wblock;
792         struct list_head *p;
793
794         list_for_each(p, &wmi_blocks.list) {
795                 wblock = list_entry(p, struct wmi_block, list);
796                 gblock = &wblock->gblock;
797
798                 if (strncmp(gblock->guid, guid_string, 16) == 0)
799                         return true;
800         }
801         return false;
802 }
803
804 /*
805  * Parse the _WDG method for the GUID data blocks
806  */
807 static __init acpi_status parse_wdg(acpi_handle handle)
808 {
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];
814         acpi_status status;
815         u32 i, total;
816
817         status = acpi_evaluate_object(handle, "_WDG", NULL, &out);
818
819         if (ACPI_FAILURE(status))
820                 return status;
821
822         obj = (union acpi_object *) out.pointer;
823
824         if (obj->type != ACPI_TYPE_BUFFER)
825                 return AE_ERROR;
826
827         total = obj->buffer.length / sizeof(struct guid_block);
828
829         gblock = kmemdup(obj->buffer.pointer, obj->buffer.length, GFP_KERNEL);
830         if (!gblock)
831                 return AE_NO_MEMORY;
832
833         for (i = 0; i < total; i++) {
834                 /*
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.
840                 */
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",
844                                 guid_string);
845                         continue;
846                 }
847                 if (debug_dump_wdg)
848                         wmi_dump_wdg(&gblock[i]);
849
850                 wblock = kzalloc(sizeof(struct wmi_block), GFP_KERNEL);
851                 if (!wblock)
852                         return AE_NO_MEMORY;
853
854                 wblock->gblock = gblock[i];
855                 wblock->handle = handle;
856                 if (debug_event) {
857                         wblock->handler = wmi_notify_debug;
858                         status = wmi_method_enable(wblock, 1);
859                 }
860                 list_add_tail(&wblock->list, &wmi_blocks.list);
861         }
862
863         kfree(out.pointer);
864         kfree(gblock);
865
866         return status;
867 }
868
869 /*
870  * WMI can have EmbeddedControl access regions. In which case, we just want to
871  * hand these off to the EC driver.
872  */
873 static acpi_status
874 acpi_wmi_ec_space_handler(u32 function, acpi_physical_address address,
875                       u32 bits, u64 *value,
876                       void *handler_context, void *region_context)
877 {
878         int result = 0, i = 0;
879         u8 temp = 0;
880
881         if ((address > 0xFF) || !value)
882                 return AE_BAD_PARAMETER;
883
884         if (function != ACPI_READ && function != ACPI_WRITE)
885                 return AE_BAD_PARAMETER;
886
887         if (bits != 8)
888                 return AE_BAD_PARAMETER;
889
890         if (function == ACPI_READ) {
891                 result = ec_read(address, &temp);
892                 (*value) |= ((u64)temp) << i;
893         } else {
894                 temp = 0xff & ((*value) >> i);
895                 result = ec_write(address, temp);
896         }
897
898         switch (result) {
899         case -EINVAL:
900                 return AE_BAD_PARAMETER;
901                 break;
902         case -ENODEV:
903                 return AE_NOT_FOUND;
904                 break;
905         case -ETIME:
906                 return AE_TIME;
907                 break;
908         default:
909                 return AE_OK;
910         }
911 }
912
913 static void acpi_wmi_notify(struct acpi_device *device, u32 event)
914 {
915         struct guid_block *block;
916         struct wmi_block *wblock;
917         struct list_head *p;
918         char guid_string[37];
919
920         list_for_each(p, &wmi_blocks.list) {
921                 wblock = list_entry(p, struct wmi_block, list);
922                 block = &wblock->gblock;
923
924                 if ((block->flags & ACPI_WMI_EVENT) &&
925                         (block->notify_id == event)) {
926                         if (wblock->handler)
927                                 wblock->handler(event, wblock->handler_data);
928                         if (debug_event) {
929                                 wmi_gtoa(wblock->gblock.guid, guid_string);
930                                 printk(KERN_INFO PREFIX "DEBUG Event GUID:"
931                                        " %s\n", guid_string);
932                         }
933
934                         acpi_bus_generate_netlink_event(
935                                 device->pnp.device_class, dev_name(&device->dev),
936                                 event, 0);
937                         break;
938                 }
939         }
940 }
941
942 static int acpi_wmi_remove(struct acpi_device *device, int type)
943 {
944         acpi_remove_address_space_handler(device->handle,
945                                 ACPI_ADR_SPACE_EC, &acpi_wmi_ec_space_handler);
946
947         return 0;
948 }
949
950 static int __init acpi_wmi_add(struct acpi_device *device)
951 {
952         acpi_status status;
953         int result = 0;
954
955         status = acpi_install_address_space_handler(device->handle,
956                                                     ACPI_ADR_SPACE_EC,
957                                                     &acpi_wmi_ec_space_handler,
958                                                     NULL, NULL);
959         if (ACPI_FAILURE(status))
960                 return -ENODEV;
961
962         status = parse_wdg(device->handle);
963         if (ACPI_FAILURE(status)) {
964                 printk(KERN_ERR PREFIX "Error installing EC region handler\n");
965                 return -ENODEV;
966         }
967
968         return result;
969 }
970
971 static int __init acpi_wmi_init(void)
972 {
973         int result;
974
975         INIT_LIST_HEAD(&wmi_blocks.list);
976
977         if (acpi_disabled)
978                 return -ENODEV;
979
980         result = acpi_bus_register_driver(&acpi_wmi_driver);
981
982         if (result < 0) {
983                 printk(KERN_INFO PREFIX "Error loading mapper\n");
984                 return -ENODEV;
985         }
986
987         result = wmi_class_init();
988         if (result) {
989                 acpi_bus_unregister_driver(&acpi_wmi_driver);
990                 return result;
991         }
992
993         printk(KERN_INFO PREFIX "Mapper loaded\n");
994
995         return result;
996 }
997
998 static void __exit acpi_wmi_exit(void)
999 {
1000         struct list_head *p, *tmp;
1001         struct wmi_block *wblock;
1002
1003         wmi_class_exit();
1004
1005         acpi_bus_unregister_driver(&acpi_wmi_driver);
1006
1007         list_for_each_safe(p, tmp, &wmi_blocks.list) {
1008                 wblock = list_entry(p, struct wmi_block, list);
1009
1010                 list_del(p);
1011                 kfree(wblock);
1012         }
1013
1014         printk(KERN_INFO PREFIX "Mapper unloaded\n");
1015 }
1016
1017 subsys_initcall(acpi_wmi_init);
1018 module_exit(acpi_wmi_exit);