home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The AGA Experience 2
/
agavol2.iso
/
software
/
utilities
/
comms
/
term
/
extras
/
hydracom
/
hydracom-source.lha
/
async.asm
< prev
next >
Wrap
Assembly Source File
|
1994-01-19
|
24KB
|
741 lines
;==============================================================================
;
; HydraCom Version 1.00
;
; A sample implementation of the
; HYDRA Bi-Directional File Transfer Protocol
;
; HydraCom was written by
; Arjen G. Lentz, LENTZ SOFTWARE-DEVELOPMENT
; COPYRIGHT (C) 1991-1993; ALL RIGHTS RESERVED
;
; The HYDRA protocol was designed by
; Arjen G. Lentz, LENTZ SOFTWARE-DEVELOPMENT and
; Joaquim H. Homrighausen
; COPYRIGHT (C) 1991-1993; ALL RIGHTS RESERVED
;
;
; Revision history:
; 06 Sep 1991 - (AGL) First tryout
; .. ... .... - Internal development
; 11 Jan 1993 - HydraCom version 1.00, Hydra revision 001 (01 Dec 1992)
;
;
; For complete details of the Hydra and HydraCom licensing restrictions,
; please refer to the license agreements which are published in their entirety
; in HYDRACOM.C and LICENSE.DOC, and also contained in the documentation file
; HYDRACOM.DOC
;
; Use of this file is subject to the restrictions contained in the Hydra and
; HydraCom licensing agreements. If you do not find the text of this agreement
; in any of the aforementioned files, or if you do not have these files, you
; should immediately contact LENTZ SOFTWARE-DEVELOPMENT and/or Joaquim
; Homrighausen at one of the addresses listed below. In no event should you
; proceed to use this file without having accepted the terms of the Hydra and
; HydraCom licensing agreements, or such other agreement as you are able to
; reach with LENTZ SOFTWARE-DEVELOMENT and Joaquim Homrighausen.
;
;
; Hydra protocol design and HydraCom driver: Hydra protocol design:
; Arjen G. Lentz Joaquim H. Homrighausen
; LENTZ SOFTWARE-DEVELOPMENT 389, route d'Arlon
; Langegracht 7B L-8011 Strassen
; 3811 BT Amersfoort Luxembourg
; The Netherlands
; FidoNet 2:283/512, AINEX-BBS +31-33-633916 FidoNet 2:270/17
; arjen_lentz@f512.n283.z2.fidonet.org joho@ae.lu
;
; Please feel free to contact us at any time to share your comments about our
; software and/or licensing policies.
;
;==============================================================================
IDEAL
IFDEF MODL
MODEL MODL
ELSEIFDEF _SMALL
MODEL SMALL
ELSEIFDEF _LARGE
MODEL LARGE
ENDIF
EOI equ 020h ; 8259 end-of-interupt
Ctrl8259_0 equ 020h ; 8259 port
Ctrl8259_1 equ 021h ; 8259 port (Masks)
BufSize equ 4100 ; Buffer Size
DATASEG
; Various things to be set upon AsyncInit()
VectorNum db ? ; Vector Number
EnableIRQ db ? ; Mask to enable 8259 IRQ
DisableIRQ db ? ; Mask to disable 8259 IRQ
VectorSeg dw ? ; Old Vector Segment
VectorOfs dw ? ; Old Vector Offset
Fifo db ? ; Nonzero if 16550 FIFO enabled
CTShand dw ? ; Nonzero if CTS handshaking ok
; Register Addresses for the 8250 UART
Port dw ? ; Port Base Address
LABEL RegStart word
THR dw ? ; Transmitter Holding Register
RDR dw ? ; Receiver Data Register
BRDL dw ? ; Baud Rate Divisor, Low byte
BRDH dw ? ; Baud Rate Divisor, High Byte
IER dw ? ; Interupt Enable Register
IIR dw ? ; Interupt Identification Reg
FCR dw ? ; FIFO Control Register
LCR dw ? ; Line Control Register
MCR dw ? ; Modem Control Register
LSR dw ? ; Line Status Register
MSR dw ? ; Modem Status Register
; Register Offsets for the UART
RegOffsets dw 0, 0, 0, 1, 1, 2, 2, 3, 4, 5, 6
; Buffer Data
RecBuffer db BufSize DUP (?) ; Receive Buffer
RecHead dw ? ; Buffer Head Pointer
RecTail dw ? ; Buffer Tail Pointer
TransBuffer db BufSize DUP (?) ; Transmit Buffer
TransHead dw ? ; Buffer Head Pointer
TransTail dw ? ; Buffer Tail Pointer
CODESEG
PUBLIC _AsyncInit, _AsyncDump, _AsyncPurge, _AsyncStop
PUBLIC _AsyncIn, _AsyncOut, _AsyncSet
PUBLIC _AsyncHand, _AsyncStat, _AsyncInStat
PUBLIC _AsyncOutStat, _AsyncCTS, _AsyncFifo
;-----------------------------------------------------------------------------
; AsyncDump Empty the transmit buffer
;-----------------------------------------------------------------------------
; void AsyncDump (void);
;
;
;-----------------------------------------------------------------------------
PROC _AsyncDump
cli
push ax
mov ax, offset TransBuffer
mov [TransHead], ax
mov [TransTail], ax
pop ax
sti
ret
ENDP _AsyncDump
;-----------------------------------------------------------------------------
; AsyncPurge Empty the receive buffer
;-----------------------------------------------------------------------------
; void AsyncPurge (void);
;
;
;-----------------------------------------------------------------------------
PROC _AsyncPurge
cli
push ax
mov ax, offset RecBuffer
mov [RecHead], ax
mov [RecTail], ax
pop ax
sti
ret
ENDP _AsyncPurge
;-----------------------------------------------------------------------------
; AsyncInit Initalize Serial Port and install ISR
;-----------------------------------------------------------------------------
; void AsyncInit( int port)
;
; Where Port is
; 0 = COM1
; 1 = COM2
; 2 = COM3
; 3 = COM4
;
;-----------------------------------------------------------------------------
PROC _AsyncInit
ARG CommPort:word
push bp
mov bp, sp
;---- Set various things according to com port number
mov ax, [CommPort]
;----- COM1
cmp ax, 0
jne @@1
mov [Port], 03F8h
mov [VectorNum], 0Ch
mov [EnableIRQ], 0EFh
mov [DisableIRQ], 10h
jmp short @@Done
@@1:
;----- COM2
cmp ax, 1
jne @@2
mov [Port], 02F8h
mov [VectorNum], 0Bh
mov [EnableIRQ], 0F7h
mov [DisableIRQ], 08h
jmp short @@Done
@@2:
;----- COM3
cmp ax, 2 ; 2
jne @@3
mov [Port], 03E8h ; 03E8
mov [VectorNum], 0Ch ; 0C
mov [EnableIRQ], 0EFh ; EF
mov [DisableIRQ], 10h ; 10
jmp short @@Done
@@3:
;----- COM4
mov [Port], 02E8h ; 02E8
mov [VectorNum], 0Bh ; 0B
mov [EnableIRQ], 0F7h ; F7
mov [DisableIRQ], 08h ; 08
@@Done:
;---- Compute Register locations
mov cx, 11
mov bx, offset RegOffsets
push di
mov di, offset RegStart
@@4:
mov ax, [bx]
add ax, [Port]
mov [di], ax
add bx, 2
add di, 2
loop @@4
pop di
;----- Initalize Buffers
call _AsyncDump
call _AsyncPurge
;--- Save and reassign interrupt vector
push ds ; Save Old Vector
mov al,[VectorNum]
mov ah,35h
int 21h
mov [VectorSeg], es
mov [VectorOfs], bx
mov al, [VectorNum]
push cs ; Set New Vector
pop ds
mov dx, offset AsyncISR
mov ah, 25h
int 21h
pop ds
;----- Enable 8259 interrupt (IRQ) line for this async adapter
in al, Ctrl8259_1
and al, [EnableIRQ]
out Ctrl8259_1, al
;----- Enable 8250 Interrupt-on-data-ready
mov dx, [LCR] ; Read Line control register and clear
in al, dx ; bit 7, the Divisor Latch Address
and al, 07Fh
out dx, al
mov dx, [IER]
mov al, 0 ; we're gonna test the UART first
out dx, al
in al, dx ; if this isn't 0, there's no UART
cmp al, 0
jnz @@222
mov al, 3
out dx, al
;----- Try to enable 16550 FIFOs
mov dx, [FCR] ; FIFO Control Register
mov al, 0C7h ; bits 76210 (trigger14,clearIO,enable)
out dx, al ; Write
mov dx, [IIR]
in al, dx
and al, 0C0h ; 8250/16450 sets none of the 2 bits
cmp al, 0C0h ; faulty 16550 sets 1 of the 2 bits
je okfifo
mov dx, [FCR] ; didn't work, turn off case faulty 550
xor al, al ; set to zero = no FIFO
out dx, al
okfifo: mov [Fifo], al ; store 16550 FIFO situation
;----- Reset CTS handshaking flag
mov [CTShand], 0 ; Disable CTS handshaking
;----- Clear 8250 Status and data registers
@@10:
mov dx, [RDR] ; Clear RDR by reading port
in al, dx
mov dx, [LSR] ; Clear LSR
in al, dx
mov dx, [MSR] ; Clear MSR
in al, dx
mov dx, [IIR] ; Clear IIR
in al, dx
test al, 1
jz @@10
;----- Set Bit 3 of MCR -- Enable interupts, also raise DTR and RTS
mov dx, [MCR]
in al, dx
or al, 0Bh
out dx, al
;----- Clear Buffers Just in case
call _AsyncDump
call _AsyncPurge
;----- Return
xor ax, ax
@@222:
pop bp
ret
ENDP _AsyncInit
;-----------------------------------------------------------------------------
; AsyncStop Uninstall ISR
;-----------------------------------------------------------------------------
; void AsyncStop( void)
;-----------------------------------------------------------------------------
PROC _AsyncStop
push bp
mov bp, sp
;----- Mask (disable) 8259 IRQ Interrupt
in al, Ctrl8259_1
or al, [DisableIRQ]
out Ctrl8259_1, al
;----- Disable 8250 interrupt
mov dx, [LCR]
in al, dx
and al, 07Fh
out dx, al
mov dx, [IER]
xor al, al
out dx, al
;----- Set bit 3 in MCR to 0
mov dx, [MCR]
in al, dx
and al, 0F7h
out dx, al
;----- Disable 16550 FIFOs
mov dx, [FCR] ; FIFO Control Register
xor al, al ; set to 0
out dx, al ; Write
;----- Interrupts are disables. Restore saved interrupt vector.
push ds
mov al, [VectorNum]
mov ah, 25h
mov dx, [VectorOfs]
mov ds, [VectorSeg]
int 21h
pop ds
;----- Return
pop bp
ret
ENDP _AsyncStop
;-----------------------------------------------------------------------------
; AsyncISR Async Interrupt Service Routine
;-----------------------------------------------------------------------------
; To be called only as an interrupt.
;-----------------------------------------------------------------------------
PROC AsyncISR
sti
push ax ; Save Registers
push bx
push cx
push ds
push dx
mov ax, @data ; Address local data with ds
mov ds, ax
@@isr: mov dx, [IIR] ; Check if data actually received
in al, dx
and al, 07h
test al, 1
jnz @@end
cmp al, 04h ; Receive interrupt
je @@receive
cmp al, 02h
je @@transmit ; Transmit interrupt
cmp al, 0
je @@modem ; Modem Status interrupt
@@end: cli
mov al, EOI ; Signal end of interrupt
out Ctrl8259_0, al
; Disable and re-enable interrupts so that there
; is an interrupt edge.
; mov dx,[IER] ; Point to Interrupt Enable Register.
; in al,dx ; Read the current value.
; push ax ; Save it.
; mov al,0 ; Disable the interrupts.
; out dx,al
; pop ax ; Restore original mask.
; out dx,al ; Re-enable interrupts.
pop dx ; Restore saved registers.
pop ds
pop cx
pop bx
pop ax
iret
;----- Receive a byte
@@receive:
mov dx, [RDR] ; Get Byte
in al, dx
mov bx, [RecHead] ; Store Byte in buffer
mov [byte ptr bx], al
inc bx ; Update RecHead
cmp bx, offset RecBuffer + BufSize
jb @@10
mov bx, offset RecBuffer
@@10:
cmp bx, [RecTail]
jne @@20
mov bx, [RecHead] ; Cancel Pointer advance on overflow
@@20:
mov [RecHead], bx ; Store new pointer
mov dx, [LSR] ; Read Line Status Register
in al, dx
test al, 01h ; Check for more Data Ready
jnz @@receive ; Will mostly happen in FIFO mode
jmp short @@isr
;----- Modem Status Interrupt - for CTS handshake handling
@@modem:
mov dx, [MSR] ; Modem Status Register
in al, dx
test al, 010h ; Clear To Send went high?
jz @@isr ; Nope, some other line went somewhere
mov dx, [IER] ; Point to Interrupt Enable Register.
mov al, 03h ; RD was on, TD now on, MS now off.
out dx, al
; fallthrough modem to transmit, CTS went high and THR must have been empty
;----- Transmit A byte
@@transmit:
mov cx, 1 ; Assume no FIFO, xmit one char
mov al, [Fifo]
or al, al
jz @@xtop ; Not FIFO mode
mov cx, 16 ; FIFO, can transmit max 16 chars
@@xtop:
mov bx, [TransTail]
cmp bx, [TransHead]
jne @@1
mov dx, [IER] ; Buffer empty
mov al, 1
out dx, al ; Disable THR empty interrupt
jmp @@isr
@@1:
mov ax, [CTShand]
or ax, ax
jz @@xmit ; No handshaking, so ignore CTS
mov dx, [MSR] ; Point to Modem Status Register.
in al, dx ; Read the current value.
and al, 010h ; Check if CTS line high
jnz @@xmit ; Yeo, so can transmit
mov dx, [IER] ; No CTS, ask for irq on Modem Status
mov al, 09h ; RD was on, TD now off, MS now on
out dx, al
jmp @@isr
@@xmit: mov al, [byte ptr bx] ; Get Byte
inc [TransTail] ; Update buffer pointer
cmp [word ptr TransTail], offset TransBuffer + BufSize
jb @@2
mov [TransTail], offset TransBuffer
@@2:
mov dx, [THR]
out dx, al
loopnz @@xtop
jmp @@isr
ENDP AsyncISR
;-----------------------------------------------------------------------------
; AsyncIn Gets a byte from the input buffer
;-----------------------------------------------------------------------------
; int AsyncIn( void)
;-----------------------------------------------------------------------------
PROC _AsyncIn
push bp
mov bp, sp
xor ax, ax ; Pre-Set result to 0
mov bx, [RecTail]
cmp bx, [RecHead]
je @@return
mov al, [byte ptr bx]
inc [RecTail]
cmp [word ptr RecTail], offset RecBuffer + BufSize
jb @@return
mov [RecTail], offset RecBuffer
@@return:
pop bp
ret
ENDP _AsyncIn
;-----------------------------------------------------------------------------
; AsyncOut Output a byte
;-----------------------------------------------------------------------------
; void AsyncOut( int c)
;-----------------------------------------------------------------------------
PROC _AsyncOut
ARG CharOut:word
push bp
mov bp, sp
mov ax, [CharOut]
mov bx, [TransHead]
mov cx, bx
inc cx ; Compute NEW buffer position
cmp cx, offset TransBuffer + BufSize
jb @@1
mov cx, offset TransBuffer
@@1:
cmp cx, [TransTail] ; Wait for space in buffer
je @@1
mov [byte ptr bx], al ; Add byte to buffer
mov [TransHead], cx ; Update pointer
mov dx, [IER] ; Enable THR empty interrupt
mov al, 3
out dx, al
pop bp
ret
ENDP _AsyncOut
;-----------------------------------------------------------------------------
; AsyncSet Set communication paramaters
;-----------------------------------------------------------------------------
; void AsyncSet( word Baud, int Control)
;
; Baud = 150, 300, 600, 1200, 2400, 4800, 9600, 19200, 28800, 38400, 57600
; Control = The valure to place in the LCR
;-----------------------------------------------------------------------------
PROC _AsyncSet
ARG Baud:word, Control:word
push bp
mov bp, sp
mov bx, [Baud]
cmp bx, 0
je @@abort
mov ax, 0C200h ; Baud rate divisor = 115200 / Baud
mov dx, 0001h ; 115200 = 0001C200h
div bx
mov cx, ax
cli
mov dx, [LCR] ; Set Port Toggle to BRDL/BRDH regs
mov al, 0ffh
out dx, al
mov dx, [BRDL] ; Set Baud Rate
mov al, cl
out dx, al
mov dx, [BRDH]
mov al, ch
out dx, al
mov dx, [LCR] ; Set LCR and Port Toggle
mov ax, [Control]
and al, 07Fh
out dx, al
sti
@@abort:
pop bp
ret
ENDP _AsyncSet
;-----------------------------------------------------------------------------
; AsyncInStat Returns the # of characters in buffer
;-----------------------------------------------------------------------------
; int AsyncInStat( void)
;-----------------------------------------------------------------------------
PROC _AsyncInStat
push bp
mov bp, sp
mov ax,[RecHead]
sub ax, [RecTail]
jge @@10
add ax, BufSize
@@10:
pop bp
ret
ENDP _AsyncInStat
;-----------------------------------------------------------------------------
; AsyncOutStat Returns the # of characters in buffer
;-----------------------------------------------------------------------------
; int AsyncOutStat( void)
;-----------------------------------------------------------------------------
PROC _AsyncOutStat
push bp
mov bp, sp
mov ax,[TransHead]
sub ax, [TransTail]
jge @@10
add ax, BufSize
@@10:
pop bp
ret
ENDP _AsyncOutStat
;-----------------------------------------------------------------------------
; AsyncHand Sets various handshaking lines
;-----------------------------------------------------------------------------
; void AsyncHand( int Hand)
;-----------------------------------------------------------------------------
PROC _AsyncHand
ARG Hand:word
push bp
mov bp, sp
mov dx, [MCR]
mov ax, [Hand]
or al, 08h ; Keep interrupt enable ON
out dx, al
pop bp
ret
ENDP _AsyncHand
;-----------------------------------------------------------------------------
; AsyncStat Returns Async/Modem status
;-----------------------------------------------------------------------------
; unsigned AsyncStat (void)
;
; MSR is returned in the high byte, LSR in the low byte
;-----------------------------------------------------------------------------
PROC _AsyncStat
push bp
mov bp, sp
mov dx, [MSR]
in al, dx
mov cl, al
mov dx, [LSR]
in al, dx ; LSR in low byte
mov ah, cl ; MSR in high byte
pop bp
ret
ENDP _AsyncStat
;-----------------------------------------------------------------------------
; AsyncCTS Enable/disable CTS handshaking
;-----------------------------------------------------------------------------
; void AsyncCTS( int enable)
;-----------------------------------------------------------------------------
PROC _AsyncCTS
ARG enable:word
push bp
mov bp, sp
mov ax, [enable]
mov [CTShand], ax
pop bp
ret
ENDP _AsyncCTS
;-----------------------------------------------------------------------------
; AsyncFifo Returns nonzero if 16550 (FIFO enabled)
;-----------------------------------------------------------------------------
; unsigned AsyncFifo (void)
;-----------------------------------------------------------------------------
PROC _AsyncFifo
push bp
mov bp, sp
xor ah, ah
mov al, [Fifo]
pop bp
ret
ENDP _AsyncFifo
END
; end of async.asm