linux/arch/mips/include/asm/mach-generic/ide.h
<<
>>
Prefs
   1/*
   2 * This file is subject to the terms and conditions of the GNU General Public
   3 * License.  See the file "COPYING" in the main directory of this archive
   4 * for more details.
   5 *
   6 * Copyright (C) 1994-1996  Linus Torvalds & authors
   7 *
   8 * Copied from i386; many of the especially older MIPS or ISA-based platforms
   9 * are basically identical.  Using this file probably implies i8259 PIC
  10 * support in a system but the very least interrupt numbers 0 - 15 need to
  11 * be put aside for legacy devices.
  12 */
  13#ifndef __ASM_MACH_GENERIC_IDE_H
  14#define __ASM_MACH_GENERIC_IDE_H
  15
  16#ifdef __KERNEL__
  17
  18#include <linux/pci.h>
  19#include <linux/stddef.h>
  20#include <asm/processor.h>
  21
  22/* MIPS port and memory-mapped I/O string operations.  */
  23static inline void __ide_flush_prologue(void)
  24{
  25#ifdef CONFIG_SMP
  26        if (cpu_has_dc_aliases || !cpu_has_ic_fills_f_dc)
  27                preempt_disable();
  28#endif
  29}
  30
  31static inline void __ide_flush_epilogue(void)
  32{
  33#ifdef CONFIG_SMP
  34        if (cpu_has_dc_aliases || !cpu_has_ic_fills_f_dc)
  35                preempt_enable();
  36#endif
  37}
  38
  39static inline void __ide_flush_dcache_range(unsigned long addr, unsigned long size)
  40{
  41        if (cpu_has_dc_aliases || !cpu_has_ic_fills_f_dc) {
  42                unsigned long end = addr + size;
  43
  44                while (addr < end) {
  45                        local_flush_data_cache_page((void *)addr);
  46                        addr += PAGE_SIZE;
  47                }
  48        }
  49}
  50
  51/*
  52 * insw() and gang might be called with interrupts disabled, so we can't
  53 * send IPIs for flushing due to the potencial of deadlocks, see the comment
  54 * above smp_call_function() in arch/mips/kernel/smp.c.  We work around the
  55 * problem by disabling preemption so we know we actually perform the flush
  56 * on the processor that actually has the lines to be flushed which hopefully
  57 * is even better for performance anyway.
  58 */
  59static inline void __ide_insw(unsigned long port, void *addr,
  60        unsigned int count)
  61{
  62        __ide_flush_prologue();
  63        insw(port, addr, count);
  64        __ide_flush_dcache_range((unsigned long)addr, count * 2);
  65        __ide_flush_epilogue();
  66}
  67
  68static inline void __ide_insl(unsigned long port, void *addr, unsigned int count)
  69{
  70        __ide_flush_prologue();
  71        insl(port, addr, count);
  72        __ide_flush_dcache_range((unsigned long)addr, count * 4);
  73        __ide_flush_epilogue();
  74}
  75
  76static inline void __ide_outsw(unsigned long port, const void *addr,
  77        unsigned long count)
  78{
  79        __ide_flush_prologue();
  80        outsw(port, addr, count);
  81        __ide_flush_dcache_range((unsigned long)addr, count * 2);
  82        __ide_flush_epilogue();
  83}
  84
  85static inline void __ide_outsl(unsigned long port, const void *addr,
  86        unsigned long count)
  87{
  88        __ide_flush_prologue();
  89        outsl(port, addr, count);
  90        __ide_flush_dcache_range((unsigned long)addr, count * 4);
  91        __ide_flush_epilogue();
  92}
  93
  94static inline void __ide_mm_insw(void __iomem *port, void *addr, u32 count)
  95{
  96        __ide_flush_prologue();
  97        readsw(port, addr, count);
  98        __ide_flush_dcache_range((unsigned long)addr, count * 2);
  99        __ide_flush_epilogue();
 100}
 101
 102static inline void __ide_mm_insl(void __iomem *port, void *addr, u32 count)
 103{
 104        __ide_flush_prologue();
 105        readsl(port, addr, count);
 106        __ide_flush_dcache_range((unsigned long)addr, count * 4);
 107        __ide_flush_epilogue();
 108}
 109
 110static inline void __ide_mm_outsw(void __iomem *port, void *addr, u32 count)
 111{
 112        __ide_flush_prologue();
 113        writesw(port, addr, count);
 114        __ide_flush_dcache_range((unsigned long)addr, count * 2);
 115        __ide_flush_epilogue();
 116}
 117
 118static inline void __ide_mm_outsl(void __iomem * port, void *addr, u32 count)
 119{
 120        __ide_flush_prologue();
 121        writesl(port, addr, count);
 122        __ide_flush_dcache_range((unsigned long)addr, count * 4);
 123        __ide_flush_epilogue();
 124}
 125
 126/* ide_insw calls insw, not __ide_insw.  Why? */
 127#undef insw
 128#undef insl
 129#undef outsw
 130#undef outsl
 131#define insw(port, addr, count) __ide_insw(port, addr, count)
 132#define insl(port, addr, count) __ide_insl(port, addr, count)
 133#define outsw(port, addr, count) __ide_outsw(port, addr, count)
 134#define outsl(port, addr, count) __ide_outsl(port, addr, count)
 135
 136#endif /* __KERNEL__ */
 137
 138#endif /* __ASM_MACH_GENERIC_IDE_H */
 139