home *** CD-ROM | disk | FTP | other *** search
- ;---------------------------------------------------------------
- ;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