home *** CD-ROM | disk | FTP | other *** search
- ;==============================================================================
- ;
- ; 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
-