www.pudn.com > ScriptsSample.zip > GEN_TOOL.C


/*************************************************************************** 
 *                                                                         * 
 *  Copyright 1995 Symbios Logic Incorporated.  All rights reserved.       * 
 *                                                                         * 
 * This software was written by Symbios Logic Inc. to develop and test new * 
 * products.  Symbios Logic assumes no liability for its use. This software* 
 * is released to the public domain to illustrate certain programming      * 
 * techniques for testing the 53c8xx chips                                 * 
 *                                                                         * 
 ***************************************************************************/ 
 
/*           Name:  GEN_TOOL.C 
 *          Title:  Validation test code generic tools 
 *      $Workfile:  $ 
 *      $Revision:  $ 
 *       $Modtime:  $ 
 *     Programmer: Symbios Logic  
 *  Creation Date:  11/29/95 
 * 
 *  Version History 
 *  --------------- 
 * 
 *    Date    Who?  Description 
 *  --------  ----  ------------------------------------------------------- 
#BeginRevision 
 *  03/06/96  SYM   - Made general formatting changes and documentation 
 *						  additions 
 *						  - Changed IORead/Write32 to inline assembly functions 
 *						  - Added Random buffer init to InitBuffer function 
 *						  - Fixed problem with InitBuffer func. 1.  It wouldn't 
 *						  increment by fill value, just by 1 always. 
 *						  - Changed Writelog Detail output so that it won't put 
 *						  /n's in the String.  Carraige returns are now at the 
 *						  descretion of the user. 
 *						  - Changed all fprintf's that went to stderr to go to 
 *						  stdout instead. 
 * 
 #EndRevision 
 * 
 *  11/29/95  SYM   Initial Revision. 
 * 
#BeginDescription 
 * 
 *  This file contains generic functions which allow manipulation of    
 *  data buffers, determination of physical addresses, log file entries 
 *  and other general purpose tools.  These routines are not device 
 *  specific and can be ported to other hardware interfaces. 
 * 
#EndDescription 
 * 
 *------------------------------------------------------------------------- 
 * 
 *  $Header: $ 
 * 
 */ 
 
#include "valtypes.h" 
#include "gen_tool.h" 
#include  
#include  
#include  
 
/* This tells the compiler that there is assembly code in this file */ 
#pragma inline 
 
/* Function prototypes */ 
VULONG getPhysAddr(void far * addr); 
VUBYTE IORead8(VULONG IO_Addr); 
void IOWrite8(VULONG IO_Addr, VUBYTE value); 
VULONG IORead32(VULONG IO_Addr); 
void IOWrite32(VULONG IO_Addr, VULONG value); 
void far *ByteAlignBuffer(void far *buffer, VINT alignment); 
void far *CacheAlignBuffer(void far *buffer, VINT cls, VINT offset); 
void InitBuffer(VUBYTE far *buffer, VUINT size, VINT operation, 
						VUBYTE fill_val); 
VULONG Get_Time(void); 
VINT HasTimeElapsed(VULONG StartTime, VINT Seconds); 
VINT WriteLog(VINT P_F, VINT B_D, VCHAR *Str1, VCHAR *Str2); 
 
/****************************************************************************** 
 Function: getPhysAddr 
	Purpose: To determine the physical address of a given pointer 
	Input: far pointer to a data buffer 
	Output: Physical address of the pointer 
	Assumptions: Executable is currently running in DOS real mode. 
	Restrictions: This function will not work properly unless it is  
		      running in DOS real mode.  This does not include 
		      a Windows DOS shell or any other type of DOS 
		      shell running under a protected mode Operating system 
	Other functions called: none 
 
******************************************************************************/ 
 
VULONG getPhysAddr(void far * addr) 
{ 
	 VULONG seg, off; 
 
	 seg = FP_SEG(addr);            /* get segment of pointer */ 
	 off = FP_OFF(addr);            /* get offset of pointer */ 
 
	 return ((seg << 4) + off); 
} 
 
/****************************************************************************** 
 Function: IORead8 
	Purpose: To read a byte from an io port 
	Input: IO address of byte to be read 
	Output: byte read from io port 
	Assumptions: That the IO port actually exists 
	Restrictions: Although IO_Addr is defined as a VULONG it must not 
		      exceed 16 bits in length as this is the maximum 
		      IO address the X86 archtecture can produce 
	Other functions called: inportb to read the io port 
 
******************************************************************************/ 
 
VUBYTE IORead8(VULONG IO_Addr) 
{ 
 
	return (inportb((VUINT) IO_Addr)); 
 
} 
 
/****************************************************************************** 
 Function: IOWrite8 
	Purpose: To write a byte out to an IO port 
	Input: Value to be written and IO port address 
	Output: None 
	Assumptions: That the IO port actually exists 
	Restrictions: Although IO_Addr is defined as a VULONG it must not 
				exceed 16 bits in length as this is the maximum 
				IO address the X86 archtecture can produce 
	Other functions called: outportb to write to the io port 
 
******************************************************************************/ 
 
void IOWrite8(VULONG IO_Addr, VUBYTE value) 
{ 
 
	outportb((VUINT) IO_Addr, value); 
 
} 
 
/****************************************************************************** 
 Function: IORead32 
	Purpose: To read a dword (32 bits) from an io port 
	Input: IO address of dword to be read 
	Output: dword read from io port 
	Assumptions: That the IO port actually exists 
	Restrictions: Although IO_Addr is defined as a VULONG it must not 
		      exceed 16 bits in length as this is the maximum 
		      IO address the X86 archtecture can produce 
	Other functions called: none 
 
******************************************************************************/ 
 
VULONG IORead32(VULONG IO_Addr) 
{ 
 
	VULONG result; 
 
	asm 
	{ 
		.386 
		mov dx, [IO_Addr] 
		in eax, dx 
		mov [result], eax 
	} 
 
   return(result); 
 
} 
 
/****************************************************************************** 
 Function: IOWrite32 
	Purpose: To write a dword (32 bits) out to an IO port 
	Input: Value to be written and IO port address 
	Output: None 
	Assumptions: That the IO port actually exists 
	Restrictions: Although IO_Addr is defined as a VULONG it must not 
		      exceed 16 bits in length as this is the maximum 
		      IO address the X86 archtecture can produce 
	Other functions called: none 
 
******************************************************************************/ 
 
void IOWrite32(VULONG IO_Addr, VULONG value) 
{ 
 
	asm 
	{ 
		.386 
		mov dx, [IO_Addr] 
		mov eax, [value] 
		out dx, eax 
	} 
} 
 
/****************************************************************************** 
 Function: ByteAlignBuffer 
	Purpose: To align a buffer to a given byte alignment 
	Input: Pointer to buffer to be aligned. Buffer should be 3 bytes  
	       larger than it's desired size. 
	       Desired alignment of the given buffer. 
		 0 = dword (32-bit) aligned 
		 1 = byte (8-bit) aligned 
		 2 = word (16-bit) aligned 
		 3 = 3byte (24-bit) aligned 
	Output: Pointer to requested buffer alignment.  The pointer will 
		be as close to the buffer start address as possible. 
	Assumptions: Executable is currently running in DOS real mode. 
	Restrictions: This function will not work properly unless it is  
		      running in DOS real mode.  This does not include 
		      a Windows DOS shell or any other type of DOS 
		      shell running under a protected mode Operating system 
	Other functions called: FP_SEG to get buffer segment 
				FP_OFF to get buffer offset 
				MK_FP to create a new far pointer to the 
				requested buffer alignment 
 
******************************************************************************/ 
 
void far *ByteAlignBuffer(void far *buffer, VINT alignment) 
{ 
	VUINT seg; 
	VUINT off; 
 
	seg = FP_SEG(buffer); 
	off = FP_OFF(buffer) + (((4+alignment) - (FP_OFF(buffer)&0x03)) & 0x03); 
	return(MK_FP(seg,off)); 
 
} 
 
/****************************************************************************** 
 Function: CacheAlignBuffer 
	Purpose: To align a buffer to a given cache alignment 
	Input: pointer to data buffer to be aligned.  Buffer should be a  
	       cache line size larger than the desired buffer size. 
	       The cache line size to be aligned to.  This does not have 
	       to be the cache line size of the system. 
	       An offset from the cache line boundary 
	Output: A pointer to the cache line boundary plus the offset based 
		on the provided cache line size.  The pointer will be as 
		close to the begining of the buffer as possible. 
	Assumptions: Executable is currently running in DOS real mode. 
	Restrictions: This function will not work properly unless it is  
		      running in DOS real mode.  This does not include 
		      a Windows DOS shell or any other type of DOS 
		      shell running under a protected mode Operating system 
	Other functions called: FP_SEG to get buffer segment 
				FP_OFF to get buffer offset 
				MK_FP to create a new far pointer to the 
				requested buffer alignment 
 
******************************************************************************/ 
 
void far *CacheAlignBuffer(void far *buffer, VINT cls, VINT offset) 
{ 
  VUINT seg; 
  VUINT off; 
 
  seg = FP_SEG(buffer); 
  off = FP_OFF(buffer) + (((cls*4+offset) - (FP_OFF(buffer)&(cls*4-1))) & (cls*4-1)); 
  return (MK_FP(seg, off)); 
 
} 
 
/****************************************************************************** 
 Function: InitBuffer 
	Purpose: To initialize a buffer to a known value 
	Input: Far pointer to a byte data buffer. 
	       The size of the data buffer. 
	       The fill/increment value for the buffer 
	       The operation to be performed on the buffer 
		  0 - fill buffer with fill value 
		  1 - fill buffer with incrementing pattern, increment by 
				the fill value and start at 0. 
		  2 - fill buffer with random values. 
		  default is to fill buffer with 0's. 
	Output: Initialized buffer 
	Assumptions: none 
	Restrictions: Buffer size cannot exceed 64k 
	Other functions called: none 
 
******************************************************************************/ 
 
void InitBuffer(VUBYTE far *buffer, VUINT size, VINT operation, 
						VUBYTE fill_val) 
{ 
	VUINT i; 
 
	switch(operation) 
	{ 
		case 0x00:  for(i=0; i < size; i++) buffer[i] = fill_val; 
						break; 
		case 0x01:  buffer[0] = 0; 
						for(i=1; i < size; i++) buffer[i] = buffer[i-1] + fill_val; 
						break; 
		case 0x02:	for(i=0; i < size; i++) buffer[i] = rand() % fill_val; 
						break; 
		default:    for(i=0; i < size; i++) buffer[i] = 0; 
	} 
 
} 
 
/****************************************************************************** 
 Function: Get_Time 
	Purpose: Gets the current timer tick value from the system bios  
		 data area.  The timer ticks 18.2 times every second. 
	Input: none 
	Output: Current value of the timer 
	Assumptions: None 
	Restrictions: None 
	Other functions called: MK_FP to create a pointer to the timer tick 
				memory location 
				enable to enable interrupts 
				disable to disable interrupts 
 
******************************************************************************/ 
 
VULONG Get_Time(void) 
 
{ 
	VULONG far *timer_ptr; 
	VULONG time; 
 
	/* force ptr to point to timer in bios area */ 
	timer_ptr = MK_FP(0x40, 0x6C); 
 
 
	/* shut off interrupts */ 
	disable(); 
	/* get current time */ 
	time = *timer_ptr; 
	/* turn interrupts back on */ 
	enable(); 
 
	return(time); 
 
} 
 
/****************************************************************************** 
 Function: HasTimeElapsed 
	Purpose: To determine if a given amount of time in seconds has elapsed 
	Input: A start time for a given time period to be measured 
	       The number of seconds to have elapsed 
	Output: True (1) if the number of seconds has elapsed 
		False (0) if not 
	Assumptions: The system timers is ticking at 18.2 ticks per second. 
		     To reduce complexity the ticks per second is rounded up 
		     to 19.  This results in slightly higher actual elapsed 
		     time periods but it is felt this will not pose a  
		     substantial problem as this function will be mainly 
		     used as a watchdog type timer. 
	Restrictions: None 
	Other functions called: Get_Time to get the current time. 
 
******************************************************************************/ 
 
VINT HasTimeElapsed(VULONG StartTime, VINT Seconds) 
 
{ 
	VULONG CurrentTime; 
	VULONG ElapsedTime; 
 
	CurrentTime = Get_Time(); 
 
	ElapsedTime = CurrentTime - StartTime; 
 
	if (ElapsedTime > Seconds*19) return(1); 
	else return(0); 
 
} 
 
/****************************************************************************** 
 Function: WriteLog 
	Purpose: To write a standard string out to an output file. If 
		 the log file is an actual file (not stdout) then the  
		 file is opened appended to and closed to prevent any 
		 loss of information do to some hardware failure. 
	Input: P_F - indicates a passing or failing log entry 
		   (The macros LOG_PASS and LOG_FAIL in gen_tool.h can be 
		    used for this parameter) 
	       B_D - indicates a basic or detail log entry 
		   (The macros LOG_BASIC and LOG_DETAIL in gen_tool.h can be 
		    used for this parameter) 
	       Str1 - Test name in a basic log entry & entire output string 
		      in a detail entry.  This string should not contain a 
		      newline symbol (\n) 
	       Str2 - Parameter list in a basic entry, not used in detail entry 
		      This string should not contain a newline symbol (\n) 
	       logfilename_ptr - This is a global pointer that points to 
				 the name of the log file name.  If it is null 
				 then the strings above are written to stdout 
	Output:  Given the two parameter P_F and B_D four different strings 
		 are written to either the log file or stdout or both.  The 
		 following chart spells out the variations. 
		 LOG_BASIC, LOG_PASS - "PASS Test:(Str1) Par:(Str2)\n" 
		 LOG_BASIC, LOG_FAIL - "FAIL Test:(Str1) Par:(Str2)\n" 
		 LOG_DETAIL, LOG_PASS - "(Str1)\n" 
		 LOG_DETAIL, LOG_FAIL - "(Str1)\n" 
			(Note that the final option (DETAIL, FAIL) is written 
			 to both the log file and stderr if necessary, all 
			 other options go to just the log file or stdout) 
	Assumptions: logfilename_ptr is properly assigned 
	Restrictions: Str1 and Str2 must not contain the newline symbol (\n) 
	Other functions called: fopen to open the log file (if not stdout) 
				fclose to close the log file (if not stdout) 
				fprintf to print the strings 
 
******************************************************************************/ 
 
VINT WriteLog( VINT P_F, VINT B_D, VCHAR *Str1, VCHAR *Str2) 
 
{ 
 
	FILE *logfile; 
 
	if (logfilename_ptr == NULL) 
		logfile = stdout; 
	else 
		logfile = fopen(logfilename_ptr, "at"); 
 
	/* we open and close the log file on each entry to prevent lost info */ 
	/* in the event of a hang during testing */ 
	if (logfile != NULL) 
	{ 
		/* Basic or detail */ 
		if (B_D == LOG_BASIC) 
		{ 
			/* Basic log entry */ 
			/* pass or fail */ 
			if (P_F == LOG_PASS) 
				fprintf(logfile, "PASS Test:%s Par:%s\n", Str1, Str2); 
			else 
				fprintf(logfile, "FAIL Test:%s Par:%s\n", Str1, Str2); 
		} 
		else   /* Detail log entry */ 
		{ 
			/* A detail passing log entry will go only to the log file */ 
			/* A detail failing log entry will go to stdout and the log file */ 
			/* if it isn't assigned to stdout */ 
			if (P_F == LOG_PASS) 
				fprintf(logfile, "%s", Str1); 
			else 
			{ 
				fprintf(stdout, "%s", Str1); 
				if (logfile != stdout) 
					fprintf(logfile, "%s", Str1); 
			} 
		} 
	} 
	else   /* Whoops! */ 
	{ 
		fprintf(stdout, "Error. Can't open log file!!\n"); 
		return(LOG_FAIL); 
	} 
 
	if (logfile != stdout) fclose(logfile); 
	return(LOG_PASS); 
}