Coherent4.2.10/include/sys/inline.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	__SYS_INLINE_H__
#define	__SYS_INLINE_H__

/*
 * This header file exists for compatibility with the System V DDI/DKI.
 * It defines some routines which are commonly kept inlined for
 * efficiency reasons (although under the full DDI/DKI regime they are not
 * in fact inlined).
 */

#include <common/feature.h>
#include <common/ccompat.h>
#include <common/xdebug.h>
#include <kernel/__pl.h>
#include <kernel/ddi_cpu.h>
#include <kernel/x86io.h>


/*
 * This header is made a little more complex by the fact that we want to
 * be able to support inlining for those compilers that can do it, yet we
 * also need to be able to use the #include <sys/ddi.h> mechanism to force
 * all of these to be bound to regular C functions.
 *
 * To support this, the initial compiler-dependent part of the
 * file performs feature tests and sets a __FORWARD_x__ macro for those
 * definitions that are to be "forwarded" via macro to a version whose name
 * has some additional leading underscores prepended.
 *
 * In this way, for systems that have inlining the #include <sys/ddi.h> will
 * suppress the forwarding.
 */

/*
 * Perform feature tests to try and work out how the processor priority
 * level can be manipulated under this machine/compiler.
 */

/*
 * The 80x86 processor and the IBM PC have numerous design problems with
 * regard to interrupt priority. Some are the result of using
 * external hardware to deal with interrupt priority level (not in itself a
 * big deal, but the 8259A on the PC ISA-bus is a problem). Others are a
 * result of the modality of the various processors in the 80x86 family and
 * the fact that none of them can emulate the others very well, by design.
 *
 * The key features are that the sti/cli instructions used in the CPU to mask
 * all interrupts are simply too coarse for regular use, plus the fact that
 * certain instructions which manipulate the processor priority at some
 * privelege levels may trap (or worse, simply do nothing) at others, meaning
 * branches and tests are required for reliable operation.
 *
 * Programming the 8259A interrupt controller directly gives the necessary
 * granularity (but may cause problems due to bus issues) and allows the
 * hard-wired priority levels to be redefined by software.
 */

#if	__GNUC__ && _I386	/* 80386 running GCC */

#define __IBM_PC__
#define	__PICC__	0x20
#define	__PICM__	0x21
#define	__SPICC__	0xA0
#define	__SPICM__	0xA1

#define	__EOI_CMD__	0x20

extern intmask_t	_masktab [];

__LOCAL__ __INLINE__ void __CHEAP_DISABLE_INTS (void) {
	__NON_ISO (asm) ("cli");
}

__LOCAL__ __INLINE__ void __CHEAP_ENABLE_INTS (void) {
	__NON_ISO (asm) ("sti");
}

__LOCAL__ __INLINE__ void __OUT_IPL_MASK (intmask_t _mask) {
	outb (__PICM__, _mask);
	outb (__SPICM__, _mask >> 8);
}

__LOCAL__ __INLINE__ intmask_t __GET_BASE_MASK (void) {
	return ddi_cpu_data ()->dc_base_mask;
}

__LOCAL__ __INLINE__ void __SET_BASE_MASK (intmask_t _mask) {
	__OUT_IPL_MASK (ddi_cpu_data ()->dc_base_mask = _mask);
}

__LOCAL__ __INLINE__ void __SEND_EOI (int _vector) {
	outb (__PICC__, __EOI_CMD__);

	if (_vector >= 8)
		outb (__SPICC__, __EOI_CMD__);
}

#define	__FORWARD_splx__
#define	__FORWARD_splraise__


#elif 	__BORLANDC__


#define __IBM_PC__
#define	__PICC__	0x20
#define	__PICM__	0x21
#define	__SPICC__	0xA0
#define	__SPICM__	0xA1

#define	__EOI_CMD__	0x20

void	__emit__ (unsigned char _byte, ...);

#define	__CLI__		0xFB
#define	__STI__		0xFA

extern intmask_t	_masktab [];

#define	__CHEAP_DISABLE_INTS()		__emit__ (__CLI__)
#define	__CHEAP_ENABLE_INTS()		__emit__ (__STI__)

#define	__OUT_IPL_MASK(mask) \
	(void) (outb (__PICM__, mask), \
		outb (__SPICM__, mask >> 8))

#define	__GET_BASE_MASK()\
		(const intmask_t) (ddi_cpu_data ()->dc_base_mask)
#define	__SET_BASE_MASK(mask)\
		(void) (ddi_cpu_data ()->dc_base_mask = (mask), \
			__OUT_IPL_MASK (ddi_cpu_data ()->dc_base_mask))

#define	__SEND_EOI(vector) \
		(outb (__PICC__, __EOI_CMD__), (vector < 8 ? (void) 0 : \
		   outb (__SPICC__, __EOI_CMD__)))

/*
 * Since BC++ 3.1 has outlawed inline functions in C code, to the point of
 * not even providing an __inline__ keyword, we can only provide in-line
 * definitions for splx () and splraise () under C++
 */

#ifdef	__cplusplus

#define	__FORWARD_splx__
#define	__FORWARD_splraise__

#endif


#elif	__COHERENT__


/*
 * Coherent's C compiler has no extensions.
 */

#define __IBM_PC__
#define	__PICC__	0x20
#define	__PICM__	0x21
#define	__SPICC__	0xA0
#define	__SPICM__	0xA1

#define	__EOI_CMD__	0x20


extern intmask_t	_masktab [];


#define	__GET_BASE_MASK()\
		(const intmask_t) (ddi_cpu_data ()->dc_base_mask)

__EXTERN_C_BEGIN__

void		__CHEAP_DISABLE_INTS	__PROTO ((void));
void		__CHEAP_ENABLE_INTS	__PROTO ((void));
void		__SET_BASE_MASK		__PROTO ((intmask_t _newmask));

__EXTERN_C_END__

#endif	/* ! __COHERENT__ */


/*
 * Generic stuff for the 80x86 IBM PC interrupt architecture.
 */

#ifdef	__IBM_PC__

#ifdef	__FORWARD_splx__

__LOCAL__ __INLINE__ __pl_t __splx (__pl_t _newpl) {
	__pl_t		_prev_pl;
	intmask_t	_mask = __GET_BASE_MASK () | _masktab [_newpl];

	__OUT_IPL_MASK (_mask);

	_prev_pl = (__pl_t) ddi_cpu_data ()->dc_ipl;
	ddi_cpu_data ()->dc_ipl = _newpl;

	return _prev_pl;
}

#endif

#ifdef	__FORWARD_splraise__

__LOCAL__ __INLINE__ __pl_t __splraise (__pl_t _newpl) {
	__pl_t		_prev_pl;

	if (_newpl > (_prev_pl = (__pl_t) ddi_cpu_data ()->dc_ipl)) {
		intmask_t	_mask = __GET_BASE_MASK () |
					_masktab [_newpl];

		__OUT_IPL_MASK (_mask);
		ddi_cpu_data ()->dc_ipl = _newpl;
	}

	return _prev_pl;
}

#endif


#define	__splbase()	splx (plbase)
#define	__spltimeout()	splx (pltimeout)
#define	__spldisk()	splx (pldisk)
#define	__splstr()	splx (plbase)
#define	__splhi()	splx (plhi)

#define	__FORWARD_splbase__
#define	__FORWARD_spltimeout__
#define	__FORWARD_spldisk__
#define	__FORWARD_splstr__
#define	__FORWARD_splhi__

#endif


/*
 * Function versions of these are available by including <sys/ddi.h> or by
 * using a compiler setup that does not permit inlining. The actual function
 * prototypes always live here, <sys/ddi.h> merely knows how to #undef some
 * names.
 */

__EXTERN_C_BEGIN__

__pl_t		splbase		__PROTO ((void));	/* enabled */
__pl_t		spltimeout	__PROTO ((void));	/* timeouts */
__pl_t		spldisk		__PROTO ((void));	/* disk I/O */
__pl_t		splstr		__PROTO ((void));	/* STREAMS */
__pl_t		splhi		__PROTO ((void));	/* disabled */
__pl_t		splx		__PROTO ((__pl_t _pl));	/* restore */

/* Internal functions - not part of DDI/DKI interface */

int		splcmp		__PROTO ((__pl_t _l, __pl_t _r));
							/* compare */
__pl_t		splraise	__PROTO ((__pl_t _pl));	/* raise priority */

__EXTERN_C_END__


/*
 * Define forwarding macros for those functions that need them.
 *
 * Note that the form of these definitions is such that they can be
 * suppressed by enclosing the name in parentheses. Simply defining a
 * token mapping is not a good idea for functions.
 */

#ifdef	__FORWARD_splbase__
# define	splbase()	__splbase ()
#endif

#ifdef	__FORWARD_spltimeout__
# define	spltimeout()	__spltimeout ()
#endif

#ifdef	__FORWARD_spldisk__
# define	spldisk()	__spldisk ()
#endif

#ifdef	__FORWARD_splstr__
# define	splstr()	__splstr ()
#endif

#ifdef	__FORWARD_splhi__
# define	splhi()		__splhi ()
#endif

#ifdef	__FORWARD_splx__
# define	splx(x)		__splx (x)
#endif

#ifdef	__FORWARD_splcmp__
# define	splcmp(l,r)	__splcmp (l,r)
#endif

#ifdef	__FORWARD_splraise__
# define	splraise(x)	__splraise(x)
#endif


/*
 * Clean up the macros we #define
 */

#undef	__IBM_PC__
#undef	__FORWARD_splbase__
#undef	__FORWARD_spltimeout__
#undef	__FORWARD_spldisk__
#undef	__FORWARD_splstr__
#undef	__FORWARD_splhi__
#undef	__FORWARD_splx__
#undef	__FORWARD_splcmp__
#undef	__FORWARD_splraise__

#endif	/* ! defined (__SYS_INLINE_H__) */