From:	CSBVAX::MRGATE!@KL.SRI.Com,@wiscvm.wisc.edu:dstevens@sitvxb@SMTP  8-JUL-1987 17:32
To:	EVERHART
Subj:	Help with a Kernal mode macro program

Received: from wiscvm.wisc.edu by KL.SRI.COM with TCP; Wed 8 Jul 87 09:39:19-PDT
Received: from sitvxb by wiscvm.wisc.edu ; Wed, 08 Jul 87 11:27:46 CDT
Date:     Wed, 8 Jul 87 12:29:44 EDT
From:     dstevens (David L Stevens) @ sitvxb
Message-Id: <870708122836.001@sitvxb>
Subject:  Help with a Kernal mode macro program
To:       INFO-VAX @ SRI-KL.ARPA


 Greetings,
        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.
 If I take out the MOVC3 statements, and run the program the Length of the
 port string, the length of the Server string are retrieved no problem.  Also
 I checked, and R8 does point at the beginning of the LAT information area in
 the UCB block.  If anyone can tell me what I am doing wrong here please let
 me know, I'm stumpted.  Remember this is KERNAL Mode code that is broken, and
 as such will crash the system, and requires CMKRNL priv, so be carefull when
 you test it/(hopfully) fix it.

------------------------------------------------------------------------------
                        LAT_PLUS_INFO.MAR

        .title lat_plus_info
;;; lat_info - get information about LAT terminals (privileged)
;++
;    Module :   LAT_INFO.MAR
;    Author :   David L. Stevens
;               Stevens Institute of Technology
;
; This module was based on the TTUCB.MAR file of the Finger system.  I
;    gratefully thank the author of that program for the help that it
;    gave me while hacking out this program.  This program requires
;    CMKRNL privileges to run.  It will retrieve the Server name, the
;    Server Port Number and the Server's Ethernet address.  Hopefully
;    DEC will not modify the format of a LAT Plus UCB and destroy the offsets.
;
; revision history:
;
;  7-July-1987          Create this Module.             [DLS]
;
;--

        .library  /sys$library:lib.mlb/
        $ucbdef
        $ddbdef
        $ipldef
        $ttyucbdef
;
;       Useful constants
;
num_args        =       4                       ;; Number of arguments
ap_numb         =       4                       ;; Offset to unit number
ap_name         =       8                       ;; Offset to return buff addr
ap_port         =       12                      ;; Offset to return port buffer
ap_eth          =       16                      ;; Offset to return eth buffer

ucb$b_srv_info  =       ^x134                   ;; offset in UCB to server info

srv_info_port   =       1
srv_info_name   =       2









;;
;; LAT_INFO
;;
;; this routine is called to get information about a specified lat line
;;
;;      r2  - LTA device number to get info on
;;      r3  - Pointer to return buffer for the Server name
;;      r4  - Pointer to return buffer for the Server port
;;      r5  - Pointer to return buffer for the Server ethernet address
;;      r6  - Scratch
;;

        .entry  lat_info,^M<r2,r3,r4,r5,r6>

        cmpl    #num_args,(ap)                  ; need this many arguments
        beql    10$                             ; branch if correct
        movl    #ss$_badparam,r0                ; setup error status
        ret                                     ; go give him the bad news

10$:    clrl    eth_addr                        ; Clear out the --
        clrw    eth_addr+4                      ;   -- ethernet addr buffer
        clrb    srv_name_len                    ; Clear out the server name len
        clrb    port_len                        ; Clear out the port # buff

        $lkwset_s inadr=lock1                   ; lock routine into working set
        cmpl    #ss$_wasclr,r0                  ; did we lock the pages?
        beql    20$                             ; branch if so
        cmpl    #ss$_wasset,r0                  ; were they already locked?
        bneq    err                             ; if not, then error

20$:    movw    ap_numb(ap),unit_numb           ; Get the needed unit number
        $cmkrnl_s routin=latinfkrn              ; do the privileged stuff
        movl    r0,r6                           ; save status for later

        $ulwset_s inadr=lock1                   ; unlock kernel routine
        cmpl    #ss$_wasclr,r0                  ; did we unlock the pages?
        beql    info                            ; branch if so
        cmpl    #ss$_wasset,r0                  ; were they already unlocked?
        beql    info                            ; branch if so
err:    ret                                     ; ERROR; that's all folks!

info:   tstb    srv_name_len
        beql    40$
        movl    ap_name(ap),r3                  ; Get the return name buf addr
        movc3   srv_name_len,srv_name_str,(r3)

40$:    tstb    port_len
        beql    50$
        movl    ap_port(ap),r4                  ; Get the return port buf addr
        movc3   port_len,port_numb,(r4)

50$:    tstl    eth_addr
        beql    60$
        movl    ap_eth(ap),r5                   ; Get the return eth-adr buf adr
        movl    eth_addr,(r5)
        movw    eth_addr+4,4(r5)

60$:    movl    r6,r0
        ret                                     ; that's all folks!










;
;       Descriptor used to lock kernel routine into our working set
;
lock1:  .address        latinfkrn
        .address        latinfkrnend

;;
;; LATINFKRN
;;
;; Entry point for the privileged search and slurp. The following
;; registers are used:
;;
;;      r0  - return status
;;      r6  - Port Buffer
;;      r7  - Server name buffer
;;      r8  - Start address of LAT Plus Info
;;      r9  - address of current LAT UCB
;;      r10 - address of current DDB
;;

        .entry  latinfkrn,^M<r6,r7,r8,r9,r10>

        jsb     sch$iolockr                     ;; lock io data base for read
        dsbint  #ipl$_synch                     ;; raise ipl while mucking...
;;
;; First we need to search the DDB's for the one for the desired device
;;
        movl    ioc$gl_devlist,r10              ;; ddb list in r10
        movl    #port_numb, r6                  ;; Port buffer address
        movl    #srv_name_str, r7               ;; Server name buffer address
        brb     jump1                           ;; jump into middle loop

loop1:  movl    ddb$l_link(r10),r10             ;; look at next ddb
jump1:  beql    finish                          ;; already did last controller

        cmpc3   #3,dev_name,ddb$t_name+1(r10)   ;; Is it an LTA DDB ???
        bneq    loop1                           ;; No try for the next one.
;;
;; Now we traverse down the string of UCB's for the correct unit
;;
        movl    ddb$l_ucb(r10),r9               ;; fetch first ucb for this ddb
        brb     jump2                           ;; jump into innermost loop

loop2:  movl    ucb$l_link(r9),r9               ;; look at next ucb
jump2:  beql    finish                          ;; no more units left

        cmpw    unit_numb,ucb$w_unit(r9)        ;; is this the right unit number
        bneq    loop2                           ;; next ucb if not
;;
;; Establish a pointer to the beginning of the LAT Plus Data
;;
        addl3   #ucb$b_srv_info, r9, r8
;;
;; Now we get the information we need about the LAT line
;;
        movzbw  (r8), port_len                  ;; Get the length of port string
        beql    srvinf                          ;; If Zero length then branch
;;
;; Move the data into the storage area
;;
        movc3   port_len, srv_info_port(r8), (r6)
;;
;; Get the Server name information
;;
srvinf:
        addl2   port_len, r8                    ;; Offset to srv name length
;;
;; Get the length of the string
;;
        movzbw  srv_info_port(r8), srv_name_len
        beql    finish                          ;; If Zero length then branch
;;
;; Get the data
;;
  ;;    movc3   srv_name_len, srv_info_name(r8), (r7)
;;
;; Now set up for a return
;;
finish: jsb     sch$iounlock                    ;; unlock io data base
        enbint                                  ;; restore ipl

        movl    #ss$_normal,r0                  ;; set up normal return
        ret                                     ;; back to user mode

;;
;; Storage locations
;;

dev_name:       .asciz  "LTA"                   ;; Generic device name
unit_numb:      .blkw   1                       ;; Current unit number
port_len:       .blkw   1                       ;; Length of port string
port_numb:      .blkb   16                      ;; Remote port string
srv_name_len:   .blkw   1                       ;; Length of server name string
srv_name_str:   .blkb   16                      ;; Server name string
eth_addr:       .blkw   3                       ;; Servers Ethernet Address

latinfkrnend:                                   ;; end of locked memory

        .end


-------------------------------------------------------------------------------
                                TEST.C

#include        <stdio.h>
main()
{
    char        name[20];
    char        port[20];
    int         ether[2];
    int         i = 0;

    ether[0] = 0; ether[1] = 0;
    for (;i<20;i++)
    {
        name[i] = NULL;
        port[i] = NULL;
    }

    lat_info(1,&name[0], &port[0], &ether[0]);
    printf(" LTA1, Server name %s, port %s, ether %x%x. \n",
                name, port, ether[0],ether[1]);
 }

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

 The command to link the programs together is:
        $ LINK TEST,LAT_PLUS_INFO,SYS$SYSTEM:SYS.STB/SELECT

 Any and all help will be gratefully appreciated.

 - Thanx
 - Dave Stevens
 - Systems Programmer
 - Stevens Institute of Technology
 - Address:
        BITnet:         DSTEVENS@SITVXA
        ARPAnet:        DSTEVENS%SITVXA.BITNET@WISCVM.ARPA
        CCnet:          SITVXA::DSTEVENS

