home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 8 Other
/
08-Other.zip
/
comtest.zip
/
COMTEST.ASM
next >
Wrap
Assembly Source File
|
2000-11-23
|
9KB
|
410 lines
; COMTEST - Find COMs port type and associated IRQ line
; Copyright (c) 1997-2000 Arkady Belousov <ark@mos.ru>
;
; This program is free software; you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation; either version 2 of the License, or
; (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program; if not, write to the Free Software
; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
;
WARN
.model tiny
j equ jmp short
movSeg macro dest,src
push src
pop dest
endm
PrintS macro addr
IFNB <addr>
IFDIFI <addr>,<dx>
mov dx,offset addr
ENDIF
ENDIF
mov ah,9
int 21h
endm
;██████████████████████████████ DATA SEGMENT ██████████████████████████████
.data
PIC db ?,?
IRQ_line db ?
S_header db 'COMTEST v1.0 Copyright (c) 2000 by Arkady V.Belousov',0dh,0ah
db 0dh,0ah
db 'COM Addr IRQ# Comments',0dh,0ah
db '--- ---- ---- --------'
CRLF db 0dh,0ah,'$'
S_port db ' '
S_COMno db ' '
S_IOaddr db ' $'
S_none db ' not present$'
S_8250 db ' 8250 (no FIFO)$'
S_8250A db ' 8250A/16450 (no FIFO)$'
S_16550 db ' 16550 (buggy FIFO)$'
S_16550A db ' 16550A (with FIFO)$'
UARTtable dw offset DGROUP:S_8250
dw offset DGROUP:S_8250A
dw offset DGROUP:S_16550
dw offset DGROUP:S_16550A
;██████████████████████████████ CODE SEGMENT ██████████████████████████████
.code
org 100h
start: cld
PrintS DGROUP:S_header
mov ax,1Fh ; disable mouse
call mousedrv
xor ax,ax
@@comloop: push ax
;---------- get COM port IO address
xor bx,bx
mov es,bx
mov bl,al
add al,'1'
mov [S_COMno],al
shl bx,1
mov ax,es:400h[bx]
mov [IO_address],ax
;---------- convert IO address into string
movSeg es,ds
mov di,offset DGROUP:S_IOaddr
mov cl,12
@@loophexw: push ax
shr ax,cl
and al,0Fh
cmp al,10
sbb al,69h
das
stosb
pop ax
sub cl,4
jae @@loophexw
;---------- detect UART type and IRQ line
PrintS DGROUP:S_port
call detectUART
mov dx,offset DGROUP:S_none
jc @@nextCOM
push bx
call findIRQ
pop bx
shl bx,1
mov bx,UARTtable[bx]
mov ah,' '
add al,'0'
cmp al,'0'
jne @@saveIRQno
mov al,'?'
@@saveIRQno: xchg al,ah
mov [bx],ax
mov dx,bx
;---------- get next COM port
@@nextCOM: PrintS
PrintS CRLF
pop ax
inc ax ; OPTIMIZE: AX instead AL
cmp al,4
jb @@comloop
;---------- reset mouse and exit
xor ax,ax
call mousedrv
int 20h
;▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
mousedrv proc
push ax
mov ax,3533h
int 21h
pop ax
mov cx,es
jcxz @@mouseret
int 33h
@@mouseret: ret
mousedrv endp
;▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
; Detect UART presence and type
;▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
;
; In: none
; Out: Carry flag (no UART detected)
; BX (UART type: 0=8250, 1=8250A/16450,
; 2=16550, 3=16550A)
; Use: IO_address
; Modf: AX, DX
; Call: none
;
detectUART proc
mov dx,[IO_address]
or dx,dx
jz @@noUART
add dx,4 ; {3FCh} MCR (modem ctrl reg)
in ax,dx ; {3FDh} LSR (line status reg)
test al,11100000b
jnz @@noUART ; nonzero reserved bits
inc dx
in al,dx ; {3FDh} LSR (line status reg)
inc ax
jz @@noUART ; AX=0FFFFh
dec dx
dec dx
mov al,00011011b ; =1Bh
cli
out dx,al ; {3FBh} LCR: DLAB off, even
in al,dx ; parity, stop=1, length=8
mov ah,al
mov al,00000011b ; =3
out dx,al ; {3FBh} LCR: DLAB off, no
in al,dx ; parity, stop=1, length=8
cmp ax,0001101100000011b
jne @@noUART
dec dx
dec dx
in al,dx ; {3F9h} IER (int enable reg)
test al,11110000b
jnz @@noUART ; nonzero reserved bits
;----------
xor bx,bx ; UART=pure 8250
add dx,6
mov al,055h
out dx,al ; {3FFh} SCR (scratch reg)
in al,dx
mov ah,al
mov al,0AAh
out dx,al ; {3FFh} SCR (scratch reg)
in al,dx
cmp ax,055AAh
jne @@UARTret
inc bx ; UART=16450
sub dx,5
mov al,11000111b
out dx,al ; {3FAh} FCR: enable FIFO
in al,dx ; {3FAh} IIR (intr id reg)
mov ah,al
mov al,0
out dx,al ; {3FAh} FCR: disable FIFO
test ah,11000000b
jz @@UARTret
inc bx ; UART=16550
test ah,01000000b
jz @@UARTret
inc bx ; UART=16550A
@@UARTret: sti
clc
ret
@@noUART: sti
stc
ret
detectUART endp
;███████████████████████████████ IRQ HANDLER ██████████████████████████████
findIRQ proc
mov [IRQ_line],0
call setIRQs
call triggerIRQ
call unsetIRQs
mov al,[IRQ_line]
ret
findIRQ endp
;▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
setIRQs proc
mov si,offset DGROUP:IRQentrytable
@@setIRQloop: lodsw
or ax,ax
jz @@setIRQret
push ax
mov ah,35h
int 21h ; get INT in ES:BX
lodsw
mov dx,ax
add ax,IRQoldshift
xchg di,ax ; OPTIMIZE: instead MOV DI,AX
pop ax
;movSeg ds,cs
mov di[0],bx
mov di[2],es
int 21h ; set INT in DS:DX
j @@setIRQloop
@@setIRQret: in al,21h
mov PIC[0],al
and al,not 11111100b
out 21h,al
;* in al,0A1h
;* mov PIC[1],al
;* and al,not 11111111b
;* out 0A1h,al
ret
setIRQs endp
;▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
unsetIRQs proc
mov si,offset DGROUP:IRQentrytable
@@unsetIRQloop: lodsw
or ax,ax
jz @@unsetIRQret
push ds ax
lodsw
add ax,IRQoldshift
xchg di,ax ; OPTIMIZE: instead MOV DI,AX
mov dx,di[0]
mov ds,di[2]
pop ax
int 21h ; set INT in DS:DX
pop ds
j @@unsetIRQloop
@@unsetIRQret: mov al,PIC[0]
out 21h,al
;* mov al,PIC[1]
;* out 0A1h,al
ret
unsetIRQs endp
;▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
triggerIRQ proc
mov cx,[IO_address]
mov dx,cx
add dx,3
mov al,83h
out dx,al ; {3FBh} LCR: DLAB on
xchg dx,cx
mov ax,12 ; 9600 baud rate
out dx,ax ; {3F8h},{3F9h} divisor latch
xchg dx,cx
mov ax,0803h ; {3FBh} LCR: DLAB off
out dx,ax ; {3FCh} MCR: DTR/RTS off, OUT2 on
;* inc dx
;* inc dx ; {3FDh} LSR: clear error bits
;* in ax,dx ; {3FEh} MSR: clear state bits
mov dx,cx
;* in al,dx ; {3F8h} flush receive buffer
inc dx
mov al,2
out dx,al ; {3F9h} IER: enable THRE intr
;* call delay
;* out dx,al ; {3F9h} IER: enable THRE intr
dec dx
out dx,al ; {3F8h} transmitter hold reg
call delay
inc dx
mov al,0
out dx,al ; {3F9h} IER: interrupts off
add dx,3
;mov al,0
out dx,al ; {3FCh} MCR: DTR/RTS/OUT2 off
ret
triggerIRQ endp
;▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
delay proc
xor bx,bx
mov es,bx
call @@timeloop
@@timeloop: mov bx,es:[46Ch]
@@tickwait: cmp bx,es:[46Ch]
je @@tickwait ; wait timer tick change
@ret: ret
delay endp
;▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
IRQhandler proc
push ax dx
db 0BAh ; MOV DX,word
IO_address dw ? ; COM port IO address
push dx
inc dx
inc dx
in al,dx ; {3FAh} IIR (intr id reg)
push ax
add dx,3 ; {3FDh} LSR: clear error bits
in ax,dx ; {3FEh} MSR: clear state bits
pop ax dx
shr al,1
in al,dx ; {3F8h} flush receive buffer
pop dx ax
jc @ret ; exit if no intr pending
mov cs:[IRQ_line],al
mov al,20h
out 20h,al
;* out 0A0h,al
pop ax ax
iret
IRQhandler endp
;▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
IRQentry macro irq_no,int_no
.data
dw 2500h+int_no,offset DGROUP:IRQ&irq_no
.code
IRQ&irq_no proc
push ax
mov al,irq_no
call IRQhandler
pop ax
db 0EAh ; JMP FAR to old handler
IRQoldshift = $-IRQ&irq_no
dd ?
IRQ&irq_no endp
endm
.data
IRQentrytable label
IRP irq,<2,3,4,5,6,7>
IRQentry irq,irq+8
ENDM
;*IRP irq,<8,9,10,11,12,13,14,15,0>
;* IRQentry irq,irq+68h
;*ENDM
.data
dw 0
;██████████████████████████████████████████████████████████████████████████
end start