home *** CD-ROM | disk | FTP | other *** search
- ;«OF4»«RM76»«FD66»«PL55,60,50»«RHA«OF4»«RM76»«MDBO»
-
- PAGE «PN»«MDBO»/«MDNM»«FR»«MDBO»
-
- «MDNM»»«RFA«OF4»«RM76»
- «LD-»«FR»«MDBO»MORE«MDNM»
-
- »
- ------------------------------------------------------------------
- ;«MDBO» DUMBTERM«MDNM»
- ; «MDBO»Author: CJ Dunford«MDNM»
- ; «MDBO»Rev.: 09/12/83«MDNM»
- ; «MDBO»Source: DUMBTERM.ASM«MDNM»
- ; «MDBO»Object: DUMBTERM.OBJ«MDNM»
- ; «MDBO»Code: DUMBTERM.EXE«MDNM»
- ; «MDBO»O/S: PCDOS 1.1, 2.0«MDNM»
- ;
- ; Note that the program assumes that the RS232 port is configured
- ; as COM1. It will have to be modified to use COM2. Also,
- ; the communications parameters are set as 300 baud, 7 data bits,
- ; 1 stop bit, even parity. This can be changed--see the INIT
- ; procedure. DUMBTERM will easily keep up with 1200 baud or more.
- ;
- ; Assembly/link:
- ; Assemble: MASM dumbterm;
- ; Link: LINK dumbterm;
- ;
- ; Execution:
- ; (from DOS prompt): DUMBTERM
- ;------------------------------------------------------------------
-
- ; * * * * * * * * * * * * * * *
- ; EQUATES & DEFINITIONS
- ; * * * * * * * * * * * * * * *
-
- ; ----- Define size of buffer
- BUFSIZE equ 4096 ; 4K--can be adjusted
-
- ; ----- ASCII codes
- LF equ 0AH ; Line feed
- CR equ 0DH ; Carriage return
- ESC equ 1BH ; Escape
-
- ; ----- BIOS calls
- RS232 equ 14H ; RS232 service
- kbd_io equ 16H ; Keyboard service
-
- ; ----- INS8250 ACE registers
-
- THR equ 3F8H ; Trans holding register (write)
- RBR equ 3F8H ; Receiver buffer register (read)
- IER equ 3F9H ; Interrupt enable register
- LCR equ 3FBH ; Line control register.
- ; Bit 7 of LCR is "DLAB". DLAB must
- ; be zero to access THR, RBR, IER.
- MCR equ 3FCH ; Modem control register
- LSR equ 3FDH ; Line status register
- MSR equ 3FEH ; Modem status register
-
-
- ; ----- Comm parameter definition
- ; Refer to IBM Tech Ref, page A-20
- ; See proc INIT for usage
-
- commparm record baud:3, parity:2, stopbits:1, wordbits:2
-
- ; Baud rates
- B110 equ 000B
- B150 equ 001B
- B300 equ 010B
- B600 equ 011B
- B1200 equ 100B
- B2400 equ 101B
- B4800 equ 110B
- B9600 equ 111B
-
- ; Parity
- no_parity equ 00B
- odd_parity equ 01B
- even_parity equ 11B
-
- ; Stop bits
- stop1 equ 0
- stop2 equ 1
-
- ; Data bits
- data7 equ 10B
- data8 equ 11B
-
-
- ; * * * * * * * * * * * * * * *
- ; MACROS
- ; * * * * * * * * * * * * * * *
-
- @bioscall MACRO call_num, parm
- ;; Generates an 'INT call_num', with parm in AH
- IFNB <parm>
- mov ah,parm
- ENDIF
- int call_num
- ENDM
-
-
- @doscall MACRO function,parm
- ;; Generates a DOS function call with parm in AL
- IFNB <parm>
- mov al,parm
- ENDIF
- @bioscall 21H,function
- endm
-
-
- ; * * * * * * * * * * * * * *
- ; DATA & STACK SEGMENTS
- ; * * * * * * * * * * * * * *
-
- data segment para public 'data'
-
- ; ----- The string section
- sgreeting db '--- ONLINE ---',CR,LF,'$'
- sgoodbye db CR,LF,'--- OFFLINE ---',CR,LF,'$'
- serr1 db '<R>$' ; RS232 receive error
- serr2 db '<S>$' ; RS232 send error
- serr3 db '<B>$' ; Receive buffer overflow error
-
- ; ----- Flags
- brcv_err db 0 ; Nonzero on RS232 receive error
- boverflow db 0 ; Nonzero on buffer overflow
- bdoneflag db 0 ; Nonzero after ESC from kbd
-
- ; ----- Received data buffer and associated pointers
- ; >> Buffer is empty if head pointer = tail pointer
- wbufhead dw buffer ; Pointer to head of buffer
- wbuftail dw buffer ; Pointer to tail of buffer
- buffer db BUFSIZE dup (?)
- bufend equ $
- data ends
-
- ; ----- Stack
- stack segment para stack 'stack'
- db 256 dup (?)
- stack ends
-
-
- ; * * * * * * * * * * * * *
- ; PROGRAM MAINLINE
- ; * * * * * * * * * * * * *
-
- code segment para public 'code'
- assume cs:code, ds:data, ss:stack
-
- main proc far
-
- ; ----- Initialize
- push ds ; Set up long ret to DOS
- sub ax,ax
- push ax
- call init ; Rest of initialization
-
- ; ----- Main program loop
- M100:
- call buffer_check ; Check RS232 bfr. Display if not empty
- call kb_check ; Check kbd. Send to RS232.
- test bdoneflag,0FFH ; Non-zero if done
- jz M100 ; Loop till ESC received
-
- ; ----- ESC received. Clean up interrupt & exit
- call cleanup ; Clean up
- ret ; Return to DOS
- main endp
-
-
- ; * * * * * * * * * * * * * * *
- ; PRIMARY BLOCKS
- ; * * * * * * * * * * * * * * *
-
- ; ----- INIT ------------------------------
- ; Program initialization:
- ; -- Set up RS232
- ; -- Set up vector for RS232 interrupt (INT 0CH)
- ; -- Enable IRQ4
- ; -- Enable RS232 interrupt on data ready
- ;
- ; NOTE: The communications parameters are established
- ; here. To use other parameters, change the parameters
- ; in the 'mov al,commparm' statement below. See the
- ; communications parameters record definition (above)
- ; for the correct abbreviations.
- ;
- ; Examples:
- ; 1200,N,8,1: mov al,commparm <B1200,no_parity,stop1,data8>
- ; 4800,O,7,2: mov al,commparm <B4800,odd_parity,stop2,data7>
- ; -----------------------------------------
-
- init proc near
-
- ; ----- Initialize RS232: 300,8,N,1
- mov dx,0 ; COM1
- mov al,commparm <B300,no_parity,stop1,data8>
- @bioscall RS232,0
-
- ; ----- Set up INT x'0C' for IRQ4
- cli ; Interrupts off during setup
- push ds ; Save DS
- mov dx,offset ISR ; Point to RS232 ISR in DS:DX
- push cs
- pop ds
- @doscall 25H,0CH ; Set int vctr for IRQ4
- pop ds ; Restore DS
-
- ; ----- Enable IRQ4 on 8259 interrupt controller
- in al,21H ; Get current masks
- and al,11101111B ; Reset IRQ4 mask
- out 21H,al ; And restore to IMR
-
- ; ----- Enable 8250 data ready interrupt
- mov dx,LCR ; DX ==> LCR
- in al,dx ; Reset DLAB for IER access
- and al,01111111B
- out dx,al
- mov dx,IER ; Address IER
- mov al,00000001B ; Enable 'data-ready' interrupt
- out dx,al
-
- ; ----- Enable OUT2 on 8250
- mov dx,MCR ; Address MCR
- mov al,00001000B ; Enable OUT2
- out dx,al
- sti
-
- ; ----- Display greeting & return
- mov ax,data ; Establish data seg address
- mov ds,ax
- mov dx,offset sgreeting ; Point to greeting
- call strdisp ; Display it
- ret
- init endp
-
-
- ; ---- BUFFER_CHECK -----------------------
- ; RS232 buffer check
- ;
- ; This block checks the received data buffer.
- ; It functions as follows:
- ;
- ; IF the RS232 input buffer is not empty
- ; Get the first character
- ; Display the character
- ; Update buffer pointer
- ; IF the RS232 receive error flag is nonzero
- ; Display an error indicator
- ; IF the buffer overflow flag is nonzero
- ; Display an error indicator
- ;
- ; Entry:
- ; No requirement
- ; Exit:
- ; AX, BX, DX destroyed
- ; -----------------------------------------
-
- buffer_check proc near
-
- ; ----- Check buffer status
- mov bx,wbufhead ; Buffer head pointer
- cmp bx,wbuftail ; Buffer empty if head = tail
- je BC100 ; Jump if empty
-
- ; ----- Something in buffer--get 1st char, fix pointers
- mov al,[bx] ; Get the char
- call incptr ; Bump buffer head pointer
- mov wbufhead,bx
-
- ; ----- Display character received. Filter CR/LF
- cmp al,LF ; Is it a line feed?
- je BC100 ; Skip display if yes
- call chdisp ; Display if no
- cmp al,CR ; Is it a CR?
- jne BC100 ; Jump if not
- mov al,LF ; Send LF if yes
- call chdisp
-
- ; ----- Test RS232 receive status; display errors
- BC100:
- test brcv_err,0FFH ; Flag nonzero if errors
- jz BC200 ; Jump if no errors
- mov dx,offset serr1 ; Point to error msg
- call strdisp
- mov brcv_err,0 ; Clear error flag
-
- ; ----- Test for buffer overflow; display errors
- BC200:
- test boverflow,0FFH
- jz BC300 ; Z if no overflow
- mov boverflow,0 ; Clear the flag
- mov dx,offset serr3 ; Point to error msg
- call strdisp ; And display
-
- BC300:
- ret
- buffer_check endp
-
- ; ----- KB_CHECK --------------------------
- ; Check keyboard. Functions as follows:
- ;
- ; Check the keyboard status
- ; IF a character is available
- ; IF the character is ESC
- ; set the 'done' flag
- ; ELSE
- ; send it to RS232 and watch for errors
- ;
- ; Note that this routine does not echo the KB characters
- ; to the display. Display occurs only when the characters
- ; are echoed back by the remote terminal.
- ;
- ; Entry:
- ; No requirement
- ; Exit:
- ; AX, DX destroyed
- ; -----------------------------------------
-
- kb_check proc near
-
- ; ----- Poll keyboard, check chars received
- call kb_poll ; Poll the keyboard
- jz KBC900 ; Kbd clear, exit
- cmp al,ESC ; Escape?
- jne KBC100 ; No, continue
- mov bdoneflag,0FFH ; Yes, set termination flag
- jmp short KBC900
-
- ; ----- Send the received char, watch for errors
- KBC100:
- call RS232_out ; Send it
- test ah,80H ; Time out?
- jz KBC900 ; No, sent OK
- mov dx,offset serr2 ; Point to error msg
- call strdisp ; And display it
-
- KBC900:
- ret
- kb_check endp
-
-
- ; ----- ISR -------------------------------
- ; This is the RS232 interrupt service routine. It
- ; is entered whenever the RS232 port interrupts on a
- ; 'data ready' condition. The routine simply reads
- ; the data from the asynch chip and stuffs it in the
- ; buffer. Note that the process of reading the
- ; received data register in the 8250 clears IRQ4.
- ; However, the 8259 must be told specifically that the
- ; interrupt service is complete.
- ;
- ; This replaces the function 2 of BIOS interrupt 14H
- ; (receive a character over the comm line). Since
- ; it cannot return errors in a register, it puts the
- ; error marker in memory at 'brcv_err'. The error
- ; flag is 'sticky'--a successful read will NOT clear a
- ; prior error indication. This allows the program
- ; mainline to examine the error status at its
- ; leisure. Error bits are the same as in RS232OUT,
- ; above, except that ONLY the error bits are set,
- ; and bit 7 is not used (always 0). In other words,
- ; brcv_err is nonzero only on an error. Timeout
- ; errors are not possible here.
- ;
- ; The ISR will set the overflow flag if the buffer
- ; should overflow. Shouldn't happen.
- ; -----------------------------------------
-
- ISR proc near
- sti ; Allow other interrupts
- push ax ; Save all regs used
- push bx
- push dx
- push si
- push ds
-
- ; ----- Establish data addressability
- mov ax,data
- mov ds,ax
-
- ; ----- Get error bits
- mov dx,LSR ; Base address of RS232
- in al,dx ; Get status
- and al,00011110B ; Mask non-error bits
- jz ISR010 ; Skip error set if OK
- mov brcv_err,al ; Set error indicator
-
- ; ----- Get incoming character and buffer it
- ISR010:
- mov dx,RBR ; Receiver buffer
- in al,dx ; Get input character
- mov bx,wbuftail ; Buffer input pointer
- mov si,bx ; Save pointer b4 increment
- call incptr ; Bump input pointer
- cmp bx,wbufhead ; Overflow if head = tail
- je ISR020 ; Overflow
- mov [si],al ; No overflow, save char in buffer
- mov wbuftail,bx ; And new input pointer
- jmp short ISR999
- ISR020:
- mov boverflow,0FFH ; Set overflow flag
-
- ; ----- Signal end of interrupt to 8259
- ISR999:
- cli
- mov al,20H ; Non-specific EOI
- out 20H,al ; Send it
-
- ; ----- Restore regs & return. IRET reenables interrupts
- pop ds
- pop si
- pop dx
- pop bx
- pop ax
- iret
- ISR endp
-
-
- ; ----- CLEANUP --------------------------
- ; End of program housekeeping
- ; -- Disable IRQ4
- ; -- Disable 8250 interrupts
- ; -- Disable OUT2
- ; -- Display offline message
- ; ----------------------------------------
-
- cleanup proc near
-
- ; ----- Disable IRQ4 on 8259
- cli
- in al,21H ; IMR
- or al,00010000B ; Mask bit 4--IRQ4
- out 21H,al
-
- ; ----- Disable 8250 data ready interrupt
- mov dx,LCR ; DX ==> LCR
- in al,dx ; Reset DLAB for IER access
- and al,01111111B
- out dx,al
- mov dx,IER ; Address IER
- mov al,0 ; Disable all 8250 interrupts
- out dx,al
-
- ; ----- Disable OUT2 on 8250
- mov dx,MCR ; Address MCR
- mov al,0 ; Disable OUT2
- out dx,al
- sti
-
- ; ----- Display bye-bye
- mov dx,offset sgoodbye
- call strdisp
- ret
- cleanup endp
-
-
- ; * * * * * * * * * * * * * * * *
- ; I/O & GENERAL SUBROUTINES
- ; * * * * * * * * * * * * * * * *
-
- ; ----- KB_POLL ---------------------------
- ; Set/reset Z flag on keyboard buffer status.
- ;
- ; Entry:
- ; No requirements
- ; Exit:
- ; Z = 1 if nothing available
- ; Z = 0 if char available from kbd
- ; IF Z = 0
- ; AL = char
- ; AH = scan code
- ; Other regs preserved
- ; -----------------------------------------
-
- kb_poll proc near
- @bioscall kbd_io,1 ; Poll KB. Sets Z flag if KB bfr empty
- jz KB999 ; Nothing there
- pushf ; Save flag status
- @bioscall kbd_io,0 ; Something there; get it
- popf
- KB999:
- ret
- kb_poll endp
-
-
-
- ; --- RS232_out --------------------------
- ; RS232 output routine
- ;
- ; This routine sends one character to the RS232 port.
- ; It replaces function 1 of BIOS int 14H. This is
- ; necessary because BIOS will disable the RS232
- ; interrupt (by disabling OUT2) every time it is
- ; called.
- ;
- ; Entry:
- ; AL = character to be transmitted
- ; Exit:
- ; AH = send status
- ; Bit 7 = 1 if RS232 timeout occurred
- ; IF bit 7 = 0
- ; bit 6: trans shift register empty
- ; bit 5: trans holding register empty
- ; bit 4: break detect
- ; bit 3: framing error
- ; bit 2: parity error
- ; bit 1: overrun error
- ; bit 0: data ready
- ; Other regs preserved
- ; ----------------------------------------
-
- RS232_out proc near
- push bx ; Save regs used
- push cx
- push dx
-
- ; ----- Set up RS232
- mov bl,al ; Save char to BL temporarily
- mov dx,MCR ; Modem Control Register
- mov al,00001011B ; OUT2, DTR, RTS
- out dx,al
- sub cx,cx ; Initialize timeout count
- mov dx,MSR ; Modem Status Register
-
- ; ----- Wait for DSR
- RS100:
- in al,dx
- test al,20H ; Data set ready?
- jnz RS150 ; Yes
- loop RS100 ; No, retry till timeout
- mov ah,80H ; Set timeout
- jmp short RSXIT ; And quit
-
- ; ----- Wait for CTS
- RS150:
- sub cx,cx ; Another timeout count
- RS200:
- in al,dx
- test al,10H ; Clear to send?
- jnz RS250 ; Yes
- loop RS200 ; No, loop till timeout
- mov ah,80H ; Timeout, set flag
- jmp short RSXIT ; And quit
-
- ; ----- Wait for THRE
- RS250:
- mov dx,LSR ; Line Status Register
- sub cx,cx ; Yet another timeout count
- RS300:
- in al,dx ; LSR status
- test al,20H ; Transmit holding reg empty?
- jnz RS350 ; Yes
- loop RS300 ; No, loop till timeout
- mov ah,80H ; Timeout, set flag
- jmp short RSXIT
-
- ; ----- Get line status, send char
- RS350:
- mov ah,al ; Get line status for return
- and ah,01111111B ; Mask out bit 7
- mov al,bl ; Restore char to AL
- mov dx,THR ; Trasnmit holding register
- out dx,al ; Output it to RS232
- RSXIT:
- pop dx
- pop cx
- pop bx
- ret
- RS232_out endp
-
-
-
- ; ----- CHDISP ----------------------------
- ; Display the character in AL on the CRT
- ; Entry:
- ; AL = char
- ; Exit:
- ; All regs restored
- ; -----------------------------------------
-
- chdisp proc near
- push ax
- push dx
- mov dl,al
- @doscall 2
- pop dx
- pop ax
- ret
- chdisp endp
-
-
-
- ; ----- STRDISP ---------------------------
- ; Display the string at DS:DX on the CRT
- ; Entry:
- ; DS:DX ==> string
- ; Exit:
- ; All regs restored
- ; -----------------------------------------
-
- strdisp proc near
- push ax
- @doscall 9
- pop ax
- ret
- strdisp endp
-
-
-
- ; ----- INCPTR ----------------------------
- ; Increment the buffer pointer in reg BX.
- ; If the pointer goes beyond the end of the
- ; buffer, wrap around to start.
- ;
- ; Entry:
- ; BX = buffer pointer
- ; Exit:
- ; BX = advanced buffer pointer
- ; Other regs restored
- ; -----------------------------------------
-
- incptr proc near
- inc bx ; Bump pointer
- cmp bx,offset bufend ; Past end?
- jne IP100 ; Jump if not
- mov bx,offset buffer ; Else point to start
- IP100:
- ret
- incptr endp
- code ends
- end main
-