home *** CD-ROM | disk | FTP | other *** search
Text File | 1989-01-26 | 28.4 KB | 1,116 lines |
- ;ISRS.A86
- title 'Interrupt Service Routines'
- pagesize 59+11
- ;****************************************
- ;* *
- ;* INTERRUPT HANDLERS *
- ;* CPCDOS 6.0 XIOS *
- ;* DRI OS ENGR, JMB, GMS, JW *
- ;* *
- ;****************************************
- ; Major modifications:
- ; 6.x
- ; 6 JAN 89 -- re-program timer every second
- ; 5 JAN 89 -- fix to cure problem with hard disk reads on certain GMS
- ; machines, where the ROS loses a hard disk INT.
- ; 30 Sep 88 -- tick_cursor@ doesn't update if someone has the MX IJ
- ; 9 SEP 88 -- use global chan_sel value for MGE GMS
- ; 3 Aug 88 -- Calls new PCMode user tick entry (if it exists!) IJ
- ; 22 Jul 88 -- Use new dispatcher entry point IJ
- ; 30 JUN 88 -- beep handled in windows1.a86 for MGE GMS
- ; 18 APR 88 -- "intelligent" user_tick code for GEM, etc, PAR
- ; 18 APR 88 -- added MGE support GMS
- ; 11 APR 88 -- last_curs$ variable moved to PUBDATA.A86 GMS
- ; 13 Feb 88 -- Prevent continuous Floppy Motor Off commands JC
- ; 11 DEC 87 -- equip_modes uses ROS video modes GMS
- ; 7 DEC 87 -- VS_SCREEN_MODE now uses ROS video mode values GMS
- ; 2 DEC 87 -- replaced ega$ with redefined video$ GMS
- ; 6.0
- ; 12 NOV 87 -- check tick not being re-entered GMS
- ; 10 NOV 87 -- tick_cursor made public for PCVIDEO cursor update GMS
- ; 1 Nov 87 -- use keyboard controller reset command for Ctl/Alt/Del JW
- ; 22 SEP 87 -- check ROS keyboard buffer, if char inserted do flagset GMS
- ; 22 SEP 87 -- tick_counter replaced with SYSDAT field tod_ticks$ GMS
- ; 23 JUL 87 -- reset timer IRQ on IBM model 80 JW
- ; 5.2
- ; 14 MAY 87 -- re-read real time clock moved to statline routine GMS
- ; 5.2 beta1
- ; 11 MAY 87 -- fix hide cursor on ega bug GMS
- ; 7 MAY 87 -- Auto speed switching for compaq 386 GMS
- ; 29 APR 87 -- Re-read real time clock every minute GMS
- ; 28 JAN 87 -- CDOS 386 protection error code GMS
- ; 5.1
- ; 14 JAN 87 -- Reset cursor update bit in VS_ when hardware cursor updated GMS
- ; 12 JAN 87 -- Bug fix for updating cursor position even if cursor off GMS
- ; 14 NOV 86 -- Change cursor off for Amstrad GMS
- ; 30 Oct 86 -- Previous change removed because the ROS tick count
- ; was corrupted. The user tick is only callled for DOS progs
- ; ES is now set to point to the ROS data area.
- ; 24 OCT 86 -- user tick called every tick if >1 running procs
-
- ; include COPYRITE.TXT
-
- nolist
- include CDOS.EQU
- include PCHW.EQU
- include XIOS.EQU
- include ROSDATA.EQU
- include ASCII.EQU
- if SR
- include SR.EQU
- endif
- list
- ; These have been included:
- ; include PCHW.EQU
- ; include CDOS.EQU
- ; include XIOS.EQU
- ; include ROSDATA.EQU
- ; include ASCII.EQU
- ; include sr.equ
-
- CGROUP group CODE
- DGROUP group isrs_dseg0,isrs_dseg1,isrs_dseg2,isrs_dseg3
-
- public i_clock@, i_tick@, i_nmi@, i_divide@
- public i_overflow@, i_unexpected@, reset@, pc_equip@
- public i_ndp@, beep_counter$, ndp_control$
- public i_seg_ovr@, i_bad_opcode@
- public parity_chk$, tick_cursor@
- if V386
- public fatal_int@ ; for V386
- public fatal_prot$
- public fatal_page$
- endif
- if SR
- public beep_ticks$
- endif
- dseg
-
-
- extrn tick$ :byte ; in HEADER.A86
- extrn dph_tbl$ :word, door$ :byte
- extrn sl_exit_value$ :byte ; in STATLINE.A86
- extrn num_flop$ :word, num_ndp$ :byte ; in PUBDATA.A86
- extrn cloneflag$ :byte
- extrn last_curs$ :word, timer_count$ :word
-
- extrn disk_error$ :byte, disk_on_going$ :byte ; in FLOPPY.A86
- extrn door_count$ :word, pc_at$ :byte
- extrn disk_on_going$ :byte
- extrn motor_flags$ :byte, disk_time_out$ :byte
- extrn hd_rom_seg$ :word, hd_rom_ofs$ :word ; in HDISK.A86
- extrn hd_timer$ :byte, hd_error$ :byte
-
- extrn top_screen$ :byte, video$ :byte ; in WINDOWS3.A86
- extrn kbd_imhere$ :byte, key_flag$ :word ; in KEYBOARD.A86
- if SR
- extrn pc_table$ :word, chan_sel$ :byte ; in SRTERM.A86
- extrn con_basead$ :word, station_on_off$ :byte
- endif
-
- cseg
- extrn supif@ :near, flagset@ :near ; in HEADER.A86
- extrn sysdat$ :word
- extrn io_statline@ :near, sl_error_out@ :near ; in STATLINE.A86
- extrn point_vs@ :near ; in WINDOWS2.A86
- extrn in_window@ :near, video_out@ :near ; in WINDOWS3.A86
- if SR
- extrn sr_reset@ :near, sel_chan@ :near ; in SRTERM.A86
- endif
- eject
-
- ; ****** CLOCK ISR SUBROUTINES ********
- cseg
-
-
- pic_reset:
- ;---------
- ; reset the PIC at the end of the tick service, with a kludge
- ; if it's a model 80
-
- push ax
- if V386
- test pc_at$,2 ; this fixes an incompatibility
- jz not_model80
-
- ; The following code gets called on every tick
- ; for the IBM PS/2 Model 80 (8580).
- ; On their hardware, the timer releases the IRQ
- ; on an interrupt acknowledge cycle for vector 08h
- ; or an OUT to port 61H with the top bit set. As we
- ; reprogram the PIC to use vector 50h, we have to write
- ; to port 61H to release the IRQ before resetting the PIC.
- ; Otherwise we never return from the timer ISR.
-
- push es
- push bx
- mov bx,v386_ptr$
- mov es,tss_seg ; get TSS segment address
- push es:word ptr .74h ; save state of port 61h trap
- and es:byte ptr .74h,not 2 ; enable port 61h
-
- in al,KBD_CONTROL
- or al,80h
- out KBD_CONTROL,al
-
- pop es:word ptr .74h ; restore state of port 61h trap
- pop bx
- pop es
- not_model80:
- endif
-
- mov al,PIC_OCW_SEOI + TIMER_CHANNEL ; pick up end of interrupt word
- out PIC_OCW_PORT,al ; signal EOI
- pop ax
- ret
-
- if not SR
- do_beeps:
- ; Here if we need to handle the speaker:
-
- mov bl,beep_ticks ; put in reg.
- cmp bl,00 ; is this the first time through
- jnz check_beep_tick ; no the leap around set up
- set_beep_tick:
- mov bl,0Ch ; set up for a beep
- mov al,BEEP_CMND ; set up the beep frequency
- out TIMER_CMND_REG,al ; send the command
- mov ax,TIMER_1000_HZ ; get the constant
- out TIMER_2_REG,al
- xchg ah,al
- out TIMER_2_REG,al
- check_beep_tick:
- dec bl ; are we all done with this beep
- jz check_more_beeps ; yes then leap
- cmp bl,2 ; where are we in the beep cycle
- jb turn_beep_off ; low enough to turn off
- in al,PORT_B ; else turn on the beeper
- or al,BEEP_ON
- out PORT_B,al
- jmps do_beeps_done
-
- ; Beep handler continued:
- check_more_beeps:
- dec beep_counter$ ; count down the beep
- jnz set_beep_tick ; not the last set a new one
- turn_beep_off:
- in al,PORT_B ; else get the bits
- and al,BEEP_OFF
- out PORT_B,al ; silence the beeper
- do_beeps_done:
- mov beep_ticks,bl ; replace
- jmp do_beeps_back
-
- to_do_beeps: ; 2 shorts = 1 long
- jmps do_beeps
-
- endif
-
- floppy_motor_off:
- ; handle the DOS diskette motor bytes.
-
- if V386
- cmp cloneflag$,IS_COMPAQ ; COMPAQ 386 ??
- jne dec_motor ; no......
-
- ; COMPAQ 386 auto speed support
- cmp es:motor_count_40,0f0h ; our value
- je is_running
- cmp es:motor_count_40,0ffh ; ROS value
- jnz dec_motor_386
- is_running:
- test es:motor_status_40,07h ; drive running ??
- jz dec_motor_386 ; no...
- in al,86h
- test al,080h ; auto speed select ?
- jz dec_motor_386 ; no...
- test al,040h
- jz dec_motor_386 ; no...
- mov al,92h
- out 4bh,al
- jmps $+2 ! jmps $+2 ! jmps $+2
- mov al,22h
- out 4ah,al
-
- dec_motor_386:
- dec es:motor_count_40
- jnz floppy_motor_off_back1
- test es:motor_status_40,07h ; drive running ??
- jz motor_off ; no...
- in al,86h
- test al,0c0h ; auto speed select ?
- jz motor_off ; no...
- mov al,92h
- out 4bh,al
- jmps motor_off
-
-
- dec_motor:
- ENDIF
-
- dec es:motor_count_40
- jnz floppy_motor_off_back1
- motor_off:
- and es:motor_status_40,0F0h ; indicate motor not running
- mov dx,FDC_PORT
- mov al,FDC_ON ; keep the fdc not reset
- out dx,al
- mov motor_flags$,al ; deselect the motors
- mov disk_on_going$,0FFh ; Prevent further Motor Off Commands
- floppy_motor_off_back1: ; till after the next disk op
- jmp floppy_motor_off_back
-
- eject
-
- ;
- ; User Tick Subroutine
- ;
- ; This is now allways called if there is a tick.
- ;
- ; To make life easier we first update our own
- ; tick count which is a word 0000..FFFF. This
- ; avoids (most of) the wrap problems we would get
- ; otherwise.
- ;
- ; Then, it checks the last time the current VCON
- ; had a user tick and gives it one if if needs it.
- ; Then, at approx 16.8HZ (every 3rd tick) it updates
- ; the ROS data a la PC ROS.
- ;
- ; 15 July 88 - it also checks that if a process is
- ; suspended, and doesn't get a tick for a long
- ; while, we spot it and force a user tick.
- ;
- user_tick:
- dec user_counter ; is it real time?
- jnz user_tick_done ; no, just a simulate
-
- ; we get here approx 16 times a second
-
- cmp word ptr tick_addr$,0 ; do we have a PCMode tick?
- je user_t10 ; if not Skip Code
- callf tick_addr$ ; and let PCMode do the work
-
- user_t10:
- mov user_counter,3 ; Reload the User Counter
- inc es:timer_low_40 ; update ROS count
- jnz user_tick_done ; skip if no ovfl
- inc es:timer_high_40
-
- user_tick_done:
- ret ; return to "main tick"
-
- to_floppy_motor_off:
- jmp floppy_motor_off
-
-
- eject
- ;********************************************************
- ;* *
- ;* CLOCK INTERRUPT HANDLER *
- ;* *
- ;********************************************************
-
- ; The following routine gets control from the 8253-5 on
- ; a timer interrupt. Every effort has been made to eliminate calls, rets,
- ; pushes, pops, and conditional jumps. As a result, readibility has been
- ; sacrificed for performance.
-
- just_iret: ; to bring the label in range
- ; We're here if the timer isr has interrupted the keyboard isr. This happen-
- ; stance is suspected of screwing up the keyboard if the timer isr stays away
- ; too long, so we just immediately return. The jmps below are for a hw
- ; delay, in case the PIC needs it between the time it asserts the IRQ and
- ; the time it gets a EOI. This is patch space for faster CPUs.
-
- ji0: jmps $+2
- jmps ji1
- jmps ji1
- jmps ji1
- jmps ji1
- jmps ji1
- ji1:
- call pic_reset
- pop ds
- iret
-
-
-
- ;-------
- i_clock@:
- ;------- ; interrupts are off
- cli ; but someone may have put on
- cld
- push ds
- mov ds,sysdat$
- test kbd_imhere,0ffh ; a preamble
- jnz just_iret ; forget it if we've nested
-
- test tick_imhere,0ffh
- jnz just_iret
- inc tick_imhere ; make sure we don't get re-entered
-
- mov tickint_ss,ss ; save the registers
- mov tickint_sp,sp
- mov tickint_ax,ax
- mov ss,sysdat$
- mov sp,offset tickint_save_area
-
- push bx ! push cx ! push dx ; This ISR always makes an
- push bp ! push di ! push si ! push es ; OS call...except debug.
-
- mov ax,PC_SEGMENT ; Point ES at the ROS data
- mov es,ax ; Segment
-
- call user_tick ; call "new" user_tick
-
- ; Check for char inserted in ROS keyboard buffer
- test kbd_imhere$,0ffh ; in keyboard routine ?
- jnz check_beep ; yes ... no check
- mov ax,es:buffer_head_40 ; buffer head
- cmp ax,es:buffer_tail_40 ; compare to tail
- jz check_beep
- mov dx,key_flag$ ; char inserted so wake process
- push es
- call flagset@
- pop es
-
- ; Check for speaker handling:
- check_beep:
-
- if not SR ; handled in IO_CONOUT for MGE
- cmp beep_counter$,00 ; test for beeping now
- jz do_beeps_back
- jmp to_do_beeps ; no then leap to the next test
-
- do_beeps_back:
- endif
-
- ; Check for floppy motor time out:
- cmp disk_on_going$,00h ; test for disk operation under way
- jz to_floppy_motor_off ; if not, don't touch motor off counter
- floppy_motor_off_back:
-
- ;; Check for doing a "user_tick", per Tech. Ref.:
- ;; dec user_counter ; do a user tick 1 out of 3
- ;; jz user_tick
- ;;user_tick_back:
-
- eject
-
- ; The following provides pseudo door-open interrupt support to the O.S.
- ; If a disk is not accessed for the programmed time interval,
- ; the door is declared opened. On the next BDOS call, the disk directory
- ; will be read to verify that the same disk is still in there. As a result,
- ; disk changes are more likely to be detected, and disk buffers, hash tables,
- ; etc., may be trusted blindly for the specified interval after the last
- ; disk access, which should give some performance improvement. JW, DRI UK
- sub dx,dx ; start w/ first drive
- clk_dc1:
- mov bx,dx
- shl bx,1 ; word table
- cmp door_count$[bx],0 ; door open count alive?
- jz clk_dc2 ; skip if not
- dec door_count$[bx] ; else count down
- jnz clk_dc2 ; skip if not yet expired
- mov bx,dph_tbl$[bx] ; point to the DPH
- mov DPH_MF[bx],TRUE ; set media flag
- mov door$,TRUE ; and set global flag
- clk_dc2:
- inc dx ; next disk
- cmp dx,num_flop ; is it still a floppy?
- jb clk_dc1 ; yes, ckeck it as well
-
- ; Check diskette op. time out:
- cmp disk_time_out$,0 ; if zero, then it's not being used
- jnz do_disk_time ; so, go about your business
- do_disk_time_back:
- add tick_cnt$,1 ; keep track of system ticks
- adc tick_cnt$+2,0
-
- ; check Hard disk timeout
- cmp hd_timer$,0ffh
- jne do_hd_timeout
- do_hd_back:
-
- ; Check for passage of one second:
- inc tod_ticks$
- cmp tod_ticks$,TICKS_PER_SECOND
- je do_second_flag ; if a second then leap
- do_second_flag_back:
-
- ; Check if we're multi-tasking:
- cmp tick$,0
- jne do_tick_flag
- do_tick_flag_back:
- jmp update_cursor ; skip over subroutines
-
- eject
-
-
- do_disk_time:
- ; Here to handle disk time-out errors:
- dec disk_time_out$ ; if it hasn't timed out
- jnz do_disk_time_back ; then there's no need to worry
- mov disk_error$,80h ; if it has timed out
- mov dx,FDC_FLAG ; then tell the error routine why
- call flagset@ ; and do a flag set to unstick us
- jmp do_disk_time_back
-
- do_hd_timeout:
- ; Here to handle hard disk timeout
- dec hd_timer$
- jnz do_hd_back
- mov es:hf_int_flag_40,0ffh ; set flag to force ROS to wake
- mov es:disk_status1_40,80h ; mark as timeout in ROS
- mov hd_error$,80h ; and for HDISK.A86
- mov hd_timer$,TICKS_PER_SECOND ; reset for multi-sector
- jmp do_hd_back
-
- do_second_flag:
- ; Here to tell the O.S. that a second has passed:
- mov tod_ticks$,0
- mov dx,SEC_FLAG
- call flagset@
- mov ax,timer_count$ ; variable timer count
- out TIMER_0_REG,al
- xchg ah,al
- out TIMER_0_REG,al
- jmp do_second_flag_back
-
- do_tick_flag:
- ; Here to tell the O.S. that a tick has occurred:
- mov dx,TICK_FLAG
- call flagset@
- jmp do_tick_flag_back
-
- ; Update the cursor:
- ; 20 NOV 85 -- the new code to use ROS to set cursor type means that ints. are
- ; enabled w/ an STI on ROS entry. This should not cause a problem because the
- ; timer interrupt is the highest priority and the 8259 should not allow any
- ; lower ints through until it sees an EOI.
- update_cursor:
- cli
- if V386
- push ds
- push bx
- mov bx,v386_ptr$
- mov ds,tss_seg ; get TSS segment
- sub ax,ax
- xchg al,.0DEh ; enable CRT controller access
- sub cx,cx
- xchg cl,.0E2h ; enable CRT controller access
- pop bx
- pop ds
- push ax ; save old state
- push cx
- endif
- if SR
- mov cx,NUM_SR_CONS +1
- mov si,offset pc_table$ ; physical console structures
- mov es,con_basead$ ; get control base address
- mov al,chan_sel$ ; get current selected board
- push ax ; and save
- mov al,0ffh
- update_all_cur:
- push cx ! push si
- call sel_chan@ ; start with master console
- mov si,[si] ; SI -> PC_
- mov dl,PC_TOP_SCREEN ; get top screen VS #
- else
- mov dl,top_screen$
- endif
- call point_vs@ ; point bx to top vs_
- cmp VS_SCREEN_MODE,04
- jb test_43
- cmp VS_SCREEN_MODE,07
- jne timer_interrupt_exit ; exit must be graphics mode
- test_43:
- test VS_MODE1,LINE_43_MODE ; or 43 line mode
- jnz timer_interrupt_exit ; then no cursor update
-
- call tick_cursor@
-
- timer_interrupt_exit:
-
- if SR
- pop si ! pop cx
- mov es,con_basead$ ; get control base address
- mov al,chan_sel$
- next_channel:
- inc al ; select next channel
- inc si ! inc si
- mov di,si
- sub di,offset pc_table$+2
- shr di,1 ; byte ptr
- test byte ptr station_on_off$[di],ON ; is station ON
- jnz do_next
- loop next_channel
- jmps all_done
- do_next:
- loop update_all_cur ; update cursor for all terminals
- all_done:
- pop ax
- call sel_chan@ ; re-select channel
- endif
- if V386
- pop cx
- pop ax
- push ds
- push bx
- mov bx,v386_ptr$
- mov ds,tss_seg ; get TSS segment
- mov .0DEh,al ; restore CRT controller protection
- mov .0E2h,cl ; restore CRT controller protection
- pop bx
- pop ds
- endif
-
- pop es ! pop si ! pop di ! pop bp
- pop dx ! pop cx ! pop bx
-
- cli
- call pic_reset
-
- mov ss,tickint_ss
- mov sp,tickint_sp
-
-
- dec tick_imhere
- mov ax,tickint_ax
-
- jmpf dispatch_addr$ ; go run the next ready process
- ;#IJ pop ds
- ;#IJ jmpf disp_addr$ ; go run the next ready process
-
-
- ;------
- i_tick@: ; "user" tick routine
- ;------
- iret ; do nothing
-
- eject
-
- ; If SunRiver enter with SI = PC_ structure
- tick_cursor@:
- cmp VS_MX,0 ; if within an MX
- je tick_cursor1 ; don't touch the cursor
- ret
- tick_cursor1:
- and VS_MODE,not UPDATE_BIT ; clear cursor moved bit
- mov cx,VS_OFFSET ; update cursor position
- add cx,VS_CORRECT ; whether on or off
- mov al,CURSOR_HI
- if SR
- cmp cx,PC_LAST_CURS
- je no_ch
- mov PC_LAST_CURS,cx
- else
- cmp cx,last_curs$
- je no_ch
- mov last_curs$,cx
- endif
-
- call video_out@
- no_ch:
- test VS_MODE,CURSOR_BIT
- jz old_cursor_off
-
- mov dx,VS_CURSOR
- call in_window@
- jnc put_cur1
-
- old_cursor_off:
- test video$,EGA+VGA ; EGA/VGA ?
- jz not_ega
- ega_off:
- mov cx,01E00h ; code for no curs on ega
- jmps hit_it
- not_ega:
- mov cx,1f1fh ; hide cursor (even on Amstrad)
- cmp cloneflag$,IS_AMSTRAD
- je hit_it
- mov cx,VS_CUR_TYPE ; mono/color/ega
- or ch,20h ; disable bit
- hit_it:
- mov al,CURSOR_START ; cursor display port
- jmp video_out@
-
- put_cur1:
- mov cx,VS_CUR_TYPE_HW ; mono/color/ega/ecd
- mov al,CURSOR_START
- jmp video_out@
- eject
-
- ;********************************************************
- ;* *
- ;* CLOCK INTERRUPT DATA AREA *
- ;* *
- ;********************************************************
-
- isrs_dseg0 dseg
- org 0
- ; 50 levels of tick stack for CROSSTALK:
- dw 0cccch,0cccch,0cccch,0cccch,0cccch,0cccch,0cccch,0cccch
- dw 0cccch,0cccch,0cccch,0cccch,0cccch,0cccch,0cccch,0cccch
- dw 0cccch,0cccch,0cccch,0cccch,0cccch,0cccch,0cccch,0cccch
- dw 0cccch,0cccch,0cccch,0cccch,0cccch,0cccch,0cccch,0cccch
- dw 0cccch,0cccch,0cccch,0cccch,0cccch,0cccch,0cccch,0cccch
- dw 0cccch,0cccch,0cccch,0cccch,0cccch,0cccch,0cccch,0cccch
- dw 0cccch,0cccch
-
- dw 0cccch,0cccch,0cccch,0cccch,0cccch,0cccch,0cccch,0cccch
- dw 0cccch,0cccch,0cccch,0cccch,0cccch,0cccch,0cccch,0cccch
- dw 0cccch,0cccch,0cccch,0cccch,0cccch,0cccch,0cccch,0cccch
- dw 0cccch,0cccch,0cccch,0cccch,0cccch,0cccch,0cccch,0cccch
- dw 0cccch,0cccch,0cccch,0cccch,0cccch,0cccch,0cccch,0cccch
- dw 0cccch,0cccch,0cccch,0cccch,0cccch,0cccch,0cccch,0cccch
- dw 0cccch,0cccch
-
-
- tickint_save_area rs 0
- tickint_ax rw 1 ;storage for interrupted task
- tickint_ss rw 1
- tickint_sp rw 1
-
- beep_counter$ db 0 ; how many control g's
- beep_ticks$ db 0 ; elapsed ticks this beep
- tick_imhere db 0 ; flag in tick routine
-
- vcon_counter rw 32 ; last tick count (per vcon)
- ; --- DEBUG -- MAX 32 VCONS --
- user_counter db 3 ; ROS update counter
- tick_counter dw 0 ; tick counter (0000.FFFF)
-
- ;disp_ticks db DISPATCH_TICKS ; how many to tick before dispatch
-
-
- eject
-
- ;************************************************
- ;* *
- ;* MEMORY PARITY INTERRUPT HANDLER *
- ;* *
- ;************************************************
-
- cseg
- hard8087
-
- ; Real memory parity error interrupt:
-
- i_parity:
- mov ds,sysdat$ ; there's no coming back
- mov es,sysdat$ ; so forget the registers
- mov di,offset parity_p_msg
- call fatal_proc ; store the process name
- mov di,offset parity_a_msg
- call fatal_addr ; store the return address
-
- add beep_counter$,3 ; beep thee thrice
- mov sl_exit_value$,TRUE ; take over the status line
- mov dx,sysdat$
- mov cx,offset parity_msg
- call io_statline@ ; print the error message
-
- sti
- mov bx,4 ; about 1 second
- i_parity_pause:
- loop i_parity_pause ; wait for beeps to end
- dec bx
- jnz i_parity_pause
-
- i_parity_freeze:
- cli
- hlt ; wait here forever
- jmps i_parity_freeze ; and a day
- eject
-
- ;************************************************
- ;* *
- ;* 8088 NMI INTERRUPT HANDLER *
- ;* *
- ;************************************************
-
- i_nmi@:
- ;-----
- ; This handler may be entered:
- ; 1) upon a parity error;
- ; 2) upon an 8087 signal;
- ; 3) upon execution of an INT 2 instr.;
- ; 4) upon execution of an OUT A0,80 (on old PCs).
-
- push ax
- push dx
- push ds
- mov ds,sysdat
- mov dx,parity_chk$
- pop ds
- ; in al,PORT_C
- in al,dx
- test al,0C0h ; look at io_ch_ck and par_ck
- pop dx
- pop ax
- jnz i_parity
-
- push ds
- mov ds,sysdat
- test pc_at$,0ffh ; on an at?
- pop ds
- jnz nmi_ret ; just iret
-
- ; So, was some nasty person doing an OUT A0,al or out dx,al with
- ; DX = 00A0 and al=80?
- push ds
- mov ds,sysdat
- pop ds_save_nmi
- mov bx_save_nmi,bx
- mov ds,ds_save_nmi
-
- cmp al,80h
- jne test_87
- pop bx ; offset
- pop ds ; segment
- push ds
- push bx
- cmp word ptr MIN_2[bx],0A0E6h ; "out A0,al"
- je fake_int
- cmp dx,00A0h ; port number for...
- jne test_87
- cmp byte ptr MIN_1[bx],0EEh ; "out dx,al"
- jne test_87
-
- fake_int:
- ; Here if no 8087, no parity, or out A0,80 performed.
- mov ds,sysdat
- mov bx,bx_save_nmi
- mov ds,ds_save_nmi
- nmi_ret:
- iret
-
- test_87:
- push ds
- mov ds,sysdat
- cmp num_ndp$,1
- pop ds
- jne fake_int
- mov ds,sysdat
- mov bx,bx_save_nmi
- mov ds,ds_save_nmi
- ; jmp i_ndp@
- eject
-
- ;************************************************
- ;* *
- ;* 8087 NDP INTERRUPT HANDLER *
- ;* *
- ;************************************************
- ; Numeric data processor interrupt handler:
-
- i_ndp@:
- ;-----
- push ds ; on user's stack
- mov ds,sysdat$
- mov ndp_ss_save,ss ; save user's stack
- mov ndp_sp_save,sp
- mov ss,sysdat$ ; get our own stack
- mov sp,offset ndp_stack_top
-
- push ax ! push bx ! push cx ! push dx
- push si ! push di ! push bp ! push es
- mov es,sysdat$
-
- FNSTENV env_8087 ; store 8087 environment
- FWAIT ; await completion
- FNCLEX ; clear int request bit
- xor ax,ax
- FNDISI ; disable its int's
-
- mov si,offset env_8087
- mov bx,owner_8087$ ; get current owner
- test bx,bx ; if owner has already
- jz i_ndp_continue ; terminated, skip
-
- mov ax,NDP_STATUS[si] ; if not severe error, continue
- test ax,003Ah ; 3A = under/overflow, precision
- jnz i_ndp_continue ; or denormalized operand
- or P_FLAG[bx],80h ; terminate interrupting process
-
- i_ndp_continue:
- mov byte ptr 2[si],0 ; clear stat word for env restore
-
- pop es ! pop bp ! pop di ! pop si
- pop dx ! pop cx ! pop bx ! pop ax
-
- mov ss,ndp_ss_save ; restore user's stack
- mov sp,ndp_sp_save
- FLDENV env_8087 ; restore 8087 environment
- FWAIT ; await completion
- pop ds
- iret
- eject
-
- ; Numeric data processor interrupt handler data:
-
- isrs_dseg1 dseg
-
- ndp_ss_save rw 1 ; save area for user's stack
- ndp_sp_save rw 1
-
- env_8087 rw 7 ; save area for 8087's stack
- NDP_STATUS equ word ptr 2 ; status word in env_8087
-
- ndp_control$ rw 1 ; for 8087 init routine
-
- rb 32 ; i_ndp@ stack area
- ndp_stack_top rb 0
-
- ds_save_nmi rw 1
- bx_save_nmi rw 1
- parity_chk$ dw PORT_C ; where to read parity checks
- ; set to PORT_B in init if AT
- ; parity error messages:
-
- parity_msg db 'Parity error from '
- parity_p_msg db 'PROCNAME at '
- parity_a_msg db '0000:0000 '
- db ' **** MACHINE IS HALTED! ****'
- db ' '
- eject
-
- ;************************************************
- ;* *
- ;* FATAL INTERRUPT HANDLER *
- ;* *
- ;************************************************
-
- cseg
-
- i_divide@:
- ;--------
- ; Division by zero or any division overflow:
-
- mov si,offset fatal_div ; divide by zero
- jmps fatal_int@
-
- i_overflow@:
- ;----------
- ; Arithmetic overflow when followed by an INTO (int on ovf):
-
- mov si,offset fatal_ovf
- jmps fatal_int@
-
- i_seg_ovr@:
- ;----------
- ; Segment overrun interrupt handler (286), int 13(d):
-
- mov si,offset fatal_seg_ovr
- jmps fatal_int@
-
- i_bad_opcode@:
- ;-------------
- ; Invalid opcode encountered (286), int 6:
- mov si,offset fatal_opcode
- jmps fatal_int@
-
- i_unexpected@:
- ;------------
- ; Any undefined interrupt vectors here:
-
- mov si,offset fatal_unx ; divide by zero
- ; jmps fatal_int@ ; fall through
-
-
- fatal_int@:
- sti ; allow further ints
- mov ds,sysdat$ ; local data segment
- mov es,sysdat$ ; and extra too
- mov di,offset fatal_t_msg ; error type destination
- call fatal_type ; save sub message
- mov di,offset fatal_p_msg ; proc name destination
- call fatal_proc ; save process name
- mov di,offset fatal_a_msg ; address destination
- call fatal_addr ; save come-from addr
-
- mov bx,rlr$ ; get process descriptor
- mov es,P_UDA[bx] ; set up user data area
- inc beep_counter$ ; and extra beep here
- mov si,offset fatal_msg
- mov di,offset fatal_resp ; allow any key
- call sl_error_out@ ; display message
-
- mov bx,rlr$ ; terminate the running process
- and P_FLAG[bx],not (PF_KEEP + PF_TEMPKEEP)
- mov cx,P_TERM
- mov dx,0FFFFh
- jmp supif@ ; process is terminated
- eject
-
- fatal_type:
- ; Store the "type" of fatal interrupt:
-
- mov cx,length fatal_t_msg ; sub message length
- cld
- rep movsb ; store the type of int
- ret
-
- fatal_proc:
- ; Store the process name which caused this mess:
-
- mov bx,rlr$ ; get process descriptor
- lea si,P_NAME[bx] ; point to proc name
- mov cx,8 ; max process name
- cld
- rep movsb ; store the process name
- ret
-
- fatal_addr:
- ; Store the address from whence this interrupt came:
-
- mov bp,sp
- add bp,5 ; look up the stack
- mov bx,offset hex_digits ; for translation
- call fatal_word ; print segment
- inc di ; skip the :
- ; jmp fatal_word ; and offset
-
- fatal_word:
- call fatal_byte ; print ms byte
- ; jmp fatal_byte ; and ls byte
-
- fatal_byte:
- mov al,[bp] ; return byte from stack
- dec bp ; next byte down
- call fatal_nibble ; print ms nibble
- ; jmp fatal_nibble ; and ls nibble
-
- fatal_nibble:
- mov cl,4
- rol al,cl ; ms nibble first
- push ax ; save for ls nibble
- and al,0Fh ; 4 bits only
- xlat bx
- stosb ; store hex code
- pop ax
- ret
- eject
-
- ; Fatal error messages are all in the code seg:
-
- isrs_dseg2 dseg
-
- fatal_msg rb 0
- fatal_t_msg db 'Unexpected'
- db ' Interrupt from '
- fatal_p_msg db 'PROCNAME at '
- fatal_a_msg db '0000:0000 '
- db ' Type any key to stop process. '
-
- fatal_div db ' Division'
- fatal_ovf db ' Overflow'
- fatal_unx db 'Unexpected'
- fatal_seg_ovr db 'Seg. Bound'
- fatal_opcode db 'Bad Opcode'
- fatal_type_len equ offset $ - offset fatal_unx
- if V386
- fatal_prot$ db 'Protection'
- fatal_page$ db 'Page Fault'
- endif
- fatal_resp db 0 ; allow any key
-
- hex_digits db '0123456789ABCDEF'
- eject
-
- cseg
-
- ;************************************************
- ;* *
- ;* RESET FUNCTION - CTRL/ALT/DEL REBOOT *
- ;* *
- ;************************************************
-
- reset@:
- ;------
- if SR
- call sr_reset@ ; de-select cygna card
- endif
- mov ax,PC_SEGMENT
- mov ds,ax ;ROM data segment
- mov reset_flag_40,1234H
- if V386
- mov al,0FEh ; get reset command
- out AT_KBD_STATUS,al ; request CPU reset
- jmps $
- endif
- if XM
- jmpf dword ptr rom_reset ; else jump to ROS reset entry
- endif
-
- ; Reset routine data:
-
- rom_reset dw 0000h,0FFFFh
- eject
- ;************************************************
- ;* *
- ;* PC MODE EQUIPMENT WORD *
- ;* *
- ;************************************************
-
- ; Miscellaneous code and data required for PC_MODE support in XIOS.
- ; MPV 22 NOV 83
-
- ; New XIOS function 32 used to return equipment check word:
-
- pc_equip@:
- ;---------
- mov bx,rlr$ ; ready list root
- mov dl,P_CONS[bx] ; process's console number
- call point_vs@ ; this proc's vc structure
- mov al,VS_SCREEN_MODE
-
- push ds
- mov bx,PC_SEGMENT
- mov ds,bx ; reach into base page
- mov bx,equip_flag_40 ; get IBM's equipment word
- pop ds
- cmp dl,NUM_VIR_CONS ; serial ?
- jb equip_vid ; no
- if not SR
- or bl,00110000b ; else make default console b/w
- endif
- jmps equip_done
-
- equip_vid:
- push es ! push ds ! pop es ; local es for scan
- mov di,offset equip_modes ; list of screen modes to fudge
- mov cx,EQUIP_COUNT ; number to check
- cld ; scan code already in al
- repnz scasb ; search the list
- pop es ; restore es
- jnz equip_done ; if not in the list
-
- and bl,0CFh ; mask off default console
- or bl,.EQUIP_XLAT[di] ; and mash in a fake one
-
- equip_done:
- mov ax,bx ; return equipment word
- ret
-
- isrs_dseg3 dseg
-
- ; These tables are used to make the equipment word look
- ; as if the current monitor/mode were the default value:
-
- equip_modes db 00h,01h,02h,03h ; screen modes to xlat
- db 07h,04h,05h,06h
-
- EQUIP_COUNT equ offset $ - offset equip_modes
- EQUIP_XLAT equ EQUIP_COUNT - 1
-
- db 10h,10h,20h,20h ; equip word xlations
- db 30h,20h,20h,20h
- eject
-
- end
-
- ; END OF ISRS.A86
-