ACPI: bay: new driver adding removable drive bay support
[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/proc_fs.h>
32 #include <linux/seq_file.h>
33 #include <asm/uaccess.h>
34
35 #define ACPI_BAY_DRIVER_NAME "ACPI Removable Drive Bay Driver"
36
37 ACPI_MODULE_NAME("bay")
38 MODULE_AUTHOR("Kristen Carlson Accardi");
39 MODULE_DESCRIPTION(ACPI_BAY_DRIVER_NAME);
40 MODULE_LICENSE("GPL");
41 #define ACPI_BAY_CLASS "bay"
42 #define ACPI_BAY_COMPONENT      0x10000000
43 #define _COMPONENT ACPI_BAY_COMPONENT
44 #define bay_dprintk(h,s) {\
45         char prefix[80] = {'\0'};\
46         struct acpi_buffer buffer = {sizeof(prefix), prefix};\
47         acpi_get_name(h, ACPI_FULL_PATHNAME, &buffer);\
48         printk(KERN_DEBUG PREFIX "%s: %s\n", prefix, s); }
49
50 static void bay_notify(acpi_handle handle, u32 event, void *data);
51 static int acpi_bay_add(struct acpi_device *device);
52 static int acpi_bay_remove(struct acpi_device *device, int type);
53 static int acpi_bay_match(struct acpi_device *device,
54                                 struct acpi_driver *driver);
55
56 static struct acpi_driver acpi_bay_driver = {
57         .name = ACPI_BAY_DRIVER_NAME,
58         .class = ACPI_BAY_CLASS,
59         .ops = {
60                 .add = acpi_bay_add,
61                 .remove = acpi_bay_remove,
62                 .match = acpi_bay_match,
63                 },
64 };
65
66 struct bay {
67         acpi_handle handle;
68         char *name;
69         struct list_head list;
70         struct proc_dir_entry *proc;
71 };
72
73 LIST_HEAD(drive_bays);
74
75 static struct proc_dir_entry *acpi_bay_dir;
76
77 /*****************************************************************************
78  *                         Drive Bay functions                               *
79  *****************************************************************************/
80 /**
81  * is_ejectable - see if a device is ejectable
82  * @handle: acpi handle of the device
83  *
84  * If an acpi object has a _EJ0 method, then it is ejectable
85  */
86 static int is_ejectable(acpi_handle handle)
87 {
88         acpi_status status;
89         acpi_handle tmp;
90
91         status = acpi_get_handle(handle, "_EJ0", &tmp);
92         if (ACPI_FAILURE(status))
93                 return 0;
94         return 1;
95 }
96
97 /**
98  * bay_present - see if the bay device is present
99  * @bay: the drive bay
100  *
101  * execute the _STA method.
102  */
103 static int bay_present(struct bay *bay)
104 {
105         unsigned long sta;
106         acpi_status status;
107
108         if (bay) {
109                 status = acpi_evaluate_integer(bay->handle, "_STA", NULL, &sta);
110                 if (ACPI_SUCCESS(status) && sta)
111                         return 1;
112         }
113         return 0;
114 }
115
116 /**
117  * eject_device - respond to an eject request
118  * @handle - the device to eject
119  *
120  * Call this devices _EJ0 method.
121  */
122 static void eject_device(acpi_handle handle)
123 {
124         struct acpi_object_list arg_list;
125         union acpi_object arg;
126
127         bay_dprintk(handle, "Ejecting device");
128
129         arg_list.count = 1;
130         arg_list.pointer = &arg;
131         arg.type = ACPI_TYPE_INTEGER;
132         arg.integer.value = 1;
133
134         if (ACPI_FAILURE(acpi_evaluate_object(handle, "_EJ0",
135                                               &arg_list, NULL)))
136                 pr_debug("Failed to evaluate _EJ0!\n");
137 }
138
139
140 /**
141  * is_ata - see if a device is an ata device
142  * @handle: acpi handle of the device
143  *
144  * If an acpi object has one of 4 ATA ACPI methods defined,
145  * then it is an ATA device
146  */
147 static int is_ata(acpi_handle handle)
148 {
149         acpi_handle tmp;
150
151         if ((ACPI_SUCCESS(acpi_get_handle(handle, "_GTF", &tmp))) ||
152            (ACPI_SUCCESS(acpi_get_handle(handle, "_GTM", &tmp))) ||
153            (ACPI_SUCCESS(acpi_get_handle(handle, "_STM", &tmp))) ||
154            (ACPI_SUCCESS(acpi_get_handle(handle, "_SDD", &tmp))))
155                 return 1;
156
157         return 0;
158 }
159
160 /**
161  * parent_is_ata(acpi_handle handle)
162  *
163  */
164 static int parent_is_ata(acpi_handle handle)
165 {
166         acpi_handle phandle;
167
168         if (acpi_get_parent(handle, &phandle))
169                 return 0;
170
171         return is_ata(phandle);
172 }
173
174 /**
175  * is_ejectable_bay - see if a device is an ejectable drive bay
176  * @handle: acpi handle of the device
177  *
178  * If an acpi object is ejectable and has one of the ACPI ATA
179  * methods defined, then we can safely call it an ejectable
180  * drive bay
181  */
182 static int is_ejectable_bay(acpi_handle handle)
183 {
184         if ((is_ata(handle) || parent_is_ata(handle)) && is_ejectable(handle))
185                 return 1;
186         return 0;
187 }
188
189 /**
190  * eject_removable_drive - try to eject this drive
191  * @dev : the device structure of the drive
192  *
193  * If a device is a removable drive that requires an _EJ0 method
194  * to be executed in order to safely remove from the system, do
195  * it.  ATM - always returns success
196  */
197 int eject_removable_drive(struct device *dev)
198 {
199         acpi_handle handle = DEVICE_ACPI_HANDLE(dev);
200
201         if (handle) {
202                 bay_dprintk(handle, "Got device handle");
203                 if (is_ejectable_bay(handle))
204                         eject_device(handle);
205         } else {
206                 printk("No acpi handle for device\n");
207         }
208
209         /* should I return an error code? */
210         return 0;
211 }
212 EXPORT_SYMBOL_GPL(eject_removable_drive);
213
214 static int acpi_bay_add(struct acpi_device *device)
215 {
216         bay_dprintk(device->handle, "adding bay device");
217         strcpy(acpi_device_name(device), "Dockable Bay");
218         strcpy(acpi_device_class(device), "bay");
219         return 0;
220 }
221
222 static int acpi_bay_status_seq_show(struct seq_file *seq, void *offset)
223 {
224         struct bay *bay = (struct bay *)seq->private;
225
226         if (!bay)
227                 return 0;
228
229         if (bay_present(bay))
230                 seq_printf(seq, "present\n");
231         else
232                 seq_printf(seq, "removed\n");
233
234         return 0;
235 }
236
237 static ssize_t
238 acpi_bay_write_eject(struct file *file,
239                       const char __user * buffer,
240                       size_t count, loff_t * data)
241 {
242         struct seq_file *m = (struct seq_file *)file->private_data;
243         struct bay *bay = (struct bay *)m->private;
244         char str[12] = { 0 };
245         u32 state = 0;
246
247         /* FIXME - our only valid value here is 1 */
248         if (!bay || count + 1 > sizeof str)
249                 return -EINVAL;
250
251         if (copy_from_user(str, buffer, count))
252                 return -EFAULT;
253
254         str[count] = 0;
255         state = simple_strtoul(str, NULL, 0);
256         if (state)
257                 eject_device(bay->handle);
258
259         return count;
260 }
261
262 static int
263 acpi_bay_status_open_fs(struct inode *inode, struct file *file)
264 {
265         return single_open(file, acpi_bay_status_seq_show,
266                            PDE(inode)->data);
267 }
268
269 static int
270 acpi_bay_eject_open_fs(struct inode *inode, struct file *file)
271 {
272         return single_open(file, acpi_bay_status_seq_show,
273                            PDE(inode)->data);
274 }
275
276 static struct file_operations acpi_bay_status_fops = {
277         .open = acpi_bay_status_open_fs,
278         .read = seq_read,
279         .llseek = seq_lseek,
280         .release = single_release,
281 };
282
283 static struct file_operations acpi_bay_eject_fops = {
284         .open = acpi_bay_eject_open_fs,
285         .read = seq_read,
286         .write = acpi_bay_write_eject,
287         .llseek = seq_lseek,
288         .release = single_release,
289 };
290 #if 0
291 static struct file_operations acpi_bay_insert_fops = {
292         .open = acpi_bay_insert_open_fs,
293         .read = seq_read,
294         .llseek = seq_lseek,
295         .release = single_release,
296 };
297 #endif
298 static int acpi_bay_add_fs(struct bay *bay)
299 {
300         struct proc_dir_entry *entry = NULL;
301
302         if (!bay)
303                 return -EINVAL;
304
305         /*
306          * create a proc entry for this device
307          * we need to do this a little bit differently than normal
308          * acpi device drivers because our device may not be present
309          * at the moment, and therefore we have no acpi_device struct
310          */
311
312         bay->proc = proc_mkdir(bay->name, acpi_bay_dir);
313
314         /* 'status' [R] */
315         entry = create_proc_entry("status",
316                                   S_IRUGO, bay->proc);
317         if (!entry)
318                 return -EIO;
319         else {
320                 entry->proc_fops = &acpi_bay_status_fops;
321                 entry->data = bay;
322                 entry->owner = THIS_MODULE;
323         }
324         /* 'eject' [W] */
325         entry = create_proc_entry("eject",
326                                   S_IWUGO, bay->proc);
327         if (!entry)
328                 return -EIO;
329         else {
330                 entry->proc_fops = &acpi_bay_eject_fops;
331                 entry->data = bay;
332                 entry->owner = THIS_MODULE;
333         }
334 #if 0
335         /* 'insert' [W] */
336         entry = create_proc_entry("insert",
337                                   S_IWUGO, bay->proc);
338         if (!entry)
339                 return -EIO;
340         else {
341                 entry->proc_fops = &acpi_bay_insert_fops;
342                 entry->data = bay;
343                 entry->owner = THIS_MODULE;
344         }
345 #endif
346         return 0;
347 }
348
349 static void acpi_bay_remove_fs(struct bay *bay)
350 {
351         if (!bay)
352                 return;
353
354         if (bay->proc) {
355                 remove_proc_entry("status", bay->proc);
356                 remove_proc_entry("eject", bay->proc);
357 #if 0
358                 remove_proc_entry("insert", bay->proc);
359 #endif
360                 remove_proc_entry(bay->name, acpi_bay_dir);
361                 bay->proc = NULL;
362         }
363 }
364
365 static int bay_is_dock_device(acpi_handle handle)
366 {
367         acpi_handle parent;
368
369         acpi_get_parent(handle, &parent);
370
371         /* if the device or it's parent is dependent on the
372          * dock, then we are a dock device
373          */
374         return (is_dock_device(handle) || is_dock_device(parent));
375 }
376
377 static int bay_add(acpi_handle handle)
378 {
379         acpi_status status;
380         struct bay *new_bay;
381         struct acpi_buffer nbuffer = {ACPI_ALLOCATE_BUFFER, NULL};
382         acpi_get_name(handle, ACPI_FULL_PATHNAME, &nbuffer);
383
384         bay_dprintk(handle, "Adding notify handler");
385
386         /*
387          * if this is the first bay device found, make the root
388          * proc entry
389          */
390         if (acpi_bay_dir == NULL)
391                 acpi_bay_dir = proc_mkdir(ACPI_BAY_CLASS, acpi_root_dir);
392
393         /*
394          * Initialize bay device structure
395          */
396         new_bay = kmalloc(GFP_ATOMIC, sizeof(*new_bay));
397         INIT_LIST_HEAD(&new_bay->list);
398         new_bay->handle = handle;
399         new_bay->name = (char *)nbuffer.pointer;
400         list_add(&new_bay->list, &drive_bays);
401         acpi_bay_add_fs(new_bay);
402
403         /* register for events on this device */
404         status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
405                         bay_notify, new_bay);
406         if (ACPI_FAILURE(status)) {
407                 printk(KERN_ERR PREFIX "Error installing bay notify handler\n");
408         }
409
410         /* if we are on a dock station, we should register for dock
411          * notifications.
412          */
413         if (bay_is_dock_device(handle)) {
414                 bay_dprintk(handle, "Is dependent on dock\n");
415                 register_hotplug_dock_device(handle, bay_notify, new_bay);
416         }
417         printk(KERN_INFO PREFIX "Bay [%s] Added\n", new_bay->name);
418         return 0;
419 }
420
421 static int acpi_bay_remove(struct acpi_device *device, int type)
422 {
423         /*** FIXME: do something here */
424         return 0;
425 }
426
427 static int acpi_bay_match(struct acpi_device *device,
428                                 struct acpi_driver *driver)
429 {
430         if (!device || !driver)
431                 return -EINVAL;
432
433         if (is_ejectable_bay(device->handle)) {
434                 bay_dprintk(device->handle, "matching bay device");
435                 return 0;
436         }
437
438         return -ENODEV;
439 }
440
441 /**
442  * bay_create_acpi_device - add new devices to acpi
443  * @handle - handle of the device to add
444  *
445  *  This function will create a new acpi_device for the given
446  *  handle if one does not exist already.  This should cause
447  *  acpi to scan for drivers for the given devices, and call
448  *  matching driver's add routine.
449  *
450  *  Returns a pointer to the acpi_device corresponding to the handle.
451  */
452 static struct acpi_device * bay_create_acpi_device(acpi_handle handle)
453 {
454         struct acpi_device *device = NULL;
455         struct acpi_device *parent_device;
456         acpi_handle parent;
457         int ret;
458
459         bay_dprintk(handle, "Trying to get device");
460         if (acpi_bus_get_device(handle, &device)) {
461                 /*
462                  * no device created for this object,
463                  * so we should create one.
464                  */
465                 bay_dprintk(handle, "No device for handle");
466                 acpi_get_parent(handle, &parent);
467                 if (acpi_bus_get_device(parent, &parent_device))
468                         parent_device = NULL;
469
470                 ret = acpi_bus_add(&device, parent_device, handle,
471                         ACPI_BUS_TYPE_DEVICE);
472                 if (ret) {
473                         pr_debug("error adding bus, %x\n",
474                                 -ret);
475                         return NULL;
476                 }
477         }
478         return device;
479 }
480
481 /**
482  * bay_notify - act upon an acpi bay notification
483  * @handle: the bay handle
484  * @event: the acpi event
485  * @data: our driver data struct
486  *
487  */
488 static void bay_notify(acpi_handle handle, u32 event, void *data)
489 {
490         struct acpi_device *dev;
491         struct bay *bay = data;
492
493         bay_dprintk(handle, "Bay event");
494
495         switch(event) {
496         case ACPI_NOTIFY_BUS_CHECK:
497                 printk("Bus Check\n");
498         case ACPI_NOTIFY_DEVICE_CHECK:
499                 printk("Device Check\n");
500                 dev = bay_create_acpi_device(handle);
501                 if (dev)
502                         acpi_bus_generate_event(dev, event, 0);
503                 else
504                         printk("No device for generating event\n");
505                 /* wouldn't it be a good idea to just rescan SATA
506                  * right here?
507                  */
508                 break;
509         case ACPI_NOTIFY_EJECT_REQUEST:
510                 printk("Eject request\n");
511                 dev = bay_create_acpi_device(handle);
512                 if (dev)
513                         acpi_bus_generate_event(dev, event, 0);
514                 else
515                         printk("No device for generating eventn");
516
517                 /* wouldn't it be a good idea to just call the
518                  * eject_device here if we were a SATA device?
519                  */
520                 break;
521         default:
522                 printk("unknown event %d\n", event);
523         }
524 }
525
526 static acpi_status
527 find_bay(acpi_handle handle, u32 lvl, void *context, void **rv)
528 {
529         int *count = (int *)context;
530
531         /*
532          * there could be more than one ejectable bay.
533          * so, just return AE_OK always so that every object
534          * will be checked.
535          */
536         if (is_ejectable_bay(handle)) {
537                 bay_dprintk(handle, "found ejectable bay");
538                 bay_add(handle);
539                 (*count)++;
540         }
541         return AE_OK;
542 }
543
544 static int __init bay_init(void)
545 {
546         int bays = 0;
547
548         acpi_bay_dir = NULL;
549         INIT_LIST_HEAD(&drive_bays);
550
551         /* look for dockable drive bays */
552         acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
553                 ACPI_UINT32_MAX, find_bay, &bays, NULL);
554
555         if (bays) {
556                 if ((acpi_bus_register_driver(&acpi_bay_driver) < 0)) {
557                         printk(KERN_ERR "Unable to register bay driver\n");
558                         if (acpi_bay_dir)
559                                 remove_proc_entry(ACPI_BAY_CLASS,
560                                         acpi_root_dir);
561                 }
562         }
563
564         if (!bays)
565                 return -ENODEV;
566
567         return 0;
568 }
569
570 static void __exit bay_exit(void)
571 {
572         struct bay *bay, *tmp;
573
574         list_for_each_entry_safe(bay, tmp, &drive_bays, list) {
575                 if (is_dock_device(bay->handle))
576                         unregister_hotplug_dock_device(bay->handle);
577                 acpi_bay_remove_fs(bay);
578                 acpi_remove_notify_handler(bay->handle, ACPI_SYSTEM_NOTIFY,
579                         bay_notify);
580                 kfree(bay->name);
581                 kfree(bay);
582         }
583
584         if (acpi_bay_dir)
585                 remove_proc_entry(ACPI_BAY_CLASS, acpi_root_dir);
586
587         acpi_bus_unregister_driver(&acpi_bay_driver);
588 }
589
590 postcore_initcall(bay_init);
591 module_exit(bay_exit);
592