; ; TCtask - Timer interrupt handler (IBM specific) ; ; V1.1 T.Wagner ; V1.2 TECON Ltd. ; name tctim ; .model large ; public tsk_install_timer_ public tsk_remove_timer_ ; public _tsk_chain_timer ; include tsk.mac ; timer equ 40h ; 8253 timer base I/O address inta00 equ 20h ; 8259 int controller base eoi equ 20h ; unspecific EOI tint=8h .data ; extrn _tsk_timer_counter:word ; extrn _tsk_int9_counter:word ; divisor dw ? timcnt dw ? sys_ticks dw ? timflag dw ? stat_int db ? ; .code ; extrn _sched_int:near extrn inc_counter_:near ; timer_save label fword ; in CSEG to allow addressing tsofs dd ? tsseg dw ? ; .code ;---------------------------------------------------------------------- ; ; timer interrupt handler ; timer_int proc push ds push eax mov ax,seg timflag mov ds,ax mov al,eoi ; issue EOI out inta00,al mov al,0bh ; access int control reg out inta00,al in al,inta00 ; ints pending? mov ds:stat_int,al dec ds:timcnt ; decrement tick count jne no_pass ; pass on this int if zero mov ax,ds:sys_ticks mov ds:timcnt,ax ; re-init tick counter pop eax pop ds pushfd call fword ptr cs:timer_save push ds push eax no_pass: cli ; push ds ; push eax mov ax,seg timflag mov ds,ax ; cmp timflag,1 ; initialisation ? jne no_init ; ; Install timer ; mov timcnt,1 mov timflag,0 ; signal init ready mov al,36h out timer+3,al ; setup to load divisor mov al,byte ptr divisor out timer,al ; lsb mov al,byte ptr divisor+1 out timer,al ; msb jmp short no_uninit ; no_init: cmp timflag,2 ; un-install flag set? jne no_uninit ; no un-install if not jmp uninit ; ;-------------------------------------------------------------------- ; ; Normal timer tick. The tick counter is incremented, and ; the interrupt controller is checked for other pending interrupts. ; If the timer tick occurred during processing of another interrupt, ; we may not call the scheduler, since this would delay the ; interrupt handler. ; ; Note that an EOI is issued here to allow interrupts to occur ; during further processing. The original INT 9 handler will be ; chained to from a special task. The reason behind this is that ; some TSR's link into the timer interrupt and may do some lengthy ; processing there. To allow the TSR to be preempted, we must use ; a task for the INT 9 processing. ; no_uninit: sti mov eax,offset _tsk_timer_counter call inc_counter_ ; increase timer tick counter mov al,stat_int or al,al pop eax jnz no_sch ; don't schedule if other ints active sti jmp _sched_int ; else schedule ; no_sch: pop ds iretd ; ;------------------------------------------------------------------------ ; ; Uninstall timer int handler ; uninit: mov timflag,0 ; mark un-install complete mov al,36h ; setup to load divisor out timer+3,al mov al,0 ; divisor 0 means 65536 out timer,al ; lsb out timer,al ; msb mov bl,tint mov ax,205h ;Установка вектора 8 на DS:EDX mov edx, tsofs mov cx, tsseg int 31h pop eax pop ds jmp fword ptr [timer_save] ; pass on interrupt ; timer_int endp ; ;---------------------------------------------------------------------- ; ; void far tsk_chain_timer (void) ; ; Pass timer tick on to interrupt 9 chain. ; ;_tsk_chain_timer proc ; ; pushfd ; cli ; call fword ptr [timer_save] ; ret ; ;_tsk_chain_timer endp ; ; ; void far tsk_install_timer (word divisor, word sys_ticks) ; ; This routine installs the timer tick int handler. ; The timer chip is reprogrammed on the next tick. ; tsk_install_timer_ proc ; push eax push ebx push edx push ecx mov divisor,ax mov sys_ticks,dx mov timflag,1 ; set init-flag mov bl,tint mov ax,204h ;Чтение вектора прерывания 8 = es:ebx int 31h mov tsofs,edx mov tsseg,cx cli mov bl,tint mov ax,205h ;Установка вектора 8 на DS:EDX mov edx,offset timer_int mov cx,cs int 31h sti wait_set: cmp timflag,0 ; wait until timer started jne wait_set pop ecx pop edx pop ebx pop eax ret ; tsk_install_timer_ endp ; ; ; void far tsk_remove_timer (void) ; ; This routine un-installs the timer tick int handler. ; The timer chip is reprogrammed & the interrupt vector ; restored when the system tick count reaches zero. ; tsk_remove_timer_ proc ; mov timflag,2 ; set un-init flag for timer wait_tim: sti ; just to be safe cmp timflag,0 ; wait until int un-installed jne wait_tim ret ; tsk_remove_timer_ endp ; end