/************************************************************************/
/*	Copyright (C) 1986-1993 Phar Lap Software, Inc.			*/
/*	Unpublished - rights reserved under the Copyright Laws of the	*/
/*	United States.  Use, duplication, or disclosure by the 		*/
/*	Government is subject to restrictions as set forth in 		*/
/*	subparagraph (c)(1)(ii) of the Rights in Technical Data and 	*/
/*	Computer Software clause at 252.227-7013.			*/
/*	Phar Lap Software, Inc., 60 Aberdeen Ave., Cambridge, MA 02138	*/
/************************************************************************/
/* REALBREAK.C:  Get address of function in loaded into conventional */
/*		 memory with the -REALBREAK switch */

#include <stdio.h>
#include <pltypes.h>
#include <pharlap.h>

BOOL RealBreak(ULONG FuncOffs, ULONG EndOffs, REALPTR *RealFuncpp)
/*
Description:
	This routine takes the protected mode address of a function, and
	calculates the real mode address of the function in conventional
	memory.  The function must have been loaded into conventional
	memory by using the 386|DOS-Extender -REALBREAK switch.

Calling arguments:
	FuncOffs	PROTECTED mode address (offset in code segment)
			of the function
	EndOffs		PROTECTED mode address (offset in code/data segment)
			of end of real mode code and data
	RealFuncpp	Returned;  REAL mode address of the function.  The
			real mode offset of the function (RP_OFF(*RealFuncpp))
			will always be equal to the protected mode address
			of the function (FuncOffs).  This property of the
			real mode address allows the real mode code to
			reference code and data symbolically, because the
			real mode offsets and the protected mode offsets
			are the same.

Returned values:
	TRUE		if error
	FALSE		if success
*/
{
	int	errv;		// error value from 386|DOS-Extender call
	REALPTR	Realp;		// Real mode addr of function
	ULONG	RealLinAdr;	// Linear address of real mode function
	ULONG	RealSeg;	// Real mode segment address for real mode code

//
// Check to make sure all our real mode offsets fall in the first 64K of
// our protected mode segment.  If this is not true, we can't set up
// our real mode pointers the way we want to, with real mode == protected mode
// offsets
//
	if (EndOffs < FuncOffs || EndOffs > 0x10000)
	{
		printf("Illegal real mode offsets: %08Xh, %08Xh\n", FuncOffs,
							EndOffs);
		return TRUE;
	}

//
// Get the address of where the real mode code was
// loaded by calling 386|DOS-Extender.
//
	errv = _dx_torealn((void *) FuncOffs, EndOffs - FuncOffs, &Realp);
	if (errv != 0)
	{
		printf("Error from _dx_torealn, function at offset %08Xh \
not in conventional memory\n", FuncOffs);
		return TRUE;
	}

//
// Now adjust the real mode address so offsets in the real mode segment
// are the same as offsets in the protected mode segment.  This is required
// in order for real mode code to set DS = CS and reference real mode
// code and data symbolically, using link-time offsets calculated by
// the protected-mode link.
//
	RealLinAdr = ((ULONG) RP_SEG(Realp) << 4) + (ULONG) RP_OFF(Realp);
	RealLinAdr -= FuncOffs;
	if ((RealLinAdr & 0xF) != 0)
	{
		// This should NEVER happen, since all protected mode code
		// is always 4K page-aligned
		printf("Error:  Real mode code base not paragraph-aligned\n");
		return TRUE;
	}
	RealSeg = (USHORT) (RealLinAdr >> 4);
	RP_SET(*RealFuncpp, FuncOffs, RealSeg);

	return FALSE;
}
