; This source code in this file is licensed to You by Castle Technology
; Limited ("Castle") and its licensors on contractual terms and conditions
; ("Licence") which entitle you freely to modify and/or to distribute this
; source code subject to Your compliance with the terms of the Licence.
; 
; This source code has been made available to You without any warranties
; whatsoever. Consequently, Your use, modification and distribution of this
; source code is entirely at Your own risk and neither Castle, its licensors
; nor any other person who has contributed to this source code shall be
; liable to You for any loss or damage which You may suffer as a result of
; Your use, modification or distribution of this source code.
; 
; Full details of Your rights and obligations are set out in the Licence.
; You should have received a copy of the Licence with this source code file.
; If You have not received a copy, the text of the Licence is available
; online at www.castle-technology.co.uk/riscosbaselicence.htm
; 
        SUBT    Receive routines. => &.Arthur.Econet.Receive
        OPT     OptPage

        ALIGN   $Alignment
StartReception  ROUT
        LD      r13, SReg1
        TST     r13, #SReg2Req
        BEQ     FrameDiscontinue
        LD      r13, SReg2
        ST      r13, Status2
        TST     r13, #AddressPresent
        BEQ     Reset                                   ; No, so give up and start again
        LD      r9, RxByte                              ; Get the first byte, keep in R9 for later
        LD      r13, LocalStation                       ; Get our station number
        TEQ     r9, r13
        BNE     %30                                     ; It might be a broadcast
        SetFIQ  CheckNetOfScout, r11, r13
        B       %40

30
        TEQ     r9, #255                                ; Is it a broadcast?
        BNE     FrameDiscontinue
        SetFIQ  CheckNetOfScoutForBroadcast, r11, r13
40
      [ StrongARM
	MOV	r13, #1
	ST	r13, FIQBusy				; Can't STRB PC in ARMv4
      |
        ST      pc, FIQBusy                             ; Set the Busy flag, since this is not executed in UserMode
      ]
        RTFIQ

        ALIGN   $Alignment
CheckNetOfScout
        LD      r13, SReg2
        TST     r13, #RxDA
        MakeReceptionError2 EQ
        LD      r13, RxByte
        TEQ     r13, #0                                 ; Local net of zero
        BNE     FrameDiscontinue
        B       %60

        ALIGN   $Alignment
CheckNetOfScoutForBroadcast
        LD      r13, SReg2
        TST     r13, #RxDA
        BEQ     FrameDiscontinue
        LD      r13, RxByte
        TEQ     r13, #0                                 ; Local short broadcast?
        BEQ     %50                                     ; Yes, so get on with the reception
        CMP     r13, #&FC                               ; Global short (FF), Global long (FE), Local long (FD), or Reserved (FC)?
        BLT     FrameDiscontinue                        ; No
50
        ORR     r13, r13, #( BroadcastBit :SHR: 8 )
60
        ORR     r13, r9, r13, ASL #8                    ; Bottom 16 bits are the destination Address
        ST      r13, RxMode
        SetFIQ  BufferData, r8, r9
        SetJump CheckScoutBuffer, r11, r13
        ADRL    r8, ScoutBuffer
        MOV     r9, #?ScoutBuffer
        RTFIQ

ReceptionErrorWithSReg2
        [       Debug
        LDR     r11, NetErrorListPointer
        STRB    r13, [ r11, #1 ]                        ; SReg 2 at offset 1
        ]
ReceptionError
        [       Debug
        LDR     r11, NetErrorListPointer
        STR     r8, [ r11, #4 ]                         ; The PC where it happened
        LD      r8, Time
        STR     r8, [ r11, #8 ]                         ; The time it happened
        ]
        LD      r8, Record
        TEQ     r8, #NIL                                ; Is there a valid record (ie is this an Immediate Op)?
        BEQ     NoRxRecordToUpdate
        [       Debug
        LDR     r13, [ r8, #Offset_Handle ]
        STR     r13, [ r11, #12 ]                       ; To whom it happened
        LDRB    r13, [ r8, #Offset_Station ]
        STRB    r13, [ r11, #2 ]
        LDRB    r13, [ r8, #Offset_Network ]
        STRB    r13, [ r11, #3 ]
        MOV     r13, #-1                                ; Initialise the next record
        STR     r13, [ r11, #16 ] !
        STR     r13, [ r11, #12 ]
        STR     r11, NetErrorListPointer                ; Store the pointer for next time
        ]
        LDRB    r9, [ r8, #Offset_Status ]
        LDR     r11, [ r8, #Offset_Identifier ]
        LDR     r13, =TxCBIdentifier
        TEQ     r11, r13                                ; Check if it is a Tx record
        MOVEQ   r9, #Status_NetError
        BEQ     DecrementCountAndWriteStatus            ; Yes, deal with it as a Tx record
TransmissionErrorDuringReceive
        MOV     r9, #Status_RxReady
        STRB    r9, [ r8, #Offset_Status ]
        MOV     r8, #NIL                               ; NIL the record pointer
        STR     r8, Record
NoRxRecordToUpdate
        LD      r13, SReg2
        ST      r13, Status2
        TST     r13, #(RxDA :OR: AddressPresent)
        BEQ     Reset
        B       ReInit


FrameDiscontinue
        MOV     r13, #2_10100010                        ; TxRS, Frame discontinue, RxIE
        ST      r13, CReg1
        B       Ready

        ALIGN   $Alignment
BufferData      ROUT
        LD      r13, SReg2
        TST     r13, #RxDA
        BEQ     WasThatTheEnd
        LD      r13, RxByte
        STRB    r13, [ r8 ], #1
        DECS    r9
        BEQ     FrameDiscontinue
        LD      r13, SReg2
        TST     r13, #RxDA
        BNE     %20
        TEQ     r13, #0
        BNE     WasThatTheEnd
20
        LD      r13, RxByte
        STRB    r13, [ r8 ], #1
        DECS    r9
        BEQ     FrameDiscontinue
        RTFIQ

WasThatTheEnd
        LD      r13, RxMode                             ; Turn the line around if not a broadcast
        TST     r13, #BroadcastBit
        MOVEQ   r13, #2_10000100                        ; RTS, Flag idle, 1 byte mode, NO PSE
        MOVNE   r13, #2_00000100                        ; Flag idle, 1 byte mode, NO PSE
        ST      r13, CReg2                              ; So we can see an RxDA if there is one
        MOV     r13, #2_00000000                        ; Disable interupts
        ST      r13, CReg1
        LD      r13, SReg2
        TST     r13, #FrameValid
        MakeReceptionError2 EQ
        TST     r13, #RxDA
        BEQ     %10
        LD      r13, RxByte
        STRB    r13, [ r8 ], #1
        DECS    r9
10
        TurnAroundDelay r8, r11, r13
        ADR     r13, NextJump                           ; The data fitted in the buffer and all is well
        LDR     pc, [ r13 ]

        ALIGN   $Alignment
CheckScoutBuffer ROUT
        [       DebugFIQ
        LDRNE   r11, =Border_Green
        ADR     r13, VIDC
        STR     r11, [ r13, #0 ]
        ]
        RSB     r9, r9, #?ScoutBuffer                   ; The number of bytes now in the scout buffer
        SUBS    r9, r9, #4                              ; Now the actual number of data bytes received
        BLT     Reset                                   ; FrameDiscontinue ; ReceptionError
        LDR     r11, RxCBList
        LDRB    r13, ScoutBuffer + 3                    ; Destination port
        TEQ     r13, #0                                 ; Is this an immediate operation ??
        BEQ     RxImmediate
CheckRxCB
        TEQ     r11, #NIL                               ; Scan RxCBs for a match
        BEQ     Reset                                   ; FrameDiscontinue ; ReceptionError
        LDRB    r13, [ r11, #Offset_RxStation ]         ; Check the station number first
        TEQ     r13, #255                               ; Wild, skip to check network
        BEQ     %05
        LDRB    r10, ScoutBuffer + 0                    ; Source station
        TEQ     r10, r13
        BNE     TryNextRxCB
05
        LDRB    r13, [ r11, #Offset_RxNetwork ]         ; Now check net number
        TEQ     r13, #255                               ; Wild, skip to check port
        BEQ     %10
        LDRB    r10, ScoutBuffer + 1                    ; Source network
        TEQ     r10, r13
        BNE     TryNextRxCB
10
        LDRB    r13, [ r11, #Offset_RxPort ]            ; Now check port
        TEQ     r13, #255                               ; Wild, skip to check status
        BEQ     %20
        LDRB    r10, ScoutBuffer + 3                    ; Destination port
        TEQ     r10, r13
        BNE     TryNextRxCB
20
        LDRB    r13, [ r11, #Offset_Status ]            ; Now check status
        TEQ     r13, #Status_RxReady
TryNextRxCB
        [       PoduleCapable
        LDR     r10, HardwareAddress
        |
        LDR     r10, =EconetController                  ; Always branched to with BNE, because something didn't match
        ]
        BEQ     ScoutMatch                              ; This branch taken on the TEQ above
        LDR     r11, [ r11, #Offset_Link ]
        B       CheckRxCB

ScoutMatch
        LD      r13, RxMode
        TST     r13, #BroadcastBit
        BNE     RxBroadcast

        MOV     r13, #Status_Receiving
        STRB    r13, [ r11, #Offset_Status ]
        LDR     r13, ScoutBuffer + 0                    ; Source Station, Network, Control, Port
        STRB    r13, [ r11, #Offset_Station ]
        ASR     r13, 8
        STRB    r13, [ r11, #Offset_Network ]
        ASR     r13, 8
        STRB    r13, [ r11, #Offset_Control ]
        ASR     r13, 8
        STRB    r13, [ r11, #Offset_Port ]
        ST      r11, Record

        SetFIQ  TxFromMe, r8, r13, Long
        SetJump WaitForData, r8, r13

        MOV     r13, #2_11100111                        ; RTS, CLRTxST, CLRRxST, FlagIdle, 2Byte, PSE
        ST      r13, CReg2
        MOV     r13, #2_01000100                        ; RxRS, TxIE
        ST      r13, CReg1
        RTFIQ

        ALIGN   $Alignment
WaitForData                                             ; Shared with reception of Poke
        [       False ; DebugFIQ
        ADR     r8, DebugSpacePointer
        LDR     r9, [ r8, #0 ]
        TEQ     r9, #0
        LDRNEB  r13, SReg1
        STRNEB  r13, [ r9 ], #1
        LDRNEB  r13, SReg2
        STRNEB  r13, [ r9 ], #1
        CMP     r9, #DebugSpaceEnd
        MOVGE   r9, #0
        STR     r9, [ r8, #0 ]
        ]
        SetJump EndOfData, r8, r13
        MOV     r13, #2_00111111                        ; -RTS, ClrRxST, TxLast, FC, FlagIdle, 2Byte, PSE
        ST      r13, CReg2
        WaitForFIQ r8, r9
        [       DebugFIQ
        LDR     r8, =Border_Red
        ADR     r9, VIDC
        STR     r8, [ r9, #0 ]
        ]
        LD      r13, SReg1
        TST     r13, #FrameComplete
        MakeReceptionError EQ
        MOV     r13, #2_10000010                        ; TxRS, RxIE
        ST      r13, CReg1
        WaitForFIQ r8, r9
        LD      r13, SReg2
        [       DebugFIQ
        ADR     r8, DebugSpacePointer
        LDR     r9, [ r8, #0 ]
        TEQ     r9, #0
        STRNEB  r13, [ r9 ], #1
        CMP     r9, #DebugSpaceEnd
        MOVGE   r9, #0
        STR     r9, [ r8, #0 ]
        ]
        TST     r13, #AddressPresent
        [       DebugFIQ
        LDRNE   r8, =Border_Green
        LDREQ   r8, =Border_Pink
        ADR     r9, VIDC
        STR     r8, [ r9, #0 ]
        ]
        MakeReceptionError2 EQ
        LD      r13, RxByte
        LD      r8, LocalStation
        TEQ     r13, r8
        MakeReceptionError NE
        WaitForFIQ r8, r9
        [       DebugFIQ
        LDR     r8, =Border_Yellow
        ADR     r9, VIDC
        STR     r8, [ r9, #0 ]
        ]
        LD      r13, SReg2
        TST     r13, #RxDA
        MakeReceptionError2 EQ
        LD      r13, RxByte
        TEQ     r13, #0                                 ; Local network must be zero
        MakeReceptionError NE
        WaitForFIQ r8, r9
        LD      r13, SReg2
        TST     r13, #RxDA
        MakeReceptionError2 EQ
        LD      r13, RxByte
        LDRB    r8, [ r11, #Offset_Station ]
        TEQ     r13, r8
        MakeReceptionError NE
        LD      r13, RxByte
        LDRB    r8, [ r11, #Offset_Network ]
        TEQ     r13, r8
        MakeReceptionError NE
        SetFIQ  BufferData, r8, r13, Long
        ADD     r11, r11, #Offset_Start
        LDMIA   r11, { r8, r9 }                         ; Start & Length
        RTFIQ

        ALIGN   $Alignment
EndOfData
        LD      r11, Record
        LDR     r8, [ r11, #Offset_Size ]               ; The original size
        SUB     r9, r8, r9                              ; The number of bytes received
        STR     r9, [ r11, #Offset_RxSize ]             ; Mark reception so client can find out

        SetFIQ  TxFromMe, r8, r9, Long
        SetJump EndOfData2, r8, r9
        MOV     r13, #2_11100111                        ; RTS, CLRTxST, CLRRxST, FlagIdle, 2Byte, PSE
        ST      r13, CReg2
        [       Analyser
        MOV     r13, #2_01000101                        ; RxRS, TxIE, AC=1
        ST      r13, CReg1
        MOV     r13, #2_10000000                        ; +DTR, NONLOOP
        ST      r13, CReg3
        [       DebugFIQ
        LDR     r8, =Border_Magenta
        ADR     r9, VIDC
        STR     r8, [ r9, #0 ]
        ]
        ]
        MOV     r13, #2_01000100                        ; RxRS, TxIE, AC=0
        ST      r13, CReg1
        RTFIQ

        ALIGN   $Alignment
EndOfData2
        MOV     r13, #2_00111111                        ; -RTS, ClrRxST, TxLast, FC, FlagIdle, 2Byte, PSE
        ST      r13, CReg2
        WaitForFIQ r8, r13
        LD      r13, SReg1
        TST     r13, #FrameComplete
        MakeReceptionError EQ
CompleteReception
        MOV     r13, #Status_Received
        STRB    r13, [ r11, #Offset_Status ]
CauseEventAndReset
        LD      r13, EventSequenceNumber
        INC     r13
        ST      r13, EventSequenceNumber
        STR     r13, [ r11, #Offset_Event ]
CauseInterruptAndReset
        ADR     r11, IOC
        LDRB    r13, [ r11, #IOCIRQMSKA ]               ; IRQ Mask register
        ORR     r13, r13, #force_bit                    ; FIQ to IRQ down-grade
        STRB    r13, [ r11, #IOCIRQMSKA ]               ; IRQ Mask register
        B       Reset

RxBroadcast
        LDR     r13, [ r11, #Offset_Size ]              ; Check that the user's buffer is big enough
        CMP     r9, r13                                 ; Actual size of reception
        MakeReceptionError GT
        MOV     r13, #Status_Receiving
        STRB    r13, [ r11, #Offset_Status ]
        STR     r9, [ r11, #Offset_RxSize ]
        ADR     r12, ScoutBuffer
        LDR     r13, [ r12 ], #4                        ; Source station, net, control and port
        ; R12 now pointing at the actual data
        STRB    r13, [ r11, #Offset_Station ]
        ASR     r13, 8
        STRB    r13, [ r11, #Offset_Network ]
        ASR     r13, 8
        BIC     r13, r13, #BitSeven
        STRB    r13, [ r11, #Offset_Control ]
        ASR     r13, 8
        STRB    r13, [ r11, #Offset_Port ]
        LDR     r8, [ r11, #Offset_Start ]
        ; At this point the register useage is as follows;
        ; R8  is the destination address, doesn't need to be preserved
        ; R9  is the length, in bytes, of the copy required
        ; R10 is free, it is set to its usual value by "CauseInterruptAndReset"
        ; R11 is a pointer to the receive record, not stored in "Record"
        ; R12 is the source address, known to be word aligned, see R10
        ; R13 is free
        TEQ     r9, #0
        BEQ     CompleteReception
        LDR     r10, [ r12 ], #4                        ; Get the first byte(s)
        TST     r8, #3                                  ; Check for alignment
        BEQ     CopyAlignmentZero
        STRB    r10, [ r8 ], #1                         ; Copy the first byte
        DECS    r9
        BEQ     CompleteReception                       ; There was only one byte
        LSR     r10, 8
        TST     r8, #3                                  ; Check for alignment
        BEQ     CopyAlignmentOne
        STRB    r10, [ r8 ], #1                         ; Copy the second byte
        DECS    r9
        BEQ     CompleteReception                       ; There were only two bytes
        LSR     r10, 8
        TST     r8, #3                                  ; Check for alignment
        BEQ     CopyAlignmentTwo
        STRB    r10, [ r8 ], #1                         ; Copy the third byte
        DECS    r9
        BEQ     CompleteReception                       ; There were only three bytes
        LSR     r10, 8

CopyAlignmentThree                                      ; There is one byte left in R10
        LDR     r13, [ r12 ], #4
        ADD     r10, r10, r13, LSL #8                   ; Add in the next three bytes
        CMP     r9, #3
        BLT     CompleteCopy
        STR     r10, [ r8 ], #4
        DEC     r9, 4
        MOV     r10, r13, LSR #24
        B       CopyAlignmentThree

CopyAlignmentTwo                                        ; There are two bytes left in R10
        LDR     r13, [ r12 ], #4
        ADD     r10, r10, r13, LSL #16                  ; Add in the next two bytes
        CMP     r9, #3
        BLT     CompleteCopy
        STR     r10, [ r8 ], #4
        DEC     r9, 4
        MOV     r10, r13, LSR #16
        B       CopyAlignmentTwo

CopyAlignmentOne                                        ; There are three bytes left in R10
        LDR     r13, [ r12 ], #4
        ADD     r10, r10, r13, LSL #24                  ; Add in the next byte
        CMP     r9, #3
        BLT     CompleteCopy
        STR     r10, [ r8 ], #4
        DEC     r9, 4
        MOV     r10, r13, LSR #8
        B       CopyAlignmentOne

CopyAlignmentZero                                       ; There are four bytes left in R10
        CMP     r9, #3
        BLT     CompleteCopy
AlignmentZeroLoop
        STR     r10, [ r8 ], #4
        LDR     r10, [ r12 ], #4
        DEC     r9, 4
        CMP     r9, #3
        BGE     AlignmentZeroLoop

CompleteCopy                                            ; There are 0, 1, 2, or 3 bytes left to go, data is in R10
        TEQ     r9, #0                                  ; No bytes left?
        STRNEB  r10, [ r8 ], #1                         ; No, so store one
        SUBNES  r9, r9, #1                              ; Was that the last one?
        MOVNE   r10, r10, LSR #8                        ; No get the next byte
        STRNEB  r10, [ r8 ], #1                         ; And store it
        SUBNES  r9, r9, #1
        MOVNE   r10, r10, LSR #8
        STRNEB  r10, [ r8 ], #1
        B       CompleteReception

RxImmediate
        [       DebugFIQ
        LDR     r8, =Border_Pink
        ADR     r11, VIDC
        STR     r8, [ r11, #0 ]
        ]
        ADRL    r11, ImmediateRecord
        ST      r11, Record
        MOV     r8, #Status_Receiving
        STRB    r8, [ r11, #Offset_Status ]
        LDR     r8, ScoutBuffer + 0                     ; Station
        STRB    r8, [ r11, #Offset_Station ]
        ASR     r8, 8                                   ; Network
        STRB    r8, [ r11, #Offset_Network ]
        ASR     r8, 8                                   ; Control, Port is always zero
        STRB    r8, [ r11, #Offset_Control ]
        DEC     r8                                      ; Make base of Immediates &80 not &81
        AND     r8, r8, #2_00011111                     ; Clear the top bits [ 0..31 ]
        LD      r9, LockOut
        LD      r13, Protection
        ORR     r13, r13, r9                            ; Add in the lock out state
        MOV     r13, r13, ASR r8                        ; Put relevant protection bit in bit zero
        TST     r13, #BitZero
        MakeReceptionError NE                           ; That operation was protected
        CMP     r8, #( ( ImmediateEnd - ImmediateJumpTable ) / 4 )
        ADDLT   pc, pc, r8, ASL #2
        B       Reset                                   ; That operation we have no implementation for yet
ImmediateJumpTable
        B       RxPeekData                              ; &81
        B       RxPokeData                              ; &82
        B       RxJSR                                   ; &83
        B       RxUserRPC                               ; &84
        B       RxSystemRPC                             ; &85
        B       RxHalt                                  ; &86
        B       RxContinue                              ; &87
        B       RxMachinePeek                           ; &88
        B       RxGetRegisters                          ; &89
ImmediateEnd

RxPeekData                                              ; &81
        SetJump TxStartData, r9, r13, Long
        B       ValidatePeekPokeAddress

RxPokeData                                              ; &82
        SetJump WaitForData, r9, r13                    ; Share with normal reception
ValidatePeekPokeAddress
        ADR     r8, ScoutBuffer + 4                     ; Start, End
        LDMIA   r8, { r8, r9 }
        STR     r8, [ r11, #Offset_Start ]
        SUB     r9, r9, r8                              ; Size = End - Start
        STR     r9, [ r11, #Offset_Size ]
      [ StrongARM
        MOV     r8, #1
	ST	r8, PeekPokeFlag			; Can't STRB PC in ARMv4
      |
        ST      pc, PeekPokeFlag                        ; Non zero because of the mode
      ]
        ADR     r8, IOC
        LDRB    r13, [ r8, #IOCIRQMSKA ]                ; IRQ Mask register
        ORR     r13, r13, #force_bit                    ; FIQ to IRQ down-grade
        STRB    r13, [ r8, #IOCIRQMSKA ]                ; IRQ Mask register
        SetFIQ  TxFromMe, r9, r13, Long
        RTFIQ

RxJSR                                                   ; &83
RxUserRPC                                               ; &84
RxSystemRPC                                             ; &85
        SetFIQ  TxFromMe, r8, r9
        SetJump WaitForArguments, r8, r9
        MOV     r13, #2_11100111                        ; RTS, CLRTxST, CLRRxST, FlagIdle, 2Byte, PSE
        ST      r13, CReg2
        MOV     r13, #2_01000100                        ; RxRS, TxIE
        ST      r13, CReg1
        RTFIQ                                           ; Goes off to TxFromMe, then goes to WaitForArguments

        ALIGN   $Alignment
WaitForArguments
        MOV     r13, #2_00111111                        ; -RTS, ClrRxST, TxLast, FC, FlagIdle, 2Byte, PSE
        ST      r13, CReg2
        WaitForFIQ r8, r9
        LD      r13, SReg1
        TST     r13, #FrameComplete
        MakeReceptionError EQ
        MOV     r13, #2_10000010                        ; TxRS, RxIE
        ST      r13, CReg1
        SetJump EndOfArguments, r8, r9                  ; Do this early
        WaitForFIQ r8, r9
        LD      r13, SReg2
        TST     r13, #AddressPresent
        MakeReceptionError2 EQ
        LD      r13, RxByte
        LD      r9, LocalStation
        TEQ     r13, r9
        MakeReceptionError NE                           ; Station number is wrong
        LDR     r13, ScoutBuffer + 4                    ; The JSR address or Procedure number
        ST      r13, ArgumentsAddressOrNumber
        WaitForFIQ r8, r9
        LD      r13, SReg2
        TST     r13, #RxDA
        MakeReceptionError2 EQ                          ; What?
        LD      r13, RxByte
        TEQ     r13, #0                                 ; Local network must be zero
        MakeReceptionError NE                           ; Network number is wrong
        WaitForFIQ r8, r9
        LD      r13, SReg2
        TST     r13, #RxDA
        MakeReceptionError2 EQ                          ; What?
        LD      r13, RxByte
        LDRB    r9, ImmediateRecord + Offset_Station
        TEQ     r13, r9
        MakeReceptionError NE
        LD      r13, RxByte
        LDRB    r9, ImmediateRecord + Offset_Network
        TEQ     r13, r9
        MakeReceptionError NE
        SetFIQ  BufferData, r9, r13, Long
        ADRL    r8, ArgumentsBuffer
        MOV     r9, #?ArgumentsBuffer
        RTFIQ

        ALIGN   $Alignment
EndOfArguments
        RSB     r9, r9, #?ArgumentsBuffer               ; Size of transmission
        STR     r9, ArgumentsSize
        MOV     r13, #2_11100111                        ; RTS, CLRTxST, CLRRxST, FlagIdle, 2Byte, PSE
        ST      r13, CReg2
        MOV     r13, #2_01000100                        ; RxRS, TxIE
        ST      r13, CReg1
        SetFIQ  TxFromMe, r9, r13
        SetJump EndOfArguments2, r9, r13
        RTFIQ

        ALIGN   $Alignment
EndOfArguments2
        MOV     r13, #2_00111111                        ; -RTS, ClrRxST, TxLast, FC, FlagIdle, 2Byte, PSE
        ST      r13, CReg2
        WaitForFIQ r9, r13
        LD      r13, SReg1
        TST     r13, #FrameComplete
        MakeReceptionError EQ
        MOV     r9, #2_000011100                        ; Protect against another immediate op of this class
        ST      r9, LockOut                             ; Set the lock out state
        B       CauseInterruptAndReset

RxHalt                                                  ; &86
RxContinue                                              ; &87
        B       Reset

RxMachinePeek                                           ; &88
        [       DebugFIQ
        LDR     r8, =Border_Red
        ADR     r9, VIDC
        STR     r8, [ r9, #0 ]
        ]
        [       OldOs
        ADRL    r8, MachineVersionNumber
        MOV     r9, #4 - 1
        |
        ADR     r8, MachinePeekData
        MOV     r9, #?MachinePeekData - 1
        ]
        B       CommonPeek

RxGetRegisters                                          ; &89
        ADR     r9, Registers
        STMIA   r9!, { r0-r14 } ^                       ; Put down user R0 to R14, R9 now has address of R15
        SUB     r8, lr, #4                              ; Correct PC
        STR     r8, [ r9 ], #4                          ; Store R15 (PC+PSR)
        TEQP    psr, #FFlag + IFlag + IRQ_mode          ; Go to IRQ Mode
        NOP
        STMIA   r9!, { r13, r14 }
        TEQP    psr, #FFlag + IFlag + SVC_mode          ; Go to SVC Mode
        NOP
        STMIA   r9, { r13, r14 }
        TEQP    psr, #FFlag + IFlag + FIQ_mode          ; Go back to FIQ Mode
        NOP
        ADR     r8, Registers
        MOV     r9, #?Registers - 1
CommonPeek
        SetFIQ  TxFromMe, r11, r13
        SetJump TxCommonPeekData, r11, r13
        MOV     r13, #2_11100111                        ; RTS, CLRTxST, CLRRxST, FlagIdle, 2Byte, PSE
        ST      r13, CReg2
        MOV     r13, #2_01000100                        ; RxRS, TxIE
        ST      r13, CReg1
        RTFIQ

TxCommonPeekData ROUT
        LD      r13, SReg1
20
        TSTS    r13, #TxDRA                             ; TDRA OK ?
        MakeNetError EQ

        LDRB    r13, [ r8 ], #1
        ST      r13, TxByte
        SetFIQ  TxData, r11, r13, Long
        RTFIQ

        LTORG

        END