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