//////////////////////////////////////////////////
//Title    : linux_sys.c
//Auhtor   : Liu Wei
//Desc     : Linux system infomation 
//Created  : 2007-06-02
//Revision :
//
//Revision :
//
//////////////////////////////////////////////////

#include "./include/pub_sys.h"

/*@ignore@*/
///////////////////////////////////////////////////////////////////////////
// InitParalPort:Init parallel port data	.                                                                
///////////////////////////////////////////////////////////////////////////
extern void InitParalPort(void)
{
	ioperm(0x37a,3,1);
	ioperm(0x378,3,1);
	ioperm(0x379,3,1);
	outb(0,0x37a);
	outb(0,0x378);
}


///////////////////////////////////////////////////////////////////////////
// Name      : WriteParalPort
// Function  : Write parallel port data	
// Node      : Parallel port address: 
//           : flag=0,address=0x37a B1;flag=1,address=0x37a B2        
//           : flag=2--9,address=0x378 B0--B7                                                 
///////////////////////////////////////////////////////////////////////////

extern void WriteParalPort(u8 uFlag,u8 uData)
{	
	u8		ii,jj;

	if (uFlag > 9)
		return;
	if (uData != 0 && uData != 1)
		return;
    if (uFlag == 0 || uFlag == 1) // read or write 0x37a
    {
        ii = inb(0x37a);
        jj = 1 << (uFlag + 1);
        ii = ii & (~jj);
        if (uFlag == 0)
            jj = (~uData & 0x01) << (uFlag + 1);
        else
            jj = uData << (uFlag + 1);
        ii = ii | jj;
        outb(ii,0x37a);
    }
	else
	{
		ii = inb(0x378);
		jj = 1 << (uFlag - 2);
		ii = ii & (~jj);
		jj = uData << (uFlag - 2);
		ii = ii | jj;
		outb(ii,0x378);
	}
}

///////////////////////////////////////////////////////////////////////////
// GetMemoryStr: Get memery string                                                                
//////////////////////////////////////////////////////////////////////////
extern char *GetMemoryStr(u32 Amount)
{
    static char			Buff[64];

    if (Amount > 0) {
	(void) snprintf(Buff, sizeof(Buff), "%d", Amount/MBYTES);
	return(Buff);
    }

    return((char *) NULL);
}

///////////////////////////////////////////////////////////////////////////
// GetBootTimeProc: Get System Model using the /proc/cpuinfo file.                                                                
///////////////////////////////////////////////////////////////////////////

#define PROC_FILE_UPTIME "/proc/uptime"

extern char *GetBootTimeProc (  )
{
    FILE   *pFile;
    static char sBuff[64];
    char   *pCh;
    char   *DateStr;
    time_t  tmUptime;
    time_t  tmBootTime;

    pFile = fopen ( PROC_FILE_UPTIME, "r" );
    if ( !pFile )
    {
        FLogMsg ( PIF_GERR, "%s: open readonly failed: %s", PROC_FILE_UPTIME,
                  SYSERR );
        return ( ( char * ) NULL );
    }

    if ( !fgets ( sBuff, sizeof ( sBuff ), pFile ) )
    {
        FLogMsg ( PIF_GERR, "%s: Read uptime failed: %s", PROC_FILE_UPTIME,
                  SYSERR );
        ( void ) fclose ( pFile );
        return ( ( char * ) NULL );
    }

    if ( pCh = strchr ( sBuff, ' ' ) )
    {
        *pCh = CNULL;
    }

    tmUptime = ( time_t ) strtol ( sBuff, NULL, 0 );
    if ( tmUptime <= 0 )
    {
        FLogMsg ( PIF_GERR, "Convert `%s' to long failed", sBuff );
        ( void ) fclose ( pFile );
        return ( ( char * ) NULL );
    }

    tmBootTime = time ( NULL );
    tmBootTime -= tmUptime;

    DateStr = TimeToStr ( tmBootTime, NULL );

    ( void ) fclose ( pFile );

    return ( DateStr );
}

///////////////////////////////////////////////////////////////////////////
// Get System Model using the /proc/cpuinfo file.                                                                
///////////////////////////////////////////////////////////////////////////

#define PROC_FILE_CPUINFO	"/proc/cpuinfo"
/*
extern char *GetModelProc (  )
{
    FILE   *pFile;
    static char sBuff[256];
    char   *Cpu = NULL;
    char   *Vendor = NULL;
    char   *Model = NULL;
    char    Speed[64];
    float   sp = 0;
    char  **Argv;
    int     Argc;
    int     Cleanup;

    if ( sBuff[0] )
    {
        return ( sBuff );
    }

    pFile = fopen ( PROC_FILE_CPUINFO, "r" );
    if ( !pFile )
    {
        FLogMsg ( PIF_GERR, "%s: open readonly failed: %s", PROC_FILE_CPUINFO,
                  SYSERR );
        return ( ( char * ) NULL );
    }

    Speed[0] = CNULL;
    while ( fgets ( sBuff, sizeof ( sBuff ), pFile ) )
    {
        Cleanup = TRUE;
        Argc = StrToArgv ( sBuff, ":", &Argv, NULL, 0 );
        if ( Argc < 2 )
        {
            continue;
        }
        if ( EQ ( Argv[0], "cpu" ) )
        {
            Cpu = Argv[1];
        }
        else if ( EQ ( Argv[0], "vendor_id" ) )
        {
            Vendor = Argv[1];
        }
        else if ( EQ ( Argv[0], "model name" ) )
        {
            Model = Argv[1];
        }
        else if ( EQ ( Argv[0], "cpu MHz" ) )
        {

            // This value is not always perfectly accurate as Linux estimates
            // the actual Mhz by doing a loop test at boot.

            if ( sscanf ( Argv[1], "%f", &sp ) )
            {
                ( void ) sprintf ( Speed, "%.0f Mhz", rint ( ( double ) sp ) );
            }
        }
        else
        {
            DestroyArgv ( &Argv, Argc );
            Cleanup = FALSE;
        }

        if ( Cleanup )
        {
            ( void ) free ( Argv[0] );
        }
    }

    sBuff[0] = CNULL;
    if ( Vendor )
    {
        ( void ) strcpy ( sBuff, Vendor );
        ( void ) free ( Vendor );
    }
    if ( Speed[0] )
    {
        if ( sBuff[0] )
        {
            ( void ) strcat ( sBuff, " " );
        }
        ( void ) strcat ( sBuff, Speed );
    }
    if ( Model )
    {
        if ( sBuff[0] )
        {
            strcat ( sBuff, " " );
        }
        strcat ( sBuff, Model );
        ( void ) free ( Model );
    }
    if ( Cpu )
    {
        if ( sBuff[0] )
        {
            strcat ( sBuff, " " );
        }
        strcat ( sBuff, Cpu );
        ( void ) free ( Cpu );
    }

    ( void ) fclose ( pFile );

    return ( sBuff );
}
*/
///////////////////////////////////////////////////////////////////////////
// GetMBytesStr: Get the string of Mbytes                                                                 
///////////////////////////////////////////////////////////////////////////

extern char *GetMBytesStr ( u32 wAmount )
{
    static char sBuff[64];

    if ( !wAmount )
    {
        return ( ( char * ) NULL );
    }

    if ( wAmount > KBYTES )
    {
        ( void ) snprintf ( sBuff, sizeof ( sBuff ), "%.1f GB",
                            ( float ) MbytesToGbytes ( wAmount ) );
    }
    else
    {
        ( void ) snprintf ( sBuff, sizeof ( sBuff ), "%.0f MB",
                            ( float ) wAmount );
    }
}

///////////////////////////////////////////////////////////////////////////
// GetMemoryKcore: Get System Memory using size of /proc/kcore                                                                
///////////////////////////////////////////////////////////////////////////

#define PROC_FILE_KCORE	"/proc/kcore"

extern char *GetMemoryKcore (  )
{
    static char *pMemStr = NULL;
    u32     wMemBytes = 0;
    u32     wAmount = 0;
    struct stat tStatBuf;

    if ( pMemStr )
    {
        return ( pMemStr );
    }

    if ( stat ( PROC_FILE_KCORE, &tStatBuf ) != 0 )
    {
        FLogMsg ( PIF_GERR, "%s: stat failed: %s", PROC_FILE_KCORE, SYSERR );
        return ( ( char * ) NULL );
    }

    wMemBytes = ( u32 ) ( tStatBuf.st_size - 4096 );
    wAmount = DivRndUp( wMemBytes, ( u32 ) MBYTES );
    pMemStr = GetMBytesStr ( wAmount );

    return ( pMemStr );
}

///////////////////////////////////////////////////////////////////////////
// GetMemorySysinfo: Get System Memory using sysinfo() system call                                                               
///////////////////////////////////////////////////////////////////////////

extern char *GetMemorySysinfo (  )
{
    struct sysinfo tSysInfo;
    static char *pMemStr = NULL;
    u32     wMemBytes = 0;
    u32     wAmount = 0;

    if ( pMemStr )
    {
        return ( pMemStr );
    }

    if ( sysinfo ( &tSysInfo ) != 0 )
    {
        FLogMsg ( PIF_GERR, "sysinfo() system call failed: %s", SYSERR );
        return ( ( char * ) NULL );
    }

    // sysinfo.totalram represents total USABLE physical memory.  Memory
    // reserved by the kernel is not included.  So this is as close as we
    // can get for now.  

    wMemBytes = ( u32 ) tSysInfo.totalram;
    wAmount = DivRndUp( wMemBytes, ( u32 ) MBYTES );
    pMemStr = GetMemoryStr ( wAmount );

    return ( pMemStr );
}

///////////////////////////////////////////////////////////////////////////
// GetVirtMemLinux:Get Virtual Memory using sysinfo() system call                                                               
///////////////////////////////////////////////////////////////////////////

extern char *GetVirtMemLinux (  )
{
    struct sysinfo tSysInfo;
    static char *pMemStr = NULL;
    u32     wMemBytes = 0;
    u32     wAmount = 0;

    if ( pMemStr )
    {
        return ( pMemStr );
    }

    if ( sysinfo ( &tSysInfo ) != 0 )
    {
        FLogMsg ( PIF_GERR, "sysinfo() system call failed: %s", SYSERR );
        return ( ( char * ) NULL );
    }

    wMemBytes = ( u32 ) ( tSysInfo.totalram + tSysInfo.totalswap );
    wAmount = DivRndUp( wMemBytes, ( u32 ) MBYTES );
    pMemStr = GetMemoryStr ( wAmount );

    return ( pMemStr );
}

///////////////////////////////////////////////////////////////////////////
// GetCpuTypeProc:Get CPU Type from /proc/cpuinfo                                                               
///////////////////////////////////////////////////////////////////////////

#define PROC_FILE_CPUINFO	"/proc/cpuinfo"
/*
extern char *GetCpuTypeProc (  )
{
    FILE   *pFile;
    static char sBuff[256];
    static char *Cpu = NULL;
    char  **Argv;
    char   *pCh;
    int     Argc;

    if ( Cpu )
    {
        return ( Cpu );
    }

    pFile = fopen ( PROC_FILE_CPUINFO, "r" );
    if ( !pFile )
    {
        FLogMsg ( PIF_GERR, "%s: open readonly failed: %s", PROC_FILE_CPUINFO,
                  SYSERR );
        return ( ( char * ) NULL );
    }

    while ( fgets ( sBuff, sizeof ( sBuff ), pFile ) )
    {
        Argc = StrToArgv ( sBuff, ":", &Argv, NULL, 0 );
        if ( Argc < 2 )
        {
            continue;
        }
        if ( EQ ( Argv[0], "cpu" ) )
        {
            // Linux 2.0 
            Cpu = Argv[1];
            break;
        }
        else if ( EQ ( Argv[0], "model name" ) )
        {
            // Linux 2.2 
            Cpu = Argv[1];
            if ( pCh = strchr ( Cpu, ' ' ) )
            {
                *pCh = CNULL;
            }
            break;
        }
    }

    ( void ) fclose ( pFile );

    return ( Cpu );

}
*/

///////////////////////////////////////////////////////////////////////////
// GetKernVerProc: Get Kernel Version string using /proc/version                                                               
///////////////////////////////////////////////////////////////////////////

#define PROC_FILE_VERSION	"/proc/version"

extern char *GetKernVerProc (  )
{
    FILE   *pFile;
    static char sBuff[512];

    if ( sBuff[0] )
    {
        return ( sBuff );
    }

    pFile = fopen ( PROC_FILE_VERSION, "r" );
    if ( !pFile )
    {
        FLogMsg ( PIF_GERR, "%s: open readonly failed: %s", PROC_FILE_VERSION,
                  SYSERR );
        return ( ( char * ) NULL );
    }

    if ( !fgets ( sBuff, sizeof ( sBuff ), pFile ) )
    {
        FLogMsg ( PIF_GERR, "%s: read failed: %s", PROC_FILE_VERSION, SYSERR );
        return ( ( char * ) NULL );
    }

    ( void ) fclose ( pFile );

    return ( sBuff );

}

///////////////////////////////////////////////////////////////////////////
// GetKernVerLinux: Get Kernel Version string using uname()                                                              
///////////////////////////////////////////////////////////////////////////

extern char *GetKernVerLinux (  )
{
    static struct utsname tName;
    static char *pVerStr = NULL;

    if ( uname ( &tName ) != 0 )
    {
        FLogMsg ( PIF_GERR, "uname() system call failed: %s", SYSERR );
        return ( ( char * ) NULL );
    }

    pVerStr = tName.version;

    return ( pVerStr );
}

///////////////////////////////////////////////////////////////////////////
// GetOSDistLinux: Get linux distribution (vendor)                                                       
///////////////////////////////////////////////////////////////////////////
/*
extern char *GetOSDistLinux (  )
{
    static char sBuff[256];
    register char *pCh;
    register char *End;
    char    IssueFile[] = "/etc/issue";
    char    Welcome[] = "Welcome to ";
    FILE   *pFile;
    int     Found = FALSE;

    if ( !( pFile = fopen ( IssueFile, "r" ) ) )
    {
        FLogMsg ( PIF_GERR, "%s: Cannot open to get OS Dist: %s", IssueFile,
                  SYSERR );
        return ( ( char * ) NULL );
    }

    while ( fgets ( sBuff, sizeof ( sBuff ), pFile ) )
    {
        // Some distributions have VGA control chars in them 
        if ( !isalpha ( sBuff[0] ) )
        {
            continue;
        }
        for ( pCh = sBuff; pCh && *pCh && *pCh != '\n' && !isalpha ( *pCh );
              ++pCh )
            ;
        if ( *pCh == '\n' || !strlen ( pCh ) )
        {
            continue;
        }
        // Found first nonblank line 
        Found = TRUE;
        break;
    }

    ( void ) fclose ( pFile );

    if ( !Found )
    {
        return ( ( char * ) NULL );
    }

    if ( EQN ( pCh, Welcome, sizeof ( Welcome ) - 1 ) )
    {
        pCh += sizeof ( Welcome ) - 1;
    }
    else if ( EQN ( pCh, "Linux ", 6 ) )
    {
        pCh += 6;
    }

    if ( End = strchr ( pCh, '-' ) )
    {
        --End;
        while ( *End && isspace ( *End ) )
        {
            --End;
        }
        *++End = CNULL;
    }

    return ( pCh );
}

/*@end@*/
