summaryrefslogtreecommitdiffstats
path: root/include/asm-alpha/io.h
blob: 51d2af5968920e6f98ab422a463672dd1050568e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
#ifndef __ALPHA_IO_H
#define __ALPHA_IO_H

#include <linux/config.h>
#include <asm/system.h>
#include <asm/machvec.h>

/* We don't use IO slowdowns on the Alpha, but.. */
#define __SLOW_DOWN_IO	do { } while (0)
#define SLOW_DOWN_IO	do { } while (0)

/*
 * Virtual -> physical identity mapping starts at this offset
 */
#ifdef USE_48_BIT_KSEG
#define IDENT_ADDR     0xffff800000000000
#else
#define IDENT_ADDR     0xfffffc0000000000
#endif

#ifdef __KERNEL__

/*
 * We try to avoid hae updates (thus the cache), but when we
 * do need to update the hae, we need to do it atomically, so
 * that any interrupts wouldn't get confused with the hae
 * register not being up-to-date with respect to the hardware
 * value.
 */
static inline void __set_hae(unsigned long new_hae)
{
	unsigned long ipl = swpipl(7);

	alpha_mv.hae_cache = new_hae;
	*alpha_mv.hae_register = new_hae;
	mb();

	/* Re-read to make sure it was written.  */
	new_hae = *alpha_mv.hae_register;
	setipl(ipl);
}

static inline void set_hae(unsigned long new_hae)
{
	if (new_hae != alpha_mv.hae_cache)
		__set_hae(new_hae);
}

/*
 * Change virtual addresses to physical addresses and vv.
 */
static inline unsigned long virt_to_phys(volatile void * address)
{
	/* Conditionalize this on the CPU?  This here is 40 bits,
	   whereas EV4 only supports 34.  But KSEG is farther out
	   so it shouldn't _really_ matter.  */
	return 0xffffffffffUL & (unsigned long) address;
}

static inline void * phys_to_virt(unsigned long address)
{
	return (void *) (address + IDENT_ADDR);
}

#else /* !__KERNEL__ */

/*
 * Define actual functions in private name-space so it's easier to
 * accommodate things like XFree or svgalib that like to define their
 * own versions of inb etc.
 */
extern void __sethae (unsigned long addr);	/* syscall */
extern void _sethae (unsigned long addr);	/* cached version */

#endif /* !__KERNEL__ */

/*
 * There are different chipsets to interface the Alpha CPUs to the world.
 */

#ifdef CONFIG_ALPHA_GENERIC

/* In a generic kernel, we always go through the machine vector.  */

# define virt_to_bus(a)	alpha_mv.mv_virt_to_bus(a)
# define bus_to_virt(a)	alpha_mv.mv_bus_to_virt(a)

# define __inb		alpha_mv.mv_inb
# define __inw		alpha_mv.mv_inw
# define __inl		alpha_mv.mv_inl
# define __outb		alpha_mv.mv_outb
# define __outw		alpha_mv.mv_outw
# define __outl		alpha_mv.mv_outl

# define __readb(a)	alpha_mv.mv_readb((unsigned long)(a))
# define __readw(a)	alpha_mv.mv_readw((unsigned long)(a))
# define __readl(a)	alpha_mv.mv_readl((unsigned long)(a))
# define __readq(a)	alpha_mv.mv_readq((unsigned long)(a))
# define __writeb(v,a)	alpha_mv.mv_writeb((v),(unsigned long)(a))
# define __writew(v,a)	alpha_mv.mv_writew((v),(unsigned long)(a))
# define __writel(v,a)	alpha_mv.mv_writel((v),(unsigned long)(a))
# define __writeq(v,a)	alpha_mv.mv_writeq((v),(unsigned long)(a))

# define inb		__inb
# define inw		__inw
# define inl		__inl
# define outb		__outb
# define outw		__outw
# define outl		__outl

# define readb		__readb
# define readw		__readw
# define readl		__readl
# define readq		__readq
# define writeb		__writeb
# define writew		__writew
# define writel		__writel
# define writeq		__writeq

# define dense_mem(a)	alpha_mv.mv_dense_mem(a)

#else

/* Control how and what gets defined within the core logic headers.  */
#define __WANT_IO_DEF

#if defined(CONFIG_ALPHA_APECS)
# include <asm/core_apecs.h>
#elif defined(CONFIG_ALPHA_CIA)
# include <asm/core_cia.h>
#elif defined(CONFIG_ALPHA_LCA)
# include <asm/core_lca.h>
#elif defined(CONFIG_ALPHA_MCPCIA)
# include <asm/core_mcpcia.h>
#elif defined(CONFIG_ALPHA_PYXIS)
# include <asm/core_pyxis.h>
#elif defined(CONFIG_ALPHA_T2)
# include <asm/core_t2.h>
#elif defined(CONFIG_ALPHA_TSUNAMI)
# include <asm/core_tsunami.h>
#elif defined(CONFIG_ALPHA_JENSEN)
# include <asm/jensen.h>
#else
#error "What system is this?"
#endif

#undef __WANT_IO_DEF

#endif /* GENERIC */

/*
 * The convention used for inb/outb etc. is that names starting with
 * two underscores are the inline versions, names starting with a
 * single underscore are proper functions, and names starting with a
 * letter are macros that map in some way to inline or proper function
 * versions.  Not all that pretty, but before you change it, be sure
 * to convince yourself that it won't break anything (in particular
 * module support).
 */
extern unsigned int	_inb (unsigned long port);
extern unsigned int	_inw (unsigned long port);
extern unsigned int	_inl (unsigned long port);
extern void		_outb (unsigned char b,unsigned long port);
extern void		_outw (unsigned short w,unsigned long port);
extern void		_outl (unsigned int l,unsigned long port);
extern unsigned long	_readb(unsigned long addr);
extern unsigned long	_readw(unsigned long addr);
extern unsigned long	_readl(unsigned long addr);
extern unsigned long	_readq(unsigned long addr);
extern void		_writeb(unsigned char b, unsigned long addr);
extern void		_writew(unsigned short b, unsigned long addr);
extern void		_writel(unsigned int b, unsigned long addr);
extern void		_writeq(unsigned long b, unsigned long addr);

/*
 * The platform header files may define some of these macros to use
 * the inlined versions where appropriate.  These macros may also be
 * redefined by userlevel programs.
 */
#ifndef inb
# define inb(p)		_inb((p))
#endif
#ifndef inw
# define inw(p)		_inw((p))
#endif
#ifndef inl
# define inl(p)		_inl((p))
#endif
#ifndef outb
# define outb(b,p)	_outb((b),(p))
#endif
#ifndef outw
# define outw(w,p)	_outw((w),(p))
#endif
#ifndef outl
# define outl(l,p)	_outl((l),(p))
#endif

#ifndef inb_p
# define inb_p		inb
#endif
#ifndef inw_p
# define inw_p		inw
#endif
#ifndef inl_p
# define inl_p		inl
#endif

#ifndef outb_p
# define outb_p		outb
#endif
#ifndef outw_p
# define outw_p		outw
#endif
#ifndef outl_p
# define outl_p		outl
#endif

/*
 * The "address" in IO memory space is not clearly either an integer or a
 * pointer. We will accept both, thus the casts.
 *
 * On the alpha, we have the whole physical address space mapped at all
 * times, so "ioremap()" and "iounmap()" do not need to do anything.
 */
static inline void * ioremap(unsigned long offset, unsigned long size)
{
	return (void *) offset;
} 

static inline void iounmap(void *addr)
{
}

#ifndef readb
# define readb(a)	_readb((unsigned long)(a))
#endif
#ifndef readw
# define readw(a)	_readw((unsigned long)(a))
#endif
#ifndef readl
# define readl(a)	_readl((unsigned long)(a))
#endif
#ifndef readq
# define readq(a)	_readq((unsigned long)(a))
#endif
#ifndef writeb
# define writeb(v,a)	_writeb((v),(unsigned long)(a))
#endif
#ifndef writew
# define writew(v,a)	_writew((v),(unsigned long)(a))
#endif
#ifndef writel
# define writel(v,a)	_writel((v),(unsigned long)(a))
#endif
#ifndef writeq
# define writeq(v,a)	_writeq((v),(unsigned long)(a))
#endif

#ifdef __KERNEL__

/*
 * String version of IO memory access ops:
 */
extern void _memcpy_fromio(void *, unsigned long, long);
extern void _memcpy_toio(unsigned long, void *, long);
extern void _memset_c_io(unsigned long, unsigned long, long);

#define memcpy_fromio(to,from,len) \
  _memcpy_fromio((to),(unsigned long)(from),(len))
#define memcpy_toio(to,from,len) \
  _memcpy_toio((unsigned long)(to),(from),(len))
#define memset_io(addr,c,len) \
  _memset_c_io((unsigned long)(addr),0x0101010101010101UL*(u8)(c),(len))

#define __HAVE_ARCH_MEMSETW_IO
#define memsetw_io(addr,c,len) \
  _memset_c_io((unsigned long)(addr),0x0001000100010001UL*(u16)(c),(len))

/*
 * String versions of in/out ops:
 */
extern void insb (unsigned long port, void *dst, unsigned long count);
extern void insw (unsigned long port, void *dst, unsigned long count);
extern void insl (unsigned long port, void *dst, unsigned long count);
extern void outsb (unsigned long port, const void *src, unsigned long count);
extern void outsw (unsigned long port, const void *src, unsigned long count);
extern void outsl (unsigned long port, const void *src, unsigned long count);

/*
 * XXX - We don't have csum_partial_copy_fromio() yet, so we cheat here and 
 * just copy it. The net code will then do the checksum later. Presently 
 * only used by some shared memory 8390 Ethernet cards anyway.
 */

#define eth_io_copy_and_sum(skb,src,len,unused) \
  memcpy_fromio((skb)->data,(src),(len))

static inline int
check_signature(unsigned long io_addr, const unsigned char *signature,
		int length)
{
	int retval = 0;
	do {
		if (readb(io_addr) != *signature)
			goto out;
		io_addr++;
		signature++;
		length--;
	} while (length);
	retval = 1;
out:
	return retval;
}

/*
 * The Alpha Jensen hardware for some rather strange reason puts
 * the RTC clock at 0x170 instead of 0x70. Probably due to some
 * misguided idea about using 0x70 for NMI stuff.
 *
 * These defines will override the defaults when doing RTC queries
 */

#ifdef CONFIG_ALPHA_GENERIC
# define RTC_PORT(x)	((x) + alpha_mv.rtc_port)
#else
# ifdef CONFIG_ALPHA_JENSEN
#  define RTC_PORT(x)	(0x170+(x))
# else
#  define RTC_PORT(x)	(0x70 + (x))
# endif
#endif
#define RTC_ALWAYS_BCD	0

#endif /* __KERNEL__ */

#endif /* __ALPHA_IO_H */