title 'I3 interrupt entry' ;************************************************ ; * ; INTERFACER 3 BOARD MODULE * ; Last changed : 2/10/84 * ; * ;************************************************ include i3board.equ dseg extrn icdesctbl:word extrn ocdesctbl:word extrn i3_xmit_int_vec:byte extrn bit_mask_tbl:byte cseg public i3r_int public i3t_int extrn sysdat:word extrn reset_i3iint_pic:near extrn reset_i3tint_pic:near extrn store_char:near extrn xmit_on:near extrn xmit_off:near extrn intco:near ;;======= i3t_int: ; Interfacer 3 transmit interrupt entry ;;======= ;; ;; ENTRY: from the interfacer 3's transmit ready interrupt line. ;; The interfacer 3's interrupt status register has ;; a bit set for each USART whose transmit buffer is empty. ;; ;; I3_xmit_int_vec contains a bit vector of the USARTS on ;; Interfacer 3 that we have characters for. ;; ;; EXIT: back to the process we interrupted ;; ;; NOTE: All the USART's Xmit interrupts are wire ORed together ;; push ds mov ds,sysdat mov i3_out_int_ss,ss mov i3_out_int_sp,sp mov ss,sysdat mov sp,offset i3_out_int_tos push ax push bx push cx push dx co_test_lp: mov al, 0 ;; We have to select a usart before out I3_SELECT_REG, al ;; we can query the board, see page 9 ;; of the interfacer 3 manual mov ah, i3_xmit_int_vec ;; bit vector of expected interrupts mov bx, offset bit_mask_tbl ;; byte mask for each Xmit interrupt mov cx, 8 ;; length of bit mask table co_lp: test ah, [bx] jz co_lp_1 in al, I3_XMIT_INT_STAT ;; Get the board's interrupt status test al, [bx] ;; Is this the interrupt we expect ? jnz co_found_it co_lp_1: inc bx ;; point to the next mask loop co_lp ;; check all the USARTS jmp co_exit co_found_it: ;; cx = the USART number that interrupted us mov bx, offset ocdesctbl ;; base of Xmit Q table shl cx, 1 add bx, cx ;; index into the table mov bx, [bx] ;; bx -> Xmit Q ctl Structure call intco ;; send the character jmps co_test_lp ;; In case another interrupt came in ;; while we were doing this one, check ;; the interrupt status again. co_exit: call reset_i3tint_pic pop dx ;; restore the environment pop cx pop bx pop ax mov ss, i3_out_int_ss ;; restore the stack mov sp, i3_out_int_sp pop ds ;; restore the data segment iret ;; back to the process we interrupted ; ;interfacer 3 output interrupt stack area rw 32 i3_out_int_tos: rw 0 i3_out_int_ss rw 1 i3_out_int_sp rw 1 ;;----------- i3r_int: ;; Interfacer 3 receive interrupt entry ;;--------- ;; ;; ENTRY: from an interrupt push ds ;; establish a local data segment mov ds, sysdat mov i3r_sss, ss ;; save the stack we came in on mov i3r_sps, sp mov ss, sysdat ;; and establish our own local stack mov sp, offset i3r_tos push ax ;; save the reg's we need for push bx ;; the interrupt handler mov al, 0 ;; We have to select a USART on the out I3_SELECT_REG, al ;; interfacer 3 before we can query ;; the interrupt status register. ;; see page 9 of the interfacer 3 ;; manual in al, I3_RCV_INT_STAT ;; read the interfacer 3's ;; interrupt status call res_usart ;; find which USART interrupted us mov bx, ax ;; save the usart's number out I3_SELECT_REG, al ;; select the USART in al, I3_UART_STATUS ;; get the status mov ah, al in al, I3_UART_DATA ;; and the data push ax ;; store the status and data call reset_i3iint_pic xor bh, bh ;; clear the high byte of the index inc bx ;; usart 0 in table is the SS board shl bx, 1 ;; word table mov bx, icdesctbl[bx] ;; bx -> USART q pop ax ;; retrieve the usart's status and data call store_char ;; process the character pop bx ;; restore the cpu registers pop ax cli ;; entering a critical region mov ss, i3r_sss ;; restore the stack mov sp, i3r_sps pop ds ;; restore the data segment iret res_usart: ;;--------- ;; ;; This routine does a binary search for the bit representing the USART ;; that interrupted us. ;; ;; ENTRY: al = the interfacer 3's receive interrupt status byte ;; ;; EXIT: al = the number of usart whose bit is set ;; ;; NOTE: This routine only uses ax and the flags test al, 0FH jnz low_nibble test al, 30H ;; one of the bits in the upper nibble jz u_half test al,10H ;; in the lower half of the upper nibble jnz u_4 mov al, 5 ;; USART 5 jmps ux u_4: mov al,4 ;; USART 4 jmps ux u_half: test al, 40H ;; it's either bit 6 or 7 jnz u_6 mov al, 7 ;; USART 7 jmps ux u_6: mov al, 6 ;; USART 6 jmps ux low_nibble: test al, 03H ;; one of the bits in the lower nibble jz u_half1 test al, 01H ;; in the lower half of the lower nibble jnz u_0 mov al, 1 ;; USART 1 jmps ux u_0: mov al,0 ;; USART 0 jmps ux u_half1: test al, 04H ;; it's either usart 2 or 3 jnz u_2 mov al, 3 ;; USART 3 jmps ux u_2: mov al,2 ;; USART 2 ux: ret i3r_sss dw 0 ; interfacer 3 receive stack segment save i3r_sps dw 0 ; interfacer 3 receive stack offset save rw 40 i3r_tos: end