summaryrefslogtreecommitdiffstats
path: root/include/asm-alpha/io.h
blob: 35a9dafc3f30af1cbf170e55e43d872710662a6e (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
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
#ifndef __ALPHA_IO_H
#define __ALPHA_IO_H

#include <linux/config.h>
#include <linux/kernel.h>
#include <asm/system.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__
#include <asm/machvec.h>

/*
 * 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 flags;
	__save_and_cli(flags);

	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;

	__restore_flags(flags);
}

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(void *address)
{
	return (unsigned long)address - IDENT_ADDR;
}

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

/*
 * Change addresses as seen by the kernel (virtual) to addresses as
 * seen by a device (bus), and vice versa.
 *
 * Note that this only works for a limited range of kernel addresses,
 * and very well may not span all memory.  Consider this interface 
 * deprecated in favour of the mapping functions in <asm/pci.h>.
 */
extern unsigned long __direct_map_base;
extern unsigned long __direct_map_size;

static inline unsigned long virt_to_bus(void *address)
{
	unsigned long phys = virt_to_phys(address);
	unsigned long bus = phys + __direct_map_base;
	return phys <= __direct_map_size ? bus : 0;
}

static inline void *bus_to_virt(unsigned long address)
{
	void *virt;

	/* This check is a sanity check but also ensures that bus address 0
	   maps to virtual address 0 which is useful to detect null pointers
	   (the NCR driver is much simpler if NULL pointers are preserved).  */
	address -= __direct_map_base;
	virt = phys_to_virt(address);
	return (long)address <= 0 ? NULL : virt;
}

#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 __KERNEL__
#ifdef CONFIG_ALPHA_GENERIC

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

# define __inb(p)	alpha_mv.mv_inb((unsigned long)(p))
# define __inw(p)	alpha_mv.mv_inw((unsigned long)(p))
# define __inl(p)	alpha_mv.mv_inl((unsigned long)(p))
# define __outb(x,p)	alpha_mv.mv_outb((x),(unsigned long)(p))
# define __outw(x,p)	alpha_mv.mv_outw((x),(unsigned long)(p))
# define __outl(x,p)	alpha_mv.mv_outl((x),(unsigned long)(p))

# 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 __ioremap(a)	alpha_mv.mv_ioremap((unsigned long)(a))
# define __is_ioaddr(a)	alpha_mv.mv_is_ioaddr((unsigned long)(a))

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

# define __raw_readb	__readb
# define __raw_readw	__readw
# define __raw_readl	__readl
# define __raw_readq	__readq
# define __raw_writeb	__writeb
# define __raw_writew	__writew
# define __raw_writel	__writel
# define __raw_writeq	__writeq

#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_IRONGATE)
# include <asm/core_irongate.h>
#elif defined(CONFIG_ALPHA_JENSEN)
# include <asm/jensen.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_POLARIS)
# include <asm/core_polaris.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_TITAN)
# include <asm/core_titan.h>
#elif defined(CONFIG_ALPHA_WILDFIRE)
# include <asm/core_wildfire.h>
#else
#error "What system is this?"
#endif

#undef __WANT_IO_DEF

#endif /* GENERIC */
#endif /* __KERNEL__ */

/*
 * 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);

#ifdef __KERNEL__
/*
 * 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

#define IO_SPACE_LIMIT 0xffff

#else 

/* Userspace declarations.  */

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 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);

#endif /* __KERNEL__ */

#ifdef __KERNEL__

/*
 * On Alpha, we have the whole of I/O space mapped at all times, but
 * at odd and sometimes discontinuous addresses.  Note that the 
 * discontinuities are all across busses, so we need not care for that
 * for any one device.
 *
 * Map the I/O space address into the kernel's virtual address space.
 */
static inline void * ioremap(unsigned long offset, unsigned long size)
{
	return (void *) __ioremap(offset);
} 

static inline void iounmap(void *addr)
{
}

static inline void * ioremap_nocache(unsigned long offset, unsigned long size)
{
	return ioremap(offset, size);
} 

/* Indirect back to the macros provided.  */

extern unsigned long	___raw_readb(unsigned long addr);
extern unsigned long	___raw_readw(unsigned long addr);
extern unsigned long	___raw_readl(unsigned long addr);
extern unsigned long	___raw_readq(unsigned long addr);
extern void		___raw_writeb(unsigned char b, unsigned long addr);
extern void		___raw_writew(unsigned short b, unsigned long addr);
extern void		___raw_writel(unsigned int b, unsigned long addr);
extern void		___raw_writeq(unsigned long b, unsigned long addr);

#ifdef __raw_readb
# define readb(a)	({ unsigned long r_ = __raw_readb(a); mb(); r_; })
#endif
#ifdef __raw_readw
# define readw(a)	({ unsigned long r_ = __raw_readw(a); mb(); r_; })
#endif
#ifdef __raw_readl
# define readl(a)	({ unsigned long r_ = __raw_readl(a); mb(); r_; })
#endif
#ifdef __raw_readq
# define readq(a)	({ unsigned long r_ = __raw_readq(a); mb(); r_; })
#endif

#ifdef __raw_writeb
# define writeb(v,a)	({ __raw_writeb((v),(a)); mb(); })
#endif
#ifdef __raw_writew
# define writew(v,a)	({ __raw_writew((v),(a)); mb(); })
#endif
#ifdef __raw_writel
# define writel(v,a)	({ __raw_writel((v),(a)); mb(); })
#endif
#ifdef __raw_writeq
# define writeq(v,a)	({ __raw_writeq((v),(a)); mb(); })
#endif

#ifndef __raw_readb
# define __raw_readb(a)	___raw_readb((unsigned long)(a))
#endif
#ifndef __raw_readw
# define __raw_readw(a)	___raw_readw((unsigned long)(a))
#endif
#ifndef __raw_readl
# define __raw_readl(a)	___raw_readl((unsigned long)(a))
#endif
#ifndef __raw_readq
# define __raw_readq(a)	___raw_readq((unsigned long)(a))
#endif

#ifndef __raw_writeb
# define __raw_writeb(v,a)  ___raw_writeb((v),(unsigned long)(a))
#endif
#ifndef __raw_writew
# define __raw_writew(v,a)  ___raw_writew((v),(unsigned long)(a))
#endif
#ifndef __raw_writel
# define __raw_writel(v,a)  ___raw_writel((v),(unsigned long)(a))
#endif
#ifndef __raw_writeq
# define __raw_writeq(v,a)  ___raw_writeq((v),(unsigned long)(a))
#endif

#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

/*
 * String version of IO memory access ops:
 */
extern void _memcpy_fromio(void *, unsigned long, long);
extern void _memcpy_toio(unsigned long, const 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

/* Nothing to do */

#define dma_cache_inv(_start,_size)		do { } while (0)
#define dma_cache_wback(_start,_size)		do { } while (0)
#define dma_cache_wback_inv(_start,_size)	do { } while (0)

#endif /* __KERNEL__ */

#endif /* __ALPHA_IO_H */