home *** CD-ROM | disk | FTP | other *** search
/ World of Shareware - Software Farm 2 / wosw_2.zip / wosw_2 / CPROG / DUMBTERM.ZIP / DUMBTERM.ASM
Assembly Source File  |  1989-03-20  |  16KB  |  635 lines

  1. ;«OF4»«RM76»«FD66»«PL55,60,50»«RHA«OF4»«RM76»«MDBO»
  2.  
  3. PAGE «PN»«MDBO»/«MDNM»«FR»«MDBO»
  4.  
  5. «MDNM»»«RFA«OF4»«RM76»
  6. «LD-»«FR»«MDBO»MORE«MDNM»
  7.  
  8. »
  9. ------------------------------------------------------------------
  10. ;«MDBO»                     DUMBTERM«MDNM»
  11. ; «MDBO»Author:    CJ Dunford«MDNM»
  12. ; «MDBO»Rev.:        09/12/83«MDNM»
  13. ; «MDBO»Source:    DUMBTERM.ASM«MDNM»
  14. ; «MDBO»Object:    DUMBTERM.OBJ«MDNM»
  15. ; «MDBO»Code:        DUMBTERM.EXE«MDNM»
  16. ; «MDBO»O/S:        PCDOS 1.1, 2.0«MDNM»
  17. ;
  18. ; Note that the program assumes that the RS232 port is configured
  19. ; as COM1.  It will have to be modified to use COM2.  Also,
  20. ; the communications parameters are set as 300 baud, 7 data bits,
  21. ; 1 stop bit, even parity.  This can be changed--see the INIT
  22. ; procedure.  DUMBTERM will easily keep up with 1200 baud or more.
  23. ;
  24. ; Assembly/link:
  25. ;   Assemble: MASM dumbterm;
  26. ;   Link:     LINK dumbterm;
  27. ;
  28. ; Execution:
  29. ;   (from DOS prompt): DUMBTERM
  30. ;------------------------------------------------------------------
  31.  
  32. ; * * * * * * * * * * * * * * *
  33. ;   EQUATES & DEFINITIONS
  34. ; * * * * * * * * * * * * * * *
  35.  
  36. ; ----- Define size of buffer
  37. BUFSIZE        equ    4096        ; 4K--can be adjusted
  38.  
  39. ; ----- ASCII codes
  40. LF        equ    0AH        ; Line feed
  41. CR        equ    0DH        ; Carriage return
  42. ESC        equ    1BH        ; Escape
  43.  
  44. ; ----- BIOS calls
  45. RS232           equ    14H        ; RS232 service
  46. kbd_io           equ    16H        ; Keyboard service
  47.  
  48. ; ----- INS8250 ACE registers
  49.  
  50. THR    equ    3F8H        ; Trans    holding    register (write)
  51. RBR    equ    3F8H        ; Receiver buffer register (read)
  52. IER    equ    3F9H        ; Interrupt enable register
  53. LCR    equ    3FBH        ; Line control register.
  54.                 ; Bit 7    of LCR is "DLAB".  DLAB    must
  55.                 ; be zero to access THR, RBR, IER.
  56. MCR    equ    3FCH        ; Modem    control    register
  57. LSR    equ    3FDH        ; Line status register
  58. MSR    equ    3FEH        ; Modem    status register
  59.  
  60.  
  61. ; ----- Comm parameter definition
  62. ; Refer    to IBM Tech Ref, page A-20
  63. ; See proc INIT    for usage
  64.  
  65. commparm record    baud:3,    parity:2, stopbits:1, wordbits:2
  66.  
  67. ; Baud rates
  68. B110        equ    000B
  69. B150        equ    001B
  70. B300        equ    010B
  71. B600        equ    011B
  72. B1200        equ    100B
  73. B2400        equ    101B
  74. B4800        equ    110B
  75. B9600        equ    111B
  76.  
  77. ; Parity
  78. no_parity    equ    00B
  79. odd_parity    equ    01B
  80. even_parity    equ    11B
  81.  
  82. ; Stop bits
  83. stop1        equ    0
  84. stop2        equ    1
  85.  
  86. ; Data bits
  87. data7        equ    10B
  88. data8        equ    11B
  89.  
  90.  
  91. ; * * * * * * * * * * * * * * *
  92. ;    MACROS
  93. ; * * * * * * * * * * * * * * *
  94.  
  95. @bioscall MACRO    call_num, parm
  96. ;; Generates an 'INT call_num', with parm in AH
  97.     IFNB <parm>
  98.       mov ah,parm
  99.     ENDIF
  100.     int call_num
  101.     ENDM
  102.  
  103.  
  104. @doscall MACRO function,parm
  105. ;; Generates a DOS function call with parm in AL
  106.     IFNB <parm>
  107.      mov al,parm
  108.     ENDIF
  109.     @bioscall 21H,function
  110.     endm
  111.  
  112.  
  113. ; * * * * * * * * * * * * * *
  114. ;    DATA & STACK SEGMENTS
  115. ; * * * * * * * * * * * * * *
  116.  
  117. data segment para public 'data'
  118.  
  119. ; ----- The string section
  120. sgreeting    db    '--- ONLINE ---',CR,LF,'$'
  121. sgoodbye    db    CR,LF,'--- OFFLINE ---',CR,LF,'$'
  122. serr1        db    '<R>$'    ; RS232    receive    error
  123. serr2        db    '<S>$'    ; RS232    send error
  124. serr3        db    '<B>$'    ; Receive buffer overflow error
  125.  
  126. ; ----- Flags
  127. brcv_err    db    0    ; Nonzero on RS232 receive error
  128. boverflow    db    0    ; Nonzero on buffer overflow
  129. bdoneflag    db    0    ; Nonzero after ESC from kbd
  130.  
  131. ; ----- Received data buffer and associated pointers
  132. ; >> Buffer is empty if head pointer = tail pointer
  133. wbufhead    dw    buffer    ; Pointer to head of buffer
  134. wbuftail    dw    buffer     ; Pointer to tail of buffer
  135. buffer        db    BUFSIZE dup (?)
  136. bufend        equ $
  137. data ends
  138.  
  139. ; ----- Stack
  140. stack segment para stack 'stack'
  141.     db    256 dup (?)
  142. stack ends
  143.  
  144.  
  145. ; * * * * * * * * * * * * *
  146. ;     PROGRAM MAINLINE
  147. ; * * * * * * * * * * * * *
  148.  
  149. code    segment    para public 'code'
  150.     assume cs:code, ds:data, ss:stack
  151.  
  152. main    proc far
  153.  
  154. ; ----- Initialize
  155.     push ds            ; Set up long ret to DOS
  156.     sub ax,ax
  157.     push ax
  158.     call init        ; Rest of initialization
  159.  
  160. ; ----- Main program loop
  161. M100:
  162.     call buffer_check       ; Check RS232 bfr. Display if not empty
  163.     call kb_check           ; Check kbd. Send to RS232.
  164.     test bdoneflag,0FFH    ; Non-zero if done
  165.     jz M100            ; Loop till ESC received
  166.  
  167. ; ----- ESC received.  Clean up interrupt & exit
  168.     call cleanup        ; Clean    up
  169.     ret            ; Return to DOS
  170. main    endp
  171.  
  172.  
  173. ; * * * * * * * * * * * * * * *
  174. ;     PRIMARY BLOCKS
  175. ; * * * * * * * * * * * * * * *
  176.  
  177. ; -----    INIT ------------------------------
  178. ; Program initialization:
  179. ;   -- Set up RS232
  180. ;   -- Set up vector for RS232 interrupt (INT 0CH)
  181. ;   -- Enable IRQ4
  182. ;   -- Enable RS232 interrupt on data ready
  183. ;
  184. ; NOTE: The communications parameters are established
  185. ; here.  To use other parameters, change the parameters
  186. ; in the 'mov al,commparm' statement below.  See the
  187. ; communications parameters record definition (above)
  188. ; for the correct abbreviations.
  189. ;
  190. ; Examples:
  191. ;   1200,N,8,1:    mov al,commparm <B1200,no_parity,stop1,data8>
  192. ;   4800,O,7,2: mov al,commparm <B4800,odd_parity,stop2,data7>
  193. ; -----------------------------------------
  194.  
  195. init proc near
  196.  
  197. ; ----- Initialize RS232: 300,8,N,1
  198.     mov dx,0            ; COM1
  199.     mov al,commparm    <B300,no_parity,stop1,data8>
  200.     @bioscall RS232,0
  201.  
  202. ; ----- Set up INT x'0C' for IRQ4
  203.     cli                ; Interrupts off during    setup
  204.     push ds                ; Save DS
  205.     mov dx,offset ISR        ; Point    to RS232 ISR in    DS:DX
  206.     push cs
  207.     pop ds
  208.     @doscall 25H,0CH        ; Set int vctr for IRQ4
  209.     pop ds                ; Restore DS
  210.  
  211. ; ----- Enable IRQ4 on 8259 interrupt controller
  212.     in al,21H            ; Get current masks
  213.     and al,11101111B        ; Reset    IRQ4 mask
  214.     out 21H,al            ; And restore to IMR
  215.  
  216. ; ----- Enable 8250 data ready interrupt
  217.     mov dx,LCR            ; DX ==> LCR
  218.     in al,dx                        ; Reset DLAB for IER access
  219.     and al,01111111B
  220.     out dx,al
  221.     mov dx,IER            ; Address IER
  222.     mov al,00000001B        ; Enable 'data-ready' interrupt
  223.     out dx,al
  224.  
  225. ; ----- Enable OUT2 on 8250
  226.     mov dx,MCR             ; Address MCR
  227.     mov al,00001000B        ; Enable OUT2
  228.     out dx,al
  229.     sti
  230.  
  231. ; ----- Display greeting & return
  232.     mov ax,data            ; Establish data seg address
  233.     mov ds,ax
  234.     mov dx,offset sgreeting        ; Point to greeting
  235.     call strdisp            ; Display it
  236.     ret
  237. init endp
  238.  
  239.  
  240. ; ---- BUFFER_CHECK -----------------------
  241. ; RS232 buffer check
  242. ;
  243. ; This block checks the received data buffer.
  244. ; It functions as follows:
  245. ;
  246. ; IF the RS232 input buffer is not empty
  247. ;    Get the first character
  248. ;    Display the character
  249. ;    Update buffer pointer
  250. ; IF the RS232 receive error flag is nonzero
  251. ;    Display an error indicator
  252. ; IF the buffer overflow flag is nonzero
  253. ;    Display an error indicator
  254. ;
  255. ; Entry:
  256. ;  No requirement
  257. ; Exit:
  258. ;  AX, BX, DX destroyed
  259. ; -----------------------------------------
  260.  
  261. buffer_check proc near
  262.  
  263. ; ----- Check buffer status
  264.     mov bx,wbufhead            ; Buffer head pointer
  265.     cmp bx,wbuftail            ; Buffer empty if head = tail
  266.     je BC100            ; Jump if empty
  267.  
  268. ; ----- Something in buffer--get 1st char, fix pointers
  269.     mov al,[bx]            ; Get the char
  270.     call incptr            ; Bump buffer head pointer
  271.     mov wbufhead,bx
  272.  
  273. ; ----- Display character received.  Filter CR/LF
  274.     cmp al,LF            ; Is it a line feed?
  275.     je BC100            ; Skip display if yes
  276.     call chdisp            ; Display if no
  277.     cmp al,CR            ; Is it a CR?
  278.     jne BC100             ; Jump if not
  279.     mov al,LF            ; Send LF if yes
  280.     call chdisp
  281.  
  282. ; ----- Test RS232 receive status; display errors
  283. BC100:
  284.     test brcv_err,0FFH        ; Flag nonzero if errors
  285.     jz BC200            ; Jump if no errors
  286.     mov dx,offset serr1        ; Point to error msg
  287.     call strdisp
  288.     mov brcv_err,0            ; Clear error flag
  289.  
  290. ; ----- Test for buffer overflow; display errors
  291. BC200:
  292.     test boverflow,0FFH
  293.     jz BC300            ; Z if no overflow
  294.     mov boverflow,0            ; Clear the flag
  295.     mov dx,offset serr3        ; Point to error msg
  296.     call strdisp            ; And display
  297.  
  298. BC300:
  299.     ret
  300. buffer_check endp
  301.  
  302. ; ----- KB_CHECK --------------------------
  303. ; Check keyboard.  Functions as follows:
  304. ;
  305. ; Check the keyboard status
  306. ; IF a character is available
  307. ;   IF the character is ESC
  308. ;      set the 'done' flag
  309. ;   ELSE
  310. ;      send it to RS232 and watch for errors
  311. ;
  312. ; Note that this routine does not echo the KB characters
  313. ; to the display.   Display occurs only when the characters
  314. ; are echoed back by the remote terminal.
  315. ;
  316. ; Entry:
  317. ;  No requirement
  318. ; Exit:
  319. ;  AX, DX destroyed
  320. ; -----------------------------------------
  321.  
  322. kb_check proc near
  323.  
  324. ; -----    Poll keyboard, check chars received
  325.     call kb_poll                    ; Poll the keyboard
  326.     jz KBC900            ; Kbd clear, exit
  327.     cmp al,ESC            ; Escape?
  328.     jne KBC100            ; No, continue
  329.     mov bdoneflag,0FFH        ; Yes, set termination flag
  330.     jmp short KBC900
  331.  
  332. ; ----- Send the received char, watch for errors
  333. KBC100:
  334.     call RS232_out            ; Send it
  335.     test ah,80H            ; Time out?
  336.     jz KBC900            ; No, sent OK
  337.     mov dx,offset serr2        ; Point to error msg
  338.     call strdisp            ; And display it
  339.  
  340. KBC900:
  341.     ret
  342. kb_check endp
  343.  
  344.  
  345. ; -----    ISR -------------------------------
  346. ; This is the RS232 interrupt service routine.  It
  347. ; is entered whenever the RS232 port interrupts on a
  348. ; 'data ready' condition.  The routine simply reads
  349. ; the data from the asynch chip and stuffs it in the
  350. ; buffer.  Note that the process of reading the
  351. ; received data register in the 8250 clears IRQ4.
  352. ; However, the 8259 must be told specifically that the
  353. ; interrupt service is complete.
  354. ;
  355. ; This replaces the function 2 of BIOS interrupt 14H
  356. ; (receive a character over the comm line).  Since
  357. ; it cannot return errors in a register, it puts the
  358. ; error marker in memory at 'brcv_err'.  The error
  359. ; flag is 'sticky'--a successful read will NOT clear a
  360. ; prior error indication.  This allows the program
  361. ; mainline to examine the error status at its
  362. ; leisure.  Error bits are the same as in RS232OUT,
  363. ; above, except that ONLY the error bits are set,
  364. ; and bit 7 is not used (always 0).  In other words,
  365. ; brcv_err is nonzero only on an error.  Timeout
  366. ; errors are not possible here.
  367. ;
  368. ; The ISR will set the overflow flag if the buffer
  369. ; should overflow.  Shouldn't happen.
  370. ; -----------------------------------------
  371.  
  372. ISR    proc near
  373.     sti            ; Allow    other interrupts
  374.     push ax            ; Save all regs used
  375.     push bx
  376.     push dx
  377.     push si
  378.     push ds
  379.  
  380. ; ----- Establish data addressability
  381.     mov ax,data
  382.     mov ds,ax
  383.  
  384. ; ----- Get error bits
  385.     mov dx,LSR        ; Base address of RS232
  386.     in al,dx        ; Get status
  387.     and al,00011110B    ; Mask non-error bits
  388.     jz ISR010        ; Skip error set if OK
  389.     mov brcv_err,al        ; Set error indicator
  390.  
  391. ; ----- Get incoming character and buffer it
  392. ISR010:
  393.     mov dx,RBR        ; Receiver buffer
  394.     in al,dx        ; Get input character
  395.     mov bx,wbuftail        ; Buffer input pointer
  396.     mov si,bx        ; Save pointer b4 increment
  397.     call incptr        ; Bump input pointer
  398.     cmp bx,wbufhead        ; Overflow if head = tail
  399.     je ISR020        ; Overflow
  400.     mov [si],al        ; No overflow, save char in buffer
  401.     mov wbuftail,bx        ; And new input    pointer
  402.     jmp short ISR999
  403. ISR020:
  404.     mov boverflow,0FFH    ; Set overflow flag
  405.  
  406. ; ----- Signal end of interrupt to 8259
  407. ISR999:
  408.     cli
  409.     mov al,20H        ; Non-specific EOI
  410.     out 20H,al        ; Send it
  411.  
  412. ; ----- Restore regs & return.  IRET reenables interrupts
  413.     pop ds
  414.     pop si
  415.     pop dx
  416.     pop bx
  417.     pop ax
  418.     iret
  419. ISR    endp
  420.  
  421.  
  422. ; ----- CLEANUP --------------------------
  423. ; End of program housekeeping
  424. ;   -- Disable IRQ4
  425. ;   -- Disable 8250 interrupts
  426. ;   -- Disable OUT2
  427. ;   -- Display offline message
  428. ; ----------------------------------------
  429.  
  430. cleanup    proc near
  431.  
  432. ; ----- Disable IRQ4 on 8259
  433.     cli
  434.     in al,21H            ; IMR
  435.     or al,00010000B            ; Mask bit 4--IRQ4
  436.     out 21H,al
  437.  
  438. ; ----- Disable 8250 data ready interrupt
  439.     mov dx,LCR            ; DX ==> LCR
  440.     in al,dx                        ; Reset DLAB for IER access
  441.     and al,01111111B
  442.     out dx,al
  443.     mov dx,IER            ; Address IER
  444.     mov al,0            ; Disable all 8250 interrupts
  445.     out dx,al
  446.  
  447. ; ----- Disable OUT2 on 8250
  448.     mov dx,MCR             ; Address MCR
  449.     mov al,0            ; Disable OUT2
  450.     out dx,al
  451.     sti
  452.  
  453. ; ----- Display bye-bye
  454.     mov dx,offset sgoodbye
  455.     call strdisp
  456.     ret
  457. cleanup    endp
  458.  
  459.  
  460. ; * * * * * * * * * * * * * * * *
  461. ;    I/O & GENERAL SUBROUTINES
  462. ; * * * * * * * * * * * * * * * *
  463.  
  464. ; -----    KB_POLL ---------------------------
  465. ; Set/reset Z flag on keyboard buffer status.
  466. ;
  467. ; Entry:
  468. ;  No requirements
  469. ; Exit:
  470. ;  Z = 1 if nothing available
  471. ;  Z = 0 if char available from kbd
  472. ;  IF Z = 0
  473. ;    AL = char
  474. ;    AH = scan code
  475. ; Other regs preserved
  476. ; -----------------------------------------
  477.  
  478. kb_poll proc near
  479.     @bioscall kbd_io,1    ; Poll KB. Sets    Z flag if KB bfr empty
  480.     jz KB999        ; Nothing there
  481.     pushf                   ; Save flag status
  482.     @bioscall kbd_io,0    ; Something there; get it
  483.     popf
  484. KB999:
  485.     ret
  486. kb_poll endp
  487.  
  488.  
  489.  
  490. ; --- RS232_out --------------------------
  491. ; RS232 output routine
  492. ;
  493. ; This routine sends one character to the RS232 port.
  494. ; It replaces function 1 of BIOS int 14H.  This is
  495. ; necessary because BIOS will disable the RS232
  496. ; interrupt (by disabling OUT2) every time it is
  497. ; called.
  498. ;
  499. ; Entry:
  500. ;  AL = character to be transmitted
  501. ; Exit:
  502. ;  AH = send status
  503. ;    Bit 7 = 1 if RS232 timeout occurred
  504. ;    IF bit 7 = 0
  505. ;       bit 6: trans shift register empty
  506. ;       bit 5: trans holding register empty
  507. ;       bit 4: break detect
  508. ;       bit 3: framing error
  509. ;       bit 2: parity error
  510. ;       bit 1: overrun error
  511. ;       bit 0: data ready
  512. ;  Other regs preserved
  513. ; ----------------------------------------
  514.  
  515. RS232_out proc near
  516.     push bx            ; Save regs used
  517.     push cx
  518.     push dx
  519.  
  520. ; ----- Set up RS232
  521.     mov bl,al        ; Save char to BL temporarily
  522.     mov dx,MCR        ; Modem    Control    Register
  523.     mov al,00001011B    ; OUT2,    DTR, RTS
  524.     out dx,al
  525.     sub cx,cx        ; Initialize timeout count
  526.     mov dx,MSR        ; Modem    Status Register
  527.  
  528. ; ----- Wait for DSR
  529. RS100:
  530.     in al,dx
  531.     test al,20H        ; Data set ready?
  532.     jnz RS150        ; Yes
  533.     loop RS100        ; No, retry till timeout
  534.     mov ah,80H        ; Set timeout
  535.     jmp short RSXIT        ; And quit
  536.  
  537. ; ----- Wait for CTS
  538. RS150:
  539.     sub cx,cx        ; Another timeout count
  540. RS200:
  541.     in al,dx
  542.     test al,10H        ; Clear    to send?
  543.     jnz RS250        ; Yes
  544.     loop RS200        ; No, loop till    timeout
  545.     mov ah,80H        ; Timeout, set flag
  546.     jmp short RSXIT        ; And quit
  547.  
  548. ; ----- Wait for THRE
  549. RS250:
  550.     mov dx,LSR        ; Line Status Register
  551.     sub cx,cx        ; Yet another timeout count
  552. RS300:
  553.     in al,dx        ; LSR status
  554.     test al,20H        ; Transmit holding reg empty?
  555.     jnz RS350        ; Yes
  556.     loop RS300        ; No, loop till    timeout
  557.     mov ah,80H        ; Timeout, set flag
  558.     jmp short RSXIT
  559.  
  560. ; ----- Get line status, send char
  561. RS350:
  562.     mov ah,al        ; Get line status for return
  563.     and ah,01111111B    ; Mask out bit 7
  564.     mov al,bl        ; Restore char to AL
  565.     mov dx,THR        ; Trasnmit holding register
  566.     out dx,al        ; Output it to RS232
  567. RSXIT:
  568.     pop dx
  569.     pop cx
  570.     pop bx
  571.     ret
  572. RS232_out endp
  573.  
  574.  
  575.  
  576. ; ----- CHDISP ----------------------------
  577. ; Display the character in AL on the CRT
  578. ; Entry:
  579. ;  AL = char
  580. ; Exit:
  581. ;  All regs restored
  582. ; -----------------------------------------
  583.  
  584. chdisp proc near
  585.     push ax
  586.     push dx
  587.     mov dl,al
  588.     @doscall 2
  589.     pop dx
  590.     pop ax
  591.     ret
  592. chdisp endp
  593.  
  594.  
  595.  
  596. ; ----- STRDISP ---------------------------
  597. ; Display the string at DS:DX on the CRT
  598. ; Entry:
  599. ;  DS:DX ==> string
  600. ; Exit:
  601. ;  All regs restored
  602. ; -----------------------------------------
  603.  
  604. strdisp proc near
  605.     push ax
  606.     @doscall 9
  607.     pop ax
  608.     ret
  609. strdisp endp
  610.  
  611.  
  612.  
  613. ; ----- INCPTR ----------------------------
  614. ; Increment the buffer pointer in reg BX.
  615. ; If the pointer goes beyond the end of the
  616. ; buffer, wrap around to start.
  617. ;
  618. ; Entry:
  619. ;  BX = buffer pointer
  620. ; Exit:
  621. ;  BX = advanced buffer pointer
  622. ;  Other regs restored
  623. ; -----------------------------------------
  624.  
  625. incptr proc near
  626.     inc bx                ; Bump pointer
  627.     cmp bx,offset bufend        ; Past end?
  628.     jne IP100            ; Jump if not
  629.     mov bx,offset buffer            ; Else point to start
  630. IP100:
  631.     ret
  632. incptr    endp
  633. code ends
  634.     end main
  635.