bk://bart.bkbits.net/ide-dev-2.6 bzolnier@trik.(none)|ChangeSet|20050203204718|55262 bzolnier # This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2005/02/03 21:47:18+01:00 bzolnier@trik.(none) # [ide] fix via82cxxx resume failure # # With David Woodhouse . # # On resume from sleep, via_set_speed() doesn't reinstate the correct # mode, because it thinks the drive is already configured correctly. # # Also kill redundant printk, ide_config_drive_speed() warns about errors. # # drivers/ide/pci/via82cxxx.c # 2005/02/03 21:47:05+01:00 bzolnier@trik.(none) +2 -5 # [ide] fix via82cxxx resume failure # # ChangeSet # 2005/02/03 21:20:52+01:00 bzolnier@trik.(none) # [ide] ide-scsi: add basic refcounting # # * pointers to a SCSI host and a drive are added to idescsi_scsi_t # * pointer to the SCSI host is stored in disk->private_data # * ide_scsi_{get,put}() is used to {get,put} reference to the SCSI host # # drivers/scsi/ide-scsi.c # 2005/01/21 23:41:42+01:00 bzolnier@trik.(none) +58 -11 # [ide] ide-scsi: add basic refcounting # # ChangeSet # 2005/02/03 21:19:36+01:00 bzolnier@trik.(none) # [ide] ide-tape: add basic refcounting # # Similar changes as for ide-cd.c. # # drivers/ide/ide-tape.c # 2005/01/21 23:41:25+01:00 bzolnier@trik.(none) +80 -14 # [ide] ide-tape: add basic refcounting # # ChangeSet # 2005/02/03 21:18:37+01:00 bzolnier@trik.(none) # [ide] ide-floppy: add basic refcounting # # Similar changes as for ide-cd.c. # # drivers/ide/ide-floppy.c # 2005/01/21 23:41:14+01:00 bzolnier@trik.(none) +90 -25 # [ide] ide-floppy: add basic refcounting # # ChangeSet # 2005/02/03 21:17:26+01:00 bzolnier@trik.(none) # [ide] ide-disk: add basic refcounting # # Similar changes as for ide-cd.c (except that struct ide_disk_obj is added). # # drivers/ide/ide-disk.c # 2005/01/21 23:41:03+01:00 bzolnier@trik.(none) +88 -9 # [ide] ide-disk: add basic refcounting # # ChangeSet # 2005/02/03 21:15:21+01:00 bzolnier@trik.(none) # [ide] ide-cd: add basic refcounting # # * based on reference counting in drivers/scsi/{sd,sr}.c # * fixes race between ->open() and ->cleanup() (ide_unregister_subdriver() # tests for drive->usage != 0 but there is no protection against new users) # * struct kref and pointer to a drive are added to struct ide_cdrom_info # * pointer to drive's struct ide_cdrom_info is stored in disk->private_data # * ide_cd_{get,put}() is used to {get,put} reference to struct ide_cdrom_info # * ide_cd_release() is a release method for struct ide_cdrom_info # # drivers/ide/ide-cd.h # 2005/01/21 23:40:52+01:00 bzolnier@trik.(none) +2 -0 # [ide] ide-cd: add basic refcounting # # drivers/ide/ide-cd.c # 2005/01/21 23:40:52+01:00 bzolnier@trik.(none) +80 -19 # [ide] ide-cd: add basic refcounting # # ChangeSet # 2005/02/03 21:13:29+01:00 bzolnier@trik.(none) # [ide] make ide_generic_ioctl() take ide_drive_t * as an argument # # As a result disk->private_data can be used by device drivers now. # # include/linux/ide.h # 2005/01/21 22:30:19+01:00 bzolnier@trik.(none) +1 -1 # [ide] make ide_generic_ioctl() take ide_drive_t * as an argument # # drivers/scsi/ide-scsi.c # 2005/01/21 22:30:19+01:00 bzolnier@trik.(none) +2 -1 # [ide] make ide_generic_ioctl() take ide_drive_t * as an argument # # drivers/ide/ide.c # 2005/01/21 22:30:19+01:00 bzolnier@trik.(none) +1 -2 # [ide] make ide_generic_ioctl() take ide_drive_t * as an argument # # drivers/ide/ide-tape.c # 2005/01/21 22:30:19+01:00 bzolnier@trik.(none) +1 -1 # [ide] make ide_generic_ioctl() take ide_drive_t * as an argument # # drivers/ide/ide-floppy.c # 2005/01/21 22:30:19+01:00 bzolnier@trik.(none) +1 -1 # [ide] make ide_generic_ioctl() take ide_drive_t * as an argument # # drivers/ide/ide-disk.c # 2005/01/21 22:30:19+01:00 bzolnier@trik.(none) +2 -1 # [ide] make ide_generic_ioctl() take ide_drive_t * as an argument # # drivers/ide/ide-cd.c # 2005/01/21 22:30:19+01:00 bzolnier@trik.(none) +1 -1 # [ide] make ide_generic_ioctl() take ide_drive_t * as an argument # # ChangeSet # 2005/02/03 21:08:15+01:00 bzolnier@trik.(none) # [ide] kill setup_driver_defaults() # # * move default_do_request() to ide-default.c # * fix drivers to set ide_driver_t->{do_request,end_request,error,abort} # * kill setup_driver_defaults() # # drivers/ide/ide.c # 2005/01/21 22:27:18+01:00 bzolnier@trik.(none) +0 -37 # [ide] kill setup_driver_defaults() # # drivers/ide/ide-tape.c # 2005/01/21 22:27:18+01:00 bzolnier@trik.(none) +2 -0 # [ide] kill setup_driver_defaults() # # drivers/ide/ide-io.c # 2005/01/21 22:27:18+01:00 bzolnier@trik.(none) +4 -0 # [ide] kill setup_driver_defaults() # # drivers/ide/ide-floppy.c # 2005/01/21 22:27:18+01:00 bzolnier@trik.(none) +2 -0 # [ide] kill setup_driver_defaults() # # drivers/ide/ide-disk.c # 2005/01/21 22:27:18+01:00 bzolnier@trik.(none) +3 -0 # [ide] kill setup_driver_defaults() # # drivers/ide/ide-default.c # 2005/01/21 22:27:18+01:00 bzolnier@trik.(none) +10 -0 # [ide] kill setup_driver_defaults() # # drivers/ide/ide-cd.c # 2005/01/21 22:27:18+01:00 bzolnier@trik.(none) +3 -0 # [ide] kill setup_driver_defaults() # # ChangeSet # 2005/02/03 21:04:06+01:00 bzolnier@trik.(none) # [ide] kill ide_driver_t->capacity # # * add private /proc/ide/hd?/capacity handlers to ide-{cd,disk,floppy}.c # * use generic proc_ide_read_capacity() for ide-{scsi,tape}.c # * kill ->capacity, default_capacity() and generic_subdriver_entries[] # # include/linux/ide.h # 2005/01/21 22:23:17+01:00 bzolnier@trik.(none) +0 -1 # [ide] kill ide_driver_t->capacity # # drivers/scsi/ide-scsi.c # 2005/01/21 22:23:17+01:00 bzolnier@trik.(none) +10 -0 # [ide] kill ide_driver_t->capacity # # drivers/ide/ide.c # 2005/02/03 21:00:44+01:00 bzolnier@trik.(none) +1 -15 # [ide] kill ide_driver_t->capacity # # drivers/ide/ide-tape.c # 2005/01/21 22:23:17+01:00 bzolnier@trik.(none) +1 -0 # [ide] kill ide_driver_t->capacity # # drivers/ide/ide-proc.c # 2005/01/21 22:23:17+01:00 bzolnier@trik.(none) +3 -5 # [ide] kill ide_driver_t->capacity # # drivers/ide/ide-floppy.c # 2005/01/21 22:23:17+01:00 bzolnier@trik.(none) +11 -1 # [ide] kill ide_driver_t->capacity # # drivers/ide/ide-disk.c # 2005/01/21 22:23:17+01:00 bzolnier@trik.(none) +11 -1 # [ide] kill ide_driver_t->capacity # # drivers/ide/ide-cd.c # 2005/01/21 22:23:17+01:00 bzolnier@trik.(none) +20 -1 # [ide] kill ide_driver_t->capacity # # ChangeSet # 2005/02/03 20:44:44+01:00 bzolnier@trik.(none) # Merge # # include/linux/ide.h # 2005/02/03 20:44:41+01:00 bzolnier@trik.(none) +0 -0 # SCCS merged # # drivers/ide/ide-iops.c # 2005/02/03 20:44:41+01:00 bzolnier@trik.(none) +0 -0 # SCCS merged # # drivers/scsi/ide-scsi.c # 2005/02/03 20:37:17+01:00 bzolnier@trik.(none) +0 -0 # Auto merged # # drivers/ide/ide.c # 2005/02/03 20:37:17+01:00 bzolnier@trik.(none) +0 -0 # Auto merged # # drivers/ide/ide-taskfile.c # 2005/02/03 20:37:17+01:00 bzolnier@trik.(none) +0 -0 # Auto merged # # drivers/ide/ide-tape.c # 2005/02/03 20:37:17+01:00 bzolnier@trik.(none) +0 -0 # Auto merged # # drivers/ide/ide-probe.c # 2005/02/03 20:37:17+01:00 bzolnier@trik.(none) +0 -0 # Auto merged # # drivers/ide/ide-io.c # 2005/02/03 20:37:17+01:00 bzolnier@trik.(none) +0 -0 # Auto merged # # drivers/ide/ide-floppy.c # 2005/02/03 20:37:17+01:00 bzolnier@trik.(none) +0 -0 # Auto merged # # drivers/ide/ide-disk.c # 2005/02/03 20:37:17+01:00 bzolnier@trik.(none) +0 -0 # Auto merged # # ChangeSet # 2005/01/21 20:25:56+01:00 bzolnier@trik.(none) # [ide] kill ide_driver_t->pre_reset # # Add ide_drive_t->post_reset flag and use it to signal post reset # condition to the ide-tape driver (the only user of ->pre_reset). # # include/linux/ide.h # 2005/01/21 20:13:35+01:00 bzolnier@trik.(none) +1 -1 # [ide] kill ide_driver_t->pre_reset # # drivers/ide/ide.c # 2005/01/21 20:13:35+01:00 bzolnier@trik.(none) +0 -5 # [ide] kill ide_driver_t->pre_reset # # drivers/ide/ide-tape.c # 2005/01/21 20:13:35+01:00 bzolnier@trik.(none) +5 -11 # [ide] kill ide_driver_t->pre_reset # # drivers/ide/ide-iops.c # 2005/01/21 20:13:35+01:00 bzolnier@trik.(none) +1 -1 # [ide] kill ide_driver_t->pre_reset # # ChangeSet # 2005/01/21 20:24:38+01:00 bzolnier@trik.(none) # [ide] fix some rare ide-default vs ide-disk races # # Some rare races between ide-default and ide-disk are possible, i.e.: # * ide-default is used, I/O request is triggered (ie. /proc/ide/hd?/identify), # drive->special is cleared silently (so CHS is not initialized properly), # ide-disk is loaded and fails if drive uses CHS # * ide-disk is used, drive is resetted, ide-disk is unloaded, ide-default # takes control over drive and on the first I/O request silently clears # drive->special without restoring settings # # Fix them by moving idedisk_{special,pre_reset}() and company to IDE core. # # include/linux/ide.h # 2005/01/21 20:13:47+01:00 bzolnier@trik.(none) +0 -1 # [ide] fix some rare ide-default vs ide-disk races # # drivers/ide/ide.c # 2005/01/21 20:13:47+01:00 bzolnier@trik.(none) +0 -10 # [ide] fix some rare ide-default vs ide-disk races # # drivers/ide/ide-taskfile.c # 2005/01/21 20:13:47+01:00 bzolnier@trik.(none) +0 -6 # [ide] fix some rare ide-default vs ide-disk races # # drivers/ide/ide-probe.c # 2005/01/21 20:13:47+01:00 bzolnier@trik.(none) +58 -2 # [ide] fix some rare ide-default vs ide-disk races # # drivers/ide/ide-iops.c # 2005/01/21 20:13:47+01:00 bzolnier@trik.(none) +19 -1 # [ide] fix some rare ide-default vs ide-disk races # # drivers/ide/ide-io.c # 2005/01/21 20:13:47+01:00 bzolnier@trik.(none) +66 -2 # [ide] fix some rare ide-default vs ide-disk races # # drivers/ide/ide-disk.c # 2005/01/21 20:13:47+01:00 bzolnier@trik.(none) +0 -108 # [ide] fix some rare ide-default vs ide-disk races # # drivers/ide/Kconfig # 2005/01/21 20:13:47+01:00 bzolnier@trik.(none) +0 -1 # [ide] fix some rare ide-default vs ide-disk races # # ChangeSet # 2005/01/21 20:23:26+01:00 bzolnier@trik.(none) # [ide] generic Power Management for IDE devices # # Move PM code from ide-cd.c and ide-disk.c to IDE core so: # * PM is supported for other ATAPI devices (floppy, tape) # * PM is supported even if specific driver is not loaded # # include/linux/ide.h # 2005/01/21 20:14:00+01:00 bzolnier@trik.(none) +0 -2 # [ide] generic Power Management for IDE devices # # drivers/ide/ide.c # 2005/01/21 20:14:00+01:00 bzolnier@trik.(none) +0 -9 # [ide] generic Power Management for IDE devices # # drivers/ide/ide-io.c # 2005/01/21 20:14:00+01:00 bzolnier@trik.(none) +89 -2 # [ide] generic Power Management for IDE devices # # drivers/ide/ide-disk.c # 2005/01/21 20:14:00+01:00 bzolnier@trik.(none) +0 -86 # [ide] generic Power Management for IDE devices # # drivers/ide/ide-cd.c # 2005/01/21 20:14:00+01:00 bzolnier@trik.(none) +0 -41 # [ide] generic Power Management for IDE devices # # ChangeSet # 2005/01/21 20:21:54+01:00 bzolnier@trik.(none) # [ide] fix drive->ready_stat for ATAPI # # ATAPI devices ignore DRDY bit so drive->ready_stat must be set to zero. # It is currently done by device drivers (including ide-default fake driver) # but for PMAC driver it is too late as wait_for_ready() may be called during # probe: probe_hwif()->pmac_ide_dma_check()->pmac_ide_{mdma,udma}_enable()-> # ->pmac_ide_do_setfeature()->wait_for_ready(). # # Fixup drive->ready_stat just after detecting ATAPI device. # # drivers/scsi/ide-scsi.c # 2005/01/21 20:14:18+01:00 bzolnier@trik.(none) +0 -1 # [ide] fix drive->ready_stat for ATAPI # # drivers/ide/ide.c # 2005/01/21 20:14:18+01:00 bzolnier@trik.(none) +2 -0 # [ide] fix drive->ready_stat for ATAPI # # drivers/ide/ide-tape.c # 2005/01/21 20:14:18+01:00 bzolnier@trik.(none) +0 -2 # [ide] fix drive->ready_stat for ATAPI # # drivers/ide/ide-probe.c # 2005/01/21 20:14:18+01:00 bzolnier@trik.(none) +2 -0 # [ide] fix drive->ready_stat for ATAPI # # drivers/ide/ide-floppy.c # 2005/01/21 20:14:18+01:00 bzolnier@trik.(none) +0 -1 # [ide] fix drive->ready_stat for ATAPI # # drivers/ide/ide-default.c # 2005/01/21 20:14:18+01:00 bzolnier@trik.(none) +0 -7 # [ide] fix drive->ready_stat for ATAPI # # drivers/ide/ide-cd.c # 2005/01/21 20:14:18+01:00 bzolnier@trik.(none) +0 -1 # [ide] fix drive->ready_stat for ATAPI # # ChangeSet # 2005/01/21 20:20:25+01:00 bzolnier@trik.(none) # [ide] ignore BIOS enable bits for Promise controllers # # Since there are no Promise binary drivers for 2.6.x kernels: # * ignore BIOS enable bits completely # * remove CONFIG_PDC202XX_FORCE # * kill IDEPCI_FLAG_FORCE_PDC hack # # include/linux/ide.h # 2005/01/21 20:14:29+01:00 bzolnier@trik.(none) +0 -1 # [ide] ignore BIOS enable bits for Promise controllers # # drivers/ide/setup-pci.c # 2005/01/21 20:14:29+01:00 bzolnier@trik.(none) +1 -14 # [ide] ignore BIOS enable bits for Promise controllers # # drivers/ide/pci/pdc202xx_old.h # 2005/01/21 20:14:29+01:00 bzolnier@trik.(none) +0 -17 # [ide] ignore BIOS enable bits for Promise controllers # # drivers/ide/pci/pdc202xx_new.h # 2005/01/21 20:14:29+01:00 bzolnier@trik.(none) +0 -6 # [ide] ignore BIOS enable bits for Promise controllers # # drivers/ide/Kconfig # 2005/01/21 20:14:29+01:00 bzolnier@trik.(none) +0 -7 # [ide] ignore BIOS enable bits for Promise controllers # diff -Nru a/drivers/ide/Kconfig b/drivers/ide/Kconfig --- a/drivers/ide/Kconfig 2005-02-03 18:46:34 -08:00 +++ b/drivers/ide/Kconfig 2005-02-03 18:46:34 -08:00 @@ -150,7 +150,6 @@ config IDEDISK_MULTI_MODE bool "Use multi-mode by default" - depends on BLK_DEV_IDEDISK help If you get this error, try to say Y here: @@ -658,13 +657,6 @@ config BLK_DEV_PDC202XX_NEW tristate "PROMISE PDC202{68|69|70|71|75|76|77} support" - -# FIXME - probably wants to be one for old and for new -config PDC202XX_FORCE - bool "Enable controller even if disabled by BIOS" - depends on BLK_DEV_PDC202XX_NEW - help - Enable the PDC202xx controller even if it has been disabled in the BIOS setup. config BLK_DEV_SVWKS tristate "ServerWorks OSB4/CSB5/CSB6 chipsets support" diff -Nru a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c --- a/drivers/ide/ide-cd.c 2005-02-03 18:46:34 -08:00 +++ b/drivers/ide/ide-cd.c 2005-02-03 18:46:34 -08:00 @@ -324,6 +324,33 @@ #include "ide-cd.h" +static DECLARE_MUTEX(idecd_ref_sem); + +#define to_ide_cd(obj) container_of(obj, struct cdrom_info, kref) + +#define ide_cd_g(disk) ((disk)->private_data) + +static struct cdrom_info *ide_cd_get(struct gendisk *disk) +{ + struct cdrom_info *cd = NULL; + + down(&idecd_ref_sem); + cd = ide_cd_g(disk); + if (cd) + kref_get(&cd->kref); + up(&idecd_ref_sem); + return cd; +} + +static void ide_cd_release(struct kref *); + +static void ide_cd_put(struct cdrom_info *cd) +{ + down(&idecd_ref_sem); + kref_put(&cd->kref, ide_cd_release); + up(&idecd_ref_sem); +} + /**************************************************************************** * Generic packet command support and error handling routines. */ @@ -3088,7 +3115,6 @@ drive->queue->unplug_delay = 1; drive->special.all = 0; - drive->ready_stat = 0; CDROM_STATE_FLAGS(drive)->media_changed = 1; CDROM_STATE_FLAGS(drive)->toc_valid = 0; @@ -3226,14 +3252,27 @@ int ide_cdrom_cleanup(ide_drive_t *drive) { struct cdrom_info *info = drive->driver_data; - struct cdrom_device_info *devinfo = &info->devinfo; - struct gendisk *g = drive->disk; if (ide_unregister_subdriver(drive)) { printk(KERN_ERR "%s: %s: failed to ide_unregister_subdriver\n", __FUNCTION__, drive->name); return 1; } + + del_gendisk(drive->disk); + + ide_cd_put(info); + + return 0; +} + +static void ide_cd_release(struct kref *kref) +{ + struct cdrom_info *info = to_ide_cd(kref); + struct cdrom_device_info *devinfo = &info->devinfo; + ide_drive_t *drive = info->drive; + struct gendisk *g = drive->disk; + if (info->buffer != NULL) kfree(info->buffer); if (info->toc != NULL) @@ -3241,56 +3280,36 @@ if (info->changer_info != NULL) kfree(info->changer_info); if (devinfo->handle == drive && unregister_cdrom(devinfo)) - printk(KERN_ERR "%s: ide_cdrom_cleanup failed to unregister device from the cdrom driver.\n", drive->name); - kfree(info); + printk(KERN_ERR "%s: %s failed to unregister device from the cdrom " + "driver.\n", __FUNCTION__, drive->name); drive->driver_data = NULL; blk_queue_prep_rq(drive->queue, NULL); - del_gendisk(g); + g->private_data = NULL; g->fops = ide_fops; - return 0; + kfree(info); } static int ide_cdrom_attach (ide_drive_t *drive); -/* - * Power Management state machine. - * - * We don't do much for CDs right now. - */ - -static void ide_cdrom_complete_power_step (ide_drive_t *drive, struct request *rq, u8 stat, u8 error) -{ -} - -static ide_startstop_t ide_cdrom_start_power_step (ide_drive_t *drive, struct request *rq) +#ifdef CONFIG_PROC_FS +static int proc_idecd_read_capacity + (char *page, char **start, off_t off, int count, int *eof, void *data) { - ide_task_t *args = rq->special; - - memset(args, 0, sizeof(*args)); - - switch (rq->pm->pm_step) { - case ide_pm_state_start_suspend: - break; + ide_drive_t*drive = (ide_drive_t *)data; + int len; - case ide_pm_state_start_resume: /* Resume step 1 (restore DMA) */ - /* - * Right now, all we do is call hwif->ide_dma_check(drive), - * we could be smarter and check for current xfer_speed - * in struct drive etc... - * Also, this step could be implemented as a generic helper - * as most subdrivers will use it. - */ - if ((drive->id->capability & 1) == 0) - break; - if (HWIF(drive)->ide_dma_check == NULL) - break; - HWIF(drive)->ide_dma_check(drive); - break; - } - rq->pm->pm_step = ide_pm_state_completed; - return ide_stopped; + len = sprintf(page,"%llu\n", (long long)ide_cdrom_capacity(drive)); + PROC_IDE_READ_RETURN(page,start,off,count,eof,len); } +static ide_proc_entry_t idecd_proc[] = { + { "capacity", S_IFREG|S_IRUGO, proc_idecd_read_capacity, NULL }, + { NULL, 0, NULL, NULL } +}; +#else +# define idecd_proc NULL +#endif + static ide_driver_t ide_cdrom_driver = { .owner = THIS_MODULE, .name = "ide-cdrom", @@ -3300,18 +3319,26 @@ .supports_dsc_overlap = 1, .cleanup = ide_cdrom_cleanup, .do_request = ide_do_rw_cdrom, - .capacity = ide_cdrom_capacity, + .end_request = ide_end_request, + .error = __ide_error, + .abort = __ide_abort, + .proc = idecd_proc, .attach = ide_cdrom_attach, .drives = LIST_HEAD_INIT(ide_cdrom_driver.drives), - .start_power_step = ide_cdrom_start_power_step, - .complete_power_step = ide_cdrom_complete_power_step, }; static int idecd_open(struct inode * inode, struct file * file) { - ide_drive_t *drive = inode->i_bdev->bd_disk->private_data; - struct cdrom_info *info = drive->driver_data; + struct gendisk *disk = inode->i_bdev->bd_disk; + struct cdrom_info *info; + ide_drive_t *drive; int rc = -ENOMEM; + + if (!(info = ide_cd_get(disk))) + return -ENXIO; + + drive = info->drive; + drive->usage++; if (!info->buffer) @@ -3319,16 +3346,24 @@ GFP_KERNEL|__GFP_REPEAT); if (!info->buffer || (rc = cdrom_open(&info->devinfo, inode, file))) drive->usage--; + + if (rc < 0) + ide_cd_put(info); + return rc; } static int idecd_release(struct inode * inode, struct file * file) { - ide_drive_t *drive = inode->i_bdev->bd_disk->private_data; - struct cdrom_info *info = drive->driver_data; + struct gendisk *disk = inode->i_bdev->bd_disk; + struct cdrom_info *info = ide_cd_g(disk); + ide_drive_t *drive = info->drive; cdrom_release (&info->devinfo, file); drive->usage--; + + ide_cd_put(info); + return 0; } @@ -3336,27 +3371,27 @@ unsigned int cmd, unsigned long arg) { struct block_device *bdev = inode->i_bdev; - ide_drive_t *drive = bdev->bd_disk->private_data; - int err = generic_ide_ioctl(file, bdev, cmd, arg); - if (err == -EINVAL) { - struct cdrom_info *info = drive->driver_data; + struct cdrom_info *info = ide_cd_g(bdev->bd_disk); + int err; + + err = generic_ide_ioctl(info->drive, file, bdev, cmd, arg); + if (err == -EINVAL) err = cdrom_ioctl(file, &info->devinfo, inode, cmd, arg); - } + return err; } static int idecd_media_changed(struct gendisk *disk) { - ide_drive_t *drive = disk->private_data; - struct cdrom_info *info = drive->driver_data; + struct cdrom_info *info = ide_cd_g(disk); return cdrom_media_changed(&info->devinfo); } static int idecd_revalidate_disk(struct gendisk *disk) { - ide_drive_t *drive = disk->private_data; + struct cdrom_info *info = ide_cd_g(disk); struct request_sense sense; - cdrom_read_toc(drive, &sense); + cdrom_read_toc(info->drive, &sense); return 0; } @@ -3410,7 +3445,12 @@ goto failed; } memset(info, 0, sizeof (struct cdrom_info)); + + kref_init(&info->kref); + + info->drive = drive; drive->driver_data = info; + DRIVER(drive)->busy++; g->minors = 1; snprintf(g->devfs_name, sizeof(g->devfs_name), @@ -3437,6 +3477,7 @@ cdrom_read_toc(drive, &sense); g->fops = &idecd_ops; + g->private_data = info; g->flags |= GENHD_FL_REMOVABLE; add_disk(g); return 0; diff -Nru a/drivers/ide/ide-cd.h b/drivers/ide/ide-cd.h --- a/drivers/ide/ide-cd.h 2005-02-03 18:46:34 -08:00 +++ b/drivers/ide/ide-cd.h 2005-02-03 18:46:34 -08:00 @@ -460,6 +460,8 @@ /* Extra per-device info for cdrom drives. */ struct cdrom_info { + ide_drive_t *drive; + struct kref kref; /* Buffer for table of contents. NULL if we haven't allocated a TOC buffer for this device yet. */ diff -Nru a/drivers/ide/ide-default.c b/drivers/ide/ide-default.c --- a/drivers/ide/ide-default.c 2005-02-03 18:46:34 -08:00 +++ b/drivers/ide/ide-default.c 2005-02-03 18:46:34 -08:00 @@ -38,6 +38,12 @@ static int idedefault_attach(ide_drive_t *drive); +static ide_startstop_t idedefault_do_request(ide_drive_t *drive, struct request *rq, sector_t block) +{ + ide_end_request(drive, 0, 0); + return ide_stopped; +} + /* * IDE subdriver functions, registered with ide.c */ @@ -47,6 +53,10 @@ .version = IDEDEFAULT_VERSION, .attach = idedefault_attach, .cleanup = ide_unregister_subdriver, + .do_request = idedefault_do_request, + .end_request = ide_end_request, + .error = __ide_error, + .abort = __ide_abort, .drives = LIST_HEAD_INIT(idedefault_driver.drives) }; @@ -57,13 +67,6 @@ "driver with ide.c\n", drive->name); return 1; } - - /* For the sake of the request layer, we must make sure we have a - * correct ready_stat value, that is 0 for ATAPI devices or we will - * fail any request like Power Management - */ - if (drive->media != ide_disk) - drive->ready_stat = 0; return 0; } diff -Nru a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c --- a/drivers/ide/ide-disk.c 2005-02-03 18:46:34 -08:00 +++ b/drivers/ide/ide-disk.c 2005-02-03 18:46:34 -08:00 @@ -71,6 +71,38 @@ #include #include +struct ide_disk_obj { + ide_drive_t *drive; + struct kref kref; +}; + +static DECLARE_MUTEX(idedisk_ref_sem); + +#define to_ide_disk(obj) container_of(obj, struct ide_disk_obj, kref) + +#define ide_disk_g(disk) ((disk)->private_data) + +static struct ide_disk_obj *ide_disk_get(struct gendisk *disk) +{ + struct ide_disk_obj *idkp = NULL; + + down(&idedisk_ref_sem); + idkp = ide_disk_g(disk); + if (idkp) + kref_get(&idkp->kref); + up(&idedisk_ref_sem); + return idkp; +} + +static void ide_disk_release(struct kref *); + +static void ide_disk_put(struct ide_disk_obj *idkp) +{ + down(&idedisk_ref_sem); + kref_put(&idkp->kref, ide_disk_release); + up(&idedisk_ref_sem); +} + /* * lba_capacity_is_ok() performs a sanity check on the claimed "lba_capacity" * value for this drive (from its reported identification information). @@ -516,75 +548,6 @@ return drive->capacity64 - drive->sect0; } -#define IS_PDC4030_DRIVE 0 - -static ide_startstop_t idedisk_special (ide_drive_t *drive) -{ - special_t *s = &drive->special; - - if (s->b.set_geometry) { - s->b.set_geometry = 0; - if (!IS_PDC4030_DRIVE) { - ide_task_t args; - memset(&args, 0, sizeof(ide_task_t)); - args.tfRegister[IDE_NSECTOR_OFFSET] = drive->sect; - args.tfRegister[IDE_SECTOR_OFFSET] = drive->sect; - args.tfRegister[IDE_LCYL_OFFSET] = drive->cyl; - args.tfRegister[IDE_HCYL_OFFSET] = drive->cyl>>8; - args.tfRegister[IDE_SELECT_OFFSET] = ((drive->head-1)|drive->select.all)&0xBF; - args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SPECIFY; - args.command_type = IDE_DRIVE_TASK_NO_DATA; - args.handler = &set_geometry_intr; - do_rw_taskfile(drive, &args); - } - } else if (s->b.recalibrate) { - s->b.recalibrate = 0; - if (!IS_PDC4030_DRIVE) { - ide_task_t args; - memset(&args, 0, sizeof(ide_task_t)); - args.tfRegister[IDE_NSECTOR_OFFSET] = drive->sect; - args.tfRegister[IDE_COMMAND_OFFSET] = WIN_RESTORE; - args.command_type = IDE_DRIVE_TASK_NO_DATA; - args.handler = &recal_intr; - do_rw_taskfile(drive, &args); - } - } else if (s->b.set_multmode) { - s->b.set_multmode = 0; - if (drive->mult_req > drive->id->max_multsect) - drive->mult_req = drive->id->max_multsect; - if (!IS_PDC4030_DRIVE) { - ide_task_t args; - memset(&args, 0, sizeof(ide_task_t)); - args.tfRegister[IDE_NSECTOR_OFFSET] = drive->mult_req; - args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SETMULT; - args.command_type = IDE_DRIVE_TASK_NO_DATA; - args.handler = &set_multmode_intr; - do_rw_taskfile(drive, &args); - } - } else if (s->all) { - int special = s->all; - s->all = 0; - printk(KERN_ERR "%s: bad special flag: 0x%02x\n", drive->name, special); - return ide_stopped; - } - return IS_PDC4030_DRIVE ? ide_stopped : ide_started; -} - -static void idedisk_pre_reset (ide_drive_t *drive) -{ - int legacy = (drive->id->cfs_enable_2 & 0x0400) ? 0 : 1; - - drive->special.all = 0; - drive->special.b.set_geometry = legacy; - drive->special.b.recalibrate = legacy; - if (OK_TO_RESET_CONTROLLER) - drive->mult_count = 0; - if (!drive->keep_settings && !drive->using_dma) - drive->mult_req = 0; - if (drive->mult_req != drive->mult_count) - drive->special.b.set_multmode = 1; -} - #ifdef CONFIG_PROC_FS static int smart_enable(ide_drive_t *drive) @@ -648,6 +611,16 @@ PROC_IDE_READ_RETURN(page,start,off,count,eof,len); } +static int proc_idedisk_read_capacity + (char *page, char **start, off_t off, int count, int *eof, void *data) +{ + ide_drive_t*drive = (ide_drive_t *)data; + int len; + + len = sprintf(page,"%llu\n", (long long)idedisk_capacity(drive)); + PROC_IDE_READ_RETURN(page,start,off,count,eof,len); +} + static int proc_idedisk_read_smart_thresholds (char *page, char **start, off_t off, int count, int *eof, void *data) { @@ -688,6 +661,7 @@ static ide_proc_entry_t idedisk_proc[] = { { "cache", S_IFREG|S_IRUGO, proc_idedisk_read_cache, NULL }, + { "capacity", S_IFREG|S_IRUGO, proc_idedisk_read_capacity, NULL }, { "geometry", S_IFREG|S_IRUGO, proc_ide_read_geometry, NULL }, { "smart_values", S_IFREG|S_IRUSR, proc_idedisk_read_smart_values, NULL }, { "smart_thresholds", S_IFREG|S_IRUSR, proc_idedisk_read_smart_thresholds, NULL }, @@ -854,90 +828,6 @@ ide_add_setting(drive, "max_failures", SETTING_RW, -1, -1, TYPE_INT, 0, 65535, 1, 1, &drive->max_failures, NULL); } -/* - * Power Management state machine. This one is rather trivial for now, - * we should probably add more, like switching back to PIO on suspend - * to help some BIOSes, re-do the door locking on resume, etc... - */ - -enum { - idedisk_pm_flush_cache = ide_pm_state_start_suspend, - idedisk_pm_standby, - - idedisk_pm_idle = ide_pm_state_start_resume, - idedisk_pm_restore_dma, -}; - -static void idedisk_complete_power_step (ide_drive_t *drive, struct request *rq, u8 stat, u8 error) -{ - switch (rq->pm->pm_step) { - case idedisk_pm_flush_cache: /* Suspend step 1 (flush cache) complete */ - if (rq->pm->pm_state == 4) - rq->pm->pm_step = ide_pm_state_completed; - else - rq->pm->pm_step = idedisk_pm_standby; - break; - case idedisk_pm_standby: /* Suspend step 2 (standby) complete */ - rq->pm->pm_step = ide_pm_state_completed; - break; - case idedisk_pm_idle: /* Resume step 1 (idle) complete */ - rq->pm->pm_step = idedisk_pm_restore_dma; - break; - } -} - -static ide_startstop_t idedisk_start_power_step (ide_drive_t *drive, struct request *rq) -{ - ide_task_t *args = rq->special; - - memset(args, 0, sizeof(*args)); - - switch (rq->pm->pm_step) { - case idedisk_pm_flush_cache: /* Suspend step 1 (flush cache) */ - /* Not supported? Switch to next step now. */ - if (!drive->wcache || !ide_id_has_flush_cache(drive->id)) { - idedisk_complete_power_step(drive, rq, 0, 0); - return ide_stopped; - } - if (ide_id_has_flush_cache_ext(drive->id)) - args->tfRegister[IDE_COMMAND_OFFSET] = WIN_FLUSH_CACHE_EXT; - else - args->tfRegister[IDE_COMMAND_OFFSET] = WIN_FLUSH_CACHE; - args->command_type = IDE_DRIVE_TASK_NO_DATA; - args->handler = &task_no_data_intr; - return do_rw_taskfile(drive, args); - - case idedisk_pm_standby: /* Suspend step 2 (standby) */ - args->tfRegister[IDE_COMMAND_OFFSET] = WIN_STANDBYNOW1; - args->command_type = IDE_DRIVE_TASK_NO_DATA; - args->handler = &task_no_data_intr; - return do_rw_taskfile(drive, args); - - case idedisk_pm_idle: /* Resume step 1 (idle) */ - args->tfRegister[IDE_COMMAND_OFFSET] = WIN_IDLEIMMEDIATE; - args->command_type = IDE_DRIVE_TASK_NO_DATA; - args->handler = task_no_data_intr; - return do_rw_taskfile(drive, args); - - case idedisk_pm_restore_dma: /* Resume step 2 (restore DMA) */ - /* - * Right now, all we do is call hwif->ide_dma_check(drive), - * we could be smarter and check for current xfer_speed - * in struct drive etc... - * Also, this step could be implemented as a generic helper - * as most subdrivers will use it - */ - if ((drive->id->capability & 1) == 0) - break; - if (HWIF(drive)->ide_dma_check == NULL) - break; - HWIF(drive)->ide_dma_check(drive); - break; - } - rq->pm->pm_step = ide_pm_state_completed; - return ide_stopped; -} - static void idedisk_setup (ide_drive_t *drive) { struct hd_driveid *id = drive->id; @@ -976,28 +866,6 @@ printk(KERN_INFO "%s: max request size: %dKiB\n", drive->name, drive->queue->max_sectors / 2); - /* Extract geometry if we did not already have one for the drive */ - if (!drive->cyl || !drive->head || !drive->sect) { - drive->cyl = drive->bios_cyl = id->cyls; - drive->head = drive->bios_head = id->heads; - drive->sect = drive->bios_sect = id->sectors; - } - - /* Handle logical geometry translation by the drive */ - if ((id->field_valid & 1) && id->cur_cyls && - id->cur_heads && (id->cur_heads <= 16) && id->cur_sectors) { - drive->cyl = id->cur_cyls; - drive->head = id->cur_heads; - drive->sect = id->cur_sectors; - } - - /* Use physical geometry if what we have still makes no sense */ - if (drive->head > 16 && id->heads && id->heads <= 16) { - drive->cyl = id->cyls; - drive->head = id->heads; - drive->sect = id->sectors; - } - /* calculate drive capacity, and select LBA if possible */ init_idedisk_capacity (drive); @@ -1061,21 +929,6 @@ ide_dma_verbose(drive); printk("\n"); - drive->mult_count = 0; - if (id->max_multsect) { -#ifdef CONFIG_IDEDISK_MULTI_MODE - id->multsect = ((id->max_multsect/2) > 1) ? id->max_multsect : 0; - id->multsect_valid = id->multsect ? 1 : 0; - drive->mult_req = id->multsect_valid ? id->max_multsect : INITIAL_MULT_COUNT; - drive->special.b.set_multmode = drive->mult_req ? 1 : 0; -#else /* original, pre IDE-NFG, per request of AC */ - drive->mult_req = INITIAL_MULT_COUNT; - if (drive->mult_req > id->max_multsect) - drive->mult_req = id->max_multsect; - if (drive->mult_req || ((id->multsect_valid & 1) && id->multsect)) - drive->special.b.set_multmode = 1; -#endif /* CONFIG_IDEDISK_MULTI_MODE */ - } drive->no_io_32bit = id->dword_io ? 1 : 0; /* write cache enabled? */ @@ -1119,14 +972,30 @@ static int idedisk_cleanup (ide_drive_t *drive) { + struct ide_disk_obj *idkp = drive->driver_data; struct gendisk *g = drive->disk; + ide_cacheflush_p(drive); if (ide_unregister_subdriver(drive)) return 1; del_gendisk(g); + + ide_disk_put(idkp); + + return 0; +} + +static void ide_disk_release(struct kref *kref) +{ + struct ide_disk_obj *idkp = to_ide_disk(kref); + ide_drive_t *drive = idkp->drive; + struct gendisk *g = drive->disk; + + drive->driver_data = NULL; drive->devfs_name[0] = '\0'; + g->private_data = NULL; g->fops = ide_fops; - return 0; + kfree(idkp); } static int idedisk_attach(ide_drive_t *drive); @@ -1174,19 +1043,25 @@ .supports_dsc_overlap = 0, .cleanup = idedisk_cleanup, .do_request = ide_do_rw_disk, - .pre_reset = idedisk_pre_reset, - .capacity = idedisk_capacity, - .special = idedisk_special, + .end_request = ide_end_request, + .error = __ide_error, + .abort = __ide_abort, .proc = idedisk_proc, .attach = idedisk_attach, .drives = LIST_HEAD_INIT(idedisk_driver.drives), - .start_power_step = idedisk_start_power_step, - .complete_power_step = idedisk_complete_power_step, }; static int idedisk_open(struct inode *inode, struct file *filp) { - ide_drive_t *drive = inode->i_bdev->bd_disk->private_data; + struct gendisk *disk = inode->i_bdev->bd_disk; + struct ide_disk_obj *idkp; + ide_drive_t *drive; + + if (!(idkp = ide_disk_get(disk))) + return -ENXIO; + + drive = idkp->drive; + drive->usage++; if (drive->removable && drive->usage == 1) { ide_task_t args; @@ -1208,7 +1083,10 @@ static int idedisk_release(struct inode *inode, struct file *filp) { - ide_drive_t *drive = inode->i_bdev->bd_disk->private_data; + struct gendisk *disk = inode->i_bdev->bd_disk; + struct ide_disk_obj *idkp = ide_disk_g(disk); + ide_drive_t *drive = idkp->drive; + if (drive->usage == 1) ide_cacheflush_p(drive); if (drive->removable && drive->usage == 1) { @@ -1221,6 +1099,9 @@ drive->doorlocking = 0; } drive->usage--; + + ide_disk_put(idkp); + return 0; } @@ -1228,12 +1109,14 @@ unsigned int cmd, unsigned long arg) { struct block_device *bdev = inode->i_bdev; - return generic_ide_ioctl(file, bdev, cmd, arg); + struct ide_disk_obj *idkp = ide_disk_g(bdev->bd_disk); + return generic_ide_ioctl(idkp->drive, file, bdev, cmd, arg); } static int idedisk_media_changed(struct gendisk *disk) { - ide_drive_t *drive = disk->private_data; + struct ide_disk_obj *idkp = ide_disk_g(disk); + ide_drive_t *drive = idkp->drive; /* do not scan partitions twice if this is a removable device */ if (drive->attach) { @@ -1246,8 +1129,8 @@ static int idedisk_revalidate_disk(struct gendisk *disk) { - ide_drive_t *drive = disk->private_data; - set_capacity(disk, idedisk_capacity(drive)); + struct ide_disk_obj *idkp = ide_disk_g(disk); + set_capacity(disk, idedisk_capacity(idkp->drive)); return 0; } @@ -1264,6 +1147,7 @@ static int idedisk_attach(ide_drive_t *drive) { + struct ide_disk_obj *idkp; struct gendisk *g = drive->disk; /* strstr("foo", "") is non-NULL */ @@ -1274,10 +1158,22 @@ if (drive->media != ide_disk) goto failed; + idkp = kmalloc(sizeof(*idkp), GFP_KERNEL); + if (!idkp) + goto failed; + if (ide_register_subdriver(drive, &idedisk_driver)) { printk (KERN_ERR "ide-disk: %s: Failed to register the driver with ide.c\n", drive->name); - goto failed; + goto out_free_idkp; } + + memset(idkp, 0, sizeof(*idkp)); + + kref_init(&idkp->kref); + + idkp->drive = drive; + drive->driver_data = idkp; + DRIVER(drive)->busy++; idedisk_setup(drive); if ((!drive->head || drive->head > 16) && !drive->select.b.lba) { @@ -1293,8 +1189,11 @@ g->flags = drive->removable ? GENHD_FL_REMOVABLE : 0; set_capacity(g, idedisk_capacity(drive)); g->fops = &idedisk_ops; + g->private_data = idkp; add_disk(g); return 0; +out_free_idkp: + kfree(idkp); failed: return 1; } diff -Nru a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c --- a/drivers/ide/ide-floppy.c 2005-02-03 18:46:34 -08:00 +++ b/drivers/ide/ide-floppy.c 2005-02-03 18:46:34 -08:00 @@ -274,8 +274,9 @@ * driver due to an interrupt or a timer event is stored in a variable * of type idefloppy_floppy_t, defined below. */ -typedef struct { - ide_drive_t *drive; +typedef struct ide_floppy_obj { + ide_drive_t *drive; + struct kref kref; /* Current packet command */ idefloppy_pc_t *pc; @@ -514,6 +515,33 @@ u8 reserved[4]; } idefloppy_mode_parameter_header_t; +static DECLARE_MUTEX(idefloppy_ref_sem); + +#define to_ide_floppy(obj) container_of(obj, struct ide_floppy_obj, kref) + +#define ide_floppy_g(disk) ((disk)->private_data) + +static struct ide_floppy_obj *ide_floppy_get(struct gendisk *disk) +{ + struct ide_floppy_obj *floppy = NULL; + + down(&idefloppy_ref_sem); + floppy = ide_floppy_g(disk); + if (floppy) + kref_get(&floppy->kref); + up(&idefloppy_ref_sem); + return floppy; +} + +static void ide_floppy_release(struct kref *); + +static void ide_floppy_put(struct ide_floppy_obj *floppy) +{ + down(&idefloppy_ref_sem); + kref_put(&floppy->kref, ide_floppy_release); + up(&idefloppy_ref_sem); +} + /* * Too bad. The drive wants to send us data which we are not ready to accept. * Just throw it away. @@ -1792,10 +1820,6 @@ struct idefloppy_id_gcw gcw; *((u16 *) &gcw) = drive->id->config; - drive->driver_data = floppy; - drive->ready_stat = 0; - memset(floppy, 0, sizeof(idefloppy_floppy_t)); - floppy->drive = drive; floppy->pc = floppy->pc_stack; if (gcw.drq_type == 1) set_bit(IDEFLOPPY_DRQ_INTERRUPT, &floppy->flags); @@ -1839,16 +1863,40 @@ if (ide_unregister_subdriver(drive)) return 1; - drive->driver_data = NULL; - kfree(floppy); + del_gendisk(g); - g->fops = ide_fops; + + ide_floppy_put(floppy); + return 0; } +static void ide_floppy_release(struct kref *kref) +{ + struct ide_floppy_obj *floppy = to_ide_floppy(kref); + ide_drive_t *drive = floppy->drive; + struct gendisk *g = drive->disk; + + drive->driver_data = NULL; + g->private_data = NULL; + g->fops = ide_fops; + kfree(floppy); +} + #ifdef CONFIG_PROC_FS +static int proc_idefloppy_read_capacity + (char *page, char **start, off_t off, int count, int *eof, void *data) +{ + ide_drive_t*drive = (ide_drive_t *)data; + int len; + + len = sprintf(page,"%llu\n", (long long)idefloppy_capacity(drive)); + PROC_IDE_READ_RETURN(page,start,off,count,eof,len); +} + static ide_proc_entry_t idefloppy_proc[] = { + { "capacity", S_IFREG|S_IRUGO, proc_idefloppy_read_capacity, NULL }, { "geometry", S_IFREG|S_IRUGO, proc_ide_read_geometry, NULL }, { NULL, 0, NULL, NULL } }; @@ -1874,7 +1922,8 @@ .cleanup = idefloppy_cleanup, .do_request = idefloppy_do_request, .end_request = idefloppy_do_end_request, - .capacity = idefloppy_capacity, + .error = __ide_error, + .abort = __ide_abort, .proc = idefloppy_proc, .attach = idefloppy_attach, .drives = LIST_HEAD_INIT(idefloppy_driver.drives), @@ -1882,14 +1931,21 @@ static int idefloppy_open(struct inode *inode, struct file *filp) { - ide_drive_t *drive = inode->i_bdev->bd_disk->private_data; - idefloppy_floppy_t *floppy = drive->driver_data; + struct gendisk *disk = inode->i_bdev->bd_disk; + struct ide_floppy_obj *floppy; + ide_drive_t *drive; idefloppy_pc_t pc; + int ret = 0; - drive->usage++; - debug_log(KERN_INFO "Reached idefloppy_open\n"); + if (!(floppy = ide_floppy_get(disk))) + return -ENXIO; + + drive = floppy->drive; + + drive->usage++; + if (drive->usage == 1) { clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags); /* Just in case */ @@ -1909,13 +1965,15 @@ */ ) { drive->usage--; - return -EIO; + ret = -EIO; + goto out_put_floppy; } if (floppy->wp && (filp->f_mode & 2)) { drive->usage--; - return -EROFS; - } + ret = -EROFS; + goto out_put_floppy; + } set_bit(IDEFLOPPY_MEDIA_CHANGED, &floppy->flags); /* IOMEGA Clik! drives do not support lock/unlock commands */ if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) { @@ -1925,21 +1983,26 @@ check_disk_change(inode->i_bdev); } else if (test_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags)) { drive->usage--; - return -EBUSY; + ret = -EBUSY; + goto out_put_floppy; } return 0; + +out_put_floppy: + ide_floppy_put(floppy); + return ret; } static int idefloppy_release(struct inode *inode, struct file *filp) { - ide_drive_t *drive = inode->i_bdev->bd_disk->private_data; + struct gendisk *disk = inode->i_bdev->bd_disk; + struct ide_floppy_obj *floppy = ide_floppy_g(disk); + ide_drive_t *drive = floppy->drive; idefloppy_pc_t pc; debug_log(KERN_INFO "Reached idefloppy_release\n"); if (drive->usage == 1) { - idefloppy_floppy_t *floppy = drive->driver_data; - /* IOMEGA Clik! drives do not support lock/unlock commands */ if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) { idefloppy_create_prevent_cmd(&pc, 0); @@ -1949,6 +2012,9 @@ clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags); } drive->usage--; + + ide_floppy_put(floppy); + return 0; } @@ -1956,10 +2022,10 @@ unsigned int cmd, unsigned long arg) { struct block_device *bdev = inode->i_bdev; - ide_drive_t *drive = bdev->bd_disk->private_data; - idefloppy_floppy_t *floppy = drive->driver_data; + struct ide_floppy_obj *floppy = ide_floppy_g(bdev->bd_disk); + ide_drive_t *drive = floppy->drive; void __user *argp = (void __user *)arg; - int err = generic_ide_ioctl(file, bdev, cmd, arg); + int err = generic_ide_ioctl(drive, file, bdev, cmd, arg); int prevent = (arg) ? 1 : 0; idefloppy_pc_t pc; if (err != -EINVAL) @@ -2020,8 +2086,8 @@ static int idefloppy_media_changed(struct gendisk *disk) { - ide_drive_t *drive = disk->private_data; - idefloppy_floppy_t *floppy = drive->driver_data; + struct ide_floppy_obj *floppy = ide_floppy_g(disk); + ide_drive_t *drive = floppy->drive; /* do not scan partitions twice if this is a removable device */ if (drive->attach) { @@ -2033,8 +2099,8 @@ static int idefloppy_revalidate_disk(struct gendisk *disk) { - ide_drive_t *drive = disk->private_data; - set_capacity(disk, idefloppy_capacity(drive)); + struct ide_floppy_obj *floppy = ide_floppy_g(disk); + set_capacity(disk, idefloppy_capacity(floppy->drive)); return 0; } @@ -2074,6 +2140,15 @@ kfree (floppy); goto failed; } + + memset(floppy, 0, sizeof(*floppy)); + + kref_init(&floppy->kref); + + floppy->drive = drive; + + drive->driver_data = floppy; + DRIVER(drive)->busy++; idefloppy_setup (drive, floppy); DRIVER(drive)->busy--; @@ -2082,6 +2157,7 @@ strcpy(g->devfs_name, drive->devfs_name); g->flags = drive->removable ? GENHD_FL_REMOVABLE : 0; g->fops = &idefloppy_ops; + g->private_data = floppy; drive->attach = 1; add_disk(g); return 0; diff -Nru a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c --- a/drivers/ide/ide-io.c 2005-02-03 18:46:34 -08:00 +++ b/drivers/ide/ide-io.c 2005-02-03 18:46:34 -08:00 @@ -189,6 +189,93 @@ } EXPORT_SYMBOL(ide_end_request); +/* + * Power Management state machine. This one is rather trivial for now, + * we should probably add more, like switching back to PIO on suspend + * to help some BIOSes, re-do the door locking on resume, etc... + */ + +enum { + ide_pm_flush_cache = ide_pm_state_start_suspend, + idedisk_pm_standby, + + idedisk_pm_idle = ide_pm_state_start_resume, + ide_pm_restore_dma, +}; + +static void ide_complete_power_step(ide_drive_t *drive, struct request *rq, u8 stat, u8 error) +{ + if (drive->media != ide_disk) + return; + + switch (rq->pm->pm_step) { + case ide_pm_flush_cache: /* Suspend step 1 (flush cache) complete */ + if (rq->pm->pm_state == 4) + rq->pm->pm_step = ide_pm_state_completed; + else + rq->pm->pm_step = idedisk_pm_standby; + break; + case idedisk_pm_standby: /* Suspend step 2 (standby) complete */ + rq->pm->pm_step = ide_pm_state_completed; + break; + case idedisk_pm_idle: /* Resume step 1 (idle) complete */ + rq->pm->pm_step = ide_pm_restore_dma; + break; + } +} + +static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *rq) +{ + ide_task_t *args = rq->special; + + memset(args, 0, sizeof(*args)); + + switch (rq->pm->pm_step) { + case ide_pm_flush_cache: /* Suspend step 1 (flush cache) */ + if (drive->media != ide_disk) + break; + /* Not supported? Switch to next step now. */ + if (!drive->wcache || !ide_id_has_flush_cache(drive->id)) { + ide_complete_power_step(drive, rq, 0, 0); + return ide_stopped; + } + if (ide_id_has_flush_cache_ext(drive->id)) + args->tfRegister[IDE_COMMAND_OFFSET] = WIN_FLUSH_CACHE_EXT; + else + args->tfRegister[IDE_COMMAND_OFFSET] = WIN_FLUSH_CACHE; + args->command_type = IDE_DRIVE_TASK_NO_DATA; + args->handler = &task_no_data_intr; + return do_rw_taskfile(drive, args); + + case idedisk_pm_standby: /* Suspend step 2 (standby) */ + args->tfRegister[IDE_COMMAND_OFFSET] = WIN_STANDBYNOW1; + args->command_type = IDE_DRIVE_TASK_NO_DATA; + args->handler = &task_no_data_intr; + return do_rw_taskfile(drive, args); + + case idedisk_pm_idle: /* Resume step 1 (idle) */ + args->tfRegister[IDE_COMMAND_OFFSET] = WIN_IDLEIMMEDIATE; + args->command_type = IDE_DRIVE_TASK_NO_DATA; + args->handler = task_no_data_intr; + return do_rw_taskfile(drive, args); + + case ide_pm_restore_dma: /* Resume step 2 (restore DMA) */ + /* + * Right now, all we do is call hwif->ide_dma_check(drive), + * we could be smarter and check for current xfer_speed + * in struct drive etc... + */ + if ((drive->id->capability & 1) == 0) + break; + if (drive->hwif->ide_dma_check == NULL) + break; + drive->hwif->ide_dma_check(drive); + break; + } + rq->pm->pm_step = ide_pm_state_completed; + return ide_stopped; +} + /** * ide_complete_pm_request - end the current Power Management request * @drive: target drive @@ -408,7 +495,7 @@ printk("%s: complete_power_step(step: %d, stat: %x, err: %x)\n", drive->name, rq->pm->pm_step, stat, err); #endif - DRIVER(drive)->complete_power_step(drive, rq, stat, err); + ide_complete_power_step(drive, rq, stat, err); if (rq->pm->pm_step == ide_pm_state_completed) ide_complete_pm_request(drive, rq); return; @@ -535,6 +622,8 @@ return ide_atapi_error(drive, rq, stat, err); } +EXPORT_SYMBOL_GPL(__ide_error); + /** * ide_error - handle an error on the IDE * @drive: drive the error occurred on @@ -579,6 +668,8 @@ return ide_stopped; } +EXPORT_SYMBOL_GPL(__ide_abort); + /** * ide_abort - abort pending IDE operatins * @drive: drive the error occurred on @@ -667,6 +758,65 @@ return ide_stopped; } +static void ide_init_specify_cmd(ide_drive_t *drive, ide_task_t *task) +{ + task->tfRegister[IDE_NSECTOR_OFFSET] = drive->sect; + task->tfRegister[IDE_SECTOR_OFFSET] = drive->sect; + task->tfRegister[IDE_LCYL_OFFSET] = drive->cyl; + task->tfRegister[IDE_HCYL_OFFSET] = drive->cyl>>8; + task->tfRegister[IDE_SELECT_OFFSET] = ((drive->head-1)|drive->select.all)&0xBF; + task->tfRegister[IDE_COMMAND_OFFSET] = WIN_SPECIFY; + + task->handler = &set_geometry_intr; +} + +static void ide_init_restore_cmd(ide_drive_t *drive, ide_task_t *task) +{ + task->tfRegister[IDE_NSECTOR_OFFSET] = drive->sect; + task->tfRegister[IDE_COMMAND_OFFSET] = WIN_RESTORE; + + task->handler = &recal_intr; +} + +static void ide_init_setmult_cmd(ide_drive_t *drive, ide_task_t *task) +{ + task->tfRegister[IDE_NSECTOR_OFFSET] = drive->mult_req; + task->tfRegister[IDE_COMMAND_OFFSET] = WIN_SETMULT; + + task->handler = &set_multmode_intr; +} + +static ide_startstop_t ide_disk_special(ide_drive_t *drive) +{ + special_t *s = &drive->special; + ide_task_t args; + + memset(&args, 0, sizeof(ide_task_t)); + args.command_type = IDE_DRIVE_TASK_NO_DATA; + + if (s->b.set_geometry) { + s->b.set_geometry = 0; + ide_init_specify_cmd(drive, &args); + } else if (s->b.recalibrate) { + s->b.recalibrate = 0; + ide_init_restore_cmd(drive, &args); + } else if (s->b.set_multmode) { + s->b.set_multmode = 0; + if (drive->mult_req > drive->id->max_multsect) + drive->mult_req = drive->id->max_multsect; + ide_init_setmult_cmd(drive, &args); + } else if (s->all) { + int special = s->all; + s->all = 0; + printk(KERN_ERR "%s: bad special flag: 0x%02x\n", drive->name, special); + return ide_stopped; + } + + do_rw_taskfile(drive, &args); + + return ide_started; +} + /** * do_special - issue some special commands * @drive: drive the command is for @@ -688,9 +838,14 @@ if (HWIF(drive)->tuneproc != NULL) HWIF(drive)->tuneproc(drive, drive->tune_req); return ide_stopped; + } else { + if (drive->media == ide_disk) + return ide_disk_special(drive); + + s->all = 0; + drive->mult_req = 0; + return ide_stopped; } - else - return DRIVER(drive)->special(drive); } void ide_map_sg(ide_drive_t *drive, struct request *rq) @@ -905,7 +1060,7 @@ printk("%s: start_power_step(step: %d)\n", drive->name, rq->pm->pm_step); #endif - startstop = DRIVER(drive)->start_power_step(drive, rq); + startstop = ide_start_power_step(drive, rq); if (startstop == ide_stopped && rq->pm->pm_step == ide_pm_state_completed) ide_complete_pm_request(drive, rq); diff -Nru a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c --- a/drivers/ide/ide-iops.c 2005-02-03 18:46:34 -08:00 +++ b/drivers/ide/ide-iops.c 2005-02-03 18:46:34 -08:00 @@ -1107,9 +1107,27 @@ #endif } +static void ide_disk_pre_reset(ide_drive_t *drive) +{ + int legacy = (drive->id->cfs_enable_2 & 0x0400) ? 0 : 1; + + drive->special.all = 0; + drive->special.b.set_geometry = legacy; + drive->special.b.recalibrate = legacy; + if (OK_TO_RESET_CONTROLLER) + drive->mult_count = 0; + if (!drive->keep_settings && !drive->using_dma) + drive->mult_req = 0; + if (drive->mult_req != drive->mult_count) + drive->special.b.set_multmode = 1; +} + static void pre_reset(ide_drive_t *drive) { - DRIVER(drive)->pre_reset(drive); + if (drive->media == ide_disk) + ide_disk_pre_reset(drive); + else + drive->post_reset = 1; if (!drive->keep_settings) { if (drive->using_dma) { diff -Nru a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c --- a/drivers/ide/ide-probe.c 2005-02-03 18:46:34 -08:00 +++ b/drivers/ide/ide-probe.c 2005-02-03 18:46:34 -08:00 @@ -74,7 +74,55 @@ drive->id->cur_heads = drive->head; drive->id->cur_sectors = drive->sect; } - + +static void ide_disk_init_chs(ide_drive_t *drive) +{ + struct hd_driveid *id = drive->id; + + /* Extract geometry if we did not already have one for the drive */ + if (!drive->cyl || !drive->head || !drive->sect) { + drive->cyl = drive->bios_cyl = id->cyls; + drive->head = drive->bios_head = id->heads; + drive->sect = drive->bios_sect = id->sectors; + } + + /* Handle logical geometry translation by the drive */ + if ((id->field_valid & 1) && id->cur_cyls && + id->cur_heads && (id->cur_heads <= 16) && id->cur_sectors) { + drive->cyl = id->cur_cyls; + drive->head = id->cur_heads; + drive->sect = id->cur_sectors; + } + + /* Use physical geometry if what we have still makes no sense */ + if (drive->head > 16 && id->heads && id->heads <= 16) { + drive->cyl = id->cyls; + drive->head = id->heads; + drive->sect = id->sectors; + } +} + +static void ide_disk_init_mult_count(ide_drive_t *drive) +{ + struct hd_driveid *id = drive->id; + + drive->mult_count = 0; + if (id->max_multsect) { +#ifdef CONFIG_IDEDISK_MULTI_MODE + id->multsect = ((id->max_multsect/2) > 1) ? id->max_multsect : 0; + id->multsect_valid = id->multsect ? 1 : 0; + drive->mult_req = id->multsect_valid ? id->max_multsect : INITIAL_MULT_COUNT; + drive->special.b.set_multmode = drive->mult_req ? 1 : 0; +#else /* original, pre IDE-NFG, per request of AC */ + drive->mult_req = INITIAL_MULT_COUNT; + if (drive->mult_req > id->max_multsect) + drive->mult_req = id->max_multsect; + if (drive->mult_req || ((id->multsect_valid & 1) && id->multsect)) + drive->special.b.set_multmode = 1; +#endif + } +} + /** * drive_is_flashcard - check for compact flash * @drive: drive to check @@ -221,6 +269,8 @@ } printk (" drive\n"); drive->media = type; + /* an ATAPI device ignores DRDY */ + drive->ready_stat = 0; return; } @@ -588,8 +638,16 @@ if(!drive->present) return 0; /* The drive wasn't being helpful. Add generic info only */ - if(!drive->id_read) + if (drive->id_read == 0) { generic_id(drive); + return 1; + } + + if (drive->media == ide_disk) { + ide_disk_init_chs(drive); + ide_disk_init_mult_count(drive); + } + return drive->present; } diff -Nru a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c --- a/drivers/ide/ide-proc.c 2005-02-03 18:46:34 -08:00 +++ b/drivers/ide/ide-proc.c 2005-02-03 18:46:34 -08:00 @@ -269,13 +269,11 @@ int proc_ide_read_capacity (char *page, char **start, off_t off, int count, int *eof, void *data) { - ide_drive_t *drive = (ide_drive_t *) data; - int len; - - len = sprintf(page,"%llu\n", - (long long) (DRIVER(drive)->capacity(drive))); + int len = sprintf(page,"%llu\n", (long long)0x7fffffff); PROC_IDE_READ_RETURN(page,start,off,count,eof,len); } + +EXPORT_SYMBOL_GPL(proc_ide_read_capacity); int proc_ide_read_geometry (char *page, char **start, off_t off, int count, int *eof, void *data) diff -Nru a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c --- a/drivers/ide/ide-tape.c 2005-02-03 18:46:34 -08:00 +++ b/drivers/ide/ide-tape.c 2005-02-03 18:46:34 -08:00 @@ -781,8 +781,10 @@ * driver due to an interrupt or a timer event is stored in a variable * of type idetape_tape_t, defined below. */ -typedef struct { - ide_drive_t *drive; +typedef struct ide_tape_obj { + ide_drive_t *drive; + struct kref kref; + /* * Since a typical character device operation requires more * than one packet command, we provide here enough memory @@ -1007,6 +1009,33 @@ int debug_level; } idetape_tape_t; +static DECLARE_MUTEX(idetape_ref_sem); + +#define to_ide_tape(obj) container_of(obj, struct ide_tape_obj, kref) + +#define ide_tape_g(disk) ((disk)->private_data) + +static struct ide_tape_obj *ide_tape_get(struct gendisk *disk) +{ + struct ide_tape_obj *tape = NULL; + + down(&idetape_ref_sem); + tape = ide_tape_g(disk); + if (tape) + kref_get(&tape->kref); + up(&idetape_ref_sem); + return tape; +} + +static void ide_tape_release(struct kref *); + +static void ide_tape_put(struct ide_tape_obj *tape) +{ + down(&idetape_ref_sem); + kref_put(&tape->kref, ide_tape_release); + up(&idetape_ref_sem); +} + /* * Tape door status */ @@ -2428,6 +2457,11 @@ if (!drive->dsc_overlap && !(rq->cmd[0] & REQ_IDETAPE_PC2)) set_bit(IDETAPE_IGNORE_DSC, &tape->flags); + if (drive->post_reset == 1) { + set_bit(IDETAPE_IGNORE_DSC, &tape->flags); + drive->post_reset = 0; + } + if (tape->tape_still_time > 100 && tape->tape_still_time < 200) tape->measure_insert_time = 1; if (time_after(jiffies, tape->insert_time)) @@ -3558,16 +3592,6 @@ } /* - * idetape_pre_reset is called before an ATAPI/ATA software reset. - */ -static void idetape_pre_reset (ide_drive_t *drive) -{ - idetape_tape_t *tape = drive->driver_data; - if (tape != NULL) - set_bit(IDETAPE_IGNORE_DSC, &tape->flags); -} - -/* * idetape_space_over_filemarks is now a bit more complicated than just * passing the command to the tape since we may have crossed some * filemarks during our pipelined read-ahead mode. @@ -4527,11 +4551,7 @@ int stage_size; struct sysinfo si; - memset(tape, 0, sizeof (idetape_tape_t)); spin_lock_init(&tape->spinlock); - drive->driver_data = tape; - /* An ATAPI device ignores DRDY */ - drive->ready_stat = 0; drive->dsc_overlap = 1; #ifdef CONFIG_BLK_DEV_IDEPCI if (HWIF(drive)->pci_dev != NULL) { @@ -4549,7 +4569,6 @@ /* Seagate Travan drives do not support DSC overlap. */ if (strstr(drive->id->model, "Seagate STT3401")) drive->dsc_overlap = 0; - tape->drive = drive; tape->minor = minor; tape->name[0] = 'h'; tape->name[1] = 't'; @@ -4643,13 +4662,25 @@ spin_unlock_irqrestore(&ide_lock, flags); DRIVER(drive)->busy = 0; (void) ide_unregister_subdriver(drive); + + ide_tape_put(tape); + + return 0; +} + +static void ide_tape_release(struct kref *kref) +{ + struct ide_tape_obj *tape = to_ide_tape(kref); + ide_drive_t *drive = tape->drive; + struct gendisk *g = drive->disk; + drive->driver_data = NULL; devfs_remove("%s/mt", drive->devfs_name); devfs_remove("%s/mtn", drive->devfs_name); - devfs_unregister_tape(drive->disk->number); - kfree (tape); - drive->disk->fops = ide_fops; - return 0; + devfs_unregister_tape(g->number); + g->private_data = NULL; + g->fops = ide_fops; + kfree(tape); } #ifdef CONFIG_PROC_FS @@ -4667,6 +4698,7 @@ } static ide_proc_entry_t idetape_proc[] = { + { "capacity", S_IFREG|S_IRUGO, proc_ide_read_capacity, NULL }, { "name", S_IFREG|S_IRUGO, proc_idetape_read_name, NULL }, { NULL, 0, NULL, NULL } }; @@ -4692,7 +4724,8 @@ .cleanup = idetape_cleanup, .do_request = idetape_do_request, .end_request = idetape_end_request, - .pre_reset = idetape_pre_reset, + .error = __ide_error, + .abort = __ide_abort, .proc = idetape_proc, .attach = idetape_attach, .drives = LIST_HEAD_INIT(idetape_driver.drives), @@ -4712,15 +4745,30 @@ static int idetape_open(struct inode *inode, struct file *filp) { - ide_drive_t *drive = inode->i_bdev->bd_disk->private_data; + struct gendisk *disk = inode->i_bdev->bd_disk; + struct ide_tape_obj *tape; + ide_drive_t *drive; + + if (!(tape = ide_tape_get(disk))) + return -ENXIO; + + drive = tape->drive; + drive->usage++; + return 0; } static int idetape_release(struct inode *inode, struct file *filp) { - ide_drive_t *drive = inode->i_bdev->bd_disk->private_data; + struct gendisk *disk = inode->i_bdev->bd_disk; + struct ide_tape_obj *tape = ide_tape_g(disk); + ide_drive_t *drive = tape->drive; + drive->usage--; + + ide_tape_put(tape); + return 0; } @@ -4728,8 +4776,9 @@ unsigned int cmd, unsigned long arg) { struct block_device *bdev = inode->i_bdev; - ide_drive_t *drive = bdev->bd_disk->private_data; - int err = generic_ide_ioctl(file, bdev, cmd, arg); + struct ide_tape_obj *tape = ide_tape_g(bdev->bd_disk); + ide_drive_t *drive = tape->drive; + int err = generic_ide_ioctl(drive, file, bdev, cmd, arg); if (err == -EINVAL) err = idetape_blkdev_ioctl(drive, cmd, arg); return err; @@ -4745,6 +4794,7 @@ static int idetape_attach (ide_drive_t *drive) { idetape_tape_t *tape; + struct gendisk *g = drive->disk; int minor; if (!strstr("ide-tape", drive->driver_req)) @@ -4777,6 +4827,15 @@ } for (minor = 0; idetape_chrdevs[minor].drive != NULL; minor++) ; + + memset(tape, 0, sizeof(*tape)); + + kref_init(&tape->kref); + + tape->drive = drive; + + drive->driver_data = tape; + idetape_setup(drive, tape, minor); idetape_chrdevs[minor].drive = drive; @@ -4787,8 +4846,10 @@ S_IFCHR | S_IRUGO | S_IWUGO, "%s/mtn", drive->devfs_name); - drive->disk->number = devfs_register_tape(drive->devfs_name); - drive->disk->fops = &idetape_block_ops; + g->number = devfs_register_tape(drive->devfs_name); + g->fops = &idetape_block_ops; + g->private_data = tape; + return 0; failed: return 1; diff -Nru a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c --- a/drivers/ide/ide-taskfile.c 2005-02-03 18:46:34 -08:00 +++ b/drivers/ide/ide-taskfile.c 2005-02-03 18:46:34 -08:00 @@ -181,8 +181,6 @@ return ide_stopped; } -EXPORT_SYMBOL(set_multmode_intr); - /* * set_geometry_intr() is invoked on completion of a WIN_SPECIFY cmd. */ @@ -207,8 +205,6 @@ return ide_started; } -EXPORT_SYMBOL(set_geometry_intr); - /* * recal_intr() is invoked on completion of a WIN_RESTORE (recalibrate) cmd. */ @@ -221,8 +217,6 @@ return ide_error(drive, "recal_intr", stat); return ide_stopped; } - -EXPORT_SYMBOL(recal_intr); /* * Handler for commands without a data phase diff -Nru a/drivers/ide/ide.c b/drivers/ide/ide.c --- a/drivers/ide/ide.c 2005-02-03 18:46:34 -08:00 +++ b/drivers/ide/ide.c 2005-02-03 18:46:34 -08:00 @@ -197,7 +197,6 @@ 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! @@ -301,8 +300,6 @@ 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]; @@ -413,11 +410,6 @@ #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, @@ -1418,10 +1410,9 @@ 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; int err = 0; void __user *p = (void __user *)arg; @@ -1747,6 +1738,8 @@ 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" */ @@ -2018,68 +2011,6 @@ #endif } -static ide_startstop_t default_do_request (ide_drive_t *drive, struct request *rq, sector_t block) -{ - 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; @@ -2105,10 +2036,8 @@ drive->nice1 = 1; } #ifdef CONFIG_PROC_FS - if (drive->driver != &idedefault_driver) { - ide_add_proc_entries(drive->proc, generic_subdriver_entries, drive); + if (drive->driver != &idedefault_driver) ide_add_proc_entries(drive->proc, driver->proc, drive); - } #endif return 0; } @@ -2142,7 +2071,6 @@ } #ifdef CONFIG_PROC_FS ide_remove_proc_entries(drive->proc, DRIVER(drive)->proc); - ide_remove_proc_entries(drive->proc, generic_subdriver_entries); #endif auto_remove_settings(drive); drive->driver = &idedefault_driver; @@ -2180,8 +2108,6 @@ 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); diff -Nru a/drivers/ide/pci/pdc202xx_new.h b/drivers/ide/pci/pdc202xx_new.h --- a/drivers/ide/pci/pdc202xx_new.h 2005-02-03 18:46:34 -08:00 +++ b/drivers/ide/pci/pdc202xx_new.h 2005-02-03 18:46:34 -08:00 @@ -73,9 +73,6 @@ .init_hwif = init_hwif_pdc202new, .channels = 2, .autodma = AUTODMA, -#ifndef CONFIG_PDC202XX_FORCE - .enablebits = {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, -#endif .bootable = OFF_BOARD, },{ /* 3 */ .name = "PDC20271", @@ -100,9 +97,6 @@ .init_hwif = init_hwif_pdc202new, .channels = 2, .autodma = AUTODMA, -#ifndef CONFIG_PDC202XX_FORCE - .enablebits = {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, -#endif .bootable = OFF_BOARD, },{ /* 6 */ .name = "PDC20277", diff -Nru a/drivers/ide/pci/pdc202xx_old.h b/drivers/ide/pci/pdc202xx_old.h --- a/drivers/ide/pci/pdc202xx_old.h 2005-02-03 18:46:34 -08:00 +++ b/drivers/ide/pci/pdc202xx_old.h 2005-02-03 18:46:34 -08:00 @@ -79,9 +79,6 @@ .init_dma = init_dma_pdc202xx, .channels = 2, .autodma = AUTODMA, -#ifndef CONFIG_PDC202XX_FORCE - .enablebits = {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, -#endif .bootable = OFF_BOARD, .extra = 16, },{ /* 1 */ @@ -92,12 +89,8 @@ .init_dma = init_dma_pdc202xx, .channels = 2, .autodma = AUTODMA, -#ifndef CONFIG_PDC202XX_FORCE - .enablebits = {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, -#endif .bootable = OFF_BOARD, .extra = 48, - .flags = IDEPCI_FLAG_FORCE_PDC, },{ /* 2 */ .name = "PDC20263", .init_setup = init_setup_pdc202ata4, @@ -106,9 +99,6 @@ .init_dma = init_dma_pdc202xx, .channels = 2, .autodma = AUTODMA, -#ifndef CONFIG_PDC202XX_FORCE - .enablebits = {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, -#endif .bootable = OFF_BOARD, .extra = 48, },{ /* 3 */ @@ -119,12 +109,8 @@ .init_dma = init_dma_pdc202xx, .channels = 2, .autodma = AUTODMA, -#ifndef CONFIG_PDC202XX_FORCE - .enablebits = {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, -#endif .bootable = OFF_BOARD, .extra = 48, - .flags = IDEPCI_FLAG_FORCE_PDC, },{ /* 4 */ .name = "PDC20267", .init_setup = init_setup_pdc202xx, @@ -133,9 +119,6 @@ .init_dma = init_dma_pdc202xx, .channels = 2, .autodma = AUTODMA, -#ifndef CONFIG_PDC202XX_FORCE - .enablebits = {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, -#endif .bootable = OFF_BOARD, .extra = 48, } diff -Nru a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c --- a/drivers/ide/pci/via82cxxx.c 2005-02-03 18:46:34 -08:00 +++ b/drivers/ide/pci/via82cxxx.c 2005-02-03 18:46:34 -08:00 @@ -332,11 +332,8 @@ struct ide_timing t, p; unsigned int T, UT; - if (speed != XFER_PIO_SLOW && speed != drive->current_speed) - if (ide_config_drive_speed(drive, speed)) - printk(KERN_WARNING "ide%d: Drive %d didn't " - "accept speed setting. Oh, well.\n", - drive->dn >> 1, drive->dn & 1); + if (speed != XFER_PIO_SLOW) + ide_config_drive_speed(drive, speed); T = 1000000000 / via_clock; diff -Nru a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c --- a/drivers/ide/setup-pci.c 2005-02-03 18:46:34 -08:00 +++ b/drivers/ide/setup-pci.c 2005-02-03 18:46:34 -08:00 @@ -579,7 +579,6 @@ int port; int at_least_one_hwif_enabled = 0; ide_hwif_t *hwif, *mate = NULL; - static int secondpdc = 0; u8 tmp; index->all = 0xf0f0; @@ -590,22 +589,10 @@ for (port = 0; port <= 1; ++port) { ide_pci_enablebit_t *e = &(d->enablebits[port]); - - /* - * If this is a Promise FakeRaid controller, - * the 2nd controller will be marked as - * disabled while it is actually there and enabled - * by the bios for raid purposes. - * Skip the normal "is it enabled" test for those. - */ - if ((d->flags & IDEPCI_FLAG_FORCE_PDC) && - (secondpdc++==1) && (port==1)) - goto controller_ok; - + if (e->reg && (pci_read_config_byte(dev, e->reg, &tmp) || (tmp & e->mask) != e->val)) continue; /* port not enabled */ -controller_ok: if (d->channels <= port) break; diff -Nru a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c --- a/drivers/scsi/ide-scsi.c 2005-02-03 18:46:34 -08:00 +++ b/drivers/scsi/ide-scsi.c 2005-02-03 18:46:34 -08:00 @@ -96,14 +96,39 @@ */ #define IDESCSI_LOG_CMD 0 /* Log SCSI commands */ -typedef struct { - ide_drive_t *drive; +typedef struct ide_scsi_obj { + ide_drive_t *drive; + struct Scsi_Host *host; + idescsi_pc_t *pc; /* Current packet command */ unsigned long flags; /* Status/Action flags */ unsigned long transform; /* SCSI cmd translation layer */ unsigned long log; /* log flags */ } idescsi_scsi_t; +static DECLARE_MUTEX(idescsi_ref_sem); + +#define ide_scsi_g(disk) ((disk)->private_data) + +static struct ide_scsi_obj *ide_scsi_get(struct gendisk *disk) +{ + struct ide_scsi_obj *scsi = NULL; + + down(&idescsi_ref_sem); + scsi = ide_scsi_g(disk); + if (scsi) + scsi_host_get(scsi->host); + up(&idescsi_ref_sem); + return scsi; +} + +static void ide_scsi_put(struct ide_scsi_obj *scsi) +{ + down(&idescsi_ref_sem); + scsi_host_put(scsi->host); + up(&idescsi_ref_sem); +} + static inline idescsi_scsi_t *scsihost_to_idescsi(struct Scsi_Host *host) { return (idescsi_scsi_t*) (&host[1]); @@ -679,7 +704,6 @@ static void idescsi_setup (ide_drive_t *drive, idescsi_scsi_t *scsi) { DRIVER(drive)->busy++; - drive->ready_stat = 0; if (drive->id && (drive->id->config & 0x0060) == 0x20) set_bit (IDESCSI_DRQ_INTERRUPT, &scsi->flags); set_bit(IDESCSI_TRANSFORM, &scsi->transform); @@ -694,21 +718,34 @@ static int idescsi_cleanup (ide_drive_t *drive) { struct Scsi_Host *scsihost = drive->driver_data; + struct gendisk *g = drive->disk; if (ide_unregister_subdriver(drive)) return 1; - - /* FIXME?: Are these two statements necessary? */ + + /* FIXME: drive->driver_data shouldn't be used */ drive->driver_data = NULL; - drive->disk->fops = ide_fops; + /* FIXME: add driver's private struct gendisk */ + g->private_data = NULL; + g->fops = ide_fops; scsi_remove_host(scsihost); - scsi_host_put(scsihost); + ide_scsi_put(scsihost_to_idescsi(scsihost)); + return 0; } static int idescsi_attach(ide_drive_t *drive); +#ifdef CONFIG_PROC_FS +static ide_proc_entry_t idescsi_proc[] = { + { "capacity", S_IFREG|S_IRUGO, proc_ide_read_capacity, NULL }, + { NULL, 0, NULL, NULL } +}; +#else +# define idescsi_proc NULL +#endif + /* * IDE subdriver functions, registered with ide.c */ @@ -719,6 +756,7 @@ .media = ide_scsi, .busy = 0, .supports_dsc_overlap = 0, + .proc = idescsi_proc, .attach = idescsi_attach, .cleanup = idescsi_cleanup, .do_request = idescsi_do_request, @@ -730,15 +768,30 @@ static int idescsi_ide_open(struct inode *inode, struct file *filp) { - ide_drive_t *drive = inode->i_bdev->bd_disk->private_data; + struct gendisk *disk = inode->i_bdev->bd_disk; + struct ide_scsi_obj *scsi; + ide_drive_t *drive; + + if (!(scsi = ide_scsi_get(disk))) + return -ENXIO; + + drive = scsi->drive; + drive->usage++; + return 0; } static int idescsi_ide_release(struct inode *inode, struct file *filp) { - ide_drive_t *drive = inode->i_bdev->bd_disk->private_data; + struct gendisk *disk = inode->i_bdev->bd_disk; + struct ide_scsi_obj *scsi = ide_scsi_g(disk); + ide_drive_t *drive = scsi->drive; + drive->usage--; + + ide_scsi_put(scsi); + return 0; } @@ -746,7 +799,8 @@ unsigned int cmd, unsigned long arg) { struct block_device *bdev = inode->i_bdev; - return generic_ide_ioctl(file, bdev, cmd, arg); + struct ide_scsi_obj *scsi = ide_scsi_g(bdev->bd_disk); + return generic_ide_ioctl(scsi->drive, file, bdev, cmd, arg); } static struct block_device_operations idescsi_ops = { @@ -1033,6 +1087,7 @@ { idescsi_scsi_t *idescsi; struct Scsi_Host *host; + struct gendisk *g = drive->disk; static int warned; int err; @@ -1061,10 +1116,12 @@ drive->driver_data = host; idescsi = scsihost_to_idescsi(host); idescsi->drive = drive; + idescsi->host = host; err = ide_register_subdriver(drive, &idescsi_driver); if (!err) { idescsi_setup (drive, idescsi); - drive->disk->fops = &idescsi_ops; + g->fops = &idescsi_ops; + g->private_data = idescsi; err = scsi_add_host(host, &drive->gendev); if (!err) { scsi_scan_host(host); diff -Nru a/include/linux/ide.h b/include/linux/ide.h --- a/include/linux/ide.h 2005-02-03 18:46:34 -08:00 +++ b/include/linux/ide.h 2005-02-03 18:46:34 -08:00 @@ -718,6 +718,7 @@ */ unsigned scsi : 1; /* 0=default, 1=ide-scsi emulation */ unsigned sleeping : 1; /* 1=sleeping & sleep field valid */ + unsigned post_reset : 1; u8 quirk_list; /* considered quirky, set for a specific host */ u8 init_speed; /* transfer rate set at boot */ @@ -1098,15 +1099,10 @@ ide_startstop_t (*error)(ide_drive_t *, struct request *rq, u8, u8); ide_startstop_t (*abort)(ide_drive_t *, struct request *rq); int (*ioctl)(ide_drive_t *, struct inode *, struct file *, unsigned int, unsigned long); - void (*pre_reset)(ide_drive_t *); - sector_t (*capacity)(ide_drive_t *); - ide_startstop_t (*special)(ide_drive_t *); ide_proc_entry_t *proc; int (*attach)(ide_drive_t *); void (*ata_prebuilder)(ide_drive_t *); void (*atapi_prebuilder)(ide_drive_t *); - ide_startstop_t (*start_power_step)(ide_drive_t *, struct request *); - void (*complete_power_step)(ide_drive_t *, struct request *, u8, u8); struct device_driver gen_driver; struct list_head drives; struct list_head drivers; @@ -1114,7 +1110,7 @@ #define DRIVER(drive) ((drive)->driver) -extern int generic_ide_ioctl(struct file *, struct block_device *, unsigned, unsigned long); +int generic_ide_ioctl(ide_drive_t *, struct file *, struct block_device *, unsigned, unsigned long); /* * ide_hwifs[] is the master data structure used to keep track @@ -1390,7 +1386,6 @@ enum { /* Uses ISA control ports not PCI ones. */ IDEPCI_FLAG_ISA_PORTS = (1 << 0), - IDEPCI_FLAG_FORCE_PDC = (1 << 1), }; typedef struct ide_pci_device_s {