Linux-2.6.12-rc2
[linux-flexiantxendom0-natty.git] / drivers / acpi / battery.c
1 /*
2  *  acpi_battery.c - ACPI Battery Driver ($Revision: 37 $)
3  *
4  *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
5  *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
6  *
7  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8  *
9  *  This program is free software; you can redistribute it and/or modify
10  *  it under the terms of the GNU General Public License as published by
11  *  the Free Software Foundation; either version 2 of the License, or (at
12  *  your option) any later version.
13  *
14  *  This program is distributed in the hope that it will be useful, but
15  *  WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  *  General Public License for more details.
18  *
19  *  You should have received a copy of the GNU General Public License along
20  *  with this program; if not, write to the Free Software Foundation, Inc.,
21  *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
22  *
23  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
24  */
25
26 #include <linux/kernel.h>
27 #include <linux/module.h>
28 #include <linux/init.h>
29 #include <linux/types.h>
30 #include <linux/proc_fs.h>
31 #include <linux/seq_file.h>
32 #include <asm/uaccess.h>
33
34 #include <acpi/acpi_bus.h>
35 #include <acpi/acpi_drivers.h>
36
37
38 #define ACPI_BATTERY_VALUE_UNKNOWN 0xFFFFFFFF
39
40 #define ACPI_BATTERY_FORMAT_BIF "NNNNNNNNNSSSS"
41 #define ACPI_BATTERY_FORMAT_BST "NNNN"
42
43 #define ACPI_BATTERY_COMPONENT          0x00040000
44 #define ACPI_BATTERY_CLASS              "battery"
45 #define ACPI_BATTERY_HID                "PNP0C0A"
46 #define ACPI_BATTERY_DRIVER_NAME        "ACPI Battery Driver"
47 #define ACPI_BATTERY_DEVICE_NAME        "Battery"
48 #define ACPI_BATTERY_FILE_INFO          "info"
49 #define ACPI_BATTERY_FILE_STATUS        "state"
50 #define ACPI_BATTERY_FILE_ALARM         "alarm"
51 #define ACPI_BATTERY_NOTIFY_STATUS      0x80
52 #define ACPI_BATTERY_NOTIFY_INFO        0x81
53 #define ACPI_BATTERY_UNITS_WATTS        "mW"
54 #define ACPI_BATTERY_UNITS_AMPS         "mA"
55
56
57 #define _COMPONENT              ACPI_BATTERY_COMPONENT
58 ACPI_MODULE_NAME                ("acpi_battery")
59
60 MODULE_AUTHOR("Paul Diefenbaugh");
61 MODULE_DESCRIPTION(ACPI_BATTERY_DRIVER_NAME);
62 MODULE_LICENSE("GPL");
63
64 static int acpi_battery_add (struct acpi_device *device);
65 static int acpi_battery_remove (struct acpi_device *device, int type);
66
67 static struct acpi_driver acpi_battery_driver = {
68         .name =         ACPI_BATTERY_DRIVER_NAME,
69         .class =        ACPI_BATTERY_CLASS,
70         .ids =          ACPI_BATTERY_HID,
71         .ops =          {
72                                 .add =          acpi_battery_add,
73                                 .remove =       acpi_battery_remove,
74                         },
75 };
76
77 struct acpi_battery_status {
78         acpi_integer            state;
79         acpi_integer            present_rate;
80         acpi_integer            remaining_capacity;
81         acpi_integer            present_voltage;
82 };
83
84 struct acpi_battery_info {
85         acpi_integer            power_unit;
86         acpi_integer            design_capacity;
87         acpi_integer            last_full_capacity;
88         acpi_integer            battery_technology;
89         acpi_integer            design_voltage;
90         acpi_integer            design_capacity_warning;
91         acpi_integer            design_capacity_low;
92         acpi_integer            battery_capacity_granularity_1;
93         acpi_integer            battery_capacity_granularity_2;
94         acpi_string             model_number;
95         acpi_string             serial_number;
96         acpi_string             battery_type;
97         acpi_string             oem_info;
98 };
99
100 struct acpi_battery_flags {
101         u8                      present:1;      /* Bay occupied? */
102         u8                      power_unit:1;   /* 0=watts, 1=apms */
103         u8                      alarm:1;        /* _BTP present? */
104         u8                      reserved:5;
105 };
106
107 struct acpi_battery_trips {
108         unsigned long           warning;
109         unsigned long           low;
110 };
111
112 struct acpi_battery {
113         acpi_handle             handle;
114         struct acpi_battery_flags flags;
115         struct acpi_battery_trips trips;
116         unsigned long           alarm;
117         struct acpi_battery_info *info;
118 };
119
120
121 /* --------------------------------------------------------------------------
122                                Battery Management
123    -------------------------------------------------------------------------- */
124
125 static int
126 acpi_battery_get_info (
127         struct acpi_battery     *battery,
128         struct acpi_battery_info **bif)
129 {
130         int                     result = 0;
131         acpi_status             status = 0;
132         struct acpi_buffer      buffer = {ACPI_ALLOCATE_BUFFER, NULL};
133         struct acpi_buffer      format = {sizeof(ACPI_BATTERY_FORMAT_BIF),
134                                                 ACPI_BATTERY_FORMAT_BIF};
135         struct acpi_buffer      data = {0, NULL};
136         union acpi_object       *package = NULL;
137
138         ACPI_FUNCTION_TRACE("acpi_battery_get_info");
139
140         if (!battery || !bif)
141                 return_VALUE(-EINVAL);
142
143         /* Evalute _BIF */
144
145         status = acpi_evaluate_object(battery->handle, "_BIF", NULL, &buffer);
146         if (ACPI_FAILURE(status)) {
147                 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _BIF\n"));
148                 return_VALUE(-ENODEV);
149         }
150
151         package = (union acpi_object *) buffer.pointer;
152
153         /* Extract Package Data */
154
155         status = acpi_extract_package(package, &format, &data);
156         if (status != AE_BUFFER_OVERFLOW) {
157                 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error extracting _BIF\n"));
158                 result = -ENODEV;
159                 goto end;
160         }
161
162         data.pointer = kmalloc(data.length, GFP_KERNEL);
163         if (!data.pointer) {
164                 result = -ENOMEM;
165                 goto end;
166         }
167         memset(data.pointer, 0, data.length);
168
169         status = acpi_extract_package(package, &format, &data);
170         if (ACPI_FAILURE(status)) {
171                 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error extracting _BIF\n"));
172                 kfree(data.pointer);
173                 result = -ENODEV;
174                 goto end;
175         }
176
177 end:
178         acpi_os_free(buffer.pointer);
179
180         if (!result)
181                 (*bif) = (struct acpi_battery_info *) data.pointer;
182
183         return_VALUE(result);
184 }
185
186 static int
187 acpi_battery_get_status (
188         struct acpi_battery     *battery,
189         struct acpi_battery_status **bst)
190 {
191         int                     result = 0;
192         acpi_status             status = 0;
193         struct acpi_buffer      buffer = {ACPI_ALLOCATE_BUFFER, NULL};
194         struct acpi_buffer      format = {sizeof(ACPI_BATTERY_FORMAT_BST),
195                                                 ACPI_BATTERY_FORMAT_BST};
196         struct acpi_buffer      data = {0, NULL};
197         union acpi_object       *package = NULL;
198
199         ACPI_FUNCTION_TRACE("acpi_battery_get_status");
200
201         if (!battery || !bst)
202                 return_VALUE(-EINVAL);
203
204         /* Evalute _BST */
205
206         status = acpi_evaluate_object(battery->handle, "_BST", NULL, &buffer);
207         if (ACPI_FAILURE(status)) {
208                 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _BST\n"));
209                 return_VALUE(-ENODEV);
210         }
211
212         package = (union acpi_object *) buffer.pointer;
213
214         /* Extract Package Data */
215
216         status = acpi_extract_package(package, &format, &data);
217         if (status != AE_BUFFER_OVERFLOW) {
218                 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error extracting _BST\n"));
219                 result = -ENODEV;
220                 goto end;
221         }
222
223         data.pointer = kmalloc(data.length, GFP_KERNEL);
224         if (!data.pointer) {
225                 result = -ENOMEM;
226                 goto end;
227         }
228         memset(data.pointer, 0, data.length);
229
230         status = acpi_extract_package(package, &format, &data);
231         if (ACPI_FAILURE(status)) {
232                 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error extracting _BST\n"));
233                 kfree(data.pointer);
234                 result = -ENODEV;
235                 goto end;
236         }
237
238 end:
239         acpi_os_free(buffer.pointer);
240
241         if (!result)
242                 (*bst) = (struct acpi_battery_status *) data.pointer;
243
244         return_VALUE(result);
245 }
246
247
248 static int
249 acpi_battery_set_alarm (
250         struct acpi_battery     *battery,
251         unsigned long           alarm)
252 {
253         acpi_status             status = 0;
254         union acpi_object       arg0 = {ACPI_TYPE_INTEGER};
255         struct acpi_object_list arg_list = {1, &arg0};
256
257         ACPI_FUNCTION_TRACE("acpi_battery_set_alarm");
258
259         if (!battery)
260                 return_VALUE(-EINVAL);
261
262         if (!battery->flags.alarm)
263                 return_VALUE(-ENODEV);
264
265         arg0.integer.value = alarm;
266
267         status = acpi_evaluate_object(battery->handle, "_BTP", &arg_list, NULL);
268         if (ACPI_FAILURE(status))
269                 return_VALUE(-ENODEV);
270
271         ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Alarm set to %d\n", (u32) alarm));
272
273         battery->alarm = alarm;
274
275         return_VALUE(0);
276 }
277
278
279 static int
280 acpi_battery_check (
281         struct acpi_battery     *battery)
282 {
283         int                     result = 0;
284         acpi_status             status = AE_OK;
285         acpi_handle             handle = NULL;
286         struct acpi_device      *device = NULL;
287         struct acpi_battery_info *bif = NULL;
288
289         ACPI_FUNCTION_TRACE("acpi_battery_check");
290         
291         if (!battery)
292                 return_VALUE(-EINVAL);
293
294         result = acpi_bus_get_device(battery->handle, &device);
295         if (result)
296                 return_VALUE(result);
297
298         result = acpi_bus_get_status(device);
299         if (result)
300                 return_VALUE(result);
301
302         /* Insertion? */
303
304         if (!battery->flags.present && device->status.battery_present) {
305
306                 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Battery inserted\n"));
307
308                 /* Evalute _BIF to get certain static information */
309
310                 result = acpi_battery_get_info(battery, &bif);
311                 if (result)
312                         return_VALUE(result);
313
314                 battery->flags.power_unit = bif->power_unit;
315                 battery->trips.warning = bif->design_capacity_warning;
316                 battery->trips.low = bif->design_capacity_low;
317                 kfree(bif);
318
319                 /* See if alarms are supported, and if so, set default */
320
321                 status = acpi_get_handle(battery->handle, "_BTP", &handle);
322                 if (ACPI_SUCCESS(status)) {
323                         battery->flags.alarm = 1;
324                         acpi_battery_set_alarm(battery, battery->trips.warning);
325                 }
326         }
327
328         /* Removal? */
329
330         else if (battery->flags.present && !device->status.battery_present) {
331                 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Battery removed\n"));
332         }
333
334         battery->flags.present = device->status.battery_present;
335
336         return_VALUE(result);
337 }
338
339
340 /* --------------------------------------------------------------------------
341                               FS Interface (/proc)
342    -------------------------------------------------------------------------- */
343
344 static struct proc_dir_entry    *acpi_battery_dir;
345 static int acpi_battery_read_info(struct seq_file *seq, void *offset)
346 {
347         int                     result = 0;
348         struct acpi_battery     *battery = (struct acpi_battery *) seq->private;
349         struct acpi_battery_info *bif = NULL;
350         char                    *units = "?";
351
352         ACPI_FUNCTION_TRACE("acpi_battery_read_info");
353
354         if (!battery)
355                 goto end;
356
357         if (battery->flags.present)
358                 seq_printf(seq, "present:                 yes\n");
359         else {
360                 seq_printf(seq, "present:                 no\n");
361                 goto end;
362         }
363
364         /* Battery Info (_BIF) */
365
366         result = acpi_battery_get_info(battery, &bif);
367         if (result || !bif) {
368                 seq_printf(seq, "ERROR: Unable to read battery information\n");
369                 goto end;
370         }
371
372         units = bif->power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS;
373                                         
374         if (bif->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
375                 seq_printf(seq, "design capacity:         unknown\n");
376         else
377                 seq_printf(seq, "design capacity:         %d %sh\n",
378                         (u32) bif->design_capacity, units);
379
380         if (bif->last_full_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
381                 seq_printf(seq, "last full capacity:      unknown\n");
382         else
383                 seq_printf(seq, "last full capacity:      %d %sh\n",
384                         (u32) bif->last_full_capacity, units);
385
386         switch ((u32) bif->battery_technology) {
387         case 0:
388                 seq_printf(seq, "battery technology:      non-rechargeable\n");
389                 break;
390         case 1:
391                 seq_printf(seq, "battery technology:      rechargeable\n");
392                 break;
393         default:
394                 seq_printf(seq, "battery technology:      unknown\n");
395                 break;
396         }
397
398         if (bif->design_voltage == ACPI_BATTERY_VALUE_UNKNOWN)
399                 seq_printf(seq, "design voltage:          unknown\n");
400         else
401                 seq_printf(seq, "design voltage:          %d mV\n",
402                         (u32) bif->design_voltage);
403         
404         seq_printf(seq, "design capacity warning: %d %sh\n",
405                 (u32) bif->design_capacity_warning, units);
406         seq_printf(seq, "design capacity low:     %d %sh\n",
407                 (u32) bif->design_capacity_low, units);
408         seq_printf(seq, "capacity granularity 1:  %d %sh\n",
409                 (u32) bif->battery_capacity_granularity_1, units);
410         seq_printf(seq, "capacity granularity 2:  %d %sh\n",
411                 (u32) bif->battery_capacity_granularity_2, units);
412         seq_printf(seq, "model number:            %s\n",
413                 bif->model_number);
414         seq_printf(seq, "serial number:           %s\n",
415                 bif->serial_number);
416         seq_printf(seq, "battery type:            %s\n",
417                 bif->battery_type);
418         seq_printf(seq, "OEM info:                %s\n",
419                 bif->oem_info);
420
421 end:
422         kfree(bif);
423
424         return_VALUE(0);
425 }
426
427 static int acpi_battery_info_open_fs(struct inode *inode, struct file *file)
428 {
429         return single_open(file, acpi_battery_read_info, PDE(inode)->data);
430 }
431
432
433 static int
434 acpi_battery_read_state (struct seq_file *seq, void *offset)
435 {
436         int                     result = 0;
437         struct acpi_battery     *battery = (struct acpi_battery *) seq->private;
438         struct acpi_battery_status *bst = NULL;
439         char                    *units = "?";
440
441         ACPI_FUNCTION_TRACE("acpi_battery_read_state");
442
443         if (!battery)
444                 goto end;
445
446         if (battery->flags.present)
447                 seq_printf(seq, "present:                 yes\n");
448         else {
449                 seq_printf(seq, "present:                 no\n");
450                 goto end;
451         }
452
453         /* Battery Units */
454
455         units = battery->flags.power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS;
456
457         /* Battery Status (_BST) */
458
459         result = acpi_battery_get_status(battery, &bst);
460         if (result || !bst) {
461                 seq_printf(seq, "ERROR: Unable to read battery status\n");
462                 goto end;
463         }
464
465         if (!(bst->state & 0x04))
466                 seq_printf(seq, "capacity state:          ok\n");
467         else
468                 seq_printf(seq, "capacity state:          critical\n");
469
470         if ((bst->state & 0x01) && (bst->state & 0x02)){
471                 seq_printf(seq, "charging state:          charging/discharging\n");
472                 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
473                                         "Battery Charging and Discharging?\n"));
474         }
475         else if (bst->state & 0x01)
476                 seq_printf(seq, "charging state:          discharging\n");
477         else if (bst->state & 0x02)
478                 seq_printf(seq, "charging state:          charging\n");
479         else {
480                 seq_printf(seq, "charging state:          charged\n");
481         }
482
483         if (bst->present_rate == ACPI_BATTERY_VALUE_UNKNOWN)
484                 seq_printf(seq, "present rate:            unknown\n");
485         else
486                 seq_printf(seq, "present rate:            %d %s\n",
487                         (u32) bst->present_rate, units);
488
489         if (bst->remaining_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
490                 seq_printf(seq, "remaining capacity:      unknown\n");
491         else
492                 seq_printf(seq, "remaining capacity:      %d %sh\n",
493                         (u32) bst->remaining_capacity, units);
494
495         if (bst->present_voltage == ACPI_BATTERY_VALUE_UNKNOWN)
496                 seq_printf(seq, "present voltage:         unknown\n");
497         else
498                 seq_printf(seq, "present voltage:         %d mV\n",
499                         (u32) bst->present_voltage);
500
501 end:
502         kfree(bst);
503
504         return_VALUE(0);
505 }
506
507 static int acpi_battery_state_open_fs(struct inode *inode, struct file *file)
508 {
509         return single_open(file, acpi_battery_read_state, PDE(inode)->data);
510 }
511
512
513 static int
514 acpi_battery_read_alarm (struct seq_file *seq, void *offset)
515 {
516         struct acpi_battery     *battery = (struct acpi_battery *) seq->private;
517         char                    *units = "?";
518
519         ACPI_FUNCTION_TRACE("acpi_battery_read_alarm");
520
521         if (!battery)
522                 goto end;
523
524         if (!battery->flags.present) {
525                 seq_printf(seq, "present:                 no\n");
526                 goto end;
527         }
528
529         /* Battery Units */
530         
531         units = battery->flags.power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS;
532
533         /* Battery Alarm */
534
535         seq_printf(seq, "alarm:                   ");
536         if (!battery->alarm)
537                 seq_printf(seq, "unsupported\n");
538         else
539                 seq_printf(seq, "%d %sh\n", (u32) battery->alarm, units);
540
541 end:
542         return_VALUE(0);
543 }
544
545
546 static ssize_t
547 acpi_battery_write_alarm (
548         struct file     *file,
549         const char      __user *buffer,
550         size_t          count,
551         loff_t          *ppos)
552 {
553         int                     result = 0;
554         char                    alarm_string[12] = {'\0'};
555         struct seq_file         *m = (struct seq_file *)file->private_data;
556         struct acpi_battery     *battery = (struct acpi_battery *)m->private;
557
558         ACPI_FUNCTION_TRACE("acpi_battery_write_alarm");
559
560         if (!battery || (count > sizeof(alarm_string) - 1))
561                 return_VALUE(-EINVAL);
562
563         if (!battery->flags.present)
564                 return_VALUE(-ENODEV);
565
566         if (copy_from_user(alarm_string, buffer, count))
567                 return_VALUE(-EFAULT);
568         
569         alarm_string[count] = '\0';
570
571         result = acpi_battery_set_alarm(battery, 
572                 simple_strtoul(alarm_string, NULL, 0));
573         if (result)
574                 return_VALUE(result);
575
576         return_VALUE(count);
577 }
578
579 static int acpi_battery_alarm_open_fs(struct inode *inode, struct file *file)
580 {
581         return single_open(file, acpi_battery_read_alarm, PDE(inode)->data);
582 }
583
584 static struct file_operations acpi_battery_info_ops = {
585         .open           = acpi_battery_info_open_fs,
586         .read           = seq_read,
587         .llseek         = seq_lseek,
588         .release        = single_release,
589         .owner = THIS_MODULE,
590 };
591
592 static struct file_operations acpi_battery_state_ops = {
593         .open           = acpi_battery_state_open_fs,
594         .read           = seq_read,
595         .llseek         = seq_lseek,
596         .release        = single_release,
597         .owner = THIS_MODULE,
598 };
599
600 static struct file_operations acpi_battery_alarm_ops = {
601         .open           = acpi_battery_alarm_open_fs,
602         .read           = seq_read,
603         .write          = acpi_battery_write_alarm,
604         .llseek         = seq_lseek,
605         .release        = single_release,
606         .owner = THIS_MODULE,
607 };
608
609 static int
610 acpi_battery_add_fs (
611         struct acpi_device      *device)
612 {
613         struct proc_dir_entry   *entry = NULL;
614
615         ACPI_FUNCTION_TRACE("acpi_battery_add_fs");
616
617         if (!acpi_device_dir(device)) {
618                 acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
619                         acpi_battery_dir);
620                 if (!acpi_device_dir(device))
621                         return_VALUE(-ENODEV);
622                 acpi_device_dir(device)->owner = THIS_MODULE;
623         }
624
625         /* 'info' [R] */
626         entry = create_proc_entry(ACPI_BATTERY_FILE_INFO,
627                 S_IRUGO, acpi_device_dir(device));
628         if (!entry)
629                 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
630                         "Unable to create '%s' fs entry\n",
631                         ACPI_BATTERY_FILE_INFO));
632         else {
633                 entry->proc_fops = &acpi_battery_info_ops; 
634                 entry->data = acpi_driver_data(device);
635                 entry->owner = THIS_MODULE;
636         }
637
638         /* 'status' [R] */
639         entry = create_proc_entry(ACPI_BATTERY_FILE_STATUS,
640                 S_IRUGO, acpi_device_dir(device));
641         if (!entry)
642                 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
643                         "Unable to create '%s' fs entry\n",
644                         ACPI_BATTERY_FILE_STATUS));
645         else {
646                 entry->proc_fops = &acpi_battery_state_ops;
647                 entry->data = acpi_driver_data(device);
648                 entry->owner = THIS_MODULE;
649         }
650
651         /* 'alarm' [R/W] */
652         entry = create_proc_entry(ACPI_BATTERY_FILE_ALARM,
653                 S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device));
654         if (!entry)
655                 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
656                         "Unable to create '%s' fs entry\n",
657                         ACPI_BATTERY_FILE_ALARM));
658         else {
659                 entry->proc_fops = &acpi_battery_alarm_ops;
660                 entry->data = acpi_driver_data(device);
661                 entry->owner = THIS_MODULE;
662         }
663
664         return_VALUE(0);
665 }
666
667
668 static int
669 acpi_battery_remove_fs (
670         struct acpi_device      *device)
671 {
672         ACPI_FUNCTION_TRACE("acpi_battery_remove_fs");
673
674         if (acpi_device_dir(device)) {
675                 remove_proc_entry(ACPI_BATTERY_FILE_ALARM,
676                                   acpi_device_dir(device));
677                 remove_proc_entry(ACPI_BATTERY_FILE_STATUS,
678                                   acpi_device_dir(device));
679                 remove_proc_entry(ACPI_BATTERY_FILE_INFO,
680                                   acpi_device_dir(device));
681
682                 remove_proc_entry(acpi_device_bid(device), acpi_battery_dir);
683                 acpi_device_dir(device) = NULL;
684         }
685
686         return_VALUE(0);
687 }
688
689
690 /* --------------------------------------------------------------------------
691                                  Driver Interface
692    -------------------------------------------------------------------------- */
693
694 static void
695 acpi_battery_notify (
696         acpi_handle             handle,
697         u32                     event,
698         void                    *data)
699 {
700         struct acpi_battery     *battery = (struct acpi_battery *) data;
701         struct acpi_device      *device = NULL;
702
703         ACPI_FUNCTION_TRACE("acpi_battery_notify");
704
705         if (!battery)
706                 return_VOID;
707
708         if (acpi_bus_get_device(handle, &device))
709                 return_VOID;
710
711         switch (event) {
712         case ACPI_BATTERY_NOTIFY_STATUS:
713         case ACPI_BATTERY_NOTIFY_INFO:
714                 acpi_battery_check(battery);
715                 acpi_bus_generate_event(device, event, battery->flags.present);
716                 break;
717         default:
718                 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
719                         "Unsupported event [0x%x]\n", event));
720                 break;
721         }
722
723         return_VOID;
724 }
725
726
727 static int
728 acpi_battery_add (
729         struct acpi_device      *device)
730 {
731         int                     result = 0;
732         acpi_status             status = 0;
733         struct acpi_battery     *battery = NULL;
734
735         ACPI_FUNCTION_TRACE("acpi_battery_add");
736         
737         if (!device)
738                 return_VALUE(-EINVAL);
739
740         battery = kmalloc(sizeof(struct acpi_battery), GFP_KERNEL);
741         if (!battery)
742                 return_VALUE(-ENOMEM);
743         memset(battery, 0, sizeof(struct acpi_battery));
744
745         battery->handle = device->handle;
746         strcpy(acpi_device_name(device), ACPI_BATTERY_DEVICE_NAME);
747         strcpy(acpi_device_class(device), ACPI_BATTERY_CLASS);
748         acpi_driver_data(device) = battery;
749
750         result = acpi_battery_check(battery);
751         if (result)
752                 goto end;
753
754         result = acpi_battery_add_fs(device);
755         if (result)
756                 goto end;
757
758         status = acpi_install_notify_handler(battery->handle,
759                 ACPI_DEVICE_NOTIFY, acpi_battery_notify, battery);
760         if (ACPI_FAILURE(status)) {
761                 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
762                         "Error installing notify handler\n"));
763                 result = -ENODEV;
764                 goto end;
765         }
766
767         printk(KERN_INFO PREFIX "%s Slot [%s] (battery %s)\n",
768                 ACPI_BATTERY_DEVICE_NAME, acpi_device_bid(device),
769                 device->status.battery_present?"present":"absent");
770                 
771 end:
772         if (result) {
773                 acpi_battery_remove_fs(device);
774                 kfree(battery);
775         }
776
777         return_VALUE(result);
778 }
779
780
781 static int
782 acpi_battery_remove (
783         struct acpi_device      *device,
784         int                     type)
785 {
786         acpi_status             status = 0;
787         struct acpi_battery     *battery = NULL;
788
789         ACPI_FUNCTION_TRACE("acpi_battery_remove");
790
791         if (!device || !acpi_driver_data(device))
792                 return_VALUE(-EINVAL);
793
794         battery = (struct acpi_battery *) acpi_driver_data(device);
795
796         status = acpi_remove_notify_handler(battery->handle,
797                 ACPI_DEVICE_NOTIFY, acpi_battery_notify);
798         if (ACPI_FAILURE(status))
799                 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
800                         "Error removing notify handler\n"));
801
802         acpi_battery_remove_fs(device);
803
804         kfree(battery);
805
806         return_VALUE(0);
807 }
808
809
810 static int __init
811 acpi_battery_init (void)
812 {
813         int                     result = 0;
814
815         ACPI_FUNCTION_TRACE("acpi_battery_init");
816
817         acpi_battery_dir = proc_mkdir(ACPI_BATTERY_CLASS, acpi_root_dir);
818         if (!acpi_battery_dir)
819                 return_VALUE(-ENODEV);
820         acpi_battery_dir->owner = THIS_MODULE;
821
822         result = acpi_bus_register_driver(&acpi_battery_driver);
823         if (result < 0) {
824                 remove_proc_entry(ACPI_BATTERY_CLASS, acpi_root_dir);
825                 return_VALUE(-ENODEV);
826         }
827
828         return_VALUE(0);
829 }
830
831
832 static void __exit
833 acpi_battery_exit (void)
834 {
835         ACPI_FUNCTION_TRACE("acpi_battery_exit");
836
837         acpi_bus_unregister_driver(&acpi_battery_driver);
838
839         remove_proc_entry(ACPI_BATTERY_CLASS, acpi_root_dir);
840
841         return_VOID;
842 }
843
844
845 module_init(acpi_battery_init);
846 module_exit(acpi_battery_exit);