ide-probe: remove needless Status register reads
[safe/jmp/linux-2.6] / drivers / ide / ide.c
index 73f7521..d42216b 100644 (file)
@@ -1,7 +1,6 @@
 /*
- *  linux/drivers/ide/ide.c            Version 7.00beta2       Mar 05 2003
- *
- *  Copyright (C) 1994-1998  Linus Torvalds & authors (see below)
+ *  Copyright (C) 1994-1998        Linus Torvalds & authors (see below)
+ *  Copyrifht (C) 2003-2005, 2007   Bartlomiej Zolnierkiewicz
  */
 
 /*
  *   (usually 14 & 15).
  * There can be up to two drives per interface, as per the ATA-2 spec.
  *
- * Primary:    ide0, port 0x1f0; major=3;  hda is minor=0; hdb is minor=64
- * Secondary:  ide1, port 0x170; major=22; hdc is minor=0; hdd is minor=64
- * Tertiary:   ide2, port 0x???; major=33; hde is minor=0; hdf is minor=64
- * Quaternary: ide3, port 0x???; major=34; hdg is minor=0; hdh is minor=64
  * ...
  *
  *  From hd.c:
  *  This was a rewrite of just about everything from hd.c, though some original
  *  code is still sprinkled about.  Think of it as a major evolution, with
  *  inspiration from lots of linux users, esp.  hamish@zot.apana.org.au
- *
- *  Version 1.0 ALPHA  initial code, primary i/f working okay
- *  Version 1.3 BETA   dual i/f on shared irq tested & working!
- *  Version 1.4 BETA   added auto probing for irq(s)
- *  Version 1.5 BETA   added ALPHA (untested) support for IDE cd-roms,
- *  ...
- * Version 5.50                allow values as small as 20 for idebus=
- * Version 5.51                force non io_32bit in drive_cmd_intr()
- *                     change delay_10ms() to delay_50ms() to fix problems
- * Version 5.52                fix incorrect invalidation of removable devices
- *                     add "hdx=slow" command line option
- * Version 5.60                start to modularize the driver; the disk and ATAPI
- *                      drivers can be compiled as loadable modules.
- *                     move IDE probe code to ide-probe.c
- *                     move IDE disk code to ide-disk.c
- *                     add support for generic IDE device subdrivers
- *                     add m68k code from Geert Uytterhoeven
- *                     probe all interfaces by default
- *                     add ioctl to (re)probe an interface
- * Version 6.00                use per device request queues
- *                     attempt to optimize shared hwgroup performance
- *                     add ioctl to manually adjust bandwidth algorithms
- *                     add kerneld support for the probe module
- *                     fix bug in ide_error()
- *                     fix bug in the first ide_get_lock() call for Atari
- *                     don't flush leftover data for ATAPI devices
- * Version 6.01                clear hwgroup->active while the hwgroup sleeps
- *                     support HDIO_GETGEO for floppies
- * Version 6.02                fix ide_ack_intr() call
- *                     check partition table on floppies
- * Version 6.03                handle bad status bit sequencing in ide_wait_stat()
- * Version 6.10                deleted old entries from this list of updates
- *                     replaced triton.c with ide-dma.c generic PCI DMA
- *                     added support for BIOS-enabled UltraDMA
- *                     rename all "promise" things to "pdc4030"
- *                     fix EZ-DRIVE handling on small disks
- * Version 6.11                fix probe error in ide_scan_devices()
- *                     fix ancient "jiffies" polling bugs
- *                     mask all hwgroup interrupts on each irq entry
- * Version 6.12                integrate ioctl and proc interfaces
- *                     fix parsing of "idex=" command line parameter
- * Version 6.13                add support for ide4/ide5 courtesy rjones@orchestream.com
- * Version 6.14                fixed IRQ sharing among PCI devices
- * Version 6.15                added SMP awareness to IDE drivers
- * Version 6.16                fixed various bugs; even more SMP friendly
- * Version 6.17                fix for newest EZ-Drive problem
- * Version 6.18                default unpartitioned-disk translation now "BIOS LBA"
- * Version 6.19                Re-design for a UNIFORM driver for all platforms,
- *                       model based on suggestions from Russell King and
- *                       Geert Uytterhoeven
- *                     Promise DC4030VL now supported.
- *                     add support for ide6/ide7
- *                     delay_50ms() changed to ide_delay_50ms() and exported.
- * Version 6.20                Added/Fixed Generic ATA-66 support and hwif detection.
- *                     Added hdx=flash to allow for second flash disk
- *                       detection w/o the hang loop.
- *                     Added support for ide8/ide9
- *                     Added idex=ata66 for the quirky chipsets that are
- *                       ATA-66 compliant, but have yet to determine a method
- *                       of verification of the 80c cable presence.
- *                       Specifically Promise's PDC20262 chipset.
- * Version 6.21                Fixing/Fixed SMP spinlock issue with insight from an old
- *                       hat that clarified original low level driver design.
- * Version 6.30                Added SMP support; fixed multmode issues.  -ml
- * Version 6.31                Debug Share INTR's and request queue streaming
- *                     Native ATA-100 support
- *                     Prep for Cascades Project
- * Version 7.00alpha   First named revision of ide rearrange
- *
- *  Some additional driver compile-time options are in ./include/linux/ide.h
- *
- *  To do, in likely order of completion:
- *     - modify kernel to obtain BIOS geometry for drives on 2nd/3rd/4th i/f
- *
  */
 
 #define        REVISION        "Revision: 7.00alpha2"
-#define        VERSION         "Id: ide.c 7.00a2 20020906"
 
 #define _IDE_C                 /* Tell ide.h it's really us */
 
@@ -168,19 +88,16 @@ static const u8 ide_hwif_to_major[] = { IDE0_MAJOR, IDE1_MAJOR,
 
 static int idebus_parameter;   /* holds the "idebus=" parameter */
 static int system_bus_speed;   /* holds what we think is VESA/PCI bus speed */
-static int initializing;       /* set while initializing built-in drivers */
 
-DECLARE_MUTEX(ide_cfg_sem);
+DEFINE_MUTEX(ide_cfg_mtx);
  __cacheline_aligned_in_smp DEFINE_SPINLOCK(ide_lock);
 
-#ifdef CONFIG_BLK_DEV_IDEPCI
-static int ide_scan_direction; /* THIS was formerly 2.2.x pci=reverse */
+#ifdef CONFIG_IDEPCI_PCIBUS_ORDER
+int ide_scan_direction; /* THIS was formerly 2.2.x pci=reverse */
 #endif
 
 int noautodma = 0;
 
-EXPORT_SYMBOL(noautodma);
-
 #ifdef CONFIG_BLK_DEV_IDEACPI
 int ide_noacpi = 0;
 int ide_noacpitfs = 1;
@@ -197,7 +114,7 @@ EXPORT_SYMBOL(ide_hwifs);
 /*
  * Do not even *think* about calling this!
  */
-static void init_hwif_data(ide_hwif_t *hwif, unsigned int index)
+void ide_init_port_data(ide_hwif_t *hwif, unsigned int index)
 {
        unsigned int unit;
 
@@ -215,8 +132,6 @@ static void init_hwif_data(ide_hwif_t *hwif, unsigned int index)
 
        hwif->bus_state = BUSSTATE_ON;
 
-       hwif->atapi_dma = 0;            /* disable all atapi dma */ 
-
        init_completion(&hwif->gendev_rel_comp);
 
        default_hwif_iops(hwif);
@@ -242,6 +157,7 @@ static void init_hwif_data(ide_hwif_t *hwif, unsigned int index)
                init_completion(&drive->gendev_rel_comp);
        }
 }
+EXPORT_SYMBOL_GPL(ide_init_port_data);
 
 static void init_hwif_default(ide_hwif_t *hwif, unsigned int index)
 {
@@ -251,7 +167,6 @@ static void init_hwif_default(ide_hwif_t *hwif, unsigned int index)
 
        ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, &hwif->irq);
 
-       memcpy(&hwif->hw, &hw, sizeof(hw));
        memcpy(hwif->io_ports, hw.io_ports, sizeof(hw.io_ports));
 
        hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET];
@@ -261,8 +176,6 @@ static void init_hwif_default(ide_hwif_t *hwif, unsigned int index)
 #endif
 }
 
-extern void ide_arm_init(void);
-
 /*
  * init_ide_data() sets reasonable default values into all fields
  * of all instances of the hwifs and drives, but only on the first call.
@@ -294,18 +207,13 @@ static void __init init_ide_data (void)
        /* Initialise all interface structures */
        for (index = 0; index < MAX_HWIFS; ++index) {
                hwif = &ide_hwifs[index];
-               init_hwif_data(hwif, index);
+               ide_init_port_data(hwif, index);
                init_hwif_default(hwif, index);
 #if !defined(CONFIG_PPC32) || !defined(CONFIG_PCI)
-               hwif->irq = hwif->hw.irq =
+               hwif->irq =
                        ide_init_default_irq(hwif->io_ports[IDE_DATA_OFFSET]);
 #endif
        }
-#ifdef CONFIG_IDE_ARM
-       initializing = 1;
-       ide_arm_init();
-       initializing = 0;
-#endif
 }
 
 /**
@@ -332,27 +240,37 @@ static int ide_system_bus_speed(void)
 #define pci_default 0
 #endif /* CONFIG_PCI */
 
-       if (!system_bus_speed) {
-               if (idebus_parameter) {
-                       /* user supplied value */
-                       system_bus_speed = idebus_parameter;
-               } else if (pci_dev_present(pci_default)) {
-                       /* safe default value for PCI */
-                       system_bus_speed = 33;
-               } else {
-                       /* safe default value for VESA and PCI */
-                       system_bus_speed = 50;
-               }
-               printk(KERN_INFO "ide: Assuming %dMHz system bus speed "
-                       "for PIO modes%s\n", system_bus_speed,
-                       idebus_parameter ? "" : "; override with idebus=xx");
+       /* user supplied value */
+       if (idebus_parameter)
+               return idebus_parameter;
+
+       /* safe default value for PCI or VESA and PCI*/
+       return pci_dev_present(pci_default) ? 33 : 50;
+}
+
+ide_hwif_t * ide_find_port(unsigned long base)
+{
+       ide_hwif_t *hwif;
+       int i;
+
+       for (i = 0; i < MAX_HWIFS; i++) {
+               hwif = &ide_hwifs[i];
+               if (hwif->io_ports[IDE_DATA_OFFSET] == base)
+                       goto found;
        }
-       return system_bus_speed;
+
+       for (i = 0; i < MAX_HWIFS; i++) {
+               hwif = &ide_hwifs[i];
+               if (hwif->io_ports[IDE_DATA_OFFSET] == 0)
+                       goto found;
+       }
+
+       hwif = NULL;
+found:
+       return hwif;
 }
 
-#ifdef CONFIG_PROC_FS
-struct proc_dir_entry *proc_ide_root;
-#endif
+EXPORT_SYMBOL_GPL(ide_find_port);
 
 static struct resource* hwif_request_region(ide_hwif_t *hwif,
                                            unsigned long addr, int num)
@@ -462,27 +380,33 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif)
        hwif->straight8                 = tmp_hwif->straight8;
        hwif->bus_state                 = tmp_hwif->bus_state;
 
-       hwif->atapi_dma                 = tmp_hwif->atapi_dma;
+       hwif->host_flags                = tmp_hwif->host_flags;
+
+       hwif->pio_mask                  = tmp_hwif->pio_mask;
+
        hwif->ultra_mask                = tmp_hwif->ultra_mask;
        hwif->mwdma_mask                = tmp_hwif->mwdma_mask;
        hwif->swdma_mask                = tmp_hwif->swdma_mask;
 
+       hwif->cbl                       = tmp_hwif->cbl;
+
        hwif->chipset                   = tmp_hwif->chipset;
        hwif->hold                      = tmp_hwif->hold;
 
+       hwif->dev                       = tmp_hwif->dev;
+
 #ifdef CONFIG_BLK_DEV_IDEPCI
-       hwif->pci_dev                   = tmp_hwif->pci_dev;
        hwif->cds                       = tmp_hwif->cds;
 #endif
 
-       hwif->tuneproc                  = tmp_hwif->tuneproc;
-       hwif->speedproc                 = tmp_hwif->speedproc;
+       hwif->set_pio_mode              = tmp_hwif->set_pio_mode;
+       hwif->set_dma_mode              = tmp_hwif->set_dma_mode;
+       hwif->mdma_filter               = tmp_hwif->mdma_filter;
        hwif->udma_filter               = tmp_hwif->udma_filter;
        hwif->selectproc                = tmp_hwif->selectproc;
        hwif->reset_poll                = tmp_hwif->reset_poll;
        hwif->pre_reset                 = tmp_hwif->pre_reset;
        hwif->resetproc                 = tmp_hwif->resetproc;
-       hwif->intrproc                  = tmp_hwif->intrproc;
        hwif->maskproc                  = tmp_hwif->maskproc;
        hwif->quirkproc                 = tmp_hwif->quirkproc;
        hwif->busproc                   = tmp_hwif->busproc;
@@ -492,19 +416,15 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif)
        hwif->atapi_input_bytes         = tmp_hwif->atapi_input_bytes;
        hwif->atapi_output_bytes        = tmp_hwif->atapi_output_bytes;
 
+       hwif->dma_host_set              = tmp_hwif->dma_host_set;
        hwif->dma_setup                 = tmp_hwif->dma_setup;
        hwif->dma_exec_cmd              = tmp_hwif->dma_exec_cmd;
        hwif->dma_start                 = tmp_hwif->dma_start;
        hwif->ide_dma_end               = tmp_hwif->ide_dma_end;
-       hwif->ide_dma_check             = tmp_hwif->ide_dma_check;
-       hwif->ide_dma_on                = tmp_hwif->ide_dma_on;
-       hwif->dma_off_quietly           = tmp_hwif->dma_off_quietly;
        hwif->ide_dma_test_irq          = tmp_hwif->ide_dma_test_irq;
        hwif->ide_dma_clear_irq         = tmp_hwif->ide_dma_clear_irq;
-       hwif->dma_host_on               = tmp_hwif->dma_host_on;
-       hwif->dma_host_off              = tmp_hwif->dma_host_off;
-       hwif->ide_dma_lostirq           = tmp_hwif->ide_dma_lostirq;
-       hwif->ide_dma_timeout           = tmp_hwif->ide_dma_timeout;
+       hwif->dma_lost_irq              = tmp_hwif->dma_lost_irq;
+       hwif->dma_timeout               = tmp_hwif->dma_timeout;
 
        hwif->OUTB                      = tmp_hwif->OUTB;
        hwif->OUTBSYNC                  = tmp_hwif->OUTBSYNC;
@@ -521,14 +441,12 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif)
 
        hwif->mmio                      = tmp_hwif->mmio;
        hwif->rqsize                    = tmp_hwif->rqsize;
-       hwif->no_lba48                  = tmp_hwif->no_lba48;
 
 #ifndef CONFIG_BLK_DEV_IDECS
        hwif->irq                       = tmp_hwif->irq;
 #endif
 
        hwif->dma_base                  = tmp_hwif->dma_base;
-       hwif->dma_master                = tmp_hwif->dma_master;
        hwif->dma_command               = tmp_hwif->dma_command;
        hwif->dma_vendor1               = tmp_hwif->dma_vendor1;
        hwif->dma_status                = tmp_hwif->dma_status;
@@ -539,15 +457,50 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif)
        hwif->select_data               = tmp_hwif->select_data;
        hwif->extra_base                = tmp_hwif->extra_base;
        hwif->extra_ports               = tmp_hwif->extra_ports;
-       hwif->autodma                   = tmp_hwif->autodma;
-       hwif->udma_four                 = tmp_hwif->udma_four;
 
        hwif->hwif_data                 = tmp_hwif->hwif_data;
 }
 
+void ide_remove_port_from_hwgroup(ide_hwif_t *hwif)
+{
+       ide_hwgroup_t *hwgroup = hwif->hwgroup;
+
+       spin_lock_irq(&ide_lock);
+       /*
+        * Remove us from the hwgroup, and free
+        * the hwgroup if we were the only member
+        */
+       if (hwif->next == hwif) {
+               BUG_ON(hwgroup->hwif != hwif);
+               kfree(hwgroup);
+       } else {
+               /* There is another interface in hwgroup.
+                * Unlink us, and set hwgroup->drive and ->hwif to
+                * something sane.
+                */
+               ide_hwif_t *g = hwgroup->hwif;
+
+               while (g->next != hwif)
+                       g = g->next;
+               g->next = hwif->next;
+               if (hwgroup->hwif == hwif) {
+                       /* Chose a random hwif for hwgroup->hwif.
+                        * It's guaranteed that there are no drives
+                        * left in the hwgroup.
+                        */
+                       BUG_ON(hwgroup->drive != NULL);
+                       hwgroup->hwif = g;
+               }
+               BUG_ON(hwgroup->hwif == hwif);
+       }
+       spin_unlock_irq(&ide_lock);
+}
+
 /**
  *     ide_unregister          -       free an IDE interface
  *     @index: index of interface (will change soon to a pointer)
+ *     @init_default: init default hwif flag
+ *     @restore: restore hwif flag
  *
  *     Perform the final unregister of an IDE interface. At the moment
  *     we don't refcount interfaces so this will also get split up.
@@ -567,11 +520,11 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif)
  *     This is raving bonkers.
  */
 
-void ide_unregister(unsigned int index)
+void ide_unregister(unsigned int index, int init_default, int restore)
 {
        ide_drive_t *drive;
        ide_hwif_t *hwif, *g;
-       static ide_hwif_t tmp_hwif; /* protected by ide_cfg_sem */
+       static ide_hwif_t tmp_hwif; /* protected by ide_cfg_mtx */
        ide_hwgroup_t *hwgroup;
        int irq_count = 0, unit;
 
@@ -579,7 +532,7 @@ void ide_unregister(unsigned int index)
 
        BUG_ON(in_interrupt());
        BUG_ON(irqs_disabled());
-       down(&ide_cfg_sem);
+       mutex_lock(&ide_cfg_mtx);
        spin_lock_irq(&ide_lock);
        hwif = &ide_hwifs[index];
        if (!hwif->present)
@@ -597,7 +550,7 @@ void ide_unregister(unsigned int index)
 
        spin_unlock_irq(&ide_lock);
 
-       destroy_proc_ide_interface(hwif);
+       ide_proc_unregister_port(hwif);
 
        hwgroup = hwif->hwgroup;
        /*
@@ -612,43 +565,8 @@ void ide_unregister(unsigned int index)
        if (irq_count == 1)
                free_irq(hwif->irq, hwgroup);
 
-       spin_lock_irq(&ide_lock);
-       /*
-        * Note that we only release the standard ports,
-        * and do not even try to handle any extra ports
-        * allocated for weird IDE interface chipsets.
-        */
-       ide_hwif_release_regions(hwif);
-
-       /*
-        * Remove us from the hwgroup, and free
-        * the hwgroup if we were the only member
-        */
-       if (hwif->next == hwif) {
-               BUG_ON(hwgroup->hwif != hwif);
-               kfree(hwgroup);
-       } else {
-               /* There is another interface in hwgroup.
-                * Unlink us, and set hwgroup->drive and ->hwif to
-                * something sane.
-                */
-               g = hwgroup->hwif;
-               while (g->next != hwif)
-                       g = g->next;
-               g->next = hwif->next;
-               if (hwgroup->hwif == hwif) {
-                       /* Chose a random hwif for hwgroup->hwif.
-                        * It's guaranteed that there are no drives
-                        * left in the hwgroup.
-                        */
-                       BUG_ON(hwgroup->drive != NULL);
-                       hwgroup->hwif = g;
-               }
-               BUG_ON(hwgroup->hwif == hwif);
-       }
+       ide_remove_port_from_hwgroup(hwif);
 
-       /* More messed up locking ... */
-       spin_unlock_irq(&ide_lock);
        device_unregister(&hwif->gendev);
        wait_for_completion(&hwif->gendev_rel_comp);
 
@@ -664,7 +582,6 @@ void ide_unregister(unsigned int index)
                (void) ide_release_dma(hwif);
 
                hwif->dma_base = 0;
-               hwif->dma_master = 0;
                hwif->dma_command = 0;
                hwif->dma_vendor1 = 0;
                hwif->dma_status = 0;
@@ -675,18 +592,28 @@ void ide_unregister(unsigned int index)
                hwif->extra_ports = 0;
        }
 
+       /*
+        * Note that we only release the standard ports,
+        * and do not even try to handle any extra ports
+        * allocated for weird IDE interface chipsets.
+        */
+       ide_hwif_release_regions(hwif);
+
        /* copy original settings */
        tmp_hwif = *hwif;
 
        /* restore hwif data to pristine status */
-       init_hwif_data(hwif, index);
-       init_hwif_default(hwif, index);
+       ide_init_port_data(hwif, index);
 
-       ide_hwif_restore(hwif, &tmp_hwif);
+       if (init_default)
+               init_hwif_default(hwif, index);
+
+       if (restore)
+               ide_hwif_restore(hwif, &tmp_hwif);
 
 abort:
        spin_unlock_irq(&ide_lock);
-       up(&ide_cfg_sem);
+       mutex_unlock(&ide_cfg_mtx);
 }
 
 EXPORT_SYMBOL(ide_unregister);
@@ -739,80 +666,92 @@ void ide_setup_ports (    hw_regs_t *hw,
                }
        }
        hw->irq = irq;
-       hw->dma = NO_DMA;
        hw->ack_intr = ack_intr;
 /*
  *     hw->iops = iops;
  */
 }
 
+void ide_init_port_hw(ide_hwif_t *hwif, hw_regs_t *hw)
+{
+       memcpy(hwif->io_ports, hw->io_ports, sizeof(hwif->io_ports));
+       hwif->irq = hw->irq;
+       hwif->noprobe = 0;
+       hwif->chipset = hw->chipset;
+       hwif->gendev.parent = hw->dev;
+       hwif->ack_intr = hw->ack_intr;
+}
+EXPORT_SYMBOL_GPL(ide_init_port_hw);
+
+ide_hwif_t *ide_deprecated_find_port(unsigned long base)
+{
+       ide_hwif_t *hwif;
+       int i;
+
+       for (i = 0; i < MAX_HWIFS; i++) {
+               hwif = &ide_hwifs[i];
+               if (hwif->io_ports[IDE_DATA_OFFSET] == base)
+                       goto found;
+       }
+
+       for (i = 0; i < MAX_HWIFS; i++) {
+               hwif = &ide_hwifs[i];
+               if (hwif->hold)
+                       continue;
+               if (!hwif->present && hwif->mate == NULL)
+                       goto found;
+       }
+
+       hwif = NULL;
+found:
+       return hwif;
+}
+EXPORT_SYMBOL_GPL(ide_deprecated_find_port);
+
 /**
- *     ide_register_hw_with_fixup      -       register IDE interface
+ *     ide_register_hw         -       register IDE interface
  *     @hw: hardware registers
+ *     @quirkproc: quirkproc function
  *     @hwifp: pointer to returned hwif
- *     @fixup: fixup function
  *
  *     Register an IDE interface, specifying exactly the registers etc.
- *     Set init=1 iff calling before probes have taken place.
  *
  *     Returns -1 on error.
  */
 
-int ide_register_hw_with_fixup(hw_regs_t *hw, ide_hwif_t **hwifp, void(*fixup)(ide_hwif_t *hwif))
+int ide_register_hw(hw_regs_t *hw, void (*quirkproc)(ide_drive_t *),
+                   ide_hwif_t **hwifp)
 {
        int index, retry = 1;
        ide_hwif_t *hwif;
+       u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
 
        do {
-               for (index = 0; index < MAX_HWIFS; ++index) {
-                       hwif = &ide_hwifs[index];
-                       if (hwif->hw.io_ports[IDE_DATA_OFFSET] == hw->io_ports[IDE_DATA_OFFSET])
-                               goto found;
-               }
-               for (index = 0; index < MAX_HWIFS; ++index) {
-                       hwif = &ide_hwifs[index];
-                       if (hwif->hold)
-                               continue;
-                       if ((!hwif->present && !hwif->mate && !initializing) ||
-                           (!hwif->hw.io_ports[IDE_DATA_OFFSET] && initializing))
-                               goto found;
-               }
+               hwif = ide_deprecated_find_port(hw->io_ports[IDE_DATA_OFFSET]);
+               index = hwif->index;
+               if (hwif)
+                       goto found;
                for (index = 0; index < MAX_HWIFS; index++)
-                       ide_unregister(index);
+                       ide_unregister(index, 1, 1);
        } while (retry--);
        return -1;
 found:
        if (hwif->present)
-               ide_unregister(index);
-       else if (!hwif->hold) {
-               init_hwif_data(hwif, index);
-               init_hwif_default(hwif, index);
-       }
-       if (hwif->present)
-               return -1;
-       memcpy(&hwif->hw, hw, sizeof(*hw));
-       memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->hw.io_ports));
-       hwif->irq = hw->irq;
-       hwif->noprobe = 0;
-       hwif->chipset = hw->chipset;
-       hwif->gendev.parent = hw->dev;
+               ide_unregister(index, 0, 1);
+       else if (!hwif->hold)
+               ide_init_port_data(hwif, index);
 
-       if (!initializing) {
-               probe_hwif_init_with_fixup(hwif, fixup);
-               create_proc_ide_interfaces();
-       }
+       ide_init_port_hw(hwif, hw);
+       hwif->quirkproc = quirkproc;
 
-       if (hwifp)
-               *hwifp = hwif;
+       idx[0] = index;
 
-       return (initializing || hwif->present) ? index : -1;
-}
+       ide_device_add(idx, NULL);
 
-EXPORT_SYMBOL(ide_register_hw_with_fixup);
+       if (hwifp)
+               *hwifp = hwif;
 
-int ide_register_hw(hw_regs_t *hw, ide_hwif_t **hwifp)
-{
-       return ide_register_hw_with_fixup(hw, hwifp, NULL);
+       return hwif->present ? index : -1;
 }
 
 EXPORT_SYMBOL(ide_register_hw);
@@ -821,207 +760,9 @@ EXPORT_SYMBOL(ide_register_hw);
  *     Locks for IDE setting functionality
  */
 
-DECLARE_MUTEX(ide_setting_sem);
-
-/**
- *     __ide_add_setting       -       add an ide setting option
- *     @drive: drive to use
- *     @name: setting name
- *     @rw: true if the function is read write
- *     @read_ioctl: function to call on read
- *     @write_ioctl: function to call on write
- *     @data_type: type of data
- *     @min: range minimum
- *     @max: range maximum
- *     @mul_factor: multiplication scale
- *     @div_factor: divison scale
- *     @data: private data field
- *     @set: setting
- *     @auto_remove: setting auto removal flag
- *
- *     Removes the setting named from the device if it is present.
- *     The function takes the settings_lock to protect against 
- *     parallel changes. This function must not be called from IRQ
- *     context. Returns 0 on success or -1 on failure.
- *
- *     BUGS: This code is seriously over-engineered. There is also
- *     magic about how the driver specific features are setup. If
- *     a driver is attached we assume the driver settings are auto
- *     remove.
- */
-
-static int __ide_add_setting(ide_drive_t *drive, const char *name, int rw, int read_ioctl, int write_ioctl, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set, int auto_remove)
-{
-       ide_settings_t **p = (ide_settings_t **) &drive->settings, *setting = NULL;
-
-       down(&ide_setting_sem);
-       while ((*p) && strcmp((*p)->name, name) < 0)
-               p = &((*p)->next);
-       if ((setting = kzalloc(sizeof(*setting), GFP_KERNEL)) == NULL)
-               goto abort;
-       if ((setting->name = kmalloc(strlen(name) + 1, GFP_KERNEL)) == NULL)
-               goto abort;
-       strcpy(setting->name, name);
-       setting->rw = rw;
-       setting->read_ioctl = read_ioctl;
-       setting->write_ioctl = write_ioctl;
-       setting->data_type = data_type;
-       setting->min = min;
-       setting->max = max;
-       setting->mul_factor = mul_factor;
-       setting->div_factor = div_factor;
-       setting->data = data;
-       setting->set = set;
-       
-       setting->next = *p;
-       if (auto_remove)
-               setting->auto_remove = 1;
-       *p = setting;
-       up(&ide_setting_sem);
-       return 0;
-abort:
-       up(&ide_setting_sem);
-       kfree(setting);
-       return -1;
-}
-
-int ide_add_setting(ide_drive_t *drive, const char *name, int rw, int read_ioctl, int write_ioctl, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set)
-{
-       return __ide_add_setting(drive, name, rw, read_ioctl, write_ioctl, data_type, min, max, mul_factor, div_factor, data, set, 1);
-}
-
-EXPORT_SYMBOL(ide_add_setting);
-
-/**
- *     __ide_remove_setting    -       remove an ide setting option
- *     @drive: drive to use
- *     @name: setting name
- *
- *     Removes the setting named from the device if it is present.
- *     The caller must hold the setting semaphore.
- */
-static void __ide_remove_setting (ide_drive_t *drive, char *name)
-{
-       ide_settings_t **p, *setting;
-
-       p = (ide_settings_t **) &drive->settings;
-
-       while ((*p) && strcmp((*p)->name, name))
-               p = &((*p)->next);
-       if ((setting = (*p)) == NULL)
-               return;
-
-       (*p) = setting->next;
-       
-       kfree(setting->name);
-       kfree(setting);
-}
-
-/**
- *     ide_find_setting_by_ioctl       -       find a drive specific ioctl
- *     @drive: drive to scan
- *     @cmd: ioctl command to handle
- *
- *     Scan's the device setting table for a matching entry and returns
- *     this or NULL if no entry is found. The caller must hold the
- *     setting semaphore
- */
-static ide_settings_t *ide_find_setting_by_ioctl (ide_drive_t *drive, int cmd)
-{
-       ide_settings_t *setting = drive->settings;
-
-       while (setting) {
-               if (setting->read_ioctl == cmd || setting->write_ioctl == cmd)
-                       break;
-               setting = setting->next;
-       }
-       
-       return setting;
-}
-
-/**
- *     ide_find_setting_by_name        -       find a drive specific setting
- *     @drive: drive to scan
- *     @name: setting name
- *
- *     Scan's the device setting table for a matching entry and returns
- *     this or NULL if no entry is found. The caller must hold the
- *     setting semaphore
- */
-ide_settings_t *ide_find_setting_by_name (ide_drive_t *drive, char *name)
-{
-       ide_settings_t *setting = drive->settings;
-
-       while (setting) {
-               if (strcmp(setting->name, name) == 0)
-                       break;
-               setting = setting->next;
-       }
-       return setting;
-}
-
-/**
- *     auto_remove_settings    -       remove driver specific settings
- *     @drive: drive
- *
- *     Automatically remove all the driver specific settings for this
- *     drive. This function may not be called from IRQ context. The
- *     caller must hold ide_setting_sem.
- */
-static void auto_remove_settings (ide_drive_t *drive)
-{
-       ide_settings_t *setting;
-repeat:
-       setting = drive->settings;
-       while (setting) {
-               if (setting->auto_remove) {
-                       __ide_remove_setting(drive, setting->name);
-                       goto repeat;
-               }
-               setting = setting->next;
-       }
-}
+DEFINE_MUTEX(ide_setting_mtx);
 
-/**
- *     ide_read_setting        -       read an IDE setting
- *     @drive: drive to read from
- *     @setting: drive setting
- *
- *     Read a drive setting and return the value. The caller
- *     must hold the ide_setting_sem when making this call.
- *
- *     BUGS: the data return and error are the same return value
- *     so an error -EINVAL and true return of the same value cannot
- *     be told apart
- */
-int ide_read_setting (ide_drive_t *drive, ide_settings_t *setting)
-{
-       int             val = -EINVAL;
-       unsigned long   flags;
-
-       if ((setting->rw & SETTING_READ)) {
-               spin_lock_irqsave(&ide_lock, flags);
-               switch(setting->data_type) {
-                       case TYPE_BYTE:
-                               val = *((u8 *) setting->data);
-                               break;
-                       case TYPE_SHORT:
-                               val = *((u16 *) setting->data);
-                               break;
-                       case TYPE_INT:
-                       case TYPE_INTA:
-                               val = *((u32 *) setting->data);
-                               break;
-               }
-               spin_unlock_irqrestore(&ide_lock, flags);
-       }
-       return val;
-}
+EXPORT_SYMBOL_GPL(ide_setting_mtx);
 
 /**
  *     ide_spin_wait_hwgroup   -       wait for group
@@ -1056,79 +797,50 @@ int ide_spin_wait_hwgroup (ide_drive_t *drive)
 
 EXPORT_SYMBOL(ide_spin_wait_hwgroup);
 
-/**
- *     ide_write_setting       -       read an IDE setting
- *     @drive: drive to read from
- *     @setting: drive setting
- *     @val: value
- *
- *     Write a drive setting if it is possible. The caller
- *     must hold the ide_setting_sem when making this call.
- *
- *     BUGS: the data return and error are the same return value
- *     so an error -EINVAL and true return of the same value cannot
- *     be told apart
- *
- *     FIXME:  This should be changed to enqueue a special request
- *     to the driver to change settings, and then wait on a sema for completion.
- *     The current scheme of polling is kludgy, though safe enough.
- */
-
-int ide_write_setting (ide_drive_t *drive, ide_settings_t *setting, int val)
+int set_io_32bit(ide_drive_t *drive, int arg)
 {
-       int i;
-       u32 *p;
-
-       if (!capable(CAP_SYS_ADMIN))
-               return -EACCES;
-       if (!(setting->rw & SETTING_WRITE))
+       if (drive->no_io_32bit)
                return -EPERM;
-       if (val < setting->min || val > setting->max)
+
+       if (arg < 0 || arg > 1 + (SUPPORT_VLB_SYNC << 1))
                return -EINVAL;
-       if (setting->set)
-               return setting->set(drive, val);
+
        if (ide_spin_wait_hwgroup(drive))
                return -EBUSY;
-       switch (setting->data_type) {
-               case TYPE_BYTE:
-                       *((u8 *) setting->data) = val;
-                       break;
-               case TYPE_SHORT:
-                       *((u16 *) setting->data) = val;
-                       break;
-               case TYPE_INT:
-                       *((u32 *) setting->data) = val;
-                       break;
-               case TYPE_INTA:
-                       p = (u32 *) setting->data;
-                       for (i = 0; i < 1 << PARTN_BITS; i++, p++)
-                               *p = val;
-                       break;
-       }
+
+       drive->io_32bit = arg;
+
        spin_unlock_irq(&ide_lock);
+
        return 0;
 }
 
-static int set_io_32bit(ide_drive_t *drive, int arg)
+static int set_ksettings(ide_drive_t *drive, int arg)
 {
-       drive->io_32bit = arg;
-#ifdef CONFIG_BLK_DEV_DTC2278
-       if (HWIF(drive)->chipset == ide_dtc2278)
-               HWIF(drive)->drives[!drive->select.b.unit].io_32bit = arg;
-#endif /* CONFIG_BLK_DEV_DTC2278 */
+       if (arg < 0 || arg > 1)
+               return -EINVAL;
+
+       if (ide_spin_wait_hwgroup(drive))
+               return -EBUSY;
+       drive->keep_settings = arg;
+       spin_unlock_irq(&ide_lock);
+
        return 0;
 }
 
-static int set_using_dma (ide_drive_t *drive, int arg)
+int set_using_dma(ide_drive_t *drive, int arg)
 {
 #ifdef CONFIG_BLK_DEV_IDEDMA
        ide_hwif_t *hwif = drive->hwif;
        int err = -EPERM;
 
+       if (arg < 0 || arg > 1)
+               return -EINVAL;
+
        if (!drive->id || !(drive->id->capability & 1))
                goto out;
 
-       if (hwif->ide_dma_check == NULL)
+       if (hwif->dma_host_set == NULL)
                goto out;
 
        err = -EBUSY;
@@ -1143,7 +855,7 @@ static int set_using_dma (ide_drive_t *drive, int arg)
        err = 0;
 
        if (arg) {
-               if (ide_set_dma(drive) || hwif->ide_dma_on(drive))
+               if (ide_set_dma(drive))
                        err = -EIO;
        } else
                ide_dma_off(drive);
@@ -1157,61 +869,49 @@ static int set_using_dma (ide_drive_t *drive, int arg)
 out:
        return err;
 #else
+       if (arg < 0 || arg > 1)
+               return -EINVAL;
+
        return -EPERM;
 #endif
 }
 
-static int set_pio_mode (ide_drive_t *drive, int arg)
+int set_pio_mode(ide_drive_t *drive, int arg)
 {
        struct request rq;
 
-       if (!HWIF(drive)->tuneproc)
+       if (arg < 0 || arg > 255)
+               return -EINVAL;
+
+       if (drive->hwif->set_pio_mode == NULL)
                return -ENOSYS;
+
        if (drive->special.b.set_tune)
                return -EBUSY;
+
        ide_init_drive_cmd(&rq);
+       rq.cmd_type = REQ_TYPE_ATA_TASKFILE;
+
        drive->tune_req = (u8) arg;
        drive->special.b.set_tune = 1;
        (void) ide_do_drive_cmd(drive, &rq, ide_wait);
        return 0;
 }
 
-static int set_xfer_rate (ide_drive_t *drive, int arg)
+static int set_unmaskirq(ide_drive_t *drive, int arg)
 {
-       int err = ide_wait_cmd(drive,
-                       WIN_SETFEATURES, (u8) arg,
-                       SETFEATURES_XFER, 0, NULL);
+       if (drive->no_unmask)
+               return -EPERM;
 
-       if (!err && arg) {
-               ide_set_xfer_rate(drive, (u8) arg);
-               ide_driveid_update(drive);
-       }
-       return err;
-}
+       if (arg < 0 || arg > 1)
+               return -EINVAL;
 
-/**
- *     ide_add_generic_settings        -       generic ide settings
- *     @drive: drive being configured
- *
- *     Add the generic parts of the system settings to the /proc files and
- *     ioctls for this IDE device. The caller must not be holding the
- *     ide_setting_sem.
- */
+       if (ide_spin_wait_hwgroup(drive))
+               return -EBUSY;
+       drive->unmask = arg;
+       spin_unlock_irq(&ide_lock);
 
-void ide_add_generic_settings (ide_drive_t *drive)
-{
-/*
- *                       drive         setting name            read/write access                               read ioctl              write ioctl             data type       min     max                             mul_factor      div_factor      data pointer                    set function
- */
-       __ide_add_setting(drive,        "io_32bit",             drive->no_io_32bit ? SETTING_READ : SETTING_RW, HDIO_GET_32BIT,         HDIO_SET_32BIT,         TYPE_BYTE,      0,      1 + (SUPPORT_VLB_SYNC << 1),    1,              1,              &drive->io_32bit,               set_io_32bit,   0);
-       __ide_add_setting(drive,        "keepsettings",         SETTING_RW,                                     HDIO_GET_KEEPSETTINGS,  HDIO_SET_KEEPSETTINGS,  TYPE_BYTE,      0,      1,                              1,              1,              &drive->keep_settings,          NULL,           0);
-       __ide_add_setting(drive,        "nice1",                SETTING_RW,                                     -1,                     -1,                     TYPE_BYTE,      0,      1,                              1,              1,              &drive->nice1,                  NULL,           0);
-       __ide_add_setting(drive,        "pio_mode",             SETTING_WRITE,                                  -1,                     HDIO_SET_PIO_MODE,      TYPE_BYTE,      0,      255,                            1,              1,              NULL,                           set_pio_mode,   0);
-       __ide_add_setting(drive,        "unmaskirq",            drive->no_unmask ? SETTING_READ : SETTING_RW,   HDIO_GET_UNMASKINTR,    HDIO_SET_UNMASKINTR,    TYPE_BYTE,      0,      1,                              1,              1,              &drive->unmask,                 NULL,           0);
-       __ide_add_setting(drive,        "using_dma",            SETTING_RW,                                     HDIO_GET_DMA,           HDIO_SET_DMA,           TYPE_BYTE,      0,      1,                              1,              1,              &drive->using_dma,              set_using_dma,  0);
-       __ide_add_setting(drive,        "init_speed",           SETTING_RW,                                     -1,                     -1,                     TYPE_BYTE,      0,      70,                             1,              1,              &drive->init_speed,             NULL,           0);
-       __ide_add_setting(drive,        "current_speed",        SETTING_RW,                                     -1,                     -1,                     TYPE_BYTE,      0,      70,                             1,              1,              &drive->current_speed,          set_xfer_rate,  0);
-       __ide_add_setting(drive,        "number",               SETTING_RW,                                     -1,                     -1,                     TYPE_BYTE,      0,      3,                              1,              1,              &drive->dn,                     NULL,           0);
+       return 0;
 }
 
 /**
@@ -1223,7 +923,7 @@ void ide_add_generic_settings (ide_drive_t *drive)
 
 int system_bus_clock (void)
 {
-       return((int) ((!system_bus_speed) ? ide_system_bus_speed() : system_bus_speed ));
+       return system_bus_speed;
 }
 
 EXPORT_SYMBOL(system_bus_clock);
@@ -1235,6 +935,7 @@ static int generic_ide_suspend(struct device *dev, pm_message_t mesg)
        struct request rq;
        struct request_pm_state rqpm;
        ide_task_t args;
+       int ret;
 
        /* Call ACPI _GTM only once */
        if (!(drive->dn % 2))
@@ -1251,7 +952,14 @@ static int generic_ide_suspend(struct device *dev, pm_message_t mesg)
                mesg.event = PM_EVENT_FREEZE;
        rqpm.pm_state = mesg.event;
 
-       return ide_do_drive_cmd(drive, &rq, ide_wait);
+       ret = ide_do_drive_cmd(drive, &rq, ide_wait);
+       /* only call ACPI _PS3 after both drivers are suspended */
+       if (!ret && (((drive->dn % 2) && hwif->drives[0].present
+                && hwif->drives[1].present)
+                || !hwif->drives[0].present
+                || !hwif->drives[1].present))
+               ide_acpi_set_state(hwif, 0);
+       return ret;
 }
 
 static int generic_ide_resume(struct device *dev)
@@ -1261,10 +969,13 @@ static int generic_ide_resume(struct device *dev)
        struct request rq;
        struct request_pm_state rqpm;
        ide_task_t args;
+       int err;
 
        /* Call ACPI _STM only once */
-       if (!(drive->dn % 2))
+       if (!(drive->dn % 2)) {
+               ide_acpi_set_state(hwif, 1);
                ide_acpi_push_timing(hwif);
+       }
 
        ide_acpi_exec_tfs(drive);
 
@@ -1277,33 +988,38 @@ static int generic_ide_resume(struct device *dev)
        rqpm.pm_step = ide_pm_state_start_resume;
        rqpm.pm_state = PM_EVENT_ON;
 
-       return ide_do_drive_cmd(drive, &rq, ide_head_wait);
+       err = ide_do_drive_cmd(drive, &rq, ide_head_wait);
+
+       if (err == 0 && dev->driver) {
+               ide_driver_t *drv = to_ide_driver(dev->driver);
+
+               if (drv->resume)
+                       drv->resume(drive);
+       }
+
+       return err;
 }
 
 int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device *bdev,
                        unsigned int cmd, unsigned long arg)
 {
-       ide_settings_t *setting;
+       unsigned long flags;
        ide_driver_t *drv;
-       int err = 0;
        void __user *p = (void __user *)arg;
+       int err = 0, (*setfunc)(ide_drive_t *, int);
+       u8 *val;
 
-       down(&ide_setting_sem);
-       if ((setting = ide_find_setting_by_ioctl(drive, cmd)) != NULL) {
-               if (cmd == setting->read_ioctl) {
-                       err = ide_read_setting(drive, setting);
-                       up(&ide_setting_sem);
-                       return err >= 0 ? put_user(err, (long __user *)arg) : err;
-               } else {
-                       if (bdev != bdev->bd_contains)
-                               err = -EINVAL;
-                       else
-                               err = ide_write_setting(drive, setting, arg);
-                       up(&ide_setting_sem);
-                       return err;
-               }
+       switch (cmd) {
+       case HDIO_GET_32BIT:        val = &drive->io_32bit;      goto read_val;
+       case HDIO_GET_KEEPSETTINGS: val = &drive->keep_settings; goto read_val;
+       case HDIO_GET_UNMASKINTR:   val = &drive->unmask;        goto read_val;
+       case HDIO_GET_DMA:          val = &drive->using_dma;     goto read_val;
+       case HDIO_SET_32BIT:        setfunc = set_io_32bit;      goto set_val;
+       case HDIO_SET_KEEPSETTINGS: setfunc = set_ksettings;     goto set_val;
+       case HDIO_SET_PIO_MODE:     setfunc = set_pio_mode;      goto set_val;
+       case HDIO_SET_UNMASKINTR:   setfunc = set_unmaskirq;     goto set_val;
+       case HDIO_SET_DMA:          setfunc = set_using_dma;     goto set_val;
        }
-       up(&ide_setting_sem);
 
        switch (cmd) {
                case HDIO_OBSOLETE_IDENTITY:
@@ -1357,14 +1073,14 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device
                        ide_init_hwif_ports(&hw, (unsigned long) args[0],
                                            (unsigned long) args[1], NULL);
                        hw.irq = args[2];
-                       if (ide_register_hw(&hw, NULL) == -1)
+                       if (ide_register_hw(&hw, NULL, NULL) == -1)
                                return -EIO;
                        return 0;
                }
                case HDIO_UNREGISTER_HWIF:
                        if (!capable(CAP_SYS_RAWIO)) return -EACCES;
                        /* (arg > MAX_HWIFS) checked in function */
-                       ide_unregister(arg);
+                       ide_unregister(arg, 1, 1);
                        return 0;
                case HDIO_SET_NICE:
                        if (!capable(CAP_SYS_ADMIN)) return -EACCES;
@@ -1412,10 +1128,6 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device
                        return 0;
                }
 
-               case CDROMEJECT:
-               case CDROMCLOSETRAY:
-                       return scsi_cmd_ioctl(file, bdev->bd_disk, cmd, p);
-
                case HDIO_GET_BUSSTATE:
                        if (!capable(CAP_SYS_ADMIN))
                                return -EACCES;
@@ -1432,6 +1144,28 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device
                default:
                        return -EINVAL;
        }
+
+read_val:
+       mutex_lock(&ide_setting_mtx);
+       spin_lock_irqsave(&ide_lock, flags);
+       err = *val;
+       spin_unlock_irqrestore(&ide_lock, flags);
+       mutex_unlock(&ide_setting_mtx);
+       return err >= 0 ? put_user(err, (long __user *)arg) : err;
+
+set_val:
+       if (bdev != bdev->bd_contains)
+               err = -EINVAL;
+       else {
+               if (!capable(CAP_SYS_ADMIN))
+                       err = -EACCES;
+               else {
+                       mutex_lock(&ide_setting_mtx);
+                       err = setfunc(drive, arg);
+                       mutex_unlock(&ide_setting_mtx);
+               }
+       }
+       return err;
 }
 
 EXPORT_SYMBOL(generic_ide_ioctl);
@@ -1500,26 +1234,12 @@ static int __init match_parm (char *s, const char *keywords[], int vals[], int m
        return 0;       /* zero = nothing matched */
 }
 
-#ifdef CONFIG_BLK_DEV_ALI14XX
 extern int probe_ali14xx;
-extern int ali14xx_init(void);
-#endif
-#ifdef CONFIG_BLK_DEV_UMC8672
 extern int probe_umc8672;
-extern int umc8672_init(void);
-#endif
-#ifdef CONFIG_BLK_DEV_DTC2278
 extern int probe_dtc2278;
-extern int dtc2278_init(void);
-#endif
-#ifdef CONFIG_BLK_DEV_HT6560B
 extern int probe_ht6560b;
-extern int ht6560b_init(void);
-#endif
-#ifdef CONFIG_BLK_DEV_QD65XX
 extern int probe_qd65xx;
-extern int qd65xx_init(void);
-#endif
+extern int cmd640_vlb;
 
 static int __initdata is_chipset_set[MAX_HWIFS];
 
@@ -1561,16 +1281,16 @@ static int __init ide_setup(char *s)
        if (!strcmp(s, "ide=nodma")) {
                printk(" : Prevented DMA\n");
                noautodma = 1;
-               return 1;
+               goto obsolete_option;
        }
 
-#ifdef CONFIG_BLK_DEV_IDEPCI
+#ifdef CONFIG_IDEPCI_PCIBUS_ORDER
        if (!strcmp(s, "ide=reverse")) {
                ide_scan_direction = 1;
                printk(" : Enabled support for IDE inverse scan order.\n");
                return 1;
        }
-#endif /* CONFIG_BLK_DEV_IDEPCI */
+#endif
 
 #ifdef CONFIG_BLK_DEV_IDEACPI
        if (!strcmp(s, "ide=noacpi")) {
@@ -1595,8 +1315,8 @@ static int __init ide_setup(char *s)
         */
        if (s[0] == 'h' && s[1] == 'd' && s[2] >= 'a' && s[2] <= max_drive) {
                const char *hd_words[] = {
-                       "none", "noprobe", "nowerr", "cdrom", "minus5",
-                       "autotune", "noautotune", "minus8", "swapdata", "bswap",
+                       "none", "noprobe", "nowerr", "cdrom", "nodma",
+                       "autotune", "noautotune", "-8", "-9", "-10",
                        "noflush", "remap", "remap63", "scsi", NULL };
                unit = s[2] - 'a';
                hw   = unit / MAX_DRIVES;
@@ -1623,16 +1343,15 @@ static int __init ide_setup(char *s)
                                drive->ready_stat = 0;
                                hwif->noprobe = 0;
                                goto done;
+                       case -5: /* nodma */
+                               drive->nodma = 1;
+                               goto done;
                        case -6: /* "autotune" */
                                drive->autotune = IDE_TUNE_AUTO;
                                goto obsolete_option;
                        case -7: /* "noautotune" */
                                drive->autotune = IDE_TUNE_NOAUTO;
                                goto obsolete_option;
-                       case -9: /* "swapdata" */
-                       case -10: /* "bswap" */
-                               drive->bswap = 1;
-                               goto done;
                        case -11: /* noflush */
                                drive->noflush = 1;
                                goto done;
@@ -1684,9 +1403,12 @@ static int __init ide_setup(char *s)
                 */
                static const char *ide_words[] = {
                        "noprobe", "serialize", "minus3", "minus4",
-                       "reset", "dma", "ata66", "minus8", "minus9",
+                       "reset", "minus6", "ata66", "minus8", "minus9",
                        "minus10", "four", "qd65xx", "ht6560b", "cmd640_vlb",
                        "dtc2278", "umc8672", "ali14xx", NULL };
+
+               hw_regs_t hwregs;
+
                hw = s[3] - '0';
                hwif = &ide_hwifs[hw];
                i = match_parm(&s[4], ide_words, vals, 3);
@@ -1729,11 +1451,8 @@ static int __init ide_setup(char *s)
 #endif
 #ifdef CONFIG_BLK_DEV_CMD640
                        case -14: /* "cmd640_vlb" */
-                       {
-                               extern int cmd640_vlb; /* flag for cmd640.c */
                                cmd640_vlb = 1;
                                goto done;
-                       }
 #endif
 #ifdef CONFIG_BLK_DEV_HT6560B
                        case -13: /* "ht6560b" */
@@ -1763,19 +1482,21 @@ static int __init ide_setup(char *s)
                        case -10: /* minus10 */
                        case -9: /* minus9 */
                        case -8: /* minus8 */
+                       case -6:
                        case -4:
                        case -3:
                                goto bad_option;
                        case -7: /* ata66 */
 #ifdef CONFIG_BLK_DEV_IDEPCI
-                               hwif->udma_four = 1;
+                               /*
+                                * Use ATA_CBL_PATA40_SHORT so drive side
+                                * cable detection is also overriden.
+                                */
+                               hwif->cbl = ATA_CBL_PATA40_SHORT;
                                goto obsolete_option;
 #else
                                goto bad_hwif;
 #endif
-                       case -6: /* dma */
-                               hwif->autodma = 1;
-                               goto obsolete_option;
                        case -5: /* "reset" */
                                hwif->reset = 1;
                                goto obsolete_option;
@@ -1794,9 +1515,9 @@ static int __init ide_setup(char *s)
                        case 2: /* base,ctl */
                                vals[2] = 0;    /* default irq = probe for it */
                        case 3: /* base,ctl,irq */
-                               hwif->hw.irq = vals[2];
-                               ide_init_hwif_ports(&hwif->hw, (unsigned long) vals[0], (unsigned long) vals[1], &hwif->irq);
-                               memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports));
+                               memset(&hwregs, 0, sizeof(hwregs));
+                               ide_init_hwif_ports(&hwregs, vals[0], vals[1], &hwif->irq);
+                               memcpy(hwif->io_ports, hwregs.io_ports, sizeof(hwif->io_ports));
                                hwif->irq      = vals[2];
                                hwif->noprobe  = 0;
                                hwif->chipset  = ide_forced;
@@ -1821,127 +1542,6 @@ done:
        return 1;
 }
 
-extern void __init pnpide_init(void);
-extern void __exit pnpide_exit(void);
-extern void __init h8300_ide_init(void);
-
-/*
- * probe_for_hwifs() finds/initializes "known" IDE interfaces
- */
-static void __init probe_for_hwifs (void)
-{
-#ifdef CONFIG_BLK_DEV_IDEPCI
-       ide_scan_pcibus(ide_scan_direction);
-#endif /* CONFIG_BLK_DEV_IDEPCI */
-
-#ifdef CONFIG_ETRAX_IDE
-       {
-               extern void init_e100_ide(void);
-               init_e100_ide();
-       }
-#endif /* CONFIG_ETRAX_IDE */
-#ifdef CONFIG_BLK_DEV_CMD640
-       {
-               extern void ide_probe_for_cmd640x(void);
-               ide_probe_for_cmd640x();
-       }
-#endif /* CONFIG_BLK_DEV_CMD640 */
-#ifdef CONFIG_BLK_DEV_IDE_PMAC
-       {
-               extern int pmac_ide_probe(void);
-               (void)pmac_ide_probe();
-       }
-#endif /* CONFIG_BLK_DEV_IDE_PMAC */
-#ifdef CONFIG_BLK_DEV_GAYLE
-       {
-               extern void gayle_init(void);
-               gayle_init();
-       }
-#endif /* CONFIG_BLK_DEV_GAYLE */
-#ifdef CONFIG_BLK_DEV_FALCON_IDE
-       {
-               extern void falconide_init(void);
-               falconide_init();
-       }
-#endif /* CONFIG_BLK_DEV_FALCON_IDE */
-#ifdef CONFIG_BLK_DEV_MAC_IDE
-       {
-               extern void macide_init(void);
-               macide_init();
-       }
-#endif /* CONFIG_BLK_DEV_MAC_IDE */
-#ifdef CONFIG_BLK_DEV_Q40IDE
-       {
-               extern void q40ide_init(void);
-               q40ide_init();
-       }
-#endif /* CONFIG_BLK_DEV_Q40IDE */
-#ifdef CONFIG_BLK_DEV_BUDDHA
-       {
-               extern void buddha_init(void);
-               buddha_init();
-       }
-#endif /* CONFIG_BLK_DEV_BUDDHA */
-#ifdef CONFIG_BLK_DEV_IDEPNP
-       pnpide_init();
-#endif
-#ifdef CONFIG_H8300
-       h8300_ide_init();
-#endif
-}
-
-void ide_register_subdriver(ide_drive_t *drive, ide_driver_t *driver)
-{
-#ifdef CONFIG_PROC_FS
-       ide_add_proc_entries(drive->proc, driver->proc, drive);
-#endif
-}
-
-EXPORT_SYMBOL(ide_register_subdriver);
-
-/**
- *     ide_unregister_subdriver        -       disconnect drive from driver
- *     @drive: drive to unplug
- *     @driver: driver
- *
- *     Disconnect a drive from the driver it was attached to and then
- *     clean up the various proc files and other objects attached to it.
- *
- *     Takes ide_setting_sem and ide_lock.
- *     Caller must hold none of the locks.
- */
-
-void ide_unregister_subdriver(ide_drive_t *drive, ide_driver_t *driver)
-{
-       unsigned long flags;
-       
-#ifdef CONFIG_PROC_FS
-       ide_remove_proc_entries(drive->proc, driver->proc);
-#endif
-       down(&ide_setting_sem);
-       spin_lock_irqsave(&ide_lock, flags);
-       /*
-        * ide_setting_sem protects the settings list
-        * ide_lock protects the use of settings
-        *
-        * so we need to hold both, ide_settings_sem because we want to
-        * modify the settings list, and ide_lock because we cannot take
-        * a setting out that is being used.
-        *
-        * OTOH both ide_{read,write}_setting are only ever used under
-        * ide_setting_sem.
-        */
-       auto_remove_settings(drive);
-       spin_unlock_irqrestore(&ide_lock, flags);
-       up(&ide_setting_sem);
-}
-
-EXPORT_SYMBOL(ide_unregister_subdriver);
-
-/*
- * Probe module
- */
-
 EXPORT_SYMBOL(ide_lock);
 
 static int ide_bus_match(struct device *dev, struct device_driver *drv)
@@ -1985,27 +1585,44 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
        return sprintf(buf, "ide:m-%s\n", media_string(drive));
 }
 
+static ssize_t model_show(struct device *dev, struct device_attribute *attr,
+                         char *buf)
+{
+       ide_drive_t *drive = to_ide_device(dev);
+       return sprintf(buf, "%s\n", drive->id->model);
+}
+
+static ssize_t firmware_show(struct device *dev, struct device_attribute *attr,
+                            char *buf)
+{
+       ide_drive_t *drive = to_ide_device(dev);
+       return sprintf(buf, "%s\n", drive->id->fw_rev);
+}
+
+static ssize_t serial_show(struct device *dev, struct device_attribute *attr,
+                          char *buf)
+{
+       ide_drive_t *drive = to_ide_device(dev);
+       return sprintf(buf, "%s\n", drive->id->serial_no);
+}
+
 static struct device_attribute ide_dev_attrs[] = {
        __ATTR_RO(media),
        __ATTR_RO(drivename),
        __ATTR_RO(modalias),
+       __ATTR_RO(model),
+       __ATTR_RO(firmware),
+       __ATTR(serial, 0400, serial_show, NULL),
        __ATTR_NULL
 };
 
-static int ide_uevent(struct device *dev, char **envp, int num_envp,
-                     char *buffer, int buffer_size)
+static int ide_uevent(struct device *dev, struct kobj_uevent_env *env)
 {
        ide_drive_t *drive = to_ide_device(dev);
-       int i = 0;
-       int length = 0;
-
-       add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length,
-                      "MEDIA=%s", media_string(drive));
-       add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length,
-                      "DRIVENAME=%s", drive->name);
-       add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length,
-                      "MODALIAS=ide:m-%s", media_string(drive));
-       envp[i] = NULL;
+
+       add_uevent_var(env, "MEDIA=%s", media_string(drive));
+       add_uevent_var(env, "DRIVENAME=%s", drive->name);
+       add_uevent_var(env, "MODALIAS=ide:m-%s", media_string(drive));
        return 0;
 }
 
@@ -2061,6 +1678,10 @@ static int __init ide_init(void)
        printk(KERN_INFO "Uniform Multi-Platform E-IDE driver " REVISION "\n");
        system_bus_speed = ide_system_bus_speed();
 
+       printk(KERN_INFO "ide: Assuming %dMHz system bus speed "
+                        "for PIO modes%s\n", system_bus_speed,
+                       idebus_parameter ? "" : "; override with idebus=xx");
+
        ret = bus_register(&ide_bus_type);
        if (ret < 0) {
                printk(KERN_WARNING "IDE: bus_register error: %d\n", ret);
@@ -2069,39 +1690,8 @@ static int __init ide_init(void)
 
        init_ide_data();
 
-#ifdef CONFIG_PROC_FS
-       proc_ide_root = proc_mkdir("ide", NULL);
-#endif
-
-#ifdef CONFIG_BLK_DEV_ALI14XX
-       if (probe_ali14xx)
-               (void)ali14xx_init();
-#endif
-#ifdef CONFIG_BLK_DEV_UMC8672
-       if (probe_umc8672)
-               (void)umc8672_init();
-#endif
-#ifdef CONFIG_BLK_DEV_DTC2278
-       if (probe_dtc2278)
-               (void)dtc2278_init();
-#endif
-#ifdef CONFIG_BLK_DEV_HT6560B
-       if (probe_ht6560b)
-               (void)ht6560b_init();
-#endif
-#ifdef CONFIG_BLK_DEV_QD65XX
-       if (probe_qd65xx)
-               (void)qd65xx_init();
-#endif
-
-       initializing = 1;
-       /* Probe for special PCI and other "known" interface chipsets. */
-       probe_for_hwifs();
-       initializing = 0;
-
-#ifdef CONFIG_PROC_FS
        proc_ide_create();
-#endif
+
        return 0;
 }
 
@@ -2135,15 +1725,9 @@ void __exit cleanup_module (void)
        int index;
 
        for (index = 0; index < MAX_HWIFS; ++index)
-               ide_unregister(index);
+               ide_unregister(index, 0, 0);
 
-#ifdef CONFIG_BLK_DEV_IDEPNP
-       pnpide_exit();
-#endif
-
-#ifdef CONFIG_PROC_FS
        proc_ide_destroy();
-#endif
 
        bus_unregister(&ide_bus_type);
 }