home *** CD-ROM | disk | FTP | other *** search
/ Piper's Pit BBS/FTP: ibm 0010 - 0019 / ibm0010-0019 / ibm0010.tar / ibm0010 / CDOSDSK4.ZIP / CDOSDSK4.TD0 / XIOS / ISRS.A86 < prev    next >
Encoding:
Text File  |  1989-01-26  |  28.4 KB  |  1,116 lines

  1. ;ISRS.A86
  2. title 'Interrupt Service Routines'
  3. pagesize 59+11
  4. ;****************************************
  5. ;*                    *
  6. ;*    INTERRUPT HANDLERS        *
  7. ;*    CPCDOS 6.0 XIOS            *
  8. ;*    DRI OS ENGR, JMB, GMS, JW    *
  9. ;*                    *
  10. ;****************************************
  11. ; Major modifications:
  12. ; 6.x
  13. ;  6 JAN 89 -- re-program timer every second
  14. ;  5 JAN 89 -- fix to cure problem with hard disk reads on certain      GMS
  15. ;        machines, where the ROS loses a hard disk INT.
  16. ; 30 Sep 88 -- tick_cursor@ doesn't update if someone has the MX    IJ
  17. ;  9 SEP 88 -- use global chan_sel value for MGE            GMS
  18. ;  3 Aug 88 -- Calls new PCMode user tick entry (if it exists!)        IJ
  19. ; 22 Jul 88 -- Use new dispatcher entry point                IJ
  20. ; 30 JUN 88 -- beep handled in windows1.a86 for MGE            GMS
  21. ; 18 APR 88 -- "intelligent" user_tick code for GEM, etc,            PAR
  22. ; 18 APR 88 -- added MGE support                    GMS
  23. ; 11 APR 88 -- last_curs$ variable moved to PUBDATA.A86            GMS
  24. ; 13 Feb 88 -- Prevent continuous Floppy Motor Off commands        JC
  25. ; 11 DEC 87 -- equip_modes uses ROS video modes                GMS
  26. ;  7 DEC 87 -- VS_SCREEN_MODE now uses ROS video mode values        GMS
  27. ;  2 DEC 87 -- replaced ega$ with redefined video$            GMS
  28. ; 6.0
  29. ; 12 NOV 87 -- check tick not being re-entered                GMS
  30. ; 10 NOV 87 -- tick_cursor made public for PCVIDEO cursor update    GMS
  31. ;  1 Nov 87 -- use keyboard controller reset command for Ctl/Alt/Del    JW
  32. ; 22 SEP 87 -- check ROS keyboard buffer, if char inserted do flagset    GMS
  33. ; 22 SEP 87 -- tick_counter replaced with SYSDAT field tod_ticks$    GMS
  34. ; 23 JUL 87 -- reset timer IRQ on IBM model 80                JW
  35. ; 5.2
  36. ; 14 MAY 87 -- re-read real time clock moved to statline routine    GMS
  37. ; 5.2 beta1
  38. ; 11 MAY 87 -- fix hide cursor on ega bug                GMS
  39. ;  7 MAY 87 -- Auto speed switching for compaq 386            GMS
  40. ; 29 APR 87 -- Re-read real time clock every minute            GMS
  41. ; 28 JAN 87 -- CDOS 386 protection error code                GMS
  42. ; 5.1
  43. ; 14 JAN 87 -- Reset cursor update bit in VS_ when hardware cursor updated GMS
  44. ; 12 JAN 87 -- Bug fix for updating cursor position even if cursor off  GMS
  45. ; 14 NOV 86 -- Change cursor off for Amstrad                GMS
  46. ; 30 Oct 86 -- Previous change removed because the ROS tick count
  47. ;           was corrupted. The user tick is only callled for DOS progs
  48. ;           ES is now set to point to the ROS data area.
  49. ; 24 OCT 86 -- user tick called every tick if >1 running procs
  50.  
  51. ; include COPYRITE.TXT
  52.  
  53. nolist
  54. include CDOS.EQU
  55. include PCHW.EQU
  56. include XIOS.EQU
  57. include ROSDATA.EQU
  58. include ASCII.EQU
  59. if SR
  60. include SR.EQU
  61. endif
  62. list
  63. ; These have been included:
  64. ; include PCHW.EQU
  65. ; include CDOS.EQU
  66. ; include XIOS.EQU
  67. ; include ROSDATA.EQU
  68. ; include ASCII.EQU
  69. ; include sr.equ
  70.  
  71. CGROUP    group    CODE
  72. DGROUP    group    isrs_dseg0,isrs_dseg1,isrs_dseg2,isrs_dseg3
  73.  
  74. public    i_clock@, i_tick@, i_nmi@, i_divide@
  75. public    i_overflow@, i_unexpected@, reset@, pc_equip@
  76. public    i_ndp@, beep_counter$, ndp_control$
  77. public    i_seg_ovr@, i_bad_opcode@
  78. public    parity_chk$, tick_cursor@
  79. if V386
  80. public    fatal_int@                    ; for V386
  81. public    fatal_prot$
  82. public    fatal_page$
  83. endif
  84. if SR
  85. public    beep_ticks$
  86. endif
  87.     dseg
  88.  
  89.  
  90. extrn    tick$        :byte                ; in HEADER.A86
  91. extrn    dph_tbl$    :word, door$        :byte
  92. extrn    sl_exit_value$    :byte                ; in STATLINE.A86
  93. extrn    num_flop$    :word, num_ndp$        :byte    ; in PUBDATA.A86
  94. extrn    cloneflag$      :byte
  95. extrn    last_curs$    :word, timer_count$     :word
  96.  
  97. extrn    disk_error$    :byte, disk_on_going$    :byte    ; in FLOPPY.A86
  98. extrn    door_count$    :word, pc_at$        :byte
  99. extrn    disk_on_going$    :byte
  100. extrn    motor_flags$    :byte, disk_time_out$    :byte
  101. extrn    hd_rom_seg$    :word, hd_rom_ofs$    :word    ; in HDISK.A86
  102. extrn    hd_timer$    :byte, hd_error$    :byte
  103.  
  104. extrn    top_screen$    :byte, video$        :byte    ; in WINDOWS3.A86
  105. extrn    kbd_imhere$    :byte, key_flag$    :word    ; in KEYBOARD.A86
  106. if SR
  107. extrn    pc_table$    :word, chan_sel$    :byte    ; in SRTERM.A86
  108. extrn    con_basead$    :word, station_on_off$    :byte
  109. endif
  110.  
  111.     cseg
  112. extrn    supif@        :near, flagset@        :near    ; in HEADER.A86
  113. extrn    sysdat$        :word
  114. extrn    io_statline@    :near, sl_error_out@    :near    ; in STATLINE.A86
  115. extrn    point_vs@    :near                ; in WINDOWS2.A86
  116. extrn    in_window@    :near, video_out@    :near    ; in WINDOWS3.A86
  117. if SR
  118. extrn    sr_reset@    :near, sel_chan@    :near    ; in SRTERM.A86
  119. endif
  120. eject
  121.  
  122. ; ****** CLOCK ISR SUBROUTINES ********
  123.     cseg
  124.  
  125.  
  126. pic_reset:
  127. ;---------
  128. ; reset the PIC at the end of the tick service, with a kludge
  129. ; if it's a model 80
  130.  
  131.     push    ax
  132. if V386
  133.     test    pc_at$,2        ; this fixes an incompatibility
  134.     jz    not_model80
  135.     
  136. ;    The following code gets called on every tick
  137. ;    for the IBM PS/2 Model 80 (8580).
  138. ;    On their hardware, the timer releases the IRQ
  139. ;    on an interrupt acknowledge cycle for vector 08h
  140. ;    or an OUT to port 61H with the top bit set. As we
  141. ;    reprogram the PIC to use vector 50h, we have to write
  142. ;    to port 61H to release the IRQ before resetting the PIC.
  143. ;    Otherwise we never return from the timer ISR.
  144.  
  145.     push    es
  146.     push    bx
  147.     mov    bx,v386_ptr$
  148.     mov    es,tss_seg        ; get TSS segment address
  149.     push    es:word ptr .74h    ; save state of port 61h trap
  150.     and    es:byte ptr .74h,not 2    ; enable port 61h
  151.  
  152.     in    al,KBD_CONTROL
  153.     or    al,80h
  154.     out    KBD_CONTROL,al
  155.  
  156.     pop    es:word ptr .74h    ; restore state of port 61h trap
  157.     pop    bx
  158.     pop    es
  159. not_model80:
  160. endif
  161.  
  162.     mov    al,PIC_OCW_SEOI + TIMER_CHANNEL    ; pick up end of interrupt word
  163.     out    PIC_OCW_PORT,al            ; signal EOI
  164.     pop    ax
  165.     ret
  166.  
  167. if not SR
  168. do_beeps:
  169. ; Here if we need to handle the speaker:
  170.  
  171.     mov    bl,beep_ticks            ; put in reg.
  172.     cmp    bl,00                ; is this the first time through
  173.      jnz    check_beep_tick            ; no the leap around set up
  174. set_beep_tick:
  175.     mov    bl,0Ch                ; set up for a beep
  176.     mov    al,BEEP_CMND            ; set up the beep frequency
  177.     out    TIMER_CMND_REG,al        ; send the command
  178.     mov    ax,TIMER_1000_HZ        ; get the constant
  179.     out    TIMER_2_REG,al
  180.     xchg    ah,al
  181.     out    TIMER_2_REG,al
  182. check_beep_tick:
  183.     dec    bl                ; are we all done with this beep
  184.      jz    check_more_beeps        ; yes then leap
  185.     cmp    bl,2                ; where are we in the beep cycle
  186.      jb    turn_beep_off            ; low enough to turn off
  187.     in    al,PORT_B            ; else turn on the beeper
  188.     or    al,BEEP_ON
  189.     out    PORT_B,al
  190.     jmps    do_beeps_done
  191.  
  192. ; Beep handler continued:
  193. check_more_beeps:
  194.     dec    beep_counter$            ; count down the beep
  195.      jnz    set_beep_tick            ; not the last set a new one
  196. turn_beep_off:
  197.     in    al,PORT_B            ; else get the bits
  198.     and    al,BEEP_OFF
  199.     out    PORT_B,al            ; silence the beeper
  200. do_beeps_done:
  201.     mov    beep_ticks,bl            ; replace
  202.     jmp    do_beeps_back
  203.  
  204. to_do_beeps:                    ; 2 shorts = 1 long
  205.     jmps    do_beeps
  206.  
  207. endif
  208.  
  209. floppy_motor_off:
  210. ; handle the DOS diskette motor bytes.  
  211.  
  212. if V386
  213.     cmp    cloneflag$,IS_COMPAQ        ; COMPAQ 386 ??
  214.     jne    dec_motor            ; no......
  215.  
  216. ; COMPAQ 386 auto speed support
  217.     cmp    es:motor_count_40,0f0h        ; our value
  218.     je    is_running
  219.     cmp    es:motor_count_40,0ffh        ; ROS value
  220.     jnz    dec_motor_386
  221. is_running:
  222.     test    es:motor_status_40,07h        ; drive running ??
  223.     jz    dec_motor_386            ; no...
  224.     in    al,86h        
  225.     test    al,080h                ; auto speed select ?
  226.     jz    dec_motor_386            ; no...
  227.     test    al,040h
  228.     jz    dec_motor_386            ; no...
  229.     mov    al,92h
  230.     out    4bh,al
  231.     jmps $+2 ! jmps $+2 ! jmps $+2
  232.     mov    al,22h
  233.     out    4ah,al    
  234.  
  235. dec_motor_386:
  236.     dec    es:motor_count_40        
  237.      jnz    floppy_motor_off_back1
  238.     test    es:motor_status_40,07h        ; drive running ??
  239.     jz    motor_off            ; no...
  240.     in    al,86h        
  241.     test    al,0c0h                ; auto speed select ?
  242.     jz    motor_off            ; no...
  243.     mov    al,92h
  244.     out    4bh,al
  245.     jmps    motor_off
  246.     
  247.  
  248. dec_motor:
  249. ENDIF
  250.  
  251.     dec    es:motor_count_40
  252.      jnz    floppy_motor_off_back1
  253. motor_off:
  254.     and    es:motor_status_40,0F0h        ; indicate motor not running
  255.     mov    dx,FDC_PORT
  256.     mov    al,FDC_ON            ; keep the fdc not reset
  257.     out    dx,al
  258.     mov    motor_flags$,al            ; deselect the motors
  259.     mov    disk_on_going$,0FFh        ; Prevent further Motor Off Commands
  260. floppy_motor_off_back1:                ; till after the next disk op
  261.     jmp    floppy_motor_off_back
  262.  
  263. eject
  264.  
  265. ;
  266. ; User Tick Subroutine
  267. ;
  268. ;    This is now allways called if there is a tick.
  269. ;
  270. ;    To make life easier we first update our own
  271. ;    tick count which is a word 0000..FFFF.  This 
  272. ;    avoids (most of) the wrap problems we would get 
  273. ;    otherwise.
  274. ;
  275. ;    Then, it checks the last time the current VCON 
  276. ;    had a user tick and gives it one if if needs it.
  277. ;    Then, at approx 16.8HZ (every 3rd tick) it updates 
  278. ;    the ROS data a la PC ROS.  
  279. ;
  280. ;    15 July 88 - it also checks that if a process is 
  281. ;    suspended, and doesn't get a tick for a long 
  282. ;    while, we spot it and force a user tick.
  283. ;
  284. user_tick:
  285.     dec    user_counter            ; is it real time?
  286.      jnz     user_tick_done            ; no, just a simulate
  287.  
  288.         ; we get here approx 16 times a second
  289.      
  290.     cmp    word ptr tick_addr$,0        ; do we have a PCMode tick?
  291.     je    user_t10            ; if not Skip Code
  292.     callf    tick_addr$            ; and let PCMode do the work
  293.  
  294. user_t10:
  295.     mov    user_counter,3            ; Reload the User Counter
  296.     inc    es:timer_low_40            ; update ROS count
  297.      jnz    user_tick_done             ; skip if no ovfl
  298.     inc    es:timer_high_40
  299.  
  300. user_tick_done:
  301.     ret                    ; return to "main tick"
  302.  
  303. to_floppy_motor_off:
  304.     jmp    floppy_motor_off
  305.  
  306.     
  307. eject
  308. ;********************************************************
  309. ;*                            *
  310. ;*        CLOCK INTERRUPT HANDLER            *
  311. ;*                            *
  312. ;********************************************************
  313.  
  314. ; The following routine gets control from the 8253-5 on
  315. ; a timer interrupt.  Every effort has been made to eliminate calls, rets,
  316. ; pushes, pops, and conditional jumps.  As a result, readibility has been
  317. ; sacrificed for performance.
  318.  
  319. just_iret:                    ; to bring the label in range
  320. ; We're here if the timer isr has interrupted the keyboard isr.  This happen-
  321. ; stance is suspected of screwing up the keyboard if the timer isr stays away
  322. ; too long, so we just immediately return.  The jmps below are for a hw
  323. ; delay, in case the PIC needs it between the time it asserts the IRQ and
  324. ; the time it gets a EOI.  This is patch space for faster CPUs.
  325.  
  326. ji0:    jmps $+2
  327.     jmps ji1
  328.     jmps ji1
  329.     jmps ji1
  330.     jmps ji1
  331.     jmps ji1
  332. ji1:
  333.     call    pic_reset
  334.     pop    ds
  335.     iret
  336.  
  337.  
  338.  
  339. ;-------
  340. i_clock@:
  341. ;-------                    ; interrupts are off
  342.     cli                    ;  but someone may have put on
  343.     cld
  344.     push    ds
  345.     mov    ds,sysdat$
  346.     test    kbd_imhere,0ffh            ;  a preamble
  347.      jnz    just_iret            ; forget it if we've nested
  348.  
  349.     test    tick_imhere,0ffh
  350.     jnz    just_iret
  351.     inc    tick_imhere            ; make sure we don't get re-entered
  352.  
  353.     mov    tickint_ss,ss            ; save the registers
  354.     mov    tickint_sp,sp
  355.     mov    tickint_ax,ax
  356.     mov    ss,sysdat$
  357.     mov    sp,offset tickint_save_area
  358.  
  359.     push bx ! push cx ! push dx        ; This ISR always makes an
  360.     push bp ! push di ! push si ! push es    ; OS call...except debug.
  361.  
  362.     mov    ax,PC_SEGMENT            ; Point ES at the ROS data
  363.     mov    es,ax                ; Segment
  364.  
  365.     call    user_tick            ; call "new" user_tick
  366.  
  367. ; Check for char inserted in ROS keyboard buffer
  368.     test    kbd_imhere$,0ffh        ;  in keyboard routine ?
  369.     jnz    check_beep            ; yes ... no check
  370.     mov    ax,es:buffer_head_40        ; buffer head
  371.     cmp    ax,es:buffer_tail_40        ; compare to tail
  372.     jz    check_beep
  373.     mov    dx,key_flag$            ; char inserted so wake process
  374.     push    es
  375.     call    flagset@
  376.     pop    es
  377.     
  378. ; Check for speaker handling:
  379. check_beep:
  380.  
  381. if not SR            ; handled in IO_CONOUT for MGE
  382.     cmp    beep_counter$,00        ; test for beeping now
  383.      jz    do_beeps_back
  384.      jmp    to_do_beeps            ; no then leap to the next test
  385.  
  386. do_beeps_back:
  387. endif
  388.  
  389. ; Check for floppy motor time out:
  390.     cmp    disk_on_going$,00h        ; test for disk operation under way
  391.      jz    to_floppy_motor_off        ; if not, don't touch motor off counter
  392. floppy_motor_off_back:
  393.  
  394. ;; Check for doing a "user_tick", per Tech. Ref.:
  395. ;;    dec    user_counter            ; do a user tick 1 out of 3
  396. ;;     jz    user_tick
  397. ;;user_tick_back:
  398.  
  399. eject
  400.  
  401. ; The following provides pseudo door-open interrupt support to the O.S.
  402. ; If a disk is not accessed for the programmed time interval,
  403. ; the door is declared opened.  On the next BDOS call, the disk directory
  404. ; will be read to verify that the same disk is still in there.  As a result,
  405. ; disk changes are more likely to be detected, and disk buffers, hash tables,
  406. ; etc., may be trusted blindly for the specified interval after the last
  407. ; disk access, which should give some performance improvement.  JW, DRI UK
  408.     sub    dx,dx                ; start w/ first drive
  409. clk_dc1:
  410.     mov    bx,dx
  411.     shl    bx,1                ; word table
  412.     cmp    door_count$[bx],0        ; door open count alive?
  413.      jz    clk_dc2                ; skip if not
  414.     dec    door_count$[bx]            ; else count down
  415.      jnz    clk_dc2                ; skip if not yet expired
  416.     mov    bx,dph_tbl$[bx]            ; point to the DPH
  417.     mov    DPH_MF[bx],TRUE            ; set media flag
  418.     mov    door$,TRUE            ; and set global flag
  419. clk_dc2:
  420.     inc    dx                ; next disk
  421.     cmp    dx,num_flop            ; is it still a floppy?
  422.      jb    clk_dc1                ; yes, ckeck it as well
  423.  
  424. ; Check diskette op. time out:
  425.     cmp    disk_time_out$,0        ; if zero, then it's not being used
  426.      jnz    do_disk_time            ;  so, go about your business
  427. do_disk_time_back:
  428.     add    tick_cnt$,1            ; keep track of system ticks
  429.     adc    tick_cnt$+2,0
  430.  
  431. ; check Hard disk timeout
  432.     cmp    hd_timer$,0ffh
  433.     jne    do_hd_timeout
  434. do_hd_back:
  435.  
  436. ; Check for passage of one second:
  437.     inc    tod_ticks$
  438.     cmp    tod_ticks$,TICKS_PER_SECOND
  439.      je    do_second_flag            ; if a second then leap
  440. do_second_flag_back:
  441.  
  442. ; Check if we're multi-tasking:
  443.     cmp    tick$,0    
  444.      jne    do_tick_flag
  445. do_tick_flag_back:
  446.     jmp    update_cursor            ; skip over subroutines
  447.  
  448. eject
  449.  
  450.  
  451. do_disk_time:
  452. ; Here to handle disk time-out errors:
  453.     dec    disk_time_out$            ; if it hasn't timed out
  454.      jnz    do_disk_time_back        ;  then there's no need to worry
  455.     mov    disk_error$,80h            ; if it has timed out
  456.     mov    dx,FDC_FLAG            ;  then tell the error routine why
  457.     call    flagset@            ;  and do a flag set to unstick us
  458.     jmp    do_disk_time_back
  459.  
  460. do_hd_timeout:
  461. ; Here to handle hard disk timeout
  462.     dec    hd_timer$
  463.     jnz    do_hd_back
  464.     mov    es:hf_int_flag_40,0ffh        ; set flag to force ROS    to wake
  465.     mov    es:disk_status1_40,80h        ; mark as timeout in ROS
  466.     mov    hd_error$,80h            ; and for HDISK.A86
  467.     mov    hd_timer$,TICKS_PER_SECOND    ; reset for multi-sector
  468.     jmp    do_hd_back
  469.  
  470. do_second_flag:
  471. ; Here to tell the O.S. that a second has passed:
  472.     mov    tod_ticks$,0
  473.     mov    dx,SEC_FLAG
  474.     call    flagset@
  475.     mov    ax,timer_count$            ; variable timer count
  476.     out    TIMER_0_REG,al
  477.     xchg    ah,al
  478.     out    TIMER_0_REG,al
  479.     jmp    do_second_flag_back
  480.  
  481. do_tick_flag:
  482. ; Here to tell the O.S. that a tick has occurred:
  483.     mov    dx,TICK_FLAG
  484.     call    flagset@
  485.     jmp    do_tick_flag_back
  486.  
  487. ; Update the cursor:
  488. ; 20 NOV 85 -- the new code to use ROS to set cursor type means that ints. are
  489. ;  enabled w/ an STI on ROS entry.  This should not cause a problem because the
  490. ;  timer interrupt is the highest priority and the 8259 should not allow any
  491. ;  lower ints through until it sees an EOI.
  492. update_cursor:
  493.     cli
  494. if V386
  495.     push    ds
  496.     push    bx
  497.     mov    bx,v386_ptr$
  498.     mov    ds,tss_seg        ; get TSS segment
  499.     sub    ax,ax
  500.     xchg    al,.0DEh        ; enable CRT controller access
  501.     sub    cx,cx
  502.     xchg    cl,.0E2h        ; enable CRT controller access
  503.     pop    bx
  504.     pop    ds
  505.     push    ax            ; save old state
  506.     push    cx
  507. endif
  508. if SR
  509.     mov    cx,NUM_SR_CONS +1
  510.     mov    si,offset pc_table$    ; physical console structures
  511.     mov    es,con_basead$        ; get control base address
  512.     mov    al,chan_sel$        ; get current selected board
  513.     push    ax            ; and save
  514.     mov    al,0ffh
  515. update_all_cur:
  516.     push    cx ! push si
  517.     call    sel_chan@        ; start with master console
  518.     mov    si,[si]                ; SI -> PC_
  519.     mov    dl,PC_TOP_SCREEN        ; get top screen VS #
  520. else
  521.     mov    dl,top_screen$
  522. endif
  523.     call    point_vs@            ; point bx to top vs_
  524.     cmp    VS_SCREEN_MODE,04
  525.     jb    test_43
  526.     cmp    VS_SCREEN_MODE,07        
  527.     jne    timer_interrupt_exit        ; exit must be graphics mode
  528. test_43:
  529.     test    VS_MODE1,LINE_43_MODE        ; or 43 line mode
  530.     jnz    timer_interrupt_exit        ; then no cursor update
  531.  
  532.     call    tick_cursor@
  533.     
  534. timer_interrupt_exit:
  535.  
  536. if SR
  537.     pop si ! pop cx
  538.     mov    es,con_basead$        ; get control base address
  539.     mov    al,chan_sel$
  540. next_channel:
  541.     inc    al        ; select next channel
  542.     inc si ! inc si
  543.     mov    di,si
  544.     sub    di,offset pc_table$+2
  545.     shr    di,1            ; byte ptr
  546.     test    byte ptr station_on_off$[di],ON ; is station ON
  547.     jnz    do_next
  548.     loop    next_channel
  549.     jmps    all_done
  550. do_next:
  551.     loop    update_all_cur        ; update cursor for all terminals
  552. all_done:
  553.     pop    ax
  554.     call    sel_chan@        ; re-select channel
  555. endif
  556. if V386
  557.     pop    cx
  558.     pop    ax
  559.     push    ds
  560.     push    bx
  561.     mov    bx,v386_ptr$
  562.     mov    ds,tss_seg        ; get TSS segment
  563.     mov    .0DEh,al        ; restore CRT controller protection
  564.     mov    .0E2h,cl        ; restore CRT controller protection
  565.     pop    bx
  566.     pop    ds
  567. endif
  568.  
  569.     pop es ! pop si ! pop di ! pop bp
  570.     pop dx ! pop cx ! pop bx
  571.  
  572.     cli
  573.     call    pic_reset
  574.  
  575.     mov     ss,tickint_ss
  576.     mov     sp,tickint_sp
  577.  
  578.  
  579.     dec    tick_imhere
  580.     mov    ax,tickint_ax
  581.  
  582.     jmpf    dispatch_addr$            ; go run the next ready process
  583. ;#IJ    pop    ds
  584. ;#IJ    jmpf    disp_addr$            ; go run the next ready process
  585.  
  586.  
  587. ;------
  588. i_tick@:                    ; "user" tick routine
  589. ;------
  590.     iret                    ; do nothing
  591.  
  592. eject
  593.  
  594. ; If SunRiver enter with SI = PC_ structure
  595. tick_cursor@:
  596.     cmp    VS_MX,0                ; if within an MX
  597.      je    tick_cursor1            ; don't touch the cursor
  598.     ret
  599. tick_cursor1:
  600.     and    VS_MODE,not UPDATE_BIT        ; clear cursor moved bit
  601.     mov    cx,VS_OFFSET            ; update cursor position 
  602.     add    cx,VS_CORRECT            ; whether on or off
  603.     mov    al,CURSOR_HI
  604. if SR
  605.     cmp    cx,PC_LAST_CURS
  606.      je    no_ch
  607.     mov    PC_LAST_CURS,cx
  608. else
  609.     cmp    cx,last_curs$
  610.      je    no_ch
  611.     mov    last_curs$,cx
  612. endif
  613.  
  614.     call    video_out@
  615. no_ch:
  616.     test    VS_MODE,CURSOR_BIT
  617.      jz    old_cursor_off
  618.  
  619.     mov    dx,VS_CURSOR
  620.     call    in_window@
  621.      jnc    put_cur1
  622.  
  623. old_cursor_off:
  624.     test    video$,EGA+VGA            ; EGA/VGA ?
  625.      jz    not_ega
  626. ega_off:
  627.     mov    cx,01E00h            ; code for no curs on ega
  628.     jmps    hit_it
  629. not_ega:
  630.     mov    cx,1f1fh            ; hide cursor (even on Amstrad)
  631.     cmp    cloneflag$,IS_AMSTRAD
  632.      je    hit_it
  633.     mov    cx,VS_CUR_TYPE            ; mono/color/ega
  634.     or    ch,20h                ; disable bit
  635. hit_it:
  636.     mov    al,CURSOR_START            ; cursor display port
  637.     jmp    video_out@
  638.  
  639. put_cur1:
  640.     mov    cx,VS_CUR_TYPE_HW        ; mono/color/ega/ecd
  641.     mov    al,CURSOR_START
  642.     jmp    video_out@
  643. eject
  644.  
  645. ;********************************************************
  646. ;*                            *
  647. ;*        CLOCK INTERRUPT DATA AREA        *
  648. ;*                            *
  649. ;********************************************************
  650.  
  651. isrs_dseg0    dseg
  652. org    0
  653. ; 50 levels of tick stack for CROSSTALK:
  654.     dw    0cccch,0cccch,0cccch,0cccch,0cccch,0cccch,0cccch,0cccch
  655.     dw    0cccch,0cccch,0cccch,0cccch,0cccch,0cccch,0cccch,0cccch
  656.     dw    0cccch,0cccch,0cccch,0cccch,0cccch,0cccch,0cccch,0cccch
  657.     dw    0cccch,0cccch,0cccch,0cccch,0cccch,0cccch,0cccch,0cccch
  658.     dw    0cccch,0cccch,0cccch,0cccch,0cccch,0cccch,0cccch,0cccch
  659.     dw    0cccch,0cccch,0cccch,0cccch,0cccch,0cccch,0cccch,0cccch
  660.     dw    0cccch,0cccch
  661.  
  662.     dw    0cccch,0cccch,0cccch,0cccch,0cccch,0cccch,0cccch,0cccch
  663.     dw    0cccch,0cccch,0cccch,0cccch,0cccch,0cccch,0cccch,0cccch
  664.     dw    0cccch,0cccch,0cccch,0cccch,0cccch,0cccch,0cccch,0cccch
  665.     dw    0cccch,0cccch,0cccch,0cccch,0cccch,0cccch,0cccch,0cccch
  666.     dw    0cccch,0cccch,0cccch,0cccch,0cccch,0cccch,0cccch,0cccch
  667.     dw    0cccch,0cccch,0cccch,0cccch,0cccch,0cccch,0cccch,0cccch
  668.     dw    0cccch,0cccch
  669.  
  670.  
  671. tickint_save_area    rs    0
  672. tickint_ax    rw    1        ;storage for interrupted task
  673. tickint_ss    rw    1
  674. tickint_sp    rw    1
  675.  
  676. beep_counter$    db    0        ; how many control g's
  677. beep_ticks$    db    0        ; elapsed ticks this beep
  678. tick_imhere    db    0        ; flag in tick routine
  679.  
  680. vcon_counter    rw    32        ; last tick count (per vcon)
  681.                     ; --- DEBUG -- MAX 32 VCONS --
  682. user_counter    db    3        ; ROS update counter
  683. tick_counter    dw    0        ; tick counter (0000.FFFF)
  684.  
  685. ;disp_ticks    db   DISPATCH_TICKS    ; how many to tick before dispatch
  686.  
  687.  
  688. eject
  689.  
  690. ;************************************************
  691. ;*                        *
  692. ;*    MEMORY PARITY INTERRUPT HANDLER        *
  693. ;*                        *
  694. ;************************************************
  695.  
  696.     cseg
  697.     hard8087
  698.  
  699. ; Real memory parity error interrupt:
  700.  
  701. i_parity:
  702.     mov    ds,sysdat$            ; there's no coming back
  703.     mov    es,sysdat$            ; so forget the registers
  704.     mov    di,offset parity_p_msg
  705.     call    fatal_proc            ; store the process name
  706.     mov    di,offset parity_a_msg
  707.     call    fatal_addr            ; store the return address
  708.  
  709.     add    beep_counter$,3            ; beep thee thrice
  710.     mov    sl_exit_value$,TRUE        ; take over the status line
  711.     mov    dx,sysdat$
  712.     mov    cx,offset parity_msg
  713.     call    io_statline@            ; print the error message
  714.  
  715.     sti
  716.     mov    bx,4                ; about 1 second
  717. i_parity_pause:
  718.     loop    i_parity_pause            ; wait for beeps to end
  719.     dec    bx
  720.      jnz    i_parity_pause
  721.  
  722. i_parity_freeze:
  723.     cli
  724.     hlt                    ; wait here forever
  725.     jmps    i_parity_freeze            ;   and a day
  726. eject
  727.  
  728. ;************************************************
  729. ;*                        *
  730. ;*    8088 NMI INTERRUPT HANDLER        *
  731. ;*                        *
  732. ;************************************************
  733.  
  734. i_nmi@:
  735. ;-----
  736. ; This handler may be entered:
  737. ;    1) upon a parity error;
  738. ;    2) upon an 8087 signal;
  739. ;    3) upon execution of an INT 2 instr.;
  740. ;    4) upon execution of an OUT A0,80 (on old PCs).
  741.  
  742.     push    ax
  743.     push    dx
  744.     push    ds
  745.     mov    ds,sysdat
  746.     mov    dx,parity_chk$
  747.     pop    ds
  748. ;    in    al,PORT_C
  749.     in    al,dx
  750.     test    al,0C0h                ; look at io_ch_ck and par_ck
  751.     pop    dx
  752.     pop    ax
  753.      jnz    i_parity
  754.  
  755.     push    ds
  756.     mov    ds,sysdat
  757.     test    pc_at$,0ffh            ; on an at?
  758.     pop    ds
  759.      jnz    nmi_ret                ; just iret
  760.      
  761. ; So, was some nasty person doing an OUT A0,al or out dx,al with
  762. ; DX = 00A0 and al=80?
  763.     push    ds
  764.     mov    ds,sysdat
  765.     pop    ds_save_nmi
  766.     mov    bx_save_nmi,bx
  767.     mov    ds,ds_save_nmi
  768.  
  769.     cmp    al,80h
  770.      jne    test_87
  771.     pop    bx            ; offset
  772.     pop    ds            ; segment
  773.     push    ds
  774.     push    bx
  775.     cmp    word ptr MIN_2[bx],0A0E6h    ; "out A0,al"
  776.      je    fake_int
  777.     cmp    dx,00A0h            ; port number for...
  778.      jne    test_87
  779.     cmp    byte ptr MIN_1[bx],0EEh        ; "out dx,al"
  780.      jne    test_87
  781.  
  782. fake_int:
  783. ; Here if no 8087, no parity, or out A0,80 performed.
  784.     mov    ds,sysdat
  785.     mov    bx,bx_save_nmi
  786.     mov    ds,ds_save_nmi
  787. nmi_ret:
  788.     iret
  789.  
  790. test_87:
  791.     push    ds
  792.     mov    ds,sysdat
  793.     cmp    num_ndp$,1
  794.     pop    ds
  795.      jne    fake_int
  796.     mov    ds,sysdat
  797.     mov    bx,bx_save_nmi
  798.     mov    ds,ds_save_nmi
  799. ;    jmp    i_ndp@
  800. eject
  801.  
  802. ;************************************************
  803. ;*                        *
  804. ;*    8087 NDP INTERRUPT HANDLER        *
  805. ;*                        *
  806. ;************************************************
  807. ; Numeric data processor interrupt handler:
  808.  
  809. i_ndp@:
  810. ;-----
  811.     push    ds                ; on user's stack
  812.     mov    ds,sysdat$
  813.     mov    ndp_ss_save,ss            ; save user's stack
  814.     mov    ndp_sp_save,sp
  815.     mov    ss,sysdat$            ; get our own stack
  816.     mov    sp,offset ndp_stack_top
  817.  
  818.     push ax ! push bx ! push cx ! push dx
  819.     push si ! push di ! push bp ! push es
  820.     mov    es,sysdat$
  821.  
  822.     FNSTENV    env_8087            ; store 8087 environment
  823.     FWAIT                    ; await completion
  824.     FNCLEX                    ; clear int request bit
  825.     xor    ax,ax
  826.     FNDISI                    ; disable its int's
  827.  
  828.     mov    si,offset env_8087
  829.     mov    bx,owner_8087$            ; get current owner
  830.     test    bx,bx                ; if owner has already
  831.      jz    i_ndp_continue            ;   terminated, skip
  832.  
  833.     mov    ax,NDP_STATUS[si]        ; if not severe error, continue
  834.     test    ax,003Ah            ; 3A = under/overflow, precision
  835.      jnz    i_ndp_continue            ;      or denormalized operand
  836.     or    P_FLAG[bx],80h            ; terminate interrupting process
  837.  
  838. i_ndp_continue:
  839.     mov    byte ptr 2[si],0        ; clear stat word for env restore
  840.  
  841.     pop es ! pop bp ! pop di ! pop si
  842.     pop dx ! pop cx ! pop bx ! pop ax
  843.  
  844.     mov    ss,ndp_ss_save            ; restore user's stack
  845.     mov    sp,ndp_sp_save
  846.     FLDENV    env_8087            ; restore 8087 environment
  847.     FWAIT                    ; await completion
  848.     pop    ds
  849.     iret
  850. eject
  851.  
  852. ; Numeric data processor interrupt handler data:
  853.  
  854. isrs_dseg1    dseg
  855.  
  856. ndp_ss_save    rw    1            ; save area for user's stack
  857. ndp_sp_save    rw    1
  858.  
  859. env_8087    rw    7            ; save area for 8087's stack
  860. NDP_STATUS    equ    word ptr 2        ; status word in env_8087
  861.  
  862. ndp_control$    rw    1            ; for 8087 init routine
  863.  
  864.         rb    32            ; i_ndp@ stack area
  865. ndp_stack_top    rb    0
  866.  
  867. ds_save_nmi    rw    1
  868. bx_save_nmi    rw    1
  869. parity_chk$    dw    PORT_C            ; where to read parity checks
  870.                         ; set to PORT_B in init if AT
  871. ; parity error messages:
  872.  
  873. parity_msg    db    'Parity error from '
  874. parity_p_msg    db    'PROCNAME at '
  875. parity_a_msg    db    '0000:0000   '
  876.         db    ' ****  MACHINE IS HALTED!  ****'
  877.         db    '       '
  878. eject
  879.  
  880. ;************************************************
  881. ;*                        *
  882. ;*        FATAL INTERRUPT HANDLER        *
  883. ;*                        *
  884. ;************************************************
  885.  
  886.     cseg
  887.  
  888. i_divide@:
  889. ;--------
  890. ; Division by zero or any division overflow:
  891.  
  892.     mov    si,offset fatal_div        ; divide by zero
  893.     jmps    fatal_int@
  894.  
  895. i_overflow@:
  896. ;----------
  897. ; Arithmetic overflow when followed by an INTO (int on ovf):
  898.  
  899.     mov    si,offset fatal_ovf
  900.     jmps    fatal_int@
  901.  
  902. i_seg_ovr@:
  903. ;----------
  904. ; Segment overrun interrupt handler (286), int 13(d):
  905.  
  906.     mov    si,offset fatal_seg_ovr
  907.     jmps    fatal_int@
  908.  
  909. i_bad_opcode@:
  910. ;-------------
  911. ; Invalid opcode encountered (286), int 6:
  912.     mov    si,offset fatal_opcode
  913.     jmps    fatal_int@
  914.  
  915. i_unexpected@:
  916. ;------------
  917. ; Any undefined interrupt vectors here:
  918.  
  919.     mov    si,offset fatal_unx        ; divide by zero
  920. ;    jmps    fatal_int@            ; fall through
  921.  
  922.  
  923. fatal_int@:
  924.     sti                    ; allow further ints
  925.     mov    ds,sysdat$            ; local data segment
  926.     mov    es,sysdat$            ;   and extra too
  927.     mov    di,offset fatal_t_msg        ; error type destination
  928.     call    fatal_type            ; save sub message
  929.     mov    di,offset fatal_p_msg        ; proc name destination
  930.     call    fatal_proc            ; save process name
  931.     mov    di,offset fatal_a_msg        ; address destination
  932.     call    fatal_addr            ; save come-from addr
  933.  
  934.     mov    bx,rlr$                ; get process descriptor
  935.     mov    es,P_UDA[bx]            ; set up user data area
  936.     inc    beep_counter$            ; and extra beep here
  937.     mov    si,offset fatal_msg
  938.     mov    di,offset fatal_resp        ; allow any key
  939.     call    sl_error_out@            ; display message
  940.  
  941.     mov    bx,rlr$                ; terminate the running process
  942.     and    P_FLAG[bx],not (PF_KEEP + PF_TEMPKEEP)
  943.     mov    cx,P_TERM
  944.     mov    dx,0FFFFh
  945.     jmp    supif@                ; process is terminated
  946. eject
  947.  
  948. fatal_type:
  949. ; Store the "type" of fatal interrupt:
  950.  
  951.     mov    cx,length fatal_t_msg        ; sub message length
  952.     cld
  953.     rep    movsb                ; store the type of int
  954.     ret
  955.  
  956. fatal_proc:
  957. ; Store the process name which caused this mess:
  958.  
  959.     mov    bx,rlr$                ; get process descriptor
  960.     lea    si,P_NAME[bx]            ; point to proc name
  961.     mov    cx,8                ; max process name
  962.     cld
  963.     rep    movsb                ; store the process name
  964.     ret
  965.  
  966. fatal_addr:
  967. ; Store the address from whence this interrupt came:
  968.  
  969.     mov    bp,sp
  970.     add    bp,5                ; look up the stack
  971.     mov    bx,offset hex_digits        ; for translation
  972.     call    fatal_word            ; print segment
  973.     inc    di                ; skip the :
  974. ;    jmp    fatal_word            ;   and offset
  975.  
  976. fatal_word:
  977.     call    fatal_byte            ; print ms byte
  978. ;    jmp    fatal_byte            ;   and ls byte
  979.  
  980. fatal_byte:
  981.     mov    al,[bp]                ; return byte from stack
  982.     dec    bp                ; next byte down
  983.     call    fatal_nibble            ; print ms nibble
  984. ;    jmp    fatal_nibble            ;   and ls nibble
  985.  
  986. fatal_nibble:
  987.     mov    cl,4
  988.     rol    al,cl                ; ms nibble first
  989.     push    ax                ; save for ls nibble
  990.     and    al,0Fh                ; 4 bits only
  991.     xlat    bx
  992.     stosb                    ; store hex code
  993.     pop    ax
  994.     ret
  995. eject
  996.  
  997. ; Fatal error messages are all in the code seg:
  998.  
  999. isrs_dseg2    dseg
  1000.  
  1001. fatal_msg    rb    0
  1002. fatal_t_msg    db    'Unexpected'
  1003.         db    ' Interrupt from '
  1004. fatal_p_msg    db    'PROCNAME at '
  1005. fatal_a_msg    db    '0000:0000  '
  1006.         db    ' Type any key to stop process. '
  1007.  
  1008. fatal_div    db    '  Division'
  1009. fatal_ovf    db    '  Overflow'
  1010. fatal_unx    db    'Unexpected'
  1011. fatal_seg_ovr    db    'Seg. Bound'
  1012. fatal_opcode    db    'Bad Opcode'
  1013. fatal_type_len    equ    offset $ - offset fatal_unx
  1014. if V386
  1015. fatal_prot$    db    'Protection'
  1016. fatal_page$    db    'Page Fault'
  1017. endif
  1018. fatal_resp    db    0            ; allow any key
  1019.  
  1020. hex_digits    db    '0123456789ABCDEF'
  1021. eject
  1022.  
  1023.         cseg
  1024.  
  1025. ;************************************************
  1026. ;*                        *
  1027. ;*    RESET FUNCTION - CTRL/ALT/DEL REBOOT    *
  1028. ;*                        *
  1029. ;************************************************
  1030.  
  1031. reset@:
  1032. ;------
  1033. if SR
  1034.     call    sr_reset@            ; de-select cygna card
  1035. endif
  1036.     mov    ax,PC_SEGMENT
  1037.     mov    ds,ax                ;ROM data segment
  1038.     mov    reset_flag_40,1234H
  1039. if V386
  1040.     mov    al,0FEh                ; get reset command
  1041.     out    AT_KBD_STATUS,al        ; request CPU reset
  1042.     jmps    $
  1043. endif
  1044. if XM
  1045.     jmpf    dword ptr rom_reset        ; else jump to ROS reset entry
  1046. endif
  1047.  
  1048. ; Reset routine data:
  1049.  
  1050. rom_reset    dw    0000h,0FFFFh
  1051. eject
  1052. ;************************************************
  1053. ;*                        *
  1054. ;*    PC MODE EQUIPMENT WORD            *
  1055. ;*                        *
  1056. ;************************************************
  1057.  
  1058. ; Miscellaneous code and data required for PC_MODE support in XIOS.
  1059. ; MPV 22 NOV 83
  1060.  
  1061. ; New XIOS function 32 used to return equipment check word:
  1062.  
  1063. pc_equip@:
  1064. ;---------
  1065.     mov    bx,rlr$                ; ready list root
  1066.     mov    dl,P_CONS[bx]            ; process's console number
  1067.     call    point_vs@            ; this proc's vc structure
  1068.     mov    al,VS_SCREEN_MODE
  1069.  
  1070.     push    ds
  1071.       mov    bx,PC_SEGMENT
  1072.       mov    ds,bx                ; reach into base page
  1073.       mov    bx,equip_flag_40        ; get IBM's equipment word
  1074.     pop    ds
  1075.     cmp    dl,NUM_VIR_CONS            ; serial ?
  1076.     jb    equip_vid            ; no
  1077. if not SR
  1078.     or    bl,00110000b            ; else make default console b/w
  1079. endif
  1080.     jmps    equip_done
  1081.  
  1082. equip_vid:
  1083.     push es    ! push ds ! pop es        ; local es for scan
  1084.     mov    di,offset equip_modes        ; list of screen modes to fudge
  1085.     mov    cx,EQUIP_COUNT            ; number to check
  1086.     cld                    ; scan code already in al
  1087.     repnz    scasb                ; search the list
  1088.     pop    es                ; restore es
  1089.      jnz    equip_done            ; if not in the list
  1090.  
  1091.     and    bl,0CFh                ; mask off default console
  1092.     or    bl,.EQUIP_XLAT[di]        ;   and mash in a fake one
  1093.  
  1094. equip_done:
  1095.     mov    ax,bx                ; return equipment word
  1096.     ret
  1097.  
  1098. isrs_dseg3    dseg
  1099.  
  1100. ; These tables are used to make the equipment word look
  1101. ; as if the current monitor/mode were the default value:
  1102.  
  1103. equip_modes    db    00h,01h,02h,03h        ; screen modes to xlat
  1104.         db    07h,04h,05h,06h
  1105.  
  1106. EQUIP_COUNT    equ    offset $ - offset equip_modes
  1107. EQUIP_XLAT    equ    EQUIP_COUNT - 1
  1108.  
  1109.         db    10h,10h,20h,20h        ; equip word xlations
  1110.         db    30h,20h,20h,20h
  1111. eject
  1112.  
  1113.     end
  1114.  
  1115. ; END OF ISRS.A86
  1116.