TIP: Click on subject to list as thread! ANSI
echo: 80xxx
to: SYLVAIN LAUZON
from: JAN WAGEMAKERS
date: 1998-04-08 18:46:00
subject: to find a 16550

Hello Sylvain,
Sylvain Lauzon wrote to All :
 SL> A routine to find whether or not a 16550 installed.
Maybe the following program helps you. I have found it on a disk that was 
included with "the undocumented PC" book :
>>> File: /floppy/sertype.asm <<<
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;                           SERIAL TYPE
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;
;   Reports current serial port I/O addresses, checks the port
;   has a UART attached, and determines the basic chip type.
;
;   (c) Copyright 1994  Frank van Gilluwe  All Rights Reserved.
include undocpc.inc
cseg    segment para public
        assume  cs:cseg, ds:cseg
        org     100h               ; build as COM program
sertype proc   near
start:
        jmp     begin
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; DATA FOR SERTYPE
msg1    db      CR, LF, CR, LF, TAB, TAB
        db      ' SERTYPE - Serial Port Analysis'
        db      CR, LF, CR, LF, TAB
        db      ' Serial Port   Active?       Basic UART Type'
        db      CR, LF, TAB
        db      'ÄÄÄÄÄÄÄÄÄÄÄÄÄ  ÄÄÄÄÄÄ-  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ'
        db      CR, LF, '$'
msg2    db      TAB, '#'
msgnum  db       '1       '
msghigh dw      '  '  
msglow  dw      '  '      
        db                   '    '
msgact  db                       'No     '
uart    db                              '                         '
        db      CR, LF, '$' 
typemsg db      '                         '
typeend db      '8250                     '
        db      '8250A or 16450           '
        db      '16C1450                  '
        db      '16550 with defective FIFO'
        db      '16550AF/C/CF with FIFO   '       
        db      '16C1550 with FIFO        '
        db      '16552 dual UART with FIFO'
        db      '82510 with FIFO          '
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; start of code
begin:
        OUTMSG  msg1               ; initial message
        mov     cl, '1'            ; serial port to check
        mov     si, 0              ; index for serial addresses
ser_loop:
        mov     msgnum, cl         ; insert serial port number
        mov     msghigh, '  '
        mov     msglow, '  '       ; blank port number
        MSGNO   msgact             ; assume port not active
        mov     ax, 40h
        mov     es, ax             ; ES used for BIOS segment
        mov     dx, es:[si]        ; get serial port address
        mov     bl, 0              ; default flag to no UART
        cmp     dx, 0              ; port number present ?
        je      ser_uart           ; jump if not
        mov     bx, offset msghigh ; port number, high
        mov     al, dh             
        call    hex                ; convert to ASCII & insert
        mov     bx, offset msglow  ; port number, low
        mov     al, dl
        call    hex                ; convert to ASCII & insert
        call    testport           ; test that serial port is
                                   ;  there and chip type
        cmp     bl, 1              ; active port ?
        jb      ser_uart           ; jump if not
        MSGYES  msgact             ; serial port active
; transfer the text about which UART it is (bl= UART type)
ser_uart:
        push    cx
        push    si
        mov     cx, offset typeend - offset typemsg  ; bytes 
        mov     al, cl
        mul     bl                 ; ax = bl * al
        mov     si, ax
        add     si, offset typemsg ; ptr to UART string
        mov     di, offset uart
        push    cs
        pop     es
        cld
        rep     movsb              ; transfer string
        pop     si
        pop     cx
        OUTMSG  msg2               ; display info for one port
ser_next:
        add     si, 2              ; next index 
        inc     cl
        cmp     cl, '4'            ; are we done yet?
        ja      exit               ; jump if so
        jmp     ser_loop           ; try next port
exit:
        mov     ah, 4Ch
        int     21h                ; exit to DOS
sertype endp
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;    Testport
;       Check if the UART is responding and if so, test to
;       find out which chip it is equivalent to.
;
;       Called with:    dx = serial I/O port
;
;       Returns:        bl = chip type
;                            0 = no response, not a UART
;                            1 = 8250 (no scratch register)
;                            2 = 8250A or 16450
;                            3 = 16C1450
;                            4 = 16550 with defective FIFO
;                            5 = 16550AF/C/CF with FIFO
;                            6 = 16C1550 with FIFO
;                            7 = 16552 dual UART with FIFO
;                            8 = 82510 with FIFO
testport proc   near
        mov     bl, 0              ; return value if no-response
        mov     di, dx             ; save I/O port
        cli                        ; disable interrupts
        call    DLAB1              ; Divisor Latch Access bit=1
        mov     ah, 5Ah            ; test value 1
        call    IOtest             ; write value, read it and compare
        jne     test_exit2         ; exit if not valid
        mov     ah, 0A5h           ; test value 2
        call    IOtest             ; write value, read it and compare
        jne     test_exit2         ; exit if not valid
        sti                        ; enable interrupts
; now check if the scratch pad register is working (missing on 8250)
        inc     bl                 ; return 1 if 8250
        add     dx, 7              ; point to scratch pad register
        mov     ah, 5Ah            ; test value 1
        call    IOtest             ; write value, read it and compare
        jne     test_exit2         ; exit if no scatch register
        mov     ah, 0A5h           ; test value 2
        call    IOtest             ; write value, read it and compare
        je      scratch_ok
test_exit2:
        jmp     test_exit          ; exit if no scratch register
scratch_ok:
        mov     dx, di             ; restore base I/O port
; check for 1655x and 82510 FIFO versions
        cli                        ; disable interrupts
        add     dx, 2              ; interrupt ID register
        in      al, dx
        IODELAY
        and     al, 0C0h
        cmp     al, 0C0h           ; is 16550 FIFO already enabled ?
        je      is_1655x           ; jump if so
        mov     al, 1              ; try to enable FIFO on 1655x
        out     dx, al             ;  (if 82510 also set bank 0)
        IODELAY
        in      al, dx             ; read Interrupt Identification
        IODELAY
        mov     bh, al             ; save readback value
        mov     al, 0              ; Disable FIFO on 16550 or 
        out     dx, al             ;   select bank 0 on 82510
        IODELAY
        and     bh, 0C0h
        cmp     bh, 0C0h           ; was FIFO enabled on 16550 ?
        je      is_1655x           ; jump if so
        cmp     bh, 40h            ; FIFO UART in some PS/2s ?
        je      is_16550C
        cmp     bh, 80h            ; 16550 with defective FIFO ?
        je      is_16550
; not 16550, so now check for possible 82510 by switching to bank
;  3 (which is only possible on a 82510)
        mov     al, 60h            ; select bank 3
        out     dx, al
        IODELAY
        in      al, dx             ; read back from port
        IODELAY
        mov     bh, al             ; save for later
        mov     al, 0              ; if 83510, return to 
        out     dx, al             ;  bank 0
        IODELAY
        and     bh, 60h            ; now, did it goto bank 3?
        cmp     bh, 60h
        je      is_82510           ; jump if so (is 82510)
; no FIFO, so UART is 8250A or 16450 variant - Check if power down
;   bit functions on this UART, in the modem control register
no_FIFO:
        mov     dx, di
        add     dx, 4              ; select modem control register
        mov     al, 80h            ; see if power down mode allowable
        out     dx, al
        IODELAY
        in      al, dx             ; get modem register
        IODELAY
        mov     ah, al             ; save result
        mov     al, 0
        out     dx, al             ; turn power back on
        test    ah, 80h            ; did power down bit get set ?
        jnz     is_16C1450         ; jump if so
is_8250A:
        mov     bl, 2              ; set to 8250A/16450 UART
        jmp     test_exit
is_16C1450:
        mov     bl, 3              ; set to 16C1450 UART
        jmp     test_exit
is_16550:
        mov     bl, 4              ; set to 16550 with defective FIFO
        jmp     test_exit
; FIFO detected, and must be 16550 series 
is_1655x:
        mov     dx, di
        call    DLAB1
        add     dx, 2
        mov     ah, 7
        call    IOtest             ; write value, read it
        mov     bh, al             ; save result for later
        mov     al, 0              ; reset register select
        out     dx, al
        cmp     bh, 7              ; did it work ?
        je      is_16552           ; if compare ok, is 16552
; Check if power down bit functions on this UART, in the modem 
;   control register (only on 16C1550)
        mov     dx, di
        add     dx, 4              ; select modem control register
        mov     al, 80h            ; see if power down mode allowable
        out     dx, al
        IODELAY
        in      al, dx             ; get modem register
        IODELAY
        mov     ah, al             ; save result
        mov     al, 0
        out     dx, al             ; turn power back on
        test    ah, 80h            ; did power down bit get set ?
        jnz     is_16C1550         ; jump if so
is_16550C:
        mov     bl, 5              ; set to 16550AF/C/CF UART
        jmp     test_exit
is_16C1550:
        mov     bl, 6              ; set to 16C1550
        jmp     test_exit
is_16552:                          ; set to 16552 UART
        mov     bl, 7
        jmp     test_exit
is_82510:
        mov     bl, 8              ; set to 82510 UART
test_exit:
        mov     dx, di             ; restore base port value
        call    DLAB0              ; reset DLAB to 0
        sti                        ; enable interrupts in case off
        ret
testport endp
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;    DLAB1
;       Set the Divisor Latch Access Bit to 1 without 
;       changing other line control bits
;
;       Called with:    dx = serial I/O port
;
;       Regs Used:      al
DLAB1   proc    near
        push    dx
        add     dx, 3              ; point to Line Control Reg
        in      al, dx             ; get current state
        IODELAY
        or      al, 80h            ; set DLAB to 1
        out     dx, al
        pop     dx
        ret
DLAB1   endp
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;    DLAB0
;       Set the Divisor Latch Access Bit to 0 without 
;       changing other line control bits
;
;       Called with:    dx = serial I/O port
;
;       Regs Used:      al
DLAB0   proc    near
        push    dx
        add     dx, 3              ; point to Line Control Reg
        in      al, dx             ; get current state
        IODELAY
        and     al, 7Fh            ; set DLAB to 0
        out     dx, al
        pop     dx
        ret
DLAB0   endp
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;    IOtest
;       Write value al to port, then read back value and compare
;       to original value.
;
;       Called with:    ah = value to use for test
;                       dx = I/O port to test
;
;       Returns:        al = value read from port
;                       zero flag = 1 if register ok
IOtest  proc    near
        mov     al, ah             ; value to test
        out     dx, al             ; write value
        IODELAY
        in      al, dx             ; read back value
        IODELAY
        cmp     al, ah             ; compare if the same
        ret
IOtest  endp
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;    HEX
;       convert the hex number in al into two ascii characters
;       at ptr in bx
;
;       Called with:    al = input hex number
;                       bx = ptr where to put ascii
;
;       Regs Used:      al,bx
hex     proc    near
        push    bx
        mov     bl, al
        and     al, 0fh
        add     al, 90h
        daa
        adc     al, 40h
        daa
        mov     bh, al
        mov     al, bl             ; upper nibble
        shr     al, 1
        shr     al, 1
        shr     al, 1
        shr     al, 1
        and     al, 0fh
        add     al, 90h
        daa
        adc     al, 40h
        daa
        mov     bl, al
        mov     ax, bx
        pop     bx
        mov     [bx], ax           ; output ascii bytes
        ret
hex     endp
cseg    ends
        end     start
>>> EndFile <<<
Have a nice day Sylvain.		- Jan Wagemakers -
--- FEddy 1.1 via ifcico / Debian GNU Linux
---------------
* Origin: Many Glacier BBS [32-3-4480880] (2:292/854.19)

SOURCE: echomail via exec-pc

Email questions or comments to sysop@ipingthereforeiam.com
All parts of this website painstakingly hand-crafted in the U.S.A.!
IPTIA BBS/MUD/Terminal/Game Server List, © 2025 IPTIA Consulting™.