Category : Batch File Utilities - mostly for DOS
Archive   : UART12.ZIP
Filename : UART.ASM

 
Output of file : UART.ASM contained in archive : UART12.ZIP
PAGE 60,132
NAME UART
TITLE UART Version 1.2 1993 June 17
COMMENT û

UART C:
Detect UART type of serial port
UART COM1:
If Errorlevel 5 GoTo SyntaxError
If Errorlevel 4 GoTo PS2TYPE3
If ErrorLevel 3 GoTo AT16550FIFO
If ErrorLevel 2 GoTo AT16450
If ErrorLevel 1 GoTo XT8250
If ErrorLevel 0 GoTo NoSuchPort

UART by itself is considered a syntax error and generates a
usage message.

Sets errorlevel to type of UART detected.

This code is based on the MASM routines on page 364 Of PC
Magazine May 26, 1992.

In DESQview often ports COM1: and COM2: are not accessible. You
must have access priviledge in your PIF.

Under OS/2 virtualization makes all com ports look like 8250s.

Supports only COM1: .. COM4:. Looks in BIOS Table to find the
corresponding physical addresses.

It expects this pattern COM1: COM2: COM3: COM4:
port: 378 2f8 3e8 2e8
irq: 4 3 4 3
int: C B C B

If for example COM1: has port 2f8, then irq 3 would be
anticipated and its interrupts would be fielded on int vector B.
Port has precedence over com port number in determining irq.

To Do

- extend support to COM5..COM8
I don't know the expected IRQs or port addresses for these beasts.
If you have info on how these are supposed to work, please pass
it along. Also I would need someone with a machine with such ports
to beta test.

û ; end of comment

;======
; M A C R O S

PEEK MACRO portoffset
;; read port then delay
if (portoffset NE DITTO)
lea dx,[bx+portoffset]
endif
in al,dx
call breath
ENDM

POKE MACRO portoffset
;; write port then delay
if (portoffset NE DITTO)
lea dx,[bx+portoffset]
endif
out dx,al
call breath
ENDM

;======
; E Q U A T E S
PIC EQU 21h ; 21h PIC interrupt controller
; bits 76543210 - 1-disable interrupt
RBR EQU 0 ; 3F8 Receive Buffer Register
THR EQU 0 ; 3F8 Transmit Holding Register
LSBDIV EQU 0 ; 3F8 LSB divisor, latch bit must be on
; in the LCR
IER EQU 1 ; 3F9 Interrupt Enable Register
; 0000MLTR 1=enable
; Modem status, Line, Transmit, Receive
MSBDIV EQU 1 ; 3F9 MSB divisor, DBLAB bit must be on
IIR EQU 2 ; 3FA Interrupt Ident Register
; 001 none
; 110 line error, read line status
; 100 data avail, read char
; 010 thr empty, read IIR, send char
; 000 modem status, read MSR
FIFO EQU 2 ; 3FA Fifo Control Register
LCR EQU 3 ; 3FB Line Control Register
; DBSEPSWW
; Divisor latch, Break, Stick, Even
; Parity, Stop bits, word length11=8
MCR EQU 4 ; 3FC Modem Control Register
; 000L21RD
; Loopback, Out-2, Out-1, RTS, DTR
; Out-2 enables ints, Out-1 does reset
LSR EQU 5 ; 3FD Line Status Register
; 0THBFPOD
; Tx shift, Tx Hold, Break, Frame, Parity,
; Overrun, Data ready
MSR EQU 6 ; 3FE Modem Status Register
; SRDCSRDC
; line Signal, Ring, DSR, CTS
; delta line Signal, Ring, DSR, CTS
SCR EQU 7 ; 3FF Scratch
ENH EQU 8003h ; 83FB Enhanced register
DITTO EQU 9999 ; use same port as previously.

stack segment stack ; keep MS link happy by providing null stack
stack ends

;==============================================================

CODE SEGMENT PARA ; start off in code.

;==============================================================

data segment word ; provide a separate DATA segment
; Even though it appears in the source
; before the code, it the COM file it

;=============================================


BIOSDATA segment AT 40h ; dummy segment in low RAM
org 0h

BIOSComAddrs dw ? ; 4 words of COM1: .. COM4:
dw ? ; device addresses
dw ?
dw ?

BIOSDATA ends

;=============================================
; E R R O R M E S S A G E S
;=============================================

CopyrightMsg label byte
db 13,10
db '°±²Û UART 1.2 Û²±°',13,10
db 13,10
db 'Determines UART type on specified COM port.',13,10
db 13,10
DB '(c) Copyright Roedy Green Canadian Mind Products 1992,1993.',13,10
DB '#601 - 1330 Burrard Street, Vancouver BC CANADA V6Z 2B8 (604) 685-8412',13,10
db 'May be freely distributed and used for any purpose except military.',13,10
db 13,10,'$'

UsageMsg label Byte
db 'Error in command line. Note the mandatory colon. Try:',13,10
db 13,10
db 'UART COM1:',13,10
db 'If Errorlevel 5 GoTo SyntaxError',13,10
db 'If Errorlevel 4 GoTo PS2TYPE3',13,10
db 'If ErrorLevel 3 GoTo AT16550FIFO',13,10
db 'If ErrorLevel 2 GoTo AT16450',13,10
db 'If ErrorLevel 1 GoTo XT8250',13,10
db 'If ErrorLevel 0 GoTo NoSuchPort',13,10,'$'

PortMsg db "COM"
PortPatch1 db "x: is at hex port address: "
HexPatch1 db "xxxx.",13,10,'$'

; Messages to describe the various types of chip found.

code0 db "Port not accessible or not installed.",13,10,'$'
code1 db "XT style 8250 UART.",13,10,'$'
code2 db "AT style 16450 unbuffered UART (might possibly be old-style 16550 or 8250a).",13,10,'$'
code3 db "AT style 16550AF buffered FIFO UART",13,10,'$'
code4 db "PS/2 style IBM type 3 DMA serial port",13,10,'$'

WrongPortMsg db "Warning, COM"
portpatch2 db "x: should be at hex port address: "
HexPatch2 db "xxxx. ",13,10,'$'

GoodIRQmsg db "Port correctly configured to IRQ "
IrqPatch1 db "x.",13,10,'$'
BadIRQMsg db "ERROR: port not properly configured to IRQ "
IrqPatch2 db "x.",13,10
db 13,10
db "If the port appears to be configured correctly, retry the UART test",13,10
db "but first try one or more of the following:",13,10
db 13,10
db " 1. Remove any external devices (e.g. modems or serial mice)",13,10
db " connected to the COM ports.",13,10
db 13,10
db " 2. Install a loopback plug on the COM port under test.",13,10
db 13,10
db " 3. Boot from a floppy disk you are sure installs no drivers on the COM ports.",13,10,"$"

ConfusedIRQMsg db "WARNING: another port sharing IRQ "
IrqPatch3 db "x or driver software",13,10
db " is interfering with this test.",13,10,"$"

DescList dw offset COM:code0
dw offset com:code1
dw offset com:code2
dw offset com:code3
dw offset com;code4

ExpectedList dw 3f8h ; expected port address for COM1
dw 2f8h ; COM2
dw 3E8h ; COM3
dw 2e8h ; COM4

OldVect dd 0 ; CS:IP of current interrupt vector

OldPIC db 0 ; old value of PIC interrupt enable reg.
OldIER db 0 ; old value of Interrupt Enable Register
OldMCR db 0 ; old value of Modem Control Register
OldLCR db 0 ; old value for Line Control Register
OldLSBDivisor db 0 ; old value of latch baud rate divisor
OldMSBDivisor db 0 ; " MSB
OldScr db 0 ; old value of Scratch register
OldENH db 0 ; old value of Enhance register 1


ComNo dw 0 ; 0=COM1: 1=COM2:

Comaddr dw 0 ; 3F8=COM1: 2F8=COM2: 3E8=COM3: 2E8=COM4:

IRQ db 0 ; 3 or 4, corresponds to int B or C.

Vector db 0 ; B or C interrupt vector

EventCount dw 0 ; counts how many interrupts. Should be one.

data endS

;==============================================================

com group code,data

ASSUME CS:COM,DS:COM,ES:COM
ORG 100H
Start:
Call Parse ; prepare the command line
Call Analyse ; analyse the command line for drive letter
mov bx,ComAddr ; hex port address for com port
Call UartType ; return code in bx
push bx
Call DisplayUARTType ; message to describe type we found.
Call CheckPort ; check if port is one expected
Call CheckIRQ ; Check that IRQ is one expected
; This code does not work yet.
pop bx
mov al,bl
mov ah,04ch ; exit to dos, errorlevel in AL
int 21h

Failed:
lea dx,Copyrightmsg
call say
lea dx,usagemsg
call say
mov ax,4c05h ; exit back to DOS with error code 5
int 21h


;==============================================================

UARTTYPE Proc Near

; on entry BX is serial I/O port: e.g. 3F8
; On exit BX contains the serial port type
; This code is very similar to code in PC Magazine page 364
; May 26, 1992. I added two null checks and tighted up the code.
; 0=not present, and sets carry
; 1=8250
; 2=16450, old style 16550, 8250A
; 3=16550AF with FIFO queues
; 4=IBM type 3 serial port with DMA
; trashes bx,cx,dx

test bx,bx
jz isNullComm
Call SaveChipState
cli ; port might be in use, e.g. mouse
; attempt to do as little damage as possible.
mov al,00000011b ; set up a vanilla n81 setting
POKE LCR ; 3FB attempt to write to line control register
PEEK DITTO ; see if it took
sti
cmp al,00000011b
jne isNullComm ; no, must be no port at all.
PEEK MCR ; 3FC modem control reg
and al,11110011b ; disable serial interrupt
; Out-2 must be on for interrupts to happen
; out-1 does a reset
; Where is this documented?
POKE DITTO
cli
mov al,55h ; see if scratch register exists
POKE SCR
PEEK DITTO ; see if 55 comes back.
sti
cmp al,55h
jne is8250 ; 8250 has no scratch reg

mov al,0aah ; just in case, try that again
cli
POKE DITTO
PEEK DITTO
sti
cmp al,0aah
jne is8250 ; 8250 has no scratch reg

; must be something more advanced than the 8250

mov al,7 ; attempt to enable FIFOs
cli
POKE FIFO ; 3FA
PEEK IIR ; 3FA interrupt id reg
sti
and al,0c0h ; strip out all but FIFO bits
jz Is16450 ; all 0 if no FIFO.

; must be more advanced than the 16450
cli
PEEK ENH ; 83FB read enhanced register 1
or al,01000000b ; enable DMA Xmit mode
POKE DITTO
PEEK IIR
sti
and al,0c0h ; mask all but FIFO ID
cmp al,040h
jne Is16550

jmp IsIBMType3


IsNullComm:
mov bx,0
stc
ret

Is8250:
mov cx,1
jmp UARTTypeDone

Is16450:
mov cx,2
jmp UARTTypeDone

Is16550:
mov cx,3
jmp UARTTypeDone

IsIBMType3:
mov cx,4

UARTTypeDone:

Call RestoreChipState
mov bx,cx
clc
ret

UARTTYPE EndP

;=============================================

DisplayUARTType Proc Near

; on entry BX is the type code for the UART type.
; we display a message describing it.
; trash everything

push bx

mov ax,Comaddr ; get hex address
call AsHex ; patch in the hex address to the
; output message.
lea si,AsHexBuf
lea di,HexPatch1
movsw
movsw
mov ax,ComNo ; 0=COM1: 1=COM2:
add al,'1'
mov PortPatch1,al ; patch com port number in message.
lea dx,PortMsg ; echo port number and address.
call Say

pop bx
shl bx,1 ; index table of words
mov dx,DescList[BX]
Call Say ; display corresponding description
ret

DisplayUARTType EndP

;==============================================================

CheckPort Proc Near

; check that ComPort is usual value for this ComNo.
; If not, print a warning message.
; Presume Comaddr has been calculated already.
; trash everything

test Comaddr,-1
jz UsingProperPort ; if not in use, don't count as error.
mov bx,ComNo
shl bx,1
mov bx,ExpectedList[bx]
; expect comport #
cmp bx,ComAddr
je UsingProperPort

; Oops, this is not the port we would usually use

mov ax,bx
call AsHex ; patch in the hex address to the
; output message.
lea si,AsHexBuf
lea di,HexPatch2
movsw
movsw
mov ax,ComNo ; 0=COM1: 1=COM2:
add al,'1'
mov PortPatch2,al ; patch com port number in message.
lea dx,WrongPortMsg ; echo port number and address.
call Say

UsingProperPort:
ret

CheckPort EndP

;==============================================================

SaveChipState Proc Near

; Save values of UART registers so we can restore later

mov dx,PIC ; save state of PIC
in al,dx
mov OldPIC,al

mov bx,ComAddr ; e.g 3F8
PEEK MCR ; 3FC save current modem control reg.
mov OldMCR,al

PEEK IER ; 3F9 save current interrupt enable register
mov OldIER,al

PEEK LCR ; 3FB save current line control register
mov OldLCR,al

PEEK SCR ; 3FF save old scratch register
mov oldSCR,al

PEEK ENH ; 83FB save old enhanced reg1
mov oldENH,al

mov al,10000011b ; set up n81, access divisor
POKE DITTO
PEEK LSBDIV ; save old baud rate divisor
mov OldLSBDivisor,al
PEEK MSBDIV
mov OldMSBDivisor,al

mov al,OldLCR ; 3FB just save LCR, don't change it yet.
POKE LCR


ret

SaveChipState EndP

;=============================================

RestoreChipState Proc Near

; put all registers in chip back the way they were.

cli ; restore PIC back the way it
mov dx,PIC ; was. Non 3/4 IRQs may have legitimately
in al,dx ; changed during our run. We don't put them
and al,0e7h ; back, just irq 3/4.
mov ah,OldPic ; 0=enabled 1=disabled
and ah,018h
or al,ah
out dx,al
sti

mov bx,ComAddr ; e.g 3F8
mov al,OldIER ; 3F9 restore interrupt enable register 3F9
POKE IER

mov al,OldMCR ; 3FC restore original modem control register 3FC
POKE MCR

mov al,oldSCR
POKE SCR ; 3FF restore old scratch register

mov al,oldENH
POKE ENH ; 83FB restore old enhanced reg1

mov al,10000011b ; set up n81, access divisor
POKE LCR ; 3FB restore divisor
mov al,OldLSBdivisor
POKE LSBDIV
mov al,OldMSBDivisor
POKE MSBDIV

mov al,OldLCR ; 3FB restore line status register
POKE LCR
; we cannot directly restore the IIR
; but we can turn off the FIFO
mov al,0
POKE FIFO ; 3FA

ret

RestoreChipState EndP

;=============================================

;COMMENT û ; this routine does not work yet. WHY???
; I have chewed on this for days!!!

CheckIRQ Proc Near

; Check the that exactly one interrupt at the expected IRQ

Call CalcIRQ ; figure out which IRQ should be used
Call SetTrap ; trap interrupts from expected IRQ
Call Trigger1Int ; Trigger 1 interrupt using loopback
Call RestoreIRQ ; put trap back the way it was
Call PatchIRQ ; patch expected IRQ # into error messages.
cmp Eventcount,1 ; should see 1 int
jb BadIRQ
ja ConfusedIRQ

; Just right, saw 1 interrupt
GoodIRQ:
lea dx,GoodIRQMsg
call Say
ret

BadIRQ:
lea dx,BadIRQMsg
call Say
ret

ConfusedIRQ:
lea dx,ConfusedIRQMsg
call Say
ret

CheckIRQ EndP

;==============================================================

CalcIRQ Proc Near

; Calculate the IRQ 4 or 3 to match hex address

mov ax,ComAddr
lea di,Expectedlist ; scan list of legal port #s
mov cx,4 ; to make sure it is in the list.
repne scasw
jne NoIrq
; ax still has the address.
mov al,ah ; 3f8 2f8 3e8 2e8 -> 2 or 3
sub ah,ah
inc ax ; 3 -> 4 2 -> 3
mov IRQ,al
add al,8 ; 3->B 4->C
mov Vector,al ; which interrupt vector,
; not same as IRQ
clc

ret

NoIRQ: mov IRQ,0
mov Vector,0
stc
ret

CalcIRQ EndP

; =============================================

PatchIRQ Proc Near

; Patch expected the IRQ number into various possible error messages.

mov al,IRQ ; 3 or 4 binary
add al,030h ; 3 or 4 ASCII
mov IrqPatch1,al
mov IrqPatch2,al
mov IrqPatch3,al
ret

PatchIRQ EndP

; =============================================

ASSUME DS:nothing,ES:nothing

SetTrap Proc near

; Trap interrupts from the expected source irq 3 or 4.

push DS
push ES
mov ah,35h
mov al,Vector ; save old B/C vector
int 21h ; result in ES:BX
mov word ptr OldVect, bx
mov word ptr OldVect+2, ES
pop ES
push CS
pop DS

lea dx,CS:IntHandler
mov ah,25h
mov al,Vector ; set up new B/C vector to point to our
; miniature handler
int 21h
pop DS
ret

SetTrap EndP


; =============================================

ASSUME DS:NOTHING,ES:NOTHING

IntHandler Proc Near

; Interrupt handler for irq 3 or 4 int B or C.

; ints are off right now
push ax ; must not disturb ANYTHING!
push bx
push cx
push dx
inc CS:EventCount ; only CS: works,
; count how many interrupts.
; should be only one.
mov al,20h
out 20h,al ; send eoi command to PIC
call Breath

Call ClearPendingInterrupt
sti
pop dx
pop cx
pop bx
pop ax

iret

IntHandler EndP


;=============================================
ASSUME DS:COM,ES:COM

Trigger1Int Proc Near

; Trigger one interrupt and count how many ints appeared at the
; expected interrupt.


Call SaveChipState ; save current values of all regs we will wreck.


mov al,10000011b ; set up n81, access divisor
POKE LCR ; 3FB
mov al,030h
POKE LSBDIV ; set up 2400 baud
mov al,0
POKE MSBDIV

mov al,00000011b ; set up n81, access regular regs
POKE LCR ; 3FB

cli ; Turn on ints 3 and 4 in the PIC
mov dx,PIC
in al,dx
and al,0e7h ; 0=enabled 1=disabled.
out dx,al
sti

mov al,0 ; disable any FIFOs
POKE FIFO ; 3FA

mov al,00000110b ; enable interrupts, just THR empty & overrun
POKE IER ; 3F9 Some pending interrupt might trigger

; Loopback does not work. IBM does not let the PIC see the
; interrupts in loopback mode.

mov al,00001000b ; out-1 does a reset of attached modem
; must clear
; out-2 enables interrupts
; turn off DTR and RTS, to reset
; any attached modem

POKE MCR ; 3FC might generate an interrupt
call BigBreath

mov al,00001011b ; out-1 does a reset of attached modem
; must clear
; out-2 enables interrupts
; turn on DTR and RTS

POKE MCR ; 3FC might generate an interrupt
call BigBreath

mov EventCount,0 ; clear interrupt counter
sti ; ints should be on anyway.
mov al,0 ; send a null character
POKE THR ; Five things can happen:
; 1. device accepts the char
; 2. device keeps CTS low, so char
; never goes out. We never get an int.
; 3. device is powered off or missing.
; Then we get a line status int.
; 4. IRQ not set properly. We see no int.
; 5. Some other device is using same IRQ.
; We see multiple ints.

Call BigBreath ; Wait long enough for interrupt to happen

call ClearPendingInterrupt
Call RestoreChipState
ret

Trigger1Int EndP

;=============================================

ClearPendingInterrupt Proc Near

; If there is a pending interrupt, get it cleared
; See page 1-242 XT tech ref.
; trashes ax,bx,dx
; Called from Int handler. Cannot use DS:

mov bx,CS:ComAddr ; e.g 3F8

PEEK IIR ; 3FA read IIR to clear
; any modem transmitter holding empty interrupt

PEEK RBR ; 3F8 read receive buffer register to clear
; any char in interrupt

PEEK LSR ; e.g. 3FD read line status register to clear
; any parity interrupt

PEEK MSR ; e.g. 3FE read modem status register to clear
; any modem status interrupt
ret

ClearPendingInterrupt EndP

;=============================================

ASSUME DS:NOTHING,ES:NOTHING

RestoreIRQ proc near

; Put the B/C vector back the way it was

push DS
mov dx,word ptr OldVect
mov ax,word ptr OldVect+2
mov DS,ax
mov ah,25h
mov al,Vector ; set B/C vector
int 21h
pop DS
ret

RestoreIRQ EndP
; end of commented out code

ASSUME DS:COM,ES:COM

;=============================================
; C O M M A N D L I N E P A R S I N G R O U T I N E S
;=============================================

MLeading PROC Near

; Remove leading blanks
; on entry ES:BX is addr of string, CX its length
; trims off any leading blanks, leaving result in BX CX
; length may also be 0 or 1, but not -ve
; If the entire string is blank the result is the null string

mov di,bx
mov al,20H ; AL = blank -- the search char
jcxz mleading2 ; jump if null string
repe scasb ; scan ES:DI forwards till hit non blank
; DI points just after it (wrap ok)
; cx IS ONE TOO SMALL, OR 0 IF NONE FOUND
je mleading1 ; jump if entire string was blank
inc cx ; CX is length of remainder of string
mleading1:
dec di ; DI points to non-blank
mleading2:
mov bx,di ; put address back
ret

MLeading ENDP

;========================================

MTrailing PROC Near

; Remove trailing blanks.
; on entry ES:BX is addr of string, CX its length
; trims off any trailing blanks, leaving result in BX CX
; length may also be 0 or 1, but not -ve
; If the entire string is blank the result is the null string

mov di,bx
add di,cx ; calc addr last char in string
dec di
mov al,20H ; AL = blank -- the search char
jcxz mtrailing1 ; jump if null string
std
repe scasb ; scan ES:DI backwards till hit non blank
; DI points just ahead of it (wrap ok)
; CX is one too small, or 0 if none found
cld
je mtrailing1 ; jump if whole string was blank
inc cx
mtrailing1:
ret

MTrailing ENDP

;========================================

Parse PROC NEAR
; Parse the command line to remove lead/trail blanks from
; the single drive parameter and terminate it by 2 nulls.
; sample inputs
; UART COM1:
; UART COM2:
; UART
; ES: points to PSP
; When Done ES:BX points to start of string.
; String will be terminated by 2 nulls
; CX counts bytes in string exclusive of nulls
; counted string at HEX 80 PSP
; contains command line.
; Preceeded by unwanted spaces.
; possibly followed by unwanted spaces.
; currently missing a trailing null.
xor ch,ch
mov cl,es:[80H]
mov bx,81H
call Mleading ; get rid of leading blanks
call MTrailing ; get rid of trailing blanks
mov di,bx ; calc addr of byte just past end
add di,cx
mov word ptr ES:[di],0 ; plop in pair of nulls after string
ret

Parse ENDP

;======================================
Analyse PROC NEAR
; analyses the command line allowing COM1: COM2:
; On entry ES:BX points to start of string.
; String will be terminated by 2 nulls
; CX counts bytes in string exclusive of nulls
; lead/trail spaces are gone.
jcxz BadCmd ; was no command
cmp cx,5 ; COM1: - must be 5 chars
jne BadCmd
mov al,ES:[bx+4]
cmp al,':' ; make sure last char is :
jne BadCmd
mov al,ES:[bx+3]
sub al,'1' ; '1'->0 '2'->1 '3'->2 '4'->3
cmp al,3
ja BadCmd ; allow only COM1: to COM4:
mov Byte Ptr ComNo,AL
push ES
mov ax,BIOSDATA ; convert to port address
mov es,ax
ASSUME ES:BIOSDATA
mov di,word Ptr ComNo
shl di,1 ; address a table of words it low RAM
mov ax,ES:BIOSComAddrs[di]
ASSUME ES:COM
pop ES
mov ComAddr,ax
AnalDone:
RET
BadCmd:
Jmp Failed

Analyse ENDP

;=============================================

AsHex Proc Near

; calculates 4 digit (16 bits) hex number in AX
; get digits into place, don't worry about excess high order stuff.
; leaves result in AsHexBuf

mov AsHexBuf+3,al
mov cx,4
shr al,cl
mov AsHexBuf+2,al
mov AsHexBuf+1,ah
shr ah,cl
mov AsHexbuf+0,ah
lea si,AsHexBuf
mov cx,4
AsHexLoop:
lodsb ; fix up each character in turn
and al,0Fh
cmp al,0Ah
jle IsDigit
add al,'A'-0ah
jmp SaveDigit
IsDigit:
add al,'0'
SaveDigit:
mov [si-1],al ; lodsb incremented si already
loop AsHexLoop
ret

Data segment
AsHexBuf db '0000$'
Data Ends

AsHex EndP

;=============================================
Say Proc Near
; on entry DX points to a string to display on screen
MOV AH,9
Int 21h
ret
Say EndP

;=======================================

BigBreath Proc Near

; Wait a decent length of time for triggered interrupt to happen.

push cx
mov cx,20d ; nested wait loop
wait1:

push cx
mov cx,60000d
wait2:
loop Wait2
pop cx

loop Wait1
pop cx
ret

BigBreath EndP

;=======================================

Breath Proc Near

; Take a breath between pokes to the UART chip to give it time to
; recover ready for next i/o command. JMP $+2 is a little too tight.

push cx
mov cx,10d
wait3:
loop Wait3
pop cx

ret

Breath EndP

;=======================================

CODE ends
end start


  3 Responses to “Category : Batch File Utilities - mostly for DOS
Archive   : UART12.ZIP
Filename : UART.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/