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#ifndef MAX_HWIFS
23# ifdef CONFIG_BLK_DEV_IDEPCI
24#define MAX_HWIFS	10
25# else
26#define MAX_HWIFS	6
27# endif
28#endif
29
30#define IDE_ARCH_OBSOLETE_DEFAULTS
31
32extern int mips_system_has_legacy_ide;
33
34static __inline__ int ide_probe_legacy(void)
35{
36#ifdef CONFIG_PCI
37	return mips_system_has_legacy_ide;
38#elif defined(CONFIG_EISA) || defined(CONFIG_ISA)
39	return 1;
40#else
41	return 0;
42#endif
43}
44
45static __inline__ int ide_default_irq(unsigned long base)
46{
47	if (ide_probe_legacy())
48		switch (base) {
49		case 0x1f0:
50			return 14;
51		case 0x170:
52			return 15;
53		case 0x1e8:
54			return 11;
55		case 0x168:
56			return 10;
57		case 0x1e0:
58			return 8;
59		case 0x160:
60			return 12;
61		default:
62			return 0;
63		}
64	else
65		return 0;
66}
67
68static __inline__ unsigned long ide_default_io_base(int index)
69{
70	if (ide_probe_legacy())
71		switch (index) {
72		case 0:
73			return 0x1f0;
74		case 1:
75			return 0x170;
76		case 2:
77			return 0x1e8;
78		case 3:
79			return 0x168;
80		case 4:
81			return 0x1e0;
82		case 5:
83			return 0x160;
84		default:
85			return 0;
86		}
87	else
88		return 0;
89}
90
91#define IDE_ARCH_OBSOLETE_INIT
92#define ide_default_io_ctl(base)	((base) + 0x206) /* obsolete */
93
94#ifdef CONFIG_BLK_DEV_IDEPCI
95#define ide_init_default_irq(base)	(0)
96#else
97#define ide_init_default_irq(base)	ide_default_irq(base)
98#endif
99
100/* MIPS port and memory-mapped I/O string operations.  */
101static inline void __ide_flush_prologue(void)
102{
103#ifdef CONFIG_SMP
104	if (cpu_has_dc_aliases)
105		preempt_disable();
106#endif
107}
108
109static inline void __ide_flush_epilogue(void)
110{
111#ifdef CONFIG_SMP
112	if (cpu_has_dc_aliases)
113		preempt_enable();
114#endif
115}
116
117static inline void __ide_flush_dcache_range(unsigned long addr, unsigned long size)
118{
119	if (cpu_has_dc_aliases) {
120		unsigned long end = addr + size;
121
122		while (addr < end) {
123			local_flush_data_cache_page((void *)addr);
124			addr += PAGE_SIZE;
125		}
126	}
127}
128
129static inline void __ide_insw(unsigned long port, void *addr,
130	unsigned int count)
131{
132	__ide_flush_prologue();
133	insw(port, addr, count);
134	__ide_flush_dcache_range((unsigned long)addr, count * 2);
135	__ide_flush_epilogue();
136}
137
138static inline void __ide_insl(unsigned long port, void *addr, unsigned int count)
139{
140	__ide_flush_prologue();
141	insl(port, addr, count);
142	__ide_flush_dcache_range((unsigned long)addr, count * 4);
143	__ide_flush_epilogue();
144}
145
146static inline void __ide_outsw(unsigned long port, const void *addr,
147	unsigned long count)
148{
149	__ide_flush_prologue();
150	outsw(port, addr, count);
151	__ide_flush_dcache_range((unsigned long)addr, count * 2);
152	__ide_flush_epilogue();
153}
154
155static inline void __ide_outsl(unsigned long port, const void *addr,
156	unsigned long count)
157{
158	__ide_flush_prologue();
159	outsl(port, addr, count);
160	__ide_flush_dcache_range((unsigned long)addr, count * 4);
161	__ide_flush_epilogue();
162}
163
164static inline void __ide_mm_insw(void __iomem *port, void *addr, u32 count)
165{
166	__ide_flush_prologue();
167	readsw(port, addr, count);
168	__ide_flush_dcache_range((unsigned long)addr, count * 2);
169	__ide_flush_epilogue();
170}
171
172static inline void __ide_mm_insl(void __iomem *port, void *addr, u32 count)
173{
174	__ide_flush_prologue();
175	readsl(port, addr, count);
176	__ide_flush_dcache_range((unsigned long)addr, count * 4);
177	__ide_flush_epilogue();
178}
179
180static inline void __ide_mm_outsw(void __iomem *port, void *addr, u32 count)
181{
182	__ide_flush_prologue();
183	writesw(port, addr, count);
184	__ide_flush_dcache_range((unsigned long)addr, count * 2);
185	__ide_flush_epilogue();
186}
187
188static inline void __ide_mm_outsl(void __iomem * port, void *addr, u32 count)
189{
190	__ide_flush_prologue();
191	writesl(port, addr, count);
192	__ide_flush_dcache_range((unsigned long)addr, count * 4);
193	__ide_flush_epilogue();
194}
195
196/* ide_insw calls insw, not __ide_insw.  Why? */
197#undef insw
198#undef insl
199#undef outsw
200#undef outsl
201#define insw(port, addr, count) __ide_insw(port, addr, count)
202#define insl(port, addr, count) __ide_insl(port, addr, count)
203#define outsw(port, addr, count) __ide_outsw(port, addr, count)
204#define outsl(port, addr, count) __ide_outsl(port, addr, count)
205
206#endif /* __KERNEL__ */
207
208#endif /* __ASM_MACH_GENERIC_IDE_H */
209