How do you identify VAX/PMAX cpu's from software?

Frank Wortner frank at riscy.dec.com
Wed May 31 08:22:59 AEST 1989


I've cooked up a short program to identify CPUs --- just to show 1) it
can be done, and 2) it is not hard.  Compile the program thusly on
either VAX or DECstation:  cc cputype.c.

Have fun!
						Frank

---------------------------------Cut Here------------------------------

/*
 *	cputype.c:	Print the CPU type and memory size on stdout.
 */


#include <nlist.h>
#include <stdio.h>
#include <signal.h>
#include <time.h>

#include <sys/types.h>
#include <sys/file.h>
#include <sys/cpudata.h>
#include <sys/config.h>


#include <machine/param.h>

#ifdef	vax
#	include <machine/cpu.h>
#endif
#ifdef	mips
#	include <machine/hwconf.h>
#endif


/*
 *	The kernal data structures we are interested in.
 */
struct nlist	namelist[] = {
/*
 *	Names of things and other "static" data.
 */
	{ "_physmem" },		/* NM_PHYSMEM */
	{ "_cpu" },		/* NM_CPU */
	{ "_cpudata" },		/* NM_CPUDATA */
	{ "_cpu_subtype" },	/* NM_CPU_SUBTYPE */
/*
 *	This will only be used by the MIPS based systems,
 *	but it doesn't need to be #ifdef'd.
 */
	{ "_cpu_systype" },	/* NM_CPU_SYSTYPE */
/*
 *	End of list.
 */
	{ 0 }
};

#define NM_PHYSMEM 0
#define NM_CPU     1
#define NM_CPUDATA 2
#define NM_CPU_SUBTYPE 3
#define NM_CPU_SYSTYPE 4

/*
 *	These arrays will allow cpu.c to get a CPU string from
 *	a type and subtype.
 */
struct cpu_type {
	int	type;
	char	*string;
	struct cpu_type *subtype;
};

#ifdef	vax
struct cpu_type vax8200[] = {
	ST_8200, "VAX 8200/8250", NULL,
	ST_8300, "VAX 8300/8350", NULL,
	ST_8400, "VAX 8400/8450", NULL,
	{ 0, 0, 0, },
};

struct cpu_type vax8800[] = {
	ST_8500, "VAX 8500/8530", NULL,
	ST_8550, "VAX 8550", NULL,
	ST_8700, "VAX 8700", NULL,
	ST_8800, "VAX 8800", NULL,
	{ 0, 0, 0, },
};

struct cpu_type microvax2[] = {
	ST_MVAXII,  "MicroVAX/VAXstation II",   NULL,
	ST_VAXSTAR, "MicroVAX/VAXstation 2000", NULL,
	{ 0, 0, 0, },
};

struct cpu_type cpu_types[] = {
/*
 *	The VAX list.
 */
	VAX_780,  "VAX 11/780 or 11/785", NULL,
	VAX_750,  "VAX 11/750 or 11/751", NULL,
	VAX_730,  "VAX 11/730 or 11/725", NULL,
	VAX_8600, "VAX 8600/8650", NULL,
	VAX_8200, "VAX 8200/8250/8300/8350", vax8200,
	VAX_8800, "VAX 8800/8700/8550/8530/8500", vax8800,
	MVAX_I,   "MicroVAX I", NULL,
	MVAX_II,  "MicroVAX/VAXstation II", microvax2,
/*
 *	Future CPU types will need to be #ifdef'd as these
 *	are.  This lets the data be updated for newer versions
 *	but still be backward compatiable.
 */
#ifdef	C_VAX
	C_VAX,    "MicroVAX/VAXstation 3200/3500/3600", NULL,
#endif
#ifdef	VAX_6200
	VAX_6200, "VAX 6210/6220/6230/6240", NULL,
#endif
#ifdef	C_VAXSTAR
	C_VAXSTAR, "VAXstation 3100", NULL,
#endif
#ifdef	VAX_8820
	VAX_8820, "VAX 8820/8830/8840", NULL,
#endif
};
#endif

/*
 *	The MIPS list.
 */
#ifdef	mips
struct cpu_type cpu_types[] = {
	{ PMAX, "DECstation 3100", NULL, },
	{ 0, 0, 0, },
} ;
#endif

static int kmem;

/*
 *	Functions which don't return (int).
 */
char	*str_cpuid();


void	nlist(),
	fatal(),
	readk();



main()
{
  cpu_names();
  exit (0);
}

/*
 *	Print something about the CPU.
 */
static	cpu_names()
{
	int	sid, physmem ;
	long	subtype = -1 ;
	caddr_t	addr ;

	sid = getsid() ;

	/*
	 *	Get the amount of physical memory.
	 */
	if((addr = (caddr_t)namelist[NM_PHYSMEM].n_value) == 0 ) {
		warning("Can't get physical memory size.\n") ;
		return ;
	}
	else
		readk((long)addr, (char *)&physmem, sizeof(physmem)) ;

#ifdef	vax
	subtype = get_cpu_subtype(addr);
#endif
#ifdef	mips
	subtype = GETCPUTYPE(sid) ;
#endif

	printf("%s with %d bytes of memory.\n", str_cpuid(sid, subtype),
		physmem * NBPG) ;
}


/*
 *	Local version of a system call to get the contents of the SID
 *	register.  This function constructs a number which looks like
 *	the contents of a CPU SID register.
 *
 *	It is a feature of the MicroVAX architecture that this function
 *	will always return the correct SID.
 */
getsid()
{
/*
 *	Data for the two architectures.
 */
#ifdef	vax
	int	nm_cpu ;
	union	cpusid cpu ;
#endif
#ifdef	mips

	int	cpu_systype ;
#endif

	open_names();
/*
 *	The architecture dependent code.
 */
#ifdef	vax
	readk((long)namelist[NM_CPU].n_value, (char *)&nm_cpu, sizeof(nm_cpu)) ;

	cpu.cpuany.cp_type = nm_cpu ;

	return cpu.cpusid ;
#endif

#ifdef	mips
	readk((long)namelist[NM_CPU_SYSTYPE].n_value, (char *)&cpu_systype,
		sizeof(cpu_systype)) ;

	return cpu_systype ;
#endif
}


/*
 *	Set up the namelist and open the kernel so we can get
 *	to the names.
 */
open_names(op)
{
	/*
	 *	Initialize the namelist, nlist(x) doesn't return
	 *	anything to signify an error.
	 */
	(void)nlist("/vmunix", namelist) ;

	/*
	 *	Open memory.
	 */
	if((kmem = open("/dev/kmem", O_RDONLY, 0)) == -1 )
		fatal("Can't open /dev/kmem: ") ;
}

/*
 *	Try to close /dev/kmem.
 */
close_names(op)
{
	if( close(kmem) == -1 )
		fatal("Can't close /dev/kmem: ") ;
}



/*
 *	Get the CPU subtype.
 */
int get_cpu_subtype(addr)
     caddr_t addr;
{
  int subtype;
  
  if((addr = (caddr_t)namelist[NM_CPU_SUBTYPE].n_value) == 0 )
    subtype = -1 ;
  else
    readk((long)addr, (char *)&subtype, sizeof(long)) ;
  return (subtype);
}


/*
 *	Seek to "where" in the kernel and read "size" bytes
 *	into the space at "addr".
 */
void readk(where, addr, size)
long	where ;
char	*addr ;
int	size ;
{
	long	lseek() ;

	if( lseek(kmem, where, L_SET) == -1 )
		fatal("Can't lseek in /dev/kmem: ");

	if( read(kmem, addr, size) == -1 )
		fatal("Can't read from /dev/kmem: ");
}



/*
 *	Functions and data to take the CPU id and turn it into something
 *	"meaningful".
 */
char	*str_cpuid(ident, subtype)
int	ident ;
long	subtype ;
{
#ifdef	vax
	union cpusid cpu ;
#endif
	int	type ;
	struct cpu_type *sp, *tp ;

	tp = &cpu_types[0] ;

/*
 *	This is the VAX version of how to turn the system
 *	id into a system name.
 */
#ifdef	vax
	cpu.cpusid = ident ;
	type = cpu.cpuany.cp_type ;
#endif

/*
 *	On the mips we can get everything from the cpu_systype.
 */
#ifdef	mips
	type = GETSYSTYPE(ident) ;
#endif

	while( tp->string != NULL ) {
		if( tp->type == type ) {
			/*
			 *	If there isn't a subtype list return
			 *	the string for the type.
			 */
			if((sp = tp->subtype) == NULL )
				return tp->string ;

			/*
			 *	Else...  Walk the the subtype list
			 *	looking for a matching subtype.
			 */
			while( sp->string != NULL ) {
				if( sp->type == subtype )
					return sp->string ;

				sp++ ;
			}

			/*
			 *	If there isn't a subtype match return
			 *	the type string.
			 */
			return tp->string ;
		}

		tp++ ;
	}

	return "Unknown CPU type" ;
}



void fatal(str)
     char *str;
{
  perror(str);
  exit(1);
}

warning(str)
{
  fprintf(stderr, "%s\n", str);
}



More information about the Comp.unix.ultrix mailing list