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)