; pic module 5/17/83 goodall ; the function of this module is to provide entry ; points for every conceiveable function required ; to operate in the interrupt environment cgroup group code,data nolist include ccpmxios.equ list ; extrns from ccpmxios.a86 extrn tick:byte extrn supervisor_o:word supervisor equ dword ptr supervisor_o extrn sysdat:word public tick_init public key_data public pic_disable ; disable all reasonable ints ; (it might not pay to disable ; an interrupt which was doing ; software refreshing ) public pic_enable ; enable based on switches public pic_vectors ; setup vectors public snsfdint ; sense floppy disk int public pic_tir ; timer reset public miscflg ; a misc flag byte public pic_kb_ack ; kb int rtn requests service ; the following publics allow these bytes to be available in ; sid86 during debugging. only those actually needed during ; debugging should be activated public switches ; make switches available public timer_sw public disc8_sw public fdint_sw public mint_sw public cint_sw public ccur_sw public ccus_sw public slave_sw public gpint_sw public kbint_sw public pint_sw public int0_sw public int1_sw eject ;************************************************************************ ;* * ;* 8259 PROGRAMMABLE INTERRUPT CONTROLLER COMMANDS * ;* AND PORTS * ;* 4/7/83 dwg * ;************************************************************************ icp0m equ 18h ; master icp1m equ 1ah ; master icp0s equ 14h ; slave icp1s equ 16h ; slave ivectoff equ 20h ; set by reset rom( see bios13 pg 64 ) timer_ch equ 0+ivectoff disc8_ch equ 1+ivectoff fdint_ch equ 2+ivectoff mint_ch equ 3+ivectoff cint_ch equ 4+ivectoff ccur_ch equ 5+ivectoff ccus_ch equ 6+ivectoff slave_ch equ 7+ivectoff gpint_ch equ 8+ivectoff kbint_ch equ 9+ivectoff pint_ch equ 0ah+ivectoff int0_ch equ 0bh+ivectoff int1_ch equ 0ch+ivectoff unused_d_ch equ 0dh+ivectoff unused_e_ch equ 0eh+ivectoff unused_f_ch equ 0fh+ivectoff nmi_ch equ 02h ; non-maskable int. EJECT irq0 equ 00000001b irq1 equ 00000010b irq2 equ 00000100b irq3 equ 00001000b irq4 equ 00010000b irq5 equ 00100000b irq6 equ 01000000b irq7 equ 10000000b ; master 8259 equates timer_n equ irq0*256 disc8_n equ irq1*256 fdint_n equ irq2*256 mint_n equ irq3*256 cint_n equ irq4*256 ccur_n equ irq5*256 ccus_n equ irq6*256 slave_n equ irq7*256 ; slave 8259 equates gpint_n equ irq0 kbint_n equ irq1 pint_n equ irq2 int0_n equ irq3 int1_n equ irq4 unused_d_n equ irq5 unused_e_n equ irq6 unused_f_n equ irq7 ; miscport equ 7Ch ; miscellaneous port miscf_bell equ 10000000b ; bell miscf_mono equ 00001000b ; monocro. CRT miscf_crt equ 00000100b ; inhibit CRT display miscf_grp equ 00000010b ; graphic CRT mode miscf_tir equ 00000001b ; timer interrupt reset eject cseg ; the function of this code is to acknowledge the receipt of ; a keyboard interrupt so as to allow another pic_kb_ack: mov al,01100001b ! out icp0s,al ! ret pic_disable: mov al,0ffh ! out icp1s,al ! out icp1m,al ! ret eject pic_vectors: xor ax,ax ! mov es,ax ! mov ax,cs ; get xios data asegment mov di,(timer_ch*4)+2 ! stosw ; m 0 mov di,(disc8_ch*4)+2 ! stosw ; m 1 mov di,(fdint_ch*4)+2 ! stosw ; m 2 mov di,(mint_ch*4)+2 ! stosw ; m 3 mov di,(cint_ch*4)+2 ! stosw ; m 4 mov di,(ccur_ch*4)+2 ! stosw ; m 5 mov di,(ccus_ch*4)+2 ! stosw ; m 6 mov di,(slave_ch*4)+2 ! stosw ; m 7 mov di,(gpint_ch*4)+2 ! stosw ; s 0 mov di,(kbint_ch*4)+2 ! stosw ; s 1 mov di,(pint_ch*4)+2 ! stosw ; s 2 mov di,(int0_ch*4)+2 ! stosw ; s 3 mov di,(int1_ch*4)+2 ! stosw ; s 4 mov di,(unused_d_ch*4)+2 ! stosw ; s 5 mov di,(unused_e_ch*4)+2 ! stosw ; s 6 mov di,(unused_f_ch*4)+2 ! stosw ; s 7 mov di,timer_ch*4 ! mov ax,offset i_tick ! stosw ; m 0 * mov di,disc8_ch*4 ! mov ax,offset i_disc8_n ! stosw ; m 1 mov di,fdint_ch*4 ! mov ax,offset i_disk ! stosw ; m 2 * mov di,mint_ch*4 ! mov ax,offset i_mint_n ! stosw ; m 3 mov di,cint_ch*4 ! mov ax,offset i_cint_n ! stosw ; m 4 mov di,ccur_ch*4 ! mov ax,offset i_ccur ! stosw ; m 5 * mov di,ccus_ch*4 ! mov ax,offset i_ccus ! stosw ; m 6 * mov di,slave_ch*4 ! mov ax,offset i_slave_n ! stosw ; m 7 mov di,gpint_ch*4 ! mov ax,offset i_gpint_n ! stosw ; s 0 mov di,kbint_ch*4 ! mov ax,offset i_keyboard ! stosw ; s 1 * mov di,pint_ch*4 ! mov ax,offset i_pint_n ! stosw ; s 2 mov di,int0_ch*4 ! mov ax,offset i_int0_n ! stosw ; s 3 mov di,int1_ch*4 ! mov ax,offset i_int1_n ! stosw ; s 4 mov di,unused_d_ch*4 ! mov ax,offset i_un_d_n ! stosw ; s 5 mov di,unused_e_ch*4 ! mov ax,offset i_un_e_n ! stosw ; s 6 mov di,unused_f_ch*4 ! mov ax,offset i_un_f_n ! stosw ; s 7 ret eject ; ; the following code is included to allow debugging of interrupts ; i_timer_n: mov bx,timer_n ! jmps my_abort i_disc8_n: mov bx,disc8_n ! jmps my_abort i_fdint_n: mov bx,fdint_n ! jmps my_abort i_mint_n: mov bx,mint_n ! jmps my_abort i_cint_n: mov bx,cint_n ! jmps my_abort i_ccur_n: mov bx,ccur_n ! jmps my_abort i_ccus_n: mov bx,ccus_n ! jmps my_abort i_slave_n: mov bx,slave_n ! jmps my_abort i_gpint_n: mov bx,gpint_n ! jmps my_abort i_kbint_n: mov bx,kbint_n ! jmps my_abort i_pint_n: mov bx,pint_n ! jmps my_abort i_int0_n: mov bx,int0_n ! jmps my_abort i_int1_n: mov bx,int1_n ! jmps my_abort i_un_d_n: mov bx,unused_d_n ! jmps my_abort i_un_e_n: mov bx,unused_e_n ! jmps my_abort i_un_f_n: mov bx,unused_f_n ! jmps my_abort my_abort: mov al,0ffh ! out icp1s,al ! out icp1m,al ! int 3 eject pic_enable: mov bx,0ffffh mov al,timer_sw ! and al,al ! jz no_timer ! xor bx,timer_n no_timer: mov al,disc8_sw ! and al,al ! jz no_disc8 ! xor bx,disc8_n no_disc8: mov al,fdint_sw ! and al,al ! jz no_fdint ! xor bx,fdint_n no_fdint: mov al,mint_sw ! and al,al ! jz no_mint ! xor bx,mint_n no_mint: mov al,cint_sw ! and al,al ! jz no_cint ! xor bx,cint_n no_cint: mov al,ccur_sw ! and al,al ! jz no_ccur ! xor bx,ccur_n no_ccur: mov al,ccus_sw ! and al,al ! jz no_ccus ! xor bx,ccus_n no_ccus: mov al,gpint_sw ! and al,al ! jz no_gpint ! xor bx,gpint_n no_gpint: mov al,kbint_sw ! and al,al ! jz no_kbint ! xor bx,kbint_n no_kbint: mov al,pint_sw ! and al,al ! jz no_pint ! xor bx,pint_n no_pint: mov al,int0_sw ! and al,al ! jz no_int0 ! xor bx,int0_n no_int0: mov al,int1_sw ! and al,al ! jz no_int1 ! xor bx,int1_n no_int1: mov al,gpint_sw ! or al,kbint_sw ! or al,pint_sw or al,int0_sw ! or al,int1_sw and al,al ! jz no_slave ! xor bx,slave_n no_slave: mov masks,bx mov al,bl ! out icp1s,al mov al,bh ! out icp1m,al ret eject ; sense floppy disk interrupt ( polled method ) snsfdint: mov al,01010b out icp0m,al ; select irr in al,icp0m and al,fdint_n/256 ret pic_tir: mov al,miscflg ! or al,miscf_tir ! out miscport,al ret EJECT ; ; edge and level triggered modes ; (page 7-132, intel component data catalog 1982) ; ; In both the edge and level triggered modes the IR inputs ; must remain high until after the falling edge of the first ; INTA. If the IR input goes low before this time a DEFAULT ; IR7 will occur when the CPU acknowledges the interrupt. ; This can be a useful safeguard for detecting interrupts ; caused by spurious noise glitches on the IR inputs. To ; implement this feature the IR7 routine is used for "clean-up" ; simply executing a return instruction, thus ignoring the ; interrupt. If IR7 is needed for other purposes a default IR7 ; can still be detected by reading the ISR. A normal IR7 ; interrupt will set the corresponding ISR bit, a default IR7 ; won't. If a default IR7 routine occurs during a normal IR7 ; routine, however, the ISR will remain set. In this case it is ; necessary to keep track of whether or not the IR7 routine ; was previously entered. If another IR7 occurs it is a ; default. public i_default_ir7 ; allow debugging use of symbol i_default_ir7: iret eject dseg miscflg db 0 EJECT ; ; the following boolean flags control both the initailization of the ; 8259a and the run time execution philosophy of the xios ; if the flag is true, the interrupt level will be enabled in the ; PIC and the software will behave accordingly. switches: timer_sw db 1 ; TICK implemented disc8_sw db 0 ; not yet fdint_sw db 1 ; FDC implemented mint_sw db 0 ; not yet cint_sw db 0 ; not yet ccur_sw db 0 ; not yet ccus_sw db 0 ; not yet slave_sw db 0 ; set by init code if slave levels gpint_sw db 0 ; not yet kbint_sw db 1 ; KBD implemented pint_sw db 0 ; not yet int0_sw db 0 ; not yet int1_sw db 0 ; not yet db 0 db 0 db 0 masks rw 1 eject ;******************************************************************** ;* SYSTEM TICK INTERRUPT HANDLER ;******************************************************************** cseg tick_init: mov al,ticks_per_second mov tick_counter,al ret i_tick: push ds ;use one level of user stack mov ds,sysdat cmp t_cnt,0 jnz t_noswitch mov tickint_ss,ss mov tickint_sp,sp mov ss,sysdat mov sp,offset tickint_save_area t_noswitch: inc t_cnt ; increment the tick counter nop ;allow interrupts push ax ;save the registers push bx push cx push dx push bp push si push di push es dec tick_counter ;has 1 second elapsed ? jnz no_second_flag mov al,ticks_per_second mov tick_counter,al mov dx,sec_flag ;the second flag mov cl,dev_flagset ! xor ch,ch ! callf supervisor no_second_flag: cmp tick,false ;only set the tick flag je i_tick_exit ;when the tick variable in mov dx,tick_flag ;the XIOS header is true mov cl,dev_flagset ! xor ch,ch ! callf supervisor i_tick_exit: call pic_tir ; let pic module do details pop es ;restore the registers pop di pop si pop bp pop dx pop cx pop bx pop ax dec t_cnt jnz no_stack_restore cli mov ss,tickint_ss mov sp,tickint_sp no_stack_restore: nop cmp no_tick_dispatch,true ;set zero flag if we interrupted pop ds ;get DS from the interrupted je no_disp ;process's stack jmpf cs:dword ptr dispatcher ;go run the next ready process no_disp: iret ;go back to interrupted ;interrupt handler eject dseg ;************************************************************************ ;* * ;* TICK INTERRUPT DATA AREA * ;* * ;************************************************************************ bell_ticks dw 0 tick_counter db 0 ;counter for tick interupts; dw 0CCCCh,0CCCCH,0CCCCH dw 0CCCCh,0CCCCH,0CCCCH dw 0CCCCh,0CCCCH,0CCCCH dw 0CCCCh,0CCCCH,0CCCCH dw 0CCCCh,0CCCCH,0CCCCH dw 0CCCCh,0CCCCH,0CCCCH dw 0CCCCh,0CCCCH,0CCCCH dw 0CCCCh,0CCCCH,0CCCCH dw 0CCCCh,0CCCCH,0CCCCH dw 0CCCCh,0CCCCH,0CCCCH dw 0CCCCh,0CCCCH,0CCCCH dw 0CCCCh,0CCCCH,0CCCCH dw 0CCCCh,0CCCCH,0CCCCH dw 0CCCCh,0CCCCH,0CCCCH dw 0CCCCh,0CCCCH,0CCCCH tickint_save_area rs 0 tickint_ss rw 1 tickint_sp rw 1 t_cnt rw 1 no_tick_dispatch db false ticks_per_second db 20 eject ;************************************************************************ ;* DISK INTERRUPT HANDLER * ;************************************************************************ cseg i_disk: push ds ! mov ds,sysdat mov no_tick_dispatch,true mov disk_ss,ss ;save the stack segment mov disk_sp,sp ;and stack pointer mov ss,sysdat ;set up interrupt stack mov sp,offset disk_save_area nop push ax push bx ;save the registers push cx push dx push bp push si push di push es mov dx,fdc_flag ;flag set call must have mov cl,dev_flagset ! xor ch,ch ! callf supervisor pop es ;restore registers pop di pop si pop bp pop dx pop cx pop bx pop ax cli mov ss,disk_ss ;restore user's stack mov sp,disk_sp nop mov no_tick_dispatch,false pop ds ;DS is on user's stack iret eject dseg ; Stack switch area for disk interrupt dw 0CCCCH,0CCCCH,0CCCCH dw 0CCCCH,0CCCCH,0CCCCH dw 0CCCCH,0CCCCH,0CCCCH dw 0CCCCH,0CCCCH,0CCCCH dw 0CCCCH,0CCCCH,0CCCCH dw 0CCCCH,0CCCCH,0CCCCH dw 0CCCCH,0CCCCH,0CCCCH dw 0CCCCH,0CCCCH,0CCCCH dw 0CCCCH,0CCCCH,0CCCCH dw 0CCCCH,0CCCCH,0CCCCH dw 0CCCCH,0CCCCH,0CCCCH dw 0CCCCH,0CCCCH,0CCCCH dw 0CCCCH,0CCCCH,0CCCCH dw 0CCCCH,0CCCCH,0CCCCH dw 0CCCCH,0CCCCH,0CCCCH disk_save_area rs 0 disk_ss dw 0 disk_sp dw 0 eject ;************************************************************************ ;* ccur INTERRUPT HANDLER * ;************************************************************************ cseg i_ccur: push ds ! mov ds,sysdat mov no_tick_dispatch,true mov ccur_ss,ss ;save the stack segment mov ccur_sp,sp ;and stack pointer mov ss,sysdat ;set up interrupt stack mov sp,offset ccur_save_area nop push ax push bx ;save the registers push cx push dx push bp push si push di push es mov dx,ccur_flag ;flag set call must have mov cl,dev_flagset ! xor ch,ch ! callf supervisor pop es ;restore registers pop di pop si pop bp pop dx pop cx pop bx pop ax cli mov ss,ccur_ss ;restore user's stack mov sp,ccur_sp nop mov no_tick_dispatch,false pop ds ;DS is on user's stack iret eject dseg ; Stack switch area for ccur interrupt dw 0CCCCH,0CCCCH,0CCCCH dw 0CCCCH,0CCCCH,0CCCCH dw 0CCCCH,0CCCCH,0CCCCH dw 0CCCCH,0CCCCH,0CCCCH dw 0CCCCH,0CCCCH,0CCCCH dw 0CCCCH,0CCCCH,0CCCCH dw 0CCCCH,0CCCCH,0CCCCH dw 0CCCCH,0CCCCH,0CCCCH dw 0CCCCH,0CCCCH,0CCCCH dw 0CCCCH,0CCCCH,0CCCCH dw 0CCCCH,0CCCCH,0CCCCH dw 0CCCCH,0CCCCH,0CCCCH dw 0CCCCH,0CCCCH,0CCCCH dw 0CCCCH,0CCCCH,0CCCCH dw 0CCCCH,0CCCCH,0CCCCH ccur_save_area rs 0 ccur_ss dw 0 ccur_sp dw 0 eject ;************************************************************************ ;* ccus INTERRUPT HANDLER * ;************************************************************************ cseg i_ccus: push ds ! mov ds,sysdat mov no_tick_dispatch,true mov ccus_ss,ss ;save the stack segment mov ccus_sp,sp ;and stack pointer mov ss,sysdat ;set up interrupt stack mov sp,offset ccus_save_area nop push ax push bx ;save the registers push cx push dx push bp push si push di push es ; just set the flag mov dx,ccus_flag ;flag set call must have mov cl,dev_flagset ! xor ch,ch ! callf supervisor pop es ;restore registers pop di pop si pop bp pop dx pop cx pop bx pop ax cli mov ss,ccus_ss ;restore user's stack mov sp,ccus_sp nop mov no_tick_dispatch,false pop ds ;DS is on user's stack iret eject dseg ; Stack switch area for ccus interrupt dw 0CCCCH,0CCCCH,0CCCCH dw 0CCCCH,0CCCCH,0CCCCH dw 0CCCCH,0CCCCH,0CCCCH dw 0CCCCH,0CCCCH,0CCCCH dw 0CCCCH,0CCCCH,0CCCCH dw 0CCCCH,0CCCCH,0CCCCH dw 0CCCCH,0CCCCH,0CCCCH dw 0CCCCH,0CCCCH,0CCCCH dw 0CCCCH,0CCCCH,0CCCCH dw 0CCCCH,0CCCCH,0CCCCH dw 0CCCCH,0CCCCH,0CCCCH dw 0CCCCH,0CCCCH,0CCCCH dw 0CCCCH,0CCCCH,0CCCCH dw 0CCCCH,0CCCCH,0CCCCH dw 0CCCCH,0CCCCH,0CCCCH ccus_save_area rs 0 ccus_ss dw 0 ccus_sp dw 0 eject ; equates for the olympia people keyboard hardware kbd_control equ 56h ; console stat kbd_data equ 54h ; console data kbd_rda equ 2 ; see rom doc cseg i_keyboard: push ds ! mov ds,sysdat ;use one level of user stack mov no_tick_dispatch,true mov keyboard_ss,ss ;use data segment, keep mov keyboard_sp,sp ;XIOS code and data separate mov ss,sysdat mov sp,offset keyboard_i_stack ;keyboard interrupt stack nop push ax push bx ;save the registers push cx push dx push bp push si push di push es mov ax,ds ;set up the mov es,ax ;extra segment in al,kbd_data ; get byte from uart mov key_data,al ; save in buffer mov dx,key_flag mov cl,dev_flagset ! xor ch,ch ! callf supervisor call pic_kb_ack ; ask pic to proceed pop es ;restore registers pop di pop si pop bp pop dx pop cx pop bx pop ax cli mov ss,keyboard_ss mov sp,keyboard_sp nop mov no_tick_dispatch,false pop ds ;DS on user's stack iret eject dseg ;************************************************************************ ;* * ;* KEYBOARD INTERRUPT DATA AREA * ;* * ;************************************************************************ key_data rb 1 ; data ; Keyboard interrupt routine stack dw 0CCCCH,0CCCCH,0CCCCH dw 0CCCCH,0CCCCH,0CCCCH dw 0CCCCH,0CCCCH,0CCCCH dw 0CCCCH,0CCCCH,0CCCCH dw 0CCCCH,0CCCCH,0CCCCH dw 0CCCCH,0CCCCH,0CCCCH dw 0CCCCH,0CCCCH,0CCCCH dw 0CCCCH,0CCCCH,0CCCCH dw 0CCCCH,0CCCCH,0CCCCH dw 0CCCCH,0CCCCH,0CCCCH dw 0CCCCH,0CCCCH,0CCCCH dw 0CCCCH,0CCCCH,0CCCCH dw 0CCCCH,0CCCCH,0CCCCH dw 0CCCCH,0CCCCH,0CCCCH dw 0CCCCH,0CCCCH,0CCCCH keyboard_i_stack rs 0 keyboard_ss dw 0 ;keyboard interrupt keyboard_sp dw 0 ;handler ; end of physical pic module