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 <dwmw2@infradead.org>.
#   
#   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 <asm/io.h>
 #include <asm/div64.h>
 
+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 {