From:	CSBVAX::MRGATE!@KL.SRI.Com:gkn@Sdsc-Sds.Arpa@SMTP 10-JUL-1987 01:49
To:	EVERHART
Subj:	RE:  Help with a Kernal mode macro program

Received: from Sdsc-Sds.Arpa ([192.12.207.28].#Internet) by KL.SRI.COM with TCP; Thu 9 Jul 87 09:57:36-PDT
Date:    Thu, 9 Jul 87 15:12:01 GMT
From:     gkn@Sdsc-Sds.Arpa
Message-Id: <870709151202.00d@M5.Sdsc.Edu>
Subject: RE:  Help with a Kernal mode macro program
To:       info-vax@kl.sri.com
X-ST-Vmsmail-To: ST%"DStevens@SITVXB.BITNET",ST%"Info-VAX@KL.SRI.COM"

	From:	 dstevens (David L Stevens) @ sitvxb
	Subject: Help with a Kernal mode macro program
	Date:	 Wed, 8 Jul 87 12:29:44 EDT
 
        I am trying to modify FINGER to go out and get the Server and Port
	name from the UCB blocks for the LAT device, we are using LAT-Plus.
	I have below the code that I use, the problem I am having is that the
	MOVC3 statement in the Kernal Mode code, crashes the system every time
	I run it.

Well, here are a few problems with this:

 
You don't really need to lock any pages in your working set;  you don't
need to run above IPL 2.

        $lkwset_s inadr=lock1                   ; lock routine into working set

Owning the I/O database mutex is a sufficient lock on the I/O database; you
don't need to raise IPL all the way to SYNCH.  This just makes things more
difficult.  Also, you need to have your PCB address in R4 when you attempt
to gain ownership of a mutex.  I suspect that you were just lucky and R4
already contained your PCB address...

        jsb     sch$iolockr                     ;; lock io data base for read
        dsbint  #ipl$_synch                     ;; raise ipl while mucking...

Also, all references to locations inside VMS should use the general addressing
mode (to ensure that the code is PIC.  Writing non-PIC code is a hard habit
to break if you're a PDP-11 programmer ...)

	MOVL	G^SCH$GL_CURPCB,R4		;;Grab my PCB address
	JSB	G^SCH$IOLOCKR			;;Lock the I/O database for reading

;;
;; First we need to search the DDB's for the one for the desired device
;;

If you make a descriptor of the device name and unit number, you can save
yourself tons of work by calling IOC$SEARCHDEV, eg:

LTA_DEV:	.Ascid	"LTA1"

	MOVAQ	LTA_DEV,R1			;;Here's the device to search for
	JSB	G^IOC$SEARCHDEV			;;Go find the UCB

You must own the I/O database mutex to call IOC$SEARCHDEV.  It returns status
in R0 (low bit clear means it couldn't find the device).  The device's UCB
address will be returned in R1.  IOC$SEARCHDEV is in module IOSUBPAGD, on
fiche panel 443 B05 (for VMS V4.5).


        movl    ioc$gl_devlist,r10              ;; ddb list in r10

Use G^ addressing, eg:

	MOVL	G^IOC$GL_DEVLIST,R10		;;DDB list in R10


        movl    #port_numb, r6                  ;; Port buffer address
        movl    #srv_name_str, r7               ;; Server name buffer address

Use the MOVAB instruction, eg:

	MOVAB	PORT_NUMB,R6			;;Port buffer address
	MOVAB	SRV_NAME_STR,R7			;;Server name buffer address

;;
;; Establish a pointer to the beginning of the LAT Plus Data
;;
        addl3   #ucb$b_srv_info, r9, r8

You could save a few cycles and use:

	MOVAB	UCB$B_SRV_INFO(R9),R8		;;Address the LAT data area


Your system is crashing because the instruction below is adding more than you
think to R8.  Recall that you only stored 16 bits worth of information in
PORT_LEN, and you're using 32 bits with the ADDL instrction.  The high order
16 bits are comming from the low order 16 bits of PORT_NUMB, which is not
making the processor very happy when it goes to check to make sure you can
see the entire source string described by the first two operands for the MOVC3
instruction ...

        addl2   port_len, r8                    ;; Offset to srv name length

  ;;    movc3   srv_name_len, srv_info_name(r8), (r7)


Also, you're going to run into trouble with disconnectable LAT terminals...


A while back, I wrote a subroutine which will retrieve information about a
LAT port.  Here's another copy:

--------------------------------------------------------------------------------
	.Title	LAT_Info	- Get information about a LAT terminal
	.Ident	/V01.001/
	.Enable	SUP
	.Default Displacement,Word
	.Subtitle	Introduction

;+
;
; ----- LAT_Info:  Get information about a LAT terminal
;
;
; Facility:
;
;	VAX/VMS system programming
;
; Abstract:
;
;	This module provides a routine which can be called from any
;	VAX native  language to obtain information about a specific
;	LAT terminal.
;
; Environment:
;
;	VAX/VMS native mode, VMS V4.2 or later, LATPlus V01.012 or later,
;	CMKRNL privilege.
;
;
;
; Version:	V01.001
; Date:		03-Feb-1987
;
; Gerard K. Newman	19-Dec-1986
; San Diego Supercomputer Center
; GA Technologies
; P.O. Box 85608
; San Diego, CA  92138
; 619.534.5076
;
; Internet:	GKN@SDS.SDSC.EDU
; Bitnet:	GKN@SDSC.BITNET
; Span:		SDSC::GKN (27.1)
;
;
; Modifications:
;
;	 3-Feb-1987	GKN	Don't allow LTA0: to be used.
;
;-

	.Page
	.Subtitle	Local definitions

	.Library "SYS$LIBRARY:LIB"			;Get special macros from here
	.Link	 "SYS$SYSTEM:SYS.STB"/Selective_Search	;Ease the link process a bit

	.NoCross			;Save a tree

	$DCDEF				;Device class & type definitions
	$DDBDEF				;Device data block offsets
	$SSDEF				;System service codes
	$TTYUCBDEF			;Terminal UCB offsets
	$UCBDEF				;UCB offsets

	.Cross				;Turn CREF back on


; Local definitions

; Constants that are likely to change in a future release of VMS that are not
; defined in SYS.STB  or in a macro anywhere.  These values come from looking
; at the running system with SDA.

; Offset in an LT UCB to the length of the port name, which is a counted
; string.  Immediately following the port name is another counted string
; which is the LAT node name.

UCB$B_LT_PORT	=	^X134		;Offset to the port name length
UCB$B_LT_SESS	=	^X195		;Offset to the session number

	.Page
	.Subtitle	LAT_INFO	- Get information about a LAT terminal

;+
;
; ----- LAT_INFO:  Get information about a LAT terminal
;
;
; This routine can be called by any VAX native language to obtain the server
; name, port name  and session number of a  LAT connection given a LT device
; name.  The calling program must have  CMKRNL privilege and  must be linked
; with SYS.STB.
;
; Caveats:
;
;	Will only work with fixed (non-dynamic) string descriptors.
;
; Call sequence:
;
;	status.wlv = LAT_INFO (terminal.rt.dx, session.wlr, server.wt.dx, port.wt.dx)
;
; Inputs:
;
;	4(AP)	- Address of a descriptor of the LT device name.
;	8(AP)	- Address of a longword to return the session number in.
;	12(AP)	- Address of a descriptor to return the server name.
;	16(AP)	- Address of a descriptor to return the server port name.
;
; Outputs:
;
;	R0	- SS$_NOPRIV:	 No CMKRNL privilege.
;		- SS$_ACCVIO:	 One of the arguments is not accessible.
;		- SS$_NOSUCHDEV: The specified LT device can't be found.
;		- SS$_IVDEVNAM:	 The specified device isn't a LAT terminal.
;		- SS$_NORMAL:	 Success.
;
;-

	.Psect	LAT_INFO	EXE,RD,NOWRT,PIC,SHR,PAGE

	.Entry	LAT_INFO,^M<>		;Entry here

	$CMKRNL_S ROUTIN=B^20$,-	;Do this
		ARGLST=(AP)		; in kernel mode

10$:	RET				;Done, status in R0

; Here in kernel mode to do all of the actual work.

20$:	.Word	^M<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11> ;Here in kernel mode to get some info

; First, check to see if we can read the argument list.

	MOVL	#SS$_ACCVIO,R0		;Presume we can't
	IFNORD	#<5*4>,(AP),10$		;Probe the argument list

; Check the number of arguments

	MOVL	#SS$_INSFARG,R0		;Presume we have too few arguments
	CMPB	#4,(AP)			;Do we have enough arguments?
	BNEQ	10$			;If NEQ no, it's wrong somehow

; Check to see if we can write the session number.

	MOVL	#SS$_ACCVIO,R0		;Presume we can't
	IFNOWRT	#4,@8(AP),10$		;Probe the output session number

; See if we can read the device name descriptor.

	MOVL	4(AP),R1		;Address the LT device name descriptor
	JSB	G^EXE$PROBER_DSC	;Probe the descriptor
	BLBC	R0,10$			;Sigh.
	MOVQ	R1,-(SP)		;Save a safe copy of the probed descriptor
	MOVL	SP,R11			;Remember where it is
	CLRW	2(R11)			;Never mind the type and class info

; See if we have write access to the two output descriptors.

	MOVL	12(AP),R1		;Address the server name output descriptor
	JSB	G^EXE$PROBEW_DSC	;Probe the descriptor
	BLBC	R0,10$			;Sigh.
	MOVQ	R1,-(SP)		;Stash a safe copy of the descriptor
	MOVL	SP,R10			;Remember where I put it
	CLRW	2(R10)			;Never mind the type and class info
	MOVL	16(AP),R1		;Address the port name output descriptor
	JSB	G^EXE$PROBEW_DSC	;Probe the descriptor
	BLBC	R0,10$			;Sigh.
	MOVQ	R1,-(SP)		;Stash a safe copy of said descriptor
	MOVL	SP,R9			;Remember where it is
	CLRW	2(R9)			;Never mind the type and class info

; Ok.  Now go hunt down the device the user told us was a LAT terminal
; and see if it really is.

	MOVL	G^SCH$GL_CURPCB,R4	;Get my PCB address
	JSB	G^SCH$IOLOCKR		;Lock the I/O database mutex
	MOVL	R11,R1			;Address the device name descriptor
	JSB	G^IOC$SEARCHDEV		;Go search for the device.
	BLBC	R0,30$			;We lose.

; Now check to see if it's even a terminal, and if it is see if it's a LAT
; terminal.  Remember to chain  to the physical UCB  first in case this is
; a disconnectable terminal.

	MOVL	#SS$_IVDEVNAM,R0	     ;Presume it isn't a terminal
	CMPB	#DC$_TERM,UCB$B_DEVCLASS(R1) ;Is it a terminal?
	BNEQ	30$			     ;If NEQ no.
	MOVL	UCB$L_TL_PHYUCB(R1),R1	     ;Get to the "real" UCB
	BGEQ	30$			     ;If GEQ this is probably LTA0:
	MOVL	UCB$L_DDB(R1),R2	     ;Find the DDB
	CMPW	#^A/LT/,DDB$T_NAME+1(R2)     ;Is this a LAT terminal?
	BNEQ	30$			     ;If NEQ no

; It's a LAT terminal all right.  Obtain the server name, port name and
; session number.

	MOVZBL	UCB$B_LT_SESS(R1),@8(AP) ;Stash the session number
	MOVAB	UCB$B_LT_PORT(R1),R1	 ;Address the port name
	MOVL	R9,R6			 ;Here's the output descriptor address
	BSBB	MOVE_ASCIC		 ;Move the port name
	MOVW	(R6),@16(AP)		 ;Replace the length
	MOVL	R10,R6			 ;R1 now points at the server name
	BSBB	MOVE_ASCIC		 ;So go move it, too
	MOVW	(R6),@12(AP)		 ;Replace the length
	MOVL	#SS$_NORMAL,R0		 ;Success!
	MOVL	G^SCH$GL_CURPCB,R4	 ;Get my PCB address again

30$:	PUSHL	R0			;Save the return status
	JSB	G^SCH$IOUNLOCK		;Unlock the I/O database mutex
	SETIPL	#0			;Drop back down from IPL$_ASTDEL
	POPL	R0			;Restore the return status
	RET				;Back to user mode

; Short subroutine to move a .Ascic string to a place described by a
; descriptor.  Forms a  proper descriptor of the result, and handles
; short buffers, etc.
;
; Inputs:
;
;	R1	- Address of the .Ascic string
;	R6	- Address of the output descriptor
;
; Outputs:
;
;	R1	- Address of one byte past the end of the .Ascic string
;	R0-R5	- Smashed

MOVE_ASCIC:				;Here to move a .Ascic string

	MOVZBL	(R1)+,R0		;Grab the string length
	CMPW	(R6),R0			;Check the string length
	BGEQU	10$			;If GEQU then we can use it
	MOVZWL	(R6),R0			;Else only copy what will fit

10$:	MOVW	R0,(R6)			;Stash the length
	MOVC3	R0,(R1),@4(R6)		;Copy the string
	RSB				;Done


	.End
--------------------------------------------------------------------------------
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
