Category : Assembly Language Source Code
Archive   : ASYNLIB2.ZIP
Filename : ASYNC.ASM

 
Output of file : ASYNC.ASM contained in archive : ASYNLIB2.ZIP
; Async Module.

IDEAL
MODEL compact

EOI equ 020h ; 8259 end-of-interupt
Ctrl8259_0 equ 020h ; 8259 port
Ctrl8259_1 equ 021h ; 8259 port (Masks)
BufSize equ 8196 ; 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

; Register Addresses for the 8250 UART
Port dw ? ; Port Base Address
LABEL RegStart word
THR dw ? ; Transmitter Holding Register
RDR dw ? ; Reciever 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 Register
LCR dw ? ; Line Control Register
MCR dw ? ; Modem Control Register
LSR dw ? ; Line Status Register
MSR dw ? ; Modem Status Register

; Buffer Data
RecBuffer db BufSize DUP (?) ; Recieve 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

; Register Offsets for the UART
RegOffsets dw 0, 0, 0, 1, 1, 2, 3, 4, 5, 6


CODESEG

PUBLIC _AsyncInit, _AsyncClear, _AsyncStop
PUBLIC _AsyncIn, _AsyncOut, _AsyncSet
PUBLIC _AsyncHand, _AsyncStat, _AsyncInStat
PUBLIC _AsyncOutStat


;-----------------------------------------------------------------------------
; AsyncClear Empty the recieve buffer
;-----------------------------------------------------------------------------
; void AsyncClear( void);
;
;
;-----------------------------------------------------------------------------
PROC _AsyncClear
cli
push ax
mov ax, offset RecBuffer
mov [RecHead], ax
mov [RecTail], ax
mov ax, offset TransBuffer
mov [TransHead], ax
mov [TransTail], ax
pop ax
sti
ret
ENDP _AsyncClear



;-----------------------------------------------------------------------------
; 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 @@Done
@@1:
;----- COM2
cmp ax, 1
jne @@2
mov [Port], 02F8h
mov [VectorNum], 0Bh
mov [EnableIRQ], 0F7h
mov [DisableIRQ], 08h
jmp @@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 @@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, 10
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 Buffer
call _AsyncClear

;--- 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

;----- 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
mov dx, [MCR]
in al, dx
or al, 08h
out dx, al

;----- Clear Buffer Just in case
call _AsyncClear

;----- 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

;----- 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
push ax ; Save Registers
push bx
push ds
push dx

mov ax, @data ; Address local data with ds
mov ds, ax

mov dx, [IIR] ; Check if data actually recieved
in al, dx
and al, 06h
cmp al, 04h
je @@recieve
cmp al, 02h
jne @@end

;----- Transmit A byte
@@transmit:
mov bx, [TransTail]
cmp bx, [TransHead]
jne @@1

mov dx, [IER] ; Buffer empty
mov al, 1
out dx, al ; Disable THR empty interrupt
jmp @@end

@@1:
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
jmp @@end

;----- Recieve a byte
@@recieve:
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

@@end:
mov al, EOI ; Signal end ot 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 bx
pop ax

iret

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( int 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 registers
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


END


  3 Responses to “Category : Assembly Language Source Code
Archive   : ASYNLIB2.ZIP
Filename : ASYNC.ASM

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/