]> git.neil.brown.name Git - history.git/commitdiff
v2.4.8.2 -> v2.4.8.3
authorLinus Torvalds <torvalds@athlon.transmeta.com>
Tue, 5 Feb 2002 04:10:20 +0000 (20:10 -0800)
committerLinus Torvalds <torvalds@athlon.transmeta.com>
Tue, 5 Feb 2002 04:10:20 +0000 (20:10 -0800)
  - Patrick Mochel: fix PCI:PCI bridge 64-bit memory type detection
  - me: more forgotten nfsd off_t -> loff_t
  - Alan Cox: ide driver merge
  - Eric Lammerts, Rik van Riel: when oom, kill all threads.
  - Ben LaHaise: use down_read, not down_write() in map_user_kiobuf.
  We don't change the mappings, we just read them.
  - Kai Germaschewski: ISDN updates
  - Roland Fehrenbacher: sparse lun check
  - Tim Waugh: handle awkward Titan parallel/serial port cards
  - Stephen Rothwell: APM updates
  - Anton Altaparmakov: NTFS updates

67 files changed:
Documentation/filesystems/ntfs.txt
Documentation/isdn/README.HiSax
Documentation/sonypi.txt
Makefile
arch/i386/defconfig
arch/i386/kernel/apm.c
arch/i386/kernel/dmi_scan.c
drivers/char/ChangeLog
drivers/char/serial.c
drivers/ide/Config.in
drivers/ide/Makefile
drivers/ide/amd74xx.c [new file with mode: 0644]
drivers/ide/ide-adma.c [new file with mode: 0644]
drivers/ide/ide-cd.c
drivers/ide/ide-cd.h
drivers/ide/ide-disk.c
drivers/ide/ide-dma.c
drivers/ide/ide-floppy.c
drivers/ide/ide-pci.c
drivers/ide/ide-probe.c
drivers/ide/ide-proc.c
drivers/ide/ide-tape.c
drivers/ide/ide.c
drivers/ide/it8172.c [new file with mode: 0644]
drivers/ide/osb4.c [deleted file]
drivers/ide/pdc202xx.c
drivers/ide/piix.c
drivers/ide/serverworks.c [new file with mode: 0644]
drivers/isdn/Config.in
drivers/isdn/act2000/act2000_isa.c
drivers/isdn/act2000/module.c
drivers/isdn/avmb1/capi.c
drivers/isdn/divert/divert_procfs.c
drivers/isdn/eicon/lincfg.c
drivers/isdn/hisax/sedlbauer_cs.c
drivers/isdn/hysdn/hysdn_procconf.c
drivers/isdn/hysdn/hysdn_proclog.c
drivers/isdn/icn/icn.c
drivers/isdn/isdn_common.c
drivers/isdn/isdnloop/isdnloop.c
drivers/parport/ChangeLog
drivers/parport/parport_pc.c
drivers/pci/pci.c
drivers/scsi/scsi_scan.c
fs/Makefile
fs/buffer.c
fs/nfsd/nfs3xdr.c
fs/nfsd/nfsxdr.c
fs/ntfs/Makefile
fs/ntfs/dir.c
fs/ntfs/fs.c
fs/ntfs/support.c
fs/ntfs/util.c
fs/ntfs/util.h
fs/open.c
include/linux/apm_bios.h
include/linux/fs.h
include/linux/i2o.h
include/linux/ide.h
include/linux/nfsd/nfsd.h
include/linux/nfsd/xdr.h
include/linux/nfsd/xdr3.h
include/linux/ntfs_fs_sb.h
include/linux/pci_ids.h
mm/memory.c
mm/oom_kill.c
mm/vmscan.c

index 8af2583eabdad1bfaf93a738a7ee014e4a4dc1a4..227991677c4b800c89ad2f686cfed8c07b32ef4e 100644 (file)
@@ -1,8 +1,8 @@
 NTFS Overview
 =============
 
-Driver development has as of recently (since June '01) been sponsored
-by Legato Systems, Inc. (http://www.legato.com)
+Legato Systems, Inc. (http://www.legato.com) have sponsored Anton Altaparmakov
+to develop NTFS on Linux since June 2001.
 
 To mount an NTFS volume, use the filesystem type 'ntfs'. The driver
 currently works only in read-only mode, with no fault-tolerance supported.
@@ -36,15 +36,17 @@ Supported mount options
 
 iocharset=name         Character set to use when returning file names.
                        Unlike VFAT, NTFS suppresses names that contain
-                       unconvertible characters
-
-utf8=<bool>            Use UTF-8 for converting file names
-
-uni_xlate=<bool>,2     Use the VFAT-style encoding for file names outside
-                       the current character set. A boolean value will
-                       enable the feature, a value of 2 will enable the
-                       encoding as documented in vfat.txt:
-                               ':', (u & 0x3f), ((u>>6) & 0x3f), (u>>12),
+                       unconvertible characters. Note that most character
+                       sets contain insufficient characters to represent all
+                       possible Unicode characters that can exist on NTFS. To
+                       be sure you are not missing any files, you are advised
+                       to use the iocharset=utf8 which should be capable of
+                       representing all Unicode characters.
+
+utf8=<bool>            Use UTF-8 for converting file names. - It is preferable
+                       to use iocharset=utf8 instead, but if the utf8 NLS is
+                       not available, you can use this utf8 option, which
+                       enables the driver's builtin utf8 conversion functions.
 
 uid=
 gid=
@@ -81,6 +83,27 @@ list at sourceforge: linux-ntfs-dev@lists.sourceforge.net
 ChangeLog
 =========
 
+NTFS 1.1.16:
+
+       - Removed non-functional uni_xlate mount options.
+       - Clarified the semantics of the utf8 and iocharset mount options.
+       - Threw out the non-functional mount options for using hard coded
+         character set conversion. Only kept utf8 one.
+       - Fixed handling of mount options and proper handling of faulty mount
+         options on remount.
+       - Cleaned up character conversion which basically became simplified a
+         lot due to the removal of the above mentioned mount options.
+       - Made character conversion to be always consistent. Previously we
+         could output to the VFS file names which we would then not accept
+         back from the VFS so in effect we were generating ghost entries in
+         the directory listings which could not be accessed by any means.
+       - Simplified time conversion functions drastically without sacrificing
+         accuracy. (-8
+       - Fixed a use of a pointer before the check for the pointer being
+         NULL, reported by the Stanford checker.
+       - Fixed several missing error checks, reported by the Stanford
+         checker and fixed by Rasmus Andersen.
+
 NTFS 1.1.15 (changes since kernel 2.4.4's NTFS driver):
 
        - New mount option show_sys_files=<bool> to show all system files as
index 57fd7906f4a6d42b1ada2b6a8cff2f6e18045ea7..df729819705b215c5fd7208ea11fba33bddd8d97 100644 (file)
@@ -69,12 +69,7 @@ HFC-S+, HFC-SP/PCMCIA cards
 
 Note: PCF, PCF-Pro: up to now, only the ISDN part is supported
       PCC-8: not tested yet
-      Teles PCMCIA is EXPERIMENTAL
-      Teles 16.3c is EXPERIMENTAL
-      Teles PCI is EXPERIMENTAL
-      Teles S0Box is EXPERIMENTAL
       Eicon.Diehl Diva U interface not tested
-      HFC-S+, HFC-SP/PCMCIA are experimental
 
 If you know other passive cards with the Siemens chipset, please let me know.
 To use the PNP cards you need the isapnptools.
index 29156bff510a43767d372c7847b7fe29d7006662..0812e90b6e4a9ae04b5e51d6135d092752864626 100644 (file)
@@ -65,6 +65,19 @@ This supposes the use of minor 250 for the sonypi device:
 Bugs:
 -----
 
+       - several users reported that this driver disables the BIOS-managed
+         Fn-keys which put the laptop in sleeping state, or switch the
+         external monitor on/off. There is no workaround yet, since this
+         driver disables all APM management for those keys, by enabling the
+         ACPI management (and the ACPI core stuff is not complete yet). If
+         you have one of those laptops with working Fn keys and want to 
+         continue to use them, don't use this driver.
+
+       - some users reported that the laptop speed is lower (dhrystone
+         tested) when using the driver with the fnkeyinit parameter. I cannot
+         reproduce it on my laptop and not all users have this problem.
+         Still under investigation.
+       
        - since all development was done by reverse engineering, there is
          _absolutely no guarantee_ that this driver will not crash your
          laptop. Permanently.
index 595aaffd9bfc0b634acbf27ce5abab28dbad93c8..ed9660d8094601941e015de36b8d29cfd3eb4102 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 4
 SUBLEVEL = 9
-EXTRAVERSION =-pre2
+EXTRAVERSION =-pre3
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
index 502388df2ec871b99e2ee8e39295d11c9efd4b68..7a7a6ab113667f3fd935850c3db6308d2b4a53f1 100644 (file)
@@ -218,6 +218,7 @@ CONFIG_BLK_DEV_RZ1000=y
 CONFIG_BLK_DEV_IDEPCI=y
 CONFIG_IDEPCI_SHARE_IRQ=y
 CONFIG_BLK_DEV_IDEDMA_PCI=y
+CONFIG_BLK_DEV_ADMA=y
 # CONFIG_BLK_DEV_OFFBOARD is not set
 CONFIG_IDEDMA_PCI_AUTO=y
 CONFIG_BLK_DEV_IDEDMA=y
@@ -227,8 +228,8 @@ CONFIG_BLK_DEV_IDEDMA=y
 # CONFIG_AEC62XX_TUNING is not set
 # CONFIG_BLK_DEV_ALI15X3 is not set
 # CONFIG_WDC_ALI15X3 is not set
-# CONFIG_BLK_DEV_AMD7409 is not set
-# CONFIG_AMD7409_OVERRIDE is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+# CONFIG_AMD74XX_OVERRIDE is not set
 # CONFIG_BLK_DEV_CMD64X is not set
 # CONFIG_BLK_DEV_CY82C693 is not set
 # CONFIG_BLK_DEV_CS5530 is not set
@@ -241,7 +242,8 @@ CONFIG_PIIX_TUNING=y
 # CONFIG_BLK_DEV_OPTI621 is not set
 # CONFIG_BLK_DEV_PDC202XX is not set
 # CONFIG_PDC202XX_BURST is not set
-# CONFIG_BLK_DEV_OSB4 is not set
+# CONFIG_PDC202XX_FORCE is not set
+# CONFIG_BLK_DEV_SVWKS is not set
 # CONFIG_BLK_DEV_SIS5513 is not set
 # CONFIG_BLK_DEV_SLC90E66 is not set
 # CONFIG_BLK_DEV_TRM290 is not set
index 36d180e470a57b00514ecf762baa3dd86197da15..9dd0328eef2757ac1dae930f15894f23182ba614 100644 (file)
  *   1.14: Make connection version persist across module unload/load.
  *         Enable and engage power management earlier.
  *         Disengage power management on module unload.
+ *         Make CONFIG_APM_REAL_MODE_POWER_OFF run time configurable.
+ *         (Arjan van de Ven <arjanv@redhat.com>) modified by sfr.
+ *         Work around byte swap bug in one of the Vaio's BIOS's
+ *         (Marc Boucher <marc@mbsi.ca>).
+ *         Exposed the disable flag to dmi so that we can handle known
+ *        broken APM (Alan Cox <alan@redhat.com>).
  *
  * APM 1.1 Reference:
  *
@@ -339,14 +345,25 @@ static long                       clock_cmos_diff;
 static int                     got_clock_diff;
 #endif
 static int                     debug;
-static int                     apm_disabled;
+static int                     apm_disabled = -1;
 #ifdef CONFIG_SMP
 static int                     power_off;
 #else
 static int                     power_off = 1;
 #endif
+#ifdef CONFIG_APM_REAL_MODE_POWER_OFF
+static int                     realmode_power_off = 1;
+#else
+static int                     realmode_power_off;
+#endif
 static int                     exit_kapmd;
 static int                     kapmd_running;
+#ifdef CONFIG_APM_ALLOW_INTS
+static int                     allow_ints = 1;
+#else
+static int                     allow_ints;
+#endif
+static int                     broken_psr;
 
 static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue);
 static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue);
@@ -413,11 +430,12 @@ static const lookup_t error_table[] = {
  * Also, we KNOW that for the non error case of apm_bios_call, there
  * is no useful data returned in the low order 8 bits of eax.
  */
-#ifndef CONFIG_APM_ALLOW_INTS
-#      define APM_DO_CLI       __cli()
-#else
-#      define APM_DO_CLI       __sti()
-#endif
+#define APM_DO_CLI     \
+       if (apm_info.allow_ints) \
+               __sti(); \
+       else \
+               __cli();
+
 #ifdef APM_ZERO_SEGS
 #      define APM_DECL_SEGS \
                unsigned int saved_fs; unsigned int saved_gs;
@@ -641,7 +659,6 @@ static int apm_magic(void * unused)
 
 static void apm_power_off(void)
 {
-#ifdef CONFIG_APM_REAL_MODE_POWER_OFF
        unsigned char   po_bios_call[] = {
                0xb8, 0x00, 0x10,       /* movw  $0x1000,ax  */
                0x8e, 0xd0,             /* movw  ax,ss       */
@@ -651,7 +668,6 @@ static void apm_power_off(void)
                0xb9, 0x03, 0x00,       /* movw  $0x0003,cx  */
                0xcd, 0x15              /* int   $0x15       */
        };
-#endif
 
        /*
         * This may be called on an SMP machine.
@@ -664,11 +680,10 @@ static void apm_power_off(void)
                schedule();
        }
 #endif
-#ifdef CONFIG_APM_REAL_MODE_POWER_OFF
-       machine_real_restart(po_bios_call, sizeof(po_bios_call));
-#else
-       (void) apm_set_power_state(APM_STATE_OFF);
-#endif
+       if (apm_info.realmode_power_off)
+               machine_real_restart(po_bios_call, sizeof(po_bios_call));
+       else
+               (void) apm_set_power_state(APM_STATE_OFF);
 }
 
 #ifdef CONFIG_APM_DO_ENABLE
@@ -704,7 +719,11 @@ static int apm_get_power_status(u_short *status, u_short *bat, u_short *life)
                return (eax >> 8) & 0xff;
        *status = ebx;
        *bat = ecx;
-       *life = edx;
+       if (apm_info.get_power_status_swabinminutes) {
+               *life = swab16((u16)edx);
+               *life |= 0x8000;
+       } else
+               *life = edx;
        return APM_SUCCESS;
 }
 
@@ -1552,9 +1571,15 @@ static int __init apm_setup(char *str)
                        apm_disabled = 1;
                if (strncmp(str, "on", 2) == 0)
                        apm_disabled = 0;
+               if ((strncmp(str, "allow-ints", 10) == 0) ||
+                   (strncmp(str, "allow_ints", 10) == 0))
+                       apm_info.allow_ints = 1;
                if ((strncmp(str, "broken-psr", 10) == 0) ||
                    (strncmp(str, "broken_psr", 10) == 0))
                        apm_info.get_power_status_broken = 1;
+               if ((strncmp(str, "realmode-power-off", 18) == 0) ||
+                   (strncmp(str, "realmode_power_off", 18) == 0))
+                       apm_info.realmode_power_off = 1;
                invert = (strncmp(str, "no-", 3) == 0);
                if (invert)
                        str += 3;
@@ -1620,6 +1645,16 @@ static int __init apm_init(void)
                return -ENODEV;
        }
 
+       if (allow_ints)
+               apm_info.allow_ints = 1;
+       if (broken_psr)
+               apm_info.get_power_status_broken = 1;
+       if (realmode_power_off)
+               apm_info.realmode_power_off = 1;
+       /* User can override, but default is to trust DMI */
+       if (apm_disabled != -1)
+               apm_info.disabled = 1;
+
        /*
         * Fix for the Compaq Contura 3/25c which reports BIOS version 0.1
         * but is reportedly a 1.0 BIOS.
@@ -1644,8 +1679,9 @@ static int __init apm_init(void)
                printk("\n");
        }
 
-       if (apm_disabled) {
-               printk(KERN_NOTICE "apm: disabled on user request.\n");
+       if (apm_info.disabled) {
+               if(apm_disabled == 1)
+                       printk(KERN_NOTICE "apm: disabled on user request.\n");
                return -ENODEV;
        }
        if ((smp_num_cpus > 1) && !power_off) {
@@ -1747,5 +1783,9 @@ MODULE_PARM(power_off, "i");
 MODULE_PARM_DESC(power_off, "Enable power off");
 MODULE_PARM(bounce_interval, "i");
 MODULE_PARM_DESC(bounce_interval, "Set the number of ticks to ignore suspend bounces");
+MODULE_PARM(allow_ints, "i");
+MODULE_PARM_DESC(allow_ints, "Allow interrupts during BIOS calls");
+MODULE_PARM(broken_psr, "i");
+MODULE_PARM_DESC(broken_psr, "BIOS has a broken GetPowerStatus call");
 
 EXPORT_NO_SYMBOLS;
index 188d08f2a09d8dc907ab1f681307c6097ba3e87c..f4824555accf021359ce3702dd8e0e68a86d151f 100644 (file)
@@ -271,6 +271,18 @@ static __init int broken_apm_power(struct dmi_blacklist *d)
        return 0;
 }              
 
+
+/*
+ * This bios swaps the APM minute reporting bytes over (Many sony laptops
+ * have this problem).
+ */
+static __init int swab_apm_power_in_minutes(struct dmi_blacklist *d)
+{
+       apm_info.get_power_status_swabinminutes = 1;
+       printk(KERN_WARNING "BIOS strings suggest APM reports battery life in minutes and wrong byte order.\n");
+       return 0;
+}
 /*
  *     Process the DMI blacklists
  */
@@ -312,6 +324,11 @@ static __initdata struct dmi_blacklist dmi_blacklist[]={
                        MATCH(DMI_SYS_VENDOR, "IBM"),
                        NO_MATCH, NO_MATCH, NO_MATCH
                        } },
+       { set_apm_ints, "Dell Inspiron", {      /* Allow interrupts during suspend on Dell Inspiron laptops*/
+                       MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
+                       MATCH(DMI_PRODUCT_NAME, "Inspiron 4000"),
+                       NO_MATCH, NO_MATCH
+                       } },
        { set_apm_ints, "ASUSTeK", {   /* Allow interrupts during APM or the clock goes slow */
                        MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
                        MATCH(DMI_PRODUCT_NAME, "L8400K series Notebook PC"),
@@ -322,6 +339,21 @@ static __initdata struct dmi_blacklist dmi_blacklist[]={
                        MATCH(DMI_PRODUCT_NAME, "Delhi3"),
                        NO_MATCH, NO_MATCH,
                        } },
+       { swab_apm_power_in_minutes, "Sony VAIO", {     /* Handle problems with APM on Sony Vaio PCG-Z505LS */
+                       MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
+                       MATCH(DMI_BIOS_VERSION, "R0203Z3"),
+                       MATCH(DMI_BIOS_DATE, "08/25/00"), NO_MATCH
+                       } },
+       { swab_apm_power_in_minutes, "Sony VAIO", {     /* Handle problems with APM on Sony Vaio PCG-Z505LS */
+                       MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
+                       MATCH(DMI_BIOS_VERSION, "R0203D0"),
+                       MATCH(DMI_BIOS_DATE, "05/12/00"), NO_MATCH
+                       } },
+       { swab_apm_power_in_minutes, "Sony VAIO", {     /* Handle problems with APM on Sony Vaio PCG-Z600NE */
+                       MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
+                       MATCH(DMI_BIOS_VERSION, "R0121Z1"),
+                       MATCH(DMI_BIOS_DATE, "05/11/00"), NO_MATCH
+                       } },
        { NULL, }
 };
        
index 7e055801344c3839b451831824c5c9cbbac8aead..3f8aae855aded1e681aac3f9963716b0bafd5945 100644 (file)
@@ -1,3 +1,7 @@
+2001-08-11  Tim Waugh  <twaugh@redhat.com>
+
+       * serial.c (get_pci_port): Deal with awkward Titan cards.
+
 1998-08-26  Theodore Ts'o  <tytso@rsts-11.mit.edu>
 
        * serial.c (rs_open): Correctly decrement the module in-use count
index 5ec65dd297a03ad3f8200a2450b9254e2b58b078..dd46ea4a4cde36a27404c7333421aeba685b8e68 100644 (file)
@@ -3886,6 +3886,22 @@ static _INLINE_ int get_pci_port(struct pci_dev *dev,
                        case 6: /* BAR 4*/
                        case 7: base_idx=idx-2; /* BAR 5*/
                }
+
+       /* Some Titan cards are also a little weird */
+       if (dev->vendor == PCI_VENDOR_ID_TITAN &&
+           (dev->device == PCI_DEVICE_ID_TITAN_400L ||
+            dev->device == PCI_DEVICE_ID_TITAN_800L)) {
+               switch (idx) {
+               case 0: base_idx = 1;
+                       break;
+               case 1: base_idx = 2;
+                       break;
+               default:
+                       base_idx = 4;
+                       offset = 8 * (idx - 2);
+               }
+               
+       }
   
        port =  pci_resource_start(dev, base_idx) + offset;
 
@@ -4656,6 +4672,19 @@ static struct pci_device_id serial_pci_tbl[] __devinitdata = {
        {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800B,
                PCI_ANY_ID, PCI_ANY_ID, 0, 0, 
                pbn_b0_4_921600 },
+       {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_100L,
+               PCI_ANY_ID, PCI_ANY_ID,
+               SPCI_FL_BASE1, 1, 921600 },
+       {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200L,
+               PCI_ANY_ID, PCI_ANY_ID,
+               SPCI_FL_BASE1 | SPCI_FL_BASE_TABLE, 2, 921600 },
+       /* The 400L and 800L have a custom hack in get_pci_port */
+       {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400L,
+               PCI_ANY_ID, PCI_ANY_ID,
+               SPCI_FL_BASE_TABLE, 4, 921600 },
+       {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800L,
+               PCI_ANY_ID, PCI_ANY_ID,
+               SPCI_FL_BASE_TABLE, 8, 921600 },
 
        {       PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_550,
                PCI_ANY_ID, PCI_ANY_ID, 0, 0,
index 4fd5eba5820d4fb1f8818413cde851c044136e04..c1a7fed6b78bab7d54a381470f51bd5c40938496 100644 (file)
@@ -43,17 +43,21 @@ if [ "$CONFIG_BLK_DEV_IDE" != "n" ]; then
         if [ "$CONFIG_BLK_DEV_IDEPCI" = "y" ]; then
            bool '    Sharing PCI IDE interrupts support' CONFIG_IDEPCI_SHARE_IRQ
            bool '    Generic PCI bus-master DMA support' CONFIG_BLK_DEV_IDEDMA_PCI
+#          bool '    Asynchronous DMA support (EXPERIMENTAL)' CONFIG_BLK_DEV_ADMA $CONFIG_BLK_DEV_IDEDMA_PCI
+           define_bool CONFIG_BLK_DEV_ADMA $CONFIG_BLK_DEV_IDEDMA_PCI
            bool '    Boot off-board chipsets first support' CONFIG_BLK_DEV_OFFBOARD
            dep_bool '      Use PCI DMA by default when available' CONFIG_IDEDMA_PCI_AUTO $CONFIG_BLK_DEV_IDEDMA_PCI
            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 '      Attempt to HACK around Chipsets that TIMEOUT (WIP)' CONFIG_BLK_DEV_IDEDMA_TIMEOUT $CONFIG_IDEDMA_PCI_WIP
            dep_bool '      Good-Bad DMA Model-Firmware (WIP)' CONFIG_IDEDMA_NEW_DRIVE_LISTINGS $CONFIG_IDEDMA_PCI_WIP
+
            dep_bool '    AEC62XX chipset support' CONFIG_BLK_DEV_AEC62XX $CONFIG_BLK_DEV_IDEDMA_PCI
            dep_mbool '      AEC62XX Tuning support' CONFIG_AEC62XX_TUNING $CONFIG_BLK_DEV_AEC62XX
            dep_bool '    ALI M15x3 chipset support' CONFIG_BLK_DEV_ALI15X3 $CONFIG_BLK_DEV_IDEDMA_PCI
            dep_mbool '      ALI M15x3 WDC support (DANGEROUS)' CONFIG_WDC_ALI15X3 $CONFIG_BLK_DEV_ALI15X3
-           dep_bool '    AMD Viper support' CONFIG_BLK_DEV_AMD7409 $CONFIG_BLK_DEV_IDEDMA_PCI
-           dep_mbool '      AMD Viper ATA-66 Override (WIP)' CONFIG_AMD7409_OVERRIDE $CONFIG_BLK_DEV_AMD7409 $CONFIG_IDEDMA_PCI_WIP
+           dep_bool '    AMD Viper support' CONFIG_BLK_DEV_AMD74XX $CONFIG_BLK_DEV_IDEDMA_PCI
+           dep_mbool '      AMD Viper ATA-66 Override (WIP)' CONFIG_AMD74XX_OVERRIDE $CONFIG_BLK_DEV_AMD74XX $CONFIG_IDEDMA_PCI_WIP
            dep_bool '    CMD64X chipset support' CONFIG_BLK_DEV_CMD64X $CONFIG_BLK_DEV_IDEDMA_PCI
            dep_bool '    CY82C693 chipset support' CONFIG_BLK_DEV_CY82C693 $CONFIG_BLK_DEV_IDEDMA_PCI
            dep_bool '    Cyrix CS5530 MediaGX chipset support' CONFIG_BLK_DEV_CS5530 $CONFIG_BLK_DEV_IDEDMA_PCI
@@ -64,16 +68,24 @@ if [ "$CONFIG_BLK_DEV_IDE" != "n" ]; then
               dep_mbool '    Intel PIIXn chipsets support' CONFIG_BLK_DEV_PIIX $CONFIG_BLK_DEV_IDEDMA_PCI
               dep_mbool '      PIIXn Tuning support' CONFIG_PIIX_TUNING $CONFIG_BLK_DEV_PIIX $CONFIG_IDEDMA_PCI_AUTO
            fi
+           if [ "$CONFIG_MIPS_ITE8172" = "y" -o "$CONFIG_MIPS_IVR" = "y" ]; then
+              dep_mbool '    IT8172 IDE support' CONFIG_BLK_DEV_IT8172 $CONFIG_BLK_DEV_IDEDMA_PCI
+              dep_mbool '      IT8172 IDE Tuning support' CONFIG_IT8172_TUNING $CONFIG_BLK_DEV_IT8172 $CONFIG_IDEDMA_PCI_AUTO
+           fi
            dep_bool '    NS87415 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_NS87415 $CONFIG_BLK_DEV_IDEDMA_PCI
            dep_bool '    OPTi 82C621 chipset enhanced support (EXPERIMENTAL)' CONFIG_BLK_DEV_OPTI621 $CONFIG_EXPERIMENTAL
-           dep_bool '    PROMISE PDC20246/PDC20262/PDC20267 support' CONFIG_BLK_DEV_PDC202XX $CONFIG_BLK_DEV_IDEDMA_PCI
+           dep_bool '    PROMISE PDC202{46|62|65|67|68} support' CONFIG_BLK_DEV_PDC202XX $CONFIG_BLK_DEV_IDEDMA_PCI
            dep_bool '      Special UDMA Feature' CONFIG_PDC202XX_BURST $CONFIG_BLK_DEV_PDC202XX
-           dep_bool '    ServerWorks OSB4 chipset support' CONFIG_BLK_DEV_OSB4 $CONFIG_BLK_DEV_IDEDMA_PCI $CONFIG_X86
+           dep_bool '      Special FastTrak Feature' CONFIG_PDC202XX_FORCE $CONFIG_BLK_DEV_PDC202XX
+           dep_bool '    ServerWorks OSB4/CSB5 chipsets support' CONFIG_BLK_DEV_SVWKS $CONFIG_BLK_DEV_IDEDMA_PCI $CONFIG_X86
            dep_bool '    SiS5513 chipset support' CONFIG_BLK_DEV_SIS5513 $CONFIG_BLK_DEV_IDEDMA_PCI $CONFIG_X86
            dep_bool '    SLC90E66 chipset support' CONFIG_BLK_DEV_SLC90E66 $CONFIG_BLK_DEV_IDEDMA_PCI $CONFIG_X86
            dep_bool '    Tekram TRM290 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_TRM290 $CONFIG_BLK_DEV_IDEDMA_PCI
            dep_bool '    VIA82CXXX chipset support' CONFIG_BLK_DEV_VIA82CXXX $CONFIG_BLK_DEV_IDEDMA_PCI
          fi
+
+#       dep_mbool '   Pacific Digital A-DMA support (EXPERIMENTAL)' CONFIG_BLK_DEV_PDC_ADMA $CONFIG_BLK_DEV_ADMA $CONFIG_IDEDMA_PCI_WIP
+
         if [ "$CONFIG_PPC" = "y" -o "$CONFIG_ARM" = "y" ]; then
            bool '    Winbond SL82c105 support' CONFIG_BLK_DEV_SL82C105
         fi
@@ -97,17 +109,20 @@ if [ "$CONFIG_BLK_DEV_IDE" != "n" ]; then
         dep_bool '    RapIDE interface support' CONFIG_BLK_DEV_IDE_RAPIDE $CONFIG_ARCH_ACORN
       fi
       if [ "$CONFIG_AMIGA" = "y" ]; then
-        dep_bool '    Amiga Gayle IDE interface support' CONFIG_BLK_DEV_GAYLE $CONFIG_AMIGA
-        dep_mbool '      Amiga IDE Doubler support (EXPERIMENTAL)' CONFIG_BLK_DEV_IDEDOUBLER $CONFIG_BLK_DEV_GAYLE $CONFIG_EXPERIMENTAL
+        dep_bool '  Amiga Gayle IDE interface support' CONFIG_BLK_DEV_GAYLE $CONFIG_AMIGA
+        dep_mbool '    Amiga IDE Doubler support (EXPERIMENTAL)' CONFIG_BLK_DEV_IDEDOUBLER $CONFIG_BLK_DEV_GAYLE $CONFIG_EXPERIMENTAL
       fi
       if [ "$CONFIG_ZORRO" = "y" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then
-        dep_mbool '    Buddha/Catweasel IDE interface support (EXPERIMENTAL)' CONFIG_BLK_DEV_BUDDHA $CONFIG_ZORRO $CONFIG_EXPERIMENTAL
+        dep_mbool '  Buddha/Catweasel IDE interface support (EXPERIMENTAL)' CONFIG_BLK_DEV_BUDDHA $CONFIG_ZORRO $CONFIG_EXPERIMENTAL
       fi
       if [ "$CONFIG_ATARI" = "y" ]; then
-        dep_bool '    Falcon IDE interface support' CONFIG_BLK_DEV_FALCON_IDE $CONFIG_ATARI
+        dep_bool '  Falcon IDE interface support' CONFIG_BLK_DEV_FALCON_IDE $CONFIG_ATARI
       fi
       if [ "$CONFIG_MAC" = "y" ]; then
-        dep_bool '    Macintosh Quadra/Powerbook IDE interface support' CONFIG_BLK_DEV_MAC_IDE $CONFIG_MAC
+        dep_bool '  Macintosh Quadra/Powerbook IDE interface support' CONFIG_BLK_DEV_MAC_IDE $CONFIG_MAC
+      fi
+      if [ "$CONFIG_Q40" = "y" ]; then
+        dep_bool '  Q40/Q60 IDE interface support' CONFIG_BLK_DEV_Q40IDE $CONFIG_Q40
       fi
 
       bool '  Other IDE chipset support' CONFIG_IDE_CHIPSETS
@@ -151,7 +166,7 @@ fi
 if [ "$CONFIG_IDE_CHIPSETS" = "y" -o \
      "$CONFIG_BLK_DEV_AEC62XX" = "y" -o \
      "$CONFIG_BLK_DEV_ALI15X3" = "y" -o \
-     "$CONFIG_BLK_DEV_AMD7409" = "y" -o \
+     "$CONFIG_BLK_DEV_AMD74XX" = "y" -o \
      "$CONFIG_BLK_DEV_CMD640" = "y" -o \
      "$CONFIG_BLK_DEV_CMD64X" = "y" -o \
      "$CONFIG_BLK_DEV_CS5530" = "y" -o \
@@ -160,9 +175,10 @@ if [ "$CONFIG_IDE_CHIPSETS" = "y" -o \
      "$CONFIG_BLK_DEV_HPT366" = "y" -o \
      "$CONFIG_BLK_DEV_IDE_PMAC" = "y" -o \
      "$CONFIG_BLK_DEV_OPTI621" = "y" -o \
-     "$CONFIG_BLK_DEV_OSB4" = "y" -o \
+     "$CONFIG_BLK_DEV_SVWKS" = "y" -o \
      "$CONFIG_BLK_DEV_PDC202XX" = "y" -o \
      "$CONFIG_BLK_DEV_PIIX" = "y" -o \
+     "$CONFIG_BLK_DEV_IT8172" = "y" -o \
      "$CONFIG_BLK_DEV_SIS5513" = "y" -o \
      "$CONFIG_BLK_DEV_SLC90E66" = "y" -o \
      "$CONFIG_BLK_DEV_SL82C105" = "y" -o \
index c2d8a56448bf4c299e03ad3d1bdca1c5ddae9eda..99ff842635ec38c4078a1b7975355f61625ed802 100644 (file)
@@ -24,11 +24,12 @@ obj-$(CONFIG_BLK_DEV_IDEDISK)   += ide-disk.o
 obj-$(CONFIG_BLK_DEV_IDECD)     += ide-cd.o
 obj-$(CONFIG_BLK_DEV_IDETAPE)   += ide-tape.o
 obj-$(CONFIG_BLK_DEV_IDEFLOPPY) += ide-floppy.o
+obj-$(CONFIG_BLK_DEV_IT8172)    += it8172.o
 
 ide-obj-$(CONFIG_BLK_DEV_AEC62XX)      += aec62xx.o
 ide-obj-$(CONFIG_BLK_DEV_ALI14XX)      += ali14xx.o
 ide-obj-$(CONFIG_BLK_DEV_ALI15X3)      += alim15x3.o
-ide-obj-$(CONFIG_BLK_DEV_AMD7409)      += amd7409.o
+ide-obj-$(CONFIG_BLK_DEV_AMD74XX)      += amd74xx.o
 ide-obj-$(CONFIG_BLK_DEV_BUDDHA)       += buddha.o
 ide-obj-$(CONFIG_BLK_DEV_CMD640)       += cmd640.o
 ide-obj-$(CONFIG_BLK_DEV_CMD64X)       += cmd64x.o
@@ -42,16 +43,18 @@ ide-obj-$(CONFIG_BLK_DEV_HPT34X)    += hpt34x.o
 ide-obj-$(CONFIG_BLK_DEV_HPT366)       += hpt366.o
 ide-obj-$(CONFIG_BLK_DEV_HT6560B)      += ht6560b.o
 ide-obj-$(CONFIG_BLK_DEV_IDE_ICSIDE)   += icside.o
-ide-obj-$(CONFIG_BLK_DEV_IDEDMA)       += ide-dma.o
+ide-obj-$(CONFIG_BLK_DEV_ADMA)         += ide-adma.o
+ide-obj-$(CONFIG_BLK_DEV_IDEDMA_PCI)   += ide-dma.o
 ide-obj-$(CONFIG_BLK_DEV_IDEPCI)       += ide-pci.o
 ide-obj-$(CONFIG_BLK_DEV_ISAPNP)       += ide-pnp.o
 ide-obj-$(CONFIG_BLK_DEV_IDE_PMAC)     += ide-pmac.o
 ide-obj-$(CONFIG_BLK_DEV_MAC_IDE)      += macide.o
 ide-obj-$(CONFIG_BLK_DEV_NS87415)      += ns87415.o
 ide-obj-$(CONFIG_BLK_DEV_OPTI621)      += opti621.o
-ide-obj-$(CONFIG_BLK_DEV_OSB4)         += osb4.o
+ide-obj-$(CONFIG_BLK_DEV_SVWKS)                += serverworks.o
 ide-obj-$(CONFIG_BLK_DEV_PDC202XX)     += pdc202xx.o
 ide-obj-$(CONFIG_BLK_DEV_PDC4030)      += pdc4030.o
+ide-obj-$(CONFIG_BLK_DEV_PDC_ADMA)     += pdcadma.o
 ide-obj-$(CONFIG_BLK_DEV_PIIX)         += piix.o
 ide-obj-$(CONFIG_BLK_DEV_QD6580)       += qd6580.o
 ide-obj-$(CONFIG_BLK_DEV_IDE_RAPIDE)   += rapide.o
diff --git a/drivers/ide/amd74xx.c b/drivers/ide/amd74xx.c
new file mode 100644 (file)
index 0000000..54796da
--- /dev/null
@@ -0,0 +1,485 @@
+/*
+ * linux/drivers/ide/amd74xx.c         Version 0.05    June 9, 2000
+ *
+ * Copyright (C) 1999-2000             Andre Hedrick <andre@linux-ide.org>
+ * May be copied or modified under the terms of the GNU General Public License
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/ioport.h>
+#include <linux/blkdev.h>
+#include <linux/hdreg.h>
+
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/ide.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include "ide_modes.h"
+
+#define DISPLAY_VIPER_TIMINGS
+
+#if defined(DISPLAY_VIPER_TIMINGS) && defined(CONFIG_PROC_FS)
+#include <linux/stat.h>
+#include <linux/proc_fs.h>
+
+static int amd74xx_get_info(char *, char **, off_t, int);
+extern int (*amd74xx_display_info)(char *, char **, off_t, int); /* ide-proc.c */
+extern char *ide_media_verbose(ide_drive_t *);
+static struct pci_dev *bmide_dev;
+
+static int amd74xx_get_info (char *buffer, char **addr, off_t offset, int count)
+{
+       char *p = buffer;
+       u32 bibma = pci_resource_start(bmide_dev, 4);
+       u8 c0 = 0, c1 = 0;
+
+       /*
+        * at that point bibma+0x2 et bibma+0xa are byte registers
+        * to investigate:
+        */
+       c0 = inb_p((unsigned short)bibma + 0x02);
+       c1 = inb_p((unsigned short)bibma + 0x0a);
+
+       p += sprintf(p, "\n                                AMD %04X VIPER Chipset.\n", bmide_dev->device);
+       p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n");
+       p += sprintf(p, "                %sabled                         %sabled\n",
+                       (c0&0x80) ? "dis" : " en",
+                       (c1&0x80) ? "dis" : " en");
+       p += sprintf(p, "--------------- drive0 --------- drive1 -------- drive0 ---------- drive1 ------\n");
+       p += sprintf(p, "DMA enabled:    %s              %s             %s               %s\n",
+                       (c0&0x20) ? "yes" : "no ", (c0&0x40) ? "yes" : "no ",
+                       (c1&0x20) ? "yes" : "no ", (c1&0x40) ? "yes" : "no " );
+       p += sprintf(p, "UDMA\n");
+       p += sprintf(p, "DMA\n");
+       p += sprintf(p, "PIO\n");
+
+       return p-buffer;        /* => must be less than 4k! */
+}
+#endif  /* defined(DISPLAY_VIPER_TIMINGS) && defined(CONFIG_PROC_FS) */
+
+byte amd74xx_proc = 0;
+
+extern char *ide_xfer_verbose (byte xfer_rate);
+
+static unsigned int amd74xx_swdma_check (struct pci_dev *dev)
+{
+       unsigned int class_rev;
+
+       if (dev->device == PCI_DEVICE_ID_AMD_VIPER_7411)
+               return 0;
+
+       pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
+       class_rev &= 0xff;
+       return ((int) (class_rev >= 7) ? 1 : 0);
+}
+
+static int amd74xx_swdma_error(ide_drive_t *drive)
+{
+       printk("%s: single-word DMA not support (revision < C4)\n", drive->name);
+       return 0;
+}
+
+/*
+ * Here is where all the hard work goes to program the chipset.
+ *
+ */
+static int amd74xx_tune_chipset (ide_drive_t *drive, byte speed)
+{
+       ide_hwif_t *hwif        = HWIF(drive);
+       struct pci_dev *dev     = hwif->pci_dev;
+       int err                 = 0;
+       byte unit               = (drive->select.b.unit & 0x01);
+#ifdef CONFIG_BLK_DEV_IDEDMA
+       unsigned long dma_base  = hwif->dma_base;
+#endif /* CONFIG_BLK_DEV_IDEDMA */
+       byte drive_pci          = 0x00;
+       byte drive_pci2         = 0x00;
+       byte ultra_timing       = 0x00;
+       byte dma_pio_timing     = 0x00;
+       byte pio_timing         = 0x00;
+
+        switch (drive->dn) {
+               case 0: drive_pci = 0x53; drive_pci2 = 0x4b; break;
+               case 1: drive_pci = 0x52; drive_pci2 = 0x4a; break;
+               case 2: drive_pci = 0x51; drive_pci2 = 0x49; break;
+               case 3: drive_pci = 0x50; drive_pci2 = 0x48; break;
+               default:
+                        return -1;
+        }
+
+       pci_read_config_byte(dev, drive_pci, &ultra_timing);
+       pci_read_config_byte(dev, drive_pci2, &dma_pio_timing);
+       pci_read_config_byte(dev, 0x4c, &pio_timing);
+
+#ifdef DEBUG
+       printk("%s: UDMA 0x%02x DMAPIO 0x%02x PIO 0x%02x ",
+               drive->name, ultra_timing, dma_pio_timing, pio_timing);
+#endif
+
+       ultra_timing    &= ~0xC7;
+       dma_pio_timing  &= ~0xFF;
+       pio_timing      &= ~(0x03 << drive->dn);
+
+#ifdef DEBUG
+       printk(":: UDMA 0x%02x DMAPIO 0x%02x PIO 0x%02x ",
+               ultra_timing, dma_pio_timing, pio_timing);
+#endif
+
+       switch(speed) {
+#ifdef CONFIG_BLK_DEV_IDEDMA
+               case XFER_UDMA_5:
+#undef __CAN_MODE_5
+#ifdef __CAN_MODE_5
+                       ultra_timing |= 0x46;
+                       dma_pio_timing |= 0x20;
+                       break;
+#else
+                       printk("%s: setting to mode 4, driver problems in mode 5.\n", drive->name);
+                       speed = XFER_UDMA_4;
+#endif /* __CAN_MODE_5 */
+               case XFER_UDMA_4:
+                       ultra_timing |= 0x45;
+                       dma_pio_timing |= 0x20;
+                       break;
+               case XFER_UDMA_3:
+                       ultra_timing |= 0x44;
+                       dma_pio_timing |= 0x20;
+                       break;
+               case XFER_UDMA_2:
+                       ultra_timing |= 0x40;
+                       dma_pio_timing |= 0x20;
+                       break;
+               case XFER_UDMA_1:
+                       ultra_timing |= 0x41;
+                       dma_pio_timing |= 0x20;
+                       break;
+               case XFER_UDMA_0:
+                       ultra_timing |= 0x42;
+                       dma_pio_timing |= 0x20;
+                       break;
+               case XFER_MW_DMA_2:
+                       dma_pio_timing |= 0x20;
+                       break;
+               case XFER_MW_DMA_1:
+                       dma_pio_timing |= 0x21;
+                       break;
+               case XFER_MW_DMA_0:
+                       dma_pio_timing |= 0x77;
+                       break;
+               case XFER_SW_DMA_2:
+                       if (!amd74xx_swdma_check(dev))
+                               return amd74xx_swdma_error(drive);
+                       dma_pio_timing |= 0x42;
+                       break;
+               case XFER_SW_DMA_1:
+                       if (!amd74xx_swdma_check(dev))
+                               return amd74xx_swdma_error(drive);
+                       dma_pio_timing |= 0x65;
+                       break;
+               case XFER_SW_DMA_0:
+                       if (!amd74xx_swdma_check(dev))
+                               return amd74xx_swdma_error(drive);
+                       dma_pio_timing |= 0xA8;
+                       break;
+#endif /* CONFIG_BLK_DEV_IDEDMA */
+               case XFER_PIO_4:
+                       dma_pio_timing |= 0x20;
+                       break;
+               case XFER_PIO_3:
+                       dma_pio_timing |= 0x22;
+                       break;
+               case XFER_PIO_2:
+                       dma_pio_timing |= 0x42;
+                       break;
+               case XFER_PIO_1:
+                       dma_pio_timing |= 0x65;
+                       break;
+               case XFER_PIO_0:
+               default:
+                       dma_pio_timing |= 0xA8;
+                       break;
+        }
+
+       pio_timing |= (0x03 << drive->dn);
+
+       if (!drive->init_speed)
+               drive->init_speed = speed;
+
+#ifdef CONFIG_BLK_DEV_IDEDMA
+       pci_write_config_byte(dev, drive_pci, ultra_timing);
+#endif /* CONFIG_BLK_DEV_IDEDMA */
+       pci_write_config_byte(dev, drive_pci2, dma_pio_timing);
+       pci_write_config_byte(dev, 0x4c, pio_timing);
+
+#ifdef DEBUG
+       printk(":: UDMA 0x%02x DMAPIO 0x%02x PIO 0x%02x\n",
+               ultra_timing, dma_pio_timing, pio_timing);
+#endif
+
+#ifdef CONFIG_BLK_DEV_IDEDMA
+       if (speed > XFER_PIO_4) {
+               outb(inb(dma_base+2)|(1<<(5+unit)), dma_base+2);
+       } else {
+               outb(inb(dma_base+2) & ~(1<<(5+unit)), dma_base+2);
+       }
+#endif /* CONFIG_BLK_DEV_IDEDMA */
+
+       err = ide_config_drive_speed(drive, speed);
+       drive->current_speed = speed;
+       return (err);
+}
+
+static void config_chipset_for_pio (ide_drive_t *drive)
+{
+       unsigned short eide_pio_timing[6] = {960, 480, 240, 180, 120, 90};
+       unsigned short xfer_pio = drive->id->eide_pio_modes;
+       byte                    timing, speed, pio;
+
+       pio = ide_get_best_pio_mode(drive, 255, 5, NULL);
+
+       if (xfer_pio> 4)
+               xfer_pio = 0;
+
+       if (drive->id->eide_pio_iordy > 0) {
+               for (xfer_pio = 5;
+                       xfer_pio>0 &&
+                       drive->id->eide_pio_iordy>eide_pio_timing[xfer_pio];
+                       xfer_pio--);
+       } else {
+               xfer_pio = (drive->id->eide_pio_modes & 4) ? 0x05 :
+                          (drive->id->eide_pio_modes & 2) ? 0x04 :
+                          (drive->id->eide_pio_modes & 1) ? 0x03 :
+                          (drive->id->tPIO & 2) ? 0x02 :
+                          (drive->id->tPIO & 1) ? 0x01 : xfer_pio;
+       }
+
+       timing = (xfer_pio >= pio) ? xfer_pio : pio;
+
+       switch(timing) {
+               case 4: speed = XFER_PIO_4;break;
+               case 3: speed = XFER_PIO_3;break;
+               case 2: speed = XFER_PIO_2;break;
+               case 1: speed = XFER_PIO_1;break;
+               default:
+                       speed = (!drive->id->tPIO) ? XFER_PIO_0 : XFER_PIO_SLOW;
+                       break;
+       }
+       (void) amd74xx_tune_chipset(drive, speed);
+       drive->current_speed = speed;
+}
+
+static void amd74xx_tune_drive (ide_drive_t *drive, byte pio)
+{
+       byte speed;
+       switch(pio) {
+               case 4:         speed = XFER_PIO_4;break;
+               case 3:         speed = XFER_PIO_3;break;
+               case 2:         speed = XFER_PIO_2;break;
+               case 1:         speed = XFER_PIO_1;break;
+               default:        speed = XFER_PIO_0;break;
+       }
+       (void) amd74xx_tune_chipset(drive, speed);
+}
+
+#ifdef CONFIG_BLK_DEV_IDEDMA
+/*
+ * This allows the configuration of ide_pci chipset registers
+ * for cards that learn about the drive's UDMA, DMA, PIO capabilities
+ * after the drive is reported by the OS.
+ */
+static int config_chipset_for_dma (ide_drive_t *drive)
+{
+       ide_hwif_t *hwif        = HWIF(drive);
+       struct pci_dev *dev     = hwif->pci_dev;
+       struct hd_driveid *id   = drive->id;
+       byte udma_66            = eighty_ninty_three(drive);
+       byte udma_100           = (dev->device==PCI_DEVICE_ID_AMD_VIPER_7411) ? 1 : 0;
+       byte speed              = 0x00;
+       int  rval;
+
+       if ((id->dma_ultra & 0x0020) && (udma_66)&& (udma_100)) {
+               speed = XFER_UDMA_5;
+       } else if ((id->dma_ultra & 0x0010) && (udma_66)) {
+               speed = XFER_UDMA_4;
+       } else if ((id->dma_ultra & 0x0008) && (udma_66)) {
+               speed = XFER_UDMA_3;
+       } else if (id->dma_ultra & 0x0004) {
+               speed = XFER_UDMA_2;
+       } else if (id->dma_ultra & 0x0002) {
+               speed = XFER_UDMA_1;
+       } else if (id->dma_ultra & 0x0001) {
+               speed = XFER_UDMA_0;
+       } else if (id->dma_mword & 0x0004) {
+               speed = XFER_MW_DMA_2;
+       } else if (id->dma_mword & 0x0002) {
+               speed = XFER_MW_DMA_1;
+       } else if (id->dma_mword & 0x0001) {
+               speed = XFER_MW_DMA_0;
+       } else {
+               return ((int) ide_dma_off_quietly);
+       }
+
+       (void) amd74xx_tune_chipset(drive, speed);
+
+       rval = (int)(   ((id->dma_ultra >> 11) & 3) ? ide_dma_on :
+                       ((id->dma_ultra >> 8) & 7) ? ide_dma_on :
+                       ((id->dma_mword >> 8) & 7) ? ide_dma_on :
+                                                    ide_dma_off_quietly);
+
+       return rval;
+}
+
+static int config_drive_xfer_rate (ide_drive_t *drive)
+{
+       struct hd_driveid *id = drive->id;
+       ide_dma_action_t dma_func = ide_dma_on;
+
+       if (id && (id->capability & 1) && HWIF(drive)->autodma) {
+               /* Consult the list of known "bad" drives */
+               if (ide_dmaproc(ide_dma_bad_drive, drive)) {
+                       dma_func = ide_dma_off;
+                       goto fast_ata_pio;
+               }
+               dma_func = ide_dma_off_quietly;
+               if (id->field_valid & 4) {
+                       if (id->dma_ultra & 0x002F) {
+                               /* Force if Capable UltraDMA */
+                               dma_func = config_chipset_for_dma(drive);
+                               if ((id->field_valid & 2) &&
+                                   (dma_func != ide_dma_on))
+                                       goto try_dma_modes;
+                       }
+               } else if (id->field_valid & 2) {
+try_dma_modes:
+                       if ((id->dma_mword & 0x0007) ||
+                           ((id->dma_1word & 0x007) &&
+                            (amd74xx_swdma_check(HWIF(drive)->pci_dev)))) {
+                               /* Force if Capable regular DMA modes */
+                               dma_func = config_chipset_for_dma(drive);
+                               if (dma_func != ide_dma_on)
+                                       goto no_dma_set;
+                       }
+                       
+               } else if (ide_dmaproc(ide_dma_good_drive, drive)) {
+                       if (id->eide_dma_time > 150) {
+                               goto no_dma_set;
+                       }
+                       /* Consult the list of known "good" drives */
+                       dma_func = config_chipset_for_dma(drive);
+                       if (dma_func != ide_dma_on)
+                               goto no_dma_set;
+               } else {
+                       goto fast_ata_pio;
+               }
+       } else if ((id->capability & 8) || (id->field_valid & 2)) {
+fast_ata_pio:
+               dma_func = ide_dma_off_quietly;
+no_dma_set:
+
+               config_chipset_for_pio(drive);
+       }
+       return HWIF(drive)->dmaproc(dma_func, drive);
+}
+
+/*
+ * amd74xx_dmaproc() initiates/aborts (U)DMA read/write operations on a drive.
+ */
+
+int amd74xx_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
+{
+       switch (func) {
+               case ide_dma_check:
+                       return config_drive_xfer_rate(drive);
+               default:
+                       break;
+       }
+       return ide_dmaproc(func, drive);        /* use standard DMA stuff */
+}
+#endif /* CONFIG_BLK_DEV_IDEDMA */
+
+unsigned int __init pci_init_amd74xx (struct pci_dev *dev, const char *name)
+{
+       unsigned long fixdma_base = pci_resource_start(dev, 4);
+
+#ifdef CONFIG_BLK_DEV_IDEDMA
+       if (!amd74xx_swdma_check(dev))
+               printk("%s: disabling single-word DMA support (revision < C4)\n", name);
+#endif /* CONFIG_BLK_DEV_IDEDMA */
+
+       if (!fixdma_base) {
+               /*
+                *
+                */
+       } else {
+               /*
+                * enable DMA capable bit, and "not" simplex only
+                */
+               outb(inb(fixdma_base+2) & 0x60, fixdma_base+2);
+
+               if (inb(fixdma_base+2) & 0x80)
+                       printk("%s: simplex device: DMA will fail!!\n", name);
+       }
+#if defined(DISPLAY_VIPER_TIMINGS) && defined(CONFIG_PROC_FS)
+       if (!amd74xx_proc) {
+               amd74xx_proc = 1;
+               bmide_dev = dev;
+               amd74xx_display_info = &amd74xx_get_info;
+       }
+#endif /* DISPLAY_VIPER_TIMINGS && CONFIG_PROC_FS */
+
+       return 0;
+}
+
+unsigned int __init ata66_amd74xx (ide_hwif_t *hwif)
+{
+#ifdef CONFIG_AMD74XX_OVERRIDE
+       byte ata66 = 1;
+#else
+       byte ata66 = 0;
+#endif /* CONFIG_AMD74XX_OVERRIDE */
+
+#if 0
+       pci_read_config_byte(hwif->pci_dev, 0x48, &ata66);
+       return ((ata66 & 0x02) ? 0 : 1);
+#endif
+       return ata66;
+}
+
+void __init ide_init_amd74xx (ide_hwif_t *hwif)
+{
+       hwif->tuneproc = &amd74xx_tune_drive;
+       hwif->speedproc = &amd74xx_tune_chipset;
+
+#ifndef CONFIG_BLK_DEV_IDEDMA
+       hwif->drives[0].autotune = 1;
+       hwif->drives[1].autotune = 1;
+       hwif->autodma = 0;
+       return;
+#else
+
+       if (hwif->dma_base) {
+               hwif->dmaproc = &amd74xx_dmaproc;
+               if (!noautodma)
+                       hwif->autodma = 1;
+       } else {
+               hwif->autodma = 0;
+               hwif->drives[0].autotune = 1;
+               hwif->drives[1].autotune = 1;
+       }
+#endif /* CONFIG_BLK_DEV_IDEDMA */
+}
+
+void __init ide_dmacapable_amd74xx (ide_hwif_t *hwif, unsigned long dmabase)
+{
+       ide_setup_dma(hwif, dmabase, 8);
+}
diff --git a/drivers/ide/ide-adma.c b/drivers/ide/ide-adma.c
new file mode 100644 (file)
index 0000000..b1f9c17
--- /dev/null
@@ -0,0 +1,9 @@
+/*
+ *  linux/drivers/ide/ide-adma.c         Version 0.00  June 24, 2001
+ *
+ *  Copyright (c) 2001         Andre Hedrick <andre@linux-ide.org>
+ *
+ *  Asynchronous DMA -- TBA, this is a holding file.
+ *
+ */
+
index cadccf58f4e3182bf7cabda652514cab149995db..87ae9b61d438cdaaa72767dcef3de4af432c7be7 100644 (file)
@@ -978,8 +978,7 @@ static ide_startstop_t cdrom_read_intr (ide_drive_t *drive)
 
                /* If we've filled the present buffer but there's another
                   chained buffer after it, move on. */
-               if (rq->current_nr_sectors == 0 &&
-                   rq->nr_sectors > 0)
+               if (rq->current_nr_sectors == 0 && rq->nr_sectors)
                        cdrom_end_request (1, drive);
 
                /* If the buffers are full, cache the rest of the data in our
@@ -1193,6 +1192,55 @@ static ide_startstop_t cdrom_start_seek (ide_drive_t *drive, unsigned int block)
        return cdrom_start_packet_command (drive, 0, cdrom_start_seek_continuation);
 }
 
+static inline int cdrom_merge_requests(struct request *rq, struct request *nxt)
+{
+       int ret = 1;
+
+       /*
+        * partitions not really working, but better check anyway...
+        */
+       if (rq->cmd == nxt->cmd && rq->rq_dev == nxt->rq_dev) {
+               rq->nr_sectors += nxt->nr_sectors;
+               rq->hard_nr_sectors += nxt->nr_sectors;
+               rq->bhtail->b_reqnext = nxt->bh;
+               rq->bhtail = nxt->bhtail;
+               list_del(&nxt->queue);
+               blkdev_release_request(nxt);
+               ret = 0;
+       }
+
+       return ret;
+}
+
+/*
+ * the current request will always be the first one on the list
+ */
+static void cdrom_attempt_remerge(ide_drive_t *drive, struct request *rq)
+{
+       struct list_head *entry;
+       struct request *nxt;
+       unsigned long flags;
+
+       spin_lock_irqsave(&io_request_lock, flags);
+
+       while (1) {
+               entry = rq->queue.next;
+               if (entry == &drive->queue.queue_head)
+                       break;
+
+               nxt = blkdev_entry_to_request(entry);
+               if (rq->sector + rq->nr_sectors != nxt->sector)
+                       break;
+               else if (rq->nr_sectors + nxt->nr_sectors > SECTORS_MAX)
+                       break;
+
+               if (cdrom_merge_requests(rq, nxt))
+                       break;
+       }
+
+       spin_unlock_irqrestore(&io_request_lock, flags);
+}
+
 /* Fix up a possibly partially-processed request so that we can
    start it over entirely, or even put it back on the request queue. */
 static void restore_request (struct request *rq)
@@ -1204,6 +1252,8 @@ static void restore_request (struct request *rq)
                rq->sector -= n;
        }
        rq->current_nr_sectors = rq->bh->b_size >> SECTOR_BITS;
+       rq->hard_nr_sectors = rq->nr_sectors;
+       rq->hard_sector = rq->sector;
 }
 
 /*
@@ -1217,20 +1267,22 @@ static ide_startstop_t cdrom_start_read (ide_drive_t *drive, unsigned int block)
 
        /* If the request is relative to a partition, fix it up to refer to the
           absolute address.  */
-       if ((minor & PARTN_MASK) != 0) {
+       if (minor & PARTN_MASK) {
                rq->sector = block;
                minor &= ~PARTN_MASK;
-               rq->rq_dev = MKDEV (MAJOR(rq->rq_dev), minor);
+               rq->rq_dev = MKDEV(MAJOR(rq->rq_dev), minor);
        }
 
        /* We may be retrying this request after an error.  Fix up
           any weirdness which might be present in the request packet. */
-       restore_request (rq);
+       restore_request(rq);
 
        /* Satisfy whatever we can of this request from our cached sector. */
        if (cdrom_read_from_buffer(drive))
                return ide_stopped;
 
+       cdrom_attempt_remerge(drive, rq);
+
        /* Clear the local sector buffer. */
        info->nsectors_buffered = 0;
 
@@ -1478,7 +1530,7 @@ static inline int cdrom_write_check_ireason(ide_drive_t *drive, int len, int ire
 
 static ide_startstop_t cdrom_write_intr(ide_drive_t *drive)
 {
-       int stat, ireason, len, sectors_to_transfer;
+       int stat, ireason, len, sectors_to_transfer, uptodate;
        struct cdrom_info *info = drive->driver_data;
        int i, dma_error = 0, dma = info->dma;
        ide_startstop_t startstop;
@@ -1499,6 +1551,9 @@ static ide_startstop_t cdrom_write_intr(ide_drive_t *drive)
                return startstop;
        }
  
+       /*
+        * using dma, transfer is complete now
+        */
        if (dma) {
                if (dma_error)
                        return ide_error(drive, "dma error", stat);
@@ -1520,12 +1575,13 @@ static ide_startstop_t cdrom_write_intr(ide_drive_t *drive)
                /* If we're not done writing, complain.
                 * Otherwise, complete the command normally.
                 */
+               uptodate = 1;
                if (rq->current_nr_sectors > 0) {
                        printk("%s: write_intr: data underrun (%ld blocks)\n",
-                               drive->name, rq->current_nr_sectors);
-                       cdrom_end_request(0, drive);
-               } else
-                       cdrom_end_request(1, drive);
+                       drive->name, rq->current_nr_sectors);
+                       uptodate = 0;
+               }
+               cdrom_end_request(uptodate, drive);
                return ide_stopped;
        }
 
@@ -1534,26 +1590,42 @@ static ide_startstop_t cdrom_write_intr(ide_drive_t *drive)
                if (cdrom_write_check_ireason(drive, len, ireason))
                        return ide_stopped;
 
-       /* The number of sectors we need to read from the drive. */
        sectors_to_transfer = len / SECTOR_SIZE;
 
-       /* Now loop while we still have data to read from the drive. DMA
-        * transfers will already have been complete
+       /*
+        * now loop and write out the data
         */
        while (sectors_to_transfer > 0) {
-               /* If we've filled the present buffer but there's another
-                  chained buffer after it, move on. */
-               if (rq->current_nr_sectors == 0 && rq->nr_sectors > 0)
-                       cdrom_end_request(1, drive);
+               int this_transfer;
+
+               if (!rq->current_nr_sectors) {
+                       printk("ide-cd: write_intr: oops\n");
+                       break;
+               }
+
+               /*
+                * Figure out how many sectors we can transfer
+                */
+               this_transfer = MIN(sectors_to_transfer,rq->current_nr_sectors);
+
+               while (this_transfer > 0) {
+                       atapi_output_bytes(drive, rq->buffer, SECTOR_SIZE);
+                       rq->buffer += SECTOR_SIZE;
+                       --rq->nr_sectors;
+                       --rq->current_nr_sectors;
+                       ++rq->sector;
+                       --this_transfer;
+                       --sectors_to_transfer;
+               }
 
-               atapi_output_bytes(drive, rq->buffer, rq->current_nr_sectors);
-               rq->nr_sectors -= rq->current_nr_sectors;
-               rq->current_nr_sectors = 0;
-               rq->sector += rq->current_nr_sectors;
-               sectors_to_transfer -= rq->current_nr_sectors;
+               /*
+                * current buffer complete, move on
+                */
+               if (rq->current_nr_sectors == 0 && rq->nr_sectors)
+                       cdrom_end_request (1, drive);
        }
 
-       /* arm handler */
+       /* re-arm handler */
        ide_set_handler(drive, &cdrom_write_intr, 5 * WAIT_CMD, NULL);
        return ide_started;
 }
@@ -1584,10 +1656,26 @@ static ide_startstop_t cdrom_start_write_cont(ide_drive_t *drive)
        return cdrom_transfer_packet_command(drive, &pc, cdrom_write_intr);
 }
 
-static ide_startstop_t cdrom_start_write(ide_drive_t *drive)
+static ide_startstop_t cdrom_start_write(ide_drive_t *drive, struct request *rq)
 {
        struct cdrom_info *info = drive->driver_data;
 
+       /*
+        * writes *must* be 2kB frame aligned
+        */
+       if ((rq->nr_sectors & 3) || (rq->sector & 3)) {
+               cdrom_end_request(0, drive);
+               return ide_stopped;
+       }
+
+       /*
+        * for dvd-ram and such media, it's a really big deal to get
+        * big writes all the time. so scour the queue and attempt to
+        * remerge requests, often the plugging will not have had time
+        * to do this properly
+        */
+       cdrom_attempt_remerge(drive, rq);
+
        info->nsectors_buffered = 0;
 
         /* use dma, if possible. we don't need to check more, since we
@@ -1630,7 +1718,7 @@ ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, unsigned long block)
                                if (rq->cmd == READ)
                                        action = cdrom_start_read(drive, block);
                                else
-                                       action = cdrom_start_write(drive);
+                                       action = cdrom_start_write(drive, rq);
                        }
                        info->last_block = block;
                        return action;
@@ -1833,6 +1921,7 @@ static int cdrom_read_tocentry(ide_drive_t *drive, int trackno, int msf_flag,
 
        pc.buffer =  buf;
        pc.buflen = buflen;
+       pc.quiet = 1;
        pc.c[0] = GPCMD_READ_TOC_PMA_ATIP;
        pc.c[6] = trackno;
        pc.c[7] = (buflen >> 8);
@@ -1985,7 +2074,7 @@ static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense)
        /* Now try to get the total cdrom capacity. */
        minor = (drive->select.b.unit) << PARTN_BITS;
        dev = MKDEV(HWIF(drive)->major, minor);
-       stat = cdrom_get_last_written(dev, (long *)&toc->capacity);
+       stat = cdrom_get_last_written(dev, &toc->capacity);
        if (stat)
                stat = cdrom_read_capacity(drive, &toc->capacity, sense);
        if (stat)
@@ -2786,7 +2875,7 @@ int ide_cdrom_open (struct inode *ip, struct file *fp, ide_drive_t *drive)
        MOD_INC_USE_COUNT;
        if (info->buffer == NULL)
                info->buffer = (char *) kmalloc(SECTOR_BUFFER_SIZE, GFP_KERNEL);
-       if ((info->buffer == NULL) || (rc = cdrom_fops.open(ip, fp))) {
+        if ((info->buffer == NULL) || (rc = cdrom_fops.open(ip, fp))) {
                drive->usage--;
                MOD_DEC_USE_COUNT;
        }
@@ -2827,7 +2916,12 @@ void ide_cdrom_revalidate (ide_drive_t *drive)
        drive->part[0].nr_sects = toc->capacity * SECTORS_PER_FRAME;
        HWIF(drive)->gd->sizes[minor] = toc->capacity * BLOCKS_PER_FRAME;
 
+       /*
+        * reset block size, ide_revalidate_disk incorrectly sets it to
+        * 1024 even for CDROM's
+        */
        blk_size[HWIF(drive)->major] = HWIF(drive)->gd->sizes;
+       set_blocksize(MKDEV(HWIF(drive)->major, minor), CD_FRAMESIZE);
 }
 
 static
@@ -2862,20 +2956,32 @@ int ide_cdrom_cleanup(ide_drive_t *drive)
        return 0;
 }
 
+static
+int ide_cdrom_reinit (ide_drive_t *drive)
+{
+       return 0;
+}
+
 static ide_driver_t ide_cdrom_driver = {
        name:                   "ide-cdrom",
        version:                IDECD_VERSION,
        media:                  ide_cdrom,
+       busy:                   0,
        supports_dma:           1,
        supports_dsc_overlap:   1,
        cleanup:                ide_cdrom_cleanup,
        do_request:             ide_do_rw_cdrom,
+       end_request:            NULL,
        ioctl:                  ide_cdrom_ioctl,
        open:                   ide_cdrom_open,
        release:                ide_cdrom_release,
        media_change:           ide_cdrom_check_media_change,
        revalidate:             ide_cdrom_revalidate,
+       pre_reset:              NULL,
        capacity:               ide_cdrom_capacity,
+       special:                NULL,
+       proc:                   NULL,
+       driver_reinit:          ide_cdrom_reinit,
 };
 
 int ide_cdrom_init(void);
index f77992011618780e254e147d84dd6c50f8401ef6..702f3be3c85cc21e442c41831eb2ce3afb27adf3 100644 (file)
 
 /************************************************************************/
 
-#define SECTOR_SIZE            512
 #define SECTOR_BITS            9
-#define SECTORS_PER_FRAME      (CD_FRAMESIZE / SECTOR_SIZE)
+#define SECTOR_SIZE            (1 << SECTOR_BITS)
+#define SECTORS_PER_FRAME      (CD_FRAMESIZE >> SECTOR_BITS)
 #define SECTOR_BUFFER_SIZE     (CD_FRAMESIZE * 32)
-#define SECTORS_BUFFER         (SECTOR_BUFFER_SIZE / SECTOR_SIZE)
+#define SECTORS_BUFFER         (SECTOR_BUFFER_SIZE >> SECTOR_BITS)
+#define SECTORS_MAX            (131072 >> SECTOR_BITS)
 
 #define BLOCKS_PER_FRAME       (CD_FRAMESIZE / BLOCK_SIZE)
 
index d246487e92567e0606d0cdaa11ab32faaec1d324..f7dedd9102b7e133d3762702f86e02d33e99bbca 100644 (file)
@@ -369,6 +369,7 @@ static ide_startstop_t do_rw_disk (ide_drive_t *drive, struct request *rq, unsig
 {
        if (IDE_CONTROL_REG)
                OUT_BYTE(drive->ctl,IDE_CONTROL_REG);
+       OUT_BYTE(0x00, IDE_FEATURE_REG);
        OUT_BYTE(rq->nr_sectors,IDE_NSECTOR_REG);
 #ifdef CONFIG_BLK_DEV_PDC4030
        if (drive->select.b.lba || IS_PDC4030_DRIVE) {
@@ -692,43 +693,8 @@ static void idedisk_add_settings(ide_drive_t *drive)
        ide_add_setting(drive,  "file_readahead",       SETTING_RW,                                     BLKFRAGET,              BLKFRASET,              TYPE_INTA,      0,      INT_MAX,                        1,      1024,   &max_readahead[major][minor],   NULL);
        ide_add_setting(drive,  "max_kb_per_request",   SETTING_RW,                                     BLKSECTGET,             BLKSECTSET,             TYPE_INTA,      1,      255,                            1,      2,      &max_sectors[major][minor],     NULL);
        ide_add_setting(drive,  "lun",                  SETTING_RW,                                     -1,                     -1,                     TYPE_INT,       0,      7,                              1,      1,      &drive->lun,                    NULL);
-}
-
-/*
- *     IDE subdriver functions, registered with ide.c
- */
-static ide_driver_t idedisk_driver = {
-       "ide-disk",             /* name */
-       IDEDISK_VERSION,        /* version */
-       ide_disk,               /* media */
-       0,                      /* busy */
-       1,                      /* supports_dma */
-       0,                      /* supports_dsc_overlap */
-       NULL,                   /* cleanup */
-       do_rw_disk,             /* do_request */
-       NULL,                   /* end_request */
-       NULL,                   /* ioctl */
-       idedisk_open,           /* open */
-       idedisk_release,        /* release */
-       idedisk_media_change,   /* media_change */
-       idedisk_revalidate,     /* revalidate */
-       idedisk_pre_reset,      /* pre_reset */
-       idedisk_capacity,       /* capacity */
-       idedisk_special,        /* special */
-       idedisk_proc            /* proc */
-};
-
-int idedisk_init (void);
-static ide_module_t idedisk_module = {
-       IDE_DRIVER_MODULE,
-       idedisk_init,
-       &idedisk_driver,
-       NULL
-};
-
-static int idedisk_cleanup (ide_drive_t *drive)
-{
-       return ide_unregister_subdriver(drive);
+       ide_add_setting(drive,  "failures",             SETTING_RW,                                     -1,                     -1,                     TYPE_INT,       0,      65535,                          1,      1,      &drive->failures,               NULL);
+       ide_add_setting(drive,  "max_failures",         SETTING_RW,                                     -1,                     -1,                     TYPE_INT,       0,      65535,                          1,      1,      &drive->max_failures,           NULL);
 }
 
 static void idedisk_setup (ide_drive_t *drive)
@@ -835,6 +801,69 @@ static void idedisk_setup (ide_drive_t *drive)
        drive->no_io_32bit = id->dword_io ? 1 : 0;
 }
 
+static int idedisk_reinit (ide_drive_t *drive)
+{
+       return 0;
+}
+
+static int idedisk_cleanup (ide_drive_t *drive)
+{
+       return ide_unregister_subdriver(drive);
+}
+
+/*
+ *      IDE subdriver functions, registered with ide.c
+ */
+static ide_driver_t idedisk_driver = {
+       name:                   "ide-disk",
+       version:                IDEDISK_VERSION,
+       media:                  ide_disk,
+       busy:                   0,
+       supports_dma:           1,
+       supports_dsc_overlap:   0,
+       cleanup:                idedisk_cleanup,
+       do_request:             do_rw_disk,
+       end_request:            NULL,
+       ioctl:                  NULL,
+       open:                   idedisk_open,
+       release:                idedisk_release,
+       media_change:           idedisk_media_change,
+       revalidate:             idedisk_revalidate,
+       pre_reset:              idedisk_pre_reset,
+       capacity:               idedisk_capacity,
+       special:                idedisk_special,
+       proc:                   idedisk_proc,
+       driver_reinit:          idedisk_reinit,
+};
+
+int idedisk_init (void);
+static ide_module_t idedisk_module = {
+       IDE_DRIVER_MODULE,
+       idedisk_init,
+       &idedisk_driver,
+       NULL
+};
+
+MODULE_DESCRIPTION("ATA DISK Driver");
+
+static void __exit idedisk_exit (void)
+{
+       ide_drive_t *drive;
+       int failed = 0;
+
+       while ((drive = ide_scan_devices (ide_disk, idedisk_driver.name, &idedisk_driver, failed)) != NULL) {
+               if (idedisk_cleanup (drive)) {
+                       printk (KERN_ERR "%s: cleanup_module() called while still busy\n", drive->name);
+                       failed++;
+               }
+               /* We must remove proc entries defined in this module.
+                  Otherwise we oops while accessing these entries */
+               if (drive->proc)
+                       ide_remove_proc_entries(drive->proc, idedisk_proc);
+       }
+       ide_unregister_module(&idedisk_module);
+}
+
 int idedisk_init (void)
 {
        ide_drive_t *drive;
@@ -859,27 +888,5 @@ int idedisk_init (void)
        return 0;
 }
 
-#ifdef MODULE
-int init_module (void)
-{
-       return idedisk_init();
-}
-
-void cleanup_module (void)
-{
-       ide_drive_t *drive;
-       int failed = 0;
-
-       while ((drive = ide_scan_devices (ide_disk, idedisk_driver.name, &idedisk_driver, failed)) != NULL) {
-               if (idedisk_cleanup (drive)) {
-                       printk (KERN_ERR "%s: cleanup_module() called while still busy\n", drive->name);
-                       failed++;
-               }
-               /* We must remove proc entries defined in this module.
-                  Otherwise we oops while accessing these entries */
-               if (drive->proc)
-                       ide_remove_proc_entries(drive->proc, idedisk_proc);
-       }
-       ide_unregister_module(&idedisk_module);
-}
-#endif /* MODULE */
+module_init(idedisk_init);
+module_exit(idedisk_exit);
index 7158d34614b9716e46079b08001a6310e002a984..c92dbaaf1ed68d35977e9c35e0c5d6f592862821 100644 (file)
 #include <asm/io.h>
 #include <asm/irq.h>
 
-#undef CONFIG_BLK_DEV_IDEDMA_TIMEOUT
+/*
+ * Long lost data from 2.0.34 that is now in 2.0.39
+ *
+ * This was used in ./drivers/block/triton.c to do DMA Base address setup
+ * when PnP failed.  Oh the things we forget.  I believe this was part
+ * of SFF-8038i that has been withdrawn from public access... :-((
+ */
+#define DEFAULT_BMIBA  0xe800  /* in case BIOS did not init it */
+#define DEFAULT_BMCRBA 0xcc00  /* VIA's default value */
+#define DEFAULT_BMALIBA        0xd400  /* ALI's default value */
 
 extern char *ide_dmafunc_verbose(ide_dma_action_t dmafunc);
 
@@ -119,6 +128,12 @@ struct drive_list_entry drive_blacklist [] = {
        { "WDC AC31600H"        ,       "ALL"           },
        { "WDC AC32100H"        ,       "24.09P07"      },
        { "WDC AC23200L"        ,       "21.10N21"      },
+       { "Compaq CRD-8241B"    ,       "ALL"           },
+       { "CRD-8400B"           ,       "ALL"           },
+       { "SanDisk SDP3B-64"    ,       "ALL"           },
+       { "SAMSUNG CD-ROM SN-124",      "ALL"           },
+       { "PLEXTOR CD-R PX-W8432T",     "ALL"           },
+       { "ATAPI CD-ROM DRIVE 40X MAXIMUM",     "ALL"           },
        { 0                     ,       0               }
 
 };
@@ -206,7 +221,8 @@ ide_startstop_t ide_dma_intr (ide_drive_t *drive)
                        }
                        return ide_stopped;
                }
-               printk("%s: dma_intr: bad DMA status\n", drive->name);
+               printk("%s: dma_intr: bad DMA status (dma_stat=%x)\n", 
+                      drive->name, dma_stat);
        }
        return ide_error(drive, "dma_intr", stat);
 }
@@ -217,6 +233,9 @@ static int ide_build_sglist (ide_hwif_t *hwif, struct request *rq)
        struct scatterlist *sg = hwif->sg_table;
        int nents = 0;
 
+       if (hwif->sg_dma_active)
+               BUG();
+               
        if (rq->cmd == READ)
                hwif->sg_dma_direction = PCI_DMA_FROMDEVICE;
        else
@@ -282,11 +301,7 @@ int ide_build_dmatable (ide_drive_t *drive, ide_dma_action_t func)
                while (cur_len) {
                        if (count++ >= PRD_ENTRIES) {
                                printk("%s: DMA table too small\n", drive->name);
-                               pci_unmap_sg(HWIF(drive)->pci_dev,
-                                            HWIF(drive)->sg_table,
-                                            HWIF(drive)->sg_nents,
-                                            HWIF(drive)->sg_dma_direction);
-                               return 0; /* revert to PIO for this request */
+                               goto use_pio_instead;
                        } else {
                                u32 xcount, bcount = 0x10000 - (cur_addr & 0xffff);
 
@@ -296,6 +311,20 @@ int ide_build_dmatable (ide_drive_t *drive, ide_dma_action_t func)
                                xcount = bcount & 0xffff;
                                if (is_trm290_chipset)
                                        xcount = ((xcount >> 2) - 1) << 16;
+                               if (xcount == 0x0000) {
+                                       /* 
+                                        * Most chipsets correctly interpret a length of 0x0000 as 64KB,
+                                        * but at least one (e.g. CS5530) misinterprets it as zero (!).
+                                        * So here we break the 64KB entry into two 32KB entries instead.
+                                        */
+                                       if (count++ >= PRD_ENTRIES) {
+                                               printk("%s: DMA table too small\n", drive->name);
+                                               goto use_pio_instead;
+                                       }
+                                       *table++ = cpu_to_le32(0x8000);
+                                       *table++ = cpu_to_le32(cur_addr + 0x8000);
+                                       xcount = 0x8000;
+                               }
                                *table++ = cpu_to_le32(xcount);
                                cur_addr += bcount;
                                cur_len -= bcount;
@@ -306,12 +335,19 @@ int ide_build_dmatable (ide_drive_t *drive, ide_dma_action_t func)
                i--;
        }
 
-       if (!count)
-               printk("%s: empty DMA table?\n", drive->name);
-       else if (!is_trm290_chipset)
-               *--table |= cpu_to_le32(0x80000000);
-
-       return count;
+       if (count) {
+               if (!is_trm290_chipset)
+                       *--table |= cpu_to_le32(0x80000000);
+               return count;
+       }
+       printk("%s: empty DMA table?\n", drive->name);
+use_pio_instead:
+       pci_unmap_sg(HWIF(drive)->pci_dev,
+                    HWIF(drive)->sg_table,
+                    HWIF(drive)->sg_nents,
+                    HWIF(drive)->sg_dma_direction);
+       HWIF(drive)->sg_dma_active = 0;
+       return 0; /* revert to PIO for this request */
 }
 
 /* Teardown mappings after DMA has completed.  */
@@ -322,6 +358,7 @@ void ide_destroy_dmatable (ide_drive_t *drive)
        int nents = HWIF(drive)->sg_nents;
 
        pci_unmap_sg(dev, sg, nents, HWIF(drive)->sg_dma_direction);
+       HWIF(drive)->sg_dma_active = 0;
 }
 
 /*
@@ -426,6 +463,7 @@ static int config_drive_for_dma (ide_drive_t *drive)
        return hwif->dmaproc(ide_dma_off_quietly, drive);
 }
 
+#ifndef CONFIG_BLK_DEV_IDEDMA_TIMEOUT
 /*
  * 1 dmaing, 2 error, 4 intr
  */
@@ -449,6 +487,30 @@ static int dma_timer_expiry (ide_drive_t *drive)
                return WAIT_CMD;
        return 0;
 }
+#else /* CONFIG_BLK_DEV_IDEDMA_TIMEOUT */
+static ide_startstop_t ide_dma_timeout_revovery (ide_drive_t *drive)
+{
+       ide_hwgroup_t *hwgroup  = HWGROUP(drive);
+       ide_hwif_t *hwif        = HWIF(drive);
+       int enable_dma          = drive->using_dma;
+       unsigned long flags;
+       ide_startstop_t startstop;
+
+       spin_lock_irqsave(&io_request_lock, flags);
+       hwgroup->handler = NULL;
+       del_timer(&hwgroup->timer);
+       spin_unlock_irqrestore(&io_request_lock, flags);
+
+       drive->waiting_for_dma = 0;
+
+       startstop = ide_do_reset(drive);
+
+       if ((enable_dma) && !(drive->using_dma))
+               (void) hwif->dmaproc(ide_dma_on, drive);
+
+       return startstop;
+}
+#endif /* CONFIG_BLK_DEV_IDEDMA_TIMEOUT */
 
 /*
  * ide_dmaproc() initiates/aborts DMA read/write operations on a drive.
@@ -468,10 +530,11 @@ static int dma_timer_expiry (ide_drive_t *drive)
  */
 int ide_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
 {
-       ide_hwif_t *hwif = HWIF(drive);
-       unsigned long dma_base = hwif->dma_base;
-       byte unit = (drive->select.b.unit & 0x01);
-       unsigned int count, reading = 0;
+//     ide_hwgroup_t *hwgroup          = HWGROUP(drive);
+       ide_hwif_t *hwif                = HWIF(drive);
+       unsigned long dma_base          = hwif->dma_base;
+       byte unit                       = (drive->select.b.unit & 0x01);
+       unsigned int count, reading     = 0;
        byte dma_stat;
 
        switch (func) {
@@ -498,7 +561,11 @@ int ide_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
                        drive->waiting_for_dma = 1;
                        if (drive->media != ide_disk)
                                return 0;
+#ifdef CONFIG_BLK_DEV_IDEDMA_TIMEOUT
+                       ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL);  /* issue cmd to drive */
+#else /* !CONFIG_BLK_DEV_IDEDMA_TIMEOUT */
                        ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, dma_timer_expiry);      /* issue cmd to drive */
+#endif /* CONFIG_BLK_DEV_IDEDMA_TIMEOUT */
                        OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG);
                case ide_dma_begin:
                        /* Note that this is done *after* the cmd has
@@ -514,7 +581,7 @@ int ide_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
                        dma_stat = inb(dma_base+2);             /* get DMA status */
                        outb(dma_stat|6, dma_base+2);   /* clear the INTR & ERROR bits */
                        ide_destroy_dmatable(drive);    /* purge DMA mappings */
-                       return (dma_stat & 7) != 4;     /* verify good DMA status */
+                       return (dma_stat & 7) != 4 ? (0x10 | dma_stat) : 0;     /* verify good DMA status */
                case ide_dma_test_irq: /* returns 1 if dma irq issued, 0 otherwise */
                        dma_stat = inb(dma_base+2);
 #if 0  /* do not set unless you know what you are doing */
@@ -530,6 +597,14 @@ int ide_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
                case ide_dma_verbose:
                        return report_drive_dmaing(drive);
                case ide_dma_timeout:
+                       // FIXME: Many IDE chipsets do not permit command file register access
+                       // FIXME: while the bus-master function is still active.
+                       // FIXME: To prevent deadlock with those chipsets, we must be extremely
+                       // FIXME: careful here (and in ide_intr() as well) to NOT access any
+                       // FIXME: registers from the 0x1Fx/0x17x sets before terminating the
+                       // FIXME: bus-master operation via the bus-master control reg.
+                       // FIXME: Otherwise, chipset deadlock will occur, and some systems will
+                       // FIXME: lock up completely!!
 #ifdef CONFIG_BLK_DEV_IDEDMA_TIMEOUT
                        /*
                         * Have to issue an abort and requeue the request
@@ -537,6 +612,23 @@ int ide_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
                         * we have to clean up the mess, and here is as good
                         * as any.  Do it globally for all chipsets.
                         */
+                       outb(0x00, dma_base);           /* stop DMA */
+                       dma_stat = inb(dma_base+2);     /* get DMA status */
+                       outb(dma_stat|6, dma_base+2);   /* clear the INTR & ERROR bits */
+                       printk("%s: %s: Lets do it again!" \
+                               "stat = 0x%02x, dma_stat = 0x%02x\n",
+                               drive->name, ide_dmafunc_verbose(func),
+                               GET_STAT(), dma_stat);
+
+                       if (dma_stat & 0xF0)
+                               return ide_dma_timeout_revovery(drive);
+
+                       printk("%s: %s: (restart_request) Lets do it again!" \
+                               "stat = 0x%02x, dma_stat = 0x%02x\n",
+                               drive->name, ide_dmafunc_verbose(func),
+                               GET_STAT(), dma_stat);
+
+                       return restart_request(drive);  // BUG: return types do not match!!
 #endif /* CONFIG_BLK_DEV_IDEDMA_TIMEOUT */
                case ide_dma_retune:
                case ide_dma_lostirq:
@@ -620,6 +712,12 @@ unsigned long __init ide_get_or_set_dma_base (ide_hwif_t *hwif, int extra, const
        unsigned long   dma_base = 0;
        struct pci_dev  *dev = hwif->pci_dev;
 
+#ifdef CONFIG_BLK_DEV_IDEDMA_FORCED
+       int second_chance = 0;
+
+second_chance_to_dma:
+#endif /* CONFIG_BLK_DEV_IDEDMA_FORCED */
+
        if (hwif->mate && hwif->mate->dma_base) {
                dma_base = hwif->mate->dma_base - (hwif->channel ? 0 : 8);
        } else {
@@ -629,6 +727,26 @@ unsigned long __init ide_get_or_set_dma_base (ide_hwif_t *hwif, int extra, const
                        dma_base = 0;
                }
        }
+
+#ifdef CONFIG_BLK_DEV_IDEDMA_FORCED
+       if ((!dma_base) && (!second_chance)) {
+               unsigned long set_bmiba = 0;
+               second_chance++;
+               switch(dev->vendor) {
+                       case PCI_VENDOR_ID_AL:
+                               set_bmiba = DEFAULT_BMALIBA; break;
+                       case PCI_VENDOR_ID_VIA:
+                               set_bmiba = DEFAULT_BMCRBA; break;
+                       case PCI_VENDOR_ID_INTEL:
+                               set_bmiba = DEFAULT_BMIBA; break;
+                       default:
+                               return dma_base;
+               }
+               pci_write_config_dword(dev, 0x20, set_bmiba|1);
+               goto second_chance_to_dma;
+       }
+#endif /* CONFIG_BLK_DEV_IDEDMA_FORCED */
+
        if (dma_base) {
                if (extra) /* PDC20246, PDC20262, HPT343, & HPT366 */
                        request_region(dma_base+16, extra, name);
index fe48bc10c678e397d80a625365899c88dbbedc3e..9570f519bfe9dd52e04364c9c1eb47db0dae9632 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/drivers/ide/ide-floppy.c      Version 0.9     Jul   4, 1999
+ * linux/drivers/ide/ide-floppy.c      Version 0.9.sv  Jan 6 2001
  *
  * Copyright (C) 1996 - 1999 Gadi Oxman <gadio@netvision.net.il>
  */
  * Ver 0.9   Jul  4 99   Fix a bug which might have caused the number of
  *                        bytes requested on each interrupt to be zero.
  *                        Thanks to <shanos@es.co.nz> for pointing this out.
+ * Ver 0.9.sv Jan 6 01   Sam Varshavchik <mrsam@courier-mta.com>
+ *                       Implement low level formatting.  Reimplemented
+ *                       IDEFLOPPY_CAPABILITIES_PAGE, since we need the srfp
+ *                       bit.  My LS-120 drive barfs on
+ *                       IDEFLOPPY_CAPABILITIES_PAGE, but maybe it's just me.
+ *                       Compromise by not reporting a failure to get this
+ *                       mode page.  Implemented four IOCTLs in order to
+ *                       implement formatting.  IOCTls begin with 0x4600,
+ *                       0x46 is 'F' as in Format.
+ * Ver 0.91  Dec 11 99   Added IOMEGA Clik! drive support by 
+ *                        <paul@paulbristow.net>
+ * Ver 0.92  Oct 22 00   Paul Bristow became official maintainer for this 
+ *                        driver.  Included Powerbook internal zip kludge.
+ * Ver 0.93  Oct 24 00   Fixed bugs for Clik! drive
+ *                        no disk on insert and disk change now works
+ * Ver 0.94  Oct 27 00   Tidied up to remove strstr(Clik) everywhere
+ * Ver 0.95  Nov  7 00   Brought across to kernel 2.4
+ * Ver 0.96  Jan  7 01   Actually in line with release version of 2.4.0
+ *                       including set_bit patch from Rusty Russel
+ * Ver 0.97  Jul 22 01   Merge 0.91-0.96 onto 0.9.sv for ac series
  */
 
-#define IDEFLOPPY_VERSION "0.9"
+#define IDEFLOPPY_VERSION "0.97"
 
 #include <linux/config.h>
 #include <linux/module.h>
 #define IDEFLOPPY_DEBUG_INFO           0
 #define IDEFLOPPY_DEBUG_BUGS           1
 
+/* #define IDEFLOPPY_DEBUG(fmt, args...) printk(KERN_INFO fmt, ## args) */
+#define IDEFLOPPY_DEBUG( fmt, args... )
+
+
 /*
  *     Some drives require a longer irq timeout.
  */
@@ -228,6 +252,7 @@ typedef struct {
         *      Last error information
         */
        byte sense_key, asc, ascq;
+       int progress_indication;
 
        /*
         *      Device information
@@ -236,7 +261,7 @@ typedef struct {
        idefloppy_capacity_descriptor_t capacity;               /* Last format capacity */
        idefloppy_flexible_disk_page_t flexible_disk_page;      /* Copy of the flexible disk page */
        int wp;                                                 /* Write protect */
-
+       int srfp;                       /* Supports format progress report */
        unsigned long flags;                    /* Status/Action flags */
 } idefloppy_floppy_t;
 
@@ -246,6 +271,9 @@ typedef struct {
 #define IDEFLOPPY_DRQ_INTERRUPT                0       /* DRQ interrupt device */
 #define IDEFLOPPY_MEDIA_CHANGED                1       /* Media may have changed */
 #define IDEFLOPPY_USE_READ12           2       /* Use READ12/WRITE12 or READ10/WRITE10 */
+#define        IDEFLOPPY_FORMAT_IN_PROGRESS    3       /* Format in progress */
+#define IDEFLOPPY_CLIK_DRIVE           4       /* Avoid commands not supported in Clik drive */
+
 
 /*
  *     ATAPI floppy drive packet commands
@@ -275,6 +303,15 @@ typedef struct {
 #define MODE_SENSE_DEFAULT             0x02 
 #define MODE_SENSE_SAVED               0x03
 
+/*
+ *     IOCTLs used in low-level formatting.
+ */
+
+#define        IDEFLOPPY_IOCTL_FORMAT_SUPPORTED        0x4600
+#define        IDEFLOPPY_IOCTL_FORMAT_GET_CAPACITY     0x4601
+#define        IDEFLOPPY_IOCTL_FORMAT_START            0x4602
+#define IDEFLOPPY_IOCTL_FORMAT_GET_PROGRESS    0x4603
+
 /*
  *     Special requests for our block device strategy routine.
  */
@@ -559,7 +596,7 @@ typedef struct {
        u8              asc;                    /* Additional Sense Code */
        u8              ascq;                   /* Additional Sense Code Qualifier */
        u8              replaceable_unit_code;  /* Field Replaceable Unit Code */
-       u8              reserved[3];
+       u8              sksv[3];
        u8              pad[2];                 /* Padding to 20 bytes */
 } idefloppy_request_sense_result_t;
 
@@ -746,6 +783,8 @@ static void idefloppy_analyze_error (ide_drive_t *drive,idefloppy_request_sense_
        idefloppy_floppy_t *floppy = drive->driver_data;
 
        floppy->sense_key = result->sense_key; floppy->asc = result->asc; floppy->ascq = result->ascq;
+       floppy->progress_indication= result->sksv[0] & 0x80 ?
+               (unsigned short)get_unaligned((u16 *)(result->sksv+1)):0x10000;
 #if IDEFLOPPY_DEBUG_LOG
        if (floppy->failed_pc)
                printk (KERN_INFO "ide-floppy: pc = %x, sense key = %x, asc = %x, ascq = %x\n",floppy->failed_pc->c[0],result->sense_key,result->asc,result->ascq);
@@ -954,7 +993,7 @@ static ide_startstop_t idefloppy_transfer_pc (ide_drive_t *drive)
                return ide_do_reset (drive);
        }
        ide_set_handler (drive, &idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD, NULL);  /* Set the interrupt routine */
-       atapi_output_bytes (drive, floppy->pc->c, 12);          /* Send the actual packet */
+       atapi_output_bytes (drive, floppy->pc->c, 12); /* Send the actual packet */
        return ide_started;
 }
 
@@ -1062,6 +1101,22 @@ static void idefloppy_create_read_capacity_cmd (idefloppy_pc_t *pc)
        pc->request_transfer = 255;
 }
 
+static void idefloppy_create_format_unit_cmd (idefloppy_pc_t *pc, int b, int l)
+{
+       idefloppy_init_pc (pc);
+       pc->c[0] = IDEFLOPPY_FORMAT_UNIT_CMD;
+       pc->c[1] = 0x17;
+
+       memset(pc->buffer, 0, 12);
+       pc->buffer[1] = 0xA2;   /* Format list header, byte 1: FOV/DCRT/IMM */
+       pc->buffer[3] = 8;
+
+       put_unaligned(htonl(b), (unsigned int *)(&pc->buffer[4]));
+       put_unaligned(htonl(l), (unsigned int *)(&pc->buffer[8]));
+       pc->buffer_size=12;
+       set_bit(PC_WRITING, &pc->flags);
+}
+
 /*
  *     A mode sense command is used to "sense" floppy parameters.
  */
@@ -1235,6 +1290,25 @@ static int idefloppy_get_flexible_disk_page (ide_drive_t *drive)
        return 0;
 }
 
+static int idefloppy_get_capability_page(ide_drive_t *drive)
+{
+       idefloppy_floppy_t *floppy = drive->driver_data;
+       idefloppy_pc_t pc;
+       idefloppy_mode_parameter_header_t *header;
+       idefloppy_capabilities_page_t *page;
+
+       floppy->srfp=0;
+       idefloppy_create_mode_sense_cmd (&pc, IDEFLOPPY_CAPABILITIES_PAGE,
+                                                MODE_SENSE_CURRENT);
+       if (idefloppy_queue_pc_tail (drive,&pc)) {
+               return 1;
+       }
+       header = (idefloppy_mode_parameter_header_t *) pc.buffer;
+       page= (idefloppy_capabilities_page_t *)(header+1);
+       floppy->srfp=page->srfp;
+       return (0);
+}
+
 /*
  *     Determine if a media is present in the floppy drive, and if so,
  *     its LBA capacity.
@@ -1260,36 +1334,216 @@ static int idefloppy_get_capacity (ide_drive_t *drive)
        header = (idefloppy_capacity_header_t *) pc.buffer;
        descriptors = header->length / sizeof (idefloppy_capacity_descriptor_t);
        descriptor = (idefloppy_capacity_descriptor_t *) (header + 1);
+
        for (i = 0; i < descriptors; i++, descriptor++) {
-               blocks = descriptor->blocks = ntohl (descriptor->blocks);
-               length = descriptor->length = ntohs (descriptor->length);
-               if (!i && descriptor->dc == CAPACITY_CURRENT) {
-                       if (memcmp (descriptor, &floppy->capacity, sizeof (idefloppy_capacity_descriptor_t))) {
-                               printk (KERN_INFO "%s: %dkB, %d blocks, %d sector size, %s \n",
-                                       drive->name, blocks * length / 1024, blocks, length,
-                                       drive->using_dma ? ", DMA":"");
-                       }
-                       floppy->capacity = *descriptor;
-                       if (!length || length % 512)
-                               printk (KERN_ERR "%s: %d bytes block size not supported\n", drive->name, length);
-                       else {
-                               floppy->blocks = blocks;
-                               floppy->block_size = length;
-                               if ((floppy->bs_factor = length / 512) != 1)
-                                       printk (KERN_NOTICE "%s: warning: non 512 bytes block size not fully supported\n", drive->name);
-                               rc = 0;
-                       }
+                blocks = descriptor->blocks = ntohl (descriptor->blocks);
+                length = descriptor->length = ntohs (descriptor->length);
+
+               if (!i) 
+               {
+               switch (descriptor->dc) {
+                case CAPACITY_UNFORMATTED: /* Clik! drive returns this instead of CAPACITY_CURRENT */
+                        if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags))
+                                break; /* If it is not a clik drive, break out (maintains previous driver behaviour) */
+                case CAPACITY_CURRENT: /* Normal Zip/LS-120 disks */
+                        if (memcmp (descriptor, &floppy->capacity, sizeof (idefloppy_capacity_descriptor_t)))
+                                printk (KERN_INFO "%s: %dkB, %d blocks, %d sector size\n", drive->name, blocks * length / 1024, blocks, length);
+                        floppy->capacity = *descriptor;
+                        if (!length || length % 512)
+                                printk (KERN_NOTICE "%s: %d bytes block size not supported\n", drive->name, length);
+                        else {
+                                floppy->blocks = blocks;
+                                floppy->block_size = length;
+                                if ((floppy->bs_factor = length / 512) != 1)
+                                        printk (KERN_NOTICE "%s: warning: non 512 bytes block size not fully supported\n", drive->name);
+                                rc = 0;
+                        }
+                        break;
+                case CAPACITY_NO_CARTRIDGE:
+                        /* This is a KERN_ERR so it appears on screen for the user to see */
+                        printk (KERN_ERR "%s: No disk in drive\n", drive->name);
+                                        break;
+                case CAPACITY_INVALID:
+                        printk (KERN_ERR "%s: Invalid capacity for disk in drive\n", drive->name);
+                                        break;
                }
-#if IDEFLOPPY_DEBUG_INFO
-               if (!i) printk (KERN_INFO "Descriptor 0 Code: %d\n", descriptor->dc);
-               printk (KERN_INFO "Descriptor %d: %dkB, %d blocks, %d sector size\n", i, blocks * length / 1024, blocks, length);
-#endif /* IDEFLOPPY_DEBUG_INFO */
+               }
+               if (!i) {
+               IDEFLOPPY_DEBUG( "Descriptor 0 Code: %d\n", descriptor->dc);
+               }
+               IDEFLOPPY_DEBUG( "Descriptor %d: %dkB, %d blocks, %d sector size\n", i, blocks * length / 1024, blocks, length);
+       }
+
+       /* Clik! disk does not support get_flexible_disk_page */
+        if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags))
+       {
+               (void) idefloppy_get_flexible_disk_page (drive);
+               (void) idefloppy_get_capability_page (drive);
        }
-       (void) idefloppy_get_flexible_disk_page (drive);
+
        drive->part[0].nr_sects = floppy->blocks * floppy->bs_factor;
        return rc;
 }
 
+/*
+** Obtain the list of formattable capacities.
+** Very similar to idefloppy_get_capacity, except that we push the capacity
+** descriptors to userland, instead of our own structures.
+**
+** Userland gives us the following structure:
+**
+** struct idefloppy_format_capacities {
+**        int nformats;
+**        struct {
+**                int nblocks;
+**                int blocksize;
+**                } formats[];
+**        } ;
+**
+** userland initializes nformats to the number of allocated formats[]
+** records.  On exit we set nformats to the number of records we've
+** actually initialized.
+**
+*/
+
+static int idefloppy_get_format_capacities (ide_drive_t *drive,
+                                           struct inode *inode,
+                                           struct file *file,
+                                           int *arg)   /* Cheater */
+{
+        idefloppy_pc_t pc;
+       idefloppy_capacity_header_t *header;
+        idefloppy_capacity_descriptor_t *descriptor;
+       int i, descriptors, blocks, length;
+       int u_array_size;
+       int u_index;
+       int *argp;
+
+       if (get_user(u_array_size, arg))
+               return (-EFAULT);
+
+       if (u_array_size <= 0)
+               return (-EINVAL);
+
+       idefloppy_create_read_capacity_cmd (&pc);
+       if (idefloppy_queue_pc_tail (drive, &pc)) {
+               printk (KERN_ERR "ide-floppy: Can't get floppy parameters\n");
+                return (-EIO);
+        }
+        header = (idefloppy_capacity_header_t *) pc.buffer;
+        descriptors = header->length /
+               sizeof (idefloppy_capacity_descriptor_t);
+       descriptor = (idefloppy_capacity_descriptor_t *) (header + 1);
+
+       u_index=0;
+       argp=arg+1;
+
+       /*
+       ** We always skip the first capacity descriptor.  That's the
+       ** current capacity.  We are interested in the remaining descriptors,
+       ** the formattable capacities.
+       */
+
+       for (i=0; i<descriptors; i++, descriptor++)
+       {
+               if (u_index >= u_array_size)
+                       break;  /* User-supplied buffer too small */
+               if (i == 0)
+                       continue;       /* Skip the first descriptor */
+
+               blocks = ntohl (descriptor->blocks);
+               length = ntohs (descriptor->length);
+
+               if (put_user(blocks, argp))
+                       return (-EFAULT);
+               ++argp;
+
+               if (put_user(length, argp))
+                       return (-EFAULT);
+               ++argp;
+
+               ++u_index;
+       }
+
+       if (put_user(u_index, arg))
+               return (-EFAULT);
+       return (0);
+}
+
+/*
+** Send ATAPI_FORMAT_UNIT to the drive.
+**
+** Userland gives us the following structure:
+**
+** struct idefloppy_format_command {
+**        int nblocks;
+**        int blocksize;
+**        } ;
+*/
+
+static int idefloppy_begin_format(ide_drive_t *drive,
+                                 struct inode *inode,
+                                 struct file *file,
+                                 int *arg)
+{
+       int blocks;
+       int length;
+       idefloppy_pc_t pc;
+
+       if (get_user(blocks, arg)
+           || get_user(length, arg+1))
+       {
+               return (-EFAULT);
+       }
+
+       idefloppy_create_format_unit_cmd(&pc, blocks, length);
+       if (idefloppy_queue_pc_tail (drive, &pc))
+       {
+                return (-EIO);
+        }
+       return (0);
+}
+
+/*
+** Get ATAPI_FORMAT_UNIT progress indication.
+**
+** Userland gives a pointer to an int.  The int is set to a progresss
+** indicator 0-65536, with 65536=100%.
+**
+** If the drive does not support format progress indication, we just return
+** a 65536, screw it.
+*/
+
+static int idefloppy_get_format_progress(ide_drive_t *drive,
+                                        struct inode *inode,
+                                        struct file *file,
+                                        int *arg)
+{
+       idefloppy_floppy_t *floppy = drive->driver_data;
+       idefloppy_pc_t pc;
+       int progress_indication=0x10000;
+
+       if (floppy->srfp)
+       {
+               idefloppy_create_request_sense_cmd(&pc);
+               if (idefloppy_queue_pc_tail (drive, &pc))
+               {
+                       return (-EIO);
+               }
+
+               if (floppy->sense_key == 2 && floppy->asc == 4 &&
+                   floppy->ascq == 4)
+               {
+                       progress_indication=floppy->progress_indication;
+               }
+       }
+
+       if (put_user(progress_indication, arg))
+               return (-EFAULT);
+
+       return (0);
+}
+
 /*
  *     Our special ide-floppy ioctl's.
  *
@@ -1299,15 +1553,72 @@ static int idefloppy_ioctl (ide_drive_t *drive, struct inode *inode, struct file
                                 unsigned int cmd, unsigned long arg)
 {
        idefloppy_pc_t pc;
+       idefloppy_floppy_t *floppy = drive->driver_data;
+       int prevent = (arg) ? 1 : 0;
 
-       if (cmd == CDROMEJECT) {
+       switch (cmd) {
+       case CDROMEJECT:
+               prevent = 0;
+               /* fall through */
+       case CDROM_LOCKDOOR:
                if (drive->usage > 1)
                        return -EBUSY;
-               idefloppy_create_prevent_cmd (&pc, 0);
-               (void) idefloppy_queue_pc_tail (drive, &pc);
-               idefloppy_create_start_stop_cmd (&pc, 2);
-               (void) idefloppy_queue_pc_tail (drive, &pc);
+
+               /* The IOMEGA Clik! Drive doesn't support this command - no room for an eject mechanism */
+                if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) {
+                       idefloppy_create_prevent_cmd (&pc, prevent);
+                       (void) idefloppy_queue_pc_tail (drive, &pc);
+               }
+               if (cmd == CDROMEJECT) {
+                       idefloppy_create_start_stop_cmd (&pc, 2);
+                       (void) idefloppy_queue_pc_tail (drive, &pc);
+               }
                return 0;
+       case IDEFLOPPY_IOCTL_FORMAT_SUPPORTED:
+               return (0);
+       case IDEFLOPPY_IOCTL_FORMAT_GET_CAPACITY:
+               return (idefloppy_get_format_capacities(drive, inode, file,
+                                                       (int *)arg));
+       case IDEFLOPPY_IOCTL_FORMAT_START:
+
+               if (!(file->f_mode & 2))
+                       return (-EPERM);
+
+               {
+                       idefloppy_floppy_t *floppy = drive->driver_data;
+
+                       set_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags);
+
+                       if (drive->usage > 1)
+                       {
+                               /* Don't format if someone is using the disk */
+
+                               clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS,
+                                         &floppy->flags);
+                               return -EBUSY;
+                       }
+                       else
+                       {
+                               int rc=idefloppy_begin_format(drive, inode,
+                                                             file,
+                                                             (int *)arg);
+
+                               if (rc)
+                                       clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS,
+                                                 &floppy->flags);
+                               return (rc);
+
+                       /*
+                       ** Note, the bit will be cleared when the device is
+                       ** closed.  This is the cleanest way to handle the
+                       ** situation where the drive does not support
+                       ** format progress reporting.
+                       */
+                       }
+               }
+       case IDEFLOPPY_IOCTL_FORMAT_GET_PROGRESS:
+               return (idefloppy_get_format_progress(drive, inode, file,
+                                                     (int *)arg));
        }
        return -EIO;
 }
@@ -1326,26 +1637,41 @@ static int idefloppy_open (struct inode *inode, struct file *filp, ide_drive_t *
 
        MOD_INC_USE_COUNT;
        if (drive->usage == 1) {
+
+               clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags);
+               /* Just in case */
+
                idefloppy_create_test_unit_ready_cmd(&pc);
                if (idefloppy_queue_pc_tail(drive, &pc)) {
                        idefloppy_create_start_stop_cmd (&pc, 1);
                        (void) idefloppy_queue_pc_tail (drive, &pc);
                }
+
                if (idefloppy_get_capacity (drive)) {
                        drive->usage--;
                        MOD_DEC_USE_COUNT;
                        return -EIO;
                }
+
                if (floppy->wp && (filp->f_mode & 2)) {
                        drive->usage--;
                        MOD_DEC_USE_COUNT;
                        return -EROFS;
                }               
                set_bit (IDEFLOPPY_MEDIA_CHANGED, &floppy->flags);
-               idefloppy_create_prevent_cmd (&pc, 1);
-               (void) idefloppy_queue_pc_tail (drive, &pc);
+               /* IOMEGA Clik! drives do not support lock/unlock commands */
+                if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) {
+                       idefloppy_create_prevent_cmd (&pc, 1);
+                       (void) idefloppy_queue_pc_tail (drive, &pc);
+               }
                check_disk_change(inode->i_rdev);
        }
+       else if (test_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags))
+       {
+               drive->usage--;
+               MOD_DEC_USE_COUNT;
+               return -EBUSY;
+       }
        return 0;
 }
 
@@ -1358,9 +1684,17 @@ static void idefloppy_release (struct inode *inode, struct file *filp, ide_drive
 #endif /* IDEFLOPPY_DEBUG_LOG */
 
        if (!drive->usage) {
+               idefloppy_floppy_t *floppy = drive->driver_data;
+
                invalidate_buffers (inode->i_rdev);
-               idefloppy_create_prevent_cmd (&pc, 0);
-               (void) idefloppy_queue_pc_tail (drive, &pc);
+
+               /* IOMEGA Clik! drives do not support lock/unlock commands */
+                if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) {
+                       idefloppy_create_prevent_cmd (&pc, 0);
+                       (void) idefloppy_queue_pc_tail (drive, &pc);
+               }
+
+               clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags);
        }
        MOD_DEC_USE_COUNT;
 }
@@ -1560,6 +1894,19 @@ static void idefloppy_setup (ide_drive_t *drive, idefloppy_floppy_t *floppy)
                        max_sectors[major][minor + i] = 64;
        }
 
+       /*
+       *      Guess what?  The IOMEGA Clik! drive also needs the
+       *      above fix.  It makes nasty clicking noises without
+       *      it, so please don't remove this.
+       */
+       if (strcmp(drive->id->model, "IOMEGA Clik! 40 CZ ATAPI") == 0) 
+       {
+               for (i = 0; i < 1 << PARTN_BITS; i++)
+                       max_sectors[major][minor + i] = 64;
+               set_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags);
+       }
+
+
        (void) idefloppy_get_capacity (drive);
        idefloppy_add_settings(drive);
        for (i = 0; i < MAX_DRIVES; ++i) {
@@ -1597,28 +1944,34 @@ static ide_proc_entry_t idefloppy_proc[] = {
 
 #endif /* CONFIG_PROC_FS */
 
+static int idefloppy_reinit (ide_drive_t *drive)
+{
+       return 0;
+}
+
 /*
  *     IDE subdriver functions, registered with ide.c
  */
 static ide_driver_t idefloppy_driver = {
-       "ide-floppy",           /* name */
-       IDEFLOPPY_VERSION,      /* version */
-       ide_floppy,             /* media */
-       0,                      /* busy */
-       1,                      /* supports_dma */
-       0,                      /* supports_dsc_overlap */
-       idefloppy_cleanup,      /* cleanup */
-       idefloppy_do_request,   /* do_request */
-       idefloppy_end_request,  /* end_request */
-       idefloppy_ioctl,        /* ioctl */
-       idefloppy_open,         /* open */
-       idefloppy_release,      /* release */
-       idefloppy_media_change, /* media_change */
-       idefloppy_revalidate,   /* media_change */
-       NULL,                   /* pre_reset */
-       idefloppy_capacity,     /* capacity */
-       NULL,                   /* special */
-       idefloppy_proc          /* proc */
+       name:                   "ide-floppy",
+       version:                IDEFLOPPY_VERSION,
+       media:                  ide_floppy,
+       busy:                   0,
+       supports_dma:           1,
+       supports_dsc_overlap:   0,
+       cleanup:                idefloppy_cleanup,
+       do_request:             idefloppy_do_request,
+       end_request:            idefloppy_end_request,
+       ioctl:                  idefloppy_ioctl,
+       open:                   idefloppy_open,
+       release:                idefloppy_release,
+       media_change:           idefloppy_media_change,
+       revalidate:             idefloppy_revalidate,
+       pre_reset:              NULL,
+       capacity:               idefloppy_capacity,
+       special:                NULL,
+       proc:                   idefloppy_proc,
+       driver_reinit:          idefloppy_reinit,
 };
 
 int idefloppy_init (void);
@@ -1629,6 +1982,26 @@ static ide_module_t idefloppy_module = {
        NULL
 };
 
+MODULE_DESCRIPTION("ATAPI FLOPPY Driver");
+
+static void __exit idefloppy_exit (void)
+{
+       ide_drive_t *drive;
+       int failed = 0;
+
+       while ((drive = ide_scan_devices (ide_floppy, idefloppy_driver.name, &idefloppy_driver, failed)) != NULL) {
+               if (idefloppy_cleanup (drive)) {
+                       printk ("%s: cleanup_module() called while still busy\n", drive->name);
+                       failed++;
+               }
+               /* We must remove proc entries defined in this module.
+                  Otherwise we oops while accessing these entries */
+               if (drive->proc)
+                       ide_remove_proc_entries(drive->proc, idefloppy_proc);
+       }
+       ide_unregister_module(&idefloppy_module);
+}
+
 /*
  *     idefloppy_init will register the driver for each floppy.
  */
@@ -1638,6 +2011,7 @@ int idefloppy_init (void)
        idefloppy_floppy_t *floppy;
        int failed = 0;
 
+       printk("ide-floppy driver " IDEFLOPPY_VERSION "\n");
        MOD_INC_USE_COUNT;
        while ((drive = ide_scan_devices (ide_floppy, idefloppy_driver.name, NULL, failed++)) != NULL) {
                if (!idefloppy_identify_device (drive, drive->id)) {
@@ -1665,27 +2039,5 @@ int idefloppy_init (void)
        return 0;
 }
 
-#ifdef MODULE
-int init_module (void)
-{
-       return idefloppy_init ();
-}
-
-void cleanup_module (void)
-{
-       ide_drive_t *drive;
-       int failed = 0;
-
-       while ((drive = ide_scan_devices (ide_floppy, idefloppy_driver.name, &idefloppy_driver, failed)) != NULL) {
-               if (idefloppy_cleanup (drive)) {
-                       printk ("%s: cleanup_module() called while still busy\n", drive->name);
-                       failed++;
-               }
-               /* We must remove proc entries defined in this module.
-                  Otherwise we oops while accessing these entries */
-               if (drive->proc)
-                       ide_remove_proc_entries(drive->proc, idefloppy_proc);
-       }
-       ide_unregister_module(&idefloppy_module);
-}
-#endif /* MODULE */
+module_init(idefloppy_init);
+module_exit(idefloppy_exit);
index cd573b35ce8536b150d1df7272bdaad08ce26bcd..506ff25f38d76a5098560c6e20b905db6a236493 100644 (file)
 
 #define DEVID_PIIXa    ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82371FB_0})
 #define DEVID_PIIXb    ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82371FB_1})
+#define DEVID_MPIIX    ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82371MX})
 #define DEVID_PIIX3    ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82371SB_1})
 #define DEVID_PIIX4    ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82371AB})
-#define DEVID_ICH0     ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82801AB_1})
+#define DEVID_PIIX4E   ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82801AB_1})
 #define DEVID_PIIX4E2  ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82443MX_1})
-#define DEVID_ICH      ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82801AA_1})
+#define DEVID_PIIX4U   ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82801AA_1})
 #define DEVID_PIIX4U2  ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82372FB_1})
 #define DEVID_PIIX4NX  ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82451NX})
-#define DEVID_ICH2     ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82801BA_9})
-#define DEVID_ICH2M    ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82801BA_8})
+#define DEVID_PIIX4U3  ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82801BA_9})
+#define DEVID_PIIX4U4  ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82801BA_8})
 #define DEVID_VIA_IDE  ((ide_pci_devid_t){PCI_VENDOR_ID_VIA,     PCI_DEVICE_ID_VIA_82C561})
 #define DEVID_VP_IDE   ((ide_pci_devid_t){PCI_VENDOR_ID_VIA,     PCI_DEVICE_ID_VIA_82C586_1})
 #define DEVID_PDC20246 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20246})
 #define DEVID_PDC20262 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20262})
 #define DEVID_PDC20265 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20265})
 #define DEVID_PDC20267 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20267})
+#define DEVID_PDC20268  ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20268})
+#define DEVID_PDC20268R ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20268R})
 #define DEVID_RZ1000   ((ide_pci_devid_t){PCI_VENDOR_ID_PCTECH,  PCI_DEVICE_ID_PCTECH_RZ1000})
 #define DEVID_RZ1001   ((ide_pci_devid_t){PCI_VENDOR_ID_PCTECH,  PCI_DEVICE_ID_PCTECH_RZ1001})
 #define DEVID_SAMURAI  ((ide_pci_devid_t){PCI_VENDOR_ID_PCTECH,  PCI_DEVICE_ID_PCTECH_SAMURAI_IDE})
 #define DEVID_CY82C693 ((ide_pci_devid_t){PCI_VENDOR_ID_CONTAQ,  PCI_DEVICE_ID_CONTAQ_82C693})
 #define DEVID_HINT     ((ide_pci_devid_t){0x3388,                0x8013})
 #define DEVID_CS5530   ((ide_pci_devid_t){PCI_VENDOR_ID_CYRIX,   PCI_DEVICE_ID_CYRIX_5530_IDE})
-#define DEVID_AMD7403  ((ide_pci_devid_t){PCI_VENDOR_ID_AMD,     PCI_DEVICE_ID_AMD_COBRA_7403})
+#define DEVID_AMD7401  ((ide_pci_devid_t){PCI_VENDOR_ID_AMD,     PCI_DEVICE_ID_AMD_COBRA_7401})
 #define DEVID_AMD7409  ((ide_pci_devid_t){PCI_VENDOR_ID_AMD,     PCI_DEVICE_ID_AMD_VIPER_7409})
+#define DEVID_AMD7411  ((ide_pci_devid_t){PCI_VENDOR_ID_AMD,     PCI_DEVICE_ID_AMD_VIPER_7411})
+#define DEVID_PDCADMA  ((ide_pci_devid_t){PCI_VENDOR_ID_PDC,     PCI_DEVICE_ID_PDC_1841})
 #define DEVID_SLC90E66 ((ide_pci_devid_t){PCI_VENDOR_ID_EFAR,    PCI_DEVICE_ID_EFAR_SLC90E66_1})
 #define DEVID_OSB4     ((ide_pci_devid_t){PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4IDE})
+#define DEVID_CSB5     ((ide_pci_devid_t){PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5IDE})
+#define DEVID_ITE8172G ((ide_pci_devid_t){PCI_VENDOR_ID_ITE,     PCI_DEVICE_ID_ITE_IT8172G})
 
 #define        IDE_IGNORE      ((void *)-1)
 
@@ -110,20 +117,20 @@ extern void ide_dmacapable_ali15x3(ide_hwif_t *, unsigned long);
 #define DMA_ALI15X3    NULL
 #endif
 
-#ifdef CONFIG_BLK_DEV_AMD7409
-extern unsigned int pci_init_amd7409(struct pci_dev *, const char *);
-extern unsigned int ata66_amd7409(ide_hwif_t *);
-extern void ide_init_amd7409(ide_hwif_t *);
-extern void ide_dmacapable_amd7409(ide_hwif_t *, unsigned long);
-#define PCI_AMD7409    &pci_init_amd7409
-#define ATA66_AMD7409  &ata66_amd7409
-#define INIT_AMD7409   &ide_init_amd7409
-#define DMA_AMD7409    &ide_dmacapable_amd7409
+#ifdef CONFIG_BLK_DEV_AMD74XX
+extern unsigned int pci_init_amd74xx(struct pci_dev *, const char *);
+extern unsigned int ata66_amd74xx(ide_hwif_t *);
+extern void ide_init_amd74xx(ide_hwif_t *);
+extern void ide_dmacapable_amd74xx(ide_hwif_t *, unsigned long);
+#define PCI_AMD74XX    &pci_init_amd74xx
+#define ATA66_AMD74XX  &ata66_amd74xx
+#define INIT_AMD74XX   &ide_init_amd74xx
+#define DMA_AMD74XX    &ide_dmacapable_amd74xx
 #else
-#define PCI_AMD7409    NULL
-#define ATA66_AMD7409  NULL
-#define INIT_AMD7409   NULL
-#define DMA_AMD7409    NULL
+#define PCI_AMD74XX    NULL
+#define ATA66_AMD74XX  NULL
+#define INIT_AMD74XX   NULL
+#define DMA_AMD74XX    NULL
 #endif
 
 #ifdef CONFIG_BLK_DEV_CMD64X
@@ -186,8 +193,8 @@ extern void ide_dmacapable_hpt366(ide_hwif_t *, unsigned long);
 #define INIT_HPT366    &ide_init_hpt366
 #define DMA_HPT366     &ide_dmacapable_hpt366
 #else
-static byte hpt363_shared_irq = 0;
-static byte hpt363_shared_pin = 0;
+static byte hpt363_shared_irq;
+static byte hpt363_shared_pin;
 #define PCI_HPT366     NULL
 #define ATA66_HPT366   NULL
 #define INIT_HPT366    NULL
@@ -208,17 +215,20 @@ extern void ide_init_opti621(ide_hwif_t *);
 #define INIT_OPTI621   NULL
 #endif
 
-#ifdef CONFIG_BLK_DEV_OSB4
-extern unsigned int pci_init_osb4(struct pci_dev *, const char *);
-extern unsigned int ata66_osb4(ide_hwif_t *);
-extern void ide_init_osb4(ide_hwif_t *);
-#define PCI_OSB4        &pci_init_osb4
-#define ATA66_OSB4      &ata66_osb4
-#define INIT_OSB4       &ide_init_osb4
+#ifdef CONFIG_BLK_DEV_PDC_ADMA
+extern unsigned int pci_init_pdcadma(struct pci_dev *, const char *);
+extern unsigned int ata66_pdcadma(ide_hwif_t *);
+extern void ide_init_pdcadma(ide_hwif_t *);
+extern void ide_dmacapable_pdcadma(ide_hwif_t *, unsigned long);
+#define PCI_PDCADMA    &pci_init_pdcadma
+#define ATA66_PDCADMA  &ata66_pdcadma
+#define INIT_PDCADMA   &ide_init_pdcadma
+#define DMA_PDCADMA    &ide_dmacapable_pdcadma
 #else
-#define PCI_OSB4        NULL
-#define ATA66_OSB4      NULL
-#define INIT_OSB4       NULL
+#define PCI_PDCADMA    IDE_IGNORE
+#define ATA66_PDCADMA  IDE_IGNORE
+#define INIT_PDCADMA   IDE_IGNORE
+#define DMA_PDCADMA    IDE_IGNORE
 #endif
 
 #ifdef CONFIG_BLK_DEV_PDC202XX
@@ -247,6 +257,18 @@ extern void ide_init_piix(ide_hwif_t *);
 #define INIT_PIIX      NULL
 #endif
 
+#ifdef CONFIG_BLK_DEV_IT8172
+extern unsigned int pci_init_it8172(struct pci_dev *, const char *);
+extern unsigned int ata66_it8172(ide_hwif_t *);
+extern void ide_init_it8172(ide_hwif_t *);
+#define PCI_IT8172     &pci_init_it8172
+#define INIT_IT8172    &ide_init_it8172
+#else
+#define PCI_IT8172     NULL
+#define ATA66_IT8172   NULL
+#define INIT_IT8172    NULL
+#endif
+
 #ifdef CONFIG_BLK_DEV_RZ1000
 extern void ide_init_rz1000(ide_hwif_t *);
 #define INIT_RZ1000    &ide_init_rz1000
@@ -256,6 +278,19 @@ extern void ide_init_rz1000(ide_hwif_t *);
 
 #define INIT_SAMURAI   NULL
 
+#ifdef CONFIG_BLK_DEV_SVWKS
+extern unsigned int pci_init_svwks(struct pci_dev *, const char *);
+extern unsigned int ata66_svwks(ide_hwif_t *);
+extern void ide_init_svwks(ide_hwif_t *);
+#define PCI_SVWKS      &pci_init_svwks
+#define ATA66_SVWKS    &ata66_svwks
+#define INIT_SVWKS     &ide_init_svwks
+#else
+#define PCI_SVWKS      NULL
+#define ATA66_SVWKS    NULL
+#define INIT_SVWKS     NULL
+#endif
+
 #ifdef CONFIG_BLK_DEV_SIS5513
 extern unsigned int pci_init_sis5513(struct pci_dev *, const char *);
 extern unsigned int ata66_sis5513(ide_hwif_t *);
@@ -339,21 +374,34 @@ typedef struct ide_pci_device_s {
 static ide_pci_device_t ide_pci_chipsets[] __initdata = {
        {DEVID_PIIXa,   "PIIX",         NULL,           NULL,           INIT_PIIX,      NULL,           {{0x41,0x80,0x80}, {0x43,0x80,0x80}},   ON_BOARD,       0 },
        {DEVID_PIIXb,   "PIIX",         NULL,           NULL,           INIT_PIIX,      NULL,           {{0x41,0x80,0x80}, {0x43,0x80,0x80}},   ON_BOARD,       0 },
+       {DEVID_MPIIX,   "MPIIX",        NULL,           NULL,           INIT_PIIX,      NULL,           {{0x6D,0x80,0x80}, {0x6F,0x80,0x80}},   ON_BOARD,       0 },
        {DEVID_PIIX3,   "PIIX3",        PCI_PIIX,       NULL,           INIT_PIIX,      NULL,           {{0x41,0x80,0x80}, {0x43,0x80,0x80}},   ON_BOARD,       0 },
        {DEVID_PIIX4,   "PIIX4",        PCI_PIIX,       NULL,           INIT_PIIX,      NULL,           {{0x41,0x80,0x80}, {0x43,0x80,0x80}},   ON_BOARD,       0 },
-       {DEVID_ICH0,    "ICH0",         PCI_PIIX,       NULL,           INIT_PIIX,      NULL,           {{0x41,0x80,0x80}, {0x43,0x80,0x80}},   ON_BOARD,       0 },
+       {DEVID_PIIX4E,  "PIIX4",        PCI_PIIX,       NULL,           INIT_PIIX,      NULL,           {{0x41,0x80,0x80}, {0x43,0x80,0x80}},   ON_BOARD,       0 },
        {DEVID_PIIX4E2, "PIIX4",        PCI_PIIX,       NULL,           INIT_PIIX,      NULL,           {{0x41,0x80,0x80}, {0x43,0x80,0x80}},   ON_BOARD,       0 },
-       {DEVID_ICH,     "ICH",          PCI_PIIX,       ATA66_PIIX,     INIT_PIIX,      NULL,           {{0x41,0x80,0x80}, {0x43,0x80,0x80}},   ON_BOARD,       0 },
+       {DEVID_PIIX4U,  "PIIX4",        PCI_PIIX,       ATA66_PIIX,     INIT_PIIX,      NULL,           {{0x41,0x80,0x80}, {0x43,0x80,0x80}},   ON_BOARD,       0 },
        {DEVID_PIIX4U2, "PIIX4",        PCI_PIIX,       ATA66_PIIX,     INIT_PIIX,      NULL,           {{0x41,0x80,0x80}, {0x43,0x80,0x80}},   ON_BOARD,       0 },
        {DEVID_PIIX4NX, "PIIX4",        PCI_PIIX,       NULL,           INIT_PIIX,      NULL,           {{0x41,0x80,0x80}, {0x43,0x80,0x80}},   ON_BOARD,       0 },
-       {DEVID_ICH2,    "ICH2",         PCI_PIIX,       ATA66_PIIX,     INIT_PIIX,      NULL,           {{0x41,0x80,0x80}, {0x43,0x80,0x80}},   ON_BOARD,       0 },
-       {DEVID_ICH2M,   "ICH2-M",       PCI_PIIX,       ATA66_PIIX,     INIT_PIIX,      NULL,           {{0x41,0x80,0x80}, {0x43,0x80,0x80}},   ON_BOARD,       0 },
+       {DEVID_PIIX4U3, "PIIX4",        PCI_PIIX,       ATA66_PIIX,     INIT_PIIX,      NULL,           {{0x41,0x80,0x80}, {0x43,0x80,0x80}},   ON_BOARD,       0 },
+       {DEVID_PIIX4U4, "PIIX4",        PCI_PIIX,       ATA66_PIIX,     INIT_PIIX,      NULL,           {{0x41,0x80,0x80}, {0x43,0x80,0x80}},   ON_BOARD,       0 },
        {DEVID_VIA_IDE, "VIA_IDE",      NULL,           NULL,           NULL,           NULL,           {{0x00,0x00,0x00}, {0x00,0x00,0x00}},   ON_BOARD,       0 },
        {DEVID_VP_IDE,  "VP_IDE",       PCI_VIA82CXXX,  ATA66_VIA82CXXX,INIT_VIA82CXXX, DMA_VIA82CXXX,  {{0x40,0x02,0x02}, {0x40,0x01,0x01}},   ON_BOARD,       0 },
+#ifdef CONFIG_PDC202XX_FORCE
+        {DEVID_PDC20246,"PDC20246",    PCI_PDC202XX,   NULL,           INIT_PDC202XX,  NULL,           {{0x00,0x00,0x00}, {0x00,0x00,0x00}},   OFF_BOARD,      16 },
+        {DEVID_PDC20262,"PDC20262",    PCI_PDC202XX,   ATA66_PDC202XX, INIT_PDC202XX,  NULL,           {{0x00,0x00,0x00}, {0x00,0x00,0x00}},   OFF_BOARD,      48 },
+        {DEVID_PDC20265,"PDC20265",    PCI_PDC202XX,   ATA66_PDC202XX, INIT_PDC202XX,  NULL,           {{0x00,0x00,0x00}, {0x00,0x00,0x00}},   OFF_BOARD,      48 },
+        {DEVID_PDC20267,"PDC20267",    PCI_PDC202XX,   ATA66_PDC202XX, INIT_PDC202XX,  NULL,           {{0x00,0x00,0x00}, {0x00,0x00,0x00}},   OFF_BOARD,      48 },
+#else /* !CONFIG_PDC202XX_FORCE */
        {DEVID_PDC20246,"PDC20246",     PCI_PDC202XX,   NULL,           INIT_PDC202XX,  NULL,           {{0x50,0x02,0x02}, {0x50,0x04,0x04}},   OFF_BOARD,      16 },
        {DEVID_PDC20262,"PDC20262",     PCI_PDC202XX,   ATA66_PDC202XX, INIT_PDC202XX,  NULL,           {{0x50,0x02,0x02}, {0x50,0x04,0x04}},   OFF_BOARD,      48 },
        {DEVID_PDC20265,"PDC20265",     PCI_PDC202XX,   ATA66_PDC202XX, INIT_PDC202XX,  NULL,           {{0x50,0x02,0x02}, {0x50,0x04,0x04}},   OFF_BOARD,      48 },
        {DEVID_PDC20267,"PDC20267",     PCI_PDC202XX,   ATA66_PDC202XX, INIT_PDC202XX,  NULL,           {{0x50,0x02,0x02}, {0x50,0x04,0x04}},   OFF_BOARD,      48 },
+#endif
+       {DEVID_PDC20268,"PDC20268",     PCI_PDC202XX,   ATA66_PDC202XX, INIT_PDC202XX,  NULL,           {{0x00,0x00,0x00}, {0x00,0x00,0x00}},   OFF_BOARD,      16 },
+       /* Promise used a different PCI ident for the raid card apparently to try and
+          prevent Linux detecting it and using our own raid code. We want to detect
+          it for the ataraid drivers, so we have to list both here.. */
+       {DEVID_PDC20268R,"PDC20268",    PCI_PDC202XX,   ATA66_PDC202XX, INIT_PDC202XX,  NULL,           {{0x00,0x00,0x00}, {0x00,0x00,0x00}},   OFF_BOARD,      16 },
        {DEVID_RZ1000,  "RZ1000",       NULL,           NULL,           INIT_RZ1000,    NULL,           {{0x00,0x00,0x00}, {0x00,0x00,0x00}},   ON_BOARD,       0 },
        {DEVID_RZ1001,  "RZ1001",       NULL,           NULL,           INIT_RZ1000,    NULL,           {{0x00,0x00,0x00}, {0x00,0x00,0x00}},   ON_BOARD,       0 },
        {DEVID_SAMURAI, "SAMURAI",      NULL,           NULL,           INIT_SAMURAI,   NULL,           {{0x00,0x00,0x00}, {0x00,0x00,0x00}},   ON_BOARD,       0 },
@@ -382,10 +430,14 @@ static ide_pci_device_t ide_pci_chipsets[] __initdata = {
        {DEVID_CY82C693,"CY82C693",     PCI_CY82C693,   NULL,           INIT_CY82C693,  NULL,           {{0x00,0x00,0x00}, {0x00,0x00,0x00}},   ON_BOARD,       0 },
        {DEVID_HINT,    "HINT_IDE",     NULL,           NULL,           NULL,           NULL,           {{0x00,0x00,0x00}, {0x00,0x00,0x00}},   ON_BOARD,       0 },
        {DEVID_CS5530,  "CS5530",       PCI_CS5530,     NULL,           INIT_CS5530,    NULL,           {{0x00,0x00,0x00}, {0x00,0x00,0x00}},   ON_BOARD,       0 },
-       {DEVID_AMD7403, "AMD7403",      NULL,           NULL,           NULL,           NULL,           {{0x00,0x00,0x00}, {0x00,0x00,0x00}},   ON_BOARD,       0 },
-       {DEVID_AMD7409, "AMD7409",      PCI_AMD7409,    ATA66_AMD7409,  INIT_AMD7409,   DMA_AMD7409,    {{0x40,0x01,0x01}, {0x40,0x02,0x02}},   ON_BOARD,       0 },
+       {DEVID_AMD7401, "AMD7401",      NULL,           NULL,           NULL,           NULL,           {{0x00,0x00,0x00}, {0x00,0x00,0x00}},   ON_BOARD,       0 },
+       {DEVID_AMD7409, "AMD7409",      PCI_AMD74XX,    ATA66_AMD74XX,  INIT_AMD74XX,   DMA_AMD74XX,    {{0x40,0x01,0x01}, {0x40,0x02,0x02}},   ON_BOARD,       0 },
+       {DEVID_AMD7411, "AMD7411",      PCI_AMD74XX,    ATA66_AMD74XX,  INIT_AMD74XX,   DMA_AMD74XX,    {{0x40,0x01,0x01}, {0x40,0x02,0x02}},   ON_BOARD,       0 },
+       {DEVID_PDCADMA, "PDCADMA",      PCI_PDCADMA,    ATA66_PDCADMA,  INIT_PDCADMA,   DMA_PDCADMA,    {{0x00,0x00,0x00}, {0x00,0x00,0x00}},   OFF_BOARD,      0 },
        {DEVID_SLC90E66,"SLC90E66",     PCI_SLC90E66,   ATA66_SLC90E66, INIT_SLC90E66,  NULL,           {{0x41,0x80,0x80}, {0x43,0x80,0x80}},   ON_BOARD,       0 },
-        {DEVID_OSB4,    "ServerWorks OSB4",     PCI_OSB4,       ATA66_OSB4,     INIT_OSB4,      NULL,   {{0x00,0x00,0x00}, {0x00,0x00,0x00}},   ON_BOARD,       0 },
+        {DEVID_OSB4,    "ServerWorks OSB4",            PCI_SVWKS,      ATA66_SVWKS,    INIT_SVWKS,     NULL,           {{0x00,0x00,0x00}, {0x00,0x00,0x00}},   ON_BOARD,       0 },
+       {DEVID_CSB5,    "ServerWorks CSB5",             PCI_SVWKS,      ATA66_SVWKS,    INIT_SVWKS,     NULL,           {{0x00,0x00,0x00}, {0x00,0x00,0x00}},   ON_BOARD,       0 },
+       {DEVID_ITE8172G,"IT8172G",      PCI_IT8172,     NULL,   INIT_IT8172,    NULL,           {{0x00,0x00,0x00}, {0x40,0x00,0x01}},   ON_BOARD,       0 },
        {IDE_PCI_DEVID_NULL, "PCI_IDE", NULL,           NULL,           NULL,           NULL,           {{0x00,0x00,0x00}, {0x00,0x00,0x00}},   ON_BOARD,       0 }};
 
 /*
@@ -401,6 +453,7 @@ static unsigned int __init ide_special_settings (struct pci_dev *dev, const char
                case PCI_DEVICE_ID_PROMISE_20262:
                case PCI_DEVICE_ID_PROMISE_20265:
                case PCI_DEVICE_ID_PROMISE_20267:
+               case PCI_DEVICE_ID_PROMISE_20268:
                case PCI_DEVICE_ID_ARTOP_ATP850UF:
                case PCI_DEVICE_ID_ARTOP_ATP860:
                case PCI_DEVICE_ID_ARTOP_ATP860R:
@@ -528,9 +581,11 @@ static void __init ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t *
        byte tmp = 0;
        ide_hwif_t *hwif, *mate = NULL;
        unsigned int class_rev;
+       static int secondpdc = 0;
 
 #ifdef CONFIG_IDEDMA_AUTO
-       autodma = 1;
+       if (!noautodma)
+               autodma = 1;
 #endif
 
        pci_enable_device(dev);
@@ -628,8 +683,18 @@ check_if_enabled:
        for (port = 0; port <= 1; ++port) {
                unsigned long base = 0, ctl = 0;
                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 ((IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20265)) && (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 (IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT366) && (port) && (class_rev < 0x03))
                        return;
                if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE || (dev->class & (port ? 4 : 1)) != 0) {
@@ -679,6 +744,9 @@ check_if_enabled:
                        hwif->irq = hwif->channel ? 15 : 14;
                        goto bypass_umc_dma;
                }
+               if (IDE_PCI_DEVID_EQ(d->devid, DEVID_MPIIX))
+                       goto bypass_piix_dma;
+
                if (hwif->udma_four) {
                        printk("%s: ATA-66/100 forced bit set (WARNING)!!\n", d->name);
                } else {
@@ -688,7 +756,9 @@ check_if_enabled:
                if (IDE_PCI_DEVID_EQ(d->devid, DEVID_SIS5513) ||
                    IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6260) ||
                    IDE_PCI_DEVID_EQ(d->devid, DEVID_PIIX4NX) ||
-                   IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT34X))
+                   IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT34X)  ||
+                   IDE_PCI_DEVID_EQ(d->devid, DEVID_VIA_IDE) ||
+                   IDE_PCI_DEVID_EQ(d->devid, DEVID_VP_IDE))
                        autodma = 0;
                if (autodma)
                        hwif->autodma = 1;
@@ -696,6 +766,7 @@ check_if_enabled:
                    IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20262) ||
                    IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20265) ||
                    IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20267) ||
+                   IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20268) ||
                    IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6210) ||
                    IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6260) ||
                    IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6260R) ||
@@ -732,6 +803,7 @@ check_if_enabled:
                        }
                }
 #endif /* CONFIG_BLK_DEV_IDEDMA */
+bypass_piix_dma:
 bypass_umc_dma:
                if (d->init_hwif)  /* Call chipset-specific routine for each enabled hwif */
                        d->init_hwif(hwif);
@@ -760,7 +832,7 @@ static void __init hpt366_device_order_fixup (struct pci_dev *dev, ide_pci_devic
 
        switch(class_rev) {
                case 4:
-               case 3: printk("%s: IDE controller on PCI slot %s\n", d->name, dev->slot_name);
+               case 3: printk("%s: IDE controller on PCI bus %02x dev %02x\n", d->name, dev->bus->number, dev->devfn);
                        ide_setup_pci_device(dev, d);
                        return;
                default:        break;
@@ -779,16 +851,22 @@ static void __init hpt366_device_order_fixup (struct pci_dev *dev, ide_pci_devic
                        if (hpt363_shared_pin && hpt363_shared_irq) {
                                d->bootable = ON_BOARD;
                                printk("%s: onboard version of chipset, pin1=%d pin2=%d\n", d->name, pin1, pin2);
+#if 0
+                               /* I forgot why I did this once, but it fixed something. */
+                               pci_write_config_byte(dev2, PCI_INTERRUPT_PIN, dev->irq);
+                               printk("PCI: %s: Fixing interrupt %d pin %d to ZERO \n", d->name, dev2->irq, pin2);
+                               pci_write_config_byte(dev2, PCI_INTERRUPT_LINE, 0);
+#endif
                        }
                        break;
                }
        }
-       printk("%s: IDE controller on PCI slot %s\n", d->name, dev->slot_name);
+       printk("%s: IDE controller on PCI bus %02x dev %02x\n", d->name, dev->bus->number, dev->devfn);
        ide_setup_pci_device(dev, d);
        if (!dev2)
                return;
        d2 = d;
-       printk("%s: IDE controller on PCI slot %s\n", d2->name, dev2->slot_name);
+       printk("%s: IDE controller on PCI bus %02x dev %02x\n", d2->name, dev2->bus->number, dev2->devfn);
        ide_setup_pci_device(dev2, d2);
 }
 
@@ -810,16 +888,18 @@ void __init ide_scan_pcidev (struct pci_dev *dev)
                return;
        else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_CY82C693) && (!(PCI_FUNC(dev->devfn) & 1) || !((dev->class >> 8) == PCI_CLASS_STORAGE_IDE)))
                return; /* CY82C693 is more than only a IDE controller */
+       else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_ITE8172G) && (!(PCI_FUNC(dev->devfn) & 1) || !((dev->class >> 8) == PCI_CLASS_STORAGE_IDE)))
+               return; /* IT8172G is also more than only an IDE controller */
        else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_UM8886A) && !(PCI_FUNC(dev->devfn) & 1))
                return; /* UM8886A/BF pair */
        else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT366))
                hpt366_device_order_fixup(dev, d);
        else if (!IDE_PCI_DEVID_EQ(d->devid, IDE_PCI_DEVID_NULL) || (dev->class >> 8) == PCI_CLASS_STORAGE_IDE) {
                if (IDE_PCI_DEVID_EQ(d->devid, IDE_PCI_DEVID_NULL))
-                       printk("%s: unknown IDE controller on PCI slot %s, VID=%04x, DID=%04x\n",
-                              d->name, dev->slot_name, devid.vid, devid.did);
+                       printk("%s: unknown IDE controller on PCI bus %02x device %02x, VID=%04x, DID=%04x\n",
+                              d->name, dev->bus->number, dev->devfn, devid.vid, devid.did);
                else
-                       printk("%s: IDE controller on PCI slot %s\n", d->name, dev->slot_name);
+                       printk("%s: IDE controller on PCI bus %02x dev %02x\n", d->name, dev->bus->number, dev->devfn);
                ide_setup_pci_device(dev, d);
        }
 }
index c3eca05e6af98cd2c1a94108f63da43e2c0c1921..ca70cb81f789191ce7f1ae5b4c7b12afb857cf41 100644 (file)
@@ -681,9 +681,9 @@ static int init_irq (ide_hwif_t *hwif)
         */
        if (!match || match->irq != hwif->irq) {
 #ifdef CONFIG_IDEPCI_SHARE_IRQ
-               int sa = (hwif->chipset == ide_pci) ? SA_SHIRQ : SA_INTERRUPT;
+               int sa = IDE_CHIPSET_IS_PCI(hwif->chipset) ? SA_SHIRQ : SA_INTERRUPT;
 #else /* !CONFIG_IDEPCI_SHARE_IRQ */
-               int sa = (hwif->chipset == ide_pci) ? SA_INTERRUPT|SA_SHIRQ : SA_INTERRUPT;
+               int sa = IDE_CHIPSET_IS_PCI(hwif->chipset) ? SA_INTERRUPT|SA_SHIRQ : SA_INTERRUPT;
 #endif /* CONFIG_IDEPCI_SHARE_IRQ */
                if (ide_request_irq(hwif->irq, &ide_intr, sa, hwif->name, hwgroup)) {
                        if (!match)
index 56e8a959338af1c5189a848af41463834fb22804..950746722b1eb0df0bb0ba8cac875fa87ced1fe2 100644 (file)
@@ -81,10 +81,10 @@ int (*aec62xx_display_info)(char *, char **, off_t, int) = NULL;
 extern byte ali_proc;
 int (*ali_display_info)(char *, char **, off_t, int) = NULL;
 #endif /* CONFIG_BLK_DEV_ALI15X3 */
-#ifdef CONFIG_BLK_DEV_AMD7409
-extern byte amd7409_proc;
-int (*amd7409_display_info)(char *, char **, off_t, int) = NULL;
-#endif /* CONFIG_BLK_DEV_AMD7409 */
+#ifdef CONFIG_BLK_DEV_AMD74XX
+extern byte amd74xx_proc;
+int (*amd74xx_display_info)(char *, char **, off_t, int) = NULL;
+#endif /* CONFIG_BLK_DEV_AMD74XX */
 #ifdef CONFIG_BLK_DEV_CMD64X
 extern byte cmd64x_proc;
 int (*cmd64x_display_info)(char *, char **, off_t, int) = NULL;
@@ -101,10 +101,6 @@ int (*hpt34x_display_info)(char *, char **, off_t, int) = NULL;
 extern byte hpt366_proc;
 int (*hpt366_display_info)(char *, char **, off_t, int) = NULL;
 #endif /* CONFIG_BLK_DEV_HPT366 */
-#ifdef CONFIG_BLK_DEV_OSB4
-extern byte osb4_proc;
-int (*osb4_display_info)(char *, char **, off_t, int) = NULL;
-#endif /* CONFIG_BLK_DEV_OSB4 */
 #ifdef CONFIG_BLK_DEV_PDC202XX
 extern byte pdc202xx_proc;
 int (*pdc202xx_display_info)(char *, char **, off_t, int) = NULL;
@@ -113,6 +109,10 @@ int (*pdc202xx_display_info)(char *, char **, off_t, int) = NULL;
 extern byte piix_proc;
 int (*piix_display_info)(char *, char **, off_t, int) = NULL;
 #endif /* CONFIG_BLK_DEV_PIIX */
+#ifdef CONFIG_BLK_DEV_SVWKS
+extern byte svwks_proc;
+int (*svwks_display_info)(char *, char **, off_t, int) = NULL;
+#endif /* CONFIG_BLK_DEV_SVWKS */
 #ifdef CONFIG_BLK_DEV_SIS5513
 extern byte sis_proc;
 int (*sis_display_info)(char *, char **, off_t, int) = NULL;
@@ -817,10 +817,10 @@ void proc_ide_create(void)
        if ((ali_display_info) && (ali_proc))
                create_proc_info_entry("ali", 0, proc_ide_root, ali_display_info);
 #endif /* CONFIG_BLK_DEV_ALI15X3 */
-#ifdef CONFIG_BLK_DEV_AMD7409
-       if ((amd7409_display_info) && (amd7409_proc))
-               create_proc_info_entry("amd7409", 0, proc_ide_root, amd7409_display_info);
-#endif /* CONFIG_BLK_DEV_AMD7409 */
+#ifdef CONFIG_BLK_DEV_AMD74XX
+       if ((amd74xx_display_info) && (amd74xx_proc))
+               create_proc_info_entry("amd74xx", 0, proc_ide_root, amd74xx_display_info);
+#endif /* CONFIG_BLK_DEV_AMD74XX */
 #ifdef CONFIG_BLK_DEV_CMD64X
        if ((cmd64x_display_info) && (cmd64x_proc))
                create_proc_info_entry("cmd64x", 0, proc_ide_root, cmd64x_display_info);
@@ -837,10 +837,10 @@ void proc_ide_create(void)
        if ((hpt366_display_info) && (hpt366_proc))
                create_proc_info_entry("hpt366", 0, proc_ide_root, hpt366_display_info);
 #endif /* CONFIG_BLK_DEV_HPT366 */
-#ifdef CONFIG_BLK_DEV_OSB4
-       if ((osb4_display_info) && (osb4_proc))
-               create_proc_info_entry("osb4", 0, proc_ide_root, osb4_display_info);
-#endif /* CONFIG_BLK_DEV_OSB4 */
+#ifdef CONFIG_BLK_DEV_SVWKS
+       if ((svwks_display_info) && (svwks_proc))
+               create_proc_info_entry("svwks", 0, proc_ide_root, svwks_display_info);
+#endif /* CONFIG_BLK_DEV_SVWKS */
 #ifdef CONFIG_BLK_DEV_PDC202XX
        if ((pdc202xx_display_info) && (pdc202xx_proc))
                create_proc_info_entry("pdc202xx", 0, proc_ide_root, pdc202xx_display_info);
@@ -877,10 +877,10 @@ void proc_ide_destroy(void)
        if ((ali_display_info) && (ali_proc))
                remove_proc_entry("ide/ali",0);
 #endif /* CONFIG_BLK_DEV_ALI15X3 */
-#ifdef CONFIG_BLK_DEV_AMD7409
-       if ((amd7409_display_info) && (amd7409_proc))
-               remove_proc_entry("ide/amd7409",0);
-#endif /* CONFIG_BLK_DEV_AMD7409 */
+#ifdef CONFIG_BLK_DEV_AMD74XX
+       if ((amd74xx_display_info) && (amd74xx_proc))
+               remove_proc_entry("ide/amd74xx",0);
+#endif /* CONFIG_BLK_DEV_AMD74XX */
 #ifdef CONFIG_BLK_DEV_CMD64X
        if ((cmd64x_display_info) && (cmd64x_proc))
                remove_proc_entry("ide/cmd64x",0);
@@ -897,10 +897,6 @@ void proc_ide_destroy(void)
        if ((hpt366_display_info) && (hpt366_proc))
                remove_proc_entry("ide/hpt366",0);
 #endif /* CONFIG_BLK_DEV_HPT366 */
-#ifdef CONFIG_BLK_DEV_OSB4
-       if ((osb4_display_info) && (osb4_proc))
-               remove_proc_entry("ide/osb4",0);
-#endif /* CONFIG_BLK_DEV_OSB4 */
 #ifdef CONFIG_BLK_DEV_PDC202XX
        if ((pdc202xx_display_info) && (pdc202xx_proc))
                remove_proc_entry("ide/pdc202xx",0);
@@ -909,6 +905,10 @@ void proc_ide_destroy(void)
        if ((piix_display_info) && (piix_proc))
                remove_proc_entry("ide/piix",0);
 #endif /* CONFIG_BLK_DEV_PIIX */
+#ifdef CONFIG_BLK_DEV_SVWKS
+       if ((svwks_display_info) && (svwks_proc))
+               remove_proc_entry("ide/svwks",0);
+#endif /* CONFIG_BLK_DEV_SVWKS */
 #ifdef CONFIG_BLK_DEV_SIS5513
        if ((sis_display_info) && (sis_proc))
                remove_proc_entry("ide/sis", 0);
index fd96d80aad19cbd564656a627f6a4c9a68516347..d31630b24bc6b902dce0fffb04dd1c22231d28ac 100644 (file)
@@ -4099,9 +4099,14 @@ static int idetape_add_chrdev_read_request (ide_drive_t *drive,int blocks)
        }
        if (rq_ptr->errors == IDETAPE_ERROR_EOD)
                return 0;
-       else if (rq_ptr->errors == IDETAPE_ERROR_FILEMARK)
+       if (rq_ptr->errors == IDETAPE_ERROR_FILEMARK) {
+               idetape_switch_buffers (tape, tape->first_stage);
                set_bit (IDETAPE_FILEMARK, &tape->flags);
-       else {
+#if USE_IOTRACE
+               IO_trace(IO_IDETAPE_FIFO, tape->pipeline_head, tape->buffer_head, tape->tape_head, tape->minor);
+#endif
+               calculate_speeds(drive);
+       } else {
                idetape_switch_buffers (tape, tape->first_stage);
                if (rq_ptr->errors == IDETAPE_ERROR_GENERAL) {
 #if ONSTREAM_DEBUG
@@ -6127,24 +6132,33 @@ static ide_proc_entry_t idetape_proc[] = {
 
 #endif
 
+static int idetape_reinit (ide_drive_t *drive)
+{
+       return 0;
+}
+
 /*
  *     IDE subdriver functions, registered with ide.c
  */
 static ide_driver_t idetape_driver = {
-       name:           "ide-tape",
-       version:        IDETAPE_VERSION,
-       media:          ide_tape,
-       busy:           1,
-       supports_dma:   1,
-       supports_dsc_overlap: 1,
-       cleanup:        idetape_cleanup,
-       do_request:     idetape_do_request,
-       end_request:    idetape_end_request,
-       ioctl:          idetape_blkdev_ioctl,
-       open:           idetape_blkdev_open,
-       release:        idetape_blkdev_release,
-       pre_reset:      idetape_pre_reset,
-       proc:           idetape_proc,
+       name:                   "ide-tape",
+       version:                IDETAPE_VERSION,
+       media:                  ide_tape,
+       busy:                   1,
+       supports_dma:           1,
+       supports_dsc_overlap:   1,
+       cleanup:                idetape_cleanup,
+       do_request:             idetape_do_request,
+       end_request:            idetape_end_request,
+       ioctl:                  idetape_blkdev_ioctl,
+       open:                   idetape_blkdev_open,
+       release:                idetape_blkdev_release,
+       media_change:           NULL,
+       revalidate:             NULL,
+       pre_reset:              idetape_pre_reset,
+       capacity:               NULL,
+       proc:                   idetape_proc,
+       driver_reinit:          idetape_reinit,
 };
 
 int idetape_init (void);
@@ -6167,6 +6181,21 @@ static struct file_operations idetape_fops = {
        release:        idetape_chrdev_release,
 };
 
+MODULE_DESCRIPTION("ATAPI Streaming TAPE Driver");
+
+static void __exit idetape_exit (void)
+{
+       ide_drive_t *drive;
+       int minor;
+
+       for (minor = 0; minor < MAX_HWIFS * MAX_DRIVES; minor++) {
+               drive = idetape_chrdevs[minor].drive;
+               if (drive != NULL && idetape_cleanup (drive))
+               printk (KERN_ERR "ide-tape: %s: cleanup_module() called while still busy\n", drive->name);
+       }
+       ide_unregister_module(&idetape_module);
+}
+
 /*
  *     idetape_init will register the driver for each tape.
  */
@@ -6252,22 +6281,5 @@ int idetape_init (void)
        return 0;
 }
 
-#ifdef MODULE
-int init_module (void)
-{
-       return idetape_init ();
-}
-
-void cleanup_module (void)
-{
-       ide_drive_t *drive;
-       int minor;
-
-       for (minor = 0; minor < MAX_HWIFS * MAX_DRIVES; minor++) {
-               drive = idetape_chrdevs[minor].drive;
-               if (drive != NULL && idetape_cleanup (drive))
-                       printk (KERN_ERR "ide-tape: %s: cleanup_module() called while still busy\n", drive->name);
-       }
-       ide_unregister_module(&idetape_module);
-}
-#endif /* MODULE */
+module_init(idetape_init);
+module_exit(idetape_exit);
index 04eed0d7b4a789bc04721e3826dd466982ef87c3..aaf5fd51d804d9213851f82e62265106d40dafce 100644 (file)
 #include <linux/kmod.h>
 #endif /* CONFIG_KMOD */
 
+/* default maximum number of failures */
+#define IDE_DEFAULT_MAX_FAILURES       1
+
 static const byte ide_hwif_to_major[] = { IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR, IDE4_MAJOR, IDE5_MAJOR, IDE6_MAJOR, IDE7_MAJOR, IDE8_MAJOR, IDE9_MAJOR };
 
 static int     idebus_parameter; /* holds the "idebus=" parameter */
@@ -249,6 +252,7 @@ static void init_hwif_data (unsigned int index)
        hwif->name[1]   = 'd';
        hwif->name[2]   = 'e';
        hwif->name[3]   = '0' + index;
+       hwif->bus_state = BUSSTATE_ON;
        for (unit = 0; unit < MAX_DRIVES; ++unit) {
                ide_drive_t *drive = &hwif->drives[unit];
 
@@ -263,6 +267,7 @@ static void init_hwif_data (unsigned int index)
                drive->name[0]                  = 'h';
                drive->name[1]                  = 'd';
                drive->name[2]                  = 'a' + (index * MAX_DRIVES) + unit;
+               drive->max_failures             = IDE_DEFAULT_MAX_FAILURES;
                init_waitqueue_head(&drive->wqueue);
        }
 }
@@ -377,7 +382,19 @@ static inline void do_vlb_sync (ide_ioreg_t port) {
  */
 void ide_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount)
 {
-       byte io_32bit = drive->io_32bit;
+       byte io_32bit;
+
+       /* first check if this controller has defined a special function
+        * for handling polled ide transfers
+        */
+
+       if(HWIF(drive)->ideproc) {
+               HWIF(drive)->ideproc(ideproc_ide_input_data,
+                                    drive, buffer, wcount);
+               return;
+       }
+
+       io_32bit = drive->io_32bit;
 
        if (io_32bit) {
 #if SUPPORT_VLB_SYNC
@@ -410,7 +427,15 @@ void ide_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount)
  */
 void ide_output_data (ide_drive_t *drive, void *buffer, unsigned int wcount)
 {
-       byte io_32bit = drive->io_32bit;
+       byte io_32bit;
+
+       if(HWIF(drive)->ideproc) {
+               HWIF(drive)->ideproc(ideproc_ide_output_data,
+                                    drive, buffer, wcount);
+               return;
+       }
+
+       io_32bit = drive->io_32bit;
 
        if (io_32bit) {
 #if SUPPORT_VLB_SYNC
@@ -447,6 +472,12 @@ void ide_output_data (ide_drive_t *drive, void *buffer, unsigned int wcount)
  */
 void atapi_input_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount)
 {
+       if(HWIF(drive)->ideproc) {
+               HWIF(drive)->ideproc(ideproc_atapi_input_bytes,
+                                    drive, buffer, bytecount);
+               return;
+       }
+
        ++bytecount;
 #if defined(CONFIG_ATARI) || defined(CONFIG_Q40)
        if (MACH_IS_ATARI || MACH_IS_Q40) {
@@ -462,6 +493,12 @@ void atapi_input_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount
 
 void atapi_output_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount)
 {
+       if(HWIF(drive)->ideproc) {
+               HWIF(drive)->ideproc(ideproc_atapi_output_bytes,
+                                    drive, buffer, bytecount);
+               return;
+       }
+
        ++bytecount;
 #if defined(CONFIG_ATARI) || defined(CONFIG_Q40)
        if (MACH_IS_ATARI || MACH_IS_Q40) {
@@ -512,10 +549,20 @@ void ide_end_request (byte uptodate, ide_hwgroup_t *hwgroup)
 {
        struct request *rq;
        unsigned long flags;
+       ide_drive_t *drive = hwgroup->drive;
 
        spin_lock_irqsave(&io_request_lock, flags);
        rq = hwgroup->rq;
 
+       /*
+        * decide whether to reenable DMA -- 3 is a random magic for now,
+        * if we DMA timeout more than 3 times, just stay in PIO
+        */
+       if (drive->state == DMA_PIO_RETRY && drive->retry_pio <= 3) {
+               drive->state = 0;
+               hwgroup->hwif->dmaproc(ide_dma_on, drive);
+       }
+
        if (!end_that_request_first(rq, uptodate, hwgroup->drive->name)) {
                add_blkdev_randomness(MAJOR(rq->rq_dev));
                blkdev_dequeue_request(rq);
@@ -637,11 +684,14 @@ static ide_startstop_t reset_pollfunc (ide_drive_t *drive)
                        return ide_started;     /* continue polling */
                }
                printk("%s: reset timed-out, status=0x%02x\n", hwif->name, tmp);
+               drive->failures++;
        } else  {
                printk("%s: reset: ", hwif->name);
-               if ((tmp = GET_ERR()) == 1)
+               if ((tmp = GET_ERR()) == 1) {
                        printk("success\n");
-               else {
+                       drive->failures = 0;
+               } else {
+                       drive->failures++;
 #if FANCY_STATUS_DUMPS
                        printk("master: ");
                        switch (tmp & 0x7f) {
@@ -1049,6 +1099,12 @@ int ide_wait_stat (ide_startstop_t *startstop, ide_drive_t *drive, byte good, by
        int i;
        unsigned long flags;
  
+       /* bail early if we've exceeded max_failures */
+       if (drive->max_failures && (drive->failures > drive->max_failures)) {
+               *startstop = ide_stopped;
+               return 1;
+       }
+
        udelay(1);      /* spec allows drive 400ns to assert "BUSY" */
        if ((stat = GET_STAT()) & BUSY_STAT) {
                __save_flags(flags);    /* local CPU only */
@@ -1145,6 +1201,11 @@ static ide_startstop_t start_request (ide_drive_t *drive)
 #ifdef DEBUG
        printk("%s: start_request: current=0x%08lx\n", hwif->name, (unsigned long) rq);
 #endif
+       /* bail early if we've exceeded max_failures */
+       if (drive->max_failures && (drive->failures > drive->max_failures)) {
+               goto kill_rq;
+       }
+
        if (unit >= MAX_DRIVES) {
                printk("%s: bad device number: %s\n", hwif->name, kdevname(rq->rq_dev));
                goto kill_rq;
@@ -1200,6 +1261,19 @@ kill_rq:
        return ide_stopped;
 }
 
+ide_startstop_t restart_request (ide_drive_t *drive)
+{
+       ide_hwgroup_t *hwgroup = HWGROUP(drive);
+       unsigned long flags;
+
+       spin_lock_irqsave(&io_request_lock, flags);
+       hwgroup->handler = NULL;
+       del_timer(&hwgroup->timer);
+       spin_unlock_irqrestore(&io_request_lock, flags);
+
+       return start_request(drive);
+}
+
 /*
  * ide_stall_queue() can be used by a drive to give excess bandwidth back
  * to the hwgroup by sleeping for timeout jiffies.
@@ -1387,6 +1461,49 @@ void do_ide_request(request_queue_t *q)
        ide_do_request(q->queuedata, 0);
 }
 
+/*
+ * un-busy the hwgroup etc, and clear any pending DMA status. we want to
+ * retry the current request in pio mode instead of risking tossing it
+ * all away
+ */
+void ide_dma_timeout_retry(ide_drive_t *drive)
+{
+       ide_hwif_t *hwif = HWIF(drive);
+       struct request *rq;
+
+       /*
+        * end current dma transaction
+        */
+       (void) hwif->dmaproc(ide_dma_end, drive);
+
+       /*
+        * complain a little, later we might remove some of this verbosity
+        */
+       printk("%s: timeout waiting for DMA\n", drive->name);
+       (void) hwif->dmaproc(ide_dma_timeout, drive);
+
+       /*
+        * disable dma for now, but remember that we did so because of
+        * a timeout -- we'll reenable after we finish this next request
+        * (or rather the first chunk of it) in pio.
+        */
+       drive->retry_pio++;
+       drive->state = DMA_PIO_RETRY;
+       (void) hwif->dmaproc(ide_dma_off_quietly, drive);
+
+       /*
+        * un-busy drive etc (hwgroup->busy is cleared on return) and
+        * make sure request is sane
+        */
+       rq = HWGROUP(drive)->rq;
+       HWGROUP(drive)->rq = NULL;
+
+       rq->errors = 0;
+       rq->sector = rq->bh->b_rsector;
+       rq->current_nr_sectors = rq->bh->b_size >> 9;
+       rq->buffer = rq->bh->b_data;
+}
+
 /*
  * ide_timer_expiry() is our timeout function for all drive operations.
  * But note that it can also be invoked as a result of a "sleep" operation
@@ -1460,11 +1577,10 @@ void ide_timer_expiry (unsigned long data)
                                startstop = handler(drive);
                        } else {
                                if (drive->waiting_for_dma) {
-                                       (void) hwgroup->hwif->dmaproc(ide_dma_end, drive);
-                                       printk("%s: timeout waiting for DMA\n", drive->name);
-                                       (void) hwgroup->hwif->dmaproc(ide_dma_timeout, drive);
-                               }
-                               startstop = ide_error(drive, "irq timeout", GET_STAT());
+                                       startstop = ide_stopped;
+                                       ide_dma_timeout_retry(drive);
+                               } else
+                                       startstop = ide_error(drive, "irq timeout", GET_STAT());
                        }
                        set_recovery_timer(hwif);
                        drive->service_time = jiffies - drive->service_start;
@@ -2089,7 +2205,10 @@ void ide_unregister (unsigned int index)
        hwif->maskproc          = old_hwif.maskproc;
        hwif->quirkproc         = old_hwif.quirkproc;
        hwif->rwproc            = old_hwif.rwproc;
+       hwif->ideproc           = old_hwif.ideproc;
        hwif->dmaproc           = old_hwif.dmaproc;
+       hwif->busproc           = old_hwif.busproc;
+       hwif->bus_state         = old_hwif.bus_state;
        hwif->dma_base          = old_hwif.dma_base;
        hwif->dma_extra         = old_hwif.dma_extra;
        hwif->config_data       = old_hwif.config_data;
@@ -2671,6 +2790,20 @@ static int ide_ioctl (struct inode *inode, struct file *file,
                case BLKELVSET:
                        return blk_ioctl(inode->i_rdev, cmd, arg);
 
+               case HDIO_GET_BUSSTATE:
+                       if (!capable(CAP_SYS_ADMIN))
+                               return -EACCES;
+                       if (put_user(HWIF(drive)->bus_state, (long *)arg))
+                               return -EFAULT;
+                       return 0;
+
+               case HDIO_SET_BUSSTATE:
+                       if (!capable(CAP_SYS_ADMIN))
+                               return -EACCES;
+                       if (HWIF(drive)->busproc)
+                               HWIF(drive)->busproc(HWIF(drive), arg);
+                       return 0;
+
                default:
                        if (drive->driver != NULL)
                                return DRIVER(drive)->ioctl(drive, inode, file, cmd, arg);
@@ -3196,6 +3329,12 @@ static void __init probe_for_hwifs (void)
        }
 #endif /* CONFIG_PCI */
 
+#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);
@@ -3373,6 +3512,13 @@ static ide_startstop_t default_special (ide_drive_t *drive)
        return ide_stopped;
 }
 
+static int default_driver_reinit (ide_drive_t *drive)
+{
+       printk(KERN_ERR "%s: does not support hotswap of device class !\n", drive->name);
+
+       return 0;
+}
+
 static void setup_driver_defaults (ide_drive_t *drive)
 {
        ide_driver_t *d = drive->driver;
@@ -3387,6 +3533,7 @@ static void setup_driver_defaults (ide_drive_t *drive)
        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->driver_reinit == NULL)   d->driver_reinit = default_driver_reinit;
 }
 
 ide_drive_t *ide_scan_devices (byte media, const char *name, ide_driver_t *driver, int n)
@@ -3536,6 +3683,7 @@ EXPORT_SYMBOL(ide_error);
 EXPORT_SYMBOL(ide_fixstring);
 EXPORT_SYMBOL(ide_wait_stat);
 EXPORT_SYMBOL(ide_do_reset);
+EXPORT_SYMBOL(restart_request);
 EXPORT_SYMBOL(ide_init_drive_cmd);
 EXPORT_SYMBOL(ide_do_drive_cmd);
 EXPORT_SYMBOL(ide_end_drive_cmd);
diff --git a/drivers/ide/it8172.c b/drivers/ide/it8172.c
new file mode 100644 (file)
index 0000000..937d3e6
--- /dev/null
@@ -0,0 +1,283 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ *      IT8172 IDE controller support
+ *
+ * Copyright 2000 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *              stevel@mvista.com or support@mvista.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <linux/hdreg.h>
+#include <linux/ide.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/it8172/it8172_int.h>
+
+#include "ide_modes.h"
+
+/*
+ * Prototypes
+ */
+static void it8172_tune_drive (ide_drive_t *drive, byte pio);
+#if defined(CONFIG_BLK_DEV_IDEDMA) && defined(CONFIG_IT8172_TUNING)
+static byte it8172_dma_2_pio (byte xfer_rate);
+static int it8172_tune_chipset (ide_drive_t *drive, byte speed);
+static int it8172_config_drive_for_dma (ide_drive_t *drive);
+static int it8172_dmaproc(ide_dma_action_t func, ide_drive_t *drive);
+#endif
+unsigned int __init pci_init_it8172 (struct pci_dev *dev, const char *name);
+void __init ide_init_it8172 (ide_hwif_t *hwif);
+
+
+/*
+ *  Based on settings done by AMI BIOS
+ *  (might be usefull if drive is not registered in CMOS for any reason).
+ */
+static void it8172_tune_drive (ide_drive_t *drive, byte pio)
+{
+    unsigned long flags;
+    u16 master_data;
+    byte slave_data;
+    int is_slave       = (&HWIF(drive)->drives[1] == drive);
+    int master_port    = HWIF(drive)->index ? 0x42 : 0x40;
+    int slave_port     = 0x44;
+    /* ISP  RTC */
+    byte timings[][2]  = { { 0, 0 },
+                           { 0, 0 },
+                           { 1, 0 },
+                           { 2, 1 },
+                           { 2, 3 }, };
+
+    pio = ide_get_best_pio_mode(drive, pio, 5, NULL);
+    pci_read_config_word(HWIF(drive)->pci_dev, master_port, &master_data);
+    if (is_slave) {
+       master_data = master_data | 0x4000;
+       if (pio > 1)
+           /* enable PPE, IE and TIME */
+           master_data = master_data | 0x0070;
+       pci_read_config_byte(HWIF(drive)->pci_dev, slave_port, &slave_data);
+       slave_data = slave_data & (HWIF(drive)->index ? 0x0f : 0xf0);
+       slave_data = slave_data |
+           ((timings[pio][0] << 2) | (timings[pio][1]
+                                      << (HWIF(drive)->index ? 4 : 0)));
+    } else {
+       master_data = master_data & 0xccf8;
+       if (pio > 1)
+           /* enable PPE, IE and TIME */
+           master_data = master_data | 0x0007;
+       master_data = master_data | (timings[pio][0] << 12) |
+           (timings[pio][1] << 8);
+    }
+    save_flags(flags);
+    cli();
+    pci_write_config_word(HWIF(drive)->pci_dev, master_port, master_data);
+    if (is_slave)
+       pci_write_config_byte(HWIF(drive)->pci_dev, slave_port, slave_data);
+    restore_flags(flags);
+}
+
+#if defined(CONFIG_BLK_DEV_IDEDMA) && defined(CONFIG_IT8172_TUNING)
+/*
+ *
+ */
+static byte it8172_dma_2_pio (byte xfer_rate)
+{
+    switch(xfer_rate) {
+    case XFER_UDMA_5:
+    case XFER_UDMA_4:
+    case XFER_UDMA_3:
+    case XFER_UDMA_2:
+    case XFER_UDMA_1:
+    case XFER_UDMA_0:
+    case XFER_MW_DMA_2:
+    case XFER_PIO_4:
+       return 4;
+    case XFER_MW_DMA_1:
+    case XFER_PIO_3:
+       return 3;
+    case XFER_SW_DMA_2:
+    case XFER_PIO_2:
+       return 2;
+    case XFER_MW_DMA_0:
+    case XFER_SW_DMA_1:
+    case XFER_SW_DMA_0:
+    case XFER_PIO_1:
+    case XFER_PIO_0:
+    case XFER_PIO_SLOW:
+    default:
+       return 0;
+    }
+}
+
+static int it8172_tune_chipset (ide_drive_t *drive, byte speed)
+{
+    ide_hwif_t *hwif   = HWIF(drive);
+    struct pci_dev *dev        = hwif->pci_dev;
+    int a_speed                = 3 << (drive->dn * 4);
+    int u_flag         = 1 << drive->dn;
+    int u_speed                = 0;
+    int err            = 0;
+    byte reg48, reg4a;
+
+    pci_read_config_byte(dev, 0x48, &reg48);
+    pci_read_config_byte(dev, 0x4a, &reg4a);
+
+    switch(speed) {
+    case XFER_UDMA_4:
+    case XFER_UDMA_2:  u_speed = 2 << (drive->dn * 4); break;
+    case XFER_UDMA_5:
+    case XFER_UDMA_3:
+    case XFER_UDMA_1:  u_speed = 1 << (drive->dn * 4); break;
+    case XFER_UDMA_0:  u_speed = 0 << (drive->dn * 4); break;
+    case XFER_MW_DMA_2:
+    case XFER_MW_DMA_1:
+    case XFER_SW_DMA_2:        break;
+    default:           return -1;
+    }
+
+    if (speed >= XFER_UDMA_0) {
+       if (!(reg48 & u_flag))
+           pci_write_config_byte(dev, 0x48, reg48|u_flag);
+       if (!(reg4a & u_speed)) {
+           pci_write_config_byte(dev, 0x4a, reg4a & ~a_speed);
+           pci_write_config_byte(dev, 0x4a, reg4a|u_speed);
+       }
+    }
+    if (speed < XFER_UDMA_0) {
+       if (reg48 & u_flag)
+           pci_write_config_byte(dev, 0x48, reg48 & ~u_flag);
+       if (reg4a & a_speed)
+           pci_write_config_byte(dev, 0x4a, reg4a & ~a_speed);
+    }
+
+    it8172_tune_drive(drive, it8172_dma_2_pio(speed));
+
+#if IT8172_DEBUG
+    printk("%s: %s drive%d\n", drive->name, ide_xfer_verbose(speed), drive->dn);
+#endif
+    if (!drive->init_speed)
+       drive->init_speed = speed;
+    err = ide_config_drive_speed(drive, speed);
+    drive->current_speed = speed;
+    return err;
+}
+
+static int it8172_config_drive_for_dma (ide_drive_t *drive)
+{
+    struct hd_driveid *id = drive->id;
+    byte speed;
+
+    if (id->dma_ultra & 0x0010) {
+       speed = XFER_UDMA_2;
+    } else if (id->dma_ultra & 0x0008) {
+       speed = XFER_UDMA_1;
+    } else if (id->dma_ultra & 0x0004) {
+       speed = XFER_UDMA_2;
+    } else if (id->dma_ultra & 0x0002) {
+       speed = XFER_UDMA_1;
+    } else if (id->dma_ultra & 0x0001) {
+       speed = XFER_UDMA_0;
+    } else if (id->dma_mword & 0x0004) {
+       speed = XFER_MW_DMA_2;
+    } else if (id->dma_mword & 0x0002) {
+       speed = XFER_MW_DMA_1;
+    } else if (id->dma_1word & 0x0004) {
+       speed = XFER_SW_DMA_2;
+    } else {
+       speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, 5, NULL);
+    }
+
+    (void) it8172_tune_chipset(drive, speed);
+
+    return ((int)((id->dma_ultra >> 11) & 7) ? ide_dma_on :
+           ((id->dma_ultra >> 8) & 7) ? ide_dma_on :
+           ((id->dma_mword >> 8) & 7) ? ide_dma_on :
+           ((id->dma_1word >> 8) & 7) ? ide_dma_on :
+           ide_dma_off_quietly);
+}
+
+static int it8172_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
+{
+    switch (func) {
+    case ide_dma_check:
+       return ide_dmaproc((ide_dma_action_t)it8172_config_drive_for_dma(drive),
+                          drive);
+    default :
+       break;
+    }
+    /* Other cases are done by generic IDE-DMA code. */
+    return ide_dmaproc(func, drive);
+}
+#endif /* defined(CONFIG_BLK_DEV_IDEDMA) && (CONFIG_IT8172_TUNING) */
+
+unsigned int __init pci_init_it8172 (struct pci_dev *dev, const char *name)
+{
+    unsigned char progif;
+    
+    /*
+     * Place both IDE interfaces into PCI "native" mode
+     */
+    (void)pci_read_config_byte(dev, PCI_CLASS_PROG, &progif);
+    (void)pci_write_config_byte(dev, PCI_CLASS_PROG, progif | 0x05);    
+
+    return IT8172_IDE_IRQ;
+}
+
+
+void __init ide_init_it8172 (ide_hwif_t *hwif)
+{
+    struct pci_dev* dev = hwif->pci_dev;
+    unsigned long cmdBase, ctrlBase;
+    
+    hwif->tuneproc = &it8172_tune_drive;
+    hwif->drives[0].autotune = 1;
+    hwif->drives[1].autotune = 1;
+
+    if (!hwif->dma_base)
+       return;
+
+#ifndef CONFIG_BLK_DEV_IDEDMA
+    hwif->autodma = 0;
+#else /* CONFIG_BLK_DEV_IDEDMA */
+#ifdef CONFIG_IT8172_TUNING
+    hwif->autodma = 1;
+    hwif->dmaproc = &it8172_dmaproc;
+    hwif->speedproc = &it8172_tune_chipset;
+#endif /* CONFIG_IT8172_TUNING */
+#endif /* !CONFIG_BLK_DEV_IDEDMA */
+
+    cmdBase = dev->resource[0].start;
+    ctrlBase = dev->resource[1].start;
+    
+    ide_init_hwif_ports(&hwif->hw, cmdBase, ctrlBase | 2, NULL);
+    memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports));
+    hwif->noprobe = 0;
+}
diff --git a/drivers/ide/osb4.c b/drivers/ide/osb4.c
deleted file mode 100644 (file)
index 5f52fa4..0000000
+++ /dev/null
@@ -1,459 +0,0 @@
-/*
- * linux/drivers/block/osb4.c          Version 0.2     17 Oct 2000
- *
- *  Copyright (C) 2000 Cobalt Networks, Inc. <asun@cobalt.com>
- *  May be copied or modified under the terms of the GNU General Public License
- *
- *  interface borrowed from alim15x3.c:
- *  Copyright (C) 1998-2000 Michel Aubry, Maintainer
- *  Copyright (C) 1998-2000 Andrzej Krzysztofowicz, Maintainer
- *
- *  Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org>
- *
- *  IDE support for the ServerWorks OSB4 IDE chipset
- *
- * here's the default lspci:
- *
- * 00:0f.1 IDE interface: ServerWorks: Unknown device 0211 (prog-if 8a [Master SecP PriP])
- *     Control: I/O+ Mem- BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR+ FastB2B-
- *     Status: Cap- 66Mhz- UDF- FastB2B- ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR-
- *     Latency: 255
- *     Region 4: I/O ports at c200
- * 00: 66 11 11 02 05 01 00 02 00 8a 01 01 00 ff 80 00
- * 10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- * 20: 01 c2 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- * 30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- * 40: 99 99 99 99 ff ff ff ff 0c 0c 00 00 00 00 00 00
- * 50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- * 60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- * 70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- * 80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- * 90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- * a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- * b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- * c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- * d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- * e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- * f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- *
- */
-
-#include <linux/config.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/ioport.h>
-#include <linux/pci.h>
-#include <linux/hdreg.h>
-#include <linux/ide.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-
-#include <asm/io.h>
-
-#include "ide_modes.h"
-
-#define OSB4_DEBUG_DRIVE_INFO          0
-
-#define DISPLAY_OSB4_TIMINGS
-
-#if defined(DISPLAY_OSB4_TIMINGS) && defined(CONFIG_PROC_FS)
-#include <linux/stat.h>
-#include <linux/proc_fs.h>
-
-static struct pci_dev *bmide_dev;
-
-static int osb4_get_info(char *, char **, off_t, int);
-extern int (*osb4_display_info)(char *, char **, off_t, int); /* ide-proc.c */
-extern char *ide_media_verbose(ide_drive_t *);
-
-static int osb4_get_info (char *buffer, char **addr, off_t offset, int count)
-{
-       char *p = buffer;
-       u32 bibma = pci_resource_start(bmide_dev, 4);
-       u16 reg56;
-       u8  c0 = 0, c1 = 0, reg54;
-
-       pci_read_config_byte(bmide_dev, 0x54, &reg54);
-       pci_read_config_word(bmide_dev, 0x56, &reg56);
-
-        /*
-         * at that point bibma+0x2 et bibma+0xa are byte registers
-         * to investigate:
-         */
-       c0 = inb_p((unsigned short)bibma + 0x02);
-       c1 = inb_p((unsigned short)bibma + 0x0a);
-
-       p += sprintf(p, "\n                                ServerWorks OSB4 Chipset.\n");
-       p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n");
-       p += sprintf(p, "                %sabled                         %sabled\n",
-                       (c0&0x80) ? "dis" : " en",
-                       (c1&0x80) ? "dis" : " en");
-       p += sprintf(p, "--------------- drive0 --------- drive1 -------- drive0 ---------- drive1 ------\n");
-       p += sprintf(p, "DMA enabled:    %s              %s             %s               %s\n",
-                       (c0&0x20) ? "yes" : "no ",
-                       (c0&0x40) ? "yes" : "no ",
-                       (c1&0x20) ? "yes" : "no ",
-                       (c1&0x40) ? "yes" : "no " );
-       p += sprintf(p, "UDMA enabled:   %s              %s             %s               %s\n",
-                       (reg54 & 0x01) ? "yes" : "no ",
-                       (reg54 & 0x02) ? "yes" : "no ",
-                       (reg54 & 0x04) ? "yes" : "no ",
-                       (reg54 & 0x08) ? "yes" : "no " );
-       p += sprintf(p, "UDMA enabled:   %s                %s               %s                 %s\n",
-                    (reg56 & 0x0002) ? "2" : ((reg56 & 0x0001) ? "1" : 
-                                              ((reg56 & 0x000f) ? "X" : "0")),
-                    (reg56 & 0x0020) ? "2" : ((reg56 & 0x0010) ? "1" : 
-                                              ((reg56 & 0x00f0) ? "X" : "0")),
-                    (reg56 & 0x0200) ? "2" : ((reg56 & 0x0100) ? "1" : 
-                                              ((reg56 & 0x0f00) ? "X" : "0")),
-                    (reg56 & 0x2000) ? "2" : ((reg56 & 0x1000) ? "1" : 
-                                              ((reg56 & 0xf000) ? "X" : "0")));
-       return p-buffer;         /* => must be less than 4k! */
-}
-#endif  /* defined(DISPLAY_OSB4_TIMINGS) && defined(CONFIG_PROC_FS) */
-
-static byte osb4_revision = 0;
-
-byte osb4_proc = 0;
-
-extern char *ide_xfer_verbose (byte xfer_rate);
-
-static struct pci_dev *isa_dev;
-
-static int osb4_tune_chipset (ide_drive_t *drive, byte speed)
-{
-       byte udma_modes[]       = { 0x00, 0x01, 0x02 };
-       byte dma_modes[]        = { 0x77, 0x21, 0x20 };
-       byte pio_modes[]        = { 0x5d, 0x47, 0x34, 0x22, 0x20 };
-
-       ide_hwif_t *hwif        = HWIF(drive);
-       struct pci_dev *dev     = hwif->pci_dev;
-       byte unit               = (drive->select.b.unit & 0x01);
-#ifdef CONFIG_BLK_DEV_IDEDMA
-       unsigned long dma_base  = hwif->dma_base;
-#endif /* CONFIG_BLK_DEV_IDEDMA */
-       int err;
-
-       byte drive_pci          = 0x00;
-       byte drive_pci2         = 0x00;
-       byte drive_pci3         = hwif->channel ? 0x57 : 0x56;
-
-       byte ultra_enable       = 0x00;
-       byte ultra_timing       = 0x00;
-       byte dma_timing         = 0x00;
-       byte pio_timing         = 0x00;
-
-       byte pio        = ide_get_best_pio_mode(drive, 255, 5, NULL);
-
-        switch (drive->dn) {
-               case 0: drive_pci = 0x41; drive_pci2 = 0x45; break;
-               case 1: drive_pci = 0x40; drive_pci2 = 0x44; break;
-               case 2: drive_pci = 0x43; drive_pci2 = 0x47; break;
-               case 3: drive_pci = 0x42; drive_pci2 = 0x46; break;
-               default:
-                       return -1;
-       }
-
-       pci_read_config_byte(dev, drive_pci, &pio_timing);
-       pci_read_config_byte(dev, drive_pci2, &dma_timing);
-       pci_read_config_byte(dev, drive_pci3, &ultra_timing);
-       pci_read_config_byte(dev, 0x54, &ultra_enable);
-
-#ifdef DEBUG
-       printk("%s: UDMA 0x%02x DMAPIO 0x%02x PIO 0x%02x ",
-               drive->name, ultra_timing, dma_timing, pio_timing);
-#endif
-
-       pio_timing      &= ~0xFF;
-       dma_timing      &= ~0xFF;
-       ultra_timing    &= ~(0x0F << (4*unit));
-       ultra_enable    &= ~(0x01 << drive->dn);
-
-       switch(speed) {
-               case XFER_PIO_4:
-               case XFER_PIO_3:
-               case XFER_PIO_2:
-               case XFER_PIO_1:
-               case XFER_PIO_0:
-                       pio_timing |= pio_modes[speed - XFER_PIO_0];
-                       break;
-#ifdef CONFIG_BLK_DEV_IDEDMA
-               case XFER_MW_DMA_2:
-               case XFER_MW_DMA_1:
-               case XFER_MW_DMA_0:
-                       pio_timing |= pio_modes[pio];
-                       dma_timing |= dma_modes[speed - XFER_MW_DMA_0];
-                       break;
-
-//             case XFER_UDMA_5:
-//             case XFER_UDMA_4:
-//             case XFER_UDMA_3:
-               case XFER_UDMA_2:
-               case XFER_UDMA_1:
-               case XFER_UDMA_0:
-                       pio_timing |= pio_modes[pio];
-                       dma_timing |= dma_modes[2];
-                       ultra_timing |= ((udma_modes[speed - XFER_UDMA_0]) << (4*unit));
-                       ultra_enable |= (0x01 << drive->dn);
-#endif
-               default:
-                       break;
-       }
-
-#ifdef DEBUG
-       printk("%s: UDMA 0x%02x DMAPIO 0x%02x PIO 0x%02x ",
-               drive->name, ultra_timing, dma_timing, pio_timing);
-#endif
-
-#if OSB4_DEBUG_DRIVE_INFO
-       printk("%s: %s drive%d\n", drive->name, ide_xfer_verbose(speed), drive->dn);
-#endif /* OSB4_DEBUG_DRIVE_INFO */
-
-       if (!drive->init_speed)
-               drive->init_speed = speed;
-
-       pci_write_config_byte(dev, drive_pci, pio_timing);
-#ifdef CONFIG_BLK_DEV_IDEDMA
-       pci_write_config_byte(dev, drive_pci2, dma_timing);
-       pci_write_config_byte(dev, drive_pci3, ultra_timing);
-       pci_write_config_byte(dev, 0x54, ultra_enable);
-       
-       if (speed > XFER_PIO_4) {
-               outb(inb(dma_base+2)|(1<<(5+unit)), dma_base+2);
-       } else {
-               outb(inb(dma_base+2) & ~(1<<(5+unit)), dma_base+2);
-       }
-#endif /* CONFIG_BLK_DEV_IDEDMA */
-
-       err = ide_config_drive_speed(drive, speed);
-       drive->current_speed = speed;
-       return err;
-}
-
-static void config_chipset_for_pio (ide_drive_t *drive)
-{
-       unsigned short eide_pio_timing[6] = {960, 480, 240, 180, 120, 90};
-       unsigned short xfer_pio = drive->id->eide_pio_modes;
-       byte                    timing, speed, pio;
-
-       pio = ide_get_best_pio_mode(drive, 255, 5, NULL);
-
-       if (xfer_pio> 4)
-               xfer_pio = 0;
-
-       if (drive->id->eide_pio_iordy > 0) {
-               for (xfer_pio = 5;
-                       xfer_pio>0 &&
-                       drive->id->eide_pio_iordy>eide_pio_timing[xfer_pio];
-                       xfer_pio--);
-       } else {
-               xfer_pio = (drive->id->eide_pio_modes & 4) ? 0x05 :
-                          (drive->id->eide_pio_modes & 2) ? 0x04 :
-                          (drive->id->eide_pio_modes & 1) ? 0x03 :
-                          (drive->id->tPIO & 2) ? 0x02 :
-                          (drive->id->tPIO & 1) ? 0x01 : xfer_pio;
-       }
-
-       timing = (xfer_pio >= pio) ? xfer_pio : pio;
-
-       switch(timing) {
-               case 4: speed = XFER_PIO_4;break;
-               case 3: speed = XFER_PIO_3;break;
-               case 2: speed = XFER_PIO_2;break;
-               case 1: speed = XFER_PIO_1;break;
-               default:
-                       speed = (!drive->id->tPIO) ? XFER_PIO_0 : XFER_PIO_SLOW;
-                       break;
-       }
-       (void) osb4_tune_chipset(drive, speed);
-       drive->current_speed = speed;
-}
-
-static void osb4_tune_drive (ide_drive_t *drive, byte pio)
-{
-       byte speed;
-       switch(pio) {
-               case 4:         speed = XFER_PIO_4;break;
-               case 3:         speed = XFER_PIO_3;break;
-               case 2:         speed = XFER_PIO_2;break;
-               case 1:         speed = XFER_PIO_1;break;
-               default:        speed = XFER_PIO_0;break;
-       }
-       (void) osb4_tune_chipset(drive, speed);
-}
-
-#ifdef CONFIG_BLK_DEV_IDEDMA
-static int config_chipset_for_dma (ide_drive_t *drive)
-{
-       struct hd_driveid *id   = drive->id;
-       byte                    speed;
-
-#if 0
-       byte udma_66            = eighty_ninty_three(drive);
-       /* need specs to figure out if osb4 is capable of ata/66/100 */
-       int ultra100            = 0;
-       int ultra66             = 0;
-
-       if ((id->dma_ultra & 0x0020) && (udma_66) && (ultra100)) {
-               speed = XFER_UDMA_5;
-       } else if (id->dma_ultra & 0x0010) {
-               speed = ((udma_66) && (ultra66)) ? XFER_UDMA_4 : XFER_UDMA_2;
-       } else if (id->dma_ultra & 0x0008) {
-               speed = ((udma_66) && (ultra66)) ? XFER_UDMA_3 : XFER_UDMA_1;
-       } else if (id->dma_ultra & 0x0004) {
-#else
-       if (id->dma_ultra & 0x0004) {
-#endif
-               speed = XFER_UDMA_2;
-       } else if (id->dma_ultra & 0x0002) {
-               speed = XFER_UDMA_1;
-       } else if (id->dma_ultra & 0x0001) {
-               speed = XFER_UDMA_0;
-       } else if (id->dma_mword & 0x0004) {
-               speed = XFER_MW_DMA_2;
-       } else if (id->dma_mword & 0x0002) {
-               speed = XFER_MW_DMA_1;
-       } else if (id->dma_1word & 0x0004) {
-               speed = XFER_SW_DMA_2;
-       } else {
-               speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, 5, NULL);
-       }
-
-       (void) osb4_tune_chipset(drive, speed);
-
-       return ((int)   ((id->dma_ultra >> 11) & 7) ? ide_dma_on :
-                       ((id->dma_ultra >> 8) & 7) ? ide_dma_on :
-                       ((id->dma_mword >> 8) & 7) ? ide_dma_on :
-                       ((id->dma_1word >> 8) & 7) ? ide_dma_on :
-                                                    ide_dma_off_quietly);
-}
-
-static int config_drive_xfer_rate (ide_drive_t *drive)
-{
-       struct hd_driveid *id = drive->id;
-       ide_dma_action_t dma_func = ide_dma_on;
-
-       if (id && (id->capability & 1) && HWIF(drive)->autodma) {
-               /* Consult the list of known "bad" drives */
-               if (ide_dmaproc(ide_dma_bad_drive, drive)) {
-                       dma_func = ide_dma_off;
-                       goto fast_ata_pio;
-               }
-               dma_func = ide_dma_off_quietly;
-               if (id->field_valid & 4) {
-                       if (id->dma_ultra & 0x002F) {
-                               /* Force if Capable UltraDMA */
-                               dma_func = config_chipset_for_dma(drive);
-                               if ((id->field_valid & 2) &&
-                                   (dma_func != ide_dma_on))
-                                       goto try_dma_modes;
-                       }
-               } else if (id->field_valid & 2) {
-try_dma_modes:
-                       if ((id->dma_mword & 0x0007) ||
-                           (id->dma_1word & 0x007)) {
-                               /* Force if Capable regular DMA modes */
-                               dma_func = config_chipset_for_dma(drive);
-                               if (dma_func != ide_dma_on)
-                                       goto no_dma_set;
-                       }
-               } else if (ide_dmaproc(ide_dma_good_drive, drive)) {
-                       if (id->eide_dma_time > 150) {
-                               goto no_dma_set;
-                       }
-                       /* Consult the list of known "good" drives */
-                       dma_func = config_chipset_for_dma(drive);
-                       if (dma_func != ide_dma_on)
-                               goto no_dma_set;
-               } else {
-                       goto fast_ata_pio;
-               }
-       } else if ((id->capability & 8) || (id->field_valid & 2)) {
-fast_ata_pio:
-               dma_func = ide_dma_off_quietly;
-no_dma_set:
-               config_chipset_for_pio(drive);
-       }
-       return HWIF(drive)->dmaproc(dma_func, drive);
-}
-
-static int osb4_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
-{
-       switch (func) {
-               case ide_dma_check:
-                       return config_drive_xfer_rate(drive);
-               default :
-                       break;
-       }
-       /* Other cases are done by generic IDE-DMA code. */
-       return ide_dmaproc(func, drive);
-}
-#endif /* CONFIG_BLK_DEV_IDEDMA */
-
-unsigned int __init pci_init_osb4 (struct pci_dev *dev, const char *name)
-{
-       unsigned int reg64;
-
-       pci_read_config_byte(dev, PCI_REVISION_ID, &osb4_revision);
-
-       isa_dev = pci_find_device(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4, NULL);
-
-       pci_read_config_dword(isa_dev, 0x64, &reg64);
-#ifdef DEBUG
-       printk("%s: reg64 == 0x%08x\n", name, reg64);
-#endif
-
-//     reg64 &= ~0x0000A000;
-//#ifdef CONFIG_SMP
-//     reg64 |= 0x00008000;
-//#endif
-       /* Assume the APIC was set up properly by the BIOS for now . If it
-          wasnt we need to do a fix up _way_ earlier. Bits 15,10,3 control
-          APIC enable, routing and decode */
-          
-       reg64 &= ~0x00002000;   
-       pci_write_config_dword(isa_dev, 0x64, reg64);
-
-       pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x40);
-
-#if defined(DISPLAY_OSB4_TIMINGS) && defined(CONFIG_PROC_FS)
-       if (!osb4_proc) {
-               osb4_proc = 1;
-               bmide_dev = dev;
-               osb4_display_info = &osb4_get_info;
-       }
-#endif /* DISPLAY_OSB4_TIMINGS && CONFIG_PROC_FS */
-       return 0;
-}
-
-unsigned int __init ata66_osb4 (ide_hwif_t *hwif)
-{
-       return 0;
-}
-
-void __init ide_init_osb4 (ide_hwif_t *hwif)
-{
-       if (!hwif->irq)
-               hwif->irq = hwif->channel ? 15 : 14;
-
-       hwif->tuneproc = &osb4_tune_drive;
-       hwif->speedproc = &osb4_tune_chipset;
-
-#ifndef CONFIG_BLK_DEV_IDEDMA
-       hwif->drives[0].autotune = 1;
-       hwif->drives[1].autotune = 1;
-       hwif->autodma = 0;
-       return;
-#else /* CONFIG_BLK_DEV_IDEDMA */
-
-       if (hwif->dma_base) {
-               if (!noautodma)
-                       hwif->autodma = 1;
-               hwif->dmaproc = &osb4_dmaproc;
-       } else {
-               hwif->autodma = 0;
-               hwif->drives[0].autotune = 1;
-               hwif->drives[1].autotune = 1;
-       }
-#endif /* !CONFIG_BLK_DEV_IDEDMA */
-}
index 99002ae2e335ea3cb4ded9cf52ae9c2bf8b3ce35..f8cba2df9612858b0fa3d02803e21d1d40c66fd2 100644 (file)
@@ -108,7 +108,7 @@ static char * pdc202xx_info (char *buf, struct pci_dev *dev)
        u32 bibma  = pci_resource_start(dev, 4);
        u32 reg60h = 0, reg64h = 0, reg68h = 0, reg6ch = 0;
        u16 reg50h = 0, pmask = (1<<10), smask = (1<<11);
-       u8 hi = 0, lo = 0;
+       u8 hi = 0, lo = 0, invalid_data_set = 0;
 
         /*
          * at that point bibma+0x2 et bibma+0xa are byte registers
@@ -132,6 +132,10 @@ static char * pdc202xx_info (char *buf, struct pci_dev *dev)
        pci_read_config_dword(dev, 0x6c, &reg6ch);
 
        switch(dev->device) {
+               case PCI_DEVICE_ID_PROMISE_20268:
+                       p += sprintf(p, "\n                                PDC20268 TX2 Chipset.\n");
+                       invalid_data_set = 1;
+                       break;
                case PCI_DEVICE_ID_PROMISE_20267:
                        p += sprintf(p, "\n                                PDC20267 Chipset.\n");
                        break;
@@ -175,31 +179,38 @@ static char * pdc202xx_info (char *buf, struct pci_dev *dev)
        p += sprintf(p, "           Mode %s                      Mode %s\n",
                (sc1a & 0x01) ? "MASTER" : "PCI   ",
                (sc1b & 0x01) ? "MASTER" : "PCI   ");
-       p += sprintf(p, "                %s                     %s\n",
-               (sc1d & 0x08) ? "Error       " :
-               ((sc1d & 0x05) == 0x05) ? "Not My INTR " :
-               (sc1d & 0x04) ? "Interrupting" :
-               (sc1d & 0x02) ? "FIFO Full   " :
-               (sc1d & 0x01) ? "FIFO Empty  " : "????????????",
-               (sc1d & 0x80) ? "Error       " :
-               ((sc1d & 0x50) == 0x50) ? "Not My INTR " :
-               (sc1d & 0x40) ? "Interrupting" :
-               (sc1d & 0x20) ? "FIFO Full   " :
-               (sc1d & 0x10) ? "FIFO Empty  " : "????????????");
+       if (!(invalid_data_set))
+               p += sprintf(p, "                %s                     %s\n",
+                       (sc1d & 0x08) ? "Error       " :
+                       ((sc1d & 0x05) == 0x05) ? "Not My INTR " :
+                       (sc1d & 0x04) ? "Interrupting" :
+                       (sc1d & 0x02) ? "FIFO Full   " :
+                       (sc1d & 0x01) ? "FIFO Empty  " : "????????????",
+                       (sc1d & 0x80) ? "Error       " :
+                       ((sc1d & 0x50) == 0x50) ? "Not My INTR " :
+                       (sc1d & 0x40) ? "Interrupting" :
+                       (sc1d & 0x20) ? "FIFO Full   " :
+                       (sc1d & 0x10) ? "FIFO Empty  " : "????????????");
        p += sprintf(p, "--------------- drive0 --------- drive1 -------- drive0 ---------- drive1 ------\n");
        p += sprintf(p, "DMA enabled:    %s              %s             %s               %s\n",
                (c0&0x20)?"yes":"no ",(c0&0x40)?"yes":"no ",(c1&0x20)?"yes":"no ",(c1&0x40)?"yes":"no ");
-       p += sprintf(p, "DMA Mode:       %s           %s          %s            %s\n",
-               pdc202xx_ultra_verbose(reg60h, (reg50h & pmask)),
-               pdc202xx_ultra_verbose(reg64h, (reg50h & pmask)),
-               pdc202xx_ultra_verbose(reg68h, (reg50h & smask)),
-               pdc202xx_ultra_verbose(reg6ch, (reg50h & smask)));
-       p += sprintf(p, "PIO Mode:       %s            %s           %s            %s\n",
-               pdc202xx_pio_verbose(reg60h),pdc202xx_pio_verbose(reg64h),
-               pdc202xx_pio_verbose(reg68h),pdc202xx_pio_verbose(reg6ch));
+       if (!(invalid_data_set))
+               p += sprintf(p, "DMA Mode:       %s           %s          %s            %s\n",
+                       pdc202xx_ultra_verbose(reg60h, (reg50h & pmask)),
+                       pdc202xx_ultra_verbose(reg64h, (reg50h & pmask)),
+                       pdc202xx_ultra_verbose(reg68h, (reg50h & smask)),
+                       pdc202xx_ultra_verbose(reg6ch, (reg50h & smask)));
+       if (!(invalid_data_set))
+               p += sprintf(p, "PIO Mode:       %s            %s           %s            %s\n",
+                       pdc202xx_pio_verbose(reg60h),
+                       pdc202xx_pio_verbose(reg64h),
+                       pdc202xx_pio_verbose(reg68h),
+                       pdc202xx_pio_verbose(reg6ch));
 #if 0
        p += sprintf(p, "--------------- Can ATAPI DMA ---------------\n");
 #endif
+       if (invalid_data_set)
+               p += sprintf(p, "--------------- Cannot Decode HOST ---------------\n");
        return (char *)p;
 }
 
@@ -374,6 +385,9 @@ static int pdc202xx_tune_chipset (ide_drive_t *drive, byte speed)
 
        if ((drive->media != ide_disk) && (speed < XFER_SW_DMA_0))      return -1;
 
+       if (dev->device == PCI_DEVICE_ID_PROMISE_20268)
+               goto skip_register_hell;
+
        pci_read_config_dword(dev, drive_pci, &drive_conf);
        pci_read_config_byte(dev, (drive_pci), &AP);
        pci_read_config_byte(dev, (drive_pci)|0x01, &BP);
@@ -461,7 +475,12 @@ static int pdc202xx_tune_chipset (ide_drive_t *drive, byte speed)
        decode_registers(REG_D, DP);
 #endif /* PDC202XX_DECODE_REGISTER_INFO */
 
+skip_register_hell:
+
+       if (!drive->init_speed)
+               drive->init_speed = speed;
        err = ide_config_drive_speed(drive, speed);
+       drive->current_speed = speed;
 
 #if PDC202XX_DEBUG_DRIVE_INFO
        printk("%s: %s drive%d 0x%08x ",
@@ -513,7 +532,7 @@ static int config_chipset_for_dma (ide_drive_t *drive, byte ultra)
        byte CLKSPD             = IN_BYTE(high_16 + 0x11);
        byte udma_33            = ultra ? (inb(high_16 + 0x001f) & 1) : 0;
        byte udma_66            = ((eighty_ninty_three(drive)) && udma_33) ? 1 : 0;
-       byte udma_100           = (((dev->device == PCI_DEVICE_ID_PROMISE_20265) || (dev->device == PCI_DEVICE_ID_PROMISE_20267)) && udma_66) ? 1 : 0;
+       byte udma_100           = (((dev->device == PCI_DEVICE_ID_PROMISE_20265) || (dev->device == PCI_DEVICE_ID_PROMISE_20267) || (dev->device == PCI_DEVICE_ID_PROMISE_20268)) && udma_66) ? 1 : 0;
 
        /*
         * Set the control register to use the 66Mhz system
@@ -536,6 +555,9 @@ static int config_chipset_for_dma (ide_drive_t *drive, byte ultra)
                                   (id->dma_ultra & 0x0010) ||
                                   (id->dma_ultra & 0x0008)) ? 1 : 0;
 
+       if (dev->device == PCI_DEVICE_ID_PROMISE_20268)
+               goto jump_pci_mucking;
+
        pci_read_config_word(dev, 0x50, &EP);
 
        if (((ultra_66) || (ultra_100)) && (EP & c_mask)) {
@@ -616,6 +638,8 @@ chipset_is_set:
        if (drive->media == ide_disk)   /* PREFETCH_EN */
                pci_write_config_byte(dev, (drive_pci), AP|PREFETCH_EN);
 
+jump_pci_mucking:
+
        if ((id->dma_ultra & 0x0020) && (udma_100))     speed = XFER_UDMA_5;
        else if ((id->dma_ultra & 0x0010) && (udma_66)) speed = XFER_UDMA_4;
        else if ((id->dma_ultra & 0x0008) && (udma_66)) speed = XFER_UDMA_3;
@@ -630,7 +654,8 @@ chipset_is_set:
        else if (id->dma_1word & 0x0001)                speed = XFER_SW_DMA_0;
        else {
                /* restore original pci-config space */
-               pci_write_config_dword(dev, drive_pci, drive_conf);
+               if (dev->device != PCI_DEVICE_ID_PROMISE_20268)
+                       pci_write_config_dword(dev, drive_pci, drive_conf);
                return ide_dma_off_quietly;
        }
 
@@ -783,7 +808,10 @@ unsigned int __init pci_init_pdc202xx (struct pci_dev *dev, const char *name)
                byte irq = 0, irq2 = 0;
                pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq);
                pci_read_config_byte(dev, (PCI_INTERRUPT_LINE)|0x80, &irq2);    /* 0xbc */
-               if ((irq != irq2) && (dev->device != PCI_DEVICE_ID_PROMISE_20265) && (dev->device != PCI_DEVICE_ID_PROMISE_20267)) {
+               if ((irq != irq2) &&
+                   (dev->device != PCI_DEVICE_ID_PROMISE_20265) &&
+                   (dev->device != PCI_DEVICE_ID_PROMISE_20267) &&
+                   (dev->device != PCI_DEVICE_ID_PROMISE_20268)) {
                        pci_write_config_byte(dev, (PCI_INTERRUPT_LINE)|0x80, irq);     /* 0xbc */
                        printk("%s: pci-config space interrupt mirror fixed.\n", name);
                }
@@ -852,6 +880,14 @@ void __init ide_init_pdc202xx (ide_hwif_t *hwif)
                hwif->resetproc = &pdc202xx_reset;
        }
 
+#undef CONFIG_PDC202XX_32_UNMASK
+#ifdef CONFIG_PDC202XX_32_UNMASK
+       hwif->drives[0].io_32bit = 1;
+       hwif->drives[1].io_32bit = 1;
+       hwif->drives[0].unmask = 1;
+       hwif->drives[1].unmask = 1;
+#endif /* CONFIG_PDC202XX_32_UNMASK */
+
 #ifdef CONFIG_BLK_DEV_IDEDMA
        if (hwif->dma_base) {
                hwif->dmaproc = &pdc202xx_dmaproc;
index bdc3843db5f56e6c8e189f45fd09b793cf09f7e5..73ecc807713f0e9f93e33eac122463aaab0c0f0c 100644 (file)
@@ -88,6 +88,34 @@ static int piix_get_info (char *buffer, char **addr, off_t offset, int count)
        u8  c0 = 0, c1 = 0;
        u8  reg44 = 0, reg48 = 0, reg4a = 0, reg4b = 0, reg54 = 0, reg55 = 0;
 
+       switch(bmide_dev->device) {
+               case PCI_DEVICE_ID_INTEL_82801BA_8:
+               case PCI_DEVICE_ID_INTEL_82801BA_9:
+                       p += sprintf(p, "\n                                Intel PIIX4 Ultra 100 Chipset.\n");
+                       break;
+               case PCI_DEVICE_ID_INTEL_82372FB_1:
+               case PCI_DEVICE_ID_INTEL_82801AA_1:
+                       p += sprintf(p, "\n                                Intel PIIX4 Ultra 66 Chipset.\n");
+                       break;
+               case PCI_DEVICE_ID_INTEL_82451NX:
+               case PCI_DEVICE_ID_INTEL_82801AB_1:
+               case PCI_DEVICE_ID_INTEL_82443MX_1:
+               case PCI_DEVICE_ID_INTEL_82371AB:
+                       p += sprintf(p, "\n                                Intel PIIX4 Ultra 33 Chipset.\n");
+                       break;
+               case PCI_DEVICE_ID_INTEL_82371SB_1:
+                       p += sprintf(p, "\n                                Intel PIIX3 Chipset.\n");
+                       break;
+               case PCI_DEVICE_ID_INTEL_82371MX:
+                       p += sprintf(p, "\n                                Intel MPIIX Chipset.\n");
+                       return p-buffer;        /* => must be less than 4k! */
+               case PCI_DEVICE_ID_INTEL_82371FB_1:
+               case PCI_DEVICE_ID_INTEL_82371FB_0:
+               default:
+                       p += sprintf(p, "\n                                Intel PIIX Chipset.\n");
+                       break;
+       }
+
        pci_read_config_word(bmide_dev, 0x40, &reg40);
        pci_read_config_word(bmide_dev, 0x42, &reg42);
        pci_read_config_byte(bmide_dev, 0x44, &reg44);
@@ -100,14 +128,13 @@ static int piix_get_info (char *buffer, char **addr, off_t offset, int count)
        psitre = (reg40 & 0x4000) ? 1 : 0;
        ssitre = (reg42 & 0x4000) ? 1 : 0;
 
-        /*
-         * at that point bibma+0x2 et bibma+0xa are byte registers
-         * to investigate:
-         */
+       /*
+        * at that point bibma+0x2 et bibma+0xa are byte registers
+        * to investigate:
+        */
        c0 = inb_p((unsigned short)bibma + 0x02);
        c1 = inb_p((unsigned short)bibma + 0x0a);
 
-       p += sprintf(p, "\n                    %s Chipset.\n", bmide_dev->name);
        p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n");
        p += sprintf(p, "                %sabled                         %sabled\n",
                        (c0&0x80) ? "dis" : " en",
@@ -482,6 +509,11 @@ void __init ide_init_piix (ide_hwif_t *hwif)
                hwif->irq = hwif->channel ? 15 : 14;
 #endif /* CONFIG_IA64 */
 
+       if (hwif->pci_dev->device == PCI_DEVICE_ID_INTEL_82371MX) {
+               /* This is a painful system best to let it self tune for now */
+               return;
+       }
+
        hwif->tuneproc = &piix_tune_drive;
        hwif->drives[0].autotune = 1;
        hwif->drives[1].autotune = 1;
diff --git a/drivers/ide/serverworks.c b/drivers/ide/serverworks.c
new file mode 100644 (file)
index 0000000..c846f78
--- /dev/null
@@ -0,0 +1,577 @@
+/*
+ * linux/drivers/ide/serverworks.c             Version 0.2     17 Oct 2000
+ *
+ *  Copyright (C) 2000 Cobalt Networks, Inc. <asun@cobalt.com>
+ *  May be copied or modified under the terms of the GNU General Public License
+ *
+ *  interface borrowed from alim15x3.c:
+ *  Copyright (C) 1998-2000 Michel Aubry, Maintainer
+ *  Copyright (C) 1998-2000 Andrzej Krzysztofowicz, Maintainer
+ *
+ *  Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org>
+ *
+ *  IDE support for the ServerWorks OSB4 IDE chipset
+ *
+ * here's the default lspci:
+ *
+ * 00:0f.1 IDE interface: ServerWorks: Unknown device 0211 (prog-if 8a [Master SecP PriP])
+ *     Control: I/O+ Mem- BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR+ FastB2B-
+ *     Status: Cap- 66Mhz- UDF- FastB2B- ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR-
+ *     Latency: 255
+ *     Region 4: I/O ports at c200
+ * 00: 66 11 11 02 05 01 00 02 00 8a 01 01 00 ff 80 00
+ * 10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * 20: 01 c2 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * 30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * 40: 99 99 99 99 ff ff ff ff 0c 0c 00 00 00 00 00 00
+ * 50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * 60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * 70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * 80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * 90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ *
+ * 00:0f.1 IDE interface: ServerWorks: Unknown device 0212 (rev 92) (prog-if 8a [Master SecP PriP])
+ *         Subsystem: ServerWorks: Unknown device 0212
+ *         Control: I/O+ Mem- BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B-
+ *         Status: Cap- 66Mhz- UDF- FastB2B- ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR-
+ *         Latency: 64, cache line size 08
+ *         Region 0: I/O ports at 01f0
+ *         Region 1: I/O ports at 03f4
+ *         Region 2: I/O ports at 0170
+ *         Region 3: I/O ports at 0374
+ *         Region 4: I/O ports at 08b0
+ *         Region 5: I/O ports at 1000
+ *
+ * 00:0f.1 IDE interface: ServerWorks: Unknown device 0212 (rev 92)
+ * 00: 66 11 12 02 05 00 00 02 92 8a 01 01 08 40 80 00
+ * 10: f1 01 00 00 f5 03 00 00 71 01 00 00 75 03 00 00
+ * 20: b1 08 00 00 01 10 00 00 00 00 00 00 66 11 12 02
+ * 30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * 40: 4f 4f 4f 4f 20 ff ff ff f0 50 44 44 00 00 00 00
+ * 50: 00 00 00 00 07 00 44 02 0f 04 03 00 00 00 00 00
+ * 60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * 70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * 80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * 90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ *
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <linux/hdreg.h>
+#include <linux/ide.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+
+#include <asm/io.h>
+
+#include "ide_modes.h"
+
+#define SVWKS_DEBUG_DRIVE_INFO         0
+
+#define DISPLAY_SVWKS_TIMINGS
+
+#if defined(DISPLAY_SVWKS_TIMINGS) && defined(CONFIG_PROC_FS)
+#include <linux/stat.h>
+#include <linux/proc_fs.h>
+
+static struct pci_dev *bmide_dev;
+
+static int svwks_get_info(char *, char **, off_t, int);
+extern int (*svwks_display_info)(char *, char **, off_t, int); /* ide-proc.c */
+extern char *ide_media_verbose(ide_drive_t *);
+
+static int svwks_get_info (char *buffer, char **addr, off_t offset, int count)
+{
+       char *p = buffer;
+       u32 bibma = pci_resource_start(bmide_dev, 4);
+       u32 reg40, reg44;
+       u16 reg48, reg56;
+       u8  c0 = 0, c1 = 0, reg54;
+
+       pci_read_config_dword(bmide_dev, 0x40, &reg40);
+       pci_read_config_dword(bmide_dev, 0x44, &reg44);
+       pci_read_config_word(bmide_dev, 0x48, &reg48);
+       pci_read_config_byte(bmide_dev, 0x54, &reg54);
+       pci_read_config_word(bmide_dev, 0x56, &reg56);
+
+        /*
+         * at that point bibma+0x2 et bibma+0xa are byte registers
+         * to investigate:
+         */
+       c0 = inb_p((unsigned short)bibma + 0x02);
+       c1 = inb_p((unsigned short)bibma + 0x0a);
+
+       switch(bmide_dev->device) {
+               case PCI_DEVICE_ID_SERVERWORKS_CSB5IDE:
+                       p += sprintf(p, "\n                                ServerWorks CSB5 Chipset.\n");
+                       break;
+               case PCI_DEVICE_ID_SERVERWORKS_OSB4:
+                       p += sprintf(p, "\n                                ServerWorks OSB4 Chipset.\n");
+                       break;
+               default:
+                       p += sprintf(p, "\n                                ServerWorks 0x%04x Chipset.\n", bmide_dev->device);
+                       break;
+       }
+
+       p += sprintf(p, "------------------------------- General Status ---------------------------------\n");
+#if 0
+       p += sprintf(p, "                                     : %s\n", "str");
+#endif
+       p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n");
+       p += sprintf(p, "                %sabled                         %sabled\n",
+                       (c0&0x80) ? "dis" : " en",
+                       (c1&0x80) ? "dis" : " en");
+       p += sprintf(p, "--------------- drive0 --------- drive1 -------- drive0 ---------- drive1 ------\n");
+       p += sprintf(p, "DMA enabled:    %s              %s             %s               %s\n",
+                       (c0&0x20) ? "yes" : "no ",
+                       (c0&0x40) ? "yes" : "no ",
+                       (c1&0x20) ? "yes" : "no ",
+                       (c1&0x40) ? "yes" : "no " );
+       p += sprintf(p, "UDMA enabled:   %s              %s             %s               %s\n",
+                       (reg54 & 0x01) ? "yes" : "no ",
+                       (reg54 & 0x02) ? "yes" : "no ",
+                       (reg54 & 0x04) ? "yes" : "no ",
+                       (reg54 & 0x08) ? "yes" : "no " );
+       p += sprintf(p, "UDMA enabled:   %s                %s               %s                 %s\n",
+                       ((reg56&0x0005)==0x0005)?"5":
+                               ((reg56&0x0004)==0x0004)?"4":
+                               ((reg56&0x0003)==0x0003)?"3":
+                               ((reg56&0x0002)==0x0002)?"2":
+                               ((reg56&0x0001)==0x0001)?"1":
+                               ((reg56&0x000F))?"?":"0",
+                       ((reg56&0x0050)==0x0050)?"5":
+                               ((reg56&0x0040)==0x0040)?"4":
+                               ((reg56&0x0030)==0x0030)?"3":
+                               ((reg56&0x0020)==0x0020)?"2":
+                               ((reg56&0x0010)==0x0010)?"1":
+                               ((reg56&0x00F0))?"?":"0",
+                       ((reg56&0x0500)==0x0500)?"5":
+                               ((reg56&0x0400)==0x0400)?"4":
+                               ((reg56&0x0300)==0x0300)?"3":
+                               ((reg56&0x0200)==0x0200)?"2":
+                               ((reg56&0x0100)==0x0100)?"1":
+                               ((reg56&0x0F00))?"?":"0",
+                       ((reg56&0x5000)==0x5000)?"5":
+                               ((reg56&0x4000)==0x4000)?"4":
+                               ((reg56&0x3000)==0x3000)?"3":
+                               ((reg56&0x2000)==0x2000)?"2":
+                               ((reg56&0x1000)==0x1000)?"1":
+                               ((reg56&0xF000))?"?":"0");
+       p += sprintf(p, "DMA enabled:    %s                %s               %s                 %s\n",
+                       ((reg44&0x00002000)==0x00002000)?"2":
+                               ((reg44&0x00002100)==0x00002100)?"1":
+                               ((reg44&0x00007700)==0x00007700)?"0":
+                               ((reg44&0x0000FF00)==0x0000FF00)?"X":"?",
+                       ((reg44&0x00000020)==0x00000020)?"2":
+                               ((reg44&0x00000021)==0x00000021)?"1":
+                               ((reg44&0x00000077)==0x00000077)?"0":
+                               ((reg44&0x000000FF)==0x000000FF)?"X":"?",
+                       ((reg44&0x20000000)==0x20000000)?"2":
+                               ((reg44&0x21000000)==0x21000000)?"1":
+                               ((reg44&0x77000000)==0x77000000)?"0":
+                               ((reg44&0xFF000000)==0xFF000000)?"X":"?",
+                       ((reg44&0x00200000)==0x00200000)?"2":
+                               ((reg44&0x00210000)==0x00210000)?"1":
+                               ((reg44&0x00770000)==0x00770000)?"0":
+                               ((reg44&0x00FF0000)==0x00FF0000)?"X":"?");
+#if 0
+       if (bmide_dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE)
+               p += sprintf(p, "PIO  enabled:   %s                %s               %s                 %s\n",
+       if (bmide_dev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4)
+#endif
+               p += sprintf(p, "PIO  enabled:   %s                %s               %s                 %s\n",
+                       ((reg40&0x00002000)==0x00002000)?"4":
+                               ((reg40&0x00002200)==0x00002200)?"3":
+                               ((reg40&0x00003400)==0x00003400)?"2":
+                               ((reg40&0x00004700)==0x00004700)?"1":
+                               ((reg40&0x00005D00)==0x00005D00)?"0":"?",
+                       ((reg40&0x00000020)==0x00000020)?"4":
+                               ((reg40&0x00000022)==0x00000022)?"3":
+                               ((reg40&0x00000034)==0x00000034)?"2":
+                               ((reg40&0x00000047)==0x00000047)?"1":
+                               ((reg40&0x0000005D)==0x0000005D)?"0":"?",
+                       ((reg40&0x20000000)==0x20000000)?"4":
+                               ((reg40&0x22000000)==0x22000000)?"3":
+                               ((reg40&0x34000000)==0x34000000)?"2":
+                               ((reg40&0x47000000)==0x47000000)?"1":
+                               ((reg40&0x5D000000)==0x5D000000)?"0":"?",
+                       ((reg40&0x00200000)==0x00200000)?"4":
+                               ((reg40&0x00220000)==0x00220000)?"3":
+                               ((reg40&0x00340000)==0x00340000)?"2":
+                               ((reg40&0x00470000)==0x00470000)?"1":
+                               ((reg40&0x005D0000)==0x005D0000)?"0":"?");
+       return p-buffer;         /* => must be less than 4k! */
+}
+#endif  /* defined(DISPLAY_SVWKS_TIMINGS) && defined(CONFIG_PROC_FS) */
+
+static byte svwks_revision = 0;
+
+byte svwks_proc = 0;
+
+extern char *ide_xfer_verbose (byte xfer_rate);
+
+static struct pci_dev *isa_dev;
+
+static int svwks_tune_chipset (ide_drive_t *drive, byte speed)
+{
+       byte udma_modes[]       = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 };
+       byte dma_modes[]        = { 0x77, 0x21, 0x20 };
+       byte pio_modes[]        = { 0x5d, 0x47, 0x34, 0x22, 0x20 };
+
+       ide_hwif_t *hwif        = HWIF(drive);
+       struct pci_dev *dev     = hwif->pci_dev;
+       byte unit               = (drive->select.b.unit & 0x01);
+       byte csb5               = (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE) ? 1 : 0;
+
+#ifdef CONFIG_BLK_DEV_IDEDMA
+       unsigned long dma_base  = hwif->dma_base;
+#endif /* CONFIG_BLK_DEV_IDEDMA */
+       int err;
+
+       byte drive_pci          = 0x00;
+       byte drive_pci2         = 0x00;
+       byte drive_pci3         = hwif->channel ? 0x57 : 0x56;
+
+       byte ultra_enable       = 0x00;
+       byte ultra_timing       = 0x00;
+       byte dma_timing         = 0x00;
+       byte pio_timing         = 0x00;
+       unsigned short csb5_pio = 0x00;
+
+       byte pio        = ide_get_best_pio_mode(drive, 255, 5, NULL);
+
+        switch (drive->dn) {
+               case 0: drive_pci = 0x41; drive_pci2 = 0x45; break;
+               case 1: drive_pci = 0x40; drive_pci2 = 0x44; break;
+               case 2: drive_pci = 0x43; drive_pci2 = 0x47; break;
+               case 3: drive_pci = 0x42; drive_pci2 = 0x46; break;
+               default:
+                       return -1;
+       }
+
+       pci_read_config_byte(dev, drive_pci, &pio_timing);
+       pci_read_config_byte(dev, drive_pci2, &dma_timing);
+       pci_read_config_byte(dev, drive_pci3, &ultra_timing);
+       pci_read_config_word(dev, 0x4A, &csb5_pio);
+       pci_read_config_byte(dev, 0x54, &ultra_enable);
+
+#ifdef DEBUG
+       printk("%s: UDMA 0x%02x DMAPIO 0x%02x PIO 0x%02x ",
+               drive->name, ultra_timing, dma_timing, pio_timing);
+#endif
+
+       pio_timing      &= ~0xFF;
+       dma_timing      &= ~0xFF;
+       ultra_timing    &= ~(0x0F << (4*unit));
+       ultra_enable    &= ~(0x01 << drive->dn);
+       csb5_pio        &= ~(0x0F << (4*drive->dn));
+
+       switch(speed) {
+               case XFER_PIO_4:
+               case XFER_PIO_3:
+               case XFER_PIO_2:
+               case XFER_PIO_1:
+               case XFER_PIO_0:
+                       pio_timing |= pio_modes[speed - XFER_PIO_0];
+                       csb5_pio   |= ((speed - XFER_PIO_0) << (4*drive->dn));
+                       break;
+#ifdef CONFIG_BLK_DEV_IDEDMA
+               case XFER_MW_DMA_2:
+               case XFER_MW_DMA_1:
+               case XFER_MW_DMA_0:
+                       pio_timing |= pio_modes[pio];
+                       csb5_pio   |= (pio << (4*drive->dn));
+                       dma_timing |= dma_modes[speed - XFER_MW_DMA_0];
+                       break;
+
+               case XFER_UDMA_5:
+               case XFER_UDMA_4:
+               case XFER_UDMA_3:
+               case XFER_UDMA_2:
+               case XFER_UDMA_1:
+               case XFER_UDMA_0:
+                       pio_timing |= pio_modes[pio];
+                       csb5_pio   |= (pio << (4*drive->dn));
+                       dma_timing |= dma_modes[2];
+                       ultra_timing |= ((udma_modes[speed - XFER_UDMA_0]) << (4*unit));
+                       ultra_enable |= (0x01 << drive->dn);
+#endif
+               default:
+                       break;
+       }
+
+#ifdef DEBUG
+       printk("%s: UDMA 0x%02x DMAPIO 0x%02x PIO 0x%02x ",
+               drive->name, ultra_timing, dma_timing, pio_timing);
+#endif
+
+#if OSB4_DEBUG_DRIVE_INFO
+       printk("%s: %s drive%d\n", drive->name, ide_xfer_verbose(speed), drive->dn);
+#endif /* OSB4_DEBUG_DRIVE_INFO */
+
+       if (!drive->init_speed)
+               drive->init_speed = speed;
+
+       pci_write_config_byte(dev, drive_pci, pio_timing);
+       if (csb5)
+               pci_write_config_word(dev, 0x4A, csb5_pio);
+
+#ifdef CONFIG_BLK_DEV_IDEDMA
+       pci_write_config_byte(dev, drive_pci2, dma_timing);
+       pci_write_config_byte(dev, drive_pci3, ultra_timing);
+       pci_write_config_byte(dev, 0x54, ultra_enable);
+       
+       if (speed > XFER_PIO_4) {
+               outb(inb(dma_base+2)|(1<<(5+unit)), dma_base+2);
+       } else {
+               outb(inb(dma_base+2) & ~(1<<(5+unit)), dma_base+2);
+       }
+#endif /* CONFIG_BLK_DEV_IDEDMA */
+
+       err = ide_config_drive_speed(drive, speed);
+       drive->current_speed = speed;
+       return err;
+}
+
+static void config_chipset_for_pio (ide_drive_t *drive)
+{
+       unsigned short eide_pio_timing[6] = {960, 480, 240, 180, 120, 90};
+       unsigned short xfer_pio = drive->id->eide_pio_modes;
+       byte                    timing, speed, pio;
+
+       pio = ide_get_best_pio_mode(drive, 255, 5, NULL);
+
+       if (xfer_pio> 4)
+               xfer_pio = 0;
+
+       if (drive->id->eide_pio_iordy > 0) {
+               for (xfer_pio = 5;
+                       xfer_pio>0 &&
+                       drive->id->eide_pio_iordy>eide_pio_timing[xfer_pio];
+                       xfer_pio--);
+       } else {
+               xfer_pio = (drive->id->eide_pio_modes & 4) ? 0x05 :
+                          (drive->id->eide_pio_modes & 2) ? 0x04 :
+                          (drive->id->eide_pio_modes & 1) ? 0x03 :
+                          (drive->id->tPIO & 2) ? 0x02 :
+                          (drive->id->tPIO & 1) ? 0x01 : xfer_pio;
+       }
+
+       timing = (xfer_pio >= pio) ? xfer_pio : pio;
+
+       switch(timing) {
+               case 4: speed = XFER_PIO_4;break;
+               case 3: speed = XFER_PIO_3;break;
+               case 2: speed = XFER_PIO_2;break;
+               case 1: speed = XFER_PIO_1;break;
+               default:
+                       speed = (!drive->id->tPIO) ? XFER_PIO_0 : XFER_PIO_SLOW;
+                       break;
+       }
+       (void) svwks_tune_chipset(drive, speed);
+       drive->current_speed = speed;
+}
+
+static void svwks_tune_drive (ide_drive_t *drive, byte pio)
+{
+       byte speed;
+       switch(pio) {
+               case 4:         speed = XFER_PIO_4;break;
+               case 3:         speed = XFER_PIO_3;break;
+               case 2:         speed = XFER_PIO_2;break;
+               case 1:         speed = XFER_PIO_1;break;
+               default:        speed = XFER_PIO_0;break;
+       }
+       (void) svwks_tune_chipset(drive, speed);
+}
+
+#ifdef CONFIG_BLK_DEV_IDEDMA
+static int config_chipset_for_dma (ide_drive_t *drive)
+{
+       struct hd_driveid *id   = drive->id;
+       struct pci_dev *dev     = HWIF(drive)->pci_dev;
+       byte udma_66            = eighty_ninty_three(drive);
+       byte                    speed;
+
+       int ultra66             = (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE) ? 1 : 0;
+       /* need specs to figure out if osb4 is capable of ata/66/100 */
+       int ultra100            = (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE) ? 1 : 0;
+
+       if ((id->dma_ultra & 0x0020) && (udma_66) && (ultra100)) {
+               speed = XFER_UDMA_5;
+       } else if (id->dma_ultra & 0x0010) {
+               speed = ((udma_66) && (ultra66)) ? XFER_UDMA_4 : XFER_UDMA_2;
+       } else if (id->dma_ultra & 0x0008) {
+               speed = ((udma_66) && (ultra66)) ? XFER_UDMA_3 : XFER_UDMA_1;
+       } else if (id->dma_ultra & 0x0004) {
+               speed = XFER_UDMA_2;
+       } else if (id->dma_ultra & 0x0002) {
+               speed = XFER_UDMA_1;
+       } else if (id->dma_ultra & 0x0001) {
+               speed = XFER_UDMA_0;
+       } else if (id->dma_mword & 0x0004) {
+               speed = XFER_MW_DMA_2;
+       } else if (id->dma_mword & 0x0002) {
+               speed = XFER_MW_DMA_1;
+       } else if (id->dma_1word & 0x0004) {
+               speed = XFER_SW_DMA_2;
+       } else {
+               speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, 5, NULL);
+       }
+
+       (void) svwks_tune_chipset(drive, speed);
+
+       return ((int)   ((id->dma_ultra >> 11) & 7) ? ide_dma_on :
+                       ((id->dma_ultra >> 8) & 7) ? ide_dma_on :
+                       ((id->dma_mword >> 8) & 7) ? ide_dma_on :
+                       ((id->dma_1word >> 8) & 7) ? ide_dma_on :
+                                                    ide_dma_off_quietly);
+}
+
+static int config_drive_xfer_rate (ide_drive_t *drive)
+{
+       struct hd_driveid *id = drive->id;
+       ide_dma_action_t dma_func = ide_dma_on;
+
+       if (id && (id->capability & 1) && HWIF(drive)->autodma) {
+               /* Consult the list of known "bad" drives */
+               if (ide_dmaproc(ide_dma_bad_drive, drive)) {
+                       dma_func = ide_dma_off;
+                       goto fast_ata_pio;
+               }
+               dma_func = ide_dma_off_quietly;
+               if (id->field_valid & 4) {
+                       if (id->dma_ultra & 0x002F) {
+                               /* Force if Capable UltraDMA */
+                               dma_func = config_chipset_for_dma(drive);
+                               if ((id->field_valid & 2) &&
+                                   (dma_func != ide_dma_on))
+                                       goto try_dma_modes;
+                       }
+               } else if (id->field_valid & 2) {
+try_dma_modes:
+                       if ((id->dma_mword & 0x0007) ||
+                           (id->dma_1word & 0x007)) {
+                               /* Force if Capable regular DMA modes */
+                               dma_func = config_chipset_for_dma(drive);
+                               if (dma_func != ide_dma_on)
+                                       goto no_dma_set;
+                       }
+               } else if (ide_dmaproc(ide_dma_good_drive, drive)) {
+                       if (id->eide_dma_time > 150) {
+                               goto no_dma_set;
+                       }
+                       /* Consult the list of known "good" drives */
+                       dma_func = config_chipset_for_dma(drive);
+                       if (dma_func != ide_dma_on)
+                               goto no_dma_set;
+               } else {
+                       goto fast_ata_pio;
+               }
+       } else if ((id->capability & 8) || (id->field_valid & 2)) {
+fast_ata_pio:
+               dma_func = ide_dma_off_quietly;
+no_dma_set:
+               config_chipset_for_pio(drive);
+       }
+       return HWIF(drive)->dmaproc(dma_func, drive);
+}
+
+static int svwks_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
+{
+       switch (func) {
+               case ide_dma_check:
+                       return config_drive_xfer_rate(drive);
+               default :
+                       break;
+       }
+       /* Other cases are done by generic IDE-DMA code. */
+       return ide_dmaproc(func, drive);
+}
+#endif /* CONFIG_BLK_DEV_IDEDMA */
+
+unsigned int __init pci_init_svwks (struct pci_dev *dev, const char *name)
+{
+       unsigned int reg64;
+
+       pci_read_config_byte(dev, PCI_REVISION_ID, &svwks_revision);
+
+       if (dev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) {
+               isa_dev = pci_find_device(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4, NULL);
+
+               pci_read_config_dword(isa_dev, 0x64, &reg64);
+#ifdef DEBUG
+               printk("%s: reg64 == 0x%08x\n", name, reg64);
+#endif
+
+//             reg64 &= ~0x0000A000;
+//#ifdef CONFIG_SMP
+//             reg64 |= 0x00008000;
+//#endif
+       /* Assume the APIC was set up properly by the BIOS for now . If it
+          wasnt we need to do a fix up _way_ earlier. Bits 15,10,3 control
+          APIC enable, routing and decode */
+          
+               reg64 &= ~0x00002000;   
+               pci_write_config_dword(isa_dev, 0x64, reg64);
+       }
+       pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x40);
+
+#if defined(DISPLAY_SVWKS_TIMINGS) && defined(CONFIG_PROC_FS)
+       if (!svwks_proc) {
+               svwks_proc = 1;
+               bmide_dev = dev;
+               svwks_display_info = &svwks_get_info;
+       }
+#endif /* DISPLAY_SVWKS_TIMINGS && CONFIG_PROC_FS */
+       return 0;
+}
+
+unsigned int __init ata66_svwks (ide_hwif_t *hwif)
+{
+       return 0;
+}
+
+void __init ide_init_svwks (ide_hwif_t *hwif)
+{
+       if (!hwif->irq)
+               hwif->irq = hwif->channel ? 15 : 14;
+
+       hwif->tuneproc = &svwks_tune_drive;
+       hwif->speedproc = &svwks_tune_chipset;
+
+#ifndef CONFIG_BLK_DEV_IDEDMA
+       hwif->drives[0].autotune = 1;
+       hwif->drives[1].autotune = 1;
+       hwif->autodma = 0;
+       return;
+#else /* CONFIG_BLK_DEV_IDEDMA */
+
+       if (hwif->dma_base) {
+               if (!noautodma)
+                       hwif->autodma = 1;
+               hwif->dmaproc = &svwks_dmaproc;
+       } else {
+               hwif->autodma = 0;
+               hwif->drives[0].autotune = 1;
+               hwif->drives[1].autotune = 1;
+       }
+#endif /* !CONFIG_BLK_DEV_IDEDMA */
+}
index 567a123b428d10292ffcba1854c6b868e54bc487..8872b4c8a93c4962ba3129e00d9209f0d159f988 100644 (file)
@@ -69,8 +69,8 @@ if [ "$CONFIG_ISDN_DRV_HISAX" != "n" ]; then
    bool '  Gazel cards' CONFIG_HISAX_GAZEL
    bool '  HFC PCI-Bus cards' CONFIG_HISAX_HFC_PCI
    bool '  Winbond W6692 based cards' CONFIG_HISAX_W6692
+   bool '  HFC-S+, HFC-SP, HFC-PCMCIA cards' CONFIG_HISAX_HFC_SX
    if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then
-      bool '  HFC-S+, HFC-SP, HFC-PCMCIA cards' CONFIG_HISAX_HFC_SX
 #      bool '  TESTEMULATOR (EXPERIMENTAL)' CONFIG_HISAX_TESTEMU
       if [ "$ARCH" = "sparc" -o "$ARCH" = "sparc64" ]; then
         bool '  Am7930' CONFIG_HISAX_AMD7930
index 216269dcae72055f3b77df69d4d4849d528b10e2..c39f9d5df6260d8713eb2b46de62bffe82bca3a4 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: act2000_isa.c,v 1.11 2000/11/12 16:32:06 kai Exp $
+/* $Id: act2000_isa.c,v 1.11.6.2 2001/07/18 16:25:12 kai Exp $
  *
  * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000 (ISA-Version).
  *
 #include "act2000_isa.h"
 #include "capi.h"
 
-static act2000_card *irq2card_map[16] =
-{
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-static int act2000_isa_irqs[] =
-{
-        3, 5, 7, 10, 11, 12, 15
-};
-#define ISA_NRIRQS (sizeof(act2000_isa_irqs)/sizeof(int))
+static act2000_card *irq2card_map[16];
 
 static void
 act2000_isa_delay(long t)
@@ -82,13 +73,9 @@ int
 act2000_isa_detect(unsigned short portbase)
 {
         int ret = 0;
-        unsigned long flags;
 
-        save_flags(flags);
-        cli();
         if (!check_region(portbase, ISA_REGION))
                 ret = act2000_isa_reset(portbase);
-        restore_flags(flags);
         return ret;
 }
 
@@ -167,9 +154,6 @@ act2000_isa_enable_irq(act2000_card * card)
 int
 act2000_isa_config_irq(act2000_card * card, short irq)
 {
-        int i;
-        unsigned long flags;
-
         if (card->flags & ACT2000_FLAGS_IVALID) {
                 free_irq(card->irq, NULL);
                 irq2card_map[card->irq] = NULL;
@@ -178,30 +162,13 @@ act2000_isa_config_irq(act2000_card * card, short irq)
         outb(ISA_COR_IRQOFF, ISA_PORT_COR);
         if (!irq)
                 return 0;
-        save_flags(flags);
-        cli();
-        if (irq == -1) {
-                /* Auto select */
-                for (i = 0; i < ISA_NRIRQS; i++) {
-                        if (!request_irq(act2000_isa_irqs[i], &act2000_isa_interrupt, 0, card->regname, NULL)) {
-                                card->irq = act2000_isa_irqs[i];
-                                irq2card_map[card->irq] = card;
-                                card->flags |= ACT2000_FLAGS_IVALID;
-                                break;
-                        }
-                }
-        } else {
-                /* Fixed irq */
-                if (!request_irq(irq, &act2000_isa_interrupt, 0, card->regname, NULL)) {
-                        card->irq = irq;
-                        irq2card_map[card->irq] = card;
-                       card->flags |= ACT2000_FLAGS_IVALID;
-                }
-        }
-        restore_flags(flags);
-        if (!card->flags & ACT2000_FLAGS_IVALID) {
+
+       if (!request_irq(irq, &act2000_isa_interrupt, 0, card->regname, NULL)) {
+               card->irq = irq;
+               irq2card_map[card->irq] = card;
+               card->flags |= ACT2000_FLAGS_IVALID;
                 printk(KERN_WARNING
-                       "act2000: Could not request irq\n");
+                       "act2000: Could not request irq %d\n",irq);
                 return -EBUSY;
         } else {
                act2000_isa_select_irq(card);
index 44e3db27a7df302e25738599e8e30120d35b2a0d..9508f961bd06fae82e9444eceb6fa900ec25e66d 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: module.c,v 1.14.6.2 2000/12/18 22:14:10 kai Exp $
+/* $Id: module.c,v 1.14.6.3 2001/07/13 09:20:11 kai Exp $
  *
  * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000.
  *
@@ -38,7 +38,7 @@ static act2000_card *cards = (act2000_card *) NULL;
 /* Parameters to be set by insmod */
 static int   act_bus  =  0;
 static int   act_port = -1;  /* -1 = Autoprobe  */
-static int   act_irq  = -1;  /* -1 = Autoselect */
+static int   act_irq  = -1;
 static char *act_id   = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
 
 MODULE_DESCRIPTION(       "Driver for IBM Active 2000 ISDN card");
@@ -46,7 +46,7 @@ MODULE_AUTHOR(            "Fritz Elfert");
 MODULE_SUPPORTED_DEVICE(  "ISDN subsystem");
 MODULE_PARM_DESC(act_bus, "BusType of first card, 1=ISA, 2=MCA, 3=PCMCIA, currently only ISA");
 MODULE_PARM_DESC(membase, "Base port address of first card");
-MODULE_PARM_DESC(act_irq, "IRQ of first card (-1 = grab next free IRQ)");
+MODULE_PARM_DESC(act_irq, "IRQ of first card");
 MODULE_PARM_DESC(act_id,  "ID-String of first card");
 MODULE_PARM(act_bus,  "i");
 MODULE_PARM(act_port, "i");
index aeb1933134865008181db13816d8035ee796d416..f9d771c0803de0e021176940b4703455af813dc3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: capi.c,v 1.44.6.12 2001/06/09 15:14:15 kai Exp $
+ * $Id: capi.c,v 1.44.6.13 2001/08/13 07:46:15 kai Exp $
  *
  * CAPI 2.0 Interface for Linux
  *
@@ -43,7 +43,7 @@
 #include "capifs.h"
 #endif
 
-static char *revision = "$Revision: 1.44.6.12 $";
+static char *revision = "$Revision: 1.44.6.13 $";
 
 MODULE_AUTHOR("Carsten Paeth (calle@calle.in-berlin.de)");
 
index 39fa00d1b9925d7a6a425a5de7b428f3f6db3b37..fcd1245ecb3794267a9cce7ea2abc938b627f67a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: divert_procfs.c,v 1.11 2000/11/25 17:01:00 kai Exp $
+ * $Id: divert_procfs.c,v 1.11.6.1 2001/08/13 07:46:15 kai Exp $
  *
  * Filesystem handling for the diversion supplementary services.
  *
index 8092da21a0b1a469cc0fc56f8de8b772b62db3b2..58bdc5613f1e85827933458c770775cba187ad7d 100644 (file)
 #include <linux/kernel.h>
 #include <linux/ioport.h>
 
-#define HW_ID_EICON_PCI                        0x1133
-#define HW_ID_DIVA_SERVER_P            0xE014
-#define HW_ID_DIVA_SERVER_B_ST 0xE010
-#define HW_ID_DIVA_SERVER_B_U  0xE013
-#define HW_ID_DIVA_SERVER_Q    0xE012
-
 struct file_operations Divas_fops;
 int Divas_major;
 
@@ -73,8 +67,8 @@ int DivasCardsDiscover(void)
        
        while (wDeviceIndex < 10)
        {
-               wPCIConsultation = pcibios_find_device(HW_ID_EICON_PCI
-                               HW_ID_DIVA_SERVER_Q, 
+               wPCIConsultation = pcibios_find_device(PCI_VENDOR_ID_EICON
+                               PCI_DEVICE_ID_EICON_MAESTRAQ, 
                                wDeviceIndex, 
                                &byBus, &byFunc);
 
@@ -174,8 +168,8 @@ int DivasCardsDiscover(void)
 
        while (wDeviceIndex < 10)
        {
-               wPCIConsultation = pcibios_find_device(HW_ID_EICON_PCI
-                               HW_ID_DIVA_SERVER_B_ST
+               wPCIConsultation = pcibios_find_device(PCI_VENDOR_ID_EICON
+                               PCI_DEVICE_ID_EICON_MAESTRA
                                wDeviceIndex, 
                                &byBus, &byFunc);
 
@@ -232,8 +226,8 @@ int DivasCardsDiscover(void)
                        wNumCards++;
                }
 
-               wPCIConsultation = pcibios_find_device(HW_ID_EICON_PCI
-                               HW_ID_DIVA_SERVER_B_U, 
+               wPCIConsultation = pcibios_find_device(PCI_VENDOR_ID_EICON
+                               PCI_DEVICE_ID_EICON_MAESTRAQ_U, 
                                wDeviceIndex, 
                                &byBus, &byFunc);
 
@@ -298,8 +292,8 @@ int DivasCardsDiscover(void)
 
        while (wDeviceIndex < 10)
        {
-               wPCIConsultation = pcibios_find_device(HW_ID_EICON_PCI
-                               HW_ID_DIVA_SERVER_P, 
+               wPCIConsultation = pcibios_find_device(PCI_VENDOR_ID_EICON
+                               PCI_DEVICE_ID_EICON_MAESTRAP, 
                                wDeviceIndex, 
                                &byBus, &byFunc);
 
index 347ce442ace534fbbd5b04b0672cf63694460357..5be7d160a633ad76f1dfeef9eb068e2289290e81 100644 (file)
@@ -25,8 +25,8 @@
     <maniemann@users.sourceforge.net>. All Rights Reserved.
 
     Alternatively, the contents of this file may be used under the
-    terms of the GNU Public License version 2 (the "GPL"), in which
-    case the provisions of the GPL are applicable instead of the
+    terms of the GNU General Public License version 2 (the "GPL"), in
+    which case the provisions of the GPL are applicable instead of the
     above.  If you wish to allow the use of your version of this file
     only under the terms of the GPL and not to allow others to use
     your version of this file under the MPL, indicate your decision
index 5d6f69d23ec71510e2e5c4d57aa094814a2d4657..eae62dfd24895c2447ccb327fb916d8d2f36323f 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: hysdn_procconf.c,v 1.8.6.2 2001/04/20 02:42:00 keil Exp $
+/* $Id: hysdn_procconf.c,v 1.8.6.3 2001/08/13 07:46:15 kai Exp $
 
  * Linux driver for HYSDN cards, /proc/net filesystem dir and conf functions.
  * written by Werner Cornelius (werner@titro.de) for Hypercope GmbH
@@ -31,7 +31,7 @@
 
 #include "hysdn_defs.h"
 
-static char *hysdn_procconf_revision = "$Revision: 1.8.6.2 $";
+static char *hysdn_procconf_revision = "$Revision: 1.8.6.3 $";
 
 #define INFO_OUT_LEN 80                /* length of info line including lf */
 
index cd8d94b4cb9217eab6a8fe9aa088233cce2645b4..af1c50a9ed4285d941232f17904351c53be456c2 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: hysdn_proclog.c,v 1.9.6.1 2001/05/26 15:19:58 kai Exp $
+/* $Id: hysdn_proclog.c,v 1.9.6.2 2001/08/13 07:46:15 kai Exp $
 
  * Linux driver for HYSDN cards, /proc/net filesystem log functions.
  * written by Werner Cornelius (werner@titro.de) for Hypercope GmbH
index e1a117dbce511003e1697629cc468215bbc022d7..26e154d5660c212e10de8735a47a35824dc1baf2 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: icn.c,v 1.65.6.5 2001/06/09 15:14:19 kai Exp $
+/* $Id: icn.c,v 1.65.6.6 2001/07/13 09:20:12 kai Exp $
 
  * ISDN low-level module for the ICN active ISDN-Card.
  *
@@ -34,7 +34,7 @@
 #undef MAP_DEBUG
 
 static char
-*revision = "$Revision: 1.65.6.5 $";
+*revision = "$Revision: 1.65.6.6 $";
 
 static int icn_addcard(int, char *, char *);
 
@@ -804,8 +804,8 @@ static int
 icn_loadboot(u_char * buffer, icn_card * card)
 {
        int ret;
-       ulong flags;
        u_char *codebuf;
+       unsigned long flags;
 
 #ifdef BOOT_DEBUG
        printk(KERN_DEBUG "icn_loadboot called, buffaddr=%08lx\n", (ulong) buffer);
@@ -818,8 +818,6 @@ icn_loadboot(u_char * buffer, icn_card * card)
                kfree(codebuf);
                return ret;
        }
-       save_flags(flags);
-       cli();
        if (!card->rvalid) {
                if (check_region(card->port, ICN_PORTLEN)) {
                        printk(KERN_WARNING
@@ -827,7 +825,6 @@ icn_loadboot(u_char * buffer, icn_card * card)
                               CID,
                               card->port,
                               card->port + ICN_PORTLEN);
-                       restore_flags(flags);
                        kfree(codebuf);
                        return -EBUSY;
                }
@@ -840,14 +837,12 @@ icn_loadboot(u_char * buffer, icn_card * card)
                if (check_mem_region(dev.memaddr, 0x4000)) {
                        printk(KERN_WARNING
                               "icn: memory at 0x%08lx in use.\n", dev.memaddr);
-                       restore_flags(flags);
                        return -EBUSY;
                }
                request_mem_region(dev.memaddr, 0x4000, "icn-isdn (all cards)");
                dev.shmem = ioremap(dev.memaddr, 0x4000);
                dev.mvalid = 1;
        }
-       restore_flags(flags);
        OUTB_P(0, ICN_RUN);     /* Reset Controller */
        OUTB_P(0, ICN_MAPRAM);  /* Disable RAM      */
        icn_shiftout(ICN_CFG, 0x0f, 3, 4);      /* Windowsize= 16k  */
@@ -1051,18 +1046,19 @@ icn_writecmd(const u_char * buf, int len, int user, icn_card * card)
        ocount = 1;
        xcount = loop = 0;
        while (len) {
-               save_flags(flags);
-               cli();
-               lastmap_card = dev.mcard;
-               lastmap_channel = dev.channel;
-               icn_map_channel(card, mch);
-
                avail = cmd_free;
                count = MIN(avail, len);
                if (user)
                        copy_from_user(msg, buf, count);
                else
                        memcpy(msg, buf, count);
+
+               save_flags(flags);
+               cli();
+               lastmap_card = dev.mcard;
+               lastmap_channel = dev.channel;
+               icn_map_channel(card, mch);
+
                icn_putmsg(card, '>');
                for (p = msg, pp = readb(&cmd_i), i = count; i > 0; i--, p++, pp
                     ++) {
@@ -1140,10 +1136,7 @@ static void
 icn_disable_cards(void)
 {
        icn_card *card = cards;
-       unsigned long flags;
 
-       save_flags(flags);
-       cli();
        while (card) {
                if (check_region(card->port, ICN_PORTLEN)) {
                        printk(KERN_WARNING
@@ -1151,14 +1144,12 @@ icn_disable_cards(void)
                               CID,
                               card->port,
                               card->port + ICN_PORTLEN);
-                       cli();
                } else {
                        OUTB_P(0, ICN_RUN);     /* Reset Controller     */
                        OUTB_P(0, ICN_MAPRAM);  /* Disable RAM          */
                }
                card = card->next;
        }
-       restore_flags(flags);
 }
 
 static int
@@ -1603,25 +1594,19 @@ icn_initcard(int port, char *id)
 static int
 icn_addcard(int port, char *id1, char *id2)
 {
-       ulong flags;
        icn_card *card;
        icn_card *card2;
 
-       save_flags(flags);
-       cli();
        if (!(card = icn_initcard(port, id1))) {
-               restore_flags(flags);
                return -EIO;
        }
        if (!strlen(id2)) {
-               restore_flags(flags);
                printk(KERN_INFO
                       "icn: (%s) ICN-2B, port 0x%x added\n",
                       card->interface.id, port);
                return 0;
        }
        if (!(card2 = icn_initcard(port, id2))) {
-               restore_flags(flags);
                printk(KERN_INFO
                       "icn: (%s) half ICN-4B, port 0x%x added\n",
                       card2->interface.id, port);
@@ -1633,7 +1618,6 @@ icn_addcard(int port, char *id1, char *id2)
        card2->doubleS0 = 1;
        card2->secondhalf = 1;
        card2->other = card;
-       restore_flags(flags);
        printk(KERN_INFO
               "icn: (%s and %s) ICN-4B, port 0x%x added\n",
               card->interface.id, card2->interface.id, port);
index 468aef3a77ed2673a5c0940adb4d71781e16744b..5e90a5446a19432a8874eabf4810a17cb1393775 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: isdn_common.c,v 1.114.6.12 2001/06/09 15:14:15 kai Exp $
+/* $Id: isdn_common.c,v 1.114.6.13 2001/08/13 07:46:15 kai Exp $
 
  * Linux ISDN subsystem, common used functions (linklevel).
  *
@@ -51,7 +51,7 @@
 
 isdn_dev *dev;
 
-static char *isdn_revision = "$Revision: 1.114.6.12 $";
+static char *isdn_revision = "$Revision: 1.114.6.13 $";
 
 extern char *isdn_net_revision;
 extern char *isdn_tty_revision;
index 64e60e3bef7b927addd3e2955c28b9a9f9ba747f..5f0f14a76c02d5c596022abc1f1ae6cc0583b4dd 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: isdnloop.c,v 1.11.6.3 2001/06/09 15:14:19 kai Exp $
+/* $Id: isdnloop.c,v 1.11.6.4 2001/07/13 09:20:12 kai Exp $
 
  * ISDN low-level module implementing a dummy loop driver.
  *
@@ -26,7 +26,7 @@
 #include "isdnloop.h"
 
 static char
-*revision = "$Revision: 1.11.6.3 $";
+*revision = "$Revision: 1.11.6.4 $";
 
 static int isdnloop_addcard(char *);
 
@@ -1518,16 +1518,11 @@ isdnloop_initcard(char *id)
 static int
 isdnloop_addcard(char *id1)
 {
-       ulong flags;
        isdnloop_card *card;
 
-       save_flags(flags);
-       cli();
        if (!(card = isdnloop_initcard(id1))) {
-               restore_flags(flags);
                return -EIO;
        }
-       restore_flags(flags);
        printk(KERN_INFO
               "isdnloop: (%s) virtual card added\n",
               card->interface.id);
index e05cf22528fb5158051d3a080d82c90b88dd09dd..edee6c5e04feced733ed068335c7c00695f1784f 100644 (file)
@@ -1,3 +1,7 @@
+2001-08-11  Tim Waugh  <twaugh@redhat.com>
+
+       * parport_pc.c: Support for Titan Electronics cards.
+
 2001-08-08  Tim Waugh  <twaugh@redhat.com>
 
        * share.c (parport_unregister_device): Remove device from wait list
index eaa824166879c30d5fac8f4cf029b680f9f0553b..e5e9d5aabcafe06e2e5570d69a1f4ef88fc3e812 100644 (file)
@@ -2545,6 +2545,8 @@ enum parport_pc_pci_cards {
        timedia_9018a,
        syba_2p_epp,
        syba_1p_ecp,
+       titan_010l,
+       titan_1284p2,
 };
 
 
@@ -2611,6 +2613,8 @@ static struct parport_pc_pci {
                                            a 1K io window */
        /* syba_2p_epp AP138B */        { 2, { { 0, 0x078 }, { 0, 0x178 }, } },
        /* syba_1p_ecp W83787 */        { 1, { { 0, 0x078 }, } },
+       /* titan_010l */                { 1, { { 3, -1 }, } },
+       /* titan_1284p2 */              { 2, { { 0, 1 }, { 2, 3 }, } },
 };
 
 static struct pci_device_id parport_pc_pci_tbl[] __devinitdata = {
@@ -2696,6 +2700,9 @@ static struct pci_device_id parport_pc_pci_tbl[] __devinitdata = {
          PCI_ANY_ID, PCI_ANY_ID, 0, 0, syba_2p_epp },
        { PCI_VENDOR_ID_SYBA, PCI_DEVICE_ID_SYBA_1P_ECP,
          PCI_ANY_ID, PCI_ANY_ID, 0, 0, syba_1p_ecp },
+       { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_010L,
+         PCI_ANY_ID, PCI_ANY_ID, 0, 0, titan_010l },
+       { 0x9710, 0x9815, 0x1000, 0x0020, 0, 0, titan_1284p2 },
        { 0, } /* terminate list */
 };
 MODULE_DEVICE_TABLE(pci,parport_pc_pci_tbl);
index 18967c9f6d3eee687670bd66f44b0c2737f75a72..a8b1377f51605276651d67cdf1cc6070f7298e4e 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/pm.h>
 #include <linux/kmod.h>                /* for hotplug_path */
 #include <linux/bitops.h>
+#include <linux/delay.h>
 
 #include <asm/page.h>
 #include <asm/dma.h>   /* isa_dma_bridge_buggy */
@@ -942,8 +943,7 @@ void __init pci_read_bridge_bases(struct pci_bus *child)
 {
        struct pci_dev *dev = child->self;
        u8 io_base_lo, io_limit_lo;
-       u16 mem_base_lo, mem_limit_lo, io_base_hi, io_limit_hi;
-       u32 mem_base_hi, mem_limit_hi;
+       u16 mem_base_lo, mem_limit_lo;
        unsigned long base, limit;
        struct resource *res;
        int i;
@@ -957,10 +957,17 @@ void __init pci_read_bridge_bases(struct pci_bus *child)
        res = child->resource[0];
        pci_read_config_byte(dev, PCI_IO_BASE, &io_base_lo);
        pci_read_config_byte(dev, PCI_IO_LIMIT, &io_limit_lo);
-       pci_read_config_word(dev, PCI_IO_BASE_UPPER16, &io_base_hi);
-       pci_read_config_word(dev, PCI_IO_LIMIT_UPPER16, &io_limit_hi);
-       base = ((io_base_lo & PCI_IO_RANGE_MASK) << 8) | (io_base_hi << 16);
-       limit = ((io_limit_lo & PCI_IO_RANGE_MASK) << 8) | (io_limit_hi << 16);
+       base = (io_base_lo & PCI_IO_RANGE_MASK) << 8;
+       limit = (io_limit_lo & PCI_IO_RANGE_MASK) << 8;
+
+       if ((base & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32) {
+               u16 io_base_hi, io_limit_hi;
+               pci_read_config_word(dev, PCI_IO_BASE_UPPER16, &io_base_hi);
+               pci_read_config_word(dev, PCI_IO_LIMIT_UPPER16, &io_limit_hi);
+               base |= (io_base_hi << 16);
+               limit |= (io_limit_hi << 16);
+       }
+
        if (base && base <= limit) {
                res->flags = (io_base_lo & PCI_IO_RANGE_TYPE_MASK) | IORESOURCE_IO;
                res->start = base;
@@ -994,19 +1001,23 @@ void __init pci_read_bridge_bases(struct pci_bus *child)
        res = child->resource[2];
        pci_read_config_word(dev, PCI_PREF_MEMORY_BASE, &mem_base_lo);
        pci_read_config_word(dev, PCI_PREF_MEMORY_LIMIT, &mem_limit_lo);
-       pci_read_config_dword(dev, PCI_PREF_BASE_UPPER32, &mem_base_hi);
-       pci_read_config_dword(dev, PCI_PREF_LIMIT_UPPER32, &mem_limit_hi);
-       base = (mem_base_lo & PCI_MEMORY_RANGE_MASK) << 16;
-       limit = (mem_limit_lo & PCI_MEMORY_RANGE_MASK) << 16;
+       base = (mem_base_lo & PCI_PREF_RANGE_MASK) << 16;
+       limit = (mem_limit_lo & PCI_PREF_RANGE_MASK) << 16;
+
+       if ((mem_base_lo & PCI_PREF_RANGE_TYPE_MASK) == PCI_PREF_RANGE_TYPE_64) {
+               u32 mem_base_hi, mem_limit_hi;
+               pci_read_config_dword(dev, PCI_PREF_BASE_UPPER32, &mem_base_hi);
+               pci_read_config_dword(dev, PCI_PREF_LIMIT_UPPER32, &mem_limit_hi);
 #if BITS_PER_LONG == 64
-       base |= ((long) mem_base_hi) << 32;
-       limit |= ((long) mem_limit_hi) << 32;
+               base |= ((long) mem_base_hi) << 32;
+               limit |= ((long) mem_limit_hi) << 32;
 #else
-       if (mem_base_hi || mem_limit_hi) {
-               printk(KERN_ERR "PCI: Unable to handle 64-bit address space for %s\n", child->name);
-               return;
-       }
+               if (mem_base_hi || mem_limit_hi) {
+                       printk(KERN_ERR "PCI: Unable to handle 64-bit address space for %s\n", child->name);
+                       return;
+               }
 #endif
+       }
        if (base && base <= limit) {
                res->flags = (mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) | IORESOURCE_MEM | IORESOURCE_PREFETCH;
                res->start = base;
index 5cb0ab74414358d58310627a6fa5ab8e5d8dd1c1..c94e8f8a9e7f3217adfbcc23658d97c67f63b618 100644 (file)
@@ -153,6 +153,10 @@ static struct dev_info device_list[] =
        {"DELL", "PSEUDO DEVICE .",   "*", BLIST_SPARSELUN}, // Dell PV 530F
        {"DELL", "PV530F",    "*", BLIST_SPARSELUN}, // Dell PV 530F
        {"EMC", "SYMMETRIX", "*", BLIST_SPARSELUN},
+       {"CMD", "CRA-7280", "*", BLIST_SPARSELUN},   // CMD RAID Controller
+       {"CNSI", "G7324", "*", BLIST_SPARSELUN},     // Chaparral G7324 RAID
+       {"Zzyzx", "RocketStor 500S", "*", BLIST_SPARSELUN},
+       {"Zzyzx", "RocketStor 2000", "*", BLIST_SPARSELUN},
        {"SONY", "TSL",       "*", BLIST_FORCELUN},  // DDS3 & DDS4 autoloaders
        {"DELL", "PERCRAID", "*", BLIST_FORCELUN},
        {"HP", "NetRAID-4M", "*", BLIST_FORCELUN},
@@ -565,20 +569,26 @@ static int scan_scsis_single(unsigned int channel, unsigned int dev,
        }
 
        /*
-        * Check the peripheral qualifier field - this tells us whether LUNS
-        * are supported here or not.
+        * Check for SPARSELUN before checking the peripheral qualifier,
+        * so sparse lun devices are completely scanned.
         */
-       if ((scsi_result[0] >> 5) == 3) {
-               scsi_release_request(SRpnt);
-               return 0;       /* assume no peripheral if any sort of error */
-       }
 
        /*
         * Get any flags for this device.  
         */
        bflags = get_device_flags (scsi_result);
 
-
+       if (bflags & BLIST_SPARSELUN) {
+         *sparse_lun = 1;
+       }
+       /*
+        * Check the peripheral qualifier field - this tells us whether LUNS
+        * are supported here or not.
+        */
+       if ((scsi_result[0] >> 5) == 3) {
+               scsi_release_request(SRpnt);
+               return 0;       /* assume no peripheral if any sort of error */
+       }
         /*   The Toshiba ROM was "gender-changed" here as an inline hack.
              This is now much more generic.
              This is a mess: What we really want is to leave the scsi_result
index 355015e1e27097db473700eadad2df5bf8ec15ad..41265f21614f02700ff29a389dd72003b77d50c3 100644 (file)
@@ -7,7 +7,7 @@
 
 O_TARGET := fs.o
 
-export-objs := filesystems.o dcache.o
+export-objs := filesystems.o open.o dcache.o
 mod-subdirs := nls
 
 obj-y :=       open.o read_write.o devices.o file_table.o buffer.o \
index 50d66f3abc8dcc08b5f37d38dec7ef6e7c219733..55c416e8a63ccb9588196af363bf21dac028e508 100644 (file)
@@ -2399,7 +2399,6 @@ int try_to_free_buffers(struct page * page, unsigned int gfp_mask)
 {
        struct buffer_head * tmp, * bh = page->buffers;
        int index = BUFSIZE_INDEX(bh->b_size);
-       int loop = 0;
 
 cleaned_buffers_try_again:
        spin_lock(&lru_list_lock);
@@ -2449,8 +2448,8 @@ busy_buffer_page:
        if (gfp_mask & __GFP_IO) {
                sync_page_buffers(bh, gfp_mask);
                /* We waited synchronously, so we can free the buffers. */
-               if ((gfp_mask & __GFP_WAIT) && !loop) {
-                       loop = 1;
+               if (gfp_mask & __GFP_WAIT) {
+                       gfp_mask = 0;   /* no IO or waiting this time around */
                        goto cleaned_buffers_try_again;
                }
                wakeup_bdflush();
index f6a14e3ff0c8f2cc6e1705bcf708ca6a49ece3bb..5cbd217092e8097e6326e4dc6f828861792b073c 100644 (file)
@@ -730,14 +730,14 @@ noexec:
 
 int
 nfs3svc_encode_entry(struct readdir_cd *cd, const char *name,
-                    int namlen, off_t offset, ino_t ino, unsigned int d_type)
+                    int namlen, loff_t offset, ino_t ino, unsigned int d_type)
 {
        return encode_entry(cd, name, namlen, offset, ino, d_type, 0);
 }
 
 int
 nfs3svc_encode_entry_plus(struct readdir_cd *cd, const char *name,
-                         int namlen, off_t offset, ino_t ino, unsigned int d_type)
+                         int namlen, loff_t offset, ino_t ino, unsigned int d_type)
 {
        return encode_entry(cd, name, namlen, offset, ino, d_type, 1);
 }
index 60c6647322257d1f3c8b7cdc157188b285387410..25d8ddf63af6e3b7b800414b4082d0112620175f 100644 (file)
@@ -391,7 +391,7 @@ nfssvc_encode_statfsres(struct svc_rqst *rqstp, u32 *p,
 
 int
 nfssvc_encode_entry(struct readdir_cd *cd, const char *name,
-                   int namlen, off_t offset, ino_t ino, unsigned int d_type)
+                   int namlen, loff_t offset, ino_t ino, unsigned int d_type)
 {
        u32     *p = cd->buffer;
        int     buflen, slen;
index f6130555445b33a1944e086731b7c78af164c006..0996b8fb806a29edb24d9ef496a99ef0fab4fcfa 100644 (file)
@@ -5,7 +5,7 @@ O_TARGET := ntfs.o
 obj-y   := fs.o sysctl.o support.o util.o inode.o dir.o super.o attr.o unistr.o
 obj-m   := $(O_TARGET)
 # New version format started 3 February 2001.
-EXTRA_CFLAGS = -DNTFS_VERSION=\"1.1.15\" #-DDEBUG
+EXTRA_CFLAGS = -DNTFS_VERSION=\"1.1.16\" #-DDEBUG
 
 include $(TOPDIR)/Rules.make
 
index 33d8dd01230074716404e710a0adfc32d780fbfe..b32951df28f467618386721851f8be951c4fb8e9 100644 (file)
@@ -789,7 +789,7 @@ int ntfs_getdir_unsorted(ntfs_inode *ino, ntfs_u32 *p_high, ntfs_u32* p_low,
        int block;
        int start;
        ntfs_attribute *attr;
-       ntfs_volume *vol = ino->vol;
+       ntfs_volume *vol;
        int byte, bit;
        int error = 0;
 
@@ -797,6 +797,7 @@ int ntfs_getdir_unsorted(ntfs_inode *ino, ntfs_u32 *p_high, ntfs_u32* p_low,
                ntfs_error("No inode passed to getdir_unsorted\n");
                return -EINVAL;
        }
+       vol = ino->vol;
        if (!vol) {
                ntfs_error("Inode %d has no volume\n", ino->i_number);
                return -EINVAL;
index 74ffafcca88b322f01492fb97ea682498dd255c2..5a618251951bbe71b2e96d4acbec9b11509096c3 100644 (file)
@@ -1,8 +1,8 @@
 /*
  * fs.c - NTFS driver for Linux 2.4.x
  *
- * Development has as of recently (since June '01) been sponsored
- * by Legato Systems, Inc. (http://www.legato.com)
+ * Legato Systems, Inc. (http://www.legato.com) have sponsored Anton
+ * Altaparmakov to develop NTFS on Linux since June 2001.
  *
  * Copyright (C) 1995-1997, 1999 Martin von Löwis
  * Copyright (C) 1996 Richard Russon
@@ -286,25 +286,25 @@ static int simple_getbool(char *s, int *setval)
 }
 
 /* Parse the (re)mount options. */
-static int parse_options(ntfs_volume* vol, char *opt)
+static int parse_options(ntfs_volume *vol, char *opt, int remount)
 {
-       char *value;
-
-       vol->uid = vol->gid = 0;
-       vol->umask = 0077;
-       vol->ngt = ngt_nt;
-       vol->nls_map = 0;
-       vol->nct = 0;
+       char *value;            /* Defaults if not specified and !remount. */
+       ntfs_uid_t uid = -1;    /* 0, root user only */
+       ntfs_gid_t gid = -1;    /* 0, root user only */
+       int umask = -1;         /* 0077, owner access only */
+       unsigned int ngt = -1;  /* ngt_nt */
+       void *nls_map = NULL;   /* Try to load the default NLS. */
+       int use_utf8 = -1;      /* If no NLS specified and loading the default
+                                  NLS failed use utf8. */
        if (!opt)
                goto done;
-       for (opt = strtok(opt, ","); opt; opt = strtok(NULL, ","))
-       {
+       for (opt = strtok(opt, ","); opt; opt = strtok(NULL, ",")) {
                if ((value = strchr(opt, '=')) != NULL)
                        *value ++= '\0';
                if (strcmp(opt, "uid") == 0) {
                        if (!value || !*value)
                                goto needs_arg;
-                       vol->uid = simple_strtoul(value, &value, 0);
+                       uid = simple_strtoul(value, &value, 0);
                        if (*value) {
                                printk(KERN_ERR "NTFS: uid invalid argument\n");
                                return 0;
@@ -312,7 +312,7 @@ static int parse_options(ntfs_volume* vol, char *opt)
                } else if (strcmp(opt, "gid") == 0) {
                        if (!value || !*value)
                                goto needs_arg;
-                       vol->gid = simple_strtoul(value, &value, 0);
+                       gid = simple_strtoul(value, &value, 0);
                        if (*value) {
                                printk(KERN_ERR "NTFS: gid invalid argument\n");
                                return 0;
@@ -320,79 +320,86 @@ static int parse_options(ntfs_volume* vol, char *opt)
                } else if (strcmp(opt, "umask") == 0) {
                        if (!value || !*value)
                                goto needs_arg;
-                       vol->umask = simple_strtoul(value, &value, 0);
+                       umask = simple_strtoul(value, &value, 0);
                        if (*value) {
                                printk(KERN_ERR "NTFS: umask invalid "
                                                "argument\n");
                                return 0;
                        }
-               } else if (strcmp(opt, "iocharset") == 0) {
-                       if (!value || !*value)
-                               goto needs_arg;
-                       vol->nls_map = load_nls(value);
-                       vol->nct |= nct_map;
-                       if (!vol->nls_map) {
-                               printk(KERN_ERR "NTFS: charset not found");
-                               return 0;
-                       }
                } else if (strcmp(opt, "posix") == 0) {
                        int val;
                        if (!value || !*value)
                                goto needs_arg;
                        if (!simple_getbool(value, &val))
                                goto needs_bool;
-                       vol->ngt = val ? ngt_posix : ngt_nt;
+                       ngt = val ? ngt_posix : ngt_nt;
                } else if (strcmp(opt, "show_sys_files") == 0) {
                        int val = 0;
                        if (!value || !*value)
                                val = 1;
                        else if (!simple_getbool(value, &val))
                                goto needs_bool;
-                       vol->ngt = val ? ngt_full : ngt_nt;
-               } else if (strcmp(opt, "utf8") == 0) {
-                       int val = 0;
+                       ngt = val ? ngt_full : ngt_nt;
+               } else if (strcmp(opt, "iocharset") == 0) {
                        if (!value || !*value)
-                               val = 1;
-                       else if (!simple_getbool(value, &val))
-                               goto needs_bool;
-                       if (val)
-                               vol->nct |= nct_utf8;
-               } else if (strcmp(opt, "uni_xlate") == 0) {
+                               goto needs_arg;
+                       nls_map = load_nls(value);
+                       if (!nls_map) {
+                               printk(KERN_ERR "NTFS: charset not found");
+                               return 0;
+                       }
+               } else if (strcmp(opt, "utf8") == 0) {
                        int val = 0;
-                       /* No argument: uni_vfat. boolean argument: uni_vfat.
-                        * "2": uni. */
                        if (!value || !*value)
                                val = 1;
-                       else if (strcmp(value, "2") == 0)
-                               vol->nct |= nct_uni_xlate;
                        else if (!simple_getbool(value, &val))
                                goto needs_bool;
-                       if (val)
-                               vol->nct |= nct_uni_xlate_vfat | nct_uni_xlate;
+                       use_utf8 = val;
                } else {
                        printk(KERN_ERR "NTFS: unkown option '%s'\n", opt);
                        return 0;
                }
        }
-       if (vol->nct & nct_utf8 & (nct_map | nct_uni_xlate)) {
-               printk(KERN_ERR "utf8 cannot be combined with iocharset or "
-                               "uni_xlate\n");
-               return 0;
-       }
- done:
-       if ((vol->nct & (nct_uni_xlate | nct_map | nct_utf8)) == 0)
-               /* default to UTF-8 */
-               vol->nct = nct_utf8;
-       if (!vol->nls_map) {
-               vol->nls_map = load_nls_default();
-               if (vol->nls_map)
-                       vol->nct = nct_map | (vol->nct&nct_uni_xlate);
+done:
+       if (use_utf8 != -1 && use_utf8) {
+               if (nls_map) {
+                       unload_nls(nls_map);
+                       printk(KERN_ERR "NTFS: utf8 cannot be combined with "
+                                       "iocharset.\n");
+                       return 0;
+               }
+               if (remount && vol->nls_map)
+                       unload_nls(vol->nls_map);
+               vol->nls_map = NULL;
+       } else {
+               if (nls_map) {
+                       if (remount && vol->nls_map)
+                               unload_nls(vol->nls_map);
+                       vol->nls_map = nls_map;
+               } else if (!remount || (remount && !use_utf8 && !vol->nls_map))
+                       vol->nls_map = load_nls_default();
        }
+       if (uid != -1)
+               vol->uid = uid;
+       else if (!remount)
+               vol->uid = 0;
+       if (gid != -1)
+               vol->gid = gid;
+       else if (!remount)
+               vol->gid = 0;
+       if (umask != -1)
+               vol->umask = (ntmode_t)umask;
+       else if (!remount)
+               vol->umask = 0077;
+       if (ngt != -1)
+               vol->ngt = ngt;
+       else if (!remount)
+               vol->ngt = ngt_nt;
        return 1;
- needs_arg:
+needs_arg:
        printk(KERN_ERR "NTFS: %s needs an argument", opt);
        return 0;
- needs_bool:
+needs_bool:
        printk(KERN_ERR "NTFS: %s needs boolean argument", opt);
        return 0;
 }
@@ -898,7 +905,7 @@ static int ntfs_statfs(struct super_block *sb, struct statfs *sf)
 /* Called when remounting a filesystem by do_remount_sb() in fs/super.c. */
 static int ntfs_remount_fs(struct super_block *sb, int *flags, char *options)
 {
-       if (!parse_options(NTFS_SB2VOL(sb), options))
+       if (!parse_options(NTFS_SB2VOL(sb), options, 1))
                return -EINVAL;
        return 0;
 }
@@ -1003,7 +1010,7 @@ struct super_block * ntfs_read_super(struct super_block *sb, void *options,
 
        ntfs_debug(DEBUG_OTHER, "ntfs_read_super\n");
        vol = NTFS_SB2VOL(sb);
-       if (!parse_options(vol, (char*)options))
+       if (!parse_options(vol, (char*)options, 0))
                goto ntfs_read_super_vol;
        /* Assume a 512 bytes block device for now. */
        set_blocksize(sb->s_dev, 512);
index c3ddeb00bb411c1ace0030d5c5a14ce36bfed32c..de4b82f81c026981e9a4782f16758e6f37810026 100644 (file)
@@ -225,147 +225,81 @@ ntfs_time64_t ntfs_now(void)
        return ntfs_unixutc2ntutc(CURRENT_TIME);
 }
 
-/* When printing unicode characters base64, use this table. It is not strictly
- * base64, but the Linux vfat encoding. base64 has the disadvantage of using
- * the slash. */
-static char uni2esc[64] = 
-           "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+-";
-
-static unsigned char esc2uni(char c)
-{
-       if (c <  '0') return 255;
-       if (c <= '9') return c - '0';
-       if (c <  'A') return 255;
-       if (c <= 'Z') return c - 'A' + 10;
-       if (c <  'a') return 255;
-       if (c <= 'z') return c - 'a' + 36;
-       if (c == '+') return 62;
-       if (c == '-') return 63;
-       return 255;
-}
-
 int ntfs_dupuni2map(ntfs_volume *vol, ntfs_u16 *in, int in_len, char **out,
-                   int *out_len)
+               int *out_len)
 {
-       int i, o, val, chl, chi;
+       int i, o, chl, chi;
        char *result, *buf, charbuf[NLS_MAX_CHARSET_SIZE];
-       struct nls_tablenls = vol->nls_map;
+       struct nls_table *nls = vol->nls_map;
 
        result = ntfs_malloc(in_len + 1);
        if (!result)
                return -ENOMEM;
        *out_len = in_len;
-       result[in_len] = '\0';
        for (i = o = 0; i < in_len; i++) {
-               int cl, ch;
-               /* FIXME: byte order? */
-               cl = in[i] & 0xFF;
-               ch = (in[i] >> 8) & 0xFF;
-               if (!nls) {
-                       if (!ch) {
-                               result[o++] = cl;
-                               continue;
-                       }
-               } else {
-                       /* FIXME: byte order? */
-                       wchar_t uni = in[i];
-                       if ((chl = nls->uni2char(uni, charbuf,
-                                               NLS_MAX_CHARSET_SIZE)) > 0) {
-                               /* adjust result buffer */
-                               if (chl > 1) {
-                                       buf = ntfs_malloc(*out_len + chl - 1);
-                                       if (!buf) {
-                                               ntfs_free(result);
-                                               return -ENOMEM;
-                                       }
-                                       memcpy(buf, result, o);
+               /* FIXME: Byte order? */
+               wchar_t uni = in[i];
+               if ((chl = nls->uni2char(uni, charbuf,
+                               NLS_MAX_CHARSET_SIZE)) > 0) {
+                       /* Adjust result buffer. */
+                       if (chl > 1) {
+                               buf = ntfs_malloc(*out_len + chl - 1);
+                               if (!buf) {
                                        ntfs_free(result);
-                                       result = buf;
-                                       *out_len += (chl - 1);
+                                       return -ENOMEM;
                                }
-                               for (chi = 0; chi < chl; chi++)
-                                       result[o++] = charbuf[chi];
-                       } else
-                               result[o++] = '?';
-                       continue;
-               }
-               if (!(vol->nct & nct_uni_xlate))
-                       goto inval;
-               /* realloc */
-               buf = ntfs_malloc(*out_len + 3);
-               if (!buf) {
-                       ntfs_free(result);
-                       return -ENOMEM;
-               }
-               memcpy(buf, result, o);
-               ntfs_free(result);
-               result = buf;
-               *out_len += 3;
-               result[o++] = ':';
-               if (vol->nct & nct_uni_xlate_vfat) {
-                       val = (cl << 8) + ch;
-                       result[o+2] = uni2esc[val & 0x3f];
-                       val >>= 6;
-                       result[o+1] = uni2esc[val & 0x3f];
-                       val >>= 6;
-                       result[o] = uni2esc[val & 0x3f];
-                       o += 3;
+                               memcpy(buf, result, o);
+                               ntfs_free(result);
+                               result = buf;
+                               *out_len += (chl - 1);
+                       }
+                       for (chi = 0; chi < chl; chi++)
+                               result[o++] = charbuf[chi];
                } else {
-                       val = (ch << 8) + cl;
-                       result[o++] = uni2esc[val & 0x3f];
-                       val >>= 6;
-                       result[o++] = uni2esc[val & 0x3f];
-                       val >>= 6;
-                       result[o++] = uni2esc[val & 0x3f];
+                       /* Invalid character. */
+                       printk(KERN_ERR "NTFS: Unicode name contains a "
+                                       "character that cannot be converted "
+                                       "to chosen character set. Remount "
+                                       "with utf8 encoding and this should "
+                                       "work.\n");
+                       ntfs_free(result);
+                       return -EILSEQ;
                }
        }
+       result[*out_len] = '\0';
        *out = result;
        return 0;
- inval:
-       ntfs_free(result);
-       *out = 0;
-       return -EILSEQ;
 }
 
 int ntfs_dupmap2uni(ntfs_volume *vol, char* in, int in_len, ntfs_u16 **out,
-                   int *out_len)
+               int *out_len)
 {
        int i, o;
-       ntfs_u16result;
-       struct nls_tablenls = vol->nls_map;
+       ntfs_u16 *result;
+       struct nls_table *nls = vol->nls_map;
 
-       *out=result = ntfs_malloc(2 * in_len);
+       *out = result = ntfs_malloc(2 * in_len);
        if (!result)
                return -ENOMEM;
        *out_len = in_len;
-       for (i = o = 0; i < in_len; i++, o++){
+       for (i = o = 0; i < in_len; i++, o++) {
                wchar_t uni;
-               if (in[i] != ':' || (vol->nct & nct_uni_xlate) == 0){
-                       int charlen;
-                       charlen = nls->char2uni(&in[i], in_len-i, &uni);
-                       if (charlen < 0)
-                               return charlen;
-                       *out_len -= (charlen - 1);
-                       i += (charlen - 1);
-               } else {
-                       unsigned char c1, c2, c3;
-                       *out_len -= 3;
-                       c1 = esc2uni(in[++i]);
-                       c2 = esc2uni(in[++i]);
-                       c3 = esc2uni(in[++i]);
-                       if (c1 == 255 || c2 == 255 || c3 == 255)
-                               uni = 0;
-                       else if (vol->nct & nct_uni_xlate_vfat) {
-                               uni = (((c2 & 0x3) << 6) + c3) << 8 |
-                                     ((c1 << 4) + (c2 >> 2));
-                       } else {
-                               uni = ((c3 << 4) + (c2 >> 2)) << 8 |
-                                     (((c2 & 0x3) << 6) + c1);
-                       }
+               int charlen;
+
+               charlen = nls->char2uni(&in[i], in_len - i, &uni);
+               if (charlen < 0) {
+                       printk(KERN_ERR "NTFS: Name contains a character that "
+                                       "cannot be converted to Unicode.\n");
+                       ntfs_free(result);
+                       return charlen;
                }
-               /* FIXME: byte order? */
+               *out_len -= charlen - 1;
+               i += charlen - 1;
+               /* FIXME: Byte order? */
                result[o] = uni;
                if (!result[o]) {
+                       printk(KERN_ERR "NTFS: Name contains a character that "
+                                       "cannot be converted to Unicode.\n");
                        ntfs_free(result);
                        return -EILSEQ;
                }
index 7aea470bb4bbe9cb8745d98a6646c224c71eeac3..082e1b7d788eec00dfe3e9f58ad42559533cb93b 100644 (file)
 #include "util.h"
 #include <linux/string.h>
 #include <linux/errno.h>
+#include <asm/div64.h>         /* For do_div(). */
 #include "support.h"
 
-/* Converts a single wide character to a sequence of utf8 bytes.
+/*
+ * Converts a single wide character to a sequence of utf8 bytes.
  * The character is represented in host byte order.
- * Returns the number of bytes, or 0 on error. */
-static int to_utf8(ntfs_u16 c, unsigned char* buf)
+ * Returns the number of bytes, or 0 on error.
+ */
+static int to_utf8(ntfs_u16 c, unsigned char *buf)
 {
        if (c == 0)
                return 0; /* No support for embedded 0 runes. */
@@ -34,22 +37,21 @@ static int to_utf8(ntfs_u16 c, unsigned char* buf)
                }
                return 2;
        }
-       if (c < 0x10000) {
-               if (buf) {
-                       buf[0] = 0xe0 | (c >> 12);
-                       buf[1] = 0x80 | ((c >> 6) & 0x3f);
-                       buf[2] = 0x80 | (c & 0x3f);
-               }
-               return 3;
+       /* c < 0x10000 */
+       if (buf) {
+               buf[0] = 0xe0 | (c >> 12);
+               buf[1] = 0x80 | ((c >> 6) & 0x3f);
+               buf[2] = 0x80 | (c & 0x3f);
        }
-       /* We don't support characters above 0xFFFF in NTFS. */
-       return 0;
+       return 3;
 }
 
-/* Decodes a sequence of utf8 bytes into a single wide character.
+/*
+ * Decodes a sequence of utf8 bytes into a single wide character.
  * The character is returned in host byte order.
- * Returns the number of bytes consumed, or 0 on error. */
-static int from_utf8(const unsigned char* str, ntfs_u16 *c)
+ * Returns the number of bytes consumed, or 0 on error.
+ */
+static int from_utf8(const unsigned char *str, ntfs_u16 *c)
 {
        int l = 0, i;
 
@@ -80,11 +82,12 @@ static int from_utf8(const unsigned char* str, ntfs_u16 *c)
        return l;
 }
 
-/* Converts wide string to UTF-8. Expects two in- and two out-parameters.
+/*
+ * Converts wide string to UTF-8. Expects two in- and two out-parameters.
  * Returns 0 on success, or error code. 
  * The caller has to free the result string.
- * There is no support for UTF-16, yet. */
-static int ntfs_dupuni2utf8(ntfs_u16in, int in_len, char **out, int *out_len)
+ */
+static int ntfs_dupuni2utf8(ntfs_u16 *in, int in_len, char **out, int *out_len)
 {
        int i, tmp;
        int len8;
@@ -92,15 +95,14 @@ static int ntfs_dupuni2utf8(ntfs_u16* in, int in_len, char **out, int *out_len)
 
        ntfs_debug(DEBUG_NAME1, "converting l = %d\n", in_len);
        /* Count the length of the resulting UTF-8. */
-       for (i = len8 = 0; i < in_len; i++){
+       for (i = len8 = 0; i < in_len; i++) {
                tmp = to_utf8(NTFS_GETU16(in + i), 0);
                if (!tmp)
-                       /* invalid character */
+                       /* Invalid character. */
                        return -EILSEQ;
                len8 += tmp;
        }
        *out = result = ntfs_malloc(len8 + 1); /* allow for zero-termination */
-
        if (!result)
                return -ENOMEM;
        result[len8] = '\0';
@@ -111,10 +113,12 @@ static int ntfs_dupuni2utf8(ntfs_u16* in, int in_len, char **out, int *out_len)
        return 0;
 }
 
-/* Converts an UTF-8 sequence to a wide string. Same conventions as the
- * previous function. */
+/*
+ * Converts an UTF-8 sequence to a wide string. Same conventions as the
+ * previous function.
+ */
 static int ntfs_duputf82uni(unsigned char* in, int in_len, ntfs_u16** out,
-                           int *out_len)
+               int *out_len)
 {
        int i, tmp;
        int len16;
@@ -131,76 +135,30 @@ static int ntfs_duputf82uni(unsigned char* in, int in_len, ntfs_u16** out,
                return -ENOMEM;
        result[len16] = 0;
        *out_len = len16;
-       for (i = len16 = 0; i < in_len; i += tmp, len16++)
-       {
+       for (i = len16 = 0; i < in_len; i += tmp, len16++) {
                tmp = from_utf8(in + i, &wtmp);
                NTFS_PUTU16(result + len16, wtmp);
        }
        return 0;
 }
 
-/* See above. Produces ISO-8859-1 from wide strings. */
-static int ntfs_dupuni288591(ntfs_u16* in, int in_len, char** out, int *out_len)
-{
-       int i;
-       char *result;
-
-       /* Check for characters out of range. */
-       for (i = 0; i < in_len; i++)
-               if (NTFS_GETU16(in + i) >= 256)
-                       return -EILSEQ;
-       *out = result = ntfs_malloc(in_len + 1);
-       if (!result)
-               return -ENOMEM;
-       result[in_len] = '\0';
-       *out_len = in_len;
-       for (i = 0; i < in_len; i++)
-               result[i] = (unsigned char)NTFS_GETU16(in + i);
-       return 0;
-}
-
-/* See above. */
-static int ntfs_dup885912uni(unsigned char* in, int in_len, ntfs_u16 **out,
-                            int *out_len)
-{
-       int i;
-
-       ntfs_u16* result;
-       *out = result = ntfs_malloc(2 * in_len);
-       if (!result)
-               return -ENOMEM;
-       *out_len = in_len;
-       for (i = 0; i < in_len; i++)
-               NTFS_PUTU16(result + i, in[i]);
-       return 0;
-}
-
-/* Encodings dispatcher */
+/* Encodings dispatchers. */
 int ntfs_encodeuni(ntfs_volume *vol, ntfs_u16 *in, int in_len, char **out,
-                  int *out_len)
+               int *out_len)
 {
-       if (vol->nct & nct_utf8)
-               return ntfs_dupuni2utf8(in, in_len, out, out_len);
-       else if (vol->nct & nct_iso8859_1)
-               return ntfs_dupuni288591(in, in_len, out, out_len);
-       else if(vol->nct & (nct_map | nct_uni_xlate))
-               /* uni_xlate is handled inside map. */
+       if (vol->nls_map)
                return ntfs_dupuni2map(vol, in, in_len, out, out_len);
        else
-               return -EINVAL; /* unknown encoding */
+               return ntfs_dupuni2utf8(in, in_len, out, out_len);
 }
 
 int ntfs_decodeuni(ntfs_volume *vol, char *in, int in_len, ntfs_u16 **out,
-                  int *out_len)
+               int *out_len)
 {
-       if (vol->nct & nct_utf8)
-               return ntfs_duputf82uni(in, in_len, out, out_len);
-       else if (vol->nct & nct_iso8859_1)
-               return ntfs_dup885912uni(in, in_len, out, out_len);
-       else if (vol->nct & (nct_map | nct_uni_xlate))
+       if (vol->nls_map)
                return ntfs_dupmap2uni(vol, in, in_len, out, out_len);
        else
-               return -EINVAL;
+               return ntfs_duputf82uni(in, in_len, out, out_len);
 }
 
 /* Same address space copies. */
@@ -224,18 +182,6 @@ void *ntfs_calloc(int size)
        return result;
 }
 
-#if 0
-/* Copy len unicode characters from from to to. :) */
-void ntfs_uni2ascii(char *to, short int *from, int len)
-{
-       int i;
-
-       for (i = 0; i < len; i++)
-               to[i] = NTFS_GETU16(from + i);
-       to[i] = '\0';
-}
-#endif
-
 /* Copy len ascii characters from from to to. :) */
 void ntfs_ascii2uni(short int *to, char *from, int len)
 {
@@ -279,58 +225,27 @@ int ntfs_ua_strncmp(short int* a, char* b, int n)
        return 0;
 }
 
+#define NTFS_TIME_OFFSET ((ntfs_time64_t)(369*365 + 89) * 24 * 3600 * 10000000)
+
 /* Convert the NT UTC (based 1.1.1601, in hundred nanosecond units)
  * into Unix UTC (based 1.1.1970, in seconds). */
 ntfs_time_t ntfs_ntutc2unixutc(ntfs_time64_t ntutc)
 {
-/* This is very gross because:
- * 1: We must do 64-bit division on a 32-bit machine.
- * 2: We can't use libgcc for long long operations in the kernel.
- * 3: Floating point math in the kernel would corrupt user data. */
-       const unsigned int D = 10000000;
-       unsigned int H = (unsigned int)(ntutc >> 32);
-       unsigned int L = (unsigned int)ntutc;
-       unsigned int numerator2;
-       unsigned int lowseconds;
-       unsigned int result;
-
-       /* It is best to subtract 0x019db1ded53e8000 first. */
-       /* Then the 1601-based date becomes a 1970-based date. */
-       if (L < (unsigned)0xd53e8000)
-               H--;
-       L -= (unsigned)0xd53e8000;
-       H -= (unsigned)0x019db1de;
-
-       /* Now divide 64-bit numbers on a 32-bit machine. :-)
-        * With the subtraction already done, the result fits in 32 bits.
-        * The numerator fits in 56 bits and the denominator fits
-        * in 24 bits, so we can shift by 8 bits to make this work. */
-
-       numerator2  = (H << 8) | (L >> 24);
-       result      = (numerator2 / D);   /* shifted 24 right!! */
-       lowseconds  = result << 24;
-
-       numerator2  = ((numerator2 - result * D) << 8) | ((L >> 16) & 0xff);
-       result      = (numerator2 / D);   /* shifted 16 right!! */
-       lowseconds |= result << 16;
-
-       numerator2  = ((numerator2 - result * D) << 8) | ((L >> 8) & 0xff);
-       result      = (numerator2 / D);   /* shifted 8 right!! */
-       lowseconds |= result << 8;
-
-       numerator2  = ((numerator2 - result * D) << 8) | (L & 0xff);
-       result      = (numerator2 / D);   /* not shifted */
-       lowseconds |= result;
-
-       return lowseconds;
+       /* Subtract the NTFS time offset, then convert to 1s intervals. */
+       ntfs_time64_t t = ntutc - NTFS_TIME_OFFSET;
+       do_div(t, 10000000);
+       return (ntfs_time_t)t;
 }
 
 /* Convert the Unix UTC into NT UTC. */
 ntfs_time64_t ntfs_unixutc2ntutc(ntfs_time_t t)
 {
-       return ((t + (ntfs_time64_t)(369 * 365 + 89) * 24 * 3600) * 10000000);
+       /* Convert to 100ns intervals and then add the NTFS time offset. */
+       return (ntfs_time64_t)t * 10000000 + NTFS_TIME_OFFSET;
 }
 
+#undef NTFS_TIME_OFFSET
+
 /* Fill index name. */
 void ntfs_indexname(char *buf, int type)
 {
index 94e856e48fc49323259f3ed8ef3da4c0004eec13..a077f35bcbd6cec29f7e5a5d965c12c1c181115f 100644 (file)
@@ -5,18 +5,6 @@
  * Copyright (C) 2001 Anton Altaparmakov (AIA)
  */
 
-/* Which character set is used for file names. */
-/*  Translate everything to UTF-8. */
-#define nct_utf8             1
-/*  Translate to 8859-1. */
-#define nct_iso8859_1        2
-/*  Quote unprintables with ":". */
-#define nct_uni_xlate        4
-/*  Do that in the vfat way instead of the documented way. */
-#define nct_uni_xlate_vfat   8
-/*  Use a mapping table to determine printables. */
-#define nct_map              16
-
 /* The first 16 inodes correspond to NTFS special files. */
 typedef enum {
        FILE_$Mft       = 0,
@@ -42,9 +30,6 @@ void *ntfs_calloc(int size);
 
 /* String operations */
 /*  Copy Unicode <-> ASCII */
-#if 0
-void ntfs_uni2ascii(char *to, char *from, int len);
-#endif
 void ntfs_ascii2uni(short int *to, char *from, int len);
 
 /*  Comparison */
index c6b8f7b89c58b62622a82ede56ac11adbaa99c82..6e23ef56a51c2e39985310d29fb4c201144ab90a 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -847,3 +847,18 @@ asmlinkage long sys_vhangup(void)
        }
        return -EPERM;
 }
+
+/*
+ * Called when an inode is about to be open.
+ * We use this to disallow opening RW large files on 32bit systems if
+ * the caller didn't specify O_LARGEFILE.  On 64bit systems we force
+ * on this flag in sys_open.
+ */
+int generic_file_open(struct inode * inode, struct file * filp)
+{
+       if (!(filp->f_flags & O_LARGEFILE) && inode->i_size > MAX_NON_LFS)
+               return -EFBIG;
+       return 0;
+}
+
+EXPORT_SYMBOL(generic_file_open);
index 22fa68ec907b8e28a94d805c9702cb33a80f964c..1f11b7d91b6e64ad6a74d33b31329d21db8abe17 100644 (file)
@@ -52,6 +52,7 @@ struct apm_info {
        struct apm_bios_info    bios;
        unsigned short          connection_version;
        int                     get_power_status_broken;
+       int                     get_power_status_swabinminutes;
        int                     allow_ints;
        int                     realmode_power_off;
        int                     disabled;
index d8fed404b1e2b6e9fb9f08912050eb8b92833fc5..574c6377c97de87d59ed0f5baf1939d4dcc995e7 100644 (file)
@@ -1347,6 +1347,7 @@ extern void do_generic_file_read(struct file *, loff_t *, read_descriptor_t *, r
 extern loff_t no_llseek(struct file *file, loff_t offset, int origin);
 extern loff_t generic_file_llseek(struct file *file, loff_t offset, int origin);
 extern ssize_t generic_read_dir(struct file *, char *, size_t, loff_t *);
+extern int generic_file_open(struct inode * inode, struct file * filp);
 
 extern struct file_operations generic_ro_fops;
 
index 45c45ef0170a9050a49d861bb7d0ecfd0cc6e42a..3ece9cee16bb6ee4b1a5c48fdb71caec2c471fc0 100644 (file)
@@ -30,6 +30,7 @@
 #include <asm/semaphore.h> /* Needed for MUTEX init macros */
 #include <linux/config.h>
 #include <linux/notifier.h>
+#include <linux/ioport.h>
 #include <asm/atomic.h>
 
 /*
index 17a7748b996ee5ec08b61b595a4d0b2f83dd6033..5db43159a3be10ba729587a96d6598e92ccb9a23 100644 (file)
@@ -86,6 +86,11 @@ typedef unsigned char        byte;   /* used everywhere */
 #define ERROR_RESET    3       /* Reset controller every 4th retry */
 #define ERROR_RECAL    1       /* Recalibrate every 2nd retry */
 
+/*
+ * state flags
+ */
+#define DMA_PIO_RETRY  1       /* retrying in PIO */
+
 /*
  * Ensure that various configuration flags have compatible settings
  */
@@ -133,14 +138,6 @@ typedef unsigned char      byte;   /* used everywhere */
 #define IDE_BCOUNTL_REG                IDE_LCYL_REG
 #define IDE_BCOUNTH_REG                IDE_HCYL_REG
 
-#ifdef REALLY_FAST_IO
-#define OUT_BYTE(b,p)          outb((b),(p))
-#define IN_BYTE(p)             (byte)inb(p)
-#else
-#define OUT_BYTE(b,p)          outb_p((b),(p))
-#define IN_BYTE(p)             (byte)inb_p(p)
-#endif /* REALLY_FAST_IO */
-
 #define GET_ERR()              IN_BYTE(IDE_ERROR_REG)
 #define GET_STAT()             IN_BYTE(IDE_STATUS_REG)
 #define GET_ALTSTAT()          IN_BYTE(IDE_CONTROL_REG)
@@ -254,6 +251,27 @@ void ide_setup_ports(      hw_regs_t *hw,
 
 #include <asm/ide.h>
 
+/*
+ * If the arch-dependant ide.h did not declare/define any OUT_BYTE
+ * or IN_BYTE functions, we make some defaults here.
+ */
+
+#ifndef HAVE_ARCH_OUT_BYTE
+#ifdef REALLY_FAST_IO
+#define OUT_BYTE(b,p)          outb((b),(p))
+#else
+#define OUT_BYTE(b,p)          outb_p((b),(p))
+#endif
+#endif
+
+#ifndef HAVE_ARCH_IN_BYTE
+#ifdef REALLY_FAST_IO
+#define IN_BYTE(p)             (byte)inb_p(p)
+#else
+#define IN_BYTE(p)             (byte)inb(p)
+#endif
+#endif
+
 /*
  * Now for the data we need to maintain per-drive:  ide_drive_t
  */
@@ -286,6 +304,8 @@ typedef struct ide_drive_s {
        special_t       special;        /* special action flags */
        byte     keep_settings;         /* restore settings after drive reset */
        byte     using_dma;             /* disk is using dma for read/write */
+       byte     retry_pio;             /* retrying dma capable host in pio */
+       byte     state;                 /* retry state */
        byte     waiting_for_dma;       /* dma currently in progress */
        byte     unmask;                /* flag: okay to unmask other irqs */
        byte     slow;                  /* flag: slow data port */
@@ -349,6 +369,8 @@ typedef struct ide_drive_s {
        byte            init_speed;     /* transfer rate set at boot */
        byte            current_speed;  /* current transfer rate set */
        byte            dn;             /* now wide spread use */
+       unsigned int    failures;       /* current failure count */
+       unsigned int    max_failures;   /* maximum allowed failure count */
 } ide_drive_t;
 
 /*
@@ -372,6 +394,23 @@ typedef enum {     ide_dma_read,   ide_dma_write,          ide_dma_begin,
 
 typedef int (ide_dmaproc_t)(ide_dma_action_t, ide_drive_t *);
 
+/*
+ * An ide_ideproc_t() performs CPU-polled transfers to/from a drive.
+ * Arguments are: the drive, the buffer pointer, and the length (in bytes or
+ * words depending on if it's an IDE or ATAPI call).
+ *
+ * If it is not defined for a controller, standard-code is used from ide.c.
+ *
+ * Controllers which are not memory-mapped in the standard way need to 
+ * override that mechanism using this function to work.
+ *
+ */
+typedef enum { ideproc_ide_input_data,    ideproc_ide_output_data,
+              ideproc_atapi_input_bytes, ideproc_atapi_output_bytes
+} ide_ide_action_t;
+
+typedef void (ide_ideproc_t)(ide_ide_action_t, ide_drive_t *, void *, unsigned int);
+
 /*
  * An ide_tuneproc_t() is used to set the speed of an IDE interface
  * to a particular PIO mode.  The "byte" parameter is used
@@ -396,6 +435,11 @@ typedef void (ide_intrproc_t) (ide_drive_t *);
 typedef void (ide_maskproc_t) (ide_drive_t *, int);
 typedef void (ide_rw_proc_t) (ide_drive_t *, ide_dma_action_t);
 
+/*
+ * ide soft-power support
+ */
+typedef int (ide_busproc_t) (struct hwif_s *, int);
+
 /*
  * hwif_chipset_t is used to keep track of the specific hardware
  * chipset used by each IDE interface, if known.
@@ -405,9 +449,13 @@ typedef enum {     ide_unknown,    ide_generic,    ide_pci,
                ide_qd6580,     ide_umc8672,    ide_ht6560b,
                ide_pdc4030,    ide_rz1000,     ide_trm290,
                ide_cmd646,     ide_cy82c693,   ide_4drives,
-               ide_pmac
+               ide_pmac,       ide_etrax100
 } hwif_chipset_t;
 
+#define IDE_CHIPSET_PCI_MASK   \
+    ((1<<ide_pci)|(1<<ide_cmd646)|(1<<ide_ali14xx))
+#define IDE_CHIPSET_IS_PCI(c)  ((IDE_CHIPSET_PCI_MASK >> (c)) & 1)
+
 #ifdef CONFIG_BLK_DEV_IDEPCI
 typedef struct ide_pci_devid_s {
        unsigned short  vid;
@@ -433,12 +481,14 @@ typedef struct hwif_s {
        ide_maskproc_t  *maskproc;      /* special host masking for drive selection */
        ide_quirkproc_t *quirkproc;     /* check host's drive quirk list */
        ide_rw_proc_t   *rwproc;        /* adjust timing based upon rq->cmd direction */
+       ide_ideproc_t   *ideproc;       /* CPU-polled transfer routine */
        ide_dmaproc_t   *dmaproc;       /* dma read/write/abort routine */
        unsigned int    *dmatable_cpu;  /* dma physical region descriptor table (cpu view) */
        dma_addr_t      dmatable_dma;   /* dma physical region descriptor table (dma view) */
        struct scatterlist *sg_table;   /* Scatter-gather list used to build the above */
        int sg_nents;                   /* Current number of entries in it */
        int sg_dma_direction;           /* dma transfer direction */
+       int sg_dma_active;              /* is it in use */
        struct hwif_s   *mate;          /* other hwif from same PCI chip */
        unsigned long   dma_base;       /* base addr for dma ports */
        unsigned        dma_extra;      /* extra addr for dma ports */
@@ -467,6 +517,8 @@ typedef struct hwif_s {
 #endif
        byte            straight8;      /* Alan's straight 8 check */
        void            *hwif_data;     /* extra hwif data */
+       ide_busproc_t   *busproc;       /* driver soft-power interface */
+       byte            bus_state;      /* power state of the IDE bus */
 } ide_hwif_t;
 
 
@@ -595,6 +647,7 @@ typedef void                (ide_pre_reset_proc)(ide_drive_t *);
 typedef unsigned long  (ide_capacity_proc)(ide_drive_t *);
 typedef ide_startstop_t        (ide_special_proc)(ide_drive_t *);
 typedef void           (ide_setting_proc)(ide_drive_t *);
+typedef int            (ide_driver_reinit_proc)(ide_drive_t *);
 
 typedef struct ide_driver_s {
        const char                      *name;
@@ -615,6 +668,7 @@ typedef struct ide_driver_s {
        ide_capacity_proc               *capacity;
        ide_special_proc                *special;
        ide_proc_entry_t                *proc;
+       ide_driver_reinit_proc          *driver_reinit;
 } ide_driver_t;
 
 #define DRIVER(drive)          ((ide_driver_t *)((drive)->driver))
@@ -738,6 +792,12 @@ unsigned long current_capacity (ide_drive_t *drive);
  */
 ide_startstop_t ide_do_reset (ide_drive_t *);
 
+/*
+ * Re-Start an operation for an IDE interface.
+ * The caller should return immediately after invoking this.
+ */
+ide_startstop_t restart_request (ide_drive_t *);
+
 /*
  * This function is intended to be used prior to invoking ide_do_drive_cmd().
  */
index ed5fbc59d247361c49238262b3219951ce8ea16d..571557de8762cb08e0d3e4aa348df58804be86ea 100644 (file)
@@ -57,7 +57,7 @@ struct readdir_cd {
        char                    dotonly;
 };
 typedef int            (*encode_dent_fn)(struct readdir_cd *, const char *,
-                                               int, off_t, ino_t, unsigned int);
+                                               int, loff_t, ino_t, unsigned int);
 typedef int (*nfsd_dirop_t)(struct inode *, struct dentry *, int, int);
 
 /*
index 4bb4f668bf7c3f2d70c683daf8e4f5ab64bb5019..5d96579529ed7419483261ebd1eec9b5a669b5eb 100644 (file)
@@ -151,7 +151,7 @@ int nfssvc_encode_statfsres(struct svc_rqst *, u32 *, struct nfsd_statfsres *);
 int nfssvc_encode_readdirres(struct svc_rqst *, u32 *, struct nfsd_readdirres *);
 
 int nfssvc_encode_entry(struct readdir_cd *, const char *name,
-                               int namlen, off_t offset, ino_t ino, unsigned int);
+                               int namlen, loff_t offset, ino_t ino, unsigned int);
 
 int nfssvc_release_fhandle(struct svc_rqst *, u32 *, struct nfsd_fhandle *);
 
index a5ca90410204607405934280a41e4263e9426121..35d167ad6cd2e13f577c52f6626658447f3dc3bf 100644 (file)
@@ -292,10 +292,10 @@ int nfs3svc_release_fhandle(struct svc_rqst *, u32 *,
 int nfs3svc_release_fhandle2(struct svc_rqst *, u32 *,
                                struct nfsd3_fhandle_pair *);
 int nfs3svc_encode_entry(struct readdir_cd *, const char *name,
-                               int namlen, off_t offset, ino_t ino,
+                               int namlen, loff_t offset, ino_t ino,
                                unsigned int);
 int nfs3svc_encode_entry_plus(struct readdir_cd *, const char *name,
-                               int namlen, off_t offset, ino_t ino,
+                               int namlen, loff_t offset, ino_t ino,
                                unsigned int);
 
 
index af11d732f02243380cf2f91e72bb938305f6fae3..6181604ff0e8ea8e12bc388a58bbea9afc551fdd 100644 (file)
@@ -8,7 +8,6 @@ struct ntfs_sb_info{
        ntfs_uid_t uid;
        ntfs_gid_t gid;
        ntmode_t umask;
-        unsigned int nct;
        void *nls_map;
        unsigned int ngt;
        /* Configuration provided by user with the ntfstools.
index a32080868dcdba63a0ae6d10827881840d3e0ec0..a17b5ca296231d23c58803947e06b7a8640991e0 100644 (file)
 #define PCI_DEVICE_ID_AIRONET_4500     0x4800 // drivers/net/aironet4500_card.c
 
 #define PCI_VENDOR_ID_TITAN            0x14D2
+#define PCI_DEVICE_ID_TITAN_010L       0x8001
+#define PCI_DEVICE_ID_TITAN_100L       0x8010
 #define PCI_DEVICE_ID_TITAN_110L       0x8011
+#define PCI_DEVICE_ID_TITAN_200L       0x8020
 #define PCI_DEVICE_ID_TITAN_210L       0x8021
+#define PCI_DEVICE_ID_TITAN_400L       0x8040
+#define PCI_DEVICE_ID_TITAN_800L       0x8080
 #define PCI_DEVICE_ID_TITAN_100                0xA001
 #define PCI_DEVICE_ID_TITAN_200                0xA005
 #define PCI_DEVICE_ID_TITAN_400                0xA003
index 71945a51e9f9da0a0fe8c6a4048d85ab7005e062..79985c06aaaaf7a37d5be2b70bff5504c093e8db 100644 (file)
@@ -460,7 +460,7 @@ int map_user_kiobuf(int rw, struct kiobuf *iobuf, unsigned long va, size_t len)
        if (err)
                return err;
 
-       down_write(&mm->mmap_sem);
+       down_read(&mm->mmap_sem);
 
        err = -EFAULT;
        iobuf->locked = 0;
@@ -518,12 +518,12 @@ int map_user_kiobuf(int rw, struct kiobuf *iobuf, unsigned long va, size_t len)
                ptr += PAGE_SIZE;
        }
 
-       up_write(&mm->mmap_sem);
+       up_read(&mm->mmap_sem);
        dprintk ("map_user_kiobuf: end OK\n");
        return 0;
 
  out_unlock:
-       up_write(&mm->mmap_sem);
+       up_read(&mm->mmap_sem);
        unmap_kiobuf(iobuf);
        dprintk ("map_user_kiobuf: end %d\n", err);
        return err;
index 74b7121ddf1c69897a0bf0ca47b1398637da97d4..23b0580164e51943d0256266908634fda76bb847 100644 (file)
@@ -136,26 +136,12 @@ static struct task_struct * select_bad_process(void)
 }
 
 /**
- * oom_kill - kill the "best" process when we run out of memory
- *
- * If we run out of memory, we have the choice between either
- * killing a random task (bad), letting the system crash (worse)
- * OR try to be smart about which process to kill. Note that we
- * don't have to be perfect here, we just have to be good.
- *
  * We must be careful though to never send SIGKILL a process with
  * CAP_SYS_RAW_IO set, send SIGTERM instead (but it's unlikely that
  * we select a process with CAP_SYS_RAW_IO set).
  */
-void oom_kill(void)
+void oom_kill_task(struct task_struct *p)
 {
-
-       struct task_struct *p = select_bad_process();
-
-       /* Found nothing?!?! Either we hang forever, or we panic. */
-       if (p == NULL)
-               panic("Out of memory and no killable processes...\n");
-
        printk(KERN_ERR "Out of Memory: Killed process %d (%s).\n", p->pid, p->comm);
 
        /*
@@ -172,6 +158,30 @@ void oom_kill(void)
        } else {
                force_sig(SIGKILL, p);
        }
+}
+
+/**
+ * oom_kill - kill the "best" process when we run out of memory
+ *
+ * If we run out of memory, we have the choice between either
+ * killing a random task (bad), letting the system crash (worse)
+ * OR try to be smart about which process to kill. Note that we
+ * don't have to be perfect here, we just have to be good.
+ */
+void oom_kill(void)
+{
+       struct task_struct *p = select_bad_process(), *q;
+
+       /* Found nothing?!?! Either we hang forever, or we panic. */
+       if (p == NULL)
+               panic("Out of memory and no killable processes...\n");
+
+       /* kill all processes that share the ->mm (i.e. all threads) */
+       read_lock(&tasklist_lock);
+       for_each_task(q) {
+               if(q->mm == p->mm) oom_kill_task(q);
+       }
+       read_unlock(&tasklist_lock);
 
        /*
         * Make kswapd go out of the way, so "p" has a good chance of
index 3ef8743e9c06c8442d9fdc70b2c6c7fb632f252f..2e93eb1178bdfd0a87ac87f579237dd3d325bd20 100644 (file)
@@ -477,20 +477,19 @@ out:
  * This code used to be heavily inspired by the FreeBSD source code. 
  * Thanks go out to Matthew Dillon.
  */
-#define MAX_LAUNDER            (4 * (1 << page_cluster))
 #define CAN_DO_FS              (gfp_mask & __GFP_FS)
-#define CAN_DO_IO              (gfp_mask & __GFP_IO)
 int page_launder(int gfp_mask, int sync)
 {
-       int launder_loop, maxscan, cleaned_pages, maxlaunder;
+       int maxscan, cleaned_pages;
        struct list_head * page_lru;
        struct page * page;
 
-       launder_loop = 0;
-       maxlaunder = 0;
        cleaned_pages = 0;
 
-dirty_page_rescan:
+       /* Will we wait on IO? */
+       if (!sync)
+               gfp_mask &= ~__GFP_WAIT;
+
        spin_lock(&pagemap_lru_lock);
        maxscan = nr_inactive_dirty_pages >> DEF_PRIORITY;
        while ((page_lru = inactive_dirty_list.prev) != &inactive_dirty_list &&
@@ -545,8 +544,8 @@ dirty_page_rescan:
                        if (!writepage)
                                goto page_active;
 
-                       /* First time through? Move it to the back of the list */
-                       if (!launder_loop || !CAN_DO_FS) {
+                       /* Can't do it? Move it to the back of the list */
+                       if (!CAN_DO_FS) {
                                list_del(page_lru);
                                list_add(page_lru, &inactive_dirty_list);
                                UnlockPage(page);
@@ -576,9 +575,9 @@ dirty_page_rescan:
                 * buffer pages
                 */
                if (page->buffers) {
-                       unsigned int buffer_mask;
                        int clearedbuf;
                        int freed_page = 0;
+
                        /*
                         * Since we might be doing disk IO, we have to
                         * drop the spinlock and take an extra reference
@@ -588,16 +587,8 @@ dirty_page_rescan:
                        page_cache_get(page);
                        spin_unlock(&pagemap_lru_lock);
 
-                       /* Will we do (asynchronous) IO? */
-                       if (launder_loop && maxlaunder == 0 && sync)
-                               buffer_mask = gfp_mask;                         /* Do as much as we can */
-                       else if (launder_loop && maxlaunder-- > 0)
-                               buffer_mask = gfp_mask & ~__GFP_WAIT;                   /* Don't wait, async write-out */
-                       else
-                               buffer_mask = gfp_mask & ~(__GFP_WAIT | __GFP_IO);      /* Don't even start IO */
-
                        /* Try to free the page buffers. */
-                       clearedbuf = try_to_free_buffers(page, buffer_mask);
+                       clearedbuf = try_to_free_buffers(page, gfp_mask);
 
                        /*
                         * Re-take the spinlock. Note that we cannot
@@ -660,29 +651,6 @@ page_active:
        }
        spin_unlock(&pagemap_lru_lock);
 
-       /*
-        * If we don't have enough free pages, we loop back once
-        * to queue the dirty pages for writeout. When we were called
-        * by a user process (that /needs/ a free page) and we didn't
-        * free anything yet, we wait synchronously on the writeout of
-        * MAX_SYNC_LAUNDER pages.
-        *
-        * We also wake up bdflush, since bdflush should, under most
-        * loads, flush out the dirty pages before we have to wait on
-        * IO.
-        */
-       if (CAN_DO_IO && !launder_loop && free_shortage()) {
-               launder_loop = 1;
-               /* If we cleaned pages, never do synchronous IO. */
-               if (cleaned_pages)
-                       sync = 0;
-               /* We only do a few "out of order" flushes. */
-               maxlaunder = MAX_LAUNDER;
-               /* Kflushd takes care of the rest. */
-               wakeup_bdflush();
-               goto dirty_page_rescan;
-       }
-
        /* Return the number of pages moved to the inactive_clean list. */
        return cleaned_pages;
 }
@@ -885,6 +853,13 @@ static int do_try_to_free_pages(unsigned int gfp_mask, int user)
 {
        int ret = 0;
 
+       /*
+        * If needed, we move pages from the active list
+        * to the inactive list.
+        */
+       if (inactive_shortage()) 
+               ret += refill_inactive(gfp_mask);
+
        /*
         * If we're low on free pages, move pages from the
         * inactive_dirty list to the inactive_clean list.
@@ -893,19 +868,11 @@ static int do_try_to_free_pages(unsigned int gfp_mask, int user)
         * before we get around to moving them to the other
         * list, so this is a relatively cheap operation.
         */
-
        ret += page_launder(gfp_mask, user);
 
        ret += shrink_dcache_memory(DEF_PRIORITY, gfp_mask);
        ret += shrink_icache_memory(DEF_PRIORITY, gfp_mask);
 
-       /*
-        * If needed, we move pages from the active list
-        * to the inactive list.
-        */
-       if (inactive_shortage()) 
-               ret += refill_inactive(gfp_mask);
-
        /*      
         * Reclaim unused slab cache if memory is low.
         */
@@ -973,8 +940,6 @@ int kswapd(void *unused)
                        refill_inactive_scan(DEF_PRIORITY);
                }
 
-               run_task_queue(&tq_disk);
-
                /* 
                 * We go to sleep if either the free page shortage
                 * or the inactive page shortage is gone. We do this
@@ -987,6 +952,7 @@ int kswapd(void *unused)
                 * we'll be woken up earlier...
                 */
                if (!free_shortage() || !inactive_shortage()) {
+                       run_task_queue(&tq_disk);
                        interruptible_sleep_on_timeout(&kswapd_wait, HZ);
                /*
                 * If we couldn't free enough memory, we see if it was