home *** CD-ROM | disk | FTP | other *** search
- ; ************
- ; * OISR.asm *
- ; *******************************************
- ; * Copyright TimeSlice, Inc. 1985, 86, 87. *
- ; *******************************************
- ;
- include ts.inc
- ;
- start_data ;to define DGROUP properly
- ;
- end_data
- ;
- start_code
- ;
- ;
- ;*********
- ;* OISR( INTLST, REGOFF, REGSEG ) - This function is called within an
- ;* attached ISR to invoke the original ISR
- ;*********
- start_struct
- mbr isrobp d_int ;saved BP
- ifdef MICROSOFT
- mbr isrodi d_int ;save SI,DI
- mbr isrosi d_int
- endif
- mbr isroflg d_int ;saved flags
- mbr isroret d_ret ;return address to ISR code
- mbr isroilp d_ptr ;ptr to ISR's INTLST
- mbr isrorof d_int ;ptr to ISR' INTSTATE
- mbr isrorsg d_int ; " " " "
- end_struct isrostk
- ;
- start_struct
- mbr osavsp d_int ;current SP in itsk (really BP)
- mbr osavss d_int ;current SS
- mbr osavipi d_int ;ISR's IP
- mbr osavcsi d_int ;ISR's CS
- mbr osavipa d_int ;intrpted appl. IP
- mbr osavcsa d_int ;intrpted appl. CS
- mbr osavfl d_int ;flags
- end_struct isrosav
- ;
- routine oisr
- pushf ;and flags
- push_sdi ;save SI, DI
- push bp ;save BP
- mov bp,sp
- cli ;hold interrupts
- ;
- ; set address of OISR in call instruction
- ;
- ldptr es,si,[bp].isroilp,d
- mov di,offset oisr0
- ldint ax,es:[si].oisrip
- mov cs:[di],ax
- ldint ax,es:[si].oisrcs
- mov cs:[di+2],ax
- ;
- ; allocate on ISTK space to save a OISRSAV structure
- ;
- mov di,_istop.off
- sub di,isrosav
- mov _istop.off,di
- ;
- ; save FlagCsIpCsIp information in [di] (small space just allocated)
- ;
- mov ax,ds ;make sure ES contains DGROUP
- mov es,ax
- mov [di].osavsp,bp
- mov ax,ss
- mov [di].osavss,ax
- add di,4 ;make di point at isripi
- mov si,[bp].isrorof ;DS:SI <- isr's intstate
- mov ax,[bp].isrorsg
- mov ds,ax
- add si,intstate - isrosav + osavipi ;addr of FCICI
- mov cx,(isrosav - osavipi) / 2
- cld
- repz movsw
- mov ax,es ;restore DS to DGROUP
- mov ds,ax
- ;
- ; switch stack to interrupted code stack
- ;
- ldint ax,[bp].isrorof
- ldint bx,[bp].isrorsg
- mov sp,ax
- mov ss,bx
- ;
- ; load CPU flags with interrupted code's flags, and also set cli bit
- ; in flags left on stack. That is necessary to avoid interrupts being
- ; enabled (temporarily) after the original ISR's IRET.
- ;
- mov bp,sp
- ldint ax,[bp].isflags ;AX <= flags as pushed on stack by int
- and ax,0FDFFH ;cli interrupt enable bit in ax
- stint [bp].isflags,ax ;cli the flags with wich origISR does the IRET
- ;
- ; restore all registers as upon entry and leave only flags (CLIed) and
- ; simulate the rest of the INT with a call.
- ;
- popa ;restore regs as upon entry
- add sp,8 ;leave only flags on stack (real and CLIed)
- popf
- pushf
- ;
- ; call original ISR
- ;
- db CALLFAR ;simulate interrupt
- oisr0: dw 0 ;real destination is updated 3 lines above
- dw 0
- ;
- ; now that original ISR has executed prepare to go back to calling ISR
- ; by reseting the stack the way it was when OISR() was called.
- ;
- pushf ;put back flags
- cli ;because some %#@%!! BIOS ROUTINES modify stack flags
- sub sp,8 ;restore interpted code's INTSTATE
- pusha
- mov ax,DGROUP ;restore data segment
- mov ds,ax
- mov bp,sp ;[bp] <-- return address of intmgr
- mov di,bp ;set DI to point at bottom of FCICI
- add di,intstate - isrosav + osavipi
- mov ax,ss ;restore to interrupt stack segment
- mov es,ax ;ES <- interptd stack segment
- mov si,_istop.off ;Restore information saved below istk
- mov sp,[si].osavsp
- mov ax,[si].osavss
- mov ss,ax
- add si,osavipi ;make si point to osavipi
- cld
- mov cx,(osavfl - osavipi) / 2 ;restore CICI only to INTSTATE
- repz movsw
- ;
- ; make sure to restore interrupt flag
- ;
- mov ax,[si] ;DS:SI points at the interrupt code flags
- and ax,200H
- jnz oisr1
- and es:[di],0FDFFH
- jmp oisr2
- oisr1: or es:[di], 0200H
- oisr2: add _istop.off,isrosav ;restore _istop
- ;
- ; restore flags and bp
- ;
- pop bp
- pop_sdi
- if not ldata
- push ds
- pop es
- endif
- popf
- return oisr
- ;
- end_code
-
-
-
-