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