comment *

        Copyright (C) 1989 George A. Stanislav.
        All Rights Reserved.

        Purpose: Determine if a serial port uses the NS16550AN UART.
        Let user enter the port number on the command line, e.g.

                is16550 COM1, COM2

        Support ports COM1-COM4.

*

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;      Define port FIFO Control Register addresses
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

COM1    equ     03FAh
COM2    equ     02FAh
COM3    equ     03EAh   ; on most systems
COM4    equ     02EAh   ; on most systems as well

eos     macro

        db      13, 10, 10, '$'         ; end of string

endm

code    segment para public 'CODE'

        org     100h

        assume  cs:code, ds:code, es:code, ss:code

begin:
        jmp     start

copr    db      13, 27, '[2J', 13
        db      'Copyright (C) 1989 George A. Stanislav. ', 13, 10
        db      'All Rights Reserved.', 13, 10, 10, '$', 8, ' ', 13, 26
comsg   db      'COM'
comno   db      '1: $'
is16    db      'NS16550 detected. Suggested replacement: NS16550AN.'
        eos
is16AN  db      "NS16550AN or equivalent detected. You're in good shape."
        eos
isnot   db      'NS16550 NOT detected. If buffering is needed, replacement'
        db      13, 10, '      with an NS16550AN is suggested.'
        eos
dunno   db      "Couldn't determine."
        eos
noport  db      'No UART/serial port detected.'
        eos

results dw      isnot
        dw      dunno
        dw      is16
        dw      is16AN

ports   dw      COM1
        dw      COM2
        dw      COM3
        dw      COM4

flag    db      0

start:

        lea     dx, copr
        mov     ah, 9
        int     21h

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;      Figure out and process command line parameters
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

        mov     si, 80h         ; address of parameters
        lodsb                   ; size of parameters
        sub     ah, ah
        mov     cx, ax          ; good for a loop as well as JCXZ

        jcxz    default         ; no parameters, deefault to COM1

bigloop:

        lodsb                   ; read next character from command line

        cmp     al, '1'         ; skip anything but '1' - '4'
        jb      nextchar

        cmp     al, '4'
        ja      nextchar

        mov     byte ptr comno, al
        sub     al, '1'
        call    main

nextchar:
        loop    bigloop
        cmp     byte ptr flag, 0        ; did we do anything?
        je      default                 ; nope, use default

done:
        mov     ax, 4C00h
        int     21h                     ; exit

default:
        sub     al, al
        call    main
        jmp     done


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;      Main procedure. Test for the 16550 chip.
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

main    proc    near

        push    cx

        cbw
        shl     ax, 1                   ; word pointer
        mov     bx, ax
        push    word ptr ports[bx]      ; put port address on stack

        lea     dx, comsg
        mov     ah, 9
        int     21h

        pop     dx              ; restore port address

; Save the original value in the UART register inasmuch as possible

        in      al, dx
        mov     di, ax

; Try to turn the FIFO buffering on

        mov     al, 0C1h
        out     dx, al

; Check if FIFO buffering is on

        in      al, dx

; Restore original value, save this one in BX

        mov     bl, al
        mov     ax, di
        out     dx, al

; Our answer is hidden in bits 6 and 7 of BL. The values are:
;
;       00      = no 16550
;       10      = 16550
;       11      = 16550A
;
; However, if BL = FF, there is probably no serial port at that address
;
        lea     dx, noport
        cmp     bl, 0FFh
        je      printit
        and     bx, 11000000b   ; clean up everything else
        mov     cl, 5
        shr     bx, cl  ; convert to pointer

        mov     dx, results[bx]
printit:
        mov     ah, 9
        int     21h

        or      byte ptr flag, 1

        pop     cx
        ret

main    endp

code    ends

        end     begin

