Coherent4.2.10/include/kernel/x86io.h
/* (-lgl
* Coherent 386 release 4.2
* Copyright (c) 1982, 1993 by Mark Williams Company.
* All rights reserved. May not be copied without permission.
* For copying permission and licensing info, write licensing@mwc.com
-lgl) */
#ifndef __KERNEL_X86IO_H__
#define __KERNEL_X86IO_H__
/*
* The system V DDI/DKI for Intel processors defines a C-language interface to
* the machine I/O instructions available through <sys/types.h>.
*
* For simplicity, this has been factored out into a separate file for this
* implementation, and <sys/types.h> pulls this file in.
*/
#include <common/ccompat.h>
#include <common/feature.h>
#include <common/xdebug.h>
#include <common/__types.h>
/*
* Get these into a useful form in a similar manner to the way the spl... ()
* functions are defined in <sys/inline.h>
*/
#if __GNUC__ && _I386 /* 80386 with GNU CC */
/*
* It appears that the code GCC produces is sufficiently good that we can
* run into problems with I/O recovery times on older boards, especially with
* 386's. So, we allow for the possibility of delaying for a brief time.
*/
#ifndef __IO_RECOVER
# if 1
# define __IO_RECOVER ""
# else
# define __IO_RECOVER ";jmp LIO%=a;LIO%=a:;jmp LIO%=b;LIO%=b:"
# endif
#endif
/*
* Similarly to the above, it may be that using the REP instruction prefix
* with I/O instructions may cause problems with motherboards or peripheral
* failure to meet bus timings. To permit investigation of this problem we
* allow either the REP prefix or the LOOP instruction to be used.
*/
#if _USE_REP_PREFIX
# define __REPEAT(instr) ";rep;" instr
#else
# define __REPEAT(instr) ";LX%=: " instr "; loop LX%="
#endif
/*
* Note that the definitions for the string-input instructions assume that
* ES: is equivalent to DS:.
*/
__LOCAL__ __INLINE__ __uchar_t __inb (int _port) {
__uchar_t _result;
__NON_ISO (asm) volatile ("in %1,%0" __IO_RECOVER :
"=a" (_result) : "d" ((__ushort_t) _port));
return _result;
}
__LOCAL__ __INLINE__ __ulong_t __inl (int _port) {
__ulong_t _result;
__NON_ISO (asm) volatile ("in %1,%0" __IO_RECOVER :
"=a" (_result) : "d" ((__ushort_t) _port));
return _result;
}
__LOCAL__ __INLINE__ __ushort_t __inw (int _port) {
__ushort_t _result;
__NON_ISO (asm) volatile ("in %1,%0" __IO_RECOVER :
"=a" (_result) : "d" ((__ushort_t) _port));
return _result;
}
__LOCAL__ __INLINE__ void __outb (int _port, __uchar_t value) {
__NON_ISO (asm) volatile ("out %1,%0" __IO_RECOVER : :
"d" ((__ushort_t) _port), "a" (value));
}
__LOCAL__ __INLINE__ void __outl (int _port, __ulong_t value) {
__NON_ISO (asm) volatile ("out %1,%0" __IO_RECOVER : :
"d" ((__ushort_t) _port), "a" (value));
}
__LOCAL__ __INLINE__ void __outw (int _port, __ushort_t value) {
__NON_ISO (asm) volatile ("out %1,%0" __IO_RECOVER : :
"d" ((__ushort_t) _port), "a" (value));
}
__LOCAL__ __INLINE__
void __repinsb (int _port, __uchar_t * _addr, int _cnt) {
__NON_ISO (asm) volatile ("mov %1,%%edi" __REPEAT ("insb") : :
"d" ((__ushort_t) _port), "g" (_addr),
"c" (_cnt) : "di");
}
__LOCAL__ __INLINE__
void __repinsd (int _port, __ulong_t * _addr, int _cnt) {
__NON_ISO (asm) volatile ("mov %1,%%edi" __REPEAT ("insl") : :
"d" ((__ushort_t) _port), "g" (_addr),
"c" (_cnt) : "di");
}
__LOCAL__ __INLINE__
void __repinsw (int _port, __ushort_t * _addr, int _cnt) {
__NON_ISO (asm) volatile ("mov %1,%%edi" __REPEAT ("insw") : :
"d" ((__ushort_t) _port), "g" (_addr),
"c" (_cnt) : "di");
}
__LOCAL__ __INLINE__
void __repoutsb (int _port, __uchar_t * _addr, int _cnt) {
__NON_ISO (asm) volatile ("mov %1,%%esi" __REPEAT ("outsb") : :
"d" ((__ushort_t) _port), "g" (_addr),
"c" (_cnt) : "si");
}
__LOCAL__ __INLINE__
void __repoutsd (int _port, __ulong_t * _addr, int _cnt) {
__NON_ISO (asm) volatile ("movl %1,%%esi" __REPEAT ("outsl") : :
"d" ((__ushort_t) _port), "g" (_addr),
"c" (_cnt) : "si");
}
__LOCAL__ __INLINE__
void __repoutsw (int _port, __ushort_t * _addr, int _cnt) {
__NON_ISO (asm) volatile ("movl %1,%%esi" __REPEAT ("outsw") : :
"d" ((__ushort_t) _port), "g" (_addr),
"c" (_cnt) : "si");
}
#define __FORWARD_inb__
#define __FORWARD_inl__
#define __FORWARD_inw__
#define __FORWARD_outb__
#define __FORWARD_outl__
#define __FORWARD_outw__
#define __FORWARD_repinsb__
#define __FORWARD_repinsd__
#define __FORWARD_repinsw__
#define __FORWARD_repoutsb__
#define __FORWARD_repoutsd__
#define __FORWARD_repoutsw__
#elif __BORLANDC__
void __emit__ (unsigned char __byte, ...);
/*
* Note the use of the 0x66 operand-size override prefix below, which is built
* on the assumption that Borland generates 16-bit code segments.
*/
#define __REP__ 0xF3 /* repeat-prefix */
#define __INB__ 0xEC
#define __INW__ 0xED
#define __INL__ 0x66, __INW__ /* size-override for 32-bit form */
#define __OUTB__ 0xEE
#define __OUTW__ 0xEF
#define __OUTL__ 0x66, __OUTW__ /* size-override for 32-bit form */
#define __INSB__ 0x6C
#define __INSW__ 0x6D
#define __INSL__ 0x65, __INSW__
#define __OUTSB__ 0x6E
#define __OUTSW__ 0x6F /* word/long depending on CS: */
#define __OUTSL__ 0x66, __OUTSW__
/*
* If we are willing to restrict ourselves to i386's, Borland C++ 3.1 allows
* support for 32-bit register-pseudovariables if 386 code generation has
* been enabled.
*
* As it turns out, there are all kinds of bugs in the 386 support in BC++ 3.1
* but enough works that we can even get a far pointer into ES:whatever via
* a 32-bit register, as long as the intermediate register isn't _ESI or _EDI
* since _EAX = _ESI or _EAX = _EDI only moves the low 16 bits. Being able to
* load ES:whatever via a 32-bit register allows us to write macros that only
* reference each argument exactly once.
*
* While the 32-bit-pointer version still works in the near models, it's not
* exactly optimal, so we use a more straightforward version there.
*/
#define __inb(port) (_DX = (port), __emit__ (__INB__),\
(__uchar_t) _AL)
#define __inl(port) (_DX = (port), __emit__ (__INL__), _EAX)
#define __inw(port) (_DX = (port), __emit__ (__INW__), \
(__ushort_t) _AX)
#define __outb(port,value) (_DX = (port), _AL = (value), \
__emit__ (__OUTB__))
#define __outl(port,value) (_DX = (port), _EAX = (value), \
__emit__ (__OUTL__))
#define __outw(port,value) (_DX = (port), _AX = (value), \
__emit__ (__OUTW__))
#if defined (__LARGE__) || defined (__HUGE__) || defined (__COMPACT__)
#define __repins(p,a,c) (_EDX = (long) (void __far *) (a), _EAX = _EDX,\
_ES = (unsigned) (_EAX >> 16),\
_DI = _DX, _CX = (c), _DX = (p))
#define __repouts(p,a,c) (_EDX = (long) (void _far *) (a), _EAX = _EDX,\
_ES = (unsigned) (_EAX >> 16),\
_SI = _DX, _CX = (c), _DX = (p))
#else /* use simpler small-data versions */
#define __repins(p,a,c) (_ES = _DS, _DI = (unsigned) (a), \
_CX = (c), _DX = (p))
#define __repouts(p,a,c) (_ES = _DS, _SI = (unsigned) (a), \
_CX = (c), _DX = (p))
#endif
#define __repinsb(p,a,c) (__repins (p, a, c),\
__emit__ (__REP__, __INSB__))
#define __repinsd(p,a,c) (__repins (p, a, c),\
__emit__ (__REP__, __INSL__))
#define __repinsw(p,a,c) (__repins (p, a, c),\
__emit__ (__REP__, __INSW__))
#define __repoutsb(p,a,c) (__repouts (p, a, c),\
__emit__ (__REP__, __OUTSB__))
#define __repoutsd(p,a,c) (__repouts (p, a, c),\
__emit__ (__REP__, __OUTSL__))
#define __repoutsw(p,a,c) (__repouts (p, a, c),\
__emit__ (__REP__, __OUTSW__))
#define __FORWARD_inb__
#define __FORWARD_inl__
#define __FORWARD_inw__
#define __FORWARD_outb__
#define __FORWARD_outl__
#define __FORWARD_outw__
#define __FORWARD_repinsb__
#define __FORWARD_repinsd__
#define __FORWARD_repinsw__
#define __FORWARD_repoutsb__
#define __FORWARD_repoutsd__
#define __FORWARD_repoutsw__
#endif
__EXTERN_C_BEGIN__
__uchar_t inb __PROTO ((int _port));
__ulong_t inl __PROTO ((int _port));
__ushort_t inw __PROTO ((int _port));
void outb __PROTO ((int _port, __uchar_t _value));
void outl __PROTO ((int _port, __ulong_t _value));
void outw __PROTO ((int _port, __ushort_t _value));
void repinsb __PROTO ((int _port, __uchar_t * _addr,
int _cnt));
void repinsd __PROTO ((int _port, __ulong_t * _addr,
int _cnt));
void repinsw __PROTO ((int _port, __ushort_t * _addr,
int _cnt));
void repoutsb __PROTO ((int _port, __uchar_t * _addr,
int _cnt));
void repoutsd __PROTO ((int _port, __ulong_t * _addr,
int _cnt));
void repoutsw __PROTO ((int _port, __ushort_t * _addr,
int _cnt));
__EXTERN_C_END__
#ifdef __FORWARD_inb__
# define inb(port) __inb (port)
#endif
#ifdef __FORWARD_inl__
# define inl(port) __inl (port)
#endif
#ifdef __FORWARD_inw__
# define inw(port) __inw (port)
#endif
#ifdef __FORWARD_outb__
# define outb(port,val) __outb (port, val)
#endif
#ifdef __FORWARD_outl__
# define outl(port,val) __outl (port, val)
#endif
#ifdef __FORWARD_outw__
# define outw(port,val) __outw (port, val)
#endif
#ifdef __FORWARD_repinsb__
# define repinsb(p,a,c) __repinsb (p, a, c)
#endif
#ifdef __FORWARD_repinsd__
# define repinsd(p,a,c) __repinsd (p, a, c)
#endif
#ifdef __FORWARD_repinsw__
# define repinsw(p,a,c) __repinsw (p, a, c)
#endif
#ifdef __FORWARD_repoutsb__
# define repoutsb(p,a,c) __repoutsb (p, a, c)
#endif
#ifdef __FORWARD_repoutsd__
# define repoutsd(p,a,c) __repoutsd (p, a, c)
#endif
#ifdef __FORWARD_repoutsw__
# define repoutsw(p,a,c) __repoutsw (p, a, c)
#endif
#undef __FORWARD_inb__
#undef __FORWARD_inl__
#undef __FORWARD_inw__
#undef __FORWARD_outb__
#undef __FORWARD_outl__
#undef __FORWARD_outw__
#undef __FORWARD_repinsb__
#undef __FORWARD_repinsd__
#undef __FORWARD_repinsw__
#undef __FORWARD_repoutsb__
#undef __FORWARD_repoutsd__
#undef __FORWARD_repoutsw__
#endif /* ! defined (__KERNEL_X86IO_H__) */