; ; ircserver.asm ; ; This Lattice V5.04 assembly language routine gets added to the ; level 2 interrupt server chain to deal with INT2 interrupts ; caused by bringing the ACK pin on the parallel port low. ; ; ; NOTE: Lattice asm doesn't like: move.l _irc, a1 ; and DOES like: move.l _irc,a1 ; Only difference is the space before "a1". ; Also, calling an external Lattice C routine from assembly must be ; done after the Enable(), Permit(). (Would probably work before ; the Forbid(), Disable() too.) ; To pass a variable which is a pointer to a C function use: ; ; [struct Interrupt *SoftInterrupt; Cause(SoftInterrupt);] ; ; move.l _SoftInterrupt,a1 ; Put address of Interrupt structure ; move.l a1,-(a7) ; onto stack. ; JSR _Cause ; ADDQ #4,A7 ; Fix the stack pointer. ; ; To pass a variable which is NOT a pointer AS a pointer to a C function use: ; ; [struct Interrupt SoftInterrupt; Cause(&SoftInterrupt);] ; ; LEA _SoftInterrupt,A1 ; MOVE.L A1,-(A7) ; JSR _Cause ; ADDQ #4,A7 ; Fix the stack pointer. ; ; ; csect data,1,,2,2 xref _LVOSignal csect text xdef _ircserver xref _ciab xref _SoftInterrupt xref _thisTask xref _TimerSigMask xref _buffer xref _NSamples xref _Forbid xref _Disable xref _Enable xref _Permit xref _custom data1 equ $bfe101 dir1 equ $bfe301 _ircserver ; ; Save registers on stack. ; MOVEM.L A2-A6/D2-D7,-(SP) ; Push Registers ; ; Disable interrupts and tasking. ; JSR _Forbid ; RKM says this is a no-no but don't work without it. JSR _Disable ; Machine is MINE now until I let it go! ; ; ; Read from parallel port to see if IR hardware triggered this interrupt. ; If not then let the server chain continue without further ado. ; ; ; Set up parallel port for reading. ; move.b #0,dir1 * all lines read move.b #0,data1 move.b data1,d0 ; Move byte from parallel port to register. andi.b #$01,d0 ; Mask off bit 0. beq proceed ; If bit is one, then proceed to capture data. JSR _Enable JSR _Permit ; RKM says this is a no-no but don't work without it. MOVEM.L (SP)+,A2-A6/D2-D7 ; Pop Registers MOVEQ #$00,D0 ; Continue the server chain. RTS ; ; Disable the ACK interrupt until after processing is done. ; (Is re-enabled in irc.c) ; Hex 10 = 00010000 Should disable the 8520 FLAG interrupt. ; proceed: move.b #$10,$BFED01 ; ; Turn off the display so that DMA access for screen update doesn't ; steal cycles from the 68000 processor. ; $0100 = clear BPLEN bit; custom+$96 = dmacon register ; move.w #$100,$96+_custom ; ; Start timer B. ; lea.l _ciab,a1 ; Get address of ciab adda.l #$F00,a1 ; Add offset for ciacrb register. or.b #$01,(a1) ; $01 = CIACRBF_START ---> Starts timer b! ; ; Read data from parallel port until buffer is full. ; hold: move.b $bfdd00,d0 ; Read 8520 IRC register to get/reset interrupt bit andi.l #$02,d0 ; Mask off timer B interrupt bit. beq hold ; Loop till get an interrupt. ; ; Read a byte from 8250-A (parallel port) The data direction registers are ; set up in SoftHandler. ; movea.l _buffer,a1 ; a1 now holds buffer location move.b data1,(a1)+ ; Move byte from parallel port to buffer. move.l a1,_buffer ; Update pointer to buffer. subq.l #$1,_NSamples ; 8 bne hold ; Go wait for next timeout if buffer not full. move.b #$02,$BFDD00 ; Disable timer B interrupts. move.b $bfdd00,d0 ; Read 8520 IRC register to reset interrupt bit. ; ; Turn on the display (enable bitplane DMA). ; $8100 = set BPLEN bit; custom+$96 = dmacon register ; move.w #$8100,_custom+$96 ; ; Enable interrupts and tasking. ; JSR _Enable JSR _Permit ; RKM says this is a no-no but don't work without it. ; ; Signal main task to wake up. Data is ready! ; move.l _TimerSigMask,d0 ; Set up data in registers. movea.l _thisTask,a1 movea.l $4,a6 jsr _LVOSignal(a6) ; Send signal (see note above.) ; ; ; Clean up, restore registers and return. ; MOVEM.L (SP)+,A2-A6/D2-D7 ; Pop Registers MOVEQ #$00,D0 ; Continue the server chain. RTS END