File: /usr/src/linux/include/asm-alpha/jensen.h

1     #ifndef __ALPHA_JENSEN_H
2     #define __ALPHA_JENSEN_H
3     
4     #include <asm/compiler.h>
5     
6     /*
7      * Defines for the AlphaPC EISA IO and memory address space.
8      */
9     
10     /* The Jensen is strange */
11     #define AUX_IRQ (9)
12     
13     /*
14      * NOTE! The memory operations do not set any memory barriers, as it's
15      * not needed for cases like a frame buffer that is essentially memory-like.
16      * You need to do them by hand if the operations depend on ordering.
17      *
18      * Similarly, the port IO operations do a "mb" only after a write operation:
19      * if an mb is needed before (as in the case of doing memory mapped IO
20      * first, and then a port IO operation to the same device), it needs to be
21      * done by hand.
22      *
23      * After the above has bitten me 100 times, I'll give up and just do the
24      * mb all the time, but right now I'm hoping this will work out.  Avoiding
25      * mb's may potentially be a noticeable speed improvement, but I can't
26      * honestly say I've tested it.
27      *
28      * Handling interrupts that need to do mb's to synchronize to non-interrupts
29      * is another fun race area.  Don't do it (because if you do, I'll have to
30      * do *everything* with interrupts disabled, ugh).
31      */
32     
33     /*
34      * EISA Interrupt Acknowledge address
35      */
36     #define EISA_INTA		(IDENT_ADDR + 0x100000000UL)
37     
38     /*
39      * FEPROM addresses
40      */
41     #define EISA_FEPROM0		(IDENT_ADDR + 0x180000000UL)
42     #define EISA_FEPROM1		(IDENT_ADDR + 0x1A0000000UL)
43     
44     /*
45      * VL82C106 base address
46      */
47     #define EISA_VL82C106		(IDENT_ADDR + 0x1C0000000UL)
48     
49     /*
50      * EISA "Host Address Extension" address (bits 25-31 of the EISA address)
51      */
52     #define EISA_HAE		(IDENT_ADDR + 0x1D0000000UL)
53     
54     /*
55      * "SYSCTL" register address
56      */
57     #define EISA_SYSCTL		(IDENT_ADDR + 0x1E0000000UL)
58     
59     /*
60      * "spare" register address
61      */
62     #define EISA_SPARE		(IDENT_ADDR + 0x1F0000000UL)
63     
64     /*
65      * EISA memory address offset
66      */
67     #define EISA_MEM		(IDENT_ADDR + 0x200000000UL)
68     
69     /*
70      * EISA IO address offset
71      */
72     #define EISA_IO			(IDENT_ADDR + 0x300000000UL)
73     
74     
75     #ifdef __KERNEL__
76     
77     #ifndef __EXTERN_INLINE
78     #define __EXTERN_INLINE extern inline
79     #define __IO_EXTERN_INLINE
80     #endif
81     
82     /*
83      * Handle the "host address register". This needs to be set
84      * to the high 7 bits of the EISA address.  This is also needed
85      * for EISA IO addresses, which are only 16 bits wide (the
86      * hae needs to be set to 0).
87      *
88      * HAE isn't needed for the local IO operations, though.
89      */
90     
91     #define JENSEN_HAE_ADDRESS	EISA_HAE
92     #define JENSEN_HAE_MASK		0x1ffffff
93     
94     __EXTERN_INLINE void jensen_set_hae(unsigned long addr)
95     {
96     	/* hae on the Jensen is bits 31:25 shifted right */
97     	addr >>= 25;
98     	if (addr != alpha_mv.hae_cache)
99     		set_hae(addr);
100     }
101     
102     #define vuip	volatile unsigned int *
103     
104     /*
105      * IO functions
106      *
107      * The "local" functions are those that don't go out to the EISA bus,
108      * but instead act on the VL82C106 chip directly.. This is mainly the
109      * keyboard, RTC,  printer and first two serial lines..
110      *
111      * The local stuff makes for some complications, but it seems to be
112      * gone in the PCI version. I hope I can get DEC suckered^H^H^H^H^H^H^H^H
113      * convinced that I need one of the newer machines.
114      */
115     
116     static inline unsigned int jensen_local_inb(unsigned long addr)
117     {
118     	return 0xff & *(vuip)((addr << 9) + EISA_VL82C106);
119     }
120     
121     static inline void jensen_local_outb(unsigned char b, unsigned long addr)
122     {
123     	*(vuip)((addr << 9) + EISA_VL82C106) = b;
124     	mb();
125     }
126     
127     static inline unsigned int jensen_bus_inb(unsigned long addr)
128     {
129     	long result;
130     
131     	jensen_set_hae(0);
132     	result = *(volatile int *)((addr << 7) + EISA_IO + 0x00);
133     	return __kernel_extbl(result, addr & 3);
134     }
135     
136     static inline void jensen_bus_outb(unsigned char b, unsigned long addr)
137     {
138     	jensen_set_hae(0);
139     	*(vuip)((addr << 7) + EISA_IO + 0x00) = b * 0x01010101;
140     	mb();
141     }
142     
143     /*
144      * It seems gcc is not very good at optimizing away logical
145      * operations that result in operations across inline functions.
146      * Which is why this is a macro.
147      */
148     
149     #define jensen_is_local(addr) ( \
150     /* keyboard */	(addr == 0x60 || addr == 0x64) || \
151     /* RTC */	(addr == 0x170 || addr == 0x171) || \
152     /* mb COM2 */	(addr >= 0x2f8 && addr <= 0x2ff) || \
153     /* mb LPT1 */	(addr >= 0x3bc && addr <= 0x3be) || \
154     /* mb COM2 */	(addr >= 0x3f8 && addr <= 0x3ff))
155     
156     __EXTERN_INLINE unsigned int jensen_inb(unsigned long addr)
157     {
158     	if (jensen_is_local(addr))
159     		return jensen_local_inb(addr);
160     	else
161     		return jensen_bus_inb(addr);
162     }
163     
164     __EXTERN_INLINE void jensen_outb(unsigned char b, unsigned long addr)
165     {
166     	if (jensen_is_local(addr))
167     		jensen_local_outb(b, addr);
168     	else
169     		jensen_bus_outb(b, addr);
170     }
171     
172     __EXTERN_INLINE unsigned int jensen_inw(unsigned long addr)
173     {
174     	long result;
175     
176     	jensen_set_hae(0);
177     	result = *(volatile int *) ((addr << 7) + EISA_IO + 0x20);
178     	result >>= (addr & 3) * 8;
179     	return 0xffffUL & result;
180     }
181     
182     __EXTERN_INLINE unsigned int jensen_inl(unsigned long addr)
183     {
184     	jensen_set_hae(0);
185     	return *(vuip) ((addr << 7) + EISA_IO + 0x60);
186     }
187     
188     __EXTERN_INLINE void jensen_outw(unsigned short b, unsigned long addr)
189     {
190     	jensen_set_hae(0);
191     	*(vuip) ((addr << 7) + EISA_IO + 0x20) = b * 0x00010001;
192     	mb();
193     }
194     
195     __EXTERN_INLINE void jensen_outl(unsigned int b, unsigned long addr)
196     {
197     	jensen_set_hae(0);
198     	*(vuip) ((addr << 7) + EISA_IO + 0x60) = b;
199     	mb();
200     }
201     
202     /*
203      * Memory functions.
204      */
205     
206     __EXTERN_INLINE unsigned long jensen_readb(unsigned long addr)
207     {
208     	long result;
209     
210     	jensen_set_hae(addr);
211     	addr &= JENSEN_HAE_MASK;
212     	result = *(volatile int *) ((addr << 7) + EISA_MEM + 0x00);
213     	result >>= (addr & 3) * 8;
214     	return 0xffUL & result;
215     }
216     
217     __EXTERN_INLINE unsigned long jensen_readw(unsigned long addr)
218     {
219     	long result;
220     
221     	jensen_set_hae(addr);
222     	addr &= JENSEN_HAE_MASK;
223     	result = *(volatile int *) ((addr << 7) + EISA_MEM + 0x20);
224     	result >>= (addr & 3) * 8;
225     	return 0xffffUL & result;
226     }
227     
228     __EXTERN_INLINE unsigned long jensen_readl(unsigned long addr)
229     {
230     	jensen_set_hae(addr);
231     	addr &= JENSEN_HAE_MASK;
232     	return *(vuip) ((addr << 7) + EISA_MEM + 0x60);
233     }
234     
235     __EXTERN_INLINE unsigned long jensen_readq(unsigned long addr)
236     {
237     	unsigned long r0, r1;
238     
239     	jensen_set_hae(addr);
240     	addr &= JENSEN_HAE_MASK;
241     	addr = (addr << 7) + EISA_MEM + 0x60;
242     	r0 = *(vuip) (addr);
243     	r1 = *(vuip) (addr + (4 << 7));
244     	return r1 << 32 | r0;
245     }
246     
247     __EXTERN_INLINE void jensen_writeb(unsigned char b, unsigned long addr)
248     {
249     	jensen_set_hae(addr);
250     	addr &= JENSEN_HAE_MASK;
251     	*(vuip) ((addr << 7) + EISA_MEM + 0x00) = b * 0x01010101;
252     }
253     
254     __EXTERN_INLINE void jensen_writew(unsigned short b, unsigned long addr)
255     {
256     	jensen_set_hae(addr);
257     	addr &= JENSEN_HAE_MASK;
258     	*(vuip) ((addr << 7) + EISA_MEM + 0x20) = b * 0x00010001;
259     }
260     
261     __EXTERN_INLINE void jensen_writel(unsigned int b, unsigned long addr)
262     {
263     	jensen_set_hae(addr);
264     	addr &= JENSEN_HAE_MASK;
265     	*(vuip) ((addr << 7) + EISA_MEM + 0x60) = b;
266     }
267     
268     __EXTERN_INLINE void jensen_writeq(unsigned long b, unsigned long addr)
269     {
270     	jensen_set_hae(addr);
271     	addr &= JENSEN_HAE_MASK;
272     	addr = (addr << 7) + EISA_MEM + 0x60;
273     	*(vuip) (addr) = b;
274     	*(vuip) (addr + (4 << 7)) = b >> 32;
275     }
276     
277     __EXTERN_INLINE unsigned long jensen_ioremap(unsigned long addr, 
278     					     unsigned long size)
279     {
280     	return addr;
281     }
282     
283     __EXTERN_INLINE void jensen_iounmap(unsigned long addr)
284     {
285     	return;
286     }
287     
288     __EXTERN_INLINE int jensen_is_ioaddr(unsigned long addr)
289     {
290     	return (long)addr >= 0;
291     }
292     
293     #undef vuip
294     
295     #ifdef __WANT_IO_DEF
296     
297     #define __inb		jensen_inb
298     #define __inw		jensen_inw
299     #define __inl		jensen_inl
300     #define __outb		jensen_outb
301     #define __outw		jensen_outw
302     #define __outl		jensen_outl
303     #define __readb		jensen_readb
304     #define __readw		jensen_readw
305     #define __writeb	jensen_writeb
306     #define __writew	jensen_writew
307     #define __readl		jensen_readl
308     #define __readq		jensen_readq
309     #define __writel	jensen_writel
310     #define __writeq	jensen_writeq
311     #define __ioremap	jensen_ioremap
312     #define __iounmap(a)	jensen_iounmap((unsigned long)a)
313     #define __is_ioaddr	jensen_is_ioaddr
314     
315     /*
316      * The above have so much overhead that it probably doesn't make
317      * sense to have them inlined (better icache behaviour).
318      */
319     #define inb(port) \
320     (__builtin_constant_p((port))?__inb(port):_inb(port))
321     
322     #define outb(x, port) \
323     (__builtin_constant_p((port))?__outb((x),(port)):_outb((x),(port)))
324     
325     #endif /* __WANT_IO_DEF */
326     
327     #ifdef __IO_EXTERN_INLINE
328     #undef __EXTERN_INLINE
329     #undef __IO_EXTERN_INLINE
330     #endif
331     
332     #endif /* __KERNEL__ */
333     
334     #endif /* __ALPHA_JENSEN_H */
335