home *** CD-ROM | disk | FTP | other *** search
- ;---------------------------------------------------------------
- ;ioisr - Interrupt Service Routines for I/O Monitor |
- ;--------------------------------------------------------------|
- ;Copyright 1991 ASMicro Co. |
- ;--------------------------------------------------------------|
- ; 5/25/91 Rick Knoblaugh |
- ;--------------------------------------------------------------|
- ;include files |
- ;---------------------------------------------------------------
- .386P
- include ioequ.inc
- include iomac.inc
- include iostruc.inc
-
-
- data segment para public 'data16' use16
- extrn start_port:WORD
- extrn end_port:WORD
- extrn old_int1:DWORD
- extrn old_user_int:DWORD
- extrn io_table:BYTE
- extrn IO_TAB_ENTRIES:ABS
- extrn access_port:word
- extrn access_info:byte
- extrn store_buf:byte
- extrn store_buf_end:ABS
- extrn store_ptr:word
- extrn store_wrapped:byte
- extrn display_loc:word
- extrn trap_status:byte
- data ends
-
- gdt_seg segment para public 'data16' use16
- extrn sel_databs:byte
- extrn sel_video:byte
- extrn sel_data:byte
- extrn sel_tss_alias:byte
- gdt_seg ends
-
- tss_seg segment para public 'data16' use16
- tss_seg ends
-
-
- isrcode segment para public 'icode16' use16
- assume cs:isrcode, ds:nothing, es:nothing
- ;--------------------------------------------------------------
- ;PUBLICS |
- ;--------------------------------------------------------------
- public int1_isr
- public user_int_isr
- public int_0
- public int_2
- public int_3
- public int_4
- public int_5
- public int_6
- public int_7
- public except_8
- public except_9
- public except_0ah
- public except_0bh
- public except_0ch
- public except_0dh
- public except_0eh
- public except_0fh
- public int_20h
- public int_21h
- public int_22h
- public int_23h
- public int_24h
- public int_25h
- public int_26h
- public int_27h
-
- public int_70h
- public int_71h
- public int_72h
- public int_73h
- public int_74h
- public int_75h
- public int_76h
- public int_77h
-
- irp z, <0, 2, 3, 4, 5, 6, 7>
- DOINT &z
- endm
-
- irp z, <8, 9, 0ah, 0bh, 0ch, 0dh, 0eh, 0fh>
- DOEXCP &z
- endm
-
- irp z, <20h, 21h, 22h, 23h, 24h, 25h, 26h, 27h>
- DOEXCPH &z
- endm
-
- irp z, <70h, 71h, 72h, 73h, 74h, 75h, 76h, 77h>
- DOINT &z
- endm
-
- ;--------------------------------------------------------------
- ;int1_isr - ISR for single step interrupt. If trap_status |
- ; has EXPECT_INT1 bit set, this is the trap |
- ; that occurs just after the I/O instruction |
- ; we are monitoring executes. Store the I/O data |
- ; from ax into our buffer. |
- ;--------------------------------------------------------------
- int1_isr proc far
- push bp
- mov bp, sp
- push bx
- push ds
- mov bx, offset gdt_seg:sel_data
- mov ds, bx
- assume ds:data
- test trap_status, EXPECT_INT1 ;expecting an int 1?
- jnz int1_050
- pop ds
- pop bx
- push 1
- jmp pass_thru ;if not, do old int 1
- int1_050:
- push ax
- push cx
- push dx
- mov trap_status, 0
- and [bp].s_eflags, NOT TRAP_FLAG ;no more single step
- mov bx, store_ptr
- mov cl, access_info
- or cl, CONTAINS_DATA ;indicate data stored
- mov [bx].buf_info, cl ;store info re i/o
- mov dx, access_port
- mov [bx].buf_port, dx ;store port number
- test cl, AWORD ;word access?
- jnz int1_100
- sub ah, ah ;if not, clear half
- int1_100:
- mov [bx].buf_data, ax
- add bx, size buf_record ;advance buf ptr
- cmp bx, store_buf_end - size buf_record ;at end?
- jb int1_200
- mov bx, offset store_buf
- mov store_wrapped,1
- int1_200:
- mov store_ptr, bx ;save new ptr
- and cx, (AWORD OR ABYTE) ;number of bits
- mov ah, 1 ;indicate set
- mov dx, access_port
- call do_bit_map ;set the bits again
- pop dx
- pop cx
- pop ax
- pop ds
- pop bx
- pop bp
- iretd
- int1_isr endp
-
- ;--------------------------------------------------------------
- ;except_handler - Process as follows: |
- ; |
- ; Int 0dh - Go look for software int or |
- ; I/O instruction. |
- ; Any other |
- ; exception - go display exception number |
- ; and halt. |
- ;--------------------------------------------------------------
- except_handler proc near
- mov bp, sp
- cmp [bp].e_pushed_int , GEN_PROT_EXCEP
- je gen_prot_isr
- mov ax, [bp].e_pushed_int ;int in ax, go display
- jmp short fatal_error
- except_handler endp
-
- fatal_error proc near
- call display_it
- jmp $
- fatal_error endp
-
- ;--------------------------------------------------------------
- ;display_it - Display hex number on screen at next display |
- ; offset. |
- ; |
- ; Enter: number in AX |
- ; processor in protected mode |
- ; |
- ; All registers saved |
- ;--------------------------------------------------------------
- display_it proc near
- pusha
- push ds
- push es
-
- mov dx, offset gdt_seg:sel_data
- mov ds, dx ;get our data segment
- assume ds:data
- mov dx, offset gdt_seg:sel_video
- mov es, dx ;and video segment
- mov di, display_loc
- xchg al, ah ;print MSB first
- call put_hex_digit
- xchg al, ah ;get LSB
- call put_hex_digit
- add di, 2 ;past space and attribute
- cmp di, VID_PAGE_SIZE
- jb display_i100
- xor di, di ;back to start of page
- display_i100:
- mov display_loc, di
- pop es
- pop ds
- popa
- ret
- display_it endp
-
- put_hex_digit proc near
- push ax
- mov cx, 2 ;2 digits in al
- mov ah, al
- put_hex_100:
- shr al, 4
- cmp al, 9
- ja put_hex_200
- add al, '0'
- jmp short put_hex_300
- put_hex_200:
- add al, 'A' - 10
- put_hex_300:
- cld
- stosb
- inc di ;past attrib
- mov al, ah
- shl al, 4
- loop put_hex_100
- pop ax
- ret
- put_hex_digit endp
-
- ;--------------------------------------------------------------
- ;pass_thru - This procedure is JMPed to by any interrupt |
- ; handler which wishes to pass control to the |
- ; original ISR per the interrupt vector table. |
- ; |
- ; Entry: |
- ; See stack_area struc for stack layout |
- ; Any error code has been removed from stack.|
- ; EIP on stack has been adjusted if |
- ; necessary. |
- ;--------------------------------------------------------------
- pass_thru proc near
- mov bp, sp
- pushad
- push ds
- mov ax, offset gdt_seg:sel_databs
- mov ds, ax ;address all base memory
- movzx ebx, [bp].s_ss ;user stack
- shl ebx, 4 ;make linear
- mov edx, [bp].s_esp ;user stack pointer
- sub edx, 6 ;flags, cs, ip
- mov [bp].s_esp, edx ;adjust it
- mov eax, [bp].s_eflags ;put on flags
- mov [ebx][edx].user_flags, ax
- ;
- ;change flags on stack so that original ISR will be entered with
- ;interrupts cleared and trap flag cleared to be consistent with their
- ;state upon entering an ISR (the normal way).
- ;
- and ax, not (TRAP_FLAG + INT_FLAG)
- mov [bp].s_eflags, eax ;put back flags
- mov ax, [bp].s_cs ;put on user cs
- mov [ebx][edx].user_cs, ax
- mov eax, [bp].s_eip ;put on ip
- mov [ebx][edx].user_ip, ax
- movzx ebx, [bp].s_pushed_int ;get int number
- movzx eax, [ebx * 4].d_offset ;offset portion
- mov [bp].s_eip, eax
- mov ax, [ebx * 4].d_segment ;segment portion
- mov [bp].s_cs, ax
- pop ds
- popad
- add sp, 2 ;get rid of int number
- pop bp
- iretd
- pass_thru endp
-
- ;--------------------------------------------------------------
- ;gen_prot_isr - JMP here if int 0dh. Process as follows: |
- ; |
- ; Look for software int. If found, go route to |
- ; appropriate ISR. |
- ; |
- ; Look for I/O instructions we currently |
- ; support. If found, store port, size and |
- ; direction of I/O. Also, set trap flag and |
- ; return (we will get control at int 1 to |
- ; inspect data). |
- ; |
- ; If other than software int or I/O, go |
- ; display 0dh and halt. |
- ; |
- ;--------------------------------------------------------------
- gen_prot_isr proc near
- push ds
- pushad
- mov bx, offset gdt_seg:sel_databs
- mov ds, bx
- movzx ebx, [bp].e_cs ;get cs of user instruction
- shl ebx, 4 ;make linear
- add ebx, [bp].e_eip ;add ip
- mov ax, [ebx] ;get bytes at cs:ip
- cmp al, INT_OPCODE
- jne get_prot100
- inc [bp].e_eip ;get past the 0cdh
- get_prot050:
- inc [bp].e_eip
- ;
- ;Adjust stack so that error code goes away and int number retrieved from
- ;instruction goes in spot on stack where pushed int number is (for stacks
- ;with no error code). Stack will be the way pass_thru routine likes it.
- ;
- mov bx, [bp].e_pushed_bp
- shl ebx, 16 ;get into high word
- mov bl, ah ;interrupt number
- mov [bp].e_errcode, ebx
- popad
- pop ds
- add sp, 4 ;error code gone
- jmp pass_thru
- get_prot100:
- cmp al, INT3_OPCODE
- jne get_prot150
- mov ah, 3 ;interrupt 3
- jmp short get_prot050
- get_prot150:
-
- mov bx, offset gdt_seg:sel_data
- mov ds, bx
- mov bx, offset io_table
- mov cx, IO_TAB_ENTRIES
- get_prot200:
- cmp al, [bx].io_opcode
- jne get_prot300
- mov trap_status, EXPECT_INT1
- mov cl, [bx].io_info ;get info about instruction
- mov access_info, cl
- mov access_port, dx ;save port
- test cl, CONSTANT ;is port number in instruction?
- jz get_prot250 ;if not, we have it
- xchg ah, al ;ah = 2nd byte of instruction
- sub ah, ah
- mov access_port, ax ;save port
- mov dx, ax
- get_prot250:
- and cx, (AWORD OR ABYTE) ;number of bits
- sub ah, ah ;indicate clear
- call do_bit_map
-
- popad
- pop ds
- or [bp].e_eflags, TRAP_FLAG ;single step i/o
-
- add sp, 2 ;int number pushed
- pop bp
- add sp, 4 ;error code
- iretd
-
- get_prot300:
- add bx, size io_struc ;advance to next table entry
- loop get_prot200
- mov ax, [bp].e_cs ;get cs of user instruction
- call display_it
- mov eax, [bp].e_eip ;add ip
- call display_it
- popad
- pop ds
- mov ax, [bp].e_pushed_int
- jmp fatal_error
- gen_prot_isr endp
-
- ;--------------------------------------------------------------
- ;do_bit_map - For the number of ports specified, clear/set |
- ; corresponding I/O permission map bits. |
- ; |
- ; Enter: Ah = 0 clear, ah = 1 set |
- ; dx = starting port |
- ; cx = number of ports |
- ; |
- ; All registers saved. |
- ;--------------------------------------------------------------
- do_bit_map proc near
- push ax
- push bx
- push cx
- push dx
- push ds
- mov bx, offset gdt_seg:sel_tss_alias
- mov ds, bx
- assume ds:tss_seg
- mov bx, t_iomap
- push cx
- mov cx, dx ;port
- 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
- pop cx
- add bx, dx ;starting offset in map
- do_bit100:
- or ah, ah
- jnz do_bit200
- mov dl, al
- not dl
- and byte ptr [bx], dl ;turn off permission bit
- jmp short do_bit250
- do_bit200:
- or byte ptr [bx], al ;turn on permission bit
- do_bit250:
- rcl al, 1 ;next bit position
- jnc do_bit300
- inc bx
- rcl al, 1
- do_bit300:
- loop do_bit100
- pop ds
- pop dx
- pop cx
- pop bx
- pop ax
- ret
- do_bit_map endp
-
- ;--------------------------------------------------------------
- ;user_int_isr - return buffer address to caller. |
- ; |
- ; Exit: dx:bx= far ptr to store_buf |
- ; ax = 1 if wrapped |
- ; cx = head |
- ;--------------------------------------------------------------
- user_int_isr proc near
- mov dx, data
- mov bx, offset data:store_buf
- push ds
- mov ds,dx
- assume ds:data
- mov cx,store_ptr
- sub cx,offset store_buf
- xor ax,ax
- mov al,store_wrapped
- pop ds
- iret
- user_int_isr endp
- isrcode ends
- end