[comp.os.vms] determining the CPU type of a VAX from a non-privileged program

gkn@SDS.SDSC.EDU (06/26/87)

	From:	 Gail Rubin Walker <gwalker@SPCA.BBN.COM>
	Subject: got an 8XXX vax? Answer this simple question.
	Date:	 Fri, 26 Jun 87 11:01:10 EDT
 
	I'm trying to complete my list of which CPU types return which numbers
	in $GETSYI for the CPU field. So far I know that
	1 = 780, 782, 785
	2 = 750
	3 = 730
	4 = 8600, 8650
	7 = MicroVax I
	8 = MicroVax II
 
Determining the exact CPU type of a VAX from a non-privileged program is
doable, and not too hard, even.  It's easier if you can use the MTPR/MFPR
to bang on the console CSRs, but that requires running in kernel mode and
probably would interfere with VMS's banging on them.

At any rate, here's the general algorithm:

Grab the type field from the SID;  it's in bits 24-31.  You can use $GETSYI
to get it, or you can just grab it from EXE$GB_CPUDATA+3 (which is readable
by user-mode programs).

Use that as an index into a table which contains entries laid out like:

	0	- unknown CPU type; probably a 780 with an uninitialized SID
	1	- 780/782/785 (more on telling these apart below)
	2	- 750
	3	- 730/725
	4	- 8600/8650 (more on telling these apart below)
	5	- 8200/8300 (and probably 8250/8350;  my 8200 isn't an 8250 yet)
	6	- 8800/8700/8550/8500 (and probably 8530, but I don't know yet)
	7	- uVAX-I
	8	- uVAX-II class (more on telling these apart below)

To tell a 782 from a 780 and an 8200 from an 8300:  check the contents of
EXE$GL_MP.  If it's zero, then you're on a single processor (this test
isn't 100% certain - it could be that you're on a dual processor and the
multiprocessor code isn't loaded).

To tell a 785 from a 780 and an 8650 from an 8600:  check bit 23 in the
SID (which is at EXE$GB_CPUDATA, by the way).  If bit 23 is lit, then you
have the faster widget.

Telling the Nautilus CPUs apart is much harder.  This is where it would
be useful to go beat on the console CSRs and ask the PDP-11 front end
what kind of CPU is out there (it knows).  Fortuitously, the folks who
wrote VMB did this for you, and stashed the results in EXE$GB_CPUDATA+11.

Grab the byte from EXE$GB_CPUDATA+11 and use it as an index into a table
thusly:

	0	- 8800
	1	- 8700
	2	- ?
	3	- ?
	4	- ?
	5	- ?
	6	- 8550
	7	- 8500

I suspect that the 8530 will show up where one of the above question marks
is.

To tell the various uVAX-II CPUs apart, check the contents of the byte at
EXE$GB_CPUDATA+11 again:  if it's equal to PR$_XSID_UV_640 it's then it's
a VAXstar-2000.  I'm not too sure how to tell the various VAXstations apart,
but I suspect there's a way to do that as well.

EXE$GB_CPUDATA is at 80003F90 and EXE$GL_MP is at 80002C58 in VMS V4.x, in
pages which are protected URKW.  Listings of VMB can be found on fiche panel
542 (VMS V4.5) if you're really curious.

Also, here are some code FRAGMENTS which I use to sniff out the CPU type
with:


--------------------------------------------------------------------------------

; CPU type  vector tables.  The  entrys in the first table are indexed by the
; type bits in  the SID, which is found in EXE$GB_CPUDATA.  Each entry in the
; table is either the address of a text string to use for the type (positive)
; or the address of a routine to call to further determine the CPU type.

CPU_VECTOR:	.Ascip	<???>		;0:  Unknown
		.Long	<1@31>!CPU_780	;1:  780/782/785
		.Ascip	<VAX 11/750>	;2:  750
		.Ascip	<VAX 11/730>	;3:  11/730/725
		.Long	<1@31>!CPU_8600	;4:  8600/8650
		.Long	<1@31>!CPU_8SSS	;5:  8200/8300 (scorpio)
		.Long	<1@31>!CPU_8NNN	;6:  8800/8700/8550/8500 (nautilus)
		.Ascip	<uVAX-I>	;7:  uVAX-I
		.Long	<1@31>!CPU_UVII	;8:  uVAX-II/VAXStar

CPU_8NNN_VEC:	.Ascip	<VAX 8800>	;0:  8800
		.Ascip	<VAX 8700>	;1:  8700
		.Ascip	<VAX 8nnn 2>	;2:  unknown
		.Ascip	<VAX 8nnn 3>	;3:  unknown
		.Ascip	<VAX 8nnn 4>	;4:  unknown
		.Ascip	<VAX 8nnn 5>	;5:  unknown
		.Ascip	<VAX 8550>	;6:  8550
		.Ascip	<VAX 8500>	;7:  8500


;+
;
; ----- SYSTEM_INFO:  Retrieve and display system info
;
;
; This routine will retrieve the system uptime, processor type VMS version
; number and memory statistics and display them.
;
; Inputs:
;
;	None.
;
; Outputs:
;
;	System information displayed.
;
;-

SYSTEM_INFO:				;Ref. label

	$GETSYI_S ITMLST=GET_SYI	;Get system information

; Figure out what kind of CPU we're on.

	MOVZBL	G^EXE$GB_CPUDATA+3,R0	;Get the type field from the SID
	MOVL	CPU_VECTOR[R0],R0	;Get the table index
	BGTR	10$			;If GTR we know what kind of CPU it is
	BICL	#^x80000000,R0		;Clear out the sign bit
	JSB	(R0)			;Call the proper routine

10$:	MOVL	R0,CPU			;Stash the CPU type
	EMUL	#-10*1000*1000,-	;Convert
		G^EXE$GL_ABSTIM,-	; system uptime
		#0,-			;  in seconds to
		UPTIME			;   system delta time format
	MOVAB	VERSION_BUF,R2		;Point to the version number
	LOCC	#^A/ /,#8,(R2)		;Strip trailing
	SUBL3	R2,R1,VMS_VERSION	; spaces
	DISPLAY	FAO_LINE4,LINE4		;Display it
	RSB				;Done


;+
;
; ----- CPU_780:   Sort out 780/782/785
; ----- CPU_8600:  Sort out 8600/8650
; ----- CPU_8SSS:  Sort out 8200/8300
; ----- CPU_8NNN:  Sort out 8800/8700/8550/8500
; ----- CPU_UVII:  Sort out uVAX-II/VAXstart
;
;
; These routines are used to sort out between CPU types beyond the graunularity
; offered in the type field of the SID.
;
; Inputs:
;
;	EXE$GB_CPUDATA	- CPU specific data
;
; Outputs:
;
;	R0	- A pointer to the CPU type string
;
;-

CPU_780:				;Sort out 780/782/785

	MOVAB	VAX_11782,R0		 ;Presume an 11/782
	TSTL	G^EXE$GL_MP		 ;Multiprocessor code loaded?
	BNEQ	10$			 ;If NEQ yes
	MOVAB	VAX_11780,R0		 ;Presume an 11/780
	BBC	#23,G^EXE$GB_CPUDATA,10$ ;Branch if it is
	MOVAB	VAX_11785,R0		 ;Else it's an 11/785

10$:	RSB				;Done

CPU_8600:				;Sort out 8600/8650

	MOVAB	VAX_8600,R0		 ;Presume it's an 8600
	BBC	#23,G^EXE$GB_CPUDATA,10$ ;Branch if we're right
	MOVAB	VAX_8650,R0		 ;Else it's an 8650

10$:	RSB				 ;Done

CPU_8SSS:				;Sort out an 8200/8300

	MOVAB	VAX_8200,R0		;Presume it's an 8200
	TSTL	G^EXE$GL_MP		;Multiprocessor code loaded?
	BEQL	10$			;If EQL no
	MOVAB	VAX_8300,R0		;Else it's an 8300

10$:	RSB				;Done

CPU_8NNN:				;Sort out an 8800/8700/8550/8500

	MOVAB	VAX_8NNN,R0		;Presume it's an unknown nautilus CPU
	CVTBL	G^EXE$GB_CPUDATA+11,R1	;Grab the XSID
	BLSS	10$			;If LSS, we don't know
	MOVL	CPU_8NNN_VEC[R1],R0	;Else retrieve a pointer to the name

10$:	RSB				;Done

CPU_UVII:				;Here to sort out a uVAX-II from a VAXstar

	MOVAB	UVAX_II,R0			     ;Presume it's a uVAX-II
	CMPB	#PR$_XSID_UV_640,G^EXE$GB_CPUDATA+11 ;Is it?
	BNEQ	10$				     ;If NEQ yes
	MOVAB	VAXSTAR,R0			     ;Else it's a VAXstar

10$:	RSB				;Done


And, in case you're curious, here's .ASCIP (which generates a pointer to
a descriptor):

.Macro	.Ascip	STRING,?A		;Point to a string descriptor in another PSECT
	.Enable	LSB			;Turn on the local symbol block
	.Save				;Save the current PSECT
	.Psect	STRINGS	NOEXE,RD,NOWRT,PIC,SHR,PAGE
A:	.Ascid	\'STRING\		;String
	.Restore			;Restore the current PSECT
	.Address A			;Store pointer to the string
	.Disable LSB			;Turn off the local symbol block
.Endm	.Ascip				;	...


Hope this (long-winded answer) helps.

gkn
--------------------------------------
Arpa:	GKN@SDSC.ARPA
Bitnet:	GKN@SDSC
Span:	SDSC::GKN (27.1)
USPS:	Gerard K. Newman
	San Diego Supercomputer Center
	P.O. Box 85608
	San Diego, CA 92138
AT&T:	619.534.5076

tedcrane@batcomputer.tn.cornell.edu (Ted Crane) (06/30/87)

Have you considered looking in the SYS$LIBRARY files which document all
the system constants?  These include the various versions of LIB.* and 
STARLET.*.

In there you will find the constants defined for many CPU types and device
types.  As such files go, they are reasonably well documented.

MIGLESIAS@UCIVMSA.BITNET (06/30/87)

There's a real easy way of getting the CPU type from VMS and it requires
very little work - get the SYI$_NODE_HWTYPE item with $GETSYI.  This returns
the cpu type as 4 characters.  Here's what I have obtained with the
short FORTRAN program at the end of this message:

   On a...           Returns
  ----------------  ------------
   Vax 11/785         V785
   Vax 11/780         V780
   Vax 11/750         V750
   Vax 8200           8200
   Vaxstation 2000    2000

(One could also use

   $ WRITE SYS$OUTPUT F$GETSYI("NODE_HWTYPE")

but that's too easy!  Besides the person who asked wanted to do it from
a program)

You can guess that it would return '8800' on an 8800, '8700' on an 8700,
etc.  Another benifit of using this is that you can ask what the
cpu type is for any node in a cluster.  I believe that the SHOW CLUSTER
utility uses this for the HW_TYPE field.

Since I don't have a wide array of systems to test this on, I could
be wrong....


Mike Iglesias
University of California, Irvine
miglesias@ucivmsa.bitnet

------------------- Cut here for CPUTYPE.FOR -----------------------------
C
C  CPUTYPE - Print CPU type from the SYI$_NODE_HWTYPE item of SYS$GETSYI
C
C
        STRUCTURE /ITMLST/
          UNION
            MAP
              INTEGER*2 BUFLEN
              INTEGER*2 CODE
              INTEGER*4 BUFADR
              INTEGER*4 RETLNADR
            END MAP
            MAP
              INTEGER*4 END_LIST
            END MAP
          END UNION
        END STRUCTURE
C
        RECORD /ITMLST/ SYITEMS(2)
C
        CHARACTER CPUTYPE*4
        INTEGER*4 CPUTYLEN, SYS$GETSYIW, STATUS
C
        INCLUDE '($SYIDEF)'
        INCLUDE '($SSDEF)'
C
        SYITEMS(1).BUFLEN=4
        SYITEMS(1).CODE=SYI$_NODE_HWTYPE
        SYITEMS(1).BUFADR=%LOC(CPUTYPE)
        SYITEMS(1).RETLNADR=%LOC(CPUTYLEN)
        SYITEMS(2).END_LIST=0
        STATUS=SYS$GETSYIW(,,,SYITEMS,,,)
        PRINT *,CPUTYPE
        STOP
        END