home *** CD-ROM | disk | FTP | other *** search
- ;
- ; in_drive.asm
- ;
- ; Purpose: Interrupt primitives.
- ;
- ; Blackstar C Function Libarary
- ; (c) Copyright 1985,1989 Sterling Castle Software
- ;
-
- include model
- include blackstr.mac
-
-
- busyf equ 'B'; busy flag - already servicing
- msdosf equ 21h; interrupt for msdos function
- EOI equ 20h; end of interrupt
- m8259 equ 20h; interrupt controller port
- i8259 equ 21h;
-
- dseg 'DATA'
-
- ; interrupt structure and tables
-
- interrupt struc
- vector dw ? ;service vector offset
- chainf db 0 ;interrupt type (repl/chain)
- no db 0 ;int vector number
- roff dw ? ;interrupt routine
- rseg dw ? ;routine segment
- soff dw ? ;stack location
- sseg dw ? ;stack segment
- coff dw ? ;chain to vector
- csegg dw ? ;chain to segment
- interrupt ends
-
- int_table LABEL WORD
- int0 interrupt <,,,,,>
- int1 interrupt <,,,,,>
- int2 interrupt <,,,,,>
- int3 interrupt <,,,,,>
-
- no_ints db 0 ;number of interrupts set
- int_set db 0 ;interrupt number to set
- ifdef Large_code
- ALIAS function DWORD
- else
- ALIAS function WORD
- endif
- funoff dw 00 ;function offset
- funseg dw 00 ;function segment
-
- ; Local stack
-
- sstk db 'Start of stack';start of stack
- stck_m db 256 dup(?)
- pstack equ $-2 ;start it here
- estk db 'End of stack' ;end of stack
-
- enddseg
-
-
- cseg in_servc_
-
- istatus db 0 ;busy/idle for all interrupts
- int_no db ? ;interrupt being serviced
- itype db 0 ;type of interrupt
- choff dw ? ;function to chain to
- chseg dw ?
-
- ;--------------------------------
- ; Interrupt service vectors
- ;---------------------------------
- public int0_vec
-
- int0_vec proc far
- mov cs:int_no,0
- jmp in_servc_
- int0_vec endp
- int1_vec proc far
- mov cs:int_no,1
- jmp in_servc_
- int1_vec endp
- int2_vec proc far
- mov cs:int_no,2
- jmp in_servc_
- int2_vec endp
- int3_vec proc far
- mov cs:int_no,3
- jmp in_servc_
- int3_vec endp
-
- ; Interrupt service vector table
-
- int_vtbl:
- ifdef Small_code
- dw offset cgroup: int0_vec
- dw offset cgroup: int1_vec
- dw offset cgroup: int2_vec
- dw offset cgroup; int3_vec
- else
- dw int0_vec
- dw int1_vec
- dw int2_vec
- dw int3_vec
- endif
-
-
- ;-----------------
- ; in_servc_ dispatcher for interrupt service routine
- ;-----------------
-
- public in_servc_
-
- in_servc_ proc
- cmp byte ptr cs:istatus,busyf ;already servicing
- je short int_x
-
- servc1: mov byte ptr cs:istatus,busyf ;make it busy
- push eax
- push ebx
- push ecx
- push edx
- push edi
- push esi
- push ebp
- push ds
- push es
-
- ; set to this data seg
-
- mov eax,seg dgroup
- mov ds,eax ;point ds to dgroup
- mov es,eax ;and es
-
- ; find interrupt number to use for stack,service,and vector
-
- mov al,int_no
- cbw
- mov cl,4
- sal eax,cl ;*16 bytes per int struc
- mov ebx,offset dgroup:int_table
- add ebx,eax
-
- ; set up our own stack
-
- mov edx,ss ;save old stack on stack
- mov ecx,esp
- cli
- mov ss,[ebx.sseg] ;set stack segment to here
- mov esp,[ebx.soff]
- push edx
- push ecx ;save old stack
- sti
- mov eax,[ebx.coff] ;get chain to
- mov cs:choff,eax
- mov eax,[ebx.csegg] ;chain seg
- mov cs:chseg,eax
- mov eax,[ebx.rseg] ;get segment
- mov funseg,eax
- mov eax,[ebx.roff] ;and offset to function area
- mov funoff,eax
-
- ifdef Large_code
- call dword ptr [function]
- else
- call [function]
- endif
-
-
- ;------------
- ; int_exit exit from interrupt
- ;------------
-
- ; restore beginning stack
-
- pop ecx
- pop ebx
- cli
- mov esp,ecx
- mov ss,ebx
- sti
- pop es
- pop ds
- pop ebp
- pop esi
- pop edi
- pop edx
- pop ecx
- pop ebx
- pop eax
- mov byte ptr cs:istatus,0 ;no more busy
- cmp cs:itype,1
- jnz short int_x
-
- ; do end of interrupt for hardware - no chain
-
- push eax ;save eax
- mov al,EOI ;get end
- out m8259,al ;output it
- pop eax
-
- int_x LABEL NEAR
- jmp dword ptr cs:[choff] ;chain to next
- in_servc_ endp
-
-
- ;------------------
- ; in_set_ set interrupts on/off
- ;------------------
- ; Usage: in_set(ON/OFF);
- ;
- ; int in_set(int toggle);
-
- public in_set_
-
- in_set_ proc
- parm386<<toggle,dword>>
- parm86<<toggle,word>>
- prolog
-
- mov eax,toggle
- cmp eax,0
- cli ;disable interrupts is default
- jnz dis
- sti ; turn on interrupts
- dis:
- epilog
- in_set_ endp
-
-
- ;--------------------
- ; in_setvec_ set interrupt vector
- ;--------------------
- ;
- ; Usage: vec# = in_setvec_(vec#,function,stack,type)
- ; where type = 0 <no hardware, no chain)
- ; 1 (hardware,no chain)
- ; 2 (no hardware, chain)
- ; 3 (hardware, chain)
-
- public in_setvec_
-
- in_setvec_ proc
- parm386<<vec,dword>,<foff,dword>,<fseg,word>,<stoff,dword>,<stseg,word>,<choice,dword>>
- parm86<<vec,word>,<foff,word>,<fseg,word>,<stoff,word>,<stseg,word>,<choice,word>>
- prolog
-
- ; point ebx to interrupt vector structures
-
- ifdef Large_data
- mov ax,seg dgroup
- mov ds,ax
- endif
-
- mov al,no_ints ;update # interrupts
- mov int_set,al ;save it
- inc no_ints ;update number
- cbw
- mov ebx,offset dgroup:int_table
- mov cl,4 ;16 bytes per struc
- shl eax,cl
- add ebx,eax
- mov eax,vec ;get vector #
- mov [ebx.no],al ;save in interrupt struc
-
- ; now get function to service interrupt
-
- mov eax,foff ;get offset of routine
- mov [ebx.roff],eax
- mov eax,fseg ;get segment
- mov [ebx.rseg],eax
-
-
- ; get stack to use with interrupt
-
- mov eax,stoff ;save stack offset
- mov [ebx.soff],eax
- mov eax,stseg ;save stack segment
- mov [ebx.sseg],eax
-
- ; get chain to function
-
- mov eax,choice ;chainf flag
- mov byte ptr [ebx.chainf], al ;save in interrupt struc
- mov cs:itype,al ;and interrupt type
- cmp eax,2 ;0&1 are no chain,3&4=chain
- jge short set2
-
- ; No chain, use dummy iret
-
- mov eax,offset cs:in_iret
- mov edx,cs
- jmp short set3
-
- ; get existing interrupt function to chain to
-
- set2: mov al,[ebx.no] ;get int vector #
- push es
- push ebx
- doscall 35h ;get interrupt vector function
- mov eax,ebx
- mov edx,es ;to eax,edx
- pop ebx
- pop es
-
- set3: mov [ebx.coff],eax
- mov [ebx.csegg],edx ;put chain routine in
-
- ; now set the bios vector interrupt
-
- mov ebp,offset cs:int_vtbl ;point to vector table
- mov al,int_set ;get number being set
- cbw
- sal eax,1 ;times 2 bytes/address
- add ebp,eax
- mov edx,cs:[ebp] ;offset of int
- mov al,[ebx.no] ;interrupt # to set
- mov ecx,cs ;use this segment
- push ds
- mov ds,ecx
- doscall 25h ;set interrupt vector function
- pop ds ;restore ds
- mov al,int_set ;return vector #
- cbw
-
- epilog
- in_setvec_ endp
-
-
- ;--------------------
- ; in_remvec_ remove an interrupt vector
- ;--------------------
- ; Usage: in_remvec_(number);
- ; where number was returned by in_setvec_
- ;
- ; int in_remvec_(int number);
-
- public in_remvec_
-
- in_remvec_ proc
- parm386<<number,dword>>
- parm86<<number,word>>
- prolog
-
- ifdef Large_data
- mov ax, seg dgroup
- mov ds,ax
- endif
-
- mov eax,number ;get vector number
- mov ebx,offset dgroup:int_table
- mov cl,4
- sal eax,cl ;16 bytes/table
- mov al,[ebx.no] ;get vector number to set
- mov edx,[ebx.coff] ;reset to chain routine
- mov ecx,[ebx.csegg]
- push ds
- mov ds,ecx
- doscall 25h ; do dos set interrupt call
- pop ds
-
- ifdef asm_386
- movsx eax,ax
- endif
-
- epilog
- in_remvec_ endp
-
-
- ;--------------------
- ; in_hdwren_ hardware enable/disable
- ;--------------------
- ; Usage: in_hdwren_ (level,ON/OFF)
- ;
- ; in_hdwren_(int level, int toggle);
-
- public in_hdwren_
-
- in_hdwren_ proc
- parm386<<level,dword>,<toggle,dword>>
- parm86<<level,word>,<toggle,word>>
- prolog
-
- ifdef Large_data
- mov ax,seg dgroup
- mov ds,ax
- endif
-
- mov eax,1 ;start with bit 0
- mov ecx,level ;get number to set
- shl eax,cl ;shift to bit
- not al
- mov ebx,eax
- in al,i8259 ;get current
- and al,bl ;turn it off
- mov edx,toggle ;on or off
- cmp edx,0
- jz hdrw1
-
- not al
- or al,bl ;add this one
-
- hdrw1: out i8259,al ;enable it
-
- epilog
- in_hdwren_ endp
-
-
- ;---------------------
- ; in_iret dummy chain function
- ;--------------------
- ; Usage: in_iret();
- ;
- ; int in_iret(void);
-
- public in_iret
-
- in_iret proc
- iret
- in_iret endp
-
- endcseg in_servc_
- end
-
-