1 |
199 |
simons |
#ifndef __ALPHA_IO_H
|
2 |
|
|
#define __ALPHA_IO_H
|
3 |
|
|
|
4 |
|
|
#include <linux/config.h>
|
5 |
|
|
|
6 |
|
|
#include <asm/system.h>
|
7 |
|
|
|
8 |
|
|
/* We don't use IO slowdowns on the alpha, but.. */
|
9 |
|
|
#define __SLOW_DOWN_IO do { } while (0)
|
10 |
|
|
#define SLOW_DOWN_IO do { } while (0)
|
11 |
|
|
|
12 |
|
|
/*
|
13 |
|
|
* The hae (hardware address extension) register is used to
|
14 |
|
|
* access high IO addresses. To avoid doing an external cycle
|
15 |
|
|
* every time we need to set the hae, we have a hae cache in
|
16 |
|
|
* memory. The kernel entry code makes sure that the hae is
|
17 |
|
|
* preserved across interrupts, so it is safe to set the hae
|
18 |
|
|
* once and then depend on it staying the same in kernel code.
|
19 |
|
|
*/
|
20 |
|
|
extern struct hae {
|
21 |
|
|
unsigned long cache;
|
22 |
|
|
unsigned long *reg;
|
23 |
|
|
} hae;
|
24 |
|
|
|
25 |
|
|
/*
|
26 |
|
|
* Virtual -> physical identity mapping starts at this offset
|
27 |
|
|
*/
|
28 |
|
|
#ifdef USE_48_BIT_KSEG
|
29 |
|
|
#define IDENT_ADDR (0xffff800000000000UL)
|
30 |
|
|
#else
|
31 |
|
|
#define IDENT_ADDR (0xfffffc0000000000UL)
|
32 |
|
|
#endif
|
33 |
|
|
|
34 |
|
|
#ifdef __KERNEL__
|
35 |
|
|
|
36 |
|
|
/*
|
37 |
|
|
* We try to avoid hae updates (thus the cache), but when we
|
38 |
|
|
* do need to update the hae, we need to do it atomically, so
|
39 |
|
|
* that any interrupts wouldn't get confused with the hae
|
40 |
|
|
* register not being up-to-date with respect to the hardware
|
41 |
|
|
* value.
|
42 |
|
|
*/
|
43 |
|
|
extern inline void set_hae(unsigned long new_hae)
|
44 |
|
|
{
|
45 |
|
|
unsigned long ipl = swpipl(7);
|
46 |
|
|
hae.cache = new_hae;
|
47 |
|
|
*hae.reg = new_hae;
|
48 |
|
|
mb();
|
49 |
|
|
new_hae = *hae.reg; /* read to make sure it was written */
|
50 |
|
|
setipl(ipl);
|
51 |
|
|
}
|
52 |
|
|
|
53 |
|
|
/*
|
54 |
|
|
* Change virtual addresses to physical addresses and vv.
|
55 |
|
|
*/
|
56 |
|
|
extern inline unsigned long virt_to_phys(volatile void * address)
|
57 |
|
|
{
|
58 |
|
|
return 0xffffffffUL & (unsigned long) address;
|
59 |
|
|
}
|
60 |
|
|
|
61 |
|
|
extern inline void * phys_to_virt(unsigned long address)
|
62 |
|
|
{
|
63 |
|
|
return (void *) (address + IDENT_ADDR);
|
64 |
|
|
}
|
65 |
|
|
|
66 |
|
|
#else /* !__KERNEL__ */
|
67 |
|
|
|
68 |
|
|
/*
|
69 |
|
|
* Define actual functions in private name-space so it's easier to
|
70 |
|
|
* accommodate things like XFree or svgalib that like to define their
|
71 |
|
|
* own versions of inb etc.
|
72 |
|
|
*/
|
73 |
|
|
extern void __sethae (unsigned long addr); /* syscall */
|
74 |
|
|
extern void _sethae (unsigned long addr); /* cached version */
|
75 |
|
|
|
76 |
|
|
#endif /* !__KERNEL__ */
|
77 |
|
|
|
78 |
|
|
/*
|
79 |
|
|
* There are different chipsets to interface the Alpha CPUs to the world.
|
80 |
|
|
*/
|
81 |
|
|
#if defined(CONFIG_ALPHA_LCA)
|
82 |
|
|
# include <asm/lca.h> /* get chip-specific definitions */
|
83 |
|
|
#elif defined(CONFIG_ALPHA_APECS)
|
84 |
|
|
# include <asm/apecs.h> /* get chip-specific definitions */
|
85 |
|
|
#elif defined(CONFIG_ALPHA_CIA)
|
86 |
|
|
# include <asm/cia.h> /* get chip-specific definitions */
|
87 |
|
|
#elif defined(CONFIG_ALPHA_T2)
|
88 |
|
|
# include <asm/t2.h> /* get chip-specific definitions */
|
89 |
|
|
#elif defined(CONFIG_ALPHA_PYXIS)
|
90 |
|
|
# include <asm/pyxis.h> /* get chip-specific definitions */
|
91 |
|
|
#else
|
92 |
|
|
# include <asm/jensen.h>
|
93 |
|
|
#endif
|
94 |
|
|
|
95 |
|
|
/*
|
96 |
|
|
* The convention used for inb/outb etc. is that names starting with
|
97 |
|
|
* two underscores are the inline versions, names starting with a
|
98 |
|
|
* single underscore are proper functions, and names starting with a
|
99 |
|
|
* letter are macros that map in some way to inline or proper function
|
100 |
|
|
* versions. Not all that pretty, but before you change it, be sure
|
101 |
|
|
* to convince yourself that it won't break anything (in particular
|
102 |
|
|
* module support).
|
103 |
|
|
*/
|
104 |
|
|
extern unsigned int _inb (unsigned long port);
|
105 |
|
|
extern unsigned int _inw (unsigned long port);
|
106 |
|
|
extern unsigned int _inl (unsigned long port);
|
107 |
|
|
extern void _outb (unsigned char b,unsigned long port);
|
108 |
|
|
extern void _outw (unsigned short w,unsigned long port);
|
109 |
|
|
extern void _outl (unsigned int l,unsigned long port);
|
110 |
|
|
extern unsigned long _readb(unsigned long addr);
|
111 |
|
|
extern unsigned long _readw(unsigned long addr);
|
112 |
|
|
extern unsigned long _readl(unsigned long addr);
|
113 |
|
|
extern void _writeb(unsigned char b, unsigned long addr);
|
114 |
|
|
extern void _writew(unsigned short b, unsigned long addr);
|
115 |
|
|
extern void _writel(unsigned int b, unsigned long addr);
|
116 |
|
|
|
117 |
|
|
/*
|
118 |
|
|
* The platform header files may define some of these macros to use
|
119 |
|
|
* the inlined versions where appropriate. These macros may also be
|
120 |
|
|
* redefined by userlevel programs.
|
121 |
|
|
*/
|
122 |
|
|
#ifndef inb
|
123 |
|
|
# define inb(p) _inb((p))
|
124 |
|
|
#endif
|
125 |
|
|
#ifndef inw
|
126 |
|
|
# define inw(p) _inw((p))
|
127 |
|
|
#endif
|
128 |
|
|
#ifndef inl
|
129 |
|
|
# define inl(p) _inl((p))
|
130 |
|
|
#endif
|
131 |
|
|
#ifndef outb
|
132 |
|
|
# define outb(b,p) _outb((b),(p))
|
133 |
|
|
#endif
|
134 |
|
|
#ifndef outw
|
135 |
|
|
# define outw(w,p) _outw((w),(p))
|
136 |
|
|
#endif
|
137 |
|
|
#ifndef outl
|
138 |
|
|
# define outl(l,p) _outl((l),(p))
|
139 |
|
|
#endif
|
140 |
|
|
|
141 |
|
|
#ifndef inb_p
|
142 |
|
|
# define inb_p inb
|
143 |
|
|
#endif
|
144 |
|
|
#ifndef inw_p
|
145 |
|
|
# define inw_p inw
|
146 |
|
|
#endif
|
147 |
|
|
#ifndef inl_p
|
148 |
|
|
# define inl_p inl
|
149 |
|
|
#endif
|
150 |
|
|
|
151 |
|
|
#ifndef outb_p
|
152 |
|
|
# define outb_p outb
|
153 |
|
|
#endif
|
154 |
|
|
#ifndef outw_p
|
155 |
|
|
# define outw_p outw
|
156 |
|
|
#endif
|
157 |
|
|
#ifndef outl_p
|
158 |
|
|
# define outl_p outl
|
159 |
|
|
#endif
|
160 |
|
|
|
161 |
|
|
/*
|
162 |
|
|
* The "address" in IO memory space is not clearly either an integer or a
|
163 |
|
|
* pointer. We will accept both, thus the casts.
|
164 |
|
|
*
|
165 |
|
|
* On the alpha, we have the whole physical address space mapped at all
|
166 |
|
|
* times, so "ioremap()" and "iounmap()" do not need to do anything.
|
167 |
|
|
*/
|
168 |
|
|
extern inline void * ioremap(unsigned long offset, unsigned long size)
|
169 |
|
|
{
|
170 |
|
|
return (void *) offset;
|
171 |
|
|
}
|
172 |
|
|
|
173 |
|
|
extern inline void iounmap(void *addr)
|
174 |
|
|
{
|
175 |
|
|
}
|
176 |
|
|
|
177 |
|
|
#ifndef readb
|
178 |
|
|
# define readb(a) _readb((unsigned long)(a))
|
179 |
|
|
#endif
|
180 |
|
|
#ifndef readw
|
181 |
|
|
# define readw(a) _readw((unsigned long)(a))
|
182 |
|
|
#endif
|
183 |
|
|
#ifndef readl
|
184 |
|
|
# define readl(a) _readl((unsigned long)(a))
|
185 |
|
|
#endif
|
186 |
|
|
#ifndef writeb
|
187 |
|
|
# define writeb(v,a) _writeb((v),(unsigned long)(a))
|
188 |
|
|
#endif
|
189 |
|
|
#ifndef writew
|
190 |
|
|
# define writew(v,a) _writew((v),(unsigned long)(a))
|
191 |
|
|
#endif
|
192 |
|
|
#ifndef writel
|
193 |
|
|
# define writel(v,a) _writel((v),(unsigned long)(a))
|
194 |
|
|
#endif
|
195 |
|
|
|
196 |
|
|
#ifdef __KERNEL__
|
197 |
|
|
|
198 |
|
|
/*
|
199 |
|
|
* String version of IO memory access ops:
|
200 |
|
|
*/
|
201 |
|
|
extern void _memcpy_fromio(void *, unsigned long, unsigned long);
|
202 |
|
|
extern void _memcpy_toio(unsigned long, void *, unsigned long);
|
203 |
|
|
extern void _memset_io(unsigned long, int, unsigned long);
|
204 |
|
|
|
205 |
|
|
#define memcpy_fromio(to,from,len) _memcpy_fromio((to),(unsigned long)(from),(len))
|
206 |
|
|
#define memcpy_toio(to,from,len) _memcpy_toio((unsigned long)(to),(from),(len))
|
207 |
|
|
#define memset_io(addr,c,len) _memset_io((unsigned long)(addr),(c),(len))
|
208 |
|
|
|
209 |
|
|
/*
|
210 |
|
|
* String versions of in/out ops:
|
211 |
|
|
*/
|
212 |
|
|
extern void insb (unsigned long port, void *dst, unsigned long count);
|
213 |
|
|
extern void insw (unsigned long port, void *dst, unsigned long count);
|
214 |
|
|
extern void insl (unsigned long port, void *dst, unsigned long count);
|
215 |
|
|
extern void outsb (unsigned long port, const void *src, unsigned long count);
|
216 |
|
|
extern void outsw (unsigned long port, const void *src, unsigned long count);
|
217 |
|
|
extern void outsl (unsigned long port, const void *src, unsigned long count);
|
218 |
|
|
|
219 |
|
|
/*
|
220 |
|
|
* XXX - We don't have csum_partial_copy_fromio() yet, so we cheat here and
|
221 |
|
|
* just copy it. The net code will then do the checksum later. Presently
|
222 |
|
|
* only used by some shared memory 8390 ethernet cards anyway.
|
223 |
|
|
*/
|
224 |
|
|
|
225 |
|
|
#define eth_io_copy_and_sum(skb,src,len,unused) memcpy_fromio((skb)->data,(src),(len))
|
226 |
|
|
|
227 |
|
|
static inline int check_signature(unsigned long io_addr,
|
228 |
|
|
const unsigned char *signature, int length)
|
229 |
|
|
{
|
230 |
|
|
int retval = 0;
|
231 |
|
|
do {
|
232 |
|
|
if (readb(io_addr) != *signature)
|
233 |
|
|
goto out;
|
234 |
|
|
io_addr++;
|
235 |
|
|
signature++;
|
236 |
|
|
length--;
|
237 |
|
|
} while (length);
|
238 |
|
|
retval = 1;
|
239 |
|
|
out:
|
240 |
|
|
return retval;
|
241 |
|
|
}
|
242 |
|
|
|
243 |
|
|
#endif /* __KERNEL__ */
|
244 |
|
|
|
245 |
|
|
#endif
|