Misc. changes to have better support for Flash cards as IDE devices.

---

 drivers/ide/Config.in         |    3 +++
 drivers/ide/ide-disk.c        |   21 +++++++++++++++++++++
 drivers/ide/ide-dma.c         |   10 +++++++++-
 drivers/ide/ide-probe.c       |   17 +++++++++++++++--
 drivers/ide/ide-proc.c        |   10 ++++++++--
 drivers/ide/ide.c             |   13 +++++++++++--
 drivers/ide/pci/piix.c        |    9 +++++++++
 drivers/ide/pci/sc1200.c      |    9 +++++++++
 drivers/ide/pci/serverworks.c |    9 +++++++++
 drivers/ide/pci/via82cxxx.c   |    7 +++++++
 10 files changed, 101 insertions(+), 7 deletions(-)

diff --git a/drivers/ide/Config.in b/drivers/ide/Config.in
index 8dc29f5..1b1c21e 100644
--- a/drivers/ide/Config.in
+++ b/drivers/ide/Config.in
@@ -42,6 +42,7 @@ if [ "$CONFIG_BLK_DEV_IDE" != "n" ]; then
 	    dep_bool '      Force enable legacy 2.0.X HOSTS to use DMA' CONFIG_BLK_DEV_IDEDMA_FORCED $CONFIG_BLK_DEV_IDEDMA_PCI
 	    dep_bool '      Use PCI DMA by default when available' CONFIG_IDEDMA_PCI_AUTO $CONFIG_BLK_DEV_IDEDMA_PCI
             dep_bool '    Enable DMA only for disks ' CONFIG_IDEDMA_ONLYDISK $CONFIG_IDEDMA_PCI_AUTO
+            dep_bool '    Disable DMA for flash cards ' CONFIG_IDEDMA_NOFLASH $CONFIG_IDEDMA_PCI_AUTO
 	    define_bool CONFIG_BLK_DEV_IDEDMA $CONFIG_BLK_DEV_IDEDMA_PCI
 	    dep_bool '      ATA Work(s) In Progress (EXPERIMENTAL)' CONFIG_IDEDMA_PCI_WIP $CONFIG_BLK_DEV_IDEDMA_PCI $CONFIG_EXPERIMENTAL
 #	    dep_bool '      Good-Bad DMA Model-Firmware (WIP)' CONFIG_IDEDMA_NEW_DRIVE_LISTINGS $CONFIG_IDEDMA_PCI_WIP
@@ -151,6 +153,8 @@ if [ "$CONFIG_BLK_DEV_IDE" != "n" ]; then
 	 dep_tristate '    QDI QD65xx support' CONFIG_BLK_DEV_QD65XX $CONFIG_BLK_DEV_IDE
 	 dep_tristate '    UMC-8672 support' CONFIG_BLK_DEV_UMC8672 $CONFIG_BLK_DEV_IDE
       fi
+
+      bool '  Patch to use Flash disk & hard disk on the same controller' CONFIG_BLK_DEV_FLASHPATCH
    fi
 else
    bool 'Old hard disk (MFM/RLL/IDE) driver' CONFIG_BLK_DEV_HD_ONLY
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index dd9512a..b301b61 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -771,8 +771,14 @@ static void idedisk_release (struct inode *inode, struct file *filp, ide_drive_t
 
 static int idedisk_media_change (ide_drive_t *drive)
 {
+#if 1
+	/* flashcard can't be removed (and are often tagged as removable) */
+	extern int drive_is_flashcard (ide_drive_t *drive);
+	return (drive->removable && !drive_is_flashcard(drive));
+#else
 	/* if removable, always assume it was changed */
 	return drive->removable;
+#endif
 }
 
 static void idedisk_revalidate (ide_drive_t *drive)
@@ -1015,6 +1021,21 @@ static unsigned long idedisk_read_native_max_address(ide_drive_t *drive)
 	ide_task_t args;
 	unsigned long addr = 0;
 
+#ifdef CONFIG_ARKOON_REQUIREMENTS
+	/**
+	 * Flashcards don't support WIN_READ_NATIVE_MAX command. Don't try
+	 * to avoid theses messages:
+	 *   hda: task_no_data_intr: status=0x51 { DriveReady SeekComplete Error }
+	 *   hda: task_no_data_intr: error=0x04 { DriveStatusError }
+	 */
+	extern int drive_is_flashcard (ide_drive_t *drive);
+	if (drive_is_flashcard(drive)) {
+		printk(KERN_INFO "%s: disk is flashcard - no native capacity\n",
+			drive->name);
+		return 0;
+	}
+#endif /* CONFIG_ARKOON_REQUIREMENTS */
+
 	/* Create IDE/ATA command request structure */
 	memset(&args, 0, sizeof(ide_task_t));
 	args.tfRegister[IDE_SELECT_OFFSET]	= 0x40;
diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c
index 67256be..a714eed 100644
--- a/drivers/ide/ide-dma.c
+++ b/drivers/ide/ide-dma.c
@@ -489,10 +489,18 @@ EXPORT_SYMBOL_GPL(ide_destroy_dmatable);
  
 static int config_drive_for_dma (ide_drive_t *drive)
 {
+	int config_allows_dma = 1;
 	struct hd_driveid *id = drive->id;
 	ide_hwif_t *hwif = HWIF(drive);
 
-	if ((id->capability & 1) && hwif->autodma) {
+#ifdef CONFIG_IDEDMA_NOFLASH
+	extern int drive_is_flashcard (ide_drive_t *drive);
+	if ((drive->media == ide_disk) && (drive_is_flashcard(drive))) {
+		config_allows_dma = 0;
+	}
+#endif
+
+	if ((id->capability & 1) && hwif->autodma && config_allows_dma) {
 		/* Consult the list of known "bad" drives */
 		if (hwif->ide_dma_bad_drive(drive))
 			return hwif->ide_dma_off(drive);
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index ac45ac9..0f03882 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -94,12 +94,20 @@ static void generic_id(ide_drive_t *drive)
  *	retries, since these are MUCH faster than mechanical drives. -M.Lord
  */
  
-static inline int drive_is_flashcard (ide_drive_t *drive)
+inline int drive_is_flashcard (ide_drive_t *drive)
 {
 	struct hd_driveid *id = drive->id;
 
-	if (drive->removable && id != NULL) {
+	/**
+	 * Removable is the seventh bit of config
+	 */
+	if (!drive->removable && id != NULL) {
+		if (id->config == 0x044a) return 1;
+		if (id->config == 0x040a) return 1;
+	}
+	else if (drive->removable && id != NULL) {
 		if (id->config == 0x848a) return 1;	/* CompactFlash */
+		if (id->config == 0x048a) return 1;	/* CompactFlash */
 		if (!strncmp(id->model, "KODAK ATA_FLASH", 15)	/* Kodak */
 		 || !strncmp(id->model, "Hitachi CV", 10)	/* Hitachi */
 		 || !strncmp(id->model, "SunDisk SDCFB", 13)	/* old SanDisk */
@@ -111,6 +119,11 @@ static inline int drive_is_flashcard (ide_drive_t *drive)
 			return 1;	/* yes, it is a flash memory card */
 		}
 	}
+	if ((id != NULL) && ((!strncmp(id->model, "SanDisk SD", 10)) ||
+		(!strncmp(id->model, "SunDisk SD", 10)) ||
+		(!strncmp(id->model, "InnoDisk Corp", 13)))) {
+		return 1;
+	}
 	return 0;	/* no, it is not a flash memory card */
 }
 
diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c
index 7e156e0..4f29976 100644
--- a/drivers/ide/ide-proc.c
+++ b/drivers/ide/ide-proc.c
@@ -727,8 +727,14 @@ int proc_ide_read_media
 	int		len;
 
 	switch (drive->media) {
-		case ide_disk:	media = "disk\n";
-				break;
+		case ide_disk:
+			if (drive->is_flash) {
+				media = "disk (flashcard)\n";
+			}
+			else {
+				media = "disk\n";
+			}
+			break;
 		case ide_cdrom:	media = "cdrom\n";
 				break;
 		case ide_tape:	media = "tape\n";
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index 6348573..2b62584 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -452,7 +452,7 @@ EXPORT_SYMBOL(ide_dump_status);
  * usage == 1 (we need an open channel to use an ioctl :-), so this
  * is our limit.
  */
-int ide_revalidate_disk (kdev_t i_rdev)
+int _ide_revalidate_disk (kdev_t i_rdev, int force)
 {
 	ide_drive_t *drive;
 	ide_hwgroup_t *hwgroup;
@@ -465,7 +465,7 @@ int ide_revalidate_disk (kdev_t i_rdev)
 	minor = drive->select.b.unit << PARTN_BITS;
 	hwgroup = HWGROUP(drive);
 	spin_lock_irqsave(&io_request_lock, flags);
-	if (drive->busy || (drive->usage > 1)) {
+	if (drive->busy || ((drive->usage > 1) && (force == 0))) {
 		spin_unlock_irqrestore(&io_request_lock, flags);
 		return -EBUSY;
 	};
@@ -491,6 +491,11 @@ int ide_revalidate_disk (kdev_t i_rdev)
 	return 0;
 }
 
+int ide_revalidate_disk (kdev_t i_rdev)
+{
+	return _ide_revalidate_disk(i_rdev, 0);
+}
+
 EXPORT_SYMBOL(ide_revalidate_disk);
 
 static void revalidate_drives (int revaldiate)
@@ -1808,6 +1813,10 @@ static int ide_ioctl (struct inode *inode, struct file *file,
 		case BLKRRPART: /* Re-read partition tables */
 			if (!capable(CAP_SYS_ADMIN)) return -EACCES;
 			return ide_revalidate_disk(inode->i_rdev);
+		case _IO(0x12,120): /* Force Re-read partition tables */
+			if (!capable(CAP_SYS_ADMIN)) return -EACCES;
+			printk(KERN_INFO "BLKRRPART: ide_revalidate_disk() forced\n");
+			return _ide_revalidate_disk(inode->i_rdev, 1 /* force */);
 
 		case HDIO_OBSOLETE_IDENTITY:
 		case HDIO_GET_IDENTITY:
diff --git a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c
index 45c04e0..dc6751f 100644
--- a/drivers/ide/pci/piix.c
+++ b/drivers/ide/pci/piix.c
@@ -558,9 +558,18 @@ static int piix_config_drive_xfer_rate (ide_drive_t *drive)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
 	struct hd_driveid *id	= drive->id;
+#ifdef CONFIG_IDEDMA_NOFLASH
+	extern int drive_is_flashcard (ide_drive_t *drive);
+#endif
 
 	drive->init_speed = 0;
 
+#ifdef CONFIG_IDEDMA_NOFLASH
+	if ((drive->media == ide_disk) && (drive_is_flashcard(drive))) {
+		goto fast_ata_pio;
+	}
+#endif
+
 	if ((id->capability & 1) && (drive->autodma)) {
 
                 /* Consult the list of known "bad" drives. */
diff --git a/drivers/ide/pci/sc1200.c b/drivers/ide/pci/sc1200.c
index 42c72b6..c2e2871 100644
--- a/drivers/ide/pci/sc1200.c
+++ b/drivers/ide/pci/sc1200.c
@@ -210,6 +210,9 @@ static int sc1200_config_dma2 (ide_drive_t *drive, int mode)
 	unsigned int		reg, timings;
 	unsigned short		pci_clock;
 	unsigned int		basereg = hwif->channel ? 0x50 : 0x40;
+#ifdef CONFIG_IDEDMA_NOFLASH
+	extern int drive_is_flashcard(ide_drive_t *drive);
+#endif
 
 	/*
 	 * Default to DMA-off in case we run into trouble here.
@@ -217,6 +220,12 @@ static int sc1200_config_dma2 (ide_drive_t *drive, int mode)
 	hwif->ide_dma_off_quietly(drive);			/* turn off DMA while we fiddle */
 	outb(inb(hwif->dma_base+2)&~(unit?0x40:0x20), hwif->dma_base+2); /* clear DMA_capable bit */
 
+#ifdef CONFIG_IDEDMA_NOFLASH
+	if ((drive->media == ide_disk) && (drive_is_flashcard(drive))) {
+		return 0;
+	}
+#endif
+
 	/*
 	 * Tell the drive to switch to the new mode; abort on failure.
 	 */
diff --git a/drivers/ide/pci/serverworks.c b/drivers/ide/pci/serverworks.c
index e27e480..c1209f8 100644
--- a/drivers/ide/pci/serverworks.c
+++ b/drivers/ide/pci/serverworks.c
@@ -460,9 +460,18 @@ static int svwks_config_drive_xfer_rate (ide_drive_t *drive)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
 	struct hd_driveid *id	= drive->id;
+#ifdef CONFIG_IDEDMA_NOFLASH
+	extern int drive_is_flashcard (ide_drive_t *drive);
+#endif
 
 	drive->init_speed = 0;
 
+#ifdef CONFIG_IDEDMA_NOFLASH
+	if ((drive->media == ide_disk) && (drive_is_flashcard(drive))) {
+		return hwif->ide_dma_off_quietly(drive);
+	}
+#endif
+
 	if ((id->capability & 1) && drive->autodma) {
 		/* Consult the list of known "bad" drives */
 		if (hwif->ide_dma_bad_drive(drive))
diff --git a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c
index c5974cc..e6fa185 100644
--- a/drivers/ide/pci/via82cxxx.c
+++ b/drivers/ide/pci/via82cxxx.c
@@ -401,6 +401,13 @@ static int via82cxxx_ide_dma_check (ide_drive_t *drive)
 		(w80 && (via_config->flags & VIA_UDMA) >= VIA_UDMA_100 ? XFER_UDMA_100 : 0) |
 		(w80 && (via_config->flags & VIA_UDMA) >= VIA_UDMA_133 ? XFER_UDMA_133 : 0));
 
+#ifdef CONFIG_IDEDMA_NOFLASH
+	extern int drive_is_flashcard (ide_drive_t *drive);
+	if ((drive->media == ide_disk) && (drive_is_flashcard(drive))) {
+		return HWIF(drive)->ide_dma_off_quietly(drive);
+	}
+#endif
+
 	via_set_drive(drive, speed);
 
 	if (drive->autodma && (speed & XFER_MODE) != XFER_PIO)

