; > TestSrc.Mem1IOMD TTL RISC OS 2+ POST memory linetest ; ; This test code is used to perform basic integrity tests on DRAM. ; It doesn't test all locations - just walks patterns through data ; and address lines. ; ;------------------------------------------------------------------------ ; History ; ; Date Name Comment ; ---- ---- ------- ; 1-Jun-93 ArtG Derived from Mem1 for use on Medusa ; ; ;------------------------------------------------------------------------ ; ; Test the data and address and byte strobe lines for uniqueness. ; LTORG ROUT 1 = "VRAM :",0 2 = "VRAM-F",&88,&ff,&ff,&ff,&ff,&ff,&ff,&ff,&ff,0 3 = "DRAM ",&ff,":",0 4 = "Data :",0 5 = &88,&ff,&ff," MByte",0 ALIGN ts_LineTest ADR r4,%BT1 BL ts_SendText ; Start data line tests on VRAM MOV r0,#0 MOV_fiq r9,r0 ; r9-fiq records VRAM or low DRAM address MOV r12, #IOMD_Base MOV r2, #IOMD_VREFCR_VRAM_256Kx64 :OR: IOMD_VREFCR_REF_16 ; assume 2 banks of VRAM by default STRB r2, [r12, #IOMD_VREFCR] ; Find the size, using MemSize's method MOV r0, #VideoPhysRam ; point at VRAM ADD r1, r0, #A2 ; test A2 BL DistinctAddresses MOVEQ r9, #2 ; we've got 2M of VRAM BEQ %FT21 MOV r2, #IOMD_VREFCR_VRAM_256Kx32 :OR: IOMD_VREFCR_REF_16 STRB r2, [r12, #IOMD_VREFCR] ADD r1, r0, #A2 ; check for any VRAM at all BL DistinctAddresses MOVEQ r9, #1 ; we've got 1M of VRAM MOVNE r9, #0 ; no VRAM 21 BNE %FT22 MOV_fiq r9,r0 ; record VRAM address FAULT #R_VRAM ; indicate VRAM present ; Report size .. if this is non-zero and the data line test fails, ; RISC OS will have problems. 22 ADR r4,%BT5 ; Add size (in hex Mbyte) MOV r8,r9, LSL #24 ; to "VRam : " message BL ts_MoreText ; Worked out what size VRAM is, and set up IOMD register. ; Do a data line test on the resulting array, repeated at oddword address to ; ensure both banks get tested with walking 0 and walking 1 ADR r4,%BT4 BL ts_SendText MOV r1, #VideoPhysRam BL ts_Dataline ADDEQ r1,r1,#4 BLEQ ts_Dataline BEQ %FT25 ; looks OK - carry on with VRAM test ; ; Data line test failed. Report the bitmap that failed, then carry on. ; ADR r4,%BT2 MOV r8,r0 ; report data fault mask BL ts_SendText B %FT30 ; ; If there was some VRAM found here, and it passed the dataline test, ; do the address and bytestrobe tests on it too. ; 25 ADRL r4,%FT75 ; announce start of address line test BL ts_SendText MOV r1,#VideoPhysRam MOV r0,r9,LSL #20 ; size in MB determined before dataline test BL ts_Addrline BEQ %FT26 ADRL r4,%FT76 ; failed - report error mask MOV r8,r0 BL ts_SendText FAULT #R_LINFAILBIT ; and record failure B %FT30 26 ADRL r4,%FT77 ; announce start of byte test BL ts_SendText MOV r1,#VideoPhysRam BL ts_Byteword ADDEQ r1,r1,#4 ; retest at an oddword boundary BLEQ ts_Byteword BEQ %FT27 ADRL r4,%FT78 ; failed - report error mask MOV r8,r0,LSL #16 BL ts_SendText FAULT #R_LINFAILBIT ; and record failure 27 ; Similarly, test each DRAM bank in turn, reporting failures or sizes for each 30 MOV r11, #IOMD_DRAMCR_DRAM_Large * &55 ; set all banks to be large initially MOV r14, #IOMD_Base STRB r11, [r14, #IOMD_DRAMCR] MOV r0,#MMUC_D ; enable 32-bit addressing of data SetCop r0,CR_Control MOV r10, #0 ; indicate no RAM found yet MOV r9, #IOMD_DRAMCR_DRAM_Small ; bit to OR into DRAMCR MOV r12, #DRAM0PhysRam 35 MOV r8,r12,LSL #2 ; indicate bank under test AND r8,r8,#(3 :SHL: 28) ADR r4,%BT3 BL ts_SendText MOV r8,#0 ; r8 indicates RAM found in this bank MOV r0, r12 ADD r1, r12, #A10 ; this should be OK for both configurations BL DistinctAddresses BNE %FT50 ; [no RAM in this bank at all] MOV_fiq r2,r9 ; if this is the first bank of DRAM or VRAM, TEQS r2,#0 ; put it's address in r9_fiq BNE %FT36 MOV_fiq r9,r0 36 ADD r1, r12, #A11 ; test for 256K DRAM BL DistinctAddresses ORRNE r11, r11, r9 ; it is, so select small multiplexing MOVNE r14, #IOMD_Base STRNEB r11, [r14, #IOMD_DRAMCR] ; store new value of DRAMCR, so we can use memory immediately MOVNE r8, #1024*1024 ; must be 1Mbyte at this address BNE %FT50 ; it's bigger than 256K words, so test address lines A21-A25 in sequence ; we assume that the size of each bank is a power of 2 MOV r8, #A21 ; now go through address lines A21-A25 40 ADD r1, r12, r8 ; see if this address line is unique BL DistinctAddresses BNE %FT50 ; if we've failed then r8 is true size, so exit MOV r8, r8, LSL #1 ; else shift up to next TEQ r8, #A26 ; only test up to A25 BNE %BT40 50 MOV r13,r8 ; remember size of this bank in bytes MOV r8,r13,LSL #(24 - 20) ; and display it in 2 digits, in MBytes. ADR r4,%BT5 BL ts_MoreText ADRL r4,%FT73 ; announce data line test BL ts_SendText MOV r1,r12 ; do walking bit test BL ts_Dataline BEQ %FT55 ; looks OK, carry on to next bank ADRL r4,%FT74 ; bit test failed, so report it MOV r8,r0 BL ts_SendText ; and bit fault mask CMPS r13,#0 ; was any RAM thought to be here ? BEQ %FT55 FAULT #R_LINFAILBIT ; if so, it's faulty. MOV r13,#0 ; so ignore it 55 ; ; If there was some RAM found here, and it passed the dataline test, ; do the address and bytestrobe tests on it too. ; CMPS r13,#0 BEQ %FT60 ADR r4,%FT75 ; announce start of address line test BL ts_SendText MOV r1,r12 ; test address lines in this block MOV r0,r13 BL ts_Addrline BEQ %FT56 ADR r4,%FT76 ; failed - report error mask MOV r8,r0 BL ts_SendText FAULT #R_LINFAILBIT ; and record failure MOV r13,#0 ; then forget this memory block 56 ADR r4,%FT77 ; announce start of byte test BL ts_SendText MOV r1,r12 BL ts_Byteword BEQ %FT60 ADR r4,%FT78 ; failed - report error mask MOV r8,r0,LSL #16 BL ts_SendText FAULT #R_LINFAILBIT ; and record failure MOV r13,#0 ; then forget this memory block 60 ; If the RAM found still seems OK, add it's size into the r10 accumulator ; Working or not, carry on to check the next bank. ADD r10,r10,r13 ; accumulate DRAM if any found ADD r12, r12, #DRAM1PhysRam-DRAM0PhysRam ; move onto next bank MOV r9, r9, LSL #2 ; shunt up position in DRAMCR CMP r9, #&100 ; if more banks to do BCC %BT35 ; then loop ADR r4,%FT70 BL ts_SendText ; None found .. print message MOVS r8,r10,LSL #(24 - 20) ; all finished .. ADREQ r4,%FT71 ; did we find any DRAM? ADRNE r4,%FT72 BNE %FT65 FAULT #R_LINFAILBIT ; fault if we didn't 65 BL ts_MoreText B ts_endline 70 = "DRAM",0 71 = &88,"Failed",0 72 = &88,&ff,&ff," MByte",0 73 = "Data :",0 74 = "Data-F",&88,&ff,&ff,&ff,&ff,&ff,&ff,&ff,&ff,0 75 = "Addrs :",0 76 = "Addrs-F",&88,&ff,&ff,&ff,&ff,&ff,&ff,&ff,&ff,0 77 = "Byte :",0 78 = "Byte-F",&88,&ff,&ff,&ff,&ff,0 ; ; Data line test. ; ; In : r1 - start address for test ; ; Out : r0 - failing data pattern ; r1 - address of failure ; ; ; This exercises data lines in attempt to find shorts/opens. ; It goes something like : ; ; for (ptr = address, pattern = 1; pattern != 0; pattern <<= 1) ; *ptr++ = pattern; ; *ptr++ = ~pattern; ; for (ptr = address, pattern = 1; pattern != 0; pattern <<= 1) ; result |= pattern ^ *ptr++; ; result |= ~pattern ^ *ptr++; ; return result and address ; ts_Dataline ROUT ; ; Write all walking-zero, walking-one patterns ; 10 MOV r6,r1 ; set pointer for a write loop MOV r5,#1 ; set initial test pattern MVN r4,r5 ; and it's inverse 11 STMIA r6!,{r4-r5} ; write the patterns ADDS r5,r5,r5 ; shift the pattern (into Carry) MVN r4,r5 BCC %BT11 ; repeat until all bits done ; ; Read back and accumulate in r0 any incorrect bits ; MOV r6,r1 ; set pointer for a read loop MOV r5,#1 ; set initial test pattern MVN r4,r5 ; and it's inverse MOV r0,#0 ; accumulate result 21 LDMIA r6!,{r2-r3} ; read the patterns EOR r2,r2,r4 ORR r0,r0,r2 ; OR any failed bits into r0 EOR r3,r3,r5 ORR r0,r0,r2 ADDS r5,r5,r5 ; shift the pattern (into Carry) MVN r4,r5 BCC %BT21 ; repeat until all bits done ; ; After all checks at this address group, report back errors ; MOVS r0,r0 ; check for any result bits set MOV pc,r14 ; return r0 with error map (or 0) ; ; Address line test ; ; In : r0 - size of memory block ; r1 - start address of memory block ; ; Out : r0 - failing address bit mask ; ; This exercises address lines in an attempt to find any which don't ; work (i.e., don't select unique addresses). ; ; It works something like : ; ; MaxRam = PhysRam | (Memory size - 4); ; for (pattern = 4; pattern < memsize; pattern <<= 1 ) ; *(PhysRam ^ pattern) = pattern; ; *(MaxRam ^ pattern) = ~pattern; ; for (pattern = 4; pattern < memsize; pattern <<= 1 ) ; if (*PhysRam == *(PhysRam ^ pattern)) ; result |= pattern; ; if (*MaxRam == *(MaxRam + pattern)) ; result |= pattern; ; return result ; ts_Addrline ROUT MOVS r7,r0 ; Save memory size SUB r6,r0,#4 ; Calculate MaxRam ADD r6,r6,r1 ; (all-bits-set memory address) ; ; Mark (walking one, walking 0) addresses with unique patterns ; LDR r5,=&5A5AA5A5 ; initialize end markers STR r5,[r6] MVN r4,r5 MOV r3,r1 STR r4,[r3] MOV r5,#4 ; initialize pattern 02 MVN r4,r5 EOR r3,r5,r1 ; point to (start ^ pattern) STR r4,[r3] EOR r3,r5,r6 ; point to (end ^ pattern) STR r5,[r3] MOV r5,r5,LSL #1 ; shift test pattern up CMPS r5,r7 ; test bit still inside memory ? BCC %02 ; reached top bit - end this loop ; ; Check (walking one, walking 0) addresses for effectivity ; MOV r5,#4 ; initialize pattern MOV r3,r1 MOV r0,#0 04 MVN r4,r5 EOR r2,r5,r3 ; point to (start ^ pattern) LDR r2,[r2] LDR r1,[r3] CMPS r1,r2 ; do contents differ ? ORREQ r0,r0,r5 ; no - record ineffective bit EOR r2,r5,r6 ; point to (end ^ pattern) LDR r2,[r2] LDR r1,[r6] CMPS r1,r2 ; do contents differ ? ORREQ r0,r0,r5 ; no - record ineffective bit MOV r5,r5,LSL #1 ; shift test pattern up CMPS r5,r7 ; test bit still inside memory ? BCC %04 ; reached top bit - end this loop MOVS r0,r0 ; any result bits set - return error MOV pc,r14 ; ; Byte / word test ; ; In : r1 - memory start ; ; Out : r0 - Failure indication ; ; This test ensures that individual bytes may be written to each part of a word ; without affecting the other bytes in the word. ; ; for (byte = 0; byte < 4; byte ++) ; address[0] = word_signature ; address[1] = ~word_signature ; address + byte = byte_signature ; if (address[0] != ; (word_signature & (~ff << byte * 8)) ; | (byte_signature << byte * 8) ) ; result |= (1 << byte) ; if (result != 0 ; result |= address; /* fail at address, byte(s) */ ; return result; /* pass */ ; ts_Byteword ROUT LDR r3,=&AABBCCDD ; word signature MOV r0,#0 MOV r2,r0 ; ; byte test loop ( for bytes 0 to 4 ...) ; 02 MVN r4,r3 STMIA r1,{r3,r4} ; write word signature STRB r2,[r1,r2] ; write byte (0, 1, 2 or 3) MOV r4,r2,LSL #3 ; calculate expected result MOV r5,#&ff MVN r5,r5,LSL r4 AND r5,r5,r3 ; word signature, byte removed ORR r5,r5,r2,LSL r4 ; byte signature inserted LDR r4,[r1,#4] ; read (probable) inverse data to precharge bus LDR r4,[r1] ; read modified word CMPS r4,r5 MOV r5,#1 MOV r4,r2,LSL #2 ORRNE r0,r0,r5,LSL r4 ; fault : set bit in result mask ; ; Loop for next byte ; ADD r2,r2,#1 ; Bump byte counter CMPS r2,#4 ; ... until 4 byte strobes tested BLO %BT02 ; ; byte strobes all tested : check for errors ; CMPS r0,#0 MOV pc,r14 ; Result : return address and fault mask. ; ; End of RAM line tests ; ts_endline END