; > TestSrc.Begin

        TTL RISC OS 2+ Power-On Self-Test
;
; Startup code for RISC OS ROM Self-Test.
;
; Performs ROM test patterns, determines test strategy and enters
; external or internal test code.
;
; A minimal set of opcodes should be used (ideally, only B, LDR and ADDS)
; so that a processor test may be validly included in the internal test
; sequence.
;
;------------------------------------------------------------------------
; History
;
; Date          Name    Rel     Comment
; ----          ----    ---     -------
; 23-Feb-93     ArtG    2.00    Experimental ARM 600 / Jordan mods
; 20-Oct-93     ARTG    2.02    Changed to new conditional assembly scheme
; 18-Nov-94     RCM     2.05    Morris changes
; 15-May-96	BAR	2.06	Update for ARM7500FE variant, new IOMD ID
;				Code. Used initially in the NC product;
;				needs different prescalers and ROM speed
;				settings, switched on IOMD ID code.
; 30-May-96	BAR	2.07	Add code to flash NC's led's. Ignore morse
;				code and just use the simplified flash
;				sequence.
; 14-Jun-96	BAR	2.08	Add get call for initmodule file.
; 17-Jun-96	BAR	2.09	Change speed settings for the second bank of
;				ROM space.
; 24-Jun-96	BAR	2.10	Updated second check on IOMD ID, instead of
;				checking for ARM7500 IOMD ID code to skip
;				the Virq test, now checks for the original
;				(RiscPC) IOMD ID code and skips Virq test if
;				not equal. Thus ARM7500 and ARM7500FE
;				devices don't execute the test.
;				Updated version number.
;				Added call to sir_IOMD_Regs -show iomd registers
; 08-Jul-96     BAR     2.11    Ensure r0 is cleared before checking IOMD vsn no.
;                               Change ROM Burst speed from93.75nS to 125nS.
; 09-Jul-96                     Make IOMD ID code more efficent. Change
;                               variables used for ROMCR Values and remove
;                               'NormalSpeed' ROMs compiler switching code -
;                               no longer supporting PSwindell.
;                               Change non-7500FE ROM Burst speed from 3 ticks
;				to 4 ticks
; 25-Jul-96	BAR	2.12	Add code to handle EEPROM as well as CMOS
;				RAM. Code supplied by J.Harris.
; 29-Jul-96     BAR     2.13    Update LED stuff to wait properly.
; 29-Jul-96	BAR	2.14	Update exit codes IOMD et all.
;				More work on the LED code.
; 30-Jul-96	BAR	2.15	Humm, get the LED's to work !
; 16-Aug-96	JRH	2.16	Add check for OS image in 2nd ROM bank.
;				Don't program the 2nd ROM bank speed (ROMCR1),
;				unless CanLiveInROMCard is True, in which case
;				check whether we're running from the 2nd bank.
;				Made display of IOMD regs conditional on new
;				ShowIOMDRegs flag, which is set to TRUE
; 05-Sep-96	BAR	2.17	Updated to NOT show the progress colours on
;				the screen unless a POST box is added when
;				they will be shown. This is in accordance
;				with fault report  ANC-00159. The final red
;				fail screen will be maintained as this
;				enfoces the fact the the POSt has failed and
;				that the ser needs to attend to the unit.
;				The compile switch DontShowProgressColours
;				can be set to FALSE, then the progress
;				colours will always be shown.
; 07-Oct-96	JRH	2.18	Changed ExtIO to fix support for speaking to
;				the test box when running from the 2nd ROM bank,
;				conditioned on CanLiveOnROMCard.
; 22-Oct-96	JRH	2.19	Added an Align64 at the end of the file because
;				OS_Find was sometimes failing. Don't know why.
;				Fixed bug introduced in 2.18 which turned burst
;				off on ROMCR0.
; 08 Nov 96	BAR	2.20	Add kluge to skip ram (long) test
;				altogether, 'cos it appears to be crashing.
; amg: Renaissance merge. 7500FE unconditional, other changes now conditioned
;      on STB being {TRUE}. Extra declarations left unconditional.
; 10 Mar 97     BAR     2.21    Add code to check 1K of NVRAM - if reqd.
; 13 Mar 97     BAR     2.22    Change conditional assemble flags for
;                               including new LED flashing routines. Now
;                               checks for Left & Right LED flags.
;                               Always use the VGA VIDC Definition Table if
;                               the flag ChrontelSupport is TRUE.
; 18 Mar 97     BAR     2.23    Added C_DEFAULT (Black) Change use of
;                               C_WARMSTART to C_DEFAULT.
; 12 Jun 97     BAR     2.24    Ensure LED is set to RED before flashing
;                               them - gets the sequence right. If flashed
;                               ensure that BOTH are turned back on.
; 19 Jun 97     BAR     2.25    Remove un-necessary mov r13,r14's
;                               When completed flashing LED's restore the
;                               faultcode flag from fiq_regs.
; 04 Apr 00     KJB     2.30    Converted to run in 32-bit mode always.
;                               ShowIOMDRegs set to FALSE (request from
;                               Tom Clay)
;
;------------------------------------------------------------------------
;
; TS_STATUS should be one of :
;
; 'R'   RISC OS POST
; 'S'   Standalone version (with a2 memory test instead of RISCOS)
; 'T'   Test build - development only
;

TS_STATUS       *       "R"     ;  Medusa POST version 2.0x
;
TS_RELEASE      *       23
TS_CHANGES      *       0


                GBLL    POSTenabled
POSTenabled     SETL    {TRUE}          ; don't permit POST for ordinary startup

                GBLL    AlwaysShortPOST
AlwaysShortPOST SETL    {TRUE} :LAND: STB       		; always do a short POST

                GBLL    ShowIOMDRegs
ShowIOMDRegs	SETL    (IO_Type = "IOMD") :LAND: {FALSE} :LAND: STB	; show IOMD regs

                GBLL   DontShowProgressColours
DontShowProgressColours	SETL	{TRUE} :LAND: STB		; Do not show the progress colour screens.
								; Progress Colours will always be shown when using POST Box.
								; Set to true for NC - Fault Report ANC-00159.

                GBLL    DontDoCMOSTest
DontDoCMOSTest  SETL    {TRUE} :LAND: STB



ts_Rom_bits     *       21                              ; Widest ROM address
ts_Rom_length   *       1 :SHL: ts_Rom_bits             ; Longest ROM
ts_highaddr_bit *       1 :SHL: 25                      ; ARM address width
ts_Alias_bits   *       (1 :SHL: 23)                    ; I/F output bits
ts_recover_time *       (1 :SHL: 8)                     ; inter-twiddle delay
ts_pause_time   *       200                             ; Display pause time
ts_S5_base      *       &3350000                        ; IO register base address
ts_IOEB_ID      *       (ts_S5_base + &50)              ; IOE_B ASIC identification
ts_IOEB_ident   *       &5                              ; the value found there
ts_PCaddress    *       &3010000                        ; PC IO world base address
ts_ReadyByte_00 *       &90                             ; signal 'Here I am' to ExtIO
ts_BBRAM        *       &A0                             ; IIC address of clock/ram chip
                [ STB
ts_BBE2         *       &A8                             ; IIC address of E2ROM chip
ts_BB2KE2       *       &E0                             ; IIC address of 2K E2ROM chip
		]
ts_RamChunk     *       &2000                           ; gap between data line tests
ts_MaxRamTest   *       4*1024*1024                     ; Max. DRAM tested on normal reset
ts_VIDCPhys     *       &3400000                        ; Real location of VIDC

;
; Border colours used for self-test indicators
;
        [ VIDC_Type = "VIDC1a"
C_ARMOK         *       &40000000+&70C  ; testing ROM
C_RAMTEST       *       &40000000+&C70  ; testing RAM
C_FAULT         *       &40000000+&00F  ; failed tests
C_PASSED        *       &40000000+&7C0  ; all passed
C_WARMSTART     *       &40000000+&777  ; not tested
C_DEFAULT       *       &40000000+&000  ; default (Black)
        ]

        [ VIDC_Type = "VIDC20"
C_2NDBANK	*	&40000000+&C00070  ; jumping to image in 2nd ROM bank (Dark blue)
C_ARMOK         *       &40000000+&7000C0  ; testing ROM (Magenta)
C_RAMTEST       *       &40000000+&C07000  ; testing RAM (Blue)
C_FAULT         *       &40000000+&0000F0  ; failed tests(Red)
C_PASSED        *       &40000000+&70C000  ; all passed  (Green)
C_WARMSTART     *       &40000000+&707070  ; not tested  (Mid grey)
C_DEFAULT       *       &40000000+&000000  ; default (Black)
        ]
;
;
; Responses to external commands
;
;
ErrorCmd        *       &00FF
;
; Control bitmasks used to indicate results of test to RISCOS
;

R_SOFT          *       0               ; not a power-on reset
R_HARD          *       1               ; Self-test run due to POR
R_EXTERN        *       2               ; external tests performed
R_TESTED        *       4               ; Self-test run due to test link
R_MEMORY        *       8               ; Memory has been tested
R_ARM3          *       &10             ; ARM 3 fitted
R_MEMSKIP       *       &20             ; long memory test disabled
R_IOEB          *       &40             ; PC-style IO controller (A5000)
R_IOMD          *       &40             ; PC-style IO controller (RiscPC, ARM7500)
R_VRAM          *       &80             ; VRAM present

R_STATUS        *       &1ff            ; bits that aren't a fault

R_CHKFAILBIT    *       &100            ; CMOS contents failed checksum
R_ROMFAILBIT    *       &200            ; ROM failed checksum
R_CAMFAILBIT    *       &400            ; CAM failed
R_PROFAILBIT    *       &800            ; MEMC protection failed
R_IOCFAILBIT    *       &1000           ; IOC register test failed
R_INTFAILBIT    *       &2000           ; Cannot clear interrupts
R_VIDFAILBIT    *       &4000           ; VIDC flyback failure
R_SNDFAILBIT    *       &8000           ; Sound DMA failure
R_CMSFAILBIT    *       &10000          ; CMOS unreadable
R_LINFAILBIT    *       &20000          ; Page zero RAM failure
R_MEMFAILBIT    *       &40000          ; Main RAM test failure
R_CACFAILBIT    *       &80000          ; ARM 3 Cache test failure
;
 [ MorrisSupport
Kludge * 96
 |
Kludge * 0
 ]
        SUBT    Exception vectors
;
; These vectors are available for use while the Rom is mapped into
; low memory addresses. The Reset vector will be copied to low RAM
; as part of a software reset sequence : therefore it must perform
; a fixed operation to ensure compatibility with future versions
; of RISC-OS.
;

Reset
ts_start
        $DoMorrisROMHeader

 [ :LNOT: MorrisSupport
  [ ResetIndirected
        LDR     pc,.+ResetIndirection   ; load pc from vector at &118
  |
        B       ts_RomPatt + PhysROM    ; Jump to normal ROM space
  ]
 ]
01
        &       ts_Rom_length           ; gets patched by ROM builder
02
        &       (ts_ROM_cvectors - ROM) ; pointer to code vector table
03
        &       (ts_ROM_dvectors - ROM) ; pointer to data vector table
04
        &       (ts_ROM_bvectors - ROM) ; pointer to branch table
        B       Reset                   ; not currently used
        B       Reset
        B       Reset


ts_ROMSIZE      *       %BT01 - ts_start
ts_CVECTORS     *       %BT02 - ts_start
ts_DVECTORS     *       %BT03 - ts_start
ts_BVECTORS     *       %BT04 - ts_start

 ! 0, "ts_Rom_length held at ":CC::STR:(%BT01 - ROM)


;
; Selftest version ID
;

00
        ASSERT  %B00 <= (ts_start + &2c + Kludge)
        %       ((ts_start + &2c + Kludge) - %B00)

ts_ID   &       ((TS_STATUS :SHL: 24) + (TS_RELEASE :SHL: 16) + TS_CHANGES)

ts_ID_text
ts_himsg
        =       "SELFTEST"                      ; **DISPLAY_TEXT**
        =       &89                             ; Cursor position
        =       TS_STATUS
        =       ("0" + (TS_RELEASE /     10))
        =       "."
        =       ("0" + (TS_RELEASE :MOD: 10))
        =       ("0" + (TS_CHANGES :MOD: 10))
        =       0

        ALIGN

;
; These vector tables permit access by the external (or downloaded) test
; software to data and code in the POST modules.
; Find the start of these tables through the 2nd and 3rd vectors at
; the start of the ROM.
;

ts_ROM_dvectors
01
        &       ts_ID                   ; Selftest identification number
02
        &       (ts_ID_text - ROM)      ; Selftest identification text


ts_ROM_cvectors
        &       ts_RomPatt
        &       ts_User_startup
        &       ts_Self_test_startup
        &       ts_Dealer_startup
        &       ts_Forced_startup
        &       ts_GetCommand
        &       ts_Softstart
        &       ts_Hardstart


;
; ROM branch vectors - intended primarily so downloaded programs
; may use standard subroutines.  This table should be in a fixed place.
;

00
        ASSERT  %B00 <= (ts_start + 128 + Kludge)
        %       ((ts_start + 128 + Kludge) - %B00)

ts_ROM_bvectors
        B       ts_RomPatt
        B       ts_GetCommand
        B       ts_SendByte
        B       ts_SendWord
        B       ts_GetByte
        B       ts_GetWord
        B       ts_SendText
        B       ts_MoreText
        B       ts_SendLCDCmd


;
; Pad out until the location of the ResetIndirection vector
;

        ASSERT  .-ROM <= ResetIndirection
        %       ResetIndirection-(.-ROM)
        &       ts_RomPatt-ROM+PhysROM

;
; ROM test code
;
; Note : the register order in ADDS ...pc.. is often critical.
; If we want to adjust pc, use ADDS pc,rn,pc so that the PSR is
; rewritten with it's original value.
; If we want to do some pc-relative arithmetic, use ADDS rn,pc,rn
; so that the bits from PSR are NOT used in the address calculation.
;

        SUBT    Macros

        MACRO
        MODE    $mode_bits
        MSR     CPSR_c,#I32_bit :OR: F32_bit :OR: $mode_bits
        MEND

        MACRO
        MOV_fiq $dest,$src
        MODE    FIQ32_mode
        MOV     $dest,$src
        MODE    SVC32_mode
        MEND

        MACRO
        FAULT   $code
        MODE    FIQ32_mode
        ORR     r12_fiq,r12_fiq,$code
        MODE    SVC32_mode
        MEND


;
; Define an area of storage with the required set of data bus patterns
; These are used both for testing the complete width of the data bus
; during ROM pattern testing, and will provide a tidy set of patterns
; if the reset is held, while the ARM increments addresses.
;

        SUBT    ROM Address and Data Patterns

DataPatterns

        GBLA    dmask
dmask   SETA    &80000000

        DCD     &FFFFFFFF               ; first two : all set
        DCD     &0                      ;             all clear

        GBLA    OldOpt                  ; don't list all the walking
OldOpt  SETA    {OPT}                   ; patterns
        OPT     OptNoList

        WHILE   dmask > 0               ; then for each bit
        DCD     &$dmask                 ; set it
        DCD     :NOT: &$dmask           ; and clear it
dmask   SETA    dmask :SHR: 1
        WEND
        OPT     OldOpt
DEnd


        OPT     OptList
;
;
; Read the ROM at a series of addresses
; such that :   a) all the address lines are exercised individually
;               b) all the data lines are exercised individually
;
; Data and address lines are exercised as walking-0 and walking-1.
; The test is performed as a series of LDR operations to avoid using
; a larger instruction set.
;

ts_RomPatt ROUT

        ; Patterns which will exercise most of the data bus.
        ; All are arbitrary instructions with NV execution

        DCD     &F0000000               ; walking 1

OldOpt  SETA    {OPT}                   ; patterns
        OPT     OptNoList

dmask   SETA    &08000000
        WHILE   dmask > 0
        DCD     dmask :OR: &F0000000
dmask   SETA    dmask :SHR: 1
        WEND

        DCD     &FFFFFFFF               ; walking 0

dmask   SETA    &08000000
        WHILE   dmask > 0
        DCD     (:NOT: dmask) :OR: &F0000000
dmask   SETA    dmask :SHR: 1
        WEND

        OPT     OldOpt

        ; Now some proper code :
        ; Initialise address pointer and make MemC safe

        LDR     r0,%01
        ADD     pc,r0,pc
01
        &       0                       ; useful constant

        [ IO_Type = "IOC-A1"            ;;!! unsafe if we execute ROM at zero
        LDR     r1,%02
        ADD     pc,r0,pc
02                                      ;;!! This remaps MEMC's ROM
        &       &E000C :OR: MEMCADR     ;;!! addressing if it hasn't
        STR     r1,[r1]                 ;;!! already happened.
        ]

        LDR     r5,%03                  ; Load r5 with a constant which
        ADD     pc,r0,pc                ; may be added to ROM plus a
03                                      ; walking-zero bitmask to create
        &       ts_Rom_length - 3       ; a valid word address in ROM.
        LDR     r2,%04                  ; Offset from ROM start to here
        ADD     pc,r0,pc
04
        &       ROM - pcfromstart

        ADD     r2,pc,r2                ; pointer to start of ROM
        ADD     r3,r2,r0                ; pointer to start of ROM
pcfromstart
        ADD     r4,r2,r0                ; pointer to start of ROM

        ; assembly-time loop - only 32 iterations required

OldOpt  SETA    {OPT}

        GBLA    doffset
doffset SETA    DataPatterns
        WHILE   doffset < DEnd

        LDR     r0,doffset              ; walking 1 data pattern
        LDR     r1,doffset+4            ; walking 0 data pattern
        LDR     r6,[r2]                 ; walking 1 address pattern
        LDR     r6,[r3]                 ; walking 0 address pattern

        [ (doffset - DataPatterns) > ((32 - ts_Rom_bits) * 8)
        [ (doffset - DataPatterns) < (31 * 8)
        ADD     r2,r4,r0                ; r2 = ROM + walking 1 pattern
        ADD     r3,r4,r1                ; r3 = ROM + walking 0 pattern
        ADD     r3,r3,r5                ; adjust to a valid address
        ]
        ]

        OPT     OptNoList

doffset SETA    doffset + 8
        WEND

        ASSERT  (. - doffset < 4095)    ; in range without barrel shift ?

        OPT     OldOpt

        [ EmulatorSupport
        ARM_on_emulator r0              ; we skip the rest of POST if
        BEQ     CONT                    ; on the emulator
        ]

;
; External interface drivers -
; provides entry points to send byte- and word- and string-sized objects
; and to receive byte- and word-sized objects
;
; Continue into GetCommand, which determines adapter type (or no adapter)
; and jumps to an ExtCmd handler, ts_User_startup, ts_Forced_startup or
; ts_Dealer_startup as appropriate.
;
        B       ts_GetCommand	; (This instruction redundant 'cos ts_GetCommand
				;  is the first thing defined in TestSrc.ExtIO)
        GET     TestSrc.ExtIO

;
; External command handlers - respond to commands given through the
; external test interface.
;

        GET     TestSrc.ExtCmd


        SUBT    Selftest
;
; There is no attached test interface. Is this a power-on reset ?
; Addressing IOC will make MEMC1a remap the ROM to high memory if
; it hasn't already done it, so be careful to ensure that the
; ARM is addressing normally-addressed ROM when this code runs.
;

ts_User_startup    ROUT
        LDR     r0,%01
        ADD     pc,r0,pc
01
        &       0
;
; IOMD will only access the ROM until a write to IOMD has been made -
; make this write also switch on refresh so the DRAM has a chance to
; get running before the memory test starts.
;
        [ MEMC_Type = "IOMD"
        LDR     r1,%02
        ADD     pc,r0,pc
02
        &       (IOMD_Base+IOMD_VREFCR)
        LDR     r2,%03
        ADD     pc,r0,pc
03
        &       IOMD_VREFCR_REF_16
        STR     r2, [r1,#0]
        ]

        [ POSTenabled
        LDR     r1,%12                  ; load address of IOC IRQ register
        ADD     pc,r0,pc
12
        &       IOC+IOCIRQSTAA

        LDR     r1, [r1,#0]             ; Get IRQSTAA register (hence POR bit)
        LDR     r2, %13
        ADD     pc,r0,pc                ; Constant to shift por to bit 31
13
        &       por_bit :SHL: 1
14      ADD     r1,r1,r1
        ADDS    r2,r2,r2
        BCC     %14                     ; loop until por_bit is at bit 31
        ADDS    r1,r1,r1                ; then shift it into carry
        BCC     ts_Self_test_end        ; POR bit clear - do soft reset.

; it's a power-on reset, so assume we can't be in 32-bit mode for ARM 6/7

        MOV_fiq r12_fiq, #R_HARD
        B       ts_Self_test_startup
        |
        B       CONT                    ; if user POST disabled
        ]
;
; Perform self - tests
;
; Any distinction between test operation for Power-up, Display-only
; and Forced tests needs to be made between these three entry points.
;


; This is where tests start if a dumb test link is fitted
; (a diode from A21 to *ROMCS, disabling the ROMs when A21 is high)

ts_Forced_startup  ROUT

        MOV_fiq r12_fiq, #R_TESTED
        B       ts_Self_test_startup

; This is where the tests start if an external display adapter is fitted

ts_Dealer_startup  ROUT

        MOV_fiq r12_fiq, #R_EXTERN

        LDR     r4,%FT02                ; make a pointer to signon string
01      ADD     r4,pc,r4
        ADD     pc,r0,pc
02
        &       (ts_himsg - %BT01 - 8)

        ADD     r14,pc,r0               ; make a return address for this 'call'
        ASSERT  (.+4 = ts_Self_test_startup)    ; PC must point there already !
        B       ts_SendText

ts_Self_test_startup ROUT

; This is where the power-on test starts (every user gets this)


;
; Processor test would go here .... if there was one.
;

 [ MorrisSupport
;
; On startup Morris defaults to dividing all its clocks by two and
; accessing ROM at the slowest possible access speed. So check for
; Morris and set to sensible values.
;
; check for te veriosn of IOMD, only need to determin between variants in
; the ARM7500 and ARM7500FE - condional code assembly excludes non-ARM7500
; devices.

        MOV     r2, #IOMD_Base		; r2 points to the IOMD base address defiend in HDR:IO.IOMDL
        LDRB    r1,[r2,#IOMD_ID1]	; load r1 with IOMD ID high byte
        LDRB    r0,[r2,#IOMD_ID0]	; load r0 with IOMD ID low byte
        ORR     r0,r0,r1,LSL#8		; Or r0 and r1, shifted left 8, put in r0
        LDR     r1,=ts_IOMD_ID2		; get Ref IOMD ID code #2
        CMPS    r0,r1                   ; check for IOMD ID Code #2
	BEQ	%FT05			; If equal, got to 05

        LDRNE   r1,=ts_IOMD_ID3		; If not ID1, get ID code #3
        CMPNES  r0,r1			; If not ID1, check for IOMD ID Code #3
        BNE     %FT10			; Not equal; not an ARM7500 or an ARM7500FE - skip

  [ RO371Timings
05
        MOV     r0, #0                  ;Calling from POST
        BL      TimeCPU                 ;just sets things according to assumed bus speeds for each IOMD id, in this case

  | ; else if not RO371Timings

; Here because its an ARM7500 'FE' variant
; Program the CPU, Memory and IO clock prescalers
; Set the prescalers to :-
;	CPUCLK divide by 2 unless FECPUSpeedNormal set
;	MEMCLK divide by 1
;	IOCLK  divide by 1
;
 [ FECPUSpeedNormal
	MOV     r0, #IOMD_CLKCTL_CpuclkNormal + IOMD_CLKCTL_MemclkNormal + IOMD_CLKCTL_IOclkNormal
 |
	MOV     r0, #IOMD_CLKCTL_CpuclkHalf + IOMD_CLKCTL_MemclkNormal + IOMD_CLKCTL_IOclkNormal
 ]
        STRB    r0, [r2, #IOMD_CLKCTL] ; initialise all the prescalers.
;
; Set ROM speed, take care to preserve 16-bit mode bit...
;
; According to BSiddle on the 15-May-96, Omega will use burst mode roms: use 93nS burst, 156nS initial.
; According to TDbson on the 09-Jul-96, Omega will handle ROMS up to 120nS and 70nS.
; Thus the ROM speed should be initilised to :-
; Half Speed or H bit, clear, which is ON ! : Half the delays, thus DOUBLE all clock ticks.
; Non-Sequental delay : 10 Ticks : Half speed on, so select 5 ticks (5*2)
; Burst delay         :  8 Ticks : Half speed on, so select 4 ticks (4*2)
; Remember the Memory clock on Omega is faster than on previous porducts.
; The fast flash devices used for Omega testing should be able to cope even
; though they aren't burst devices.
        LDRB    r0, [r2, #IOMD_ROMCR0]          ; Get contents of ROMCR0 in to r0
        AND     r0, r0, #&40                    ; clear all but the 16-bit mode flag
    [ ROMSpeedNormal
        ORR     r0, r0, #IOMD_ROMCR_Normal :OR: IOMD_ROMCR_NSTicks_$ROMSpeedNSTicks :OR: IOMD_ROMCR_BTicks_$ROMSpeedBurstTicks
    |
        ORR     r0, r0, #IOMD_ROMCR_HalfSpeed :OR: IOMD_ROMCR_NSTicks_$ROMSpeedNSTicks :OR: IOMD_ROMCR_BTicks_$ROMSpeedBurstTicks
    ]
        STRB    r0, [r2, #IOMD_ROMCR0]          ; Prog. the reg.s
  [ CanLiveOnROMCard
	TST	pc, #ts_RC_2ndbank		; Not running out of 2nd ROM bank?
        ; Don't know what's in the 2nd bank -> program it to a slow default
    [ ExtROMis16bit
     [ ROMSpeedNormal
        MOVEQ   r0, #IOMD_ROMCR_Normal :OR: IOMD_ROMCR_16bit :OR: IOMD_ROMCR_NSTicks_7 :OR: IOMD_ROMCR_BurstOff
     |
        MOVEQ   r0, #IOMD_ROMCR_HalfSpeed :OR: IOMD_ROMCR_16bit :OR: IOMD_ROMCR_NSTicks_7 :OR: IOMD_ROMCR_BurstOff
     ]
    |
     [ ROMSpeedNormal
        MOVEQ   r0, #IOMD_ROMCR_Normal :OR: IOMD_ROMCR_32bit :OR: IOMD_ROMCR_NSTicks_7 :OR: IOMD_ROMCR_BurstOff
     |
        MOVEQ   r0, #IOMD_ROMCR_HalfSpeed :OR: IOMD_ROMCR_32bit :OR: IOMD_ROMCR_NSTicks_7 :OR: IOMD_ROMCR_BurstOff
     ]
    ]
        STRB    r0, [r2, #IOMD_ROMCR1]		; Otherwise program it the same
  ]
	B	%FT10
;

05
; Here because its an ARM7500 variant - NON 'FE' device.
; Program the CPU, Memory and IO clock prescalers
; Set the prescalers to :-
;	CPUCLK divide by 1
;	MEMCLK divide by 1
;	IOCLK  divide by 1
;
        MOV     r0, #IOMD_CLKCTL_CpuclkNormal + IOMD_CLKCTL_MemclkNormal + IOMD_CLKCTL_IOclkNormal
        STRB    r0, [r2, #IOMD_CLKCTL] ; initialise all prescalers to div1
;
; Set ROM speed, take care to preserve 16-bit mode bit...
;
; According to RJKing on 6/5/94, Kryten will use burst mode roms: use 93nS burst, 156nS initial.
; According to BSiddle on 09-Jul-96 - Omega will need to set the burst speed to 4 ticks from 3 ticks.
; Thus the ROM speed should be initilised to :-
; Half Speed or H bit, Set, which is OFF ! : Don't half the delays.
; Non-Sequental delay :  5 Ticks : Half speed off, so select 5 ticks
; Burst delay         :  4 Ticks : Half speed off, so select 4 ticks
; The fast EPROMS used for Kryten testing should be able to cope even though
; they aren't burst devices

        LDRB    r0, [r2, #IOMD_ROMCR0]          ; Get contents of ROMCR0 in to r0
        AND     r0, r0, #&40                    ; clear all but the 16-bit mode flag
    [ ROMSpeedNormal
        ORR     r0, r0, #IOMD_ROMCR_Normal :OR: IOMD_ROMCR_NSTicks_$ROMSpeedNSTicks :OR: IOMD_ROMCR_BTicks_$ROMSpeedBurstTicks
    |
        ORR     r0, r0, #IOMD_ROMCR_HalfSpeed :OR: IOMD_ROMCR_NSTicks_$ROMSpeedNSTicks :OR: IOMD_ROMCR_BTicks_$ROMSpeedBurstTicks
    ]
        STRB    r0, [r2, #IOMD_ROMCR0]          ; Prog. the reg.s
  [ CanLiveOnROMCard
	TST	pc, #ts_RC_2ndbank		; Not running out of 2nd ROM bank?
        ; Don't know what's in the 2nd bank -> program it to a slow default
    [ ExtROMis16bit
     [ ROMSpeedNormal
        MOVEQ   r0, #IOMD_ROMCR_Normal :OR: IOMD_ROMCR_16bit :OR: IOMD_ROMCR_NSTicks_7 :OR: IOMD_ROMCR_BurstOff
     |
        MOVEQ   r0, #IOMD_ROMCR_HalfSpeed :OR: IOMD_ROMCR_16bit :OR: IOMD_ROMCR_NSTicks_7 :OR: IOMD_ROMCR_BurstOff
     ]
    |
     [ ROMSpeedNormal
        MOVEQ   r0, #IOMD_ROMCR_Normal :OR: IOMD_ROMCR_32bit :OR: IOMD_ROMCR_NSTicks_7 :OR: IOMD_ROMCR_BurstOff
     |
        MOVEQ   r0, #IOMD_ROMCR_HalfSpeed :OR: IOMD_ROMCR_32bit :OR: IOMD_ROMCR_NSTicks_7 :OR: IOMD_ROMCR_BurstOff
     ]
    ]
        STRB    r0, [r2, #IOMD_ROMCR1]		; Otherwise program it the same
  ]

 ] ;RO371Timings conditional

;
10
 ]
;
; From this point on we assume we can safely use all the processor
;
; Initialise VIDC
;

ts_InitVIDC
        [ IO_Type = "IOMD"              ; If POSTbox fitted, ROM may still be mapped everywhere
                ; Using IOMD
                MOV     r2,#IOMD_Base
                MOV     r0, #IOMD_VREFCR_REF_16 ; switch on DRAM refresh
                STR     r0, [r2, #IOMD_VREFCR]
                MOV     r1,#ts_VIDCPhys

                [ ChrontelSupport
                        ; We have a Chrontel chip ... thus always set for VGA.
                        ADRL    r2,TestVVIDCTAB
                | ; NOT ChrontelSupport
                        ; We don't have a Chrontel chip
                        ; ... thus check MonitorType and select table as reqd.
                        ADRL    r2,TestVIDCTAB
                        LDR     r0,=IOMD_MonitorType
                        LDR     r0,[r0]
                        ANDS    r0,r0,#IOMD_MonitorIDMask
                        ADDEQ   r2,r2,#(TestVVIDCTAB-TestVIDCTAB)
                ] ; Endif - ChrontelSupport
        | ; not IOMD
                MOV     r1,#ts_VIDCPhys
                ADRL    r2,TestVIDCTAB
        ] ; Endif - IO_Type = "IOMD"

10      LDR     r0, [r2],#4
        CMP     r0, #-1
        STRNE   r0, [r1]
        BNE     %BT10

;
; Test for presence of OS image in 2nd ROM bank and jump to it
;
	GBLS	DoROMCardThings
  [ ROMCardSupport :LOR: CanLiveOnROMCard
DoROMCardThings	SETS	"GET	TestSrc.ROMCard"
  |
DoROMCardThings	SETS	""
  ]
	$DoROMCardThings


;
; Set purple screen
;

	[ DontShowProgressColours
        MOV_fiq r0,r12_fiq              	; restore the faultcode bits
        ANDS    r0,r0,#(R_EXTERN :OR: R_TESTED)	; If test adapter present,
			                   	; NE : Adaptor fitted, show progress.
 	           				; EQ : No Adaptor fitted, don't show progress
	BEQ	ts_RomTest			; EQ : Don't show colours
	]
	MOV	r1, #ts_VIDCPhys

 [ :LNOT: StrongARM_POST
   ;skip POST for StrongARM or ARM8
        ARM_read_ID r0
        AND     r0,r0,#&F000
        CMP     r0,#&A000              ;if we are a StrongARM...
        CMPNE   r0,#&8000              ;or an ARM8...
        LDREQ   r0,=C_WARMSTART        ;the colour that indicates no POST performed
        STREQ   r0,[r1]
        BEQ     ts_Hardstart           ;RISC OS - right now!
 ]

 [ ARM810support :LAND: (:LNOT: ARM810_POST)
   ;just too horrible to fix POST for ARM 8 at the moment
        ARM_read_ID r0
        AND     r0,r0,#&F000
        CMP     r0,#&8000              ;if we are an ARM 8
        LDREQ   r0,=C_WARMSTART        ;the colour that indicates no POST performed
        STREQ   r0,[r1]
        BEQ     ts_Hardstart           ;RISC OS - right now!
 ]

        LDR	r0, =C_ARMOK     		; set initial screen colour
        STR	r0, [r1]

        B       ts_RomTest

        LTORG
        ROUT

;
; Calculate ROM checksum : display status and calculated checksum.
;

1
        =       "ROM   :",0
2
        =       "ROM bad",&88,&ff,&ff,&ff,&ff,&ff,&ff,&ff,&ff,0
3
        =       "ROM size",&8A,&ff,&ff,&ff,&ff,&ff,&ff,0
        ALIGN

ts_RomTest
        ADR     r4,%BT1
        BL      ts_SendText

        BL      ts_ROM_checksum
        BEQ     %20
        ADR     r4,%BT2                 ; Failed message
        FAULT   #R_ROMFAILBIT           ; set ROM bit in r12_fiq
        MOV     r8,r0                   ; calculated checksum
        BL      ts_SendText

        BL      ts_ROM_alias            ; Checksum failed :-
        ADR     r4,%BT3                 ; hunt for first alias
        MOV     r8,r0, LSL #8
        BL      ts_SendText             ; and report it.
20

        [ IO_Type = "IOC-A1"            ; Don't use RISC OS MemSize
                                        ; until much later - it sets up
                                        ; the ARM600 MMU as well.
        B       ts_MEMCset

;
; Do MEMC setup and memory size determination (the first time).
;
        LTORG
        ROUT

1
        =       "M Size :",0
2
        =       "M Size",&89,&ff,&ff,&ff,&ff,".",&ff,&ff,0
        ALIGN

ts_MEMCset
        MOV     r12,#0
        ADR     r4,%BT1
        BL      ts_SendText
        LDR     r1,=(&E000C :OR: MEMCADR)       ; MemSize expects 32k page
        STR     r1,[r1]
        BL      MemSize

;
; MemSize returns with  r0 = page size   (now in bytes, *NOT* in MEMC control patterns),
;                       r1 = memory size (in bytes)
;                       r2 = MEMC control value
;
; Translate these into a number that looks like :
;
;                       mmmm.pp
;
; where mmmm is memory size in hex Kbytes, pp is page size in hex Kbytes.
;
        MODE    FIQ32_mode                      ; Save memory size and
        MOV     r11_fiq,r2                      ; MEMC setup value for
        MOV     r10_fiq,r1                      ; later use
        MODE    SVC32_mode

        MOV     r8, r0, LSR #2                  ; MemSize now returns actual page size in r0
        ADD     r8,r8,r1,LSL #6
        ADR     r4,%BT2
        BL      ts_SendText

        ]

;
; Test data, address and byte strobe lines.
; On MEMC systems, this calls MemSize and tests the memory that finds.
; On IOMD systems, memory sizing is performed along with the data line
; tests, and that result is used for address line testing.
;

        B       ts_LineTest

                GBLS    tsGetMem1
tsGetMem1       SETS    "GET TestSrc.Mem1" :CC: MEMC_Type
                $tsGetMem1

;
; Test IOC.
; This shuld require vector space to work (for testing interrupts),
; but the current version just reports the status register contents.
;
; Display is    ccaabbff
;
;  where cc is the control register
;        aa is IRQ status register A
;        bb is IRQ status register B
;        ff is FIQ status register
;

        B       ts_IOCTest

        LTORG
        ROUT

        [ IO_Type = "IOMD"
1
        =       "IOMD  :",0
2
        =       "IOMD-F",&88,&ff,&ff,&ff,&ff,&ff,&ff,&ff,&ff,0
3
        =       "IOMD-V"
4
        =       &88,&ff,&ff,&ff,&ff," V.",&ff,0
        |
1
        =       "IOC   :",0
2
        =       "IOC-F",&88,&ff,&ff,&ff,&ff,&ff,&ff,&ff,&ff,0
3
        =       "IOC"
4
        =       &88,&ff,&ff,&ff,&ff,&ff,&ff,&ff,&ff,0
        ]
        ALIGN

ts_IOCTest
        ADR     r4,%BT1
        BL      ts_SendText
        BL      ts_IOCreg       ; check register integrity
        BEQ     %FT8
        ADR     r4,%BT2
        BL      ts_SendText     ; report if failure

        FAULT   #R_IOCFAILBIT
8
        ADR     r4,%BT1
        BL      ts_SendText
        BL      ts_IOCstat      ; IOCstat, get IOC/IOMD Vsn number.
                                ; Note : func leaves falgs un altered, thus
                                ; result of last comparison is passed back
                                ; as the result.
                                ; r8 has the id&vsn number : &IIIIVV00
        BEQ     %FT10           ; fail message only printed if
        ADR     r4,%BT3         ; ID code unrecognised
        BL      ts_SendText
        FAULT   #R_IOCFAILBIT   ; .. and set error bit if IOMD code is wrong
        B       %FT11
10
        ADR     r4,%BT4         ; print the status value
        BL      ts_MoreText
        FAULT   #R_IOMD         ; set that bit in the result word
				; to indicate an IOMD was found.

11

  [ IO_Type = "IOMD"
		; IO world is IOMD : Show IOMD Regs, skip IOEB test
    [ ShowIOMDRegs
	BL	sir_ShowIOMDRegs
    ]
        B       ts_CMOStest
  |
		; IO world is IOEB: Do the IOEB test, skip Show IOMD Regs.
        B       ts_IOEBtest
  ]

        LTORG
        ROUT

;
; Check for presence of IOEB ASIC
;

        [ IO_Type = "IOEB"

1
        =       "IOEB  :",0
2
        =       "IOEB",&88,"exists",0


        ALIGN

ts_IOEBtest
        ADR     r4,%BT1
        BL      ts_SendText

        LDR     r0,=ts_IOEB_ID                  ; read an ID register in the IOEB ASIC
        LDRB    r0, [r0]
        AND     r0, r0, #&f
        CMPS    r0, #ts_IOEB_ident              ; if it looks right ( == 5) ..
        BNE     %10

        FAULT   #R_IOEB                         ; set that bit in the result word
        ADR     r4, %BT2
        BL      ts_SendText
10      B       ts_CMOStest
        ] ; IOEB IO world
        ROUT

;
; Read CMOS
; Check the checksum, read the memory test flag.
;


ts_CMOStest
        [ DontDoCMOSTest
        B       ts_IOinit
        |
        ADR     r4,%FT1
        BL      ts_SendText

        [ ChecksumCMOS :LAND: STB
        LDR     r0,=(ts_BBRAM + &4000)
        MOV     r1,#&C0                 ; Get first RAM area
        MOV     r2,#CMOSxseed
        BL      ts_CMOSread
        BNE     %FT10
        MOV     r2, r0
        LDR     r0,=(ts_BBRAM + &1000)  ; Accumulate the second RAM area
        MOV     r1,#&2F
        BL      ts_CMOSread
        BNE     %FT10
        RSB     r2, r0, #0              ; Subtract from the checksum byte
        LDR     r0,=(ts_BBRAM + &3F00)
        MOV     r1,#1
        BL      ts_CMOSread
        BNE     %FT10
        MOV     r8, r0, LSL #24
        ANDS    r0, r0, #&FF            ; A zero result ?
        MOV     r1, #R_CHKFAILBIT
        ADR     r4,%FT3                 ; Report checksum failure
        BNE     %FT21                   ; failed .. report error
        ]                               ; end ChecksumCMOS

	[ :LNOT: AlwaysShortPOST	; Always do a short post on STBs
        LDR     r0,=(ts_BBRAM + &FC00)  ; Read Misc1CMOS byte
        MOV     r1,#1
        MOV     r2,#0
        BL      ts_CMOSread
        BNE     %FT10
        ANDS    r0,r0,#&80              ; Test the memory-test-disable bit
        BEQ     %FT25
	]
        FAULT   #R_MEMSKIP              ; If set, skip the memory test
        B       %FT25

10
; CMOS failed -> try E2
    [ E2ROMSupport :LAND: STB
        [ ChecksumCMOS

                                        ; Accumulate the first RAM area
        LDR     r0,=(ts_BBE2 + &4000)   ; r0 = base addr + start location
        MOV     r1,#&C0                 ; r1 = length of data to read
        MOV     r2,#CMOSxseed           ; r2 = checksum seed or previous value
        BL      ts_CMOSread             ; read the cmos r0 = new checksum. NE = failure; EQ = ok.
        BNE     %FT20                   ; branch if NE - failed to ready at all.

                                        ; Accumulate the second RAM area
        MOV     r2, r0                  ; r2 = r0 = new checksum value.
        LDR     r0,=(ts_BBE2 + &1000)   ; r0 = base addr + start location
        MOV     r1,#&2F                 ; r1 = length of data to read
        BL      ts_CMOSread             ; read the cmos r0 = new checksum. NE = failure; EQ = ok.
        BNE     %FT22                   ; branch if NE - failed to ready at all.
        RSB     r2, r0, #0              ; Subtract from the checksum byte

                                        ; Check to see if we need to Accumulate the THIRD area.
        MOV     r1,#?CMOSRAMCache        ; r1 = size of the CMOS RAM
        TEQ     r1,#240                 ; Is r1 = 240 bytes ?
        BEQ     %FT15                   ; It is equal, go to checksum checking code

                                        ; Accumulate the third RAM area
        MOV     r2,r0                   ; r2 = r0 = new checksum value.
        LDR     r0,=(ts_BBE2 + &10000)  ; r0 = base addr + start location
        MOV     r1,#&300                ; r1 = length of data to read
        BL      ts_CMOSread             ; read the cmos r0 = new checksum. NE = failure; EQ = ok.
        BNE     %FT22                   ; branch if NE - failed to ready at all.

                                        ; read and check the shecksum value.
15      RSB     r2, r0, #0              ; Subtract from the checksum byte
        LDR     r0,=(ts_BBE2 + &3F00)   ; r0 = base addr + start location
        MOV     r1,#1                   ; r1 = length of data to read
        BL      ts_CMOSread             ; read the cmos r0 = new checksum. NE = failure; EQ = ok.
        BNE     %FT22                   ; branch if NE - failed to ready at all.

                                        ; Check the checksum is correct
        MOV     r8, r0, LSL #24         ; r8 = r0 << 24 : put the checksum value in r8 for displaying.
        ANDS    r0, r0, #&FF            ; r0 = r0 + &FF : If alls ok s/be a zero result ...
        MOV     r1, #R_CHKFAILBIT       ; r1 = checksum fail flag
        ADR     r4,%FT3                 ; Report checksum failure
        BNE     %FT21                   ; failed .. report error
        ]                               ; end ChecksumCMOS

	[ STB :LAND: :LNOT: AlwaysShortPOST	; Always do a short post on STBs
        LDR     r0,=(ts_BBE2 + &FC00)   ; Read Misc1CMOS byte
        MOV     r1,#1
        MOV     r2,#0
        BL      ts_CMOSread
        BNE     %FT22
        ANDS    r0,r0,#&80              ; Test the memory-test-disable bit
        BEQ     %FT25
	]
        FAULT   #R_MEMSKIP              ; If set, skip the memory test
        B       %FT25
    ]

1
        =       "SRAM  :",0
2
        =       "SRAM-F",0
3
        =       "SRAM-C",&8e,&ff,&ff,0
        ALIGN

20
; CMOS failed -> try 2K E2
    [ E2ROMSupport
        [ ChecksumCMOS

                                        ; Accumulate the first RAM area
        LDR     r0,=(ts_BB2KE2 + &4000) ; r0 = base addr + start location
        MOV     r1,#&C0                 ; r1 = length of data to read
        MOV     r2,#CMOSxseed           ; r2 = checksum seed or previous value
        BL      ts_CMOSread             ; read the cmos r0 = new checksum. NE = failure; EQ = ok.
        BNE     %FT22                   ; branch if NE - failed to ready at all.

                                        ; Accumulate the second RAM area
        MOV     r2, r0                  ; r2 = r0 = new checksum value.
        LDR     r0,=(ts_BB2KE2 + &1000) ; r0 = base addr + start location
        MOV     r1,#&2F                 ; r1 = length of data to read
        BL      ts_CMOSread             ; read the cmos r0 = new checksum. NE = failure; EQ = ok.
        BNE     %FT22                   ; branch if NE - failed to ready at all.
        RSB     r2, r0, #0              ; Subtract from the checksum byte

                                        ; Check to see if we need to Accumulate the THIRD area.
        MOV     r1,#?CMOSRAMCache        ; r1 = size of the CMOS RAM
        TEQ     r1,#240                 ; Is r1 = 240 bytes ?
        BEQ     %FT15                   ; It is equal, go to checksum checking code

                                        ; Accumulate the third RAM area
        MOV     r2,r0                   ; r2 = r0 = new checksum value.
        LDR     r0,=(ts_BB2KE2 + &10000); r0 = base addr + start location
        MOV     r1,#&300                ; r1 = length of data to read
        BL      ts_CMOSread             ; read the cmos r0 = new checksum. NE = failure; EQ = ok.
        BNE     %FT22                   ; branch if NE - failed to ready at all.

                                        ; read and check the shecksum value.
15      RSB     r2, r0, #0              ; Subtract from the checksum byte
        LDR     r0,=(ts_BB2KE2 + &3F00) ; r0 = base addr + start location
        MOV     r1,#1                   ; r1 = length of data to read
        BL      ts_CMOSread             ; read the cmos r0 = new checksum. NE = failure; EQ = ok.
        BNE     %FT22                   ; branch if NE - failed to ready at all.

                                        ; Check the checksum is correct
        MOV     r8, r0, LSL #24         ; r8 = r0 << 24 : put the checksum value in r8 for displaying.
        ANDS    r0, r0, #&FF            ; r0 = r0 + &FF : If alls ok s/be a zero result ...
        MOV     r1, #R_CHKFAILBIT       ; r1 = checksum fail flag
        ADR     r4,%BT3                 ; Report checksum failure
        BNE     %FT21                   ; failed .. report error
        ]                               ; end ChecksumCMOS

	[ :LNOT: AlwaysShortPOST	; Always do a short post on STBs
        LDR     r0,=(ts_BB2KE2 + &FC00) ; Read Misc1CMOS byte
        MOV     r1,#1
        MOV     r2,#0
        BL      ts_CMOSread
        BNE     %FT22
        ANDS    r0,r0,#&80              ; Test the memory-test-disable bit
        BEQ     %FT25
	]
        FAULT   #R_MEMSKIP              ; If set, skip the memory test
        B       %FT25
    ]
22
        MOV     r1,#R_CMSFAILBIT        ; Real fault - set the fault bit
        ADR     r4,%BT2                 ; Report fault accessing IIC
                                        ; (Bitmap & POST display)
21
        FAULT   r1
        BL      ts_SendText             ; Report one fault or another
25
        B       ts_IOinit

        ] ; DontDoCMOSTest

        LTORG
        ROUT
;
; Initialize  various machine registers - e.g, turn off the floppy
; drive, etc, etc.
;

1
        =       "IOinit:",0
        ALIGN

ts_IOinit
        ADR     r4,%BT1
        BL      ts_SendText
        ADRL    r2,ts_IOinitab
10
        LDR     r0,[r2],#4              ; Get address
        LDR     r1,[r2],#4              ; Get initialization data
        CMPS    r0,#(-1)
        STRNE   r1,[r0]                 ; write to IO port
        BNE     %10
        B       Speedset
;
; Use the RISC OS MEMC setup code to guess the proper processor / memory
; configuration. The memory speed can then be set up correctly for
; fastest possible working, and the memory array tested in the
; configuration RISC OS expects.
;
; Display the results of the TimeCPU test as :
;
;               ssss.m.r
;
; where ssss is the processor speed in hex kHz,
;       m    is 0 for MEMC, 1 for MEMC1a
;       r    is the MEMC rom speed switch setting.
;
        ROUT

1
        =       "Speed :",0
2
        =       "Speed",&88,&ff,&ff,&ff,&ff,".",&ff,".",&ff,0

        ALIGN

Speedset
        ADR     r4,%BT1
        BL      ts_SendText

        [ MEMC_Type = "IOMD"
        MOV     r9,#0
        |
        MOV_fiq r0, r11_fiq                     ; get MEMC setup
        MOV     r9,r0                           ; compare IOC and CPU clocks
        ]

        BL      TimeCPU
        MOV     r0,r9
        MOV_fiq r11_fiq,r0

        MOV     r8,r7,LSL #16
        TST     r7, #1 :SHL: 16                 ; test bit 16 of r7 :
        ADDNE   r8,r8,#&1000                    ; MEMC1 / MEMC1a detected
        AND     r9,r9,#&C0                      ; get High ROM access bits
        ADD     r8,r8,r9, LSL #2
        ADR     r4,%BT2
        BL      ts_SendText
        B       RAMtest

;
; Long RAM test, ideally exercising all memory.
; In order to keep boot time short, the following scheme is used :
;
; Normal power-on boot - test VRAM and up to 4M of first DRAM entry
; CMOS disable set     - test nothing
; Test hardware fitted - test entire memory
;

        ROUT


1
        =       "RAM   :",0
2
        =       "RAM bad",&88,&ff,&ff,&ff,&ff,&ff,&ff,&ff,&ff,0
3
        =       &89,"skipped",0
4
        =       "RAM   :",&88,&ff,&ff,&ff,&ff,&ff,&ff,&ff,&ff,0


        ALIGN

RAMtest
 [ {TRUE}
        B       ts_VIDCtest	; skip memory test altogether
 |
	ADR     r4,%BT1
 ]
        BL      ts_SendText
;
; if (R_MEMSKIP && R_HARD)
;       skip all the remaining tests
; if (!R_LINFAILBIT)
;       perform the long memory test
;
        MOV_fiq r0,r12_fiq              ; skip this test if data line fault
        AND     r1,r0,#(R_MEMSKIP :OR: R_HARD)  ; or the user didn't want it
        TEQS    r1,#(R_MEMSKIP :OR: R_HARD)
        ANDNE   r1,r1,#R_LINFAILBIT
        TEQNE   r1,#R_LINFAILBIT
        BNE     %12
        ADR     r4,%BT3                 ; skipping memory test ....
        BL      ts_MoreText
        B       ts_Report
12
	[ STB :LAND: DontShowProgressColours
        MOV_fiq r0,r12_fiq              	; restore the faultcode bits
        ANDS    r0,r0,#(R_EXTERN :OR: R_TESTED)	; If test adapter present,
			                   	; NE : Adaptor fitted, show progress.
 	           				; EQ : No Adaptor fitted, don't show progress
	BEQ	%FT13				; EQ : Don't show colours
	]
        LDR     r1,=C_RAMTEST           ; doing at least part of the long memory test
        LDR     r0,=ts_VIDCPhys         ; write the border colour
        STR     r1,[r0]
13
        BL      MemSize                 ; Set MMU up, mapping (some) RAM at logical address 0
                                        ; Note that this returns with the MMU enabled,
                                        ; the ROM remapped to it's ORGed address,
					; and r4 the offset from physical to ORGed ROM addresses
					; r4 = ROM - Phys[Ext]ROM
	RSB	r4, r4, #PhysSpace	; r4 = PhysSpace - ROM + Phys[Ext]ROM, pc = ROM + offset
        MODE    SVC32_mode              ; Must do this, as PhysSpace is outside 26 bit addressing
	ADD	pc, pc, r4		; pc = PhysSpace + Phys[Ext]ROM + offset
        NOP                             ; this instruction skipped by pc adjustment

;
; Modify the PhysRamTable so only VRAM and the first ts_MaxRamTest of DRAM gets tested
;
        MOV_fiq r0,r12                  ; get the test condition flags

        ANDS    r0,r0,#(R_EXTERN :OR: R_TESTED)
        BNE     %FT16                   ; do full test if test adapter is present
        MOV     r9,#PhysRamTable
        ADD     r10,r9,#(PhysRamTableEnd-PhysRamTable)
14
        LDR     r1,[r9, #4]
        ADD     r0,r0,r1                ; r0 = running sum of memory sizes
        SUBS    r2,r0,#ts_MaxRamTest    ; r2 = excess over ts_MaxRamTest
        SUBHI   r1,r1,r2                ; r1 = current size truncated
        STRHI   r1,[r9, #4]
        MOVHI   r0,#ts_MaxRamTest       ; truncate running sum to MaxRamTest

        ADD     r9,r9,#(DRAMPhysAddrB-DRAMPhysAddrA)
        CMPS    r9,r10
        BNE     %BT14
16
        FAULT   #R_MEMORY               ; memory tests were attempted

        MOV     r9,#VideoPhysAddr
        LDR     r8,[r9]                 ; report the test address
        ADRL    r4,%BT4
        BL      ts_SendText
        LDR     r0,[r9]                 ; get VRAM start address and size
        LDR     r1,[r9,#4]
        ADD     r0,r0,#PhysSpace
        BL      ts_RamTest
        BNE     %FT20                   ; failed - abort ram testing

;
; VRAM (or 1st MB of DRAM, if no VRAM fitted) looks OK - move the translation
; table there so memory tests can proceed without smashing it.
;
        MOV     r9,#PhysRamTable
        LDR     r0,[r9,#VideoPhysAddr-PhysRamTable]     ; get address of video RAM
        LDR     r1,[r9,#DRAMPhysAddrA-PhysRamTable]     ; get address of 1st DRAM bank
        LDR     r3, =DRAMOffset_L2PT
        ADD     r1, r1, r3              ; make r1 -> L2PT
        ADD     r0, r0, r3              ; make r0 -> temporary L2PT
        BL      ts_remap_ttab           ; copy ttab at r1 to r0 and change table base

;
; Now run the RAM test at each DRAMPhysAddr until the end of the table or a zero entry
; is reached. Mark tested entries by setting the PhysSpace address, so a pointer to the
; next entry need not be kept.
;
18
        MOV     r9,#DRAMPhysAddrA
        ADD     r10,r9,#(PhysRamTableEnd-DRAMPhysAddrA)
19
        CMPS    r9,r10                  ; reached end of table ?
        LDRNE   r0,[r9]
        TSTNE   r0,r0                   ; reached unused entries ?
        LDRNE   r1,[r9,#4]              ; or blanked-out entries ?
        TSTNE   r1,r1
        BEQ     %FT21                   ; .. all passed OK
        TSTS    r0,#PhysSpace
        ADDNE   r9,r9,#(DRAMPhysAddrB-DRAMPhysAddrA)
        BNE     %BT19                   ; this entry done .. find the next

        MOV     r8,r0                   ; report address of this block
        ADRL    r4,%BT4
        BL      ts_SendText

        LDR     r0,[r9]                 ; start testing it
        ADD     r0,r0,#PhysSpace
        LDR     r1,[r9, #4]
        STR     r0,[r9]                 ; mark block so it isn't retested
        MOV     r2,#PhysRamTable
        LDMIA   r2,{r3-r14}             ; save the PhysRamTable
        STMIA   r0,{r3-r14}
        BL      ts_RamTest
        LDMIA   r13,{r1-r11,r14}        ; restore the PhysRamTable
        MOV     r13,#PhysRamTable
        STMIA   r13,{r1-r11,r14}
        BEQ     %BT18                   ; if it passed, go look for another block

20
        FAULT   #R_MEMFAILBIT           ; failed - report fault address
        ADRL    r4,%BT2
        MOV     r11,r1                  ; Save failed data
        MOV     r8,r0                   ; first failing address
        BL      ts_SendText
        MOV     r4,r12                  ; get fault message
        MOV     r8,r11                  ; and fault data
        BL      ts_SendText
21

 [ MEMM_Type = "MEMC1"

;
; Test the CAMs - for each fitted MEMC, go through all the CAM entries
; remapping logical memory and testing against physical correspondence.
; Then try out the protection bits in each CAM entry and various
; processor modes.
; These tests return pointers to their own fault report strings.
;
        B       ts_CAMtest
        ROUT
1
        =       "CAMs :",0
2
        =       "PPLs :",0
3
        =       &89,"skipped",0
        ALIGN

ts_CAMtest
        LDR     r4,=%BT1
        BL      ts_SendText

        MOV_fiq r0,r12_fiq              ; skip this test if memory fault
        MOV     r1,#(R_LINFAILBIT :OR: R_MEMFAILBIT)
        ANDS    r0,r0,r1
        BEQ     %08
        LDR     r4,=%BT3
        BL      ts_MoreText
        B       %20

08
        BL      ts_CAM
        BEQ     %10
        BL      ts_SendText
        FAULT   #R_CAMFAILBIT
10
        LDR     r4,=%BT2
        BL      ts_SendText

        MOV_fiq r0,r12_fiq              ; skip this test if memory fault
        MOV     r1,#(R_LINFAILBIT :OR: R_MEMFAILBIT)
        ANDS    r0,r0,r1
        BEQ     %18
        LDR     r4,=%BT3
        BL      ts_MoreText
        B       %20
18
        BL      ts_memc_prot
        BEQ     %20
        BL      ts_SendText
        FAULT   #R_PROFAILBIT
20

 ]

;
; After testing memory and translation, turn MMU off again before running remainder
; of tests. This simplifies finishing up (where system must be put back into 26-bit
; mode before initialising RISCOS) if memory tests were deselected.
; Take care to poke the real translation table - it's been relocated to video
; RAM during the memory tests.
;

ts_restore_physical

  [ StrongARM_POST
    ;make sure ARM810 cache or StrongARM data cache is cleaned/flushed, because we are going to remap
        ARM_read_ID r5
        AND     r5,r5,#&F000
        CMP     r5,#&8000
        BNE     %FT22
;ARM810
;;;        ARM8_cleanflush_IDC r5  ;not implemented yet
        B       %FT24
22
        CMP     r5,#&A000
        BNE     %FT24
;StrongARM
;tricky...we'll read 16k of data in current ROM space, to act as clean and flush of current data
        MOV     r3,pc
        BIC     r3,r3,#31      ;32 byte aligned
        ARMA_clean_DC r3,r5,r7
24
  ] ;StrongARM_POST

        MOV     r5, pc                          ; obtain current address
        SUB     r5, r5,#PhysSpace               ; adjust to point to unmapped version
        MOV     r5, r5, LSR #20                 ; divide by 1MB
        MOV     r7, r5, LSL #20                 ; r7 = physical address of base of section
        ORR     r7, r7, #(AP_None * L1_APMult)
        ORR     r7, r7, #L1_Section
        MOV     r3, #VideoPhysAddr              ; find the copied translation table
        LDR     r3, [r3]
        ADD     r3, r3, #PhysSpace
        ADD     r3, r3, #DRAMOffset_L1PT
        STR     r7, [r3, r5, LSL #2]            ; store replacement entry in L1 (not U,C or B)

  [ StrongARM_POST
    ;flush cache if ARM 6/7 (ARM 8,StrongARM already sorted, above)
    ;flush TLB(s)
        ARM_read_ID r4
        AND      r4,r4,#&F000
        CMP      r4,#&8000   ;ARM 8?
        CMPNE    r4,#&A000   ;or StrongARM?
        MCRNE    ARM_config_cp,0,R0,ARM67_cacheflush_reg,C0,0   ;flush 6/7 cache
        MCRNE    ARM_config_cp,0,R0,ARM67_TLBflush_reg,C0,0     ;flush 6/7 TLB
        MCREQ    ARM_config_cp,0,R0,ARM8A_TLB_reg,C7,0          ;flush 8/StrongARM TLB(s)
  |
        SetCop  r7, CR_IDCFlush                 ; flush cache + TLB just in case
        SetCop  r7, CR_TLBFlush                 ; (data written is irrelevant)
  ]

; The ROM should now be mapped at the present address less PhysSpace, which is where it
; would be if the MMU were turned off.

        MOV     r4,#PhysSpace
        SUB     pc,pc,r4
        NOP                             ; this instruction is skipped

; now turn the MMU off, also ensures 26 bit mode, if ARM 6/7 (since P bit zero)
        MOV     r7, #MMUC_D
        SetCop  r7, CR_Control

        B       ts_VIDCtest

;
; The VIDC tests check vertical blanking frequency in a fixed video
; mode and measure the time taken for sound DMA.
;

        ROUT

1
        =       "VIDC  :",0
2
        =       "Virq bad",&88,' ',&ff,'.',&ff,&ff,&ff,&ff,&ff,0
3
        =       "Sirq bad",&8B,&ff,&ff,&ff,&ff,&ff,0
4
        =       &8A,"Mid0 ",&ff,0

        ALIGN

ts_VIDCtest
        ADR     r4,%BT1
        BL      ts_SendText
        [ IO_Type = "IOMD"
        LDR     r0,=IOMD_MonitorType    ; Indicate monitor ID bit's value
        LDR     r0,[r0]
        AND     r0,r0,#IOMD_MonitorIDMask
        MOV     r8,r0,LSL #28
        ADR     r4,%BT4
        BL      ts_MoreText
        ]

 [ MorrisSupport
        MOV     r3, #IOMD_Base
        LDRB    r1,[r3,#IOMD_ID1]	; load r1 with IOMD ID high byte
        LDRB    r0,[r3,#IOMD_ID0]	; load r1 with IOMD ID low byte
        ORR     r0,r0,r1,LSL#8		; Or r0 and r1, shifted left 8, put in r0
        LDR     r1,=ts_IOMD_ID1		; get Ref IOMD ID code #1 (Original)
        CMPS    r0,r1                   ; check for IOMD ID Code #1
	BNE	%FT10			; If not equal, got to 10
					; thus skip Virq test on ARM7500 and ARM7500FE (Morris)
 ]

        BL      ts_VIDC_period
        BEQ     %10
        ADR     r4,%B2
        MOV     r8, r0, LSL #8
        BL      ts_SendText             ; Display Virq fail msg
        FAULT   #R_VIDFAILBIT
10
        [ IO_Type = "IOMD"
  ; RCM thinks this is no longer needed - all IOMD's are issue two
  ;     besides, the test takes no account of Morris reusing the number space!
  ;      MOV     r3,#IOMD_Base           ; skip Sirq test on version 1 IOMD
  ;      LDRB    r0,[r3,#IOMD_VERSION]
  ;      CMPS    r0,#1
  ;      BEQ     %FT20
        ]
        BL      ts_SIRQ_period
        BEQ     %20
        ADR     r4,%B3
        MOV     r8, r0, LSL #12
        BL      ts_SendText             ; Display Sirq fail msg
        FAULT   #R_SNDFAILBIT
20
        MOV     r1,#ts_VIDCPhys         ; Restore full-screen
        ADRL    r2,TestVIDCTAB          ; border colour.
        [ IO_Type = "IOMD"
        LDR     r0,=IOMD_MonitorType
        LDR     r0,[r0]
        ANDS    r0,r0,#IOMD_MonitorIDMask
        ADDEQ   r2,r2,#(TestVVIDCTAB-TestVIDCTAB)
        ]
30      LDR     r0, [r2],#4
        CMP     r0, #-1
        STRNE   r0, [r1]
        BNE     %BT30

	[ STB :LAND: DontShowProgressColours
        MOV_fiq r0,r12_fiq              	; restore the faultcode bits
        ANDS    r0,r0,#(R_EXTERN :OR: R_TESTED)	; If test adapter present,
			                   	; NE : Adaptor fitted, show progress.
 	           				; EQ : No Adaptor fitted, don't show progress
	BEQ	ts_ARMtype_test			; EQ : Don't show colours
	]
        LDR     r0,=C_ARMOK             ; set initial screen colour
        STR     r0, [r1]

        B       ts_ARMtype_test

;
; Read the ARM3 identification register.
; If memory tests failed, this won't be performed since the vector
; page must exist for error recovery on ARM2 systems.
;

        ROUT
1
        =       "ARM ID:",0
2
        =       "ARM ID",&88,&ff,&ff,&ff,&ff,&ff,&ff,&ff,&ff,0
3
        =       &89,"skipped",0

        ALIGN

ts_ARMtype_test

        ADR     r4,%BT1
        BL      ts_SendText

        MOV_fiq r0,r12_fiq              ; skip this test if memory fault
        LDR     r1,=((R_LINFAILBIT :OR: R_MEMFAILBIT) :OR: (R_CAMFAILBIT :OR: R_PROFAILBIT))
        ANDS    r0,r0,r1
        BEQ     %05
        ADR     r4,%BT3
        BL      ts_MoreText
        B       %08                     ; and quit

05
        BL      ts_ARM_type
        MOVS    r8, r0                  ; ready to display ID code
        ADR     r4,%BT2

        BEQ     %FT07                   ; ARM 2 : skip cache test
        FAULT   #R_ARM3                 ; not really a fault, just status
07
        BL      ts_SendText

08
        B       ts_Report



;
; Report the test results to the user
;
; If this was a forced test (test adapter fitted) then pause even when
; test passed : otherwise, pause only on error.
;

ts_passmsg
        =       "PASS  :",&88,&ff,&ff,&ff,&ff,&ff,&ff,&ff,&ff,0
ts_failmsg
        =       "FAIL  :",&88,&ff,&ff,&ff,&ff,&ff,&ff,&ff,&ff,0

ts_R00  &       00


 [ STB :LAND: POSTFlashesFrontPanelLEDs
        ; Define Long, Equal and short flash delays
ts_Long_Flash      	*	&03		; Number of 1/4 Sec delays for a long flash
ts_Short_Flash	   	*	&01		; Number of 1/4 Sec delays for a short flash
ts_Equal_Flash     	*	&02		; Number of 1/4 Sec delays for a equal flash
ts_Fail_Flash_Delay	*	&14		; Number of Flash Cycles for a Fail, with adaptor
ts_Pass_Flash_Delay	*	&0A		; Number of Flash Cycles for a Pass, with adaptor

IOMD_LED_GREENLED       *       IOMD_C_FrontPanelRightLED               ; The right LED should be the GREEN LED
IOMD_LED_REDLED         *       IOMD_C_FrontPanelLeftLED                ; The left  LED should be the RED   LED
IOMD_LED_BOTH           *       IOMD_LED_REDLED :OR: IOMD_LED_GREENLED  ;

 ] ; Endif (POSTFlashesFrontPanelLEDs)

ts_Report       ROUT
        MOV_fiq r7,r12_fiq              ; check for fault bits set
        LDR     r0,=R_STATUS
        BICS    r0,r7,r0

        ADREQ   r4, ts_passmsg          ; tests passed
        LDREQ   r9,=C_PASSED

        ADRNE   r4, ts_failmsg          ; tests failed
        LDRNE   r9,=C_FAULT

        LDR     r0,=ts_VIDCPhys         ; write the border colour
        STR     r9,[r0]

        MOV     r8,r7
        BL      ts_SendText             ; write the message and fault code

        ; if the test adapter is present, leave green screen awhile
        ; otherwise, wait only if there's a fault.

        LDR     r3,=ts_recover_time
00      ADDS    r3,r3,r3                ; 16-loop delay
        BCC     %B00                    ; - let the adapter recover
                                        ; from previous bus activity
        ADR     r2,ts_R00
        ORR     r2,r2,#ts_Alias_bits
        LDR     r3,[r2]
        MOV     r2,#-1
        ADDS    r3,r3,r2
        BCS     ts_Report_wait

	; Here is r3 = 0, which ment a DUMP adaptor was present.
	;
	; Continue to the OS
	;
        MOV_fiq r0,r12_fiq
        LDR     r2,=R_STATUS
        BICS    r0,r0,r2
        BEQ     ts_Hardstart

ts_Report_wait        ROUT
	;
	; Here if a Display or other type of adaptor found.
	;
 [ STB :LAND: POSTFlashesFrontPanelLEDs
	;
	; Check to see if we are a PASS or FAIL
	;
        MOV_fiq r7,r12_fiq              	; check for fault bits set
        LDR     r0,=R_STATUS
        BICS    r0,r7,r0

	BEQ	ts_flash_leds_pass		; flash the leds to show a pass
						; flash the leds to show a failure
						; Fall through !

ts_flash_leds_fail
	;
	; Get here if the POST fails !
	;
        ; Set it so the RED LED is on.
        BL      ts_led_redon_only               ; Ensure that the RED LED only is on,
	; Check for display adpator, if fitted, flash LED's for 20 times
	; else flash LEDs forever.
	;
        MOV_fiq r0,r12_fiq              	; restore the faultcode bits
        ANDS    r0,r0,#(R_EXTERN :OR: R_TESTED)	; If test adapter present,
        BNE	%FT19	                   	; Adaptor    : Goto 20 Flash loops Code
 	           				; No Adaptor : Goto Infinite flash loop Code
						; Fall through !
14
	; Infinite Flash loop
	; Register usage ....
	; 	r0, used by toggle leds & delay routines
	;	r1, used by toggle leds routine
	;
15	BL	ts_led_fail			; Call code to flash the leds
	B	%BT15				; Repeat forever.

19
	; Loop for specified time
	; Register usage ....
	; 	r0, used by toggle leds & delay routines
	;	r1, used by toggle leds routine
	;
	;	r3, Loop counter
	;       r4, Pass delay time to delay code.
	;
	MOV	r3,#ts_Fail_Flash_Delay		; Set the loop counter.
20	BL	ts_led_fail			; Call code to flash the leds
	SUBS	r3,r3,#1			; Decrment loop counter
	BNE	%BT20				; Repeat until r3 = 0
	BEQ	%FT50				; r3=0, were all done
						; Goto start the OS

ts_flash_leds_pass
	; Here if POST passed.
	; If adaptor fitted, flash the LEDs for a 10 secs
        MOV_fiq r0,r12_fiq              	; restore the faultcode bits
        ANDS    r0,r0,#(R_EXTERN :OR: R_TESTED)	; If test adapter present,
	BEQ	%FT55				; No Adaptor : Goto start the OS
                                       		; Adaptor    : Goto 10 Flash loops Code
						; Fall through !

        ; Set it so the RED LED is on.
        BL      ts_led_redon_only               ; Ensure that the RED LED only is on,
	; Loop for specified time
	; Register usage ....
	; 	r0, used by toggle leds & delay routines
	;	r1, used by toggle leds routine
	;
	;	r3, Loop counter
	;       r4, Pass delay time to delay code.
	;
	MOV	r3,#ts_Pass_Flash_Delay		; Set the loop counter.
30	BL	ts_led_pass			; Call code to flash the leds
	SUBS	r3,r3,#1			; Decrment loop counter
	BNE	%BT30				; Repeat until r3 = 0
	BEQ	%FT50				; r3=0, were all done
						; Goto start the OS

ts_led_fail
	; Code to flash the LED's through one flash cycle (on-off)
	; This will take 1 Second to complete.
	;
	;|------>|--1/4 Sec--|--1/4 Sec--|--1/4 Sec--|--1/4 Sec--|
	;|--Red--|---Green---|----Red----|----Red----|----Red----|\�
	;         \_______________________________________________/
	;
	;									Red	Green
	MOV	r13,r14				; make a note of where we	On	Off
						; came from.
	BL	tl_Toggle_LEDs			; Toggle the LEDs		Off	On
	MOV	r4,#ts_Short_Flash		; Load r4 with Short flash	Off	On
	BL	ld_LED_Delay			; call delay routine		Off	On
	BL	tl_Toggle_LEDs			; Toggle the LEDs		On	Off
	MOV	r4,#ts_Long_Flash		; load r4 with long flash	On	Off
	BL	ld_LED_Delay			; call delay routine		On	Off

	MOV	pc,r13                          ; move r13 (r14) back to
						; where we came from.

ts_led_pass
	; Code to flash the LED's through one flash cycle (on-off)
	; This will take 1 Second to complete.
	;
	;|------>|--1/4 Sec--|--1/4 Sec--|--1/4 Sec--|--1/4 Sec--|
	;|--Red--|---Green---|---Green---|---Green---|----RED----|\�
	;         \_______________________________________________/
	;
	;									Red	Green
	MOV	r13,r14				; make a note of where we	On	Off
						; came from.
	BL	tl_Toggle_LEDs			; Toggle the LEDs		Off	On
	MOV	r4,#ts_Long_Flash		; Load r4 with long flash	Off	On
	BL	ld_LED_Delay			; call delay routine		Off	On
	BL	tl_Toggle_LEDs			; Toggle the LEDs		On	Off
	MOV	r4,#ts_Short_Flash		; load r4 with short flash	On	Off
	BL	ld_LED_Delay			; call delay routine		On	Off

	MOV	pc,r13                          ; move r13 (r14) back to
						; where we came from.

ts_led_redon_only
	LDR	r1, =IOMD_IOLINES               ; r1 = addr of IOMD_IOLINES
        LDRB    r0,[r1]                         ; load r0 with the byte pointed to by r1
;        DREG    r0,"contents of loc->r1"
        BIC     r0,r0,#IOMD_LED_GREENLED        ; Clear GREEN LED bit
        ORR     r0,r0,#IOMD_LED_REDLED          ; Set   RED LED bit
        ORR     r0,r0,#IOMD_C_ReadMask          ; OR with the default I/O settings
        STRB    r0,[r1]                         ; store a byte of r0 in to loc pointed to by r1
        MOV     pc, r14                         ; Return to caller

ts_led_greenon_only
	LDR	r1, =IOMD_IOLINES               ; r1 = addr of IOMD_IOLINES
        LDRB    r0,[r1]                         ; load r0 with the byte pointed to by r1
;        DREG    r0,"contents of loc->r1"
        BIC     r0,r0,#IOMD_LED_REDLED          ; clear RED LED bit
        ORR     r0,r0,#IOMD_LED_GREENLED        ; Set   GREEN LED bit
        ORR     r0,r0,#IOMD_C_ReadMask          ; OR with the default I/O settings
        STRB    r0,[r1]                         ; store a byte of r0 in to loc pointed to by r1
        MOV     pc, r14                         ; Return to caller

ts_led_bothon
	LDR	r1, =IOMD_IOLINES               ; r1 = addr of IOMD_IOLINES
        LDRB    r0,[r1]                         ; load r0 with the byte pointed to by r1
;        DREG    r0,"contents of loc->r1"
        ORR     r0,r0,#IOMD_LED_BOTH            ; Set Both Green & RED LED bits
        ORR     r0,r0,#IOMD_C_ReadMask          ; OR with the default I/O settings
        STRB    r0,[r1]                         ; store a byte of r0 in to loc pointed to by r1
        MOV     pc, r14                         ; Return to caller

ts_led_bothoff
	LDR	r1, =IOMD_IOLINES               ; r1 = addr of IOMD_IOLINES
        LDRB    r0,[r1]                         ; load r0 with the byte pointed to by r1
;        DREG    r0,"contents of loc->r1"
        BIC     r0,r0,#IOMD_LED_BOTH            ; Clear Both Green & RED LED bits
        ORR     r0,r0,#IOMD_C_ReadMask          ; OR with the default I/O settings
        STRB    r0,[r1]                         ; store a byte of r0 in to loc pointed to by r1
        MOV     pc, r14                         ; Return to caller



50
        ; come here if we've finished showing pass/fail by flashing the LEDs
        ; thus a test link or display aaptor was fitted
        ; so turn on the LED's
        BL      ts_led_bothon

55
        ; come here because we passed, but no display adaptor ot test link, thus LEDs weren't flashed
	; so ........
	; Continue on our way
	;
 | ; else
	;
	; :LNOT: POSTFlashesFrontPanelLEDs
        ; Thus we use the old way of flashing the LED etc ....
	;
	; Indicate fault found : Set the border to fault colour and flash
	; the disk LED, using the fault bitmap in r12_fiq to modulate the flashing.
	;

ts_oldLED_on       *       &be0000         ; assert SEL0 and INUSE
ts_oldLED_off      *       &ff0000         ; on machines with 1772 controller
ts_oldLEDaddr      *       (ts_S5_base :OR: &40)

ts_710LED_on       *       &100000         ; assert SEL0 and MotorEN0
ts_710LED_off      *       &110000         ; on machines with 82C710 controller
ts_710LEDaddr      *       (ts_PCaddress :OR: (&3f2 :SHL: 2))

ts_665LED_on       *       &10          ; assert SEL0 and MotorEN0
ts_665LED_off      *       &11          ; on machines with 37665 controller
                                        ; and Medusa low-byte I/O world
ts_665LEDaddr      *       (ts_PCaddress :OR: (&3f2 :SHL: 2))

01
        MOV_fiq r6,r12_fiq
        LDR     r2,=&11111111
        [ :LNOT: STB
        LDR     r7,=(35000 * 8)         ; 1/4 second pause loop count
        ]

   [ IO_Type = "IOMD"
        LDRNE   r1,=ts_665LEDaddr       ; set up for Medusa disc address
        MOVNE   r8,#ts_665LED_on
        MOVNE   r9,#ts_665LED_off
   |
        TST     r6, #R_IOEB             ; determine original / 710 disc controller
        LDREQ   r1,=ts_oldLEDaddr       ; set up for Archimedes disc address
        MOVEQ   r8,#ts_oldLED_on
        MOVEQ   r9,#ts_oldLED_off
        LDRNE   r1,=ts_710LEDaddr       ; set up for Brisbane disc address
        MOVNE   r8,#ts_710LED_on
        MOVNE   r9,#ts_710LED_off
   ]

02
	[ STB
	BL	ld_LED_Delay			; call delay routine

        MOV     r0,r8                   ; turn the LED on
        STR     r0,[r1]

	BL	ld_LED_Delay			; call delay routine

        ADDS    r6,r6,r6                ; if a '1' is to be written,
        BCC     %06
	BL	ld_LED_Delay			; call delay routine }
	BL	ld_LED_Delay			; call delay routine } Half A Second
	|
        MOV     r0,r7
03      SUBS    r0,r0,#1                ; pause for a 1/4 second
        BNE     %03

        MOV     r0,r8                   ; turn the LED on
        STR     r0,[r1]

        MOV     r0,r7
04      SUBS    r0,r0,#1                ; pause for a 1/4 second
        BNE     %04
        ADDS    r6,r6,r6                ; if a '1' is to be written,
        BCC     %06
        MOV     r0,r7,LSL #1            ; then pause another 1/2 second
05      SUBS    r0,r0,#1
        BNE     %05
	]
06
        MOV     r0, r9                  ; turn the LED off
        STR     r0,[r1]

;
; Count down 32 bits. Every 4 bits, insert an extra pause to simplify
; reading the flashes.
;
        ADDS    r2,r2,r2
        BCC     %08
 [ STB
	BL	ld_LED_Delay			; call delay routine }
	BL	ld_LED_Delay			; call delay routine } One Seconds Worth
	BL	ld_LED_Delay			; call delay routine }
	BL	ld_LED_Delay			; call delay routine }
 |
        MOV     r0,r7,LSL #2            ; then pause another second
05      SUBS    r0,r0,#1
        BNE     %05
 ]
08
        ANDS    r2,r2,r2                ; all the bits displayed now ?
        BNE     %02
        MOV_fiq r0,r12_fiq              ; restore the faultcode bits
 ] ; Endif (POSTFlashesFrontPanelLEDs)
;
        MOV_fiq r0,r12_fiq              	; restore the faultcode bits
; Uncomment the following line if the POST code is to loop when the POST
; display adaptor (post box) is fitted.
;
;        ANDS    r0,r0,#(R_EXTERN :OR: R_TESTED) ; If the display adapter & test link are present,
;
; Comment this line out if POST Code is to loop when the POST display
; adaptor (post box) is fitted.
;
        ANDS    r0,r0,# R_TESTED	; If the test link is present,
        BNE     Reset                   ; repeat the test forever

        B       CONT                    ; otherwise, run RISC OS

ts_Hardstart
        MOVS    r0,#R_HARD              ; and report a hard start
        B       CONT                    ; to RISC OS

;
; Tests skipped : fall into RISC-OS
;

ts_Self_test_end

	[ STB :LAND: DontShowProgressColours
        MOV_fiq r0,r12_fiq              	; restore the faultcode bits
        ANDS    r0,r0,#(R_EXTERN :OR: R_TESTED)	; If test adapter present,
			                   	; NE : Adaptor fitted, show progress.
 	           				; EQ : No Adaptor fitted, don't show progress
	BEQ	ts_Softstart			; EQ : Don't show colours
	]
        LDR     r1,=C_DEFAULT
        LDR     r0,=ts_VIDCPhys         ; write the border colour
        STR     r1,[r0]

ts_Softstart
        MOVS    r0,#R_SOFT              ; soft reset indicator
        B       CONT

;
;
;
        ROUT
;
; This table consists of a series of address/data pairs for IO
; initialization.
; Note that these addresses are likely to be in the IO world,
; and hence the data written is that from the MOST significant
; 16 bits of the data bus.
; An 'address' of -1 terminates the table.
;

ts_IOinitab
        [ IO_Type = "IOMD"
        |
        & ts_S5_base :OR: &10,  &000000         ; Printer port data
        & ts_S5_base :OR: &18,  &000000         ; FDC control & printer strobes
        & ts_S5_base :OR: &40,  &ff0000         ; FDD select lines
        & ts_S5_base :OR: &48,  &000000         ; VIDC clock control
        ]
        & (-1)


;
;
;---------------------------------------------------------------------------

        LTORG


; Include test modules executed by call, rather than inline

        GET     TestSrc.Mem2
        GET     TestSrc.Mem3
        GET     TestSrc.Mem4
        GET     TestSrc.Mem5
        GET     TestSrc.Vidc
        GET     TestSrc.Ioc
        GET     TestSrc.Cmos
        GET     TestSrc.Arm3

        ; amg: 7/12/96 Renaissance. Once again I wish AASM could understand conditionals
        ;              around GETs

        GBLS    get_toggleled
        GBLS    get_leddelay
        GBLS    get_showiomdrs
        [ STB
get_toggleled   SETS "GET TestSrc.ToggleLED"
get_leddelay    SETS "GET TestSrc.LEDDelay"
get_showiomdrs  SETS "GET TestSrc.ShowIOMDRs"
        |
get_toggleled   SETS ""
get_leddelay    SETS ""
get_showiomdrs  SETS ""
	]
	$get_toggleled
	$get_leddelay
	$get_showiomdrs

	ALIGN	64		; JRH: Kernel seems happier if we do this!

        END