/*      alpha-cpuid.cpp
//      
//      Copyright 2005-2011 Lucas Tsatiris <systester.project@gmail.com>
//      
//      This program is free software; you can redistribute it and/or modify
//      it under the terms of the GNU General Public License as published by
//      the Free Software Foundation; either version 2 of the License, or
//      (at your option) any later version.
//      
//      This program is distributed in the hope that it will be useful,
//      but WITHOUT ANY WARRANTY; without even the implied warranty of
//      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//      GNU General Public License for more details.
//      
//      You should have received a copy of the GNU General Public License
//      along with this program; if not, write to the Free Software
//      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
//      MA 02110-1301, USA.
//      
*/      

/* Determine the alpha CPU 
 * Based on http://h21007.www2.hp.com/portal/download/files/unprot/tru64/tips.pdf
 */

#if defined(__osf__)		/* OSF1/Tru64 Unix/Compaq C++ */
#include <sys/sysinfo.h>
#include <machine/hal_sysinfo.h>
#include <c_asm.h>

enum implver_enum
{
  IMPLVER_EV4,
  IMPLVER_EV5,
  IMPLVER_EV6,
  IMPLVER_EV7
};

int
CPUID (char *ChipID, char *VendorID)
{
  int my_implver;
  my_implver = asm ("implver %r0;");
  strcpy (VendorID, "DEC/Compaq/HP");
  switch (my_implver)
    {
    case IMPLVER_EV4:
      {
	strcpy (ChipID, "Alpha 21064 or variant (EV4 core)");
	break;
      }
    case IMPLVER_EV5:
      {
	strcpy (ChipID, "Alpha 21164 or variant (EV5 core)");
	break;
      }
    case IMPLVER_EV6:
      {
	strcpy (ChipID, "Alpha 21264 or variant (EV6 core)");
	break;
      }
    case IMPLVER_EV7:
      {
	strcpy (ChipID, "Alpha 21364 or variant (EV7 core)");
	break;
      }
    default:
      {
	strcpy (ChipID, "Unknown Alpha CPU implementation");
	break;
      }
    }

  return 3;			/* alpha cpuid = 3 */
}

#elif defined(__linux) && defined(__alpha)	/* alpha linux GCC */
/*
 * Use Alpha Linux code lifted from .../include/asm-alpha/system.h
 */

enum implver_enum
{
  IMPLVER_EV4,
  IMPLVER_EV5,
  IMPLVER_EV6,
  IMPLVER_EV7
};

#define implver() \
({ unsigned long __implver; \
__asm__ ("implver %0" : "=r"(__implver)); \
(enum implver_enum) __implver; })


int
CPUID (char *ChipID, char *VendorID)
{
  int my_implver;
  my_implver = implver ();
  strcpy (VendorID, "DEC/Compaq/HP");
  switch (my_implver)
    {
    case IMPLVER_EV4:
      {
	strcpy (ChipID, "Alpha 21064 or variant (EV4 core)");
	break;
      }
    case IMPLVER_EV5:
      {
	strcpy (ChipID, "Alpha 21164 or variant (EV5 core)");
	break;
      }
    case IMPLVER_EV6:
      {
	strcpy (ChipID, "Alpha 21264 or variant (EV6 core)");
	break;
      }
    case IMPLVER_EV7:
      {
	strcpy (ChipID, "Alpha 21364 or variant (EV7 core)");
	break;
      }
    }

  return 3;			/* alpha cpuid = 3 */
}
#endif /* __osf__ */
