0c0a6204d167a85ea55e4edf0ac9bc55665ae6b2
[pandora-kernel.git] / drivers / acpi / bay.c
1 /*
2  *  bay.c - ACPI removable drive bay driver
3  *
4  *  Copyright (C) 2006 Kristen Carlson Accardi <kristen.c.accardi@intel.com>
5  *
6  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or (at
11  *  your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful, but
14  *  WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  *  General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License along
19  *  with this program; if not, write to the Free Software Foundation, Inc.,
20  *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
21  *
22  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
23  */
24 #include <linux/kernel.h>
25 #include <linux/module.h>
26 #include <linux/init.h>
27 #include <linux/types.h>
28 #include <linux/notifier.h>
29 #include <acpi/acpi_bus.h>
30 #include <acpi/acpi_drivers.h>
31 #include <linux/seq_file.h>
32 #include <asm/uaccess.h>
33
34 #define ACPI_BAY_DRIVER_NAME "ACPI Removable Drive Bay Driver"
35
36 ACPI_MODULE_NAME("bay")
37 MODULE_AUTHOR("Kristen Carlson Accardi");
38 MODULE_DESCRIPTION(ACPI_BAY_DRIVER_NAME);
39 MODULE_LICENSE("GPL");
40 #define ACPI_BAY_CLASS "bay"
41 #define ACPI_BAY_COMPONENT      0x10000000
42 #define _COMPONENT ACPI_BAY_COMPONENT
43 #define bay_dprintk(h,s) {\
44         char prefix[80] = {'\0'};\
45         struct acpi_buffer buffer = {sizeof(prefix), prefix};\
46         acpi_get_name(h, ACPI_FULL_PATHNAME, &buffer);\
47         printk(KERN_DEBUG PREFIX "%s: %s\n", prefix, s); }
48
49 static void bay_notify(acpi_handle handle, u32 event, void *data);
50 static int acpi_bay_add(struct acpi_device *device);
51 static int acpi_bay_remove(struct acpi_device *device, int type);
52 static int acpi_bay_match(struct acpi_device *device,
53                                 struct acpi_driver *driver);
54
55 static struct acpi_driver acpi_bay_driver = {
56         .name = ACPI_BAY_DRIVER_NAME,
57         .class = ACPI_BAY_CLASS,
58         .ops = {
59                 .add = acpi_bay_add,
60                 .remove = acpi_bay_remove,
61                 .match = acpi_bay_match,
62                 },
63 };
64
65 struct bay {
66         acpi_handle handle;
67         char *name;
68         struct list_head list;
69 };
70
71 LIST_HEAD(drive_bays);
72
73
74 /*****************************************************************************
75  *                         Drive Bay functions                               *
76  *****************************************************************************/
77 /**
78  * is_ejectable - see if a device is ejectable
79  * @handle: acpi handle of the device
80  *
81  * If an acpi object has a _EJ0 method, then it is ejectable
82  */
83 static int is_ejectable(acpi_handle handle)
84 {
85         acpi_status status;
86         acpi_handle tmp;
87
88         status = acpi_get_handle(handle, "_EJ0", &tmp);
89         if (ACPI_FAILURE(status))
90                 return 0;
91         return 1;
92 }
93
94 /**
95  * bay_present - see if the bay device is present
96  * @bay: the drive bay
97  *
98  * execute the _STA method.
99  */
100 static int bay_present(struct bay *bay)
101 {
102         unsigned long sta;
103         acpi_status status;
104
105         if (bay) {
106                 status = acpi_evaluate_integer(bay->handle, "_STA", NULL, &sta);
107                 if (ACPI_SUCCESS(status) && sta)
108                         return 1;
109         }
110         return 0;
111 }
112
113 /**
114  * eject_device - respond to an eject request
115  * @handle - the device to eject
116  *
117  * Call this devices _EJ0 method.
118  */
119 static void eject_device(acpi_handle handle)
120 {
121         struct acpi_object_list arg_list;
122         union acpi_object arg;
123
124         bay_dprintk(handle, "Ejecting device");
125
126         arg_list.count = 1;
127         arg_list.pointer = &arg;
128         arg.type = ACPI_TYPE_INTEGER;
129         arg.integer.value = 1;
130
131         if (ACPI_FAILURE(acpi_evaluate_object(handle, "_EJ0",
132                                               &arg_list, NULL)))
133                 pr_debug("Failed to evaluate _EJ0!\n");
134 }
135
136
137 /**
138  * is_ata - see if a device is an ata device
139  * @handle: acpi handle of the device
140  *
141  * If an acpi object has one of 4 ATA ACPI methods defined,
142  * then it is an ATA device
143  */
144 static int is_ata(acpi_handle handle)
145 {
146         acpi_handle tmp;
147
148         if ((ACPI_SUCCESS(acpi_get_handle(handle, "_GTF", &tmp))) ||
149            (ACPI_SUCCESS(acpi_get_handle(handle, "_GTM", &tmp))) ||
150            (ACPI_SUCCESS(acpi_get_handle(handle, "_STM", &tmp))) ||
151            (ACPI_SUCCESS(acpi_get_handle(handle, "_SDD", &tmp))))
152                 return 1;
153
154         return 0;
155 }
156
157 /**
158  * parent_is_ata(acpi_handle handle)
159  *
160  */
161 static int parent_is_ata(acpi_handle handle)
162 {
163         acpi_handle phandle;
164
165         if (acpi_get_parent(handle, &phandle))
166                 return 0;
167
168         return is_ata(phandle);
169 }
170
171 /**
172  * is_ejectable_bay - see if a device is an ejectable drive bay
173  * @handle: acpi handle of the device
174  *
175  * If an acpi object is ejectable and has one of the ACPI ATA
176  * methods defined, then we can safely call it an ejectable
177  * drive bay
178  */
179 static int is_ejectable_bay(acpi_handle handle)
180 {
181         if ((is_ata(handle) || parent_is_ata(handle)) && is_ejectable(handle))
182                 return 1;
183         return 0;
184 }
185
186 /**
187  * eject_removable_drive - try to eject this drive
188  * @dev : the device structure of the drive
189  *
190  * If a device is a removable drive that requires an _EJ0 method
191  * to be executed in order to safely remove from the system, do
192  * it.  ATM - always returns success
193  */
194 int eject_removable_drive(struct device *dev)
195 {
196         acpi_handle handle = DEVICE_ACPI_HANDLE(dev);
197
198         if (handle) {
199                 bay_dprintk(handle, "Got device handle");
200                 if (is_ejectable_bay(handle))
201                         eject_device(handle);
202         } else {
203                 printk("No acpi handle for device\n");
204         }
205
206         /* should I return an error code? */
207         return 0;
208 }
209 EXPORT_SYMBOL_GPL(eject_removable_drive);
210
211 static int acpi_bay_add(struct acpi_device *device)
212 {
213         bay_dprintk(device->handle, "adding bay device");
214         strcpy(acpi_device_name(device), "Dockable Bay");
215         strcpy(acpi_device_class(device), "bay");
216         return 0;
217 }
218
219 static int acpi_bay_add_fs(struct bay *bay)
220 {
221         if (!bay)
222                 return -EINVAL;
223 }
224
225 static void acpi_bay_remove_fs(struct bay *bay)
226 {
227         if (!bay)
228                 return;
229 }
230
231 static int bay_is_dock_device(acpi_handle handle)
232 {
233         acpi_handle parent;
234
235         acpi_get_parent(handle, &parent);
236
237         /* if the device or it's parent is dependent on the
238          * dock, then we are a dock device
239          */
240         return (is_dock_device(handle) || is_dock_device(parent));
241 }
242
243 static int bay_add(acpi_handle handle)
244 {
245         acpi_status status;
246         struct bay *new_bay;
247         struct acpi_buffer nbuffer = {ACPI_ALLOCATE_BUFFER, NULL};
248         acpi_get_name(handle, ACPI_FULL_PATHNAME, &nbuffer);
249
250         bay_dprintk(handle, "Adding notify handler");
251
252         /*
253          * Initialize bay device structure
254          */
255         new_bay = kmalloc(GFP_ATOMIC, sizeof(*new_bay));
256         INIT_LIST_HEAD(&new_bay->list);
257         new_bay->handle = handle;
258         new_bay->name = (char *)nbuffer.pointer;
259         list_add(&new_bay->list, &drive_bays);
260         acpi_bay_add_fs(new_bay);
261
262         /* register for events on this device */
263         status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
264                         bay_notify, new_bay);
265         if (ACPI_FAILURE(status)) {
266                 printk(KERN_ERR PREFIX "Error installing bay notify handler\n");
267         }
268
269         /* if we are on a dock station, we should register for dock
270          * notifications.
271          */
272         if (bay_is_dock_device(handle)) {
273                 bay_dprintk(handle, "Is dependent on dock\n");
274                 register_hotplug_dock_device(handle, bay_notify, new_bay);
275         }
276         printk(KERN_INFO PREFIX "Bay [%s] Added\n", new_bay->name);
277         return 0;
278 }
279
280 static int acpi_bay_remove(struct acpi_device *device, int type)
281 {
282         /*** FIXME: do something here */
283         return 0;
284 }
285
286 static int acpi_bay_match(struct acpi_device *device,
287                                 struct acpi_driver *driver)
288 {
289         if (!device || !driver)
290                 return -EINVAL;
291
292         if (is_ejectable_bay(device->handle)) {
293                 bay_dprintk(device->handle, "matching bay device");
294                 return 0;
295         }
296
297         return -ENODEV;
298 }
299
300 /**
301  * bay_create_acpi_device - add new devices to acpi
302  * @handle - handle of the device to add
303  *
304  *  This function will create a new acpi_device for the given
305  *  handle if one does not exist already.  This should cause
306  *  acpi to scan for drivers for the given devices, and call
307  *  matching driver's add routine.
308  *
309  *  Returns a pointer to the acpi_device corresponding to the handle.
310  */
311 static struct acpi_device * bay_create_acpi_device(acpi_handle handle)
312 {
313         struct acpi_device *device = NULL;
314         struct acpi_device *parent_device;
315         acpi_handle parent;
316         int ret;
317
318         bay_dprintk(handle, "Trying to get device");
319         if (acpi_bus_get_device(handle, &device)) {
320                 /*
321                  * no device created for this object,
322                  * so we should create one.
323                  */
324                 bay_dprintk(handle, "No device for handle");
325                 acpi_get_parent(handle, &parent);
326                 if (acpi_bus_get_device(parent, &parent_device))
327                         parent_device = NULL;
328
329                 ret = acpi_bus_add(&device, parent_device, handle,
330                         ACPI_BUS_TYPE_DEVICE);
331                 if (ret) {
332                         pr_debug("error adding bus, %x\n",
333                                 -ret);
334                         return NULL;
335                 }
336         }
337         return device;
338 }
339
340 /**
341  * bay_notify - act upon an acpi bay notification
342  * @handle: the bay handle
343  * @event: the acpi event
344  * @data: our driver data struct
345  *
346  */
347 static void bay_notify(acpi_handle handle, u32 event, void *data)
348 {
349         struct acpi_device *dev;
350
351         bay_dprintk(handle, "Bay event");
352
353         switch(event) {
354         case ACPI_NOTIFY_BUS_CHECK:
355                 printk("Bus Check\n");
356         case ACPI_NOTIFY_DEVICE_CHECK:
357                 printk("Device Check\n");
358                 dev = bay_create_acpi_device(handle);
359                 if (dev)
360                         acpi_bus_generate_event(dev, event, 0);
361                 else
362                         printk("No device for generating event\n");
363                 /* wouldn't it be a good idea to just rescan SATA
364                  * right here?
365                  */
366                 break;
367         case ACPI_NOTIFY_EJECT_REQUEST:
368                 printk("Eject request\n");
369                 dev = bay_create_acpi_device(handle);
370                 if (dev)
371                         acpi_bus_generate_event(dev, event, 0);
372                 else
373                         printk("No device for generating eventn");
374
375                 /* wouldn't it be a good idea to just call the
376                  * eject_device here if we were a SATA device?
377                  */
378                 break;
379         default:
380                 printk("unknown event %d\n", event);
381         }
382 }
383
384 static acpi_status
385 find_bay(acpi_handle handle, u32 lvl, void *context, void **rv)
386 {
387         int *count = (int *)context;
388
389         /*
390          * there could be more than one ejectable bay.
391          * so, just return AE_OK always so that every object
392          * will be checked.
393          */
394         if (is_ejectable_bay(handle)) {
395                 bay_dprintk(handle, "found ejectable bay");
396                 bay_add(handle);
397                 (*count)++;
398         }
399         return AE_OK;
400 }
401
402 static int __init bay_init(void)
403 {
404         int bays = 0;
405
406         INIT_LIST_HEAD(&drive_bays);
407
408         /* look for dockable drive bays */
409         acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
410                 ACPI_UINT32_MAX, find_bay, &bays, NULL);
411
412         if (bays)
413                 if ((acpi_bus_register_driver(&acpi_bay_driver) < 0))
414                         printk(KERN_ERR "Unable to register bay driver\n");
415
416         if (!bays)
417                 return -ENODEV;
418
419         return 0;
420 }
421
422 static void __exit bay_exit(void)
423 {
424         struct bay *bay, *tmp;
425
426         list_for_each_entry_safe(bay, tmp, &drive_bays, list) {
427                 if (is_dock_device(bay->handle))
428                         unregister_hotplug_dock_device(bay->handle);
429                 acpi_bay_remove_fs(bay);
430                 acpi_remove_notify_handler(bay->handle, ACPI_SYSTEM_NOTIFY,
431                         bay_notify);
432                 kfree(bay->name);
433                 kfree(bay);
434         }
435
436         acpi_bus_unregister_driver(&acpi_bay_driver);
437 }
438
439 postcore_initcall(bay_init);
440 module_exit(bay_exit);
441