;
;  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
