Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/x86/linux...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 26 Apr 2008 16:50:58 +0000 (09:50 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 26 Apr 2008 16:50:58 +0000 (09:50 -0700)
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/x86/linux-2.6-x86-fixes:
  x86 PAT: decouple from nonpromisc devmem
  x86 PAT: tone down debugging messages

180 files changed:
arch/x86/Kconfig
arch/x86/Kconfig.cpu
arch/x86/Kconfig.debug
arch/x86/configs/i386_defconfig
arch/x86/configs/x86_64_defconfig
arch/x86/ia32/ia32_signal.c
arch/x86/ia32/ia32entry.S
arch/x86/kernel/acpi/boot.c
arch/x86/kernel/apic_32.c
arch/x86/kernel/apic_64.c
arch/x86/kernel/cpu/Makefile
arch/x86/kernel/cpu/amd.c
arch/x86/kernel/cpu/mcheck/mce_64.c
arch/x86/kernel/cpu/nexgen.c [deleted file]
arch/x86/kernel/cpu/perfctr-watchdog.c
arch/x86/kernel/genapic_64.c
arch/x86/kernel/head64.c
arch/x86/kernel/hpet.c
arch/x86/kernel/i8253.c
arch/x86/kernel/io_apic_32.c
arch/x86/kernel/io_apic_64.c
arch/x86/kernel/irq_32.c
arch/x86/kernel/mfgpt_32.c
arch/x86/kernel/mpparse.c
arch/x86/kernel/pci-calgary_64.c
arch/x86/kernel/ptrace.c
arch/x86/kernel/setup_32.c
arch/x86/kernel/setup_64.c
arch/x86/kernel/signal_32.c
arch/x86/kernel/signal_64.c
arch/x86/kernel/smpboot.c
arch/x86/kernel/summit_32.c
arch/x86/kernel/tlb_64.c
arch/x86/kernel/trampoline_32.S
arch/x86/kernel/traps_32.c
arch/x86/mach-voyager/voyager_smp.c
arch/x86/mm/init_32.c
arch/x86/xen/smp.c
drivers/char/agp/amd-k7-agp.c
drivers/char/agp/frontend.c
drivers/char/drm/ati_pcigart.c
drivers/char/drm/drm.h
drivers/char/drm/drmP.h
drivers/char/drm/drm_agpsupport.c
drivers/char/drm/drm_drv.c
drivers/char/drm/drm_fops.c
drivers/char/drm/drm_irq.c
drivers/char/drm/drm_proc.c
drivers/char/drm/drm_stub.c
drivers/char/drm/drm_sysfs.c
drivers/char/drm/drm_vm.c
drivers/char/drm/i810_dma.c
drivers/char/drm/i830_dma.c
drivers/char/drm/i915_dma.c
drivers/char/drm/i915_drm.h
drivers/char/drm/i915_drv.c
drivers/char/drm/i915_drv.h
drivers/char/drm/i915_irq.c
drivers/char/drm/mga_drv.c
drivers/char/drm/mga_drv.h
drivers/char/drm/mga_irq.c
drivers/char/drm/r128_drv.c
drivers/char/drm/r128_drv.h
drivers/char/drm/r128_irq.c
drivers/char/drm/radeon_drv.c
drivers/char/drm/radeon_drv.h
drivers/char/drm/radeon_irq.c
drivers/char/drm/via_drv.c
drivers/char/drm/via_drv.h
drivers/char/drm/via_irq.c
drivers/ide/Kconfig
drivers/ide/arm/bast-ide.c
drivers/ide/arm/icside.c
drivers/ide/arm/ide_arm.c
drivers/ide/arm/palm_bk3710.c
drivers/ide/arm/rapide.c
drivers/ide/cris/ide-cris.c
drivers/ide/h8300/ide-h8300.c
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-generic.c
drivers/ide/ide-io.c
drivers/ide/ide-lib.c
drivers/ide/ide-pnp.c
drivers/ide/ide-probe.c
drivers/ide/ide-proc.c
drivers/ide/ide.c
drivers/ide/legacy/ali14xx.c
drivers/ide/legacy/buddha.c
drivers/ide/legacy/dtc2278.c
drivers/ide/legacy/falconide.c
drivers/ide/legacy/gayle.c
drivers/ide/legacy/hd.c
drivers/ide/legacy/ht6560b.c
drivers/ide/legacy/ide-4drives.c
drivers/ide/legacy/ide-cs.c
drivers/ide/legacy/ide_platform.c
drivers/ide/legacy/macide.c
drivers/ide/legacy/q40ide.c
drivers/ide/legacy/qd65xx.c
drivers/ide/legacy/qd65xx.h
drivers/ide/legacy/umc8672.c
drivers/ide/mips/au1xxx-ide.c
drivers/ide/mips/swarm.c
drivers/ide/pci/aec62xx.c
drivers/ide/pci/alim15x3.c
drivers/ide/pci/amd74xx.c
drivers/ide/pci/atiixp.c
drivers/ide/pci/cmd640.c
drivers/ide/pci/cmd64x.c
drivers/ide/pci/cs5520.c
drivers/ide/pci/cs5530.c
drivers/ide/pci/cs5535.c
drivers/ide/pci/cy82c693.c
drivers/ide/pci/delkin_cb.c
drivers/ide/pci/generic.c
drivers/ide/pci/hpt34x.c
drivers/ide/pci/hpt366.c
drivers/ide/pci/it8213.c
drivers/ide/pci/it821x.c
drivers/ide/pci/jmicron.c
drivers/ide/pci/ns87415.c
drivers/ide/pci/opti621.c
drivers/ide/pci/piix.c
drivers/ide/pci/rz1000.c
drivers/ide/pci/sc1200.c
drivers/ide/pci/scc_pata.c
drivers/ide/pci/serverworks.c
drivers/ide/pci/sgiioc4.c
drivers/ide/pci/siimage.c
drivers/ide/pci/sis5513.c
drivers/ide/pci/sl82c105.c
drivers/ide/pci/slc90e66.c
drivers/ide/pci/tc86c001.c
drivers/ide/pci/triflex.c
drivers/ide/pci/trm290.c
drivers/ide/pci/via82cxxx.c
drivers/ide/ppc/mpc8xx.c
drivers/ide/ppc/pmac.c
drivers/ide/setup-pci.c
drivers/media/dvb/frontends/Kconfig
drivers/media/dvb/frontends/Makefile
drivers/media/dvb/frontends/mt312.h
drivers/media/dvb/frontends/s5h1411.c [new file with mode: 0644]
drivers/media/dvb/frontends/s5h1411.h [new file with mode: 0644]
drivers/media/video/au0828/Kconfig
drivers/media/video/au0828/au0828-cards.c
drivers/media/video/au0828/au0828-core.c
drivers/media/video/au0828/au0828-dvb.c
drivers/media/video/au0828/au0828-i2c.c
drivers/media/video/au0828/au0828.h
drivers/media/video/cx88/Kconfig
drivers/media/video/cx88/cx88-blackbird.c
drivers/media/video/cx88/cx88-cards.c
drivers/media/video/cx88/cx88-dvb.c
drivers/media/video/em28xx/em28xx-core.c
drivers/media/video/ir-kbd-i2c.c
drivers/media/video/pvrusb2/Kconfig
drivers/media/video/pvrusb2/pvrusb2-devattr.c
drivers/media/video/pvrusb2/pvrusb2-devattr.h
drivers/media/video/tuner-core.c
drivers/media/video/tuner-xc2028.c
drivers/media/video/vivi.c
include/asm-x86/bios_ebda.h
include/asm-x86/io_apic.h
include/asm-x86/mach-default/smpboot_hooks.h
include/asm-x86/pgtable_32.h
include/asm-x86/posix_types.h
include/asm-x86/processor.h
include/asm-x86/ptrace.h
include/asm-x86/rio.h
include/asm-x86/unistd.h
include/linux/Kbuild
include/linux/compiler-gcc.h
include/linux/hdsmart.h [deleted file]
include/linux/ide.h
kernel/fork.c

index 4aa4180..2fadf79 100644 (file)
@@ -142,6 +142,9 @@ config AUDIT_ARCH
 config ARCH_SUPPORTS_AOUT
        def_bool y
 
+config ARCH_SUPPORTS_OPTIMIZED_INLINING
+       def_bool y
+
 # Use the generic interrupt handling code in kernel/irq/:
 config GENERIC_HARDIRQS
        bool
index 57072f2..4da3cdb 100644 (file)
@@ -21,8 +21,8 @@ config M386
 
          Here are the settings recommended for greatest speed:
          - "386" for the AMD/Cyrix/Intel 386DX/DXL/SL/SLC/SX, Cyrix/TI
-         486DLC/DLC2, UMC 486SX-S and NexGen Nx586.  Only "386" kernels
-         will run on a 386 class machine.
+         486DLC/DLC2, and UMC 486SX-S.  Only "386" kernels will run on a 386
+         class machine.
          - "486" for the AMD/Cyrix/IBM/Intel 486DX/DX2/DX4 or
          SL/SLC/SLC2/SLC3/SX/SX2 and UMC U5D or U5S.
          - "586" for generic Pentium CPUs lacking the TSC
index 239fd9f..5b1979a 100644 (file)
@@ -257,3 +257,16 @@ config CPA_DEBUG
          Do change_page_attr() self-tests every 30 seconds.
 
 endmenu
+
+config OPTIMIZE_INLINING
+       bool "Allow gcc to uninline functions marked 'inline'"
+       default y
+       help
+         This option determines if the kernel forces gcc to inline the functions
+         developers have marked 'inline'. Doing so takes away freedom from gcc to
+         do what it thinks is best, which is desirable for the gcc 3.x series of
+         compilers. The gcc 4.x series have a rewritten inlining algorithm and
+         disabling this option will generate a smaller kernel there. Hopefully
+         this algorithm is so good that allowing gcc4 to make the decision can
+         become the default in the future, until then this option is there to
+         test gcc for this.
index 3df340b..ad7ddaa 100644 (file)
@@ -1421,6 +1421,7 @@ CONFIG_DEBUG_BUGVERBOSE=y
 # CONFIG_DEBUG_VM is not set
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_FRAME_POINTER is not set
+CONFIG_OPTIMIZE_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_LKDTM is not set
 # CONFIG_FAULT_INJECTION is not set
index eef98cb..2d6f5b2 100644 (file)
@@ -1346,6 +1346,7 @@ CONFIG_DEBUG_BUGVERBOSE=y
 # CONFIG_DEBUG_VM is not set
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_FRAME_POINTER is not set
+CONFIG_OPTIMIZE_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_LKDTM is not set
 # CONFIG_FAULT_INJECTION is not set
index 05e155d..bbed3a2 100644 (file)
@@ -499,11 +499,6 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka,
        regs->cs = __USER32_CS;
        regs->ss = __USER32_DS;
 
-       set_fs(USER_DS);
-       regs->flags &= ~(X86_EFLAGS_TF | X86_EFLAGS_DF);
-       if (test_thread_flag(TIF_SINGLESTEP))
-               ptrace_notify(SIGTRAP);
-
 #if DEBUG_SIG
        printk(KERN_DEBUG "SIG deliver (%s:%d): sp=%p pc=%lx ra=%u\n",
               current->comm, current->pid, frame, regs->ip, frame->pretcode);
@@ -599,11 +594,6 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
        regs->cs = __USER32_CS;
        regs->ss = __USER32_DS;
 
-       set_fs(USER_DS);
-       regs->flags &= ~(X86_EFLAGS_TF | X86_EFLAGS_DF);
-       if (test_thread_flag(TIF_SINGLESTEP))
-               ptrace_notify(SIGTRAP);
-
 #if DEBUG_SIG
        printk(KERN_DEBUG "SIG deliver (%s:%d): sp=%p pc=%lx ra=%u\n",
               current->comm, current->pid, frame, regs->ip, frame->pretcode);
index ae7158b..b5e329d 100644 (file)
@@ -430,7 +430,7 @@ ia32_sys_call_table:
        .quad sys_setuid16
        .quad sys_getuid16
        .quad compat_sys_stime  /* stime */             /* 25 */
-       .quad sys32_ptrace      /* ptrace */
+       .quad compat_sys_ptrace /* ptrace */
        .quad sys_alarm
        .quad sys_fstat /* (old)fstat */
        .quad sys_pause
index 057ccf1..977ed5c 100644 (file)
@@ -697,10 +697,6 @@ static int __init acpi_parse_hpet(struct acpi_table_header *table)
 #define HPET_RESOURCE_NAME_SIZE 9
        hpet_res = alloc_bootmem(sizeof(*hpet_res) + HPET_RESOURCE_NAME_SIZE);
 
-       if (!hpet_res)
-               return 0;
-
-       memset(hpet_res, 0, sizeof(*hpet_res));
        hpet_res->name = (void *)&hpet_res[1];
        hpet_res->flags = IORESOURCE_MEM;
        snprintf((char *)hpet_res->name, HPET_RESOURCE_NAME_SIZE, "HPET %u",
index 8317401..4b99b1b 100644 (file)
@@ -451,7 +451,8 @@ void __init setup_boot_APIC_clock(void)
        }
 
        /* Calculate the scaled math multiplication factor */
-       lapic_clockevent.mult = div_sc(delta, TICK_NSEC * LAPIC_CAL_LOOPS, 32);
+       lapic_clockevent.mult = div_sc(delta, TICK_NSEC * LAPIC_CAL_LOOPS,
+                                      lapic_clockevent.shift);
        lapic_clockevent.max_delta_ns =
                clockevent_delta2ns(0x7FFFFF, &lapic_clockevent);
        lapic_clockevent.min_delta_ns =
index bf83157..5910020 100644 (file)
@@ -360,7 +360,8 @@ static void __init calibrate_APIC_clock(void)
                result / 1000 / 1000, result / 1000 % 1000);
 
        /* Calculate the scaled math multiplication factor */
-       lapic_clockevent.mult = div_sc(result, NSEC_PER_SEC, 32);
+       lapic_clockevent.mult = div_sc(result, NSEC_PER_SEC,
+                                      lapic_clockevent.shift);
        lapic_clockevent.max_delta_ns =
                clockevent_delta2ns(0x7FFFFF, &lapic_clockevent);
        lapic_clockevent.min_delta_ns =
index ee7c452..a0c6f81 100644 (file)
@@ -11,7 +11,6 @@ obj-$(CONFIG_X86_32)  += cyrix.o
 obj-$(CONFIG_X86_32)   += centaur.o
 obj-$(CONFIG_X86_32)   += transmeta.o
 obj-$(CONFIG_X86_32)   += intel.o
-obj-$(CONFIG_X86_32)   += nexgen.o
 obj-$(CONFIG_X86_32)   += umc.o
 
 obj-$(CONFIG_X86_MCE)  += mcheck/
index 0173065..2458668 100644 (file)
@@ -343,10 +343,4 @@ static struct cpu_dev amd_cpu_dev __cpuinitdata = {
        .c_size_cache   = amd_size_cache,
 };
 
-int __init amd_init_cpu(void)
-{
-       cpu_devs[X86_VENDOR_AMD] = &amd_cpu_dev;
-       return 0;
-}
-
 cpu_vendor_dev_register(X86_VENDOR_AMD, &amd_cpu_dev);
index 9a699ed..e07e8c0 100644 (file)
@@ -49,7 +49,7 @@ static int banks;
 static unsigned long bank[NR_BANKS] = { [0 ... NR_BANKS-1] = ~0UL };
 static unsigned long notify_user;
 static int rip_msr;
-static int mce_bootlog = 1;
+static int mce_bootlog = -1;
 static atomic_t mce_events;
 
 static char trigger[128];
@@ -471,13 +471,15 @@ static void mce_init(void *dummy)
 static void __cpuinit mce_cpu_quirks(struct cpuinfo_x86 *c)
 {
        /* This should be disabled by the BIOS, but isn't always */
-       if (c->x86_vendor == X86_VENDOR_AMD && c->x86 == 15) {
-               /* disable GART TBL walk error reporting, which trips off
-                  incorrectly with the IOMMU & 3ware & Cerberus. */
-               clear_bit(10, &bank[4]);
-               /* Lots of broken BIOS around that don't clear them
-                  by default and leave crap in there. Don't log. */
-               mce_bootlog = 0;
+       if (c->x86_vendor == X86_VENDOR_AMD) {
+               if(c->x86 == 15)
+                       /* disable GART TBL walk error reporting, which trips off
+                          incorrectly with the IOMMU & 3ware & Cerberus. */
+                       clear_bit(10, &bank[4]);
+               if(c->x86 <= 17 && mce_bootlog < 0)
+                       /* Lots of broken BIOS around that don't clear them
+                          by default and leave crap in there. Don't log. */
+                       mce_bootlog = 0;
        }
 
 }
diff --git a/arch/x86/kernel/cpu/nexgen.c b/arch/x86/kernel/cpu/nexgen.c
deleted file mode 100644 (file)
index 5d5e1c1..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/string.h>
-#include <asm/processor.h>
-
-#include "cpu.h"
-
-/*
- *     Detect a NexGen CPU running without BIOS hypercode new enough
- *     to have CPUID. (Thanks to Herbert Oppmann)
- */
-
-static int __cpuinit deep_magic_nexgen_probe(void)
-{
-       int ret;
-
-       __asm__ __volatile__ (
-               "       movw    $0x5555, %%ax\n"
-               "       xorw    %%dx,%%dx\n"
-               "       movw    $2, %%cx\n"
-               "       divw    %%cx\n"
-               "       movl    $0, %%eax\n"
-               "       jnz     1f\n"
-               "       movl    $1, %%eax\n"
-               "1:\n"
-               : "=a" (ret) : : "cx", "dx");
-       return  ret;
-}
-
-static void __cpuinit init_nexgen(struct cpuinfo_x86 *c)
-{
-       c->x86_cache_size = 256; /* A few had 1 MB... */
-}
-
-static void __cpuinit nexgen_identify(struct cpuinfo_x86 *c)
-{
-       /* Detect NexGen with old hypercode */
-       if (deep_magic_nexgen_probe())
-               strcpy(c->x86_vendor_id, "NexGenDriven");
-}
-
-static struct cpu_dev nexgen_cpu_dev __cpuinitdata = {
-       .c_vendor       = "Nexgen",
-       .c_ident        = { "NexGenDriven" },
-       .c_models = {
-                       { .vendor = X86_VENDOR_NEXGEN,
-                         .family = 5,
-                         .model_names = { [1] = "Nx586" }
-                       },
-       },
-       .c_init         = init_nexgen,
-       .c_identify     = nexgen_identify,
-};
-
-int __init nexgen_init_cpu(void)
-{
-       cpu_devs[X86_VENDOR_NEXGEN] = &nexgen_cpu_dev;
-       return 0;
-}
index b943e10..f9ae93a 100644 (file)
@@ -614,16 +614,6 @@ static struct wd_ops intel_arch_wd_ops __read_mostly = {
        .evntsel = MSR_ARCH_PERFMON_EVENTSEL1,
 };
 
-static struct wd_ops coreduo_wd_ops = {
-       .reserve = single_msr_reserve,
-       .unreserve = single_msr_unreserve,
-       .setup = setup_intel_arch_watchdog,
-       .rearm = p6_rearm,
-       .stop = single_msr_stop_watchdog,
-       .perfctr = MSR_ARCH_PERFMON_PERFCTR0,
-       .evntsel = MSR_ARCH_PERFMON_EVENTSEL0,
-};
-
 static void probe_nmi_watchdog(void)
 {
        switch (boot_cpu_data.x86_vendor) {
@@ -637,8 +627,8 @@ static void probe_nmi_watchdog(void)
                /* Work around Core Duo (Yonah) errata AE49 where perfctr1
                   doesn't have a working enable bit. */
                if (boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model == 14) {
-                       wd_ops = &coreduo_wd_ops;
-                       break;
+                       intel_arch_wd_ops.perfctr = MSR_ARCH_PERFMON_PERFCTR0;
+                       intel_arch_wd_ops.evntsel = MSR_ARCH_PERFMON_EVENTSEL0;
                }
                if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) {
                        wd_ops = &intel_arch_wd_ops;
index 9546ef4..021624c 100644 (file)
@@ -51,7 +51,7 @@ void __init setup_apic_routing(void)
        else
 #endif
 
-       if (cpus_weight(cpu_possible_map) <= 8)
+       if (num_possible_cpus() <= 8)
                genapic = &apic_flat;
        else
                genapic = &apic_physflat;
index 993c767..d31d6b7 100644 (file)
@@ -22,6 +22,7 @@
 #include <asm/sections.h>
 #include <asm/kdebug.h>
 #include <asm/e820.h>
+#include <asm/bios_ebda.h>
 
 static void __init zap_identity_mappings(void)
 {
@@ -49,7 +50,6 @@ static void __init copy_bootdata(char *real_mode_data)
        }
 }
 
-#define BIOS_EBDA_SEGMENT 0x40E
 #define BIOS_LOWMEM_KILOBYTES 0x413
 
 /*
@@ -80,8 +80,7 @@ static void __init reserve_ebda_region(void)
        lowmem <<= 10;
 
        /* start of EBDA area */
-       ebda_addr = *(unsigned short *)__va(BIOS_EBDA_SEGMENT);
-       ebda_addr <<= 4;
+       ebda_addr = get_bios_ebda();
 
        /* Fixup: bios puts an EBDA in the top 64K segment */
        /* of conventional memory, but does not adjust lowmem. */
index 36652ea..9007f9e 100644 (file)
@@ -218,7 +218,7 @@ static void hpet_legacy_clockevent_register(void)
        hpet_freq = 1000000000000000ULL;
        do_div(hpet_freq, hpet_period);
        hpet_clockevent.mult = div_sc((unsigned long) hpet_freq,
-                                     NSEC_PER_SEC, 32);
+                                     NSEC_PER_SEC, hpet_clockevent.shift);
        /* Calculate the min / max delta */
        hpet_clockevent.max_delta_ns = clockevent_delta2ns(0x7FFFFFFF,
                                                           &hpet_clockevent);
index 8540abe..c1b5e3e 100644 (file)
@@ -115,7 +115,8 @@ void __init setup_pit_timer(void)
         * IO_APIC has been initialized.
         */
        pit_clockevent.cpumask = cpumask_of_cpu(smp_processor_id());
-       pit_clockevent.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC, 32);
+       pit_clockevent.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC,
+                                    pit_clockevent.shift);
        pit_clockevent.max_delta_ns =
                clockevent_delta2ns(0x7FFF, &pit_clockevent);
        pit_clockevent.min_delta_ns =
@@ -224,7 +225,8 @@ static int __init init_pit_clocksource(void)
            pit_clockevent.mode != CLOCK_EVT_MODE_PERIODIC)
                return 0;
 
-       clocksource_pit.mult = clocksource_hz2mult(CLOCK_TICK_RATE, 20);
+       clocksource_pit.mult = clocksource_hz2mult(CLOCK_TICK_RATE,
+                                                  clocksource_pit.shift);
        return clocksource_register(&clocksource_pit);
 }
 arch_initcall(init_pit_clocksource);
index 2e2f420..696b8e4 100644 (file)
@@ -2068,7 +2068,7 @@ static void __init setup_nmi(void)
  * cycles as some i82489DX-based boards have glue logic that keeps the
  * 8259A interrupt line asserted until INTA.  --macro
  */
-static inline void unlock_ExtINT_logic(void)
+static inline void __init unlock_ExtINT_logic(void)
 {
        int apic, pin, i;
        struct IO_APIC_route_entry entry0, entry1;
index 9ba11d0..ef1a8df 100644 (file)
@@ -1599,7 +1599,7 @@ static void __init setup_nmi(void)
  * cycles as some i82489DX-based boards have glue logic that keeps the
  * 8259A interrupt line asserted until INTA.  --macro
  */
-static inline void unlock_ExtINT_logic(void)
+static inline void __init unlock_ExtINT_logic(void)
 {
        int apic, pin, i;
        struct IO_APIC_route_entry entry0, entry1;
index 6ea67b7..00bda7b 100644 (file)
@@ -134,7 +134,7 @@ unsigned int do_IRQ(struct pt_regs *regs)
                        : "=a" (arg1), "=d" (arg2), "=b" (bx)
                        :  "0" (irq),   "1" (desc),  "2" (isp),
                           "D" (desc->handle_irq)
-                       : "memory", "cc"
+                       : "memory", "cc", "ecx"
                );
        } else
 #endif
index b402c0f..cfc2648 100644 (file)
@@ -364,7 +364,8 @@ int __init mfgpt_timer_setup(void)
        geode_mfgpt_write(mfgpt_event_clock, MFGPT_REG_SETUP, val);
 
        /* Set up the clock event */
-       mfgpt_clockevent.mult = div_sc(MFGPT_HZ, NSEC_PER_SEC, 32);
+       mfgpt_clockevent.mult = div_sc(MFGPT_HZ, NSEC_PER_SEC,
+                                      mfgpt_clockevent.shift);
        mfgpt_clockevent.min_delta_ns = clockevent_delta2ns(0xF,
                        &mfgpt_clockevent);
        mfgpt_clockevent.max_delta_ns = clockevent_delta2ns(0xFFFE,
index 70744e3..3e2c54d 100644 (file)
@@ -686,13 +686,11 @@ void __init get_smp_config(void)
 static int __init smp_scan_config(unsigned long base, unsigned long length,
                                  unsigned reserve)
 {
-       extern void __bad_mpf_size(void);
        unsigned int *bp = phys_to_virt(base);
        struct intel_mp_floating *mpf;
 
        Dprintk("Scan SMP from %p for %ld bytes.\n", bp, length);
-       if (sizeof(*mpf) != 16)
-               __bad_mpf_size();
+       BUILD_BUG_ON(sizeof(*mpf) != 16);
 
        while (length > 0) {
                mpf = (struct intel_mp_floating *)bp;
@@ -801,7 +799,6 @@ void __init find_smp_config(void)
 #ifdef CONFIG_X86_IO_APIC
 
 #define MP_ISA_BUS             0
-#define MP_MAX_IOAPIC_PIN      127
 
 extern struct mp_ioapic_routing mp_ioapic_routing[MAX_IO_APICS];
 
@@ -820,7 +817,7 @@ static int mp_find_ioapic(int gsi)
        return -1;
 }
 
-static u8 uniq_ioapic_id(u8 id)
+static u8 __init uniq_ioapic_id(u8 id)
 {
 #ifdef CONFIG_X86_32
        if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) &&
@@ -909,14 +906,7 @@ void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi)
        intsrc.mpc_dstapic = mp_ioapics[ioapic].mpc_apicid;     /* APIC ID */
        intsrc.mpc_dstirq = pin;        /* INTIN# */
 
-       Dprintk("Int: type %d, pol %d, trig %d, bus %d, irq %d, %d-%d\n",
-               intsrc.mpc_irqtype, intsrc.mpc_irqflag & 3,
-               (intsrc.mpc_irqflag >> 2) & 3, intsrc.mpc_srcbus,
-               intsrc.mpc_srcbusirq, intsrc.mpc_dstapic, intsrc.mpc_dstirq);
-
-       mp_irqs[mp_irq_entries] = intsrc;
-       if (++mp_irq_entries == MAX_IRQ_SOURCES)
-               panic("Max # of irq sources exceeded!\n");
+       MP_intsrc_info(&intsrc);
 }
 
 int es7000_plat;
@@ -985,23 +975,14 @@ void __init mp_config_acpi_legacy_irqs(void)
                intsrc.mpc_srcbusirq = i;       /* Identity mapped */
                intsrc.mpc_dstirq = i;
 
-               Dprintk("Int: type %d, pol %d, trig %d, bus %d, irq %d, "
-                       "%d-%d\n", intsrc.mpc_irqtype, intsrc.mpc_irqflag & 3,
-                       (intsrc.mpc_irqflag >> 2) & 3, intsrc.mpc_srcbus,
-                       intsrc.mpc_srcbusirq, intsrc.mpc_dstapic,
-                       intsrc.mpc_dstirq);
-
-               mp_irqs[mp_irq_entries] = intsrc;
-               if (++mp_irq_entries == MAX_IRQ_SOURCES)
-                       panic("Max # of irq sources exceeded!\n");
+               MP_intsrc_info(&intsrc);
        }
 }
 
 int mp_register_gsi(u32 gsi, int triggering, int polarity)
 {
-       int ioapic = -1;
-       int ioapic_pin = 0;
-       int idx, bit = 0;
+       int ioapic;
+       int ioapic_pin;
 #ifdef CONFIG_X86_32
 #define MAX_GSI_NUM    4096
 #define IRQ_COMPRESSION_START  64
@@ -1041,15 +1022,13 @@ int mp_register_gsi(u32 gsi, int triggering, int polarity)
         * with redundant pin->gsi mappings (but unique PCI devices);
         * we only program the IOAPIC on the first.
         */
-       bit = ioapic_pin % 32;
-       idx = (ioapic_pin < 32) ? 0 : (ioapic_pin / 32);
-       if (idx > 3) {
+       if (ioapic_pin > MP_MAX_IOAPIC_PIN) {
                printk(KERN_ERR "Invalid reference to IOAPIC pin "
                       "%d-%d\n", mp_ioapic_routing[ioapic].apic_id,
                       ioapic_pin);
                return gsi;
        }
-       if ((1 << bit) & mp_ioapic_routing[ioapic].pin_programmed[idx]) {
+       if (test_bit(ioapic_pin, mp_ioapic_routing[ioapic].pin_programmed)) {
                Dprintk(KERN_DEBUG "Pin %d-%d already programmed\n",
                        mp_ioapic_routing[ioapic].apic_id, ioapic_pin);
 #ifdef CONFIG_X86_32
@@ -1059,7 +1038,7 @@ int mp_register_gsi(u32 gsi, int triggering, int polarity)
 #endif
        }
 
-       mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1 << bit);
+       set_bit(ioapic_pin, mp_ioapic_routing[ioapic].pin_programmed);
 #ifdef CONFIG_X86_32
        /*
         * For GSI >= 64, use IRQ compression
index 2edee22..e28ec49 100644 (file)
@@ -43,6 +43,7 @@
 #include <asm/system.h>
 #include <asm/dma.h>
 #include <asm/rio.h>
+#include <asm/bios_ebda.h>
 
 #ifdef CONFIG_CALGARY_IOMMU_ENABLED_BY_DEFAULT
 int use_calgary __read_mostly = 1;
index 559c1b0..fb03ef3 100644 (file)
@@ -1207,97 +1207,16 @@ static int genregs32_set(struct task_struct *target,
        return ret;
 }
 
-static long ptrace32_siginfo(unsigned request, u32 pid, u32 addr, u32 data)
+long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
+                       compat_ulong_t caddr, compat_ulong_t cdata)
 {
-       siginfo_t __user *si = compat_alloc_user_space(sizeof(siginfo_t));
-       compat_siginfo_t __user *si32 = compat_ptr(data);
-       siginfo_t ssi;
-       int ret;
-
-       if (request == PTRACE_SETSIGINFO) {
-               memset(&ssi, 0, sizeof(siginfo_t));
-               ret = copy_siginfo_from_user32(&ssi, si32);
-               if (ret)
-                       return ret;
-               if (copy_to_user(si, &ssi, sizeof(siginfo_t)))
-                       return -EFAULT;
-       }
-       ret = sys_ptrace(request, pid, addr, (unsigned long)si);
-       if (ret)
-               return ret;
-       if (request == PTRACE_GETSIGINFO) {
-               if (copy_from_user(&ssi, si, sizeof(siginfo_t)))
-                       return -EFAULT;
-               ret = copy_siginfo_to_user32(si32, &ssi);
-       }
-       return ret;
-}
-
-asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data)
-{
-       struct task_struct *child;
-       struct pt_regs *childregs;
+       unsigned long addr = caddr;
+       unsigned long data = cdata;
        void __user *datap = compat_ptr(data);
        int ret;
        __u32 val;
 
        switch (request) {
-       case PTRACE_TRACEME:
-       case PTRACE_ATTACH:
-       case PTRACE_KILL:
-       case PTRACE_CONT:
-       case PTRACE_SINGLESTEP:
-       case PTRACE_SINGLEBLOCK:
-       case PTRACE_DETACH:
-       case PTRACE_SYSCALL:
-       case PTRACE_OLDSETOPTIONS:
-       case PTRACE_SETOPTIONS:
-       case PTRACE_SET_THREAD_AREA:
-       case PTRACE_GET_THREAD_AREA:
-#ifdef X86_BTS
-       case PTRACE_BTS_CONFIG:
-       case PTRACE_BTS_STATUS:
-       case PTRACE_BTS_SIZE:
-       case PTRACE_BTS_GET:
-       case PTRACE_BTS_CLEAR:
-       case PTRACE_BTS_DRAIN:
-#endif
-               return sys_ptrace(request, pid, addr, data);
-
-       default:
-               return -EINVAL;
-
-       case PTRACE_PEEKTEXT:
-       case PTRACE_PEEKDATA:
-       case PTRACE_POKEDATA:
-       case PTRACE_POKETEXT:
-       case PTRACE_POKEUSR:
-       case PTRACE_PEEKUSR:
-       case PTRACE_GETREGS:
-       case PTRACE_SETREGS:
-       case PTRACE_SETFPREGS:
-       case PTRACE_GETFPREGS:
-       case PTRACE_SETFPXREGS:
-       case PTRACE_GETFPXREGS:
-       case PTRACE_GETEVENTMSG:
-               break;
-
-       case PTRACE_SETSIGINFO:
-       case PTRACE_GETSIGINFO:
-               return ptrace32_siginfo(request, pid, addr, data);
-       }
-
-       child = ptrace_get_task_struct(pid);
-       if (IS_ERR(child))
-               return PTR_ERR(child);
-
-       ret = ptrace_check_attach(child, request == PTRACE_KILL);
-       if (ret < 0)
-               goto out;
-
-       childregs = task_pt_regs(child);
-
-       switch (request) {
        case PTRACE_PEEKUSR:
                ret = getreg32(child, addr, &val);
                if (ret == 0)
@@ -1343,12 +1262,14 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data)
                                             sizeof(struct user32_fxsr_struct),
                                             datap);
 
+       case PTRACE_GET_THREAD_AREA:
+       case PTRACE_SET_THREAD_AREA:
+               return arch_ptrace(child, request, addr, data);
+
        default:
                return compat_ptrace_request(child, request, addr, data);
        }
 
- out:
-       put_task_struct(child);
        return ret;
 }
 
index 455d3c8..44cc9b9 100644 (file)
@@ -389,7 +389,6 @@ unsigned long __init find_max_low_pfn(void)
        return max_low_pfn;
 }
 
-#define BIOS_EBDA_SEGMENT 0x40E
 #define BIOS_LOWMEM_KILOBYTES 0x413
 
 /*
@@ -420,8 +419,7 @@ static void __init reserve_ebda_region(void)
        lowmem <<= 10;
 
        /* start of EBDA area */
-       ebda_addr = *(unsigned short *)__va(BIOS_EBDA_SEGMENT);
-       ebda_addr <<= 4;
+       ebda_addr = get_bios_ebda();
 
        /* Fixup: bios puts an EBDA in the top 64K segment */
        /* of conventional memory, but does not adjust lowmem. */
index c2ec3dc..17bdf23 100644 (file)
@@ -116,7 +116,7 @@ extern int root_mountflags;
 
 char __initdata command_line[COMMAND_LINE_SIZE];
 
-struct resource standard_io_resources[] = {
+static struct resource standard_io_resources[] = {
        { .name = "dma1", .start = 0x00, .end = 0x1f,
                .flags = IORESOURCE_BUSY | IORESOURCE_IO },
        { .name = "pic1", .start = 0x20, .end = 0x21,
index f1b1179..8e05e7f 100644 (file)
@@ -413,16 +413,6 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
        regs->ss = __USER_DS;
        regs->cs = __USER_CS;
 
-       /*
-        * Clear TF when entering the signal handler, but
-        * notify any tracer that was single-stepping it.
-        * The tracer may want to single-step inside the
-        * handler too.
-        */
-       regs->flags &= ~(X86_EFLAGS_TF | X86_EFLAGS_DF);
-       if (test_thread_flag(TIF_SINGLESTEP))
-               ptrace_notify(SIGTRAP);
-
        return 0;
 
 give_sigsegv:
@@ -501,16 +491,6 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
        regs->ss = __USER_DS;
        regs->cs = __USER_CS;
 
-       /*
-        * Clear TF when entering the signal handler, but
-        * notify any tracer that was single-stepping it.
-        * The tracer may want to single-step inside the
-        * handler too.
-        */
-       regs->flags &= ~(X86_EFLAGS_TF | X86_EFLAGS_DF);
-       if (test_thread_flag(TIF_SINGLESTEP))
-               ptrace_notify(SIGTRAP);
-
        return 0;
 
 give_sigsegv:
@@ -566,6 +546,21 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
        if (ret)
                return ret;
 
+       /*
+        * Clear the direction flag as per the ABI for function entry.
+        */
+       regs->flags &= ~X86_EFLAGS_DF;
+
+       /*
+        * Clear TF when entering the signal handler, but
+        * notify any tracer that was single-stepping it.
+        * The tracer may want to single-step inside the
+        * handler too.
+        */
+       regs->flags &= ~X86_EFLAGS_TF;
+       if (test_thread_flag(TIF_SINGLESTEP))
+               ptrace_notify(SIGTRAP);
+
        spin_lock_irq(&current->sighand->siglock);
        sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
        if (!(ka->sa.sa_flags & SA_NODEFER))
index 827179c..ccb2a45 100644 (file)
@@ -285,14 +285,6 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
           even if the handler happens to be interrupting 32-bit code. */
        regs->cs = __USER_CS;
 
-       /* This, by contrast, has nothing to do with segment registers -
-          see include/asm-x86_64/uaccess.h for details. */
-       set_fs(USER_DS);
-
-       regs->flags &= ~(X86_EFLAGS_TF | X86_EFLAGS_DF);
-       if (test_thread_flag(TIF_SINGLESTEP))
-               ptrace_notify(SIGTRAP);
-
        return 0;
 
 give_sigsegv:
@@ -380,6 +372,28 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
        ret = setup_rt_frame(sig, ka, info, oldset, regs);
 
        if (ret == 0) {
+               /*
+                * This has nothing to do with segment registers,
+                * despite the name.  This magic affects uaccess.h
+                * macros' behavior.  Reset it to the normal setting.
+                */
+               set_fs(USER_DS);
+
+               /*
+                * Clear the direction flag as per the ABI for function entry.
+                */
+               regs->flags &= ~X86_EFLAGS_DF;
+
+               /*
+                * Clear TF when entering the signal handler, but
+                * notify any tracer that was single-stepping it.
+                * The tracer may want to single-step inside the
+                * handler too.
+                */
+               regs->flags &= ~X86_EFLAGS_TF;
+               if (test_thread_flag(TIF_SINGLESTEP))
+                       ptrace_notify(SIGTRAP);
+
                spin_lock_irq(&current->sighand->siglock);
                sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
                if (!(ka->sa.sa_flags & SA_NODEFER))
index eef79e8..04c662b 100644 (file)
@@ -1058,7 +1058,7 @@ int __cpuinit native_cpu_up(unsigned int cpu)
        check_tsc_sync_source(cpu);
        local_irq_restore(flags);
 
-       while (!cpu_isset(cpu, cpu_online_map)) {
+       while (!cpu_online(cpu)) {
                cpu_relax();
                touch_nmi_watchdog();
        }
@@ -1168,7 +1168,7 @@ static void __init smp_cpu_index_default(void)
        int i;
        struct cpuinfo_x86 *c;
 
-       for_each_cpu_mask(i, cpu_possible_map) {
+       for_each_possible_cpu(i) {
                c = &cpu_data(i);
                /* mark all to hotplug */
                c->cpu_index = NR_CPUS;
index 6878a9c..ae75109 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/mm.h>
 #include <linux/init.h>
 #include <asm/io.h>
+#include <asm/bios_ebda.h>
 #include <asm/mach-summit/mach_mpparse.h>
 
 static struct rio_table_hdr *rio_table_hdr __initdata;
@@ -140,8 +141,8 @@ void __init setup_summit(void)
        int                     i, next_wpeg, next_bus = 0;
 
        /* The pointer to the EBDA is stored in the word @ phys 0x40E(40:0E) */
-       ptr = *(unsigned short *)phys_to_virt(0x40Eul);
-       ptr = (unsigned long)phys_to_virt(ptr << 4);
+       ptr = get_bios_ebda();
+       ptr = (unsigned long)phys_to_virt(ptr);
 
        rio_table_hdr = NULL;
        offset = 0x180;
index df224a8..a1f07d7 100644 (file)
@@ -195,9 +195,9 @@ static int __cpuinit init_smp_flush(void)
 {
        int i;
 
-       for_each_cpu_mask(i, cpu_possible_map) {
+       for_each_possible_cpu(i)
                spin_lock_init(&per_cpu(flush_state, i).tlbstate_lock);
-       }
+
        return 0;
 }
 core_initcall(init_smp_flush);
index 6458067..d8ccc3c 100644 (file)
@@ -33,7 +33,7 @@
 
 /* We can free up trampoline after bootup if cpu hotplug is not supported. */
 #ifndef CONFIG_HOTPLUG_CPU
-.section ".init.data","aw",@progbits
+.section ".cpuinit.data","aw",@progbits
 #else
 .section .rodata,"a",@progbits
 #endif
index 471e694..bde6f63 100644 (file)
@@ -602,7 +602,7 @@ DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS)
 DO_ERROR(11, SIGBUS,  "segment not present", segment_not_present)
 DO_ERROR(12, SIGBUS,  "stack segment", stack_segment)
 DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0, 0)
-DO_ERROR_INFO(32, SIGSEGV, "iret exception", iret_error, ILL_BADSTK, 0, 1)
+DO_ERROR_INFO(32, SIGILL, "iret exception", iret_error, ILL_BADSTK, 0, 1)
 
 void __kprobes do_general_protection(struct pt_regs *regs, long error_code)
 {
index 6e2c4ef..8acbf0c 100644 (file)
@@ -113,7 +113,7 @@ static inline void send_QIC_CPI(__u32 cpuset, __u8 cpi)
        for_each_online_cpu(cpu) {
                if (cpuset & (1 << cpu)) {
 #ifdef VOYAGER_DEBUG
-                       if (!cpu_isset(cpu, cpu_online_map))
+                       if (!cpu_online(cpu))
                                VDEBUG(("CPU%d sending cpi %d to CPU%d not in "
                                        "cpu_online_map\n",
                                        hard_smp_processor_id(), cpi, cpu));
@@ -683,9 +683,9 @@ void __init smp_boot_cpus(void)
         * Code added from smpboot.c */
        {
                unsigned long bogosum = 0;
-               for (i = 0; i < NR_CPUS; i++)
-                       if (cpu_isset(i, cpu_online_map))
-                               bogosum += cpu_data(i).loops_per_jiffy;
+
+               for_each_online_cpu(i)
+                       bogosum += cpu_data(i).loops_per_jiffy;
                printk(KERN_INFO "Total of %d processors activated "
                       "(%lu.%02lu BogoMIPS).\n",
                       cpucount + 1, bogosum / (500000 / HZ),
@@ -1838,7 +1838,7 @@ static int __cpuinit voyager_cpu_up(unsigned int cpu)
                return -EIO;
        /* Unleash the CPU! */
        cpu_set(cpu, smp_commenced_mask);
-       while (!cpu_isset(cpu, cpu_online_map))
+       while (!cpu_online(cpu))
                mb();
        return 0;
 }
index baf7c4f..4a47618 100644 (file)
@@ -566,9 +566,9 @@ void __init paging_init(void)
 
 /*
  * Test if the WP bit works in supervisor mode. It isn't supported on 386's
- * and also on some strange 486's (NexGen etc.). All 586+'s are OK. This
- * used to involve black magic jumps to work around some nasty CPU bugs,
- * but fortunately the switch to using exceptions got rid of all that.
+ * and also on some strange 486's. All 586+'s are OK. This used to involve
+ * black magic jumps to work around some nasty CPU bugs, but fortunately the
+ * switch to using exceptions got rid of all that.
  */
 static void __init test_wp_bit(void)
 {
index 92dd3db..94e6900 100644 (file)
@@ -193,7 +193,7 @@ void __init xen_smp_prepare_cpus(unsigned int max_cpus)
 
        /* Restrict the possible_map according to max_cpus. */
        while ((num_possible_cpus() > 1) && (num_possible_cpus() > max_cpus)) {
-               for (cpu = NR_CPUS-1; !cpu_isset(cpu, cpu_possible_map); cpu--)
+               for (cpu = NR_CPUS - 1; !cpu_possible(cpu); cpu--)
                        continue;
                cpu_clear(cpu, cpu_possible_map);
        }
index d286699..96bdb92 100644 (file)
@@ -436,8 +436,9 @@ static int __devinit agp_amdk7_probe(struct pci_dev *pdev,
           system controller may experience noise due to strong drive strengths
         */
        if (agp_bridge->dev->device == PCI_DEVICE_ID_AMD_FE_GATE_7006) {
-               u8 cap_ptr=0;
                struct pci_dev *gfxcard=NULL;
+
+               cap_ptr = 0;
                while (!cap_ptr) {
                        gfxcard = pci_get_class(PCI_CLASS_DISPLAY_VGA<<8, gfxcard);
                        if (!gfxcard) {
index 55d7a82..857b262 100644 (file)
@@ -967,7 +967,7 @@ int agpioc_chipset_flush_wrap(struct agp_file_private *priv)
        return 0;
 }
 
-static int agp_ioctl(struct inode *inode, struct file *file,
+static long agp_ioctl(struct file *file,
                     unsigned int cmd, unsigned long arg)
 {
        struct agp_file_private *curr_priv = file->private_data;
@@ -1058,7 +1058,7 @@ static const struct file_operations agp_fops =
        .llseek         = no_llseek,
        .read           = agp_read,
        .write          = agp_write,
-       .ioctl          = agp_ioctl,
+       .unlocked_ioctl = agp_ioctl,
 #ifdef CONFIG_COMPAT
        .compat_ioctl   = compat_agp_ioctl,
 #endif
index 141f4df..b710426 100644 (file)
@@ -167,13 +167,6 @@ int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *ga
                        page_base += ATI_PCIGART_PAGE_SIZE;
                }
        }
-
-       if (gart_info->gart_table_location == DRM_ATI_GART_MAIN)
-               dma_sync_single_for_device(&dev->pdev->dev,
-                                          bus_address,
-                                          max_pages * sizeof(u32),
-                                          PCI_DMA_TODEVICE);
-
        ret = 1;
 
 #if defined(__i386__) || defined(__x86_64__)
index 3a05c6d..6874f31 100644 (file)
@@ -471,6 +471,7 @@ struct drm_irq_busid {
 enum drm_vblank_seq_type {
        _DRM_VBLANK_ABSOLUTE = 0x0,     /**< Wait for specific vblank sequence number */
        _DRM_VBLANK_RELATIVE = 0x1,     /**< Wait for given number of vblanks */
+       _DRM_VBLANK_FLIP = 0x8000000,   /**< Scheduled buffer swap should flip */
        _DRM_VBLANK_NEXTONMISS = 0x10000000,    /**< If missed, wait for next vblank */
        _DRM_VBLANK_SECONDARY = 0x20000000,     /**< Secondary display controller */
        _DRM_VBLANK_SIGNAL = 0x40000000 /**< Send signal instead of blocking */
@@ -503,6 +504,21 @@ union drm_wait_vblank {
        struct drm_wait_vblank_reply reply;
 };
 
+enum drm_modeset_ctl_cmd {
+       _DRM_PRE_MODESET = 1,
+       _DRM_POST_MODESET = 2,
+};
+
+/**
+ * DRM_IOCTL_MODESET_CTL ioctl argument type
+ *
+ * \sa drmModesetCtl().
+ */
+struct drm_modeset_ctl {
+       unsigned long arg;
+       enum drm_modeset_ctl_cmd cmd;
+};
+
 /**
  * DRM_IOCTL_AGP_ENABLE ioctl argument type.
  *
@@ -587,6 +603,7 @@ struct drm_set_version {
 #define DRM_IOCTL_GET_CLIENT            DRM_IOWR(0x05, struct drm_client)
 #define DRM_IOCTL_GET_STATS             DRM_IOR( 0x06, struct drm_stats)
 #define DRM_IOCTL_SET_VERSION          DRM_IOWR(0x07, struct drm_set_version)
+#define DRM_IOCTL_MODESET_CTL           DRM_IOW(0x08, struct drm_modeset_ctl)
 
 #define DRM_IOCTL_SET_UNIQUE           DRM_IOW( 0x10, struct drm_unique)
 #define DRM_IOCTL_AUTH_MAGIC           DRM_IOW( 0x11, struct drm_auth)
index 6540948..ecee354 100644 (file)
@@ -100,10 +100,8 @@ struct drm_device;
 #define DRIVER_HAVE_DMA    0x20
 #define DRIVER_HAVE_IRQ    0x40
 #define DRIVER_IRQ_SHARED  0x80
-#define DRIVER_IRQ_VBL     0x100
 #define DRIVER_DMA_QUEUE   0x200
 #define DRIVER_FB_DMA      0x400
-#define DRIVER_IRQ_VBL2    0x800
 
 /***********************************************************************/
 /** \name Begin the DRM... */
@@ -379,13 +377,12 @@ struct drm_buf_entry {
 struct drm_file {
        int authenticated;
        int master;
-       int minor;
        pid_t pid;
        uid_t uid;
        drm_magic_t magic;
        unsigned long ioctl_count;
        struct list_head lhead;
-       struct drm_head *head;
+       struct drm_minor *minor;
        int remove_auth_on_close;
        unsigned long lock_count;
        struct file *filp;
@@ -580,10 +577,52 @@ struct drm_driver {
        int (*context_dtor) (struct drm_device *dev, int context);
        int (*kernel_context_switch) (struct drm_device *dev, int old,
                                      int new);
-       void (*kernel_context_switch_unlock) (struct drm_device *dev);
-       int (*vblank_wait) (struct drm_device *dev, unsigned int *sequence);
-       int (*vblank_wait2) (struct drm_device *dev, unsigned int *sequence);
-       int (*dri_library_name) (struct drm_device *dev, char *buf);
+       void (*kernel_context_switch_unlock) (struct drm_device * dev);
+       /**
+        * get_vblank_counter - get raw hardware vblank counter
+        * @dev: DRM device
+        * @crtc: counter to fetch
+        *
+        * Driver callback for fetching a raw hardware vblank counter
+        * for @crtc.  If a device doesn't have a hardware counter, the
+        * driver can simply return the value of drm_vblank_count and
+        * make the enable_vblank() and disable_vblank() hooks into no-ops,
+        * leaving interrupts enabled at all times.
+        *
+        * Wraparound handling and loss of events due to modesetting is dealt
+        * with in the DRM core code.
+        *
+        * RETURNS
+        * Raw vblank counter value.
+        */
+       u32 (*get_vblank_counter) (struct drm_device *dev, int crtc);
+
+       /**
+        * enable_vblank - enable vblank interrupt events
+        * @dev: DRM device
+        * @crtc: which irq to enable
+        *
+        * Enable vblank interrupts for @crtc.  If the device doesn't have
+        * a hardware vblank counter, this routine should be a no-op, since
+        * interrupts will have to stay on to keep the count accurate.
+        *
+        * RETURNS
+        * Zero on success, appropriate errno if the given @crtc's vblank
+        * interrupt cannot be enabled.
+        */
+       int (*enable_vblank) (struct drm_device *dev, int crtc);
+
+       /**
+        * disable_vblank - disable vblank interrupt events
+        * @dev: DRM device
+        * @crtc: which irq to enable
+        *
+        * Disable vblank interrupts for @crtc.  If the device doesn't have
+        * a hardware vblank counter, this routine should be a no-op, since
+        * interrupts will have to stay on to keep the count accurate.
+        */
+       void (*disable_vblank) (struct drm_device *dev, int crtc);
+       int (*dri_library_name) (struct drm_device *dev, char * buf);
 
        /**
         * Called by \c drm_device_is_agp.  Typically used to determine if a
@@ -602,7 +641,7 @@ struct drm_driver {
 
        irqreturn_t(*irq_handler) (DRM_IRQ_ARGS);
        void (*irq_preinstall) (struct drm_device *dev);
-       void (*irq_postinstall) (struct drm_device *dev);
+       int (*irq_postinstall) (struct drm_device *dev);
        void (*irq_uninstall) (struct drm_device *dev);
        void (*reclaim_buffers) (struct drm_device *dev,
                                 struct drm_file * file_priv);
@@ -630,16 +669,19 @@ struct drm_driver {
        struct pci_driver pci_driver;
 };
 
+#define DRM_MINOR_UNASSIGNED 0
+#define DRM_MINOR_LEGACY 1
+
 /**
- * DRM head structure. This structure represent a video head on a card
- * that may contain multiple heads. Embed one per head of these in the
- * private drm_device structure.
+ * DRM minor structure. This structure represents a drm minor number.
  */
-struct drm_head {
-       int minor;                      /**< Minor device number */
+struct drm_minor {
+       int index;                      /**< Minor device number */
+       int type;                       /**< Control or render */
+       dev_t device;                   /**< Device number for mknod */
+       struct device kdev;             /**< Linux device */
        struct drm_device *dev;
        struct proc_dir_entry *dev_root;  /**< proc directory entry */
-       dev_t device;                   /**< Device number for mknod */
 };
 
 /**
@@ -647,7 +689,6 @@ struct drm_head {
  * may contain multiple heads.
  */
 struct drm_device {
-       struct device dev;              /**< Linux device */
        char *unique;                   /**< Unique identifier: e.g., busid */
        int unique_len;                 /**< Length of unique field */
        char *devname;                  /**< For /proc/interrupts */
@@ -729,13 +770,21 @@ struct drm_device {
        /** \name VBLANK IRQ support */
        /*@{ */
 
-       wait_queue_head_t vbl_queue;    /**< VBLANK wait queue */
-       atomic_t vbl_received;
-       atomic_t vbl_received2;         /**< number of secondary VBLANK interrupts */
+       wait_queue_head_t *vbl_queue;   /**< VBLANK wait queue */
+       atomic_t *_vblank_count;        /**< number of VBLANK interrupts (driver must alloc the right number of counters) */
        spinlock_t vbl_lock;
-       struct list_head vbl_sigs;              /**< signal list to send on VBLANK */
-       struct list_head vbl_sigs2;     /**< signals to send on secondary VBLANK */
-       unsigned int vbl_pending;
+       struct list_head *vbl_sigs;             /**< signal list to send on VBLANK */
+       atomic_t vbl_signal_pending;    /* number of signals pending on all crtcs*/
+       atomic_t *vblank_refcount;      /* number of users of vblank interrupts per crtc */
+       u32 *last_vblank;               /* protected by dev->vbl_lock, used */
+                                       /* for wraparound handling */
+       u32 *vblank_offset;             /* used to track how many vblanks */
+       int *vblank_enabled;            /* so we don't call enable more than
+                                          once per disable */
+       u32 *vblank_premodeset;         /*  were lost during modeset */
+       struct timer_list vblank_disable_timer;
+
+       unsigned long max_vblank_count; /**< size of vblank counter register */
        spinlock_t tasklet_lock;        /**< For drm_locked_tasklet */
        void (*locked_tasklet_func)(struct drm_device *dev);
 
@@ -755,6 +804,7 @@ struct drm_device {
 #ifdef __alpha__
        struct pci_controller *hose;
 #endif
+       int num_crtcs;                  /**< Number of CRTCs on this device */
        struct drm_sg_mem *sg;  /**< Scatter gather memory */
        void *dev_private;              /**< device private data */
        struct drm_sigdata sigdata;        /**< For block_all_signals */
@@ -763,7 +813,7 @@ struct drm_device {
        struct drm_driver *driver;
        drm_local_map_t *agp_buffer_map;
        unsigned int agp_buffer_token;
-       struct drm_head primary;                /**< primary screen head */
+       struct drm_minor *primary;              /**< render type primary screen head */
 
        /** \name Drawable information */
        /*@{ */
@@ -989,11 +1039,19 @@ extern void drm_driver_irq_preinstall(struct drm_device *dev);
 extern void drm_driver_irq_postinstall(struct drm_device *dev);
 extern void drm_driver_irq_uninstall(struct drm_device *dev);
 
-extern int drm_wait_vblank(struct drm_device *dev, void *data,
-                          struct drm_file *file_priv);
-extern int drm_vblank_wait(struct drm_device *dev, unsigned int *vbl_seq);
-extern void drm_vbl_send_signals(struct drm_device *dev);
+extern int drm_vblank_init(struct drm_device *dev, int num_crtcs);
+extern int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *filp);
+extern int drm_vblank_wait(struct drm_device * dev, unsigned int *vbl_seq);
 extern void drm_locked_tasklet(struct drm_device *dev, void(*func)(struct drm_device*));
+extern u32 drm_vblank_count(struct drm_device *dev, int crtc);
+extern void drm_update_vblank_count(struct drm_device *dev, int crtc);
+extern void drm_handle_vblank(struct drm_device *dev, int crtc);
+extern int drm_vblank_get(struct drm_device *dev, int crtc);
+extern void drm_vblank_put(struct drm_device *dev, int crtc);
+
+                               /* Modesetting support */
+extern int drm_modeset_ctl(struct drm_device *dev, void *data,
+                          struct drm_file *file_priv);
 
                                /* AGP/GART support (drm_agpsupport.h) */
 extern struct drm_agp_head *drm_agp_init(struct drm_device *dev);
@@ -1030,23 +1088,20 @@ extern int drm_agp_unbind_memory(DRM_AGP_MEM * handle);
 extern int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
                       struct drm_driver *driver);
 extern int drm_put_dev(struct drm_device *dev);
-extern int drm_put_head(struct drm_head *head);
+extern int drm_put_minor(struct drm_minor **minor);
 extern unsigned int drm_debug;
-extern unsigned int drm_cards_limit;
-extern struct drm_head **drm_heads;
+
 extern struct class *drm_class;
 extern struct proc_dir_entry *drm_proc_root;
 
+extern struct idr drm_minors_idr;
+
 extern drm_local_map_t *drm_getsarea(struct drm_device *dev);
 
                                /* Proc support (drm_proc.h) */
-extern int drm_proc_init(struct drm_device *dev,
-                        int minor,
-                        struct proc_dir_entry *root,
-                        struct proc_dir_entry **dev_root);
-extern int drm_proc_cleanup(int minor,
-                           struct proc_dir_entry *root,
-                           struct proc_dir_entry *dev_root);
+extern int drm_proc_init(struct drm_minor *minor, int minor_id,
+                        struct proc_dir_entry *root);
+extern int drm_proc_cleanup(struct drm_minor *minor, struct proc_dir_entry *root);
 
                                /* Scatter Gather Support (drm_scatter.h) */
 extern void drm_sg_cleanup(struct drm_sg_mem * entry);
@@ -1071,8 +1126,8 @@ extern void drm_pci_free(struct drm_device *dev, drm_dma_handle_t * dmah);
 struct drm_sysfs_class;
 extern struct class *drm_sysfs_create(struct module *owner, char *name);
 extern void drm_sysfs_destroy(void);
-extern int drm_sysfs_device_add(struct drm_device *dev, struct drm_head *head);
-extern void drm_sysfs_device_remove(struct drm_device *dev);
+extern int drm_sysfs_device_add(struct drm_minor *minor);
+extern void drm_sysfs_device_remove(struct drm_minor *minor);
 
 /*
  * Basic memory manager support (drm_mm.c)
index 9468c78..aefa5ac 100644 (file)
@@ -122,7 +122,7 @@ EXPORT_SYMBOL(drm_agp_acquire);
 int drm_agp_acquire_ioctl(struct drm_device *dev, void *data,
                          struct drm_file *file_priv)
 {
-       return drm_agp_acquire((struct drm_device *) file_priv->head->dev);
+       return drm_agp_acquire((struct drm_device *) file_priv->minor->dev);
 }
 
 /**
index 0e7af53..fc54140 100644 (file)
@@ -313,35 +313,36 @@ static void drm_cleanup(struct drm_device * dev)
        drm_ht_remove(&dev->map_hash);
        drm_ctxbitmap_cleanup(dev);
 
-       drm_put_head(&dev->primary);
+       drm_put_minor(&dev->primary);
        if (drm_put_dev(dev))
                DRM_ERROR("Cannot unload module\n");
 }
 
-void drm_exit(struct drm_driver *driver)
+int drm_minors_cleanup(int id, void *ptr, void *data)
 {
-       int i;
-       struct drm_device *dev = NULL;
-       struct drm_head *head;
+       struct drm_minor *minor = ptr;
+       struct drm_device *dev;
+       struct drm_driver *driver = data;
+
+       dev = minor->dev;
+       if (minor->dev->driver != driver)
+               return 0;
+
+       if (minor->type != DRM_MINOR_LEGACY)
+               return 0;
 
+       if (dev)
+               pci_dev_put(dev->pdev);
+       drm_cleanup(dev);
+       return 1;
+}
+
+void drm_exit(struct drm_driver *driver)
+{
        DRM_DEBUG("\n");
 
-       for (i = 0; i < drm_cards_limit; i++) {
-               head = drm_heads[i];
-               if (!head)
-                       continue;
-               if (!head->dev)
-                       continue;
-               if (head->dev->driver != driver)
-                       continue;
-               dev = head->dev;
-               if (dev) {
-                       /* release the pci driver */
-                       if (dev->pdev)
-                               pci_dev_put(dev->pdev);
-                       drm_cleanup(dev);
-               }
-       }
+       idr_for_each(&drm_minors_idr, &drm_minors_cleanup, driver);
+
        DRM_INFO("Module unloaded\n");
 }
 
@@ -357,13 +358,7 @@ static int __init drm_core_init(void)
 {
        int ret = -ENOMEM;
 
-       drm_cards_limit =
-           (drm_cards_limit <
-            DRM_MAX_MINOR + 1 ? drm_cards_limit : DRM_MAX_MINOR + 1);
-       drm_heads =
-           drm_calloc(drm_cards_limit, sizeof(*drm_heads), DRM_MEM_STUB);
-       if (!drm_heads)
-               goto err_p1;
+       idr_init(&drm_minors_idr);
 
        if (register_chrdev(DRM_MAJOR, "drm", &drm_stub_fops))
                goto err_p1;
@@ -391,7 +386,8 @@ err_p3:
        drm_sysfs_destroy();
 err_p2:
        unregister_chrdev(DRM_MAJOR, "drm");
-       drm_free(drm_heads, sizeof(*drm_heads) * drm_cards_limit, DRM_MEM_STUB);
+
+       idr_destroy(&drm_minors_idr);
 err_p1:
        return ret;
 }
@@ -403,7 +399,7 @@ static void __exit drm_core_exit(void)
 
        unregister_chrdev(DRM_MAJOR, "drm");
 
-       drm_free(drm_heads, sizeof(*drm_heads) * drm_cards_limit, DRM_MEM_STUB);
+       idr_destroy(&drm_minors_idr);
 }
 
 module_init(drm_core_init);
@@ -452,7 +448,7 @@ int drm_ioctl(struct inode *inode, struct file *filp,
              unsigned int cmd, unsigned long arg)
 {
        struct drm_file *file_priv = filp->private_data;
-       struct drm_device *dev = file_priv->head->dev;
+       struct drm_device *dev = file_priv->minor->dev;
        struct drm_ioctl_desc *ioctl;
        drm_ioctl_t *func;
        unsigned int nr = DRM_IOCTL_NR(cmd);
@@ -465,7 +461,7 @@ int drm_ioctl(struct inode *inode, struct file *filp,
 
        DRM_DEBUG("pid=%d, cmd=0x%02x, nr=0x%02x, dev 0x%lx, auth=%d\n",
                  task_pid_nr(current), cmd, nr,
-                 (long)old_encode_dev(file_priv->head->device),
+                 (long)old_encode_dev(file_priv->minor->device),
                  file_priv->authenticated);
 
        if ((nr >= DRM_CORE_IOCTL_COUNT) &&
index f09d4b5..68f0da8 100644 (file)
@@ -129,16 +129,15 @@ static int drm_setup(struct drm_device * dev)
 int drm_open(struct inode *inode, struct file *filp)
 {
        struct drm_device *dev = NULL;
-       int minor = iminor(inode);
+       int minor_id = iminor(inode);
+       struct drm_minor *minor;
        int retcode = 0;
 
-       if (!((minor >= 0) && (minor < drm_cards_limit)))
+       minor = idr_find(&drm_minors_idr, minor_id);
+       if (!minor)
                return -ENODEV;
 
-       if (!drm_heads[minor])
-               return -ENODEV;
-
-       if (!(dev = drm_heads[minor]->dev))
+       if (!(dev = minor->dev))
                return -ENODEV;
 
        retcode = drm_open_helper(inode, filp, dev);
@@ -168,19 +167,18 @@ EXPORT_SYMBOL(drm_open);
 int drm_stub_open(struct inode *inode, struct file *filp)
 {
        struct drm_device *dev = NULL;
-       int minor = iminor(inode);
+       struct drm_minor *minor;
+       int minor_id = iminor(inode);
        int err = -ENODEV;
        const struct file_operations *old_fops;
 
        DRM_DEBUG("\n");
 
-       if (!((minor >= 0) && (minor < drm_cards_limit)))
-               return -ENODEV;
-
-       if (!drm_heads[minor])
+       minor = idr_find(&drm_minors_idr, minor_id);
+       if (!minor)
                return -ENODEV;
 
-       if (!(dev = drm_heads[minor]->dev))
+       if (!(dev = minor->dev))
                return -ENODEV;
 
        old_fops = filp->f_op;
@@ -225,7 +223,7 @@ static int drm_cpu_valid(void)
 static int drm_open_helper(struct inode *inode, struct file *filp,
                           struct drm_device * dev)
 {
-       int minor = iminor(inode);
+       int minor_id = iminor(inode);
        struct drm_file *priv;
        int ret;
 
@@ -234,7 +232,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
        if (!drm_cpu_valid())
                return -EINVAL;
 
-       DRM_DEBUG("pid = %d, minor = %d\n", task_pid_nr(current), minor);
+       DRM_DEBUG("pid = %d, minor = %d\n", task_pid_nr(current), minor_id);
 
        priv = drm_alloc(sizeof(*priv), DRM_MEM_FILES);
        if (!priv)
@@ -245,8 +243,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
        priv->filp = filp;
        priv->uid = current->euid;
        priv->pid = task_pid_nr(current);
-       priv->minor = minor;
-       priv->head = drm_heads[minor];
+       priv->minor = idr_find(&drm_minors_idr, minor_id);
        priv->ioctl_count = 0;
        /* for compatibility root is always authenticated */
        priv->authenticated = capable(CAP_SYS_ADMIN);
@@ -297,11 +294,11 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
 int drm_fasync(int fd, struct file *filp, int on)
 {
        struct drm_file *priv = filp->private_data;
-       struct drm_device *dev = priv->head->dev;
+       struct drm_device *dev = priv->minor->dev;
        int retcode;
 
        DRM_DEBUG("fd = %d, device = 0x%lx\n", fd,
-                 (long)old_encode_dev(priv->head->device));
+                 (long)old_encode_dev(priv->minor->device));
        retcode = fasync_helper(fd, filp, on, &dev->buf_async);
        if (retcode < 0)
                return retcode;
@@ -324,7 +321,7 @@ EXPORT_SYMBOL(drm_fasync);
 int drm_release(struct inode *inode, struct file *filp)
 {
        struct drm_file *file_priv = filp->private_data;
-       struct drm_device *dev = file_priv->head->dev;
+       struct drm_device *dev = file_priv->minor->dev;
        int retcode = 0;
        unsigned long irqflags;
 
@@ -341,14 +338,14 @@ int drm_release(struct inode *inode, struct file *filp)
 
        DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n",
                  task_pid_nr(current),
-                 (long)old_encode_dev(file_priv->head->device),
+                 (long)old_encode_dev(file_priv->minor->device),
                  dev->open_count);
 
        if (dev->driver->reclaim_buffers_locked && dev->lock.hw_lock) {
                if (drm_i_have_hw_lock(dev, file_priv)) {
                        dev->driver->reclaim_buffers_locked(dev, file_priv);
                } else {
-                       unsigned long _end=jiffies + 3*DRM_HZ;
+                       unsigned long endtime = jiffies + 3 * DRM_HZ;
                        int locked = 0;
 
                        drm_idlelock_take(&dev->lock);
@@ -366,7 +363,7 @@ int drm_release(struct inode *inode, struct file *filp)
                                if (locked)
                                        break;
                                schedule();
-                       } while (!time_after_eq(jiffies, _end));
+                       } while (!time_after_eq(jiffies, endtime));
 
                        if (!locked) {
                                DRM_ERROR("reclaim_buffers_locked() deadlock. Please rework this\n"
index 089c015..286f9d6 100644 (file)
@@ -71,6 +71,117 @@ int drm_irq_by_busid(struct drm_device *dev, void *data,
        return 0;
 }
 
+static void vblank_disable_fn(unsigned long arg)
+{
+       struct drm_device *dev = (struct drm_device *)arg;
+       unsigned long irqflags;
+       int i;
+
+       for (i = 0; i < dev->num_crtcs; i++) {
+               spin_lock_irqsave(&dev->vbl_lock, irqflags);
+               if (atomic_read(&dev->vblank_refcount[i]) == 0 &&
+                   dev->vblank_enabled[i]) {
+                       dev->driver->disable_vblank(dev, i);
+                       dev->vblank_enabled[i] = 0;
+               }
+               spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
+       }
+}
+
+static void drm_vblank_cleanup(struct drm_device *dev)
+{
+       /* Bail if the driver didn't call drm_vblank_init() */
+       if (dev->num_crtcs == 0)
+               return;
+
+       del_timer(&dev->vblank_disable_timer);
+
+       vblank_disable_fn((unsigned long)dev);
+
+       drm_free(dev->vbl_queue, sizeof(*dev->vbl_queue) * dev->num_crtcs,
+                DRM_MEM_DRIVER);
+       drm_free(dev->vbl_sigs, sizeof(*dev->vbl_sigs) * dev->num_crtcs,
+                DRM_MEM_DRIVER);
+       drm_free(dev->_vblank_count, sizeof(*dev->_vblank_count) *
+                dev->num_crtcs, DRM_MEM_DRIVER);
+       drm_free(dev->vblank_refcount, sizeof(*dev->vblank_refcount) *
+                dev->num_crtcs, DRM_MEM_DRIVER);
+       drm_free(dev->vblank_enabled, sizeof(*dev->vblank_enabled) *
+                dev->num_crtcs, DRM_MEM_DRIVER);
+       drm_free(dev->last_vblank, sizeof(*dev->last_vblank) * dev->num_crtcs,
+                DRM_MEM_DRIVER);
+       drm_free(dev->vblank_premodeset, sizeof(*dev->vblank_premodeset) *
+                dev->num_crtcs, DRM_MEM_DRIVER);
+       drm_free(dev->vblank_offset, sizeof(*dev->vblank_offset) * dev->num_crtcs,
+                DRM_MEM_DRIVER);
+
+       dev->num_crtcs = 0;
+}
+
+int drm_vblank_init(struct drm_device *dev, int num_crtcs)
+{
+       int i, ret = -ENOMEM;
+
+       setup_timer(&dev->vblank_disable_timer, vblank_disable_fn,
+                   (unsigned long)dev);
+       spin_lock_init(&dev->vbl_lock);
+       atomic_set(&dev->vbl_signal_pending, 0);
+       dev->num_crtcs = num_crtcs;
+
+       dev->vbl_queue = drm_alloc(sizeof(wait_queue_head_t) * num_crtcs,
+                                  DRM_MEM_DRIVER);
+       if (!dev->vbl_queue)
+               goto err;
+
+       dev->vbl_sigs = drm_alloc(sizeof(struct list_head) * num_crtcs,
+                                 DRM_MEM_DRIVER);
+       if (!dev->vbl_sigs)
+               goto err;
+
+       dev->_vblank_count = drm_alloc(sizeof(atomic_t) * num_crtcs,
+                                     DRM_MEM_DRIVER);
+       if (!dev->_vblank_count)
+               goto err;
+
+       dev->vblank_refcount = drm_alloc(sizeof(atomic_t) * num_crtcs,
+                                        DRM_MEM_DRIVER);
+       if (!dev->vblank_refcount)
+               goto err;
+
+       dev->vblank_enabled = drm_calloc(num_crtcs, sizeof(int),
+                                        DRM_MEM_DRIVER);
+       if (!dev->vblank_enabled)
+               goto err;
+
+       dev->last_vblank = drm_calloc(num_crtcs, sizeof(u32), DRM_MEM_DRIVER);
+       if (!dev->last_vblank)
+               goto err;
+
+       dev->vblank_premodeset = drm_calloc(num_crtcs, sizeof(u32),
+                                           DRM_MEM_DRIVER);
+       if (!dev->vblank_premodeset)
+               goto err;
+
+       dev->vblank_offset = drm_calloc(num_crtcs, sizeof(u32), DRM_MEM_DRIVER);
+       if (!dev->vblank_offset)
+               goto err;
+
+       /* Zero per-crtc vblank stuff */
+       for (i = 0; i < num_crtcs; i++) {
+               init_waitqueue_head(&dev->vbl_queue[i]);
+               INIT_LIST_HEAD(&dev->vbl_sigs[i]);
+               atomic_set(&dev->_vblank_count[i], 0);
+               atomic_set(&dev->vblank_refcount[i], 0);
+       }
+
+       return 0;
+
+err:
+       drm_vblank_cleanup(dev);
+       return ret;
+}
+EXPORT_SYMBOL(drm_vblank_init);
+
 /**
  * Install IRQ handler.
  *
@@ -109,17 +220,6 @@ static int drm_irq_install(struct drm_device * dev)
 
        DRM_DEBUG("irq=%d\n", dev->irq);
 
-       if (drm_core_check_feature(dev, DRIVER_IRQ_VBL)) {
-               init_waitqueue_head(&dev->vbl_queue);
-
-               spin_lock_init(&dev->vbl_lock);
-
-               INIT_LIST_HEAD(&dev->vbl_sigs);
-               INIT_LIST_HEAD(&dev->vbl_sigs2);
-
-               dev->vbl_pending = 0;
-       }
-
        /* Before installing handler */
        dev->driver->irq_preinstall(dev);
 
@@ -137,9 +237,14 @@ static int drm_irq_install(struct drm_device * dev)
        }
 
        /* After installing handler */
-       dev->driver->irq_postinstall(dev);
+       ret = dev->driver->irq_postinstall(dev);
+       if (ret < 0) {
+               mutex_lock(&dev->struct_mutex);
+               dev->irq_enabled = 0;
+               mutex_unlock(&dev->struct_mutex);
+       }
 
-       return 0;
+       return ret;
 }
 
 /**
@@ -170,6 +275,8 @@ int drm_irq_uninstall(struct drm_device * dev)
 
        free_irq(dev->irq, dev);
 
+       drm_vblank_cleanup(dev);
+
        dev->locked_tasklet_func = NULL;
 
        return 0;
@@ -214,6 +321,148 @@ int drm_control(struct drm_device *dev, void *data,
 }
 
 /**
+ * drm_vblank_count - retrieve "cooked" vblank counter value
+ * @dev: DRM device
+ * @crtc: which counter to retrieve
+ *
+ * Fetches the "cooked" vblank count value that represents the number of
+ * vblank events since the system was booted, including lost events due to
+ * modesetting activity.
+ */
+u32 drm_vblank_count(struct drm_device *dev, int crtc)
+{
+       return atomic_read(&dev->_vblank_count[crtc]) +
+               dev->vblank_offset[crtc];
+}
+EXPORT_SYMBOL(drm_vblank_count);
+
+/**
+ * drm_update_vblank_count - update the master vblank counter
+ * @dev: DRM device
+ * @crtc: counter to update
+ *
+ * Call back into the driver to update the appropriate vblank counter
+ * (specified by @crtc).  Deal with wraparound, if it occurred, and
+ * update the last read value so we can deal with wraparound on the next
+ * call if necessary.
+ */
+void drm_update_vblank_count(struct drm_device *dev, int crtc)
+{
+       unsigned long irqflags;
+       u32 cur_vblank, diff;
+
+       /*
+        * Interrupts were disabled prior to this call, so deal with counter
+        * wrap if needed.
+        * NOTE!  It's possible we lost a full dev->max_vblank_count events
+        * here if the register is small or we had vblank interrupts off for
+        * a long time.
+        */
+       cur_vblank = dev->driver->get_vblank_counter(dev, crtc);
+       spin_lock_irqsave(&dev->vbl_lock, irqflags);
+       if (cur_vblank < dev->last_vblank[crtc]) {
+               diff = dev->max_vblank_count -
+                       dev->last_vblank[crtc];
+               diff += cur_vblank;
+       } else {
+               diff = cur_vblank - dev->last_vblank[crtc];
+       }
+       dev->last_vblank[crtc] = cur_vblank;
+       spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
+
+       atomic_add(diff, &dev->_vblank_count[crtc]);
+}
+EXPORT_SYMBOL(drm_update_vblank_count);
+
+/**
+ * drm_vblank_get - get a reference count on vblank events
+ * @dev: DRM device
+ * @crtc: which CRTC to own
+ *
+ * Acquire a reference count on vblank events to avoid having them disabled
+ * while in use.  Note callers will probably want to update the master counter
+ * using drm_update_vblank_count() above before calling this routine so that
+ * wakeups occur on the right vblank event.
+ *
+ * RETURNS
+ * Zero on success, nonzero on failure.
+ */
+int drm_vblank_get(struct drm_device *dev, int crtc)
+{
+       unsigned long irqflags;
+       int ret = 0;
+
+       spin_lock_irqsave(&dev->vbl_lock, irqflags);
+       /* Going from 0->1 means we have to enable interrupts again */
+       if (atomic_add_return(1, &dev->vblank_refcount[crtc]) == 1 &&
+           !dev->vblank_enabled[crtc]) {
+               ret = dev->driver->enable_vblank(dev, crtc);
+               if (ret)
+                       atomic_dec(&dev->vblank_refcount[crtc]);
+               else
+                       dev->vblank_enabled[crtc] = 1;
+       }
+       spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
+
+       return ret;
+}
+EXPORT_SYMBOL(drm_vblank_get);
+
+/**
+ * drm_vblank_put - give up ownership of vblank events
+ * @dev: DRM device
+ * @crtc: which counter to give up
+ *
+ * Release ownership of a given vblank counter, turning off interrupts
+ * if possible.
+ */
+void drm_vblank_put(struct drm_device *dev, int crtc)
+{
+       /* Last user schedules interrupt disable */
+       if (atomic_dec_and_test(&dev->vblank_refcount[crtc]))
+           mod_timer(&dev->vblank_disable_timer, jiffies + 5*DRM_HZ);
+}
+EXPORT_SYMBOL(drm_vblank_put);
+
+/**
+ * drm_modeset_ctl - handle vblank event counter changes across mode switch
+ * @DRM_IOCTL_ARGS: standard ioctl arguments
+ *
+ * Applications should call the %_DRM_PRE_MODESET and %_DRM_POST_MODESET
+ * ioctls around modesetting so that any lost vblank events are accounted for.
+ */
+int drm_modeset_ctl(struct drm_device *dev, void *data,
+                   struct drm_file *file_priv)
+{
+       struct drm_modeset_ctl *modeset = data;
+       int crtc, ret = 0;
+       u32 new;
+
+       crtc = modeset->arg;
+       if (crtc >= dev->num_crtcs) {
+               ret = -EINVAL;
+               goto out;
+       }
+
+       switch (modeset->cmd) {
+       case _DRM_PRE_MODESET:
+               dev->vblank_premodeset[crtc] =
+                       dev->driver->get_vblank_counter(dev, crtc);
+               break;
+       case _DRM_POST_MODESET:
+               new = dev->driver->get_vblank_counter(dev, crtc);
+               dev->vblank_offset[crtc] = dev->vblank_premodeset[crtc] - new;
+               break;
+       default:
+               ret = -EINVAL;
+               break;
+       }
+
+out:
+       return ret;
+}
+
+/**
  * Wait for VBLANK.
  *
  * \param inode device inode.
@@ -232,12 +481,13 @@ int drm_control(struct drm_device *dev, void *data,
  *
  * If a signal is not requested, then calls vblank_wait().
  */
-int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_priv)
+int drm_wait_vblank(struct drm_device *dev, void *data,
+                   struct drm_file *file_priv)
 {
        union drm_wait_vblank *vblwait = data;
        struct timeval now;
        int ret = 0;
-       unsigned int flags, seq;
+       unsigned int flags, seq, crtc;
 
        if ((!dev->irq) || (!dev->irq_enabled))
                return -EINVAL;
@@ -251,13 +501,13 @@ int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_pr
        }
 
        flags = vblwait->request.type & _DRM_VBLANK_FLAGS_MASK;
+       crtc = flags & _DRM_VBLANK_SECONDARY ? 1 : 0;
 
-       if (!drm_core_check_feature(dev, (flags & _DRM_VBLANK_SECONDARY) ?
-                                   DRIVER_IRQ_VBL2 : DRIVER_IRQ_VBL))
+       if (crtc >= dev->num_crtcs)
                return -EINVAL;
 
-       seq = atomic_read((flags & _DRM_VBLANK_SECONDARY) ? &dev->vbl_received2
-                         : &dev->vbl_received);
+       drm_update_vblank_count(dev, crtc);
+       seq = drm_vblank_count(dev, crtc);
 
        switch (vblwait->request.type & _DRM_VBLANK_TYPES_MASK) {
        case _DRM_VBLANK_RELATIVE:
@@ -276,8 +526,7 @@ int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_pr
 
        if (flags & _DRM_VBLANK_SIGNAL) {
                unsigned long irqflags;
-               struct list_head *vbl_sigs = (flags & _DRM_VBLANK_SECONDARY)
-                                     ? &dev->vbl_sigs2 : &dev->vbl_sigs;
+               struct list_head *vbl_sigs = &dev->vbl_sigs[crtc];
                struct drm_vbl_sig *vbl_sig;
 
                spin_lock_irqsave(&dev->vbl_lock, irqflags);
@@ -298,22 +547,26 @@ int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_pr
                        }
                }
 
-               if (dev->vbl_pending >= 100) {
+               if (atomic_read(&dev->vbl_signal_pending) >= 100) {
                        spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
                        return -EBUSY;
                }
 
-               dev->vbl_pending++;
-
                spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
 
-               if (!
-                   (vbl_sig =
-                    drm_alloc(sizeof(struct drm_vbl_sig), DRM_MEM_DRIVER))) {
+               vbl_sig = drm_calloc(1, sizeof(struct drm_vbl_sig),
+                                    DRM_MEM_DRIVER);
+               if (!vbl_sig)
                        return -ENOMEM;
+
+               ret = drm_vblank_get(dev, crtc);
+               if (ret) {
+                       drm_free(vbl_sig, sizeof(struct drm_vbl_sig),
+                                DRM_MEM_DRIVER);
+                       return ret;
                }
 
-               memset((void *)vbl_sig, 0, sizeof(*vbl_sig));
+               atomic_inc(&dev->vbl_signal_pending);
 
                vbl_sig->sequence = vblwait->request.sequence;
                vbl_sig->info.si_signo = vblwait->request.signal;
@@ -327,17 +580,20 @@ int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_pr
 
                vblwait->reply.sequence = seq;
        } else {
-               if (flags & _DRM_VBLANK_SECONDARY) {
-                       if (dev->driver->vblank_wait2)
-                               ret = dev->driver->vblank_wait2(dev, &vblwait->request.sequence);
-               } else if (dev->driver->vblank_wait)
-                       ret =
-                           dev->driver->vblank_wait(dev,
-                                                    &vblwait->request.sequence);
-
+               unsigned long cur_vblank;
+
+               ret = drm_vblank_get(dev, crtc);
+               if (ret)
+                       return ret;
+               DRM_WAIT_ON(ret, dev->vbl_queue[crtc], 3 * DRM_HZ,
+                           (((cur_vblank = drm_vblank_count(dev, crtc))
+                             - vblwait->request.sequence) <= (1 << 23)));
+               drm_vblank_put(dev, crtc);
                do_gettimeofday(&now);
+
                vblwait->reply.tval_sec = now.tv_sec;
                vblwait->reply.tval_usec = now.tv_usec;
+               vblwait->reply.sequence = cur_vblank;
        }
 
       done:
@@ -348,44 +604,57 @@ int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_pr
  * Send the VBLANK signals.
  *
  * \param dev DRM device.
+ * \param crtc CRTC where the vblank event occurred
  *
  * Sends a signal for each task in drm_device::vbl_sigs and empties the list.
  *
  * If a signal is not requested, then calls vblank_wait().
  */
-void drm_vbl_send_signals(struct drm_device * dev)
+static void drm_vbl_send_signals(struct drm_device * dev, int crtc)
 {
+       struct drm_vbl_sig *vbl_sig, *tmp;
+       struct list_head *vbl_sigs;
+       unsigned int vbl_seq;
        unsigned long flags;
-       int i;
 
        spin_lock_irqsave(&dev->vbl_lock, flags);
 
-       for (i = 0; i < 2; i++) {
-               struct drm_vbl_sig *vbl_sig, *tmp;
-               struct list_head *vbl_sigs = i ? &dev->vbl_sigs2 : &dev->vbl_sigs;
-               unsigned int vbl_seq = atomic_read(i ? &dev->vbl_received2 :
-                                                  &dev->vbl_received);
+       vbl_sigs = &dev->vbl_sigs[crtc];
+       vbl_seq = drm_vblank_count(dev, crtc);
 
-               list_for_each_entry_safe(vbl_sig, tmp, vbl_sigs, head) {
-                       if ((vbl_seq - vbl_sig->sequence) <= (1 << 23)) {
-                               vbl_sig->info.si_code = vbl_seq;
-                               send_sig_info(vbl_sig->info.si_signo,
-                                             &vbl_sig->info, vbl_sig->task);
+       list_for_each_entry_safe(vbl_sig, tmp, vbl_sigs, head) {
+           if ((vbl_seq - vbl_sig->sequence) <= (1 << 23)) {
+               vbl_sig->info.si_code = vbl_seq;
+               send_sig_info(vbl_sig->info.si_signo,
+                             &vbl_sig->info, vbl_sig->task);
 
-                               list_del(&vbl_sig->head);
+               list_del(&vbl_sig->head);
 
-                               drm_free(vbl_sig, sizeof(*vbl_sig),
-                                        DRM_MEM_DRIVER);
-
-                               dev->vbl_pending--;
-                       }
-               }
+               drm_free(vbl_sig, sizeof(*vbl_sig),
+                        DRM_MEM_DRIVER);
+               atomic_dec(&dev->vbl_signal_pending);
+               drm_vblank_put(dev, crtc);
+           }
        }
 
        spin_unlock_irqrestore(&dev->vbl_lock, flags);
 }
 
-EXPORT_SYMBOL(drm_vbl_send_signals);
+/**
+ * drm_handle_vblank - handle a vblank event
+ * @dev: DRM device
+ * @crtc: where this event occurred
+ *
+ * Drivers should call this routine in their vblank interrupt handlers to
+ * update the vblank counter and send any signals that may be pending.
+ */
+void drm_handle_vblank(struct drm_device *dev, int crtc)
+{
+       drm_update_vblank_count(dev, crtc);
+       DRM_WAKEUP(&dev->vbl_queue[crtc]);
+       drm_vbl_send_signals(dev, crtc);
+}
+EXPORT_SYMBOL(drm_handle_vblank);
 
 /**
  * Tasklet wrapper function.
index d9b560f..93b1e04 100644 (file)
@@ -87,34 +87,35 @@ static struct drm_proc_list {
  * "/proc/dri/%minor%/", and each entry in proc_list as
  * "/proc/dri/%minor%/%name%".
  */
-int drm_proc_init(struct drm_device * dev, int minor,
-                 struct proc_dir_entry *root, struct proc_dir_entry **dev_root)
+int drm_proc_init(struct drm_minor *minor, int minor_id,
+                 struct proc_dir_entry *root)
 {
        struct proc_dir_entry *ent;
        int i, j;
        char name[64];
 
-       sprintf(name, "%d", minor);
-       *dev_root = proc_mkdir(name, root);
-       if (!*dev_root) {
+       sprintf(name, "%d", minor_id);
+       minor->dev_root = proc_mkdir(name, root);
+       if (!minor->dev_root) {
                DRM_ERROR("Cannot create /proc/dri/%s\n", name);
                return -1;
        }
 
        for (i = 0; i < DRM_PROC_ENTRIES; i++) {
                ent = create_proc_entry(drm_proc_list[i].name,
-                                       S_IFREG | S_IRUGO, *dev_root);
+                                       S_IFREG | S_IRUGO, minor->dev_root);
                if (!ent) {
                        DRM_ERROR("Cannot create /proc/dri/%s/%s\n",
                                  name, drm_proc_list[i].name);
                        for (j = 0; j < i; j++)
                                remove_proc_entry(drm_proc_list[i].name,
-                                                 *dev_root);
+                                                 minor->dev_root);
                        remove_proc_entry(name, root);
+                       minor->dev_root = NULL;
                        return -1;
                }
                ent->read_proc = drm_proc_list[i].f;
-               ent->data = dev;
+               ent->data = minor;
        }
 
        return 0;
@@ -130,18 +131,17 @@ int drm_proc_init(struct drm_device * dev, int minor,
  *
  * Remove all proc entries created by proc_init().
  */
-int drm_proc_cleanup(int minor, struct proc_dir_entry *root,
-                    struct proc_dir_entry *dev_root)
+int drm_proc_cleanup(struct drm_minor *minor, struct proc_dir_entry *root)
 {
        int i;
        char name[64];
 
-       if (!root || !dev_root)
+       if (!root || !minor->dev_root)
                return 0;
 
        for (i = 0; i < DRM_PROC_ENTRIES; i++)
-               remove_proc_entry(drm_proc_list[i].name, dev_root);
-       sprintf(name, "%d", minor);
+               remove_proc_entry(drm_proc_list[i].name, minor->dev_root);
+       sprintf(name, "%d", minor->index);
        remove_proc_entry(name, root);
 
        return 0;
@@ -163,7 +163,8 @@ int drm_proc_cleanup(int minor, struct proc_dir_entry *root,
 static int drm_name_info(char *buf, char **start, off_t offset, int request,
                         int *eof, void *data)
 {
-       struct drm_device *dev = (struct drm_device *) data;
+       struct drm_minor *minor = (struct drm_minor *) data;
+       struct drm_device *dev = minor->dev;
        int len = 0;
 
        if (offset > DRM_PROC_LIMIT) {
@@ -205,7 +206,8 @@ static int drm_name_info(char *buf, char **start, off_t offset, int request,
 static int drm__vm_info(char *buf, char **start, off_t offset, int request,
                        int *eof, void *data)
 {
-       struct drm_device *dev = (struct drm_device *) data;
+       struct drm_minor *minor = (struct drm_minor *) data;
+       struct drm_device *dev = minor->dev;
        int len = 0;
        struct drm_map *map;
        struct drm_map_list *r_list;
@@ -261,7 +263,8 @@ static int drm__vm_info(char *buf, char **start, off_t offset, int request,
 static int drm_vm_info(char *buf, char **start, off_t offset, int request,
                       int *eof, void *data)
 {
-       struct drm_device *dev = (struct drm_device *) data;
+       struct drm_minor *minor = (struct drm_minor *) data;
+       struct drm_device *dev = minor->dev;
        int ret;
 
        mutex_lock(&dev->struct_mutex);
@@ -284,7 +287,8 @@ static int drm_vm_info(char *buf, char **start, off_t offset, int request,
 static int drm__queues_info(char *buf, char **start, off_t offset,
                            int request, int *eof, void *data)
 {
-       struct drm_device *dev = (struct drm_device *) data;
+       struct drm_minor *minor = (struct drm_minor *) data;
+       struct drm_device *dev = minor->dev;
        int len = 0;
        int i;
        struct drm_queue *q;
@@ -334,7 +338,8 @@ static int drm__queues_info(char *buf, char **start, off_t offset,
 static int drm_queues_info(char *buf, char **start, off_t offset, int request,
                           int *eof, void *data)
 {
-       struct drm_device *dev = (struct drm_device *) data;
+       struct drm_minor *minor = (struct drm_minor *) data;
+       struct drm_device *dev = minor->dev;
        int ret;
 
        mutex_lock(&dev->struct_mutex);
@@ -357,7 +362,8 @@ static int drm_queues_info(char *buf, char **start, off_t offset, int request,
 static int drm__bufs_info(char *buf, char **start, off_t offset, int request,
                          int *eof, void *data)
 {
-       struct drm_device *dev = (struct drm_device *) data;
+       struct drm_minor *minor = (struct drm_minor *) data;
+       struct drm_device *dev = minor->dev;
        int len = 0;
        struct drm_device_dma *dma = dev->dma;
        int i;
@@ -406,7 +412,8 @@ static int drm__bufs_info(char *buf, char **start, off_t offset, int request,
 static int drm_bufs_info(char *buf, char **start, off_t offset, int request,
                         int *eof, void *data)
 {
-       struct drm_device *dev = (struct drm_device *) data;
+       struct drm_minor *minor = (struct drm_minor *) data;
+       struct drm_device *dev = minor->dev;
        int ret;
 
        mutex_lock(&dev->struct_mutex);
@@ -429,7 +436,8 @@ static int drm_bufs_info(char *buf, char **start, off_t offset, int request,
 static int drm__clients_info(char *buf, char **start, off_t offset,
                             int request, int *eof, void *data)
 {
-       struct drm_device *dev = (struct drm_device *) data;
+       struct drm_minor *minor = (struct drm_minor *) data;
+       struct drm_device *dev = minor->dev;
        int len = 0;
        struct drm_file *priv;
 
@@ -445,7 +453,7 @@ static int drm__clients_info(char *buf, char **start, off_t offset,
        list_for_each_entry(priv, &dev->filelist, lhead) {
                DRM_PROC_PRINT("%c %3d %5d %5d %10u %10lu\n",
                               priv->authenticated ? 'y' : 'n',
-                              priv->minor,
+                              priv->minor->index,
                               priv->pid,
                               priv->uid, priv->magic, priv->ioctl_count);
        }
@@ -462,7 +470,8 @@ static int drm__clients_info(char *buf, char **start, off_t offset,
 static int drm_clients_info(char *buf, char **start, off_t offset,
                            int request, int *eof, void *data)
 {
-       struct drm_device *dev = (struct drm_device *) data;
+       struct drm_minor *minor = (struct drm_minor *) data;
+       struct drm_device *dev = minor->dev;
        int ret;
 
        mutex_lock(&dev->struct_mutex);
@@ -476,7 +485,8 @@ static int drm_clients_info(char *buf, char **start, off_t offset,
 static int drm__vma_info(char *buf, char **start, off_t offset, int request,
                         int *eof, void *data)
 {
-       struct drm_device *dev = (struct drm_device *) data;
+       struct drm_minor *minor = (struct drm_minor *) data;
+       struct drm_device *dev = minor->dev;
        int len = 0;
        struct drm_vma_entry *pt;
        struct vm_area_struct *vma;
@@ -535,7 +545,8 @@ static int drm__vma_info(char *buf, char **start, off_t offset, int request,
 static int drm_vma_info(char *buf, char **start, off_t offset, int request,
                        int *eof, void *data)
 {
-       struct drm_device *dev = (struct drm_device *) data;
+       struct drm_minor *minor = (struct drm_minor *) data;
+       struct drm_device *dev = minor->dev;
        int ret;
 
        mutex_lock(&dev->struct_mutex);
index d93a217..c2f584f 100644 (file)
 #include "drmP.h"
 #include "drm_core.h"
 
-unsigned int drm_cards_limit = 16;     /* Enough for one machine */
 unsigned int drm_debug = 0;    /* 1 to enable debug output */
 EXPORT_SYMBOL(drm_debug);
 
 MODULE_AUTHOR(CORE_AUTHOR);
 MODULE_DESCRIPTION(CORE_DESC);
 MODULE_LICENSE("GPL and additional rights");
-MODULE_PARM_DESC(cards_limit, "Maximum number of graphics cards");
 MODULE_PARM_DESC(debug, "Enable debug output");
 
-module_param_named(cards_limit, drm_cards_limit, int, 0444);
 module_param_named(debug, drm_debug, int, 0600);
 
-struct drm_head **drm_heads;
+struct idr drm_minors_idr;
+
 struct class *drm_class;
 struct proc_dir_entry *drm_proc_root;
 
+static int drm_minor_get_id(struct drm_device *dev, int type)
+{
+       int new_id;
+       int ret;
+       int base = 0, limit = 63;
+
+again:
+       if (idr_pre_get(&drm_minors_idr, GFP_KERNEL) == 0) {
+               DRM_ERROR("Out of memory expanding drawable idr\n");
+               return -ENOMEM;
+       }
+       mutex_lock(&dev->struct_mutex);
+       ret = idr_get_new_above(&drm_minors_idr, NULL,
+                               base, &new_id);
+       mutex_unlock(&dev->struct_mutex);
+       if (ret == -EAGAIN) {
+               goto again;
+       } else if (ret) {
+               return ret;
+       }
+
+       if (new_id >= limit) {
+               idr_remove(&drm_minors_idr, new_id);
+               return -EINVAL;
+       }
+       return new_id;
+}
+
 static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev,
                           const struct pci_device_id *ent,
                           struct drm_driver *driver)
@@ -145,48 +171,60 @@ static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev,
  * create the proc init entry via proc_init(). This routines assigns
  * minor numbers to secondary heads of multi-headed cards
  */
-static int drm_get_head(struct drm_device * dev, struct drm_head * head)
+static int drm_get_minor(struct drm_device *dev, struct drm_minor **minor, int type)
 {
-       struct drm_head **heads = drm_heads;
+       struct drm_minor *new_minor;
        int ret;
-       int minor;
+       int minor_id;
 
        DRM_DEBUG("\n");
 
-       for (minor = 0; minor < drm_cards_limit; minor++, heads++) {
-               if (!*heads) {
-
-                       *head = (struct drm_head) {
-                       .dev = dev,.device =
-                                   MKDEV(DRM_MAJOR, minor),.minor = minor,};
-
-                       if ((ret =
-                            drm_proc_init(dev, minor, drm_proc_root,
-                                          &head->dev_root))) {
-                               printk(KERN_ERR
-                                      "DRM: Failed to initialize /proc/dri.\n");
-                               goto err_g1;
-                       }
-
-                       ret = drm_sysfs_device_add(dev, head);
-                       if (ret) {
-                               printk(KERN_ERR
-                                      "DRM: Error sysfs_device_add.\n");
-                               goto err_g2;
-                       }
-                       *heads = head;
-
-                       DRM_DEBUG("new minor assigned %d\n", minor);
-                       return 0;
+       minor_id = drm_minor_get_id(dev, type);
+       if (minor_id < 0)
+               return minor_id;
+
+       new_minor = kzalloc(sizeof(struct drm_minor), GFP_KERNEL);
+       if (!new_minor) {
+               ret = -ENOMEM;
+               goto err_idr;
+       }
+
+       new_minor->type = type;
+       new_minor->device = MKDEV(DRM_MAJOR, minor_id);
+       new_minor->dev = dev;
+       new_minor->index = minor_id;
+
+       idr_replace(&drm_minors_idr, new_minor, minor_id);
+
+       if (type == DRM_MINOR_LEGACY) {
+               ret = drm_proc_init(new_minor, minor_id, drm_proc_root);
+               if (ret) {
+                       DRM_ERROR("DRM: Failed to initialize /proc/dri.\n");
+                       goto err_mem;
                }
+       } else
+               new_minor->dev_root = NULL;
+
+       ret = drm_sysfs_device_add(new_minor);
+       if (ret) {
+               printk(KERN_ERR
+                      "DRM: Error sysfs_device_add.\n");
+               goto err_g2;
        }
-       DRM_ERROR("out of minors\n");
-       return -ENOMEM;
-      err_g2:
-       drm_proc_cleanup(minor, drm_proc_root, head->dev_root);
-      err_g1:
-       *head = (struct drm_head) {
-       .dev = NULL};
+       *minor = new_minor;
+
+       DRM_DEBUG("new minor assigned %d\n", minor_id);
+       return 0;
+
+
+err_g2:
+       if (new_minor->type == DRM_MINOR_LEGACY)
+               drm_proc_cleanup(new_minor, drm_proc_root);
+err_mem:
+       kfree(new_minor);
+err_idr:
+       idr_remove(&drm_minors_idr, minor_id);
+       *minor = NULL;
        return ret;
 }
 
@@ -222,12 +260,12 @@ int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
                printk(KERN_ERR "DRM: Fill_in_dev failed.\n");
                goto err_g2;
        }
-       if ((ret = drm_get_head(dev, &dev->primary)))
+       if ((ret = drm_get_minor(dev, &dev->primary, DRM_MINOR_LEGACY)))
                goto err_g2;
 
        DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n",
                 driver->name, driver->major, driver->minor, driver->patchlevel,
-                driver->date, dev->primary.minor);
+                driver->date, dev->primary->index);
 
        return 0;
 
@@ -276,18 +314,18 @@ int drm_put_dev(struct drm_device * dev)
  * last minor released.
  *
  */
-int drm_put_head(struct drm_head * head)
+int drm_put_minor(struct drm_minor **minor_p)
 {
-       int minor = head->minor;
-
-       DRM_DEBUG("release secondary minor %d\n", minor);
-
-       drm_proc_cleanup(minor, drm_proc_root, head->dev_root);
-       drm_sysfs_device_remove(head->dev);
+       struct drm_minor *minor = *minor_p;
+       DRM_DEBUG("release secondary minor %d\n", minor->index);
 
-       *head = (struct drm_head) {.dev = NULL};
+       if (minor->type == DRM_MINOR_LEGACY)
+               drm_proc_cleanup(minor, drm_proc_root);
+       drm_sysfs_device_remove(minor);
 
-       drm_heads[minor] = NULL;
+       idr_remove(&drm_minors_idr, minor->index);
 
+       kfree(minor);
+       *minor_p = NULL;
        return 0;
 }
index 05ed504..7a1d9a7 100644 (file)
@@ -19,7 +19,7 @@
 #include "drm_core.h"
 #include "drmP.h"
 
-#define to_drm_device(d) container_of(d, struct drm_device, dev)
+#define to_drm_minor(d) container_of(d, struct drm_minor, kdev)
 
 /**
  * drm_sysfs_suspend - DRM class suspend hook
@@ -31,7 +31,8 @@
  */
 static int drm_sysfs_suspend(struct device *dev, pm_message_t state)
 {
-       struct drm_device *drm_dev = to_drm_device(dev);
+       struct drm_minor *drm_minor = to_drm_minor(dev);
+       struct drm_device *drm_dev = drm_minor->dev;
 
        printk(KERN_ERR "%s\n", __FUNCTION__);
 
@@ -50,7 +51,8 @@ static int drm_sysfs_suspend(struct device *dev, pm_message_t state)
  */
 static int drm_sysfs_resume(struct device *dev)
 {
-       struct drm_device *drm_dev = to_drm_device(dev);
+       struct drm_minor *drm_minor = to_drm_minor(dev);
+       struct drm_device *drm_dev = drm_minor->dev;
 
        if (drm_dev->driver->resume)
                return drm_dev->driver->resume(drm_dev);
@@ -120,10 +122,11 @@ void drm_sysfs_destroy(void)
 static ssize_t show_dri(struct device *device, struct device_attribute *attr,
                        char *buf)
 {
-       struct drm_device *dev = to_drm_device(device);
-       if (dev->driver->dri_library_name)
-               return dev->driver->dri_library_name(dev, buf);
-       return snprintf(buf, PAGE_SIZE, "%s\n", dev->driver->pci_driver.name);
+       struct drm_minor *drm_minor = to_drm_minor(device);
+       struct drm_device *drm_dev = drm_minor->dev;
+       if (drm_dev->driver->dri_library_name)
+               return drm_dev->driver->dri_library_name(drm_dev, buf);
+       return snprintf(buf, PAGE_SIZE, "%s\n", drm_dev->driver->pci_driver.name);
 }
 
 static struct device_attribute device_attrs[] = {
@@ -152,25 +155,28 @@ static void drm_sysfs_device_release(struct device *dev)
  * as the parent for the Linux device, and make sure it has a file containing
  * the driver we're using (for userspace compatibility).
  */
-int drm_sysfs_device_add(struct drm_device *dev, struct drm_head *head)
+int drm_sysfs_device_add(struct drm_minor *minor)
 {
        int err;
        int i, j;
+       char *minor_str;
 
-       dev->dev.parent = &dev->pdev->dev;
-       dev->dev.class = drm_class;
-       dev->dev.release = drm_sysfs_device_release;
-       dev->dev.devt = head->device;
-       snprintf(dev->dev.bus_id, BUS_ID_SIZE, "card%d", head->minor);
+       minor->kdev.parent = &minor->dev->pdev->dev;
+       minor->kdev.class = drm_class;
+       minor->kdev.release = drm_sysfs_device_release;
+       minor->kdev.devt = minor->device;
+       minor_str = "card%d";
 
-       err = device_register(&dev->dev);
+       snprintf(minor->kdev.bus_id, BUS_ID_SIZE, minor_str, minor->index);
+
+       err = device_register(&minor->kdev);
        if (err) {
                DRM_ERROR("device add failed: %d\n", err);
                goto err_out;
        }
 
        for (i = 0; i < ARRAY_SIZE(device_attrs); i++) {
-               err = device_create_file(&dev->dev, &device_attrs[i]);
+               err = device_create_file(&minor->kdev, &device_attrs[i]);
                if (err)
                        goto err_out_files;
        }
@@ -180,8 +186,8 @@ int drm_sysfs_device_add(struct drm_device *dev, struct drm_head *head)
 err_out_files:
        if (i > 0)
                for (j = 0; j < i; j++)
-                       device_remove_file(&dev->dev, &device_attrs[i]);
-       device_unregister(&dev->dev);
+                       device_remove_file(&minor->kdev, &device_attrs[i]);
+       device_unregister(&minor->kdev);
 err_out:
 
        return err;
@@ -194,11 +200,11 @@ err_out:
  * This call unregisters and cleans up a class device that was created with a
  * call to drm_sysfs_device_add()
  */
-void drm_sysfs_device_remove(struct drm_device *dev)
+void drm_sysfs_device_remove(struct drm_minor *minor)
 {
        int i;
 
        for (i = 0; i < ARRAY_SIZE(device_attrs); i++)
-               device_remove_file(&dev->dev, &device_attrs[i]);
-       device_unregister(&dev->dev);
+               device_remove_file(&minor->kdev, &device_attrs[i]);
+       device_unregister(&minor->kdev);
 }
index 945df72..c234c6f 100644 (file)
@@ -90,7 +90,7 @@ static pgprot_t drm_dma_prot(uint32_t map_type, struct vm_area_struct *vma)
 static int drm_do_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 {
        struct drm_file *priv = vma->vm_file->private_data;
-       struct drm_device *dev = priv->head->dev;
+       struct drm_device *dev = priv->minor->dev;
        struct drm_map *map = NULL;
        struct drm_map_list *r_list;
        struct drm_hash_item *hash;
@@ -207,7 +207,7 @@ static int drm_do_vm_shm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 static void drm_vm_shm_close(struct vm_area_struct *vma)
 {
        struct drm_file *priv = vma->vm_file->private_data;
-       struct drm_device *dev = priv->head->dev;
+       struct drm_device *dev = priv->minor->dev;
        struct drm_vma_entry *pt, *temp;
        struct drm_map *map;
        struct drm_map_list *r_list;
@@ -286,7 +286,7 @@ static void drm_vm_shm_close(struct vm_area_struct *vma)
 static int drm_do_vm_dma_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 {
        struct drm_file *priv = vma->vm_file->private_data;
-       struct drm_device *dev = priv->head->dev;
+       struct drm_device *dev = priv->minor->dev;
        struct drm_device_dma *dma = dev->dma;
        unsigned long offset;
        unsigned long page_nr;
@@ -321,7 +321,7 @@ static int drm_do_vm_sg_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 {
        struct drm_map *map = (struct drm_map *) vma->vm_private_data;
        struct drm_file *priv = vma->vm_file->private_data;
-       struct drm_device *dev = priv->head->dev;
+       struct drm_device *dev = priv->minor->dev;
        struct drm_sg_mem *entry = dev->sg;
        unsigned long offset;
        unsigned long map_offset;
@@ -402,7 +402,7 @@ static struct vm_operations_struct drm_vm_sg_ops = {
 static void drm_vm_open_locked(struct vm_area_struct *vma)
 {
        struct drm_file *priv = vma->vm_file->private_data;
-       struct drm_device *dev = priv->head->dev;
+       struct drm_device *dev = priv->minor->dev;
        struct drm_vma_entry *vma_entry;
 
        DRM_DEBUG("0x%08lx,0x%08lx\n",
@@ -420,7 +420,7 @@ static void drm_vm_open_locked(struct vm_area_struct *vma)
 static void drm_vm_open(struct vm_area_struct *vma)
 {
        struct drm_file *priv = vma->vm_file->private_data;
-       struct drm_device *dev = priv->head->dev;
+       struct drm_device *dev = priv->minor->dev;
 
        mutex_lock(&dev->struct_mutex);
        drm_vm_open_locked(vma);
@@ -438,7 +438,7 @@ static void drm_vm_open(struct vm_area_struct *vma)
 static void drm_vm_close(struct vm_area_struct *vma)
 {
        struct drm_file *priv = vma->vm_file->private_data;
-       struct drm_device *dev = priv->head->dev;
+       struct drm_device *dev = priv->minor->dev;
        struct drm_vma_entry *pt, *temp;
 
        DRM_DEBUG("0x%08lx,0x%08lx\n",
@@ -473,7 +473,7 @@ static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma)
        struct drm_device_dma *dma;
        unsigned long length = vma->vm_end - vma->vm_start;
 
-       dev = priv->head->dev;
+       dev = priv->minor->dev;
        dma = dev->dma;
        DRM_DEBUG("start = 0x%lx, end = 0x%lx, page offset = 0x%lx\n",
                  vma->vm_start, vma->vm_end, vma->vm_pgoff);
@@ -543,7 +543,7 @@ EXPORT_SYMBOL(drm_core_get_reg_ofs);
 static int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma)
 {
        struct drm_file *priv = filp->private_data;
-       struct drm_device *dev = priv->head->dev;
+       struct drm_device *dev = priv->minor->dev;
        struct drm_map *map = NULL;
        unsigned long offset = 0;
        struct drm_hash_item *hash;
@@ -640,12 +640,12 @@ static int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma)
                /* Don't let this area swap.  Change when
                   DRM_KERNEL advisory is supported. */
                vma->vm_flags |= VM_RESERVED;
-               vma->vm_page_prot = drm_dma_prot(map->type, vma);
                break;
        case _DRM_SCATTER_GATHER:
                vma->vm_ops = &drm_vm_sg_ops;
                vma->vm_private_data = (void *)map;
                vma->vm_flags |= VM_RESERVED;
+               vma->vm_page_prot = drm_dma_prot(map->type, vma);
                break;
        default:
                return -EINVAL; /* This should never happen. */
@@ -661,7 +661,7 @@ static int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma)
 int drm_mmap(struct file *filp, struct vm_area_struct *vma)
 {
        struct drm_file *priv = filp->private_data;
-       struct drm_device *dev = priv->head->dev;
+       struct drm_device *dev = priv->minor->dev;
        int ret;
 
        mutex_lock(&dev->struct_mutex);
index 8d7ea81..e5de8ea 100644 (file)
@@ -94,7 +94,7 @@ static int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
        drm_i810_buf_priv_t *buf_priv;
 
        lock_kernel();
-       dev = priv->head->dev;
+       dev = priv->minor->dev;
        dev_priv = dev->dev_private;
        buf = dev_priv->mmap_buffer;
        buf_priv = buf->dev_private;
@@ -122,7 +122,7 @@ static const struct file_operations i810_buffer_fops = {
 
 static int i810_map_buffer(struct drm_buf * buf, struct drm_file *file_priv)
 {
-       struct drm_device *dev = file_priv->head->dev;
+       struct drm_device *dev = file_priv->minor->dev;
        drm_i810_buf_priv_t *buf_priv = buf->dev_private;
        drm_i810_private_t *dev_priv = dev->dev_private;
        const struct file_operations *old_fops;
index 9df0810..60c9376 100644 (file)
@@ -96,7 +96,7 @@ static int i830_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
        drm_i830_buf_priv_t *buf_priv;
 
        lock_kernel();
-       dev = priv->head->dev;
+       dev = priv->minor->dev;
        dev_priv = dev->dev_private;
        buf = dev_priv->mmap_buffer;
        buf_priv = buf->dev_private;
@@ -124,7 +124,7 @@ static const struct file_operations i830_buffer_fops = {
 
 static int i830_map_buffer(struct drm_buf * buf, struct drm_file *file_priv)
 {
-       struct drm_device *dev = file_priv->head->dev;
+       struct drm_device *dev = file_priv->minor->dev;
        drm_i830_buf_priv_t *buf_priv = buf->dev_private;
        drm_i830_private_t *dev_priv = dev->dev_private;
        const struct file_operations *old_fops;
index a043bb1..ef7bf14 100644 (file)
@@ -415,10 +415,13 @@ static void i915_emit_breadcrumb(struct drm_device *dev)
        drm_i915_private_t *dev_priv = dev->dev_private;
        RING_LOCALS;
 
-       dev_priv->sarea_priv->last_enqueue = ++dev_priv->counter;
+       if (++dev_priv->counter > BREADCRUMB_MASK) {
+                dev_priv->counter = 1;
+                DRM_DEBUG("Breadcrumb counter wrapped around\n");
+       }
 
-       if (dev_priv->counter > 0x7FFFFFFFUL)
-               dev_priv->sarea_priv->last_enqueue = dev_priv->counter = 1;
+       if (dev_priv->sarea_priv)
+               dev_priv->sarea_priv->last_enqueue = dev_priv->counter;
 
        BEGIN_LP_RING(4);
        OUT_RING(CMD_STORE_DWORD_IDX);
@@ -428,6 +431,26 @@ static void i915_emit_breadcrumb(struct drm_device *dev)
        ADVANCE_LP_RING();
 }
 
+int i915_emit_mi_flush(struct drm_device *dev, uint32_t flush)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       uint32_t flush_cmd = CMD_MI_FLUSH;
+       RING_LOCALS;
+
+       flush_cmd |= flush;
+
+       i915_kernel_lost_context(dev);
+
+       BEGIN_LP_RING(4);
+       OUT_RING(flush_cmd);
+       OUT_RING(0);
+       OUT_RING(0);
+       OUT_RING(0);
+       ADVANCE_LP_RING();
+
+       return 0;
+}
+
 static int i915_dispatch_cmdbuffer(struct drm_device * dev,
                                   drm_i915_cmdbuffer_t * cmd)
 {
@@ -511,52 +534,74 @@ static int i915_dispatch_batchbuffer(struct drm_device * dev,
        return 0;
 }
 
-static int i915_dispatch_flip(struct drm_device * dev)
+static void i915_do_dispatch_flip(struct drm_device * dev, int plane, int sync)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
+       u32 num_pages, current_page, next_page, dspbase;
+       int shift = 2 * plane, x, y;
        RING_LOCALS;
 
-       DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n",
-                 __FUNCTION__,
-                 dev_priv->current_page,
-                 dev_priv->sarea_priv->pf_current_page);
+       /* Calculate display base offset */
+       num_pages = dev_priv->sarea_priv->third_handle ? 3 : 2;
+       current_page = (dev_priv->sarea_priv->pf_current_page >> shift) & 0x3;
+       next_page = (current_page + 1) % num_pages;
 
-       i915_kernel_lost_context(dev);
-
-       BEGIN_LP_RING(2);
-       OUT_RING(INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE);
-       OUT_RING(0);
-       ADVANCE_LP_RING();
+       switch (next_page) {
+       default:
+       case 0:
+               dspbase = dev_priv->sarea_priv->front_offset;
+               break;
+       case 1:
+               dspbase = dev_priv->sarea_priv->back_offset;
+               break;
+       case 2:
+               dspbase = dev_priv->sarea_priv->third_offset;
+               break;
+       }
 
-       BEGIN_LP_RING(6);
-       OUT_RING(CMD_OP_DISPLAYBUFFER_INFO | ASYNC_FLIP);
-       OUT_RING(0);
-       if (dev_priv->current_page == 0) {
-               OUT_RING(dev_priv->back_offset);
-               dev_priv->current_page = 1;
+       if (plane == 0) {
+               x = dev_priv->sarea_priv->planeA_x;
+               y = dev_priv->sarea_priv->planeA_y;
        } else {
-               OUT_RING(dev_priv->front_offset);
-               dev_priv->current_page = 0;
+               x = dev_priv->sarea_priv->planeB_x;
+               y = dev_priv->sarea_priv->planeB_y;
        }
-       OUT_RING(0);
-       ADVANCE_LP_RING();
 
-       BEGIN_LP_RING(2);
-       OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_PLANE_A_FLIP);
-       OUT_RING(0);
-       ADVANCE_LP_RING();
+       dspbase += (y * dev_priv->sarea_priv->pitch + x) * dev_priv->cpp;
 
-       dev_priv->sarea_priv->last_enqueue = dev_priv->counter++;
+       DRM_DEBUG("plane=%d current_page=%d dspbase=0x%x\n", plane, current_page,
+                 dspbase);
 
        BEGIN_LP_RING(4);
-       OUT_RING(CMD_STORE_DWORD_IDX);
-       OUT_RING(20);
-       OUT_RING(dev_priv->counter);
-       OUT_RING(0);
+       OUT_RING(sync ? 0 :
+                (MI_WAIT_FOR_EVENT | (plane ? MI_WAIT_FOR_PLANE_B_FLIP :
+                                      MI_WAIT_FOR_PLANE_A_FLIP)));
+       OUT_RING(CMD_OP_DISPLAYBUFFER_INFO | (sync ? 0 : ASYNC_FLIP) |
+                (plane ? DISPLAY_PLANE_B : DISPLAY_PLANE_A));
+       OUT_RING(dev_priv->sarea_priv->pitch * dev_priv->cpp);
+       OUT_RING(dspbase);
        ADVANCE_LP_RING();
 
-       dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
-       return 0;
+       dev_priv->sarea_priv->pf_current_page &= ~(0x3 << shift);
+       dev_priv->sarea_priv->pf_current_page |= next_page << shift;
+}
+
+void i915_dispatch_flip(struct drm_device * dev, int planes, int sync)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       int i;
+
+       DRM_DEBUG("planes=0x%x pfCurrentPage=%d\n",
+                 planes, dev_priv->sarea_priv->pf_current_page);
+
+       i915_emit_mi_flush(dev, MI_READ_FLUSH | MI_EXE_FLUSH);
+
+       for (i = 0; i < 2; i++)
+               if (planes & (1 << i))
+                       i915_do_dispatch_flip(dev, i, sync);
+
+       i915_emit_breadcrumb(dev);
+
 }
 
 static int i915_quiescent(struct drm_device * dev)
@@ -579,7 +624,6 @@ static int i915_batchbuffer(struct drm_device *dev, void *data,
                            struct drm_file *file_priv)
 {
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-       u32 *hw_status = dev_priv->hw_status_page;
        drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
            dev_priv->sarea_priv;
        drm_i915_batchbuffer_t *batch = data;
@@ -602,7 +646,7 @@ static int i915_batchbuffer(struct drm_device *dev, void *data,
 
        ret = i915_dispatch_batchbuffer(dev, batch);
 
-       sarea_priv->last_dispatch = (int)hw_status[5];
+       sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
        return ret;
 }
 
@@ -610,7 +654,6 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data,
                          struct drm_file *file_priv)
 {
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-       u32 *hw_status = dev_priv->hw_status_page;
        drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
            dev_priv->sarea_priv;
        drm_i915_cmdbuffer_t *cmdbuf = data;
@@ -635,18 +678,51 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data,
                return ret;
        }
 
-       sarea_priv->last_dispatch = (int)hw_status[5];
+       sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
+       return 0;
+}
+
+static int i915_do_cleanup_pageflip(struct drm_device * dev)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       int i, planes, num_pages = dev_priv->sarea_priv->third_handle ? 3 : 2;
+
+       DRM_DEBUG("\n");
+
+       for (i = 0, planes = 0; i < 2; i++)
+               if (dev_priv->sarea_priv->pf_current_page & (0x3 << (2 * i))) {
+                       dev_priv->sarea_priv->pf_current_page =
+                               (dev_priv->sarea_priv->pf_current_page &
+                                ~(0x3 << (2 * i))) | ((num_pages - 1) << (2 * i));
+
+                       planes |= 1 << i;
+               }
+
+       if (planes)
+               i915_dispatch_flip(dev, planes, 0);
+
        return 0;
 }
 
 static int i915_flip_bufs(struct drm_device *dev, void *data,
                          struct drm_file *file_priv)
 {
-       DRM_DEBUG("%s\n", __FUNCTION__);
+       drm_i915_flip_t *param = data;
+
+       DRM_DEBUG("\n");
 
        LOCK_TEST_WITH_RETURN(dev, file_priv);
 
-       return i915_dispatch_flip(dev);
+       /* This is really planes */
+       if (param->pipes & ~0x3) {
+               DRM_ERROR("Invalid planes 0x%x, only <= 0x3 is valid\n",
+                         param->pipes);
+               return -EINVAL;
+       }
+
+       i915_dispatch_flip(dev, param->pipes, 0);
+
+       return 0;
 }
 
 static int i915_getparam(struct drm_device *dev, void *data,
@@ -807,6 +883,8 @@ void i915_driver_lastclose(struct drm_device * dev)
        if (!dev_priv)
                return;
 
+       if (drm_getsarea(dev) && dev_priv->sarea_priv)
+               i915_do_cleanup_pageflip(dev);
        if (dev_priv->agp_heap)
                i915_mem_takedown(&(dev_priv->agp_heap));
 
index 05c66cf..0431c00 100644 (file)
@@ -105,14 +105,29 @@ typedef struct _drm_i915_sarea {
        unsigned int rotated_tiled;
        unsigned int rotated2_tiled;
 
-       int pipeA_x;
-       int pipeA_y;
-       int pipeA_w;
-       int pipeA_h;
-       int pipeB_x;
-       int pipeB_y;
-       int pipeB_w;
-       int pipeB_h;
+       int planeA_x;
+       int planeA_y;
+       int planeA_w;
+       int planeA_h;
+       int planeB_x;
+       int planeB_y;
+       int planeB_w;
+       int planeB_h;
+
+       /* Triple buffering */
+       drm_handle_t third_handle;
+       int third_offset;
+       int third_size;
+       unsigned int third_tiled;
+
+       /* buffer object handles for the static buffers.  May change
+        * over the lifetime of the client, though it doesn't in our current
+        * implementation.
+        */
+       unsigned int front_bo_handle;
+       unsigned int back_bo_handle;
+       unsigned int third_bo_handle;
+       unsigned int depth_bo_handle;
 } drm_i915_sarea_t;
 
 /* Flags for perf_boxes
@@ -146,7 +161,7 @@ typedef struct _drm_i915_sarea {
 
 #define DRM_IOCTL_I915_INIT            DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
 #define DRM_IOCTL_I915_FLUSH           DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH)
-#define DRM_IOCTL_I915_FLIP            DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLIP)
+#define DRM_IOCTL_I915_FLIP            DRM_IOW( DRM_COMMAND_BASE + DRM_I915_FLIP, drm_i915_flip_t)
 #define DRM_IOCTL_I915_BATCHBUFFER     DRM_IOW( DRM_COMMAND_BASE + DRM_I915_BATCHBUFFER, drm_i915_batchbuffer_t)
 #define DRM_IOCTL_I915_IRQ_EMIT         DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_IRQ_EMIT, drm_i915_irq_emit_t)
 #define DRM_IOCTL_I915_IRQ_WAIT         DRM_IOW( DRM_COMMAND_BASE + DRM_I915_IRQ_WAIT, drm_i915_irq_wait_t)
@@ -161,6 +176,18 @@ typedef struct _drm_i915_sarea {
 #define DRM_IOCTL_I915_GET_VBLANK_PIPE DRM_IOR( DRM_COMMAND_BASE + DRM_I915_GET_VBLANK_PIPE, drm_i915_vblank_pipe_t)
 #define DRM_IOCTL_I915_VBLANK_SWAP     DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_VBLANK_SWAP, drm_i915_vblank_swap_t)
 
+/* Asynchronous page flipping:
+ */
+typedef struct drm_i915_flip {
+       /*
+        * This is really talking about planes, and we could rename it
+        * except for the fact that some of the duplicated i915_drm.h files
+        * out there check for HAVE_I915_FLIP and so might pick up this
+        * version.
+        */
+       int pipes;
+} drm_i915_flip_t;
+
 /* Allow drivers to submit batchbuffers directly to hardware, relying
  * on the security mechanisms provided by hardware.
  */
index b2b451d..bb8f1b2 100644 (file)
@@ -533,8 +533,7 @@ static struct drm_driver driver = {
         */
        .driver_features =
            DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | /* DRIVER_USE_MTRR |*/
-           DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL |
-           DRIVER_IRQ_VBL2,
+           DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED,
        .load = i915_driver_load,
        .unload = i915_driver_unload,
        .lastclose = i915_driver_lastclose,
@@ -542,8 +541,9 @@ static struct drm_driver driver = {
        .suspend = i915_suspend,
        .resume = i915_resume,
        .device_is_agp = i915_driver_device_is_agp,
-       .vblank_wait = i915_driver_vblank_wait,
-       .vblank_wait2 = i915_driver_vblank_wait2,
+       .get_vblank_counter = i915_get_vblank_counter,
+       .enable_vblank = i915_enable_vblank,
+       .disable_vblank = i915_disable_vblank,
        .irq_preinstall = i915_driver_irq_preinstall,
        .irq_postinstall = i915_driver_irq_postinstall,
        .irq_uninstall = i915_driver_irq_uninstall,
index 675d88b..c614d78 100644 (file)
@@ -76,8 +76,9 @@ struct mem_block {
 typedef struct _drm_i915_vbl_swap {
        struct list_head head;
        drm_drawable_t drw_id;
-       unsigned int pipe;
+       unsigned int plane;
        unsigned int sequence;
+       int flip;
 } drm_i915_vbl_swap_t;
 
 typedef struct drm_i915_private {
@@ -90,7 +91,7 @@ typedef struct drm_i915_private {
        drm_dma_handle_t *status_page_dmah;
        void *hw_status_page;
        dma_addr_t dma_status_page;
-       unsigned long counter;
+       uint32_t counter;
        unsigned int status_gfx_addr;
        drm_local_map_t hws_map;
 
@@ -103,13 +104,18 @@ typedef struct drm_i915_private {
 
        wait_queue_head_t irq_queue;
        atomic_t irq_received;
-       atomic_t irq_emitted;
+       atomic_t irq_emited;
 
        int tex_lru_log_granularity;
        int allow_batchbuffer;
        struct mem_block *agp_heap;
        unsigned int sr01, adpa, ppcr, dvob, dvoc, lvds;
        int vblank_pipe;
+       spinlock_t user_irq_lock;
+       int user_irq_refcount;
+       int fence_irq_on;
+       uint32_t irq_enable_reg;
+       int irq_enabled;
 
        spinlock_t swaps_lock;
        drm_i915_vbl_swap_t vbl_swaps;
@@ -216,7 +222,7 @@ extern void i915_driver_preclose(struct drm_device *dev,
 extern int i915_driver_device_is_agp(struct drm_device * dev);
 extern long i915_compat_ioctl(struct file *filp, unsigned int cmd,
                              unsigned long arg);
-
+extern void i915_dispatch_flip(struct drm_device * dev, int pipes, int sync);
 /* i915_irq.c */
 extern int i915_irq_emit(struct drm_device *dev, void *data,
                         struct drm_file *file_priv);
@@ -227,7 +233,7 @@ extern int i915_driver_vblank_wait(struct drm_device *dev, unsigned int *sequenc
 extern int i915_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence);
 extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS);
 extern void i915_driver_irq_preinstall(struct drm_device * dev);
-extern void i915_driver_irq_postinstall(struct drm_device * dev);
+extern int i915_driver_irq_postinstall(struct drm_device * dev);
 extern void i915_driver_irq_uninstall(struct drm_device * dev);
 extern int i915_vblank_pipe_set(struct drm_device *dev, void *data,
                                struct drm_file *file_priv);
@@ -235,6 +241,9 @@ extern int i915_vblank_pipe_get(struct drm_device *dev, void *data,
                                struct drm_file *file_priv);
 extern int i915_vblank_swap(struct drm_device *dev, void *data,
                            struct drm_file *file_priv);
+extern int i915_enable_vblank(struct drm_device *dev, int crtc);
+extern void i915_disable_vblank(struct drm_device *dev, int crtc);
+extern u32 i915_get_vblank_counter(struct drm_device *dev, int crtc);
 
 /* i915_mem.c */
 extern int i915_mem_alloc(struct drm_device *dev, void *data,
@@ -379,21 +388,91 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
 
 /* Interrupt bits:
  */
-#define USER_INT_FLAG    (1<<1)
-#define VSYNC_PIPEB_FLAG (1<<5)
-#define VSYNC_PIPEA_FLAG (1<<7)
-#define HWB_OOM_FLAG     (1<<13) /* binner out of memory */
+#define I915_PIPE_CONTROL_NOTIFY_INTERRUPT             (1<<18)
+#define I915_DISPLAY_PORT_INTERRUPT                    (1<<17)
+#define I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT     (1<<15)
+#define I915_GMCH_THERMAL_SENSOR_EVENT_INTERRUPT       (1<<14)
+#define I915_HWB_OOM_INTERRUPT                         (1<<13) /* binner out of memory */
+#define I915_SYNC_STATUS_INTERRUPT                     (1<<12)
+#define I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT    (1<<11)
+#define I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT    (1<<10)
+#define I915_OVERLAY_PLANE_FLIP_PENDING_INTERRUPT      (1<<9)
+#define I915_DISPLAY_PLANE_C_FLIP_PENDING_INTERRUPT    (1<<8)
+#define I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT           (1<<7)
+#define I915_DISPLAY_PIPE_A_EVENT_INTERRUPT            (1<<6)
+#define I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT           (1<<5)
+#define I915_DISPLAY_PIPE_B_EVENT_INTERRUPT            (1<<4)
+#define I915_DEBUG_INTERRUPT                           (1<<2)
+#define I915_USER_INTERRUPT                            (1<<1)
+
 
 #define I915REG_HWSTAM         0x02098
 #define I915REG_INT_IDENTITY_R 0x020a4
 #define I915REG_INT_MASK_R     0x020a8
 #define I915REG_INT_ENABLE_R   0x020a0
+#define I915REG_INSTPM         0x020c0
+
+#define PIPEADSL               0x70000
+#define PIPEBDSL               0x71000
 
 #define I915REG_PIPEASTAT      0x70024
 #define I915REG_PIPEBSTAT      0x71024
+/*
+ * The two pipe frame counter registers are not synchronized, so
+ * reading a stable value is somewhat tricky. The following code
+ * should work:
+ *
+ *  do {
+ *    high1 = ((INREG(PIPEAFRAMEHIGH) & PIPE_FRAME_HIGH_MASK) >>
+ *             PIPE_FRAME_HIGH_SHIFT;
+ *    low1 =  ((INREG(PIPEAFRAMEPIXEL) & PIPE_FRAME_LOW_MASK) >>
+ *             PIPE_FRAME_LOW_SHIFT);
+ *    high2 = ((INREG(PIPEAFRAMEHIGH) & PIPE_FRAME_HIGH_MASK) >>
+ *             PIPE_FRAME_HIGH_SHIFT);
+ *  } while (high1 != high2);
+ *  frame = (high1 << 8) | low1;
+ */
+#define PIPEAFRAMEHIGH          0x70040
+#define PIPEBFRAMEHIGH         0x71040
+#define PIPE_FRAME_HIGH_MASK    0x0000ffff
+#define PIPE_FRAME_HIGH_SHIFT   0
+#define PIPEAFRAMEPIXEL         0x70044
+#define PIPEBFRAMEPIXEL                0x71044
 
-#define I915_VBLANK_INTERRUPT_ENABLE   (1UL<<17)
-#define I915_VBLANK_CLEAR              (1UL<<1)
+#define PIPE_FRAME_LOW_MASK     0xff000000
+#define PIPE_FRAME_LOW_SHIFT    24
+/*
+ * Pixel within the current frame is counted in the PIPEAFRAMEPIXEL register
+ * and is 24 bits wide.
+ */
+#define PIPE_PIXEL_MASK         0x00ffffff
+#define PIPE_PIXEL_SHIFT        0
+
+#define I915_FIFO_UNDERRUN_STATUS              (1UL<<31)
+#define I915_CRC_ERROR_ENABLE                  (1UL<<29)
+#define I915_CRC_DONE_ENABLE                   (1UL<<28)
+#define I915_GMBUS_EVENT_ENABLE                        (1UL<<27)
+#define I915_VSYNC_INTERRUPT_ENABLE            (1UL<<25)
+#define I915_DISPLAY_LINE_COMPARE_ENABLE       (1UL<<24)
+#define I915_DPST_EVENT_ENABLE                 (1UL<<23)
+#define I915_LEGACY_BLC_EVENT_ENABLE           (1UL<<22)
+#define I915_ODD_FIELD_INTERRUPT_ENABLE                (1UL<<21)
+#define I915_EVEN_FIELD_INTERRUPT_ENABLE       (1UL<<20)
+#define I915_START_VBLANK_INTERRUPT_ENABLE     (1UL<<18)       /* 965 or later */
+#define I915_VBLANK_INTERRUPT_ENABLE           (1UL<<17)
+#define I915_OVERLAY_UPDATED_ENABLE            (1UL<<16)
+#define I915_CRC_ERROR_INTERRUPT_STATUS                (1UL<<13)
+#define I915_CRC_DONE_INTERRUPT_STATUS         (1UL<<12)
+#define I915_GMBUS_INTERRUPT_STATUS            (1UL<<11)
+#define I915_VSYNC_INTERRUPT_STATUS            (1UL<<9)
+#define I915_DISPLAY_LINE_COMPARE_STATUS       (1UL<<8)
+#define I915_DPST_EVENT_STATUS                 (1UL<<7)
+#define I915_LEGACY_BLC_EVENT_STATUS           (1UL<<6)
+#define I915_ODD_FIELD_INTERRUPT_STATUS                (1UL<<5)
+#define I915_EVEN_FIELD_INTERRUPT_STATUS       (1UL<<4)
+#define I915_START_VBLANK_INTERRUPT_STATUS     (1UL<<2)        /* 965 or later */
+#define I915_VBLANK_INTERRUPT_STATUS           (1UL<<1)
+#define I915_OVERLAY_UPDATED_STATUS            (1UL<<0)
 
 #define SRX_INDEX              0x3c4
 #define SRX_DATA               0x3c5
@@ -566,6 +645,8 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
 #define XY_SRC_COPY_BLT_CMD            ((2<<29)|(0x53<<22)|6)
 #define XY_SRC_COPY_BLT_WRITE_ALPHA    (1<<21)
 #define XY_SRC_COPY_BLT_WRITE_RGB      (1<<20)
+#define XY_SRC_COPY_BLT_SRC_TILED      (1<<15)
+#define XY_SRC_COPY_BLT_DST_TILED      (1<<11)
 
 #define MI_BATCH_BUFFER                ((0x30<<23)|1)
 #define MI_BATCH_BUFFER_START  (0x31<<23)
index 92653b3..023ce66 100644 (file)
 #define MAX_NOPID ((u32)~0)
 
 /**
+ * i915_get_pipe - return the the pipe associated with a given plane
+ * @dev: DRM device
+ * @plane: plane to look for
+ *
+ * The Intel Mesa & 2D drivers call the vblank routines with a plane number
+ * rather than a pipe number, since they may not always be equal.  This routine
+ * maps the given @plane back to a pipe number.
+ */
+static int
+i915_get_pipe(struct drm_device *dev, int plane)
+{
+       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+       u32 dspcntr;
+
+       dspcntr = plane ? I915_READ(DSPBCNTR) : I915_READ(DSPACNTR);
+
+       return dspcntr & DISPPLANE_SEL_PIPE_MASK ? 1 : 0;
+}
+
+/**
+ * i915_get_plane - return the the plane associated with a given pipe
+ * @dev: DRM device
+ * @pipe: pipe to look for
+ *
+ * The Intel Mesa & 2D drivers call the vblank routines with a plane number
+ * rather than a plane number, since they may not always be equal.  This routine
+ * maps the given @pipe back to a plane number.
+ */
+static int
+i915_get_plane(struct drm_device *dev, int pipe)
+{
+       if (i915_get_pipe(dev, 0) == pipe)
+               return 0;
+       return 1;
+}
+
+/**
+ * i915_pipe_enabled - check if a pipe is enabled
+ * @dev: DRM device
+ * @pipe: pipe to check
+ *
+ * Reading certain registers when the pipe is disabled can hang the chip.
+ * Use this routine to make sure the PLL is running and the pipe is active
+ * before reading such registers if unsure.
+ */
+static int
+i915_pipe_enabled(struct drm_device *dev, int pipe)
+{
+       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+       unsigned long pipeconf = pipe ? PIPEBCONF : PIPEACONF;
+
+       if (I915_READ(pipeconf) & PIPEACONF_ENABLE)
+               return 1;
+
+       return 0;
+}
+
+/**
+ * Emit a synchronous flip.
+ *
+ * This function must be called with the drawable spinlock held.
+ */
+static void
+i915_dispatch_vsync_flip(struct drm_device *dev, struct drm_drawable_info *drw,
+                        int plane)
+{
+       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+       drm_i915_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       u16 x1, y1, x2, y2;
+       int pf_planes = 1 << plane;
+
+       /* If the window is visible on the other plane, we have to flip on that
+        * plane as well.
+        */
+       if (plane == 1) {
+               x1 = sarea_priv->planeA_x;
+               y1 = sarea_priv->planeA_y;
+               x2 = x1 + sarea_priv->planeA_w;
+               y2 = y1 + sarea_priv->planeA_h;
+       } else {
+               x1 = sarea_priv->planeB_x;
+               y1 = sarea_priv->planeB_y;
+               x2 = x1 + sarea_priv->planeB_w;
+               y2 = y1 + sarea_priv->planeB_h;
+       }
+
+       if (x2 > 0 && y2 > 0) {
+               int i, num_rects = drw->num_rects;
+               struct drm_clip_rect *rect = drw->rects;
+
+               for (i = 0; i < num_rects; i++)
+                       if (!(rect[i].x1 >= x2 || rect[i].y1 >= y2 ||
+                             rect[i].x2 <= x1 || rect[i].y2 <= y1)) {
+                               pf_planes = 0x3;
+
+                               break;
+                       }
+       }
+
+       i915_dispatch_flip(dev, pf_planes, 1);
+}
+
+/**
  * Emit blits for scheduled buffer swaps.
  *
  * This function will be called with the HW lock held.
 static void i915_vblank_tasklet(struct drm_device *dev)
 {
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-       unsigned long irqflags;
        struct list_head *list, *tmp, hits, *hit;
-       int nhits, nrects, slice[2], upper[2], lower[2], i;
-       unsigned counter[2] = { atomic_read(&dev->vbl_received),
-                               atomic_read(&dev->vbl_received2) };
+       int nhits, nrects, slice[2], upper[2], lower[2], i, num_pages;
+       unsigned counter[2];
        struct drm_drawable_info *drw;
        drm_i915_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       u32 cpp = dev_priv->cpp;
+       u32 cpp = dev_priv->cpp,  offsets[3];
        u32 cmd = (cpp == 4) ? (XY_SRC_COPY_BLT_CMD |
                                XY_SRC_COPY_BLT_WRITE_ALPHA |
                                XY_SRC_COPY_BLT_WRITE_RGB)
                             : XY_SRC_COPY_BLT_CMD;
-       u32 pitchropcpp = (sarea_priv->pitch * cpp) | (0xcc << 16) |
-                         (cpp << 23) | (1 << 24);
+       u32 src_pitch = sarea_priv->pitch * cpp;
+       u32 dst_pitch = sarea_priv->pitch * cpp;
+       /* COPY rop (0xcc), map cpp to magic color depth constants */
+       u32 ropcpp = (0xcc << 16) | ((cpp - 1) << 24);
        RING_LOCALS;
 
+       if (sarea_priv->front_tiled) {
+               cmd |= XY_SRC_COPY_BLT_DST_TILED;
+               dst_pitch >>= 2;
+       }
+       if (sarea_priv->back_tiled) {
+               cmd |= XY_SRC_COPY_BLT_SRC_TILED;
+               src_pitch >>= 2;
+       }
+
+       counter[0] = drm_vblank_count(dev, 0);
+       counter[1] = drm_vblank_count(dev, 1);
+
        DRM_DEBUG("\n");
 
        INIT_LIST_HEAD(&hits);
 
        nhits = nrects = 0;
 
-       spin_lock_irqsave(&dev_priv->swaps_lock, irqflags);
+       /* No irqsave/restore necessary.  This tasklet may be run in an
+        * interrupt context or normal context, but we don't have to worry
+        * about getting interrupted by something acquiring the lock, because
+        * we are the interrupt context thing that acquires the lock.
+        */
+       spin_lock(&dev_priv->swaps_lock);
 
        /* Find buffer swaps scheduled for this vertical blank */
        list_for_each_safe(list, tmp, &dev_priv->vbl_swaps.head) {
                drm_i915_vbl_swap_t *vbl_swap =
                        list_entry(list, drm_i915_vbl_swap_t, head);
+               int pipe = i915_get_pipe(dev, vbl_swap->plane);
 
-               if ((counter[vbl_swap->pipe] - vbl_swap->sequence) > (1<<23))
+               if ((counter[pipe] - vbl_swap->sequence) > (1<<23))
                        continue;
 
                list_del(list);
                dev_priv->swaps_pending--;
+               drm_vblank_put(dev, pipe);
 
                spin_unlock(&dev_priv->swaps_lock);
                spin_lock(&dev->drw_lock);
@@ -116,33 +238,23 @@ static void i915_vblank_tasklet(struct drm_device *dev)
                spin_lock(&dev_priv->swaps_lock);
        }
 
-       if (nhits == 0) {
-               spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags);
-               return;
-       }
-
        spin_unlock(&dev_priv->swaps_lock);
 
-       i915_kernel_lost_context(dev);
-
-       BEGIN_LP_RING(6);
-
-       OUT_RING(GFX_OP_DRAWRECT_INFO);
-       OUT_RING(0);
-       OUT_RING(0);
-       OUT_RING(sarea_priv->width | sarea_priv->height << 16);
-       OUT_RING(sarea_priv->width | sarea_priv->height << 16);
-       OUT_RING(0);
-
-       ADVANCE_LP_RING();
+       if (nhits == 0)
+               return;
 
-       sarea_priv->ctxOwner = DRM_KERNEL_CONTEXT;
+       i915_kernel_lost_context(dev);
 
        upper[0] = upper[1] = 0;
-       slice[0] = max(sarea_priv->pipeA_h / nhits, 1);
-       slice[1] = max(sarea_priv->pipeB_h / nhits, 1);
-       lower[0] = sarea_priv->pipeA_y + slice[0];
-       lower[1] = sarea_priv->pipeB_y + slice[0];
+       slice[0] = max(sarea_priv->planeA_h / nhits, 1);
+       slice[1] = max(sarea_priv->planeB_h / nhits, 1);
+       lower[0] = sarea_priv->planeA_y + slice[0];
+       lower[1] = sarea_priv->planeB_y + slice[0];
+
+       offsets[0] = sarea_priv->front_offset;
+       offsets[1] = sarea_priv->back_offset;
+       offsets[2] = sarea_priv->third_offset;
+       num_pages = sarea_priv->third_handle ? 3 : 2;
 
        spin_lock(&dev->drw_lock);
 
@@ -154,6 +266,8 @@ static void i915_vblank_tasklet(struct drm_device *dev)
        for (i = 0; i++ < nhits;
             upper[0] = lower[0], lower[0] += slice[0],
             upper[1] = lower[1], lower[1] += slice[1]) {
+               int init_drawrect = 1;
+
                if (i == nhits)
                        lower[0] = lower[1] = sarea_priv->height;
 
@@ -161,7 +275,7 @@ static void i915_vblank_tasklet(struct drm_device *dev)
                        drm_i915_vbl_swap_t *swap_hit =
                                list_entry(hit, drm_i915_vbl_swap_t, head);
                        struct drm_clip_rect *rect;
-                       int num_rects, pipe;
+                       int num_rects, plane, front, back;
                        unsigned short top, bottom;
 
                        drw = drm_get_drawable_info(dev, swap_hit->drw_id);
@@ -169,10 +283,50 @@ static void i915_vblank_tasklet(struct drm_device *dev)
                        if (!drw)
                                continue;
 
+                       plane = swap_hit->plane;
+
+                       if (swap_hit->flip) {
+                               i915_dispatch_vsync_flip(dev, drw, plane);
+                               continue;
+                       }
+
+                       if (init_drawrect) {
+                               int width  = sarea_priv->width;
+                               int height = sarea_priv->height;
+                               if (IS_I965G(dev)) {
+                                       BEGIN_LP_RING(4);
+
+                                       OUT_RING(GFX_OP_DRAWRECT_INFO_I965);
+                                       OUT_RING(0);
+                                       OUT_RING(((width - 1) & 0xffff) | ((height - 1) << 16));
+                                       OUT_RING(0);
+
+                                       ADVANCE_LP_RING();
+                               } else {
+                                       BEGIN_LP_RING(6);
+
+                                       OUT_RING(GFX_OP_DRAWRECT_INFO);
+                                       OUT_RING(0);
+                                       OUT_RING(0);
+                                       OUT_RING(((width - 1) & 0xffff) | ((height - 1) << 16));
+                                       OUT_RING(0);
+                                       OUT_RING(0);
+
+                                       ADVANCE_LP_RING();
+                               }
+
+                               sarea_priv->ctxOwner = DRM_KERNEL_CONTEXT;
+
+                               init_drawrect = 0;
+                       }
+
                        rect = drw->rects;
-                       pipe = swap_hit->pipe;
-                       top = upper[pipe];
-                       bottom = lower[pipe];
+                       top = upper[plane];
+                       bottom = lower[plane];
+
+                       front = (dev_priv->sarea_priv->pf_current_page >>
+                                (2 * plane)) & 0x3;
+                       back = (front + 1) % num_pages;
 
                        for (num_rects = drw->num_rects; num_rects--; rect++) {
                                int y1 = max(rect->y1, top);
@@ -184,20 +338,20 @@ static void i915_vblank_tasklet(struct drm_device *dev)
                                BEGIN_LP_RING(8);
 
                                OUT_RING(cmd);
-                               OUT_RING(pitchropcpp);
+                               OUT_RING(ropcpp | dst_pitch);
                                OUT_RING((y1 << 16) | rect->x1);
                                OUT_RING((y2 << 16) | rect->x2);
-                               OUT_RING(sarea_priv->front_offset);
+                               OUT_RING(offsets[front]);
                                OUT_RING((y1 << 16) | rect->x1);
-                               OUT_RING(pitchropcpp & 0xffff);
-                               OUT_RING(sarea_priv->back_offset);
+                               OUT_RING(src_pitch);
+                               OUT_RING(offsets[back]);
 
                                ADVANCE_LP_RING();
                        }
                }
        }
 
-       spin_unlock_irqrestore(&dev->drw_lock, irqflags);
+       spin_unlock(&dev->drw_lock);
 
        list_for_each_safe(hit, tmp, &hits) {
                drm_i915_vbl_swap_t *swap_hit =
@@ -209,67 +363,112 @@ static void i915_vblank_tasklet(struct drm_device *dev)
        }
 }
 
+u32 i915_get_vblank_counter(struct drm_device *dev, int plane)
+{
+       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+       unsigned long high_frame;
+       unsigned long low_frame;
+       u32 high1, high2, low, count;
+       int pipe;
+
+       pipe = i915_get_pipe(dev, plane);
+       high_frame = pipe ? PIPEBFRAMEHIGH : PIPEAFRAMEHIGH;
+       low_frame = pipe ? PIPEBFRAMEPIXEL : PIPEAFRAMEPIXEL;
+
+       if (!i915_pipe_enabled(dev, pipe)) {
+           printk(KERN_ERR "trying to get vblank count for disabled "
+                  "pipe %d\n", pipe);
+           return 0;
+       }
+
+       /*
+        * High & low register fields aren't synchronized, so make sure
+        * we get a low value that's stable across two reads of the high
+        * register.
+        */
+       do {
+               high1 = ((I915_READ(high_frame) & PIPE_FRAME_HIGH_MASK) >>
+                        PIPE_FRAME_HIGH_SHIFT);
+               low =  ((I915_READ(low_frame) & PIPE_FRAME_LOW_MASK) >>
+                       PIPE_FRAME_LOW_SHIFT);
+               high2 = ((I915_READ(high_frame) & PIPE_FRAME_HIGH_MASK) >>
+                        PIPE_FRAME_HIGH_SHIFT);
+       } while (high1 != high2);
+
+       count = (high1 << 8) | low;
+
+       /* count may be reset by other driver(e.g. 2D driver),
+          we have no way to know if it is wrapped or resetted
+          when count is zero. do a rough guess.
+       */
+       if (count == 0 && dev->last_vblank[pipe] < dev->max_vblank_count/2)
+               dev->last_vblank[pipe] = 0;
+
+       return count;
+}
+
 irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
 {
        struct drm_device *dev = (struct drm_device *) arg;
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-       u16 temp;
+       u32 iir;
        u32 pipea_stats, pipeb_stats;
-
-       pipea_stats = I915_READ(I915REG_PIPEASTAT);
-       pipeb_stats = I915_READ(I915REG_PIPEBSTAT);
-
-       temp = I915_READ16(I915REG_INT_IDENTITY_R);
-
-       temp &= (USER_INT_FLAG | VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG);
-
-       DRM_DEBUG("%s flag=%08x\n", __FUNCTION__, temp);
-
-       if (temp == 0)
+       int vblank = 0;
+
+       iir = I915_READ(I915REG_INT_IDENTITY_R);
+       if (iir == 0) {
+               DRM_DEBUG ("iir 0x%08x im 0x%08x ie 0x%08x pipea 0x%08x pipeb 0x%08x\n",
+                          iir,
+                          I915_READ(I915REG_INT_MASK_R),
+                          I915_READ(I915REG_INT_ENABLE_R),
+                          I915_READ(I915REG_PIPEASTAT),
+                          I915_READ(I915REG_PIPEBSTAT));
                return IRQ_NONE;
+       }
 
-       I915_WRITE16(I915REG_INT_IDENTITY_R, temp);
-       (void) I915_READ16(I915REG_INT_IDENTITY_R);
-       DRM_READMEMORYBARRIER();
-
-       dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
+       /*
+        * Clear the PIPE(A|B)STAT regs before the IIR otherwise
+        * we may get extra interrupts.
+        */
+       if (iir & I915_DISPLAY_PIPE_A_EVENT_INTERRUPT) {
+               pipea_stats = I915_READ(I915REG_PIPEASTAT);
+               if (pipea_stats & (I915_START_VBLANK_INTERRUPT_STATUS|
+                                  I915_VBLANK_INTERRUPT_STATUS))
+               {
+                       vblank++;
+                       drm_handle_vblank(dev, i915_get_plane(dev, 0));
+               }
+               I915_WRITE(I915REG_PIPEASTAT, pipea_stats);
+       }
+       if (iir & I915_DISPLAY_PIPE_B_EVENT_INTERRUPT) {
+               pipeb_stats = I915_READ(I915REG_PIPEBSTAT);
+               if (pipeb_stats & (I915_START_VBLANK_INTERRUPT_STATUS|
+                                  I915_VBLANK_INTERRUPT_STATUS))
+               {
+                       vblank++;
+                       drm_handle_vblank(dev, i915_get_plane(dev, 1));
+               }
+               I915_WRITE(I915REG_PIPEBSTAT, pipeb_stats);
+       }
 
-       if (temp & USER_INT_FLAG)
-               DRM_WAKEUP(&dev_priv->irq_queue);
+       if (dev_priv->sarea_priv)
+           dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
 
-       if (temp & (VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG)) {
-               int vblank_pipe = dev_priv->vblank_pipe;
-
-               if ((vblank_pipe &
-                    (DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B))
-                   == (DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B)) {
-                       if (temp & VSYNC_PIPEA_FLAG)
-                               atomic_inc(&dev->vbl_received);
-                       if (temp & VSYNC_PIPEB_FLAG)
-                               atomic_inc(&dev->vbl_received2);
-               } else if (((temp & VSYNC_PIPEA_FLAG) &&
-                           (vblank_pipe & DRM_I915_VBLANK_PIPE_A)) ||
-                          ((temp & VSYNC_PIPEB_FLAG) &&
-                           (vblank_pipe & DRM_I915_VBLANK_PIPE_B)))
-                       atomic_inc(&dev->vbl_received);
-
-               DRM_WAKEUP(&dev->vbl_queue);
-               drm_vbl_send_signals(dev);
+       I915_WRITE(I915REG_INT_IDENTITY_R, iir);
+       (void) I915_READ(I915REG_INT_IDENTITY_R); /* Flush posted write */
 
+       if (iir & I915_USER_INTERRUPT) {
+               DRM_WAKEUP(&dev_priv->irq_queue);
+       }
+       if (vblank) {
                if (dev_priv->swaps_pending > 0)
                        drm_locked_tasklet(dev, i915_vblank_tasklet);
-               I915_WRITE(I915REG_PIPEASTAT,
-                       pipea_stats|I915_VBLANK_INTERRUPT_ENABLE|
-                       I915_VBLANK_CLEAR);
-               I915_WRITE(I915REG_PIPEBSTAT,
-                       pipeb_stats|I915_VBLANK_INTERRUPT_ENABLE|
-                       I915_VBLANK_CLEAR);
        }
 
        return IRQ_HANDLED;
 }
 
-static int i915_emit_irq(struct drm_device * dev)
+static int i915_emit_irq(struct drm_device *dev)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
        RING_LOCALS;
@@ -316,42 +515,12 @@ static int i915_wait_irq(struct drm_device * dev, int irq_nr)
                          READ_BREADCRUMB(dev_priv), (int)dev_priv->counter);
        }
 
-       dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
-       return ret;
-}
-
-static int i915_driver_vblank_do_wait(struct drm_device *dev, unsigned int *sequence,
-                                     atomic_t *counter)
-{
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       unsigned int cur_vblank;
-       int ret = 0;
-
-       if (!dev_priv) {
-               DRM_ERROR("called with no initialization\n");
-               return -EINVAL;
-       }
-
-       DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
-                   (((cur_vblank = atomic_read(counter))
-                       - *sequence) <= (1<<23)));
-
-       *sequence = cur_vblank;
-
+       if (dev_priv->sarea_priv)
+               dev_priv->sarea_priv->last_dispatch =
+                       READ_BREADCRUMB(dev_priv);
        return ret;
 }
 
-
-int i915_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence)
-{
-       return i915_driver_vblank_do_wait(dev, sequence, &dev->vbl_received);
-}
-
-int i915_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence)
-{
-       return i915_driver_vblank_do_wait(dev, sequence, &dev->vbl_received2);
-}
-
 /* Needs the lock as it touches the ring.
  */
 int i915_irq_emit(struct drm_device *dev, void *data,
@@ -394,18 +563,96 @@ int i915_irq_wait(struct drm_device *dev, void *data,
        return i915_wait_irq(dev, irqwait->irq_seq);
 }
 
+int i915_enable_vblank(struct drm_device *dev, int plane)
+{
+       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+       int pipe = i915_get_pipe(dev, plane);
+       u32     pipestat_reg = 0;
+       u32     pipestat;
+
+       switch (pipe) {
+       case 0:
+               pipestat_reg = I915REG_PIPEASTAT;
+               dev_priv->irq_enable_reg |= I915_DISPLAY_PIPE_A_EVENT_INTERRUPT;
+               break;
+       case 1:
+               pipestat_reg = I915REG_PIPEBSTAT;
+               dev_priv->irq_enable_reg |= I915_DISPLAY_PIPE_B_EVENT_INTERRUPT;
+               break;
+       default:
+               DRM_ERROR("tried to enable vblank on non-existent pipe %d\n",
+                         pipe);
+               break;
+       }
+
+       if (pipestat_reg)
+       {
+               pipestat = I915_READ (pipestat_reg);
+               /*
+                * Older chips didn't have the start vblank interrupt,
+                * but
+                */
+               if (IS_I965G (dev))
+                       pipestat |= I915_START_VBLANK_INTERRUPT_ENABLE;
+               else
+                       pipestat |= I915_VBLANK_INTERRUPT_ENABLE;
+               /*
+                * Clear any pending status
+                */
+               pipestat |= (I915_START_VBLANK_INTERRUPT_STATUS |
+                            I915_VBLANK_INTERRUPT_STATUS);
+               I915_WRITE(pipestat_reg, pipestat);
+       }
+       I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
+
+       return 0;
+}
+
+void i915_disable_vblank(struct drm_device *dev, int plane)
+{
+       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+       int pipe = i915_get_pipe(dev, plane);
+       u32     pipestat_reg = 0;
+       u32     pipestat;
+
+       switch (pipe) {
+       case 0:
+               pipestat_reg = I915REG_PIPEASTAT;
+               dev_priv->irq_enable_reg &= ~I915_DISPLAY_PIPE_A_EVENT_INTERRUPT;
+               break;
+       case 1:
+               pipestat_reg = I915REG_PIPEBSTAT;
+               dev_priv->irq_enable_reg &= ~I915_DISPLAY_PIPE_B_EVENT_INTERRUPT;
+               break;
+       default:
+               DRM_ERROR("tried to disable vblank on non-existent pipe %d\n",
+                         pipe);
+               break;
+       }
+
+       I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
+       if (pipestat_reg)
+       {
+               pipestat = I915_READ (pipestat_reg);
+               pipestat &= ~(I915_START_VBLANK_INTERRUPT_ENABLE |
+                             I915_VBLANK_INTERRUPT_ENABLE);
+               /*
+                * Clear any pending status
+                */
+               pipestat |= (I915_START_VBLANK_INTERRUPT_STATUS |
+                            I915_VBLANK_INTERRUPT_STATUS);
+               I915_WRITE(pipestat_reg, pipestat);
+       }
+}
+
 static void i915_enable_interrupt (struct drm_device *dev)
 {
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-       u16 flag;
 
-       flag = 0;
-       if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_A)
-               flag |= VSYNC_PIPEA_FLAG;
-       if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_B)
-               flag |= VSYNC_PIPEB_FLAG;
+       dev_priv->irq_enable_reg |= I915_USER_INTERRUPT;
 
-       I915_WRITE16(I915REG_INT_ENABLE_R, USER_INT_FLAG | flag);
+       I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
+       dev_priv->irq_enabled = 1;
 }
 
 /* Set the vblank monitor pipe
@@ -428,8 +675,6 @@ int i915_vblank_pipe_set(struct drm_device *dev, void *data,
 
        dev_priv->vblank_pipe = pipe->pipe;
 
-       i915_enable_interrupt (dev);
-
        return 0;
 }
 
@@ -447,9 +692,9 @@ int i915_vblank_pipe_get(struct drm_device *dev, void *data,
 
        flag = I915_READ(I915REG_INT_ENABLE_R);
        pipe->pipe = 0;
-       if (flag & VSYNC_PIPEA_FLAG)
+       if (flag & I915_DISPLAY_PIPE_A_EVENT_INTERRUPT)
                pipe->pipe |= DRM_I915_VBLANK_PIPE_A;
-       if (flag & VSYNC_PIPEB_FLAG)
+       if (flag & I915_DISPLAY_PIPE_B_EVENT_INTERRUPT)
                pipe->pipe |= DRM_I915_VBLANK_PIPE_B;
 
        return 0;
@@ -464,27 +709,30 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
        drm_i915_private_t *dev_priv = dev->dev_private;
        drm_i915_vblank_swap_t *swap = data;
        drm_i915_vbl_swap_t *vbl_swap;
-       unsigned int pipe, seqtype, curseq;
+       unsigned int pipe, seqtype, curseq, plane;
        unsigned long irqflags;
        struct list_head *list;
+       int ret;
 
        if (!dev_priv) {
                DRM_ERROR("%s called with no initialization\n", __func__);
                return -EINVAL;
        }
 
-       if (dev_priv->sarea_priv->rotation) {
+       if (!dev_priv->sarea_priv || dev_priv->sarea_priv->rotation) {
                DRM_DEBUG("Rotation not supported\n");
                return -EINVAL;
        }
 
        if (swap->seqtype & ~(_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE |
-                            _DRM_VBLANK_SECONDARY | _DRM_VBLANK_NEXTONMISS)) {
+                            _DRM_VBLANK_SECONDARY | _DRM_VBLANK_NEXTONMISS |
+                            _DRM_VBLANK_FLIP)) {
                DRM_ERROR("Invalid sequence type 0x%x\n", swap->seqtype);
                return -EINVAL;
        }
 
-       pipe = (swap->seqtype & _DRM_VBLANK_SECONDARY) ? 1 : 0;
+       plane = (swap->seqtype & _DRM_VBLANK_SECONDARY) ? 1 : 0;
+       pipe = i915_get_pipe(dev, plane);
 
        seqtype = swap->seqtype & (_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE);
 
@@ -495,6 +743,11 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
 
        spin_lock_irqsave(&dev->drw_lock, irqflags);
 
+       /* It makes no sense to schedule a swap for a drawable that doesn't have
+        * valid information at this point. E.g. this could mean that the X
+        * server is too old to push drawable information to the DRM, in which
+        * case all such swaps would become ineffective.
+        */
        if (!drm_get_drawable_info(dev, swap->drawable)) {
                spin_unlock_irqrestore(&dev->drw_lock, irqflags);
                DRM_DEBUG("Invalid drawable ID %d\n", swap->drawable);
@@ -503,7 +756,8 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
 
        spin_unlock_irqrestore(&dev->drw_lock, irqflags);
 
-       curseq = atomic_read(pipe ? &dev->vbl_received2 : &dev->vbl_received);
+       drm_update_vblank_count(dev, pipe);
+       curseq = drm_vblank_count(dev, pipe);
 
        if (seqtype == _DRM_VBLANK_RELATIVE)
                swap->sequence += curseq;
@@ -517,14 +771,43 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
                }
        }
 
+       if (swap->seqtype & _DRM_VBLANK_FLIP) {
+               swap->sequence--;
+
+               if ((curseq - swap->sequence) <= (1<<23)) {
+                       struct drm_drawable_info *drw;
+
+                       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+                       spin_lock_irqsave(&dev->drw_lock, irqflags);
+
+                       drw = drm_get_drawable_info(dev, swap->drawable);
+
+                       if (!drw) {
+                               spin_unlock_irqrestore(&dev->drw_lock,
+                                   irqflags);
+                               DRM_DEBUG("Invalid drawable ID %d\n",
+                                         swap->drawable);
+                               return -EINVAL;
+                       }
+
+                       i915_dispatch_vsync_flip(dev, drw, plane);
+
+                       spin_unlock_irqrestore(&dev->drw_lock, irqflags);
+
+                       return 0;
+               }
+       }
+
        spin_lock_irqsave(&dev_priv->swaps_lock, irqflags);
 
        list_for_each(list, &dev_priv->vbl_swaps.head) {
                vbl_swap = list_entry(list, drm_i915_vbl_swap_t, head);
 
                if (vbl_swap->drw_id == swap->drawable &&
-                   vbl_swap->pipe == pipe &&
+                   vbl_swap->plane == plane &&
                    vbl_swap->sequence == swap->sequence) {
+                       vbl_swap->flip = (swap->seqtype & _DRM_VBLANK_FLIP);
                        spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags);
                        DRM_DEBUG("Already scheduled\n");
                        return 0;
@@ -547,9 +830,19 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
 
        DRM_DEBUG("\n");
 
+       ret = drm_vblank_get(dev, pipe);
+       if (ret) {
+               drm_free(vbl_swap, sizeof(*vbl_swap), DRM_MEM_DRIVER);
+               return ret;
+       }
+
        vbl_swap->drw_id = swap->drawable;
-       vbl_swap->pipe = pipe;
+       vbl_swap->plane = plane;
        vbl_swap->sequence = swap->sequence;
+       vbl_swap->flip = (swap->seqtype & _DRM_VBLANK_FLIP);
+
+       if (vbl_swap->flip)
+               swap->sequence++;
 
        spin_lock_irqsave(&dev_priv->swaps_lock, irqflags);
 
@@ -567,37 +860,57 @@ void i915_driver_irq_preinstall(struct drm_device * dev)
 {
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 
-       I915_WRITE16(I915REG_HWSTAM, 0xfffe);
+       I915_WRITE16(I915REG_HWSTAM, 0xeffe);
        I915_WRITE16(I915REG_INT_MASK_R, 0x0);
        I915_WRITE16(I915REG_INT_ENABLE_R, 0x0);
 }
 
-void i915_driver_irq_postinstall(struct drm_device * dev)
+int i915_driver_irq_postinstall(struct drm_device * dev)
 {
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+       int ret, num_pipes = 2;
 
        spin_lock_init(&dev_priv->swaps_lock);
        INIT_LIST_HEAD(&dev_priv->vbl_swaps.head);
        dev_priv->swaps_pending = 0;
 
-       if (!dev_priv->vblank_pipe)
-               dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A;
+       dev_priv->user_irq_refcount = 0;
+       dev_priv->irq_enable_reg = 0;
+
+       ret = drm_vblank_init(dev, num_pipes);
+       if (ret)
+               return ret;
+
+       dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
+
        i915_enable_interrupt(dev);
        DRM_INIT_WAITQUEUE(&dev_priv->irq_queue);
+
+       /*
+        * Initialize the hardware status page IRQ location.
+        */
+
+       I915_WRITE(I915REG_INSTPM, (1 << 5) | (1 << 21));
+       return 0;
 }
 
 void i915_driver_irq_uninstall(struct drm_device * dev)
 {
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-       u16 temp;
+       u32 temp;
 
        if (!dev_priv)
                return;
 
-       I915_WRITE16(I915REG_HWSTAM, 0xffff);
-       I915_WRITE16(I915REG_INT_MASK_R, 0xffff);
-       I915_WRITE16(I915REG_INT_ENABLE_R, 0x0);
-
-       temp = I915_READ16(I915REG_INT_IDENTITY_R);
-       I915_WRITE16(I915REG_INT_IDENTITY_R, temp);
+       dev_priv->irq_enabled = 0;
+       I915_WRITE(I915REG_HWSTAM, 0xffffffff);
+       I915_WRITE(I915REG_INT_MASK_R, 0xffffffff);
+       I915_WRITE(I915REG_INT_ENABLE_R, 0x0);
+
+       temp = I915_READ(I915REG_PIPEASTAT);
+       I915_WRITE(I915REG_PIPEASTAT, temp);
+       temp = I915_READ(I915REG_PIPEBSTAT);
+       I915_WRITE(I915REG_PIPEBSTAT, temp);
+       temp = I915_READ(I915REG_INT_IDENTITY_R);
+       I915_WRITE(I915REG_INT_IDENTITY_R, temp);
 }
index 5572939..6b37909 100644 (file)
@@ -45,15 +45,16 @@ static struct pci_device_id pciidlist[] = {
 static struct drm_driver driver = {
        .driver_features =
            DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA |
-           DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED |
-           DRIVER_IRQ_VBL,
+           DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED,
        .dev_priv_size = sizeof(drm_mga_buf_priv_t),
        .load = mga_driver_load,
        .unload = mga_driver_unload,
        .lastclose = mga_driver_lastclose,
        .dma_quiescent = mga_driver_dma_quiescent,
        .device_is_agp = mga_driver_device_is_agp,
-       .vblank_wait = mga_driver_vblank_wait,
+       .get_vblank_counter = mga_get_vblank_counter,
+       .enable_vblank = mga_enable_vblank,
+       .disable_vblank = mga_disable_vblank,
        .irq_preinstall = mga_driver_irq_preinstall,
        .irq_postinstall = mga_driver_irq_postinstall,
        .irq_uninstall = mga_driver_irq_uninstall,
index f6ebd24..8f7291f 100644 (file)
@@ -120,6 +120,7 @@ typedef struct drm_mga_private {
        u32 clear_cmd;
        u32 maccess;
 
+       atomic_t vbl_received;          /**< Number of vblanks received. */
        wait_queue_head_t fence_queue;
        atomic_t last_fence_retired;
        u32 next_fence_to_post;
@@ -181,11 +182,14 @@ extern int mga_warp_install_microcode(drm_mga_private_t * dev_priv);
 extern int mga_warp_init(drm_mga_private_t * dev_priv);
 
                                /* mga_irq.c */
+extern int mga_enable_vblank(struct drm_device *dev, int crtc);
+extern void mga_disable_vblank(struct drm_device *dev, int crtc);
+extern u32 mga_get_vblank_counter(struct drm_device *dev, int crtc);
 extern int mga_driver_fence_wait(struct drm_device * dev, unsigned int *sequence);
 extern int mga_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence);
 extern irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS);
 extern void mga_driver_irq_preinstall(struct drm_device * dev);
-extern void mga_driver_irq_postinstall(struct drm_device * dev);
+extern int mga_driver_irq_postinstall(struct drm_device * dev);
 extern void mga_driver_irq_uninstall(struct drm_device * dev);
 extern long mga_compat_ioctl(struct file *filp, unsigned int cmd,
                             unsigned long arg);
index 9302cb8..06852fb 100644 (file)
 #include "mga_drm.h"
 #include "mga_drv.h"
 
+u32 mga_get_vblank_counter(struct drm_device *dev, int crtc)
+{
+       const drm_mga_private_t *const dev_priv =
+               (drm_mga_private_t *) dev->dev_private;
+
+       if (crtc != 0) {
+               return 0;
+       }
+
+
+       return atomic_read(&dev_priv->vbl_received);
+}
+
+
 irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS)
 {
        struct drm_device *dev = (struct drm_device *) arg;
@@ -47,9 +61,8 @@ irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS)
        /* VBLANK interrupt */
        if (status & MGA_VLINEPEN) {
                MGA_WRITE(MGA_ICLEAR, MGA_VLINEICLR);
-               atomic_inc(&dev->vbl_received);
-               DRM_WAKEUP(&dev->vbl_queue);
-               drm_vbl_send_signals(dev);
+               atomic_inc(&dev_priv->vbl_received);
+               drm_handle_vblank(dev, 0);
                handled = 1;
        }
 
@@ -78,22 +91,34 @@ irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS)
        return IRQ_NONE;
 }
 
-int mga_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence)
+int mga_enable_vblank(struct drm_device *dev, int crtc)
 {
-       unsigned int cur_vblank;
-       int ret = 0;
+       drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
 
-       /* Assume that the user has missed the current sequence number
-        * by about a day rather than she wants to wait for years
-        * using vertical blanks...
-        */
-       DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
-                   (((cur_vblank = atomic_read(&dev->vbl_received))
-                     - *sequence) <= (1 << 23)));
+       if (crtc != 0) {
+               DRM_ERROR("tried to enable vblank on non-existent crtc %d\n",
+                         crtc);
+               return 0;
+       }
 
-       *sequence = cur_vblank;
+       MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN);
+       return 0;
+}
 
-       return ret;
+
+void mga_disable_vblank(struct drm_device *dev, int crtc)
+{
+       if (crtc != 0) {
+               DRM_ERROR("tried to disable vblank on non-existent crtc %d\n",
+                         crtc);
+       }
+
+       /* Do *NOT* disable the vertical refresh interrupt.  MGA doesn't have
+        * a nice hardware counter that tracks the number of refreshes when
+        * the interrupt is disabled, and the kernel doesn't know the refresh
+        * rate to calculate an estimate.
+        */
+       /* MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN); */
 }
 
 int mga_driver_fence_wait(struct drm_device * dev, unsigned int *sequence)
@@ -125,14 +150,22 @@ void mga_driver_irq_preinstall(struct drm_device * dev)
        MGA_WRITE(MGA_ICLEAR, ~0);
 }
 
-void mga_driver_irq_postinstall(struct drm_device * dev)
+int mga_driver_irq_postinstall(struct drm_device * dev)
 {
        drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
+       int ret;
+
+       ret = drm_vblank_init(dev, 1);
+       if (ret)
+               return ret;
 
        DRM_INIT_WAITQUEUE(&dev_priv->fence_queue);
 
-       /* Turn on vertical blank interrupt and soft trap interrupt. */
-       MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN);
+       /* Turn on soft trap interrupt.  Vertical blank interrupts are enabled
+        * in mga_enable_vblank.
+        */
+       MGA_WRITE(MGA_IEN, MGA_SOFTRAPEN);
+       return 0;
 }
 
 void mga_driver_irq_uninstall(struct drm_device * dev)
index 6108e75..2888aa0 100644 (file)
@@ -43,12 +43,13 @@ static struct pci_device_id pciidlist[] = {
 static struct drm_driver driver = {
        .driver_features =
            DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG |
-           DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED |
-           DRIVER_IRQ_VBL,
+           DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED,
        .dev_priv_size = sizeof(drm_r128_buf_priv_t),
        .preclose = r128_driver_preclose,
        .lastclose = r128_driver_lastclose,
-       .vblank_wait = r128_driver_vblank_wait,
+       .get_vblank_counter = r128_get_vblank_counter,
+       .enable_vblank = r128_enable_vblank,
+       .disable_vblank = r128_disable_vblank,
        .irq_preinstall = r128_driver_irq_preinstall,
        .irq_postinstall = r128_driver_irq_postinstall,
        .irq_uninstall = r128_driver_irq_uninstall,
index 011105e..80af9e0 100644 (file)
@@ -97,6 +97,8 @@ typedef struct drm_r128_private {
        u32 crtc_offset;
        u32 crtc_offset_cntl;
 
+       atomic_t vbl_received;
+
        u32 color_fmt;
        unsigned int front_offset;
        unsigned int front_pitch;
@@ -149,11 +151,12 @@ extern int r128_wait_ring(drm_r128_private_t * dev_priv, int n);
 extern int r128_do_cce_idle(drm_r128_private_t * dev_priv);
 extern int r128_do_cleanup_cce(struct drm_device * dev);
 
-extern int r128_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence);
-
+extern int r128_enable_vblank(struct drm_device *dev, int crtc);
+extern void r128_disable_vblank(struct drm_device *dev, int crtc);
+extern u32 r128_get_vblank_counter(struct drm_device *dev, int crtc);
 extern irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS);
 extern void r128_driver_irq_preinstall(struct drm_device * dev);
-extern void r128_driver_irq_postinstall(struct drm_device * dev);
+extern int r128_driver_irq_postinstall(struct drm_device * dev);
 extern void r128_driver_irq_uninstall(struct drm_device * dev);
 extern void r128_driver_lastclose(struct drm_device * dev);
 extern void r128_driver_preclose(struct drm_device * dev,
index c76fdca..5b95bd8 100644 (file)
 #include "r128_drm.h"
 #include "r128_drv.h"
 
+u32 r128_get_vblank_counter(struct drm_device *dev, int crtc)
+{
+       const drm_r128_private_t *dev_priv = dev->dev_private;
+
+       if (crtc != 0)
+               return 0;
+
+       return atomic_read(&dev_priv->vbl_received);
+}
+
 irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS)
 {
        struct drm_device *dev = (struct drm_device *) arg;
@@ -46,30 +56,38 @@ irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS)
        /* VBLANK interrupt */
        if (status & R128_CRTC_VBLANK_INT) {
                R128_WRITE(R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK);
-               atomic_inc(&dev->vbl_received);
-               DRM_WAKEUP(&dev->vbl_queue);
-               drm_vbl_send_signals(dev);
+               atomic_inc(&dev_priv->vbl_received);
+               drm_handle_vblank(dev, 0);
                return IRQ_HANDLED;
        }
        return IRQ_NONE;
 }
 
-int r128_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence)
+int r128_enable_vblank(struct drm_device *dev, int crtc)
 {
-       unsigned int cur_vblank;
-       int ret = 0;
+       drm_r128_private_t *dev_priv = dev->dev_private;
 
-       /* Assume that the user has missed the current sequence number
-        * by about a day rather than she wants to wait for years
-        * using vertical blanks...
-        */
-       DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
-                   (((cur_vblank = atomic_read(&dev->vbl_received))
-                     - *sequence) <= (1 << 23)));
+       if (crtc != 0) {
+               DRM_ERROR("%s:  bad crtc %d\n", __FUNCTION__, crtc);
+               return -EINVAL;
+       }
 
-       *sequence = cur_vblank;
+       R128_WRITE(R128_GEN_INT_CNTL, R128_CRTC_VBLANK_INT_EN);
+       return 0;
+}
+
+void r128_disable_vblank(struct drm_device *dev, int crtc)
+{
+       if (crtc != 0)
+               DRM_ERROR("%s:  bad crtc %d\n", __FUNCTION__, crtc);
 
-       return ret;
+       /*
+        * FIXME: implement proper interrupt disable by using the vblank
+        * counter register (if available)
+        *
+        * R128_WRITE(R128_GEN_INT_CNTL,
+        *            R128_READ(R128_GEN_INT_CNTL) & ~R128_CRTC_VBLANK_INT_EN);
+        */
 }
 
 void r128_driver_irq_preinstall(struct drm_device * dev)
@@ -82,12 +100,9 @@ void r128_driver_irq_preinstall(struct drm_device * dev)
        R128_WRITE(R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK);
 }
 
-void r128_driver_irq_postinstall(struct drm_device * dev)
+int r128_driver_irq_postinstall(struct drm_device * dev)
 {
-       drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private;
-
-       /* Turn on VBL interrupt */
-       R128_WRITE(R128_GEN_INT_CNTL, R128_CRTC_VBLANK_INT_EN);
+       return drm_vblank_init(dev, 1);
 }
 
 void r128_driver_irq_uninstall(struct drm_device * dev)
index 349ac3d..a261031 100644 (file)
@@ -59,8 +59,7 @@ static struct pci_device_id pciidlist[] = {
 static struct drm_driver driver = {
        .driver_features =
            DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG |
-           DRIVER_HAVE_IRQ | DRIVER_HAVE_DMA | DRIVER_IRQ_SHARED |
-           DRIVER_IRQ_VBL | DRIVER_IRQ_VBL2,
+           DRIVER_HAVE_IRQ | DRIVER_HAVE_DMA | DRIVER_IRQ_SHARED,
        .dev_priv_size = sizeof(drm_radeon_buf_priv_t),
        .load = radeon_driver_load,
        .firstopen = radeon_driver_firstopen,
@@ -69,8 +68,9 @@ static struct drm_driver driver = {
        .postclose = radeon_driver_postclose,
        .lastclose = radeon_driver_lastclose,
        .unload = radeon_driver_unload,
-       .vblank_wait = radeon_driver_vblank_wait,
-       .vblank_wait2 = radeon_driver_vblank_wait2,
+       .get_vblank_counter = radeon_get_vblank_counter,
+       .enable_vblank = radeon_enable_vblank,
+       .disable_vblank = radeon_disable_vblank,
        .dri_library_name = dri_library_name,
        .irq_preinstall = radeon_driver_irq_preinstall,
        .irq_postinstall = radeon_driver_irq_postinstall,
index 173ae62..b791420 100644 (file)
@@ -304,6 +304,9 @@ typedef struct drm_radeon_private {
 
        u32 scratch_ages[5];
 
+       unsigned int crtc_last_cnt;
+       unsigned int crtc2_last_cnt;
+
        /* starting from here on, data is preserved accross an open */
        uint32_t flags;         /* see radeon_chip_flags */
        unsigned long fb_aper_offset;
@@ -374,13 +377,13 @@ extern int radeon_irq_emit(struct drm_device *dev, void *data, struct drm_file *
 extern int radeon_irq_wait(struct drm_device *dev, void *data, struct drm_file *file_priv);
 
 extern void radeon_do_release(struct drm_device * dev);
-extern int radeon_driver_vblank_wait(struct drm_device * dev,
-                                    unsigned int *sequence);
-extern int radeon_driver_vblank_wait2(struct drm_device * dev,
-                                     unsigned int *sequence);
+extern u32 radeon_get_vblank_counter(struct drm_device *dev, int crtc);
+extern int radeon_enable_vblank(struct drm_device *dev, int crtc);
+extern void radeon_disable_vblank(struct drm_device *dev, int crtc);
+extern void radeon_do_release(struct drm_device * dev);
 extern irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS);
 extern void radeon_driver_irq_preinstall(struct drm_device * dev);
-extern void radeon_driver_irq_postinstall(struct drm_device * dev);
+extern int radeon_driver_irq_postinstall(struct drm_device * dev);
 extern void radeon_driver_irq_uninstall(struct drm_device * dev);
 extern int radeon_vblank_crtc_get(struct drm_device *dev);
 extern int radeon_vblank_crtc_set(struct drm_device *dev, int64_t value);
@@ -558,6 +561,12 @@ extern int r300_do_cp_cmdbuf(struct drm_device * dev,
                                ? DRM_READ32( dev_priv->ring_rptr, RADEON_SCRATCHOFF(x) ) \
                                : RADEON_READ( RADEON_SCRATCH_REG0 + 4*(x) ) )
 
+#define RADEON_CRTC_CRNT_FRAME 0x0214
+#define RADEON_CRTC2_CRNT_FRAME 0x0314
+
+#define RADEON_CRTC_STATUS             0x005c
+#define RADEON_CRTC2_STATUS            0x03fc
+
 #define RADEON_GEN_INT_CNTL            0x0040
 #      define RADEON_CRTC_VBLANK_MASK          (1 << 0)
 #      define RADEON_CRTC2_VBLANK_MASK         (1 << 9)
index 009af38..507d6b7 100644 (file)
 #include "radeon_drm.h"
 #include "radeon_drv.h"
 
-static __inline__ u32 radeon_acknowledge_irqs(drm_radeon_private_t * dev_priv,
-                                             u32 mask)
+static void radeon_irq_set_state(struct drm_device *dev, u32 mask, int state)
 {
-       u32 irqs = RADEON_READ(RADEON_GEN_INT_STATUS) & mask;
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+
+       if (state)
+               dev_priv->irq_enable_reg |= mask;
+       else
+               dev_priv->irq_enable_reg &= ~mask;
+
+       RADEON_WRITE(RADEON_GEN_INT_CNTL, dev_priv->irq_enable_reg);
+}
+
+int radeon_enable_vblank(struct drm_device *dev, int crtc)
+{
+       switch (crtc) {
+       case 0:
+               radeon_irq_set_state(dev, RADEON_CRTC_VBLANK_MASK, 1);
+               break;
+       case 1:
+               radeon_irq_set_state(dev, RADEON_CRTC2_VBLANK_MASK, 1);
+               break;
+       default:
+               DRM_ERROR("tried to enable vblank on non-existent crtc %d\n",
+                         crtc);
+               return EINVAL;
+       }
+
+       return 0;
+}
+
+void radeon_disable_vblank(struct drm_device *dev, int crtc)
+{
+       switch (crtc) {
+       case 0:
+               radeon_irq_set_state(dev, RADEON_CRTC_VBLANK_MASK, 0);
+               break;
+       case 1:
+               radeon_irq_set_state(dev, RADEON_CRTC2_VBLANK_MASK, 0);
+               break;
+       default:
+               DRM_ERROR("tried to enable vblank on non-existent crtc %d\n",
+                         crtc);
+               break;
+       }
+}
+
+static __inline__ u32 radeon_acknowledge_irqs(drm_radeon_private_t * dev_priv)
+{
+       u32 irqs = RADEON_READ(RADEON_GEN_INT_STATUS) &
+               (RADEON_SW_INT_TEST | RADEON_CRTC_VBLANK_STAT |
+                RADEON_CRTC2_VBLANK_STAT);
+
        if (irqs)
                RADEON_WRITE(RADEON_GEN_INT_STATUS, irqs);
+
        return irqs;
 }
 
@@ -72,39 +121,21 @@ irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS)
        /* Only consider the bits we're interested in - others could be used
         * outside the DRM
         */
-       stat = radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK |
-                                                 RADEON_CRTC_VBLANK_STAT |
-                                                 RADEON_CRTC2_VBLANK_STAT));
+       stat = radeon_acknowledge_irqs(dev_priv);
        if (!stat)
                return IRQ_NONE;
 
        stat &= dev_priv->irq_enable_reg;
 
        /* SW interrupt */
-       if (stat & RADEON_SW_INT_TEST) {
+       if (stat & RADEON_SW_INT_TEST)
                DRM_WAKEUP(&dev_priv->swi_queue);
-       }
 
        /* VBLANK interrupt */
-       if (stat & (RADEON_CRTC_VBLANK_STAT|RADEON_CRTC2_VBLANK_STAT)) {
-               int vblank_crtc = dev_priv->vblank_crtc;
-
-               if ((vblank_crtc &
-                    (DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) ==
-                   (DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) {
-                       if (stat & RADEON_CRTC_VBLANK_STAT)
-                               atomic_inc(&dev->vbl_received);
-                       if (stat & RADEON_CRTC2_VBLANK_STAT)
-                               atomic_inc(&dev->vbl_received2);
-               } else if (((stat & RADEON_CRTC_VBLANK_STAT) &&
-                          (vblank_crtc & DRM_RADEON_VBLANK_CRTC1)) ||
-                          ((stat & RADEON_CRTC2_VBLANK_STAT) &&
-                           (vblank_crtc & DRM_RADEON_VBLANK_CRTC2)))
-                       atomic_inc(&dev->vbl_received);
-
-               DRM_WAKEUP(&dev->vbl_queue);
-               drm_vbl_send_signals(dev);
-       }
+       if (stat & RADEON_CRTC_VBLANK_STAT)
+               drm_handle_vblank(dev, 0);
+       if (stat & RADEON_CRTC2_VBLANK_STAT)
+               drm_handle_vblank(dev, 1);
 
        return IRQ_HANDLED;
 }
@@ -144,54 +175,27 @@ static int radeon_wait_irq(struct drm_device * dev, int swi_nr)
        return ret;
 }
 
-static int radeon_driver_vblank_do_wait(struct drm_device * dev,
-                                       unsigned int *sequence, int crtc)
+u32 radeon_get_vblank_counter(struct drm_device *dev, int crtc)
 {
-       drm_radeon_private_t *dev_priv =
-           (drm_radeon_private_t *) dev->dev_private;
-       unsigned int cur_vblank;
-       int ret = 0;
-       int ack = 0;
-       atomic_t *counter;
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       u32 crtc_cnt_reg, crtc_status_reg;
+
        if (!dev_priv) {
                DRM_ERROR("called with no initialization\n");
                return -EINVAL;
        }
 
-       if (crtc == DRM_RADEON_VBLANK_CRTC1) {
-               counter = &dev->vbl_received;
-               ack |= RADEON_CRTC_VBLANK_STAT;
-       } else if (crtc == DRM_RADEON_VBLANK_CRTC2) {
-               counter = &dev->vbl_received2;
-               ack |= RADEON_CRTC2_VBLANK_STAT;
-       } else
+       if (crtc == 0) {
+               crtc_cnt_reg = RADEON_CRTC_CRNT_FRAME;
+               crtc_status_reg = RADEON_CRTC_STATUS;
+       } else if (crtc == 1) {
+               crtc_cnt_reg = RADEON_CRTC2_CRNT_FRAME;
+               crtc_status_reg = RADEON_CRTC2_STATUS;
+       } else {
                return -EINVAL;
+       }
 
-       radeon_acknowledge_irqs(dev_priv, ack);
-
-       dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
-
-       /* Assume that the user has missed the current sequence number
-        * by about a day rather than she wants to wait for years
-        * using vertical blanks...
-        */
-       DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
-                   (((cur_vblank = atomic_read(counter))
-                     - *sequence) <= (1 << 23)));
-
-       *sequence = cur_vblank;
-
-       return ret;
-}
-
-int radeon_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence)
-{
-       return radeon_driver_vblank_do_wait(dev, sequence, DRM_RADEON_VBLANK_CRTC1);
-}
-
-int radeon_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence)
-{
-       return radeon_driver_vblank_do_wait(dev, sequence, DRM_RADEON_VBLANK_CRTC2);
+       return RADEON_READ(crtc_cnt_reg) + (RADEON_READ(crtc_status_reg) & 1);
 }
 
 /* Needs the lock as it touches the ring.
@@ -234,21 +238,6 @@ int radeon_irq_wait(struct drm_device *dev, void *data, struct drm_file *file_pr
        return radeon_wait_irq(dev, irqwait->irq_seq);
 }
 
-static void radeon_enable_interrupt(struct drm_device *dev)
-{
-       drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private;
-
-       dev_priv->irq_enable_reg = RADEON_SW_INT_ENABLE;
-       if (dev_priv->vblank_crtc & DRM_RADEON_VBLANK_CRTC1)
-               dev_priv->irq_enable_reg |= RADEON_CRTC_VBLANK_MASK;
-
-       if (dev_priv->vblank_crtc & DRM_RADEON_VBLANK_CRTC2)
-               dev_priv->irq_enable_reg |= RADEON_CRTC2_VBLANK_MASK;
-
-       RADEON_WRITE(RADEON_GEN_INT_CNTL, dev_priv->irq_enable_reg);
-       dev_priv->irq_enabled = 1;
-}
-
 /* drm_dma.h hooks
 */
 void radeon_driver_irq_preinstall(struct drm_device * dev)
@@ -260,20 +249,27 @@ void radeon_driver_irq_preinstall(struct drm_device * dev)
        RADEON_WRITE(RADEON_GEN_INT_CNTL, 0);
 
        /* Clear bits if they're already high */
-       radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK |
-                                          RADEON_CRTC_VBLANK_STAT |
-                                          RADEON_CRTC2_VBLANK_STAT));
+       radeon_acknowledge_irqs(dev_priv);
 }
 
-void radeon_driver_irq_postinstall(struct drm_device * dev)
+int radeon_driver_irq_postinstall(struct drm_device * dev)
 {
        drm_radeon_private_t *dev_priv =
            (drm_radeon_private_t *) dev->dev_private;
+       int ret;
 
        atomic_set(&dev_priv->swi_emitted, 0);
        DRM_INIT_WAITQUEUE(&dev_priv->swi_queue);
 
-       radeon_enable_interrupt(dev);
+       ret = drm_vblank_init(dev, 2);
+       if (ret)
+               return ret;
+
+       dev->max_vblank_count = 0x001fffff;
+
+       radeon_irq_set_state(dev, RADEON_SW_INT_ENABLE, 1);
+
+       return 0;
 }
 
 void radeon_driver_irq_uninstall(struct drm_device * dev)
@@ -315,6 +311,5 @@ int radeon_vblank_crtc_set(struct drm_device *dev, int64_t value)
                return -EINVAL;
        }
        dev_priv->vblank_crtc = (unsigned int)value;
-       radeon_enable_interrupt(dev);
        return 0;
 }
index 80c01cd..37870a4 100644 (file)
@@ -40,11 +40,13 @@ static struct pci_device_id pciidlist[] = {
 static struct drm_driver driver = {
        .driver_features =
            DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_HAVE_IRQ |
-           DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL,
+           DRIVER_IRQ_SHARED,
        .load = via_driver_load,
        .unload = via_driver_unload,
        .context_dtor = via_final_context,
-       .vblank_wait = via_driver_vblank_wait,
+       .get_vblank_counter = via_get_vblank_counter,
+       .enable_vblank = via_enable_vblank,
+       .disable_vblank = via_disable_vblank,
        .irq_preinstall = via_driver_irq_preinstall,
        .irq_postinstall = via_driver_irq_postinstall,
        .irq_uninstall = via_driver_irq_uninstall,
index 2daae81..fe67030 100644 (file)
@@ -75,6 +75,7 @@ typedef struct drm_via_private {
        struct timeval last_vblank;
        int last_vblank_valid;
        unsigned usec_per_vblank;
+       atomic_t vbl_received;
        drm_via_state_t hc_state;
        char pci_buf[VIA_PCI_BUF_SIZE];
        const uint32_t *fire_offsets[VIA_FIRE_BUF_SIZE];
@@ -130,11 +131,13 @@ extern int via_init_context(struct drm_device * dev, int context);
 extern int via_final_context(struct drm_device * dev, int context);
 
 extern int via_do_cleanup_map(struct drm_device * dev);
-extern int via_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence);
+extern u32 via_get_vblank_counter(struct drm_device *dev, int crtc);
+extern int via_enable_vblank(struct drm_device *dev, int crtc);
+extern void via_disable_vblank(struct drm_device *dev, int crtc);
 
 extern irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS);
 extern void via_driver_irq_preinstall(struct drm_device * dev);
-extern void via_driver_irq_postinstall(struct drm_device * dev);
+extern int via_driver_irq_postinstall(struct drm_device * dev);
 extern void via_driver_irq_uninstall(struct drm_device * dev);
 
 extern int via_dma_cleanup(struct drm_device * dev);
index c6bb978..f1ab6fc 100644 (file)
@@ -92,8 +92,17 @@ static int via_irqmap_unichrome[] = {-1, -1, -1, 0, -1, 1};
 static unsigned time_diff(struct timeval *now, struct timeval *then)
 {
        return (now->tv_usec >= then->tv_usec) ?
-           now->tv_usec - then->tv_usec :
-           1000000 - (then->tv_usec - now->tv_usec);
+               now->tv_usec - then->tv_usec :
+               1000000 - (then->tv_usec - now->tv_usec);
+}
+
+u32 via_get_vblank_counter(struct drm_device *dev, int crtc)
+{
+       drm_via_private_t *dev_priv = dev->dev_private;
+       if (crtc != 0)
+               return 0;
+
+       return atomic_read(&dev_priv->vbl_received);
 }
 
 irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS)
@@ -108,8 +117,8 @@ irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS)
 
        status = VIA_READ(VIA_REG_INTERRUPT);
        if (status & VIA_IRQ_VBLANK_PENDING) {
-               atomic_inc(&dev->vbl_received);
-               if (!(atomic_read(&dev->vbl_received) & 0x0F)) {
+               atomic_inc(&dev_priv->vbl_received);
+               if (!(atomic_read(&dev_priv->vbl_received) & 0x0F)) {
                        do_gettimeofday(&cur_vblank);
                        if (dev_priv->last_vblank_valid) {
                                dev_priv->usec_per_vblank =
@@ -119,12 +128,11 @@ irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS)
                        dev_priv->last_vblank = cur_vblank;
                        dev_priv->last_vblank_valid = 1;
                }
-               if (!(atomic_read(&dev->vbl_received) & 0xFF)) {
+               if (!(atomic_read(&dev_priv->vbl_received) & 0xFF)) {
                        DRM_DEBUG("US per vblank is: %u\n",
                                  dev_priv->usec_per_vblank);
                }
-               DRM_WAKEUP(&dev->vbl_queue);
-               drm_vbl_send_signals(dev);
+               drm_handle_vblank(dev, 0);
                handled = 1;
        }
 
@@ -163,31 +171,34 @@ static __inline__ void viadrv_acknowledge_irqs(drm_via_private_t * dev_priv)
        }
 }
 
-int via_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence)
+int via_enable_vblank(struct drm_device *dev, int crtc)
 {
-       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
-       unsigned int cur_vblank;
-       int ret = 0;
+       drm_via_private_t *dev_priv = dev->dev_private;
+       u32 status;
 
-       DRM_DEBUG("\n");
-       if (!dev_priv) {
-               DRM_ERROR("called with no initialization\n");
+       if (crtc != 0) {
+               DRM_ERROR("%s:  bad crtc %d\n", __FUNCTION__, crtc);
                return -EINVAL;
        }
 
-       viadrv_acknowledge_irqs(dev_priv);
+       status = VIA_READ(VIA_REG_INTERRUPT);
+       VIA_WRITE(VIA_REG_INTERRUPT, status & VIA_IRQ_VBLANK_ENABLE);
 
-       /* Assume that the user has missed the current sequence number
-        * by about a day rather than she wants to wait for years
-        * using vertical blanks...
-        */
+       VIA_WRITE8(0x83d4, 0x11);
+       VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) | 0x30);
 
-       DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
-                   (((cur_vblank = atomic_read(&dev->vbl_received)) -
-                     *sequence) <= (1 << 23)));
+       return 0;
+}
 
-       *sequence = cur_vblank;
-       return ret;
+void via_disable_vblank(struct drm_device *dev, int crtc)
+{
+       drm_via_private_t *dev_priv = dev->dev_private;
+
+       VIA_WRITE8(0x83d4, 0x11);
+       VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) & ~0x30);
+
+       if (crtc != 0)
+               DRM_ERROR("%s:  bad crtc %d\n", __FUNCTION__, crtc);
 }
 
 static int
@@ -292,23 +303,25 @@ void via_driver_irq_preinstall(struct drm_device * dev)
        }
 }
 
-void via_driver_irq_postinstall(struct drm_device * dev)
+int via_driver_irq_postinstall(struct drm_device * dev)
 {
        drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
        u32 status;
 
-       DRM_DEBUG("\n");
-       if (dev_priv) {
-               status = VIA_READ(VIA_REG_INTERRUPT);
-               VIA_WRITE(VIA_REG_INTERRUPT, status | VIA_IRQ_GLOBAL
-                         | dev_priv->irq_enable_mask);
+       DRM_DEBUG("via_driver_irq_postinstall\n");
+       if (!dev_priv)
+               return -EINVAL;
 
-               /* Some magic, oh for some data sheets ! */
+       drm_vblank_init(dev, 1);
+       status = VIA_READ(VIA_REG_INTERRUPT);
+       VIA_WRITE(VIA_REG_INTERRUPT, status | VIA_IRQ_GLOBAL
+                 | dev_priv->irq_enable_mask);
 
-               VIA_WRITE8(0x83d4, 0x11);
-               VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) | 0x30);
+       /* Some magic, oh for some data sheets ! */
+       VIA_WRITE8(0x83d4, 0x11);
+       VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) | 0x30);
 
-       }
+       return 0;
 }
 
 void via_driver_irq_uninstall(struct drm_device * dev)
index 8753203..3f9e100 100644 (file)
@@ -1031,7 +1031,7 @@ comment "Other IDE chipsets support"
 comment "Note: most of these also require special kernel boot parameters"
 
 config BLK_DEV_4DRIVES
-       bool "Generic 4 drives/port support"
+       tristate "Generic 4 drives/port support"
        help
          Certain older chipsets, including the Tekram 690CD, use a single set
          of I/O ports at 0x1f0 to control up to four drives, instead of the
index ec46c44..a80b957 100644 (file)
@@ -21,6 +21,8 @@
 #include <asm/arch/bast-map.h>
 #include <asm/arch/bast-irq.h>
 
+#define DRV_NAME "bast-ide"
+
 static int __init bastide_register(unsigned int base, unsigned int aux, int irq)
 {
        ide_hwif_t *hwif;
@@ -41,7 +43,7 @@ static int __init bastide_register(unsigned int base, unsigned int aux, int irq)
        hw.io_ports[IDE_CONTROL_OFFSET] = aux + (6 * 0x20);
        hw.irq = irq;
 
-       hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
+       hwif = ide_find_port();
        if (hwif == NULL)
                goto out;
 
@@ -53,6 +55,7 @@ static int __init bastide_register(unsigned int base, unsigned int aux, int irq)
                ide_init_port_data(hwif, i);
 
        ide_init_port_hw(hwif, &hw);
+       hwif->mmio = 1;
        hwif->quirkproc = NULL;
 
        idx[0] = i;
@@ -64,6 +67,8 @@ out:
 
 static int __init bastide_init(void)
 {
+       unsigned long base = BAST_VA_IDEPRI + BAST_IDE_CS;
+
        /* we can treat the VR1000 and the BAST the same */
 
        if (!(machine_is_bast() || machine_is_vr1000()))
@@ -71,6 +76,11 @@ static int __init bastide_init(void)
 
        printk("BAST: IDE driver, (c) 2003-2004 Simtec Electronics\n");
 
+       if (!request_mem_region(base, 0x400000, DRV_NAME)) {
+               printk(KERN_ERR "%s: resources busy\n", DRV_NAME);
+               return -EBUSY;
+       }
+
        bastide_register(BAST_VA_IDEPRI, BAST_VA_IDEPRIAUX, IRQ_IDE0);
        bastide_register(BAST_VA_IDESEC, BAST_VA_IDESECAUX, IRQ_IDE1);
 
index e816b0f..fd12bbe 100644 (file)
@@ -400,7 +400,7 @@ icside_setup(void __iomem *base, struct cardinfo *info, struct expansion_card *e
        unsigned long port = (unsigned long)base + info->dataoffset;
        ide_hwif_t *hwif;
 
-       hwif = ide_find_port(port);
+       hwif = ide_find_port();
        if (hwif) {
                int i;
 
index be9ff73..82643df 100644 (file)
@@ -34,7 +34,7 @@ static int __init ide_arm_init(void)
        ide_std_init_ports(&hw, IDE_ARM_IO, IDE_ARM_IO + 0x206);
        hw.irq = IDE_ARM_IRQ;
 
-       hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
+       hwif = ide_find_port();
        if (hwif) {
                ide_init_port_hw(hwif, &hw);
                idx[0] = hwif->index;
index 420fcb7..666df77 100644 (file)
@@ -96,11 +96,11 @@ static void palm_bk3710_setudmamode(void __iomem *base, unsigned int dev,
        u16 val16;
 
        /* DMA Data Setup */
-       t0 = (palm_bk3710_udmatimings[mode].cycletime + ide_palm_clk - 1)
-                       / ide_palm_clk - 1;
-       tenv = (20 + ide_palm_clk - 1) / ide_palm_clk - 1;
-       trp = (palm_bk3710_udmatimings[mode].rptime + ide_palm_clk - 1)
-                       / ide_palm_clk - 1;
+       t0 = DIV_ROUND_UP(palm_bk3710_udmatimings[mode].cycletime,
+                         ide_palm_clk) - 1;
+       tenv = DIV_ROUND_UP(20, ide_palm_clk) - 1;
+       trp = DIV_ROUND_UP(palm_bk3710_udmatimings[mode].rptime,
+                          ide_palm_clk) - 1;
 
        /* udmatim Register */
        val16 = readw(base + BK3710_UDMATIM) & (dev ? 0xFF0F : 0xFFF0);
@@ -141,8 +141,8 @@ static void palm_bk3710_setdmamode(void __iomem *base, unsigned int dev,
        cycletime = max_t(int, t->cycle, min_cycle);
 
        /* DMA Data Setup */
-       t0 = (cycletime + ide_palm_clk - 1) / ide_palm_clk;
-       td = (t->active + ide_palm_clk - 1) / ide_palm_clk;
+       t0 = DIV_ROUND_UP(cycletime, ide_palm_clk);
+       td = DIV_ROUND_UP(t->active, ide_palm_clk);
        tkw = t0 - td - 1;
        td -= 1;
 
@@ -168,9 +168,9 @@ static void palm_bk3710_setpiomode(void __iomem *base, ide_drive_t *mate,
        struct ide_timing *t;
 
        /* PIO Data Setup */
-       t0 = (cycletime + ide_palm_clk - 1) / ide_palm_clk;
-       t2 = (ide_timing_find_mode(XFER_PIO_0 + mode)->active +
-             ide_palm_clk - 1) / ide_palm_clk;
+       t0 = DIV_ROUND_UP(cycletime, ide_palm_clk);
+       t2 = DIV_ROUND_UP(ide_timing_find_mode(XFER_PIO_0 + mode)->active,
+                         ide_palm_clk);
 
        t2i = t0 - t2 - 1;
        t2 -= 1;
@@ -192,8 +192,8 @@ static void palm_bk3710_setpiomode(void __iomem *base, ide_drive_t *mate,
 
        /* TASKFILE Setup */
        t = ide_timing_find_mode(XFER_PIO_0 + mode);
-       t0 = (t->cyc8b + ide_palm_clk - 1) / ide_palm_clk;
-       t2 = (t->act8b + ide_palm_clk - 1) / ide_palm_clk;
+       t0 = DIV_ROUND_UP(t->cyc8b, ide_palm_clk);
+       t2 = DIV_ROUND_UP(t->act8b, ide_palm_clk);
 
        t2i = t0 - t2 - 1;
        t2 -= 1;
@@ -378,7 +378,7 @@ static int __devinit palm_bk3710_probe(struct platform_device *pdev)
        hw.irq = irq->start;
        hw.chipset = ide_palm3710;
 
-       hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
+       hwif = ide_find_port();
        if (hwif == NULL)
                goto out;
 
index b30adcf..2c3d0ec 100644 (file)
@@ -44,7 +44,7 @@ rapide_probe(struct expansion_card *ec, const struct ecard_id *id)
                goto release;
        }
 
-       hwif = ide_find_port((unsigned long)base);
+       hwif = ide_find_port();
        if (hwif) {
                memset(&hw, 0, sizeof(hw));
                rapide_setup_ports(&hw, base, base + 0x818, 1 << 6, ec->irq);
index 31266d2..790a775 100644 (file)
@@ -804,7 +804,7 @@ static int __init init_e100_ide(void)
 
                cris_setup_ports(&hw, cris_ide_base_address(h));
 
-               hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
+               hwif = ide_find_port();
                if (hwif == NULL)
                        continue;
                ide_init_port_data(hwif, hwif->index);
index 4108ec4..92b02b9 100644 (file)
@@ -99,8 +99,7 @@ static int __init h8300_ide_init(void)
 
        hw_setup(&hw);
 
-       /* register if */
-       hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
+       hwif = ide_find_port();
        if (hwif == NULL) {
                printk(KERN_ERR "ide-h8300: IDE I/F register failed\n");
                return -ENOENT;
index fe5aefb..1afd95a 100644 (file)
@@ -13,8 +13,8 @@
  *
  * Suggestions are welcome. Patches that work are more welcome though. ;-)
  * For those wishing to work on this driver, please be sure you download
- * and comply with the latest Mt. Fuji (SFF8090 version 4) and ATAPI 
- * (SFF-8020i rev 2.6) standards. These documents can be obtained by 
+ * and comply with the latest Mt. Fuji (SFF8090 version 4) and ATAPI
+ * (SFF-8020i rev 2.6) standards. These documents can be obtained by
  * anonymous ftp from:
  * ftp://fission.dt.wdc.com/pub/standards/SFF_atapi/spec/SFF8020-r2.6/PS/8020r26.ps
  * ftp://ftp.avc-pioneer.com/Mtfuji4/Spec/Fuji4r10.pdf
@@ -51,7 +51,7 @@
 
 static DEFINE_MUTEX(idecd_ref_mutex);
 
-#define to_ide_cd(obj) container_of(obj, struct cdrom_info, kref) 
+#define to_ide_cd(obj) container_of(obj, struct cdrom_info, kref)
 
 #define ide_cd_g(disk) \
        container_of((disk)->private_data, struct cdrom_info, driver)
@@ -83,13 +83,12 @@ static void ide_cd_put(struct cdrom_info *cd)
 
 /* Mark that we've seen a media change, and invalidate our internal
    buffers. */
-static void cdrom_saw_media_change (ide_drive_t *drive)
+static void cdrom_saw_media_change(ide_drive_t *drive)
 {
        struct cdrom_info *cd = drive->driver_data;
 
        cd->cd_flags |= IDE_CD_FLAG_MEDIA_CHANGED;
        cd->cd_flags &= ~IDE_CD_FLAG_TOC_VALID;
-       cd->nsectors_buffered = 0;
 }
 
 static int cdrom_log_sense(ide_drive_t *drive, struct request *rq,
@@ -101,38 +100,39 @@ static int cdrom_log_sense(ide_drive_t *drive, struct request *rq,
                return 0;
 
        switch (sense->sense_key) {
-               case NO_SENSE: case RECOVERED_ERROR:
-                       break;
-               case NOT_READY:
-                       /*
-                        * don't care about tray state messages for
-                        * e.g. capacity commands or in-progress or
-                        * becoming ready
-                        */
-                       if (sense->asc == 0x3a || sense->asc == 0x04)
-                               break;
-                       log = 1;
-                       break;
-               case ILLEGAL_REQUEST:
-                       /*
-                        * don't log START_STOP unit with LoEj set, since
-                        * we cannot reliably check if drive can auto-close
-                        */
-                       if (rq->cmd[0] == GPCMD_START_STOP_UNIT && sense->asc == 0x24)
-                               break;
-                       log = 1;
-                       break;
-               case UNIT_ATTENTION:
-                       /*
-                        * Make good and sure we've seen this potential media
-                        * change. Some drives (i.e. Creative) fail to present
-                        * the correct sense key in the error register.
-                        */
-                       cdrom_saw_media_change(drive);
+       case NO_SENSE:
+       case RECOVERED_ERROR:
+               break;
+       case NOT_READY:
+               /*
+                * don't care about tray state messages for
+                * e.g. capacity commands or in-progress or
+                * becoming ready
+                */
+               if (sense->asc == 0x3a || sense->asc == 0x04)
                        break;
-               default:
-                       log = 1;
+               log = 1;
+               break;
+       case ILLEGAL_REQUEST:
+               /*
+                * don't log START_STOP unit with LoEj set, since
+                * we cannot reliably check if drive can auto-close
+                */
+               if (rq->cmd[0] == GPCMD_START_STOP_UNIT && sense->asc == 0x24)
                        break;
+               log = 1;
+               break;
+       case UNIT_ATTENTION:
+               /*
+                * Make good and sure we've seen this potential media
+                * change. Some drives (i.e. Creative) fail to present
+                * the correct sense key in the error register.
+                */
+               cdrom_saw_media_change(drive);
+               break;
+       default:
+               log = 1;
+               break;
        }
        return log;
 }
@@ -159,8 +159,8 @@ void cdrom_analyze_sense_data(ide_drive_t *drive,
                if (sense->sense_key == 0x05 && sense->asc == 0x24)
                        return;
 
-       if (sense->error_code == 0x70) {        /* Current Error */
-               switch(sense->sense_key) {
+       if (sense->error_code == 0x70) {        /* Current Error */
+               switch (sense->sense_key) {
                case MEDIUM_ERROR:
                case VOLUME_OVERFLOW:
                case ILLEGAL_REQUEST:
@@ -179,7 +179,7 @@ void cdrom_analyze_sense_data(ide_drive_t *drive,
                                bio_sectors = 4;
                        if (drive->queue->hardsect_size == 2048)
                                sector <<= 2;   /* Device sector size is 2K */
-                       sector &= ~(bio_sectors -1);
+                       sector &= ~(bio_sectors - 1);
                        valid = (sector - failed_command->sector) << 9;
 
                        if (valid < 0)
@@ -188,8 +188,8 @@ void cdrom_analyze_sense_data(ide_drive_t *drive,
                                drive->probed_capacity - sector < 4 * 75) {
                                set_capacity(info->disk, sector);
                        }
-               }
-       }
+               }
+       }
 
        ide_cd_log_error(drive->name, failed_command, sense);
 }
@@ -230,7 +230,7 @@ static void cdrom_queue_request_sense(ide_drive_t *drive, void *sense,
        (void) ide_do_drive_cmd(drive, rq, ide_preempt);
 }
 
-static void cdrom_end_request (ide_drive_t *drive, int uptodate)
+static void cdrom_end_request(ide_drive_t *drive, int uptodate)
 {
        struct request *rq = HWGROUP(drive)->rq;
        int nsectors = rq->hard_cur_sectors;
@@ -293,7 +293,7 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
 {
        struct request *rq = HWGROUP(drive)->rq;
        int stat, err, sense_key;
-       
+
        /* Check for errors. */
        stat = ide_read_status(drive);
 
@@ -334,26 +334,26 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
 
                /* Check for tray open. */
                if (sense_key == NOT_READY) {
-                       cdrom_saw_media_change (drive);
+                       cdrom_saw_media_change(drive);
                } else if (sense_key == UNIT_ATTENTION) {
                        /* Check for media change. */
-                       cdrom_saw_media_change (drive);
+                       cdrom_saw_media_change(drive);
                        /*printk("%s: media changed\n",drive->name);*/
                        return 0;
-               } else if ((sense_key == ILLEGAL_REQUEST) &&
-                          (rq->cmd[0] == GPCMD_START_STOP_UNIT)) {
-                       /*
-                        * Don't print error message for this condition--
-                        * SFF8090i indicates that 5/24/00 is the correct
-                        * response to a request to close the tray if the
-                        * drive doesn't have that capability.
-                        * cdrom_log_sense() knows this!
-                        */
+               } else if (sense_key == ILLEGAL_REQUEST &&
+                          rq->cmd[0] == GPCMD_START_STOP_UNIT) {
+                       /*
+                        * Don't print error message for this condition--
+                        * SFF8090i indicates that 5/24/00 is the correct
+                        * response to a request to close the tray if the
+                        * drive doesn't have that capability.
+                        * cdrom_log_sense() knows this!
+                        */
                } else if (!(rq->cmd_flags & REQ_QUIET)) {
                        /* Otherwise, print an error. */
                        ide_dump_status(drive, "packet command error", stat);
                }
-               
+
                rq->cmd_flags |= REQ_FAILED;
 
                /*
@@ -374,10 +374,10 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
                if (sense_key == NOT_READY) {
                        /* Tray open. */
                        if (rq_data_dir(rq) == READ) {
-                               cdrom_saw_media_change (drive);
+                               cdrom_saw_media_change(drive);
 
                                /* Fail the request. */
-                               printk ("%s: tray open\n", drive->name);
+                               printk("%s: tray open\n", drive->name);
                                do_end_request = 1;
                        } else {
                                struct cdrom_info *info = drive->driver_data;
@@ -399,7 +399,7 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
                                         */
                                        spin_lock_irqsave(&ide_lock, flags);
                                        blk_plug_device(drive->queue);
-                                       spin_unlock_irqrestore(&ide_lock,flags);
+                                       spin_unlock_irqrestore(&ide_lock, flags);
                                        return 1;
                                }
                        }
@@ -407,25 +407,31 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
                        /* Media change. */
                        cdrom_saw_media_change (drive);
 
-                       /* Arrange to retry the request.
-                          But be sure to give up if we've retried
-                          too many times. */
+                       /*
+                        * Arrange to retry the request.
+                        * But be sure to give up if we've retried
+                        * too many times.
+                        */
                        if (++rq->errors > ERROR_MAX)
                                do_end_request = 1;
                } else if (sense_key == ILLEGAL_REQUEST ||
                           sense_key == DATA_PROTECT) {
-                       /* No point in retrying after an illegal
-                          request or data protect error.*/
-                       ide_dump_status_no_sense (drive, "command error", stat);
+                       /*
+                        * No point in retrying after an illegal
+                        * request or data protect error.
+                        */
+                       ide_dump_status_no_sense(drive, "command error", stat);
                        do_end_request = 1;
                } else if (sense_key == MEDIUM_ERROR) {
-                       /* No point in re-trying a zillion times on a bad 
-                        * sector...  If we got here the error is not correctable */
-                       ide_dump_status_no_sense (drive, "media error (bad sector)", stat);
+                       /*
+                        * No point in re-trying a zillion times on a bad
+                        * sector... If we got here the error is not correctable
+                        */
+                       ide_dump_status_no_sense(drive, "media error (bad sector)", stat);
                        do_end_request = 1;
                } else if (sense_key == BLANK_CHECK) {
                        /* Disk appears blank ?? */
-                       ide_dump_status_no_sense (drive, "media error (blank)", stat);
+                       ide_dump_status_no_sense(drive, "media error (blank)", stat);
                        do_end_request = 1;
                } else if ((err & ~ABRT_ERR) != 0) {
                        /* Go to the default handler
@@ -486,18 +492,18 @@ static int cdrom_timer_expiry(ide_drive_t *drive)
         * ide_timer_expiry keep polling us for these.
         */
        switch (rq->cmd[0]) {
-               case GPCMD_BLANK:
-               case GPCMD_FORMAT_UNIT:
-               case GPCMD_RESERVE_RZONE_TRACK:
-               case GPCMD_CLOSE_TRACK:
-               case GPCMD_FLUSH_CACHE:
-                       wait = ATAPI_WAIT_PC;
-                       break;
-               default:
-                       if (!(rq->cmd_flags & REQ_QUIET))
-                               printk(KERN_INFO "ide-cd: cmd 0x%x timed out\n", rq->cmd[0]);
-                       wait = 0;
-                       break;
+       case GPCMD_BLANK:
+       case GPCMD_FORMAT_UNIT:
+       case GPCMD_RESERVE_RZONE_TRACK:
+       case GPCMD_CLOSE_TRACK:
+       case GPCMD_FLUSH_CACHE:
+               wait = ATAPI_WAIT_PC;
+               break;
+       default:
+               if (!(rq->cmd_flags & REQ_QUIET))
+                       printk(KERN_INFO "ide-cd: cmd 0x%x timed out\n", rq->cmd[0]);
+               wait = 0;
+               break;
        }
        return wait;
 }
@@ -557,7 +563,7 @@ static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive,
    HANDLER is the interrupt handler to call when the command completes
    or there's data ready. */
 #define ATAPI_MIN_CDB_BYTES 12
-static ide_startstop_t cdrom_transfer_packet_command (ide_drive_t *drive,
+static ide_startstop_t cdrom_transfer_packet_command(ide_drive_t *drive,
                                          struct request *rq,
                                          ide_handler_t *handler)
 {
@@ -626,47 +632,6 @@ static void ide_cd_drain_data(ide_drive_t *drive, int nsects)
 }
 
 /*
- * Buffer up to SECTORS_TO_TRANSFER sectors from the drive in our sector
- * buffer.  Once the first sector is added, any subsequent sectors are
- * assumed to be continuous (until the buffer is cleared).  For the first
- * sector added, SECTOR is its sector number.  (SECTOR is then ignored until
- * the buffer is cleared.)
- */
-static void cdrom_buffer_sectors (ide_drive_t *drive, unsigned long sector,
-                                  int sectors_to_transfer)
-{
-       struct cdrom_info *info = drive->driver_data;
-
-       /* Number of sectors to read into the buffer. */
-       int sectors_to_buffer = min_t(int, sectors_to_transfer,
-                                    (SECTOR_BUFFER_SIZE >> SECTOR_BITS) -
-                                      info->nsectors_buffered);
-
-       char *dest;
-
-       /* If we couldn't get a buffer, don't try to buffer anything... */
-       if (info->buffer == NULL)
-               sectors_to_buffer = 0;
-
-       /* If this is the first sector in the buffer, remember its number. */
-       if (info->nsectors_buffered == 0)
-               info->sector_buffered = sector;
-
-       /* Read the data into the buffer. */
-       dest = info->buffer + info->nsectors_buffered * SECTOR_SIZE;
-       while (sectors_to_buffer > 0) {
-               HWIF(drive)->atapi_input_bytes(drive, dest, SECTOR_SIZE);
-               --sectors_to_buffer;
-               --sectors_to_transfer;
-               ++info->nsectors_buffered;
-               dest += SECTOR_SIZE;
-       }
-
-       /* Throw away any remaining data. */
-       ide_cd_drain_data(drive, sectors_to_transfer);
-}
-
-/*
  * Check the contents of the interrupt reason register from the cdrom
  * and attempt to recover if there are problems.  Returns  0 if everything's
  * ok; nonzero if the request has been terminated.
@@ -686,7 +651,7 @@ static int ide_cd_check_ireason(ide_drive_t *drive, struct request *rq,
 
                /* Whoops... */
                printk(KERN_ERR "%s: %s: wrong transfer direction!\n",
-                               drive->name, __FUNCTION__);
+                               drive->name, __func__);
 
                xf = rw ? hwif->atapi_output_bytes : hwif->atapi_input_bytes;
                ide_cd_pad_transfer(drive, xf, len);
@@ -699,7 +664,7 @@ static int ide_cd_check_ireason(ide_drive_t *drive, struct request *rq,
        } else {
                /* Drive wants a command packet, or invalid ireason... */
                printk(KERN_ERR "%s: %s: bad interrupt reason 0x%02x\n",
-                               drive->name, __FUNCTION__, ireason);
+                               drive->name, __func__, ireason);
        }
 
        if (rq->cmd_type == REQ_TYPE_ATA_PC)
@@ -721,7 +686,7 @@ static int ide_cd_check_transfer_size(ide_drive_t *drive, int len)
                return 0;
 
        printk(KERN_ERR "%s: %s: Bad transfer size %d\n",
-                       drive->name, __FUNCTION__, len);
+                       drive->name, __func__, len);
 
        if (cd->cd_flags & IDE_CD_FLAG_LIMIT_NFRAMES)
                printk(KERN_ERR "  This drive is not supported by "
@@ -734,65 +699,6 @@ static int ide_cd_check_transfer_size(ide_drive_t *drive, int len)
        return 1;
 }
 
-/*
- * Try to satisfy some of the current read request from our cached data.
- * Returns nonzero if the request has been completed, zero otherwise.
- */
-static int cdrom_read_from_buffer (ide_drive_t *drive)
-{
-       struct cdrom_info *info = drive->driver_data;
-       struct request *rq = HWGROUP(drive)->rq;
-       unsigned short sectors_per_frame;
-
-       sectors_per_frame = queue_hardsect_size(drive->queue) >> SECTOR_BITS;
-
-       /* Can't do anything if there's no buffer. */
-       if (info->buffer == NULL) return 0;
-
-       /* Loop while this request needs data and the next block is present
-          in our cache. */
-       while (rq->nr_sectors > 0 &&
-              rq->sector >= info->sector_buffered &&
-              rq->sector < info->sector_buffered + info->nsectors_buffered) {
-               if (rq->current_nr_sectors == 0)
-                       cdrom_end_request(drive, 1);
-
-               memcpy (rq->buffer,
-                       info->buffer +
-                       (rq->sector - info->sector_buffered) * SECTOR_SIZE,
-                       SECTOR_SIZE);
-               rq->buffer += SECTOR_SIZE;
-               --rq->current_nr_sectors;
-               --rq->nr_sectors;
-               ++rq->sector;
-       }
-
-       /* If we've satisfied the current request,
-          terminate it successfully. */
-       if (rq->nr_sectors == 0) {
-               cdrom_end_request(drive, 1);
-               return -1;
-       }
-
-       /* Move on to the next buffer if needed. */
-       if (rq->current_nr_sectors == 0)
-               cdrom_end_request(drive, 1);
-
-       /* If this condition does not hold, then the kluge i use to
-          represent the number of sectors to skip at the start of a transfer
-          will fail.  I think that this will never happen, but let's be
-          paranoid and check. */
-       if (rq->current_nr_sectors < bio_cur_sectors(rq->bio) &&
-           (rq->sector & (sectors_per_frame - 1))) {
-               printk(KERN_ERR "%s: cdrom_read_from_buffer: buffer botch (%ld)\n",
-                       drive->name, (long)rq->sector);
-               cdrom_end_request(drive, 0);
-               return -1;
-       }
-
-       return 0;
-}
-
 static ide_startstop_t cdrom_newpc_intr(ide_drive_t *);
 
 /*
@@ -825,7 +731,7 @@ static ide_startstop_t cdrom_start_rw_cont(ide_drive_t *drive)
                        if (rq->current_nr_sectors !=
                            bio_cur_sectors(rq->bio)) {
                                printk(KERN_ERR "%s: %s: buffer botch (%u)\n",
-                                               drive->name, __FUNCTION__,
+                                               drive->name, __func__,
                                                rq->current_nr_sectors);
                                cdrom_end_request(drive, 0);
                                return ide_stopped;
@@ -849,7 +755,7 @@ static ide_startstop_t cdrom_start_rw_cont(ide_drive_t *drive)
 #define IDECD_SEEK_TIMER       (5 * WAIT_MIN_SLEEP)    /* 100 ms */
 #define IDECD_SEEK_TIMEOUT     (2 * WAIT_CMD)          /* 20 sec */
 
-static ide_startstop_t cdrom_seek_intr (ide_drive_t *drive)
+static ide_startstop_t cdrom_seek_intr(ide_drive_t *drive)
 {
        struct cdrom_info *info = drive->driver_data;
        int stat;
@@ -866,14 +772,14 @@ static ide_startstop_t cdrom_seek_intr (ide_drive_t *drive)
                         * this condition is far too common, to bother
                         * users about it
                         */
-                       /* printk("%s: disabled DSC seek overlap\n", drive->name);*/ 
+                       /* printk("%s: disabled DSC seek overlap\n", drive->name);*/
                        drive->dsc_overlap = 0;
                }
        }
        return ide_stopped;
 }
 
-static ide_startstop_t cdrom_start_seek_continuation (ide_drive_t *drive)
+static ide_startstop_t cdrom_start_seek_continuation(ide_drive_t *drive)
 {
        struct request *rq = HWGROUP(drive)->rq;
        sector_t frame = rq->sector;
@@ -888,7 +794,7 @@ static ide_startstop_t cdrom_start_seek_continuation (ide_drive_t *drive)
        return cdrom_transfer_packet_command(drive, rq, &cdrom_seek_intr);
 }
 
-static ide_startstop_t cdrom_start_seek (ide_drive_t *drive, unsigned int block)
+static ide_startstop_t cdrom_start_seek(ide_drive_t *drive, unsigned int block)
 {
        struct cdrom_info *info = drive->driver_data;
 
@@ -897,9 +803,11 @@ 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);
 }
 
-/* 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)
+/*
+ * 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)
 {
        if (rq->buffer != bio_data(rq->bio)) {
                sector_t n = (rq->buffer - (char *) bio_data(rq->bio)) / SECTOR_SIZE;
@@ -950,7 +858,7 @@ int ide_cd_queue_pc(ide_drive_t *drive, struct request *rq)
                error = ide_do_drive_cmd(drive, rq, ide_wait);
                time = jiffies - time;
 
-               /* FIXME: we should probably abort/retry or something 
+               /* FIXME: we should probably abort/retry or something
                 * in case of failure */
                if (rq->cmd_flags & REQ_FAILED) {
                        /* The request failed.  Retry if it was due to a unit
@@ -1057,7 +965,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
                        if (rq->current_nr_sectors > 0) {
                                printk(KERN_ERR "%s: %s: data underrun "
                                                "(%d blocks)\n",
-                                               drive->name, __FUNCTION__,
+                                               drive->name, __func__,
                                                rq->current_nr_sectors);
                                if (!write)
                                        rq->cmd_flags |= REQ_FAILED;
@@ -1134,11 +1042,9 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
                if (!ptr) {
                        if (blk_fs_request(rq) && !write)
                                /*
-                                * If the buffers are full, cache the rest
-                                * of the data in our internal buffer.
-                                */
-                               cdrom_buffer_sectors(drive, rq->sector,
-                                                    thislen >> 9);
+                                * If the buffers are full, pipe the rest into
+                                * oblivion. */
+                               ide_cd_drain_data(drive, thislen >> 9);
                        else {
                                printk(KERN_ERR "%s: confused, missing data\n",
                                                drive->name);
@@ -1243,10 +1149,6 @@ static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq)
                 * weirdness which might be present in the request packet.
                 */
                restore_request(rq);
-
-               /* Satisfy whatever we can of this request from our cache. */
-               if (cdrom_read_from_buffer(drive))
-                       return ide_stopped;
        }
 
        /*
@@ -1262,9 +1164,6 @@ static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq)
        } else
                cd->dma = drive->using_dma;
 
-       /* Clear the local sector buffer. */
-       cd->nsectors_buffered = 0;
-
        if (write)
                cd->devinfo.media_written = 1;
 
@@ -1320,7 +1219,7 @@ static ide_startstop_t cdrom_do_block_pc(ide_drive_t *drive, struct request *rq)
  * cdrom driver request routine.
  */
 static ide_startstop_t
-ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, sector_t block)
+ide_do_rw_cdrom(ide_drive_t *drive, struct request *rq, sector_t block)
 {
        ide_startstop_t action;
        struct cdrom_info *info = drive->driver_data;
@@ -1335,13 +1234,13 @@ ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, sector_t block)
                                        ide_stall_queue(drive, IDECD_SEEK_TIMER);
                                        return ide_stopped;
                                }
-                               printk (KERN_ERR "%s: DSC timeout\n", drive->name);
+                               printk(KERN_ERR "%s: DSC timeout\n", drive->name);
                        }
                        info->cd_flags &= ~IDE_CD_FLAG_SEEKING;
                }
-               if ((rq_data_dir(rq) == READ) && IDE_LARGE_SEEK(info->last_block, block, IDECD_SEEK_THRESHOLD) && drive->dsc_overlap) {
+               if ((rq_data_dir(rq) == READ) && IDE_LARGE_SEEK(info->last_block, block, IDECD_SEEK_THRESHOLD) && drive->dsc_overlap)
                        action = cdrom_start_seek(drive, block);
-               else
+               else
                        action = cdrom_start_rw(drive, rq);
                info->last_block = block;
                return action;
@@ -1374,7 +1273,7 @@ ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, sector_t block)
  */
 
 static
-void msf_from_bcd (struct atapi_msf *msf)
+void msf_from_bcd(struct atapi_msf *msf)
 {
        msf->minute = BCD2BIN(msf->minute);
        msf->second = BCD2BIN(msf->second);
@@ -1474,7 +1373,7 @@ int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense)
                /* Try to allocate space. */
                toc = kmalloc(sizeof(struct atapi_toc), GFP_KERNEL);
                if (toc == NULL) {
-                       printk (KERN_ERR "%s: No cdrom TOC buffer!\n", drive->name);
+                       printk(KERN_ERR "%s: No cdrom TOC buffer!\n", drive->name);
                        return -ENOMEM;
                }
                info->toc = toc;
@@ -1569,9 +1468,9 @@ int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense)
                                toc->ent[i].track = BCD2BIN(toc->ent[i].track);
                        msf_from_bcd(&toc->ent[i].addr.msf);
                }
-               toc->ent[i].addr.lba = msf_to_lba (toc->ent[i].addr.msf.minute,
-                                                  toc->ent[i].addr.msf.second,
-                                                  toc->ent[i].addr.msf.frame);
+               toc->ent[i].addr.lba = msf_to_lba(toc->ent[i].addr.msf.minute,
+                                                 toc->ent[i].addr.msf.second,
+                                                 toc->ent[i].addr.msf.frame);
        }
 
        /* Read the multisession information. */
@@ -1595,9 +1494,9 @@ int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense)
                if (stat)
                        return stat;
 
-               msf_from_bcd (&ms_tmp.ent.addr.msf);
+               msf_from_bcd(&ms_tmp.ent.addr.msf);
                toc->last_session_lba = msf_to_lba(ms_tmp.ent.addr.msf.minute,
-                                                  ms_tmp.ent.addr.msf.second,
+                                                  ms_tmp.ent.addr.msf.second,
                                                   ms_tmp.ent.addr.msf.frame);
        }
 
@@ -1679,7 +1578,7 @@ static struct cdrom_device_ops ide_cdrom_dops = {
        .generic_packet         = ide_cdrom_packet,
 };
 
-static int ide_cdrom_register (ide_drive_t *drive, int nslots)
+static int ide_cdrom_register(ide_drive_t *drive, int nslots)
 {
        struct cdrom_info *info = drive->driver_data;
        struct cdrom_device_info *devinfo = &info->devinfo;
@@ -1698,7 +1597,7 @@ static int ide_cdrom_register (ide_drive_t *drive, int nslots)
 }
 
 static
-int ide_cdrom_probe_capabilities (ide_drive_t *drive)
+int ide_cdrom_probe_capabilities(ide_drive_t *drive)
 {
        struct cdrom_info *cd = drive->driver_data;
        struct cdrom_device_info *cdi = &cd->devinfo;
@@ -1870,7 +1769,7 @@ static int ide_cdrom_prep_pc(struct request *rq)
                rq->errors = ILLEGAL_REQUEST;
                return BLKPREP_KILL;
        }
-       
+
        return BLKPREP_OK;
 }
 
@@ -1948,7 +1847,7 @@ static unsigned int ide_cd_flags(struct hd_driveid *id)
 }
 
 static
-int ide_cdrom_setup (ide_drive_t *drive)
+int ide_cdrom_setup(ide_drive_t *drive)
 {
        struct cdrom_info *cd = drive->driver_data;
        struct cdrom_device_info *cdi = &cd->devinfo;
@@ -1979,7 +1878,7 @@ int ide_cdrom_setup (ide_drive_t *drive)
        else if (cd->cd_flags & IDE_CD_FLAG_SANYO_3CD)
                cdi->sanyo_slot = 3;    /* 3 => use CD in slot 0 */
 
-       nslots = ide_cdrom_probe_capabilities (drive);
+       nslots = ide_cdrom_probe_capabilities(drive);
 
        /*
         * set correct block size
@@ -1991,7 +1890,7 @@ int ide_cdrom_setup (ide_drive_t *drive)
                drive->dsc_overlap = (drive->next != drive);
 
        if (ide_cdrom_register(drive, nslots)) {
-               printk (KERN_ERR "%s: ide_cdrom_setup failed to register device with the cdrom driver.\n", drive->name);
+               printk(KERN_ERR "%s: ide_cdrom_setup failed to register device with the cdrom driver.\n", drive->name);
                cd->devinfo.handle = NULL;
                return 1;
        }
@@ -1999,19 +1898,6 @@ int ide_cdrom_setup (ide_drive_t *drive)
        return 0;
 }
 
-#ifdef CONFIG_IDE_PROC_FS
-static
-sector_t ide_cdrom_capacity (ide_drive_t *drive)
-{
-       unsigned long capacity, sectors_per_frame;
-
-       if (cdrom_read_capacity(drive, &capacity, &sectors_per_frame, NULL))
-               return 0;
-
-       return capacity * sectors_per_frame;
-}
-#endif
-
 static void ide_cd_remove(ide_drive_t *drive)
 {
        struct cdrom_info *info = drive->driver_data;
@@ -2030,7 +1916,6 @@ static void ide_cd_release(struct kref *kref)
        ide_drive_t *drive = info->drive;
        struct gendisk *g = info->disk;
 
-       kfree(info->buffer);
        kfree(info->toc);
        if (devinfo->handle == drive)
                unregister_cdrom(devinfo);
@@ -2045,14 +1930,24 @@ static void ide_cd_release(struct kref *kref)
 static int ide_cd_probe(ide_drive_t *);
 
 #ifdef CONFIG_IDE_PROC_FS
+static sector_t ide_cdrom_capacity(ide_drive_t *drive)
+{
+       unsigned long capacity, sectors_per_frame;
+
+       if (cdrom_read_capacity(drive, &capacity, &sectors_per_frame, NULL))
+               return 0;
+
+       return capacity * sectors_per_frame;
+}
+
 static int proc_idecd_read_capacity
        (char *page, char **start, off_t off, int count, int *eof, void *data)
 {
        ide_drive_t *drive = data;
        int len;
 
-       len = sprintf(page,"%llu\n", (long long)ide_cdrom_capacity(drive));
-       PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
+       len = sprintf(page, "%llu\n", (long long)ide_cdrom_capacity(drive));
+       PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
 }
 
 static ide_proc_entry_t idecd_proc[] = {
@@ -2081,20 +1976,17 @@ static ide_driver_t ide_cdrom_driver = {
 #endif
 };
 
-static int idecd_open(struct inode * inode, struct file * file)
+static int idecd_open(struct inode *inode, struct file *file)
 {
        struct gendisk *disk = inode->i_bdev->bd_disk;
        struct cdrom_info *info;
        int rc = -ENOMEM;
 
-       if (!(info = ide_cd_get(disk)))
+       info = ide_cd_get(disk);
+       if (!info)
                return -ENXIO;
 
-       if (!info->buffer)
-               info->buffer = kmalloc(SECTOR_BUFFER_SIZE, GFP_KERNEL|__GFP_REPEAT);
-
-       if (info->buffer)
-               rc = cdrom_open(&info->devinfo, inode, file);
+       rc = cdrom_open(&info->devinfo, inode, file);
 
        if (rc < 0)
                ide_cd_put(info);
@@ -2102,12 +1994,12 @@ static int idecd_open(struct inode * inode, struct file * file)
        return rc;
 }
 
-static int idecd_release(struct inode * inode, struct file * file)
+static int idecd_release(struct inode *inode, struct file *file)
 {
        struct gendisk *disk = inode->i_bdev->bd_disk;
        struct cdrom_info *info = ide_cd_g(disk);
 
-       cdrom_release (&info->devinfo, file);
+       cdrom_release(&info->devinfo, file);
 
        ide_cd_put(info);
 
@@ -2139,7 +2031,7 @@ static int idecd_get_spindown(struct cdrom_device_info *cdi, unsigned long arg)
        struct packet_command cgc;
        char buffer[16];
        int stat;
-       char spindown;
+       char spindown;
 
        init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_UNKNOWN);
 
@@ -2148,12 +2040,12 @@ static int idecd_get_spindown(struct cdrom_device_info *cdi, unsigned long arg)
                return stat;
 
        spindown = buffer[11] & 0x0f;
-       if (copy_to_user((void __user *)arg, &spindown, sizeof (char)))
+       if (copy_to_user((void __user *)arg, &spindown, sizeof(char)))
                return -EFAULT;
        return 0;
 }
 
-static int idecd_ioctl (struct inode *inode, struct file *file,
+static int idecd_ioctl(struct inode *inode, struct file *file,
                        unsigned int cmd, unsigned long arg)
 {
        struct block_device *bdev = inode->i_bdev;
@@ -2161,13 +2053,13 @@ static int idecd_ioctl (struct inode *inode, struct file *file,
        int err;
 
        switch (cmd) {
-       case CDROMSETSPINDOWN:
+       case CDROMSETSPINDOWN:
                return idecd_set_spindown(&info->devinfo, arg);
-       case CDROMGETSPINDOWN:
+       case CDROMGETSPINDOWN:
                return idecd_get_spindown(&info->devinfo, arg);
        default:
                break;
-       }
+       }
 
        err = generic_ide_ioctl(info->drive, file, bdev, cmd, arg);
        if (err == -EINVAL)
@@ -2193,16 +2085,16 @@ static int idecd_revalidate_disk(struct gendisk *disk)
 }
 
 static struct block_device_operations idecd_ops = {
-       .owner          = THIS_MODULE,
-       .open           = idecd_open,
-       .release        = idecd_release,
-       .ioctl          = idecd_ioctl,
-       .media_changed  = idecd_media_changed,
-       .revalidate_disk= idecd_revalidate_disk
+       .owner                  = THIS_MODULE,
+       .open                   = idecd_open,
+       .release                = idecd_release,
+       .ioctl                  = idecd_ioctl,
+       .media_changed          = idecd_media_changed,
+       .revalidate_disk        = idecd_revalidate_disk
 };
 
 /* options */
-static char *ignore = NULL;
+static char *ignore;
 
 module_param(ignore, charp, 0400);
 MODULE_DESCRIPTION("ATAPI CD-ROM Driver");
index 22e3751..a58801c 100644 (file)
@@ -119,10 +119,6 @@ struct cdrom_info {
 
        struct atapi_toc *toc;
 
-       unsigned long   sector_buffered;
-       unsigned long   nsectors_buffered;
-       unsigned char   *buffer;
-
        /* The result of the last successful request sense command
           on this device. */
        struct request_sense sense_data;
index 39501d1..8e08d08 100644 (file)
@@ -16,8 +16,6 @@
 
 #define IDEDISK_VERSION        "1.18"
 
-//#define DEBUG
-
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/string.h>
@@ -88,7 +86,7 @@ static void ide_disk_put(struct ide_disk_obj *idkp)
  *
  * It is called only once for each drive.
  */
-static int lba_capacity_is_ok (struct hd_driveid *id)
+static int lba_capacity_is_ok(struct hd_driveid *id)
 {
        unsigned long lba_sects, chs_sects, head, tail;
 
@@ -176,7 +174,8 @@ static void ide_tf_set_cmd(ide_drive_t *drive, ide_task_t *task, u8 dma)
  * __ide_do_rw_disk() issues READ and WRITE commands to a disk,
  * using LBA if supported, or CHS otherwise, to address sectors.
  */
-static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq, sector_t block)
+static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
+                                       sector_t block)
 {
        ide_hwif_t *hwif        = HWIF(drive);
        unsigned int dma        = drive->using_dma;
@@ -228,7 +227,8 @@ static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
                        tf->device = (block >> 8) & 0xf;
                }
        } else {
-               unsigned int sect,head,cyl,track;
+               unsigned int sect, head, cyl, track;
+
                track = (int)block / drive->sect;
                sect  = (int)block % drive->sect + 1;
                head  = track % drive->head;
@@ -271,7 +271,8 @@ static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
  * 1073741822 == 549756 MB or 48bit addressing fake drive
  */
 
-static ide_startstop_t ide_do_rw_disk (ide_drive_t *drive, struct request *rq, sector_t block)
+static ide_startstop_t ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
+                                     sector_t block)
 {
        ide_hwif_t *hwif = HWIF(drive);
 
@@ -452,7 +453,7 @@ static void idedisk_check_hpa(ide_drive_t *drive)
  * in above order (i.e., if value of higher priority is available,
  * reset will be ignored).
  */
-static void init_idedisk_capacity (ide_drive_t  *drive)
+static void init_idedisk_capacity(ide_drive_t *drive)
 {
        struct hd_driveid *id = drive->id;
        /*
@@ -479,7 +480,7 @@ static void init_idedisk_capacity (ide_drive_t  *drive)
        }
 }
 
-static sector_t idedisk_capacity (ide_drive_t *drive)
+static sector_t idedisk_capacity(ide_drive_t *drive)
 {
        return drive->capacity64 - drive->sect0;
 }
@@ -524,10 +525,11 @@ static int proc_idedisk_read_cache
        int             len;
 
        if (drive->id_read)
-               len = sprintf(out,"%i\n", drive->id->buf_size / 2);
+               len = sprintf(out, "%i\n", drive->id->buf_size / 2);
        else
-               len = sprintf(out,"(none)\n");
-       PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
+               len = sprintf(out, "(none)\n");
+
+       PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
 }
 
 static int proc_idedisk_read_capacity
@@ -536,54 +538,52 @@ static int proc_idedisk_read_capacity
        ide_drive_t*drive = (ide_drive_t *)data;
        int len;
 
-       len = sprintf(page,"%llu\n", (long long)idedisk_capacity(drive));
-       PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
+       len = sprintf(page, "%llu\n", (long long)idedisk_capacity(drive));
+
+       PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
 }
 
-static int proc_idedisk_read_smart_thresholds
-       (char *page, char **start, off_t off, int count, int *eof, void *data)
+static int proc_idedisk_read_smart(char *page, char **start, off_t off,
+                                  int count, int *eof, void *data, u8 sub_cmd)
 {
        ide_drive_t     *drive = (ide_drive_t *)data;
        int             len = 0, i = 0;
 
-       if (get_smart_data(drive, page, SMART_READ_THRESHOLDS) == 0) {
+       if (get_smart_data(drive, page, sub_cmd) == 0) {
                unsigned short *val = (unsigned short *) page;
                char *out = ((char *)val) + (SECTOR_WORDS * 4);
                page = out;
                do {
-                       out += sprintf(out, "%04x%c", le16_to_cpu(*val), (++i & 7) ? ' ' : '\n');
+                       out += sprintf(out, "%04x%c", le16_to_cpu(*val),
+                                      (++i & 7) ? ' ' : '\n');
                        val += 1;
                } while (i < (SECTOR_WORDS * 2));
                len = out - page;
        }
-       PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
+
+       PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
 }
 
-static int proc_idedisk_read_smart_values
+static int proc_idedisk_read_sv
        (char *page, char **start, off_t off, int count, int *eof, void *data)
 {
-       ide_drive_t     *drive = (ide_drive_t *)data;
-       int             len = 0, i = 0;
+       return proc_idedisk_read_smart(page, start, off, count, eof, data,
+                                      SMART_READ_VALUES);
+}
 
-       if (get_smart_data(drive, page, SMART_READ_VALUES) == 0) {
-               unsigned short *val = (unsigned short *) page;
-               char *out = ((char *)val) + (SECTOR_WORDS * 4);
-               page = out;
-               do {
-                       out += sprintf(out, "%04x%c", le16_to_cpu(*val), (++i & 7) ? ' ' : '\n');
-                       val += 1;
-               } while (i < (SECTOR_WORDS * 2));
-               len = out - page;
-       }
-       PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
+static int proc_idedisk_read_st
+       (char *page, char **start, off_t off, int count, int *eof, void *data)
+{
+       return proc_idedisk_read_smart(page, start, off, count, eof, data,
+                                      SMART_READ_THRESHOLDS);
 }
 
 static ide_proc_entry_t idedisk_proc[] = {
-       { "cache",              S_IFREG|S_IRUGO,        proc_idedisk_read_cache,                NULL },
-       { "capacity",           S_IFREG|S_IRUGO,        proc_idedisk_read_capacity,             NULL },
-       { "geometry",           S_IFREG|S_IRUGO,        proc_ide_read_geometry,                 NULL },
-       { "smart_values",       S_IFREG|S_IRUSR,        proc_idedisk_read_smart_values,         NULL },
-       { "smart_thresholds",   S_IFREG|S_IRUSR,        proc_idedisk_read_smart_thresholds,     NULL },
+       { "cache",        S_IFREG|S_IRUGO, proc_idedisk_read_cache,    NULL },
+       { "capacity",     S_IFREG|S_IRUGO, proc_idedisk_read_capacity, NULL },
+       { "geometry",     S_IFREG|S_IRUGO, proc_ide_read_geometry,     NULL },
+       { "smart_values", S_IFREG|S_IRUSR, proc_idedisk_read_sv,       NULL },
+       { "smart_thresholds", S_IFREG|S_IRUSR, proc_idedisk_read_st,   NULL },
        { NULL, 0, NULL, NULL }
 };
 #endif /* CONFIG_IDE_PROC_FS */
@@ -625,12 +625,13 @@ static int set_multcount(ide_drive_t *drive, int arg)
        if (drive->special.b.set_multmode)
                return -EBUSY;
 
-       ide_init_drive_cmd (&rq);
+       ide_init_drive_cmd(&rq);
        rq.cmd_type = REQ_TYPE_ATA_TASKFILE;
 
        drive->mult_req = arg;
        drive->special.b.set_multmode = 1;
-       (void) ide_do_drive_cmd (drive, &rq, ide_wait);
+       (void)ide_do_drive_cmd(drive, &rq, ide_wait);
+
        return (drive->mult_count == arg) ? 0 : -EIO;
 }
 
@@ -706,7 +707,7 @@ static int write_cache(ide_drive_t *drive, int arg)
        return err;
 }
 
-static int do_idedisk_flushcache (ide_drive_t *drive)
+static int do_idedisk_flushcache(ide_drive_t *drive)
 {
        ide_task_t args;
 
@@ -719,7 +720,7 @@ static int do_idedisk_flushcache (ide_drive_t *drive)
        return ide_no_data_taskfile(drive, &args);
 }
 
-static int set_acoustic (ide_drive_t *drive, int arg)
+static int set_acoustic(ide_drive_t *drive, int arg)
 {
        ide_task_t args;
 
@@ -753,7 +754,7 @@ static int set_lba_addressing(ide_drive_t *drive, int arg)
                return 0;
 
        if (!idedisk_supports_lba48(drive->id))
-                return -EIO;
+               return -EIO;
        drive->addressing = arg;
        return 0;
 }
@@ -763,23 +764,35 @@ static void idedisk_add_settings(ide_drive_t *drive)
 {
        struct hd_driveid *id = drive->id;
 
-       ide_add_setting(drive,  "bios_cyl",     SETTING_RW,     TYPE_INT,       0,      65535,                  1,      1,      &drive->bios_cyl,       NULL);
-       ide_add_setting(drive,  "bios_head",    SETTING_RW,     TYPE_BYTE,      0,      255,                    1,      1,      &drive->bios_head,      NULL);
-       ide_add_setting(drive,  "bios_sect",    SETTING_RW,     TYPE_BYTE,      0,      63,                     1,      1,      &drive->bios_sect,      NULL);
-       ide_add_setting(drive,  "address",      SETTING_RW,     TYPE_BYTE,      0,      2,                      1,      1,      &drive->addressing,     set_lba_addressing);
-       ide_add_setting(drive,  "multcount",    SETTING_RW,     TYPE_BYTE,      0,      id->max_multsect,       1,      1,      &drive->mult_count,     set_multcount);
-       ide_add_setting(drive,  "nowerr",       SETTING_RW,     TYPE_BYTE,      0,      1,                      1,      1,      &drive->nowerr,         set_nowerr);
-       ide_add_setting(drive,  "lun",          SETTING_RW,     TYPE_INT,       0,      7,                      1,      1,      &drive->lun,            NULL);
-       ide_add_setting(drive,  "wcache",       SETTING_RW,     TYPE_BYTE,      0,      1,                      1,      1,      &drive->wcache,         write_cache);
-       ide_add_setting(drive,  "acoustic",     SETTING_RW,     TYPE_BYTE,      0,      254,                    1,      1,      &drive->acoustic,       set_acoustic);
-       ide_add_setting(drive,  "failures",     SETTING_RW,     TYPE_INT,       0,      65535,                  1,      1,      &drive->failures,       NULL);
-       ide_add_setting(drive,  "max_failures", SETTING_RW,     TYPE_INT,       0,      65535,                  1,      1,      &drive->max_failures,   NULL);
+       ide_add_setting(drive, "bios_cyl", SETTING_RW, TYPE_INT, 0, 65535, 1, 1,
+                       &drive->bios_cyl, NULL);
+       ide_add_setting(drive, "bios_head", SETTING_RW, TYPE_BYTE, 0, 255, 1, 1,
+                       &drive->bios_head, NULL);
+       ide_add_setting(drive, "bios_sect", SETTING_RW, TYPE_BYTE, 0, 63, 1, 1,
+                       &drive->bios_sect, NULL);
+       ide_add_setting(drive, "address", SETTING_RW, TYPE_BYTE, 0, 2, 1, 1,
+                       &drive->addressing, set_lba_addressing);
+       ide_add_setting(drive, "multcount", SETTING_RW, TYPE_BYTE, 0,
+                       id->max_multsect, 1, 1, &drive->mult_count,
+                       set_multcount);
+       ide_add_setting(drive, "nowerr", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1,
+                       &drive->nowerr, set_nowerr);
+       ide_add_setting(drive, "lun", SETTING_RW, TYPE_INT, 0, 7, 1, 1,
+                       &drive->lun, NULL);
+       ide_add_setting(drive, "wcache", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1,
+                       &drive->wcache, write_cache);
+       ide_add_setting(drive, "acoustic", SETTING_RW, TYPE_BYTE, 0, 254, 1, 1,
+                       &drive->acoustic, set_acoustic);
+       ide_add_setting(drive, "failures", SETTING_RW, TYPE_INT, 0, 65535, 1, 1,
+                       &drive->failures, NULL);
+       ide_add_setting(drive, "max_failures", SETTING_RW, TYPE_INT, 0, 65535,
+                       1, 1, &drive->max_failures, NULL);
 }
 #else
 static inline void idedisk_add_settings(ide_drive_t *drive) { ; }
 #endif
 
-static void idedisk_setup (ide_drive_t *drive)
+static void idedisk_setup(ide_drive_t *drive)
 {
        ide_hwif_t *hwif = drive->hwif;
        struct hd_driveid *id = drive->id;
@@ -792,11 +805,10 @@ static void idedisk_setup (ide_drive_t *drive)
 
        if (drive->removable) {
                /*
-                * Removable disks (eg. SYQUEST); ignore 'WD' drives 
+                * Removable disks (eg. SYQUEST); ignore 'WD' drives
                 */
-               if (id->model[0] != 'W' || id->model[1] != 'D') {
+               if (id->model[0] != 'W' || id->model[1] != 'D')
                        drive->doorlocking = 1;
-               }
        }
 
        (void)set_lba_addressing(drive, 1);
@@ -810,10 +822,11 @@ static void idedisk_setup (ide_drive_t *drive)
                blk_queue_max_sectors(drive->queue, max_s);
        }
 
-       printk(KERN_INFO "%s: max request size: %dKiB\n", drive->name, drive->queue->max_sectors / 2);
+       printk(KERN_INFO "%s: max request size: %dKiB\n", drive->name,
+                        drive->queue->max_sectors / 2);
 
        /* calculate drive capacity, and select LBA if possible */
-       init_idedisk_capacity (drive);
+       init_idedisk_capacity(drive);
 
        /* limit drive capacity to 137GB if LBA48 cannot be used */
        if (drive->addressing == 0 && drive->capacity64 > 1ULL << 28) {
@@ -826,9 +839,9 @@ static void idedisk_setup (ide_drive_t *drive)
 
        if ((hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) && drive->addressing) {
                if (drive->capacity64 > 1ULL << 28) {
-                       printk(KERN_INFO "%s: cannot use LBA48 DMA - PIO mode will"
-                                        " be used for accessing sectors > %u\n",
-                                        drive->name, 1 << 28);
+                       printk(KERN_INFO "%s: cannot use LBA48 DMA - PIO mode"
+                                        " will be used for accessing sectors "
+                                        "> %u\n", drive->name, 1 << 28);
                } else
                        drive->addressing = 0;
        }
@@ -837,7 +850,8 @@ static void idedisk_setup (ide_drive_t *drive)
         * if possible, give fdisk access to more of the drive,
         * by correcting bios_cyls:
         */
-       capacity = idedisk_capacity (drive);
+       capacity = idedisk_capacity(drive);
+
        if (!drive->forced_geom) {
 
                if (idedisk_supports_lba48(drive->id)) {
@@ -993,7 +1007,8 @@ static int idedisk_open(struct inode *inode, struct file *filp)
        struct ide_disk_obj *idkp;
        ide_drive_t *drive;
 
-       if (!(idkp = ide_disk_get(disk)))
+       idkp = ide_disk_get(disk);
+       if (idkp == NULL)
                return -ENXIO;
 
        drive = idkp->drive;
@@ -1115,13 +1130,13 @@ static int idedisk_revalidate_disk(struct gendisk *disk)
 }
 
 static struct block_device_operations idedisk_ops = {
-       .owner          = THIS_MODULE,
-       .open           = idedisk_open,
-       .release        = idedisk_release,
-       .ioctl          = idedisk_ioctl,
-       .getgeo         = idedisk_getgeo,
-       .media_changed  = idedisk_media_changed,
-       .revalidate_disk= idedisk_revalidate_disk
+       .owner                  = THIS_MODULE,
+       .open                   = idedisk_open,
+       .release                = idedisk_release,
+       .ioctl                  = idedisk_ioctl,
+       .getgeo                 = idedisk_getgeo,
+       .media_changed          = idedisk_media_changed,
+       .revalidate_disk        = idedisk_revalidate_disk
 };
 
 MODULE_DESCRIPTION("ATA DISK Driver");
@@ -1184,7 +1199,7 @@ failed:
        return -ENODEV;
 }
 
-static void __exit idedisk_exit (void)
+static void __exit idedisk_exit(void)
 {
        driver_unregister(&idedisk_driver.gen_driver);
 }
index d61e578..8757e5e 100644 (file)
@@ -703,17 +703,8 @@ static int ide_tune_dma(ide_drive_t *drive)
 
        speed = ide_max_dma_mode(drive);
 
-       if (!speed) {
-                /* is this really correct/needed? */
-               if ((hwif->host_flags & IDE_HFLAG_CY82C693) &&
-                   ide_dma_good_drive(drive))
-                       return 1;
-               else
-                       return 0;
-       }
-
-       if (hwif->host_flags & IDE_HFLAG_NO_SET_MODE)
-               return 1;
+       if (!speed)
+               return 0;
 
        if (ide_set_dma_mode(drive, speed))
                return 0;
index 5f133df..ed19a8b 100644 (file)
@@ -396,7 +396,7 @@ static void idefloppy_retry_pc(ide_drive_t *drive)
 }
 
 /* The usual interrupt handler called during a packet command. */
-static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive)
+static ide_startstop_t idefloppy_pc_intr(ide_drive_t *drive)
 {
        idefloppy_floppy_t *floppy = drive->driver_data;
        ide_hwif_t *hwif = drive->hwif;
@@ -1596,13 +1596,13 @@ static int idefloppy_revalidate_disk(struct gendisk *disk)
 }
 
 static struct block_device_operations idefloppy_ops = {
-       .owner          = THIS_MODULE,
-       .open           = idefloppy_open,
-       .release        = idefloppy_release,
-       .ioctl          = idefloppy_ioctl,
-       .getgeo         = idefloppy_getgeo,
-       .media_changed  = idefloppy_media_changed,
-       .revalidate_disk= idefloppy_revalidate_disk
+       .owner                  = THIS_MODULE,
+       .open                   = idefloppy_open,
+       .release                = idefloppy_release,
+       .ioctl                  = idefloppy_ioctl,
+       .getgeo                 = idefloppy_getgeo,
+       .media_changed          = idefloppy_media_changed,
+       .revalidate_disk        = idefloppy_revalidate_disk
 };
 
 static int ide_floppy_probe(ide_drive_t *drive)
index 25fda0a..19f63e3 100644 (file)
@@ -33,7 +33,7 @@ static ssize_t store_add(struct class *cls, const char *buf, size_t n)
        if (sscanf(buf, "%x:%x:%d", &base, &ctl, &irq) != 3)
                return -EINVAL;
 
-       hwif = ide_find_port(base);
+       hwif = ide_find_port();
        if (hwif == NULL)
                return -ENOENT;
 
@@ -90,11 +90,21 @@ static int __init ide_generic_init(void)
        int i;
 
        for (i = 0; i < MAX_HWIFS; i++) {
-               ide_hwif_t *hwif = &ide_hwifs[i];
+               ide_hwif_t *hwif;
                unsigned long io_addr = ide_default_io_base(i);
                hw_regs_t hw;
 
-               if (hwif->chipset == ide_unknown && io_addr) {
+               if (io_addr) {
+                       /*
+                        * Skip probing if the corresponding
+                        * slot is already occupied.
+                        */
+                       hwif = ide_find_port();
+                       if (hwif == NULL || hwif->index != i) {
+                               idx[i] = 0xff;
+                               continue;
+                       }
+
                        memset(&hw, 0, sizeof(hw));
                        ide_std_init_ports(&hw, io_addr, io_addr + 0x206);
                        hw.irq = ide_default_irq(io_addr);
index 31e5afa..51d181e 100644 (file)
@@ -726,10 +726,6 @@ static ide_startstop_t do_special (ide_drive_t *drive)
                s->b.set_tune = 0;
 
                if (set_pio_mode_abuse(drive->hwif, req_pio)) {
-
-                       if (hwif->set_pio_mode == NULL)
-                               return ide_stopped;
-
                        /*
                         * take ide_lock for drive->[no_]unmask/[no_]io_32bit
                         */
index 7031a8d..c859de7 100644 (file)
@@ -274,16 +274,6 @@ u8 ide_get_best_pio_mode (ide_drive_t *drive, u8 mode_wanted, u8 max_mode)
                if (overridden)
                        printk(KERN_INFO "%s: tPIO > 2, assuming tPIO = 2\n",
                                         drive->name);
-
-               /*
-                * Conservative "downgrade" for all pre-ATA2 drives
-                */
-               if ((drive->hwif->host_flags & IDE_HFLAG_PIO_NO_DOWNGRADE) == 0 &&
-                   pio_mode && pio_mode < 4) {
-                       pio_mode--;
-                       printk(KERN_INFO "%s: applying conservative "
-                                        "PIO \"downgrade\"\n", drive->name);
-               }
        }
 
        if (pio_mode > max_mode)
@@ -300,7 +290,8 @@ void ide_set_pio(ide_drive_t *drive, u8 req_pio)
        ide_hwif_t *hwif = drive->hwif;
        u8 host_pio, pio;
 
-       if (hwif->set_pio_mode == NULL)
+       if (hwif->set_pio_mode == NULL ||
+           (hwif->host_flags & IDE_HFLAG_NO_SET_MODE))
                return;
 
        BUG_ON(hwif->pio_mask == 0x00);
@@ -353,6 +344,9 @@ int ide_set_pio_mode(ide_drive_t *drive, const u8 mode)
 {
        ide_hwif_t *hwif = drive->hwif;
 
+       if (hwif->host_flags & IDE_HFLAG_NO_SET_MODE)
+               return 0;
+
        if (hwif->set_pio_mode == NULL)
                return -1;
 
@@ -380,6 +374,9 @@ int ide_set_dma_mode(ide_drive_t *drive, const u8 mode)
 {
        ide_hwif_t *hwif = drive->hwif;
 
+       if (hwif->host_flags & IDE_HFLAG_NO_SET_MODE)
+               return 0;
+
        if (hwif->set_dma_mode == NULL)
                return -1;
 
@@ -410,7 +407,8 @@ int ide_set_xfer_rate(ide_drive_t *drive, u8 rate)
 {
        ide_hwif_t *hwif = drive->hwif;
 
-       if (hwif->set_dma_mode == NULL)
+       if (hwif->set_dma_mode == NULL ||
+           (hwif->host_flags & IDE_HFLAG_NO_SET_MODE))
                return -1;
 
        rate = ide_rate_filter(drive, rate);
index 34c2ad3..8a178a5 100644 (file)
@@ -11,7 +11,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * (for example /usr/src/linux/COPYING); if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
 #include <linux/init.h>
 
 /* Add your devices here :)) */
 static struct pnp_device_id idepnp_devices[] = {
-       /* Generic ESDI/IDE/ATA compatible hard disk controller */
+       /* Generic ESDI/IDE/ATA compatible hard disk controller */
        {.id = "PNP0600", .driver_data = 0},
        {.id = ""}
 };
 
-static int idepnp_probe(struct pnp_dev * dev, const struct pnp_device_id *dev_id)
+static int idepnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
 {
        hw_regs_t hw;
        ide_hwif_t *hwif;
@@ -38,7 +38,7 @@ static int idepnp_probe(struct pnp_dev * dev, const struct pnp_device_id *dev_id
                                pnp_port_start(dev, 1));
        hw.irq = pnp_irq(dev, 0);
 
-       hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
+       hwif = ide_find_port();
        if (hwif) {
                u8 index = hwif->index;
                u8 idx[4] = { index, 0xff, 0xff, 0xff };
@@ -47,7 +47,7 @@ static int idepnp_probe(struct pnp_dev * dev, const struct pnp_device_id *dev_id
                ide_init_port_hw(hwif, &hw);
 
                printk(KERN_INFO "ide%d: generic PnP IDE interface\n", index);
-               pnp_set_drvdata(dev,hwif);
+               pnp_set_drvdata(dev, hwif);
 
                ide_device_add(idx, NULL);
 
@@ -57,7 +57,7 @@ static int idepnp_probe(struct pnp_dev * dev, const struct pnp_device_id *dev_id
        return -1;
 }
 
-static void idepnp_remove(struct pnp_dev * dev)
+static void idepnp_remove(struct pnp_dev *dev)
 {
        ide_hwif_t *hwif = pnp_get_drvdata(dev);
 
index 6a196c2..8754297 100644 (file)
@@ -1444,6 +1444,54 @@ static int ide_sysfs_register_port(ide_hwif_t *hwif)
        return rc;
 }
 
+/**
+ *     ide_find_port_slot      -       find free ide_hwifs[] slot
+ *     @d: IDE port info
+ *
+ *     Return the new hwif.  If we are out of free slots return NULL.
+ */
+
+ide_hwif_t *ide_find_port_slot(const struct ide_port_info *d)
+{
+       ide_hwif_t *hwif;
+       int i;
+       u8 bootable = (d && (d->host_flags & IDE_HFLAG_NON_BOOTABLE)) ? 0 : 1;
+
+       /*
+        * Claim an unassigned slot.
+        *
+        * Give preference to claiming other slots before claiming ide0/ide1,
+        * just in case there's another interface yet-to-be-scanned
+        * which uses ports 0x1f0/0x170 (the ide0/ide1 defaults).
+        *
+        * Unless there is a bootable card that does not use the standard
+        * ports 0x1f0/0x170 (the ide0/ide1 defaults).
+        */
+       if (bootable) {
+               i = (d && (d->host_flags & IDE_HFLAG_QD_2ND_PORT)) ? 1 : 0;
+
+               for (; i < MAX_HWIFS; i++) {
+                       hwif = &ide_hwifs[i];
+                       if (hwif->chipset == ide_unknown)
+                               return hwif;
+               }
+       } else {
+               for (i = 2; i < MAX_HWIFS; i++) {
+                       hwif = &ide_hwifs[i];
+                       if (hwif->chipset == ide_unknown)
+                               return hwif;
+               }
+               for (i = 0; i < 2 && i < MAX_HWIFS; i++) {
+                       hwif = &ide_hwifs[i];
+                       if (hwif->chipset == ide_unknown)
+                               return hwif;
+               }
+       }
+
+       return NULL;
+}
+EXPORT_SYMBOL_GPL(ide_find_port_slot);
+
 int ide_device_add_all(u8 *idx, const struct ide_port_info *d)
 {
        ide_hwif_t *hwif, *mate = NULL;
index edd7f18..5d3562b 100644 (file)
@@ -47,28 +47,28 @@ static int proc_ide_read_imodel
        const char      *name;
 
        switch (hwif->chipset) {
-               case ide_generic:       name = "generic";       break;
-               case ide_pci:           name = "pci";           break;
-               case ide_cmd640:        name = "cmd640";        break;
-               case ide_dtc2278:       name = "dtc2278";       break;
-               case ide_ali14xx:       name = "ali14xx";       break;
-               case ide_qd65xx:        name = "qd65xx";        break;
-               case ide_umc8672:       name = "umc8672";       break;
-               case ide_ht6560b:       name = "ht6560b";       break;
-               case ide_rz1000:        name = "rz1000";        break;
-               case ide_trm290:        name = "trm290";        break;
-               case ide_cmd646:        name = "cmd646";        break;
-               case ide_cy82c693:      name = "cy82c693";      break;
-               case ide_4drives:       name = "4drives";       break;
-               case ide_pmac:          name = "mac-io";        break;
-               case ide_au1xxx:        name = "au1xxx";        break;
-               case ide_palm3710:      name = "palm3710";      break;
-               case ide_etrax100:      name = "etrax100";      break;
-               case ide_acorn:         name = "acorn";         break;
-               default:                name = "(unknown)";     break;
+       case ide_generic:       name = "generic";       break;
+       case ide_pci:           name = "pci";           break;
+       case ide_cmd640:        name = "cmd640";        break;
+       case ide_dtc2278:       name = "dtc2278";       break;
+       case ide_ali14xx:       name = "ali14xx";       break;
+       case ide_qd65xx:        name = "qd65xx";        break;
+       case ide_umc8672:       name = "umc8672";       break;
+       case ide_ht6560b:       name = "ht6560b";       break;
+       case ide_rz1000:        name = "rz1000";        break;
+       case ide_trm290:        name = "trm290";        break;
+       case ide_cmd646:        name = "cmd646";        break;
+       case ide_cy82c693:      name = "cy82c693";      break;
+       case ide_4drives:       name = "4drives";       break;
+       case ide_pmac:          name = "mac-io";        break;
+       case ide_au1xxx:        name = "au1xxx";        break;
+       case ide_palm3710:      name = "palm3710";      break;
+       case ide_etrax100:      name = "etrax100";      break;
+       case ide_acorn:         name = "acorn";         break;
+       default:                name = "(unknown)";     break;
        }
        len = sprintf(page, "%s\n", name);
-       PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
+       PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
 }
 
 static int proc_ide_read_mate
@@ -81,7 +81,7 @@ static int proc_ide_read_mate
                len = sprintf(page, "%s\n", hwif->mate->name);
        else
                len = sprintf(page, "(none)\n");
-       PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
+       PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
 }
 
 static int proc_ide_read_channel
@@ -93,7 +93,7 @@ static int proc_ide_read_channel
        page[0] = hwif->channel ? '1' : '0';
        page[1] = '\n';
        len = 2;
-       PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
+       PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
 }
 
 static int proc_ide_read_identify
@@ -120,7 +120,7 @@ static int proc_ide_read_identify
                        len = out - page;
                }
        }
-       PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
+       PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
 }
 
 /**
@@ -197,7 +197,7 @@ EXPORT_SYMBOL(ide_add_setting);
  *     The caller must hold the setting semaphore.
  */
 
-static void __ide_remove_setting (ide_drive_t *drive, char *name)
+static void __ide_remove_setting(ide_drive_t *drive, char *name)
 {
        ide_settings_t **p, *setting;
 
@@ -205,7 +205,8 @@ static void __ide_remove_setting (ide_drive_t *drive, char *name)
 
        while ((*p) && strcmp((*p)->name, name))
                p = &((*p)->next);
-       if ((setting = (*p)) == NULL)
+       setting = (*p);
+       if (setting == NULL)
                return;
 
        (*p) = setting->next;
@@ -223,7 +224,7 @@ static void __ide_remove_setting (ide_drive_t *drive, char *name)
  *     caller must hold ide_setting_mtx.
  */
 
-static void auto_remove_settings (ide_drive_t *drive)
+static void auto_remove_settings(ide_drive_t *drive)
 {
        ide_settings_t *setting;
 repeat:
@@ -279,16 +280,16 @@ static int ide_read_setting(ide_drive_t *drive, ide_settings_t *setting)
 
        if ((setting->rw & SETTING_READ)) {
                spin_lock_irqsave(&ide_lock, flags);
-               switch(setting->data_type) {
-                       case TYPE_BYTE:
-                               val = *((u8 *) setting->data);
-                               break;
-                       case TYPE_SHORT:
-                               val = *((u16 *) setting->data);
-                               break;
-                       case TYPE_INT:
-                               val = *((u32 *) setting->data);
-                               break;
+               switch (setting->data_type) {
+               case TYPE_BYTE:
+                       val = *((u8 *) setting->data);
+                       break;
+               case TYPE_SHORT:
+                       val = *((u16 *) setting->data);
+                       break;
+               case TYPE_INT:
+                       val = *((u32 *) setting->data);
+                       break;
                }
                spin_unlock_irqrestore(&ide_lock, flags);
        }
@@ -326,15 +327,15 @@ static int ide_write_setting(ide_drive_t *drive, ide_settings_t *setting, int va
        if (ide_spin_wait_hwgroup(drive))
                return -EBUSY;
        switch (setting->data_type) {
-               case TYPE_BYTE:
-                       *((u8 *) setting->data) = val;
-                       break;
-               case TYPE_SHORT:
-                       *((u16 *) setting->data) = val;
-                       break;
-               case TYPE_INT:
-                       *((u32 *) setting->data) = val;
-                       break;
+       case TYPE_BYTE:
+               *((u8 *) setting->data) = val;
+               break;
+       case TYPE_SHORT:
+               *((u16 *) setting->data) = val;
+               break;
+       case TYPE_INT:
+               *((u32 *) setting->data) = val;
+               break;
        }
        spin_unlock_irq(&ide_lock);
        return 0;
@@ -390,7 +391,7 @@ void ide_add_generic_settings (ide_drive_t *drive)
 
 static void proc_ide_settings_warn(void)
 {
-       static int warned = 0;
+       static int warned;
 
        if (warned)
                return;
@@ -413,11 +414,12 @@ static int proc_ide_read_settings
        mutex_lock(&ide_setting_mtx);
        out += sprintf(out, "name\t\t\tvalue\t\tmin\t\tmax\t\tmode\n");
        out += sprintf(out, "----\t\t\t-----\t\t---\t\t---\t\t----\n");
-       while(setting) {
+       while (setting) {
                mul_factor = setting->mul_factor;
                div_factor = setting->div_factor;
                out += sprintf(out, "%-24s", setting->name);
-               if ((rc = ide_read_setting(drive, setting)) >= 0)
+               rc = ide_read_setting(drive, setting);
+               if (rc >= 0)
                        out += sprintf(out, "%-16d", rc * mul_factor / div_factor);
                else
                        out += sprintf(out, "%-16s", "write-only");
@@ -431,7 +433,7 @@ static int proc_ide_read_settings
        }
        len = out - page;
        mutex_unlock(&ide_setting_mtx);
-       PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
+       PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
 }
 
 #define MAX_LEN        30
@@ -512,8 +514,7 @@ static int proc_ide_write_settings(struct file *file, const char __user *buffer,
 
                        mutex_lock(&ide_setting_mtx);
                        setting = ide_find_setting_by_name(drive, name);
-                       if (!setting)
-                       {
+                       if (!setting) {
                                mutex_unlock(&ide_setting_mtx);
                                goto parse_error;
                        }
@@ -533,8 +534,8 @@ parse_error:
 int proc_ide_read_capacity
        (char *page, char **start, off_t off, int count, int *eof, void *data)
 {
-       int len = sprintf(page,"%llu\n", (long long)0x7fffffff);
-       PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
+       int len = sprintf(page, "%llu\n", (long long)0x7fffffff);
+       PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
 }
 
 EXPORT_SYMBOL_GPL(proc_ide_read_capacity);
@@ -546,13 +547,13 @@ int proc_ide_read_geometry
        char            *out = page;
        int             len;
 
-       out += sprintf(out,"physical     %d/%d/%d\n",
+       out += sprintf(out, "physical     %d/%d/%d\n",
                        drive->cyl, drive->head, drive->sect);
-       out += sprintf(out,"logical      %d/%d/%d\n",
+       out += sprintf(out, "logical      %d/%d/%d\n",
                        drive->bios_cyl, drive->bios_head, drive->bios_sect);
 
        len = out - page;
-       PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
+       PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
 }
 
 EXPORT_SYMBOL(proc_ide_read_geometry);
@@ -566,7 +567,7 @@ static int proc_ide_read_dmodel
 
        len = sprintf(page, "%.40s\n",
                (id && id->model[0]) ? (char *)id->model : "(none)");
-       PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
+       PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
 }
 
 static int proc_ide_read_driver
@@ -583,7 +584,7 @@ static int proc_ide_read_driver
                                dev->driver->name, ide_drv->version);
        } else
                len = sprintf(page, "ide-default version 0.9.newide\n");
-       PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
+       PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
 }
 
 static int ide_replace_subdriver(ide_drive_t *drive, const char *driver)
@@ -639,30 +640,26 @@ static int proc_ide_read_media
        int             len;
 
        switch (drive->media) {
-               case ide_disk:  media = "disk\n";
-                               break;
-               case ide_cdrom: media = "cdrom\n";
-                               break;
-               case ide_tape:  media = "tape\n";
-                               break;
-               case ide_floppy:media = "floppy\n";
-                               break;
-               case ide_optical:media = "optical\n";
-                               break;
-               default:        media = "UNKNOWN\n";
-                               break;
+       case ide_disk:          media = "disk\n";       break;
+       case ide_cdrom:         media = "cdrom\n";      break;
+       case ide_tape:          media = "tape\n";       break;
+       case ide_floppy:        media = "floppy\n";     break;
+       case ide_optical:       media = "optical\n";    break;
+       default:                media = "UNKNOWN\n";    break;
        }
-       strcpy(page,media);
+       strcpy(page, media);
        len = strlen(media);
-       PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
+       PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
 }
 
 static ide_proc_entry_t generic_drive_entries[] = {
-       { "driver",     S_IFREG|S_IRUGO,        proc_ide_read_driver,   proc_ide_write_driver },
-       { "identify",   S_IFREG|S_IRUSR,        proc_ide_read_identify, NULL },
-       { "media",      S_IFREG|S_IRUGO,        proc_ide_read_media,    NULL },
-       { "model",      S_IFREG|S_IRUGO,        proc_ide_read_dmodel,   NULL },
-       { "settings",   S_IFREG|S_IRUSR|S_IWUSR,proc_ide_read_settings, proc_ide_write_settings },
+       { "driver",     S_IFREG|S_IRUGO,         proc_ide_read_driver,
+                                                proc_ide_write_driver },
+       { "identify",   S_IFREG|S_IRUSR,         proc_ide_read_identify, NULL },
+       { "media",      S_IFREG|S_IRUGO,         proc_ide_read_media,    NULL },
+       { "model",      S_IFREG|S_IRUGO,         proc_ide_read_dmodel,   NULL },
+       { "settings",   S_IFREG|S_IRUSR|S_IWUSR, proc_ide_read_settings,
+                                                proc_ide_write_settings },
        { NULL, 0, NULL, NULL }
 };
 
@@ -734,7 +731,6 @@ void ide_proc_unregister_driver(ide_drive_t *drive, ide_driver_t *driver)
        spin_unlock_irqrestore(&ide_lock, flags);
        mutex_unlock(&ide_setting_mtx);
 }
-
 EXPORT_SYMBOL(ide_proc_unregister_driver);
 
 void ide_proc_port_register_devices(ide_hwif_t *hwif)
@@ -755,7 +751,7 @@ void ide_proc_port_register_devices(ide_hwif_t *hwif)
                drive->proc = proc_mkdir(drive->name, parent);
                if (drive->proc)
                        ide_add_proc_entries(drive->proc, generic_drive_entries, drive);
-               sprintf(name,"ide%d/%s", (drive->name[2]-'a')/2, drive->name);
+               sprintf(name, "ide%d/%s", (drive->name[2]-'a')/2, drive->name);
                ent = proc_symlink(drive->name, proc_ide_root, name);
                if (!ent) return;
        }
@@ -795,7 +791,6 @@ void ide_pci_create_host_proc(const char *name, get_info_t *get_info)
 {
        create_proc_info_entry(name, 0, proc_ide_root, get_info);
 }
-
 EXPORT_SYMBOL_GPL(ide_pci_create_host_proc);
 #endif
 
index 917c72d..d868ca4 100644 (file)
@@ -100,13 +100,8 @@ int ide_noacpitfs = 1;
 int ide_noacpionboot = 1;
 #endif
 
-/*
- * This is declared extern in ide.h, for access by other IDE modules:
- */
 ide_hwif_t ide_hwifs[MAX_HWIFS];       /* master data repository */
 
-EXPORT_SYMBOL(ide_hwifs);
-
 static void ide_port_init_devices_data(ide_hwif_t *);
 
 /*
@@ -232,30 +227,6 @@ static int ide_system_bus_speed(void)
        return pci_dev_present(pci_default) ? 33 : 50;
 }
 
-ide_hwif_t * ide_find_port(unsigned long base)
-{
-       ide_hwif_t *hwif;
-       int i;
-
-       for (i = 0; i < MAX_HWIFS; i++) {
-               hwif = &ide_hwifs[i];
-               if (hwif->io_ports[IDE_DATA_OFFSET] == base)
-                       goto found;
-       }
-
-       for (i = 0; i < MAX_HWIFS; i++) {
-               hwif = &ide_hwifs[i];
-               if (hwif->chipset == ide_unknown)
-                       goto found;
-       }
-
-       hwif = NULL;
-found:
-       return hwif;
-}
-
-EXPORT_SYMBOL_GPL(ide_find_port);
-
 static struct resource* hwif_request_region(ide_hwif_t *hwif,
                                            unsigned long addr, int num)
 {
@@ -280,29 +251,21 @@ static struct resource* hwif_request_region(ide_hwif_t *hwif,
 int ide_hwif_request_regions(ide_hwif_t *hwif)
 {
        unsigned long addr;
-       unsigned int i;
 
        if (hwif->mmio)
                return 0;
+
        addr = hwif->io_ports[IDE_CONTROL_OFFSET];
+
        if (addr && !hwif_request_region(hwif, addr, 1))
                goto control_region_busy;
-       hwif->straight8 = 0;
+
        addr = hwif->io_ports[IDE_DATA_OFFSET];
-       if ((addr | 7) == hwif->io_ports[IDE_STATUS_OFFSET]) {
-               if (!hwif_request_region(hwif, addr, 8))
-                       goto data_region_busy;
-               hwif->straight8 = 1;
-               return 0;
-       }
-       for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
-               addr = hwif->io_ports[i];
-               if (!hwif_request_region(hwif, addr, 1)) {
-                       while (--i)
-                               release_region(addr, 1);
-                       goto data_region_busy;
-               }
-       }
+       BUG_ON((addr | 7) != hwif->io_ports[IDE_STATUS_OFFSET]);
+
+       if (!hwif_request_region(hwif, addr, 8))
+               goto data_region_busy;
+
        return 0;
 
 data_region_busy:
@@ -328,19 +291,13 @@ control_region_busy:
 
 void ide_hwif_release_regions(ide_hwif_t *hwif)
 {
-       u32 i = 0;
-
        if (hwif->mmio)
                return;
+
        if (hwif->io_ports[IDE_CONTROL_OFFSET])
                release_region(hwif->io_ports[IDE_CONTROL_OFFSET], 1);
-       if (hwif->straight8) {
-               release_region(hwif->io_ports[IDE_DATA_OFFSET], 8);
-               return;
-       }
-       for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++)
-               if (hwif->io_ports[i])
-                       release_region(hwif->io_ports[i], 1);
+
+       release_region(hwif->io_ports[IDE_DATA_OFFSET], 8);
 }
 
 void ide_remove_port_from_hwgroup(ide_hwif_t *hwif)
@@ -627,11 +584,13 @@ out:
 int set_pio_mode(ide_drive_t *drive, int arg)
 {
        struct request rq;
+       ide_hwif_t *hwif = drive->hwif;
 
        if (arg < 0 || arg > 255)
                return -EINVAL;
 
-       if (drive->hwif->set_pio_mode == NULL)
+       if (hwif->set_pio_mode == NULL ||
+           (hwif->host_flags & IDE_HFLAG_NO_SET_MODE))
                return -ENOSYS;
 
        if (drive->special.b.set_tune)
index bc8b1f8..33bb7b8 100644 (file)
@@ -86,7 +86,7 @@ static u8 regOff;     /* output to base port to close registers */
 /*
  * Read a controller register.
  */
-static inline u8 inReg (u8 reg)
+static inline u8 inReg(u8 reg)
 {
        outb_p(reg, regPort);
        return inb(dataPort);
@@ -95,7 +95,7 @@ static inline u8 inReg (u8 reg)
 /*
  * Write a controller register.
  */
-static void outReg (u8 data, u8 reg)
+static void outReg(u8 data, u8 reg)
 {
        outb_p(reg, regPort);
        outb_p(data, dataPort);
@@ -143,7 +143,7 @@ static void ali14xx_set_pio_mode(ide_drive_t *drive, const u8 pio)
 /*
  * Auto-detect the IDE controller port.
  */
-static int __init findPort (void)
+static int __init findPort(void)
 {
        int i;
        u8 t;
@@ -175,7 +175,8 @@ static int __init findPort (void)
 /*
  * Initialize controller registers with default values.
  */
-static int __init initRegisters (void) {
+static int __init initRegisters(void)
+{
        const RegInitializer *p;
        u8 t;
        unsigned long flags;
@@ -199,7 +200,8 @@ static const struct ide_port_info ali14xx_port_info = {
 
 static int __init ali14xx_probe(void)
 {
-       static u8 idx[4] = { 0, 1, 0xff, 0xff };
+       ide_hwif_t *hwif, *mate;
+       static u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
        hw_regs_t hw[2];
 
        printk(KERN_DEBUG "ali14xx: base=0x%03x, regOn=0x%02x.\n",
@@ -219,18 +221,26 @@ static int __init ali14xx_probe(void)
        ide_std_init_ports(&hw[1], 0x170, 0x376);
        hw[1].irq = 15;
 
-       ide_init_port_hw(&ide_hwifs[0], &hw[0]);
-       ide_init_port_hw(&ide_hwifs[1], &hw[1]);
+       hwif = ide_find_port();
+       if (hwif) {
+               ide_init_port_hw(hwif, &hw[0]);
+               hwif->set_pio_mode = &ali14xx_set_pio_mode;
+               idx[0] = hwif->index;
+       }
 
-       ide_hwifs[0].set_pio_mode = &ali14xx_set_pio_mode;
-       ide_hwifs[1].set_pio_mode = &ali14xx_set_pio_mode;
+       mate = ide_find_port();
+       if (mate) {
+               ide_init_port_hw(mate, &hw[1]);
+               mate->set_pio_mode = &ali14xx_set_pio_mode;
+               idx[1] = mate->index;
+       }
 
        ide_device_add(idx, &ali14xx_port_info);
 
        return 0;
 }
 
-int probe_ali14xx = 0;
+int probe_ali14xx;
 
 module_param_named(probe, probe_ali14xx, bool, 0);
 MODULE_PARM_DESC(probe, "probe for ALI M14xx chipsets");
index fdd3791..6956eb8 100644 (file)
@@ -221,7 +221,7 @@ fail_base2:
 
                        buddha_setup_ports(&hw, base, ctl, irq_port, ack_intr);
 
-                       hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
+                       hwif = ide_find_port();
                        if (hwif) {
                                u8 index = hwif->index;
 
index 5f69cd2..9c6b324 100644 (file)
@@ -102,15 +102,9 @@ static int __init dtc2278_probe(void)
 {
        unsigned long flags;
        ide_hwif_t *hwif, *mate;
-       static u8 idx[4] = { 0, 1, 0xff, 0xff };
+       static u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
        hw_regs_t hw[2];
 
-       hwif = &ide_hwifs[0];
-       mate = &ide_hwifs[1];
-
-       if (hwif->chipset != ide_unknown || mate->chipset != ide_unknown)
-               return 1;
-
        local_irq_save(flags);
        /*
         * This enables the second interface
@@ -137,10 +131,18 @@ static int __init dtc2278_probe(void)
        ide_std_init_ports(&hw[1], 0x170, 0x376);
        hw[1].irq = 15;
 
-       ide_init_port_hw(hwif, &hw[0]);
-       ide_init_port_hw(mate, &hw[1]);
+       hwif = ide_find_port();
+       if (hwif) {
+               ide_init_port_hw(hwif, &hw[0]);
+               hwif->set_pio_mode = dtc2278_set_pio_mode;
+               idx[0] = hwif->index;
+       }
 
-       hwif->set_pio_mode = &dtc2278_set_pio_mode;
+       mate = ide_find_port();
+       if (mate) {
+               ide_init_port_hw(mate, &hw[1]);
+               idx[1] = mate->index;
+       }
 
        ide_device_add(idx, &dtc2278_port_info);
 
index e950afa..8c9c9f7 100644 (file)
@@ -22,6 +22,7 @@
 #include <asm/atariints.h>
 #include <asm/atari_stdma.h>
 
+#define DRV_NAME "falconide"
 
     /*
      *  Base of the IDE interface
@@ -74,15 +75,21 @@ static int __init falconide_init(void)
 
        printk(KERN_INFO "ide: Falcon IDE controller\n");
 
+       if (!request_mem_region(ATA_HD_BASE, 0x40, DRV_NAME)) {
+               printk(KERN_ERR "%s: resources busy\n", DRV_NAME);
+               return -EBUSY;
+       }
+
        falconide_setup_ports(&hw);
 
-       hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
+       hwif = ide_find_port();
        if (hwif) {
                u8 index = hwif->index;
                u8 idx[4] = { index, 0xff, 0xff, 0xff };
 
                ide_init_port_data(hwif, index);
                ide_init_port_hw(hwif, &hw);
+               hwif->mmio = 1;
 
                ide_get_lock(NULL, NULL);
                ide_device_add(idx, NULL);
index e3b4638..fcc8d52 100644 (file)
@@ -175,7 +175,7 @@ found:
 
        gayle_setup_ports(&hw, base, ctrlport, irqport, ack_intr);
 
-       hwif = ide_find_port(base);
+       hwif = ide_find_port();
        if (hwif) {
            u8 index = hwif->index;
 
index 0b0d867..abdedf5 100644 (file)
@@ -122,12 +122,12 @@ static int hd_error;
  *  This struct defines the HD's and their types.
  */
 struct hd_i_struct {
-       unsigned int head,sect,cyl,wpcom,lzone,ctl;
+       unsigned int head, sect, cyl, wpcom, lzone, ctl;
        int unit;
        int recalibrate;
        int special_op;
 };
-       
+
 #ifdef HD_TYPE
 static struct hd_i_struct hd_info[] = { HD_TYPE };
 static int NR_HD = ARRAY_SIZE(hd_info);
@@ -168,7 +168,7 @@ unsigned long read_timer(void)
 
        spin_lock_irqsave(&i8253_lock, flags);
        t = jiffies * 11932;
-       outb_p(0, 0x43);
+       outb_p(0, 0x43);
        i = inb_p(0x40);
        i |= inb(0x40) << 8;
        spin_unlock_irqrestore(&i8253_lock, flags);
@@ -183,7 +183,7 @@ static void __init hd_setup(char *str, int *ints)
        if (ints[0] != 3)
                return;
        if (hd_info[0].head != 0)
-               hdind=1;
+               hdind = 1;
        hd_info[hdind].head = ints[2];
        hd_info[hdind].sect = ints[3];
        hd_info[hdind].cyl = ints[1];
@@ -193,7 +193,7 @@ static void __init hd_setup(char *str, int *ints)
        NR_HD = hdind+1;
 }
 
-static void dump_status (const char *msg, unsigned int stat)
+static void dump_status(const char *msg, unsigned int stat)
 {
        char *name = "hd?";
        if (CURRENT)
@@ -291,7 +291,6 @@ static int controller_ready(unsigned int drive, unsigned int head)
        return 0;
 }
 
-               
 static void hd_out(struct hd_i_struct *disk,
                   unsigned int nsect,
                   unsigned int sect,
@@ -313,15 +312,15 @@ static void hd_out(struct hd_i_struct *disk,
                return;
        }
        SET_HANDLER(intr_addr);
-       outb_p(disk->ctl,HD_CMD);
-       port=HD_DATA;
-       outb_p(disk->wpcom>>2,++port);
-       outb_p(nsect,++port);
-       outb_p(sect,++port);
-       outb_p(cyl,++port);
-       outb_p(cyl>>8,++port);
-       outb_p(0xA0|(disk->unit<<4)|head,++port);
-       outb_p(cmd,++port);
+       outb_p(disk->ctl, HD_CMD);
+       port = HD_DATA;
+       outb_p(disk->wpcom >> 2, ++port);
+       outb_p(nsect, ++port);
+       outb_p(sect, ++port);
+       outb_p(cyl, ++port);
+       outb_p(cyl >> 8, ++port);
+       outb_p(0xA0 | (disk->unit << 4) | head, ++port);
+       outb_p(cmd, ++port);
 }
 
 static void hd_request (void);
@@ -344,14 +343,14 @@ static void reset_controller(void)
 {
        int     i;
 
-       outb_p(4,HD_CMD);
-       for(i = 0; i < 1000; i++) barrier();
-       outb_p(hd_info[0].ctl & 0x0f,HD_CMD);
-       for(i = 0; i < 1000; i++) barrier();
+       outb_p(4, HD_CMD);
+       for (i = 0; i < 1000; i++) barrier();
+       outb_p(hd_info[0].ctl & 0x0f, HD_CMD);
+       for (i = 0; i < 1000; i++) barrier();
        if (drive_busy())
                printk("hd: controller still busy\n");
        else if ((hd_error = inb(HD_ERROR)) != 1)
-               printk("hd: controller reset failed: %02x\n",hd_error);
+               printk("hd: controller reset failed: %02x\n", hd_error);
 }
 
 static void reset_hd(void)
@@ -371,8 +370,8 @@ repeat:
        if (++i < NR_HD) {
                struct hd_i_struct *disk = &hd_info[i];
                disk->special_op = disk->recalibrate = 1;
-               hd_out(disk,disk->sect,disk->sect,disk->head-1,
-                       disk->cyl,WIN_SPECIFY,&reset_hd);
+               hd_out(disk, disk->sect, disk->sect, disk->head-1,
+                       disk->cyl, WIN_SPECIFY, &reset_hd);
                if (reset)
                        goto repeat;
        } else
@@ -393,7 +392,7 @@ static void unexpected_hd_interrupt(void)
        unsigned int stat = inb_p(HD_STATUS);
 
        if (stat & (BUSY_STAT|DRQ_STAT|ECC_STAT|ERR_STAT)) {
-               dump_status ("unexpected interrupt", stat);
+               dump_status("unexpected interrupt", stat);
                SET_TIMER;
        }
 }
@@ -453,7 +452,7 @@ static void read_intr(void)
        return;
 ok_to_read:
        req = CURRENT;
-       insw(HD_DATA,req->buffer,256);
+       insw(HD_DATA, req->buffer, 256);
        req->sector++;
        req->buffer += 512;
        req->errors = 0;
@@ -507,7 +506,7 @@ ok_to_write:
                end_request(req, 1);
        if (i > 0) {
                SET_HANDLER(&write_intr);
-               outsw(HD_DATA,req->buffer,256);
+               outsw(HD_DATA, req->buffer, 256);
                local_irq_enable();
        } else {
 #if (HD_DELAY > 0)
@@ -560,11 +559,11 @@ static int do_special_op(struct hd_i_struct *disk, struct request *req)
 {
        if (disk->recalibrate) {
                disk->recalibrate = 0;
-               hd_out(disk,disk->sect,0,0,0,WIN_RESTORE,&recal_intr);
+               hd_out(disk, disk->sect, 0, 0, 0, WIN_RESTORE, &recal_intr);
                return reset;
        }
        if (disk->head > 16) {
-               printk ("%s: cannot handle device with more than 16 heads - giving up\n", req->rq_disk->disk_name);
+               printk("%s: cannot handle device with more than 16 heads - giving up\n", req->rq_disk->disk_name);
                end_request(req, 0);
        }
        disk->special_op = 0;
@@ -633,19 +632,21 @@ repeat:
        if (blk_fs_request(req)) {
                switch (rq_data_dir(req)) {
                case READ:
-                       hd_out(disk,nsect,sec,head,cyl,WIN_READ,&read_intr);
+                       hd_out(disk, nsect, sec, head, cyl, WIN_READ,
+                               &read_intr);
                        if (reset)
                                goto repeat;
                        break;
                case WRITE:
-                       hd_out(disk,nsect,sec,head,cyl,WIN_WRITE,&write_intr);
+                       hd_out(disk, nsect, sec, head, cyl, WIN_WRITE,
+                               &write_intr);
                        if (reset)
                                goto repeat;
                        if (wait_DRQ()) {
                                bad_rw_intr();
                                goto repeat;
                        }
-                       outsw(HD_DATA,req->buffer,256);
+                       outsw(HD_DATA, req->buffer, 256);
                        break;
                default:
                        printk("unknown hd-command\n");
@@ -655,7 +656,7 @@ repeat:
        }
 }
 
-static void do_hd_request (struct request_queue * q)
+static void do_hd_request(struct request_queue *q)
 {
        disable_irq(HD_IRQ);
        hd_request();
@@ -708,12 +709,12 @@ static int __init hd_init(void)
 {
        int drive;
 
-       if (register_blkdev(MAJOR_NR,"hd"))
+       if (register_blkdev(MAJOR_NR, "hd"))
                return -1;
 
        hd_queue = blk_init_queue(do_hd_request, &hd_lock);
        if (!hd_queue) {
-               unregister_blkdev(MAJOR_NR,"hd");
+               unregister_blkdev(MAJOR_NR, "hd");
                return -ENOMEM;
        }
 
@@ -742,7 +743,7 @@ static int __init hd_init(void)
                goto out;
        }
 
-       for (drive=0 ; drive < NR_HD ; drive++) {
+       for (drive = 0 ; drive < NR_HD ; drive++) {
                struct gendisk *disk = alloc_disk(64);
                struct hd_i_struct *p = &hd_info[drive];
                if (!disk)
@@ -756,7 +757,7 @@ static int __init hd_init(void)
                disk->queue = hd_queue;
                p->unit = drive;
                hd_gendisk[drive] = disk;
-               printk ("%s: %luMB, CHS=%d/%d/%d\n",
+               printk("%s: %luMB, CHS=%d/%d/%d\n",
                        disk->disk_name, (unsigned long)get_capacity(disk)/2048,
                        p->cyl, p->head, p->sect);
        }
@@ -776,7 +777,7 @@ static int __init hd_init(void)
        }
 
        /* Let them fly */
-       for(drive=0; drive < NR_HD; drive++)
+       for (drive = 0; drive < NR_HD; drive++)
                add_disk(hd_gendisk[drive]);
 
        return 0;
@@ -791,7 +792,7 @@ out1:
        NR_HD = 0;
 out:
        del_timer(&device_timer);
-       unregister_blkdev(MAJOR_NR,"hd");
+       unregister_blkdev(MAJOR_NR, "hd");
        blk_cleanup_queue(hd_queue);
        return -1;
 Enomem:
@@ -800,7 +801,8 @@ Enomem:
        goto out;
 }
 
-static int __init parse_hd_setup (char *line) {
+static int __init parse_hd_setup(char *line)
+{
        int ints[6];
 
        (void) get_options(line, ARRAY_SIZE(ints), ints);
index 88fe907..60f52f5 100644 (file)
@@ -35,6 +35,7 @@
  *  Try:  http://www.maf.iki.fi/~maf/ht6560b/
  */
 
+#define DRV_NAME       "ht6560b"
 #define HT6560B_VERSION "v0.08"
 
 #include <linux/module.h>
@@ -339,16 +340,13 @@ static const struct ide_port_info ht6560b_port_info __initdata = {
 static int __init ht6560b_init(void)
 {
        ide_hwif_t *hwif, *mate;
-       static u8 idx[4] = { 0, 1, 0xff, 0xff };
+       static u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
        hw_regs_t hw[2];
 
        if (probe_ht6560b == 0)
                return -ENODEV;
 
-       hwif = &ide_hwifs[0];
-       mate = &ide_hwifs[1];
-
-       if (!request_region(HT_CONFIG_PORT, 1, hwif->name)) {
+       if (!request_region(HT_CONFIG_PORT, 1, DRV_NAME)) {
                printk(KERN_NOTICE "%s: HT_CONFIG_PORT not found\n",
                        __FUNCTION__);
                return -ENODEV;
@@ -367,17 +365,23 @@ static int __init ht6560b_init(void)
        ide_std_init_ports(&hw[1], 0x170, 0x376);
        hw[1].irq = 15;
 
-       ide_init_port_hw(hwif, &hw[0]);
-       ide_init_port_hw(mate, &hw[1]);
-
-       hwif->selectproc = &ht6560b_selectproc;
-       hwif->set_pio_mode = &ht6560b_set_pio_mode;
-
-       mate->selectproc = &ht6560b_selectproc;
-       mate->set_pio_mode = &ht6560b_set_pio_mode;
+       hwif = ide_find_port();
+       if (hwif) {
+               ide_init_port_hw(hwif, &hw[0]);
+               hwif->selectproc     = ht6560b_selectproc;
+               hwif->set_pio_mode   = ht6560b_set_pio_mode;
+               hwif->port_init_devs = ht6560b_port_init_devs;
+               idx[0] = hwif->index;
+       }
 
-       hwif->port_init_devs = ht6560b_port_init_devs;
-       mate->port_init_devs = ht6560b_port_init_devs;
+       mate = ide_find_port();
+       if (mate) {
+               ide_init_port_hw(mate, &hw[1]);
+               mate->selectproc     = ht6560b_selectproc;
+               mate->set_pio_mode   = ht6560b_set_pio_mode;
+               mate->port_init_devs = ht6560b_port_init_devs;
+               idx[1] = mate->index;
+       }
 
        ide_device_add(idx, &ht6560b_port_info);
 
index ecd7f35..c352f12 100644 (file)
@@ -4,7 +4,7 @@
 #include <linux/module.h>
 #include <linux/ide.h>
 
-int probe_4drives = 0;
+int probe_4drives;
 
 module_param_named(probe, probe_4drives, bool, 0);
 MODULE_PARM_DESC(probe, "probe for generic IDE chipset with 4 drives/port");
@@ -12,31 +12,37 @@ MODULE_PARM_DESC(probe, "probe for generic IDE chipset with 4 drives/port");
 static int __init ide_4drives_init(void)
 {
        ide_hwif_t *hwif, *mate;
-       u8 idx[4] = { 0, 1, 0xff, 0xff };
+       u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
        hw_regs_t hw;
 
        if (probe_4drives == 0)
                return -ENODEV;
 
-       hwif = &ide_hwifs[0];
-       mate = &ide_hwifs[1];
-
        memset(&hw, 0, sizeof(hw));
 
        ide_std_init_ports(&hw, 0x1f0, 0x3f6);
        hw.irq = 14;
        hw.chipset = ide_4drives;
 
-       ide_init_port_hw(hwif, &hw);
-       ide_init_port_hw(mate, &hw);
-
-       mate->drives[0].select.all ^= 0x20;
-       mate->drives[1].select.all ^= 0x20;
-
-       hwif->mate = mate;
-       mate->mate = hwif;
-
-       hwif->serialized = mate->serialized = 1;
+       hwif = ide_find_port();
+       if (hwif) {
+               ide_init_port_hw(hwif, &hw);
+               idx[0] = hwif->index;
+       }
+
+       mate = ide_find_port();
+       if (mate) {
+               ide_init_port_hw(mate, &hw);
+               mate->drives[0].select.all ^= 0x20;
+               mate->drives[1].select.all ^= 0x20;
+               idx[1] = mate->index;
+
+               if (hwif) {
+                       hwif->mate = mate;
+                       mate->mate = hwif;
+                       hwif->serialized = mate->serialized = 1;
+               }
+       }
 
        ide_device_add(idx, NULL);
 
index 9a23b94..b97b8d5 100644 (file)
@@ -156,7 +156,7 @@ static int idecs_register(unsigned long io, unsigned long ctl, unsigned long irq
     hw.chipset = ide_pci;
     hw.dev = &handle->dev;
 
-    hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
+    hwif = ide_find_port();
     if (hwif == NULL)
        return -1;
 
index 361b1bb..bf24077 100644 (file)
@@ -89,7 +89,7 @@ static int __devinit plat_ide_probe(struct platform_device *pdev)
                        res_alt->start, res_alt->end - res_alt->start + 1);
        }
 
-       hwif = ide_find_port((unsigned long)base);
+       hwif = ide_find_port();
        if (!hwif) {
                ret = -ENODEV;
                goto out;
@@ -100,11 +100,10 @@ static int __devinit plat_ide_probe(struct platform_device *pdev)
        hw.dev = &pdev->dev;
 
        ide_init_port_hw(hwif, &hw);
+       hwif->mmio = 1;
 
-       if (mmio) {
-               hwif->mmio = 1;
+       if (mmio)
                default_hwif_mmiops(hwif);
-       }
 
        idx[0] = hwif->index;
 
index eaf5dbe..7429b80 100644 (file)
@@ -120,7 +120,7 @@ static int __init macide_init(void)
 
        macide_setup_ports(&hw, base, irq, ack_intr);
 
-       hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
+       hwif = ide_find_port();
        if (hwif) {
                u8 index = hwif->index;
                u8 idx[4] = { index, 0xff, 0xff, 0xff };
index 2da2875..fcbff0e 100644 (file)
@@ -137,7 +137,7 @@ static int __init q40ide_init(void)
 //                     m68kide_iops,
                        q40ide_default_irq(pcide_bases[i]));
 
-       hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
+       hwif = ide_find_port();
        if (hwif) {
                ide_init_port_data(hwif, hwif->index);
                ide_init_port_hw(hwif, &hw);
index 7016bdf..6e820c7 100644 (file)
 static int timings[4]={-1,-1,-1,-1}; /* stores current timing for each timer */
 
 /*
- * qd_select:
+ * qd65xx_select:
  *
- * This routine is invoked from ide.c to prepare for access to a given drive.
+ * This routine is invoked to prepare for access to a given drive.
  */
 
-static void qd_select (ide_drive_t *drive)
+static void qd65xx_select(ide_drive_t *drive)
 {
        u8 index = ((   (QD_TIMREG(drive)) & 0x80 ) >> 7) |
                        (QD_TIMREG(drive) & 0x02);
@@ -168,36 +168,15 @@ static int qd_find_disk_type (ide_drive_t *drive,
 }
 
 /*
- * qd_timing_ok:
- *
- * check whether timings don't conflict
- */
-
-static int qd_timing_ok (ide_drive_t drives[])
-{
-       return (IDE_IMPLY(drives[0].present && drives[1].present,
-                       IDE_IMPLY(QD_TIMREG(drives) == QD_TIMREG(drives+1),
-                                 QD_TIMING(drives) == QD_TIMING(drives+1))));
-       /* if same timing register, must be same timing */
-}
-
-/*
  * qd_set_timing:
  *
- * records the timing, and enables selectproc as needed
+ * records the timing
  */
 
 static void qd_set_timing (ide_drive_t *drive, u8 timing)
 {
-       ide_hwif_t *hwif = HWIF(drive);
-
        drive->drive_data &= 0xff00;
        drive->drive_data |= timing;
-       if (qd_timing_ok(hwif->drives)) {
-               qd_select(drive); /* selects once */
-               hwif->selectproc = NULL;
-       } else
-               hwif->selectproc = &qd_select;
 
        printk(KERN_DEBUG "%s: %#x\n", drive->name, timing);
 }
@@ -225,10 +204,11 @@ static void qd6500_set_pio_mode(ide_drive_t *drive, const u8 pio)
 
 static void qd6580_set_pio_mode(ide_drive_t *drive, const u8 pio)
 {
-       int base = HWIF(drive)->select_data;
+       ide_hwif_t *hwif = drive->hwif;
        unsigned int cycle_time;
        int active_time   = 175;
        int recovery_time = 415; /* worst case values from the dos driver */
+       u8 base = (hwif->config_data & 0xff00) >> 8;
 
        if (drive->id && !qd_find_disk_type(drive, &active_time, &recovery_time)) {
                cycle_time = ide_pio_cycle_time(drive, pio);
@@ -299,21 +279,10 @@ static int __init qd_testreg(int port)
        return (readreg != QD_TESTVAL);
 }
 
-/*
- * qd_setup:
- *
- * called to setup an ata channel : adjusts attributes & links for tuning
- */
-
-static void __init qd_setup(ide_hwif_t *hwif, int base, int config)
-{
-       hwif->select_data = base;
-       hwif->config_data = config;
-}
-
 static void __init qd6500_port_init_devs(ide_hwif_t *hwif)
 {
-       u8 base = hwif->select_data, config = QD_CONFIG(hwif);
+       u8 base = (hwif->config_data & 0xff00) >> 8;
+       u8 config = QD_CONFIG(hwif);
 
        hwif->drives[0].drive_data = QD6500_DEF_DATA;
        hwif->drives[1].drive_data = QD6500_DEF_DATA;
@@ -322,9 +291,10 @@ static void __init qd6500_port_init_devs(ide_hwif_t *hwif)
 static void __init qd6580_port_init_devs(ide_hwif_t *hwif)
 {
        u16 t1, t2;
-       u8 base = hwif->select_data, config = QD_CONFIG(hwif);
+       u8 base = (hwif->config_data & 0xff00) >> 8;
+       u8 config = QD_CONFIG(hwif);
 
-       if (QD_CONTROL(hwif) & QD_CONTR_SEC_DISABLED) {
+       if (hwif->host_flags & IDE_HFLAG_SINGLE) {
                t1 = QD6580_DEF_DATA;
                t2 = QD6580_DEF_DATA2;
        } else
@@ -355,14 +325,18 @@ static int __init qd_probe(int base)
        u8 config, unit;
        u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
        hw_regs_t hw[2];
+       struct ide_port_info d = qd65xx_port_info;
 
        config = inb(QD_CONFIG_PORT);
 
        if (! ((config & QD_CONFIG_BASEPORT) >> 1 == (base == 0xb0)) )
-               return 1;
+               return -ENODEV;
 
        unit = ! (config & QD_CONFIG_IDE_BASEPORT);
 
+       if (unit)
+               d.host_flags |= IDE_HFLAG_QD_2ND_PORT;
+
        memset(&hw, 0, sizeof(hw));
 
        ide_std_init_ports(&hw[0], 0x1f0, 0x3f6);
@@ -373,30 +347,37 @@ static int __init qd_probe(int base)
 
        if ((config & 0xf0) == QD_CONFIG_QD6500) {
 
-               if (qd_testreg(base)) return 1;         /* bad register */
+               if (qd_testreg(base))
+                        return -ENODEV;        /* bad register */
 
                /* qd6500 found */
 
-               hwif = &ide_hwifs[unit];
-               printk(KERN_NOTICE "%s: qd6500 at %#x\n", hwif->name, base);
-               printk(KERN_DEBUG "qd6500: config=%#x, ID3=%u\n",
-                       config, QD_ID3);
-               
                if (config & QD_CONFIG_DISABLED) {
                        printk(KERN_WARNING "qd6500 is disabled !\n");
-                       return 1;
+                       return -ENODEV;
                }
 
+               printk(KERN_NOTICE "qd6500 at %#x\n", base);
+               printk(KERN_DEBUG "qd6500: config=%#x, ID3=%u\n",
+                       config, QD_ID3);
+
+               d.host_flags |= IDE_HFLAG_SINGLE;
+
+               hwif = ide_find_port_slot(&d);
+               if (hwif == NULL)
+                       return -ENOENT;
+
                ide_init_port_hw(hwif, &hw[unit]);
 
-               qd_setup(hwif, base, config);
+               hwif->config_data = (base << 8) | config;
 
                hwif->port_init_devs = qd6500_port_init_devs;
-               hwif->set_pio_mode = &qd6500_set_pio_mode;
+               hwif->set_pio_mode   = qd6500_set_pio_mode;
+               hwif->selectproc     = qd65xx_select;
 
-               idx[unit] = unit;
+               idx[unit] = hwif->index;
 
-               ide_device_add(idx, &qd65xx_port_info);
+               ide_device_add(idx, &d);
 
                return 1;
        }
@@ -406,8 +387,8 @@ static int __init qd_probe(int base)
 
                u8 control;
 
-               if (qd_testreg(base) || qd_testreg(base+0x02)) return 1;
-                       /* bad registers */
+               if (qd_testreg(base) || qd_testreg(base + 0x02))
+                       return -ENODEV; /* bad registers */
 
                /* qd6580 found */
 
@@ -422,46 +403,52 @@ static int __init qd_probe(int base)
                if (control & QD_CONTR_SEC_DISABLED) {
                        /* secondary disabled */
 
-                       hwif = &ide_hwifs[unit];
-                       printk(KERN_INFO "%s: qd6580: single IDE board\n",
-                                        hwif->name);
+                       printk(KERN_INFO "qd6580: single IDE board\n");
+
+                       d.host_flags |= IDE_HFLAG_SINGLE;
+
+                       hwif = ide_find_port_slot(&d);
+                       if (hwif == NULL)
+                               return -ENOENT;
 
                        ide_init_port_hw(hwif, &hw[unit]);
 
-                       qd_setup(hwif, base, config | (control << 8));
+                       hwif->config_data = (base << 8) | config;
 
                        hwif->port_init_devs = qd6580_port_init_devs;
-                       hwif->set_pio_mode = &qd6580_set_pio_mode;
+                       hwif->set_pio_mode   = qd6580_set_pio_mode;
+                       hwif->selectproc     = qd65xx_select;
 
-                       idx[unit] = unit;
+                       idx[unit] = hwif->index;
 
-                       ide_device_add(idx, &qd65xx_port_info);
+                       ide_device_add(idx, &d);
 
                        return 1;
                } else {
                        ide_hwif_t *mate;
 
-                       hwif = &ide_hwifs[0];
-                       mate = &ide_hwifs[1];
                        /* secondary enabled */
-                       printk(KERN_INFO "%s&%s: qd6580: dual IDE board\n",
-                                       hwif->name, mate->name);
-
-                       ide_init_port_hw(hwif, &hw[0]);
-                       ide_init_port_hw(mate, &hw[1]);
-
-                       qd_setup(hwif, base, config | (control << 8));
-
-                       hwif->port_init_devs = qd6580_port_init_devs;
-                       hwif->set_pio_mode = &qd6580_set_pio_mode;
-
-                       qd_setup(mate, base, config | (control << 8));
-
-                       mate->port_init_devs = qd6580_port_init_devs;
-                       mate->set_pio_mode = &qd6580_set_pio_mode;
-
-                       idx[0] = 0;
-                       idx[1] = 1;
+                       printk(KERN_INFO "qd6580: dual IDE board\n");
+
+                       hwif = ide_find_port();
+                       if (hwif) {
+                               ide_init_port_hw(hwif, &hw[0]);
+                               hwif->config_data = (base << 8) | config;
+                               hwif->port_init_devs = qd6580_port_init_devs;
+                               hwif->set_pio_mode   = qd6580_set_pio_mode;
+                               hwif->selectproc     = qd65xx_select;
+                               idx[0] = hwif->index;
+                       }
+
+                       mate = ide_find_port();
+                       if (mate) {
+                               ide_init_port_hw(mate, &hw[1]);
+                               mate->config_data = (base << 8) | config;
+                               mate->port_init_devs = qd6580_port_init_devs;
+                               mate->set_pio_mode   = qd6580_set_pio_mode;
+                               mate->selectproc     = qd65xx_select;
+                               idx[1] = mate->index;
+                       }
 
                        ide_device_add(idx, &qd65xx_port_info);
 
@@ -469,7 +456,7 @@ static int __init qd_probe(int base)
                }
        }
        /* no qd65xx found */
-       return 1;
+       return -ENODEV;
 }
 
 int probe_qd65xx = 0;
@@ -479,14 +466,18 @@ MODULE_PARM_DESC(probe, "probe for QD65xx chipsets");
 
 static int __init qd65xx_init(void)
 {
+       int rc1, rc2 = -ENODEV;
+
        if (probe_qd65xx == 0)
                return -ENODEV;
 
-       if (qd_probe(0x30))
-               qd_probe(0xb0);
-       if (ide_hwifs[0].chipset != ide_qd65xx &&
-           ide_hwifs[1].chipset != ide_qd65xx)
+       rc1 = qd_probe(0x30);
+       if (rc1)
+               rc2 = qd_probe(0xb0);
+
+       if (rc1 < 0 && rc2 < 0)
                return -ENODEV;
+
        return 0;
 }
 
index 28dd50a..c83dea8 100644 (file)
@@ -30,7 +30,6 @@
 #define QD_ID3                 ((config & QD_CONFIG_ID3)!=0)
 
 #define QD_CONFIG(hwif)                ((hwif)->config_data & 0x00ff)
-#define QD_CONTROL(hwif)       (((hwif)->config_data & 0xff00) >> 8)
 
 #define QD_TIMING(drive)       (byte)(((drive)->drive_data) & 0x00ff)
 #define QD_TIMREG(drive)       (byte)((((drive)->drive_data) & 0xff00) >> 8)
index bc19448..4d90bad 100644 (file)
@@ -19,7 +19,7 @@
  */
 
 /*
- * VLB Controller Support from 
+ * VLB Controller Support from
  * Wolfram Podien
  * Rohoefe 3
  * D28832 Achim
@@ -32,7 +32,7 @@
  * #define UMC_DRIVE0 11
  * in the beginning of the driver, which sets the speed of drive 0 to 11 (there
  * are some lines present). 0 - 11 are allowed speed values. These values are
- * the results from the DOS speed test program supplied from UMC. 11 is the 
+ * the results from the DOS speed test program supplied from UMC. 11 is the
  * highest speed (about PIO mode 3)
  */
 #define REALLY_SLOW_IO         /* some systems can safely undef this */
 #define UMC_DRIVE3      1              /* In case of crash reduce speed */
 
 static u8 current_speeds[4] = {UMC_DRIVE0, UMC_DRIVE1, UMC_DRIVE2, UMC_DRIVE3};
-static const u8 pio_to_umc [5] = {0,3,7,10,11};        /* rough guesses */
+static const u8 pio_to_umc [5] = {0, 3, 7, 10, 11};    /* rough guesses */
 
 /*       0    1    2    3    4    5    6    7    8    9    10   11      */
 static const u8 speedtab [3][12] = {
-       {0xf, 0xb, 0x2, 0x2, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 },
-       {0x3, 0x2, 0x2, 0x2, 0x2, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 },
-       {0xff,0xcb,0xc0,0x58,0x36,0x33,0x23,0x22,0x21,0x11,0x10,0x0}};
+       {0x0f, 0x0b, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x1},
+       {0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x1},
+       {0xff, 0xcb, 0xc0, 0x58, 0x36, 0x33, 0x23, 0x22, 0x21, 0x11, 0x10, 0x0}
+};
 
-static void out_umc (char port,char wert)
+static void out_umc(char port, char wert)
 {
-       outb_p(port,0x108);
-       outb_p(wert,0x109);
+       outb_p(port, 0x108);
+       outb_p(wert, 0x109);
 }
 
-static inline u8 in_umc (char port)
+static inline u8 in_umc(char port)
 {
-       outb_p(port,0x108);
+       outb_p(port, 0x108);
        return inb_p(0x109);
 }
 
-static void umc_set_speeds (u8 speeds[])
+static void umc_set_speeds(u8 speeds[])
 {
        int i, tmp;
 
-       outb_p(0x5A,0x108); /* enable umc */
+       outb_p(0x5A, 0x108); /* enable umc */
 
-       out_umc (0xd7,(speedtab[0][speeds[2]] | (speedtab[0][speeds[3]]<<4)));
-       out_umc (0xd6,(speedtab[0][speeds[0]] | (speedtab[0][speeds[1]]<<4)));
+       out_umc(0xd7, (speedtab[0][speeds[2]] | (speedtab[0][speeds[3]]<<4)));
+       out_umc(0xd6, (speedtab[0][speeds[0]] | (speedtab[0][speeds[1]]<<4)));
        tmp = 0;
-       for (i = 3; i >= 0; i--) {
+       for (i = 3; i >= 0; i--)
                tmp = (tmp << 2) | speedtab[1][speeds[i]];
+       out_umc(0xdc, tmp);
+       for (i = 0; i < 4; i++) {
+               out_umc(0xd0 + i, speedtab[2][speeds[i]]);
+               out_umc(0xd8 + i, speedtab[2][speeds[i]]);
        }
-       out_umc (0xdc,tmp);
-       for (i = 0;i < 4; i++) {
-               out_umc (0xd0+i,speedtab[2][speeds[i]]);
-               out_umc (0xd8+i,speedtab[2][speeds[i]]);
-       }
-       outb_p(0xa5,0x108); /* disable umc */
+       outb_p(0xa5, 0x108); /* disable umc */
 
-       printk ("umc8672: drive speeds [0 to 11]: %d %d %d %d\n",
+       printk("umc8672: drive speeds [0 to 11]: %d %d %d %d\n",
                speeds[0], speeds[1], speeds[2], speeds[3]);
 }
 
 static void umc_set_pio_mode(ide_drive_t *drive, const u8 pio)
 {
+       ide_hwif_t *hwif = drive->hwif;
        unsigned long flags;
-       ide_hwgroup_t *hwgroup = ide_hwifs[HWIF(drive)->index^1].hwgroup;
 
        printk("%s: setting umc8672 to PIO mode%d (speed %d)\n",
                drive->name, pio, pio_to_umc[pio]);
        spin_lock_irqsave(&ide_lock, flags);
-       if (hwgroup && hwgroup->handler != NULL) {
+       if (hwif->mate && hwif->mate->hwgroup->handler) {
                printk(KERN_ERR "umc8672: other interface is busy: exiting tune_umc()\n");
        } else {
                current_speeds[drive->name[2] - 'a'] = pio_to_umc[pio];
-               umc_set_speeds (current_speeds);
+               umc_set_speeds(current_speeds);
        }
        spin_unlock_irqrestore(&ide_lock, flags);
 }
@@ -128,8 +128,9 @@ static const struct ide_port_info umc8672_port_info __initdata = {
 
 static int __init umc8672_probe(void)
 {
+       ide_hwif_t *hwif, *mate;
        unsigned long flags;
-       static u8 idx[4] = { 0, 1, 0xff, 0xff };
+       static u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
        hw_regs_t hw[2];
 
        if (!request_region(0x108, 2, "umc8672")) {
@@ -137,16 +138,16 @@ static int __init umc8672_probe(void)
                return 1;
        }
        local_irq_save(flags);
-       outb_p(0x5A,0x108); /* enable umc */
+       outb_p(0x5A, 0x108); /* enable umc */
        if (in_umc (0xd5) != 0xa0) {
                local_irq_restore(flags);
                printk(KERN_ERR "umc8672: not found\n");
                release_region(0x108, 2);
-               return 1;  
+               return 1;
        }
-       outb_p(0xa5,0x108); /* disable umc */
+       outb_p(0xa5, 0x108); /* disable umc */
 
-       umc_set_speeds (current_speeds);
+       umc_set_speeds(current_speeds);
        local_irq_restore(flags);
 
        memset(&hw, 0, sizeof(hw));
@@ -157,18 +158,26 @@ static int __init umc8672_probe(void)
        ide_std_init_ports(&hw[1], 0x170, 0x376);
        hw[1].irq = 15;
 
-       ide_init_port_hw(&ide_hwifs[0], &hw[0]);
-       ide_init_port_hw(&ide_hwifs[1], &hw[1]);
+       hwif = ide_find_port();
+       if (hwif) {
+               ide_init_port_hw(hwif, &hw[0]);
+               hwif->set_pio_mode = umc_set_pio_mode;
+               idx[0] = hwif->index;
+       }
 
-       ide_hwifs[0].set_pio_mode = &umc_set_pio_mode;
-       ide_hwifs[1].set_pio_mode = &umc_set_pio_mode;
+       mate = ide_find_port();
+       if (mate) {
+               ide_init_port_hw(mate, &hw[1]);
+               mate->set_pio_mode = umc_set_pio_mode;
+               idx[1] = mate->index;
+       }
 
        ide_device_add(idx, &umc8672_port_info);
 
        return 0;
 }
 
-int probe_umc8672 = 0;
+int probe_umc8672;
 
 module_param_named(probe, probe_umc8672, bool, 0);
 MODULE_PARM_DESC(probe, "probe for UMC8672 chipset");
index 9b62824..a8cd003 100644 (file)
@@ -599,9 +599,11 @@ static int au_ide_probe(struct device *dev)
                goto out;
        }
 
-       /* FIXME:  This might possibly break PCMCIA IDE devices */
-
-       hwif                            = &ide_hwifs[pdev->id];
+       hwif = ide_find_port();
+       if (hwif == NULL) {
+               ret = -ENOENT;
+               goto out;
+       }
 
        memset(&hw, 0, sizeof(hw));
        auide_setup_ports(&hw, ahwif);
index 956259f..bbe8d58 100644 (file)
@@ -76,17 +76,12 @@ static int __devinit swarm_ide_probe(struct device *dev)
        if (!SIBYTE_HAVE_IDE)
                return -ENODEV;
 
-       /* Find an empty slot.  */
-       for (i = 0; i < MAX_HWIFS; i++)
-               if (!ide_hwifs[i].io_ports[IDE_DATA_OFFSET])
-                       break;
-       if (i >= MAX_HWIFS) {
+       hwif = ide_find_port();
+       if (hwif == NULL) {
                printk(KERN_ERR DRV_NAME ": no free slot for interface\n");
                return -ENOMEM;
        }
 
-       hwif = ide_hwifs + i;
-
        base = ioremap(A_IO_EXT_BASE, 0x800);
        offset = __raw_readq(base + R_IO_EXT_REG(R_IO_EXT_START_ADDR, IDE_CS));
        size = __raw_readq(base + R_IO_EXT_REG(R_IO_EXT_MULT_SIZE, IDE_CS));
index cfb3265..c9ba15a 100644 (file)
@@ -220,7 +220,8 @@ static const struct ide_port_info aec62xx_chipsets[] __devinitdata = {
                .init_hwif      = init_hwif_aec62xx,
                .enablebits     = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
                .host_flags     = IDE_HFLAG_NO_ATAPI_DMA |
-                                 IDE_HFLAG_ABUSE_SET_DMA_MODE,
+                                 IDE_HFLAG_ABUSE_SET_DMA_MODE |
+                                 IDE_HFLAG_NON_BOOTABLE,
                .pio_mask       = ATA_PIO4,
                .mwdma_mask     = ATA_MWDMA2,
                .udma_mask      = ATA_UDMA4,
index b3b6f51..3fa2d9f 100644 (file)
@@ -750,7 +750,6 @@ static const struct ide_port_info ali15x3_chipset __devinitdata = {
        .init_chipset   = init_chipset_ali15x3,
        .init_hwif      = init_hwif_ali15x3,
        .init_dma       = init_dma_ali15x3,
-       .host_flags     = IDE_HFLAG_BOOTABLE,
        .pio_mask       = ATA_PIO5,
        .swdma_mask     = ATA_SWDMA2,
        .mwdma_mask     = ATA_MWDMA2,
index 2ef890c..ff684d3 100644 (file)
@@ -219,12 +219,10 @@ static void __devinit init_hwif_amd74xx(ide_hwif_t *hwif)
 
 #define IDE_HFLAGS_AMD \
        (IDE_HFLAG_PIO_NO_BLACKLIST | \
-        IDE_HFLAG_PIO_NO_DOWNGRADE | \
         IDE_HFLAG_ABUSE_SET_DMA_MODE | \
         IDE_HFLAG_POST_SET_MODE | \
         IDE_HFLAG_IO_32BIT | \
-        IDE_HFLAG_UNMASK_IRQS | \
-        IDE_HFLAG_BOOTABLE)
+        IDE_HFLAG_UNMASK_IRQS)
 
 #define DECLARE_AMD_DEV(name_str, swdma, udma)                         \
        {                                                               \
index 7e037c8..91722f8 100644 (file)
@@ -151,7 +151,7 @@ static const struct ide_port_info atiixp_pci_info[] __devinitdata = {
                .name           = "ATIIXP",
                .init_hwif      = init_hwif_atiixp,
                .enablebits     = {{0x48,0x01,0x00}, {0x48,0x08,0x00}},
-               .host_flags     = IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_BOOTABLE,
+               .host_flags     = IDE_HFLAG_LEGACY_IRQS,
                .pio_mask       = ATA_PIO4,
                .mwdma_mask     = ATA_MWDMA2,
                .udma_mask      = ATA_UDMA5,
@@ -159,8 +159,7 @@ static const struct ide_port_info atiixp_pci_info[] __devinitdata = {
                .name           = "SB600_PATA",
                .init_hwif      = init_hwif_atiixp,
                .enablebits     = {{0x48,0x01,0x00}, {0x00,0x00,0x00}},
-               .host_flags     = IDE_HFLAG_SINGLE | IDE_HFLAG_LEGACY_IRQS |
-                                 IDE_HFLAG_BOOTABLE,
+               .host_flags     = IDE_HFLAG_SINGLE | IDE_HFLAG_LEGACY_IRQS,
                .pio_mask       = ATA_PIO4,
                .mwdma_mask     = ATA_MWDMA2,
                .udma_mask      = ATA_UDMA5,
index a1cfe03..b076dbf 100644 (file)
@@ -4,7 +4,7 @@
 
 /*
  *  Original authors:  abramov@cecmow.enet.dec.com (Igor Abramov)
- *                     mlord@pobox.com (Mark Lord)
+ *                     mlord@pobox.com (Mark Lord)
  *
  *  See linux/MAINTAINERS for address of current maintainer.
  *
@@ -98,7 +98,7 @@
 
 #define CMD640_PREFETCH_MASKS 1
 
-//#define CMD640_DUMP_REGS
+/*#define CMD640_DUMP_REGS */
 
 #include <linux/types.h>
 #include <linux/kernel.h>
 /*
  * This flag is set in ide.c by the parameter:  ide0=cmd640_vlb
  */
-int cmd640_vlb = 0;
+int cmd640_vlb;
 
 /*
  * CMD640 specific registers definition.
@@ -185,7 +185,6 @@ static DEFINE_SPINLOCK(cmd640_lock);
  * These are initialized to point at the devices we control
  */
 static ide_hwif_t  *cmd_hwif0, *cmd_hwif1;
-static ide_drive_t *cmd_drives[4];
 
 /*
  * Interface to access cmd640x registers
@@ -207,13 +206,13 @@ static unsigned int cmd640_chip_version;
 
 /* PCI method 1 access */
 
-static void put_cmd640_reg_pci1 (u16 reg, u8 val)
+static void put_cmd640_reg_pci1(u16 reg, u8 val)
 {
        outl_p((reg & 0xfc) | cmd640_key, 0xcf8);
        outb_p(val, (reg & 3) | 0xcfc);
 }
 
-static u8 get_cmd640_reg_pci1 (u16 reg)
+static u8 get_cmd640_reg_pci1(u16 reg)
 {
        outl_p((reg & 0xfc) | cmd640_key, 0xcf8);
        return inb_p((reg & 3) | 0xcfc);
@@ -221,14 +220,14 @@ static u8 get_cmd640_reg_pci1 (u16 reg)
 
 /* PCI method 2 access (from CMD datasheet) */
 
-static void put_cmd640_reg_pci2 (u16 reg, u8 val)
+static void put_cmd640_reg_pci2(u16 reg, u8 val)
 {
        outb_p(0x10, 0xcf8);
        outb_p(val, cmd640_key + reg);
        outb_p(0, 0xcf8);
 }
 
-static u8 get_cmd640_reg_pci2 (u16 reg)
+static u8 get_cmd640_reg_pci2(u16 reg)
 {
        u8 b;
 
@@ -240,13 +239,13 @@ static u8 get_cmd640_reg_pci2 (u16 reg)
 
 /* VLB access */
 
-static void put_cmd640_reg_vlb (u16 reg, u8 val)
+static void put_cmd640_reg_vlb(u16 reg, u8 val)
 {
        outb_p(reg, cmd640_key);
        outb_p(val, cmd640_key + 4);
 }
 
-static u8 get_cmd640_reg_vlb (u16 reg)
+static u8 get_cmd640_reg_vlb(u16 reg)
 {
        outb_p(reg, cmd640_key);
        return inb_p(cmd640_key + 4);
@@ -268,11 +267,11 @@ static void put_cmd640_reg(u16 reg, u8 val)
        unsigned long flags;
 
        spin_lock_irqsave(&cmd640_lock, flags);
-       __put_cmd640_reg(reg,val);
+       __put_cmd640_reg(reg, val);
        spin_unlock_irqrestore(&cmd640_lock, flags);
 }
 
-static int __init match_pci_cmd640_device (void)
+static int __init match_pci_cmd640_device(void)
 {
        const u8 ven_dev[4] = {0x95, 0x10, 0x40, 0x06};
        unsigned int i;
@@ -292,7 +291,7 @@ static int __init match_pci_cmd640_device (void)
 /*
  * Probe for CMD640x -- pci method 1
  */
-static int __init probe_for_cmd640_pci1 (void)
+static int __init probe_for_cmd640_pci1(void)
 {
        __get_cmd640_reg = get_cmd640_reg_pci1;
        __put_cmd640_reg = put_cmd640_reg_pci1;
@@ -308,7 +307,7 @@ static int __init probe_for_cmd640_pci1 (void)
 /*
  * Probe for CMD640x -- pci method 2
  */
-static int __init probe_for_cmd640_pci2 (void)
+static int __init probe_for_cmd640_pci2(void)
 {
        __get_cmd640_reg = get_cmd640_reg_pci2;
        __put_cmd640_reg = put_cmd640_reg_pci2;
@@ -322,7 +321,7 @@ static int __init probe_for_cmd640_pci2 (void)
 /*
  * Probe for CMD640x -- vlb
  */
-static int __init probe_for_cmd640_vlb (void)
+static int __init probe_for_cmd640_vlb(void)
 {
        u8 b;
 
@@ -343,7 +342,7 @@ static int __init probe_for_cmd640_vlb (void)
  *  Returns 1 if an IDE interface/drive exists at 0x170,
  *  Returns 0 otherwise.
  */
-static int __init secondary_port_responding (void)
+static int __init secondary_port_responding(void)
 {
        unsigned long flags;
 
@@ -367,7 +366,7 @@ static int __init secondary_port_responding (void)
 /*
  * Dump out all cmd640 registers.  May be called from ide.c
  */
-static void cmd640_dump_regs (void)
+static void cmd640_dump_regs(void)
 {
        unsigned int reg = cmd640_vlb ? 0x50 : 0x00;
 
@@ -386,9 +385,8 @@ static void cmd640_dump_regs (void)
  * Check whether prefetch is on for a drive,
  * and initialize the unmask flags for safe operation.
  */
-static void __init check_prefetch (unsigned int index)
+static void __init check_prefetch(ide_drive_t *drive, unsigned int index)
 {
-       ide_drive_t *drive = cmd_drives[index];
        u8 b = get_cmd640_reg(prefetch_regs[index]);
 
        if (b & prefetch_masks[index]) {        /* is prefetch off? */
@@ -404,28 +402,13 @@ static void __init check_prefetch (unsigned int index)
        }
 }
 
-/*
- * Figure out which devices we control
- */
-static void __init setup_device_ptrs (void)
-{
-       cmd_hwif0 = &ide_hwifs[0];
-       cmd_hwif1 = &ide_hwifs[1];
-
-       cmd_drives[0] = &cmd_hwif0->drives[0];
-       cmd_drives[1] = &cmd_hwif0->drives[1];
-       cmd_drives[2] = &cmd_hwif1->drives[0];
-       cmd_drives[3] = &cmd_hwif1->drives[1];
-}
-
 #ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
 
 /*
  * Sets prefetch mode for a drive.
  */
-static void set_prefetch_mode (unsigned int index, int mode)
+static void set_prefetch_mode(ide_drive_t *drive, unsigned int index, int mode)
 {
-       ide_drive_t *drive = cmd_drives[index];
        unsigned long flags;
        int reg = prefetch_regs[index];
        u8 b;
@@ -452,7 +435,7 @@ static void set_prefetch_mode (unsigned int index, int mode)
 /*
  * Dump out current drive clocks settings
  */
-static void display_clocks (unsigned int index)
+static void display_clocks(unsigned int index)
 {
        u8 active_count, recovery_count;
 
@@ -471,7 +454,7 @@ static void display_clocks (unsigned int index)
  * Pack active and recovery counts into single byte representation
  * used by controller
  */
-static inline u8 pack_nibbles (u8 upper, u8 lower)
+static inline u8 pack_nibbles(u8 upper, u8 lower)
 {
        return ((upper & 0x0f) << 4) | (lower & 0x0f);
 }
@@ -479,7 +462,7 @@ static inline u8 pack_nibbles (u8 upper, u8 lower)
 /*
  * This routine retrieves the initial drive timings from the chipset.
  */
-static void __init retrieve_drive_counts (unsigned int index)
+static void __init retrieve_drive_counts(unsigned int index)
 {
        u8 b;
 
@@ -488,10 +471,10 @@ static void __init retrieve_drive_counts (unsigned int index)
         */
        b = get_cmd640_reg(arttim_regs[index]) & ~0x3f;
        switch (b) {
-               case 0x00: b = 4; break;
-               case 0x80: b = 3; break;
-               case 0x40: b = 2; break;
-               default:   b = 5; break;
+       case 0x00: b = 4; break;
+       case 0x80: b = 3; break;
+       case 0x40: b = 2; break;
+       default:   b = 5; break;
        }
        setup_counts[index] = b;
 
@@ -508,7 +491,7 @@ static void __init retrieve_drive_counts (unsigned int index)
  * This routine writes the prepared setup/active/recovery counts
  * for a drive into the cmd640 chipset registers to active them.
  */
-static void program_drive_counts (unsigned int index)
+static void program_drive_counts(ide_drive_t *drive, unsigned int index)
 {
        unsigned long flags;
        u8 setup_count    = setup_counts[index];
@@ -522,8 +505,11 @@ static void program_drive_counts (unsigned int index)
         * so we merge the timings, using the slowest value for each timing.
         */
        if (index > 1) {
-               unsigned int mate;
-               if (cmd_drives[mate = index ^ 1]->present) {
+               ide_hwif_t *hwif = drive->hwif;
+               ide_drive_t *peer = &hwif->drives[!drive->select.b.unit];
+               unsigned int mate = index ^ 1;
+
+               if (peer->present) {
                        if (setup_count < setup_counts[mate])
                                setup_count = setup_counts[mate];
                        if (active_count < active_counts[mate])
@@ -537,11 +523,11 @@ static void program_drive_counts (unsigned int index)
         * Convert setup_count to internal chipset representation
         */
        switch (setup_count) {
-               case 4:  setup_count = 0x00; break;
-               case 3:  setup_count = 0x80; break;
-               case 1:
-               case 2:  setup_count = 0x40; break;
-               default: setup_count = 0xc0; /* case 5 */
+       case 4:  setup_count = 0x00; break;
+       case 3:  setup_count = 0x80; break;
+       case 1:
+       case 2:  setup_count = 0x40; break;
+       default: setup_count = 0xc0; /* case 5 */
        }
 
        /*
@@ -562,7 +548,8 @@ static void program_drive_counts (unsigned int index)
 /*
  * Set a specific pio_mode for a drive
  */
-static void cmd640_set_mode (unsigned int index, u8 pio_mode, unsigned int cycle_time)
+static void cmd640_set_mode(ide_drive_t *drive, unsigned int index,
+                           u8 pio_mode, unsigned int cycle_time)
 {
        int setup_time, active_time, recovery_time, clock_time;
        u8 setup_count, active_count, recovery_count, recovery_count2, cycle_count;
@@ -574,15 +561,15 @@ static void cmd640_set_mode (unsigned int index, u8 pio_mode, unsigned int cycle
        active_time = ide_pio_timings[pio_mode].active_time;
        recovery_time = cycle_time - (setup_time + active_time);
        clock_time = 1000 / bus_speed;
-       cycle_count = (cycle_time + clock_time - 1) / clock_time;
+       cycle_count = DIV_ROUND_UP(cycle_time, clock_time);
 
-       setup_count = (setup_time + clock_time - 1) / clock_time;
+       setup_count = DIV_ROUND_UP(setup_time, clock_time);
 
-       active_count = (active_time + clock_time - 1) / clock_time;
+       active_count = DIV_ROUND_UP(active_time, clock_time);
        if (active_count < 2)
                active_count = 2; /* minimum allowed by cmd640 */
 
-       recovery_count = (recovery_time + clock_time - 1) / clock_time;
+       recovery_count = DIV_ROUND_UP(recovery_time, clock_time);
        recovery_count2 = cycle_count - (setup_count + active_count);
        if (recovery_count2 > recovery_count)
                recovery_count = recovery_count2;
@@ -611,7 +598,7 @@ static void cmd640_set_mode (unsigned int index, u8 pio_mode, unsigned int cycle
         *      1) this is the wrong place to do it (proper is do_special() in ide.c)
         *      2) in practice this is rarely, if ever, necessary
         */
-       program_drive_counts (index);
+       program_drive_counts(drive, index);
 }
 
 static void cmd640_set_pio_mode(ide_drive_t *drive, const u8 pio)
@@ -619,32 +606,26 @@ static void cmd640_set_pio_mode(ide_drive_t *drive, const u8 pio)
        unsigned int index = 0, cycle_time;
        u8 b;
 
-       while (drive != cmd_drives[index]) {
-               if (++index > 3) {
-                       printk(KERN_ERR "%s: bad news in %s\n",
-                                       drive->name, __FUNCTION__);
-                       return;
-               }
-       }
        switch (pio) {
-               case 6: /* set fast-devsel off */
-               case 7: /* set fast-devsel on */
-                       b = get_cmd640_reg(CNTRL) & ~0x27;
-                       if (pio & 1)
-                               b |= 0x27;
-                       put_cmd640_reg(CNTRL, b);
-                       printk("%s: %sabled cmd640 fast host timing (devsel)\n", drive->name, (pio & 1) ? "en" : "dis");
-                       return;
-
-               case 8: /* set prefetch off */
-               case 9: /* set prefetch on */
-                       set_prefetch_mode(index, pio & 1);
-                       printk("%s: %sabled cmd640 prefetch\n", drive->name, (pio & 1) ? "en" : "dis");
-                       return;
+       case 6: /* set fast-devsel off */
+       case 7: /* set fast-devsel on */
+               b = get_cmd640_reg(CNTRL) & ~0x27;
+               if (pio & 1)
+                       b |= 0x27;
+               put_cmd640_reg(CNTRL, b);
+               printk("%s: %sabled cmd640 fast host timing (devsel)\n",
+                       drive->name, (pio & 1) ? "en" : "dis");
+               return;
+       case 8: /* set prefetch off */
+       case 9: /* set prefetch on */
+               set_prefetch_mode(drive, index, pio & 1);
+               printk("%s: %sabled cmd640 prefetch\n",
+                       drive->name, (pio & 1) ? "en" : "dis");
+               return;
        }
 
        cycle_time = ide_pio_cycle_time(drive, pio);
-       cmd640_set_mode(index, pio, cycle_time);
+       cmd640_set_mode(drive, index, pio, cycle_time);
 
        printk("%s: selected cmd640 PIO mode%d (%dns)",
                drive->name, pio, cycle_time);
@@ -749,7 +730,7 @@ static int __init cmd640x_init(void)
        cfr = get_cmd640_reg(CFR);
        cmd640_chip_version = cfr & CFR_DEVREV;
        if (cmd640_chip_version == 0) {
-               printk ("ide: bad cmd640 revision: %d\n", cmd640_chip_version);
+               printk("ide: bad cmd640 revision: %d\n", cmd640_chip_version);
                return 0;
        }
 
@@ -764,17 +745,19 @@ static int __init cmd640x_init(void)
        printk(KERN_INFO "cmd640: buggy cmd640%c interface on %s, config=0x%02x"
                         "\n", 'a' + cmd640_chip_version - 1, bus_type, cfr);
 
+       cmd_hwif0 = ide_find_port();
+
        /*
         * Initialize data for primary port
         */
-       setup_device_ptrs ();
-
-       ide_init_port_hw(cmd_hwif0, &hw[0]);
+       if (cmd_hwif0) {
+               ide_init_port_hw(cmd_hwif0, &hw[0]);
 #ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
-       cmd_hwif0->set_pio_mode = &cmd640_set_pio_mode;
+               cmd_hwif0->set_pio_mode = &cmd640_set_pio_mode;
 #endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
 
-       idx[0] = cmd_hwif0->index;
+               idx[0] = cmd_hwif0->index;
+       }
 
        /*
         * Ensure compatibility by always using the slowest timings
@@ -786,10 +769,13 @@ static int __init cmd640x_init(void)
        put_cmd640_reg(CMDTIM, 0);
        put_cmd640_reg(BRST, 0x40);
 
+       cmd_hwif1 = ide_find_port();
+
        /*
         * Try to enable the secondary interface, if not already enabled
         */
-       if (cmd_hwif1->drives[0].noprobe && cmd_hwif1->drives[1].noprobe) {
+       if (cmd_hwif1 &&
+           cmd_hwif1->drives[0].noprobe && cmd_hwif1->drives[1].noprobe) {
                port2 = "not probed";
        } else {
                b = get_cmd640_reg(CNTRL);
@@ -820,7 +806,7 @@ static int __init cmd640x_init(void)
        /*
         * Initialize data for secondary cmd640 port, if enabled
         */
-       if (second_port_cmd640) {
+       if (second_port_cmd640 && cmd_hwif1) {
                ide_init_port_hw(cmd_hwif1, &hw[1]);
 #ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
                cmd_hwif1->set_pio_mode = &cmd640_set_pio_mode;
@@ -828,7 +814,7 @@ static int __init cmd640x_init(void)
 
                idx[1] = cmd_hwif1->index;
        }
-       printk(KERN_INFO "%s: %sserialized, secondary interface %s\n", cmd_hwif1->name,
+       printk(KERN_INFO "cmd640: %sserialized, secondary interface %s\n",
                         second_port_cmd640 ? "" : "not ", port2);
 
        /*
@@ -836,18 +822,30 @@ static int __init cmd640x_init(void)
         * Do not unnecessarily disturb any prior BIOS setup of these.
         */
        for (index = 0; index < (2 + (second_port_cmd640 << 1)); index++) {
-               ide_drive_t *drive = cmd_drives[index];
+               ide_drive_t *drive;
+
+               if (index > 1) {
+                       if (cmd_hwif1 == NULL)
+                               continue;
+                       drive = &cmd_hwif1->drives[index & 1];
+               } else  {
+                       if (cmd_hwif0 == NULL)
+                               continue;
+                       drive = &cmd_hwif0->drives[index & 1];
+               }
+
 #ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
                if (drive->autotune || ((index > 1) && second_port_toggled)) {
-                       /*
-                        * Reset timing to the slowest speed and turn off prefetch.
-                        * This way, the drive identify code has a better chance.
+                       /*
+                        * Reset timing to the slowest speed and turn off
+                        * prefetch.  This way, the drive identify code has
+                        * a better chance.
                         */
                        setup_counts    [index] = 4;    /* max possible */
                        active_counts   [index] = 16;   /* max possible */
                        recovery_counts [index] = 16;   /* max possible */
-                       program_drive_counts (index);
-                       set_prefetch_mode (index, 0);
+                       program_drive_counts(drive, index);
+                       set_prefetch_mode(drive, index, 0);
                        printk("cmd640: drive%d timings/prefetch cleared\n", index);
                } else {
                        /*
@@ -855,7 +853,7 @@ static int __init cmd640x_init(void)
                         * This preserves any prior BIOS setup.
                         */
                        retrieve_drive_counts (index);
-                       check_prefetch (index);
+                       check_prefetch(drive, index);
                        printk("cmd640: drive%d timings/prefetch(%s) preserved",
                                index, drive->no_io_32bit ? "off" : "on");
                        display_clocks(index);
@@ -864,7 +862,7 @@ static int __init cmd640x_init(void)
                /*
                 * Set the drive unmask flags to match the prefetch setting
                 */
-               check_prefetch (index);
+               check_prefetch(drive, index);
                printk("cmd640: drive%d timings/prefetch(%s) preserved\n",
                        index, drive->no_io_32bit ? "off" : "on");
 #endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
index edabe62..8baccfe 100644 (file)
@@ -440,8 +440,7 @@ static const struct ide_port_info cmd64x_chipsets[] __devinitdata = {
                .init_hwif      = init_hwif_cmd64x,
                .enablebits     = {{0x00,0x00,0x00}, {0x51,0x08,0x08}},
                .host_flags     = IDE_HFLAG_CLEAR_SIMPLEX |
-                                 IDE_HFLAG_ABUSE_PREFETCH |
-                                 IDE_HFLAG_BOOTABLE,
+                                 IDE_HFLAG_ABUSE_PREFETCH,
                .pio_mask       = ATA_PIO5,
                .mwdma_mask     = ATA_MWDMA2,
                .udma_mask      = 0x00, /* no udma */
@@ -451,7 +450,7 @@ static const struct ide_port_info cmd64x_chipsets[] __devinitdata = {
                .init_hwif      = init_hwif_cmd64x,
                .enablebits     = {{0x51,0x04,0x04}, {0x51,0x08,0x08}},
                .chipset        = ide_cmd646,
-               .host_flags     = IDE_HFLAG_ABUSE_PREFETCH | IDE_HFLAG_BOOTABLE,
+               .host_flags     = IDE_HFLAG_ABUSE_PREFETCH,
                .pio_mask       = ATA_PIO5,
                .mwdma_mask     = ATA_MWDMA2,
                .udma_mask      = ATA_UDMA2,
@@ -460,7 +459,7 @@ static const struct ide_port_info cmd64x_chipsets[] __devinitdata = {
                .init_chipset   = init_chipset_cmd64x,
                .init_hwif      = init_hwif_cmd64x,
                .enablebits     = {{0x51,0x04,0x04}, {0x51,0x08,0x08}},
-               .host_flags     = IDE_HFLAG_ABUSE_PREFETCH | IDE_HFLAG_BOOTABLE,
+               .host_flags     = IDE_HFLAG_ABUSE_PREFETCH,
                .pio_mask       = ATA_PIO5,
                .mwdma_mask     = ATA_MWDMA2,
                .udma_mask      = ATA_UDMA4,
@@ -469,7 +468,7 @@ static const struct ide_port_info cmd64x_chipsets[] __devinitdata = {
                .init_chipset   = init_chipset_cmd64x,
                .init_hwif      = init_hwif_cmd64x,
                .enablebits     = {{0x51,0x04,0x04}, {0x51,0x08,0x08}},
-               .host_flags     = IDE_HFLAG_ABUSE_PREFETCH | IDE_HFLAG_BOOTABLE,
+               .host_flags     = IDE_HFLAG_ABUSE_PREFETCH,
                .pio_mask       = ATA_PIO5,
                .mwdma_mask     = ATA_MWDMA2,
                .udma_mask      = ATA_UDMA5,
index 1c163e4..01b37ec 100644 (file)
@@ -122,8 +122,7 @@ static void __devinit init_hwif_cs5520(ide_hwif_t *hwif)
                                  IDE_HFLAG_CS5520 |            \
                                  IDE_HFLAG_VDMA |              \
                                  IDE_HFLAG_NO_ATAPI_DMA |      \
-                                 IDE_HFLAG_ABUSE_SET_DMA_MODE |\
-                                 IDE_HFLAG_BOOTABLE,           \
+                                 IDE_HFLAG_ABUSE_SET_DMA_MODE, \
                .pio_mask       = ATA_PIO4,                     \
        }
 
index 941a134..56a369c 100644 (file)
@@ -249,8 +249,7 @@ static const struct ide_port_info cs5530_chipset __devinitdata = {
        .init_chipset   = init_chipset_cs5530,
        .init_hwif      = init_hwif_cs5530,
        .host_flags     = IDE_HFLAG_SERIALIZE |
-                         IDE_HFLAG_POST_SET_MODE |
-                         IDE_HFLAG_BOOTABLE,
+                         IDE_HFLAG_POST_SET_MODE,
        .pio_mask       = ATA_PIO4,
        .mwdma_mask     = ATA_MWDMA2,
        .udma_mask      = ATA_UDMA2,
index d7b5ea9..c9685f2 100644 (file)
@@ -186,7 +186,7 @@ static const struct ide_port_info cs5535_chipset __devinitdata = {
        .name           = "CS5535",
        .init_hwif      = init_hwif_cs5535,
        .host_flags     = IDE_HFLAG_SINGLE | IDE_HFLAG_POST_SET_MODE |
-                         IDE_HFLAG_ABUSE_SET_DMA_MODE | IDE_HFLAG_BOOTABLE,
+                         IDE_HFLAG_ABUSE_SET_DMA_MODE,
        .pio_mask       = ATA_PIO4,
        .mwdma_mask     = ATA_MWDMA2,
        .udma_mask      = ATA_UDMA4,
index 724cbac..08eab7e 100644 (file)
@@ -6,7 +6,7 @@
  *
  * The CY82C693 chipset is used on Digital's PC-Alpha 164SX boards.
  * Writing the driver was quite simple, since most of the job is
- * done by the generic pci-ide support. 
+ * done by the generic pci-ide support.
  * The hard part was finding the CY82C693's datasheet on Cypress's
  * web page :-(. But Altavista solved this problem :-).
  *
  * - I recently got a 16.8G IBM DTTA, so I was able to test it with
  *   a large and fast disk - the results look great, so I'd say the
  *   driver is working fine :-)
- *   hdparm -t reports 8.17 MB/sec at about 6% CPU usage for the DTTA 
- * - this is my first linux driver, so there's probably a lot  of room 
+ *   hdparm -t reports 8.17 MB/sec at about 6% CPU usage for the DTTA
+ * - this is my first linux driver, so there's probably a lot  of room
  *   for optimizations and bug fixing, so feel free to do it.
  * - use idebus=xx parameter to set PCI bus speed - needed to calc
  *   timings for PIO modes (default will be 40)
- * - if using PIO mode it's a good idea to set the PIO mode and 
+ * - if using PIO mode it's a good idea to set the PIO mode and
  *   32-bit I/O support (if possible), e.g. hdparm -p2 -c1 /dev/hda
  * - I had some problems with my IBM DHEA with PIO modes < 2
  *   (lost interrupts) ?????
@@ -110,11 +110,11 @@ typedef struct pio_clocks_s {
  * calc clocks using bus_speed
  * returns (rounded up) time in bus clocks for time in ns
  */
-static int calc_clk (int time, int bus_speed)
+static int calc_clk(int time, int bus_speed)
 {
        int clocks;
 
-       clocks = (time*bus_speed+999)/1000 -1;
+       clocks = (time*bus_speed+999)/1000 - 1;
 
        if (clocks < 0)
                clocks = 0;
@@ -132,8 +132,8 @@ static int calc_clk (int time, int bus_speed)
  * NOTE: for mode 0,1 and 2 drives 8-bit IDE command control registers are used
  *       for mode 3 and 4 drives 8 and 16-bit timings are the same
  *
- */ 
-static void compute_clocks (u8 pio, pio_clocks_t *p_pclk)
+ */
+static void compute_clocks(u8 pio, pio_clocks_t *p_pclk)
 {
        int clk1, clk2;
        int bus_speed = system_bus_clock();     /* get speed of PCI bus */
@@ -158,7 +158,7 @@ static void compute_clocks (u8 pio, pio_clocks_t *p_pclk)
        clk1 = (clk1<<4)|clk2;  /* combine active and recovery clocks */
 
        /* note: we use the same values for 16bit IOR and IOW
-         *     those are all the same, since I don't have other
+             those are all the same, since I don't have other
         *      timings than those from ide-lib.c
         */
 
@@ -186,7 +186,7 @@ static void cy82c693_set_dma_mode(ide_drive_t *drive, const u8 mode)
        outb(index, CY82_INDEX_PORT);
        data = inb(CY82_DATA_PORT);
 
-       printk (KERN_INFO "%s (ch=%d, dev=%d): DMA mode is %d (single=%d)\n",
+       printk(KERN_INFO "%s (ch=%d, dev=%d): DMA mode is %d (single=%d)\n",
                drive->name, HWIF(drive)->channel, drive->select.b.unit,
                (data&0x3), ((data>>2)&1));
 #endif /* CY82C693_DEBUG_LOGS */
@@ -202,7 +202,7 @@ static void cy82c693_set_dma_mode(ide_drive_t *drive, const u8 mode)
                mode & 3, single);
 #endif /* CY82C693_DEBUG_INFO */
 
-       /* 
+       /*
         * note: below we set the value for Bus Master IDE TimeOut Register
         * I'm not absolutly sure what this does, but it solved my problem
         * with IDE DMA and sound, so I now can play sound and work with
@@ -216,8 +216,8 @@ static void cy82c693_set_dma_mode(ide_drive_t *drive, const u8 mode)
        outb(CY82_INDEX_TIMEOUT, CY82_INDEX_PORT);
        outb(data, CY82_DATA_PORT);
 
-#if CY82C693_DEBUG_INFO        
-       printk (KERN_INFO "%s: Set IDE Bus Master TimeOut Register to 0x%X\n",
+#if CY82C693_DEBUG_INFO
+       printk(KERN_INFO "%s: Set IDE Bus Master TimeOut Register to 0x%X\n",
                drive->name, data);
 #endif /* CY82C693_DEBUG_INFO */
 }
@@ -242,14 +242,14 @@ static void cy82c693_set_pio_mode(ide_drive_t *drive, const u8 pio)
 
 #if CY82C693_DEBUG_LOGS
        /* for debug let's show the register values */
-       
-               if (drive->select.b.unit == 0) {
+
+       if (drive->select.b.unit == 0) {
                /*
-                * get master drive registers                   
+                * get master drive registers
                 * address setup control register
                 * is 32 bit !!!
-                */ 
-               pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl);                
+                */
+               pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl);
                addrCtrl &= 0x0F;
 
                /* now let's get the remaining registers */
@@ -261,7 +261,7 @@ static void cy82c693_set_pio_mode(ide_drive_t *drive, const u8 pio)
                 * set slave drive registers
                 * address setup control register
                 * is 32 bit !!!
-                */ 
+                */
                pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl);
 
                addrCtrl &= 0xF0;
@@ -288,9 +288,9 @@ static void cy82c693_set_pio_mode(ide_drive_t *drive, const u8 pio)
                 * set master drive
                 * address setup control register
                 * is 32 bit !!!
-                */ 
+                */
                pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl);
-               
+
                addrCtrl &= (~0xF);
                addrCtrl |= (unsigned int)pclk.address_time;
                pci_write_config_dword(dev, CY82_IDE_ADDRSETUP, addrCtrl);
@@ -299,14 +299,14 @@ static void cy82c693_set_pio_mode(ide_drive_t *drive, const u8 pio)
                pci_write_config_byte(dev, CY82_IDE_MASTER_IOR, pclk.time_16r);
                pci_write_config_byte(dev, CY82_IDE_MASTER_IOW, pclk.time_16w);
                pci_write_config_byte(dev, CY82_IDE_MASTER_8BIT, pclk.time_8);
-               
+
                addrCtrl &= 0xF;
        } else {
                /*
                 * set slave drive
                 * address setup control register
                 * is 32 bit !!!
-                */ 
+                */
                pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl);
 
                addrCtrl &= (~0xF0);
@@ -320,7 +320,7 @@ static void cy82c693_set_pio_mode(ide_drive_t *drive, const u8 pio)
 
                addrCtrl >>= 4;
                addrCtrl &= 0xF;
-       }       
+       }
 
 #if CY82C693_DEBUG_INFO
        printk(KERN_INFO "%s (ch=%d, dev=%d): set PIO timing to "
@@ -340,41 +340,41 @@ static unsigned int __devinit init_chipset_cy82c693(struct pci_dev *dev, const c
 
 #ifdef CY82C693_SETDMA_CLOCK
        u8 data = 0;
-#endif /* CY82C693_SETDMA_CLOCK */ 
+#endif /* CY82C693_SETDMA_CLOCK */
 
        /* write info about this verion of the driver */
        printk(KERN_INFO CY82_VERSION "\n");
 
 #ifdef CY82C693_SETDMA_CLOCK
        /* okay let's set the DMA clock speed */
-        
-        outb(CY82_INDEX_CTRLREG1, CY82_INDEX_PORT);
-        data = inb(CY82_DATA_PORT);
+
+       outb(CY82_INDEX_CTRLREG1, CY82_INDEX_PORT);
+       data = inb(CY82_DATA_PORT);
 
 #if CY82C693_DEBUG_INFO
        printk(KERN_INFO "%s: Peripheral Configuration Register: 0x%X\n",
                name, data);
 #endif /* CY82C693_DEBUG_INFO */
 
-        /*
+       /*
         * for some reason sometimes the DMA controller
         * speed is set to ATCLK/2 ???? - we fix this here
-        * 
+        *
         * note: i don't know what causes this strange behaviour,
         *       but even changing the dma speed doesn't solve it :-(
-        *       the ide performance is still only half the normal speed 
-        * 
+        *       the ide performance is still only half the normal speed
+        *
         *       if anybody knows what goes wrong with my machine, please
         *       let me know - ASK
-         */
+        */
 
        data |= 0x03;
 
-        outb(CY82_INDEX_CTRLREG1, CY82_INDEX_PORT);
-        outb(data, CY82_DATA_PORT);
+       outb(CY82_INDEX_CTRLREG1, CY82_INDEX_PORT);
+       outb(data, CY82_DATA_PORT);
 
 #if CY82C693_DEBUG_INFO
-       printk (KERN_INFO "%s: New Peripheral Configuration Register: 0x%X\n",
+       printk(KERN_INFO "%s: New Peripheral Configuration Register: 0x%X\n",
                name, data);
 #endif /* CY82C693_DEBUG_INFO */
 
@@ -410,8 +410,7 @@ static const struct ide_port_info cy82c693_chipset __devinitdata = {
        .init_iops      = init_iops_cy82c693,
        .init_hwif      = init_hwif_cy82c693,
        .chipset        = ide_cy82c693,
-       .host_flags     = IDE_HFLAG_SINGLE | IDE_HFLAG_CY82C693 |
-                         IDE_HFLAG_BOOTABLE,
+       .host_flags     = IDE_HFLAG_SINGLE,
        .pio_mask       = ATA_PIO4,
        .swdma_mask     = ATA_SWDMA2,
        .mwdma_mask     = ATA_MWDMA2,
@@ -424,7 +423,7 @@ static int __devinit cy82c693_init_one(struct pci_dev *dev, const struct pci_dev
 
        /* CY82C693 is more than only a IDE controller.
           Function 1 is primary IDE channel, function 2 - secondary. */
-        if ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE &&
+       if ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE &&
            PCI_FUNC(dev->devfn) == 1) {
                dev2 = pci_get_slot(dev->bus, dev->devfn + 1);
                ret = ide_setup_pci_devices(dev, dev2, &cy82c693_chipset);
index 961698d..753b86f 100644 (file)
@@ -71,14 +71,13 @@ delkin_cb_probe (struct pci_dev *dev, const struct pci_device_id *id)
                if (setup[i])
                        outb(setup[i], base + i);
        }
-       pci_release_regions(dev);       /* IDE layer handles regions itself */
 
        memset(&hw, 0, sizeof(hw));
        ide_std_init_ports(&hw, base + 0x10, base + 0x1e);
        hw.irq = dev->irq;
        hw.chipset = ide_pci;           /* this enables IRQ sharing */
 
-       hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
+       hwif = ide_find_port();
        if (hwif == NULL)
                goto out_disable;
 
@@ -90,6 +89,7 @@ delkin_cb_probe (struct pci_dev *dev, const struct pci_device_id *id)
                ide_init_port_data(hwif, i);
 
        ide_init_port_hw(hwif, &hw);
+       hwif->mmio = 1;
        hwif->quirkproc = &ide_undecoded_slave;
 
        idx[0] = i;
@@ -110,6 +110,7 @@ delkin_cb_probe (struct pci_dev *dev, const struct pci_device_id *id)
 
 out_disable:
        printk(KERN_ERR "delkin_cb: no IDE devices found\n");
+       pci_release_regions(dev);
        pci_disable_device(dev);
        return -ENODEV;
 }
@@ -122,6 +123,7 @@ delkin_cb_remove (struct pci_dev *dev)
        if (hwif)
                ide_unregister(hwif->index);
 
+       pci_release_regions(dev);
        pci_disable_device(dev);
 }
 
index 7fd83a9..041720e 100644 (file)
@@ -38,8 +38,7 @@ MODULE_PARM_DESC(all_generic_ide, "IDE generic will claim all unknown PCI IDE st
        { \
                .name           = name_str, \
                .host_flags     = IDE_HFLAG_TRUST_BIOS_FOR_DMA | \
-                                 extra_flags | \
-                                 IDE_HFLAG_BOOTABLE, \
+                                 extra_flags, \
                .swdma_mask     = ATA_SWDMA2, \
                .mwdma_mask     = ATA_MWDMA2, \
                .udma_mask      = ATA_UDMA6, \
@@ -50,9 +49,8 @@ static const struct ide_port_info generic_chipsets[] __devinitdata = {
 
        {       /* 1 */
                .name           = "NS87410",
-               .enablebits     = {{0x43,0x08,0x08}, {0x47,0x08,0x08}},
-               .host_flags     = IDE_HFLAG_TRUST_BIOS_FOR_DMA |
-                                 IDE_HFLAG_BOOTABLE,
+               .enablebits     = { {0x43, 0x08, 0x08}, {0x47, 0x08, 0x08} },
+               .host_flags     = IDE_HFLAG_TRUST_BIOS_FOR_DMA,
                .swdma_mask     = ATA_SWDMA2,
                .mwdma_mask     = ATA_MWDMA2,
                .udma_mask      = ATA_UDMA6,
@@ -99,7 +97,7 @@ static const struct ide_port_info generic_chipsets[] __devinitdata = {
  *     Called when the PCI registration layer (or the IDE initialization)
  *     finds a device matching our IDE device tables.
  */
+
 static int __devinit generic_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
        const struct ide_port_info *d = &generic_chipsets[id->driver_data];
index 9f01da4..9f2fc30 100644 (file)
@@ -133,7 +133,7 @@ static const struct ide_port_info hpt34x_chipsets[] __devinitdata = {
                .init_chipset   = init_chipset_hpt34x,
                .init_hwif      = init_hwif_hpt34x,
                .extra          = 16,
-               .host_flags     = IDE_HFLAGS_HPT34X,
+               .host_flags     = IDE_HFLAGS_HPT34X | IDE_HFLAG_NON_BOOTABLE,
                .pio_mask       = ATA_PIO5,
        },
        { /* 1 */
index 82d0e31..a490906 100644 (file)
@@ -1557,7 +1557,7 @@ static int __devinit hpt366_init_one(struct pci_dev *dev, const struct pci_devic
                        hpt374_init(dev, dev2);
                else {
                        if (hpt36x_init(dev, dev2))
-                               d.host_flags |= IDE_HFLAG_BOOTABLE;
+                               d.host_flags &= ~IDE_HFLAG_NON_BOOTABLE;
                }
 
                ret = ide_setup_pci_devices(dev, dev2, &d);
index e3427ea..5b5b0cc 100644 (file)
@@ -35,7 +35,7 @@ static void it8213_set_pio_mode(ide_drive_t *drive, const u8 pio)
        static DEFINE_SPINLOCK(tune_lock);
        int control = 0;
 
-       static const u8 timings[][2]= {
+       static const u8 timings[][2] = {
                                        { 0, 0 },
                                        { 0, 0 },
                                        { 1, 0 },
@@ -105,11 +105,10 @@ static void it8213_set_dma_mode(ide_drive_t *drive, const u8 speed)
 
                if (!(reg48 & u_flag))
                        pci_write_config_byte(dev, 0x48, reg48 | u_flag);
-               if (speed >= XFER_UDMA_5) {
+               if (speed >= XFER_UDMA_5)
                        pci_write_config_byte(dev, 0x55, (u8) reg55|w_flag);
-               } else {
+               else
                        pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag);
-               }
 
                if ((reg4a & a_speed) != u_speed)
                        pci_write_config_word(dev, 0x4a, (reg4a & ~a_speed) | u_speed);
@@ -170,9 +169,8 @@ static void __devinit init_hwif_it8213(ide_hwif_t *hwif)
        {                                               \
                .name           = name_str,             \
                .init_hwif      = init_hwif_it8213,     \
-               .enablebits     = {{0x41,0x80,0x80}}, \
-               .host_flags     = IDE_HFLAG_SINGLE |    \
-                                 IDE_HFLAG_BOOTABLE,   \
+               .enablebits     = { {0x41, 0x80, 0x80} }, \
+               .host_flags     = IDE_HFLAG_SINGLE,     \
                .pio_mask       = ATA_PIO4,             \
                .swdma_mask     = ATA_SWDMA2_ONLY,      \
                .mwdma_mask     = ATA_MWDMA12_ONLY,     \
index d8a1674..a38ec47 100644 (file)
@@ -523,16 +523,12 @@ static void __devinit it821x_quirkproc(ide_drive_t *drive)
 static void __devinit init_hwif_it821x(ide_hwif_t *hwif)
 {
        struct pci_dev *dev = to_pci_dev(hwif->dev);
-       struct it821x_dev *idev = kzalloc(sizeof(struct it821x_dev), GFP_KERNEL);
+       struct it821x_dev **itdevs = (struct it821x_dev **)pci_get_drvdata(dev);
+       struct it821x_dev *idev = itdevs[hwif->channel];
        u8 conf;
 
        hwif->quirkproc = &it821x_quirkproc;
 
-       if (idev == NULL) {
-               printk(KERN_ERR "it821x: out of memory, falling back to legacy behaviour.\n");
-               return;
-       }
-
        ide_set_hwifdata(hwif, idev);
 
        pci_read_config_byte(dev, 0x50, &conf);
@@ -623,7 +619,6 @@ static unsigned int __devinit init_chipset_it821x(struct pci_dev *dev, const cha
                .name           = name_str,             \
                .init_chipset   = init_chipset_it821x,  \
                .init_hwif      = init_hwif_it821x,     \
-               .host_flags     = IDE_HFLAG_BOOTABLE,   \
                .pio_mask       = ATA_PIO4,             \
        }
 
@@ -642,6 +637,22 @@ static const struct ide_port_info it821x_chipsets[] __devinitdata = {
 
 static int __devinit it821x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
+       struct it821x_dev *itdevs[2] = { NULL, NULL} , *itdev;
+       unsigned int i;
+
+       for (i = 0; i < 2; i++) {
+               itdev = kzalloc(sizeof(*itdev), GFP_KERNEL);
+               if (itdev == NULL) {
+                       kfree(itdevs[0]);
+                       printk(KERN_ERR "it821x: out of memory\n");
+                       return -ENOMEM;
+               }
+
+               itdevs[i] = itdev;
+       }
+
+       pci_set_drvdata(dev, itdevs);
+
        return ide_setup_pci_device(dev, &it821x_chipsets[id->driver_data]);
 }
 
index a56bcb4..673f7dc 100644 (file)
@@ -63,8 +63,7 @@ static u8 __devinit ata66_jmicron(ide_hwif_t *hwif)
         *      actually do our cable checking etc. Thankfully we don't need
         *      to do the plumbing for other cases.
         */
-       switch (port_map[port])
-       {
+       switch (port_map[port]) {
        case PORT_PATA0:
                if (control & (1 << 3)) /* 40/80 pin primary */
                        return ATA_CBL_PATA40;
@@ -114,7 +113,6 @@ static void __devinit init_hwif_jmicron(ide_hwif_t *hwif)
 static const struct ide_port_info jmicron_chipset __devinitdata = {
        .name           = "JMB",
        .init_hwif      = init_hwif_jmicron,
-       .host_flags     = IDE_HFLAG_BOOTABLE,
        .enablebits     = { { 0x40, 0x01, 0x01 }, { 0x40, 0x10, 0x10 } },
        .pio_mask       = ATA_PIO5,
        .mwdma_mask     = ATA_MWDMA2,
index 7551332..3015d69 100644 (file)
@@ -265,8 +265,7 @@ static const struct ide_port_info ns87415_chipset __devinitdata = {
 #endif
        .init_hwif      = init_hwif_ns87415,
        .host_flags     = IDE_HFLAG_TRUST_BIOS_FOR_DMA |
-                         IDE_HFLAG_NO_ATAPI_DMA |
-                         IDE_HFLAG_BOOTABLE,
+                         IDE_HFLAG_NO_ATAPI_DMA,
 };
 
 static int __devinit ns87415_init_one(struct pci_dev *dev, const struct pci_device_id *id)
index 46e8748..88a4dd9 100644 (file)
@@ -57,9 +57,9 @@
  * (use idebus=xx to select PCI bus speed).
  *
  * Version 0.1, Nov 8, 1996
- * by Jaromir Koutek, for 2.1.8. 
+ * by Jaromir Koutek, for 2.1.8.
  * Initial version of driver.
- * 
+ *
  * Version 0.2
  * Number 0.2 skipped.
  *
@@ -75,7 +75,7 @@
  * by Jaromir Koutek
  * Updates for use with (again) new IDE block driver.
  * Update of documentation.
- * 
+ *
  * Version 0.6, Jan 2, 1999
  * by Jaromir Koutek
  * Reversed to version 0.3 of the driver, because
@@ -208,29 +208,34 @@ typedef struct pio_clocks_s {
 
 static void compute_clocks(int pio, pio_clocks_t *clks)
 {
-        if (pio != PIO_NOT_EXIST) {
-               int adr_setup, data_pls;
+       if (pio != PIO_NOT_EXIST) {
+               int adr_setup, data_pls;
                int bus_speed = system_bus_clock();
 
-               adr_setup = ide_pio_timings[pio].setup_time;
-               data_pls = ide_pio_timings[pio].active_time;
-               clks->address_time = cmpt_clk(adr_setup, bus_speed);
-               clks->data_time = cmpt_clk(data_pls, bus_speed);
-               clks->recovery_time = cmpt_clk(ide_pio_timings[pio].cycle_time
-                       - adr_setup-data_pls, bus_speed);
-               if (clks->address_time<1) clks->address_time = 1;
-               if (clks->address_time>4) clks->address_time = 4;
-               if (clks->data_time<1) clks->data_time = 1;
-               if (clks->data_time>16) clks->data_time = 16;
-               if (clks->recovery_time<2) clks->recovery_time = 2;
-               if (clks->recovery_time>17) clks->recovery_time = 17;
+               adr_setup = ide_pio_timings[pio].setup_time;
+               data_pls = ide_pio_timings[pio].active_time;
+               clks->address_time = cmpt_clk(adr_setup, bus_speed);
+               clks->data_time = cmpt_clk(data_pls, bus_speed);
+               clks->recovery_time = cmpt_clk(ide_pio_timings[pio].cycle_time
+                       - adr_setup-data_pls, bus_speed);
+               if (clks->address_time < 1)
+                       clks->address_time = 1;
+               if (clks->address_time > 4)
+                       clks->address_time = 4;
+               if (clks->data_time < 1)
+                       clks->data_time = 1;
+               if (clks->data_time > 16)
+                       clks->data_time = 16;
+               if (clks->recovery_time < 2)
+                       clks->recovery_time = 2;
+               if (clks->recovery_time > 17)
+                       clks->recovery_time = 17;
        } else {
                clks->address_time = 1;
                clks->data_time = 1;
                clks->recovery_time = 2;
                /* minimal values */
        }
 }
 
 static void opti621_set_pio_mode(ide_drive_t *drive, const u8 pio)
@@ -247,8 +252,8 @@ static void opti621_set_pio_mode(ide_drive_t *drive, const u8 pio)
 
        /* sets drive->drive_data for both drives */
        compute_pios(drive, pio);
-       pio1 = hwif->drives[0].drive_data;
-       pio2 = hwif->drives[1].drive_data;
+       pio1 = hwif->drives[0].drive_data;
+       pio2 = hwif->drives[1].drive_data;
 
        compute_clocks(pio1, &first);
        compute_clocks(pio2, &second);
@@ -275,7 +280,7 @@ static void opti621_set_pio_mode(ide_drive_t *drive, const u8 pio)
 
        spin_lock_irqsave(&opti621_lock, flags);
 
-       reg_base = hwif->io_ports[IDE_DATA_OFFSET];
+       reg_base = hwif->io_ports[IDE_DATA_OFFSET];
 
        /* allow Register-B */
        outb(0xc0, reg_base + CNTRL_REG);
@@ -324,7 +329,7 @@ static void __devinit opti621_port_init_devs(ide_hwif_t *hwif)
 /*
  * init_hwif_opti621() is called once for each hwif found at boot.
  */
-static void __devinit init_hwif_opti621 (ide_hwif_t *hwif)
+static void __devinit init_hwif_opti621(ide_hwif_t *hwif)
 {
        hwif->port_init_devs = opti621_port_init_devs;
        hwif->set_pio_mode = &opti621_set_pio_mode;
@@ -334,18 +339,16 @@ static const struct ide_port_info opti621_chipsets[] __devinitdata = {
        {       /* 0 */
                .name           = "OPTI621",
                .init_hwif      = init_hwif_opti621,
-               .enablebits     = {{0x45,0x80,0x00}, {0x40,0x08,0x00}},
-               .host_flags     = IDE_HFLAG_TRUST_BIOS_FOR_DMA |
-                                 IDE_HFLAG_BOOTABLE,
+               .enablebits     = { {0x45, 0x80, 0x00}, {0x40, 0x08, 0x00} },
+               .host_flags     = IDE_HFLAG_TRUST_BIOS_FOR_DMA,
                .pio_mask       = ATA_PIO3,
                .swdma_mask     = ATA_SWDMA2,
                .mwdma_mask     = ATA_MWDMA2,
-       },    /* 1 */
+       }, {    /* 1 */
                .name           = "OPTI621X",
                .init_hwif      = init_hwif_opti621,
-               .enablebits     = {{0x45,0x80,0x00}, {0x40,0x08,0x00}},
-               .host_flags     = IDE_HFLAG_TRUST_BIOS_FOR_DMA |
-                                 IDE_HFLAG_BOOTABLE,
+               .enablebits     = { {0x45, 0x80, 0x00}, {0x40, 0x08, 0x00} },
+               .host_flags     = IDE_HFLAG_TRUST_BIOS_FOR_DMA,
                .pio_mask       = ATA_PIO3,
                .swdma_mask     = ATA_SWDMA2,
                .mwdma_mask     = ATA_MWDMA2,
index decef0f..89d74ff 100644 (file)
@@ -307,9 +307,9 @@ static void __devinit init_hwif_ich(ide_hwif_t *hwif)
 }
 
 #ifndef CONFIG_IA64
- #define IDE_HFLAGS_PIIX (IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_BOOTABLE)
+ #define IDE_HFLAGS_PIIX IDE_HFLAG_LEGACY_IRQS
 #else
- #define IDE_HFLAGS_PIIX IDE_HFLAG_BOOTABLE
+ #define IDE_HFLAGS_PIIX 0
 #endif
 
 #define DECLARE_PIIX_DEV(name_str, udma) \
index 5167661..532154a 100644 (file)
@@ -43,7 +43,7 @@ static const struct ide_port_info rz1000_chipset __devinitdata = {
        .name           = "RZ100x",
        .init_hwif      = init_hwif_rz1000,
        .chipset        = ide_rz1000,
-       .host_flags     = IDE_HFLAG_NO_DMA | IDE_HFLAG_BOOTABLE,
+       .host_flags     = IDE_HFLAG_NO_DMA,
 };
 
 static int __devinit rz1000_init_one(struct pci_dev *dev, const struct pci_device_id *id)
index 561aa47..44985c8 100644 (file)
@@ -307,8 +307,7 @@ static const struct ide_port_info sc1200_chipset __devinitdata = {
        .init_hwif      = init_hwif_sc1200,
        .host_flags     = IDE_HFLAG_SERIALIZE |
                          IDE_HFLAG_POST_SET_MODE |
-                         IDE_HFLAG_ABUSE_DMA_MODES |
-                         IDE_HFLAG_BOOTABLE,
+                         IDE_HFLAG_ABUSE_DMA_MODES,
        .pio_mask       = ATA_PIO4,
        .mwdma_mask     = ATA_MWDMA2,
        .udma_mask      = ATA_UDMA2,
index ef07c7a..5214579 100644 (file)
@@ -65,7 +65,7 @@
 
 static struct scc_ports {
        unsigned long ctl, dma;
-       unsigned char hwif_id;  /* for removing hwif from system */
+       ide_hwif_t *hwif;  /* for removing port from system */
 } scc_ports[MAX_HWIFS];
 
 /* PIO transfer mode  table */
@@ -534,12 +534,8 @@ static int scc_ide_setup_pci_device(struct pci_dev *dev,
        u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
        int i;
 
-       for (i = 0; i < MAX_HWIFS; i++) {
-               hwif = &ide_hwifs[i];
-               if (hwif->chipset == ide_unknown)
-                       break; /* pick an unused entry */
-       }
-       if (i == MAX_HWIFS) {
+       hwif = ide_find_port();
+       if (hwif == NULL) {
                printk(KERN_ERR "%s: too many IDE interfaces, "
                                "no room in table\n", SCC_PATA_NAME);
                return -ENOMEM;
@@ -696,7 +692,7 @@ static void __devinit init_hwif_scc(ide_hwif_t *hwif)
 {
        struct scc_ports *ports = ide_get_hwifdata(hwif);
 
-       ports->hwif_id = hwif->index;
+       ports->hwif = hwif;
 
        hwif->dma_command = hwif->dma_base;
        hwif->dma_status = hwif->dma_base + 0x04;
@@ -725,8 +721,7 @@ static void __devinit init_hwif_scc(ide_hwif_t *hwif)
       .name            = name_str,                     \
       .init_iops       = init_iops_scc,                \
       .init_hwif       = init_hwif_scc,                \
-      .host_flags      = IDE_HFLAG_SINGLE |            \
-                         IDE_HFLAG_BOOTABLE,           \
+      .host_flags      = IDE_HFLAG_SINGLE,             \
       .pio_mask                = ATA_PIO4,                     \
   }
 
@@ -758,7 +753,7 @@ static int __devinit scc_init_one(struct pci_dev *dev, const struct pci_device_i
 static void __devexit scc_remove(struct pci_dev *dev)
 {
        struct scc_ports *ports = pci_get_drvdata(dev);
-       ide_hwif_t *hwif = &ide_hwifs[ports->hwif_id];
+       ide_hwif_t *hwif = ports->hwif;
        unsigned long ctl_base = pci_resource_start(dev, 0);
        unsigned long dma_base = pci_resource_start(dev, 1);
        unsigned long ctl_size = pci_resource_len(dev, 0);
index c11880b..cfe9274 100644 (file)
@@ -350,8 +350,7 @@ static void __devinit init_hwif_svwks (ide_hwif_t *hwif)
 
 #define IDE_HFLAGS_SVWKS \
        (IDE_HFLAG_LEGACY_IRQS | \
-        IDE_HFLAG_ABUSE_SET_DMA_MODE | \
-        IDE_HFLAG_BOOTABLE)
+        IDE_HFLAG_ABUSE_SET_DMA_MODE)
 
 static const struct ide_port_info serverworks_chipsets[] __devinitdata = {
        {       /* 0 */
@@ -418,7 +417,7 @@ static int __devinit svwks_init_one(struct pci_dev *dev, const struct pci_device
        else if (idx == 2 || idx == 3) {
                if ((PCI_FUNC(dev->devfn) & 1) == 0) {
                        if (pci_resource_start(dev, 0) != 0x01f1)
-                               d.host_flags &= ~IDE_HFLAG_BOOTABLE;
+                               d.host_flags |= IDE_HFLAG_NON_BOOTABLE;
                        d.host_flags |= IDE_HFLAG_SINGLE;
                } else
                        d.host_flags &= ~IDE_HFLAG_SINGLE;
index 9d1a303..6bd9523 100644 (file)
@@ -590,20 +590,12 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev)
        unsigned long bar0, cmd_phys_base, ctl;
        void __iomem *virt_base;
        ide_hwif_t *hwif;
-       int h;
        u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
        hw_regs_t hw;
        struct ide_port_info d = sgiioc4_port_info;
 
-       /*
-        * Find an empty HWIF; if none available, return -ENOMEM.
-        */
-       for (h = 0; h < MAX_HWIFS; ++h) {
-               hwif = &ide_hwifs[h];
-               if (hwif->chipset == ide_unknown)
-                       break;
-       }
-       if (h == MAX_HWIFS) {
+       hwif = ide_find_port();
+       if (hwif == NULL) {
                printk(KERN_ERR "%s: too many IDE interfaces, no room in table\n",
                                DRV_NAME);
                return -ENOMEM;
index b6be1b4..c9ecab8 100644 (file)
@@ -808,7 +808,6 @@ static void __devinit init_hwif_siimage(ide_hwif_t *hwif)
                .init_chipset   = init_chipset_siimage, \
                .init_iops      = init_iops_siimage,    \
                .init_hwif      = init_hwif_siimage,    \
-               .host_flags     = IDE_HFLAG_BOOTABLE,   \
                .pio_mask       = ATA_PIO4,             \
                .mwdma_mask     = ATA_MWDMA2,           \
                .udma_mask      = ATA_UDMA6,            \
index 512bb4c..181b647 100644 (file)
 #define ATA_16         0x01
 #define ATA_33         0x02
 #define ATA_66         0x03
-#define ATA_100a       0x04 // SiS730/SiS550 is ATA100 with ATA66 layout
+#define ATA_100a       0x04 /* SiS730/SiS550 is ATA100 with ATA66 layout */
 #define ATA_100                0x05
-#define ATA_133a       0x06 // SiS961b with 133 support
-#define ATA_133                0x07 // SiS962/963
+#define ATA_133a       0x06 /* SiS961b with 133 support */
+#define ATA_133                0x07 /* SiS962/963 */
 
 static u8 chipset_family;
 
@@ -111,69 +111,70 @@ static const struct {
    Indexed by chipset_family and (dma_mode - XFER_UDMA_0) */
 
 /* {0, ATA_16, ATA_33, ATA_66, ATA_100a, ATA_100, ATA_133} */
-static u8 cycle_time_offset[] = {0,0,5,4,4,0,0};
-static u8 cycle_time_range[] = {0,0,2,3,3,4,4};
+static u8 cycle_time_offset[] = { 0, 0, 5, 4, 4, 0, 0 };
+static u8 cycle_time_range[]  = { 0, 0, 2, 3, 3, 4, 4 };
 static u8 cycle_time_value[][XFER_UDMA_6 - XFER_UDMA_0 + 1] = {
-       {0,0,0,0,0,0,0}, /* no udma */
-       {0,0,0,0,0,0,0}, /* no udma */
-       {3,2,1,0,0,0,0}, /* ATA_33 */
-       {7,5,3,2,1,0,0}, /* ATA_66 */
-       {7,5,3,2,1,0,0}, /* ATA_100a (730 specific), differences are on cycle_time range and offset */
-       {11,7,5,4,2,1,0}, /* ATA_100 */
-       {15,10,7,5,3,2,1}, /* ATA_133a (earliest 691 southbridges) */
-       {15,10,7,5,3,2,1}, /* ATA_133 */
+       {  0,  0, 0, 0, 0, 0, 0 }, /* no UDMA */
+       {  0,  0, 0, 0, 0, 0, 0 }, /* no UDMA */
+       {  3,  2, 1, 0, 0, 0, 0 }, /* ATA_33 */
+       {  7,  5, 3, 2, 1, 0, 0 }, /* ATA_66 */
+       {  7,  5, 3, 2, 1, 0, 0 }, /* ATA_100a (730 specific),
+                                     different cycle_time range and offset */
+       { 11,  7, 5, 4, 2, 1, 0 }, /* ATA_100 */
+       { 15, 10, 7, 5, 3, 2, 1 }, /* ATA_133a (earliest 691 southbridges) */
+       { 15, 10, 7, 5, 3, 2, 1 }, /* ATA_133 */
 };
 /* CRC Valid Setup Time vary across IDE clock setting 33/66/100/133
    See SiS962 data sheet for more detail */
 static u8 cvs_time_value[][XFER_UDMA_6 - XFER_UDMA_0 + 1] = {
-       {0,0,0,0,0,0,0}, /* no udma */
-       {0,0,0,0,0,0,0}, /* no udma */
-       {2,1,1,0,0,0,0},
-       {4,3,2,1,0,0,0},
-       {4,3,2,1,0,0,0},
-       {6,4,3,1,1,1,0},
-       {9,6,4,2,2,2,2},
-       {9,6,4,2,2,2,2},
+       { 0, 0, 0, 0, 0, 0, 0 }, /* no UDMA */
+       { 0, 0, 0, 0, 0, 0, 0 }, /* no UDMA */
+       { 2, 1, 1, 0, 0, 0, 0 },
+       { 4, 3, 2, 1, 0, 0, 0 },
+       { 4, 3, 2, 1, 0, 0, 0 },
+       { 6, 4, 3, 1, 1, 1, 0 },
+       { 9, 6, 4, 2, 2, 2, 2 },
+       { 9, 6, 4, 2, 2, 2, 2 },
 };
 /* Initialize time, Active time, Recovery time vary across
    IDE clock settings. These 3 arrays hold the register value
    for PIO0/1/2/3/4 and DMA0/1/2 mode in order */
 static u8 ini_time_value[][8] = {
-       {0,0,0,0,0,0,0,0},
-       {0,0,0,0,0,0,0,0},
-       {2,1,0,0,0,1,0,0},
-       {4,3,1,1,1,3,1,1},
-       {4,3,1,1,1,3,1,1},
-       {6,4,2,2,2,4,2,2},
-       {9,6,3,3,3,6,3,3},
-       {9,6,3,3,3,6,3,3},
+       { 0, 0, 0, 0, 0, 0, 0, 0 },
+       { 0, 0, 0, 0, 0, 0, 0, 0 },
+       { 2, 1, 0, 0, 0, 1, 0, 0 },
+       { 4, 3, 1, 1, 1, 3, 1, 1 },
+       { 4, 3, 1, 1, 1, 3, 1, 1 },
+       { 6, 4, 2, 2, 2, 4, 2, 2 },
+       { 9, 6, 3, 3, 3, 6, 3, 3 },
+       { 9, 6, 3, 3, 3, 6, 3, 3 },
 };
 static u8 act_time_value[][8] = {
-       {0,0,0,0,0,0,0,0},
-       {0,0,0,0,0,0,0,0},
-       {9,9,9,2,2,7,2,2},
-       {19,19,19,5,4,14,5,4},
-       {19,19,19,5,4,14,5,4},
-       {28,28,28,7,6,21,7,6},
-       {38,38,38,10,9,28,10,9},
-       {38,38,38,10,9,28,10,9},
+       {  0,  0,  0,  0, 0,  0,  0, 0 },
+       {  0,  0,  0,  0, 0,  0,  0, 0 },
+       {  9,  9,  9,  2, 2,  7,  2, 2 },
+       { 19, 19, 19,  5, 4, 14,  5, 4 },
+       { 19, 19, 19,  5, 4, 14,  5, 4 },
+       { 28, 28, 28,  7, 6, 21,  7, 6 },
+       { 38, 38, 38, 10, 9, 28, 10, 9 },
+       { 38, 38, 38, 10, 9, 28, 10, 9 },
 };
 static u8 rco_time_value[][8] = {
-       {0,0,0,0,0,0,0,0},
-       {0,0,0,0,0,0,0,0},
-       {9,2,0,2,0,7,1,1},
-       {19,5,1,5,2,16,3,2},
-       {19,5,1,5,2,16,3,2},
-       {30,9,3,9,4,25,6,4},
-       {40,12,4,12,5,34,12,5},
-       {40,12,4,12,5,34,12,5},
+       {  0,  0, 0,  0, 0,  0,  0, 0 },
+       {  0,  0, 0,  0, 0,  0,  0, 0 },
+       {  9,  2, 0,  2, 0,  7,  1, 1 },
+       { 19,  5, 1,  5, 2, 16,  3, 2 },
+       { 19,  5, 1,  5, 2, 16,  3, 2 },
+       { 30,  9, 3,  9, 4, 25,  6, 4 },
+       { 40, 12, 4, 12, 5, 34, 12, 5 },
+       { 40, 12, 4, 12, 5, 34, 12, 5 },
 };
 
 /*
  * Printing configuration
  */
 /* Used for chipset type printing at boot time */
-static charchipset_capability[] = {
+static char *chipset_capability[] = {
        "ATA", "ATA 16",
        "ATA 33", "ATA 66",
        "ATA 100 (1st gen)", "ATA 100 (2nd gen)",
@@ -272,7 +273,7 @@ static void sis_program_timings(ide_drive_t *drive, const u8 mode)
                sis_ata133_program_timings(drive, mode);
 }
 
-static void config_drive_art_rwp (ide_drive_t *drive)
+static void config_drive_art_rwp(ide_drive_t *drive)
 {
        ide_hwif_t *hwif        = HWIF(drive);
        struct pci_dev *dev     = to_pci_dev(hwif->dev);
@@ -358,8 +359,7 @@ static u8 sis5513_ata133_udma_filter(ide_drive_t *drive)
        return (regdw & 0x08) ? ATA_UDMA6 : ATA_UDMA5;
 }
 
-/* Chip detection and general config */
-static unsigned int __devinit init_chipset_sis5513 (struct pci_dev *dev, const char *name)
+static int __devinit sis_find_family(struct pci_dev *dev)
 {
        struct pci_dev *host;
        int i = 0;
@@ -381,7 +381,7 @@ static unsigned int __devinit init_chipset_sis5513 (struct pci_dev *dev, const c
                                chipset_family = ATA_100a;
                }
                pci_dev_put(host);
-       
+
                printk(KERN_INFO "SIS5513: %s %s controller\n",
                         SiSHostChipInfo[i].name, chipset_capability[chipset_family]);
        }
@@ -440,63 +440,60 @@ static unsigned int __devinit init_chipset_sis5513 (struct pci_dev *dev, const c
                        }
        }
 
-       if (!chipset_family)
-               return -1;
+       return chipset_family;
+}
 
+static unsigned int __devinit init_chipset_sis5513(struct pci_dev *dev,
+                                                  const char *name)
+{
        /* Make general config ops here
           1/ tell IDE channels to operate in Compatibility mode only
           2/ tell old chips to allow per drive IDE timings */
 
-       {
-               u8 reg;
-               u16 regw;
-
-               switch(chipset_family) {
-                       case ATA_133:
-                               /* SiS962 operation mode */
-                               pci_read_config_word(dev, 0x50, &regw);
-                               if (regw & 0x08)
-                                       pci_write_config_word(dev, 0x50, regw&0xfff7);
-                               pci_read_config_word(dev, 0x52, &regw);
-                               if (regw & 0x08)
-                                       pci_write_config_word(dev, 0x52, regw&0xfff7);
-                               break;
-                       case ATA_133a:
-                       case ATA_100:
-                               /* Fixup latency */
-                               pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x80);
-                               /* Set compatibility bit */
-                               pci_read_config_byte(dev, 0x49, &reg);
-                               if (!(reg & 0x01)) {
-                                       pci_write_config_byte(dev, 0x49, reg|0x01);
-                               }
-                               break;
-                       case ATA_100a:
-                       case ATA_66:
-                               /* Fixup latency */
-                               pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x10);
-
-                               /* On ATA_66 chips the bit was elsewhere */
-                               pci_read_config_byte(dev, 0x52, &reg);
-                               if (!(reg & 0x04)) {
-                                       pci_write_config_byte(dev, 0x52, reg|0x04);
-                               }
-                               break;
-                       case ATA_33:
-                               /* On ATA_33 we didn't have a single bit to set */
-                               pci_read_config_byte(dev, 0x09, &reg);
-                               if ((reg & 0x0f) != 0x00) {
-                                       pci_write_config_byte(dev, 0x09, reg&0xf0);
-                               }
-                       case ATA_16:
-                               /* force per drive recovery and active timings
-                                  needed on ATA_33 and below chips */
-                               pci_read_config_byte(dev, 0x52, &reg);
-                               if (!(reg & 0x08)) {
-                                       pci_write_config_byte(dev, 0x52, reg|0x08);
-                               }
-                               break;
-               }
+       u8 reg;
+       u16 regw;
+
+       switch (chipset_family) {
+       case ATA_133:
+               /* SiS962 operation mode */
+               pci_read_config_word(dev, 0x50, &regw);
+               if (regw & 0x08)
+                       pci_write_config_word(dev, 0x50, regw&0xfff7);
+               pci_read_config_word(dev, 0x52, &regw);
+               if (regw & 0x08)
+                       pci_write_config_word(dev, 0x52, regw&0xfff7);
+               break;
+       case ATA_133a:
+       case ATA_100:
+               /* Fixup latency */
+               pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x80);
+               /* Set compatibility bit */
+               pci_read_config_byte(dev, 0x49, &reg);
+               if (!(reg & 0x01))
+                       pci_write_config_byte(dev, 0x49, reg|0x01);
+               break;
+       case ATA_100a:
+       case ATA_66:
+               /* Fixup latency */
+               pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x10);
+
+               /* On ATA_66 chips the bit was elsewhere */
+               pci_read_config_byte(dev, 0x52, &reg);
+               if (!(reg & 0x04))
+                       pci_write_config_byte(dev, 0x52, reg|0x04);
+               break;
+       case ATA_33:
+               /* On ATA_33 we didn't have a single bit to set */
+               pci_read_config_byte(dev, 0x09, &reg);
+               if ((reg & 0x0f) != 0x00)
+                       pci_write_config_byte(dev, 0x09, reg&0xf0);
+       case ATA_16:
+               /* force per drive recovery and active timings
+                  needed on ATA_33 and below chips */
+               pci_read_config_byte(dev, 0x52, &reg);
+               if (!(reg & 0x08))
+                       pci_write_config_byte(dev, 0x52, reg|0x08);
+               break;
        }
 
        return 0;
@@ -546,10 +543,8 @@ static u8 __devinit ata66_sis5513(ide_hwif_t *hwif)
        return ata66 ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
 }
 
-static void __devinit init_hwif_sis5513 (ide_hwif_t *hwif)
+static void __devinit init_hwif_sis5513(ide_hwif_t *hwif)
 {
-       u8 udma_rates[] = { 0x00, 0x00, 0x07, 0x1f, 0x3f, 0x3f, 0x7f, 0x7f };
-
        hwif->set_pio_mode = &sis_set_pio_mode;
        hwif->set_dma_mode = &sis_set_dma_mode;
 
@@ -557,27 +552,29 @@ static void __devinit init_hwif_sis5513 (ide_hwif_t *hwif)
                hwif->udma_filter = sis5513_ata133_udma_filter;
 
        hwif->cable_detect = ata66_sis5513;
-
-       if (hwif->dma_base == 0)
-               return;
-
-       hwif->ultra_mask = udma_rates[chipset_family];
 }
 
 static const struct ide_port_info sis5513_chipset __devinitdata = {
        .name           = "SIS5513",
        .init_chipset   = init_chipset_sis5513,
        .init_hwif      = init_hwif_sis5513,
-       .enablebits     = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
-       .host_flags     = IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_NO_AUTODMA |
-                         IDE_HFLAG_BOOTABLE,
+       .enablebits     = { {0x4a, 0x02, 0x02}, {0x4a, 0x04, 0x04} },
+       .host_flags     = IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_NO_AUTODMA,
        .pio_mask       = ATA_PIO4,
        .mwdma_mask     = ATA_MWDMA2,
 };
 
 static int __devinit sis5513_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
-       return ide_setup_pci_device(dev, &sis5513_chipset);
+       struct ide_port_info d = sis5513_chipset;
+       u8 udma_rates[] = { 0x00, 0x00, 0x07, 0x1f, 0x3f, 0x3f, 0x7f, 0x7f };
+
+       if (sis_find_family(dev) == 0)
+               return -ENOTSUPP;
+
+       d.udma_mask = udma_rates[chipset_family];
+
+       return ide_setup_pci_device(dev, &d);
 }
 
 static const struct pci_device_id sis5513_pci_tbl[] = {
index 1f00251..40b3eeb 100644 (file)
@@ -332,8 +332,7 @@ static const struct ide_port_info sl82c105_chipset __devinitdata = {
 #if defined(CONFIG_LOPEC) || defined(CONFIG_SANDPOINT)
                          IDE_HFLAG_FORCE_LEGACY_IRQS |
 #endif
-                         IDE_HFLAG_NO_AUTODMA |
-                         IDE_HFLAG_BOOTABLE,
+                         IDE_HFLAG_NO_AUTODMA,
        .pio_mask       = ATA_PIO5,
 };
 
index 65f4c2f..eab557c 100644 (file)
@@ -27,9 +27,9 @@ static void slc90e66_set_pio_mode(ide_drive_t *drive, const u8 pio)
        unsigned long flags;
        u16 master_data;
        u8 slave_data;
-       int control = 0;
+       int control = 0;
                                     /* ISP  RTC */
-       static const u8 timings[][2]= {
+       static const u8 timings[][2] = {
                                        { 0, 0 },
                                        { 0, 0 },
                                        { 1, 0 },
@@ -136,8 +136,8 @@ static void __devinit init_hwif_slc90e66(ide_hwif_t *hwif)
 static const struct ide_port_info slc90e66_chipset __devinitdata = {
        .name           = "SLC90E66",
        .init_hwif      = init_hwif_slc90e66,
-       .enablebits     = {{0x41,0x80,0x80}, {0x43,0x80,0x80}},
-       .host_flags     = IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_BOOTABLE,
+       .enablebits     = { {0x41, 0x80, 0x80}, {0x43, 0x80, 0x80} },
+       .host_flags     = IDE_HFLAG_LEGACY_IRQS,
        .pio_mask       = ATA_PIO4,
        .swdma_mask     = ATA_SWDMA2_ONLY,
        .mwdma_mask     = ATA_MWDMA12_ONLY,
index 1e4a626..c154351 100644 (file)
@@ -18,20 +18,20 @@ static void tc86c001_set_mode(ide_drive_t *drive, const u8 speed)
        u16 mode, scr           = inw(scr_port);
 
        switch (speed) {
-               case XFER_UDMA_4:       mode = 0x00c0; break;
-               case XFER_UDMA_3:       mode = 0x00b0; break;
-               case XFER_UDMA_2:       mode = 0x00a0; break;
-               case XFER_UDMA_1:       mode = 0x0090; break;
-               case XFER_UDMA_0:       mode = 0x0080; break;
-               case XFER_MW_DMA_2:     mode = 0x0070; break;
-               case XFER_MW_DMA_1:     mode = 0x0060; break;
-               case XFER_MW_DMA_0:     mode = 0x0050; break;
-               case XFER_PIO_4:        mode = 0x0400; break;
-               case XFER_PIO_3:        mode = 0x0300; break;
-               case XFER_PIO_2:        mode = 0x0200; break;
-               case XFER_PIO_1:        mode = 0x0100; break;
-               case XFER_PIO_0:
-               default:                mode = 0x0000; break;
+       case XFER_UDMA_4:       mode = 0x00c0; break;
+       case XFER_UDMA_3:       mode = 0x00b0; break;
+       case XFER_UDMA_2:       mode = 0x00a0; break;
+       case XFER_UDMA_1:       mode = 0x0090; break;
+       case XFER_UDMA_0:       mode = 0x0080; break;
+       case XFER_MW_DMA_2:     mode = 0x0070; break;
+       case XFER_MW_DMA_1:     mode = 0x0060; break;
+       case XFER_MW_DMA_0:     mode = 0x0050; break;
+       case XFER_PIO_4:        mode = 0x0400; break;
+       case XFER_PIO_3:        mode = 0x0300; break;
+       case XFER_PIO_2:        mode = 0x0200; break;
+       case XFER_PIO_1:        mode = 0x0100; break;
+       case XFER_PIO_0:
+       default:                mode = 0x0000; break;
        }
 
        scr &= (speed < XFER_MW_DMA_0) ? 0xf8ff : 0xff0f;
index a67d02a..3316b19 100644 (file)
@@ -97,7 +97,6 @@ static const struct ide_port_info triflex_device __devinitdata = {
        .name           = "TRIFLEX",
        .init_hwif      = init_hwif_triflex,
        .enablebits     = {{0x80, 0x01, 0x01}, {0x80, 0x02, 0x02}},
-       .host_flags     = IDE_HFLAG_BOOTABLE,
        .pio_mask       = ATA_PIO4,
        .swdma_mask     = ATA_SWDMA2,
        .mwdma_mask     = ATA_MWDMA2,
index de750f7..2b8f3a2 100644 (file)
@@ -337,7 +337,6 @@ static const struct ide_port_info trm290_chipset __devinitdata = {
                          IDE_HFLAG_TRUST_BIOS_FOR_DMA |
 #endif
                          IDE_HFLAG_NO_AUTODMA |
-                         IDE_HFLAG_BOOTABLE |
                          IDE_HFLAG_NO_LBA48,
 };
 
index 9004e75..cff3caf 100644 (file)
@@ -429,11 +429,9 @@ static const struct ide_port_info via82cxxx_chipset __devinitdata = {
        .init_hwif      = init_hwif_via82cxxx,
        .enablebits     = { { 0x40, 0x02, 0x02 }, { 0x40, 0x01, 0x01 } },
        .host_flags     = IDE_HFLAG_PIO_NO_BLACKLIST |
-                         IDE_HFLAG_PIO_NO_DOWNGRADE |
                          IDE_HFLAG_ABUSE_SET_DMA_MODE |
                          IDE_HFLAG_POST_SET_MODE |
-                         IDE_HFLAG_IO_32BIT |
-                         IDE_HFLAG_BOOTABLE,
+                         IDE_HFLAG_IO_32BIT,
        .pio_mask       = ATA_PIO5,
        .swdma_mask     = ATA_SWDMA2,
        .mwdma_mask     = ATA_MWDMA2,
index a784a97..467656f 100644 (file)
@@ -36,6 +36,8 @@
 #include <asm/machdep.h>
 #include <asm/irq.h>
 
+#define DRV_NAME "ide-mpc8xx"
+
 static int identify  (volatile u8 *p);
 static void print_fixed (volatile u8 *p);
 static void print_funcid (int func);
@@ -127,7 +129,7 @@ static int pcmcia_schlvl = PCMCIA_SCHLVL;
  * MPC8xx's internal PCMCIA interface
  */
 #if defined(CONFIG_IDE_8xx_PCCARD) || defined(CONFIG_IDE_8xx_DIRECT)
-static void __init m8xx_ide_init_ports(hw_regs_t *hw, unsigned long data_port)
+static int __init m8xx_ide_init_ports(hw_regs_t *hw, unsigned long data_port)
 {
        unsigned long *p = hw->io_ports;
        int i;
@@ -182,6 +184,13 @@ static void __init m8xx_ide_init_ports(hw_regs_t *hw, unsigned long data_port)
                        pcmcia_phy_base, pcmcia_phy_end,
                        pcmcia_phy_end - pcmcia_phy_base);
 
+               if (!request_mem_region(pcmcia_phy_base,
+                                       pcmcia_phy_end - pcmcia_phy_base,
+                                       DRV_NAME)) {
+                       printk(KERN_ERR "%s: resources busy\n", DRV_NAME);
+                       return -EBUSY;
+               }
+
                pcmcia_base=(unsigned long)ioremap(pcmcia_phy_base,
                                                   pcmcia_phy_end-pcmcia_phy_base);
 
@@ -236,7 +245,7 @@ static void __init m8xx_ide_init_ports(hw_regs_t *hw, unsigned long data_port)
        if (pcmp->pcmc_pipr & (M8XX_PCMCIA_CD1(_slot_)|M8XX_PCMCIA_CD2(_slot_))) {
                printk ("No card in slot %c: PIPR=%08x\n",
                        'A' + _slot_, (u32) pcmp->pcmc_pipr);
-               return;         /* No card in slot */
+               return -ENODEV;         /* No card in slot */
        }
 
        check_ide_device (pcmcia_base);
@@ -279,9 +288,6 @@ static void __init m8xx_ide_init_ports(hw_regs_t *hw, unsigned long data_port)
        }
 #endif /* CONFIG_IDE_8xx_PCCARD */
 
-       ide_hwifs[data_port].pio_mask = ATA_PIO4;
-       ide_hwifs[data_port].set_pio_mode = m8xx_ide_set_pio_mode;
-
        /* Enable Harddisk Interrupt,
         * and make it edge sensitive
         */
@@ -296,6 +302,8 @@ static void __init m8xx_ide_init_ports(hw_regs_t *hw, unsigned long data_port)
        /* Enable falling edge irq */
        pcmp->pcmc_per = 0x100000 >> (16 * _slot_);
 #endif /* CONFIG_IDE_8xx_PCCARD */
+
+       return 0;
 }
 #endif /* CONFIG_IDE_8xx_PCCARD || CONFIG_IDE_8xx_DIRECT */
 
@@ -304,7 +312,7 @@ static void __init m8xx_ide_init_ports(hw_regs_t *hw, unsigned long data_port)
  * MPC8xx's internal PCMCIA interface
  */
 #if defined(CONFIG_IDE_EXT_DIRECT)
-static void __init m8xx_ide_init_ports(hw_regs_t *hw, unsigned long data_port)
+static int __init m8xx_ide_init_ports(hw_regs_t *hw, unsigned long data_port)
 {
        unsigned long *p = hw->io_ports;
        int i;
@@ -327,7 +335,12 @@ static void __init m8xx_ide_init_ports(hw_regs_t *hw, unsigned long data_port)
                printk ("IDE phys mem : %08x...%08x (size %08x)\n",
                        ide_phy_base, ide_phy_end,
                        ide_phy_end - ide_phy_base);
-               
+
+               if (!request_mem_region(ide_phy_base, 0x200, DRV_NAME)) {
+                       printk(KERN_ERR "%s: resources busy\n", DRV_NAME);
+                       return -EBUSY;
+               }
+
                ide_base=(unsigned long)ioremap(ide_phy_base,
                                                ide_phy_end-ide_phy_base);
 
@@ -357,15 +370,14 @@ static void __init m8xx_ide_init_ports(hw_regs_t *hw, unsigned long data_port)
        hw->irq = ioport_dsc[data_port].irq;
        hw->ack_intr = (ide_ack_intr_t *)ide_interrupt_ack;
 
-       ide_hwifs[data_port].pio_mask = ATA_PIO4;
-       ide_hwifs[data_port].set_pio_mode = m8xx_ide_set_pio_mode;
-
        /* Enable Harddisk Interrupt,
         * and make it edge sensitive
         */
        /* (11-18) Set edge detect for irq, no wakeup from low power mode */
        ((immap_t *) IMAP_ADDR)->im_siu_conf.sc_siel |=
                        (0x80000000 >> ioport_dsc[data_port].irq);
+
+       return 0;
 }
 #endif /* CONFIG_IDE_8xx_DIRECT */
 
@@ -794,14 +806,28 @@ static int __init mpc8xx_ide_probe(void)
 
 #ifdef IDE0_BASE_OFFSET
        memset(&hw, 0, sizeof(hw));
-       m8xx_ide_init_ports(&hw, 0);
-       ide_init_port_hw(&ide_hwifs[0], &hw);
-       idx[0] = 0;
+       if (!m8xx_ide_init_ports(&hw, 0)) {
+               ide_hwif_t *hwif = &ide_hwifs[0];
+
+               ide_init_port_hw(hwif, &hw);
+               hwif->mmio = 1;
+               hwif->pio_mask = ATA_PIO4;
+               hwif->set_pio_mode = m8xx_ide_set_pio_mode;
+
+               idx[0] = 0;
+       }
 #ifdef IDE1_BASE_OFFSET
        memset(&hw, 0, sizeof(hw));
-       m8xx_ide_init_ports(&hw, 1);
-       ide_init_port_hw(&ide_hwifs[1], &hw);
-       idx[1] = 1;
+       if (!m8xx_ide_init_ports(&hw, 1)) {
+               ide_hwif_t *mate = &ide_hwifs[1];
+
+               ide_init_port_hw(mate, &hw);
+               mate->mmio = 1;
+               mate->pio_mask = ATA_PIO4;
+               mate->set_pio_mode = m8xx_ide_set_pio_mode;
+
+               idx[1] = 1;
+       }
 #endif
 #endif
 
index 88619b5..177961e 100644 (file)
@@ -79,8 +79,6 @@ typedef struct pmac_ide_hwif {
        
 } pmac_ide_hwif_t;
 
-static pmac_ide_hwif_t pmac_ide[MAX_HWIFS];
-
 enum {
        controller_ohare,       /* OHare based */
        controller_heathrow,    /* Heathrow/Paddington */
@@ -923,7 +921,6 @@ pmac_ide_do_resume(ide_hwif_t *hwif)
 static const struct ide_port_info pmac_port_info = {
        .chipset                = ide_pmac,
        .host_flags             = IDE_HFLAG_SET_PIO_MODE_KEEP_DMA |
-                                 IDE_HFLAG_PIO_NO_DOWNGRADE |
                                  IDE_HFLAG_POST_SET_MODE |
                                  IDE_HFLAG_NO_DMA | /* no SFF-style DMA */
                                  IDE_HFLAG_UNMASK_IRQS,
@@ -1088,35 +1085,36 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match)
 {
        void __iomem *base;
        unsigned long regbase;
-       int irq;
        ide_hwif_t *hwif;
        pmac_ide_hwif_t *pmif;
-       int i, rc;
+       int irq, rc;
        hw_regs_t hw;
 
-       i = 0;
-       while (i < MAX_HWIFS && (ide_hwifs[i].io_ports[IDE_DATA_OFFSET] != 0
-           || pmac_ide[i].node != NULL))
-               ++i;
-       if (i >= MAX_HWIFS) {
+       pmif = kzalloc(sizeof(*pmif), GFP_KERNEL);
+       if (pmif == NULL)
+               return -ENOMEM;
+
+       hwif = ide_find_port();
+       if (hwif == NULL) {
                printk(KERN_ERR "ide-pmac: MacIO interface attach with no slot\n");
                printk(KERN_ERR "          %s\n", mdev->ofdev.node->full_name);
-               return -ENODEV;
+               rc = -ENODEV;
+               goto out_free_pmif;
        }
 
-       pmif = &pmac_ide[i];
-       hwif = &ide_hwifs[i];
-
        if (macio_resource_count(mdev) == 0) {
-               printk(KERN_WARNING "ide%d: no address for %s\n",
-                      i, mdev->ofdev.node->full_name);
-               return -ENXIO;
+               printk(KERN_WARNING "ide-pmac: no address for %s\n",
+                                   mdev->ofdev.node->full_name);
+               rc = -ENXIO;
+               goto out_free_pmif;
        }
 
        /* Request memory resource for IO ports */
        if (macio_request_resource(mdev, 0, "ide-pmac (ports)")) {
-               printk(KERN_ERR "ide%d: can't request mmio resource !\n", i);
-               return -EBUSY;
+               printk(KERN_ERR "ide-pmac: can't request MMIO resource for "
+                               "%s!\n", mdev->ofdev.node->full_name);
+               rc = -EBUSY;
+               goto out_free_pmif;
        }
                        
        /* XXX This is bogus. Should be fixed in the registry by checking
@@ -1125,8 +1123,8 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match)
         * where that happens though...
         */
        if (macio_irq_count(mdev) == 0) {
-               printk(KERN_WARNING "ide%d: no intrs for device %s, using 13\n",
-                       i, mdev->ofdev.node->full_name);
+               printk(KERN_WARNING "ide-pmac: no intrs for device %s, using "
+                                   "13\n", mdev->ofdev.node->full_name);
                irq = irq_create_mapping(NULL, 13);
        } else
                irq = macio_irq(mdev, 0);
@@ -1144,7 +1142,9 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match)
 #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
        if (macio_resource_count(mdev) >= 2) {
                if (macio_request_resource(mdev, 1, "ide-pmac (dma)"))
-                       printk(KERN_WARNING "ide%d: can't request DMA resource !\n", i);
+                       printk(KERN_WARNING "ide-pmac: can't request DMA "
+                                           "resource for %s!\n",
+                                           mdev->ofdev.node->full_name);
                else
                        pmif->dma_regs = ioremap(macio_resource_start(mdev, 1), 0x1000);
        } else
@@ -1166,11 +1166,15 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match)
                        iounmap(pmif->dma_regs);
                        macio_release_resource(mdev, 1);
                }
-               memset(pmif, 0, sizeof(*pmif));
                macio_release_resource(mdev, 0);
+               kfree(pmif);
        }
 
        return rc;
+
+out_free_pmif:
+       kfree(pmif);
+       return rc;
 }
 
 static int
@@ -1215,7 +1219,7 @@ pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id)
        pmac_ide_hwif_t *pmif;
        void __iomem *base;
        unsigned long rbase, rlen;
-       int i, rc;
+       int rc;
        hw_regs_t hw;
 
        np = pci_device_to_OF_node(pdev);
@@ -1223,30 +1227,32 @@ pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id)
                printk(KERN_ERR "ide-pmac: cannot find MacIO node for Kauai ATA interface\n");
                return -ENODEV;
        }
-       i = 0;
-       while (i < MAX_HWIFS && (ide_hwifs[i].io_ports[IDE_DATA_OFFSET] != 0
-           || pmac_ide[i].node != NULL))
-               ++i;
-       if (i >= MAX_HWIFS) {
+
+       pmif = kzalloc(sizeof(*pmif), GFP_KERNEL);
+       if (pmif == NULL)
+               return -ENOMEM;
+
+       hwif = ide_find_port();
+       if (hwif == NULL) {
                printk(KERN_ERR "ide-pmac: PCI interface attach with no slot\n");
                printk(KERN_ERR "          %s\n", np->full_name);
-               return -ENODEV;
+               rc = -ENODEV;
+               goto out_free_pmif;
        }
 
-       pmif = &pmac_ide[i];
-       hwif = &ide_hwifs[i];
-
        if (pci_enable_device(pdev)) {
-               printk(KERN_WARNING "ide%i: Can't enable PCI device for %s\n",
-                       i, np->full_name);
-               return -ENXIO;
+               printk(KERN_WARNING "ide-pmac: Can't enable PCI device for "
+                                   "%s\n", np->full_name);
+               rc = -ENXIO;
+               goto out_free_pmif;
        }
        pci_set_master(pdev);
                        
        if (pci_request_regions(pdev, "Kauai ATA")) {
-               printk(KERN_ERR "ide%d: Cannot obtain PCI resources for %s\n",
-                       i, np->full_name);
-               return -ENXIO;
+               printk(KERN_ERR "ide-pmac: Cannot obtain PCI resources for "
+                               "%s\n", np->full_name);
+               rc = -ENXIO;
+               goto out_free_pmif;
        }
 
        hwif->dev = &pdev->dev;
@@ -1276,11 +1282,15 @@ pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id)
                /* The inteface is released to the common IDE layer */
                pci_set_drvdata(pdev, NULL);
                iounmap(base);
-               memset(pmif, 0, sizeof(*pmif));
                pci_release_regions(pdev);
+               kfree(pmif);
        }
 
        return rc;
+
+out_free_pmif:
+       kfree(pmif);
+       return rc;
 }
 
 static int
index f7ede0e..6302010 100644 (file)
 #include <asm/io.h>
 #include <asm/irq.h>
 
-
-/**
- *     ide_match_hwif  -       match a PCI IDE against an ide_hwif
- *     @io_base: I/O base of device
- *     @bootable: set if its bootable
- *     @name: name of device
- *
- *     Match a PCI IDE port against an entry in ide_hwifs[],
- *     based on io_base port if possible. Return the matching hwif,
- *     or a new hwif. If we find an error (clashing, out of devices, etc)
- *     return NULL
- *
- *     FIXME: we need to handle mmio matches here too
- */
-
-static ide_hwif_t *ide_match_hwif(unsigned long io_base, u8 bootable, const char *name)
-{
-       int h;
-       ide_hwif_t *hwif;
-
-       /*
-        * Look for a hwif with matching io_base default value.
-        * If chipset is "ide_unknown", then claim that hwif slot.
-        * Otherwise, some other chipset has already claimed it..  :(
-        */
-       for (h = 0; h < MAX_HWIFS; ++h) {
-               hwif = &ide_hwifs[h];
-               if (hwif->io_ports[IDE_DATA_OFFSET] == io_base) {
-                       if (hwif->chipset == ide_unknown)
-                               return hwif; /* match */
-                       printk(KERN_ERR "%s: port 0x%04lx already claimed by %s\n",
-                               name, io_base, hwif->name);
-                       return NULL;    /* already claimed */
-               }
-       }
-       /*
-        * Okay, there is no hwif matching our io_base,
-        * so we'll just claim an unassigned slot.
-        * Give preference to claiming other slots before claiming ide0/ide1,
-        * just in case there's another interface yet-to-be-scanned
-        * which uses ports 1f0/170 (the ide0/ide1 defaults).
-        *
-        * Unless there is a bootable card that does not use the standard
-        * ports 1f0/170 (the ide0/ide1 defaults). The (bootable) flag.
-        */
-       if (bootable) {
-               for (h = 0; h < MAX_HWIFS; ++h) {
-                       hwif = &ide_hwifs[h];
-                       if (hwif->chipset == ide_unknown)
-                               return hwif;    /* pick an unused entry */
-               }
-       } else {
-               for (h = 2; h < MAX_HWIFS; ++h) {
-                       hwif = ide_hwifs + h;
-                       if (hwif->chipset == ide_unknown)
-                               return hwif;    /* pick an unused entry */
-               }
-       }
-       for (h = 0; h < 2 && h < MAX_HWIFS; ++h) {
-               hwif = ide_hwifs + h;
-               if (hwif->chipset == ide_unknown)
-                       return hwif;    /* pick an unused entry */
-       }
-       printk(KERN_ERR "%s: too many IDE interfaces, no room in table\n", name);
-       return NULL;
-}
-
 /**
  *     ide_setup_pci_baseregs  -       place a PCI IDE controller native
  *     @dev: PCI device of interface to switch native
@@ -94,13 +27,13 @@ static ide_hwif_t *ide_match_hwif(unsigned long io_base, u8 bootable, const char
  *
  *     We attempt to place the PCI interface into PCI native mode. If
  *     we succeed the BARs are ok and the controller is in PCI mode.
- *     Returns 0 on success or an errno code. 
+ *     Returns 0 on success or an errno code.
  *
  *     FIXME: if we program the interface and then fail to set the BARS
  *     we don't switch it back to legacy mode. Do we actually care ??
  */
-static int ide_setup_pci_baseregs (struct pci_dev *dev, const char *name)
+
+static int ide_setup_pci_baseregs(struct pci_dev *dev, const char *name)
 {
        u8 progif = 0;
 
@@ -207,7 +140,6 @@ void ide_setup_pci_noise(struct pci_dev *dev, const struct ide_port_info *d)
                         " PCI slot %s\n", d->name, dev->vendor, dev->device,
                         dev->revision, pci_name(dev));
 }
-
 EXPORT_SYMBOL_GPL(ide_setup_pci_noise);
 
 
@@ -220,7 +152,7 @@ EXPORT_SYMBOL_GPL(ide_setup_pci_noise);
  *     but if that fails then we only need IO space. The PCI code should
  *     have setup the proper resources for us already for controllers in
  *     legacy mode.
- *     
+ *
  *     Returns zero on success or an error code
  */
 
@@ -279,8 +211,8 @@ static int ide_pci_configure(struct pci_dev *dev, const struct ide_port_info *d)
         * Maybe the user deliberately *disabled* the device,
         * but we'll eventually ignore it again if no drives respond.
         */
-       if (ide_setup_pci_baseregs(dev, d->name) || pci_write_config_word(dev, PCI_COMMAND, pcicmd|PCI_COMMAND_IO)) 
-       {
+       if (ide_setup_pci_baseregs(dev, d->name) ||
+           pci_write_config_word(dev, PCI_COMMAND, pcicmd | PCI_COMMAND_IO)) {
                printk(KERN_INFO "%s: device disabled (BIOS)\n", d->name);
                return -ENODEV;
        }
@@ -301,26 +233,24 @@ static int ide_pci_configure(struct pci_dev *dev, const struct ide_port_info *d)
  *     @d: IDE port info
  *     @bar: BAR number
  *
- *     Checks if a BAR is configured and points to MMIO space. If so
- *     print an error and return an error code. Otherwise return 0
+ *     Checks if a BAR is configured and points to MMIO space. If so,
+ *     return an error code. Otherwise return 0
  */
 
-static int ide_pci_check_iomem(struct pci_dev *dev, const struct ide_port_info *d, int bar)
+static int ide_pci_check_iomem(struct pci_dev *dev, const struct ide_port_info *d,
+                              int bar)
 {
        ulong flags = pci_resource_flags(dev, bar);
-       
+
        /* Unconfigured ? */
        if (!flags || pci_resource_len(dev, bar) == 0)
                return 0;
 
-       /* I/O space */         
-       if(flags & PCI_BASE_ADDRESS_IO_MASK)
+       /* I/O space */
+       if (flags & IORESOURCE_IO)
                return 0;
-               
+
        /* Bad */
-       printk(KERN_ERR "%s: IO baseregs (BIOS) are reported "
-                       "as MEM, report to "
-                       "<andre@linux-ide.org>.\n", d->name);
        return -EINVAL;
 }
 
@@ -344,14 +274,16 @@ static ide_hwif_t *ide_hwif_configure(struct pci_dev *dev,
 {
        unsigned long ctl = 0, base = 0;
        ide_hwif_t *hwif;
-       u8 bootable = (d->host_flags & IDE_HFLAG_BOOTABLE) ? 1 : 0;
        struct hw_regs_s hw;
 
        if ((d->host_flags & IDE_HFLAG_ISA_PORTS) == 0) {
-               /*  Possibly we should fail if these checks report true */
-               ide_pci_check_iomem(dev, d, 2*port);
-               ide_pci_check_iomem(dev, d, 2*port+1);
+               if (ide_pci_check_iomem(dev, d, 2 * port) ||
+                   ide_pci_check_iomem(dev, d, 2 * port + 1)) {
+                       printk(KERN_ERR "%s: I/O baseregs (BIOS) are reported "
+                                       "as MEM for port %d!\n", d->name, port);
+                       return NULL;
+               }
+
                ctl  = pci_resource_start(dev, 2*port+1);
                base = pci_resource_start(dev, 2*port);
                if ((ctl && !base) || (base && !ctl)) {
@@ -360,14 +292,18 @@ static ide_hwif_t *ide_hwif_configure(struct pci_dev *dev,
                        return NULL;
                }
        }
-       if (!ctl)
-       {
+       if (!ctl) {
                /* Use default values */
                ctl = port ? 0x374 : 0x3f4;
                base = port ? 0x170 : 0x1f0;
        }
-       if ((hwif = ide_match_hwif(base, bootable, d->name)) == NULL)
-               return NULL;    /* no room in ide_hwifs[] */
+
+       hwif = ide_find_port_slot(d);
+       if (hwif == NULL) {
+               printk(KERN_ERR "%s: too many IDE interfaces, no room in "
+                               "table\n", d->name);
+               return NULL;
+       }
 
        memset(&hw, 0, sizeof(hw));
        hw.irq = irq;
@@ -407,9 +343,9 @@ void ide_hwif_setup_dma(ide_hwif_t *hwif, const struct ide_port_info *d)
                unsigned long dma_base = ide_get_or_set_dma_base(d, hwif);
                if (dma_base && !(pcicmd & PCI_COMMAND_MASTER)) {
                        /*
-                        * Set up BM-DMA capability
+                        * Set up BM-DMA capability
                         * (PnP BIOS should have done this)
-                        */
+                        */
                        pci_set_master(dev);
                        if (pci_read_config_word(dev, PCI_COMMAND, &pcicmd) || !(pcicmd & PCI_COMMAND_MASTER)) {
                                printk(KERN_ERR "%s: %s error updating PCICMD\n",
@@ -514,7 +450,6 @@ void ide_pci_setup_ports(struct pci_dev *dev, const struct ide_port_info *d, int
                *(idx + port) = hwif->index;
        }
 }
-
 EXPORT_SYMBOL_GPL(ide_pci_setup_ports);
 
 /*
@@ -597,7 +532,6 @@ int ide_setup_pci_device(struct pci_dev *dev, const struct ide_port_info *d)
 
        return ret;
 }
-
 EXPORT_SYMBOL_GPL(ide_setup_pci_device);
 
 int ide_setup_pci_devices(struct pci_dev *dev1, struct pci_dev *dev2,
@@ -621,5 +555,4 @@ int ide_setup_pci_devices(struct pci_dev *dev1, struct pci_dev *dev2,
 out:
        return ret;
 }
-
 EXPORT_SYMBOL_GPL(ide_setup_pci_devices);
index 68fab61..f5fceb3 100644 (file)
@@ -307,6 +307,14 @@ config DVB_AU8522
          An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
          to support this frontend.
 
+config DVB_S5H1411
+       tristate "Samsung S5H1411 based"
+       depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
+       help
+         An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
+         to support this frontend.
+
 comment "Tuners/PLL support"
        depends on DVB_CORE
 
index 2f873fc..9747c73 100644 (file)
@@ -55,3 +55,4 @@ obj-$(CONFIG_DVB_TUNER_XC5000) += xc5000.o
 obj-$(CONFIG_DVB_TUNER_ITD1000) += itd1000.o
 obj-$(CONFIG_DVB_AU8522) += au8522.o
 obj-$(CONFIG_DVB_TDA10048) += tda10048.o
+obj-$(CONFIG_DVB_S5H1411) += s5h1411.o
index 96338f0..de796ea 100644 (file)
@@ -33,7 +33,7 @@ struct mt312_config {
        u8 demod_address;
 
        /* inverted voltage setting */
-       int voltage_inverted:1;
+       unsigned int voltage_inverted:1;
 };
 
 #if defined(CONFIG_DVB_MT312) || (defined(CONFIG_DVB_MT312_MODULE) && defined(MODULE))
diff --git a/drivers/media/dvb/frontends/s5h1411.c b/drivers/media/dvb/frontends/s5h1411.c
new file mode 100644 (file)
index 0000000..eb5bfc9
--- /dev/null
@@ -0,0 +1,888 @@
+/*
+    Samsung S5H1411 VSB/QAM demodulator driver
+
+    Copyright (C) 2008 Steven Toth <stoth@hauppauge.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 program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    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/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include "dvb_frontend.h"
+#include "dvb-pll.h"
+#include "s5h1411.h"
+
+struct s5h1411_state {
+
+       struct i2c_adapter *i2c;
+
+       /* configuration settings */
+       const struct s5h1411_config *config;
+
+       struct dvb_frontend frontend;
+
+       fe_modulation_t current_modulation;
+
+       u32 current_frequency;
+       int if_freq;
+
+       u8 inversion;
+};
+
+static int debug;
+
+#define dprintk(arg...) do {   \
+       if (debug)              \
+               printk(arg);    \
+       } while (0)
+
+/* Register values to initialise the demod, defaults to VSB */
+static struct init_tab {
+       u8      addr;
+       u8      reg;
+       u16     data;
+} init_tab[] = {
+       { S5H1411_I2C_TOP_ADDR, 0x00, 0x0071, },
+       { S5H1411_I2C_TOP_ADDR, 0x08, 0x0047, },
+       { S5H1411_I2C_TOP_ADDR, 0x1c, 0x0400, },
+       { S5H1411_I2C_TOP_ADDR, 0x1e, 0x0370, },
+       { S5H1411_I2C_TOP_ADDR, 0x1f, 0x342a, },
+       { S5H1411_I2C_TOP_ADDR, 0x24, 0x0231, },
+       { S5H1411_I2C_TOP_ADDR, 0x25, 0x1011, },
+       { S5H1411_I2C_TOP_ADDR, 0x26, 0x0f07, },
+       { S5H1411_I2C_TOP_ADDR, 0x27, 0x0f04, },
+       { S5H1411_I2C_TOP_ADDR, 0x28, 0x070f, },
+       { S5H1411_I2C_TOP_ADDR, 0x29, 0x2820, },
+       { S5H1411_I2C_TOP_ADDR, 0x2a, 0x102e, },
+       { S5H1411_I2C_TOP_ADDR, 0x2b, 0x0220, },
+       { S5H1411_I2C_TOP_ADDR, 0x2e, 0x0d0e, },
+       { S5H1411_I2C_TOP_ADDR, 0x2f, 0x1013, },
+       { S5H1411_I2C_TOP_ADDR, 0x31, 0x171b, },
+       { S5H1411_I2C_TOP_ADDR, 0x32, 0x0e0f, },
+       { S5H1411_I2C_TOP_ADDR, 0x33, 0x0f10, },
+       { S5H1411_I2C_TOP_ADDR, 0x34, 0x170e, },
+       { S5H1411_I2C_TOP_ADDR, 0x35, 0x4b10, },
+       { S5H1411_I2C_TOP_ADDR, 0x36, 0x0f17, },
+       { S5H1411_I2C_TOP_ADDR, 0x3c, 0x1577, },
+       { S5H1411_I2C_TOP_ADDR, 0x3d, 0x081a, },
+       { S5H1411_I2C_TOP_ADDR, 0x3e, 0x77ee, },
+       { S5H1411_I2C_TOP_ADDR, 0x40, 0x1e09, },
+       { S5H1411_I2C_TOP_ADDR, 0x41, 0x0f0c, },
+       { S5H1411_I2C_TOP_ADDR, 0x42, 0x1f10, },
+       { S5H1411_I2C_TOP_ADDR, 0x4d, 0x0509, },
+       { S5H1411_I2C_TOP_ADDR, 0x4e, 0x0a00, },
+       { S5H1411_I2C_TOP_ADDR, 0x50, 0x0000, },
+       { S5H1411_I2C_TOP_ADDR, 0x5b, 0x0000, },
+       { S5H1411_I2C_TOP_ADDR, 0x5c, 0x0008, },
+       { S5H1411_I2C_TOP_ADDR, 0x57, 0x1101, },
+       { S5H1411_I2C_TOP_ADDR, 0x65, 0x007c, },
+       { S5H1411_I2C_TOP_ADDR, 0x68, 0x0512, },
+       { S5H1411_I2C_TOP_ADDR, 0x69, 0x0258, },
+       { S5H1411_I2C_TOP_ADDR, 0x70, 0x0004, },
+       { S5H1411_I2C_TOP_ADDR, 0x71, 0x0007, },
+       { S5H1411_I2C_TOP_ADDR, 0x76, 0x00a9, },
+       { S5H1411_I2C_TOP_ADDR, 0x78, 0x3141, },
+       { S5H1411_I2C_TOP_ADDR, 0x7a, 0x3141, },
+       { S5H1411_I2C_TOP_ADDR, 0xb3, 0x8003, },
+       { S5H1411_I2C_TOP_ADDR, 0xb5, 0xafbb, },
+       { S5H1411_I2C_TOP_ADDR, 0xb5, 0xa6bb, },
+       { S5H1411_I2C_TOP_ADDR, 0xb6, 0x0609, },
+       { S5H1411_I2C_TOP_ADDR, 0xb7, 0x2f06, },
+       { S5H1411_I2C_TOP_ADDR, 0xb8, 0x003f, },
+       { S5H1411_I2C_TOP_ADDR, 0xb9, 0x2700, },
+       { S5H1411_I2C_TOP_ADDR, 0xba, 0xfac8, },
+       { S5H1411_I2C_TOP_ADDR, 0xbe, 0x1003, },
+       { S5H1411_I2C_TOP_ADDR, 0xbf, 0x103f, },
+       { S5H1411_I2C_TOP_ADDR, 0xce, 0x2000, },
+       { S5H1411_I2C_TOP_ADDR, 0xcf, 0x0800, },
+       { S5H1411_I2C_TOP_ADDR, 0xd0, 0x0800, },
+       { S5H1411_I2C_TOP_ADDR, 0xd1, 0x0400, },
+       { S5H1411_I2C_TOP_ADDR, 0xd2, 0x0800, },
+       { S5H1411_I2C_TOP_ADDR, 0xd3, 0x2000, },
+       { S5H1411_I2C_TOP_ADDR, 0xd4, 0x3000, },
+       { S5H1411_I2C_TOP_ADDR, 0xdb, 0x4a9b, },
+       { S5H1411_I2C_TOP_ADDR, 0xdc, 0x1000, },
+       { S5H1411_I2C_TOP_ADDR, 0xde, 0x0001, },
+       { S5H1411_I2C_TOP_ADDR, 0xdf, 0x0000, },
+       { S5H1411_I2C_TOP_ADDR, 0xe3, 0x0301, },
+       { S5H1411_I2C_QAM_ADDR, 0xf3, 0x0000, },
+       { S5H1411_I2C_QAM_ADDR, 0xf3, 0x0001, },
+       { S5H1411_I2C_QAM_ADDR, 0x08, 0x0600, },
+       { S5H1411_I2C_QAM_ADDR, 0x18, 0x4201, },
+       { S5H1411_I2C_QAM_ADDR, 0x1e, 0x6476, },
+       { S5H1411_I2C_QAM_ADDR, 0x21, 0x0830, },
+       { S5H1411_I2C_QAM_ADDR, 0x0c, 0x5679, },
+       { S5H1411_I2C_QAM_ADDR, 0x0d, 0x579b, },
+       { S5H1411_I2C_QAM_ADDR, 0x24, 0x0102, },
+       { S5H1411_I2C_QAM_ADDR, 0x31, 0x7488, },
+       { S5H1411_I2C_QAM_ADDR, 0x32, 0x0a08, },
+       { S5H1411_I2C_QAM_ADDR, 0x3d, 0x8689, },
+       { S5H1411_I2C_QAM_ADDR, 0x49, 0x0048, },
+       { S5H1411_I2C_QAM_ADDR, 0x57, 0x2012, },
+       { S5H1411_I2C_QAM_ADDR, 0x5d, 0x7676, },
+       { S5H1411_I2C_QAM_ADDR, 0x04, 0x0400, },
+       { S5H1411_I2C_QAM_ADDR, 0x58, 0x00c0, },
+       { S5H1411_I2C_QAM_ADDR, 0x5b, 0x0100, },
+};
+
+/* VSB SNR lookup table */
+static struct vsb_snr_tab {
+       u16     val;
+       u16     data;
+} vsb_snr_tab[] = {
+       {  0x39f, 300, },
+       {  0x39b, 295, },
+       {  0x397, 290, },
+       {  0x394, 285, },
+       {  0x38f, 280, },
+       {  0x38b, 275, },
+       {  0x387, 270, },
+       {  0x382, 265, },
+       {  0x37d, 260, },
+       {  0x377, 255, },
+       {  0x370, 250, },
+       {  0x36a, 245, },
+       {  0x364, 240, },
+       {  0x35b, 235, },
+       {  0x353, 230, },
+       {  0x349, 225, },
+       {  0x340, 320, },
+       {  0x337, 215, },
+       {  0x327, 210, },
+       {  0x31b, 205, },
+       {  0x310, 200, },
+       {  0x302, 195, },
+       {  0x2f3, 190, },
+       {  0x2e4, 185, },
+       {  0x2d7, 180, },
+       {  0x2cd, 175, },
+       {  0x2bb, 170, },
+       {  0x2a9, 165, },
+       {  0x29e, 160, },
+       {  0x284, 155, },
+       {  0x27a, 150, },
+       {  0x260, 145, },
+       {  0x23a, 140, },
+       {  0x224, 135, },
+       {  0x213, 130, },
+       {  0x204, 125, },
+       {  0x1fe, 120, },
+       {      0,   0, },
+};
+
+/* QAM64 SNR lookup table */
+static struct qam64_snr_tab {
+       u16     val;
+       u16     data;
+} qam64_snr_tab[] = {
+       {  0x0001,   0, },
+       {  0x0af0, 300, },
+       {  0x0d80, 290, },
+       {  0x10a0, 280, },
+       {  0x14b5, 270, },
+       {  0x1590, 268, },
+       {  0x1680, 266, },
+       {  0x17b0, 264, },
+       {  0x18c0, 262, },
+       {  0x19b0, 260, },
+       {  0x1ad0, 258, },
+       {  0x1d00, 256, },
+       {  0x1da0, 254, },
+       {  0x1ef0, 252, },
+       {  0x2050, 250, },
+       {  0x20f0, 249, },
+       {  0x21d0, 248, },
+       {  0x22b0, 247, },
+       {  0x23a0, 246, },
+       {  0x2470, 245, },
+       {  0x24f0, 244, },
+       {  0x25a0, 243, },
+       {  0x26c0, 242, },
+       {  0x27b0, 241, },
+       {  0x28d0, 240, },
+       {  0x29b0, 239, },
+       {  0x2ad0, 238, },
+       {  0x2ba0, 237, },
+       {  0x2c80, 236, },
+       {  0x2d20, 235, },
+       {  0x2e00, 234, },
+       {  0x2f10, 233, },
+       {  0x3050, 232, },
+       {  0x3190, 231, },
+       {  0x3300, 230, },
+       {  0x3340, 229, },
+       {  0x3200, 228, },
+       {  0x3550, 227, },
+       {  0x3610, 226, },
+       {  0x3600, 225, },
+       {  0x3700, 224, },
+       {  0x3800, 223, },
+       {  0x3920, 222, },
+       {  0x3a20, 221, },
+       {  0x3b30, 220, },
+       {  0x3d00, 219, },
+       {  0x3e00, 218, },
+       {  0x4000, 217, },
+       {  0x4100, 216, },
+       {  0x4300, 215, },
+       {  0x4400, 214, },
+       {  0x4600, 213, },
+       {  0x4700, 212, },
+       {  0x4800, 211, },
+       {  0x4a00, 210, },
+       {  0x4b00, 209, },
+       {  0x4d00, 208, },
+       {  0x4f00, 207, },
+       {  0x5050, 206, },
+       {  0x5200, 205, },
+       {  0x53c0, 204, },
+       {  0x5450, 203, },
+       {  0x5650, 202, },
+       {  0x5820, 201, },
+       {  0x6000, 200, },
+       {  0xffff,   0, },
+};
+
+/* QAM256 SNR lookup table */
+static struct qam256_snr_tab {
+       u16     val;
+       u16     data;
+} qam256_snr_tab[] = {
+       {  0x0001,   0, },
+       {  0x0970, 400, },
+       {  0x0a90, 390, },
+       {  0x0b90, 380, },
+       {  0x0d90, 370, },
+       {  0x0ff0, 360, },
+       {  0x1240, 350, },
+       {  0x1345, 348, },
+       {  0x13c0, 346, },
+       {  0x14c0, 344, },
+       {  0x1500, 342, },
+       {  0x1610, 340, },
+       {  0x1700, 338, },
+       {  0x1800, 336, },
+       {  0x18b0, 334, },
+       {  0x1900, 332, },
+       {  0x1ab0, 330, },
+       {  0x1bc0, 328, },
+       {  0x1cb0, 326, },
+       {  0x1db0, 324, },
+       {  0x1eb0, 322, },
+       {  0x2030, 320, },
+       {  0x2200, 318, },
+       {  0x2280, 316, },
+       {  0x2410, 314, },
+       {  0x25b0, 312, },
+       {  0x27a0, 310, },
+       {  0x2840, 308, },
+       {  0x29d0, 306, },
+       {  0x2b10, 304, },
+       {  0x2d30, 302, },
+       {  0x2f20, 300, },
+       {  0x30c0, 298, },
+       {  0x3260, 297, },
+       {  0x32c0, 296, },
+       {  0x3300, 295, },
+       {  0x33b0, 294, },
+       {  0x34b0, 293, },
+       {  0x35a0, 292, },
+       {  0x3650, 291, },
+       {  0x3800, 290, },
+       {  0x3900, 289, },
+       {  0x3a50, 288, },
+       {  0x3b30, 287, },
+       {  0x3cb0, 286, },
+       {  0x3e20, 285, },
+       {  0x3fa0, 284, },
+       {  0x40a0, 283, },
+       {  0x41c0, 282, },
+       {  0x42f0, 281, },
+       {  0x44a0, 280, },
+       {  0x4600, 279, },
+       {  0x47b0, 278, },
+       {  0x4900, 277, },
+       {  0x4a00, 276, },
+       {  0x4ba0, 275, },
+       {  0x4d00, 274, },
+       {  0x4f00, 273, },
+       {  0x5000, 272, },
+       {  0x51f0, 272, },
+       {  0x53a0, 270, },
+       {  0x5520, 269, },
+       {  0x5700, 268, },
+       {  0x5800, 267, },
+       {  0x5a00, 266, },
+       {  0x5c00, 265, },
+       {  0x5d00, 264, },
+       {  0x5f00, 263, },
+       {  0x6000, 262, },
+       {  0x6200, 261, },
+       {  0x6400, 260, },
+       {  0xffff,   0, },
+};
+
+/* 8 bit registers, 16 bit values */
+static int s5h1411_writereg(struct s5h1411_state *state,
+       u8 addr, u8 reg, u16 data)
+{
+       int ret;
+       u8 buf [] = { reg, data >> 8,  data & 0xff };
+
+       struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = buf, .len = 3 };
+
+       ret = i2c_transfer(state->i2c, &msg, 1);
+
+       if (ret != 1)
+               printk(KERN_ERR "%s: writereg error 0x%02x 0x%02x 0x%04x, "
+                      "ret == %i)\n", __func__, addr, reg, data, ret);
+
+       return (ret != 1) ? -1 : 0;
+}
+
+static u16 s5h1411_readreg(struct s5h1411_state *state, u8 addr, u8 reg)
+{
+       int ret;
+       u8 b0 [] = { reg };
+       u8 b1 [] = { 0, 0 };
+
+       struct i2c_msg msg [] = {
+               { .addr = addr, .flags = 0, .buf = b0, .len = 1 },
+               { .addr = addr, .flags = I2C_M_RD, .buf = b1, .len = 2 } };
+
+       ret = i2c_transfer(state->i2c, msg, 2);
+
+       if (ret != 2)
+               printk(KERN_ERR "%s: readreg error (ret == %i)\n",
+                       __func__, ret);
+       return (b1[0] << 8) | b1[1];
+}
+
+static int s5h1411_softreset(struct dvb_frontend *fe)
+{
+       struct s5h1411_state *state = fe->demodulator_priv;
+
+       dprintk("%s()\n", __func__);
+
+       s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf7, 0);
+       s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf7, 1);
+       return 0;
+}
+
+static int s5h1411_set_if_freq(struct dvb_frontend *fe, int KHz)
+{
+       struct s5h1411_state *state = fe->demodulator_priv;
+
+       dprintk("%s(%d KHz)\n", __func__, KHz);
+
+       switch (KHz) {
+       case 3250:
+               s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x38, 0x10d9);
+               s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x39, 0x5342);
+               s5h1411_writereg(state, S5H1411_I2C_QAM_ADDR, 0x2c, 0x10d9);
+               break;
+       case 3500:
+               s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x38, 0x1225);
+               s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x39, 0x1e96);
+               s5h1411_writereg(state, S5H1411_I2C_QAM_ADDR, 0x2c, 0x1225);
+               break;
+       case 4000:
+               s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x38, 0x14bc);
+               s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x39, 0xb53e);
+               s5h1411_writereg(state, S5H1411_I2C_QAM_ADDR, 0x2c, 0x14bd);
+               break;
+       default:
+               dprintk("%s(%d KHz) Invalid, defaulting to 5380\n",
+                       __func__, KHz);
+               /* no break, need to continue */
+       case 5380:
+       case 44000:
+               s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x38, 0x1be4);
+               s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x39, 0x3655);
+               s5h1411_writereg(state, S5H1411_I2C_QAM_ADDR, 0x2c, 0x1be4);
+               break;
+       }
+
+       state->if_freq = KHz;
+
+       return 0;
+}
+
+static int s5h1411_set_mpeg_timing(struct dvb_frontend *fe, int mode)
+{
+       struct s5h1411_state *state = fe->demodulator_priv;
+       u16 val;
+
+       dprintk("%s(%d)\n", __func__, mode);
+
+       val = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xbe) & 0xcfff;
+       switch (mode) {
+       case S5H1411_MPEGTIMING_CONTINOUS_INVERTING_CLOCK:
+               val |= 0x0000;
+               break;
+       case S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK:
+               dprintk("%s(%d) Mode1 or Defaulting\n", __func__, mode);
+               val |= 0x1000;
+               break;
+       case S5H1411_MPEGTIMING_NONCONTINOUS_INVERTING_CLOCK:
+               val |= 0x2000;
+               break;
+       case S5H1411_MPEGTIMING_NONCONTINOUS_NONINVERTING_CLOCK:
+               val |= 0x3000;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       /* Configure MPEG Signal Timing charactistics */
+       return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xbe, val);
+}
+
+static int s5h1411_set_spectralinversion(struct dvb_frontend *fe, int inversion)
+{
+       struct s5h1411_state *state = fe->demodulator_priv;
+       u16 val;
+
+       dprintk("%s(%d)\n", __func__, inversion);
+       val = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0x24) & ~0x1000;
+
+       if (inversion == 1)
+               val |= 0x1000; /* Inverted */
+       else
+               val |= 0x0000;
+
+       state->inversion = inversion;
+       return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x24, val);
+}
+
+static int s5h1411_enable_modulation(struct dvb_frontend *fe,
+                                    fe_modulation_t m)
+{
+       struct s5h1411_state *state = fe->demodulator_priv;
+
+       dprintk("%s(0x%08x)\n", __func__, m);
+
+       switch (m) {
+       case VSB_8:
+               dprintk("%s() VSB_8\n", __func__);
+               s5h1411_set_if_freq(fe, state->config->vsb_if);
+               s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x00, 0x71);
+               s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf6, 0x00);
+               s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xcd, 0xf1);
+               break;
+       case QAM_64:
+       case QAM_256:
+               dprintk("%s() QAM_AUTO (64/256)\n", __func__);
+               s5h1411_set_if_freq(fe, state->config->qam_if);
+               s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x00, 0x0171);
+               s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf6, 0x0001);
+               s5h1411_writereg(state, S5H1411_I2C_QAM_ADDR, 0x16, 0x1101);
+               s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xcd, 0x00f0);
+               break;
+       default:
+               dprintk("%s() Invalid modulation\n", __func__);
+               return -EINVAL;
+       }
+
+       state->current_modulation = m;
+       s5h1411_softreset(fe);
+
+       return 0;
+}
+
+static int s5h1411_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+       struct s5h1411_state *state = fe->demodulator_priv;
+
+       dprintk("%s(%d)\n", __func__, enable);
+
+       if (enable)
+               return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf5, 1);
+       else
+               return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf5, 0);
+}
+
+static int s5h1411_set_gpio(struct dvb_frontend *fe, int enable)
+{
+       struct s5h1411_state *state = fe->demodulator_priv;
+       u16 val;
+
+       dprintk("%s(%d)\n", __func__, enable);
+
+       val = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xe0) & ~0x02;
+
+       if (enable)
+               return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xe0,
+                               val | 0x02);
+       else
+               return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xe0, val);
+}
+
+static int s5h1411_sleep(struct dvb_frontend *fe, int enable)
+{
+       struct s5h1411_state *state = fe->demodulator_priv;
+
+       dprintk("%s(%d)\n", __func__, enable);
+
+       if (enable)
+               s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf4, 1);
+       else {
+               s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf4, 0);
+               s5h1411_softreset(fe);
+       }
+
+       return 0;
+}
+
+static int s5h1411_register_reset(struct dvb_frontend *fe)
+{
+       struct s5h1411_state *state = fe->demodulator_priv;
+
+       dprintk("%s()\n", __func__);
+
+       return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf3, 0);
+}
+
+/* Talk to the demod, set the FEC, GUARD, QAM settings etc */
+static int s5h1411_set_frontend(struct dvb_frontend *fe,
+       struct dvb_frontend_parameters *p)
+{
+       struct s5h1411_state *state = fe->demodulator_priv;
+
+       dprintk("%s(frequency=%d)\n", __func__, p->frequency);
+
+       s5h1411_softreset(fe);
+
+       state->current_frequency = p->frequency;
+
+       s5h1411_enable_modulation(fe, p->u.vsb.modulation);
+
+       /* Allow the demod to settle */
+       msleep(100);
+
+       if (fe->ops.tuner_ops.set_params) {
+               if (fe->ops.i2c_gate_ctrl)
+                       fe->ops.i2c_gate_ctrl(fe, 1);
+
+               fe->ops.tuner_ops.set_params(fe, p);
+
+               if (fe->ops.i2c_gate_ctrl)
+                       fe->ops.i2c_gate_ctrl(fe, 0);
+       }
+
+       return 0;
+}
+
+/* Reset the demod hardware and reset all of the configuration registers
+   to a default state. */
+static int s5h1411_init(struct dvb_frontend *fe)
+{
+       struct s5h1411_state *state = fe->demodulator_priv;
+       int i;
+
+       dprintk("%s()\n", __func__);
+
+       s5h1411_sleep(fe, 0);
+       s5h1411_register_reset(fe);
+
+       for (i = 0; i < ARRAY_SIZE(init_tab); i++)
+               s5h1411_writereg(state, init_tab[i].addr,
+                       init_tab[i].reg,
+                       init_tab[i].data);
+
+       /* The datasheet says that after initialisation, VSB is default */
+       state->current_modulation = VSB_8;
+
+       if (state->config->output_mode == S5H1411_SERIAL_OUTPUT)
+               /* Serial */
+               s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xbd, 0x1101);
+       else
+               /* Parallel */
+               s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xbd, 0x1001);
+
+       s5h1411_set_spectralinversion(fe, state->config->inversion);
+       s5h1411_set_if_freq(fe, state->config->vsb_if);
+       s5h1411_set_gpio(fe, state->config->gpio);
+       s5h1411_set_mpeg_timing(fe, state->config->mpeg_timing);
+       s5h1411_softreset(fe);
+
+       /* Note: Leaving the I2C gate closed. */
+       s5h1411_i2c_gate_ctrl(fe, 0);
+
+       return 0;
+}
+
+static int s5h1411_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+       struct s5h1411_state *state = fe->demodulator_priv;
+       u16 reg;
+       u32 tuner_status = 0;
+
+       *status = 0;
+
+       /* Get the demodulator status */
+       reg = (s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xf2) >> 15)
+               & 0x0001;
+       if (reg)
+               *status |= FE_HAS_LOCK | FE_HAS_CARRIER | FE_HAS_SIGNAL;
+
+       switch (state->current_modulation) {
+       case QAM_64:
+       case QAM_256:
+               reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xf0);
+               if (reg & 0x100)
+                       *status |= FE_HAS_VITERBI;
+               if (reg & 0x10)
+                       *status |= FE_HAS_SYNC;
+               break;
+       case VSB_8:
+               reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0x5e);
+               if (reg & 0x0001)
+                       *status |= FE_HAS_SYNC;
+               reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xf2);
+               if (reg & 0x1000)
+                       *status |= FE_HAS_VITERBI;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       switch (state->config->status_mode) {
+       case S5H1411_DEMODLOCKING:
+               if (*status & FE_HAS_VITERBI)
+                       *status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
+               break;
+       case S5H1411_TUNERLOCKING:
+               /* Get the tuner status */
+               if (fe->ops.tuner_ops.get_status) {
+                       if (fe->ops.i2c_gate_ctrl)
+                               fe->ops.i2c_gate_ctrl(fe, 1);
+
+                       fe->ops.tuner_ops.get_status(fe, &tuner_status);
+
+                       if (fe->ops.i2c_gate_ctrl)
+                               fe->ops.i2c_gate_ctrl(fe, 0);
+               }
+               if (tuner_status)
+                       *status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
+               break;
+       }
+
+       dprintk("%s() status 0x%08x\n", __func__, *status);
+
+       return 0;
+}
+
+static int s5h1411_qam256_lookup_snr(struct dvb_frontend *fe, u16 *snr, u16 v)
+{
+       int i, ret = -EINVAL;
+       dprintk("%s()\n", __func__);
+
+       for (i = 0; i < ARRAY_SIZE(qam256_snr_tab); i++) {
+               if (v < qam256_snr_tab[i].val) {
+                       *snr = qam256_snr_tab[i].data;
+                       ret = 0;
+                       break;
+               }
+       }
+       return ret;
+}
+
+static int s5h1411_qam64_lookup_snr(struct dvb_frontend *fe, u16 *snr, u16 v)
+{
+       int i, ret = -EINVAL;
+       dprintk("%s()\n", __func__);
+
+       for (i = 0; i < ARRAY_SIZE(qam64_snr_tab); i++) {
+               if (v < qam64_snr_tab[i].val) {
+                       *snr = qam64_snr_tab[i].data;
+                       ret = 0;
+                       break;
+               }
+       }
+       return ret;
+}
+
+static int s5h1411_vsb_lookup_snr(struct dvb_frontend *fe, u16 *snr, u16 v)
+{
+       int i, ret = -EINVAL;
+       dprintk("%s()\n", __func__);
+
+       for (i = 0; i < ARRAY_SIZE(vsb_snr_tab); i++) {
+               if (v > vsb_snr_tab[i].val) {
+                       *snr = vsb_snr_tab[i].data;
+                       ret = 0;
+                       break;
+               }
+       }
+       dprintk("%s() snr=%d\n", __func__, *snr);
+       return ret;
+}
+
+static int s5h1411_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+       struct s5h1411_state *state = fe->demodulator_priv;
+       u16 reg;
+       dprintk("%s()\n", __func__);
+
+       switch (state->current_modulation) {
+       case QAM_64:
+               reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xf1);
+               return s5h1411_qam64_lookup_snr(fe, snr, reg);
+       case QAM_256:
+               reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xf1);
+               return s5h1411_qam256_lookup_snr(fe, snr, reg);
+       case VSB_8:
+               reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR,
+                       0xf2) & 0x3ff;
+               return s5h1411_vsb_lookup_snr(fe, snr, reg);
+       default:
+               break;
+       }
+
+       return -EINVAL;
+}
+
+static int s5h1411_read_signal_strength(struct dvb_frontend *fe,
+       u16 *signal_strength)
+{
+       return s5h1411_read_snr(fe, signal_strength);
+}
+
+static int s5h1411_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+       struct s5h1411_state *state = fe->demodulator_priv;
+
+       *ucblocks = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xc9);
+
+       return 0;
+}
+
+static int s5h1411_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+       return s5h1411_read_ucblocks(fe, ber);
+}
+
+static int s5h1411_get_frontend(struct dvb_frontend *fe,
+                               struct dvb_frontend_parameters *p)
+{
+       struct s5h1411_state *state = fe->demodulator_priv;
+
+       p->frequency = state->current_frequency;
+       p->u.vsb.modulation = state->current_modulation;
+
+       return 0;
+}
+
+static int s5h1411_get_tune_settings(struct dvb_frontend *fe,
+                                    struct dvb_frontend_tune_settings *tune)
+{
+       tune->min_delay_ms = 1000;
+       return 0;
+}
+
+static void s5h1411_release(struct dvb_frontend *fe)
+{
+       struct s5h1411_state *state = fe->demodulator_priv;
+       kfree(state);
+}
+
+static struct dvb_frontend_ops s5h1411_ops;
+
+struct dvb_frontend *s5h1411_attach(const struct s5h1411_config *config,
+                                   struct i2c_adapter *i2c)
+{
+       struct s5h1411_state *state = NULL;
+       u16 reg;
+
+       /* allocate memory for the internal state */
+       state = kmalloc(sizeof(struct s5h1411_state), GFP_KERNEL);
+       if (state == NULL)
+               goto error;
+
+       /* setup the state */
+       state->config = config;
+       state->i2c = i2c;
+       state->current_modulation = VSB_8;
+       state->inversion = state->config->inversion;
+
+       /* check if the demod exists */
+       reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0x05);
+       if (reg != 0x0066)
+               goto error;
+
+       /* create dvb_frontend */
+       memcpy(&state->frontend.ops, &s5h1411_ops,
+              sizeof(struct dvb_frontend_ops));
+
+       state->frontend.demodulator_priv = state;
+
+       if (s5h1411_init(&state->frontend) != 0) {
+               printk(KERN_ERR "%s: Failed to initialize correctly\n",
+                       __func__);
+               goto error;
+       }
+
+       /* Note: Leaving the I2C gate open here. */
+       s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf5, 1);
+
+       return &state->frontend;
+
+error:
+       kfree(state);
+       return NULL;
+}
+EXPORT_SYMBOL(s5h1411_attach);
+
+static struct dvb_frontend_ops s5h1411_ops = {
+
+       .info = {
+               .name                   = "Samsung S5H1411 QAM/8VSB Frontend",
+               .type                   = FE_ATSC,
+               .frequency_min          = 54000000,
+               .frequency_max          = 858000000,
+               .frequency_stepsize     = 62500,
+               .caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
+       },
+
+       .init                 = s5h1411_init,
+       .i2c_gate_ctrl        = s5h1411_i2c_gate_ctrl,
+       .set_frontend         = s5h1411_set_frontend,
+       .get_frontend         = s5h1411_get_frontend,
+       .get_tune_settings    = s5h1411_get_tune_settings,
+       .read_status          = s5h1411_read_status,
+       .read_ber             = s5h1411_read_ber,
+       .read_signal_strength = s5h1411_read_signal_strength,
+       .read_snr             = s5h1411_read_snr,
+       .read_ucblocks        = s5h1411_read_ucblocks,
+       .release              = s5h1411_release,
+};
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Enable verbose debug messages");
+
+MODULE_DESCRIPTION("Samsung S5H1411 QAM-B/ATSC Demodulator driver");
+MODULE_AUTHOR("Steven Toth");
+MODULE_LICENSE("GPL");
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ */
diff --git a/drivers/media/dvb/frontends/s5h1411.h b/drivers/media/dvb/frontends/s5h1411.h
new file mode 100644 (file)
index 0000000..1855f64
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+    Samsung S5H1411 VSB/QAM demodulator driver
+
+    Copyright (C) 2008 Steven Toth <stoth@hauppauge.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 program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    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.
+
+*/
+
+#ifndef __S5H1411_H__
+#define __S5H1411_H__
+
+#include <linux/dvb/frontend.h>
+
+#define S5H1411_I2C_TOP_ADDR (0x32 >> 1)
+#define S5H1411_I2C_QAM_ADDR (0x34 >> 1)
+
+struct s5h1411_config {
+
+       /* serial/parallel output */
+#define S5H1411_PARALLEL_OUTPUT 0
+#define S5H1411_SERIAL_OUTPUT   1
+       u8 output_mode;
+
+       /* GPIO Setting */
+#define S5H1411_GPIO_OFF 0
+#define S5H1411_GPIO_ON  1
+       u8 gpio;
+
+       /* MPEG signal timing */
+#define S5H1411_MPEGTIMING_CONTINOUS_INVERTING_CLOCK       0
+#define S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK    1
+#define S5H1411_MPEGTIMING_NONCONTINOUS_INVERTING_CLOCK    2
+#define S5H1411_MPEGTIMING_NONCONTINOUS_NONINVERTING_CLOCK 3
+       u16 mpeg_timing;
+
+       /* IF Freq for QAM and VSB in KHz */
+#define S5H1411_IF_2500  2500
+#define S5H1411_IF_3500  3500
+#define S5H1411_IF_4000  4000
+#define S5H1411_IF_5380  5380
+#define S5H1411_IF_44000 44000
+#define S5H1411_VSB_IF_DEFAULT S5H1411_IF_44000
+#define S5H1411_QAM_IF_DEFAULT S5H1411_IF_44000
+       u16 qam_if;
+       u16 vsb_if;
+
+       /* Spectral Inversion */
+#define S5H1411_INVERSION_OFF 0
+#define S5H1411_INVERSION_ON  1
+       u8 inversion;
+
+       /* Return lock status based on tuner lock, or demod lock */
+#define S5H1411_TUNERLOCKING 0
+#define S5H1411_DEMODLOCKING 1
+       u8 status_mode;
+};
+
+#if defined(CONFIG_DVB_S5H1411) || \
+       (defined(CONFIG_DVB_S5H1411_MODULE) && defined(MODULE))
+extern struct dvb_frontend *s5h1411_attach(const struct s5h1411_config *config,
+                                          struct i2c_adapter *i2c);
+#else
+static inline struct dvb_frontend *s5h1411_attach(
+       const struct s5h1411_config *config,
+       struct i2c_adapter *i2c)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+       return NULL;
+}
+#endif /* CONFIG_DVB_S5H1411 */
+
+#endif /* __S5H1411_H__ */
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ */
index c97c4bd..4170826 100644 (file)
@@ -1,7 +1,7 @@
 
 config VIDEO_AU0828
        tristate "Auvitek AU0828 support"
-       depends on VIDEO_DEV && I2C && INPUT
+       depends on VIDEO_DEV && I2C && INPUT && DVB_CORE
        select I2C_ALGOBIT
        select DVB_AU8522 if !DVB_FE_CUSTOMIZE
        select DVB_TUNER_XC5000 if !DVB_FE_CUSTOMIZE
index 8ca91f8..a2a6983 100644 (file)
@@ -36,7 +36,6 @@ struct au0828_board au0828_boards[] = {
                .name   = "DViCO FusionHDTV USB",
        },
 };
-const unsigned int au0828_bcount = ARRAY_SIZE(au0828_boards);
 
 /* Tuner callback function for au0828 boards. Currently only needed
  * for HVR1500Q, which has an xc5000 tuner.
index e65d564..54bfc0f 100644 (file)
  * 4 = I2C related
  * 8 = Bridge related
  */
-unsigned int debug;
-module_param(debug, int, 0644);
+int au0828_debug;
+module_param_named(debug, au0828_debug, int, 0644);
 MODULE_PARM_DESC(debug, "enable debug messages");
 
-unsigned int usb_debug;
-module_param(usb_debug, int, 0644);
-MODULE_PARM_DESC(usb_debug, "enable usb debug messages");
-
-unsigned int bridge_debug;
-module_param(bridge_debug, int, 0644);
-MODULE_PARM_DESC(bridge_debug, "enable bridge debug messages");
-
 #define _AU0828_BULKPIPE 0x03
 #define _BULKPIPESIZE 0xffff
 
@@ -229,24 +221,18 @@ static int __init au0828_init(void)
 {
        int ret;
 
-       if (debug)
+       if (au0828_debug & 1)
                printk(KERN_INFO "%s() Debugging is enabled\n", __func__);
 
-       if (usb_debug) {
+       if (au0828_debug & 2)
                printk(KERN_INFO "%s() USB Debugging is enabled\n", __func__);
-               debug |= 2;
-       }
 
-       if (i2c_debug) {
+       if (au0828_debug & 4)
                printk(KERN_INFO "%s() I2C Debugging is enabled\n", __func__);
-               debug |= 4;
-       }
 
-       if (bridge_debug) {
+       if (au0828_debug & 8)
                printk(KERN_INFO "%s() Bridge Debugging is enabled\n",
                       __func__);
-               debug |= 8;
-       }
 
        printk(KERN_INFO "au0828 driver loaded\n");
 
index 85d0ae9..5040d7f 100644 (file)
@@ -204,7 +204,7 @@ static int au0828_dvb_stop_feed(struct dvb_demux_feed *feed)
        return ret;
 }
 
-int dvb_register(struct au0828_dev *dev)
+static int dvb_register(struct au0828_dev *dev)
 {
        struct au0828_dvb *dvb = &dev->dvb;
        int result;
index 94c8b74..741a493 100644 (file)
 
 #include <media/v4l2-common.h>
 
-unsigned int i2c_debug;
-module_param(i2c_debug, int, 0444);
-MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");
-
-unsigned int i2c_scan;
+static int i2c_scan;
 module_param(i2c_scan, int, 0444);
 MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time");
 
index 0200b9f..7beb571 100644 (file)
@@ -96,15 +96,12 @@ struct au0828_buff {
 /* au0828-core.c */
 extern u32 au0828_read(struct au0828_dev *dev, u16 reg);
 extern u32 au0828_write(struct au0828_dev *dev, u16 reg, u32 val);
-extern unsigned int debug;
-extern unsigned int usb_debug;
-extern unsigned int bridge_debug;
+extern int au0828_debug;
 
 /* ----------------------------------------------------------- */
 /* au0828-cards.c */
 extern struct au0828_board au0828_boards[];
 extern struct usb_device_id au0828_usb_id_table[];
-extern const unsigned int au0828_bcount;
 extern void au0828_gpio_setup(struct au0828_dev *dev);
 extern int au0828_tuner_callback(void *priv, int command, int arg);
 extern void au0828_card_setup(struct au0828_dev *dev);
@@ -115,7 +112,6 @@ extern int au0828_i2c_register(struct au0828_dev *dev);
 extern int au0828_i2c_unregister(struct au0828_dev *dev);
 extern void au0828_call_i2c_clients(struct au0828_dev *dev,
        unsigned int cmd, void *arg);
-extern unsigned int i2c_debug;
 
 /* ----------------------------------------------------------- */
 /* au0828-dvb.c */
@@ -123,6 +119,6 @@ extern int au0828_dvb_register(struct au0828_dev *dev);
 extern void au0828_dvb_unregister(struct au0828_dev *dev);
 
 #define dprintk(level, fmt, arg...)\
-       do { if (debug & level)\
+       do { if (au0828_debug & level)\
                printk(KERN_DEBUG DRIVER_NAME "/0: " fmt, ## arg);\
        } while (0)
index bcf6d9b..27635cd 100644 (file)
@@ -58,6 +58,7 @@ config VIDEO_CX88_DVB
        select DVB_CX24123 if !DVB_FE_CUSTOMISE
        select DVB_ISL6421 if !DVB_FE_CUSTOMISE
        select TUNER_SIMPLE if !DVB_FE_CUSTOMISE
+       select DVB_S5H1411 if !DVB_FE_CUSTOMISE
        ---help---
          This adds support for DVB/ATSC cards based on the
          Conexant 2388x chip.
index 61c4f72..6c0c94c 100644 (file)
@@ -546,10 +546,12 @@ static int blackbird_initialize_codec(struct cx8802_dev *dev)
                if (retval < 0)
                        return retval;
 
-               dev->mailbox = blackbird_find_mailbox(dev);
-               if (dev->mailbox < 0)
+               retval = blackbird_find_mailbox(dev);
+               if (retval < 0)
                        return -1;
 
+               dev->mailbox = retval;
+
                retval = blackbird_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); /* ping */
                if (retval < 0) {
                        dprintk(0, "ERROR: Firmware ping failed!\n");
index 620159d..2b6b283 100644 (file)
@@ -1591,6 +1591,7 @@ static const struct cx88_board cx88_boards[] = {
                        .vmux   = 2,
                        .gpio0  = 0x16d9,
                }},
+               .mpeg           = CX88_MPEG_DVB,
        },
        [CX88_BOARD_PROLINK_PV_8000GT] = {
                .name           = "Prolink Pixelview MPEG 8000GT",
index f1251b8..1c7fe68 100644 (file)
@@ -47,6 +47,7 @@
 #include "isl6421.h"
 #include "tuner-simple.h"
 #include "tda9887.h"
+#include "s5h1411.h"
 
 MODULE_DESCRIPTION("driver for cx2388x based DVB cards");
 MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>");
@@ -463,6 +464,22 @@ static struct zl10353_config cx88_geniatech_x8000_mt = {
        .no_tuner = 1,
 };
 
+static struct s5h1411_config dvico_fusionhdtv7_config = {
+       .output_mode   = S5H1411_SERIAL_OUTPUT,
+       .gpio          = S5H1411_GPIO_ON,
+       .mpeg_timing   = S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
+       .qam_if        = S5H1411_IF_44000,
+       .vsb_if        = S5H1411_IF_44000,
+       .inversion     = S5H1411_INVERSION_OFF,
+       .status_mode   = S5H1411_DEMODLOCKING
+};
+
+static struct xc5000_config dvico_fusionhdtv7_tuner_config = {
+       .i2c_address    = 0xc2 >> 1,
+       .if_khz         = 5380,
+       .tuner_callback = cx88_tuner_callback,
+};
+
 static int attach_xc3028(u8 addr, struct cx8802_dev *dev)
 {
        struct dvb_frontend *fe;
@@ -844,6 +861,21 @@ static int dvb_register(struct cx8802_dev *dev)
                if (attach_xc3028(0x61, dev) < 0)
                        return -EINVAL;
                break;
+       case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD:
+               dev->dvb.frontend = dvb_attach(s5h1411_attach,
+                                              &dvico_fusionhdtv7_config,
+                                              &dev->core->i2c_adap);
+               if (dev->dvb.frontend != NULL) {
+                       /* tuner_config.video_dev must point to
+                        * i2c_adap.algo_data
+                        */
+                       dvico_fusionhdtv7_tuner_config.priv =
+                                               dev->core->i2c_adap.algo_data;
+                       dvb_attach(xc5000_attach, dev->dvb.frontend,
+                                  &dev->core->i2c_adap,
+                                  &dvico_fusionhdtv7_tuner_config);
+               }
+               break;
        default:
                printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card isn't supported yet\n",
                       dev->core->name);
index f8c41d8..5d837c1 100644 (file)
@@ -650,7 +650,7 @@ int em28xx_init_isoc(struct em28xx *dev, int max_packets,
 
        dev->isoc_ctl.transfer_buffer = kzalloc(sizeof(void *)*num_bufs,
                                              GFP_KERNEL);
-       if (!dev->isoc_ctl.urb) {
+       if (!dev->isoc_ctl.transfer_buffer) {
                em28xx_errdev("cannot allocate memory for usbtransfer\n");
                kfree(dev->isoc_ctl.urb);
                return -ENOMEM;
index 11c5fde..7b65f5e 100644 (file)
@@ -509,8 +509,11 @@ static int ir_probe(struct i2c_adapter *adap)
        static const int probe_cx88[] = { 0x18, 0x6b, 0x71, -1 };
        static const int probe_cx23885[] = { 0x6b, -1 };
        const int *probe;
-       struct i2c_client *c;
-       unsigned char buf;
+       struct i2c_msg msg = {
+               .flags = I2C_M_RD,
+               .len = 0,
+               .buf = NULL,
+       };
        int i, rc;
 
        switch (adap->id) {
@@ -536,23 +539,17 @@ static int ir_probe(struct i2c_adapter *adap)
                return 0;
        }
 
-       c = kzalloc(sizeof(*c), GFP_KERNEL);
-       if (!c)
-               return -ENOMEM;
-
-       c->adapter = adap;
        for (i = 0; -1 != probe[i]; i++) {
-               c->addr = probe[i];
-               rc = i2c_master_recv(c, &buf, 0);
+               msg.addr = probe[i];
+               rc = i2c_transfer(adap, &msg, 1);
                dprintk(1,"probe 0x%02x @ %s: %s\n",
                        probe[i], adap->name,
-                       (0 == rc) ? "yes" : "no");
-               if (0 == rc) {
+                       (1 == rc) ? "yes" : "no");
+               if (1 == rc) {
                        ir_attach(adap, probe[i], 0, 0);
                        break;
                }
        }
-       kfree(c);
        return 0;
 }
 
index a8da90f..158b3d0 100644 (file)
@@ -64,6 +64,7 @@ config VIDEO_PVRUSB2_DVB
        depends on VIDEO_PVRUSB2 && DVB_CORE && EXPERIMENTAL
        select DVB_LGDT330X if !DVB_FE_CUSTOMISE
        select DVB_S5H1409 if !DVB_FE_CUSTOMISE
+       select DVB_S5H1411 if !DVB_FE_CUSTOMISE
        select DVB_TDA10048 if !DVB_FE_CUSTOMIZE
        select DVB_TDA18271 if !DVB_FE_CUSTOMIZE
        select TUNER_SIMPLE if !DVB_FE_CUSTOMISE
index 2dd06a9..3a141d9 100644 (file)
@@ -36,6 +36,7 @@ pvr2_device_desc structures.
 #include "pvrusb2-hdw-internal.h"
 #include "lgdt330x.h"
 #include "s5h1409.h"
+#include "s5h1411.h"
 #include "tda10048.h"
 #include "tda18271.h"
 #include "tda8290.h"
@@ -368,6 +369,15 @@ static struct s5h1409_config pvr2_s5h1409_config = {
        .status_mode   = S5H1409_DEMODLOCKING,
 };
 
+static struct s5h1411_config pvr2_s5h1411_config = {
+       .output_mode   = S5H1411_PARALLEL_OUTPUT,
+       .gpio          = S5H1411_GPIO_OFF,
+       .vsb_if        = S5H1411_IF_44000,
+       .qam_if        = S5H1411_IF_4000,
+       .inversion     = S5H1411_INVERSION_ON,
+       .status_mode   = S5H1411_DEMODLOCKING,
+};
+
 static struct tda18271_std_map hauppauge_tda18271_std_map = {
        .atsc_6   = { .if_freq = 5380, .agc_mode = 3, .std = 3,
                      .if_lvl = 6, .rfagc_top = 0x37, },
@@ -390,6 +400,16 @@ static int pvr2_s5h1409_attach(struct pvr2_dvb_adapter *adap)
        return -EIO;
 }
 
+static int pvr2_s5h1411_attach(struct pvr2_dvb_adapter *adap)
+{
+       adap->fe = dvb_attach(s5h1411_attach, &pvr2_s5h1411_config,
+                             &adap->channel.hdw->i2c_adap);
+       if (adap->fe)
+               return 0;
+
+       return -EIO;
+}
+
 static int pvr2_tda18271_8295_attach(struct pvr2_dvb_adapter *adap)
 {
        dvb_attach(tda829x_attach, adap->fe,
@@ -406,6 +426,11 @@ struct pvr2_dvb_props pvr2_750xx_dvb_props = {
        .frontend_attach = pvr2_s5h1409_attach,
        .tuner_attach    = pvr2_tda18271_8295_attach,
 };
+
+struct pvr2_dvb_props pvr2_751xx_dvb_props = {
+       .frontend_attach = pvr2_s5h1411_attach,
+       .tuner_attach    = pvr2_tda18271_8295_attach,
+};
 #endif
 
 static const char *pvr2_client_75xxx[] = {
@@ -454,6 +479,9 @@ static const struct pvr2_device_desc pvr2_device_751xx = {
                .digital_control_scheme = PVR2_DIGITAL_SCHEME_HAUPPAUGE,
                .default_std_mask = V4L2_STD_NTSC_M,
                .led_scheme = PVR2_LED_SCHEME_HAUPPAUGE,
+#ifdef CONFIG_VIDEO_PVRUSB2_DVB
+               .dvb_props = &pvr2_751xx_dvb_props,
+#endif
 };
 
 
index c2e2b06..d016f8b 100644 (file)
@@ -104,28 +104,28 @@ struct pvr2_device_desc {
        unsigned char digital_control_scheme;
 
        /* If set, we don't bother trying to load cx23416 firmware. */
-       int flag_skip_cx23416_firmware:1;
+       unsigned int flag_skip_cx23416_firmware:1;
 
        /* If set, the encoder must be healthy in order for digital mode to
           work (otherwise we assume that digital streaming will work even
           if we fail to locate firmware for the encoder).  If the device
           doesn't support digital streaming then this flag has no
           effect. */
-       int flag_digital_requires_cx23416:1;
+       unsigned int flag_digital_requires_cx23416:1;
 
        /* Device has a hauppauge eeprom which we can interrogate. */
-       int flag_has_hauppauge_rom:1;
+       unsigned int flag_has_hauppauge_rom:1;
 
        /* Device does not require a powerup command to be issued. */
-       int flag_no_powerup:1;
+       unsigned int flag_no_powerup:1;
 
        /* Device has a cx25840 - this enables special additional logic to
           handle it. */
-       int flag_has_cx25840:1;
+       unsigned int flag_has_cx25840:1;
 
        /* Device has a wm8775 - this enables special additional logic to
           ensure that it is found. */
-       int flag_has_wm8775:1;
+       unsigned int flag_has_wm8775:1;
 
        /* Device has IR hardware that can be faked into looking like a
           normal Hauppauge i2c IR receiver.  This is currently very
@@ -135,15 +135,15 @@ struct pvr2_device_desc {
           to virtualize the presence of the non-existant IR receiver chip and
           implement the virtual receiver in terms of appropriate FX2
           commands. */
-       int flag_has_hauppauge_custom_ir:1;
+       unsigned int flag_has_hauppauge_custom_ir:1;
 
        /* These bits define which kinds of sources the device can handle.
           Note: Digital tuner presence is inferred by the
           digital_control_scheme enumeration. */
-       int flag_has_fmradio:1;       /* Has FM radio receiver */
-       int flag_has_analogtuner:1;   /* Has analog tuner */
-       int flag_has_composite:1;     /* Has composite input */
-       int flag_has_svideo:1;        /* Has s-video input */
+       unsigned int flag_has_fmradio:1;       /* Has FM radio receiver */
+       unsigned int flag_has_analogtuner:1;   /* Has analog tuner */
+       unsigned int flag_has_composite:1;     /* Has composite input */
+       unsigned int flag_has_svideo:1;        /* Has s-video input */
 };
 
 extern struct usb_device_id pvr2_device_table[];
index 529e009..2b72e10 100644 (file)
@@ -369,19 +369,13 @@ static void set_type(struct i2c_client *c, unsigned int type,
                break;
        }
        case TUNER_TEA5767:
-               if (tea5767_attach(&t->fe, t->i2c->adapter, t->i2c->addr) == NULL) {
-                       t->type = TUNER_ABSENT;
-                       t->mode_mask = T_UNINITIALIZED;
-                       return;
-               }
+               if (!tea5767_attach(&t->fe, t->i2c->adapter, t->i2c->addr))
+                       goto attach_failed;
                t->mode_mask = T_RADIO;
                break;
        case TUNER_TEA5761:
-               if (tea5761_attach(&t->fe, t->i2c->adapter, t->i2c->addr) == NULL) {
-                       t->type = TUNER_ABSENT;
-                       t->mode_mask = T_UNINITIALIZED;
-                       return;
-               }
+               if (!tea5761_attach(&t->fe, t->i2c->adapter, t->i2c->addr))
+                       goto attach_failed;
                t->mode_mask = T_RADIO;
                break;
        case TUNER_PHILIPS_FMD1216ME_MK3:
@@ -394,12 +388,9 @@ static void set_type(struct i2c_client *c, unsigned int type,
                buffer[2] = 0x86;
                buffer[3] = 0x54;
                i2c_master_send(c, buffer, 4);
-               if (simple_tuner_attach(&t->fe, t->i2c->adapter, t->i2c->addr,
-                                       t->type) == NULL) {
-                       t->type = TUNER_ABSENT;
-                       t->mode_mask = T_UNINITIALIZED;
-                       return;
-               }
+               if (!simple_tuner_attach(&t->fe, t->i2c->adapter, t->i2c->addr,
+                                       t->type))
+                       goto attach_failed;
                break;
        case TUNER_PHILIPS_TD1316:
                buffer[0] = 0x0b;
@@ -407,12 +398,9 @@ static void set_type(struct i2c_client *c, unsigned int type,
                buffer[2] = 0x86;
                buffer[3] = 0xa4;
                i2c_master_send(c,buffer,4);
-               if (simple_tuner_attach(&t->fe, t->i2c->adapter,
-                                       t->i2c->addr, t->type) == NULL) {
-                       t->type = TUNER_ABSENT;
-                       t->mode_mask = T_UNINITIALIZED;
-                       return;
-               }
+               if (!simple_tuner_attach(&t->fe, t->i2c->adapter,
+                                       t->i2c->addr, t->type))
+                       goto attach_failed;
                break;
        case TUNER_XC2028:
        {
@@ -421,40 +409,34 @@ static void set_type(struct i2c_client *c, unsigned int type,
                        .i2c_addr  = t->i2c->addr,
                        .callback  = t->tuner_callback,
                };
-               if (!xc2028_attach(&t->fe, &cfg)) {
-                       t->type = TUNER_ABSENT;
-                       t->mode_mask = T_UNINITIALIZED;
-                       return;
-               }
+               if (!xc2028_attach(&t->fe, &cfg))
+                       goto attach_failed;
                break;
        }
        case TUNER_TDA9887:
                tda9887_attach(&t->fe, t->i2c->adapter, t->i2c->addr);
                break;
        case TUNER_XC5000:
+       {
+               struct dvb_tuner_ops *xc_tuner_ops;
+
                xc5000_cfg.i2c_address    = t->i2c->addr;
                xc5000_cfg.if_khz         = 5380;
                xc5000_cfg.priv           = c->adapter->algo_data;
                xc5000_cfg.tuner_callback = t->tuner_callback;
-               if (!xc5000_attach(&t->fe, t->i2c->adapter, &xc5000_cfg)) {
-                       t->type = TUNER_ABSENT;
-                       t->mode_mask = T_UNINITIALIZED;
-                       return;
-               }
-               {
-               struct dvb_tuner_ops *xc_tuner_ops;
+               if (!xc5000_attach(&t->fe, t->i2c->adapter, &xc5000_cfg))
+                       goto attach_failed;
+
                xc_tuner_ops = &t->fe.ops.tuner_ops;
-               if(xc_tuner_ops->init != NULL)
+               if (xc_tuner_ops->init)
                        xc_tuner_ops->init(&t->fe);
-               }
                break;
+       }
        default:
-               if (simple_tuner_attach(&t->fe, t->i2c->adapter,
-                                       t->i2c->addr, t->type) == NULL) {
-                       t->type = TUNER_ABSENT;
-                       t->mode_mask = T_UNINITIALIZED;
-                       return;
-               }
+               if (!simple_tuner_attach(&t->fe, t->i2c->adapter,
+                                       t->i2c->addr, t->type))
+                       goto attach_failed;
+
                break;
        }
 
@@ -476,11 +458,27 @@ static void set_type(struct i2c_client *c, unsigned int type,
        if (t->mode_mask == T_UNINITIALIZED)
                t->mode_mask = new_mode_mask;
 
-       set_freq(c, (V4L2_TUNER_RADIO == t->mode) ? t->radio_freq : t->tv_freq);
+       /* xc2028/3028 and xc5000 requires a firmware to be set-up later
+          trying to set a frequency here will just fail
+          FIXME: better to move set_freq to the tuner code. This is needed
+          on analog tuners for PLL to properly work
+        */
+       if (t->type != TUNER_XC2028 && t->type != TUNER_XC5000)
+               set_freq(c, (V4L2_TUNER_RADIO == t->mode) ?
+                           t->radio_freq : t->tv_freq);
+
        tuner_dbg("%s %s I2C addr 0x%02x with type %d used for 0x%02x\n",
                  c->adapter->name, c->driver->driver.name, c->addr << 1, type,
                  t->mode_mask);
        tuner_i2c_address_check(t);
+       return;
+
+attach_failed:
+       tuner_dbg("Tuner attach for type = %d failed.\n", t->type);
+       t->type = TUNER_ABSENT;
+       t->mode_mask = T_UNINITIALIZED;
+
+       return;
 }
 
 /*
@@ -495,14 +493,16 @@ static void set_addr(struct i2c_client *c, struct tuner_setup *tun_setup)
 {
        struct tuner *t = i2c_get_clientdata(c);
 
-       tuner_dbg("set addr for type %i\n", t->type);
-
        if ( (t->type == UNSET && ((tun_setup->addr == ADDR_UNSET) &&
                (t->mode_mask & tun_setup->mode_mask))) ||
                (tun_setup->addr == c->addr)) {
                        set_type(c, tun_setup->type, tun_setup->mode_mask,
                                 tun_setup->config, tun_setup->tuner_callback);
-       }
+       } else
+               tuner_dbg("set addr discarded for type %i, mask %x. "
+                         "Asked to change tuner at addr 0x%02x, with mask %x\n",
+                         t->type, t->mode_mask,
+                         tun_setup->addr, tun_setup->mode_mask);
 }
 
 static inline int check_mode(struct tuner *t, char *cmd)
index cc3db7d..9e9003c 100644 (file)
@@ -432,7 +432,7 @@ static int seek_firmware(struct dvb_frontend *fe, unsigned int type,
 
        type &= type_mask;
 
-       if (!type & SCODE)
+       if (!(type & SCODE))
                type_mask = ~0;
 
        /* Seek for exact match */
index b1e9592..845be18 100644 (file)
@@ -888,7 +888,7 @@ static int vivi_open(struct inode *inode, struct file *file)
 {
        int minor = iminor(inode);
        struct vivi_dev *dev;
-       struct vivi_fh *fh;
+       struct vivi_fh *fh = NULL;
        int i;
        int retval = 0;
 
index 9cbd9a6..b4a46b7 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef _MACH_BIOS_EBDA_H
 #define _MACH_BIOS_EBDA_H
 
+#include <asm/io.h>
+
 /*
  * there is a real-mode segmented pointer pointing to the
  * 4K EBDA area at 0x40E.
index 0c9e17c..d593e14 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef __ASM_IO_APIC_H
 #define __ASM_IO_APIC_H
 
-#include <asm/types.h>
+#include <linux/types.h>
 #include <asm/mpspec.h>
 #include <asm/apicdef.h>
 
@@ -110,11 +110,13 @@ extern int nr_ioapic_registers[MAX_IO_APICS];
  * MP-BIOS irq configuration table structures:
  */
 
+#define MP_MAX_IOAPIC_PIN 127
+
 struct mp_ioapic_routing {
        int apic_id;
        int gsi_base;
        int gsi_end;
-       u32 pin_programmed[4];
+       DECLARE_BITMAP(pin_programmed, MP_MAX_IOAPIC_PIN + 1);
 };
 
 /* I/O APIC entries */
index 3ff2c5b..56d0e1f 100644 (file)
@@ -33,7 +33,7 @@ static inline void smpboot_restore_warm_reset_vector(void)
        *((volatile long *) phys_to_virt(0x467)) = 0;
 }
 
-static inline void smpboot_setup_io_apic(void)
+static inline void __init smpboot_setup_io_apic(void)
 {
        /*
         * Here we can be sure that there is an IO-APIC in the system. Let's
index 168b644..577ab79 100644 (file)
@@ -198,16 +198,16 @@ do {                                              \
  */
 #define update_mmu_cache(vma, address, pte) do { } while (0)
 
-void native_pagetable_setup_start(pgd_t *base);
-void native_pagetable_setup_done(pgd_t *base);
+extern void native_pagetable_setup_start(pgd_t *base);
+extern void native_pagetable_setup_done(pgd_t *base);
 
 #ifndef CONFIG_PARAVIRT
-static inline void paravirt_pagetable_setup_start(pgd_t *base)
+static inline void __init paravirt_pagetable_setup_start(pgd_t *base)
 {
        native_pagetable_setup_start(base);
 }
 
-static inline void paravirt_pagetable_setup_done(pgd_t *base)
+static inline void __init paravirt_pagetable_setup_done(pgd_t *base)
 {
        native_pagetable_setup_done(base);
 }
index fe312a5..bb7133d 100644 (file)
@@ -1,5 +1,11 @@
 #ifdef __KERNEL__
-# if defined(CONFIG_X86_32) || defined(__i386__)
+# ifdef CONFIG_X86_32
+#  include "posix_types_32.h"
+# else
+#  include "posix_types_64.h"
+# endif
+#else
+# ifdef __i386__
 #  include "posix_types_32.h"
 # else
 #  include "posix_types_64.h"
index e6bf92d..117343b 100644 (file)
@@ -118,7 +118,6 @@ struct cpuinfo_x86 {
 #define X86_VENDOR_CYRIX       1
 #define X86_VENDOR_AMD         2
 #define X86_VENDOR_UMC         3
-#define X86_VENDOR_NEXGEN      4
 #define X86_VENDOR_CENTAUR     5
 #define X86_VENDOR_TRANSMETA   7
 #define X86_VENDOR_NSC         8
index 24ec061..9f922b0 100644 (file)
@@ -231,6 +231,8 @@ extern int do_get_thread_area(struct task_struct *p, int idx,
 extern int do_set_thread_area(struct task_struct *p, int idx,
                              struct user_desc __user *info, int can_allocate);
 
+#define __ARCH_WANT_COMPAT_SYS_PTRACE
+
 #endif /* __KERNEL__ */
 
 #endif /* !__ASSEMBLY__ */
index 3451c57..c9448bd 100644 (file)
@@ -60,15 +60,4 @@ enum {
        ALT_CALGARY     = 5,    /* Second Planar Calgary      */
 };
 
-/*
- * there is a real-mode segmented pointer pointing to the
- * 4K EBDA area at 0x40E.
- */
-static inline unsigned long get_bios_ebda(void)
-{
-       unsigned long address = *(unsigned short *)phys_to_virt(0x40EUL);
-       address <<= 4;
-       return address;
-}
-
 #endif /* __ASM_RIO_H */
index effc7ad..2a58ed3 100644 (file)
@@ -1,5 +1,11 @@
 #ifdef __KERNEL__
-# if defined(CONFIG_X86_32) || defined(__i386__)
+# ifdef CONFIG_X86_32
+#  include "unistd_32.h"
+# else
+#  include "unistd_64.h"
+# endif
+#else
+# ifdef __i386__
 #  include "unistd_32.h"
 # else
 #  include "unistd_64.h"
index cbb5ccb..bda6f04 100644 (file)
@@ -210,7 +210,6 @@ unifdef-y += hayesesp.h
 unifdef-y += hdlcdrv.h
 unifdef-y += hdlc.h
 unifdef-y += hdreg.h
-unifdef-y += hdsmart.h
 unifdef-y += hid.h
 unifdef-y += hiddev.h
 unifdef-y += hidraw.h
index fe23792..b2fd754 100644 (file)
 #define __must_be_array(a) \
   BUILD_BUG_ON_ZERO(__builtin_types_compatible_p(typeof(a), typeof(&a[0])))
 
-#define inline         inline          __attribute__((always_inline))
-#define __inline__     __inline__      __attribute__((always_inline))
-#define __inline       __inline        __attribute__((always_inline))
+/*
+ * Force always-inline if the user requests it so via the .config:
+ */
+#if !defined(CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING) || \
+    !defined(CONFIG_OPTIMIZE_INLINING) && (__GNUC__ >= 4)
+# define inline                inline          __attribute__((always_inline))
+# define __inline__    __inline__      __attribute__((always_inline))
+# define __inline      __inline        __attribute__((always_inline))
+#endif
+
 #define __deprecated                   __attribute__((deprecated))
 #define __packed                       __attribute__((packed))
 #define __weak                         __attribute__((weak))
diff --git a/include/linux/hdsmart.h b/include/linux/hdsmart.h
deleted file mode 100644 (file)
index 4f4faf9..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * linux/include/linux/hdsmart.h
- *
- * Copyright (C) 1999-2000     Michael Cornwell <cornwell@acm.org>
- * Copyright (C) 2000          Andre Hedrick <andre@linux-ide.org>
- *
- * 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, or (at your option)
- * any later version.
- *
- * You should have received a copy of the GNU General Public License
- * (for example /usr/src/linux/COPYING); if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef _LINUX_HDSMART_H
-#define _LINUX_HDSMART_H
-
-#ifndef __KERNEL__
-#define OFFLINE_FULL_SCAN              0
-#define SHORT_SELF_TEST                        1
-#define EXTEND_SELF_TEST               2
-#define SHORT_CAPTIVE_SELF_TEST                129
-#define EXTEND_CAPTIVE_SELF_TEST       130
-
-/* smart_attribute is the vendor specific in SFF-8035 spec */
-typedef struct ata_smart_attribute_s {
-       unsigned char                   id;
-       unsigned short                  status_flag;
-       unsigned char                   normalized;
-       unsigned char                   worse_normal;
-       unsigned char                   raw[6];
-       unsigned char                   reserv;
-} __attribute__ ((packed)) ata_smart_attribute_t;
-
-/* smart_values is format of the read drive Atrribute command */
-typedef struct ata_smart_values_s {
-       unsigned short                  revnumber;
-       ata_smart_attribute_t           vendor_attributes [30];
-        unsigned char                  offline_data_collection_status;
-        unsigned char                  self_test_exec_status;
-       unsigned short                  total_time_to_complete_off_line;
-       unsigned char                   vendor_specific_366;
-       unsigned char                   offline_data_collection_capability;
-       unsigned short                  smart_capability;
-       unsigned char                   errorlog_capability;
-       unsigned char                   vendor_specific_371;
-       unsigned char                   short_test_completion_time;
-       unsigned char                   extend_test_completion_time;
-       unsigned char                   reserved_374_385 [12];
-       unsigned char                   vendor_specific_386_509 [125];
-       unsigned char                   chksum;
-} __attribute__ ((packed)) ata_smart_values_t;
-
-/* Smart Threshold data structures */
-/* Vendor attribute of SMART Threshold */
-typedef struct ata_smart_threshold_entry_s {
-       unsigned char                   id;
-       unsigned char                   normalized_threshold;
-       unsigned char                   reserved[10];
-} __attribute__ ((packed)) ata_smart_threshold_entry_t;
-
-/* Format of Read SMART THreshold Command */
-typedef struct ata_smart_thresholds_s {
-       unsigned short                  revnumber;
-       ata_smart_threshold_entry_t     thres_entries[30];
-       unsigned char                   reserved[149];
-       unsigned char                   chksum;
-} __attribute__ ((packed)) ata_smart_thresholds_t;
-
-typedef struct ata_smart_errorlog_command_struct_s {
-       unsigned char                   devicecontrolreg;
-       unsigned char                   featuresreg;
-       unsigned char                   sector_count;
-       unsigned char                   sector_number;
-       unsigned char                   cylinder_low;
-       unsigned char                   cylinder_high;
-       unsigned char                   drive_head;
-       unsigned char                   commandreg;
-       unsigned int                    timestamp;
-} __attribute__ ((packed)) ata_smart_errorlog_command_struct_t;
-
-typedef struct ata_smart_errorlog_error_struct_s {
-       unsigned char                   error_condition;
-       unsigned char                   extended_error[14];
-       unsigned char                   state;
-       unsigned short                  timestamp;
-} __attribute__ ((packed)) ata_smart_errorlog_error_struct_t;
-
-typedef struct ata_smart_errorlog_struct_s {
-       ata_smart_errorlog_command_struct_t     commands[6];
-       ata_smart_errorlog_error_struct_t       error_struct;
-} __attribute__ ((packed)) ata_smart_errorlog_struct_t;
-
-typedef struct ata_smart_errorlog_s {
-       unsigned char                   revnumber;
-       unsigned char                   error_log_pointer;
-       ata_smart_errorlog_struct_t     errorlog_struct[5];
-       unsigned short                  ata_error_count;
-       unsigned short                  non_fatal_count;
-       unsigned short                  drive_timeout_count;
-       unsigned char                   reserved[53];
-       unsigned char                   chksum;
-} __attribute__ ((packed)) ata_smart_errorlog_t;
-
-typedef struct ata_smart_selftestlog_struct_s {
-       unsigned char                   selftestnumber;
-       unsigned char                   selfteststatus;
-       unsigned short                  timestamp;
-       unsigned char                   selftestfailurecheckpoint;
-       unsigned int                    lbafirstfailure;
-       unsigned char                   vendorspecific[15];
-} __attribute__ ((packed)) ata_smart_selftestlog_struct_t;
-
-typedef struct ata_smart_selftestlog_s {
-       unsigned short                  revnumber;
-       ata_smart_selftestlog_struct_t  selftest_struct[21];
-       unsigned char                   vendorspecific[2];
-       unsigned char                   mostrecenttest;
-       unsigned char                   resevered[2];
-       unsigned char                   chksum;
-} __attribute__ ((packed)) ata_smart_selftestlog_t;
-#endif /* __KERNEL__ */
-
-#endif /* _LINUX_HDSMART_H */
index 5f3e82a..f20410d 100644 (file)
@@ -170,7 +170,6 @@ typedef struct hw_regs_s {
        struct device   *dev;
 } hw_regs_t;
 
-struct hwif_s * ide_find_port(unsigned long);
 void ide_init_port_data(struct hwif_s *, unsigned int);
 void ide_init_port_hw(struct hwif_s *, hw_regs_t *);
 
@@ -522,7 +521,6 @@ typedef struct hwif_s {
        unsigned        reset      : 1; /* reset after probe */
        unsigned        sg_mapped  : 1; /* sg_table and sg_nents are ready */
        unsigned        mmio       : 1; /* host uses MMIO */
-       unsigned        straight8  : 1; /* Alan's straight 8 check */
 
        struct device           gendev;
        struct device           *portdev;
@@ -809,6 +807,13 @@ extern     ide_hwif_t      ide_hwifs[];            /* master data repository */
 #endif
 extern int noautodma;
 
+ide_hwif_t *ide_find_port_slot(const struct ide_port_info *);
+
+static inline ide_hwif_t *ide_find_port(void)
+{
+       return ide_find_port_slot(NULL);
+}
+
 extern int ide_end_request (ide_drive_t *drive, int uptodate, int nrsecs);
 int ide_end_dequeued_request(ide_drive_t *drive, struct request *rq,
                             int uptodate, int nr_sectors);
@@ -1027,8 +1032,8 @@ enum {
        IDE_HFLAG_SINGLE                = (1 << 1),
        /* don't use legacy PIO blacklist */
        IDE_HFLAG_PIO_NO_BLACKLIST      = (1 << 2),
-       /* don't use conservative PIO "downgrade" */
-       IDE_HFLAG_PIO_NO_DOWNGRADE      = (1 << 3),
+       /* set for the second port of QD65xx */
+       IDE_HFLAG_QD_2ND_PORT           = (1 << 3),
        /* use PIO8/9 for prefetch off/on */
        IDE_HFLAG_ABUSE_PREFETCH        = (1 << 4),
        /* use PIO6/7 for fast-devsel off/on */
@@ -1050,8 +1055,8 @@ enum {
        IDE_HFLAG_VDMA                  = (1 << 11),
        /* ATAPI DMA is unsupported */
        IDE_HFLAG_NO_ATAPI_DMA          = (1 << 12),
-       /* set if host is a "bootable" controller */
-       IDE_HFLAG_BOOTABLE              = (1 << 13),
+       /* set if host is a "non-bootable" controller */
+       IDE_HFLAG_NON_BOOTABLE          = (1 << 13),
        /* host doesn't support DMA */
        IDE_HFLAG_NO_DMA                = (1 << 14),
        /* check if host is PCI IDE device before allowing DMA */
@@ -1079,8 +1084,6 @@ enum {
        /* unmask IRQs */
        IDE_HFLAG_UNMASK_IRQS           = (1 << 25),
        IDE_HFLAG_ABUSE_SET_DMA_MODE    = (1 << 26),
-       /* host is CY82C693 */
-       IDE_HFLAG_CY82C693              = (1 << 27),
        /* force host out of "simplex" mode */
        IDE_HFLAG_CLEAR_SIMPLEX         = (1 << 28),
        /* DSC overlap is unsupported */
@@ -1092,9 +1095,9 @@ enum {
 };
 
 #ifdef CONFIG_BLK_DEV_OFFBOARD
-# define IDE_HFLAG_OFF_BOARD   IDE_HFLAG_BOOTABLE
-#else
 # define IDE_HFLAG_OFF_BOARD   0
+#else
+# define IDE_HFLAG_OFF_BOARD   IDE_HFLAG_NON_BOOTABLE
 #endif
 
 struct ide_port_info {
index efb618f..cb46bef 100644 (file)
@@ -1787,7 +1787,7 @@ bad_unshare_out:
 int unshare_files(struct files_struct **displaced)
 {
        struct task_struct *task = current;
-       struct files_struct *copy;
+       struct files_struct *copy = NULL;
        int error;
 
        error = unshare_fd(CLONE_FILES, &copy);