X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fide%2Fide.c;h=3fdab563fec25f405a7903b8c13002206d47d45e;hb=43bc926fffd92024b46cafaf7350d669ba9ca884;hp=15b643afc11807adc8e79e7e2b044e47c8b22da3;hpb=6a77f38946aaee1cd85eeec6cf4229b204c15071;p=linux-2.6.git diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 15b643afc..3fdab563f 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -196,9 +196,6 @@ ide_hwif_t ide_hwifs[MAX_HWIFS]; /* master data repository */ EXPORT_SYMBOL(ide_hwifs); -extern ide_driver_t idedefault_driver; -static void setup_driver_defaults(ide_driver_t *driver); - /* * Do not even *think* about calling this! */ @@ -225,7 +222,7 @@ static void init_hwif_data(ide_hwif_t *hwif, unsigned int index) hwif->mwdma_mask = 0x80; /* disable all mwdma */ hwif->swdma_mask = 0x80; /* disable all swdma */ - sema_init(&hwif->gendev_rel_sem, 0); + init_completion(&hwif->gendev_rel_comp); default_hwif_iops(hwif); default_hwif_transport(hwif); @@ -245,11 +242,9 @@ static void init_hwif_data(ide_hwif_t *hwif, unsigned int index) drive->name[2] = 'a' + (index * MAX_DRIVES) + unit; drive->max_failures = IDE_DEFAULT_MAX_FAILURES; drive->using_dma = 0; - drive->is_flash = 0; - drive->driver = &idedefault_driver; drive->vdma = 0; INIT_LIST_HEAD(&drive->list); - sema_init(&drive->gendev_rel_sem, 0); + init_completion(&drive->gendev_rel_comp); } } @@ -301,8 +296,6 @@ static void __init init_ide_data (void) return; /* already initialized */ magic_cookie = 0; - setup_driver_defaults(&idedefault_driver); - /* Initialise all interface structures */ for (index = 0; index < MAX_HWIFS; ++index) { hwif = &ide_hwifs[index]; @@ -362,66 +355,8 @@ static int ide_system_bus_speed(void) return system_bus_speed; } -static int ide_open (struct inode * inode, struct file * filp) -{ - return -ENXIO; -} - -/* - * drives_lock protects the list of drives, drivers_lock the - * list of drivers. Currently nobody takes both at once. - */ - -static DEFINE_SPINLOCK(drives_lock); -static DEFINE_SPINLOCK(drivers_lock); -static LIST_HEAD(drivers); - -/* Iterator for the driver list. */ - -static void *m_start(struct seq_file *m, loff_t *pos) -{ - struct list_head *p; - loff_t l = *pos; - spin_lock(&drivers_lock); - list_for_each(p, &drivers) - if (!l--) - return list_entry(p, ide_driver_t, drivers); - return NULL; -} - -static void *m_next(struct seq_file *m, void *v, loff_t *pos) -{ - struct list_head *p = ((ide_driver_t *)v)->drivers.next; - (*pos)++; - return p==&drivers ? NULL : list_entry(p, ide_driver_t, drivers); -} - -static void m_stop(struct seq_file *m, void *v) -{ - spin_unlock(&drivers_lock); -} - -static int show_driver(struct seq_file *m, void *v) -{ - ide_driver_t *driver = v; - seq_printf(m, "%s version %s\n", driver->name, driver->version); - return 0; -} - -struct seq_operations ide_drivers_op = { - .start = m_start, - .next = m_next, - .stop = m_stop, - .show = show_driver -}; - #ifdef CONFIG_PROC_FS struct proc_dir_entry *proc_ide_root; - -static ide_proc_entry_t generic_subdriver_entries[] = { - { "capacity", S_IFREG|S_IRUGO, proc_ide_read_capacity, NULL }, - { NULL, 0, NULL, NULL } -}; #endif static struct resource* hwif_request_region(ide_hwif_t *hwif, @@ -644,7 +579,7 @@ void ide_unregister(unsigned int index) ide_hwif_t *hwif, *g; static ide_hwif_t tmp_hwif; /* protected by ide_cfg_sem */ ide_hwgroup_t *hwgroup; - int irq_count = 0, unit, i; + int irq_count = 0, unit; BUG_ON(index >= MAX_HWIFS); @@ -657,23 +592,22 @@ void ide_unregister(unsigned int index) goto abort; for (unit = 0; unit < MAX_DRIVES; ++unit) { drive = &hwif->drives[unit]; - if (!drive->present) + if (!drive->present) { + if (drive->devfs_name[0] != '\0') { + devfs_remove(drive->devfs_name); + drive->devfs_name[0] = '\0'; + } continue; - if (drive->usage || DRIVER(drive)->busy) - goto abort; - drive->dead = 1; + } + spin_unlock_irq(&ide_lock); + device_unregister(&drive->gendev); + wait_for_completion(&drive->gendev_rel_comp); + spin_lock_irq(&ide_lock); } hwif->present = 0; spin_unlock_irq(&ide_lock); - for (unit = 0; unit < MAX_DRIVES; ++unit) { - drive = &hwif->drives[unit]; - if (!drive->present) - continue; - DRIVER(drive)->cleanup(drive); - } - destroy_proc_ide_interface(hwif); hwgroup = hwif->hwgroup; @@ -701,44 +635,6 @@ void ide_unregister(unsigned int index) * Remove us from the hwgroup, and free * the hwgroup if we were the only member */ - for (i = 0; i < MAX_DRIVES; ++i) { - drive = &hwif->drives[i]; - if (drive->devfs_name[0] != '\0') { - devfs_remove(drive->devfs_name); - drive->devfs_name[0] = '\0'; - } - if (!drive->present) - continue; - if (drive == drive->next) { - /* special case: last drive from hwgroup. */ - BUG_ON(hwgroup->drive != drive); - hwgroup->drive = NULL; - } else { - ide_drive_t *walk; - - walk = hwgroup->drive; - while (walk->next != drive) - walk = walk->next; - walk->next = drive->next; - if (hwgroup->drive == drive) { - hwgroup->drive = drive->next; - hwgroup->hwif = HWIF(hwgroup->drive); - } - } - BUG_ON(hwgroup->drive == drive); - if (drive->id != NULL) { - kfree(drive->id); - drive->id = NULL; - } - drive->present = 0; - /* Messed up locking ... */ - spin_unlock_irq(&ide_lock); - blk_cleanup_queue(drive->queue); - device_unregister(&drive->gendev); - down(&drive->gendev_rel_sem); - spin_lock_irq(&ide_lock); - drive->queue = NULL; - } if (hwif->next == hwif) { BUG_ON(hwgroup->hwif != hwif); kfree(hwgroup); @@ -765,17 +661,12 @@ void ide_unregister(unsigned int index) /* More messed up locking ... */ spin_unlock_irq(&ide_lock); device_unregister(&hwif->gendev); - down(&hwif->gendev_rel_sem); + wait_for_completion(&hwif->gendev_rel_comp); /* * Remove us from the kernel's knowledge */ blk_unregister_region(MKDEV(hwif->major, 0), MAX_DRIVES<drives[i].disk; - hwif->drives[i].disk = NULL; - put_disk(disk); - } kfree(hwif->sg_table); unregister_blkdev(hwif->major, hwif->name); spin_lock_irq(&ide_lock); @@ -911,6 +802,7 @@ found: hwif->irq = hw->irq; hwif->noprobe = 0; hwif->chipset = hw->chipset; + hwif->gendev.parent = hw->dev; if (!initializing) { probe_hwif_init_with_fixup(hwif, fixup); @@ -939,7 +831,7 @@ EXPORT_SYMBOL(ide_register_hw); DECLARE_MUTEX(ide_setting_sem); /** - * ide_add_setting - add an ide setting option + * __ide_add_setting - add an ide setting option * @drive: drive to use * @name: setting name * @rw: true if the function is read write @@ -952,6 +844,7 @@ DECLARE_MUTEX(ide_setting_sem); * @div_factor: divison scale * @data: private data field * @set: setting + * @auto_remove: setting auto removal flag * * Removes the setting named from the device if it is present. * The function takes the settings_lock to protect against @@ -963,17 +856,16 @@ DECLARE_MUTEX(ide_setting_sem); * a driver is attached we assume the driver settings are auto * remove. */ - -int ide_add_setting (ide_drive_t *drive, const char *name, int rw, int read_ioctl, int write_ioctl, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set) + +static int __ide_add_setting(ide_drive_t *drive, const char *name, int rw, int read_ioctl, int write_ioctl, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set, int auto_remove) { ide_settings_t **p = (ide_settings_t **) &drive->settings, *setting = NULL; down(&ide_setting_sem); while ((*p) && strcmp((*p)->name, name) < 0) p = &((*p)->next); - if ((setting = kmalloc(sizeof(*setting), GFP_KERNEL)) == NULL) + if ((setting = kzalloc(sizeof(*setting), GFP_KERNEL)) == NULL) goto abort; - memset(setting, 0, sizeof(*setting)); if ((setting->name = kmalloc(strlen(name) + 1, GFP_KERNEL)) == NULL) goto abort; strcpy(setting->name, name); @@ -989,18 +881,22 @@ int ide_add_setting (ide_drive_t *drive, const char *name, int rw, int read_ioct setting->set = set; setting->next = *p; - if (drive->driver != &idedefault_driver) + if (auto_remove) setting->auto_remove = 1; *p = setting; up(&ide_setting_sem); return 0; abort: up(&ide_setting_sem); - if (setting) - kfree(setting); + kfree(setting); return -1; } +int ide_add_setting(ide_drive_t *drive, const char *name, int rw, int read_ioctl, int write_ioctl, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set) +{ + return __ide_add_setting(drive, name, rw, read_ioctl, write_ioctl, data_type, min, max, mul_factor, div_factor, data, set, 1); +} + EXPORT_SYMBOL(ide_add_setting); /** @@ -1290,17 +1186,17 @@ static int set_xfer_rate (ide_drive_t *drive, int arg) void ide_add_generic_settings (ide_drive_t *drive) { /* - * drive setting name read/write access read ioctl write ioctl data type min max mul_factor div_factor data pointer set function + * drive setting name read/write access read ioctl write ioctl data type min max mul_factor div_factor data pointer set function */ - ide_add_setting(drive, "io_32bit", drive->no_io_32bit ? SETTING_READ : SETTING_RW, HDIO_GET_32BIT, HDIO_SET_32BIT, TYPE_BYTE, 0, 1 + (SUPPORT_VLB_SYNC << 1), 1, 1, &drive->io_32bit, set_io_32bit); - ide_add_setting(drive, "keepsettings", SETTING_RW, HDIO_GET_KEEPSETTINGS, HDIO_SET_KEEPSETTINGS, TYPE_BYTE, 0, 1, 1, 1, &drive->keep_settings, NULL); - ide_add_setting(drive, "nice1", SETTING_RW, -1, -1, TYPE_BYTE, 0, 1, 1, 1, &drive->nice1, NULL); - ide_add_setting(drive, "pio_mode", SETTING_WRITE, -1, HDIO_SET_PIO_MODE, TYPE_BYTE, 0, 255, 1, 1, NULL, set_pio_mode); - ide_add_setting(drive, "unmaskirq", drive->no_unmask ? SETTING_READ : SETTING_RW, HDIO_GET_UNMASKINTR, HDIO_SET_UNMASKINTR, TYPE_BYTE, 0, 1, 1, 1, &drive->unmask, NULL); - ide_add_setting(drive, "using_dma", SETTING_RW, HDIO_GET_DMA, HDIO_SET_DMA, TYPE_BYTE, 0, 1, 1, 1, &drive->using_dma, set_using_dma); - ide_add_setting(drive, "init_speed", SETTING_RW, -1, -1, TYPE_BYTE, 0, 70, 1, 1, &drive->init_speed, NULL); - ide_add_setting(drive, "current_speed", SETTING_RW, -1, -1, TYPE_BYTE, 0, 70, 1, 1, &drive->current_speed, set_xfer_rate); - ide_add_setting(drive, "number", SETTING_RW, -1, -1, TYPE_BYTE, 0, 3, 1, 1, &drive->dn, NULL); + __ide_add_setting(drive, "io_32bit", drive->no_io_32bit ? SETTING_READ : SETTING_RW, HDIO_GET_32BIT, HDIO_SET_32BIT, TYPE_BYTE, 0, 1 + (SUPPORT_VLB_SYNC << 1), 1, 1, &drive->io_32bit, set_io_32bit, 0); + __ide_add_setting(drive, "keepsettings", SETTING_RW, HDIO_GET_KEEPSETTINGS, HDIO_SET_KEEPSETTINGS, TYPE_BYTE, 0, 1, 1, 1, &drive->keep_settings, NULL, 0); + __ide_add_setting(drive, "nice1", SETTING_RW, -1, -1, TYPE_BYTE, 0, 1, 1, 1, &drive->nice1, NULL, 0); + __ide_add_setting(drive, "pio_mode", SETTING_WRITE, -1, HDIO_SET_PIO_MODE, TYPE_BYTE, 0, 255, 1, 1, NULL, set_pio_mode, 0); + __ide_add_setting(drive, "unmaskirq", drive->no_unmask ? SETTING_READ : SETTING_RW, HDIO_GET_UNMASKINTR, HDIO_SET_UNMASKINTR, TYPE_BYTE, 0, 1, 1, 1, &drive->unmask, NULL, 0); + __ide_add_setting(drive, "using_dma", SETTING_RW, HDIO_GET_DMA, HDIO_SET_DMA, TYPE_BYTE, 0, 1, 1, 1, &drive->using_dma, set_using_dma, 0); + __ide_add_setting(drive, "init_speed", SETTING_RW, -1, -1, TYPE_BYTE, 0, 70, 1, 1, &drive->init_speed, NULL, 0); + __ide_add_setting(drive, "current_speed", SETTING_RW, -1, -1, TYPE_BYTE, 0, 70, 1, 1, &drive->current_speed, set_xfer_rate, 0); + __ide_add_setting(drive, "number", SETTING_RW, -1, -1, TYPE_BYTE, 0, 3, 1, 1, &drive->dn, NULL, 0); } /** @@ -1317,73 +1213,6 @@ int system_bus_clock (void) EXPORT_SYMBOL(system_bus_clock); -/* - * Locking is badly broken here - since way back. That sucker is - * root-only, but that's not an excuse... The real question is what - * exclusion rules do we want here. - */ -int ide_replace_subdriver (ide_drive_t *drive, const char *driver) -{ - if (!drive->present || drive->usage || drive->dead) - goto abort; - if (DRIVER(drive)->cleanup(drive)) - goto abort; - strlcpy(drive->driver_req, driver, sizeof(drive->driver_req)); - if (ata_attach(drive)) { - spin_lock(&drives_lock); - list_del_init(&drive->list); - spin_unlock(&drives_lock); - drive->driver_req[0] = 0; - ata_attach(drive); - } else { - drive->driver_req[0] = 0; - } - if (DRIVER(drive)!= &idedefault_driver && !strcmp(DRIVER(drive)->name, driver)) - return 0; -abort: - return 1; -} - -/** - * ata_attach - attach an ATA/ATAPI device - * @drive: drive to attach - * - * Takes a drive that is as yet not assigned to any midlayer IDE - * driver (or is assigned to the default driver) and figures out - * which driver would like to own it. If nobody claims the drive - * then it is automatically attached to the default driver used for - * unclaimed objects. - * - * A return of zero indicates attachment to a driver, of one - * attachment to the default driver. - * - * Takes drivers_lock. - */ - -int ata_attach(ide_drive_t *drive) -{ - struct list_head *p; - spin_lock(&drivers_lock); - list_for_each(p, &drivers) { - ide_driver_t *driver = list_entry(p, ide_driver_t, drivers); - if (!try_module_get(driver->owner)) - continue; - spin_unlock(&drivers_lock); - if (driver->attach(drive) == 0) { - module_put(driver->owner); - drive->gendev.driver = &driver->gen_driver; - return 0; - } - spin_lock(&drivers_lock); - module_put(driver->owner); - } - drive->gendev.driver = &idedefault_driver.gen_driver; - spin_unlock(&drivers_lock); - if(idedefault_driver.attach(drive) != 0) - panic("ide: default attach failed"); - return 1; -} - static int generic_ide_suspend(struct device *dev, pm_message_t state) { ide_drive_t *drive = dev->driver_data; @@ -1398,7 +1227,7 @@ static int generic_ide_suspend(struct device *dev, pm_message_t state) rq.special = &args; rq.pm = &rqpm; rqpm.pm_step = ide_pm_state_start_suspend; - rqpm.pm_state = state; + rqpm.pm_state = state.event; return ide_do_drive_cmd(drive, &rq, ide_wait); } @@ -1417,16 +1246,16 @@ static int generic_ide_resume(struct device *dev) rq.special = &args; rq.pm = &rqpm; rqpm.pm_step = ide_pm_state_start_resume; - rqpm.pm_state = 0; + rqpm.pm_state = PM_EVENT_ON; return ide_do_drive_cmd(drive, &rq, ide_head_wait); } -int generic_ide_ioctl(struct file *file, struct block_device *bdev, +int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device *bdev, unsigned int cmd, unsigned long arg) { - ide_drive_t *drive = bdev->bd_disk->private_data; ide_settings_t *setting; + ide_driver_t *drv; int err = 0; void __user *p = (void __user *)arg; @@ -1448,19 +1277,6 @@ int generic_ide_ioctl(struct file *file, struct block_device *bdev, up(&ide_setting_sem); switch (cmd) { - case HDIO_GETGEO: - { - struct hd_geometry geom; - if (!p || (drive->media != ide_disk && drive->media != ide_floppy)) return -EINVAL; - geom.heads = drive->bios_head; - geom.sectors = drive->bios_sect; - geom.cylinders = (u16)drive->bios_cyl; /* truncate */ - geom.start = get_start_sect(bdev); - if (copy_to_user(p, &geom, sizeof(struct hd_geometry))) - return -EFAULT; - return 0; - } - case HDIO_OBSOLETE_IDENTITY: case HDIO_GET_IDENTITY: if (bdev != bdev->bd_contains) @@ -1526,7 +1342,8 @@ int generic_ide_ioctl(struct file *file, struct block_device *bdev, if (arg != (arg & ((1 << IDE_NICE_DSC_OVERLAP) | (1 << IDE_NICE_1)))) return -EPERM; drive->dsc_overlap = (arg >> IDE_NICE_DSC_OVERLAP) & 1; - if (drive->dsc_overlap && !DRIVER(drive)->supports_dsc_overlap) { + drv = *(ide_driver_t **)bdev->bd_disk->private_data; + if (drive->dsc_overlap && !drv->supports_dsc_overlap) { drive->dsc_overlap = 0; return -EPERM; } @@ -1751,6 +1568,8 @@ static int __init ide_setup(char *s) case -4: /* "cdrom" */ drive->present = 1; drive->media = ide_cdrom; + /* an ATAPI device ignores DRDY */ + drive->ready_stat = 0; hwif->noprobe = 0; goto done; case -5: /* "serialize" */ @@ -1777,6 +1596,7 @@ static int __init ide_setup(char *s) goto done; case 3: /* cyl,head,sect */ drive->media = ide_disk; + drive->ready_stat = READY_STAT; drive->cyl = drive->bios_cyl = vals[0]; drive->head = drive->bios_head = vals[1]; drive->sect = drive->bios_sect = vals[2]; @@ -2022,99 +1842,11 @@ static void __init probe_for_hwifs (void) #endif } -static ide_startstop_t default_do_request (ide_drive_t *drive, struct request *rq, sector_t block) +void ide_register_subdriver(ide_drive_t *drive, ide_driver_t *driver) { - ide_end_request(drive, 0, 0); - return ide_stopped; -} - -static int default_end_request (ide_drive_t *drive, int uptodate, int nr_sects) -{ - return ide_end_request(drive, uptodate, nr_sects); -} - -static ide_startstop_t -default_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err) -{ - return __ide_error(drive, rq, stat, err); -} - -static void default_pre_reset (ide_drive_t *drive) -{ -} - -static sector_t default_capacity (ide_drive_t *drive) -{ - return 0x7fffffff; -} - -static ide_startstop_t default_special (ide_drive_t *drive) -{ - special_t *s = &drive->special; - - s->all = 0; - drive->mult_req = 0; - return ide_stopped; -} - -static ide_startstop_t default_abort(ide_drive_t *drive, struct request *rq) -{ - return __ide_abort(drive, rq); -} - -static ide_startstop_t default_start_power_step(ide_drive_t *drive, - struct request *rq) -{ - rq->pm->pm_step = ide_pm_state_completed; - return ide_stopped; -} - -static void setup_driver_defaults (ide_driver_t *d) -{ - BUG_ON(d->attach == NULL || d->cleanup == NULL); - - if (d->do_request == NULL) d->do_request = default_do_request; - if (d->end_request == NULL) d->end_request = default_end_request; - if (d->error == NULL) d->error = default_error; - if (d->abort == NULL) d->abort = default_abort; - if (d->pre_reset == NULL) d->pre_reset = default_pre_reset; - if (d->capacity == NULL) d->capacity = default_capacity; - if (d->special == NULL) d->special = default_special; - if (d->start_power_step == NULL) - d->start_power_step = default_start_power_step; -} - -int ide_register_subdriver(ide_drive_t *drive, ide_driver_t *driver) -{ - unsigned long flags; - - BUG_ON(!drive->driver); - - spin_lock_irqsave(&ide_lock, flags); - if (!drive->present || drive->driver != &idedefault_driver || - drive->usage || drive->dead) { - spin_unlock_irqrestore(&ide_lock, flags); - return 1; - } - drive->driver = driver; - spin_unlock_irqrestore(&ide_lock, flags); - spin_lock(&drives_lock); - list_add_tail(&drive->list, &driver->drives); - spin_unlock(&drives_lock); -// printk(KERN_INFO "%s: attached %s driver.\n", drive->name, driver->name); - if ((drive->autotune == IDE_TUNE_DEFAULT) || - (drive->autotune == IDE_TUNE_AUTO)) { - /* DMA timings and setup moved to ide-probe.c */ - drive->dsc_overlap = (drive->next != drive && driver->supports_dsc_overlap); - drive->nice1 = 1; - } #ifdef CONFIG_PROC_FS - if (drive->driver != &idedefault_driver) { - ide_add_proc_entries(drive->proc, generic_subdriver_entries, drive); - ide_add_proc_entries(drive->proc, driver->proc, drive); - } + ide_add_proc_entries(drive->proc, driver->proc, drive); #endif - return 0; } EXPORT_SYMBOL(ide_register_subdriver); @@ -2122,146 +1854,142 @@ EXPORT_SYMBOL(ide_register_subdriver); /** * ide_unregister_subdriver - disconnect drive from driver * @drive: drive to unplug + * @driver: driver * * Disconnect a drive from the driver it was attached to and then * clean up the various proc files and other objects attached to it. * - * Takes ide_setting_sem, ide_lock and drives_lock. + * Takes ide_setting_sem and ide_lock. * Caller must hold none of the locks. - * - * No locking versus subdriver unload because we are moving to the - * default driver anyway. Wants double checking. */ -int ide_unregister_subdriver (ide_drive_t *drive) +void ide_unregister_subdriver(ide_drive_t *drive, ide_driver_t *driver) { unsigned long flags; down(&ide_setting_sem); spin_lock_irqsave(&ide_lock, flags); - if (drive->usage || drive->driver == &idedefault_driver || DRIVER(drive)->busy) { - spin_unlock_irqrestore(&ide_lock, flags); - up(&ide_setting_sem); - return 1; - } #ifdef CONFIG_PROC_FS - ide_remove_proc_entries(drive->proc, DRIVER(drive)->proc); - ide_remove_proc_entries(drive->proc, generic_subdriver_entries); + ide_remove_proc_entries(drive->proc, driver->proc); #endif auto_remove_settings(drive); - drive->driver = &idedefault_driver; spin_unlock_irqrestore(&ide_lock, flags); up(&ide_setting_sem); - spin_lock(&drives_lock); - list_del_init(&drive->list); - spin_unlock(&drives_lock); - /* drive will be added to &idedefault_driver->drives in ata_attach() */ - return 0; } EXPORT_SYMBOL(ide_unregister_subdriver); -static int ide_drive_remove(struct device * dev) +/* + * Probe module + */ + +EXPORT_SYMBOL(ide_lock); + +static int ide_bus_match(struct device *dev, struct device_driver *drv) { - ide_drive_t * drive = container_of(dev,ide_drive_t,gendev); - DRIVER(drive)->cleanup(drive); - return 0; + return 1; } -/** - * ide_register_driver - register IDE device driver - * @driver: the IDE device driver - * - * Register a new device driver and then scan the devices - * on the IDE bus in case any should be attached to the - * driver we have just registered. If so attach them. - * - * Takes drivers_lock and drives_lock. - */ - -int ide_register_driver(ide_driver_t *driver) +static char *media_string(ide_drive_t *drive) { - struct list_head list; - struct list_head *list_loop; - struct list_head *tmp_storage; - - setup_driver_defaults(driver); - - spin_lock(&drivers_lock); - list_add(&driver->drivers, &drivers); - spin_unlock(&drivers_lock); - - INIT_LIST_HEAD(&list); - spin_lock(&drives_lock); - list_splice_init(&idedefault_driver.drives, &list); - spin_unlock(&drives_lock); - - list_for_each_safe(list_loop, tmp_storage, &list) { - ide_drive_t *drive = container_of(list_loop, ide_drive_t, list); - list_del_init(&drive->list); - if (drive->present) - ata_attach(drive); + switch (drive->media) { + case ide_disk: + return "disk"; + case ide_cdrom: + return "cdrom"; + case ide_tape: + return "tape"; + case ide_floppy: + return "floppy"; + default: + return "UNKNOWN"; } - driver->gen_driver.name = (char *) driver->name; - driver->gen_driver.bus = &ide_bus_type; - driver->gen_driver.remove = ide_drive_remove; - return driver_register(&driver->gen_driver); } -EXPORT_SYMBOL(ide_register_driver); +static ssize_t media_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + ide_drive_t *drive = to_ide_device(dev); + return sprintf(buf, "%s\n", media_string(drive)); +} -/** - * ide_unregister_driver - unregister IDE device driver - * @driver: the IDE device driver - * - * Called when a driver module is being unloaded. We reattach any - * devices to whatever driver claims them next (typically the default - * driver). - * - * Takes drivers_lock and called functions will take ide_setting_sem. - */ +static ssize_t drivename_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + ide_drive_t *drive = to_ide_device(dev); + return sprintf(buf, "%s\n", drive->name); +} -void ide_unregister_driver(ide_driver_t *driver) +static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, char *buf) { - ide_drive_t *drive; + ide_drive_t *drive = to_ide_device(dev); + return sprintf(buf, "ide:m-%s\n", media_string(drive)); +} - spin_lock(&drivers_lock); - list_del(&driver->drivers); - spin_unlock(&drivers_lock); +static struct device_attribute ide_dev_attrs[] = { + __ATTR_RO(media), + __ATTR_RO(drivename), + __ATTR_RO(modalias), + __ATTR_NULL +}; - driver_unregister(&driver->gen_driver); +static int ide_uevent(struct device *dev, char **envp, int num_envp, + char *buffer, int buffer_size) +{ + ide_drive_t *drive = to_ide_device(dev); + int i = 0; + int length = 0; + + add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, + "MEDIA=%s", media_string(drive)); + add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, + "DRIVENAME=%s", drive->name); + add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, + "MODALIAS=ide:m-%s", media_string(drive)); + envp[i] = NULL; + return 0; +} - while(!list_empty(&driver->drives)) { - drive = list_entry(driver->drives.next, ide_drive_t, list); - if (driver->cleanup(drive)) { - printk(KERN_ERR "%s: cleanup_module() called while still busy\n", drive->name); - BUG(); - } - ata_attach(drive); - } +static int generic_ide_probe(struct device *dev) +{ + ide_drive_t *drive = to_ide_device(dev); + ide_driver_t *drv = to_ide_driver(dev->driver); + + return drv->probe ? drv->probe(drive) : -ENODEV; } -EXPORT_SYMBOL(ide_unregister_driver); +static int generic_ide_remove(struct device *dev) +{ + ide_drive_t *drive = to_ide_device(dev); + ide_driver_t *drv = to_ide_driver(dev->driver); -struct block_device_operations ide_fops[] = {{ - .owner = THIS_MODULE, - .open = ide_open, -}}; + if (drv->remove) + drv->remove(drive); -EXPORT_SYMBOL(ide_fops); + return 0; +} -/* - * Probe module - */ +static void generic_ide_shutdown(struct device *dev) +{ + ide_drive_t *drive = to_ide_device(dev); + ide_driver_t *drv = to_ide_driver(dev->driver); -EXPORT_SYMBOL(ide_lock); + if (dev->driver && drv->shutdown) + drv->shutdown(drive); +} struct bus_type ide_bus_type = { .name = "ide", + .match = ide_bus_match, + .uevent = ide_uevent, + .probe = generic_ide_probe, + .remove = generic_ide_remove, + .shutdown = generic_ide_shutdown, + .dev_attrs = ide_dev_attrs, .suspend = generic_ide_suspend, .resume = generic_ide_resume, }; +EXPORT_SYMBOL_GPL(ide_bus_type); + /* * This is gets invoked once during initialization, to set *everything* up */ @@ -2330,7 +2058,7 @@ static void __init parse_options (char *line) } } -int init_module (void) +int __init init_module (void) { parse_options(options); return ide_init();