73008f7bdc93708281e647889a7e3d6c6be87c41
[linux-2.6.git] / include / asm-mips / mach-generic / ide.h
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 static __inline__ int ide_probe_legacy(void)
23 {
24 #ifdef CONFIG_PCI
25         struct pci_dev *dev;
26         /*
27          * This can be called on the ide_setup() path, super-early in
28          * boot.  But the down_read() will enable local interrupts,
29          * which can cause some machines to crash.  So here we detect
30          * and flag that situation and bail out early.
31          */
32         if (no_pci_devices())
33                 return 0;
34         dev = pci_get_class(PCI_CLASS_BRIDGE_EISA << 8, NULL);
35         if (dev)
36                 goto found;
37         dev = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, NULL);
38         if (dev)
39                 goto found;
40         return 0;
41 found:
42         pci_dev_put(dev);
43         return 1;
44 #elif defined(CONFIG_EISA) || defined(CONFIG_ISA)
45         return 1;
46 #else
47         return 0;
48 #endif
49 }
50
51 /* MIPS port and memory-mapped I/O string operations.  */
52 static inline void __ide_flush_prologue(void)
53 {
54 #ifdef CONFIG_SMP
55         if (cpu_has_dc_aliases)
56                 preempt_disable();
57 #endif
58 }
59
60 static inline void __ide_flush_epilogue(void)
61 {
62 #ifdef CONFIG_SMP
63         if (cpu_has_dc_aliases)
64                 preempt_enable();
65 #endif
66 }
67
68 static inline void __ide_flush_dcache_range(unsigned long addr, unsigned long size)
69 {
70         if (cpu_has_dc_aliases) {
71                 unsigned long end = addr + size;
72
73                 while (addr < end) {
74                         local_flush_data_cache_page((void *)addr);
75                         addr += PAGE_SIZE;
76                 }
77         }
78 }
79
80 /*
81  * insw() and gang might be called with interrupts disabled, so we can't
82  * send IPIs for flushing due to the potencial of deadlocks, see the comment
83  * above smp_call_function() in arch/mips/kernel/smp.c.  We work around the
84  * problem by disabling preemption so we know we actually perform the flush
85  * on the processor that actually has the lines to be flushed which hopefully
86  * is even better for performance anyway.
87  */
88 static inline void __ide_insw(unsigned long port, void *addr,
89         unsigned int count)
90 {
91         __ide_flush_prologue();
92         insw(port, addr, count);
93         __ide_flush_dcache_range((unsigned long)addr, count * 2);
94         __ide_flush_epilogue();
95 }
96
97 static inline void __ide_insl(unsigned long port, void *addr, unsigned int count)
98 {
99         __ide_flush_prologue();
100         insl(port, addr, count);
101         __ide_flush_dcache_range((unsigned long)addr, count * 4);
102         __ide_flush_epilogue();
103 }
104
105 static inline void __ide_outsw(unsigned long port, const void *addr,
106         unsigned long count)
107 {
108         __ide_flush_prologue();
109         outsw(port, addr, count);
110         __ide_flush_dcache_range((unsigned long)addr, count * 2);
111         __ide_flush_epilogue();
112 }
113
114 static inline void __ide_outsl(unsigned long port, const void *addr,
115         unsigned long count)
116 {
117         __ide_flush_prologue();
118         outsl(port, addr, count);
119         __ide_flush_dcache_range((unsigned long)addr, count * 4);
120         __ide_flush_epilogue();
121 }
122
123 static inline void __ide_mm_insw(void __iomem *port, void *addr, u32 count)
124 {
125         __ide_flush_prologue();
126         readsw(port, addr, count);
127         __ide_flush_dcache_range((unsigned long)addr, count * 2);
128         __ide_flush_epilogue();
129 }
130
131 static inline void __ide_mm_insl(void __iomem *port, void *addr, u32 count)
132 {
133         __ide_flush_prologue();
134         readsl(port, addr, count);
135         __ide_flush_dcache_range((unsigned long)addr, count * 4);
136         __ide_flush_epilogue();
137 }
138
139 static inline void __ide_mm_outsw(void __iomem *port, void *addr, u32 count)
140 {
141         __ide_flush_prologue();
142         writesw(port, addr, count);
143         __ide_flush_dcache_range((unsigned long)addr, count * 2);
144         __ide_flush_epilogue();
145 }
146
147 static inline void __ide_mm_outsl(void __iomem * port, void *addr, u32 count)
148 {
149         __ide_flush_prologue();
150         writesl(port, addr, count);
151         __ide_flush_dcache_range((unsigned long)addr, count * 4);
152         __ide_flush_epilogue();
153 }
154
155 /* ide_insw calls insw, not __ide_insw.  Why? */
156 #undef insw
157 #undef insl
158 #undef outsw
159 #undef outsl
160 #define insw(port, addr, count) __ide_insw(port, addr, count)
161 #define insl(port, addr, count) __ide_insl(port, addr, count)
162 #define outsw(port, addr, count) __ide_outsw(port, addr, count)
163 #define outsl(port, addr, count) __ide_outsl(port, addr, count)
164
165 #endif /* __KERNEL__ */
166
167 #endif /* __ASM_MACH_GENERIC_IDE_H */