; 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 Transmit routines. => &.Arthur.Econet.Transmit
OPT OptPage
ALIGN $Alignment
TxFromMe ROUT ; Send out the destination Address
[ Debug
LDR r13, =Border_Cyan
ADR r11, VIDC
STR r13, [ r11, #0 ]
]
LD r13, SReg1
TSTS r13, #TxDRA ; TDRA OK ?
MakeNetError1 EQ
LD r11, Record ; R11 points to the active record
LDRB r13, [ r11, #Offset_Station ] ; Station number
ST r13, TxByte
LDRB r13, [ r11, #Offset_Network ] ; Net number
ST r13, TxByte
WaitForFIQ r11, r13
LD r13, SReg1
TSTS r13, #TxDRA ; TDRA OK ?
MakeNetError1 EQ
LD r13, LocalStation
ST r13, TxByte
MOV r13, #0 ; Local network must be zero
ST r13, TxByte
PutFIQ r11, r13 ; Go back to "calling" routine
LD r11, Record
RTFIQ ; Note the exit condition => r11 (txRec/rxRec) contains Pointer
ALIGN $Alignment
TxControlAndPort ROUT ; Send out the flag and port bytes
LD r13, SReg1
TSTS r13, #TxDRA ; TDRA OK ?
MakeNetError1 EQ
LDRB r13, [ r11, #Offset_Control ]
ST r13, TxByte
LDRB r13, [ r11, #Offset_Port ]
ST r13, TxByte
LD r13, TxMode
TST r13, #BroadcastBit
BNE BroadcastData ; It IS a broadcast so, now send out the data
TST r13, #ImmediateBit
BEQ FinishScout ; Ordinary case
ImmediateScout
TST r13, #ShortBit
BNE FinishScout
WaitForFIQ r8, r9
LD r13, SReg1
TSTS r13, #TxDRA ; TDRA OK ?
MakeNetError1 EQ
LDR r13, [ r11, #Offset_Destination ]
ST r13, TxByte ; Lo byte
ASR r13, 8
ST r13, TxByte ; MidLo byte
WaitForFIQ r8, r9
LD r13, SReg1
TSTS r13, #TxDRA ; TDRA OK ?
MakeNetError1 EQ
LDR r13, [ r11, #Offset_Destination ]
ASR r13, 16
ST r13, TxByte ; MidHi byte
ASR r13, 8
ST r13, TxByte ; Hi byte
LD r13, TxMode
TST r13, #LongBit
BEQ FinishScout
WaitForFIQ r8, r9
LD r13, SReg1
TSTS r13, #TxDRA ; TDRA OK ?
MakeNetError1 EQ
LDR r13, [ r11, #Offset_Destination ]
LDR r9, [ r11, #Offset_Size ]
ADD r13, r13, r9 ; The end address
ST r13, TxByte ; Lo byte
ASR r13, 8
ST r13, TxByte ; MidLo byte
WaitForFIQ r8, r9
LD r13, SReg1
TSTS r13, #TxDRA ; TDRA OK ?
MakeNetError1 EQ
LDR r13, [ r11, #Offset_Destination ]
LDR r9, [ r11, #Offset_Size ]
ADD r13, r13, r9 ; The end address
ASR r13, 16
ST r13, TxByte ; MidHi byte
ASR r13, 8
ST r13, TxByte ; Hi byte
FinishScout
LDR r13, =2_00111111 ; -RTS, ClrRxST, TxLast, FC, FlagIdle, 2Byte, PSE
ST r13, CReg2
LDR r13, =2_00000100 ; TxIE, Enable the receiver section
ST r13, CReg1
WaitForFIQ r8, r9
LD r13, SReg1
TSTS r13, #FrameComplete
MakeNetError1 EQ
LDR r13, =2_10000010 ; TxRS, RxIE
ST r13, CReg1
WaitForFIQ r8, r9
LD r13, SReg2
ST r13, Status2
TSTS r13, #AddressPresent ; This is the begining of the ScoutAck
MOVEQ r9, #Status_NotListening
BEQ DecrementCountAndWriteStatus ; Every other failure is NetError except this one
LD r13, RxByte
LD r9, LocalStation
TEQ r13, r9 ; Is it well-formed?
MakeNetError NE
WaitForFIQ r8, r9 ; Needed because Address Present forces single byte mode
LD r13, SReg2
TSTS r13, #RxDA
MakeNetError2 EQ
LD r13, RxByte
TEQ r13, #0 ; Local network must be zero
MakeNetError NE
WaitForFIQ r8, r9
LD r13, SReg2
TSTS r13, #RxDA
MakeNetError2 EQ
LD r13, RxByte
LDRB r9, [ r11, #Offset_Station ]
TEQ r13, r9 ; Is it from the right station?
LDREQB r13, RxByte
LDREQB r9, [ r11, #Offset_Network ]
TEQEQ r13, r9 ; On the right network?
MakeNetError NE
LD r13, TxMode
TST r13, #PeekBit
BNE ReadyToPeekData ; Yes, it is a Peek
TST r13, #TwoWayBit
BNE EndOfFinalAck
LD r13, SReg2
TSTS r13, #FrameValid
MakeNetError2 EQ
LDR r13, =2_11100111 ; RTS, CLRTxST, CLRRxST, FlagIdle, 2Byte, PSE
ST r13, CReg2 ; Turn the line around
LDR r13, =2_01000100 ; RxRS, TxIE
ST r13, CReg1
TurnAroundDelay r8, r9, r13
IgnoreCTS
LD r13, SReg1
[ False ; Fix2441 **************************************
TSTS r13, #CTS ; Is there a CTS status that we should ignore?
BNE IgnoreCTS
]
TSTS r13, #TxDRA ; TDRA OK ?
MakeNetError1 EQ
SetFIQ TxFromMe, r8, r9
SetJump TxStartData, r8, r9
RTFIQ
BroadcastData ROUT ; Come here after sending out the Port and Control
SetFIQ TxStartData, r8, r9
RTFIQ
ALIGN $Alignment
ReadyToPeekData
SetFIQ PeekData, r8, r9
ADD r9, r11, #Offset_Start
LDMIA r9, { r8, r9 }
RTFIQ
ALIGN $Alignment
PeekData ROUT
LD r13, SReg2
TST r13, #RxDA
BEQ WasThatTheEndOfPeek
LD r13, RxByte
STRB r13, [ r8 ], #1
DECS r9
MakeNetError EQ
LD r13, SReg2
TST r13, #RxDA
BNE %01 ; Data is definately available
TEQ r13, #0
BNE WasThatTheEndOfPeek
01
LD r13, RxByte
STRB r13, [ r8 ], #1
DECS r9
MakeNetError EQ
RTFIQ ; Will return to PeekData
WasThatTheEndOfPeek
TSTS r13, #FrameValid
MakeNetError2 EQ
LD r13, RxByte
STRB r13, [ r8 ]
MOV r9, #Status_Transmitted
B WriteStatusAndReset
ALIGN $Alignment
TxStartData
LD r13, SReg1
TSTS r13, #TxDRA ; TDRA OK ?
MakeNetError1 EQ
SetFIQ TxData, r8, r9 ; Set up for the transfer routine
ADD r8, r11, #Offset_Start
LDMIA r8, { r8, r9 } ; Get the address and length of the data to send
TEQ r9, #0 ; Zero length transmit ??
B DoTxByte
ALIGN $Alignment
TxData ; The data transfer routine itself
LD r13, SReg1
TSTS r13, #TxDRA ; TDRA OK ?
MakeNetError1 EQ
LDRB r13, [ r8 ], #1
ST r13, TxByte
DECS r9
DoTxByte
BEQ EndOfTx
LDRB r13, [ r8 ], #1
ST r13, TxByte
DECS r9
BEQ EndOfTx
RTFIQ ; Will return to TxData
EndOfTx
LDRB r13, =2_00111111 ; -RTS, ClrRxST, TxLast, FC, FlagIdle, 2Byte, PSE
STRB r13, CReg2
LDRB r13, =2_00000100 ; TxIE, Enable the receiver section
STRB r13, CReg1
WaitForFrameCompletion
LD r13, SReg1
TSTS r13, #INT
BEQ WaitForFrameCompletion
TSTS r13, #FrameComplete
MakeNetError1 EQ
LDR r13, =2_10000010 ; TxRS, RxIE
STRB r13, CReg1
LD r13, TxMode
TST r13, #BroadcastBit
MOVNE r9, #Status_Transmitted
BNE WriteStatusAndReset ; End of broadcast
WaitForFIQ r8, r9
LD r13, SReg2
TSTS r13, #AddressPresent ; This should be the FinalAck
BNE %05 ; It may be the special case of a small idle from a BBC machine
TSTS r13, #RxIdle
BEQ %04 ; Anything but is an error
MOV r13, #2_01100111 ; ClearRxStatus, ClearTxStatus, etc.
STRB r13, CReg2
MOV r9, #200 ; Magic empirical number
03
LD r13, SReg2
TSTS r13, #AddressPresent
BNE %05 ; It may be the special case of a small idle from a BBC machine
DECS r9
BNE %03
04
MakeNetError2
05
LD r13, RxByte
LD r9, LocalStation
TEQ r13, r9
MakeNetError NE
WaitForFIQ r8, r9 ; Needed because AddressPresent forces single byte mode
LD r13, SReg2
TSTS r13, #RxDA
MakeNetError2 EQ
LD r13, RxByte
TEQ r13, #0 ; Local network must be zero
MakeNetError NE
WaitForFIQ r8, r9
LD r13, SReg2
TSTS r13, #RxDA
MakeNetError2 EQ
LDR r11, Record
LD r13, RxByte
LDRB r8, [ r11, #Offset_Station ]
TEQ r13, r8
LDREQB r13, RxByte
LDREQB r8, [ r11, #Offset_Network ]
TEQEQ r13, r8
MakeNetError NE
EndOfFinalAck
LD r13, SReg2
TSTS r13, #FrameValid
MakeNetError2 EQ
MOV r9, #Status_Transmitted
B WriteStatusAndReset
NetErrorWithSReg1 ; Status Register 1 in R13
[ Debug
LDR r11, NetErrorListPointer
STRB r13, [ r11, #0 ] ; SReg 1 at offset 0
]
TST r13, #SReg2Req
BEQ NetError
LD r13, SReg2
NetErrorWithSReg2 ; Status Register 2 in R13
[ Debug
LDR r11, NetErrorListPointer
STRB r13, [ r11, #1 ] ; SReg 2 at offset 1
]
ST r13, Status2
NetError ; No status registers
[ 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 Reset
[ 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
]
LDR r11, [ r8, #Offset_Identifier ]
LDR r13, =RxCBIdentifier
TEQ r11, r13 ; Check if it is an Rx record
BEQ TransmissionErrorDuringReceive ; Yes, deal with it as an Rx record
MOV r9, #Status_NetError
DecrementCountAndWriteStatus ; R9 is the status
LD r8, Record
LDR r13, [ r8, #Offset_Count ]
DECS r13
BLE WriteStatusAndReset ; That was the last retry
STR r13, [ r8, #Offset_Count ]
LDR r13, [ r8, #Offset_Delay ]
LDR r11, [ r8, #Offset_Time ]
ADD r11, r11, r13 ; Compute next start time
STR r11, [ r8, #Offset_Time ]
ADD r11, r11, #ClaimTime ; Compute next LineJammed time
STR r11, [ r8, #Offset_ClaimTime ]
MOV r9, #Status_TxReady ; Ready to restart
WriteStatusAndReset
LDR r11, Record
STRB r9, [ r11, #Offset_Status ]
MOV r8, #NIL ; NIL the record pointer
STR r8, Record
TEQ r9, #Status_TxReady
BEQ Reset
B CauseEventAndReset ; Give an interrupt if it completes
LTORG
FindLocalNetwork ROUT
; Called in SVC mode and remains in SVC mode
; Disables IRQs but preserves the IRQ state
; In None
; Out R0 will have the error pointer if V is set
; All other registers preserved
; Possible errors:
; No Clock
END