Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * This file is subject to the terms and conditions of the GNU General Public
0003  * License.  See the file "COPYING" in the main directory of this archive
0004  * for more details.
0005  *
0006  * Copyright (C) 1994-1996  Linus Torvalds & authors
0007  *
0008  * Copied from i386; many of the especially older MIPS or ISA-based platforms
0009  * are basically identical.  Using this file probably implies i8259 PIC
0010  * support in a system but the very least interrupt numbers 0 - 15 need to
0011  * be put aside for legacy devices.
0012  */
0013 #ifndef __ASM_MACH_GENERIC_IDE_H
0014 #define __ASM_MACH_GENERIC_IDE_H
0015 
0016 #ifdef __KERNEL__
0017 
0018 #include <linux/pci.h>
0019 #include <linux/stddef.h>
0020 #include <asm/processor.h>
0021 
0022 /* MIPS port and memory-mapped I/O string operations.  */
0023 static inline void __ide_flush_prologue(void)
0024 {
0025 #ifdef CONFIG_SMP
0026     if (cpu_has_dc_aliases || !cpu_has_ic_fills_f_dc)
0027         preempt_disable();
0028 #endif
0029 }
0030 
0031 static inline void __ide_flush_epilogue(void)
0032 {
0033 #ifdef CONFIG_SMP
0034     if (cpu_has_dc_aliases || !cpu_has_ic_fills_f_dc)
0035         preempt_enable();
0036 #endif
0037 }
0038 
0039 static inline void __ide_flush_dcache_range(unsigned long addr, unsigned long size)
0040 {
0041     if (cpu_has_dc_aliases || !cpu_has_ic_fills_f_dc) {
0042         unsigned long end = addr + size;
0043 
0044         while (addr < end) {
0045             local_flush_data_cache_page((void *)addr);
0046             addr += PAGE_SIZE;
0047         }
0048     }
0049 }
0050 
0051 /*
0052  * insw() and gang might be called with interrupts disabled, so we can't
0053  * send IPIs for flushing due to the potencial of deadlocks, see the comment
0054  * above smp_call_function() in arch/mips/kernel/smp.c.  We work around the
0055  * problem by disabling preemption so we know we actually perform the flush
0056  * on the processor that actually has the lines to be flushed which hopefully
0057  * is even better for performance anyway.
0058  */
0059 static inline void __ide_insw(unsigned long port, void *addr,
0060     unsigned int count)
0061 {
0062     __ide_flush_prologue();
0063     insw(port, addr, count);
0064     __ide_flush_dcache_range((unsigned long)addr, count * 2);
0065     __ide_flush_epilogue();
0066 }
0067 
0068 static inline void __ide_insl(unsigned long port, void *addr, unsigned int count)
0069 {
0070     __ide_flush_prologue();
0071     insl(port, addr, count);
0072     __ide_flush_dcache_range((unsigned long)addr, count * 4);
0073     __ide_flush_epilogue();
0074 }
0075 
0076 static inline void __ide_outsw(unsigned long port, const void *addr,
0077     unsigned long count)
0078 {
0079     __ide_flush_prologue();
0080     outsw(port, addr, count);
0081     __ide_flush_dcache_range((unsigned long)addr, count * 2);
0082     __ide_flush_epilogue();
0083 }
0084 
0085 static inline void __ide_outsl(unsigned long port, const void *addr,
0086     unsigned long count)
0087 {
0088     __ide_flush_prologue();
0089     outsl(port, addr, count);
0090     __ide_flush_dcache_range((unsigned long)addr, count * 4);
0091     __ide_flush_epilogue();
0092 }
0093 
0094 static inline void __ide_mm_insw(void __iomem *port, void *addr, u32 count)
0095 {
0096     __ide_flush_prologue();
0097     readsw(port, addr, count);
0098     __ide_flush_dcache_range((unsigned long)addr, count * 2);
0099     __ide_flush_epilogue();
0100 }
0101 
0102 static inline void __ide_mm_insl(void __iomem *port, void *addr, u32 count)
0103 {
0104     __ide_flush_prologue();
0105     readsl(port, addr, count);
0106     __ide_flush_dcache_range((unsigned long)addr, count * 4);
0107     __ide_flush_epilogue();
0108 }
0109 
0110 static inline void __ide_mm_outsw(void __iomem *port, void *addr, u32 count)
0111 {
0112     __ide_flush_prologue();
0113     writesw(port, addr, count);
0114     __ide_flush_dcache_range((unsigned long)addr, count * 2);
0115     __ide_flush_epilogue();
0116 }
0117 
0118 static inline void __ide_mm_outsl(void __iomem * port, void *addr, u32 count)
0119 {
0120     __ide_flush_prologue();
0121     writesl(port, addr, count);
0122     __ide_flush_dcache_range((unsigned long)addr, count * 4);
0123     __ide_flush_epilogue();
0124 }
0125 
0126 /* ide_insw calls insw, not __ide_insw.  Why? */
0127 #undef insw
0128 #undef insl
0129 #undef outsw
0130 #undef outsl
0131 #define insw(port, addr, count) __ide_insw(port, addr, count)
0132 #define insl(port, addr, count) __ide_insl(port, addr, count)
0133 #define outsw(port, addr, count) __ide_outsw(port, addr, count)
0134 #define outsl(port, addr, count) __ide_outsl(port, addr, count)
0135 
0136 #endif /* __KERNEL__ */
0137 
0138 #endif /* __ASM_MACH_GENERIC_IDE_H */