]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/ide/pci/cmd640.c
slub: Add kmalloc_large_node() to support kmalloc_node fallback
[linux-2.6-omap-h63xx.git] / drivers / ide / pci / cmd640.c
index f369645e4d1645ce91651df6742c78302fc3752b..ec667982809c18ae8ddf59bc5023190134cb33c1 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  linux/drivers/ide/pci/cmd640.c             Version 1.02  Sep 01, 1996
- *
  *  Copyright (C) 1995-1996  Linus Torvalds & authors (see below)
  */
 
 #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/ide.h>
 #include <linux/init.h>
@@ -185,6 +179,8 @@ static u8 recovery_counts[4] = {16, 16, 16, 16}; /* Recovery count (encoded) */
 
 #endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
 
+static DEFINE_SPINLOCK(cmd640_lock);
+
 /*
  * These are initialized to point at the devices we control
  */
@@ -258,12 +254,12 @@ static u8 get_cmd640_reg_vlb (u16 reg)
 
 static u8 get_cmd640_reg(u16 reg)
 {
-       u8 b;
        unsigned long flags;
+       u8 b;
 
-       spin_lock_irqsave(&ide_lock, flags);
+       spin_lock_irqsave(&cmd640_lock, flags);
        b = __get_cmd640_reg(reg);
-       spin_unlock_irqrestore(&ide_lock, flags);
+       spin_unlock_irqrestore(&cmd640_lock, flags);
        return b;
 }
 
@@ -271,9 +267,9 @@ static void put_cmd640_reg(u16 reg, u8 val)
 {
        unsigned long flags;
 
-       spin_lock_irqsave(&ide_lock, flags);
+       spin_lock_irqsave(&cmd640_lock, flags);
        __put_cmd640_reg(reg,val);
-       spin_unlock_irqrestore(&ide_lock, flags);
+       spin_unlock_irqrestore(&cmd640_lock, flags);
 }
 
 static int __init match_pci_cmd640_device (void)
@@ -351,7 +347,7 @@ static int __init secondary_port_responding (void)
 {
        unsigned long flags;
 
-       spin_lock_irqsave(&ide_lock, flags);
+       spin_lock_irqsave(&cmd640_lock, flags);
 
        outb_p(0x0a, 0x170 + IDE_SELECT_OFFSET);        /* select drive0 */
        udelay(100);
@@ -359,11 +355,11 @@ static int __init secondary_port_responding (void)
                outb_p(0x1a, 0x170 + IDE_SELECT_OFFSET); /* select drive1 */
                udelay(100);
                if ((inb_p(0x170 + IDE_SELECT_OFFSET) & 0x1f) != 0x1a) {
-                       spin_unlock_irqrestore(&ide_lock, flags);
+                       spin_unlock_irqrestore(&cmd640_lock, flags);
                        return 0; /* nothing responded */
                }
        }
-       spin_unlock_irqrestore(&ide_lock, flags);
+       spin_unlock_irqrestore(&cmd640_lock, flags);
        return 1; /* success */
 }
 
@@ -440,11 +436,11 @@ static void __init setup_device_ptrs (void)
 static void set_prefetch_mode (unsigned int index, int mode)
 {
        ide_drive_t *drive = cmd_drives[index];
+       unsigned long flags;
        int reg = prefetch_regs[index];
        u8 b;
-       unsigned long flags;
 
-       spin_lock_irqsave(&ide_lock, flags);
+       spin_lock_irqsave(&cmd640_lock, flags);
        b = __get_cmd640_reg(reg);
        if (mode) {     /* want prefetch on? */
 #if CMD640_PREFETCH_MASKS
@@ -460,7 +456,7 @@ static void set_prefetch_mode (unsigned int index, int mode)
                b |= prefetch_masks[index];     /* disable prefetch */
        }
        __put_cmd640_reg(reg, b);
-       spin_unlock_irqrestore(&ide_lock, flags);
+       spin_unlock_irqrestore(&cmd640_lock, flags);
 }
 
 /*
@@ -561,7 +557,7 @@ static void program_drive_counts (unsigned int index)
        /*
         * Now that everything is ready, program the new timings
         */
-       spin_lock_irqsave(&ide_lock, flags);
+       spin_lock_irqsave(&cmd640_lock, flags);
        /*
         * Program the address_setup clocks into ARTTIM reg,
         * and then the active/recovery counts into the DRWTIM reg
@@ -570,7 +566,7 @@ static void program_drive_counts (unsigned int index)
        setup_count |= __get_cmd640_reg(arttim_regs[index]) & 0x3f;
        __put_cmd640_reg(arttim_regs[index], setup_count);
        __put_cmd640_reg(drwtim_regs[index], pack_nibbles(active_count, recovery_count));
-       spin_unlock_irqrestore(&ide_lock, flags);
+       spin_unlock_irqrestore(&cmd640_lock, flags);
 }
 
 /*
@@ -670,20 +666,20 @@ static void cmd640_set_pio_mode(ide_drive_t *drive, const u8 pio)
 
 static int pci_conf1(void)
 {
-       u32 tmp;
        unsigned long flags;
+       u32 tmp;
 
-       spin_lock_irqsave(&ide_lock, flags);
+       spin_lock_irqsave(&cmd640_lock, flags);
        outb(0x01, 0xCFB);
        tmp = inl(0xCF8);
        outl(0x80000000, 0xCF8);
        if (inl(0xCF8) == 0x80000000) {
                outl(tmp, 0xCF8);
-               spin_unlock_irqrestore(&ide_lock, flags);
+               spin_unlock_irqrestore(&cmd640_lock, flags);
                return 1;
        }
        outl(tmp, 0xCF8);
-       spin_unlock_irqrestore(&ide_lock, flags);
+       spin_unlock_irqrestore(&cmd640_lock, flags);
        return 0;
 }
 
@@ -691,22 +687,34 @@ static int pci_conf2(void)
 {
        unsigned long flags;
 
-       spin_lock_irqsave(&ide_lock, flags);
+       spin_lock_irqsave(&cmd640_lock, flags);
        outb(0x00, 0xCFB);
        outb(0x00, 0xCF8);
        outb(0x00, 0xCFA);
        if (inb(0xCF8) == 0x00 && inb(0xCF8) == 0x00) {
-               spin_unlock_irqrestore(&ide_lock, flags);
+               spin_unlock_irqrestore(&cmd640_lock, flags);
                return 1;
        }
-       spin_unlock_irqrestore(&ide_lock, flags);
+       spin_unlock_irqrestore(&cmd640_lock, flags);
        return 0;
 }
 
+static const struct ide_port_info cmd640_port_info __initdata = {
+       .chipset                = ide_cmd640,
+       .host_flags             = IDE_HFLAG_SERIALIZE |
+                                 IDE_HFLAG_NO_DMA |
+                                 IDE_HFLAG_NO_AUTOTUNE |
+                                 IDE_HFLAG_ABUSE_PREFETCH |
+                                 IDE_HFLAG_ABUSE_FAST_DEVSEL,
+#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
+       .pio_mask               = ATA_PIO5,
+#endif
+};
+
 /*
- * Probe for a cmd640 chipset, and initialize it if found.  Called from ide.c
+ * Probe for a cmd640 chipset, and initialize it if found.
  */
-int __init ide_probe_for_cmd640x (void)
+static int __init cmd640x_init(void)
 {
 #ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
        int second_port_toggled = 0;
@@ -715,6 +723,7 @@ int __init ide_probe_for_cmd640x (void)
        const char *bus_type, *port2;
        unsigned int index;
        u8 b, cfr;
+       u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
 
        if (cmd640_vlb && probe_for_cmd640_vlb()) {
                bus_type = "VLB";
@@ -759,14 +768,12 @@ int __init ide_probe_for_cmd640x (void)
        setup_device_ptrs ();
        printk("%s: buggy cmd640%c interface on %s, config=0x%02x\n",
               cmd_hwif0->name, 'a' + cmd640_chip_version - 1, bus_type, cfr);
-       cmd_hwif0->chipset = ide_cmd640;
 #ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
-       cmd_hwif0->host_flags = IDE_HFLAG_ABUSE_PREFETCH |
-                               IDE_HFLAG_ABUSE_FAST_DEVSEL;
-       cmd_hwif0->pio_mask = ATA_PIO5;
        cmd_hwif0->set_pio_mode = &cmd640_set_pio_mode;
 #endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
 
+       idx[0] = cmd_hwif0->index;
+
        /*
         * Ensure compatibility by always using the slowest timings
         * for access to the drive's command register block,
@@ -780,7 +787,8 @@ int __init ide_probe_for_cmd640x (void)
        /*
         * Try to enable the secondary interface, if not already enabled
         */
-       if (cmd_hwif1->noprobe) {
+       if (cmd_hwif1->noprobe ||
+           (cmd_hwif1->drives[0].noprobe && cmd_hwif1->drives[1].noprobe)) {
                port2 = "not probed";
        } else {
                b = get_cmd640_reg(CNTRL);
@@ -812,21 +820,14 @@ int __init ide_probe_for_cmd640x (void)
         * Initialize data for secondary cmd640 port, if enabled
         */
        if (second_port_cmd640) {
-               cmd_hwif0->serialized = 1;
-               cmd_hwif1->serialized = 1;
-               cmd_hwif1->chipset = ide_cmd640;
-               cmd_hwif0->mate = cmd_hwif1;
-               cmd_hwif1->mate = cmd_hwif0;
-               cmd_hwif1->channel = 1;
 #ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
-               cmd_hwif1->host_flags = IDE_HFLAG_ABUSE_PREFETCH |
-                                       IDE_HFLAG_ABUSE_FAST_DEVSEL;
-               cmd_hwif1->pio_mask = ATA_PIO5;
                cmd_hwif1->set_pio_mode = &cmd640_set_pio_mode;
 #endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
+
+               idx[1] = cmd_hwif1->index;
        }
        printk(KERN_INFO "%s: %sserialized, secondary interface %s\n", cmd_hwif1->name,
-               cmd_hwif0->serialized ? "" : "not ", port2);
+                        second_port_cmd640 ? "" : "not ", port2);
 
        /*
         * Establish initial timings/prefetch for all drives.
@@ -870,6 +871,13 @@ int __init ide_probe_for_cmd640x (void)
 #ifdef CMD640_DUMP_REGS
        cmd640_dump_regs();
 #endif
+
+       ide_device_add(idx, &cmd640_port_info);
+
        return 1;
 }
 
+module_param_named(probe_vlb, cmd640_vlb, bool, 0);
+MODULE_PARM_DESC(probe_vlb, "probe for VLB version of CMD640 chipset");
+
+module_init(cmd640x_init);