home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library 1.3 / Microsoft-Programers-Library-v1.3.iso / sampcode / advos2 / ch12 / dumbterm.asm < prev    next >
Encoding:
Assembly Source File  |  1988-12-12  |  14.5 KB  |  416 lines

  1.     title    DUMBTERM -- OS/2 Terminal Program
  2.         page    55,132
  3.         .286
  4.  
  5. ;
  6. ; DUMBTERM.ASM
  7. ;
  8. ; A simple multithreaded OS/2 terminal program that exchanges
  9. ; characters between the console and the serial port.
  10. ;
  11. ; Communication parameters for COM1 are set at 2400 baud,
  12. ; 8 data bits, no parity, and 1 stop bit.
  13. ;
  14. ; Assemble with:  C> masm dumbterm.asm;
  15. ; Link with:  C> link dumbterm,,,os2,dumbterm
  16. ;
  17. ; Usage is:  C> dumbterm
  18. ;
  19. ; Press Alt-X to terminate the program.
  20. ;
  21. ; Copyright (C) 1988 Ray Duncan
  22. ;
  23.  
  24. cr      equ     0dh             ; ASCII carriage return
  25. lf    equ    0ah        ; ASCII linefeed
  26.  
  27. kwait   equ     0               ; KbdCharIn parameters
  28. knowait equ     1
  29.  
  30. stksize equ     2048            ; stack size for threads
  31.  
  32. exitkey equ     2dh             ; Alt-X key is exit signal
  33.  
  34.                                 ; COM port configuration
  35. com1    equ    1        ; nonzero if using COM1
  36. com2    equ    0        ; nonzero if using COM2
  37. com3    equ    0        ; nonzero if using COM3
  38. baud    equ     2400            ; baud rate for COM port
  39. parity    equ    0        ; 0=N, 1=O, 2=E, 3=M, 4=S
  40. databit equ     8               ; 5-8
  41. stopbit equ    0        ; 0=1, 1=1.5, 2=2
  42.  
  43.         extrn   DosAllocSeg:far ; OS/2 API functions
  44.         extrn   DosClose:far    
  45.         extrn   DosCreateThread:far
  46.         extrn   DosDevIOCtl:far
  47.         extrn   DosExit:far
  48.         extrn   DosOpen:far
  49.         extrn   DosRead:far
  50.         extrn   DosSemClear:far
  51.         extrn   DosSemSet:far
  52.         extrn   DosSemWait:far
  53.         extrn   DosSuspendThread:far
  54.         extrn   DosWrite:far
  55.         extrn   KbdCharIn:far
  56.         extrn   KbdGetStatus:far
  57.         extrn   KbdSetStatus:far
  58.         extrn   VioWrtTTY:far
  59.  
  60. DGROUP  group   _DATA
  61.  
  62. _DATA   segment word public 'DATA'
  63.  
  64. cname   label   byte            ; COM port logical name
  65.         if      com1
  66.         db      'COM1',0        ; COM1 device
  67.         endif
  68.         if      com2
  69.         db      'COM2',0        ; COM2 device
  70.         endif
  71.         if      com3
  72.         db      'COM3',0        ; COM3 device
  73.         endif
  74.  
  75. f41info dw      baud            ; baud rate
  76.  
  77. f42info db      databit         ; data bits
  78.         db      parity          ; parity 
  79.         db      stopbit         ; stop bits
  80.  
  81. kbdinfo db      0               ; character code
  82.         db      0               ; scan code
  83.         db      0               ; status flags
  84.         db      0               ; reserved
  85.         dw      0               ; shift state
  86.     dd    0        ; timestamp
  87.  
  88. kbdstat dw      10              ; length of structure
  89.         dw      0               ; keyboard state flags
  90.         db      0,0             ; logical end-of-line
  91.         dw      0               ; interim character flags
  92.         dw      0               ; shift state
  93.  
  94. exitsem dd      0               ; exit semaphore
  95.  
  96. chandle dw      0               ; receives COM device handle
  97. action  dw      0               ; receives DosOpen action 
  98. sel     dw      0               ; receives selector
  99. rlen    dw      0               ; receives bytes read count
  100. wlen    dw      0               ; receives bytes written count
  101. cinID   dw      0               ; COM input thread ID
  102. coutID  dw      0               ; COM output thread ID
  103. inchar    db    0        ; input character from COM port
  104.  
  105. msg1    db      cr,lf
  106.         db      "Can't open COM device."
  107.         db      cr,lf
  108. msg1_len equ    $-msg1
  109.  
  110. msg2    db      cr,lf
  111.         db      "Can't set baud rate."
  112.         db      cr,lf
  113. msg2_len equ    $-msg2
  114.  
  115. msg3    db      cr,lf
  116.         db      "Can't configure COM port."
  117.         db      cr,lf
  118. msg3_len equ    $-msg3
  119.  
  120. msg4    db      cr,lf
  121.         db      "Memory allocation failure."
  122.         db      cr,lf
  123. msg4_len equ    $-msg4
  124.  
  125. msg5    db      cr,lf
  126.         db      "Can't create COM input thread."
  127.         db      cr,lf
  128. msg5_len equ    $-msg5
  129.  
  130. msg6    db      cr,lf
  131.         db      "Can't create COM output thread."
  132.         db      cr,lf
  133. msg6_len equ    $-msg6
  134.  
  135. msg7    db      cr,lf
  136.         db      "Communicating..."
  137.         db      cr,lf
  138. msg7_len equ    $-msg7
  139.  
  140. msg8    db      cr,lf
  141.         db      "Terminating..."
  142.         db      cr,lf
  143. msg8_len equ    $-msg8
  144.  
  145. _DATA   ends    
  146.  
  147.  
  148. _TEXT   segment word public 'CODE'
  149.  
  150.         assume  cs:_TEXT,ds:DGROUP
  151.  
  152. main    proc    far             ; entry point from OS/2
  153.                                         
  154.                                 ; open COM port...
  155.         push    ds              ; device name address
  156.         push    offset DGROUP:cname
  157.         push    ds              ; receives device handle
  158.         push    offset DGROUP:chandle
  159.         push    ds              ; receives action
  160.         push    offset DGROUP:action
  161.         push    0               ; initial allocation (N/A)
  162.         push    0
  163.         push    0               ; attribute (N/A)
  164.         push    1               ; open flag: fail if device
  165.                                 ;            does not exist
  166.         push    12h             ; open mode: read/write,
  167.                 ;         deny-all
  168.         push    0               ; DWORD reserved
  169.         push    0
  170.         call    DosOpen         ; transfer to OS/2
  171.         or      ax,ax           ; was function successful?
  172.         jz      main1           ; yes, jump
  173.  
  174.         mov     cx,msg1_len     ; no, display error message
  175.         mov     dx,offset DGROUP:msg1
  176.         jmp     main9           ; and exit
  177.  
  178. main1:                          ; set baud rate...
  179.         push    0               ; data buffer address
  180.         push    0
  181.         push    ds              ; parameter buffer address
  182.         push    offset DGROUP:f41info
  183.         push    41h             ; function number
  184.         push    1               ; category number
  185.         push    chandle         ; COM device handle
  186.         call    DosDevIOCtl     ; transfer to OS/2
  187.         or      ax,ax           ; was function successful?
  188.         jz      main2           ; yes, jump
  189.  
  190.         mov     cx,msg2_len     ; no, display error message
  191.         mov     dx,offset DGROUP:msg2
  192.         jmp     main9           ; and exit
  193.  
  194. main2:                          ; configure parity, stop bits,
  195.                                 ; and character length...
  196.         push    0               ; data buffer address
  197.         push    0
  198.         push    ds              ; parameter buffer address
  199.         push    offset DGROUP:f42info
  200.         push    42h             ; function number
  201.         push    1               ; category number
  202.         push    chandle         ; COM device handle
  203.         call    DosDevIOCtl     ; transfer to OS/2
  204.         or      ax,ax           ; was function successful?
  205.         jz      main3           ; yes, jump
  206.  
  207.         mov     cx,msg3_len     ; no, display error message
  208.         mov     dx,offset DGROUP:msg3
  209.         jmp     main9           ; and exit
  210.  
  211. main3:                          ; put keyboard in binary mode
  212.                                 ; with echo off...
  213.  
  214.                                 ; get keyboard state
  215.         push    ds              ; address of info structure
  216.         push    offset DGROUP:kbdstat
  217.         push    0               ; default keyboard handle
  218.         call    KbdGetStatus    ; transfer to OS/2
  219.  
  220.                                 ; set binary mode, no echo
  221.         and     word ptr kbdstat+2,0fff0h
  222.         or      word ptr kbdstat+2,6
  223.  
  224.                                 ; set keyboard state
  225.         push    ds              ; address of info structure
  226.         push    offset DGROUP:kbdstat
  227.         push    0               ; default keyboard handle
  228.         call    KbdSetStatus    ; transfer to OS/2
  229.  
  230.         push    ds              ; set exit semaphore
  231.         push    offset DGROUP:exitsem
  232.         call    DosSemSet       ; transfer to OS/2
  233.  
  234.                                 ; allocate thread stack
  235.         push    stksize         ; stack size in bytes
  236.         push    ds              ; receives new selector
  237.         push    offset DGROUP:sel
  238.         push    0               ; not sharable/discardable
  239.         call    DosAllocSeg     ; transfer to OS/2
  240.         or      ax,ax           ; was function successful?
  241.         jz      main4           ; yes, jump
  242.  
  243.         mov     cx,msg4_len     ; no, display error message
  244.         mov     dx,offset DGROUP:msg4
  245.         jmp     main9           ; and exit
  246.  
  247. main4:                          ; create COM input thread
  248.         push    cs              ; thread entry point
  249.         push    offset _TEXT:comin
  250.         push    ds              ; receives thread ID    
  251.         push    offset DGROUP:cinID
  252.         push    sel             ; address of stack base
  253.         push    stksize
  254.         call    DosCreateThread ; transfer to OS/2
  255.         or      ax,ax           ; was function successful?
  256.         jz      main5           ; yes, jump
  257.  
  258.         mov     cx,msg5_len     ; no, display error message
  259.         mov     dx,offset DGROUP:msg5
  260.         jmp     main9           ; and exit
  261.  
  262. main5:                          ; allocate thread stack
  263.         push    stksize         ; stack size in bytes
  264.         push    ds              ; receives new selector
  265.         push    offset DGROUP:sel
  266.         push    0               ; not sharable/discardable
  267.         call    DosAllocSeg     ; transfer to OS/2
  268.         or      ax,ax           ; was function successful?
  269.         jz      main6           ; yes, jump
  270.  
  271.         mov     cx,msg4_len     ; no, display error message
  272.         mov     dx,offset DGROUP:msg4
  273.         jmp     main9           ; and exit
  274.  
  275. main6:                          ; create COM output thread
  276.         push    cs              ; thread entry point
  277.         push    offset _TEXT:comout
  278.         push    ds              ; receives thread ID    
  279.         push    offset DGROUP:coutID
  280.         push    sel             ; address of stack base
  281.         push    stksize
  282.         call    DosCreateThread ; transfer to OS/2
  283.         or      ax,ax           ; was function successful?
  284.         jz      main7           ; yes, jump
  285.  
  286.         mov     cx,msg6_len     ; no, display error message
  287.         mov     dx,offset DGROUP:msg6
  288.         jmp     main9           ; and exit
  289.  
  290. main7:                          ; display "Communicating..."
  291.         push    ds              ; message address
  292.         push    offset DGROUP:msg7
  293.         push    msg7_len        ; message length
  294.         push    0               ; default video handle
  295.         call    VioWrtTTY       ; transfer to OS/2
  296.         
  297.                                 ; wait for exit signal
  298.         push    ds              ; semaphore handle
  299.         push    offset DGROUP:exitsem
  300.         push    -1              ; wait indefinitely
  301.         push    -1
  302.         call    DosSemWait      ; transfer to OS/2
  303.  
  304.                                 ; suspend COM input thread
  305.         push    cinID           ; thread ID
  306.         call    DosSuspendThread ; transfer to OS/2
  307.  
  308.                                 ; suspend COM output thread
  309.         push    coutID          ; thread ID
  310.         call    DosSuspendThread ; transfer to OS/2
  311.         
  312. main8:                ; display "Terminating"...
  313.         push    ds              ; message address
  314.         push    offset DGROUP:msg8
  315.         push    msg8_len        ; message length
  316.         push    0               ; default video handle
  317.         call    VioWrtTTY       ; transfer to OS/2
  318.  
  319.                                 ; final exit to OS/2...
  320.         push    1               ; terminate all threads
  321.     push    0        ; return code = 0 (success)
  322.         call    DosExit         ; transfer to OS/2
  323.  
  324. main9:                          ; display error message...
  325.                                 ; DS:DX = msg, CX = length
  326.         push    ds              ; address of message
  327.         push    dx
  328.         push    cx              ; length of message
  329.         push    0               ; default video handle
  330.         call    VioWrtTTY       ; transfer to OS/2
  331.  
  332.                                 ; final exit to OS/2...
  333.         push    1               ; terminate all threads
  334.     push    1        ; return code = 1 (error)
  335.         call    DosExit         ; transfer to OS/2
  336.         
  337. main    endp
  338.  
  339.  
  340. ; COM input thread: Reads characters one at a time
  341. ; from the COM port, and writes them to the display.
  342.  
  343. comin   proc    far
  344.  
  345.                 ; read character from COM...
  346.         push    chandle         ; COM device handle
  347.         push    ds              ; receives COM data
  348.         push    offset DGROUP:inchar
  349.         push    1               ; length to read
  350.         push    ds              ; receives read count
  351.         push    offset DGROUP:rlen
  352.         call    DosRead         ; transfer to OS/2
  353.  
  354.                 ; send character to display...
  355.         push    ds              ; address of character
  356.         push    offset DGROUP:inchar
  357.         push    1               ; length to write
  358.         push    0               ; default video handle
  359.         call    VioWrtTTY       ; transfer to OS/2
  360.  
  361.     jmp    comin        ; wait for next character
  362.  
  363. comin   endp
  364.  
  365.  
  366. ; COM output thread: Reads characters from the keyboard
  367. ; in raw mode and sends them to the COM port.  If the
  368. ; exit key is detected, the main thread is signaled to
  369. ; clean up and terminate the process.
  370.  
  371. comout  proc    far
  372.  
  373.                 ; read keyboard character...
  374.         push    ds              ; receives keyboard data
  375.         push    offset DGROUP:kbdinfo
  376.         push    kwait           ; wait if necessary
  377.         push    0               ; default keyboard handle
  378.         call    KbdCharIn       ; transfer to OS/2
  379.  
  380.         mov     cx,1            ; assume writing one byte
  381.  
  382.         cmp     kbdinfo,0       ; check for extended key
  383.         jz      comout1         ; jump, extended key
  384.         cmp     kbdinfo,0e0h
  385.         jnz     comout2         ; jump, not extended key
  386.  
  387. comout1:                        ; extended key detected
  388.         mov     cx,2            ; must write 2 bytes
  389.  
  390.                                 ; check for exit key
  391.         cmp     kbdinfo+1,exitkey
  392.         jnz     comout2         ; not exit key, jump
  393.  
  394.                                 ; clear exit semaphore...
  395.         push    ds              ; semaphore address
  396.         push    offset DGROUP:exitsem
  397.         call    DosSemClear     ; transfer to OS/2
  398.         jmp     comout          ; discard exit key
  399.  
  400. comout2:            ; send character to COM port...
  401.         push    chandle         ; COM device handle
  402.         push    ds              ; address of character
  403.         push    offset DGROUP:kbdinfo
  404.         push    cx              ; length to write
  405.         push    ds              ; receives write count
  406.         push    offset DGROUP:wlen
  407.         call    DosWrite        ; transfer to OS/2
  408.  
  409.         jmp     comout          ; wait for next key
  410.  
  411. comout  endp
  412.  
  413. _TEXT   ends
  414.  
  415.         end     main
  416.