From:	CRDGW2::CRDGW2::MRGATE::"SMTP::CRVAX.SRI.COM::RELAY-INFO-VAX"  6-DEC-1989 09:36
To:	MRGATE::"ARISIA::EVERHART"
Subj:	Ether_Hard_Address.Mar - Changes DEC Ethernet board physical address

Received: From SLCS.SLB.COM by CRVAX.SRI.COM with TCP; Wed,  6 DEC 89 05:18:12 PDT
Received: from ascsu1.SLCS.SLB.COM ([129.87.7.36]) by SLCS.SLB.COM (4.0/SLCS Mailhost 2.4)
	id AA03024; Wed, 6 Dec 89 07:19:05 CST
Received: from sdr.psi by ascsu1.SLCS.SLB.COM (3.2/SLCS Relay 1.1)
	id AA25221; Wed, 6 Dec 89 07:19:00 CST
Date: Wed, 6 Dec 89 07:19:00 CST
Message-Id: <8912061319.AA25221@ascsu1.SLCS.SLB.COM>
From: barbe@sdr.SLB.COM (Claude Barbe - SDR - 1 203 431 5524)
To: info-vax@sri.com
X-Vms-To: PSI%ASCSU1::SRI.COM::INFO-VAX
Subject: Ether_Hard_Address.Mar - Changes DEC Ethernet board physical address

	.title	ether_hard_address
	.ident	/1.0/

; This program gets the hardware address for Ethernet interface named ETA0
; and tries to set the physical address to be same.  This allows machines with
; two or more Ethernet connections to use Ethernet addresses that are different
; on each interface (instead of the default Decnet address).  This allows
; a VAX to speak DEC (Net, Lat, LAVC) on one segment (this interface needs to
; keep the default physical address based on the node number), and non-DEC
; (IP, Apple) on another segment (this is the one that needs to be modified)
; with the two segments bridged with a LANbridge-100.
;
; $ MACRO ETHER_HARD_ADDRESS.MAR
; $ LINK  ETHER_HARD_ADDRESS
; $ DEFINE/USER ETA0 _ETB0: ! Or XEB0: or any name of a secondary Ethernet
; $ RUN   ETHER_HARD_ADDRESS
; Physical Address = AA-00-04-00-2F-1A - Hardware Address = 08-00-2B-02-FE-71
; will print on SYS$OUTPUT
;
; The code is straightforward and based on what is said on the subject of
; physical address in the I/O User's guide.
;
; The program sends one frame (to ourselves) and if we are the first 
; application to do IO on that interface, the hardware address will become
; the physical address.  It is harmless on an Ethernet interface after
; Decnet has started, it simply tells you both addresses
;
; Part of this code has probably been borrowed from macro files posted
; on info-vax.  DEC said there were not other ways to have a VAX with
; more than one DEC Ethernet interface on several segments LAN-bridged
; together.
;
; In a mixed or lavc cluster, the first interface happens to be seized by
; CLUSTER_SERVER or VMS itself before STARTUP.COM is called, so the first
; interface seems to be always running with the Decnet node number physical
; address.  Other interfaces can be configured with this program (ie in
; SYLOGICALS.COM) before foreign software packages are started.  Before
; posting it, this has been successfully used for several weeks.
;
; Claude Barbe - Schlumberger-Doll Research - Ridgefield, CT
; August 1989 - VMS 5.1 and 5.2
;
	.library	"SYS$LIBRARY:LIB.MLB"

	$IODEF
	$NMADEF			; network management (Ethernet)

;===========================
; Initial setmode buffer

set1buf:
	.word	NMA$C_PCLI_FMT		; packet format
		.long	NMA$C_LINFM_ETH
	.word	NMA$C_PCLI_PTY		; Our protocol type
		.long	^X4455		; arbitrary unused protocol
	.word	NMA$C_PCLI_PAD		; Padding OFF
		.long	NMA$C_STATE_OFF
set1len=.-set1buf
set1dsc:
	.long		set1len
	.address	set1buf

;===========================
; Sensemode parameter buffer

sensebuf:
	.blkb	150
senselen=.-sensebuf
sensedsc:
	.long		senselen
	.address	sensebuf

;======================
; other local variables

devdsc:	.ascid	'ETA0'

chan:	.blkw	1		; channel number

iosb:	.blkw	4		; i/o status block

pa:	.blkb	6		; physical address (from sensemode) kept here
padsc:
	.long		0
	.address	pa

ha:	.blkb	6		; hardware address (from sensemode) kept here
hadsc:
	.long		0
	.address	ha

xmtbuf:	.blkb	64		; to be xmitted to ourselves (but not read)
xmtlen=.-xmtbuf
;=======================
; fao data

faostr:
        .ascid  "Physical Address = !XB-!XB-!XB-!XB-!XB-!XB - Hardware Address = !XB-!XB-!XB-!XB-!XB-!XB"
 
faodsc:
        .long           ^d132
        .address        faobuf
 
faobuf:
        .blkb           ^d132
 
;=========================
;	Code

	.entry	start,^M<>

; Assign a channel

	$ASSIGN_S	-
			 DEVNAM=devdsc -
			,CHAN=chan
	blbs	r0,assign_ok
	ret				; assign error

assign_ok:

	$QIOW_S		-
			FUNC=#<IO$_SETMODE!IO$M_CTRL!IO$M_STARTUP>,-
			CHAN=chan,-
			IOSB=iosb,-
			P2=#set1dsc
	blbs	r0,set1_ok1
	ret				; setmode error
set1_ok1:
	movzwl	iosb,r0
	blbs	r0,set1_ok2
	ret

set1_ok2:
	$QIOW_S		-
			FUNC=#<IO$_SENSEMODE!IO$M_CTRL>,-
			CHAN=chan,-
			IOSB=iosb,-
			P2=#sensedsc
	blbs	r0,sense_ok1
	ret				; sensemode error
sense_ok1:
	movzwl	iosb,r0
	blbs	r0,sense_ok2
	ret

sense_ok2:

; check the contents of sensebuf, look for _PHA and _HWA parameters
; display those when found

	clrl	padsc+0			; no physical address seen so far
	clrl	hadsc+0			; no hardware address seen so far

	movab	sensebuf, r3
	movzwl	iosb+2,r1		; returned length

10$:	tstl	r1			; are we at end of string?
	bleq	200$			; yes

	bbs	#^x0C,(r3),20$		; this is a string param

	addl	#6,r3			; this is a long word
	subl	#6,r1
	brb	10$			; skip type word and value longword

20$:	bicw	#^x0F000,(r3)		; clear the flag bits in type field
	cmpw	#NMA$C_PCLI_PHA,(r3)	; is it Physical Address ?
	beql	110$			; yes - keep it

	cmpw	#NMA$C_PCLI_HWA,(r3)	; is it Hardware Address ?
	beql	120$			; yes - keep it

; skip over the string parameter

30$:	addl	#2,r3
	subl	#2,r1
	movzwl	(r3)+,r2		; string length
	addl	r2,r3			; advance pointer
	subl	r2,r1			; reduce counter
	brb	10$

; keep Physical Address

110$:
	movl	4(r3),pa+0		; 4 bytes of physical address
	movw	8(r3),pa+4		; 2 bytes of physical address
	movzbl	#6,padsc+0		; flag = physical address seen
	brb	30$			; continue scanning

; keep Hardware Address

120$:
	movl	4(r3),ha+0		; 4 bytes of hardware address
	movw	8(r3),ha+4		; 2 bytes of hardware address
	movzbl	#6,hadsc+0		; flag = hardware address seen
	brb	30$			; continue scanning

200$:

; display the physical and hardware addresses

	movw	#^d132,faodsc			; set length of dest string
        $FAO_S  CTRSTR=faostr, -		; format
		OUTBUF=faodsc, -		; dest buffer
		OUTLEN=faodsc, -		; length buffer
		P1=pa+0, -			; longword to convert
		P2=pa+1, -			; longword to convert
		P3=pa+2, -			; longword to convert
		P4=pa+3, -			; longword to convert
		P5=pa+4, -			; longword to convert
		P6=pa+5, -			; longword to convert
		P7=ha+0, -			; longword to convert
		P8=ha+1, -			; longword to convert
		P9=ha+2, -			; longword to convert
		P10=ha+3, -			; longword to convert
		P11=ha+4, -			; longword to convert
		P12=ha+5			; longword to convert
;	blbs	r0,fao_ok
;fao_ok:
	pushab	faodsc
	calls	#1,G^LIB$PUT_OUTPUT

; now transmit the test message

	$QIOW_S		-
			FUNC=#<IO$_WRITEVBLK>,-
			CHAN=chan,-
			IOSB=iosb,-
			P1=XMTBUF,-
			P2=#XMTLEN,-
			P5=#ha
	blbs	r0,out_ok1
	ret				; output error
out_ok1:
	movzwl	iosb,r0
	blbs	r0,out_ok2
	ret

out_ok2:
	ret

	.end	start			; main program

