home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware 1 2 the Maxx
/
sw_1.zip
/
sw_1
/
COMM
/
IOMON2.ZIP
/
IOINIT.ASM
< prev
next >
Wrap
Assembly Source File
|
1992-02-20
|
20KB
|
544 lines
;---------------------------------------------------------------
;ioinit - main module for I/O Monitor |
;--------------------------------------------------------------|
;Copyright 1991 ASMicro Co. |
;--------------------------------------------------------------|
; 5/19/91 Rick Knoblaugh |
;--------------------------------------------------------------|
;include files |
;---------------------------------------------------------------
.386P
include ioequ.inc
include iostruc.inc
include iomac.inc
include iodat.inc
;--------------------------------------------------------------
;EXTERNALS |
;--------------------------------------------------------------
isrcode segment para public 'icode16' use16
extrn int_0:far
extrn int_2:far
extrn int_3:far
extrn int_4:far
extrn int_5:far
extrn int_6:far
extrn int_7:far
extrn except_8:far
extrn except_9:far
extrn except_0ah:far
extrn except_0bh:far
extrn except_0ch:far
extrn except_0dh:far
extrn except_0eh:far
extrn except_0fh:far
extrn int_20h:far
extrn int_21h:far
extrn int_22h:far
extrn int_23h:far
extrn int_24h:far
extrn int_25h:far
extrn int_26h:far
extrn int_27h:far
extrn int_70h:far
extrn int_71h:far
extrn int_72h:far
extrn int_73h:far
extrn int_74h:far
extrn int_75h:far
extrn int_76h:far
extrn int_77h:far
extrn int1_isr:far
extrn user_int_isr:far
isrcode ends
assume cs:code, ds:nothing, es:nothing
code segment para public 'code16' use16
assume cs:code, ds:data, es:data
.8086
start proc far
push ds ;save psp seg
mov ax, data
mov es, ax
call get_args ;get io ports
mov ax, data
mov ds, ax
jnc start_100 ;continue if args ok
start_050:
mov ah, DOS_PRT_STRING
int 21h
mov ax, 4c01h
int 21h
start_100:
call verify_cpu
jc start_050 ;continue if 386/486 in real mode
.386P
start_200:
call setup_ints ;take over user int
call init_gdt
call init_tss
mov ax, data
mov ds, ax
assume ds:data
cli ;no ints until protected mode
mov ax, gdt_seg
movzx eax, ax
shl eax, 4
mov gdtadrs, eax
mov ax, idt_seg
movzx eax, ax
shl eax, 4
mov idtadrs, eax
call reprogram_pic
lgdt gdtl
lidt idtl
mov dx, iostack3 ;get stack segment
mov bx, sp ;and pointer
mov eax, cr0
or eax, 1 ;turn on protected mode bit
mov cr0, eax ;go into protected mode
;
;jump to clear prefetch queue
;
db 0eah ;far jump
dw offset code:start_400
dw gdt_seg:sel_code
start_400:
mov ax, offset gdt_seg:sel_tss
ltr ax
xor ax, ax
lldt ax ;null ldt
mov ax, seg data
movzx eax, ax
push eax ;null gs
push eax ;null fs
push eax ;null ds
push eax ;null es
push 0
push dx ;stack segment
push 0
push bx ;stack pointer
push 2 ;VM bit set in upper eflags
push 3000h ;NT=0, IOPL=3, CLI in lower eflags
push 0
push seg code ;cs of where to return
push 0
push offset code:start_500 ;ip of where to return
;
;Must ensure that Nested Task bit is not set in eflags. If it were,
;processor would attempt to switch to a task via the selector in
;the TSS backlink field. Since that field is now zero, an invalid TSS
;fault would occur.
;
pushf
pop ax
and ax, NOT NT_FLAG
push ax
popf
iretd
start_500: ;begin vm86 task here
pop bx ;get saved psp seg
sti ;interrupts ok now
mov dx, code + 1 ;init code we are dropping
sub dx, bx
mov al, OK ;exit code
mov ah, DOS_TSR_FUNC
int 21h
start endp
reprogram_pic proc near
in al, 21h
mov ah, al
mov al, 11h ;init
out 20h, al
mov al, 20h ;irq0 to int 20h
out 21h, al
jmp short $ + 2
jmp short $ + 2
mov al, 4
out 21h, al
jmp short $ + 2
jmp short $ + 2
mov al, 1
out 21h, al
jmp short $ + 2
jmp short $ + 2
mov al, ah
out 21h, al
ret
reprogram_pic endp
.8086
;--------------------------------------------------------------
;get_args - retrieve starting and ending i/o addresses from |
; the command line. |
; |
; Enter: ds=PSP seg |
; |
; Exit: If invalid, carry set and dx=offset msg |
;--------------------------------------------------------------
get_args proc near
cld
xor si, si
sub ch, ch
mov cl, [si].arg_len ;get cmd line length
lea si, [si].arg_off ;and offset
call skip_white_sp
mov dx, offset es:bad_arg_msg
jcxz get_a800 ;if no args
call get_validate ;get first i/o port
jc get_a999
mov es:start_port, bx ;save it
call skip_white_sp
jcxz get_a800 ;if no 2nd arg
call get_validate ;get 2nd i/o port
jc get_a999
mov es:end_port, bx ;save it
cmp bx, es:start_port ;2nd arg >= 1st arg
jae get_a900
mov dx, offset es:bad_2nd_msg
get_a800:
stc
jmp short get_a999
get_a900:
clc
get_a999:
ret
get_args endp
;--------------------------------------------------------------
;get_validate - Retrieve and validate an ASCII hex number. |
; |
; Enter: si ptr to data |
; cx max len |
; |
; Exit: data at si now binary |
; cx decremented by length of number |
; If invalid, carry set and dx=&err_msg |
; bx=binary value of number |
;--------------------------------------------------------------
get_validate proc near
xor bx, bx
get_v100:
cmp byte ptr [si + bx], ' '
je get_v200
cmp byte ptr [si + bx], CR
je get_v200
inc bx
jmp short get_v100
get_v200:
sub cx, bx ;cmd line chars left
push cx
mov cx, bx
xor bx, bx
get_v300:
sub ah, ah
lodsb ;get a digit
call asc2bin ;validate and convert
jc get_v900 ;exit if invalid
push cx
jcxz get_v500
dec cx ;position from right - 1
shl cl, 1
shl cl, 1
shl ax, cl ;get nibble into position
get_v500:
or bx, ax ;build number
pop cx
loop get_v300
clc ;ok
get_v900:
pop cx
ret
get_validate endp
asc2bin proc near
cmp al, 'a'
jb asc2b_100
and al, 0dfh ;force to upper case
asc2b_100:
cmp al, '0'
jb asc2b_800
cmp al, '9' ;see if 0-9 or A-F
ja asc2b_500
sub al, '0' ;convert to binary
jmp short asc2b_600
asc2b_500:
cmp al, 'F'
ja asc2b_800
sub al, 'A' - 10
asc2b_600:
clc
jmp short asc2b_900
asc2b_800:
mov dx, offset es:bad_arg_msg
stc
asc2b_900:
ret
asc2bin endp
skip_white_sp proc near
cmp byte ptr [si], ' '
je skip_w200
cmp byte ptr [si], TAB
je skip_w200
jmp short skip_w900
skip_w200:
inc si
loop skip_white_sp
skip_w900:
ret
skip_white_sp endp
verify_cpu proc near
xor ax,ax
push ax
popf
pushf
pop ax
and ax,0f000h
cmp ax,0f000h
jz verify_c800 ;not 386
mov ax, 0f000h
push ax
popf
pushf
pop ax
and ax,0f000h ;not 386
jz verify_c800
mov dx,offset noprot_msg
.386P
smsw ax ;get pm flag into carry
rcr ax,1
jmp short verify_c999
verify_c800: mov dx, offset not386_msg
stc
verify_c999:
ret
verify_cpu endp
setup_ints proc near
mov bx, USER_INT
mov di, offset old_user_int
mov cx, isrcode
mov dx, offset isrcode:user_int_isr
call get_int
ret
setup_ints endp
;--------------------------------------------------------------
;get_int - For a given interrupt vector, store contents and |
; load with new isr address. |
; |
; bx = int number |
; es:di = location to store contents |
; dx = offset new isr |
; cx = cs of new isr
;--------------------------------------------------------------
get_int proc near
cld
push ds
xor ax, ax
mov ds, ax
shl bx, 2
mov ax, [bx]
stosw
mov ax, [bx].d_segment
stosw
cli
mov [bx].d_offset, dx
mov [bx].d_segment, cx
sti
pop ds
ret
get_int endp
init_gdt proc near
mov ax, gdt_seg
mov ds, ax
assume ds:gdt_seg
mov dx, tss_seg
movzx edx, dx ;base data segment
mov ecx, (TSS_END - TSS_BEG ) - 1 ;limit
mov ah, TSS_DESC
mov si, offset sel_tss
call make_entry
mov dx, tss_seg
movzx edx, dx ;base data segment
mov ecx, (TSS_END - TSS_BEG ) - 1 ;limit
mov ah, RW_DATA ;alias as r/w for editing
mov si, offset sel_tss_alias
call make_entry
mov dx, gdt_seg
movzx edx, dx ;base data segment
mov ecx, (GDT_END - GDT_BEG ) - 1 ;limit
mov ah, RW_DATA ;alias as r/w for editing
mov si, offset sel_gdt_alias
call make_entry
mov dx, isrcode
movzx edx, dx ;base of isr code segment
mov ecx, 0ffffh ;max segment size
mov ah, ER_CODE
mov si, offset sel_isrcode
call make_entry
mov dx, code
movzx edx, dx ;base code segment
mov ecx, 0ffffh ;max segment size
mov ah, ER_CODE
mov si, offset sel_code
call make_entry
xor edx, edx ;zero base
mov ecx, 0fffffh ;base memory size
mov ah, RW_DATA
mov si, offset sel_databs
call make_entry
mov dx, iostack
movzx edx, dx ;base stack segment
mov ecx, (STACK_END - STACK_BEG ) - 1 ;limit
mov ah, RW_DATA
mov si, offset sel_stack
call make_entry
mov dx, data
movzx edx, dx ;base data segment
mov ecx, (DATA_END - DATA_BEG ) - 1 ;limit
mov ah, RW_DATA
mov si, offset sel_data
call make_entry
int 11h ;equipment check
mov edx, 0b800h ;color segment
and al, 30h ;monitor bits
cmp al, 30h ;30h=monochrome
jne init_gdt500
mov edx, 0b000h ;monochrome segment
init_gdt500:
mov ecx, VID_PAGE_SIZE - 1 ;page size - 1
mov ah, RW_DATA
mov si, offset sel_video
call make_entry
ret
init_gdt endp
;--------------------------------------------------------------
;make_entry - Load a GDT entry from information passed as |
; follows: |
; |
; ds=gdt segent |
; si=offset of gdt entry to load |
; ah=type | dpl |
; ecx=limit |
; edx=base segment (convert it to linear) |
; Always set for byte granularity and 16 bit size |
; |
;--------------------------------------------------------------
make_entry proc near
shl edx, 4 ;convert seg to linear
mov [si].seg_limit_low, cx
mov [si].seg_base_low, dx
shr edx, 16
mov [si].seg_base_mid, dl
mov [si].seg_type_dpl, ah
shr ecx, 16
and cl, 0fh ;limit and byte gran
mov [si].seg_limit_gran, cl
mov [si].seg_base_top, dh
ret
make_entry endp
;--------------------------------------------------------------
;init_tss - Initilize TSS with base of I/O bit map and set |
; appropriate bits in I/O bit map per cmd line. |
; |
;--------------------------------------------------------------
init_tss proc near
mov ax, tss_seg
mov ds, ax
assume ds:tss_seg
xor si, si
mov ax, offset gdt_seg:sel_stack
mov [si].t_ess0, ax
mov ax, offset iostack:io_sp
movzx eax, ax
mov [si].t_esp0, eax
lea bx, [si].t_iomap
mov [si].t_iobase, bx
mov cx, es:start_port ;start of range to monitor
mov dx, cx
and cl, 7 ;get non byte boundary
mov al, 1 ;first bit position
shl al, cl ;get out corresponding bit
shr dx, 3 ;start_port/8
mov cx, es:end_port
sub cx, es:start_port
inc cx
add bx, dx ;starting offset in map
init_t100:
or byte ptr [bx], al ;turn on permission bit
rcl al, 1 ;next bit position
jnc init_t300
inc bx
rcl al, 1
init_t300:
loop init_t100
ret
init_tss endp
code ends
end start