/* Application - HPDI32 - Any OS */
/* $Workfile: util_id.c $ */
/* $Revision: 5 $ */
/* $Date: 9/16/08 9:10a $ */
/* $Log: /NEW SOURCESAFE DATABASE/SDK/hpdi32/utils/util_id.c $
 * 
 * 5     9/16/08 9:10a Dnewbold
 * 
 * 4     3/12/08 6:14p Dnewbold
 * White space reduction.
 * 
 * 3     10/27/07 4:22p Dnewbold
 * Linux porting changes.
 * 
 * 2     1/12/07 10:09a Dnewbold
 * Added id_features().
 * 
 * 1     8/22/05 4:02p Dnewbold
*/

#include <stdio.h>

#include "util_id.h"

#include "hpdi32_api.h"
#include "util_label.h"
#include "util_reg.h"



/*****************************************************************************
*
*	Function:	_id_api
*
*	Purpose:
*
*		Report the API version number the application was programmed for.
*
*	Arguments:
*
*		None.
*
*	Returned:
*
*		>= 0	The number of errors encountered here.
*
*****************************************************************************/

static int _id_api(void)
{
	label_text("API Interface Version");
	printf("%d\n", HPDI32_API_VERSION);
	return(0);
}



/*****************************************************************************
*
*	Function:	_id_api_lib
*
*	Purpose:
*
*		Report the version number for the API Library.
*
*	Arguments:
*
*		None.
*
*	Returned:
*
*		>= 0	The number of errors encountered here.
*
*****************************************************************************/

static int _id_api_lib(void)
{
	char	buf[64];
	int		errs;
	U32		status;

	label_text("SDK Library Version");
	status	= hpdi32_version_get(NULL, GSC_VERSION_LIBRARY, buf, sizeof(buf));

	if (status == GSC_SUCCESS)
	{
		errs	= 0;
		printf("%s\n", buf);
	}
	else
	{
		errs	= label_fail_func(1, "hpdi32_version_get", status);
	}

	return(errs);
}



/*****************************************************************************
*
*	Function:	_id_app
*
*	Purpose:
*
*		Identify the application.
*
*	Arguments:
*
*		dev		The handle of the board to access.
*
*	Returned:
*
*		None.
*
*****************************************************************************/

static int _id_app(const char* version)
{
	if (version)
	{
		label_text("Application Version");
		printf("%s\n", version);
	}

	return(0);
}



/*****************************************************************************
*
*	Function:	_id_driver
*
*	Purpose:
*
*		Report the version number for the driver.
*
*	Arguments:
*
*		dev		The handle for the device.
*
*	Returned:
*
*		>= 0	The number of errors encountered here.
*
*****************************************************************************/

static int _id_driver(void* dev)
{
	char	buf[64];
	int		errs;
	U32		status;

	label_text("Device Driver Version");
	status	= hpdi32_version_get(dev, GSC_VERSION_DRIVER, buf, sizeof(buf));

	if (status == GSC_SUCCESS)
	{
		errs	= 0;
		printf("%s\n", buf);
	}
	else
	{
		errs	= label_fail_func(1, "hpdi32_version_get", status);
	}

	return(errs);
}



/*****************************************************************************
*
*	Function:	_id_frr_new
*
*	Purpose:
*
*		Identify the board using the Firmware Revision Register, which follows
*		the updated specification.
*
*	Arguments:
*
*		frr		The value read from the Firmware Revision Register.
*
*	Returned:
*
*		>= 0	The number of errors encountered here.
*
*****************************************************************************/

static int _id_frr_new(U32 frr)
{
	static const char*	_form_factor[]	=
		{
			"RESERVED",
			"PCI",
			"PMC",
			"cPCI",
			"PC104+",
			"RESERVED",
			"RESERVED",
			"RESERVED",
			"RESERVED",
			"RESERVED",
			"RESERVED",
			"RESERVED",
			"RESERVED",
			"RESERVED",
			"RESERVED",
			"RESERVED"
		};

	int		errs	= 0;
	U32		fld;
	const char*	psz;

	label_text("Feature Set Register");
	fld	= (frr & 0x80000000) >> 28;
	printf("0x%01lX-------  ", (long) fld);
	printf("(%s)\n", fld ? "yes" : "no");

	label_text("Conformant");
	fld	= (frr & 0x40000000) >> 28;
	printf("0x%01lX-------  ", (long) fld);
	printf("(%s)\n", fld ? "yes" : "no");

	label_text("Reserved");
	fld	= (frr & 0x20000000) >> 28;
	printf("0x%01lX-------  ", (long) fld);
	printf("\n");

	label_text("Bus Size");
	fld	= (frr & 0x10000000) >> 28;
	printf("0x%01lX-------  ", (long) fld);
	printf("(%s-bits)\n", fld ? "64" : "32");

	label_text("Form Factor");
	fld	= (frr & 0x0F000000) >> 24;
	printf("0x-%01lX------  ", (long) fld);
	psz	= _form_factor[fld];
	printf("(%s)\n", psz);

	label_text("Hardware Revision");
	fld	= (frr & 0x00FF0000) >> 16;
	printf("0x--%02lX----  ", (long) fld);

	if (fld == 0)
		printf("(no revisions)\n");
	else
		printf("(Rev. %c)\n", (char) ('A' + fld - 1));

	label_text("Board Version");
	fld	= (frr & 0x0000FF00) >> 8;
	printf("0x----%02lX--  ", (long) fld);
	printf("\n");

	label_text("Firmware Revision");
	fld	= (frr & 0x000000FF) >> 0;
	printf("0x------%02lX  ", (long) fld);
	printf("\n");

	return(errs);
}



/*****************************************************************************
*
*	Function:	_id_frr_old
*
*	Purpose:
*
*		Identify the board using the Firmware Revision Register, which follows
*		the original format.
*
*	Arguments:
*
*		didd	The value read from the Device ID Register.
*
*		frr		The value read from the Firmware Revision Register.
*
*	Returned:
*
*		>= 0	The number of errors encountered here.
*
*****************************************************************************/

static int _id_frr_old(U32 didr, U32 frr)
{
	char	buf[64];
	int		errs	= 0;
	U32		fld;
	U32		reg;
	U32		tmp;

	label_text("Firmware Revision");
	fld	= HPDI32_FRR_FIRMWARE_DECODE(frr);
	reg	= HPDI32_FRR_FIRMWARE_ENCODE(fld);
	printf("0x%08lX  (0x%02lX)\n", (long) reg, (long) fld);

	label_text("PCB Revision");
	fld	= HPDI32_FRR_PCB_DECODE(frr);
	reg	= HPDI32_FRR_PCB_ENCODE(fld);
	printf("0x%08lX  (0x%02lX, ", (long) reg, (long) fld);

	if (fld == 0)
		printf("no revisions)\n");
	else
		printf("Rev. %c)\n", (char) ('A' + fld - 1));

	label_text("Sub ID");
	fld	= HPDI32_FRR_SUB_ID_DECODE(frr);
	reg	= HPDI32_FRR_SUB_ID_ENCODE(fld);
	printf("0x%08lX  (0x%02lX)\n", (long) reg, (long) fld);

	label_text("Reserved");
	fld	= HPDI32_FRR_RESERVED_DECODE(frr);
	reg	= HPDI32_FRR_RESERVED_ENCODE(fld);
	printf("0x%08lX  (0x%02lX)\n", (long) reg, (long) fld);
	label_level_inc();

	if (didr == HPDI32_DEVICE_ID_32)
	{
		fld	&= ~HPDI32_FRR_RESERVED_PMC;
		label_text("PMC Form Factor");
		tmp	= HPDI32_FRR_RES_PMC_DECODE(frr);
		reg	= HPDI32_FRR_RES_PMC_ENCODE(tmp);
		printf("0x%08lX  (0x%01lX, ", (long) reg, (long) tmp);
			
		if (tmp)
			printf("Yes, PMC)\n");
		else
			printf("No)\n");
	}

	if (didr == HPDI32_DEVICE_ID_64)
	{
		fld	&= ~HPDI32_FRR_RESERVED_FW_64;
		label_text("64-bit Firmware");
		tmp	= HPDI32_FRR_RES_FW_64_DECODE(frr);
		reg	= HPDI32_FRR_RES_FW_64_ENCODE(tmp);
		printf("0x%08lX  (0x%01lX, ", (long) reg, (long) tmp);
			
		if (tmp)
			printf("Yes, 64-bit)\n");
		else
			printf("No, 32-bit)\n");
	}

	if (fld)
	{
		label_text("Remaining Bits");
		reg	= HPDI32_FRR_RESERVED_ENCODE(fld);
		printf("0x%08lX  ", (long) reg);
		sprintf(buf, "0x%02lX, NOT RECOGNIZED", (long) fld);
		errs	+= label_fail_text(1, buf);
	}

	label_level_dec();

	label_text("Conformant");
	fld	= HPDI32_FRR_CONFORM_DECODE(frr);
	reg	= HPDI32_FRR_CONFORM_ENCODE(fld);
	printf("0x%08lX  ", (long) reg);
	sprintf(buf, "0x%01lX, Yes, updated specification", (long) fld);

	if (fld)
		errs	+= label_fail_text(1, buf);
	else
		printf("(0x%01lX, No, original format)\n", (long) fld);

	label_text("Feature Set Register");
	fld	= HPDI32_FRR_FSR_DECODE(frr);
	reg	= HPDI32_FRR_FSR_ENCODE(fld);
	printf("0x%08lX  (0x%01lX, ", (long) reg, (long) fld);

	if (fld)
		printf("Yes, implemented)\n");
	else
		printf("No, not supported)\n");

	return(errs);
}



/*****************************************************************************
*
*	Function:	_id_frr
*
*	Purpose:
*
*		Identify the board using the Firmware Revision Register.
*
*	Arguments:
*
*		dev		The handle of the device to access.
*
*		didr	The value read from the PCI ID Register.
*
*		frr		The value read from the FRR is put here.
*
*	Returned:
*
*		>= 0	The number of errors encountered here.
*
*****************************************************************************/

static int _id_frr(void* dev, U32 didr, U32* frr)
{
	int	errs;

	label_text("Firmware Rev. Register");
	errs	= dev_reg_read(dev, HPDI32_FRR, frr, 1);

	if (errs == 0)
	{
		printf("0x%08lX  ", (long) frr[0]);

		if (frr[0] & HPDI32_FRR_CONFORMANT)
		{
			printf("(updated specification)\n");
			label_level_inc();
			errs	= _id_frr_new(frr[0]);
			label_level_dec();
		}
		else
		{
			printf("(original format)\n");
			label_level_inc();
			errs	= _id_frr_old(didr, frr[0]);
			label_level_dec();
		}
	}

	return(errs);
}



/*****************************************************************************
*
*	Function:	_id_pci
*
*	Purpose:
*
*		Identify the board using the PCI register information.
*
*	Arguments:
*
*		dev		The handle of the device to access.
*
*		didr	The PCI Device ID Register value is recorded here.
*
*	Returned:
*
*		>= 0	The number of errors encountered here.
*
*****************************************************************************/

static int _id_pci(void* dev, U32* didr)
{
	int	err;
	int	errs	= 0;
	U32	sid;
	U32	svid;
	U32	vidr;

	/*
	*	Vendor ID
	*/

	label_text("Vendor ID");
	err		= dev_reg_read(dev, GSC_PCI_9080_VIDR, &vidr, 1);
	errs	+= err;

	if (err == 0)
	{
		printf("0x%04lX      ", (long) vidr);

		if (vidr == HPDI32_VENDOR_ID)
			printf("(PLX)\n");
		else
			errs	+= label_fail_text(1, "NOT RECOGNIZED");
	}

	/*
	*	Device ID
	*/

	label_text("Device ID");
	err		= dev_reg_read(dev, GSC_PCI_9080_DIDR, didr, 1);
	errs	+= err;

	if (err == 0)
	{
		printf("0x%04lX      ", (long) didr[0]);

		if (didr[0] == HPDI32_DEVICE_ID_32)
			printf("(PCI9080)\n");
		else if (didr[0] == HPDI32_DEVICE_ID_64)
			printf("(PCI9656)\n");
		else
			errs	+= label_fail_text(1, "NOT RECOGNIZED");
	}

	/*
	*	Subsystem Vendor ID
	*/

	label_text("Subsystem Vendor ID");
	err		= dev_reg_read(dev, GSC_PCI_9080_SVID, &svid, 1);
	errs	+= err;

	if (err == 0)
	{
		printf("0x%04lX      ", (long) svid);

		if (svid == HPDI32_SUBVENDOR_ID)
			printf("(Subsystem ID is PLX assigned)\n");
		else
			errs	+= label_fail_text(1, "NOT RECOGNIZED");
	}

	/*
	*	Subsystem ID
	*/

	label_text("Subsystem ID");
	err		= dev_reg_read(dev, GSC_PCI_9080_SID, &sid, 1);
	errs	+= err;

	if (err == 0)
	{
		printf("0x%04lX      ", (long) sid);

		if (sid == HPDI32_SUBSYSTEM_ID_32)
			printf("(HPDI32, 32-bit PCI)\n");
		else if (sid == HPDI32_SUBSYSTEM_ID_64)
			printf("(HPDI32, 64-bit PCI)\n");
		else
			errs	+= label_fail_text(1, "NOT RECOGNIZED");
	}

	/*
	*	ID Consistance
	*/

	if (	(!((didr[0] == HPDI32_DEVICE_ID_32) && (sid == HPDI32_SUBSYSTEM_ID_32))) &&
			(!((didr[0] == HPDI32_DEVICE_ID_64) && (sid == HPDI32_SUBSYSTEM_ID_64))))
	{
		label_text("Consistancy");
		errs	+= label_fail_text(1, "device id and subsystem id mismatch");
	}

	return(errs);
}



/*****************************************************************************
*
*	Function:	_id_fsr
*
*	Purpose:
*
*		Identify the board using the Features Register.
*
*	Arguments:
*
*		dev		The handle used to access the device.
*
*		frr		The value read from the Firmware Revision Register.
*
*	Returned:
*
*		>= 0	The number of errors encountered here.
*
*****************************************************************************/

static int _id_fsr(void* dev, U32 frr)
{
	int	errs	= 0;
	U32	fld;
	U32	fsr;

	if (frr & HPDI32_FRR_FSR)
	{
		label_text("Feature Set Register");
		errs	= dev_reg_read(dev, HPDI32_FSR, &fsr, 1);
	}


	if ((frr & HPDI32_FRR_FSR) && (errs == 0))
	{
		printf("0x%08lX\n", (long) fsr);
		label_level_inc();

		fld	= fsr & HPDI32_FSR_TFSR_RFSR;
		fsr	&= ~fld;
		label_text("FIFO Size Registers");
		printf("0x%08lX  (%s)\n", (long) fld, fld ? "Yes" : "No");

		fld	= fsr & HPDI32_FSR_TFWR_RFWR;
		fsr	&= ~fld;
		label_text("FIFO Words Registers");
		printf("0x%08lX  (%s)\n", (long) fld, fld ? "Yes" : "No");

		fld	= fsr & HPDI32_FSR_IELR_IHLR;
		fsr	&= ~fld;
		label_text("IRQ Config Registers");
		printf("0x%08lX  (%s)\n", (long) fld, fld ? "Yes" : "No");

		fld	= fsr & HPDI32_FSR_GPIO_0_5;
		fsr	&= ~fld;
		label_text("GPIO 0-5 Signals");
		printf("0x%08lX  (%s)\n", (long) fld, fld ? "Yes" : "No");

		fld	= fsr & HPDI32_FSR_DMDMA_CH1;
		fsr	&= ~fld;
		label_text("Tx DMDMA on Chan. 1");
		printf("0x%08lX  (%s)\n", (long) fld, fld ? "Yes" : "No");

		fld	= fsr & HPDI32_FSR_OVR_UNDR_RUN;
		fsr	&= ~fld;
		label_text("Tx/Rx Over/Under Run");
		printf("0x%08lX  (%s)\n", (long) fld, fld ? "Yes" : "No");

		fld	= fsr & HPDI32_FSR_GPIO6_TXAS;
		fsr	&= ~fld;
		label_text("GPIO 6 Signal");
		printf("0x%08lX  (%s)\n", (long) fld, fld ? "Yes" : "No");
		label_text("Tx Auto Stop Control");
		printf("0x%08lX  (%s)\n", (long) fld, fld ? "Yes" : "No");

		fld	= fsr & HPDI32_FSR_SCD;
		fsr	&= ~fld;
		label_text("Single Cycle Disable");
		printf("0x%08lX  (%s)\n", (long) fld, fld ? "Yes" : "No");

		label_text("Reserved");
		printf("0x%08lX  \n", (long) fsr);

		label_level_dec();
	}

	return(errs);
}



/*****************************************************************************
*
*	Function:	_id_user_jumpers
*
*	Purpose:
*
*		Identify the board using the User Jumpers.
*
*	Arguments:
*
*		dev		The handle of the device to access.
*
*	Returned:
*
*		>= 0	The number of errors encountered here.
*
*****************************************************************************/

static int _id_user_jumpers(void* dev)
{
	unsigned long	bj;
	int				errs;
	unsigned long	feature;
	U32				status;

	for (;;)
	{
		label_text("User Jumpers");

		status	= HPDI32_MISC_FEATURES__USER_JUMPERS(dev, &feature);

		if (status != GSC_SUCCESS)
		{
			errs	= label_fail_func(	1,
										"HPDI32_MISC_FEATURES__USER_JUMPERS",
										status);
			break;
		}

		if (feature != HPDI32_MISC_FEATURES_PRESENT)
		{
			errs	= 0;
			printf("(not supported)\n");
			break;
		}

		status	= HPDI32_MISC_BOARD_JUMPERS__GET(dev, &bj);

		if (status != GSC_SUCCESS)
		{
			errs	= label_fail_func(	1,
										"HPDI32_MISC_BOARD_JUMPERS__GET",
										status);
			break;
		}

		errs	= 0;
		printf(	"0x%01lX         (UJ1 %s, UJ0 %s)\n",
				bj,
				(bj & 0x2) ? "On" : "Off",
				(bj & 0x1) ? "On" : "Off");
		break;
	}

	return(errs);
}



/*****************************************************************************
*
*	Function:	id_hardware
*
*	Purpose:
*
*		Identify the hardware being used.
*
*	Arguments:
*
*		dev		The handle for the device.
*
*		index	The index of the device.
*
*	Returned:
*
*		>= 0	The number of errors encountered here.
*
*****************************************************************************/

int id_hardware(void* dev, int index)
{
	char	buf[128];
	U32		didr;
	int		errs	= 0;
	U32		frr;

	sprintf(buf, "Hardware Identification (#%d)", index);
	label_text(buf);
	printf("\n");
	label_level_inc();

	errs	+= _id_pci(dev, &didr);
	errs	+= _id_frr(dev, didr, &frr);
	errs	+= _id_fsr(dev, frr);
	errs	+= _id_user_jumpers(dev);

	label_level_dec();
	return(errs);
}



/*****************************************************************************
*
*	Function:	_id_feature_count
*
*	Purpose:
*
*		Test and report on the feature count value reported by the API.
*
*	Arguments:
*
*		get		The results reported by the query.
*
*	Returned:
*
*		>= 0	The number of errors encountered here.
*
*****************************************************************************/

static int _id_feature_count(U32 get)
{
	char	buf[64];
	int		errs	= 0;
	U32		exp		= HPDI32_MISC_FEATURES_LAST_INDEX + 1;

	printf("%ld  ", (long) get);

	if (get == exp)
	{
		printf("\n");
	}
	else
	{
		sprintf(buf, "%ld was expected", (long) exp);
		errs	+= label_fail_text(1, buf);
	}

	return(errs);
}



/*****************************************************************************
*
*	Function:	_id_feature_yes_no
*
*	Purpose:
*
*		Report the YES/NO results of a feature query.
*
*	Arguments:
*
*		get		The results reported by the query.
*
*	Returned:
*
*		>= 0	The number of errors encountered here.
*
*****************************************************************************/

static int _id_feature_yes_no(U32 get)
{
	int	errs;

	if (get == HPDI32_MISC_FEATURES_ABSENT)
	{
		errs	= 0;
		printf("No\n");
	}
	else if (get == HPDI32_MISC_FEATURES_PRESENT)
	{
		errs	= 0;
		printf("Yes\n");
	}
	else
	{
		errs	= label_fail_value(1, get);
	}

	return(errs);
}



/*****************************************************************************
*
*	Function:	id_features
*
*	Purpose:
*
*		Identify the board's set of features.
*
*	Arguments:
*
*		dev		The handle for the device of interest.
*
*	Returned:
*
*		>= 0	The number of errors encountered here.
*
*****************************************************************************/

int id_features(void* dev)
{
	static const struct
	{
		U32			feature;
		const char*	text;
		int			(*id)(U32 get);
	} list[]	=
	{
		{
		/* feature	*/	HPDI32_MISC_FEATURES_COUNT,
		/* text		*/	"Feature Count",
		/* id		*/	_id_feature_count
		},
		{
		/* feature	*/	HPDI32_MISC_FEATURES_FSR,
		/* text		*/	"Feature Set Register",
		/* id		*/	_id_feature_yes_no
		},
		{
		/* feature	*/	HPDI32_MISC_FEATURES_FIFO_SIZE,
		/* text		*/	"FIFO Size Registers",
		/* id		*/	_id_feature_yes_no
		},
		{
		/* feature	*/	HPDI32_MISC_FEATURES_ICR,
		/* text		*/	"IRQ Config Registers",
		/* id		*/	_id_feature_yes_no
		},
		{
		/* feature	*/	HPDI32_MISC_FEATURES_GPIO_0_5,
		/* text		*/	"GPIO 0-5 Signals",
		/* id		*/	_id_feature_yes_no
		},
		{
		/* feature	*/	HPDI32_MISC_FEATURES_GPIO_6,
		/* text		*/	"GPIO 6 Signal",
		/* id		*/	_id_feature_yes_no
		},
		{
		/* feature	*/	HPDI32_MISC_FEATURES_DMA_CH1,
		/* text		*/	"Tx DMDMA on Chan. 1",
		/* id		*/	_id_feature_yes_no
		},
		{
		/* feature	*/	HPDI32_MISC_FEATURES_OVR_UNDR_RUN,
		/* text		*/	"Tx/Rx Over/Under Run",
		/* id		*/	_id_feature_yes_no
		},
		{
		/* feature	*/	HPDI32_MISC_FEATURES_TX_AUTO_STOP,
		/* text		*/	"Tx Auto Stop Control",
		/* id		*/	_id_feature_yes_no
		},
		{
		/* feature	*/	HPDI32_MISC_FEATURES_1_CYCLE_DISABLE,
		/* text		*/	"Single Cycle Disable",
		/* id		*/	_id_feature_yes_no
		},
		{
		/* feature	*/	HPDI32_MISC_FEATURES_USER_JUMPERS,
		/* text		*/	"User Jumpers",
		/* id		*/	_id_feature_yes_no
		},
		{ 0, NULL, NULL }
	};

	int				err;
	int				errs	= 0;
	unsigned long	get;
	int				i;
	U32				status;

	label_text("Features");
	printf("\n");
	label_level_inc();

	for (i = 0; list[i].text; i++)
	{
		label_text(list[i].text);
		status	= HPDI32_MISC_FEATURES__GET(dev, list[i].feature, &get);
		err		= label_fail_func(1, "HPDI32_MISC_FEATURES__GET", status);

		if (err)
			errs++;
		else
			errs	+= list[i].id(get);
	}

	if (i != (HPDI32_MISC_FEATURES_LAST_INDEX + 1))
	{
		label_text("Tested Features");
		errs	+= label_fail_text(1, "some features are untested");
	}

	label_level_dec();
	return(errs);
}



/*****************************************************************************
*
*	Function:	id_software
*
*	Purpose:
*
*		Identify the software being used.
*
*	Arguments:
*
*		dev		The handle for the device.
*
*		app_ver	The version for the application.
*
*	Returned:
*
*		>= 0	The number of errors encountered here.
*
*****************************************************************************/

int id_software(void* dev, const char* app_ver)
{
	int		errs	= 0;

	label_text("Software Identification");
	printf("\n");
	label_level_inc();

	errs	+= _id_app(app_ver);
	errs	+= _id_api();
	errs	+= _id_api_lib();
	errs	+= _id_driver(dev);

	label_level_dec();
	return(errs);
}



//*****************************************************************************
long long id_total_mem_silent(void)
{
	char		buf[1024];
	int			end;
	char		factor	= 0;
	FILE*		file;
	int			i;
	long		mb;
	long		mem;
	long long	total	= 0;

	file	= fopen("/proc/meminfo", "r");

	if (file)
	{
		for (;;)
		{
			end	= feof(file);

			if (end)
				break;

			fgets(buf, sizeof(buf), file);
			i	= sscanf(buf, "MemTotal: %ld %c", &mem, &factor);

			if (i == 2)
				break;
		}

		fclose(file);
	}

	total	= mem;

	switch (factor)
	{
		case 't':
		case 'T':	total	*= 1024;	break;	// change to G bytes
		case 'g':
		case 'G':	total	*= 1024;	break;	// change to M bytes
		case 'm':
		case 'M':	total	*= 1024;	break;	// change to K bytes
		case 'k':
		case 'K':	total	*= 1024;	break;	// change to bytes
		case 'b':
		case 'B':
		default:						break;
	}

	mb	= total / (1024L * 1024L);

	if (mb == 0)
	{
	}
	else if (mb <= 512)
	{
		mb		= (((mb + 63) / 64) * 64);
		total	= mb * 1024 * 1024;
	}
	else if (mb <= 1024)
	{
		mb	= (((mb + 127) / 128) * 128);
		total	= mb * 1024 * 1024;
	}
	else
	{
		total	= (((mb + 255) / 256) * 256);
		total	= mb * 1024 * 1024;
	}

	return(total);
}


