xref: /illumos-gate/usr/src/grub/grub-0.97/netboot/io.h (revision 7f11fd00)
1*7f11fd00SRichard Lowe #include <sys/ccompile.h>
2*7f11fd00SRichard Lowe 
37c478bd9Sstevel@tonic-gate #ifndef	IO_H
47c478bd9Sstevel@tonic-gate #define IO_H
57c478bd9Sstevel@tonic-gate 
67c478bd9Sstevel@tonic-gate /* Amount of relocation etherboot is experiencing */
77c478bd9Sstevel@tonic-gate extern unsigned long virt_offset;
87c478bd9Sstevel@tonic-gate 
97c478bd9Sstevel@tonic-gate /* Don't require identity mapped physical memory,
107c478bd9Sstevel@tonic-gate  * osloader.c is the only valid user at the moment.
117c478bd9Sstevel@tonic-gate  */
127c478bd9Sstevel@tonic-gate unsigned long virt_to_phys(volatile const void *virt_addr);
137c478bd9Sstevel@tonic-gate void *phys_to_virt(unsigned long phys_addr);
147c478bd9Sstevel@tonic-gate 
157c478bd9Sstevel@tonic-gate /* virt_to_bus converts an addresss inside of etherboot [_start, _end]
167c478bd9Sstevel@tonic-gate  * into a memory access cards can use.
177c478bd9Sstevel@tonic-gate  */
187c478bd9Sstevel@tonic-gate #define virt_to_bus virt_to_phys
197c478bd9Sstevel@tonic-gate 
207c478bd9Sstevel@tonic-gate 
217c478bd9Sstevel@tonic-gate /* bus_to_virt reverses virt_to_bus, the address must be output
227c478bd9Sstevel@tonic-gate  * from virt_to_bus to be valid.  This function does not work on
237c478bd9Sstevel@tonic-gate  * all bus addresses.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate #define bus_to_virt phys_to_virt
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate /* ioremap converts a random 32bit bus address into something
287c478bd9Sstevel@tonic-gate  * etherboot can access.
297c478bd9Sstevel@tonic-gate  */
ioremap(unsigned long bus_addr,unsigned long length __unused)307c478bd9Sstevel@tonic-gate static inline void *ioremap(unsigned long bus_addr, unsigned long length __unused)
317c478bd9Sstevel@tonic-gate {
327c478bd9Sstevel@tonic-gate 	return bus_to_virt(bus_addr);
337c478bd9Sstevel@tonic-gate }
347c478bd9Sstevel@tonic-gate 
357c478bd9Sstevel@tonic-gate /* iounmap cleans up anything ioremap had to setup */
iounmap(void * virt_addr __unused)367c478bd9Sstevel@tonic-gate static inline void iounmap(void *virt_addr __unused)
377c478bd9Sstevel@tonic-gate {
387c478bd9Sstevel@tonic-gate 	return;
397c478bd9Sstevel@tonic-gate }
407c478bd9Sstevel@tonic-gate 
417c478bd9Sstevel@tonic-gate /*
427c478bd9Sstevel@tonic-gate  * This file contains the definitions for the x86 IO instructions
437c478bd9Sstevel@tonic-gate  * inb/inw/inl/outb/outw/outl and the "string versions" of the same
447c478bd9Sstevel@tonic-gate  * (insb/insw/insl/outsb/outsw/outsl). You can also use "pausing"
457c478bd9Sstevel@tonic-gate  * versions of the single-IO instructions (inb_p/inw_p/..).
467c478bd9Sstevel@tonic-gate  *
477c478bd9Sstevel@tonic-gate  * This file is not meant to be obfuscating: it's just complicated
487c478bd9Sstevel@tonic-gate  * to (a) handle it all in a way that makes gcc able to optimize it
497c478bd9Sstevel@tonic-gate  * as well as possible and (b) trying to avoid writing the same thing
507c478bd9Sstevel@tonic-gate  * over and over again with slight variations and possibly making a
517c478bd9Sstevel@tonic-gate  * mistake somewhere.
527c478bd9Sstevel@tonic-gate  */
537c478bd9Sstevel@tonic-gate 
547c478bd9Sstevel@tonic-gate /*
557c478bd9Sstevel@tonic-gate  * Thanks to James van Artsdalen for a better timing-fix than
567c478bd9Sstevel@tonic-gate  * the two short jumps: using outb's to a nonexistent port seems
577c478bd9Sstevel@tonic-gate  * to guarantee better timings even on fast machines.
587c478bd9Sstevel@tonic-gate  *
597c478bd9Sstevel@tonic-gate  * On the other hand, I'd like to be sure of a non-existent port:
607c478bd9Sstevel@tonic-gate  * I feel a bit unsafe about using 0x80 (should be safe, though)
617c478bd9Sstevel@tonic-gate  *
627c478bd9Sstevel@tonic-gate  *		Linus
637c478bd9Sstevel@tonic-gate  */
647c478bd9Sstevel@tonic-gate 
657c478bd9Sstevel@tonic-gate #ifdef	SLOW_IO_BY_JUMPING
667c478bd9Sstevel@tonic-gate #define __SLOW_DOWN_IO __asm__ __volatile__("jmp 1f\n1:\tjmp 1f\n1:")
677c478bd9Sstevel@tonic-gate #else
687c478bd9Sstevel@tonic-gate #define __SLOW_DOWN_IO __asm__ __volatile__("outb %al,$0x80")
697c478bd9Sstevel@tonic-gate #endif
707c478bd9Sstevel@tonic-gate 
717c478bd9Sstevel@tonic-gate #ifdef	REALLY_SLOW_IO
727c478bd9Sstevel@tonic-gate #define SLOW_DOWN_IO { __SLOW_DOWN_IO; __SLOW_DOWN_IO; __SLOW_DOWN_IO; __SLOW_DOWN_IO; }
737c478bd9Sstevel@tonic-gate #else
747c478bd9Sstevel@tonic-gate #define SLOW_DOWN_IO __SLOW_DOWN_IO
757c478bd9Sstevel@tonic-gate #endif
767c478bd9Sstevel@tonic-gate 
777c478bd9Sstevel@tonic-gate /*
787c478bd9Sstevel@tonic-gate  * readX/writeX() are used to access memory mapped devices. On some
797c478bd9Sstevel@tonic-gate  * architectures the memory mapped IO stuff needs to be accessed
807c478bd9Sstevel@tonic-gate  * differently. On the x86 architecture, we just read/write the
817c478bd9Sstevel@tonic-gate  * memory location directly.
827c478bd9Sstevel@tonic-gate  */
837c478bd9Sstevel@tonic-gate #define readb(addr) (*(volatile unsigned char *) (addr))
847c478bd9Sstevel@tonic-gate #define readw(addr) (*(volatile unsigned short *) (addr))
857c478bd9Sstevel@tonic-gate #define readl(addr) (*(volatile unsigned int *) (addr))
867c478bd9Sstevel@tonic-gate 
877c478bd9Sstevel@tonic-gate #define writeb(b,addr) ((*(volatile unsigned char *) (addr)) = (b))
887c478bd9Sstevel@tonic-gate #define writew(b,addr) ((*(volatile unsigned short *) (addr)) = (b))
897c478bd9Sstevel@tonic-gate #define writel(b,addr) ((*(volatile unsigned int *) (addr)) = (b))
907c478bd9Sstevel@tonic-gate 
917c478bd9Sstevel@tonic-gate #define memcpy_fromio(a,b,c)	memcpy((a),(void *)(b),(c))
927c478bd9Sstevel@tonic-gate #define memcpy_toio(a,b,c)	memcpy((void *)(a),(b),(c))
937c478bd9Sstevel@tonic-gate 
947c478bd9Sstevel@tonic-gate /*
957c478bd9Sstevel@tonic-gate  * Force strict CPU ordering.
967c478bd9Sstevel@tonic-gate  * And yes, this is required on UP too when we're talking
977c478bd9Sstevel@tonic-gate  * to devices.
987c478bd9Sstevel@tonic-gate  *
997c478bd9Sstevel@tonic-gate  * For now, "wmb()" doesn't actually do anything, as all
1007c478bd9Sstevel@tonic-gate  * Intel CPU's follow what Intel calls a *Processor Order*,
1017c478bd9Sstevel@tonic-gate  * in which all writes are seen in the program order even
1027c478bd9Sstevel@tonic-gate  * outside the CPU.
1037c478bd9Sstevel@tonic-gate  *
1047c478bd9Sstevel@tonic-gate  * I expect future Intel CPU's to have a weaker ordering,
1057c478bd9Sstevel@tonic-gate  * but I'd also expect them to finally get their act together
1067c478bd9Sstevel@tonic-gate  * and add some real memory barriers if so.
1077c478bd9Sstevel@tonic-gate  *
1087c478bd9Sstevel@tonic-gate  * Some non intel clones support out of order store. wmb() ceases to be a
1097c478bd9Sstevel@tonic-gate  * nop for these.
1107c478bd9Sstevel@tonic-gate  */
111*7f11fd00SRichard Lowe 
1127c478bd9Sstevel@tonic-gate #define mb() 	__asm__ __volatile__ ("lock; addl $0,0(%%esp)": : :"memory")
1137c478bd9Sstevel@tonic-gate #define rmb()	mb()
1147c478bd9Sstevel@tonic-gate #define wmb()	mb();
1157c478bd9Sstevel@tonic-gate 
1167c478bd9Sstevel@tonic-gate 
1177c478bd9Sstevel@tonic-gate /*
1187c478bd9Sstevel@tonic-gate  * Talk about misusing macros..
1197c478bd9Sstevel@tonic-gate  */
1207c478bd9Sstevel@tonic-gate 
1217c478bd9Sstevel@tonic-gate #define __OUT1(s,x) \
1227c478bd9Sstevel@tonic-gate extern void __out##s(unsigned x value, unsigned short port); \
123*7f11fd00SRichard Lowe extern __GNU_INLINE \
124*7f11fd00SRichard Lowe void __out##s(unsigned x value, unsigned short port) {
1257c478bd9Sstevel@tonic-gate 
1267c478bd9Sstevel@tonic-gate #define __OUT2(s,s1,s2) \
1277c478bd9Sstevel@tonic-gate __asm__ __volatile__ ("out" #s " %" s1 "0,%" s2 "1"
1287c478bd9Sstevel@tonic-gate 
1297c478bd9Sstevel@tonic-gate #define __OUT(s,s1,x) \
1307c478bd9Sstevel@tonic-gate __OUT1(s,x) __OUT2(s,s1,"w") : : "a" (value), "d" (port)); } \
1317c478bd9Sstevel@tonic-gate __OUT1(s##c,x) __OUT2(s,s1,"") : : "a" (value), "id" (port)); } \
1327c478bd9Sstevel@tonic-gate __OUT1(s##_p,x) __OUT2(s,s1,"w") : : "a" (value), "d" (port)); SLOW_DOWN_IO; } \
1337c478bd9Sstevel@tonic-gate __OUT1(s##c_p,x) __OUT2(s,s1,"") : : "a" (value), "id" (port)); SLOW_DOWN_IO; }
1347c478bd9Sstevel@tonic-gate 
1357c478bd9Sstevel@tonic-gate #define __IN1(s,x) \
1367c478bd9Sstevel@tonic-gate extern unsigned x __in##s(unsigned short port); \
137*7f11fd00SRichard Lowe extern __GNU_INLINE \
138*7f11fd00SRichard Lowe unsigned x __in##s(unsigned short port) { unsigned x _v;
1397c478bd9Sstevel@tonic-gate 
1407c478bd9Sstevel@tonic-gate #define __IN2(s,s1,s2) \
1417c478bd9Sstevel@tonic-gate __asm__ __volatile__ ("in" #s " %" s2 "1,%" s1 "0"
1427c478bd9Sstevel@tonic-gate 
1437c478bd9Sstevel@tonic-gate #define __IN(s,s1,x,i...) \
1447c478bd9Sstevel@tonic-gate __IN1(s,x) __IN2(s,s1,"w") : "=a" (_v) : "d" (port) ,##i ); return _v; } \
1457c478bd9Sstevel@tonic-gate __IN1(s##c,x) __IN2(s,s1,"") : "=a" (_v) : "id" (port) ,##i ); return _v; } \
1467c478bd9Sstevel@tonic-gate __IN1(s##_p,x) __IN2(s,s1,"w") : "=a" (_v) : "d" (port) ,##i ); SLOW_DOWN_IO; return _v; } \
1477c478bd9Sstevel@tonic-gate __IN1(s##c_p,x) __IN2(s,s1,"") : "=a" (_v) : "id" (port) ,##i ); SLOW_DOWN_IO; return _v; }
1487c478bd9Sstevel@tonic-gate 
1497c478bd9Sstevel@tonic-gate #define __INS(s) \
1507c478bd9Sstevel@tonic-gate extern void ins##s(unsigned short port, void * addr, unsigned long count); \
151*7f11fd00SRichard Lowe extern __GNU_INLINE \
152*7f11fd00SRichard Lowe void ins##s(unsigned short port, void * addr, unsigned long count)	\
1537c478bd9Sstevel@tonic-gate { __asm__ __volatile__ ("cld ; rep ; ins" #s \
1547c478bd9Sstevel@tonic-gate : "=D" (addr), "=c" (count) : "d" (port),"0" (addr),"1" (count)); }
1557c478bd9Sstevel@tonic-gate 
1567c478bd9Sstevel@tonic-gate #define __OUTS(s) \
1577c478bd9Sstevel@tonic-gate extern void outs##s(unsigned short port, const void * addr, unsigned long  count); \
158*7f11fd00SRichard Lowe extern __GNU_INLINE \
159*7f11fd00SRichard Lowe void outs##s(unsigned short port, const void * addr, unsigned long count) \
1607c478bd9Sstevel@tonic-gate { __asm__ __volatile__ ("cld ; rep ; outs" #s \
1617c478bd9Sstevel@tonic-gate : "=S" (addr), "=c" (count) : "d" (port),"0" (addr),"1" (count)); }
1627c478bd9Sstevel@tonic-gate 
1637c478bd9Sstevel@tonic-gate __IN(b,"", char)
1647c478bd9Sstevel@tonic-gate __IN(w,"",short)
1657c478bd9Sstevel@tonic-gate __IN(l,"", long)
1667c478bd9Sstevel@tonic-gate 
1677c478bd9Sstevel@tonic-gate __OUT(b,"b",char)
1687c478bd9Sstevel@tonic-gate __OUT(w,"w",short)
1697c478bd9Sstevel@tonic-gate __OUT(l,,int)
1707c478bd9Sstevel@tonic-gate 
1717c478bd9Sstevel@tonic-gate __INS(b)
1727c478bd9Sstevel@tonic-gate __INS(w)
1737c478bd9Sstevel@tonic-gate __INS(l)
1747c478bd9Sstevel@tonic-gate 
1757c478bd9Sstevel@tonic-gate __OUTS(b)
1767c478bd9Sstevel@tonic-gate __OUTS(w)
1777c478bd9Sstevel@tonic-gate __OUTS(l)
1787c478bd9Sstevel@tonic-gate 
1797c478bd9Sstevel@tonic-gate /*
1807c478bd9Sstevel@tonic-gate  * Note that due to the way __builtin_constant_p() works, you
1817c478bd9Sstevel@tonic-gate  *  - can't use it inside a inline function (it will never be true)
1827c478bd9Sstevel@tonic-gate  *  - you don't have to worry about side effects within the __builtin..
1837c478bd9Sstevel@tonic-gate  */
1847c478bd9Sstevel@tonic-gate #define outb(val,port) \
1857c478bd9Sstevel@tonic-gate ((__builtin_constant_p((port)) && (port) < 256) ? \
1867c478bd9Sstevel@tonic-gate 	__outbc((val),(port)) : \
1877c478bd9Sstevel@tonic-gate 	__outb((val),(port)))
1887c478bd9Sstevel@tonic-gate 
1897c478bd9Sstevel@tonic-gate #define inb(port) \
1907c478bd9Sstevel@tonic-gate ((__builtin_constant_p((port)) && (port) < 256) ? \
1917c478bd9Sstevel@tonic-gate 	__inbc(port) : \
1927c478bd9Sstevel@tonic-gate 	__inb(port))
1937c478bd9Sstevel@tonic-gate 
1947c478bd9Sstevel@tonic-gate #define outb_p(val,port) \
1957c478bd9Sstevel@tonic-gate ((__builtin_constant_p((port)) && (port) < 256) ? \
1967c478bd9Sstevel@tonic-gate 	__outbc_p((val),(port)) : \
1977c478bd9Sstevel@tonic-gate 	__outb_p((val),(port)))
1987c478bd9Sstevel@tonic-gate 
1997c478bd9Sstevel@tonic-gate #define inb_p(port) \
2007c478bd9Sstevel@tonic-gate ((__builtin_constant_p((port)) && (port) < 256) ? \
2017c478bd9Sstevel@tonic-gate 	__inbc_p(port) : \
2027c478bd9Sstevel@tonic-gate 	__inb_p(port))
2037c478bd9Sstevel@tonic-gate 
2047c478bd9Sstevel@tonic-gate #define outw(val,port) \
2057c478bd9Sstevel@tonic-gate ((__builtin_constant_p((port)) && (port) < 256) ? \
2067c478bd9Sstevel@tonic-gate 	__outwc((val),(port)) : \
2077c478bd9Sstevel@tonic-gate 	__outw((val),(port)))
2087c478bd9Sstevel@tonic-gate 
2097c478bd9Sstevel@tonic-gate #define inw(port) \
2107c478bd9Sstevel@tonic-gate ((__builtin_constant_p((port)) && (port) < 256) ? \
2117c478bd9Sstevel@tonic-gate 	__inwc(port) : \
2127c478bd9Sstevel@tonic-gate 	__inw(port))
2137c478bd9Sstevel@tonic-gate 
2147c478bd9Sstevel@tonic-gate #define outw_p(val,port) \
2157c478bd9Sstevel@tonic-gate ((__builtin_constant_p((port)) && (port) < 256) ? \
2167c478bd9Sstevel@tonic-gate 	__outwc_p((val),(port)) : \
2177c478bd9Sstevel@tonic-gate 	__outw_p((val),(port)))
2187c478bd9Sstevel@tonic-gate 
2197c478bd9Sstevel@tonic-gate #define inw_p(port) \
2207c478bd9Sstevel@tonic-gate ((__builtin_constant_p((port)) && (port) < 256) ? \
2217c478bd9Sstevel@tonic-gate 	__inwc_p(port) : \
2227c478bd9Sstevel@tonic-gate 	__inw_p(port))
2237c478bd9Sstevel@tonic-gate 
2247c478bd9Sstevel@tonic-gate #define outl(val,port) \
2257c478bd9Sstevel@tonic-gate ((__builtin_constant_p((port)) && (port) < 256) ? \
2267c478bd9Sstevel@tonic-gate 	__outlc((val),(port)) : \
2277c478bd9Sstevel@tonic-gate 	__outl((val),(port)))
2287c478bd9Sstevel@tonic-gate 
2297c478bd9Sstevel@tonic-gate #define inl(port) \
2307c478bd9Sstevel@tonic-gate ((__builtin_constant_p((port)) && (port) < 256) ? \
2317c478bd9Sstevel@tonic-gate 	__inlc(port) : \
2327c478bd9Sstevel@tonic-gate 	__inl(port))
2337c478bd9Sstevel@tonic-gate 
2347c478bd9Sstevel@tonic-gate #define outl_p(val,port) \
2357c478bd9Sstevel@tonic-gate ((__builtin_constant_p((port)) && (port) < 256) ? \
2367c478bd9Sstevel@tonic-gate 	__outlc_p((val),(port)) : \
2377c478bd9Sstevel@tonic-gate 	__outl_p((val),(port)))
2387c478bd9Sstevel@tonic-gate 
2397c478bd9Sstevel@tonic-gate #define inl_p(port) \
2407c478bd9Sstevel@tonic-gate ((__builtin_constant_p((port)) && (port) < 256) ? \
2417c478bd9Sstevel@tonic-gate 	__inlc_p(port) : \
2427c478bd9Sstevel@tonic-gate 	__inl_p(port))
2437c478bd9Sstevel@tonic-gate 
2447c478bd9Sstevel@tonic-gate #endif /* ETHERBOOT_IO_H */
245