home *** CD-ROM | disk | FTP | other *** search
- ;TSRUTIL.ASM
-
- ;Define segment names used by C
- ;
- _TEXT segment byte public 'CODE'
- _TEXT ends
-
- CONST segment word public 'CONST'
- CONST ends
-
- _BSS segment word public 'BSS'
- _BSS ends
-
- _DATA segment word public 'DATA'
- _DATA ends
-
- DGROUP GROUP CONST, _BSS, _DATA
-
- assume CS:_TEXT, DS:DGROUP
-
- public _new_int13, _init_intr
- IFDEF MULTI
- public _timer_int_chain
- public _new_int10, _new_int25, _new_int26
- ELSE
- public _deinstall
- ENDIF
-
- extrn _ss_save:near ;save foreground SS
- extrn _sp_save:near ;save foreground SP
- extrn _unsafe_flag:near ;if true, don't interrupt
- extrn _old_int13:near
- IFDEF MULTI
- extrn _old_int8:near
- extrn _old_int10:near
- extrn _old_int25:near ; note difference between
- extrn _old_int26:near ; old_int25 and _old_int25!
- ELSE
- extrn _multiplex_id:near ;our int 2f id byte
- ENDIF
-
- _TEXT segment
-
- IFNDEF MULTI
- ;*****
- ;void far deinstall(void)
- ;function to use int 2f to ask TSR to deinstall itself
- ;the registers are probably all changed when our tsr exits
- ;so we save then and perform the INT 2f. The TSR exit will
- ;eventually bring us back here. Then the registers are restored
- ;This function is called from the foreground, not the TSR
-
- DEINSTALL equ 1
-
- _deinstall proc far
- push si
- push di
- push bp
- mov word ptr _ss_save,ss ;save our stack frame
- mov word ptr _sp_save,sp
-
- mov cs:_ds_save,ds ; save DS for later restore
-
- mov bx,cs
- mov dx,offset TerminateAddr ;bx:dx points to terminate address
- mov ah, byte ptr _multiplex_id
- mov al, DEINSTALL
- int 2fh ;call our TSR
- ;
- ;if TSR terminates ok, we'll skip this code and return to Terminate Addr
- ;
- jmp short NoTerminate
-
- TerminateAddr:
- ;Restore DS and stack
- mov ax,cs:_ds_save ;bring back our data segment
- mov ds,ax ;destroyed by int 2f
-
- mov al,2 ;Set value for success
-
- mov ss, word ptr _ss_save ;restore our stack
- mov sp, word ptr _sp_save ;destroyed by int 2f
-
- NoTerminate:
- cbw ;Extend return value to word
- pop bp
- pop di
- pop si
- ret
- _deinstall endp
- ENDIF
-
- ;*****
- ;void inc_unsafe_flag(void) - increment unsafe flag
- ;*****
- inc_unsafe_flag proc far
- push ax
- push ds
- mov ax,DGROUP ;make DS = to our TSR C data segment
- mov ds,ax
-
- inc word ptr _unsafe_flag
-
- pop ds ;put DS back to whatever it was
- pop ax
- ret
- inc_unsafe_flag endp
-
- ;*****
- ;void dec_unsafe_flag(void) - decrement unsafe flag
- ;*****
- dec_unsafe_flag proc far
- push ax
- push ds
- mov ax,DGROUP ;make DS = to our TSR 'C' data segment
- mov ds,ax
-
- dec word ptr _unsafe_flag
-
- pop ds ;put DS back to whatever it was
- pop ax
- ret
- dec_unsafe_flag endp
-
- ;we can't trap the following interrupts in C for a number of
- ;reasons
- ; INT 13 returns info in the FLAGS, but a normal IRET
- ; restores the flags
- ;
- ; INT 25 & 26 leave the flags on the stack. The user
- ; must pop the off after performing an INT 25 or 26
- ;
- ; These interrupts pass information via registers such
- ; as DS. We don't want to change DS.
- ;
- ; Since DS is unknown, we must call the old interrupts
- ; via variables in the code segment. The _init_intr routine
- ; sets up these CS variables from ones with nearly-identical
- ; names in the C data segment in TSREXAMP.C.
-
- ;*****
- ;void far init_intr(void)
- ;move interrupt pointer saved in the C program to our CS data area
- ;*****
- _init_intr proc far
- push es
- push bx
-
- IFDEF MULTI
- les bx,dword ptr _old_int10
- mov word ptr cs:old_int10,bx
- mov word ptr cs:old_int10+2,es
-
- les bx,dword ptr _old_int25
- mov word ptr cs:old_int25,bx
- mov word ptr cs:old_int25+2,es
-
- les bx,dword ptr _old_int26
- mov word ptr cs:old_int26,bx
- mov word ptr cs:old_int26+2,es
- ENDIF
- ; note incredibly confusing distinction
- ; between e.g. _old_int13 and old_int13
- les bx,dword ptr _old_int13
- mov word ptr cs:old_int13,bx
- mov word ptr cs:old_int13+2,es
-
- pop bx
- pop es
- ret
- _init_intr endp
-
- ;*****
- ;void far new_int13(void) - disk interrupt
- ;*****
- _new_int13 proc far
- call inc_unsafe_flag
- pushf ;simulate interrupt call
- call cs:old_int13
- call dec_unsafe_flag
- ret 2 ; leave flags intact
- _new_int13 endp
-
- IFDEF MULTI
- ;*****
- ;void far new_int10(void) - video interrupt
- ;*****
- _new_int10 proc far
- call inc_unsafe_flag
- pushf ;simulate interrupt call
- call cs:old_int10
- call dec_unsafe_flag
- iret
- _new_int10 endp
-
- ;*****
- ;void far new_int25(void) - MS-DOS absolute sector read
- ;*****
- _new_int25 proc far
- call inc_unsafe_flag
- call cs:old_int25
- call dec_unsafe_flag
- ret ; user must pop flags - MS-DOS convention
- ; so leave them on the stack
- _new_int25 endp
-
- ;*****
- ;void far new_int26(void) - MS-DOS absolute sector write
- ;*****
- _new_int26 proc far
- call inc_unsafe_flag
- call cs:old_int26
- call dec_unsafe_flag
- ret ; user must pop flags - MS-DOS convention
- ; so leave them on the stack
- _new_int26 endp
-
- ;*****
- ;void far timer_int_chain(void) - jump to next timer ISR
- ;we need to clean up the stack because of this call
- ;*****
- _timer_int_chain proc far
- mov _ax_save,ax
- pop ax
- pop ax
- mov ax,_ax_save
- jmp dword ptr _old_int8
- _timer_int_chain endp
- ENDIF
-
- ;
- ;save areas for original interrupt vectors
- ;
- IFDEF MULTI
- old_int10 dd 0 ;video
- old_int25 dd 0 ;sector read
- old_int26 dd 0 ;sector write
- ENDIF
- old_int13 dd 0 ;disk
-
- _ds_save dw 0
- _TEXT ends
-
- _DATA segment
- IFDEF MULTI
- _ax_save dw 0
- ENDIF
- _DATA ends
-
- end
-