home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / X25.ZIP / X25 / X25_M / X25MXMIT.ASM < prev    next >
Assembly Source File  |  1991-09-29  |  31KB  |  635 lines

  1.         PAGE    ,132  ; (CTRL-OH) sets printer to condensed mode
  2.         TITLE   X25MXMIT - Transmitter Sample Program for MASM 5.1
  3. ;***************************************************************************
  4. ; Module      : X25MXMIT.ASM
  5. ;
  6. ; Copyright   : (C) Copyright IBM Corp. 1989.1991
  7. ;               Licensed Material - Program Property of IBM
  8. ;               All Rights Reserved
  9. ;
  10. ; Compiler    : Microsoft Macro Assembler 5.1
  11. ;               Microsoft is a registered trademark of Microsoft Corporation.
  12. ;
  13. ; Description : This is the transmitter part of the sample program to
  14. ;               demonstrate use of the X.25 API supplied in the OS/2
  15. ;               Extended Services Communications Manager.
  16. ;
  17. ;               After initialising the X.25 API, the program places
  18. ;               a call to the name given as the parameter to the program.
  19. ;               Then transmits several blocks of data before sending an end
  20. ;               of data marker. It then waits for the receiver to acknowledge
  21. ;               receipt of the data by sending a clear packet.
  22. ;
  23. ;               In the event of an error, a message is printed,
  24. ;               and the program tries to tidy up before exiting.
  25. ;
  26. ;               The program uses the following X.25 API verbs:
  27. ;
  28. ;                   X25APPINIT
  29. ;                   X25CALL
  30. ;                   X25DATASEND
  31. ;                   X25DATARECEIVE
  32. ;                   X25APPTERM
  33. ;
  34. ; Note        : This program should be started after the corresponding
  35. ;               receiver program, X25MRCV.
  36. ;
  37. ;               The name given must exist in the X.25 Directory. It should
  38. ;               refer to a non-SNA remote SVC.
  39. ;
  40. ;                D bit acknowledgement can be requested by setting use_dbit
  41. ;                EQU d_bit.
  42. ;***************************************************************************
  43.  
  44. .286p                           ; Allows use of 286 protected mode instructions
  45. .xlist                                ; turns off the listing of included files
  46.  
  47.             INCLUDE sysmac.inc              ; Include macros for OS/2 functions
  48.             INCLUDE x25_aset.inc                                 ; X25 includes
  49.             INCLUDE x25_a.inc
  50. .list                                                ; restores the list option
  51.  
  52. @mova      macro    full_address, ofs, sel      ; move selector and offset
  53.             mov   ax, sel                       ; move address of data selector
  54.             mov   word ptr full_address+2,ax    ; and
  55.             mov   ax, ofs                       ; offset into the data buffer
  56.             mov   word ptr full_address,ax      ; double word
  57.            endm
  58.  
  59. @X25       macro                                        ; define x25 call macro
  60.             push shrdseg
  61.             push ofs_xvrb
  62.             call far ptr x25
  63.            endm
  64.  
  65.  
  66. stack       SEGMENT word stack 'STACK'
  67.             DB     3500d DUP (?)                         ; define our stacksize
  68. stack       ENDS
  69.  
  70. dgroup      GROUP  data                               ; DGROUP required by OS/2
  71.  
  72. data        SEGMENT word public 'DATA'
  73.  
  74. ofs_xvrb        DW  0                                          ; offset of xvrb
  75. ofs_call_data   DW  0                              ; offset of call data buffer
  76. ofs_data_data   DW  0                 ; offset of data buffer for received data
  77. SemAddress      DD  0                                ; address of ram semaphore
  78.  
  79. buffer_size     EQU 128d                             ; size of Data Send buffer
  80. rcv_buffer_size EQU 512d                            ; size of Call Clear buffer
  81. Dir_Pointer     DD  0                         ; pointer to directory entry name
  82. num_of_messages DB  5d                                      ; that we will send
  83. DirName         DB  8  DUP (' ')                       ; directory name to call
  84. DirNameLen      EQU $-DirName                           ; length of this string
  85. DirNameChars    DW  ?                            ; actual length of input chars
  86. data_type       DB  ?                               ; used by data receive verb
  87. datatosend      DB  40 DUP(' ')
  88. datatosendlen   DW  0
  89. shrdseg         DW  0                  ; segment selector for our shared memory
  90. initalise       EQU 1               ; flag for dossubset to initalise a segment
  91. shareable       EQU 0011b                                ; flag for DosAllocSeg
  92. segsize         EQU 32768                ; size for DosAllocSeg and DosSubAlloc
  93. use_dbit        EQU 0                                ; do not want to use d bit
  94. connid          DD  0                                   ; connection identifier
  95. ErrNum          DW  ?                   ; return code from x25 and system calls
  96. ErrorType       DW  ?                        ; to check if error was Dos or X25
  97. Immediate       EQU 1                                      ;X25 immediate error
  98. Completion      EQU 2                                     ;X25 completion error
  99. DosError        EQU 3                                      ;Error from OS2 call
  100.  
  101. NoTimeOut       DD  -1                             ; no time out for DosSemWait
  102. hundreds        DB  ?                      ; used for hex to decimal conversion
  103. tens            DB  ?
  104. units           DB  ?
  105. hundred         DW  100d
  106. ten             DW  10d
  107.  
  108.                                                  ; Messages used by the program
  109. BadEnvMsg       DB  'Bad Enviroment - cannot find directory entry name'
  110. BadEnvLen       EQU $-BadEnvMsg
  111. InitGoodMsg     DB  'X.25 API Initialised'
  112. InitGoodLen     EQU $-InitGoodMsg
  113. InitBadMsg      DB  'Couldn''t initialise X.25 API'
  114. InitBadLen      EQU $-InitBadMsg
  115. MCallMsg        DB  'Making a Call'
  116. MCallLen        EQU $-MCallMsg
  117. MCallGoodMsg    DB  'Connection established to remote DTE'
  118. MCallGoodLen    EQU $-MCallGoodMsg
  119. MCallBadMsg     DB  'Couldn''t make a call'
  120. MCallBadLen     EQU $-MCallBadMsg
  121. ClrErrMsg       DB  'Call was cleared - Cause :'
  122. ClrErrLen       EQU $-ClrErrMsg
  123. SDataGoodMsg    DB  'Sent Data ...'
  124. SDataGoodLen    EQU $-SDataGoodMsg
  125. SDataBadMsg     DB  'Data send failed'
  126. SDataBadLen     EQU $- SDataBadMsg
  127. DataRcvGoodMsg  DB  'Data Receive completed successfully'
  128. DataRcvGoodLen  EQU $-DataRcvGoodMsg
  129. DataRcvBadMsg   DB  'Data receive failed'
  130. DataRcvBadLen   EQU $-DataRcvBadMsg
  131. UknDataMsg      DB  'Unexpected type of data has been received'
  132. UknDataLen      EQU $-UknDataMsg
  133. DiagCodeMsg     DB  ' Diagnostic :'
  134. DiagCodeLen     EQU $-DiagCodeMsg
  135. TermGoodMsg     DB  'X.25 API Terminated'
  136. TermGoodLen     EQU $-TermGoodMsg
  137. TermBadMsg      DB  'Couldn''t Terminate X.25 API'
  138. TermBadLen      EQU $-TermBadMsg
  139. ClearMsg        DB  'Clear indication packet has been received'
  140. ClearLen        EQU $-ClearMsg
  141. EOMSentMsg      DB  'End of data marker sent'
  142. EOMSentLen      EQU $-EOMSentMsg
  143. MessageStr      DB  'ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890'
  144. MessageLen      EQU $-MessageStr
  145. EomStr          DB  '***'
  146. EomLen          EQU $-EomStr
  147. X25ImmErrMsg    DB  'X25 Error occured Immediate return code of :'
  148. X25ImmErrLen    EQU $-X25ImmErrMsg
  149. X25DelErrMsg    DB  'X25 Error occured Completion return code of :'
  150. X25DelErrLen    EQU $-X25DelErrMsg
  151. DosErrMsg       DB  'Dos Error occured return code of :'
  152. DosErrLen       EQU $-DosErrMsg
  153. DosTermMsg      DB  ' Terminating Program'
  154. DosTermLen      EQU $-DosTermMsg
  155. crlf            DB  0Dh, 0Ah                     ;carriage return and line feed
  156.  
  157.                                                 ; variables for character input
  158.  
  159. data        ENDS
  160.  
  161. shared_buffer SEGMENT word public 'shared'
  162.  
  163. xvrb            X25VERB         <>               ; define over the same storage
  164.                 org     xvrb                    ; we will override the selector
  165. call_data       X25CALL_DATA    <>                          ; and offset anyway
  166.                 org     xvrb
  167. data_data       X25DATA_DATA    <>
  168.  
  169. shared_buffer ENDS
  170.  
  171. code        SEGMENT byte public 'CODE'
  172.             ASSUME cs:code,ds:dgroup,ss:stack
  173.  
  174. ;=============================================================================
  175. ; Main program starts here
  176. ;=============================================================================
  177. x25mxmit    PROC   FAR                                  ; Entry point from OS/2
  178.             mov    word ptr Dir_Pointer+2,AX      ; Save pointer to command line
  179.             mov    word ptr Dir_Pointer,BX
  180.             mov    ax,dgroup                         ; Set up addressability to
  181.             mov    ds,ax                           ; the automatic data segment
  182.             call   allocmem               ; allocate the shared memory segments
  183.  
  184.             call   parse_dirname            ; get the directory entry to call
  185.             assume es:shared_buffer         ; so we don't need ES: all the time
  186.             mov    es, shrdseg                ; set es to our allocated segment
  187.             call   init_app                                ; initialise the API
  188.             call   make_call                                  ; set up the call
  189.  
  190. ;=============================================================================
  191. ; Now send data to Receiver
  192. ;=============================================================================
  193.             mov   bx, 0
  194. Filldata:                                   ; copy data into send buffer
  195.             mov   al, [MessageStr + BX]
  196.             mov   [Datatosend + BX ], al
  197.             inc   bx
  198.             cmp   bx, messagelen
  199.             jne   FillData
  200.             mov   datatosendlen,messagelen  ; length of data to send
  201.  
  202.             mov    cl,0                     ; use cl to count the messages sent
  203. LoopSend:
  204.  
  205.             call   send_data
  206.             inc    cl
  207.             cmp    cl, num_of_messages      ; test to see if all data sent
  208.             jne    LoopSend
  209.  
  210. ;=============================================================================
  211. ; Now send end of data marker
  212. ;=============================================================================
  213.             mov   bx, 0
  214. Eomdata:                                    ; copy data into send buffer
  215.             mov   al, [EomStr + BX]
  216.             mov   [Datatosend + BX ], al
  217.             inc   bx
  218.             cmp   bx, Eomlen
  219.             jne   EomData
  220.             mov   datatosendlen,eomlen      ; length of data to send
  221.  
  222.             call   send_data
  223.             @VioWrtTTY EOMSentMsg, EOMSentLen,0
  224.             @VioWrtTTY crlf,2,0
  225.  
  226. ;=============================================================================
  227. ; Now wait for Receiver to send clear packet
  228. ;=============================================================================
  229. looprcv:
  230.             call   rcv_data                             ; receive data
  231.             cmp    data_type, X25DATARCV_CLEAR          ; see if clear packet
  232.             je     finish
  233.             @VioWrtTTY UknDataMsg, UknDataLen,0
  234.             @VioWrtTTY crlf,2,0
  235.             jmp    looprcv                       ; repeat until clear received
  236. finish:
  237.             @VioWrtTTY ClearMsg, ClearLen,0
  238.             @VioWrtTTY crlf,2,0
  239.             call   term_app                                 ; terminate the API
  240.  
  241.             @dosexit       1,0                     ; Exit with return code of 0
  242.  
  243. ;=============================================================================
  244. ; Get Directory name
  245. ;=============================================================================
  246. parse_dirname proc
  247.  
  248. ; Gets the directory name from the command line and places it into a variable
  249. ; for later use
  250.  
  251.          les     di,Dir_Pointer              ;points to command line in env str
  252.          xor     ax,ax                                             ;set AL = 00
  253.          mov     cx,100                           ;max size to scan = 100 bytes
  254.          cld                                               ;set DF to increment
  255. Pf_Skip_Command:
  256.          scas    es:byte ptr [di]                 ;look for 00 (end of command)
  257.          je      Pf_Next                           ;we are now past the command
  258.          dec     cx                                             ;else try again
  259.          jcxz    Pf_Bad_Env                  ;if we count out,something's wrong
  260.          jmp     Pf_Skip_Command               ;keep looking for end of command
  261. Pf_Next:
  262.          cmp     byte ptr es:0 [di],20h        ;Usually we have a leading blank
  263.          jne     Pf_Noadj                          ;If not, the name addr is ok
  264.          inc     di                            ;Else, increment to skip leading
  265.                                                ;blank
  266.          jmp     Pf_Next                       ;Keep looking for first nonblank
  267. Pf_Noadj:
  268.          mov     word ptr Dir_Pointer,di          ;reset ptr to indicate ASCIIZ
  269.                                                   ;filename
  270.          xor     cx,cx                                         ;string size = 0
  271.          mov     si,0                                      ;offset into DirName
  272.                                                            ;to put data
  273. Pf_Loop:
  274.          mov     al,byte ptr es:[di]                        ;get a byte of name
  275.          cmp     al,00                                      ;end of name flag ?
  276.          je      Pf_Done                           ;if so we are done moving it
  277.          cmp     al,20h                                        ;is it a blank ?
  278.          Je      Pf_Skipit                                   ;if blank, skip it
  279.          mov     byte ptr [DirName + si],al                      ;move the data
  280.          inc     si                                     ;SI = index in DirNname
  281.          inc     cx                                            ;increment count
  282. Pf_Skipit:
  283.          inc     di                            ;DI = source index in env string
  284.          cmp     cx,DirNameLen                              ;check for max size
  285.          je      Pf_8_Bytes                            ;only take first 8 bytes
  286.          Jmp     Pf_Loop                                       ;go move another
  287. Pf_Done:
  288.          mov     byte ptr [DirName + si],al                    ;move the data
  289.          inc     cx                                            ;increment count
  290. Pf_8_Bytes:
  291.          mov     DirNameChars,cx
  292.          ret
  293.  
  294. Pf_Bad_env:                                                ;error in env string
  295.          @VioWrtTTY BadEnvMsg, BadEnvLen,0  ;issue message
  296.          @VioWrtTTY crlf,2,0
  297.          @DosExit 0,0                       ;and quit
  298. parse_dirname endp
  299. ;=============================================================================
  300. ; Make and Call X25APPINIT
  301. ;=============================================================================
  302. init_app    PROC                                 ;make verb and call X25APPINIT
  303.             mov   di, ofs_xvrb
  304.             mov   [di+xvrb.verb_code], X25APPINIT
  305.             mov   [di+xvrb.version_id], X25_API_VERSION
  306.             mov   [di+xvrb.data_buffer_size], 0   ; The data buffer is not used
  307.  
  308.             @X25                                                 ; call the API
  309.             cmp   ax, X25_OK                               ; check immediate RC
  310.             je    NoImmErr1
  311.             mov   ErrorType, Immediate               ; Indicate immediate error
  312.             jmp   InitErr
  313. NoImmErr1:
  314.             call  SemWait                           ; wait for verb to complete
  315.             mov   di, ofs_xvrb
  316.             mov   ax, [di+xvrb.return_code]
  317.             cmp   ax, X25_OK                              ; check Completion RC
  318.             je    InitGood
  319.             mov   ErrorType, Completion             ; Indicate completion error
  320.             jmp   InitErr
  321. InitErr:
  322.             mov   ErrNum, ax
  323.             @VioWrtTTY InitBadMsg,InitBadlen,0
  324.             @VioWrtTTY crlf,2,0
  325.             call  Error
  326. InitGood:
  327.             @VioWrtTTY InitGoodMsg,InitGoodlen,0
  328.             @VioWrtTTY crlf,2,0
  329.             ret
  330.  
  331. init_app    ENDP
  332.  
  333. ;=============================================================================
  334. ; Make and Call X25CALL
  335. ;=============================================================================
  336. make_call   PROC                                    ;make verb and call X25CALL
  337.             mov   di, ofs_xvrb
  338.             mov   [di+xvrb.verb_code], X25CALL
  339.             mov   [di+xvrb.version_id], X25_API_VERSION
  340.             mov   [di+xvrb.queue_number], 0          ; queues are not used here
  341.             @mova [di+xvrb.data_buffer_ptr], ofs_call_data, shrdseg
  342.             mov   [di+xvrb.data_buffer_size], X25CALLDATA_SIZE
  343.  
  344.             ; indicate that we don't wish to use delivery confirmation for data
  345.             mov   [di+xvrb.control], use_dbit
  346.  
  347.  
  348.             mov   di, ofs_call_data
  349.             mov   ax, DirNameChars
  350.             mov   [di+call_data.called_address_length], ax
  351.             mov   [di+call_data.calling_address_length], 0
  352.             mov   [di+call_data.facilities_length], 0
  353.             mov   [di+call_data.cud_length], 0
  354.  
  355.             mov   bx, 0                                      ; Initialise index
  356. CopyLoop:                                          ;now copy the directory name
  357.             mov   al , byte ptr [DirName+bx]         ;into the call data buffer
  358.             mov   byte ptr [di+call_data.called_address+bx], al
  359.             inc   bx
  360.             cmp   bx, DirNameLen                            ; see if all copied
  361.             jne   CopyLoop
  362.  
  363.             @VioWrtTTY MCallMsg,MCalllen,0
  364.             @VioWrtTTY crlf,2,0
  365.  
  366.             @X25                                            ; Call the X.25 API
  367.             cmp   ax, X25_OK                               ; check immediate RC
  368.             je    NoImmErr2
  369.             mov   ErrorType, Immediate               ; Indicate immediate error
  370.             jmp   MakeCallErr
  371. NoImmErr2:
  372.             call  SemWait                           ; wait for verb to complete
  373.             mov   di, ofs_xvrb
  374.             mov   ax, [di+xvrb.return_code]
  375.             cmp   ax, X25_OK                              ; check Completion RC
  376.             je    MakeCallGood
  377.             mov   ErrorType, Completion             ; Indicate completion error
  378.             jmp   MakeCallErr
  379. MakeCallErr:
  380.             mov  ErrNum, ax
  381.             cmp  ax, X25_CALL_CLEARED                     ; ax still has the rc
  382.             je   ClearError
  383.             @VioWrtTTY MCallBadMsg,MCallBadlen,0
  384.             @VioWrtTTY crlf,2,0
  385.             call Error
  386. MakeCallGood:
  387.             @VioWrtTTY MCallGoodMsg,MCAllGoodlen,0
  388.             @VioWrtTTY crlf,2,0
  389.             mov   di, ofs_xvrb
  390.             mov   ax, word ptr [di+xvrb.connection_id]            ; fill in the
  391.             mov   word ptr connid, ax                           ; connection id
  392.             mov   ax, word ptr [di+xvrb.connection_id+2]
  393.             mov   word ptr connid+2, ax
  394.             ret
  395. ClearError:
  396.             @VioWrtTTY ClrErrMsg,ClrErrLen,0
  397.             xor   ax,ax                                              ; clear ax
  398.             mov   al, byte ptr [di+xvrb.cause_code]
  399.             call  WrtDec
  400.             @VioWrtTTY DiagCodeMsg,DiagCodeLen,0
  401.             xor   ax,ax                                              ; clear ax
  402.             mov   al, byte ptr [di+xvrb.diagnostic_code]
  403.             call  WrtDec
  404.             @VioWrtTTY crlf,2,0
  405.             call  Error
  406.  
  407. make_call   ENDP
  408.  
  409. ;=============================================================================
  410. ; Make and Call X25DATASEND
  411. ;=============================================================================
  412. send_data   PROC                                ;make verb and call X25DATASEND
  413.             mov   di, ofs_xvrb
  414.             mov   [di+xvrb.verb_code], X25DATASEND      ; function to be called
  415.             mov   [di+xvrb.version_id], X25_API_VERSION
  416.             mov   [di+xvrb.queue_number], 0
  417.             @mova [di+xvrb.data_buffer_ptr], ofs_data_data, shrdseg
  418.             mov   [di+xvrb.data_buffer_size], buffer_size
  419.             mov   [di+xvrb.data_length], messagelen
  420.             mov   ax, word ptr connid+2
  421.             mov   word ptr [di+xvrb.connection_id+2], ax          ; fill in the
  422.             mov   ax, word ptr connid                           ; connection id
  423.             mov   word ptr [di+xvrb.connection_id], ax
  424.  
  425.             ; now we set the d, m and q bits to off
  426.             ; all 3 bits are in the control byte
  427.             mov   [di+xvrb.control], use_dbit
  428.  
  429.             mov   di, ofs_data_data
  430.             mov   bx, 0
  431. FillBuffer:
  432.             mov   al, [Datatosend + BX]
  433.             mov   [di+ data_data + BX ], al
  434.             inc   bx
  435.             cmp   bx, datatosendlen
  436.             jne   FillBuffer
  437.  
  438.             @X25                                            ; Call the X.25 API
  439.  
  440.             cmp   ax, X25_OK                               ; check immediate RC
  441.             je    NoImmErr3
  442.             mov   ErrorType, Immediate               ; Indicate immediate error
  443.             jmp   SDataErr
  444. NoImmErr3:
  445.             call  SemWait                           ; wait for verb to complete
  446.             mov   di, ofs_xvrb
  447.             mov   ax, [di+xvrb.return_code]
  448.             cmp   ax, X25_OK                              ; check Completion RC
  449.             je    SDataGood
  450.             mov   ErrorType, Completion             ; Indicate completion error
  451.             jmp   SDataErr
  452. SDataErr:
  453.             mov   ErrNum, ax
  454.             @VioWrtTTY SDataBadMsg,SDataBadlen,0
  455.             @VioWrtTTY crlf,2,0
  456.             call  error
  457. SDataGood:
  458.             @VioWrtTTY SDataGoodMsg,SDataGoodlen,0
  459.             @VioWrtTTY crlf,2,0
  460.             ret
  461.  
  462. send_data   ENDP
  463.  
  464. ;=============================================================================
  465. ; Make and Call X25DATARECEIVE
  466. ;=============================================================================
  467. rcv_data    PROC                             ;make verb and call X25DATARECEIVE
  468.             mov    di, ofs_xvrb
  469.             mov    [di+xvrb.verb_code], X25DATARECEIVE  ; function to be called
  470.             mov    [di+xvrb.version_id], X25_API_VERSION
  471.             mov    [di+xvrb.queue_number], 0
  472.             @mova  [di+xvrb.data_buffer_ptr], ofs_data_data, shrdseg
  473.             mov    ax, rcv_buffer_size          ; size of the call clear packet
  474.             mov    [di+xvrb.data_buffer_size], ax
  475.             mov    ax, word ptr connid+2
  476.             mov    word ptr [di+xvrb.connection_id+2], ax         ; fill in the
  477.             mov    ax, word ptr connid                          ; connection id
  478.             mov    word ptr [di+xvrb.connection_id], ax
  479.  
  480.             @X25                                            ; Call the X.25 API
  481.             cmp    ax, X25_OK                              ; check immediate RC
  482.             je     NoImmErr5
  483.             mov    ErrorType, Immediate              ; Indicate immediate error
  484.             jmp    DataRcvErr
  485. NoImmErr5:
  486.             call   SemWait                          ; wait for verb to complete
  487.             mov    di, ofs_xvrb
  488.             mov    ax, [di+xvrb.return_code]
  489.             cmp    ax, X25_OK                             ; check Completion RC
  490.             je     DataRcvGood
  491.             mov    ErrorType, Completion            ; Indicate completion error
  492.             jmp    DataRcvErr
  493. DataRcvErr:
  494.             mov    ErrNum, ax
  495.             @VioWrtTTY DataRcvBadMsg,DataRcvBadlen,0
  496.             @VioWrtTTY crlf,2,0
  497.             call   Error
  498. DataRcvGood:
  499.             @VioWrtTTY DataRcvGoodMsg,DataRcvGoodlen,0
  500.             @VioWrtTTY crlf,2,0
  501.  
  502.             mov    di, ofs_xvrb
  503.             mov    al, [di+xvrb.data_event_type]
  504.             mov    data_type, al                           ; save received type
  505.             ret
  506.  
  507. rcv_data    ENDP
  508.  
  509. ;=============================================================================
  510. ; Make and Call X25APPTERM
  511. ;=============================================================================
  512. term_app    PROC                                 ;make verb and call X25APPTERM
  513.             mov   di, ofs_xvrb
  514.             mov   [di+xvrb.verb_code], X25APPTERM
  515.             mov   [di+xvrb.version_id], X25_API_VERSION
  516.  
  517.             @X25                                            ; Call the X.25 API
  518.             cmp   ax, X25_OK                               ; check immediate RC
  519.             je    NoImmErr6
  520.             mov   ErrorType, Immediate               ; Indicate immediate error
  521.             jmp   TermErr
  522. NoImmErr6:
  523.             call  SemWait                           ; wait for verb to complete
  524.             mov   di, ofs_xvrb
  525.             mov   ax, [di+xvrb.return_code]
  526.             cmp   ax, X25_OK                              ; check Completion RC
  527.             je    TermGood
  528.             mov   ErrorType, Completion             ; Indicate completion error
  529.             jmp   TermErr
  530. TermErr:
  531.             mov   ErrNum, ax
  532.             @VioWrtTTY TermBadMsg,TermBadlen,0
  533.             @VioWrtTTY crlf,2,0
  534.             call  Error
  535. TermGood:
  536.             @VioWrtTTY TermGoodMsg,TermGoodlen,0
  537.             @VioWrtTTY crlf,2,0
  538.             ret
  539.  
  540. term_app    ENDP
  541. ;=============================================================================
  542. ; Allocate Memory for shared data segment
  543. ;=============================================================================
  544. allocmem    PROC
  545.             @DosAllocSeg segsize, shrdseg, shareable    ; size of 32k, sharable
  546.                                                      ; and allocated to shrdseg
  547.             cmp    ax, 0                                     ; check rc is zero
  548.             je     SubSet                           ; then jump to next command
  549.             mov    ErrNum, ax                            ; else store the error
  550.             mov    ErrorType, DosError                    ; note the error type
  551.             Call   Error                   ; and show that an error has occured
  552. SubSet:
  553.             @DosSubSet shrdseg, initalise, segsize             ; initialise for
  554.                                                                 ; suballocation
  555.             @DosSubAlloc shrdseg,ofs_xvrb, X25VERB_SIZE
  556.             @DosSubAlloc shrdseg,ofs_call_data, X25CALLDATA_SIZE
  557.             @DosSubAlloc shrdseg,ofs_data_data, rcv_buffer_size
  558.             ret
  559.  
  560. allocmem    ENDP
  561.  
  562. ;=============================================================================
  563. ; wait for the verb to complete
  564. ;=============================================================================
  565. SemWait    PROC                       ; for a RAM semaphore we give the address
  566.                                          ; where the semaphore handle is stored
  567.            mov   di, ofs_xvrb
  568.            lea   ax, [di+xvrb.ram_semaphore]                           ; offset
  569.            mov   word ptr SemAddress,ax
  570.            mov   ax, shrdseg                                         ; selector
  571.            mov   word ptr SemAddress+2,ax
  572.            @DosSemWait SemAddress , NoTimeOut
  573.            ret
  574.  
  575. SemWait    ENDP
  576.  
  577. ;=============================================================================
  578. ; Register an Error
  579. ;=============================================================================
  580. Error       PROC
  581.             mov    ax, ErrorType                       ; place error type in AX
  582.             cmp    ax, Immediate                 ; compare with immediate error
  583.             je     ImmErr                      ; If immediate error goto ImmErr
  584.             cmp    ax, DosError                       ; commpare with Dos error
  585.             je     DosErr                            ; If Dos error goto DosErr
  586. CompErr:
  587.             @VioWrtTTY x25DelErrMsg,x25DelErrLen,0 ;indicate error has occurred
  588.             mov    ax, ErrNum                       ; Move error number into AX
  589.             call   WrtDec                            ; Display out error number
  590.             jmp    terminate                                ; terminate program
  591. ImmErr:
  592.             @VioWrtTTY x25ImmErrMsg,x25ImmErrLen,0 ;indicate error has occurred
  593.             mov    ax, ErrNum                       ; Move error number into AX
  594.             call   WrtDec                            ; Display out error number
  595.             jmp    terminate                                ; terminate program
  596. DosErr:
  597.             @VioWrtTTY DosErrMsg,DosErrLen,0      ; indicate error has occurred
  598.             mov    ax, ErrNum                       ; Move error number into AX
  599.             call   WrtDec                            ; Display out error number
  600.                                                             ; terminate program
  601. terminate:  @VioWrtTTY crlf,2,0                 ; carriage return and line feed
  602.             @VioWrtTTY DosTermMsg,DosTermLen,0    ; Display terminating message
  603.             @dosexit       1,1                     ; Exit with return code of 1
  604.             ret
  605.  
  606. Error       ENDP
  607.  
  608. ;=============================================================================
  609. ; convert a hex word to a decimal number
  610. ;=============================================================================
  611. WrtDec      PROC                        ; write the decimal value of a hex word
  612.                                                  ; less than 1000d stored in ax
  613.                                                ; at the current cursor position
  614.             cwd                               ; extends ax into the dx register
  615.             div    hundred                  ; divide the word by word value 100
  616.             mov    hundreds, al               ; quotient in ax, remainder in dx
  617.             add    hundreds, 30h     ; add 30h to make it a printable character
  618.             mov    ax, dx                              ; move remainder into ax
  619.             cwd                               ; extends ax into the dx register
  620.             div    ten                       ; divide the word by word value 10
  621.             mov    tens, al                   ; quotient in ax, remainder in dx
  622.             add    tens, 30h         ; add 30h to make it a printable character
  623.             mov    units, dl                               ; remainder is units
  624.             add    units, 30h        ; add 30h to make it a printable character
  625.             @VioWrtTTY hundreds,1,0                        ; print out hundreds
  626.             @VioWrtTTY tens,1,0                                ; print out tens
  627.             @VioWrtTTY units,1,0                              ; print out units
  628.             ret
  629.  
  630. WrtDec      ENDP
  631.  
  632. x25mxmit    ENDP
  633. code        ENDS
  634.             END    x25mxmit
  635.