home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
High Voltage Shareware
/
high1.zip
/
high1
/
DIR4
/
V12N16.ZIP
/
FINDIR.ZIP
/
FINASM.ZIP
/
IRQMAIN.ASM
< prev
next >
Wrap
Assembly Source File
|
1993-08-24
|
36KB
|
799 lines
;---------------------------------------------------------------
;irqmain.asm - Main module for FINDIRQ Utility |
;--------------------------------------------------------------|
;FINDIRQ Copyright (c) 1993 |
; |
;Rick Knoblaugh All rights reserved. |
;First Appeared in PC MAGAZINE, US Edition, |
;September 28, 1993 |
;--------------------------------------------------------------|
; 4/17/93 Rick Knoblaugh |
;--------------------------------------------------------------|
;include files |
;---------------------------------------------------------------
include irqequ.inc
include irqstruc.inc
bios_seg segment at 0f000h
org 0fffeh
model_id db ?
bios_seg ends
code segment public 'CODE'
assume cs:code, ds:code, es:code
;--------------------------------------------------------------
;externals |
;--------------------------------------------------------------
extrn get_from_disk:near ;irqsupt.asm
extrn put_to_disk:near ;irqsupt.asm
extrn get_switch:near ;irqsupt.asm
extrn get_set_int:near ;irqsupt.asm
extrn get_path:near ;irqsupt.asm
extrn load_desc:near ;irqsupt.asm
extrn find_devices:near ;irqsupt.asm
extrn find_drivers:near ;irqsupt.asm
extrn see_if_install:near ;irqsupt.asm
extrn ck_for_dos:near ;irqsupt.asm
extrn verify_enables:near ;irqsupt.asm
extrn ck_monitor:near ;irqsupt.asm
extrn get_stacks_seg:near ;irqsupt.asm
extrn int_1c_isr:near ;irqisr.asm
extrn int_28_isr:near ;irqisr.asm
extrn int_2f_isr:near ;irqisr.asm
extrn old_1c_isr:near ;irqisr.asm
extrn old_28_isr:near ;irqisr.asm
extrn old_2f_isr:near ;irqisr.asm
extrn atclassf:byte ;irqisr.asm
extrn pic_mask:word ;irqisr.asm
extrn read_pic_masks:near ;irqisr.asm
extrn startup:near ;irqisr.asm
extrn disp_screen:near ;irqdisp.asm
extrn cls_total:near ;irqdisp.asm
extrn disp_pscreen:near ;irqdisp.asm
extrn set_cursor:near ;irqdisp.asm
;--------------------------------------------------------------
;publics |
;--------------------------------------------------------------
public data_path, data_file, installf
public start_util, int_table
public last_code, num_com, num_prt
public pc_std_dev, at_std_dev
public pc_basic_dev, at_basic_dev
public com3_desc, com4_desc
public other_desc, mouse_desc
public device_desc, int_tab_off, int_tab_seg
public FILE_NAME_LEN, dos_handler_seg
public block_desc, drv_desc_ptr, drv_ptr
public ver_irq_mask
public block_abbrv, monoflag, monoatrib
public dos_ver, math_present
;--------------------------------------------------------------
;Variables |
;--------------------------------------------------------------
data_path db MAX_PATHLEN dup(0)
data_file db 'FINDIRQ.DAT', 0
FILE_NAME_LEN equ ($ - data_file)
int_table isr_data <1ch, int_1c_isr, old_1c_isr>
isr_data <28h, int_28_isr, old_28_isr>
isr_data <INSTALL_INT, int_2f_isr, old_2f_isr>
INT_ENTRIES equ ($ - int_table)/ size isr_data
;--------------------------------------------------------------
;Everything below here dropped when go TSR |
;--------------------------------------------------------------
last_code label byte
installf db FALSE ;TRUE if installed
math_present db FALSE ;TRUE if have coprocessor
cmd_table cmd_dispatch <irq_help, HELP_SWITCH> ;help for 'H' or
cmd_dispatch <irq_help, HELP2_SWITCH> ;help for '?'
cmd_dispatch <irq_init, INIT_SWITCH>
cmd_dispatch <irq_uninst, UNINST_SWITCH >
cmd_dispatch <irq_tsr, TSR_SWITCH>
MAX_SWITCHES EQU ($ - cmd_table) / size cmd_dispatch
num_com db 0 ;number of COM ports
num_prt db 0 ;number of printers
work_string db 4 dup(?) ;used to format irq numbers
dos_handler_seg dw 0 ;segment for DOS stack handlers
dos_ver dw 0
drv_ptr dd ? ;pointer to NUL device
;
;The following word contains bits set corresponding to IRQs typically
;assigned to devices that may or may not be present. If standard
;devices (such as COMn and LPn) are detected, bits corresponding to
;the IRQs used by such devices are turned off. Any bits remaining on
;after we interrogate the system, represent IRQs that we should verify.
;For example, if an ill-behaved program enables IRQs in the PIC masks,
;but doesn't do anything with them (i.e. the vectors are still pointing
;to default handlers), we should not report these as active.
;
;
ver_irq_mask dw ( ( (mask atirq15) or (mask atmath) or (mask atirq12) or (mask atirq11) \
(mask atirq10)) shl 8 or ( (mask atlpt1) or \
(mask atlpt2) or (mask atcom1) or (mask atcom2) \
or (mask atcas) ))
monoflag db FALSE ;TRUE if monochrome monitor
monoatrib db FALSE ;TRUE if should use B/W attributes
;keep these together
int_tab_off dw 0 ;offset of int table in TSR code
int_tab_seg dw 0 ;segment of int table in TSR code
;--------------------------------------------------------------
;Data for screen displays |
;--------------------------------------------------------------
include irqsdata.inc
;--------------------------------------------------------------
start_util proc near
cld ;all strings forward
mov ah, DOS_GET_VER ;check unlikely event
int 21h ;that user has really
mov dx, offset invalid_dos_msg
;
;FINDIRQ requires DOS version 3.0 or better becuase it utilizes the
;information at the end of the DOS environment block which specifies
;the path for the process that owns the environment.
;
cmp al, 3 ;need DOS 3.0 or better
jae start_u050
jmp start_u900 ;far jump
start_u050:
mov cs:dos_ver, ax
mov ax, bios_seg ;look at ROM area
mov es, ax
assume es:bios_seg
cmp es:model_id, AT_MODEL ;for AT model code
je start_u100
cmp es:model_id, PS2_AT ;for PS/2 model code
je start_u100
assume es:nothing
mov cs:atclassf, FALSE ;XT or less
start_u100:
call ck_monitor ;determine if monochrome
call get_path ;get current path
xor si, si ;offset zero from psp
sub ch, ch
mov cl, [si].psp_cmd_len
lea si, [si].psp_cmd_tail
call get_switch
mov dx, offset invalid_swt_msg
jc start_u900
mov bp, ax ;save switch
;These 2 lines can be removed for .COM file
push cs
pop ds ;setup data segment
mov pic_mask, 0ffffh ;default to no IRQs active
;Next, attempt to get PIC mask values from data file (it may not exist yet).
;
push cx ;save count of cmd line chars
call get_from_disk ;attempt to read data file
;Look at standard devices and alter PIC mask for those devices we
;know are present, but that may not be enabled (e.g. LPTn:, COMn:).
call get_init_pic ;get PIC mask values
call get_stacks_seg ;get segment of DOS STACKS
pop cx
;At this point, cx=0 if no switch supplied on command line
jcxz start_u140 ;jmp if no command line switch
cmp bp, NOVERIFY_SWITCH ;/d option - don't verify enables?
je start_u160
jmp short start_u180 ;go process other switches
start_u140:
call verify_enables ;ensure IRQs really used
start_u160:
;Go get device descriptions for IRQs where devices are static
;(e.g. IRQ0 is always used for the timer
;
call load_desc
call find_devices ;look for other devices
;If don't have descriptions for IRQs (i.e. device is some add-in
;board such as a sound board, SCSI adapter, etc.), go get the name of
;the driver or TSR to which the int is vectored.
;
call find_drivers
call display_status
jmp short start_u999
start_u180:
;
mov ax, bp ;get switch
mov cx, MAX_SWITCHES
mov di, offset cmd_table
start_u200:
cmp al, [di].cmd_switch ;switch found?
je start_u300 ;if so, go process
add di, size cmd_dispatch ;advance to next entry
loop start_u200
mov dx, offset invalid_swt_msg ;bad switch message
jmp short start_u950 ;go display and exit
start_u300:
call [di].cmd_routine ;process per switch
jmp short start_u999
start_u900:
push cs
pop ds ;get data segment
start_u950:
mov ah, DOS_PRT_STRING
int 21h
start_u999:
mov ax, (DOS_TERM SHL 8) ;terminate
int 21h
ret
start_util endp
irq_help proc near
mov si, offset help_screen
call disp_screen
ret
irq_help endp
;--------------------------------------------------------------
;irq_init - Utility has been invoked with the "/I" option. |
; Thus, user wants to overwrite any saved IRQ |
; information and reinitialize the IRQ data |
; file values for currently active IRQs. This |
; would typically be done if a board has been |
; removed, or a jumper setting has been changed. |
; |
; Enter: |
; ds = local data segment |
; data_path=file spec for data file |
; |
; |
; Exit: |
; |
; pic_mask updated |
; |
; Message is displayed. |
; |
;--------------------------------------------------------------
irq_init proc near
mov pic_mask, 0ffffh ;default to none active
;Look at standard devices and alter our PIC mask for those devices we
;know are present, but may not be enabled (e.g. LPTn:, COMn:).
call get_init_pic ;get PIC mask values
call put_to_disk ;write then to disk
jnc irq_init100
mov dx, offset io_err_msg ;report i/o error
jmp short irq_init800
irq_init100:
mov dx, offset init_msg ;tell user we initialized it
irq_init800:
mov ah, DOS_PRT_STRING
int 21h
irq_init999:
ret
irq_init endp
irq_tsr proc near
;The following call returns with carry set if we are already installed
call see_if_install ;detect our presence
jnc irq_tsr100
mov dx, offset tsr_already_msg
mov ah, DOS_PRT_STRING
int 21h
ret
irq_tsr100:
mov cx, INT_ENTRIES ;number of ints to hook
mov si, offset int_table ;int routines etc.
irq_tsr200:
mov al, [si].int_number ;the interrupt to capture
mov di, [si].old_isr ;place to store old &isr
mov dx, [si].isr_routine ;our isr offset
call get_set_int ;go install our isr
add si, size isr_data
loop irq_tsr200
mov dx, offset tsr_ok_msg
mov ah, DOS_PRT_STRING
int 21h
pop ax ;clean up stack
mov dx, cs
mov bx, dx
inc dx
mov ax, offset last_code
mov cl, 4
shr ax, cl
add dx, ax
sub dx, bx ;paragraphs to keep
mov ax, (DOS_TSR_FUNC SHL 8) ;exit code 0
int 21h ;Go TSR
irq_tsr endp
;--------------------------------------------------------------
;get_init_pic - Looking at standard devices from equipment |
; list, reflect those devices as being enabled. |
; Also, read current PIC mask values and |
; reflect any new ones. |
; |
; Enter: |
; ds = local data segment |
; atclassf = TRUE if AT class machine |
; |
; pic_mask will hold current values read |
; from data file (or reinitilized |
; values if called as a result of |
; /I option). |
; |
; Exit: |
; |
; pic_mask and ver_irq_mask updated |
; |
; |
; |
; |
;--------------------------------------------------------------
get_init_pic proc near
cmp atclassf, TRUE ;AT machine?
je get_init050
and ver_irq_mask.d_master, not (mask atlpt2) ;no need to verify this IRQ
jmp short get_init080
get_init050:
and pic_mask.d_slave, not (mask atclock) ;ATs have clock
get_init080:
int 11h ;do equipment check
push ax ;save the flags
test ax, mask math_co ;math coprocessor present?
jz get_init100
mov math_present, TRUE ;if so, set flag
get_init100:
and ax, mask num_prt_bits ;isolate printers
mov cl, num_prt_bits
shr ax, cl ;have number printers
mov num_prt, al ;save number of printers
jz get_init200 ;no printers
and pic_mask.d_master, not (mask atlpt1) ;show it enabled
and ver_irq_mask.d_master, not (mask atlpt1) ;no need to verify this IRQ
cmp atclassf, TRUE ;AT machine?
jne get_init200
cmp ax, 1 ;if so, more than 1 lpt ?
je get_init200
and pic_mask.d_master, not (mask atlpt2) ;show it enabled
and ver_irq_mask.d_master, not (mask atlpt2) ;no need to verify this IRQ
get_init200:
pop ax ;get back equipment flags
and ax, mask num_com_bits ;isolate com ports
mov cl, num_com_bits
shr ax, cl ;have number com ports
mov num_com, al ;save number of com ports
jz get_init500 ;no com ports
and pic_mask.d_master, not (mask atcom1) ;show it enabled
and ver_irq_mask.d_master, not (mask atcom1) ;no need to verify this IRQ
cmp ax, 1 ;more than 1 com ?
je get_init500
and pic_mask.d_master, not (mask atcom2) ;show it enabled
and ver_irq_mask.d_master, not (mask atcom2) ;no need to verify this IRQ
get_init500:
call read_pic_masks
ret
get_init_pic endp
;--------------------------------------------------------------
;display_status - Display screen showing IRQs, use by |
; standard devices, and use by this |
; system. |
; |
; |
; Enter: |
; ds = local data segment |
; |
; |
; Exit: |
; |
; |
;--------------------------------------------------------------
display_status proc near
mov bh, SCREEN_ATTRIB
call cls_total ;clear screen first
mov di, offset rep_top ;top portion of display
call disp_pscreen ;display top lines
mov dh, DISP_BEG_ROW ;row display counter
mov cx, 16 ;max irqs
cmp atclassf, TRUE ;AT machine?
je display_s100 ;if so, 16 IRQs
shr cx, 1 ;else 8
display_s100:
push cx ;save irq count
display_s150:
mov det_line.str_rowp, dh ;row for display
mov di, offset det_line
call disp_pscreen
inc dh ;advance row counter
loop display_s150
mov bot_line.str_rowp, dh ;row for display
mov di, offset bot_line
call disp_pscreen ;display bottom line
pop cx ;number of irqs
xor al, al ;irq counter
mov bx, pic_mask ;bl=mask master bh=mask slave
mov dh, DISP_BEG_ROW ;row display counter
push ds
pop es ;get es=ds
display_s190:
mov wrk_line.str_rowp, dh
mov wrk_line.str_colp, COLUMN_IRQ
mov wrk_line.str_attribp, DETAIL_ATTRIB
mov di, offset work_string
mov wrk_line.str_data_ptr, di
push ax ;save irq counter
aam ;make irq number bcd
add ax, 3030h ;make ASCII
cmp ah, 30h ;< 10?
jne display_s200 ;if not, go move high order
mov ah, ' '
display_s200:
xchg al, ah
stosb
xchg al, ah
stosb
mov byte ptr [di], STR_TERM
pop ax ;restore irq counter
mov di, offset wrk_line
shr bx, 1 ;get irq mask bit into carry
push bx
lahf ;get flags
jnc display_s300 ;jmp if irq active
cmp al, 0dh ;math coprocessor
je display_s300 ;if so, it's reserved (not available)
mov wrk_line.str_attribp, FREE_ATTRIB ;highlight indicating free
display_s300:
call disp_pscreen
;display device that normally uses this irq
call disp_std_dev
;display device that uses this irq on this system
call disp_this_dev
call disp_use ;display use status
inc dh ;advance row
inc al ;next irq
pop bx
loop display_s190
;The following call returns with carry set if we are already installed
call see_if_install ;detect our presence
jnc display_s800
mov di, offset rel_line
call disp_pscreen ;display them
display_s800:
mov di, offset press_esc ;press esc and help message
call disp_pscreen ;display them
display_s900:
xor al, al ;zero
call set_cursor ;turn cursor off
display_s950:
sub ah, ah
int 16h ;get a key
cmp al, ESC_KEY
jne display_s950
mov al, 1
call set_cursor ;turn cursor on
ret
display_status endp
;--------------------------------------------------------------
;disp_std_dev - Per the IRQ number, display device name that |
; normally uses that device. |
; |
; |
; Enter: |
; ds = local data segment |
; al = irq number |
; atclassf = true if AT class machine |
; wrk_line.str_rowp = row for display |
; |
; Exit: |
; |
; |
;--------------------------------------------------------------
disp_std_dev proc near
sub bh, bh
mov bl, al ;irq number
shl bx, 1 ;index into words
mov wrk_line.str_colp, COLUMN_STD
mov wrk_line.str_attribp, DETAIL_ATTRIB
mov di, offset at_std_dev
cmp atclassf, TRUE ;AT machine?
je disp_std_100
mov di, offset pc_std_dev
disp_std_100:
mov bx, [di + bx] ;get ptr to description
or bx, bx ;is there a device here?
jz disp_std_999 ;if not, nothing to do
mov di, offset wrk_line
mov wrk_line.str_data_ptr, bx
call disp_pscreen
disp_std_999:
ret
disp_std_dev endp
;--------------------------------------------------------------
;disp_this_dev - Per the IRQ number, display device name that |
; uses it on this system. If not a std |
; device, display "other". |
; |
; Enter: |
; ds = local data segment |
; al = irq number |
; atclassf = true if AT class machine |
; wrk_line.str_rowp = row for display |
; ah = flags (where carry set if irq |
; Exit: is inactive) |
; |
; cx saved |
;--------------------------------------------------------------
disp_this_dev proc near
sub bh, bh
mov bl, al ;irq number
shl bx, 1 ;index into array
shl bx, 1
shl bx, 1
mov dl, COLUMN_THIS
mov wrk_line.str_attribp, DETAIL_ATTRIB
mov di, offset device_desc
push cx
mov cx, (size device_desc_off) / DESC_ENTRY ;number of descriptions
disp_this_100:
cmp [di + bx].d_segment, 0 ;more than 1 description?
je disp_this_125
sub dl, 2 ;if so, start back little
disp_this_125:
mov bp, [di + bx] ;get ptr to description
sahf ;get flag indicating active
jnc disp_this_500 ;jmp if active
or bp, bp ;is there a description?
jnz disp_this_600 ;there is
disp_this_150:
mov bp, offset vacant_desc ;if not, print "vacant"
disp_this_500:
or bp, bp ;is there a description?
jnz disp_this_600
mov bp, offset other_desc ;if not, print "Other"
disp_this_600:
push di
mov di, offset wrk_line
mov wrk_line.str_data_ptr, bp
mov wrk_line.str_colp, dl ;column to start
call disp_pscreen
pop di
inc dl ;next column
add bx, DESC_ENTRY ;next description
mov bp, [di + bx] ;get ptr to next description
cmp bp, 0
loopne disp_this_600
disp_this_999:
pop cx
ret
disp_this_dev endp
;--------------------------------------------------------------
;disp_use - Per the IRQ number, display whether this irq |
; is in-use or free. |
; |
; Enter: |
; ds = local data segment |
; al = irq number |
; atclassf = true if AT class machine |
; wrk_line.str_rowp = row for display |
; ah = flags (where carry set if irq |
; Exit: is inactive) |
; |
; |
;--------------------------------------------------------------
disp_use proc near
mov wrk_line.str_colp, COLUMN_STATUS
mov wrk_line.str_attribp, DETAIL_ATTRIB
mov bx, offset inuse_desc ;default to inuse
sahf ;get flag indicating active
jnc disp_use_900 ;jmp if active
mov bx, offset free_desc
cmp al, 0dh ;math coprocessor
jne disp_use_500
mov bx, offset reserv_desc ;if so, it's reserved
jmp short disp_use_900
disp_use_500:
mov wrk_line.str_attribp, FREE_ATTRIB
disp_use_900:
mov di, offset wrk_line
mov wrk_line.str_data_ptr, bx
call disp_pscreen
ret
disp_use endp
;--------------------------------------------------------------
;irq_uninst - Use interrupt to determine if we are resident. |
; If resident, unhook used interrupts and |
; release memory. |
; |
; Enter: |
; ds = local data segment |
; Exit: |
; message displayed |
; |
;--------------------------------------------------------------
irq_uninst proc near
call see_if_install ;detect our presence
mov dx, offset not_install_msg
jnc irq_un900 ;exit if not installed
call vectors_same ;anyone steal vectors?
jc irq_un800 ;if so, can't uninstall
call restore_vectors
mov ax, int_tab_seg ;get our TSR PSP
mov es, ax
mov bx, psp_environ_seg
mov ax, es:[bx] ;get environment segment
mov es, ax
mov ah, DOS_RELEASE_MEM
int 21h
jc irq_un800 ;if error, report it
mov ax, int_tab_seg ;get our TSR PSP
mov es, ax
mov ah, DOS_RELEASE_MEM
int 21h
jc irq_un800 ;if error, report it
mov dx, offset uninst_ok_msg
jmp short irq_un900
irq_un800:
mov dx, offset cant_un_msg
irq_un900:
mov ah, DOS_PRT_STRING
int 21h
ret
irq_uninst endp
vectors_same proc near
push ds
xor bx, bx
mov es, bx ;vectors
mov dx, int_tab_off.d_segment ;get segment of our isr
assume ds:nothing
lds di, dword ptr int_tab_off ;int table in TSR code
mov cx, INT_ENTRIES ;number of entries
vectors_s100:
mov bl, [di].int_number
shl bx, 1
shl bx, 1
mov ax, [di].isr_routine ;offset to &isr
cmp ax, es:[bx].d_offset
jne vectors_s800
cmp dx, es:[bx].d_segment
jne vectors_s800
add di, size isr_data
loop vectors_s100
clc
jmp short vectors_s900
vectors_s800:
stc
vectors_s900:
pop ds
assume ds:code
vectors_s999:
ret
vectors_same endp
restore_vectors proc near
push ds
les si, dword ptr int_tab_off ;int table in TSR code
mov cx, INT_ENTRIES ;number of entries
restore_v200:
mov al, es:[si].int_number ;the interrupt to restore
mov di, es:[si].old_isr ;&variable holding &isr to restore
mov dx, es:[di].d_segment
mov ds, dx
mov dx, es:[di].d_offset
mov ah, DOS_SET_INT
int 21h ;ds:dx has our routine
add si, size isr_data
loop restore_v200
pop ds
ret
restore_vectors endp
code ends
end startup