page ,132

; masm tisr ; >err
	.286p
.xlist
include ..\..\include\bogus.inc
.list


Words struc
LoWord dw ?
HiWord dw ?
Words ends

EOI equ 020h			; EOI command for PIC

INTA00 equ 020h 		; Master PIC control
INTA01 equ 021h 		; Master PIC mask register
INT_MASTER_0 equ 08h		; Master PIC INT number

INTB00 equ 0A0h 		; Slave PIC control
INTB01 equ 0A1h 		; Slave PIC mask register
INT_SLAVE_0 EQU 70h		; Slave PIC INT number

;
; Set variables for our interrupt number
;
ife (FAKE_IRQ GE 8)
INT_DEV equ (INT_MASTER_0+(FAKE_IRQ AND 7))
PIC00 equ INTA00
PIC01 equ INTA01
else
INT_DEV equ (INT_SLAVE_0+(FAKE_IRQ AND 7))
INT_MASK equ 1 SHL (FAKE_IRQ AND 7)
PIC00 equ INTB00
PIC01 equ INTB01
endif

page
CONST SEGMENT DWORD PUBLIC 'DATA'
sdNoBogus db 'I do not see the bogus device.',0dh,0ah,'$'
sdPrompt db 0Dh,0Ah,'S)tart, or Q)uit: ','$'
sdCRLF	db 0Dh,0Ah,'$'
sdDot	db '.','$'

CONST ENDS

DATA SEGMENT DWORD PUBLIC 'DATA'
dwCount1 dw 0
dwCount2 dw 0
lpPrevISR dd 0		    ; address of prior ISR
fStopping db 0		    ; TRUE when stopping
DATA ENDS

STACK SEGMENT DWORD STACK 'STACK'
    db	512 dup (?)
STACK ENDS

DGroup GROUP CONST,DATA,STACK

page

;IP	IntSvcRtn - The Interrupt Service Routine
;
;	WARNINGS
;
;	NOTES
;	    This ISR generally increments an interrupt count (dwCount1)
;	    and re-arms the device.
;
;	    If the "fStopping" flag is set, the device is not re-armed.
;

FIXED_TEXT SEGMENT PARA PUBLIC 'CODE'
segData1    dw	DGroup
	assume	CS:FIXED_TEXT,DS:NOTHING
IntSvcRtn proc far
	push	ax
	push	dx
	push	ds
	mov	ds,segData1
	assume	ds:DGroup
	inc	dwCount1
	mov	al,NOT FAKE_CTL_EOI
	mov	dx,FAKE_PORT
	out	dx,al			; send EOI to device
	mov	al,EOI
	out	PIC00,al		; send EOI to PIC
ife (PIC00 EQ INTA00)
	out	INTA00,al		; send EOI to master PIC, too
endif
	cmp	fStopping,0		; exiting?
	jnz	isr9			; if so, then don't restart
	mov	al,NOT FAKE_CTL_START
	mov	dx,FAKE_PORT
	out	dx,al			; restart I/O
isr9:
	pop	ds
	assume	ds:NOTHING
	pop	dx
	pop	ax
	iret
IntSvcRtn endp

FIXED_TEXT ENDS

page
;IP	__main - program entry point
;
;	NOTES
;	    The user is prompted to S)tart or Q)uit the program.  If
;	    "S" is selected, the programs enables interrupts and arms
;	    the device, printing out a dot each time the device interrupts.
;

_TEXT SEGMENT PARA PUBLIC 'CODE'
segData2    dw	DGroup
segFixed    dw	FIXED_TEXT
	assume	cs:_TEXT,ds:NOTHING

__main label far
	mov	ds,segData2		; Initialize default data segment
	assume	ds:DGroup

	mov	dx,FAKE_PORT
	in	al,dx		    ; Is the bogus device present ?
	or	al,al
	jns	ml0		    ; skip if so
	mov	dx,OFFSET DGroup:sdNoBogus
	mov	ah,9
	int	21h		    ; else print error message
	mov	ax,4C01h
	int	21h		    ; and exit

ml0:
	mov	ax,3500h+INT_DEV
	cli
	int	21h		    ; Query the current ISR
	mov	lpPrevISR.LoWord,bx
	mov	lpPrevISR.HiWord,es ; Save it

	mov	dx,OFFSET FIXED_TEXT:IntSvcRtn
	push	ds
	mov	ds,segFixed
	assume	ds:NOTHING
	mov	ax,2500h+INT_DEV
	int	21h		    ; Set our ISR
	pop	ds
	assume	ds:DGroup
	sti

	mov	dx,OFFSET DGroup:sdPrompt
	mov	ah,9
	int	21h		    ; "S)tart or Q)uit

ml1:
	mov	dl,0FFh
	mov	ah,6
	int	21h		    ; read from console, nowait
	jz	ml3
	or	al,40h
	cmp	al,'q'
	je	ml8		    ; skip if "Q" pressed
	cmp	al,'s'
	jne	ml3		    ; skip if "S" not pressed
	cli
	in	al,PIC01	    ; unmask the interrupt
	and	al,NOT INT_MASK
	out	PIC01,al
	sti
	mov	al,NOT FAKE_CTL_START
	mov	dx,FAKE_PORT
	out	dx,al		    ; start device I/O
ml3:
	mov	ax,dwCount1
	cmp	ax,dwCount2
	je	ml4		    ; skip if the count of interrupts unchanged
	mov	dwCount2,ax
	mov	dx,OFFSET DGroup:sdDot
	mov	ah,9
	int	21h		    ; else, display a dot
ml4:
	jmp	ml1		    ; loop for more

ml8:
	mov	fStopping,1	    ; Tell the ISR to stop
	mov	dx,FAKE_PORT
ml9:
	in	al,dx
	rcr	al,1
	jnc	ml9		    ; loop while busy

	cli
	in	al,PIC01
	or	al,INT_MASK
	out	PIC01,al	    ; mask the interrupt level
	sti

	push	ds
	lds	dx,lpPrevISR
	assume	ds:NOTHING
	mov	ax,2500h+INT_DEV
	int	21h		    ; restore the previous ISR
	pop	ds
	assume	ds:DGroup
	mov	ax,4C00h
	int	21h		    ; exit
_TEXT ENDS

	end	__main
