diff options
author | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2008-04-18 00:46:23 +0200 |
---|---|---|
committer | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2008-04-18 00:46:23 +0200 |
commit | f0298512c86ebc2eae9f4556d0b15087aa750646 (patch) | |
tree | 4686624de999deb1c6fb155d5d4630869fc1c0c6 /drivers/ide/ide-generic.c | |
parent | ide: add warm-plug support for IDE devices (take 2) (diff) | |
download | linux-f0298512c86ebc2eae9f4556d0b15087aa750646.tar.xz linux-f0298512c86ebc2eae9f4556d0b15087aa750646.zip |
ide-generic: add ide_generic class and attribute for adding new interfaces
* Add ide_generic_sysfs_init() helper registering 'ide_generic' class
(together with ide_generic_class_release() ->class_release method)
and use it in ide_generic_init().
* Add "add" class attribute to 'ide_generic' class for adding new interfaces
(it is intended to be a replacement for obsoleted "idex=base[,ctl[,irq]]"
kernel parameters).
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Diffstat (limited to 'drivers/ide/ide-generic.c')
-rw-r--r-- | drivers/ide/ide-generic.c | 78 |
1 files changed, 77 insertions, 1 deletions
diff --git a/drivers/ide/ide-generic.c b/drivers/ide/ide-generic.c index c1d8d71f8791..387574fe4b2b 100644 --- a/drivers/ide/ide-generic.c +++ b/drivers/ide/ide-generic.c @@ -1,17 +1,89 @@ /* * generic/default IDE host driver * - * Copyright (C) 2004 Bartlomiej Zolnierkiewicz + * Copyright (C) 2004, 2008 Bartlomiej Zolnierkiewicz * This code was split off from ide.c. See it for original copyrights. * * May be copied or modified under the terms of the GNU General Public License. */ +/* + * For special cases new interfaces may be added using sysfs, i.e. + * + * echo -n "0x168:0x36e:10" > /sys/class/ide_generic/add + * + * will add an interface using I/O ports 0x168-0x16f/0x36e and IRQ 10. + */ + #include <linux/kernel.h> #include <linux/init.h> #include <linux/module.h> #include <linux/ide.h> +#define DRV_NAME "ide_generic" + +static ssize_t store_add(struct class *cls, const char *buf, size_t n) +{ + ide_hwif_t *hwif; + unsigned int base, ctl; + int irq; + hw_regs_t hw; + u8 idx[] = { 0xff, 0xff, 0xff, 0xff }; + + if (sscanf(buf, "%x:%x:%d", &base, &ctl, &irq) != 3) + return -EINVAL; + + hwif = ide_find_port(base); + if (hwif == NULL) + return -ENOENT; + + memset(&hw, 0, sizeof(hw)); + ide_std_init_ports(&hw, base, ctl); + hw.irq = irq; + hw.chipset = ide_generic; + + ide_init_port_hw(hwif, &hw); + + idx[0] = hwif->index; + + ide_device_add(idx, NULL); + + return n; +}; + +static struct class_attribute ide_generic_class_attrs[] = { + __ATTR(add, S_IWUSR, NULL, store_add), + __ATTR_NULL +}; + +static void ide_generic_class_release(struct class *cls) +{ + kfree(cls); +} + +static int __init ide_generic_sysfs_init(void) +{ + struct class *cls; + int rc; + + cls = kzalloc(sizeof(*cls), GFP_KERNEL); + if (!cls) + return -ENOMEM; + + cls->name = DRV_NAME; + cls->owner = THIS_MODULE; + cls->class_release = ide_generic_class_release; + cls->class_attrs = ide_generic_class_attrs; + + rc = class_register(cls); + if (rc) { + kfree(cls); + return rc; + } + + return 0; +} + static int __init ide_generic_init(void) { u8 idx[MAX_HWIFS]; @@ -30,6 +102,10 @@ static int __init ide_generic_init(void) ide_device_add_all(idx, NULL); + if (ide_generic_sysfs_init()) + printk(KERN_ERR DRV_NAME ": failed to create ide_generic " + "class\n"); + return 0; } |