{"id":116,"date":"2013-01-30T15:15:30","date_gmt":"2013-01-30T21:15:30","guid":{"rendered":"http:\/\/tommysprinkle.com\/mvssp\/?p=116"},"modified":"2013-06-24T21:07:15","modified_gmt":"2013-06-25T02:07:15","slug":"console-communications","status":"publish","type":"post","link":"https:\/\/tommysprinkle.com\/mvssp\/2013\/01\/30\/console-communications\/","title":{"rendered":"Console Communications"},"content":{"rendered":"<p>I include this one not so much because I have found it really useful but becuase I think it has a bit of a cool factor.\u00a0 I first used this back many years ago when I was an operator and would write various utilities for us to use in operations.\u00a0 Since we were in the computer room with the console it was pretty easy just\u00a0 use WTOR to make the program interactive with the console.\u00a0 Back in those days we were batch only and didn&#8217;t use TSO.\u00a0 Using WTOR for communication through the operator console is pretty simple but lacks the cool factor associated with using the MODIFY console command.\u00a0 So here is how to use MODIFY and STOP to communicate with a running program.<\/p>\n<p>First we need to get the address of the Communications Parameter List (mapped by the IEZCOM macro).\u00a0 The COM parameter list consists of two words.<\/p>\n<pre>COMECBPT DS    A       Address of ECB for STOP\/MODIFY\r\nCOMCIBPT DS    A       Address of Command Input Buffer<\/pre>\n<p>To get the address of the COM parameter area we can use the EXTRACT macro.<\/p>\n<pre>         EXTRACT COMPTR,FIELDS=COMM    GET POINTER TO COMM FIELDS<\/pre>\n<p>COMPTR is a fullword where the address of the COM parameter area will be stored. We request the COM parameter area by specifying FIELDS=COMM.<\/p>\n<pre>         L     R1,COMPTR          POINTER TO COMM FIELDS \r\n         LA    R2,4(,R1)          CIB ORIGIN             \r\n         L     R3,0(,R2)          PONTER TO FIRST CIB    \r\n         LTR   R3,R3              ANY START CIB PRESENT  \r\n         BZ    SETCIB             NO - CONTINUE<\/pre>\n<p>Next we load the address of the COM parm area into register 1. Now we have to check to see if there is a Command Input Buffer (CIB) related to a START command. If we are running as a Started Task there should be a CIB, otherwise there is no CIB and the pointer is zero.<\/p>\n<pre>         QEDIT ORIGIN=(R2),BLOCK=(R3)   FREE START CIB<\/pre>\n<p>If there is a CIB as the result of a START command we need to free the CIB. For this we use the QEDIT macro and pass two parameters. ORIGIN refers the the address of the COMCIBPT field (the second word in the COM parmameter list) and BLOCK points the the CIB we wish to free.<\/p>\n<pre>SETCIB   DS    0H                                                     \r\n         QEDIT ORIGIN=(R2),CIBCTR=1     SET CIB LIMIT TO ONE AT A TIME<\/pre>\n<p>Now we set a limit on how many CIBs may be queued to our job at one time. Initially this value is zero which means that MODIFY commands will not be accepted by our job. We want to allow one CIB to be queued at a time so we set the limit using the QEDIT macro. Here we specify the ORIGIN (again the address of the COMCIBPT field) and specify a limit with the CIBCTR parameter.<\/p>\n<pre>LOOP     DS    0H                                    \r\n         L     R1,COMPTR          COMM FIELDS        \r\n         LA    R2,0(,R1)          ECB ADDRESS PTR    \r\n         L     R3,0(,R2)          ECB ADDRESS        \r\n*                                                    \r\n         WAIT  1,ECB=(R3)         WAIT FOR A COMMAND<\/pre>\n<p>Now we will wait for a command from the console. We do this by waiting on the ECB pointed to by the COMECBPT field. We could also be doing some work and check to see if the ECB has been posted to interrupt whatever we are currenty doing. Here we just wait for a command.<\/p>\n<pre>         L     R1,COMPTR          POINTER TO COMM FIELD \r\n         LA    R2,4(,R1)          CIB ORIGIN            \r\n         L     R3,0(,R2)          PONTER TO FIRST CIB<\/pre>\n<p>When the ECB is posted we resume execution and get the address of the CIB. The CIB is mapped by the IEZCIB macro and contains the following fields.<\/p>\n<pre>CIBNEXT  DS    A                  POINTER TO NEXT CIB ON CHAIN OR ZERO IF LAST\r\nCIBVERB  DS    X                  VERB INDICATING TYPE OF COMMAND\r\n*                                 X'04' - START, X'40' - STOP, X'44' - MODIFY\r\nCIBLEN   DS    X                  LENGTH IN DOUBLEWORDS OF CIB\r\n         DS    XL4                Reserved\r\nCIBASID  DS    H  \r\nCIBCONID DS    X                  CONSOLE ID - FROM WHERE COMMAND WAS ISSUED\r\n         DS    X                  Reserved\r\nCIBDATLN DS    H                  LENGTH, IN BYTES, OF CIB DATA\r\nCIBDATA  DS    0C                 DATA FROM MODIFY COMMAND<\/pre>\n<p>The VERB tells us in the CIB was created as a result of a START, STOP, or MODIFY console command. CIBDATALN is the length of data associated with the command. CIBDATA is a variable length field that contains the data from the START or MODIFY command.<\/p>\n<pre>         CLI   4(R3),X'44'        IS IT A MODIFY COMMAND \r\n         BE    MODIFY                                    \r\n*                                                        \r\n         CLI   4(R3),X'40'        IS IT A STOP COMMAND   \r\n         BE    STOP                                      \r\n*                                                        \r\n         WTO   '***  UNKNOWN CIB TYPE ***',ROUTCDE=(1,11)\r\n         B     FREECIB<\/pre>\n<p>Now we check the VERB to determine what type of command we are dealing with. We only expect to find either a STOP or a MODIFY command.<\/p>\n<pre>MODIFY   DS   0H                                                 \r\n         WTO   '***  MODIFY COMMAND RECEIVED ***',ROUTCDE=(1,11) \r\n*                                                                \r\n         LH    R5,14(,R3)         GET COMMAND LENGTH             \r\n         LA    R6,16(,R3)         POINT TO COMMAND<\/pre>\n<p>Here we process a MODIFY command. We point to the data and get the data length from the CIB.<\/p>\n<pre>         LR    R1,R5              COPY LENGTH  \r\n         BCTR  R1,0               SUBTRACT ONE \r\n         MVC   WORK(4),=C'*** '                \r\n         EX    R1,MODMVC                       \r\nMODMVC   MVC   WORK+4(1),0(R6)                 \r\n         LA    R1,WORK+4                       \r\n         AR    R1,R5                           \r\n         MVC   0(4,R1),=C' ***'                \r\n         LA    R1,WORK                         \r\n         LA    R0,8(,R5)                       \r\n         BAL   R14,WTO                         \r\n*                                              \r\n         B     FREECIB<\/pre>\n<p>Next we copy the data into a message area and BAL to a routine that will WTO the message to the console.<\/p>\n<pre>WTO      DS    0H                                  \r\n         STM   R14,R12,12(R13)                     \r\n         LA    R3,SAVEA2                           \r\n         ST    R13,4(,R3)                          \r\n         ST    R3,8(,R13)                          \r\n         LR    R13,R3                              \r\n*                                                  \r\n         LR    R10,R0             SAVE LENGTH      \r\n         LR    R11,R1             SAVE PTR TO TEXT \r\n*                                                  \r\n         LA    R1,1                                \r\n         CR    R10,R1                              \r\n         BL    WTO020                              \r\n*                                                  \r\n         LA    R1,80              MAX LEN          \r\n         CR    R10,R1                              \r\n         BNH   WTO010\r\n*                    \r\n         LR    R10,R1<\/pre>\n<p>Here is the routine to issue the WTO. First we save the caller&#8217;s registers, set up a new save area, and then check the length of the message.<\/p>\n<pre>WTO010   DS    0H                      \r\n         MVC   WTOWORK(4),=X'00008000' \r\n         LA    R1,4(,R10)              \r\n         STH   R1,WTOWORK              \r\n         BCTR  R10,0                   \r\n         EX    R10,WTOMVC              \r\n*WTOMVC  MVC   WTOWORK+4(1),0(R11)     \r\n         LA    R1,WTOWORK              \r\n         LA    R1,5(R10,R1)            \r\n         MVC   0(4,R1),=X'00008020'<\/pre>\n<p>Now we build the SVC 35 parameter list.<\/p>\n<pre>LA    R1,WTOWORK      \r\n         SVC   35              \r\n*                              \r\nWTO020   DS    0H              \r\n         L     R13,4(,R13)     \r\n         LM    R14,R12,12(R13) \r\n         BR    R14<\/pre>\n<p>Now we point to the parameter list, issue the WTO SVC, and then return to the caller.<\/p>\n<pre>STOP     DS   0H                                               \r\n         WTO   '***  STOP COMMAND RECEIVED ***',ROUTCDE=(1,11) \r\n         B     EXIT<\/pre>\n<p>If the VERB indicates a STOP command we issue a WTO and exit.<\/p>\n<pre>FREECIB  DS    0H                                        \r\n         L     R1,COMPTR          POINTER TO COMM FIELDS \r\n         LA    R2,4(,R1)          CIB ORIGIN             \r\n         L     R3,0(,R2)          PONTER TO FIRST CIB    \r\n*                                                        \r\n         QEDIT ORIGIN=(R2),BLOCK=(R3)   FREE THE CIB     \r\n*                                                        \r\n         B     LOOP<\/pre>\n<p>Once we have processed a MODIFY command we need to free the CIB so our program can accept another modify command. We free it using QEDIT the same way we did with the START CIB.<\/p>\n<pre>JOB 6920  $HASP373 CIB01    STARTED - INIT 12 - CLASS A - SYS TCS3  \r\n          f CIB01,HELLO                                             \r\nJOB 6920  +***  MODIFY COMMAND RECEIVED ***                         \r\nJOB 6920  +*** HELLO ***                                            \r\n          f cib01,This is a TEST                                    \r\nJOB 6920  +***  MODIFY COMMAND RECEIVED ***                         \r\nJOB 6920  +*** THIS IS A TEST ***                                   \r\n          f cib01,Parameters to pass to the program                 \r\nJOB 6920  +***  MODIFY COMMAND RECEIVED ***                         \r\nJOB 6920  +*** PARAMETERS TO PASS TO THE PROGRAM ***                \r\n          p cib01                                                   \r\nJOB 6920  +***  STOP COMMAND RECEIVED ***                           \r\nJOB 6920  14.09.40   0.00.45   0.00.00  0000   CIB01     MVSSP      \r\nJOB 6920  14.09.40   0.00.45   0.00.00  0000   CIB01     ########   \r\nJOB 6920  $HASP395 CIB01    ENDED<\/pre>\n<p>And here is some sample output from running the program and communicating with it using MODIFY and STOP.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I include this one not so much because I have found it really useful but becuase I think it has a bit of a cool factor.\u00a0 I first used this back many years ago when I was an operator and would write various utilities for us to use in operations.\u00a0 Since we were in the &#8230;<\/p>\n<p><a href=\"https:\/\/tommysprinkle.com\/mvssp\/2013\/01\/30\/console-communications\/\" class=\"more-link\">Continue reading &lsquo;Console Communications&rsquo; &raquo;<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[26],"tags":[],"class_list":["post-116","post","type-post","status-publish","format-standard","hentry","category-modify-and-stop-console-commands"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p3x7AW-1S","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/tommysprinkle.com\/mvssp\/wp-json\/wp\/v2\/posts\/116","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/tommysprinkle.com\/mvssp\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/tommysprinkle.com\/mvssp\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/tommysprinkle.com\/mvssp\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/tommysprinkle.com\/mvssp\/wp-json\/wp\/v2\/comments?post=116"}],"version-history":[{"count":4,"href":"https:\/\/tommysprinkle.com\/mvssp\/wp-json\/wp\/v2\/posts\/116\/revisions"}],"predecessor-version":[{"id":211,"href":"https:\/\/tommysprinkle.com\/mvssp\/wp-json\/wp\/v2\/posts\/116\/revisions\/211"}],"wp:attachment":[{"href":"https:\/\/tommysprinkle.com\/mvssp\/wp-json\/wp\/v2\/media?parent=116"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/tommysprinkle.com\/mvssp\/wp-json\/wp\/v2\/categories?post=116"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/tommysprinkle.com\/mvssp\/wp-json\/wp\/v2\/tags?post=116"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}