This file contains the assembler version of the procedure 'detect_IRQ'. Mike Surikov wrote the C source, and I've translated it to assembly language. Simply adjust BASEADDR, assemble it (with MASM or TASM) and run the .EXE file you get. Chris ----8<--------8<--------8<--------8<--------8<--------8<--------8<---- model small BASEADDR equ 03f8h .data? mask db ? irq db ? imr db ? ier db ? lcr db ? mcr db ? .data nonetext db "NONE$" irqtext db "IRQ level $" .code detect_IRQ proc near ; Call this routine with the base address of the UART ; in DX. It returns the interrupt level in AX or -1 ; if none. ; No registers except AX and flags are changed. push bx push dx cli ; disable interrupts add dx,3 ; DX points to the LCR in al,dx ; read LCR mov lcr,al ; and store it for later use and al,7fh ; clear DLAB out dx,al ; and rewrite value of LCR sub dx,2 ; DX points to the IER in al,dx ; read IER mov ier,al ; and store it for later use xor al,al ; disable all UART interrupts out dx,al ; separately add dx,3 ; DX now points to the MCR in al,dx ; read the MCR mov mcr,al ; and store its value and al,NOT 10h ; clear the loopback bit or al,0ch ; and allow UART interrupts out dx,al ; and write this value back in al,21h ; get the interrupt mask register mov imr,al ; and store its value mov al,0ah ; prepare to read the IRR of out 20h,al ; the ICU ; at this point the transmitter must already be empty mov bl,0fch ; the mask for IRQ 2-7 sub dx,3 ; DX now points to the IER mov al,2 ; allow 'Transmitter Empty' out dx,al ; interrupts in al,20h ; check if an interrupt request and bl,al ; appeared xor al,al ; disable 'Transmitter Empty' out dx,al ; interrupt again in al,20h ; check if the interrupt request not al ; disappeared again and bl,al mov al,2 ; enable 'Transmitter Empty' out dx,al ; interrupt again in al,20h ; and check again if it appeared and al,bl ; in the ICU not al out 21h,al ; unmask the interrupt found yet mov al,0ch ; enter the poll mode of the ICU out 20h,al in al,20h ; accept the interrupt (we get mov bl,al ; the int level in bit 0-2) ; now clear all possible int sources add dx,4 ; DX now points to the LSR in al,dx sub dx,5 ; DX now points to the RBR in al,dx add dx,2 ; DX now points to the IIR in al,dx add dx,4 ; DX now points to the MSR in al,dx mov al,ier ; restore old value of the IER sub dx,5 ; DX now points to the IER out dx,al mov al,lcr ; restore old value of the LCR add dx,2 ; DX now points to the LCR out dx,al mov al,mcr ; restore old value of the MCR inc dx ; DX now points to the MCR out dx,al mov al,20h ; signal end of poll mode out 20h,al ; to the ICU mov al,imr ; restore old interrupt mask out 21h,al sti ; and enable all interrupts again mov ax,-1 ; default: 'no int' test bl,80h ; see if any interrupt appeared jz det_int_1 mov ax,bx and ax,7 ; strip all bits we don't need det_int_1: pop dx pop bx ret detect_IRQ endp ; here we test it. start: mov ax,DGROUP mov ds,ax mov dx,BASEADDR call detect_IRQ cmp ax,-1 jne not_none lea dx,nonetext mov ah,9 int 21h jmp end not_none: push ax lea dx,irqtext mov ah,9 int 21h pop dx add dl,'0' mov ah,2 int 21h end: mov ax,4c00h int 21h .stack 256 end start ---->8-------->8-------->8-------->8-------->8-------->8-------->8----