home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 8 Other / 08-Other.zip / comtest.zip / COMTEST.ASM next >
Assembly Source File  |  2000-11-23  |  9KB  |  410 lines

  1. ; COMTEST - Find COMs port type and associated IRQ line
  2. ; Copyright (c) 1997-2000 Arkady Belousov <ark@mos.ru>
  3. ;
  4. ; This program is free software; you can redistribute it and/or modify
  5. ; it under the terms of the GNU General Public License as published by
  6. ; the Free Software Foundation; either version 2 of the License, or
  7. ; (at your option) any later version.
  8. ;
  9. ; This program is distributed in the hope that it will be useful,
  10. ; but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. ; GNU General Public License for more details.
  13. ;
  14. ; You should have received a copy of the GNU General Public License
  15. ; along with this program; if not, write to the Free Software
  16. ; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  17. ;
  18.  
  19. WARN
  20. .model tiny
  21.  
  22. j        equ    jmp short
  23.  
  24. movSeg        macro    dest,src
  25.         push    src
  26.         pop    dest
  27.     endm
  28.  
  29. PrintS        macro    addr
  30.     IFNB <addr>
  31.      IFDIFI <addr>,<dx>
  32.         mov    dx,offset addr
  33.      ENDIF
  34.     ENDIF
  35.         mov    ah,9
  36.         int    21h
  37.     endm
  38.  
  39.  
  40. ;██████████████████████████████ DATA SEGMENT ██████████████████████████████
  41.  
  42. .data
  43.  
  44. PIC        db    ?,?
  45. IRQ_line    db    ?
  46.  
  47. S_header    db    'COMTEST v1.0 Copyright (c) 2000 by Arkady V.Belousov',0dh,0ah
  48.         db    0dh,0ah
  49.         db    'COM Addr IRQ# Comments',0dh,0ah
  50.         db    '--- ---- ---- --------'
  51. CRLF        db    0dh,0ah,'$'
  52. S_port        db    ' '
  53. S_COMno        db     '   '
  54. S_IOaddr    db        '      $'
  55. S_none        db          '    not present$'
  56. S_8250        db          '    8250 (no FIFO)$'
  57. S_8250A        db          '    8250A/16450 (no FIFO)$'
  58. S_16550        db          '    16550 (buggy FIFO)$'
  59. S_16550A    db          '    16550A (with FIFO)$'
  60.  
  61. UARTtable    dw    offset DGROUP:S_8250
  62.         dw    offset DGROUP:S_8250A
  63.         dw    offset DGROUP:S_16550
  64.         dw    offset DGROUP:S_16550A
  65.  
  66.  
  67. ;██████████████████████████████ CODE SEGMENT ██████████████████████████████
  68.  
  69. .code
  70.         org    100h
  71. start:        cld
  72.         PrintS    DGROUP:S_header
  73.         mov    ax,1Fh            ; disable mouse
  74.         call    mousedrv
  75.  
  76.         xor    ax,ax
  77. @@comloop:    push    ax
  78.  
  79. ;---------- get COM port IO address
  80.         xor    bx,bx
  81.         mov    es,bx
  82.         mov    bl,al
  83.         add    al,'1'
  84.         mov    [S_COMno],al
  85.         shl    bx,1
  86.         mov    ax,es:400h[bx]
  87.         mov    [IO_address],ax
  88.  
  89. ;---------- convert IO address into string
  90.         movSeg    es,ds
  91.         mov    di,offset DGROUP:S_IOaddr
  92.         mov    cl,12
  93. @@loophexw:    push    ax
  94.         shr    ax,cl
  95.         and    al,0Fh
  96.         cmp    al,10
  97.         sbb    al,69h
  98.         das
  99.         stosb
  100.         pop    ax
  101.         sub    cl,4
  102.         jae    @@loophexw
  103.  
  104. ;---------- detect UART type and IRQ line
  105.         PrintS    DGROUP:S_port
  106.         call    detectUART
  107.         mov    dx,offset DGROUP:S_none
  108.         jc    @@nextCOM
  109.  
  110.         push    bx
  111.         call    findIRQ
  112.         pop    bx
  113.         shl    bx,1
  114.         mov    bx,UARTtable[bx]
  115.         mov    ah,' '
  116.         add    al,'0'
  117.         cmp    al,'0'
  118.         jne    @@saveIRQno
  119.         mov    al,'?'
  120. @@saveIRQno:    xchg    al,ah
  121.         mov    [bx],ax
  122.         mov    dx,bx
  123.  
  124. ;---------- get next COM port
  125. @@nextCOM:    PrintS
  126.         PrintS    CRLF
  127.         pop    ax
  128.         inc    ax            ; OPTIMIZE: AX instead AL
  129.         cmp    al,4
  130.         jb    @@comloop
  131.  
  132. ;---------- reset mouse and exit
  133.         xor    ax,ax
  134.         call    mousedrv
  135.         int    20h
  136.  
  137. ;▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
  138.  
  139. mousedrv    proc
  140.         push    ax
  141.         mov    ax,3533h
  142.         int    21h
  143.         pop    ax
  144.         mov    cx,es
  145.         jcxz    @@mouseret
  146.         int    33h
  147. @@mouseret:    ret
  148. mousedrv    endp
  149.  
  150. ;▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
  151. ;            Detect UART presence and type
  152. ;▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
  153. ;
  154. ; In:    none
  155. ; Out:    Carry flag            (no UART detected)
  156. ;    BX                (UART type: 0=8250, 1=8250A/16450,
  157. ;                     2=16550, 3=16550A)
  158. ; Use:    IO_address
  159. ; Modf:    AX, DX
  160. ; Call:    none
  161. ;
  162. detectUART    proc
  163.         mov    dx,[IO_address]
  164.         or    dx,dx
  165.         jz    @@noUART
  166.  
  167.         add    dx,4            ; {3FCh} MCR (modem ctrl reg)
  168.         in    ax,dx            ; {3FDh} LSR (line status reg)
  169.         test    al,11100000b
  170.         jnz    @@noUART        ; nonzero reserved bits
  171.         inc    dx
  172.         in    al,dx            ; {3FDh} LSR (line status reg)
  173.         inc    ax
  174.         jz    @@noUART        ; AX=0FFFFh
  175.  
  176.         dec    dx
  177.         dec    dx
  178.         mov    al,00011011b        ; =1Bh
  179.         cli
  180.         out    dx,al            ; {3FBh} LCR: DLAB off, even
  181.         in    al,dx            ;  parity, stop=1, length=8
  182.         mov    ah,al
  183.         mov    al,00000011b        ; =3
  184.         out    dx,al            ; {3FBh} LCR: DLAB off, no
  185.         in    al,dx            ;  parity, stop=1, length=8
  186.         cmp    ax,0001101100000011b
  187.         jne    @@noUART
  188.  
  189.         dec    dx
  190.         dec    dx
  191.         in    al,dx            ; {3F9h} IER (int enable reg)
  192.         test    al,11110000b
  193.         jnz    @@noUART        ; nonzero reserved bits
  194. ;----------
  195.         xor    bx,bx            ; UART=pure 8250
  196.         add    dx,6
  197.         mov    al,055h
  198.         out    dx,al            ; {3FFh} SCR (scratch reg)
  199.         in    al,dx
  200.         mov    ah,al
  201.         mov    al,0AAh
  202.         out    dx,al            ; {3FFh} SCR (scratch reg)
  203.         in    al,dx
  204.         cmp    ax,055AAh
  205.         jne    @@UARTret
  206.  
  207.         inc    bx            ; UART=16450
  208.         sub    dx,5
  209.         mov    al,11000111b
  210.         out    dx,al            ; {3FAh} FCR: enable FIFO
  211.         in    al,dx            ; {3FAh} IIR (intr id reg)
  212.         mov    ah,al
  213.         mov    al,0
  214.         out    dx,al            ; {3FAh} FCR: disable FIFO
  215.         test    ah,11000000b
  216.         jz    @@UARTret
  217.         inc    bx            ; UART=16550
  218.         test    ah,01000000b
  219.         jz    @@UARTret
  220.         inc    bx            ; UART=16550A
  221. @@UARTret:    sti
  222.         clc
  223.         ret
  224. @@noUART:    sti
  225.         stc
  226.         ret
  227. detectUART    endp
  228.  
  229.  
  230. ;███████████████████████████████ IRQ HANDLER ██████████████████████████████
  231.  
  232. findIRQ        proc
  233.         mov    [IRQ_line],0
  234.         call    setIRQs
  235.         call    triggerIRQ
  236.         call    unsetIRQs
  237.         mov    al,[IRQ_line]
  238.         ret
  239. findIRQ        endp
  240.  
  241. ;▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
  242.  
  243. setIRQs        proc
  244.         mov    si,offset DGROUP:IRQentrytable
  245. @@setIRQloop:    lodsw
  246.         or    ax,ax
  247.         jz    @@setIRQret
  248.         push    ax
  249.         mov    ah,35h
  250.         int    21h            ; get INT in ES:BX
  251.         lodsw
  252.         mov    dx,ax
  253.         add    ax,IRQoldshift
  254.         xchg    di,ax            ; OPTIMIZE: instead MOV DI,AX
  255.         pop    ax
  256.         ;movSeg    ds,cs
  257.         mov    di[0],bx
  258.         mov    di[2],es
  259.         int    21h            ; set INT in DS:DX
  260.         j    @@setIRQloop
  261.  
  262. @@setIRQret:    in    al,21h
  263.         mov    PIC[0],al
  264.         and    al,not 11111100b
  265.         out    21h,al
  266. ;*        in    al,0A1h
  267. ;*        mov    PIC[1],al
  268. ;*        and    al,not 11111111b
  269. ;*        out    0A1h,al
  270.         ret
  271. setIRQs        endp
  272.  
  273. ;▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
  274.  
  275. unsetIRQs    proc
  276.         mov    si,offset DGROUP:IRQentrytable
  277. @@unsetIRQloop:    lodsw
  278.         or    ax,ax
  279.         jz    @@unsetIRQret
  280.         push    ds ax
  281.         lodsw
  282.         add    ax,IRQoldshift
  283.         xchg    di,ax            ; OPTIMIZE: instead MOV DI,AX
  284.         mov    dx,di[0]
  285.         mov    ds,di[2]
  286.         pop    ax
  287.         int    21h            ; set INT in DS:DX
  288.         pop    ds
  289.         j    @@unsetIRQloop
  290.  
  291. @@unsetIRQret:    mov    al,PIC[0]
  292.         out    21h,al
  293. ;*        mov    al,PIC[1]
  294. ;*        out    0A1h,al
  295.         ret
  296. unsetIRQs    endp
  297.  
  298. ;▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
  299.  
  300. triggerIRQ    proc
  301.         mov    cx,[IO_address]
  302.         mov    dx,cx
  303.         add    dx,3
  304.         mov    al,83h
  305.         out    dx,al            ; {3FBh} LCR: DLAB on
  306.         xchg    dx,cx
  307.         mov    ax,12            ; 9600 baud rate
  308.         out    dx,ax            ; {3F8h},{3F9h} divisor latch
  309.  
  310.         xchg    dx,cx
  311.         mov    ax,0803h        ; {3FBh} LCR: DLAB off
  312.         out    dx,ax            ; {3FCh} MCR: DTR/RTS off, OUT2 on
  313.  
  314. ;*        inc    dx
  315. ;*        inc    dx            ; {3FDh} LSR: clear error bits
  316. ;*        in    ax,dx            ; {3FEh} MSR: clear state bits
  317.         mov    dx,cx
  318. ;*        in    al,dx            ; {3F8h} flush receive buffer
  319.  
  320.         inc    dx
  321.         mov    al,2
  322.         out    dx,al            ; {3F9h} IER: enable THRE intr
  323. ;*        call    delay
  324. ;*        out    dx,al            ; {3F9h} IER: enable THRE intr
  325.  
  326.         dec    dx
  327.         out    dx,al            ; {3F8h} transmitter hold reg
  328.         call    delay
  329.  
  330.         inc    dx
  331.         mov    al,0
  332.         out    dx,al            ; {3F9h} IER: interrupts off
  333.         add    dx,3
  334.         ;mov    al,0
  335.         out    dx,al            ; {3FCh} MCR: DTR/RTS/OUT2 off
  336.         ret
  337. triggerIRQ    endp
  338.  
  339. ;▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
  340.  
  341. delay        proc
  342.         xor    bx,bx
  343.         mov    es,bx
  344.         call    @@timeloop
  345. @@timeloop:    mov    bx,es:[46Ch]
  346. @@tickwait:    cmp    bx,es:[46Ch]
  347.         je    @@tickwait        ; wait timer tick change
  348. @ret:        ret
  349. delay        endp
  350.  
  351. ;▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
  352.  
  353. IRQhandler    proc
  354.         push    ax dx
  355.         db    0BAh            ; MOV DX,word
  356. IO_address    dw    ?            ; COM port IO address
  357.         push    dx
  358.         inc    dx
  359.         inc    dx
  360.         in    al,dx            ; {3FAh} IIR (intr id reg)
  361.         push    ax
  362.         add    dx,3            ; {3FDh} LSR: clear error bits
  363.         in    ax,dx            ; {3FEh} MSR: clear state bits
  364.         pop    ax dx
  365.         shr    al,1
  366.         in    al,dx            ; {3F8h} flush receive buffer
  367.         pop    dx ax
  368.         jc    @ret            ; exit if no intr pending
  369.  
  370.         mov    cs:[IRQ_line],al
  371.         mov    al,20h
  372.         out    20h,al
  373. ;*        out    0A0h,al
  374.         pop    ax ax
  375.         iret
  376. IRQhandler    endp
  377.  
  378. ;▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
  379.  
  380. IRQentry    macro    irq_no,int_no
  381.         .data
  382.         dw    2500h+int_no,offset DGROUP:IRQ&irq_no
  383.         .code
  384. IRQ&irq_no    proc
  385.         push    ax
  386.         mov    al,irq_no
  387.         call    IRQhandler
  388.         pop    ax
  389.         db    0EAh            ; JMP FAR to old handler
  390. IRQoldshift = $-IRQ&irq_no
  391.         dd    ?
  392. IRQ&irq_no    endp
  393.     endm
  394.  
  395. .data
  396. IRQentrytable    label
  397. IRP irq,<2,3,4,5,6,7>
  398.     IRQentry irq,irq+8
  399. ENDM
  400. ;*IRP irq,<8,9,10,11,12,13,14,15,0>
  401. ;*    IRQentry irq,irq+68h
  402. ;*ENDM
  403. .data
  404.         dw    0
  405.  
  406.  
  407. ;██████████████████████████████████████████████████████████████████████████
  408.  
  409.         end    start
  410.